mirror of
https://github.com/hathach/tinyusb.git
synced 2025-04-10 03:44:22 +00:00
Merge pull request #646 from hathach/detect-clear-set-ep-status-from-class
remove the requirement of std SET/CLEAR_FEATURE must not return zlp status
This commit is contained in:
commit
89fcaf1efd
@ -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;
|
||||
|
||||
|
@ -67,12 +67,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con
|
||||
{
|
||||
// Opposite to endpoint in Data Phase
|
||||
uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN;
|
||||
|
||||
TU_LOG2(" Queue EP %02X with zlp Status\r\n", ep_addr);
|
||||
|
||||
// status direction is reversed to one in the setup packet
|
||||
// Note: Status must always be DATA1
|
||||
return dcd_edpt_xfer(rhport, ep_addr, NULL, 0);
|
||||
return usbd_edpt_xfer(rhport, ep_addr, NULL, 0);
|
||||
}
|
||||
|
||||
// Status phase
|
||||
@ -101,9 +96,7 @@ static bool _data_stage_xact(uint8_t rhport)
|
||||
if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len);
|
||||
}
|
||||
|
||||
TU_LOG2(" Queue EP %02X with %u bytes\r\n", ep_addr, xact_len);
|
||||
|
||||
return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len);
|
||||
return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len);
|
||||
}
|
||||
|
||||
// Transmit data to/from the control endpoint.
|
||||
@ -140,9 +133,6 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo
|
||||
// USBD API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Prototypes
|
||||
//--------------------------------------------------------------------+
|
||||
void usbd_control_reset(void);
|
||||
void usbd_control_set_request(tusb_control_request_t const *request);
|
||||
void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp );
|
||||
@ -153,13 +143,13 @@ void usbd_control_reset(void)
|
||||
tu_varclr(&_ctrl_xfer);
|
||||
}
|
||||
|
||||
// TODO may find a better way
|
||||
// Set complete callback
|
||||
void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp )
|
||||
{
|
||||
_ctrl_xfer.complete_cb = fp;
|
||||
}
|
||||
|
||||
// useful for dcd_set_address where DCD is responsible for status response
|
||||
// for dcd_set_address where DCD is responsible for status response
|
||||
void usbd_control_set_request(tusb_control_request_t const *request)
|
||||
{
|
||||
_ctrl_xfer.request = (*request);
|
||||
|
Loading…
x
Reference in New Issue
Block a user