Pipe_t *control_pipe; | Pipe_t *control_pipe; | ||||
Device_t *next; | Device_t *next; | ||||
setup_t setup; | setup_t setup; | ||||
USBHostDriver *driver[6]; | |||||
uint8_t speed; // 0=12, 1=1.5, 2=480 Mbit/sec | uint8_t speed; // 0=12, 1=1.5, 2=480 Mbit/sec | ||||
uint8_t address; | uint8_t address; | ||||
uint8_t hub_address; | uint8_t hub_address; | ||||
static void print_hexbytes(const void *ptr, uint32_t len); | static void print_hexbytes(const void *ptr, uint32_t len); | ||||
static void print(const char *s); | static void print(const char *s); | ||||
static void print(const char *s, int num); | 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); | |||||
} | |||||
}; | }; | ||||
virtual bool claim_interface(Device_t *device, const uint8_t *descriptors) { | virtual bool claim_interface(Device_t *device, const uint8_t *descriptors) { | ||||
return false; | return false; | ||||
} | } | ||||
virtual bool control_callback(const Transfer_t *transfer) { | |||||
return false; | |||||
} | |||||
virtual void disconnect() { | virtual void disconnect() { | ||||
} | } | ||||
class USBHub : public USBHostDriver { | class USBHub : public USBHostDriver { | ||||
public: | public: | ||||
USBHub(); // { driver_ready_for_device(this); } | |||||
USBHub(); | |||||
virtual bool claim_device(Device_t *device, const uint8_t *descriptors); | 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]; | |||||
}; | }; | ||||
static uint8_t enumbuf[256] __attribute__ ((aligned(16))); | 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 void claim_drivers(Device_t *dev); | ||||
static uint32_t assign_addr(void); | static uint32_t assign_addr(void); | ||||
static void pipe_set_maxlen(Pipe_t *pipe, uint32_t maxlen); | static void pipe_set_maxlen(Pipe_t *pipe, uint32_t maxlen); | ||||
Serial.println(enumbuf[4]); | Serial.println(enumbuf[4]); | ||||
Serial.print("bConfigurationValue = "); | Serial.print("bConfigurationValue = "); | ||||
Serial.println(enumbuf[5]); | Serial.println(enumbuf[5]); | ||||
dev->bmAttributes = enumbuf[7]; | |||||
dev->bMaxPower = enumbuf[8]; | |||||
// TODO: actually do something with interface descriptor? | // TODO: actually do something with interface descriptor? | ||||
mk_setup(dev->setup, 0, 9, enumbuf[5], 0, 0); // 9=SET_CONFIGURATION | mk_setup(dev->setup, 0, 9, enumbuf[5], 0, 0); // 9=SET_CONFIGURATION | ||||
new_Transfer(dev->control_pipe, NULL, 0); | new_Transfer(dev->control_pipe, NULL, 0); | ||||
// TODO: unlock exclusive access to enumeration process | // TODO: unlock exclusive access to enumeration process | ||||
// if any detected devices are waiting, start the first | // if any detected devices are waiting, start the first | ||||
return; | 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: | default: | ||||
return; | return; | ||||
} | } | ||||
available_drivers = driver->next; | available_drivers = driver->next; | ||||
} | } | ||||
driver->next = NULL; | driver->next = NULL; | ||||
dev->driver[0] = driver; | |||||
return; | return; | ||||
} | } | ||||
prev = driver; | prev = driver; | ||||
return 29; // TODO: when multiple devices, assign a unique address | 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) | static void pipe_set_maxlen(Pipe_t *pipe, uint32_t maxlen) | ||||
{ | { | ||||
Serial.print("pipe_set_maxlen "); | Serial.print("pipe_set_maxlen "); |
Serial.print("USBHub claim_device this="); | Serial.print("USBHub claim_device this="); | ||||
Serial.println((uint32_t)this, HEX); | Serial.println((uint32_t)this, HEX); | ||||
// check for HUB type | |||||
if (dev->bDeviceClass != 9 || dev->bDeviceSubClass != 0) return false; | 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 = 0 is full speed | ||||
// bDeviceProtocol = 1 is high speed single TT | // bDeviceProtocol = 1 is high speed single TT | ||||
// bDeviceProtocol = 2 is high speed multiple TT | // bDeviceProtocol = 2 is high speed multiple TT | ||||
Serial.print("bDeviceProtocol = "); | Serial.print("bDeviceProtocol = "); | ||||
Serial.println(dev->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; | 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 | |||||
*/ | |||||