tinyusb/src/device/usbd.c
static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request)
{
  usbd_control_set_complete_callback(NULL);

  if ( TUSB_REQ_RCPT_DEVICE == p_request->bmRequestType_bit.recipient &&
       TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type )
  {
    //------------- Standard Device Requests e.g in enumeration -------------//
    void* data_buf = NULL;
    uint16_t data_len = 0;

    switch ( p_request->bRequest )
    {
      case TUSB_REQ_SET_ADDRESS:
        // response with status first before changing device address
        usbd_control_status(rhport, p_request);
        dcd_set_address(rhport, (uint8_t) p_request->wValue);
        return true; // skip the rest
      break;

      case TUSB_REQ_GET_CONFIGURATION:
        data_buf = &_usbd_dev.config_num;
        data_len = 1;
      break;

      case TUSB_REQ_SET_CONFIGURATION:
      {
        uint8_t const config = (uint8_t) p_request->wValue;

        dcd_set_config(rhport, config);
        _usbd_dev.config_num = config;

        TU_ASSERT( TUSB_ERROR_NONE == process_set_config(rhport) );
      }
      break;

      case TUSB_REQ_GET_DESCRIPTOR:
        data_buf = (void*) get_descriptor(p_request, &data_len);
        if ( data_buf == NULL || data_len == 0 ) return false;
      break;

      default:
        TU_BREAKPOINT();
      return false;
    }

    usbd_control_xfer(rhport, p_request, data_buf, data_len);
  }
  else if ( TUSB_REQ_RCPT_INTERFACE == p_request->bmRequestType_bit.recipient )
  {
    //------------- Class/Interface Specific Request -------------//
    uint8_t const itf = tu_u16_low(p_request->wIndex);
    uint8_t const drvid = _usbd_dev.itf2drv[ itf ];

    TU_VERIFY (drvid < USBD_CLASS_DRIVER_COUNT );

    usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_request_complete );

    // control endpoint will be stalled if driver return false
    return usbd_class_drivers[drvid].control_request(rhport, p_request);
  }
  else if ( p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT &&
            p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD )
  {
    //------------- Endpoint Request -------------//
    switch ( p_request->bRequest )
    {
      case TUSB_REQ_GET_STATUS:
      {
        uint16_t status = dcd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000;
        usbd_control_xfer(rhport, p_request, &status, 2);
      }
      break;

      case TUSB_REQ_CLEAR_FEATURE:
        // only endpoint feature is halted/stalled
        dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex));
        usbd_control_status(rhport, p_request);
      break;

      case TUSB_REQ_SET_FEATURE:
        // only endpoint feature is halted/stalled
        dcd_edpt_stall(rhport, tu_u16_low(p_request->wIndex));
        usbd_control_status(rhport, p_request);
      break;

      default:
        TU_BREAKPOINT();
      return false;
    }
  }
  else
  {
    //------------- Unsupported Request -------------//
    TU_BREAKPOINT();
    return false;
  }

  return true;
}
// This handles the actual request and its response.
// return false will cause its caller to stall control endpoint

