Browse Source

Separate functions for data vs control transfer

main
PaulStoffregen 7 years ago
parent
commit
4b2258e5a7
4 changed files with 67 additions and 56 deletions
  1. +5
    -1
      USBHost.h
  2. +50
    -42
      ehci.cpp
  3. +10
    -11
      enumeration.cpp
  4. +2
    -2
      hub.cpp

+ 5
- 1
USBHost.h View File

protected: protected:
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_Transfer(Pipe_t *pipe, void *buffer, uint32_t len);
static bool new_Control_Transfer(Device_t *dev, setup_t *setup,
void *buf, USBDriver *driver=NULL);
static bool new_Data_Transfer(Pipe_t *pipe, void *buffer,
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);
static void enumeration(const Transfer_t *transfer); static void enumeration(const Transfer_t *transfer);
static void driver_ready_for_device(USBDriver *driver); static void driver_ready_for_device(USBDriver *driver);
private: private:
static void isr(); static void isr();
static void claim_drivers(Device_t *dev); static void claim_drivers(Device_t *dev);
static bool queue_Transfer(Pipe_t *pipe, Transfer_t *transfer);
static void init_Device_Pipe_Transfer_memory(void); static void init_Device_Pipe_Transfer_memory(void);
static Device_t * allocate_Device(void); static Device_t * allocate_Device(void);
static void free_Device(Device_t *q); static void free_Device(Device_t *q);

+ 50
- 42
ehci.cpp View File

} }




// Create a Transfer and queue it

