diff options
author | Pete Johanson <peter@peterjohanson.com> | 2020-12-20 09:49:42 -0500 |
---|---|---|
committer | Nick Van Doorn <nick@nv.delivery> | 2021-11-26 09:59:03 -0800 |
commit | 4e4faca67015df3a3e1bf1b9937265f465c5093d (patch) | |
tree | 65557196f4bd4d22532bbda17cb531b468cb8af2 /app/src/split/bluetooth/service.c | |
parent | 67d30762529bee82236446d43b98858072f8afd0 (diff) |
feature(split): behavior locality support.
* GATT characteristic allowing passng data + behavior
label to invoke the behavior on the peripheral side.
* Behaviors have a locality setting to specify where they run.
* Build reset/power/RGB on peripheral.
Diffstat (limited to 'app/src/split/bluetooth/service.c')
-rw-r--r-- | app/src/split/bluetooth/service.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c index fbac644..bb0202c 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -15,6 +15,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include <bluetooth/gatt.h> #include <bluetooth/uuid.h> +#include <drivers/behavior.h> +#include <zmk/behavior.h> #include <zmk/matrix.h> #include <zmk/split/bluetooth/uuid.h> #include <zmk/split/bluetooth/service.h> @@ -24,12 +26,57 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); static uint8_t num_of_positions = ZMK_KEYMAP_LEN; static uint8_t position_state[POS_STATE_LEN]; +static struct zmk_split_run_behavior_payload behavior_run_payload; + static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs, void *buf, uint16_t len, uint16_t offset) { return bt_gatt_attr_read(conn, attrs, buf, len, offset, &position_state, sizeof(position_state)); } +static ssize_t split_svc_run_behavior(struct bt_conn *conn, const struct bt_gatt_attr *attrs, + const void *buf, uint16_t len, uint16_t offset, + uint8_t flags) { + struct zmk_split_run_behavior_payload *payload = attrs->user_data; + uint16_t end_addr = offset + len; + + LOG_DBG("offset %d len %d", offset, len); + + if (end_addr > sizeof(struct zmk_split_run_behavior_payload)) { + return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); + } + + memcpy(payload + offset, buf, len); + + // We run if: + // 1: We've gotten all the position/state/param data. + // 2: We have a null terminated string for the behavior device label. + if ((end_addr > sizeof(struct zmk_split_run_behavior_data)) && + payload->behavior_dev[end_addr - sizeof(struct zmk_split_run_behavior_data)] == '\0') { + struct zmk_behavior_binding binding = { + .param1 = payload->data.param1, + .param2 = payload->data.param2, + .behavior_dev = payload->behavior_dev, + }; + LOG_DBG("INVOKE THE BEHAVIOR: %s with params %d %d", log_strdup(binding.behavior_dev), + binding.param1, binding.param2); + struct zmk_behavior_binding_event event = {.position = payload->data.position, + .timestamp = k_uptime_get()}; + int err; + if (payload->data.state > 0) { + err = behavior_keymap_binding_pressed(&binding, event); + } else { + err = behavior_keymap_binding_released(&binding, event); + } + + if (err) { + LOG_ERR("Failed to invoke behavior %s: %d", log_strdup(binding.behavior_dev), err); + } + } + + return len; +} + static ssize_t split_svc_num_of_positions(struct bt_conn *conn, const struct bt_gatt_attr *attrs, void *buf, uint16_t len, uint16_t offset) { return bt_gatt_attr_read(conn, attrs, buf, len, offset, attrs->user_data, sizeof(uint8_t)); @@ -45,6 +92,9 @@ BT_GATT_SERVICE_DEFINE( BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, split_svc_pos_state, NULL, &position_state), BT_GATT_CCC(split_svc_pos_state_ccc, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT), + BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID), + BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, + split_svc_run_behavior, &behavior_run_payload), BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL, &num_of_positions), ); |