summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2021-02-09 15:57:29 +0700
committerhathach <[email protected]>2021-02-09 15:57:29 +0700
commitd2b8e591f6f939f87c28aaa8b12f67a5072d2b06 (patch)
treec97c4692866d3ec7cf3b3f7c4e1fe3acd3fcead5
parentecd16cf24bcef606019c8e4d694b3bf0f138c9aa (diff)
tud_hid_report_complete_cb() API
update hid composite to make use of tud_hid_report_complete_cb() for sending reports when possible.
-rw-r--r--changelog.md6
-rw-r--r--examples/device/hid_composite/src/main.c185
-rw-r--r--examples/device/hid_composite/src/usb_descriptors.c2
-rw-r--r--examples/device/hid_composite/src/usb_descriptors.h3
-rw-r--r--src/class/hid/hid_device.c20
-rw-r--r--src/class/hid/hid_device.h5
6 files changed, 131 insertions, 90 deletions
diff --git a/changelog.md b/changelog.md
index 393ca24ca..d645b4fbf 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,11 @@
# TinyUSB Changelog
+## WIP
+
+- Fix dropping MIDI sysex message when fifo is full
+- Add DPad/Hat support for HID Gamepad
+- Add tud_hid_report_complete_cb() API
+
## 0.8.0 - 2021.02.05
### Device Controller Driver
diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c
index 45b8ba674..9fb2de88d 100644
--- a/examples/device/hid_composite/src/main.c
+++ b/examples/device/hid_composite/src/main.c
@@ -104,114 +104,135 @@ void tud_resume_cb(void)
// USB HID
//--------------------------------------------------------------------+
-void hid_task(void)
+static void send_hid_report(uint8_t report_id, uint32_t btn)
{
- // Poll every 10ms
- const uint32_t interval_ms = 10;
- static uint32_t start_ms = 0;
+ // skip if hid is not ready yet
+ if ( !tud_hid_ready() ) return;
- if ( board_millis() - start_ms < interval_ms) return; // not enough time
- start_ms += interval_ms;
+ switch(report_id)
+ {
+ case REPORT_ID_KEYBOARD:
+ {
+ // use to avoid send multiple consecutive zero report for keyboard
+ static bool has_keyboard_key = false;
- uint32_t const btn = board_button_read();
+ if ( btn )
+ {
+ uint8_t keycode[6] = { 0 };
+ keycode[0] = HID_KEY_A;
- // Remote wakeup
- if ( tud_suspended() && btn )
- {
- // Wake up host if we are in suspend mode
- // and REMOTE_WAKEUP feature is enabled by host
- tud_remote_wakeup();
- }
+ tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
+ has_keyboard_key = true;
+ }else
+ {
+ // send empty key report if previously has key pressed
+ if (has_keyboard_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL);
+ has_keyboard_key = false;
+ }
+ }
+ break;
- /*------------- Mouse -------------*/
- if ( tud_hid_ready() )
- {
- if ( btn )
+ case REPORT_ID_MOUSE:
{
int8_t const delta = 5;
- // no button, right + down, no scroll pan
+ // no button, right + down, no scroll, no pan
tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0);
-
- // delay a bit before sending keyboard report
- board_delay(10);
}
- }
-
- /*------------- Keyboard -------------*/
- if ( tud_hid_ready() )
- {
- // use to avoid send multiple consecutive zero report for keyboard
- static bool has_key = false;
+ break;
- if ( btn )
+ case REPORT_ID_CONSUMER_CONTROL:
{
- uint8_t keycode[6] = { 0 };
- keycode[0] = HID_KEY_A;
-
- tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
+ // use to avoid send multiple consecutive zero report
+ static bool has_consumer_key = false;
- has_key = true;
- }else
- {
- // send empty key report if previously has key pressed
- if (has_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL);
- has_key = false;
+ if ( btn )
+ {
+ // volume down
+ uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT;
+ tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2);
+ has_consumer_key = true;
+ }else
+ {
+ // send empty key report (release key) if previously has key pressed
+ uint16_t empty_key = 0;
+ if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2);
+ has_consumer_key = false;
+ }
}
+ break;
- // delay a bit before sending consumer report
- board_delay(10);
- }
+ case REPORT_ID_GAMEPAD:
+ {
+ // use to avoid send multiple consecutive zero report for keyboard
+ static bool has_gamepad_key = false;
- /*------------- Consume Control -------------*/
- if ( tud_hid_ready() )
- {
- // use to avoid send multiple consecutive zero report
- static bool has_consumer_key = false;
+ hid_gamepad_report_t report =
+ {
+ .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0,
+ .hat = 0, .buttons = 0
+ };
- if ( btn )
- {
- // volume down
- uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT;
- tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2);
+ if ( btn )
+ {
+ report.hat = GAMEPAD_HAT_UP;
+ report.buttons = GAMEPAD_BUTTON_A;
+ tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
- has_consumer_key = true;
- }else
- {
- // send empty key report (release key) if previously has key pressed
- uint16_t empty_key = 0;
- if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2);
- has_consumer_key = false;
+ has_gamepad_key = true;
+ }else
+ {
+ report.hat = GAMEPAD_HAT_CENTERED;
+ report.buttons = 0;
+ if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
+ has_gamepad_key = false;
+ }
}
+ break;
- // delay a bit before sending next report
- board_delay(10);
+ default: break;
}
+}
+
+// Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..)
+// tud_hid_report_complete_cb() is used to send the next report after previous one is complete
+void hid_task(void)
+{
+ // Poll every 10ms
+ const uint32_t interval_ms = 10;
+ static uint32_t start_ms = 0;
+
+ if ( board_millis() - start_ms < interval_ms) return; // not enough time
+ start_ms += interval_ms;
- /*------------- Gamepad -------------*/
- if ( tud_hid_ready() )
+ uint32_t const btn = board_button_read();
+
+ // Remote wakeup
+ if ( tud_suspended() && btn )
{
- // use to avoid send multiple consecutive zero report for keyboard
- static bool has_gamepad_key = false;
+ // Wake up host if we are in suspend mode
+ // and REMOTE_WAKEUP feature is enabled by host
+ tud_remote_wakeup();
+ }else
+ {
+ // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb()
+ send_hid_report(REPORT_ID_KEYBOARD, btn);
+ }
+}
- hid_gamepad_report_t report =
- {
- .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0,
- .hat = 0, .buttons = 0
- };
+// Invoked when sent REPORT successfully to host
+// Application can use this to send the next report
+// Note: For composite reports, report[0] is report ID
+void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len)
+{
+ (void) itf;
+ (void) len;
- if ( btn )
- {
- report.hat = GAMEPAD_HAT_UP;
- tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
+ uint8_t next_report_id = report[0] + 1;
- has_gamepad_key = true;
- }else
- {
- report.hat = GAMEPAD_HAT_CENTERED;
- if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
- has_gamepad_key = false;
- }
+ if (next_report_id < REPORT_ID_COUNT)
+ {
+ send_hid_report(next_report_id, board_button_read());
}
}
diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c
index fbe0e2550..e5f1ea703 100644
--- a/examples/device/hid_composite/src/usb_descriptors.c
+++ b/examples/device/hid_composite/src/usb_descriptors.c
@@ -107,7 +107,7 @@ uint8_t const desc_configuration[] =
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
- TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
+ TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 2)
};
// Invoked when received GET CONFIGURATION DESCRIPTOR
diff --git a/examples/device/hid_composite/src/usb_descriptors.h b/examples/device/hid_composite/src/usb_descriptors.h
index 7894719fd..ca8925ad9 100644
--- a/examples/device/hid_composite/src/usb_descriptors.h
+++ b/examples/device/hid_composite/src/usb_descriptors.h
@@ -30,7 +30,8 @@ enum
REPORT_ID_KEYBOARD = 1,
REPORT_ID_MOUSE,
REPORT_ID_CONSUMER_CONTROL,
- REPORT_ID_GAMEPAD
+ REPORT_ID_GAMEPAD,
+ REPORT_ID_COUNT
};
#endif /* USB_DESCRIPTORS_H_ */
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c
index 5b9735071..4cdcecc9e 100644
--- a/src/class/hid/hid_device.c
+++ b/src/class/hid/hid_device.c
@@ -381,14 +381,24 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
uint8_t itf = 0;
hidd_interface_t * p_hid = _hidd_itf;
- for ( ; ; itf++, p_hid++)
+ // Identify which interface to use
+ for (itf = 0; itf < CFG_TUD_HID; itf++)
{
- if (itf >= TU_ARRAY_SIZE(_hidd_itf)) return false;
-
- if ( ep_addr == p_hid->ep_out ) break;
+ p_hid = &_hidd_itf[itf];
+ if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break;
}
+ TU_ASSERT(itf < CFG_TUD_HID);
- if (ep_addr == p_hid->ep_out)
+ // Sent report successfully
+ if (ep_addr == p_hid->ep_in)
+ {
+ if (tud_hid_report_complete_cb)
+ {
+ tud_hid_report_complete_cb(itf, p_hid->epin_buf, (uint8_t) xferred_bytes);
+ }
+ }
+ // Received report
+ else if (ep_addr == p_hid->ep_out)
{
tud_hid_set_report_cb(
#if CFG_TUD_HID > 1
diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h
index a92dc14e0..d5de53221 100644
--- a/src/class/hid/hid_device.h
+++ b/src/class/hid/hid_device.h
@@ -123,7 +123,10 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate);
#endif
-// TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, );
+// Invoked when sent REPORT successfully to host
+// Application can use this to send the next report
+// Note: For composite reports, report[0] is report ID
+TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len);
//--------------------------------------------------------------------+