From 4b2258e5a70cec1858cc1b720cc3fc428042bdba Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Sun, 12 Feb 2017 12:54:10 -0800 Subject: [PATCH] Separate functions for data vs control transfer --- USBHost.h | 6 +++- ehci.cpp | 96 ++++++++++++++++++++++++++----------------------- enumeration.cpp | 21 ++++++----- hub.cpp | 4 +-- 4 files changed, 69 insertions(+), 58 deletions(-) diff --git a/USBHost.h b/USBHost.h index 61063e0..c3469a3 100644 --- a/USBHost.h +++ b/USBHost.h @@ -139,13 +139,17 @@ public: protected: static Pipe_t * new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint, 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 void enumeration(const Transfer_t *transfer); static void driver_ready_for_device(USBDriver *driver); private: static void isr(); 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 Device_t * allocate_Device(void); static void free_Device(Device_t *q); diff --git a/ehci.cpp b/ehci.cpp index a43c6aa..85bc994 100644 --- a/ehci.cpp +++ b/ehci.cpp @@ -411,56 +411,64 @@ static void init_qTD(volatile Transfer_t *t, void *buf, uint32_t len, } -// 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 (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) { - free_Transfer(transfer); - 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; - } else { - // bulk, interrupt or isochronous transfer + status = allocate_Transfer(); + if (!status) { free_Transfer(transfer); return false; } + if (setup->wLength > 0) { + data = allocate_Transfer(); + if (!data) { + free_Transfer(transfer); + free_Transfer(status); + return false; + } + 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 { + 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 Transfer_t *halt = (Transfer_t *)(pipe->qh.next); while (!(halt->qtd.token & 0x40)) halt = (Transfer_t *)(halt->qtd.next); diff --git a/enumeration.cpp b/enumeration.cpp index 4538e6d..398fe58 100644 --- a/enumeration.cpp +++ b/enumeration.cpp @@ -81,8 +81,7 @@ Device_t * USBHost::new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_p // any new devices detected while enumerating would // go onto a waiting list 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; } @@ -109,13 +108,13 @@ void USBHost::enumeration(const Transfer_t *transfer) case 0: // read 8 bytes of device desc, set max packet, and send set address pipe_set_maxlen(dev->control_pipe, enumbuf[7]); 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; return; 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_Transfer(dev->control_pipe, enumbuf, 18); + new_Control_Transfer(dev, &dev->setup, enumbuf); dev->enum_state = 2; return; case 2: // parse 18 device desc bytes @@ -136,7 +135,7 @@ void USBHost::enumeration(const Transfer_t *transfer) case 3: // request Language ID len = sizeof(enumbuf) - 4; 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; return; case 4: // parse Language ID @@ -153,7 +152,7 @@ void USBHost::enumeration(const Transfer_t *transfer) case 5: // request Manufacturer string len = sizeof(enumbuf) - 4; 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; return; case 6: // parse Manufacturer string @@ -165,7 +164,7 @@ void USBHost::enumeration(const Transfer_t *transfer) case 7: // request Product string len = sizeof(enumbuf) - 4; 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; return; case 8: // parse Product string @@ -176,7 +175,7 @@ void USBHost::enumeration(const Transfer_t *transfer) case 9: // request Serial Number string len = sizeof(enumbuf) - 4; 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; return; case 10: // parse Serial Number string @@ -185,7 +184,7 @@ void USBHost::enumeration(const Transfer_t *transfer) break; case 11: // request first 9 bytes of config desc 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; return; case 12: // read 9 bytes, request all of config desc @@ -196,7 +195,7 @@ void USBHost::enumeration(const Transfer_t *transfer) // TODO: how to handle device with too much config data } 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; return; case 13: // read all config desc, send set config @@ -208,7 +207,7 @@ void USBHost::enumeration(const Transfer_t *transfer) 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); + new_Control_Transfer(dev, &dev->setup, NULL); dev->enum_state = 14; return; case 14: // device is now configured diff --git a/hub.cpp b/hub.cpp index 6925ea9..18b3a10 100644 --- a/hub.cpp +++ b/hub.cpp @@ -77,7 +77,7 @@ bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors) // 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_Transfer(dev->control_pipe, hub_desc, sizeof(hub_desc)); + new_Control_Transfer(dev, &dev->setup, hub_desc); return true; } @@ -86,7 +86,7 @@ void USBHub::poweron(uint32_t port) { // TODO: need a way to do control transfers with our own setup data. 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)