From c23d752917774bc740c791e2f7eeef6f8f9e1033 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Fri, 19 Jun 2020 15:32:33 -0400
Subject: [PATCH 01/12] Some initial work on behavior bindings for keymaps

---
 app/CMakeLists.txt                            |  3 +
 app/boards/arm/nice_nano/nice_nano.dts        |  2 +
 .../keymap/keymap.overlay                     | 13 +++
 .../keymap/keymap.overlay                     |  9 ++
 app/dts/behaviors/key_press.dtsi              |  9 ++
 app/dts/behaviors/reset.dtsi                  |  9 ++
 app/dts/bindings/behaviors/one_param.yaml     | 14 +++
 app/dts/bindings/behaviors/two_param.yaml     | 15 +++
 app/dts/bindings/behaviors/zero_param.yaml    | 11 +++
 .../behaviors/zmk,behavior-key-press.yaml     |  8 ++
 .../behaviors/zmk,behavior-reset.yaml         |  8 ++
 app/dts/bindings/zmk,layers.yaml              |  3 +-
 app/include/drivers/behavior.h                | 88 ++++++++++++++++++
 app/include/zmk/keymap.h                      | 18 +---
 app/prj.conf                                  |  5 +-
 app/src/behaviors/behavior_key_press.c        | 66 +++++++++++++
 app/src/behaviors/behavior_reset.c            | 51 ++++++++++
 app/src/keymap.c                              | 93 +++++++++++--------
 app/src/kscan.c                               |  9 +-
 19 files changed, 370 insertions(+), 64 deletions(-)
 create mode 100644 app/dts/behaviors/key_press.dtsi
 create mode 100644 app/dts/behaviors/reset.dtsi
 create mode 100644 app/dts/bindings/behaviors/one_param.yaml
 create mode 100644 app/dts/bindings/behaviors/two_param.yaml
 create mode 100644 app/dts/bindings/behaviors/zero_param.yaml
 create mode 100644 app/dts/bindings/behaviors/zmk,behavior-key-press.yaml
 create mode 100644 app/dts/bindings/behaviors/zmk,behavior-reset.yaml
 create mode 100644 app/include/drivers/behavior.h
 create mode 100644 app/src/behaviors/behavior_key_press.c
 create mode 100644 app/src/behaviors/behavior_reset.c

diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index ed2c28c8..89f4055b 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -1,6 +1,7 @@
 # Find Zephyr. This also loads Zephyr's build system.
 cmake_minimum_required(VERSION 3.13.1)
 
+set(CONFIG_APPLICATION_DEFINED_SYSCALL true)
 list(APPEND BOARD_ROOT ${CMAKE_SOURCE_DIR})
 list(APPEND DTS_ROOT ${CMAKE_SOURCE_DIR})
 
@@ -29,6 +30,8 @@ target_include_directories(app PRIVATE include)
 target_sources(app PRIVATE src/kscan.c)
 target_sources(app PRIVATE src/keymap.c)
 target_sources(app PRIVATE src/hid.c)
+target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
+target_sources(app PRIVATE src/behaviors/behavior_reset.c)
 target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
 target_sources_ifdef(CONFIG_ZMK_KSCAN_MOCK_DRIVER app PRIVATE src/kscan_mock.c)
 target_sources_ifdef(CONFIG_ZMK_KSCAN_COMPOSITE_DRIVER app PRIVATE src/kscan_composite.c)
diff --git a/app/boards/arm/nice_nano/nice_nano.dts b/app/boards/arm/nice_nano/nice_nano.dts
index 21b60d38..4604e9a6 100644
--- a/app/boards/arm/nice_nano/nice_nano.dts
+++ b/app/boards/arm/nice_nano/nice_nano.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 #include <nordic/nrf52840_qiaa.dtsi>
+#include <behaviors/key_press.dtsi>
+#include <behaviors/reset.dtsi>
 #include "arduino_pro_micro_pins.dtsi"
 
 / {
diff --git a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
index d87363f9..8cb76541 100644
--- a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
@@ -1,4 +1,6 @@
 #include <dt-bindings/zmk/keys.h>
+#include <behaviors/key_press.dtsi>
+#include <behaviors/reset.dtsi>
 #include <keymap.h>
 
 / {
@@ -21,6 +23,9 @@
 	KC_A MT(MOD_LSFT, KC_B)    ZC_NO ZC_NO
 	CC_RAIS CC_LOWR            ZC_NO ZC_NO
 	>;
+			bindings = <
+				&reset &kp 0
+				&kp 1  &kp 2>;
 		};
 
 		lower: layer_1 {
@@ -29,6 +34,10 @@
 			KC_MPLY KC_MNXT    ZC_NO ZC_NO
 			ZC_TRNS ZC_TRNS    ZC_NO ZC_NO
 			>;
+
+			bindings = <
+				&reset &kp 0
+				&kp 1  &kp 2>;
 		};
 
 		raise: layer_2 {
@@ -36,6 +45,10 @@
 			keys = <
 			KC_C KC_D          ZC_NO ZC_NO
 			ZC_TRNS ZC_TRNS    ZC_NO ZC_NO>;
+
+			bindings = <
+				&reset &kp 0
+				&kp 1  &kp 2>;
 		};
 	};
 };
diff --git a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
index c1bd5425..f4d746ed 100644
--- a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
@@ -21,6 +21,9 @@
 	KC_A MT(MOD_LSFT, KC_B)
 	CC_RAIS CC_LOWR
 	>;
+			bindings = <
+				&reset &kp 0
+				&kp 1  &kp 2>;
 		};
 
 		lower: layer_1 {
@@ -29,6 +32,9 @@
 			KC_MPLY KC_MNXT
 			ZC_TRNS ZC_TRNS
 			>;
+			bindings = <
+				&reset &kp 0
+				&kp 1  &kp 2>;
 		};
 
 		raise: layer_2 {
@@ -37,6 +43,9 @@
 			KC_C KC_D
 			ZC_TRNS ZC_TRNS
 			>;
+			bindings = <
+				&reset &kp 0
+				&kp 1  &kp 2>;
 		};
 	};
 };
diff --git a/app/dts/behaviors/key_press.dtsi b/app/dts/behaviors/key_press.dtsi
new file mode 100644
index 00000000..7c7ac5b3
--- /dev/null
+++ b/app/dts/behaviors/key_press.dtsi
@@ -0,0 +1,9 @@
+/ {
+	behaviors {
+		kp: behavior_key_press {
+			compatible = "zmk,behavior-key-press";
+			label = "KEY_PRESS";
+			#binding-cells = <1>;
+		};
+	};
+};
diff --git a/app/dts/behaviors/reset.dtsi b/app/dts/behaviors/reset.dtsi
new file mode 100644
index 00000000..4e3b4446
--- /dev/null
+++ b/app/dts/behaviors/reset.dtsi
@@ -0,0 +1,9 @@
+/ {
+	behaviors {
+		reset: behavior_reset {
+			compatible = "zmk,behavior-reset";
+			label = "RESET";
+			#binding-cells = <0>;
+		};
+	};
+};
diff --git a/app/dts/bindings/behaviors/one_param.yaml b/app/dts/bindings/behaviors/one_param.yaml
new file mode 100644
index 00000000..1f33aee2
--- /dev/null
+++ b/app/dts/bindings/behaviors/one_param.yaml
@@ -0,0 +1,14 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+properties:
+  label:
+    type: string
+    required: true
+  "#binding-cells":
+    type: int
+    required: true
+    const: 1
+
+binding-cells:
+  - param1
diff --git a/app/dts/bindings/behaviors/two_param.yaml b/app/dts/bindings/behaviors/two_param.yaml
new file mode 100644
index 00000000..f8b3af93
--- /dev/null
+++ b/app/dts/bindings/behaviors/two_param.yaml
@@ -0,0 +1,15 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+properties:
+  label:
+    type: string
+    required: true
+  "#binding-cells":
+    type: int
+    required: true
+    const: 2
+
+binding-cells:
+  - param1
+  - param2
diff --git a/app/dts/bindings/behaviors/zero_param.yaml b/app/dts/bindings/behaviors/zero_param.yaml
new file mode 100644
index 00000000..20f15288
--- /dev/null
+++ b/app/dts/bindings/behaviors/zero_param.yaml
@@ -0,0 +1,11 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+properties:
+  label:
+    type: string
+    required: true
+  "#binding-cells":
+    type: int
+    required: true
+    const: 0
diff --git a/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml b/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml
new file mode 100644
index 00000000..0169d7d5
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+description: Key press/release behavior
+
+compatible: "zmk,behavior-key-press"
+
+include: one_param.yaml
diff --git a/app/dts/bindings/behaviors/zmk,behavior-reset.yaml b/app/dts/bindings/behaviors/zmk,behavior-reset.yaml
new file mode 100644
index 00000000..c8e5e6fb
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-reset.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+description: Keyboard Reset Behavior
+
+compatible: "zmk,behavior-reset"
+
+include: zero_param.yaml
diff --git a/app/dts/bindings/zmk,layers.yaml b/app/dts/bindings/zmk,layers.yaml
index c9b462a1..2bbb0231 100644
--- a/app/dts/bindings/zmk,layers.yaml
+++ b/app/dts/bindings/zmk,layers.yaml
@@ -11,4 +11,5 @@ child-binding:
       type: string
     keys:
       type: array
-
+    bindings:
+      type: phandle-array
diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h
new file mode 100644
index 00000000..84b11ce2
--- /dev/null
+++ b/app/include/drivers/behavior.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020 Peter Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <device.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @cond INTERNAL_HIDDEN
+ *
+ * Behavior driver API definition and system call entry points.
+ *
+ * (Internal use only.)
+ */
+
+typedef int (*behavior_position_pressed_t)(struct device *dev, u32_t param1, u32_t param2);
+typedef int (*behavior_position_released_t)(struct device *dev, u32_t param1, u32_t param2);
+
+__subsystem struct behavior_driver_api {
+	behavior_position_pressed_t position_pressed;
+	behavior_position_released_t position_released;
+};
+/**
+ * @endcond
+ */
+
+/**
+ * @brief Handle the assigned position being pressed
+ * @param dev Pointer to the device structure for the driver instance.
+ * @param param1 User parameter specified at time of behavior assignment.
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int behavior_position_pressed(struct device *dev, u32_t param1, u32_t param2);
+
+static inline int z_impl_behavior_position_pressed(struct device *dev, u32_t param1, u32_t param2)
+{
+	const struct behavior_driver_api *api =
+			(const struct behavior_driver_api *)dev->driver_api;
+
+	if (api->position_pressed == NULL) {
+		return -ENOTSUP;
+	}
+
+	return api->position_pressed(dev, param1, param2);
+}
+
+/**
+ * @brief Handle the assigned position being pressed
+ * @param dev Pointer to the device structure for the driver instance.
+ * @param param1 User parameter specified at time of behavior assignment.
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int behavior_position_released(struct device *dev, u32_t param1, u32_t param2);
+
+static inline int z_impl_behavior_position_released(struct device *dev, u32_t param1, u32_t param2)
+{
+	const struct behavior_driver_api *api =
+			(const struct behavior_driver_api *)dev->driver_api;
+
+	if (api->position_released == NULL) {
+		return -ENOTSUP;
+	}
+
+	return api->position_released(dev, param1, param2);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#include <syscalls/behavior.h>
diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h
index 285b0718..7866cd57 100644
--- a/app/include/zmk/keymap.h
+++ b/app/include/zmk/keymap.h
@@ -6,23 +6,9 @@
 #include <dt-bindings/zmk/keys.h>
 
 #include <zmk/matrix.h>
-#include <zmk/keys.h>
-
-#define ZMK_KEYMAP_NODE DT_CHOSEN(zmk_keymap)
-#define ZMK_KEYMAP_LAYERS_LEN DT_PROP_LEN(ZMK_KEYMAP_NODE, layers)
-
-/* TODO: Need to actually be able to get a NODELABEL from a node id
-#define _ZMK_KEYMAP_GENERATE_LAYER_CONST(node_id) \
-    DT_NODELABEL_FOR_NODE(node_id)_layer,
-
-enum zmk_keymap_layer
-{
-    DT_FOREACH_CHILD(DT_INST(0, zmk_layers), _ZMK_KEYMAP_GENERATE_LAYER_CONST)
-};
-*/
+// #include <zmk/keys.h>
 
 bool zmk_keymap_layer_activate(u8_t layer);
 bool zmk_keymap_layer_deactivate(u8_t layer);
 
-zmk_key
-zmk_keymap_keycode_from_position(u32_t row, u32_t column);
+int zmk_keymap_position_state_changed(u32_t row, u32_t column, bool pressed);
diff --git a/app/prj.conf b/app/prj.conf
index f5b2d4a9..cba93112 100644
--- a/app/prj.conf
+++ b/app/prj.conf
@@ -1,3 +1,4 @@
-# CONFIG_LOG=y
-# CONFIG_ZMK_LOG_LEVEL_DBG=y
+CONFIG_LOG=y
+CONFIG_ZMK_LOG_LEVEL_DBG=y
 CONFIG_KERNEL_BIN_NAME="zmk"
+CONFIG_REBOOT=y
\ No newline at end of file
diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c
new file mode 100644
index 00000000..b9d0ff04
--- /dev/null
+++ b/app/src/behaviors/behavior_key_press.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_key_press
+
+#include <device.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+struct behavior_key_press_config { };
+struct behavior_key_press_data { };
+
+static int behavior_key_press_init(struct device *dev)
+{
+	return 0;
+};
+
+
+// They keycode is passed by the "keymap" based on the parameter created as part of the assignment.
+// Other drivers instead might activate a layer, update the consumer page state, or update the RGB state, etc.
+// Returns:
+//  * > 0 -  indicate successful processing, and halt further handling,
+//  * 0 - Indicate successful processing, and continue propagation.
+//  * < 0 - Indicate error processing, report and halt further propagation.
+static int on_position_pressed(struct device *dev, u32_t keycode, u32_t _)
+{
+  // Invoking this triggers a *new* event, that can be linked to other behaviours.
+  //return zmk_key_state_press(u32_t keycode);
+  return 0;
+}
+
+
+// They keycode is passed by the "keymap" based on the parameter created as part of the assignment.
+static int on_position_released(struct device *dev, u32_t keycode, u32_t _)
+{
+  // Invoking this triggers a *new* event, that can will be handled by other behaviors
+  // This is the "command" piece. Which could be better/richer, but captures essence here.
+  // return zmk_key_state_release(u32_t keycode);
+  return 0;
+}
+
+static const struct behavior_driver_api behavior_key_press_driver_api = {
+  // These callbacks are all optional, and define which kinds of events the behavior can handle.
+  // They can reference local functions defined here, or shared event handlers.
+  .position_pressed = on_position_pressed,
+  .position_released = on_position_released
+  // Other optional callbacks a behavior can implement
+  // .on_mouse_moved
+  // .on_sensor_data - Any behaviour that wants to be linked to a censor can implement this behavior
+};
+
+
+static const struct behavior_key_press_config behavior_key_press_config = {};
+
+static struct behavior_key_press_data behavior_key_press_data;
+
+DEVICE_AND_API_INIT(behavior_key_press, DT_INST_LABEL(0), behavior_key_press_init,
+                    &behavior_key_press_data,
+                    &behavior_key_press_config,
+                    APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+                    &behavior_key_press_driver_api);
diff --git a/app/src/behaviors/behavior_reset.c b/app/src/behaviors/behavior_reset.c
new file mode 100644
index 00000000..1609fad6
--- /dev/null
+++ b/app/src/behaviors/behavior_reset.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_reset
+
+#include <device.h>
+#include <power/reboot.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+struct behavior_reset_config { };
+struct behavior_reset_data { };
+
+static int behavior_reset_init(struct device *dev)
+{
+	return 0;
+};
+
+static int on_position_pressed(struct device *dev, u32_t _param1, u32_t _param2)
+{
+  // TODO: Correct magic code for going into DFU?
+  // See https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
+  sys_reboot(0);
+  return 0;
+}
+
+static int on_position_released(struct device *dev, u32_t _param1, u32_t _param2)
+{
+  return 0;
+}
+
+static const struct behavior_driver_api behavior_reset_driver_api = {
+  .position_pressed = on_position_pressed,
+  .position_released = on_position_released
+};
+
+
+static const struct behavior_reset_config behavior_reset_config = {};
+
+static struct behavior_reset_data behavior_reset_data;
+
+DEVICE_AND_API_INIT(behavior_reset, DT_INST_LABEL(0), behavior_reset_init,
+                    &behavior_reset_data,
+                    &behavior_reset_config,
+                    APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+                    &behavior_reset_driver_api);
\ No newline at end of file
diff --git a/app/src/keymap.c b/app/src/keymap.c
index 1cb705e2..386de81f 100644
--- a/app/src/keymap.c
+++ b/app/src/keymap.c
@@ -3,22 +3,48 @@
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 #include <zmk/keymap.h>
 #include <dt-bindings/zmk/matrix-transform.h>
+#include <drivers/behavior.h>
 #include <sys/util.h>
 
 static u32_t zmk_keymap_layer_state = 0;
 static u8_t zmk_keymap_layer_default = 0;
 
+struct zmk_behavior_binding {
+	char *behavior_dev;
+	u32_t param1;
+	u32_t param2;
+};
+
+#define ZMK_KEYMAP_NODE DT_CHOSEN(zmk_keymap)
+#define ZMK_KEYMAP_LAYERS_LEN DT_PROP_LEN(ZMK_KEYMAP_NODE, layers)
+
+#define LAYER_NODE(l) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, l)
+
+#define BINDING_FOR_IDX(layer,idx) \
+	{ .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, layer), bindings, idx)), \
+	  .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), bindings, idx, param1), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), bindings, idx, param1))), \
+	  .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), bindings, idx, param2), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), bindings, idx, param2))), \
+	}
+
 #if DT_NODE_HAS_PROP(ZMK_KEYMAP_NODE, transform)
 #define ZMK_KEYMAP_TRANSFORM_NODE DT_PHANDLE(ZMK_KEYMAP_NODE, transform)
 #define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_TRANSFORM_NODE, map)
 
 #define _TRANSFORM_ENTRY(i, l) \
-	[(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))] = DT_PROP_BY_IDX(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, l), keys, 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))] = BINDING_FOR_IDX(l,i),
+
+#else
+
+#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_NODE, bindings)
+#define _TRANSFORM_ENTRY(i, l) \
+	BINDING_FOR_IDX(l,i),
+
+#endif
 
 #define TRANSFORMED_LAYER(idx) \
-  { UTIL_LISTIFY(ZMK_KEYMAP_LEN, _TRANSFORM_ENTRY, idx) }
+  { UTIL_LISTIFY(DT_PROP_LEN(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, idx), bindings), _TRANSFORM_ENTRY, idx) }
 
-static zmk_key zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_ROWS * ZMK_MATRIX_COLS] = {
+static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_ROWS * ZMK_MATRIX_COLS] = {
 #if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 0)
 	TRANSFORMED_LAYER(0),
 #endif
@@ -51,36 +77,7 @@ static zmk_key zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_ROWS * ZMK_MATRIX_CO
 #endif
 };
 
-#else
-
-static zmk_key zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_ROWS * ZMK_MATRIX_COLS] = {
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 0)
-	DT_PROP_BY_PHANDLE_IDX(ZMK_KEYMAP_NODE, layers, 0, keys),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 1)
-	DT_PROP_BY_PHANDLE_IDX(ZMK_KEYMAP_NODE, layers, 1, keys),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 2)
-	DT_PROP_BY_PHANDLE_IDX(ZMK_KEYMAP_NODE, layers, 2, keys),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 3)
-	DT_PROP_BY_PHANDLE_IDX(ZMK_KEYMAP_NODE, layers, 3, keys),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 4)
-	DT_PROP_BY_PHANDLE_IDX(ZMK_KEYMAP_NODE, layers, 4, keys),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 5)
-	DT_PROP_BY_PHANDLE_IDX(ZMK_KEYMAP_NODE, layers, 5, keys),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 6)
-	DT_PROP_BY_PHANDLE_IDX(ZMK_KEYMAP_NODE, layers, 6, keys),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 7)
-	DT_PROP_BY_PHANDLE_IDX(ZMK_KEYMAP_NODE, layers, 7, keys),
-#endif
-};
-
-#endif
+// #else
 
 #define SET_LAYER_STATE(layer, state)                \
 	if (layer >= 32)                                 \
