瀏覽代碼

implement usbh_edpt_busy (WIP), remove hcd_edpt_busy

hathach 4 年之前
父節點
當前提交
c7f51cde40

+ 5 - 5
src/class/cdc/cdc_host.c

@@ -73,13 +73,13 @@ bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid)
   switch (pipeid)
   {
     case CDC_PIPE_NOTIFICATION:
-      return hcd_edpt_busy(dev_addr, p_cdc->ep_notif );
+      return usbh_edpt_busy(dev_addr, p_cdc->ep_notif );
 
     case CDC_PIPE_DATA_IN:
-      return hcd_edpt_busy(dev_addr, p_cdc->ep_in );
+      return usbh_edpt_busy(dev_addr, p_cdc->ep_in );
 
     case CDC_PIPE_DATA_OUT:
-      return hcd_edpt_busy(dev_addr, p_cdc->ep_out );
+      return usbh_edpt_busy(dev_addr, p_cdc->ep_out );
 
     default:
       return false;
@@ -103,7 +103,7 @@ bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool i
   TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA);
 
   uint8_t const ep_out = cdch_data[dev_addr-1].ep_out;
-  if ( hcd_edpt_busy(dev_addr, ep_out) ) return false;
+  if ( usbh_edpt_busy(dev_addr, ep_out) ) return false;
 
   return usbh_edpt_xfer(dev_addr, ep_out, (void *) p_data, length);
 }
@@ -115,7 +115,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is
   TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA);
 
   uint8_t const ep_in = cdch_data[dev_addr-1].ep_in;
-  if ( hcd_edpt_busy(dev_addr, ep_in) ) return false;
+  if ( usbh_edpt_busy(dev_addr, ep_in) ) return false;
 
   return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length);
 }

+ 1 - 1
src/class/hid/hid_host.c

@@ -201,7 +201,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u
 //  TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance));
 //
 //  hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
-//  return !hcd_edpt_busy(dev_addr, hid_itf->ep_in);
+//  return !usbh_edpt_busy(dev_addr, hid_itf->ep_in);
 //}
 
 //void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len);

+ 1 - 1
src/class/msc/msc_host.c

@@ -111,7 +111,7 @@ bool tuh_msc_mounted(uint8_t dev_addr)
 bool tuh_msc_ready(uint8_t dev_addr)
 {
   msch_interface_t* p_msc = get_itf(dev_addr);
-  return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in);
+  return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in);
 }
 
 //--------------------------------------------------------------------+

+ 1 - 1
src/device/dcd.h

@@ -122,7 +122,7 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK;
 void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK;
 
 // Configure endpoint's registers according to descriptor
-bool dcd_edpt_open            (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc);
+bool dcd_edpt_open            (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep);
 
 // Close an endpoint.
 // Since it is weak, caller must TU_ASSERT this function's existence before calling it.

+ 2 - 2
src/device/usbd.c

@@ -1248,8 +1248,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
   // Attempt to transfer on a busy endpoint, sound like an race condition !
   TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0);
 
-  // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return
-  // and usbd task can preempt and clear the busy
+  // Set busy first since the actual transfer can be complete before dcd_edpt_xfer()
+  // could return and USBD task can preempt and clear the busy
   _usbd_dev.ep_status[epnum][dir].busy = true;
 
   if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) )

+ 0 - 2
src/host/hcd.h

@@ -137,8 +137,6 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr);
 bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]);
 bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
 bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
-
-bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr);
 bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr);
 
 //--------------------------------------------------------------------+

+ 43 - 3
src/host/usbh.c

@@ -314,8 +314,11 @@ uint8_t* usbh_get_enum_buf(void)
   return _usbh_ctrl_buf;
 }
 
-//------------- Endpoint API -------------//
+//--------------------------------------------------------------------+
+// Endpoint API
+//--------------------------------------------------------------------+
 
+// TODO has some duplication code with device, refactor later
 bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
 {
   uint8_t const epnum = tu_edpt_number(ep_addr);
@@ -343,6 +346,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
   return ret;
 }
 
