1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 30 /* 31 * Usage: kbd [-r] [-t] [-l] [-i] [-c on|off] [-a enable|disable|alternate] 32 * [-d keyboard device] 33 * -r reset the keyboard as if power-up 34 * -t return the type of the keyboard being used 35 * -l return the layout of the keyboard being used, 36 * and the Autorepeat settings 37 * -i read in the default configuration file 38 * -c on|off turn on|off clicking 39 * -a enable|disable|alternate sets abort sequence 40 * -D autorepeat delay sets autorepeat dealy, unit in ms 41 * -R autorepeat rate sets autorepeat rate, unit in ms 42 * -d keyboard device chooses the kbd device, default /dev/kbd. 43 */ 44 45 #include <sys/types.h> 46 #include <sys/ioctl.h> 47 #include <sys/kbio.h> 48 #include <sys/kbd.h> 49 #include <stdio.h> 50 #include <fcntl.h> 51 #include <deflt.h> 52 #include <unistd.h> 53 #include <string.h> 54 #include <stdlib.h> 55 #include <stropts.h> 56 57 #define KBD_DEVICE "/dev/kbd" /* default keyboard device */ 58 #define DEF_FILE "/etc/default/kbd" /* kbd defaults file */ 59 #define DEF_ABORT "KEYBOARD_ABORT=" 60 #define DEF_CLICK "KEYCLICK=" 61 #define DEF_RPTDELAY "REPEAT_DELAY=" 62 #define DEF_RPTRATE "REPEAT_RATE=" 63 64 static void reset(int); 65 static void get_type(int); 66 static void get_layout(int); 67 static void kbd_defaults(int); 68 static void usage(void); 69 70 static int click(char *, int); 71 static int abort_enable(char *, int); 72 static int set_repeat_delay(char *, int); 73 static int set_repeat_rate(char *, int); 74 75 int 76 main(int argc, char **argv) 77 { 78 int c, error; 79 int rflag, tflag, lflag, cflag, dflag, aflag, iflag, errflag, 80 Dflag, Rflag, rtlacDRflag; 81 char *copt, *aopt, *delay, *rate; 82 char *kbdname = KBD_DEVICE; 83 int kbd; 84 extern char *optarg; 85 extern int optind; 86 87 rflag = tflag = cflag = dflag = aflag = iflag = errflag = lflag = 88 Dflag = Rflag = 0; 89 copt = aopt = (char *)0; 90 91 while ((c = getopt(argc, argv, "rtlic:a:d:D:R:")) != EOF) { 92 switch (c) { 93 case 'r': 94 rflag++; 95 break; 96 case 't': 97 tflag++; 98 break; 99 case 'l': 100 lflag++; 101 break; 102 case 'i': 103 iflag++; 104 break; 105 case 'c': 106 copt = optarg; 107 cflag++; 108 break; 109 case 'a': 110 aopt = optarg; 111 aflag++; 112 break; 113 case 'd': 114 kbdname = optarg; 115 dflag++; 116 break; 117 case 'D': 118 delay = optarg; 119 Dflag++; 120 break; 121 case 'R': 122 rate = optarg; 123 Rflag++; 124 break; 125 case '?': 126 errflag++; 127 break; 128 } 129 } 130 131 /* 132 * Check for valid arguments: 133 * 134 * If argument parsing failed or if there are left-over 135 * command line arguments, then we're done now. 136 */ 137 if (errflag != 0 || argc != optind) { 138 usage(); 139 exit(1); 140 } 141 /* 142 * kbd requires that the user specify either "-i" or at least one of 143 * -[rtlacDR]. The "-d" option is, well, optional. We don't 144 * care if it's there or not. 145 */ 146 rtlacDRflag = rflag + tflag + lflag + aflag + cflag + Dflag + Rflag; 147 if ((iflag != 0 && rtlacDRflag != 0) || 148 (iflag == 0 && rtlacDRflag == 0)) { 149 usage(); 150 exit(1); 151 } 152 153 if (Dflag && atoi(delay) <= 0) { 154 (void) fprintf(stderr, "Invalid arguments: -D %s\n", delay); 155 usage(); 156 exit(1); 157 } 158 159 if (Rflag && atoi(rate) <= 0) { 160 (void) fprintf(stderr, "Invalid arguments: -R %s\n", rate); 161 usage(); 162 exit(1); 163 } 164 165 /* 166 * Open the keyboard device 167 */ 168 if ((kbd = open(kbdname, O_RDWR)) < 0) { 169 perror("opening the keyboard"); 170 (void) fprintf(stderr, "kbd: Cannot open %s\n", kbdname); 171 exit(1); 172 } 173 174 if (iflag) { 175 kbd_defaults(kbd); 176 exit(0); /* A mutually exclusive option */ 177 /*NOTREACHED*/ 178 } 179 180 if (tflag) 181 get_type(kbd); 182 183 if (lflag) 184 get_layout(kbd); 185 186 if (cflag && (error = click(copt, kbd)) != 0) 187 exit(error); 188 189 if (rflag) 190 reset(kbd); 191 192 if (aflag && (error = abort_enable(aopt, kbd)) != 0) 193 exit(error); 194 195 if (Dflag && (error = set_repeat_delay(delay, kbd)) != 0) 196 exit(error); 197 198 if (Rflag && (error = set_repeat_rate(rate, kbd)) != 0) 199 exit(error); 200 201 return (0); 202 } 203 204 /* 205 * this routine resets the state of the keyboard as if power-up 206 */ 207 static void 208 reset(int kbd) 209 { 210 int cmd; 211 212 cmd = KBD_CMD_RESET; 213 214 if (ioctl(kbd, KIOCCMD, &cmd)) { 215 perror("kbd: ioctl error"); 216 exit(1); 217 } 218 219 } 220 221 /* 222 * this routine gets the type of the keyboard being used 223 */ 224 static void 225 get_type(int kbd) 226 { 227 int kbd_type; 228 229 if (ioctl(kbd, KIOCTYPE, &kbd_type)) { 230 perror("ioctl (kbd type)"); 231 exit(1); 232 } 233 234 switch (kbd_type) { 235 236 case KB_SUN3: 237 (void) printf("Type 3 Sun keyboard\n"); 238 break; 239 240 case KB_SUN4: 241 (void) printf("Type 4 Sun keyboard\n"); 242 break; 243 244 case KB_ASCII: 245 (void) printf("ASCII\n"); 246 break; 247 248 case KB_PC: 249 (void) printf("PC\n"); 250 break; 251 252 case KB_USB: 253 (void) printf("USB keyboard\n"); 254 break; 255 256 default: 257 (void) printf("Unknown keyboard type\n"); 258 break; 259 } 260 } 261 262 /* 263 * this routine gets the layout of the keyboard being used 264 * also, included the autorepeat delay and rate being used 265 */ 266 static void 267 get_layout(int kbd) 268 { 269 int kbd_type; 270 int kbd_layout; 271 /* these two variables are used for getting delay&rate */ 272 int delay, rate; 273 delay = rate = 0; 274 275 if (ioctl(kbd, KIOCTYPE, &kbd_type)) { 276 perror("ioctl (kbd type)"); 277 exit(1); 278 } 279 280 if (ioctl(kbd, KIOCLAYOUT, &kbd_layout)) { 281 perror("ioctl (kbd layout)"); 282 exit(1); 283 } 284 285 (void) printf("type=%d\nlayout=%d (0x%.2x)\n", 286 kbd_type, kbd_layout, kbd_layout); 287 288 /* below code is used to get the autorepeat delay and rate */ 289 if (ioctl(kbd, KIOCGRPTDELAY, &delay)) { 290 perror("ioctl (kbd get repeat delay)"); 291 exit(1); 292 } 293 294 if (ioctl(kbd, KIOCGRPTRATE, &rate)) { 295 perror("ioctl (kbd get repeat rate)"); 296 exit(1); 297 } 298 299 (void) printf("delay(ms)=%d\n", delay); 300 (void) printf("rate(ms)=%d\n", rate); 301 } 302 303 /* 304 * this routine enables or disables clicking of the keyboard 305 */ 306 static int 307 click(char *copt, int kbd) 308 { 309 int cmd; 310 311 if (strcmp(copt, "on") == 0) 312 cmd = KBD_CMD_CLICK; 313 else if (strcmp(copt, "off") == 0) 314 cmd = KBD_CMD_NOCLICK; 315 else { 316 (void) fprintf(stderr, "wrong option -- %s\n", copt); 317 usage(); 318 return (1); 319 } 320 321 if (ioctl(kbd, KIOCCMD, &cmd)) { 322 perror("kbd ioctl (keyclick)"); 323 return (1); 324 } 325 return (0); 326 } 327 328 /* 329 * this routine enables/disables/sets BRK or abort sequence feature 330 */ 331 static int 332 abort_enable(char *aopt, int kbd) 333 { 334 int enable; 335 336 if (strcmp(aopt, "alternate") == 0) 337 enable = KIOCABORTALTERNATE; 338 else if (strcmp(aopt, "enable") == 0) 339 enable = KIOCABORTENABLE; 340 else if (strcmp(aopt, "disable") == 0) 341 enable = KIOCABORTDISABLE; 342 else { 343 (void) fprintf(stderr, "wrong option -- %s\n", aopt); 344 usage(); 345 return (1); 346 } 347 348 if (ioctl(kbd, KIOCSKABORTEN, &enable)) { 349 perror("kbd ioctl (abort enable)"); 350 return (1); 351 } 352 return (0); 353 } 354 355 /* 356 * this routine set autorepeat delay 357 */ 358 static int 359 set_repeat_delay(char *delay_str, int kbd) 360 { 361 int delay = atoi(delay_str); 362 363 /* 364 * The error message depends on the different inputs. 365 * a. the input is a invalid integer(unit in ms) 366 * b. the input is a integer less than the minimal delay setting. 367 * The condition (a) has been covered by main function and set_default 368 * function. 369 */ 370 if (ioctl(kbd, KIOCSRPTDELAY, &delay) == -1) { 371 if (delay < KIOCRPTDELAY_MIN) 372 (void) fprintf(stderr, "kbd: specified delay %d is " 373 "less than minimum %d\n", delay, KIOCRPTDELAY_MIN); 374 else 375 perror("kbd: set repeat delay"); 376 return (1); 377 } 378 379 return (0); 380 } 381 382 /* 383 * this routine set autorepeat rate 384 */ 385 static int 386 set_repeat_rate(char *rate_str, int kbd) 387 { 388 int rate = atoi(rate_str); 389 390 /* 391 * The error message depends on the different inputs. 392 * a. the input is a invalid integer(unit in ms) 393 * b. the input is a integer less than the minimal rate setting. 394 * The condition (a) has been covered by main function and set_default 395 * function. 396 */ 397 if (ioctl(kbd, KIOCSRPTRATE, &rate) == -1) { 398 if (rate < KIOCRPTRATE_MIN) 399 (void) fprintf(stderr, "kbd: specified rate %d is " 400 "less than minimum %d\n", rate, KIOCRPTRATE_MIN); 401 else 402 perror("kbd: set repeat rate"); 403 return (1); 404 } 405 406 return (0); 407 } 408 409 #define BAD_DEFAULT "kbd: bad default value for %s: %s\n" 410 411 static void 412 kbd_defaults(int kbd) 413 { 414 char *p; 415 416 if (defopen(DEF_FILE) != 0) { 417 (void) fprintf(stderr, "Can't open default file: %s\n", 418 DEF_FILE); 419 exit(1); 420 } 421 422 p = defread(DEF_CLICK); 423 if (p != NULL) { 424 /* 425 * KEYCLICK must equal "on" or "off" 426 */ 427 if ((strcmp(p, "on") == 0) || (strcmp(p, "off") == 0)) 428 (void) click(p, kbd); 429 else 430 (void) fprintf(stderr, BAD_DEFAULT, DEF_CLICK, p); 431 } 432 433 p = defread(DEF_ABORT); 434 if (p != NULL) { 435 /* 436 * ABORT must equal "enable", "disable" or "alternate" 437 */ 438 if ((strcmp(p, "enable") == 0) || 439 (strcmp(p, "alternate") == 0) || 440 (strcmp(p, "disable") == 0)) 441 (void) abort_enable(p, kbd); 442 else 443 (void) fprintf(stderr, BAD_DEFAULT, DEF_ABORT, p); 444 } 445 446 p = defread(DEF_RPTDELAY); 447 if (p != NULL) { 448 /* 449 * REPEAT_DELAY unit in ms 450 */ 451 if (atoi(p) > 0) 452 (void) set_repeat_delay(p, kbd); 453 else 454 (void) fprintf(stderr, BAD_DEFAULT, DEF_RPTDELAY, p); 455 } 456 457 p = defread(DEF_RPTRATE); 458 if (p != NULL) { 459 /* 460 * REPEAT_RATE unit in ms 461 */ 462 if (atoi(p) > 0) 463 (void) set_repeat_rate(p, kbd); 464 else 465 (void) fprintf(stderr, BAD_DEFAULT, DEF_RPTRATE, p); 466 } 467 } 468 469 static char *usage1 = "kbd [-r] [-t] [-l] [-a enable|disable|alternate]"; 470 static char *usage2 = " [-c on|off][-D delay][-R rate][-d keyboard device]"; 471 static char *usage3 = "kbd -i [-d keyboard device]"; 472 473 static void 474 usage(void) 475 { 476 (void) fprintf(stderr, "Usage:\t%s\n\t%s\n\t%s\n", usage1, usage2, 477 usage3); 478 } 479