@@ -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); |
@@ -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 = "); |
@@ -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) |
@@ -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; |
@@ -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); | |||
} |