Kaynağa Gözat

adding new hcd api, tested working with control xfer.

- hcd_edpt_open
- hcd_edpt_xfer
- hcd_edpt_xfer
hathach 7 yıl önce
ebeveyn
işleme
13d08cd636
3 değiştirilmiş dosya ile 140 ekleme ve 40 silme
  1. 104 36
      src/host/ehci/ehci.c
  2. 9 0
      src/host/hcd.h
  3. 27 4
      src/host/usbh.c

+ 104 - 36
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 -------------//

+ 9 - 0
src/host/hcd.h

@@ -123,6 +123,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
 //--------------------------------------------------------------------+

+ 27 - 4
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;
 }