diff --git a/Usb.cpp b/Usb.cpp index 13ce8cbf..8aee8144 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -5,58 +5,56 @@ #include "usbhost.h" #include "Usb.h" #include "WProgram.h" -//#include 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 - /* constructor */ - -USB::USB () +USB::USB () : bmHubPre(0) { usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine init(); } - /* Initialize data structures */ void USB::init() { - devConfigIndex = 0; - - //UsbDevice *p = addrPool.GetUsbDevicePtr(0); - - //if (p) - //{ - // p->epinfo = &dev0ep; - // dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0 - // dev0ep.rcvToggle = bmRCVTOG0; - //} + devConfigIndex = 0; + bmHubPre = 0; } uint8_t USB::getUsbTaskState( void ) { return( usb_task_state ); } + void USB::setUsbTaskState( uint8_t state ) { usb_task_state = state; } -EP_RECORD* USB::getDevTableEntry( uint8_t addr, uint8_t ep ) + +EpInfo* USB::getEpInfoEntry( uint8_t addr, uint8_t ep ) { UsbDevice *p = addrPool.GetUsbDevicePtr(addr); - if (p) - return (p->epinfo + ep); + if (!p || !p->epinfo) + return NULL; + EpInfo *pep = p->epinfo; + + for (uint8_t i=0; iepcount; i++) + { + if ((pep)->epAddr == ep) + return pep; + + pep ++; + } 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 */ -uint8_t USB::setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr ) +uint8_t USB::setEpInfoEntry( uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr ) { if (!eprecord_ptr) return USB_ERROR_INVALID_ARGUMENT; @@ -67,153 +65,212 @@ uint8_t USB::setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr ) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; p->address = addr; - p->devclass = 0; p->epinfo = eprecord_ptr; + p->epcount = epcount; 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 */ -/* return codes: */ -/* 00 = success */ -/* 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 ) + +uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit) { - 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 - - /* fill in setup packet */ - setup_pkt.ReqType_u.bmRequestType = bmReqType; - setup_pkt.bRequest = bRequest; - setup_pkt.wVal_u.wValueLo = wValLo; - setup_pkt.wVal_u.wValueHi = wValHi; - setup_pkt.wIndex = wInd; - setup_pkt.wLength = nbytes; - bytesWr( rSUDFIFO, 8, (uint8_t*)&setup_pkt ); //transfer to setup packet FIFO - rcode = dispatchPkt( tokSETUP, ep, nak_limit ); //dispatch packet - //Serial.println("Setup packet"); //DEBUG - if( rcode ) { //return HRSLT if not zero - Serial.print("Setup packet error: "); - Serial.print( rcode, HEX ); - return( rcode ); - } - //Serial.println( direction, HEX ); - if( dataptr != NULL ) { //data stage, if present - rcode = ctrlData( addr, ep, nbytes, dataptr, direction ); - } - if( rcode ) { //return error - Serial.print("Data packet error: "); - Serial.print( rcode, HEX ); - return( rcode ); - } - rcode = ctrlStatus( ep, direction ); //status stage - return( rcode ); -} -/* Control transfer with status stage and no data stage */ -/* Assumed peripheral address is already set */ -uint8_t USB::ctrlStatus( uint8_t ep, boolean direction, unsigned int nak_limit ) -{ - uint8_t rcode; - if( direction ) { //GET - rcode = dispatchPkt( tokOUTHS, ep, nak_limit ); - } - else { - rcode = dispatchPkt( tokINHS, ep, nak_limit ); - } - return( rcode ); -} -/* 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; - 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' */ -/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, - 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; - - Serial.print("iT"); - - Serial.print(" A:"); - Serial.print(addr, HEX); - Serial.print(" E:"); - Serial.print(ep, HEX); - UsbDevice *p = addrPool.GetUsbDevicePtr(addr); if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - if (!p->epinfo) + if (!p->epinfo) return USB_ERROR_EPINFO_IS_NULL; - EP_RECORD *pep = &p->epinfo[ep]; + *ppep = getEpInfoEntry(addr, ep); + + if (!*ppep) + return USB_ERROR_EP_NOT_FOUND_IN_TBL; + + nak_limit = (0x0001UL << ( ( (*ppep)->bmNakPower > USB_NAK_MAX_POWER ) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower) ); -//////////////////////////////////////////////////////////////////////////////////////// regWr( rPERADDR, addr ); //set peripheral address uint8_t mode = regRd( rMODE ); - //if (p->lowspeed) - // regWr( rMODE, mode | bmHUBPRE ); //set HUBPRE = 1 for low speed devices - //else - // regWr( rMODE, mode & ~bmHUBPRE ); //set HUBPRE = 0 for full speed devices - -//////////////////////////////////////////////////////////////////////////////////////// + // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise + regWr( rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED)); + delay(20); - Serial.print(" E:"); - Serial.print(pep->epAddr, HEX); - Serial.print(" M:"); - Serial.print(pep->MaxPktSize, HEX); - Serial.print(" T:"); - Serial.println(pep->rcvToggle, HEX); + return 0; +} - uint8_t maxpktsize = pep->MaxPktSize; +/* 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 */ +/* return codes: */ +/* 00 = success */ +/* 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 ) +{ + return ctrlReq(addr, ep, bmReqType, bRequest, wValLo, wValHi, wInd, nbytes, nbytes, dataptr, NULL); +} + +//uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, +// uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBREADCALLBACK pf) +//{ +// boolean direction = false; //request direction, IN or OUT +// uint8_t rcode; +// SETUP_PKT setup_pkt; +// +// EpInfo *pep = NULL; +// uint16_t nak_limit; +// +// rcode = SetAddress(addr, ep, &pep, nak_limit); +// +// if (rcode) +// return rcode; +// +// direction = (( bmReqType & 0x80 ) > 0); +// +// /* fill in setup packet */ +// setup_pkt.ReqType_u.bmRequestType = bmReqType; +// setup_pkt.bRequest = bRequest; +// setup_pkt.wVal_u.wValueLo = wValLo; +// setup_pkt.wVal_u.wValueHi = wValHi; +// setup_pkt.wIndex = wInd; +// setup_pkt.wLength = total; +// +// bytesWr( rSUDFIFO, 8, (uint8_t*)&setup_pkt ); //transfer to setup packet FIFO +// +// rcode = dispatchPkt( tokSETUP, ep, nak_limit ); //dispatch packet +// +// if( rcode ) //return HRSLT if not zero +// return( rcode ); +// +// if( dataptr != NULL ) //data stage, if present +// { +// if( direction ) //IN transfer +// { +// uint16_t left = total; +// +// while (left) +// { +// pep->bmRcvToggle = 1; //bmRCVTOG1; +// rcode = InTransfer( pep, nak_limit, nbytes, dataptr ); +// +// // Bytes read into buffer +// uint16_t read = (left < nbytes) ? left : nbytes; +// +// // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified +// if (!rcode && pf) +// pf( read, dataptr, total - left ); +// +// left -= read; +// } +// } +// else //OUT transfer +// { +// pep->bmSndToggle = 1; //bmSNDTOG1; +// rcode = OutTransfer( pep, nak_limit, nbytes, dataptr ); +// } +// if( rcode ) //return error +// return( rcode ); +// } +// // Status stage +// return dispatchPkt( (direction) ? tokOUTHS : tokINHS, ep, nak_limit ); //GET if direction +//} + +uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, + uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, UsbReadParser *p) +{ + boolean direction = false; //request direction, IN or OUT + uint8_t rcode; + SETUP_PKT setup_pkt; + + EpInfo *pep = NULL; + uint16_t nak_limit; + + rcode = SetAddress(addr, ep, &pep, nak_limit); + + if (rcode) + return rcode; + + direction = (( bmReqType & 0x80 ) > 0); + + /* fill in setup packet */ + setup_pkt.ReqType_u.bmRequestType = bmReqType; + setup_pkt.bRequest = bRequest; + setup_pkt.wVal_u.wValueLo = wValLo; + setup_pkt.wVal_u.wValueHi = wValHi; + setup_pkt.wIndex = wInd; + setup_pkt.wLength = total; + + bytesWr( rSUDFIFO, 8, (uint8_t*)&setup_pkt ); //transfer to setup packet FIFO + + rcode = dispatchPkt( tokSETUP, ep, nak_limit ); //dispatch packet + + if( rcode ) //return HRSLT if not zero + return( rcode ); + + if( dataptr != NULL ) //data stage, if present + { + if( direction ) //IN transfer + { + uint16_t left = total; + + while (left) + { + pep->bmRcvToggle = 1; //bmRCVTOG1; + rcode = InTransfer( pep, nak_limit, nbytes, dataptr ); + + // Bytes read into buffer + uint16_t read = (left < nbytes) ? left : nbytes; + + // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified + if (!rcode && p) + p->Parse( read, dataptr, total - left ); + + left -= read; + } + } + else //OUT transfer + { + pep->bmSndToggle = 1; //bmSNDTOG1; + rcode = OutTransfer( pep, nak_limit, nbytes, dataptr ); + } + if( rcode ) //return error + return( rcode ); + } + // Status stage + return dispatchPkt( (direction) ? tokOUTHS : tokINHS, ep, nak_limit ); //GET if direction +} + +/* 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' */ +/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, + fe USB xfer timeout */ +uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ) +{ + EpInfo *pep = NULL; + uint16_t nak_limit = 0; + + uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit); + + if (rcode) + return rcode; + + return InTransfer(pep, nak_limit, nbytes, data); +} + +uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t* data ) +{ + uint8_t rcode; + uint8_t pktsize; + + uint8_t maxpktsize = pep->maxPktSize; unsigned int xfrlen = 0; - regWr( rHCTL, pep->rcvToggle ); //set toggle value + regWr( rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0 ); //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. + rcode = dispatchPkt( tokIN, pep->epAddr, nak_limit ); //IN packet to EP-'endpoint'. Function takes care of NAKS. if( rcode ) return( rcode ); //should be 0, indicating ACK. Else return error code. @@ -232,57 +289,46 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* /* 2. 'nbytes' have been transferred. */ if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) // have we transferred 'nbytes' bytes? { - if( regRd( rHRSL ) & bmRCVTOGRD ) //save toggle value - pep->rcvToggle = bmRCVTOG1; - else - pep->rcvToggle = bmRCVTOG0; + // Save toggle value + pep->bmRcvToggle = ( regRd( rHRSL ) & bmRCVTOGRD ) ? 1 : 0; 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 */ /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */ /* 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 USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ) { - 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; + EpInfo *pep = NULL; + uint16_t nak_limit; - UsbDevice *p = addrPool.GetUsbDevicePtr(addr); + uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit); - if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + if (rcode) + return rcode; - EP_RECORD *pep = p->epinfo + ep; + return OutTransfer(pep, nak_limit, nbytes, data); +} - if (!p->epinfo) - return USB_ERROR_EPINFO_IS_NULL; +uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t *data) +{ + uint8_t rcode, retry_count; + uint8_t *data_p = data; //local copy of the data pointer + uint16_t bytes_tosend, nak_count; + uint16_t bytes_left = nbytes; -/////////////////////////////////////////////////////////////////////////// - regWr( rPERADDR, addr ); //set peripheral address - - //uint8_t mode = regRd( rMODE ); - - //if (p->lowspeed) - // regWr( rMODE, mode | bmHUBPRE ); //set HUBPRE = 1 for low speed devices - //else - // regWr( rMODE, mode & ~bmHUBPRE ); //set HUBPRE = 0 for full speed devices - -/////////////////////////////////////////////////////////////////////////// - - uint8_t maxpktsize = pep->MaxPktSize; + uint8_t maxpktsize = pep->maxPktSize; + + if (maxpktsize < 1 || maxpktsize > 64) + return USB_ERROR_INVALID_MAX_PKT_SIZE; unsigned long timeout = millis() + USB_XFER_TIMEOUT; - if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64 - return 0xFE; - } - - regWr( rHCTL, pep->sndToggle ); //set toggle value + regWr( rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0 ); //set toggle value while( bytes_left ) { @@ -291,7 +337,7 @@ uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t 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 + regWr( rHXFR, ( tokOUT | pep->epAddr )); //dispatch packet while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ rcode = ( regRd( rHRSL ) & 0x0f ); @@ -301,26 +347,24 @@ uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t switch( rcode ) { case hrNAK: - nak_count++; - if( nak_limit && ( nak_count == USB_NAK_LIMIT )) - { - return( rcode); //return NAK - } + nak_count ++; + if( nak_limit && ( nak_count == nak_limit )) + return( rcode ); break; case hrTIMEOUT: - retry_count++; - if( retry_count == USB_RETRY_LIMIT ) { - return( rcode ); //return TIMEOUT - } + retry_count ++; + if( retry_count == USB_RETRY_LIMIT ) + return( rcode ); break; - default: + default: return( rcode ); - } //switch( 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 + regWr( rHXFR, ( tokOUT | pep->epAddr )); //dispatch packet while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ rcode = ( regRd( rHRSL ) & 0x0f ); @@ -328,7 +372,7 @@ uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t bytes_left -= bytes_tosend; data_p += bytes_tosend; }//while( bytes_left... - pep->sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0; //update toggle + pep->bmSndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? 1 : 0; //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 */ @@ -336,77 +380,87 @@ uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t /* If nak_limit == 0, do not count NAKs, exit after timeout */ /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */ /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */ -uint8_t USB::dispatchPkt( uint8_t token, uint8_t ep, unsigned int nak_limit ) +uint8_t USB::dispatchPkt( uint8_t token, uint8_t ep, uint16_t nak_limit ) { - unsigned long timeout = millis() + USB_XFER_TIMEOUT; - uint8_t tmpdata; - uint8_t rcode; - unsigned int nak_count = 0; - char retry_count = 0; + unsigned long timeout = millis() + USB_XFER_TIMEOUT; + uint8_t tmpdata; + uint8_t rcode; + uint8_t retry_count = 0; + uint16_t nak_count = 0; - while( timeout > millis() ) { - regWr( rHXFR, ( token|ep )); //launch the transfer - rcode = 0xff; - while( millis() < timeout ) { //wait for transfer completion - tmpdata = regRd( rHIRQ ); - if( tmpdata & bmHXFRDNIRQ ) { - regWr( rHIRQ, bmHXFRDNIRQ ); //clear the interrupt - rcode = 0x00; - break; - }//if( tmpdata & bmHXFRDNIRQ - }//while ( millis() < timeout - if( rcode != 0x00 ) { //exit if timeout - return( rcode ); - } - rcode = ( regRd( rHRSL ) & 0x0f ); //analyze transfer result - switch( rcode ) { - case hrNAK: - nak_count ++; - if( nak_limit && ( nak_count == nak_limit )) { - return( rcode ); - } - break; - case hrTIMEOUT: - retry_count ++; - if( retry_count == USB_RETRY_LIMIT ) { - return( rcode ); - } - break; - default: - return( rcode ); - }//switch( rcode - }//while( timeout > millis() - return( rcode ); + while( timeout > millis() ) + { + regWr( rHXFR, ( token|ep )); //launch the transfer + rcode = 0xff; + + while( millis() < timeout ) //wait for transfer completion + { + tmpdata = regRd( rHIRQ ); + + if( tmpdata & bmHXFRDNIRQ ) + { + regWr( rHIRQ, bmHXFRDNIRQ ); //clear the interrupt + rcode = 0x00; + break; + }//if( tmpdata & bmHXFRDNIRQ + + }//while ( millis() < timeout + + if( rcode != 0x00 ) //exit if timeout + return( rcode ); + + rcode = ( regRd( rHRSL ) & 0x0f ); //analyze transfer result + + switch( rcode ) + { + case hrNAK: + nak_count ++; + if( nak_limit && ( nak_count == nak_limit )) + return( rcode ); + break; + case hrTIMEOUT: + retry_count ++; + if( retry_count == USB_RETRY_LIMIT ) + return( rcode ); + break; + default: + return( rcode ); + }//switch( rcode + + }//while( timeout > millis() + return( rcode ); } + /* USB main task. Performs enumeration/cleanup */ void USB::Task( void ) //USB state machine { - uint8_t i; - uint8_t rcode; - static uint8_t tmpaddr; - uint8_t tmpdata; - static unsigned long delay = 0; - USB_DEVICE_DESCRIPTOR buf; + uint8_t rcode; + uint8_t tmpdata; + static unsigned long delay = 0; + USB_DEVICE_DESCRIPTOR buf; + bool lowspeed = false; - //MAX3421E::Task(); + MAX3421E::Task(); tmpdata = getVbusState(); - /* modify USB task state if Vbus changed */ + /* modify USB task state if Vbus changed */ switch( tmpdata ) { case SE1: //illegal state usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; + lowspeed = false; break; case SE0: //disconnected - if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) { + if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; - } + lowspeed = false; break; - case FSHOST: //attached case LSHOST: - //Serial.println("FSHOST"); - if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) { + lowspeed = true; + case FSHOST: //attached + if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) + { delay = millis() + USB_SETTLE_DELAY; usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; } @@ -414,45 +468,32 @@ void USB::Task( void ) //USB state machine }// switch( tmpdata for (uint8_t i=0; iPoll(); - } - } //for switch( usb_task_state ) { case USB_DETACHED_SUBSTATE_INITIALIZE: - Serial.println("INIT"); init(); + for (uint8_t i=0; iRelease(); - } - } //for - usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; + + 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() ) { + if( delay < millis() ) usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; - } break; case USB_ATTACHED_SUBSTATE_RESET_DEVICE: - //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: - //Serial.println("RCOMP"); if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) { tmpdata = regRd( rMODE ) | bmSOFKAENAB; //start SOF generation @@ -462,32 +503,14 @@ void USB::Task( void ) //USB state machine } 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_STATE_CONFIGURING; - //usb_task_state = USB_STATE_ADDRESSING; - //usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE; - } + if( regRd( rHIRQ ) & bmFRAMEIRQ ) //when first SOF received we can continue + { + if( delay < millis() ) //20ms passed + usb_task_state = USB_STATE_CONFIGURING; } break; - case USB_STATE_ADDRESSING: - Serial.println("ADR"); - - //rcode = Addressing(0, 0, &tmpaddr); - - //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(0, 0); + rcode = Configuring(0, 0, lowspeed); if (rcode) { @@ -501,39 +524,42 @@ void USB::Task( void ) //USB state machine usb_task_state = USB_STATE_RUNNING; break; case USB_STATE_RUNNING: - //Serial.println("RUN"); break; case USB_STATE_ERROR: break; } // switch( usb_task_state ) } -uint8_t USB::DefaultAddressing() +uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t buf[12]; uint8_t rcode; - UsbDevice *p = NULL; - - Serial.println("Dfl"); + UsbDevice *p0 = NULL, *p = NULL; // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); + p0 = addrPool.GetUsbDevicePtr(0); - if (!p) + if (!p0) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - if (!p->epinfo) - { - Serial.println("epinfo"); + if (!p0->epinfo) return USB_ERROR_EPINFO_IS_NULL; - } + + p0->lowspeed = (lowspeed) ? true : false; // Allocate new address according to device class - uint8_t bAddress = addrPool.AllocAddress(0, false, 0); + uint8_t bAddress = addrPool.AllocAddress(parent, false, port); if (!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + // Assign new address to the device rcode = setAddr( 0, 0, bAddress ); @@ -541,17 +567,12 @@ uint8_t USB::DefaultAddressing() { addrPool.FreeAddress(bAddress); bAddress = 0; - Serial.print("setAddr:"); - Serial.println(rcode, HEX); return rcode; } - - Serial.print("Addr:"); - Serial.println(bAddress, HEX); return 0; }; -uint8_t USB::Configuring(uint8_t parent, uint8_t port) +uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) { static uint8_t dev_index = 0; uint8_t rcode = 0; @@ -561,7 +582,7 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port) if (!devConfig[devConfigIndex]) continue; - rcode = devConfig[devConfigIndex]->Init(parent, port); + rcode = devConfig[devConfigIndex]->Init(parent, port, lowspeed); if (!rcode) { @@ -581,324 +602,42 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port) } // if we get here that means that the device class is not supported by any of registered classes devConfigIndex = 0; - rcode = DefaultAddressing(); - if (rcode) - Serial.println("Dfl fail"); + rcode = DefaultAddressing(parent, port, lowspeed); return rcode; } -//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::ReleaseDevice(uint8_t addr) +{ + if (!addr) + return 0; + for (uint8_t i=0; iGetAddress() == addr) + return devConfig[i]->Release(); +} 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; + return SetPortFeature(addr, 0, HUB_FEATURE_PORT_POWER, port, 0); } 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; + return SetPortFeature(addr, 0, HUB_FEATURE_PORT_RESET, port, 0); } 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; + return ClearPortFeature(addr, 0, bm_features, port, 0); } -#if 0 -// Hub Polling -uint8_t USB::PollHub() -{ - uint8_t rcode; - uint8_t buf[8]; +//void USB::PrintHubStatus(/*USB *usbptr,*/ uint8_t addr) +//{ +// uint8_t buf[4]; +// +// return /*usbptr->*/GetHubStatus(addr, 0, 4, (uint8_t*)&buf); +// +//} -// 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(""); -} - - -#if !defined( USB_METHODS_INLINE ) -//get device descriptor - 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 - 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 - 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 ) { - return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr, nak_limit )); -} -//set address - uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr, unsigned int nak_limit ) { - return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL, nak_limit )); -} -//set configuration - uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL, nak_limit )); -} -//class requests - uint8_t USB::setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL, nak_limit )); -} - uint8_t USB::getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit )); -} -//get HID report descriptor - uint8_t USB::getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit )); -} - uint8_t USB::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 ) { - return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit )); -} - uint8_t USB::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 ) { // ** RI 04/11/09 - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit )); -} -/* returns one byte of data in dataptr */ - uint8_t USB::getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit )); -} - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 // !defined(USB_METHODS_INLINE) \ No newline at end of file diff --git a/Usb.h b/Usb.h index 126e3c5a..9f96efe5 100644 --- a/Usb.h +++ b/Usb.h @@ -138,32 +138,26 @@ #define USB_ERROR_EPINFO_IS_NULL 0xD6 #define USB_ERROR_INVALID_ARGUMENT 0xD7 #define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD8 - -//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_ERROR_INVALID_MAX_PKT_SIZE 0xD9 +#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDA class USBDeviceConfig { public: - virtual uint8_t Init(uint8_t parent, uint8_t port) = 0; + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) = 0; virtual uint8_t Release() = 0; virtual uint8_t Poll() = 0; + virtual uint8_t GetAddress() = 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 USB_NUMDEVICES 64 //number of USB devices +#define HUB_MAX_HUBS 7 // 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 */ @@ -208,12 +202,12 @@ typedef struct { unsigned int wLength; // 6 Depends on bRequest } SETUP_PKT, *PSETUP_PKT; -/* device record structure */ -typedef struct -{ - EP_RECORD *epinfo; //device endpoint information - uint8_t devclass; //device class -} DEV_RECORD; +///* device record structure */ +//typedef struct +//{ +// EpInfo *epinfo; //device endpoint information +// uint8_t devclass; //device class +//} DEV_RECORD; struct HubDescriptor @@ -237,30 +231,30 @@ struct HubDescriptor }; +// Base class for incomming data parser +class UsbReadParser +{ +public: + virtual void Parse(const uint8_t len, const uint8_t *pbuf, const uint16_t &offset) = 0; +}; + //typedef MAX3421e MAX3421E; // Black Widdow typedef MAX3421e MAX3421E; // Duemielanove class USB : public MAX3421E { -//data structures -/* device table. Filled during enumeration */ -/* index corresponds to device address */ -/* each entry contains pointer to endpoint structure */ -/* and device class to use in various places */ -//DEV_RECORD devtable[ USB_NUMDEVICES + 1 ]; -//EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device - -//byte usb_task_state; - - AddressPoolImpl addrPool; USBDeviceConfig* devConfig[USB_NUMDEVICES]; uint8_t devConfigIndex; + uint8_t bmHubPre; public: USB( void ); + void SetHubPreMask() { bmHubPre |= bmHUBPRE; }; + void ResetHubPreMask() { bmHubPre &= (~bmHUBPRE); }; + AddressPool& GetAddressPool() { return (AddressPool&)addrPool; @@ -284,163 +278,156 @@ class USB : public MAX3421E uint8_t getUsbTaskState( void ); void setUsbTaskState( uint8_t state ); - EP_RECORD* getDevTableEntry( uint8_t addr, uint8_t ep ); - uint8_t setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr ); + EpInfo* getEpInfoEntry( uint8_t addr, uint8_t ep ); + uint8_t setEpInfoEntry( uint8_t addr, uint8_t epcount, EpInfo* 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 ); + 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); /* 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 ); - uint8_t setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr, unsigned int nak_limit = USB_NAK_LIMIT ); - uint8_t setConf( uint8_t addr, uint8_t ep, uint8_t conf_value, unsigned int nak_limit = USB_NAK_LIMIT ); + uint8_t getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ); + uint8_t getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr ); + uint8_t getStrDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t index, unsigned int langid, uint8_t* dataptr ); + uint8_t setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr ); + uint8_t setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ); /**/ - uint8_t setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol, unsigned int nak_limit = USB_NAK_LIMIT ); - 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 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 ); + uint8_t setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol ); + uint8_t getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr ); + uint8_t getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ); + 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 ); + 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 ); + uint8_t getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr ); + uint8_t setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration ); /**/ - uint8_t ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT ); - uint8_t ctrlStatus( uint8_t ep, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT ); - 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 ); + uint8_t ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction ); + uint8_t ctrlStatus( uint8_t ep, boolean direction, uint16_t nak_limit ); + uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ); + uint8_t outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ); + uint8_t dispatchPkt( uint8_t token, uint8_t ep, uint16_t 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 ClearHubFeature( uint8_t addr, uint8_t ep, uint8_t fid ); + uint8_t ClearPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel = 0 ); + uint8_t GetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t index, uint16_t nbytes, uint8_t *dataptr ); + uint8_t GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr ); + uint8_t GetPortStatus( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr ); + uint8_t SetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr ); + uint8_t SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid ); + uint8_t SetPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel = 0 ); 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 DefaultAddressing(); - - uint8_t Configuring(uint8_t parent, uint8_t port); + uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t ReleaseDevice(uint8_t addr); + //typedef void (*USBREADCALLBACK)(uint16_t nbytes, uint8_t *data, uint16_t offset); + + //uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, + // uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBREADCALLBACK pf); + + uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, + uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, UsbReadParser *p); + private: void init(); + uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit); + uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t *data); + uint8_t InTransfer (EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t* data); }; -#if defined(USB_METHODS_INLINE) +//#if defined(USB_METHODS_INLINE) //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 )); +inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ) { + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr )); } //get configuration descriptor -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 )); +inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr ) { + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr )); } //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 ) { - return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr, nak_limit )); +inline uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, unsigned int nuint8_ts, uint8_t index, unsigned int langid, uint8_t* dataptr ) { + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr )); } //set address -inline uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr, unsigned int nak_limit ) { - return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL, nak_limit )); +inline uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr ) { + return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL )); } //set configuration -inline uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL, nak_limit )); +inline uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ) { + return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL )); } //class requests -inline uint8_t USB::setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL, nak_limit )); +inline uint8_t USB::setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol ) { + return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL )); } -inline uint8_t USB::getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit )); +inline uint8_t USB::getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr ) { + return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr )); } //get HID report descriptor -inline uint8_t USB::getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit )); +inline uint8_t USB::getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ) { + return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr )); } -inline uint8_t USB::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 ) { - return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit )); +inline uint8_t USB::setReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr ) { + return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr )); } -inline uint8_t USB::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 ) { // ** RI 04/11/09 - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit )); +inline uint8_t USB::getReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr ) { + return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr )); } /* returns one byte of data in dataptr */ -inline uint8_t USB::getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, unsigned int nak_limit ) { - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit )); +inline uint8_t USB::getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr ) { + return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr )); } -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 )); +inline uint8_t USB::setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration ) { + return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL )); } -// 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 ) +inline uint8_t USB::ClearHubFeature( uint8_t addr, uint8_t ep, uint8_t fid ) { - return( ctrlReq( addr, ep, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, NULL, nak_limit )); + return( ctrlReq( addr, ep, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, NULL )); } // 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 ) +inline uint8_t USB::ClearPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel ) { - return( ctrlReq( addr, ep, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, NULL, nak_limit )); + return( ctrlReq( addr, ep, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, NULL )); } // 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 ) +inline uint8_t USB::GetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t index, uint16_t nbytes, uint8_t *dataptr ) { - return( ctrlReq( addr, ep, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, dataptr, nak_limit )); + return( ctrlReq( addr, ep, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, dataptr )); } // Get Hub Status -inline uint8_t USB::GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit ) +inline uint8_t USB::GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr ) { - return( ctrlReq( addr, ep, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, dataptr, nak_limit )); + return( ctrlReq( addr, ep, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, dataptr )); } // 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 ) +inline uint8_t USB::GetPortStatus( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr ) { - //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 )); + return( ctrlReq( addr, ep, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, dataptr )); } // 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 ) +inline uint8_t USB::SetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr ) { - return( ctrlReq( addr, ep, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, dataptr, nak_limit )); + return( ctrlReq( addr, ep, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, dataptr )); } // Set Hub Feature -inline uint8_t USB::SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit ) +inline uint8_t USB::SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid ) { - return( ctrlReq( addr, ep, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, NULL, nak_limit )); + return( ctrlReq( addr, ep, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, NULL )); } // 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 ) +inline uint8_t USB::SetPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel ) { - return( ctrlReq( addr, ep, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, NULL, nak_limit )); + return( ctrlReq( addr, ep, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, NULL )); } -#endif // defined(USB_METHODS_INLINE) +//#endif // defined(USB_METHODS_INLINE) #endif //_usb_h_ \ No newline at end of file diff --git a/address.h b/address.h index f4e689ed..75b6a58c 100644 --- a/address.h +++ b/address.h @@ -4,19 +4,25 @@ #include #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; +#define USB_NAK_MAX_POWER 15 //NAK binary order maximum value + +struct EpInfo +{ + uint8_t epAddr; // Endpoint address + uint8_t maxPktSize; // Maximum packet size + + union + { + uint8_t epAttribs; + + struct + { + uint8_t bmSndToggle : 1; // Send toggle, when zerro bmSNDTOG0, bmSNDTOG1 otherwise + uint8_t bmRcvToggle : 1; // Send toggle, when zerro bmRCVTOG0, bmRCVTOG1 otherwise + uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value + }; + }; +}; // 7 6 5 4 3 2 1 0 // --------------------------------- @@ -48,10 +54,11 @@ struct UsbDeviceAddress struct UsbDevice { - EP_RECORD *epinfo; // endpoint info pointer + EpInfo *epinfo; // endpoint info pointer uint8_t address; // address + uint8_t epcount; // number of endpoints bool lowspeed; // indicates if a device is the low speed one - uint8_t devclass; // device class +// uint8_t devclass; // device class }; class AddressPool @@ -70,7 +77,7 @@ typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev); template class AddressPoolImpl : public AddressPool { - EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device + EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device uint8_t hubCounter; // hub counter is kept // in order to avoid hub address duplication @@ -81,6 +88,7 @@ class AddressPoolImpl : public AddressPool void InitEntry(uint8_t index) { thePool[index].address = 0; + thePool[index].epcount = 1; thePool[index].lowspeed = 0; thePool[index].epinfo = &dev0ep; }; @@ -141,9 +149,9 @@ public: 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; + dev0ep.maxPktSize = 8; + dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0 + dev0ep.bmNakPower = USB_NAK_MAX_POWER; InitAllAddresses(); }; @@ -171,20 +179,28 @@ public: // Allocates new address virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { + if (parent != 0 && port == 0) + Serial.println("PRT: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; + if (is_hub) + { + thePool[index].address = 0x41; + hubCounter ++; + } + else + thePool[index].address = 1; + return thePool[index].address; } @@ -204,6 +220,13 @@ public: } thePool[index].address = *((uint8_t*)&addr); + Serial.print("Addr:"); + Serial.print(addr.bmHub, HEX); + Serial.print("."); + Serial.print(addr.bmParent, HEX); + Serial.print("."); + Serial.println(addr.bmAddress, HEX); + return thePool[index].address; }; // Empties pool entry @@ -220,20 +243,20 @@ public: }; // 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; + //uint8_t GetNumHubs() + //{ + // return hubCounter; + //}; + //uint8_t GetNumDevices() + //{ + // uint8_t counter = 0; - for (uint8_t i=1; i - -#ifdef PORTA -#define USE_PORTA -#endif -#ifdef PORTB -#define USE_PORTB -#endif -#ifdef PORTC -#define USE_PORTC -#endif -#ifdef PORTD -#define USE_PORTD -#endif -#ifdef PORTE -#define USE_PORTE -#endif -#ifdef PORTF -#define USE_PORTF -#endif -#ifdef PORTG -#define USE_PORTG -#endif -#ifdef PORTH -#define USE_PORTH -#endif -#ifdef PORTJ -#define USE_PORTJ -#endif -#ifdef PORTK -#define USE_PORTK -#endif -#ifdef PORTQ -#define USE_PORTQ -#endif -#ifdef PORTR -#define USE_PORTR -#endif - -#ifdef TCCR0A -#define USE_TCCR0A -#endif -#ifdef TCCR1A -#define USE_TCCR1A -#endif -#ifdef TCCR2A -#define USE_TCCR2A -#endif - -//Port definitions for AtTiny, AtMega families. - -#define MAKE_PORT(portName, ddrName, pinName, className, ID) \ - class className{\ - public:\ - typedef uint8_t DataT;\ - public:\ - static void Write(DataT value){portName = value;}\ - static void ClearAndSet(DataT clearMask, DataT value){portName = (portName & ~clearMask) | value;}\ - static DataT Read(){return portName;}\ - static void DirWrite(DataT value){ddrName = value;}\ - static DataT DirRead(){return ddrName;}\ - static void Set(DataT value){portName |= value;}\ - static void Clear(DataT value){portName &= ~value;}\ - static void Toggle(DataT value){portName ^= value;}\ - static void DirSet(DataT value){ddrName |= value;}\ - static void DirClear(DataT value){ddrName &= ~value;}\ - static void DirToggle(DataT value){ddrName ^= value;}\ - static DataT PinRead(){return pinName;}\ - enum{Id = ID};\ - enum{Width=sizeof(DataT)*8};\ - }; - -// TCCR registers to set/clear Arduino PWM -#define MAKE_TCCR(TccrName, className) \ - class className{\ - public:\ - typedef uint8_t DataT;\ - public:\ - static void Write(DataT value){TccrName = value;}\ - static void ClearAndSet(DataT clearMask, DataT value){TccrName = (TccrName & ~clearMask) | value;}\ - static DataT Read(){return TccrName;}\ - static void Set(DataT value){TccrName |= value;}\ - static void Clear(DataT value){TccrName &= ~value;}\ - static void Toggle(DataT value){TccrName ^= value;}\ - enum{Width=sizeof(DataT)*8};\ - }; - -#ifdef USE_PORTA -MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A') -#endif -#ifdef USE_PORTB -MAKE_PORT(PORTB, DDRB, PINB, Portb, 'B') -#endif -#ifdef USE_PORTC -MAKE_PORT(PORTC, DDRC, PINC, Portc, 'C') -#endif -#ifdef USE_PORTD -MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D') -#endif -#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) -#endif -#ifdef USE_TCCR1A -MAKE_TCCR(TCCR1A, Tccr1a) -#endif -#ifdef USE_TCCR2A -MAKE_TCCR(TCCR2A, Tccr2a) -#endif - - // this class represents one pin in a IO port. - // It is fully static. - template - class TPin - { -// BOOST_STATIC_ASSERT(PIN < PORT::Width); - public: - typedef PORT Port; - enum{Number = PIN}; - - static void Set() { PORT::Set(1 << PIN); } - - static void Set(uint8_t val){ - if(val) - Set(); - else Clear();} - - static void SetDir(uint8_t val){ - if(val) - SetDirWrite(); - else SetDirRead();} - - static void Clear(){PORT::Clear(1 << PIN);} - - static void Toggle(){PORT::Toggle(1 << PIN);} - - static void SetDirRead(){PORT::DirClear(1 << PIN);} - - static void SetDirWrite(){PORT::DirSet(1 << PIN);} - - static uint8_t IsSet(){return PORT::PinRead() & (uint8_t)(1 << PIN);} - - static void WaiteForSet(){ while(IsSet()==0){} } - - static void WaiteForClear(){ while(IsSet()){} } - }; //class TPin... - - // this class represents one bit in TCCR port. - // used to set/clear TCCRx bits - // It is fully static. - template - class TCom - { -// BOOST_STATIC_ASSERT(PIN < PORT::Width); - public: - typedef TCCR Tccr; - enum{Com = COM}; - - static void Set() { TCCR::Set(1 << COM); } - - static void Clear() { TCCR::Clear(1 << COM); } - - static void Toggle() { TCCR::Toggle(1 << COM); } - }; //class TCom... - -//Short pin definitions -#ifdef USE_PORTA -typedef TPin Pa0; -typedef TPin Pa1; -typedef TPin Pa2; -typedef TPin Pa3; -typedef TPin Pa4; -typedef TPin Pa5; -typedef TPin Pa6; -typedef TPin Pa7; -#endif - -#ifdef USE_PORTB -typedef TPin Pb0; -typedef TPin Pb1; -typedef TPin Pb2; -typedef TPin Pb3; -typedef TPin Pb4; -typedef TPin Pb5; -typedef TPin Pb6; -typedef TPin Pb7; -#endif - -#ifdef USE_PORTC -typedef TPin Pc0; -typedef TPin Pc1; -typedef TPin Pc2; -typedef TPin Pc3; -typedef TPin Pc4; -typedef TPin Pc5; -typedef TPin Pc6; -typedef TPin Pc7; -#endif - -#ifdef USE_PORTD -typedef TPin Pd0; -typedef TPin Pd1; -typedef TPin Pd2; -typedef TPin Pd3; -typedef TPin Pd4; -typedef TPin Pd5; -typedef TPin Pd6; -typedef TPin Pd7; -#endif - -#ifdef USE_PORTE -typedef TPin Pe0; -typedef TPin Pe1; -typedef TPin Pe2; -typedef TPin Pe3; -typedef TPin Pe4; -typedef TPin Pe5; -typedef TPin Pe6; -typedef TPin Pe7; -#endif - -#ifdef USE_PORTF -typedef TPin Pf0; -typedef TPin Pf1; -typedef TPin Pf2; -typedef TPin Pf3; -typedef TPin Pf4; -typedef TPin Pf5; -typedef TPin Pf6; -typedef TPin Pf7; -#endif - -#ifdef USE_PORTG -typedef TPin Pg0; -typedef TPin Pg1; -typedef TPin Pg2; -typedef TPin Pg3; -typedef TPin Pg4; -typedef TPin Pg5; -typedef TPin Pg6; -typedef TPin Pg7; -#endif - -#ifdef USE_PORTH -typedef TPin Ph0; -typedef TPin Ph1; -typedef TPin Ph2; -typedef TPin Ph3; -typedef TPin Ph4; -typedef TPin Ph5; -typedef TPin Ph6; -typedef TPin Ph7; -#endif - -#ifdef USE_PORTJ -typedef TPin Pj0; -typedef TPin Pj1; -typedef TPin Pj2; -typedef TPin Pj3; -typedef TPin Pj4; -typedef TPin Pj5; -typedef TPin Pj6; -typedef TPin Pj7; -#endif - -#ifdef USE_PORTK -typedef TPin Pk0; -typedef TPin Pk1; -typedef TPin Pk2; -typedef TPin Pk3; -typedef TPin Pk4; -typedef TPin Pk5; -typedef TPin Pk6; -typedef TPin Pk7; -#endif - -#ifdef USE_PORTQ -typedef TPin Pq0; -typedef TPin Pq1; -typedef TPin Pq2; -typedef TPin Pq3; -typedef TPin Pq4; -typedef TPin Pq5; -typedef TPin Pq6; -typedef TPin Pq7; -#endif - -#ifdef USE_PORTR -typedef TPin Pr0; -typedef TPin Pr1; -typedef TPin Pr2; -typedef TPin Pr3; -typedef TPin Pr4; -typedef TPin Pr5; -typedef TPin Pr6; -typedef TPin Pr7; -#endif - -#ifdef USE_TCCR0A -typedef TCom Tc0a; //P6 -typedef TCom Tc0b; //P5 -#endif - -#ifdef USE_TCCR1A -typedef TCom Tc1a; //P9 -typedef TCom Tc1b; //P10 -#endif - -#ifdef USE_TCCR2A -typedef TCom Tc2a; //P11 -typedef TCom Tc2b; //P3 -#endif - -template - class Tp_Tc - { - public: - static void SetDir(uint8_t val){ - if(val) - SetDirWrite(); - else SetDirRead(); - } - static void SetDirRead(){ - Tp_pin::SetDirRead(); //set pin direction - Tc_bit::Clear(); //disconnect pin from PWM - } - static void SetDirWrite(){ - Tp_pin::SetDirWrite(); - Tc_bit::Clear(); - } - }; - -/* pin definitions for cases where it's necessary to clear compare output mode bits */ - -//typedef Tp_Tc P3; //Arduino pin 3 -//typedef Tp_Tc P5; //Arduino pin 5 -//typedef Tp_Tc P6; //Arduino pin 6 -//typedef Tp_Tc P9; //Arduino pin 9 -//typedef Tp_Tc P10; //Arduino pin 10 -//typedef Tp_Tc P11; //Arduino pin 11 - -/* 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 -#define P2 Pd2 -#define P3 Pd3 -#define P4 Pd4 -#define P5 Pd5 -#define P6 Pd6 -#define P7 Pd7 - -#define P8 Pb0 -#define P9 Pb1 -#define P10 Pb2 -#define P11 Pb3 -#define P12 Pb4 -#define P13 Pb5 - -#define P14 Pc0 -#define P15 Pc1 -#define P16 Pc2 -#define P17 Pc3 -#define P18 Pc4 -#define P19 Pc5 - -#endif - +/* copied from Konstantin Chizhov's AVR port templates */ + +#ifndef _avrpins_h_ +#define _avrpins_h_ + +//#include "WProgram.h" +#include + +#ifdef PORTA +#define USE_PORTA +#endif +#ifdef PORTB +#define USE_PORTB +#endif +#ifdef PORTC +#define USE_PORTC +#endif +#ifdef PORTD +#define USE_PORTD +#endif +#ifdef PORTE +#define USE_PORTE +#endif +#ifdef PORTF +#define USE_PORTF +#endif +#ifdef PORTG +#define USE_PORTG +#endif +#ifdef PORTH +#define USE_PORTH +#endif +#ifdef PORTJ +#define USE_PORTJ +#endif +#ifdef PORTK +#define USE_PORTK +#endif +#ifdef PORTQ +#define USE_PORTQ +#endif +#ifdef PORTR +#define USE_PORTR +#endif + +#ifdef TCCR0A +#define USE_TCCR0A +#endif +#ifdef TCCR1A +#define USE_TCCR1A +#endif +#ifdef TCCR2A +#define USE_TCCR2A +#endif + +//Port definitions for AtTiny, AtMega families. + +#define MAKE_PORT(portName, ddrName, pinName, className, ID) \ + class className{\ + public:\ + typedef uint8_t DataT;\ + public:\ + static void Write(DataT value){portName = value;}\ + static void ClearAndSet(DataT clearMask, DataT value){portName = (portName & ~clearMask) | value;}\ + static DataT Read(){return portName;}\ + static void DirWrite(DataT value){ddrName = value;}\ + static DataT DirRead(){return ddrName;}\ + static void Set(DataT value){portName |= value;}\ + static void Clear(DataT value){portName &= ~value;}\ + static void Toggle(DataT value){portName ^= value;}\ + static void DirSet(DataT value){ddrName |= value;}\ + static void DirClear(DataT value){ddrName &= ~value;}\ + static void DirToggle(DataT value){ddrName ^= value;}\ + static DataT PinRead(){return pinName;}\ + enum{Id = ID};\ + enum{Width=sizeof(DataT)*8};\ + }; + +// TCCR registers to set/clear Arduino PWM +#define MAKE_TCCR(TccrName, className) \ + class className{\ + public:\ + typedef uint8_t DataT;\ + public:\ + static void Write(DataT value){TccrName = value;}\ + static void ClearAndSet(DataT clearMask, DataT value){TccrName = (TccrName & ~clearMask) | value;}\ + static DataT Read(){return TccrName;}\ + static void Set(DataT value){TccrName |= value;}\ + static void Clear(DataT value){TccrName &= ~value;}\ + static void Toggle(DataT value){TccrName ^= value;}\ + enum{Width=sizeof(DataT)*8};\ + }; + +#ifdef USE_PORTA +MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A') +#endif +#ifdef USE_PORTB +MAKE_PORT(PORTB, DDRB, PINB, Portb, 'B') +#endif +#ifdef USE_PORTC +MAKE_PORT(PORTC, DDRC, PINC, Portc, 'C') +#endif +#ifdef USE_PORTD +MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D') +#endif +#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) +#endif +#ifdef USE_TCCR1A +MAKE_TCCR(TCCR1A, Tccr1a) +#endif +#ifdef USE_TCCR2A +MAKE_TCCR(TCCR2A, Tccr2a) +#endif + + // this class represents one pin in a IO port. + // It is fully static. + template + class TPin + { +// BOOST_STATIC_ASSERT(PIN < PORT::Width); + public: + typedef PORT Port; + enum{Number = PIN}; + + static void Set() { PORT::Set(1 << PIN); } + + static void Set(uint8_t val){ + if(val) + Set(); + else Clear();} + + static void SetDir(uint8_t val){ + if(val) + SetDirWrite(); + else SetDirRead();} + + static void Clear(){PORT::Clear(1 << PIN);} + + static void Toggle(){PORT::Toggle(1 << PIN);} + + static void SetDirRead(){PORT::DirClear(1 << PIN);} + + static void SetDirWrite(){PORT::DirSet(1 << PIN);} + + static uint8_t IsSet(){return PORT::PinRead() & (uint8_t)(1 << PIN);} + + static void WaiteForSet(){ while(IsSet()==0){} } + + static void WaiteForClear(){ while(IsSet()){} } + }; //class TPin... + + // this class represents one bit in TCCR port. + // used to set/clear TCCRx bits + // It is fully static. + template + class TCom + { +// BOOST_STATIC_ASSERT(PIN < PORT::Width); + public: + typedef TCCR Tccr; + enum{Com = COM}; + + static void Set() { TCCR::Set(1 << COM); } + + static void Clear() { TCCR::Clear(1 << COM); } + + static void Toggle() { TCCR::Toggle(1 << COM); } + }; //class TCom... + +//Short pin definitions +#ifdef USE_PORTA +typedef TPin Pa0; +typedef TPin Pa1; +typedef TPin Pa2; +typedef TPin Pa3; +typedef TPin Pa4; +typedef TPin Pa5; +typedef TPin Pa6; +typedef TPin Pa7; +#endif + +#ifdef USE_PORTB +typedef TPin Pb0; +typedef TPin Pb1; +typedef TPin Pb2; +typedef TPin Pb3; +typedef TPin Pb4; +typedef TPin Pb5; +typedef TPin Pb6; +typedef TPin Pb7; +#endif + +#ifdef USE_PORTC +typedef TPin Pc0; +typedef TPin Pc1; +typedef TPin Pc2; +typedef TPin Pc3; +typedef TPin Pc4; +typedef TPin Pc5; +typedef TPin Pc6; +typedef TPin Pc7; +#endif + +#ifdef USE_PORTD +typedef TPin Pd0; +typedef TPin Pd1; +typedef TPin Pd2; +typedef TPin Pd3; +typedef TPin Pd4; +typedef TPin Pd5; +typedef TPin Pd6; +typedef TPin Pd7; +#endif + +#ifdef USE_PORTE +typedef TPin Pe0; +typedef TPin Pe1; +typedef TPin Pe2; +typedef TPin Pe3; +typedef TPin Pe4; +typedef TPin Pe5; +typedef TPin Pe6; +typedef TPin Pe7; +#endif + +#ifdef USE_PORTF +typedef TPin Pf0; +typedef TPin Pf1; +typedef TPin Pf2; +typedef TPin Pf3; +typedef TPin Pf4; +typedef TPin Pf5; +typedef TPin Pf6; +typedef TPin Pf7; +#endif + +#ifdef USE_PORTG +typedef TPin Pg0; +typedef TPin Pg1; +typedef TPin Pg2; +typedef TPin Pg3; +typedef TPin Pg4; +typedef TPin Pg5; +typedef TPin Pg6; +typedef TPin Pg7; +#endif + +#ifdef USE_PORTH +typedef TPin Ph0; +typedef TPin Ph1; +typedef TPin Ph2; +typedef TPin Ph3; +typedef TPin Ph4; +typedef TPin Ph5; +typedef TPin Ph6; +typedef TPin Ph7; +#endif + +#ifdef USE_PORTJ +typedef TPin Pj0; +typedef TPin Pj1; +typedef TPin Pj2; +typedef TPin Pj3; +typedef TPin Pj4; +typedef TPin Pj5; +typedef TPin Pj6; +typedef TPin Pj7; +#endif + +#ifdef USE_PORTK +typedef TPin Pk0; +typedef TPin Pk1; +typedef TPin Pk2; +typedef TPin Pk3; +typedef TPin Pk4; +typedef TPin Pk5; +typedef TPin Pk6; +typedef TPin Pk7; +#endif + +#ifdef USE_PORTQ +typedef TPin Pq0; +typedef TPin Pq1; +typedef TPin Pq2; +typedef TPin Pq3; +typedef TPin Pq4; +typedef TPin Pq5; +typedef TPin Pq6; +typedef TPin Pq7; +#endif + +#ifdef USE_PORTR +typedef TPin Pr0; +typedef TPin Pr1; +typedef TPin Pr2; +typedef TPin Pr3; +typedef TPin Pr4; +typedef TPin Pr5; +typedef TPin Pr6; +typedef TPin Pr7; +#endif + +#ifdef USE_TCCR0A +typedef TCom Tc0a; //P6 +typedef TCom Tc0b; //P5 +#endif + +#ifdef USE_TCCR1A +typedef TCom Tc1a; //P9 +typedef TCom Tc1b; //P10 +#endif + +#ifdef USE_TCCR2A +typedef TCom Tc2a; //P11 +typedef TCom Tc2b; //P3 +#endif + +template + class Tp_Tc + { + public: + static void SetDir(uint8_t val){ + if(val) + SetDirWrite(); + else SetDirRead(); + } + static void SetDirRead(){ + Tp_pin::SetDirRead(); //set pin direction + Tc_bit::Clear(); //disconnect pin from PWM + } + static void SetDirWrite(){ + Tp_pin::SetDirWrite(); + Tc_bit::Clear(); + } + }; + +/* pin definitions for cases where it's necessary to clear compare output mode bits */ + +//typedef Tp_Tc P3; //Arduino pin 3 +//typedef Tp_Tc P5; //Arduino pin 5 +//typedef Tp_Tc P6; //Arduino pin 6 +//typedef Tp_Tc P9; //Arduino pin 9 +//typedef Tp_Tc P10; //Arduino pin 10 +//typedef Tp_Tc P11; //Arduino pin 11 + +/* 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 +#define P2 Pd2 +#define P3 Pd3 +#define P4 Pd4 +#define P5 Pd5 +#define P6 Pd6 +#define P7 Pd7 + +#define P8 Pb0 +#define P9 Pb1 +#define P10 Pb2 +#define P11 Pb3 +#define P12 Pb4 +#define P13 Pb5 + +#define P14 Pc0 +#define P15 Pc1 +#define P16 Pc2 +#define P17 Pc3 +#define P18 Pc4 +#define P19 Pc5 + +#endif + #endif //_avrpins_h_ diff --git a/max3421e.h b/max3421e.h index b4320886..e39a61f2 100644 --- a/max3421e.h +++ b/max3421e.h @@ -9,8 +9,8 @@ /* pin numbers to port numbers */ //#define MAX_SS 10 -//#define MAX_INT 3 // Black Widdow -#define MAX_INT 9 // Duemielanove +#define MAX_INT 3 // Black Widdow +//#define MAX_INT 9 // Duemielanove #define MAX_GPX 8 //#define MAX_RESET 7 diff --git a/usbhost.h b/usbhost.h index d1fc7b32..46212f31 100644 --- a/usbhost.h +++ b/usbhost.h @@ -249,7 +249,7 @@ uint8_t MAX3421e< SS, INTR >::Task( void ) uint8_t pinvalue; //Serial.print("Vbus state: "); //Serial.println( vbusState, HEX ); - pinvalue = INTR::Read(); + pinvalue = INTR::IsSet(); //Read(); //pinvalue = digitalRead( MAX_INT ); if( pinvalue == LOW ) { rcode = IntHandler(); diff --git a/usbhub.cpp b/usbhub.cpp index 38b9ecfc..0b99fea3 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -1,35 +1,34 @@ #include "usbhub.h" +bool USBHub::bResetInitiated = false; + 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[0].maxPktSize = 8; + epInfo[0].epAttribs = 0; + epInfo[0].bmNakPower = USB_NAK_MAX_POWER; 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; + epInfo[1].maxPktSize = 1; + epInfo[1].epAttribs = 0; if (pUsb) pUsb->RegisterDeviceClass(this); } -uint8_t USBHub::Init(uint8_t parent, uint8_t port) +uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t buf[32]; uint8_t rcode; UsbDevice *p = NULL; - EP_RECORD *oldep_ptr = NULL; + EpInfo *oldep_ptr = NULL; uint8_t len = 0; uint16_t cd_len = 0; @@ -38,8 +37,6 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) switch (bInitState) { case 0: - Serial.println("Init"); - if (bAddress) return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; @@ -50,10 +47,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; if (!p->epinfo) - { - Serial.println("epinfo"); return USB_ERROR_EPINFO_IS_NULL; - } // Save old pointer to EP_RECORD of address 0 oldep_ptr = p->epinfo; @@ -61,9 +55,13 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence p->epinfo = epInfo; + p->lowspeed = lowspeed; + // Get device descriptor rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); + p->lowspeed = false; + if (!rcode) len = (buf[0] > 32) ? 32 : buf[0]; @@ -71,8 +69,6 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) { // Restore p->epinfo p->epinfo = oldep_ptr; - - Serial.println("getDevDesc:"); return rcode; } @@ -88,7 +84,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; // Extract Max Packet Size from the device descriptor - epInfo[0].MaxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + epInfo[0].maxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; // Assign new address to the device rcode = pUsb->setAddr( 0, 0, bAddress ); @@ -99,14 +95,9 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) p->epinfo = oldep_ptr; addrPool.FreeAddress(bAddress); bAddress = 0; - Serial.print("setAddr:"); - Serial.println(rcode, HEX); return rcode; } - Serial.print("Addr:"); - Serial.println(bAddress, HEX); - // Restore p->epinfo p->epinfo = oldep_ptr; @@ -117,7 +108,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) goto FailGetDevDescr; // Assign epInfo to epinfo pointer - rcode = pUsb->setDevTableEntry(bAddress, epInfo); + rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo); if (rcode) goto FailSetDevTblEntry; @@ -159,17 +150,12 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) goto FailGetConfDescr; } - Serial.print("Conf val:"); - Serial.println(buf[5], HEX); - // Set Configuration Value rcode = pUsb->setConf(bAddress, 0, buf[5]); if (rcode) goto FailSetConfDescr; - Serial.println("Hub configured"); - bInitState = 3; case 3: @@ -177,8 +163,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) for (uint8_t j=1; j<=bNbrPorts; j++) pUsb->HubPortPowerOn(bAddress, j); - Serial.println("Ports powered"); - + pUsb->SetHubPreMask(); bPollEnable = true; bInitState = 0; } @@ -186,31 +171,24 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port) 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; } @@ -218,9 +196,11 @@ uint8_t USBHub::Release() { pUsb->GetAddressPool().FreeAddress(bAddress); + if (bAddress == 0x41) + pUsb->SetHubPreMask(); + bAddress = 0; bNbrPorts = 0; -// bPortResetCounter = 0; qNextPollTime = 0; bPollEnable = false; return 0; @@ -235,51 +215,27 @@ uint8_t USBHub::Poll() if (qNextPollTime <= millis()) { - Serial.print("Poll:"); Serial.println(bAddress, HEX); rcode = GetHubStatus(bAddress); - if (rcode) - { - Serial.print("HubStatus:"); - Serial.println(rcode,HEX); - } qNextPollTime = millis() + 100; } 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); + rcode = pUsb->inTransfer(addr, 1, 1, buf); 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); + //pUsb->PrintHubStatus(addr); //rcode = GetHubStatus(1, 0, 1, 4, buf); //if (rcode) //{ @@ -298,91 +254,91 @@ uint8_t USBHub::GetHubStatus(uint8_t addr) 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); + + rcode = HubPortStatusChange(addr, port, evt); + + if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) + return 0; + + if (rcode) + return rcode; } } // for + + for (uint8_t port=1; port<=bNbrPorts; port++) + { + HubEvent evt; + evt.bmEvent = 0; + + rcode = pUsb->GetPortStatus(addr, 0, port, 4, evt.evtBuff); + + if (rcode) + continue; + + if ((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED) + continue; + + // Emulate connection event for the port + evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION; + + rcode = HubPortStatusChange(addr, port, evt); + + if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) + return 0; + + if (rcode) + return rcode; + } // for return 0; } -void USBHub::HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt) +uint8_t 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, true); - 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"); + case bmHUB_PORT_EVENT_LS_CONNECT: + if (bResetInitiated) + return 0; + pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_ENABLE); pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_CONNECTION); pUsb->HubPortReset(addr, port); - break; + bResetInitiated = true; + return HUB_ERROR_PORT_HAS_BEEN_RESET; + + // Device disconnected event + case bmHUB_PORT_EVENT_DISCONNECT: + pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_ENABLE); + pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_CONNECTION); + bResetInitiated = false; + + UsbDeviceAddress a; + a.bmHub = 0; + a.bmParent = addr; + a.bmAddress = port; + pUsb->ReleaseDevice(a.devAddress); + return 0; // Reset complete event case bmHUB_PORT_EVENT_RESET_COMPLETE: - Serial.println("RCMPL"); + case bmHUB_PORT_EVENT_LS_RESET_COMPLETE: pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_RESET | HUB_FEATURE_C_PORT_CONNECTION); - // Check if device is a low-speed device - if (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) - { - UsbDevice *p = pUsb->GetAddressPool().GetUsbDevicePtr(addr); + delay(20); - if (p) - p->lowspeed = true; - } + a.devAddress = addr; - delay(50); - - pUsb->Configuring(addr, port); + pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) ); + bResetInitiated = false; 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) + return 0; } - void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes) { uint8_t rcode = 0; diff --git a/usbhub.h b/usbhub.h index c1bd802e..1a9de648 100644 --- a/usbhub.h +++ b/usbhub.h @@ -19,25 +19,27 @@ #define USB_STATE_HUB_PORT_RESETTING 0xb5 #define USB_STATE_HUB_PORT_ENABLED 0xb6 +// Additional Error Codes +#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1 + // 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) +// Bit mask to check for DISABLED state in HubEvent::bmStatus field +#define bmHUB_PORT_STATE_CHECK_DISABLED (0x0000 | 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) +#define bmHUB_PORT_STATE_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) // Hub Port Events -#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATE_DISABLED) +#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) +#define bmHUB_PORT_EVENT_DISCONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER) #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) +#define bmHUB_PORT_EVENT_LS_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) +#define bmHUB_PORT_EVENT_LS_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 | bmHUB_PORT_STATUS_PORT_LOW_SPEED) +#define bmHUB_PORT_EVENT_LS_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 | bmHUB_PORT_STATUS_PORT_LOW_SPEED) struct HubEvent { @@ -56,50 +58,30 @@ struct HubEvent class USBHub : USBDeviceConfig { + static bool bResetInitiated; // True when reset is triggered + USB *pUsb; // USB class instance pointer - EP_RECORD epInfo[2]; // interrupt endpoint info structure + EpInfo 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); + uint8_t HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt); public: USBHub(USB *p); - virtual uint8_t Init(uint8_t parent, uint8_t port); + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); virtual uint8_t Release(); virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; }; void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); - -// --------------------------------- -// | 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__ \ No newline at end of file