@@ -100,24 +97,38 @@ bool zmk_keymap_layer_deactivate(u8_t layer)
 	SET_LAYER_STATE(layer, false);
 };
 
-zmk_key zmk_keymap_keycode_from_position(u32_t row, u32_t column)
+int zmk_keymap_position_state_changed(u32_t row, u32_t column, bool pressed)
 {
 	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)
 		{
 			u8_t key_index = (row * ZMK_MATRIX_COLS) + column;
-			LOG_DBG("Getting key at index %d", key_index);
+			struct zmk_behavior_binding *binding = &zmk_keymap[layer][key_index];
+			struct device *behavior;
+			int ret;
 
-			zmk_key key = zmk_keymap[layer][key_index];
-			if (key == ZC_TRNS)
-			{
-				continue;
+			LOG_DBG("key index: %d, binding name: %s", key_index, binding->behavior_dev);
+
+			behavior = device_get_binding(binding->behavior_dev);
+			if (pressed) {
+				ret = behavior_position_pressed(behavior, binding->param1, binding->param2);
+			} else {
+				ret = behavior_position_released(behavior, binding->param1, binding->param2);
 			}
+			
 
-			return key;
+			if (ret > 0) {
+				LOG_DBG("behavior processing to continue to next layer");
+				continue;
+			} else if (ret < 0) {
+				LOG_DBG("Behavior returned error: %d", ret);
+				return ret; 
+			} else {
+				return ret;
+			}
 		}
 	}
 
-	return ZC_NO;
+	return -ENOTSUP;
 }
diff --git a/app/src/kscan.c b/app/src/kscan.c
index 1f54a147..d1ed6210 100644
--- a/app/src/kscan.c
+++ b/app/src/kscan.c
@@ -49,11 +49,12 @@ void zmk_kscan_process_msgq(struct k_work *item)
 	while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0)
 	{
 		bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
-		zmk_key key = zmk_keymap_keycode_from_position(ev.row, ev.column);
-		struct zmk_key_event kev = (struct zmk_key_event){.row = ev.row, .column = ev.column, .key = key, .pressed = pressed};
+		zmk_keymap_position_state_changed(ev.row, ev.column, pressed);
+		// zmk_key key = zmk_keymap_keycode_from_position(ev.row, ev.column);
+		// struct zmk_key_event kev = (struct zmk_key_event){.row = ev.row, .column = ev.column, .key = key, .pressed = pressed};
 
-		LOG_DBG("Row: %d, col: %d, key: %d, pressed: %s\n", ev.row, ev.column, key, (pressed ? "true" : "false"));
-		zmk_handle_key(kev);
+		// LOG_DBG("Row: %d, col: %d, key: %d, pressed: %s\n", ev.row, ev.column, key, (pressed ? "true" : "false"));
+		// zmk_handle_key(kev);
 	}
 }
 

From d65629b9a0b79b6e294419fe9a4118fb09491c91 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sat, 20 Jun 2020 00:11:39 -0400
Subject: [PATCH 02/12] Lots more pieces toward HID working again.

---
 app/CMakeLists.txt                            |  3 +
 app/boards/arm/nice_nano/nice_nano.dts        |  1 +
 app/boards/native_posix.overlay               | 22 ++++++
 .../keymap/keymap.overlay                     |  7 ++
 app/dts/behaviors/hid.dtsi                    |  9 +++
 app/dts/behaviors/keymap.dtsi                 |  9 +++
 .../bindings/behaviors/zmk,behavior-hid.yaml  |  8 +++
 .../behaviors/zmk,behavior-keymap.yaml        |  8 +++
 app/dts/bindings/zmk,global-bindings.yaml     |  9 +++
 app/include/drivers/behavior.h                | 55 ++++++++++++--
 app/include/zmk/behavior.h                    |  8 +++
 app/include/zmk/events.h                      | 13 ++++
 app/src/behaviors/behavior_hid.c              | 59 +++++++++++++++
 app/src/behaviors/behavior_key_press.c        | 13 ++--
 app/src/behaviors/behavior_keymap.c           | 50 +++++++++++++
 app/src/endpoints.c                           |  1 +
 app/src/events.c                              | 72 +++++++++++++++++++
 app/src/kscan.c                               | 11 ++-
 app/src/kscan_mock.c                          |  1 +
 19 files changed, 346 insertions(+), 13 deletions(-)
 create mode 100644 app/dts/behaviors/hid.dtsi
 create mode 100644 app/dts/behaviors/keymap.dtsi
 create mode 100644 app/dts/bindings/behaviors/zmk,behavior-hid.yaml
 create mode 100644 app/dts/bindings/behaviors/zmk,behavior-keymap.yaml
 create mode 100644 app/dts/bindings/zmk,global-bindings.yaml
 create mode 100644 app/include/zmk/behavior.h
 create mode 100644 app/include/zmk/events.h
 create mode 100644 app/src/behaviors/behavior_hid.c
 create mode 100644 app/src/behaviors/behavior_keymap.c
 create mode 100644 app/src/events.c

diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 89f4055b..6f4217aa 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -28,8 +28,11 @@ endif()
 # find_package(Zephyr) which defines the target.
 target_include_directories(app PRIVATE include)
 target_sources(app PRIVATE src/kscan.c)
+target_sources(app PRIVATE src/events.c)
 target_sources(app PRIVATE src/keymap.c)
 target_sources(app PRIVATE src/hid.c)
+target_sources(app PRIVATE src/behaviors/behavior_keymap.c)
+target_sources(app PRIVATE src/behaviors/behavior_hid.c)
 target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
 target_sources(app PRIVATE src/behaviors/behavior_reset.c)
 target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
diff --git a/app/boards/arm/nice_nano/nice_nano.dts b/app/boards/arm/nice_nano/nice_nano.dts
index 4604e9a6..9d3b484b 100644
--- a/app/boards/arm/nice_nano/nice_nano.dts
+++ b/app/boards/arm/nice_nano/nice_nano.dts
@@ -8,6 +8,7 @@
 #include <nordic/nrf52840_qiaa.dtsi>
 #include <behaviors/key_press.dtsi>
 #include <behaviors/reset.dtsi>
+#include <behaviors/keymap.dtsi>
 #include "arduino_pro_micro_pins.dtsi"
 
 / {
diff --git a/app/boards/native_posix.overlay b/app/boards/native_posix.overlay
index 9d92beeb..3f2eead1 100644
--- a/app/boards/native_posix.overlay
+++ b/app/boards/native_posix.overlay
@@ -1,10 +1,20 @@
 #include <dt-bindings/zmk/keys.h>
+#include <behaviors/key_press.dtsi>
+#include <behaviors/reset.dtsi>
+#include <behaviors/keymap.dtsi>
+#include <behaviors/hid.dtsi>
 #include <zmk/kscan-mock.h>
 
 / {
 	chosen {
 		zmk,kscan = &kscan0;
 		zmk,keymap = &keymap0;
+		zmk,global_bindings = &bindings;
+	};
+
+	bindings: global_bindings {
+		compatible = "zmk,global-bindings";
+		bindings = <&keymap_behavior &hid_behavior>;
 	};
 
 	kscan0: kscan_0 {
@@ -58,6 +68,10 @@
 				KC_A MT(MOD_LSFT, KC_B) KC_C KC_D
 				KC_E KC_F KC_G KC_H
 			>;
+
+			bindings = <
+				&kp 5 &kp 0 &kp 10 &kp 11
+				&kp 1  &kp 2 &kp 4 &kp 89>;
 		};
 
 		lower: layer_1 {
@@ -66,6 +80,10 @@
 				KC_A KC_B KC_C KC_D
 				KC_E KC_F KC_G KC_H
 			>;
+
+			bindings = <
+				&kp 5 &kp 0 &kp 10 &kp 11
+				&kp 1  &kp 2 &kp 4 &kp 89>;
 		};
 
 		raise: layer_2 {
@@ -74,6 +92,10 @@
 				KC_E KC_F KC_G KC_H 
 				KC_A KC_B KC_C KC_D
 			>;
+
+			bindings = <
+				&kp 5 &kp 0 &kp 10 &kp 11
+				&kp 1  &kp 2 &kp 4 &kp 89>;
 		};
 	};
 };
diff --git a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
index 8cb76541..5ae78cf8 100644
--- a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
@@ -1,11 +1,18 @@
 #include <dt-bindings/zmk/keys.h>
 #include <behaviors/key_press.dtsi>
 #include <behaviors/reset.dtsi>
