refactor(keys): Unify usage page.
* Remove need for separate `&cp` behavior, but keep it for now for backward compat. * Refactor sensor inc/dec as well.
This commit is contained in:
parent
542358bfc2
commit
2b5d87334a
12 changed files with 436 additions and 469 deletions
|
@ -3,17 +3,9 @@
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
kp: behavior_key_press {
|
pr: cp: kp: behavior_key_press {
|
||||||
compatible = "zmk,behavior-key-press";
|
compatible = "zmk,behavior-key-press";
|
||||||
label = "KEY_PRESS";
|
label = "KEY_PRESS";
|
||||||
usage_page = <HID_USAGE_KEY>;
|
|
||||||
#binding-cells = <1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
cp: behavior_consumer_press {
|
|
||||||
compatible = "zmk,behavior-key-press";
|
|
||||||
label = "CONSUMER_PRESS";
|
|
||||||
usage_page = <HID_USAGE_CONSUMER>;
|
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,17 +3,9 @@
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
inc_dec_kp: behavior_sensor_rotate_key_press {
|
inc_dec: inc_dec_cp: inc_dec_kp: behavior_sensor_rotate_key_press {
|
||||||
compatible = "zmk,behavior-sensor-rotate-key-press";
|
compatible = "zmk,behavior-sensor-rotate-key-press";
|
||||||
label = "ENC_KEY_PRESS";
|
label = "ENC_KEY_PRESS";
|
||||||
usage_page = <HID_USAGE_KEY>;
|
|
||||||
#sensor-binding-cells = <2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
inc_dec_cp: behavior_sensor_rotate_consumer_press {
|
|
||||||
compatible = "zmk,behavior-sensor-rotate-key-press";
|
|
||||||
label = "ENC_CONSUMER_PRESS";
|
|
||||||
usage_page = <HID_USAGE_CONSUMER>;
|
|
||||||
#sensor-binding-cells = <2>;
|
#sensor-binding-cells = <2>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,8 +6,3 @@ description: Key press/release behavior
|
||||||
compatible: "zmk,behavior-key-press"
|
compatible: "zmk,behavior-key-press"
|
||||||
|
|
||||||
include: one_param.yaml
|
include: one_param.yaml
|
||||||
|
|
||||||
properties:
|
|
||||||
usage_page:
|
|
||||||
type: int
|
|
||||||
default: 0
|
|
||||||
|
|
|
@ -13,9 +13,6 @@ properties:
|
||||||
type: int
|
type: int
|
||||||
required: true
|
required: true
|
||||||
const: 2
|
const: 2
|
||||||
usage_page:
|
|
||||||
type: int
|
|
||||||
default: 0
|
|
||||||
|
|
||||||
sensor-binding-cells:
|
sensor-binding-cells:
|
||||||
- param1
|
- param1
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,6 +9,7 @@
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <dt-bindings/zmk/modifiers.h>
|
#include <dt-bindings/zmk/modifiers.h>
|
||||||
#include <zmk/event-manager.h>
|
#include <zmk/event-manager.h>
|
||||||
|
#include <dt-bindings/zmk/hid_usage_pages.h>
|
||||||
|
|
||||||
struct keycode_state_changed {
|
struct keycode_state_changed {
|
||||||
struct zmk_event_header header;
|
struct zmk_event_header header;
|
||||||
|
@ -29,3 +30,15 @@ create_keycode_state_changed(u8_t usage_page, u32_t keycode, bool state) {
|
||||||
ev->state = state;
|
ev->state = state;
|
||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct keycode_state_changed *keycode_state_changed_from_encoded(u32_t encoded,
|
||||||
|
bool pressed) {
|
||||||
|
u16_t page = (encoded >> 16) & 0xFF;
|
||||||
|
u16_t id = encoded & 0xFFFF;
|
||||||
|
|
||||||
|
if (!page) {
|
||||||
|
page = HID_USAGE_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return create_keycode_state_changed(page, id, pressed);
|
||||||
|
}
|
|
@ -16,42 +16,28 @@
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
struct behavior_key_press_config {
|
|
||||||
u8_t usage_page;
|
|
||||||
};
|
|
||||||
struct behavior_key_press_data {};
|
|
||||||
|
|
||||||
static int behavior_key_press_init(struct device *dev) { return 0; };
|
static int behavior_key_press_init(struct device *dev) { return 0; };
|
||||||
|
|
||||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||||
struct zmk_behavior_binding_event event) {
|
struct zmk_behavior_binding_event event) {
|
||||||
struct device *dev = device_get_binding(binding->behavior_dev);
|
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||||
const struct behavior_key_press_config *cfg = dev->config_info;
|
|
||||||
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", event.position, cfg->usage_page,
|
|
||||||
binding->param1);
|
|
||||||
|
|
||||||
return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, binding->param1, true));
|
return ZMK_EVENT_RAISE(keycode_state_changed_from_encoded(binding->param1, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||||
struct zmk_behavior_binding_event event) {
|
struct zmk_behavior_binding_event event) {
|
||||||
struct device *dev = device_get_binding(binding->behavior_dev);
|
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||||
const struct behavior_key_press_config *cfg = dev->config_info;
|
|
||||||
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", event.position, cfg->usage_page,
|
|
||||||
binding->param1);
|
|
||||||
|
|
||||||
return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, binding->param1, false));
|
return ZMK_EVENT_RAISE(keycode_state_changed_from_encoded(binding->param1, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct behavior_driver_api behavior_key_press_driver_api = {
|
static const struct behavior_driver_api behavior_key_press_driver_api = {
|
||||||
.binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
.binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
||||||
|
|
||||||
#define KP_INST(n) \
|
#define KP_INST(n) \
|
||||||
static const struct behavior_key_press_config behavior_key_press_config_##n = { \
|
DEVICE_AND_API_INIT(behavior_key_press_##n, DT_INST_LABEL(n), behavior_key_press_init, NULL, \
|
||||||
.usage_page = DT_INST_PROP(n, usage_page)}; \
|
NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||||
static struct behavior_key_press_data behavior_key_press_data_##n; \
|
&behavior_key_press_driver_api);
|
||||||
DEVICE_AND_API_INIT(behavior_key_press_##n, DT_INST_LABEL(n), behavior_key_press_init, \
|
|
||||||
&behavior_key_press_data_##n, &behavior_key_press_config_##n, APPLICATION, \
|
|
||||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_key_press_driver_api);
|
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
||||||
|
|
|
@ -16,23 +16,14 @@
|
||||||
|
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
struct behavior_sensor_rotate_key_press_config {
|
|
||||||
u8_t usage_page;
|
|
||||||
};
|
|
||||||
struct behavior_sensor_rotate_key_press_data {};
|
|
||||||
|
|
||||||
static int behavior_sensor_rotate_key_press_init(struct device *dev) { return 0; };
|
static int behavior_sensor_rotate_key_press_init(struct device *dev) { return 0; };
|
||||||
|
|
||||||
static int on_sensor_binding_triggered(struct zmk_behavior_binding *binding,
|
static int on_sensor_binding_triggered(struct zmk_behavior_binding *binding,
|
||||||
struct device *sensor) {
|
struct device *sensor) {
|
||||||
struct device *dev = device_get_binding(binding->behavior_dev);
|
|
||||||
const struct behavior_sensor_rotate_key_press_config *cfg = dev->config_info;
|
|
||||||
struct sensor_value value;
|
struct sensor_value value;
|
||||||
int err;
|
int err;
|
||||||
u32_t keycode;
|
u32_t keycode;
|
||||||
struct keycode_state_changed *ev;
|
LOG_DBG("inc keycode 0x%02X dec keycode 0x%02X", binding->param1, binding->param2);
|
||||||
LOG_DBG("usage_page 0x%02X inc keycode 0x%02X dec keycode 0x%02X", cfg->usage_page,
|
|
||||||
binding->param1, binding->param2);
|
|
||||||
|
|
||||||
err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value);
|
err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value);
|
||||||
|
|
||||||
|
@ -54,33 +45,21 @@ static int on_sensor_binding_triggered(struct zmk_behavior_binding *binding,
|
||||||
|
|
||||||
LOG_DBG("SEND %d", keycode);
|
LOG_DBG("SEND %d", keycode);
|
||||||
|
|
||||||
ev = new_keycode_state_changed();
|
ZMK_EVENT_RAISE(keycode_state_changed_from_encoded(keycode, true));
|
||||||
ev->usage_page = cfg->usage_page;
|
|
||||||
ev->keycode = keycode;
|
|
||||||
ev->state = true;
|
|
||||||
ZMK_EVENT_RAISE(ev);
|
|
||||||
|
|
||||||
// TODO: Better way to do this?
|
// TODO: Better way to do this?
|
||||||
k_msleep(5);
|
k_msleep(5);
|
||||||
|
|
||||||
ev = new_keycode_state_changed();
|
return ZMK_EVENT_RAISE(keycode_state_changed_from_encoded(keycode, false));
|
||||||
ev->usage_page = cfg->usage_page;
|
|
||||||
ev->keycode = keycode;
|
|
||||||
ev->state = false;
|
|
||||||
return ZMK_EVENT_RAISE(ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = {
|
static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = {
|
||||||
.sensor_binding_triggered = on_sensor_binding_triggered};
|
.sensor_binding_triggered = on_sensor_binding_triggered};
|
||||||
|
|
||||||
#define KP_INST(n) \
|
#define KP_INST(n) \
|
||||||
static const struct behavior_sensor_rotate_key_press_config \
|
DEVICE_AND_API_INIT(behavior_sensor_rotate_key_press_##n, DT_INST_LABEL(n), \
|
||||||
behavior_sensor_rotate_key_press_config_##n = {.usage_page = DT_INST_PROP(n, usage_page)}; \
|
behavior_sensor_rotate_key_press_init, NULL, NULL, APPLICATION, \
|
||||||
static struct behavior_sensor_rotate_key_press_data behavior_sensor_rotate_key_press_data_##n; \
|
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||||
DEVICE_AND_API_INIT( \
|
&behavior_sensor_rotate_key_press_driver_api);
|
||||||
behavior_sensor_rotate_key_press_##n, DT_INST_LABEL(n), \
|
|
||||||
behavior_sensor_rotate_key_press_init, &behavior_sensor_rotate_key_press_data_##n, \
|
|
||||||
&behavior_sensor_rotate_key_press_config_##n, APPLICATION, \
|
|
||||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_key_press_driver_api);
|
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
|
@ -46,22 +46,3 @@ Example:
|
||||||
```
|
```
|
||||||
&kp A
|
&kp A
|
||||||
```
|
```
|
||||||
|
|
||||||
## Consumer Key Press
|
|
||||||
|
|
||||||
The "consumer key press" behavior allows you to send "consumer" usage page keycodes on press/release.
|
|
||||||
These are mostly used for media and power related keycodes, such as sending "Pause", "Scan Track Next",
|
|
||||||
"Scan Track Previous", etc.
|
|
||||||
|
|
||||||
There are a subset of the full consumer usage IDs found in the `keys.h` include, prefixed with `C_`, e.g. `C_PREV`.
|
|
||||||
|
|
||||||
### Behavior Binding
|
|
||||||
|
|
||||||
- Reference: `&cp`
|
|
||||||
- Parameter: The keycode usage ID from the consumer usage page, e.g. `C_PREV` or `C_EJECT`
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```
|
|
||||||
&cp C_PREV
|
|
||||||
```
|
|
||||||
|
|
|
@ -393,7 +393,6 @@ The two `#include` lines at the top of the keymap are required in order to bring
|
||||||
Further documentation on behaviors and bindings is forthcoming, but a summary of the current behaviors you can bind to key positions is as follows:
|
Further documentation on behaviors and bindings is forthcoming, but a summary of the current behaviors you can bind to key positions is as follows:
|
||||||
|
|
||||||
- `kp` is the "key press" behavior, and takes a single binding argument of the HID keycode from the 'keyboard/keypad" HID usage table.
|
- `kp` is the "key press" behavior, and takes a single binding argument of the HID keycode from the 'keyboard/keypad" HID usage table.
|
||||||
- `cp` is the "consumer key press" behavior, and takes a single binding argument of the HID keycode from the "consumer page" HID usage table. This is mostly useful for media keys.
|
|
||||||
- `mo` is the "momentary layer" behaviour, and takes a single binding argument of the numeric ID of the layer to momentarily enable when that key is held.
|
- `mo` is the "momentary layer" behaviour, and takes a single binding argument of the numeric ID of the layer to momentarily enable when that key is held.
|
||||||
- `trans` is the "transparent" behavior, useful to be place in higher layers above `mo` bindings to be sure the key release is handled by the lower layer. No binding arguments are required.
|
- `trans` is the "transparent" behavior, useful to be place in higher layers above `mo` bindings to be sure the key release is handled by the lower layer. No binding arguments are required.
|
||||||
- `mt` is the "mod-tap" behavior, and takes two binding arguments, the modifier to use if held, and the keycode to send if tapped.
|
- `mt` is the "mod-tap" behavior, and takes two binding arguments, the modifier to use if held, and the keycode to send if tapped.
|
||||||
|
|
|
@ -25,7 +25,7 @@ Rotation is handled separately as a type of sensor. The behavior for this is set
|
||||||
sensor-bindings = <BINDING CW_KEY CCW_KEY>;
|
sensor-bindings = <BINDING CW_KEY CCW_KEY>;
|
||||||
```
|
```
|
||||||
|
|
||||||
- `BINDING` is one of two rotation bindings that are currently defined, `&inc_dec_cp` for consumer key presses or `&inc_dec_kp` for normal key presses (see [Key Press](/docs/behavior/key-press) for the difference between the two).
|
- `BINDING` is currently only the one implemented bindings; `&inc_dec` for key presses (see [Key Press](/docs/behavior/key-press) for details on available keycodes).
|
||||||
- `CW_KEY` is the keycode activated by a clockwise turn.
|
- `CW_KEY` is the keycode activated by a clockwise turn.
|
||||||
- `CCW_KEY` is the keycode activated by a counter-clockwise turn.
|
- `CCW_KEY` is the keycode activated by a counter-clockwise turn.
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ Additional encoders can be configured by adding more `BINDING CW_KEY CCW_KEY` se
|
||||||
As an example, a complete `sensor-bindings` for a Kyria with two encoders could look like:
|
As an example, a complete `sensor-bindings` for a Kyria with two encoders could look like:
|
||||||
|
|
||||||
```
|
```
|
||||||
sensor-bindings = <&inc_dec_cp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>;
|
sensor-bindings = <&inc_dec C_VOL_UP C_VOL_DN &inc_dec PG_UP PG_DN>;
|
||||||
```
|
```
|
||||||
|
|
||||||
Here, the left encoder is configured to control volume up and down while the right encoder sends either Page Up or Page Down.
|
Here, the left encoder is configured to control volume up and down while the right encoder sends either Page Up or Page Down.
|
||||||
|
|
|
@ -22,7 +22,7 @@ ZMK is currently missing some features found in other popular firmware. This tab
|
||||||
| [Keymaps and Layers](behavior/layers) | ✅ | ✅ | ✅ |
|
| [Keymaps and Layers](behavior/layers) | ✅ | ✅ | ✅ |
|
||||||
| [Hold-Tap](behavior/hold-tap) (which includes [Mod-Tap](behavior/mod-tap) and [Layer-Tap](behavior/layers/#layer-tap)) | ✅ | ✅ | ✅ |
|
| [Hold-Tap](behavior/hold-tap) (which includes [Mod-Tap](behavior/mod-tap) and [Layer-Tap](behavior/layers/#layer-tap)) | ✅ | ✅ | ✅ |
|
||||||
| [Basic Keycodes](behavior/key-press) | ✅ | ✅ | ✅ |
|
| [Basic Keycodes](behavior/key-press) | ✅ | ✅ | ✅ |
|
||||||
| [Basic consumer (Media) Keycodes](behavior/key-press#consumer-key-press) | ✅ | ✅ | ✅ |
|
| [Basic consumer (Media) Keycodes](behavior/key-press) | ✅ | ✅ | ✅ |
|
||||||
| [Encoders](feature/encoders)[^1] | ✅ | | ✅ |
|
| [Encoders](feature/encoders)[^1] | ✅ | | ✅ |
|
||||||
| [OLED Display Support](feature/displays)[^2] | 🚧 | 🚧 | ✅ |
|
| [OLED Display Support](feature/displays)[^2] | 🚧 | 🚧 | ✅ |
|
||||||
| [RGB Underglow](feature/underglow) | ✅ | ✅ | ✅ |
|
| [RGB Underglow](feature/underglow) | ✅ | ✅ | ✅ |
|
||||||
|
|
Loading…
Add table
Reference in a new issue