fix some HUB related issues

This commit is contained in:
ardi69 2018-10-11 17:23:31 +02:00
parent d4ea5892c8
commit ea63a6b537
4 changed files with 60 additions and 20 deletions

54
Usb.cpp
View file

@ -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;
}

View file

@ -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);
};

View file

@ -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;

View file

@ -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