1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Usage: kbd [-r] [-t] [-l] [-c on|off] [-a enable|disable|alternate]
28 * [-d keyboard device] [-D autorepeat dealy] [-R autorepeat
29 * rate]
30 * kbd [-i] [-d keyboard device]
31 * kbd -s [language]
32 * kbd -b [keyboard|console] frequency
33 * -r reset the keyboard as if power-up
34 * -t return the type of the keyboard being used
35 * -l return the layout of the keyboard being used,
36 * and the Autorepeat settings
37 * -i read in the default configuration file
38 * -c on|off turn on|off clicking
39 * -a enable|disable|alternate sets abort sequence
40 * -D autorepeat delay sets autorepeat dealy, unit in ms
41 * -R autorepeat rate sets autorepeat rate, unit in ms
42 * -d keyboard device chooses the kbd device, default /dev/kbd.
43 * -s keyboard layout sets keyboard layout
44 * -b [keyboard| console] frequency
45 * sets keyboard or console beeper frequency
46 */
47
48 #include <sys/types.h>
49 #include <sys/ioctl.h>
50 #include <sys/kbio.h>
51 #include <sys/kbd.h>
52 #include <stdio.h>
53 #include <fcntl.h>
54 #include <deflt.h>
55 #include <unistd.h>
56 #include <string.h>
57 #include <stdlib.h>
58 #include <stropts.h>
59 #include <libintl.h>
60 #include <locale.h>
61 #include <errno.h>
62 #include <inttypes.h>
63 #include <libscf.h>
64
65 #define KBD_DEVICE "/dev/kbd" /* default keyboard device */
66
67 #define KBD_LAYOUT_FILE "/usr/share/lib/keytables/type_6/kbd_layouts"
68 #define MAX_LAYOUT_NUM 128
69 #define MAX_LINE_SIZE 256
70 #define DEFAULT_KBD_LAYOUT 33
71
72 #define KBD_FMRI "svc:/system/keymap:default"
73 #define KBD_PG "keymap"
74 #define KBD_PROP_LAYOUT "layout"
75 #define KBD_PROP_KEYCLICK "keyclick"
76 #define KBD_PROP_KEYBOARD_ABORT "keyboard_abort"
77 #define KBD_PROP_RPTDELAY "repeat_delay"
78 #define KBD_PROP_RPTRATE "repeat_rate"
79 #define KBD_PROP_FREQ "kbd_beeper_freq"
80 #define KBD_PROP_CONSFREQ "console_beeper_freq"
81 #define KBD_MAX_NAME_LEN 1024
82
83 char *layout_names[MAX_LAYOUT_NUM];
84 int layout_numbers[MAX_LAYOUT_NUM];
85 static int layout_count;
86 static int default_layout_number = 0;
87
88 static void reset(int);
89 static int get_type(int);
90 static void get_layout(int);
91 static void kbd_defaults(int);
92 static void usage(void);
93
94 static int click(char *, int);
95 static int abort_enable(char *, int);
96 static int set_repeat_delay(char *, int);
97 static int set_rptdelay(int, int);
98 static int set_repeat_rate(char *, int);
99 static int set_rptrate(int, int);
100
101 static int get_layout_number(char *);
102 static int set_layout(int, int);
103 static int get_layouts(void);
104 static int set_kbd_layout(int, char *);
105 static int set_beep_freq(int, char *, int);
106
107 int
main(int argc,char ** argv)108 main(int argc, char **argv)
109 {
110 int c, error;
111 int rflag, tflag, lflag, cflag, dflag, aflag, iflag, errflag,
112 Dflag, Rflag, rtlacDRflag, sflag, bflag;
113 char *copt, *aopt, *delay, *rate, *layout_name, *b_type, *freq_str;
114 char *kbdname = KBD_DEVICE, *endptr = NULL;
115 int kbd, freq_val;
116 extern char *optarg;
117 extern int optind;
118
119 rflag = tflag = cflag = dflag = aflag = iflag = errflag = lflag =
120 Dflag = Rflag = sflag = bflag = 0;
121 copt = aopt = (char *)0;
122
123 (void) setlocale(LC_ALL, "");
124 #if !defined(TEXT_DOMAIN)
125 #define TEXT_DOMAIN "SYS_TEST"
126 #endif
127 (void) textdomain(TEXT_DOMAIN);
128
129 while ((c = getopt(argc, argv, "rtlisc:a:d:D:R:b:")) != EOF) {
130 switch (c) {
131 case 'r':
132 rflag++;
133 break;
134 case 't':
135 tflag++;
136 break;
137 case 'l':
138 lflag++;
139 break;
140 case 'i':
141 iflag++;
142 break;
143 case 's':
144 sflag++;
145 break;
146 case 'c':
147 copt = optarg;
148 cflag++;
149 break;
150 case 'a':
151 aopt = optarg;
152 aflag++;
153 break;
154 case 'd':
155 kbdname = optarg;
156 dflag++;
157 break;
158 case 'D':
159 delay = optarg;
160 Dflag++;
161 break;
162 case 'R':
163 rate = optarg;
164 Rflag++;
165 break;
166 case 'b':
167 bflag++;
168 break;
169 case '?':
170 errflag++;
171 break;
172 }
173 }
174
175 /*
176 * Check for valid arguments:
177 *
178 * If argument parsing failed or if there are left-over
179 * command line arguments(except -s and -b option),
180 * then we're done now.
181 */
182 if (errflag != 0 || (sflag == 0 && bflag == 0 && argc != optind)) {
183 usage();
184 exit(1);
185 }
186
187 /*
188 * kbd requires that the user specify either "-i" or "-s" or "-b" or
189 * at least one of -[rtlacDR]. The "-d" option is, well, optional.
190 * We don't care if it's there or not.
191 */
192 rtlacDRflag = rflag + tflag + lflag + aflag + cflag + Dflag + Rflag;
193 if (!((iflag != 0 && sflag == 0 && bflag == 0 && rtlacDRflag == 0) ||
194 (iflag == 0 && sflag != 0 && bflag == 0 && dflag == 0 &&
195 rtlacDRflag == 0) ||
196 (iflag == 0 && sflag == 0 && bflag == 0 && rtlacDRflag != 0) ||
197 (iflag == 0 && sflag == 0 && bflag != 0 && rtlacDRflag == 0))) {
198 usage();
199 exit(1);
200 }
201
202 if (Dflag && atoi(delay) <= 0) {
203 (void) fprintf(stderr, "Invalid arguments: -D %s\n", delay);
204 usage();
205 exit(1);
206 }
207
208 if (Rflag && atoi(rate) <= 0) {
209 (void) fprintf(stderr, "Invalid arguments: -R %s\n", rate);
210 usage();
211 exit(1);
212 }
213
214 /*
215 * Open the keyboard device
216 */
217 if ((kbd = open(kbdname, O_RDWR)) < 0) {
218 perror("opening the keyboard");
219 (void) fprintf(stderr, "kbd: Cannot open %s\n", kbdname);
220 exit(1);
221 }
222
223 if (iflag) {
224 kbd_defaults(kbd);
225 exit(0); /* A mutually exclusive option */
226 /*NOTREACHED*/
227 }
228
229 if (tflag)
230 (void) get_type(kbd);
231
232 if (lflag)
233 get_layout(kbd);
234
235 if (cflag && (error = click(copt, kbd)) != 0)
236 exit(error);
237
238 if (rflag)
239 reset(kbd);
240
241 if (aflag && (error = abort_enable(aopt, kbd)) != 0)
242 exit(error);
243
244 if (Dflag && (error = set_repeat_delay(delay, kbd)) != 0)
245 exit(error);
246
247 if (Rflag && (error = set_repeat_rate(rate, kbd)) != 0)
248 exit(error);
249
250 if (sflag) {
251 if (argc == optind) {
252 layout_name = NULL;
253 } else if (argc == (optind + 1)) {
254 layout_name = argv[optind];
255 } else {
256 usage();
257 exit(1);
258 }
259
260 if ((error = set_kbd_layout(kbd, layout_name)) != 0)
261 exit(error);
262 }
263
264 if (bflag) {
265 if (argc == optind) {
266 b_type = "keyboard";
267 } else if (argc == (optind + 1)) {
268 b_type = argv[argc - 2];
269 } else {
270 usage();
271 exit(1);
272 }
273
274 if (strcmp(b_type, "keyboard") && strcmp(b_type, "console")) {
275 usage();
276 exit(1);
277 }
278
279 freq_str = argv[argc - 1];
280 errno = 0;
281 freq_val = (int)strtol(freq_str, &endptr, 10);
282 if (errno != 0 || endptr[0] != '\0') {
283 usage();
284 exit(1);
285 }
286
287 if (freq_val < 0 || freq_val > INT16_MAX) {
288 (void) fprintf(stderr, "Invalid arguments: -b %s\n",
289 freq_str);
290 (void) fprintf(stderr, "Frequency range: [0 - %d]\n",
291 INT16_MAX);
292 exit(1);
293 }
294
295 if ((error = set_beep_freq(kbd, b_type, freq_val)) != 0)
296 exit(1);
297 }
298
299 return (0);
300 }
301
302 /*
303 * this routine gets the type of the keyboard being used
304 */
305 static int
set_kbd_layout(int kbd,char * layout_name)306 set_kbd_layout(int kbd, char *layout_name)
307 {
308 int layout_num;
309 int error = 1;
310
311 /* layout setting is possible only for USB type keyboards */
312 if (get_type(kbd) != KB_USB) {
313 (void) fprintf(stderr, "The -s option does not apply for this"
314 " keyboard type.\n"
315 "Only USB/PS2 type keyboards support this option.\n");
316 return (error);
317 }
318
319 /* get the language info from the layouts file */
320 if (get_layouts() != 0)
321 return (error);
322
323 if (layout_name != NULL) {
324 if ((layout_num = get_layout_number(layout_name)) == -1) {
325 (void) fprintf(stderr, "%s: unknown layout name\n"
326 "Please refer to 'kbd -s' to get the "
327 "supported layouts.\n", layout_name);
328 return (error);
329 }
330 } else {
331 int i, j, print_cnt, input_num;
332 boolean_t input_right = B_TRUE;
333 boolean_t default_input = B_FALSE;
334 char input[8]; /* 8 chars is enough for numbers */
335
336 print_cnt = (layout_count % 2) ?
337 layout_count/2+1 : layout_count/2;
338
339 for (i = 1; i <= print_cnt; i++) {
340 (void) printf("%2d. %-30s", i,
341 layout_names[i-1]);
342 j = i + print_cnt;
343 if (j <= layout_count) {
344 (void) printf("%-2d. %-30s\n", j,
345 layout_names[j-1]);
346 }
347 }
348 (void) printf(gettext("\nTo select the keyboard layout,"
349 " enter a number [default %d]:"),
350 default_layout_number+1);
351
352 for (;;) {
353 if (input_right == B_FALSE)
354 (void) printf(gettext("Invalid input. "
355 "Please input a number "
356 "(1,2,...):"));
357 (void) memset(input, 0, 8);
358 (void) fflush(stdin);
359 (void) fgets(input, 8, stdin);
360 if (strlen(input) > 4) {
361 input_right = B_FALSE;
362 continue;
363 }
364 if (input[0] == '\n') {
365 default_input = B_TRUE;
366 break;
367 }
368 input_right = B_TRUE;
369 /* check if the inputs are numbers 0~9 */
370 for (i = 0; i < (strlen(input) - 1); i++) {
371 if ((input[i] < '0') ||
372 (input[i] > '9')) {
373 input_right = B_FALSE;
374 break;
375 }
376 }
377 if (input_right == B_FALSE)
378 continue;
379 input_num = atoi(input);
380 if ((input_num > 0) &&
381 (input_num <= layout_count))
382 break;
383 else
384 input_right = B_FALSE;
385 }
386 if (default_input == B_TRUE)
387 layout_num = DEFAULT_KBD_LAYOUT;
388 else
389 layout_num = layout_numbers[--input_num];
390 }
391
392 if ((error = set_layout(kbd, layout_num)) != 0)
393 return (error);
394
395 return (0);
396 }
397
398 /*
399 * This routine sets keyboard or console beeper frequency
400 */
401 static int
set_beep_freq(int fd,char * type,int freq)402 set_beep_freq(int fd, char *type, int freq)
403 {
404 struct freq_request fr_struct;
405
406 if (strcmp(type, "keyboard") == 0)
407 fr_struct.type = KBD_BEEP;
408 else if (strcmp(type, "console") == 0)
409 fr_struct.type = CONSOLE_BEEP;
410 else
411 return (EINVAL);
412
413 fr_struct.freq = (int16_t)freq;
414
415 return (ioctl(fd, KIOCSETFREQ, &fr_struct));
416 }
417
418 /*
419 * this routine resets the state of the keyboard as if power-up
420 */
421 static void
reset(int kbd)422 reset(int kbd)
423 {
424 int cmd;
425
426 cmd = KBD_CMD_RESET;
427
428 if (ioctl(kbd, KIOCCMD, &cmd)) {
429 perror("kbd: ioctl error");
430 exit(1);
431 }
432
433 }
434
435 /*
436 * this routine gets the type of the keyboard being used
437 */
438 static int
get_type(int kbd)439 get_type(int kbd)
440 {
441 int kbd_type;
442
443 if (ioctl(kbd, KIOCTYPE, &kbd_type)) {
444 perror("ioctl (kbd type)");
445 exit(1);
446 }
447
448 switch (kbd_type) {
449
450 case KB_SUN3:
451 (void) printf("Type 3 Sun keyboard\n");
452 break;
453
454 case KB_SUN4:
455 (void) printf("Type 4 Sun keyboard\n");
456 break;
457
458 case KB_ASCII:
459 (void) printf("ASCII\n");
460 break;
461
462 case KB_PC:
463 (void) printf("PC\n");
464 break;
465
466 case KB_USB:
467 (void) printf("USB keyboard\n");
468 break;
469
470 default:
471 (void) printf("Unknown keyboard type\n");
472 break;
473 }
474 return (kbd_type);
475 }
476
477 /*
478 * this routine gets the layout of the keyboard being used
479 * also, included the autorepeat delay and rate being used
480 */
481 static void
get_layout(int kbd)482 get_layout(int kbd)
483 {
484 int kbd_type;
485 int kbd_layout;
486 /* these two variables are used for getting delay&rate */
487 int delay, rate;
488 delay = rate = 0;
489
490 if (ioctl(kbd, KIOCTYPE, &kbd_type)) {
491 perror("ioctl (kbd type)");
492 exit(1);
493 }
494
495 if (ioctl(kbd, KIOCLAYOUT, &kbd_layout)) {
496 perror("ioctl (kbd layout)");
497 exit(1);
498 }
499
500 (void) printf("type=%d\nlayout=%d (0x%.2x)\n",
501 kbd_type, kbd_layout, kbd_layout);
502
503 /* below code is used to get the autorepeat delay and rate */
504 if (ioctl(kbd, KIOCGRPTDELAY, &delay)) {
505 perror("ioctl (kbd get repeat delay)");
506 exit(1);
507 }
508
509 if (ioctl(kbd, KIOCGRPTRATE, &rate)) {
510 perror("ioctl (kbd get repeat rate)");
511 exit(1);
512 }
513
514 (void) printf("delay(ms)=%d\n", delay);
515 (void) printf("rate(ms)=%d\n", rate);
516 }
517
518 /*
519 * this routine enables or disables clicking of the keyboard
520 */
521 static int
click(char * copt,int kbd)522 click(char *copt, int kbd)
523 {
524 int cmd;
525
526 if (strcmp(copt, "on") == 0)
527 cmd = KBD_CMD_CLICK;
528 else if (strcmp(copt, "off") == 0)
529 cmd = KBD_CMD_NOCLICK;
530 else {
531 (void) fprintf(stderr, "wrong option -- %s\n", copt);
532 usage();
533 return (1);
534 }
535
536 if (ioctl(kbd, KIOCCMD, &cmd)) {
537 perror("kbd ioctl (keyclick)");
538 return (1);
539 }
540 return (0);
541 }
542
543 /*
544 * this routine enables/disables/sets BRK or abort sequence feature
545 */
546 static int
abort_enable(char * aopt,int kbd)547 abort_enable(char *aopt, int kbd)
548 {
549 int enable;
550
551 if (strcmp(aopt, "alternate") == 0)
552 enable = KIOCABORTALTERNATE;
553 else if (strcmp(aopt, "enable") == 0)
554 enable = KIOCABORTENABLE;
555 else if (strcmp(aopt, "disable") == 0)
556 enable = KIOCABORTDISABLE;
557 else {
558 (void) fprintf(stderr, "wrong option -- %s\n", aopt);
559 usage();
560 return (1);
561 }
562
563 if (ioctl(kbd, KIOCSKABORTEN, &enable)) {
564 perror("kbd ioctl (abort enable)");
565 return (1);
566 }
567 return (0);
568 }
569
570 static int
set_rptdelay(int delay,int kbd)571 set_rptdelay(int delay, int kbd)
572 {
573 /*
574 * The error message depends on the different inputs.
575 * a. the input is a invalid integer(unit in ms)
576 * b. the input is a integer less than the minimal delay setting.
577 * The condition (a) has been covered by main function and kbd_defaults
578 * function.
579 */
580 if (ioctl(kbd, KIOCSRPTDELAY, &delay) == -1) {
581 if (delay < KIOCRPTDELAY_MIN)
582 (void) fprintf(stderr, "kbd: specified delay %d is "
583 "less than minimum %d\n", delay, KIOCRPTDELAY_MIN);
584 else
585 perror("kbd: set repeat delay");
586 return (1);
587 }
588
589 return (0);
590 }
591
592 /*
593 * this routine set autorepeat delay
594 */
595 static int
set_repeat_delay(char * delay_str,int kbd)596 set_repeat_delay(char *delay_str, int kbd)
597 {
598 int delay = atoi(delay_str);
599
600 return (set_rptdelay(delay, kbd));
601 }
602
603 static int
set_rptrate(int rate,int kbd)604 set_rptrate(int rate, int kbd)
605 {
606 /*
607 * The input validation check has been covered by main function
608 * and kbd_defaults function.Here just give an error message if
609 * the ioctl fails.
610 */
611 if (ioctl(kbd, KIOCSRPTRATE, &rate) == -1) {
612 perror("kbd: set repeat rate");
613 return (1);
614 }
615 return (0);
616 }
617
618 /*
619 * this routine set autorepeat rate
620 */
621 static int
set_repeat_rate(char * rate_str,int kbd)622 set_repeat_rate(char *rate_str, int kbd)
623 {
624 int rate = atoi(rate_str);
625
626 return (set_rptrate(rate, kbd));
627 }
628
629 #define BAD_DEFAULT_STR "kbd: bad default value for %s: %s\n"
630 #define BAD_DEFAULT_INT "kbd: bad default value for %s: %d\n"
631 #define BAD_DEFAULT_LLINT "kbd: bad default value for %s: %lld\n"
632
633 static void
kbd_defaults(int kbd)634 kbd_defaults(int kbd)
635 {
636 scf_handle_t *h = NULL;
637 scf_snapshot_t *snap = NULL;
638 scf_instance_t *inst = NULL;
639 scf_propertygroup_t *pg = NULL;
640 scf_property_t *prop = NULL;
641 scf_value_t *val = NULL;
642
643 int layout_num;
644 char *val_layout = NULL, *val_abort = NULL;
645 uint8_t val_click;
646 int64_t val_delay, val_rate;
647 int64_t val_kbd_beeper, val_console_beeper;
648
649 if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
650 scf_handle_bind(h) != 0 ||
651 (inst = scf_instance_create(h)) == NULL ||
652 (snap = scf_snapshot_create(h)) == NULL ||
653 (pg = scf_pg_create(h)) == NULL ||
654 (prop = scf_property_create(h)) == NULL ||
655 (val = scf_value_create(h)) == NULL) {
656 goto out;
657 }
658
659 if (scf_handle_decode_fmri(h, KBD_FMRI, NULL, NULL, inst,
660 NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
661 goto out;
662 }
663
664 if (scf_instance_get_snapshot(inst, "running", snap) != 0) {
665 scf_snapshot_destroy(snap);
666 snap = NULL;
667 }
668
669 if (scf_instance_get_pg_composed(inst, snap, KBD_PG, pg) != 0) {
670 goto out;
671 }
672
673 if ((val_abort = malloc(KBD_MAX_NAME_LEN)) == NULL) {
674 (void) fprintf(stderr,
675 "Can not alloc memory for keyboard properties\n");
676 goto out;
677 }
678
679 if ((val_layout = malloc(KBD_MAX_NAME_LEN)) == NULL) {
680 (void) fprintf(stderr,
681 "Can not alloc memory for keyboard properties\n");
682 goto out;
683 }
684
685 if (scf_pg_get_property(pg, KBD_PROP_KEYCLICK, prop) != 0 ||
686 scf_property_get_value(prop, val) != 0 ||
687 scf_value_get_boolean(val, &val_click) == -1) {
688 (void) fprintf(stderr, "Can not get KEYCLICK\n");
689 }
690
691 if (val_click == 1)
692 (void) click("on", kbd);
693 else if (val_click == 0)
694 (void) click("off", kbd);
695 else
696 (void) fprintf(stderr,
697 BAD_DEFAULT_INT, KBD_PROP_KEYCLICK, val_click);
698
699 if (scf_pg_get_property(pg, KBD_PROP_KEYBOARD_ABORT, prop) != 0 ||
700 scf_property_get_value(prop, val) != 0 ||
701 scf_value_get_astring(val, val_abort, KBD_MAX_NAME_LEN) == -1) {
702 (void) fprintf(stderr, "Can not get KEYBOARD_ABORT\n");
703 }
704
705 if (*val_abort != '\0') {
706 /*
707 * ABORT must equal "enable", "disable" or "alternate"
708 */
709 if ((strcmp(val_abort, "enable") == 0) ||
710 (strcmp(val_abort, "alternate") == 0) ||
711 (strcmp(val_abort, "disable") == 0))
712 (void) abort_enable(val_abort, kbd);
713 else
714 (void) fprintf(stderr, BAD_DEFAULT_STR,
715 KBD_PROP_KEYBOARD_ABORT, val_abort);
716 }
717
718 if (scf_pg_get_property(pg, KBD_PROP_RPTDELAY, prop) != 0 ||
719 scf_property_get_value(prop, val) != 0 ||
720 scf_value_get_integer(val, &val_delay) == -1) {
721 (void) fprintf(stderr, "Can not get RPTDELAY\n");
722 }
723
724 if (val_delay > 0)
725 (void) set_rptdelay(val_delay, kbd);
726 else
727 (void) fprintf(stderr,
728 BAD_DEFAULT_LLINT, KBD_PROP_RPTDELAY, val_delay);
729
730 if (scf_pg_get_property(pg, KBD_PROP_RPTRATE, prop) != 0 ||
731 scf_property_get_value(prop, val) != 0 ||
732 scf_value_get_integer(val, &val_rate) == -1) {
733 (void) fprintf(stderr, "Can not get RPTRATE\n");
734 }
735
736 if (val_rate > 0)
737 (void) set_rptrate(val_rate, kbd);
738 else
739 (void) fprintf(stderr,
740 BAD_DEFAULT_LLINT, KBD_PROP_RPTRATE, val_rate);
741
742 if (scf_pg_get_property(pg, KBD_PROP_LAYOUT, prop) != 0 ||
743 scf_property_get_value(prop, val) != 0 ||
744 scf_value_get_astring(val, val_layout, KBD_MAX_NAME_LEN) == -1) {
745 (void) fprintf(stderr, "Can not get LAYOUT\n");
746 }
747
748 if (*val_layout != '\0') {
749 /*
750 * LAYOUT must be one of the layouts supported in kbd_layouts
751 */
752 if (get_layouts() != 0)
753 goto out;
754
755 if ((layout_num = get_layout_number(val_layout)) == -1) {
756 (void) fprintf(stderr,
757 BAD_DEFAULT_STR, KBD_PROP_LAYOUT, val_layout);
758 goto out;
759 }
760
761 (void) set_layout(kbd, layout_num);
762 }
763
764 if (scf_pg_get_property(pg, KBD_PROP_FREQ, prop) != 0 ||
765 scf_property_get_value(prop, val) != 0 ||
766 scf_value_get_integer(val, &val_kbd_beeper) == -1) {
767 (void) fprintf(stderr, "Can not get FREQ\n");
768 }
769
770 if (val_kbd_beeper >= 0 && val_kbd_beeper <= INT16_MAX)
771 (void) set_beep_freq(kbd, "keyboard", val_kbd_beeper);
772 else
773 (void) fprintf(stderr,
774 BAD_DEFAULT_LLINT, KBD_PROP_FREQ, val_kbd_beeper);
775
776 if (scf_pg_get_property(pg, KBD_PROP_CONSFREQ, prop) != 0 ||
777 scf_property_get_value(prop, val) != 0 ||
778 scf_value_get_integer(val, &val_console_beeper) == -1) {
779 (void) fprintf(stderr, "Can not get CONSFREQ\n");
780 }
781
782 if (val_console_beeper >= 0 && val_console_beeper <= INT16_MAX)
783 (void) set_beep_freq(kbd, "console", val_console_beeper);
784 else
785 (void) fprintf(stderr,
786 BAD_DEFAULT_LLINT, KBD_PROP_CONSFREQ, val_console_beeper);
787
788 out:
789 if (val_layout != NULL)
790 free(val_layout);
791 if (val_abort != NULL)
792 free(val_abort);
793 if (snap != NULL)
794 scf_snapshot_destroy(snap);
795 scf_value_destroy(val);
796 scf_property_destroy(prop);
797 scf_pg_destroy(pg);
798 scf_instance_destroy(inst);
799 scf_handle_destroy(h);
800 }
801
802 static int
get_layout_number(char * layout)803 get_layout_number(char *layout)
804 {
805 int i;
806 int layout_number = -1;
807
808 for (i = 0; i < layout_count; i ++) {
809 if (strcmp(layout, layout_names[i]) == 0) {
810 layout_number = layout_numbers[i];
811 break;
812 }
813 }
814
815 return (layout_number);
816 }
817
818 static int
get_layouts()819 get_layouts()
820 {
821 FILE *stream;
822 char buffer[MAX_LINE_SIZE];
823 char *result = NULL;
824 int i = 0;
825 char *tmpbuf;
826
827 if ((stream = fopen(KBD_LAYOUT_FILE, "r")) == 0) {
828 perror(KBD_LAYOUT_FILE);
829 return (1);
830 }
831
832 while ((fgets(buffer, MAX_LINE_SIZE, stream) != NULL) &&
833 (i < MAX_LAYOUT_NUM)) {
834 if (buffer[0] == '#')
835 continue;
836 if ((result = strtok(buffer, "=")) == NULL)
837 continue;
838 if ((tmpbuf = strdup(result)) != NULL) {
839 layout_names[i] = tmpbuf;
840 } else {
841 perror("out of memory getting layout names");
842 return (1);
843 }
844 if ((result = strtok(NULL, "\n")) == NULL)
845 continue;
846 layout_numbers[i] = atoi(result);
847 if (strcmp(tmpbuf, "US-English") == 0)
848 default_layout_number = i;
849 i++;
850 }
851 layout_count = i;
852
853 return (0);
854 }
855
856 /*
857 * this routine sets the layout of the keyboard being used
858 */
859 static int
set_layout(int kbd,int layout_num)860 set_layout(int kbd, int layout_num)
861 {
862
863 if (ioctl(kbd, KIOCSLAYOUT, layout_num)) {
864 perror("ioctl (set kbd layout)");
865 return (1);
866 }
867
868 return (0);
869 }
870
871 static char *usage1 = "kbd [-r] [-t] [-l] [-a enable|disable|alternate]";
872 static char *usage2 = " [-c on|off][-D delay][-R rate][-d keyboard device]";
873 static char *usage3 = "kbd -i [-d keyboard device]";
874 static char *usage4 = "kbd -s [language]";
875 static char *usage5 = "kbd -b [keyboard|console] frequency";
876
877 static void
usage(void)878 usage(void)
879 {
880 (void) fprintf(stderr, "Usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", usage1,
881 usage2, usage3, usage4, usage5);
882 }
883