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