| @@ -63,6 +63,7 @@ struct Device_struct { | |||
| Pipe_t *control_pipe; | |||
| Device_t *next; | |||
| setup_t setup; | |||
| USBHostDriver *driver[6]; | |||
| uint8_t speed; // 0=12, 1=1.5, 2=480 Mbit/sec | |||
| uint8_t address; | |||
| uint8_t hub_address; | |||
| @@ -159,6 +160,12 @@ protected: | |||
| static void print_hexbytes(const void *ptr, uint32_t len); | |||
| static void print(const char *s); | |||
| static void print(const char *s, int num); | |||
| static void mk_setup(setup_t &s, uint32_t bmRequestType, uint32_t bRequest, | |||
| uint32_t wValue, uint32_t wIndex, uint32_t wLength) { | |||
| s.word1 = bmRequestType | (bRequest << 8) | (wValue << 16); | |||
| s.word2 = wIndex | (wLength << 16); | |||
| } | |||
| }; | |||
| @@ -174,6 +181,9 @@ public: | |||
| virtual bool claim_interface(Device_t *device, const uint8_t *descriptors) { | |||
| return false; | |||
| } | |||
| virtual bool control_callback(const Transfer_t *transfer) { | |||
| return false; | |||
| } | |||
| virtual void disconnect() { | |||
| } | |||
| @@ -182,9 +192,11 @@ public: | |||
| class USBHub : public USBHostDriver { | |||
| public: | |||
| USBHub(); // { driver_ready_for_device(this); } | |||
| USBHub(); | |||
| virtual bool claim_device(Device_t *device, const uint8_t *descriptors); | |||
| virtual bool control_callback(const Transfer_t *transfer); | |||
| setup_t setup; | |||
| uint8_t hub_desc[12]; | |||
| }; | |||
| @@ -29,8 +29,6 @@ static USBHostDriver *available_drivers = NULL; | |||
| static uint8_t enumbuf[256] __attribute__ ((aligned(16))); | |||
| static void mk_setup(setup_t &s, uint32_t bmRequestType, uint32_t bRequest, | |||
| uint32_t wValue, uint32_t wIndex, uint32_t wLength); | |||
| static void claim_drivers(Device_t *dev); | |||
| static uint32_t assign_addr(void); | |||
| static void pipe_set_maxlen(Pipe_t *pipe, uint32_t maxlen); | |||
| @@ -206,6 +204,8 @@ void USBHost::enumeration(const Transfer_t *transfer) | |||
| Serial.println(enumbuf[4]); | |||
| Serial.print("bConfigurationValue = "); | |||
| Serial.println(enumbuf[5]); | |||
| dev->bmAttributes = enumbuf[7]; | |||
| dev->bMaxPower = enumbuf[8]; | |||
| // 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); | |||
| @@ -217,7 +217,15 @@ void USBHost::enumeration(const Transfer_t *transfer) | |||
| // TODO: unlock exclusive access to enumeration process | |||
| // if any detected devices are waiting, start the first | |||
| return; | |||
| case 15: // control transfers for other stuff?? | |||
| case 15: // control transfers for other stuff? | |||
| // TODO: handle other standard control: set/clear feature, etc | |||
| for (unsigned int i=0; i < 6; i++) { | |||
| if (dev->driver[i] == NULL) break; // no more drivers | |||
| if (dev->driver[i]->control_callback(transfer)) { | |||
| // this driver processed the control transfer reply | |||
| return; | |||
| } | |||
| } | |||
| default: | |||
| return; | |||
| } | |||
| @@ -237,6 +245,7 @@ static void claim_drivers(Device_t *dev) | |||
| available_drivers = driver->next; | |||
| } | |||
| driver->next = NULL; | |||
| dev->driver[0] = driver; | |||
| return; | |||
| } | |||
| prev = driver; | |||
| @@ -250,13 +259,6 @@ static uint32_t assign_addr(void) | |||
| return 29; // TODO: when multiple devices, assign a unique address | |||
| } | |||
| static void mk_setup(setup_t &s, uint32_t bmRequestType, uint32_t bRequest, | |||
| uint32_t wValue, uint32_t wIndex, uint32_t wLength) | |||
| { | |||
| s.word1 = bmRequestType | (bRequest << 8) | (wValue << 16); | |||
| s.word2 = wIndex | (wLength << 16); | |||
| } | |||
| static void pipe_set_maxlen(Pipe_t *pipe, uint32_t maxlen) | |||
| { | |||
| Serial.print("pipe_set_maxlen "); | |||
| @@ -35,8 +35,26 @@ bool USBHub::claim_device(Device_t *dev, const uint8_t *descriptors) | |||
| Serial.print("USBHub claim_device this="); | |||
| Serial.println((uint32_t)this, HEX); | |||
| // check for HUB type | |||
| if (dev->bDeviceClass != 9 || dev->bDeviceSubClass != 0) return false; | |||
| // protocol must be 0=FS, 1=HS Single-TT, or 2=HS Multi-TT | |||
| if (dev->bDeviceProtocol > 2) return false; | |||
| // check for endpoint descriptor | |||
| if (descriptors[9] != 7 || descriptors[10] != 5) return false; | |||
| // endpoint must be IN direction | |||
| if ((descriptors[11] & 0xF0) != 0x80) return false; | |||
| // endpoint type must be interrupt | |||
| if (descriptors[12] != 3) return false; | |||
| // get the endpoint number, must not be zero | |||
| uint32_t endpoint = descriptors[11] & 0x0F; | |||
| if (endpoint == 0) return false; | |||
| // get the maximum packet size | |||
| uint32_t maxsize = descriptors[13] | (descriptors[14] << 8); | |||
| Serial.println(descriptors[9]); | |||
| Serial.println(descriptors[10]); | |||
| Serial.println(descriptors[11], HEX); | |||
| Serial.println(maxsize); | |||
| // bDeviceProtocol = 0 is full speed | |||
| // bDeviceProtocol = 1 is high speed single TT | |||
| // bDeviceProtocol = 2 is high speed multiple TT | |||
| @@ -48,6 +66,29 @@ bool USBHub::claim_device(Device_t *dev, const uint8_t *descriptors) | |||
| Serial.print("bDeviceProtocol = "); | |||
| Serial.println(dev->bDeviceProtocol); | |||
| 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) | |||
| { | |||
| Serial.println("USBHub control callback"); | |||
| print_hexbytes(transfer->buffer, transfer->length); | |||
| return true; | |||
| } | |||
| /* | |||
| config descriptor from a Multi-TT hub | |||
| 09 02 29 00 01 01 00 E0 32 | |||
| 09 04 00 00 01 09 00 01 00 | |||
| 07 05 81 03 01 00 0C | |||
| 09 04 00 01 01 09 00 02 00 | |||
| 07 05 81 03 01 00 0C | |||
| */ | |||