1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Usage: kbd [-r] [-t] [-l] [-c on|off] [-a enable|disable|alternate] 28 * [-d keyboard device] [-A autorepeat count] 29 * [-D autorepeat delay] [-R autorepeat rate] 30 * kbd [-i] [-d keyboard device] 31 * kbd -s [language] 32 * kbd -b [keyboard|console] frequency 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 * -A autorepeat count sets autorepeat sequence length in chars. 41 * -D autorepeat delay sets autorepeat delay, unit in ms 42 * -R autorepeat rate sets autorepeat rate, unit in ms 43 * -d keyboard device chooses the kbd device, default /dev/kbd. 44 * -s keyboard layout sets keyboard layout 45 * -b [keyboard| console] frequency 46 * sets keyboard or console beeper frequency 47 */ 48 49 #include <sys/types.h> 50 #include <sys/ioctl.h> 51 #include <sys/kbio.h> 52 #include <sys/kbd.h> 53 #include <stdio.h> 54 #include <fcntl.h> 55 #include <deflt.h> 56 #include <unistd.h> 57 #include <string.h> 58 #include <stdlib.h> 59 #include <stropts.h> 60 #include <libintl.h> 61 #include <locale.h> 62 #include <errno.h> 63 #include <inttypes.h> 64 #include <libscf.h> 65 #include <limits.h> 66 67 #define KBD_DEVICE "/dev/kbd" /* default keyboard device */ 68 69 #define KBD_LAYOUT_FILE "/usr/share/lib/keytables/type_6/kbd_layouts" 70 #define MAX_LAYOUT_NUM 128 71 #define MAX_LINE_SIZE 256 72 #define DEFAULT_KBD_LAYOUT 33 73 74 #define KBD_FMRI "svc:/system/keymap:default" 75 #define KBD_PG "keymap" 76 #define KBD_PROP_LAYOUT "layout" 77 #define KBD_PROP_KEYCLICK "keyclick" 78 #define KBD_PROP_KEYBOARD_ABORT "keyboard_abort" 79 #define KBD_PROP_RPTDELAY "repeat_delay" 80 #define KBD_PROP_RPTRATE "repeat_rate" 81 #define KBD_PROP_RPTCOUNT "repeat_count" 82 #define KBD_PROP_FREQ "kbd_beeper_freq" 83 #define KBD_PROP_CONSFREQ "console_beeper_freq" 84 #define KBD_MAX_NAME_LEN 1024 85 86 char *layout_names[MAX_LAYOUT_NUM]; 87 int layout_numbers[MAX_LAYOUT_NUM]; 88 static int layout_count; 89 static int default_layout_number = 0; 90 91 static void reset(int); 92 static int get_type(int); 93 static void get_layout(int); 94 static void kbd_defaults(int); 95 static void usage(void); 96 97 static int click(char *, int); 98 static int abort_enable(char *, int); 99 static int set_repeat_count(char *, int); 100 static int set_rptcount(int, int); 101 static int set_repeat_delay(char *, int); 102 static int set_rptdelay(int, int); 103 static int set_repeat_rate(char *, int); 104 static int set_rptrate(int, int); 105 106 static int get_layout_number(char *); 107 static int set_layout(int, int); 108 static int get_layouts(void); 109 static int set_kbd_layout(int, char *); 110 static int set_beep_freq(int, char *, int); 111 112 int 113 main(int argc, char **argv) 114 { 115 int c, error; 116 int rflag, tflag, lflag, cflag, dflag, aflag, iflag, errflag, 117 Aflag, Dflag, Rflag, rtlacADRflag, sflag, bflag; 118 char *copt, *aopt, *count, *delay, *rate, *layout_name, *b_type; 119 char *freq_str; 120 char *kbdname = KBD_DEVICE, *endptr = NULL; 121 int kbd, freq_val; 122 extern char *optarg; 123 extern int optind; 124 125 rflag = tflag = cflag = dflag = aflag = iflag = errflag = lflag = 126 Aflag = Dflag = Rflag = sflag = bflag = 0; 127 copt = aopt = NULL; 128 129 (void) setlocale(LC_ALL, ""); 130 #if !defined(TEXT_DOMAIN) 131 #define TEXT_DOMAIN "SYS_TEST" 132 #endif 133 (void) textdomain(TEXT_DOMAIN); 134 135 while ((c = getopt(argc, argv, "rtlisc:a:d:A:D:R:b:")) != EOF) { 136 switch (c) { 137 case 'r': 138 rflag++; 139 break; 140 case 't': 141 tflag++; 142 break; 143 case 'l': 144 lflag++; 145 break; 146 case 'i': 147 iflag++; 148 break; 149 case 's': 150 sflag++; 151 break; 152 case 'c': 153 copt = optarg; 154 cflag++; 155 break; 156 case 'a': 157 aopt = optarg; 158 aflag++; 159 break; 160 case 'd': 161 kbdname = optarg; 162 dflag++; 163 break; 164 case 'A': 165 count = optarg; 166 Aflag++; 167 break; 168 case 'D': 169 delay = optarg; 170 Dflag++; 171 break; 172 case 'R': 173 rate = optarg; 174 Rflag++; 175 break; 176 case 'b': 177 bflag++; 178 break; 179 case '?': 180 errflag++; 181 break; 182 } 183 } 184 185 /* 186 * Check for valid arguments: 187 * 188 * If argument parsing failed or if there are left-over 189 * command line arguments(except -s and -b option), 190 * then we're done now. 191 */ 192 if (errflag != 0 || (sflag == 0 && bflag == 0 && argc != optind)) { 193 usage(); 194 exit(1); 195 } 196 197 /* 198 * kbd requires that the user specify either "-i" or "-s" or "-b" or 199 * at least one of -[rtlacADR]. The "-d" option is, well, optional. 200 * We don't care if it's there or not. 201 */ 202 rtlacADRflag = rflag + tflag + lflag + aflag + cflag + Aflag + 203 Dflag + Rflag; 204 if (!((iflag != 0 && sflag == 0 && bflag == 0 && rtlacADRflag == 0) || 205 (iflag == 0 && sflag != 0 && bflag == 0 && dflag == 0 && 206 rtlacADRflag == 0) || 207 (iflag == 0 && sflag == 0 && bflag == 0 && rtlacADRflag != 0) || 208 (iflag == 0 && sflag == 0 && bflag != 0 && rtlacADRflag == 0))) { 209 usage(); 210 exit(1); 211 } 212 213 if (Aflag && atoi(count) < -1) { 214 (void) fprintf(stderr, "Invalid arguments: -A %s\n", count); 215 usage(); 216 exit(1); 217 } 218 219 if (Dflag && atoi(delay) <= 0) { 220 (void) fprintf(stderr, "Invalid arguments: -D %s\n", delay); 221 usage(); 222 exit(1); 223 } 224 225 if (Rflag && atoi(rate) <= 0) { 226 (void) fprintf(stderr, "Invalid arguments: -R %s\n", rate); 227 usage(); 228 exit(1); 229 } 230 231 /* 232 * Open the keyboard device 233 */ 234 if ((kbd = open(kbdname, O_RDWR)) < 0) { 235 perror("opening the keyboard"); 236 (void) fprintf(stderr, "kbd: Cannot open %s\n", kbdname); 237 exit(1); 238 } 239 240 if (iflag) { 241 kbd_defaults(kbd); 242 exit(0); /* A mutually exclusive option */ 243 /*NOTREACHED*/ 244 } 245 246 if (tflag) 247 (void) get_type(kbd); 248 249 if (lflag) 250 get_layout(kbd); 251 252 if (cflag && (error = click(copt, kbd)) != 0) 253 exit(error); 254 255 if (rflag) 256 reset(kbd); 257 258 if (aflag && (error = abort_enable(aopt, kbd)) != 0) 259 exit(error); 260 261 if (Aflag && (error = set_repeat_count(count, kbd)) != 0) 262 exit(error); 263 264 if (Dflag && (error = set_repeat_delay(delay, kbd)) != 0) 265 exit(error); 266 267 if (Rflag && (error = set_repeat_rate(rate, kbd)) != 0) 268 exit(error); 269 270 if (sflag) { 271 if (argc == optind) { 272 layout_name = NULL; 273 } else if (argc == (optind + 1)) { 274 layout_name = argv[optind]; 275 } else { 276 usage(); 277 exit(1); 278 } 279 280 if ((error = set_kbd_layout(kbd, layout_name)) != 0) 281 exit(error); 282 } 283 284 if (bflag) { 285 if (argc == optind) { 286 b_type = "keyboard"; 287 } else if (argc == (optind + 1)) { 288 b_type = argv[argc - 2]; 289 } else { 290 usage(); 291 exit(1); 292 } 293 294 if (strcmp(b_type, "keyboard") && strcmp(b_type, "console")) { 295 usage(); 296 exit(1); 297 } 298 299 freq_str = argv[argc - 1]; 300 errno = 0; 301 freq_val = (int)strtol(freq_str, &endptr, 10); 302 if (errno != 0 || endptr[0] != '\0') { 303 usage(); 304 exit(1); 305 } 306 307 if (freq_val < 0 || freq_val > INT16_MAX) { 308 (void) fprintf(stderr, "Invalid arguments: -b %s\n", 309 freq_str); 310 (void) fprintf(stderr, "Frequency range: [0 - %d]\n", 311 INT16_MAX); 312 exit(1); 313 } 314 315 if ((error = set_beep_freq(kbd, b_type, freq_val)) != 0) 316 exit(1); 317 } 318 319 return (0); 320 } 321 322 /* 323 * this routine gets the type of the keyboard being used 324 */ 325 static int 326 set_kbd_layout(int kbd, char *layout_name) 327 { 328 int layout_num; 329 int error = 1; 330 331 /* layout setting is possible only for USB type keyboards */ 332 if (get_type(kbd) != KB_USB) { 333 (void) fprintf(stderr, "The -s option does not apply for this" 334 " keyboard type.\n" 335 "Only USB/PS2 type keyboards support this option.\n"); 336 return (error); 337 } 338 339 /* get the language info from the layouts file */ 340 if (get_layouts() != 0) 341 return (error); 342 343 if (layout_name != NULL) { 344 if ((layout_num = get_layout_number(layout_name)) == -1) { 345 (void) fprintf(stderr, "%s: unknown layout name\n" 346 "Please refer to 'kbd -s' to get the " 347 "supported layouts.\n", layout_name); 348 return (error); 349 } 350 } else { 351 int i, j, print_cnt, input_num; 352 boolean_t input_right = B_TRUE; 353 boolean_t default_input = B_FALSE; 354 char input[8]; /* 8 chars is enough for numbers */ 355 356 print_cnt = (layout_count % 2) ? 357 layout_count/2+1 : layout_count/2; 358 359 for (i = 1; i <= print_cnt; i++) { 360 (void) printf("%2d. %-30s", i, 361 layout_names[i-1]); 362 j = i + print_cnt; 363 if (j <= layout_count) { 364 (void) printf("%-2d. %-30s\n", j, 365 layout_names[j-1]); 366 } 367 } 368 (void) printf(gettext("\nTo select the keyboard layout," 369 " enter a number [default %d]:"), 370 default_layout_number+1); 371 372 for (;;) { 373 if (input_right == B_FALSE) 374 (void) printf(gettext("Invalid input. " 375 "Please input a number " 376 "(1,2,...):")); 377 (void) memset(input, 0, 8); 378 (void) fflush(stdin); 379 (void) fgets(input, 8, stdin); 380 if (strlen(input) > 4) { 381 input_right = B_FALSE; 382 continue; 383 } 384 if (input[0] == '\n') { 385 default_input = B_TRUE; 386 break; 387 } 388 input_right = B_TRUE; 389 /* check if the inputs are numbers 0~9 */ 390 for (i = 0; i < (strlen(input) - 1); i++) { 391 if ((input[i] < '0') || 392 (input[i] > '9')) { 393 input_right = B_FALSE; 394 break; 395 } 396 } 397 if (input_right == B_FALSE) 398 continue; 399 input_num = atoi(input); 400 if ((input_num > 0) && 401 (input_num <= layout_count)) 402 break; 403 else 404 input_right = B_FALSE; 405 } 406 if (default_input == B_TRUE) 407 layout_num = DEFAULT_KBD_LAYOUT; 408 else 409 layout_num = layout_numbers[--input_num]; 410 } 411 412 if ((error = set_layout(kbd, layout_num)) != 0) 413 return (error); 414 415 return (0); 416 } 417 418 /* 419 * This routine sets keyboard or console beeper frequency 420 */ 421 static int 422 set_beep_freq(int fd, char *type, int freq) 423 { 424 struct freq_request fr_struct; 425 426 if (strcmp(type, "keyboard") == 0) 427 fr_struct.type = KBD_BEEP; 428 else if (strcmp(type, "console") == 0) 429 fr_struct.type = CONSOLE_BEEP; 430 else 431 return (EINVAL); 432 433 fr_struct.freq = (int16_t)freq; 434 435 return (ioctl(fd, KIOCSETFREQ, &fr_struct)); 436 } 437 438 /* 439 * this routine resets the state of the keyboard as if power-up 440 */ 441 static void 442 reset(int kbd) 443 { 444 int cmd; 445 446 cmd = KBD_CMD_RESET; 447 448 if (ioctl(kbd, KIOCCMD, &cmd)) { 449 perror("kbd: ioctl error"); 450 exit(1); 451 } 452 453 } 454 455 /* 456 * this routine gets the type of the keyboard being used 457 */ 458 static int 459 get_type(int kbd) 460 { 461 int kbd_type; 462 463 if (ioctl(kbd, KIOCTYPE, &kbd_type)) { 464 perror("ioctl (kbd type)"); 465 exit(1); 466 } 467 468 switch (kbd_type) { 469 470 case KB_SUN3: 471 (void) printf("Type 3 Sun keyboard\n"); 472 break; 473 474 case KB_SUN4: 475 (void) printf("Type 4 Sun keyboard\n"); 476 break; 477 478 case KB_ASCII: 479 (void) printf("ASCII\n"); 480 break; 481 482 case KB_PC: 483 (void) printf("PC\n"); 484 break; 485 486 case KB_USB: 487 (void) printf("USB keyboard\n"); 488 break; 489 490 default: 491 (void) printf("Unknown keyboard type\n"); 492 break; 493 } 494 return (kbd_type); 495 } 496 497 /* 498 * this routine gets the layout of the keyboard being used 499 * also, included the autorepeat delay and rate being used 500 */ 501 static void 502 get_layout(int kbd) 503 { 504 int kbd_type; 505 int kbd_layout; 506 /* these three variables are used for getting delay&rate&count */ 507 int delay, rate, count = -1; 508 delay = rate = 0; 509 510 if (ioctl(kbd, KIOCTYPE, &kbd_type)) { 511 perror("ioctl (kbd type)"); 512 exit(1); 513 } 514 515 if (ioctl(kbd, KIOCLAYOUT, &kbd_layout)) { 516 perror("ioctl (kbd layout)"); 517 exit(1); 518 } 519 520 (void) printf("type=%d\nlayout=%d (0x%.2x)\n", 521 kbd_type, kbd_layout, kbd_layout); 522 523 /* below code is used to get the autorepeat delay and rate */ 524 if (ioctl(kbd, KIOCGRPTDELAY, &delay)) { 525 perror("ioctl (kbd get repeat delay)"); 526 exit(1); 527 } 528 529 if (ioctl(kbd, KIOCGRPTRATE, &rate)) { 530 perror("ioctl (kbd get repeat rate)"); 531 exit(1); 532 } 533 534 if (ioctl(kbd, KIOCGRPTCOUNT, &count)) { 535 perror("ioctl (kbd get repeat count)"); 536 exit(1); 537 } 538 539 (void) printf("delay(ms)=%d\n", delay); 540 (void) printf("rate(ms)=%d\n", rate); 541 if (count == -1) 542 (void) printf("count=unlimited\n"); 543 else 544 (void) printf("count=%d\n", count); 545 } 546 547 /* 548 * this routine enables or disables clicking of the keyboard 549 */ 550 static int 551 click(char *copt, int kbd) 552 { 553 int cmd; 554 555 if (strcmp(copt, "on") == 0) 556 cmd = KBD_CMD_CLICK; 557 else if (strcmp(copt, "off") == 0) 558 cmd = KBD_CMD_NOCLICK; 559 else { 560 (void) fprintf(stderr, "wrong option -- %s\n", copt); 561 usage(); 562 return (1); 563 } 564 565 if (ioctl(kbd, KIOCCMD, &cmd)) { 566 perror("kbd ioctl (keyclick)"); 567 return (1); 568 } 569 return (0); 570 } 571 572 /* 573 * this routine enables/disables/sets BRK or abort sequence feature 574 */ 575 static int 576 abort_enable(char *aopt, int kbd) 577 { 578 int enable; 579 580 if (strcmp(aopt, "alternate") == 0) 581 enable = KIOCABORTALTERNATE; 582 else if (strcmp(aopt, "enable") == 0) 583 enable = KIOCABORTENABLE; 584 else if (strcmp(aopt, "disable") == 0) 585 enable = KIOCABORTDISABLE; 586 else { 587 (void) fprintf(stderr, "wrong option -- %s\n", aopt); 588 usage(); 589 return (1); 590 } 591 592 if (ioctl(kbd, KIOCSKABORTEN, &enable)) { 593 perror("kbd ioctl (abort enable)"); 594 return (1); 595 } 596 return (0); 597 } 598 599 static int 600 set_rptcount(int count, int kbd) 601 { 602 if (ioctl(kbd, KIOCSRPTCOUNT, &count) == -1) { 603 perror("kbd: set repeat count"); 604 return (1); 605 } 606 return (0); 607 } 608 609 static int 610 set_repeat_count(char *count_str, int kbd) 611 { 612 int count = atoi(count_str); 613 614 return (set_rptcount(count, kbd)); 615 } 616 617 static int 618 set_rptdelay(int delay, int kbd) 619 { 620 /* 621 * The error message depends on the different inputs. 622 * a. the input is a invalid integer(unit in ms) 623 * b. the input is a integer less than the minimal delay setting. 624 * The condition (a) has been covered by main function and kbd_defaults 625 * function. 626 */ 627 if (ioctl(kbd, KIOCSRPTDELAY, &delay) == -1) { 628 if (delay < KIOCRPTDELAY_MIN) 629 (void) fprintf(stderr, "kbd: specified delay %d is " 630 "less than minimum %d\n", delay, KIOCRPTDELAY_MIN); 631 else 632 perror("kbd: set repeat delay"); 633 return (1); 634 } 635 636 return (0); 637 } 638 639 /* 640 * this routine set autorepeat delay 641 */ 642 static int 643 set_repeat_delay(char *delay_str, int kbd) 644 { 645 int delay = atoi(delay_str); 646 647 return (set_rptdelay(delay, kbd)); 648 } 649 650 static int 651 set_rptrate(int rate, int kbd) 652 { 653 /* 654 * The input validation check has been covered by main function 655 * and kbd_defaults function.Here just give an error message if 656 * the ioctl fails. 657 */ 658 if (ioctl(kbd, KIOCSRPTRATE, &rate) == -1) { 659 perror("kbd: set repeat rate"); 660 return (1); 661 } 662 return (0); 663 } 664 665 /* 666 * this routine set autorepeat rate 667 */ 668 static int 669 set_repeat_rate(char *rate_str, int kbd) 670 { 671 int rate = atoi(rate_str); 672 673 return (set_rptrate(rate, kbd)); 674 } 675 676 #define BAD_DEFAULT_STR "kbd: bad default value for %s: %s\n" 677 #define BAD_DEFAULT_INT "kbd: bad default value for %s: %d\n" 678 #define BAD_DEFAULT_LLINT "kbd: bad default value for %s: %lld\n" 679 680 static void 681 kbd_defaults(int kbd) 682 { 683 scf_handle_t *h = NULL; 684 scf_snapshot_t *snap = NULL; 685 scf_instance_t *inst = NULL; 686 scf_propertygroup_t *pg = NULL; 687 scf_property_t *prop = NULL; 688 scf_value_t *val = NULL; 689 690 int layout_num; 691 char *val_layout = NULL, *val_abort = NULL; 692 uint8_t val_click; 693 int64_t val_delay, val_rate, val_count; 694 int64_t val_kbd_beeper, val_console_beeper; 695 696 if ((h = scf_handle_create(SCF_VERSION)) == NULL || 697 scf_handle_bind(h) != 0 || 698 (inst = scf_instance_create(h)) == NULL || 699 (snap = scf_snapshot_create(h)) == NULL || 700 (pg = scf_pg_create(h)) == NULL || 701 (prop = scf_property_create(h)) == NULL || 702 (val = scf_value_create(h)) == NULL) { 703 goto out; 704 } 705 706 if (scf_handle_decode_fmri(h, KBD_FMRI, NULL, NULL, inst, 707 NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 708 goto out; 709 } 710 711 if (scf_instance_get_snapshot(inst, "running", snap) != 0) { 712 scf_snapshot_destroy(snap); 713 snap = NULL; 714 } 715 716 if (scf_instance_get_pg_composed(inst, snap, KBD_PG, pg) != 0) { 717 goto out; 718 } 719 720 if ((val_abort = malloc(KBD_MAX_NAME_LEN)) == NULL) { 721 (void) fprintf(stderr, 722 "Can not alloc memory for keyboard properties\n"); 723 goto out; 724 } 725 726 if ((val_layout = malloc(KBD_MAX_NAME_LEN)) == NULL) { 727 (void) fprintf(stderr, 728 "Can not alloc memory for keyboard properties\n"); 729 goto out; 730 } 731 732 if (scf_pg_get_property(pg, KBD_PROP_KEYCLICK, prop) != 0 || 733 scf_property_get_value(prop, val) != 0 || 734 scf_value_get_boolean(val, &val_click) == -1) { 735 (void) fprintf(stderr, "Can not get KEYCLICK\n"); 736 } 737 738 if (val_click == 1) 739 (void) click("on", kbd); 740 else if (val_click == 0) 741 (void) click("off", kbd); 742 else 743 (void) fprintf(stderr, 744 BAD_DEFAULT_INT, KBD_PROP_KEYCLICK, val_click); 745 746 if (scf_pg_get_property(pg, KBD_PROP_KEYBOARD_ABORT, prop) != 0 || 747 scf_property_get_value(prop, val) != 0 || 748 scf_value_get_astring(val, val_abort, KBD_MAX_NAME_LEN) == -1) { 749 (void) fprintf(stderr, "Can not get KEYBOARD_ABORT\n"); 750 } 751 752 if (*val_abort != '\0') { 753 /* 754 * ABORT must equal "enable", "disable" or "alternate" 755 */ 756 if ((strcmp(val_abort, "enable") == 0) || 757 (strcmp(val_abort, "alternate") == 0) || 758 (strcmp(val_abort, "disable") == 0)) 759 (void) abort_enable(val_abort, kbd); 760 else 761 (void) fprintf(stderr, BAD_DEFAULT_STR, 762 KBD_PROP_KEYBOARD_ABORT, val_abort); 763 } 764 765 if (scf_pg_get_property(pg, KBD_PROP_RPTCOUNT, prop) != 0 || 766 scf_property_get_value(prop, val) != 0 || 767 scf_value_get_integer(val, &val_count) == -1) { 768 (void) fprintf(stderr, "Can not get RPTCOUNT\n"); 769 } 770 771 if (val_count == -1 || (val_count > 0 && val_count < INT_MAX)) 772 (void) set_rptcount(val_count, kbd); 773 else 774 (void) fprintf(stderr, 775 BAD_DEFAULT_LLINT, KBD_PROP_RPTCOUNT, val_count); 776 777 if (scf_pg_get_property(pg, KBD_PROP_RPTDELAY, prop) != 0 || 778 scf_property_get_value(prop, val) != 0 || 779 scf_value_get_integer(val, &val_delay) == -1) { 780 (void) fprintf(stderr, "Can not get RPTDELAY\n"); 781 } 782 783 if (val_delay > 0) 784 (void) set_rptdelay(val_delay, kbd); 785 else 786 (void) fprintf(stderr, 787 BAD_DEFAULT_LLINT, KBD_PROP_RPTDELAY, val_delay); 788 789 if (scf_pg_get_property(pg, KBD_PROP_RPTRATE, prop) != 0 || 790 scf_property_get_value(prop, val) != 0 || 791 scf_value_get_integer(val, &val_rate) == -1) { 792 (void) fprintf(stderr, "Can not get RPTRATE\n"); 793 } 794 795 if (val_rate > 0) 796 (void) set_rptrate(val_rate, kbd); 797 else 798 (void) fprintf(stderr, 799 BAD_DEFAULT_LLINT, KBD_PROP_RPTRATE, val_rate); 800 801 if (scf_pg_get_property(pg, KBD_PROP_LAYOUT, prop) != 0 || 802 scf_property_get_value(prop, val) != 0 || 803 scf_value_get_astring(val, val_layout, KBD_MAX_NAME_LEN) == -1) { 804 (void) fprintf(stderr, "Can not get LAYOUT\n"); 805 } 806 807 if (*val_layout != '\0') { 808 /* 809 * LAYOUT must be one of the layouts supported in kbd_layouts 810 */ 811 if (get_layouts() != 0) 812 goto out; 813 814 if ((layout_num = get_layout_number(val_layout)) == -1) { 815 (void) fprintf(stderr, 816 BAD_DEFAULT_STR, KBD_PROP_LAYOUT, val_layout); 817 goto out; 818 } 819 820 (void) set_layout(kbd, layout_num); 821 } 822 823 if (scf_pg_get_property(pg, KBD_PROP_FREQ, prop) != 0 || 824 scf_property_get_value(prop, val) != 0 || 825 scf_value_get_integer(val, &val_kbd_beeper) == -1) { 826 (void) fprintf(stderr, "Can not get FREQ\n"); 827 } 828 829 if (val_kbd_beeper >= 0 && val_kbd_beeper <= INT16_MAX) 830 (void) set_beep_freq(kbd, "keyboard", val_kbd_beeper); 831 else 832 (void) fprintf(stderr, 833 BAD_DEFAULT_LLINT, KBD_PROP_FREQ, val_kbd_beeper); 834 835 if (scf_pg_get_property(pg, KBD_PROP_CONSFREQ, prop) != 0 || 836 scf_property_get_value(prop, val) != 0 || 837 scf_value_get_integer(val, &val_console_beeper) == -1) { 838 (void) fprintf(stderr, "Can not get CONSFREQ\n"); 839 } 840 841 if (val_console_beeper >= 0 && val_console_beeper <= INT16_MAX) 842 (void) set_beep_freq(kbd, "console", val_console_beeper); 843 else 844 (void) fprintf(stderr, 845 BAD_DEFAULT_LLINT, KBD_PROP_CONSFREQ, val_console_beeper); 846 847 out: 848 if (val_layout != NULL) 849 free(val_layout); 850 if (val_abort != NULL) 851 free(val_abort); 852 if (snap != NULL) 853 scf_snapshot_destroy(snap); 854 scf_value_destroy(val); 855 scf_property_destroy(prop); 856 scf_pg_destroy(pg); 857 scf_instance_destroy(inst); 858 scf_handle_destroy(h); 859 } 860 861 static int 862 get_layout_number(char *layout) 863 { 864 int i; 865 int layout_number = -1; 866 867 for (i = 0; i < layout_count; i ++) { 868 if (strcmp(layout, layout_names[i]) == 0) { 869 layout_number = layout_numbers[i]; 870 break; 871 } 872 } 873 874 return (layout_number); 875 } 876 877 static int 878 get_layouts() 879 { 880 FILE *stream; 881 char buffer[MAX_LINE_SIZE]; 882 char *result = NULL; 883 int i = 0; 884 char *tmpbuf; 885 886 if ((stream = fopen(KBD_LAYOUT_FILE, "r")) == 0) { 887 perror(KBD_LAYOUT_FILE); 888 return (1); 889 } 890 891 while ((fgets(buffer, MAX_LINE_SIZE, stream) != NULL) && 892 (i < MAX_LAYOUT_NUM)) { 893 if (buffer[0] == '#') 894 continue; 895 if ((result = strtok(buffer, "=")) == NULL) 896 continue; 897 if ((tmpbuf = strdup(result)) != NULL) { 898 layout_names[i] = tmpbuf; 899 } else { 900 perror("out of memory getting layout names"); 901 return (1); 902 } 903 if ((result = strtok(NULL, "\n")) == NULL) 904 continue; 905 layout_numbers[i] = atoi(result); 906 if (strcmp(tmpbuf, "US-English") == 0) 907 default_layout_number = i; 908 i++; 909 } 910 layout_count = i; 911 912 return (0); 913 } 914 915 /* 916 * this routine sets the layout of the keyboard being used 917 */ 918 static int 919 set_layout(int kbd, int layout_num) 920 { 921 922 if (ioctl(kbd, KIOCSLAYOUT, layout_num)) { 923 perror("ioctl (set kbd layout)"); 924 return (1); 925 } 926 (void) system("/usr/bin/loadkeys"); 927 928 return (0); 929 } 930 931 static char *usage1 = 932 "kbd [-r] [-t] [-l] [-a enable|disable|alternate] [-c on|off]\n" 933 "\t [-d keyboard device] [-A count] [-D delay] [-R rate]"; 934 static char *usage2 = "kbd -i [-d keyboard device]"; 935 static char *usage3 = "kbd -s [language]"; 936 static char *usage4 = "kbd -b [keyboard|console] frequency"; 937 938 static void 939 usage(void) 940 { 941 (void) fprintf(stderr, "Usage:\t%s\n\t%s\n\t%s\n\t%s\n", usage1, 942 usage2, usage3, usage4); 943 } 944