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