summaryrefslogtreecommitdiff
path: root/tmk_core
diff options
context:
space:
mode:
authorStefan Kerkmann <karlk90@pm.me>2023-10-27 18:44:58 +0200
committerGitHub <noreply@github.com>2023-10-27 18:44:58 +0200
commit5856d5e13b1f59187f1a73d1bda8075cba7daaa8 (patch)
tree3914fbaf702c268ea1348b3bb3c8269f4983cdde /tmk_core
parent64d1ce751fa455a9918e7b93a18dde9479beba2f (diff)
[Maintenance] USB HID control packet as struct (#21688)
* ChibiOS: USB HID control request as dedicated struct Instead of accessing the raw USB setup packet and documenting the values as the corresponding USB HID control request fields we introduce a struct that allows direct access to the fields. This is safer and self documenting. * Rename usb_request.h to usb_types.h In the future all shared USB data types can live in this file.
Diffstat (limited to 'tmk_core')
-rw-r--r--tmk_core/protocol/chibios/usb_main.c151
-rw-r--r--tmk_core/protocol/usb_types.h23
2 files changed, 82 insertions, 92 deletions
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index f2158fd009..66f9ad0318 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -43,6 +43,7 @@
43#include "usb_device_state.h" 43#include "usb_device_state.h"
44#include "usb_descriptor.h" 44#include "usb_descriptor.h"
45#include "usb_driver.h" 45#include "usb_driver.h"
46#include "usb_types.h"
46 47
47#ifdef NKRO_ENABLE 48#ifdef NKRO_ENABLE
48# include "keycode_config.h" 49# include "keycode_config.h"
@@ -103,30 +104,18 @@ union {
103 NULL, /* SETUP buffer (not a SETUP endpoint) */ 104 NULL, /* SETUP buffer (not a SETUP endpoint) */
104#endif 105#endif
105 106
106/* HID specific constants */
107#define HID_GET_REPORT 0x01
108#define HID_GET_IDLE 0x02
109#define HID_GET_PROTOCOL 0x03
110#define HID_SET_REPORT 0x09
111#define HID_SET_IDLE 0x0A
112#define HID_SET_PROTOCOL 0x0B
113
114/*
115 * Handles the GET_DESCRIPTOR callback
116 *
117 * Returns the proper descriptor
118 */
119static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) { 107static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) {
120 (void)usbp; 108 usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;
121 static USBDescriptor desc; 109
122 uint16_t wValue = ((uint16_t)dtype << 8) | dindex; 110 static USBDescriptor descriptor;
123 uint16_t wLength = ((uint16_t)usbp->setup[7] << 8) | usbp->setup[6]; 111 descriptor.ud_string = NULL;
124 desc.ud_string = NULL; 112 descriptor.ud_size = get_usb_descriptor(setup->wValue.word, setup->wIndex, setup->wLength, (const void **const) & descriptor.ud_string);
125 desc.ud_size = get_usb_descriptor(wValue, wIndex, wLength, (const void **const) & desc.ud_string); 113
126 if (desc.ud_string == NULL) 114 if (descriptor.ud_string == NULL) {
127 return NULL; 115 return NULL;
128 else 116 }
129 return &desc; 117
118 return &descriptor;
130} 119}
131 120
132/* 121/*
@@ -497,8 +486,7 @@ void usb_event_queue_task(void) {
497 } 486 }
498} 487}
499 488
500/* Handles the USB driver global events 489/* Handles the USB driver global events. */
501 * TODO: maybe disable some things when connection is lost? */
502static void usb_event_cb(USBDriver *usbp, usbevent_t event) { 490static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
503 switch (event) { 491 switch (event) {
504 case USB_EVENT_ADDRESS: 492 case USB_EVENT_ADDRESS:
@@ -570,16 +558,6 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
570 } 558 }
571} 559}
572 560
573/* Function used locally in os/hal/src/usb.c for getting descriptors
574 * need it here for HID descriptor */
575static uint16_t get_hword(uint8_t *p) {
576 uint16_t hw;
577
578 hw = (uint16_t)*p++;
579 hw |= (uint16_t)*p << 8U;
580 return hw;
581}
582
583/* 561/*
584 * Appendix G: HID Request Support Requirements 562 * Appendix G: HID Request Support Requirements
585 * 563 *
@@ -596,7 +574,9 @@ static uint16_t get_hword(uint8_t *p) {
596static uint8_t set_report_buf[2] __attribute__((aligned(4))); 574static uint8_t set_report_buf[2] __attribute__((aligned(4)));
597 575
598static void set_led_transfer_cb(USBDriver *usbp) { 576static void set_led_transfer_cb(USBDriver *usbp) {
599 if (usbp->setup[6] == 2) { /* LSB(wLength) */ 577 usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;
578
579 if (setup->wLength == 2) {
600 uint8_t report_id = set_report_buf[0]; 580 uint8_t report_id = set_report_buf[0];
601 if ((report_id == REPORT_ID_KEYBOARD) || (report_id == REPORT_ID_NKRO)) { 581 if ((report_id == REPORT_ID_KEYBOARD) || (report_id == REPORT_ID_NKRO)) {
602 keyboard_led_state = set_report_buf[1]; 582 keyboard_led_state = set_report_buf[1];
@@ -606,24 +586,16 @@ static void set_led_transfer_cb(USBDriver *usbp) {
606 } 586 }
607} 587}
608 588
609/* Callback for SETUP request on the endpoint 0 (control) */ 589static bool usb_requests_hook_cb(USBDriver *usbp) {
610static bool usb_request_hook_cb(USBDriver *usbp) { 590 usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;
611 const USBDescriptor *dp;
612
613 /* usbp->setup fields:
614 * 0: bmRequestType (bitmask)
615 * 1: bRequest
616 * 2,3: (LSB,MSB) wValue
617 * 4,5: (LSB,MSB) wIndex
618 * 6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
619 591
620 /* Handle HID class specific requests */ 592 /* Handle HID class specific requests */
621 if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) && ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) { 593 if ((setup->bmRequestType & (USB_RTYPE_TYPE_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_TYPE_CLASS | USB_RTYPE_RECIPIENT_INTERFACE)) {
622 switch (usbp->setup[0] & USB_RTYPE_DIR_MASK) { 594 switch (setup->bmRequestType & USB_RTYPE_DIR_MASK) {
623 case USB_RTYPE_DIR_DEV2HOST: 595 case USB_RTYPE_DIR_DEV2HOST:
624 switch (usbp->setup[1]) { /* bRequest */ 596 switch (setup->bRequest) {
625 case HID_GET_REPORT: 597 case HID_REQ_GetReport:
626 switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */ 598 switch (setup->wIndex) {
627#ifndef KEYBOARD_SHARED_EP 599#ifndef KEYBOARD_SHARED_EP
628 case KEYBOARD_INTERFACE: 600 case KEYBOARD_INTERFACE:
629 usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL); 601 usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL);
@@ -639,59 +611,54 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
639#ifdef SHARED_EP_ENABLE 611#ifdef SHARED_EP_ENABLE
640 case SHARED_INTERFACE: 612 case SHARED_INTERFACE:
641# ifdef KEYBOARD_SHARED_EP 613# ifdef KEYBOARD_SHARED_EP
642 if (usbp->setup[2] == REPORT_ID_KEYBOARD) { 614 if (setup->wValue.lbyte == REPORT_ID_KEYBOARD) {
643 usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL); 615 usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL);
644 return TRUE; 616 return true;
645 break;
646 } 617 }
647# endif 618# endif
648# ifdef MOUSE_SHARED_EP 619# ifdef MOUSE_SHARED_EP
649 if (usbp->setup[2] == REPORT_ID_MOUSE) { 620 if (setup->wValue.lbyte == REPORT_ID_MOUSE) {
650 usbSetupTransfer(usbp, (uint8_t *)&mouse_report_sent, sizeof(mouse_report_sent), NULL); 621 usbSetupTransfer(usbp, (uint8_t *)&mouse_report_sent, sizeof(mouse_report_sent), NULL);
651 return TRUE; 622 return true;
652 break;
653 } 623 }
654# endif 624# endif
655#endif /* SHARED_EP_ENABLE */ 625#endif /* SHARED_EP_ENABLE */
656 default: 626 default:
657 universal_report_blank.report_id = usbp->setup[2]; 627 universal_report_blank.report_id = setup->wValue.lbyte;
658 usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, usbp->setup[6], NULL); 628 usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, setup->wLength, NULL);
659 return TRUE; 629 return true;
660 break;
661 } 630 }
662 break; 631 break;
663 632
664 case HID_GET_PROTOCOL: 633 case HID_REQ_GetProtocol:
665 if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */ 634 if (setup->wIndex == KEYBOARD_INTERFACE) {
666 usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL); 635 usbSetupTransfer(usbp, &keyboard_protocol, sizeof(uint8_t), NULL);
667 return TRUE; 636 return true;
668 } 637 }
669 break; 638 break;
670 639
671 case HID_GET_IDLE: 640 case HID_REQ_GetIdle:
672 usbSetupTransfer(usbp, &keyboard_idle, 1, NULL); 641 usbSetupTransfer(usbp, &keyboard_idle, sizeof(uint8_t), NULL);
673 return TRUE; 642 return true;
674 break;
675 } 643 }
676 break; 644 break;
677 645
678 case USB_RTYPE_DIR_HOST2DEV: 646 case USB_RTYPE_DIR_HOST2DEV:
679 switch (usbp->setup[1]) { /* bRequest */ 647 switch (setup->bRequest) {
680 case HID_SET_REPORT: 648 case HID_REQ_SetReport:
681 switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */ 649 switch (setup->wIndex) {
682 case KEYBOARD_INTERFACE: 650 case KEYBOARD_INTERFACE:
683#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP) 651#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
684 case SHARED_INTERFACE: 652 case SHARED_INTERFACE:
685#endif 653#endif
686 usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb); 654 usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
687 return TRUE; 655 return true;
688 break;
689 } 656 }
690 break; 657 break;
691 658
692 case HID_SET_PROTOCOL: 659 case HID_REQ_SetProtocol:
693 if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */ 660 if (setup->wIndex == KEYBOARD_INTERFACE) {
694 keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */ 661 keyboard_protocol = setup->wValue.word;
695#ifdef NKRO_ENABLE 662#ifdef NKRO_ENABLE
696 if (!keyboard_protocol && keyboard_idle) { 663 if (!keyboard_protocol && keyboard_idle) {
697#else /* NKRO_ENABLE */ 664#else /* NKRO_ENABLE */
@@ -704,12 +671,11 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
704 } 671 }
705 } 672 }
706 usbSetupTransfer(usbp, NULL, 0, NULL); 673 usbSetupTransfer(usbp, NULL, 0, NULL);
707 return TRUE; 674 return true;
708 break;
709 675
710 case HID_SET_IDLE: 676 case HID_REQ_SetIdle:
711 keyboard_idle = usbp->setup[3]; /* MSB(wValue) */ 677 keyboard_idle = setup->wValue.hbyte;
712 /* arm the timer */ 678 /* arm the timer */
713#ifdef NKRO_ENABLE 679#ifdef NKRO_ENABLE
714 if (!keymap_config.nkro && keyboard_idle) { 680 if (!keymap_config.nkro && keyboard_idle) {
715#else /* NKRO_ENABLE */ 681#else /* NKRO_ENABLE */
@@ -720,19 +686,21 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
720 osalSysUnlockFromISR(); 686 osalSysUnlockFromISR();
721 } 687 }
722 usbSetupTransfer(usbp, NULL, 0, NULL); 688 usbSetupTransfer(usbp, NULL, 0, NULL);
723 return TRUE; 689 return true;
724 break;
725 } 690 }
726 break; 691 break;
727 } 692 }
728 } 693 }
729 694
730 /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */ 695 /* Handle the Get_Descriptor Request for HID class, which is not handled by
731 if ((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) { 696 * the ChibiOS USB driver */
732 dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4])); 697 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)) {
733 if (dp == NULL) return FALSE; 698 const USBDescriptor *descriptor = usbp->config->get_descriptor_cb(usbp, setup->wValue.lbyte, setup->wValue.hbyte, setup->wIndex);
734 usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL); 699 if (descriptor == NULL) {
735 return TRUE; 700 return false;
701 }
702 usbSetupTransfer(usbp, (uint8_t *)descriptor->ud_string, descriptor->ud_size, NULL);
703 return true;
736 } 704 }
737 705
738 for (int i = 0; i < NUM_USB_DRIVERS; i++) { 706 for (int i = 0; i < NUM_USB_DRIVERS; i++) {
@@ -742,10 +710,9 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
742 } 710 }
743 } 711 }
744 712
745 return FALSE; 713 return false;
746} 714}
747 715
748/* Start-of-frame callback */
749static void usb_sof_cb(USBDriver *usbp) { 716static void usb_sof_cb(USBDriver *usbp) {
750 osalSysLockFromISR(); 717 osalSysLockFromISR();
751 for (int i = 0; i < NUM_USB_DRIVERS; i++) { 718 for (int i = 0; i < NUM_USB_DRIVERS; i++) {
@@ -758,7 +725,7 @@ static void usb_sof_cb(USBDriver *usbp) {
758static const USBConfig usbcfg = { 725static const USBConfig usbcfg = {
759 usb_event_cb, /* USB events callback */ 726 usb_event_cb, /* USB events callback */
760 usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */ 727 usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */
761 usb_request_hook_cb, /* Requests hook callback */ 728 usb_requests_hook_cb, /* Requests hook callback */
762 usb_sof_cb /* Start Of Frame callback */ 729 usb_sof_cb /* Start Of Frame callback */
763}; 730};
764 731
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 @@
1// Copyright 2023 Stefan Kerkmann
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "util.h"
7
8/**
9 * @brief Common USB 2.0 control request structure
10 */
11typedef struct {
12 uint8_t bmRequestType; // [0] (Bitmask)
13 uint8_t bRequest; // [1]
14 union {
15 struct {
16 uint8_t lbyte; // [2] (LSB)
17 uint8_t hbyte; // [3] (MSB)
18 };
19 uint16_t word; // [2,3] (LSB,MSB)
20 } wValue;
21 uint16_t wIndex; // [4,5] (LSB,MSB)
22 uint16_t wLength; // [6,7] (LSB,MSB)
23} PACKED usb_control_request_t;