diff --git a/demos/device/device_os_none/keyboardd_app.c b/demos/device/device_os_none/keyboardd_app.c index 842099eb6..b072d7e12 100644 --- a/demos/device/device_os_none/keyboardd_app.c +++ b/demos/device/device_os_none/keyboardd_app.c @@ -80,6 +80,41 @@ void tusbd_hid_keyboard_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_ } } +uint16_t tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length) +{ + // get other than input report is not supported by this keyboard demo + if ( report_type != HID_REQUEST_REPORT_INPUT ) return 0; + + (*pp_report) = &keyboard_report; + return requested_length; +} + +void tusbd_hid_keyboard_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t p_report_data[], uint16_t length) +{ + // set other than output report is not supported by this keyboard demo + if ( report_type != HID_REQUEST_REPORT_OUTPUT ) return; + + uint8_t kbd_led = p_report_data[0]; + uint32_t interval_divider = 1; // each LED will reduce blinking interval by a half + + if (kbd_led & KEYBOARD_LED_NUMLOCK) + { + interval_divider *= 2; + } + + if (kbd_led & KEYBOARD_LED_CAPSLOCK) + { + interval_divider *= 2; + } + + if (kbd_led & KEYBOARD_LED_SCROLLLOCK) + { + interval_divider *= 2; + } + + led_blinking_set_interval( 1000 / interval_divider); +} + //--------------------------------------------------------------------+ // APPLICATION CODE //--------------------------------------------------------------------+ diff --git a/demos/device/device_os_none/main.c b/demos/device/device_os_none/main.c index 897b5f5be..c4e1d785e 100644 --- a/demos/device/device_os_none/main.c +++ b/demos/device/device_os_none/main.c @@ -108,7 +108,7 @@ int main(void) #error need to start RTOS schduler #endif - while(1) { } // should not be reached here + while(1) { } // should not reach here return 0; } @@ -116,13 +116,19 @@ int main(void) //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ +static uint32_t led_blink_interval_ms = 1000; // default is 1 seconda +void led_blinking_set_interval(uint32_t ms) +{ + led_blink_interval_ms = ms; +} + OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para) { OSAL_TASK_LOOP_BEGIN static uint32_t led_on_mask = 0; - osal_task_delay(1000); + osal_task_delay(led_blink_interval_ms); board_leds(led_on_mask, 1 - led_on_mask); led_on_mask = 1 - led_on_mask; // toggle diff --git a/demos/device/device_os_none/moused_app.c b/demos/device/device_os_none/moused_app.c index e9cc16998..dd6600131 100644 --- a/demos/device/device_os_none/moused_app.c +++ b/demos/device/device_os_none/moused_app.c @@ -80,6 +80,19 @@ void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_byt } } +uint16_t tusbd_hid_mouse_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length) +{ + if ( report_type != HID_REQUEST_REPORT_INPUT ) return 0; // not support other report type for this mouse demo + + (*pp_report) = &mouse_report; + return requested_length; +} + +void tusbd_hid_mouse_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t report_data[], uint16_t length) +{ + // mouse demo does not support set report --> return 0 will result in rejecting (STALL) this request + return 0; +} //--------------------------------------------------------------------+ // APPLICATION CODE //--------------------------------------------------------------------+ diff --git a/demos/device/device_os_none/tusb_config.h b/demos/device/device_os_none/tusb_config.h index c04aefcaa..899ee37f1 100644 --- a/demos/device/device_os_none/tusb_config.h +++ b/demos/device/device_os_none/tusb_config.h @@ -87,7 +87,7 @@ #define TUSB_CFG_DEVICE_HID_MOUSE 1 #define TUSB_CFG_DEVICE_HID_GENERIC 0 #define TUSB_CFG_DEVICE_MSC 0 -#define TUSB_CFG_DEVICE_CDC 0 +#define TUSB_CFG_DEVICE_CDC 1 diff --git a/tinyusb/class/cdc_device.c b/tinyusb/class/cdc_device.c index bb3e86db4..39619fbd5 100644 --- a/tinyusb/class/cdc_device.c +++ b/tinyusb/class/cdc_device.c @@ -182,7 +182,7 @@ void cdcd_close(uint8_t coreid) memclr_(&cdcd_data[coreid], sizeof(cdcd_data_t)); } -tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const * p_request) +tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request) { //------------- Class Specific Request -------------// if (p_request->bmRequestType_bit.type != TUSB_REQUEST_TYPE_CLASS) return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; @@ -191,17 +191,17 @@ tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const * { case CDC_REQUEST_GET_LINE_CODING: dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, - &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength) ); + &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false ); break; case CDC_REQUEST_SET_LINE_CODING: dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, - &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength) ); + &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false ); // TODO notify application on xfer complete break; case CDC_REQUEST_SET_CONTROL_LINE_STATE: // TODO extract DTE present - dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, NULL, 0); +// dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, NULL, 0); break; diff --git a/tinyusb/class/cdc_device.h b/tinyusb/class/cdc_device.h index bb0c7644c..601b29cca 100644 --- a/tinyusb/class/cdc_device.h +++ b/tinyusb/class/cdc_device.h @@ -76,7 +76,7 @@ void tusbd_cdc_xfer_cb(uint8_t coreid, tusb_event_t event, cdc_pipeid_t pipe_id, void cdcd_init(void); tusb_error_t cdcd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length); -tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const * p_request); +tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request); tusb_error_t cdcd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes); void cdcd_close(uint8_t coreid); diff --git a/tinyusb/class/hid.h b/tinyusb/class/hid.h index fcb192c4d..017223c0f 100644 --- a/tinyusb/class/hid.h +++ b/tinyusb/class/hid.h @@ -199,6 +199,14 @@ typedef enum { KEYBOARD_MODIFIER_RIGHTGUI = BIT_(7) ///< Right Window }hid_keyboard_modifier_bm_t; +typedef enum { + KEYBOARD_LED_NUMLOCK = BIT_(0), ///< Num Lock LED + KEYBOARD_LED_CAPSLOCK = BIT_(1), ///< Caps Lock LED + KEYBOARD_LED_SCROLLLOCK = BIT_(2), ///< Scroll Lock LED + KEYBOARD_LED_COMPOSE = BIT_(3), ///< Composition Mode + KEYBOARD_LED_KANA = BIT_(4) ///< Kana mode +}hid_keyboard_led_bm_t; + /// @} #define HID_KEYCODE_TABLE(ENTRY) \ diff --git a/tinyusb/class/hid_device.c b/tinyusb/class/hid_device.c index 3e171a1de..0b413329c 100644 --- a/tinyusb/class/hid_device.c +++ b/tinyusb/class/hid_device.c @@ -51,7 +51,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -ATTR_USB_MIN_ALIGNMENT uint8_t set_report[ MAX_OF(sizeof(hid_keyboard_report_t), sizeof(hid_mouse_report_t)) ] TUSB_CFG_ATTR_USBRAM; enum { HIDD_NUMBER_OF_SUBCLASS = 3 @@ -70,6 +69,8 @@ typedef struct { void (* const mounted_cb) (uint8_t coreid); void (* const unmounted_cb) (uint8_t coreid); void (* const xfer_cb) (uint8_t, tusb_event_t, uint32_t); + uint16_t (* const get_report_cb) (uint8_t, hid_request_report_type_t, void**, uint16_t ); + void (* const set_report_cb) (uint8_t, hid_request_report_type_t, uint8_t[], uint16_t); }hidd_class_driver_t; extern ATTR_WEAK hidd_interface_t keyboardd_data; @@ -86,7 +87,9 @@ static hidd_class_driver_t const hidd_class_driver[HIDD_NUMBER_OF_SUBCLASS] = .p_interface = &keyboardd_data, .mounted_cb = tusbd_hid_keyboard_mounted_cb, .unmounted_cb = tusbd_hid_keyboard_unmounted_cb, - .xfer_cb = tusbd_hid_keyboard_cb + .xfer_cb = tusbd_hid_keyboard_cb, + .get_report_cb = tusbd_hid_keyboard_get_report_cb, + .set_report_cb = tusbd_hid_keyboard_set_report_cb }, #endif @@ -97,11 +100,17 @@ static hidd_class_driver_t const hidd_class_driver[HIDD_NUMBER_OF_SUBCLASS] = .p_interface = &moused_data, .mounted_cb = tusbd_hid_mouse_mounted_cb, .unmounted_cb = tusbd_hid_mouse_unmounted_cb, - .xfer_cb = tusbd_hid_mouse_cb + .xfer_cb = tusbd_hid_mouse_cb, + .get_report_cb = tusbd_hid_mouse_get_report_cb, + .set_report_cb = tusbd_hid_mouse_set_report_cb } #endif }; +#if TUSB_CFG_DEVICE_HID_KEYBOARD || TUSB_CFG_DEVICE_HID_MOUSE +ATTR_USB_MIN_ALIGNMENT uint8_t m_control_data[ MAX_OF(sizeof(hid_keyboard_report_t), sizeof(hid_mouse_report_t)) ] TUSB_CFG_ATTR_USBRAM; +#endif + //--------------------------------------------------------------------+ // KEYBOARD APPLICATION API //--------------------------------------------------------------------+ @@ -180,7 +189,7 @@ void hidd_close(uint8_t coreid) } } -tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * p_request) +tusb_error_t hidd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request) { uint8_t subclass_idx; for(subclass_idx=0; subclass_idxp_interface; //------------- STD Request -------------// @@ -208,39 +217,50 @@ tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * ASSERT ( p_request->bRequest == TUSB_REQUEST_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT, TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT); - dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, p_driver->p_report_desc, p_hid->report_length); + dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, p_driver->p_report_desc, p_hid->report_length, false); } //------------- Class Specific Request -------------// else if (p_request->bmRequestType_bit.type == TUSB_REQUEST_TYPE_CLASS) { - switch(p_request->bRequest) + OSAL_SUBTASK_BEGIN + + if( (HID_REQUEST_CONTROL_GET_REPORT == p_request->bRequest) && (p_driver->get_report_cb != NULL) ) { - case HID_REQUEST_CONTROL_SET_IDLE: - // idle_rate = u16_high_u8(p_request->wValue); - break; + // wValue = Report Type | Report ID + void* p_buffer = NULL; - case HID_REQUEST_CONTROL_SET_REPORT: - { -// return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; // TODO test STALL control out endpoint (with mouse+keyboard)aaaaa + uint16_t actual_length = p_driver->get_report_cb(coreid, (hid_request_report_type_t) u16_high_u8(p_request->wValue), + &p_buffer, p_request->wLength); + SUBTASK_ASSERT( p_buffer != NULL && actual_length > 0 ); - // TODO HIDD set report support - hid_request_report_type_t report_type = u16_high_u8(p_request->wValue); - uint8_t report_id = u16_low_u8(p_request->wValue); - - (void) report_id; - (void) report_type; - - dcd_pipe_control_xfer(coreid, TUSB_DIR_HOST_TO_DEV, &set_report, p_request->wLength); - } - break; - - case HID_REQUEST_CONTROL_GET_IDLE: - case HID_REQUEST_CONTROL_GET_REPORT: - case HID_REQUEST_CONTROL_GET_PROTOCOL: - case HID_REQUEST_CONTROL_SET_PROTOCOL: - default: - return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; + dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, actual_length, false); } + else if ( (HID_REQUEST_CONTROL_SET_REPORT == p_request->bRequest) && (p_driver->set_report_cb != NULL) ) + { + // return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; // TODO test STALL control out endpoint (with mouse+keyboard) + // wValue = Report Type | Report ID + tusb_error_t error; + + dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, &m_control_data, p_request->wLength, true); + + osal_semaphore_wait(usbd_control_xfer_sem_hdl, OSAL_TIMEOUT_NORMAL, &error); // wait for control xfer complete + SUBTASK_ASSERT_STATUS(error); + + p_driver->set_report_cb(coreid, (hid_request_report_type_t) u16_high_u8(p_request->wValue), + &m_control_data, p_request->wLength); + } + else if (HID_REQUEST_CONTROL_SET_IDLE == p_request->bRequest) + { + // uint8_t idle_rate = u16_high_u8(p_request->wValue); + }else + { +// HID_REQUEST_CONTROL_GET_IDLE: +// HID_REQUEST_CONTROL_GET_PROTOCOL: +// HID_REQUEST_CONTROL_SET_PROTOCOL: + return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; + } + + OSAL_SUBTASK_END }else { return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; @@ -270,7 +290,7 @@ tusb_error_t hidd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int case HID_PROTOCOL_KEYBOARD: case HID_PROTOCOL_MOUSE: { - hidd_class_driver_t * const p_driver = &hidd_class_driver[p_interface_desc->bInterfaceProtocol]; + hidd_class_driver_t const * const p_driver = &hidd_class_driver[p_interface_desc->bInterfaceProtocol]; hidd_interface_t * const p_hid = p_driver->p_interface; ASSERT_PTR(p_hid, TUSB_ERROR_FAILED); diff --git a/tinyusb/class/hid_device.h b/tinyusb/class/hid_device.h index b51b0d8eb..e91000f68 100644 --- a/tinyusb/class/hid_device.h +++ b/tinyusb/class/hid_device.h @@ -94,8 +94,8 @@ void tusbd_hid_keyboard_unmounted_cb(uint8_t coreid); */ void tusbd_hid_keyboard_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_bytes); -void tusbd_hid_keyboard_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t report_data[]); -void tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report); +void tusbd_hid_keyboard_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t p_report_data[], uint16_t length); +uint16_t tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length); /** @} */ /** @} */ @@ -108,8 +108,6 @@ void tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t /** \defgroup Mouse_Device Device * @{ */ -//bool tusbd_hid_mouse_is_configured(uint8_t coreid); - /** \brief Check if the interface is currently busy or not * \param[in] coreid USB Controller ID * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to host @@ -149,6 +147,8 @@ void tusbd_hid_mouse_unmounted_cb(uint8_t coreid); */ void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_bytes); +uint16_t tusbd_hid_mouse_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length); +void tusbd_hid_mouse_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t p_report_data[], uint16_t length); /** @} */ /** @} */ @@ -161,7 +161,7 @@ void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_byt void hidd_init(void); tusb_error_t hidd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length); -tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * p_request); +tusb_error_t hidd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request); tusb_error_t hidd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes); void hidd_close(uint8_t coreid); diff --git a/tinyusb/class/msc_device.c b/tinyusb/class/msc_device.c index c91c1913e..52c2e5de8 100644 --- a/tinyusb/class/msc_device.c +++ b/tinyusb/class/msc_device.c @@ -113,7 +113,7 @@ tusb_error_t mscd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int return TUSB_ERROR_NONE; } -tusb_error_t mscd_control_request(uint8_t coreid, tusb_control_request_t const * p_request) +tusb_error_t mscd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request) { ASSERT(p_request->bmRequestType_bit.type == TUSB_REQUEST_TYPE_CLASS, TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT); diff --git a/tinyusb/class/msc_device.h b/tinyusb/class/msc_device.h index bb20e4b13..8f824380a 100644 --- a/tinyusb/class/msc_device.h +++ b/tinyusb/class/msc_device.h @@ -126,7 +126,7 @@ msc_csw_status_t tusbd_msc_scsi_received_isr (uint8_t coreid, uint8_t lun, uint8 void mscd_init(void); tusb_error_t mscd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length); -tusb_error_t mscd_control_request(uint8_t coreid, tusb_control_request_t const * p_request); +tusb_error_t mscd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request); tusb_error_t mscd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes); void mscd_close(uint8_t coreid); diff --git a/tinyusb/common/common.h b/tinyusb/common/common.h index bf0955924..2cd29417f 100644 --- a/tinyusb/common/common.h +++ b/tinyusb/common/common.h @@ -83,6 +83,8 @@ #include "std_descriptors.h" #include "std_request.h" +#include "osal/osal.h" + //--------------------------------------------------------------------+ // MACROS @@ -93,6 +95,7 @@ #define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) // expand then concat #define MAX_OF(a, b) ( (a) > (b) ? (a) : (b) ) +#define MIN_OF(a, b) ( (a) < (b) ? (a) : (b) ) #define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff)) #define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff)) diff --git a/tinyusb/device/dcd.h b/tinyusb/device/dcd.h index d02108fa7..f84a26d95 100644 --- a/tinyusb/device/dcd.h +++ b/tinyusb/device/dcd.h @@ -81,7 +81,7 @@ void dcd_controller_set_address(uint8_t coreid, uint8_t dev_addr); void dcd_controller_set_configuration(uint8_t coreid); //------------- PIPE API -------------// -tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length); +tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length, bool int_on_complete); void dcd_pipe_control_stall(uint8_t coreid); endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT; diff --git a/tinyusb/device/dcd_lpc_11uxx_13uxx.c b/tinyusb/device/dcd_lpc_11uxx_13uxx.c index 92f086c19..1b64154e8 100644 --- a/tinyusb/device/dcd_lpc_11uxx_13uxx.c +++ b/tinyusb/device/dcd_lpc_11uxx_13uxx.c @@ -114,7 +114,7 @@ typedef struct { }next_td[DCD_11U_13U_QHD_COUNT]; uint32_t current_ioc; ///< interrupt on complete mask for current TD - uint32_t next_ioc; ///< interrupt on complete mask for next TD + uint32_t next_ioc; ///< interrupt on complete mask for next TD // should start from 128 ATTR_ALIGNED(64) tusb_control_request_t setup_request; @@ -200,6 +200,61 @@ static void bus_reset(void) LPC_USB->INTEN = INT_MASK_DEVICE_STATUS | BIT_(0) | BIT_(1); // enable device status & control endpoints } +static void endpoint_non_control_isr(uint32_t int_status) +{ + for(uint8_t ep_id = 2; ep_id < DCD_11U_13U_QHD_COUNT; ep_id++ ) + { + if ( BIT_TEST_(int_status, ep_id) ) + { + dcd_11u_13u_qhd_t * const arr_qhd = dcd_data.qhd[ep_id]; + + // when double buffering, the complete buffer is opposed to the current active buffer in EPINUSE + uint8_t const buff_idx = LPC_USB->EPINUSE & BIT_(ep_id) ? 0 : 1; + uint16_t const xferred_bytes = dcd_data.current_td[ep_id].queued_bytes_in_buff[buff_idx] - arr_qhd[buff_idx].total_bytes; + + dcd_data.current_td[ep_id].xferred_total += xferred_bytes; + + // there are still data to transfer. + if ( (arr_qhd[buff_idx].total_bytes == 0) && (dcd_data.current_td[ep_id].remaining_bytes > 0) ) + { // NOTE although buff_addr_offset has been increased when xfer is completed + // but we still need to increase it one more as we are using double buffering. + queue_xfer_to_buffer(ep_id, buff_idx, arr_qhd[buff_idx].buff_addr_offset+1, dcd_data.current_td[ep_id].remaining_bytes); + } + // short packet or (no more byte and both buffers are finished) + else if ( (arr_qhd[buff_idx].total_bytes > 0) || !arr_qhd[1-buff_idx].active ) + { // current TD (request) is completed + LPC_USB->EPSKIP = BIT_SET_(LPC_USB->EPSKIP, ep_id); // skip other endpoint in case of short-package + + dcd_data.current_td[ep_id].remaining_bytes = 0; + + if ( BIT_TEST_(dcd_data.current_ioc, ep_id) ) + { + endpoint_handle_t edpt_hdl = + { + .coreid = 0, + .index = ep_id, + .class_code = dcd_data.class_code[ep_id] + }; + + dcd_data.current_ioc = BIT_CLR_(dcd_data.current_ioc, edpt_hdl.index); + + // TODO no way determine if the transfer is failed or not + usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, dcd_data.current_td[ep_id].xferred_total); + } + + //------------- Next TD is available -------------// + if ( dcd_data.next_td[ep_id].total_bytes != 0 ) + { + queue_xfer_in_next_td(ep_id); + } + }else + { + // transfer complete, there is no more remaining bytes, but this buffer is not the last transaction (the other is) + } + } + } +} + void dcd_isr(uint8_t coreid) { (void) coreid; @@ -248,7 +303,7 @@ void dcd_isr(uint8_t coreid) // } } - //------------- Control Endpoint -------------// + //------------- Setup Received -------------// if ( BIT_TEST_(int_status, 0) && (dev_cmd_stat & CMDSTAT_SETUP_RECEIVED_MASK) ) { // received control request from host // copy setup request & acknowledge so that the next setup can be received by hw @@ -260,88 +315,73 @@ void dcd_isr(uint8_t coreid) LPC_USB->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK; dcd_data.qhd[0][1].buff_addr_offset = addr_offset(&dcd_data.setup_request); } + //------------- Control Endpoint -------------// else if ( int_status & 0x03 ) { // either control endpoints - endpoint_handle_t edpt_hdl = + uint8_t const ep_id = ( int_status & BIT_(0) ) ? 0 : 1; + + // there are still data to transfer. + if ( (dcd_data.qhd[ep_id][0].total_bytes == 0) && (dcd_data.current_td[ep_id].remaining_bytes > 0) ) { - .coreid = coreid, - .index = BIT_TEST_(int_status, 1) ? 1 : 0 - }; - - // FIXME xferred_byte for control xfer is not needed now !!! - usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, 0); - } - - //------------- Non-Control Endpoints -------------// - for(uint8_t ep_id = 2; ep_id < DCD_11U_13U_QHD_COUNT; ep_id++ ) - { - if ( BIT_TEST_(int_status, ep_id) ) + queue_xfer_to_buffer(ep_id, 0, dcd_data.qhd[ep_id][0].buff_addr_offset, dcd_data.current_td[ep_id].remaining_bytes); + }else { - dcd_11u_13u_qhd_t * const arr_qhd = dcd_data.qhd[ep_id]; + dcd_data.current_td[ep_id].remaining_bytes = 0; - // when double buffering, the complete buffer is opposed to the current active buffer in EPINUSE - uint8_t const buff_idx = LPC_USB->EPINUSE & BIT_(ep_id) ? 0 : 1; - uint16_t const xferred_bytes = dcd_data.current_td[ep_id].queued_bytes_in_buff[buff_idx] - arr_qhd[buff_idx].total_bytes; - - dcd_data.current_td[ep_id].xferred_total += xferred_bytes; - - // there are still data to transfer. - if ( (arr_qhd[buff_idx].total_bytes == 0) && (dcd_data.current_td[ep_id].remaining_bytes > 0) ) - { // NOTE although buff_addr_offset has been increased when xfer is completed - // but we still need to increase it one more as we are using double buffering. - queue_xfer_to_buffer(ep_id, buff_idx, arr_qhd[buff_idx].buff_addr_offset+1, dcd_data.current_td[ep_id].remaining_bytes); - } - // short packet or (no more byte and both buffers are finished) - else if ( (arr_qhd[buff_idx].total_bytes > 0) || !arr_qhd[1-buff_idx].active ) - { // current TD (request) is completed - LPC_USB->EPSKIP = BIT_SET_(LPC_USB->EPSKIP, ep_id); // skip other endpoint in case of short-package - - dcd_data.current_td[ep_id].remaining_bytes = 0; - - if ( BIT_TEST_(dcd_data.current_ioc, ep_id) ) + if ( BIT_TEST_(dcd_data.current_ioc, ep_id) ) + { + endpoint_handle_t edpt_hdl = { - endpoint_handle_t edpt_hdl = - { - .coreid = coreid, - .index = ep_id, - .class_code = dcd_data.class_code[ep_id] - }; + .coreid = coreid, + .index = 0 + }; - dcd_data.current_ioc = BIT_CLR_(dcd_data.current_ioc, edpt_hdl.index); + dcd_data.current_ioc = BIT_CLR_(dcd_data.current_ioc, edpt_hdl.index); - // TODO no way determine if the transfer is failed or not - usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, dcd_data.current_td[ep_id].xferred_total); - } - - //------------- Next TD is available -------------// - if ( dcd_data.next_td[ep_id].total_bytes != 0 ) - { - queue_xfer_in_next_td(ep_id); - } + // FIXME xferred_byte for control xfer is not needed now !!! + usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, 0); } } } + + //------------- Non-Control Endpoints -------------// + endpoint_non_control_isr(int_status); } //--------------------------------------------------------------------+ // CONTROL PIPE API //--------------------------------------------------------------------+ void dcd_pipe_control_stall(uint8_t coreid) -{ // TODO cannot able to STALL Control OUT endpoint !!!!! +{ (void) coreid; - + // TODO cannot able to STALL Control OUT endpoint !!!!! FIXME try some walk-around dcd_data.qhd[0][0].stall = dcd_data.qhd[1][0].stall = 1; } -tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length) +tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length, bool int_on_complete) { (void) coreid; - uint8_t const ep_id = dir; // IN : 1, OUT = 0 + // determine Endpoint where Data & Status phase occurred (IN or OUT) + uint8_t const ep_data = (dir == TUSB_DIR_DEV_TO_HOST) ? 1 : 0; + uint8_t const ep_status = 1 - ep_data; - dcd_data.qhd[ep_id][0].buff_addr_offset = (length ? addr_offset(p_buffer) : 0 ); - dcd_data.qhd[ep_id][0].total_bytes = length; - dcd_data.qhd[ep_id][0].active = 1 ; + dcd_data.current_ioc = int_on_complete ? BIT_SET_(dcd_data.current_ioc, ep_status) : BIT_CLR_(dcd_data.current_ioc, ep_status); + + //------------- Data Phase -------------// + if (length) + { + dcd_data.current_td[ep_data].remaining_bytes = length; + dcd_data.current_td[ep_data].xferred_total = 0; + + queue_xfer_to_buffer(ep_data, 0, addr_offset(p_buffer), length); + } + + //------------- Status Phase -------------// + dcd_data.current_td[ep_status].remaining_bytes = 0; + dcd_data.current_td[ep_status].xferred_total = 0; + + queue_xfer_to_buffer(ep_status, 0, NULL, 0); return TUSB_ERROR_NONE; } diff --git a/tinyusb/device/usbd.c b/tinyusb/device/usbd.c index a2da447d1..7e6f98a74 100644 --- a/tinyusb/device/usbd.c +++ b/tinyusb/device/usbd.c @@ -49,13 +49,6 @@ #include "tusb_descriptors.h" // TODO callback include #include "usbd_dcd.h" -// Some MCUs cannot transfer more than 64 bytes each queue, thus require special task-alike treatment -#if TUSB_CFG_MCU == MCU_LPC11UXX || TUSB_CFG_MCU == MCU_LPC175X_6X - #define USBD_CONTROL_ONE_PACKET_EACH_XFER // for each Transfer, cannot queue more than packet size - enum { - USBD_COTNROL_MAX_LENGTH_EACH_XFER = 64 - }; -#endif //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -67,33 +60,33 @@ static usbd_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAPPED_INDEX_STAR #if DEVICE_CLASS_HID [TUSB_CLASS_HID] = { - .init = hidd_init, - .open = hidd_open, - .control_request = hidd_control_request, - .xfer_cb = hidd_xfer_cb, - .close = hidd_close + .init = hidd_init, + .open = hidd_open, + .control_request_subtask = hidd_control_request_subtask, + .xfer_cb = hidd_xfer_cb, + .close = hidd_close }, #endif #if TUSB_CFG_DEVICE_MSC [TUSB_CLASS_MSC] = { - .init = mscd_init, - .open = mscd_open, - .control_request = mscd_control_request, - .xfer_cb = mscd_xfer_cb, - .close = mscd_close + .init = mscd_init, + .open = mscd_open, + .control_request_subtask = mscd_control_request_subtask, + .xfer_cb = mscd_xfer_cb, + .close = mscd_close }, #endif #if TUSB_CFG_DEVICE_CDC [TUSB_CLASS_CDC] = { - .init = cdcd_init, - .open = cdcd_open, - .control_request = cdcd_control_request, - .xfer_cb = cdcd_xfer_cb, - .close = cdcd_close + .init = cdcd_init, + .open = cdcd_open, + .control_request_subtask = cdcd_control_request_subtask, + .xfer_cb = cdcd_xfer_cb, + .close = cdcd_close }, #endif @@ -151,7 +144,7 @@ OSAL_QUEUE_DEF(usbd_queue_def, USBD_TASK_QUEUE_DEPTH, usbd_task_event_t); OSAL_SEM_DEF(usbd_control_xfer_semaphore_def); static osal_queue_handle_t usbd_queue_hdl; -static osal_semaphore_handle_t usbd_control_xfer_sem_hdl; +/*static*/ osal_semaphore_handle_t usbd_control_xfer_sem_hdl; // TODO may need to change to static with wrapper function tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * const p_request) { @@ -165,29 +158,14 @@ tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t { if ( TUSB_REQUEST_GET_DESCRIPTOR == p_request->bRequest ) { - OSAL_VAR uint8_t* p_buffer = NULL; - OSAL_VAR uint16_t length = 0; + uint8_t* p_buffer = NULL; + uint16_t length = 0; error = get_descriptor_subtask(coreid, p_request, &p_buffer, &length); -#ifdef USBD_CONTROL_ONE_PACKET_EACH_XFER - while ( length > USBD_COTNROL_MAX_LENGTH_EACH_XFER && error == TUSB_ERROR_NONE ) - { - usbd_devices[coreid].is_waiting_control_xfer = true; - - dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, USBD_COTNROL_MAX_LENGTH_EACH_XFER); // zero length - osal_semaphore_wait(usbd_control_xfer_sem_hdl, OSAL_TIMEOUT_NORMAL, &error); - - length -= USBD_COTNROL_MAX_LENGTH_EACH_XFER; - p_buffer += USBD_COTNROL_MAX_LENGTH_EACH_XFER; - - usbd_devices[coreid].is_waiting_control_xfer = false; - } -#endif - if ( TUSB_ERROR_NONE == error ) { - dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, length); + dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, length, false); } } else if ( TUSB_REQUEST_SET_ADDRESS == p_request->bRequest ) @@ -207,12 +185,14 @@ tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t //------------- Class/Interface Specific Request -------------// else if ( TUSB_REQUEST_RECIPIENT_INTERFACE == p_request->bmRequestType_bit.recipient) { - tusb_std_class_code_t class_code = usbd_devices[coreid].interface2class[ u16_low_u8(p_request->wIndex) ]; + OSAL_VAR tusb_std_class_code_t class_code; + + class_code = usbd_devices[coreid].interface2class[ u16_low_u8(p_request->wIndex) ]; if ( (TUSB_CLASS_AUDIO <= class_code) && (class_code <= TUSB_CLASS_AUDIO_VIDEO) && - usbd_class_drivers[class_code].control_request ) + usbd_class_drivers[class_code].control_request_subtask ) { - error = usbd_class_drivers[class_code].control_request(coreid, p_request); + OSAL_SUBTASK_INVOKED_AND_WAIT( usbd_class_drivers[class_code].control_request_subtask(coreid, p_request), error ); }else { error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; @@ -234,9 +214,9 @@ tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t { // Response with Protocol Stall if request is not supported dcd_pipe_control_stall(coreid); // ASSERT(error == TUSB_ERROR_NONE, VOID_RETURN); - }else - { // status phase - dcd_pipe_control_xfer(coreid, 1-p_request->bmRequestType_bit.direction, NULL, 0); // zero length + }else if (p_request->wLength == 0) + { + dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, NULL, 0, false); // zero length for non-data } OSAL_SUBTASK_END @@ -418,10 +398,7 @@ void usbd_xfer_isr(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xfer { if (edpt_hdl.class_code == 0 ) // Control Transfer { - if (usbd_devices[edpt_hdl.coreid].is_waiting_control_xfer) - { - osal_semaphore_post( usbd_control_xfer_sem_hdl ); - } + osal_semaphore_post( usbd_control_xfer_sem_hdl ); }else { usbd_task_event_t task_event = diff --git a/tinyusb/device/usbd.h b/tinyusb/device/usbd.h index 12b329aa8..83837ebfe 100644 --- a/tinyusb/device/usbd.h +++ b/tinyusb/device/usbd.h @@ -70,7 +70,7 @@ typedef struct { void (* const init) (void); tusb_error_t (* const open)(uint8_t, tusb_descriptor_interface_t const *, uint16_t*); - tusb_error_t (* const control_request) (uint8_t, tusb_control_request_t const *); + tusb_error_t (* const control_request_subtask) (uint8_t, tusb_control_request_t const *); tusb_error_t (* const xfer_cb) (endpoint_handle_t, tusb_event_t, uint32_t); void (* const close) (uint8_t); } usbd_class_driver_t; @@ -90,8 +90,11 @@ bool tusbd_is_configured(uint8_t coreid) ATTR_WARN_UNUSED_RESULT; //--------------------------------------------------------------------+ #ifdef _TINY_USB_SOURCE_FILE_ +extern osal_semaphore_handle_t usbd_control_xfer_sem_hdl; + tusb_error_t usbd_init(void); OSAL_TASK_FUNCTION (usbd_task) (void* p_task_para); + #endif #ifdef __cplusplus diff --git a/tinyusb/device/usbd_dcd.h b/tinyusb/device/usbd_dcd.h index a4a37cd94..f37fd663d 100644 --- a/tinyusb/device/usbd_dcd.h +++ b/tinyusb/device/usbd_dcd.h @@ -68,7 +68,6 @@ typedef enum { typedef struct { volatile uint8_t state; - uint8_t is_waiting_control_xfer; // set if task is waiting for control xfer to complete to proceed uint8_t interface2class[USBD_INTERFACE_NUM_MAX]; // determine interface number belongs to which class }usbd_device_info_t;