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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*7db6e34eSqz150045 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * Usage: kbd [-r] [-t] [-l] [-i] [-c on|off] [-a enable|disable|alternate] 327c478bd9Sstevel@tonic-gate * [-d keyboard device] 337c478bd9Sstevel@tonic-gate * -r reset the keyboard as if power-up 347c478bd9Sstevel@tonic-gate * -t return the type of the keyboard being used 357c478bd9Sstevel@tonic-gate * -l return the layout of the keyboard being used, 367c478bd9Sstevel@tonic-gate * and the Autorepeat settings 377c478bd9Sstevel@tonic-gate * -i read in the default configuration file 387c478bd9Sstevel@tonic-gate * -c on|off turn on|off clicking 397c478bd9Sstevel@tonic-gate * -a enable|disable|alternate sets abort sequence 407c478bd9Sstevel@tonic-gate * -D autorepeat delay sets autorepeat dealy, unit in ms 417c478bd9Sstevel@tonic-gate * -R autorepeat rate sets autorepeat rate, unit in ms 427c478bd9Sstevel@tonic-gate * -d keyboard device chooses the kbd device, default /dev/kbd. 43*7db6e34eSqz150045 * -s keyboard layout sets keyboard layout 447c478bd9Sstevel@tonic-gate */ 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #include <sys/types.h> 477c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 487c478bd9Sstevel@tonic-gate #include <sys/kbio.h> 497c478bd9Sstevel@tonic-gate #include <sys/kbd.h> 507c478bd9Sstevel@tonic-gate #include <stdio.h> 517c478bd9Sstevel@tonic-gate #include <fcntl.h> 527c478bd9Sstevel@tonic-gate #include <deflt.h> 537c478bd9Sstevel@tonic-gate #include <unistd.h> 547c478bd9Sstevel@tonic-gate #include <string.h> 557c478bd9Sstevel@tonic-gate #include <stdlib.h> 567c478bd9Sstevel@tonic-gate #include <stropts.h> 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #define KBD_DEVICE "/dev/kbd" /* default keyboard device */ 597c478bd9Sstevel@tonic-gate #define DEF_FILE "/etc/default/kbd" /* kbd defaults file */ 607c478bd9Sstevel@tonic-gate #define DEF_ABORT "KEYBOARD_ABORT=" 617c478bd9Sstevel@tonic-gate #define DEF_CLICK "KEYCLICK=" 627c478bd9Sstevel@tonic-gate #define DEF_RPTDELAY "REPEAT_DELAY=" 637c478bd9Sstevel@tonic-gate #define DEF_RPTRATE "REPEAT_RATE=" 64*7db6e34eSqz150045 #define DEF_LAYOUT "LAYOUT=" 65*7db6e34eSqz150045 66*7db6e34eSqz150045 #define KBD_LAYOUT_FILE "/usr/share/lib/keytables/type_6/kbd_layouts" 67*7db6e34eSqz150045 #define MAX_LAYOUT_NUM 128 68*7db6e34eSqz150045 #define MAX_LINE_SIZE 256 69*7db6e34eSqz150045 #define DEFAULT_KBD_LAYOUT 33 70*7db6e34eSqz150045 71*7db6e34eSqz150045 char *layout_names[MAX_LAYOUT_NUM]; 72*7db6e34eSqz150045 int layout_numbers[MAX_LAYOUT_NUM]; 73*7db6e34eSqz150045 static int layout_count; 74*7db6e34eSqz150045 static int default_layout_number = 0; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static void reset(int); 777c478bd9Sstevel@tonic-gate static void get_type(int); 787c478bd9Sstevel@tonic-gate static void get_layout(int); 797c478bd9Sstevel@tonic-gate static void kbd_defaults(int); 807c478bd9Sstevel@tonic-gate static void usage(void); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate static int click(char *, int); 837c478bd9Sstevel@tonic-gate static int abort_enable(char *, int); 847c478bd9Sstevel@tonic-gate static int set_repeat_delay(char *, int); 857c478bd9Sstevel@tonic-gate static int set_repeat_rate(char *, int); 867c478bd9Sstevel@tonic-gate 87*7db6e34eSqz150045 static int get_layout_number(char *); 88*7db6e34eSqz150045 static int set_layout(int, int); 89*7db6e34eSqz150045 static int get_layouts(void); 90*7db6e34eSqz150045 static int set_kbd_layout(int, char *); 91*7db6e34eSqz150045 927c478bd9Sstevel@tonic-gate int 937c478bd9Sstevel@tonic-gate main(int argc, char **argv) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate int c, error; 967c478bd9Sstevel@tonic-gate int rflag, tflag, lflag, cflag, dflag, aflag, iflag, errflag, 97*7db6e34eSqz150045 Dflag, Rflag, rtlacDRflag, sflag; 98*7db6e34eSqz150045 char *copt, *aopt, *delay, *rate, *layout_name; 997c478bd9Sstevel@tonic-gate char *kbdname = KBD_DEVICE; 1007c478bd9Sstevel@tonic-gate int kbd; 1017c478bd9Sstevel@tonic-gate extern char *optarg; 1027c478bd9Sstevel@tonic-gate extern int optind; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate rflag = tflag = cflag = dflag = aflag = iflag = errflag = lflag = 105*7db6e34eSqz150045 Dflag = Rflag = sflag = 0; 1067c478bd9Sstevel@tonic-gate copt = aopt = (char *)0; 1077c478bd9Sstevel@tonic-gate 108*7db6e34eSqz150045 while ((c = getopt(argc, argv, "rtlisc:a:d:D:R:")) != EOF) { 1097c478bd9Sstevel@tonic-gate switch (c) { 1107c478bd9Sstevel@tonic-gate case 'r': 1117c478bd9Sstevel@tonic-gate rflag++; 1127c478bd9Sstevel@tonic-gate break; 1137c478bd9Sstevel@tonic-gate case 't': 1147c478bd9Sstevel@tonic-gate tflag++; 1157c478bd9Sstevel@tonic-gate break; 1167c478bd9Sstevel@tonic-gate case 'l': 1177c478bd9Sstevel@tonic-gate lflag++; 1187c478bd9Sstevel@tonic-gate break; 1197c478bd9Sstevel@tonic-gate case 'i': 1207c478bd9Sstevel@tonic-gate iflag++; 1217c478bd9Sstevel@tonic-gate break; 122*7db6e34eSqz150045 case 's': 123*7db6e34eSqz150045 sflag++; 124*7db6e34eSqz150045 break; 1257c478bd9Sstevel@tonic-gate case 'c': 1267c478bd9Sstevel@tonic-gate copt = optarg; 1277c478bd9Sstevel@tonic-gate cflag++; 1287c478bd9Sstevel@tonic-gate break; 1297c478bd9Sstevel@tonic-gate case 'a': 1307c478bd9Sstevel@tonic-gate aopt = optarg; 1317c478bd9Sstevel@tonic-gate aflag++; 1327c478bd9Sstevel@tonic-gate break; 1337c478bd9Sstevel@tonic-gate case 'd': 1347c478bd9Sstevel@tonic-gate kbdname = optarg; 1357c478bd9Sstevel@tonic-gate dflag++; 1367c478bd9Sstevel@tonic-gate break; 1377c478bd9Sstevel@tonic-gate case 'D': 1387c478bd9Sstevel@tonic-gate delay = optarg; 1397c478bd9Sstevel@tonic-gate Dflag++; 1407c478bd9Sstevel@tonic-gate break; 1417c478bd9Sstevel@tonic-gate case 'R': 1427c478bd9Sstevel@tonic-gate rate = optarg; 1437c478bd9Sstevel@tonic-gate Rflag++; 1447c478bd9Sstevel@tonic-gate break; 1457c478bd9Sstevel@tonic-gate case '?': 1467c478bd9Sstevel@tonic-gate errflag++; 1477c478bd9Sstevel@tonic-gate break; 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * Check for valid arguments: 1537c478bd9Sstevel@tonic-gate * 1547c478bd9Sstevel@tonic-gate * If argument parsing failed or if there are left-over 155*7db6e34eSqz150045 * command line arguments(except -s option), then we're done now. 1567c478bd9Sstevel@tonic-gate */ 157*7db6e34eSqz150045 if (errflag != 0 || ((sflag == 0) && (argc != optind))) { 1587c478bd9Sstevel@tonic-gate usage(); 1597c478bd9Sstevel@tonic-gate exit(1); 1607c478bd9Sstevel@tonic-gate } 161*7db6e34eSqz150045 1627c478bd9Sstevel@tonic-gate /* 163*7db6e34eSqz150045 * kbd requires that the user specify either "-i" or "-s" or at 164*7db6e34eSqz150045 * least one of -[rtlacDR]. The "-d" option is, well, optional. 165*7db6e34eSqz150045 * We don't care if it's there or not. 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate rtlacDRflag = rflag + tflag + lflag + aflag + cflag + Dflag + Rflag; 168*7db6e34eSqz150045 if (!((iflag != 0 && sflag == 0 && rtlacDRflag == 0) || 169*7db6e34eSqz150045 (iflag == 0 && sflag != 0 && dflag == 0 && rtlacDRflag == 0) || 170*7db6e34eSqz150045 (iflag == 0 && sflag == 0 && rtlacDRflag != 0))) { 1717c478bd9Sstevel@tonic-gate usage(); 1727c478bd9Sstevel@tonic-gate exit(1); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate if (Dflag && atoi(delay) <= 0) { 1767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Invalid arguments: -D %s\n", delay); 1777c478bd9Sstevel@tonic-gate usage(); 1787c478bd9Sstevel@tonic-gate exit(1); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate if (Rflag && atoi(rate) <= 0) { 1827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Invalid arguments: -R %s\n", rate); 1837c478bd9Sstevel@tonic-gate usage(); 1847c478bd9Sstevel@tonic-gate exit(1); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate /* 1887c478bd9Sstevel@tonic-gate * Open the keyboard device 1897c478bd9Sstevel@tonic-gate */ 1907c478bd9Sstevel@tonic-gate if ((kbd = open(kbdname, O_RDWR)) < 0) { 1917c478bd9Sstevel@tonic-gate perror("opening the keyboard"); 1927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "kbd: Cannot open %s\n", kbdname); 1937c478bd9Sstevel@tonic-gate exit(1); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate if (iflag) { 1977c478bd9Sstevel@tonic-gate kbd_defaults(kbd); 1987c478bd9Sstevel@tonic-gate exit(0); /* A mutually exclusive option */ 1997c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate if (tflag) 2037c478bd9Sstevel@tonic-gate get_type(kbd); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate if (lflag) 2067c478bd9Sstevel@tonic-gate get_layout(kbd); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate if (cflag && (error = click(copt, kbd)) != 0) 2097c478bd9Sstevel@tonic-gate exit(error); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate if (rflag) 2127c478bd9Sstevel@tonic-gate reset(kbd); 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate if (aflag && (error = abort_enable(aopt, kbd)) != 0) 2157c478bd9Sstevel@tonic-gate exit(error); 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (Dflag && (error = set_repeat_delay(delay, kbd)) != 0) 2187c478bd9Sstevel@tonic-gate exit(error); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate if (Rflag && (error = set_repeat_rate(rate, kbd)) != 0) 2217c478bd9Sstevel@tonic-gate exit(error); 2227c478bd9Sstevel@tonic-gate 223*7db6e34eSqz150045 if (sflag) { 224*7db6e34eSqz150045 if (argc == optind) { 225*7db6e34eSqz150045 layout_name = NULL; 226*7db6e34eSqz150045 } else if (argc == (optind + 1)) { 227*7db6e34eSqz150045 layout_name = argv[optind]; 228*7db6e34eSqz150045 } else { 229*7db6e34eSqz150045 usage(); 230*7db6e34eSqz150045 exit(1); 231*7db6e34eSqz150045 } 232*7db6e34eSqz150045 233*7db6e34eSqz150045 if ((error = set_kbd_layout(kbd, layout_name)) != 0) 234*7db6e34eSqz150045 exit(error); 235*7db6e34eSqz150045 } 236*7db6e34eSqz150045 237*7db6e34eSqz150045 return (0); 238*7db6e34eSqz150045 } 239*7db6e34eSqz150045 240*7db6e34eSqz150045 /* 241*7db6e34eSqz150045 * this routine gets the type of the keyboard being used 242*7db6e34eSqz150045 */ 243*7db6e34eSqz150045 static int 244*7db6e34eSqz150045 set_kbd_layout(int kbd, char *layout_name) 245*7db6e34eSqz150045 { 246*7db6e34eSqz150045 int layout_num; 247*7db6e34eSqz150045 int error = 1; 248*7db6e34eSqz150045 249*7db6e34eSqz150045 /* get the language info from the layouts file */ 250*7db6e34eSqz150045 if (get_layouts() != 0) 251*7db6e34eSqz150045 return (error); 252*7db6e34eSqz150045 253*7db6e34eSqz150045 if (layout_name != NULL) { 254*7db6e34eSqz150045 if ((layout_num = get_layout_number(layout_name)) == -1) { 255*7db6e34eSqz150045 (void) fprintf(stderr, "%s: unknown layout name\n" 256*7db6e34eSqz150045 "Please refer to 'kbd -s' to get the " 257*7db6e34eSqz150045 "supported layouts.\n", layout_name); 258*7db6e34eSqz150045 return (error); 259*7db6e34eSqz150045 } 260*7db6e34eSqz150045 } else { 261*7db6e34eSqz150045 int i, j, print_cnt, input_num; 262*7db6e34eSqz150045 boolean_t input_right = B_TRUE; 263*7db6e34eSqz150045 boolean_t default_input = B_FALSE; 264*7db6e34eSqz150045 char input[8]; /* 8 chars is enough for numbers */ 265*7db6e34eSqz150045 266*7db6e34eSqz150045 print_cnt = (layout_count % 2) ? 267*7db6e34eSqz150045 layout_count/2+1 : layout_count/2; 268*7db6e34eSqz150045 269*7db6e34eSqz150045 for (i = 1; i <= print_cnt; i++) { 270*7db6e34eSqz150045 (void) printf("%2d. %-30s", i, 271*7db6e34eSqz150045 layout_names[i-1]); 272*7db6e34eSqz150045 j = i + print_cnt; 273*7db6e34eSqz150045 if (j <= layout_count) { 274*7db6e34eSqz150045 (void) printf("%-2d. %-30s\n", j, 275*7db6e34eSqz150045 layout_names[j-1]); 276*7db6e34eSqz150045 } 277*7db6e34eSqz150045 } 278*7db6e34eSqz150045 (void) printf("\nTo select the keyboard layout, enter" 279*7db6e34eSqz150045 " a number [default %d]:", 280*7db6e34eSqz150045 default_layout_number+1); 281*7db6e34eSqz150045 282*7db6e34eSqz150045 for (;;) { 283*7db6e34eSqz150045 if (input_right == B_FALSE) 284*7db6e34eSqz150045 (void) printf("Invalid input. Please " 285*7db6e34eSqz150045 "input a number (1,2,...):"); 286*7db6e34eSqz150045 (void) memset(input, 0, 8); 287*7db6e34eSqz150045 (void) fflush(stdin); 288*7db6e34eSqz150045 (void) fgets(input, 8, stdin); 289*7db6e34eSqz150045 if (strlen(input) > 4) { 290*7db6e34eSqz150045 input_right = B_FALSE; 291*7db6e34eSqz150045 continue; 292*7db6e34eSqz150045 } 293*7db6e34eSqz150045 if (input[0] == '\n') { 294*7db6e34eSqz150045 default_input = B_TRUE; 295*7db6e34eSqz150045 break; 296*7db6e34eSqz150045 } 297*7db6e34eSqz150045 input_right = B_TRUE; 298*7db6e34eSqz150045 /* check if the inputs are numbers 0~9 */ 299*7db6e34eSqz150045 for (i = 0; i < (strlen(input) - 1); i++) { 300*7db6e34eSqz150045 if ((input[i] < '0') || 301*7db6e34eSqz150045 (input[i] > '9')) { 302*7db6e34eSqz150045 input_right = B_FALSE; 303*7db6e34eSqz150045 break; 304*7db6e34eSqz150045 } 305*7db6e34eSqz150045 } 306*7db6e34eSqz150045 if (input_right == B_FALSE) 307*7db6e34eSqz150045 continue; 308*7db6e34eSqz150045 input_num = atoi(input); 309*7db6e34eSqz150045 if ((input_num > 0) && 310*7db6e34eSqz150045 (input_num <= layout_count)) 311*7db6e34eSqz150045 break; 312*7db6e34eSqz150045 else 313*7db6e34eSqz150045 input_right = B_FALSE; 314*7db6e34eSqz150045 } 315*7db6e34eSqz150045 if (default_input == B_TRUE) 316*7db6e34eSqz150045 layout_num = DEFAULT_KBD_LAYOUT; 317*7db6e34eSqz150045 else 318*7db6e34eSqz150045 layout_num = layout_numbers[--input_num]; 319*7db6e34eSqz150045 } 320*7db6e34eSqz150045 321*7db6e34eSqz150045 if ((error = set_layout(kbd, layout_num)) != 0) 322*7db6e34eSqz150045 return (error); 323*7db6e34eSqz150045 3247c478bd9Sstevel@tonic-gate return (0); 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate /* 3287c478bd9Sstevel@tonic-gate * this routine resets the state of the keyboard as if power-up 3297c478bd9Sstevel@tonic-gate */ 3307c478bd9Sstevel@tonic-gate static void 3317c478bd9Sstevel@tonic-gate reset(int kbd) 3327c478bd9Sstevel@tonic-gate { 3337c478bd9Sstevel@tonic-gate int cmd; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate cmd = KBD_CMD_RESET; 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCCMD, &cmd)) { 3387c478bd9Sstevel@tonic-gate perror("kbd: ioctl error"); 3397c478bd9Sstevel@tonic-gate exit(1); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* 3457c478bd9Sstevel@tonic-gate * this routine gets the type of the keyboard being used 3467c478bd9Sstevel@tonic-gate */ 3477c478bd9Sstevel@tonic-gate static void 3487c478bd9Sstevel@tonic-gate get_type(int kbd) 3497c478bd9Sstevel@tonic-gate { 3507c478bd9Sstevel@tonic-gate int kbd_type; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCTYPE, &kbd_type)) { 3537c478bd9Sstevel@tonic-gate perror("ioctl (kbd type)"); 3547c478bd9Sstevel@tonic-gate exit(1); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate switch (kbd_type) { 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate case KB_SUN3: 3607c478bd9Sstevel@tonic-gate (void) printf("Type 3 Sun keyboard\n"); 3617c478bd9Sstevel@tonic-gate break; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate case KB_SUN4: 3647c478bd9Sstevel@tonic-gate (void) printf("Type 4 Sun keyboard\n"); 3657c478bd9Sstevel@tonic-gate break; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate case KB_ASCII: 3687c478bd9Sstevel@tonic-gate (void) printf("ASCII\n"); 3697c478bd9Sstevel@tonic-gate break; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate case KB_PC: 3727c478bd9Sstevel@tonic-gate (void) printf("PC\n"); 3737c478bd9Sstevel@tonic-gate break; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate case KB_USB: 3767c478bd9Sstevel@tonic-gate (void) printf("USB keyboard\n"); 3777c478bd9Sstevel@tonic-gate break; 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate default: 3807c478bd9Sstevel@tonic-gate (void) printf("Unknown keyboard type\n"); 3817c478bd9Sstevel@tonic-gate break; 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * this routine gets the layout of the keyboard being used 3877c478bd9Sstevel@tonic-gate * also, included the autorepeat delay and rate being used 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate static void 3907c478bd9Sstevel@tonic-gate get_layout(int kbd) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate int kbd_type; 3937c478bd9Sstevel@tonic-gate int kbd_layout; 3947c478bd9Sstevel@tonic-gate /* these two variables are used for getting delay&rate */ 3957c478bd9Sstevel@tonic-gate int delay, rate; 3967c478bd9Sstevel@tonic-gate delay = rate = 0; 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCTYPE, &kbd_type)) { 3997c478bd9Sstevel@tonic-gate perror("ioctl (kbd type)"); 4007c478bd9Sstevel@tonic-gate exit(1); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCLAYOUT, &kbd_layout)) { 4047c478bd9Sstevel@tonic-gate perror("ioctl (kbd layout)"); 4057c478bd9Sstevel@tonic-gate exit(1); 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate (void) printf("type=%d\nlayout=%d (0x%.2x)\n", 4097c478bd9Sstevel@tonic-gate kbd_type, kbd_layout, kbd_layout); 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate /* below code is used to get the autorepeat delay and rate */ 4127c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCGRPTDELAY, &delay)) { 4137c478bd9Sstevel@tonic-gate perror("ioctl (kbd get repeat delay)"); 4147c478bd9Sstevel@tonic-gate exit(1); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCGRPTRATE, &rate)) { 4187c478bd9Sstevel@tonic-gate perror("ioctl (kbd get repeat rate)"); 4197c478bd9Sstevel@tonic-gate exit(1); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate (void) printf("delay(ms)=%d\n", delay); 4237c478bd9Sstevel@tonic-gate (void) printf("rate(ms)=%d\n", rate); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* 4277c478bd9Sstevel@tonic-gate * this routine enables or disables clicking of the keyboard 4287c478bd9Sstevel@tonic-gate */ 4297c478bd9Sstevel@tonic-gate static int 4307c478bd9Sstevel@tonic-gate click(char *copt, int kbd) 4317c478bd9Sstevel@tonic-gate { 4327c478bd9Sstevel@tonic-gate int cmd; 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate if (strcmp(copt, "on") == 0) 4357c478bd9Sstevel@tonic-gate cmd = KBD_CMD_CLICK; 4367c478bd9Sstevel@tonic-gate else if (strcmp(copt, "off") == 0) 4377c478bd9Sstevel@tonic-gate cmd = KBD_CMD_NOCLICK; 4387c478bd9Sstevel@tonic-gate else { 4397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "wrong option -- %s\n", copt); 4407c478bd9Sstevel@tonic-gate usage(); 4417c478bd9Sstevel@tonic-gate return (1); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCCMD, &cmd)) { 4457c478bd9Sstevel@tonic-gate perror("kbd ioctl (keyclick)"); 4467c478bd9Sstevel@tonic-gate return (1); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate return (0); 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate /* 4527c478bd9Sstevel@tonic-gate * this routine enables/disables/sets BRK or abort sequence feature 4537c478bd9Sstevel@tonic-gate */ 4547c478bd9Sstevel@tonic-gate static int 4557c478bd9Sstevel@tonic-gate abort_enable(char *aopt, int kbd) 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate int enable; 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate if (strcmp(aopt, "alternate") == 0) 4607c478bd9Sstevel@tonic-gate enable = KIOCABORTALTERNATE; 4617c478bd9Sstevel@tonic-gate else if (strcmp(aopt, "enable") == 0) 4627c478bd9Sstevel@tonic-gate enable = KIOCABORTENABLE; 4637c478bd9Sstevel@tonic-gate else if (strcmp(aopt, "disable") == 0) 4647c478bd9Sstevel@tonic-gate enable = KIOCABORTDISABLE; 4657c478bd9Sstevel@tonic-gate else { 4667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "wrong option -- %s\n", aopt); 4677c478bd9Sstevel@tonic-gate usage(); 4687c478bd9Sstevel@tonic-gate return (1); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCSKABORTEN, &enable)) { 4727c478bd9Sstevel@tonic-gate perror("kbd ioctl (abort enable)"); 4737c478bd9Sstevel@tonic-gate return (1); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate return (0); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate /* 4797c478bd9Sstevel@tonic-gate * this routine set autorepeat delay 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate static int 4827c478bd9Sstevel@tonic-gate set_repeat_delay(char *delay_str, int kbd) 4837c478bd9Sstevel@tonic-gate { 4847c478bd9Sstevel@tonic-gate int delay = atoi(delay_str); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* 4877c478bd9Sstevel@tonic-gate * The error message depends on the different inputs. 4887c478bd9Sstevel@tonic-gate * a. the input is a invalid integer(unit in ms) 4897c478bd9Sstevel@tonic-gate * b. the input is a integer less than the minimal delay setting. 4907c478bd9Sstevel@tonic-gate * The condition (a) has been covered by main function and set_default 4917c478bd9Sstevel@tonic-gate * function. 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCSRPTDELAY, &delay) == -1) { 4947c478bd9Sstevel@tonic-gate if (delay < KIOCRPTDELAY_MIN) 4957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "kbd: specified delay %d is " 4967c478bd9Sstevel@tonic-gate "less than minimum %d\n", delay, KIOCRPTDELAY_MIN); 4977c478bd9Sstevel@tonic-gate else 4987c478bd9Sstevel@tonic-gate perror("kbd: set repeat delay"); 4997c478bd9Sstevel@tonic-gate return (1); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate return (0); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* 5067c478bd9Sstevel@tonic-gate * this routine set autorepeat rate 5077c478bd9Sstevel@tonic-gate */ 5087c478bd9Sstevel@tonic-gate static int 5097c478bd9Sstevel@tonic-gate set_repeat_rate(char *rate_str, int kbd) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate int rate = atoi(rate_str); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate /* 5147c478bd9Sstevel@tonic-gate * The error message depends on the different inputs. 5157c478bd9Sstevel@tonic-gate * a. the input is a invalid integer(unit in ms) 5167c478bd9Sstevel@tonic-gate * b. the input is a integer less than the minimal rate setting. 5177c478bd9Sstevel@tonic-gate * The condition (a) has been covered by main function and set_default 5187c478bd9Sstevel@tonic-gate * function. 5197c478bd9Sstevel@tonic-gate */ 5207c478bd9Sstevel@tonic-gate if (ioctl(kbd, KIOCSRPTRATE, &rate) == -1) { 5217c478bd9Sstevel@tonic-gate if (rate < KIOCRPTRATE_MIN) 5227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "kbd: specified rate %d is " 5237c478bd9Sstevel@tonic-gate "less than minimum %d\n", rate, KIOCRPTRATE_MIN); 5247c478bd9Sstevel@tonic-gate else 5257c478bd9Sstevel@tonic-gate perror("kbd: set repeat rate"); 5267c478bd9Sstevel@tonic-gate return (1); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate return (0); 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate #define BAD_DEFAULT "kbd: bad default value for %s: %s\n" 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate static void 5357c478bd9Sstevel@tonic-gate kbd_defaults(int kbd) 5367c478bd9Sstevel@tonic-gate { 5377c478bd9Sstevel@tonic-gate char *p; 538*7db6e34eSqz150045 int layout_num; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate if (defopen(DEF_FILE) != 0) { 5417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Can't open default file: %s\n", 5427c478bd9Sstevel@tonic-gate DEF_FILE); 5437c478bd9Sstevel@tonic-gate exit(1); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate p = defread(DEF_CLICK); 5477c478bd9Sstevel@tonic-gate if (p != NULL) { 5487c478bd9Sstevel@tonic-gate /* 5497c478bd9Sstevel@tonic-gate * KEYCLICK must equal "on" or "off" 5507c478bd9Sstevel@tonic-gate */ 5517c478bd9Sstevel@tonic-gate if ((strcmp(p, "on") == 0) || (strcmp(p, "off") == 0)) 5527c478bd9Sstevel@tonic-gate (void) click(p, kbd); 5537c478bd9Sstevel@tonic-gate else 5547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, BAD_DEFAULT, DEF_CLICK, p); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate p = defread(DEF_ABORT); 5587c478bd9Sstevel@tonic-gate if (p != NULL) { 5597c478bd9Sstevel@tonic-gate /* 5607c478bd9Sstevel@tonic-gate * ABORT must equal "enable", "disable" or "alternate" 5617c478bd9Sstevel@tonic-gate */ 5627c478bd9Sstevel@tonic-gate if ((strcmp(p, "enable") == 0) || 5637c478bd9Sstevel@tonic-gate (strcmp(p, "alternate") == 0) || 5647c478bd9Sstevel@tonic-gate (strcmp(p, "disable") == 0)) 5657c478bd9Sstevel@tonic-gate (void) abort_enable(p, kbd); 5667c478bd9Sstevel@tonic-gate else 5677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, BAD_DEFAULT, DEF_ABORT, p); 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate p = defread(DEF_RPTDELAY); 5717c478bd9Sstevel@tonic-gate if (p != NULL) { 5727c478bd9Sstevel@tonic-gate /* 5737c478bd9Sstevel@tonic-gate * REPEAT_DELAY unit in ms 5747c478bd9Sstevel@tonic-gate */ 5757c478bd9Sstevel@tonic-gate if (atoi(p) > 0) 5767c478bd9Sstevel@tonic-gate (void) set_repeat_delay(p, kbd); 5777c478bd9Sstevel@tonic-gate else 5787c478bd9Sstevel@tonic-gate (void) fprintf(stderr, BAD_DEFAULT, DEF_RPTDELAY, p); 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate p = defread(DEF_RPTRATE); 5827c478bd9Sstevel@tonic-gate if (p != NULL) { 5837c478bd9Sstevel@tonic-gate /* 5847c478bd9Sstevel@tonic-gate * REPEAT_RATE unit in ms 5857c478bd9Sstevel@tonic-gate */ 5867c478bd9Sstevel@tonic-gate if (atoi(p) > 0) 5877c478bd9Sstevel@tonic-gate (void) set_repeat_rate(p, kbd); 5887c478bd9Sstevel@tonic-gate else 5897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, BAD_DEFAULT, DEF_RPTRATE, p); 5907c478bd9Sstevel@tonic-gate } 591*7db6e34eSqz150045 592*7db6e34eSqz150045 p = defread(DEF_LAYOUT); 593*7db6e34eSqz150045 if (p != NULL) { 594*7db6e34eSqz150045 /* 595*7db6e34eSqz150045 * LAYOUT must be one of the layouts supported in kbd_layouts 596*7db6e34eSqz150045 */ 597*7db6e34eSqz150045 if (get_layouts() != 0) 598*7db6e34eSqz150045 return; 599*7db6e34eSqz150045 600*7db6e34eSqz150045 if ((layout_num = get_layout_number(p)) == -1) { 601*7db6e34eSqz150045 (void) fprintf(stderr, BAD_DEFAULT, DEF_LAYOUT, p); 602*7db6e34eSqz150045 return; 603*7db6e34eSqz150045 } 604*7db6e34eSqz150045 605*7db6e34eSqz150045 (void) set_layout(kbd, layout_num); 606*7db6e34eSqz150045 } 607*7db6e34eSqz150045 } 608*7db6e34eSqz150045 609*7db6e34eSqz150045 static int 610*7db6e34eSqz150045 get_layout_number(char *layout) 611*7db6e34eSqz150045 { 612*7db6e34eSqz150045 int i; 613*7db6e34eSqz150045 int layout_number = -1; 614*7db6e34eSqz150045 615*7db6e34eSqz150045 for (i = 0; i < layout_count; i ++) { 616*7db6e34eSqz150045 if (strcmp(layout, layout_names[i]) == 0) { 617*7db6e34eSqz150045 layout_number = layout_numbers[i]; 618*7db6e34eSqz150045 break; 619*7db6e34eSqz150045 } 620*7db6e34eSqz150045 } 621*7db6e34eSqz150045 622*7db6e34eSqz150045 return (layout_number); 623*7db6e34eSqz150045 } 624*7db6e34eSqz150045 625*7db6e34eSqz150045 static int 626*7db6e34eSqz150045 get_layouts() 627*7db6e34eSqz150045 { 628*7db6e34eSqz150045 FILE *stream; 629*7db6e34eSqz150045 char buffer[MAX_LINE_SIZE]; 630*7db6e34eSqz150045 char *result = NULL; 631*7db6e34eSqz150045 int i = 0; 632*7db6e34eSqz150045 char *tmpbuf; 633*7db6e34eSqz150045 634*7db6e34eSqz150045 if ((stream = fopen(KBD_LAYOUT_FILE, "r")) == 0) { 635*7db6e34eSqz150045 perror(KBD_LAYOUT_FILE); 636*7db6e34eSqz150045 return (1); 637*7db6e34eSqz150045 } 638*7db6e34eSqz150045 639*7db6e34eSqz150045 while ((fgets(buffer, MAX_LINE_SIZE, stream) != NULL) && 640*7db6e34eSqz150045 (i < MAX_LAYOUT_NUM)) { 641*7db6e34eSqz150045 if (buffer[0] == '#') 642*7db6e34eSqz150045 continue; 643*7db6e34eSqz150045 if ((result = strtok(buffer, "=")) == NULL) 644*7db6e34eSqz150045 continue; 645*7db6e34eSqz150045 if ((tmpbuf = strdup(result)) != NULL) { 646*7db6e34eSqz150045 layout_names[i] = tmpbuf; 647*7db6e34eSqz150045 } else { 648*7db6e34eSqz150045 perror("out of memory getting layout names"); 649*7db6e34eSqz150045 return (1); 650*7db6e34eSqz150045 } 651*7db6e34eSqz150045 if ((result = strtok(NULL, "\n")) == NULL) 652*7db6e34eSqz150045 continue; 653*7db6e34eSqz150045 layout_numbers[i] = atoi(result); 654*7db6e34eSqz150045 if (strcmp(tmpbuf, "US-English") == 0) 655*7db6e34eSqz150045 default_layout_number = i; 656*7db6e34eSqz150045 i++; 657*7db6e34eSqz150045 } 658*7db6e34eSqz150045 layout_count = i; 659*7db6e34eSqz150045 660*7db6e34eSqz150045 return (0); 661*7db6e34eSqz150045 } 662*7db6e34eSqz150045 663*7db6e34eSqz150045 /* 664*7db6e34eSqz150045 * this routine sets the layout of the keyboard being used 665*7db6e34eSqz150045 */ 666*7db6e34eSqz150045 static int 667*7db6e34eSqz150045 set_layout(int kbd, int layout_num) 668*7db6e34eSqz150045 { 669*7db6e34eSqz150045 670*7db6e34eSqz150045 if (ioctl(kbd, KIOCSLAYOUT, layout_num)) { 671*7db6e34eSqz150045 perror("ioctl (set kbd layout)"); 672*7db6e34eSqz150045 return (1); 673*7db6e34eSqz150045 } 674*7db6e34eSqz150045 675*7db6e34eSqz150045 return (0); 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate static char *usage1 = "kbd [-r] [-t] [-l] [-a enable|disable|alternate]"; 6797c478bd9Sstevel@tonic-gate static char *usage2 = " [-c on|off][-D delay][-R rate][-d keyboard device]"; 6807c478bd9Sstevel@tonic-gate static char *usage3 = "kbd -i [-d keyboard device]"; 681*7db6e34eSqz150045 static char *usage4 = "kbd -s [language]"; 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate static void 6847c478bd9Sstevel@tonic-gate usage(void) 6857c478bd9Sstevel@tonic-gate { 686*7db6e34eSqz150045 (void) fprintf(stderr, "Usage:\t%s\n\t%s\n\t%s\n\t%s\n", usage1, usage2, 687*7db6e34eSqz150045 usage3, usage4); 6887c478bd9Sstevel@tonic-gate } 689