From 57f958c368467853782577fc7550b07ce12a3b91 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Sat, 18 Feb 2017 11:21:28 -0800 Subject: [PATCH] Drivers claim interface & add Keyboard driver claim --- USBHost.h | 6 ++--- ehci.cpp | 1 + enumeration.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++------ hub.cpp | 2 +- keyboard.cpp | 32 +++++++++++++++++++++++---- 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/USBHost.h b/USBHost.h index 1d0f201..cb0f5e7 100644 --- a/USBHost.h +++ b/USBHost.h @@ -191,7 +191,7 @@ protected: // device has its vid&pid, class/subclass fields initialized // type is 0 for device level, 1 for interface level, 2 for IAD // 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 // function is called for all drivers bound to the device. Return @@ -233,7 +233,7 @@ class USBHub : public USBDriver { public: USBHub(); 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 disconnect(); void poweron(uint32_t port); @@ -269,7 +269,7 @@ public: void attachPress(void (*keyPressed)()); void attachRelease(void (*keyReleased)()); 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(); static void callback(const Transfer_t *transfer); void new_data(const Transfer_t *transfer); diff --git a/ehci.cpp b/ehci.cpp index 5f13d66..2422164 100644 --- a/ehci.cpp +++ b/ehci.cpp @@ -58,6 +58,7 @@ void USBHost::begin() PORTE_PCR6 = PORT_PCR_MUX(1); GPIOE_PDDR |= (1<<6); GPIOE_PSOR = (1<<6); // turn on USB host power + delay(10); Serial.print("sizeof Device = "); Serial.println(sizeof(Device_t)); Serial.print("sizeof Pipe = "); diff --git a/enumeration.cpp b/enumeration.cpp index 000a167..5cf35b9 100644 --- a/enumeration.cpp +++ b/enumeration.cpp @@ -28,6 +28,7 @@ static USBDriver *available_drivers = NULL; static uint8_t enumbuf[256] __attribute__ ((aligned(16))); static setup_t enumsetup __attribute__ ((aligned(16))); +static uint16_t enumlen; static uint32_t assign_addr(void); @@ -197,13 +198,13 @@ void USBHost::enumeration(const Transfer_t *transfer) dev->enum_state = 12; return; 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.println(len); - if (len > sizeof(enumbuf)) { + Serial.println(enumlen); + if (enumlen > sizeof(enumbuf)) { // 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); dev->enum_state = 13; return; @@ -239,7 +240,7 @@ void USBHost::claim_drivers(Device_t *dev) // first check if any driver wishes to claim the entire device 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) { prev->next = driver->next; } else { @@ -252,8 +253,52 @@ void USBHost::claim_drivers(Device_t *dev) } 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) diff --git a/hub.cpp b/hub.cpp index 08ba847..cbdd7e4 100644 --- a/hub.cpp +++ b/hub.cpp @@ -30,7 +30,7 @@ USBHub::USBHub() 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 if (type != 0) return false; diff --git a/keyboard.cpp b/keyboard.cpp index eaf2bde..466bd13 100644 --- a/keyboard.cpp +++ b/keyboard.cpp @@ -31,18 +31,40 @@ KeyboardController::KeyboardController() 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.println((uint32_t)this, HEX); // only claim at interface level 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->callback_function = callback; queue_Data_Transfer(datapipe, report, 8, this); return true; } @@ -58,6 +80,8 @@ void KeyboardController::callback(const Transfer_t *transfer) void KeyboardController::new_data(const Transfer_t *transfer) { Serial.println("KeyboardController Callback (member)"); + Serial.print(" KB Data: "); + print_hexbytes(transfer->buffer, 8); // TODO: parse the new data queue_Data_Transfer(datapipe, report, 8, this); }