aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2022-11-20 19:26:20 +0100
committerLouis Burda <quent.burda@gmail.com>2022-11-20 19:26:20 +0100
commit7f1cf3407ab3ba4827053133a7a47901ce763c61 (patch)
tree85f5d8030fb6810b83cbb3a2590108d8888feb5b /src
parent7162946544630859face4ef3e397c16d823028f5 (diff)
downloadsxkbd-7f1cf3407ab3ba4827053133a7a47901ce763c61.tar.gz
sxkbd-7f1cf3407ab3ba4827053133a7a47901ce763c61.zip
Integrate tinyUSB composite HID example
Diffstat (limited to 'src')
-rw-r--r--src/board.h8
-rw-r--r--src/main.c137
-rw-r--r--src/tusb_config.h2
-rw-r--r--src/usb_descriptors.c46
4 files changed, 164 insertions, 29 deletions
diff --git a/src/board.h b/src/board.h
index 38775b7..77d1840 100644
--- a/src/board.h
+++ b/src/board.h
@@ -4,4 +4,12 @@
#define ONBOARD_LED_PIN 25
+#define REPORT_ID_MIN REPORT_ID_KEYBOARD
+enum {
+ REPORT_ID_KEYBOARD = 1,
+ REPORT_ID_MOUSE,
+ REPORT_ID_CONSUMER_CONTROL,
+ REPORT_ID_MAX
+};
+
extern struct neopix onboard_led;
diff --git a/src/main.c b/src/main.c
index 1e386d4..841ce45 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,7 @@
#include "board.h"
#include "class/cdc/cdc_device.h"
+#include "class/hid/hid.h"
+#include "device/usbd.h"
#include "neopix.h"
#include "util.h"
@@ -24,7 +26,10 @@ void stub_stdio_write(const char *buf, int len);
void stub_stdio_flush(void);
int stub_stdio_read(char *buf, int len);
-void led_blinking_task(void);
+bool send_hid_report(int id, bool state);
+
+void hid_task(void);
+void blink_task(void);
static struct stdio_driver usb_stdio = {
.out_chars = stub_stdio_write,
@@ -35,6 +40,8 @@ static struct stdio_driver usb_stdio = {
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
+static bool hit_state = false;
+
struct neopix onboard_led;
int
@@ -51,7 +58,8 @@ main(void)
while (true) {
tud_task();
- led_blinking_task();
+ blink_task();
+ hid_task();
}
return 0;
@@ -114,7 +122,6 @@ tud_cdc_rx_cb(uint8_t itf)
(void) itf;
}
-/* Invoked on GET_REPORT */
uint16_t
tud_hid_get_report_cb(uint8_t itf, uint8_t report_id,
hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
@@ -128,7 +135,6 @@ tud_hid_get_report_cb(uint8_t itf, uint8_t report_id,
return 0;
}
-/* Invoked on SET_REPORT or receive on OUT with (Report ID = 0, Type = 0) */
void
tud_hid_set_report_cb(uint8_t itf, uint8_t report_id,
hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
@@ -136,21 +142,136 @@ tud_hid_set_report_cb(uint8_t itf, uint8_t report_id,
(void) itf;
(void) report_id;
(void) report_type;
+ (void) buffer;
+ (void) bufsize;
+}
+
+void
+tud_hid_report_complete_cb(uint8_t instance,
+ uint8_t const *report, uint8_t len)
+{
+ uint8_t id;
+
+ (void) instance;
+ (void) report;
+ (void) len;
+
+ for (id = report[0] + 1; id < REPORT_ID_MAX; id++) {
+ if (send_hid_report(id, hit_state))
+ break;
+ }
+}
+
+bool
+send_keyboard_report(bool state)
+{
+ static bool cleared = true;
+ uint8_t keycode[6] = { 0 };
+
+ if (state) {
+ keycode[0] = HID_KEY_A;
+ tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
+ cleared = false;
+ return true;
+ } else if (!cleared) {
+ tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL);
+ cleared = true;
+ return true;
+ }
+
+ return false;
+}
+
+bool
+send_mouse_report(bool state)
+{
+ if (state) {
+ tud_hid_mouse_report(REPORT_ID_MOUSE, 0, 10, 10, 0, 0);
+ return true;
+ }
+
+ return false;
+}
+
+bool
+send_consumer_control_report(bool state)
+{
+ static bool cleared = true;
+ uint16_t report;
+
+ if (state) {
+ report = HID_USAGE_CONSUMER_VOLUME_DECREMENT;
+ tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &report, 2);
+ cleared = false;
+ return true;
+ } else if (!cleared) {
+ report = 0;
+ tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &report, 2);
+ cleared = true;
+ return true;
+ }
- tud_hid_report(0, buffer, bufsize);
+ return false;
+}
+
+bool
+send_hid_report(int id, bool state)
+{
+ switch (id) {
+ case REPORT_ID_KEYBOARD:
+ return send_keyboard_report(state);
+ case REPORT_ID_MOUSE:
+ return send_mouse_report(state);
+ case REPORT_ID_CONSUMER_CONTROL:
+ return send_consumer_control_report(state);
+ }
+
+ return false;
+}
+
+void
+send_hid_report_timed(void)
+{
+ const uint32_t period_ms = 1000;
+ static uint32_t start_ms = 0;
+
+ if (!tud_hid_ready()) return;
+
+ hit_state = (board_millis() - start_ms < period_ms);
+ if (hit_state) start_ms += period_ms;
+
+ send_hid_report(REPORT_ID_MIN, hit_state);
}
void
-led_blinking_task(void)
+hid_task(void)
+{
+ const uint32_t poll_ms = 10;
+ static uint32_t start_ms = 0;
+
+ if (board_millis() - start_ms < poll_ms)
+ return;
+ start_ms += poll_ms;
+
+ // if (tud_suspended()) {
+ // tud_remote_wakeup();
+ // return;
+ // }
+
+ send_hid_report_timed();
+}
+
+void
+blink_task(void)
{
static uint32_t start_ms = 0;
static bool state = false;
if (board_millis() - start_ms < blink_interval_ms)
return;
+ start_ms += blink_interval_ms;
+ state ^= true;
neopix_put(&onboard_led, neopix_u32rgb(255 * state, 0, 255 * state));
- start_ms += blink_interval_ms;
- state ^= true;
}
diff --git a/src/tusb_config.h b/src/tusb_config.h
index cd251d6..31bdac7 100644
--- a/src/tusb_config.h
+++ b/src/tusb_config.h
@@ -46,6 +46,8 @@ extern "C" {
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 0
+#define CFG_TUD_HID_EP_BUFSIZE 16
+
#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c
index 8372c2a..8b648ef 100644
--- a/src/usb_descriptors.c
+++ b/src/usb_descriptors.c
@@ -1,32 +1,32 @@
+#include "board.h"
+
+#include "class/hid/hid_device.h"
#include "tusb.h"
#include "tusb_types.h"
#define ARRLEN(x) (sizeof(x) / sizeof((x)[0]))
-/* same VID/PID with difference interface can cause issues! */
+/* same VID/PID with different interface can cause issues! */
#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) \
| _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4))
-#define USB_VID 0xC0FE
+#define USB_VID 0xC0FF
#define USB_BCD 0x0200
#define CONFIG_TOTAL_LEN \
- (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN)
-
-#define EPNUM_HID 0x01
+ (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_DESC_LEN)
/* MCU-specific! */
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x82
-#define EPNUM_MSC_OUT 0x03
-#define EPNUM_MSC_IN 0x83
+#define EPNUM_HID 0x83
enum {
ITF_NUM_CDC,
- ITF_NUM_CTC_DATA,
+ ITF_NUM_CDC_DATA,
ITF_NUM_HID,
ITF_NUM_TOTAL
};
@@ -36,9 +36,9 @@ tusb_desc_device_t const desc_device = {
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = USB_BCD,
- .bDeviceClass = TUSB_CLASS_MISC,
- .bDeviceSubClass = MISC_SUBCLASS_COMMON,
- .bDeviceProtocol = MISC_PROTOCOL_IAD,
+ .bDeviceClass = 0x00,
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
@@ -54,13 +54,16 @@ tusb_desc_device_t const desc_device = {
};
uint8_t const desc_hid_report[] = {
- TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE)
+ TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD)),
+ TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID_MOUSE)),
+ TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL))
};
uint8_t const desc_fs_configuration[] = {
/* Config number, interface count, string index,
* total length, attribute, power in mA */
- TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN,
+ TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
/* Interface number, string index, EP notification address and size,
* EP data address (out, in) and size */
@@ -68,16 +71,17 @@ uint8_t const desc_fs_configuration[] = {
EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
/* Interface number, string index, protocol, report descriptor len,
- * EP In & Out address, size & polling interval */
- TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 5, HID_ITF_PROTOCOL_NONE,
- sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, 64, 10)
+ * EP In address, size & polling interval */
+ TUD_HID_DESCRIPTOR(ITF_NUM_HID, 5, HID_ITF_PROTOCOL_NONE,
+ sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5)
};
#if TUD_OPT_HIGH_SPEED
uint8_t const desc_hs_configuration[] = {
/* Config number, interface count, string index,
* total length, attribute, power in mA */
- TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN,
+ TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
/* Interface number, string index, EP notification address and size,
* EP data address (out, in) and size */
@@ -85,9 +89,9 @@ uint8_t const desc_hs_configuration[] = {
EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
/* Interface number, string index, protocol, report descriptor len,
- * EP In & Out address, size & polling interval */
- TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 5, HID_ITF_PROTOCOL_NONE,
- sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, 512, 10)
+ * EP In address, size & polling interval */
+ TUD_HID_DESCRIPTOR(ITF_NUM_HID, 5, HID_ITF_PROTOCOL_NONE,
+ sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5)
};
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
@@ -109,7 +113,7 @@ tusb_desc_device_qualifier_t const desc_device_qualifier =
#endif
char const *string_desc_arr[] = {
- [0] = (const char[]) { 0x09, 0x04 }, /* supported language is English */
+ [0] = (const char[]) { 0x09, 0x04 }, /* Supported language is English */
[1] = "TinyUSB", /* Manufacturer */
[2] = "TinyUSB Device", /* Product */
[3] = "123456", /* Serials, should use chip ID */