mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-28 16:20:26 +00:00
Merge pull request #557 from hathach/rework-class-driver-control
Rework class driver control transfer
This commit is contained in:
commit
49f09f55d0
@ -143,9 +143,14 @@ void tud_resume_cb(void)
|
||||
// WebUSB use vendor class
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when received VENDOR control request
|
||||
bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request)
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
|
||||
{
|
||||
// nothing to with DATA & ACK stage
|
||||
if (stage != CONTROL_STAGE_SETUP ) return true;
|
||||
|
||||
switch (request->bRequest)
|
||||
{
|
||||
case VENDOR_REQUEST_WEBUSB:
|
||||
@ -194,16 +199,6 @@ bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const
|
||||
return true;
|
||||
}
|
||||
|
||||
// Invoked when DATA Stage of VENDOR's request is complete
|
||||
bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) request;
|
||||
|
||||
// nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
void webserial_task(void)
|
||||
{
|
||||
if ( web_serial_connected )
|
||||
|
@ -989,7 +989,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
|
||||
|
||||
// Invoked when class request DATA stage is finished.
|
||||
// return false to stall control EP (e.g Host send non-sense DATA)
|
||||
bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
{
|
||||
// Handle audio class specific set requests
|
||||
if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT)
|
||||
@ -1065,7 +1065,7 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re
|
||||
|
||||
// Handle class control request
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
@ -1175,6 +1175,20 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req
|
||||
return false;
|
||||
}
|
||||
|
||||
bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
|
||||
{
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
return audiod_control_request(rhport, request);
|
||||
}
|
||||
else if ( stage == CONTROL_STAGE_DATA )
|
||||
{
|
||||
return audiod_control_complete(rhport, request);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
||||
{
|
||||
(void) result;
|
||||
|
@ -384,11 +384,10 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t b
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
void audiod_init (void);
|
||||
void audiod_reset (uint8_t rhport);
|
||||
uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request);
|
||||
void audiod_init (void);
|
||||
void audiod_reset (uint8_t rhport);
|
||||
uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -186,45 +186,48 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_
|
||||
return drv_len;
|
||||
}
|
||||
|
||||
bool btd_control_complete(uint8_t rhport, tusb_control_request_t const *request)
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
// Handle class request only
|
||||
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
|
||||
request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE)
|
||||
{
|
||||
// HCI command packet addressing for single function Primary Controllers
|
||||
TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0);
|
||||
}
|
||||
else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE)
|
||||
{
|
||||
if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex)
|
||||
{
|
||||
// TODO: Set interface it would involve changing size of endpoint size
|
||||
}
|
||||
else
|
||||
{
|
||||
// HCI command packet for Primary Controller function in a composite device
|
||||
TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num);
|
||||
}
|
||||
}
|
||||
else return false;
|
||||
|
||||
if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength);
|
||||
return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength);
|
||||
}
|
||||
else if ( stage == CONTROL_STAGE_DATA )
|
||||
{
|
||||
// Handle class request only
|
||||
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||
|
||||
if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool btd_control_request(uint8_t rhport, tusb_control_request_t const *request)
|
||||
{
|
||||
(void)rhport;
|
||||
|
||||
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
|
||||
request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE)
|
||||
{
|
||||
// HCI command packet addressing for single function Primary Controllers
|
||||
TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0);
|
||||
}
|
||||
else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE)
|
||||
{
|
||||
if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex)
|
||||
{
|
||||
// TODO: Set interface it would involve changing size of endpoint size
|
||||
}
|
||||
else
|
||||
{
|
||||
// HCI command packet for Primary Controller function in a composite device
|
||||
TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num);
|
||||
}
|
||||
}
|
||||
else return false;
|
||||
|
||||
return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength);
|
||||
}
|
||||
|
||||
bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
||||
{
|
||||
(void)result;
|
||||
|
@ -96,12 +96,11 @@ bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len);
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
void btd_init (void);
|
||||
void btd_reset (uint8_t rhport);
|
||||
uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool btd_control_request (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool btd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
void btd_init (void);
|
||||
void btd_reset (uint8_t rhport);
|
||||
uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request);
|
||||
bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -315,38 +315,10 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
|
||||
return drv_len;
|
||||
}
|
||||
|
||||
// Invoked when class request DATA stage is finished.
|
||||
// return false to stall control endpoint (e.g Host send non-sense DATA)
|
||||
bool cdcd_control_complete(uint8_t rhport, tusb_control_request_t const * request)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
//------------- Class Specific Request -------------//
|
||||
TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||
|
||||
uint8_t itf = 0;
|
||||
cdcd_interface_t* p_cdc = _cdcd_itf;
|
||||
|
||||
// Identify which interface to use
|
||||
for ( ; ; itf++, p_cdc++)
|
||||
{
|
||||
if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
|
||||
|
||||
if ( p_cdc->itf_num == request->wIndex ) break;
|
||||
}
|
||||
|
||||
// Invoke callback
|
||||
if ( CDC_REQUEST_SET_LINE_CODING == request->bRequest )
|
||||
{
|
||||
if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle class control request
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request)
|
||||
bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
|
||||
{
|
||||
// Handle class request only
|
||||
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||
@ -365,34 +337,47 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
switch ( request->bRequest )
|
||||
{
|
||||
case CDC_REQUEST_SET_LINE_CODING:
|
||||
TU_LOG2(" Set Line Coding\r\n");
|
||||
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
|
||||
if (stage == CONTROL_STAGE_SETUP)
|
||||
{
|
||||
TU_LOG2(" Set Line Coding\r\n");
|
||||
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
|
||||
}
|
||||
else if ( stage == CONTROL_STAGE_ACK)
|
||||
{
|
||||
if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
|
||||
}
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_GET_LINE_CODING:
|
||||
TU_LOG2(" Get Line Coding\r\n");
|
||||
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
|
||||
if (stage == CONTROL_STAGE_SETUP)
|
||||
{
|
||||
TU_LOG2(" Get Line Coding\r\n");
|
||||
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
|
||||
}
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
|
||||
{
|
||||
// CDC PSTN v1.2 section 6.3.12
|
||||
// Bit 0: Indicates if DTE is present or not.
|
||||
// This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready)
|
||||
// Bit 1: Carrier control for half-duplex modems.
|
||||
// This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send)
|
||||
bool const dtr = tu_bit_test(request->wValue, 0);
|
||||
bool const rts = tu_bit_test(request->wValue, 1);
|
||||
if (stage == CONTROL_STAGE_SETUP)
|
||||
{
|
||||
tud_control_status(rhport, request);
|
||||
}
|
||||
else if (stage == CONTROL_STAGE_ACK)
|
||||
{
|
||||
// CDC PSTN v1.2 section 6.3.12
|
||||
// Bit 0: Indicates if DTE is present or not.
|
||||
// This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready)
|
||||
// Bit 1: Carrier control for half-duplex modems.
|
||||
// This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send)
|
||||
bool const dtr = tu_bit_test(request->wValue, 0);
|
||||
bool const rts = tu_bit_test(request->wValue, 1);
|
||||
|
||||
p_cdc->line_state = (uint8_t) request->wValue;
|
||||
p_cdc->line_state = (uint8_t) request->wValue;
|
||||
|
||||
TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
|
||||
TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
|
||||
// Invoke callback
|
||||
if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts);
|
||||
}
|
||||
// Invoke callback
|
||||
if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts);
|
||||
}
|
||||
break;
|
||||
|
||||
default: return false; // stall unsupported request
|
||||
|
@ -236,12 +236,11 @@ static inline uint32_t tud_cdc_write_available(void)
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL USBD-CLASS DRIVER API
|
||||
//--------------------------------------------------------------------+
|
||||
void cdcd_init (void);
|
||||
void cdcd_reset (uint8_t rhport);
|
||||
uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
void cdcd_init (void);
|
||||
void cdcd_reset (uint8_t rhport);
|
||||
uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -85,17 +85,14 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui
|
||||
return drv_len;
|
||||
}
|
||||
|
||||
bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request)
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) request;
|
||||
// nothing to do with DATA and ACK stage
|
||||
if ( stage != CONTROL_STAGE_SETUP ) return true;
|
||||
|
||||
// nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request)
|
||||
{
|
||||
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
|
||||
|
||||
// dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request
|
||||
|
@ -66,8 +66,7 @@ TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb conventi
|
||||
void dfu_rtd_init(void);
|
||||
void dfu_rtd_reset(uint8_t rhport);
|
||||
uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -211,9 +211,10 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1
|
||||
return drv_len;
|
||||
}
|
||||
|
||||
// Handle class control request
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request)
|
||||
bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
|
||||
{
|
||||
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
|
||||
|
||||
@ -225,27 +226,29 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD)
|
||||
{
|
||||
//------------- STD Request -------------//
|
||||
uint8_t const desc_type = tu_u16_high(request->wValue);
|
||||
uint8_t const desc_index = tu_u16_low (request->wValue);
|
||||
(void) desc_index;
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
uint8_t const desc_type = tu_u16_high(request->wValue);
|
||||
//uint8_t const desc_index = tu_u16_low (request->wValue);
|
||||
|
||||
if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID)
|
||||
{
|
||||
TU_VERIFY(p_hid->hid_descriptor != NULL);
|
||||
TU_VERIFY(tud_control_xfer(rhport, request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength));
|
||||
}
|
||||
else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT)
|
||||
{
|
||||
uint8_t const * desc_report = tud_hid_descriptor_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
);
|
||||
tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // stall unsupported request
|
||||
if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID)
|
||||
{
|
||||
TU_VERIFY(p_hid->hid_descriptor != NULL);
|
||||
TU_VERIFY(tud_control_xfer(rhport, request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength));
|
||||
}
|
||||
else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT)
|
||||
{
|
||||
uint8_t const * desc_report = tud_hid_descriptor_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
);
|
||||
tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // stall unsupported request
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS)
|
||||
@ -254,70 +257,98 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
switch( request->bRequest )
|
||||
{
|
||||
case HID_REQ_CONTROL_GET_REPORT:
|
||||
{
|
||||
// wValue = Report Type | Report ID
|
||||
uint8_t const report_type = tu_u16_high(request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(request->wValue);
|
||||
|
||||
uint16_t xferlen = tud_hid_get_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength
|
||||
);
|
||||
TU_ASSERT( xferlen > 0 );
|
||||
|
||||
tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_SET_REPORT:
|
||||
TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf));
|
||||
tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength);
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_SET_IDLE:
|
||||
p_hid->idle_rate = tu_u16_high(request->wValue);
|
||||
if ( tud_hid_set_idle_cb )
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
// stall request if callback return false
|
||||
TU_VERIFY( tud_hid_set_idle_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
p_hid->idle_rate)
|
||||
);
|
||||
}
|
||||
uint8_t const report_type = tu_u16_high(request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(request->wValue);
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_GET_IDLE:
|
||||
// TODO idle rate of report
|
||||
tud_control_xfer(rhport, request, &p_hid->idle_rate, 1);
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_GET_PROTOCOL:
|
||||
{
|
||||
uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); // 0 is Boot, 1 is Report protocol
|
||||
tud_control_xfer(rhport, request, &protocol, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_SET_PROTOCOL:
|
||||
p_hid->boot_mode = 1 - request->wValue; // 0 is Boot, 1 is Report protocol
|
||||
|
||||
if (tud_hid_boot_mode_cb)
|
||||
{
|
||||
tud_hid_boot_mode_cb(
|
||||
uint16_t xferlen = tud_hid_get_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
p_hid->boot_mode
|
||||
report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength
|
||||
);
|
||||
TU_ASSERT( xferlen > 0 );
|
||||
|
||||
tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_SET_REPORT:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf));
|
||||
tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength);
|
||||
}
|
||||
else if ( stage == CONTROL_STAGE_ACK )
|
||||
{
|
||||
uint8_t const report_type = tu_u16_high(request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(request->wValue);
|
||||
|
||||
tud_hid_set_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
case HID_REQ_CONTROL_SET_IDLE:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
p_hid->idle_rate = tu_u16_high(request->wValue);
|
||||
if ( tud_hid_set_idle_cb )
|
||||
{
|
||||
// stall request if callback return false
|
||||
TU_VERIFY( tud_hid_set_idle_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
p_hid->idle_rate)
|
||||
);
|
||||
}
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_GET_IDLE:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
// TODO idle rate of report
|
||||
tud_control_xfer(rhport, request, &p_hid->idle_rate, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_GET_PROTOCOL:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
// 0 is Boot, 1 is Report protocol
|
||||
uint8_t protocol = (uint8_t)(1-p_hid->boot_mode);
|
||||
tud_control_xfer(rhport, request, &protocol, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_SET_PROTOCOL:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
// 0 is Boot, 1 is Report protocol
|
||||
p_hid->boot_mode = 1 - request->wValue;
|
||||
tud_control_status(rhport, request);
|
||||
}
|
||||
else if ( stage == CONTROL_STAGE_ACK )
|
||||
{
|
||||
if (tud_hid_boot_mode_cb)
|
||||
{
|
||||
tud_hid_boot_mode_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
p_hid->boot_mode
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: return false; // stall unsupported request
|
||||
@ -330,35 +361,6 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request
|
||||
return true;
|
||||
}
|
||||
|
||||
// Invoked when class request DATA stage is finished.
|
||||
// return false to stall control endpoint (e.g Host send non-sense DATA)
|
||||
bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
uint8_t const hid_itf = get_index_by_itfnum((uint8_t) p_request->wIndex);
|
||||
TU_VERIFY(hid_itf < CFG_TUD_HID);
|
||||
|
||||
hidd_interface_t* p_hid = &_hidd_itf[hid_itf];
|
||||
|
||||
if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
|
||||
p_request->bRequest == HID_REQ_CONTROL_SET_REPORT)
|
||||
{
|
||||
// wValue = Report Type | Report ID
|
||||
uint8_t const report_type = tu_u16_high(p_request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(p_request->wValue);
|
||||
|
||||
tud_hid_set_report_cb(
|
||||
#if CFG_TUD_HID > 1
|
||||
hid_itf, // TODO for backward compatible callback, remove later when appropriate
|
||||
#endif
|
||||
report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
||||
{
|
||||
(void) result;
|
||||
|
@ -359,12 +359,11 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
void hidd_init (void);
|
||||
void hidd_reset (uint8_t rhport);
|
||||
uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||
void hidd_init (void);
|
||||
void hidd_reset (uint8_t rhport);
|
||||
uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -375,17 +375,14 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
|
||||
return drv_len;
|
||||
}
|
||||
|
||||
bool midid_control_complete(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) p_request;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) p_request;
|
||||
(void) stage;
|
||||
(void) request;
|
||||
|
||||
// driver doesn't support any request yet
|
||||
return false;
|
||||
|
@ -142,12 +142,11 @@ static inline bool tud_midi_send (uint8_t const packet[4])
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
void midid_init (void);
|
||||
void midid_reset (uint8_t rhport);
|
||||
uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
void midid_init (void);
|
||||
void midid_reset (uint8_t rhport);
|
||||
uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -186,10 +186,14 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
|
||||
return drv_len;
|
||||
}
|
||||
|
||||
// Handle class control request
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request)
|
||||
{
|
||||
// nothing to do with DATA & ACK stage
|
||||
if (stage != CONTROL_STAGE_SETUP) return true;
|
||||
|
||||
// Handle class request only
|
||||
TU_VERIFY(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||
|
||||
@ -219,17 +223,6 @@ bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque
|
||||
return true;
|
||||
}
|
||||
|
||||
// Invoked when class request DATA stage is finished.
|
||||
// return false to stall control endpoint (e.g Host send non-sense DATA)
|
||||
bool mscd_control_complete(uint8_t rhport, tusb_control_request_t const * request)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) request;
|
||||
|
||||
// nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW)
|
||||
// In case of a failed status, sense key must be set for reason of failure
|
||||
int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize)
|
||||
|
@ -158,12 +158,11 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun);
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
void mscd_init (void);
|
||||
void mscd_reset (uint8_t rhport);
|
||||
uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request);
|
||||
bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request);
|
||||
bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||
void mscd_init (void);
|
||||
void mscd_reset (uint8_t rhport);
|
||||
uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request);
|
||||
bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -220,26 +220,6 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
|
||||
return drv_len;
|
||||
}
|
||||
|
||||
// Invoked when class request DATA stage is finished.
|
||||
// return false to stall control endpoint (e.g Host send nonsense DATA)
|
||||
bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * request)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
// Handle RNDIS class control OUT only
|
||||
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
|
||||
request->bmRequestType_bit.direction == TUSB_DIR_OUT &&
|
||||
_netd_itf.itf_num == request->wIndex)
|
||||
{
|
||||
if ( !_netd_itf.ecm_mode )
|
||||
{
|
||||
rndis_class_set_handler(notify.rndis_buf, request->wLength);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ecm_report(bool nc)
|
||||
{
|
||||
notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc;
|
||||
@ -247,99 +227,116 @@ static void ecm_report(bool nc)
|
||||
netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf));
|
||||
}
|
||||
|
||||
// Handle class control request
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request)
|
||||
bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
|
||||
{
|
||||
switch ( request->bmRequestType_bit.type )
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
case TUSB_REQ_TYPE_STANDARD:
|
||||
switch ( request->bRequest )
|
||||
{
|
||||
case TUSB_REQ_GET_INTERFACE:
|
||||
switch ( request->bmRequestType_bit.type )
|
||||
{
|
||||
case TUSB_REQ_TYPE_STANDARD:
|
||||
switch ( request->bRequest )
|
||||
{
|
||||
uint8_t const req_itfnum = (uint8_t) request->wIndex;
|
||||
TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum);
|
||||
|
||||
tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case TUSB_REQ_SET_INTERFACE:
|
||||
{
|
||||
uint8_t const req_itfnum = (uint8_t) request->wIndex;
|
||||
uint8_t const req_alt = (uint8_t) request->wValue;
|
||||
|
||||
// Only valid for Data Interface with Alternate is either 0 or 1
|
||||
TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2);
|
||||
|
||||
// ACM-ECM only: qequest to enable/disable network activities
|
||||
TU_VERIFY(_netd_itf.ecm_mode);
|
||||
|
||||
_netd_itf.itf_data_alt = req_alt;
|
||||
|
||||
if ( _netd_itf.itf_data_alt )
|
||||
case TUSB_REQ_GET_INTERFACE:
|
||||
{
|
||||
// TODO since we don't actually close endpoint
|
||||
// hack here to not re-open it
|
||||
if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 )
|
||||
{
|
||||
TU_ASSERT(_netd_itf.ecm_desc_epdata);
|
||||
TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) );
|
||||
uint8_t const req_itfnum = (uint8_t) request->wIndex;
|
||||
TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum);
|
||||
|
||||
// TODO should be merge with RNDIS's after endpoint opened
|
||||
// Also should have opposite callback for application to disable network !!
|
||||
tud_network_init_cb();
|
||||
can_xmit = true; // we are ready to transmit a packet
|
||||
tud_network_recv_renew(); // prepare for incoming packets
|
||||
}
|
||||
}else
|
||||
{
|
||||
// TODO close the endpoint pair
|
||||
// For now pretend that we did, this should have no harm since host won't try to
|
||||
// communicate with the endpoints again
|
||||
// _netd_itf.ep_in = _netd_itf.ep_out = 0
|
||||
tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
case TUSB_REQ_SET_INTERFACE:
|
||||
{
|
||||
uint8_t const req_itfnum = (uint8_t) request->wIndex;
|
||||
uint8_t const req_alt = (uint8_t) request->wValue;
|
||||
|
||||
// Only valid for Data Interface with Alternate is either 0 or 1
|
||||
TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2);
|
||||
|
||||
// ACM-ECM only: qequest to enable/disable network activities
|
||||
TU_VERIFY(_netd_itf.ecm_mode);
|
||||
|
||||
_netd_itf.itf_data_alt = req_alt;
|
||||
|
||||
if ( _netd_itf.itf_data_alt )
|
||||
{
|
||||
// TODO since we don't actually close endpoint
|
||||
// hack here to not re-open it
|
||||
if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 )
|
||||
{
|
||||
TU_ASSERT(_netd_itf.ecm_desc_epdata);
|
||||
TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) );
|
||||
|
||||
// TODO should be merge with RNDIS's after endpoint opened
|
||||
// Also should have opposite callback for application to disable network !!
|
||||
tud_network_init_cb();
|
||||
can_xmit = true; // we are ready to transmit a packet
|
||||
tud_network_recv_renew(); // prepare for incoming packets
|
||||
}
|
||||
}else
|
||||
{
|
||||
// TODO close the endpoint pair
|
||||
// For now pretend that we did, this should have no harm since host won't try to
|
||||
// communicate with the endpoints again
|
||||
// _netd_itf.ep_in = _netd_itf.ep_out = 0
|
||||
}
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
}
|
||||
break;
|
||||
|
||||
// unsupported request
|
||||
default: return false;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
// unsupported request
|
||||
default: return false;
|
||||
}
|
||||
break;
|
||||
case TUSB_REQ_TYPE_CLASS:
|
||||
TU_VERIFY (_netd_itf.itf_num == request->wIndex);
|
||||
|
||||
case TUSB_REQ_TYPE_CLASS:
|
||||
TU_VERIFY (_netd_itf.itf_num == request->wIndex);
|
||||
|
||||
if (_netd_itf.ecm_mode)
|
||||
{
|
||||
/* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */
|
||||
if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest)
|
||||
if (_netd_itf.ecm_mode)
|
||||
{
|
||||
tud_control_xfer(rhport, request, NULL, 0);
|
||||
ecm_report(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request->bmRequestType_bit.direction == TUSB_DIR_IN)
|
||||
{
|
||||
rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf);
|
||||
uint32_t msglen = tu_le32toh(rndis_msg->MessageLength);
|
||||
TU_ASSERT(msglen <= sizeof(notify.rndis_buf));
|
||||
tud_control_xfer(rhport, request, notify.rndis_buf, msglen);
|
||||
/* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */
|
||||
if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest)
|
||||
{
|
||||
tud_control_xfer(rhport, request, NULL, 0);
|
||||
ecm_report(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf));
|
||||
if (request->bmRequestType_bit.direction == TUSB_DIR_IN)
|
||||
{
|
||||
rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf);
|
||||
uint32_t msglen = tu_le32toh(rndis_msg->MessageLength);
|
||||
TU_ASSERT(msglen <= sizeof(notify.rndis_buf));
|
||||
tud_control_xfer(rhport, request, notify.rndis_buf, msglen);
|
||||
}
|
||||
else
|
||||
{
|
||||
tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
// unsupported request
|
||||
default: return false;
|
||||
// unsupported request
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
else if ( stage == CONTROL_STAGE_DATA )
|
||||
{
|
||||
// Handle RNDIS class control OUT only
|
||||
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
|
||||
request->bmRequestType_bit.direction == TUSB_DIR_OUT &&
|
||||
_netd_itf.itf_num == request->wIndex)
|
||||
{
|
||||
if ( !_netd_itf.ecm_mode )
|
||||
{
|
||||
rndis_class_set_handler(notify.rndis_buf, request->wLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -73,13 +73,12 @@ void tud_network_xmit(void *ref, uint16_t arg);
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL USBD-CLASS DRIVER API
|
||||
//--------------------------------------------------------------------+
|
||||
void netd_init (void);
|
||||
void netd_reset (uint8_t rhport);
|
||||
uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
void netd_report (uint8_t *buf, uint16_t len);
|
||||
void netd_init (void);
|
||||
void netd_reset (uint8_t rhport);
|
||||
uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
void netd_report (uint8_t *buf, uint16_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -575,7 +575,13 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
|
||||
return false;
|
||||
}
|
||||
|
||||
bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) {
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
|
||||
{
|
||||
// nothing to do with DATA and ACK stage
|
||||
if ( stage != CONTROL_STAGE_SETUP ) return true;
|
||||
|
||||
uint8_t tmcStatusCode = USBTMC_STATUS_FAILED;
|
||||
#if (CFG_TUD_USBTMC_ENABLE_488)
|
||||
@ -855,13 +861,4 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r
|
||||
TU_VERIFY(false);
|
||||
}
|
||||
|
||||
bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request)
|
||||
{
|
||||
(void)rhport;
|
||||
//------------- Class Specific Request -------------//
|
||||
TU_ASSERT (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* CFG_TUD_TSMC */
|
||||
|
@ -111,8 +111,7 @@ bool tud_usbtmc_start_bus_read(void);
|
||||
uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||
void usbtmcd_reset_cb(uint8_t rhport);
|
||||
bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
void usbtmcd_init_cb(void);
|
||||
|
||||
/************************************************************
|
||||
|
@ -250,6 +250,13 @@ typedef enum
|
||||
MS_OS_20_FEATURE_VENDOR_REVISION = 0x08
|
||||
} microsoft_os_20_type_t;
|
||||
|
||||
enum
|
||||
{
|
||||
CONTROL_STAGE_SETUP,
|
||||
CONTROL_STAGE_DATA,
|
||||
CONTROL_STAGE_ACK
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USB Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -93,131 +93,121 @@ static usbd_class_driver_t const _usbd_driver[] =
|
||||
{
|
||||
#if CFG_TUD_CDC
|
||||
{
|
||||
DRIVER_NAME("CDC")
|
||||
.init = cdcd_init,
|
||||
.reset = cdcd_reset,
|
||||
.open = cdcd_open,
|
||||
.control_request = cdcd_control_request,
|
||||
.control_complete = cdcd_control_complete,
|
||||
.xfer_cb = cdcd_xfer_cb,
|
||||
.sof = NULL
|
||||
DRIVER_NAME("CDC")
|
||||
.init = cdcd_init,
|
||||
.reset = cdcd_reset,
|
||||
.open = cdcd_open,
|
||||
.control_xfer_cb = cdcd_control_xfer_cb,
|
||||
.xfer_cb = cdcd_xfer_cb,
|
||||
.sof = NULL
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_MSC
|
||||
{
|
||||
DRIVER_NAME("MSC")
|
||||
.init = mscd_init,
|
||||
.reset = mscd_reset,
|
||||
.open = mscd_open,
|
||||
.control_request = mscd_control_request,
|
||||
.control_complete = mscd_control_complete,
|
||||
.xfer_cb = mscd_xfer_cb,
|
||||
.sof = NULL
|
||||
DRIVER_NAME("MSC")
|
||||
.init = mscd_init,
|
||||
.reset = mscd_reset,
|
||||
.open = mscd_open,
|
||||
.control_xfer_cb = mscd_control_xfer_cb,
|
||||
.xfer_cb = mscd_xfer_cb,
|
||||
.sof = NULL
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_HID
|
||||
{
|
||||
DRIVER_NAME("HID")
|
||||
.init = hidd_init,
|
||||
.reset = hidd_reset,
|
||||
.open = hidd_open,
|
||||
.control_request = hidd_control_request,
|
||||
.control_complete = hidd_control_complete,
|
||||
.xfer_cb = hidd_xfer_cb,
|
||||
.sof = NULL
|
||||
DRIVER_NAME("HID")
|
||||
.init = hidd_init,
|
||||
.reset = hidd_reset,
|
||||
.open = hidd_open,
|
||||
.control_xfer_cb = hidd_control_xfer_cb,
|
||||
.xfer_cb = hidd_xfer_cb,
|
||||
.sof = NULL
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_AUDIO
|
||||
{
|
||||
DRIVER_NAME("AUDIO")
|
||||
#if CFG_TUD_AUDIO
|
||||
{
|
||||
DRIVER_NAME("AUDIO")
|
||||
.init = audiod_init,
|
||||
.reset = audiod_reset,
|
||||
.reset = audiod_reset,
|
||||
.open = audiod_open,
|
||||
.control_request = audiod_control_request,
|
||||
.control_complete = audiod_control_complete,
|
||||
.control_xfer_cb = audiod_control_xfer_cb,
|
||||
.xfer_cb = audiod_xfer_cb,
|
||||
.sof = NULL
|
||||
},
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_MIDI
|
||||
{
|
||||
DRIVER_NAME("MIDI")
|
||||
.init = midid_init,
|
||||
.open = midid_open,
|
||||
.reset = midid_reset,
|
||||
.control_request = midid_control_request,
|
||||
.control_complete = midid_control_complete,
|
||||
.xfer_cb = midid_xfer_cb,
|
||||
.sof = NULL
|
||||
DRIVER_NAME("MIDI")
|
||||
.init = midid_init,
|
||||
.open = midid_open,
|
||||
.reset = midid_reset,
|
||||
.control_xfer_cb = midid_control_xfer_cb,
|
||||
.xfer_cb = midid_xfer_cb,
|
||||
.sof = NULL
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_VENDOR
|
||||
{
|
||||
DRIVER_NAME("VENDOR")
|
||||
.init = vendord_init,
|
||||
.reset = vendord_reset,
|
||||
.open = vendord_open,
|
||||
.control_request = tud_vendor_control_request_cb,
|
||||
.control_complete = tud_vendor_control_complete_cb,
|
||||
.xfer_cb = vendord_xfer_cb,
|
||||
.sof = NULL
|
||||
DRIVER_NAME("VENDOR")
|
||||
.init = vendord_init,
|
||||
.reset = vendord_reset,
|
||||
.open = vendord_open,
|
||||
.control_xfer_cb = tud_vendor_control_xfer_cb,
|
||||
.xfer_cb = vendord_xfer_cb,
|
||||
.sof = NULL
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_USBTMC
|
||||
{
|
||||
DRIVER_NAME("TMC")
|
||||
.init = usbtmcd_init_cb,
|
||||
.reset = usbtmcd_reset_cb,
|
||||
.open = usbtmcd_open_cb,
|
||||
.control_request = usbtmcd_control_request_cb,
|
||||
.control_complete = usbtmcd_control_complete_cb,
|
||||
.xfer_cb = usbtmcd_xfer_cb,
|
||||
.sof = NULL
|
||||
DRIVER_NAME("TMC")
|
||||
.init = usbtmcd_init_cb,
|
||||
.reset = usbtmcd_reset_cb,
|
||||
.open = usbtmcd_open_cb,
|
||||
.control_xfer_cb = usbtmcd_control_xfer_cb,
|
||||
.xfer_cb = usbtmcd_xfer_cb,
|
||||
.sof = NULL
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_DFU_RT
|
||||
{
|
||||
DRIVER_NAME("DFU-RT")
|
||||
.init = dfu_rtd_init,
|
||||
.reset = dfu_rtd_reset,
|
||||
.open = dfu_rtd_open,
|
||||
.control_request = dfu_rtd_control_request,
|
||||
.control_complete = dfu_rtd_control_complete,
|
||||
.xfer_cb = dfu_rtd_xfer_cb,
|
||||
.sof = NULL
|
||||
DRIVER_NAME("DFU-RT")
|
||||
.init = dfu_rtd_init,
|
||||
.reset = dfu_rtd_reset,
|
||||
.open = dfu_rtd_open,
|
||||
.control_xfer_cb = dfu_rtd_control_xfer_cb,
|
||||
.xfer_cb = dfu_rtd_xfer_cb,
|
||||
.sof = NULL
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_NET
|
||||
{
|
||||
DRIVER_NAME("NET")
|
||||
.init = netd_init,
|
||||
.reset = netd_reset,
|
||||
.open = netd_open,
|
||||
.control_request = netd_control_request,
|
||||
.control_complete = netd_control_complete,
|
||||
.xfer_cb = netd_xfer_cb,
|
||||
.sof = NULL,
|
||||
DRIVER_NAME("NET")
|
||||
.init = netd_init,
|
||||
.reset = netd_reset,
|
||||
.open = netd_open,
|
||||
.control_xfer_cb = netd_control_xfer_cb,
|
||||
.xfer_cb = netd_xfer_cb,
|
||||
.sof = NULL,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_BTH
|
||||
{
|
||||
DRIVER_NAME("BTH")
|
||||
.init = btd_init,
|
||||
.reset = btd_reset,
|
||||
.open = btd_open,
|
||||
.control_request = btd_control_request,
|
||||
.control_complete = btd_control_complete,
|
||||
.xfer_cb = btd_xfer_cb,
|
||||
.sof = NULL
|
||||
DRIVER_NAME("BTH")
|
||||
.init = btd_init,
|
||||
.reset = btd_reset,
|
||||
.open = btd_open,
|
||||
.control_xfer_cb = btd_control_xfer_cb,
|
||||
.xfer_cb = btd_xfer_cb,
|
||||
.sof = NULL
|
||||
},
|
||||
#endif
|
||||
};
|
||||
@ -274,7 +264,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
|
||||
// from usbd_control.c
|
||||
void usbd_control_reset(void);
|
||||
void usbd_control_set_request(tusb_control_request_t const *request);
|
||||
void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) );
|
||||
void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp );
|
||||
bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||
|
||||
|
||||
@ -313,12 +303,12 @@ static char const* const _tusb_std_request_str[] =
|
||||
};
|
||||
|
||||
// for usbd_control to print the name of control complete driver
|
||||
void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const * ))
|
||||
void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback)
|
||||
{
|
||||
for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++)
|
||||
{
|
||||
usbd_class_driver_t const * driver = get_driver(i);
|
||||
if ( driver->control_complete == control_complete )
|
||||
if ( driver->control_xfer_cb == callback )
|
||||
{
|
||||
TU_LOG2(" %s control complete\r\n", driver->name);
|
||||
return;
|
||||
@ -565,9 +555,9 @@ void tud_task (void)
|
||||
// Helper to invoke class driver control request handler
|
||||
static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request)
|
||||
{
|
||||
usbd_control_set_complete_callback(driver->control_complete);
|
||||
usbd_control_set_complete_callback(driver->control_xfer_cb);
|
||||
TU_LOG2(" %s control request\r\n", driver->name);
|
||||
return driver->control_request(rhport, request);
|
||||
return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request);
|
||||
}
|
||||
|
||||
// This handles the actual request and its response.
|
||||
@ -581,10 +571,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
|
||||
// Vendor request
|
||||
if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR )
|
||||
{
|
||||
TU_VERIFY(tud_vendor_control_request_cb);
|
||||
TU_VERIFY(tud_vendor_control_xfer_cb);
|
||||
|
||||
if (tud_vendor_control_complete_cb) usbd_control_set_complete_callback(tud_vendor_control_complete_cb);
|
||||
return tud_vendor_control_request_cb(rhport, p_request);
|
||||
usbd_control_set_complete_callback(tud_vendor_control_xfer_cb);
|
||||
return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request);
|
||||
}
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
|
@ -125,11 +125,7 @@ TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en);
|
||||
TU_ATTR_WEAK void tud_resume_cb(void);
|
||||
|
||||
// Invoked when received control request with VENDOR TYPE
|
||||
TU_ATTR_WEAK bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request);
|
||||
|
||||
// Invoked when vendor control request is complete
|
||||
TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request);
|
||||
|
||||
TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Binary Device Object Store (BOS) Descriptor Templates
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "dcd.h"
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *));
|
||||
extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback);
|
||||
#endif
|
||||
|
||||
enum
|
||||
@ -50,7 +50,7 @@ typedef struct
|
||||
uint16_t data_len;
|
||||
uint16_t total_xferred;
|
||||
|
||||
bool (*complete_cb) (uint8_t, tusb_control_request_t const *);
|
||||
usbd_control_xfer_cb_t complete_cb;
|
||||
} usbd_control_xfer_t;
|
||||
|
||||
static usbd_control_xfer_t _ctrl_xfer;
|
||||
@ -146,7 +146,7 @@ void usbd_control_reset(void)
|
||||
}
|
||||
|
||||
// TODO may find a better way
|
||||
void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) )
|
||||
void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp )
|
||||
{
|
||||
_ctrl_xfer.complete_cb = fp;
|
||||
}
|
||||
@ -171,7 +171,16 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result
|
||||
if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction )
|
||||
{
|
||||
TU_ASSERT(0 == xferred_bytes);
|
||||
|
||||
// invoke optional dcd hook if available
|
||||
if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request);
|
||||
|
||||
if (_ctrl_xfer.complete_cb)
|
||||
{
|
||||
// TODO refactor with usbd_driver_print_control_complete_name
|
||||
_ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -199,7 +208,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result
|
||||
usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb);
|
||||
#endif
|
||||
|
||||
is_ok = _ctrl_xfer.complete_cb(rhport, &_ctrl_xfer.request);
|
||||
is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request);
|
||||
}
|
||||
|
||||
if ( is_ok )
|
||||
|
@ -46,8 +46,7 @@ typedef struct
|
||||
void (* init ) (void);
|
||||
void (* reset ) (uint8_t rhport);
|
||||
uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len);
|
||||
bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request);
|
||||
bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||
void (* sof ) (uint8_t rhport); /* optional */
|
||||
} usbd_class_driver_t;
|
||||
@ -57,6 +56,9 @@ typedef struct
|
||||
// Note: The drivers array must be accessible at all time when stack is active
|
||||
usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK;
|
||||
|
||||
|
||||
typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBD Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
Loading…
x
Reference in New Issue
Block a user