mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
avrpins with mega1280/2560 support
This commit is contained in:
parent
e238472454
commit
600e5c3a07
10 changed files with 2013 additions and 368 deletions
683
Usb.cpp
683
Usb.cpp
|
@ -5,33 +5,38 @@
|
|||
#include "usbhost.h"
|
||||
#include "Usb.h"
|
||||
#include "WProgram.h"
|
||||
//#include <ptpdebug.h>
|
||||
|
||||
static uint8_t usb_error = 0;
|
||||
static uint8_t usb_task_state;
|
||||
DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
|
||||
EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
||||
//DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
|
||||
//EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
||||
|
||||
|
||||
/* constructor */
|
||||
|
||||
USB::USB ()
|
||||
USB::USB ()
|
||||
{
|
||||
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/* Initialize data structures */
|
||||
void USB::init()
|
||||
{
|
||||
uint8_t i;
|
||||
for( i = 0; i < ( USB_NUMDEVICES + 1 ); i++ ) {
|
||||
devtable[ i ].epinfo = NULL; //clear device table
|
||||
devtable[ i ].devclass = 0;
|
||||
}
|
||||
devtable[ 0 ].epinfo = &dev0ep; //set single ep for uninitialized device
|
||||
// not necessary dev0ep.MaxPktSize = 8; //minimum possible
|
||||
dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||
dev0ep.rcvToggle = bmRCVTOG0;
|
||||
devConfigIndex = 0;
|
||||
|
||||
//UsbDevice *p = addrPool.GetUsbDevicePtr(0);
|
||||
|
||||
//if (p)
|
||||
//{
|
||||
// p->epinfo = &dev0ep;
|
||||
// dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||
// dev0ep.rcvToggle = bmRCVTOG0;
|
||||
//}
|
||||
}
|
||||
|
||||
uint8_t USB::getUsbTaskState( void )
|
||||
{
|
||||
return( usb_task_state );
|
||||
|
@ -42,17 +47,30 @@ void USB::setUsbTaskState( uint8_t state )
|
|||
}
|
||||
EP_RECORD* USB::getDevTableEntry( uint8_t addr, uint8_t ep )
|
||||
{
|
||||
EP_RECORD* ptr;
|
||||
ptr = devtable[ addr ].epinfo;
|
||||
ptr += ep;
|
||||
return( ptr );
|
||||
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||
|
||||
if (p)
|
||||
return (p->epinfo + ep);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* set device table entry */
|
||||
/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
|
||||
void USB::setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr )
|
||||
uint8_t USB::setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr )
|
||||
{
|
||||
devtable[ addr ].epinfo = eprecord_ptr;
|
||||
//return();
|
||||
if (!eprecord_ptr)
|
||||
return USB_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||
|
||||
if (!p)
|
||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||
|
||||
p->address = addr;
|
||||
p->devclass = 0;
|
||||
p->epinfo = eprecord_ptr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */
|
||||
/* depending on request. Actual requests are defined as inlines */
|
||||
|
@ -61,14 +79,15 @@ void USB::setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr )
|
|||
/* 01-0f = non-zero HRSLT */
|
||||
uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, unsigned int wInd, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit )
|
||||
{
|
||||
boolean direction = false; //request direction, IN or OUT
|
||||
uint8_t rcode;
|
||||
SETUP_PKT setup_pkt;
|
||||
boolean direction = false; //request direction, IN or OUT
|
||||
uint8_t rcode;
|
||||
SETUP_PKT setup_pkt;
|
||||
|
||||
regWr( rPERADDR, addr ); //set peripheral address
|
||||
if( bmReqType & 0x80 ) {
|
||||
direction = true; //determine request direction
|
||||
}
|
||||
regWr( rPERADDR, addr ); //set peripheral address
|
||||
|
||||
if( bmReqType & 0x80 )
|
||||
direction = true; //determine request direction
|
||||
|
||||
/* fill in setup packet */
|
||||
setup_pkt.ReqType_u.bmRequestType = bmReqType;
|
||||
setup_pkt.bRequest = bRequest;
|
||||
|
@ -100,7 +119,7 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ
|
|||
/* Assumed peripheral address is already set */
|
||||
uint8_t USB::ctrlStatus( uint8_t ep, boolean direction, unsigned int nak_limit )
|
||||
{
|
||||
uint8_t rcode;
|
||||
uint8_t rcode;
|
||||
if( direction ) { //GET
|
||||
rcode = dispatchPkt( tokOUTHS, ep, nak_limit );
|
||||
}
|
||||
|
@ -112,17 +131,34 @@ uint8_t USB::ctrlStatus( uint8_t ep, boolean direction, unsigned int nak_limit )
|
|||
/* Control transfer with data stage. Stages 2 and 3 of control transfer. Assumes preipheral address is set and setup packet has been sent */
|
||||
uint8_t USB::ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction, unsigned int nak_limit )
|
||||
{
|
||||
uint8_t rcode;
|
||||
if( direction ) { //IN transfer
|
||||
devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
|
||||
rcode = inTransfer( addr, ep, nbytes, dataptr, nak_limit );
|
||||
return( rcode );
|
||||
}
|
||||
else { //OUT transfer
|
||||
devtable[ addr ].epinfo[ ep ].sndToggle = bmSNDTOG1;
|
||||
rcode = outTransfer( addr, ep, nbytes, dataptr, nak_limit );
|
||||
return( rcode );
|
||||
}
|
||||
uint8_t rcode;
|
||||
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||
|
||||
//Serial.print("cD");
|
||||
//Serial.print("\tA:");
|
||||
//Serial.print(addr, HEX);
|
||||
//Serial.print("\tE:");
|
||||
//Serial.println(ep, HEX);
|
||||
|
||||
if (!p)
|
||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||
|
||||
if (!p->epinfo)
|
||||
return USB_ERROR_EPINFO_IS_NULL;
|
||||
|
||||
EP_RECORD *pep = &p->epinfo[ep];
|
||||
|
||||
if( direction ) //IN transfer
|
||||
{
|
||||
pep->rcvToggle = bmRCVTOG1;
|
||||
rcode = inTransfer( addr, ep, nbytes, dataptr, nak_limit );
|
||||
}
|
||||
else //OUT transfer
|
||||
{
|
||||
pep->sndToggle = bmSNDTOG1;
|
||||
rcode = outTransfer( addr, ep, nbytes, dataptr, nak_limit );
|
||||
}
|
||||
return( rcode );
|
||||
}
|
||||
/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
||||
/* Keep sending INs and writes data to memory area pointed by 'data' */
|
||||
|
@ -130,16 +166,33 @@ uint8_t USB::ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* d
|
|||
fe USB xfer timeout */
|
||||
uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit )
|
||||
{
|
||||
uint8_t rcode;
|
||||
uint8_t pktsize;
|
||||
uint8_t maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize;
|
||||
unsigned int xfrlen = 0;
|
||||
regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle ); //set toggle value
|
||||
while( 1 ) { // use a 'return' to exit this loop
|
||||
uint8_t rcode;
|
||||
uint8_t pktsize;
|
||||
|
||||
//Serial.println("iT");
|
||||
|
||||
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||
|
||||
if (!p)
|
||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||
|
||||
if (!p->epinfo)
|
||||
return USB_ERROR_EPINFO_IS_NULL;
|
||||
|
||||
EP_RECORD *pep = &p->epinfo[ep];
|
||||
|
||||
uint8_t maxpktsize = pep->MaxPktSize;
|
||||
|
||||
unsigned int xfrlen = 0;
|
||||
regWr( rHCTL, pep->rcvToggle ); //set toggle value
|
||||
|
||||
while( 1 ) // use a 'return' to exit this loop
|
||||
{
|
||||
rcode = dispatchPkt( tokIN, ep, nak_limit ); //IN packet to EP-'endpoint'. Function takes care of NAKS.
|
||||
if( rcode ) {
|
||||
|
||||
if( rcode )
|
||||
return( rcode ); //should be 0, indicating ACK. Else return error code.
|
||||
}
|
||||
|
||||
/* check for RCVDAVIRQ and generate error if not present */
|
||||
/* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
|
||||
if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {
|
||||
|
@ -152,16 +205,16 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t*
|
|||
/* The transfer is complete under two conditions: */
|
||||
/* 1. The device sent a short packet (L.T. maxPacketSize) */
|
||||
/* 2. 'nbytes' have been transferred. */
|
||||
if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) { // have we transferred 'nbytes' bytes?
|
||||
if( regRd( rHRSL ) & bmRCVTOGRD ) { //save toggle value
|
||||
devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
|
||||
}
|
||||
else {
|
||||
devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
}//while( 1 )
|
||||
if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) // have we transferred 'nbytes' bytes?
|
||||
{
|
||||
if( regRd( rHRSL ) & bmRCVTOGRD ) //save toggle value
|
||||
pep->rcvToggle = bmRCVTOG1;
|
||||
else
|
||||
pep->rcvToggle = bmRCVTOG0;
|
||||
|
||||
return( 0 );
|
||||
} // if
|
||||
} //while( 1 )
|
||||
}
|
||||
/* OUT transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
||||
/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
|
||||
|
@ -169,59 +222,77 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t*
|
|||
/* major part of this function borrowed from code shared by Richard Ibbotson */
|
||||
uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit )
|
||||
{
|
||||
uint8_t rcode, retry_count;
|
||||
uint8_t* data_p = data; //local copy of the data pointer
|
||||
unsigned int bytes_tosend, nak_count;
|
||||
unsigned int bytes_left = nbytes;
|
||||
uint8_t maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize;
|
||||
unsigned long timeout = millis() + USB_XFER_TIMEOUT;
|
||||
uint8_t rcode, retry_count;
|
||||
uint8_t* data_p = data; //local copy of the data pointer
|
||||
unsigned int bytes_tosend, nak_count;
|
||||
unsigned int bytes_left = nbytes;
|
||||
|
||||
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||
|
||||
if (!p)
|
||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||
|
||||
EP_RECORD *pep = p->epinfo + ep;
|
||||
|
||||
if (!p->epinfo)
|
||||
return USB_ERROR_EPINFO_IS_NULL;
|
||||
|
||||
uint8_t maxpktsize = pep->MaxPktSize;
|
||||
|
||||
if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64
|
||||
return 0xFE;
|
||||
}
|
||||
unsigned long timeout = millis() + USB_XFER_TIMEOUT;
|
||||
|
||||
regWr( rHCTL, devtable[ addr ].epinfo[ ep ].sndToggle ); //set toggle value
|
||||
while( bytes_left ) {
|
||||
retry_count = 0;
|
||||
nak_count = 0;
|
||||
bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left;
|
||||
bytesWr( rSNDFIFO, bytes_tosend, data_p ); //filling output FIFO
|
||||
regWr( rSNDBC, bytes_tosend ); //set number of bytes
|
||||
regWr( rHXFR, ( tokOUT | ep )); //dispatch packet
|
||||
while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ
|
||||
regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ
|
||||
rcode = ( regRd( rHRSL ) & 0x0f );
|
||||
while( rcode && ( timeout > millis())) {
|
||||
switch( rcode ) {
|
||||
case hrNAK:
|
||||
nak_count++;
|
||||
if( nak_limit && ( nak_count == USB_NAK_LIMIT )) {
|
||||
return( rcode); //return NAK
|
||||
}
|
||||
break;
|
||||
case hrTIMEOUT:
|
||||
retry_count++;
|
||||
if( retry_count == USB_RETRY_LIMIT ) {
|
||||
return( rcode ); //return TIMEOUT
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return( rcode );
|
||||
}//switch( rcode...
|
||||
/* process NAK according to Host out NAK bug */
|
||||
regWr( rSNDBC, 0 );
|
||||
regWr( rSNDFIFO, *data_p );
|
||||
regWr( rSNDBC, bytes_tosend );
|
||||
regWr( rHXFR, ( tokOUT | ep )); //dispatch packet
|
||||
while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ
|
||||
regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ
|
||||
rcode = ( regRd( rHRSL ) & 0x0f );
|
||||
}//while( rcode && ....
|
||||
bytes_left -= bytes_tosend;
|
||||
data_p += bytes_tosend;
|
||||
}//while( bytes_left...
|
||||
devtable[ addr ].epinfo[ ep ].sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0; //update toggle
|
||||
return( rcode ); //should be 0 in all cases
|
||||
if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64
|
||||
return 0xFE;
|
||||
}
|
||||
|
||||
regWr( rHCTL, pep->sndToggle ); //set toggle value
|
||||
|
||||
while( bytes_left )
|
||||
{
|
||||
retry_count = 0;
|
||||
nak_count = 0;
|
||||
bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left;
|
||||
bytesWr( rSNDFIFO, bytes_tosend, data_p ); //filling output FIFO
|
||||
regWr( rSNDBC, bytes_tosend ); //set number of bytes
|
||||
regWr( rHXFR, ( tokOUT | ep )); //dispatch packet
|
||||
while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ
|
||||
regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ
|
||||
rcode = ( regRd( rHRSL ) & 0x0f );
|
||||
|
||||
while( rcode && ( timeout > millis()))
|
||||
{
|
||||
switch( rcode )
|
||||
{
|
||||
case hrNAK:
|
||||
nak_count++;
|
||||
if( nak_limit && ( nak_count == USB_NAK_LIMIT ))
|
||||
{
|
||||
return( rcode); //return NAK
|
||||
}
|
||||
break;
|
||||
case hrTIMEOUT:
|
||||
retry_count++;
|
||||
if( retry_count == USB_RETRY_LIMIT ) {
|
||||
return( rcode ); //return TIMEOUT
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return( rcode );
|
||||
} //switch( rcode...
|
||||
/* process NAK according to Host out NAK bug */
|
||||
regWr( rSNDBC, 0 );
|
||||
regWr( rSNDFIFO, *data_p );
|
||||
regWr( rSNDBC, bytes_tosend );
|
||||
regWr( rHXFR, ( tokOUT | ep )); //dispatch packet
|
||||
while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ
|
||||
regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ
|
||||
rcode = ( regRd( rHRSL ) & 0x0f );
|
||||
}//while( rcode && ....
|
||||
bytes_left -= bytes_tosend;
|
||||
data_p += bytes_tosend;
|
||||
}//while( bytes_left...
|
||||
pep->sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0; //update toggle
|
||||
return( rcode ); //should be 0 in all cases
|
||||
}
|
||||
/* dispatch usb packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
|
||||
/* If NAK, tries to re-send up to nak_limit times */
|
||||
|
@ -285,7 +356,8 @@ void USB::Task( void ) //USB state machine
|
|||
tmpdata = getVbusState();
|
||||
/* modify USB task state if Vbus changed */
|
||||
|
||||
switch( tmpdata ) {
|
||||
switch( tmpdata )
|
||||
{
|
||||
case SE1: //illegal state
|
||||
usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
|
||||
break;
|
||||
|
@ -296,90 +368,399 @@ void USB::Task( void ) //USB state machine
|
|||
break;
|
||||
case FSHOST: //attached
|
||||
case LSHOST:
|
||||
//Serial.println("FSHOST");
|
||||
if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
|
||||
delay = millis() + USB_SETTLE_DELAY;
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
|
||||
}
|
||||
break;
|
||||
}// switch( tmpdata
|
||||
//Serial.print("USB task state: ");
|
||||
//Serial.println( usb_task_state, HEX );
|
||||
}// switch( tmpdata
|
||||
|
||||
for (uint8_t i=0; i<USB_NUMDEVICES; i++)
|
||||
{
|
||||
if (devConfig[i])
|
||||
{
|
||||
rcode = devConfig[i]->Poll();
|
||||
}
|
||||
} //for
|
||||
|
||||
switch( usb_task_state ) {
|
||||
case USB_DETACHED_SUBSTATE_INITIALIZE:
|
||||
Serial.println("INIT");
|
||||
init();
|
||||
usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
|
||||
break;
|
||||
case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
|
||||
Serial.println("WFD");
|
||||
break;
|
||||
case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
|
||||
Serial.println("ILL");
|
||||
break;
|
||||
case USB_ATTACHED_SUBSTATE_SETTLE: //setlle time for just attached device
|
||||
Serial.println("STL");
|
||||
if( delay < millis() ) {
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
|
||||
}
|
||||
break;
|
||||
case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
|
||||
regWr( rHCTL, bmBUSRST ); //issue bus reset
|
||||
Serial.println("RES");
|
||||
regWr( rHCTL, bmBUSRST ); //issue bus reset
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
|
||||
break;
|
||||
case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
|
||||
if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) {
|
||||
Serial.println("RCOMP");
|
||||
if(( regRd( rHCTL ) & bmBUSRST ) == 0 )
|
||||
{
|
||||
tmpdata = regRd( rMODE ) | bmSOFKAENAB; //start SOF generation
|
||||
regWr( rMODE, tmpdata );
|
||||
// regWr( rMODE, bmSOFKAENAB );
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
|
||||
delay = millis() + 20; //20ms wait after reset per USB spec
|
||||
}
|
||||
break;
|
||||
case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
|
||||
Serial.println("WSOF");
|
||||
if( regRd( rHIRQ ) & bmFRAMEIRQ ) { //when first SOF received we can continue
|
||||
if( delay < millis() ) { //20ms passed
|
||||
usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
|
||||
if( delay < millis() ) { //20ms passed
|
||||
usb_task_state = USB_STATE_ADDRESSING;
|
||||
//usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE:
|
||||
// toggle( BPNT_0 );
|
||||
devtable[ 0 ].epinfo->MaxPktSize = 8; //set max.packet size to min.allowed
|
||||
rcode = getDevDescr( 0, 0, 8, (uint8_t*)&buf );
|
||||
if( rcode == 0 ) {
|
||||
devtable[ 0 ].epinfo->MaxPktSize = buf.bMaxPacketSize0;
|
||||
usb_task_state = USB_STATE_ADDRESSING;
|
||||
}
|
||||
else {
|
||||
usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
break;
|
||||
case USB_STATE_ADDRESSING:
|
||||
for( i = 1; i < USB_NUMDEVICES; i++ ) {
|
||||
if( devtable[ i ].epinfo == NULL ) {
|
||||
devtable[ i ].epinfo = devtable[ 0 ].epinfo; //set correct MaxPktSize
|
||||
//temporary record
|
||||
//until plugged with real device endpoint structure
|
||||
rcode = setAddr( 0, 0, i );
|
||||
if( rcode == 0 ) {
|
||||
tmpaddr = i;
|
||||
usb_task_state = USB_STATE_CONFIGURING;
|
||||
}
|
||||
else {
|
||||
usb_error = USB_STATE_ADDRESSING; //set address error
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
break; //break if address assigned or error occured during address assignment attempt
|
||||
}
|
||||
} //for( i = 1; i < USB_NUMDEVICES; i++)
|
||||
Serial.println("ADR");
|
||||
|
||||
rcode = Addressing(&tmpaddr);
|
||||
|
||||
if( usb_task_state == USB_STATE_ADDRESSING ) { //no vacant place in devtable
|
||||
usb_error = 0xfe;
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
if (rcode == hrSUCCESS)
|
||||
usb_task_state = USB_STATE_CONFIGURING;
|
||||
else
|
||||
{
|
||||
usb_error = rcode;
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
break;
|
||||
case USB_STATE_CONFIGURING:
|
||||
Serial.print("CNF");
|
||||
|
||||
rcode = Configuring(tmpaddr);
|
||||
|
||||
if (rcode)
|
||||
{
|
||||
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
|
||||
{
|
||||
usb_error = rcode;
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
usb_task_state = USB_STATE_RUNNING;
|
||||
break;
|
||||
case USB_STATE_RUNNING:
|
||||
Serial.println("RUN");
|
||||
break;
|
||||
case USB_STATE_ERROR:
|
||||
break;
|
||||
}// switch( usb_task_state
|
||||
} // switch( usb_task_state )
|
||||
}
|
||||
|
||||
uint8_t USB::Addressing(uint8_t *address)
|
||||
{
|
||||
uint8_t rcode = hrSUCCESS, buf[8];
|
||||
|
||||
Serial.println("Adrsng");
|
||||
|
||||
UsbDevice *p = addrPool.GetUsbDevicePtr(0);
|
||||
|
||||
if (!p)
|
||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||
|
||||
if (!p->epinfo)
|
||||
{
|
||||
Serial.println("epinfo");
|
||||
return USB_ERROR_EPINFO_IS_NULL;
|
||||
}
|
||||
Serial.print("addr:");
|
||||
Serial.println(p->address, HEX);
|
||||
Serial.print("ep:");
|
||||
Serial.println(p->epinfo->epAddr, HEX);
|
||||
|
||||
//p->epinfo->MaxPktSize = 8;
|
||||
|
||||
Serial.print("Max:");
|
||||
Serial.println(p->epinfo->MaxPktSize, HEX);
|
||||
|
||||
rcode = getDevDescr( 0, 0, 8, (uint8_t*)buf );
|
||||
|
||||
if( rcode == 0 )
|
||||
{
|
||||
Serial.println("OK!");
|
||||
p->epinfo->MaxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
|
||||
p->devclass = ((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("getDevDesc:");
|
||||
return rcode;
|
||||
}
|
||||
|
||||
uint8_t addr = addrPool.AllocAddress(0, (p->devclass == 0x09) ? true : false);
|
||||
|
||||
if (!addr)
|
||||
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
|
||||
|
||||
Serial.print("Addr:");
|
||||
Serial.println(addr,HEX);
|
||||
|
||||
rcode = setAddr( 0, 0, addr );
|
||||
|
||||
if (!rcode)
|
||||
{
|
||||
*address = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("setAddr:");
|
||||
Serial.println(rcode, HEX);
|
||||
return rcode;
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
uint8_t USB::Configuring(uint8_t addr)
|
||||
{
|
||||
static uint8_t dev_index = 0;
|
||||
uint8_t rcode = 0, buf[8];
|
||||
|
||||
for (; devConfigIndex<USB_NUMDEVICES; devConfigIndex++)
|
||||
{
|
||||
rcode = devConfig[devConfigIndex]->Init(addr);
|
||||
|
||||
Serial.println(".");
|
||||
|
||||
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
|
||||
{
|
||||
// in case of an error dev_index should be reset to 0
|
||||
// in order to start from the very beginning the
|
||||
// next time the program gets here
|
||||
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
|
||||
devConfigIndex = 0;
|
||||
|
||||
return rcode;
|
||||
}
|
||||
}
|
||||
// if we get here that means that the device class is not supported by any of registered classes
|
||||
devConfigIndex = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//class UsbHub
|
||||
//{
|
||||
// uint8_t bNbrPorts; // Number of ports
|
||||
// uint8_t portStates[HUB_MAX_PORTS]; // State of each port a hub has
|
||||
//};
|
||||
//
|
||||
//struct HubPort
|
||||
//{
|
||||
// UsbDevAddress *hubAddr;
|
||||
// uint8_t numPort;
|
||||
// uint8_t portState;
|
||||
//};
|
||||
|
||||
//static uint8_t USB::PortTask(HubPort *phub_port, uint8_t sig)
|
||||
////static uint8_t USB::PortTask(uint8_t hub_addr, uint8_t port, uint8_t &state, uint8_t sig)
|
||||
//{
|
||||
// switch(state)
|
||||
// {
|
||||
// case USB_STATE_HUB_PORT_POWERED_OFF:
|
||||
// Serial.println("POWERED_OFF");
|
||||
//
|
||||
// for (uint8_t j=1; j<=hubs[0].bNbrPorts; j++)
|
||||
// HubPortPowerOn(hubs[0].bAddress, j);
|
||||
//
|
||||
// delay = millis() + USB_SETTLE_DELAY;
|
||||
// usb_task_state = USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD;
|
||||
// break;
|
||||
// case USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD:
|
||||
// Serial.println("WAIT_FOR_POWER_GOOD");
|
||||
// if (millis() >= delay)
|
||||
// usb_task_state = USB_STATE_HUB_PORT_DISCONNECTED;
|
||||
//// usb_task_state = USB_STATE_HUB_PORT_DISABLED;
|
||||
// break;
|
||||
// case USB_STATE_HUB_PORT_DISCONNECTED:
|
||||
// Serial.println("PORT_DISCONNECTED");
|
||||
//
|
||||
// for (uint8_t j=1; j<=hubs[0].bNbrPorts; j++)
|
||||
// HubClearPortFeatures(hubs[0].bAddress, j, HUB_FEATURE_PORT_ENABLE | HUB_FEATURE_C_PORT_CONNECTION);
|
||||
//
|
||||
// usb_task_state = USB_STATE_HUB_PORT_DISABLED;
|
||||
// break;
|
||||
// case USB_STATE_HUB_PORT_DISABLED:
|
||||
// Serial.println("PORT_DISABLED");
|
||||
//
|
||||
// for (uint8_t j=1; j<=hubs[0].bNbrPorts; j++)
|
||||
// HubPortReset(hubs[0].bAddress, j);
|
||||
//
|
||||
// delay = millis() + HUB_PORT_RESET_DELAY;
|
||||
// usb_task_state = USB_STATE_HUB_PORT_RESETTING;
|
||||
// break;
|
||||
// case USB_STATE_HUB_PORT_RESETTING:
|
||||
// Serial.println("PORT_RESETTING");
|
||||
// if (millis() >= delay)
|
||||
// usb_task_state = USB_STATE_HUB_PORT_ENABLED;
|
||||
// break;
|
||||
// case USB_STATE_HUB_PORT_ENABLED:
|
||||
// Serial.println("PORT_ENABLED");
|
||||
// usb_task_state = USB_STATE_RUNNING;
|
||||
// break;
|
||||
// }
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
|
||||
uint8_t USB::HubPortPowerOn(uint8_t addr, uint8_t port)
|
||||
{
|
||||
uint8_t rcode = SetPortFeature(addr, 0, HUB_FEATURE_PORT_POWER, port, 0);
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("PORT #");
|
||||
Serial.print(port, DEC);
|
||||
Serial.print(" pwr err:");
|
||||
Serial.println(rcode,HEX);
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
uint8_t USB::HubPortReset(uint8_t addr, uint8_t port)
|
||||
{
|
||||
uint8_t rcode = SetPortFeature(addr, 0, HUB_FEATURE_PORT_RESET, port, 0);
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("PORT #");
|
||||
Serial.print(port, DEC);
|
||||
Serial.print(" rst err:");
|
||||
Serial.println(rcode,HEX);
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
uint8_t USB::HubClearPortFeatures(uint8_t addr, uint8_t port, uint8_t bm_features)
|
||||
{
|
||||
uint8_t rcode = ClearPortFeature(addr, 0, bm_features, port, 0);
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("PORT #");
|
||||
Serial.print(port, DEC);
|
||||
Serial.print(" f.clr err:");
|
||||
Serial.println(rcode,HEX);
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Hub Polling
|
||||
uint8_t USB::PollHub()
|
||||
{
|
||||
uint8_t rcode;
|
||||
uint8_t buf[8];
|
||||
|
||||
// uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
//Serial.println(devtable[1].epinfo->epAddr, HEX);
|
||||
|
||||
rcode = inTransfer(1, 0x1 /*devtable[1].epinfo->epAddr*/, 1, buf, 1);
|
||||
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("inTransfer:");
|
||||
Serial.println(rcode, HEX);
|
||||
return rcode;
|
||||
}
|
||||
Serial.print("Int:");
|
||||
Serial.println(buf[0],HEX);
|
||||
|
||||
//return 0;
|
||||
|
||||
if (buf[0] & 0x01) // Hub Status Change
|
||||
{
|
||||
PrintHubStatus(1);
|
||||
//rcode = GetHubStatus(1, 0, 1, 4, buf);
|
||||
//if (rcode)
|
||||
//{
|
||||
// Serial.print("GetHubStatus Error");
|
||||
// Serial.println(rcode, HEX);
|
||||
// return rcode;
|
||||
//}
|
||||
}
|
||||
if (buf[0] & 0x02) // Port 1
|
||||
{
|
||||
rcode = GetPortStatus(1, 0, 1, 4, buf);
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("GetPortStatus Error");
|
||||
Serial.println(rcode, HEX);
|
||||
return rcode;
|
||||
}
|
||||
if (buf[2] & bmHUB_PORT_STATUS_C_PORT_RESET)
|
||||
{
|
||||
Serial.println("PORT_RESET");
|
||||
|
||||
rcode = ClearPortFeature(1, 0, 1, HUB_FEATURE_C_PORT_RESET);
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("ClearPortFeature Error");
|
||||
Serial.println(rcode, HEX);
|
||||
return rcode;
|
||||
}
|
||||
//usb_task_state = USB_STATE_HUB_PORT_ENABLED; //USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
|
||||
return 0;
|
||||
}
|
||||
if (buf[2] & bmHUB_PORT_STATUS_C_PORT_CONNECTION)
|
||||
{
|
||||
Serial.println("PORT_CONNECTION");
|
||||
|
||||
rcode = ClearPortFeature(1, 0, 1, HUB_FEATURE_C_PORT_CONNECTION);
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("ClearPortFeature Error");
|
||||
Serial.println(rcode, HEX);
|
||||
return rcode;
|
||||
}
|
||||
// //if (buf & bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||
// // usb_task_state = USB_STATE_HUB_PORT_DISABLED;
|
||||
// //else
|
||||
// // usb_task_state = USB_STATE_RUNNING;
|
||||
|
||||
}
|
||||
|
||||
} // if (buf[0] & 0x02) // Port 1
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void USB::PrintHubStatus(/*USB *usbptr,*/ uint8_t addr)
|
||||
{
|
||||
uint8_t rcode = 0;
|
||||
uint8_t buf[4];
|
||||
|
||||
rcode = /*usbptr->*/GetHubStatus(addr, 0, 4, (uint8_t*)&buf);
|
||||
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("ERROR:");
|
||||
Serial.println(rcode, HEX);
|
||||
return;
|
||||
}
|
||||
Serial.println("\r\nHub");
|
||||
Serial.println("\r\nStatus");
|
||||
|
||||
Serial.print("Local Pwr Src:\t");
|
||||
Serial.println((buf[0] & bmHUB_STATUS_LOCAL_POWER_SOURCE) > 0, DEC);
|
||||
Serial.print("Over-current:\t");
|
||||
Serial.println((buf[0] & bmHUB_STATUS_OVER_CURRENT) > 0, DEC);
|
||||
|
||||
Serial.println("\r\nChanges");
|
||||
Serial.print("Local Pwr Src:\t");
|
||||
Serial.println((buf[2] & bmHUB_STATUS_C_LOCAL_POWER_SOURCE) > 0, DEC);
|
||||
Serial.print("Over-current:\t");
|
||||
Serial.println((buf[2] & bmHUB_STATUS_C_OVER_CURRENT) > 0, DEC);
|
||||
Serial.println("");
|
||||
}
|
||||
|
|
309
Usb.h
309
Usb.h
|
@ -7,27 +7,155 @@
|
|||
#include "max3421e.h"
|
||||
#include "usbhost.h"
|
||||
#include "usb_ch9.h"
|
||||
#include "address.h"
|
||||
#include <WProgram.h>
|
||||
|
||||
/* Common setup data constant combinations */
|
||||
#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type
|
||||
#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface'
|
||||
#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type
|
||||
|
||||
/* HID requests */
|
||||
#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
||||
#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
||||
#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE
|
||||
|
||||
#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
|
||||
#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. o meand NAKs are not counted
|
||||
#define USB_RETRY_LIMIT 3 //retry limit for a transfer
|
||||
#define USB_SETTLE_DELAY 200 //settle delay in milliseconds
|
||||
#define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code
|
||||
|
||||
#define USB_NUMDEVICES 2 //number of USB devices
|
||||
|
||||
// D7 data transfer direction (0 - host-to-device, 1 - device-to-host)
|
||||
// D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved)
|
||||
// D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved)
|
||||
|
||||
|
||||
// USB Device Classes
|
||||
#define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors
|
||||
#define USB_CLASS_AUDIO 0x01 // Audio
|
||||
#define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control
|
||||
#define USB_CLASS_HID 0x03 // HID
|
||||
#define USB_CLASS_PHYSICAL 0x05 // Physical
|
||||
#define USB_CLASS_IMAGE 0x06 // Image
|
||||
#define USB_CLASS_PRINTER 0x07 // Printer
|
||||
#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage
|
||||
#define USB_CLASS_HUB 0x09 // Hub
|
||||
#define USB_CLASS_CDC_DATA 0x0a // CDC-Data
|
||||
#define USB_CLASS_SMART_CARD 0x0b // Smart-Card
|
||||
#define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security
|
||||
#define USB_CLASS_VIDEO 0x0e // Video
|
||||
#define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare
|
||||
#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device
|
||||
#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller
|
||||
#define USB_CLASS_MISC 0xef // Miscellaneous
|
||||
#define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific
|
||||
#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific
|
||||
|
||||
|
||||
// Hub Requests
|
||||
#define bmREQ_CLEAR_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_CLEAR_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_CLEAR_TT_BUFFER USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_GET_HUB_DESCRIPTOR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_GET_HUB_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_GET_PORT_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_RESET_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_SET_HUB_DESCRIPTOR USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_SET_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_SET_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_GET_TT_STATE USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_STOP_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
|
||||
// Hub Class Requests
|
||||
#define HUB_REQUEST_CLEAR_TT_BUFFER 8
|
||||
#define HUB_REQUEST_RESET_TT 9
|
||||
#define HUB_REQUEST_GET_TT_STATE 10
|
||||
#define HUB_REQUEST_STOP_TT 11
|
||||
|
||||
// Hub Features
|
||||
#define HUB_FEATURE_C_HUB_LOCAL_POWER 0
|
||||
#define HUB_FEATURE_C_HUB_OVER_CURRENT 1
|
||||
#define HUB_FEATURE_PORT_CONNECTION 0
|
||||
#define HUB_FEATURE_PORT_ENABLE 1
|
||||
#define HUB_FEATURE_PORT_SUSPEND 2
|
||||
#define HUB_FEATURE_PORT_OVER_CURRENT 3
|
||||
#define HUB_FEATURE_PORT_RESET 4
|
||||
#define HUB_FEATURE_PORT_POWER 8
|
||||
#define HUB_FEATURE_PORT_LOW_SPEED 9
|
||||
#define HUB_FEATURE_C_PORT_CONNECTION 16
|
||||
#define HUB_FEATURE_C_PORT_ENABLE 17
|
||||
#define HUB_FEATURE_C_PORT_SUSPEND 18
|
||||
#define HUB_FEATURE_C_PORT_OVER_CURRENT 19
|
||||
#define HUB_FEATURE_C_PORT_RESET 20
|
||||
#define HUB_FEATURE_PORT_TEST 21
|
||||
#define HUB_FEATURE_PORT_INDICATOR 22
|
||||
|
||||
// Hub Port Test Modes
|
||||
#define HUB_PORT_TEST_MODE_J 1
|
||||
#define HUB_PORT_TEST_MODE_K 2
|
||||
#define HUB_PORT_TEST_MODE_SE0_NAK 3
|
||||
#define HUB_PORT_TEST_MODE_PACKET 4
|
||||
#define HUB_PORT_TEST_MODE_FORCE_ENABLE 5
|
||||
|
||||
// Hub Port Indicator Color
|
||||
#define HUB_PORT_INDICATOR_AUTO 0
|
||||
#define HUB_PORT_INDICATOR_AMBER 1
|
||||
#define HUB_PORT_INDICATOR_GREEN 2
|
||||
#define HUB_PORT_INDICATOR_OFF 3
|
||||
|
||||
// Hub Port Status Bitmasks
|
||||
#define bmHUB_PORT_STATUS_PORT_CONNECTION 0x0001
|
||||
#define bmHUB_PORT_STATUS_PORT_ENABLE 0x0002
|
||||
#define bmHUB_PORT_STATUS_PORT_SUSPEND 0x0004
|
||||
#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT 0x0008
|
||||
#define bmHUB_PORT_STATUS_PORT_RESET 0x0010
|
||||
#define bmHUB_PORT_STATUS_PORT_POWER 0x0100
|
||||
#define bmHUB_PORT_STATUS_PORT_LOW_SPEED 0x0200
|
||||
#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED 0x0400
|
||||
#define bmHUB_PORT_STATUS_PORT_TEST 0x0800
|
||||
#define bmHUB_PORT_STATUS_PORT_INDICATOR 0x1000
|
||||
|
||||
// Hub Port Status Change Bitmasks (used one byte instead of two)
|
||||
#define bmHUB_PORT_STATUS_C_PORT_CONNECTION 0x0001
|
||||
#define bmHUB_PORT_STATUS_C_PORT_ENABLE 0x0002
|
||||
#define bmHUB_PORT_STATUS_C_PORT_SUSPEND 0x0004
|
||||
#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT 0x0008
|
||||
#define bmHUB_PORT_STATUS_C_PORT_RESET 0x0010
|
||||
|
||||
// Hub Status Bitmasks (used one byte instead of two)
|
||||
#define bmHUB_STATUS_LOCAL_POWER_SOURCE 0x01
|
||||
#define bmHUB_STATUS_OVER_CURRENT 0x12
|
||||
|
||||
// Hub Status Change Bitmasks (used one byte instead of two)
|
||||
#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE 0x01
|
||||
#define bmHUB_STATUS_C_OVER_CURRENT 0x12
|
||||
|
||||
// Additional Error Codes
|
||||
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1
|
||||
#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2
|
||||
#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3
|
||||
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4
|
||||
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD5
|
||||
#define USB_ERROR_EPINFO_IS_NULL 0xD6
|
||||
#define USB_ERROR_INVALID_ARGUMENT 0xD7
|
||||
|
||||
class USBDeviceConfig
|
||||
{
|
||||
public:
|
||||
virtual uint8_t Init(uint8_t addr) = 0;
|
||||
virtual uint8_t Release(uint8_t addr) = 0;
|
||||
virtual uint8_t Poll() = 0;
|
||||
};
|
||||
|
||||
|
||||
#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
|
||||
#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. o meand NAKs are not counted
|
||||
#define USB_RETRY_LIMIT 3 //retry limit for a transfer
|
||||
#define USB_SETTLE_DELAY 200 //settle delay in milliseconds
|
||||
#define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code
|
||||
|
||||
#define USB_NUMDEVICES 6 //number of USB devices
|
||||
#define HUB_MAX_HUBS 5 // maximum number of hubs that can be attached to the host controller
|
||||
#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms
|
||||
|
||||
/* USB state machine states */
|
||||
|
||||
#define USB_STATE_MASK 0xf0
|
||||
|
||||
#define USB_STATE_DETACHED 0x10
|
||||
|
@ -44,6 +172,7 @@
|
|||
#define USB_STATE_RUNNING 0x90
|
||||
#define USB_STATE_ERROR 0xa0
|
||||
|
||||
|
||||
// byte usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE
|
||||
|
||||
/* USB Setup Packet Structure */
|
||||
|
@ -56,7 +185,7 @@ typedef struct {
|
|||
uint8_t direction: 1; // Direction of data X-fer
|
||||
};
|
||||
}ReqType_u;
|
||||
uint8_t bRequest; // 1 Request
|
||||
uint8_t bRequest; // 1 Request
|
||||
union {
|
||||
unsigned int wValue; // 2 Depends on bRequest
|
||||
struct {
|
||||
|
@ -68,26 +197,38 @@ typedef struct {
|
|||
unsigned int wLength; // 6 Depends on bRequest
|
||||
} SETUP_PKT, *PSETUP_PKT;
|
||||
|
||||
/* Endpoint information structure */
|
||||
/* bToggle of endpoint 0 initialized to 0xff */
|
||||
/* during enumeration bToggle is set to 00 */
|
||||
typedef struct {
|
||||
uint8_t epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints )
|
||||
uint8_t Attr; // Endpoint transfer type.
|
||||
unsigned int MaxPktSize; // Maximum packet size.
|
||||
uint8_t Interval; // Polling interval in frames.
|
||||
uint8_t sndToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||
uint8_t rcvToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||
/* not sure if both are necessary */
|
||||
} EP_RECORD;
|
||||
/* device record structure */
|
||||
typedef struct {
|
||||
EP_RECORD* epinfo; //device endpoint information
|
||||
uint8_t devclass; //device class
|
||||
typedef struct
|
||||
{
|
||||
EP_RECORD *epinfo; //device endpoint information
|
||||
uint8_t devclass; //device class
|
||||
} DEV_RECORD;
|
||||
|
||||
|
||||
typedef MAX3421e<P10, P9> MAX3421E;
|
||||
struct HubDescriptor
|
||||
{
|
||||
uint8_t bDescLength; // descriptor length
|
||||
uint8_t bDescriptorType; // descriptor type
|
||||
uint8_t bNbrPorts; // number of ports a hub equiped with
|
||||
|
||||
struct
|
||||
{
|
||||
uint16_t LogPwrSwitchMode : 2;
|
||||
uint16_t CompoundDevice : 1;
|
||||
uint16_t OverCurrentProtectMode : 2;
|
||||
uint16_t TTThinkTime : 2;
|
||||
uint16_t PortIndicatorsSupported : 1;
|
||||
uint16_t Reserved : 8;
|
||||
};
|
||||
|
||||
uint8_t bPwrOn2PwrGood;
|
||||
uint8_t bHubContrCurrent;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//typedef MAX3421e<P6, P3> MAX3421E; // Black Widdow
|
||||
typedef MAX3421e<P10, P9> MAX3421E; // Duemielanove
|
||||
|
||||
class USB : public MAX3421E
|
||||
{
|
||||
|
@ -101,14 +242,39 @@ class USB : public MAX3421E
|
|||
|
||||
//byte usb_task_state;
|
||||
|
||||
|
||||
AddressPoolImpl<USB_NUMDEVICES> addrPool;
|
||||
USBDeviceConfig* devConfig[USB_NUMDEVICES];
|
||||
uint8_t devConfigIndex;
|
||||
|
||||
public:
|
||||
USB( void );
|
||||
uint8_t getUsbTaskState( void );
|
||||
|
||||
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
|
||||
{
|
||||
for (uint8_t i=0; i<USB_NUMDEVICES; i++)
|
||||
{
|
||||
if (!devConfig[i])
|
||||
{
|
||||
devConfig[i] = pdev;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
|
||||
};
|
||||
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
|
||||
{
|
||||
addrPool.ForEachUsbDevice(pfunc);
|
||||
};
|
||||
uint8_t getUsbTaskState( void );
|
||||
void setUsbTaskState( uint8_t state );
|
||||
|
||||
EP_RECORD* getDevTableEntry( uint8_t addr, uint8_t ep );
|
||||
void setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr );
|
||||
uint8_t setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr );
|
||||
|
||||
uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, unsigned int wInd, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
/* Control requests */
|
||||
|
||||
/* Control requests */
|
||||
uint8_t getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t getStrDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t index, unsigned int langid, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
|
@ -119,7 +285,7 @@ class USB : public MAX3421E
|
|||
uint8_t getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t setReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t getReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t getReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
/**/
|
||||
|
@ -128,19 +294,46 @@ class USB : public MAX3421E
|
|||
uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t dispatchPkt( uint8_t token, uint8_t ep, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
|
||||
// Hub Methods
|
||||
uint8_t ClearHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t ClearPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel = 0, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t GetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t index, uint16_t nbytes, uint8_t *dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t GetPortStatus( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t SetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
uint8_t SetPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel = 0, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
|
||||
uint8_t HubPortPowerOn(uint8_t addr, uint8_t port);
|
||||
uint8_t HubPortReset(uint8_t addr, uint8_t port);
|
||||
uint8_t HubClearPortFeatures(uint8_t addr, uint8_t port, uint8_t bm_features);
|
||||
|
||||
uint8_t GetNumDevices();
|
||||
uint8_t GetNumHubs();
|
||||
|
||||
uint8_t PollHubs();
|
||||
uint8_t PollHub();
|
||||
|
||||
void PrintHubStatus(/*USB *usbptr,*/ uint8_t addr);
|
||||
|
||||
void Task( void );
|
||||
//uint8_t nit() {};
|
||||
|
||||
uint8_t Addressing(uint8_t *address);
|
||||
uint8_t Configuring(uint8_t addr);
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
|
||||
//get device descriptor
|
||||
inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit ));
|
||||
}
|
||||
//get configuration descriptor
|
||||
inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, unsigned int nuint8_ts, uint8_t conf, uint8_t* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nuint8_ts, dataptr, nak_limit ));
|
||||
inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit ));
|
||||
}
|
||||
//get string descriptor
|
||||
inline uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, unsigned int nuint8_ts, uint8_t index, unsigned int langid, uint8_t* dataptr, unsigned int nak_limit ) {
|
||||
|
@ -178,4 +371,58 @@ inline uint8_t USB::getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_
|
|||
inline uint8_t USB::setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL, nak_limit ));
|
||||
}
|
||||
|
||||
// uint8_t ctrlReq(
|
||||
//uint8_t addr,
|
||||
//uint8_t ep,
|
||||
//uint8_t bmReqType,
|
||||
//uint8_t bRequest,
|
||||
//uint8_t wValLo,
|
||||
//uint8_t wValHi,
|
||||
//unsigned int wInd,
|
||||
//unsigned int nbytes,
|
||||
//uint8_t* dataptr,
|
||||
//unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
|
||||
// Clear Hub Feature
|
||||
inline uint8_t USB::ClearHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit )
|
||||
{
|
||||
return( ctrlReq( addr, ep, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, NULL, nak_limit ));
|
||||
}
|
||||
// Clear Port Feature
|
||||
inline uint8_t USB::ClearPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel, unsigned int nak_limit )
|
||||
{
|
||||
return( ctrlReq( addr, ep, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, NULL, nak_limit ));
|
||||
}
|
||||
// Get Hub Descriptor
|
||||
inline uint8_t USB::GetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t index, uint16_t nbytes, uint8_t *dataptr, unsigned int nak_limit )
|
||||
{
|
||||
return( ctrlReq( addr, ep, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, dataptr, nak_limit ));
|
||||
}
|
||||
// Get Hub Status
|
||||
inline uint8_t USB::GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit )
|
||||
{
|
||||
return( ctrlReq( addr, ep, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, dataptr, nak_limit ));
|
||||
}
|
||||
// Get Port Status
|
||||
inline uint8_t USB::GetPortStatus( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit )
|
||||
{
|
||||
//Serial.println(bmREQ_GET_PORT_STATUS, BIN);
|
||||
return( ctrlReq( addr, ep, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, dataptr, nak_limit ));
|
||||
}
|
||||
// Set Hub Descriptor
|
||||
inline uint8_t USB::SetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit )
|
||||
{
|
||||
return( ctrlReq( addr, ep, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, dataptr, nak_limit ));
|
||||
}
|
||||
// Set Hub Feature
|
||||
inline uint8_t USB::SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit )
|
||||
{
|
||||
return( ctrlReq( addr, ep, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, NULL, nak_limit ));
|
||||
}
|
||||
// Set Port Feature
|
||||
inline uint8_t USB::SetPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel, unsigned int nak_limit )
|
||||
{
|
||||
return( ctrlReq( addr, ep, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, NULL, nak_limit ));
|
||||
}
|
||||
#endif //_usb_h_
|
237
address.h
Normal file
237
address.h
Normal file
|
@ -0,0 +1,237 @@
|
|||
#if !defined(__ADDRESS_H__)
|
||||
#define __ADDRESS_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "max3421e.h"
|
||||
|
||||
/* Endpoint information structure */
|
||||
/* bToggle of endpoint 0 initialized to 0xff */
|
||||
/* during enumeration bToggle is set to 00 */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints )
|
||||
uint8_t Attr; // Endpoint transfer type.
|
||||
unsigned int MaxPktSize; // Maximum packet size.
|
||||
uint8_t Interval; // Polling interval in frames.
|
||||
uint8_t sndToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||
uint8_t rcvToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||
/* not sure if both are necessary */
|
||||
} EP_RECORD;
|
||||
|
||||
// 7 6 5 4 3 2 1 0
|
||||
// ---------------------------------
|
||||
// | | H | P | P | P | A | A | A |
|
||||
// ---------------------------------
|
||||
//
|
||||
// H - if 1 the address is a hub address
|
||||
// P - parent hub address
|
||||
// A - device address / port number in case of hub
|
||||
//
|
||||
struct UsbDeviceAddress
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t bmAddress : 3; // device address/port number
|
||||
uint8_t bmParent : 3; // parent hub address
|
||||
uint8_t bmHub : 1; // hub flag
|
||||
uint8_t bmReserved : 1; // reserved, must be zerro
|
||||
};
|
||||
uint8_t devAddress;
|
||||
};
|
||||
};
|
||||
|
||||
#define bmUSB_DEV_ADDR_ADDRESS 0x07
|
||||
#define bmUSB_DEV_ADDR_PARENT 0x38
|
||||
#define bmUSB_DEV_ADDR_HUB 0x40
|
||||
|
||||
struct UsbDevice
|
||||
{
|
||||
EP_RECORD *epinfo; // endpoint info pointer
|
||||
uint8_t address; // address
|
||||
uint8_t devclass; // device class
|
||||
};
|
||||
|
||||
class AddressPool
|
||||
{
|
||||
public:
|
||||
virtual uint8_t AllocAddress(UsbDeviceAddress parent, bool is_hub = false, uint8_t port = 0) = 0;
|
||||
virtual void FreeAddress(UsbDeviceAddress addr) = 0;
|
||||
};
|
||||
|
||||
typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
|
||||
|
||||
#define ADDR_ERROR_INVALID_INDEX 0xFF
|
||||
#define ADDR_ERROR_INVALID_ADDRESS 0xFF
|
||||
|
||||
template <const uint8_t MAX_DEVICES_ALLOWED>
|
||||
class AddressPoolImpl
|
||||
{
|
||||
EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
||||
|
||||
uint8_t hubCounter; // hub counter is kept
|
||||
// in order to avoid hub address duplication
|
||||
|
||||
UsbDevice thePool[MAX_DEVICES_ALLOWED];
|
||||
|
||||
// Initializes address pool entry
|
||||
void InitEntry(uint8_t index)
|
||||
{
|
||||
thePool[index].address = 0;
|
||||
thePool[index].devclass = 0;
|
||||
thePool[index].epinfo = &dev0ep;
|
||||
};
|
||||
// Returns thePool index for a given address
|
||||
uint8_t FindAddressIndex(uint8_t address = 0)
|
||||
{
|
||||
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
|
||||
{
|
||||
if (thePool[i].address == address)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
// Returns thePool child index for a given parent
|
||||
uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1)
|
||||
{
|
||||
for (uint8_t i=(start<1 || start>=MAX_DEVICES_ALLOWED) ? 1 : start; i<MAX_DEVICES_ALLOWED; i++)
|
||||
{
|
||||
if (((UsbDeviceAddress*)&thePool[i].address)->bmParent == addr.bmAddress)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
// Frees address entry specified by index parameter
|
||||
void FreeAddressByIndex(uint8_t index)
|
||||
{
|
||||
// Zerro field is reserved and should not be affected
|
||||
if (index == 0)
|
||||
return;
|
||||
|
||||
// If a hub was switched off all port addresses should be freed
|
||||
if (((UsbDeviceAddress*)&thePool[index].address)->bmHub == 1)
|
||||
{
|
||||
for (uint8_t i=1; i = FindChildIndex(*((UsbDeviceAddress*)&thePool[index].address), i); )
|
||||
FreeAddressByIndex(i);
|
||||
|
||||
// If the hub had the last allocated address, hubCounter should be decremented
|
||||
if (hubCounter == ((UsbDeviceAddress*)&thePool[index].address)->bmAddress)
|
||||
hubCounter --;
|
||||
}
|
||||
InitEntry(index);
|
||||
}
|
||||
// Initializes the whole address pool at once
|
||||
void InitAllAddresses()
|
||||
{
|
||||
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
|
||||
InitEntry(i);
|
||||
|
||||
hubCounter = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
AddressPoolImpl() : hubCounter(0)
|
||||
{
|
||||
// Zerro address is reserved
|
||||
InitEntry(0);
|
||||
|
||||
thePool[0].address = 0;
|
||||
thePool[0].epinfo = &dev0ep;
|
||||
dev0ep.epAddr = 0;
|
||||
dev0ep.MaxPktSize = 8;
|
||||
dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||
dev0ep.rcvToggle = bmRCVTOG0;
|
||||
|
||||
InitAllAddresses();
|
||||
};
|
||||
// Returns a pointer to a specified address entry
|
||||
UsbDevice* GetUsbDevicePtr(uint8_t addr)
|
||||
{
|
||||
if (!addr)
|
||||
return thePool;
|
||||
|
||||
uint8_t index = FindAddressIndex(addr);
|
||||
|
||||
return (!index) ? NULL : thePool + index;
|
||||
};
|
||||
|
||||
// Performs an operation specified by pfunc for each addressed device
|
||||
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
|
||||
{
|
||||
if (!pfunc)
|
||||
return;
|
||||
|
||||
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
|
||||
if (thePool[i].address)
|
||||
pfunc(thePool + i);
|
||||
};
|
||||
// Allocates new address
|
||||
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0)
|
||||
{
|
||||
if (parent > 127 || port > 7)
|
||||
return 0;
|
||||
|
||||
// finds first empty address entry starting from one
|
||||
uint8_t index = FindAddressIndex(0);
|
||||
|
||||
Serial.println(index, DEC);
|
||||
|
||||
if (!index) // if empty entry is not found
|
||||
return 0;
|
||||
|
||||
if (parent == 0)
|
||||
{
|
||||
thePool[index].address = (is_hub) ? 0x41 : 1;
|
||||
return thePool[index].address;
|
||||
}
|
||||
|
||||
UsbDeviceAddress addr;
|
||||
|
||||
addr.bmParent = ((UsbDeviceAddress*)&parent)->bmAddress;
|
||||
|
||||
if (is_hub)
|
||||
{
|
||||
addr.bmHub = 1;
|
||||
addr.bmAddress = ++hubCounter;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr.bmHub = 0;
|
||||
addr.bmAddress = port;
|
||||
}
|
||||
thePool[index].address = *((uint8_t*)&addr);
|
||||
|
||||
return thePool[index].address;
|
||||
};
|
||||
// Empties pool entry
|
||||
virtual void FreeAddress(uint8_t addr)
|
||||
{
|
||||
// if the root hub is disconnected all the addresses should be initialized
|
||||
if (addr == 0x41)
|
||||
{
|
||||
InitAllAddresses();
|
||||
return;
|
||||
}
|
||||
uint8_t index = FindAddressIndex(addr);
|
||||
FreeAddressByIndex(index);
|
||||
};
|
||||
// Returns number of hubs attached
|
||||
// It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.
|
||||
uint8_t GetNumHubs()
|
||||
{
|
||||
return hubCounter;
|
||||
};
|
||||
uint8_t GetNumDevices()
|
||||
{
|
||||
uint8_t counter = 0;
|
||||
|
||||
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
|
||||
if (thePool[i].address != 0);
|
||||
counter ++;
|
||||
|
||||
return counter;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // __ADDRESS_H__
|
94
avrpins.h
94
avrpins.h
|
@ -106,6 +106,27 @@ MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D')
|
|||
#ifdef USE_PORTE
|
||||
MAKE_PORT(PORTE, DDRE, PINE, Porte, 'E')
|
||||
#endif
|
||||
#ifdef USE_PORTF
|
||||
MAKE_PORT(PORTF, DDRF, PINF, Portf, 'F')
|
||||
#endif
|
||||
#ifdef USE_PORTG
|
||||
MAKE_PORT(PORTG, DDRG, PING, Portg, 'G')
|
||||
#endif
|
||||
#ifdef USE_PORTH
|
||||
MAKE_PORT(PORTH, DDRH, PINH, Porth, 'H')
|
||||
#endif
|
||||
#ifdef USE_PORTJ
|
||||
MAKE_PORT(PORTJ, DDRJ, PINJ, Portj, 'J')
|
||||
#endif
|
||||
#ifdef USE_PORTK
|
||||
MAKE_PORT(PORTK, DDRK, PINK, Portk, 'K')
|
||||
#endif
|
||||
#ifdef USE_PORTQ
|
||||
MAKE_PORT(PORTQ, DDRQ, PINQ, Portq, 'Q')
|
||||
#endif
|
||||
#ifdef USE_PORTR
|
||||
MAKE_PORT(PORTR, DDRR, PINR, Portr, 'R')
|
||||
#endif
|
||||
|
||||
#ifdef USE_TCCR0A
|
||||
MAKE_TCCR(TCCR0A, Tccr0a)
|
||||
|
@ -348,7 +369,74 @@ template<typename Tp_pin, typename Tc_bit>
|
|||
//typedef Tp_Tc<Pb2, Tc1b> P10; //Arduino pin 10
|
||||
//typedef Tp_Tc<Pb3, Tc2a> P11; //Arduino pin 11
|
||||
|
||||
//Arduino pin numbers
|
||||
/* Arduino pin definitions */
|
||||
#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__)
|
||||
|
||||
// "Mega" Arduino pin numbers
|
||||
|
||||
#define P0 Pe0
|
||||
#define P1 Pe1
|
||||
#define P2 Pe4
|
||||
#define P3 Pe5
|
||||
#define P4 Pg5
|
||||
#define P5 Pe5
|
||||
#define P6 Ph3
|
||||
#define P7 Ph4
|
||||
|
||||
#define P8 Ph5
|
||||
#define P9 Ph6
|
||||
#define P10 Pb4
|
||||
#define P11 Pb5
|
||||
#define P12 Pb6
|
||||
#define P13 Pb7
|
||||
|
||||
#define P14 Pj1
|
||||
#define P15 Pj0
|
||||
#define P16 Ph1
|
||||
#define P17 Ph0
|
||||
#define P18 Pd3
|
||||
#define P19 Pd2
|
||||
#define P20 Pd1
|
||||
#define P21 Pd0
|
||||
|
||||
#define P22 Pa0
|
||||
#define P23 Pa1
|
||||
#define P24 Pa2
|
||||
#define P25 Pa3
|
||||
#define P26 Pa4
|
||||
#define P27 Pa5
|
||||
#define P28 Pa6
|
||||
#define P29 Pa7
|
||||
#define P30 Pc7
|
||||
#define P31 Pc6
|
||||
#define P32 Pc5
|
||||
#define P33 Pc4
|
||||
#define P34 Pc3
|
||||
#define P35 Pc2
|
||||
#define P36 Pc1
|
||||
#define P37 Pc0
|
||||
|
||||
#define P38 Pd7
|
||||
#define P39 Pg2
|
||||
#define P40 Pg1
|
||||
#define P41 Pg0
|
||||
#define P42 Pl7
|
||||
#define P43 Pl6
|
||||
#define P44 Pl5
|
||||
#define P45 Pl4
|
||||
#define P46 Pl3
|
||||
#define P47 Pl2
|
||||
#define P48 Pl1
|
||||
#define P49 Pl0
|
||||
#define P50 Pb3
|
||||
#define P51 Pb2
|
||||
#define P52 Pb1
|
||||
#define P53 Pb0
|
||||
|
||||
#endif //"Mega" pin definitions
|
||||
|
||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
|
||||
//"Classical" Arduino pin numbers
|
||||
|
||||
#define P0 Pd0
|
||||
#define P1 Pd1
|
||||
|
@ -373,4 +461,6 @@ template<typename Tp_pin, typename Tc_bit>
|
|||
#define P18 Pc4
|
||||
#define P19 Pc5
|
||||
|
||||
#endif //_avrpins_h_
|
||||
#endif
|
||||
|
||||
#endif //_avrpins_h_
|
||||
|
|
12
max3421e.h
12
max3421e.h
|
@ -9,7 +9,9 @@
|
|||
/* pin numbers to port numbers */
|
||||
|
||||
//#define MAX_SS 10
|
||||
#define MAX_INT 9
|
||||
//#define MAX_INT 3 // Black Widdow
|
||||
#define MAX_INT 9 // Duemielanove
|
||||
|
||||
#define MAX_GPX 8
|
||||
//#define MAX_RESET 7
|
||||
//
|
||||
|
@ -144,7 +146,8 @@
|
|||
#define bmFRAMEIRQ 0x40
|
||||
#define bmHXFRDNIRQ 0x80
|
||||
|
||||
#define rHIEN 0xd0 //26<<3
|
||||
#define rHIEN 0xd0 //26<<3
|
||||
|
||||
/* HIEN Bits */
|
||||
#define bmBUSEVENTIE 0x01
|
||||
#define bmRWUIE 0x02
|
||||
|
@ -155,7 +158,8 @@
|
|||
#define bmFRAMEIE 0x40
|
||||
#define bmHXFRDNIE 0x80
|
||||
|
||||
#define rMODE 0xd8 //27<<3
|
||||
#define rMODE 0xd8 //27<<3
|
||||
|
||||
/* MODE Bits */
|
||||
#define bmHOST 0x01
|
||||
#define bmLOWSPEED 0x02
|
||||
|
@ -191,6 +195,7 @@
|
|||
#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0
|
||||
|
||||
#define rHRSL 0xf8 //31<<3
|
||||
|
||||
/* HRSL Bits */
|
||||
#define bmRCVTOGRD 0x10
|
||||
#define bmSNDTOGRD 0x20
|
||||
|
@ -198,6 +203,7 @@
|
|||
#define bmJSTATUS 0x80
|
||||
#define bmSE0 0x00 //SE0 - disconnect state
|
||||
#define bmSE1 0xc0 //SE1 - illegal state
|
||||
|
||||
/* Host error result codes, the 4 LSB's in the HRSL register */
|
||||
#define hrSUCCESS 0x00
|
||||
#define hrBUSY 0x01
|
||||
|
|
59
newusb.pde
Normal file
59
newusb.pde
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* new USB library tests */
|
||||
|
||||
//nclude <digitalWriteFast.h>
|
||||
#include "usbhost.h"
|
||||
|
||||
MAX3421e<P10, P9> Max;
|
||||
uint8_t buf[10] = {0};
|
||||
|
||||
void setup() {
|
||||
// Max.regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL ));
|
||||
// Max.regWr( rUSBCTL, bmCHIPRES ); //Chip reset. This stops the oscillator
|
||||
// Max.regWr( rUSBCTL, 0x00 ); //Remove the reset
|
||||
// delay( 100 );
|
||||
Serial.begin( 115200 );
|
||||
Serial.println("Start");
|
||||
|
||||
// pinModeFast2( 8, OUTPUT)
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// uint16_t i;
|
||||
// Max.regWr( rUSBCTL, bmCHIPRES );
|
||||
// Max.regWr( rUSBCTL, 0x00 );
|
||||
// for( i = 0; i < 65535; i++ ) {
|
||||
// if( ( Max.regRd( rUSBIRQ ) & bmOSCOKIRQ )) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
Serial.println( Max.reset(), DEC );
|
||||
//Max.reset();
|
||||
//delay( 100 );
|
||||
//Max.regRd( rREVISION );
|
||||
//Serial.println( Max.regRd( rREVISION ), HEX );
|
||||
|
||||
//Serial.println("tick");
|
||||
// uint8_t tmp;
|
||||
// for( uint16_t i = 0; i < 256; i++ ) {
|
||||
// tmp = Max.SPIxfer( i );
|
||||
// if( tmp != i ) {
|
||||
// Serial.println("error");
|
||||
// }
|
||||
// if( SPSR & 0x40 ) {
|
||||
// Serial.println("WCOL");
|
||||
// }
|
||||
// }
|
||||
// static bool oldintval = 0;
|
||||
// if( Max.intval() != oldintval ) {
|
||||
// oldintval = Max.intval();
|
||||
// Serial.println( oldintval, DEC );
|
||||
// }
|
||||
// Max.sstoggle();
|
||||
|
||||
//digitalWriteFast2( 8, 0 );
|
||||
//digitalWriteFast2( 8, 1 );
|
||||
}
|
||||
|
||||
|
||||
|
336
usb_ch9.h
336
usb_ch9.h
|
@ -1,169 +1,169 @@
|
|||
/* USB chapter 9 structures */
|
||||
#ifndef _ch9_h_
|
||||
#define _ch9_h_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/* Misc.USB constants */
|
||||
#define DEV_DESCR_LEN 18 //device descriptor length
|
||||
#define CONF_DESCR_LEN 9 //configuration descriptor length
|
||||
#define INTR_DESCR_LEN 9 //interface descriptor length
|
||||
#define EP_DESCR_LEN 7 //endpoint descriptor length
|
||||
|
||||
/* Standard Device Requests */
|
||||
|
||||
#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS
|
||||
#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE
|
||||
#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE
|
||||
#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS
|
||||
#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR
|
||||
#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR
|
||||
#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION
|
||||
#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION
|
||||
#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE
|
||||
#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE
|
||||
#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME
|
||||
|
||||
#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt
|
||||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up
|
||||
#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode
|
||||
|
||||
/* Setup Data Constants */
|
||||
|
||||
#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer
|
||||
#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer
|
||||
#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard
|
||||
#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class
|
||||
#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor
|
||||
#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device
|
||||
#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface
|
||||
#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint
|
||||
#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other
|
||||
|
||||
/* USB descriptors */
|
||||
|
||||
#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor.
|
||||
#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor.
|
||||
#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor.
|
||||
#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor.
|
||||
#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor.
|
||||
#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier.
|
||||
#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration.
|
||||
#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power.
|
||||
#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor.
|
||||
|
||||
/* OTG SET FEATURE Constants */
|
||||
#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP
|
||||
#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP
|
||||
#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP
|
||||
|
||||
/* USB Endpoint Transfer Types */
|
||||
#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint.
|
||||
#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint.
|
||||
#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint.
|
||||
#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint.
|
||||
#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes
|
||||
|
||||
|
||||
/* Standard Feature Selectors for CLEAR_FEATURE Requests */
|
||||
#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient
|
||||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient
|
||||
#define USB_FEATURE_TEST_MODE 2 // Device recipient
|
||||
|
||||
/* HID constants. Not part of chapter 9 */
|
||||
/* Class-Specific Requests */
|
||||
#define HID_REQUEST_GET_REPORT 0x01
|
||||
#define HID_REQUEST_GET_IDLE 0x02
|
||||
#define HID_REQUEST_GET_PROTOCOL 0x03
|
||||
#define HID_REQUEST_SET_REPORT 0x09
|
||||
#define HID_REQUEST_SET_IDLE 0x0A
|
||||
#define HID_REQUEST_SET_PROTOCOL 0x0B
|
||||
|
||||
/* Class Descriptor Types */
|
||||
#define HID_DESCRIPTOR_HID 0x21
|
||||
#define HID_DESCRIPTOR_REPORT 0x22
|
||||
#define HID_DESRIPTOR_PHY 0x23
|
||||
|
||||
/* Protocol Selection */
|
||||
#define BOOT_PROTOCOL 0x00
|
||||
#define RPT_PROTOCOL 0x01
|
||||
/* HID Interface Class Code */
|
||||
#define HID_INTF 0x03
|
||||
/* HID Interface Class SubClass Codes */
|
||||
#define BOOT_INTF_SUBCLASS 0x01
|
||||
/* HID Interface Class Protocol Codes */
|
||||
#define HID_PROTOCOL_NONE 0x00
|
||||
#define HID_PROTOCOL_KEYBOARD 0x01
|
||||
#define HID_PROTOCOL_MOUSE 0x02
|
||||
|
||||
|
||||
/* descriptor data structures */
|
||||
|
||||
/* Device descriptor structure */
|
||||
typedef struct {
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
|
||||
uint16_t bcdUSB; // USB Spec Release Number (BCD).
|
||||
uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0.
|
||||
uint16_t idVendor; // Vendor ID (assigned by the USB-IF).
|
||||
uint16_t idProduct; // Product ID (assigned by the manufacturer).
|
||||
uint16_t bcdDevice; // Device release number (BCD).
|
||||
uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer.
|
||||
uint8_t iProduct; // Index of String Descriptor describing the product.
|
||||
uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.
|
||||
uint8_t bNumConfigurations; // Number of possible configurations.
|
||||
} USB_DEVICE_DESCRIPTOR;
|
||||
|
||||
/* Configuration descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
|
||||
uint16_t wTotalLength; // Total length of all descriptors for this configuration.
|
||||
uint8_t bNumInterfaces; // Number of interfaces in this configuration.
|
||||
uint8_t bConfigurationValue; // Value of this configuration (1 based).
|
||||
uint8_t iConfiguration; // Index of String Descriptor describing the configuration.
|
||||
uint8_t bmAttributes; // Configuration characteristics.
|
||||
uint8_t bMaxPower; // Maximum power consumed by this configuration.
|
||||
} USB_CONFIGURATION_DESCRIPTOR;
|
||||
|
||||
/* Interface descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
|
||||
uint8_t bInterfaceNumber; // Number of this interface (0 based).
|
||||
uint8_t bAlternateSetting; // Value of this alternate interface setting.
|
||||
uint8_t bNumEndpoints; // Number of endpoints in this interface.
|
||||
uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t iInterface; // Index of String Descriptor describing the interface.
|
||||
} USB_INTERFACE_DESCRIPTOR;
|
||||
|
||||
/* Endpoint descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
|
||||
uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
|
||||
uint8_t bmAttributes; // Endpoint transfer type.
|
||||
uint16_t wMaxPacketSize; // Maximum packet size.
|
||||
uint8_t bInterval; // Polling interval in frames.
|
||||
} USB_ENDPOINT_DESCRIPTOR;
|
||||
|
||||
/* HID descriptor */
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdHID;
|
||||
uint8_t bCountryCode;
|
||||
uint8_t bNumDescriptors;
|
||||
uint8_t bDescrType;
|
||||
uint16_t wDescriptorLength;
|
||||
} USB_HID_DESCRIPTOR;
|
||||
|
||||
/* USB chapter 9 structures */
|
||||
#ifndef _ch9_h_
|
||||
#define _ch9_h_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/* Misc.USB constants */
|
||||
#define DEV_DESCR_LEN 18 //device descriptor length
|
||||
#define CONF_DESCR_LEN 9 //configuration descriptor length
|
||||
#define INTR_DESCR_LEN 9 //interface descriptor length
|
||||
#define EP_DESCR_LEN 7 //endpoint descriptor length
|
||||
|
||||
/* Standard Device Requests */
|
||||
|
||||
#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS
|
||||
#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE
|
||||
#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE
|
||||
#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS
|
||||
#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR
|
||||
#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR
|
||||
#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION
|
||||
#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION
|
||||
#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE
|
||||
#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE
|
||||
#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME
|
||||
|
||||
#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt
|
||||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up
|
||||
#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode
|
||||
|
||||
/* Setup Data Constants */
|
||||
|
||||
#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer
|
||||
#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer
|
||||
#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard
|
||||
#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class
|
||||
#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor
|
||||
#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device
|
||||
#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface
|
||||
#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint
|
||||
#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other
|
||||
|
||||
/* USB descriptors */
|
||||
|
||||
#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor.
|
||||
#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor.
|
||||
#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor.
|
||||
#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor.
|
||||
#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor.
|
||||
#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier.
|
||||
#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration.
|
||||
#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power.
|
||||
#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor.
|
||||
|
||||
/* OTG SET FEATURE Constants */
|
||||
#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP
|
||||
#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP
|
||||
#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP
|
||||
|
||||
/* USB Endpoint Transfer Types */
|
||||
#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint.
|
||||
#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint.
|
||||
#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint.
|
||||
#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint.
|
||||
#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes
|
||||
|
||||
|
||||
/* Standard Feature Selectors for CLEAR_FEATURE Requests */
|
||||
#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient
|
||||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient
|
||||
#define USB_FEATURE_TEST_MODE 2 // Device recipient
|
||||
|
||||
/* HID constants. Not part of chapter 9 */
|
||||
/* Class-Specific Requests */
|
||||
#define HID_REQUEST_GET_REPORT 0x01
|
||||
#define HID_REQUEST_GET_IDLE 0x02
|
||||
#define HID_REQUEST_GET_PROTOCOL 0x03
|
||||
#define HID_REQUEST_SET_REPORT 0x09
|
||||
#define HID_REQUEST_SET_IDLE 0x0A
|
||||
#define HID_REQUEST_SET_PROTOCOL 0x0B
|
||||
|
||||
/* Class Descriptor Types */
|
||||
#define HID_DESCRIPTOR_HID 0x21
|
||||
#define HID_DESCRIPTOR_REPORT 0x22
|
||||
#define HID_DESRIPTOR_PHY 0x23
|
||||
|
||||
/* Protocol Selection */
|
||||
#define BOOT_PROTOCOL 0x00
|
||||
#define RPT_PROTOCOL 0x01
|
||||
/* HID Interface Class Code */
|
||||
#define HID_INTF 0x03
|
||||
/* HID Interface Class SubClass Codes */
|
||||
#define BOOT_INTF_SUBCLASS 0x01
|
||||
/* HID Interface Class Protocol Codes */
|
||||
#define HID_PROTOCOL_NONE 0x00
|
||||
#define HID_PROTOCOL_KEYBOARD 0x01
|
||||
#define HID_PROTOCOL_MOUSE 0x02
|
||||
|
||||
|
||||
/* descriptor data structures */
|
||||
|
||||
/* Device descriptor structure */
|
||||
typedef struct {
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
|
||||
uint16_t bcdUSB; // USB Spec Release Number (BCD).
|
||||
uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0.
|
||||
uint16_t idVendor; // Vendor ID (assigned by the USB-IF).
|
||||
uint16_t idProduct; // Product ID (assigned by the manufacturer).
|
||||
uint16_t bcdDevice; // Device release number (BCD).
|
||||
uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer.
|
||||
uint8_t iProduct; // Index of String Descriptor describing the product.
|
||||
uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.
|
||||
uint8_t bNumConfigurations; // Number of possible configurations.
|
||||
} USB_DEVICE_DESCRIPTOR;
|
||||
|
||||
/* Configuration descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
|
||||
uint16_t wTotalLength; // Total length of all descriptors for this configuration.
|
||||
uint8_t bNumInterfaces; // Number of interfaces in this configuration.
|
||||
uint8_t bConfigurationValue; // Value of this configuration (1 based).
|
||||
uint8_t iConfiguration; // Index of String Descriptor describing the configuration.
|
||||
uint8_t bmAttributes; // Configuration characteristics.
|
||||
uint8_t bMaxPower; // Maximum power consumed by this configuration.
|
||||
} USB_CONFIGURATION_DESCRIPTOR;
|
||||
|
||||
/* Interface descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
|
||||
uint8_t bInterfaceNumber; // Number of this interface (0 based).
|
||||
uint8_t bAlternateSetting; // Value of this alternate interface setting.
|
||||
uint8_t bNumEndpoints; // Number of endpoints in this interface.
|
||||
uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t iInterface; // Index of String Descriptor describing the interface.
|
||||
} USB_INTERFACE_DESCRIPTOR;
|
||||
|
||||
/* Endpoint descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
|
||||
uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
|
||||
uint8_t bmAttributes; // Endpoint transfer type.
|
||||
uint16_t wMaxPacketSize; // Maximum packet size.
|
||||
uint8_t bInterval; // Polling interval in frames.
|
||||
} USB_ENDPOINT_DESCRIPTOR;
|
||||
|
||||
/* HID descriptor */
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdHID;
|
||||
uint8_t bCountryCode;
|
||||
uint8_t bNumDescriptors;
|
||||
uint8_t bDescrType;
|
||||
uint16_t wDescriptorLength;
|
||||
} USB_HID_DESCRIPTOR;
|
||||
|
||||
#endif // _ch9_h_
|
||||
|
|
26
usbhost.h
26
usbhost.h
|
@ -66,8 +66,8 @@ MAX3421e< SS, INTR >::MAX3421e()
|
|||
/* pin and peripheral setup */
|
||||
SS::SetDirWrite();
|
||||
SS::Set();
|
||||
/* For shield rev.1.xx uncomment following two lines */
|
||||
P7::SetDirWrite();
|
||||
/* For shield rev.1.xx uncomment following two lines */
|
||||
P7::SetDirWrite();
|
||||
P7::Set();
|
||||
|
||||
spi::init();
|
||||
|
@ -193,12 +193,12 @@ int8_t MAX3421e< SS, INTR >::Init()
|
|||
regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST ); // set pull-downs, Host
|
||||
|
||||
regWr( rHIEN, bmCONDETIE|bmFRAMEIE ); //connection detection
|
||||
|
||||
/* check if device is connected */
|
||||
regWr( rHCTL,bmSAMPLEBUS ); // sample USB bus
|
||||
while(!(regRd( rHCTL ) & bmSAMPLEBUS )); //wait for sample operation to finish
|
||||
busprobe(); //check if anything is connected
|
||||
|
||||
// Serial.println(getVbusState(), HEX);
|
||||
busprobe(); //check if anything is connected
|
||||
|
||||
regWr( rHIRQ, bmCONDETIRQ ); //clear connection detect interrupt
|
||||
regWr( rCPUCTL, 0x01 ); //enable interrupt pin
|
||||
|
@ -210,33 +210,33 @@ template< typename SS, typename INTR >
|
|||
void MAX3421e< SS, INTR >::busprobe()
|
||||
{
|
||||
byte bus_sample;
|
||||
bus_sample = regRd( rHRSL ); //Get J,K status
|
||||
bus_sample &= ( bmJSTATUS|bmKSTATUS ); //zero the rest of the byte
|
||||
switch( bus_sample ) { //start full-speed or low-speed host
|
||||
bus_sample = regRd( rHRSL ); //Get J,K status
|
||||
bus_sample &= ( bmJSTATUS|bmKSTATUS ); //zero the rest of the byte
|
||||
switch( bus_sample ) { //start full-speed or low-speed host
|
||||
case( bmJSTATUS ):
|
||||
if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
|
||||
regWr( rMODE, MODE_FS_HOST ); //start full-speed host
|
||||
regWr( rMODE, MODE_FS_HOST ); //start full-speed host
|
||||
vbusState = FSHOST;
|
||||
}
|
||||
else {
|
||||
regWr( rMODE, MODE_LS_HOST); //start low-speed host
|
||||
regWr( rMODE, MODE_LS_HOST); //start low-speed host
|
||||
vbusState = LSHOST;
|
||||
}
|
||||
break;
|
||||
case( bmKSTATUS ):
|
||||
if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
|
||||
regWr( rMODE, MODE_LS_HOST ); //start low-speed host
|
||||
regWr( rMODE, MODE_LS_HOST ); //start low-speed host
|
||||
vbusState = LSHOST;
|
||||
}
|
||||
else {
|
||||
regWr( rMODE, MODE_FS_HOST ); //start full-speed host
|
||||
regWr( rMODE, MODE_FS_HOST ); //start full-speed host
|
||||
vbusState = FSHOST;
|
||||
}
|
||||
break;
|
||||
case( bmSE1 ): //illegal state
|
||||
case( bmSE1 ): //illegal state
|
||||
vbusState = SE1;
|
||||
break;
|
||||
case( bmSE0 ): //disconnected state
|
||||
case( bmSE0 ): //disconnected state
|
||||
vbusState = SE0;
|
||||
break;
|
||||
}//end switch( bus_sample )
|
||||
|
|
520
usbhub.cpp
Normal file
520
usbhub.cpp
Normal file
|
@ -0,0 +1,520 @@
|
|||
#include "usbhub.h"
|
||||
|
||||
USBHub::USBHub(USB *p) :
|
||||
pUsb(p),
|
||||
bAddress(0),
|
||||
bNbrPorts(0),
|
||||
bInitState(0),
|
||||
bPortResetCounter(1),
|
||||
qNextPollTime(0),
|
||||
bPollEnable(false)
|
||||
{
|
||||
epInfo[0].epAddr = 0;
|
||||
epInfo[0].MaxPktSize = 8;
|
||||
epInfo[0].sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||
epInfo[0].rcvToggle = bmRCVTOG0;
|
||||
|
||||
epInfo[1].epAddr = 1;
|
||||
epInfo[1].MaxPktSize = 1;
|
||||
epInfo[1].Interval = 0xff;
|
||||
epInfo[1].sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||
epInfo[1].rcvToggle = bmRCVTOG0;
|
||||
|
||||
if (pUsb)
|
||||
pUsb->RegisterDeviceClass(this);
|
||||
}
|
||||
|
||||
uint8_t USBHub::Init(uint8_t addr)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
uint8_t rcode;
|
||||
|
||||
switch (bInitState)
|
||||
{
|
||||
case 0:
|
||||
Serial.println("Init");
|
||||
|
||||
bAddress = addr;
|
||||
|
||||
rcode = pUsb->getDevDescr( addr, 0, 8, (uint8_t*)buf );
|
||||
|
||||
if(rcode)
|
||||
goto FailGetDevDescr;
|
||||
|
||||
// Return if the device is not a hub
|
||||
if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass != 0x09)
|
||||
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||
|
||||
rcode = pUsb->setDevTableEntry(addr, epInfo);
|
||||
|
||||
if (rcode)
|
||||
goto FailSetDevTblEntry;
|
||||
|
||||
bInitState = 1;
|
||||
|
||||
case 1:
|
||||
// Get hub descriptor
|
||||
rcode = pUsb->GetHubDescriptor(addr, 0, 0, 8, buf);
|
||||
|
||||
if (rcode)
|
||||
goto FailGetHubDescr;
|
||||
|
||||
// Save number of ports for future use
|
||||
bNbrPorts = ((HubDescriptor*)buf)->bNbrPorts;
|
||||
|
||||
bInitState = 2;
|
||||
|
||||
case 2:
|
||||
// Read configuration Descriptor in Order To Obtain Proper Configuration Value
|
||||
rcode = pUsb->getConfDescr(addr, 0, 8, 0, buf);
|
||||
|
||||
if (rcode)
|
||||
goto FailGetConfDescr;
|
||||
|
||||
Serial.print("Conf val:");
|
||||
Serial.println(buf[5], HEX);
|
||||
|
||||
// Set Configuration Value
|
||||
rcode = pUsb->setConf(addr, 0, buf[5]);
|
||||
|
||||
if (rcode)
|
||||
goto FailSetConfDescr;
|
||||
|
||||
Serial.println("Hub configured");
|
||||
|
||||
bInitState = 3;
|
||||
|
||||
case 3:
|
||||
// Power on all ports
|
||||
for (uint8_t j=1; j<=bNbrPorts; j++)
|
||||
pUsb->HubPortPowerOn(addr, j);
|
||||
|
||||
Serial.println("Ports powered");
|
||||
|
||||
bPollEnable = true;
|
||||
bInitState = 0;
|
||||
// bInitState = 4;
|
||||
|
||||
//case 4:
|
||||
// Serial.print("RC:");
|
||||
// Serial.println(bPortResetCounter, DEC);
|
||||
|
||||
// for (; bPortResetCounter<=bNbrPorts; bPortResetCounter++)
|
||||
// {
|
||||
// HubEvent evt;
|
||||
// rcode = pUsb->GetPortStatus(addr, 0, bPortResetCounter, 4, evt.evtBuff);
|
||||
|
||||
// if (rcode)
|
||||
// goto FailGetPortStatus;
|
||||
|
||||
// Serial.print("RC:");
|
||||
// Serial.println(bPortResetCounter, DEC);
|
||||
// Serial.print("\tSt:");
|
||||
// Serial.print(evt.bmStatus, BIN);
|
||||
// Serial.print("\tCh:");
|
||||
// Serial.println(evt.bmChange, BIN);
|
||||
|
||||
// // Initiate reset only if there is a device plugged into the port
|
||||
// if (evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||
// {
|
||||
// Serial.print("Con:");
|
||||
// Serial.println(bPortResetCounter, DEC);
|
||||
|
||||
// pUsb->HubPortReset(addr, bPortResetCounter);
|
||||
// bPollEnable = true;
|
||||
//
|
||||
// if (bPortResetCounter < bNbrPorts)
|
||||
// bPortResetCounter ++;
|
||||
|
||||
// return USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE;
|
||||
// }
|
||||
// } // for
|
||||
// bPortResetCounter = 1;
|
||||
}
|
||||
bInitState = 0;
|
||||
return 0;
|
||||
|
||||
FailGetDevDescr:
|
||||
Serial.print("getDevDescr:");
|
||||
goto Fail;
|
||||
|
||||
FailSetDevTblEntry:
|
||||
Serial.print("setDevTblEn:");
|
||||
goto Fail;
|
||||
|
||||
FailGetHubDescr:
|
||||
Serial.print("getHub:");
|
||||
goto Fail;
|
||||
|
||||
FailGetConfDescr:
|
||||
Serial.print("getConf:");
|
||||
goto Fail;
|
||||
|
||||
FailSetConfDescr:
|
||||
Serial.print("setConf:");
|
||||
goto Fail;
|
||||
|
||||
FailGetPortStatus:
|
||||
Serial.print("GetPortStatus:");
|
||||
goto Fail;
|
||||
|
||||
Fail:
|
||||
Serial.println(rcode, HEX);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
uint8_t USBHub::Release(uint8_t addr)
|
||||
{
|
||||
bAddress = 0;
|
||||
bNbrPorts = 0;
|
||||
bPortResetCounter = 0;
|
||||
qNextPollTime = 0;
|
||||
bPollEnable = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t USBHub::Poll()
|
||||
{
|
||||
uint8_t rcode = 0;
|
||||
|
||||
if (!bPollEnable)
|
||||
return 0;
|
||||
|
||||
if (qNextPollTime <= millis())
|
||||
{
|
||||
Serial.println("Poll");
|
||||
|
||||
rcode = GetHubStatus(bAddress);
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("HubStatus:");
|
||||
Serial.println(rcode,HEX);
|
||||
}
|
||||
qNextPollTime = millis() + 10;
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
|
||||
//bmHUB_PORT_STATUS_C_PORT_CONNECTION
|
||||
//bmHUB_PORT_STATUS_C_PORT_ENABLE
|
||||
//bmHUB_PORT_STATUS_C_PORT_SUSPEND
|
||||
//bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT
|
||||
//bmHUB_PORT_STATUS_C_PORT_RESET
|
||||
|
||||
uint8_t USBHub::GetHubStatus(uint8_t addr)
|
||||
{
|
||||
uint8_t rcode;
|
||||
uint8_t buf[8];
|
||||
|
||||
// uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
//Serial.println(devtable[1].epinfo->epAddr, HEX);
|
||||
|
||||
rcode = pUsb->inTransfer(addr, 1, 1, buf, 1);
|
||||
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("inTransfer:");
|
||||
Serial.println(rcode, HEX);
|
||||
return rcode;
|
||||
}
|
||||
Serial.print("Int:");
|
||||
Serial.println(buf[0],HEX);
|
||||
|
||||
//return 0;
|
||||
|
||||
if (buf[0] & 0x01) // Hub Status Change
|
||||
{
|
||||
pUsb->PrintHubStatus(addr);
|
||||
//rcode = GetHubStatus(1, 0, 1, 4, buf);
|
||||
//if (rcode)
|
||||
//{
|
||||
// Serial.print("GetHubStatus Error");
|
||||
// Serial.println(rcode, HEX);
|
||||
// return rcode;
|
||||
//}
|
||||
}
|
||||
for (uint8_t port=1,mask=0x02; port<8; mask<<=1, port++)
|
||||
{
|
||||
if (buf[0] & mask)
|
||||
{
|
||||
HubEvent evt;
|
||||
evt.bmEvent = 0;
|
||||
|
||||
rcode = pUsb->GetPortStatus(addr, 0, port, 4, evt.evtBuff);
|
||||
|
||||
if (rcode)
|
||||
{
|
||||
Serial.print("GetPortStatus err:");
|
||||
Serial.println(rcode, HEX);
|
||||
Serial.print("on port:");
|
||||
Serial.println(port, DEC);
|
||||
continue;
|
||||
}
|
||||
HubPortStatusChange(addr, port, evt);
|
||||
}
|
||||
} // for
|
||||
return 0;
|
||||
}
|
||||
|
||||
void USBHub::HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt)
|
||||
{
|
||||
Serial.print("Prt:");
|
||||
Serial.print(port,HEX);
|
||||
|
||||
Serial.print("\tEvt:");
|
||||
Serial.println(evt.bmEvent,HEX);
|
||||
Serial.print("\tSt:");
|
||||
Serial.println(evt.bmStatus,HEX);
|
||||
Serial.print("\tCh:");
|
||||
Serial.println(evt.bmChange,HEX);
|
||||
|
||||
|
||||
//Serial.print("Con:");
|
||||
//Serial.println(bmHUB_PORT_EVENT_CONNECT, HEX);
|
||||
|
||||
Serial.print("Rc:");
|
||||
Serial.println(bmHUB_PORT_EVENT_RESET_COMPLETE, HEX);
|
||||
|
||||
PrintHubPortStatus(pUsb, addr, port);
|
||||
|
||||
switch (evt.bmEvent)
|
||||
{
|
||||
//case (bmHUB_PORT_STATE_DISABLED | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_SUSPEND):
|
||||
// Serial.println("DIS");
|
||||
// pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_PORT_ENABLE | HUB_FEATURE_C_PORT_CONNECTION);
|
||||
// pUsb->HubPortReset(addr, port);
|
||||
// break;
|
||||
|
||||
// Device connected event
|
||||
case bmHUB_PORT_EVENT_CONNECT:
|
||||
Serial.println("CON");
|
||||
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_ENABLE);
|
||||
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_CONNECTION);
|
||||
pUsb->HubPortReset(addr, port);
|
||||
break;
|
||||
|
||||
// Reset complete event
|
||||
case bmHUB_PORT_EVENT_RESET_COMPLETE:
|
||||
Serial.println("RCMPL");
|
||||
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_RESET | HUB_FEATURE_C_PORT_CONNECTION);
|
||||
|
||||
// Check if device is a low-speed device
|
||||
|
||||
{
|
||||
uint8_t new_addr;
|
||||
|
||||
delay(20);
|
||||
|
||||
// Begin addressing
|
||||
pUsb->Addressing(&new_addr);
|
||||
}
|
||||
|
||||
//uint8_t new_addr = addrPool.AllocAddress(addr, true, port);
|
||||
//rcode = pUsb->setAddr(0, 0, new_addr);
|
||||
//if (rcode)
|
||||
//{
|
||||
// Serial.print("ERR:");
|
||||
// Serial.println(rcode, HEX);
|
||||
//}
|
||||
break;
|
||||
|
||||
// Suspended or resuming state
|
||||
case bmHUB_PORT_STATE_SUSPENDED:
|
||||
Serial.println("SUSP");
|
||||
break;
|
||||
|
||||
// Resume complete event
|
||||
case (bmHUB_PORT_STATE_ENABLED | HUB_FEATURE_C_PORT_SUSPEND):
|
||||
break;
|
||||
|
||||
//case bmHUB_PORT_STATE_RESUMING:
|
||||
// break;
|
||||
|
||||
} // switch (evt.bmEvent)
|
||||
}
|
||||
|
||||
|
||||
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port)
|
||||
{
|
||||
uint8_t rcode = 0;
|
||||
HubEvent evt;
|
||||
|
||||
rcode = usbptr->GetPortStatus(addr, 0, port, 4, evt.evtBuff);
|
||||
|
||||
if (rcode)
|
||||
{
|
||||
Serial.println("ERROR!!!");
|
||||
return;
|
||||
}
|
||||
Serial.print("\r\nPort ");
|
||||
Serial.println(port, DEC);
|
||||
|
||||
Serial.println("Status");
|
||||
Serial.print("CONNECTION:\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC);
|
||||
Serial.print("ENABLE:\t\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC);
|
||||
Serial.print("SUSPEND:\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC);
|
||||
Serial.print("OVER_CURRENT:\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC);
|
||||
Serial.print("RESET:\t\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC);
|
||||
Serial.print("POWER:\t\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC);
|
||||
Serial.print("LOW_SPEED:\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC);
|
||||
Serial.print("HIGH_SPEED:\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC);
|
||||
Serial.print("TEST:\t\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC);
|
||||
Serial.print("INDICATOR:\t");
|
||||
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC);
|
||||
|
||||
Serial.println("\nChange");
|
||||
Serial.print("CONNECTION:\t");
|
||||
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC);
|
||||
Serial.print("ENABLE:\t\t");
|
||||
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC);
|
||||
Serial.print("SUSPEND:\t");
|
||||
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC);
|
||||
Serial.print("OVER_CURRENT:\t");
|
||||
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC);
|
||||
Serial.print("RESET:\t\t");
|
||||
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
case USB_STATE_ADDRESSING:
|
||||
Serial.println("ADRESSING");
|
||||
{
|
||||
UsbDevice *p = addrPool.GetUsbDevicePtr(0);
|
||||
|
||||
if (p)
|
||||
{
|
||||
uint8_t addr = addrPool.AllocAddress(0, (p->devclass == 0x09) ? true : false);
|
||||
|
||||
if (addr)
|
||||
{
|
||||
Serial.print("Addr:");
|
||||
Serial.println(addr,HEX);
|
||||
|
||||
UsbDevice *p0 = p;
|
||||
|
||||
rcode = setAddr( 0, 0, addr );
|
||||
|
||||
if (rcode)
|
||||
{
|
||||
Serial.println(rcode, HEX);
|
||||
break;
|
||||
}
|
||||
p = addrPool.GetUsbDevicePtr(addr);
|
||||
|
||||
usb_task_state = USB_STATE_CONFIGURING;
|
||||
|
||||
} // if (addr)
|
||||
} // if (p)
|
||||
}
|
||||
// for( i = 1; i < USB_NUMDEVICES; i++ )
|
||||
//{
|
||||
// if ( devtable[ i ].epinfo == NULL )
|
||||
// {
|
||||
// devtable[ i ].epinfo = devtable[ 0 ].epinfo; //set correct MaxPktSize
|
||||
// //temporary record
|
||||
// //until plugged with real device endpoint structure
|
||||
// devtable[ i ].devclass = devtable[ 0 ].devclass;
|
||||
|
||||
// rcode = setAddr( 0, 0, i );
|
||||
|
||||
// if( rcode == 0 )
|
||||
// {
|
||||
// tmpaddr = i;
|
||||
|
||||
// if (devtable[i].devclass == USB_CLASS_HUB)
|
||||
// {
|
||||
// Serial.println("USB_CLASS_HUB");
|
||||
|
||||
// uint8_t buf[8];
|
||||
|
||||
// rcode = GetHubDescriptor(i, 0, 0, 8, buf);
|
||||
|
||||
// if (rcode == 0)
|
||||
// {
|
||||
// // Increment number of hubs found
|
||||
// numHubs ++;
|
||||
|
||||
// // Insert hub address into a first available hub array entry
|
||||
// for (uint8_t j=0; j<HUB_MAX_HUBS; j++)
|
||||
// {
|
||||
// if (hubs[j].bAddress == 0)
|
||||
// {
|
||||
// hubs[j].bAddress = i;
|
||||
// hubs[j].bNbrPorts = ((HubDescriptor*)buf)->bNbrPorts;
|
||||
// break;
|
||||
// }
|
||||
// } // for
|
||||
//
|
||||
// } // if (rcode == 0)
|
||||
// }
|
||||
// usb_task_state = USB_STATE_CONFIGURING;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// usb_error = USB_STATE_ADDRESSING; //set address error
|
||||
// usb_task_state = USB_STATE_ERROR;
|
||||
// }
|
||||
// break; //break if address assigned or error occured during address assignment attempt
|
||||
|
||||
// } // if( devtable[ i ].epinfo == NULL )
|
||||
// } //for( i = 1; i < USB_NUMDEVICES; i++)
|
||||
|
||||
if( usb_task_state == USB_STATE_ADDRESSING ) //no vacant place in devtable
|
||||
{
|
||||
usb_error = 0xfe;
|
||||
usb_task_state = USB_STATE_ERROR;
|
||||
}
|
||||
break;
|
||||
case USB_STATE_CONFIGURING:
|
||||
Serial.print("CONFIGURING...");
|
||||
|
||||
//// Hub Configuration Code
|
||||
//if (devtable[1].devclass == USB_CLASS_HUB)
|
||||
//{
|
||||
// Serial.println("HUB");
|
||||
|
||||
// // Read configuration Descriptor in Order To Obtain Proper Configuration Value
|
||||
// uint8_t buf[8];
|
||||
// rcode = getConfDescr(1, 0, 8, 0, buf);
|
||||
|
||||
// if (rcode)
|
||||
// {
|
||||
// Serial.print("getConfDescr:");
|
||||
// Serial.println(rcode, HEX);
|
||||
// }
|
||||
|
||||
// Serial.print("Conf val:");
|
||||
// Serial.println(buf[5], HEX);
|
||||
|
||||
// // Set Configuration Value
|
||||
// rcode = setConf(1, 0, buf[5]);
|
||||
|
||||
// if (rcode)
|
||||
// {
|
||||
// Serial.print("setConf:");
|
||||
// Serial.println(rcode, HEX);
|
||||
// }
|
||||
|
||||
// Serial.println("Hub configured");
|
||||
|
||||
// // Enter Port Configuring State
|
||||
// usb_task_state = USB_STATE_HUB_PORT_POWERED_OFF;
|
||||
// //usb_task_state = USB_STATE_HUB_PORT_DISABLED;
|
||||
// break;
|
||||
|
||||
//} //if (devtable[i].devclass == USB_CLASS_HUB)
|
||||
usb_task_state = USB_STATE_RUNNING;
|
||||
Serial.println("Configured");
|
||||
break;
|
||||
#endif
|
105
usbhub.h
Normal file
105
usbhub.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
#if !defined(__USBHUB_H__)
|
||||
#define __USBHUB_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "avrpins.h"
|
||||
#include "max3421e.h"
|
||||
#include "usbhost.h"
|
||||
#include "usb_ch9.h"
|
||||
#include "Usb.h"
|
||||
#include <WProgram.h>
|
||||
|
||||
// Hub Port Configuring Substates
|
||||
#define USB_STATE_HUB_PORT_CONFIGURING 0xb0
|
||||
#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1
|
||||
#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2
|
||||
#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3
|
||||
#define USB_STATE_HUB_PORT_DISABLED 0xb4
|
||||
#define USB_STATE_HUB_PORT_RESETTING 0xb5
|
||||
#define USB_STATE_HUB_PORT_ENABLED 0xb6
|
||||
|
||||
|
||||
// The bit mask to check for all necessary state bits
|
||||
#define bmHUB_PORT_STATUS_ALL_MAIN ((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE | bmHUB_PORT_STATUS_C_PORT_SUSPEND | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND)
|
||||
|
||||
// Hub Port States
|
||||
//#define bmHUB_PORT_STATE_POWERED ((0UL | bmHUB_PORT_STATUS_PORT_POWER) << 16)
|
||||
#define bmHUB_PORT_STATE_DISCONNECTED ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE) << 16)
|
||||
|
||||
#define bmHUB_PORT_STATE_DISABLED ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION))
|
||||
|
||||
#define bmHUB_PORT_STATE_RESETTING ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_RESET) << 16)
|
||||
#define bmHUB_PORT_STATE_ENABLED ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE) << 16)
|
||||
#define bmHUB_PORT_STATE_SUSPENDED ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_SUSPEND) << 16)
|
||||
|
||||
// Hub Port Events
|
||||
#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATE_DISABLED)
|
||||
#define bmHUB_PORT_EVENT_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||
|
||||
#define bmHUB_PORT_EVENT_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||
|
||||
struct HubEvent
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t bmStatus; // port status bits
|
||||
uint16_t bmChange; // port status change bits
|
||||
};
|
||||
uint32_t bmEvent;
|
||||
uint8_t evtBuff[4];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class USBHub : USBDeviceConfig
|
||||
{
|
||||
USB *pUsb; // USB class instance pointer
|
||||
|
||||
EP_RECORD epInfo[2]; // interrupt endpoint info structure
|
||||
|
||||
uint8_t bAddress; // address
|
||||
uint8_t bNbrPorts; // number of ports
|
||||
uint8_t bInitState; // initialization state variable
|
||||
uint8_t bPortResetCounter; // number of ports reset
|
||||
uint32_t qNextPollTime; // next poll time
|
||||
bool bPollEnable; // poll enable flag
|
||||
|
||||
uint8_t GetHubStatus(uint8_t addr);
|
||||
void HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt);
|
||||
|
||||
public:
|
||||
USBHub(USB *p);
|
||||
|
||||
virtual uint8_t Init(uint8_t addr);
|
||||
virtual uint8_t Release(uint8_t addr);
|
||||
virtual uint8_t Poll();
|
||||
};
|
||||
|
||||
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port);
|
||||
|
||||
|
||||
// ---------------------------------
|
||||
// | H | H | H | P | P | P | S | S |
|
||||
// ---------------------------------
|
||||
// H - hub ID
|
||||
// P - port number
|
||||
// S - port state
|
||||
|
||||
struct UsbHubPortState
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t bmState : 2;
|
||||
uint8_t bmPort : 3;
|
||||
uint8_t bmHub : 3;
|
||||
};
|
||||
uint8_t portState;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // __USBHUB_H__
|
Loading…
Reference in a new issue