From 757496f8a091734b24c5cf7d98682baea2061908 Mon Sep 17 00:00:00 2001 From: whowechina Date: Wed, 18 Sep 2024 21:56:38 +0800 Subject: [PATCH] IO4 can be turned off (to live with official IO4 board) --- Production/firmware/mai_pico.uf2 | Bin 150528 -> 151040 bytes firmware/src/commands.c | 21 ++- firmware/src/config.c | 4 +- firmware/src/config.h | 2 +- firmware/src/hid.c | 2 +- firmware/src/main.c | 4 + firmware/src/usb_descriptors.c | 9 +- firmware/src/usb_descriptors.h | 303 ++++++++++++++++--------------- 8 files changed, 180 insertions(+), 165 deletions(-) diff --git a/Production/firmware/mai_pico.uf2 b/Production/firmware/mai_pico.uf2 index ed2cae56dbbd448f5e4217dba6ee3e8720076502..0063ace0e732953ada12f04a69b9b1b3e6435a83 100644 GIT binary patch delta 23711 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.joy ? "ON" : "OFF", + printf(" IO4: %s, NKRO: %s\n", mai_cfg->hid.io4 ? "on" : "off", mai_cfg->hid.nkro <= 2 ? nkro[mai_cfg->hid.nkro] : "key1"); if (mai_runtime.key_stuck) { - printf(" !!! Button stuck, force JOY only !!!\n"); + printf(" !!! Button stuck, force IO4 only !!!\n"); } } @@ -221,32 +221,35 @@ static void handle_stat(int argc, char *argv[]) static void handle_hid(int argc, char *argv[]) { - const char *usage = "Usage: hid \n"; + const char *usage = "Usage: hid \n"; if (argc != 1) { printf(usage); return; } - const char *choices[] = {"joy", "key1", "key2"}; - int match = cli_match_prefix(choices, 3, argv[0]); + const char *choices[] = {"io4", "key1", "key2", "off"}; + int match = cli_match_prefix(choices, count_of(choices), argv[0]); if (match < 0) { printf(usage); return; } switch (match) { - break; case 1: - mai_cfg->hid.joy = 0; + mai_cfg->hid.io4 = 0; mai_cfg->hid.nkro = 1; break; case 2: - mai_cfg->hid.joy = 0; + mai_cfg->hid.io4 = 0; mai_cfg->hid.nkro = 2; break; + case 3: + mai_cfg->hid.io4 = 0; + mai_cfg->hid.nkro = 0; + break; case 0: default: - mai_cfg->hid.joy = 1; + mai_cfg->hid.io4 = 1; mai_cfg->hid.nkro = 0; break; } diff --git a/firmware/src/config.c b/firmware/src/config.c index 82c38de..c8cb4f3 100644 --- a/firmware/src/config.c +++ b/firmware/src/config.c @@ -26,8 +26,8 @@ static mai_cfg_t default_cfg = { .debounce_release = 2, }, .hid = { - .joy = 0, - .nkro = 1, + .io4 = 1, + .nkro = 0, }, .rgb = { .per_button = 1, diff --git a/firmware/src/config.h b/firmware/src/config.h index 4a0ab21..3e78474 100644 --- a/firmware/src/config.h +++ b/firmware/src/config.h @@ -25,7 +25,7 @@ typedef struct __attribute__((packed)) { int8_t zones[34]; } sense; struct { - uint8_t joy : 4; + uint8_t io4 : 4; uint8_t nkro : 4; } hid; struct { diff --git a/firmware/src/hid.c b/firmware/src/hid.c index 2dbe579..51c53a6 100644 --- a/firmware/src/hid.c +++ b/firmware/src/hid.c @@ -42,7 +42,7 @@ static uint16_t native_to_io4(uint16_t button) static void report_usb_hid() { if (tud_hid_ready()) { - if (mai_cfg->hid.joy || mai_runtime.key_stuck) { + if (mai_cfg->hid.io4 || mai_runtime.key_stuck) { static uint16_t last_buttons = 0; uint16_t buttons = button_read(); hid_joy.buttons[0] = native_to_io4(buttons); diff --git a/firmware/src/main.c b/firmware/src/main.c index 65c329c..fb78620 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -145,6 +145,10 @@ void init() save_init(board_id_32() ^ 0xcafe1111, &core1_io_lock); + if (!mai_cfg->hid.io4) { + usb_descriptors_disable_io4(); + } + touch_init(); button_init(); rgb_init(); diff --git a/firmware/src/usb_descriptors.c b/firmware/src/usb_descriptors.c index db51649..661f32a 100644 --- a/firmware/src/usb_descriptors.c +++ b/firmware/src/usb_descriptors.c @@ -157,13 +157,15 @@ uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { static char serial_number_str[24] = "123456\0"; +static char joy_name_string[128] = "I/O CONTROL BD;15257;01;90;1831;6679A;00;GOUT=14_ADIN=8,E_ROTIN=4_COININ=2_SWIN=2,E_UQ1=41,6;"; + // array of pointer to string descriptors static const char *string_desc_arr[] = { (const char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) "SEGA", // 1: Manufacturer "Mai Pico", // 2: Product serial_number_str, // 3: Serials, use chip ID - "I/O CONTROL BD;15257;01;90;1831;6679A;00;GOUT=14_ADIN=8,E_ROTIN=4_COININ=2_SWIN=2,E_UQ1=41,6;", + joy_name_string, "Mai Pico NKRO", "Mai Pico Command Line Port", "Mai Pico Touch Port", @@ -206,3 +208,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) return _desc_str; } + +void usb_descriptors_disable_io4() +{ + strcpy(joy_name_string, "Mai Pico Joystick"); +} diff --git a/firmware/src/usb_descriptors.h b/firmware/src/usb_descriptors.h index 756bf2d..848d8b3 100644 --- a/firmware/src/usb_descriptors.h +++ b/firmware/src/usb_descriptors.h @@ -1,151 +1,152 @@ -#ifndef USB_DESCRIPTORS_H_ -#define USB_DESCRIPTORS_H_ - -#include "common/tusb_common.h" -#include "device/usbd.h" - -enum { - REPORT_ID_JOYSTICK = 1, - REPORT_ID_OUTPUT = 16, -}; - -// because they are missing from tusb_hid.h -#define HID_STRING_INDEX(x) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, 1) -#define HID_STRING_INDEX_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, n) -#define HID_STRING_MINIMUM(x) HID_REPORT_ITEM(x, 8, RI_TYPE_LOCAL, 1) -#define HID_STRING_MINIMUM_N(x, n) HID_REPORT_ITEM(x, 8, RI_TYPE_LOCAL, n) -#define HID_STRING_MAXIMUM(x) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, 1) -#define HID_STRING_MAXIMUM_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, n) - -// Joystick Report Descriptor to Emulate IO4 -#define MAIPICO_REPORT_DESC_JOYSTICK \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_JOYSTICK), \ - HID_COLLECTION(HID_COLLECTION_APPLICATION), \ - HID_REPORT_ID(REPORT_ID_JOYSTICK) \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_X), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_Y), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_X), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_Y), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_X), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_Y), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_X), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_Y), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_RX), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_RY), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_RX), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_RY), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_SLIDER), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_SLIDER), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(48), HID_REPORT_SIZE(1), \ - HID_USAGE_MIN_N(1, 2), HID_USAGE_MAX_N(48, 2), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - \ - HID_REPORT_COUNT(1), HID_REPORT_SIZE(232), \ - HID_INPUT(HID_CONSTANT | HID_ABSOLUTE), \ - \ - HID_USAGE_PAGE_N(0xffa0, 2), \ - HID_USAGE(0x00), \ - HID_REPORT_ID(REPORT_ID_OUTPUT) \ - HID_COLLECTION(HID_COLLECTION_APPLICATION), \ - HID_USAGE(0x00), \ - HID_LOGICAL_MIN(0), HID_LOGICAL_MAX(255), \ - HID_REPORT_COUNT(63), HID_REPORT_SIZE(8), \ - HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - HID_COLLECTION_END, \ - HID_COLLECTION_END - -#define MAIPICO_REPORT_DESC_NKRO \ - HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ - HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \ - HID_COLLECTION(HID_COLLECTION_APPLICATION), \ - /* Modifier */ \ - HID_REPORT_SIZE(1), \ - HID_REPORT_COUNT(8), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \ - HID_USAGE_MIN(224), \ - HID_USAGE_MAX(231), \ - HID_LOGICAL_MIN(0), \ - HID_LOGICAL_MAX(1), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - /* LED output that we don't care */ \ - HID_REPORT_COUNT(5), \ - HID_REPORT_SIZE(1), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \ - HID_USAGE_MIN(1), \ - HID_USAGE_MAX(5), \ - HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - HID_REPORT_COUNT(1), \ - HID_REPORT_SIZE(3), \ - HID_OUTPUT(HID_CONSTANT), \ - /* Full Keyboard Bitmap */ \ - HID_REPORT_SIZE(1), \ - HID_REPORT_COUNT(120), \ - HID_LOGICAL_MIN(0), \ - HID_LOGICAL_MAX(1), \ - HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \ - HID_USAGE_MIN(0), \ - HID_USAGE_MAX(119), \ - HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ - HID_COLLECTION_END - -// HID_REPORT_ID(REPORT_ID_NKRO) - -#endif /* USB_DESCRIPTORS_H_ */ +#ifndef USB_DESCRIPTORS_H_ +#define USB_DESCRIPTORS_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" + +enum { + REPORT_ID_JOYSTICK = 1, + REPORT_ID_OUTPUT = 16, +}; + +// because they are missing from tusb_hid.h +#define HID_STRING_INDEX(x) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, 1) +#define HID_STRING_INDEX_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, n) +#define HID_STRING_MINIMUM(x) HID_REPORT_ITEM(x, 8, RI_TYPE_LOCAL, 1) +#define HID_STRING_MINIMUM_N(x, n) HID_REPORT_ITEM(x, 8, RI_TYPE_LOCAL, n) +#define HID_STRING_MAXIMUM(x) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, 1) +#define HID_STRING_MAXIMUM_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, n) + +// Joystick Report Descriptor to Emulate IO4 +#define MAIPICO_REPORT_DESC_JOYSTICK \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_JOYSTICK), \ + HID_COLLECTION(HID_COLLECTION_APPLICATION), \ + HID_REPORT_ID(REPORT_ID_JOYSTICK) \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_X), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_Y), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_X), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_Y), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_X), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_Y), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_X), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_Y), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_RX), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_RY), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_RX), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_RY), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_SLIDER), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_SLIDER), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(48), HID_REPORT_SIZE(1), \ + HID_USAGE_MIN_N(1, 2), HID_USAGE_MAX_N(48, 2), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + \ + HID_REPORT_COUNT(1), HID_REPORT_SIZE(232), \ + HID_INPUT(HID_CONSTANT | HID_ABSOLUTE), \ + \ + HID_USAGE_PAGE_N(0xffa0, 2), \ + HID_USAGE(0x00), \ + HID_REPORT_ID(REPORT_ID_OUTPUT) \ + HID_COLLECTION(HID_COLLECTION_APPLICATION), \ + HID_USAGE(0x00), \ + HID_LOGICAL_MIN(0), HID_LOGICAL_MAX(255), \ + HID_REPORT_COUNT(63), HID_REPORT_SIZE(8), \ + HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + HID_COLLECTION_END, \ + HID_COLLECTION_END + +#define MAIPICO_REPORT_DESC_NKRO \ + HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \ + HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \ + HID_COLLECTION(HID_COLLECTION_APPLICATION), \ + /* Modifier */ \ + HID_REPORT_SIZE(1), \ + HID_REPORT_COUNT(8), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \ + HID_USAGE_MIN(224), \ + HID_USAGE_MAX(231), \ + HID_LOGICAL_MIN(0), \ + HID_LOGICAL_MAX(1), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + /* LED output that we don't care */ \ + HID_REPORT_COUNT(5), \ + HID_REPORT_SIZE(1), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \ + HID_USAGE_MIN(1), \ + HID_USAGE_MAX(5), \ + HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + HID_REPORT_COUNT(1), \ + HID_REPORT_SIZE(3), \ + HID_OUTPUT(HID_CONSTANT), \ + /* Full Keyboard Bitmap */ \ + HID_REPORT_SIZE(1), \ + HID_REPORT_COUNT(120), \ + HID_LOGICAL_MIN(0), \ + HID_LOGICAL_MAX(1), \ + HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \ + HID_USAGE_MIN(0), \ + HID_USAGE_MAX(119), \ + HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ + HID_COLLECTION_END + +// HID_REPORT_ID(REPORT_ID_NKRO) + +void usb_descriptors_disable_io4(); +#endif /* USB_DESCRIPTORS_H_ */