1 /*
2 * Copyright (c) 2022, Basalte bv
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT zephyr_gpio_emul_sdl
8
9 #include <zephyr/drivers/gpio/gpio_emul.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/logging/log.h>
12
13 #include "gpio_emul_sdl_bottom.h"
14
15 LOG_MODULE_REGISTER(gpio_emul_sdl, CONFIG_GPIO_LOG_LEVEL);
16
17 struct gpio_sdl_config {
18 const struct device *emul;
19
20 const int *codes;
21 uint8_t num_codes;
22 struct gpio_sdl_data *data;
23 };
24
sdl_filter_top(struct gpio_sdl_data * bottom_data)25 static int sdl_filter_top(struct gpio_sdl_data *bottom_data)
26 {
27 const struct device *port = bottom_data->dev;
28 const struct gpio_sdl_config *config = port->config;
29 int ret;
30
31 gpio_pin_t pin = 0;
32
33 /* Search for the corresponding scancode */
34 while (pin < config->num_codes) {
35 if (config->codes[pin] == bottom_data->event_scan_code) {
36 break;
37 }
38 pin++;
39 }
40
41 if (pin == config->num_codes) {
42 /* Not tracked */
43 return 1;
44 }
45
46 /* Lock the scheduler so we can't be preempted,
47 * as the gpio_emul driver keeps a mutex locked
48 * for as long as there are pending interrupts
49 */
50 k_sched_lock();
51
52 /* Update the pin state */
53 ret = gpio_emul_input_set(config->emul, pin, bottom_data->key_down);
54
55 k_sched_unlock();
56 if (ret < 0) {
57 LOG_WRN("Failed to emulate input (%d)", ret);
58 }
59
60 return 0;
61 }
62
gpio_sdl_init(const struct device * dev)63 static int gpio_sdl_init(const struct device *dev)
64 {
65 const struct gpio_sdl_config *config = dev->config;
66
67 for (uint8_t pin = 0; pin < config->num_codes; ++pin) {
68 if (config->codes[pin] != GPIOEMULSDL_SCANCODE_UNKNOWN) {
69 LOG_INF("GPIO %s:%u = %u", dev->name, pin, config->codes[pin]);
70 }
71 }
72
73 config->data->dev = (void *)dev;
74 config->data->callback = sdl_filter_top;
75 gpio_sdl_init_bottom(config->data);
76 return 0;
77 }
78
79 #define GPIO_SDL_DEFINE(inst) \
80 BUILD_ASSERT(DT_NODE_HAS_COMPAT_STATUS(DT_INST_PARENT(inst), \
81 zephyr_gpio_emul, okay), \
82 "Enabled parent zephyr,gpio-emul node is required"); \
83 \
84 static const int gpio_sdl_##inst##_codes[] \
85 = DT_INST_PROP(inst, scancodes); \
86 \
87 static struct gpio_sdl_data data_##inst; \
88 \
89 static const struct gpio_sdl_config gpio_sdl_##inst##_config = { \
90 .emul = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
91 .codes = gpio_sdl_##inst##_codes, \
92 .num_codes = DT_INST_PROP_LEN(inst, scancodes), \
93 .data = &data_##inst, \
94 }; \
95 \
96 DEVICE_DT_INST_DEFINE(inst, gpio_sdl_init, NULL, NULL, \
97 &gpio_sdl_##inst##_config, POST_KERNEL, \
98 CONFIG_GPIO_INIT_PRIORITY, NULL);
99
100 DT_INST_FOREACH_STATUS_OKAY(GPIO_SDL_DEFINE)
101