sxkbd

Firmware for RP2040-based corne split keyboard
git clone https://git.sinitax.com/sinitax/sxkbd
Log | Files | Refs | Submodules | README | LICENSE | sfeed.txt

usb_descriptors.c (5638B)


      1#include "hid.h"
      2
      3#include "class/hid/hid_device.h"
      4#include "tusb.h"
      5#include "tusb_types.h"
      6
      7#define ARRLEN(x) (sizeof(x) / sizeof((x)[0]))
      8
      9#define CONFIG_TOTAL_LEN \
     10	(TUD_CONFIG_DESC_LEN + 2 * TUD_HID_DESC_LEN + TUD_CDC_DESC_LEN)
     11
     12/* MCU-specific! */
     13#define EPNUM_HID_KBD    0x81
     14#define EPNUM_HID_MISC   0x82
     15#define EPNUM_CDC_NOTIF  0x84
     16#define EPNUM_CDC_IN     0x85
     17#define EPNUM_CDC_OUT    0x05
     18
     19/* NOTE: same VID/PID with different interface can cause issues! */
     20
     21enum {
     22	ITF_NUM_HID_KBD,
     23	ITF_NUM_HID_MISC,
     24	ITF_NUM_CDC,
     25	ITF_NUM_CDC_DATA,
     26	ITF_NUM_TOTAL
     27};
     28
     29static const tusb_desc_device_t desc_device = {
     30	.bLength            = sizeof(tusb_desc_device_t),
     31	.bDescriptorType    = TUSB_DESC_DEVICE,
     32	.bcdUSB             = 0x200,
     33
     34	.bDeviceClass       = 0x00,
     35	.bDeviceSubClass    = 0x00,
     36	.bDeviceProtocol    = 0x00,
     37
     38	.bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,
     39
     40	.idVendor           = 0x1209,
     41	.idProduct          = 0xDEF0,
     42	.bcdDevice          = 0x0100,
     43
     44	.iManufacturer      = 0x01,
     45	.iProduct           = 0x02,
     46	.iSerialNumber      = 0x03,
     47
     48	.bNumConfigurations = 0x01
     49};
     50
     51static const uint8_t desc_hid_kbd_report[] = {
     52	TUD_HID_REPORT_DESC_KEYBOARD()
     53};
     54
     55static const uint8_t desc_hid_misc_report[] = {
     56	TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID_MOUSE)),
     57	TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(REPORT_ID_CONSUMER)),
     58	TUD_HID_REPORT_DESC_SYSTEM_CONTROL(HID_REPORT_ID(REPORT_ID_SYSTEM)),
     59	TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(REPORT_ID_GAMEPAD))
     60};
     61
     62static const uint8_t desc_fs_configuration[] = {
     63	/* Config number, interface count, string index,
     64	 * total length, attribute, power in mA */
     65	TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN,
     66		TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
     67
     68	/* Interface number, string index, protocol, report descriptor len,
     69	 * EP In address, size & polling interval */
     70	TUD_HID_DESCRIPTOR(ITF_NUM_HID_KBD, 5, HID_ITF_PROTOCOL_KEYBOARD,
     71		sizeof(desc_hid_kbd_report), EPNUM_HID_KBD, 8, 1),
     72	TUD_HID_DESCRIPTOR(ITF_NUM_HID_MISC, 6, HID_ITF_PROTOCOL_NONE,
     73		sizeof(desc_hid_misc_report), EPNUM_HID_MISC, 16, 1),
     74
     75	/* Interface number, string index, EP notification address and size,
     76	 * EP data address (out, in) and size */
     77	TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8,
     78		EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
     79};
     80
     81#if TUD_OPT_HIGH_SPEED
     82static const uint8_t desc_hs_configuration[] = {
     83	/* Config number, interface count, string index,
     84	 * total length, attribute, power in mA */
     85	TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN,
     86		TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
     87
     88	/* Interface number, string index, protocol, report descriptor len,
     89	 * EP In address, size & polling interval */
     90	TUD_HID_DESCRIPTOR(ITF_NUM_HID_KBD, 5, HID_ITF_PROTOCOL_KEYBOARD,
     91		sizeof(desc_hid_kbd_report), EPNUM_HID_KBD, 8, 1),
     92	TUD_HID_DESCRIPTOR(ITF_NUM_HID_MISC, 6, HID_ITF_PROTOCOL_NONE,
     93		sizeof(desc_hid_misc_report), EPNUM_HID_MISC, 16, 1),
     94
     95	/* Interface number, string index, EP notification address and size,
     96	 * EP data address (out, in) and size */
     97	TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8,
     98		EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
     99};
    100
    101static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
    102
    103static const tusb_desc_device_qualifier_t desc_device_qualifier =
    104{
    105	.bLength            = sizeof(tusb_desc_device_qualifier_t),
    106	.bDescriptorType    = TUSB_DESC_DEVICE_QUALIFIER,
    107	.bcdUSB             = 0x200,
    108
    109	.bDeviceClass       = 0x00,
    110	.bDeviceSubClass    = 0x00,
    111	.bDeviceProtocol    = 0x00,
    112
    113	.bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,
    114	.bNumConfigurations = 0x01,
    115	.bReserved          = 0x00
    116};
    117#endif
    118
    119static const char *string_desc_arr[] = {
    120	[0] = "\x07\x04",       /* LangID: German (0x0407) */
    121	[1] = "SNX",            /* Manufacturer */
    122	[2] = "SXKBD Keyboard", /* Product */
    123	[3] = "000001",         /* Serial Number */
    124	[4] = "CDC",
    125	[5] = "HID-KBD",
    126	[6] = "HID-MISC"
    127};
    128
    129static uint16_t _desc_str[32];
    130
    131const uint8_t *
    132tud_descriptor_device_cb(void)
    133{
    134	return (const uint8_t *) &desc_device;
    135}
    136
    137const uint8_t *
    138tud_hid_descriptor_report_cb(uint8_t instance)
    139{
    140	if (instance == INST_HID_KBD)
    141		return desc_hid_kbd_report;
    142	else
    143		return desc_hid_misc_report;
    144}
    145
    146const uint8_t *
    147tud_descriptor_configuration_cb(uint8_t instance)
    148{
    149#if TUD_OPT_HIGH_SPEED
    150	if (tud_speed_get() == TUSB_SPEED_HIGH)
    151		return desc_hs_configuration;
    152	else
    153		return desc_fs_configuration;
    154#else
    155	return desc_fs_configuration;
    156#endif
    157}
    158
    159const uint16_t *
    160tud_descriptor_string_cb(uint8_t index, uint16_t langid)
    161{
    162	const char *str;
    163	uint8_t i, chr_count;
    164
    165	if (index == 0) {
    166		memcpy(&_desc_str[1], string_desc_arr[0], 2);
    167		chr_count = 1;
    168	} else {
    169		if (index >= ARRLEN(string_desc_arr))
    170			return NULL;
    171
    172		str = string_desc_arr[index];
    173
    174		chr_count = (uint8_t) strlen(str);
    175		if (chr_count > 31) chr_count = 31;
    176
    177		/* Convert ASCII string into UTF-16 */
    178		for (i = 0; i < chr_count; i++)
    179			_desc_str[i+1] = str[i];
    180	}
    181
    182	/* first byte is length (including header), second byte is type */
    183	_desc_str[0] = (uint8_t) (2 * chr_count + 2);
    184	_desc_str[0] |= (uint16_t) (TUSB_DESC_STRING << 8);
    185
    186	return _desc_str;
    187}
    188
    189#if TUD_OPT_HIGH_SPEED
    190const uint8_t *
    191tud_descriptor_device_qualifier_cb(void)
    192{
    193	return (const uint8_t *) &desc_device_qualifier;
    194}
    195
    196const uint8_t *
    197tud_descriptor_other_speed_configuration_cb(uint8_t instance)
    198{
    199	if (tud_speed_get() == TUSB_SPEED_HIGH) {
    200		memcpy(desc_other_speed_config, desc_hs_configuration,
    201			CONFIG_TOTAL_LEN);
    202	} else {
    203		memcpy(desc_other_speed_config, desc_fs_configuration,
    204			CONFIG_TOTAL_LEN);
    205	}
    206
    207	desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
    208
    209	return desc_other_speed_config;
    210}
    211#endif