Browse Source

Merge pull request #183 from petejohanson/ops/clang-format-checks

Standardize code formatting using clang-format w/ LLVM style
xmkb
Pete Johanson 4 years ago committed by GitHub
parent
commit
9110335142
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .clang-format
  2. 25
      .github/workflows/clang-format-lint.yml
  3. 54
      app/boards/arm/dz60rgb/pinmux.c
  4. 27
      app/boards/arm/nrfmicro/pinmux.c
  5. 52
      app/boards/arm/planck/pinmux.c
  6. 54
      app/boards/arm/proton_c/pinmux.c
  7. 203
      app/drivers/zephyr/ec11.c
  8. 49
      app/drivers/zephyr/ec11.h
  9. 176
      app/drivers/zephyr/ec11_trigger.c
  10. 349
      app/drivers/zephyr/kscan_gpio_direct.c
  11. 474
      app/drivers/zephyr/kscan_gpio_matrix.c
  12. 69
      app/include/drivers/behavior.h
  13. 16
      app/include/dt-bindings/zmk/bt.h
  14. 6
      app/include/dt-bindings/zmk/keys.h
  15. 9
      app/include/dt-bindings/zmk/reset.h
  16. 75
      app/include/zmk/event-manager.h
  17. 1
      app/include/zmk/events/ble-active-profile-changed.h
  18. 6
      app/include/zmk/events/keycode-state-changed.h
  19. 6
      app/include/zmk/events/modifiers-state-changed.h
  20. 12
      app/include/zmk/hid.h
  21. 3
      app/include/zmk/keys.h
  22. 18
      app/include/zmk/matrix.h
  23. 5
      app/include/zmk/split/bluetooth/uuid.h
  24. 23
      app/src/behaviors/behavior_bt.c
  25. 754
      app/src/behaviors/behavior_hold_tap.c
  26. 50
      app/src/behaviors/behavior_key_press.c
  27. 35
      app/src/behaviors/behavior_momentary_layer.c
  28. 32
      app/src/behaviors/behavior_none.c
  29. 40
      app/src/behaviors/behavior_reset.c
  30. 45
      app/src/behaviors/behavior_rgb_underglow.c
  31. 102
      app/src/behaviors/behavior_sensor_rotate_key_press.c
  32. 33
      app/src/behaviors/behavior_toggle_layer.c
  33. 32
      app/src/behaviors/behavior_transparent.c
  34. 154
      app/src/ble.c
  35. 17
      app/src/ble_unpair_combo.c
  36. 6
      app/src/display.c
  37. 21
      app/src/endpoints.c
  38. 42
      app/src/event_manager.c
  39. 91
      app/src/hid.c
  40. 130
      app/src/hid_listener.c
  41. 124
      app/src/hog.c
  42. 267
      app/src/keymap.c
  43. 78
      app/src/kscan.c
  44. 63
      app/src/kscan_composite.c
  45. 119
      app/src/kscan_mock.c
  46. 20
      app/src/main.c
  47. 11
      app/src/matrix_transform.c
  48. 205
      app/src/rgb_underglow.c
  49. 30
      app/src/sensors.c
  50. 475
      app/src/split/bluetooth/central.c
  51. 39
      app/src/split/bluetooth/service.c
  52. 21
      app/src/split_listener.c
  53. 93
      app/src/usb_hid.c

4
.clang-format

@ -0,0 +1,4 @@
BasedOnStyle: LLVM
IndentWidth: 4
ColumnLimit: 100
SortIncludes: false

25
.github/workflows/clang-format-lint.yml

@ -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"

54
app/boards/arm/dz60rgb/pinmux.c

@ -15,55 +15,53 @@
/* pin assignments for STM32F3DISCOVERY board */ /* pin assignments for STM32F3DISCOVERY board */
static const struct pin_config pinconf[] = { static const struct pin_config pinconf[] = {
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay) && CONFIG_SERIAL #if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay) && CONFIG_SERIAL
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX}, {STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX}, {STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay) && CONFIG_SERIAL #if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay) && CONFIG_SERIAL
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX}, {STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX}, {STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) && CONFIG_I2C #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) && CONFIG_I2C
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL}, {STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA}, {STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay) && CONFIG_I2C #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay) && CONFIG_I2C
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL}, {STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA}, {STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI #if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI
#ifdef CONFIG_SPI_STM32_USE_HW_SS #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 */ #endif /* CONFIG_SPI_STM32_USE_HW_SS */
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK}, {STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO}, {STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI}, {STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay) && CONFIG_SPI #if DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay) && CONFIG_SPI
#ifdef CONFIG_SPI_STM32_USE_HW_SS #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 */ #endif /* CONFIG_SPI_STM32_USE_HW_SS */
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK}, {STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO}, {STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI}, {STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
#endif #endif
#ifdef CONFIG_USB_DC_STM32 #ifdef CONFIG_USB_DC_STM32
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM}, {STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP}, {STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
#endif /* CONFIG_USB_DC_STM32 */ #endif /* CONFIG_USB_DC_STM32 */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) && CONFIG_CAN #if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) && CONFIG_CAN
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX}, {STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX}, {STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
#endif #endif
}; };
static int pinmux_stm32_init(struct device *port) static int pinmux_stm32_init(struct device *port) {
{ ARG_UNUSED(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, SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);

27
app/boards/arm/nrfmicro/pinmux.c

@ -11,31 +11,30 @@
#include <sys/sys_io.h> #include <sys/sys_io.h>
#include <devicetree.h> #include <devicetree.h>
static int pinmux_nrfmicro_init(struct device *port) static int pinmux_nrfmicro_init(struct device *port) {
{ ARG_UNUSED(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 #if CONFIG_BOARD_NRFMICRO_13
struct device *p0 = device_get_binding("GPIO_0"); struct device *p0 = device_get_binding("GPIO_0");
// enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1) // enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
gpio_pin_configure(p1, 9, GPIO_OUTPUT); gpio_pin_configure(p1, 9, GPIO_OUTPUT);
gpio_pin_set(p1, 9, 0); gpio_pin_set(p1, 9, 0);
#if CONFIG_BOARD_NRFMICRO_CHARGER #if CONFIG_BOARD_NRFMICRO_CHARGER
gpio_pin_configure(p0, 5, GPIO_OUTPUT); gpio_pin_configure(p0, 5, GPIO_OUTPUT);
gpio_pin_set(p0, 5, 0); gpio_pin_set(p0, 5, 0);
#else #else
gpio_pin_configure(p0, 5, GPIO_INPUT); gpio_pin_configure(p0, 5, GPIO_INPUT);
#endif #endif
#else #else
// enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1) // enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
gpio_pin_configure(p1, 9, GPIO_OUTPUT); gpio_pin_configure(p1, 9, GPIO_OUTPUT);
gpio_pin_set(p1, 9, 1); gpio_pin_set(p1, 9, 1);
#endif #endif
return 0; return 0;
} }
SYS_INIT(pinmux_nrfmicro_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); SYS_INIT(pinmux_nrfmicro_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);

52
app/boards/arm/planck/pinmux.c

@ -15,55 +15,53 @@
/* pin assignments for STM32F3DISCOVERY board */ /* pin assignments for STM32F3DISCOVERY board */
static const struct pin_config pinconf[] = { static const struct pin_config pinconf[] = {
#ifdef CONFIG_UART_1 #ifdef CONFIG_UART_1
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX}, {STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX}, {STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
#endif /* CONFIG_UART_1 */ #endif /* CONFIG_UART_1 */
#ifdef CONFIG_UART_2 #ifdef CONFIG_UART_2
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX}, {STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX}, {STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
#endif /* CONFIG_UART_2 */ #endif /* CONFIG_UART_2 */
#ifdef CONFIG_I2C_1 #ifdef CONFIG_I2C_1
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL}, {STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA}, {STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
#endif /* CONFIG_I2C_1 */ #endif /* CONFIG_I2C_1 */
#ifdef CONFIG_I2C_2 #ifdef CONFIG_I2C_2
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL}, {STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA}, {STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
#endif /* CONFIG_I2C_2 */ #endif /* CONFIG_I2C_2 */
#ifdef CONFIG_SPI_1 #ifdef CONFIG_SPI_1
#ifdef CONFIG_SPI_STM32_USE_HW_SS #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 */ #endif /* CONFIG_SPI_STM32_USE_HW_SS */
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK}, {STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO}, {STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI}, {STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
#endif /* CONFIG_SPI_1 */ #endif /* CONFIG_SPI_1 */
#ifdef CONFIG_SPI_2 #ifdef CONFIG_SPI_2
#ifdef CONFIG_SPI_STM32_USE_HW_SS #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 */ #endif /* CONFIG_SPI_STM32_USE_HW_SS */
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK}, {STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO}, {STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI}, {STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
#endif /* CONFIG_SPI_2 */ #endif /* CONFIG_SPI_2 */
#ifdef CONFIG_USB_DC_STM32 #ifdef CONFIG_USB_DC_STM32
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM}, {STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP}, {STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
#endif /* CONFIG_USB_DC_STM32 */ #endif /* CONFIG_USB_DC_STM32 */
#ifdef CONFIG_CAN_1 #ifdef CONFIG_CAN_1
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX}, {STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX}, {STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
#endif /* CONFIG_CAN_1 */ #endif /* CONFIG_CAN_1 */
}; };
static int pinmux_stm32_init(struct device *port) static int pinmux_stm32_init(struct device *port) {
{ ARG_UNUSED(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, SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);

54
app/boards/arm/proton_c/pinmux.c

@ -15,55 +15,53 @@
/* pin assignments for STM32F3DISCOVERY board */ /* pin assignments for STM32F3DISCOVERY board */
static const struct pin_config pinconf[] = { static const struct pin_config pinconf[] = {
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay) && CONFIG_SERIAL #if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay) && CONFIG_SERIAL
{STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX}, {STM32_PIN_PC4, STM32F3_PINMUX_FUNC_PC4_USART1_TX},
{STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX}, {STM32_PIN_PC5, STM32F3_PINMUX_FUNC_PC5_USART1_RX},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay) && CONFIG_SERIAL #if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay) && CONFIG_SERIAL
{STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX}, {STM32_PIN_PA2, STM32F3_PINMUX_FUNC_PA2_USART2_TX},
{STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX}, {STM32_PIN_PA3, STM32F3_PINMUX_FUNC_PA3_USART2_RX},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) && CONFIG_I2C #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) && CONFIG_I2C
{STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL}, {STM32_PIN_PB6, STM32F3_PINMUX_FUNC_PB6_I2C1_SCL},
{STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA}, {STM32_PIN_PB7, STM32F3_PINMUX_FUNC_PB7_I2C1_SDA},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay) && CONFIG_I2C #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c2), okay) && CONFIG_I2C
{STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL}, {STM32_PIN_PA9, STM32F3_PINMUX_FUNC_PA9_I2C2_SCL},
{STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA}, {STM32_PIN_PA10, STM32F3_PINMUX_FUNC_PA10_I2C2_SDA},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI #if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI
#ifdef CONFIG_SPI_STM32_USE_HW_SS #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 */ #endif /* CONFIG_SPI_STM32_USE_HW_SS */
{STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK}, {STM32_PIN_PA5, STM32F3_PINMUX_FUNC_PA5_SPI1_SCK},
{STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO}, {STM32_PIN_PA6, STM32F3_PINMUX_FUNC_PA6_SPI1_MISO},
{STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI}, {STM32_PIN_PA7, STM32F3_PINMUX_FUNC_PA7_SPI1_MOSI},
#endif #endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay) && CONFIG_SPI #if DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay) && CONFIG_SPI
#ifdef CONFIG_SPI_STM32_USE_HW_SS #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 */ #endif /* CONFIG_SPI_STM32_USE_HW_SS */
{STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK}, {STM32_PIN_PB13, STM32F3_PINMUX_FUNC_PB13_SPI2_SCK},
{STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO}, {STM32_PIN_PB14, STM32F3_PINMUX_FUNC_PB14_SPI2_MISO},
{STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI}, {STM32_PIN_PB15, STM32F3_PINMUX_FUNC_PB15_SPI2_MOSI},
#endif #endif
#ifdef CONFIG_USB_DC_STM32 #ifdef CONFIG_USB_DC_STM32
{STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM}, {STM32_PIN_PA11, STM32F3_PINMUX_FUNC_PA11_USB_DM},
{STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP}, {STM32_PIN_PA12, STM32F3_PINMUX_FUNC_PA12_USB_DP},
#endif /* CONFIG_USB_DC_STM32 */ #endif /* CONFIG_USB_DC_STM32 */
#if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) && CONFIG_CAN #if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay) && CONFIG_CAN
{STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX}, {STM32_PIN_PD0, STM32F3_PINMUX_FUNC_PD0_CAN1_RX},
{STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX}, {STM32_PIN_PD1, STM32F3_PINMUX_FUNC_PD1_CAN1_TX},
#endif #endif
}; };
static int pinmux_stm32_init(struct device *port) static int pinmux_stm32_init(struct device *port) {
{ ARG_UNUSED(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, SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);
CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);

203
app/drivers/zephyr/ec11.c

@ -18,136 +18,131 @@
LOG_MODULE_REGISTER(EC11, CONFIG_SENSOR_LOG_LEVEL); LOG_MODULE_REGISTER(EC11, CONFIG_SENSOR_LOG_LEVEL);
static int ec11_get_ab_state(struct device *dev) static int ec11_get_ab_state(struct device *dev) {
{ struct ec11_data *drv_data = dev->driver_data;
struct ec11_data *drv_data = dev->driver_data; const struct ec11_config *drv_cfg = dev->config_info;
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) static int ec11_sample_fetch(struct device *dev, enum sensor_channel chan) {
{ struct ec11_data *drv_data = dev->driver_data;
struct ec11_data *drv_data = dev->driver_data; const struct ec11_config *drv_cfg = dev->config_info;
const struct ec11_config *drv_cfg = dev->config_info; u8_t val;
u8_t val; s8_t delta;
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)) {
switch(val | (drv_data->ab_state << 2)) { case 0b0010:
case 0b0010: case 0b0100: case 0b1101: case 0b1011: case 0b0100:
delta = -1; case 0b1101:
break; case 0b1011:
case 0b0001: case 0b0111: case 0b1110: case 0b1000: delta = -1;
delta = 1; break;
break; case 0b0001:
default: case 0b0111:
delta = 0; case 0b1110:
break; case 0b1000:
} delta = 1;
break;
LOG_DBG("Delta: %d", delta); default:
delta = 0;
drv_data->pulses += delta; break;
drv_data->ab_state = val; }
drv_data->ticks = drv_data->pulses / drv_cfg->resolution; LOG_DBG("Delta: %d", delta);
drv_data->delta = delta;
drv_data->pulses %= drv_cfg->resolution; drv_data->pulses += delta;
drv_data->ab_state = val;
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, static int ec11_channel_get(struct device *dev, enum sensor_channel chan,
enum sensor_channel chan, struct sensor_value *val) {
struct sensor_value *val) struct ec11_data *drv_data = dev->driver_data;
{
struct ec11_data *drv_data = dev->driver_data;
if (chan != SENSOR_CHAN_ROTATION) { if (chan != SENSOR_CHAN_ROTATION) {
return -ENOTSUP; return -ENOTSUP;
} }
val->val1 = drv_data->ticks; val->val1 = drv_data->ticks;
val->val2 = drv_data->delta; val->val2 = drv_data->delta;
return 0; return 0;
} }
static const struct sensor_driver_api ec11_driver_api = { static const struct sensor_driver_api ec11_driver_api = {
#ifdef CONFIG_EC11_TRIGGER #ifdef CONFIG_EC11_TRIGGER
.trigger_set = ec11_trigger_set, .trigger_set = ec11_trigger_set,
#endif #endif
.sample_fetch = ec11_sample_fetch, .sample_fetch = ec11_sample_fetch,
.channel_get = ec11_channel_get, .channel_get = ec11_channel_get,
}; };
int ec11_init(struct device *dev) int ec11_init(struct device *dev) {
{ struct ec11_data *drv_data = dev->driver_data;
struct ec11_data *drv_data = dev->driver_data; const struct ec11_config *drv_cfg = dev->config_info;
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);
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); LOG_DBG("A: %s %d B: %s %d resolution %d", drv_cfg->a_label, drv_cfg->a_pin, drv_cfg->b_label,
if (drv_data->b == NULL) { drv_cfg->b_pin, drv_cfg->resolution);
LOG_ERR("Failed to get pointer to B GPIO device");
return -EINVAL;
}
if (gpio_pin_configure(drv_data->a, drv_cfg->a_pin, drv_data->a = device_get_binding(drv_cfg->a_label);
drv_cfg->a_flags if (drv_data->a == NULL) {
| GPIO_INPUT)) { LOG_ERR("Failed to get pointer to A GPIO device");
LOG_DBG("Failed to configure A pin"); return -EINVAL;
return -EIO; }
}
if (gpio_pin_configure(drv_data->b, drv_cfg->b_pin, drv_data->b = device_get_binding(drv_cfg->b_label);
drv_cfg->b_flags if (drv_data->b == NULL) {
| GPIO_INPUT)) { LOG_ERR("Failed to get pointer to B GPIO device");
LOG_DBG("Failed to configure B pin"); return -EINVAL;
return -EIO; }
}
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 #ifdef CONFIG_EC11_TRIGGER
if (ec11_init_interrupt(dev) < 0) { if (ec11_init_interrupt(dev) < 0) {
LOG_DBG("Failed to initialize interrupt!"); LOG_DBG("Failed to initialize interrupt!");
return -EIO; return -EIO;
} }
#endif #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) \ #define EC11_INST(n) \
struct ec11_data ec11_data_##n; \ struct ec11_data ec11_data_##n; \
const struct ec11_config ec11_cfg_##n = { \ const struct ec11_config ec11_cfg_##n = { \
.a_label = DT_INST_GPIO_LABEL(n, a_gpios), \ .a_label = DT_INST_GPIO_LABEL(n, a_gpios), \
.a_pin = DT_INST_GPIO_PIN(n, a_gpios), \ .a_pin = DT_INST_GPIO_PIN(n, a_gpios), \
.a_flags = DT_INST_GPIO_FLAGS(n, a_gpios), \ .a_flags = DT_INST_GPIO_FLAGS(n, a_gpios), \
.b_label = DT_INST_GPIO_LABEL(n, b_gpios), \ .b_label = DT_INST_GPIO_LABEL(n, b_gpios), \
.b_pin = DT_INST_GPIO_PIN(n, b_gpios), \ .b_pin = DT_INST_GPIO_PIN(n, b_gpios), \
.b_flags = DT_INST_GPIO_FLAGS(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))), \ 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, \ DEVICE_AND_API_INIT(ec11, DT_INST_LABEL(n), ec11_init, &ec11_data_##n, &ec11_cfg_##n, \
&ec11_data_##n, \ POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ec11_driver_api);
&ec11_cfg_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
&ec11_driver_api);
DT_INST_FOREACH_STATUS_OKAY(EC11_INST) DT_INST_FOREACH_STATUS_OKAY(EC11_INST)

49
app/drivers/zephyr/ec11.h

@ -11,39 +11,39 @@
#include <sys/util.h> #include <sys/util.h>
struct ec11_config { struct ec11_config {
const char *a_label; const char *a_label;
const u8_t a_pin; const u8_t a_pin;
const u8_t a_flags; const u8_t a_flags;
const char *b_label; const char *b_label;
const u8_t b_pin; const u8_t b_pin;
const u8_t b_flags; const u8_t b_flags;
const u8_t resolution; const u8_t resolution;
}; };
struct ec11_data { struct ec11_data {
struct device *a; struct device *a;
struct device *b; struct device *b;
u8_t ab_state; u8_t ab_state;
s8_t pulses; s8_t pulses;
s8_t ticks; s8_t ticks;
s8_t delta; s8_t delta;
#ifdef CONFIG_EC11_TRIGGER #ifdef CONFIG_EC11_TRIGGER
struct gpio_callback a_gpio_cb; struct gpio_callback a_gpio_cb;
struct gpio_callback b_gpio_cb; struct gpio_callback b_gpio_cb;
struct device *dev; struct device *dev;
sensor_trigger_handler_t handler; sensor_trigger_handler_t handler;
const struct sensor_trigger *trigger; const struct sensor_trigger *trigger;
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD) #if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_EC11_THREAD_STACK_SIZE); K_THREAD_STACK_MEMBER(thread_stack, CONFIG_EC11_THREAD_STACK_SIZE);
struct k_sem gpio_sem; struct k_sem gpio_sem;
struct k_thread thread; struct k_thread thread;
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD) #elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
struct k_work work; struct k_work work;
#endif #endif
#endif /* CONFIG_EC11_TRIGGER */ #endif /* CONFIG_EC11_TRIGGER */
@ -51,9 +51,8 @@ struct ec11_data {
#ifdef CONFIG_EC11_TRIGGER #ifdef CONFIG_EC11_TRIGGER
int ec11_trigger_set(struct device *dev, int ec11_trigger_set(struct device *dev, const struct sensor_trigger *trig,
const struct sensor_trigger *trig, sensor_trigger_handler_t handler);
sensor_trigger_handler_t handler);
int ec11_init_interrupt(struct device *dev); int ec11_init_interrupt(struct device *dev);
#endif #endif

176
app/drivers/zephyr/ec11_trigger.c

@ -19,158 +19,130 @@ extern struct ec11_data ec11_driver;
#include <logging/log.h> #include <logging/log.h>
LOG_MODULE_DECLARE(EC11, CONFIG_SENSOR_LOG_LEVEL); LOG_MODULE_DECLARE(EC11, CONFIG_SENSOR_LOG_LEVEL);
static inline void setup_int(struct device *dev, static inline void setup_int(struct device *dev, bool enable) {
bool enable) struct ec11_data *data = dev->driver_data;
{ const struct ec11_config *cfg = dev->config_info;
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)) {
if (gpio_pin_interrupt_configure(data->a, LOG_WRN("Unable to set A pin GPIO interrupt");
cfg->a_pin, }
enable
? GPIO_INT_EDGE_BOTH if (gpio_pin_interrupt_configure(data->b, cfg->b_pin,
: GPIO_INT_DISABLE)) { enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE)) {
LOG_WRN("Unable to set A pin GPIO interrupt"); 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, static void ec11_a_gpio_callback(struct device *dev, struct gpio_callback *cb, u32_t pins) {
struct gpio_callback *cb, u32_t pins) struct ec11_data *drv_data = CONTAINER_OF(cb, struct ec11_data, a_gpio_cb);
{
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) #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) #elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
k_work_submit(&drv_data->work); k_work_submit(&drv_data->work);
#endif #endif
} }
static void ec11_b_gpio_callback(struct device *dev, static void ec11_b_gpio_callback(struct device *dev, struct gpio_callback *cb, u32_t pins) {
struct gpio_callback *cb, u32_t pins) struct ec11_data *drv_data = CONTAINER_OF(cb, struct ec11_data, b_gpio_cb);
{
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) #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) #elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
k_work_submit(&drv_data->work); k_work_submit(&drv_data->work);
#endif #endif
} }
static void ec11_thread_cb(void *arg) static void ec11_thread_cb(void *arg) {
{ struct device *dev = arg;
struct device *dev = arg; struct ec11_data *drv_data = dev->driver_data;
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 #ifdef CONFIG_EC11_TRIGGER_OWN_THREAD
static void ec11_thread(int dev_ptr, int unused) static void ec11_thread(int dev_ptr, int unused) {
{ struct device *dev = INT_TO_POINTER(dev_ptr);
struct device *dev = INT_TO_POINTER(dev_ptr); struct ec11_data *drv_data = dev->driver_data;
struct ec11_data *drv_data = dev->driver_data;
ARG_UNUSED(unused); ARG_UNUSED(unused);
while (1) { while (1) {
k_sem_take(&drv_data->gpio_sem, K_FOREVER); k_sem_take(&drv_data->gpio_sem, K_FOREVER);
ec11_thread_cb(dev); ec11_thread_cb(dev);
} }
} }
#endif #endif
#ifdef CONFIG_EC11_TRIGGER_GLOBAL_THREAD #ifdef CONFIG_EC11_TRIGGER_GLOBAL_THREAD
static void ec11_work_cb(struct k_work *work) static void ec11_work_cb(struct k_work *work) {
{ struct ec11_data *drv_data = CONTAINER_OF(work, struct ec11_data, 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 #endif
int ec11_trigger_set(struct device *dev, int ec11_trigger_set(struct device *dev, const struct sensor_trigger *trig,
const struct sensor_trigger *trig, sensor_trigger_handler_t handler) {
sensor_trigger_handler_t handler) struct ec11_data *drv_data = dev->driver_data;
{
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->trigger = trig;
drv_data->handler = handler; drv_data->handler = handler;
setup_int(dev, true); setup_int(dev, true);
return 0; return 0;
} }
int ec11_init_interrupt(struct device *dev) int ec11_init_interrupt(struct device *dev) {
{ struct ec11_data *drv_data = dev->driver_data;
struct ec11_data *drv_data = dev->driver_data; const struct ec11_config *drv_cfg = dev->config_info;
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, gpio_init_callback(&drv_data->a_gpio_cb, ec11_a_gpio_callback, BIT(drv_cfg->a_pin));
ec11_a_gpio_callback,
BIT(drv_cfg->a_pin));
if (gpio_add_callback(drv_data->a, &drv_data->a_gpio_cb) < 0) { if (gpio_add_callback(drv_data->a, &drv_data->a_gpio_cb) < 0) {
LOG_DBG("Failed to set A callback!"); LOG_DBG("Failed to set A callback!");
return -EIO; return -EIO;
} }
gpio_init_callback(&drv_data->b_gpio_cb, gpio_init_callback(&drv_data->b_gpio_cb, ec11_b_gpio_callback, BIT(drv_cfg->b_pin));
ec11_b_gpio_callback,
BIT(drv_cfg->b_pin));
if (gpio_add_callback(drv_data->b, &drv_data->b_gpio_cb) < 0) { if (gpio_add_callback(drv_data->b, &drv_data->b_gpio_cb) < 0) {
LOG_DBG("Failed to set B callback!"); LOG_DBG("Failed to set B callback!");
return -EIO; return -EIO;
} }
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD) #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, k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_EC11_THREAD_STACK_SIZE,
CONFIG_EC11_THREAD_STACK_SIZE, (k_thread_entry_t)ec11_thread, dev, 0, NULL,
(k_thread_entry_t)ec11_thread, dev, K_PRIO_COOP(CONFIG_EC11_THREAD_PRIORITY), 0, K_NO_WAIT);
0, NULL, K_PRIO_COOP(CONFIG_EC11_THREAD_PRIORITY),
0, K_NO_WAIT);
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD) #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 #endif
return 0; return 0;
} }

