summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2018-12-07 17:31:35 +0700
committerhathach <[email protected]>2018-12-07 17:31:35 +0700
commit13d08cd63681c20d30e07e8fdcb4ac8d863453a5 (patch)
tree3fb10a1f6054f9a6f33a200b907a0245f98f7d19
parent9b74f0e98f267c5fe650f501b500c2b8413f4e27 (diff)
adding new hcd api, tested working with control xfer.
- hcd_edpt_open - hcd_edpt_xfer - hcd_edpt_xfer
-rw-r--r--src/host/ehci/ehci.c140
-rw-r--r--src/host/hcd.h9
-rw-r--r--src/host/usbh.c31
3 files changed, 140 insertions, 40 deletions
diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c
index 84839b697..f941c0b4c 100644
--- a/src/host/ehci/ehci.c
+++ b/src/host/ehci/ehci.c
@@ -281,63 +281,131 @@ static tusb_error_t hcd_controller_stop(uint8_t hostid)
//--------------------------------------------------------------------+
// CONTROL PIPE API
//--------------------------------------------------------------------+
-tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
+bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc)
{
- ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+ // FIXME control only for now
+ (void) rhport;
+ hcd_pipe_control_open(dev_addr, ep_desc->wMaxPacketSize.size);
- qhd_init(p_qhd, dev_addr, max_packet_size, 0, TUSB_XFER_CONTROL, 1); // TODO binterval of control is ignored
+ return true;
+}
- if (dev_addr != 0)
- {
- //------------- insert to async list -------------//
- list_insert( (ehci_link_t*) get_async_head(_usbh_devices[dev_addr].core_id),
- (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
- }
+bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
+{
+ // FIXME control only for now
- return TUSB_ERROR_NONE;
+ hcd_pipe_control_close(dev_addr);
+
+ return true;
}
-bool hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[])
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
{
- ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+ uint8_t const epnum = edpt_number(ep_addr);
+ uint8_t const dir = edpt_dir(ep_addr);
- ehci_qtd_t *p_setup = get_control_qtds(dev_addr);
- ehci_qtd_t *p_data = p_setup + 1;
- ehci_qtd_t *p_status = p_setup + 2;
+ // FIXME control only for now
+ if ( epnum == 0 )
+ {
+ ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+ ehci_qtd_t *p_data = get_control_qtds(dev_addr);
- //------------- SETUP Phase -------------//
- qtd_init(p_setup, (uint32_t) p_request, 8);
- p_setup->pid = EHCI_PID_SETUP;
- p_setup->next.address = (uint32_t) p_data;
+ qtd_init(p_data, (uint32_t) buffer, buflen);
- //------------- DATA Phase -------------//
- if (p_request->wLength > 0)
- {
- qtd_init(p_data, (uint32_t) data, p_request->wLength);
+ // first first data toggle is always 1 (data & setup stage)
p_data->data_toggle = 1;
- p_data->pid = p_request->bmRequestType_bit.direction ? EHCI_PID_IN : EHCI_PID_OUT;
- }else
- {
- p_data = p_setup;
+ p_data->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT;
+ p_data->int_on_complete = 1;
+ p_data->next.terminate = 1;
+
+ // sw region
+ p_qhd->p_qtd_list_head = p_data;
+ p_qhd->p_qtd_list_tail = p_data;
+
+ // attach TD
+ p_qhd->qtd_overlay.next.address = (uint32_t) p_data;
}
- p_data->next.address = (uint32_t) p_status;
- //------------- STATUS Phase -------------//
- qtd_init(p_status, 0, 0); // zero-length data
- p_status->int_on_complete = 1;
- p_status->data_toggle = 1;
- p_status->pid = p_request->bmRequestType_bit.direction ? EHCI_PID_OUT : EHCI_PID_IN; // reverse direction of data phase
- p_status->next.terminate = 1;
+ return true;
+}
+
+bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
+{
+ ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+ ehci_qtd_t *p_setup = get_control_qtds(dev_addr);
+
+ qtd_init(p_setup, (uint32_t) setup_packet, 8);
+ p_setup->pid = EHCI_PID_SETUP;
+ p_setup->int_on_complete = 1;
+ p_setup->next.terminate = 1;
- //------------- Attach TDs list to Control Endpoint -------------//
+ // sw region
p_qhd->p_qtd_list_head = p_setup;
- p_qhd->p_qtd_list_tail = p_status;
+ p_qhd->p_qtd_list_tail = p_setup;
+ // attach TD
p_qhd->qtd_overlay.next.address = (uint32_t) p_setup;
return true;
}
+tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
+{
+ ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+
+ qhd_init(p_qhd, dev_addr, max_packet_size, 0, TUSB_XFER_CONTROL, 1); // TODO binterval of control is ignored
+
+ if (dev_addr != 0)
+ {
+ //------------- insert to async list -------------//
+ list_insert( (ehci_link_t*) get_async_head(_usbh_devices[dev_addr].core_id),
+ (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
+ }
+
+ return TUSB_ERROR_NONE;
+}
+
+//bool hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[])
+//{
+// ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+//
+// ehci_qtd_t *p_setup = get_control_qtds(dev_addr);
+// ehci_qtd_t *p_data = p_setup + 1;
+// ehci_qtd_t *p_status = p_setup + 2;
+//
+// //------------- SETUP Phase -------------//
+// qtd_init(p_setup, (uint32_t) p_request, 8);
+// p_setup->pid = EHCI_PID_SETUP;
+// p_setup->next.address = (uint32_t) p_data;
+//
+// //------------- DATA Phase -------------//
+// if (p_request->wLength > 0)
+// {
+// qtd_init(p_data, (uint32_t) data, p_request->wLength);
+// p_data->data_toggle = 1;
+// p_data->pid = p_request->bmRequestType_bit.direction ? EHCI_PID_IN : EHCI_PID_OUT;
+// }else
+// {
+// p_data = p_setup;
+// }
+// p_data->next.address = (uint32_t) p_status;
+//
+// //------------- STATUS Phase -------------//
+// qtd_init(p_status, 0, 0); // zero-length data
+// p_status->int_on_complete = 1;
+// p_status->data_toggle = 1;
+// p_status->pid = p_request->bmRequestType_bit.direction ? EHCI_PID_OUT : EHCI_PID_IN; // reverse direction of data phase
+// p_status->next.terminate = 1;
+//
+// //------------- Attach TDs list to Control Endpoint -------------//
+// p_qhd->p_qtd_list_head = p_setup;
+// p_qhd->p_qtd_list_tail = p_status;
+//
+// p_qhd->qtd_overlay.next.address = (uint32_t) p_setup;
+//
+// return true;
+//}
+
tusb_error_t hcd_pipe_control_close(uint8_t dev_addr)
{
//------------- TODO pipe handle validate -------------//
diff --git a/src/host/hcd.h b/src/host/hcd.h
index 104c78a36..94ee8d0fa 100644
--- a/src/host/hcd.h
+++ b/src/host/hcd.h
@@ -124,6 +124,15 @@ void hcd_int_disable(uint8_t rhport);
void hcd_event_handler(hcd_event_t const* event, bool in_isr);
//--------------------------------------------------------------------+
+// Endpoints API
+//--------------------------------------------------------------------+
+bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc);
+bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr);
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
+
+bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]);
+
+//--------------------------------------------------------------------+
// PIPE API
//--------------------------------------------------------------------+
// TODO control xfer should be used via usbh layer
diff --git a/src/host/usbh.c b/src/host/usbh.c
index 6c3194fdd..69ac042e6 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -193,14 +193,27 @@ bool usbh_init(void)
bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data)
{
usbh_device_t* dev = &_usbh_devices[dev_addr];
+ const uint8_t rhport = dev->core_id;
TU_ASSERT(osal_mutex_lock(dev->control.mutex_hdl, OSAL_TIMEOUT_NORMAL));
dev->control.request = *request;
dev->control.pipe_status = 0;
- TU_ASSERT(hcd_pipe_control_xfer(dev_addr, &dev->control.request, data));
- TU_ASSERT(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL));
+ // Setup Stage
+ hcd_setup_send(rhport, dev_addr, (uint8_t*) &dev->control.request);
+ TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL));
+
+ // Data stage : first data toggle is always 1
+ if ( request->wLength )
+ {
+ hcd_edpt_xfer(rhport, dev_addr, edpt_addr(0, request->bmRequestType_bit.direction), data, request->wLength);
+ TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL));
+ }
+
+ // Status : data toggle is always 1
+ hcd_edpt_xfer(rhport, dev_addr, edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0);
+ TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL));
osal_mutex_unlock(dev->control.mutex_hdl);
@@ -219,14 +232,24 @@ tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
osal_semaphore_reset( _usbh_devices[dev_addr].control.sem_hdl );
//osal_mutex_reset( usbh_devices[dev_addr].control.mutex_hdl );
- TU_ASSERT_ERR( hcd_pipe_control_open(dev_addr, max_packet_size) );
+ tusb_desc_endpoint_t ep0_desc =
+ {
+ .bLength = sizeof(tusb_desc_endpoint_t),
+ .bDescriptorType = TUSB_DESC_ENDPOINT,
+ .bEndpointAddress = 0,
+ .bmAttributes = { .xfer = TUSB_XFER_CONTROL },
+ .wMaxPacketSize = { .size = max_packet_size },
+ .bInterval = 0
+ };
+
+ hcd_edpt_open(_usbh_devices[dev_addr].core_id, dev_addr, &ep0_desc);
return TUSB_ERROR_NONE;
}
static inline tusb_error_t usbh_pipe_control_close(uint8_t dev_addr)
{
- TU_ASSERT_ERR( hcd_pipe_control_close(dev_addr) );
+ hcd_edpt_close(_usbh_devices[dev_addr].core_id, dev_addr, 0);
return TUSB_ERROR_NONE;
}