diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index f62b9258173..3d01be82057 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -643,6 +643,11 @@ ifeq ($(strip $(VIA_ENABLE)), yes) TRI_LAYER_ENABLE := yes endif +ifeq ($(strip $(RAW_ENABLE)), yes) + OPT_DEFS += -DRAW_ENABLE + SRC += raw_hid.c +endif + ifeq ($(strip $(DYNAMIC_KEYMAP_ENABLE)), yes) SEND_STRING_ENABLE := yes endif diff --git a/drivers/bluetooth/bluetooth.c b/drivers/bluetooth/bluetooth.c index 61a3f0f32a4..e61e24e1f22 100644 --- a/drivers/bluetooth/bluetooth.c +++ b/drivers/bluetooth/bluetooth.c @@ -28,3 +28,5 @@ __attribute__((weak)) void bluetooth_send_mouse(report_mouse_t *report) {} __attribute__((weak)) void bluetooth_send_consumer(uint16_t usage) {} __attribute__((weak)) void bluetooth_send_system(uint16_t usage) {} + +__attribute__((weak)) void bluetooth_send_raw_hid(uint8_t *data, uint8_t length) {} diff --git a/drivers/bluetooth/bluetooth.h b/drivers/bluetooth/bluetooth.h index e50b588db2f..bbd41a91943 100644 --- a/drivers/bluetooth/bluetooth.h +++ b/drivers/bluetooth/bluetooth.h @@ -81,3 +81,11 @@ void bluetooth_send_consumer(uint16_t usage); * \param usage The system usage to send. */ void bluetooth_send_system(uint16_t usage); + +/** + * \brief Send a raw_hid packet. + * + * \param data A pointer to the buffer to be sent. Always 32 bytes in length. + * \param length The length of the buffer. Always 32. + */ +void bluetooth_send_raw_hid(uint8_t *data, uint8_t length); diff --git a/quantum/raw_hid.c b/quantum/raw_hid.c new file mode 100644 index 00000000000..2c7a75f325d --- /dev/null +++ b/quantum/raw_hid.c @@ -0,0 +1,15 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "raw_hid.h" +#include "host.h" + +void raw_hid_send(uint8_t *data, uint8_t length) { + host_raw_hid_send(data, length); +} + +__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { + // Users should #include "raw_hid.h" in their own code + // and implement this function there. Leave this as weak linkage + // so users can opt to not handle data coming in. +} diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index 2930efc2833..81520c1bc81 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk @@ -33,10 +33,6 @@ ifeq ($(strip $(PROGRAMMABLE_BUTTON_ENABLE)), yes) SHARED_EP_ENABLE = yes endif -ifeq ($(strip $(RAW_ENABLE)), yes) - OPT_DEFS += -DRAW_ENABLE -endif - ifeq ($(strip $(CONSOLE_ENABLE)), yes) OPT_DEFS += -DCONSOLE_ENABLE else diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c index d752f3746b0..19d8121e349 100644 --- a/tmk_core/protocol/chibios/chibios.c +++ b/tmk_core/protocol/chibios/chibios.c @@ -66,9 +66,19 @@ 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); +void send_raw_hid(uint8_t *data, uint8_t length); /* host struct */ -host_driver_t chibios_driver = {.keyboard_leds = usb_device_state_get_leds, .send_keyboard = send_keyboard, .send_nkro = send_nkro, .send_mouse = send_mouse, .send_extra = send_extra}; +host_driver_t chibios_driver = { + .keyboard_leds = usb_device_state_get_leds, + .send_keyboard = send_keyboard, + .send_nkro = send_nkro, + .send_mouse = send_mouse, + .send_extra = send_extra, +#ifdef RAW_ENABLE + .send_raw_hid = send_raw_hid, +#endif +}; #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 5a5354416f4..f9d7f5c4d64 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -32,6 +32,10 @@ #include "usb_driver.h" #include "usb_types.h" +#ifdef RAW_ENABLE +# include "raw_hid.h" +#endif + #ifdef NKRO_ENABLE # include "keycode_config.h" @@ -515,19 +519,13 @@ void console_task(void) { #endif /* CONSOLE_ENABLE */ #ifdef RAW_ENABLE -void raw_hid_send(uint8_t *data, uint8_t length) { +void send_raw_hid(uint8_t *data, uint8_t length) { if (length != RAW_EPSIZE) { return; } send_report(USB_ENDPOINT_IN_RAW, data, length); } -__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { - // Users should #include "raw_hid.h" in their own code - // and implement this function there. Leave this as weak linkage - // so users can opt to not handle data coming in. -} - void raw_hid_task(void) { uint8_t buffer[RAW_EPSIZE]; while (receive_report(USB_ENDPOINT_OUT_RAW, buffer, sizeof(buffer))) { diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c index e785cb24cc6..4874d7c1d36 100644 --- a/tmk_core/protocol/host.c +++ b/tmk_core/protocol/host.c @@ -55,6 +55,9 @@ host_driver_t bt_driver = { .send_nkro = bluetooth_send_nkro, .send_mouse = bluetooth_send_mouse, .send_extra = bluetooth_send_extra, +# ifdef RAW_ENABLE + .send_raw_hid = bluetooth_send_raw_hid, +# endif }; #endif @@ -299,6 +302,15 @@ void host_programmable_button_send(uint32_t data) { __attribute__((weak)) void send_programmable_button(report_programmable_button_t *report) {} +#ifdef RAW_ENABLE +void host_raw_hid_send(uint8_t *data, uint8_t length) { + host_driver_t *driver = host_get_active_driver(); + if (!driver || !driver->send_raw_hid) return; + + (*driver->send_raw_hid)(data, length); +} +#endif + uint16_t host_last_system_usage(void) { return last_system_usage; } diff --git a/tmk_core/protocol/host.h b/tmk_core/protocol/host.h index 8e8a18e2ed3..a0b1e73dccc 100644 --- a/tmk_core/protocol/host.h +++ b/tmk_core/protocol/host.h @@ -41,6 +41,7 @@ void host_mouse_send(report_mouse_t *report); void host_system_send(uint16_t usage); void host_consumer_send(uint16_t usage); void host_programmable_button_send(uint32_t data); +void host_raw_hid_send(uint8_t *data, uint8_t length); uint16_t host_last_system_usage(void); uint16_t host_last_consumer_usage(void); diff --git a/tmk_core/protocol/host_driver.h b/tmk_core/protocol/host_driver.h index 8aa38b6dee2..c2835aaa99f 100644 --- a/tmk_core/protocol/host_driver.h +++ b/tmk_core/protocol/host_driver.h @@ -29,6 +29,9 @@ typedef struct { void (*send_nkro)(report_nkro_t *); void (*send_mouse)(report_mouse_t *); void (*send_extra)(report_extra_t *); +#ifdef RAW_ENABLE + void (*send_raw_hid)(uint8_t *, uint8_t); +#endif } host_driver_t; void send_joystick(report_joystick_t *report); diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 81da035f0c0..d59468133c4 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -75,11 +75,24 @@ static report_keyboard_t keyboard_report_sent; /* Host driver */ -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 = usb_device_state_get_leds, .send_keyboard = send_keyboard, .send_nkro = send_nkro, .send_mouse = send_mouse, .send_extra = send_extra}; +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); +#ifdef RAW_ENABLE +static void send_raw_hid(uint8_t *data, uint8_t length); +#endif + +host_driver_t lufa_driver = { + .keyboard_leds = usb_device_state_get_leds, + .send_keyboard = send_keyboard, + .send_nkro = send_nkro, + .send_mouse = send_mouse, + .send_extra = send_extra, +#ifdef RAW_ENABLE + .send_raw_hid = send_raw_hid, +#endif +}; void send_report(uint8_t endpoint, void *report, size_t size) { uint8_t timeout = 255; @@ -131,21 +144,11 @@ USB_ClassInfo_CDC_Device_t cdc_device = { * * FIXME: Needs doc */ -void raw_hid_send(uint8_t *data, uint8_t length) { +static void send_raw_hid(uint8_t *data, uint8_t length) { if (length != RAW_EPSIZE) return; send_report(RAW_IN_EPNUM, data, RAW_EPSIZE); } -/** \brief Raw HID Receive - * - * FIXME: Needs doc - */ -__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { - // Users should #include "raw_hid.h" in their own code - // and implement this function there. Leave this as weak linkage - // so users can opt to not handle data coming in. -} - /** \brief Raw HID Task * * FIXME: Needs doc diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 56cf82e5a67..43cce6eb2fc 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -144,7 +144,7 @@ static void send_report(uint8_t endpoint, void *report, size_t size) { static uint8_t raw_output_buffer[RAW_BUFFER_SIZE]; static uint8_t raw_output_received_bytes = 0; -void raw_hid_send(uint8_t *data, uint8_t length) { +static void send_raw_hid(uint8_t *data, uint8_t length) { if (length != RAW_BUFFER_SIZE) { return; } @@ -152,12 +152,6 @@ void raw_hid_send(uint8_t *data, uint8_t length) { send_report(4, data, 32); } -__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { - // Users should #include "raw_hid.h" in their own code - // and implement this function there. Leave this as weak linkage - // so users can opt to not handle data coming in. -} - void raw_hid_task(void) { usbPoll(); @@ -213,8 +207,20 @@ 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); +#ifdef RAW_ENABLE +static void send_raw_hid(uint8_t *data, uint8_t length); +#endif -static host_driver_t driver = {.keyboard_leds = usb_device_state_get_leds, .send_keyboard = send_keyboard, .send_nkro = send_nkro, .send_mouse = send_mouse, .send_extra = send_extra}; +static host_driver_t driver = { + .keyboard_leds = usb_device_state_get_leds, + .send_keyboard = send_keyboard, + .send_nkro = send_nkro, + .send_mouse = send_mouse, + .send_extra = send_extra, +#ifdef RAW_ENABLE + .send_raw_hid = send_raw_hid, +#endif +}; host_driver_t *vusb_driver(void) { return &driver;