| // device has its vid&pid, class/subclass fields initialized | // device has its vid&pid, class/subclass fields initialized | ||||
| // type is 0 for device level, 1 for interface level, 2 for IAD | // type is 0 for device level, 1 for interface level, 2 for IAD | ||||
| // descriptors points to the specific descriptor data | // descriptors points to the specific descriptor data | ||||
| virtual bool claim(Device_t *device, int type, const uint8_t *descriptors); | |||||
| virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); | |||||
| // When an unknown (not chapter 9) control transfer completes, this | // When an unknown (not chapter 9) control transfer completes, this | ||||
| // function is called for all drivers bound to the device. Return | // function is called for all drivers bound to the device. Return | ||||
| public: | public: | ||||
| USBHub(); | USBHub(); | ||||
| protected: | protected: | ||||
| virtual bool claim(Device_t *device, int type, const uint8_t *descriptors); | |||||
| virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); | |||||
| virtual void control(const Transfer_t *transfer); | virtual void control(const Transfer_t *transfer); | ||||
| virtual void disconnect(); | virtual void disconnect(); | ||||
| void poweron(uint32_t port); | void poweron(uint32_t port); | ||||
| void attachPress(void (*keyPressed)()); | void attachPress(void (*keyPressed)()); | ||||
| void attachRelease(void (*keyReleased)()); | void attachRelease(void (*keyReleased)()); | ||||
| protected: | protected: | ||||
| virtual bool claim(Device_t *device, int type, const uint8_t *descriptors); | |||||
| virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); | |||||
| virtual void disconnect(); | virtual void disconnect(); | ||||
| static void callback(const Transfer_t *transfer); | static void callback(const Transfer_t *transfer); | ||||
| void new_data(const Transfer_t *transfer); | void new_data(const Transfer_t *transfer); |
| PORTE_PCR6 = PORT_PCR_MUX(1); | PORTE_PCR6 = PORT_PCR_MUX(1); | ||||
| GPIOE_PDDR |= (1<<6); | GPIOE_PDDR |= (1<<6); | ||||
| GPIOE_PSOR = (1<<6); // turn on USB host power | GPIOE_PSOR = (1<<6); // turn on USB host power | ||||
| delay(10); | |||||
| Serial.print("sizeof Device = "); | Serial.print("sizeof Device = "); | ||||
| Serial.println(sizeof(Device_t)); | Serial.println(sizeof(Device_t)); | ||||
| Serial.print("sizeof Pipe = "); | Serial.print("sizeof Pipe = "); |
| static USBDriver *available_drivers = NULL; | static USBDriver *available_drivers = NULL; | ||||
| static uint8_t enumbuf[256] __attribute__ ((aligned(16))); | static uint8_t enumbuf[256] __attribute__ ((aligned(16))); | ||||
| static setup_t enumsetup __attribute__ ((aligned(16))); | static setup_t enumsetup __attribute__ ((aligned(16))); | ||||
| static uint16_t enumlen; | |||||
| static uint32_t assign_addr(void); | static uint32_t assign_addr(void); | ||||
| dev->enum_state = 12; | dev->enum_state = 12; | ||||
| return; | return; | ||||
| case 12: // read 9 bytes, request all of config desc | case 12: // read 9 bytes, request all of config desc | ||||
| len = enumbuf[2] | (enumbuf[3] << 8); | |||||
| enumlen = enumbuf[2] | (enumbuf[3] << 8); | |||||
| Serial.print("Config data length = "); | Serial.print("Config data length = "); | ||||
| Serial.println(len); | |||||
| if (len > sizeof(enumbuf)) { | |||||
| Serial.println(enumlen); | |||||
| if (enumlen > sizeof(enumbuf)) { | |||||
| // TODO: how to handle device with too much config data | // TODO: how to handle device with too much config data | ||||
| } | } | ||||
| mk_setup(enumsetup, 0x80, 6, 0x0200, 0, len); // 6=GET_DESCRIPTOR | |||||
| mk_setup(enumsetup, 0x80, 6, 0x0200, 0, enumlen); // 6=GET_DESCRIPTOR | |||||
| queue_Control_Transfer(dev, &enumsetup, enumbuf, NULL); | queue_Control_Transfer(dev, &enumsetup, enumbuf, NULL); | ||||
| dev->enum_state = 13; | dev->enum_state = 13; | ||||
| return; | return; | ||||
| // first check if any driver wishes to claim the entire device | // first check if any driver wishes to claim the entire device | ||||
| for (driver=available_drivers; driver != NULL; driver = driver->next) { | for (driver=available_drivers; driver != NULL; driver = driver->next) { | ||||
| if (driver->claim(dev, 0, enumbuf + 9)) { | |||||
| if (driver->claim(dev, 0, enumbuf + 9, enumlen - 9)) { | |||||
| if (prev) { | if (prev) { | ||||
| prev->next = driver->next; | prev->next = driver->next; | ||||
| } else { | } else { | ||||
| } | } | ||||
| prev = driver; | prev = driver; | ||||
| } | } | ||||
| // TODO: parse interfaces from config descriptor | |||||
| // try claim_interface on drivers | |||||
| // parse interfaces from config descriptor | |||||
| const uint8_t *p = enumbuf + 9; | |||||
| const uint8_t *end = enumbuf + enumlen; | |||||
| while (p < end) { | |||||
| uint8_t desclen = *p; | |||||
| uint8_t desctype = *(p+1); | |||||
| Serial.print("Descriptor "); | |||||
| Serial.print(desctype); | |||||
| Serial.print(" = "); | |||||
| if (desctype == 4) Serial.println("INTERFACE"); | |||||
| else if (desctype == 5) Serial.println("ENDPOINT"); | |||||
| else if (desctype == 6) Serial.println("DEV_QUALIFIER"); | |||||
| else if (desctype == 7) Serial.println("OTHER_SPEED"); | |||||
| else if (desctype == 11) Serial.println("IAD"); | |||||
| else if (desctype == 33) Serial.println("HID"); | |||||
| else Serial.println(" ???"); | |||||
| if (desctype == 11 && desclen == 8) { | |||||
| // TODO: parse IAD, ask drivers for claim | |||||
| // TODO: how to skip over all interfaces IAD represented | |||||
| } | |||||
| if (desctype == 4 && desclen == 9) { | |||||
| // found an interface, ask available drivers if they want it | |||||
| prev = NULL; | |||||
| for (driver=available_drivers; driver != NULL; driver = driver->next) { | |||||
| if (driver->claim(dev, 1, p, end - p)) { | |||||
| // this driver claims iface | |||||
| // remove it from available_drivers list | |||||
| if (prev) { | |||||
| prev->next = driver->next; | |||||
| } else { | |||||
| available_drivers = driver->next; | |||||
| } | |||||
| // add to list of drivers using this device | |||||
| if (dev->drivers) { | |||||
| dev->drivers->next = driver; | |||||
| } | |||||
| dev->drivers = driver; | |||||
| driver->next = NULL; | |||||
| driver->device = dev; | |||||
| // not done, may be more interface for more drivers | |||||
| } | |||||
| prev = driver; | |||||
| } | |||||
| } | |||||
| p += desclen; | |||||
| } | |||||
| } | } | ||||
| static uint32_t assign_addr(void) | static uint32_t assign_addr(void) |
| driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
| } | } | ||||
| bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors) | |||||
| bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len) | |||||
| { | { | ||||
| // only claim entire device, never at interface level | // only claim entire device, never at interface level | ||||
| if (type != 0) return false; | if (type != 0) return false; |
| driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
| } | } | ||||
| bool KeyboardController::claim(Device_t *dev, int type, const uint8_t *descriptors) | |||||
| bool KeyboardController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len) | |||||
| { | { | ||||
| Serial.print("KeyboardController claim this="); | Serial.print("KeyboardController claim this="); | ||||
| Serial.println((uint32_t)this, HEX); | Serial.println((uint32_t)this, HEX); | ||||
| // only claim at interface level | // only claim at interface level | ||||
| if (type != 1) return false; | if (type != 1) return false; | ||||
| if (len < 9+9+7) return false; | |||||
| return false; | |||||
| uint32_t endpoint=1; | |||||
| uint32_t numendpoint = descriptors[4]; | |||||
| if (numendpoint < 1) return false; | |||||
| if (descriptors[5] != 3) return false; // bInterfaceClass, 3 = HID | |||||
| if (descriptors[6] != 1) return false; // bInterfaceSubClass, 1 = Boot Device | |||||
| if (descriptors[7] != 1) return false; // bInterfaceProtocol, 1 = Keyboard | |||||
| if (descriptors[9] != 9) return false; | |||||
| if (descriptors[10] != 33) return false; // HID descriptor (ignored, Boot Protocol) | |||||
| if (descriptors[18] != 7) return false; | |||||
| if (descriptors[19] != 5) return false; // endpoint descriptor | |||||
| uint32_t endpoint = descriptors[20]; | |||||
| Serial.print("ep = "); | |||||
| Serial.println(endpoint, HEX); | |||||
| if ((endpoint & 0xF0) != 0x80) return false; // must be IN direction | |||||
| endpoint &= 0x0F; | |||||
| if (endpoint == 0) return false; | |||||
| if (descriptors[21] != 3) return false; // must be interrupt type | |||||
| uint32_t size = descriptors[22] | (descriptors[23] << 8); | |||||
| Serial.print("packet size = "); | |||||
| Serial.println(size); | |||||
| if (size != 8) return false; // must be 8 bytes for Keyboard Boot Protocol | |||||
| uint32_t interval = descriptors[24]; | |||||
| Serial.print("polling interval = "); | |||||
| Serial.println(interval); | |||||
| datapipe = new_Pipe(dev, 3, endpoint, 1, 8, 64); | datapipe = new_Pipe(dev, 3, endpoint, 1, 8, 64); | ||||
| datapipe->callback_function = callback; | |||||
| queue_Data_Transfer(datapipe, report, 8, this); | queue_Data_Transfer(datapipe, report, 8, this); | ||||
| return true; | return true; | ||||
| } | } | ||||
| void KeyboardController::new_data(const Transfer_t *transfer) | void KeyboardController::new_data(const Transfer_t *transfer) | ||||
| { | { | ||||
| Serial.println("KeyboardController Callback (member)"); | Serial.println("KeyboardController Callback (member)"); | ||||
| Serial.print(" KB Data: "); | |||||
| print_hexbytes(transfer->buffer, 8); | |||||
| // TODO: parse the new data | // TODO: parse the new data | ||||
| queue_Data_Transfer(datapipe, report, 8, this); | queue_Data_Transfer(datapipe, report, 8, this); | ||||
| } | } |