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