+#include <behaviors/keymap.dtsi>
 #include <keymap.h>
 
 / {
 	chosen {
 		zmk,keymap = &keymap0;
+		zmk,global_bindings = &bindings;
+	};
+
+	bindings: global_bindings {
+		compatible = "zmk,global-bindings";
+		bindings = <&reset>;
 	};
 	keymap0: keymap {
 		compatible = "zmk,keymap";
diff --git a/app/dts/behaviors/hid.dtsi b/app/dts/behaviors/hid.dtsi
new file mode 100644
index 00000000..d859c378
--- /dev/null
+++ b/app/dts/behaviors/hid.dtsi
@@ -0,0 +1,9 @@
+/ {
+	behaviors {
+		hid_behavior: behavior_hid {
+			compatible = "zmk,behavior-hid";
+			label = "HID";
+			#binding-cells = <0>;
+		};
+	};
+};
diff --git a/app/dts/behaviors/keymap.dtsi b/app/dts/behaviors/keymap.dtsi
new file mode 100644
index 00000000..87b2f41c
--- /dev/null
+++ b/app/dts/behaviors/keymap.dtsi
@@ -0,0 +1,9 @@
+/ {
+	behaviors {
+		keymap_behavior: behavior_keymap {
+			compatible = "zmk,behavior-keymap";
+			label = "KEYMAP";
+			#binding-cells = <0>;
+		};
+	};
+};
diff --git a/app/dts/bindings/behaviors/zmk,behavior-hid.yaml b/app/dts/bindings/behaviors/zmk,behavior-hid.yaml
new file mode 100644
index 00000000..f3e06032
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-hid.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+description: HID Report Behavior
+
+compatible: "zmk,behavior-hid"
+
+include: zero_param.yaml
diff --git a/app/dts/bindings/behaviors/zmk,behavior-keymap.yaml b/app/dts/bindings/behaviors/zmk,behavior-keymap.yaml
new file mode 100644
index 00000000..1d8a51fc
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-keymap.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+description: Keymap Behavior
+
+compatible: "zmk,behavior-keymap"
+
+include: zero_param.yaml
diff --git a/app/dts/bindings/zmk,global-bindings.yaml b/app/dts/bindings/zmk,global-bindings.yaml
new file mode 100644
index 00000000..69e79cda
--- /dev/null
+++ b/app/dts/bindings/zmk,global-bindings.yaml
@@ -0,0 +1,9 @@
+description: |
+  Specify the the global behaviors bound to state changes
+
+compatible: "zmk,global-bindings"
+
+properties:
+  bindings:
+    type: phandles
+    required: true
diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h
index 84b11ce2..f5f5f537 100644
--- a/app/include/drivers/behavior.h
+++ b/app/include/drivers/behavior.h
@@ -22,12 +22,14 @@ extern "C" {
  * (Internal use only.)
  */
 
-typedef int (*behavior_position_pressed_t)(struct device *dev, u32_t param1, u32_t param2);
-typedef int (*behavior_position_released_t)(struct device *dev, u32_t param1, u32_t param2);
+typedef int (*behavior_position_callback_t)(struct device *dev, u32_t param1, u32_t param2);
+typedef int (*behavior_keycode_callback_t)(struct device *dev, u32_t keycode);
 
 __subsystem struct behavior_driver_api {
-	behavior_position_pressed_t position_pressed;
-	behavior_position_released_t position_released;
+	behavior_position_callback_t position_pressed;
+	behavior_position_callback_t position_released;
+	behavior_keycode_callback_t keycode_pressed;
+	behavior_keycode_callback_t keycode_released;
 };
 /**
  * @endcond
@@ -77,6 +79,51 @@ static inline int z_impl_behavior_position_released(struct device *dev, u32_t pa
 	return api->position_released(dev, param1, param2);
 }
 
+/**
+ * @brief Handle the keycode being pressed
+ * @param dev Pointer to the device structure for the driver instance.
+ * @param keycode The keycode that is being pressed.
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int behavior_keycode_pressed(struct device *dev, u32_t keycode);
+
+static inline int z_impl_behavior_keycode_pressed(struct device *dev, u32_t keycode)
+{
+	const struct behavior_driver_api *api =
+			(const struct behavior_driver_api *)dev->driver_api;
+
+	if (api->keycode_pressed == NULL) {
+		return -ENOTSUP;
+	}
+
+	return api->keycode_pressed(dev, keycode);
+}
+
+
+/**
+ * @brief Handle the keycode being released
+ * @param dev Pointer to the device structure for the driver instance.
+ * @param keycode The keycode that is being pressed.
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int behavior_keycode_released(struct device *dev, u32_t keycode);
+
+static inline int z_impl_behavior_keycode_released(struct device *dev, u32_t keycode)
+{
+	const struct behavior_driver_api *api =
+			(const struct behavior_driver_api *)dev->driver_api;
+
+	if (api->keycode_released == NULL) {
+		return -ENOTSUP;
+	}
+
+	return api->keycode_released(dev, keycode);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/app/include/zmk/behavior.h b/app/include/zmk/behavior.h
new file mode 100644
index 00000000..63edcc9e
--- /dev/null
+++ b/app/include/zmk/behavior.h
@@ -0,0 +1,8 @@
+
+#pragma once
+
+struct zmk_behavior_binding {
+    char *behavior_dev;
+    u32_t param1;
+    u32_t param2;
+};
\ No newline at end of file
diff --git a/app/include/zmk/events.h b/app/include/zmk/events.h
new file mode 100644
index 00000000..9314b9d0
--- /dev/null
+++ b/app/include/zmk/events.h
@@ -0,0 +1,13 @@
+#pragma once
+
+int zmk_events_position_pressed(u32_t row, u32_t column);
+int zmk_events_position_released(u32_t row, u32_t column);
+int zmk_events_keycode_pressed(u32_t keycode);
+int zmk_events_keycode_released(u32_t keycode);
+int zmk_events_mod_pressed(u32_t modifier);
+int zmk_events_mod_released(u32_t modifier);
+int zmk_events_consumer_key_pressed(u32_t usage);
+int zmk_events_consumer_key_released(u32_t usage);
+
+// TODO: Encoders?
+// TODO: Sensors?
\ No newline at end of file
diff --git a/app/src/behaviors/behavior_hid.c b/app/src/behaviors/behavior_hid.c
new file mode 100644
index 00000000..2779568e
--- /dev/null
+++ b/app/src/behaviors/behavior_hid.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_hid
+
+#include <device.h>
+#include <power/reboot.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+#include <zmk/hid.h>
+#include <zmk/endpoints.h>
+
+struct behavior_hid_config { };
+struct behavior_hid_data { };
+
+static int behavior_hid_init(struct device *dev)
+{
+	return 0;
+};
+
+static int on_keycode_pressed(struct device *dev, u32_t keycode)
+{
+  enum zmk_hid_report_changes changes;
+  LOG_DBG("keycode %d", keycode);
+  
+  changes = zmk_hid_press_key(keycode);
+  return zmk_endpoints_send_report(changes);
+}
+
+static int on_keycode_released(struct device *dev, u32_t keycode)
+{
+  enum zmk_hid_report_changes changes;
+  LOG_DBG("keycode %d", keycode);
+  
+  changes = zmk_hid_release_key(keycode);
+  return zmk_endpoints_send_report(changes);
+}
+
+static const struct behavior_driver_api behavior_hid_driver_api = {
+  .keycode_pressed = on_keycode_pressed,
+  .keycode_released = on_keycode_released
+};
+
+
+static const struct behavior_hid_config behavior_hid_config = {};
+
+static struct behavior_hid_data behavior_hid_data;
+
+DEVICE_AND_API_INIT(behavior_hid, DT_INST_LABEL(0), behavior_hid_init,
+                    &behavior_hid_data,
+                    &behavior_hid_config,
+                    APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+                    &behavior_hid_driver_api);
\ No newline at end of file
diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c
index b9d0ff04..3c57c513 100644
--- a/app/src/behaviors/behavior_key_press.c
+++ b/app/src/behaviors/behavior_key_press.c
@@ -10,6 +10,8 @@
 #include <drivers/behavior.h>
 #include <logging/log.h>
 
+#include <zmk/events.h>
+
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
 struct behavior_key_press_config { };
@@ -29,19 +31,16 @@ static int behavior_key_press_init(struct device *dev)
 //  * < 0 - Indicate error processing, report and halt further propagation.
 static int on_position_pressed(struct device *dev, u32_t keycode, u32_t _)
 {
-  // Invoking this triggers a *new* event, that can be linked to other behaviours.
-  //return zmk_key_state_press(u32_t keycode);
-  return 0;
+  LOG_DBG("pressing: %d", keycode);
+  return zmk_events_keycode_pressed(keycode);
 }
 
 
 // They keycode is passed by the "keymap" based on the parameter created as part of the assignment.
 static int on_position_released(struct device *dev, u32_t keycode, u32_t _)
 {
-  // Invoking this triggers a *new* event, that can will be handled by other behaviors
-  // This is the "command" piece. Which could be better/richer, but captures essence here.
-  // return zmk_key_state_release(u32_t keycode);
-  return 0;
+  LOG_DBG("releasing: %d", keycode);
+  return zmk_events_keycode_released(keycode);
 }
 
 static const struct behavior_driver_api behavior_key_press_driver_api = {
diff --git a/app/src/behaviors/behavior_keymap.c b/app/src/behaviors/behavior_keymap.c
new file mode 100644
index 00000000..48f85473
--- /dev/null
+++ b/app/src/behaviors/behavior_keymap.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_keymap
+
+#include <device.h>
+#include <power/reboot.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+#include <zmk/keymap.h>
+
+struct behavior_keymap_config { };
+struct behavior_keymap_data { };
+
+static int behavior_keymap_init(struct device *dev)
+{
+	return 0;
+};
+
+static int on_position_pressed(struct device *dev, u32_t row, u32_t column)
+{
+  return zmk_keymap_position_state_changed(row, column, true);
+}
+
+static int on_position_released(struct device *dev, u32_t row, u32_t column)
+{
+  return zmk_keymap_position_state_changed(row, column, false);
+}
+
+static const struct behavior_driver_api behavior_keymap_driver_api = {
+  .position_pressed = on_position_pressed,
+  .position_released = on_position_released
+};
+
+
+static const struct behavior_keymap_config behavior_keymap_config = {};
+
+static struct behavior_keymap_data behavior_keymap_data;
+
+DEVICE_AND_API_INIT(behavior_keymap, DT_INST_LABEL(0), behavior_keymap_init,
+                    &behavior_keymap_data,
+                    &behavior_keymap_config,
+                    APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+                    &behavior_keymap_driver_api);
\ No newline at end of file
diff --git a/app/src/endpoints.c b/app/src/endpoints.c
index f46d42df..2f31e109 100644
--- a/app/src/endpoints.c
+++ b/app/src/endpoints.c
@@ -40,6 +40,7 @@ int zmk_endpoints_send_report(enum zmk_hid_report_changes report_type)
     int err;
     struct zmk_hid_keypad_report *keypad_report;
     struct zmk_hid_consumer_report *consumer_report;
+    LOG_DBG("");
     switch (report_type)
     {
     case Keypad:
diff --git a/app/src/events.c b/app/src/events.c
new file mode 100644
index 00000000..c3e8d841
--- /dev/null
+++ b/app/src/events.c
@@ -0,0 +1,72 @@
+
+#include <zephyr.h>
+#include <drivers/behavior.h>
+#include <zmk/behavior.h>
+#include <zmk/events.h>
+#include <sys/util.h>
+
+#define BINDINGS_NODE DT_CHOSEN(zmk_global_bindings)
+#define BINDING_COUNT DT_PROP_LEN(BINDINGS_NODE, bindings)
+
+#define BINDING_GEN(idx,_) \
+    { .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(BINDINGS_NODE, bindings, idx)), \
+	  .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(BINDINGS_NODE, bindings, idx, param1), (0), (DT_PHA_BY_IDX(BINDINGS_NODE, bindings, idx, param1))), \
+	  .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(BINDINGS_NODE, bindings, idx, param2), (0), (DT_PHA_BY_IDX(BINDINGS_NODE, bindings, idx, param2))), \
+	},
+
+static const struct zmk_behavior_binding bindings[] =
+    { UTIL_LISTIFY(BINDING_COUNT, BINDING_GEN, 0) };
+
+int zmk_events_position_pressed(u32_t row, u32_t column)
+{
+    for (int i = 0; i < BINDING_COUNT; i++) {
+        const struct zmk_behavior_binding *b = &bindings[i];
+        struct device *dev = device_get_binding(b->behavior_dev);
+        behavior_position_pressed(dev, row, column);
+    }
+    return 0;
+};
+
+int zmk_events_position_released(u32_t row, u32_t column)
+{
+    for (int i = 0; i < BINDING_COUNT; i++) {
+        const struct zmk_behavior_binding *b = &bindings[i];
+        struct device *dev = device_get_binding(b->behavior_dev);
+        behavior_position_released(dev, row, column);
+    }
+    return 0;
+}
+int zmk_events_keycode_pressed(u32_t keycode)
+{
+    for (int i = 0; i < BINDING_COUNT; i++) {
+        const struct zmk_behavior_binding *b = &bindings[i];
+        struct device *dev = device_get_binding(b->behavior_dev);
+        behavior_keycode_pressed(dev, keycode);
+    }
+    return 0;
+}
+int zmk_events_keycode_released(u32_t keycode)
+{
+    for (int i = 0; i < BINDING_COUNT; i++) {
+        const struct zmk_behavior_binding *b = &bindings[i];
+        struct device *dev = device_get_binding(b->behavior_dev);
+        behavior_keycode_released(dev, keycode);
+    }
+    return 0;
+};
+int zmk_events_mod_pressed(u32_t modifier)
+{
+    return 0;
+};
+int zmk_events_mod_released(u32_t modifier)
+{
+    return 0;
+};
+int zmk_events_consumer_key_pressed(u32_t usage)
+{
+    return 0;
+};
+int zmk_events_consumer_key_released(u32_t usage)
+{
+    return 0;
+};
\ No newline at end of file
diff --git a/app/src/kscan.c b/app/src/kscan.c
index d1ed6210..781824df 100644
--- a/app/src/kscan.c
+++ b/app/src/kscan.c
@@ -11,7 +11,7 @@
 
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
-#include <zmk/keymap.h>
+#include <zmk/events.h>
 #include <zmk/handlers.h>
 
 #define ZMK_KSCAN_EVENT_STATE_PRESSED 0
@@ -49,7 +49,14 @@ void zmk_kscan_process_msgq(struct k_work *item)
 	while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0)
 	{
 		bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
-		zmk_keymap_position_state_changed(ev.row, ev.column, pressed);
+		if (pressed) {
+			LOG_DBG("PRESSING");
+			zmk_events_position_pressed(ev.row, ev.column);
+		} else {
+			LOG_DBG("RELEASSING");
+			zmk_events_position_released(ev.row, ev.column);
+		}
+		// zmk_keymap_position_state_changed(ev.row, ev.column, pressed);
 		// zmk_key key = zmk_keymap_keycode_from_position(ev.row, ev.column);
 		// struct zmk_key_event kev = (struct zmk_key_event){.row = ev.row, .column = ev.column, .key = key, .pressed = pressed};
 
diff --git a/app/src/kscan_mock.c b/app/src/kscan_mock.c
index 7d2d24d2..b0ba90bb 100644
--- a/app/src/kscan_mock.c
+++ b/app/src/kscan_mock.c
@@ -9,6 +9,7 @@
 #include <device.h>
 #include <drivers/kscan.h>
 #include <logging/log.h>
+
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
 #include <zmk/kscan-mock.h>

From 7e659851c80bf2819554d93ad9971f56aa5b225b Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sat, 20 Jun 2020 17:54:52 -0400
Subject: [PATCH 03/12] Refactor matrix transform, positions pervasively

* Do mapping to positions right in kscan handler, and then
  surface positions throughout the API.
---
 app/CMakeLists.txt                     |  1 +
 app/boards/shields/kyria/kyria.overlay | 39 ++++++++++++++++++++++++++
 app/include/zmk/events.h               |  4 +--
 app/include/zmk/keymap.h               |  2 +-
 app/include/zmk/matrix_transform.h     |  3 ++
 app/src/behaviors/behavior_keymap.c    |  8 +++---
 app/src/events.c                       |  8 +++---
 app/src/keymap.c                       | 35 ++++-------------------
 app/src/kscan.c                        | 16 ++++-------
 app/src/matrix_transform.c             | 30 ++++++++++++++++++++
 10 files changed, 95 insertions(+), 51 deletions(-)
 create mode 100644 app/include/zmk/matrix_transform.h
 create mode 100644 app/src/matrix_transform.c

diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 6f4217aa..ff534fe2 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -28,6 +28,7 @@ endif()
 # find_package(Zephyr) which defines the target.
 target_include_directories(app PRIVATE include)
 target_sources(app PRIVATE src/kscan.c)
+target_sources(app PRIVATE src/matrix_transform.c)
 target_sources(app PRIVATE src/events.c)
 target_sources(app PRIVATE src/keymap.c)
 target_sources(app PRIVATE src/hid.c)
diff --git a/app/boards/shields/kyria/kyria.overlay b/app/boards/shields/kyria/kyria.overlay
index af4e591c..4140fcfc 100644
--- a/app/boards/shields/kyria/kyria.overlay
+++ b/app/boards/shields/kyria/kyria.overlay
@@ -4,9 +4,20 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/matrix-transform.h>
+#include <behaviors/keymap.dtsi>
+#include <behaviors/hid.dtsi>
+
 / {
 	chosen {
 		zmk,kscan = &kscan0;
+		zmk,matrix_transform = &default_transform;
+		zmk,global_bindings = &bindings;
+	};
+
+	bindings: global_bindings {
+		compatible = "zmk,global-bindings";
+		bindings = <&keymap_behavior &hid_behavior>;
 	};
 
 	kscan0: kscan_comp {
@@ -28,6 +39,34 @@
 		};
 	};
 
+	default_transform: keymap_transform_0 {
+		compatible = "zmk,matrix-transform";
+// | MX6  | MX5  | MX4  | MX3  | MX2  | MX1  |                               | MX1  | MX2  | MX3  | MX4  | MX5  | MX6  |
+// | MX12 | MX11 | MX10 | MX9  | MX8  | MX7  |                               | MX7  | MX8  | MX9  | MX10 | MX11 | MX12 |
+// | MX20 | MX19 | MX18 | MX17 | MX16 | MX15 | MX14 | MX13 |   | MX13 | MX14 | MX15 | MX16 | MX17 | MX18 | MX19 | MX20 |
+//                    | MX25 | MX24 | MX23 | MX22 | MX21 |       | MX21 | MX22 | MX23 | MX24 | MX25 |
+		map = <
+RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5)                                 RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,15)
+RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5)                                 RC(1,10) RC(1,11) RC(1,12) RC(1,13) RC(1,14) RC(1,15)
+RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13) RC(2,14) RC(2,15)
+                        RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12)
+		>;
+	};
+
+// | MX5  | MX4  | MX3  | MX2  | MX1  |                               | MX1  | MX2  | MX3  | MX4  | MX5  |
+// | MX11 | MX10 | MX9  | MX8  | MX7  |                               | MX7  | MX8  | MX9  | MX10 | MX11 |
+// | MX19 | MX18 | MX17 | MX16 | MX15 | MX14 | MX13 |   | MX13 | MX14 | MX15 | MX16 | MX17 | MX18 | MX19 |
+//             | MX25 | MX24 | MX23 | MX22 | MX21 |       | MX21 | MX22 | MX23 | MX24 | MX25 |
+	five_column_transform: keymap_transform_1 {
+		compatible = "zmk,matrix-transform";
+		map = <
+RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4)                                 RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13)
+RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4)                                 RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13)
+RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13)
+                RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
+		>;
+	};
+
 	kscan_left: kscan_left {
 		compatible = "gpio-kscan";
 		label = "KSCAN_LEFT";
diff --git a/app/include/zmk/events.h b/app/include/zmk/events.h
index 9314b9d0..ac4815a9 100644
--- a/app/include/zmk/events.h
+++ b/app/include/zmk/events.h
@@ -1,7 +1,7 @@
 #pragma once
 
-int zmk_events_position_pressed(u32_t row, u32_t column);
-int zmk_events_position_released(u32_t row, u32_t column);
+int zmk_events_position_pressed(u32_t position);
+int zmk_events_position_released(u32_t position);
 int zmk_events_keycode_pressed(u32_t keycode);
 int zmk_events_keycode_released(u32_t keycode);
 int zmk_events_mod_pressed(u32_t modifier);
diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h
index 7866cd57..cf38904a 100644
--- a/app/include/zmk/keymap.h
+++ b/app/include/zmk/keymap.h
@@ -11,4 +11,4 @@
 bool zmk_keymap_layer_activate(u8_t layer);
 bool zmk_keymap_layer_deactivate(u8_t layer);
 
-int zmk_keymap_position_state_changed(u32_t row, u32_t column, bool pressed);
+int zmk_keymap_position_state_changed(u32_t position, bool pressed);
diff --git a/app/include/zmk/matrix_transform.h b/app/include/zmk/matrix_transform.h
new file mode 100644
index 00000000..e9e969a4
--- /dev/null
+++ b/app/include/zmk/matrix_transform.h
@@ -0,0 +1,3 @@
+#pragma once
+
+u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column);
\ No newline at end of file
diff --git a/app/src/behaviors/behavior_keymap.c b/app/src/behaviors/behavior_keymap.c
index 48f85473..9369b404 100644
--- a/app/src/behaviors/behavior_keymap.c
+++ b/app/src/behaviors/behavior_keymap.c
@@ -23,14 +23,14 @@ static int behavior_keymap_init(struct device *dev)
 	return 0;
 };
 
-static int on_position_pressed(struct device *dev, u32_t row, u32_t column)
+static int on_position_pressed(struct device *dev, u32_t position, u32_t _)
 {
-  return zmk_keymap_position_state_changed(row, column, true);
+  return zmk_keymap_position_state_changed(position, true);
 }
 
-static int on_position_released(struct device *dev, u32_t row, u32_t column)
+static int on_position_released(struct device *dev, u32_t position, u32_t _)
 {
-  return zmk_keymap_position_state_changed(row, column, false);
+  return zmk_keymap_position_state_changed(position, false);
 }
 
 static const struct behavior_driver_api behavior_keymap_driver_api = {
diff --git a/app/src/events.c b/app/src/events.c
index c3e8d841..73c0e291 100644
--- a/app/src/events.c
+++ b/app/src/events.c
@@ -17,22 +17,22 @@
 static const struct zmk_behavior_binding bindings[] =
     { UTIL_LISTIFY(BINDING_COUNT, BINDING_GEN, 0) };
 
-int zmk_events_position_pressed(u32_t row, u32_t column)
+int zmk_events_position_pressed(u32_t position)
 {
     for (int i = 0; i < BINDING_COUNT; i++) {
         const struct zmk_behavior_binding *b = &bindings[i];
         struct device *dev = device_get_binding(b->behavior_dev);
-        behavior_position_pressed(dev, row, column);
+        behavior_position_pressed(dev, position, 0);
     }
     return 0;
 };
 
-int zmk_events_position_released(u32_t row, u32_t column)
+int zmk_events_position_released(u32_t position)
 {
     for (int i = 0; i < BINDING_COUNT; i++) {
         const struct zmk_behavior_binding *b = &bindings[i];
         struct device *dev = device_get_binding(b->behavior_dev);
-        behavior_position_released(dev, row, column);
+        behavior_position_released(dev, position, 0);
     }
     return 0;
 }
diff --git a/app/src/keymap.c b/app/src/keymap.c
index 386de81f..6ee61ec3 100644
--- a/app/src/keymap.c
+++ b/app/src/keymap.c
@@ -4,42 +4,22 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 #include <zmk/keymap.h>
 #include <dt-bindings/zmk/matrix-transform.h>
 #include <drivers/behavior.h>
+#include <zmk/behavior.h>
 #include <sys/util.h>
 
 static u32_t zmk_keymap_layer_state = 0;
 static u8_t zmk_keymap_layer_default = 0;
 
-struct zmk_behavior_binding {
-	char *behavior_dev;
-	u32_t param1;
-	u32_t param2;
-};
-
 #define ZMK_KEYMAP_NODE DT_CHOSEN(zmk_keymap)
 #define ZMK_KEYMAP_LAYERS_LEN DT_PROP_LEN(ZMK_KEYMAP_NODE, layers)
 
 #define LAYER_NODE(l) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, l)
 
-#define BINDING_FOR_IDX(layer,idx) \
+#define _TRANSFORM_ENTRY(idx, layer) \
 	{ .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, layer), bindings, idx)), \
 	  .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), bindings, idx, param1), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), bindings, idx, param1))), \
 	  .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), bindings, idx, param2), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), bindings, idx, param2))), \
-	}
-
-#if DT_NODE_HAS_PROP(ZMK_KEYMAP_NODE, transform)
-#define ZMK_KEYMAP_TRANSFORM_NODE DT_PHANDLE(ZMK_KEYMAP_NODE, transform)
-#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_TRANSFORM_NODE, map)
-
-#define _TRANSFORM_ENTRY(i, l) \
-	[(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))] = BINDING_FOR_IDX(l,i),
-
-#else
-
-#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_NODE, bindings)
-#define _TRANSFORM_ENTRY(i, l) \
-	BINDING_FOR_IDX(l,i),
-
-#endif
+	},
 
 #define TRANSFORMED_LAYER(idx) \
   { UTIL_LISTIFY(DT_PROP_LEN(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, idx), bindings), _TRANSFORM_ENTRY, idx) }
@@ -77,8 +57,6 @@ static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_
 #endif
 };
 
-// #else
-
 #define SET_LAYER_STATE(layer, state)                \
 	if (layer >= 32)                                 \
 	{                                                \
@@ -97,18 +75,17 @@ bool zmk_keymap_layer_deactivate(u8_t layer)
 	SET_LAYER_STATE(layer, false);
 };
 
-int zmk_keymap_position_state_changed(u32_t row, u32_t column, 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--)
 	{
 		if ((zmk_keymap_layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default)
 		{
-			u8_t key_index = (row * ZMK_MATRIX_COLS) + column;
-			struct zmk_behavior_binding *binding = &zmk_keymap[layer][key_index];
+			struct zmk_behavior_binding *binding = &zmk_keymap[layer][position];
 			struct device *behavior;
 			int ret;
 
-			LOG_DBG("key index: %d, binding name: %s", key_index, binding->behavior_dev);
+			LOG_DBG("position: %d, binding name: %s", position, binding->behavior_dev);
 
 			behavior = device_get_binding(binding->behavior_dev);
 			if (pressed) {
diff --git a/app/src/kscan.c b/app/src/kscan.c
index 781824df..29a60199 100644
--- a/app/src/kscan.c
+++ b/app/src/kscan.c
@@ -11,8 +11,8 @@
 
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
+#include <zmk/matrix_transform.h>
 #include <zmk/events.h>
-#include <zmk/handlers.h>
 
 #define ZMK_KSCAN_EVENT_STATE_PRESSED 0
 #define ZMK_KSCAN_EVENT_STATE_RELEASED 1
@@ -49,19 +49,13 @@ void zmk_kscan_process_msgq(struct k_work *item)
 	while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0)
 	{
 		bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED);
+		u32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column);
+		LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s\n", ev.row, ev.column, position, (pressed ? "true" : "false"));
 		if (pressed) {
-			LOG_DBG("PRESSING");
-			zmk_events_position_pressed(ev.row, ev.column);
+			zmk_events_position_pressed(position);
 		} else {
-			LOG_DBG("RELEASSING");
-			zmk_events_position_released(ev.row, ev.column);
+			zmk_events_position_released(position);
 		}
-		// zmk_keymap_position_state_changed(ev.row, ev.column, pressed);
-		// zmk_key key = zmk_keymap_keycode_from_position(ev.row, ev.column);
-		// struct zmk_key_event kev = (struct zmk_key_event){.row = ev.row, .column = ev.column, .key = key, .pressed = pressed};
-
-		// LOG_DBG("Row: %d, col: %d, key: %d, pressed: %s\n", ev.row, ev.column, key, (pressed ? "true" : "false"));
-		// zmk_handle_key(kev);
 	}
 }
 
diff --git a/app/src/matrix_transform.c b/app/src/matrix_transform.c
new file mode 100644
index 00000000..7e8b481e
--- /dev/null
+++ b/app/src/matrix_transform.c
@@ -0,0 +1,30 @@
+
+#include <zephyr.h>
+#include <zmk/matrix_transform.h>
+#include <zmk/matrix.h>
+#include <dt-bindings/zmk/matrix-transform.h>
+
+#define HAS_TRANSFORM DT_HAS_CHOSEN(zmk_matrix_transform)
+
+#if HAS_TRANSFORM
+#define ZMK_KEYMAP_TRANSFORM_NODE DT_CHOSEN(zmk_matrix_transform)
+#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_TRANSFORM_NODE, map)
+
+#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,
+
+static u32_t transform[] = 
+    { UTIL_LISTIFY(ZMK_KEYMAP_LEN, _TRANSFORM_ENTRY, 0) };
+
+#endif
+
+u32_t zmk_matrix_transform_row_column_to_position(u32_t row, u32_t column)
+{
+    u32_t matrix_index = (row * ZMK_MATRIX_COLS) + column;
+
+#if HAS_TRANSFORM
+    return transform[matrix_index];
+#else
+    return matrix_index;
+#endif /* HAS_TRANSFORM */
+};

From 223edf05ad08938b066f9187668ebfae43c5e91a Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sun, 21 Jun 2020 21:43:44 -0400
Subject: [PATCH 04/12] Refactor global bindings, implement mod-tap.

* Use extra comptible = "zmk,behavior-global" to add
   behaviors to global bindings for event notification.
* Implement mod-tap, as a keymap binding and global one
  to skip tap if other keycode pressed while held.
---
 app/CMakeLists.txt                            |   1 +
 app/boards/native_posix.overlay               |   9 +-
 app/boards/shields/kyria/kyria.overlay        |   6 -
 .../keymap/keymap.overlay                     |   5 -
 app/dts/behaviors/hid.dtsi                    |   2 +-
 app/dts/behaviors/keymap.dtsi                 |   2 +-
 app/dts/behaviors/mod_tap.dtsi                |   9 ++
 .../behaviors/zmk,behavior-mod-tap.yaml       |   8 ++
 app/dts/bindings/zmk,global-bindings.yaml     |   9 --
 app/include/drivers/behavior.h                | 119 ++++++++++++++++--
 app/include/zmk/events.h                      |   6 +-
 app/include/zmk/keymap.h                      |   8 --
 app/include/zmk/matrix.h                      |   2 +
 app/src/behaviors/behavior_hid.c              |  20 ++-
 app/src/behaviors/behavior_key_press.c        |  12 +-
 app/src/behaviors/behavior_keymap.c           |   8 +-
 app/src/behaviors/behavior_mod_tap.c          |  89 +++++++++++++
 app/src/behaviors/behavior_reset.c            |  10 +-
 app/src/events.c                              |  69 +++++-----
 app/src/keymap.c                              |  13 +-
 20 files changed, 307 insertions(+), 100 deletions(-)
 create mode 100644 app/dts/behaviors/mod_tap.dtsi
 create mode 100644 app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml
 delete mode 100644 app/dts/bindings/zmk,global-bindings.yaml
 create mode 100644 app/src/behaviors/behavior_mod_tap.c

diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index ff534fe2..e91bd58a 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -36,6 +36,7 @@ target_sources(app PRIVATE src/behaviors/behavior_keymap.c)
 target_sources(app PRIVATE src/behaviors/behavior_hid.c)
 target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
 target_sources(app PRIVATE src/behaviors/behavior_reset.c)
+target_sources(app PRIVATE src/behaviors/behavior_mod_tap.c)
 target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
 target_sources_ifdef(CONFIG_ZMK_KSCAN_MOCK_DRIVER app PRIVATE src/kscan_mock.c)
 target_sources_ifdef(CONFIG_ZMK_KSCAN_COMPOSITE_DRIVER app PRIVATE src/kscan_composite.c)
diff --git a/app/boards/native_posix.overlay b/app/boards/native_posix.overlay
index 3f2eead1..80047054 100644
--- a/app/boards/native_posix.overlay
+++ b/app/boards/native_posix.overlay
@@ -1,5 +1,6 @@
 #include <dt-bindings/zmk/keys.h>
 #include <behaviors/key_press.dtsi>
+#include <behaviors/mod_tap.dtsi>
 #include <behaviors/reset.dtsi>
 #include <behaviors/keymap.dtsi>
 #include <behaviors/hid.dtsi>
@@ -9,12 +10,6 @@
 	chosen {
 		zmk,kscan = &kscan0;
 		zmk,keymap = &keymap0;
-		zmk,global_bindings = &bindings;
-	};
-
-	bindings: global_bindings {
-		compatible = "zmk,global-bindings";
-		bindings = <&keymap_behavior &hid_behavior>;
 	};
 
 	kscan0: kscan_0 {
@@ -70,7 +65,7 @@
 			>;
 
 			bindings = <
-				&kp 5 &kp 0 &kp 10 &kp 11
+				&kp 5 &mt MOD_LSFT KC_B &kp 10 &kp 11
 				&kp 1  &kp 2 &kp 4 &kp 89>;
 		};
 
diff --git a/app/boards/shields/kyria/kyria.overlay b/app/boards/shields/kyria/kyria.overlay
index 4140fcfc..d560ed69 100644
--- a/app/boards/shields/kyria/kyria.overlay
+++ b/app/boards/shields/kyria/kyria.overlay
@@ -12,12 +12,6 @@
 	chosen {
 		zmk,kscan = &kscan0;
 		zmk,matrix_transform = &default_transform;
-		zmk,global_bindings = &bindings;
-	};
-
-	bindings: global_bindings {
-		compatible = "zmk,global-bindings";
-		bindings = <&keymap_behavior &hid_behavior>;
 	};
 
 	kscan0: kscan_comp {
diff --git a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
index 5ae78cf8..1a70ff4c 100644
--- a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
@@ -7,13 +7,8 @@
 / {
 	chosen {
 		zmk,keymap = &keymap0;
-		zmk,global_bindings = &bindings;
 	};
 
-	bindings: global_bindings {
-		compatible = "zmk,global-bindings";
-		bindings = <&reset>;
-	};
 	keymap0: keymap {
 		compatible = "zmk,keymap";
 		label ="Default keymap";
diff --git a/app/dts/behaviors/hid.dtsi b/app/dts/behaviors/hid.dtsi
index d859c378..30ebb090 100644
--- a/app/dts/behaviors/hid.dtsi
+++ b/app/dts/behaviors/hid.dtsi
@@ -1,7 +1,7 @@
 / {
 	behaviors {
 		hid_behavior: behavior_hid {
-			compatible = "zmk,behavior-hid";
+			compatible = "zmk,behavior-hid", "zmk,behavior-global";
 			label = "HID";
 			#binding-cells = <0>;
 		};
diff --git a/app/dts/behaviors/keymap.dtsi b/app/dts/behaviors/keymap.dtsi
index 87b2f41c..ec434d5f 100644
--- a/app/dts/behaviors/keymap.dtsi
+++ b/app/dts/behaviors/keymap.dtsi
@@ -1,7 +1,7 @@
 / {
 	behaviors {
 		keymap_behavior: behavior_keymap {
-			compatible = "zmk,behavior-keymap";
+			compatible = "zmk,behavior-keymap", "zmk,behavior-global";
 			label = "KEYMAP";
 			#binding-cells = <0>;
 		};
diff --git a/app/dts/behaviors/mod_tap.dtsi b/app/dts/behaviors/mod_tap.dtsi
new file mode 100644
index 00000000..1be7db6f
--- /dev/null
+++ b/app/dts/behaviors/mod_tap.dtsi
@@ -0,0 +1,9 @@
+/ {
+	behaviors {
+		mt: behavior_mod_tap {
+			compatible = "zmk,behavior-mod-tap", "zmk,behavior-global";
+			label = "MOD_TAP";
+			#binding-cells = <2>;
+		};
+	};
+};
diff --git a/app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml b/app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml
new file mode 100644
index 00000000..7911082f
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+description: Mod-Tap Beavhior
+
+compatible: "zmk,behavior-mod-tap"
+
+include: two_param.yaml
diff --git a/app/dts/bindings/zmk,global-bindings.yaml b/app/dts/bindings/zmk,global-bindings.yaml
deleted file mode 100644
index 69e79cda..00000000
--- a/app/dts/bindings/zmk,global-bindings.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-description: |
-  Specify the the global behaviors bound to state changes
-
-compatible: "zmk,global-bindings"
-
-properties:
-  bindings:
-    type: phandles
-    required: true
diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h
index f5f5f537..b3c6ad2c 100644
--- a/app/include/drivers/behavior.h
+++ b/app/include/drivers/behavior.h
@@ -9,6 +9,7 @@
 #include <zephyr/types.h>
 #include <stddef.h>
 #include <device.h>
+#include <zmk/keys.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -22,30 +23,36 @@ extern "C" {
  * (Internal use only.)
  */
 
-typedef int (*behavior_position_callback_t)(struct device *dev, u32_t param1, u32_t param2);
+typedef int (*behavior_position_callback_t)(struct device *dev, u32_t position);
+typedef int (*behavior_keymap_binding_callback_t)(struct device *dev, u32_t position, u32_t param1, u32_t param2);
 typedef int (*behavior_keycode_callback_t)(struct device *dev, u32_t keycode);
+typedef int (*behavior_modifiers_callback_t)(struct device *dev, zmk_mod_flags modifiers);
 
 __subsystem struct behavior_driver_api {
 	behavior_position_callback_t position_pressed;
 	behavior_position_callback_t position_released;
+	behavior_keymap_binding_callback_t binding_pressed;
+	behavior_keymap_binding_callback_t binding_released;
 	behavior_keycode_callback_t keycode_pressed;
 	behavior_keycode_callback_t keycode_released;
+	behavior_modifiers_callback_t modifiers_pressed;
+	behavior_modifiers_callback_t modifiers_released;
 };
 /**
  * @endcond
  */
 
 /**
- * @brief Handle the assigned position being pressed
+ * @brief Handle the key position being pressed
  * @param dev Pointer to the device structure for the driver instance.
- * @param param1 User parameter specified at time of behavior assignment.
+ * @param position They key position that was pressed
  *
  * @retval 0 If successful.
  * @retval Negative errno code if failure.
  */
-__syscall int behavior_position_pressed(struct device *dev, u32_t param1, u32_t param2);
+__syscall int behavior_position_pressed(struct device *dev, u32_t position);
 
-static inline int z_impl_behavior_position_pressed(struct device *dev, u32_t param1, u32_t param2)
+static inline int z_impl_behavior_position_pressed(struct device *dev, u32_t position)
 {
 	const struct behavior_driver_api *api =
 			(const struct behavior_driver_api *)dev->driver_api;
@@ -54,7 +61,52 @@ static inline int z_impl_behavior_position_pressed(struct device *dev, u32_t par
 		return -ENOTSUP;
 	}
 
-	return api->position_pressed(dev, param1, param2);
+	return api->position_pressed(dev, position);
+}
+
+/**
+ * @brief Handle the key position being released
+ * @param dev Pointer to the device structure for the driver instance.
+ * @param position They key position that was released
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int behavior_position_released(struct device *dev, u32_t position);
+
+static inline int z_impl_behavior_position_released(struct device *dev, u32_t position)
+{
+	const struct behavior_driver_api *api =
+			(const struct behavior_driver_api *)dev->driver_api;
+
+	if (api->position_released == NULL) {
+		return -ENOTSUP;
+	}
+
+	return api->position_released(dev, position);
+}
+
+/**
+ * @brief Handle the keymap binding being pressed
+ * @param dev Pointer to the device structure for the driver instance.
+ * @param param1 User parameter specified at time of behavior binding.
+ * @param param2 User parameter specified at time of behavior binding.
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1, u32_t param2);
+
+static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1, u32_t param2)
+{
+	const struct behavior_driver_api *api =
+			(const struct behavior_driver_api *)dev->driver_api;
+
+	if (api->binding_pressed == NULL) {
+		return -ENOTSUP;
+	}
+
+	return api->binding_pressed(dev, position, param1, param2);
 }
 
 /**
@@ -65,20 +117,21 @@ static inline int z_impl_behavior_position_pressed(struct device *dev, u32_t par
  * @retval 0 If successful.
  * @retval Negative errno code if failure.
  */
-__syscall int behavior_position_released(struct device *dev, 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_position_released(struct device *dev, u32_t param1, u32_t param2)
+static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u32_t position, u32_t param1, u32_t param2)
 {
 	const struct behavior_driver_api *api =
 			(const struct behavior_driver_api *)dev->driver_api;
 
-	if (api->position_released == NULL) {
+	if (api->binding_released == NULL) {
 		return -ENOTSUP;
 	}
 
-	return api->position_released(dev, param1, param2);
+	return api->binding_released(dev, position, param1, param2);
 }
 
+
 /**
  * @brief Handle the keycode being pressed
  * @param dev Pointer to the device structure for the driver instance.
@@ -124,6 +177,52 @@ static inline int z_impl_behavior_keycode_released(struct device *dev, u32_t key
 	return api->keycode_released(dev, keycode);
 }
 
+
+/**
+ * @brief Handle the keycode being pressed
+ * @param dev Pointer to the device structure for the driver instance.
+ * @param keycode The keycode that is being pressed.
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int behavior_modifiers_pressed(struct device *dev, zmk_mod_flags modifiers);
+
+static inline int z_impl_behavior_modifiers_pressed(struct device *dev, zmk_mod_flags modifiers)
+{
+	const struct behavior_driver_api *api =
+			(const struct behavior_driver_api *)dev->driver_api;
+
+	if (api->modifiers_pressed == NULL) {
+		return -ENOTSUP;
+	}
+
+	return api->modifiers_pressed(dev, modifiers);
+}
+
+
+/**
+ * @brief Handle the keycode being released
+ * @param dev Pointer to the device structure for the driver instance.
+ * @param keycode The keycode that is being pressed.
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int behavior_modifiers_released(struct device *dev, zmk_mod_flags modifiers);
+
+static inline int z_impl_behavior_modifiers_released(struct device *dev, zmk_mod_flags modifiers)
+{
+	const struct behavior_driver_api *api =
+			(const struct behavior_driver_api *)dev->driver_api;
+
+	if (api->modifiers_released == NULL) {
+		return -ENOTSUP;
+	}
+
+	return api->modifiers_released(dev, modifiers);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/app/include/zmk/events.h b/app/include/zmk/events.h
index ac4815a9..8d1ae6af 100644
--- a/app/include/zmk/events.h
+++ b/app/include/zmk/events.h
@@ -1,11 +1,13 @@
 #pragma once
 
+#include <zmk/keys.h>
+
 int zmk_events_position_pressed(u32_t position);
 int zmk_events_position_released(u32_t position);
 int zmk_events_keycode_pressed(u32_t keycode);
 int zmk_events_keycode_released(u32_t keycode);
-int zmk_events_mod_pressed(u32_t modifier);
-int zmk_events_mod_released(u32_t modifier);
+int zmk_events_modifiers_pressed(zmk_mod_flags modifiers);
+int zmk_events_modifiers_released(zmk_mod_flags modifiers);
 int zmk_events_consumer_key_pressed(u32_t usage);
 int zmk_events_consumer_key_released(u32_t usage);
 
diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h
index cf38904a..38c1249d 100644
--- a/app/include/zmk/keymap.h
+++ b/app/include/zmk/keymap.h
@@ -1,13 +1,5 @@
 #pragma once
 
-#include <devicetree.h>
-#include <usb/usb_device.h>
-#include <usb/class/usb_hid.h>
-#include <dt-bindings/zmk/keys.h>
-
-#include <zmk/matrix.h>
-// #include <zmk/keys.h>
-
 bool zmk_keymap_layer_activate(u8_t layer);
 bool zmk_keymap_layer_deactivate(u8_t layer);
 
diff --git a/app/include/zmk/matrix.h b/app/include/zmk/matrix.h
index 783c98e2..9cabb7e4 100644
--- a/app/include/zmk/matrix.h
+++ b/app/include/zmk/matrix.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#include <devicetree.h>
+
 #define ZMK_MATRIX_NODE_ID DT_CHOSEN(zmk_kscan)
 
 #if DT_NODE_HAS_PROP(ZMK_MATRIX_NODE_ID,row_gpios)
diff --git a/app/src/behaviors/behavior_hid.c b/app/src/behaviors/behavior_hid.c
index 2779568e..0aeade51 100644
--- a/app/src/behaviors/behavior_hid.c
+++ b/app/src/behaviors/behavior_hid.c
@@ -42,9 +42,27 @@ static int on_keycode_released(struct device *dev, u32_t keycode)
   return zmk_endpoints_send_report(changes);
 }
 
+static int on_modifiers_pressed(struct device *dev, zmk_mod_flags modifiers)
+{
+  LOG_DBG("modifiers %d", modifiers);
+  
+  zmk_hid_register_mods(modifiers);
+  return zmk_endpoints_send_report(Keypad);
+}
+
+static int on_modifiers_released(struct device *dev, zmk_mod_flags modifiers)
+{
+  LOG_DBG("modifiers %d", modifiers);
+  
+  zmk_hid_unregister_mods(modifiers);
+  return zmk_endpoints_send_report(Keypad);
+}
+
 static const struct behavior_driver_api behavior_hid_driver_api = {
   .keycode_pressed = on_keycode_pressed,
-  .keycode_released = on_keycode_released
+  .keycode_released = on_keycode_released,
+  .modifiers_pressed = on_modifiers_pressed,
+  .modifiers_released = on_modifiers_released
 };
 
 
diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c
index 3c57c513..1b3e670f 100644
--- a/app/src/behaviors/behavior_key_press.c
+++ b/app/src/behaviors/behavior_key_press.c
@@ -29,25 +29,25 @@ static int behavior_key_press_init(struct device *dev)
 //  * > 0 -  indicate successful processing, and halt further handling,
 //  * 0 - Indicate successful processing, and continue propagation.
 //  * < 0 - Indicate error processing, report and halt further propagation.
-static int on_position_pressed(struct device *dev, u32_t keycode, u32_t _)
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _)
 {
-  LOG_DBG("pressing: %d", keycode);
+  LOG_DBG("position %d keycode %d", position, keycode);
   return zmk_events_keycode_pressed(keycode);
 }
 
 
 // They keycode is passed by the "keymap" based on the parameter created as part of the assignment.
-static int on_position_released(struct device *dev, u32_t keycode, u32_t _)
+static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _)
 {
-  LOG_DBG("releasing: %d", keycode);
+  LOG_DBG("position %d keycode %d", position, keycode);
   return zmk_events_keycode_released(keycode);
 }
 
 static const struct behavior_driver_api behavior_key_press_driver_api = {
   // These callbacks are all optional, and define which kinds of events the behavior can handle.
   // They can reference local functions defined here, or shared event handlers.
-  .position_pressed = on_position_pressed,
-  .position_released = on_position_released
+  .binding_pressed = on_keymap_binding_pressed,
+  .binding_released = on_keymap_binding_released
   // Other optional callbacks a behavior can implement
   // .on_mouse_moved
   // .on_sensor_data - Any behaviour that wants to be linked to a censor can implement this behavior
diff --git a/app/src/behaviors/behavior_keymap.c b/app/src/behaviors/behavior_keymap.c
index 9369b404..7a06b2fd 100644
--- a/app/src/behaviors/behavior_keymap.c
+++ b/app/src/behaviors/behavior_keymap.c
@@ -23,19 +23,19 @@ static int behavior_keymap_init(struct device *dev)
 	return 0;
 };
 
-static int on_position_pressed(struct device *dev, u32_t position, u32_t _)
+static int on_position_pressed(struct device *dev, u32_t position)
 {
   return zmk_keymap_position_state_changed(position, true);
 }
 
-static int on_position_released(struct device *dev, u32_t position, u32_t _)
+static int on_position_released(struct device *dev, u32_t position)
 {
   return zmk_keymap_position_state_changed(position, false);
 }
 
 static const struct behavior_driver_api behavior_keymap_driver_api = {
   .position_pressed = on_position_pressed,
-  .position_released = on_position_released
+  .position_released = on_position_released,
 };
 
 
@@ -47,4 +47,4 @@ DEVICE_AND_API_INIT(behavior_keymap, DT_INST_LABEL(0), behavior_keymap_init,
                     &behavior_keymap_data,
                     &behavior_keymap_config,
                     APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
-                    &behavior_keymap_driver_api);
\ No newline at end of file
+                    &behavior_keymap_driver_api);
diff --git a/app/src/behaviors/behavior_mod_tap.c b/app/src/behaviors/behavior_mod_tap.c
new file mode 100644
index 00000000..7684c298
--- /dev/null
+++ b/app/src/behaviors/behavior_mod_tap.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_mod_tap
+
+#include <device.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+
+#include <zmk/events.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+struct behavior_mod_tap_config { };
+struct behavior_mod_tap_data {
+  u16_t pending_press_positions;
+};
+
+static int behavior_mod_tap_init(struct device *dev)
+{
+	return 0;
+};
+
+
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t mods, u32_t keycode)
+{
+  struct behavior_mod_tap_data *data = dev->driver_data;
+  LOG_DBG("mods: %d, keycode: %d", mods, keycode);
+  WRITE_BIT(data->pending_press_positions, position, true);
+  return zmk_events_modifiers_pressed(mods);
+}
+
+
+// They keycode is passed by the "keymap" based on the parameter created as part of the assignment.
+static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t mods, u32_t keycode)
+{
+  struct behavior_mod_tap_data *data = dev->driver_data;
+  LOG_DBG("mods: %d, keycode: %d", mods, keycode);
+  
+  zmk_events_modifiers_released(mods);
+  if (data->pending_press_positions & BIT(position)) {
+    zmk_events_keycode_pressed(keycode);
+    k_msleep(10);
+    zmk_events_keycode_released(keycode);
+  }
+
+  return 0;
+}
+
+static int on_keycode_pressed(struct device *dev, u32_t keycode)
+{
+  struct behavior_mod_tap_data *data = dev->driver_data;
+  data->pending_press_positions = 0;
+  LOG_DBG("pressing: %d", keycode);
+  return 0;
+}
+
+
+static int on_keycode_released(struct device *dev, u32_t keycode)
+{
+  LOG_DBG("releasing: %d", keycode);
+  return 0;
+}
+
+static const struct behavior_driver_api behavior_mod_tap_driver_api = {
+  // These callbacks are all optional, and define which kinds of events the behavior can handle.
+  // They can reference local functions defined here, or shared event handlers.
+  .binding_pressed = on_keymap_binding_pressed,
+  .binding_released = on_keymap_binding_released,
+  .keycode_pressed = on_keycode_pressed,
+  .keycode_released = on_keycode_released
+  // Other optional callbacks a behavior can implement
+  // .on_mouse_moved
+  // .on_sensor_data - Any behaviour that wants to be linked to a censor can implement this behavior
+};
+
+
+static const struct behavior_mod_tap_config behavior_mod_tap_config = {};
+
+static struct behavior_mod_tap_data behavior_mod_tap_data;
+
+DEVICE_AND_API_INIT(behavior_key_press, DT_INST_LABEL(0), behavior_mod_tap_init,
+                    &behavior_mod_tap_data,
+                    &behavior_mod_tap_config,
+                    APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+                    &behavior_mod_tap_driver_api);
diff --git a/app/src/behaviors/behavior_reset.c b/app/src/behaviors/behavior_reset.c
index 1609fad6..44cbc219 100644
--- a/app/src/behaviors/behavior_reset.c
+++ b/app/src/behaviors/behavior_reset.c
@@ -21,7 +21,7 @@ static int behavior_reset_init(struct device *dev)
 	return 0;
 };
 
-static int on_position_pressed(struct device *dev, u32_t _param1, u32_t _param2)
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
 {
   // TODO: Correct magic code for going into DFU?
   // See https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
@@ -29,14 +29,8 @@ static int on_position_pressed(struct device *dev, u32_t _param1, u32_t _param2)
   return 0;
 }
 
-static int on_position_released(struct device *dev, u32_t _param1, u32_t _param2)
-{
-  return 0;
-}
-
 static const struct behavior_driver_api behavior_reset_driver_api = {
-  .position_pressed = on_position_pressed,
-  .position_released = on_position_released
+  .binding_pressed = on_keymap_binding_pressed,
 };
 
 
diff --git a/app/src/events.c b/app/src/events.c
index 73c0e291..376f370a 100644
--- a/app/src/events.c
+++ b/app/src/events.c
@@ -5,63 +5,74 @@
 #include <zmk/events.h>
 #include <sys/util.h>
 
-#define BINDINGS_NODE DT_CHOSEN(zmk_global_bindings)
-#define BINDING_COUNT DT_PROP_LEN(BINDINGS_NODE, bindings)
+#define DT_DRV_COMPAT zmk_behavior_global
+#define GLOBAL_BEHAVIOR_LEN DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)
 
-#define BINDING_GEN(idx,_) \
-    { .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(BINDINGS_NODE, bindings, idx)), \
-	  .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(BINDINGS_NODE, bindings, idx, param1), (0), (DT_PHA_BY_IDX(BINDINGS_NODE, bindings, idx, param1))), \
-	  .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(BINDINGS_NODE, bindings, idx, param2), (0), (DT_PHA_BY_IDX(BINDINGS_NODE, bindings, idx, param2))), \
-	},
-
-static const struct zmk_behavior_binding bindings[] =
-    { UTIL_LISTIFY(BINDING_COUNT, BINDING_GEN, 0) };
+#define LABEL_ENTRY(i) DT_INST_LABEL(i),
+static const char *global_behaviors[] = {
+    DT_INST_FOREACH_STATUS_OKAY(LABEL_ENTRY)
+};
 
 int zmk_events_position_pressed(u32_t position)
 {
-    for (int i = 0; i < BINDING_COUNT; i++) {
-        const struct zmk_behavior_binding *b = &bindings[i];
-        struct device *dev = device_get_binding(b->behavior_dev);
-        behavior_position_pressed(dev, position, 0);
+    for (int i = 0; i < GLOBAL_BEHAVIOR_LEN; i++) {
+        const char* label = global_behaviors[i];
+        struct device *dev = device_get_binding(label);
+        behavior_position_pressed(dev, position);
     }
     return 0;
 };
 
 int zmk_events_position_released(u32_t position)
 {
-    for (int i = 0; i < BINDING_COUNT; i++) {
-        const struct zmk_behavior_binding *b = &bindings[i];
-        struct device *dev = device_get_binding(b->behavior_dev);
-        behavior_position_released(dev, position, 0);
+    for (int i = 0; i < GLOBAL_BEHAVIOR_LEN; i++) {
+        const char* label = global_behaviors[i];
+        struct device *dev = device_get_binding(label);
+        behavior_position_released(dev, position);
     }
     return 0;
-}
+};
+
 int zmk_events_keycode_pressed(u32_t keycode)
 {
-    for (int i = 0; i < BINDING_COUNT; i++) {
-        const struct zmk_behavior_binding *b = &bindings[i];
-        struct device *dev = device_get_binding(b->behavior_dev);
+    for (int i = 0; i < GLOBAL_BEHAVIOR_LEN; i++) {
+        const char* label = global_behaviors[i];
+        struct device *dev = device_get_binding(label);
         behavior_keycode_pressed(dev, keycode);
     }
     return 0;
-}
+};
+
 int zmk_events_keycode_released(u32_t keycode)
 {
-    for (int i = 0; i < BINDING_COUNT; i++) {
-        const struct zmk_behavior_binding *b = &bindings[i];
-        struct device *dev = device_get_binding(b->behavior_dev);
+    for (int i = 0; i < GLOBAL_BEHAVIOR_LEN; i++) {
+        const char* label = global_behaviors[i];
+        struct device *dev = device_get_binding(label);
         behavior_keycode_released(dev, keycode);
     }
     return 0;
 };
-int zmk_events_mod_pressed(u32_t modifier)
+
+int zmk_events_modifiers_pressed(zmk_mod_flags modifiers)
 {
+    for (int i = 0; i < GLOBAL_BEHAVIOR_LEN; i++) {
+        const char* label = global_behaviors[i];
+        struct device *dev = device_get_binding(label);
+        behavior_modifiers_pressed(dev, modifiers);
+    }
     return 0;
 };
-int zmk_events_mod_released(u32_t modifier)
+
+int zmk_events_modifiers_released(zmk_mod_flags modifiers)
 {
+    for (int i = 0; i < GLOBAL_BEHAVIOR_LEN; i++) {
+        const char* label = global_behaviors[i];
+        struct device *dev = device_get_binding(label);
+        behavior_modifiers_released(dev, modifiers);
+    }
     return 0;
 };
+
 int zmk_events_consumer_key_pressed(u32_t usage)
 {
     return 0;
@@ -69,4 +80,4 @@ int zmk_events_consumer_key_pressed(u32_t usage)
 int zmk_events_consumer_key_released(u32_t usage)
 {
     return 0;
-};
\ No newline at end of file
+};
diff --git a/app/src/keymap.c b/app/src/keymap.c
index 6ee61ec3..e14626a3 100644
--- a/app/src/keymap.c
+++ b/app/src/keymap.c
@@ -1,11 +1,13 @@
 
+#include <sys/util.h>
 #include <logging/log.h>
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+#include <zmk/matrix.h>
 #include <zmk/keymap.h>
 #include <dt-bindings/zmk/matrix-transform.h>
 #include <drivers/behavior.h>
 #include <zmk/behavior.h>
-#include <sys/util.h>
 
 static u32_t zmk_keymap_layer_state = 0;
 static u8_t zmk_keymap_layer_default = 0;
@@ -88,10 +90,15 @@ int zmk_keymap_position_state_changed(u32_t position, bool pressed)
 			LOG_DBG("position: %d, binding name: %s", position, binding->behavior_dev);
 
 			behavior = device_get_binding(binding->behavior_dev);
+
+			if (!behavior) {
+				LOG_DBG("No behavior assigned to %d on layer %d", position, layer);
+				continue;
+			}
 			if (pressed) {
-				ret = behavior_position_pressed(behavior, binding->param1, binding->param2);
+				ret = behavior_keymap_binding_pressed(behavior, position, binding->param1, binding->param2);
 			} else {
-				ret = behavior_position_released(behavior, binding->param1, binding->param2);
+				ret = behavior_keymap_binding_released(behavior, position, binding->param1, binding->param2);
 			}
 			
 

From 93635077e600e269aa905a0558c07acf0efebffb Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sun, 21 Jun 2020 21:56:49 -0400
Subject: [PATCH 05/12] Implement momentary layer + transparent behaviors

* Implement "momentary layer" behavior with `&mo`
  reference.
* Implement basic "transparent" behavior with `&trans`
  reference.
---
 app/CMakeLists.txt                            |  2 +
 app/boards/native_posix.overlay               |  8 ++-
 app/dts/behaviors/momentary_layer.dtsi        |  9 +++
 app/dts/behaviors/transparent.dtsi            |  9 +++
 .../zmk,behavior-momentary-layer.yaml         |  8 +++
 .../behaviors/zmk,behavior-transparent.yaml   |  8 +++
 app/src/behaviors/behavior_momentary_layer.c  | 55 +++++++++++++++++++
 app/src/behaviors/behavior_transparent.c      | 48 ++++++++++++++++
 8 files changed, 144 insertions(+), 3 deletions(-)
 create mode 100644 app/dts/behaviors/momentary_layer.dtsi
 create mode 100644 app/dts/behaviors/transparent.dtsi
 create mode 100644 app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml
 create mode 100644 app/dts/bindings/behaviors/zmk,behavior-transparent.yaml
 create mode 100644 app/src/behaviors/behavior_momentary_layer.c
 create mode 100644 app/src/behaviors/behavior_transparent.c

diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index e91bd58a..38bd0750 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -37,6 +37,8 @@ target_sources(app PRIVATE src/behaviors/behavior_hid.c)
 target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
 target_sources(app PRIVATE src/behaviors/behavior_reset.c)
 target_sources(app PRIVATE src/behaviors/behavior_mod_tap.c)
+target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
+target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
 target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
 target_sources_ifdef(CONFIG_ZMK_KSCAN_MOCK_DRIVER app PRIVATE src/kscan_mock.c)
 target_sources_ifdef(CONFIG_ZMK_KSCAN_COMPOSITE_DRIVER app PRIVATE src/kscan_composite.c)
diff --git a/app/boards/native_posix.overlay b/app/boards/native_posix.overlay
index 80047054..1a4fb138 100644
--- a/app/boards/native_posix.overlay
+++ b/app/boards/native_posix.overlay
@@ -1,6 +1,8 @@
 #include <dt-bindings/zmk/keys.h>
 #include <behaviors/key_press.dtsi>
+#include <behaviors/transparent.dtsi>
 #include <behaviors/mod_tap.dtsi>
+#include <behaviors/momentary_layer.dtsi>
 #include <behaviors/reset.dtsi>
 #include <behaviors/keymap.dtsi>
 #include <behaviors/hid.dtsi>
@@ -65,7 +67,7 @@
 			>;
 
 			bindings = <
-				&kp 5 &mt MOD_LSFT KC_B &kp 10 &kp 11
+				&kp 5 &mo 1 &kp 10 &kp 11
 				&kp 1  &kp 2 &kp 4 &kp 89>;
 		};
 
@@ -77,8 +79,8 @@
 			>;
 
 			bindings = <
-				&kp 5 &kp 0 &kp 10 &kp 11
-				&kp 1  &kp 2 &kp 4 &kp 89>;
+				&kp 20 &trans &kp 18 &kp 19
+				&kp 21  &kp 22 &kp 24 &kp 49>;
 		};
 
 		raise: layer_2 {
diff --git a/app/dts/behaviors/momentary_layer.dtsi b/app/dts/behaviors/momentary_layer.dtsi
new file mode 100644
index 00000000..e5b6c3ce
--- /dev/null
+++ b/app/dts/behaviors/momentary_layer.dtsi
@@ -0,0 +1,9 @@
+/ {
+	behaviors {
+		mo: behavior_momentary_layer {
+			compatible = "zmk,behavior-momentary-layer";
+			label = "MO";
+			#binding-cells = <1>;
+		};
+	};
+};
diff --git a/app/dts/behaviors/transparent.dtsi b/app/dts/behaviors/transparent.dtsi
new file mode 100644
index 00000000..ddd05220
--- /dev/null
+++ b/app/dts/behaviors/transparent.dtsi
@@ -0,0 +1,9 @@
+/ {
+	behaviors {
+		trans: behavior_transparent {
+			compatible = "zmk,behavior-transparent";
+			label = "TRANS";
+			#binding-cells = <0>;
+		};
+	};
+};
diff --git a/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml b/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml
new file mode 100644
index 00000000..70c7c7f9
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+description: Momentary layer on press/release behavior
+
+compatible: "zmk,behavior-momentary-layer"
+
+include: one_param.yaml
diff --git a/app/dts/bindings/behaviors/zmk,behavior-transparent.yaml b/app/dts/bindings/behaviors/zmk,behavior-transparent.yaml
new file mode 100644
index 00000000..33f1abae
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-transparent.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+description: Transparent Binding Behavior
+
+compatible: "zmk,behavior-transparent"
+
+include: zero_param.yaml
diff --git a/app/src/behaviors/behavior_momentary_layer.c b/app/src/behaviors/behavior_momentary_layer.c
new file mode 100644
index 00000000..f85d33d4
--- /dev/null
+++ b/app/src/behaviors/behavior_momentary_layer.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_momentary_layer
+
+#include <device.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+
+#include <zmk/events.h>
+#include <zmk/keymap.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+struct behavior_mo_config { };
+struct behavior_mo_data { };
+
+static int behavior_mo_init(struct device *dev)
+{
+	return 0;
+};
+
+
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _)
+{
+  LOG_DBG("position %d layer %d", position, layer);
+
+  return zmk_keymap_layer_activate(layer);
+}
+
+static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _)
+{
+  LOG_DBG("position %d layer %d", position, layer);
+
+  return zmk_keymap_layer_deactivate(layer);
+}
+
+static const struct behavior_driver_api behavior_mo_driver_api = {
+  .binding_pressed = on_keymap_binding_pressed,
+  .binding_released = on_keymap_binding_released
+};
+
+
+static const struct behavior_mo_config behavior_mo_config = {};
+
+static struct behavior_mo_data behavior_mo_data;
+
+DEVICE_AND_API_INIT(behavior_mo, DT_INST_LABEL(0), behavior_mo_init,
+                    &behavior_mo_data,
+                    &behavior_mo_config,
+                    APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+                    &behavior_mo_driver_api);
diff --git a/app/src/behaviors/behavior_transparent.c b/app/src/behaviors/behavior_transparent.c
new file mode 100644
index 00000000..5109264a
--- /dev/null
+++ b/app/src/behaviors/behavior_transparent.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_transparent
+
+#include <device.h>
+#include <power/reboot.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+struct behavior_transparent_config { };
+struct behavior_transparent_data { };
+
+static int behavior_transparent_init(struct device *dev)
+{
+	return 0;
+};
+
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
+{
+  return 1;
+}
+
+static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
+{
+  return 1;
+}
+
+static const struct behavior_driver_api behavior_transparent_driver_api = {
+  .binding_pressed = on_keymap_binding_pressed,
+  .binding_released = on_keymap_binding_released,
+};
+
+
+static const struct behavior_transparent_config behavior_transparent_config = {};
+
+static struct behavior_transparent_data behavior_transparent_data;
+
+DEVICE_AND_API_INIT(behavior_transparent, DT_INST_LABEL(0), behavior_transparent_init,
+                    &behavior_transparent_data,
+                    &behavior_transparent_config,
+                    APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+                    &behavior_transparent_driver_api);
\ No newline at end of file

From c6625169e5f6cfc8641fc08662f59935abf11588 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sun, 21 Jun 2020 22:05:11 -0400
Subject: [PATCH 06/12] Refactor to single <behaviors.dtsi> include.

---
 app/boards/arm/nice_nano/nice_nano.dts        |  3 --
 app/boards/native_posix.overlay               |  8 +----
 .../kyria/keymaps/default/keymap.overlay      | 30 +------------------
 .../keymap/keymap.overlay                     |  4 +--
 .../keymap/keymap.overlay                     |  1 +
 app/dts/behaviors.dtsi                        |  7 +++++
 6 files changed, 11 insertions(+), 42 deletions(-)
 create mode 100644 app/dts/behaviors.dtsi

diff --git a/app/boards/arm/nice_nano/nice_nano.dts b/app/boards/arm/nice_nano/nice_nano.dts
index 9d3b484b..21b60d38 100644
--- a/app/boards/arm/nice_nano/nice_nano.dts
+++ b/app/boards/arm/nice_nano/nice_nano.dts
@@ -6,9 +6,6 @@
 
 /dts-v1/;
 #include <nordic/nrf52840_qiaa.dtsi>
-#include <behaviors/key_press.dtsi>
-#include <behaviors/reset.dtsi>
-#include <behaviors/keymap.dtsi>
 #include "arduino_pro_micro_pins.dtsi"
 
 / {
diff --git a/app/boards/native_posix.overlay b/app/boards/native_posix.overlay
index 1a4fb138..204032a5 100644
--- a/app/boards/native_posix.overlay
+++ b/app/boards/native_posix.overlay
@@ -1,11 +1,5 @@
 #include <dt-bindings/zmk/keys.h>
-#include <behaviors/key_press.dtsi>
-#include <behaviors/transparent.dtsi>
-#include <behaviors/mod_tap.dtsi>
-#include <behaviors/momentary_layer.dtsi>
-#include <behaviors/reset.dtsi>
-#include <behaviors/keymap.dtsi>
-#include <behaviors/hid.dtsi>
+#include <behaviors.dtsi>
 #include <zmk/kscan-mock.h>
 
 / {
diff --git a/app/boards/shields/kyria/keymaps/default/keymap.overlay b/app/boards/shields/kyria/keymaps/default/keymap.overlay
index 303c6756..66c1a230 100644
--- a/app/boards/shields/kyria/keymaps/default/keymap.overlay
+++ b/app/boards/shields/kyria/keymaps/default/keymap.overlay
@@ -1,3 +1,4 @@
+#include <behaviors.dtsi>
 #include <dt-bindings/zmk/keys.h>
 #include <dt-bindings/zmk/matrix-transform.h>
 #include <keymap.h>
@@ -11,35 +12,6 @@
 		compatible = "zmk,keymap";
 		label ="Default Kyria Keymap";
 		layers = <&default>;
-		transform = <&default_transform>;
-	};
-
-	default_transform: keymap_transform_0 {
-		compatible = "zmk,matrix-transform";
-// | MX6  | MX5  | MX4  | MX3  | MX2  | MX1  |                               | MX1  | MX2  | MX3  | MX4  | MX5  | MX6  |
-// | MX12 | MX11 | MX10 | MX9  | MX8  | MX7  |                               | MX7  | MX8  | MX9  | MX10 | MX11 | MX12 |
-// | MX20 | MX19 | MX18 | MX17 | MX16 | MX15 | MX14 | MX13 |   | MX13 | MX14 | MX15 | MX16 | MX17 | MX18 | MX19 | MX20 |
-//                    | MX25 | MX24 | MX23 | MX22 | MX21 |       | MX21 | MX22 | MX23 | MX24 | MX25 |
-		map = <
-RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5)                                 RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,15)
-RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5)                                 RC(1,10) RC(1,11) RC(1,12) RC(1,13) RC(1,14) RC(1,15)
-RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13) RC(2,14) RC(2,15)
-                        RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12)
-		>;
-	};
-
-// | MX5  | MX4  | MX3  | MX2  | MX1  |                               | MX1  | MX2  | MX3  | MX4  | MX5  |
-// | MX11 | MX10 | MX9  | MX8  | MX7  |                               | MX7  | MX8  | MX9  | MX10 | MX11 |
-// | MX19 | MX18 | MX17 | MX16 | MX15 | MX14 | MX13 |   | MX13 | MX14 | MX15 | MX16 | MX17 | MX18 | MX19 |
-//             | MX25 | MX24 | MX23 | MX22 | MX21 |       | MX21 | MX22 | MX23 | MX24 | MX25 |
-	five_column_transform: keymap_transform_1 {
-		compatible = "zmk,matrix-transform";
-		map = <
-RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4)                                 RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13)
-RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4)                                 RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13)
-RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13)
-                RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
-		>;
 	};
 
 	layers {
diff --git a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
index 1a70ff4c..5da88b88 100644
--- a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
@@ -1,7 +1,5 @@
 #include <dt-bindings/zmk/keys.h>
-#include <behaviors/key_press.dtsi>
-#include <behaviors/reset.dtsi>
-#include <behaviors/keymap.dtsi>
+#include <behaviors.dtsi>
 #include <keymap.h>
 
 / {
diff --git a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
index f4d746ed..ad07e9fa 100644
--- a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
@@ -1,3 +1,4 @@
+#include <behaviors.dtsi>
 #include <dt-bindings/zmk/keys.h>
 #include <keymap.h>
 
diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi
new file mode 100644
index 00000000..cd5a3ab0
--- /dev/null
+++ b/app/dts/behaviors.dtsi
@@ -0,0 +1,7 @@
+#include <behaviors/key_press.dtsi>
+#include <behaviors/transparent.dtsi>
+#include <behaviors/mod_tap.dtsi>
+#include <behaviors/momentary_layer.dtsi>
+#include <behaviors/reset.dtsi>
+#include <behaviors/keymap.dtsi>
+#include <behaviors/hid.dtsi>
\ No newline at end of file

From ec663310c1682f55578b1b6d886ebcae4965425c Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sun, 21 Jun 2020 22:46:27 -0400
Subject: [PATCH 07/12] Clean up after refactor, better HID constants.

---
 app/CMakeLists.txt                            |   1 -
 app/boards/native_posix.overlay               |  25 +-
 .../default => keymap}/keymap.overlay         |  13 +-
 .../kyria/keymaps/default/include/keymap.h    |   5 -
 .../shields/kyria/keymaps/default/keymap.c    |  34 ---
 .../keymap/keymap.overlay                     |  28 +--
 app/dts/bindings/zmk,layers.yaml              |   4 +-
 app/include/dt-bindings/zmk/keys.h            | 215 ++++++++----------
 app/include/zmk/hid.h                         |   2 +-
 app/src/ble.c                                 |   4 +-
 app/src/handlers.c                            |  88 -------
 app/src/hid.c                                 |  42 ++--
 12 files changed, 146 insertions(+), 315 deletions(-)
 rename app/boards/shields/kyria/{keymaps/default => keymap}/keymap.overlay (65%)
 delete mode 100644 app/boards/shields/kyria/keymaps/default/include/keymap.h
 delete mode 100644 app/boards/shields/kyria/keymaps/default/keymap.c
 delete mode 100644 app/src/handlers.c

diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 38bd0750..4dcd2f6a 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -46,5 +46,4 @@ target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c)
 target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c)
 target_sources(app PRIVATE src/endpoints.c)
 target_sources(app PRIVATE src/main.c)
-target_sources(app PRIVATE src/handlers.c)
 
diff --git a/app/boards/native_posix.overlay b/app/boards/native_posix.overlay
index 204032a5..bf9ae2ca 100644
--- a/app/boards/native_posix.overlay
+++ b/app/boards/native_posix.overlay
@@ -54,39 +54,26 @@
 
 		default: layer_0 {
 			label = "DEFAULT";
-			keys =
-			<
-				KC_A MT(MOD_LSFT, KC_B) KC_C KC_D
-				KC_E KC_F KC_G KC_H
-			>;
 
 			bindings = <
-				&kp 5 &mo 1 &kp 10 &kp 11
-				&kp 1  &kp 2 &kp 4 &kp 89>;
+				&kp B &mo A &kp C &kp E
+				&kp D &kp G &kp F &kp Q>;
 		};
 
 		lower: layer_1 {
 			label = "LOWER";
-			keys = <
-				KC_A KC_B KC_C KC_D
-				KC_E KC_F KC_G KC_H
-			>;
 
 			bindings = <
-				&kp 20 &trans &kp 18 &kp 19
-				&kp 21  &kp 22 &kp 24 &kp 49>;
+				&kp N &trans &kp O &kp Q
+				&kp L  &kp J &kp P &kp K>;
 		};
 
 		raise: layer_2 {
 			label = "RAISE";
-			keys = <
-				KC_E KC_F KC_G KC_H 
-				KC_A KC_B KC_C KC_D
-			>;
 
 			bindings = <
-				&kp 5 &kp 0 &kp 10 &kp 11
-				&kp 1  &kp 2 &kp 4 &kp 89>;
+				&kp W &kp U &kp I &kp N
+				&kp X  &kp M &kp C &kp B>;
 		};
 	};
 };
diff --git a/app/boards/shields/kyria/keymaps/default/keymap.overlay b/app/boards/shields/kyria/keymap/keymap.overlay
similarity index 65%
rename from app/boards/shields/kyria/keymaps/default/keymap.overlay
rename to app/boards/shields/kyria/keymap/keymap.overlay
index 66c1a230..f61bb6ce 100644
--- a/app/boards/shields/kyria/keymaps/default/keymap.overlay
+++ b/app/boards/shields/kyria/keymap/keymap.overlay
@@ -1,7 +1,6 @@
 #include <behaviors.dtsi>
 #include <dt-bindings/zmk/keys.h>
 #include <dt-bindings/zmk/matrix-transform.h>
-#include <keymap.h>
 
 / {
 	chosen {
@@ -24,12 +23,12 @@
 // |  <-   |  A  |  S  |  D   |  F   |  G   |                                          |  H   |  J    |  K    |  L   |   ;   |  '  |
 // | SHIFT |  Z  |  X  |  C   |  V   |  B   | L SHIFT | L SHIFT |  | L SHIFT | L SHIFT |  N   |  M    |  ,    |  .   |   /   |  -  |
 //                     | GUI  | DEL  | RET  |  SPACE  |   ESC   |  |   RET   |  SPACE  | TAB  | BSPC  | R-ALT |
-			keys = <
-	KC_ESC  KC_Q   KC_W KC_E    KC_R   KC_T                                             KC_Y   KC_U    KC_I    KC_O   KC_P    KC_PIPE
-	KC_BKSP KC_A   KC_S KC_D    KC_F   KC_G                                             KC_H   KC_J    KC_K    KC_L   KC_SCLN KC_QUOT
-	KC_LSFT KC_Z   KC_X KC_C    KC_V   KC_B    KC_LSFT KC_LSFT      KC_LSFT   KC_LSFT   KC_N   KC_M    KC_CMMA KC_DOT KC_BSLH KC_MIN
-	                    KC_LGUI KC_DEL KC_RET  KC_SPC  KC_ESC       KC_RET    KC_SPC    KC_TAB KC_BKSP KC_RALT
-	>;
+			bindings = <
+	&kp ESC  &kp Q &kp W &kp E &kp R &kp T                                            &kp Y &kp U  &kp I    &kp O   &kp P    &kp PIPE
+	&kp BKSP &kp A &kp S &kp D &kp F &kp G                                            &kp H &kp J  &kp K    &kp L   &kp SCLN &kp QUOT
+	&kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp  LSFT &kp LSFT       &kp LSFT &kp LSFT &kp N &kp M  &kp CMMA &kp DOT &kp BSLH &kp MINUS
+	                     &kp LGUI &kp DEL &kp RET &kp SPC &kp ESC       &kp RET  &kp SPC  &kp TAB &kp BKSP &kp RALT
+			>;
 		};
 	};
 };
diff --git a/app/boards/shields/kyria/keymaps/default/include/keymap.h b/app/boards/shields/kyria/keymaps/default/include/keymap.h
deleted file mode 100644
index 01cd9e5b..00000000
--- a/app/boards/shields/kyria/keymaps/default/include/keymap.h
+++ /dev/null
@@ -1,5 +0,0 @@
-
-#include <dt-bindings/zmk/keys.h>
-
-#define CC_RAIS ZC_CSTM(1)
-#define CC_LOWR ZC_CSTM(2)
\ No newline at end of file
diff --git a/app/boards/shields/kyria/keymaps/default/keymap.c b/app/boards/shields/kyria/keymaps/default/keymap.c
deleted file mode 100644
index 067cd08e..00000000
--- a/app/boards/shields/kyria/keymaps/default/keymap.c
+++ /dev/null
@@ -1,34 +0,0 @@
-
-#include <zmk/keys.h>
-#include <zmk/keymap.h>
-#include <keymap.h>
-
-bool zmk_handle_key_user(struct zmk_key_event *key_event)
-{
-	switch (key_event->key)
-	{
-	case CC_LOWR:
-		if (key_event->pressed)
-		{
-			zmk_keymap_layer_activate(1);
-		}
-		else
-		{
-			zmk_keymap_layer_deactivate(1);
-		}
-
-		return false;
-	case CC_RAIS:
-		if (key_event->pressed)
-		{
-			zmk_keymap_layer_activate(2);
-		}
-		else
-		{
-			zmk_keymap_layer_deactivate(2);
-		}
-		return false;
-	}
-
-	return true;
-};
diff --git a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
index ad07e9fa..75400222 100644
--- a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
@@ -17,36 +17,26 @@
 
 		default: layer_0 {
 			label = "DEFAULT";
-			keys =
-	<
-	KC_A MT(MOD_LSFT, KC_B)
-	CC_RAIS CC_LOWR
-	>;
+
 			bindings = <
-				&reset &kp 0
-				&kp 1  &kp 2>;
+				&reset &kp A
+				&kp B  &kp C>;
 		};
 
 		lower: layer_1 {
 			label = "LOWER";
-			keys = <
-			KC_MPLY KC_MNXT
-			ZC_TRNS ZC_TRNS
-			>;
+
 			bindings = <
-				&reset &kp 0
-				&kp 1  &kp 2>;
+				&reset &kp D
+				&kp F  &kp E>;
 		};
 
 		raise: layer_2 {
 			label = "RAISE";
-			keys = <
-			KC_C KC_D
-			ZC_TRNS ZC_TRNS
-			>;
+
 			bindings = <
-				&reset &kp 0
-				&kp 1  &kp 2>;
+				&reset &kp I
+				&kp G  &kp H>;
 		};
 	};
 };
diff --git a/app/dts/bindings/zmk,layers.yaml b/app/dts/bindings/zmk,layers.yaml
index 2bbb0231..34cbb954 100644
--- a/app/dts/bindings/zmk,layers.yaml
+++ b/app/dts/bindings/zmk,layers.yaml
@@ -9,7 +9,7 @@ child-binding:
   properties:
     label:
       type: string
-    keys:
-      type: array
+      required: true
     bindings:
       type: phandle-array
+      required: true
diff --git a/app/include/dt-bindings/zmk/keys.h b/app/include/dt-bindings/zmk/keys.h
index c91d27b1..476d1100 100644
--- a/app/include/dt-bindings/zmk/keys.h
+++ b/app/include/dt-bindings/zmk/keys.h
@@ -1,122 +1,117 @@
 
 #pragma once
 
-#define KC_A 0x04
-#define KC_B 0x05
-#define KC_C 0x06
-#define KC_D 0x07
-#define KC_E 0x08
-#define KC_F 0x09
-#define KC_G 0x0A
-#define KC_H 0x0B
-#define KC_I 0x0C
-#define KC_J 0x0D
-#define KC_K 0x0E
-#define KC_L 0x0F
-#define KC_M 0x10
-#define KC_N 0x11
-#define KC_O 0x12
-#define KC_P 0x13
-#define KC_Q 0x14
-#define KC_R 0x15
-#define KC_S 0x16
-#define KC_T 0x17
-#define KC_U 0x18
-#define KC_V 0x19
-#define KC_W 0x1A
-#define KC_X 0x1B
-#define KC_Y 0x1C
-#define KC_Z 0x1D
-#define KC_1 0x1E
-#define KC_2 0x1F
-#define KC_3 0x20
-#define KC_4 0x21
-#define KC_5 0x22
-#define KC_6 0x23
-#define KC_7 0x24
-#define KC_8 0x25
-#define KC_9 0x26
-#define KC_0 0x27
-#define KC_RET 0x28
-#define KC_ESC 0x29
-#define KC_DEL 0x2A
-#define KC_BKSP KC_DEL
-#define KC_TAB 0x2B
-#define KC_SPC 0x2C
-#define KC_MIN 0x2D
-#define KC_EQL 0x2E
-#define KC_LBKT 0x2F
-#define KC_RBKT 0x30
-#define KC_FSLH 0x31
+#define A 0x04
+#define B 0x05
+#define C 0x06
+#define D 0x07
+#define E 0x08
+#define F 0x09
+#define G 0x0A
+#define H 0x0B
+#define I 0x0C
+#define J 0x0D
+#define K 0x0E
+#define L 0x0F
+#define M 0x10
+#define N 0x11
+#define O 0x12
+#define P 0x13
+#define Q 0x14
+#define R 0x15
+#define S 0x16
+#define T 0x17
+#define U 0x18
+#define V 0x19
+#define W 0x1A
+#define X 0x1B
+#define Y 0x1C
+#define Z 0x1D
+#define NUM_1 0x1E
+#define NUM_2 0x1F
+#define NUM_3 0x20
+#define NUM_4 0x21
+#define NUM_5 0x22
+#define NUM_6 0x23
+#define NUM_7 0x24
+#define NUM_8 0x25
+#define NUM_9 0x26
+#define NUM_0 0x27
+#define RET 0x28
+#define ESC 0x29
+#define DEL 0x2A
+#define BKSP DEL
+#define TAB 0x2B
+#define SPC 0x2C
+#define MINUS 0x2D
+#define EQL 0x2E
+#define LBKT 0x2F
+#define RBKT 0x30
+#define FSLH 0x31
 
-#define KC_SCLN 0x33
-#define KC_QUOT 0x34
-#define KC_GRAV 0x35
-#define KC_CMMA 0x36
-#define KC_DOT 0x37
-#define KC_BSLH 0x38
-#define KC_CLCK 0x39
-#define KC_F1 0x3A
-#define KC_F2 0x3B
+#define SCLN 0x33
+#define QUOT 0x34
+#define GRAV 0x35
+#define CMMA 0x36
+#define DOT 0x37
+#define BSLH 0x38
+#define CLCK 0x39
+#define F1 0x3A
+#define F2 0x3B
 
-#define KC_RARW 0x4F
-#define KC_LARW 0x50
-#define KC_DARW 0x51
-#define KC_UARW 0x52
+#define RARW 0x4F
+#define LARW 0x50
+#define DARW 0x51
+#define UARW 0x52
 
-#define KC_KDIV 0x54
-#define KC_KMLT 0x55
-#define KC_KMIN 0x56
-#define KC_KPLS 0x57
+#define KDIV 0x54
+#define KMLT 0x55
+#define KMIN 0x56
+#define KPLS 0x57
 
-#define KC_APP 0x65
+#define GUI 0x65
 
-#define KC_CURU 0xB4
+#define CURU 0xB4
 
-#define KC_LPRN 0xB6
-#define KC_RPRN 0xB7
-#define KC_LCUR 0xB8
-#define KC_RCUR 0xB9
+#define LPRN 0xB6
+#define RPRN 0xB7
+#define LCUR 0xB8
+#define RCUR 0xB9
 
-#define KC_CRRT 0xC3
-#define KC_PRCT 0xC4
-#define KC_LABT 0xC5
-#define KC_RABT 0xC6
-#define KC_AMPS 0xC7
-#define KC_PIPE 0xC9
-#define KC_COLN 0xCB
-#define KC_HASH 0xCC
-#define KC_KSPC 0xCD
-#define KC_ATSN 0xCE
-#define KC_BANG 0xCF
+#define CRRT 0xC3
+#define PRCT 0xC4
+#define LABT 0xC5
+#define RABT 0xC6
+#define AMPS 0xC7
+#define PIPE 0xC9
+#define COLN 0xCB
+#define HASH 0xCC
+#define KSPC 0xCD
+#define ATSN 0xCE
+#define BANG 0xCF
 
-#define KC_LCTL 0xE0
-#define KC_LSFT 0xE1
-#define KC_LALT 0xE2
-#define KC_LGUI 0xE3
-#define KC_RCTL 0xE4
-#define KC_RSFT 0xE5
-#define KC_RALT 0xE6
-#define KC_RGUI 0xE7
+#define LCTL 0xE0
+#define LSFT 0xE1
+#define LALT 0xE2
+#define LGUI 0xE3
+#define RCTL 0xE4
+#define RSFT 0xE5
+#define RALT 0xE6
+#define RGUI 0xE7
 
-#define KC_VOLU 0x80
-#define KC_VOLD 0x81
+#define VOLU 0x80
+#define VOLD 0x81
 
 /* The following are select consumer page usages */
 
-#define KC_MNXT 0x100
-#define KC_MPRV 0x101
-#define KC_MSTP 0x102
-#define KC_MJCT 0x103
-#define KC_MPLY 0x104
-#define KC_MMUT 0x105
-#define KC_MVLU 0x106
-#define KC_MVLD 0x107
-
-#define ZC_TRNS (0xFFFF)
-#define ZC_NO (0xFFFF - 1)
-
-#define ZC_CSTM(n) (0xFFF + n)
+#define MNXT 0x100
+#define MPRV 0x101
+#define MSTP 0x102
+#define MJCT 0x103
+#define MPLY 0x104
+#define MMUT 0x105
+#define MVLU 0x106
+#define MVLD 0x107
 
 #define MOD_LCTL (1 << 0x00)
 #define MOD_LSFT (1 << 0x01)
@@ -127,16 +122,4 @@
 #define MOD_RALT (1 << 0x06)
 #define MOD_RGUI (1 << 0x07)
 
-#define ZK_ACTION(k) (k >> 24)
-#define _ACTION(a) (a << 24)
-#define _ACTION_MODS(m) (m << 16)
-#define ZK_KEY(a) (a & 0xFFFF)
-#define ZK_MODS(a) ((a >> 16) & 0xFF)
-
 #define ZK_IS_CONSUMER(k) (ZK_KEY(k) >= 0x100)
-
-#define ZMK_ACTION_KEY 0x01
-#define ZMK_ACTION_MOD_TAP 0x01
-#define ZMK_ACTION_ONE_SHOT 0x02
-
-#define MT(mods, kc) (_ACTION(ZMK_ACTION_MOD_TAP) + _ACTION_MODS(mods) + kc)
diff --git a/app/include/zmk/hid.h b/app/include/zmk/hid.h
index 7e3560d5..e14a51a0 100644
--- a/app/include/zmk/hid.h
+++ b/app/include/zmk/hid.h
@@ -9,7 +9,7 @@
 
 #define COLLECTION_REPORT 0x03
 
-#define ZMK_HID_MAX_KEYCODE KC_APP
+#define ZMK_HID_MAX_KEYCODE GUI
 
 static const u8_t zmk_hid_report_desc[] = {
     /* USAGE_PAGE (Generic Desktop) */
diff --git a/app/src/ble.c b/app/src/ble.c
index 51607c66..0e6c5f29 100644
--- a/app/src/ble.c
+++ b/app/src/ble.c
@@ -168,12 +168,12 @@ bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
         return true;
     }
 
-    if (key < KC_1 || key > KC_0)
+    if (key < NUM_1 || key > NUM_0)
     {
         return true;
     }
 
-    u32_t val = (key == KC_0) ? 0 : (key - KC_1 + 1);
+    u32_t val = (key == NUM_0) ? 0 : (key - NUM_1 + 1);
 
     passkey_entries[passkey_digit++] = val;
 
diff --git a/app/src/handlers.c b/app/src/handlers.c
deleted file mode 100644
index 464b1abd..00000000
--- a/app/src/handlers.c
+++ /dev/null
@@ -1,88 +0,0 @@
-
-#include <zmk/ble.h>
-#include <zmk/handlers.h>
-#include <zmk/endpoints.h>
-#include <zmk/hid.h>
-#include <zmk/matrix.h>
-
-#ifdef CONFIG_ZMK_ACTION_MOD_TAP
-u16_t action_effect_pending = 0;
-#endif
-
-__attribute__((weak)) bool zmk_handle_key_user(struct zmk_key_event *key_event)
-{
-	return true;
-};
-
-bool zmk_handle_action(zmk_action action, struct zmk_key_event *key_event)
-{
-	zmk_mod mods = ZK_MODS(key_event->key);
-	u8_t flattened_index = (key_event->row * ZMK_MATRIX_COLS) + key_event->column;
-	switch (action)
-	{
-#ifdef CONFIG_ZMK_ACTION_MOD_TAP
-	case ZMK_ACTION_MOD_TAP:
-		if (key_event->pressed)
-		{
-			WRITE_BIT(action_effect_pending, flattened_index, true);
-			zmk_hid_register_mods(mods);
-		}
-		else
-		{
-			zmk_hid_unregister_mods(mods);
-			if (action_effect_pending & BIT(flattened_index))
-			{
-				struct zmk_key_event non_mod_event =
-					{
-						.row = key_event->row,
-						.column = key_event->column,
-						.key = ZK_KEY(key_event->key),
-						.pressed = true};
-
-				zmk_handle_key(non_mod_event);
-				// A small sleep is needed to ensure device layer sends initial
-				// key, before we send the release.
-				k_msleep(10);
-				non_mod_event.pressed = false;
-				zmk_handle_key(non_mod_event);
-			}
-			else
-			{
-				// Since not sending a keycode, at least send the report w/ the mod removed
-				zmk_endpoints_send_report(Keypad);
-			}
-		}
-		break;
-#endif
-	}
-	return false;
-};
-
-void zmk_handle_key(struct zmk_key_event key_event)
-{
-	zmk_action action = ZK_ACTION(key_event.key);
-
-	if (!zmk_handle_key_user(&key_event))
-	{
-		return;
-	}
-
-	if (action && !zmk_handle_action(action, &key_event))
-	{
-		return;
-	}
-
-#ifdef CONFIG_ZMK_ACTION_MOD_TAP
-	action_effect_pending = 0;
-#endif
-
-#ifdef CONFIG_ZMK_BLE
-	/* Used for intercepting key presses when doing passkey verification */
-	if (!zmk_ble_handle_key_user(&key_event))
-	{
-		return;
-	}
-#endif /* CONFIG_ZMK_BLE */
-
-	zmk_endpoints_send_key_event(key_event);
-};
diff --git a/app/src/hid.c b/app/src/hid.c
index b3d47cf9..2bcb6216 100644
--- a/app/src/hid.c
+++ b/app/src/hid.c
@@ -66,19 +66,19 @@ int zmk_hid_unregister_mods(zmk_mod_flags modifiers)
 
 enum zmk_hid_report_changes zmk_hid_press_key(zmk_key code)
 {
-    if (code >= KC_LCTL && code <= KC_RGUI)
+    if (code >= LCTL && code <= RGUI)
     {
-        return zmk_hid_register_mod(code - KC_LCTL);
+        return zmk_hid_register_mod(code - LCTL);
     }
 
-    if (ZK_IS_CONSUMER(code))
-    {
-        LOG_DBG("Toggling a consumer key!");
-        TOGGLE_CONSUMER(code, true);
-        return Consumer;
-    }
-    else
-    {
+    // if (ZK_IS_CONSUMER(code))
+    // {
+    //     LOG_DBG("Toggling a consumer key!");
+    //     TOGGLE_CONSUMER(code, true);
+    //     return Consumer;
+    // }
+    // else
+    // {
         if (code > ZMK_HID_MAX_KEYCODE)
         {
             return -EINVAL;
@@ -89,23 +89,23 @@ enum zmk_hid_report_changes zmk_hid_press_key(zmk_key code)
         TOGGLE_KEY(code, true);
 
         return Keypad;
-    }
+    // }
 };
 
 enum zmk_hid_report_changes zmk_hid_release_key(zmk_key code)
 {
-    if (code >= KC_LCTL && code <= KC_RGUI)
+    if (code >= LCTL && code <= RGUI)
     {
-        return zmk_hid_unregister_mod(code - KC_LCTL);
+        return zmk_hid_unregister_mod(code - LCTL);
     }
 
-    if (ZK_IS_CONSUMER(code))
-    {
-        TOGGLE_CONSUMER(code, false);
-        return Consumer;
-    }
-    else
-    {
+    // if (ZK_IS_CONSUMER(code))
+    // {
+    //     TOGGLE_CONSUMER(code, false);
+    //     return Consumer;
+    // }
+    // else
+    // {
         if (code > ZMK_HID_MAX_KEYCODE)
         {
             return -EINVAL;
@@ -116,7 +116,7 @@ enum zmk_hid_report_changes zmk_hid_release_key(zmk_key code)
         TOGGLE_KEY(code, false);
 
         return Keypad;
-    }
+    // }
 };
 
 struct zmk_hid_keypad_report *zmk_hid_get_keypad_report()

From 037db585c1c317d9de5743c3ac67ce0c914232e7 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sun, 21 Jun 2020 22:52:50 -0400
Subject: [PATCH 08/12] Remove unneeded custom keymap code.

---
 .../keymap/include/keymap.h                   |  9 -----
 .../keymap/keymap.c                           | 34 -------------------
 .../keymap/keymap.overlay                     | 12 +++----
 3 files changed, 6 insertions(+), 49 deletions(-)
 delete mode 100644 app/boards/shields/petejohanson_proton_handwire/keymap/include/keymap.h
 delete mode 100644 app/boards/shields/petejohanson_proton_handwire/keymap/keymap.c

diff --git a/app/boards/shields/petejohanson_proton_handwire/keymap/include/keymap.h b/app/boards/shields/petejohanson_proton_handwire/keymap/include/keymap.h
deleted file mode 100644
index 0fd2f9ff..00000000
--- a/app/boards/shields/petejohanson_proton_handwire/keymap/include/keymap.h
+++ /dev/null
@@ -1,9 +0,0 @@
-
-#include <dt-bindings/zmk/keys.h>
-
-#define DEFAULT 0
-#define RAISE 1
-#define LOWER 2
-
-#define CC_RAIS ZC_CSTM(RAISE)
-#define CC_LOWR ZC_CSTM(LOWER)
diff --git a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.c b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.c
deleted file mode 100644
index bde15ac2..00000000
--- a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.c
+++ /dev/null
@@ -1,34 +0,0 @@
-
-#include <zmk/keys.h>
-#include <zmk/keymap.h>
-#include <keymap.h>
-
-bool zmk_handle_key_user(struct zmk_key_event *key_event)
-{
-	switch (key_event->key)
-	{
-	case CC_LOWR:
-		if (key_event->pressed)
-		{
-			zmk_keymap_layer_activate(LOWER);
-		}
-		else
-		{
-			zmk_keymap_layer_deactivate(LOWER);
-		}
-
-		return false;
-	case CC_RAIS:
-		if (key_event->pressed)
-		{
-			zmk_keymap_layer_activate(RAISE);
-		}
-		else
-		{
-			zmk_keymap_layer_deactivate(RAISE);
-		}
-		return false;
-	}
-
-	return true;
-};
diff --git a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
index 75400222..406b0144 100644
--- a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
@@ -19,24 +19,24 @@
 			label = "DEFAULT";
 
 			bindings = <
-				&reset &kp A
-				&kp B  &kp C>;
+				&to 1 &kp A
+				&to 2 &kp C>;
 		};
 
 		lower: layer_1 {
 			label = "LOWER";
 
 			bindings = <
-				&reset &kp D
-				&kp F  &kp E>;
+				&trans &kp D
+				&trans &kp E>;
 		};
 
 		raise: layer_2 {
 			label = "RAISE";
 
 			bindings = <
-				&reset &kp I
-				&kp G  &kp H>;
+				&trans &kp I
+				&trans &kp H>;
 		};
 	};
 };

From 321d510d02500e1c1eac0817a846e9469cc27342 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sun, 21 Jun 2020 22:56:13 -0400
Subject: [PATCH 09/12] One more minor fix.

---
 .../shields/petejohanson_proton_handwire/keymap/keymap.overlay   | 1 -
 1 file changed, 1 deletion(-)

diff --git a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
index 406b0144..911ff4a5 100644
--- a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
@@ -1,6 +1,5 @@
 #include <behaviors.dtsi>
 #include <dt-bindings/zmk/keys.h>
-#include <keymap.h>
 
 / {
 	chosen {

From 8027be106eef7671604695a1a0f0e2828839ceb3 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Sun, 21 Jun 2020 23:20:38 -0400
Subject: [PATCH 10/12] Fix momentary-layer reference.

---
 .../petejohanson_proton_handwire/keymap/keymap.overlay        | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
index 911ff4a5..ca035579 100644
--- a/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_proton_handwire/keymap/keymap.overlay
@@ -18,8 +18,8 @@
 			label = "DEFAULT";
 
 			bindings = <
-				&to 1 &kp A
-				&to 2 &kp C>;
+				&mo 1 &kp A
+				&mo 2 &kp C>;
 		};
 
 		lower: layer_1 {

From 55cf9db564e66e2804f2d3f2201c55c3c86a90d7 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Mon, 22 Jun 2020 11:06:01 -0400
Subject: [PATCH 11/12] Fix consumer keys w/ refactored behaviors.

---
 app/boards/native_posix.overlay               |  4 +-
 .../keymap/include/keymap.h                   |  5 --
 .../petejohanson_handwire/keymap/keymap.c     | 34 --------
 .../keymap/keymap.overlay                     | 26 ++-----
 app/dts/behaviors/key_press.dtsi              | 10 +++
 .../behaviors/zmk,behavior-key-press.yaml     |  5 ++
 app/include/drivers/behavior.h                | 16 ++--
 app/include/dt-bindings/zmk/keys.h            | 19 +++--
 app/include/zmk/endpoints.h                   |  3 +-
 app/include/zmk/events.h                      |  4 +-
 app/include/zmk/hid.h                         | 55 ++++---------
 app/include/zmk/keymap.h                      |  4 +-
 app/src/behaviors/behavior_hid.c              | 51 +++++++++---
 app/src/behaviors/behavior_key_press.c        | 48 +++++-------
 app/src/behaviors/behavior_mod_tap.c          | 11 ++-
 app/src/behaviors/behavior_momentary_layer.c  |  8 +-
 app/src/endpoints.c                           | 32 ++------
 app/src/events.c                              |  8 +-
 app/src/hid.c                                 | 78 ++++++++++---------
 app/src/keymap.c                              | 10 +--
 20 files changed, 193 insertions(+), 238 deletions(-)
 delete mode 100644 app/boards/shields/petejohanson_handwire/keymap/include/keymap.h
 delete mode 100644 app/boards/shields/petejohanson_handwire/keymap/keymap.c

diff --git a/app/boards/native_posix.overlay b/app/boards/native_posix.overlay
index bf9ae2ca..e9c4c959 100644
--- a/app/boards/native_posix.overlay
+++ b/app/boards/native_posix.overlay
@@ -56,7 +56,7 @@
 			label = "DEFAULT";
 
 			bindings = <
-				&kp B &mo A &kp C &kp E
+				&kp B &mo 1 &kp C &kp E
 				&kp D &kp G &kp F &kp Q>;
 		};
 
@@ -64,7 +64,7 @@
 			label = "LOWER";
 
 			bindings = <
-				&kp N &trans &kp O &kp Q
+				&cp M_NEXT &trans &kp O &kp Q
 				&kp L  &kp J &kp P &kp K>;
 		};
 
diff --git a/app/boards/shields/petejohanson_handwire/keymap/include/keymap.h b/app/boards/shields/petejohanson_handwire/keymap/include/keymap.h
deleted file mode 100644
index 01cd9e5b..00000000
--- a/app/boards/shields/petejohanson_handwire/keymap/include/keymap.h
+++ /dev/null
@@ -1,5 +0,0 @@
-
-#include <dt-bindings/zmk/keys.h>
-
-#define CC_RAIS ZC_CSTM(1)
-#define CC_LOWR ZC_CSTM(2)
\ No newline at end of file
diff --git a/app/boards/shields/petejohanson_handwire/keymap/keymap.c b/app/boards/shields/petejohanson_handwire/keymap/keymap.c
deleted file mode 100644
index 067cd08e..00000000
--- a/app/boards/shields/petejohanson_handwire/keymap/keymap.c
+++ /dev/null
@@ -1,34 +0,0 @@
-
-#include <zmk/keys.h>
-#include <zmk/keymap.h>
-#include <keymap.h>
-
-bool zmk_handle_key_user(struct zmk_key_event *key_event)
-{
-	switch (key_event->key)
-	{
-	case CC_LOWR:
-		if (key_event->pressed)
-		{
-			zmk_keymap_layer_activate(1);
-		}
-		else
-		{
-			zmk_keymap_layer_deactivate(1);
-		}
-
-		return false;
-	case CC_RAIS:
-		if (key_event->pressed)
-		{
-			zmk_keymap_layer_activate(2);
-		}
-		else
-		{
-			zmk_keymap_layer_deactivate(2);
-		}
-		return false;
-	}
-
-	return true;
-};
diff --git a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
index 5da88b88..b2941713 100644
--- a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
+++ b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
@@ -1,6 +1,5 @@
 #include <dt-bindings/zmk/keys.h>
 #include <behaviors.dtsi>
-#include <keymap.h>
 
 / {
 	chosen {
@@ -18,37 +17,24 @@
 
 		default: layer_0 {
 			label = "DEFAULT";
-			keys =
-	<
-	KC_A MT(MOD_LSFT, KC_B)    ZC_NO ZC_NO
-	CC_RAIS CC_LOWR            ZC_NO ZC_NO
-	>;
 			bindings = <
-				&reset &kp 0
-				&kp 1  &kp 2>;
+				&cp M_NEXT &mt MOD_LSFT B &trans &trans
+				&mo 1  &mo 2         &trans &trans>;
 		};
 
 		lower: layer_1 {
 			label = "LOWER";
-			keys = <
-			KC_MPLY KC_MNXT    ZC_NO ZC_NO
-			ZC_TRNS ZC_TRNS    ZC_NO ZC_NO
-			>;
 
 			bindings = <
-				&reset &kp 0
-				&kp 1  &kp 2>;
+				&cp M_PLAY &cp M_NEXT &trans &trans
+				&trans  &trans &trans &trans>;
 		};
 
 		raise: layer_2 {
 			label = "RAISE";
-			keys = <
-			KC_C KC_D          ZC_NO ZC_NO
-			ZC_TRNS ZC_TRNS    ZC_NO ZC_NO>;
-
 			bindings = <
-				&reset &kp 0
-				&kp 1  &kp 2>;
+				&kp C &kp D &trans &trans
+				&trans  &kp E &trans &trans>;
 		};
 	};
 };
diff --git a/app/dts/behaviors/key_press.dtsi b/app/dts/behaviors/key_press.dtsi
index 7c7ac5b3..5a01953c 100644
--- a/app/dts/behaviors/key_press.dtsi
+++ b/app/dts/behaviors/key_press.dtsi
@@ -1,8 +1,18 @@
+#include <dt-bindings/zmk/keys.h>
+
 / {
 	behaviors {
 		kp: behavior_key_press {
 			compatible = "zmk,behavior-key-press";
 			label = "KEY_PRESS";
+			usage_page = <USAGE_KEYPAD>;
+			#binding-cells = <1>;
+		};
+
+		cp: behavior_consumer_press {
+			compatible = "zmk,behavior-key-press";
+			label = "CONSUMER_PRESS";
+			usage_page = <USAGE_CONSUMER>;
 			#binding-cells = <1>;
 		};
 	};
diff --git a/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml b/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml
index 0169d7d5..7ec5494c 100644
--- a/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml
+++ b/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml
@@ -6,3 +6,8 @@ description: Key press/release behavior
 compatible: "zmk,behavior-key-press"
 
 include: one_param.yaml
+
+properties:
+  usage_page:
+    type: int
+    default: 0
diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h
index b3c6ad2c..cca9272a 100644
--- a/app/include/drivers/behavior.h
+++ b/app/include/drivers/behavior.h
@@ -25,7 +25,7 @@ extern "C" {
 
 typedef int (*behavior_position_callback_t)(struct device *dev, u32_t position);
 typedef int (*behavior_keymap_binding_callback_t)(struct device *dev, u32_t position, u32_t param1, u32_t param2);
-typedef int (*behavior_keycode_callback_t)(struct device *dev, u32_t keycode);
+typedef int (*behavior_keycode_callback_t)(struct device *dev, u8_t usage_page, u32_t keycode);
 typedef int (*behavior_modifiers_callback_t)(struct device *dev, zmk_mod_flags modifiers);
 
 __subsystem struct behavior_driver_api {
@@ -135,14 +135,15 @@ static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u3
 /**
  * @brief Handle the keycode being pressed
  * @param dev Pointer to the device structure for the driver instance.
+ * @param usage_page The usage page for the keycode.
  * @param keycode The keycode that is being pressed.
  *
  * @retval 0 If successful.
  * @retval Negative errno code if failure.
  */
-__syscall int behavior_keycode_pressed(struct device *dev, u32_t keycode);
+__syscall int behavior_keycode_pressed(struct device *dev, u8_t usage_page, u32_t keycode);
 
-static inline int z_impl_behavior_keycode_pressed(struct device *dev, u32_t keycode)
+static inline int z_impl_behavior_keycode_pressed(struct device *dev, u8_t usage_page, u32_t keycode)
 {
 	const struct behavior_driver_api *api =
 			(const struct behavior_driver_api *)dev->driver_api;
@@ -151,21 +152,22 @@ static inline int z_impl_behavior_keycode_pressed(struct device *dev, u32_t keyc
 		return -ENOTSUP;
 	}
 
-	return api->keycode_pressed(dev, keycode);
+	return api->keycode_pressed(dev, usage_page, keycode);
 }
 
 
 /**
  * @brief Handle the keycode being released
  * @param dev Pointer to the device structure for the driver instance.
+ * @param usage_page The usage page for the keycode.
  * @param keycode The keycode that is being pressed.
  *
  * @retval 0 If successful.
  * @retval Negative errno code if failure.
  */
-__syscall int behavior_keycode_released(struct device *dev, u32_t keycode);
+__syscall int behavior_keycode_released(struct device *dev, u8_t usage_page, u32_t keycode);
 
-static inline int z_impl_behavior_keycode_released(struct device *dev, u32_t keycode)
+static inline int z_impl_behavior_keycode_released(struct device *dev, u8_t usage_page, u32_t keycode)
 {
 	const struct behavior_driver_api *api =
 			(const struct behavior_driver_api *)dev->driver_api;
@@ -174,7 +176,7 @@ static inline int z_impl_behavior_keycode_released(struct device *dev, u32_t key
 		return -ENOTSUP;
 	}
 
-	return api->keycode_released(dev, keycode);
+	return api->keycode_released(dev, usage_page, keycode);
 }
 
 
diff --git a/app/include/dt-bindings/zmk/keys.h b/app/include/dt-bindings/zmk/keys.h
index 476d1100..c7003c6b 100644
--- a/app/include/dt-bindings/zmk/keys.h
+++ b/app/include/dt-bindings/zmk/keys.h
@@ -1,6 +1,9 @@
 
 #pragma once
 
+#define USAGE_KEYPAD 0x07
+#define USAGE_CONSUMER 0x0C
+
 #define A 0x04
 #define B 0x05
 #define C 0x06
@@ -104,14 +107,14 @@
 
 /* The following are select consumer page usages */
 
-#define MNXT 0x100
-#define MPRV 0x101
-#define MSTP 0x102
-#define MJCT 0x103
-#define MPLY 0x104
-#define MMUT 0x105
-#define MVLU 0x106
-#define MVLD 0x107
+#define M_NEXT 0xB5
+#define M_PREV 0xB6
+#define M_STOP 0xB7
+#define M_EJCT 0xB8
+#define M_PLAY 0xCD
+#define M_MUTE 0xE2
+#define M_VOLU 0xE9
+#define M_VOLD 0xEA
 
 #define MOD_LCTL (1 << 0x00)
 #define MOD_LSFT (1 << 0x01)
diff --git a/app/include/zmk/endpoints.h b/app/include/zmk/endpoints.h
index 255ca54d..624bb4e8 100644
--- a/app/include/zmk/endpoints.h
+++ b/app/include/zmk/endpoints.h
@@ -4,5 +4,4 @@
 #include <zmk/hid.h>
 
 int zmk_endpoints_init();
-int zmk_endpoints_send_report(enum zmk_hid_report_changes changes);
-int zmk_endpoints_send_key_event(struct zmk_key_event key_event);
+int zmk_endpoints_send_report(u8_t usage_report);
diff --git a/app/include/zmk/events.h b/app/include/zmk/events.h
index 8d1ae6af..5be2bebd 100644
--- a/app/include/zmk/events.h
+++ b/app/include/zmk/events.h
@@ -4,8 +4,8 @@
 
 int zmk_events_position_pressed(u32_t position);
 int zmk_events_position_released(u32_t position);
-int zmk_events_keycode_pressed(u32_t keycode);
-int zmk_events_keycode_released(u32_t keycode);
+int zmk_events_keycode_pressed(u8_t usage_page, u32_t keycode);
+int zmk_events_keycode_released(u8_t usage_page, u32_t keycode);
 int zmk_events_modifiers_pressed(zmk_mod_flags modifiers);
 int zmk_events_modifiers_released(zmk_mod_flags modifiers);
 int zmk_events_consumer_key_pressed(u32_t usage);
diff --git a/app/include/zmk/hid.h b/app/include/zmk/hid.h
index e14a51a0..138606a5 100644
--- a/app/include/zmk/hid.h
+++ b/app/include/zmk/hid.h
@@ -108,40 +108,21 @@ static const u8_t zmk_hid_report_desc[] = {
     0x00,
     /* LOGICAL_MAXIMUM (1) */
     HID_GI_LOGICAL_MAX(1),
-    0x01,
-    /* USAGE (Scan Next Track) */
-    HID_LI_USAGE,
-    0xB5,
-    /* USAGE (Scan Previous Track) */
-    HID_LI_USAGE,
-    0xB6,
-    /* USAGE (Stop) */
-    HID_LI_USAGE,
-    0xB7,
-    /* USAGE (Eject) */
-    HID_LI_USAGE,
-    0xB8,
-    /* USAGE (Media Play/Pause) */
-    HID_LI_USAGE,
-    0xCD,
-    /* USAGE (Mute) */
-    HID_LI_USAGE,
-    0xE2,
-    /* USAGE (Volume Increment) */
-    HID_LI_USAGE,
-    0xE9,
-    /* USAGE (Volume Decrement) */
-    HID_LI_USAGE,
-    0xEA,
+    0xFF,
+    HID_LI_USAGE_MIN(1),
+    0x00,
+    /* USAGE_MAXIMUM (Keyboard Application) */
+    HID_LI_USAGE_MAX(1),
+    0xFF,
     /* INPUT (Data,Ary,Abs) */
-    /* REPORT_SIZE (1) */
+    /* REPORT_SIZE (8) */
     HID_GI_REPORT_SIZE,
-    0x01,
+    0x08,
     /* REPORT_COUNT (8) */
     HID_GI_REPORT_COUNT,
-    0x08,
+    0x06,
     HID_MI_INPUT,
-    0x02,
+    0x00,
     /* END COLLECTION */
     HID_MI_COLLECTION_END,
 };
@@ -167,7 +148,7 @@ struct zmk_hid_keypad_report
 
 struct zmk_hid_consumer_report_body
 {
-    u8_t keys;
+    u8_t keys[6];
 } __packed;
 
 struct zmk_hid_consumer_report
@@ -176,19 +157,15 @@ struct zmk_hid_consumer_report
     struct zmk_hid_consumer_report_body body;
 } __packed;
 
-enum zmk_hid_report_changes
-{
-    None = 0x00,
-    Keypad = (0x01 << 0x00),
-    Consumer = (0x01 << 0x01)
-};
-
 int zmk_hid_register_mod(zmk_mod modifier);
 int zmk_hid_unregister_mod(zmk_mod modifier);
 int zmk_hid_register_mods(zmk_mod_flags modifiers);
 int zmk_hid_unregister_mods(zmk_mod_flags modifiers);
-enum zmk_hid_report_changes zmk_hid_press_key(zmk_key key);
-enum zmk_hid_report_changes zmk_hid_release_key(zmk_key key);
+int zmk_hid_keypad_press(zmk_key key);
+int zmk_hid_keypad_release(zmk_key key);
+
+int zmk_hid_consumer_press(zmk_key key);
+int zmk_hid_consumer_release(zmk_key key);
 
 struct zmk_hid_keypad_report *zmk_hid_get_keypad_report();
 struct zmk_hid_consumer_report *zmk_hid_get_consumer_report();
diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h
index 38c1249d..4a6bb37d 100644
--- a/app/include/zmk/keymap.h
+++ b/app/include/zmk/keymap.h
@@ -1,6 +1,6 @@
 #pragma once
 
-bool zmk_keymap_layer_activate(u8_t layer);
-bool zmk_keymap_layer_deactivate(u8_t layer);
+int zmk_keymap_layer_activate(u8_t layer);
+int zmk_keymap_layer_deactivate(u8_t layer);
 
 int zmk_keymap_position_state_changed(u32_t position, bool pressed);
diff --git a/app/src/behaviors/behavior_hid.c b/app/src/behaviors/behavior_hid.c
index 0aeade51..1ac7404a 100644
--- a/app/src/behaviors/behavior_hid.c
+++ b/app/src/behaviors/behavior_hid.c
@@ -24,22 +24,53 @@ static int behavior_hid_init(struct device *dev)
 	return 0;
 };
 
-static int on_keycode_pressed(struct device *dev, u32_t keycode)
+static int on_keycode_pressed(struct device *dev, u8_t usage_page, u32_t keycode)
 {
-  enum zmk_hid_report_changes changes;
+  int err;
   LOG_DBG("keycode %d", keycode);
   
-  changes = zmk_hid_press_key(keycode);
-  return zmk_endpoints_send_report(changes);
+  switch (usage_page) {
+  case USAGE_KEYPAD:
+    err = zmk_hid_keypad_press(keycode);
+    if (err) {
+      LOG_ERR("Unable to press keycode");
+      return err;
+    }
+    break;
+  case USAGE_CONSUMER:
+    err = zmk_hid_consumer_press(keycode);
+    if (err) {
+      LOG_ERR("Unable to press keycode");
+      return err;
+    }
+    break;
+  }
+
+  return zmk_endpoints_send_report(usage_page);
 }
 
-static int on_keycode_released(struct device *dev, u32_t keycode)
+static int on_keycode_released(struct device *dev, u8_t usage_page, u32_t keycode)
 {
-  enum zmk_hid_report_changes changes;
+  int err;
   LOG_DBG("keycode %d", keycode);
   
-  changes = zmk_hid_release_key(keycode);
-  return zmk_endpoints_send_report(changes);
+  switch (usage_page) {
+  case USAGE_KEYPAD:
+    err = zmk_hid_keypad_release(keycode);
+    if (err) {
+      LOG_ERR("Unable to press keycode");
+      return err;
+    }
+    break;
+  case USAGE_CONSUMER:
+    err = zmk_hid_consumer_release(keycode);
+    if (err) {
+      LOG_ERR("Unable to press keycode");
+      return err;
+    }
+    break;
+  }
+  return zmk_endpoints_send_report(usage_page);
 }
 
 static int on_modifiers_pressed(struct device *dev, zmk_mod_flags modifiers)
@@ -47,7 +78,7 @@ static int on_modifiers_pressed(struct device *dev, zmk_mod_flags modifiers)
   LOG_DBG("modifiers %d", modifiers);
   
   zmk_hid_register_mods(modifiers);
-  return zmk_endpoints_send_report(Keypad);
+  return zmk_endpoints_send_report(USAGE_KEYPAD);
 }
 
 static int on_modifiers_released(struct device *dev, zmk_mod_flags modifiers)
@@ -55,7 +86,7 @@ static int on_modifiers_released(struct device *dev, zmk_mod_flags modifiers)
   LOG_DBG("modifiers %d", modifiers);
   
   zmk_hid_unregister_mods(modifiers);
-  return zmk_endpoints_send_report(Keypad);
+  return zmk_endpoints_send_report(USAGE_KEYPAD);
 }
 
 static const struct behavior_driver_api behavior_hid_driver_api = {
diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c
index 1b3e670f..7213b3c2 100644
--- a/app/src/behaviors/behavior_key_press.c
+++ b/app/src/behaviors/behavior_key_press.c
@@ -14,7 +14,9 @@
 
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
-struct behavior_key_press_config { };
+struct behavior_key_press_config {
+  u8_t usage_page;
+};
 struct behavior_key_press_data { };
 
 static int behavior_key_press_init(struct device *dev)
@@ -22,44 +24,34 @@ static int behavior_key_press_init(struct device *dev)
 	return 0;
 };
 
-
-// They keycode is passed by the "keymap" based on the parameter created as part of the assignment.
-// Other drivers instead might activate a layer, update the consumer page state, or update the RGB state, etc.
-// Returns:
-//  * > 0 -  indicate successful processing, and halt further handling,
-//  * 0 - Indicate successful processing, and continue propagation.
-//  * < 0 - Indicate error processing, report and halt further propagation.
 static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _)
 {
-  LOG_DBG("position %d keycode %d", position, keycode);
-  return zmk_events_keycode_pressed(keycode);
+  const struct behavior_key_press_config *cfg = dev->config_info;
+  LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
+  return zmk_events_keycode_pressed(cfg->usage_page, keycode);
 }
 
-
-// They keycode is passed by the "keymap" based on the parameter created as part of the assignment.
 static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _)
 {
-  LOG_DBG("position %d keycode %d", position, keycode);
-  return zmk_events_keycode_released(keycode);
+  const struct behavior_key_press_config *cfg = dev->config_info;
+  LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
+  return zmk_events_keycode_released(cfg->usage_page, keycode);
 }
 
 static const struct behavior_driver_api behavior_key_press_driver_api = {
-  // These callbacks are all optional, and define which kinds of events the behavior can handle.
-  // They can reference local functions defined here, or shared event handlers.
   .binding_pressed = on_keymap_binding_pressed,
   .binding_released = on_keymap_binding_released
-  // Other optional callbacks a behavior can implement
-  // .on_mouse_moved
-  // .on_sensor_data - Any behaviour that wants to be linked to a censor can implement this behavior
 };
 
+#define KP_INST(n) \
+  static const struct behavior_key_press_config behavior_key_press_config_##n = { \
+    .usage_page = DT_INST_PROP(n, usage_page) \
+  }; \
+  static struct behavior_key_press_data behavior_key_press_data_##n; \
+  DEVICE_AND_API_INIT(behavior_key_press_##n, DT_INST_LABEL(n), behavior_key_press_init, \
+                      &behavior_key_press_data_##n, \
+                      &behavior_key_press_config_##n, \
+                      APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
+                      &behavior_key_press_driver_api);
 
-static const struct behavior_key_press_config behavior_key_press_config = {};
-
-static struct behavior_key_press_data behavior_key_press_data;
-
-DEVICE_AND_API_INIT(behavior_key_press, DT_INST_LABEL(0), behavior_key_press_init,
-                    &behavior_key_press_data,
-                    &behavior_key_press_config,
-                    APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
-                    &behavior_key_press_driver_api);
+DT_INST_FOREACH_STATUS_OKAY(KP_INST)
\ No newline at end of file
diff --git a/app/src/behaviors/behavior_mod_tap.c b/app/src/behaviors/behavior_mod_tap.c
index 7684c298..2e6e3391 100644
--- a/app/src/behaviors/behavior_mod_tap.c
+++ b/app/src/behaviors/behavior_mod_tap.c
@@ -40,17 +40,17 @@ static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t
   struct behavior_mod_tap_data *data = dev->driver_data;
   LOG_DBG("mods: %d, keycode: %d", mods, keycode);
   
-  zmk_events_modifiers_released(mods);
+zmk_events_modifiers_released(mods);
   if (data->pending_press_positions & BIT(position)) {
-    zmk_events_keycode_pressed(keycode);
+    zmk_events_keycode_pressed(USAGE_KEYPAD, keycode);
     k_msleep(10);
-    zmk_events_keycode_released(keycode);
+    zmk_events_keycode_released(USAGE_KEYPAD, keycode);
   }
 
   return 0;
 }
 
-static int on_keycode_pressed(struct device *dev, u32_t keycode)
+static int on_keycode_pressed(struct device *dev, u8_t usage_page, u32_t keycode)
 {
   struct behavior_mod_tap_data *data = dev->driver_data;
   data->pending_press_positions = 0;
@@ -58,8 +58,7 @@ static int on_keycode_pressed(struct device *dev, u32_t keycode)
   return 0;
 }
 
-
-static int on_keycode_released(struct device *dev, u32_t keycode)
+static int on_keycode_released(struct device *dev, u8_t usage_page, u32_t keycode)
 {
   LOG_DBG("releasing: %d", keycode);
   return 0;
diff --git a/app/src/behaviors/behavior_momentary_layer.c b/app/src/behaviors/behavior_momentary_layer.c
index f85d33d4..904051e4 100644
--- a/app/src/behaviors/behavior_momentary_layer.c
+++ b/app/src/behaviors/behavior_momentary_layer.c
@@ -24,14 +24,14 @@ static int behavior_mo_init(struct device *dev)
 };
 
 
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _)
+static int mo_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _)
 {
   LOG_DBG("position %d layer %d", position, layer);
 
   return zmk_keymap_layer_activate(layer);
 }
 
-static int on_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);
 
@@ -39,8 +39,8 @@ static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t
 }
 
 static const struct behavior_driver_api behavior_mo_driver_api = {
-  .binding_pressed = on_keymap_binding_pressed,
-  .binding_released = on_keymap_binding_released
+  .binding_pressed = mo_keymap_binding_pressed,
+  .binding_released = mo_keymap_binding_released
 };
 
 