349
app/drivers/zephyr/kscan_gpio_direct.c

@ -15,248 +15,215 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) #if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
struct kscan_gpio_item_config struct kscan_gpio_item_config {
{ char *label;
char *label; gpio_pin_t pin;
gpio_pin_t pin; gpio_flags_t flags;
gpio_flags_t flags;
}; };
union work_reference { union work_reference {
struct k_delayed_work delayed; struct k_delayed_work delayed;
struct k_work direct; struct k_work direct;
}; };
struct kscan_gpio_config struct kscan_gpio_config {
{ u8_t num_of_inputs;
u8_t num_of_inputs; u8_t debounce_period;
u8_t debounce_period; struct kscan_gpio_item_config inputs[];
struct kscan_gpio_item_config inputs[];
}; };
struct kscan_gpio_data struct kscan_gpio_data {
{
#if defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) #if defined(CONFIG_ZMK_KSCAN_GPIO_POLLING)
struct k_timer poll_timer; struct k_timer poll_timer;
#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */ #endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
kscan_callback_t callback; kscan_callback_t callback;
union work_reference work; union work_reference work;
struct device *dev; struct device *dev;
u32_t pin_state; u32_t pin_state;
struct device *inputs[]; struct device *inputs[];
}; };
static struct device **kscan_gpio_input_devices(struct device *dev) static struct device **kscan_gpio_input_devices(struct device *dev) {
{ struct kscan_gpio_data *data = dev->driver_data;
struct kscan_gpio_data *data = dev->driver_data; return data->inputs;
return data->inputs;
} }
static const struct kscan_gpio_item_config *kscan_gpio_input_configs(struct device *dev) static const struct kscan_gpio_item_config *kscan_gpio_input_configs(struct device *dev) {
{ const struct kscan_gpio_config *cfg = dev->config_info;
const struct kscan_gpio_config *cfg = dev->config_info; return cfg->inputs;
return cfg->inputs;
} }
#if !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) #if !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING)
struct kscan_gpio_irq_callback struct kscan_gpio_irq_callback {
{ union work_reference *work;
union work_reference *work; u8_t debounce_period;
u8_t debounce_period; struct gpio_callback callback;
struct gpio_callback callback;
}; };
static int kscan_gpio_config_interrupts(struct device *dev, gpio_flags_t flags) static int kscan_gpio_config_interrupts(struct device *dev, gpio_flags_t flags) {
{ const struct kscan_gpio_config *cfg = dev->config_info;
const struct kscan_gpio_config *cfg = dev->config_info; struct device **devices = kscan_gpio_input_devices(dev);
struct device **devices = kscan_gpio_input_devices(dev); const struct kscan_gpio_item_config *configs = kscan_gpio_input_configs(dev);
const struct kscan_gpio_item_config *configs = kscan_gpio_input_configs(dev);
for (int i = 0; i < cfg->num_of_inputs; i++) for (int i = 0; i < cfg->num_of_inputs; i++) {
{ struct device *dev = devices[i];
struct device *dev = devices[i]; const struct kscan_gpio_item_config *cfg = &configs[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) if (err) {
{ LOG_ERR("Unable to enable matrix GPIO interrupt");
LOG_ERR("Unable to enable matrix GPIO interrupt"); return err;
return err; }
} }
}
return 0; return 0;
} }
static int kscan_gpio_direct_enable(struct device *dev) static int kscan_gpio_direct_enable(struct device *dev) {
{ return kscan_gpio_config_interrupts(dev, GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH);
return kscan_gpio_config_interrupts(dev,
GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH);
} }
static int kscan_gpio_direct_disable(struct device *dev) static int kscan_gpio_direct_disable(struct device *dev) {
{ return kscan_gpio_config_interrupts(dev, GPIO_INT_DISABLE);
return kscan_gpio_config_interrupts(dev,
GPIO_INT_DISABLE);
} }
static void kscan_gpio_irq_callback_handler(struct device *dev, static void kscan_gpio_irq_callback_handler(struct device *dev, struct gpio_callback *cb,
struct gpio_callback *cb, gpio_port_pins_t pin) gpio_port_pins_t pin) {
{ struct kscan_gpio_irq_callback *data =
struct kscan_gpio_irq_callback *data = CONTAINER_OF(cb, struct kscan_gpio_irq_callback, callback);
CONTAINER_OF(cb, struct kscan_gpio_irq_callback, callback);
if (data->debounce_period > 0) {
if (data->debounce_period > 0) { k_delayed_work_cancel(&data->work->delayed);
k_delayed_work_cancel(&data->work->delayed); k_delayed_work_submit(&data->work->delayed, K_MSEC(data->debounce_period));
k_delayed_work_submit(&data->work->delayed, K_MSEC(data->debounce_period)); } else {
} else { k_work_submit(&data->work->direct);
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) static void kscan_gpio_timer_handler(struct k_timer *timer) {
{ struct kscan_gpio_data *data = CONTAINER_OF(timer, struct kscan_gpio_data, poll_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) static int kscan_gpio_direct_enable(struct device *dev) {
{ struct kscan_gpio_data *data = dev->driver_data;
struct kscan_gpio_data *data = dev->driver_data; k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10));
k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); return 0;
return 0;
} }
static int kscan_gpio_direct_disable(struct device *dev) static int kscan_gpio_direct_disable(struct device *dev) {
{ struct kscan_gpio_data *data = dev->driver_data;
struct kscan_gpio_data *data = dev->driver_data; k_timer_stop(&data->poll_timer);
k_timer_stop(&data->poll_timer); return 0;
return 0;
} }
#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */ #endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */
static int kscan_gpio_direct_configure(struct device *dev, kscan_callback_t callback) static int kscan_gpio_direct_configure(struct device *dev, kscan_callback_t callback) {
{ struct kscan_gpio_data *data = dev->driver_data;
struct kscan_gpio_data *data = dev->driver_data; if (!callback) {
if (!callback) return -EINVAL;
{ }
return -EINVAL; data->callback = callback;
} return 0;
data->callback = callback;
return 0;
} }
static int kscan_gpio_read(struct device *dev) static int kscan_gpio_read(struct device *dev) {
{ struct kscan_gpio_data *data = dev->driver_data;
struct kscan_gpio_data *data = dev->driver_data; const struct kscan_gpio_config *cfg = dev->config_info;
const struct kscan_gpio_config *cfg = dev->config_info; u32_t read_state = data->pin_state;
u32_t read_state = data->pin_state; for (int i = 0; i < cfg->num_of_inputs; i++) {
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];
struct device *in_dev = kscan_gpio_input_devices(dev)[i]; WRITE_BIT(read_state, i, gpio_pin_get(in_dev, in_cfg->pin) > 0);
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;
for (int i = 0; i < cfg->num_of_inputs; i++) bool pressed = BIT(i) & read_state;
{ if (pressed != prev_pressed) {
bool prev_pressed = BIT(i) & data->pin_state; LOG_DBG("Sending event at %d,%d state %s", 0, i, (pressed ? "on" : "off"));
bool pressed = BIT(i) & read_state; WRITE_BIT(data->pin_state, i, pressed);
if (pressed != prev_pressed) data->callback(dev, 0, i, pressed);
{ }
LOG_DBG("Sending event at %d,%d state %s", }
0, i, (pressed ? "on" : "off")); return 0;
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) static void kscan_gpio_work_handler(struct k_work *work) {
{ struct kscan_gpio_data *data = CONTAINER_OF(work, struct kscan_gpio_data, work);
struct kscan_gpio_data *data = kscan_gpio_read(data->dev);
CONTAINER_OF(work, struct kscan_gpio_data, work);
kscan_gpio_read(data->dev);
} }
static const struct kscan_driver_api gpio_driver_api = { static const struct kscan_driver_api gpio_driver_api = {
.config = kscan_gpio_direct_configure, .config = kscan_gpio_direct_configure,
.enable_callback = kscan_gpio_direct_enable, .enable_callback = kscan_gpio_direct_enable,
.disable_callback = kscan_gpio_direct_disable, .disable_callback = kscan_gpio_direct_disable,
}; };
#define KSCAN_DIRECT_INPUT_ITEM(i,n) \ #define KSCAN_DIRECT_INPUT_ITEM(i, n) \
{ \ { \
.label = DT_INST_GPIO_LABEL_BY_IDX(n, input_gpios, i), \ .label = DT_INST_GPIO_LABEL_BY_IDX(n, input_gpios, i), \
.pin = DT_INST_GPIO_PIN_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), \ .flags = DT_INST_GPIO_FLAGS_BY_IDX(n, input_gpios, i), \
}, },
#define INST_INPUT_LEN(n) DT_INST_PROP_LEN(n, input_gpios) #define INST_INPUT_LEN(n) DT_INST_PROP_LEN(n, input_gpios)
#define GPIO_INST_INIT(n) \ #define GPIO_INST_INIT(n) \
COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, (static struct kscan_gpio_irq_callback \ COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, \
irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \ (static struct kscan_gpio_irq_callback irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \
static struct kscan_gpio_data kscan_gpio_data_##n = { \ static struct kscan_gpio_data kscan_gpio_data_##n = { \
.inputs = { [INST_INPUT_LEN(n)-1] = NULL } \ .inputs = {[INST_INPUT_LEN(n) - 1] = NULL}}; \
}; \ static int kscan_gpio_init_##n(struct device *dev) { \
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; \
struct kscan_gpio_data *data = dev->driver_data; \ int err; \
const struct kscan_gpio_config *cfg = dev->config_info; \ struct device **input_devices = kscan_gpio_input_devices(dev); \
int err; \ for (int i = 0; i < cfg->num_of_inputs; i++) { \
struct device **input_devices = kscan_gpio_input_devices(dev); \ const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i]; \
for (int i = 0; i < cfg->num_of_inputs; i++) \ input_devices[i] = device_get_binding(in_cfg->label); \
{ \ if (!input_devices[i]) { \
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs(dev)[i]; \ LOG_ERR("Unable to find input GPIO device"); \
input_devices[i] = device_get_binding(in_cfg->label); \ return -EINVAL; \
if (!input_devices[i]) \ } \
{ \ err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
LOG_ERR("Unable to find input GPIO device"); \ if (err) { \
return -EINVAL; \ LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
} \ return err; \
err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \ } \
if (err) \ COND_CODE_0( \
{ \ CONFIG_ZMK_KSCAN_GPIO_POLLING, \
LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \ (irq_callbacks_##n[i].work = &data->work; \
return err; \ irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \
} \ gpio_init_callback(&irq_callbacks_##n[i].callback, \
COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, \ kscan_gpio_irq_callback_handler, BIT(in_cfg->pin)); \
( \ err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
irq_callbacks_##n[i].work = &data->work; \ if (err) { \
irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \ LOG_ERR("Error adding the callback to the column device"); \
gpio_init_callback(&irq_callbacks_##n[i].callback, kscan_gpio_irq_callback_handler, BIT(in_cfg->pin)); \ return err; \
err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \ }), \
if (err) \ ()) \
{ \ } \
LOG_ERR("Error adding the callback to the column device"); \ data->dev = dev; \
return err; \ 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); \
data->dev = dev; \ } else { \
COND_CODE_1(CONFIG_ZMK_KSCAN_GPIO_POLLING, (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ( )) \ k_work_init(&data->work.direct, kscan_gpio_work_handler); \
if (cfg->debounce_period > 0) { \ } \
k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \ return 0; \
} else { \ } \
k_work_init(&data->work.direct, kscan_gpio_work_handler); \ static const struct kscan_gpio_config kscan_gpio_config_##n = { \
} \ .inputs = {UTIL_LISTIFY(INST_INPUT_LEN(n), KSCAN_DIRECT_INPUT_ITEM, n)}, \
return 0; \ .num_of_inputs = INST_INPUT_LEN(n), \
} \ .debounce_period = DT_INST_PROP(n, debounce_period)}; \
static const struct kscan_gpio_config kscan_gpio_config_##n = { \ DEVICE_AND_API_INIT(kscan_gpio_##n, DT_INST_LABEL(n), kscan_gpio_init_##n, \
.inputs = { UTIL_LISTIFY(INST_INPUT_LEN(n), KSCAN_DIRECT_INPUT_ITEM, n) }, \ &kscan_gpio_data_##n, &kscan_gpio_config_##n, POST_KERNEL, \
.num_of_inputs = INST_INPUT_LEN(n), \ CONFIG_ZMK_KSCAN_INIT_PRIORITY, &gpio_driver_api);
.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) DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT)

474
app/drivers/zephyr/kscan_gpio_matrix.c

@ -15,266 +15,248 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) #if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
struct kscan_gpio_item_config struct kscan_gpio_item_config {
{ char *label;
char *label; gpio_pin_t pin;
gpio_pin_t pin; gpio_flags_t flags;
gpio_flags_t flags;
}; };
#define _KSCAN_GPIO_ITEM_CFG_INIT(n, prop, idx) \
#define _KSCAN_GPIO_ITEM_CFG_INIT(n, prop, idx) \ { \
{ \ .label = DT_INST_GPIO_LABEL_BY_IDX(n, prop, idx), \
.label = DT_INST_GPIO_LABEL_BY_IDX(n, prop, idx), \ .pin = DT_INST_GPIO_PIN_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), \
.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_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) #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, static int kscan_gpio_config_interrupts(struct device **devices,
const struct kscan_gpio_item_config *configs, const struct kscan_gpio_item_config *configs, size_t len,
size_t len, gpio_flags_t flags) gpio_flags_t flags) {
{ for (int i = 0; i < len; i++) {
for (int i = 0; i < len; i++) struct device *dev = devices[i];
{ const struct kscan_gpio_item_config *cfg = &configs[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) if (err) {
{ LOG_ERR("Unable to enable matrix GPIO interrupt");
LOG_ERR("Unable to enable matrix GPIO interrupt"); return err;
return err; }
} }
}
return 0; return 0;
} }
#define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios) #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_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_OUTPUT_LEN(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))) 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) \ #define GPIO_INST_INIT(n) \
struct kscan_gpio_irq_callback_##n \ struct kscan_gpio_irq_callback_##n { \
{ \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \ struct gpio_callback callback; \
struct gpio_callback callback; \ }; \
}; \ static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \
static struct kscan_gpio_irq_callback_##n \ struct kscan_gpio_config_##n { \
irq_callbacks_##n[INST_INPUT_LEN(n)]; \ struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \
struct kscan_gpio_config_##n \ struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \
{ \ }; \
struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \ struct kscan_gpio_data_##n { \
struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \ kscan_callback_t callback; \
}; \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \
struct kscan_gpio_data_##n \ bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
{ \ struct device *rows[INST_MATRIX_ROWS(n)]; \
kscan_callback_t callback; \ struct device *cols[INST_MATRIX_COLS(n)]; \
struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \ struct device *dev; \
bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ }; \
struct device *rows[INST_MATRIX_ROWS(n)]; \ static struct device **kscan_gpio_input_devices_##n(struct device *dev) { \
struct device *cols[INST_MATRIX_COLS(n)]; \ struct kscan_gpio_data_##n *data = dev->driver_data; \
struct device *dev; \ return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->cols), \
}; \ (data->rows))); \
static struct device **kscan_gpio_input_devices_##n(struct device *dev) \ } \
{ \ static const struct kscan_gpio_item_config *kscan_gpio_input_configs_##n(struct device *dev) { \
struct kscan_gpio_data_##n *data = dev->driver_data; \ const struct kscan_gpio_config_##n *cfg = dev->config_info; \
return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->cols), (data->rows))); \ return (( \
} \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->cols), (cfg->rows)))); \
static const struct kscan_gpio_item_config *kscan_gpio_input_configs_##n(struct device *dev) \ } \
{ \ static struct device **kscan_gpio_output_devices_##n(struct device *dev) { \
const struct kscan_gpio_config_##n *cfg = dev->config_info; \ struct kscan_gpio_data_##n *data = dev->driver_data; \
return ((COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->cols), (cfg->rows)))); \ return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->rows), \
} \ (data->cols))); \
static struct device **kscan_gpio_output_devices_##n(struct device *dev) \ } \
{ \ static const struct kscan_gpio_item_config *kscan_gpio_output_configs_##n( \
struct kscan_gpio_data_##n *data = dev->driver_data; \ struct device *dev) { \
return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (data->rows), (data->cols))); \ const struct kscan_gpio_config_##n *cfg = dev->config_info; \
} \ return ( \
static const struct kscan_gpio_item_config *kscan_gpio_output_configs_##n(struct device *dev) \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \
{ \ } \
const struct kscan_gpio_config_##n *cfg = dev->config_info; \ static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \
return (COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \ return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \
} \ kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
static int kscan_gpio_enable_interrupts_##n(struct device *dev) \ GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \
{ \ } \
return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \
GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \
} \ kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \
static int kscan_gpio_disable_interrupts_##n(struct device *dev) \ GPIO_INT_DISABLE); \
{ \ } \
return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \
GPIO_INT_DISABLE); \ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \
} \ struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \
static void kscan_gpio_set_output_state_##n(struct device *dev, int value) \ const struct kscan_gpio_item_config *cfg = &kscan_gpio_output_configs_##n(dev)[i]; \
{ \ gpio_pin_set(in_dev, cfg->pin, value); \
for (int i = 0; i < INST_OUTPUT_LEN(n); i++) \ } \
{ \ } \
struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \ static void kscan_gpio_set_matrix_state_##n( \
const struct kscan_gpio_item_config *cfg = &kscan_gpio_output_configs_##n(dev)[i]; \ bool state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)], u32_t input_index, \
gpio_pin_set(in_dev, cfg->pin, value); \ u32_t output_index, bool value) { \
} \ state[COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (output_index), \
} \ (input_index))] \
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) \ [COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (input_index), \
{ \ (output_index))] = 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) { \
static int kscan_gpio_read_##n(struct device *dev) \ bool submit_follow_up_read = false; \
{ \ struct kscan_gpio_data_##n *data = dev->driver_data; \
bool submit_follow_up_read = false; \ static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \
struct kscan_gpio_data_##n *data = dev->driver_data; \ /* Disable our interrupts temporarily while we scan, to avoid */ \
static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ /* re-entry while we iterate columns and set them active one by one */ \
/* Disable our interrupts temporarily while we scan, to avoid */ \ /* to get pressed state for each matrix cell. */ \
/* re-entry while we iterate columns and set them active one by one */ \ kscan_gpio_disable_interrupts_##n(dev); \
/* to get pressed state for each matrix cell. */ \ kscan_gpio_set_output_state_##n(dev, 0); \
kscan_gpio_disable_interrupts_##n(dev); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
kscan_gpio_set_output_state_##n(dev, 0); \ struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \
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]; \
{ \ gpio_pin_set(out_dev, out_cfg->pin, 1); \
struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \ for (int i = 0; i < INST_INPUT_LEN(n); i++) { \
const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \ struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \
gpio_pin_set(out_dev, out_cfg->pin, 1); \ const struct kscan_gpio_item_config *in_cfg = \
for (int i = 0; i < INST_INPUT_LEN(n); i++) \ &kscan_gpio_input_configs_##n(dev)[i]; \
{ \ kscan_gpio_set_matrix_state_##n(read_state, i, o, \
struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \ gpio_pin_get(in_dev, in_cfg->pin) > 0); \
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); \
} \ } \
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 */ \
/* Set all our outputs as active again, then re-enable interrupts, */ \ kscan_gpio_set_output_state_##n(dev, 1); \
/* so we can trigger interrupts again for future press/release */ \ kscan_gpio_enable_interrupts_##n(dev); \
kscan_gpio_set_output_state_##n(dev, 1); \ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \
kscan_gpio_enable_interrupts_##n(dev); \ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \
for (int r = 0; r < INST_MATRIX_ROWS(n); r++) \ bool pressed = read_state[r][c]; \
{ \ /* Follow up reads needed because further interrupts won't fire on already tripped \
for (int c = 0; c < INST_MATRIX_COLS(n); c++) \ * input GPIO pins */ \
{ \ submit_follow_up_read = (submit_follow_up_read || pressed); \
bool pressed = read_state[r][c]; \ if (pressed != data->matrix_state[r][c]) { \
/* Follow up reads needed because further interrupts won't fire on already tripped input GPIO pins */ \ LOG_DBG("Sending event at %d,%d state %s", r, c, (pressed ? "on" : "off")); \
submit_follow_up_read = (submit_follow_up_read || pressed); \ data->matrix_state[r][c] = pressed; \
if (pressed != data->matrix_state[r][c]) \ data->callback(dev, r, c, pressed); \
{ \ } \
LOG_DBG("Sending event at %d,%d state %s", \ } \
r, c, (pressed ? "on" : "off")); \ } \
data->matrix_state[r][c] = pressed; \ if (submit_follow_up_read) { \
data->callback(dev, r, c, pressed); \ 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)); \
} \ })) \
if (submit_follow_up_read) { \ } \
COND_CODE_0(DT_INST_PROP(n, debounce_period), \ return 0; \
({ k_work_submit(&data->work); }), \ } \
({ \ static void kscan_gpio_work_handler_##n(struct k_work *work) { \
k_delayed_work_cancel(&data->work); \ struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \
k_delayed_work_submit(&data->work, K_MSEC(5)); })) \ kscan_gpio_read_##n(data->dev); \
} \ } \
return 0; \ static void kscan_gpio_irq_callback_handler_##n(struct device *dev, struct gpio_callback *cb, \
} \ gpio_port_pins_t pin) { \
static void kscan_gpio_work_handler_##n(struct k_work *work) \ struct kscan_gpio_irq_callback_##n *data = \
{ \ CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \
struct kscan_gpio_data_##n *data = \ COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \
CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \ k_delayed_work_cancel(data->work); \
kscan_gpio_read_##n(data->dev); \ k_delayed_work_submit(data->work, \
} \ K_MSEC(DT_INST_PROP(n, debounce_period))); \
static void kscan_gpio_irq_callback_handler_##n(struct device *dev, \ })) \
struct gpio_callback *cb, gpio_port_pins_t pin) \ } \
{ \ static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
struct kscan_gpio_irq_callback_##n *data = \ .rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \
CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \ static int kscan_gpio_configure_##n(struct device *dev, kscan_callback_t callback) { \
COND_CODE_0(DT_INST_PROP(n, debounce_period), \ struct kscan_gpio_data_##n *data = dev->driver_data; \
({ k_work_submit(data->work); }), \ if (!callback) { \
({ \ return -EINVAL; \
k_delayed_work_cancel(data->work); \ } \
k_delayed_work_submit(data->work, K_MSEC(DT_INST_PROP(n, debounce_period))); })) \ data->callback = callback; \
} \ return 0; \
static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \ }; \
.rows = { [INST_MATRIX_ROWS(n)-1] = NULL}, \ static int kscan_gpio_enable_##n(struct device *dev) { \
.cols = { [INST_MATRIX_COLS(n)-1] = NULL }\ int err = kscan_gpio_enable_interrupts_##n(dev); \
}; \ if (err) { \
static int kscan_gpio_configure_##n(struct device *dev, kscan_callback_t callback) \ return err; \
{ \ } \
struct kscan_gpio_data_##n *data = dev->driver_data; \ return kscan_gpio_read_##n(dev); \
if (!callback) \ }; \
{ \ static int kscan_gpio_init_##n(struct device *dev) { \
return -EINVAL; \ struct kscan_gpio_data_##n *data = dev->driver_data; \
} \ int err; \
data->callback = callback; \ struct device **input_devices = kscan_gpio_input_devices_##n(dev); \
return 0; \ 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]; \
static int kscan_gpio_enable_##n(struct device *dev) \ input_devices[i] = device_get_binding(in_cfg->label); \
{ \ if (!input_devices[i]) { \
int err = kscan_gpio_enable_interrupts_##n(dev); \ LOG_ERR("Unable to find input GPIO device"); \
if (err) { return err; } \ return -EINVAL; \
return kscan_gpio_read_##n(dev); \ } \
}; \ err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
static int kscan_gpio_init_##n(struct device *dev) \ if (err) { \
{ \ LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
struct kscan_gpio_data_##n *data = dev->driver_data; \ return err; \
int err; \ } \
struct device **input_devices = kscan_gpio_input_devices_##n(dev); \ irq_callbacks_##n[i].work = &data->work; \
for (int i = 0; i < INST_INPUT_LEN(n); i++) \ gpio_init_callback(&irq_callbacks_##n[i].callback, \
{ \ kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs_##n(dev)[i]; \ err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \
input_devices[i] = device_get_binding(in_cfg->label); \ if (err) { \
if (!input_devices[i]) \ LOG_ERR("Error adding the callback to the column device"); \
{ \ return err; \
LOG_ERR("Unable to find input GPIO device"); \ } \
return -EINVAL; \ } \
} \ struct device **output_devices = kscan_gpio_output_devices_##n(dev); \
err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \
if (err) \ const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
{ \ output_devices[o] = device_get_binding(out_cfg->label); \
LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \ if (!output_devices[o]) { \
return err; \ LOG_ERR("Unable to find output GPIO device"); \
} \ return -EINVAL; \
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_pin_configure(output_devices[o], out_cfg->pin, \
err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \ GPIO_OUTPUT_ACTIVE | out_cfg->flags); \
if (err) \ if (err) { \
{ \ LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, \
LOG_ERR("Error adding the callback to the column device"); \ out_cfg->label); \
return err; \ return err; \
} \ } \
} \ } \
struct device **output_devices = kscan_gpio_output_devices_##n(dev); \ data->dev = dev; \
for (int o = 0; o < INST_OUTPUT_LEN(n); o++) \ (COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \
{ \ &data->work, kscan_gpio_work_handler_##n); \
const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \ return 0; \
output_devices[o] = device_get_binding(out_cfg->label); \ } \
if (!output_devices[o]) \ static const struct kscan_driver_api gpio_driver_api_##n = { \
{ \ .config = kscan_gpio_configure_##n, \
LOG_ERR("Unable to find output GPIO device"); \ .enable_callback = kscan_gpio_enable_##n, \
return -EINVAL; \ .disable_callback = kscan_gpio_disable_interrupts_##n, \
} \ }; \
err = gpio_pin_configure(output_devices[o], out_cfg->pin, GPIO_OUTPUT_ACTIVE | out_cfg->flags); \ static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \
if (err) \ .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)}, \
LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, out_cfg->label); \ }; \
return err; \ 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);
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) DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT)

