Skip to content

Commit 4e9cdd0

Browse files
committed
Add seesaw keypad
Signed-off-by: Titouan Christophe <[email protected]>
1 parent 2c5c832 commit 4e9cdd0

File tree

5 files changed

+142
-0
lines changed

5 files changed

+142
-0
lines changed

drivers/input/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ zephyr_library_sources_ifdef(CONFIG_INPUT_PINNACLE input_pinnacle.c)
3131
zephyr_library_sources_ifdef(CONFIG_INPUT_PMW3610 input_pmw3610.c)
3232
zephyr_library_sources_ifdef(CONFIG_INPUT_REALTEK_RTS5912_KBD input_realtek_rts5912_kbd.c)
3333
zephyr_library_sources_ifdef(CONFIG_INPUT_SBUS input_sbus.c)
34+
zephyr_library_sources_ifdef(CONFIG_INPUT_SEESAW_KEYPAD input_seesaw_keypad.c)
3435
zephyr_library_sources_ifdef(CONFIG_INPUT_STM32_TSC_KEYS input_tsc_keys.c)
3536
zephyr_library_sources_ifdef(CONFIG_INPUT_STMPE811 input_stmpe811.c)
3637
zephyr_library_sources_ifdef(CONFIG_INPUT_TOUCH input_touch.c)

drivers/input/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ source "drivers/input/Kconfig.pmw3610"
3434
source "drivers/input/Kconfig.rts5912"
3535
source "drivers/input/Kconfig.sbus"
3636
source "drivers/input/Kconfig.sdl"
37+
source "drivers/input/Kconfig.seesaw_keypad"
3738
source "drivers/input/Kconfig.stmpe811"
3839
source "drivers/input/Kconfig.touch"
3940
source "drivers/input/Kconfig.tsc_keys"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2025 Titouan Christophe
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config INPUT_SEESAW_KEYPAD
5+
bool "Adafruit seesaw keypad over I2C"
6+
default y
7+
depends on DT_HAS_ADAFRUIT_SEESAW_KEYPAD_ENABLED
8+
depends on MFD_SEESAW
9+
help
10+
Enable support for Adafruit Seesaw gpio
11+
12+
if INPUT_SEESAW_KEYPAD
13+
14+
config INPUT_SEESAW_KEYPAD_POLL_INTERVAL
15+
int "Event poll interval (ms)"
16+
default 25
17+
18+
endif
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright (c) 2025 Titouan Christophe
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT adafruit_seesaw_keypad
8+
9+
#include <zephyr/input/input.h>
10+
#include <zephyr/drivers/mfd/mfd_seesaw.h>
11+
12+
#include <zephyr/logging/log.h>
13+
LOG_MODULE_REGISTER(seesaw_keypad, CONFIG_MFD_SEESAW_LOG_LEVEL);
14+
15+
enum {
16+
KEYPAD_STATUS = 0x00,
17+
KEYPAD_EVENT = 0x01,
18+
KEYPAD_INTENSET = 0x02,
19+
KEYPAD_INTENCLR = 0x03,
20+
KEYPAD_COUNT = 0x04,
21+
KEYPAD_FIFO = 0x10,
22+
};
23+
24+
enum key_edge {
25+
EDGE_HIGH = 0,
26+
EDGE_LOW = 1,
27+
EDGE_FALLING = 2,
28+
EDGE_RISING = 3,
29+
};
30+
31+
struct seesaw_keypad_config {
32+
const struct device *seesaw;
33+
};
34+
35+
struct seesaw_keypad_data {
36+
const struct device *dev;
37+
struct k_work_delayable work;
38+
};
39+
40+
static int seesaw_keypad_get_event(const struct device *dev)
41+
{
42+
const struct seesaw_keypad_config *config = dev->config;
43+
uint8_t keypad_event;
44+
int ret = seesaw_read(config->seesaw, SEESAW_MOD_KEYPAD, KEYPAD_FIFO, &keypad_event, 1);
45+
46+
if (ret < 0) {
47+
LOG_ERR("Error polling events FIFO: %d", ret);
48+
return ret;
49+
}
50+
51+
if (keypad_event == 0xff) {
52+
/* Reached end of FIFO */
53+
return 0;
54+
}
55+
56+
input_report(dev, INPUT_EV_KEY, (keypad_event >> 2), (keypad_event & 1), true, K_NO_WAIT);
57+
return 1;
58+
}
59+
60+
static void seesaw_keypad_poll(struct k_work *work)
61+
{
62+
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
63+
struct seesaw_keypad_data *drv_data = CONTAINER_OF(dwork, struct seesaw_keypad_data, work);
64+
65+
while (seesaw_keypad_get_event(drv_data->dev) > 0) {
66+
continue;
67+
}
68+
69+
k_work_reschedule(dwork, K_MSEC(CONFIG_INPUT_SEESAW_KEYPAD_POLL_INTERVAL));
70+
}
71+
72+
static int seesaw_keypad_init(const struct device *dev)
73+
{
74+
int ret;
75+
struct seesaw_keypad_data *drv_data = dev->data;
76+
const struct seesaw_keypad_config *config = dev->config;
77+
/* Enable RISE/FALL events on all keys */
78+
uint8_t edges = BIT(EDGE_RISING) | BIT(EDGE_FALLING);
79+
80+
ret = seesaw_claim_module(config->seesaw, SEESAW_MOD_KEYPAD, dev);
81+
if (ret) {
82+
return ret;
83+
}
84+
85+
drv_data->dev = dev;
86+
k_work_init_delayable(&drv_data->work, seesaw_keypad_poll);
87+
88+
for (int i = 0; i < 16; i++) {
89+
uint8_t buf[] = {
90+
(i & 0xc) << 1 | (i & 0x03),
91+
(edges << 1) | 1,
92+
};
93+
94+
ret = seesaw_write(config->seesaw, SEESAW_MOD_KEYPAD, KEYPAD_EVENT,
95+
buf, sizeof(buf));
96+
if (ret) {
97+
LOG_ERR("Unable to configure keypad event: %d", ret);
98+
return ret;
99+
}
100+
}
101+
102+
k_work_reschedule(&drv_data->work, K_MSEC(CONFIG_INPUT_SEESAW_KEYPAD_POLL_INTERVAL));
103+
LOG_DBG("%s initialized", dev->name);
104+
105+
return 0;
106+
}
107+
108+
#define SEESAW_KEYPAD_INIT(inst) \
109+
static struct seesaw_keypad_data data_##inst; \
110+
static const struct seesaw_keypad_config config_##inst = { \
111+
.seesaw = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
112+
}; \
113+
DEVICE_DT_INST_DEFINE(inst, seesaw_keypad_init, NULL, &data_##inst, &config_##inst, \
114+
POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL);
115+
116+
DT_INST_FOREACH_STATUS_OKAY(SEESAW_KEYPAD_INIT)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) 2025 Titouan Christophe
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Adafruit Seesaw keypad input
5+
6+
compatible: "adafruit,seesaw-keypad"

0 commit comments

Comments
 (0)