diff --git a/app/src/endpoints.c b/app/src/endpoints.c
index 2f31e109..7823e954 100644
--- a/app/src/endpoints.c
+++ b/app/src/endpoints.c
@@ -3,6 +3,7 @@
 #include <zmk/hid.h>
 #include <zmk/usb_hid.h>
 #include <zmk/hog.h>
+#
 
 #include <logging/log.h>
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
@@ -35,15 +36,15 @@ int zmk_endpoints_init()
     return 0;
 }
 
-int zmk_endpoints_send_report(enum zmk_hid_report_changes report_type)
+int zmk_endpoints_send_report(u8_t usage_page)
 {
     int err;
     struct zmk_hid_keypad_report *keypad_report;
     struct zmk_hid_consumer_report *consumer_report;
-    LOG_DBG("");
-    switch (report_type)
+    LOG_DBG("usage page 0x%02X", usage_page);
+    switch (usage_page)
     {
-    case Keypad:
+    case USAGE_KEYPAD:
         keypad_report = zmk_hid_get_keypad_report();
 #ifdef CONFIG_ZMK_USB
         if (zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(struct zmk_hid_keypad_report)) != 0)
@@ -61,7 +62,7 @@ int zmk_endpoints_send_report(enum zmk_hid_report_changes report_type)
 #endif /* CONFIG_ZMK_BLE */
 
         break;
-    case Consumer:
+    case USAGE_CONSUMER:
         consumer_report = zmk_hid_get_consumer_report();
 #ifdef CONFIG_ZMK_USB
         if (zmk_usb_hid_send_report((u8_t *)consumer_report, sizeof(struct zmk_hid_consumer_report)) != 0)
@@ -80,27 +81,10 @@ int zmk_endpoints_send_report(enum zmk_hid_report_changes report_type)
 
         break;
     default:
-        LOG_ERR("Unknown report change type %d", report_type);
-        return -EINVAL;
+        LOG_ERR("Unsupported usage page %d", usage_page);
+        return -ENOTSUP;
     }
 
     return 0;
 }
 