69
app/include/drivers/behavior.h

@ -19,19 +19,20 @@
* (Internal use only.) * (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_keymap_binding_callback_t)(struct device *dev, u32_t position, u32_t param1,
typedef int (*behavior_sensor_keymap_binding_callback_t)(struct device *dev, struct device *sensor, u32_t param1, u32_t param2); 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 { __subsystem struct behavior_driver_api {
behavior_keymap_binding_callback_t binding_pressed; behavior_keymap_binding_callback_t binding_pressed;
behavior_keymap_binding_callback_t binding_released; behavior_keymap_binding_callback_t binding_released;
behavior_sensor_keymap_binding_callback_t sensor_binding_triggered; behavior_sensor_keymap_binding_callback_t sensor_binding_triggered;
}; };
/** /**
* @endcond * @endcond
*/ */
/** /**
* @brief Handle the keymap binding being pressed * @brief Handle the keymap binding being pressed
* @param dev Pointer to the device structure for the driver instance. * @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 0 If successful.
* @retval Negative errno code if failure. * @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) 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 *api = (const struct behavior_driver_api *)dev->driver_api;
(const struct behavior_driver_api *)dev->driver_api;
if (api->binding_pressed == NULL) { if (api->binding_pressed == NULL) {
return -ENOTSUP; 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 0 If successful.
* @retval Negative errno code if failure. * @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) 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 *api = (const struct behavior_driver_api *)dev->driver_api;
(const struct behavior_driver_api *)dev->driver_api;
if (api->binding_released == NULL) { if (api->binding_released == NULL) {
return -ENOTSUP; 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 0 If successful.
* @retval Negative errno code if failure. * @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) static inline int z_impl_behavior_sensor_keymap_binding_triggered(struct device *dev,
{ struct device *sensor,
const struct behavior_driver_api *api = u32_t param1, u32_t param2) {
(const struct behavior_driver_api *)dev->driver_api; const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
if (api->sensor_binding_triggered == NULL) { if (api->sensor_binding_triggered == NULL) {
return -ENOTSUP; return -ENOTSUP;
} }
return api->sensor_binding_triggered(dev, sensor, param1, param2); return api->sensor_binding_triggered(dev, sensor, param1, param2);
} }
/** /**
* @} * @}
*/ */

16
app/include/dt-bindings/zmk/bt.h

@ -4,10 +4,10 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#define BT_CLR_CMD 0 #define BT_CLR_CMD 0
#define BT_NXT_CMD 1 #define BT_NXT_CMD 1
#define BT_PRV_CMD 2 #define BT_PRV_CMD 2
#define BT_SEL_CMD 3 #define BT_SEL_CMD 3
// #define BT_FULL_RESET_CMD 4 // #define BT_FULL_RESET_CMD 4
/* /*
@ -15,7 +15,7 @@ Note: Some future commands will include additional parameters, so we
defines these aliases up front. defines these aliases up front.
*/ */
#define BT_CLR BT_CLR_CMD 0 #define BT_CLR BT_CLR_CMD 0
#define BT_NXT BT_NXT_CMD 0 #define BT_NXT BT_NXT_CMD 0
#define BT_PRV BT_PRV_CMD 0 #define BT_PRV BT_PRV_CMD 0
#define BT_SEL BT_SEL_CMD #define BT_SEL BT_SEL_CMD

6
app/include/dt-bindings/zmk/keys.h

@ -55,7 +55,7 @@
#define QUOT 0x34 #define QUOT 0x34
#define GRAV 0x35 #define GRAV 0x35
#define CMMA 0x36 #define CMMA 0x36
#define DOT 0x37 #define DOT 0x37
#define FSLH 0x38 #define FSLH 0x38
#define CLCK 0x39 #define CLCK 0x39
#define F1 0x3A #define F1 0x3A
@ -77,8 +77,8 @@
#define INS 0x49 #define INS 0x49
#define HOME 0x4A #define HOME 0x4A
#define PGUP 0x4B #define PGUP 0x4B
#define DEL 0x4C #define DEL 0x4C
#define END 0x4D #define END 0x4D
#define PGDN 0x4E #define PGDN 0x4E
#define RARW 0x4F #define RARW 0x4F
#define LARW 0x50 #define LARW 0x50

9
app/include/dt-bindings/zmk/reset.h

@ -4,9 +4,10 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#define RST_WARM 0x00 #define RST_WARM 0x00
#define RST_COLD 0x01 #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

75
app/include/zmk/event-manager.h

@ -10,13 +10,12 @@
#include <kernel.h> #include <kernel.h>
#include <zephyr/types.h> #include <zephyr/types.h>
struct zmk_event_type struct zmk_event_type {
{
const char *name; const char *name;
}; };
struct zmk_event_header { struct zmk_event_header {
const struct zmk_event_type* event; const struct zmk_event_type *event;
u8_t last_listener_index; u8_t last_listener_index;
}; };
@ -24,8 +23,7 @@ struct zmk_event_header {
#define ZMK_EV_EVENT_CAPTURED 2 #define ZMK_EV_EVENT_CAPTURED 2
typedef int (*zmk_listener_callback_t)(const struct zmk_event_header *eh); typedef int (*zmk_listener_callback_t)(const struct zmk_event_header *eh);
struct zmk_listener struct zmk_listener {
{
zmk_listener_callback_t callback; zmk_listener_callback_t callback;
}; };
@ -34,55 +32,50 @@ struct zmk_event_subscription {
const struct zmk_listener *listener; const struct zmk_listener *listener;
}; };
#define ZMK_EVENT_DECLARE(event_type) \ #define ZMK_EVENT_DECLARE(event_type) \
struct event_type* new_##event_type(); \ struct event_type *new_##event_type(); \
bool is_##event_type(const struct zmk_event_header *eh); \ bool is_##event_type(const struct zmk_event_header *eh); \
struct event_type* cast_##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; extern const struct zmk_event_type zmk_event_##event_type;
#define ZMK_EVENT_IMPL(event_type) \ #define ZMK_EVENT_IMPL(event_type) \
const struct zmk_event_type zmk_event_##event_type = { \ const struct zmk_event_type zmk_event_##event_type = {.name = STRINGIFY(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; \
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* new_##event_type() { \ struct event_type *ev = (struct event_type *)k_malloc(sizeof(struct event_type)); \
struct event_type* ev = (struct event_type *) k_malloc(sizeof(struct event_type)); \ ev->header.event = &zmk_event_##event_type; \
ev->header.event = &zmk_event_##event_type; \ return ev; \
return ev; \ }; \
}; \ bool is_##event_type(const struct zmk_event_header *eh) { \
bool is_##event_type(const struct zmk_event_header *eh) { \ return eh->event == &zmk_event_##event_type; \
return eh->event == &zmk_event_##event_type; \ }; \
}; \ struct event_type *cast_##event_type(const struct zmk_event_header *eh) { \
struct event_type* cast_##event_type(const struct zmk_event_header *eh) {\ return (struct event_type *)eh; \
return (struct event_type*)eh; \
}; };
#define ZMK_LISTENER(mod, cb) const struct zmk_listener zmk_listener_##mod = {.callback = cb};
#define ZMK_LISTENER(mod, cb) \ #define ZMK_SUBSCRIPTION(mod, ev_type) \
const struct zmk_listener zmk_listener_##mod = { \ const Z_DECL_ALIGN(struct zmk_event_subscription) \
.callback = cb \ _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_SUBSCRIPTION(mod, ev_type) \ #define ZMK_EVENT_RAISE(ev) zmk_event_manager_raise((struct zmk_event_header *)ev);
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_AFTER(ev, mod) \ #define ZMK_EVENT_RAISE_AFTER(ev, mod) \
zmk_event_manager_raise_after((struct zmk_event_header *)ev, &zmk_listener_##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); zmk_event_manager_raise_at((struct zmk_event_header *)ev, &zmk_listener_##mod);
#define ZMK_EVENT_RELEASE(ev) \ #define ZMK_EVENT_RELEASE(ev) zmk_event_manager_release((struct zmk_event_header *)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(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_raise_at(struct zmk_event_header *event, const struct zmk_listener *listener);
int zmk_event_manager_release(struct zmk_event_header *event); int zmk_event_manager_release(struct zmk_event_header *event);

1
app/include/zmk/events/ble-active-profile-changed.h

@ -12,7 +12,6 @@
#include <zmk/ble/profile.h> #include <zmk/ble/profile.h>
struct ble_active_profile_changed { struct ble_active_profile_changed {
struct zmk_event_header header; struct zmk_event_header header;
u8_t index; u8_t index;

6
app/include/zmk/events/keycode-state-changed.h

@ -18,9 +18,9 @@ struct keycode_state_changed {
ZMK_EVENT_DECLARE(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) 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(); struct keycode_state_changed *ev = new_keycode_state_changed();
ev->usage_page = usage_page; ev->usage_page = usage_page;
ev->keycode = keycode; ev->keycode = keycode;
ev->state = state; ev->state = state;

6
app/include/zmk/events/modifiers-state-changed.h

@ -18,9 +18,9 @@ struct modifiers_state_changed {
ZMK_EVENT_DECLARE(modifiers_state_changed); ZMK_EVENT_DECLARE(modifiers_state_changed);
inline struct modifiers_state_changed* create_modifiers_state_changed(zmk_mod_flags modifiers, bool state) inline struct modifiers_state_changed *create_modifiers_state_changed(zmk_mod_flags modifiers,
{ bool state) {
struct modifiers_state_changed* ev = new_modifiers_state_changed(); struct modifiers_state_changed *ev = new_modifiers_state_changed();
ev->modifiers = modifiers; ev->modifiers = modifiers;
ev->state = state; ev->state = state;

12
app/include/zmk/hid.h

@ -140,25 +140,21 @@ static const u8_t zmk_hid_report_desc[] = {
// u8_t keys[6]; // u8_t keys[6];
// } __packed; // } __packed;
struct zmk_hid_keypad_report_body struct zmk_hid_keypad_report_body {
{
zmk_mod_flags modifiers; zmk_mod_flags modifiers;
u8_t keys[13]; u8_t keys[13];
} __packed; } __packed;
struct zmk_hid_keypad_report struct zmk_hid_keypad_report {
{
u8_t report_id; u8_t report_id;
struct zmk_hid_keypad_report_body body; struct zmk_hid_keypad_report_body body;
} __packed; } __packed;
struct zmk_hid_consumer_report_body struct zmk_hid_consumer_report_body {
{
u8_t keys[6]; u8_t keys[6];
} __packed; } __packed;
struct zmk_hid_consumer_report struct zmk_hid_consumer_report {
{
u8_t report_id; u8_t report_id;
struct zmk_hid_consumer_report_body body; struct zmk_hid_consumer_report_body body;
} __packed; } __packed;

3
app/include/zmk/keys.h

@ -14,8 +14,7 @@ typedef u8_t zmk_action;
typedef u8_t zmk_mod; typedef u8_t zmk_mod;
typedef u8_t zmk_mod_flags; typedef u8_t zmk_mod_flags;
struct zmk_key_event struct zmk_key_event {
{
u32_t column; u32_t column;
u32_t row; u32_t row;
zmk_key key; zmk_key key;

18
app/include/zmk/matrix.h

@ -15,20 +15,20 @@
#define ZMK_KEYMAP_TRANSFORM_NODE DT_CHOSEN(zmk_matrix_transform) #define ZMK_KEYMAP_TRANSFORM_NODE DT_CHOSEN(zmk_matrix_transform)
#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_TRANSFORM_NODE, map) #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_ROWS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE, rows)
#define ZMK_MATRIX_COLS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE,columns) #define ZMK_MATRIX_COLS DT_PROP(ZMK_KEYMAP_TRANSFORM_NODE, columns)
#else /* DT_HAS_CHOSEN(zmk_matrix_transform) */ #else /* DT_HAS_CHOSEN(zmk_matrix_transform) */
#if DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID,row_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_ROWS DT_PROP_LEN(ZMK_MATRIX_NODE_ID, row_gpios)
#define ZMK_MATRIX_COLS DT_PROP_LEN(ZMK_MATRIX_NODE_ID,col_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) #elif DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID, input_gpios)
#define ZMK_MATRIX_ROWS 1 #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 #else
#define ZMK_MATRIX_ROWS DT_PROP(ZMK_MATRIX_NODE_ID,rows) #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_COLS DT_PROP(ZMK_MATRIX_NODE_ID, columns)
#endif #endif
#define ZMK_KEYMAP_LEN (ZMK_MATRIX_COLS * ZMK_MATRIX_ROWS) #define ZMK_KEYMAP_LEN (ZMK_MATRIX_COLS * ZMK_MATRIX_ROWS)

5
app/include/zmk/split/bluetooth/uuid.h

@ -3,10 +3,9 @@
#include <bluetooth/uuid.h> #include <bluetooth/uuid.h>
#ifndef BT_UUID_NUM_OF_DIGITALS #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 #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_SERVICE_UUID ZMK_BT_SPLIT_UUID(0x00000000)
#define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001) #define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001)

23
app/src/behaviors/behavior_bt.c

@ -18,10 +18,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/ble.h> #include <zmk/ble.h>
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t command, u32_t arg) static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t command, u32_t arg) {
{ switch (command) {
switch (command)
{
case BT_CLR_CMD: case BT_CLR_CMD:
return zmk_ble_clear_bonds(); return zmk_ble_clear_bonds();
case BT_NXT_CMD: case BT_NXT_CMD:
@ -37,13 +35,10 @@ static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t c
return -ENOTSUP; return -ENOTSUP;
} }
static int behavior_bt_init(struct device *dev) static int behavior_bt_init(struct device *dev) { return 0; };
{
return 0;
};
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t command, u32_t arg) static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t command,
{ u32_t arg) {
return 0; return 0;
} }
@ -52,9 +47,5 @@ static const struct behavior_driver_api behavior_bt_driver_api = {
.binding_released = on_keymap_binding_released, .binding_released = on_keymap_binding_released,
}; };
DEVICE_AND_API_INIT(behavior_bt, DT_INST_LABEL(0), DEVICE_AND_API_INIT(behavior_bt, DT_INST_LABEL(0), behavior_bt_init, NULL, NULL, APPLICATION,
behavior_bt_init, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_bt_driver_api);
NULL,
NULL,
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_bt_driver_api);

754
app/src/behaviors/behavior_hold_tap.c

@ -29,36 +29,35 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
// increase if you have keyboard with more keys. // increase if you have keyboard with more keys.
#define ZMK_BHV_HOLD_TAP_POSITION_NOT_USED 9999 #define ZMK_BHV_HOLD_TAP_POSITION_NOT_USED 9999
enum flavor { enum flavor {
ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED = 0, ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED = 0,
ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED = 1, ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED = 1,
ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2, ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2,
}; };
struct behavior_hold_tap_behaviors { struct behavior_hold_tap_behaviors {
struct zmk_behavior_binding tap; struct zmk_behavior_binding tap;
struct zmk_behavior_binding hold; struct zmk_behavior_binding hold;
}; };
typedef k_timeout_t (*timer_func)(); typedef k_timeout_t (*timer_func)();
struct behavior_hold_tap_config { struct behavior_hold_tap_config {
timer_func tapping_term_ms; timer_func tapping_term_ms;
struct behavior_hold_tap_behaviors *behaviors; struct behavior_hold_tap_behaviors *behaviors;
enum flavor flavor; enum flavor flavor;
}; };
// this data is specific for each hold-tap // this data is specific for each hold-tap
struct active_hold_tap { struct active_hold_tap {
s32_t position; s32_t position;
u32_t param_hold; u32_t param_hold;
u32_t param_tap; u32_t param_tap;
bool is_decided; bool is_decided;
bool is_hold; bool is_hold;
const struct behavior_hold_tap_config *config; const struct behavior_hold_tap_config *config;
struct k_delayed_work work; struct k_delayed_work work;
bool work_is_cancelled; bool work_is_cancelled;
}; };
// The undecided hold tap is the hold tap that needs to be decided before // 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. // 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] = {}; const struct zmk_event_header *captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {};
static int capture_event(const struct zmk_event_header *event) static int capture_event(const struct zmk_event_header *event) {
{ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) { if (captured_events[i] == NULL) {
if (captured_events[i] == NULL) { captured_events[i] = event;
captured_events[i] = event; return 0;
return 0; }
} }
} return -ENOMEM;
return -ENOMEM;
} }
static struct position_state_changed *find_captured_keydown_event(u32_t position) static struct position_state_changed *find_captured_keydown_event(u32_t position) {
{ struct position_state_changed *last_match = NULL;
struct position_state_changed *last_match = NULL; for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) { const struct zmk_event_header *eh = captured_events[i];
const struct zmk_event_header *eh = captured_events[i]; if (eh == NULL) {
if (eh == NULL) { return last_match;
return last_match; }
} if (!is_position_state_changed(eh)) {
if (!is_position_state_changed(eh)) { continue;
continue; }
} struct position_state_changed *position_event = cast_position_state_changed(eh);
struct position_state_changed *position_event = cast_position_state_changed(eh); if (position_event->position == position && position_event->state) {
if (position_event->position == position && position_event->state) { last_match = position_event;
last_match = position_event; }
} }
} return last_match;
return last_match;
} }
const struct zmk_listener zmk_listener_behavior_hold_tap; const struct zmk_listener zmk_listener_behavior_hold_tap;
static void release_captured_events() static void release_captured_events() {
{ if (undecided_hold_tap != NULL) {
if (undecided_hold_tap != NULL) { return;
return; }
}
// We use a trick to prevent copying the captured_events array.
// We use a trick to prevent copying the captured_events array. //
// // Events for different mod-tap instances are separated by a NULL pointer.
// 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
// 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
// because to start capturing a mod-tap-key-down event must first completely // go through the events queue.
// go through the events queue. //
// // Example of this release process;
// Example of this release process; // [mt2_down, k1_down, k1_up, mt2_up, null, ...]
// [mt2_down, k1_down, k1_up, mt2_up, null, ...] // ^
// ^ // mt2_down position event isn't captured because no hold-tap is active.
// 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
// mt2_down behavior event is handled, now we have an undecided hold-tap // [null, k1_down, k1_up, mt2_up, null, ...]
// [null, k1_down, k1_up, mt2_up, null, ...] // ^
// ^ // k1_down is captured by the mt2 mod-tap
// 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
// !note that searches for find_captured_keydown_event by the mt2 behavior will stop at the first null encountered // first null encountered [mt1_down, null, k1_up, mt2_up, null, ...]
// [mt1_down, null, k1_up, mt2_up, null, ...] // ^
// ^ // k1_up event is captured by the new hold-tap:
// k1_up event is captured by the new hold-tap: // [k1_down, k1_up, null, mt2_up, null, ...]
// [k1_down, k1_up, null, mt2_up, null, ...] // ^
// ^ // mt2_up event is not captured but causes release of mt2 behavior
// mt2_up event is not captured but causes release of mt2 behavior // [k1_down, k1_up, null, null, null, ...]
// [k1_down, k1_up, null, null, null, ...] // now mt2 will start releasing it's own captured positions.
// now mt2 will start releasing it's own captured positions. for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) { const struct zmk_event_header *captured_event = captured_events[i];
const struct zmk_event_header *captured_event = captured_events[i]; if (captured_event == NULL) {
if (captured_event == NULL) { return;
return; }
} captured_events[i] = NULL;
captured_events[i] = NULL; if (undecided_hold_tap != NULL) {
if (undecided_hold_tap != NULL) { k_msleep(10);
k_msleep(10); }
} if (is_position_state_changed(captured_event)) {
if (is_position_state_changed(captured_event)) { struct position_state_changed *position_event =
struct position_state_changed *position_event = cast_position_state_changed(captured_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")); LOG_DBG("Releasing key position event for position %d %s", position_event->position,
} else { (position_event->state ? "pressed" : "released"));
struct keycode_state_changed *modifier_event = cast_keycode_state_changed(captured_event); } else {
LOG_DBG("Releasing mods changed event 0x%02X %s", modifier_event->keycode, (modifier_event->state ? "pressed" : "released")); struct keycode_state_changed *modifier_event =
} cast_keycode_state_changed(captured_event);
ZMK_EVENT_RAISE_AT(captured_event, behavior_hold_tap); 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) static struct active_hold_tap *find_hold_tap(u32_t position) {
{ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) { if (active_hold_taps[i].position == position) {
if (active_hold_taps[i].position == position) { return &active_hold_taps[i];
return &active_hold_taps[i]; }
} }
} return NULL;
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) 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++) { 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) { if (active_hold_taps[i].position != ZMK_BHV_HOLD_TAP_POSITION_NOT_USED) {
continue; continue;
} }
active_hold_taps[i].position = position; active_hold_taps[i].position = position;
active_hold_taps[i].is_decided = false; active_hold_taps[i].is_decided = false;
active_hold_taps[i].is_hold = false; active_hold_taps[i].is_hold = false;
active_hold_taps[i].config = config; active_hold_taps[i].config = config;
active_hold_taps[i].param_hold = param_hold; active_hold_taps[i].param_hold = param_hold;
active_hold_taps[i].param_tap = param_tap; active_hold_taps[i].param_tap = param_tap;
return &active_hold_taps[i]; return &active_hold_taps[i];
} }
return NULL; return NULL;
} }
static void clear_hold_tap(struct active_hold_tap *hold_tap) static void clear_hold_tap(struct active_hold_tap *hold_tap) {
{ hold_tap->position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
hold_tap->position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED; hold_tap->is_decided = false;
hold_tap->is_decided = false; hold_tap->is_hold = false;
hold_tap->is_hold = false; hold_tap->work_is_cancelled = false;
hold_tap->work_is_cancelled = false;
} }
enum decision_moment { enum decision_moment {
HT_KEY_UP = 0, HT_KEY_UP = 0,
HT_OTHER_KEY_DOWN = 1, HT_OTHER_KEY_DOWN = 1,
HT_OTHER_KEY_UP = 2, HT_OTHER_KEY_UP = 2,
HT_TIMER_EVENT = 3, HT_TIMER_EVENT = 3,
}; };
static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_moment event) static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_moment event) {
{ switch (event) {
switch (event) { case HT_KEY_UP:
case HT_KEY_UP: hold_tap->is_hold = 0;
hold_tap->is_hold = 0; hold_tap->is_decided = true;
hold_tap->is_decided = true; break;
break; case HT_OTHER_KEY_UP:
case HT_OTHER_KEY_UP: case HT_TIMER_EVENT:
case HT_TIMER_EVENT: hold_tap->is_hold = 1;
hold_tap->is_hold = 1; hold_tap->is_decided = true;
hold_tap->is_decided = true; break;
break; default:
default: return; return;
} }
} }
static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) {
{ switch (event) {
switch (event) { case HT_KEY_UP:
case HT_KEY_UP: hold_tap->is_hold = 0;
hold_tap->is_hold = 0; hold_tap->is_decided = true;
hold_tap->is_decided = true; break;
break; case HT_TIMER_EVENT:
case HT_TIMER_EVENT: hold_tap->is_hold = 1;
hold_tap->is_hold = 1; hold_tap->is_decided = true;
hold_tap->is_decided = true; break;
break; default:
default: return; return;
} }
} }
static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) {
{ switch (event) {
switch (event) { case HT_KEY_UP:
case HT_KEY_UP: hold_tap->is_hold = 0;
hold_tap->is_hold = 0; hold_tap->is_decided = true;
hold_tap->is_decided = true; break;
break; case HT_OTHER_KEY_DOWN:
case HT_OTHER_KEY_DOWN: case HT_TIMER_EVENT:
case HT_TIMER_EVENT: hold_tap->is_hold = 1;
hold_tap->is_hold = 1; hold_tap->is_decided = true;
hold_tap->is_decided = true; break;
break; default:
default: return; return;
} }
} }
static inline char* flavor_str(enum flavor flavor) { static inline char *flavor_str(enum flavor flavor) {
switch(flavor) { switch (flavor) {
case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED: case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
return "hold-preferred"; return "hold-preferred";
case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED: case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
return "balanced"; return "balanced";
case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED: case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
return "tap-preferred"; return "tap-preferred";
} }
return "UNKNOWN FLAVOR"; return "UNKNOWN FLAVOR";
} }
static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event) static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event) {
{ if (hold_tap->is_decided) {
if (hold_tap->is_decided) { return;
return; }
}
if (hold_tap != undecided_hold_tap) {
if (hold_tap != undecided_hold_tap) { LOG_DBG("ERROR found undecided tap hold that is not the active tap hold");
LOG_DBG("ERROR found undecided tap hold that is not the active tap hold"); return;
return; }
}
switch (hold_tap->config->flavor) {
switch(hold_tap->config->flavor) { case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED: decide_hold_preferred(hold_tap, event);
decide_hold_preferred(hold_tap, event); case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED: decide_balanced(hold_tap, event);
decide_balanced(hold_tap, event); case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED: decide_tap_preferred(hold_tap, event);
decide_tap_preferred(hold_tap, event); }
}
if (!hold_tap->is_decided) {
if (!hold_tap->is_decided) { return;
return; }
}
LOG_DBG("%d decided %s (%s event %d)", hold_tap->position, hold_tap->is_hold ? "hold" : "tap",
LOG_DBG("%d decided %s (%s event %d)", flavor_str(hold_tap->config->flavor), event);
hold_tap->position, undecided_hold_tap = NULL;
hold_tap->is_hold ? "hold" : "tap",
flavor_str(hold_tap->config->flavor), struct zmk_behavior_binding *behavior;
event); if (hold_tap->is_hold) {
undecided_hold_tap = NULL; behavior = &hold_tap->config->behaviors->hold;
struct device *behavior_device = device_get_binding(behavior->behavior_dev);
struct zmk_behavior_binding *behavior; behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_hold,
if (hold_tap->is_hold) { 0);
behavior = &hold_tap->config->behaviors->hold; } else {
struct device *behavior_device = device_get_binding(behavior->behavior_dev); behavior = &hold_tap->config->behaviors->tap;
behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_hold, 0); struct device *behavior_device = device_get_binding(behavior->behavior_dev);
} else { behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_tap,
behavior = &hold_tap->config->behaviors->tap; 0);
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();
}
release_captured_events();
} }
static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t param_hold, u32_t param_tap) 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; const struct behavior_hold_tap_config *cfg = dev->config_info;
if (undecided_hold_tap != NULL) { if (undecided_hold_tap != NULL) {
LOG_DBG("ERROR another hold-tap behavior is undecided."); LOG_DBG("ERROR another hold-tap behavior is undecided.");
// if this happens, make sure the behavior events occur AFTER other position events. // if this happens, make sure the behavior events occur AFTER other position events.
return 0; return 0;
} }
struct active_hold_tap *hold_tap = store_hold_tap(position, param_hold, param_tap, cfg); struct active_hold_tap *hold_tap = store_hold_tap(position, param_hold, param_tap, cfg);
if (hold_tap == NULL) { 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); LOG_ERR("unable to store hold-tap info, did you press more than %d hold-taps?",
return 0; ZMK_BHV_HOLD_TAP_MAX_HELD);
} return 0;
}
LOG_DBG("%d new undecided hold_tap", position); LOG_DBG("%d new undecided hold_tap", position);
undecided_hold_tap = hold_tap; undecided_hold_tap = hold_tap;
k_delayed_work_submit(&hold_tap->work, cfg->tapping_term_ms()); 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 // todo: once we get timing info for keypresses, start the timer relative to the original
// don't forget to simulate a timer-event before the event after that time was handled. // 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 __) 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);
struct active_hold_tap *hold_tap = find_hold_tap(position);
if (hold_tap == NULL) {
if (hold_tap == NULL) { LOG_ERR("ACTIVE_HOLD_TAP_CLEANED_UP_TOO_EARLY");
LOG_ERR("ACTIVE_HOLD_TAP_CLEANED_UP_TOO_EARLY"); return 0;
return 0; }
}
int work_cancel_result = k_delayed_work_cancel(&hold_tap->work);
int work_cancel_result = k_delayed_work_cancel(&hold_tap->work); decide_hold_tap(hold_tap, HT_KEY_UP);
decide_hold_tap(hold_tap, HT_KEY_UP);
struct zmk_behavior_binding *behavior;
struct zmk_behavior_binding *behavior; if (hold_tap->is_hold) {
if (hold_tap->is_hold) { behavior = &hold_tap->config->behaviors->hold;
behavior = &hold_tap->config->behaviors->hold; struct device *behavior_device = device_get_binding(behavior->behavior_dev);
struct device *behavior_device = device_get_binding(behavior->behavior_dev); behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_hold,
behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_hold, 0); 0);
} else { } else {
behavior = &hold_tap->config->behaviors->tap; behavior = &hold_tap->config->behaviors->tap;
struct device *behavior_device = device_get_binding(behavior->behavior_dev); struct device *behavior_device = device_get_binding(behavior->behavior_dev);
behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_tap, 0); behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_tap,
} 0);
}
if (work_cancel_result == -EINPROGRESS) { if (work_cancel_result == -EINPROGRESS) {
// let the timer handler clean up // let the timer handler clean up
// if we'd clear now, the timer may call back for an uninitialized active_hold_tap. // 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); LOG_DBG("%d hold-tap timer work in event queue", position);
hold_tap->work_is_cancelled = true; hold_tap->work_is_cancelled = true;
} else { } else {
LOG_DBG("%d cleaning up hold-tap", position); LOG_DBG("%d cleaning up hold-tap", position);
clear_hold_tap(hold_tap); clear_hold_tap(hold_tap);
} }
return 0; return 0;
} }
static const struct behavior_driver_api behavior_hold_tap_driver_api = { static const struct behavior_driver_api behavior_hold_tap_driver_api = {
.binding_pressed = on_hold_tap_binding_pressed, .binding_pressed = on_hold_tap_binding_pressed,
.binding_released = on_hold_tap_binding_released, .binding_released = on_hold_tap_binding_released,
}; };
static int position_state_changed_listener(const struct zmk_event_header *eh) {
static int position_state_changed_listener(const struct zmk_event_header *eh) struct position_state_changed *ev = cast_position_state_changed(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);
if (undecided_hold_tap == NULL) { return 0;
LOG_DBG("%d bubble (no undecided hold_tap active)", ev->position); }
return 0;
} if (undecided_hold_tap->position == ev->position) {
if (ev->state) { // keydown
if (undecided_hold_tap->position == ev->position) { LOG_ERR("hold-tap listener should be called before before most other listeners!");
if (ev->state) { // keydown return 0;
LOG_ERR("hold-tap listener should be called before before most other listeners!"); } else { // keyup
return 0; LOG_DBG("%d bubble undecided hold-tap keyrelease event", undecided_hold_tap->position);
} else { // keyup return 0;
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.
if (!ev->state && find_captured_keydown_event(ev->position) == NULL) { // we'll catch modifiers later in modifier_state_changed_listener
// no keydown event has been captured, let it bubble. LOG_DBG("%d bubbling %d %s event", undecided_hold_tap->position, ev->position,
// we'll catch modifiers later in modifier_state_changed_listener ev->state ? "down" : "up");
LOG_DBG("%d bubbling %d %s event", undecided_hold_tap->position, ev->position, ev->state ? "down" : "up"); return 0;
return 0; }
}
LOG_DBG("%d capturing %d %s event", undecided_hold_tap->position, ev->position,
LOG_DBG("%d capturing %d %s event", undecided_hold_tap->position, ev->position, ev->state ? "down" : "up"); ev->state ? "down" : "up");
capture_event(eh); capture_event(eh);
decide_hold_tap(undecided_hold_tap, ev->state ? HT_OTHER_KEY_DOWN : HT_OTHER_KEY_UP); decide_hold_tap(undecided_hold_tap, ev->state ? HT_OTHER_KEY_DOWN : HT_OTHER_KEY_UP);
return ZMK_EV_EVENT_CAPTURED; return ZMK_EV_EVENT_CAPTURED;
} }
static bool is_mod(struct keycode_state_changed *ev) static bool is_mod(struct keycode_state_changed *ev) {
{ return ev->usage_page == USAGE_KEYPAD && ev->keycode >= LCTL && ev->keycode <= RGUI;
return ev->usage_page == USAGE_KEYPAD && ev->keycode >= LCTL && ev->keycode <= RGUI;
} }
static int keycode_state_changed_listener(const struct zmk_event_header *eh) static int keycode_state_changed_listener(const struct zmk_event_header *eh) {
{ // we want to catch layer-up events too... how?
// we want to catch layer-up events too... how? struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
if (undecided_hold_tap == NULL) {
if (undecided_hold_tap == NULL) { // LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode);
// LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode); return 0;
return 0; }
}
if (!is_mod(ev)) {
if (!is_mod(ev)) { // LOG_DBG("0x%02X bubble (not a mod)", ev->keycode);
// LOG_DBG("0x%02X bubble (not a mod)", ev->keycode); return 0;
return 0; }
}
// only key-up events will bubble through position_state_changed_listener
// only key-up events will bubble through position_state_changed_listener // if a undecided_hold_tap is active.
// if a undecided_hold_tap is active. LOG_DBG("%d capturing 0x%02X %s event", undecided_hold_tap->position, ev->keycode,
LOG_DBG("%d capturing 0x%02X %s event", undecided_hold_tap->position, ev->keycode, ev->state ? "down" : "up"); ev->state ? "down" : "up");
capture_event(eh); capture_event(eh);
return ZMK_EV_EVENT_CAPTURED; return ZMK_EV_EVENT_CAPTURED;
} }
int behavior_hold_tap_listener(const struct zmk_event_header *eh) {
int behavior_hold_tap_listener(const struct zmk_event_header *eh) if (is_position_state_changed(eh)) {
{ return position_state_changed_listener(eh);
if (is_position_state_changed(eh)) { } else if (is_keycode_state_changed(eh)) {
return position_state_changed_listener(eh); return keycode_state_changed_listener(eh);
} else if (is_keycode_state_changed(eh)) { }
return keycode_state_changed_listener(eh); return 0;
}
return 0;
} }
ZMK_LISTENER(behavior_hold_tap, behavior_hold_tap_listener); 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. // this should be modifiers_state_changed, but unfrotunately that's not implemented yet.
ZMK_SUBSCRIPTION(behavior_hold_tap, keycode_state_changed); ZMK_SUBSCRIPTION(behavior_hold_tap, keycode_state_changed);
void behavior_hold_tap_timer_work_handler(struct k_work *item) 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);
struct active_hold_tap *hold_tap = CONTAINER_OF(item, struct active_hold_tap, work);
if (hold_tap->work_is_cancelled) { if (hold_tap->work_is_cancelled) {
clear_hold_tap(hold_tap); clear_hold_tap(hold_tap);
} else { } else {
decide_hold_tap(hold_tap, HT_TIMER_EVENT); decide_hold_tap(hold_tap, HT_TIMER_EVENT);
} }
} }
static int behavior_hold_tap_init(struct device *dev) static int behavior_hold_tap_init(struct device *dev) {
{ static bool init_first_run = true;
static bool init_first_run = true;
if (init_first_run) {
if (init_first_run) { for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
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);
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;
active_hold_taps[i].position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED; }
} }
} init_first_run = false;
init_first_run = false; return 0;
return 0;
} }
struct behavior_hold_tap_data {}; struct behavior_hold_tap_data {};
static struct behavior_hold_tap_data behavior_hold_tap_data; static struct behavior_hold_tap_data behavior_hold_tap_data;
#define _TRANSFORM_ENTRY(idx, node) \ #define _TRANSFORM_ENTRY(idx, node) \
{ \ { \
.behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \ .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))), \ .param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), \
.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))), \ (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 = { \ #define KP_INST(n) \
.hold = _TRANSFORM_ENTRY(0, n) \ static k_timeout_t behavior_hold_tap_config_##n##_gettime() { \
.tap = _TRANSFORM_ENTRY(1, n) \ return K_MSEC(DT_INST_PROP(n, tapping_term_ms)); \
}; \ } \
static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \ static struct behavior_hold_tap_behaviors behavior_hold_tap_behaviors_##n = { \
.behaviors = &behavior_hold_tap_behaviors_##n, \ .hold = _TRANSFORM_ENTRY(0, n).tap = _TRANSFORM_ENTRY(1, n)}; \
.tapping_term_ms = &behavior_hold_tap_config_##n##_gettime, \ static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \
.flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \ .behaviors = &behavior_hold_tap_behaviors_##n, \
}; \ .tapping_term_ms = &behavior_hold_tap_config_##n##_gettime, \
DEVICE_AND_API_INIT( \ .flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \
behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \ }; \
&behavior_hold_tap_data, \ DEVICE_AND_API_INIT(behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \
&behavior_hold_tap_config_##n, \ &behavior_hold_tap_data, &behavior_hold_tap_config_##n, APPLICATION, \
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_hold_tap_driver_api);
&behavior_hold_tap_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST) DT_INST_FOREACH_STATUS_OKAY(KP_INST)
#endif #endif

