diff --git a/Usb.cpp b/Usb.cpp index 10fcc935..13ce8cbf 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -169,7 +169,12 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* uint8_t rcode; uint8_t pktsize; - //Serial.println("iT"); + Serial.print("iT"); + + Serial.print(" A:"); + Serial.print(addr, HEX); + Serial.print(" E:"); + Serial.print(ep, HEX); UsbDevice *p = addrPool.GetUsbDevicePtr(addr); @@ -181,6 +186,26 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* EP_RECORD *pep = &p->epinfo[ep]; +//////////////////////////////////////////////////////////////////////////////////////// + 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 + +//////////////////////////////////////////////////////////////////////////////////////// + + + Serial.print(" E:"); + Serial.print(pep->epAddr, HEX); + Serial.print(" M:"); + Serial.print(pep->MaxPktSize, HEX); + Serial.print(" T:"); + Serial.println(pep->rcvToggle, HEX); + uint8_t maxpktsize = pep->MaxPktSize; unsigned int xfrlen = 0; @@ -237,6 +262,18 @@ uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t if (!p->epinfo) return USB_ERROR_EPINFO_IS_NULL; +/////////////////////////////////////////////////////////////////////////// + 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; unsigned long timeout = millis() + USB_XFER_TIMEOUT; @@ -388,27 +425,34 @@ void USB::Task( void ) //USB state machine 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; break; case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here - Serial.println("WFD"); + //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"); + //Serial.println("STL"); if( delay < millis() ) { usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; } break; case USB_ATTACHED_SUBSTATE_RESET_DEVICE: - Serial.println("RES"); + //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"); + //Serial.println("RCOMP"); if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) { tmpdata = regRd( rMODE ) | bmSOFKAENAB; //start SOF generation @@ -418,10 +462,11 @@ void USB::Task( void ) //USB state machine } break; case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order - Serial.println("WSOF"); + //Serial.println("WSOF"); if( regRd( rHIRQ ) & bmFRAMEIRQ ) { //when first SOF received we can continue if( delay < millis() ) { //20ms passed - usb_task_state = USB_STATE_ADDRESSING; + usb_task_state = USB_STATE_CONFIGURING; + //usb_task_state = USB_STATE_ADDRESSING; //usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE; } } @@ -429,20 +474,20 @@ void USB::Task( void ) //USB state machine case USB_STATE_ADDRESSING: Serial.println("ADR"); - rcode = Addressing(&tmpaddr); + //rcode = Addressing(0, 0, &tmpaddr); - if (rcode == hrSUCCESS) - usb_task_state = USB_STATE_CONFIGURING; - else - { - usb_error = rcode; - usb_task_state = USB_STATE_ERROR; - } + //if (rcode == hrSUCCESS) + // usb_task_state = USB_STATE_CONFIGURING; + //else + //{ + // usb_error = rcode; + // usb_task_state = USB_STATE_ERROR; + //} break; case USB_STATE_CONFIGURING: Serial.print("CNF"); - rcode = Configuring(tmpaddr); + rcode = Configuring(0, 0); if (rcode) { @@ -456,88 +501,74 @@ void USB::Task( void ) //USB state machine usb_task_state = USB_STATE_RUNNING; break; case USB_STATE_RUNNING: - Serial.println("RUN"); + //Serial.println("RUN"); break; case USB_STATE_ERROR: break; } // switch( usb_task_state ) } -uint8_t USB::Addressing(uint8_t *address) +uint8_t USB::DefaultAddressing() { - uint8_t rcode = hrSUCCESS, buf[8]; + uint8_t buf[12]; + uint8_t rcode; + UsbDevice *p = NULL; - Serial.println("Adrsng"); + Serial.println("Dfl"); - UsbDevice *p = addrPool.GetUsbDevicePtr(0); + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); if (!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; if (!p->epinfo) { Serial.println("epinfo"); return USB_ERROR_EPINFO_IS_NULL; } - Serial.print("addr:"); - Serial.println(p->address, HEX); - Serial.print("ep:"); - Serial.println(p->epinfo->epAddr, HEX); - //p->epinfo->MaxPktSize = 8; + // Allocate new address according to device class + uint8_t bAddress = addrPool.AllocAddress(0, false, 0); - Serial.print("Max:"); - Serial.println(p->epinfo->MaxPktSize, HEX); - - rcode = getDevDescr( 0, 0, 8, (uint8_t*)buf ); - - if( rcode == 0 ) - { - Serial.println("OK!"); - p->epinfo->MaxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - p->devclass = ((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass; - } - else - { - Serial.println("getDevDesc:"); - return rcode; - } - - uint8_t addr = addrPool.AllocAddress(0, (p->devclass == 0x09) ? true : false); - - if (!addr) + if (!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - Serial.print("Addr:"); - Serial.println(addr,HEX); + // Assign new address to the device + rcode = setAddr( 0, 0, bAddress ); - rcode = setAddr( 0, 0, addr ); - - if (!rcode) - { - *address = addr; - } - else + if (rcode) { + addrPool.FreeAddress(bAddress); + bAddress = 0; Serial.print("setAddr:"); Serial.println(rcode, HEX); return rcode; } - return rcode; -} -uint8_t USB::Configuring(uint8_t addr) + Serial.print("Addr:"); + Serial.println(bAddress, HEX); + return 0; +}; + +uint8_t USB::Configuring(uint8_t parent, uint8_t port) { static uint8_t dev_index = 0; - uint8_t rcode = 0, buf[8]; + uint8_t rcode = 0; for (; devConfigIndexInit(addr); + if (!devConfig[devConfigIndex]) + continue; - Serial.println("."); + rcode = devConfig[devConfigIndex]->Init(parent, port); - if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED) + if (!rcode) + { + devConfigIndex = 0; + return 0; + } + if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) { // in case of an error dev_index should be reset to 0 // in order to start from the very beginning the @@ -550,7 +581,12 @@ uint8_t USB::Configuring(uint8_t addr) } // if we get here that means that the device class is not supported by any of registered classes devConfigIndex = 0; - return 0; + rcode = DefaultAddressing(); + + if (rcode) + Serial.println("Dfl fail"); + + return rcode; } //class UsbHub @@ -764,3 +800,105 @@ void USB::PrintHubStatus(/*USB *usbptr,*/ uint8_t addr) 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 7287d8d9..126e3c5a 100644 --- a/Usb.h +++ b/Usb.h @@ -2,6 +2,8 @@ #ifndef _usb_h_ #define _usb_h_ +#define USB_METHODS_INLINE + #include #include "avrpins.h" #include "max3421e.h" @@ -135,13 +137,22 @@ #define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD5 #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; +//}; class USBDeviceConfig { public: - virtual uint8_t Init(uint8_t addr) = 0; - virtual uint8_t Release(uint8_t addr) = 0; - virtual uint8_t Poll() = 0; + virtual uint8_t Init(uint8_t parent, uint8_t port) = 0; + virtual uint8_t Release() = 0; + virtual uint8_t Poll() = 0; }; @@ -250,6 +261,10 @@ class USB : public MAX3421E public: USB( void ); + AddressPool& GetAddressPool() + { + return (AddressPool&)addrPool; + }; uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) { for (uint8_t i=0; i -class AddressPoolImpl +class AddressPoolImpl : public AddressPool { EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device @@ -79,7 +81,7 @@ class AddressPoolImpl void InitEntry(uint8_t index) { thePool[index].address = 0; - thePool[index].devclass = 0; + thePool[index].lowspeed = 0; thePool[index].epinfo = &dev0ep; }; // Returns thePool index for a given address @@ -146,7 +148,7 @@ public: InitAllAddresses(); }; // Returns a pointer to a specified address entry - UsbDevice* GetUsbDevicePtr(uint8_t addr) + virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { if (!addr) return thePool; diff --git a/usbhost.h b/usbhost.h index 91939dfd..d1fc7b32 100644 --- a/usbhost.h +++ b/usbhost.h @@ -209,7 +209,7 @@ int8_t MAX3421e< SS, INTR >::Init() template< typename SS, typename INTR > void MAX3421e< SS, INTR >::busprobe() { - byte bus_sample; + uint8_t bus_sample; bus_sample = regRd( rHRSL ); //Get J,K status bus_sample &= ( bmJSTATUS|bmKSTATUS ); //zero the rest of the byte switch( bus_sample ) { //start full-speed or low-speed host @@ -249,14 +249,15 @@ uint8_t MAX3421e< SS, INTR >::Task( void ) uint8_t pinvalue; //Serial.print("Vbus state: "); //Serial.println( vbusState, HEX ); - pinvalue = digitalRead( MAX_INT ); + pinvalue = INTR::Read(); + //pinvalue = digitalRead( MAX_INT ); if( pinvalue == LOW ) { rcode = IntHandler(); } - pinvalue = digitalRead( MAX_GPX ); - if( pinvalue == LOW ) { - GpxHandler(); - } +// pinvalue = digitalRead( MAX_GPX ); +// if( pinvalue == LOW ) { +// GpxHandler(); +// } // usbSM(); //USB state machine return( rcode ); } @@ -277,17 +278,17 @@ uint8_t MAX3421e< SS, INTR >::IntHandler() regWr( rHIRQ, HIRQ_sendback ); return( HIRQ_sendback ); } -template< typename SS, typename INTR > -uint8_t MAX3421e< SS, INTR >::GpxHandler() -{ - uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register -// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload -// vbusPwr( OFF ); //attempt powercycle -// delay( 1000 ); -// vbusPwr( ON ); -// regWr( rGPINIRQ, bmGPINIRQ7 ); -// } - return( GPINIRQ ); -} +//template< typename SS, typename INTR > +//uint8_t MAX3421e< SS, INTR >::GpxHandler() +//{ +// uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register +//// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload +//// vbusPwr( OFF ); //attempt powercycle +//// delay( 1000 ); +//// vbusPwr( ON ); +//// regWr( rGPINIRQ, bmGPINIRQ7 ); +//// } +// return( GPINIRQ ); +//} #endif //_USBHOST_H_ diff --git a/usbhub.cpp b/usbhub.cpp index dd45a895..38b9ecfc 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -5,47 +5,119 @@ USBHub::USBHub(USB *p) : bAddress(0), bNbrPorts(0), bInitState(0), - bPortResetCounter(1), +// 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].sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0 + epInfo[0].rcvToggle = bmRCVTOG0; epInfo[1].epAddr = 1; epInfo[1].MaxPktSize = 1; epInfo[1].Interval = 0xff; - epInfo[1].sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0 - epInfo[1].rcvToggle = bmRCVTOG0; + epInfo[1].sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0 + epInfo[1].rcvToggle = bmRCVTOG0; if (pUsb) pUsb->RegisterDeviceClass(this); } -uint8_t USBHub::Init(uint8_t addr) +uint8_t USBHub::Init(uint8_t parent, uint8_t port) { - uint8_t buf[8]; - uint8_t rcode; + uint8_t buf[32]; + uint8_t rcode; + UsbDevice *p = NULL; + EP_RECORD *oldep_ptr = NULL; + uint8_t len = 0; + uint16_t cd_len = 0; + + AddressPool &addrPool = pUsb->GetAddressPool(); switch (bInitState) { case 0: Serial.println("Init"); - bAddress = addr; + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - rcode = pUsb->getDevDescr( addr, 0, 8, (uint8_t*)buf ); + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) + { + Serial.println("epinfo"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + // Get device descriptor + rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); + + if (!rcode) + len = (buf[0] > 32) ? 32 : buf[0]; + + if( rcode ) + { + // Restore p->epinfo + p->epinfo = oldep_ptr; + + Serial.println("getDevDesc:"); + return rcode; + } + + // Extract device class from device descriptor + // If device class is not a hub return + if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass != 0x09) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0x09) ? true : false, port); + + if (!bAddress) + 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; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + + if (rcode) + { + // Restore p->epinfo + 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; + + if (len) + rcode = pUsb->getDevDescr( bAddress, 0, len, (uint8_t*)buf ); if(rcode) goto FailGetDevDescr; - // Return if the device is not a hub - if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass != 0x09) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - rcode = pUsb->setDevTableEntry(addr, epInfo); + // Assign epInfo to epinfo pointer + rcode = pUsb->setDevTableEntry(bAddress, epInfo); if (rcode) goto FailSetDevTblEntry; @@ -54,28 +126,44 @@ uint8_t USBHub::Init(uint8_t addr) case 1: // Get hub descriptor - rcode = pUsb->GetHubDescriptor(addr, 0, 0, 8, buf); + rcode = pUsb->GetHubDescriptor(bAddress, 0, 0, 8, buf); if (rcode) goto FailGetHubDescr; // Save number of ports for future use bNbrPorts = ((HubDescriptor*)buf)->bNbrPorts; - + bInitState = 2; case 2: // Read configuration Descriptor in Order To Obtain Proper Configuration Value - rcode = pUsb->getConfDescr(addr, 0, 8, 0, buf); + rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); + if (!rcode) + { + cd_len = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength; + rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf); + } if (rcode) goto FailGetConfDescr; + // The following code is of no practical use in real life applications. + // It only intended for the usb protocol sniffer to properly parse hub-class requests. + { + uint8_t buf2[24]; + + rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2); + + if (rcode) + goto FailGetConfDescr; + } + Serial.print("Conf val:"); Serial.println(buf[5], HEX); // Set Configuration Value - rcode = pUsb->setConf(addr, 0, buf[5]); + rcode = pUsb->setConf(bAddress, 0, buf[5]); if (rcode) goto FailSetConfDescr; @@ -87,49 +175,12 @@ uint8_t USBHub::Init(uint8_t addr) case 3: // Power on all ports for (uint8_t j=1; j<=bNbrPorts; j++) - pUsb->HubPortPowerOn(addr, j); + pUsb->HubPortPowerOn(bAddress, j); Serial.println("Ports powered"); bPollEnable = true; bInitState = 0; -// bInitState = 4; - - //case 4: - // Serial.print("RC:"); - // Serial.println(bPortResetCounter, DEC); - - // for (; bPortResetCounter<=bNbrPorts; bPortResetCounter++) - // { - // HubEvent evt; - // rcode = pUsb->GetPortStatus(addr, 0, bPortResetCounter, 4, evt.evtBuff); - - // if (rcode) - // goto FailGetPortStatus; - - // Serial.print("RC:"); - // Serial.println(bPortResetCounter, DEC); - // Serial.print("\tSt:"); - // Serial.print(evt.bmStatus, BIN); - // Serial.print("\tCh:"); - // Serial.println(evt.bmChange, BIN); - - // // Initiate reset only if there is a device plugged into the port - // if (evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) - // { - // Serial.print("Con:"); - // Serial.println(bPortResetCounter, DEC); - - // pUsb->HubPortReset(addr, bPortResetCounter); - // bPollEnable = true; - // - // if (bPortResetCounter < bNbrPorts) - // bPortResetCounter ++; - - // return USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE; - // } - // } // for -// bPortResetCounter = 1; } bInitState = 0; return 0; @@ -163,11 +214,13 @@ Fail: return rcode; } -uint8_t USBHub::Release(uint8_t addr) +uint8_t USBHub::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; bNbrPorts = 0; - bPortResetCounter = 0; +// bPortResetCounter = 0; qNextPollTime = 0; bPollEnable = false; return 0; @@ -182,7 +235,8 @@ uint8_t USBHub::Poll() if (qNextPollTime <= millis()) { - Serial.println("Poll"); + Serial.print("Poll:"); + Serial.println(bAddress, HEX); rcode = GetHubStatus(bAddress); if (rcode) @@ -190,7 +244,7 @@ uint8_t USBHub::Poll() Serial.print("HubStatus:"); Serial.println(rcode,HEX); } - qNextPollTime = millis() + 10; + qNextPollTime = millis() + 100; } return rcode; } @@ -273,10 +327,10 @@ void USBHub::HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt) //Serial.print("Con:"); //Serial.println(bmHUB_PORT_EVENT_CONNECT, HEX); - Serial.print("Rc:"); - Serial.println(bmHUB_PORT_EVENT_RESET_COMPLETE, HEX); + //Serial.print("Rc:"); + //Serial.println(bmHUB_PORT_EVENT_RESET_COMPLETE, HEX); - PrintHubPortStatus(pUsb, addr, port); + PrintHubPortStatus(pUsb, addr, port, true); switch (evt.bmEvent) { @@ -300,23 +354,17 @@ void USBHub::HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt) 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) { - uint8_t new_addr; + UsbDevice *p = pUsb->GetAddressPool().GetUsbDevicePtr(addr); - delay(20); - - // Begin addressing - pUsb->Addressing(&new_addr); + if (p) + p->lowspeed = true; } - //uint8_t new_addr = addrPool.AllocAddress(addr, true, port); - //rcode = pUsb->setAddr(0, 0, new_addr); - //if (rcode) - //{ - // Serial.print("ERR:"); - // Serial.println(rcode, HEX); - //} + delay(50); + + pUsb->Configuring(addr, port); break; // Suspended or resuming state @@ -335,7 +383,7 @@ void USBHub::HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt) } -void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port) +void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes) { uint8_t rcode = 0; HubEvent evt; @@ -372,6 +420,9 @@ void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port) Serial.print("INDICATOR:\t"); Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC); + if (!print_changes) + return; + Serial.println("\nChange"); Serial.print("CONNECTION:\t"); Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC); @@ -384,137 +435,3 @@ void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port) Serial.print("RESET:\t\t"); Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC); } - - -#if 0 - case USB_STATE_ADDRESSING: - Serial.println("ADRESSING"); - { - UsbDevice *p = addrPool.GetUsbDevicePtr(0); - - if (p) - { - uint8_t addr = addrPool.AllocAddress(0, (p->devclass == 0x09) ? true : false); - - if (addr) - { - Serial.print("Addr:"); - Serial.println(addr,HEX); - - UsbDevice *p0 = p; - - rcode = setAddr( 0, 0, addr ); - - if (rcode) - { - Serial.println(rcode, HEX); - break; - } - p = addrPool.GetUsbDevicePtr(addr); - - usb_task_state = USB_STATE_CONFIGURING; - - } // if (addr) - } // if (p) - } - // for( i = 1; i < USB_NUMDEVICES; i++ ) - //{ - // if ( devtable[ i ].epinfo == NULL ) - // { - // devtable[ i ].epinfo = devtable[ 0 ].epinfo; //set correct MaxPktSize - // //temporary record - // //until plugged with real device endpoint structure - // devtable[ i ].devclass = devtable[ 0 ].devclass; - - // rcode = setAddr( 0, 0, i ); - - // if( rcode == 0 ) - // { - // tmpaddr = i; - - // if (devtable[i].devclass == USB_CLASS_HUB) - // { - // Serial.println("USB_CLASS_HUB"); - - // uint8_t buf[8]; - - // rcode = GetHubDescriptor(i, 0, 0, 8, buf); - - // if (rcode == 0) - // { - // // Increment number of hubs found - // numHubs ++; - - // // Insert hub address into a first available hub array entry - // for (uint8_t j=0; jbNbrPorts; - // break; - // } - // } // for - // - // } // if (rcode == 0) - // } - // usb_task_state = USB_STATE_CONFIGURING; - // } - // else - // { - // usb_error = USB_STATE_ADDRESSING; //set address error - // usb_task_state = USB_STATE_ERROR; - // } - // break; //break if address assigned or error occured during address assignment attempt - - // } // if( devtable[ i ].epinfo == NULL ) - // } //for( i = 1; i < USB_NUMDEVICES; i++) - - if( usb_task_state == USB_STATE_ADDRESSING ) //no vacant place in devtable - { - usb_error = 0xfe; - usb_task_state = USB_STATE_ERROR; - } - break; - case USB_STATE_CONFIGURING: - Serial.print("CONFIGURING..."); - - //// Hub Configuration Code - //if (devtable[1].devclass == USB_CLASS_HUB) - //{ - // Serial.println("HUB"); - - // // Read configuration Descriptor in Order To Obtain Proper Configuration Value - // uint8_t buf[8]; - // rcode = getConfDescr(1, 0, 8, 0, buf); - - // if (rcode) - // { - // Serial.print("getConfDescr:"); - // Serial.println(rcode, HEX); - // } - - // Serial.print("Conf val:"); - // Serial.println(buf[5], HEX); - - // // Set Configuration Value - // rcode = setConf(1, 0, buf[5]); - - // if (rcode) - // { - // Serial.print("setConf:"); - // Serial.println(rcode, HEX); - // } - - // Serial.println("Hub configured"); - - // // Enter Port Configuring State - // usb_task_state = USB_STATE_HUB_PORT_POWERED_OFF; - // //usb_task_state = USB_STATE_HUB_PORT_DISABLED; - // break; - - //} //if (devtable[i].devclass == USB_CLASS_HUB) - usb_task_state = USB_STATE_RUNNING; - Serial.println("Configured"); - break; -#endif \ No newline at end of file diff --git a/usbhub.h b/usbhub.h index 3f13fbe5..c1bd802e 100644 --- a/usbhub.h +++ b/usbhub.h @@ -63,7 +63,7 @@ class USBHub : USBDeviceConfig uint8_t bAddress; // address uint8_t bNbrPorts; // number of ports uint8_t bInitState; // initialization state variable - uint8_t bPortResetCounter; // number of ports reset +// uint8_t bPortResetCounter; // number of ports reset uint32_t qNextPollTime; // next poll time bool bPollEnable; // poll enable flag @@ -73,12 +73,12 @@ class USBHub : USBDeviceConfig public: USBHub(USB *p); - virtual uint8_t Init(uint8_t addr); - virtual uint8_t Release(uint8_t addr); + virtual uint8_t Init(uint8_t parent, uint8_t port); + virtual uint8_t Release(); virtual uint8_t Poll(); }; -void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port); +void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); // ---------------------------------