+// TODO has some duplication code with device, refactor later
 bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
 {
   uint8_t const epnum = tu_edpt_number(ep_addr);
@@ -368,11 +372,36 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
   return ret;
 }
 
+// TODO has some duplication code with device, refactor later
 bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
 {
+  uint8_t const epnum = tu_edpt_number(ep_addr);
+  uint8_t const dir   = tu_edpt_dir(ep_addr);
+
   usbh_device_t* dev = &_usbh_devices[dev_addr];
-  TU_LOG2("  Queue EP %02X with %u bytes ... OK\r\n", ep_addr, total_bytes);
-  return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes);
+
+  TU_LOG2("  Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
+
+  // Attempt to transfer on a busy endpoint, sound like an race condition !
+  TU_ASSERT(dev->ep_status[epnum][dir].busy == 0);
+
+  // Set busy first since the actual transfer can be complete before hcd_edpt_xfer()
+  // could return and USBH task can preempt and clear the busy
+  dev->ep_status[epnum][dir].busy = true;
+
+  if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) )
+  {
+    TU_LOG2("OK\r\n");
+    return true;
+  }else
+  {
+    // HCD error, mark endpoint as ready to allow next transfer
+    dev->ep_status[epnum][dir].busy = false;
+    dev->ep_status[epnum][dir].claimed = 0;
+    TU_LOG2("failed\r\n");
+    TU_BREAKPOINT();
+    return false;
+  }
 }
 
 bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
@@ -419,6 +448,17 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
   return ret;
 }
 
+bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
+{
+  uint8_t const epnum = tu_edpt_number(ep_addr);
+  uint8_t const dir   = tu_edpt_dir(ep_addr);
+
+  usbh_device_t* dev = &_usbh_devices[dev_addr];
+
+  return dev->ep_status[epnum][dir].busy;
+}
+
+
 //--------------------------------------------------------------------+
 // HCD Event Handler
 //--------------------------------------------------------------------+

+ 13 - 6
src/host/usbh_classdriver.h

@@ -52,22 +52,29 @@ typedef struct {
   void (* const close      )(uint8_t dev_addr);
 } usbh_class_driver_t;
 
+// Call by class driver to tell USBH that it has complete the enumeration
+void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num);
+
+uint8_t usbh_get_rhport(uint8_t dev_addr);
+
+uint8_t* usbh_get_enum_buf(void);
+
 //--------------------------------------------------------------------+
 // USBH Endpoint API
 //--------------------------------------------------------------------+
 
-bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
+// Open an endpoint
+bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep);
+
+// Submit a usb transfer
 bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
 
 // Claim an endpoint before submitting a transfer.
 // If caller does not make any transfer, it must release endpoint for others.
 bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr);
 
-void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num);
-
-uint8_t usbh_get_rhport(uint8_t dev_addr);
-
-uint8_t* usbh_get_enum_buf(void);
+// Check if endpoint transferring is complete
+bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr);
 
 #ifdef __cplusplus
  }

+ 0 - 6
src/portable/ehci/ehci.c

@@ -440,12 +440,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
   return true;
 }
 
-bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
-{
-  ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr);
-  return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL);
-}
-
 bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
 {
   ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr);

+ 0 - 6
src/portable/ohci/ohci.c

@@ -489,12 +489,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
   return true;
 }
 
-bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
-{
-  ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr);
-  return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail);
-}
-
 bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
 {
   ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr);

+ 13 - 13
src/portable/raspberrypi/rp2040/hcd_rp2040.c

@@ -515,19 +515,19 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
     return true;
 }
 
-bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
-{
-    // EPX is shared, so multiple device addresses and endpoint addresses share that
-    // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own
-    // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint
-    // on that device
-    pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr);
-    struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
-    assert(ep);
-    bool busy = ep->active;
-    pico_trace("busy == %d\n", busy);
-    return busy;
-}
+//bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
+//{
+//    // EPX is shared, so multiple device addresses and endpoint addresses share that
+//    // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own
+//    // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint
+//    // on that device
+//    pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr);
+//    struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
+//    assert(ep);
+//    bool busy = ep->active;
+//    pico_trace("busy == %d\n", busy);
+//    return busy;
+//}
 
 bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
 {