50
app/src/behaviors/behavior_key_press.c

@ -16,45 +16,35 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_key_press_config { 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) static int behavior_key_press_init(struct device *dev) { return 0; };
{
return 0;
};
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _) 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;
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);
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 _) 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;
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);
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 = { static const struct behavior_driver_api behavior_key_press_driver_api = {
.binding_pressed = on_keymap_binding_pressed, .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
.binding_released = on_keymap_binding_released
}; #define KP_INST(n) \
static const struct behavior_key_press_config behavior_key_press_config_##n = { \
#define KP_INST(n) \ .usage_page = DT_INST_PROP(n, usage_page)}; \
static const struct behavior_key_press_config behavior_key_press_config_##n = { \ static struct behavior_key_press_data behavior_key_press_data_##n; \
.usage_page = DT_INST_PROP(n, usage_page) \ 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, \
static struct behavior_key_press_data behavior_key_press_data_##n; \ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_key_press_driver_api);
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) DT_INST_FOREACH_STATUS_OKAY(KP_INST)

35
app/src/behaviors/behavior_momentary_layer.c

@ -14,41 +14,30 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_mo_config { }; struct behavior_mo_config {};
struct behavior_mo_data { }; struct behavior_mo_data {};
static int behavior_mo_init(struct device *dev) static int behavior_mo_init(struct device *dev) { return 0; };
{
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 _) return zmk_keymap_layer_activate(layer);
{
LOG_DBG("position %d layer %d", position, layer);
return zmk_keymap_layer_activate(layer);
} }
static int mo_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _) 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);
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 = { static const struct behavior_driver_api behavior_mo_driver_api = {
.binding_pressed = mo_keymap_binding_pressed, .binding_pressed = mo_keymap_binding_pressed, .binding_released = mo_keymap_binding_released};
.binding_released = mo_keymap_binding_released
};
static const struct behavior_mo_config behavior_mo_config = {}; static const struct behavior_mo_config behavior_mo_config = {};
static struct behavior_mo_data behavior_mo_data; static struct behavior_mo_data behavior_mo_data;
DEVICE_AND_API_INIT(behavior_mo, DT_INST_LABEL(0), behavior_mo_init, DEVICE_AND_API_INIT(behavior_mo, DT_INST_LABEL(0), behavior_mo_init, &behavior_mo_data,
&behavior_mo_data, &behavior_mo_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_mo_config,
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_mo_driver_api); &behavior_mo_driver_api);

32
app/src/behaviors/behavior_none.c

@ -13,36 +13,30 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_none_config { }; struct behavior_none_config {};
struct behavior_none_data { }; struct behavior_none_data {};
static int behavior_none_init(struct device *dev) static int behavior_none_init(struct device *dev) { return 0; };
{
return 0;
};
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2) static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
{ u32_t _param2) {
return 0; return 0;
} }
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, u32_t _param2) static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1,
{ u32_t _param2) {
return 0; return 0;
} }
static const struct behavior_driver_api behavior_none_driver_api = { static const struct behavior_driver_api behavior_none_driver_api = {
.binding_pressed = on_keymap_binding_pressed, .binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released, .binding_released = on_keymap_binding_released,
}; };
static const struct behavior_none_config behavior_none_config = {}; static const struct behavior_none_config behavior_none_config = {};
static struct behavior_none_data behavior_none_data; static struct behavior_none_data behavior_none_data;
DEVICE_AND_API_INIT(behavior_none, DT_INST_LABEL(0), behavior_none_init, DEVICE_AND_API_INIT(behavior_none, DT_INST_LABEL(0), behavior_none_init, &behavior_none_data,
&behavior_none_data, &behavior_none_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_none_config,
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_none_driver_api); &behavior_none_driver_api);

40
app/src/behaviors/behavior_reset.c

@ -14,37 +14,31 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_reset_config { struct behavior_reset_config {
int type; int type;
}; };
static int behavior_reset_init(struct device *dev) static int behavior_reset_init(struct device *dev) { return 0; };
{
return 0;
};
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2) 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; const struct behavior_reset_config *cfg = dev->config_info;
// TODO: Correct magic code for going into DFU? // TODO: Correct magic code for going into DFU?
// See https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107 // See
sys_reboot(cfg->type); // https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
return 0; sys_reboot(cfg->type);
return 0;
} }
static const struct behavior_driver_api behavior_reset_driver_api = { 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) \
#define RST_INST(n) \ static const struct behavior_reset_config behavior_reset_config_##n = { \
static const struct behavior_reset_config behavior_reset_config_##n = { \ .type = DT_INST_PROP(n, type)}; \
.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, \
DEVICE_AND_API_INIT(behavior_reset_##n, DT_INST_LABEL(n), behavior_reset_init, \ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_reset_driver_api);
NULL, \
&behavior_reset_config_##n, \
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&behavior_reset_driver_api);
DT_INST_FOREACH_STATUS_OKAY(RST_INST) DT_INST_FOREACH_STATUS_OKAY(RST_INST)

45
app/src/behaviors/behavior_rgb_underglow.c

@ -15,48 +15,41 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
static int behavior_rgb_underglow_init(struct device *dev) static int behavior_rgb_underglow_init(struct device *dev) { return 0; }
{
return 0;
}
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t action, u32_t _) static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t action, u32_t _) {
{ switch (action) {
switch (action)
{
case RGB_TOG: case RGB_TOG:
return zmk_rgb_underglow_toggle(); return zmk_rgb_underglow_toggle();
case RGB_HUI: case RGB_HUI:
return zmk_rgb_underglow_change_hue(1); return zmk_rgb_underglow_change_hue(1);
case RGB_HUD: case RGB_HUD:
return zmk_rgb_underglow_change_hue(-1); return zmk_rgb_underglow_change_hue(-1);
case RGB_SAI: case RGB_SAI:
return zmk_rgb_underglow_change_sat(1); return zmk_rgb_underglow_change_sat(1);
case RGB_SAD: case RGB_SAD:
return zmk_rgb_underglow_change_sat(-1); return zmk_rgb_underglow_change_sat(-1);
case RGB_BRI: case RGB_BRI:
return zmk_rgb_underglow_change_brt(1); return zmk_rgb_underglow_change_brt(1);
case RGB_BRD: case RGB_BRD:
return zmk_rgb_underglow_change_brt(-1); return zmk_rgb_underglow_change_brt(-1);
case RGB_SPI: case RGB_SPI:
return zmk_rgb_underglow_change_spd(1); return zmk_rgb_underglow_change_spd(1);
case RGB_SPD: case RGB_SPD:
return zmk_rgb_underglow_change_spd(-1); return zmk_rgb_underglow_change_spd(-1);
case RGB_EFF: case RGB_EFF:
return zmk_rgb_underglow_cycle_effect(1); return zmk_rgb_underglow_cycle_effect(1);
case RGB_EFR: 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 = { 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, DEVICE_AND_API_INIT(behavior_rgb_underglow, DT_INST_LABEL(0), behavior_rgb_underglow_init, NULL,
NULL, NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
NULL,
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_rgb_underglow_driver_api); &behavior_rgb_underglow_driver_api);

102
app/src/behaviors/behavior_sensor_rotate_key_press.c

@ -17,75 +17,69 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_sensor_rotate_key_press_config { struct behavior_sensor_rotate_key_press_config {
u8_t usage_page; u8_t usage_page;
};
struct behavior_sensor_rotate_key_press_data { };
static int behavior_sensor_rotate_key_press_init(struct device *dev)
{
return 0;
}; };
struct behavior_sensor_rotate_key_press_data {};
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) 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; const struct behavior_sensor_rotate_key_press_config *cfg = dev->config_info;
struct sensor_value value; struct sensor_value value;
int err; int err;
u32_t keycode; u32_t keycode;
struct keycode_state_changed *ev; 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); 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) { if (err) {
LOG_WRN("Failed to ge sensor rotation value: %d", err); LOG_WRN("Failed to ge sensor rotation value: %d", err);
return err; return err;
} }
switch (value.val1) { switch (value.val1) {
case 1: case 1:
keycode = increment_keycode; keycode = increment_keycode;
break; break;
case -1: case -1:
keycode = decrement_keycode; keycode = decrement_keycode;
break; break;
default: default:
return -ENOTSUP; return -ENOTSUP;
} }
LOG_DBG("SEND %d", keycode);
LOG_DBG("SEND %d", keycode);
ev = new_keycode_state_changed(); ev = new_keycode_state_changed();
ev->usage_page = cfg->usage_page; ev->usage_page = cfg->usage_page;
ev->keycode = keycode; ev->keycode = keycode;
ev->state = true; ev->state = true;
ZMK_EVENT_RAISE(ev); ZMK_EVENT_RAISE(ev);
// TODO: Better way to do this? // TODO: Better way to do this?
k_msleep(5); k_msleep(5);
ev = new_keycode_state_changed(); ev = new_keycode_state_changed();
ev->usage_page = cfg->usage_page; ev->usage_page = cfg->usage_page;
ev->keycode = keycode; ev->keycode = keycode;
ev->state = false; ev->state = false;
return ZMK_EVENT_RAISE(ev); return ZMK_EVENT_RAISE(ev);
} }
static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = { 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) \
#define KP_INST(n) \ static const struct behavior_sensor_rotate_key_press_config \
static const struct behavior_sensor_rotate_key_press_config behavior_sensor_rotate_key_press_config_##n = { \ behavior_sensor_rotate_key_press_config_##n = {.usage_page = DT_INST_PROP(n, usage_page)}; \
.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( \
static struct behavior_sensor_rotate_key_press_data behavior_sensor_rotate_key_press_data_##n; \ behavior_sensor_rotate_key_press_##n, DT_INST_LABEL(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_init, &behavior_sensor_rotate_key_press_data_##n, \
&behavior_sensor_rotate_key_press_data_##n, \ &behavior_sensor_rotate_key_press_config_##n, APPLICATION, \
&behavior_sensor_rotate_key_press_config_##n, \ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_key_press_driver_api);
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&behavior_sensor_rotate_key_press_driver_api);
DT_INST_FOREACH_STATUS_OKAY(KP_INST) DT_INST_FOREACH_STATUS_OKAY(KP_INST)

33
app/src/behaviors/behavior_toggle_layer.c