// Create a Control Transfer and queue it
// //
bool USBHost::new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
bool USBHost::new_Control_Transfer(Device_t *dev, setup_t *setup, void *buf, USBDriver *driver)
{ {
Serial.println("new_Transfer");
Transfer_t *transfer = allocate_Transfer();
Transfer_t *transfer, *data, *status;
uint32_t status_direction;

Serial.println("new_Control_Transfer");
if (setup->wLength > 16384) return false; // max 16K data for control
transfer = allocate_Transfer();
if (!transfer) return false; if (!transfer) return false;
if (pipe->type == 0) {
// control transfer
Transfer_t *data, *status;
uint32_t status_direction;
if (len > 16384) {
// hopefully we never need more
// than 16K in a control transfer
free_Transfer(transfer);
return false;
}
status = allocate_Transfer();
if (!status) {
status = allocate_Transfer();
if (!status) {
free_Transfer(transfer);
return false;
}
if (setup->wLength > 0) {
data = allocate_Transfer();
if (!data) {
free_Transfer(transfer); free_Transfer(transfer);
free_Transfer(status);
return false; return false;
} }
if (len > 0) {
data = allocate_Transfer();
if (!data) {
free_Transfer(transfer);
free_Transfer(status);
return false;
}
init_qTD(data, buffer, len, pipe->direction, 1, false);
transfer->qtd.next = (uint32_t)data;
data->qtd.next = (uint32_t)status;
status_direction = pipe->direction ^ 1;
} else {
transfer->qtd.next = (uint32_t)status;
status_direction = 1; // always IN, USB 2.0 page 226
}
Serial.print("setup address ");
Serial.println((uint32_t)&pipe->device->setup, HEX);
init_qTD(transfer, &pipe->device->setup, 8, 2, 0, false);
init_qTD(status, NULL, 0, status_direction, 1, true);
status->pipe = pipe;
status->buffer = buffer;
status->length = len;
status->qtd.next = 1;
uint32_t pid = (setup->bmRequestType & 0x80) ? 1 : 0;
init_qTD(data, buf, setup->wLength, pid, 1, false);
transfer->qtd.next = (uint32_t)data;
data->qtd.next = (uint32_t)status;
status_direction = pid ^ 1;
} else { } else {
// bulk, interrupt or isochronous transfer
free_Transfer(transfer);
return false;
transfer->qtd.next = (uint32_t)status;
status_direction = 1; // always IN, USB 2.0 page 226
} }
Serial.print("setup address ");
Serial.println((uint32_t)setup, HEX);
init_qTD(transfer, setup, 8, 2, 0, false);
init_qTD(status, NULL, 0, status_direction, 1, true);
status->pipe = dev->control_pipe;
status->buffer = buf;
status->length = setup->wLength;
status->qtd.next = 1;
return queue_Transfer(dev->control_pipe, transfer);
}


// Create a Bulk or Interrupt Transfer and queue it
//
bool USBHost::new_Data_Transfer(Pipe_t *pipe, void *buffer, uint32_t len, USBDriver *driver)
{
Serial.println("new_Data_Transfer");
//Transfer_t *transfer = allocate_Transfer();
//if (!transfer) return false;
return false;
//return queue_Transfer(pipe, transfer);
}

bool USBHost::queue_Transfer(Pipe_t *pipe, Transfer_t *transfer)
{
// find halt qTD // find halt qTD
Transfer_t *halt = (Transfer_t *)(pipe->qh.next); Transfer_t *halt = (Transfer_t *)(pipe->qh.next);
while (!(halt->qtd.token & 0x40)) halt = (Transfer_t *)(halt->qtd.next); while (!(halt->qtd.token & 0x40)) halt = (Transfer_t *)(halt->qtd.next);

+ 10
- 11
enumeration.cpp View File

// 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 mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 8); // 6=GET_DESCRIPTOR
new_Transfer(dev->control_pipe, enumbuf, 8);

new_Control_Transfer(dev, &dev->setup, enumbuf);
return dev; return dev;
} }


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 mk_setup(dev->setup, 0, 5, assign_addr(), 0, 0); // 5=SET_ADDRESS
new_Transfer(dev->control_pipe, NULL, 0);
new_Control_Transfer(dev, &dev->setup, 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); pipe_set_addr(dev->control_pipe, dev->setup.wValue);
mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 18); // 6=GET_DESCRIPTOR mk_setup(dev->setup, 0x80, 6, 0x0100, 0, 18); // 6=GET_DESCRIPTOR
new_Transfer(dev->control_pipe, enumbuf, 18);
new_Control_Transfer(dev, &dev->setup, enumbuf);
dev->enum_state = 2; dev->enum_state = 2;
return; return;
case 2: // parse 18 device desc bytes case 2: // parse 18 device desc bytes
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 mk_setup(dev->setup, 0x80, 6, 0x0300, 0, len); // 6=GET_DESCRIPTOR
new_Transfer(dev->control_pipe, enumbuf + 4, len);
new_Control_Transfer(dev, &dev->setup, enumbuf + 4);
dev->enum_state = 4; dev->enum_state = 4;
return; return;
case 4: // parse Language ID case 4: // parse Language ID
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); mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[0], dev->LanguageID, len);
new_Transfer(dev->control_pipe, enumbuf + 4, len);
new_Control_Transfer(dev, &dev->setup, enumbuf + 4);
dev->enum_state = 6; dev->enum_state = 6;
return; return;
case 6: // parse Manufacturer string case 6: // parse Manufacturer string
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); mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[1], dev->LanguageID, len);
new_Transfer(dev->control_pipe, enumbuf + 4, len);
new_Control_Transfer(dev, &dev->setup, enumbuf + 4);
dev->enum_state = 8; dev->enum_state = 8;
return; return;
case 8: // parse Product string case 8: // parse Product string
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); mk_setup(dev->setup, 0x80, 6, 0x0300 | enumbuf[2], dev->LanguageID, len);
new_Transfer(dev->control_pipe, enumbuf + 4, len);
new_Control_Transfer(dev, &dev->setup, enumbuf + 4);
dev->enum_state = 10; dev->enum_state = 10;
return; return;
case 10: // parse Serial Number string case 10: // parse Serial Number string
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 mk_setup(dev->setup, 0x80, 6, 0x0200, 0, 9); // 6=GET_DESCRIPTOR
new_Transfer(dev->control_pipe, enumbuf, 9);
new_Control_Transfer(dev, &dev->setup, enumbuf);
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
// 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 mk_setup(dev->setup, 0x80, 6, 0x0200, 0, len); // 6=GET_DESCRIPTOR
new_Transfer(dev->control_pipe, enumbuf, len);
new_Control_Transfer(dev, &dev->setup, enumbuf);
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->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 mk_setup(dev->setup, 0, 9, enumbuf[5], 0, 0); // 9=SET_CONFIGURATION
new_Transfer(dev->control_pipe, NULL, 0);
new_Control_Transfer(dev, &dev->setup, NULL);
dev->enum_state = 14; dev->enum_state = 14;
return; return;
case 14: // device is now configured case 14: // device is now configured

+ 2
- 2
hub.cpp View File



// 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)); mk_setup(dev->setup, 0xA0, 6, 0x2900, 0, sizeof(hub_desc));
new_Transfer(dev->control_pipe, hub_desc, sizeof(hub_desc));
new_Control_Transfer(dev, &dev->setup, hub_desc);


return true; return true;
} }
{ {
// 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); mk_setup(device->setup, 0x23, 3, 8, port, 0);
new_Transfer(device->control_pipe, NULL, 0);
new_Control_Transfer(device, &device->setup, NULL);
} }


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

Loading…
Cancel
Save