mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-27 19:42:15 -05:00
Request string descriptors during enumeration
This commit is contained in:
parent
6122604f55
commit
03fb64e1ab
27
host.h
27
host.h
@ -60,6 +60,12 @@ struct Device_struct {
|
||||
uint8_t hub_address;
|
||||
uint8_t hub_port;
|
||||
uint8_t enum_state;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t LanguageID;
|
||||
};
|
||||
|
||||
struct Pipe_struct {
|
||||
@ -108,4 +114,25 @@ void free_Pipe(Pipe_t *q);
|
||||
Transfer_t * allocate_Transfer(void);
|
||||
void free_Transfer(Transfer_t *q);
|
||||
|
||||
class USBHostDriver {
|
||||
public:
|
||||
virtual bool claim_device(Device_t *device) {
|
||||
return false;
|
||||
}
|
||||
virtual bool claim_interface(Device_t *device) {
|
||||
return false;
|
||||
}
|
||||
virtual void disconnect() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class USBHub : public USBHostDriver {
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
168
k66_usbhost.ino
168
k66_usbhost.ino
@ -330,7 +330,7 @@ void mk_setup(setup_t &s, uint32_t bmRequestType, uint32_t bRequest,
|
||||
s.word2 = wIndex | (wLength << 16);
|
||||
}
|
||||
|
||||
static uint8_t enumbuf[255];
|
||||
static uint8_t enumbuf[256] __attribute__ ((aligned(16)));
|
||||
|
||||
void enumeration(const Transfer_t *transfer)
|
||||
{
|
||||
@ -341,55 +341,127 @@ void enumeration(const Transfer_t *transfer)
|
||||
//print(transfer);
|
||||
Device_t *dev = transfer->pipe->device;
|
||||
|
||||
switch (dev->enum_state) {
|
||||
case 0: // read 8 bytes of device desc, set max packet, and send set address
|
||||
pipe_set_maxlen(dev->control_pipe, enumbuf[7]);
|
||||
mk_setup(dev->setup, 0, 5, assign_addr(), 0, 0); // 5=SET_ADDRESS
|
||||
new_Transfer(dev->control_pipe, NULL, 0);
|
||||
dev->enum_state = 1;
|
||||
break;
|
||||
case 1: // request all 18 bytes of device descriptor
|
||||
pipe_set_addr(dev->control_pipe, dev->setup.wValue);
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 18); // 6=GET_DESCRIPTOR
|
||||
new_Transfer(dev->control_pipe, enumbuf, 18);
|
||||
dev->enum_state = 2;
|
||||
break;
|
||||
case 2: // read 18 device desc bytes, request first 9 bytes of config desc
|
||||
// TODO: actually do something with device descriptor?
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0200, 0, 9); // 6=GET_DESCRIPTOR
|
||||
new_Transfer(dev->control_pipe, enumbuf, 9);
|
||||
dev->enum_state = 3;
|
||||
break;
|
||||
case 3: // read 9 bytes, request all of config desc
|
||||
len = enumbuf[2] | (enumbuf[3] << 8);
|
||||
Serial.print("Config data length = ");
|
||||
Serial.println(len);
|
||||
if (len > sizeof(enumbuf)) {
|
||||
// TODO: how to handle device with too much config data
|
||||
while (1) {
|
||||
// Within this large switch/case, "break" means we've done
|
||||
// some work, but more remains to be done in a different
|
||||
// state. Generally break is used after parsing received
|
||||
// data, but what happens next could be different states.
|
||||
// When completed, return is used. Generally, return happens
|
||||
// only after a new control transfer is queued, or when
|
||||
// enumeration is complete and no more communication is needed.
|
||||
switch (dev->enum_state) {
|
||||
case 0: // read 8 bytes of device desc, set max packet, and send set address
|
||||
pipe_set_maxlen(dev->control_pipe, enumbuf[7]);
|
||||
mk_setup(dev->setup, 0, 5, assign_addr(), 0, 0); // 5=SET_ADDRESS
|
||||
new_Transfer(dev->control_pipe, NULL, 0);
|
||||
dev->enum_state = 1;
|
||||
return;
|
||||
case 1: // request all 18 bytes of device descriptor
|
||||
pipe_set_addr(dev->control_pipe, dev->setup.wValue);
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 18); // 6=GET_DESCRIPTOR
|
||||
new_Transfer(dev->control_pipe, enumbuf, 18);
|
||||
dev->enum_state = 2;
|
||||
return;
|
||||
case 2: // parse 18 device desc bytes
|
||||
dev->bDeviceClass = enumbuf[4];
|
||||
dev->bDeviceSubClass = enumbuf[5];
|
||||
dev->bDeviceProtocol = enumbuf[6];
|
||||
dev->idVendor = enumbuf[8] | (enumbuf[9] << 8);
|
||||
dev->idProduct = enumbuf[10] | (enumbuf[11] << 8);
|
||||
enumbuf[0] = enumbuf[14];
|
||||
enumbuf[1] = enumbuf[15];
|
||||
enumbuf[2] = enumbuf[16];
|
||||
if ((enumbuf[0] | enumbuf[1] | enumbuf[2]) > 0) {
|
||||
dev->enum_state = 3;
|
||||
} else {
|
||||
dev->enum_state = 11;
|
||||
}
|
||||
break;
|
||||
case 3: // request Language ID
|
||||
len = sizeof(enumbuf) - 4;
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0300, 0, len); // 6=GET_DESCRIPTOR
|
||||
new_Transfer(dev->control_pipe, enumbuf + 4, len);
|
||||
dev->enum_state = 4;
|
||||
return;
|
||||
case 4: // parse Language ID
|
||||
if (enumbuf[4] < 4 || enumbuf[5] != 3) {
|
||||
dev->enum_state = 11;
|
||||
} else {
|
||||
dev->LanguageID = enumbuf[6] | (enumbuf[7] << 8);
|
||||
if (enumbuf[0]) dev->enum_state = 5;
|
||||
else if (enumbuf[1]) dev->enum_state = 7;
|
||||
else if (enumbuf[2]) dev->enum_state = 9;
|
||||
else dev->enum_state = 11;
|
||||
}
|
||||
break;
|
||||
case 5: // request Manufacturer string
|
||||
len = sizeof(enumbuf) - 4;
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[0], dev->LanguageID, len);
|
||||
new_Transfer(dev->control_pipe, enumbuf + 4, len);
|
||||
dev->enum_state = 6;
|
||||
return;
|
||||
case 6: // parse Manufacturer string
|
||||
// TODO: receive the string...
|
||||
if (enumbuf[1]) dev->enum_state = 7;
|
||||
else if (enumbuf[2]) dev->enum_state = 9;
|
||||
else dev->enum_state = 11;
|
||||
break;
|
||||
case 7: // request Product string
|
||||
len = sizeof(enumbuf) - 4;
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[1], dev->LanguageID, len);
|
||||
new_Transfer(dev->control_pipe, enumbuf + 4, len);
|
||||
dev->enum_state = 8;
|
||||
return;
|
||||
case 8: // parse Product string
|
||||
// TODO: receive the string...
|
||||
if (enumbuf[2]) dev->enum_state = 9;
|
||||
else dev->enum_state = 11;
|
||||
break;
|
||||
case 9: // request Serial Number string
|
||||
len = sizeof(enumbuf) - 4;
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[2], dev->LanguageID, len);
|
||||
new_Transfer(dev->control_pipe, enumbuf + 4, len);
|
||||
dev->enum_state = 10;
|
||||
return;
|
||||
case 10: // parse Serial Number string
|
||||
// TODO: receive the string...
|
||||
dev->enum_state = 11;
|
||||
break;
|
||||
case 11: // request first 9 bytes of config desc
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0200, 0, 9); // 6=GET_DESCRIPTOR
|
||||
new_Transfer(dev->control_pipe, enumbuf, 9);
|
||||
dev->enum_state = 12;
|
||||
return;
|
||||
case 12: // read 9 bytes, request all of config desc
|
||||
len = enumbuf[2] | (enumbuf[3] << 8);
|
||||
Serial.print("Config data length = ");
|
||||
Serial.println(len);
|
||||
if (len > sizeof(enumbuf)) {
|
||||
// TODO: how to handle device with too much config data
|
||||
}
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0200, 0, len); // 6=GET_DESCRIPTOR
|
||||
new_Transfer(dev->control_pipe, enumbuf, len);
|
||||
dev->enum_state = 13;
|
||||
return;
|
||||
case 13: // read all config desc, send set config
|
||||
Serial.print("bNumInterfaces = ");
|
||||
Serial.println(enumbuf[4]);
|
||||
Serial.print("bConfigurationValue = ");
|
||||
Serial.println(enumbuf[5]);
|
||||
// TODO: actually do something with interface descriptor?
|
||||
mk_setup(dev->setup, 0, 9, enumbuf[5], 0, 0); // 9=SET_CONFIGURATION
|
||||
new_Transfer(dev->control_pipe, NULL, 0);
|
||||
dev->enum_state = 14;
|
||||
return;
|
||||
case 14: // device is now configured
|
||||
// TODO: initialize drivers??
|
||||
dev->enum_state = 15;
|
||||
return;
|
||||
case 15: // control transfers for other stuff??
|
||||
default:
|
||||
return;
|
||||
}
|
||||
mk_setup(dev->setup, 0x80, 6, 0x0200, 0, len); // 6=GET_DESCRIPTOR
|
||||
new_Transfer(dev->control_pipe, enumbuf, len);
|
||||
dev->enum_state = 4;
|
||||
break;
|
||||
case 4: // read all config desc, send set config
|
||||
Serial.print("bNumInterfaces = ");
|
||||
Serial.println(enumbuf[4]);
|
||||
Serial.print("bConfigurationValue = ");
|
||||
Serial.println(enumbuf[5]);
|
||||
// TODO: actually do something with interface descriptor?
|
||||
mk_setup(dev->setup, 0, 9, enumbuf[5], 0, 0); // 9=SET_CONFIGURATION
|
||||
new_Transfer(dev->control_pipe, NULL, 0);
|
||||
dev->enum_state = 5;
|
||||
break;
|
||||
case 5: // device is now configured
|
||||
// TODO: initialize drivers??
|
||||
dev->enum_state = 6;
|
||||
break;
|
||||
case 6: // control transfers for other stuff??
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint32_t assign_addr(void)
|
||||
|
Loading…
Reference in New Issue
Block a user