xref: /titanic_54/usr/src/cmd/kbd/kbd.c (revision 8ffc942d5d69695c8690274a7a3649bf0a80d3fb)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5d8c870b0Sqz150045  * Common Development and Distribution License (the "License").
6d8c870b0Sqz150045  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22d8c870b0Sqz150045  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
30*8ffc942dSrz201010  *	Usage: kbd [-r] [-t] [-l] [-c on|off] [-a enable|disable|alternate]
31*8ffc942dSrz201010  *		   [-d keyboard device] [-D autorepeat dealy] [-R autorepeat
32*8ffc942dSrz201010  *		   rate]
33*8ffc942dSrz201010  *	       kbd [-i] [-d keyboard device]
34*8ffc942dSrz201010  *	       kbd -s [language]
35*8ffc942dSrz201010  *	       kbd -b [keyboard|console] frequency
367c478bd9Sstevel@tonic-gate  *	-r			reset the keyboard as if power-up
377c478bd9Sstevel@tonic-gate  *	-t			return the type of the keyboard being used
387c478bd9Sstevel@tonic-gate  *	-l			return the layout of the keyboard being used,
397c478bd9Sstevel@tonic-gate  *				and the Autorepeat settings
407c478bd9Sstevel@tonic-gate  *	-i			read in the default configuration file
417c478bd9Sstevel@tonic-gate  *	-c on|off		turn on|off clicking
427c478bd9Sstevel@tonic-gate  *	-a enable|disable|alternate	sets abort sequence
437c478bd9Sstevel@tonic-gate  *	-D autorepeat delay	sets autorepeat dealy, unit in ms
447c478bd9Sstevel@tonic-gate  *	-R autorepeat rate	sets autorepeat rate, unit in ms
457c478bd9Sstevel@tonic-gate  *	-d keyboard device	chooses the kbd device, default /dev/kbd.
467db6e34eSqz150045  *	-s keyboard layout	sets keyboard layout
47*8ffc942dSrz201010  *	-b [keyboard| console]	frequency
48*8ffc942dSrz201010  *				sets keyboard or console beeper frequency
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #include <sys/types.h>
527c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
537c478bd9Sstevel@tonic-gate #include <sys/kbio.h>
547c478bd9Sstevel@tonic-gate #include <sys/kbd.h>
557c478bd9Sstevel@tonic-gate #include <stdio.h>
567c478bd9Sstevel@tonic-gate #include <fcntl.h>
577c478bd9Sstevel@tonic-gate #include <deflt.h>
587c478bd9Sstevel@tonic-gate #include <unistd.h>
597c478bd9Sstevel@tonic-gate #include <string.h>
607c478bd9Sstevel@tonic-gate #include <stdlib.h>
617c478bd9Sstevel@tonic-gate #include <stropts.h>
62d8c870b0Sqz150045 #include <libintl.h>
63d8c870b0Sqz150045 #include <locale.h>
64*8ffc942dSrz201010 #include <errno.h>
65*8ffc942dSrz201010 #include <inttypes.h>
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #define	KBD_DEVICE	"/dev/kbd"		/* default keyboard device */
687c478bd9Sstevel@tonic-gate #define	DEF_FILE	"/etc/default/kbd"	/* kbd defaults file	*/
697c478bd9Sstevel@tonic-gate #define	DEF_ABORT	"KEYBOARD_ABORT="
707c478bd9Sstevel@tonic-gate #define	DEF_CLICK	"KEYCLICK="
717c478bd9Sstevel@tonic-gate #define	DEF_RPTDELAY	"REPEAT_DELAY="
727c478bd9Sstevel@tonic-gate #define	DEF_RPTRATE	"REPEAT_RATE="
737db6e34eSqz150045 #define	DEF_LAYOUT	"LAYOUT="
74*8ffc942dSrz201010 #define	DEF_KBDFREQ	"KBD_BEEPER_FREQ="
75*8ffc942dSrz201010 #define	DEF_CONSFREQ	"CONSOLE_BEEPER_FREQ="
767db6e34eSqz150045 
777db6e34eSqz150045 #define	KBD_LAYOUT_FILE  "/usr/share/lib/keytables/type_6/kbd_layouts"
787db6e34eSqz150045 #define	MAX_LAYOUT_NUM		128
797db6e34eSqz150045 #define	MAX_LINE_SIZE		256
807db6e34eSqz150045 #define	DEFAULT_KBD_LAYOUT	33
817db6e34eSqz150045 
82*8ffc942dSrz201010 int errno;
837db6e34eSqz150045 char *layout_names[MAX_LAYOUT_NUM];
847db6e34eSqz150045 int layout_numbers[MAX_LAYOUT_NUM];
857db6e34eSqz150045 static int layout_count;
867db6e34eSqz150045 static int default_layout_number = 0;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static void reset(int);
897c478bd9Sstevel@tonic-gate static void get_type(int);
907c478bd9Sstevel@tonic-gate static void get_layout(int);
917c478bd9Sstevel@tonic-gate static void kbd_defaults(int);
927c478bd9Sstevel@tonic-gate static void usage(void);
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate static int click(char *, int);
957c478bd9Sstevel@tonic-gate static int abort_enable(char *, int);
967c478bd9Sstevel@tonic-gate static int set_repeat_delay(char *, int);
977c478bd9Sstevel@tonic-gate static int set_repeat_rate(char *, int);
987c478bd9Sstevel@tonic-gate 
997db6e34eSqz150045 static int get_layout_number(char *);
1007db6e34eSqz150045 static int set_layout(int, int);
1017db6e34eSqz150045 static int get_layouts(void);
1027db6e34eSqz150045 static int set_kbd_layout(int, char *);
103*8ffc942dSrz201010 static int set_beep_freq(int, char *, int);
1047db6e34eSqz150045 
1057c478bd9Sstevel@tonic-gate int
1067c478bd9Sstevel@tonic-gate main(int argc, char **argv)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	int c, error;
1097c478bd9Sstevel@tonic-gate 	int rflag, tflag, lflag, cflag, dflag, aflag, iflag, errflag,
110*8ffc942dSrz201010 	    Dflag, Rflag, rtlacDRflag, sflag, bflag;
111*8ffc942dSrz201010 	char *copt, *aopt, *delay, *rate, *layout_name, *b_type, *freq_str;
112*8ffc942dSrz201010 	char *kbdname = KBD_DEVICE, *endptr = NULL;
113*8ffc942dSrz201010 	int kbd, freq_val;
1147c478bd9Sstevel@tonic-gate 	extern char *optarg;
1157c478bd9Sstevel@tonic-gate 	extern int optind;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	rflag = tflag = cflag = dflag = aflag = iflag = errflag = lflag =
118*8ffc942dSrz201010 	    Dflag = Rflag = sflag = bflag = 0;
1197c478bd9Sstevel@tonic-gate 	copt = aopt = (char *)0;
1207c478bd9Sstevel@tonic-gate 
121d8c870b0Sqz150045 	(void) setlocale(LC_ALL, "");
122d8c870b0Sqz150045 #if !defined(TEXT_DOMAIN)
123d8c870b0Sqz150045 #define	TEXT_DOMAIN	"SYS_TEST"
124d8c870b0Sqz150045 #endif
125d8c870b0Sqz150045 	(void) textdomain(TEXT_DOMAIN);
126d8c870b0Sqz150045 
127*8ffc942dSrz201010 	while ((c = getopt(argc, argv, "rtlisc:a:d:D:R:b:")) != EOF) {
1287c478bd9Sstevel@tonic-gate 		switch (c) {
1297c478bd9Sstevel@tonic-gate 		case 'r':
1307c478bd9Sstevel@tonic-gate 			rflag++;
1317c478bd9Sstevel@tonic-gate 			break;
1327c478bd9Sstevel@tonic-gate 		case 't':
1337c478bd9Sstevel@tonic-gate 			tflag++;
1347c478bd9Sstevel@tonic-gate 			break;
1357c478bd9Sstevel@tonic-gate 		case 'l':
1367c478bd9Sstevel@tonic-gate 			lflag++;
1377c478bd9Sstevel@tonic-gate 			break;
1387c478bd9Sstevel@tonic-gate 		case 'i':
1397c478bd9Sstevel@tonic-gate 			iflag++;
1407c478bd9Sstevel@tonic-gate 			break;
1417db6e34eSqz150045 		case 's':
1427db6e34eSqz150045 			sflag++;
1437db6e34eSqz150045 			break;
1447c478bd9Sstevel@tonic-gate 		case 'c':
1457c478bd9Sstevel@tonic-gate 			copt = optarg;
1467c478bd9Sstevel@tonic-gate 			cflag++;
1477c478bd9Sstevel@tonic-gate 			break;
1487c478bd9Sstevel@tonic-gate 		case 'a':
1497c478bd9Sstevel@tonic-gate 			aopt = optarg;
1507c478bd9Sstevel@tonic-gate 			aflag++;
1517c478bd9Sstevel@tonic-gate 			break;
1527c478bd9Sstevel@tonic-gate 		case 'd':
1537c478bd9Sstevel@tonic-gate 			kbdname = optarg;
1547c478bd9Sstevel@tonic-gate 			dflag++;
1557c478bd9Sstevel@tonic-gate 			break;
1567c478bd9Sstevel@tonic-gate 		case 'D':
1577c478bd9Sstevel@tonic-gate 			delay = optarg;
1587c478bd9Sstevel@tonic-gate 			Dflag++;
1597c478bd9Sstevel@tonic-gate 			break;
1607c478bd9Sstevel@tonic-gate 		case 'R':
1617c478bd9Sstevel@tonic-gate 			rate = optarg;
1627c478bd9Sstevel@tonic-gate 			Rflag++;
1637c478bd9Sstevel@tonic-gate 			break;
164*8ffc942dSrz201010 		case 'b':
165*8ffc942dSrz201010 			bflag++;
166*8ffc942dSrz201010 			break;
1677c478bd9Sstevel@tonic-gate 		case '?':
1687c478bd9Sstevel@tonic-gate 			errflag++;
1697c478bd9Sstevel@tonic-gate 			break;
1707c478bd9Sstevel@tonic-gate 		}
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	/*
1747c478bd9Sstevel@tonic-gate 	 * Check for valid arguments:
1757c478bd9Sstevel@tonic-gate 	 *
1767c478bd9Sstevel@tonic-gate 	 * If argument parsing failed or if there are left-over
177*8ffc942dSrz201010 	 * command line arguments(except -s and -b option),
178*8ffc942dSrz201010 	 * then we're done now.
1797c478bd9Sstevel@tonic-gate 	 */
180*8ffc942dSrz201010 	if (errflag != 0 || (sflag == 0 && bflag == 0 && argc != optind)) {
1817c478bd9Sstevel@tonic-gate 		usage();
1827c478bd9Sstevel@tonic-gate 		exit(1);
1837c478bd9Sstevel@tonic-gate 	}
1847db6e34eSqz150045 
1857c478bd9Sstevel@tonic-gate 	/*
186*8ffc942dSrz201010 	 * kbd requires that the user specify either "-i" or "-s" or "-b" or
187*8ffc942dSrz201010 	 * at least one of -[rtlacDR].  The "-d" option is, well, optional.
1887db6e34eSqz150045 	 * We don't care if it's there or not.
1897c478bd9Sstevel@tonic-gate 	 */
1907c478bd9Sstevel@tonic-gate 	rtlacDRflag = rflag + tflag + lflag + aflag + cflag + Dflag + Rflag;
191*8ffc942dSrz201010 	if (!((iflag != 0 && sflag == 0 && bflag == 0 && rtlacDRflag == 0) ||
192*8ffc942dSrz201010 	    (iflag == 0 && sflag != 0 && bflag == 0 && dflag == 0 &&
193*8ffc942dSrz201010 	    rtlacDRflag == 0) ||
194*8ffc942dSrz201010 	    (iflag == 0 && sflag == 0 && bflag == 0 && rtlacDRflag != 0) ||
195*8ffc942dSrz201010 	    (iflag == 0 && sflag == 0 && bflag != 0 && rtlacDRflag == 0))) {
1967c478bd9Sstevel@tonic-gate 		usage();
1977c478bd9Sstevel@tonic-gate 		exit(1);
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	if (Dflag && atoi(delay) <= 0) {
2017c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Invalid arguments: -D %s\n", delay);
2027c478bd9Sstevel@tonic-gate 		usage();
2037c478bd9Sstevel@tonic-gate 		exit(1);
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	if (Rflag && atoi(rate) <= 0) {
2077c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Invalid arguments: -R %s\n", rate);
2087c478bd9Sstevel@tonic-gate 		usage();
2097c478bd9Sstevel@tonic-gate 		exit(1);
2107c478bd9Sstevel@tonic-gate 	}
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	/*
2137c478bd9Sstevel@tonic-gate 	 * Open the keyboard device
2147c478bd9Sstevel@tonic-gate 	 */
2157c478bd9Sstevel@tonic-gate 	if ((kbd = open(kbdname, O_RDWR)) < 0) {
2167c478bd9Sstevel@tonic-gate 		perror("opening the keyboard");
2177c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "kbd: Cannot open %s\n", kbdname);
2187c478bd9Sstevel@tonic-gate 		exit(1);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	if (iflag) {
2227c478bd9Sstevel@tonic-gate 		kbd_defaults(kbd);
2237c478bd9Sstevel@tonic-gate 		exit(0);	/* A mutually exclusive option */
2247c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	if (tflag)
2287c478bd9Sstevel@tonic-gate 		get_type(kbd);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (lflag)
2317c478bd9Sstevel@tonic-gate 		get_layout(kbd);
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (cflag && (error = click(copt, kbd)) != 0)
2347c478bd9Sstevel@tonic-gate 		exit(error);
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	if (rflag)
2377c478bd9Sstevel@tonic-gate 		reset(kbd);
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	if (aflag && (error = abort_enable(aopt, kbd)) != 0)
2407c478bd9Sstevel@tonic-gate 		exit(error);
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	if (Dflag && (error = set_repeat_delay(delay, kbd)) != 0)
2437c478bd9Sstevel@tonic-gate 		exit(error);
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if (Rflag && (error = set_repeat_rate(rate, kbd)) != 0)
2467c478bd9Sstevel@tonic-gate 		exit(error);
2477c478bd9Sstevel@tonic-gate 
2487db6e34eSqz150045 	if (sflag) {
2497db6e34eSqz150045 		if (argc == optind) {
2507db6e34eSqz150045 			layout_name = NULL;
2517db6e34eSqz150045 		} else if (argc == (optind + 1)) {
2527db6e34eSqz150045 			layout_name = argv[optind];
2537db6e34eSqz150045 		} else {
2547db6e34eSqz150045 			usage();
2557db6e34eSqz150045 			exit(1);
2567db6e34eSqz150045 		}
2577db6e34eSqz150045 
2587db6e34eSqz150045 		if ((error = set_kbd_layout(kbd, layout_name)) != 0)
2597db6e34eSqz150045 			exit(error);
2607db6e34eSqz150045 	}
2617db6e34eSqz150045 
262*8ffc942dSrz201010 	if (bflag) {
263*8ffc942dSrz201010 		if (argc == optind) {
264*8ffc942dSrz201010 			b_type = "keyboard";
265*8ffc942dSrz201010 		} else if (argc == (optind + 1)) {
266*8ffc942dSrz201010 			b_type = argv[argc - 2];
267*8ffc942dSrz201010 		} else {
268*8ffc942dSrz201010 			usage();
269*8ffc942dSrz201010 			exit(1);
270*8ffc942dSrz201010 		}
271*8ffc942dSrz201010 
272*8ffc942dSrz201010 		if (strcmp(b_type, "keyboard") && strcmp(b_type, "console")) {
273*8ffc942dSrz201010 			usage();
274*8ffc942dSrz201010 			exit(1);
275*8ffc942dSrz201010 		}
276*8ffc942dSrz201010 
277*8ffc942dSrz201010 		freq_str = argv[argc - 1];
278*8ffc942dSrz201010 		errno = 0;
279*8ffc942dSrz201010 		freq_val = (int)strtol(freq_str, &endptr, 10);
280*8ffc942dSrz201010 		if (errno != 0 || endptr[0] != '\0') {
281*8ffc942dSrz201010 			usage();
282*8ffc942dSrz201010 			exit(1);
283*8ffc942dSrz201010 		}
284*8ffc942dSrz201010 
285*8ffc942dSrz201010 		if (freq_val < 0 || freq_val > INT16_MAX) {
286*8ffc942dSrz201010 			(void) fprintf(stderr, "Invalid arguments: -b %s\n",
287*8ffc942dSrz201010 			    freq_str);
288*8ffc942dSrz201010 			(void) fprintf(stderr, "Frequency range: [0 - %d]\n",
289*8ffc942dSrz201010 			    INT16_MAX);
290*8ffc942dSrz201010 			exit(1);
291*8ffc942dSrz201010 		}
292*8ffc942dSrz201010 
293*8ffc942dSrz201010 		if ((error = set_beep_freq(kbd, b_type, freq_val)) != 0)
294*8ffc942dSrz201010 			exit(1);
295*8ffc942dSrz201010 	}
296*8ffc942dSrz201010 
2977db6e34eSqz150045 	return (0);
2987db6e34eSqz150045 }
2997db6e34eSqz150045 
3007db6e34eSqz150045 /*
3017db6e34eSqz150045  * this routine gets the type of the keyboard being used
3027db6e34eSqz150045  */
3037db6e34eSqz150045 static int
3047db6e34eSqz150045 set_kbd_layout(int kbd, char *layout_name)
3057db6e34eSqz150045 {
3067db6e34eSqz150045 	int layout_num;
3077db6e34eSqz150045 	int error = 1;
3087db6e34eSqz150045 
3097db6e34eSqz150045 	/* get the language info from the layouts file */
3107db6e34eSqz150045 	if (get_layouts() != 0)
3117db6e34eSqz150045 		return (error);
3127db6e34eSqz150045 
3137db6e34eSqz150045 	if (layout_name != NULL) {
3147db6e34eSqz150045 		if ((layout_num = get_layout_number(layout_name)) == -1) {
3157db6e34eSqz150045 			(void) fprintf(stderr, "%s: unknown layout name\n"
3167db6e34eSqz150045 				    "Please refer to 'kbd -s' to get the "
3177db6e34eSqz150045 				    "supported layouts.\n", layout_name);
3187db6e34eSqz150045 			return (error);
3197db6e34eSqz150045 		}
3207db6e34eSqz150045 	} else {
3217db6e34eSqz150045 			int i, j, print_cnt, input_num;
3227db6e34eSqz150045 			boolean_t input_right = B_TRUE;
3237db6e34eSqz150045 			boolean_t default_input = B_FALSE;
3247db6e34eSqz150045 			char input[8]; /* 8 chars is enough for numbers */
3257db6e34eSqz150045 
3267db6e34eSqz150045 			print_cnt = (layout_count % 2) ?
3277db6e34eSqz150045 				layout_count/2+1 : layout_count/2;
3287db6e34eSqz150045 
3297db6e34eSqz150045 			for (i = 1; i <= print_cnt; i++) {
3307db6e34eSqz150045 				(void) printf("%2d. %-30s", i,
3317db6e34eSqz150045 					    layout_names[i-1]);
3327db6e34eSqz150045 				j = i + print_cnt;
3337db6e34eSqz150045 				if (j <= layout_count) {
3347db6e34eSqz150045 					(void) printf("%-2d. %-30s\n", j,
3357db6e34eSqz150045 						    layout_names[j-1]);
3367db6e34eSqz150045 				}
3377db6e34eSqz150045 			}
338d8c870b0Sqz150045 			(void) printf(gettext("\nTo select the keyboard layout,"
339d8c870b0Sqz150045 				    " enter a number [default %d]:"),
3407db6e34eSqz150045 				    default_layout_number+1);
3417db6e34eSqz150045 
3427db6e34eSqz150045 			for (;;) {
3437db6e34eSqz150045 				if (input_right == B_FALSE)
344d8c870b0Sqz150045 					(void) printf(gettext("Invalid input. "
345d8c870b0Sqz150045 					    "Please input a number "
346d8c870b0Sqz150045 					    "(1,2,...):"));
3477db6e34eSqz150045 				(void) memset(input, 0, 8);
3487db6e34eSqz150045 				(void) fflush(stdin);
3497db6e34eSqz150045 				(void) fgets(input, 8, stdin);
3507db6e34eSqz150045 				if (strlen(input) > 4) {
3517db6e34eSqz150045 					input_right = B_FALSE;
3527db6e34eSqz150045 					continue;
3537db6e34eSqz150045 				}
3547db6e34eSqz150045 				if (input[0] == '\n') {
3557db6e34eSqz150045 					default_input = B_TRUE;
3567db6e34eSqz150045 					break;
3577db6e34eSqz150045 				}
3587db6e34eSqz150045 				input_right = B_TRUE;
3597db6e34eSqz150045 				/* check if the inputs are numbers 0~9 */
3607db6e34eSqz150045 				for (i = 0; i < (strlen(input) - 1); i++) {
3617db6e34eSqz150045 					if ((input[i] < '0') ||
3627db6e34eSqz150045 					    (input[i] > '9')) {
3637db6e34eSqz150045 						input_right = B_FALSE;
3647db6e34eSqz150045 						break;
3657db6e34eSqz150045 					}
3667db6e34eSqz150045 				}
3677db6e34eSqz150045 				if (input_right == B_FALSE)
3687db6e34eSqz150045 					continue;
3697db6e34eSqz150045 				input_num = atoi(input);
3707db6e34eSqz150045 				if ((input_num > 0) &&
3717db6e34eSqz150045 				    (input_num <= layout_count))
3727db6e34eSqz150045 					break;
3737db6e34eSqz150045 				else
3747db6e34eSqz150045 					input_right = B_FALSE;
3757db6e34eSqz150045 			}
3767db6e34eSqz150045 			if (default_input == B_TRUE)
3777db6e34eSqz150045 				layout_num = DEFAULT_KBD_LAYOUT;
3787db6e34eSqz150045 			else
3797db6e34eSqz150045 				layout_num = layout_numbers[--input_num];
3807db6e34eSqz150045 	}
3817db6e34eSqz150045 
3827db6e34eSqz150045 	if ((error = set_layout(kbd, layout_num)) != 0)
3837db6e34eSqz150045 		return (error);
3847db6e34eSqz150045 
3857c478bd9Sstevel@tonic-gate 	return (0);
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate /*
389*8ffc942dSrz201010  * This routine sets keyboard or console beeper frequency
390*8ffc942dSrz201010  */
391*8ffc942dSrz201010 static int
392*8ffc942dSrz201010 set_beep_freq(int fd, char *type, int freq)
393*8ffc942dSrz201010 {
394*8ffc942dSrz201010 	struct freq_request fr_struct;
395*8ffc942dSrz201010 
396*8ffc942dSrz201010 	if (strcmp(type, "keyboard") == 0)
397*8ffc942dSrz201010 		fr_struct.type = KBD_BEEP;
398*8ffc942dSrz201010 	else if (strcmp(type, "console") == 0)
399*8ffc942dSrz201010 		fr_struct.type = CONSOLE_BEEP;
400*8ffc942dSrz201010 	else
401*8ffc942dSrz201010 		return (EINVAL);
402*8ffc942dSrz201010 
403*8ffc942dSrz201010 	fr_struct.freq = (int16_t)freq;
404*8ffc942dSrz201010 
405*8ffc942dSrz201010 	return (ioctl(fd, KIOCSETFREQ, &fr_struct));
406*8ffc942dSrz201010 }
407*8ffc942dSrz201010 
408*8ffc942dSrz201010 /*
4097c478bd9Sstevel@tonic-gate  * this routine resets the state of the keyboard as if power-up
4107c478bd9Sstevel@tonic-gate  */
4117c478bd9Sstevel@tonic-gate static void
4127c478bd9Sstevel@tonic-gate reset(int kbd)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	int cmd;
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	cmd = KBD_CMD_RESET;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCCMD, &cmd)) {
4197c478bd9Sstevel@tonic-gate 		perror("kbd: ioctl error");
4207c478bd9Sstevel@tonic-gate 		exit(1);
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate  * this routine gets the type of the keyboard being used
4277c478bd9Sstevel@tonic-gate  */
4287c478bd9Sstevel@tonic-gate static void
4297c478bd9Sstevel@tonic-gate get_type(int kbd)
4307c478bd9Sstevel@tonic-gate {
4317c478bd9Sstevel@tonic-gate 	int kbd_type;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCTYPE, &kbd_type)) {
4347c478bd9Sstevel@tonic-gate 		perror("ioctl (kbd type)");
4357c478bd9Sstevel@tonic-gate 		exit(1);
4367c478bd9Sstevel@tonic-gate 	}
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	switch (kbd_type) {
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	case KB_SUN3:
4417c478bd9Sstevel@tonic-gate 		(void) printf("Type 3 Sun keyboard\n");
4427c478bd9Sstevel@tonic-gate 		break;
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	case KB_SUN4:
4457c478bd9Sstevel@tonic-gate 		(void) printf("Type 4 Sun keyboard\n");
4467c478bd9Sstevel@tonic-gate 		break;
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	case KB_ASCII:
4497c478bd9Sstevel@tonic-gate 		(void) printf("ASCII\n");
4507c478bd9Sstevel@tonic-gate 		break;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	case KB_PC:
4537c478bd9Sstevel@tonic-gate 		(void) printf("PC\n");
4547c478bd9Sstevel@tonic-gate 		break;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	case KB_USB:
4577c478bd9Sstevel@tonic-gate 		(void) printf("USB keyboard\n");
4587c478bd9Sstevel@tonic-gate 		break;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	default:
4617c478bd9Sstevel@tonic-gate 		(void) printf("Unknown keyboard type\n");
4627c478bd9Sstevel@tonic-gate 		break;
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate  * this routine gets the layout of the keyboard being used
4687c478bd9Sstevel@tonic-gate  * also, included the autorepeat delay and rate being used
4697c478bd9Sstevel@tonic-gate  */
4707c478bd9Sstevel@tonic-gate static void
4717c478bd9Sstevel@tonic-gate get_layout(int kbd)
4727c478bd9Sstevel@tonic-gate {
4737c478bd9Sstevel@tonic-gate 	int kbd_type;
4747c478bd9Sstevel@tonic-gate 	int kbd_layout;
4757c478bd9Sstevel@tonic-gate 	/* these two variables are used for getting delay&rate */
4767c478bd9Sstevel@tonic-gate 	int delay, rate;
4777c478bd9Sstevel@tonic-gate 	delay = rate = 0;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCTYPE, &kbd_type)) {
4807c478bd9Sstevel@tonic-gate 		perror("ioctl (kbd type)");
4817c478bd9Sstevel@tonic-gate 		exit(1);
4827c478bd9Sstevel@tonic-gate 	}
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCLAYOUT, &kbd_layout)) {
4857c478bd9Sstevel@tonic-gate 		perror("ioctl (kbd layout)");
4867c478bd9Sstevel@tonic-gate 		exit(1);
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	(void) printf("type=%d\nlayout=%d (0x%.2x)\n",
4907c478bd9Sstevel@tonic-gate 	    kbd_type, kbd_layout, kbd_layout);
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	/* below code is used to get the autorepeat delay and rate */
4937c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCGRPTDELAY, &delay)) {
4947c478bd9Sstevel@tonic-gate 		perror("ioctl (kbd get repeat delay)");
4957c478bd9Sstevel@tonic-gate 		exit(1);
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCGRPTRATE, &rate)) {
4997c478bd9Sstevel@tonic-gate 		perror("ioctl (kbd get repeat rate)");
5007c478bd9Sstevel@tonic-gate 		exit(1);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	(void) printf("delay(ms)=%d\n", delay);
5047c478bd9Sstevel@tonic-gate 	(void) printf("rate(ms)=%d\n", rate);
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate  * this routine enables or disables clicking of the keyboard
5097c478bd9Sstevel@tonic-gate  */
5107c478bd9Sstevel@tonic-gate static int
5117c478bd9Sstevel@tonic-gate click(char *copt, int kbd)
5127c478bd9Sstevel@tonic-gate {
5137c478bd9Sstevel@tonic-gate 	int cmd;
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	if (strcmp(copt, "on") == 0)
5167c478bd9Sstevel@tonic-gate 		cmd = KBD_CMD_CLICK;
5177c478bd9Sstevel@tonic-gate 	else if (strcmp(copt, "off") == 0)
5187c478bd9Sstevel@tonic-gate 		cmd = KBD_CMD_NOCLICK;
5197c478bd9Sstevel@tonic-gate 	else {
5207c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "wrong option -- %s\n", copt);
5217c478bd9Sstevel@tonic-gate 		usage();
5227c478bd9Sstevel@tonic-gate 		return (1);
5237c478bd9Sstevel@tonic-gate 	}
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCCMD, &cmd)) {
5267c478bd9Sstevel@tonic-gate 		perror("kbd ioctl (keyclick)");
5277c478bd9Sstevel@tonic-gate 		return (1);
5287c478bd9Sstevel@tonic-gate 	}
5297c478bd9Sstevel@tonic-gate 	return (0);
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate /*
5337c478bd9Sstevel@tonic-gate  * this routine enables/disables/sets BRK or abort sequence feature
5347c478bd9Sstevel@tonic-gate  */
5357c478bd9Sstevel@tonic-gate static int
5367c478bd9Sstevel@tonic-gate abort_enable(char *aopt, int kbd)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate 	int enable;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	if (strcmp(aopt, "alternate") == 0)
5417c478bd9Sstevel@tonic-gate 		enable = KIOCABORTALTERNATE;
5427c478bd9Sstevel@tonic-gate 	else if (strcmp(aopt, "enable") == 0)
5437c478bd9Sstevel@tonic-gate 		enable = KIOCABORTENABLE;
5447c478bd9Sstevel@tonic-gate 	else if (strcmp(aopt, "disable") == 0)
5457c478bd9Sstevel@tonic-gate 		enable = KIOCABORTDISABLE;
5467c478bd9Sstevel@tonic-gate 	else {
5477c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "wrong option -- %s\n", aopt);
5487c478bd9Sstevel@tonic-gate 		usage();
5497c478bd9Sstevel@tonic-gate 		return (1);
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCSKABORTEN, &enable)) {
5537c478bd9Sstevel@tonic-gate 		perror("kbd ioctl (abort enable)");
5547c478bd9Sstevel@tonic-gate 		return (1);
5557c478bd9Sstevel@tonic-gate 	}
5567c478bd9Sstevel@tonic-gate 	return (0);
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate  * this routine set autorepeat delay
5617c478bd9Sstevel@tonic-gate  */
5627c478bd9Sstevel@tonic-gate static int
5637c478bd9Sstevel@tonic-gate set_repeat_delay(char *delay_str, int kbd)
5647c478bd9Sstevel@tonic-gate {
5657c478bd9Sstevel@tonic-gate 	int delay = atoi(delay_str);
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 	/*
5687c478bd9Sstevel@tonic-gate 	 * The error message depends on the different inputs.
5697c478bd9Sstevel@tonic-gate 	 * a. the input is a invalid integer(unit in ms)
5707c478bd9Sstevel@tonic-gate 	 * b. the input is a integer less than the minimal delay setting.
5717c478bd9Sstevel@tonic-gate 	 * The condition (a) has been covered by main function and set_default
5727c478bd9Sstevel@tonic-gate 	 * function.
5737c478bd9Sstevel@tonic-gate 	 */
5747c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCSRPTDELAY, &delay) == -1) {
5757c478bd9Sstevel@tonic-gate 		if (delay < KIOCRPTDELAY_MIN)
5767c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "kbd: specified delay %d is "
5777c478bd9Sstevel@tonic-gate 			    "less than minimum %d\n", delay, KIOCRPTDELAY_MIN);
5787c478bd9Sstevel@tonic-gate 		else
5797c478bd9Sstevel@tonic-gate 			perror("kbd: set repeat delay");
5807c478bd9Sstevel@tonic-gate 		return (1);
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	return (0);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate /*
5877c478bd9Sstevel@tonic-gate  * this routine set autorepeat rate
5887c478bd9Sstevel@tonic-gate  */
5897c478bd9Sstevel@tonic-gate static int
5907c478bd9Sstevel@tonic-gate set_repeat_rate(char *rate_str, int kbd)
5917c478bd9Sstevel@tonic-gate {
5927c478bd9Sstevel@tonic-gate 	int rate = atoi(rate_str);
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	/*
5957c478bd9Sstevel@tonic-gate 	 * The error message depends on the different inputs.
5967c478bd9Sstevel@tonic-gate 	 * a. the input is a invalid integer(unit in ms)
5977c478bd9Sstevel@tonic-gate 	 * b. the input is a integer less than the minimal rate setting.
5987c478bd9Sstevel@tonic-gate 	 * The condition (a) has been covered by main function and set_default
5997c478bd9Sstevel@tonic-gate 	 * function.
6007c478bd9Sstevel@tonic-gate 	 */
6017c478bd9Sstevel@tonic-gate 	if (ioctl(kbd, KIOCSRPTRATE, &rate) == -1) {
6027c478bd9Sstevel@tonic-gate 		if (rate < KIOCRPTRATE_MIN)
6037c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "kbd: specified rate %d is "
6047c478bd9Sstevel@tonic-gate 			    "less than minimum %d\n", rate, KIOCRPTRATE_MIN);
6057c478bd9Sstevel@tonic-gate 		else
6067c478bd9Sstevel@tonic-gate 			perror("kbd: set repeat rate");
6077c478bd9Sstevel@tonic-gate 		return (1);
6087c478bd9Sstevel@tonic-gate 	}
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	return (0);
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate #define	BAD_DEFAULT	"kbd: bad default value for %s: %s\n"
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate static void
6167c478bd9Sstevel@tonic-gate kbd_defaults(int kbd)
6177c478bd9Sstevel@tonic-gate {
618*8ffc942dSrz201010 	char *p, *endptr;
619*8ffc942dSrz201010 	int layout_num, freq;
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	if (defopen(DEF_FILE) != 0) {
6227c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Can't open default file: %s\n",
6237c478bd9Sstevel@tonic-gate 		    DEF_FILE);
6247c478bd9Sstevel@tonic-gate 		exit(1);
6257c478bd9Sstevel@tonic-gate 	}
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	p = defread(DEF_CLICK);
6287c478bd9Sstevel@tonic-gate 	if (p != NULL) {
6297c478bd9Sstevel@tonic-gate 		/*
6307c478bd9Sstevel@tonic-gate 		 * KEYCLICK must equal "on" or "off"
6317c478bd9Sstevel@tonic-gate 		 */
6327c478bd9Sstevel@tonic-gate 		if ((strcmp(p, "on") == 0) || (strcmp(p, "off") == 0))
6337c478bd9Sstevel@tonic-gate 			(void) click(p, kbd);
6347c478bd9Sstevel@tonic-gate 		else
6357c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, BAD_DEFAULT, DEF_CLICK, p);
6367c478bd9Sstevel@tonic-gate 	}
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	p = defread(DEF_ABORT);
6397c478bd9Sstevel@tonic-gate 	if (p != NULL) {
6407c478bd9Sstevel@tonic-gate 		/*
6417c478bd9Sstevel@tonic-gate 		 * ABORT must equal "enable", "disable" or "alternate"
6427c478bd9Sstevel@tonic-gate 		 */
6437c478bd9Sstevel@tonic-gate 		if ((strcmp(p, "enable") == 0) ||
6447c478bd9Sstevel@tonic-gate 		    (strcmp(p, "alternate") == 0) ||
6457c478bd9Sstevel@tonic-gate 		    (strcmp(p, "disable") == 0))
6467c478bd9Sstevel@tonic-gate 			(void) abort_enable(p, kbd);
6477c478bd9Sstevel@tonic-gate 		else
6487c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, BAD_DEFAULT, DEF_ABORT, p);
6497c478bd9Sstevel@tonic-gate 	}
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	p = defread(DEF_RPTDELAY);
6527c478bd9Sstevel@tonic-gate 	if (p != NULL) {
6537c478bd9Sstevel@tonic-gate 		/*
6547c478bd9Sstevel@tonic-gate 		 * REPEAT_DELAY unit in ms
6557c478bd9Sstevel@tonic-gate 		 */
6567c478bd9Sstevel@tonic-gate 		if (atoi(p) > 0)
6577c478bd9Sstevel@tonic-gate 			(void) set_repeat_delay(p, kbd);
6587c478bd9Sstevel@tonic-gate 		else
6597c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, BAD_DEFAULT, DEF_RPTDELAY, p);
6607c478bd9Sstevel@tonic-gate 	}
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	p = defread(DEF_RPTRATE);
6637c478bd9Sstevel@tonic-gate 	if (p != NULL) {
6647c478bd9Sstevel@tonic-gate 		/*
6657c478bd9Sstevel@tonic-gate 		 * REPEAT_RATE unit in ms
6667c478bd9Sstevel@tonic-gate 		 */
6677c478bd9Sstevel@tonic-gate 		if (atoi(p) > 0)
6687c478bd9Sstevel@tonic-gate 			(void) set_repeat_rate(p, kbd);
6697c478bd9Sstevel@tonic-gate 		else
6707c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, BAD_DEFAULT, DEF_RPTRATE, p);
6717c478bd9Sstevel@tonic-gate 	}
6727db6e34eSqz150045 
6737db6e34eSqz150045 	p = defread(DEF_LAYOUT);
6747db6e34eSqz150045 	if (p != NULL) {
6757db6e34eSqz150045 		/*
6767db6e34eSqz150045 		 * LAYOUT must be one of the layouts supported in kbd_layouts
6777db6e34eSqz150045 		 */
6787db6e34eSqz150045 		if (get_layouts() != 0)
6797db6e34eSqz150045 			return;
6807db6e34eSqz150045 
6817db6e34eSqz150045 		if ((layout_num = get_layout_number(p)) == -1) {
6827db6e34eSqz150045 			(void) fprintf(stderr, BAD_DEFAULT, DEF_LAYOUT, p);
6837db6e34eSqz150045 			return;
6847db6e34eSqz150045 		}
6857db6e34eSqz150045 
6867db6e34eSqz150045 		(void) set_layout(kbd, layout_num);
6877db6e34eSqz150045 	}
688*8ffc942dSrz201010 
689*8ffc942dSrz201010 	p = defread(DEF_KBDFREQ);
690*8ffc942dSrz201010 	if (p != NULL) {
691*8ffc942dSrz201010 		/*
692*8ffc942dSrz201010 		 * Keyboard beeper frequency unit in Hz
693*8ffc942dSrz201010 		 */
694*8ffc942dSrz201010 		endptr = NULL;
695*8ffc942dSrz201010 		errno = 0;
696*8ffc942dSrz201010 		freq = (int)strtol(p, &endptr, 10);
697*8ffc942dSrz201010 		if (errno == 0 && endptr[0] == '\0' &&
698*8ffc942dSrz201010 		    freq >= 0 && freq <= INT16_MAX)
699*8ffc942dSrz201010 			(void) set_beep_freq(kbd, "keyboard", freq);
700*8ffc942dSrz201010 		else
701*8ffc942dSrz201010 			(void) fprintf(stderr, BAD_DEFAULT, DEF_KBDFREQ, p);
702*8ffc942dSrz201010 	}
703*8ffc942dSrz201010 
704*8ffc942dSrz201010 	p = defread(DEF_CONSFREQ);
705*8ffc942dSrz201010 	if (p != NULL) {
706*8ffc942dSrz201010 		/*
707*8ffc942dSrz201010 		 * Console beeper frequency unit in Hz
708*8ffc942dSrz201010 		 */
709*8ffc942dSrz201010 		endptr = NULL;
710*8ffc942dSrz201010 		errno = 0;
711*8ffc942dSrz201010 		freq = (int)strtol(p, &endptr, 10);
712*8ffc942dSrz201010 		if (errno == 0 && endptr[0] == '\0' &&
713*8ffc942dSrz201010 		    freq >= 0 && freq <= INT16_MAX)
714*8ffc942dSrz201010 			(void) set_beep_freq(kbd, "console", freq);
715*8ffc942dSrz201010 		else
716*8ffc942dSrz201010 			(void) fprintf(stderr, BAD_DEFAULT, DEF_CONSFREQ, p);
717*8ffc942dSrz201010 	}
7187db6e34eSqz150045 }
7197db6e34eSqz150045 
7207db6e34eSqz150045 static int
7217db6e34eSqz150045 get_layout_number(char *layout)
7227db6e34eSqz150045 {
7237db6e34eSqz150045 	int i;
7247db6e34eSqz150045 	int layout_number = -1;
7257db6e34eSqz150045 
7267db6e34eSqz150045 	for (i = 0; i < layout_count; i ++) {
7277db6e34eSqz150045 		if (strcmp(layout, layout_names[i]) == 0) {
7287db6e34eSqz150045 			layout_number = layout_numbers[i];
7297db6e34eSqz150045 			break;
7307db6e34eSqz150045 		}
7317db6e34eSqz150045 	}
7327db6e34eSqz150045 
7337db6e34eSqz150045 	return (layout_number);
7347db6e34eSqz150045 }
7357db6e34eSqz150045 
7367db6e34eSqz150045 static int
7377db6e34eSqz150045 get_layouts()
7387db6e34eSqz150045 {
7397db6e34eSqz150045 	FILE *stream;
7407db6e34eSqz150045 	char buffer[MAX_LINE_SIZE];
7417db6e34eSqz150045 	char *result = NULL;
7427db6e34eSqz150045 	int  i = 0;
7437db6e34eSqz150045 	char *tmpbuf;
7447db6e34eSqz150045 
7457db6e34eSqz150045 	if ((stream = fopen(KBD_LAYOUT_FILE, "r")) == 0) {
7467db6e34eSqz150045 		perror(KBD_LAYOUT_FILE);
7477db6e34eSqz150045 		return (1);
7487db6e34eSqz150045 	}
7497db6e34eSqz150045 
7507db6e34eSqz150045 	while ((fgets(buffer, MAX_LINE_SIZE, stream) != NULL) &&
7517db6e34eSqz150045 	    (i < MAX_LAYOUT_NUM)) {
7527db6e34eSqz150045 		if (buffer[0] == '#')
7537db6e34eSqz150045 			continue;
7547db6e34eSqz150045 		if ((result = strtok(buffer, "=")) == NULL)
7557db6e34eSqz150045 			continue;
7567db6e34eSqz150045 		if ((tmpbuf = strdup(result)) != NULL) {
7577db6e34eSqz150045 			layout_names[i] = tmpbuf;
7587db6e34eSqz150045 		} else {
7597db6e34eSqz150045 			perror("out of memory getting layout names");
7607db6e34eSqz150045 			return (1);
7617db6e34eSqz150045 		}
7627db6e34eSqz150045 		if ((result = strtok(NULL, "\n")) == NULL)
7637db6e34eSqz150045 			continue;
7647db6e34eSqz150045 		layout_numbers[i] = atoi(result);
7657db6e34eSqz150045 		if (strcmp(tmpbuf, "US-English") == 0)
7667db6e34eSqz150045 			default_layout_number = i;
7677db6e34eSqz150045 		i++;
7687db6e34eSqz150045 	}
7697db6e34eSqz150045 	layout_count = i;
7707db6e34eSqz150045 
7717db6e34eSqz150045 	return (0);
7727db6e34eSqz150045 }
7737db6e34eSqz150045 
7747db6e34eSqz150045 /*
7757db6e34eSqz150045  * this routine sets the layout of the keyboard being used
7767db6e34eSqz150045  */
7777db6e34eSqz150045 static int
7787db6e34eSqz150045 set_layout(int kbd, int layout_num)
7797db6e34eSqz150045 {
7807db6e34eSqz150045 
7817db6e34eSqz150045 	if (ioctl(kbd, KIOCSLAYOUT, layout_num)) {
7827db6e34eSqz150045 		perror("ioctl (set kbd layout)");
7837db6e34eSqz150045 		return (1);
7847db6e34eSqz150045 	}
7857db6e34eSqz150045 
7867db6e34eSqz150045 	return (0);
7877c478bd9Sstevel@tonic-gate }
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate static char *usage1 = "kbd [-r] [-t] [-l] [-a enable|disable|alternate]";
7907c478bd9Sstevel@tonic-gate static char *usage2 = "    [-c on|off][-D delay][-R rate][-d keyboard device]";
7917c478bd9Sstevel@tonic-gate static char *usage3 = "kbd -i [-d keyboard device]";
7927db6e34eSqz150045 static char *usage4 = "kbd -s [language]";
793*8ffc942dSrz201010 static char *usage5 = "kbd -b [keyboard|console] frequency";
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate static void
7967c478bd9Sstevel@tonic-gate usage(void)
7977c478bd9Sstevel@tonic-gate {
798*8ffc942dSrz201010 	(void) fprintf(stderr, "Usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", usage1,
799*8ffc942dSrz201010 	    usage2, usage3, usage4, usage5);
8007c478bd9Sstevel@tonic-gate }
801