@ -14,30 +14,21 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_tog_config struct behavior_tog_config {};
{ struct behavior_tog_data {};
};
struct behavior_tog_data
{
};
static int behavior_tog_init(struct device *dev) static int behavior_tog_init(struct device *dev) { return 0; };
{
return 0;
};
static int tog_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _) 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);
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 _) 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);
LOG_DBG("position %d layer %d", position, layer);
return 0; return 0;
} }
static const struct behavior_driver_api behavior_tog_driver_api = { 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; static struct behavior_tog_data behavior_tog_data;
DEVICE_AND_API_INIT(behavior_tog, DT_INST_LABEL(0), behavior_tog_init, DEVICE_AND_API_INIT(behavior_tog, DT_INST_LABEL(0), behavior_tog_init, &behavior_tog_data,
&behavior_tog_data, &behavior_tog_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_tog_config,
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_tog_driver_api); &behavior_tog_driver_api);

32
app/src/behaviors/behavior_transparent.c

@ -13,36 +13,30 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_transparent_config { }; struct behavior_transparent_config {};
struct behavior_transparent_data { }; struct behavior_transparent_data {};
static int behavior_transparent_init(struct device *dev) static int behavior_transparent_init(struct device *dev) { return 0; };
{
return 0;
};
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2) static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
{ u32_t _param2) {
return 1; return 1;
} }
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, u32_t _param2) static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1,
{ u32_t _param2) {
return 1; return 1;
} }
static const struct behavior_driver_api behavior_transparent_driver_api = { static const struct behavior_driver_api behavior_transparent_driver_api = {
.binding_pressed = on_keymap_binding_pressed, .binding_pressed = on_keymap_binding_pressed,
.binding_released = on_keymap_binding_released, .binding_released = on_keymap_binding_released,
}; };
static const struct behavior_transparent_config behavior_transparent_config = {}; static const struct behavior_transparent_config behavior_transparent_config = {};
static struct behavior_transparent_data behavior_transparent_data; static struct behavior_transparent_data behavior_transparent_data;
DEVICE_AND_API_INIT(behavior_transparent, DT_INST_LABEL(0), behavior_transparent_init, DEVICE_AND_API_INIT(behavior_transparent, DT_INST_LABEL(0), behavior_transparent_init,
&behavior_transparent_data, &behavior_transparent_data, &behavior_transparent_config, APPLICATION,
&behavior_transparent_config, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_transparent_driver_api);
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&behavior_transparent_driver_api);

154
app/src/ble.c

@ -45,7 +45,6 @@ static u8_t passkey_digit = 0;
#define PROFILE_COUNT CONFIG_BT_MAX_PAIRED #define PROFILE_COUNT CONFIG_BT_MAX_PAIRED
#endif #endif
static struct zmk_ble_profile profiles[PROFILE_COUNT]; static struct zmk_ble_profile profiles[PROFILE_COUNT];
static u8_t active_profile; static u8_t active_profile;
@ -53,13 +52,12 @@ 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_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA_BYTES(BT_DATA_UUID16_SOME, BT_DATA_BYTES(BT_DATA_UUID16_SOME,
#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) #if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
0x12, 0x18, /* HID Service */ 0x12, 0x18, /* HID Service */
#endif #endif
0x0f, 0x18 /* Battery Service */ 0x0f, 0x18 /* Battery Service */
), ),
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_DATA_BYTES(BT_DATA_UUID128_ALL, ZMK_SPLIT_BT_SERVICE_UUID)
ZMK_SPLIT_BT_SERVICE_UUID)
#endif #endif
}; };
@ -69,8 +67,7 @@ static bt_addr_le_t peripheral_addr;
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */ #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
static void raise_profile_changed_event() static void raise_profile_changed_event() {
{
struct ble_active_profile_changed *ev = new_ble_active_profile_changed(); struct ble_active_profile_changed *ev = new_ble_active_profile_changed();
ev->index = active_profile; ev->index = active_profile;
ev->profile = &profiles[active_profile]; ev->profile = &profiles[active_profile];
@ -78,13 +75,11 @@ static void raise_profile_changed_event()
ZMK_EVENT_RAISE(ev); ZMK_EVENT_RAISE(ev);
} }
static bool active_profile_is_open() static bool active_profile_is_open() {
{
return !bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY); 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) void set_profile_address(u8_t index, const bt_addr_le_t *addr) {
{
char setting_name[15]; char setting_name[15];
char addr_str[BT_ADDR_LE_STR_LEN]; char addr_str[BT_ADDR_LE_STR_LEN];
@ -97,8 +92,7 @@ void set_profile_address(u8_t index, const bt_addr_le_t *addr)
raise_profile_changed_event(); raise_profile_changed_event();
} }
int zmk_ble_adv_pause() int zmk_ble_adv_pause() {
{
int err = bt_le_adv_stop(); int err = bt_le_adv_stop();
if (err) { if (err) {
LOG_ERR("Failed to stop advertising (err %d)", err); LOG_ERR("Failed to stop advertising (err %d)", err);
@ -108,16 +102,12 @@ int zmk_ble_adv_pause()
return 0; return 0;
}; };
int zmk_ble_adv_resume() int zmk_ble_adv_resume() {
{ LOG_DBG("active_profile %d, directed? %s", active_profile,
LOG_DBG("active_profile %d, directed? %s", active_profile, active_profile_is_open() ? "no" : "yes"); active_profile_is_open() ? "no" : "yes");
int err = bt_le_adv_start( int err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
BT_LE_ADV_CONN_NAME, if (err) {
zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad),
NULL, 0);
if (err)
{
LOG_ERR("Advertising failed to start (err %d)", err); LOG_ERR("Advertising failed to start (err %d)", err);
return err; return err;
} }
@ -125,8 +115,7 @@ int zmk_ble_adv_resume()
return 0; return 0;
}; };
int zmk_ble_clear_bonds() int zmk_ble_clear_bonds() {
{
LOG_DBG(""); LOG_DBG("");
if (bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY)) { if (bt_addr_le_cmp(&profiles[active_profile].peer, BT_ADDR_LE_ANY)) {
@ -138,8 +127,7 @@ int zmk_ble_clear_bonds()
return 0; return 0;
}; };
int zmk_ble_prof_select(u8_t index) int zmk_ble_prof_select(u8_t index) {
{
LOG_DBG("profile %d", index); LOG_DBG("profile %d", index);
if (active_profile == index) { if (active_profile == index) {
return 0; return 0;
@ -151,32 +139,23 @@ int zmk_ble_prof_select(u8_t index)
raise_profile_changed_event(); raise_profile_changed_event();
}; };
int zmk_ble_prof_next() int zmk_ble_prof_next() {
{
LOG_DBG(""); LOG_DBG("");
return zmk_ble_prof_select((active_profile + 1) % PROFILE_COUNT); return zmk_ble_prof_select((active_profile + 1) % PROFILE_COUNT);
}; };
int zmk_ble_prof_prev() int zmk_ble_prof_prev() {
{
LOG_DBG(""); LOG_DBG("");
return zmk_ble_prof_select((active_profile + PROFILE_COUNT - 1) % PROFILE_COUNT); return zmk_ble_prof_select((active_profile + PROFILE_COUNT - 1) % PROFILE_COUNT);
}; };
bt_addr_le_t *zmk_ble_active_profile_addr() bt_addr_le_t *zmk_ble_active_profile_addr() { return &profiles[active_profile].peer; }
{
return &profiles[active_profile].peer;
}
char *zmk_ble_active_profile_name() char *zmk_ble_active_profile_name() { return profiles[active_profile].name; }
{
return profiles[active_profile].name;
}
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) #if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr) void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr) {
{
memcpy(&peripheral_addr, addr, sizeof(bt_addr_le_t)); memcpy(&peripheral_addr, addr, sizeof(bt_addr_le_t));
settings_save_one("ble/peripheral_address", addr, sizeof(bt_addr_le_t)); settings_save_one("ble/peripheral_address", addr, sizeof(bt_addr_le_t));
} }
@ -185,8 +164,8 @@ void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr)
#if IS_ENABLED(CONFIG_SETTINGS) #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) static int ble_profiles_handle_set(const char *name, size_t len, settings_read_cb read_cb,
{ void *cb_arg) {
const char *next; const char *next;
LOG_DBG("Setting BLE value %s", log_strdup(name)); LOG_DBG("Setting BLE value %s", log_strdup(name));
@ -200,7 +179,8 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
} }
if (len != sizeof(struct zmk_ble_profile)) { if (len != sizeof(struct zmk_ble_profile)) {
LOG_ERR("Invalid profile size (got %d expected %d)", len, sizeof(struct zmk_ble_profile)); LOG_ERR("Invalid profile size (got %d expected %d)", len,
sizeof(struct zmk_ble_profile));
return -EINVAL; return -EINVAL;
} }
@ -247,19 +227,14 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
return 0; return 0;
}; };
struct settings_handler profiles_handler = { struct settings_handler profiles_handler = {.name = "ble", .h_set = ble_profiles_handle_set};
.name = "ble",
.h_set = ble_profiles_handle_set
};
#endif /* IS_ENABLED(CONFIG_SETTINGS) */ #endif /* IS_ENABLED(CONFIG_SETTINGS) */
static void connected(struct bt_conn *conn, u8_t err) static void connected(struct bt_conn *conn, u8_t err) {
{
char addr[BT_ADDR_LE_STR_LEN]; char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 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); LOG_WRN("Failed to connect to %s (%u)", log_strdup(addr), err);
return; return;
} }
@ -272,14 +247,12 @@ static void connected(struct bt_conn *conn, u8_t err)
bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M); bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M);
#endif #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"); 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]; char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
@ -287,7 +260,8 @@ static void disconnected(struct bt_conn *conn, u8_t reason)
LOG_DBG("Disconnected from %s (reason 0x%02x)", log_strdup(addr), reason); LOG_DBG("Disconnected from %s (reason 0x%02x)", log_strdup(addr), reason);
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) #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))) { // 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(); // zmk_ble_adv_resume();
// } // }
#else #else
@ -295,21 +269,15 @@ static void disconnected(struct bt_conn *conn, u8_t reason)
#endif #endif
} }
static void security_changed(struct bt_conn *conn, bt_security_t level, static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {
enum bt_security_err err)
{
char addr[BT_ADDR_LE_STR_LEN]; char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 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); LOG_DBG("Security changed: %s level %u", log_strdup(addr), level);
} } else {
else LOG_ERR("Security failed: %s level %u err %d", log_strdup(addr), level, err);
{
LOG_ERR("Security failed: %s level %u err %d", log_strdup(addr), level,
err);
} }
} }
@ -319,8 +287,7 @@ static struct bt_conn_cb conn_callbacks = {
.security_changed = security_changed, .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]; char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
@ -330,8 +297,7 @@ static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY #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]; char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
@ -342,14 +308,12 @@ static void auth_passkey_entry(struct bt_conn *conn)
#endif #endif
static void auth_cancel(struct bt_conn *conn) static void auth_cancel(struct bt_conn *conn) {
{
char addr[BT_ADDR_LE_STR_LEN]; char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 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); bt_conn_unref(auth_passkey_entry_conn);
auth_passkey_entry_conn = NULL; auth_passkey_entry_conn = NULL;
} }
@ -360,8 +324,8 @@ static void auth_cancel(struct bt_conn *conn)
} }
#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) #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) 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; struct bt_conn_info info;
bt_conn_get_info(conn, &info); bt_conn_get_info(conn, &info);
@ -375,8 +339,7 @@ static enum bt_security_err auth_pairing_accept(struct bt_conn *conn, const stru
}; };
#endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */ #endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */
static void auth_pairing_complete(struct bt_conn *conn, bool bonded) static void auth_pairing_complete(struct bt_conn *conn, bool bonded) {
{
struct bt_conn_info info; struct bt_conn_info info;
char addr[BT_ADDR_LE_STR_LEN]; char addr[BT_ADDR_LE_STR_LEN];
const bt_addr_le_t *dst = bt_conn_get_dst(conn); const bt_addr_le_t *dst = bt_conn_get_dst(conn);
@ -413,12 +376,9 @@ static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
.cancel = auth_cancel, .cancel = auth_cancel,
}; };
static void zmk_ble_ready(int err) {
static void zmk_ble_ready(int err)
{
LOG_DBG("ready? %d", err); LOG_DBG("ready? %d", err);
if (err) if (err) {
{
LOG_ERR("Bluetooth init failed (err %d)", err); LOG_ERR("Bluetooth init failed (err %d)", err);
return; return;
} }
@ -426,12 +386,10 @@ static void zmk_ble_ready(int err)
zmk_ble_adv_resume(); 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); int err = bt_enable(NULL);
if (err) if (err) {
{
LOG_ERR("BLUETOOTH FAILED (%d)", err); LOG_ERR("BLUETOOTH FAILED (%d)", err);
return err; return err;
} }
@ -475,8 +433,7 @@ static int zmk_ble_init(struct device *_arg)
return 0; return 0;
} }
int zmk_ble_unpair_all() int zmk_ble_unpair_all() {
{
int resp = 0; int resp = 0;
for (int i = BT_ID_DEFAULT; i < CONFIG_BT_ID_MAX; i++) { for (int i = BT_ID_DEFAULT; i < CONFIG_BT_ID_MAX; i++) {
@ -490,17 +447,14 @@ int zmk_ble_unpair_all()
return resp; 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; zmk_key key = key_event->key;
if (!auth_passkey_entry_conn) if (!auth_passkey_entry_conn) {
{
return true; return true;
} }
if (key < NUM_1 || key > NUM_0) if (key < NUM_1 || key > NUM_0) {
{
return true; return true;
} }
@ -508,11 +462,9 @@ bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
passkey_entries[passkey_digit++] = val; passkey_entries[passkey_digit++] = val;
if (passkey_digit == 6) if (passkey_digit == 6) {
{
u32_t passkey = 0; u32_t passkey = 0;
for (int i = 5; i >= 0; i--) for (int i = 5; i >= 0; i--) {
{
passkey = (passkey * 10) + val; passkey = (passkey * 10) + val;
} }
bt_conn_auth_passkey_entry(auth_passkey_entry_conn, passkey); bt_conn_auth_passkey_entry(auth_passkey_entry_conn, passkey);
@ -523,6 +475,4 @@ bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
return false; return false;
} }
SYS_INIT(zmk_ble_init, SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);
APPLICATION,
CONFIG_ZMK_BLE_INIT_PRIORITY);

17
app/src/ble_unpair_combo.c

@ -18,14 +18,12 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/event-manager.h> #include <zmk/event-manager.h>
#include <zmk/events/position-state-changed.h> #include <zmk/events/position-state-changed.h>
static u8_t combo_state; static u8_t combo_state;
const u32_t key_positions[] = DT_INST_PROP(0, key_positions); const u32_t key_positions[] = DT_INST_PROP(0, key_positions);
#define KP_LEN DT_INST_PROP_LEN(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++) { for (int i = 0; i < KP_LEN; i++) {
if (key_positions[i] == kp) { if (key_positions[i] == kp) {
return i; return i;
@ -35,8 +33,7 @@ int index_for_key_position(u32_t kp)
return -1; 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)) { if (is_position_state_changed(eh)) {
const struct position_state_changed *psc = cast_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; 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++) { for (int i = 0; i < KP_LEN; i++) {
if (!(combo_state & BIT(i))) { if (!(combo_state & BIT(i))) {
LOG_DBG("Key position %d not held, skipping unpair combo", key_positions[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; 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_init(&unpair_combo_work, unpair_combo_work_handler);
k_delayed_work_submit(&unpair_combo_work, K_SECONDS(2)); 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_LISTENER(zmk_ble_unpair_combo, unpair_combo_listener);
ZMK_SUBSCRIPTION(zmk_ble_unpair_combo, position_state_changed); ZMK_SUBSCRIPTION(zmk_ble_unpair_combo, position_state_changed);
SYS_INIT(zmk_ble_unpair_combo_init, SYS_INIT(zmk_ble_unpair_combo_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
APPLICATION,
CONFIG_APPLICATION_INIT_PRIORITY);
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ #endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */

6
app/src/display.c

@ -20,8 +20,7 @@ static struct device *display;
static lv_obj_t *screen; static lv_obj_t *screen;
int zmk_display_init() int zmk_display_init() {
{
lv_obj_t *hello_world_label; lv_obj_t *hello_world_label;
lv_obj_t *count_label; lv_obj_t *count_label;
@ -48,8 +47,7 @@ int zmk_display_init()
return 0; return 0;
} }
void zmk_display_task_handler() void zmk_display_task_handler() {
{
lv_tick_inc(10); lv_tick_inc(10);
lv_task_handler(); lv_task_handler();
k_sleep(K_MSEC(10)); k_sleep(K_MSEC(10));

21
app/src/endpoints.c

@ -12,27 +12,24 @@
#include <logging/log.h> #include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); 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; int err;
struct zmk_hid_keypad_report *keypad_report; struct zmk_hid_keypad_report *keypad_report;
struct zmk_hid_consumer_report *consumer_report; struct zmk_hid_consumer_report *consumer_report;
LOG_DBG("usage page 0x%02X", usage_page); LOG_DBG("usage page 0x%02X", usage_page);
switch (usage_page) switch (usage_page) {
{
case USAGE_KEYPAD: case USAGE_KEYPAD:
keypad_report = zmk_hid_get_keypad_report(); keypad_report = zmk_hid_get_keypad_report();
#ifdef CONFIG_ZMK_USB #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"); LOG_DBG("USB Send Failed");
} }
#endif /* CONFIG_ZMK_USB */ #endif /* CONFIG_ZMK_USB */
#ifdef CONFIG_ZMK_BLE #ifdef CONFIG_ZMK_BLE
err = zmk_hog_send_keypad_report(&keypad_report->body); err = zmk_hog_send_keypad_report(&keypad_report->body);
if (err) if (err) {
{
LOG_ERR("FAILED TO SEND OVER HOG: %d", err); LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
} }
#endif /* CONFIG_ZMK_BLE */ #endif /* CONFIG_ZMK_BLE */
@ -41,16 +38,15 @@ int zmk_endpoints_send_report(u8_t usage_page)
case USAGE_CONSUMER: case USAGE_CONSUMER:
consumer_report = zmk_hid_get_consumer_report(); consumer_report = zmk_hid_get_consumer_report();
#ifdef CONFIG_ZMK_USB #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"); LOG_DBG("USB Send Failed");
} }
#endif /* CONFIG_ZMK_USB */ #endif /* CONFIG_ZMK_USB */
#ifdef CONFIG_ZMK_BLE #ifdef CONFIG_ZMK_BLE
err = zmk_hog_send_consumer_report(&consumer_report->body); err = zmk_hog_send_consumer_report(&consumer_report->body);
if (err) if (err) {
{
LOG_ERR("FAILED TO SEND OVER HOG: %d", err); LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
} }
#endif /* CONFIG_ZMK_BLE */ #endif /* CONFIG_ZMK_BLE */
@ -63,4 +59,3 @@ int zmk_endpoints_send_report(u8_t usage_page)
return 0; return 0;
} }

42
app/src/event_manager.c

@ -11,15 +11,13 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/event-manager.h> #include <zmk/event-manager.h>
extern struct zmk_event_type* __event_type_start[]; extern struct zmk_event_type *__event_type_start[];
extern struct zmk_event_type* __event_type_end[]; extern struct zmk_event_type *__event_type_end[];
extern struct zmk_event_subscription __event_subscriptions_start[]; extern struct zmk_event_subscription __event_subscriptions_start[];
extern struct zmk_event_subscription __event_subscriptions_end[]; 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; int ret = 0;
u8_t len = __event_subscriptions_end - __event_subscriptions_start; u8_t len = __event_subscriptions_end - __event_subscriptions_start;
for (int i = start_index; i < len; i++) { 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; goto release;
} else if (ret > 0) { } else if (ret > 0) {
switch (ret) { switch (ret) {
case ZMK_EV_EVENT_HANDLED: case ZMK_EV_EVENT_HANDLED:
LOG_DBG("Listener handled the event"); LOG_DBG("Listener handled the event");
ret = 0; ret = 0;
goto release; goto release;
case ZMK_EV_EVENT_CAPTURED: case ZMK_EV_EVENT_CAPTURED:
LOG_DBG("Listener captured the event"); LOG_DBG("Listener captured the event");
event->last_listener_index = i; event->last_listener_index = i;
// Listeners are expected to free events they capture // Listeners are expected to free events they capture
return 0; return 0;
} }
} }
} }
@ -50,19 +48,18 @@ release:
return ret; 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); 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; u8_t len = __event_subscriptions_end - __event_subscriptions_start;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i; struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
if (ev_sub->event_type == event->event && ev_sub->listener == listener) { 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; 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; u8_t len = __event_subscriptions_end - __event_subscriptions_start;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
struct zmk_event_subscription *ev_sub = __event_subscriptions_start + 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; 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); return zmk_event_manager_handle_from(event, event->last_listener_index + 1);
} }

91
app/src/hid.c

@ -10,41 +10,27 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/hid.h> #include <zmk/hid.h>
static struct zmk_hid_keypad_report kp_report = { static struct zmk_hid_keypad_report kp_report = {
.report_id = 1, .report_id = 1, .body = {.modifiers = 0, .keys = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}};
.body = {
.modifiers = 0, static struct zmk_hid_consumer_report consumer_report = {.report_id = 2,
.keys = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}; .body = {.keys = {0, 0, 0, 0, 0, 0}}};
static struct zmk_hid_consumer_report consumer_report = { #define _TOGGLE_MOD(mod, state) \
.report_id = 2, if (modifier > MOD_RGUI) { \
.body = { return -EINVAL; \
.keys = {0,0,0,0,0,0}}}; } \
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; return 0;
int zmk_hid_register_mod(zmk_mod modifier) int zmk_hid_register_mod(zmk_mod modifier) { _TOGGLE_MOD(modifier, true); }
{ int zmk_hid_unregister_mod(zmk_mod modifier) { _TOGGLE_MOD(modifier, false); }
_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; kp_report.body.modifiers |= modifiers;
return 0; 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; kp_report.body.modifiers &= ~modifiers;
return 0; return 0;
} }
@ -67,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_KEY(code, val) WRITE_BIT(kp_report.body.keys[code / 8], code % 8, val)
#define TOGGLE_CONSUMER(match, val) \ #define TOGGLE_CONSUMER(match, val) \
for (int idx = 0; idx < MAX_KEYS; idx++) \ for (int idx = 0; idx < MAX_KEYS; idx++) { \
{ \ if (consumer_report.body.keys[idx] != match) { \
if (consumer_report.body.keys[idx] != match) \ continue; \
{ \ } \
continue; \ consumer_report.body.keys[idx] = val; \
} \ break; \
consumer_report.body.keys[idx] = val; \
break; \
} }
int zmk_hid_keypad_press(zmk_key code) {
int zmk_hid_keypad_press(zmk_key code) if (code >= LCTL && code <= RGUI) {
{
if (code >= LCTL && code <= RGUI)
{
return zmk_hid_register_mod(code - LCTL); return zmk_hid_register_mod(code - LCTL);
} }
if (code > ZMK_HID_MAX_KEYCODE) {
if (code > ZMK_HID_MAX_KEYCODE)
{
return -EINVAL; return -EINVAL;
} }
@ -99,15 +78,12 @@ int zmk_hid_keypad_press(zmk_key code)
return 0; return 0;
}; };
int zmk_hid_keypad_release(zmk_key code) int zmk_hid_keypad_release(zmk_key code) {
{ if (code >= LCTL && code <= RGUI) {
if (code >= LCTL && code <= RGUI)
{
return zmk_hid_unregister_mod(code - LCTL); return zmk_hid_unregister_mod(code - LCTL);
} }
if (code > ZMK_HID_MAX_KEYCODE) if (code > ZMK_HID_MAX_KEYCODE) {
{
return -EINVAL; return -EINVAL;
} }
@ -118,25 +94,20 @@ int zmk_hid_keypad_release(zmk_key code)
return 0; return 0;
}; };
int zmk_hid_consumer_press(zmk_key code) int zmk_hid_consumer_press(zmk_key code) {
{
TOGGLE_CONSUMER(0U, code); TOGGLE_CONSUMER(0U, code);
return 0; return 0;
}; };
int zmk_hid_consumer_release(zmk_key code) {
int zmk_hid_consumer_release(zmk_key code)
{
TOGGLE_CONSUMER(code, 0U); TOGGLE_CONSUMER(code, 0U);
return 0; 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; 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; return &consumer_report;
} }

130
app/src/hid_listener.c

@ -15,90 +15,84 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/hid.h> #include <zmk/hid.h>
#include <zmk/endpoints.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) switch (usage_page) {
{ case USAGE_KEYPAD:
int err; err = zmk_hid_keypad_press(keycode);
LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode); if (err) {
LOG_ERR("Unable to press keycode");
switch (usage_page) { return err;
case USAGE_KEYPAD: }
err = zmk_hid_keypad_press(keycode); break;
if (err) { case USAGE_CONSUMER:
LOG_ERR("Unable to press keycode"); err = zmk_hid_consumer_press(keycode);
return err; if (err) {
} LOG_ERR("Unable to press keycode");
break; return err;
case USAGE_CONSUMER: }
err = zmk_hid_consumer_press(keycode); break;
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) static int hid_listener_keycode_released(u8_t usage_page, u32_t keycode) {
{ int err;
int err; LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
LOG_DBG("usage_page 0x%02X keycode 0x%02X", usage_page, keycode);
switch (usage_page) { switch (usage_page) {
case USAGE_KEYPAD: case USAGE_KEYPAD:
err = zmk_hid_keypad_release(keycode); err = zmk_hid_keypad_release(keycode);
if (err) { if (err) {
LOG_ERR("Unable to release keycode"); LOG_ERR("Unable to release keycode");
return err; return err;
}
break;
case USAGE_CONSUMER:
err = zmk_hid_consumer_release(keycode);
if (err) {
LOG_ERR("Unable to release keycode");
return err;
}
break;
} }
break; return zmk_endpoints_send_report(usage_page);
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);
} }
static int hid_listener_modifiers_pressed(zmk_mod_flags modifiers) static int hid_listener_modifiers_pressed(zmk_mod_flags modifiers) {
{ LOG_DBG("modifiers %d", modifiers);
LOG_DBG("modifiers %d", modifiers);
zmk_hid_register_mods(modifiers); zmk_hid_register_mods(modifiers);
return zmk_endpoints_send_report(USAGE_KEYPAD); return zmk_endpoints_send_report(USAGE_KEYPAD);
} }
static int hid_listener_modifiers_released(zmk_mod_flags modifiers) static int hid_listener_modifiers_released(zmk_mod_flags modifiers) {
{ LOG_DBG("modifiers %d", modifiers);
LOG_DBG("modifiers %d", modifiers);
zmk_hid_unregister_mods(modifiers); zmk_hid_unregister_mods(modifiers);
return zmk_endpoints_send_report(USAGE_KEYPAD); return zmk_endpoints_send_report(USAGE_KEYPAD);
} }
int hid_listener(const struct zmk_event_header *eh) int hid_listener(const struct zmk_event_header *eh) {
{ if (is_keycode_state_changed(eh)) {
if (is_keycode_state_changed(eh)) { const struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
const struct keycode_state_changed *ev = cast_keycode_state_changed(eh); if (ev->state) {
if (ev->state) { hid_listener_keycode_pressed(ev->usage_page, ev->keycode);
hid_listener_keycode_pressed(ev->usage_page, ev->keycode); } else {
} else { hid_listener_keycode_released(ev->usage_page, ev->keycode);
hid_listener_keycode_released(ev->usage_page, ev->keycode); }
} } else if (is_modifiers_state_changed(eh)) {
} else if (is_modifiers_state_changed(eh)) { const struct modifiers_state_changed *ev = cast_modifiers_state_changed(eh);
const struct modifiers_state_changed *ev = cast_modifiers_state_changed(eh); if (ev->state) {
if (ev->state) { hid_listener_modifiers_pressed(ev->modifiers);
hid_listener_modifiers_pressed(ev->modifiers); } else {
} else { hid_listener_modifiers_released(ev->modifiers);
hid_listener_modifiers_released(ev->modifiers); }
} }
} return 0;
return 0;
} }
ZMK_LISTENER(hid_listener, hid_listener); ZMK_LISTENER(hid_listener, hid_listener);

124
app/src/hog.c

@ -17,21 +17,18 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/hog.h> #include <zmk/hog.h>
#include <zmk/hid.h> #include <zmk/hid.h>
enum enum {
{
HIDS_REMOTE_WAKE = BIT(0), HIDS_REMOTE_WAKE = BIT(0),
HIDS_NORMALLY_CONNECTABLE = BIT(1), HIDS_NORMALLY_CONNECTABLE = BIT(1),
}; };
struct hids_info struct hids_info {
{
u16_t version; /* version number of base USB HID Specification */ u16_t version; /* version number of base USB HID Specification */
u8_t code; /* country HID Device hardware is localized for. */ u8_t code; /* country HID Device hardware is localized for. */
u8_t flags; u8_t flags;
} __packed; } __packed;
struct hids_report struct hids_report {
{
u8_t id; /* report id */ u8_t id; /* report id */
u8_t type; /* report type */ u8_t type; /* report type */
} __packed; } __packed;
@ -42,8 +39,7 @@ static struct hids_info info = {
.flags = HIDS_NORMALLY_CONNECTABLE & HIDS_REMOTE_WAKE, .flags = HIDS_NORMALLY_CONNECTABLE & HIDS_REMOTE_WAKE,
}; };
enum enum {
{
HIDS_INPUT = 0x01, HIDS_INPUT = 0x01,
HIDS_OUTPUT = 0x02, HIDS_OUTPUT = 0x02,
HIDS_FEATURE = 0x03, HIDS_FEATURE = 0x03,
@ -63,31 +59,37 @@ static bool host_requests_notification = false;
static u8_t ctrl_point; static u8_t ctrl_point;
// static u8_t proto_mode; // static u8_t proto_mode;
static ssize_t read_hids_info(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset) static ssize_t read_hids_info(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
{ u16_t len, u16_t offset) {
return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data, sizeof(struct hids_info)); return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data,
sizeof(struct hids_info));
} }
static ssize_t read_hids_report_ref(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset) static ssize_t read_hids_report_ref(struct bt_conn *conn, const struct bt_gatt_attr *attr,
{ void *buf, u16_t len, u16_t offset) {
return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data, sizeof(struct hids_report)); return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data,
sizeof(struct hids_report));
} }
static ssize_t read_hids_report_map(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset) static ssize_t read_hids_report_map(struct bt_conn *conn, const struct bt_gatt_attr *attr,
{ void *buf, u16_t len, u16_t offset) {
return bt_gatt_attr_read(conn, attr, buf, len, offset, zmk_hid_report_desc, sizeof(zmk_hid_report_desc)); return bt_gatt_attr_read(conn, attr, buf, len, offset, zmk_hid_report_desc,
sizeof(zmk_hid_report_desc));
} }
static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset) static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
{ void *buf, u16_t len, u16_t offset) {
struct zmk_hid_keypad_report_body *report_body = &zmk_hid_get_keypad_report()->body; struct zmk_hid_keypad_report_body *report_body = &zmk_hid_get_keypad_report()->body;
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body, sizeof(struct zmk_hid_keypad_report_body)); return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
sizeof(struct zmk_hid_keypad_report_body));
} }
static ssize_t read_hids_consumer_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset) static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
{ const struct bt_gatt_attr *attr, void *buf,
u16_t len, u16_t offset) {
struct zmk_hid_consumer_report_body *report_body = &zmk_hid_get_consumer_report()->body; struct zmk_hid_consumer_report_body *report_body = &zmk_hid_get_consumer_report()->body;
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body, sizeof(struct zmk_hid_consumer_report_body)); return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
sizeof(struct zmk_hid_consumer_report_body));
} }
// static ssize_t write_proto_mode(struct bt_conn *conn, // static ssize_t write_proto_mode(struct bt_conn *conn,
@ -99,20 +101,15 @@ static ssize_t read_hids_consumer_input_report(struct bt_conn *conn, const struc
// return 0; // return 0;
// } // }
static void input_ccc_changed(const struct bt_gatt_attr *attr, u16_t value) static void input_ccc_changed(const struct bt_gatt_attr *attr, u16_t value) {
{
host_requests_notification = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0; host_requests_notification = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
} }
static ssize_t write_ctrl_point(struct bt_conn *conn, static ssize_t write_ctrl_point(struct bt_conn *conn, const struct bt_gatt_attr *attr,
const struct bt_gatt_attr *attr, const void *buf, u16_t len, u16_t offset, u8_t flags) {
const void *buf, u16_t len, u16_t offset,
u8_t flags)
{
u8_t *value = attr->user_data; u8_t *value = attr->user_data;
if (offset + len > sizeof(ctrl_point)) if (offset + len > sizeof(ctrl_point)) {
{
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
} }
@ -122,35 +119,27 @@ static ssize_t write_ctrl_point(struct bt_conn *conn,
} }
/* HID Service Declaration */ /* HID Service Declaration */
BT_GATT_SERVICE_DEFINE(hog_svc, BT_GATT_SERVICE_DEFINE(
BT_GATT_PRIMARY_SERVICE(BT_UUID_HIDS), hog_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_HIDS),
// BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_PROTOCOL_MODE, BT_GATT_CHRC_WRITE_WITHOUT_RESP, // BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_PROTOCOL_MODE, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
// BT_GATT_PERM_WRITE, NULL, write_proto_mode, &proto_mode), // BT_GATT_PERM_WRITE, NULL, write_proto_mode, &proto_mode),
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_INFO, BT_GATT_CHRC_READ, BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_INFO, BT_GATT_CHRC_READ, BT_GATT_PERM_READ, read_hids_info,
BT_GATT_PERM_READ, read_hids_info, NULL, &info), NULL, &info),
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT_MAP, BT_GATT_CHRC_READ, BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT_MAP, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
BT_GATT_PERM_READ, read_hids_report_map, NULL, NULL), read_hids_report_map, NULL, NULL),
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, read_hids_input_report, NULL, NULL),
BT_GATT_PERM_READ_ENCRYPT, BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
read_hids_input_report, NULL, NULL), BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ, read_hids_report_ref, NULL,
BT_GATT_CCC(input_ccc_changed, &input),
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT), BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ, BT_GATT_PERM_READ_ENCRYPT, read_hids_consumer_input_report, NULL, NULL),
read_hids_report_ref, NULL, &input), BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ, read_hids_report_ref, NULL,
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, &consumer_input),
BT_GATT_PERM_READ_ENCRYPT, BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
read_hids_consumer_input_report, NULL, NULL), BT_GATT_PERM_WRITE, NULL, write_ctrl_point, &ctrl_point));
BT_GATT_CCC(input_ccc_changed,
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ,
read_hids_report_ref, NULL, &consumer_input),
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT,
BT_GATT_CHRC_WRITE_WITHOUT_RESP,
BT_GATT_PERM_WRITE,
NULL, write_ctrl_point, &ctrl_point));
struct bt_conn *destination_connection() { struct bt_conn *destination_connection() {
struct bt_conn *conn; struct bt_conn *conn;
@ -165,11 +154,9 @@ struct bt_conn *destination_connection() {
} }
return conn; return conn;
} }
int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *report) int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *report) {
{
struct bt_conn *conn = destination_connection(); struct bt_conn *conn = destination_connection();
if (conn == NULL) { if (conn == NULL) {
return -ENOTCONN; return -ENOTCONN;
@ -177,15 +164,16 @@ int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *report)
LOG_DBG("Sending to NULL? %s", conn == NULL ? "yes" : "no"); LOG_DBG("Sending to NULL? %s", conn == NULL ? "yes" : "no");
return bt_gatt_notify(conn, &hog_svc.attrs[5], report, sizeof(struct zmk_hid_keypad_report_body)); return bt_gatt_notify(conn, &hog_svc.attrs[5], report,
sizeof(struct zmk_hid_keypad_report_body));
}; };
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
{
struct bt_conn *conn = destination_connection(); struct bt_conn *conn = destination_connection();
if (conn == NULL) { if (conn == NULL) {
return -ENOTCONN; return -ENOTCONN;
} }
return bt_gatt_notify(conn, &hog_svc.attrs[10], report, sizeof(struct zmk_hid_consumer_report_body)); return bt_gatt_notify(conn, &hog_svc.attrs[10], report,
sizeof(struct zmk_hid_consumer_report_body));
}; };

