|
|
@@ -27,6 +27,7 @@ |
|
|
|
|
|
|
|
static USBDriver *available_drivers = NULL; |
|
|
|
static uint8_t enumbuf[256] __attribute__ ((aligned(16))); |
|
|
|
static setup_t enumsetup __attribute__ ((aligned(16))); |
|
|
|
|
|
|
|
|
|
|
|
static uint32_t assign_addr(void); |
|
|
@@ -80,8 +81,8 @@ Device_t * USBHost::new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_p |
|
|
|
// TODO: exclusive access to enumeration process |
|
|
|
// any new devices detected while enumerating would |
|
|
|
// go onto a waiting list |
|
|
|
mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 8); // 6=GET_DESCRIPTOR |
|
|
|
new_Control_Transfer(dev, &dev->setup, enumbuf); |
|
|
|
mk_setup(enumsetup, 0x80, 6, 0x0100, 0, 8); // 6=GET_DESCRIPTOR |
|
|
|
new_Control_Transfer(dev, &enumsetup, enumbuf, NULL); |
|
|
|
return dev; |
|
|
|
} |
|
|
|
|
|
|
@@ -107,14 +108,14 @@ void USBHost::enumeration(const Transfer_t *transfer) |
|
|
|
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_Control_Transfer(dev, &dev->setup, NULL); |
|
|
|
mk_setup(enumsetup, 0, 5, assign_addr(), 0, 0); // 5=SET_ADDRESS |
|
|
|
new_Control_Transfer(dev, &enumsetup, NULL, NULL); |
|
|
|
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_Control_Transfer(dev, &dev->setup, enumbuf); |
|
|
|
pipe_set_addr(dev->control_pipe, enumsetup.wValue); |
|
|
|
mk_setup(enumsetup, 0x80, 6, 0x0100, 0, 18); // 6=GET_DESCRIPTOR |
|
|
|
new_Control_Transfer(dev, &enumsetup, enumbuf, NULL); |
|
|
|
dev->enum_state = 2; |
|
|
|
return; |
|
|
|
case 2: // parse 18 device desc bytes |
|
|
@@ -134,8 +135,8 @@ void USBHost::enumeration(const Transfer_t *transfer) |
|
|
|
break; |
|
|
|
case 3: // request Language ID |
|
|
|
len = sizeof(enumbuf) - 4; |
|
|
|
mk_setup(dev->setup, 0x80, 6, 0x0300, 0, len); // 6=GET_DESCRIPTOR |
|
|
|
new_Control_Transfer(dev, &dev->setup, enumbuf + 4); |
|
|
|
mk_setup(enumsetup, 0x80, 6, 0x0300, 0, len); // 6=GET_DESCRIPTOR |
|
|
|
new_Control_Transfer(dev, &enumsetup, enumbuf + 4, NULL); |
|
|
|
dev->enum_state = 4; |
|
|
|
return; |
|
|
|
case 4: // parse Language ID |
|
|
@@ -151,8 +152,8 @@ void USBHost::enumeration(const Transfer_t *transfer) |
|
|
|
break; |
|
|
|
case 5: // request Manufacturer string |
|
|
|
len = sizeof(enumbuf) - 4; |
|
|
|
mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[0], dev->LanguageID, len); |
|
|
|
new_Control_Transfer(dev, &dev->setup, enumbuf + 4); |
|
|
|
mk_setup(enumsetup, 0x80, 6, 0x0300 | enumbuf[0], dev->LanguageID, len); |
|
|
|
new_Control_Transfer(dev, &enumsetup, enumbuf + 4, NULL); |
|
|
|
dev->enum_state = 6; |
|
|
|
return; |
|
|
|
case 6: // parse Manufacturer string |
|
|
@@ -163,8 +164,8 @@ void USBHost::enumeration(const Transfer_t *transfer) |
|
|
|
break; |
|
|
|
case 7: // request Product string |
|
|
|
len = sizeof(enumbuf) - 4; |
|
|
|
mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[1], dev->LanguageID, len); |
|
|
|
new_Control_Transfer(dev, &dev->setup, enumbuf + 4); |
|
|
|
mk_setup(enumsetup, 0x80, 6, 0x0300 | enumbuf[1], dev->LanguageID, len); |
|
|
|
new_Control_Transfer(dev, &enumsetup, enumbuf + 4, NULL); |
|
|
|
dev->enum_state = 8; |
|
|
|
return; |
|
|
|
case 8: // parse Product string |
|
|
@@ -174,8 +175,8 @@ void USBHost::enumeration(const Transfer_t *transfer) |
|
|
|
break; |
|
|
|
case 9: // request Serial Number string |
|
|
|
len = sizeof(enumbuf) - 4; |
|
|
|
mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[2], dev->LanguageID, len); |
|
|
|
new_Control_Transfer(dev, &dev->setup, enumbuf + 4); |
|
|
|
mk_setup(enumsetup, 0x80, 6, 0x0300 | enumbuf[2], dev->LanguageID, len); |
|
|
|
new_Control_Transfer(dev, &enumsetup, enumbuf + 4, NULL); |
|
|
|
dev->enum_state = 10; |
|
|
|
return; |
|
|
|
case 10: // parse Serial Number string |
|
|
@@ -183,8 +184,8 @@ void USBHost::enumeration(const Transfer_t *transfer) |
|
|
|
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_Control_Transfer(dev, &dev->setup, enumbuf); |
|
|
|
mk_setup(enumsetup, 0x80, 6, 0x0200, 0, 9); // 6=GET_DESCRIPTOR |
|
|
|
new_Control_Transfer(dev, &enumsetup, enumbuf, NULL); |
|
|
|
dev->enum_state = 12; |
|
|
|
return; |
|
|
|
case 12: // read 9 bytes, request all of config desc |
|
|
@@ -194,8 +195,8 @@ void USBHost::enumeration(const Transfer_t *transfer) |
|
|
|
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_Control_Transfer(dev, &dev->setup, enumbuf); |
|
|
|
mk_setup(enumsetup, 0x80, 6, 0x0200, 0, len); // 6=GET_DESCRIPTOR |
|
|
|
new_Control_Transfer(dev, &enumsetup, enumbuf, NULL); |
|
|
|
dev->enum_state = 13; |
|
|
|
return; |
|
|
|
case 13: // read all config desc, send set config |
|
|
@@ -206,8 +207,8 @@ void USBHost::enumeration(const Transfer_t *transfer) |
|
|
|
dev->bmAttributes = enumbuf[7]; |
|
|
|
dev->bMaxPower = enumbuf[8]; |
|
|
|
// TODO: actually do something with interface descriptor? |
|
|
|
mk_setup(dev->setup, 0, 9, enumbuf[5], 0, 0); // 9=SET_CONFIGURATION |
|
|
|
new_Control_Transfer(dev, &dev->setup, NULL); |
|
|
|
mk_setup(enumsetup, 0, 9, enumbuf[5], 0, 0); // 9=SET_CONFIGURATION |
|
|
|
new_Control_Transfer(dev, &enumsetup, NULL, NULL); |
|
|
|
dev->enum_state = 14; |
|
|
|
return; |
|
|
|
case 14: // device is now configured |