Merge remote-tracking branch 'upstream/main' into bluetooth/battery-reporting
This commit is contained in:
commit
da0fb965f6
132 changed files with 3192 additions and 2651 deletions
4
.clang-format
Normal file
4
.clang-format
Normal file
|
@ -0,0 +1,4 @@
|
|||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 100
|
||||
SortIncludes: false
|
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
|
@ -17,6 +17,7 @@ jobs:
|
|||
- lily58_left
|
||||
- lily58_right
|
||||
- romac
|
||||
- settings_reset
|
||||
include:
|
||||
- board: proton_c
|
||||
shield: clueboard_california
|
||||
|
|
25
.github/workflows/clang-format-lint.yml
vendored
Normal file
25
.github/workflows/clang-format-lint.yml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
name: clang-format-lint
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "app/boards/**/*.c"
|
||||
- "app/include/**/*.h"
|
||||
- "app/src/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "app/boards/**/*.c"
|
||||
- "app/include/**/*.h"
|
||||
- "app/src/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: clang-format lint
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: DoozyX/clang-format-lint-action@v0.9
|
||||
with:
|
||||
source: "./app"
|
||||
extensions: "h,c"
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@
|
|||
/tools
|
||||
/zephyr
|
||||
/build
|
||||
*.DS_Store
|
||||
|
|
11
AUTHORS
Normal file
11
AUTHORS
Normal file
|
@ -0,0 +1,11 @@
|
|||
# The ZMK Project consists of many contributors. This file includes individuals
|
||||
# who have contributed significant changes to the project. To be added to here,
|
||||
# please submit a PR to the project repo.
|
||||
Peter Johanson (@petejohanson)
|
||||
Innovaker (@innovaker)
|
||||
Nick Winans (@Nicell)
|
||||
Okke Formsma (@okke-formsma)
|
||||
Cody McGinnis (@BrainWart)
|
||||
Kurtis Lew (@kurtis-lew)
|
||||
Richard Jones (@bmcgavin)
|
||||
Kevin Chen (@chenkevinh)
|
|
@ -29,22 +29,26 @@ target_sources(app PRIVATE src/hid.c)
|
|||
target_sources(app PRIVATE src/sensors.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_DISPLAY app PRIVATE src/display.c)
|
||||
target_sources(app PRIVATE src/event_manager.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble_unpair_combo.c)
|
||||
target_sources(app PRIVATE src/events/position_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/keycode_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/modifiers_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/sensor_event.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_none.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c)
|
||||
target_sources(app PRIVATE src/keymap.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c)
|
||||
if (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_none.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c)
|
||||
target_sources(app PRIVATE src/keymap.c)
|
||||
endif()
|
||||
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble_unpair_combo.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split_listener.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split/bluetooth/service.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL app PRIVATE src/split/bluetooth/central.c)
|
||||
|
@ -57,4 +61,4 @@ target_sources(app PRIVATE src/endpoints.c)
|
|||
target_sources(app PRIVATE src/hid_listener.c)
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
|
||||
zephyr_cc_option(-Wfatal-errors)
|
||||
zephyr_cc_option(-Wfatal-errors)
|
||||
|
|
36
app/Kconfig
36
app/Kconfig
|
@ -37,21 +37,26 @@ menuconfig ZMK_BLE
|
|||
select BT
|
||||
select BT_SMP
|
||||
select BT_SMP_SC_PAIR_ONLY
|
||||
select BT_SMP_APP_PAIRING_ACCEPT
|
||||
select BT_PERIPHERAL
|
||||
select BT_GATT_DIS
|
||||
select BT_GATT_BAS
|
||||
select BT_SETTINGS
|
||||
select SETTINGS
|
||||
# select BT_SETTINGS
|
||||
|
||||
if ZMK_BLE
|
||||
|
||||
config ZMK_BLE_INIT_PRIORITY
|
||||
int "Init Priority"
|
||||
default 50
|
||||
|
||||
|
||||
config SYSTEM_WORKQUEUE_STACK_SIZE
|
||||
default 2048
|
||||
|
||||
config ZMK_BLE_CLEAR_BONDS_ON_START
|
||||
bool "Configuration that clears all bond information from the keyboard on startup."
|
||||
default n
|
||||
|
||||
# HID GATT notifications sent this way are *not* picked up by Linux, and possibly others.
|
||||
config BT_GATT_NOTIFY_MULTIPLE
|
||||
default n
|
||||
|
@ -101,28 +106,20 @@ config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
|||
select BT_CENTRAL
|
||||
select BT_GATT_CLIENT
|
||||
|
||||
if ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
|
||||
config BT_MAX_CONN
|
||||
default 5
|
||||
|
||||
config BT_MAX_PAIRED
|
||||
# Bump this everywhere once we support switching active connections!
|
||||
default 2
|
||||
|
||||
endif
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_PERIPHERAL
|
||||
bool "Peripheral"
|
||||
select BT_KEYS_OVERWRITE_OLDEST
|
||||
|
||||
if ZMK_SPLIT_BLE_ROLE_PERIPHERAL
|
||||
|
||||
config ZMK_USB
|
||||
default n
|
||||
|
||||
config BT_MAX_PAIRED
|
||||
default 1
|
||||
|
||||
config BT_MAX_CONN
|
||||
default 5
|
||||
default 1
|
||||
|
||||
config BT_GAP_AUTO_UPDATE_CONN_PARAMS
|
||||
default n
|
||||
|
@ -135,8 +132,17 @@ endif
|
|||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
if ZMK_BLE && (!ZMK_SPLIT_BLE || ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
|
||||
config BT_MAX_CONN
|
||||
default 6
|
||||
|
||||
config BT_MAX_PAIRED
|
||||
default 5
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
||||
config ZMK_KSCAN_MOCK_DRIVER
|
||||
bool "Enable mock kscan driver to simulate key presses"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2020 Nick Winans
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config BOARD_DZ60RGB_REV1
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# DZ60RGB keyboard configuration
|
||||
|
||||
# Copyright (c) 2020 Nick Winans
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if BOARD_DZ60RGB_REV1
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Nick Winans
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -15,55 +15,53 @@
|
|||
/* pin assignments for STM32F3DISCOVERY board */
|
||||
static const struct pin_config pinconf[] = {
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay) && CONFIG_SERIAL
|
||||
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
|
||||
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
|
||||
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
|
||||
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay) && CONFIG_SERIAL
|
||||
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
|
||||
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
|
||||
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
|
||||
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) && CONFIG_I2C
|
||||
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
|
||||
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
|
||||
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
|
||||
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay) && CONFIG_I2C
|
||||
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
|
||||
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
|
||||
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
|
||||
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI
|
||||
#ifdef CONFIG_SPI_STM32_USE_HW_SS
|
||||
{STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
|
||||
{STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
|
||||
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
|
||||
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
|
||||
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
|
||||
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
|
||||
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
|
||||
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
|
||||
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay) && CONFIG_SPI
|
||||
#ifdef CONFIG_SPI_STM32_USE_HW_SS
|
||||
{STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
|
||||
{STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
|
||||
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
|
||||
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
|
||||
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
|
||||
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
|
||||
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
|
||||
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
|
||||
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
|
||||
#endif
|
||||
#ifdef CONFIG_USB_DC_STM32
|
||||
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
|
||||
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
|
||||
#endif /* CONFIG_USB_DC_STM32 */
|
||||
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
|
||||
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
|
||||
#endif /* CONFIG_USB_DC_STM32 */
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) && CONFIG_CAN
|
||||
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
|
||||
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
|
||||
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
|
||||
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
|
||||
#endif
|
||||
};
|
||||
|
||||
static int pinmux_stm32_init(struct device *port)
|
||||
{
|
||||
ARG_UNUSED(port);
|
||||
static int pinmux_stm32_init(struct device *port) {
|
||||
ARG_UNUSED(port);
|
||||
|
||||
stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
|
||||
stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1,
|
||||
CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
|
||||
SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
|
|
@ -1,6 +1,6 @@
|
|||
# nrfmicro board configuration
|
||||
|
||||
# Copyright (c) 2020 Okke Formsma, joric
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config BOARD_NRFMICRO_11
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Electronut Labs Papyr board configuration
|
||||
|
||||
# Copyright (c) 2020 Okke Formsma, joric
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Okke Formsma, joric
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Okke Formsma, joric
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Okke Formsma, joric
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Okke Formsma, joric
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Okke Formsma, joric
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Okke Formsma, joric
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -11,31 +11,30 @@
|
|||
#include <sys/sys_io.h>
|
||||
#include <devicetree.h>
|
||||
|
||||
static int pinmux_nrfmicro_init(struct device *port)
|
||||
{
|
||||
ARG_UNUSED(port);
|
||||
static int pinmux_nrfmicro_init(struct device *port) {
|
||||
ARG_UNUSED(port);
|
||||
|
||||
struct device *p1 = device_get_binding("GPIO_1");
|
||||
struct device *p1 = device_get_binding("GPIO_1");
|
||||
|
||||
#if CONFIG_BOARD_NRFMICRO_13
|
||||
struct device *p0 = device_get_binding("GPIO_0");
|
||||
// enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
|
||||
gpio_pin_configure(p1, 9, GPIO_OUTPUT);
|
||||
gpio_pin_set(p1, 9, 0);
|
||||
struct device *p0 = device_get_binding("GPIO_0");
|
||||
// enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
|
||||
gpio_pin_configure(p1, 9, GPIO_OUTPUT);
|
||||
gpio_pin_set(p1, 9, 0);
|
||||
|
||||
#if CONFIG_BOARD_NRFMICRO_CHARGER
|
||||
gpio_pin_configure(p0, 5, GPIO_OUTPUT);
|
||||
gpio_pin_set(p0, 5, 0);
|
||||
gpio_pin_configure(p0, 5, GPIO_OUTPUT);
|
||||
gpio_pin_set(p0, 5, 0);
|
||||
#else
|
||||
gpio_pin_configure(p0, 5, GPIO_INPUT);
|
||||
gpio_pin_configure(p0, 5, GPIO_INPUT);
|
||||
#endif
|
||||
|
||||
#else
|
||||
// enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
|
||||
gpio_pin_configure(p1, 9, GPIO_OUTPUT);
|
||||
gpio_pin_set(p1, 9, 1);
|
||||
gpio_pin_configure(p1, 9, GPIO_OUTPUT);
|
||||
gpio_pin_set(p1, 9, 1);
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(pinmux_nrfmicro_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Planck V6 board configuration
|
||||
|
||||
# Copyright (c) 2020 Peter Johanson
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config BOARD_PLANCK_REV6
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Planck keyboard configuration
|
||||
|
||||
# Copyright (c) 2020 Peter Johanson
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if BOARD_PLANCK_REV6
|
||||
|
|
|
@ -15,55 +15,53 @@
|
|||
/* pin assignments for STM32F3DISCOVERY board */
|
||||
static const struct pin_config pinconf[] = {
|
||||
#ifdef CONFIG_UART_1
|
||||
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
|
||||
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
|
||||
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
|
||||
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
|
||||
#endif /* CONFIG_UART_1 */
|
||||
#ifdef CONFIG_UART_2
|
||||
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
|
||||
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
|
||||
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
|
||||
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
|
||||
#endif /* CONFIG_UART_2 */
|
||||
#ifdef CONFIG_I2C_1
|
||||
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
|
||||
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
|
||||
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
|
||||
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
|
||||
#endif /* CONFIG_I2C_1 */
|
||||
#ifdef CONFIG_I2C_2
|
||||
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
|
||||
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
|
||||
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
|
||||
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
|
||||
#endif /* CONFIG_I2C_2 */
|
||||
#ifdef CONFIG_SPI_1
|
||||
#ifdef CONFIG_SPI_STM32_USE_HW_SS
|
||||
{STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
|
||||
{STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
|
||||
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
|
||||
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
|
||||
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
|
||||
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
|
||||
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
|
||||
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
|
||||
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
|
||||
#endif /* CONFIG_SPI_1 */
|
||||
#ifdef CONFIG_SPI_2
|
||||
#ifdef CONFIG_SPI_STM32_USE_HW_SS
|
||||
{STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
|
||||
{STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
|
||||
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
|
||||
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
|
||||
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
|
||||
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
|
||||
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
|
||||
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
|
||||
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
|
||||
#endif /* CONFIG_SPI_2 */
|
||||
#ifdef CONFIG_USB_DC_STM32
|
||||
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
|
||||
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
|
||||
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
|
||||
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
|
||||
#endif /* CONFIG_USB_DC_STM32 */
|
||||
#ifdef CONFIG_CAN_1
|
||||
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
|
||||
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
|
||||
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
|
||||
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
|
||||
#endif /* CONFIG_CAN_1 */
|
||||
};
|
||||
|
||||
static int pinmux_stm32_init(struct device *port)
|
||||
{
|
||||
ARG_UNUSED(port);
|
||||
static int pinmux_stm32_init(struct device *port) {
|
||||
ARG_UNUSED(port);
|
||||
|
||||
stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
|
||||
stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1,
|
||||
CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
|
||||
SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
|
||||
|
|
|
@ -15,55 +15,53 @@
|
|||
/* pin assignments for STM32F3DISCOVERY board */
|
||||
static const struct pin_config pinconf[] = {
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay) && CONFIG_SERIAL
|
||||
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
|
||||
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
|
||||
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
|
||||
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay) && CONFIG_SERIAL
|
||||
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
|
||||
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
|
||||
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
|
||||
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) && CONFIG_I2C
|
||||
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
|
||||
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
|
||||
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
|
||||
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay) && CONFIG_I2C
|
||||
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
|
||||
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
|
||||
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
|
||||
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI
|
||||
#ifdef CONFIG_SPI_STM32_USE_HW_SS
|
||||
{STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
|
||||
{STM32_PIN_PA4, STM32F3_PINMUX_FUNC_PA4_SPI1_NSS},
|
||||
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
|
||||
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
|
||||
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
|
||||
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
|
||||
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
|
||||
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
|
||||
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
|
||||
#endif
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay) && CONFIG_SPI
|
||||
#ifdef CONFIG_SPI_STM32_USE_HW_SS
|
||||
{STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
|
||||
{STM32_PIN_PB12, STM32F3_PINMUX_FUNC_PB12_SPI2_NSS},
|
||||
#endif /* CONFIG_SPI_STM32_USE_HW_SS */
|
||||
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
|
||||
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
|
||||
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
|
||||
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
|
||||
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
|
||||
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
|
||||
#endif
|
||||
#ifdef CONFIG_USB_DC_STM32
|
||||
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
|
||||
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
|
||||
#endif /* CONFIG_USB_DC_STM32 */
|
||||
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
|
||||
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
|
||||
#endif /* CONFIG_USB_DC_STM32 */
|
||||
#if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) && CONFIG_CAN
|
||||
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
|
||||
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
|
||||
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
|
||||
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
|
||||
#endif
|
||||
};
|
||||
|
||||
static int pinmux_stm32_init(struct device *port)
|
||||
{
|
||||
ARG_UNUSED(port);
|
||||
static int pinmux_stm32_init(struct device *port) {
|
||||
ARG_UNUSED(port);
|
||||
|
||||
stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
|
||||
stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf));
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1,
|
||||
CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
|
||||
SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
|
@ -21,14 +22,14 @@
|
|||
lower_layer {
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | BKSP |
|
||||
// | CTRL | | | | | | | LFT | DWN | UP | RGT | | |
|
||||
// | BTCLR| BT1 | BT2 | BT3 | BT4 | BT5 | | LFT | DWN | UP | RGT | | |
|
||||
// | SHFT | | | | | | | | | | | | |
|
||||
// | GUI | | SPC | | ENT | | ALT |
|
||||
bindings = <
|
||||
&kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp BKSP
|
||||
&kp LCTL &trans &trans &trans &trans &trans &kp LARW &kp DARW &kp UARW &kp RARW &trans &trans
|
||||
&kp LSFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&kp LGUI &trans &kp SPC &kp RET &trans &kp RALT
|
||||
&kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp BKSP
|
||||
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &kp LARW &kp DARW &kp UARW &kp RARW &trans &trans
|
||||
&kp LSFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&kp LGUI &trans &kp SPC &kp RET &trans &kp RALT
|
||||
>;
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
|
@ -26,17 +27,17 @@
|
|||
|
||||
lower_layer {
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
// | | | | | | | | | | | | | |
|
||||
// | BTCLR | BT1 | BT2 | BT3 | BT4 | BT5 | | | | | | | |
|
||||
// | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |
|
||||
// | ` | ! | @ | # | $ | % | | ^ | & | * | ( | ) | ~ |
|
||||
// | | | | | | | | | | | _ | + | { | } | "|" |
|
||||
// | | | | | | | |
|
||||
bindings = <
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
|
||||
&kp GRAV &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp TILD
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp KPLS &kp LCUR &kp RCUR &kp PIPE
|
||||
&trans &trans &trans &trans &trans &trans
|
||||
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans
|
||||
&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
|
||||
&kp GRAV &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp TILD
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp KPLS &kp LCUR &kp RCUR &kp PIPE
|
||||
&trans &trans &trans &trans &trans &trans
|
||||
>;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
|
@ -25,17 +26,17 @@
|
|||
|
||||
lower_layer {
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
// | | | | | | | | | | | | | |
|
||||
// | BTCLR | BT1 | BT2 | BT3 | BT4 | BT5 | | | | | | | |
|
||||
// | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |
|
||||
// | ` | ! | @ | # | $ | % | | ^ | & | * | ( | ) | ~ |
|
||||
// | | | | | | | | | | | _ | + | { | } | "|" |
|
||||
// | | | | | | | | | |
|
||||
bindings = <
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
|
||||
&kp GRAV &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp TILD
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp KPLS &kp LCUR &kp RCUR &kp PIPE
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans
|
||||
&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
|
||||
&kp GRAV &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp TILD
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp KPLS &kp LCUR &kp RCUR &kp PIPE
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans
|
||||
>;
|
||||
|
||||
sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2020 TJ Campie
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if SHIELD_QAZ
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2020 TJ Campie
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_MY_BOARD
|
||||
def_bool $(shields_list_contains,qaz)
|
||||
|
||||
config SHIELD_QAZ
|
||||
def_bool $(shields_list_contains,qaz)
|
||||
|
|
|
@ -1,16 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2020 TJ Campie
|
||||
*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
#define DEFAULT 0
|
||||
#define NUM_SYM 1
|
||||
#define NAV 2
|
||||
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
hm: homerow_mods {
|
||||
compatible = "zmk,behavior-hold-tap";
|
||||
label = "homerow mods";
|
||||
#binding-cells = <2>;
|
||||
tapping_term_ms = <225>;
|
||||
flavor = "tap-preferred";
|
||||
bindings = <&kp>, <&kp>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
@ -18,9 +32,9 @@
|
|||
default_layer {
|
||||
bindings = <
|
||||
&kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P
|
||||
&kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp RET
|
||||
&hm LGUI A &hm LALT S &hm LCTL D &hm LSFT F &kp G &kp H &hm RSFT J &hm RCTL K &hm RALT L &hm RGUI RET
|
||||
&kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT
|
||||
&kp LSFT &kp LGUI &kp LALT &mo NAV &kp SPC &mo NUM_SYM &kp QUOT &kp FSLH
|
||||
&kp LSFT &kp LGUI &kp LALT < NAV RET < NUM_SYM SPC &kp COLN &kp QUOT &kp FSLH
|
||||
>;
|
||||
};
|
||||
num_sym {
|
||||
|
@ -34,10 +48,10 @@
|
|||
|
||||
nav {
|
||||
bindings = <
|
||||
&none &none &none &none &none &none &none &kp UARW &none &kp BKSP
|
||||
&bt BT_CLR &bt BT_NXT &bt BT_PRV &none &none &none &none &kp UARW &none &kp BKSP
|
||||
&trans &trans &trans &trans &none &none &kp LARW &kp DARW &kp RARW &none
|
||||
&none &none &none &none &none &none &none &none &none
|
||||
&none &none &none &none &none &trans &trans &kp RET &trans &kp FSLH
|
||||
&none &none &none &trans &trans &kp RET &trans &kp FSLH
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2020 TJ Campie
|
||||
*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
|
@ -28,16 +29,16 @@
|
|||
|
||||
nav_layer {
|
||||
// -----------------------
|
||||
// | _ | HOME | PGUP |
|
||||
// | _ | END | PGDN |
|
||||
// | _ | _ | _ |
|
||||
// | _ | _ | RET |
|
||||
// | BTNXT | HOME | PGUP |
|
||||
// | BTPRV | END | PGDN |
|
||||
// | BTCLR | _ | _ |
|
||||
// | _ | _ | RET |
|
||||
// -----------------------
|
||||
bindings = <
|
||||
&trans &kp HOME &kp PGUP
|
||||
&trans &kp END &kp PGDN
|
||||
&trans &trans &trans
|
||||
&trans &trans &kp RET
|
||||
&bt BT_NXT &kp HOME &kp PGUP
|
||||
&bt BT_PRV &kp END &kp PGDN
|
||||
&bt BT_CLR &trans &trans
|
||||
&trans &trans &kp RET
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
|
10
app/boards/shields/settings_reset/Kconfig.defconfig
Normal file
10
app/boards/shields/settings_reset/Kconfig.defconfig
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if SHIELD_SETTINGS_RESET
|
||||
|
||||
config ZMK_KEYBOARD_NAME
|
||||
default "SETTINGS RESET"
|
||||
|
||||
endif
|
||||
|
5
app/boards/shields/settings_reset/Kconfig.shield
Normal file
5
app/boards/shields/settings_reset/Kconfig.shield
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_SETTINGS_RESET
|
||||
def_bool $(shields_list_contains,settings_reset)
|
1
app/boards/shields/settings_reset/settings_reset.conf
Normal file
1
app/boards/shields/settings_reset/settings_reset.conf
Normal file
|
@ -0,0 +1 @@
|
|||
CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START=y
|
22
app/boards/shields/settings_reset/settings_reset.keymap
Normal file
22
app/boards/shields/settings_reset/settings_reset.keymap
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&reset
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
24
app/boards/shields/settings_reset/settings_reset.overlay
Normal file
24
app/boards/shields/settings_reset/settings_reset.overlay
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/zmk/matrix-transform.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-direct";
|
||||
label = "KSCAN";
|
||||
|
||||
input-gpios
|
||||
= <&pro_micro_d 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
|
@ -44,17 +45,17 @@
|
|||
|
||||
raise_layer {
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
// | | | | | | | | | | | | | |
|
||||
// |BTCLR| BT1 | BT2 | BT3 | BT4 | BT5 | | | | | | | |
|
||||
// | | INS | PSCR | GUI | | | | PGUP | | ^ | | | |
|
||||
// | | ALT | CTRL | SHIFT | | CAPS | | PGDN | <- | v | -> | DEL | BKSPC |
|
||||
// | | UNDO | CUT | COPY | PASTE | | | | | | | | | | |
|
||||
// | | | | | | | | | | | |
|
||||
bindings = <
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&trans &kp INS &kp PRSC &kp GUI &trans &trans &kp PGUP &trans &kp UARW &trans &kp NUM_0 &trans
|
||||
&trans &kp LALT &kp LCTL &kp LSFT &trans &kp CLCK &kp PGDN &kp LARW &kp DARW &kp RARW &kp DEL &kp BKSP
|
||||
&trans &kp UNDO &kp CUT &kp COPY &kp PSTE &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans
|
||||
&trans &kp INS &kp PRSC &kp GUI &trans &trans &kp PGUP &trans &kp UARW &trans &kp NUM_0 &trans
|
||||
&trans &kp LALT &kp LCTL &kp LSFT &trans &kp CLCK &kp PGDN &kp LARW &kp DARW &kp RARW &kp DEL &kp BKSP
|
||||
&trans &kp UNDO &kp CUT &kp COPY &kp PSTE &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
>;
|
||||
|
||||
sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD &inc_dec_kp PGUP PGDN>;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -18,136 +18,131 @@
|
|||
|
||||
LOG_MODULE_REGISTER(EC11, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int ec11_get_ab_state(struct device *dev)
|
||||
{
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
const struct ec11_config *drv_cfg = dev->config_info;
|
||||
static int ec11_get_ab_state(struct device *dev) {
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
const struct ec11_config *drv_cfg = dev->config_info;
|
||||
|
||||
return (gpio_pin_get(drv_data->a, drv_cfg->a_pin) << 1) | gpio_pin_get(drv_data->b, drv_cfg->b_pin);
|
||||
return (gpio_pin_get(drv_data->a, drv_cfg->a_pin) << 1) |
|
||||
gpio_pin_get(drv_data->b, drv_cfg->b_pin);
|
||||
}
|
||||
|
||||
static int ec11_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
const struct ec11_config *drv_cfg = dev->config_info;
|
||||
u8_t val;
|
||||
s8_t delta;
|
||||
static int ec11_sample_fetch(struct device *dev, enum sensor_channel chan) {
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
const struct ec11_config *drv_cfg = dev->config_info;
|
||||
u8_t val;
|
||||
s8_t delta;
|
||||
|
||||
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_ROTATION);
|
||||
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_ROTATION);
|
||||
|
||||
val = ec11_get_ab_state(dev);
|
||||
val = ec11_get_ab_state(dev);
|
||||
|
||||
LOG_DBG("prev: %d, new: %d", drv_data->ab_state, val);
|
||||
LOG_DBG("prev: %d, new: %d", drv_data->ab_state, val);
|
||||
|
||||
switch(val | (drv_data->ab_state << 2)) {
|
||||
case 0b0010: case 0b0100: case 0b1101: case 0b1011:
|
||||
delta = -1;
|
||||
break;
|
||||
case 0b0001: case 0b0111: case 0b1110: case 0b1000:
|
||||
delta = 1;
|
||||
break;
|
||||
default:
|
||||
delta = 0;
|
||||
break;
|
||||
}
|
||||
switch (val | (drv_data->ab_state << 2)) {
|
||||
case 0b0010:
|
||||
case 0b0100:
|
||||
case 0b1101:
|
||||
case 0b1011:
|
||||
delta = -1;
|
||||
break;
|
||||
case 0b0001:
|
||||
case 0b0111:
|
||||
case 0b1110:
|
||||
case 0b1000:
|
||||
delta = 1;
|
||||
break;
|
||||
default:
|
||||
delta = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_DBG("Delta: %d", delta);
|
||||
LOG_DBG("Delta: %d", delta);
|
||||
|
||||
drv_data->pulses += delta;
|
||||
drv_data->ab_state = val;
|
||||
drv_data->pulses += delta;
|
||||
drv_data->ab_state = val;
|
||||
|
||||
drv_data->ticks = drv_data->pulses / drv_cfg->resolution;
|
||||
drv_data->delta = delta;
|
||||
drv_data->pulses %= drv_cfg->resolution;
|
||||
|
||||
return 0;
|
||||
drv_data->ticks = drv_data->pulses / drv_cfg->resolution;
|
||||
drv_data->delta = delta;
|
||||
drv_data->pulses %= drv_cfg->resolution;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ec11_channel_get(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
|
||||
if (chan != SENSOR_CHAN_ROTATION) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
static int ec11_channel_get(struct device *dev, enum sensor_channel chan,
|
||||
struct sensor_value *val) {
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
|
||||
val->val1 = drv_data->ticks;
|
||||
val->val2 = drv_data->delta;
|
||||
|
||||
return 0;
|
||||
if (chan != SENSOR_CHAN_ROTATION) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
val->val1 = drv_data->ticks;
|
||||
val->val2 = drv_data->delta;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api ec11_driver_api = {
|
||||
#ifdef CONFIG_EC11_TRIGGER
|
||||
.trigger_set = ec11_trigger_set,
|
||||
.trigger_set = ec11_trigger_set,
|
||||
#endif
|
||||
.sample_fetch = ec11_sample_fetch,
|
||||
.channel_get = ec11_channel_get,
|
||||
.sample_fetch = ec11_sample_fetch,
|
||||
.channel_get = ec11_channel_get,
|
||||
};
|
||||
|
||||
int ec11_init(struct device *dev)
|
||||
{
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
const struct ec11_config *drv_cfg = dev->config_info;
|
||||
int ec11_init(struct device *dev) {
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
const struct ec11_config *drv_cfg = dev->config_info;
|
||||
|
||||
LOG_DBG("A: %s %d B: %s %d resolution %d", drv_cfg->a_label, drv_cfg->a_pin, drv_cfg->b_label, drv_cfg->b_pin, drv_cfg->resolution);
|
||||
LOG_DBG("A: %s %d B: %s %d resolution %d", drv_cfg->a_label, drv_cfg->a_pin, drv_cfg->b_label,
|
||||
drv_cfg->b_pin, drv_cfg->resolution);
|
||||
|
||||
drv_data->a = device_get_binding(drv_cfg->a_label);
|
||||
if (drv_data->a == NULL) {
|
||||
LOG_ERR("Failed to get pointer to A GPIO device");
|
||||
return -EINVAL;
|
||||
}
|
||||
drv_data->a = device_get_binding(drv_cfg->a_label);
|
||||
if (drv_data->a == NULL) {
|
||||
LOG_ERR("Failed to get pointer to A GPIO device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
drv_data->b = device_get_binding(drv_cfg->b_label);
|
||||
if (drv_data->b == NULL) {
|
||||
LOG_ERR("Failed to get pointer to B GPIO device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio_pin_configure(drv_data->a, drv_cfg->a_pin,
|
||||
drv_cfg->a_flags
|
||||
| GPIO_INPUT)) {
|
||||
LOG_DBG("Failed to configure A pin");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (gpio_pin_configure(drv_data->b, drv_cfg->b_pin,
|
||||
drv_cfg->b_flags
|
||||
| GPIO_INPUT)) {
|
||||
LOG_DBG("Failed to configure B pin");
|
||||
return -EIO;
|
||||
}
|
||||
drv_data->b = device_get_binding(drv_cfg->b_label);
|
||||
if (drv_data->b == NULL) {
|
||||
LOG_ERR("Failed to get pointer to B GPIO device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio_pin_configure(drv_data->a, drv_cfg->a_pin, drv_cfg->a_flags | GPIO_INPUT)) {
|
||||
LOG_DBG("Failed to configure A pin");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (gpio_pin_configure(drv_data->b, drv_cfg->b_pin, drv_cfg->b_flags | GPIO_INPUT)) {
|
||||
LOG_DBG("Failed to configure B pin");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EC11_TRIGGER
|
||||
if (ec11_init_interrupt(dev) < 0) {
|
||||
LOG_DBG("Failed to initialize interrupt!");
|
||||
return -EIO;
|
||||
}
|
||||
if (ec11_init_interrupt(dev) < 0) {
|
||||
LOG_DBG("Failed to initialize interrupt!");
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
drv_data->ab_state = ec11_get_ab_state(dev);
|
||||
drv_data->ab_state = ec11_get_ab_state(dev);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define EC11_INST(n) \
|
||||
struct ec11_data ec11_data_##n; \
|
||||
const struct ec11_config ec11_cfg_##n = { \
|
||||
.a_label = DT_INST_GPIO_LABEL(n, a_gpios), \
|
||||
.a_pin = DT_INST_GPIO_PIN(n, a_gpios), \
|
||||
.a_flags = DT_INST_GPIO_FLAGS(n, a_gpios), \
|
||||
.b_label = DT_INST_GPIO_LABEL(n, b_gpios), \
|
||||
.b_pin = DT_INST_GPIO_PIN(n, b_gpios), \
|
||||
.b_flags = DT_INST_GPIO_FLAGS(n, b_gpios), \
|
||||
COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))), \
|
||||
}; \
|
||||
DEVICE_AND_API_INIT(ec11, DT_INST_LABEL(n), ec11_init, \
|
||||
&ec11_data_##n, \
|
||||
&ec11_cfg_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
|
||||
&ec11_driver_api);
|
||||
#define EC11_INST(n) \
|
||||
struct ec11_data ec11_data_##n; \
|
||||
const struct ec11_config ec11_cfg_##n = { \
|
||||
.a_label = DT_INST_GPIO_LABEL(n, a_gpios), \
|
||||
.a_pin = DT_INST_GPIO_PIN(n, a_gpios), \
|
||||
.a_flags = DT_INST_GPIO_FLAGS(n, a_gpios), \
|
||||
.b_label = DT_INST_GPIO_LABEL(n, b_gpios), \
|
||||
.b_pin = DT_INST_GPIO_PIN(n, b_gpios), \
|
||||
.b_flags = DT_INST_GPIO_FLAGS(n, b_gpios), \
|
||||
COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))), \
|
||||
}; \
|
||||
DEVICE_AND_API_INIT(ec11, DT_INST_LABEL(n), ec11_init, &ec11_data_##n, &ec11_cfg_##n, \
|
||||
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ec11_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(EC11_INST)
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -11,39 +11,39 @@
|
|||
#include <sys/util.h>
|
||||
|
||||
struct ec11_config {
|
||||
const char *a_label;
|
||||
const u8_t a_pin;
|
||||
const u8_t a_flags;
|
||||
const char *a_label;
|
||||
const u8_t a_pin;
|
||||
const u8_t a_flags;
|
||||
|
||||
const char *b_label;
|
||||
const u8_t b_pin;
|
||||
const u8_t b_flags;
|
||||
const char *b_label;
|
||||
const u8_t b_pin;
|
||||
const u8_t b_flags;
|
||||
|
||||
const u8_t resolution;
|
||||
const u8_t resolution;
|
||||
};
|
||||
|
||||
struct ec11_data {
|
||||
struct device *a;
|
||||
struct device *b;
|
||||
u8_t ab_state;
|
||||
s8_t pulses;
|
||||
s8_t ticks;
|
||||
s8_t delta;
|
||||
struct device *a;
|
||||
struct device *b;
|
||||
u8_t ab_state;
|
||||
s8_t pulses;
|
||||
s8_t ticks;
|
||||
s8_t delta;
|
||||
|
||||
#ifdef CONFIG_EC11_TRIGGER
|
||||
struct gpio_callback a_gpio_cb;
|
||||
struct gpio_callback b_gpio_cb;
|
||||
struct device *dev;
|
||||
struct gpio_callback a_gpio_cb;
|
||||
struct gpio_callback b_gpio_cb;
|
||||
struct device *dev;
|
||||
|
||||
sensor_trigger_handler_t handler;
|
||||
const struct sensor_trigger *trigger;
|
||||
sensor_trigger_handler_t handler;
|
||||
const struct sensor_trigger *trigger;
|
||||
|
||||
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
|
||||
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_EC11_THREAD_STACK_SIZE);
|
||||
struct k_sem gpio_sem;
|
||||
struct k_thread thread;
|
||||
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_EC11_THREAD_STACK_SIZE);
|
||||
struct k_sem gpio_sem;
|
||||
struct k_thread thread;
|
||||
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
|
||||
struct k_work work;
|
||||
struct k_work work;
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_EC11_TRIGGER */
|
||||
|
@ -51,9 +51,8 @@ struct ec11_data {
|
|||
|
||||
#ifdef CONFIG_EC11_TRIGGER
|
||||
|
||||
int ec11_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler);
|
||||
int ec11_trigger_set(struct device *dev, const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler);
|
||||
|
||||
int ec11_init_interrupt(struct device *dev);
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -19,158 +19,130 @@ extern struct ec11_data ec11_driver;
|
|||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(EC11, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static inline void setup_int(struct device *dev,
|
||||
bool enable)
|
||||
{
|
||||
struct ec11_data *data = dev->driver_data;
|
||||
const struct ec11_config *cfg = dev->config_info;
|
||||
static inline void setup_int(struct device *dev, bool enable) {
|
||||
struct ec11_data *data = dev->driver_data;
|
||||
const struct ec11_config *cfg = dev->config_info;
|
||||
|
||||
LOG_DBG("enabled %s", (enable ? "true" : "false"));
|
||||
LOG_DBG("enabled %s", (enable ? "true" : "false"));
|
||||
|
||||
if (gpio_pin_interrupt_configure(data->a,
|
||||
cfg->a_pin,
|
||||
enable
|
||||
? GPIO_INT_EDGE_BOTH
|
||||
: GPIO_INT_DISABLE)) {
|
||||
LOG_WRN("Unable to set A pin GPIO interrupt");
|
||||
}
|
||||
if (gpio_pin_interrupt_configure(data->a, cfg->a_pin,
|
||||
enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE)) {
|
||||
LOG_WRN("Unable to set A pin GPIO interrupt");
|
||||
}
|
||||
|
||||
if (gpio_pin_interrupt_configure(data->b,
|
||||
cfg->b_pin,
|
||||
enable
|
||||
? GPIO_INT_EDGE_BOTH
|
||||
: GPIO_INT_DISABLE)) {
|
||||
LOG_WRN("Unable to set A pin GPIO interrupt");
|
||||
}
|
||||
if (gpio_pin_interrupt_configure(data->b, cfg->b_pin,
|
||||
enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE)) {
|
||||
LOG_WRN("Unable to set A pin GPIO interrupt");
|
||||
}
|
||||
}
|
||||
|
||||
static void ec11_a_gpio_callback(struct device *dev,
|
||||
struct gpio_callback *cb, u32_t pins)
|
||||
{
|
||||
struct ec11_data *drv_data =
|
||||
CONTAINER_OF(cb, struct ec11_data, a_gpio_cb);
|
||||
static void ec11_a_gpio_callback(struct device *dev, struct gpio_callback *cb, u32_t pins) {
|
||||
struct ec11_data *drv_data = CONTAINER_OF(cb, struct ec11_data, a_gpio_cb);
|
||||
|
||||
LOG_DBG("");
|
||||
LOG_DBG("");
|
||||
|
||||
setup_int(drv_data->dev, false);
|
||||
setup_int(drv_data->dev, false);
|
||||
|
||||
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&drv_data->gpio_sem);
|
||||
k_sem_give(&drv_data->gpio_sem);
|
||||
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&drv_data->work);
|
||||
k_work_submit(&drv_data->work);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ec11_b_gpio_callback(struct device *dev,
|
||||
struct gpio_callback *cb, u32_t pins)
|
||||
{
|
||||
struct ec11_data *drv_data =
|
||||
CONTAINER_OF(cb, struct ec11_data, b_gpio_cb);
|
||||
static void ec11_b_gpio_callback(struct device *dev, struct gpio_callback *cb, u32_t pins) {
|
||||
struct ec11_data *drv_data = CONTAINER_OF(cb, struct ec11_data, b_gpio_cb);
|
||||
|
||||
LOG_DBG("");
|
||||
LOG_DBG("");
|
||||
|
||||
setup_int(drv_data->dev, false);
|
||||
setup_int(drv_data->dev, false);
|
||||
|
||||
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&drv_data->gpio_sem);
|
||||
k_sem_give(&drv_data->gpio_sem);
|
||||
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&drv_data->work);
|
||||
k_work_submit(&drv_data->work);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ec11_thread_cb(void *arg)
|
||||
{
|
||||
struct device *dev = arg;
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
static void ec11_thread_cb(void *arg) {
|
||||
struct device *dev = arg;
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
|
||||
drv_data->handler(dev, drv_data->trigger);
|
||||
drv_data->handler(dev, drv_data->trigger);
|
||||
|
||||
setup_int(dev, true);
|
||||
setup_int(dev, true);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EC11_TRIGGER_OWN_THREAD
|
||||
static void ec11_thread(int dev_ptr, int unused)
|
||||
{
|
||||
struct device *dev = INT_TO_POINTER(dev_ptr);
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
static void ec11_thread(int dev_ptr, int unused) {
|
||||
struct device *dev = INT_TO_POINTER(dev_ptr);
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
|
||||
ARG_UNUSED(unused);
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
while (1) {
|
||||
k_sem_take(&drv_data->gpio_sem, K_FOREVER);
|
||||
ec11_thread_cb(dev);
|
||||
}
|
||||
while (1) {
|
||||
k_sem_take(&drv_data->gpio_sem, K_FOREVER);
|
||||
ec11_thread_cb(dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EC11_TRIGGER_GLOBAL_THREAD
|
||||
static void ec11_work_cb(struct k_work *work)
|
||||
{
|
||||
struct ec11_data *drv_data =
|
||||
CONTAINER_OF(work, struct ec11_data, work);
|
||||
static void ec11_work_cb(struct k_work *work) {
|
||||
struct ec11_data *drv_data = CONTAINER_OF(work, struct ec11_data, work);
|
||||
|
||||
LOG_DBG("");
|
||||
LOG_DBG("");
|
||||
|
||||
ec11_thread_cb(drv_data->dev);
|
||||
ec11_thread_cb(drv_data->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ec11_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
int ec11_trigger_set(struct device *dev, const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler) {
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
|
||||
setup_int(dev, false);
|
||||
setup_int(dev, false);
|
||||
|
||||
k_msleep(5);
|
||||
k_msleep(5);
|
||||
|
||||
drv_data->trigger = trig;
|
||||
drv_data->handler = handler;
|
||||
drv_data->trigger = trig;
|
||||
drv_data->handler = handler;
|
||||
|
||||
setup_int(dev, true);
|
||||
setup_int(dev, true);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ec11_init_interrupt(struct device *dev)
|
||||
{
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
const struct ec11_config *drv_cfg = dev->config_info;
|
||||
int ec11_init_interrupt(struct device *dev) {
|
||||
struct ec11_data *drv_data = dev->driver_data;
|
||||
const struct ec11_config *drv_cfg = dev->config_info;
|
||||
|
||||
drv_data->dev = dev;
|
||||
/* setup gpio interrupt */
|
||||
drv_data->dev = dev;
|
||||
/* setup gpio interrupt */
|
||||
|
||||
gpio_init_callback(&drv_data->a_gpio_cb, ec11_a_gpio_callback, BIT(drv_cfg->a_pin));
|
||||
|
||||
gpio_init_callback(&drv_data->a_gpio_cb,
|
||||
ec11_a_gpio_callback,
|
||||
BIT(drv_cfg->a_pin));
|
||||
if (gpio_add_callback(drv_data->a, &drv_data->a_gpio_cb) < 0) {
|
||||
LOG_DBG("Failed to set A callback!");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (gpio_add_callback(drv_data->a, &drv_data->a_gpio_cb) < 0) {
|
||||
LOG_DBG("Failed to set A callback!");
|
||||
return -EIO;
|
||||
}
|
||||
gpio_init_callback(&drv_data->b_gpio_cb, ec11_b_gpio_callback, BIT(drv_cfg->b_pin));
|
||||
|
||||
gpio_init_callback(&drv_data->b_gpio_cb,
|
||||
ec11_b_gpio_callback,
|
||||
BIT(drv_cfg->b_pin));
|
||||
|
||||
if (gpio_add_callback(drv_data->b, &drv_data->b_gpio_cb) < 0) {
|
||||
LOG_DBG("Failed to set B callback!");
|
||||
return -EIO;
|
||||
}
|
||||
if (gpio_add_callback(drv_data->b, &drv_data->b_gpio_cb) < 0) {
|
||||
LOG_DBG("Failed to set B callback!");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
|
||||
k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);
|
||||
k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);
|
||||
|
||||
k_thread_create(&drv_data->thread, drv_data->thread_stack,
|
||||
CONFIG_EC11_THREAD_STACK_SIZE,
|
||||
(k_thread_entry_t)ec11_thread, dev,
|
||||
0, NULL, K_PRIO_COOP(CONFIG_EC11_THREAD_PRIORITY),
|
||||
0, K_NO_WAIT);
|
||||
k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_EC11_THREAD_STACK_SIZE,
|
||||
(k_thread_entry_t)ec11_thread, dev, 0, NULL,
|
||||
K_PRIO_COOP(CONFIG_EC11_THREAD_PRIORITY), 0, K_NO_WAIT);
|
||||
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_init(&drv_data->work, ec11_work_cb);
|
||||
k_work_init(&drv_data->work, ec11_work_cb);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -15,248 +15,215 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
struct kscan_gpio_item_config
|
||||
{
|
||||
char *label;
|
||||
gpio_pin_t pin;
|
||||
gpio_flags_t flags;
|
||||
struct kscan_gpio_item_config {
|
||||
char *label;
|
||||
gpio_pin_t pin;
|
||||
gpio_flags_t flags;
|
||||
};
|
||||
|
||||
union work_reference {
|
||||
struct k_delayed_work delayed;
|
||||
struct k_work direct;
|
||||
struct k_delayed_work delayed;
|
||||
struct k_work direct;
|
||||
};
|
||||
|
||||
struct kscan_gpio_config
|
||||
{
|
||||
u8_t num_of_inputs;
|
||||
u8_t debounce_period;
|
||||
struct kscan_gpio_item_config inputs[];
|
||||
struct kscan_gpio_config {
|
||||
u8_t num_of_inputs;
|
||||
u8_t debounce_period;
|
||||
struct kscan_gpio_item_config inputs[];
|
||||
};
|
||||
|
||||
struct kscan_gpio_data
|
||||
{
|
||||
struct kscan_gpio_data {
|
||||
#if defined(CONFIG_ZMK_KSCAN_GPIO_POLLING)
|
||||
struct k_timer poll_timer;
|
||||
struct k_timer poll_timer;
|
||||
#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
|
||||
kscan_callback_t callback;
|
||||
union work_reference work;
|
||||
struct device *dev;
|
||||
u32_t pin_state;
|
||||
struct device *inputs[];
|
||||
kscan_callback_t callback;
|
||||
union work_reference work;
|
||||
struct device *dev;
|
||||
u32_t pin_state;
|
||||
struct device *inputs[];
|
||||
};
|
||||
|
||||
static struct device **kscan_gpio_input_devices(struct device *dev)
|
||||
{
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
return data->inputs;
|
||||
static struct device **kscan_gpio_input_devices(struct device *dev) {
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
return data->inputs;
|
||||
}
|
||||
|
||||
static const struct kscan_gpio_item_config *kscan_gpio_input_configs(struct device *dev)
|
||||
{
|
||||
const struct kscan_gpio_config *cfg = dev->config_info;
|
||||
return cfg->inputs;
|
||||
static const struct kscan_gpio_item_config *kscan_gpio_input_configs(struct device *dev) {
|
||||
const struct kscan_gpio_config *cfg = dev->config_info;
|
||||
return cfg->inputs;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING)
|
||||
|
||||
struct kscan_gpio_irq_callback
|
||||
{
|
||||
union work_reference *work;
|
||||
u8_t debounce_period;
|
||||
struct gpio_callback callback;
|
||||
struct kscan_gpio_irq_callback {
|
||||
union work_reference *work;
|
||||
u8_t debounce_period;
|
||||
struct gpio_callback callback;
|
||||
};
|
||||
|
||||
static int kscan_gpio_config_interrupts(struct device *dev, gpio_flags_t flags)
|
||||
{
|
||||
const struct kscan_gpio_config *cfg = dev->config_info;
|
||||
struct device **devices = kscan_gpio_input_devices(dev);
|
||||
const struct kscan_gpio_item_config *configs = kscan_gpio_input_configs(dev);
|
||||
|
||||
for (int i = 0; i < cfg->num_of_inputs; i++)
|
||||
{
|
||||
struct device *dev = devices[i];
|
||||
const struct kscan_gpio_item_config *cfg = &configs[i];
|
||||
static int kscan_gpio_config_interrupts(struct device *dev, gpio_flags_t flags) {
|
||||
const struct kscan_gpio_config *cfg = dev->config_info;
|
||||
struct device **devices = kscan_gpio_input_devices(dev);
|
||||
const struct kscan_gpio_item_config *configs = kscan_gpio_input_configs(dev);
|
||||
|
||||
int err = gpio_pin_interrupt_configure(dev, cfg->pin, flags);
|
||||
for (int i = 0; i < cfg->num_of_inputs; i++) {
|
||||
struct device *dev = devices[i];
|
||||
const struct kscan_gpio_item_config *cfg = &configs[i];
|
||||
|
||||
if (err)
|
||||
{
|
||||
LOG_ERR("Unable to enable matrix GPIO interrupt");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
int err = gpio_pin_interrupt_configure(dev, cfg->pin, flags);
|
||||
|
||||
return 0;
|
||||
if (err) {
|
||||
LOG_ERR("Unable to enable matrix GPIO interrupt");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kscan_gpio_direct_enable(struct device *dev)
|
||||
{
|
||||
return kscan_gpio_config_interrupts(dev,
|
||||
GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH);
|
||||
static int kscan_gpio_direct_enable(struct device *dev) {
|
||||
return kscan_gpio_config_interrupts(dev, GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH);
|
||||
}
|
||||
static int kscan_gpio_direct_disable(struct device *dev)
|
||||
{
|
||||
return kscan_gpio_config_interrupts(dev,
|
||||
GPIO_INT_DISABLE);
|
||||
static int kscan_gpio_direct_disable(struct device *dev) {
|
||||
return kscan_gpio_config_interrupts(dev, GPIO_INT_DISABLE);
|
||||
}
|
||||
|
||||
static void kscan_gpio_irq_callback_handler(struct device *dev,
|
||||
struct gpio_callback *cb, gpio_port_pins_t pin)
|
||||
{
|
||||
struct kscan_gpio_irq_callback *data =
|
||||
CONTAINER_OF(cb, struct kscan_gpio_irq_callback, callback);
|
||||
|
||||
if (data->debounce_period > 0) {
|
||||
k_delayed_work_cancel(&data->work->delayed);
|
||||
k_delayed_work_submit(&data->work->delayed, K_MSEC(data->debounce_period));
|
||||
} else {
|
||||
k_work_submit(&data->work->direct);
|
||||
}
|
||||
static void kscan_gpio_irq_callback_handler(struct device *dev, struct gpio_callback *cb,
|
||||
gpio_port_pins_t pin) {
|
||||
struct kscan_gpio_irq_callback *data =
|
||||
CONTAINER_OF(cb, struct kscan_gpio_irq_callback, callback);
|
||||
|
||||
if (data->debounce_period > 0) {
|
||||
k_delayed_work_cancel(&data->work->delayed);
|
||||
k_delayed_work_submit(&data->work->delayed, K_MSEC(data->debounce_period));
|
||||
} else {
|
||||
k_work_submit(&data->work->direct);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
|
||||
#else /* !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
|
||||
|
||||
static void kscan_gpio_timer_handler(struct k_timer *timer)
|
||||
{
|
||||
struct kscan_gpio_data *data =
|
||||
CONTAINER_OF(timer, struct kscan_gpio_data, poll_timer);
|
||||
static void kscan_gpio_timer_handler(struct k_timer *timer) {
|
||||
struct kscan_gpio_data *data = CONTAINER_OF(timer, struct kscan_gpio_data, poll_timer);
|
||||
|
||||
k_work_submit(&data->work.direct);
|
||||
k_work_submit(&data->work.direct);
|
||||
}
|
||||
|
||||
static int kscan_gpio_direct_enable(struct device *dev)
|
||||
{
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10));
|
||||
return 0;
|
||||
static int kscan_gpio_direct_enable(struct device *dev) {
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10));
|
||||
return 0;
|
||||
}
|
||||
static int kscan_gpio_direct_disable(struct device *dev)
|
||||
{
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
k_timer_stop(&data->poll_timer);
|
||||
return 0;
|
||||
static int kscan_gpio_direct_disable(struct device *dev) {
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
k_timer_stop(&data->poll_timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
|
||||
|
||||
static int kscan_gpio_direct_configure(struct device *dev, kscan_callback_t callback)
|
||||
{
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
if (!callback)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
data->callback = callback;
|
||||
return 0;
|
||||
static int kscan_gpio_direct_configure(struct device *dev, kscan_callback_t callback) {
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
if (!callback) {
|
||||
return -EINVAL;
|
||||
}
|
||||
data->callback = callback;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kscan_gpio_read(struct device *dev)
|
||||
{
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
const struct kscan_gpio_config *cfg = dev->config_info;
|
||||
u32_t read_state = data->pin_state;
|
||||
for (int i = 0; i < cfg->num_of_inputs; i++)
|
||||
{
|
||||
struct device *in_dev = kscan_gpio_input_devices(dev)[i];
|
||||
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i];
|
||||
WRITE_BIT(read_state, i, gpio_pin_get(in_dev, in_cfg->pin) > 0);
|
||||
}
|
||||
for (int i = 0; i < cfg->num_of_inputs; i++)
|
||||
{
|
||||
bool prev_pressed = BIT(i) & data->pin_state;
|
||||
bool pressed = BIT(i) & read_state;
|
||||
if (pressed != prev_pressed)
|
||||
{
|
||||
LOG_DBG("Sending event at %d,%d state %s",
|
||||
0, i, (pressed ? "on" : "off"));
|
||||
WRITE_BIT(data->pin_state, i, pressed);
|
||||
data->callback(dev, 0, i, pressed);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
static int kscan_gpio_read(struct device *dev) {
|
||||
struct kscan_gpio_data *data = dev->driver_data;
|
||||
const struct kscan_gpio_config *cfg = dev->config_info;
|
||||
u32_t read_state = data->pin_state;
|
||||
for (int i = 0; i < cfg->num_of_inputs; i++) {
|
||||
struct device *in_dev = kscan_gpio_input_devices(dev)[i];
|
||||
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i];
|
||||
WRITE_BIT(read_state, i, gpio_pin_get(in_dev, in_cfg->pin) > 0);
|
||||
}
|
||||
for (int i = 0; i < cfg->num_of_inputs; i++) {
|
||||
bool prev_pressed = BIT(i) & data->pin_state;
|
||||
bool pressed = BIT(i) & read_state;
|
||||
if (pressed != prev_pressed) {
|
||||
LOG_DBG("Sending event at %d,%d state %s", 0, i, (pressed ? "on" : "off"));
|
||||
WRITE_BIT(data->pin_state, i, pressed);
|
||||
data->callback(dev, 0, i, pressed);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kscan_gpio_work_handler(struct k_work *work)
|
||||
{
|
||||
struct kscan_gpio_data *data =
|
||||
CONTAINER_OF(work, struct kscan_gpio_data, work);
|
||||
kscan_gpio_read(data->dev);
|
||||
static void kscan_gpio_work_handler(struct k_work *work) {
|
||||
struct kscan_gpio_data *data = CONTAINER_OF(work, struct kscan_gpio_data, work);
|
||||
kscan_gpio_read(data->dev);
|
||||
}
|
||||
|
||||
static const struct kscan_driver_api gpio_driver_api = {
|
||||
.config = kscan_gpio_direct_configure,
|
||||
.enable_callback = kscan_gpio_direct_enable,
|
||||
.disable_callback = kscan_gpio_direct_disable,
|
||||
.config = kscan_gpio_direct_configure,
|
||||
.enable_callback = kscan_gpio_direct_enable,
|
||||
.disable_callback = kscan_gpio_direct_disable,
|
||||
};
|
||||
|
||||
#define KSCAN_DIRECT_INPUT_ITEM(i,n) \
|
||||
{ \
|
||||
.label = DT_INST_GPIO_LABEL_BY_IDX(n, input_gpios, i), \
|
||||
.pin = DT_INST_GPIO_PIN_BY_IDX(n, input_gpios, i), \
|
||||
.flags = DT_INST_GPIO_FLAGS_BY_IDX(n, input_gpios, i), \
|
||||
},
|
||||
#define KSCAN_DIRECT_INPUT_ITEM(i, n) \
|
||||
{ \
|
||||
.label = DT_INST_GPIO_LABEL_BY_IDX(n, input_gpios, i), \
|
||||
.pin = DT_INST_GPIO_PIN_BY_IDX(n, input_gpios, i), \
|
||||
.flags = DT_INST_GPIO_FLAGS_BY_IDX(n, input_gpios, i), \
|
||||
},
|
||||
|
||||
#define INST_INPUT_LEN(n) DT_INST_PROP_LEN(n, input_gpios)
|
||||
|
||||
#define GPIO_INST_INIT(n) \
|
||||
COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, (static struct kscan_gpio_irq_callback \
|
||||
irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \
|
||||
static struct kscan_gpio_data kscan_gpio_data_##n = { \
|
||||
.inputs = { [INST_INPUT_LEN(n)-1] = NULL } \
|
||||
}; \
|
||||
static int kscan_gpio_init_##n(struct device *dev) \
|
||||
{ \
|
||||
struct kscan_gpio_data *data = dev->driver_data; \
|
||||
const struct kscan_gpio_config *cfg = dev->config_info; \
|
||||
int err; \
|
||||
struct device **input_devices = kscan_gpio_input_devices(dev); \
|
||||
for (int i = 0; i < cfg->num_of_inputs; i++) \
|
||||
{ \
|
||||
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i]; \
|
||||
input_devices[i] = device_get_binding(in_cfg->label); \
|
||||
if (!input_devices[i]) \
|
||||
{ \
|
||||
LOG_ERR("Unable to find input GPIO device"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
|
||||
if (err) \
|
||||
{ \
|
||||
LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
|
||||
return err; \
|
||||
} \
|
||||
COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, \
|
||||
( \
|
||||
irq_callbacks_##n[i].work = &data->work; \
|
||||
irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \
|
||||
gpio_init_callback(&irq_callbacks_##n[i].callback, kscan_gpio_irq_callback_handler, BIT(in_cfg->pin)); \
|
||||
err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
|
||||
if (err) \
|
||||
{ \
|
||||
LOG_ERR("Error adding the callback to the column device"); \
|
||||
return err; \
|
||||
} \
|
||||
), ()) \
|
||||
} \
|
||||
data->dev = dev; \
|
||||
COND_CODE_1(CONFIG_ZMK_KSCAN_GPIO_POLLING, (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ( )) \
|
||||
if (cfg->debounce_period > 0) { \
|
||||
k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \
|
||||
} else { \
|
||||
k_work_init(&data->work.direct, kscan_gpio_work_handler); \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
static const struct kscan_gpio_config kscan_gpio_config_##n = { \
|
||||
.inputs = { UTIL_LISTIFY(INST_INPUT_LEN(n), KSCAN_DIRECT_INPUT_ITEM, n) }, \
|
||||
.num_of_inputs = INST_INPUT_LEN(n), \
|
||||
.debounce_period = DT_INST_PROP(n, debounce_period) \
|
||||
}; \
|
||||
DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
|
||||
&kscan_gpio_data_##n, &kscan_gpio_config_##n, \
|
||||
POST_KERNEL, CONFIG_ZMK_KSCAN_INIT_PRIORITY, \
|
||||
&gpio_driver_api);
|
||||
#define GPIO_INST_INIT(n) \
|
||||
COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, \
|
||||
(static struct kscan_gpio_irq_callback irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \
|
||||
static struct kscan_gpio_data kscan_gpio_data_##n = { \
|
||||
.inputs = {[INST_INPUT_LEN(n) - 1] = NULL}}; \
|
||||
static int kscan_gpio_init_##n(struct device *dev) { \
|
||||
struct kscan_gpio_data *data = dev->driver_data; \
|
||||
const struct kscan_gpio_config *cfg = dev->config_info; \
|
||||
int err; \
|
||||
struct device **input_devices = kscan_gpio_input_devices(dev); \
|
||||
for (int i = 0; i < cfg->num_of_inputs; i++) { \
|
||||
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i]; \
|
||||
input_devices[i] = device_get_binding(in_cfg->label); \
|
||||
if (!input_devices[i]) { \
|
||||
LOG_ERR("Unable to find input GPIO device"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
|
||||
if (err) { \
|
||||
LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
|
||||
return err; \
|
||||
} \
|
||||
COND_CODE_0( \
|
||||
CONFIG_ZMK_KSCAN_GPIO_POLLING, \
|
||||
(irq_callbacks_##n[i].work = &data->work; \
|
||||
irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \
|
||||
gpio_init_callback(&irq_callbacks_##n[i].callback, \
|
||||
kscan_gpio_irq_callback_handler, BIT(in_cfg->pin)); \
|
||||
err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
|
||||
if (err) { \
|
||||
LOG_ERR("Error adding the callback to the column device"); \
|
||||
return err; \
|
||||
}), \
|
||||
()) \
|
||||
} \
|
||||
data->dev = dev; \
|
||||
COND_CODE_1(CONFIG_ZMK_KSCAN_GPIO_POLLING, \
|
||||
(k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \
|
||||
if (cfg->debounce_period > 0) { \
|
||||
k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \
|
||||
} else { \
|
||||
k_work_init(&data->work.direct, kscan_gpio_work_handler); \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
static const struct kscan_gpio_config kscan_gpio_config_##n = { \
|
||||
.inputs = {UTIL_LISTIFY(INST_INPUT_LEN(n), KSCAN_DIRECT_INPUT_ITEM, n)}, \
|
||||
.num_of_inputs = INST_INPUT_LEN(n), \
|
||||
.debounce_period = DT_INST_PROP(n, debounce_period)}; \
|
||||
DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
|
||||
&kscan_gpio_data_##n, &kscan_gpio_config_##n, POST_KERNEL, \
|
||||
CONFIG_ZMK_KSCAN_INIT_PRIORITY, &gpio_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -15,266 +15,248 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
struct kscan_gpio_item_config
|
||||
{
|
||||
char *label;
|
||||
gpio_pin_t pin;
|
||||
gpio_flags_t flags;
|
||||
struct kscan_gpio_item_config {
|
||||
char *label;
|
||||
gpio_pin_t pin;
|
||||
gpio_flags_t flags;
|
||||
};
|
||||
|
||||
|
||||
#define _KSCAN_GPIO_ITEM_CFG_INIT(n, prop, idx) \
|
||||
{ \
|
||||
.label = DT_INST_GPIO_LABEL_BY_IDX(n, prop, idx), \
|
||||
.pin = DT_INST_GPIO_PIN_BY_IDX(n, prop, idx), \
|
||||
.flags = DT_INST_GPIO_FLAGS_BY_IDX(n, prop, idx), \
|
||||
},
|
||||
#define _KSCAN_GPIO_ITEM_CFG_INIT(n, prop, idx) \
|
||||
{ \
|
||||
.label = DT_INST_GPIO_LABEL_BY_IDX(n, prop, idx), \
|
||||
.pin = DT_INST_GPIO_PIN_BY_IDX(n, prop, idx), \
|
||||
.flags = DT_INST_GPIO_FLAGS_BY_IDX(n, prop, idx), \
|
||||
},
|
||||
|
||||
#define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx)
|
||||
#define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx)
|
||||
|
||||
|
||||
static int kscan_gpio_config_interrupts(struct device **devices,
|
||||
const struct kscan_gpio_item_config *configs,
|
||||
size_t len, gpio_flags_t flags)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
struct device *dev = devices[i];
|
||||
const struct kscan_gpio_item_config *cfg = &configs[i];
|
||||
const struct kscan_gpio_item_config *configs, size_t len,
|
||||
gpio_flags_t flags) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
struct device *dev = devices[i];
|
||||
const struct kscan_gpio_item_config *cfg = &configs[i];
|
||||
|
||||
int err = gpio_pin_interrupt_configure(dev, cfg->pin, flags);
|
||||
int err = gpio_pin_interrupt_configure(dev, cfg->pin, flags);
|
||||
|
||||
if (err)
|
||||
{
|
||||
LOG_ERR("Unable to enable matrix GPIO interrupt");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
LOG_ERR("Unable to enable matrix GPIO interrupt");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
#define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios)
|
||||
#define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios)
|
||||
#define INST_OUTPUT_LEN(n) COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (INST_MATRIX_ROWS(n)), (INST_MATRIX_COLS(n)))
|
||||
#define INST_INPUT_LEN(n) COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (INST_MATRIX_COLS(n)), (INST_MATRIX_ROWS(n)))
|
||||
#define INST_OUTPUT_LEN(n) \
|
||||
COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (INST_MATRIX_ROWS(n)), \
|
||||
(INST_MATRIX_COLS(n)))
|
||||
#define INST_INPUT_LEN(n) \
|
||||
COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (INST_MATRIX_COLS(n)), \
|
||||
(INST_MATRIX_ROWS(n)))
|
||||
|
||||
#define GPIO_INST_INIT(n) \
|
||||
struct kscan_gpio_irq_callback_##n \
|
||||
{ \
|
||||
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \
|
||||
struct gpio_callback callback; \
|
||||
}; \
|
||||
static struct kscan_gpio_irq_callback_##n \
|
||||
irq_callbacks_##n[INST_INPUT_LEN(n)]; \
|
||||
struct kscan_gpio_config_##n \
|
||||
{ \
|
||||
struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \
|
||||
struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \
|
||||
}; \
|
||||
struct kscan_gpio_data_##n \
|
||||
{ \
|
||||
kscan_callback_t callback; \
|
||||
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \
|
||||
bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
|
||||
struct device *rows[INST_MATRIX_ROWS(n)]; \
|
||||
struct device *cols[INST_MATRIX_COLS(n)]; \
|
||||
struct device *dev; \
|
||||
}; \
|
||||
static struct device **kscan_gpio_input_devices_##n(struct device *dev) \
|
||||
{ \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->cols), (data->rows))); \
|
||||
} \
|
||||
static const struct kscan_gpio_item_config *kscan_gpio_input_configs_##n(struct device *dev) \
|
||||
{ \
|
||||
const struct kscan_gpio_config_##n *cfg = dev->config_info; \
|
||||
return ((COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->cols), (cfg->rows)))); \
|
||||
} \
|
||||
static struct device **kscan_gpio_output_devices_##n(struct device *dev) \
|
||||
{ \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->rows), (data->cols))); \
|
||||
} \
|
||||
static const struct kscan_gpio_item_config *kscan_gpio_output_configs_##n(struct device *dev) \
|
||||
{ \
|
||||
const struct kscan_gpio_config_##n *cfg = dev->config_info; \
|
||||
return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \
|
||||
} \
|
||||
static int kscan_gpio_enable_interrupts_##n(struct device *dev) \
|
||||
{ \
|
||||
return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
|
||||
GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \
|
||||
} \
|
||||
static int kscan_gpio_disable_interrupts_##n(struct device *dev) \
|
||||
{ \
|
||||
return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
|
||||
GPIO_INT_DISABLE); \
|
||||
} \
|
||||
static void kscan_gpio_set_output_state_##n(struct device *dev, int value) \
|
||||
{ \
|
||||
for (int i = 0; i < INST_OUTPUT_LEN(n); i++) \
|
||||
{ \
|
||||
struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \
|
||||
const struct kscan_gpio_item_config *cfg = &kscan_gpio_output_configs_##n(dev)[i]; \
|
||||
gpio_pin_set(in_dev, cfg->pin, value); \
|
||||
} \
|
||||
} \
|
||||
static void kscan_gpio_set_matrix_state_##n(bool state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)], u32_t input_index, u32_t output_index, bool value) \
|
||||
{ \
|
||||
state[COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (output_index), (input_index))][COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (input_index), (output_index))] = value; \
|
||||
} \
|
||||
static int kscan_gpio_read_##n(struct device *dev) \
|
||||
{ \
|
||||
bool submit_follow_up_read = false; \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
|
||||
/* Disable our interrupts temporarily while we scan, to avoid */ \
|
||||
/* re-entry while we iterate columns and set them active one by one */ \
|
||||
/* to get pressed state for each matrix cell. */ \
|
||||
kscan_gpio_disable_interrupts_##n(dev); \
|
||||
kscan_gpio_set_output_state_##n(dev, 0); \
|
||||
for (int o = 0; o < INST_OUTPUT_LEN(n); o++) \
|
||||
{ \
|
||||
struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \
|
||||
const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
|
||||
gpio_pin_set(out_dev, out_cfg->pin, 1); \
|
||||
for (int i = 0; i < INST_INPUT_LEN(n); i++) \
|
||||
{ \
|
||||
struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \
|
||||
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs_##n(dev)[i]; \
|
||||
kscan_gpio_set_matrix_state_##n(read_state, i, o, gpio_pin_get(in_dev, in_cfg->pin) > 0); \
|
||||
} \
|
||||
gpio_pin_set(out_dev, out_cfg->pin, 0); \
|
||||
} \
|
||||
/* Set all our outputs as active again, then re-enable interrupts, */ \
|
||||
/* so we can trigger interrupts again for future press/release */ \
|
||||
kscan_gpio_set_output_state_##n(dev, 1); \
|
||||
kscan_gpio_enable_interrupts_##n(dev); \
|
||||
for (int r = 0; r < INST_MATRIX_ROWS(n); r++) \
|
||||
{ \
|
||||
for (int c = 0; c < INST_MATRIX_COLS(n); c++) \
|
||||
{ \
|
||||
bool pressed = read_state[r][c]; \
|
||||
/* Follow up reads needed because further interrupts won't fire on already tripped input GPIO pins */ \
|
||||
submit_follow_up_read = (submit_follow_up_read || pressed); \
|
||||
if (pressed != data->matrix_state[r][c]) \
|
||||
{ \
|
||||
LOG_DBG("Sending event at %d,%d state %s", \
|
||||
r, c, (pressed ? "on" : "off")); \
|
||||
data->matrix_state[r][c] = pressed; \
|
||||
data->callback(dev, r, c, pressed); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (submit_follow_up_read) { \
|
||||
COND_CODE_0(DT_INST_PROP(n, debounce_period), \
|
||||
({ k_work_submit(&data->work); }), \
|
||||
({ \
|
||||
k_delayed_work_cancel(&data->work); \
|
||||
k_delayed_work_submit(&data->work, K_MSEC(5)); })) \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
static void kscan_gpio_work_handler_##n(struct k_work *work) \
|
||||
{ \
|
||||
struct kscan_gpio_data_##n *data = \
|
||||
CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \
|
||||
kscan_gpio_read_##n(data->dev); \
|
||||
} \
|
||||
static void kscan_gpio_irq_callback_handler_##n(struct device *dev, \
|
||||
struct gpio_callback *cb, gpio_port_pins_t pin) \
|
||||
{ \
|
||||
struct kscan_gpio_irq_callback_##n *data = \
|
||||
CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \
|
||||
COND_CODE_0(DT_INST_PROP(n, debounce_period), \
|
||||
({ k_work_submit(data->work); }), \
|
||||
({ \
|
||||
k_delayed_work_cancel(data->work); \
|
||||
k_delayed_work_submit(data->work, K_MSEC(DT_INST_PROP(n, debounce_period))); })) \
|
||||
} \
|
||||
static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
|
||||
.rows = { [INST_MATRIX_ROWS(n)-1] = NULL}, \
|
||||
.cols = { [INST_MATRIX_COLS(n)-1] = NULL }\
|
||||
}; \
|
||||
static int kscan_gpio_configure_##n(struct device *dev, kscan_callback_t callback) \
|
||||
{ \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
if (!callback) \
|
||||
{ \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
data->callback = callback; \
|
||||
return 0; \
|
||||
}; \
|
||||
static int kscan_gpio_enable_##n(struct device *dev) \
|
||||
{ \
|
||||
int err = kscan_gpio_enable_interrupts_##n(dev); \
|
||||
if (err) { return err; } \
|
||||
return kscan_gpio_read_##n(dev); \
|
||||
}; \
|
||||
static int kscan_gpio_init_##n(struct device *dev) \
|
||||
{ \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
int err; \
|
||||
struct device **input_devices = kscan_gpio_input_devices_##n(dev); \
|
||||
for (int i = 0; i < INST_INPUT_LEN(n); i++) \
|
||||
{ \
|
||||
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs_##n(dev)[i]; \
|
||||
input_devices[i] = device_get_binding(in_cfg->label); \
|
||||
if (!input_devices[i]) \
|
||||
{ \
|
||||
LOG_ERR("Unable to find input GPIO device"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
|
||||
if (err) \
|
||||
{ \
|
||||
LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
|
||||
return err; \
|
||||
} \
|
||||
irq_callbacks_##n[i].work = &data->work; \
|
||||
gpio_init_callback(&irq_callbacks_##n[i].callback, kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \
|
||||
err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
|
||||
if (err) \
|
||||
{ \
|
||||
LOG_ERR("Error adding the callback to the column device"); \
|
||||
return err; \
|
||||
} \
|
||||
} \
|
||||
struct device **output_devices = kscan_gpio_output_devices_##n(dev); \
|
||||
for (int o = 0; o < INST_OUTPUT_LEN(n); o++) \
|
||||
{ \
|
||||
const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
|
||||
output_devices[o] = device_get_binding(out_cfg->label); \
|
||||
if (!output_devices[o]) \
|
||||
{ \
|
||||
LOG_ERR("Unable to find output GPIO device"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
err = gpio_pin_configure(output_devices[o], out_cfg->pin, GPIO_OUTPUT_ACTIVE | out_cfg->flags); \
|
||||
if (err) \
|
||||
{ \
|
||||
LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, out_cfg->label); \
|
||||
return err; \
|
||||
} \
|
||||
} \
|
||||
data->dev = dev; \
|
||||
(COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))(&data->work, kscan_gpio_work_handler_##n); \
|
||||
return 0; \
|
||||
} \
|
||||
static const struct kscan_driver_api gpio_driver_api_##n = { \
|
||||
.config = kscan_gpio_configure_##n, \
|
||||
.enable_callback = kscan_gpio_enable_##n, \
|
||||
.disable_callback = kscan_gpio_disable_interrupts_##n, \
|
||||
}; \
|
||||
static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \
|
||||
.rows = { UTIL_LISTIFY(INST_MATRIX_ROWS(n), _KSCAN_GPIO_ROW_CFG_INIT, n) }, \
|
||||
.cols = { UTIL_LISTIFY(INST_MATRIX_COLS(n), _KSCAN_GPIO_COL_CFG_INIT, n) }, \
|
||||
}; \
|
||||
DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
|
||||
&kscan_gpio_data_##n, &kscan_gpio_config_##n, \
|
||||
APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, \
|
||||
&gpio_driver_api_##n);
|
||||
#define GPIO_INST_INIT(n) \
|
||||
struct kscan_gpio_irq_callback_##n { \
|
||||
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \
|
||||
struct gpio_callback callback; \
|
||||
}; \
|
||||
static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \
|
||||
struct kscan_gpio_config_##n { \
|
||||
struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \
|
||||
struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \
|
||||
}; \
|
||||
struct kscan_gpio_data_##n { \
|
||||
kscan_callback_t callback; \
|
||||
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \
|
||||
bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
|
||||
struct device *rows[INST_MATRIX_ROWS(n)]; \
|
||||
struct device *cols[INST_MATRIX_COLS(n)]; \
|
||||
struct device *dev; \
|
||||
}; \
|
||||
static struct device **kscan_gpio_input_devices_##n(struct device *dev) { \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->cols), \
|
||||
(data->rows))); \
|
||||
} \
|
||||
static const struct kscan_gpio_item_config *kscan_gpio_input_configs_##n(struct device *dev) { \
|
||||
const struct kscan_gpio_config_##n *cfg = dev->config_info; \
|
||||
return (( \
|
||||
COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->cols), (cfg->rows)))); \
|
||||
} \
|
||||
static struct device **kscan_gpio_output_devices_##n(struct device *dev) { \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->rows), \
|
||||
(data->cols))); \
|
||||
} \
|
||||
static const struct kscan_gpio_item_config *kscan_gpio_output_configs_##n( \
|
||||
struct device *dev) { \
|
||||
const struct kscan_gpio_config_##n *cfg = dev->config_info; \
|
||||
return ( \
|
||||
COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \
|
||||
} \
|
||||
static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \
|
||||
return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \
|
||||
kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
|
||||
GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \
|
||||
} \
|
||||
static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \
|
||||
return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \
|
||||
kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
|
||||
GPIO_INT_DISABLE); \
|
||||
} \
|
||||
static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \
|
||||
for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \
|
||||
struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \
|
||||
const struct kscan_gpio_item_config *cfg = &kscan_gpio_output_configs_##n(dev)[i]; \
|
||||
gpio_pin_set(in_dev, cfg->pin, value); \
|
||||
} \
|
||||
} \
|
||||
static void kscan_gpio_set_matrix_state_##n( \
|
||||
bool state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)], u32_t input_index, \
|
||||
u32_t output_index, bool value) { \
|
||||
state[COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (output_index), \
|
||||
(input_index))] \
|
||||
[COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (input_index), \
|
||||
(output_index))] = value; \
|
||||
} \
|
||||
static int kscan_gpio_read_##n(struct device *dev) { \
|
||||
bool submit_follow_up_read = false; \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
|
||||
/* Disable our interrupts temporarily while we scan, to avoid */ \
|
||||
/* re-entry while we iterate columns and set them active one by one */ \
|
||||
/* to get pressed state for each matrix cell. */ \
|
||||
kscan_gpio_disable_interrupts_##n(dev); \
|
||||
kscan_gpio_set_output_state_##n(dev, 0); \
|
||||
for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
|
||||
struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \
|
||||
const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
|
||||
gpio_pin_set(out_dev, out_cfg->pin, 1); \
|
||||
for (int i = 0; i < INST_INPUT_LEN(n); i++) { \
|
||||
struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \
|
||||
const struct kscan_gpio_item_config *in_cfg = \
|
||||
&kscan_gpio_input_configs_##n(dev)[i]; \
|
||||
kscan_gpio_set_matrix_state_##n(read_state, i, o, \
|
||||
gpio_pin_get(in_dev, in_cfg->pin) > 0); \
|
||||
} \
|
||||
gpio_pin_set(out_dev, out_cfg->pin, 0); \
|
||||
} \
|
||||
/* Set all our outputs as active again, then re-enable interrupts, */ \
|
||||
/* so we can trigger interrupts again for future press/release */ \
|
||||
kscan_gpio_set_output_state_##n(dev, 1); \
|
||||
kscan_gpio_enable_interrupts_##n(dev); \
|
||||
for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \
|
||||
for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \
|
||||
bool pressed = read_state[r][c]; \
|
||||
/* Follow up reads needed because further interrupts won't fire on already tripped \
|
||||
* input GPIO pins */ \
|
||||
submit_follow_up_read = (submit_follow_up_read || pressed); \
|
||||
if (pressed != data->matrix_state[r][c]) { \
|
||||
LOG_DBG("Sending event at %d,%d state %s", r, c, (pressed ? "on" : "off")); \
|
||||
data->matrix_state[r][c] = pressed; \
|
||||
data->callback(dev, r, c, pressed); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (submit_follow_up_read) { \
|
||||
COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(&data->work); }), ({ \
|
||||
k_delayed_work_cancel(&data->work); \
|
||||
k_delayed_work_submit(&data->work, K_MSEC(5)); \
|
||||
})) \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
static void kscan_gpio_work_handler_##n(struct k_work *work) { \
|
||||
struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \
|
||||
kscan_gpio_read_##n(data->dev); \
|
||||
} \
|
||||
static void kscan_gpio_irq_callback_handler_##n(struct device *dev, struct gpio_callback *cb, \
|
||||
gpio_port_pins_t pin) { \
|
||||
struct kscan_gpio_irq_callback_##n *data = \
|
||||
CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \
|
||||
COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \
|
||||
k_delayed_work_cancel(data->work); \
|
||||
k_delayed_work_submit(data->work, \
|
||||
K_MSEC(DT_INST_PROP(n, debounce_period))); \
|
||||
})) \
|
||||
} \
|
||||
static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
|
||||
.rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \
|
||||
static int kscan_gpio_configure_##n(struct device *dev, kscan_callback_t callback) { \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
if (!callback) { \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
data->callback = callback; \
|
||||
return 0; \
|
||||
}; \
|
||||
static int kscan_gpio_enable_##n(struct device *dev) { \
|
||||
int err = kscan_gpio_enable_interrupts_##n(dev); \
|
||||
if (err) { \
|
||||
return err; \
|
||||
} \
|
||||
return kscan_gpio_read_##n(dev); \
|
||||
}; \
|
||||
static int kscan_gpio_init_##n(struct device *dev) { \
|
||||
struct kscan_gpio_data_##n *data = dev->driver_data; \
|
||||
int err; \
|
||||
struct device **input_devices = kscan_gpio_input_devices_##n(dev); \
|
||||
for (int i = 0; i < INST_INPUT_LEN(n); i++) { \
|
||||
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs_##n(dev)[i]; \
|
||||
input_devices[i] = device_get_binding(in_cfg->label); \
|
||||
if (!input_devices[i]) { \
|
||||
LOG_ERR("Unable to find input GPIO device"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
|
||||
if (err) { \
|
||||
LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
|
||||
return err; \
|
||||
} \
|
||||
irq_callbacks_##n[i].work = &data->work; \
|
||||
gpio_init_callback(&irq_callbacks_##n[i].callback, \
|
||||
kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \
|
||||
err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
|
||||
if (err) { \
|
||||
LOG_ERR("Error adding the callback to the column device"); \
|
||||
return err; \
|
||||
} \
|
||||
} \
|
||||
struct device **output_devices = kscan_gpio_output_devices_##n(dev); \
|
||||
for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
|
||||
const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
|
||||
output_devices[o] = device_get_binding(out_cfg->label); \
|
||||
if (!output_devices[o]) { \
|
||||
LOG_ERR("Unable to find output GPIO device"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
err = gpio_pin_configure(output_devices[o], out_cfg->pin, \
|
||||
GPIO_OUTPUT_ACTIVE | out_cfg->flags); \
|
||||
if (err) { \
|
||||
LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, \
|
||||
out_cfg->label); \
|
||||
return err; \
|
||||
} \
|
||||
} \
|
||||
data->dev = dev; \
|
||||
(COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \
|
||||
&data->work, kscan_gpio_work_handler_##n); \
|
||||
return 0; \
|
||||
} \
|
||||
static const struct kscan_driver_api gpio_driver_api_##n = { \
|
||||
.config = kscan_gpio_configure_##n, \
|
||||
.enable_callback = kscan_gpio_enable_##n, \
|
||||
.disable_callback = kscan_gpio_disable_interrupts_##n, \
|
||||
}; \
|
||||
static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \
|
||||
.rows = {UTIL_LISTIFY(INST_MATRIX_ROWS(n), _KSCAN_GPIO_ROW_CFG_INIT, n)}, \
|
||||
.cols = {UTIL_LISTIFY(INST_MATRIX_COLS(n), _KSCAN_GPIO_COL_CFG_INIT, n)}, \
|
||||
}; \
|
||||
DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
|
||||
&kscan_gpio_data_##n, &kscan_gpio_config_##n, APPLICATION, \
|
||||
CONFIG_APPLICATION_INIT_PRIORITY, &gpio_driver_api_##n);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT)
|
||||
|
||||
|
|
|
@ -7,4 +7,5 @@
|
|||
#include <behaviors/toggle_layer.dtsi>
|
||||
#include <behaviors/reset.dtsi>
|
||||
#include <behaviors/sensor_rotate_key_press.dtsi>
|
||||
#include <behaviors/rgb_underglow.dtsi>
|
||||
#include <behaviors/rgb_underglow.dtsi>
|
||||
#include <behaviors/bluetooth.dtsi>
|
9
app/dts/behaviors/bluetooth.dtsi
Normal file
9
app/dts/behaviors/bluetooth.dtsi
Normal file
|
@ -0,0 +1,9 @@
|
|||
/ {
|
||||
behaviors {
|
||||
bt: behavior_bluetooth {
|
||||
compatible = "zmk,behavior-bluetooth";
|
||||
label = "BLUETOOTH";
|
||||
#binding-cells = <2>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Cody McGinnis <brainwart@gmail.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/ {
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
tog: behavior_toggle_layer {
|
||||
compatible = "zmk,behavior-toggle-layer";
|
||||
|
|
8
app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml
Normal file
8
app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2020, Peter Johanson
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: Bluetooth Behavior
|
||||
|
||||
compatible: "zmk,behavior-bluetooth"
|
||||
|
||||
include: two_param.yaml
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2020, Cody McGinnis; Okke Formsma
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: Hold or Tap behavior
|
||||
|
@ -12,12 +12,12 @@ properties:
|
|||
type: phandles
|
||||
required: true
|
||||
tapping_term_ms:
|
||||
type: int
|
||||
type: int
|
||||
flavor:
|
||||
type: string
|
||||
required: false
|
||||
default: "hold-preferred"
|
||||
enum:
|
||||
- "hold-preferred"
|
||||
- "balanced"
|
||||
- "tap-preferred"
|
||||
- "hold-preferred"
|
||||
- "balanced"
|
||||
- "tap-preferred"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Copyright (c) 2020, Nick Winans
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: RGB Underglow Action
|
||||
|
||||
compatible: "zmk,behavior-rgb-underglow"
|
||||
|
||||
include: one_param.yaml
|
||||
include: one_param.yaml
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2020, Cody McGinnis <brainwart@gmail.com>
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: Toggle Layer
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -19,19 +19,20 @@
|
|||
* (Internal use only.)
|
||||
*/
|
||||
|
||||
typedef int (*behavior_keymap_binding_callback_t)(struct device *dev, u32_t position, u32_t param1, u32_t param2);
|
||||
typedef int (*behavior_sensor_keymap_binding_callback_t)(struct device *dev, struct device *sensor, u32_t param1, u32_t param2);
|
||||
typedef int (*behavior_keymap_binding_callback_t)(struct device *dev, u32_t position, u32_t param1,
|
||||
u32_t param2);
|
||||
typedef int (*behavior_sensor_keymap_binding_callback_t)(struct device *dev, struct device *sensor,
|
||||
u32_t param1, u32_t param2);
|
||||
|
||||
__subsystem struct behavior_driver_api {
|
||||
behavior_keymap_binding_callback_t binding_pressed;
|
||||
behavior_keymap_binding_callback_t binding_released;
|
||||
behavior_sensor_keymap_binding_callback_t sensor_binding_triggered;
|
||||
behavior_keymap_binding_callback_t binding_pressed;
|
||||
behavior_keymap_binding_callback_t binding_released;
|
||||
behavior_sensor_keymap_binding_callback_t sensor_binding_triggered;
|
||||
};
|
||||
/**
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle the keymap binding being pressed
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
|
@ -41,18 +42,18 @@ __subsystem struct behavior_driver_api {
|
|||
* @retval 0 If successful.
|
||||
* @retval Negative errno code if failure.
|
||||
*/
|
||||
__syscall int behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1, u32_t param2);
|
||||
__syscall int behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1,
|
||||
u32_t param2);
|
||||
|
||||
static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1, u32_t param2)
|
||||
{
|
||||
const struct behavior_driver_api *api =
|
||||
(const struct behavior_driver_api *)dev->driver_api;
|
||||
static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32_t position,
|
||||
u32_t param1, u32_t param2) {
|
||||
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
|
||||
|
||||
if (api->binding_pressed == NULL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
if (api->binding_pressed == NULL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return api->binding_pressed(dev, position, param1, param2);
|
||||
return api->binding_pressed(dev, position, param1, param2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,18 +64,18 @@ static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32
|
|||
* @retval 0 If successful.
|
||||
* @retval Negative errno code if failure.
|
||||
*/
|
||||
__syscall int behavior_keymap_binding_released(struct device *dev, u32_t position, u32_t param1, u32_t param2);
|
||||
__syscall int behavior_keymap_binding_released(struct device *dev, u32_t position, u32_t param1,
|
||||
u32_t param2);
|
||||
|
||||
static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u32_t position, u32_t param1, u32_t param2)
|
||||
{
|
||||
const struct behavior_driver_api *api =
|
||||
(const struct behavior_driver_api *)dev->driver_api;
|
||||
static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u32_t position,
|
||||
u32_t param1, u32_t param2) {
|
||||
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
|
||||
|
||||
if (api->binding_released == NULL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
if (api->binding_released == NULL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return api->binding_released(dev, position, param1, param2);
|
||||
return api->binding_released(dev, position, param1, param2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,21 +88,21 @@ static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u3
|
|||
* @retval 0 If successful.
|
||||
* @retval Negative errno code if failure.
|
||||
*/
|
||||
__syscall int behavior_sensor_keymap_binding_triggered(struct device *dev, struct device *sensor, u32_t param1, u32_t param2);
|
||||
__syscall int behavior_sensor_keymap_binding_triggered(struct device *dev, struct device *sensor,
|
||||
u32_t param1, u32_t param2);
|
||||
|
||||
static inline int z_impl_behavior_sensor_keymap_binding_triggered(struct device *dev, struct device *sensor, u32_t param1, u32_t param2)
|
||||
{
|
||||
const struct behavior_driver_api *api =
|
||||
(const struct behavior_driver_api *)dev->driver_api;
|
||||
static inline int z_impl_behavior_sensor_keymap_binding_triggered(struct device *dev,
|
||||
struct device *sensor,
|
||||
u32_t param1, u32_t param2) {
|
||||
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
|
||||
|
||||
if (api->sensor_binding_triggered == NULL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
if (api->sensor_binding_triggered == NULL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return api->sensor_binding_triggered(dev, sensor, param1, param2);
|
||||
return api->sensor_binding_triggered(dev, sensor, param1, param2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
21
app/include/dt-bindings/zmk/bt.h
Normal file
21
app/include/dt-bindings/zmk/bt.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define BT_CLR_CMD 0
|
||||
#define BT_NXT_CMD 1
|
||||
#define BT_PRV_CMD 2
|
||||
#define BT_SEL_CMD 3
|
||||
// #define BT_FULL_RESET_CMD 4
|
||||
|
||||
/*
|
||||
Note: Some future commands will include additional parameters, so we
|
||||
defines these aliases up front.
|
||||
*/
|
||||
|
||||
#define BT_CLR BT_CLR_CMD 0
|
||||
#define BT_NXT BT_NXT_CMD 0
|
||||
#define BT_PRV BT_PRV_CMD 0
|
||||
#define BT_SEL BT_SEL_CMD
|
|
@ -55,7 +55,7 @@
|
|||
#define QUOT 0x34
|
||||
#define GRAV 0x35
|
||||
#define CMMA 0x36
|
||||
#define DOT 0x37
|
||||
#define DOT 0x37
|
||||
#define FSLH 0x38
|
||||
#define CLCK 0x39
|
||||
#define F1 0x3A
|
||||
|
@ -77,8 +77,8 @@
|
|||
#define INS 0x49
|
||||
#define HOME 0x4A
|
||||
#define PGUP 0x4B
|
||||
#define DEL 0x4C
|
||||
#define END 0x4D
|
||||
#define DEL 0x4C
|
||||
#define END 0x4D
|
||||
#define PGDN 0x4E
|
||||
#define RARW 0x4F
|
||||
#define LARW 0x50
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define RST_WARM 0x00
|
||||
#define RST_COLD 0x01
|
||||
#define RST_WARM 0x00
|
||||
#define RST_COLD 0x01
|
||||
|
||||
// AdaFruit nrf52 Bootloader Specific. See https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
|
||||
// AdaFruit nrf52 Bootloader Specific. See
|
||||
// https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
|
||||
|
||||
#define RST_UF2 0x57
|
||||
#define RST_UF2 0x57
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -1,7 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zmk/keys.h>
|
||||
#include <zmk/ble/profile.h>
|
||||
|
||||
int zmk_ble_clear_bonds();
|
||||
int zmk_ble_prof_next();
|
||||
int zmk_ble_prof_prev();
|
||||
int zmk_ble_prof_select(u8_t index);
|
||||
|
||||
bt_addr_le_t *zmk_ble_active_profile_addr();
|
||||
char *zmk_ble_active_profile_name();
|
||||
|
||||
int zmk_ble_unpair_all();
|
||||
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr);
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
|
16
app/include/zmk/ble/profile.h
Normal file
16
app/include/zmk/ble/profile.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <bluetooth/addr.h>
|
||||
|
||||
#define ZMK_BLE_PROFILE_NAME_MAX 15
|
||||
|
||||
struct zmk_ble_profile {
|
||||
char name[ZMK_BLE_PROFILE_NAME_MAX];
|
||||
bt_addr_le_t peer;
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zmk/keys.h>
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <kernel.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
struct zmk_event_type
|
||||
{
|
||||
struct zmk_event_type {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct zmk_event_header {
|
||||
const struct zmk_event_type* event;
|
||||
const struct zmk_event_type *event;
|
||||
u8_t last_listener_index;
|
||||
};
|
||||
|
||||
|
@ -24,8 +23,7 @@ struct zmk_event_header {
|
|||
#define ZMK_EV_EVENT_CAPTURED 2
|
||||
|
||||
typedef int (*zmk_listener_callback_t)(const struct zmk_event_header *eh);
|
||||
struct zmk_listener
|
||||
{
|
||||
struct zmk_listener {
|
||||
zmk_listener_callback_t callback;
|
||||
};
|
||||
|
||||
|
@ -34,55 +32,50 @@ struct zmk_event_subscription {
|
|||
const struct zmk_listener *listener;
|
||||
};
|
||||
|
||||
#define ZMK_EVENT_DECLARE(event_type) \
|
||||
struct event_type* new_##event_type(); \
|
||||
bool is_##event_type(const struct zmk_event_header *eh); \
|
||||
struct event_type* cast_##event_type(const struct zmk_event_header *eh); \
|
||||
#define ZMK_EVENT_DECLARE(event_type) \
|
||||
struct event_type *new_##event_type(); \
|
||||
bool is_##event_type(const struct zmk_event_header *eh); \
|
||||
struct event_type *cast_##event_type(const struct zmk_event_header *eh); \
|
||||
extern const struct zmk_event_type zmk_event_##event_type;
|
||||
|
||||
#define ZMK_EVENT_IMPL(event_type) \
|
||||
const struct zmk_event_type zmk_event_##event_type = { \
|
||||
.name = STRINGIFY(event_type) \
|
||||
}; \
|
||||
const struct zmk_event_type* zmk_event_ref_##event_type __used __attribute__((__section__(".event_type"))) = &zmk_event_##event_type; \
|
||||
struct event_type* new_##event_type() { \
|
||||
struct event_type* ev = (struct event_type *) k_malloc(sizeof(struct event_type)); \
|
||||
ev->header.event = &zmk_event_##event_type; \
|
||||
return ev; \
|
||||
}; \
|
||||
bool is_##event_type(const struct zmk_event_header *eh) { \
|
||||
return eh->event == &zmk_event_##event_type; \
|
||||
}; \
|
||||
struct event_type* cast_##event_type(const struct zmk_event_header *eh) {\
|
||||
return (struct event_type*)eh; \
|
||||
};
|
||||
|
||||
|
||||
#define ZMK_LISTENER(mod, cb) \
|
||||
const struct zmk_listener zmk_listener_##mod = { \
|
||||
.callback = cb \
|
||||
#define ZMK_EVENT_IMPL(event_type) \
|
||||
const struct zmk_event_type zmk_event_##event_type = {.name = STRINGIFY(event_type)}; \
|
||||
const struct zmk_event_type *zmk_event_ref_##event_type __used \
|
||||
__attribute__((__section__(".event_type"))) = &zmk_event_##event_type; \
|
||||
struct event_type *new_##event_type() { \
|
||||
struct event_type *ev = (struct event_type *)k_malloc(sizeof(struct event_type)); \
|
||||
ev->header.event = &zmk_event_##event_type; \
|
||||
return ev; \
|
||||
}; \
|
||||
bool is_##event_type(const struct zmk_event_header *eh) { \
|
||||
return eh->event == &zmk_event_##event_type; \
|
||||
}; \
|
||||
struct event_type *cast_##event_type(const struct zmk_event_header *eh) { \
|
||||
return (struct event_type *)eh; \
|
||||
};
|
||||
|
||||
#define ZMK_SUBSCRIPTION(mod, ev_type) \
|
||||
const Z_DECL_ALIGN(struct zmk_event_subscription) _CONCAT(_CONCAT(zmk_event_sub_,mod),ev_type) __used __attribute__((__section__(".event_subscription"))) = { \
|
||||
.event_type = &zmk_event_##ev_type, \
|
||||
.listener = &zmk_listener_##mod, \
|
||||
#define ZMK_LISTENER(mod, cb) const struct zmk_listener zmk_listener_##mod = {.callback = cb};
|
||||
|
||||
#define ZMK_SUBSCRIPTION(mod, ev_type) \
|
||||
const Z_DECL_ALIGN(struct zmk_event_subscription) \
|
||||
_CONCAT(_CONCAT(zmk_event_sub_, mod), ev_type) __used \
|
||||
__attribute__((__section__(".event_subscription"))) = { \
|
||||
.event_type = &zmk_event_##ev_type, \
|
||||
.listener = &zmk_listener_##mod, \
|
||||
};
|
||||
|
||||
#define ZMK_EVENT_RAISE(ev) \
|
||||
zmk_event_manager_raise((struct zmk_event_header *)ev);
|
||||
#define ZMK_EVENT_RAISE(ev) zmk_event_manager_raise((struct zmk_event_header *)ev);
|
||||
|
||||
#define ZMK_EVENT_RAISE_AFTER(ev, mod) \
|
||||
#define ZMK_EVENT_RAISE_AFTER(ev, mod) \
|
||||
zmk_event_manager_raise_after((struct zmk_event_header *)ev, &zmk_listener_##mod);
|
||||
|
||||
|
||||
#define ZMK_EVENT_RAISE_AT(ev, mod) \
|
||||
#define ZMK_EVENT_RAISE_AT(ev, mod) \
|
||||
zmk_event_manager_raise_at((struct zmk_event_header *)ev, &zmk_listener_##mod);
|
||||
|
||||
#define ZMK_EVENT_RELEASE(ev) \
|
||||
zmk_event_manager_release((struct zmk_event_header *)ev);
|
||||
#define ZMK_EVENT_RELEASE(ev) zmk_event_manager_release((struct zmk_event_header *)ev);
|
||||
|
||||
int zmk_event_manager_raise(struct zmk_event_header *event);
|
||||
int zmk_event_manager_raise_after(struct zmk_event_header *event, const struct zmk_listener *listener);
|
||||
int zmk_event_manager_raise_after(struct zmk_event_header *event,
|
||||
const struct zmk_listener *listener);
|
||||
int zmk_event_manager_raise_at(struct zmk_event_header *event, const struct zmk_listener *listener);
|
||||
int zmk_event_manager_release(struct zmk_event_header *event);
|
||||
|
|
21
app/include/zmk/events/ble-active-profile-changed.h
Normal file
21
app/include/zmk/events/ble-active-profile-changed.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <zmk/event-manager.h>
|
||||
#include <device.h>
|
||||
|
||||
#include <zmk/ble/profile.h>
|
||||
|
||||
struct ble_active_profile_changed {
|
||||
struct zmk_event_header header;
|
||||
u8_t index;
|
||||
struct zmk_ble_profile *profile;
|
||||
};
|
||||
|
||||
ZMK_EVENT_DECLARE(ble_active_profile_changed);
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -18,9 +18,9 @@ struct keycode_state_changed {
|
|||
|
||||
ZMK_EVENT_DECLARE(keycode_state_changed);
|
||||
|
||||
inline struct keycode_state_changed* create_keycode_state_changed(u8_t usage_page, u32_t keycode, bool state)
|
||||
{
|
||||
struct keycode_state_changed* ev = new_keycode_state_changed();
|
||||
inline struct keycode_state_changed *create_keycode_state_changed(u8_t usage_page, u32_t keycode,
|
||||
bool state) {
|
||||
struct keycode_state_changed *ev = new_keycode_state_changed();
|
||||
ev->usage_page = usage_page;
|
||||
ev->keycode = keycode;
|
||||
ev->state = state;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zephyr.h>
|
||||
|
@ -18,9 +18,9 @@ struct modifiers_state_changed {
|
|||
|
||||
ZMK_EVENT_DECLARE(modifiers_state_changed);
|
||||
|
||||
inline struct modifiers_state_changed* create_modifiers_state_changed(zmk_mod_flags modifiers, bool state)
|
||||
{
|
||||
struct modifiers_state_changed* ev = new_modifiers_state_changed();
|
||||
inline struct modifiers_state_changed *create_modifiers_state_changed(zmk_mod_flags modifiers,
|
||||
bool state) {
|
||||
struct modifiers_state_changed *ev = new_modifiers_state_changed();
|
||||
ev->modifiers = modifiers;
|
||||
ev->state = state;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <usb/usb_device.h>
|
||||
|
@ -134,25 +140,21 @@ static const u8_t zmk_hid_report_desc[] = {
|
|||
// u8_t keys[6];
|
||||
// } __packed;
|
||||
|
||||
struct zmk_hid_keypad_report_body
|
||||
{
|
||||
struct zmk_hid_keypad_report_body {
|
||||
zmk_mod_flags modifiers;
|
||||
u8_t keys[13];
|
||||
} __packed;
|
||||
|
||||
struct zmk_hid_keypad_report
|
||||
{
|
||||
struct zmk_hid_keypad_report {
|
||||
u8_t report_id;
|
||||
struct zmk_hid_keypad_report_body body;
|
||||
} __packed;
|
||||
|
||||
struct zmk_hid_consumer_report_body
|
||||
{
|
||||
struct zmk_hid_consumer_report_body {
|
||||
u8_t keys[6];
|
||||
} __packed;
|
||||
|
||||
struct zmk_hid_consumer_report
|
||||
{
|
||||
struct zmk_hid_consumer_report {
|
||||
u8_t report_id;
|
||||
struct zmk_hid_consumer_report_body body;
|
||||
} __packed;
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
bool zmk_keymap_layer_active(u8_t layer);
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zephyr.h>
|
||||
|
@ -8,8 +14,7 @@ typedef u8_t zmk_action;
|
|||
typedef u8_t zmk_mod;
|
||||
typedef u8_t zmk_mod_flags;
|
||||
|
||||
struct zmk_key_event
|
||||
{
|
||||
struct zmk_key_event {
|
||||
u32_t column;
|
||||
u32_t row;
|
||||
zmk_key key;
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
int zmk_kscan_init(char *name);
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <devicetree.h>
|
||||
|
@ -9,20 +15,20 @@
|
|||
#define ZMK_KEYMAP_TRANSFORM_NODE DT_CHOSEN(zmk_matrix_transform)
|
||||
#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_TRANSFORM_NODE, map)
|
||||
|
||||
#define ZMK_MATRIX_ROWS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE,rows)
|
||||
#define ZMK_MATRIX_COLS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE,columns)
|
||||
#define ZMK_MATRIX_ROWS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE, rows)
|
||||
#define ZMK_MATRIX_COLS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE, columns)
|
||||
|
||||
#else /* DT_HAS_CHOSEN(zmk_matrix_transform) */
|
||||
|
||||
#if DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID,row_gpios)
|
||||
#define ZMK_MATRIX_ROWS DT_PROP_LEN(ZMK_MATRIX_NODE_ID,row_gpios)
|
||||
#define ZMK_MATRIX_COLS DT_PROP_LEN(ZMK_MATRIX_NODE_ID,col_gpios)
|
||||
#elif DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID,input_gpios)
|
||||
#if DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID, row_gpios)
|
||||
#define ZMK_MATRIX_ROWS DT_PROP_LEN(ZMK_MATRIX_NODE_ID, row_gpios)
|
||||
#define ZMK_MATRIX_COLS DT_PROP_LEN(ZMK_MATRIX_NODE_ID, col_gpios)
|
||||
#elif DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID, input_gpios)
|
||||
#define ZMK_MATRIX_ROWS 1
|
||||
#define ZMK_MATRIX_COLS DT_PROP_LEN(ZMK_MATRIX_NODE_ID,input_gpios)
|
||||
#define ZMK_MATRIX_COLS DT_PROP_LEN(ZMK_MATRIX_NODE_ID, input_gpios)
|
||||
#else
|
||||
#define ZMK_MATRIX_ROWS DT_PROP(ZMK_MATRIX_NODE_ID,rows)
|
||||
#define ZMK_MATRIX_COLS DT_PROP(ZMK_MATRIX_NODE_ID,columns)
|
||||
#define ZMK_MATRIX_ROWS DT_PROP(ZMK_MATRIX_NODE_ID, rows)
|
||||
#define ZMK_MATRIX_COLS DT_PROP(ZMK_MATRIX_NODE_ID, columns)
|
||||
#endif
|
||||
|
||||
#define ZMK_KEYMAP_LEN (ZMK_MATRIX_COLS * ZMK_MATRIX_ROWS)
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column);
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Nick Winans <nick@winans.codes>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
#include <bluetooth/uuid.h>
|
||||
|
||||
#ifndef BT_UUID_NUM_OF_DIGITALS
|
||||
#define BT_UUID_NUM_OF_DIGITALS BT_UUID_DECLARE_16(0x2909)
|
||||
#define BT_UUID_NUM_OF_DIGITALS BT_UUID_DECLARE_16(0x2909)
|
||||
#endif
|
||||
|
||||
#define ZMK_BT_SPLIT_UUID(num) BT_UUID_128_ENCODE(num, 0x0096, 0x7107, 0xc967, 0xc5cfb1c2482a)
|
||||
#define ZMK_BT_SPLIT_UUID(num) BT_UUID_128_ENCODE(num, 0x0096, 0x7107, 0xc967, 0xc5cfb1c2482a)
|
||||
#define ZMK_SPLIT_BT_SERVICE_UUID ZMK_BT_SPLIT_UUID(0x00000000)
|
||||
#define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001)
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#ifndef ZMK_USB_HID
|
||||
#define ZMK_USB_HID
|
||||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <usb/usb_device.h>
|
||||
#include <usb/class/usb_hid.h>
|
||||
|
@ -10,5 +15,3 @@
|
|||
int zmk_usb_hid_init();
|
||||
|
||||
int zmk_usb_hid_send_report(u8_t *report, size_t len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2020 Peter Johanson; Cody McGinnis
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
@ -22,6 +22,7 @@ echo "Running $testcase:"
|
|||
west build -d build/$testcase -b native_posix -- -DZMK_CONFIG=$testcase > /dev/null 2>&1
|
||||
if [ $? -gt 0 ]; then
|
||||
echo "FAIL: $testcase did not build" >> ./build/tests/pass-fail.log
|
||||
exit 1
|
||||
else
|
||||
./build/$testcase/zephyr/zmk.exe | sed -e "s/.*> //" | tee build/$testcase/keycode_events_full.log | sed -n -f $testcase/events.patterns > build/$testcase/keycode_events.log
|
||||
diff -au $testcase/keycode_events.snapshot build/$testcase/keycode_events.log
|
||||
|
|
51
app/src/behaviors/behavior_bt.c
Normal file
51
app/src/behaviors/behavior_bt.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_behavior_bluetooth
|
||||
|
||||
#include <device.h>
|
||||
#include <drivers/behavior.h>
|
||||
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
#include <bluetooth/conn.h>
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#include <zmk/ble.h>
|
||||
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t command, u32_t arg) {
|
||||
switch (command) {
|
||||
case BT_CLR_CMD:
|
||||
return zmk_ble_clear_bonds();
|
||||
case BT_NXT_CMD:
|
||||
return zmk_ble_prof_next();
|
||||
case BT_PRV_CMD:
|
||||
return zmk_ble_prof_prev();
|
||||
case BT_SEL_CMD:
|
||||
return zmk_ble_prof_select(arg);
|
||||
default:
|
||||
LOG_ERR("Unknown BT command: %d", command);
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int behavior_bt_init(struct device *dev) { return 0; };
|
||||
|
||||
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t command,
|
||||
u32_t arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_bt_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(behavior_bt, DT_INST_LABEL(0), behavior_bt_init, NULL, NULL, APPLICATION,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_bt_driver_api);
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Cody McGinnis, Okke Formsma
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -29,36 +29,35 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
// increase if you have keyboard with more keys.
|
||||
#define ZMK_BHV_HOLD_TAP_POSITION_NOT_USED 9999
|
||||
|
||||
|
||||
enum flavor {
|
||||
ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED = 0,
|
||||
ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED = 1,
|
||||
ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2,
|
||||
ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED = 0,
|
||||
ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED = 1,
|
||||
ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2,
|
||||
};
|
||||
|
||||
struct behavior_hold_tap_behaviors {
|
||||
struct zmk_behavior_binding tap;
|
||||
struct zmk_behavior_binding hold;
|
||||
struct zmk_behavior_binding tap;
|
||||
struct zmk_behavior_binding hold;
|
||||
};
|
||||
|
||||
typedef k_timeout_t (*timer_func)();
|
||||
|
||||
struct behavior_hold_tap_config {
|
||||
timer_func tapping_term_ms;
|
||||
struct behavior_hold_tap_behaviors *behaviors;
|
||||
enum flavor flavor;
|
||||
timer_func tapping_term_ms;
|
||||
struct behavior_hold_tap_behaviors *behaviors;
|
||||
enum flavor flavor;
|
||||
};
|
||||
|
||||
// this data is specific for each hold-tap
|
||||
struct active_hold_tap {
|
||||
s32_t position;
|
||||
u32_t param_hold;
|
||||
u32_t param_tap;
|
||||
bool is_decided;
|
||||
bool is_hold;
|
||||
const struct behavior_hold_tap_config *config;
|
||||
struct k_delayed_work work;
|
||||
bool work_is_cancelled;
|
||||
s32_t position;
|
||||
u32_t param_hold;
|
||||
u32_t param_tap;
|
||||
bool is_decided;
|
||||
bool is_hold;
|
||||
const struct behavior_hold_tap_config *config;
|
||||
struct k_delayed_work work;
|
||||
bool work_is_cancelled;
|
||||
};
|
||||
|
||||
// The undecided hold tap is the hold tap that needs to be decided before
|
||||
|
@ -71,371 +70,366 @@ struct active_hold_tap active_hold_taps[ZMK_BHV_HOLD_TAP_MAX_HELD] = {};
|
|||
// We capture most position_state_changed events and some modifiers_state_changed events.
|
||||
const struct zmk_event_header *captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {};
|
||||
|
||||
static int capture_event(const struct zmk_event_header *event)
|
||||
{
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
||||
if (captured_events[i] == NULL) {
|
||||
captured_events[i] = event;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ENOMEM;
|
||||
static int capture_event(const struct zmk_event_header *event) {
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
||||
if (captured_events[i] == NULL) {
|
||||
captured_events[i] = event;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static struct position_state_changed *find_captured_keydown_event(u32_t position)
|
||||
{
|
||||
struct position_state_changed *last_match = NULL;
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
||||
const struct zmk_event_header *eh = captured_events[i];
|
||||
if (eh == NULL) {
|
||||
return last_match;
|
||||
}
|
||||
if (!is_position_state_changed(eh)) {
|
||||
continue;
|
||||
}
|
||||
struct position_state_changed *position_event = cast_position_state_changed(eh);
|
||||
if (position_event->position == position && position_event->state) {
|
||||
last_match = position_event;
|
||||
}
|
||||
}
|
||||
return last_match;
|
||||
static struct position_state_changed *find_captured_keydown_event(u32_t position) {
|
||||
struct position_state_changed *last_match = NULL;
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
||||
const struct zmk_event_header *eh = captured_events[i];
|
||||
if (eh == NULL) {
|
||||
return last_match;
|
||||
}
|
||||
if (!is_position_state_changed(eh)) {
|
||||
continue;
|
||||
}
|
||||
struct position_state_changed *position_event = cast_position_state_changed(eh);
|
||||
if (position_event->position == position && position_event->state) {
|
||||
last_match = position_event;
|
||||
}
|
||||
}
|
||||
return last_match;
|
||||
}
|
||||
|
||||
const struct zmk_listener zmk_listener_behavior_hold_tap;
|
||||
|
||||
static void release_captured_events()
|
||||
{
|
||||
if (undecided_hold_tap != NULL) {
|
||||
return;
|
||||
}
|
||||
static void release_captured_events() {
|
||||
if (undecided_hold_tap != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We use a trick to prevent copying the captured_events array.
|
||||
//
|
||||
// Events for different mod-tap instances are separated by a NULL pointer.
|
||||
//
|
||||
// The first event popped will never be catched by the next active hold-tap
|
||||
// because to start capturing a mod-tap-key-down event must first completely
|
||||
// go through the events queue.
|
||||
//
|
||||
// Example of this release process;
|
||||
// [mt2_down, k1_down, k1_up, mt2_up, null, ...]
|
||||
// ^
|
||||
// mt2_down position event isn't captured because no hold-tap is active.
|
||||
// mt2_down behavior event is handled, now we have an undecided hold-tap
|
||||
// [null, k1_down, k1_up, mt2_up, null, ...]
|
||||
// ^
|
||||
// k1_down is captured by the mt2 mod-tap
|
||||
// !note that searches for find_captured_keydown_event by the mt2 behavior will stop at the first null encountered
|
||||
// [mt1_down, null, k1_up, mt2_up, null, ...]
|
||||
// ^
|
||||
// k1_up event is captured by the new hold-tap:
|
||||
// [k1_down, k1_up, null, mt2_up, null, ...]
|
||||
// ^
|
||||
// mt2_up event is not captured but causes release of mt2 behavior
|
||||
// [k1_down, k1_up, null, null, null, ...]
|
||||
// now mt2 will start releasing it's own captured positions.
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
||||
const struct zmk_event_header *captured_event = captured_events[i];
|
||||
if (captured_event == NULL) {
|
||||
return;
|
||||
}
|
||||
captured_events[i] = NULL;
|
||||
if (undecided_hold_tap != NULL) {
|
||||
k_msleep(10);
|
||||
}
|
||||
if (is_position_state_changed(captured_event)) {
|
||||
struct position_state_changed *position_event = cast_position_state_changed(captured_event);
|
||||
LOG_DBG("Releasing key position event for position %d %s", position_event->position, (position_event->state ? "pressed" : "released"));
|
||||
} else {
|
||||
struct keycode_state_changed *modifier_event = cast_keycode_state_changed(captured_event);
|
||||
LOG_DBG("Releasing mods changed event 0x%02X %s", modifier_event->keycode, (modifier_event->state ? "pressed" : "released"));
|
||||
}
|
||||
ZMK_EVENT_RAISE_AT(captured_event, behavior_hold_tap);
|
||||
}
|
||||
// We use a trick to prevent copying the captured_events array.
|
||||
//
|
||||
// Events for different mod-tap instances are separated by a NULL pointer.
|
||||
//
|
||||
// The first event popped will never be catched by the next active hold-tap
|
||||
// because to start capturing a mod-tap-key-down event must first completely
|
||||
// go through the events queue.
|
||||
//
|
||||
// Example of this release process;
|
||||
// [mt2_down, k1_down, k1_up, mt2_up, null, ...]
|
||||
// ^
|
||||
// mt2_down position event isn't captured because no hold-tap is active.
|
||||
// mt2_down behavior event is handled, now we have an undecided hold-tap
|
||||
// [null, k1_down, k1_up, mt2_up, null, ...]
|
||||
// ^
|
||||
// k1_down is captured by the mt2 mod-tap
|
||||
// !note that searches for find_captured_keydown_event by the mt2 behavior will stop at the
|
||||
// first null encountered [mt1_down, null, k1_up, mt2_up, null, ...]
|
||||
// ^
|
||||
// k1_up event is captured by the new hold-tap:
|
||||
// [k1_down, k1_up, null, mt2_up, null, ...]
|
||||
// ^
|
||||
// mt2_up event is not captured but causes release of mt2 behavior
|
||||
// [k1_down, k1_up, null, null, null, ...]
|
||||
// now mt2 will start releasing it's own captured positions.
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
|
||||
const struct zmk_event_header *captured_event = captured_events[i];
|
||||
if (captured_event == NULL) {
|
||||
return;
|
||||
}
|
||||
captured_events[i] = NULL;
|
||||
if (undecided_hold_tap != NULL) {
|
||||
k_msleep(10);
|
||||
}
|
||||
if (is_position_state_changed(captured_event)) {
|
||||
struct position_state_changed *position_event =
|
||||
cast_position_state_changed(captured_event);
|
||||
LOG_DBG("Releasing key position event for position %d %s", position_event->position,
|
||||
(position_event->state ? "pressed" : "released"));
|
||||
} else {
|
||||
struct keycode_state_changed *modifier_event =
|
||||
cast_keycode_state_changed(captured_event);
|
||||
LOG_DBG("Releasing mods changed event 0x%02X %s", modifier_event->keycode,
|
||||
(modifier_event->state ? "pressed" : "released"));
|
||||
}
|
||||
ZMK_EVENT_RAISE_AT(captured_event, behavior_hold_tap);
|
||||
}
|
||||
}
|
||||
|
||||
static struct active_hold_tap *find_hold_tap(u32_t position)
|
||||
{
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
|
||||
if (active_hold_taps[i].position == position) {
|
||||
return &active_hold_taps[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
static struct active_hold_tap *find_hold_tap(u32_t position) {
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
|
||||
if (active_hold_taps[i].position == position) {
|
||||
return &active_hold_taps[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold, u32_t param_tap, const struct behavior_hold_tap_config *config)
|
||||
{
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
|
||||
if (active_hold_taps[i].position != ZMK_BHV_HOLD_TAP_POSITION_NOT_USED) {
|
||||
continue;
|
||||
}
|
||||
active_hold_taps[i].position = position;
|
||||
active_hold_taps[i].is_decided = false;
|
||||
active_hold_taps[i].is_hold = false;
|
||||
active_hold_taps[i].config = config;
|
||||
active_hold_taps[i].param_hold = param_hold;
|
||||
active_hold_taps[i].param_tap = param_tap;
|
||||
return &active_hold_taps[i];
|
||||
}
|
||||
return NULL;
|
||||
static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold, u32_t param_tap,
|
||||
const struct behavior_hold_tap_config *config) {
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
|
||||
if (active_hold_taps[i].position != ZMK_BHV_HOLD_TAP_POSITION_NOT_USED) {
|
||||
continue;
|
||||
}
|
||||
active_hold_taps[i].position = position;
|
||||
active_hold_taps[i].is_decided = false;
|
||||
active_hold_taps[i].is_hold = false;
|
||||
active_hold_taps[i].config = config;
|
||||
active_hold_taps[i].param_hold = param_hold;
|
||||
active_hold_taps[i].param_tap = param_tap;
|
||||
return &active_hold_taps[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void clear_hold_tap(struct active_hold_tap *hold_tap)
|
||||
{
|
||||
hold_tap->position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
|
||||
hold_tap->is_decided = false;
|
||||
hold_tap->is_hold = false;
|
||||
hold_tap->work_is_cancelled = false;
|
||||
static void clear_hold_tap(struct active_hold_tap *hold_tap) {
|
||||
hold_tap->position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
|
||||
hold_tap->is_decided = false;
|
||||
hold_tap->is_hold = false;
|
||||
hold_tap->work_is_cancelled = false;
|
||||
}
|
||||
|
||||
enum decision_moment {
|
||||
HT_KEY_UP = 0,
|
||||
HT_OTHER_KEY_DOWN = 1,
|
||||
HT_OTHER_KEY_UP = 2,
|
||||
HT_TIMER_EVENT = 3,
|
||||
HT_KEY_UP = 0,
|
||||
HT_OTHER_KEY_DOWN = 1,
|
||||
HT_OTHER_KEY_UP = 2,
|
||||
HT_TIMER_EVENT = 3,
|
||||
};
|
||||
|
||||
static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_moment event)
|
||||
{
|
||||
switch (event) {
|
||||
case HT_KEY_UP:
|
||||
hold_tap->is_hold = 0;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
case HT_OTHER_KEY_UP:
|
||||
case HT_TIMER_EVENT:
|
||||
hold_tap->is_hold = 1;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_moment event) {
|
||||
switch (event) {
|
||||
case HT_KEY_UP:
|
||||
hold_tap->is_hold = 0;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
case HT_OTHER_KEY_UP:
|
||||
case HT_TIMER_EVENT:
|
||||
hold_tap->is_hold = 1;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision_moment event)
|
||||
{
|
||||
switch (event) {
|
||||
case HT_KEY_UP:
|
||||
hold_tap->is_hold = 0;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
case HT_TIMER_EVENT:
|
||||
hold_tap->is_hold = 1;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) {
|
||||
switch (event) {
|
||||
case HT_KEY_UP:
|
||||
hold_tap->is_hold = 0;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
case HT_TIMER_EVENT:
|
||||
hold_tap->is_hold = 1;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decision_moment event)
|
||||
{
|
||||
switch (event) {
|
||||
case HT_KEY_UP:
|
||||
hold_tap->is_hold = 0;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
case HT_OTHER_KEY_DOWN:
|
||||
case HT_TIMER_EVENT:
|
||||
hold_tap->is_hold = 1;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) {
|
||||
switch (event) {
|
||||
case HT_KEY_UP:
|
||||
hold_tap->is_hold = 0;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
case HT_OTHER_KEY_DOWN:
|
||||
case HT_TIMER_EVENT:
|
||||
hold_tap->is_hold = 1;
|
||||
hold_tap->is_decided = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static inline char* flavor_str(enum flavor flavor) {
|
||||
switch(flavor) {
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
|
||||
return "hold-preferred";
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
|
||||
return "balanced";
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
|
||||
return "tap-preferred";
|
||||
}
|
||||
return "UNKNOWN FLAVOR";
|
||||
static inline char *flavor_str(enum flavor flavor) {
|
||||
switch (flavor) {
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
|
||||
return "hold-preferred";
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
|
||||
return "balanced";
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
|
||||
return "tap-preferred";
|
||||
}
|
||||
return "UNKNOWN FLAVOR";
|
||||
}
|
||||
|
||||
static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event)
|
||||
{
|
||||
if (hold_tap->is_decided) {
|
||||
return;
|
||||
}
|
||||
static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event) {
|
||||
if (hold_tap->is_decided) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hold_tap != undecided_hold_tap) {
|
||||
LOG_DBG("ERROR found undecided tap hold that is not the active tap hold");
|
||||
return;
|
||||
}
|
||||
if (hold_tap != undecided_hold_tap) {
|
||||
LOG_DBG("ERROR found undecided tap hold that is not the active tap hold");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(hold_tap->config->flavor) {
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
|
||||
decide_hold_preferred(hold_tap, event);
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
|
||||
decide_balanced(hold_tap, event);
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
|
||||
decide_tap_preferred(hold_tap, event);
|
||||
}
|
||||
switch (hold_tap->config->flavor) {
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
|
||||
decide_hold_preferred(hold_tap, event);
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
|
||||
decide_balanced(hold_tap, event);
|
||||
case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
|
||||
decide_tap_preferred(hold_tap, event);
|
||||
}
|
||||
|
||||
if (!hold_tap->is_decided) {
|
||||
return;
|
||||
}
|
||||
if (!hold_tap->is_decided) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DBG("%d decided %s (%s event %d)",
|
||||
hold_tap->position,
|
||||
hold_tap->is_hold ? "hold" : "tap",
|
||||
flavor_str(hold_tap->config->flavor),
|
||||
event);
|
||||
undecided_hold_tap = NULL;
|
||||
LOG_DBG("%d decided %s (%s event %d)", hold_tap->position, hold_tap->is_hold ? "hold" : "tap",
|
||||
flavor_str(hold_tap->config->flavor), event);
|
||||
undecided_hold_tap = NULL;
|
||||
|
||||
struct zmk_behavior_binding *behavior;
|
||||
if (hold_tap->is_hold) {
|
||||
behavior = &hold_tap->config->behaviors->hold;
|
||||
struct device *behavior_device = device_get_binding(behavior->behavior_dev);
|
||||
behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_hold, 0);
|
||||
} else {
|
||||
behavior = &hold_tap->config->behaviors->tap;
|
||||
struct device *behavior_device = device_get_binding(behavior->behavior_dev);
|
||||
behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_tap, 0);
|
||||
}
|
||||
release_captured_events();
|
||||
struct zmk_behavior_binding *behavior;
|
||||
if (hold_tap->is_hold) {
|
||||
behavior = &hold_tap->config->behaviors->hold;
|
||||
struct device *behavior_device = device_get_binding(behavior->behavior_dev);
|
||||
behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_hold,
|
||||
0);
|
||||
} else {
|
||||
behavior = &hold_tap->config->behaviors->tap;
|
||||
struct device *behavior_device = device_get_binding(behavior->behavior_dev);
|
||||
behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_tap,
|
||||
0);
|
||||
}
|
||||
release_captured_events();
|
||||
}
|
||||
|
||||
static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t param_hold, u32_t param_tap)
|
||||
{
|
||||
const struct behavior_hold_tap_config *cfg = dev->config_info;
|
||||
static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t param_hold,
|
||||
u32_t param_tap) {
|
||||
const struct behavior_hold_tap_config *cfg = dev->config_info;
|
||||
|
||||
if (undecided_hold_tap != NULL) {
|
||||
LOG_DBG("ERROR another hold-tap behavior is undecided.");
|
||||
// if this happens, make sure the behavior events occur AFTER other position events.
|
||||
return 0;
|
||||
}
|
||||
if (undecided_hold_tap != NULL) {
|
||||
LOG_DBG("ERROR another hold-tap behavior is undecided.");
|
||||
// if this happens, make sure the behavior events occur AFTER other position events.
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct active_hold_tap *hold_tap = store_hold_tap(position, param_hold, param_tap, cfg);
|
||||
if (hold_tap == NULL) {
|
||||
LOG_ERR("unable to store hold-tap info, did you press more than %d hold-taps?", ZMK_BHV_HOLD_TAP_MAX_HELD);
|
||||
return 0;
|
||||
}
|
||||
struct active_hold_tap *hold_tap = store_hold_tap(position, param_hold, param_tap, cfg);
|
||||
if (hold_tap == NULL) {
|
||||
LOG_ERR("unable to store hold-tap info, did you press more than %d hold-taps?",
|
||||
ZMK_BHV_HOLD_TAP_MAX_HELD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_DBG("%d new undecided hold_tap", position);
|
||||
undecided_hold_tap = hold_tap;
|
||||
k_delayed_work_submit(&hold_tap->work, cfg->tapping_term_ms());
|
||||
LOG_DBG("%d new undecided hold_tap", position);
|
||||
undecided_hold_tap = hold_tap;
|
||||
k_delayed_work_submit(&hold_tap->work, cfg->tapping_term_ms());
|
||||
|
||||
// todo: once we get timing info for keypresses, start the timer relative to the original keypress
|
||||
// don't forget to simulate a timer-event before the event after that time was handled.
|
||||
// todo: once we get timing info for keypresses, start the timer relative to the original
|
||||
// keypress don't forget to simulate a timer-event before the event after that time was handled.
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_hold_tap_binding_released(struct device *dev, u32_t position, u32_t _, u32_t __)
|
||||
{
|
||||
struct active_hold_tap *hold_tap = find_hold_tap(position);
|
||||
static int on_hold_tap_binding_released(struct device *dev, u32_t position, u32_t _, u32_t __) {
|
||||
struct active_hold_tap *hold_tap = find_hold_tap(position);
|
||||
|
||||
if (hold_tap == NULL) {
|
||||
LOG_ERR("ACTIVE_HOLD_TAP_CLEANED_UP_TOO_EARLY");
|
||||
return 0;
|
||||
}
|
||||
if (hold_tap == NULL) {
|
||||
LOG_ERR("ACTIVE_HOLD_TAP_CLEANED_UP_TOO_EARLY");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int work_cancel_result = k_delayed_work_cancel(&hold_tap->work);
|
||||
decide_hold_tap(hold_tap, HT_KEY_UP);
|
||||
int work_cancel_result = k_delayed_work_cancel(&hold_tap->work);
|
||||
decide_hold_tap(hold_tap, HT_KEY_UP);
|
||||
|
||||
struct zmk_behavior_binding *behavior;
|
||||
if (hold_tap->is_hold) {
|
||||
behavior = &hold_tap->config->behaviors->hold;
|
||||
struct device *behavior_device = device_get_binding(behavior->behavior_dev);
|
||||
behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_hold, 0);
|
||||
} else {
|
||||
behavior = &hold_tap->config->behaviors->tap;
|
||||
struct device *behavior_device = device_get_binding(behavior->behavior_dev);
|
||||
behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_tap, 0);
|
||||
}
|
||||
struct zmk_behavior_binding *behavior;
|
||||
if (hold_tap->is_hold) {
|
||||
behavior = &hold_tap->config->behaviors->hold;
|
||||
struct device *behavior_device = device_get_binding(behavior->behavior_dev);
|
||||
behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_hold,
|
||||
0);
|
||||
} else {
|
||||
behavior = &hold_tap->config->behaviors->tap;
|
||||
struct device *behavior_device = device_get_binding(behavior->behavior_dev);
|
||||
behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_tap,
|
||||
0);
|
||||
}
|
||||
|
||||
if (work_cancel_result == -EINPROGRESS) {
|
||||
// let the timer handler clean up
|
||||
// if we'd clear now, the timer may call back for an uninitialized active_hold_tap.
|
||||
LOG_DBG("%d hold-tap timer work in event queue", position);
|
||||
hold_tap->work_is_cancelled = true;
|
||||
} else {
|
||||
LOG_DBG("%d cleaning up hold-tap", position);
|
||||
clear_hold_tap(hold_tap);
|
||||
}
|
||||
|
||||
if (work_cancel_result == -EINPROGRESS) {
|
||||
// let the timer handler clean up
|
||||
// if we'd clear now, the timer may call back for an uninitialized active_hold_tap.
|
||||
LOG_DBG("%d hold-tap timer work in event queue", position);
|
||||
hold_tap->work_is_cancelled = true;
|
||||
} else {
|
||||
LOG_DBG("%d cleaning up hold-tap", position);
|
||||
clear_hold_tap(hold_tap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_hold_tap_driver_api = {
|
||||
.binding_pressed = on_hold_tap_binding_pressed,
|
||||
.binding_released = on_hold_tap_binding_released,
|
||||
.binding_pressed = on_hold_tap_binding_pressed,
|
||||
.binding_released = on_hold_tap_binding_released,
|
||||
};
|
||||
|
||||
static int position_state_changed_listener(const struct zmk_event_header *eh) {
|
||||
struct position_state_changed *ev = cast_position_state_changed(eh);
|
||||
|
||||
static int position_state_changed_listener(const struct zmk_event_header *eh)
|
||||
{
|
||||
struct position_state_changed *ev = cast_position_state_changed(eh);
|
||||
if (undecided_hold_tap == NULL) {
|
||||
LOG_DBG("%d bubble (no undecided hold_tap active)", ev->position);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (undecided_hold_tap == NULL) {
|
||||
LOG_DBG("%d bubble (no undecided hold_tap active)", ev->position);
|
||||
return 0;
|
||||
}
|
||||
if (undecided_hold_tap->position == ev->position) {
|
||||
if (ev->state) { // keydown
|
||||
LOG_ERR("hold-tap listener should be called before before most other listeners!");
|
||||
return 0;
|
||||
} else { // keyup
|
||||
LOG_DBG("%d bubble undecided hold-tap keyrelease event", undecided_hold_tap->position);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (undecided_hold_tap->position == ev->position) {
|
||||
if (ev->state) { // keydown
|
||||
LOG_ERR("hold-tap listener should be called before before most other listeners!");
|
||||
return 0;
|
||||
} else { // keyup
|
||||
LOG_DBG("%d bubble undecided hold-tap keyrelease event", undecided_hold_tap->position);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!ev->state && find_captured_keydown_event(ev->position) == NULL) {
|
||||
// no keydown event has been captured, let it bubble.
|
||||
// we'll catch modifiers later in modifier_state_changed_listener
|
||||
LOG_DBG("%d bubbling %d %s event", undecided_hold_tap->position, ev->position,
|
||||
ev->state ? "down" : "up");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ev->state && find_captured_keydown_event(ev->position) == NULL) {
|
||||
// no keydown event has been captured, let it bubble.
|
||||
// we'll catch modifiers later in modifier_state_changed_listener
|
||||
LOG_DBG("%d bubbling %d %s event", undecided_hold_tap->position, ev->position, ev->state ? "down" : "up");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_DBG("%d capturing %d %s event", undecided_hold_tap->position, ev->position, ev->state ? "down" : "up");
|
||||
capture_event(eh);
|
||||
decide_hold_tap(undecided_hold_tap, ev->state ? HT_OTHER_KEY_DOWN : HT_OTHER_KEY_UP);
|
||||
return ZMK_EV_EVENT_CAPTURED;
|
||||
LOG_DBG("%d capturing %d %s event", undecided_hold_tap->position, ev->position,
|
||||
ev->state ? "down" : "up");
|
||||
capture_event(eh);
|
||||
decide_hold_tap(undecided_hold_tap, ev->state ? HT_OTHER_KEY_DOWN : HT_OTHER_KEY_UP);
|
||||
return ZMK_EV_EVENT_CAPTURED;
|
||||
}
|
||||
|
||||
static bool is_mod(struct keycode_state_changed *ev)
|
||||
{
|
||||
return ev->usage_page == USAGE_KEYPAD && ev->keycode >= LCTL && ev->keycode <= RGUI;
|
||||
static bool is_mod(struct keycode_state_changed *ev) {
|
||||
return ev->usage_page == USAGE_KEYPAD && ev->keycode >= LCTL && ev->keycode <= RGUI;
|
||||
}
|
||||
|
||||
static int keycode_state_changed_listener(const struct zmk_event_header *eh)
|
||||
{
|
||||
// we want to catch layer-up events too... how?
|
||||
struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
|
||||
static int keycode_state_changed_listener(const struct zmk_event_header *eh) {
|
||||
// we want to catch layer-up events too... how?
|
||||
struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
|
||||
|
||||
if (undecided_hold_tap == NULL) {
|
||||
// LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode);
|
||||
return 0;
|
||||
}
|
||||
if (undecided_hold_tap == NULL) {
|
||||
// LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!is_mod(ev)) {
|
||||
// LOG_DBG("0x%02X bubble (not a mod)", ev->keycode);
|
||||
return 0;
|
||||
}
|
||||
if (!is_mod(ev)) {
|
||||
// LOG_DBG("0x%02X bubble (not a mod)", ev->keycode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// only key-up events will bubble through position_state_changed_listener
|
||||
// if a undecided_hold_tap is active.
|
||||
LOG_DBG("%d capturing 0x%02X %s event", undecided_hold_tap->position, ev->keycode, ev->state ? "down" : "up");
|
||||
capture_event(eh);
|
||||
return ZMK_EV_EVENT_CAPTURED;
|
||||
// only key-up events will bubble through position_state_changed_listener
|
||||
// if a undecided_hold_tap is active.
|
||||
LOG_DBG("%d capturing 0x%02X %s event", undecided_hold_tap->position, ev->keycode,
|
||||
ev->state ? "down" : "up");
|
||||
capture_event(eh);
|
||||
return ZMK_EV_EVENT_CAPTURED;
|
||||
}
|
||||
|
||||
|
||||
int behavior_hold_tap_listener(const struct zmk_event_header *eh)
|
||||
{
|
||||
if (is_position_state_changed(eh)) {
|
||||
return position_state_changed_listener(eh);
|
||||
} else if (is_keycode_state_changed(eh)) {
|
||||
return keycode_state_changed_listener(eh);
|
||||
}
|
||||
return 0;
|
||||
int behavior_hold_tap_listener(const struct zmk_event_header *eh) {
|
||||
if (is_position_state_changed(eh)) {
|
||||
return position_state_changed_listener(eh);
|
||||
} else if (is_keycode_state_changed(eh)) {
|
||||
return keycode_state_changed_listener(eh);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(behavior_hold_tap, behavior_hold_tap_listener);
|
||||
|
@ -443,60 +437,56 @@ ZMK_SUBSCRIPTION(behavior_hold_tap, position_state_changed);
|
|||
// this should be modifiers_state_changed, but unfrotunately that's not implemented yet.
|
||||
ZMK_SUBSCRIPTION(behavior_hold_tap, keycode_state_changed);
|
||||
|
||||
void behavior_hold_tap_timer_work_handler(struct k_work *item)
|
||||
{
|
||||
struct active_hold_tap *hold_tap = CONTAINER_OF(item, struct active_hold_tap, work);
|
||||
void behavior_hold_tap_timer_work_handler(struct k_work *item) {
|
||||
struct active_hold_tap *hold_tap = CONTAINER_OF(item, struct active_hold_tap, work);
|
||||
|
||||
if (hold_tap->work_is_cancelled) {
|
||||
clear_hold_tap(hold_tap);
|
||||
} else {
|
||||
decide_hold_tap(hold_tap, HT_TIMER_EVENT);
|
||||
}
|
||||
if (hold_tap->work_is_cancelled) {
|
||||
clear_hold_tap(hold_tap);
|
||||
} else {
|
||||
decide_hold_tap(hold_tap, HT_TIMER_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
static int behavior_hold_tap_init(struct device *dev)
|
||||
{
|
||||
static bool init_first_run = true;
|
||||
static int behavior_hold_tap_init(struct device *dev) {
|
||||
static bool init_first_run = true;
|
||||
|
||||
if (init_first_run) {
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
|
||||
k_delayed_work_init(&active_hold_taps[i].work, behavior_hold_tap_timer_work_handler);
|
||||
active_hold_taps[i].position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
|
||||
}
|
||||
}
|
||||
init_first_run = false;
|
||||
return 0;
|
||||
if (init_first_run) {
|
||||
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
|
||||
k_delayed_work_init(&active_hold_taps[i].work, behavior_hold_tap_timer_work_handler);
|
||||
active_hold_taps[i].position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
|
||||
}
|
||||
}
|
||||
init_first_run = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct behavior_hold_tap_data {};
|
||||
static struct behavior_hold_tap_data behavior_hold_tap_data;
|
||||
|
||||
#define _TRANSFORM_ENTRY(idx, node) \
|
||||
{ \
|
||||
.behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \
|
||||
.param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), (DT_INST_PHA_BY_IDX(node, bindings, idx, param1))), \
|
||||
.param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param2), (0), (DT_INST_PHA_BY_IDX(node, bindings, idx, param2))), \
|
||||
},
|
||||
#define _TRANSFORM_ENTRY(idx, node) \
|
||||
{ \
|
||||
.behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \
|
||||
.param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), \
|
||||
(DT_INST_PHA_BY_IDX(node, bindings, idx, param1))), \
|
||||
.param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param2), (0), \
|
||||
(DT_INST_PHA_BY_IDX(node, bindings, idx, param2))), \
|
||||
},
|
||||
|
||||
#define KP_INST(n) \
|
||||
static k_timeout_t behavior_hold_tap_config_##n##_gettime() { return K_MSEC(DT_INST_PROP(n, tapping_term_ms)); } \
|
||||
static struct behavior_hold_tap_behaviors behavior_hold_tap_behaviors_##n = { \
|
||||
.hold = _TRANSFORM_ENTRY(0, n) \
|
||||
.tap = _TRANSFORM_ENTRY(1, n) \
|
||||
}; \
|
||||
static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \
|
||||
.behaviors = &behavior_hold_tap_behaviors_##n, \
|
||||
.tapping_term_ms = &behavior_hold_tap_config_##n##_gettime, \
|
||||
.flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \
|
||||
}; \
|
||||
DEVICE_AND_API_INIT( \
|
||||
behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \
|
||||
&behavior_hold_tap_data, \
|
||||
&behavior_hold_tap_config_##n, \
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
&behavior_hold_tap_driver_api);
|
||||
#define KP_INST(n) \
|
||||
static k_timeout_t behavior_hold_tap_config_##n##_gettime() { \
|
||||
return K_MSEC(DT_INST_PROP(n, tapping_term_ms)); \
|
||||
} \
|
||||
static struct behavior_hold_tap_behaviors behavior_hold_tap_behaviors_##n = { \
|
||||
.hold = _TRANSFORM_ENTRY(0, n).tap = _TRANSFORM_ENTRY(1, n)}; \
|
||||
static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \
|
||||
.behaviors = &behavior_hold_tap_behaviors_##n, \
|
||||
.tapping_term_ms = &behavior_hold_tap_config_##n##_gettime, \
|
||||
.flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \
|
||||
}; \
|
||||
DEVICE_AND_API_INIT(behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \
|
||||
&behavior_hold_tap_data, &behavior_hold_tap_config_##n, APPLICATION, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_hold_tap_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
||||
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -16,45 +16,35 @@
|
|||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct behavior_key_press_config {
|
||||
u8_t usage_page;
|
||||
u8_t usage_page;
|
||||
};
|
||||
struct behavior_key_press_data { };
|
||||
struct behavior_key_press_data {};
|
||||
|
||||
static int behavior_key_press_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
static int behavior_key_press_init(struct device *dev) { return 0; };
|
||||
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _)
|
||||
{
|
||||
const struct behavior_key_press_config *cfg = dev->config_info;
|
||||
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _) {
|
||||
const struct behavior_key_press_config *cfg = dev->config_info;
|
||||
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
|
||||
|
||||
return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true));
|
||||
return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true));
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _)
|
||||
{
|
||||
const struct behavior_key_press_config *cfg = dev->config_info;
|
||||
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
|
||||
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _) {
|
||||
const struct behavior_key_press_config *cfg = dev->config_info;
|
||||
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
|
||||
|
||||
return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false));
|
||||
return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false));
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_key_press_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released
|
||||
};
|
||||
.binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
||||
|
||||
#define KP_INST(n) \
|
||||
static const struct behavior_key_press_config behavior_key_press_config_##n = { \
|
||||
.usage_page = DT_INST_PROP(n, usage_page) \
|
||||
}; \
|
||||
static struct behavior_key_press_data behavior_key_press_data_##n; \
|
||||
DEVICE_AND_API_INIT(behavior_key_press_##n, DT_INST_LABEL(n), behavior_key_press_init, \
|
||||
&behavior_key_press_data_##n, \
|
||||
&behavior_key_press_config_##n, \
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
&behavior_key_press_driver_api);
|
||||
#define KP_INST(n) \
|
||||
static const struct behavior_key_press_config behavior_key_press_config_##n = { \
|
||||
.usage_page = DT_INST_PROP(n, usage_page)}; \
|
||||
static struct behavior_key_press_data behavior_key_press_data_##n; \
|
||||
DEVICE_AND_API_INIT(behavior_key_press_##n, DT_INST_LABEL(n), behavior_key_press_init, \
|
||||
&behavior_key_press_data_##n, &behavior_key_press_config_##n, APPLICATION, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_key_press_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -14,41 +14,30 @@
|
|||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct behavior_mo_config { };
|
||||
struct behavior_mo_data { };
|
||||
struct behavior_mo_config {};
|
||||
struct behavior_mo_data {};
|
||||
|
||||
static int behavior_mo_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
static int behavior_mo_init(struct device *dev) { return 0; };
|
||||
|
||||
static int mo_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _) {
|
||||
LOG_DBG("position %d layer %d", position, layer);
|
||||
|
||||
static int mo_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _)
|
||||
{
|
||||
LOG_DBG("position %d layer %d", position, layer);
|
||||
|
||||
return zmk_keymap_layer_activate(layer);
|
||||
return zmk_keymap_layer_activate(layer);
|
||||
}
|
||||
|
||||
static int mo_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _)
|
||||
{
|
||||
LOG_DBG("position %d layer %d", position, layer);
|
||||
static int mo_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _) {
|
||||
LOG_DBG("position %d layer %d", position, layer);
|
||||
|
||||
return zmk_keymap_layer_deactivate(layer);
|
||||
return zmk_keymap_layer_deactivate(layer);
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_mo_driver_api = {
|
||||
.binding_pressed = mo_keymap_binding_pressed,
|
||||
.binding_released = mo_keymap_binding_released
|
||||
};
|
||||
|
||||
.binding_pressed = mo_keymap_binding_pressed, .binding_released = mo_keymap_binding_released};
|
||||
|
||||
static const struct behavior_mo_config behavior_mo_config = {};
|
||||
|
||||
static struct behavior_mo_data behavior_mo_data;
|
||||
|
||||
DEVICE_AND_API_INIT(behavior_mo, DT_INST_LABEL(0), behavior_mo_init,
|
||||
&behavior_mo_data,
|
||||
&behavior_mo_config,
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
DEVICE_AND_API_INIT(behavior_mo, DT_INST_LABEL(0), behavior_mo_init, &behavior_mo_data,
|
||||
&behavior_mo_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&behavior_mo_driver_api);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -13,36 +13,30 @@
|
|||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct behavior_none_config { };
|
||||
struct behavior_none_data { };
|
||||
struct behavior_none_config {};
|
||||
struct behavior_none_data {};
|
||||
|
||||
static int behavior_none_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
static int behavior_none_init(struct device *dev) { return 0; };
|
||||
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
|
||||
{
|
||||
return 0;
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
|
||||
u32_t _param2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
|
||||
{
|
||||
return 0;
|
||||
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1,
|
||||
u32_t _param2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_none_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
};
|
||||
|
||||
|
||||
static const struct behavior_none_config behavior_none_config = {};
|
||||
|
||||
static struct behavior_none_data behavior_none_data;
|
||||
|
||||
DEVICE_AND_API_INIT(behavior_none, DT_INST_LABEL(0), behavior_none_init,
|
||||
&behavior_none_data,
|
||||
&behavior_none_config,
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
DEVICE_AND_API_INIT(behavior_none, DT_INST_LABEL(0), behavior_none_init, &behavior_none_data,
|
||||
&behavior_none_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&behavior_none_driver_api);
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -14,37 +14,31 @@
|
|||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct behavior_reset_config {
|
||||
int type;
|
||||
int type;
|
||||
};
|
||||
|
||||
static int behavior_reset_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
static int behavior_reset_init(struct device *dev) { return 0; };
|
||||
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
|
||||
{
|
||||
const struct behavior_reset_config *cfg = dev->config_info;
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
|
||||
u32_t _param2) {
|
||||
const struct behavior_reset_config *cfg = dev->config_info;
|
||||
|
||||
// TODO: Correct magic code for going into DFU?
|
||||
// See https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
|
||||
sys_reboot(cfg->type);
|
||||
return 0;
|
||||
// TODO: Correct magic code for going into DFU?
|
||||
// See
|
||||
// https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
|
||||
sys_reboot(cfg->type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_reset_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
};
|
||||
|
||||
#define RST_INST(n) \
|
||||
static const struct behavior_reset_config behavior_reset_config_##n = { \
|
||||
.type = DT_INST_PROP(n, type)}; \
|
||||
DEVICE_AND_API_INIT(behavior_reset_##n, DT_INST_LABEL(n), behavior_reset_init, NULL, \
|
||||
&behavior_reset_config_##n, APPLICATION, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_reset_driver_api);
|
||||
|
||||
#define RST_INST(n) \
|
||||
static const struct behavior_reset_config behavior_reset_config_##n = { \
|
||||
.type = DT_INST_PROP(n, type) \
|
||||
}; \
|
||||
DEVICE_AND_API_INIT(behavior_reset_##n, DT_INST_LABEL(n), behavior_reset_init, \
|
||||
NULL, \
|
||||
&behavior_reset_config_##n, \
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
&behavior_reset_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(RST_INST)
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Nick Winans <nick@winans.codes>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -15,48 +15,41 @@
|
|||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
static int behavior_rgb_underglow_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int behavior_rgb_underglow_init(struct device *dev) { return 0; }
|
||||
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t action, u32_t _)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t action, u32_t _) {
|
||||
switch (action) {
|
||||
case RGB_TOG:
|
||||
return zmk_rgb_underglow_toggle();
|
||||
return zmk_rgb_underglow_toggle();
|
||||
case RGB_HUI:
|
||||
return zmk_rgb_underglow_change_hue(1);
|
||||
return zmk_rgb_underglow_change_hue(1);
|
||||
case RGB_HUD:
|
||||
return zmk_rgb_underglow_change_hue(-1);
|
||||
return zmk_rgb_underglow_change_hue(-1);
|
||||
case RGB_SAI:
|
||||
return zmk_rgb_underglow_change_sat(1);
|
||||
return zmk_rgb_underglow_change_sat(1);
|
||||
case RGB_SAD:
|
||||
return zmk_rgb_underglow_change_sat(-1);
|
||||
return zmk_rgb_underglow_change_sat(-1);
|
||||
case RGB_BRI:
|
||||
return zmk_rgb_underglow_change_brt(1);
|
||||
return zmk_rgb_underglow_change_brt(1);
|
||||
case RGB_BRD:
|
||||
return zmk_rgb_underglow_change_brt(-1);
|
||||
return zmk_rgb_underglow_change_brt(-1);
|
||||
case RGB_SPI:
|
||||
return zmk_rgb_underglow_change_spd(1);
|
||||
return zmk_rgb_underglow_change_spd(1);
|
||||
case RGB_SPD:
|
||||
return zmk_rgb_underglow_change_spd(-1);
|
||||
return zmk_rgb_underglow_change_spd(-1);
|
||||
case RGB_EFF:
|
||||
return zmk_rgb_underglow_cycle_effect(1);
|
||||
return zmk_rgb_underglow_cycle_effect(1);
|
||||
case RGB_EFR:
|
||||
return zmk_rgb_underglow_cycle_effect(-1);
|
||||
}
|
||||
return zmk_rgb_underglow_cycle_effect(-1);
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_rgb_underglow_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(behavior_rgb_underglow, DT_INST_LABEL(0), behavior_rgb_underglow_init,
|
||||
NULL,
|
||||
NULL,
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
DEVICE_AND_API_INIT(behavior_rgb_underglow, DT_INST_LABEL(0), behavior_rgb_underglow_init, NULL,
|
||||
NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&behavior_rgb_underglow_driver_api);
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -17,75 +17,69 @@
|
|||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct behavior_sensor_rotate_key_press_config {
|
||||
u8_t usage_page;
|
||||
u8_t usage_page;
|
||||
};
|
||||
struct behavior_sensor_rotate_key_press_data { };
|
||||
struct behavior_sensor_rotate_key_press_data {};
|
||||
|
||||
static int behavior_sensor_rotate_key_press_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
static int behavior_sensor_rotate_key_press_init(struct device *dev) { return 0; };
|
||||
|
||||
static int on_sensor_binding_triggered(struct device *dev, struct device *sensor,
|
||||
u32_t increment_keycode, u32_t decrement_keycode) {
|
||||
const struct behavior_sensor_rotate_key_press_config *cfg = dev->config_info;
|
||||
struct sensor_value value;
|
||||
int err;
|
||||
u32_t keycode;
|
||||
struct keycode_state_changed *ev;
|
||||
LOG_DBG("usage_page 0x%02X inc keycode 0x%02X dec keycode 0x%02X", cfg->usage_page,
|
||||
increment_keycode, decrement_keycode);
|
||||
|
||||
static int on_sensor_binding_triggered(struct device *dev, struct device *sensor, u32_t increment_keycode, u32_t decrement_keycode)
|
||||
{
|
||||
const struct behavior_sensor_rotate_key_press_config *cfg = dev->config_info;
|
||||
struct sensor_value value;
|
||||
int err;
|
||||
u32_t keycode;
|
||||
struct keycode_state_changed *ev;
|
||||
LOG_DBG("usage_page 0x%02X inc keycode 0x%02X dec keycode 0x%02X", cfg->usage_page, increment_keycode, decrement_keycode);
|
||||
err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value);
|
||||
|
||||
err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value);
|
||||
if (err) {
|
||||
LOG_WRN("Failed to ge sensor rotation value: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
LOG_WRN("Failed to ge sensor rotation value: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
switch (value.val1) {
|
||||
switch (value.val1) {
|
||||
case 1:
|
||||
keycode = increment_keycode;
|
||||
break;
|
||||
keycode = increment_keycode;
|
||||
break;
|
||||
case -1:
|
||||
keycode = decrement_keycode;
|
||||
break;
|
||||
keycode = decrement_keycode;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
LOG_DBG("SEND %d", keycode);
|
||||
LOG_DBG("SEND %d", keycode);
|
||||
|
||||
ev = new_keycode_state_changed();
|
||||
ev->usage_page = cfg->usage_page;
|
||||
ev->keycode = keycode;
|
||||
ev->state = true;
|
||||
ZMK_EVENT_RAISE(ev);
|
||||
|
||||
ev = new_keycode_state_changed();
|
||||
ev->usage_page = cfg->usage_page;
|
||||
ev->keycode = keycode;
|
||||
ev->state = true;
|
||||
ZMK_EVENT_RAISE(ev);
|
||||
// TODO: Better way to do this?
|
||||
k_msleep(5);
|
||||
|
||||
// TODO: Better way to do this?
|
||||
k_msleep(5);
|
||||
|
||||
ev = new_keycode_state_changed();
|
||||
ev->usage_page = cfg->usage_page;
|
||||
ev->keycode = keycode;
|
||||
ev->state = false;
|
||||
return ZMK_EVENT_RAISE(ev);
|
||||
ev = new_keycode_state_changed();
|
||||
ev->usage_page = cfg->usage_page;
|
||||
ev->keycode = keycode;
|
||||
ev->state = false;
|
||||
return ZMK_EVENT_RAISE(ev);
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = {
|
||||
.sensor_binding_triggered = on_sensor_binding_triggered
|
||||
};
|
||||
.sensor_binding_triggered = on_sensor_binding_triggered};
|
||||
|
||||
#define KP_INST(n) \
|
||||
static const struct behavior_sensor_rotate_key_press_config behavior_sensor_rotate_key_press_config_##n = { \
|
||||
.usage_page = DT_INST_PROP(n, usage_page) \
|
||||
}; \
|
||||
static struct behavior_sensor_rotate_key_press_data behavior_sensor_rotate_key_press_data_##n; \
|
||||
DEVICE_AND_API_INIT(behavior_sensor_rotate_key_press_##n, DT_INST_LABEL(n), behavior_sensor_rotate_key_press_init, \
|
||||
&behavior_sensor_rotate_key_press_data_##n, \
|
||||
&behavior_sensor_rotate_key_press_config_##n, \
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
&behavior_sensor_rotate_key_press_driver_api);
|
||||
#define KP_INST(n) \
|
||||
static const struct behavior_sensor_rotate_key_press_config \
|
||||
behavior_sensor_rotate_key_press_config_##n = {.usage_page = DT_INST_PROP(n, usage_page)}; \
|
||||
static struct behavior_sensor_rotate_key_press_data behavior_sensor_rotate_key_press_data_##n; \
|
||||
DEVICE_AND_API_INIT( \
|
||||
behavior_sensor_rotate_key_press_##n, DT_INST_LABEL(n), \
|
||||
behavior_sensor_rotate_key_press_init, &behavior_sensor_rotate_key_press_data_##n, \
|
||||
&behavior_sensor_rotate_key_press_config_##n, APPLICATION, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_key_press_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Cody McGinnis <brainwart@gmail.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -14,30 +14,21 @@
|
|||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct behavior_tog_config
|
||||
{
|
||||
};
|
||||
struct behavior_tog_data
|
||||
{
|
||||
};
|
||||
struct behavior_tog_config {};
|
||||
struct behavior_tog_data {};
|
||||
|
||||
static int behavior_tog_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
static int behavior_tog_init(struct device *dev) { return 0; };
|
||||
|
||||
static int tog_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _)
|
||||
{
|
||||
LOG_DBG("position %d layer %d", position, layer);
|
||||
static int tog_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _) {
|
||||
LOG_DBG("position %d layer %d", position, layer);
|
||||
|
||||
return zmk_keymap_layer_toggle(layer);
|
||||
return zmk_keymap_layer_toggle(layer);
|
||||
}
|
||||
|
||||
static int tog_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _)
|
||||
{
|
||||
LOG_DBG("position %d layer %d", position, layer);
|
||||
static int tog_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _) {
|
||||
LOG_DBG("position %d layer %d", position, layer);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_tog_driver_api = {
|
||||
|
@ -49,8 +40,6 @@ static const struct behavior_tog_config behavior_tog_config = {};
|
|||
|
||||
static struct behavior_tog_data behavior_tog_data;
|
||||
|
||||
DEVICE_AND_API_INIT(behavior_tog, DT_INST_LABEL(0), behavior_tog_init,
|
||||
&behavior_tog_data,
|
||||
&behavior_tog_config,
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
DEVICE_AND_API_INIT(behavior_tog, DT_INST_LABEL(0), behavior_tog_init, &behavior_tog_data,
|
||||
&behavior_tog_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&behavior_tog_driver_api);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -13,36 +13,30 @@
|
|||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct behavior_transparent_config { };
|
||||
struct behavior_transparent_data { };
|
||||
struct behavior_transparent_config {};
|
||||
struct behavior_transparent_data {};
|
||||
|
||||
static int behavior_transparent_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
static int behavior_transparent_init(struct device *dev) { return 0; };
|
||||
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
|
||||
{
|
||||
return 1;
|
||||
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
|
||||
u32_t _param2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
|
||||
{
|
||||
return 1;
|
||||
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1,
|
||||
u32_t _param2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_transparent_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
};
|
||||
|
||||
|
||||
static const struct behavior_transparent_config behavior_transparent_config = {};
|
||||
|
||||
static struct behavior_transparent_data behavior_transparent_data;
|
||||
|
||||
DEVICE_AND_API_INIT(behavior_transparent, DT_INST_LABEL(0), behavior_transparent_init,
|
||||
&behavior_transparent_data,
|
||||
&behavior_transparent_config,
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&behavior_transparent_driver_api);
|
||||
&behavior_transparent_data, &behavior_transparent_config, APPLICATION,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_transparent_driver_api);
|
400
app/src/ble.c
400
app/src/ble.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -8,6 +8,8 @@
|
|||
#include <init.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <settings/settings.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
@ -15,37 +17,224 @@
|
|||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/uuid.h>
|
||||
#include <bluetooth/gatt.h>
|
||||
#include <bluetooth/hci_err.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||
|
||||
#include <settings/settings.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <logging/log.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#include <zmk/ble.h>
|
||||
#include <zmk/keys.h>
|
||||
#include <zmk/split/bluetooth/uuid.h>
|
||||
#include <zmk/event-manager.h>
|
||||
#include <zmk/events/ble-active-profile-changed.h>
|
||||
|
||||
static struct bt_conn *auth_passkey_entry_conn;
|
||||
static u8_t passkey_entries[6] = {0, 0, 0, 0, 0, 0};
|
||||
static u8_t passkey_digit = 0;
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
#define ZMK_ADV_PARAMS BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
|
||||
BT_LE_ADV_OPT_USE_NAME | \
|
||||
BT_LE_ADV_OPT_ONE_TIME, \
|
||||
BT_GAP_ADV_FAST_INT_MIN_2, \
|
||||
BT_GAP_ADV_FAST_INT_MAX_2, NULL)
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
#define PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1)
|
||||
#else
|
||||
#define ZMK_ADV_PARAMS BT_LE_ADV_CONN_NAME
|
||||
#define PROFILE_COUNT CONFIG_BT_MAX_PAIRED
|
||||
#endif
|
||||
|
||||
static void connected(struct bt_conn *conn, u8_t err)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
static struct zmk_ble_profile profiles[PROFILE_COUNT];
|
||||
static u8_t active_profile;
|
||||
|
||||
static const struct bt_data zmk_ble_ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_SOME,
|
||||
#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
0x12, 0x18, /* HID Service */
|
||||
#endif
|
||||
0x0f, 0x18 /* Battery Service */
|
||||
),
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
BT_DATA_BYTES(BT_DATA_UUID128_ALL, ZMK_SPLIT_BT_SERVICE_UUID)
|
||||
#endif
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
|
||||
static bt_addr_le_t peripheral_addr;
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
|
||||
|
||||
static void raise_profile_changed_event() {
|
||||
struct ble_active_profile_changed *ev = new_ble_active_profile_changed();
|
||||
ev->index = active_profile;
|
||||
ev->profile = &profiles[active_profile];
|
||||
|
||||
ZMK_EVENT_RAISE(ev);
|
||||
}
|
||||
|
||||
static bool active_profile_is_open() {
|
||||
return !bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY);
|
||||
}
|
||||
|
||||
void set_profile_address(u8_t index, const bt_addr_le_t *addr) {
|
||||
char setting_name[15];
|
||||
char addr_str[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
|
||||
|
||||
memcpy(&profiles[index].peer, addr, sizeof(bt_addr_le_t));
|
||||
sprintf(setting_name, "ble/profiles/%d", index);
|
||||
LOG_DBG("Setting profile addr for %s to %s", log_strdup(setting_name), log_strdup(addr_str));
|
||||
settings_save_one(setting_name, &profiles[index], sizeof(struct zmk_ble_profile));
|
||||
raise_profile_changed_event();
|
||||
}
|
||||
|
||||
int zmk_ble_adv_pause() {
|
||||
int err = bt_le_adv_stop();
|
||||
if (err) {
|
||||
LOG_ERR("Failed to stop advertising (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
int zmk_ble_adv_resume() {
|
||||
LOG_DBG("active_profile %d, directed? %s", active_profile,
|
||||
active_profile_is_open() ? "no" : "yes");
|
||||
|
||||
int err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
|
||||
if (err) {
|
||||
LOG_ERR("Advertising failed to start (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
int zmk_ble_clear_bonds() {
|
||||
LOG_DBG("");
|
||||
|
||||
if (bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY)) {
|
||||
LOG_DBG("Unpairing!");
|
||||
bt_unpair(BT_ID_DEFAULT, &profiles[active_profile].peer);
|
||||
set_profile_address(active_profile, BT_ADDR_LE_ANY);
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
int zmk_ble_prof_select(u8_t index) {
|
||||
LOG_DBG("profile %d", index);
|
||||
if (active_profile == index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
active_profile = index;
|
||||
return settings_save_one("ble/active_profile", &active_profile, sizeof(active_profile));
|
||||
|
||||
raise_profile_changed_event();
|
||||
};
|
||||
|
||||
int zmk_ble_prof_next() {
|
||||
LOG_DBG("");
|
||||
return zmk_ble_prof_select((active_profile + 1) % PROFILE_COUNT);
|
||||
};
|
||||
|
||||
int zmk_ble_prof_prev() {
|
||||
LOG_DBG("");
|
||||
return zmk_ble_prof_select((active_profile + PROFILE_COUNT - 1) % PROFILE_COUNT);
|
||||
};
|
||||
|
||||
bt_addr_le_t *zmk_ble_active_profile_addr() { return &profiles[active_profile].peer; }
|
||||
|
||||
char *zmk_ble_active_profile_name() { return profiles[active_profile].name; }
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
|
||||
void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr) {
|
||||
memcpy(&peripheral_addr, addr, sizeof(bt_addr_le_t));
|
||||
settings_save_one("ble/peripheral_address", addr, sizeof(bt_addr_le_t));
|
||||
}
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
|
||||
|
||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||
|
||||
static int ble_profiles_handle_set(const char *name, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg) {
|
||||
const char *next;
|
||||
|
||||
LOG_DBG("Setting BLE value %s", log_strdup(name));
|
||||
|
||||
if (settings_name_steq(name, "profiles", &next) && next) {
|
||||
char *endptr;
|
||||
u8_t idx = strtoul(next, &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
LOG_WRN("Invalid profile index: %s", log_strdup(next));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len != sizeof(struct zmk_ble_profile)) {
|
||||
LOG_ERR("Invalid profile size (got %d expected %d)", len,
|
||||
sizeof(struct zmk_ble_profile));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (idx >= PROFILE_COUNT) {
|
||||
LOG_WRN("Profile address for index %d is larger than max of %d", idx, PROFILE_COUNT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int err = read_cb(cb_arg, &profiles[idx], sizeof(struct zmk_ble_profile));
|
||||
if (err <= 0) {
|
||||
LOG_ERR("Failed to handle profile address from settings (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
char addr_str[BT_ADDR_LE_STR_LEN];
|
||||
bt_addr_le_to_str(&profiles[idx].peer, addr_str, sizeof(addr_str));
|
||||
|
||||
LOG_DBG("Loaded %s address for profile %d", log_strdup(addr_str), idx);
|
||||
} else if (settings_name_steq(name, "active_profile", &next) && !next) {
|
||||
if (len != sizeof(active_profile)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int err = read_cb(cb_arg, &active_profile, sizeof(active_profile));
|
||||
if (err <= 0) {
|
||||
LOG_ERR("Failed to handle active profile from settings (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
else if (settings_name_steq(name, "peripheral_address", &next) && !next) {
|
||||
if (len != sizeof(bt_addr_le_t)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int err = read_cb(cb_arg, &peripheral_addr, sizeof(bt_addr_le_t));
|
||||
if (err <= 0) {
|
||||
LOG_ERR("Failed to handle peripheral address from settings (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
struct settings_handler profiles_handler = {.name = "ble", .h_set = ble_profiles_handle_set};
|
||||
#endif /* IS_ENABLED(CONFIG_SETTINGS) */
|
||||
|
||||
static void connected(struct bt_conn *conn, u8_t err) {
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
if (err)
|
||||
{
|
||||
if (err) {
|
||||
LOG_WRN("Failed to connect to %s (%u)", log_strdup(addr), err);
|
||||
return;
|
||||
}
|
||||
|
@ -58,36 +247,37 @@ static void connected(struct bt_conn *conn, u8_t err)
|
|||
bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M);
|
||||
#endif
|
||||
|
||||
if (bt_conn_set_security(conn, BT_SECURITY_L2))
|
||||
{
|
||||
if (bt_conn_set_security(conn, BT_SECURITY_L2)) {
|
||||
LOG_ERR("Failed to set security");
|
||||
}
|
||||
}
|
||||
|
||||
static void disconnected(struct bt_conn *conn, u8_t reason)
|
||||
{
|
||||
static void disconnected(struct bt_conn *conn, u8_t reason) {
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
LOG_DBG("Disconnected from %s (reason 0x%02x)", log_strdup(addr), reason);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
// if (bt_addr_le_cmp(&peripheral_addr, BT_ADDR_LE_ANY) && bt_addr_le_cmp(&peripheral_addr,
|
||||
// bt_conn_get_dst(conn))) {
|
||||
// zmk_ble_adv_resume();
|
||||
// }
|
||||
#else
|
||||
// zmk_ble_adv_resume();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void security_changed(struct bt_conn *conn, bt_security_t level,
|
||||
enum bt_security_err err)
|
||||
{
|
||||
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
if (!err)
|
||||
{
|
||||
if (!err) {
|
||||
LOG_DBG("Security changed: %s level %u", log_strdup(addr), level);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERR("Security failed: %s level %u err %d", log_strdup(addr), level,
|
||||
err);
|
||||
} else {
|
||||
LOG_ERR("Security failed: %s level %u err %d", log_strdup(addr), level, err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,8 +287,7 @@ static struct bt_conn_cb conn_callbacks = {
|
|||
.security_changed = security_changed,
|
||||
};
|
||||
|
||||
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
|
||||
{
|
||||
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey) {
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
@ -108,8 +297,7 @@ static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
|
|||
|
||||
#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY
|
||||
|
||||
static void auth_passkey_entry(struct bt_conn *conn)
|
||||
{
|
||||
static void auth_passkey_entry(struct bt_conn *conn) {
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
@ -120,14 +308,12 @@ static void auth_passkey_entry(struct bt_conn *conn)
|
|||
|
||||
#endif
|
||||
|
||||
static void auth_cancel(struct bt_conn *conn)
|
||||
{
|
||||
static void auth_cancel(struct bt_conn *conn) {
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
if (auth_passkey_entry_conn)
|
||||
{
|
||||
if (auth_passkey_entry_conn) {
|
||||
bt_conn_unref(auth_passkey_entry_conn);
|
||||
auth_passkey_entry_conn = NULL;
|
||||
}
|
||||
|
@ -137,7 +323,51 @@ static void auth_cancel(struct bt_conn *conn)
|
|||
LOG_DBG("Pairing cancelled: %s", log_strdup(addr));
|
||||
}
|
||||
|
||||
#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
static enum bt_security_err auth_pairing_accept(struct bt_conn *conn,
|
||||
const struct bt_conn_pairing_feat *const feat) {
|
||||
struct bt_conn_info info;
|
||||
bt_conn_get_info(conn, &info);
|
||||
|
||||
LOG_DBG("role %d, open? %s", info.role, active_profile_is_open() ? "yes" : "no");
|
||||
if (info.role == BT_CONN_ROLE_SLAVE && !active_profile_is_open()) {
|
||||
LOG_WRN("Rejecting pairing request to taken profile %d", active_profile);
|
||||
return BT_SECURITY_ERR_PAIR_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
return BT_SECURITY_ERR_SUCCESS;
|
||||
};
|
||||
#endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
|
||||
|
||||
static void auth_pairing_complete(struct bt_conn *conn, bool bonded) {
|
||||
struct bt_conn_info info;
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
const bt_addr_le_t *dst = bt_conn_get_dst(conn);
|
||||
|
||||
bt_addr_le_to_str(dst, addr, sizeof(addr));
|
||||
bt_conn_get_info(conn, &info);
|
||||
|
||||
if (info.role != BT_CONN_ROLE_SLAVE) {
|
||||
LOG_DBG("SKIPPING FOR ROLE %d", info.role);
|
||||
return;
|
||||
}
|
||||
|
||||
#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
if (!active_profile_is_open()) {
|
||||
LOG_ERR("Pairing completed but current profile is not open: %s", log_strdup(addr));
|
||||
bt_unpair(BT_ID_DEFAULT, dst);
|
||||
return;
|
||||
}
|
||||
#endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
|
||||
|
||||
set_profile_address(active_profile, dst);
|
||||
};
|
||||
|
||||
static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
|
||||
#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
.pairing_accept = auth_pairing_accept,
|
||||
#endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
|
||||
.pairing_complete = auth_pairing_complete,
|
||||
// .passkey_display = auth_passkey_display,
|
||||
|
||||
#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY
|
||||
|
@ -146,52 +376,55 @@ static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
|
|||
.cancel = auth_cancel,
|
||||
};
|
||||
|
||||
static const struct bt_data zmk_ble_ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_SOME,
|
||||
#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
0x12, 0x18, /* HID Service */
|
||||
#endif
|
||||
0x0f, 0x18 /* Battery Service */
|
||||
),
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
BT_DATA_BYTES(BT_DATA_UUID128_ALL,
|
||||
ZMK_SPLIT_BT_SERVICE_UUID)
|
||||
#endif
|
||||
};
|
||||
|
||||
static void zmk_ble_ready(int err)
|
||||
{
|
||||
static void zmk_ble_ready(int err) {
|
||||
LOG_DBG("ready? %d", err);
|
||||
if (err)
|
||||
{
|
||||
if (err) {
|
||||
LOG_ERR("Bluetooth init failed (err %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
err = bt_le_adv_start(ZMK_ADV_PARAMS, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
|
||||
if (err)
|
||||
{
|
||||
LOG_ERR("Advertising failed to start (err %d)", err);
|
||||
return;
|
||||
}
|
||||
zmk_ble_adv_resume();
|
||||
}
|
||||
|
||||
static int zmk_ble_init(struct device *_arg)
|
||||
{
|
||||
static int zmk_ble_init(struct device *_arg) {
|
||||
int err = bt_enable(NULL);
|
||||
|
||||
if (err)
|
||||
{
|
||||
if (err) {
|
||||
LOG_ERR("BLUETOOTH FAILED (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS))
|
||||
{
|
||||
settings_load();
|
||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||
settings_subsys_init();
|
||||
|
||||
err = settings_register(&profiles_handler);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to setup the profile settings handler (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
settings_load();
|
||||
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START)
|
||||
LOG_WRN("Clearing all existing BLE bond information from the keyboard");
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
bt_unpair(i, NULL);
|
||||
}
|
||||
|
||||
for (int i = 0; i < PROFILE_COUNT; i++) {
|
||||
char setting_name[15];
|
||||
sprintf(setting_name, "ble/profiles/%d", i);
|
||||
|
||||
err = settings_delete(setting_name);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to delete setting: %d", err);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bt_conn_cb_register(&conn_callbacks);
|
||||
bt_conn_auth_cb_register(&zmk_ble_auth_cb_display);
|
||||
|
||||
|
@ -200,23 +433,28 @@ static int zmk_ble_init(struct device *_arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int zmk_ble_unpair_all()
|
||||
{
|
||||
LOG_DBG("");
|
||||
return bt_unpair(BT_ID_DEFAULT, NULL);
|
||||
int zmk_ble_unpair_all() {
|
||||
int resp = 0;
|
||||
for (int i = BT_ID_DEFAULT; i < CONFIG_BT_ID_MAX; i++) {
|
||||
|
||||
int err = bt_unpair(BT_ID_DEFAULT, NULL);
|
||||
if (err) {
|
||||
resp = err;
|
||||
LOG_ERR("Failed to unpair devices (err %d)", err);
|
||||
}
|
||||
}
|
||||
|
||||
return resp;
|
||||
};
|
||||
|
||||
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
|
||||
{
|
||||
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event) {
|
||||
zmk_key key = key_event->key;
|
||||
|
||||
if (!auth_passkey_entry_conn)
|
||||
{
|
||||
if (!auth_passkey_entry_conn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key < NUM_1 || key > NUM_0)
|
||||
{
|
||||
if (key < NUM_1 || key > NUM_0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -224,11 +462,9 @@ bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
|
|||
|
||||
passkey_entries[passkey_digit++] = val;
|
||||
|
||||
if (passkey_digit == 6)
|
||||
{
|
||||
if (passkey_digit == 6) {
|
||||
u32_t passkey = 0;
|
||||
for (int i = 5; i >= 0; i--)
|
||||
{
|
||||
for (int i = 5; i >= 0; i--) {
|
||||
passkey = (passkey * 10) + val;
|
||||
}
|
||||
bt_conn_auth_passkey_entry(auth_passkey_entry_conn, passkey);
|
||||
|
@ -239,6 +475,4 @@ bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
|
|||
return false;
|
||||
}
|
||||
|
||||
SYS_INIT(zmk_ble_init,
|
||||
APPLICATION,
|
||||
CONFIG_ZMK_BLE_INIT_PRIORITY);
|
||||
SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -18,14 +18,12 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
#include <zmk/event-manager.h>
|
||||
#include <zmk/events/position-state-changed.h>
|
||||
|
||||
|
||||
static u8_t combo_state;
|
||||
|
||||
const u32_t key_positions[] = DT_INST_PROP(0, key_positions);
|
||||
#define KP_LEN DT_INST_PROP_LEN(0, key_positions)
|
||||
|
||||
int index_for_key_position(u32_t kp)
|
||||
{
|
||||
int index_for_key_position(u32_t kp) {
|
||||
for (int i = 0; i < KP_LEN; i++) {
|
||||
if (key_positions[i] == kp) {
|
||||
return i;
|
||||
|
@ -35,8 +33,7 @@ int index_for_key_position(u32_t kp)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int unpair_combo_listener(const struct zmk_event_header *eh)
|
||||
{
|
||||
int unpair_combo_listener(const struct zmk_event_header *eh) {
|
||||
if (is_position_state_changed(eh)) {
|
||||
const struct position_state_changed *psc = cast_position_state_changed(eh);
|
||||
|
||||
|
@ -51,8 +48,7 @@ int unpair_combo_listener(const struct zmk_event_header *eh)
|
|||
return 0;
|
||||
};
|
||||
|
||||
void unpair_combo_work_handler(struct k_work *work)
|
||||
{
|
||||
void unpair_combo_work_handler(struct k_work *work) {
|
||||
for (int i = 0; i < KP_LEN; i++) {
|
||||
if (!(combo_state & BIT(i))) {
|
||||
LOG_DBG("Key position %d not held, skipping unpair combo", key_positions[i]);
|
||||
|
@ -65,8 +61,7 @@ void unpair_combo_work_handler(struct k_work *work)
|
|||
|
||||
struct k_delayed_work unpair_combo_work;
|
||||
|
||||
int zmk_ble_unpair_combo_init(struct device *_unused)
|
||||
{
|
||||
int zmk_ble_unpair_combo_init(struct device *_unused) {
|
||||
k_delayed_work_init(&unpair_combo_work, unpair_combo_work_handler);
|
||||
k_delayed_work_submit(&unpair_combo_work, K_SECONDS(2));
|
||||
|
||||
|
@ -76,8 +71,6 @@ int zmk_ble_unpair_combo_init(struct device *_unused)
|
|||
ZMK_LISTENER(zmk_ble_unpair_combo, unpair_combo_listener);
|
||||
ZMK_SUBSCRIPTION(zmk_ble_unpair_combo, position_state_changed);
|
||||
|
||||
SYS_INIT(zmk_ble_unpair_combo_init,
|
||||
APPLICATION,
|
||||
CONFIG_APPLICATION_INIT_PRIORITY);
|
||||
SYS_INIT(zmk_ble_unpair_combo_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||
|
||||
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -20,8 +20,7 @@ static struct device *display;
|
|||
|
||||
static lv_obj_t *screen;
|
||||
|
||||
int zmk_display_init()
|
||||
{
|
||||
int zmk_display_init() {
|
||||
lv_obj_t *hello_world_label;
|
||||
lv_obj_t *count_label;
|
||||
|
||||
|
@ -48,8 +47,7 @@ int zmk_display_init()
|
|||
return 0;
|
||||
}
|
||||
|
||||
void zmk_display_task_handler()
|
||||
{
|
||||
void zmk_display_task_handler() {
|
||||
lv_tick_inc(10);
|
||||
lv_task_handler();
|
||||
k_sleep(K_MSEC(10));
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <zmk/endpoints.h>
|
||||
#include <zmk/hid.h>
|
||||
|
@ -7,27 +12,24 @@
|
|||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
int zmk_endpoints_send_report(u8_t usage_page)
|
||||
{
|
||||
int zmk_endpoints_send_report(u8_t usage_page) {
|
||||
int err;
|
||||
struct zmk_hid_keypad_report *keypad_report;
|
||||
struct zmk_hid_consumer_report *consumer_report;
|
||||
LOG_DBG("usage page 0x%02X", usage_page);
|
||||
switch (usage_page)
|
||||
{
|
||||
switch (usage_page) {
|
||||
case USAGE_KEYPAD:
|
||||
keypad_report = zmk_hid_get_keypad_report();
|
||||
#ifdef CONFIG_ZMK_USB
|
||||
if (zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(struct zmk_hid_keypad_report)) != 0)
|
||||
{
|
||||
if (zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(struct zmk_hid_keypad_report)) !=
|
||||
0) {
|
||||
LOG_DBG("USB Send Failed");
|
||||
}
|
||||
#endif /* CONFIG_ZMK_USB */
|
||||
|
||||
#ifdef CONFIG_ZMK_BLE
|
||||
err = zmk_hog_send_keypad_report(&keypad_report->body);
|
||||
if (err)
|
||||
{
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||
}
|
||||
#endif /* CONFIG_ZMK_BLE */
|
||||
|
@ -36,16 +38,15 @@ int zmk_endpoints_send_report(u8_t usage_page)
|
|||
case USAGE_CONSUMER:
|
||||
consumer_report = zmk_hid_get_consumer_report();
|
||||
#ifdef CONFIG_ZMK_USB
|
||||
if (zmk_usb_hid_send_report((u8_t *)consumer_report, sizeof(struct zmk_hid_consumer_report)) != 0)
|
||||
{
|
||||
if (zmk_usb_hid_send_report((u8_t *)consumer_report,
|
||||
sizeof(struct zmk_hid_consumer_report)) != 0) {
|
||||
LOG_DBG("USB Send Failed");
|
||||
}
|
||||
#endif /* CONFIG_ZMK_USB */
|
||||
|
||||
#ifdef CONFIG_ZMK_BLE
|
||||
err = zmk_hog_send_consumer_report(&consumer_report->body);
|
||||
if (err)
|
||||
{
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||
}
|
||||
#endif /* CONFIG_ZMK_BLE */
|
||||
|
@ -58,4 +59,3 @@ int zmk_endpoints_send_report(u8_t usage_page)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
|
@ -11,15 +11,13 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
|
||||
#include <zmk/event-manager.h>
|
||||
|
||||
extern struct zmk_event_type* __event_type_start[];
|
||||
extern struct zmk_event_type* __event_type_end[];
|
||||
extern struct zmk_event_type *__event_type_start[];
|
||||
extern struct zmk_event_type *__event_type_end[];
|
||||
|
||||
extern struct zmk_event_subscription __event_subscriptions_start[];
|
||||
extern struct zmk_event_subscription __event_subscriptions_end[];
|
||||
|
||||
|
||||
int zmk_event_manager_handle_from(struct zmk_event_header *event, u8_t start_index)
|
||||
{
|
||||
int zmk_event_manager_handle_from(struct zmk_event_header *event, u8_t start_index) {
|
||||
int ret = 0;
|
||||
u8_t len = __event_subscriptions_end - __event_subscriptions_start;
|
||||
for (int i = start_index; i < len; i++) {
|
||||
|
@ -31,15 +29,15 @@ int zmk_event_manager_handle_from(struct zmk_event_header *event, u8_t start_ind
|
|||
goto release;
|
||||
} else if (ret > 0) {
|
||||
switch (ret) {
|
||||
case ZMK_EV_EVENT_HANDLED:
|
||||
LOG_DBG("Listener handled the event");
|
||||
ret = 0;
|
||||
goto release;
|
||||
case ZMK_EV_EVENT_CAPTURED:
|
||||
LOG_DBG("Listener captured the event");
|
||||
event->last_listener_index = i;
|
||||
// Listeners are expected to free events they capture
|
||||
return 0;
|
||||
case ZMK_EV_EVENT_HANDLED:
|
||||
LOG_DBG("Listener handled the event");
|
||||
ret = 0;
|
||||
goto release;
|
||||
case ZMK_EV_EVENT_CAPTURED:
|
||||
LOG_DBG("Listener captured the event");
|
||||
event->last_listener_index = i;
|
||||
// Listeners are expected to free events they capture
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,19 +48,18 @@ release:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int zmk_event_manager_raise(struct zmk_event_header *event)
|
||||
{
|
||||
int zmk_event_manager_raise(struct zmk_event_header *event) {
|
||||
return zmk_event_manager_handle_from(event, 0);
|
||||
}
|
||||
|
||||
int zmk_event_manager_raise_after(struct zmk_event_header *event, const struct zmk_listener *listener)
|
||||
{
|
||||
int zmk_event_manager_raise_after(struct zmk_event_header *event,
|
||||
const struct zmk_listener *listener) {
|
||||
u8_t len = __event_subscriptions_end - __event_subscriptions_start;
|
||||
for (int i = 0; i < len; i++) {
|
||||
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
|
||||
|
||||
if (ev_sub->event_type == event->event && ev_sub->listener == listener) {
|
||||
return zmk_event_manager_handle_from(event, i+1);
|
||||
return zmk_event_manager_handle_from(event, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,8 +68,8 @@ int zmk_event_manager_raise_after(struct zmk_event_header *event, const struct z
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
int zmk_event_manager_raise_at(struct zmk_event_header *event, const struct zmk_listener *listener)
|
||||
{
|
||||
int zmk_event_manager_raise_at(struct zmk_event_header *event,
|
||||
const struct zmk_listener *listener) {
|
||||
u8_t len = __event_subscriptions_end - __event_subscriptions_start;
|
||||
for (int i = 0; i < len; i++) {
|
||||
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
|
||||
|
@ -87,7 +84,6 @@ int zmk_event_manager_raise_at(struct zmk_event_header *event, const struct zmk_
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
int zmk_event_manager_release(struct zmk_event_header *event)
|
||||
{
|
||||
int zmk_event_manager_release(struct zmk_event_header *event) {
|
||||
return zmk_event_manager_handle_from(event, event->last_listener_index + 1);
|
||||
}
|
||||
|
|
10
app/src/events/ble_active_profile_changed.c
Normal file
10
app/src/events/ble_active_profile_changed.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <zmk/events/ble-active-profile-changed.h>
|
||||
|
||||
ZMK_EVENT_IMPL(ble_active_profile_changed);
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,44 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#include <zmk/hid.h>
|
||||
|
||||
static struct zmk_hid_keypad_report kp_report = {
|
||||
.report_id = 1,
|
||||
.body = {
|
||||
.modifiers = 0,
|
||||
.keys = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}};
|
||||
.report_id = 1, .body = {.modifiers = 0, .keys = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}};
|
||||
|
||||
static struct zmk_hid_consumer_report consumer_report = {
|
||||
.report_id = 2,
|
||||
.body = {
|
||||
.keys = {0,0,0,0,0,0}}};
|
||||
static struct zmk_hid_consumer_report consumer_report = {.report_id = 2,
|
||||
.body = {.keys = {0, 0, 0, 0, 0, 0}}};
|
||||
|
||||
#define _TOGGLE_MOD(mod, state) \
|
||||
if (modifier > MOD_RGUI) \
|
||||
{ \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
WRITE_BIT(kp_report.body.modifiers, mod, state); \
|
||||
#define _TOGGLE_MOD(mod, state) \
|
||||
if (modifier > MOD_RGUI) { \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
WRITE_BIT(kp_report.body.modifiers, mod, state); \
|
||||
return 0;
|
||||
|
||||
int zmk_hid_register_mod(zmk_mod modifier)
|
||||
{
|
||||
_TOGGLE_MOD(modifier, true);
|
||||
}
|
||||
int zmk_hid_unregister_mod(zmk_mod modifier)
|
||||
{
|
||||
_TOGGLE_MOD(modifier, false);
|
||||
}
|
||||
int zmk_hid_register_mod(zmk_mod modifier) { _TOGGLE_MOD(modifier, true); }
|
||||
int zmk_hid_unregister_mod(zmk_mod modifier) { _TOGGLE_MOD(modifier, false); }
|
||||
|
||||
int zmk_hid_register_mods(zmk_mod_flags modifiers)
|
||||
{
|
||||
int zmk_hid_register_mods(zmk_mod_flags modifiers) {
|
||||
kp_report.body.modifiers |= modifiers;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmk_hid_unregister_mods(zmk_mod_flags modifiers)
|
||||
{
|
||||
int zmk_hid_unregister_mods(zmk_mod_flags modifiers) {
|
||||
kp_report.body.modifiers &= ~modifiers;
|
||||
return 0;
|
||||
}
|
||||
|
@ -61,28 +53,21 @@ int zmk_hid_unregister_mods(zmk_mod_flags modifiers)
|
|||
|
||||
#define TOGGLE_KEY(code, val) WRITE_BIT(kp_report.body.keys[code / 8], code % 8, val)
|
||||
|
||||
#define TOGGLE_CONSUMER(match, val) \
|
||||
for (int idx = 0; idx < MAX_KEYS; idx++) \
|
||||
{ \
|
||||
if (consumer_report.body.keys[idx] != match) \
|
||||
{ \
|
||||
continue; \
|
||||
} \
|
||||
consumer_report.body.keys[idx] = val; \
|
||||
break; \
|
||||
#define TOGGLE_CONSUMER(match, val) \
|
||||
for (int idx = 0; idx < MAX_KEYS; idx++) { \
|
||||
if (consumer_report.body.keys[idx] != match) { \
|
||||
continue; \
|
||||
} \
|
||||
consumer_report.body.keys[idx] = val; \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
int zmk_hid_keypad_press(zmk_key code)
|
||||
{
|
||||
if (code >= LCTL && code <= RGUI)
|
||||
{
|
||||
int zmk_hid_keypad_press(zmk_key code) {
|
||||
if (code >= LCTL && code <= RGUI) {
|
||||
return zmk_hid_register_mod(code - LCTL);
|
||||
}
|
||||
|
||||
|
||||
if (code > ZMK_HID_MAX_KEYCODE)
|
||||
{
|
||||
if (code > ZMK_HID_MAX_KEYCODE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -93,15 +78,12 @@ int zmk_hid_keypad_press(zmk_key code)
|
|||
return 0;
|
||||
};
|
||||
|
||||
int zmk_hid_keypad_release(zmk_key code)
|
||||
{
|
||||
if (code >= LCTL && code <= RGUI)
|
||||
{
|
||||
int zmk_hid_keypad_release(zmk_key code) {
|
||||
if (code >= LCTL && code <= RGUI) {
|
||||
return zmk_hid_unregister_mod(code - LCTL);
|
||||
}
|
||||
|
||||
if (code > ZMK_HID_MAX_KEYCODE)
|
||||
{
|
||||
if (code > ZMK_HID_MAX_KEYCODE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -112,25 +94,20 @@ int zmk_hid_keypad_release(zmk_key code)
|
|||
return 0;
|
||||
};
|
||||
|
||||
int zmk_hid_consumer_press(zmk_key code)
|
||||
{
|
||||
int zmk_hid_consumer_press(zmk_key code) {
|
||||
TOGGLE_CONSUMER(0U, code);
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
int zmk_hid_consumer_release(zmk_key code)
|
||||
{
|
||||
int zmk_hid_consumer_release(zmk_key code) {
|
||||
TOGGLE_CONSUMER(code, 0U);
|
||||
return 0;
|
||||
};
|
||||
|
||||
struct zmk_hid_keypad_report *zmk_hid_get_keypad_report()
|
||||
{
|
||||
struct zmk_hid_keypad_report *zmk_hid_get_keypad_report() {
|
||||
return &kp_report;
|
||||
}
|
||||
|
||||
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report()
|
||||
{
|
||||
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report() {
|
||||
return &consumer_report;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -15,90 +15,84 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
#include <zmk/hid.h>
|
||||
#include <zmk/endpoints.h>
|
||||
|
||||
static int hid_listener_keycode_pressed(u8_t usage_page, u32_t keycode) {
|
||||
int err;
|
||||
LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
|
||||
|
||||
static int hid_listener_keycode_pressed(u8_t usage_page, u32_t keycode)
|
||||
{
|
||||
int err;
|
||||
LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
|
||||
|
||||
switch (usage_page) {
|
||||
case USAGE_KEYPAD:
|
||||
err = zmk_hid_keypad_press(keycode);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to press keycode");
|
||||
return err;
|
||||
switch (usage_page) {
|
||||
case USAGE_KEYPAD:
|
||||
err = zmk_hid_keypad_press(keycode);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to press keycode");
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
case USAGE_CONSUMER:
|
||||
err = zmk_hid_consumer_press(keycode);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to press keycode");
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case USAGE_CONSUMER:
|
||||
err = zmk_hid_consumer_press(keycode);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to press keycode");
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return zmk_endpoints_send_report(usage_page);
|
||||
return zmk_endpoints_send_report(usage_page);
|
||||
}
|
||||
|
||||
static int hid_listener_keycode_released(u8_t usage_page, u32_t keycode)
|
||||
{
|
||||
int err;
|
||||
LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
|
||||
|
||||
switch (usage_page) {
|
||||
case USAGE_KEYPAD:
|
||||
err = zmk_hid_keypad_release(keycode);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to release keycode");
|
||||
return err;
|
||||
static int hid_listener_keycode_released(u8_t usage_page, u32_t keycode) {
|
||||
int err;
|
||||
LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
|
||||
|
||||
switch (usage_page) {
|
||||
case USAGE_KEYPAD:
|
||||
err = zmk_hid_keypad_release(keycode);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to release keycode");
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
case USAGE_CONSUMER:
|
||||
err = zmk_hid_consumer_release(keycode);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to release keycode");
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case USAGE_CONSUMER:
|
||||
err = zmk_hid_consumer_release(keycode);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to release keycode");
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return zmk_endpoints_send_report(usage_page);
|
||||
return zmk_endpoints_send_report(usage_page);
|
||||
}
|
||||
|
||||
static int hid_listener_modifiers_pressed(zmk_mod_flags modifiers)
|
||||
{
|
||||
LOG_DBG("modifiers %d", modifiers);
|
||||
|
||||
zmk_hid_register_mods(modifiers);
|
||||
return zmk_endpoints_send_report(USAGE_KEYPAD);
|
||||
static int hid_listener_modifiers_pressed(zmk_mod_flags modifiers) {
|
||||
LOG_DBG("modifiers %d", modifiers);
|
||||
|
||||
zmk_hid_register_mods(modifiers);
|
||||
return zmk_endpoints_send_report(USAGE_KEYPAD);
|
||||
}
|
||||
|
||||
static int hid_listener_modifiers_released(zmk_mod_flags modifiers)
|
||||
{
|
||||
LOG_DBG("modifiers %d", modifiers);
|
||||
|
||||
zmk_hid_unregister_mods(modifiers);
|
||||
return zmk_endpoints_send_report(USAGE_KEYPAD);
|
||||
static int hid_listener_modifiers_released(zmk_mod_flags modifiers) {
|
||||
LOG_DBG("modifiers %d", modifiers);
|
||||
|
||||
zmk_hid_unregister_mods(modifiers);
|
||||
return zmk_endpoints_send_report(USAGE_KEYPAD);
|
||||
}
|
||||
|
||||
int hid_listener(const struct zmk_event_header *eh)
|
||||
{
|
||||
if (is_keycode_state_changed(eh)) {
|
||||
const struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
|
||||
if (ev->state) {
|
||||
hid_listener_keycode_pressed(ev->usage_page, ev->keycode);
|
||||
} else {
|
||||
hid_listener_keycode_released(ev->usage_page, ev->keycode);
|
||||
int hid_listener(const struct zmk_event_header *eh) {
|
||||
if (is_keycode_state_changed(eh)) {
|
||||
const struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
|
||||
if (ev->state) {
|
||||
hid_listener_keycode_pressed(ev->usage_page, ev->keycode);
|
||||
} else {
|
||||
hid_listener_keycode_released(ev->usage_page, ev->keycode);
|
||||
}
|
||||
} else if (is_modifiers_state_changed(eh)) {
|
||||
const struct modifiers_state_changed *ev = cast_modifiers_state_changed(eh);
|
||||
if (ev->state) {
|
||||
hid_listener_modifiers_pressed(ev->modifiers);
|
||||
} else {
|
||||
hid_listener_modifiers_released(ev->modifiers);
|
||||
}
|
||||
}
|
||||
} else if (is_modifiers_state_changed(eh)) {
|
||||
const struct modifiers_state_changed *ev = cast_modifiers_state_changed(eh);
|
||||
if (ev->state) {
|
||||
hid_listener_modifiers_pressed(ev->modifiers);
|
||||
} else {
|
||||
hid_listener_modifiers_released(ev->modifiers);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(hid_listener, hid_listener);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue