1 #include "keyboard.h"
2 #include <libc/src/unistd.h>
3 // 功能键标志变量
4 static bool shift_l = 0, shift_r = 0, ctrl_l = 0, ctrl_r = 0, alt_l = 0, alt_r = 0;
5 static bool gui_l = 0, gui_r = 0, apps = 0, insert = 0, home = 0, pgup = 0, del = 0, end = 0, pgdn = 0, arrow_u = 0, arrow_l = 0, arrow_d = 0, arrow_r = 0;
6 static bool kp_forward_slash = 0, kp_en = 0;
7 
8 // 键盘扫描码有三种:
9 // 0xE1开头的PauseBreak键
10 // 0xE0开头的功能键
11 // 1byte的普通按键
12 
13 // pause break键的扫描码,没错,它就是这么长
14 unsigned char pause_break_scan_code[] = {0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5};
15 
16 // 第一套键盘扫描码 及其对应的字符
17 uint32_t keycode_map_normal[NUM_SCAN_CODES * MAP_COLS] =
18     {
19         /*scan-code	unShift		Shift		*/
20         /*--------------------------------------------------------------*/
21         /*0x00*/ 0,
22         0,
23         /*0x01*/ 0,
24         0, // ESC
25         /*0x02*/ '1',
26         '!',
27         /*0x03*/ '2',
28         '@',
29         /*0x04*/ '3',
30         '#',
31         /*0x05*/ '4',
32         '$',
33         /*0x06*/ '5',
34         '%',
35         /*0x07*/ '6',
36         '^',
37         /*0x08*/ '7',
38         '&',
39         /*0x09*/ '8',
40         '*',
41         /*0x0a*/ '9',
42         '(',
43         /*0x0b*/ '0',
44         ')',
45         /*0x0c*/ '-',
46         '_',
47         /*0x0d*/ '=',
48         '+',
49         /*0x0e*/ '\b',
50         '\b', // BACKSPACE
51         /*0x0f*/ '\t',
52         '\t', // TAB
53 
54         /*0x10*/ 'q',
55         'Q',
56         /*0x11*/ 'w',
57         'W',
58         /*0x12*/ 'e',
59         'E',
60         /*0x13*/ 'r',
61         'R',
62         /*0x14*/ 't',
63         'T',
64         /*0x15*/ 'y',
65         'Y',
66         /*0x16*/ 'u',
67         'U',
68         /*0x17*/ 'i',
69         'I',
70         /*0x18*/ 'o',
71         'O',
72         /*0x19*/ 'p',
73         'P',
74         /*0x1a*/ '[',
75         '{',
76         /*0x1b*/ ']',
77         '}',
78         /*0x1c*/ '\n',
79         '\n', // ENTER
80         /*0x1d*/ 0x1d,
81         0x1d, // CTRL Left
82         /*0x1e*/ 'a',
83         'A',
84         /*0x1f*/ 's',
85         'S',
86 
87         /*0x20*/ 'd',
88         'D',
89         /*0x21*/ 'f',
90         'F',
91         /*0x22*/ 'g',
92         'G',
93         /*0x23*/ 'h',
94         'H',
95         /*0x24*/ 'j',
96         'J',
97         /*0x25*/ 'k',
98         'K',
99         /*0x26*/ 'l',
100         'L',
101         /*0x27*/ ';',
102         ':',
103         /*0x28*/ '\'',
104         '"',
105         /*0x29*/ '`',
106         '~',
107         /*0x2a*/ 0x2a,
108         0x2a, // SHIFT Left
109         /*0x2b*/ '\\',
110         '|',
111         /*0x2c*/ 'z',
112         'Z',
113         /*0x2d*/ 'x',
114         'X',
115         /*0x2e*/ 'c',
116         'C',
117         /*0x2f*/ 'v',
118         'V',
119 
120         /*0x30*/ 'b',
121         'B',
122         /*0x31*/ 'n',
123         'N',
124         /*0x32*/ 'm',
125         'M',
126         /*0x33*/ ',',
127         '<',
128         /*0x34*/ '.',
129         '>',
130         /*0x35*/ '/',
131         '?',
132         /*0x36*/ 0x36,
133         0x36, // SHIFT Right
134         /*0x37*/ '*',
135         '*',
136         /*0x38*/ 0x38,
137         0x38, // ALT Left
138         /*0x39*/ ' ',
139         ' ',
140         /*0x3a*/ 0,
141         0, // CAPS LOCK
142         /*0x3b*/ 0,
143         0, // F1
144         /*0x3c*/ 0,
145         0, // F2
146         /*0x3d*/ 0,
147         0, // F3
148         /*0x3e*/ 0,
149         0, // F4
150         /*0x3f*/ 0,
151         0, // F5
152 
153         /*0x40*/ 0,
154         0, // F6
155         /*0x41*/ 0,
156         0, // F7
157         /*0x42*/ 0,
158         0, // F8
159         /*0x43*/ 0,
160         0, // F9
161         /*0x44*/ 0,
162         0, // F10
163         /*0x45*/ 0,
164         0, // NUM LOCK
165         /*0x46*/ 0,
166         0, // SCROLL LOCK
167         /*0x47*/ '7',
168         0, /*PAD HONE*/
169         /*0x48*/ '8',
170         0, /*PAD UP*/
171         /*0x49*/ '9',
172         0, /*PAD PAGEUP*/
173         /*0x4a*/ '-',
174         0, /*PAD MINUS*/
175         /*0x4b*/ '4',
176         0, /*PAD LEFT*/
177         /*0x4c*/ '5',
178         0, /*PAD MID*/
179         /*0x4d*/ '6',
180         0, /*PAD RIGHT*/
181         /*0x4e*/ '+',
182         0, /*PAD PLUS*/
183         /*0x4f*/ '1',
184         0, /*PAD END*/
185 
186         /*0x50*/ '2',
187         0, /*PAD DOWN*/
188         /*0x51*/ '3',
189         0, /*PAD PAGEDOWN*/
190         /*0x52*/ '0',
191         0, /*PAD INS*/
192         /*0x53*/ '.',
193         0, /*PAD DOT*/
194         /*0x54*/ 0,
195         0,
196         /*0x55*/ 0,
197         0,
198         /*0x56*/ 0,
199         0,
200         /*0x57*/ 0,
201         0, // F11
202         /*0x58*/ 0,
203         0, // F12
204         /*0x59*/ 0,
205         0,
206         /*0x5a*/ 0,
207         0,
208         /*0x5b*/ 0,
209         0,
210         /*0x5c*/ 0,
211         0,
212         /*0x5d*/ 0,
213         0,
214         /*0x5e*/ 0,
215         0,
216         /*0x5f*/ 0,
217         0,
218 
219         /*0x60*/ 0,
220         0,
221         /*0x61*/ 0,
222         0,
223         /*0x62*/ 0,
224         0,
225         /*0x63*/ 0,
226         0,
227         /*0x64*/ 0,
228         0,
229         /*0x65*/ 0,
230         0,
231         /*0x66*/ 0,
232         0,
233         /*0x67*/ 0,
234         0,
235         /*0x68*/ 0,
236         0,
237         /*0x69*/ 0,
238         0,
239         /*0x6a*/ 0,
240         0,
241         /*0x6b*/ 0,
242         0,
243         /*0x6c*/ 0,
244         0,
245         /*0x6d*/ 0,
246         0,
247         /*0x6e*/ 0,
248         0,
249         /*0x6f*/ 0,
250         0,
251 
252         /*0x70*/ 0,
253         0,
254         /*0x71*/ 0,
255         0,
256         /*0x72*/ 0,
257         0,
258         /*0x73*/ 0,
259         0,
260         /*0x74*/ 0,
261         0,
262         /*0x75*/ 0,
263         0,
264         /*0x76*/ 0,
265         0,
266         /*0x77*/ 0,
267         0,
268         /*0x78*/ 0,
269         0,
270         /*0x79*/ 0,
271         0,
272         /*0x7a*/ 0,
273         0,
274         /*0x7b*/ 0,
275         0,
276         /*0x7c*/ 0,
277         0,
278         /*0x7d*/ 0,
279         0,
280         /*0x7e*/ 0,
281         0,
282         /*0x7f*/ 0,
283         0,
284 };
285 
286 /**
287  * @brief 解析键盘扫描码
288  *
289  */
keyboard_analyze_keycode(int fd)290 int keyboard_analyze_keycode(int fd)
291 {
292     bool flag_make = false;
293 
294     int c = keyboard_get_scancode(fd);
295     // 循环队列为空
296     if (c == -1)
297         return 0;
298 
299     unsigned char scancode = (unsigned char)c;
300 
301     int key = 0;
302     if (scancode == 0xE1) // Pause Break
303     {
304         key = PAUSE_BREAK;
305         // 清除缓冲区中剩下的扫描码
306         for (int i = 1; i < 6; ++i)
307             if (keyboard_get_scancode(fd) != pause_break_scan_code[i])
308             {
309                 key = 0;
310                 break;
311             }
312     }
313     else if (scancode == 0xE0) // 功能键, 有多个扫描码
314     {
315         // 获取下一个扫描码
316         scancode = keyboard_get_scancode(fd);
317         switch (scancode)
318         {
319         case 0x2a: // print screen 按键被按下
320             if (keyboard_get_scancode(fd) == 0xe0)
321                 if (keyboard_get_scancode(fd) == 0x37)
322                 {
323                     key = PRINT_SCREEN;
324                     flag_make = true;
325                 }
326             break;
327         case 0xb7: // print screen 按键被松开
328             if (keyboard_get_scancode(fd) == 0xe0)
329                 if (keyboard_get_scancode(fd) == 0xaa)
330                 {
331                     key = PRINT_SCREEN;
332                     flag_make = false;
333                 }
334             break;
335         case 0x1d: // 按下右边的ctrl
336             ctrl_r = true;
337             key = OTHER_KEY;
338             break;
339         case 0x9d: // 松开右边的ctrl
340             ctrl_r = false;
341             key = OTHER_KEY;
342             break;
343         case 0x38: // 按下右边的alt
344             alt_r = true;
345             key = OTHER_KEY;
346             break;
347         case 0xb8: // 松开右边的alt
348             alt_r = false;
349             key = OTHER_KEY;
350             break;
351         case 0x5b:
352             gui_l = true;
353             key = OTHER_KEY;
354             break;
355         case 0xdb:
356             gui_l = false;
357             key = OTHER_KEY;
358             break;
359         case 0x5c:
360             gui_r = true;
361             key = OTHER_KEY;
362             break;
363         case 0xdc:
364             gui_r = false;
365             key = OTHER_KEY;
366             break;
367         case 0x5d:
368             apps = true;
369             key = OTHER_KEY;
370             break;
371         case 0xdd:
372             apps = false;
373             key = OTHER_KEY;
374             break;
375         case 0x52:
376             insert = true;
377             key = OTHER_KEY;
378             break;
379         case 0xd2:
380             insert = false;
381             key = OTHER_KEY;
382             break;
383         case 0x47:
384             home = true;
385             key = OTHER_KEY;
386             break;
387         case 0xc7:
388             home = false;
389             key = OTHER_KEY;
390             break;
391         case 0x49:
392             pgup = true;
393             key = OTHER_KEY;
394             break;
395         case 0xc9:
396             pgup = false;
397             key = OTHER_KEY;
398             break;
399         case 0x53:
400             del = true;
401             key = OTHER_KEY;
402             break;
403         case 0xd3:
404             del = false;
405             key = OTHER_KEY;
406             break;
407         case 0x4f:
408             end = true;
409             key = OTHER_KEY;
410             break;
411         case 0xcf:
412             end = false;
413             key = OTHER_KEY;
414             break;
415         case 0x51:
416             pgdn = true;
417             key = OTHER_KEY;
418             break;
419         case 0xd1:
420             pgdn = false;
421             key = OTHER_KEY;
422             break;
423         case 0x48:
424             arrow_u = true;
425             key = OTHER_KEY;
426             break;
427         case 0xc8:
428             arrow_u = false;
429             key = OTHER_KEY;
430             return 0xc8;
431             break;
432         case 0x4b:
433             arrow_l = true;
434             key = OTHER_KEY;
435             break;
436         case 0xcb:
437             arrow_l = false;
438             key = OTHER_KEY;
439             break;
440         case 0x50:
441             arrow_d = true;
442             key = OTHER_KEY;
443             return 0x50;
444             break;
445         case 0xd0:
446             arrow_d = false;
447             key = OTHER_KEY;
448             break;
449         case 0x4d:
450             arrow_r = true;
451             key = OTHER_KEY;
452             break;
453         case 0xcd:
454             arrow_r = false;
455             key = OTHER_KEY;
456             break;
457 
458         case 0x35: // 数字小键盘的 / 符号
459             kp_forward_slash = true;
460             key = OTHER_KEY;
461             break;
462         case 0xb5:
463             kp_forward_slash = false;
464             key = OTHER_KEY;
465             break;
466         case 0x1c:
467             kp_en = true;
468             key = OTHER_KEY;
469             break;
470         case 0x9c:
471             kp_en = false;
472             key = OTHER_KEY;
473             break;
474 
475         default:
476             key = OTHER_KEY;
477             break;
478         }
479     }
480 
481     if (key == 0) // 属于第三类扫描码
482     {
483         // 判断按键是被按下还是抬起
484         flag_make = ((scancode & FLAG_BREAK) ? 0 : 1);
485 
486         // 计算扫描码位于码表的第几行
487         uint32_t *key_row = &keycode_map_normal[(scancode & 0x7f) * MAP_COLS];
488         unsigned char col = 0;
489         // shift被按下
490         if (shift_l || shift_r)
491             col = 1;
492         key = key_row[col];
493 
494         switch (scancode & 0x7f)
495         {
496         case 0x2a:
497             shift_l = flag_make;
498             key = 0;
499             break;
500         case 0x36:
501             shift_r = flag_make;
502             key = 0;
503             break;
504         case 0x1d:
505             ctrl_l = flag_make;
506             key = 0;
507             break;
508         case 0x38:
509             ctrl_r = flag_make;
510             key = 0;
511             break;
512         default:
513             if (!flag_make)
514                 key = 0;
515             break;
516         }
517         if (key)
518             return key;
519     }
520     return 0;
521 }
522 
523 /**
524  * @brief 从键盘设备文件中获取键盘扫描码
525  *
526  */
keyboard_get_scancode(int fd)527 int keyboard_get_scancode(int fd)
528 {
529     unsigned int ret = 0;
530     read(fd, &ret, 1);
531     return ret;
532 }