|
|
@@ -485,6 +485,12 @@ void tud_task (void)
|
|
|
// But it is easier to set it every time instead of wasting time to check then set
|
|
|
_usbd_dev.connected = 1;
|
|
|
|
|
|
+ // mark both in & out control as free
|
|
|
+ _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false;
|
|
|
+ _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0;
|
|
|
+ _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false;
|
|
|
+ _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0;
|
|
|
+
|
|
|
// Process control request
|
|
|
if ( !process_control_request(event.rhport, &event.setup_received) )
|
|
|
{
|
|
|
@@ -605,6 +611,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
|
|
|
// forward to class driver: "non-STD request to Interface"
|
|
|
return invoke_class_control(rhport, driver, p_request);
|
|
|
}
|
|
|
+
|
|
|
if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type )
|
|
|
{
|
|
|
// Non standard request is not supported
|
|
|
@@ -712,14 +719,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
|
|
|
|
|
|
TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) );
|
|
|
|
|
|
- bool ret = false;
|
|
|
+ usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]);
|
|
|
|
|
|
- // Handle STD request to endpoint
|
|
|
- if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type )
|
|
|
+ if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type )
|
|
|
{
|
|
|
- // force return true for standard request
|
|
|
- ret = true;
|
|
|
-
|
|
|
+ // Forward class request to its driver
|
|
|
+ TU_VERIFY(driver);
|
|
|
+ return invoke_class_control(rhport, driver, p_request);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Handle STD request to endpoint
|
|
|
switch ( p_request->bRequest )
|
|
|
{
|
|
|
case TUSB_REQ_GET_STATUS:
|
|
|
@@ -730,40 +740,39 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
|
|
|
break;
|
|
|
|
|
|
case TUSB_REQ_CLEAR_FEATURE:
|
|
|
- if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_clear_stall(rhport, ep_addr);
|
|
|
- tud_control_status(rhport, p_request);
|
|
|
- break;
|
|
|
-
|
|
|
case TUSB_REQ_SET_FEATURE:
|
|
|
- if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_stall(rhport, ep_addr);
|
|
|
- tud_control_status(rhport, p_request);
|
|
|
+ {
|
|
|
+ if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
|
|
|
+ {
|
|
|
+ if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest )
|
|
|
+ {
|
|
|
+ usbd_edpt_clear_stall(rhport, ep_addr);
|
|
|
+ }else
|
|
|
+ {
|
|
|
+ usbd_edpt_stall(rhport, ep_addr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (driver)
|
|
|
+ {
|
|
|
+ // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request
|
|
|
+ // We will also forward std request targeted endpoint to class drivers as well
|
|
|
+
|
|
|
+ // STD request must always be ACKed regardless of driver returned value
|
|
|
+ // Also clear complete callback if driver set since it can also stall the request.
|
|
|
+ (void) invoke_class_control(rhport, driver, p_request);
|
|
|
+ usbd_control_set_complete_callback(NULL);
|
|
|
+
|
|
|
+ // skip ZLP status if driver already did that
|
|
|
+ if ( !_usbd_dev.ep_status[0][TUSB_DIR_IN].busy ) tud_control_status(rhport, p_request);
|
|
|
+ }
|
|
|
+ }
|
|
|
break;
|
|
|
|
|
|
// Unknown/Unsupported request
|
|
|
default: TU_BREAKPOINT(); return false;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]);
|
|
|
-
|
|
|
- if (driver)
|
|
|
- {
|
|
|
- // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request
|
|
|
- // We will forward all request targeted endpoint to class drivers after
|
|
|
- // - For class-type requests: driver is fully responsible to reply to host
|
|
|
- // - For std-type requests : driver init/re-init internal variable/buffer only, and
|
|
|
- // must not call tud_control_status(), driver's return value will have no effect.
|
|
|
- // EP state has already affected (stalled/cleared)
|
|
|
- if ( invoke_class_control(rhport, driver, p_request) ) ret = true;
|
|
|
- }
|
|
|
-
|
|
|
- if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type )
|
|
|
- {
|
|
|
- // Set complete callback = NULL since it can also stall the request.
|
|
|
- usbd_control_set_complete_callback(NULL);
|
|
|
- }
|
|
|
-
|
|
|
- return ret;
|
|
|
}
|
|
|
break;
|
|
|
|