diff --git a/host.h b/host.h index ca9180d..65e31c8 100644 --- a/host.h +++ b/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 diff --git a/k66_usbhost.ino b/k66_usbhost.ino index c61d5a0..e7fd928 100644 --- a/k66_usbhost.ino +++ b/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)