-int zmk_endpoints_send_key_event(struct zmk_key_event key_event)
-{
-    enum zmk_hid_report_changes changes;
-
-    LOG_DBG("key %d, state %d\n", key_event.key, key_event.pressed);
-
-    if (key_event.pressed)
-    {
-        changes = zmk_hid_press_key(key_event.key);
-    }
-    else
-    {
-        changes = zmk_hid_release_key(key_event.key);
-    }
-
-    return zmk_endpoints_send_report(changes);
-}
diff --git a/app/src/events.c b/app/src/events.c
index 376f370a..fabb93e1 100644
--- a/app/src/events.c
+++ b/app/src/events.c
@@ -33,22 +33,22 @@ int zmk_events_position_released(u32_t position)
     return 0;
 };
 
-int zmk_events_keycode_pressed(u32_t keycode)
+int zmk_events_keycode_pressed(u8_t usage_page, u32_t keycode)
 {
     for (int i = 0; i < GLOBAL_BEHAVIOR_LEN; i++) {
         const char* label = global_behaviors[i];
         struct device *dev = device_get_binding(label);
-        behavior_keycode_pressed(dev, keycode);
+        behavior_keycode_pressed(dev, usage_page, keycode);
     }
     return 0;
 };
 
-int zmk_events_keycode_released(u32_t keycode)
+int zmk_events_keycode_released(u8_t usage_page, u32_t keycode)
 {
     for (int i = 0; i < GLOBAL_BEHAVIOR_LEN; i++) {
         const char* label = global_behaviors[i];
         struct device *dev = device_get_binding(label);
-        behavior_keycode_released(dev, keycode);
+        behavior_keycode_released(dev, usage_page, keycode);
     }
     return 0;
 };
