1
2
3
4
5
6
7
8
9
10#include <common.h>
11#include <console.h>
12#include <dm.h>
13#include <errno.h>
14#include <stdio_dev.h>
15#include <input.h>
16#ifdef CONFIG_DM_KEYBOARD
17#include <keyboard.h>
18#endif
19#include <linux/input.h>
20
21enum {
22
23 FLAG_SCROLL_LOCK = 1 << 0,
24 FLAG_NUM_LOCK = 1 << 1,
25 FLAG_CAPS_LOCK = 1 << 2,
26
27
28 KEY_RELEASE = 1 << 15,
29 KEY_MASK = 0xfff,
30};
31
32
33
34
35
36
37
38static const uchar kbd_plain_xlate[] = {
39 0xff, 0x1b, '1', '2', '3', '4', '5', '6',
40 '7', '8', '9', '0', '-', '=', '\b', '\t',
41 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
42 'o', 'p', '[', ']', '\r', 0xff, 'a', 's',
43 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
44 '\'', '`', 0xff, '\\', 'z', 'x', 'c', 'v',
45 'b', 'n', 'm', ',' , '.', '/', 0xff, 0xff, 0xff,
46 ' ', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
47 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '7',
48 '8', '9', '-', '4', '5', '6', '+', '1',
49 '2', '3', '0', '.', 0xff, 0xff, 0xff, 0xff,
50 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
51 '\r', 0xff, '/', '*',
52};
53
54static unsigned char kbd_shift_xlate[] = {
55 0xff, 0x1b, '!', '@', '#', '$', '%', '^',
56 '&', '*', '(', ')', '_', '+', '\b', '\t',
57 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
58 'O', 'P', '{', '}', '\r', 0xff, 'A', 'S',
59 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
60 '"', '~', 0xff, '|', 'Z', 'X', 'C', 'V',
61 'B', 'N', 'M', '<', '>', '?', 0xff, 0xff, 0xff,
62 ' ', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
63 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '7',
64 '8', '9', '-', '4', '5', '6', '+', '1',
65 '2', '3', '0', '.', 0xff, 0xff, 0xff, 0xff, 0xff,
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 '\r', 0xff, '/', '*',
68};
69
70static unsigned char kbd_ctrl_xlate[] = {
71 0xff, 0x1b, '1', 0x00, '3', '4', '5', 0x1E,
72 '7', '8', '9', '0', 0x1F, '=', '\b', '\t',
73 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09,
74 0x0f, 0x10, 0x1b, 0x1d, '\n', 0xff, 0x01, 0x13,
75 0x04, 0x06, 0x08, 0x09, 0x0a, 0x0b, 0x0c, ';',
76 '\'', '~', 0x00, 0x1c, 0x1a, 0x18, 0x03, 0x16,
77 0x02, 0x0e, 0x0d, '<', '>', '?', 0xff, 0xff,
78 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
79 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '7',
80 '8', '9', '-', '4', '5', '6', '+', '1',
81 '2', '3', '0', '.', 0xff, 0xff, 0xff, 0xff,
82 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
83 '\r', 0xff, '/', '*',
84};
85
86static const uchar kbd_plain_xlate_german[] = {
87 0xff, 0x1b, '1', '2', '3', '4', '5', '6',
88 '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t',
89 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
90 'o', 'p', 0x81, '+', '\r', 0xff, 'a', 's',
91 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94,
92 0x84, '^', 0xff, '#', 'y', 'x', 'c', 'v',
93 'b', 'n', 'm', ',', '.', '-', 0xff, '*',
94 ' ', ' ', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '7',
96 '8', '9', '-', '4', '5', '6', '+', '1',
97 '2', '3', '0', ',', 0xff, 0xff, '<', 0xff,
98 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
99 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
100 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
102 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
103 '\r', 0xff, '/', '*',
104};
105
106static unsigned char kbd_shift_xlate_german[] = {
107 0xff, 0x1b, '!', '"', 0x15, '$', '%', '&',
108 '/', '(', ')', '=', '?', '`', 0x08, '\t',
109 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I',
110 'O', 'P', 0x9a, '*', '\r', 0xff, 'A', 'S',
111 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0x99,
112 0x8e, 0xf8, 0xff, '\'', 'Y', 'X', 'C', 'V',
113 'B', 'N', 'M', ';', ':', '_', 0xff, '*',
114 ' ', ' ', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
115 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '7',
116 '8', '9', '-', '4', '5', '6', '+', '1',
117 '2', '3', '0', ',', 0xff, 0xff, '>', 0xff,
118 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
119 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
120 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
122 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
123 '\r', 0xff, '/', '*',
124};
125
126static unsigned char kbd_right_alt_xlate_german[] = {
127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
128 '{', '[', ']', '}', '\\', 0xff, 0xff, 0xff,
129 '@', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
130 0xff, 0xff, 0xff, '~', 0xff, 0xff, 0xff, 0xff,
131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff,
134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '|', 0xff,
138};
139
140enum kbd_mask {
141 KBD_ENGLISH = 1 << 0,
142 KBD_GERMAN = 1 << 1,
143};
144
145static struct kbd_entry {
146 int kbd_mask;
147 int left_keycode;
148 int right_keycode;
149 const uchar *xlate;
150 int num_entries;
151} kbd_entry[] = {
152 { KBD_ENGLISH, -1, -1,
153 kbd_plain_xlate, ARRAY_SIZE(kbd_plain_xlate) },
154 { KBD_GERMAN, -1, -1,
155 kbd_plain_xlate_german, ARRAY_SIZE(kbd_plain_xlate_german) },
156 { KBD_ENGLISH, KEY_LEFTSHIFT, KEY_RIGHTSHIFT,
157 kbd_shift_xlate, ARRAY_SIZE(kbd_shift_xlate) },
158 { KBD_GERMAN, KEY_LEFTSHIFT, KEY_RIGHTSHIFT,
159 kbd_shift_xlate_german, ARRAY_SIZE(kbd_shift_xlate_german) },
160 { KBD_ENGLISH | KBD_GERMAN, KEY_LEFTCTRL, KEY_RIGHTCTRL,
161 kbd_ctrl_xlate, ARRAY_SIZE(kbd_ctrl_xlate) },
162 { KBD_GERMAN, -1, KEY_RIGHTALT,
163 kbd_right_alt_xlate_german,
164 ARRAY_SIZE(kbd_right_alt_xlate_german) },
165 {},
166};
167
168
169
170
171
172static struct {
173 int kbd_scan_code;
174 char *escape;
175} kbd_to_ansi364[] = {
176 { KEY_UP, "\033[A"},
177 { KEY_DOWN, "\033[B"},
178 { KEY_RIGHT, "\033[C"},
179 { KEY_LEFT, "\033[D"},
180};
181
182
183#define ANSI_CHAR_MAX 3
184
185static int input_queue_ascii(struct input_config *config, int ch)
186{
187 if (config->fifo_in + 1 == INPUT_BUFFER_LEN) {
188 if (!config->fifo_out)
189 return -1;
190 else
191 config->fifo_in = 0;
192 } else {
193 if (config->fifo_in + 1 == config->fifo_out)
194 return -1;
195 config->fifo_in++;
196 }
197 debug(" {%02x} ", ch);
198 config->fifo[config->fifo_in] = (uchar)ch;
199
200 return 0;
201}
202
203int input_tstc(struct input_config *config)
204{
205 if (config->fifo_in == config->fifo_out && config->read_keys) {
206 if (!(*config->read_keys)(config))
207 return 0;
208 }
209 return config->fifo_in != config->fifo_out;
210}
211
212int input_getc(struct input_config *config)
213{
214 int err = 0;
215
216 while (config->fifo_in == config->fifo_out) {
217 if (config->read_keys)
218 err = (*config->read_keys)(config);
219 if (err)
220 return -1;
221 }
222
223 if (++config->fifo_out == INPUT_BUFFER_LEN)
224 config->fifo_out = 0;
225
226 return config->fifo[config->fifo_out];
227}
228
229
230
231
232
233
234
235
236
237
238
239
240static struct input_key_xlate *process_modifier(struct input_config *config,
241 int key, int release)
242{
243#ifdef CONFIG_DM_KEYBOARD
244 struct udevice *dev = config->dev;
245 struct keyboard_ops *ops = keyboard_get_ops(dev);
246#endif
247 struct input_key_xlate *table;
248 int i;
249
250
251 assert(config->num_tables > 0);
252 table = &config->table[0];
253 for (i = 1; i < config->num_tables; i++) {
254 struct input_key_xlate *tab = &config->table[i];
255
256 if (key == tab->left_keycode || key == tab->right_keycode)
257 table = tab;
258 }
259
260
261 if (!release) {
262 int flip = -1;
263
264 switch (key) {
265 case KEY_SCROLLLOCK:
266 flip = FLAG_SCROLL_LOCK;
267 break;
268 case KEY_NUMLOCK:
269 flip = FLAG_NUM_LOCK;
270 break;
271 case KEY_CAPSLOCK:
272 flip = FLAG_CAPS_LOCK;
273 break;
274 }
275
276 if (flip != -1) {
277 int leds = 0;
278
279 config->flags ^= flip;
280 if (config->flags & FLAG_NUM_LOCK)
281 leds |= INPUT_LED_NUM;
282 if (config->flags & FLAG_CAPS_LOCK)
283 leds |= INPUT_LED_CAPS;
284 if (config->flags & FLAG_SCROLL_LOCK)
285 leds |= INPUT_LED_SCROLL;
286 config->leds = leds;
287 config->leds_changed = flip;
288
289#ifdef CONFIG_DM_KEYBOARD
290 if (ops->update_leds) {
291 if (ops->update_leds(dev, config->leds))
292 debug("Update keyboard's LED failed\n");
293 }
294#endif
295 }
296 }
297
298 return table;
299}
300
301
302
303
304
305
306
307
308
309static int array_search(int *array, int count, int key)
310{
311 int i;
312
313 for (i = 0; i < count; i++) {
314 if (array[i] == key)
315 return i;
316 }
317
318 return -1;
319}
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335static int sort_array_by_ordering(int *dest, int count, int *order,
336 int ocount)
337{
338 int temp[count];
339 int dest_count;
340 int same;
341 int i;
342
343
344 memcpy(temp, dest, count * sizeof(*dest));
345 dest_count = 0;
346
347
348 for (i = 0; i < ocount; i++) {
349 if (array_search(temp, count, order[i]) != -1)
350 dest[dest_count++] = order[i];
351 }
352 same = dest_count;
353
354
355 for (i = 0; i < count; i++) {
356 if (array_search(order, ocount, temp[i]) == -1)
357 dest[dest_count++] = temp[i];
358 }
359 assert(dest_count == count);
360 return same;
361}
362
363
364
365
366
367
368
369
370
371
372
373
374static int input_check_keycodes(struct input_config *config,
375 int keycode[], int num_keycodes, int *same)
376{
377
378 if (!config->num_tables) {
379 debug("%s: No xlate tables: cannot decode keys\n", __func__);
380 return -1;
381 }
382
383
384 *same = sort_array_by_ordering(keycode, num_keycodes,
385 config->prev_keycodes, config->num_prev_keycodes);
386
387 memcpy(config->prev_keycodes, keycode, num_keycodes * sizeof(int));
388 config->num_prev_keycodes = num_keycodes;
389
390 return *same != num_keycodes;
391}
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406static int input_keycode_to_ansi364(struct input_config *config,
407 int keycode, char output_ch[], int max_chars)
408{
409 const char *escape;
410 int ch_count;
411 int i;
412
413 for (i = ch_count = 0; i < ARRAY_SIZE(kbd_to_ansi364); i++) {
414 if (keycode != kbd_to_ansi364[i].kbd_scan_code)
415 continue;
416 for (escape = kbd_to_ansi364[i].escape; *escape; escape++) {
417 if (ch_count < max_chars)
418 output_ch[ch_count] = *escape;
419 ch_count++;
420 }
421 return ch_count;
422 }
423
424 return 0;
425}
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449static int input_keycodes_to_ascii(struct input_config *config,
450 int keycode[], int num_keycodes, char output_ch[],
451 int max_chars, int same)
452{
453 struct input_key_xlate *table;
454 int ch_count = 0;
455 int i;
456
457 table = &config->table[0];
458
459
460 for (i = 0; i < num_keycodes; i++) {
461 int key = keycode[i] & KEY_MASK;
462
463 if (key >= table->num_entries || table->xlate[key] == 0xff) {
464 table = process_modifier(config, key,
465 keycode[i] & KEY_RELEASE);
466 }
467 }
468
469
470 for (i = same; i < num_keycodes; i++) {
471 int key = keycode[i];
472 int ch;
473
474
475
476
477
478 if (key < table->num_entries) {
479 ch = table->xlate[key];
480 if ((config->flags & FLAG_CAPS_LOCK) &&
481 ch >= 'a' && ch <= 'z')
482 ch -= 'a' - 'A';
483
484 if (!(config->flags & FLAG_NUM_LOCK)) {
485 if (key >= KEY_KP7 && key <= KEY_KPDOT &&
486 key != KEY_KPMINUS && key != KEY_KPPLUS)
487 ch = 0xff;
488 }
489 if (ch_count < max_chars && ch != 0xff)
490 output_ch[ch_count++] = (uchar)ch;
491 } else {
492 ch_count += input_keycode_to_ansi364(config, key,
493 output_ch, max_chars);
494 }
495 }
496
497 if (ch_count > max_chars) {
498 debug("%s: Output char buffer overflow size=%d, need=%d\n",
499 __func__, max_chars, ch_count);
500 return -1;
501 }
502
503
504 return ch_count;
505}
506
507static int _input_send_keycodes(struct input_config *config, int keycode[],
508 int num_keycodes, bool do_send)
509{
510 char ch[num_keycodes * ANSI_CHAR_MAX];
511 int count, i, same = 0;
512 int is_repeat = 0;
513 unsigned delay_ms;
514
515 config->modifiers = 0;
516 if (!input_check_keycodes(config, keycode, num_keycodes, &same)) {
517
518
519
520
521
522
523
524
525 is_repeat = config->allow_repeats || (config->repeat_rate_ms &&
526 (int)get_timer(config->next_repeat_ms) >= 0);
527 if (!is_repeat)
528 return 0;
529 }
530
531 count = input_keycodes_to_ascii(config, keycode, num_keycodes,
532 ch, sizeof(ch), is_repeat ? 0 : same);
533 if (do_send) {
534 for (i = 0; i < count; i++)
535 input_queue_ascii(config, ch[i]);
536 }
537 delay_ms = is_repeat ?
538 config->repeat_rate_ms :
539 config->repeat_delay_ms;
540
541 config->next_repeat_ms = get_timer(0) + delay_ms;
542
543 return count;
544}
545
546int input_send_keycodes(struct input_config *config, int keycode[],
547 int num_keycodes)
548{
549 return _input_send_keycodes(config, keycode, num_keycodes, true);
550}
551
552int input_add_keycode(struct input_config *config, int new_keycode,
553 bool release)
554{
555 int keycode[INPUT_MAX_MODIFIERS + 1];
556 int count, i;
557
558
559 for (i = 0, count = 0; i < config->num_prev_keycodes; i++) {
560 int code = config->prev_keycodes[i];
561
562 if (new_keycode == code) {
563 if (release)
564 continue;
565 new_keycode = -1;
566 }
567 keycode[count++] = code;
568 }
569
570 if (!release && new_keycode != -1)
571 keycode[count++] = new_keycode;
572 debug("\ncodes for %02x/%d: ", new_keycode, release);
573 for (i = 0; i < count; i++)
574 debug("%02x ", keycode[i]);
575 debug("\n");
576
577
578 return _input_send_keycodes(config, keycode, count, !release);
579}
580
581int input_add_table(struct input_config *config, int left_keycode,
582 int right_keycode, const uchar *xlate, int num_entries)
583{
584 struct input_key_xlate *table;
585
586 if (config->num_tables == INPUT_MAX_MODIFIERS) {
587 debug("%s: Too many modifier tables\n", __func__);
588 return -1;
589 }
590
591 table = &config->table[config->num_tables++];
592 table->left_keycode = left_keycode;
593 table->right_keycode = right_keycode;
594 table->xlate = xlate;
595 table->num_entries = num_entries;
596
597 return 0;
598}
599
600void input_set_delays(struct input_config *config, int repeat_delay_ms,
601 int repeat_rate_ms)
602{
603 config->repeat_delay_ms = repeat_delay_ms;
604 config->repeat_rate_ms = repeat_rate_ms;
605}
606
607void input_allow_repeats(struct input_config *config, bool allow_repeats)
608{
609 config->allow_repeats = allow_repeats;
610}
611
612int input_leds_changed(struct input_config *config)
613{
614 if (config->leds_changed)
615 return config->leds;
616
617 return -1;
618}
619
620int input_add_tables(struct input_config *config, bool german)
621{
622 struct kbd_entry *entry;
623 int mask;
624 int ret;
625
626 mask = german ? KBD_GERMAN : KBD_ENGLISH;
627 for (entry = kbd_entry; entry->kbd_mask; entry++) {
628 if (!(mask & entry->kbd_mask))
629 continue;
630 ret = input_add_table(config, entry->left_keycode,
631 entry->right_keycode, entry->xlate,
632 entry->num_entries);
633 if (ret)
634 return ret;
635 }
636
637 return 0;
638}
639
640int input_init(struct input_config *config, int leds)
641{
642 memset(config, '\0', sizeof(*config));
643 config->leds = leds;
644
645 return 0;
646}
647
648int input_stdio_register(struct stdio_dev *dev)
649{
650 int error;
651
652 error = stdio_register(dev);
653
654
655 if (!error && strcmp(getenv("stdin"), dev->name) == 0) {
656
657 if (OVERWRITE_CONSOLE ||
658 console_assign(stdin, dev->name))
659 return -1;
660 }
661
662 return 0;
663}
664