| @@ -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); | |||
| @@ -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) { | |||
| 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; | |||
| } | |||
| 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 { | |||
| // 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 | |||
| Transfer_t *halt = (Transfer_t *)(pipe->qh.next); | |||
| while (!(halt->qtd.token & 0x40)) halt = (Transfer_t *)(halt->qtd.next); | |||
| @@ -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 | |||
| @@ -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) | |||