diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index efa349052cf..99668af0235 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -87,6 +87,7 @@ target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c) target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c) target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c) target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c) +target_sources_ifdef(CONFIG_ZMK_PROFILESWITCH app PRIVATE src/profile_switch.c) target_sources(app PRIVATE src/workqueue.c) target_sources(app PRIVATE src/main.c) diff --git a/app/Kconfig b/app/Kconfig index 89a128b5a27..d81e14188e6 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -180,6 +180,10 @@ config BT_PERIPHERAL_PREF_LATENCY config BT_PERIPHERAL_PREF_TIMEOUT default 400 +config ZMK_PROFILESWITCH + bool "Enable two state profile switch" + default n + #ZMK_BLE endif diff --git a/app/dts/bindings/zmk,profile-switch.yaml b/app/dts/bindings/zmk,profile-switch.yaml new file mode 100644 index 00000000000..2c093abe6e3 --- /dev/null +++ b/app/dts/bindings/zmk,profile-switch.yaml @@ -0,0 +1,14 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: | + Generic driver for controlling the bluetooth profile on the + switch-gpio pin status + (Only in supported hardware) + +compatible: "zmk,profile-switch" + +properties: + switch-gpios: + type: phandle-array + required: true diff --git a/app/src/profile_switch.c b/app/src/profile_switch.c new file mode 100644 index 00000000000..d6a820b7916 --- /dev/null +++ b/app/src/profile_switch.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +BUILD_ASSERT(DT_HAS_CHOSEN(zmk_profileswitch), + "CONFIG_ZMK_PROFILESWITCH is enabled but no zmk,profileswitch chosen node found"); + +struct gpio_callback a_gpio_cb; +const struct gpio_dt_spec switchgpio = GPIO_DT_SPEC_GET(DT_CHOSEN(zmk_profileswitch), switch_gpios); + +static void zmk_profile_switch_read() { + uint8_t val = gpio_pin_get_dt(&switchgpio); + LOG_DBG("Setting BLE profile to %d", val); + zmk_ble_prof_select(val); + if (gpio_pin_interrupt_configure_dt(&switchgpio, GPIO_INT_EDGE_BOTH)) { + LOG_WRN("Unable to set A pin GPIO interrupt"); + } +} + +static void zmk_profile_switch_work_cb(struct k_work *work) { zmk_profile_switch_read(); } + +K_WORK_DEFINE(profileswitch_work, zmk_profile_switch_work_cb); + +static void zmk_profile_switch_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) { + + if (gpio_pin_interrupt_configure_dt(&switchgpio, GPIO_INT_DISABLE)) { + LOG_WRN("Unable to set A pin GPIO interrupt"); + } + LOG_DBG("interrupt triggered"); + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &profileswitch_work); +} + +static int zmk_profile_switch_init(const struct device *_arg) { + + if (!device_is_ready(switchgpio.port)) { + LOG_ERR("A GPIO device is not ready"); + return -EINVAL; + } + if (gpio_pin_configure_dt(&switchgpio, GPIO_INPUT)) { + LOG_DBG("Failed to configure A pin"); + return -EIO; + } + gpio_init_callback(&a_gpio_cb, zmk_profile_switch_callback, BIT(switchgpio.pin)); + + if (gpio_add_callback(switchgpio.port, &a_gpio_cb) < 0) { + LOG_DBG("Failed to set A callback!"); + return -EIO; + } + if (gpio_pin_interrupt_configure_dt(&switchgpio, GPIO_INT_EDGE_BOTH)) { + LOG_WRN("Unable to set A pin GPIO interrupt"); + } + LOG_DBG("Setting profile now"); + zmk_profile_switch_read(); + return 0; +} + +SYS_INIT(zmk_profile_switch_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); \ No newline at end of file