From ea63a6b537ab006ca3cda1039ebf5b8b61bff5cc Mon Sep 17 00:00:00 2001 From: ardi69 Date: Thu, 11 Oct 2018 17:23:31 +0200 Subject: [PATCH] fix some HUB related issues --- Usb.cpp | 54 ++++++++++++++++++++++++++++++++++-------------------- UsbCore.h | 5 +++++ usbhub.cpp | 20 ++++++++++++++++++++ usbhub.h | 1 + 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/Usb.cpp b/Usb.cpp index 1fb593f3..1b5f32ce 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -581,6 +581,25 @@ uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) { return 0; }; +void USB::ResetHubPort(uint8_t parent, uint8_t port) { + 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 { + for (uint8_t i = 0; i < USB_NUMDEVICES; i++) { + if (devConfig[i]) { + UsbDeviceAddress addr; + addr.devAddress = devConfig[i]->GetAddress(); + if (addr.bmHub && addr.bmAddress == parent) { + devConfig[i]->ResetHubPort(port); + break; + } + } + } + } +} + uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) { //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port); uint8_t retries = 0; @@ -588,14 +607,7 @@ uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lo again: uint8_t 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); - } + ResetHubPort(parent, port); } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works delay(100); retries++; @@ -611,14 +623,7 @@ again: } if(rcode) { // Issue a bus reset, because the device may be in a limbo state - 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); - } + ResetHubPort(parent, port); } return rcode; } @@ -762,13 +767,22 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) { } uint8_t USB::ReleaseDevice(uint8_t addr) { + UsbDeviceAddress a; if(!addr) return 0; - - for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { - if(!devConfig[i]) continue; - if(devConfig[i]->GetAddress() == addr) + a.devAddress = addr; + if(a.bmHub) { + for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { + if(!devConfig[i]) continue; + if(devConfig[i]->GetAddress() == addr) return devConfig[i]->Release(); + } + } else { + for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { + if(!devConfig[i]) continue; + if(devConfig[i]->GetPortAddress() == addr) + return devConfig[i]->Release(); + } } return 0; } diff --git a/UsbCore.h b/UsbCore.h index 02397368..83664692 100644 --- a/UsbCore.h +++ b/UsbCore.h @@ -152,6 +152,10 @@ public: return 0; } + virtual uint8_t GetPortAddress() { + return GetAddress(); + } + virtual void ResetHubPort(uint8_t port __attribute__((unused))) { return; } // Note used for hubs only! @@ -274,6 +278,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 bInterval = 0); + void ResetHubPort(uint8_t parent, uint8_t port); uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed); }; diff --git a/usbhub.cpp b/usbhub.cpp index e4d9d79e..4ed443f6 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -21,6 +21,7 @@ bool USBHub::bResetInitiated = false; USBHub::USBHub(USB *p) : pUsb(p), bAddress(0), +bPortAddress(0), bNbrPorts(0), //bInitState(0), qNextPollTime(0), @@ -104,6 +105,14 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { if(!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + { + UsbDeviceAddress a; + a.devAddress = bAddress; + a.bmHub = 0; + a.bmAddress = port ? : 1; + bPortAddress = a.devAddress; + } + // Extract Max Packet Size from the device descriptor epInfo[0].maxPktSize = udd->bMaxPacketSize0; @@ -115,6 +124,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { p->epinfo = oldep_ptr; addrPool.FreeAddress(bAddress); bAddress = 0; + bPortAddress = 0; return rcode; } @@ -214,12 +224,22 @@ Fail: } uint8_t USBHub::Release() { + UsbDeviceAddress a; + a.devAddress = 0; + a.bmHub = 0; + a.bmParent = bAddress; + for (uint8_t j = 1; j <= bNbrPorts; j++) { + a.bmAddress = j; + pUsb->ReleaseDevice(a.devAddress); + } + pUsb->GetAddressPool().FreeAddress(bAddress); if(bAddress == 0x41) pUsb->SetHubPreMask(); bAddress = 0; + bPortAddress = 0; bNbrPorts = 0; qNextPollTime = 0; bPollEnable = false; diff --git a/usbhub.h b/usbhub.h index 1ac94944..7c197dec 100644 --- a/usbhub.h +++ b/usbhub.h @@ -169,6 +169,7 @@ class USBHub : USBDeviceConfig { EpInfo epInfo[2]; // interrupt endpoint info structure uint8_t bAddress; // address + uint8_t bPortAddress; // port address uint8_t bNbrPorts; // number of ports // uint8_t bInitState; // initialization state variable uint32_t qNextPollTime; // next poll time