diff --git a/app/src/hid.c b/app/src/hid.c
index 2bcb6216..ca040562 100644
--- a/app/src/hid.c
+++ b/app/src/hid.c
@@ -12,7 +12,7 @@ static struct zmk_hid_keypad_report kp_report = {
 static struct zmk_hid_consumer_report consumer_report = {
     .report_id = 2,
     .body = {
-        .keys = 0x00}};
+        .keys = {0,0,0,0,0,0}}};
 
 #define _TOGGLE_MOD(mod, state)                      \
     if (modifier > MOD_RGUI)                         \
@@ -61,62 +61,68 @@ int zmk_hid_unregister_mods(zmk_mod_flags modifiers)
 
 #define TOGGLE_KEY(code, val) WRITE_BIT(kp_report.body.keys[code / 8], code % 8, val)
 
-#define TOGGLE_CONSUMER(key, state) \
-    WRITE_BIT(consumer_report.body.keys, (key - 0x100), state);
+#define TOGGLE_CONSUMER(match, val)                  \
+    for (int idx = 0; idx < MAX_KEYS; idx++)         \
+    {                                                \
+        if (consumer_report.body.keys[idx] != match) \
+        {                                            \
+            continue;                                \
+        }                                            \
+        consumer_report.body.keys[idx] = val;        \
+        break;                                       \
+    }
 
