1 /*
2  * Copyright 2023 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #define DT_DRV_COMPAT zephyr_kscan_input
7 
8 #include <zephyr/drivers/kscan.h>
9 #include <zephyr/input/input.h>
10 
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(kscan_input, CONFIG_KSCAN_LOG_LEVEL);
13 
14 struct kscan_input_config {
15 	const struct device *input_dev;
16 };
17 
18 struct kscan_input_data {
19 	bool enabled;
20 	kscan_callback_t callback;
21 	int row;
22 	int col;
23 	bool pressed;
24 };
25 
kscan_input_cb(struct input_event * evt,void * user_data)26 static void kscan_input_cb(struct input_event *evt, void *user_data)
27 {
28 	const struct device *dev = user_data;
29 	struct kscan_input_data *data = dev->data;
30 
31 	switch (evt->code) {
32 	case INPUT_ABS_X:
33 		data->col = evt->value;
34 		break;
35 	case INPUT_ABS_Y:
36 		data->row = evt->value;
37 		break;
38 	case INPUT_BTN_TOUCH:
39 		data->pressed = evt->value;
40 		break;
41 	}
42 
43 	if (evt->sync) {
44 		LOG_DBG("input event: %3d %3d %d",
45 			data->row, data->col, data->pressed);
46 		if (data->callback) {
47 			data->callback(dev, data->row, data->col, data->pressed);
48 		}
49 	}
50 }
51 
kscan_input_configure(const struct device * dev,kscan_callback_t callback)52 static int kscan_input_configure(const struct device *dev,
53 				      kscan_callback_t callback)
54 {
55 	struct kscan_input_data *data = dev->data;
56 
57 	if (!callback) {
58 		LOG_ERR("Invalid callback (NULL)");
59 		return -EINVAL;
60 	}
61 
62 	data->callback = callback;
63 
64 	return 0;
65 }
66 
kscan_input_enable_callback(const struct device * dev)67 static int kscan_input_enable_callback(const struct device *dev)
68 {
69 	struct kscan_input_data *data = dev->data;
70 
71 	data->enabled = true;
72 
73 	return 0;
74 }
75 
kscan_input_disable_callback(const struct device * dev)76 static int kscan_input_disable_callback(const struct device *dev)
77 {
78 	struct kscan_input_data *data = dev->data;
79 
80 	data->enabled = false;
81 
82 	return 0;
83 }
84 
kscan_input_init(const struct device * dev)85 static int kscan_input_init(const struct device *dev)
86 {
87 	const struct kscan_input_config *cfg = dev->config;
88 
89 	if (!device_is_ready(cfg->input_dev)) {
90 		LOG_ERR("Input device not ready");
91 		return -ENODEV;
92 	}
93 
94 	return 0;
95 }
96 
97 static DEVICE_API(kscan, kscan_input_driver_api) = {
98 	.config = kscan_input_configure,
99 	.enable_callback = kscan_input_enable_callback,
100 	.disable_callback = kscan_input_disable_callback,
101 };
102 
103 #define KSCAN_INPUT_INIT(index) \
104 	INPUT_CALLBACK_DEFINE_NAMED(DEVICE_DT_GET(DT_INST_PARENT(index)),      \
105 				    kscan_input_cb,                            \
106 				    (void *)DEVICE_DT_INST_GET(index),         \
107 				    kscan_input_cb_##index);                   \
108 	static const struct kscan_input_config kscan_input_config_##index = {  \
109 		.input_dev = DEVICE_DT_GET(DT_INST_PARENT(index)),             \
110 	};                                                                     \
111 	static struct kscan_input_data kscan_input_data_##index;               \
112 	DEVICE_DT_INST_DEFINE(index, kscan_input_init, NULL,                   \
113 			      &kscan_input_data_##index,                       \
114 			      &kscan_input_config_##index,                     \
115 			      POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY,         \
116 			      &kscan_input_driver_api);
117 
118 DT_INST_FOREACH_STATUS_OKAY(KSCAN_INPUT_INIT)
119