diff --git a/Usb.cpp b/Usb.cpp index c09db2d8..53bcb76d 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -563,6 +563,25 @@ uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) { return 0; }; +uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t rcode = 0; + //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port); + + rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed); + if (rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) { + if (parent == 0) { + // Send a bus reset on the root interface. + regWr(rHCTL, bmBUSRST); //issue bus reset + delay(102); // delay 102ms, compensate for clock inaccuracy. + } else { + // reset parent port + devConfig[parent]->ResetHubPort(port); + } + } + rcode = devConfig[driver]->Init(parent, port, lowspeed); + return rcode; +} + /* * This is broken. We need to enumerate differently. * It causes major problems with several devices if detected in an unexpected order. @@ -604,40 +623,96 @@ uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) { * */ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) { + //uint8_t bAddress = 0; + //printf("Configuring: parent = %i, port = %i\r\n", parent, port); uint8_t rcode = 0; + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + EpInfo epInfo; - for (; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { - if (!devConfig[devConfigIndex]) - continue; + epInfo.epAddr = 0; + epInfo.maxPktSize = 8; + epInfo.epAttribs = 0; + epInfo.bmNakPower = USB_NAK_MAX_POWER; - rcode = devConfig[devConfigIndex]->ConfigureDevice(parent, port, lowspeed); - if (rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) { - if (parent == 0) { - // Send a bus reset on the root interface. - regWr(rHCTL, bmBUSRST); //issue bus reset - delay(102); // delay 102ms, compensate for clock inaccuracy. - } else { - // reset parent port - devConfig[parent]->ResetHubPort(port); - } + delay(2000); + AddressPool &addrPool = GetAddressPool(); + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + if (!p) { + //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n"); + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + // 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; + + p->lowspeed = lowspeed; + // Get device descriptor + rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if (rcode) { + //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n"); + return rcode; + } + + // to-do? + // Allocate new address according to device class + //bAddress = addrPool.AllocAddress(parent, false, port); + + //if (!bAddress) + // return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + uint16_t vid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; + uint16_t pid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; + uint8_t klass = ((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass; + + + // Attempt to configure if VID/PID or device class matches with a driver + for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { + if (!devConfig[devConfigIndex]) continue; // no driver + if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed + if (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) { + rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); + break; } - rcode = devConfig[devConfigIndex]->Init(parent, port, lowspeed); - if (!rcode) { + } + + if (devConfigIndex < USB_NUMDEVICES) { + if (rcode) { + //printf("Configuring error: %i\r\n", rcode); devConfigIndex = 0; - return 0; } + return rcode; + } + + + // blindly attempt to configure + for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { + if (!devConfig[devConfigIndex]) continue; + if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed + rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); + //printf("ERROR ENUMERATING %2.2x\r\n", rcode); 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 // next time the program gets here - if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) - devConfigIndex = 0; + //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) + // devConfigIndex = 0; return rcode; } } // if we get here that means that the device class is not supported by any of registered classes - devConfigIndex = 0; rcode = DefaultAddressing(parent, port, lowspeed); diff --git a/Usb.h b/Usb.h index 37d0427a..bcb8bd8e 100644 --- a/Usb.h +++ b/Usb.h @@ -141,12 +141,14 @@ typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega class USBDeviceConfig { public: - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) = 0; + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) { return 0; } virtual uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {return 0; } - virtual uint8_t Release() = 0; - virtual uint8_t Poll() = 0; - virtual uint8_t GetAddress() = 0; + virtual uint8_t Release() { return 0; } + virtual uint8_t Poll() { return 0; } + virtual uint8_t GetAddress() { return 0; } virtual void ResetHubPort(uint8_t port) { return; } // Note used for hubs only! + virtual boolean VIDPIDOK(uint16_t vid, uint16_t pid) { return false; } + virtual boolean DEVCLASSOK(uint8_t klass) { return false; } }; /* USB Setup Packet Structure */ @@ -256,6 +258,7 @@ private: uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit); uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data); uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data); + uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed); }; #if 0 //defined(USB_METHODS_INLINE) diff --git a/confdescparser.h b/confdescparser.h index d3e726af..a3bc7cc7 100644 --- a/confdescparser.h +++ b/confdescparser.h @@ -35,7 +35,7 @@ public: #define CP_MASK_COMPARE_CLASS 1 #define CP_MASK_COMPARE_SUBCLASS 2 #define CP_MASK_COMPARE_PROTOCOL 4 -#define CP_MASK_COMPARE_ALL 7 +#define CP_MASK_COMPARE_ALL 7 // Configuration Descriptor Parser Class Template @@ -104,10 +104,10 @@ bool ConfigDescParser::ParseDescriptor dscrType = *((uint8_t*) theBuffer.pValue + 1); stateParseDescr = 2; case 2: - // This is a sort of hack. Assuming that two bytes are allready in the buffer + // This is a sort of hack. Assuming that two bytes are all ready in the buffer // the pointer is positioned two bytes ahead in order for the rest of descriptor // to be read right after the size and the type fields. - // This should be used carefuly. varBuffer should be used directly to handle data + // This should be used carefully. varBuffer should be used directly to handle data // in the buffer. theBuffer.pValue = varBuffer + 2; stateParseDescr = 3; @@ -208,4 +208,4 @@ void ConfigDescParser::PrintHidDescrip } -#endif // __CONFDESCPARSER_H__ \ No newline at end of file +#endif // __CONFDESCPARSER_H__ diff --git a/masstorage.cpp b/masstorage.cpp index a19ce44e..c514155c 100644 --- a/masstorage.cpp +++ b/masstorage.cpp @@ -277,7 +277,7 @@ uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { EpInfo *oldep_ptr = NULL; USBTRACE("MS ConfigureDevice\r\n"); ClearAllEP(); - delay(2000); + //delay(2000); AddressPool &addrPool = pUsb->GetAddressPool(); @@ -409,7 +409,6 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { // Assign epInfo to epinfo pointer pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - USBTRACE("MS ConfigureDevice\r\n"); USBTRACE2("Conf:", bConfNum); // Set Configuration Value @@ -528,6 +527,42 @@ Fail: return rcode; } +/** + * For driver use only. + * + * @param conf + * @param iface + * @param alt + * @param proto + * @param pep + */ +void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR * pep) { + ErrorMessage (PSTR("Conf.Val"), conf); + ErrorMessage (PSTR("Iface Num"), iface); + ErrorMessage (PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if ((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); +} + /** * For driver use only. * @@ -1256,42 +1291,6 @@ uint8_t BulkOnly::HandleSCSIError(uint8_t status) { //////////////////////////////////////////////////////////////////////////////// -/** - * For driver use only. - * - * @param conf - * @param iface - * @param alt - * @param proto - * @param pep - */ -void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR * pep) { - ErrorMessage (PSTR("Conf.Val"), conf); - ErrorMessage (PSTR("Iface Num"), iface); - ErrorMessage (PSTR("Alt.Set"), alt); - - bConfNum = conf; - - uint8_t index; - - if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - index = epInterruptInIndex; - else - if ((pep->bmAttributes & 0x02) == 2) - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - else - return; - - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; - - bNumEP++; - - PrintEndpointDescriptor(pep); -} - /** * * @param ep_ptr diff --git a/masstorage.h b/masstorage.h index a851003d..2048a6a8 100644 --- a/masstorage.h +++ b/masstorage.h @@ -275,6 +275,8 @@ public: // UsbConfigXtracter implementation virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + virtual boolean DEVCLASSOK(uint8_t klass) { return (klass == USB_CLASS_MASS_STORAGE); } + private: uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf); diff --git a/usbhub.cpp b/usbhub.cpp index 6b20476b..4df7bfdb 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -22,7 +22,7 @@ USBHub::USBHub(USB *p) : pUsb(p), bAddress(0), bNbrPorts(0), -bInitState(0), +//bInitState(0), qNextPollTime(0), bPollEnable(false) { epInfo[0].epAddr = 0; @@ -47,12 +47,13 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t len = 0; uint16_t cd_len = 0; - //USBTRACE("\r\nHub Init Start"); + //USBTRACE("\r\nHub Init Start "); + //D_PrintHex (bInitState, 0x80); AddressPool &addrPool = pUsb->GetAddressPool(); - switch (bInitState) { - case 0: + //switch (bInitState) { + // case 0: if (bAddress) return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; @@ -129,9 +130,9 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { if (rcode) goto FailSetDevTblEntry; - bInitState = 1; + // bInitState = 1; - case 1: + // case 1: // Get hub descriptor rcode = GetHubDescriptor(0, 8, buf); @@ -141,9 +142,9 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { // Save number of ports for future use bNbrPorts = ((HubDescriptor*)buf)->bNbrPorts; - bInitState = 2; + // bInitState = 2; - case 2: + // case 2: // Read configuration Descriptor in Order To Obtain Proper Configuration Value rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); @@ -171,18 +172,19 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { if (rcode) goto FailSetConfDescr; - bInitState = 3; + // bInitState = 3; - case 3: + // case 3: // Power on all ports for (uint8_t j = 1; j <= bNbrPorts; j++) SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j); pUsb->SetHubPreMask(); bPollEnable = true; - bInitState = 0; - } - bInitState = 0; + // bInitState = 0; + //} + //bInitState = 0; + //USBTRACE("...OK\r\n"); return 0; // Oleg, No debugging?? -- xxxajk @@ -202,6 +204,7 @@ FailSetConfDescr: goto Fail; Fail: + USBTRACE("...FAIL\r\n"); return rcode; } @@ -241,17 +244,17 @@ uint8_t USBHub::CheckHubStatus() { if (rcode) return rcode; - if (buf[0] & 0x01) // Hub Status Change - { - //pUsb->PrintHubStatus(addr); - //rcode = GetHubStatus(1, 0, 1, 4, buf); - //if (rcode) - //{ - // USB_HOST_SERIAL.print("GetHubStatus Error"); - // USB_HOST_SERIAL.println(rcode, HEX); - // return rcode; - //} - } + //if (buf[0] & 0x01) // Hub Status Change + //{ + // pUsb->PrintHubStatus(addr); + // rcode = GetHubStatus(1, 0, 1, 4, buf); + // if (rcode) + // { + // USB_HOST_SERIAL.print("GetHubStatus Error"); + // USB_HOST_SERIAL.println(rcode, HEX); + // return rcode; + // } + //} for (uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) { if (buf[0] & mask) { HubEvent evt; @@ -308,18 +311,17 @@ void USBHub::ResetHubPort(uint8_t port) { SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); - for(;;) { - rcode = GetPortStatus(port, 4, evt.evtBuff); - if(rcode) return; // Some kind of error, bail. - rcode = evt.bmEvent; - if (rcode == bmHUB_PORT_EVENT_RESET_COMPLETE || rcode == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) { - ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - delay(20); - return; - } - delay(100); // simulate polling. + for (int i = 0; i < 3; i++) { + rcode = GetPortStatus(port, 4, evt.evtBuff); + if (rcode) break; // Some kind of error, bail. + if (evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) { + break; + } + delay(100); // simulate polling. } + ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + delay(20); } uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) { diff --git a/usbhub.h b/usbhub.h index 4d04b7d4..10cccfe5 100644 --- a/usbhub.h +++ b/usbhub.h @@ -183,7 +183,7 @@ class USBHub : USBDeviceConfig { uint8_t bAddress; // address uint8_t bNbrPorts; // number of ports - uint8_t bInitState; // initialization state variable +// uint8_t bInitState; // initialization state variable uint32_t qNextPollTime; // next poll time bool bPollEnable; // poll enable flag @@ -211,6 +211,8 @@ public: virtual uint8_t GetAddress() { return bAddress; }; + virtual boolean DEVCLASSOK(uint8_t klass) { return (klass == 0x09); } + }; // Clear Hub Feature