mirror of
https://github.com/gdsports/USBHost_t36
synced 2025-02-17 07:20:25 -05:00
Separate functions for data vs control transfer
This commit is contained in:
parent
93c40091da
commit
4b2258e5a7
@ -139,13 +139,17 @@ public:
|
|||||||
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);
|
||||||
|
96
ehci.cpp
96
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, *data, *status;
|
||||||
Transfer_t *transfer = allocate_Transfer();
|
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) {
|
status = allocate_Transfer();
|
||||||
// control transfer
|
if (!status) {
|
||||||
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
|
|
||||||
free_Transfer(transfer);
|
free_Transfer(transfer);
|
||||||
return false;
|
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
|
// 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);
|
||||||
|
@ -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
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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
|
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
|
||||||
@ -136,7 +135,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
|
|||||||
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
|
||||||
@ -153,7 +152,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
|
|||||||
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
|
||||||
@ -165,7 +164,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
|
|||||||
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
|
||||||
@ -176,7 +175,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
|
|||||||
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
|
||||||
@ -185,7 +184,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
|
|||||||
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
|
||||||
@ -196,7 +195,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
|
|||||||
// 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
|
||||||
@ -208,7 +207,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
|
|||||||
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
|
||||||
|
4
hub.cpp
4
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.
|
// 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;
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ 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);
|
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…
Reference in New Issue
Block a user