[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cdi-devel] [PATCH 08/10] usb: Clear ENDPOINT_HALT on stalling bulk transfer



+ If a bulk transfer stalled, it is a good idea to clear the
  ENDPOINT_HALT feature for the endpoint in question.
  (We generally do not need this for control transfers, because while
  they may return a STALL, they should not actually stall (that is, the
  ENDPOINT_HALT feature will not be set; this is what the USB
  specification recommends). Also, all of our control transfers
  currently go to EP 0 which really, really should not get halted. If it
  is, the device is pretty broken (you need EP 0 to clear the
  ENDPOINT_HALT feature).)
  (We will not really need this for interrupt transfers, just because it
  is more unlikely for them to stall than for bulk transfers.)

Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
 include/cdi/usb-structures.h |  8 ++++++++
 usb/usb.c                    | 10 ++++++++++
 2 files changed, 18 insertions(+)

diff --git a/include/cdi/usb-structures.h b/include/cdi/usb-structures.h
index f894b9e..45b0d98 100644
--- a/include/cdi/usb-structures.h
+++ b/include/cdi/usb-structures.h
@@ -130,6 +130,14 @@ enum {
     CDI_USB_CREQ_SYNCH_FRAME        = 12,
 };
 
+/// Feature selectors for ClearFeature() and SetFeature()
+/// (cdi_usb_setup_packet.w_value)
+enum {
+    CDI_USB_FEATURE_ENDPOINT_HALT           = 0,
+    CDI_USB_FEATURE_DEVICE_REMOTE_WAKEUP    = 1,
+    CDI_USB_FEATURE_TEST_MODE               = 2,
+};
+
 /// Descriptor IDs
 enum {
     CDI_USB_DESC_DEVICE         = 1,
diff --git a/usb/usb.c b/usb/usb.c
index 374ba57..4e1dacc 100644
--- a/usb/usb.c
+++ b/usb/usb.c
@@ -755,6 +755,16 @@ cdi_usb_transmission_result_t usb_bulk_transfer(struct cdi_usb_device *dev,
     hcd->wait_transaction(ldev->dev->hc, ta);
     hcd->destroy_transaction(ldev->dev->hc, ta);
 
+    if (res == CDI_USB_STALL) {
+        usb_control_transfer(dev, 0, &(struct cdi_usb_setup_packet){
+                .bm_request_type    = CDI_USB_CREQ_ENDPOINT
+                                    | CDI_USB_CREQ_OUT,
+                .b_request          = CDI_USB_CREQ_CLEAR_FEATURE,
+                .w_value            = CDI_USB_FEATURE_ENDPOINT_HALT,
+                .w_index            = ep
+            }, NULL);
+    }
+
     return res;
 }
 
-- 
2.6.4