diff --git a/USBHost.h b/USBHost.h index 184de5d..2c5e04e 100644 --- a/USBHost.h +++ b/USBHost.h @@ -62,8 +62,7 @@ typedef union { struct Device_struct { Pipe_t *control_pipe; Device_t *next; - setup_t setup; - //USBHostDriver *driver[6]; + setup_t setup; // TODO: move this to static in enumeration.cpp USBHostDriver *drivers; uint8_t speed; // 0=12, 1=1.5, 2=480 Mbit/sec uint8_t address; @@ -146,6 +145,7 @@ protected: static void driver_ready_for_device(USBHostDriver *driver); private: static void isr(); + static void claim_drivers(Device_t *dev); static void init_Device_Pipe_Transfer_memory(void); static Device_t * allocate_Device(void); static void free_Device(Device_t *q); @@ -175,29 +175,55 @@ protected: /************************************************/ class USBHostDriver : public USBHost { -public: - virtual bool claim_device(Device_t *device, const uint8_t *descriptors) { +protected: + USBHostDriver() : next(NULL), device(NULL) {} + // Check if a driver wishes to claim a device or interface or group + // of interfaces within a device. When this function returns true, + // the driver is considered bound or loaded for that device. When + // new devices are detected, enumeration.cpp calls this function on + // all unbound driver objects, to give them an opportunity to bind + // to the new device. + // 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) { return false; } - virtual bool claim_interface(Device_t *device, const uint8_t *descriptors) { - return false; - } - virtual bool control_callback(const Transfer_t *transfer) { + // When an unknown (not chapter 9) control transfer completes, this + // function is called for all drivers bound to the device. Return + // true means this driver originated this control transfer, so no + // more drivers need to be offered an opportunity to process it. + virtual bool control(const Transfer_t *transfer) { return false; } + // When a device disconnects from the USB, this function is called. + // The driver must free all resources it has allocated. virtual void disconnect() { } - + // Drivers are managed by this single-linked list. All inactive + // (not bound to any device) drivers are linked from + // available_drivers is enumeration.cpp. When bound to a device, + // drivers are linked from that Device_t drivers list. USBHostDriver *next; + // When not bound to any device, this must be NULL. + Device_t *device; + friend class USBHost; +public: + // TODO: user-level functions + // check if device is bound/active/online + // query vid, pid + // query string: manufacturer, product, serial number }; class USBHub : public USBHostDriver { public: USBHub(); - virtual bool claim_device(Device_t *device, const uint8_t *descriptors); - virtual bool control_callback(const Transfer_t *transfer); - setup_t setup; +protected: + virtual bool claim(Device_t *device, int type, const uint8_t *descriptors); + virtual bool control(const Transfer_t *transfer); + setup_t setup; // TODO: use this for our control transfers, not device's uint8_t hub_desc[12]; + uint32_t change; }; diff --git a/enumeration.cpp b/enumeration.cpp index 8740bfb..7edb6f7 100644 --- a/enumeration.cpp +++ b/enumeration.cpp @@ -29,7 +29,6 @@ static USBHostDriver *available_drivers = NULL; static uint8_t enumbuf[256] __attribute__ ((aligned(16))); -static void claim_drivers(Device_t *dev); static uint32_t assign_addr(void); static void pipe_set_maxlen(Pipe_t *pipe, uint32_t maxlen); static void pipe_set_addr(Pipe_t *pipe, uint32_t addr); @@ -220,7 +219,7 @@ void USBHost::enumeration(const Transfer_t *transfer) case 15: // control transfers for other stuff? // TODO: handle other standard control: set/clear feature, etc for (USBHostDriver *d = dev->drivers; d != NULL; d = d->next) { - if (d->control_callback(transfer)) { + if (d->control(transfer)) { // this driver processed the control transfer reply return; } @@ -231,18 +230,19 @@ void USBHost::enumeration(const Transfer_t *transfer) } } -static void claim_drivers(Device_t *dev) +void USBHost::claim_drivers(Device_t *dev) { USBHostDriver *driver, *prev=NULL; // first check if any driver wishes to claim the entire device for (driver=available_drivers; driver != NULL; driver = driver->next) { - if (driver->claim_device(dev, enumbuf + 9)) { + if (driver->claim(dev, 0, enumbuf + 9)) { if (prev) { prev->next = driver->next; } else { available_drivers = driver->next; } + driver->device = dev; driver->next = NULL; dev->drivers = driver; return; diff --git a/hub.cpp b/hub.cpp index a3cc7e9..c13f3ce 100644 --- a/hub.cpp +++ b/hub.cpp @@ -30,8 +30,11 @@ USBHub::USBHub() driver_ready_for_device(this); } -bool USBHub::claim_device(Device_t *dev, const uint8_t *descriptors) +bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors) { + // only claim entire device, never at interface level + if (type != 0) return false; + Serial.print("USBHub claim_device this="); Serial.println((uint32_t)this, HEX); @@ -66,17 +69,25 @@ bool USBHub::claim_device(Device_t *dev, const uint8_t *descriptors) Serial.print("bDeviceProtocol = "); Serial.println(dev->bDeviceProtocol); + // TODO: need a way to do control transfers with our own setup data. mk_setup(dev->setup, 0xA0, 6, 0x2900, 0, sizeof(hub_desc)); new_Transfer(dev->control_pipe, hub_desc, sizeof(hub_desc)); - // TODO: need to arrange for callback to this driver from enumeration.cpp return true; } -bool USBHub::control_callback(const Transfer_t *transfer) +bool USBHub::control(const Transfer_t *transfer) { - Serial.println("USBHub control callback"); - print_hexbytes(transfer->buffer, transfer->length); + if (transfer->buffer == hub_desc) { + Serial.println("USBHub control callback"); + print_hexbytes(transfer->buffer, transfer->length); + if (hub_desc[0] == 9 && hub_desc[1] == 0x29) { + + + + } + } + return true; }