267
app/src/keymap.c

@ -24,33 +24,38 @@ static u8_t zmk_keymap_layer_default = 0;
#define DT_DRV_COMPAT zmk_keymap #define DT_DRV_COMPAT zmk_keymap
#define LAYER_CHILD_LEN(node) 1+ #define LAYER_CHILD_LEN(node) 1 +
#define ZMK_KEYMAP_NODE DT_DRV_INST(0) #define ZMK_KEYMAP_NODE DT_DRV_INST(0)
#define ZMK_KEYMAP_LAYERS_LEN (DT_INST_FOREACH_CHILD(0, LAYER_CHILD_LEN) 0) #define ZMK_KEYMAP_LAYERS_LEN (DT_INST_FOREACH_CHILD(0, LAYER_CHILD_LEN) 0)
#define LAYER_NODE(l) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, l) #define LAYER_NODE(l) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, l)
#define _TRANSFORM_ENTRY(idx, layer) \ #define _TRANSFORM_ENTRY(idx, layer) \
{ .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(layer, bindings, idx)), \ { \
.param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, bindings, idx, param1), (0), (DT_PHA_BY_IDX(layer, bindings, idx, param1))), \ .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(layer, bindings, idx)), \
.param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, bindings, idx, param2), (0), (DT_PHA_BY_IDX(layer, bindings, idx, param2))), \ .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, bindings, idx, param1), (0), \
}, (DT_PHA_BY_IDX(layer, bindings, idx, param1))), \
.param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, bindings, idx, param2), (0), \
#define TRANSFORMED_LAYER(node) \ (DT_PHA_BY_IDX(layer, bindings, idx, param2))), \
{ UTIL_LISTIFY(DT_PROP_LEN(node, bindings), _TRANSFORM_ENTRY, node) }, },
#define TRANSFORMED_LAYER(node) {UTIL_LISTIFY(DT_PROP_LEN(node, bindings), _TRANSFORM_ENTRY, node)},
#if ZMK_KEYMAP_HAS_SENSORS #if ZMK_KEYMAP_HAS_SENSORS
#define _TRANSFORM_SENSOR_ENTRY(idx, layer) \ #define _TRANSFORM_SENSOR_ENTRY(idx, layer) \
{ .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(layer, sensor_bindings, idx)), \ { \
.param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param1), (0), (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param1))), \ .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(layer, sensor_bindings, idx)), \
.param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param2), (0), (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param2))), \ .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param1), (0), \
}, (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param1))), \
.param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param2), (0), \
#define SENSOR_LAYER(node) \ (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param2))), \
COND_CODE_1(DT_NODE_HAS_PROP(node, sensor_bindings), \ },
({ UTIL_LISTIFY(DT_PROP_LEN(node, sensor_bindings), _TRANSFORM_SENSOR_ENTRY, node) }), \
({})), #define SENSOR_LAYER(node) \
COND_CODE_1( \
DT_NODE_HAS_PROP(node, sensor_bindings), \
({UTIL_LISTIFY(DT_PROP_LEN(node, sensor_bindings), _TRANSFORM_SENSOR_ENTRY, node)}), \
({})),
#endif /* ZMK_KEYMAP_HAS_SENSORS */ #endif /* ZMK_KEYMAP_HAS_SENSORS */
@ -62,155 +67,142 @@ static u8_t zmk_keymap_layer_default = 0;
static u32_t zmk_keymap_active_behavior_layer[ZMK_KEYMAP_LEN]; static u32_t zmk_keymap_active_behavior_layer[ZMK_KEYMAP_LEN];
static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_LEN] = { static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_LEN] = {
DT_INST_FOREACH_CHILD(0, TRANSFORMED_LAYER) DT_INST_FOREACH_CHILD(0, TRANSFORMED_LAYER)};
};
#if ZMK_KEYMAP_HAS_SENSORS #if ZMK_KEYMAP_HAS_SENSORS
static struct zmk_behavior_binding zmk_sensor_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_SENSORS_LEN] = { static struct zmk_behavior_binding zmk_sensor_keymap[ZMK_KEYMAP_LAYERS_LEN]
DT_INST_FOREACH_CHILD(0, SENSOR_LAYER) [ZMK_KEYMAP_SENSORS_LEN] = {
}; DT_INST_FOREACH_CHILD(0, SENSOR_LAYER)};
#endif /* ZMK_KEYMAP_HAS_SENSORS */ #endif /* ZMK_KEYMAP_HAS_SENSORS */
#define SET_LAYER_STATE(layer, state) \ #define SET_LAYER_STATE(layer, state) \
if (layer >= 32) \ if (layer >= 32) { \
{ \ return -EINVAL; \
return -EINVAL; \ } \
} \ WRITE_BIT(zmk_keymap_layer_state, layer, state); \
WRITE_BIT(zmk_keymap_layer_state, layer, state); \ return 0;
return 0;
bool zmk_keymap_layer_active(u8_t layer)
{
return (zmk_keymap_layer_state & (BIT(layer))) == (BIT(layer));
};
int zmk_keymap_layer_activate(u8_t layer) bool zmk_keymap_layer_active(u8_t layer) {
{ return (zmk_keymap_layer_state & (BIT(layer))) == (BIT(layer));
SET_LAYER_STATE(layer, true);
}; };
int zmk_keymap_layer_deactivate(u8_t layer) int zmk_keymap_layer_activate(u8_t layer) { SET_LAYER_STATE(layer, true); };
{
SET_LAYER_STATE(layer, false);
};
int zmk_keymap_layer_toggle(u8_t layer) int zmk_keymap_layer_deactivate(u8_t layer) { SET_LAYER_STATE(layer, false); };
{
if (zmk_keymap_layer_active(layer))
{
return zmk_keymap_layer_deactivate(layer);
}
return zmk_keymap_layer_activate(layer); int zmk_keymap_layer_toggle(u8_t layer) {
if (zmk_keymap_layer_active(layer)) {
return zmk_keymap_layer_deactivate(layer);
}
return zmk_keymap_layer_activate(layer);
}; };
bool is_active_layer(u8_t layer, u32_t layer_state) bool is_active_layer(u8_t layer, u32_t layer_state) {
{ return (layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default;
return (layer_state & BIT(layer)) == BIT(layer)
|| layer == zmk_keymap_layer_default;
} }
int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed) int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed) {
{ struct zmk_behavior_binding *binding = &zmk_keymap[layer][position];
struct zmk_behavior_binding *binding = &zmk_keymap[layer][position]; struct device *behavior;
struct device *behavior;
LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, log_strdup(binding->behavior_dev)); LOG_DBG("layer: %d position: %d, binding name: %s", layer, position,
log_strdup(binding->behavior_dev));
behavior = device_get_binding(binding->behavior_dev); behavior = device_get_binding(binding->behavior_dev);
if (!behavior) { if (!behavior) {
LOG_DBG("No behavior assigned to %d on layer %d", position, layer); LOG_DBG("No behavior assigned to %d on layer %d", position, layer);
return 1; return 1;
} }
if (pressed) { if (pressed) {
return behavior_keymap_binding_pressed(behavior, position, binding->param1, binding->param2); return behavior_keymap_binding_pressed(behavior, position, binding->param1,
} else { binding->param2);
return behavior_keymap_binding_released(behavior, position, binding->param1, binding->param2); } else {
} return behavior_keymap_binding_released(behavior, position, binding->param1,
binding->param2);
}
} }
int zmk_keymap_position_state_changed(u32_t position, bool pressed) int zmk_keymap_position_state_changed(u32_t position, bool pressed) {
{ for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--) {
for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--) u32_t layer_state =
{ pressed ? zmk_keymap_layer_state : zmk_keymap_active_behavior_layer[position];
u32_t layer_state = pressed ? zmk_keymap_layer_state : zmk_keymap_active_behavior_layer[position]; if (is_active_layer(layer, layer_state)) {
if (is_active_layer(layer, layer_state)) int ret = zmk_keymap_apply_position_state(layer, position, pressed);
{
int ret = zmk_keymap_apply_position_state(layer, position, pressed); zmk_keymap_active_behavior_layer[position] = zmk_keymap_layer_state;
zmk_keymap_active_behavior_layer[position] = zmk_keymap_layer_state; if (ret > 0) {
LOG_DBG("behavior processing to continue to next layer");
if (ret > 0) { continue;
LOG_DBG("behavior processing to continue to next layer"); } else if (ret < 0) {
continue; LOG_DBG("Behavior returned error: %d", ret);
} else if (ret < 0) { return ret;
LOG_DBG("Behavior returned error: %d", ret); } else {
return ret; return ret;
} else { }
return ret; }
} }
}
} return -ENOTSUP;
return -ENOTSUP;
} }
#if ZMK_KEYMAP_HAS_SENSORS #if ZMK_KEYMAP_HAS_SENSORS
int zmk_keymap_sensor_triggered(u8_t sensor_number, struct device *sensor) int zmk_keymap_sensor_triggered(u8_t sensor_number, struct device *sensor) {
{ for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--) {
for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--) if (((zmk_keymap_layer_state & BIT(layer)) == BIT(layer) ||
{ layer == zmk_keymap_layer_default) &&
if (((zmk_keymap_layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default) && zmk_sensor_keymap[layer] != NULL) zmk_sensor_keymap[layer] != NULL) {
{ struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_number];
struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_number]; struct device *behavior;
struct device *behavior; int ret;
int ret;
LOG_DBG("layer: %d sensor_number: %d, binding name: %s", layer, sensor_number,
LOG_DBG("layer: %d sensor_number: %d, binding name: %s", layer, sensor_number, log_strdup(binding->behavior_dev)); log_strdup(binding->behavior_dev));
behavior = device_get_binding(binding->behavior_dev); behavior = device_get_binding(binding->behavior_dev);
if (!behavior) { if (!behavior) {
LOG_DBG("No behavior assigned to %d on layer %d", sensor_number, layer); LOG_DBG("No behavior assigned to %d on layer %d", sensor_number, layer);
continue; continue;
} }
ret = behavior_sensor_keymap_binding_triggered(behavior, sensor, binding->param1, binding->param2); ret = behavior_sensor_keymap_binding_triggered(behavior, sensor, binding->param1,
binding->param2);
if (ret > 0) {
LOG_DBG("behavior processing to continue to next layer"); if (ret > 0) {
continue; LOG_DBG("behavior processing to continue to next layer");
} else if (ret < 0) { continue;
LOG_DBG("Behavior returned error: %d", ret); } else if (ret < 0) {
return ret; LOG_DBG("Behavior returned error: %d", ret);
} else { return ret;
return ret; } else {
} return ret;
} }
} }
}
return -ENOTSUP;
return -ENOTSUP;
} }
#endif /* ZMK_KEYMAP_HAS_SENSORS */ #endif /* ZMK_KEYMAP_HAS_SENSORS */
int keymap_listener(const struct zmk_event_header *eh) int keymap_listener(const struct zmk_event_header *eh) {
{ if (is_position_state_changed(eh)) {
if (is_position_state_changed(eh)) { const struct position_state_changed *ev = cast_position_state_changed(eh);
const struct position_state_changed *ev = cast_position_state_changed(eh); return zmk_keymap_position_state_changed(ev->position, ev->state);
return zmk_keymap_position_state_changed(ev->position, ev->state);
#if ZMK_KEYMAP_HAS_SENSORS #if ZMK_KEYMAP_HAS_SENSORS
} else if (is_sensor_event(eh)) { } else if (is_sensor_event(eh)) {
const struct sensor_event *ev = cast_sensor_event(eh); const struct sensor_event *ev = cast_sensor_event(eh);
return zmk_keymap_sensor_triggered(ev->sensor_number, ev->sensor); return zmk_keymap_sensor_triggered(ev->sensor_number, ev->sensor);
#endif /* ZMK_KEYMAP_HAS_SENSORS */ #endif /* ZMK_KEYMAP_HAS_SENSORS */
} }
return -ENOTSUP; return -ENOTSUP;
} }
ZMK_LISTENER(keymap, keymap_listener); ZMK_LISTENER(keymap, keymap_listener);
@ -219,4 +211,3 @@ ZMK_SUBSCRIPTION(keymap, position_state_changed);
#if ZMK_KEYMAP_HAS_SENSORS #if ZMK_KEYMAP_HAS_SENSORS
ZMK_SUBSCRIPTION(keymap, sensor_event); ZMK_SUBSCRIPTION(keymap, sensor_event);
#endif /* ZMK_KEYMAP_HAS_SENSORS */ #endif /* ZMK_KEYMAP_HAS_SENSORS */

78
app/src/kscan.c

@ -18,61 +18,55 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define ZMK_KSCAN_EVENT_STATE_PRESSED 0 #define ZMK_KSCAN_EVENT_STATE_PRESSED 0
#define ZMK_KSCAN_EVENT_STATE_RELEASED 1 #define ZMK_KSCAN_EVENT_STATE_RELEASED 1
struct zmk_kscan_event struct zmk_kscan_event {
{ u32_t row;
u32_t row; u32_t column;
u32_t column; u32_t state;
u32_t state;
}; };
struct zmk_kscan_msg_processor struct zmk_kscan_msg_processor {
{ struct k_work work;
struct k_work work;
} msg_processor; } msg_processor;
K_MSGQ_DEFINE(zmk_kscan_msgq, sizeof(struct zmk_kscan_event), CONFIG_ZMK_KSCAN_EVENT_QUEUE_SIZE, 4); K_MSGQ_DEFINE(zmk_kscan_msgq, sizeof(struct zmk_kscan_event), CONFIG_ZMK_KSCAN_EVENT_QUEUE_SIZE, 4);
static void zmk_kscan_callback(struct device *dev, u32_t row, u32_t column, bool pressed) static void zmk_kscan_callback(struct device *dev, u32_t row, u32_t column, bool pressed) {
{ struct zmk_kscan_event ev = {
struct zmk_kscan_event ev = { .row = row,
.row = row, .column = column,
.column = column, .state = (pressed ? ZMK_KSCAN_EVENT_STATE_PRESSED : ZMK_KSCAN_EVENT_STATE_RELEASED)};
.state = (pressed ? ZMK_KSCAN_EVENT_STATE_PRESSED : ZMK_KSCAN_EVENT_STATE_RELEASED)};
k_msgq_put(&zmk_kscan_msgq, &ev, K_NO_WAIT); k_msgq_put(&zmk_kscan_msgq, &ev, K_NO_WAIT);
k_work_submit(&msg_processor.work); k_work_submit(&msg_processor.work);
} }
void zmk_kscan_process_msgq(struct k_work *item) void zmk_kscan_process_msgq(struct k_work *item) {
{ struct zmk_kscan_event ev;
struct zmk_kscan_event ev;
while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0) while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0) {
{ bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED); u32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column);
u32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column); struct position_state_changed *pos_ev;
struct position_state_changed *pos_ev; LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s\n", ev.row, ev.column, position,
LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s\n", ev.row, ev.column, position, (pressed ? "true" : "false")); (pressed ? "true" : "false"));
pos_ev = new_position_state_changed(); pos_ev = new_position_state_changed();
pos_ev->state = pressed; pos_ev->state = pressed;
pos_ev->position = position; pos_ev->position = position;
ZMK_EVENT_RAISE(pos_ev); ZMK_EVENT_RAISE(pos_ev);
} }
} }
int zmk_kscan_init(char *name) int zmk_kscan_init(char *name) {
{ struct device *dev = device_get_binding(name);
struct device *dev = device_get_binding(name); if (dev == NULL) {
if (dev == NULL) LOG_ERR("Failed to get the KSCAN device");
{ return -EINVAL;
LOG_ERR("Failed to get the KSCAN device"); }
return -EINVAL;
}
k_work_init(&msg_processor.work, zmk_kscan_process_msgq); k_work_init(&msg_processor.work, zmk_kscan_process_msgq);
kscan_config(dev, zmk_kscan_callback); kscan_config(dev, zmk_kscan_callback);
kscan_enable_callback(dev); kscan_enable_callback(dev);
return 0; return 0;
} }

