1 /*
2 * Support for decoding of VT ioctl commands.
3 *
4 * Copyright (c) 2019-2021 Eugene Syromyatnikov <evgsyr@gmail.com>
5 * Copyright (c) 2019-2022 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: LGPL-2.1-or-later
9 */
10
11 #include "defs.h"
12
13 #include <linux/kd.h>
14 #include <linux/keyboard.h>
15
16 #include "print_fields.h"
17 #include "print_utils.h"
18
19 #include "xlat/kd_default_led_flags.h"
20 #include "xlat/kd_kbd_modes.h"
21 #include "xlat/kd_kbd_types.h"
22 #include "xlat/kd_keymap_flags.h"
23 #include "xlat/kd_key_tables.h"
24 #include "xlat/kd_key_types.h"
25 #include "xlat/kd_key_fn_keys.h"
26 #include "xlat/kd_key_fn_key_vals.h"
27 #include "xlat/kd_key_spec_keys.h"
28 #include "xlat/kd_key_pad_keys.h"
29 #include "xlat/kd_key_dead_keys.h"
30 #include "xlat/kd_key_cur_keys.h"
31 #include "xlat/kd_key_shift_keys.h"
32 #include "xlat/kd_key_ascii_keys.h"
33 #include "xlat/kd_key_lock_keys.h"
34 #include "xlat/kd_key_slock_keys.h"
35 #include "xlat/kd_key_brl_keys.h"
36 #include "xlat/kd_led_flags.h"
37 #include "xlat/kd_meta_vals.h"
38 #include "xlat/kd_modes.h"
39
40 #define XLAT_MACROS_ONLY
41 # include "xlat/kd_ioctl_cmds.h"
42 #undef XLAT_MACROS_ONLY
43
44 #ifdef HAVE_STRUCT_KBDIACRUC
45 typedef struct kbdiacruc struct_kbdiacruc;
46 #else
47 typedef struct {
48 unsigned int diacr;
49 unsigned int base;
50 unsigned int result;
51 } struct_kbdiacruc;
52 #endif
53
54 #ifdef HAVE_STRUCT_KBDIACRSUC
55 typedef struct kbdiacrsuc struct_kbdiacrsuc;
56 #else
57 typedef struct {
58 unsigned int kb_cnt;
59 struct_kbdiacruc kbdiacruc[256];
60 } struct_kbdiacrsuc;
61 #endif
62
63 enum {
64 KERNEL_PIT_TICK_RATE = 1193182,
65 KERNEL_E_TABSZ = 256,
66 KERNEL_MAX_DIACR = 256,
67 };
68
69 static int
70 kiocsound(struct tcb *const tcp, const kernel_ulong_t arg)
71 {
72 unsigned int freq = arg ? KERNEL_PIT_TICK_RATE / arg : 0;
73
74 tprint_arg_next();
75 PRINT_VAL_U(arg);
76 if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) {
77 if (freq)
78 tprintf_comment("%u Hz", freq);
79 else
80 tprints_comment("off");
81 }
82
83 return RVAL_IOCTL_DECODED;
84 }
85
86 static int
87 kd_mk_tone(struct tcb *const tcp, const unsigned int arg)
88 {
89 unsigned int ticks = arg >> 16;
90 unsigned int count = arg & 0xFFFF;
91 unsigned int freq = ticks && count ? KERNEL_PIT_TICK_RATE / count : 0;
92
93 tprint_arg_next();
94 tprint_flags_begin();
95 if (ticks) {
96 tprint_shift_begin();
97 PRINT_VAL_U(ticks);
98 tprint_shift();
99 PRINT_VAL_U(16);
100 tprint_shift_end();
101 tprint_flags_or();
102 }
103 PRINT_VAL_U(count);
104 tprint_flags_end();
105
106 if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) {
107 if (freq)
108 tprintf_comment("%u Hz, %u ms", freq, ticks);
109 else
110 tprints_comment("off");
111 }
112
113 return RVAL_IOCTL_DECODED;
114 }
115
116 static void
117 print_leds(struct tcb *const tcp, const kernel_ulong_t arg,
118 const bool get, const bool dflt)
119 {
120 unsigned char val;
121
122 if (get) {
123 if (umove_or_printaddr(tcp, arg, &val))
124 return;
125 } else {
126 val = arg;
127 }
128
129 if (get)
130 tprint_indirect_begin();
131 printflags(dflt ? kd_default_led_flags : kd_led_flags, val,
132 "LED_???");
133 if (get)
134 tprint_indirect_end();
135 }
136
137 static int
138 kd_leds(struct tcb *const tcp, const unsigned int code,
139 const kernel_ulong_t arg)
140 {
141 bool get = false;
142 bool dflt = false;
143
144 switch (code) {
145 case KDGETLED:
146 case KDGKBLED:
147 get = true;
148 }
149
150 switch (code) {
151 case KDGKBLED:
152 case KDSKBLED:
153 dflt = true;
154 }
155
156 if (entering(tcp)) {
157 tprint_arg_next();
158
159 if (get)
160 return 0;
161 }
162
163 print_leds(tcp, arg, get, dflt);
164
165 return RVAL_IOCTL_DECODED;
166 }
167
168 static int
169 kd_get_kb_type(struct tcb *const tcp, const kernel_ulong_t arg)
170 {
171 unsigned char val;
172
173 if (entering(tcp)) {
174 tprint_arg_next();
175 return 0;
176 }
177
178 if (umove_or_printaddr(tcp, arg, &val))
179 return RVAL_IOCTL_DECODED;
180
181 tprint_indirect_begin();
182 printxval(kd_kbd_types, val, "KB_???");
183 tprint_indirect_end();
184
185 return RVAL_IOCTL_DECODED;
186 }
187
188 static int
189 kd_io(struct tcb *const tcp, kernel_ulong_t arg)
190 {
191 enum { GPFIRST = 0x3b4, GPLAST = 0x3df };
192
193 tprint_arg_next();
194 PRINT_VAL_X(arg);
195
196 if (arg >= GPFIRST && arg <= GPLAST
197 && xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW)
198 tprintf_comment("GPFIRST + %" PRI_klu, arg - GPFIRST);
199
200 return RVAL_IOCTL_DECODED;
201 }
202
203 static int
204 kd_set_mode(struct tcb *const tcp, const kernel_ulong_t arg)
205 {
206 tprint_arg_next();
207 printxval(kd_modes, arg, "KD_???");
208
209 return RVAL_IOCTL_DECODED;
210 }
211
212 static int
213 kd_get_mode(struct tcb *const tcp, const kernel_ulong_t arg)
214 {
215 unsigned int val;
216
217 if (entering(tcp)) {
218 tprint_arg_next();
219 return 0;
220 }
221
222 if (umove_or_printaddr(tcp, arg, &val))
223 return RVAL_IOCTL_DECODED;
224
225 tprint_indirect_begin();
226 printxval(kd_modes, val, "KD_???");
227 tprint_indirect_end();
228
229 return RVAL_IOCTL_DECODED;
230 }
231
232 static int
233 kd_screen_map(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
234 {
235 if (entering(tcp)) {
236 tprint_arg_next();
237
238 if (get)
239 return 0;
240 }
241
242 if (entering(tcp) || !syserror(tcp))
243 printstr_ex(tcp, arg, KERNEL_E_TABSZ, QUOTE_FORCE_HEX);
244 else
245 printaddr(arg);
246
247 return RVAL_IOCTL_DECODED;
248 }
249
250 static bool
251 print_scrmap_array_member(struct tcb *tcp, void *elem_buf,
252 size_t elem_size, void *data)
253 {
254 unsigned short val = *(unsigned short *) elem_buf;
255
256 if ((xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) ||
257 ((val & ~UNI_DIRECT_MASK) != UNI_DIRECT_BASE))
258 PRINT_VAL_X(val);
259
260 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
261 return true;
262
263 if ((val & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
264 (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE
265 ? tprintf_comment : tprintf_string)("UNI_DIRECT_BASE+%#hx",
266 val & UNI_DIRECT_MASK);
267
268 return true;
269 }
270
271 static int
272 kd_uni_screen_map(struct tcb *const tcp, const kernel_ulong_t arg,
273 const bool get)
274 {
275 unsigned short elem;
276
277 if (entering(tcp)) {
278 tprint_arg_next();
279
280 if (get)
281 return 0;
282 }
283
284 print_array(tcp, arg, KERNEL_E_TABSZ, &elem, sizeof(elem),
285 tfetch_mem, print_scrmap_array_member, 0);
286
287 return RVAL_IOCTL_DECODED;
288 }
289
290 static int
291 kd_set_kbd_mode(struct tcb *const tcp, const unsigned int arg)
292 {
293 tprint_arg_next();
294 printxval_d(kd_kbd_modes, arg, "K_???");
295
296 return RVAL_IOCTL_DECODED;
297 }
298
299 static int
300 kd_get_kbd_mode(struct tcb *const tcp, const kernel_ulong_t arg)
301 {
302 unsigned int val;
303
304 if (entering(tcp)) {
305 tprint_arg_next();
306 return 0;
307 }
308
309 if (umove_or_printaddr(tcp, arg, &val))
310 return RVAL_IOCTL_DECODED;
311
312 tprint_indirect_begin();
313 printxval_d(kd_kbd_modes, val, "K_???");
314 tprint_indirect_end();
315
316 return RVAL_IOCTL_DECODED;
317 }
318
319 static int
320 kd_kbd_entry(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
321 {
322 static const struct xlat *xlat_tables[] = {
323 /* KT_LATIN */
324 [KT_FN] = kd_key_fn_keys,
325 [KT_SPEC] = kd_key_spec_keys,
326 [KT_PAD] = kd_key_pad_keys,
327 [KT_DEAD] = kd_key_dead_keys,
328 /* KT_CONS */
329 [KT_CUR] = kd_key_cur_keys,
330 [KT_SHIFT] = kd_key_shift_keys,
331 /* KT_META */
332 [KT_ASCII] = kd_key_ascii_keys,
333 [KT_LOCK] = kd_key_lock_keys,
334 /* KT_LETTER */
335 [KT_SLOCK] = kd_key_slock_keys,
336 /* KT_DEAD2 */
337 [KT_BRL] = kd_key_brl_keys,
338 };
339
340 struct kbentry val;
341 unsigned char ktyp;
342 unsigned char kval;
343 const char *str = NULL;
344
345 if (entering(tcp)) {
346 tprint_arg_next();
347
348 if (umoven(tcp, arg, offsetofend(struct kbentry, kb_index),
349 &val)) {
350 printaddr(arg);
351 return RVAL_IOCTL_DECODED;
352 }
353
354 tprint_struct_begin();
355
356 const char *keymap_str = xlookup(kd_key_tables, val.kb_table);
357
358 if (keymap_str) {
359 tprints_field_name("kb_table");
360 print_xlat_ex(val.kb_table, keymap_str,
361 XLAT_STYLE_DEFAULT);
362 } else {
363 PRINT_FIELD_FLAGS(val, kb_table, kd_keymap_flags,
364 "K_???");
365 }
366
367 tprint_struct_next();
368 PRINT_FIELD_U(val, kb_index);
369
370 if (get)
371 return 0;
372 } else if (syserror(tcp)) {
373 goto out;
374 }
375
376 tprint_struct_next();
377 if (umove(tcp, arg + offsetof(struct kbentry, kb_value),
378 &val.kb_value)) {
379 tprints_field_name("kb_value");
380 tprint_unavailable();
381 goto out;
382 }
383
384 PRINT_FIELD_X(val, kb_value);
385
386 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
387 goto out;
388
389 ktyp = KTYP(val.kb_value);
390 kval = KVAL(val.kb_value);
391
392 if (ktyp < ARRAY_SIZE(xlat_tables) && xlat_tables[ktyp])
393 str = xlookup(xlat_tables[ktyp], val.kb_value);
394
395 if (str) {
396 tprints_comment(str);
397 } else {
398 tprint_comment_begin();
399 tprints_arg_begin("K");
400 printxvals_ex(ktyp, NULL, XLAT_STYLE_ABBREV,
401 kd_key_types, NULL);
402 tprint_arg_next();
403
404 switch (ktyp) {
405 case KT_LATIN:
406 case KT_META:
407 case KT_LETTER:
408 case KT_DEAD2:
409 print_char(kval, SCF_QUOTES | SCF_ESC_WS);
410 break;
411 default:
412 PRINT_VAL_X(kval);
413 }
414
415 tprint_arg_end();
416 tprint_comment_end();
417 }
418
419 out:
420 tprint_struct_end();
421
422 return RVAL_IOCTL_DECODED;
423 }
424
425 static int
426 kd_kbd_str_entry(struct tcb *const tcp, const kernel_ulong_t arg,
427 const bool get)
428 {
429 struct kbsentry val;
430
431 if (entering(tcp)) {
432 tprint_arg_next();
433
434 if (umove_or_printaddr(tcp, arg, &(val.kb_func)))
435 return RVAL_IOCTL_DECODED;
436
437 tprint_struct_begin();
438 PRINT_FIELD_XVAL(val, kb_func, kd_key_fn_key_vals,
439 "KVAL(K_???"")");
440
441 if (get)
442 return 0;
443 } else if (syserror(tcp)) {
444 goto out;
445 }
446
447 tprint_struct_next();
448 tprints_field_name("kb_string");
449
450 int ret = umovestr(tcp, arg + offsetof(struct kbsentry, kb_string),
451 sizeof(val.kb_string), (char *) val.kb_string);
452
453 if (ret < 0) {
454 tprint_unavailable();
455 goto out;
456 }
457
458 if (print_quoted_string((char *) val.kb_string,
459 MIN(max_strlen,
460 (unsigned int) ret ?: sizeof(val.kb_string)),
461 QUOTE_OMIT_TRAILING_0))
462 tprint_more_data_follows();
463
464 out:
465 tprint_struct_end();
466
467 return RVAL_IOCTL_DECODED;
468 }
469
470 static bool
471 print_kbdiacr_array_member(struct tcb *tcp, void *elem_buf,
472 size_t elem_size, void *data)
473 {
474 struct kbdiacr *val = elem_buf;
475
476 tprint_struct_begin();
477 PRINT_FIELD_CHAR(*val, diacr, SCF_QUOTES | SCF_ESC_WS);
478 tprint_struct_next();
479 PRINT_FIELD_CHAR(*val, base, SCF_QUOTES | SCF_ESC_WS);
480 tprint_struct_next();
481 PRINT_FIELD_CHAR(*val, result, SCF_QUOTES | SCF_ESC_WS);
482 tprint_struct_end();
483
484 return true;
485 }
486
487 static int
488 kd_diacr(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
489 {
490 unsigned int kb_cnt; /* struct kbdiacrs.kb_cnt */
491 struct kbdiacr elem;
492
493 if (entering(tcp)) {
494 tprint_arg_next();
495
496 if (get)
497 return 0;
498 }
499
500 if (umove_or_printaddr(tcp, arg, &kb_cnt))
501 return RVAL_IOCTL_DECODED;
502
503 tprint_struct_begin();
504 tprints_field_name("kb_cnt");
505 PRINT_VAL_U(kb_cnt);
506 tprint_struct_next();
507 tprints_field_name("kbdiacr");
508 print_array_ex(tcp, arg + offsetof(struct kbdiacrs, kbdiacr),
509 MIN(kb_cnt, KERNEL_MAX_DIACR), &elem, sizeof(elem),
510 tfetch_mem, print_kbdiacr_array_member, 0,
511 kb_cnt > KERNEL_MAX_DIACR ? PAF_ARRAY_TRUNCATED : 0,
512 NULL, NULL);
513 tprint_struct_end();
514
515 return RVAL_IOCTL_DECODED;
516 }
517
518 static bool
519 print_kbdiacruc_array_member(struct tcb *tcp, void *elem_buf,
520 size_t elem_size, void *data)
521 {
522 struct_kbdiacruc *val = elem_buf;
523
524 tprint_struct_begin();
525 PRINT_FIELD_X(*val, diacr);
526 tprint_struct_next();
527 PRINT_FIELD_X(*val, base);
528 tprint_struct_next();
529 PRINT_FIELD_X(*val, result);
530 tprint_struct_end();
531
532 return true;
533 }
534
535 static int
536 kd_diacr_uc(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
537 {
538 unsigned int kb_cnt; /* struct kbdiacrs.kb_cnt */
539 struct_kbdiacruc elem;
540
541 if (entering(tcp)) {
542 tprint_arg_next();
543
544 if (get)
545 return 0;
546 }
547
548 if (umove_or_printaddr(tcp, arg, &kb_cnt))
549 return RVAL_IOCTL_DECODED;
550
551 tprint_struct_begin();
552 tprints_field_name("kb_cnt");
553 PRINT_VAL_U(kb_cnt);
554 tprint_struct_next();
555 tprints_field_name("kbdiacruc");
556 print_array_ex(tcp, arg + offsetof(struct_kbdiacrsuc, kbdiacruc),
557 MIN(kb_cnt, KERNEL_MAX_DIACR), &elem, sizeof(elem),
558 tfetch_mem, print_kbdiacruc_array_member, 0,
559 kb_cnt > KERNEL_MAX_DIACR ? PAF_ARRAY_TRUNCATED : 0,
560 NULL, NULL);
561 tprint_struct_end();
562
563 return RVAL_IOCTL_DECODED;
564 }
565
566 static int
567 kd_keycode(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
568 {
569 struct kbkeycode val;
570
571 if (entering(tcp)) {
572 tprint_arg_next();
573
574 if (umove_or_printaddr(tcp, arg, &val))
575 return RVAL_IOCTL_DECODED;
576
577 tprint_struct_begin();
578 PRINT_FIELD_X(val, scancode);
579 tprint_struct_next();
580 PRINT_FIELD_X(val, keycode);
581
582 if (get)
583 return 0;
584
585 goto end;
586 }
587
588 /* exiting */
589 if (syserror(tcp) ||
590 umove(tcp, arg + offsetof(struct kbkeycode, keycode), &val.keycode))
591 {
592 tprint_struct_end();
593 return RVAL_IOCTL_DECODED;
594 }
595
596 tprint_value_changed();
597 PRINT_VAL_X(val.keycode);
598
599 end:
600 tprint_struct_end();
601
602 return RVAL_IOCTL_DECODED;
603 }
604
605 static int
606 kd_sigaccept(struct tcb *const tcp, const kernel_ulong_t arg)
607 {
608 tprint_arg_next();
609
610 if (arg < INT_MAX)
611 printsignal(arg);
612 else
613 PRINT_VAL_U(arg);
614
615 return RVAL_IOCTL_DECODED;
616 }
617
618 static void
619 print_kbd_repeat(struct kbd_repeat *val)
620 {
621 tprint_struct_begin();
622 PRINT_FIELD_D(*val, delay);
623 tprint_struct_next();
624 PRINT_FIELD_D(*val, period);
625 tprint_struct_end();
626 }
627
628 static int
629 kd_kbdrep(struct tcb *const tcp, const kernel_ulong_t arg)
630 {
631 struct kbd_repeat val;
632
633 if (entering(tcp)) {
634 tprint_arg_next();
635
636 if (umove_or_printaddr(tcp, arg, &val))
637 return RVAL_IOCTL_DECODED;
638
639 print_kbd_repeat(&val);
640
641 return 0;
642 }
643
644 /* exiting */
645 if (syserror(tcp) || umove(tcp, arg, &val))
646 return RVAL_IOCTL_DECODED;
647
648 tprint_value_changed();
649
650 print_kbd_repeat(&val);
651
652 return RVAL_IOCTL_DECODED;
653 }
654
655 static int
656 kd_font(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
657 {
658 if (entering(tcp)) {
659 tprint_arg_next();
660
661 if (get)
662 return 0;
663 }
664
665 /*
666 * [GP]IO_FONT are equivalent to KDFONTOP with width == 8,
667 * height == 32, and charcount == 256, so the total size
668 * is (width + 7) / 8 * height * charcount == 8192.
669 */
670 if (exiting(tcp) && syserror(tcp))
671 printaddr(arg);
672 else
673 printstr_ex(tcp, arg, 8192, QUOTE_FORCE_HEX);
674
675 return RVAL_IOCTL_DECODED;
676 }
677
678 static int
679 kd_kbmeta(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
680 {
681 unsigned int val;
682
683 if (entering(tcp)) {
684 tprint_arg_next();
685
686 if (get)
687 return 0;
688 }
689
690 if (get) {
691 if (umove_or_printaddr(tcp, arg, &val))
692 return RVAL_IOCTL_DECODED;
693 } else {
694 val = arg;
695 }
696
697 if (get)
698 tprint_indirect_begin();
699 printxval(kd_meta_vals, val, "K_???");
700 if (get)
701 tprint_indirect_end();
702
703 return RVAL_IOCTL_DECODED;
704 }
705
706 static int
707 kd_unimapclr(struct tcb *const tcp, const kernel_ulong_t arg)
708 {
709 struct unimapinit umi;
710
711 tprint_arg_next();
712
713 if (umove_or_printaddr(tcp, arg, &umi))
714 return RVAL_IOCTL_DECODED;
715
716 tprint_struct_begin();
717 PRINT_FIELD_U(umi, advised_hashsize);
718 tprint_struct_next();
719 PRINT_FIELD_U(umi, advised_hashstep);
720 tprint_struct_next();
721 PRINT_FIELD_U(umi, advised_hashlevel);
722 tprint_struct_end();
723
724 return RVAL_IOCTL_DECODED;
725 }
726
727 static int
728 kd_cmap(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
729 {
730 if (entering(tcp)) {
731 tprint_arg_next();
732
733 if (get)
734 return 0;
735 } else {
736 if (syserror(tcp)) {
737 printaddr(arg);
738
739 return RVAL_IOCTL_DECODED;
740 }
741 }
742
743 printstr_ex(tcp, arg, 3 * 16, QUOTE_FORCE_HEX);
744
745 return RVAL_IOCTL_DECODED;
746 }
747
748 int
749 kd_ioctl(struct tcb *const tcp, const unsigned int code,
750 kernel_ulong_t arg)
751 {
752 arg = truncate_kulong_to_current_wordsize(arg);
753
754 switch (code) {
755 case KIOCSOUND:
756 return kiocsound(tcp, arg);
757
758 case KDMKTONE:
759 return kd_mk_tone(tcp, arg);
760
761 case KDGETLED:
762 case KDSETLED:
763 case KDGKBLED:
764 case KDSKBLED:
765 return kd_leds(tcp, code, arg);
766
767 case KDGKBTYPE:
768 return kd_get_kb_type(tcp, arg);
769
770 case KDADDIO:
771 case KDDELIO:
772 return kd_io(tcp, arg);
773
774 case KDSETMODE:
775 return kd_set_mode(tcp, arg);
776 case KDGETMODE:
777 return kd_get_mode(tcp, arg);
778
779 case GIO_SCRNMAP:
780 case PIO_SCRNMAP:
781 return kd_screen_map(tcp, arg, code == GIO_SCRNMAP);
782
783 case GIO_UNISCRNMAP:
784 case PIO_UNISCRNMAP:
785 return kd_uni_screen_map(tcp, arg, code == GIO_UNISCRNMAP);
786
787 case KDGKBMODE:
788 return kd_get_kbd_mode(tcp, arg);
789 case KDSKBMODE:
790 return kd_set_kbd_mode(tcp, arg);
791
792 case KDGKBENT:
793 case KDSKBENT:
794 return kd_kbd_entry(tcp, arg, code == KDGKBENT);
795
796 case KDGKBSENT:
797 case KDSKBSENT:
798 return kd_kbd_str_entry(tcp, arg, code == KDGKBSENT);
799
800 case KDGKBDIACR:
801 case KDSKBDIACR:
802 return kd_diacr(tcp, arg, code == KDGKBDIACR);
803
804 case KDGKBDIACRUC:
805 case KDSKBDIACRUC:
806 return kd_diacr_uc(tcp, arg, code == KDGKBDIACRUC);
807
808 case KDGETKEYCODE:
809 case KDSETKEYCODE:
810 return kd_keycode(tcp, arg, code == KDGETKEYCODE);
811
812 case KDSIGACCEPT:
813 return kd_sigaccept(tcp, arg);
814
815 case KDKBDREP:
816 return kd_kbdrep(tcp, arg);
817
818 case GIO_FONT:
819 case PIO_FONT:
820 return kd_font(tcp, arg, code == GIO_FONT);
821
822 case KDGKBMETA:
823 case KDSKBMETA:
824 return kd_kbmeta(tcp, arg, code == KDGKBMETA);
825
826 case PIO_UNIMAPCLR:
827 return kd_unimapclr(tcp, arg);
828
829 case GIO_CMAP:
830 case PIO_CMAP:
831 return kd_cmap(tcp, arg, code == GIO_CMAP);
832
833 /* no arguments */
834 case KDENABIO:
835 case KDDISABIO:
836 case KDMAPDISP:
837 case KDUNMAPDISP:
838 case PIO_FONTRESET:
839 return RVAL_IOCTL_DECODED;
840 }
841
842 /* GIO_UNIMAP, PIO_UNIMAP, GIO_FONTX, PIO_FONTX, KDFONTOP */
843 return kd_mpers_ioctl(tcp, code, arg);
844 }