Improve hub descriptor parsing, find all interfaces

This commit is contained in:
PaulStoffregen 2018-05-26 08:01:05 -07:00
parent 1494a02918
commit 62fbf401d2
2 changed files with 42 additions and 27 deletions

View File

@ -581,6 +581,10 @@ private:
uint32_t changebits;
uint32_t statusbits;
uint8_t hub_desc[16];
uint8_t interface_count;
uint8_t interface_number;
uint8_t altsetting;
uint8_t protocol;
uint8_t endpoint;
uint8_t interval;
uint8_t numports;

65
hub.cpp
View File

@ -41,7 +41,7 @@ void USBHub::init()
driver_ready_for_device(this);
}
bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
bool USBHub::claim(Device_t *dev, int type, const uint8_t *d, uint32_t len)
{
// only claim entire device, never at interface level
if (type != 0) return false;
@ -56,33 +56,44 @@ bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t
if (dev->bDeviceClass != 9 || dev->bDeviceSubClass != 0) return false;
// protocol must be 0=FS, 1=HS Single-TT, or 2=HS Multi-TT
if (dev->bDeviceProtocol > 2) return false;
// check for endpoint descriptor
if (descriptors[9] != 7 || descriptors[10] != 5) return false;
// endpoint must be IN direction
if ((descriptors[11] & 0xF0) != 0x80) return false;
// endpoint type must be interrupt
if (descriptors[12] != 3) return false;
// get the endpoint number, must not be zero
endpoint = descriptors[11] & 0x0F;
if (endpoint == 0) return false;
// get the maximum packet size
uint32_t maxsize = descriptors[13] | (descriptors[14] << 8);
if (maxsize == 0) return false;
if (maxsize > 1) return false; // do hub chips with > 7 ports exist?
interval = descriptors[15];
println(" polling interval = ", interval);
println(descriptors[9]);
println(descriptors[10]);
println(descriptors[11], HEX);
println(maxsize);
// bDeviceProtocol = 0 is full speed
// bDeviceProtocol = 1 is high speed single TT
// bDeviceProtocol = 2 is high speed multiple TT
println("bDeviceClass = ", dev->bDeviceClass);
println("bDeviceSubClass = ", dev->bDeviceSubClass);
println("bDeviceProtocol = ", dev->bDeviceProtocol);
interface_count = 0;
while (len >= 16) {
if (d[0] == 9 && d[1] == 4 && // valid interface descriptor
d[4] == 1 && // has 1 endpoint
d[5] == 9 && // bInterfaceClass is HUB type
d[7] >= 0 && d[7] <= 2 && // bInterfaceProtocol is ok
d[9] == 7 && d[10] == 5 && // valid endpoint descriptor
(d[11] & 0xF0) == 0x80 && // endpoint direction is IN
d[12] == 3 && // endpoint type is interrupt
d[13] == 1 && d[14] == 0) { // max packet size is 1 byte
println("found possible interface, altsetting=", d[3]);
if (interface_count == 0) {
interface_number = d[2];
altsetting = d[3];
protocol = d[7];
endpoint = d[11] & 0x0F;
interval = d[15];
} else {
if (d[2] != interface_number) break;
if (d[7] > protocol) {
altsetting = d[3];
protocol = d[7];
endpoint = d[11] & 0x0F;
interval = d[15];
}
}
interface_count++;
}
d += 16; // jump forward to next interface
len -= 16;
}
if (interface_count == 0) return false; // no usable interface found
println("number of interfaces found = ", interface_count);
if (interface_count > 1) {
print("best interface is ", interface_number);
println(" using altsetting ", altsetting);
}
numports = 0; // unknown until hub descriptor is read
changepipe = NULL;
changebits = 0;