63
app/src/kscan_composite.c

@ -15,37 +15,31 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define MATRIX_ROWS DT_PROP(MATRIX_NODE_ID, rows) #define MATRIX_ROWS DT_PROP(MATRIX_NODE_ID, rows)
#define MATRIX_COLS DT_PROP(MATRIX_NODE_ID, columns) #define MATRIX_COLS DT_PROP(MATRIX_NODE_ID, columns)
struct kscan_composite_child_config struct kscan_composite_child_config {
{
char *label; char *label;
u8_t row_offset; u8_t row_offset;
u8_t column_offset; u8_t column_offset;
}; };
#define CHILD_CONFIG(inst) \ #define CHILD_CONFIG(inst) \
{ \ {.label = DT_LABEL(DT_PHANDLE(inst, kscan)), \
.label = DT_LABEL(DT_PHANDLE(inst, kscan)), \ .row_offset = DT_PROP(inst, row_offset), \
.row_offset = DT_PROP(inst, row_offset), \ .column_offset = DT_PROP(inst, column_offset)},
.column_offset = DT_PROP(inst, column_offset)},
const struct kscan_composite_child_config kscan_composite_children[] = { const struct kscan_composite_child_config kscan_composite_children[] = {
DT_FOREACH_CHILD(MATRIX_NODE_ID, CHILD_CONFIG)}; DT_FOREACH_CHILD(MATRIX_NODE_ID, CHILD_CONFIG)};
struct kscan_composite_config struct kscan_composite_config {};
{
};
struct kscan_composite_data struct kscan_composite_data {
{
kscan_callback_t callback; kscan_callback_t callback;
struct device *dev; struct device *dev;
}; };
static int kscan_composite_enable_callback(struct device *dev) static int kscan_composite_enable_callback(struct device *dev) {
{ for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]);
for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); i++) i++) {
{
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
kscan_enable_callback(device_get_binding(cfg->label)); kscan_enable_callback(device_get_binding(cfg->label));
@ -53,10 +47,9 @@ static int kscan_composite_enable_callback(struct device *dev)
return 0; return 0;
} }
static int kscan_composite_disable_callback(struct device *dev) static int kscan_composite_disable_callback(struct device *dev) {
{ for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]);
for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); i++) i++) {
{
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
kscan_disable_callback(device_get_binding(cfg->label)); kscan_disable_callback(device_get_binding(cfg->label));
@ -64,18 +57,17 @@ static int kscan_composite_disable_callback(struct device *dev)
return 0; return 0;
} }
static void kscan_composite_child_callback(struct device *child_dev, u32_t row, u32_t column, bool pressed) static void kscan_composite_child_callback(struct device *child_dev, u32_t row, u32_t column,
{ bool pressed) {
// TODO: Ideally we can get this passed into our callback! // TODO: Ideally we can get this passed into our callback!
struct device *dev = device_get_binding(DT_INST_LABEL(0)); struct device *dev = device_get_binding(DT_INST_LABEL(0));
struct kscan_composite_data *data = dev->driver_data; struct kscan_composite_data *data = dev->driver_data;
for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); i++) for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]);
{ i++) {
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
if (device_get_binding(cfg->label) != child_dev) if (device_get_binding(cfg->label) != child_dev) {
{
continue; continue;
} }
@ -83,17 +75,15 @@ static void kscan_composite_child_callback(struct device *child_dev, u32_t row,
} }
} }
static int kscan_composite_configure(struct device *dev, kscan_callback_t callback) static int kscan_composite_configure(struct device *dev, kscan_callback_t callback) {
{
struct kscan_composite_data *data = dev->driver_data; struct kscan_composite_data *data = dev->driver_data;
if (!callback) if (!callback) {
{
return -EINVAL; return -EINVAL;
} }
for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); i++) for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]);
{ i++) {
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
kscan_config(device_get_binding(cfg->label), &kscan_composite_child_callback); kscan_config(device_get_binding(cfg->label), &kscan_composite_child_callback);
@ -104,8 +94,7 @@ static int kscan_composite_configure(struct device *dev, kscan_callback_t callba
return 0; return 0;
} }
static int kscan_composite_init(struct device *dev) static int kscan_composite_init(struct device *dev) {
{
struct kscan_composite_data *data = dev->driver_data; struct kscan_composite_data *data = dev->driver_data;
data->dev = dev; data->dev = dev;
@ -123,8 +112,6 @@ static const struct kscan_composite_config kscan_composite_config = {};
static struct kscan_composite_data kscan_composite_data; static struct kscan_composite_data kscan_composite_data;
DEVICE_AND_API_INIT(kscan_composite, DT_INST_LABEL(0), kscan_composite_init, DEVICE_AND_API_INIT(kscan_composite, DT_INST_LABEL(0), kscan_composite_init, &kscan_composite_data,
&kscan_composite_data, &kscan_composite_config, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&kscan_composite_config,
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&mock_driver_api); &mock_driver_api);

119
app/src/kscan_mock.c

@ -15,8 +15,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <dt-bindings/zmk/kscan-mock.h> #include <dt-bindings/zmk/kscan-mock.h>
struct kscan_mock_data struct kscan_mock_data {
{
kscan_callback_t callback; kscan_callback_t callback;
u8_t event_index; u8_t event_index;
@ -24,20 +23,17 @@ struct kscan_mock_data
struct device *dev; struct device *dev;
}; };
static int kscan_mock_disable_callback(struct device *dev) static int kscan_mock_disable_callback(struct device *dev) {
{
struct kscan_mock_data *data = dev->driver_data; struct kscan_mock_data *data = dev->driver_data;
k_delayed_work_cancel(&data->work); k_delayed_work_cancel(&data->work);
return 0; return 0;
} }
static int kscan_mock_configure(struct device *dev, kscan_callback_t callback) static int kscan_mock_configure(struct device *dev, kscan_callback_t callback) {
{
struct kscan_mock_data *data = dev->driver_data; struct kscan_mock_data *data = dev->driver_data;
if (!callback) if (!callback) {
{
return -EINVAL; return -EINVAL;
} }
@ -47,64 +43,53 @@ static int kscan_mock_configure(struct device *dev, kscan_callback_t callback)
return 0; return 0;
} }
#define MOCK_INST_INIT(n) \ #define MOCK_INST_INIT(n) \
struct kscan_mock_config_##n \ struct kscan_mock_config_##n { \
{ \ u32_t events[DT_INST_PROP_LEN(n, events)]; \
u32_t events[DT_INST_PROP_LEN(n, events)]; \ bool exit_after; \
bool exit_after; \ }; \
}; \ static void kscan_mock_schedule_next_event_##n(struct device *dev) { \
static void kscan_mock_schedule_next_event_##n(struct device *dev) \ struct kscan_mock_data *data = dev->driver_data; \
{ \ const struct kscan_mock_config_##n *cfg = dev->config_info; \
struct kscan_mock_data *data = dev->driver_data; \ if (data->event_index < DT_INST_PROP_LEN(n, events)) { \
const struct kscan_mock_config_##n *cfg = dev->config_info; \ u32_t ev = cfg->events[data->event_index]; \
if (data->event_index < DT_INST_PROP_LEN(n, events)) \ LOG_DBG("delaying next keypress: %d", ZMK_MOCK_MSEC(ev)); \
{ \ k_delayed_work_submit(&data->work, K_MSEC(ZMK_MOCK_MSEC(ev))); \
u32_t ev = cfg->events[data->event_index]; \ } else if (cfg->exit_after) { \
LOG_DBG("delaying next keypress: %d", ZMK_MOCK_MSEC(ev)); \ LOG_DBG("Exiting"); \
k_delayed_work_submit(&data->work, K_MSEC(ZMK_MOCK_MSEC(ev))); \ exit(0); \
} else if (cfg->exit_after) { \ } \
LOG_DBG("Exiting"); \ } \
exit(0); \ static void kscan_mock_work_handler_##n(struct k_work *work) { \
} \ struct kscan_mock_data *data = CONTAINER_OF(work, struct kscan_mock_data, work); \
} \ const struct kscan_mock_config_##n *cfg = data->dev->config_info; \
static void kscan_mock_work_handler_##n(struct k_work *work) \ u32_t ev = cfg->events[data->event_index]; \
{ \ LOG_DBG("ev %u row %d column %d state %d\n", ev, ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), \
struct kscan_mock_data *data = \ ZMK_MOCK_IS_PRESS(ev)); \
CONTAINER_OF(work, struct kscan_mock_data, work); \ data->callback(data->dev, ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev)); \
const struct kscan_mock_config_##n *cfg = data->dev->config_info; \ kscan_mock_schedule_next_event_##n(data->dev); \
u32_t ev = cfg->events[data->event_index]; \ data->event_index++; \
LOG_DBG("ev %u row %d column %d state %d\n", ev, \ } \
ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev)); \ static int kscan_mock_init_##n(struct device *dev) { \
data->callback(data->dev, \ struct kscan_mock_data *data = dev->driver_data; \
ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev)); \ data->dev = dev; \
kscan_mock_schedule_next_event_##n(data->dev); \ k_delayed_work_init(&data->work, kscan_mock_work_handler_##n); \
data->event_index++; \ return 0; \
} \ } \
static int kscan_mock_init_##n(struct device *dev) \ static int kscan_mock_enable_callback_##n(struct device *dev) { \
{ \ kscan_mock_schedule_next_event_##n(dev); \
struct kscan_mock_data *data = dev->driver_data; \ return 0; \
data->dev = dev; \ } \
k_delayed_work_init(&data->work, kscan_mock_work_handler_##n); \ static const struct kscan_driver_api mock_driver_api_##n = { \
return 0; \ .config = kscan_mock_configure, \
} \ .enable_callback = kscan_mock_enable_callback_##n, \
static int kscan_mock_enable_callback_##n(struct device *dev) \ .disable_callback = kscan_mock_disable_callback, \
{ \ }; \
kscan_mock_schedule_next_event_##n(dev); \ static struct kscan_mock_data kscan_mock_data_##n; \
return 0; \ static const struct kscan_mock_config_##n kscan_mock_config_##n = { \
} \ .events = DT_INST_PROP(n, events), .exit_after = DT_INST_PROP(n, exit_after)}; \
static const struct kscan_driver_api mock_driver_api_##n = { \ DEVICE_AND_API_INIT(kscan_mock_##n, DT_INST_LABEL(n), kscan_mock_init_##n, \
.config = kscan_mock_configure, \ &kscan_mock_data_##n, &kscan_mock_config_##n, APPLICATION, \
.enable_callback = kscan_mock_enable_callback_##n, \ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &mock_driver_api_##n);
.disable_callback = kscan_mock_disable_callback, \
}; \
static struct kscan_mock_data kscan_mock_data_##n; \
static const struct kscan_mock_config_##n kscan_mock_config_##n = { \
.events = DT_INST_PROP(n, events), \
.exit_after = DT_INST_PROP(n, exit_after) }; \
DEVICE_AND_API_INIT(kscan_mock_##n, DT_INST_LABEL(n), kscan_mock_init_##n, \
&kscan_mock_data_##n, \
&kscan_mock_config_##n, \
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&mock_driver_api_##n);
DT_INST_FOREACH_STATUS_OKAY(MOCK_INST_INIT) DT_INST_FOREACH_STATUS_OKAY(MOCK_INST_INIT)

20
app/src/main.c

@ -18,20 +18,18 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL);
#define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID) #define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID)
void main(void) void main(void) {
{ LOG_INF("Welcome to ZMK!\n");
LOG_INF("Welcome to ZMK!\n");
if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0) if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0) {
{ return;
return; }
}
#ifdef CONFIG_ZMK_DISPLAY #ifdef CONFIG_ZMK_DISPLAY
zmk_display_init(); zmk_display_init();
while (1) { while (1) {
zmk_display_task_handler(); zmk_display_task_handler();
} }
#endif /* CONFIG_ZMK_DISPLAY */ #endif /* CONFIG_ZMK_DISPLAY */
} }

11
app/src/matrix_transform.c

