mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-30 12: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_address;
|
||||||
uint8_t hub_port;
|
uint8_t hub_port;
|
||||||
uint8_t enum_state;
|
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 {
|
struct Pipe_struct {
|
||||||
@ -108,4 +114,25 @@ void free_Pipe(Pipe_t *q);
|
|||||||
Transfer_t * allocate_Transfer(void);
|
Transfer_t * allocate_Transfer(void);
|
||||||
void free_Transfer(Transfer_t *q);
|
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
|
#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);
|
s.word2 = wIndex | (wLength << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t enumbuf[255];
|
static uint8_t enumbuf[256] __attribute__ ((aligned(16)));
|
||||||
|
|
||||||
void enumeration(const Transfer_t *transfer)
|
void enumeration(const Transfer_t *transfer)
|
||||||
{
|
{
|
||||||
@ -341,55 +341,127 @@ void enumeration(const Transfer_t *transfer)
|
|||||||
//print(transfer);
|
//print(transfer);
|
||||||
Device_t *dev = transfer->pipe->device;
|
Device_t *dev = transfer->pipe->device;
|
||||||
|
|
||||||
switch (dev->enum_state) {
|
while (1) {
|
||||||
case 0: // read 8 bytes of device desc, set max packet, and send set address
|
// Within this large switch/case, "break" means we've done
|
||||||
pipe_set_maxlen(dev->control_pipe, enumbuf[7]);
|
// some work, but more remains to be done in a different
|
||||||
mk_setup(dev->setup, 0, 5, assign_addr(), 0, 0); // 5=SET_ADDRESS
|
// state. Generally break is used after parsing received
|
||||||
new_Transfer(dev->control_pipe, NULL, 0);
|
// data, but what happens next could be different states.
|
||||||
dev->enum_state = 1;
|
// When completed, return is used. Generally, return happens
|
||||||
break;
|
// only after a new control transfer is queued, or when
|
||||||
case 1: // request all 18 bytes of device descriptor
|
// enumeration is complete and no more communication is needed.
|
||||||
pipe_set_addr(dev->control_pipe, dev->setup.wValue);
|
switch (dev->enum_state) {
|
||||||
mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 18); // 6=GET_DESCRIPTOR
|
case 0: // read 8 bytes of device desc, set max packet, and send set address
|
||||||
new_Transfer(dev->control_pipe, enumbuf, 18);
|
pipe_set_maxlen(dev->control_pipe, enumbuf[7]);
|
||||||
dev->enum_state = 2;
|
mk_setup(dev->setup, 0, 5, assign_addr(), 0, 0); // 5=SET_ADDRESS
|
||||||
break;
|
new_Transfer(dev->control_pipe, NULL, 0);
|
||||||
case 2: // read 18 device desc bytes, request first 9 bytes of config desc
|
dev->enum_state = 1;
|
||||||
// TODO: actually do something with device descriptor?
|
return;
|
||||||
mk_setup(dev->setup, 0x80, 6, 0x0200, 0, 9); // 6=GET_DESCRIPTOR
|
case 1: // request all 18 bytes of device descriptor
|
||||||
new_Transfer(dev->control_pipe, enumbuf, 9);
|
pipe_set_addr(dev->control_pipe, dev->setup.wValue);
|
||||||
dev->enum_state = 3;
|
mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 18); // 6=GET_DESCRIPTOR
|
||||||
break;
|
new_Transfer(dev->control_pipe, enumbuf, 18);
|
||||||
case 3: // read 9 bytes, request all of config desc
|
dev->enum_state = 2;
|
||||||
len = enumbuf[2] | (enumbuf[3] << 8);
|
return;
|
||||||
Serial.print("Config data length = ");
|
case 2: // parse 18 device desc bytes
|
||||||
Serial.println(len);
|
dev->bDeviceClass = enumbuf[4];
|
||||||
if (len > sizeof(enumbuf)) {
|
dev->bDeviceSubClass = enumbuf[5];
|
||||||
// TODO: how to handle device with too much config data
|
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)
|
uint32_t assign_addr(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user