Browse Source

Separate setup data for enumeration & drivers

main
PaulStoffregen 7 years ago
parent
commit
de69cf9af2
4 changed files with 42 additions and 34 deletions
  1. +8
    -7
      USBHost.h
  2. +8
    -2
      ehci.cpp
  3. +22
    -21
      enumeration.cpp
  4. +4
    -4
      hub.cpp

+ 8
- 7
USBHost.h View File

struct Device_struct { struct Device_struct {
Pipe_t *control_pipe; Pipe_t *control_pipe;
Device_t *next; Device_t *next;
setup_t setup; // TODO: move this to static in enumeration.cpp
USBDriver *drivers; USBDriver *drivers;
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;
// of Transfer_t are created, these fields and the // of Transfer_t are created, these fields and the
// interrupt-on-complete bit in the qTD token are only // interrupt-on-complete bit in the qTD token are only
// set in the last Transfer_t of the list. // set in the last Transfer_t of the list.
Pipe_t *pipe;
void *buffer;
uint32_t length;
uint32_t unused[3];
Pipe_t *pipe;
void *buffer;
uint32_t length;
setup_t *setup;
USBDriver *driver;
uint32_t unused;
}; };


/************************************************/ /************************************************/
static Pipe_t * new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint, static Pipe_t * new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint,
uint32_t direction, uint32_t max_packet_len); uint32_t direction, uint32_t max_packet_len);
static bool new_Control_Transfer(Device_t *dev, setup_t *setup, static bool new_Control_Transfer(Device_t *dev, setup_t *setup,
void *buf, USBDriver *driver=NULL);
void *buf, USBDriver *driver);
static bool new_Data_Transfer(Pipe_t *pipe, void *buffer, static bool new_Data_Transfer(Pipe_t *pipe, void *buffer,
uint32_t len, USBDriver *driver); uint32_t len, USBDriver *driver);
static Device_t * new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_port); static Device_t * new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_port);
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors); virtual bool claim(Device_t *device, int type, const uint8_t *descriptors);
virtual bool control(const Transfer_t *transfer); virtual bool control(const Transfer_t *transfer);
void poweron(uint32_t port); void poweron(uint32_t port);
setup_t setup; // TODO: use this for our control transfers, not device's
setup_t setup;
uint8_t hub_desc[16]; uint8_t hub_desc[16];
uint8_t endpoint; uint8_t endpoint;
uint8_t numports; uint8_t numports;

+ 8
- 2
ehci.cpp View File

status->pipe = dev->control_pipe; status->pipe = dev->control_pipe;
status->buffer = buf; status->buffer = buf;
status->length = setup->wLength; status->length = setup->wLength;
status->setup = setup;
status->driver = driver;
status->qtd.next = 1; status->qtd.next = 1;
return queue_Transfer(dev->control_pipe, transfer); return queue_Transfer(dev->control_pipe, transfer);
} }
// copy transfer non-token fields to halt // copy transfer non-token fields to halt
halt->qtd.next = transfer->qtd.next; halt->qtd.next = transfer->qtd.next;
halt->qtd.alt_next = transfer->qtd.alt_next; halt->qtd.alt_next = transfer->qtd.alt_next;
halt->qtd.buffer[0] = transfer->qtd.buffer[0]; // TODO: optimize...
halt->qtd.buffer[1] = transfer->qtd.buffer[1];
halt->qtd.buffer[0] = transfer->qtd.buffer[0]; // TODO: optimize memcpy, all
halt->qtd.buffer[1] = transfer->qtd.buffer[1]; // fields except token
halt->qtd.buffer[2] = transfer->qtd.buffer[2]; halt->qtd.buffer[2] = transfer->qtd.buffer[2];
halt->qtd.buffer[3] = transfer->qtd.buffer[3]; halt->qtd.buffer[3] = transfer->qtd.buffer[3];
halt->qtd.buffer[4] = transfer->qtd.buffer[4]; halt->qtd.buffer[4] = transfer->qtd.buffer[4];
halt->pipe = pipe; halt->pipe = pipe;
halt->buffer = transfer->buffer;
halt->length = transfer->length;
halt->setup = transfer->setup;
halt->driver = transfer->driver;
// find the last qTD we're adding // find the last qTD we're adding
Transfer_t *last = halt; Transfer_t *last = halt;
while ((uint32_t)(last->qtd.next) != 1) last = (Transfer_t *)(last->qtd.next); while ((uint32_t)(last->qtd.next) != 1) last = (Transfer_t *)(last->qtd.next);