This handles the actual request and its response.
return false will cause its caller to stall control endpoint
This handles the actual request and its response . return false will cause its caller to stall control endpoint
static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request)
{
  usbd_control_set_complete_callback(NULL);
  if ( TUSB_REQ_RCPT_DEVICE == p_request->bmRequestType_bit.recipient &&
       TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type )
  {
    void* data_buf = NULL;
    uint16_t data_len = 0;
    switch ( p_request->bRequest )
    {
      case TUSB_REQ_SET_ADDRESS:
        usbd_control_status(rhport, p_request);
        dcd_set_address(rhport, (uint8_t) p_request->wValue);
        return true; 
      break;
      case TUSB_REQ_GET_CONFIGURATION:
        data_buf = &_usbd_dev.config_num;
        data_len = 1;
      break;
      case TUSB_REQ_SET_CONFIGURATION:
      {
        uint8_t const config = (uint8_t) p_request->wValue;
        dcd_set_config(rhport, config);
        _usbd_dev.config_num = config;
        TU_ASSERT( TUSB_ERROR_NONE == process_set_config(rhport) );
      }
      break;
      case TUSB_REQ_GET_DESCRIPTOR:
        data_buf = (void*) get_descriptor(p_request, &data_len);
        if ( data_buf == NULL || data_len == 0 ) return false;
      break;
      default:
        TU_BREAKPOINT();
      return false;
    }
    usbd_control_xfer(rhport, p_request, data_buf, data_len);
  }
  else if ( TUSB_REQ_RCPT_INTERFACE == p_request->bmRequestType_bit.recipient )
  {
    uint8_t const itf = tu_u16_low(p_request->wIndex);
    uint8_t const drvid = _usbd_dev.itf2drv[ itf ];
    TU_VERIFY (drvid < USBD_CLASS_DRIVER_COUNT );
    usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_request_complete );
    return usbd_class_drivers[drvid].control_request(rhport, p_request);
  }
  else if ( p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT &&
            p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD )
  {
    switch ( p_request->bRequest )
    {
      case TUSB_REQ_GET_STATUS:
      {
        uint16_t status = dcd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000;
        usbd_control_xfer(rhport, p_request, &status, 2);
      }
      break;
      case TUSB_REQ_CLEAR_FEATURE:
        dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex));
        usbd_control_status(rhport, p_request);
      break;
      case TUSB_REQ_SET_FEATURE:
        dcd_edpt_stall(rhport, tu_u16_low(p_request->wIndex));
        usbd_control_status(rhport, p_request);
      break;
      default:
        TU_BREAKPOINT();
      return false;
    }
  }
  else
  {
    TU_BREAKPOINT();
    return false;
  }
  return true;
}
static bool process_control_request ( uint8_t rhport , tusb_control_request_t const * p_request ) { usbd_control_set_complete_callback ( NULL ) ; if ( TUSB_REQ_RCPT_DEVICE == p_request -> bmRequestType_bit . recipient && TUSB_REQ_TYPE_STANDARD == p_request -> bmRequestType_bit . type ) { void * data_buf = NULL ; uint16_t data_len = 0 ; switch ( p_request -> bRequest ) { case TUSB_REQ_SET_ADDRESS : usbd_control_status ( rhport , p_request ) ; dcd_set_address ( rhport , ( uint8_t ) p_request -> wValue ) ; return true ; break ; case TUSB_REQ_GET_CONFIGURATION : data_buf = & _usbd_dev . config_num ; data_len = 1 ; break ; case TUSB_REQ_SET_CONFIGURATION : { uint8_t const config = ( uint8_t ) p_request -> wValue ; dcd_set_config ( rhport , config ) ; _usbd_dev . config_num = config ; TU_ASSERT ( TUSB_ERROR_NONE == process_set_config ( rhport ) ) ; } break ; case TUSB_REQ_GET_DESCRIPTOR : data_buf = ( void * ) get_descriptor ( p_request , & data_len ) ; if ( data_buf == NULL || data_len == 0 ) return false ; break ; default : TU_BREAKPOINT ( ) ; return false ; } usbd_control_xfer ( rhport , p_request , data_buf , data_len ) ; } else if ( TUSB_REQ_RCPT_INTERFACE == p_request -> bmRequestType_bit . recipient ) { uint8_t const itf = tu_u16_low ( p_request -> wIndex ) ; uint8_t const drvid = _usbd_dev . itf2drv [ itf ] ; TU_VERIFY ( drvid < USBD_CLASS_DRIVER_COUNT ) ; usbd_control_set_complete_callback ( usbd_class_drivers [ drvid ] . control_request_complete ) ; return usbd_class_drivers [ drvid ] . control_request ( rhport , p_request ) ; } else if ( p_request -> bmRequestType_bit . recipient == TUSB_REQ_RCPT_ENDPOINT && p_request -> bmRequestType_bit . type == TUSB_REQ_TYPE_STANDARD ) { switch ( p_request -> bRequest ) { case TUSB_REQ_GET_STATUS : { uint16_t status = dcd_edpt_stalled ( rhport , tu_u16_low ( p_request -> wIndex ) ) ? 0x0001 : 0x0000 ; usbd_control_xfer ( rhport , p_request , & status , 2 ) ; } break ; case TUSB_REQ_CLEAR_FEATURE : dcd_edpt_clear_stall ( rhport , tu_u16_low ( p_request -> wIndex ) ) ; usbd_control_status ( rhport , p_request ) ; break ; case TUSB_REQ_SET_FEATURE : dcd_edpt_stall ( rhport , tu_u16_low ( p_request -> wIndex ) ) ; usbd_control_status ( rhport , p_request ) ; break ; default : TU_BREAKPOINT ( ) ; return false ; } } else { TU_BREAKPOINT ( ) ; return false ; } return true ; }
This handles the actual request and its response.
This handles the actual request and its response .
//------------- Standard Device Requests e.g in enumeration -------------//
 // response with status first before changing device address
 // skip the rest
 //------------- Class/Interface Specific Request -------------//
 // control endpoint will be stalled if driver return false
 //------------- Endpoint Request -------------//
 // only endpoint feature is halted/stalled
 // only endpoint feature is halted/stalled
 //------------- Unsupported Request -------------//
