1 /*
2 * Copyright (c) 2019 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/printk.h>
9 #include <soc.h>
10 #include <zephyr/drivers/kscan.h>
11
12 #define LOG_LEVEL LOG_LEVEL_DBG
13 #include <zephyr/logging/log.h>
14
15 LOG_MODULE_REGISTER(main);
16
17 const struct device *const kscan_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_keyboard_scan));
18 static struct k_timer typematic_timer;
19 static struct k_timer block_matrix_timer;
20
21 #define KEY_RSVD 0U
22 #define MAX_MATRIX_KEY_COLS 16
23 #define MAX_MATRIX_KEY_ROWS 8
24
25 /****************************************************************************/
26 /* Fujitsu keyboard model N860-7401-TOO1 */
27 /* */
28 /* Sense7 Sense6 Sense5 Sense4 Sense3 Sense2 Sense1 Sense0 */
29 /*+---------------------------------------------------------------+ */
30 /*| | Capslk| | 1! | Tab | F1 | `~ | | Scan 0 */
31 /*| | (30) | | (2) | (16) | (112) | (1) | | (KEY #) */
32 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
33 /*| | W | Q | F7 | | Esc | F6 | F5 | Scan 1 */
34 /*| | (18) | (17) | (118) | | (110) | (117) | (116) | (KEY #) */
35 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
36 /*| | F8 | | 2@ | F4 | F3 | | F2 | Scan 2 */
37 /*| | (119) | | (3) | (115) | (114) | | (113) | (KEY #) */
38 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
39 /*| | R | E | 3# | 4$ | C | F | V | Scan 3 */
40 /*| | (20) | (19) | (4) | (5) | (48) | (34) | (49) | (KEY #) */
41 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
42 /*| N | Y | 6^ | 5% | B | T | H | G | Scan 4 */
43 /*| (51) | (22) | (7) | (6) | (50) | (21) | (36) | (35) | (KEY #) */
44 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
45 /*| SpaceB| M | A | 7& | J | D | S | U | Scan 5 */
46 /*| (61) | (52) | (31) | (8) | (37) | (33) | (32) | (23) | (KEY #) */
47 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
48 /*| F9 | I | ,< | 8* | | Z | X | K | Scan 6 */
49 /*| (120) | (24) | (53) | (9) | | (46) | (47) | (38) | (KEY #) */
50 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
51 /*| | =+ | ]} | 9( | L | | CRSL | O | Scan 7 */
52 /*| | (13) | (28) | (10) | (39) | | (79) | (25) | (KEY #) */
53 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
54 /*| -_ | 0) | /? | [{ | ;: | | | '" | Scan 8 */
55 /*| (12) | (11) | (55) | (27) | (40) | | | (41) | (KEY #) */
56 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
57 /*| F10 | Pause | NumLK | P | | | | | Scan 9 */
58 /*| (121) | (126) | (90) | (26) | | | | | (KEY #) */
59 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
60 /*| BkSpac| \| | F11 | .> | | | W-Appl| CRSD | Scan 10 */
61 /*| (15) | (29) | (122) | (54) | | | (71) | (84) | (KEY #) */
62 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
63 /*| Enter | Delete| Insert| F12 | | | CRSU | CRSR | Scan 11 */
64 /*| (43) | (76) | (75) | (123) | | | (83) | (89) | (KEY #) */
65 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
66 /*| | R-WIN | | | | | L-WIN | Fn | Scan 12 */
67 /*| | (87) | | | | | (59) | (255) | (KEY #) */
68 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
69 /*| | | | RShift| LShift| | | | Scan 13 */
70 /*| | | | (57) | (44) | | | | (KEY #) */
71 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
72 /*| | | | | | | L Alt | R Alt | Scan 14 */
73 /*| | | | | | | (60) | (62) | (KEY #) */
74 /*|-------+-------+-------+-------+-------+-------+-------+-------| */
75 /*| R Ctrl| | | | | L Ctrl| | | Scan 15 */
76 /*| (64) | | | | | (58) | | | (KEY #) */
77 /*+---------------------------------------------------------------+ */
78 /* */
79 /****************************************************************************/
80
81 static const uint8_t keymap[MAX_MATRIX_KEY_COLS][MAX_MATRIX_KEY_ROWS] = {
82 {KEY_RSVD, 1, 112, 16, 2, KEY_RSVD, 30, KEY_RSVD},
83 {116, 117, 110, KEY_RSVD, 118, 17, 18, KEY_RSVD},
84 {113, KEY_RSVD, 114, 115, 3, KEY_RSVD, 119, KEY_RSVD},
85 {49, 34, 48, 5, 4, 19, 20, KEY_RSVD},
86 {35, 36, 21, 50, 6, 7, 22, 51},
87 {23, 32, 33, 37, 8, 31, 52, 61},
88 {38, 47, 46, KEY_RSVD, 9, 53, 24, 120},
89 {25, 79, KEY_RSVD, 39, 10, 28, 13, KEY_RSVD},
90 {41, KEY_RSVD, KEY_RSVD, 40, 27, 55, 11, 12},
91 {KEY_RSVD, KEY_RSVD, KEY_RSVD, KEY_RSVD, 26, 90, 126, 121},
92 {84, 71, KEY_RSVD, KEY_RSVD, 54, 122, 29, 15},
93 {89, 83, KEY_RSVD, KEY_RSVD, 123, 75, 76, 43},
94 {255, 59, KEY_RSVD, KEY_RSVD, KEY_RSVD, KEY_RSVD, 87, KEY_RSVD},
95 {KEY_RSVD, KEY_RSVD, 44, 57, KEY_RSVD, KEY_RSVD, KEY_RSVD},
96 {62, 60, KEY_RSVD, KEY_RSVD, KEY_RSVD, KEY_RSVD, KEY_RSVD, KEY_RSVD},
97 {KEY_RSVD, KEY_RSVD, 58, KEY_RSVD, KEY_RSVD, KEY_RSVD, KEY_RSVD, 64},
98 };
99
100 /* Key used for typematic */
101 static uint8_t last_key;
102
103 /* Typematic rate and delay values correspond to the data passed after
104 * the F3 command (See the 8042 spec online)
105 */
106 static const uint16_t period[] = {
107 33U, 37U, 42U, 46U, 50U, 54U, 58U, 63U,
108 67U, 75U, 83U, 92U, 100U, 109U, 116U, 125U,
109 133U, 149U, 167U, 182U, 200U, 217U, 232U, 250U,
110 270U, 303U, 333U, 370U, 400U, 435U, 470U, 500U
111 };
112
113 static const uint16_t delay[] = { 250U, 500U, 750U, 1000U };
114
115 static bool block_kb_matrix;
116
typematic_callback(struct k_timer * timer)117 static void typematic_callback(struct k_timer *timer)
118 {
119 LOG_INF("Typematic : %u\n", last_key);
120 }
121
kb_callback(const struct device * dev,uint32_t row,uint32_t col,bool pressed)122 static void kb_callback(const struct device *dev, uint32_t row, uint32_t col,
123 bool pressed)
124 {
125 ARG_UNUSED(dev);
126 last_key = keymap[col][row];
127
128 LOG_INF("Key code = %u Pressed = %u\n", last_key, pressed);
129
130 if (pressed) {
131 k_timer_start(&typematic_timer,
132 K_MSEC(delay[0]), K_MSEC(period[0]));
133 } else {
134 k_timer_stop(&typematic_timer);
135 }
136 }
137
block_matrix_callback(struct k_timer * timer)138 static void block_matrix_callback(struct k_timer *timer)
139 {
140 LOG_DBG("block host : %d\n", block_kb_matrix);
141 if (block_kb_matrix) {
142 kscan_disable_callback(kscan_dev);
143 block_kb_matrix = false;
144 k_timer_stop(&typematic_timer);
145 } else {
146 kscan_enable_callback(kscan_dev);
147 block_kb_matrix = true;
148 }
149 }
150
main(void)151 int main(void)
152 {
153 printk("Kscan matrix sample application\n");
154
155 if (!device_is_ready(kscan_dev)) {
156 LOG_ERR("kscan device %s not ready", kscan_dev->name);
157 return 0;
158 }
159
160 kscan_config(kscan_dev, kb_callback);
161 k_timer_init(&typematic_timer, typematic_callback, NULL);
162 k_timer_init(&block_matrix_timer, block_matrix_callback, NULL);
163 k_timer_start(&block_matrix_timer, K_SECONDS(1), K_SECONDS(3));
164
165 return 0;
166 }
167