From 1982886f87f87785fbc8b12dbc77393b0371bec2 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 25 Jul 2018 15:58:52 +0700 Subject: [PATCH] add control set boot protocol support and keyboard idle rate - tud_hid_keyboard_is_boot_protocol() - tud_hid_mouse_is_boot_protocol() --- examples/device/nrf52840/src/main.c | 10 +++--- src/class/hid/hid_device.c | 52 +++++++++++++++++++---------- src/class/hid/hid_device.h | 15 ++++++--- 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/examples/device/nrf52840/src/main.c b/examples/device/nrf52840/src/main.c index 5ece8bf96..0008bb69c 100644 --- a/examples/device/nrf52840/src/main.c +++ b/examples/device/nrf52840/src/main.c @@ -134,10 +134,12 @@ void usb_hid_task(void) /*------------- Mouse -------------*/ if ( tud_hid_mouse_ready() ) { - if ( btn & 0x01 ) tud_hid_mouse_move(-10, 0 ); // left - else if( btn & 0x02 ) tud_hid_mouse_move( 10, 0 ); // right - else if( btn & 0x04 ) tud_hid_mouse_move( 0, -10); // up - else if( btn & 0x08 ) tud_hid_mouse_move( 0, 10); // down + enum { DELTA = 5 }; + + if ( btn & 0x01 ) tud_hid_mouse_move(-DELTA, 0); // left + if ( btn & 0x02 ) tud_hid_mouse_move( DELTA, 0); // right + if ( btn & 0x04 ) tud_hid_mouse_move( 0 , -DELTA); // up + if ( btn & 0x08 ) tud_hid_mouse_move( 0 , DELTA); // down } } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 59bf24256..81805665e 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -58,7 +58,9 @@ typedef struct { uint8_t itf_num; uint8_t ep_in; - uint8_t idle_rate; + + uint8_t idle_rate; // in unit of 4 ms + bool boot_protocol; uint8_t report_id; uint16_t report_len; @@ -92,24 +94,30 @@ bool tud_hid_keyboard_ready(void) return !dcd_edpt_busy(TUD_OPT_RHPORT, _kbd_itf.ep_in); } +bool tud_hid_keyboard_is_boot_protocol(void) +{ + return _kbd_itf.boot_protocol; +} + static bool hidd_kbd_report(hid_keyboard_report_t const *p_report) { VERIFY( tud_hid_keyboard_ready() ); hidd_interface_t * p_hid = &_kbd_itf; - if ( p_report ) - { - memcpy(p_hid->report_buf, p_report, sizeof(hid_keyboard_report_t)); - }else - { - // only send empty report if previous report is not empty - // TODO idle rate - if ( mem_all_zero(p_hid->report_buf, sizeof(hid_keyboard_report_t)) ) return true; + // Idle Rate = 0 : only send report if there is changes, i.e skip duplication + // Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). + // If idle time is less than interrupt polling then use the polling. + static tu_timeout_t idle_tm = { 0, 0 }; - arrclr_(p_hid->report_buf); + if ( (p_hid->idle_rate == 0) || !tu_timeout_expired(&idle_tm) ) + { + if ( 0 == memcmp(p_hid->report_buf, p_report, sizeof(hid_keyboard_report_t)) ) return true; } + tu_timeout_restart(&idle_tm); + + memcpy(p_hid->report_buf, p_report, sizeof(hid_keyboard_report_t)); return dcd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->report_buf, sizeof(hid_keyboard_report_t)); } @@ -173,12 +181,18 @@ bool tud_hid_keyboard_key_sequence(const char* str, uint32_t interval_ms) // MOUSE APPLICATION API //--------------------------------------------------------------------+ #if CFG_TUD_HID_MOUSE + bool tud_hid_mouse_ready(void) { VERIFY( _mse_itf.ep_in != 0 ); return !dcd_edpt_busy(TUD_OPT_RHPORT, _mse_itf.ep_in); } +bool tud_hid_mouse_is_boot_protocol(void) +{ + return _mse_itf.boot_protocol; +} + static bool hidd_mouse_report(hid_mouse_report_t const *p_report) { VERIFY( tud_hid_mouse_ready() ); @@ -302,10 +316,11 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, u TU_ASSERT( dcd_edpt_open(rhport, desc_edpt), TUSB_ERROR_DCD_FAILED ); - p_hid->report_len = desc_hid->wReportLength; - p_hid->itf_num = desc_itf->bInterfaceNumber; - p_hid->ep_in = desc_edpt->bEndpointAddress; - p_hid->report_id = 0; + p_hid->boot_protocol = true; // default to boot mode when mounted + p_hid->report_len = desc_hid->wReportLength; + p_hid->itf_num = desc_itf->bInterfaceNumber; + p_hid->ep_in = desc_edpt->bEndpointAddress; + p_hid->report_id = 0; *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t); } @@ -402,12 +417,15 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons } else if (HID_REQ_CONTROL_GET_PROTOCOL == p_request->bRequest ) { - _usbd_ctrl_buf[0] = 1 - CFG_TUD_HID_BOOT_PROTOCOL; // 0 is Boot, 1 is Report protocol + _usbd_ctrl_buf[0] = 1-p_hid->boot_protocol; // 0 is Boot, 1 is Report protocol usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, _usbd_ctrl_buf, 1); } - else + 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 + dcd_control_status(rhport, p_request->bmRequestType_bit.direction); + }else { -// HID_REQ_CONTROL_SET_PROTOCOL: dcd_control_stall(rhport); } }else diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 659981a48..e8f5b40f4 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -61,6 +61,7 @@ * \note Application must not perform any action if the interface is not ready */ bool tud_hid_keyboard_ready(void); +bool tud_hid_keyboard_is_boot_protocol(void); bool tud_hid_keyboard_keycode(uint8_t modifier, uint8_t keycode[6]); @@ -77,10 +78,9 @@ typedef struct{ extern const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128]; #endif -/*------------- Callbacks -------------*/ +/*------------- Callbacks, ATTR_WEAK means optional -------------*/ -/** \brief Callback function that is invoked when USB host request \ref HID_REQUEST_CONTROL_GET_REPORT - * via control endpoint. +/** Callback invoked when USB host request \ref HID_REQ_CONTROL_GET_REPORT. * \param[in] report_type specify which report (INPUT, OUTPUT, FEATURE) that host requests * \param[out] buffer data that application need to update, value must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM) * \param[in] reqlen number of bytes that host requested @@ -93,8 +93,7 @@ extern const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128]; */ ATTR_WEAK uint16_t tud_hid_keyboard_get_report_cb(hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); -/** \brief Callback function that is invoked when USB host request \ref HID_REQUEST_CONTROL_SET_REPORT - * via control endpoint. +/** Callback invoked when USB host request \ref HID_REQ_CONTROL_SET_REPORT. * \param[in] report_type specify which report (INPUT, OUTPUT, FEATURE) that host requests * \param[in] buffer containing the report's data * \param[in] bufsize number of bytes in the \a buffer @@ -103,6 +102,9 @@ ATTR_WEAK uint16_t tud_hid_keyboard_get_report_cb(hid_report_type_t report_type, */ ATTR_WEAK void tud_hid_keyboard_set_report_cb(hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); + +//ATTR_WEAK void tud_hid_keyboard_set_protocol_cb(bool boot_protocol); + /** @} */ /** @} */ @@ -120,6 +122,7 @@ ATTR_WEAK void tud_hid_keyboard_set_report_cb(hid_report_type_t report_type, uin * \note This function is primarily used for polling/waiting result after \ref tusbd_hid_mouse_send. */ bool tud_hid_mouse_ready(void); +bool tud_hid_mouse_is_boot_protocol(void); bool tud_hid_mouse_data(uint8_t buttons, int8_t x, int8_t y, int8_t scroll, int8_t pan); @@ -161,6 +164,8 @@ ATTR_WEAK uint16_t tud_hid_mouse_get_report_cb(hid_report_type_t report_type, ui */ ATTR_WEAK void tud_hid_mouse_set_report_cb(hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); +//ATTR_WEAK void tud_hid_mouse_set_protocol_cb(bool boot_protocol); + /** @} */ /** @} */