-enum zmk_hid_report_changes zmk_hid_press_key(zmk_key code)
+
+int zmk_hid_keypad_press(zmk_key code)
 {
     if (code >= LCTL && code <= RGUI)
     {
         return zmk_hid_register_mod(code - LCTL);
     }
 
-    // if (ZK_IS_CONSUMER(code))
-    // {
-    //     LOG_DBG("Toggling a consumer key!");
-    //     TOGGLE_CONSUMER(code, true);
-    //     return Consumer;
-    // }
-    // else
-    // {
-        if (code > ZMK_HID_MAX_KEYCODE)
-        {
-            return -EINVAL;
-        }
+   
+    if (code > ZMK_HID_MAX_KEYCODE)
+    {
+        return -EINVAL;
+    }
 
-        // TOGGLE_BOOT_KEY(0U, code);
+    // TOGGLE_BOOT_KEY(0U, code);
 
-        TOGGLE_KEY(code, true);
+    TOGGLE_KEY(code, true);
 
-        return Keypad;
-    // }
+    return 0;
 };
 
-enum zmk_hid_report_changes zmk_hid_release_key(zmk_key code)
+int zmk_hid_keypad_release(zmk_key code)
 {
     if (code >= LCTL && code <= RGUI)
     {
         return zmk_hid_unregister_mod(code - LCTL);
     }
 
-    // if (ZK_IS_CONSUMER(code))
-    // {
-    //     TOGGLE_CONSUMER(code, false);
-    //     return Consumer;
-    // }
-    // else
-    // {
-        if (code > ZMK_HID_MAX_KEYCODE)
-        {
-            return -EINVAL;
-        }
+    if (code > ZMK_HID_MAX_KEYCODE)
+    {
+        return -EINVAL;
+    }
 
-        // TOGGLE_BOOT_KEY(0U, code);
+    // TOGGLE_BOOT_KEY(0U, code);
 
-        TOGGLE_KEY(code, false);
+    TOGGLE_KEY(code, false);
 
-        return Keypad;
-    // }
+    return 0;
+};
+
+int zmk_hid_consumer_press(zmk_key code)
+{
+    TOGGLE_CONSUMER(0U, code);
+    return 0;
+};
+
+
+int zmk_hid_consumer_release(zmk_key code)
+{
+    TOGGLE_CONSUMER(code, 0U);
+    return 0;
 };
 
 struct zmk_hid_keypad_report *zmk_hid_get_keypad_report()
