121 lines
3.0 KiB
C
121 lines
3.0 KiB
C
|
/*
|
||
|
* Copyright 2023 Google LLC
|
||
|
*
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
*/
|
||
|
#define DT_DRV_COMPAT zephyr_kscan_input
|
||
|
|
||
|
#include <zephyr/drivers/kscan.h>
|
||
|
#include <zephyr/input/input.h>
|
||
|
|
||
|
#include <zephyr/logging/log.h>
|
||
|
LOG_MODULE_REGISTER(kscan_input, CONFIG_KSCAN_LOG_LEVEL);
|
||
|
|
||
|
struct kscan_input_config {
|
||
|
const struct device *input_dev;
|
||
|
};
|
||
|
|
||
|
struct kscan_input_data {
|
||
|
bool enabled;
|
||
|
kscan_callback_t callback;
|
||
|
int row;
|
||
|
int col;
|
||
|
bool pressed;
|
||
|
};
|
||
|
|
||
|
static void kscan_input_cb(const struct device *dev, struct input_event *evt)
|
||
|
{
|
||
|
struct kscan_input_data *data = dev->data;
|
||
|
|
||
|
switch (evt->code) {
|
||
|
case INPUT_ABS_X:
|
||
|
data->col = evt->value;
|
||
|
break;
|
||
|
case INPUT_ABS_Y:
|
||
|
data->row = evt->value;
|
||
|
break;
|
||
|
case INPUT_BTN_TOUCH:
|
||
|
data->pressed = evt->value;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (evt->sync) {
|
||
|
LOG_DBG("input event: %3d %3d %d",
|
||
|
data->row, data->col, data->pressed);
|
||
|
if (data->callback) {
|
||
|
data->callback(dev, data->row, data->col, data->pressed);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int kscan_input_configure(const struct device *dev,
|
||
|
kscan_callback_t callback)
|
||
|
{
|
||
|
struct kscan_input_data *data = dev->data;
|
||
|
|
||
|
if (!callback) {
|
||
|
LOG_ERR("Invalid callback (NULL)");
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
data->callback = callback;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int kscan_input_enable_callback(const struct device *dev)
|
||
|
{
|
||
|
struct kscan_input_data *data = dev->data;
|
||
|
|
||
|
data->enabled = true;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int kscan_input_disable_callback(const struct device *dev)
|
||
|
{
|
||
|
struct kscan_input_data *data = dev->data;
|
||
|
|
||
|
data->enabled = false;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int kscan_input_init(const struct device *dev)
|
||
|
{
|
||
|
const struct kscan_input_config *cfg = dev->config;
|
||
|
|
||
|
if (!device_is_ready(cfg->input_dev)) {
|
||
|
LOG_ERR("Input device not ready");
|
||
|
return -ENODEV;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static const struct kscan_driver_api kscan_input_driver_api = {
|
||
|
.config = kscan_input_configure,
|
||
|
.enable_callback = kscan_input_enable_callback,
|
||
|
.disable_callback = kscan_input_disable_callback,
|
||
|
};
|
||
|
|
||
|
#define KSCAN_INPUT_INIT(index) \
|
||
|
static void kscan_input_cb_##index(struct input_event *evt) \
|
||
|
{ \
|
||
|
kscan_input_cb(DEVICE_DT_GET(DT_INST(index, DT_DRV_COMPAT)), \
|
||
|
evt); \
|
||
|
} \
|
||
|
INPUT_LISTENER_CB_DEFINE(DEVICE_DT_GET(DT_INST_PARENT(index)), \
|
||
|
kscan_input_cb_##index); \
|
||
|
static const struct kscan_input_config kscan_input_config_##index = { \
|
||
|
.input_dev = DEVICE_DT_GET(DT_INST_PARENT(index)), \
|
||
|
}; \
|
||
|
static struct kscan_input_data kscan_input_data_##index; \
|
||
|
DEVICE_DT_INST_DEFINE(index, kscan_input_init, NULL, \
|
||
|
&kscan_input_data_##index, \
|
||
|
&kscan_input_config_##index, \
|
||
|
POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \
|
||
|
&kscan_input_driver_api);
|
||
|
|
||
|
DT_INST_FOREACH_STATUS_OKAY(KSCAN_INPUT_INIT)
|