@@ -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 | |||
*/ | |||