qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

usb_descriptor.c (51878B)


      1 /*
      2  * Copyright 2012 Jun Wako <wakojun@gmail.com>
      3  * This file is based on:
      4  *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
      5  *     LUFA-120219/Demos/Device/Lowlevel/GenericHID
      6  */
      7 
      8 /*
      9                          LUFA Library
     10          Copyright (C) Dean Camera, 2012.
     11 
     12     dean [at] fourwalledcubicle [dot] com
     13                      www.lufa-lib.org
     14 */
     15 
     16 /*
     17     Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)
     18     Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
     19 
     20     Permission to use, copy, modify, distribute, and sell this
     21     software and its documentation for any purpose is hereby granted
     22     without fee, provided that the above copyright notice appear in
     23     all copies and that both that the copyright notice and this
     24     permission notice and warranty disclaimer appear in supporting
     25     documentation, and that the name of the author not be used in
     26     advertising or publicity pertaining to distribution of the
     27     software without specific, written prior permission.
     28 
     29     The author disclaim all warranties with regard to this
     30     software, including all implied warranties of merchantability
     31     and fitness.  In no event shall the author be liable for any
     32     special, indirect or consequential damages or any damages
     33     whatsoever resulting from loss of use, data or profits, whether
     34     in an action of contract, negligence or other tortious action,
     35     arising out of or in connection with the use or performance of
     36     this software.
     37 */
     38 
     39 #include "util.h"
     40 #include "report.h"
     41 #include "usb_descriptor.h"
     42 #include "usb_descriptor_common.h"
     43 
     44 #ifdef JOYSTICK_ENABLE
     45 #    include "joystick.h"
     46 #endif
     47 
     48 #ifdef OS_DETECTION_ENABLE
     49 #    include "os_detection.h"
     50 #endif
     51 
     52 #if defined(SERIAL_NUMBER) || (defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE)
     53 
     54 #    define HAS_SERIAL_NUMBER
     55 
     56 #    if defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE
     57 #        include "hardware_id.h"
     58 #    endif
     59 
     60 #endif // defined(SERIAL_NUMBER) || (defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE)
     61 
     62 // clang-format off
     63 
     64 /*
     65  * HID report descriptors
     66  */
     67 #ifdef KEYBOARD_SHARED_EP
     68 const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
     69 #    define SHARED_REPORT_STARTED
     70 #else
     71 const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = {
     72 #endif
     73     HID_RI_USAGE_PAGE(8, 0x01),        // Generic Desktop
     74     HID_RI_USAGE(8, 0x06),             // Keyboard
     75     HID_RI_COLLECTION(8, 0x01),        // Application
     76 #ifdef KEYBOARD_SHARED_EP
     77         HID_RI_REPORT_ID(8, REPORT_ID_KEYBOARD),
     78 #endif
     79         // Modifiers (8 bits)
     80         HID_RI_USAGE_PAGE(8, 0x07),    // Keyboard/Keypad
     81         HID_RI_USAGE_MINIMUM(8, 0xE0), // Keyboard Left Control
     82         HID_RI_USAGE_MAXIMUM(8, 0xE7), // Keyboard Right GUI
     83         HID_RI_LOGICAL_MINIMUM(8, 0x00),
     84         HID_RI_LOGICAL_MAXIMUM(8, 0x01),
     85         HID_RI_REPORT_COUNT(8, 0x08),
     86         HID_RI_REPORT_SIZE(8, 0x01),
     87         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
     88         // Reserved (1 byte)
     89         HID_RI_REPORT_COUNT(8, 0x01),
     90         HID_RI_REPORT_SIZE(8, 0x08),
     91         HID_RI_INPUT(8, HID_IOF_CONSTANT),
     92         // Keycodes (6 bytes)
     93         HID_RI_USAGE_PAGE(8, 0x07),    // Keyboard/Keypad
     94         HID_RI_USAGE_MINIMUM(8, 0x00),
     95         HID_RI_USAGE_MAXIMUM(8, 0xFF),
     96         HID_RI_LOGICAL_MINIMUM(8, 0x00),
     97         HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
     98         HID_RI_REPORT_COUNT(8, 0x06),
     99         HID_RI_REPORT_SIZE(8, 0x08),
    100         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
    101 
    102         // Status LEDs (5 bits)
    103         HID_RI_USAGE_PAGE(8, 0x08),    // LED
    104         HID_RI_USAGE_MINIMUM(8, 0x01), // Num Lock
    105         HID_RI_USAGE_MAXIMUM(8, 0x05), // Kana
    106         HID_RI_LOGICAL_MINIMUM(8, 0x00),
    107         HID_RI_LOGICAL_MAXIMUM(8, 0x01),
    108         HID_RI_REPORT_COUNT(8, 0x05),
    109         HID_RI_REPORT_SIZE(8, 0x01),
    110         HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
    111         // LED padding (3 bits)
    112         HID_RI_REPORT_COUNT(8, 0x01),
    113         HID_RI_REPORT_SIZE(8, 0x03),
    114         HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
    115     HID_RI_END_COLLECTION(0),
    116 #ifndef KEYBOARD_SHARED_EP
    117 };
    118 #endif
    119 
    120 #ifdef MOUSE_ENABLE
    121 #    ifndef MOUSE_SHARED_EP
    122 const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = {
    123 #    elif !defined(SHARED_REPORT_STARTED)
    124 const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
    125 #        define SHARED_REPORT_STARTED
    126 #    endif
    127     HID_RI_USAGE_PAGE(8, 0x01),            // Generic Desktop
    128     HID_RI_USAGE(8, 0x02),                 // Mouse
    129     HID_RI_COLLECTION(8, 0x01),            // Application
    130 #    ifdef MOUSE_SHARED_EP
    131         HID_RI_REPORT_ID(8, REPORT_ID_MOUSE),
    132 #    endif
    133         HID_RI_USAGE(8, 0x01),             // Pointer
    134         HID_RI_COLLECTION(8, 0x00),        // Physical
    135             // Buttons (8 bits)
    136             HID_RI_USAGE_PAGE(8, 0x09),    // Button
    137             HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1
    138             HID_RI_USAGE_MAXIMUM(8, 0x08), // Button 8
    139             HID_RI_LOGICAL_MINIMUM(8, 0x00),
    140             HID_RI_LOGICAL_MAXIMUM(8, 0x01),
    141             HID_RI_REPORT_COUNT(8, 0x08),
    142             HID_RI_REPORT_SIZE(8, 0x01),
    143             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    144 
    145 #    ifdef MOUSE_EXTENDED_REPORT
    146             // Boot protocol XY ignored in Report protocol
    147             HID_RI_REPORT_COUNT(8, 0x02),
    148             HID_RI_REPORT_SIZE(8, 0x08),
    149             HID_RI_INPUT(8, HID_IOF_CONSTANT),
    150 #    endif
    151             // X/Y position (2 or 4 bytes)
    152             HID_RI_USAGE_PAGE(8, 0x01),    // Generic Desktop
    153             HID_RI_USAGE(8, 0x30),         // X
    154             HID_RI_USAGE(8, 0x31),         // Y
    155 #    ifndef MOUSE_EXTENDED_REPORT
    156             HID_RI_LOGICAL_MINIMUM(8, -127),
    157             HID_RI_LOGICAL_MAXIMUM(8, 127),
    158             HID_RI_REPORT_COUNT(8, 0x02),
    159             HID_RI_REPORT_SIZE(8, 0x08),
    160 #    else
    161             HID_RI_LOGICAL_MINIMUM(16, -32767),
    162             HID_RI_LOGICAL_MAXIMUM(16,  32767),
    163             HID_RI_REPORT_COUNT(8, 0x02),
    164             HID_RI_REPORT_SIZE(8, 0x10),
    165 #    endif
    166             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
    167 
    168 #    ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
    169             HID_RI_COLLECTION(8, 0x02),
    170             // Feature report and padding (1 byte)
    171             HID_RI_USAGE(8, 0x48),     // Resolution Multiplier
    172             HID_RI_REPORT_COUNT(8, 0x01),
    173             HID_RI_REPORT_SIZE(8, 0x02),
    174             HID_RI_LOGICAL_MINIMUM(8, 0x00),
    175             HID_RI_LOGICAL_MAXIMUM(8, 0x01),
    176             HID_RI_PHYSICAL_MINIMUM(8, 1),
    177             HID_RI_PHYSICAL_MAXIMUM(8, POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER),
    178             HID_RI_UNIT_EXPONENT(8, POINTING_DEVICE_HIRES_SCROLL_EXPONENT),
    179             HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    180             HID_RI_PHYSICAL_MINIMUM(8, 0x00),
    181             HID_RI_PHYSICAL_MAXIMUM(8, 0x00),
    182             HID_RI_REPORT_SIZE(8, 0x06),
    183             HID_RI_FEATURE(8, HID_IOF_CONSTANT),
    184 #    endif
    185 
    186             // Vertical wheel (1 or 2 bytes)
    187             HID_RI_USAGE(8, 0x38),     // Wheel
    188 #    ifndef WHEEL_EXTENDED_REPORT
    189             HID_RI_LOGICAL_MINIMUM(8, -127),
    190             HID_RI_LOGICAL_MAXIMUM(8, 127),
    191             HID_RI_REPORT_COUNT(8, 0x01),
    192             HID_RI_REPORT_SIZE(8, 0x08),
    193 #    else
    194             HID_RI_LOGICAL_MINIMUM(16, -32767),
    195             HID_RI_LOGICAL_MAXIMUM(16,  32767),
    196             HID_RI_REPORT_COUNT(8, 0x01),
    197             HID_RI_REPORT_SIZE(8, 0x10),
    198 #    endif
    199             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
    200 
    201             // Horizontal wheel (1 or 2 bytes)
    202             HID_RI_USAGE_PAGE(8, 0x0C),// Consumer
    203             HID_RI_USAGE(16, 0x0238),  // AC Pan
    204 #    ifndef WHEEL_EXTENDED_REPORT
    205             HID_RI_LOGICAL_MINIMUM(8, -127),
    206             HID_RI_LOGICAL_MAXIMUM(8, 127),
    207             HID_RI_REPORT_COUNT(8, 0x01),
    208             HID_RI_REPORT_SIZE(8, 0x08),
    209 #    else
    210             HID_RI_LOGICAL_MINIMUM(16, -32767),
    211             HID_RI_LOGICAL_MAXIMUM(16,  32767),
    212             HID_RI_REPORT_COUNT(8, 0x01),
    213             HID_RI_REPORT_SIZE(8, 0x10),
    214 #    endif
    215             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
    216 
    217 #    ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE
    218             HID_RI_END_COLLECTION(0),
    219 #    endif
    220 
    221         HID_RI_END_COLLECTION(0),
    222     HID_RI_END_COLLECTION(0),
    223 #    ifndef MOUSE_SHARED_EP
    224 };
    225 #    endif
    226 #endif
    227 
    228 #ifdef JOYSTICK_ENABLE
    229 #    ifndef JOYSTICK_SHARED_EP
    230 const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = {
    231 #    elif !defined(SHARED_REPORT_STARTED)
    232 const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
    233 #        define SHARED_REPORT_STARTED
    234 #    endif
    235     HID_RI_USAGE_PAGE(8, 0x01),     // Generic Desktop
    236     HID_RI_USAGE(8, 0x04),          // Joystick
    237     HID_RI_COLLECTION(8, 0x01),     // Application
    238 #    ifdef JOYSTICK_SHARED_EP
    239         HID_RI_REPORT_ID(8, REPORT_ID_JOYSTICK),
    240 #    endif
    241         HID_RI_COLLECTION(8, 0x00), // Physical
    242 #    if JOYSTICK_AXIS_COUNT > 0
    243             HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
    244             HID_RI_USAGE(8, 0x30),      // X
    245 #        if JOYSTICK_AXIS_COUNT > 1
    246             HID_RI_USAGE(8, 0x31),      // Y
    247 #        endif
    248 #        if JOYSTICK_AXIS_COUNT > 2
    249             HID_RI_USAGE(8, 0x32),      // Z
    250 #        endif
    251 #        if JOYSTICK_AXIS_COUNT > 3
    252             HID_RI_USAGE(8, 0x33),      // Rx
    253 #        endif
    254 #        if JOYSTICK_AXIS_COUNT > 4
    255             HID_RI_USAGE(8, 0x34),      // Ry
    256 #        endif
    257 #        if JOYSTICK_AXIS_COUNT > 5
    258             HID_RI_USAGE(8, 0x35),      // Rz
    259 #        endif
    260 #        if JOYSTICK_AXIS_RESOLUTION == 8
    261             HID_RI_LOGICAL_MINIMUM(8, -JOYSTICK_MAX_VALUE),
    262             HID_RI_LOGICAL_MAXIMUM(8, JOYSTICK_MAX_VALUE),
    263             HID_RI_REPORT_COUNT(8, JOYSTICK_AXIS_COUNT),
    264             HID_RI_REPORT_SIZE(8, 0x08),
    265 #        else
    266             HID_RI_LOGICAL_MINIMUM(16, -JOYSTICK_MAX_VALUE),
    267             HID_RI_LOGICAL_MAXIMUM(16, JOYSTICK_MAX_VALUE),
    268             HID_RI_REPORT_COUNT(8, JOYSTICK_AXIS_COUNT),
    269             HID_RI_REPORT_SIZE(8, 0x10),
    270 #        endif
    271             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    272 #    endif
    273 
    274 #    ifdef JOYSTICK_HAS_HAT
    275             // Hat Switch (4 bits)
    276             HID_RI_USAGE(8, 0x39), // Hat Switch
    277             HID_RI_LOGICAL_MINIMUM(8, 0x00),
    278             HID_RI_LOGICAL_MAXIMUM(8, 0x07),
    279             HID_RI_PHYSICAL_MINIMUM(8, 0),
    280             HID_RI_PHYSICAL_MAXIMUM(16, 315),
    281             HID_RI_UNIT(8, 0x14),  // Degree, English Rotation
    282             HID_RI_REPORT_COUNT(8, 1),
    283             HID_RI_REPORT_SIZE(8, 4),
    284             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NULLSTATE),
    285             // Padding (4 bits)
    286             HID_RI_REPORT_COUNT(8, 0x04),
    287             HID_RI_REPORT_SIZE(8, 0x01),
    288             HID_RI_INPUT(8, HID_IOF_CONSTANT),
    289 #    endif
    290 
    291 #    if JOYSTICK_BUTTON_COUNT > 0
    292             HID_RI_USAGE_PAGE(8, 0x09), // Button
    293             HID_RI_USAGE_MINIMUM(8, 0x01),
    294             HID_RI_USAGE_MAXIMUM(8, JOYSTICK_BUTTON_COUNT),
    295             HID_RI_LOGICAL_MINIMUM(8, 0x00),
    296             HID_RI_LOGICAL_MAXIMUM(8, 0x01),
    297             HID_RI_REPORT_COUNT(8, JOYSTICK_BUTTON_COUNT),
    298             HID_RI_REPORT_SIZE(8, 0x01),
    299             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    300 
    301 #        if (JOYSTICK_BUTTON_COUNT % 8) != 0
    302             HID_RI_REPORT_COUNT(8, 8 - (JOYSTICK_BUTTON_COUNT % 8)),
    303             HID_RI_REPORT_SIZE(8, 0x01),
    304             HID_RI_INPUT(8, HID_IOF_CONSTANT),
    305 #        endif
    306 #    endif
    307         HID_RI_END_COLLECTION(0),
    308     HID_RI_END_COLLECTION(0),
    309 #    ifndef JOYSTICK_SHARED_EP
    310 };
    311 #    endif
    312 #endif
    313 
    314 #ifdef DIGITIZER_ENABLE
    315 #    ifndef DIGITIZER_SHARED_EP
    316 const USB_Descriptor_HIDReport_Datatype_t PROGMEM DigitizerReport[] = {
    317 #    elif !defined(SHARED_REPORT_STARTED)
    318 const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
    319 #        define SHARED_REPORT_STARTED
    320 #    endif
    321     HID_RI_USAGE_PAGE(8, 0x0D),            // Digitizers
    322     HID_RI_USAGE(8, 0x01),                 // Digitizer
    323     HID_RI_COLLECTION(8, 0x01),            // Application
    324 #    ifdef DIGITIZER_SHARED_EP
    325         HID_RI_REPORT_ID(8, REPORT_ID_DIGITIZER),
    326 #    endif
    327         HID_RI_USAGE(8, 0x20),             // Stylus
    328         HID_RI_COLLECTION(8, 0x00),        // Physical
    329             // In Range, Tip Switch & Barrel Switch (3 bits)
    330             HID_RI_USAGE(8, 0x32),         // In Range
    331             HID_RI_USAGE(8, 0x42),         // Tip Switch
    332             HID_RI_USAGE(8, 0x44),         // Barrel Switch
    333             HID_RI_LOGICAL_MINIMUM(8, 0x00),
    334             HID_RI_LOGICAL_MAXIMUM(8, 0x01),
    335             HID_RI_REPORT_COUNT(8, 0x03),
    336             HID_RI_REPORT_SIZE(8, 0x01),
    337             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    338             // Padding (5 bits)
    339             HID_RI_REPORT_COUNT(8, 0x05),
    340             HID_RI_INPUT(8, HID_IOF_CONSTANT),
    341 
    342             // X/Y Position (4 bytes)
    343             HID_RI_USAGE_PAGE(8, 0x01),    // Generic Desktop
    344             HID_RI_USAGE(8, 0x30),         // X
    345             HID_RI_USAGE(8, 0x31),         // Y
    346             HID_RI_LOGICAL_MAXIMUM(16, 0x7FFF),
    347             HID_RI_REPORT_COUNT(8, 0x02),
    348             HID_RI_REPORT_SIZE(8, 0x10),
    349             HID_RI_UNIT(8, 0x13),          // Inch, English Linear
    350             HID_RI_UNIT_EXPONENT(8, 0x0E), // -2
    351             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    352         HID_RI_END_COLLECTION(0),
    353     HID_RI_END_COLLECTION(0),
    354 #    ifndef DIGITIZER_SHARED_EP
    355 };
    356 #    endif
    357 #endif
    358 
    359 #if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED)
    360 const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
    361 #endif
    362 
    363 #ifdef EXTRAKEY_ENABLE
    364     HID_RI_USAGE_PAGE(8, 0x01),           // Generic Desktop
    365     HID_RI_USAGE(8, 0x80),                // System Control
    366     HID_RI_COLLECTION(8, 0x01),           // Application
    367         HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM),
    368         HID_RI_USAGE_MINIMUM(8, 0x01),    // Pointer
    369         HID_RI_USAGE_MAXIMUM(16, 0x00B7), // System Display LCD Autoscale
    370         HID_RI_LOGICAL_MINIMUM(8, 0x01),
    371         HID_RI_LOGICAL_MAXIMUM(16, 0x00B7),
    372         HID_RI_REPORT_COUNT(8, 1),
    373         HID_RI_REPORT_SIZE(8, 16),
    374         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
    375     HID_RI_END_COLLECTION(0),
    376 
    377     HID_RI_USAGE_PAGE(8, 0x0C),           // Consumer
    378     HID_RI_USAGE(8, 0x01),                // Consumer Control
    379     HID_RI_COLLECTION(8, 0x01),           // Application
    380         HID_RI_REPORT_ID(8, REPORT_ID_CONSUMER),
    381         HID_RI_USAGE_MINIMUM(8, 0x01),    // Consumer Control
    382         HID_RI_USAGE_MAXIMUM(16, 0x02A0), // AC Desktop Show All Applications
    383         HID_RI_LOGICAL_MINIMUM(8, 0x01),
    384         HID_RI_LOGICAL_MAXIMUM(16, 0x02A0),
    385         HID_RI_REPORT_COUNT(8, 1),
    386         HID_RI_REPORT_SIZE(8, 16),
    387         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
    388     HID_RI_END_COLLECTION(0),
    389 #endif
    390 
    391 #ifdef PROGRAMMABLE_BUTTON_ENABLE
    392     HID_RI_USAGE_PAGE(8, 0x0C),            // Consumer
    393     HID_RI_USAGE(8, 0x01),                 // Consumer Control
    394     HID_RI_COLLECTION(8, 0x01),            // Application
    395         HID_RI_REPORT_ID(8, REPORT_ID_PROGRAMMABLE_BUTTON),
    396         HID_RI_USAGE(8, 0x03),             // Programmable Buttons
    397         HID_RI_COLLECTION(8, 0x04),        // Named Array
    398             HID_RI_USAGE_PAGE(8, 0x09),    // Button
    399             HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1
    400             HID_RI_USAGE_MAXIMUM(8, 0x20), // Button 32
    401             HID_RI_LOGICAL_MINIMUM(8, 0x00),
    402             HID_RI_LOGICAL_MAXIMUM(8, 0x01),
    403             HID_RI_REPORT_COUNT(8, 32),
    404             HID_RI_REPORT_SIZE(8, 1),
    405             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    406         HID_RI_END_COLLECTION(0),
    407     HID_RI_END_COLLECTION(0),
    408 #endif
    409 
    410 #ifdef NKRO_ENABLE
    411     HID_RI_USAGE_PAGE(8, 0x01),        // Generic Desktop
    412     HID_RI_USAGE(8, 0x06),             // Keyboard
    413     HID_RI_COLLECTION(8, 0x01),        // Application
    414         HID_RI_REPORT_ID(8, REPORT_ID_NKRO),
    415         // Modifiers (8 bits)
    416         HID_RI_USAGE_PAGE(8, 0x07),    // Keyboard/Keypad
    417         HID_RI_USAGE_MINIMUM(8, 0xE0), // Keyboard Left Control
    418         HID_RI_USAGE_MAXIMUM(8, 0xE7), // Keyboard Right GUI
    419         HID_RI_LOGICAL_MINIMUM(8, 0x00),
    420         HID_RI_LOGICAL_MAXIMUM(8, 0x01),
    421         HID_RI_REPORT_COUNT(8, 0x08),
    422         HID_RI_REPORT_SIZE(8, 0x01),
    423         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    424         // Keycodes
    425         HID_RI_USAGE_PAGE(8, 0x07),    // Keyboard/Keypad
    426         HID_RI_USAGE_MINIMUM(8, 0x00),
    427         HID_RI_USAGE_MAXIMUM(8, NKRO_REPORT_BITS * 8 - 1),
    428         HID_RI_LOGICAL_MINIMUM(8, 0x00),
    429         HID_RI_LOGICAL_MAXIMUM(8, 0x01),
    430         HID_RI_REPORT_COUNT(8, NKRO_REPORT_BITS * 8),
    431         HID_RI_REPORT_SIZE(8, 0x01),
    432         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    433 
    434         // Status LEDs (5 bits)
    435         HID_RI_USAGE_PAGE(8, 0x08),    // LED
    436         HID_RI_USAGE_MINIMUM(8, 0x01), // Num Lock
    437         HID_RI_USAGE_MAXIMUM(8, 0x05), // Kana
    438         HID_RI_REPORT_COUNT(8, 0x05),
    439         HID_RI_REPORT_SIZE(8, 0x01),
    440         HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
    441         // LED padding (3 bits)
    442         HID_RI_REPORT_COUNT(8, 0x01),
    443         HID_RI_REPORT_SIZE(8, 0x03),
    444         HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
    445     HID_RI_END_COLLECTION(0),
    446 #endif
    447 
    448 #ifdef SHARED_EP_ENABLE
    449 };
    450 #endif
    451 
    452 #ifdef RAW_ENABLE
    453 const USB_Descriptor_HIDReport_Datatype_t PROGMEM RawReport[] = {
    454     HID_RI_USAGE_PAGE(16, RAW_USAGE_PAGE), // Vendor Defined
    455     HID_RI_USAGE(8, RAW_USAGE_ID),         // Vendor Defined
    456     HID_RI_COLLECTION(8, 0x01),    // Application
    457         // Data to host
    458         HID_RI_USAGE(8, 0x62),     // Vendor Defined
    459         HID_RI_LOGICAL_MINIMUM(8, 0x00),
    460         HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
    461         HID_RI_REPORT_COUNT(8, RAW_EPSIZE),
    462         HID_RI_REPORT_SIZE(8, 0x08),
    463         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    464 
    465         // Data from host
    466         HID_RI_USAGE(8, 0x63),     // Vendor Defined
    467         HID_RI_LOGICAL_MINIMUM(8, 0x00),
    468         HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
    469         HID_RI_REPORT_COUNT(8, RAW_EPSIZE),
    470         HID_RI_REPORT_SIZE(8, 0x08),
    471         HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
    472     HID_RI_END_COLLECTION(0),
    473 };
    474 #endif
    475 
    476 #ifdef CONSOLE_ENABLE
    477 const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = {
    478     HID_RI_USAGE_PAGE(16, 0xFF31), // Vendor Defined (PJRC Teensy compatible)
    479     HID_RI_USAGE(8, 0x74),         // Vendor Defined (PJRC Teensy compatible)
    480     HID_RI_COLLECTION(8, 0x01),    // Application
    481         // Data to host
    482         HID_RI_USAGE(8, 0x75),     // Vendor Defined
    483         HID_RI_LOGICAL_MINIMUM(8, 0x00),
    484         HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
    485         HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE),
    486         HID_RI_REPORT_SIZE(8, 0x08),
    487         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
    488     HID_RI_END_COLLECTION(0),
    489 };
    490 #endif
    491 
    492 /*
    493  * Device descriptor
    494  */
    495 const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {
    496     .Header = {
    497         .Size                   = sizeof(USB_Descriptor_Device_t),
    498         .Type                   = DTYPE_Device
    499     },
    500     .USBSpecification           = VERSION_BCD(2, 0, 0),
    501 
    502 #if VIRTSER_ENABLE
    503     .Class                      = USB_CSCP_IADDeviceClass,
    504     .SubClass                   = USB_CSCP_IADDeviceSubclass,
    505     .Protocol                   = USB_CSCP_IADDeviceProtocol,
    506 #else
    507     .Class                      = USB_CSCP_NoDeviceClass,
    508     .SubClass                   = USB_CSCP_NoDeviceSubclass,
    509     .Protocol                   = USB_CSCP_NoDeviceProtocol,
    510 #endif
    511 
    512     .Endpoint0Size              = FIXED_CONTROL_ENDPOINT_SIZE,
    513     // Specified in config.h
    514     .VendorID                   = VENDOR_ID,
    515     .ProductID                  = PRODUCT_ID,
    516     .ReleaseNumber              = DEVICE_VER,
    517     .ManufacturerStrIndex       = 0x01,
    518     .ProductStrIndex            = 0x02,
    519 #ifdef HAS_SERIAL_NUMBER
    520     .SerialNumStrIndex          = 0x03,
    521 #else // HAS_SERIAL_NUMBER
    522     .SerialNumStrIndex          = 0x00,
    523 #endif // HAS_SERIAL_NUMBER
    524     .NumberOfConfigurations     = FIXED_NUM_CONFIGURATIONS
    525 };
    526 
    527 #ifndef USB_MAX_POWER_CONSUMPTION
    528 #    define USB_MAX_POWER_CONSUMPTION 500
    529 #endif
    530 
    531 #ifndef USB_POLLING_INTERVAL_MS
    532 #    define USB_POLLING_INTERVAL_MS 1
    533 #endif
    534 
    535 /*
    536  * Configuration descriptors
    537  */
    538 const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
    539     .Config = {
    540         .Header = {
    541             .Size               = sizeof(USB_Descriptor_Configuration_Header_t),
    542             .Type               = DTYPE_Configuration
    543         },
    544         .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
    545         .TotalInterfaces        = TOTAL_INTERFACES,
    546         .ConfigurationNumber    = 1,
    547         .ConfigurationStrIndex  = NO_DESCRIPTOR,
    548         .ConfigAttributes       = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
    549         .MaxPowerConsumption    = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION)
    550     },
    551 #ifndef KEYBOARD_SHARED_EP
    552     /*
    553      * Keyboard
    554      */
    555     .Keyboard_Interface = {
    556         .Header = {
    557             .Size               = sizeof(USB_Descriptor_Interface_t),
    558             .Type               = DTYPE_Interface
    559         },
    560         .InterfaceNumber        = KEYBOARD_INTERFACE,
    561         .AlternateSetting       = 0x00,
    562         .TotalEndpoints         = 1,
    563         .Class                  = HID_CSCP_HIDClass,
    564         .SubClass               = HID_CSCP_BootSubclass,
    565         .Protocol               = HID_CSCP_KeyboardBootProtocol,
    566         .InterfaceStrIndex      = NO_DESCRIPTOR
    567     },
    568     .Keyboard_HID = {
    569         .Header = {
    570             .Size               = sizeof(USB_HID_Descriptor_HID_t),
    571             .Type               = HID_DTYPE_HID
    572         },
    573         .HIDSpec                = VERSION_BCD(1, 1, 1),
    574         .CountryCode            = 0x00,
    575         .TotalReportDescriptors = 1,
    576         .HIDReportType          = HID_DTYPE_Report,
    577         .HIDReportLength        = sizeof(KeyboardReport)
    578     },
    579     .Keyboard_INEndpoint = {
    580         .Header = {
    581             .Size               = sizeof(USB_Descriptor_Endpoint_t),
    582             .Type               = DTYPE_Endpoint
    583         },
    584         .EndpointAddress        = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM),
    585         .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
    586         .EndpointSize           = KEYBOARD_EPSIZE,
    587         .PollingIntervalMS      = USB_POLLING_INTERVAL_MS
    588     },
    589 #endif
    590 
    591 #ifdef RAW_ENABLE
    592     /*
    593      * Raw HID
    594      */
    595     .Raw_Interface = {
    596         .Header = {
    597             .Size               = sizeof(USB_Descriptor_Interface_t),
    598             .Type               = DTYPE_Interface
    599         },
    600         .InterfaceNumber        = RAW_INTERFACE,
    601         .AlternateSetting       = 0x00,
    602         .TotalEndpoints         = 2,
    603         .Class                  = HID_CSCP_HIDClass,
    604         .SubClass               = HID_CSCP_NonBootSubclass,
    605         .Protocol               = HID_CSCP_NonBootProtocol,
    606         .InterfaceStrIndex      = NO_DESCRIPTOR
    607     },
    608     .Raw_HID = {
    609         .Header = {
    610             .Size               = sizeof(USB_HID_Descriptor_HID_t),
    611             .Type               = HID_DTYPE_HID
    612         },
    613         .HIDSpec                = VERSION_BCD(1, 1, 1),
    614         .CountryCode            = 0x00,
    615         .TotalReportDescriptors = 1,
    616         .HIDReportType          = HID_DTYPE_Report,
    617         .HIDReportLength        = sizeof(RawReport)
    618     },
    619     .Raw_INEndpoint = {
    620         .Header = {
    621             .Size               = sizeof(USB_Descriptor_Endpoint_t),
    622             .Type               = DTYPE_Endpoint
    623         },
    624         .EndpointAddress        = (ENDPOINT_DIR_IN | RAW_IN_EPNUM),
    625         .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
    626         .EndpointSize           = RAW_EPSIZE,
    627         .PollingIntervalMS      = 0x01
    628     },
    629     .Raw_OUTEndpoint = {
    630         .Header = {
    631             .Size               = sizeof(USB_Descriptor_Endpoint_t),
    632             .Type               = DTYPE_Endpoint
    633         },
    634         .EndpointAddress        = (ENDPOINT_DIR_OUT | RAW_OUT_EPNUM),
    635         .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
    636         .EndpointSize           = RAW_EPSIZE,
    637         .PollingIntervalMS      = 0x01
    638     },
    639 #endif
    640 
    641 #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
    642     /*
    643      * Mouse
    644      */
    645     .Mouse_Interface  = {
    646         .Header = {
    647             .Size               = sizeof(USB_Descriptor_Interface_t),
    648             .Type               = DTYPE_Interface
    649         },
    650         .InterfaceNumber        = MOUSE_INTERFACE,
    651         .AlternateSetting       = 0x00,
    652         .TotalEndpoints         = 1,
    653         .Class                  = HID_CSCP_HIDClass,
    654         .SubClass               = HID_CSCP_BootSubclass,
    655         .Protocol               = HID_CSCP_MouseBootProtocol,
    656         .InterfaceStrIndex      = NO_DESCRIPTOR
    657     },
    658     .Mouse_HID = {
    659         .Header = {
    660             .Size               = sizeof(USB_HID_Descriptor_HID_t),
    661             .Type               = HID_DTYPE_HID
    662         },
    663         .HIDSpec                = VERSION_BCD(1, 1, 1),
    664         .CountryCode            = 0x00,
    665         .TotalReportDescriptors = 1,
    666         .HIDReportType          = HID_DTYPE_Report,
    667         .HIDReportLength        = sizeof(MouseReport)
    668     },
    669     .Mouse_INEndpoint = {
    670         .Header = {
    671             .Size               = sizeof(USB_Descriptor_Endpoint_t),
    672             .Type               = DTYPE_Endpoint
    673         },
    674         .EndpointAddress        = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM),
    675         .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
    676         .EndpointSize           = MOUSE_EPSIZE,
    677         .PollingIntervalMS      = USB_POLLING_INTERVAL_MS
    678     },
    679 #endif
    680 
    681 #ifdef SHARED_EP_ENABLE
    682     /*
    683      * Shared
    684      */
    685     .Shared_Interface = {
    686         .Header = {
    687             .Size               = sizeof(USB_Descriptor_Interface_t),
    688             .Type               = DTYPE_Interface
    689         },
    690         .InterfaceNumber        = SHARED_INTERFACE,
    691         .AlternateSetting       = 0x00,
    692         .TotalEndpoints         = 1,
    693         .Class                  = HID_CSCP_HIDClass,
    694 #    ifdef KEYBOARD_SHARED_EP
    695         .SubClass               = HID_CSCP_BootSubclass,
    696         .Protocol               = HID_CSCP_KeyboardBootProtocol,
    697 #    else
    698         .SubClass               = HID_CSCP_NonBootSubclass,
    699         .Protocol               = HID_CSCP_NonBootProtocol,
    700 #    endif
    701         .InterfaceStrIndex      = NO_DESCRIPTOR
    702     },
    703     .Shared_HID = {
    704         .Header = {
    705             .Size               = sizeof(USB_HID_Descriptor_HID_t),
    706             .Type               = HID_DTYPE_HID
    707         },
    708         .HIDSpec                = VERSION_BCD(1, 1, 1),
    709         .CountryCode            = 0x00,
    710         .TotalReportDescriptors = 1,
    711         .HIDReportType          = HID_DTYPE_Report,
    712         .HIDReportLength        = sizeof(SharedReport)
    713     },
    714     .Shared_INEndpoint = {
    715         .Header = {
    716             .Size               = sizeof(USB_Descriptor_Endpoint_t),
    717             .Type               = DTYPE_Endpoint
    718         },
    719         .EndpointAddress        = (ENDPOINT_DIR_IN | SHARED_IN_EPNUM),
    720         .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
    721         .EndpointSize           = SHARED_EPSIZE,
    722         .PollingIntervalMS      = USB_POLLING_INTERVAL_MS
    723     },
    724 #endif
    725 
    726 #ifdef CONSOLE_ENABLE
    727     /*
    728      * Console
    729      */
    730     .Console_Interface = {
    731         .Header = {
    732             .Size               = sizeof(USB_Descriptor_Interface_t),
    733             .Type               = DTYPE_Interface
    734         },
    735         .InterfaceNumber        = CONSOLE_INTERFACE,
    736         .AlternateSetting       = 0x00,
    737         .TotalEndpoints         = 1,
    738         .Class                  = HID_CSCP_HIDClass,
    739         .SubClass               = HID_CSCP_NonBootSubclass,
    740         .Protocol               = HID_CSCP_NonBootProtocol,
    741         .InterfaceStrIndex      = NO_DESCRIPTOR
    742     },
    743     .Console_HID = {
    744         .Header = {
    745             .Size               = sizeof(USB_HID_Descriptor_HID_t),
    746             .Type               = HID_DTYPE_HID
    747         },
    748         .HIDSpec                = VERSION_BCD(1, 1, 1),
    749         .CountryCode            = 0x00,
    750         .TotalReportDescriptors = 1,
    751         .HIDReportType          = HID_DTYPE_Report,
    752         .HIDReportLength        = sizeof(ConsoleReport)
    753     },
    754     .Console_INEndpoint = {
    755         .Header = {
    756             .Size               = sizeof(USB_Descriptor_Endpoint_t),
    757             .Type               = DTYPE_Endpoint
    758         },
    759         .EndpointAddress        = (ENDPOINT_DIR_IN | CONSOLE_IN_EPNUM),
    760         .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
    761         .EndpointSize           = CONSOLE_EPSIZE,
    762         .PollingIntervalMS      = 0x01
    763     },
    764 #endif
    765 
    766 #ifdef MIDI_ENABLE
    767     /*
    768      * MIDI
    769      */
    770     .Audio_Interface_Association = {
    771         .Header = {
    772             .Size               = sizeof(USB_Descriptor_Interface_Association_t),
    773             .Type               = DTYPE_InterfaceAssociation
    774         },
    775         .FirstInterfaceIndex    = AC_INTERFACE,
    776         .TotalInterfaces        = 2,
    777         .Class                  = AUDIO_CSCP_AudioClass,
    778         .SubClass               = AUDIO_CSCP_ControlSubclass,
    779         .Protocol               = AUDIO_CSCP_ControlProtocol,
    780         .IADStrIndex            = NO_DESCRIPTOR,
    781     },
    782     .Audio_ControlInterface = {
    783         .Header = {
    784             .Size               = sizeof(USB_Descriptor_Interface_t),
    785             .Type               = DTYPE_Interface
    786         },
    787         .InterfaceNumber        = AC_INTERFACE,
    788         .AlternateSetting       = 0,
    789         .TotalEndpoints         = 0,
    790         .Class                  = AUDIO_CSCP_AudioClass,
    791         .SubClass               = AUDIO_CSCP_ControlSubclass,
    792         .Protocol               = AUDIO_CSCP_ControlProtocol,
    793         .InterfaceStrIndex      = NO_DESCRIPTOR
    794     },
    795     .Audio_ControlInterface_SPC = {
    796         .Header = {
    797             .Size               = sizeof(USB_Audio_Descriptor_Interface_AC_t),
    798             .Type               = AUDIO_DTYPE_CSInterface
    799         },
    800         .Subtype                = AUDIO_DSUBTYPE_CSInterface_Header,
    801         .ACSpecification        = VERSION_BCD(1, 0, 0),
    802         .TotalLength            = sizeof(USB_Audio_Descriptor_Interface_AC_t),
    803         .InCollection           = 1,
    804         .InterfaceNumber        = AS_INTERFACE,
    805     },
    806     .Audio_StreamInterface = {
    807         .Header = {
    808             .Size               = sizeof(USB_Descriptor_Interface_t),
    809             .Type               = DTYPE_Interface
    810         },
    811         .InterfaceNumber        = AS_INTERFACE,
    812         .AlternateSetting       = 0,
    813         .TotalEndpoints         = 2,
    814         .Class                  = AUDIO_CSCP_AudioClass,
    815         .SubClass               = AUDIO_CSCP_MIDIStreamingSubclass,
    816         .Protocol               = AUDIO_CSCP_StreamingProtocol,
    817         .InterfaceStrIndex      = NO_DESCRIPTOR
    818     },
    819     .Audio_StreamInterface_SPC = {
    820         .Header = {
    821             .Size               = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t),
    822             .Type               = AUDIO_DTYPE_CSInterface
    823         },
    824         .Subtype                = AUDIO_DSUBTYPE_CSInterface_General,
    825         .AudioSpecification     = VERSION_BCD(1, 0, 0),
    826         .TotalLength            = offsetof(USB_Descriptor_Configuration_t, MIDI_Out_Jack_Endpoint_SPC) + sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t) - offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC)
    827     },
    828     .MIDI_In_Jack_Emb = {
    829         .Header = {
    830             .Size               = sizeof(USB_MIDI_Descriptor_InputJack_t),
    831             .Type               = AUDIO_DTYPE_CSInterface
    832         },
    833         .Subtype                = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
    834         .JackType               = MIDI_JACKTYPE_Embedded,
    835         .JackID = 0x01,
    836         .JackStrIndex           = NO_DESCRIPTOR
    837     },
    838     .MIDI_In_Jack_Ext = {
    839         .Header = {
    840             .Size               = sizeof(USB_MIDI_Descriptor_InputJack_t),
    841             .Type               = AUDIO_DTYPE_CSInterface
    842         },
    843         .Subtype                = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
    844         .JackType               = MIDI_JACKTYPE_External,
    845         .JackID                 = 0x02,
    846         .JackStrIndex           = NO_DESCRIPTOR
    847     },
    848     .MIDI_Out_Jack_Emb = {
    849         .Header = {
    850             .Size               = sizeof(USB_MIDI_Descriptor_OutputJack_t),
    851             .Type               = AUDIO_DTYPE_CSInterface
    852         },
    853         .Subtype                = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
    854         .JackType               = MIDI_JACKTYPE_Embedded,
    855         .JackID                 = 0x03,
    856         .NumberOfPins           = 1,
    857         .SourceJackID           = {0x02},
    858         .SourcePinID            = {0x01},
    859         .JackStrIndex           = NO_DESCRIPTOR
    860     },
    861     .MIDI_Out_Jack_Ext = {
    862         .Header = {
    863             .Size               = sizeof(USB_MIDI_Descriptor_OutputJack_t),
    864             .Type               = AUDIO_DTYPE_CSInterface
    865         },
    866         .Subtype                = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
    867         .JackType               = MIDI_JACKTYPE_External,
    868         .JackID                 = 0x04,
    869         .NumberOfPins           = 1,
    870         .SourceJackID           = {0x01},
    871         .SourcePinID            = {0x01},
    872         .JackStrIndex           = NO_DESCRIPTOR
    873     },
    874     .MIDI_In_Jack_Endpoint = {
    875         .Endpoint = {
    876             .Header = {
    877                 .Size           = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t),
    878                 .Type           = DTYPE_Endpoint
    879             },
    880             .EndpointAddress    = (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM),
    881             .Attributes         = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
    882             .EndpointSize       = MIDI_STREAM_EPSIZE,
    883             .PollingIntervalMS  = 0x05
    884         },
    885         .Refresh                = 0,
    886         .SyncEndpointNumber     = 0
    887     },
    888     .MIDI_In_Jack_Endpoint_SPC = {
    889         .Header = {
    890             .Size               = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t),
    891             .Type               = AUDIO_DTYPE_CSEndpoint
    892         },
    893         .Subtype                = AUDIO_DSUBTYPE_CSEndpoint_General,
    894         .TotalEmbeddedJacks     = 0x01,
    895         .AssociatedJackID       = {0x01}
    896     },
    897     .MIDI_Out_Jack_Endpoint = {
    898         .Endpoint = {
    899             .Header = {
    900                 .Size           = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t),
    901                 .Type           = DTYPE_Endpoint
    902             },
    903             .EndpointAddress    = (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM),
    904             .Attributes         = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
    905             .EndpointSize       = MIDI_STREAM_EPSIZE,
    906             .PollingIntervalMS  = 0x05
    907         },
    908         .Refresh                = 0,
    909         .SyncEndpointNumber     = 0
    910     },
    911     .MIDI_Out_Jack_Endpoint_SPC = {
    912         .Header = {
    913             .Size               = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t),
    914             .Type               = AUDIO_DTYPE_CSEndpoint
    915         },
    916         .Subtype                = AUDIO_DSUBTYPE_CSEndpoint_General,
    917         .TotalEmbeddedJacks     = 0x01,
    918         .AssociatedJackID       = {0x03}
    919     },
    920 #endif
    921 
    922 #ifdef VIRTSER_ENABLE
    923     /*
    924      * Virtual Serial
    925      */
    926     .CDC_Interface_Association = {
    927         .Header = {
    928             .Size               = sizeof(USB_Descriptor_Interface_Association_t),
    929             .Type               = DTYPE_InterfaceAssociation
    930         },
    931         .FirstInterfaceIndex    = CCI_INTERFACE,
    932         .TotalInterfaces        = 2,
    933         .Class                  = CDC_CSCP_CDCClass,
    934         .SubClass               = CDC_CSCP_ACMSubclass,
    935         .Protocol               = CDC_CSCP_ATCommandProtocol,
    936         .IADStrIndex            = NO_DESCRIPTOR,
    937     },
    938     .CDC_CCI_Interface = {
    939         .Header = {
    940             .Size               = sizeof(USB_Descriptor_Interface_t),
    941             .Type               = DTYPE_Interface
    942         },
    943         .InterfaceNumber        = CCI_INTERFACE,
    944         .AlternateSetting       = 0,
    945         .TotalEndpoints         = 1,
    946         .Class                  = CDC_CSCP_CDCClass,
    947         .SubClass               = CDC_CSCP_ACMSubclass,
    948         .Protocol               = CDC_CSCP_ATCommandProtocol,
    949         .InterfaceStrIndex      = NO_DESCRIPTOR
    950     },
    951     .CDC_Functional_Header = {
    952         .Header = {
    953             .Size               = sizeof(USB_CDC_Descriptor_FunctionalHeader_t),
    954             .Type               = CDC_DTYPE_CSInterface
    955         },
    956         .Subtype                = 0x00,
    957         .CDCSpecification       = VERSION_BCD(1, 1, 0),
    958     },
    959     .CDC_Functional_ACM = {
    960         .Header = {
    961             .Size               = sizeof(USB_CDC_Descriptor_FunctionalACM_t),
    962             .Type               = CDC_DTYPE_CSInterface
    963         },
    964         .Subtype                = 0x02,
    965         .Capabilities           = 0x02,
    966     },
    967     .CDC_Functional_Union = {
    968         .Header = {
    969             .Size               = sizeof(USB_CDC_Descriptor_FunctionalUnion_t),
    970             .Type               = CDC_DTYPE_CSInterface
    971         },
    972         .Subtype                = 0x06,
    973         .MasterInterfaceNumber  = CCI_INTERFACE,
    974         .SlaveInterfaceNumber   = CDI_INTERFACE,
    975     },
    976     .CDC_NotificationEndpoint = {
    977         .Header = {
    978             .Size               = sizeof(USB_Descriptor_Endpoint_t),
    979             .Type               = DTYPE_Endpoint
    980         },
    981         .EndpointAddress        = (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM),
    982         .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
    983         .EndpointSize           = CDC_NOTIFICATION_EPSIZE,
    984         .PollingIntervalMS      = 0xFF
    985     },
    986     .CDC_DCI_Interface = {
    987         .Header = {
    988             .Size               = sizeof(USB_Descriptor_Interface_t),
    989             .Type               = DTYPE_Interface
    990         },
    991         .InterfaceNumber        = CDI_INTERFACE,
    992         .AlternateSetting       = 0,
    993         .TotalEndpoints         = 2,
    994         .Class                  = CDC_CSCP_CDCDataClass,
    995         .SubClass               = CDC_CSCP_NoDataSubclass,
    996         .Protocol               = CDC_CSCP_NoDataProtocol,
    997         .InterfaceStrIndex      = NO_DESCRIPTOR
    998     },
    999     .CDC_DataOutEndpoint = {
   1000         .Header = {
   1001             .Size               = sizeof(USB_Descriptor_Endpoint_t),
   1002             .Type               = DTYPE_Endpoint
   1003         },
   1004         .EndpointAddress        = (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM),
   1005         .Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
   1006         .EndpointSize           = CDC_EPSIZE,
   1007         .PollingIntervalMS      = 0x05
   1008     },
   1009     .CDC_DataInEndpoint = {
   1010         .Header = {
   1011             .Size               = sizeof(USB_Descriptor_Endpoint_t),
   1012             .Type               = DTYPE_Endpoint
   1013         },
   1014         .EndpointAddress        = (ENDPOINT_DIR_IN | CDC_IN_EPNUM),
   1015         .Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
   1016         .EndpointSize           = CDC_EPSIZE,
   1017         .PollingIntervalMS      = 0x05
   1018     },
   1019 #endif
   1020 
   1021 #if defined(JOYSTICK_ENABLE) && !defined(JOYSTICK_SHARED_EP)
   1022     /*
   1023      * Joystick
   1024      */
   1025     .Joystick_Interface = {
   1026         .Header = {
   1027             .Size               = sizeof(USB_Descriptor_Interface_t),
   1028             .Type               = DTYPE_Interface
   1029         },
   1030         .InterfaceNumber        = JOYSTICK_INTERFACE,
   1031         .AlternateSetting       = 0x00,
   1032         .TotalEndpoints         = 1,
   1033         .Class                  = HID_CSCP_HIDClass,
   1034         .SubClass               = HID_CSCP_NonBootSubclass,
   1035         .Protocol               = HID_CSCP_NonBootProtocol,
   1036         .InterfaceStrIndex      = NO_DESCRIPTOR
   1037     },
   1038     .Joystick_HID = {
   1039         .Header = {
   1040             .Size               = sizeof(USB_HID_Descriptor_HID_t),
   1041             .Type               = HID_DTYPE_HID
   1042         },
   1043         .HIDSpec                = VERSION_BCD(1, 1, 1),
   1044         .CountryCode            = 0x00,
   1045         .TotalReportDescriptors = 1,
   1046         .HIDReportType          = HID_DTYPE_Report,
   1047         .HIDReportLength        = sizeof(JoystickReport)
   1048     },
   1049     .Joystick_INEndpoint = {
   1050         .Header = {
   1051             .Size               = sizeof(USB_Descriptor_Endpoint_t),
   1052             .Type               = DTYPE_Endpoint
   1053         },
   1054         .EndpointAddress        = (ENDPOINT_DIR_IN | JOYSTICK_IN_EPNUM),
   1055         .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
   1056         .EndpointSize           = JOYSTICK_EPSIZE,
   1057         .PollingIntervalMS      = USB_POLLING_INTERVAL_MS
   1058     },
   1059 #endif
   1060 
   1061 #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP)
   1062     /*
   1063      * Digitizer
   1064      */
   1065     .Digitizer_Interface  = {
   1066         .Header = {
   1067             .Size               = sizeof(USB_Descriptor_Interface_t),
   1068             .Type               = DTYPE_Interface
   1069         },
   1070         .InterfaceNumber        = DIGITIZER_INTERFACE,
   1071         .AlternateSetting       = 0x00,
   1072         .TotalEndpoints         = 1,
   1073         .Class                  = HID_CSCP_HIDClass,
   1074         .SubClass               = HID_CSCP_NonBootSubclass,
   1075         .Protocol               = HID_CSCP_NonBootProtocol,
   1076         .InterfaceStrIndex      = NO_DESCRIPTOR
   1077     },
   1078     .Digitizer_HID = {
   1079         .Header = {
   1080             .Size               = sizeof(USB_HID_Descriptor_HID_t),
   1081             .Type               = HID_DTYPE_HID
   1082         },
   1083         .HIDSpec                = VERSION_BCD(1, 1, 1),
   1084         .CountryCode            = 0x00,
   1085         .TotalReportDescriptors = 1,
   1086         .HIDReportType          = HID_DTYPE_Report,
   1087         .HIDReportLength        = sizeof(DigitizerReport)
   1088     },
   1089     .Digitizer_INEndpoint = {
   1090         .Header = {
   1091             .Size               = sizeof(USB_Descriptor_Endpoint_t),
   1092             .Type               = DTYPE_Endpoint
   1093         },
   1094         .EndpointAddress        = (ENDPOINT_DIR_IN | DIGITIZER_IN_EPNUM),
   1095         .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
   1096         .EndpointSize           = DIGITIZER_EPSIZE,
   1097         .PollingIntervalMS      = USB_POLLING_INTERVAL_MS
   1098     },
   1099 #endif
   1100 };
   1101 
   1102 /*
   1103  * String descriptors
   1104  */
   1105 
   1106 #define USB_DESCRIPTOR_SIZE_LITERAL_U16STRING(str) \
   1107     (sizeof(USB_Descriptor_Header_t) + sizeof(str) - sizeof(wchar_t)) // include header, don't count null terminator
   1108 
   1109 const USB_Descriptor_String_t PROGMEM LanguageString = {
   1110     .Header = {
   1111         .Size                   = sizeof(USB_Descriptor_Header_t) + sizeof(uint16_t),
   1112         .Type                   = DTYPE_String
   1113     },
   1114     .UnicodeString              = {LANGUAGE_ID_ENG}
   1115 };
   1116 
   1117 const USB_Descriptor_String_t PROGMEM ManufacturerString = {
   1118     .Header = {
   1119         .Size                   = USB_DESCRIPTOR_SIZE_LITERAL_U16STRING(USBSTR(MANUFACTURER)),
   1120         .Type                   = DTYPE_String
   1121     },
   1122     .UnicodeString              = USBSTR(MANUFACTURER)
   1123 };
   1124 
   1125 const USB_Descriptor_String_t PROGMEM ProductString = {
   1126     .Header = {
   1127         .Size                   = USB_DESCRIPTOR_SIZE_LITERAL_U16STRING(USBSTR(PRODUCT)),
   1128         .Type                   = DTYPE_String
   1129     },
   1130     .UnicodeString              = USBSTR(PRODUCT)
   1131 };
   1132 
   1133 // clang-format on
   1134 
   1135 #if defined(SERIAL_NUMBER)
   1136 // clang-format off
   1137 const USB_Descriptor_String_t PROGMEM SerialNumberString = {
   1138     .Header = {
   1139         .Size                   = USB_DESCRIPTOR_SIZE_LITERAL_U16STRING(USBSTR(SERIAL_NUMBER)),
   1140         .Type                   = DTYPE_String
   1141     },
   1142     .UnicodeString              = USBSTR(SERIAL_NUMBER)
   1143 };
   1144 // clang-format on
   1145 
   1146 #else // defined(SERIAL_NUMBER)
   1147 
   1148 #    if defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE
   1149 
   1150 #        if defined(__AVR__)
   1151 #            error Dynamically setting the serial number on AVR is unsupported as LUFA requires the string to be in PROGMEM.
   1152 #        endif // defined(__AVR__)
   1153 
   1154 #        ifndef SERIAL_NUMBER_LENGTH
   1155 #            define SERIAL_NUMBER_LENGTH (sizeof(hardware_id_t) * 2)
   1156 #        endif
   1157 
   1158 #        define SERIAL_NUMBER_DESCRIPTOR_SIZE                                            \
   1159             (sizeof(USB_Descriptor_Header_t)                     /* Descriptor header */ \
   1160              + (((SERIAL_NUMBER_LENGTH) + 1) * sizeof(wchar_t))) /* Length of serial number, with potential extra character as we're converting 2 nibbles at a time */
   1161 
   1162 uint8_t SerialNumberString[SERIAL_NUMBER_DESCRIPTOR_SIZE] = {0};
   1163 
   1164 void set_serial_number_descriptor(void) {
   1165     static bool is_set = false;
   1166     if (is_set) {
   1167         return;
   1168     }
   1169     is_set = true;
   1170 
   1171     static const char        hex_str[] = "0123456789ABCDEF";
   1172     hardware_id_t            id        = get_hardware_id();
   1173     USB_Descriptor_String_t* desc      = (USB_Descriptor_String_t*)SerialNumberString;
   1174 
   1175     // Copy across nibbles from the hardware ID as unicode hex characters
   1176     int      length = MIN(sizeof(id) * 2, SERIAL_NUMBER_LENGTH);
   1177     uint8_t* p      = (uint8_t*)&id;
   1178     for (int i = 0; i < length; i += 2) {
   1179         desc->UnicodeString[i + 0] = hex_str[p[i / 2] >> 4];
   1180         desc->UnicodeString[i + 1] = hex_str[p[i / 2] & 0xF];
   1181     }
   1182 
   1183     desc->Header.Size = sizeof(USB_Descriptor_Header_t) + (length * sizeof(wchar_t)); // includes header, don't count null terminator
   1184     desc->Header.Type = DTYPE_String;
   1185 }
   1186 
   1187 #    endif // defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE
   1188 
   1189 #endif // defined(SERIAL_NUMBER)
   1190 
   1191 /**
   1192  * This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
   1193  * documentation) by the application code so that the address and size of a requested descriptor can be given
   1194  * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
   1195  * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
   1196  * USB host.
   1197  */
   1198 uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, const void** const DescriptorAddress) {
   1199     const uint8_t DescriptorType  = (wValue >> 8);
   1200     const uint8_t DescriptorIndex = (wValue & 0xFF);
   1201     const void*   Address         = NULL;
   1202     uint16_t      Size            = NO_DESCRIPTOR;
   1203 
   1204     switch (DescriptorType) {
   1205         case DTYPE_Device:
   1206             Address = &DeviceDescriptor;
   1207             Size    = sizeof(USB_Descriptor_Device_t);
   1208 
   1209             break;
   1210         case DTYPE_Configuration:
   1211             Address = &ConfigurationDescriptor;
   1212             Size    = sizeof(USB_Descriptor_Configuration_t);
   1213 
   1214             break;
   1215         case DTYPE_String:
   1216             switch (DescriptorIndex) {
   1217                 case 0x00:
   1218                     Address = &LanguageString;
   1219                     Size    = pgm_read_byte(&LanguageString.Header.Size);
   1220 
   1221                     break;
   1222                 case 0x01:
   1223                     Address = &ManufacturerString;
   1224                     Size    = pgm_read_byte(&ManufacturerString.Header.Size);
   1225 
   1226                     break;
   1227                 case 0x02:
   1228                     Address = &ProductString;
   1229                     Size    = pgm_read_byte(&ProductString.Header.Size);
   1230 
   1231                     break;
   1232 #ifdef HAS_SERIAL_NUMBER
   1233                 case 0x03:
   1234                     Address = (const USB_Descriptor_String_t*)&SerialNumberString;
   1235 #    if defined(SERIAL_NUMBER)
   1236                     Size = pgm_read_byte(&SerialNumberString.Header.Size);
   1237 #    else
   1238                     set_serial_number_descriptor();
   1239                     Size = ((const USB_Descriptor_String_t*)SerialNumberString)->Header.Size;
   1240 #    endif
   1241 
   1242                     break;
   1243 #endif // HAS_SERIAL_NUMBER
   1244             }
   1245 #ifdef OS_DETECTION_ENABLE
   1246             process_wlength(wLength);
   1247 #endif
   1248 
   1249             break;
   1250         case HID_DTYPE_HID:
   1251             switch (wIndex) {
   1252 #ifndef KEYBOARD_SHARED_EP
   1253                 case KEYBOARD_INTERFACE:
   1254                     Address = &ConfigurationDescriptor.Keyboard_HID;
   1255                     Size    = sizeof(USB_HID_Descriptor_HID_t);
   1256                     break;
   1257 #endif
   1258 
   1259 #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
   1260                 case MOUSE_INTERFACE:
   1261                     Address = &ConfigurationDescriptor.Mouse_HID;
   1262                     Size    = sizeof(USB_HID_Descriptor_HID_t);
   1263 
   1264                     break;
   1265 #endif
   1266 
   1267 #ifdef SHARED_EP_ENABLE
   1268                 case SHARED_INTERFACE:
   1269                     Address = &ConfigurationDescriptor.Shared_HID;
   1270                     Size    = sizeof(USB_HID_Descriptor_HID_t);
   1271 
   1272                     break;
   1273 #endif
   1274 
   1275 #ifdef RAW_ENABLE
   1276                 case RAW_INTERFACE:
   1277                     Address = &ConfigurationDescriptor.Raw_HID;
   1278                     Size    = sizeof(USB_HID_Descriptor_HID_t);
   1279 
   1280                     break;
   1281 #endif
   1282 
   1283 #ifdef CONSOLE_ENABLE
   1284                 case CONSOLE_INTERFACE:
   1285                     Address = &ConfigurationDescriptor.Console_HID;
   1286                     Size    = sizeof(USB_HID_Descriptor_HID_t);
   1287 
   1288                     break;
   1289 #endif
   1290 #if defined(JOYSTICK_ENABLE) && !defined(JOYSTICK_SHARED_EP)
   1291                 case JOYSTICK_INTERFACE:
   1292                     Address = &ConfigurationDescriptor.Joystick_HID;
   1293                     Size    = sizeof(USB_HID_Descriptor_HID_t);
   1294                     break;
   1295 #endif
   1296 #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP)
   1297                 case DIGITIZER_INTERFACE:
   1298                     Address = &ConfigurationDescriptor.Digitizer_HID;
   1299                     Size    = sizeof(USB_HID_Descriptor_HID_t);
   1300 
   1301                     break;
   1302 #endif
   1303             }
   1304 
   1305             break;
   1306         case HID_DTYPE_Report:
   1307             switch (wIndex) {
   1308 #ifndef KEYBOARD_SHARED_EP
   1309                 case KEYBOARD_INTERFACE:
   1310                     Address = &KeyboardReport;
   1311                     Size    = sizeof(KeyboardReport);
   1312 
   1313                     break;
   1314 #endif
   1315 
   1316 #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
   1317                 case MOUSE_INTERFACE:
   1318                     Address = &MouseReport;
   1319                     Size    = sizeof(MouseReport);
   1320 
   1321                     break;
   1322 #endif
   1323 
   1324 #ifdef SHARED_EP_ENABLE
   1325                 case SHARED_INTERFACE:
   1326                     Address = &SharedReport;
   1327                     Size    = sizeof(SharedReport);
   1328 
   1329                     break;
   1330 #endif
   1331 
   1332 #ifdef RAW_ENABLE
   1333                 case RAW_INTERFACE:
   1334                     Address = &RawReport;
   1335                     Size    = sizeof(RawReport);
   1336 
   1337                     break;
   1338 #endif
   1339 
   1340 #ifdef CONSOLE_ENABLE
   1341                 case CONSOLE_INTERFACE:
   1342                     Address = &ConsoleReport;
   1343                     Size    = sizeof(ConsoleReport);
   1344 
   1345                     break;
   1346 #endif
   1347 #if defined(JOYSTICK_ENABLE) && !defined(JOYSTICK_SHARED_EP)
   1348                 case JOYSTICK_INTERFACE:
   1349                     Address = &JoystickReport;
   1350                     Size    = sizeof(JoystickReport);
   1351                     break;
   1352 #endif
   1353 #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP)
   1354                 case DIGITIZER_INTERFACE:
   1355                     Address = &DigitizerReport;
   1356                     Size    = sizeof(DigitizerReport);
   1357                     break;
   1358 #endif
   1359             }
   1360 
   1361             break;
   1362     }
   1363 
   1364     *DescriptorAddress = Address;
   1365 
   1366     return Size;
   1367 }