diff options
Diffstat (limited to 'tmk_core/protocol')
| -rw-r--r-- | tmk_core/protocol/arm_atsam/main_arm_atsam.c | 59 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h | 2 | ||||
| -rw-r--r-- | tmk_core/protocol/chibios/chibios.c | 3 | ||||
| -rw-r--r-- | tmk_core/protocol/chibios/usb_main.c | 173 | ||||
| -rw-r--r-- | tmk_core/protocol/host.c | 33 | ||||
| -rw-r--r-- | tmk_core/protocol/host.h | 4 | ||||
| -rw-r--r-- | tmk_core/protocol/host_driver.h | 1 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 34 | ||||
| -rw-r--r-- | tmk_core/protocol/report.c | 43 | ||||
| -rw-r--r-- | tmk_core/protocol/report.h | 154 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_descriptor.c | 4 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_descriptor.h | 2 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_types.h | 23 | ||||
| -rw-r--r-- | tmk_core/protocol/vusb/vusb.c | 92 | 
14 files changed, 305 insertions, 322 deletions
diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index 30817c17b6..8abcfd6090 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -36,6 +36,7 @@ uint8_t g_usb_state = USB_FSMSTATUS_FSMSTATE_OFF_Val; // Saved USB state from ha  void    main_subtasks(void);  uint8_t keyboard_leds(void);  void    send_keyboard(report_keyboard_t *report); +void    send_nkro(report_nkro_t *report);  void    send_mouse(report_mouse_t *report);  void    send_extra(report_extra_t *report); @@ -43,7 +44,7 @@ void    send_extra(report_extra_t *report);  void deferred_exec_task(void);  #endif // DEFERRED_EXEC_ENABLE -host_driver_t arm_atsam_driver = {keyboard_leds, send_keyboard, send_mouse, send_extra}; +host_driver_t arm_atsam_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};  uint8_t led_states; @@ -59,41 +60,41 @@ uint8_t keyboard_leds(void) {  void send_keyboard(report_keyboard_t *report) {      uint32_t irqflags; -#ifdef NKRO_ENABLE -    if (!keymap_config.nkro) { -#endif // NKRO_ENABLE -        while (udi_hid_kbd_b_report_trans_ongoing) { -            main_subtasks(); -        } // Run other tasks while waiting for USB to be free +    while (udi_hid_kbd_b_report_trans_ongoing) { +        main_subtasks(); +    } // Run other tasks while waiting for USB to be free -        irqflags = __get_PRIMASK(); -        __disable_irq(); -        __DMB(); +    irqflags = __get_PRIMASK(); +    __disable_irq(); +    __DMB(); -        memcpy(udi_hid_kbd_report, report->raw, UDI_HID_KBD_REPORT_SIZE); -        udi_hid_kbd_b_report_valid = 1; -        udi_hid_kbd_send_report(); +    memcpy(udi_hid_kbd_report, report, UDI_HID_KBD_REPORT_SIZE); +    udi_hid_kbd_b_report_valid = 1; +    udi_hid_kbd_send_report(); -        __DMB(); -        __set_PRIMASK(irqflags); +    __DMB(); +    __set_PRIMASK(irqflags); +} + +void send_nkro(report_nkro_t *report) {  #ifdef NKRO_ENABLE -    } else { -        while (udi_hid_nkro_b_report_trans_ongoing) { -            main_subtasks(); -        } // Run other tasks while waiting for USB to be free +    uint32_t irqflags; -        irqflags = __get_PRIMASK(); -        __disable_irq(); -        __DMB(); +    while (udi_hid_nkro_b_report_trans_ongoing) { +        main_subtasks(); +    } // Run other tasks while waiting for USB to be free -        memcpy(udi_hid_nkro_report, report->raw, UDI_HID_NKRO_REPORT_SIZE); -        udi_hid_nkro_b_report_valid = 1; -        udi_hid_nkro_send_report(); +    irqflags = __get_PRIMASK(); +    __disable_irq(); +    __DMB(); -        __DMB(); -        __set_PRIMASK(irqflags); -    } -#endif // NKRO_ENABLE +    memcpy(udi_hid_nkro_report, report, UDI_HID_NKRO_REPORT_SIZE); +    udi_hid_nkro_b_report_valid = 1; +    udi_hid_nkro_send_report(); + +    __DMB(); +    __set_PRIMASK(irqflags); +#endif  }  void send_mouse(report_mouse_t *report) { diff --git a/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h b/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h index 7a9ed31930..47bd02c074 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h +++ b/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h @@ -19,7 +19,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define _UDI_DEVICE_EPSIZE_H_  #define KEYBOARD_EPSIZE 8 -#define MOUSE_EPSIZE 8 +#define MOUSE_EPSIZE 16  #define EXTRAKEY_EPSIZE 8  #define RAW_EPSIZE 32  #define CONSOLE_EPSIZE 32 diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c index 4d97f1cd82..91bb252c7c 100644 --- a/tmk_core/protocol/chibios/chibios.c +++ b/tmk_core/protocol/chibios/chibios.c @@ -59,11 +59,12 @@  /* declarations */  uint8_t keyboard_leds(void);  void    send_keyboard(report_keyboard_t *report); +void    send_nkro(report_nkro_t *report);  void    send_mouse(report_mouse_t *report);  void    send_extra(report_extra_t *report);  /* host struct */ -host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_extra}; +host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};  #ifdef VIRTSER_ENABLE  void virtser_task(void); diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index b14ca30c1a..66f9ad0318 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -43,6 +43,7 @@  #include "usb_device_state.h"  #include "usb_descriptor.h"  #include "usb_driver.h" +#include "usb_types.h"  #ifdef NKRO_ENABLE  #    include "keycode_config.h" @@ -71,7 +72,7 @@ static virtual_timer_t keyboard_idle_timer;  static void keyboard_idle_timer_cb(struct ch_virtual_timer *, void *arg); -report_keyboard_t keyboard_report_sent = {{0}}; +report_keyboard_t keyboard_report_sent = {0};  report_mouse_t    mouse_report_sent    = {0};  union { @@ -103,30 +104,18 @@ union {              NULL, /* SETUP buffer (not a SETUP endpoint) */  #endif -/* HID specific constants */ -#define HID_GET_REPORT 0x01 -#define HID_GET_IDLE 0x02 -#define HID_GET_PROTOCOL 0x03 -#define HID_SET_REPORT 0x09 -#define HID_SET_IDLE 0x0A -#define HID_SET_PROTOCOL 0x0B - -/* - * Handles the GET_DESCRIPTOR callback - * - * Returns the proper descriptor - */  static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) { -    (void)usbp; -    static USBDescriptor desc; -    uint16_t             wValue  = ((uint16_t)dtype << 8) | dindex; -    uint16_t             wLength = ((uint16_t)usbp->setup[7] << 8) | usbp->setup[6]; -    desc.ud_string               = NULL; -    desc.ud_size                 = get_usb_descriptor(wValue, wIndex, wLength, (const void **const) & desc.ud_string); -    if (desc.ud_string == NULL) +    usb_control_request_t *setup = (usb_control_request_t *)usbp->setup; + +    static USBDescriptor descriptor; +    descriptor.ud_string = NULL; +    descriptor.ud_size   = get_usb_descriptor(setup->wValue.word, setup->wIndex, setup->wLength, (const void **const) & descriptor.ud_string); + +    if (descriptor.ud_string == NULL) {          return NULL; -    else -        return &desc; +    } + +    return &descriptor;  }  /* @@ -497,8 +486,7 @@ void usb_event_queue_task(void) {      }  } -/* Handles the USB driver global events - * TODO: maybe disable some things when connection is lost? */ +/* Handles the USB driver global events. */  static void usb_event_cb(USBDriver *usbp, usbevent_t event) {      switch (event) {          case USB_EVENT_ADDRESS: @@ -570,16 +558,6 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {      }  } -/* Function used locally in os/hal/src/usb.c for getting descriptors - * need it here for HID descriptor */ -static uint16_t get_hword(uint8_t *p) { -    uint16_t hw; - -    hw = (uint16_t)*p++; -    hw |= (uint16_t)*p << 8U; -    return hw; -} -  /*   * Appendix G: HID Request Support Requirements   * @@ -596,7 +574,9 @@ static uint16_t get_hword(uint8_t *p) {  static uint8_t set_report_buf[2] __attribute__((aligned(4)));  static void set_led_transfer_cb(USBDriver *usbp) { -    if (usbp->setup[6] == 2) { /* LSB(wLength) */ +    usb_control_request_t *setup = (usb_control_request_t *)usbp->setup; + +    if (setup->wLength == 2) {          uint8_t report_id = set_report_buf[0];          if ((report_id == REPORT_ID_KEYBOARD) || (report_id == REPORT_ID_NKRO)) {              keyboard_led_state = set_report_buf[1]; @@ -606,24 +586,16 @@ static void set_led_transfer_cb(USBDriver *usbp) {      }  } -/* Callback for SETUP request on the endpoint 0 (control) */ -static bool usb_request_hook_cb(USBDriver *usbp) { -    const USBDescriptor *dp; - -    /* usbp->setup fields: -     *  0:   bmRequestType (bitmask) -     *  1:   bRequest -     *  2,3: (LSB,MSB) wValue -     *  4,5: (LSB,MSB) wIndex -     *  6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */ +static bool usb_requests_hook_cb(USBDriver *usbp) { +    usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;      /* Handle HID class specific requests */ -    if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) && ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) { -        switch (usbp->setup[0] & USB_RTYPE_DIR_MASK) { +    if ((setup->bmRequestType & (USB_RTYPE_TYPE_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_TYPE_CLASS | USB_RTYPE_RECIPIENT_INTERFACE)) { +        switch (setup->bmRequestType & USB_RTYPE_DIR_MASK) {              case USB_RTYPE_DIR_DEV2HOST: -                switch (usbp->setup[1]) { /* bRequest */ -                    case HID_GET_REPORT: -                        switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */ +                switch (setup->bRequest) { +                    case HID_REQ_GetReport: +                        switch (setup->wIndex) {  #ifndef KEYBOARD_SHARED_EP                              case KEYBOARD_INTERFACE:                                  usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL); @@ -639,59 +611,54 @@ static bool usb_request_hook_cb(USBDriver *usbp) {  #ifdef SHARED_EP_ENABLE                              case SHARED_INTERFACE:  #    ifdef KEYBOARD_SHARED_EP -                                if (usbp->setup[2] == REPORT_ID_KEYBOARD) { +                                if (setup->wValue.lbyte == REPORT_ID_KEYBOARD) {                                      usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL); -                                    return TRUE; -                                    break; +                                    return true;                                  }  #    endif  #    ifdef MOUSE_SHARED_EP -                                if (usbp->setup[2] == REPORT_ID_MOUSE) { +                                if (setup->wValue.lbyte == REPORT_ID_MOUSE) {                                      usbSetupTransfer(usbp, (uint8_t *)&mouse_report_sent, sizeof(mouse_report_sent), NULL); -                                    return TRUE; -                                    break; +                                    return true;                                  }  #    endif  #endif /* SHARED_EP_ENABLE */                              default: -                                universal_report_blank.report_id = usbp->setup[2]; -                                usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, usbp->setup[6], NULL); -                                return TRUE; -                                break; +                                universal_report_blank.report_id = setup->wValue.lbyte; +                                usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, setup->wLength, NULL); +                                return true;                          }                          break; -                    case HID_GET_PROTOCOL: -                        if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */ -                            usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL); -                            return TRUE; +                    case HID_REQ_GetProtocol: +                        if (setup->wIndex == KEYBOARD_INTERFACE) { +                            usbSetupTransfer(usbp, &keyboard_protocol, sizeof(uint8_t), NULL); +                            return true;                          }                          break; -                    case HID_GET_IDLE: -                        usbSetupTransfer(usbp, &keyboard_idle, 1, NULL); -                        return TRUE; -                        break; +                    case HID_REQ_GetIdle: +                        usbSetupTransfer(usbp, &keyboard_idle, sizeof(uint8_t), NULL); +                        return true;                  }                  break;              case USB_RTYPE_DIR_HOST2DEV: -                switch (usbp->setup[1]) { /* bRequest */ -                    case HID_SET_REPORT: -                        switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */ +                switch (setup->bRequest) { +                    case HID_REQ_SetReport: +                        switch (setup->wIndex) {                              case KEYBOARD_INTERFACE:  #if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)                              case SHARED_INTERFACE:  #endif                                  usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb); -                                return TRUE; -                                break; +                                return true;                          }                          break; -                    case HID_SET_PROTOCOL: -                        if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */ -                            keyboard_protocol = ((usbp->setup[2]) != 0x00);                    /* LSB(wValue) */ +                    case HID_REQ_SetProtocol: +                        if (setup->wIndex == KEYBOARD_INTERFACE) { +                            keyboard_protocol = setup->wValue.word;  #ifdef NKRO_ENABLE                              if (!keyboard_protocol && keyboard_idle) {  #else  /* NKRO_ENABLE */ @@ -704,12 +671,11 @@ static bool usb_request_hook_cb(USBDriver *usbp) {                              }                          }                          usbSetupTransfer(usbp, NULL, 0, NULL); -                        return TRUE; -                        break; +                        return true; -                    case HID_SET_IDLE: -                        keyboard_idle = usbp->setup[3]; /* MSB(wValue) */ -                                                        /* arm the timer */ +                    case HID_REQ_SetIdle: +                        keyboard_idle = setup->wValue.hbyte; +                        /* arm the timer */  #ifdef NKRO_ENABLE                          if (!keymap_config.nkro && keyboard_idle) {  #else  /* NKRO_ENABLE */ @@ -720,19 +686,21 @@ static bool usb_request_hook_cb(USBDriver *usbp) {                              osalSysUnlockFromISR();                          }                          usbSetupTransfer(usbp, NULL, 0, NULL); -                        return TRUE; -                        break; +                        return true;                  }                  break;          }      } -    /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */ -    if ((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) { -        dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4])); -        if (dp == NULL) return FALSE; -        usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL); -        return TRUE; +    /* Handle the Get_Descriptor Request for HID class, which is not handled by +     * the ChibiOS USB driver */ +    if (((setup->bmRequestType & (USB_RTYPE_DIR_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_DIR_DEV2HOST | USB_RTYPE_RECIPIENT_INTERFACE)) && (setup->bRequest == USB_REQ_GET_DESCRIPTOR)) { +        const USBDescriptor *descriptor = usbp->config->get_descriptor_cb(usbp, setup->wValue.lbyte, setup->wValue.hbyte, setup->wIndex); +        if (descriptor == NULL) { +            return false; +        } +        usbSetupTransfer(usbp, (uint8_t *)descriptor->ud_string, descriptor->ud_size, NULL); +        return true;      }      for (int i = 0; i < NUM_USB_DRIVERS; i++) { @@ -742,10 +710,9 @@ static bool usb_request_hook_cb(USBDriver *usbp) {          }      } -    return FALSE; +    return false;  } -/* Start-of-frame callback */  static void usb_sof_cb(USBDriver *usbp) {      osalSysLockFromISR();      for (int i = 0; i < NUM_USB_DRIVERS; i++) { @@ -758,7 +725,7 @@ static void usb_sof_cb(USBDriver *usbp) {  static const USBConfig usbcfg = {      usb_event_cb,          /* USB events callback */      usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */ -    usb_request_hook_cb,   /* Requests hook callback */ +    usb_requests_hook_cb,  /* Requests hook callback */      usb_sof_cb             /* Start Of Frame callback */  }; @@ -883,26 +850,22 @@ void send_report(uint8_t endpoint, void *report, size_t size) {  /* prepare and start sending a report IN   * not callable from ISR or locked state */  void send_keyboard(report_keyboard_t *report) { -    uint8_t ep   = KEYBOARD_IN_EPNUM; -    size_t  size = KEYBOARD_REPORT_SIZE; -      /* If we're in Boot Protocol, don't send any report ID or other funky fields */      if (!keyboard_protocol) { -        send_report(ep, &report->mods, 8); +        send_report(KEYBOARD_IN_EPNUM, &report->mods, 8);      } else { -#ifdef NKRO_ENABLE -        if (keymap_config.nkro) { -            ep   = SHARED_IN_EPNUM; -            size = sizeof(struct nkro_report); -        } -#endif - -        send_report(ep, report, size); +        send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE);      }      keyboard_report_sent = *report;  } +void send_nkro(report_nkro_t *report) { +#ifdef NKRO_ENABLE +    send_report(SHARED_IN_EPNUM, report, sizeof(report_nkro_t)); +#endif +} +  /* ---------------------------------------------------------   *                     Mouse functions   * --------------------------------------------------------- diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c index 2c6654e9a6..732fbdc37d 100644 --- a/tmk_core/protocol/host.c +++ b/tmk_core/protocol/host.c @@ -81,26 +81,29 @@ void host_keyboard_send(report_keyboard_t *report) {  #endif      if (!driver) return; -#if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP) -    if (keyboard_protocol && keymap_config.nkro) { -        /* The callers of this function assume that report->mods is where mods go in. -         * But report->nkro.mods can be at a different offset if core keyboard does not have a report ID. -         */ -        report->nkro.mods      = report->mods; -        report->nkro.report_id = REPORT_ID_NKRO; -    } else -#endif -    {  #ifdef KEYBOARD_SHARED_EP -        report->report_id = REPORT_ID_KEYBOARD; +    report->report_id = REPORT_ID_KEYBOARD;  #endif -    }      (*driver->send_keyboard)(report);      if (debug_keyboard) { -        dprint("keyboard_report: "); -        for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) { -            dprintf("%02X ", report->raw[i]); +        dprintf("keyboard_report: %02X | ", report->mods); +        for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { +            dprintf("%02X ", report->keys[i]); +        } +        dprint("\n"); +    } +} + +void host_nkro_send(report_nkro_t *report) { +    if (!driver) return; +    report->report_id = REPORT_ID_NKRO; +    (*driver->send_nkro)(report); + +    if (debug_keyboard) { +        dprintf("nkro_report: %02X | ", report->mods); +        for (uint8_t i = 0; i < NKRO_REPORT_BITS; i++) { +            dprintf("%02X ", report->bits[i]);          }          dprint("\n");      } diff --git a/tmk_core/protocol/host.h b/tmk_core/protocol/host.h index add408caf6..959753ae02 100644 --- a/tmk_core/protocol/host.h +++ b/tmk_core/protocol/host.h @@ -23,9 +23,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "host_driver.h"  #include "led.h" -#define IS_LED_ON(leds, led_name) ((leds) & (1 << (led_name))) -#define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name))) -  #ifdef __cplusplus  extern "C" {  #endif @@ -41,6 +38,7 @@ host_driver_t *host_get_driver(void);  uint8_t host_keyboard_leds(void);  led_t   host_keyboard_led_state(void);  void    host_keyboard_send(report_keyboard_t *report); +void    host_nkro_send(report_nkro_t *report);  void    host_mouse_send(report_mouse_t *report);  void    host_system_send(uint16_t usage);  void    host_consumer_send(uint16_t usage); diff --git a/tmk_core/protocol/host_driver.h b/tmk_core/protocol/host_driver.h index 7dc6c3d810..8aa38b6dee 100644 --- a/tmk_core/protocol/host_driver.h +++ b/tmk_core/protocol/host_driver.h @@ -26,6 +26,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  typedef struct {      uint8_t (*keyboard_leds)(void);      void (*send_keyboard)(report_keyboard_t *); +    void (*send_nkro)(report_nkro_t *);      void (*send_mouse)(report_mouse_t *);      void (*send_extra)(report_extra_t *);  } host_driver_t; diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index f04ca79a0c..553f69b1e4 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -55,12 +55,6 @@  #include "usb_device_state.h"  #include <util/atomic.h> -#ifdef NKRO_ENABLE -#    include "keycode_config.h" - -extern keymap_config_t keymap_config; -#endif -  #ifdef VIRTSER_ENABLE  #    include "virtser.h"  #endif @@ -83,9 +77,10 @@ static report_keyboard_t keyboard_report_sent;  /* Host driver */  static uint8_t keyboard_leds(void);  static void    send_keyboard(report_keyboard_t *report); +static void    send_nkro(report_nkro_t *report);  static void    send_mouse(report_mouse_t *report);  static void    send_extra(report_extra_t *report); -host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_extra}; +host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};  void send_report(uint8_t endpoint, void *report, size_t size) {      uint8_t timeout = 255; @@ -559,27 +554,26 @@ static uint8_t keyboard_leds(void) {   * FIXME: Needs doc   */  static void send_keyboard(report_keyboard_t *report) { -    /* Select the Keyboard Report Endpoint */ -    uint8_t ep   = KEYBOARD_IN_EPNUM; -    uint8_t size = KEYBOARD_REPORT_SIZE; -      /* If we're in Boot Protocol, don't send any report ID or other funky fields */      if (!keyboard_protocol) { -        send_report(ep, &report->mods, 8); +        send_report(KEYBOARD_IN_EPNUM, &report->mods, 8);      } else { -#ifdef NKRO_ENABLE -        if (keymap_config.nkro) { -            ep   = SHARED_IN_EPNUM; -            size = sizeof(struct nkro_report); -        } -#endif - -        send_report(ep, report, size); +        send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE);      }      keyboard_report_sent = *report;  } +/** \brief Send NKRO + * + * FIXME: Needs doc + */ +static void send_nkro(report_nkro_t *report) { +#ifdef NKRO_ENABLE +    send_report(SHARED_IN_EPNUM, report, sizeof(report_nkro_t)); +#endif +} +  /** \brief Send Mouse   *   * FIXME: Needs doc diff --git a/tmk_core/protocol/report.c b/tmk_core/protocol/report.c index 1ba3be4604..0166bf654f 100644 --- a/tmk_core/protocol/report.c +++ b/tmk_core/protocol/report.c @@ -15,6 +15,7 @@   */  #include "report.h" +#include "action_util.h"  #include "host.h"  #include "keycode_config.h"  #include "debug.h" @@ -35,14 +36,14 @@ static int8_t cb_count = 0;   *   * FIXME: Needs doc   */ -uint8_t has_anykey(report_keyboard_t* keyboard_report) { +uint8_t has_anykey(void) {      uint8_t  cnt = 0;      uint8_t* p   = keyboard_report->keys;      uint8_t  lp  = sizeof(keyboard_report->keys);  #ifdef NKRO_ENABLE      if (keyboard_protocol && keymap_config.nkro) { -        p  = keyboard_report->nkro.bits; -        lp = sizeof(keyboard_report->nkro.bits); +        p  = nkro_report->bits; +        lp = sizeof(nkro_report->bits);      }  #endif      while (lp--) { @@ -55,13 +56,13 @@ uint8_t has_anykey(report_keyboard_t* keyboard_report) {   *   * FIXME: Needs doc   */ -uint8_t get_first_key(report_keyboard_t* keyboard_report) { +uint8_t get_first_key(void) {  #ifdef NKRO_ENABLE      if (keyboard_protocol && keymap_config.nkro) {          uint8_t i = 0; -        for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) +        for (; i < NKRO_REPORT_BITS && !nkro_report->bits[i]; i++)              ; -        return i << 3 | biton(keyboard_report->nkro.bits[i]); +        return i << 3 | biton(nkro_report->bits[i]);      }  #endif  #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE @@ -83,14 +84,14 @@ uint8_t get_first_key(report_keyboard_t* keyboard_report) {   * Returns true if the keyboard_report reports that the key is pressed, otherwise false   * Note: The function doesn't support modifers currently, and it returns false for KC_NO   */ -bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key) { +bool is_key_pressed(uint8_t key) {      if (key == KC_NO) {          return false;      }  #ifdef NKRO_ENABLE      if (keyboard_protocol && keymap_config.nkro) { -        if ((key >> 3) < KEYBOARD_REPORT_BITS) { -            return keyboard_report->nkro.bits[key >> 3] & 1 << (key & 7); +        if ((key >> 3) < NKRO_REPORT_BITS) { +            return nkro_report->bits[key >> 3] & 1 << (key & 7);          } else {              return false;          } @@ -215,9 +216,9 @@ void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) {   *   * FIXME: Needs doc   */ -void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { -    if ((code >> 3) < KEYBOARD_REPORT_BITS) { -        keyboard_report->nkro.bits[code >> 3] |= 1 << (code & 7); +void add_key_bit(report_nkro_t* nkro_report, uint8_t code) { +    if ((code >> 3) < NKRO_REPORT_BITS) { +        nkro_report->bits[code >> 3] |= 1 << (code & 7);      } else {          dprintf("add_key_bit: can't add: %02X\n", code);      } @@ -227,9 +228,9 @@ void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {   *   * FIXME: Needs doc   */ -void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { -    if ((code >> 3) < KEYBOARD_REPORT_BITS) { -        keyboard_report->nkro.bits[code >> 3] &= ~(1 << (code & 7)); +void del_key_bit(report_nkro_t* nkro_report, uint8_t code) { +    if ((code >> 3) < NKRO_REPORT_BITS) { +        nkro_report->bits[code >> 3] &= ~(1 << (code & 7));      } else {          dprintf("del_key_bit: can't del: %02X\n", code);      } @@ -240,10 +241,10 @@ void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {   *   * FIXME: Needs doc   */ -void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) { +void add_key_to_report(uint8_t key) {  #ifdef NKRO_ENABLE      if (keyboard_protocol && keymap_config.nkro) { -        add_key_bit(keyboard_report, key); +        add_key_bit(nkro_report, key);          return;      }  #endif @@ -254,10 +255,10 @@ void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) {   *   * FIXME: Needs doc   */ -void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) { +void del_key_from_report(uint8_t key) {  #ifdef NKRO_ENABLE      if (keyboard_protocol && keymap_config.nkro) { -        del_key_bit(keyboard_report, key); +        del_key_bit(nkro_report, key);          return;      }  #endif @@ -268,11 +269,11 @@ void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) {   *   * FIXME: Needs doc   */ -void clear_keys_from_report(report_keyboard_t* keyboard_report) { +void clear_keys_from_report(void) {      // not clear mods  #ifdef NKRO_ENABLE      if (keyboard_protocol && keymap_config.nkro) { -        memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits)); +        memset(nkro_report->bits, 0, sizeof(nkro_report->bits));          return;      }  #endif diff --git a/tmk_core/protocol/report.h b/tmk_core/protocol/report.h index 9d415a3bfd..ec985e69ad 100644 --- a/tmk_core/protocol/report.h +++ b/tmk_core/protocol/report.h @@ -20,6 +20,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include <stdint.h>  #include <stdbool.h>  #include "keycode.h" +#include "util.h"  // clang-format off @@ -54,9 +55,9 @@ enum mouse_buttons {   */  enum consumer_usages {      // 15.5 Display Controls -    SNAPSHOT               = 0x065, -    BRIGHTNESS_UP          = 0x06F, // https://www.usb.org/sites/default/files/hutrr41_0.pdf -    BRIGHTNESS_DOWN        = 0x070, +    SNAPSHOT        = 0x065, +    BRIGHTNESS_UP   = 0x06F, // https://www.usb.org/sites/default/files/hutrr41_0.pdf +    BRIGHTNESS_DOWN = 0x070,      // 15.7 Transport Controls      TRANSPORT_RECORD       = 0x0B2,      TRANSPORT_FAST_FORWARD = 0x0B3, @@ -69,43 +70,44 @@ enum consumer_usages {      TRANSPORT_STOP_EJECT   = 0x0CC,      TRANSPORT_PLAY_PAUSE   = 0x0CD,      // 15.9.1 Audio Controls - Volume -    AUDIO_MUTE             = 0x0E2, -    AUDIO_VOL_UP           = 0x0E9, -    AUDIO_VOL_DOWN         = 0x0EA, +    AUDIO_MUTE     = 0x0E2, +    AUDIO_VOL_UP   = 0x0E9, +    AUDIO_VOL_DOWN = 0x0EA,      // 15.15 Application Launch Buttons -    AL_CC_CONFIG           = 0x183, -    AL_EMAIL               = 0x18A, -    AL_CALCULATOR          = 0x192, -    AL_LOCAL_BROWSER       = 0x194, -    AL_LOCK                = 0x19E, -    AL_CONTROL_PANEL       = 0x19F, -    AL_ASSISTANT           = 0x1CB, -    AL_KEYBOARD_LAYOUT     = 0x1AE, +    AL_CC_CONFIG       = 0x183, +    AL_EMAIL           = 0x18A, +    AL_CALCULATOR      = 0x192, +    AL_LOCAL_BROWSER   = 0x194, +    AL_LOCK            = 0x19E, +    AL_CONTROL_PANEL   = 0x19F, +    AL_ASSISTANT       = 0x1CB, +    AL_KEYBOARD_LAYOUT = 0x1AE,      // 15.16 Generic GUI Application Controls -    AC_NEW                 = 0x201, -    AC_OPEN                = 0x202, -    AC_CLOSE               = 0x203, -    AC_EXIT                = 0x204, -    AC_MAXIMIZE            = 0x205, -    AC_MINIMIZE            = 0x206, -    AC_SAVE                = 0x207, -    AC_PRINT               = 0x208, -    AC_PROPERTIES          = 0x209, -    AC_UNDO                = 0x21A, -    AC_COPY                = 0x21B, -    AC_CUT                 = 0x21C, -    AC_PASTE               = 0x21D, -    AC_SELECT_ALL          = 0x21E, -    AC_FIND                = 0x21F, -    AC_SEARCH              = 0x221, -    AC_HOME                = 0x223, -    AC_BACK                = 0x224, -    AC_FORWARD             = 0x225, -    AC_STOP                = 0x226, -    AC_REFRESH             = 0x227, -    AC_BOOKMARKS           = 0x22A, -    AC_MISSION_CONTROL     = 0x29F, -    AC_LAUNCHPAD           = 0x2A0 +    AC_NEW                         = 0x201, +    AC_OPEN                        = 0x202, +    AC_CLOSE                       = 0x203, +    AC_EXIT                        = 0x204, +    AC_MAXIMIZE                    = 0x205, +    AC_MINIMIZE                    = 0x206, +    AC_SAVE                        = 0x207, +    AC_PRINT                       = 0x208, +    AC_PROPERTIES                  = 0x209, +    AC_UNDO                        = 0x21A, +    AC_COPY                        = 0x21B, +    AC_CUT                         = 0x21C, +    AC_PASTE                       = 0x21D, +    AC_SELECT_ALL                  = 0x21E, +    AC_FIND                        = 0x21F, +    AC_SEARCH                      = 0x221, +    AC_HOME                        = 0x223, +    AC_BACK                        = 0x224, +    AC_FORWARD                     = 0x225, +    AC_STOP                        = 0x226, +    AC_REFRESH                     = 0x227, +    AC_BOOKMARKS                   = 0x22A, +    AC_NEXT_KEYBOARD_LAYOUT_SELECT = 0x29D, +    AC_DESKTOP_SHOW_ALL_WINDOWS    = 0x29F, +    AC_SOFT_KEY_LEFT               = 0x2A0  };  /* Generic Desktop Page (0x01) @@ -124,21 +126,7 @@ enum desktop_usages {  // clang-format on -#define NKRO_SHARED_EP -/* key report size(NKRO or boot mode) */ -#if defined(NKRO_ENABLE) -#    if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS) -#        include "protocol/usb_descriptor.h" -#        define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2) -#    elif defined(PROTOCOL_ARM_ATSAM) -#        include "protocol/arm_atsam/usb/udi_device_epsize.h" -#        define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) -#        undef NKRO_SHARED_EP -#        undef MOUSE_SHARED_EP -#    else -#        error "NKRO not supported with this protocol" -#    endif -#endif +#define NKRO_REPORT_BITS 30  #ifdef KEYBOARD_SHARED_EP  #    define KEYBOARD_REPORT_SIZE 9 @@ -172,36 +160,30 @@ extern "C" {   * desc |Lcontrol|Lshift  |Lalt    |Lgui    |Rcontrol|Rshift  |Ralt    |Rgui   *   */ -typedef union { -    uint8_t raw[KEYBOARD_REPORT_SIZE]; -    struct { +typedef struct {  #ifdef KEYBOARD_SHARED_EP -        uint8_t report_id; -#endif -        uint8_t mods; -        uint8_t reserved; -        uint8_t keys[KEYBOARD_REPORT_KEYS]; -    }; -#ifdef NKRO_ENABLE -    struct nkro_report { -#    ifdef NKRO_SHARED_EP -        uint8_t report_id; -#    endif -        uint8_t mods; -        uint8_t bits[KEYBOARD_REPORT_BITS]; -    } nkro; +    uint8_t report_id;  #endif -} __attribute__((packed)) report_keyboard_t; +    uint8_t mods; +    uint8_t reserved; +    uint8_t keys[KEYBOARD_REPORT_KEYS]; +} PACKED report_keyboard_t; + +typedef struct { +    uint8_t report_id; +    uint8_t mods; +    uint8_t bits[NKRO_REPORT_BITS]; +} PACKED report_nkro_t;  typedef struct {      uint8_t  report_id;      uint16_t usage; -} __attribute__((packed)) report_extra_t; +} PACKED report_extra_t;  typedef struct {      uint8_t  report_id;      uint32_t usage; -} __attribute__((packed)) report_programmable_button_t; +} PACKED report_programmable_button_t;  #ifdef MOUSE_EXTENDED_REPORT  typedef int16_t mouse_xy_report_t; @@ -222,7 +204,7 @@ typedef struct {      mouse_xy_report_t y;      int8_t            v;      int8_t            h; -} __attribute__((packed)) report_mouse_t; +} PACKED report_mouse_t;  typedef struct {  #ifdef DIGITIZER_SHARED_EP @@ -234,7 +216,7 @@ typedef struct {      uint8_t  reserved : 5;      uint16_t x;      uint16_t y; -} __attribute__((packed)) report_digitizer_t; +} PACKED report_digitizer_t;  typedef struct {  #ifdef JOYSTICK_SHARED_EP @@ -251,7 +233,7 @@ typedef struct {  #if JOYSTICK_BUTTON_COUNT > 0      uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1];  #endif -} __attribute__((packed)) report_joystick_t; +} PACKED report_joystick_t;  /* keycode to system usage */  static inline uint16_t KEYCODE2SYSTEM(uint8_t key) { @@ -321,28 +303,28 @@ static inline uint16_t KEYCODE2CONSUMER(uint8_t key) {          case KC_WWW_FAVORITES:              return AC_BOOKMARKS;          case KC_MISSION_CONTROL: -            return AC_MISSION_CONTROL; +            return AC_DESKTOP_SHOW_ALL_WINDOWS;          case KC_LAUNCHPAD: -            return AC_LAUNCHPAD; +            return AC_SOFT_KEY_LEFT;          default:              return 0;      }  } -uint8_t has_anykey(report_keyboard_t* keyboard_report); -uint8_t get_first_key(report_keyboard_t* keyboard_report); -bool    is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key); +uint8_t has_anykey(void); +uint8_t get_first_key(void); +bool    is_key_pressed(uint8_t key);  void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code);  void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code);  #ifdef NKRO_ENABLE -void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code); -void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code); +void add_key_bit(report_nkro_t* nkro_report, uint8_t code); +void del_key_bit(report_nkro_t* nkro_report, uint8_t code);  #endif -void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key); -void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key); -void clear_keys_from_report(report_keyboard_t* keyboard_report); +void add_key_to_report(uint8_t key); +void del_key_from_report(uint8_t key); +void clear_keys_from_report(void);  #ifdef MOUSE_ENABLE  bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report); diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index e215c90900..eb214c0492 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -359,10 +359,10 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {          // Keycodes          HID_RI_USAGE_PAGE(8, 0x07),    // Keyboard/Keypad          HID_RI_USAGE_MINIMUM(8, 0x00), -        HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS * 8 - 1), +        HID_RI_USAGE_MAXIMUM(8, NKRO_REPORT_BITS * 8 - 1),          HID_RI_LOGICAL_MINIMUM(8, 0x00),          HID_RI_LOGICAL_MAXIMUM(8, 0x01), -        HID_RI_REPORT_COUNT(8, KEYBOARD_REPORT_BITS * 8), +        HID_RI_REPORT_COUNT(8, NKRO_REPORT_BITS * 8),          HID_RI_REPORT_SIZE(8, 0x01),          HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h index ed84f4c9ab..1268bdae73 100644 --- a/tmk_core/protocol/usb_descriptor.h +++ b/tmk_core/protocol/usb_descriptor.h @@ -299,7 +299,7 @@ enum usb_endpoints {  #define KEYBOARD_EPSIZE 8  #define SHARED_EPSIZE 32 -#define MOUSE_EPSIZE 8 +#define MOUSE_EPSIZE 16  #define RAW_EPSIZE 32  #define CONSOLE_EPSIZE 32  #define MIDI_STREAM_EPSIZE 64 diff --git a/tmk_core/protocol/usb_types.h b/tmk_core/protocol/usb_types.h new file mode 100644 index 0000000000..019775a1c4 --- /dev/null +++ b/tmk_core/protocol/usb_types.h @@ -0,0 +1,23 @@ +// Copyright 2023 Stefan Kerkmann +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "util.h" + +/** + * @brief Common USB 2.0 control request structure + */ +typedef struct { +    uint8_t bmRequestType; // [0] (Bitmask) +    uint8_t bRequest;      // [1] +    union { +        struct { +            uint8_t lbyte; // [2] (LSB) +            uint8_t hbyte; // [3] (MSB) +        }; +        uint16_t word; // [2,3] (LSB,MSB) +    } wValue; +    uint16_t wIndex;  // [4,5] (LSB,MSB) +    uint16_t wLength; // [6,7] (LSB,MSB) +} PACKED usb_control_request_t; diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index d74f375f66..3502d9e644 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -48,16 +48,14 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #    include "os_detection.h"  #endif -#define NEXT_INTERFACE __COUNTER__ -  /*   * Interface indexes   */  enum usb_interfaces {  #ifndef KEYBOARD_SHARED_EP -    KEYBOARD_INTERFACE = NEXT_INTERFACE, +    KEYBOARD_INTERFACE,  #else -    SHARED_INTERFACE = NEXT_INTERFACE, +    SHARED_INTERFACE,  #    define KEYBOARD_INTERFACE SHARED_INTERFACE  #endif @@ -65,32 +63,31 @@ enum usb_interfaces {  // interface number, to support Linux/OSX platforms and chrome.hid  // If Raw HID is enabled, let it be always 1.  #ifdef RAW_ENABLE -    RAW_INTERFACE = NEXT_INTERFACE, +    RAW_INTERFACE,  #endif  #if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP) -    SHARED_INTERFACE = NEXT_INTERFACE, +    SHARED_INTERFACE,  #endif  #ifdef CONSOLE_ENABLE -    CONSOLE_INTERFACE = NEXT_INTERFACE, +    CONSOLE_INTERFACE,  #endif -    TOTAL_INTERFACES = NEXT_INTERFACE +    TOTAL_INTERFACES  };  #define MAX_INTERFACES 3 -#if (NEXT_INTERFACE - 1) > MAX_INTERFACES -#    error There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console -#endif +_Static_assert(TOTAL_INTERFACES <= MAX_INTERFACES, "There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console.");  #if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)) && CONSOLE_ENABLE  #    error Mouse/Extra Keys share an endpoint with Console. Please disable one of the two.  #endif  static uint8_t keyboard_led_state = 0; -static uint8_t vusb_idle_rate     = 0; +uint8_t        keyboard_idle      = 0; +uint8_t        keyboard_protocol  = 1;  /* Keyboard report send buffer */  #define KBUF_SIZE 16 @@ -231,10 +228,11 @@ void console_task(void) {   *------------------------------------------------------------------*/  static uint8_t keyboard_leds(void);  static void    send_keyboard(report_keyboard_t *report); +static void    send_nkro(report_nkro_t *report);  static void    send_mouse(report_mouse_t *report);  static void    send_extra(report_extra_t *report); -static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_extra}; +static host_driver_t driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};  host_driver_t *vusb_driver(void) {      return &driver; @@ -259,6 +257,10 @@ static void send_keyboard(report_keyboard_t *report) {      keyboard_report_sent = *report;  } +static void send_nkro(report_nkro_t *report) { +    // TODO: Implement NKRO +} +  #ifndef KEYBOARD_SHARED_EP  #    define usbInterruptIsReadyShared usbInterruptIsReady3  #    define usbSetInterruptShared usbSetInterrupt3 @@ -319,30 +321,44 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) {      usbRequest_t *rq = (void *)data;      if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) { /* class request type */ -        if (rq->bRequest == USBRQ_HID_GET_REPORT) { -            dprint("GET_REPORT:"); -            if (rq->wIndex.word == KEYBOARD_INTERFACE) { -                usbMsgPtr = (usbMsgPtr_t)&keyboard_report_sent; -                return sizeof(keyboard_report_sent); -            } -        } else if (rq->bRequest == USBRQ_HID_GET_IDLE) { -            dprint("GET_IDLE:"); -            usbMsgPtr = (usbMsgPtr_t)&vusb_idle_rate; -            return 1; -        } else if (rq->bRequest == USBRQ_HID_SET_IDLE) { -            vusb_idle_rate = rq->wValue.bytes[1]; -            dprintf("SET_IDLE: %02X", vusb_idle_rate); -        } else if (rq->bRequest == USBRQ_HID_SET_REPORT) { -            dprint("SET_REPORT:"); -            // Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard) -            if (rq->wValue.word == 0x0200 && rq->wIndex.word == KEYBOARD_INTERFACE) { -                dprint("SET_LED:"); -                last_req.kind = SET_LED; -                last_req.len  = rq->wLength.word; -            } -            return USB_NO_MSG; // to get data in usbFunctionWrite -        } else { -            dprint("UNKNOWN:"); +        switch (rq->bRequest) { +            case USBRQ_HID_GET_REPORT: +                dprint("GET_REPORT:"); +                if (rq->wIndex.word == KEYBOARD_INTERFACE) { +                    usbMsgPtr = (usbMsgPtr_t)&keyboard_report_sent; +                    return sizeof(keyboard_report_sent); +                } +                break; +            case USBRQ_HID_GET_IDLE: +                dprint("GET_IDLE:"); +                usbMsgPtr = (usbMsgPtr_t)&keyboard_idle; +                return 1; +            case USBRQ_HID_GET_PROTOCOL: +                dprint("GET_PROTOCOL:"); +                usbMsgPtr = (usbMsgPtr_t)&keyboard_protocol; +                return 1; +            case USBRQ_HID_SET_REPORT: +                dprint("SET_REPORT:"); +                // Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard) +                if (rq->wValue.word == 0x0200 && rq->wIndex.word == KEYBOARD_INTERFACE) { +                    dprint("SET_LED:"); +                    last_req.kind = SET_LED; +                    last_req.len  = rq->wLength.word; +                } +                return USB_NO_MSG; // to get data in usbFunctionWrite +            case USBRQ_HID_SET_IDLE: +                keyboard_idle = (rq->wValue.word & 0xFF00) >> 8; +                dprintf("SET_IDLE: %02X", keyboard_idle); +                break; +            case USBRQ_HID_SET_PROTOCOL: +                if (rq->wIndex.word == KEYBOARD_INTERFACE) { +                    keyboard_protocol = rq->wValue.word & 0xFF; +                    dprintf("SET_PROTOCOL: %02X", keyboard_protocol); +                } +                break; +            default: +                dprint("UNKNOWN:"); +                break;          }      } else {          dprint("VENDOR:"); @@ -1024,7 +1040,7 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {  #endif              break;          case USBDESCR_HID: -            switch (rq->wValue.bytes[0]) { +            switch (rq->wIndex.word) {  #ifndef KEYBOARD_SHARED_EP                  case KEYBOARD_INTERFACE:                      usbMsgPtr = (usbMsgPtr_t)&usbConfigurationDescriptor.keyboardHID;  | 
