diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index 5d007e099d4..f62b9258173 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -898,16 +898,17 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) NO_USB_STARTUP_CHECK := yes CONNECTION_ENABLE := yes COMMON_VPATH += $(DRIVER_PATH)/bluetooth + SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c ifeq ($(strip $(BLUETOOTH_DRIVER)), bluefruit_le) SPI_DRIVER_REQUIRED = yes - SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c + SRC += $(DRIVER_PATH)/bluetooth/bluetooth_drivers.c SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp endif ifeq ($(strip $(BLUETOOTH_DRIVER)), rn42) UART_DRIVER_REQUIRED = yes - SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c + SRC += $(DRIVER_PATH)/bluetooth/bluetooth_drivers.c SRC += $(DRIVER_PATH)/bluetooth/rn42.c endif endif diff --git a/drivers/bluetooth/bluetooth.c b/drivers/bluetooth/bluetooth.c index d5382401e7e..3d41d8b11cd 100644 --- a/drivers/bluetooth/bluetooth.c +++ b/drivers/bluetooth/bluetooth.c @@ -1,62 +1,26 @@ -/* - * Copyright 2022 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later #include "bluetooth.h" -#if defined(BLUETOOTH_BLUEFRUIT_LE) -# include "bluefruit_le.h" -#elif defined(BLUETOOTH_RN42) -# include "rn42.h" -#endif +__attribute__((weak)) void bluetooth_init(void) {} -void bluetooth_init(void) { -#if defined(BLUETOOTH_BLUEFRUIT_LE) - bluefruit_le_init(); -#elif defined(BLUETOOTH_RN42) - rn42_init(); -#endif +__attribute__((weak)) void bluetooth_task(void) {} + +__attribute__((weak)) bool bluetooth_is_connected(void) { + return true; } -void bluetooth_task(void) { -#if defined(BLUETOOTH_BLUEFRUIT_LE) - bluefruit_le_task(); -#endif +__attribute__((weak)) uint8_t bluetooth_keyboard_leds(void) { + return 0; } -void bluetooth_send_keyboard(report_keyboard_t *report) { -#if defined(BLUETOOTH_BLUEFRUIT_LE) - bluefruit_le_send_keyboard(report); -#elif defined(BLUETOOTH_RN42) - rn42_send_keyboard(report); -#endif -} +__attribute__((weak)) void bluetooth_send_keyboard(report_keyboard_t *report) {} -void bluetooth_send_mouse(report_mouse_t *report) { -#if defined(BLUETOOTH_BLUEFRUIT_LE) - bluefruit_le_send_mouse(report); -#elif defined(BLUETOOTH_RN42) - rn42_send_mouse(report); -#endif -} +__attribute__((weak)) void bluetooth_send_nkro(report_nkro_t *report) {} -void bluetooth_send_consumer(uint16_t usage) { -#if defined(BLUETOOTH_BLUEFRUIT_LE) - bluefruit_le_send_consumer(usage); -#elif defined(BLUETOOTH_RN42) - rn42_send_consumer(usage); -#endif -} +__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) {} diff --git a/drivers/bluetooth/bluetooth.h b/drivers/bluetooth/bluetooth.h index 2e4d0df5381..fe67c0c968f 100644 --- a/drivers/bluetooth/bluetooth.h +++ b/drivers/bluetooth/bluetooth.h @@ -30,6 +30,18 @@ void bluetooth_init(void); */ void bluetooth_task(void); +/** + * \brief Detects if Bluetooth is connected. + * + * \return `true` if connected, `false` otherwise. + */ +bool bluetooth_is_connected(void); + +/** + * \brief Get current LED state. + */ +uint8_t bluetooth_keyboard_leds(void); + /** * \brief Send a keyboard report. * @@ -37,6 +49,13 @@ void bluetooth_task(void); */ void bluetooth_send_keyboard(report_keyboard_t *report); +/** + * \brief Send a nkro report. + * + * \param report The nkro report to send. + */ +void bluetooth_send_nkro(report_nkro_t *report); + /** * \brief Send a mouse report. * @@ -50,3 +69,10 @@ void bluetooth_send_mouse(report_mouse_t *report); * \param usage The consumer usage to send. */ void bluetooth_send_consumer(uint16_t usage); + +/** + * \brief Send a system usage. + * + * \param usage The system usage to send. + */ +void bluetooth_send_system(uint16_t usage); diff --git a/drivers/bluetooth/bluetooth_drivers.c b/drivers/bluetooth/bluetooth_drivers.c new file mode 100644 index 00000000000..b91d4501e61 --- /dev/null +++ b/drivers/bluetooth/bluetooth_drivers.c @@ -0,0 +1,71 @@ +/* + * Copyright 2022 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "bluetooth.h" + +#if defined(BLUETOOTH_BLUEFRUIT_LE) +# include "bluefruit_le.h" +#elif defined(BLUETOOTH_RN42) +# include "rn42.h" +#endif + +void bluetooth_init(void) { +#if defined(BLUETOOTH_BLUEFRUIT_LE) + bluefruit_le_init(); +#elif defined(BLUETOOTH_RN42) + rn42_init(); +#endif +} + +void bluetooth_task(void) { +#if defined(BLUETOOTH_BLUEFRUIT_LE) + bluefruit_le_task(); +#endif +} + +bool bluetooth_is_connected(void) { +#if defined(BLUETOOTH_BLUEFRUIT_LE) + return bluefruit_le_is_connected(); +#else + // TODO: drivers should check if BT is connected here + return true; +#endif +} + +void bluetooth_send_keyboard(report_keyboard_t *report) { +#if defined(BLUETOOTH_BLUEFRUIT_LE) + bluefruit_le_send_keyboard(report); +#elif defined(BLUETOOTH_RN42) + rn42_send_keyboard(report); +#endif +} + +void bluetooth_send_mouse(report_mouse_t *report) { +#if defined(BLUETOOTH_BLUEFRUIT_LE) + bluefruit_le_send_mouse(report); +#elif defined(BLUETOOTH_RN42) + rn42_send_mouse(report); +#endif +} + +void bluetooth_send_consumer(uint16_t usage) { +#if defined(BLUETOOTH_BLUEFRUIT_LE) + bluefruit_le_send_consumer(usage); +#elif defined(BLUETOOTH_RN42) + rn42_send_consumer(usage); +#endif +} diff --git a/quantum/connection/connection.c b/quantum/connection/connection.c index c7f3c4b4246..1ff88768762 100644 --- a/quantum/connection/connection.c +++ b/quantum/connection/connection.c @@ -5,6 +5,10 @@ #include "usb_util.h" #include "util.h" +#ifdef BLUETOOTH_ENABLE +# include "bluetooth.h" +#endif + // ======== DEPRECATED DEFINES - DO NOT USE ======== #ifdef OUTPUT_DEFAULT # undef CONNECTION_HOST_DEFAULT @@ -14,16 +18,6 @@ __attribute__((weak)) void set_output_user(uint8_t output) {} // ======== -#ifdef BLUETOOTH_ENABLE -# ifdef BLUETOOTH_BLUEFRUIT_LE -# include "bluefruit_le.h" -# define bluetooth_is_connected() bluefruit_le_is_connected() -# else -// TODO: drivers should check if BT is connected here -# define bluetooth_is_connected() true -# endif -#endif - #define CONNECTION_HOST_INVALID 0xFF #ifndef CONNECTION_HOST_DEFAULT diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c index 453952049fe..4f3867df08d 100644 --- a/tmk_core/protocol/host.c +++ b/tmk_core/protocol/host.c @@ -30,12 +30,31 @@ along with this program. If not, see . # include "joystick.h" #endif -#ifdef BLUETOOTH_ENABLE -# ifndef CONNECTION_ENABLE -# error CONNECTION_ENABLE required and not enabled -# endif +#ifdef CONNECTION_ENABLE # include "connection.h" +#endif + +#ifdef BLUETOOTH_ENABLE # include "bluetooth.h" + +static void bluetooth_send_extra(report_extra_t *report) { + switch (report->report_id) { + case REPORT_ID_SYSTEM: + bluetooth_send_system(report->usage); + return; + case REPORT_ID_CONSUMER: + bluetooth_send_consumer(report->usage); + return; + } +} + +host_driver_t bt_driver = { + .keyboard_leds = bluetooth_keyboard_leds, + .send_keyboard = bluetooth_send_keyboard, + .send_nkro = bluetooth_send_nkro, + .send_mouse = bluetooth_send_mouse, + .send_extra = bluetooth_send_extra, +}; #endif #ifdef NKRO_ENABLE @@ -55,6 +74,22 @@ host_driver_t *host_get_driver(void) { return driver; } +static host_driver_t *host_get_active_driver(void) { +#ifdef CONNECTION_ENABLE + switch (connection_get_host()) { +# ifdef BLUETOOTH_ENABLE + case CONNECTION_HOST_BLUETOOTH: + return &bt_driver; +# endif + case CONNECTION_HOST_NONE: + return NULL; + default: + break; + } +#endif + return driver; +} + #ifdef SPLIT_KEYBOARD uint8_t split_led_state = 0; void set_split_host_keyboard_leds(uint8_t led_state) { @@ -66,7 +101,10 @@ uint8_t host_keyboard_leds(void) { #ifdef SPLIT_KEYBOARD if (!is_keyboard_master()) return split_led_state; #endif - if (!driver) return 0; + + host_driver_t *driver = host_get_active_driver(); + if (!driver || !driver->keyboard_leds) return 0; + return (*driver->keyboard_leds)(); } @@ -76,14 +114,9 @@ led_t host_keyboard_led_state(void) { /* send report */ void host_keyboard_send(report_keyboard_t *report) { -#ifdef BLUETOOTH_ENABLE - if (connection_get_host() == CONNECTION_HOST_BLUETOOTH) { - bluetooth_send_keyboard(report); - return; - } -#endif + host_driver_t *driver = host_get_active_driver(); + if (!driver || !driver->send_keyboard) return; - if (!driver) return; #ifdef KEYBOARD_SHARED_EP report->report_id = REPORT_ID_KEYBOARD; #endif @@ -99,7 +132,9 @@ void host_keyboard_send(report_keyboard_t *report) { } void host_nkro_send(report_nkro_t *report) { - if (!driver) return; + host_driver_t *driver = host_get_active_driver(); + if (!driver || !driver->send_nkro) return; + report->report_id = REPORT_ID_NKRO; (*driver->send_nkro)(report); @@ -113,14 +148,9 @@ void host_nkro_send(report_nkro_t *report) { } void host_mouse_send(report_mouse_t *report) { -#ifdef BLUETOOTH_ENABLE - if (connection_get_host() == CONNECTION_HOST_BLUETOOTH) { - bluetooth_send_mouse(report); - return; - } -#endif + host_driver_t *driver = host_get_active_driver(); + if (!driver || !driver->send_mouse) return; - if (!driver) return; #ifdef MOUSE_SHARED_EP report->report_id = REPORT_ID_MOUSE; #endif @@ -136,7 +166,8 @@ void host_system_send(uint16_t usage) { if (usage == last_system_usage) return; last_system_usage = usage; - if (!driver) return; + host_driver_t *driver = host_get_active_driver(); + if (!driver || !driver->send_extra) return; report_extra_t report = { .report_id = REPORT_ID_SYSTEM, @@ -149,14 +180,8 @@ void host_consumer_send(uint16_t usage) { if (usage == last_consumer_usage) return; last_consumer_usage = usage; -#ifdef BLUETOOTH_ENABLE - if (connection_get_host() == CONNECTION_HOST_BLUETOOTH) { - bluetooth_send_consumer(usage); - return; - } -#endif - - if (!driver) return; + host_driver_t *driver = host_get_active_driver(); + if (!driver || !driver->send_extra) return; report_extra_t report = { .report_id = REPORT_ID_CONSUMER,