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