Merge remote-tracking branch 'origin/develop' into xap

This commit is contained in:
zvecr
2023-11-01 01:19:30 +00:00
223 changed files with 5317 additions and 1244 deletions
+59 -92
View File
@@ -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"
@@ -107,30 +108,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;
}
/*
@@ -512,8 +501,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:
@@ -585,16 +573,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
*
@@ -611,7 +589,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];
@@ -621,24 +601,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);
@@ -654,59 +626,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 */
@@ -719,12 +686,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 */
@@ -735,19 +701,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++) {
@@ -757,10 +725,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++) {
@@ -773,7 +740,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 */
};
+41 -40
View File
@@ -55,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,
@@ -70,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)
@@ -302,9 +303,9 @@ 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;
}
+23
View File
@@ -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;
+13 -17
View File
@@ -53,16 +53,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
@@ -70,36 +68,34 @@ 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
#ifdef XAP_ENABLE
XAP_INTERFACE = NEXT_INTERFACE,
XAP_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 */
@@ -423,7 +419,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) {
break;
case USBRQ_HID_GET_IDLE:
dprint("GET_IDLE:");
usbMsgPtr = (usbMsgPtr_t)&vusb_idle_rate;
usbMsgPtr = (usbMsgPtr_t)&keyboard_idle;
return 1;
case USBRQ_HID_GET_PROTOCOL:
dprint("GET_PROTOCOL:");
@@ -439,8 +435,8 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) {
}
return USB_NO_MSG; // to get data in usbFunctionWrite
case USBRQ_HID_SET_IDLE:
vusb_idle_rate = rq->wValue.bytes[1];
dprintf("SET_IDLE: %02X", vusb_idle_rate);
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) {
@@ -1223,7 +1219,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;