fix #154 forward all endpoint recipeint request to class driver

fix typo
remove magic number 0xff of driver id
This commit is contained in:
hathach
2019-09-13 22:16:24 +07:00
parent 064adebbd0
commit ac8c343fef
2 changed files with 76 additions and 43 deletions

View File

@@ -38,7 +38,7 @@
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Macros Helper // Macros Helper
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
#define TU_ARRAY_SZIE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) #define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) )
#define TU_MIN(_x, _y) ( (_x) < (_y) ) ? (_x) : (_y) ) #define TU_MIN(_x, _y) ( (_x) < (_y) ) ? (_x) : (_y) )
#define TU_MAX(_x, _y) ( (_x) > (_y) ) ? (_x) : (_y) ) #define TU_MAX(_x, _y) ( (_x) > (_y) ) ? (_x) : (_y) )

View File

@@ -61,6 +61,9 @@ typedef struct {
static usbd_device_t _usbd_dev = { 0 }; static usbd_device_t _usbd_dev = { 0 };
// Invalid driver ID in itf2drv[] ep2drv[][] mapping
enum { DRVID_INVALID = 0xff };
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Class Driver // Class Driver
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@@ -144,7 +147,7 @@ static usbd_class_driver_t const usbd_class_drivers[] =
#endif #endif
}; };
enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SZIE(usbd_class_drivers) }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbd_class_drivers) };
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// DCD Event // DCD Event
@@ -213,8 +216,8 @@ static void usbd_reset(uint8_t rhport)
{ {
tu_varclr(&_usbd_dev); tu_varclr(&_usbd_dev);
memset(_usbd_dev.itf2drv, 0xff, sizeof(_usbd_dev.itf2drv)); // invalid mapping memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping
memset(_usbd_dev.ep2drv , 0xff, sizeof(_usbd_dev.ep2drv )); // invalid mapping memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping
usbd_control_reset(rhport); usbd_control_reset(rhport);
@@ -288,18 +291,18 @@ void tud_task (void)
// Invoke the class callback associated with the endpoint address // Invoke the class callback associated with the endpoint address
uint8_t const ep_addr = event.xfer_complete.ep_addr; uint8_t const ep_addr = event.xfer_complete.ep_addr;
uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr);
_usbd_dev.ep_busy_map[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_busy_map[dir], epnum); _usbd_dev.ep_busy_map[ep_dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_busy_map[ep_dir], epnum);
if ( 0 == tu_edpt_number(ep_addr) ) if ( 0 == epnum )
{ {
// control transfer DATA stage callback // control transfer DATA stage callback
usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
} }
else else
{ {
uint8_t const drv_id = _usbd_dev.ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)]; uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir];
TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,);
usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
@@ -435,7 +438,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
case TUSB_REQ_RCPT_INTERFACE: case TUSB_REQ_RCPT_INTERFACE:
{ {
uint8_t const itf = tu_u16_low(p_request->wIndex); uint8_t const itf = tu_u16_low(p_request->wIndex);
TU_VERIFY(itf < TU_ARRAY_SZIE(_usbd_dev.itf2drv)); TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
uint8_t const drvid = _usbd_dev.itf2drv[itf]; uint8_t const drvid = _usbd_dev.itf2drv[itf];
TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT);
@@ -465,18 +468,16 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
default: default:
// forward to class driver: "STD request to Interface" // forward to class driver: "STD request to Interface"
// GET HID REPORT DESCRIPTOR falls into this case // GET HID REPORT DESCRIPTOR falls into this case
usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete);
// stall control endpoint if driver return false // stall control endpoint if driver return false
usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete);
TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request));
break; break;
} }
}else }else
{ {
// forward to class driver: "non-STD request to Interface" // forward to class driver: "non-STD request to Interface"
usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete);
// stall control endpoint if driver return false // stall control endpoint if driver return false
usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete);
TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request));
} }
} }
@@ -484,14 +485,42 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
//------------- Endpoint Request -------------// //------------- Endpoint Request -------------//
case TUSB_REQ_RCPT_ENDPOINT: case TUSB_REQ_RCPT_ENDPOINT:
// Non standard request is not supported {
TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ); uint8_t const ep_addr = tu_u16_low(p_request->wIndex);
uint8_t const ep_num = tu_edpt_number(ep_addr);
uint8_t const ep_dir = tu_edpt_dir(ep_addr);
TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) );
uint8_t const drv_id = _usbd_dev.ep2drv[ep_num][ep_dir];
TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT);
// Some classes such as TMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request
// We will forward all request targeted endpoint to its class driver
// - For non-standard request: driver can ACK or Stall the request by return true/false
// - For standard request: usbd decide the ACK stage regardless of driver return value
bool ret;
if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type )
{
// complete callback is also capable of stalling/acking the request
usbd_control_set_complete_callback(usbd_class_drivers[drv_id].control_complete);
}
// Invoke class driver first
ret = usbd_class_drivers[drv_id].control_request(rhport, p_request);
// Then handle if it is standard request
if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type )
{
// force return true for standard request
ret = true;
switch ( p_request->bRequest ) switch ( p_request->bRequest )
{ {
case TUSB_REQ_GET_STATUS: case TUSB_REQ_GET_STATUS:
{ {
uint16_t status = usbd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000; uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000;
tud_control_xfer(rhport, p_request, &status, 2); tud_control_xfer(rhport, p_request, &status, 2);
} }
break; break;
@@ -499,7 +528,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
case TUSB_REQ_CLEAR_FEATURE: case TUSB_REQ_CLEAR_FEATURE:
if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
{ {
usbd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex)); usbd_edpt_clear_stall(rhport, ep_addr);
} }
tud_control_status(rhport, p_request); tud_control_status(rhport, p_request);
break; break;
@@ -507,7 +536,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
case TUSB_REQ_SET_FEATURE: case TUSB_REQ_SET_FEATURE:
if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
{ {
usbd_edpt_stall(rhport, tu_u16_low(p_request->wIndex)); usbd_edpt_stall(rhport, ep_addr);
} }
tud_control_status(rhport, p_request); tud_control_status(rhport, p_request);
break; break;
@@ -515,6 +544,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Unknown/Unsupported request // Unknown/Unsupported request
default: TU_BREAKPOINT(); return false; default: TU_BREAKPOINT(); return false;
} }
}
return ret;
}
break; break;
// Unknown recipient // Unknown recipient
@@ -560,7 +593,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT );
// Interface number must not be used already TODO alternate interface // Interface number must not be used already TODO alternate interface
TU_ASSERT( 0xff == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] );
_usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id;
uint16_t itf_len=0; uint16_t itf_len=0;