diff --git a/app/src/keymap.c b/app/src/keymap.c
index e14626a3..dd0fee47 100644
--- a/app/src/keymap.c
+++ b/app/src/keymap.c
@@ -62,17 +62,17 @@ static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_
 #define SET_LAYER_STATE(layer, state)                \
 	if (layer >= 32)                                 \
 	{                                                \
-		return false;                                \
+		return -EINVAL;                              \
 	}                                                \
 	WRITE_BIT(zmk_keymap_layer_state, layer, state); \
-	return true;
+	return 0;
 
-bool zmk_keymap_layer_activate(u8_t layer)
+int zmk_keymap_layer_activate(u8_t layer)
 {
 	SET_LAYER_STATE(layer, true);
 };
 
-bool zmk_keymap_layer_deactivate(u8_t layer)
+int zmk_keymap_layer_deactivate(u8_t layer)
 {
 	SET_LAYER_STATE(layer, false);
 };
@@ -87,7 +87,7 @@ int zmk_keymap_position_state_changed(u32_t position, bool pressed)
 			struct device *behavior;
 			int ret;
 
-			LOG_DBG("position: %d, binding name: %s", position, binding->behavior_dev);
+			LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, binding->behavior_dev);
 
 			behavior = device_get_binding(binding->behavior_dev);
 

From f2f9d4502122a332aa6f35ac87d9f6b5e3ff7335 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Mon, 22 Jun 2020 11:16:00 -0400
Subject: [PATCH 12/12] Comment out debug settings again.

---
 app/prj.conf | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/prj.conf b/app/prj.conf
index cba93112..abb3bdd2 100644
--- a/app/prj.conf
+++ b/app/prj.conf
@@ -1,4 +1,4 @@
-CONFIG_LOG=y
-CONFIG_ZMK_LOG_LEVEL_DBG=y
+# CONFIG_LOG=y
+# CONFIG_ZMK_LOG_LEVEL_DBG=y
 CONFIG_KERNEL_BIN_NAME="zmk"
 CONFIG_REBOOT=y
\ No newline at end of file