@ -11,16 +11,15 @@
#ifdef ZMK_KEYMAP_TRANSFORM_NODE #ifdef ZMK_KEYMAP_TRANSFORM_NODE
#define _TRANSFORM_ENTRY(i, _) \ #define _TRANSFORM_ENTRY(i, _) \
[(KT_ROW(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i)) * ZMK_MATRIX_COLS) + KT_COL(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i))] = i, [(KT_ROW(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i)) * ZMK_MATRIX_COLS) + \
KT_COL(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i))] = i,
static u32_t transform[] = static u32_t transform[] = {UTIL_LISTIFY(ZMK_KEYMAP_LEN, _TRANSFORM_ENTRY, 0)};
{ UTIL_LISTIFY(ZMK_KEYMAP_LEN, _TRANSFORM_ENTRY, 0) };
#endif #endif
u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column) u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column) {
{
u32_t matrix_index; u32_t matrix_index;
#if DT_NODE_HAS_PROP(ZMK_KEYMAP_TRANSFORM_NODE, col_offset) #if DT_NODE_HAS_PROP(ZMK_KEYMAP_TRANSFORM_NODE, col_offset)

205
app/src/rgb_underglow.c

@ -18,8 +18,8 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define STRIP_LABEL DT_LABEL(DT_CHOSEN(zmk_underglow)) #define STRIP_LABEL DT_LABEL(DT_CHOSEN(zmk_underglow))
#define STRIP_NUM_PIXELS DT_PROP(DT_CHOSEN(zmk_underglow), chain_length) #define STRIP_NUM_PIXELS DT_PROP(DT_CHOSEN(zmk_underglow), chain_length)
enum rgb_underglow_effect { enum rgb_underglow_effect {
UNDERGLOW_EFFECT_SOLID, UNDERGLOW_EFFECT_SOLID,
@ -30,19 +30,19 @@ enum rgb_underglow_effect {
}; };
struct led_hsb { struct led_hsb {
u16_t h; u16_t h;
u8_t s; u8_t s;
u8_t b; u8_t b;
}; };
struct rgb_underglow_state { struct rgb_underglow_state {
u16_t hue; u16_t hue;
u8_t saturation; u8_t saturation;
u8_t brightness; u8_t brightness;
u8_t animation_speed; u8_t animation_speed;
u8_t current_effect; u8_t current_effect;
u16_t animation_step; u16_t animation_step;
bool on; bool on;
}; };
struct rgb_underglow_state state; struct rgb_underglow_state state;
@ -51,8 +51,7 @@ struct device *led_strip;
struct led_rgb pixels[STRIP_NUM_PIXELS]; struct led_rgb pixels[STRIP_NUM_PIXELS];
static struct led_rgb hsb_to_rgb(struct led_hsb hsb) static struct led_rgb hsb_to_rgb(struct led_hsb hsb) {
{
double r, g, b; double r, g, b;
u8_t i = hsb.h / 60; u8_t i = hsb.h / 60;
@ -63,44 +62,63 @@ static struct led_rgb hsb_to_rgb(struct led_hsb hsb)
double q = v * (1 - f * s); double q = v * (1 - f * s);
double t = v * (1 - (1 - f) * s); double t = v * (1 - (1 - f) * s);
switch (i % 6) switch (i % 6) {
{ case 0:
case 0: r = v; g = t; b = p; break; r = v;
case 1: r = q; g = v; b = p; break; g = t;
case 2: r = p; g = v; b = t; break; b = p;
case 3: r = p; g = q; b = v; break; break;
case 4: r = t; g = p; b = v; break; case 1:
case 5: r = v; g = p; b = q; break; r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
} }
struct led_rgb rgb = { r: r*255, g: g*255, b: b*255 }; struct led_rgb rgb = {r : r * 255, g : g * 255, b : b * 255};
return rgb; return rgb;
} }
static void zmk_rgb_underglow_effect_solid() static void zmk_rgb_underglow_effect_solid() {
{ for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
for (int i=0; i<STRIP_NUM_PIXELS; i++)
{
int hue = state.hue; int hue = state.hue;
int sat = state.saturation; int sat = state.saturation;
int brt = state.brightness; int brt = state.brightness;
struct led_hsb hsb = { hue, sat, brt }; struct led_hsb hsb = {hue, sat, brt};
pixels[i] = hsb_to_rgb(hsb); pixels[i] = hsb_to_rgb(hsb);
} }
} }
static void zmk_rgb_underglow_effect_breathe() static void zmk_rgb_underglow_effect_breathe() {
{ for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
for (int i=0; i<STRIP_NUM_PIXELS; i++)
{
int hue = state.hue; int hue = state.hue;
int sat = state.saturation; int sat = state.saturation;
int brt = abs(state.animation_step - 1200) / 12; int brt = abs(state.animation_step - 1200) / 12;
struct led_hsb hsb = { hue, sat, brt }; struct led_hsb hsb = {hue, sat, brt};
pixels[i] = hsb_to_rgb(hsb); pixels[i] = hsb_to_rgb(hsb);
} }
@ -112,15 +130,13 @@ static void zmk_rgb_underglow_effect_breathe()
} }
} }
static void zmk_rgb_underglow_effect_spectrum() static void zmk_rgb_underglow_effect_spectrum() {
{ for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
for (int i=0; i<STRIP_NUM_PIXELS; i++)
{
int hue = state.animation_step; int hue = state.animation_step;
int sat = state.saturation; int sat = state.saturation;
int brt = state.brightness; int brt = state.brightness;
struct led_hsb hsb = { hue, sat, brt }; struct led_hsb hsb = {hue, sat, brt};
pixels[i] = hsb_to_rgb(hsb); pixels[i] = hsb_to_rgb(hsb);
} }
@ -129,15 +145,13 @@ static void zmk_rgb_underglow_effect_spectrum()
state.animation_step = state.animation_step % 360; state.animation_step = state.animation_step % 360;
} }
static void zmk_rgb_underglow_effect_swirl() static void zmk_rgb_underglow_effect_swirl() {
{ for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
for (int i=0; i<STRIP_NUM_PIXELS; i++)
{
int hue = (360 / STRIP_NUM_PIXELS * i + state.animation_step) % 360; int hue = (360 / STRIP_NUM_PIXELS * i + state.animation_step) % 360;
int sat = state.saturation; int sat = state.saturation;
int brt = state.brightness; int brt = state.brightness;
struct led_hsb hsb = { hue, sat, brt }; struct led_hsb hsb = {hue, sat, brt};
pixels[i] = hsb_to_rgb(hsb); pixels[i] = hsb_to_rgb(hsb);
} }
@ -146,22 +160,20 @@ static void zmk_rgb_underglow_effect_swirl()
state.animation_step = state.animation_step % 360; state.animation_step = state.animation_step % 360;
} }
static void zmk_rgb_underglow_tick(struct k_work *work) static void zmk_rgb_underglow_tick(struct k_work *work) {
{ switch (state.current_effect) {
switch (state.current_effect) case UNDERGLOW_EFFECT_SOLID:
{ zmk_rgb_underglow_effect_solid();
case UNDERGLOW_EFFECT_SOLID: break;
zmk_rgb_underglow_effect_solid(); case UNDERGLOW_EFFECT_BREATHE:
break; zmk_rgb_underglow_effect_breathe();
case UNDERGLOW_EFFECT_BREATHE: break;
zmk_rgb_underglow_effect_breathe(); case UNDERGLOW_EFFECT_SPECTRUM:
break; zmk_rgb_underglow_effect_spectrum();
case UNDERGLOW_EFFECT_SPECTRUM: break;
zmk_rgb_underglow_effect_spectrum(); case UNDERGLOW_EFFECT_SWIRL:
break; zmk_rgb_underglow_effect_swirl();
case UNDERGLOW_EFFECT_SWIRL: break;
zmk_rgb_underglow_effect_swirl();
break;
} }
led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS); led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS);
@ -169,31 +181,29 @@ static void zmk_rgb_underglow_tick(struct k_work *work)
K_WORK_DEFINE(underglow_work, zmk_rgb_underglow_tick); K_WORK_DEFINE(underglow_work, zmk_rgb_underglow_tick);
static void zmk_rgb_underglow_tick_handler(struct k_timer *timer) static void zmk_rgb_underglow_tick_handler(struct k_timer *timer) {
{
k_work_submit(&underglow_work); k_work_submit(&underglow_work);
} }
K_TIMER_DEFINE(underglow_tick, zmk_rgb_underglow_tick_handler, NULL); K_TIMER_DEFINE(underglow_tick, zmk_rgb_underglow_tick_handler, NULL);
static int zmk_rgb_underglow_init(struct device *_arg) static int zmk_rgb_underglow_init(struct device *_arg) {
{ led_strip = device_get_binding(STRIP_LABEL);
led_strip = device_get_binding(STRIP_LABEL); if (led_strip) {
if (led_strip) { LOG_INF("Found LED strip device %s", STRIP_LABEL);
LOG_INF("Found LED strip device %s", STRIP_LABEL); } else {
} else { LOG_ERR("LED strip device %s not found", STRIP_LABEL);
LOG_ERR("LED strip device %s not found", STRIP_LABEL); return -EINVAL;
return -EINVAL; }
}
state = (struct rgb_underglow_state){ state = (struct rgb_underglow_state){
hue: 0, hue : 0,
saturation: 100, saturation : 100,
brightness: 100, brightness : 100,
animation_speed: 3, animation_speed : 3,
current_effect: 0, current_effect : 0,
animation_step: 0, animation_step : 0,
on: true on : true
}; };
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
@ -201,9 +211,9 @@ static int zmk_rgb_underglow_init(struct device *_arg)
return 0; return 0;
} }
int zmk_rgb_underglow_cycle_effect(int direction) int zmk_rgb_underglow_cycle_effect(int direction) {
{ if (!led_strip)
if (!led_strip) return -ENODEV; return -ENODEV;
if (state.current_effect == 0 && direction < 0) { if (state.current_effect == 0 && direction < 0) {
state.current_effect = UNDERGLOW_EFFECT_NUMBER - 1; state.current_effect = UNDERGLOW_EFFECT_NUMBER - 1;
@ -221,9 +231,9 @@ int zmk_rgb_underglow_cycle_effect(int direction)
return 0; return 0;
} }
int zmk_rgb_underglow_toggle() int zmk_rgb_underglow_toggle() {
{ if (!led_strip)
if (!led_strip) return -ENODEV; return -ENODEV;
state.on = !state.on; state.on = !state.on;
@ -232,9 +242,8 @@ int zmk_rgb_underglow_toggle()
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
} else { } else {
for (int i=0; i<STRIP_NUM_PIXELS; i++) for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
{ pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0};
pixels[i] = (struct led_rgb){ r: 0, g: 0, b: 0};
} }
led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS); led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS);
@ -245,9 +254,9 @@ int zmk_rgb_underglow_toggle()
return 0; return 0;
} }
int zmk_rgb_underglow_change_hue(int direction) int zmk_rgb_underglow_change_hue(int direction) {
{ if (!led_strip)
if (!led_strip) return -ENODEV; return -ENODEV;
if (state.hue == 0 && direction < 0) { if (state.hue == 0 && direction < 0) {
state.hue = 350; state.hue = 350;
@ -263,9 +272,9 @@ int zmk_rgb_underglow_change_hue(int direction)
return 0; return 0;
} }
int zmk_rgb_underglow_change_sat(int direction) int zmk_rgb_underglow_change_sat(int direction) {
{ if (!led_strip)
if (!led_strip) return -ENODEV; return -ENODEV;
if (state.saturation == 0 && direction < 0) { if (state.saturation == 0 && direction < 0) {
return 0; return 0;
@ -280,9 +289,9 @@ int zmk_rgb_underglow_change_sat(int direction)
return 0; return 0;
} }
int zmk_rgb_underglow_change_brt(int direction) int zmk_rgb_underglow_change_brt(int direction) {
{ if (!led_strip)
if (!led_strip) return -ENODEV; return -ENODEV;
if (state.brightness == 0 && direction < 0) { if (state.brightness == 0 && direction < 0) {
return 0; return 0;
@ -297,9 +306,9 @@ int zmk_rgb_underglow_change_brt(int direction)
return 0; return 0;
} }
int zmk_rgb_underglow_change_spd(int direction) int zmk_rgb_underglow_change_spd(int direction) {
{ if (!led_strip)
if (!led_strip) return -ENODEV; return -ENODEV;
if (state.animation_speed == 1 && direction < 0) { if (state.animation_speed == 1 && direction < 0) {
return 0; return 0;
@ -314,6 +323,4 @@ int zmk_rgb_underglow_change_spd(int direction)
return 0; return 0;
} }
SYS_INIT(zmk_rgb_underglow_init, SYS_INIT(zmk_rgb_underglow_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
APPLICATION,
CONFIG_APPLICATION_INIT_PRIORITY);

30
app/src/sensors.c

@ -24,17 +24,17 @@ struct sensors_data_item {
struct sensor_trigger trigger; struct sensor_trigger trigger;
}; };
#define _SENSOR_ITEM(node) {.dev = NULL, .trigger = { .type = SENSOR_TRIG_DELTA, .chan = SENSOR_CHAN_ROTATION } }, #define _SENSOR_ITEM(node) \
#define SENSOR_ITEM(idx, _) COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx),okay), (_SENSOR_ITEM(ZMK_KEYMAP_SENSORS_BY_IDX(idx))),()) {.dev = NULL, .trigger = {.type = SENSOR_TRIG_DELTA, .chan = SENSOR_CHAN_ROTATION}},
#define SENSOR_ITEM(idx, _) \
COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx), okay), \
(_SENSOR_ITEM(ZMK_KEYMAP_SENSORS_BY_IDX(idx))), ())
static struct sensors_data_item sensors[] = { static struct sensors_data_item sensors[] = {UTIL_LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_ITEM, 0)};
UTIL_LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_ITEM, 0)
};
static void zmk_sensors_trigger_handler(struct device *dev, struct sensor_trigger *trigger) static void zmk_sensors_trigger_handler(struct device *dev, struct sensor_trigger *trigger) {
{
int err; int err;
struct sensors_data_item * item = CONTAINER_OF(trigger, struct sensors_data_item, trigger); struct sensors_data_item *item = CONTAINER_OF(trigger, struct sensors_data_item, trigger);
struct sensor_event *event; struct sensor_event *event;
LOG_DBG("sensor %d", item->sensor_number); LOG_DBG("sensor %d", item->sensor_number);
@ -52,8 +52,7 @@ static void zmk_sensors_trigger_handler(struct device *dev, struct sensor_trigge
ZMK_EVENT_RAISE(event); ZMK_EVENT_RAISE(event);
} }
static void zmk_sensors_init_item(const char *node, u8_t i, u8_t abs_i) static void zmk_sensors_init_item(const char *node, u8_t i, u8_t abs_i) {
{
LOG_DBG("Init %s at index %d with sensor_number %d", node, i, abs_i); LOG_DBG("Init %s at index %d with sensor_number %d", node, i, abs_i);
sensors[i].dev = device_get_binding(node); sensors[i].dev = device_get_binding(node);
@ -68,10 +67,11 @@ static void zmk_sensors_init_item(const char *node, u8_t i, u8_t abs_i)
} }
#define _SENSOR_INIT(node) zmk_sensors_init_item(DT_LABEL(node), local_index++, absolute_index++); #define _SENSOR_INIT(node) zmk_sensors_init_item(DT_LABEL(node), local_index++, absolute_index++);
#define SENSOR_INIT(idx, _i) COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx),okay), (_SENSOR_INIT(ZMK_KEYMAP_SENSORS_BY_IDX(idx))),(absolute_index++;)) #define SENSOR_INIT(idx, _i) \
COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx), okay), \
(_SENSOR_INIT(ZMK_KEYMAP_SENSORS_BY_IDX(idx))), (absolute_index++;))
static int zmk_sensors_init(struct device *_arg) static int zmk_sensors_init(struct device *_arg) {
{
int local_index = 0; int local_index = 0;
int absolute_index = 0; int absolute_index = 0;
@ -79,8 +79,6 @@ static int zmk_sensors_init(struct device *_arg)
return 0; return 0;
} }
SYS_INIT(zmk_sensors_init, SYS_INIT(zmk_sensors_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
APPLICATION,
CONFIG_APPLICATION_INIT_PRIORITY);
#endif /* ZMK_KEYMAP_HAS_SENSORS */ #endif /* ZMK_KEYMAP_HAS_SENSORS */

475
app/src/split/bluetooth/central.c

@ -33,303 +33,290 @@ static struct bt_uuid_128 uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID);
static struct bt_gatt_discover_params discover_params; static struct bt_gatt_discover_params discover_params;
static struct bt_gatt_subscribe_params subscribe_params; static struct bt_gatt_subscribe_params subscribe_params;
static u8_t split_central_notify_func(struct bt_conn *conn, static u8_t split_central_notify_func(struct bt_conn *conn, struct bt_gatt_subscribe_params *params,
struct bt_gatt_subscribe_params *params, const void *data, u16_t length) {
const void *data, u16_t length) static u8_t position_state[POSITION_STATE_DATA_LEN];
{
static u8_t position_state[POSITION_STATE_DATA_LEN]; u8_t changed_positions[POSITION_STATE_DATA_LEN];
u8_t changed_positions[POSITION_STATE_DATA_LEN]; if (!data) {
LOG_DBG("[UNSUBSCRIBED]");
if (!data) { params->value_handle = 0U;
LOG_DBG("[UNSUBSCRIBED]"); return BT_GATT_ITER_STOP;
params->value_handle = 0U; }
return BT_GATT_ITER_STOP;
} LOG_DBG("[NOTIFICATION] data %p length %u", data, length);
LOG_DBG("[NOTIFICATION] data %p length %u", data, length); for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
changed_positions[i] = ((u8_t *)data)[i] ^ position_state[i];
for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) { position_state[i] = ((u8_t *)data)[i];
changed_positions[i] = ((u8_t *)data)[i] ^ position_state[i]; }
position_state[i] = ((u8_t *)data)[i];
} for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
for (int j = 0; j < 8; j++) {
for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) { if (changed_positions[i] & BIT(j)) {
for (int j = 0; j < 8; j++) { u32_t position = (i * 8) + j;
if (changed_positions[i] & BIT(j)) { bool pressed = position_state[i] & BIT(j);
u32_t position = (i * 8) + j; struct position_state_changed *pos_ev = new_position_state_changed();
bool pressed = position_state[i] & BIT(j); pos_ev->position = position;
struct position_state_changed *pos_ev = new_position_state_changed(); pos_ev->state = pressed;
pos_ev->position = position;
pos_ev->state = pressed; LOG_DBG("Trigger key position state change for %d", position);
ZMK_EVENT_RAISE(pos_ev);
LOG_DBG("Trigger key position state change for %d", position); }
ZMK_EVENT_RAISE(pos_ev); }
} }
}
} return BT_GATT_ITER_CONTINUE;
return BT_GATT_ITER_CONTINUE;
} }
static int split_central_subscribe(struct bt_conn *conn) static int split_central_subscribe(struct bt_conn *conn) {
{ int err = bt_gatt_subscribe(conn, &subscribe_params);
int err = bt_gatt_subscribe(conn, &subscribe_params); switch (err) {
switch (err) { case -EALREADY:
case -EALREADY: LOG_DBG("[ALREADY SUBSCRIBED]");
LOG_DBG("[ALREADY SUBSCRIBED]"); break;
break; // break;
// break; // bt_gatt_unsubscribe(conn, &subscribe_params);
// bt_gatt_unsubscribe(conn, &subscribe_params); // return split_central_subscribe(conn);
// return split_central_subscribe(conn); case 0:
case 0: LOG_DBG("[SUBSCRIBED]");
LOG_DBG("[SUBSCRIBED]"); break;
break; default:
default: LOG_ERR("Subscribe failed (err %d)", err);
LOG_ERR("Subscribe failed (err %d)", err); break;
break; }
}
return 0;
return 0;
} }
static u8_t split_central_discovery_func(struct bt_conn *conn, static u8_t split_central_discovery_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params) {
struct bt_gatt_discover_params *params) int err;
{
int err; if (!attr) {
LOG_DBG("Discover complete");
if (!attr) { (void)memset(params, 0, sizeof(*params));
LOG_DBG("Discover complete"); return BT_GATT_ITER_STOP;
(void)memset(params, 0, sizeof(*params)); }
return BT_GATT_ITER_STOP;
} LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);
LOG_DBG("[ATTRIBUTE] handle %u", attr->handle); if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
memcpy(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), sizeof(uuid));
if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) { discover_params.uuid = &uuid.uuid;
memcpy(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), sizeof(uuid)); discover_params.start_handle = attr->handle + 1;
discover_params.uuid = &uuid.uuid; discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
discover_params.start_handle = attr->handle + 1;
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; err = bt_gatt_discover(conn, &discover_params);
if (err) {
err = bt_gatt_discover(conn, &discover_params); LOG_ERR("Discover failed (err %d)", err);
if (err) { }
LOG_ERR("Discover failed (err %d)", err); } else if (!bt_uuid_cmp(discover_params.uuid,
} BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) {
} else if (!bt_uuid_cmp(discover_params.uuid, memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) { discover_params.uuid = &uuid.uuid;
memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid)); discover_params.start_handle = attr->handle + 2;
discover_params.uuid = &uuid.uuid; discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
discover_params.start_handle = attr->handle + 2; subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
subscribe_params.value_handle = bt_gatt_attr_value_handle(attr); err = bt_gatt_discover(conn, &discover_params);
if (err) {
err = bt_gatt_discover(conn, &discover_params); LOG_ERR("Discover failed (err %d)", err);
if (err) { }
LOG_ERR("Discover failed (err %d)", err); } else {
} subscribe_params.notify = split_central_notify_func;
} else { subscribe_params.value = BT_GATT_CCC_NOTIFY;
subscribe_params.notify = split_central_notify_func; subscribe_params.ccc_handle = attr->handle;
subscribe_params.value = BT_GATT_CCC_NOTIFY;
subscribe_params.ccc_handle = attr->handle; split_central_subscribe(conn);
split_central_subscribe(conn); return BT_GATT_ITER_STOP;
}
return BT_GATT_ITER_STOP;
} return BT_GATT_ITER_STOP;
return BT_GATT_ITER_STOP;
} }
static void split_central_process_connection(struct bt_conn *conn) { static void split_central_process_connection(struct bt_conn *conn) {
int err; int err;
LOG_DBG("Current security for connection: %d", bt_conn_get_security(conn)); LOG_DBG("Current security for connection: %d", bt_conn_get_security(conn));
err = bt_conn_set_security(conn, BT_SECURITY_L2); err = bt_conn_set_security(conn, BT_SECURITY_L2);
if (err) { if (err) {
LOG_ERR("Failed to set security (reason %d)", err); LOG_ERR("Failed to set security (reason %d)", err);
return; return;
} }
if (conn == default_conn && !subscribe_params.value) { if (conn == default_conn && !subscribe_params.value) {
discover_params.uuid = &uuid.uuid; discover_params.uuid = &uuid.uuid;
discover_params.func = split_central_discovery_func; discover_params.func = split_central_discovery_func;
discover_params.start_handle = 0x0001; discover_params.start_handle = 0x0001;
discover_params.end_handle = 0xffff; discover_params.end_handle = 0xffff;
discover_params.type = BT_GATT_DISCOVER_PRIMARY; discover_params.type = BT_GATT_DISCOVER_PRIMARY;
err = bt_gatt_discover(default_conn, &discover_params); err = bt_gatt_discover(default_conn, &discover_params);
if (err) { if (err) {
LOG_ERR("Discover failed(err %d)", err); LOG_ERR("Discover failed(err %d)", err);
return; return;
} }
} }
struct bt_conn_info info; struct bt_conn_info info;
bt_conn_get_info(conn, &info); bt_conn_get_info(conn, &info);
LOG_DBG("New connection params: Interval: %d, Latency: %d, PHY: %d", info.le.interval, info.le.latency, info.le.phy->rx_phy); LOG_DBG("New connection params: Interval: %d, Latency: %d, PHY: %d", info.le.interval,
info.le.latency, info.le.phy->rx_phy);
} }
static bool split_central_eir_found(struct bt_data *data, void *user_data) static bool split_central_eir_found(struct bt_data *data, void *user_data) {
{ bt_addr_le_t *addr = user_data;
bt_addr_le_t *addr = user_data; int i;
int i;
LOG_DBG("[AD]: %u data_len %u", data->type, data->data_len); LOG_DBG("[AD]: %u data_len %u", data->type, data->data_len);
switch (data->type) { switch (data->type) {
case BT_DATA_UUID128_SOME: case BT_DATA_UUID128_SOME:
case BT_DATA_UUID128_ALL: case BT_DATA_UUID128_ALL:
if (data->data_len % 16 != 0U) { if (data->data_len % 16 != 0U) {
LOG_ERR("AD malformed"); LOG_ERR("AD malformed");
return true; return true;
} }
for (i = 0; i < data->data_len; i += 16) { for (i = 0; i < data->data_len; i += 16) {
struct bt_le_conn_param *param; struct bt_le_conn_param *param;
struct bt_uuid uuid; struct bt_uuid uuid;
int err; int err;
if (!bt_uuid_create(&uuid, &data->data[i], 16)) { if (!bt_uuid_create(&uuid, &data->data[i], 16)) {
LOG_ERR("Unable to load UUID"); LOG_ERR("Unable to load UUID");
continue; continue;
} }
if (!bt_uuid_cmp(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) { if (!bt_uuid_cmp(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
char uuid_str[BT_UUID_STR_LEN]; char uuid_str[BT_UUID_STR_LEN];
char service_uuid_str[BT_UUID_STR_LEN]; char service_uuid_str[BT_UUID_STR_LEN];
bt_uuid_to_str(&uuid, uuid_str, sizeof(uuid_str)); bt_uuid_to_str(&uuid, uuid_str, sizeof(uuid_str));
bt_uuid_to_str(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID), service_uuid_str, sizeof(service_uuid_str)); bt_uuid_to_str(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID), service_uuid_str,
LOG_DBG("UUID %s does not match split UUID: %s", log_strdup(uuid_str), log_strdup(service_uuid_str)); sizeof(service_uuid_str));
continue; LOG_DBG("UUID %s does not match split UUID: %s", log_strdup(uuid_str),
} log_strdup(service_uuid_str));
continue;
LOG_DBG("Found the split service"); }
zmk_ble_set_peripheral_addr(addr); LOG_DBG("Found the split service");
err = bt_le_scan_stop(); zmk_ble_set_peripheral_addr(addr);
if (err) {
LOG_ERR("Stop LE scan failed (err %d)", err); err = bt_le_scan_stop();
continue; if (err) {
} LOG_ERR("Stop LE scan failed (err %d)", err);
continue;
default_conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr); }
if (default_conn) {
LOG_DBG("Found existing connection"); default_conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr);
split_central_process_connection(default_conn); if (default_conn) {
} else { LOG_DBG("Found existing connection");
param = BT_LE_CONN_PARAM(0x0006, 0x0006, 30, 400); split_central_process_connection(default_conn);
} else {
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param = BT_LE_CONN_PARAM(0x0006, 0x0006, 30, 400);
param, &default_conn);
if (err) { err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &default_conn);
LOG_ERR("Create conn failed (err %d) (create conn? 0x%04x)", err, BT_HCI_OP_LE_CREATE_CONN); if (err) {
start_scan(); LOG_ERR("Create conn failed (err %d) (create conn? 0x%04x)", err,
} BT_HCI_OP_LE_CREATE_CONN);
start_scan();
err = bt_conn_le_phy_update(default_conn, BT_CONN_LE_PHY_PARAM_2M); }
if (err) {
LOG_ERR("Update phy conn failed (err %d)", err); err = bt_conn_le_phy_update(default_conn, BT_CONN_LE_PHY_PARAM_2M);
start_scan(); if (err) {
} LOG_ERR("Update phy conn failed (err %d)", err);
} start_scan();
}
return false; }
}
} return false;
}
return true; }
return true;
} }
static void split_central_device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t type, static void split_central_device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t type,
struct net_buf_simple *ad) struct net_buf_simple *ad) {
{ char dev[BT_ADDR_LE_STR_LEN];
char dev[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(addr, dev, sizeof(dev));
bt_addr_le_to_str(addr, dev, sizeof(dev)); LOG_DBG("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i", log_strdup(dev), type, ad->len,
LOG_DBG("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i", rssi);
log_strdup(dev), type, ad->len, rssi);
/* We're only interested in connectable events */
/* We're only interested in connectable events */ if (type == BT_GAP_ADV_TYPE_ADV_IND || type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
if (type == BT_GAP_ADV_TYPE_ADV_IND || bt_data_parse(ad, split_central_eir_found, (void *)addr);
type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) { }
bt_data_parse(ad, split_central_eir_found, (void *)addr);
}
} }
static int start_scan(void) static int start_scan(void) {
{ int err;
int err;
err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, split_central_device_found); err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, split_central_device_found);
if (err) { if (err) {
LOG_ERR("Scanning failed to start (err %d)", err); LOG_ERR("Scanning failed to start (err %d)", err);
return err; return err;
} }
LOG_DBG("Scanning successfully started"); LOG_DBG("Scanning successfully started");
return 0; return 0;
} }
static void split_central_connected(struct bt_conn *conn, u8_t conn_err) static void split_central_connected(struct bt_conn *conn, u8_t conn_err) {
{ char addr[BT_ADDR_LE_STR_LEN];
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (conn_err) { if (conn_err) {
LOG_ERR("Failed to connect to %s (%u)", log_strdup(addr), conn_err); LOG_ERR("Failed to connect to %s (%u)", log_strdup(addr), conn_err);
bt_conn_unref(default_conn); bt_conn_unref(default_conn);
default_conn = NULL; default_conn = NULL;
start_scan(); start_scan();
return; return;
} }
LOG_DBG("Connected: %s", log_strdup(addr)); LOG_DBG("Connected: %s", log_strdup(addr));
split_central_process_connection(conn); split_central_process_connection(conn);
} }
static void split_central_disconnected(struct bt_conn *conn, u8_t reason) static void split_central_disconnected(struct bt_conn *conn, u8_t reason) {
{ char addr[BT_ADDR_LE_STR_LEN];
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_DBG("Disconnected: %s (reason %d)", log_strdup(addr), reason); LOG_DBG("Disconnected: %s (reason %d)", log_strdup(addr), reason);
if (default_conn != conn) { if (default_conn != conn) {
return; return;
} }
bt_conn_unref(default_conn); bt_conn_unref(default_conn);
default_conn = NULL; default_conn = NULL;
start_scan(); start_scan();
} }
static struct bt_conn_cb conn_callbacks = { static struct bt_conn_cb conn_callbacks = {
.connected = split_central_connected, .connected = split_central_connected,
.disconnected = split_central_disconnected, .disconnected = split_central_disconnected,
}; };
int zmk_split_bt_central_init(struct device *_arg) int zmk_split_bt_central_init(struct device *_arg) {
{ bt_conn_cb_register(&conn_callbacks);
bt_conn_cb_register(&conn_callbacks);
return start_scan(); return start_scan();
} }
SYS_INIT(zmk_split_bt_central_init, SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);
APPLICATION,
CONFIG_ZMK_BLE_INIT_PRIORITY);

39
app/src/split/bluetooth/service.c

@ -21,41 +21,36 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
static u8_t num_of_positions = ZMK_KEYMAP_LEN; static u8_t num_of_positions = ZMK_KEYMAP_LEN;
static u8_t position_state[16]; static u8_t position_state[16];
static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs, void *buf, u16_t len, u16_t offset) static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
{ void *buf, u16_t len, u16_t offset) {
return bt_gatt_attr_read(conn, attrs, buf, len, offset, &position_state, sizeof(position_state)); return bt_gatt_attr_read(conn, attrs, buf, len, offset, &position_state,
sizeof(position_state));
} }
static ssize_t split_svc_num_of_positions(struct bt_conn *conn, const struct bt_gatt_attr *attrs, void *buf, u16_t len, u16_t offset) static ssize_t split_svc_num_of_positions(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
{ void *buf, u16_t len, u16_t offset) {
return bt_gatt_attr_read(conn, attrs, buf, len, offset, attrs->user_data, sizeof(u8_t)); return bt_gatt_attr_read(conn, attrs, buf, len, offset, attrs->user_data, sizeof(u8_t));
} }
static void split_svc_pos_state_ccc(const struct bt_gatt_attr *attr, u16_t value) static void split_svc_pos_state_ccc(const struct bt_gatt_attr *attr, u16_t value) {
{
LOG_DBG("value %d", value); LOG_DBG("value %d", value);
} }
BT_GATT_SERVICE_DEFINE(
split_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)),
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID),
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT,
split_svc_pos_state, NULL, &position_state),
BT_GATT_CCC(split_svc_pos_state_ccc, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL,
&num_of_positions), );
BT_GATT_SERVICE_DEFINE(split_svc, int zmk_split_bt_position_pressed(u8_t position) {
BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)),
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ_ENCRYPT,
split_svc_pos_state, NULL, &position_state),
BT_GATT_CCC(split_svc_pos_state_ccc,
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ,
split_svc_num_of_positions, NULL, &num_of_positions),
);
int zmk_split_bt_position_pressed(u8_t position)
{
WRITE_BIT(position_state[position / 8], position % 8, true); WRITE_BIT(position_state[position / 8], position % 8, true);
return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state)); return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state));
} }
int zmk_split_bt_position_released(u8_t position) int zmk_split_bt_position_released(u8_t position) {
{
WRITE_BIT(position_state[position / 8], position % 8, false); WRITE_BIT(position_state[position / 8], position % 8, false);
return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state)); return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state));
} }

21
app/src/split_listener.c

@ -19,18 +19,17 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/hid.h> #include <zmk/hid.h>
#include <zmk/endpoints.h> #include <zmk/endpoints.h>
int split_listener(const struct zmk_event_header *eh) int split_listener(const struct zmk_event_header *eh) {
{ LOG_DBG("");
LOG_DBG(""); if (is_position_state_changed(eh)) {
if (is_position_state_changed(eh)) { const struct position_state_changed *ev = cast_position_state_changed(eh);
const struct position_state_changed *ev = cast_position_state_changed(eh); if (ev->state) {
if (ev->state) { return zmk_split_bt_position_pressed(ev->position);
return zmk_split_bt_position_pressed(ev->position); } else {
} else { return zmk_split_bt_position_released(ev->position);
return zmk_split_bt_position_released(ev->position); }
} }
} return 0;
return 0;
} }
ZMK_LISTENER(split_listener, split_listener); ZMK_LISTENER(split_listener, split_listener);

93
app/src/usb_hid.c

@ -22,71 +22,56 @@ static struct device *hid_dev;
static K_SEM_DEFINE(hid_sem, 1, 1); static K_SEM_DEFINE(hid_sem, 1, 1);
static void in_ready_cb(void) static void in_ready_cb(void) { k_sem_give(&hid_sem); }
{
k_sem_give(&hid_sem);
}
static const struct hid_ops ops = static const struct hid_ops ops = {
{ .int_in_ready = in_ready_cb,
.int_in_ready = in_ready_cb,
}; };
int zmk_usb_hid_send_report(const u8_t *report, size_t len) int zmk_usb_hid_send_report(const u8_t *report, size_t len) {
{ switch (usb_status) {
switch(usb_status) { case USB_DC_SUSPEND:
case USB_DC_SUSPEND: return usb_wakeup_request();
return usb_wakeup_request(); case USB_DC_ERROR:
case USB_DC_ERROR: case USB_DC_RESET:
case USB_DC_RESET: case USB_DC_DISCONNECTED:
case USB_DC_DISCONNECTED: case USB_DC_UNKNOWN:
case USB_DC_UNKNOWN: return -ENODEV;
return -ENODEV; default:
default: k_sem_take(&hid_sem, K_MSEC(30));
k_sem_take(&hid_sem, K_MSEC(30)); int err = hid_int_ep_write(hid_dev, report, len, NULL);
int err = hid_int_ep_write(hid_dev, report, len, NULL);
if (err) {
if (err) { k_sem_give(&hid_sem);
k_sem_give(&hid_sem); }
}
return err;
return err; }
}
} }
void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params) void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params) { usb_status = status; };
{
usb_status = status;
};
static int zmk_usb_hid_init(struct device *_arg) static int zmk_usb_hid_init(struct device *_arg) {
{ int usb_enable_ret;
int usb_enable_ret;
hid_dev = device_get_binding("HID_0"); hid_dev = device_get_binding("HID_0");
if (hid_dev == NULL) if (hid_dev == NULL) {
{ LOG_ERR("Unable to locate HID device");
LOG_ERR("Unable to locate HID device"); return -EINVAL;
return -EINVAL; }
}
usb_hid_register_device(hid_dev, usb_hid_register_device(hid_dev, zmk_hid_report_desc, sizeof(zmk_hid_report_desc), &ops);
zmk_hid_report_desc, sizeof(zmk_hid_report_desc),
&ops);
usb_hid_init(hid_dev); usb_hid_init(hid_dev);
usb_enable_ret = usb_enable(usb_hid_status_cb); usb_enable_ret = usb_enable(usb_hid_status_cb);
if (usb_enable_ret != 0) if (usb_enable_ret != 0) {
{ LOG_ERR("Unable to enable USB");
LOG_ERR("Unable to enable USB"); return -EINVAL;
return -EINVAL; }
}
return 0; return 0;
} }
SYS_INIT(zmk_usb_hid_init, SYS_INIT(zmk_usb_hid_init, APPLICATION, CONFIG_ZMK_USB_INIT_PRIORITY);
APPLICATION,
CONFIG_ZMK_USB_INIT_PRIORITY);

Loading…
Cancel
Save