diff options
Diffstat (limited to 'tmk_core')
| -rw-r--r-- | tmk_core/protocol/chibios/usb_main.c | 151 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_types.h | 23 |
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 | */ | ||
| 119 | static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) { | 107 | static 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? */ | ||
| 502 | static void usb_event_cb(USBDriver *usbp, usbevent_t event) { | 490 | static 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 */ | ||
| 575 | static 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) { | |||
| 596 | static uint8_t set_report_buf[2] __attribute__((aligned(4))); | 574 | static uint8_t set_report_buf[2] __attribute__((aligned(4))); |
| 597 | 575 | ||
| 598 | static void set_led_transfer_cb(USBDriver *usbp) { | 576 | static 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) */ | 589 | static bool usb_requests_hook_cb(USBDriver *usbp) { |
| 610 | static 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 */ | ||
| 749 | static void usb_sof_cb(USBDriver *usbp) { | 716 | static 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) { | |||
| 758 | static const USBConfig usbcfg = { | 725 | static 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 | */ | ||
| 11 | typedef 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; | ||
