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 5*d8c870b0Sqz150045 * Common Development and Distribution License (the "License"). 6*d8c870b0Sqz150045 * 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 /* 22*d8c870b0Sqz150045 * 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 /* 307c478bd9Sstevel@tonic-gate * Usage: kbd [-r] [-t] [-l] [-i] [-c on|off] [-a enable|disable|alternate] 317c478bd9Sstevel@tonic-gate * [-d keyboard device] 327c478bd9Sstevel@tonic-gate * -r reset the keyboard as if power-up 337c478bd9Sstevel@tonic-gate * -t return the type of the keyboard being used 347c478bd9Sstevel@tonic-gate * -l return the layout of the keyboard being used, 357c478bd9Sstevel@tonic-gate * and the Autorepeat settings 367c478bd9Sstevel@tonic-gate * -i read in the default configuration file 377c478bd9Sstevel@tonic-gate * -c on|off turn on|off clicking 387c478bd9Sstevel@tonic-gate * -a enable|disable|alternate sets abort sequence 397c478bd9Sstevel@tonic-gate * -D autorepeat delay sets autorepeat dealy, unit in ms 407c478bd9Sstevel@tonic-gate * -R autorepeat rate sets autorepeat rate, unit in ms 417c478bd9Sstevel@tonic-gate * -d keyboard device chooses the kbd device, default /dev/kbd. 427db6e34eSqz150045 * -s keyboard layout sets keyboard layout 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #include <sys/types.h> 467c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 477c478bd9Sstevel@tonic-gate #include <sys/kbio.h> 487c478bd9Sstevel@tonic-gate #include <sys/kbd.h> 497c478bd9Sstevel@tonic-gate #include <stdio.h> 507c478bd9Sstevel@tonic-gate #include <fcntl.h> 517c478bd9Sstevel@tonic-gate #include <deflt.h> 527c478bd9Sstevel@tonic-gate #include <unistd.h> 537c478bd9Sstevel@tonic-gate #include <string.h> 547c478bd9Sstevel@tonic-gate #include <stdlib.h> 557c478bd9Sstevel@tonic-gate #include <stropts.h> 56*d8c870b0Sqz150045 #include <libintl.h> 57*d8c870b0Sqz150045 #include <locale.h> 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #define KBD_DEVICE "/dev/kbd" /* default keyboard device */ 607c478bd9Sstevel@tonic-gate #define DEF_FILE "/etc/default/kbd" /* kbd defaults file */ 617c478bd9Sstevel@tonic-gate #define DEF_ABORT "KEYBOARD_ABORT=" 627c478bd9Sstevel@tonic-gate #define DEF_CLICK "KEYCLICK=" 637c478bd9Sstevel@tonic-gate #define DEF_RPTDELAY "REPEAT_DELAY=" 647c478bd9Sstevel@tonic-gate #define DEF_RPTRATE "REPEAT_RATE=" 657db6e34eSqz150045 #define DEF_LAYOUT "LAYOUT=" 667db6e34eSqz150045 677db6e34eSqz150045 #define KBD_LAYOUT_FILE "/usr/share/lib/keytables/type_6/kbd_layouts" 687db6e34eSqz150045 #define MAX_LAYOUT_NUM 128 697db6e34eSqz150045 #define MAX_LINE_SIZE 256 707db6e34eSqz150045 #define DEFAULT_KBD_LAYOUT 33 717db6e34eSqz150045 727db6e34eSqz150045 char *layout_names[MAX_LAYOUT_NUM]; 737db6e34eSqz150045 int layout_numbers[MAX_LAYOUT_NUM]; 747db6e34eSqz150045 static int layout_count; 757db6e34eSqz150045 static int default_layout_number = 0; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate static void reset(int); 787c478bd9Sstevel@tonic-gate static void get_type(int); 797c478bd9Sstevel@tonic-gate static void get_layout(int); 807c478bd9Sstevel@tonic-gate static void kbd_defaults(int); 817c478bd9Sstevel@tonic-gate static void usage(void); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate static int click(char *, int); 847c478bd9Sstevel@tonic-gate static int abort_enable(char *, int); 857c478bd9Sstevel@tonic-gate static int set_repeat_delay(char *, int); 867c478bd9Sstevel@tonic-gate static int set_repeat_rate(char *, int); 877c478bd9Sstevel@tonic-gate 887db6e34eSqz150045 static int get_layout_number(char *); 897db6e34eSqz150045 static int set_layout(int, int); 907db6e34eSqz150045 static int get_layouts(void); 917db6e34eSqz150045 static int set_kbd_layout(int, char *); 927db6e34eSqz150045 937c478bd9Sstevel@tonic-gate int 947c478bd9Sstevel@tonic-gate main(int argc, char **argv) 957c478bd9Sstevel@tonic-gate { 967c478bd9Sstevel@tonic-gate int c, error; 977c478bd9Sstevel@tonic-gate int rflag, tflag, lflag, cflag, dflag, aflag, iflag, errflag, 987db6e34eSqz150045 Dflag, Rflag, rtlacDRflag, sflag; 997db6e34eSqz150045 char *copt, *aopt, *delay, *rate, *layout_name; 1007c478bd9Sstevel@tonic-gate char *kbdname = KBD_DEVICE; 1017c478bd9Sstevel@tonic-gate int kbd; 1027c478bd9Sstevel@tonic-gate extern char *optarg; 1037c478bd9Sstevel@tonic-gate extern int optind; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate rflag = tflag = cflag = dflag = aflag = iflag = errflag = lflag = 1067db6e34eSqz150045 Dflag = Rflag = sflag = 0; 1077c478bd9Sstevel@tonic-gate copt = aopt = (char *)0; 1087c478bd9Sstevel@tonic-gate 109*d8c870b0Sqz150045 (void) setlocale(LC_ALL, ""); 110*d8c870b0Sqz150045 #if !defined(TEXT_DOMAIN) 111*d8c870b0Sqz150045 #define TEXT_DOMAIN "SYS_TEST" 112*d8c870b0Sqz150045 #endif 113*d8c870b0Sqz150045 (void) textdomain(TEXT_DOMAIN); 114*d8c870b0Sqz150045 1157db6e34eSqz150045 while ((c = getopt(argc, argv, "rtlisc:a:d:D:R:")) != EOF) { 1167c478bd9Sstevel@tonic-gate switch (c) { 1177c478bd9Sstevel@tonic-gate case 'r': 1187c478bd9Sstevel@tonic-gate rflag++; 1197c478bd9Sstevel@tonic-gate break; 1207c478bd9Sstevel@tonic-gate case 't': 1217c478bd9Sstevel@tonic-gate tflag++; 1227c478bd9Sstevel@tonic-gate break; 1237c478bd9Sstevel@tonic-gate case 'l': 1247c478bd9Sstevel@tonic-gate lflag++; 1257c478bd9Sstevel@tonic-gate break; 1267c478bd9Sstevel@tonic-gate case 'i': 1277c478bd9Sstevel@tonic-gate iflag++; 1287c478bd9Sstevel@tonic-gate break; 1297db6e34eSqz150045 case 's': 1307db6e34eSqz150045 sflag++; 1317db6e34eSqz150045 break; 1327c478bd9Sstevel@tonic-gate case 'c': 1337c478bd9Sstevel@tonic-gate copt = optarg; 1347c478bd9Sstevel@tonic-gate cflag++; 1357c478bd9Sstevel@tonic-gate break; 1367c478bd9Sstevel@tonic-gate case 'a': 1377c478bd9Sstevel@tonic-gate aopt = optarg; 1387c478bd9Sstevel@tonic-gate aflag++; 1397c478bd9Sstevel@tonic-gate break; 1407c478bd9Sstevel@tonic-gate case 'd': 1417c478bd9Sstevel@tonic-gate kbdname = optarg; 1427c478bd9Sstevel@tonic-gate dflag++; 1437c478bd9Sstevel@tonic-gate break; 1447c478bd9Sstevel@tonic-gate case 'D': 1457c478bd9Sstevel@tonic-gate delay = optarg; 1467c478bd9Sstevel@tonic-gate Dflag++; 1477c478bd9Sstevel@tonic-gate break; 1487c478bd9Sstevel@tonic-gate case 'R': 1497c478bd9Sstevel@tonic-gate rate = optarg; 1507c478bd9Sstevel@tonic-gate Rflag++; 1517c478bd9Sstevel@tonic-gate break; 1527c478bd9Sstevel@tonic-gate case '?': 1537c478bd9Sstevel@tonic-gate errflag++; 1547c478bd9Sstevel@tonic-gate break; 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * Check for valid arguments: 1607c478bd9Sstevel@tonic-gate * 1617c478bd9Sstevel@tonic-gate * If argument parsing failed or if there are left-over 1627db6e34eSqz150045 * command line arguments(except -s option), then we're done now. 1637c478bd9Sstevel@tonic-gate */ 1647db6e34eSqz150045 if (errflag != 0 || ((sflag == 0) && (argc != optind))) { 1657c478bd9Sstevel@tonic-gate usage(); 1667c478bd9Sstevel@tonic-gate exit(1); 1677c478bd9Sstevel@tonic-gate } 1687db6e34eSqz150045 1697c478bd9Sstevel@tonic-gate /* 1707db6e34eSqz150045 * kbd requires that the user specify either "-i" or "-s" or at 1717db6e34eSqz150045 * least one of -[rtlacDR]. The "-d" option is, well, optional. 1727db6e34eSqz150045 * We don't care if it's there or not. 1737c478bd9Sstevel@tonic-gate */ 1747c478bd9Sstevel@tonic-gate rtlacDRflag = rflag + tflag + lflag + aflag + cflag + Dflag + Rflag; 1757db6e34eSqz150045 if (!((iflag != 0 && sflag == 0 && rtlacDRflag == 0) || 1767db6e34eSqz150045 (iflag == 0 && sflag != 0 && dflag == 0 && rtlacDRflag == 0) || 1777db6e34eSqz150045 (iflag == 0 && sflag == 0 && rtlacDRflag != 0))) { 1787c478bd9Sstevel@tonic-gate usage(); 1797c478bd9Sstevel@tonic-gate exit(1); 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate if (Dflag && atoi(delay) <= 0) { 1837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Invalid arguments: -D %s\n", delay); 1847c478bd9Sstevel@tonic-gate usage(); 1857c478bd9Sstevel@tonic-gate exit(1); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (Rflag && atoi(rate) <= 0) { 1897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Invalid arguments: -R %s\n", rate); 1907c478bd9Sstevel@tonic-gate usage(); 1917c478bd9Sstevel@tonic-gate exit(1); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * Open the keyboard device 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate if ((kbd = open(kbdname, O_RDWR)) < 0) { 1987c478bd9Sstevel@tonic-gate perror("opening the keyboard"); 1997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "kbd: Cannot open %s\n", kbdname); 2007c478bd9Sstevel@tonic-gate exit(1); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate if (iflag) { 2047c478bd9Sstevel@tonic-gate kbd_defaults(kbd); 2057c478bd9Sstevel@tonic-gate exit(0); /* A mutually exclusive option */ 2067c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate if (tflag) 2107c478bd9Sstevel@tonic-gate get_type(kbd); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate if (lflag) 2137c478bd9Sstevel@tonic-gate get_layout(kbd); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate if (cflag && (error = click(copt, kbd)) != 0) 2167c478bd9Sstevel@tonic-gate exit(error); 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate if (rflag) 2197c478bd9Sstevel@tonic-gate reset(kbd); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (aflag && (error = abort_enable(aopt, kbd)) != 0) 2227c478bd9Sstevel@tonic-gate exit(error); 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate if (Dflag && (error = set_repeat_delay(delay, kbd)) != 0) 2257c478bd9Sstevel@tonic-gate exit(error); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate if (Rflag && (error = set_repeat_rate(rate, kbd)) != 0) 2287c478bd9Sstevel@tonic-gate exit(error); 2297c478bd9Sstevel@tonic-gate 2307db6e34eSqz150045 if (sflag) { 2317db6e34eSqz150045 if (argc == optind) { 2327db6e34eSqz150045 layout_name = NULL; 2337db6e34eSqz150045 } else if (argc == (optind + 1)) { 2347db6e34eSqz150045 layout_name = argv[optind]; 2357db6e34eSqz150045 } else { 2367db6e34eSqz150045 usage(); 2377db6e34eSqz150045 exit(1); 2387db6e34eSqz150045 } 2397db6e34eSqz150045 2407db6e34eSqz150045 if ((error = set_kbd_layout(kbd, layout_name)) != 0) 2417db6e34eSqz150045 exit(error); 2427db6e34eSqz150045 } 2437db6e34eSqz150045 2447db6e34eSqz150045 return (0); 2457db6e34eSqz150045 } 2467db6e34eSqz150045 2477db6e34eSqz150045 /* 2487db6e34eSqz150045 * this routine gets the type of the keyboard being used 2497db6e34eSqz150045 */ 2507db6e34eSqz150045 static int 2517db6e34eSqz150045 set_kbd_layout(int kbd, char *layout_name) 2527db6e34eSqz150045 { 2537db6e34eSqz150045 int layout_num; 2547db6e34eSqz150045 int error = 1; 2557db6e34eSqz150045 2567db6e34eSqz150045 /* get the language info from the layouts file */ 2577db6e34eSqz150045 if (get_layouts() != 0) 2587db6e34eSqz150045 return (error); 2597db6e34eSqz150045 2607db6e34eSqz150045 if (layout_name != NULL) { 2617db6e34eSqz150045 if ((layout_num = get_layout_number(layout_name)) == -1) { 2627db6e34eSqz150045 (void) fprintf(stderr, "%s: unknown layout name\n" 2637db6e34eSqz150045 "Please refer to 'kbd -s' to get the " 2647db6e34eSqz150045 "supported layouts.\n", layout_name); 2657db6e34eSqz150045 return (error); 2667db6e34eSqz150045 } 2677db6e34eSqz150045 } else { 2687db6e34eSqz150045 int i, j, print_cnt, input_num; 2697db6e34eSqz150045 boolean_t input_right = B_TRUE; 2707db6e34eSqz150045 boolean_t default_input = B_FALSE; 2717db6e34eSqz150045 char input[8]; /* 8 chars is enough for numbers */ 2727db6e34eSqz150045 2737db6e34eSqz150045 print_cnt = (layout_count % 2) ? 2747db6e34eSqz150045 layout_count/2+1 : layout_count/2; 2757db6e34eSqz150045 2767db6e34eSqz150045 for (i = 1; i <= print_cnt; i++) { 2777db6e34eSqz150045 (void) printf("%2d. %-30s", i, 2787db6e34eSqz150045 layout_names[i-1]); 2797db6e34eSqz150045 j = i + print_cnt; 2807db6e34eSqz150045 if (j <= layout_count) { 2817db6e34eSqz150045 (void) printf("%-2d. %-30s\n", j, 2827db6e34eSqz150045 layout_names[j-1]); 2837db6e34eSqz150045 } 2847db6e34eSqz150045 } 285*d8c870b0Sqz150045 (void) printf(gettext("\nTo select the keyboard layout," 286*d8c870b0Sqz150045 " enter a number [default %d]:"), 2877db6e34eSqz150045 default_layout_number+1); 2887db6e34eSqz150045 2897db6e34eSqz150045 for (;;) { 2907db6e34eSqz150045 if (input_right == B_FALSE) 291*d8c870b0Sqz150045 (void) printf(gettext("Invalid input. " 292*d8c870b0Sqz150045 "Please input a number " 293*d8c870b0Sqz150045 "(1,2,...):")); 2947db6e34eSqz150045 (void) memset(input, 0, 8); 2957db6e34eSqz150045 (void) fflush(stdin); 2967db6e34eSqz150045 (void) fgets(input, 8, stdin); 2977db6e34eSqz150045 if (strlen(input) > 4) { 2987db6e34eSqz150045 input_right = B_FALSE; 2997db6e34eSqz150045 continue; 3007db6e34eSqz150045 } 3017db6e34eSqz150045 if (input[0] == '\n') { 3027db6e34eSqz150045 default_input = B_TRUE; 3037db6e34eSqz150045 break; 3047db6e34eSqz150045 } 3057db6e34eSqz150045 input_right = B_TRUE; 3067db6e34eSqz150045 /* check if the inputs are numbers 0~9 */ 3077db6e34eSqz150045 for (i = 0; i < (strlen(input) - 1); i++) { 3087db6e34eSqz150045 if ((input[i] < '0') || 3097db6e34eSqz150045 (input[i] > '9')) { 3107db6e34eSqz150045 input_right = B_FALSE; 3117db6e34eSqz150045 break; 3127db6e34eSqz150045 } 3137db6e34eSqz150045 } 3147db6e34eSqz150045 if (input_right == B_FALSE) 3157db6e34eSqz150045 continue; 3167db6e34eSqz150045 input_num = atoi(input); 3177db6e34eSqz150045 if ((input_num > 0) && 3187db6e34eSqz150045 (input_num <= layout_count)) 3197db6e34eSqz150045 break; 3207db6e34eSqz150045 else 3217db6e34eSqz150045 input_right = B_FALSE; 3227db6e34eSqz150045 } 3237db6e34eSqz150045 if (default_input == B_TRUE) 3247db6e34eSqz150045 layout_num = DEFAULT_KBD_LAYOUT; 3257db6e34eSqz150045 else 3267db6e34eSqz150045 layout_num = layout_numbers[--input_num]; 3277db6e34eSqz150045 } 3287db6e34eSqz150045 3297db6e34eSqz150045 if ((error = set_layout(kbd, layout_num)) != 0) 3307db6e34eSqz150045 return (error); 3317db6e34eSqz150045 3327c478bd9Sstevel@tonic-gate return (0); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * this routine resets the state of the keyboard as if power-up 3377c478bd9Sstevel@tonic-gate */ 3387c478bd9Sstevel@tonic-gate static void 3397c478bd9Sstevel@tonic-gate reset(int kbd) 3407c478bd9Sstevel@tonic-gate { 3417c478bd9Sstevel@tonic-gate int cmd; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate cmd = KBD_CMD_RESET; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCCMD, &cmd)) { 3467c478bd9Sstevel@tonic-gate perror("kbd: ioctl error"); 3477c478bd9Sstevel@tonic-gate exit(1); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* 3537c478bd9Sstevel@tonic-gate * this routine gets the type of the keyboard being used 3547c478bd9Sstevel@tonic-gate */ 3557c478bd9Sstevel@tonic-gate static void 3567c478bd9Sstevel@tonic-gate get_type(int kbd) 3577c478bd9Sstevel@tonic-gate { 3587c478bd9Sstevel@tonic-gate int kbd_type; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCTYPE, &kbd_type)) { 3617c478bd9Sstevel@tonic-gate perror("ioctl (kbd type)"); 3627c478bd9Sstevel@tonic-gate exit(1); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate switch (kbd_type) { 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate case KB_SUN3: 3687c478bd9Sstevel@tonic-gate (void) printf("Type 3 Sun keyboard\n"); 3697c478bd9Sstevel@tonic-gate break; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate case KB_SUN4: 3727c478bd9Sstevel@tonic-gate (void) printf("Type 4 Sun keyboard\n"); 3737c478bd9Sstevel@tonic-gate break; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate case KB_ASCII: 3767c478bd9Sstevel@tonic-gate (void) printf("ASCII\n"); 3777c478bd9Sstevel@tonic-gate break; 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate case KB_PC: 3807c478bd9Sstevel@tonic-gate (void) printf("PC\n"); 3817c478bd9Sstevel@tonic-gate break; 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate case KB_USB: 3847c478bd9Sstevel@tonic-gate (void) printf("USB keyboard\n"); 3857c478bd9Sstevel@tonic-gate break; 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate default: 3887c478bd9Sstevel@tonic-gate (void) printf("Unknown keyboard type\n"); 3897c478bd9Sstevel@tonic-gate break; 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate /* 3947c478bd9Sstevel@tonic-gate * this routine gets the layout of the keyboard being used 3957c478bd9Sstevel@tonic-gate * also, included the autorepeat delay and rate being used 3967c478bd9Sstevel@tonic-gate */ 3977c478bd9Sstevel@tonic-gate static void 3987c478bd9Sstevel@tonic-gate get_layout(int kbd) 3997c478bd9Sstevel@tonic-gate { 4007c478bd9Sstevel@tonic-gate int kbd_type; 4017c478bd9Sstevel@tonic-gate int kbd_layout; 4027c478bd9Sstevel@tonic-gate /* these two variables are used for getting delay&rate */ 4037c478bd9Sstevel@tonic-gate int delay, rate; 4047c478bd9Sstevel@tonic-gate delay = rate = 0; 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCTYPE, &kbd_type)) { 4077c478bd9Sstevel@tonic-gate perror("ioctl (kbd type)"); 4087c478bd9Sstevel@tonic-gate exit(1); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCLAYOUT, &kbd_layout)) { 4127c478bd9Sstevel@tonic-gate perror("ioctl (kbd layout)"); 4137c478bd9Sstevel@tonic-gate exit(1); 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate (void) printf("type=%d\nlayout=%d (0x%.2x)\n", 4177c478bd9Sstevel@tonic-gate kbd_type, kbd_layout, kbd_layout); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* below code is used to get the autorepeat delay and rate */ 4207c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCGRPTDELAY, &delay)) { 4217c478bd9Sstevel@tonic-gate perror("ioctl (kbd get repeat delay)"); 4227c478bd9Sstevel@tonic-gate exit(1); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCGRPTRATE, &rate)) { 4267c478bd9Sstevel@tonic-gate perror("ioctl (kbd get repeat rate)"); 4277c478bd9Sstevel@tonic-gate exit(1); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate (void) printf("delay(ms)=%d\n", delay); 4317c478bd9Sstevel@tonic-gate (void) printf("rate(ms)=%d\n", rate); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate /* 4357c478bd9Sstevel@tonic-gate * this routine enables or disables clicking of the keyboard 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate static int 4387c478bd9Sstevel@tonic-gate click(char *copt, int kbd) 4397c478bd9Sstevel@tonic-gate { 4407c478bd9Sstevel@tonic-gate int cmd; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate if (strcmp(copt, "on") == 0) 4437c478bd9Sstevel@tonic-gate cmd = KBD_CMD_CLICK; 4447c478bd9Sstevel@tonic-gate else if (strcmp(copt, "off") == 0) 4457c478bd9Sstevel@tonic-gate cmd = KBD_CMD_NOCLICK; 4467c478bd9Sstevel@tonic-gate else { 4477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "wrong option -- %s\n", copt); 4487c478bd9Sstevel@tonic-gate usage(); 4497c478bd9Sstevel@tonic-gate return (1); 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCCMD, &cmd)) { 4537c478bd9Sstevel@tonic-gate perror("kbd ioctl (keyclick)"); 4547c478bd9Sstevel@tonic-gate return (1); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate return (0); 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate /* 4607c478bd9Sstevel@tonic-gate * this routine enables/disables/sets BRK or abort sequence feature 4617c478bd9Sstevel@tonic-gate */ 4627c478bd9Sstevel@tonic-gate static int 4637c478bd9Sstevel@tonic-gate abort_enable(char *aopt, int kbd) 4647c478bd9Sstevel@tonic-gate { 4657c478bd9Sstevel@tonic-gate int enable; 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate if (strcmp(aopt, "alternate") == 0) 4687c478bd9Sstevel@tonic-gate enable = KIOCABORTALTERNATE; 4697c478bd9Sstevel@tonic-gate else if (strcmp(aopt, "enable") == 0) 4707c478bd9Sstevel@tonic-gate enable = KIOCABORTENABLE; 4717c478bd9Sstevel@tonic-gate else if (strcmp(aopt, "disable") == 0) 4727c478bd9Sstevel@tonic-gate enable = KIOCABORTDISABLE; 4737c478bd9Sstevel@tonic-gate else { 4747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "wrong option -- %s\n", aopt); 4757c478bd9Sstevel@tonic-gate usage(); 4767c478bd9Sstevel@tonic-gate return (1); 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCSKABORTEN, &enable)) { 4807c478bd9Sstevel@tonic-gate perror("kbd ioctl (abort enable)"); 4817c478bd9Sstevel@tonic-gate return (1); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate return (0); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* 4877c478bd9Sstevel@tonic-gate * this routine set autorepeat delay 4887c478bd9Sstevel@tonic-gate */ 4897c478bd9Sstevel@tonic-gate static int 4907c478bd9Sstevel@tonic-gate set_repeat_delay(char *delay_str, int kbd) 4917c478bd9Sstevel@tonic-gate { 4927c478bd9Sstevel@tonic-gate int delay = atoi(delay_str); 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate /* 4957c478bd9Sstevel@tonic-gate * The error message depends on the different inputs. 4967c478bd9Sstevel@tonic-gate * a. the input is a invalid integer(unit in ms) 4977c478bd9Sstevel@tonic-gate * b. the input is a integer less than the minimal delay setting. 4987c478bd9Sstevel@tonic-gate * The condition (a) has been covered by main function and set_default 4997c478bd9Sstevel@tonic-gate * function. 5007c478bd9Sstevel@tonic-gate */ 5017c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCSRPTDELAY, &delay) == -1) { 5027c478bd9Sstevel@tonic-gate if (delay < KIOCRPTDELAY_MIN) 5037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "kbd: specified delay %d is " 5047c478bd9Sstevel@tonic-gate "less than minimum %d\n", delay, KIOCRPTDELAY_MIN); 5057c478bd9Sstevel@tonic-gate else 5067c478bd9Sstevel@tonic-gate perror("kbd: set repeat delay"); 5077c478bd9Sstevel@tonic-gate return (1); 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate return (0); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate /* 5147c478bd9Sstevel@tonic-gate * this routine set autorepeat rate 5157c478bd9Sstevel@tonic-gate */ 5167c478bd9Sstevel@tonic-gate static int 5177c478bd9Sstevel@tonic-gate set_repeat_rate(char *rate_str, int kbd) 5187c478bd9Sstevel@tonic-gate { 5197c478bd9Sstevel@tonic-gate int rate = atoi(rate_str); 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* 5227c478bd9Sstevel@tonic-gate * The error message depends on the different inputs. 5237c478bd9Sstevel@tonic-gate * a. the input is a invalid integer(unit in ms) 5247c478bd9Sstevel@tonic-gate * b. the input is a integer less than the minimal rate setting. 5257c478bd9Sstevel@tonic-gate * The condition (a) has been covered by main function and set_default 5267c478bd9Sstevel@tonic-gate * function. 5277c478bd9Sstevel@tonic-gate */ 5287c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCSRPTRATE, &rate) == -1) { 5297c478bd9Sstevel@tonic-gate if (rate < KIOCRPTRATE_MIN) 5307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "kbd: specified rate %d is " 5317c478bd9Sstevel@tonic-gate "less than minimum %d\n", rate, KIOCRPTRATE_MIN); 5327c478bd9Sstevel@tonic-gate else 5337c478bd9Sstevel@tonic-gate perror("kbd: set repeat rate"); 5347c478bd9Sstevel@tonic-gate return (1); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate return (0); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate #define BAD_DEFAULT "kbd: bad default value for %s: %s\n" 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate static void 5437c478bd9Sstevel@tonic-gate kbd_defaults(int kbd) 5447c478bd9Sstevel@tonic-gate { 5457c478bd9Sstevel@tonic-gate char *p; 5467db6e34eSqz150045 int layout_num; 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if (defopen(DEF_FILE) != 0) { 5497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Can't open default file: %s\n", 5507c478bd9Sstevel@tonic-gate DEF_FILE); 5517c478bd9Sstevel@tonic-gate exit(1); 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate p = defread(DEF_CLICK); 5557c478bd9Sstevel@tonic-gate if (p != NULL) { 5567c478bd9Sstevel@tonic-gate /* 5577c478bd9Sstevel@tonic-gate * KEYCLICK must equal "on" or "off" 5587c478bd9Sstevel@tonic-gate */ 5597c478bd9Sstevel@tonic-gate if ((strcmp(p, "on") == 0) || (strcmp(p, "off") == 0)) 5607c478bd9Sstevel@tonic-gate (void) click(p, kbd); 5617c478bd9Sstevel@tonic-gate else 5627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, BAD_DEFAULT, DEF_CLICK, p); 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate p = defread(DEF_ABORT); 5667c478bd9Sstevel@tonic-gate if (p != NULL) { 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * ABORT must equal "enable", "disable" or "alternate" 5697c478bd9Sstevel@tonic-gate */ 5707c478bd9Sstevel@tonic-gate if ((strcmp(p, "enable") == 0) || 5717c478bd9Sstevel@tonic-gate (strcmp(p, "alternate") == 0) || 5727c478bd9Sstevel@tonic-gate (strcmp(p, "disable") == 0)) 5737c478bd9Sstevel@tonic-gate (void) abort_enable(p, kbd); 5747c478bd9Sstevel@tonic-gate else 5757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, BAD_DEFAULT, DEF_ABORT, p); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate p = defread(DEF_RPTDELAY); 5797c478bd9Sstevel@tonic-gate if (p != NULL) { 5807c478bd9Sstevel@tonic-gate /* 5817c478bd9Sstevel@tonic-gate * REPEAT_DELAY unit in ms 5827c478bd9Sstevel@tonic-gate */ 5837c478bd9Sstevel@tonic-gate if (atoi(p) > 0) 5847c478bd9Sstevel@tonic-gate (void) set_repeat_delay(p, kbd); 5857c478bd9Sstevel@tonic-gate else 5867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, BAD_DEFAULT, DEF_RPTDELAY, p); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate p = defread(DEF_RPTRATE); 5907c478bd9Sstevel@tonic-gate if (p != NULL) { 5917c478bd9Sstevel@tonic-gate /* 5927c478bd9Sstevel@tonic-gate * REPEAT_RATE unit in ms 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate if (atoi(p) > 0) 5957c478bd9Sstevel@tonic-gate (void) set_repeat_rate(p, kbd); 5967c478bd9Sstevel@tonic-gate else 5977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, BAD_DEFAULT, DEF_RPTRATE, p); 5987c478bd9Sstevel@tonic-gate } 5997db6e34eSqz150045 6007db6e34eSqz150045 p = defread(DEF_LAYOUT); 6017db6e34eSqz150045 if (p != NULL) { 6027db6e34eSqz150045 /* 6037db6e34eSqz150045 * LAYOUT must be one of the layouts supported in kbd_layouts 6047db6e34eSqz150045 */ 6057db6e34eSqz150045 if (get_layouts() != 0) 6067db6e34eSqz150045 return; 6077db6e34eSqz150045 6087db6e34eSqz150045 if ((layout_num = get_layout_number(p)) == -1) { 6097db6e34eSqz150045 (void) fprintf(stderr, BAD_DEFAULT, DEF_LAYOUT, p); 6107db6e34eSqz150045 return; 6117db6e34eSqz150045 } 6127db6e34eSqz150045 6137db6e34eSqz150045 (void) set_layout(kbd, layout_num); 6147db6e34eSqz150045 } 6157db6e34eSqz150045 } 6167db6e34eSqz150045 6177db6e34eSqz150045 static int 6187db6e34eSqz150045 get_layout_number(char *layout) 6197db6e34eSqz150045 { 6207db6e34eSqz150045 int i; 6217db6e34eSqz150045 int layout_number = -1; 6227db6e34eSqz150045 6237db6e34eSqz150045 for (i = 0; i < layout_count; i ++) { 6247db6e34eSqz150045 if (strcmp(layout, layout_names[i]) == 0) { 6257db6e34eSqz150045 layout_number = layout_numbers[i]; 6267db6e34eSqz150045 break; 6277db6e34eSqz150045 } 6287db6e34eSqz150045 } 6297db6e34eSqz150045 6307db6e34eSqz150045 return (layout_number); 6317db6e34eSqz150045 } 6327db6e34eSqz150045 6337db6e34eSqz150045 static int 6347db6e34eSqz150045 get_layouts() 6357db6e34eSqz150045 { 6367db6e34eSqz150045 FILE *stream; 6377db6e34eSqz150045 char buffer[MAX_LINE_SIZE]; 6387db6e34eSqz150045 char *result = NULL; 6397db6e34eSqz150045 int i = 0; 6407db6e34eSqz150045 char *tmpbuf; 6417db6e34eSqz150045 6427db6e34eSqz150045 if ((stream = fopen(KBD_LAYOUT_FILE, "r")) == 0) { 6437db6e34eSqz150045 perror(KBD_LAYOUT_FILE); 6447db6e34eSqz150045 return (1); 6457db6e34eSqz150045 } 6467db6e34eSqz150045 6477db6e34eSqz150045 while ((fgets(buffer, MAX_LINE_SIZE, stream) != NULL) && 6487db6e34eSqz150045 (i < MAX_LAYOUT_NUM)) { 6497db6e34eSqz150045 if (buffer[0] == '#') 6507db6e34eSqz150045 continue; 6517db6e34eSqz150045 if ((result = strtok(buffer, "=")) == NULL) 6527db6e34eSqz150045 continue; 6537db6e34eSqz150045 if ((tmpbuf = strdup(result)) != NULL) { 6547db6e34eSqz150045 layout_names[i] = tmpbuf; 6557db6e34eSqz150045 } else { 6567db6e34eSqz150045 perror("out of memory getting layout names"); 6577db6e34eSqz150045 return (1); 6587db6e34eSqz150045 } 6597db6e34eSqz150045 if ((result = strtok(NULL, "\n")) == NULL) 6607db6e34eSqz150045 continue; 6617db6e34eSqz150045 layout_numbers[i] = atoi(result); 6627db6e34eSqz150045 if (strcmp(tmpbuf, "US-English") == 0) 6637db6e34eSqz150045 default_layout_number = i; 6647db6e34eSqz150045 i++; 6657db6e34eSqz150045 } 6667db6e34eSqz150045 layout_count = i; 6677db6e34eSqz150045 6687db6e34eSqz150045 return (0); 6697db6e34eSqz150045 } 6707db6e34eSqz150045 6717db6e34eSqz150045 /* 6727db6e34eSqz150045 * this routine sets the layout of the keyboard being used 6737db6e34eSqz150045 */ 6747db6e34eSqz150045 static int 6757db6e34eSqz150045 set_layout(int kbd, int layout_num) 6767db6e34eSqz150045 { 6777db6e34eSqz150045 6787db6e34eSqz150045 if (ioctl(kbd, KIOCSLAYOUT, layout_num)) { 6797db6e34eSqz150045 perror("ioctl (set kbd layout)"); 6807db6e34eSqz150045 return (1); 6817db6e34eSqz150045 } 6827db6e34eSqz150045 6837db6e34eSqz150045 return (0); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate static char *usage1 = "kbd [-r] [-t] [-l] [-a enable|disable|alternate]"; 6877c478bd9Sstevel@tonic-gate static char *usage2 = " [-c on|off][-D delay][-R rate][-d keyboard device]"; 6887c478bd9Sstevel@tonic-gate static char *usage3 = "kbd -i [-d keyboard device]"; 6897db6e34eSqz150045 static char *usage4 = "kbd -s [language]"; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate static void 6927c478bd9Sstevel@tonic-gate usage(void) 6937c478bd9Sstevel@tonic-gate { 6947db6e34eSqz150045 (void) fprintf(stderr, "Usage:\t%s\n\t%s\n\t%s\n\t%s\n", usage1, usage2, 6957db6e34eSqz150045 usage3, usage4); 6967c478bd9Sstevel@tonic-gate } 697