|
| 1 | +/* |
| 2 | + * Copyright (c) 2024 The ZMK Contributors |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: MIT |
| 5 | + */ |
| 6 | + |
| 7 | +#define DT_DRV_COMPAT zmk_sensor_encoder_mock |
| 8 | + |
| 9 | +#include <stdlib.h> |
| 10 | +#include <zephyr/device.h> |
| 11 | +#include <zephyr/drivers/sensor.h> |
| 12 | +#include <zephyr/kernel.h> |
| 13 | +#include <zephyr/logging/log.h> |
| 14 | + |
| 15 | +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); |
| 16 | + |
| 17 | +struct enc_mock_config { |
| 18 | + uint16_t startup_delay; |
| 19 | + uint16_t event_period; |
| 20 | + bool exit_after; |
| 21 | + const int16_t *events; |
| 22 | + size_t events_len; |
| 23 | +}; |
| 24 | + |
| 25 | +struct enc_mock_data { |
| 26 | + const struct sensor_trigger *trigger; |
| 27 | + sensor_trigger_handler_t handler; |
| 28 | + |
| 29 | + size_t event_index; |
| 30 | + struct k_work_delayable work; |
| 31 | + const struct device *dev; |
| 32 | +}; |
| 33 | + |
| 34 | +static void enc_mock_work_cb(struct k_work *work) { |
| 35 | + struct k_work_delayable *dwork = CONTAINER_OF(work, struct k_work_delayable, work); |
| 36 | + struct enc_mock_data *data = CONTAINER_OF(dwork, struct enc_mock_data, work); |
| 37 | + |
| 38 | + const struct device *dev = data->dev; |
| 39 | + |
| 40 | + data->handler(dev, data->trigger); |
| 41 | +} |
| 42 | + |
| 43 | +static int enc_mock_trigger_set(const struct device *dev, const struct sensor_trigger *trig, |
| 44 | + sensor_trigger_handler_t handler) { |
| 45 | + struct enc_mock_data *drv_data = dev->data; |
| 46 | + const struct enc_mock_config *drv_cfg = dev->config; |
| 47 | + |
| 48 | + drv_data->trigger = trig; |
| 49 | + drv_data->handler = handler; |
| 50 | + |
| 51 | + int ret = k_work_schedule(&drv_data->work, K_MSEC(drv_cfg->startup_delay)); |
| 52 | + if (ret < 0) { |
| 53 | + LOG_WRN("Failed to schedule next mock sensor event %d", ret); |
| 54 | + return ret; |
| 55 | + } |
| 56 | + |
| 57 | + return 0; |
| 58 | +} |
| 59 | + |
| 60 | +static int enc_mock_sample_fetch(const struct device *dev, enum sensor_channel chan) { |
| 61 | + struct enc_mock_data *drv_data = dev->data; |
| 62 | + const struct enc_mock_config *drv_cfg = dev->config; |
| 63 | + |
| 64 | + drv_data->event_index++; |
| 65 | + |
| 66 | + if (drv_data->event_index < drv_cfg->events_len - 1) { |
| 67 | + k_work_schedule(&drv_data->work, K_MSEC(drv_cfg->event_period)); |
| 68 | + } else if (drv_cfg->exit_after) { |
| 69 | + exit(0); |
| 70 | + } |
| 71 | + return 0; |
| 72 | +} |
| 73 | + |
| 74 | +static int enc_mock_channel_get(const struct device *dev, enum sensor_channel chan, |
| 75 | + struct sensor_value *val) { |
| 76 | + struct enc_mock_data *drv_data = dev->data; |
| 77 | + const struct enc_mock_config *drv_cfg = dev->config; |
| 78 | + |
| 79 | + val->val1 = drv_cfg->events[drv_data->event_index]; |
| 80 | + |
| 81 | + return 0; |
| 82 | +} |
| 83 | + |
| 84 | +static const struct sensor_driver_api enc_mock_driver_api = { |
| 85 | + .trigger_set = enc_mock_trigger_set, |
| 86 | + .sample_fetch = enc_mock_sample_fetch, |
| 87 | + .channel_get = enc_mock_channel_get, |
| 88 | +}; |
| 89 | + |
| 90 | +int enc_mock_init(const struct device *dev) { |
| 91 | + struct enc_mock_data *drv_data = dev->data; |
| 92 | + |
| 93 | + drv_data->dev = dev; |
| 94 | + drv_data->event_index = -1; |
| 95 | + |
| 96 | + k_work_init_delayable(&drv_data->work, enc_mock_work_cb); |
| 97 | + |
| 98 | + return 0; |
| 99 | +} |
| 100 | + |
| 101 | +#define ENC_MOCK_INST(n) \ |
| 102 | + struct enc_mock_data enc_mock_data_##n = {}; \ |
| 103 | + const int16_t mock_data_##n[] = DT_INST_PROP(n, events); \ |
| 104 | + const struct enc_mock_config enc_mock_cfg_##n = { \ |
| 105 | + .events = mock_data_##n, \ |
| 106 | + .events_len = DT_INST_PROP_LEN(n, events), \ |
| 107 | + .startup_delay = DT_INST_PROP(n, event_startup_delay), \ |
| 108 | + .event_period = DT_INST_PROP(n, event_period), \ |
| 109 | + .exit_after = DT_INST_PROP(n, exit_after), \ |
| 110 | + }; \ |
| 111 | + DEVICE_DT_INST_DEFINE(n, enc_mock_init, NULL, &enc_mock_data_##n, &enc_mock_cfg_##n, \ |
| 112 | + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &enc_mock_driver_api); |
| 113 | + |
| 114 | +DT_INST_FOREACH_STATUS_OKAY(ENC_MOCK_INST) |
0 commit comments