+ 22
- 21
enumeration.cpp View File



static USBDriver *available_drivers = NULL; static USBDriver *available_drivers = NULL;
static uint8_t enumbuf[256] __attribute__ ((aligned(16))); static uint8_t enumbuf[256] __attribute__ ((aligned(16)));
static setup_t enumsetup __attribute__ ((aligned(16)));




static uint32_t assign_addr(void); static uint32_t assign_addr(void);
// TODO: exclusive access to enumeration process // TODO: exclusive access to enumeration process
// any new devices detected while enumerating would // any new devices detected while enumerating would
// go onto a waiting list // go onto a waiting list
mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 8); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &dev->setup, enumbuf);
mk_setup(enumsetup, 0x80, 6, 0x0100, 0, 8); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &enumsetup, enumbuf, NULL);
return dev; return dev;
} }


switch (dev->enum_state) { switch (dev->enum_state) {
case 0: // read 8 bytes of device desc, set max packet, and send set address case 0: // read 8 bytes of device desc, set max packet, and send set address
pipe_set_maxlen(dev->control_pipe, enumbuf[7]); pipe_set_maxlen(dev->control_pipe, enumbuf[7]);
mk_setup(dev->setup, 0, 5, assign_addr(), 0, 0); // 5=SET_ADDRESS
new_Control_Transfer(dev, &dev->setup, NULL);
mk_setup(enumsetup, 0, 5, assign_addr(), 0, 0); // 5=SET_ADDRESS
new_Control_Transfer(dev, &enumsetup, NULL, NULL);
dev->enum_state = 1; dev->enum_state = 1;
return; return;
case 1: // request all 18 bytes of device descriptor case 1: // request all 18 bytes of device descriptor
pipe_set_addr(dev->control_pipe, dev->setup.wValue);
mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 18); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &dev->setup, enumbuf);
pipe_set_addr(dev->control_pipe, enumsetup.wValue);
mk_setup(enumsetup, 0x80, 6, 0x0100, 0, 18); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &enumsetup, enumbuf, NULL);
dev->enum_state = 2; dev->enum_state = 2;
return; return;
case 2: // parse 18 device desc bytes case 2: // parse 18 device desc bytes
break; break;
case 3: // request Language ID case 3: // request Language ID
len = sizeof(enumbuf) - 4; len = sizeof(enumbuf) - 4;
mk_setup(dev->setup, 0x80, 6, 0x0300, 0, len); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &dev->setup, enumbuf + 4);
mk_setup(enumsetup, 0x80, 6, 0x0300, 0, len); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &enumsetup, enumbuf + 4, NULL);
dev->enum_state = 4; dev->enum_state = 4;
return; return;
case 4: // parse Language ID case 4: // parse Language ID
break; break;
case 5: // request Manufacturer string case 5: // request Manufacturer string
len = sizeof(enumbuf) - 4; len = sizeof(enumbuf) - 4;
mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[0], dev->LanguageID, len);
new_Control_Transfer(dev, &dev->setup, enumbuf + 4);
mk_setup(enumsetup, 0x80, 6, 0x0300 | enumbuf[0], dev->LanguageID, len);
new_Control_Transfer(dev, &enumsetup, enumbuf + 4, NULL);
dev->enum_state = 6; dev->enum_state = 6;
return; return;
case 6: // parse Manufacturer string case 6: // parse Manufacturer string
break; break;
case 7: // request Product string case 7: // request Product string
len = sizeof(enumbuf) - 4; len = sizeof(enumbuf) - 4;
mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[1], dev->LanguageID, len);
new_Control_Transfer(dev, &dev->setup, enumbuf + 4);
mk_setup(enumsetup, 0x80, 6, 0x0300 | enumbuf[1], dev->LanguageID, len);
new_Control_Transfer(dev, &enumsetup, enumbuf + 4, NULL);
dev->enum_state = 8; dev->enum_state = 8;
return; return;
case 8: // parse Product string case 8: // parse Product string
break; break;
case 9: // request Serial Number string case 9: // request Serial Number string
len = sizeof(enumbuf) - 4; len = sizeof(enumbuf) - 4;
mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[2], dev->LanguageID, len);
new_Control_Transfer(dev, &dev->setup, enumbuf + 4);
mk_setup(enumsetup, 0x80, 6, 0x0300 | enumbuf[2], dev->LanguageID, len);
new_Control_Transfer(dev, &enumsetup, enumbuf + 4, NULL);
dev->enum_state = 10; dev->enum_state = 10;
return; return;
case 10: // parse Serial Number string case 10: // parse Serial Number string
dev->enum_state = 11; dev->enum_state = 11;
break; break;
case 11: // request first 9 bytes of config desc case 11: // request first 9 bytes of config desc
mk_setup(dev->setup, 0x80, 6, 0x0200, 0, 9); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &dev->setup, enumbuf);
mk_setup(enumsetup, 0x80, 6, 0x0200, 0, 9); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &enumsetup, enumbuf, NULL);
dev->enum_state = 12; dev->enum_state = 12;
return; return;
case 12: // read 9 bytes, request all of config desc case 12: // read 9 bytes, request all of config desc
if (len > sizeof(enumbuf)) { if (len > sizeof(enumbuf)) {
// TODO: how to handle device with too much config data // TODO: how to handle device with too much config data
} }
mk_setup(dev->setup, 0x80, 6, 0x0200, 0, len); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &dev->setup, enumbuf);
mk_setup(enumsetup, 0x80, 6, 0x0200, 0, len); // 6=GET_DESCRIPTOR
new_Control_Transfer(dev, &enumsetup, enumbuf, NULL);
dev->enum_state = 13; dev->enum_state = 13;
return; return;
case 13: // read all config desc, send set config case 13: // read all config desc, send set config
dev->bmAttributes = enumbuf[7]; dev->bmAttributes = enumbuf[7];
dev->bMaxPower = enumbuf[8]; 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
new_Control_Transfer(dev, &dev->setup, NULL);
mk_setup(enumsetup, 0, 9, enumbuf[5], 0, 0); // 9=SET_CONFIGURATION
new_Control_Transfer(dev, &enumsetup, NULL, NULL);
dev->enum_state = 14; dev->enum_state = 14;
return; return;
case 14: // device is now configured case 14: // device is now configured

+ 4
- 4
hub.cpp View File

state = 0; state = 0;


// TODO: need a way to do control transfers with our own setup data. // 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_Control_Transfer(dev, &dev->setup, hub_desc);
mk_setup(setup, 0xA0, 6, 0x2900, 0, sizeof(hub_desc));
new_Control_Transfer(dev, &setup, hub_desc, this);


return true; return true;
} }
void USBHub::poweron(uint32_t port) void USBHub::poweron(uint32_t port)
{ {
// TODO: need a way to do control transfers with our own setup data. // TODO: need a way to do control transfers with our own setup data.
mk_setup(device->setup, 0x23, 3, 8, port, 0);
new_Control_Transfer(device, &device->setup, NULL);
mk_setup(setup, 0x23, 3, 8, port, 0);
new_Control_Transfer(device, &setup, NULL, this);
} }


bool USBHub::control(const Transfer_t *transfer) bool USBHub::control(const Transfer_t *transfer)

Loading…
Cancel
Save