From 215f8603b14cc29e08d8a25e08f8eca44ed90826 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 Nov 2018 21:56:39 +0700 Subject: nrf5x: refactor device control transfer. - make control transfer as part of usbd. Class driver must use usbd_control_ API() instead of dcd_ api. - change the signature of class driver's control_request - allow control request complete to stall in staus stage - move control request parser & handling to usbd. --- src/class/hid/hid_device.c | 141 +++++++++++++++++++++++---------------------- src/class/hid/hid_device.h | 5 +- 2 files changed, 74 insertions(+), 72 deletions(-) (limited to 'src/class/hid') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index efa602ad6..b5586a488 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -46,7 +46,6 @@ //--------------------------------------------------------------------+ #include "common/tusb_common.h" #include "hid_device.h" -#include "device/control.h" #include "device/usbd_pvt.h" //--------------------------------------------------------------------+ @@ -403,110 +402,112 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, u return TUSB_ERROR_NONE; } -tusb_error_t hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent) +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex ); - TU_ASSERT(p_hid, TUSB_ERROR_FAILED); + TU_ASSERT(p_hid); - //------------- STD Request -------------// if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { + //------------- STD Request -------------// uint8_t const desc_type = tu_u16_high(p_request->wValue); uint8_t const desc_index = tu_u16_low (p_request->wValue); (void) desc_index; if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - // TODO: Handle zero length packet. - uint16_t remaining_bytes = p_hid->desc_len - bytes_already_sent; - if (remaining_bytes > 64) { - remaining_bytes = 64; - } - memcpy(_shared_control_buffer, p_hid->desc_report + bytes_already_sent, remaining_bytes); - - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, _shared_control_buffer, remaining_bytes); + usbd_control_xfer(rhport, p_request, p_hid->desc_report, p_hid->desc_len); }else { - return TUSB_ERROR_FAILED; + return false; // stall unsupported request } } - //------------- Class Specific Request -------------// else if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { - if( HID_REQ_CONTROL_GET_REPORT == p_request->bRequest ) + //------------- Class Specific Request -------------// + switch( p_request->bRequest ) { - // 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); - - uint16_t xferlen; - if ( p_hid->get_report_cb ) + case HID_REQ_CONTROL_GET_REPORT: { - xferlen = p_hid->get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->report_buf, p_request->wLength); - }else + // 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); + + uint16_t xferlen; + if ( p_hid->get_report_cb ) + { + xferlen = p_hid->get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->report_buf, p_request->wLength); + }else + { + // For boot Interface only: re-use report_buf -> report has no change + xferlen = p_request->wLength; + } + + TU_ASSERT( xferlen > 0 ); + usbd_control_xfer(rhport, p_request, p_hid->report_buf, xferlen); + } + break; + + case HID_REQ_CONTROL_SET_REPORT: + usbd_control_xfer(rhport, p_request, p_hid->report_buf, p_request->wLength); + break; + + case HID_REQ_CONTROL_SET_IDLE: + // TODO idle rate of report + p_hid->idle_rate = tu_u16_high(p_request->wValue); + usbd_control_status(rhport, p_request); + break; + + case HID_REQ_CONTROL_GET_IDLE: + // TODO idle rate of report + usbd_control_xfer(rhport, p_request, &p_hid->idle_rate, 1); + break; + + case HID_REQ_CONTROL_GET_PROTOCOL: { - // For boot Interface only: re-use report_buf -> report has no change - xferlen = p_request->wLength; + uint8_t protocol = 1-p_hid->boot_protocol; // 0 is Boot, 1 is Report protocol + usbd_control_xfer(rhport, p_request, &protocol, 1); } + break; - TU_ASSERT( xferlen > 0 ); - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, _shared_control_buffer, xferlen); - } - else if ( HID_REQ_CONTROL_SET_REPORT == p_request->bRequest ) - { - dcd_edpt_xfer(rhport, 0, _shared_control_buffer, p_request->wLength); - } - else if (HID_REQ_CONTROL_SET_IDLE == p_request->bRequest) - { - // TODO idle rate of report - p_hid->idle_rate = tu_u16_high(p_request->wValue); - } - else if (HID_REQ_CONTROL_GET_IDLE == p_request->bRequest) - { - // TODO idle rate of report - _shared_control_buffer[0] = p_hid->idle_rate; - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, _shared_control_buffer, 1); - } - else if (HID_REQ_CONTROL_GET_PROTOCOL == p_request->bRequest ) - { - _shared_control_buffer[0] = 1-p_hid->boot_protocol; // 0 is Boot, 1 is Report protocol - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, _shared_control_buffer, 1); - } - else if (HID_REQ_CONTROL_SET_PROTOCOL == p_request->bRequest ) - { - p_hid->boot_protocol = 1 - p_request->wValue; // 0 is Boot, 1 is Report protocol - }else - { - return TUSB_ERROR_FAILED; + case HID_REQ_CONTROL_SET_PROTOCOL: + p_hid->boot_protocol = 1 - p_request->wValue; // 0 is Boot, 1 is Report protocol + usbd_control_status(rhport, p_request); + break; + + default: return false; // stall unsupported request } }else { - return TUSB_ERROR_FAILED; + return false; // stall unsupported request } - return TUSB_ERROR_NONE; + + return true; } -void hidd_control_request_complete(uint8_t rhport, tusb_control_request_t const * p_request) +// Invoked when class request DATA stage is finished. +// return false to stall control endpoint (e.g Host send non-sense DATA) +bool hidd_control_request_complete(uint8_t rhport, tusb_control_request_t const * p_request) { hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex ); - if (p_hid == NULL) { - return; - } + TU_ASSERT(p_hid); - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + p_request->bRequest == HID_REQ_CONTROL_SET_REPORT) { - if ( HID_REQ_CONTROL_SET_REPORT == p_request->bRequest ) - { - // 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); + // 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); - if ( p_hid->set_report_cb ) - { - p_hid->set_report_cb(report_id, (hid_report_type_t) report_type, _shared_control_buffer, p_request->wLength); - } + if ( p_hid->set_report_cb ) + { + p_hid->set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->report_buf, p_request->wLength); } } + + return true; } tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 1dc40af57..7f8cd0fa7 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -378,8 +378,8 @@ ATTR_WEAK void tud_hid_mouse_set_report_cb(uint8_t report_id, hid_report_type_t void hidd_init(void); tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); -tusb_error_t hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent); -void hidd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request); +bool hidd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); void hidd_reset(uint8_t rhport); @@ -390,3 +390,4 @@ void hidd_reset(uint8_t rhport); #endif #endif /* _TUSB_HID_DEVICE_H_ */ + -- cgit v1.3.1