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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 /* SunOS-4.0 1.60 */ 28 /* From: SunOS4.0 sundev/kbd.c */ 29 30 /* 31 * Keyboard input streams module - handles conversion of up/down codes to 32 * ASCII or event format. 33 */ 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/sysmacros.h> 37 #include <sys/signal.h> 38 #include <sys/termios.h> 39 #include <sys/termio.h> 40 #include <sys/stream.h> 41 #include <sys/stropts.h> 42 #include <sys/strsun.h> 43 #include <sys/kmem.h> 44 #include <sys/file.h> 45 #include <sys/uio.h> 46 #include <sys/errno.h> 47 #include <sys/time.h> 48 #include <sys/consdev.h> 49 #include <sys/kbd.h> 50 #include <sys/kbio.h> 51 #include <sys/kbdreg.h> 52 #include <sys/vuid_event.h> 53 #include <sys/debug.h> 54 #include <sys/ddi.h> 55 #include <sys/sunddi.h> 56 #include <sys/policy.h> 57 58 #include <sys/modctl.h> 59 #include <sys/beep.h> 60 #include <sys/int_limits.h> 61 62 static struct streamtab kbd_info; 63 64 static struct fmodsw fsw = { 65 "kb", 66 &kbd_info, 67 D_MP | D_MTPERMOD 68 }; 69 70 /* 71 * Module linkage information for the kernel. 72 */ 73 74 static struct modlstrmod modlstrmod = { 75 &mod_strmodops, "streams module for keyboard", &fsw 76 }; 77 78 static struct modlinkage modlinkage = { 79 MODREV_1, (void *)&modlstrmod, NULL 80 }; 81 82 int 83 _init(void) 84 { 85 return (mod_install(&modlinkage)); 86 } 87 88 int 89 _fini(void) 90 { 91 return (mod_remove(&modlinkage)); 92 } 93 94 int 95 _info(struct modinfo *modinfop) 96 { 97 return (mod_info(&modlinkage, modinfop)); 98 } 99 100 /* 101 * For now these are shared. 102 * These data structures are static (defined in keytables.c) thus 103 * there is no need to perform any locking. 104 */ 105 extern struct keyboards keytables[]; 106 extern char keystringtab[16][KTAB_STRLEN]; 107 extern struct compose_sequence_t kb_compose_table[]; 108 extern signed char kb_compose_map[]; 109 extern struct fltaccent_sequence_t kb_fltaccent_table[]; 110 extern uchar_t kb_numlock_table[]; 111 112 /* 113 * This value corresponds approximately to max 10 fingers 114 */ 115 static int kbd_downs_size = 15; 116 117 typedef struct key_event { 118 uchar_t key_station; /* Physical key station associated with event */ 119 Firm_event event; /* Event that sent out on down */ 120 } Key_event; 121 struct kbddata { 122 queue_t *kbdd_readq; 123 queue_t *kbdd_writeq; 124 mblk_t *kbdd_iocpending; /* "ioctl" awaiting buffer */ 125 mblk_t *kbdd_replypending; /* "ioctl" reply awaiting result */ 126 int kbdd_flags; /* random flags */ 127 bufcall_id_t kbdd_bufcallid; /* bufcall id */ 128 timeout_id_t kbdd_rptid; /* timeout id for kbdrpt() */ 129 timeout_id_t kbdd_layoutid; /* timeout id for kbdlayout() */ 130 int kbdd_iocid; /* ID of "ioctl" being waited for */ 131 int kbdd_iocerror; /* error return from "ioctl" */ 132 struct keyboardstate kbdd_state; 133 /* 134 * State of keyboard & keyboard 135 * specific settings, e.g., tables 136 */ 137 int kbdd_translate; /* Translate keycodes? */ 138 int kbdd_translatable; /* Keyboard is translatable? */ 139 int kbdd_compat; /* Generating pre-4.1 events? */ 140 short kbdd_ascii_addr; /* Vuid_id_addr for ascii events */ 141 short kbdd_top_addr; /* Vuid_id_addr for top events */ 142 short kbdd_vkey_addr; /* Vuid_id_addr for vkey events */ 143 struct key_event *kbdd_downs; 144 /* 145 * Table of key stations currently down 146 * that have firm events that need 147 * to be matched with up transitions 148 * when kbdd_translate is TR_*EVENT 149 */ 150 int kbdd_downs_entries; /* # of possible entries in kbdd_downs */ 151 uint_t kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */ 152 ushort_t compose_key; /* first compose key */ 153 ushort_t fltaccent_entry; /* floating accent keymap entry */ 154 char led_state; /* current state of LEDs */ 155 unsigned char shiftkey; /* used for the new abort keys */ 156 }; 157 158 #define KBD_OPEN 0x00000001 /* keyboard is open for business */ 159 #define KBD_IOCWAIT 0x00000002 /* "open" waiting for "ioctl" to finish */ 160 161 #define NO_HARD_RESET 0 /* don't do hard reset */ 162 #define HARD_RESET 1 /* do hard reset */ 163 164 165 /* 166 * Constants setup during the first open of a kbd (so that they can be patched 167 * for debugging purposes). 168 */ 169 static int kbd_repeatrate; 170 static int kbd_repeatdelay; 171 172 static int kbd_overflow_cnt; /* Number of times kbd overflowed input q */ 173 static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */ 174 175 #ifdef KBD_DEBUG 176 int kbd_debug = 0; 177 int kbd_ra_debug = 0; 178 int kbd_raw_debug = 0; 179 int kbd_rpt_debug = 0; 180 int kbd_input_debug = 0; 181 #endif /* KBD_DEBUG */ 182 183 static int kbdopen(queue_t *, dev_t *, int, int, cred_t *); 184 static int kbdclose(queue_t *, int, cred_t *); 185 static void kbdwput(queue_t *, mblk_t *); 186 static void kbdrput(queue_t *, mblk_t *); 187 188 static struct module_info kbdmiinfo = { 189 0, 190 "kb", 191 0, 192 INFPSZ, 193 2048, 194 128 195 }; 196 197 static struct qinit kbdrinit = { 198 (int (*)())kbdrput, 199 (int (*)())NULL, 200 kbdopen, 201 kbdclose, 202 (int (*)())NULL, 203 &kbdmiinfo 204 }; 205 206 static struct module_info kbdmoinfo = { 207 0, 208 "kb", 209 0, 210 INFPSZ, 211 2048, 212 128 213 }; 214 215 static struct qinit kbdwinit = { 216 (int (*)())kbdwput, 217 (int (*)())NULL, 218 kbdopen, 219 kbdclose, 220 (int (*)())NULL, 221 &kbdmoinfo 222 }; 223 224 static struct streamtab kbd_info = { 225 &kbdrinit, 226 &kbdwinit, 227 NULL, 228 NULL, 229 }; 230 231 static void kbdreioctl(void *); 232 static void kbdioctl(queue_t *, mblk_t *); 233 static void kbdflush(struct kbddata *); 234 static void kbduse(struct kbddata *, unsigned); 235 static void kbdsetled(struct kbddata *); 236 static void kbd_beep_off(void *arg); 237 static void kbd_beep_on(void *arg); 238 static void kbdcmd(queue_t *, char); 239 static void kbdreset(struct kbddata *, uint_t); 240 static int kbdsetkey(struct kbddata *, struct kiockey *, cred_t *); 241 static int kbdgetkey(struct kbddata *, struct kiockey *); 242 static int kbdskey(struct kbddata *, struct kiockeymap *, cred_t *); 243 static int kbdgkey(struct kbddata *, struct kiockeymap *); 244 static void kbdlayouttimeout(void *); 245 static void kbdinput(struct kbddata *, unsigned); 246 static void kbdid(struct kbddata *, int); 247 static struct keymap *settable(struct kbddata *, uint_t); 248 static void kbdrpt(void *); 249 static void kbdcancelrpt(struct kbddata *); 250 static void kbdtranslate(struct kbddata *, unsigned, queue_t *); 251 static int kbd_do_compose(ushort_t, ushort_t, ushort_t *); 252 static void kbd_send_esc_event(char, struct kbddata *); 253 char *strsetwithdecimal(char *, uint_t, uint_t); 254 static void kbdkeypressed(struct kbddata *, uchar_t, Firm_event *, 255 ushort_t); 256 static void kbdqueuepress(struct kbddata *, uchar_t, Firm_event *); 257 static void kbdkeyreleased(struct kbddata *, uchar_t); 258 static void kbdreleaseall(struct kbddata *); 259 static void kbdputcode(uint_t, queue_t *); 260 static void kbdputbuf(char *, queue_t *); 261 static void kbdqueueevent(struct kbddata *, Firm_event *); 262 263 /* 264 * Dummy qbufcall callback routine used by open and close. 265 * The framework will wake up qwait_sig when we return from 266 * this routine (as part of leaving the perimeters.) 267 * (The framework enters the perimeters before calling the qbufcall() callback 268 * and leaves the perimeters after the callback routine has executed. The 269 * framework performs an implicit wakeup of any thread in qwait/qwait_sig 270 * when it leaves the perimeter. See qwait(9E).) 271 */ 272 /* ARGSUSED */ 273 static void dummy_callback(void *arg) 274 {} 275 276 277 /* 278 * Open a keyboard. 279 * Ttyopen sets line characteristics 280 */ 281 /* ARGSUSED */ 282 static int 283 kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) 284 { 285 register int error; 286 register struct kbddata *kbdd; 287 mblk_t *mp; 288 mblk_t *datap; 289 register struct iocblk *iocb; 290 register struct termios *cb; 291 292 /* Set these up only once so that they could be changed from adb */ 293 if (!kbd_repeatrate) { 294 kbd_repeatrate = (hz+29)/30; 295 kbd_repeatdelay = hz/2; 296 } 297 298 if (q->q_ptr != NULL) 299 return (0); /* already attached */ 300 301 /* 302 * Only allow open requests to succeed for privileged users. This 303 * necessary to prevent users from pushing the "kb" module again 304 * on the stream associated with /dev/kbd. 305 */ 306 if (secpolicy_console(crp) != 0) { 307 return (EPERM); 308 } 309 310 311 switch (sflag) { 312 313 case MODOPEN: 314 break; 315 316 case CLONEOPEN: 317 return (EINVAL); /* No Bozos! */ 318 } 319 320 /* allocate keyboard */ 321 322 kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP); 323 324 325 /* 326 * Set up queue pointers, so that the "put" procedure will accept 327 * the reply to the "ioctl" message we send down. 328 */ 329 q->q_ptr = kbdd; 330 WR(q)->q_ptr = kbdd; 331 332 qprocson(q); 333 334 /* 335 * Setup tty modes. 336 */ 337 while ((mp = mkiocb(TCSETSF)) == NULL) { 338 timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI, 339 dummy_callback, NULL); 340 if (!qwait_sig(q)) { 341 qunbufcall(q, id); 342 kmem_free(kbdd, sizeof (struct kbddata)); 343 qprocsoff(q); 344 345 return (EINTR); 346 } 347 } 348 while ((datap = allocb(sizeof (struct termios), BPRI_HI)) == 349 NULL) { 350 timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI, 351 dummy_callback, NULL); 352 if (!qwait_sig(q)) { 353 qunbufcall(q, id); 354 freemsg(mp); 355 kmem_free(kbdd, sizeof (struct kbddata)); 356 qprocsoff(q); 357 358 return (EINTR); 359 } 360 } 361 362 iocb = (struct iocblk *)mp->b_rptr; 363 iocb->ioc_count = sizeof (struct termios); 364 365 cb = (struct termios *)datap->b_rptr; 366 cb->c_iflag = 0; 367 cb->c_oflag = 0; 368 cb->c_cflag = CREAD|CS8|B1200; 369 cb->c_lflag = 0; 370 bzero(cb->c_cc, NCCS); 371 datap->b_wptr += sizeof (struct termios); 372 mp->b_cont = datap; 373 kbdd->kbdd_flags |= KBD_IOCWAIT; /* indicate that we're */ 374 kbdd->kbdd_iocid = iocb->ioc_id; /* waiting for this response */ 375 putnext(WR(q), mp); 376 377 /* 378 * Now wait for it. Let our read queue put routine wake us up 379 * when it arrives. 380 */ 381 while (kbdd->kbdd_flags & KBD_IOCWAIT) { 382 if (!qwait_sig(q)) { 383 error = EINTR; 384 goto error; 385 } 386 } 387 if ((error = kbdd->kbdd_iocerror) != 0) 388 goto error; 389 390 /* 391 * Set up private data. 392 */ 393 kbdd->kbdd_readq = q; 394 kbdd->kbdd_writeq = WR(q); 395 kbdd->kbdd_iocpending = NULL; 396 kbdd->kbdd_translatable = TR_CAN; 397 kbdd->kbdd_translate = TR_ASCII; 398 kbdd->kbdd_compat = 1; 399 kbdd->kbdd_ascii_addr = ASCII_FIRST; 400 kbdd->kbdd_top_addr = TOP_FIRST; 401 kbdd->kbdd_vkey_addr = VKEY_FIRST; 402 /* Allocate dynamic memory for downs table */ 403 kbdd->kbdd_downs_entries = kbd_downs_size; 404 kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event); 405 kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP); 406 kbdd->kbdd_flags = KBD_OPEN; 407 kbdd->led_state = 0; 408 409 /* 410 * Reset kbd. 411 */ 412 kbdreset(kbdd, HARD_RESET); 413 414 (void) beep_init((void *)WR(q), kbd_beep_on, kbd_beep_off, NULL); 415 416 return (0); 417 418 error: 419 qprocsoff(q); 420 kmem_free(kbdd, sizeof (struct kbddata)); 421 return (error); 422 } 423 424 /* 425 * Close a keyboard. 426 */ 427 /* ARGSUSED1 */ 428 static int 429 kbdclose(register queue_t *q, int flag, cred_t *crp) 430 { 431 register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 432 register mblk_t *mp; 433 434 qprocsoff(q); 435 (void) beep_fini(); 436 /* 437 * Since we're about to destroy our private data, turn off 438 * our open flag first, so we don't accept any more input 439 * and try to use that data. 440 */ 441 kbdd->kbdd_flags = 0; 442 443 if ((mp = kbdd->kbdd_replypending) != NULL) { 444 /* 445 * There was a KIOCLAYOUT pending; presumably, it timed out. 446 * Throw the reply away. 447 */ 448 kbdd->kbdd_replypending = NULL; 449 freemsg(mp); 450 } 451 452 /* clear all timeouts */ 453 if (kbdd->kbdd_bufcallid) 454 qunbufcall(q, kbdd->kbdd_bufcallid); 455 if (kbdd->kbdd_rptid) 456 (void) quntimeout(q, kbdd->kbdd_rptid); 457 if (kbdd->kbdd_layoutid) 458 (void) quntimeout(q, kbdd->kbdd_layoutid); 459 kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 460 kmem_free(kbdd, sizeof (struct kbddata)); 461 return (0); 462 } 463 464 /* 465 * Line discipline output queue put procedure: handles M_IOCTL 466 * messages. 467 */ 468 static void 469 kbdwput(register queue_t *q, register mblk_t *mp) 470 { 471 /* 472 * Process M_FLUSH, and some M_IOCTL, messages here; pass 473 * everything else down. 474 */ 475 switch (mp->b_datap->db_type) { 476 477 case M_FLUSH: 478 if (*mp->b_rptr & FLUSHW) 479 flushq(q, FLUSHDATA); 480 if (*mp->b_rptr & FLUSHR) 481 flushq(RD(q), FLUSHDATA); 482 483 default: 484 putnext(q, mp); /* pass it down the line */ 485 break; 486 487 case M_IOCTL: 488 kbdioctl(q, mp); 489 break; 490 } 491 } 492 493 494 static void 495 kbdreioctl(void *kbdd_addr) 496 { 497 struct kbddata *kbdd = kbdd_addr; 498 queue_t *q; 499 mblk_t *mp; 500 501 kbdd->kbdd_bufcallid = 0; 502 q = kbdd->kbdd_writeq; 503 if ((mp = kbdd->kbdd_iocpending) != NULL) { 504 kbdd->kbdd_iocpending = NULL; /* not pending any more */ 505 kbdioctl(q, mp); 506 } 507 } 508 509 static void 510 kbdioctl(register queue_t *q, register mblk_t *mp) 511 { 512 register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 513 register struct iocblk *iocp; 514 register short new_translate; 515 register Vuid_addr_probe *addr_probe; 516 register short *addr_ptr; 517 mblk_t *datap; 518 size_t ioctlrespsize; 519 int err = 0; 520 int tmp; 521 int cycles; 522 int frequency; 523 int msecs; 524 525 iocp = (struct iocblk *)mp->b_rptr; 526 527 switch (iocp->ioc_cmd) { 528 529 case VUIDSFORMAT: 530 err = miocpullup(mp, sizeof (int)); 531 if (err != 0) 532 break; 533 534 new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ? 535 TR_ASCII : TR_EVENT; 536 if (new_translate == kbdd->kbdd_translate) 537 break; 538 kbdd->kbdd_translate = new_translate; 539 goto output_format_change; 540 541 case KIOCTRANS: 542 err = miocpullup(mp, sizeof (int)); 543 if (err != 0) 544 break; 545 546 new_translate = *(int *)mp->b_cont->b_rptr; 547 if (new_translate == kbdd->kbdd_translate) 548 break; 549 kbdd->kbdd_translate = new_translate; 550 goto output_format_change; 551 552 case KIOCCMD: 553 err = miocpullup(mp, sizeof (int)); 554 if (err != 0) 555 break; 556 557 tmp = (char)(*(int *)mp->b_cont->b_rptr); 558 if (tmp == KBD_CMD_BELL) 559 (void) beeper_on(BEEP_TYPE4); 560 else if (tmp == KBD_CMD_NOBELL) 561 (void) beeper_off(); 562 else 563 kbdcmd(q, tmp); 564 break; 565 566 case KIOCMKTONE: 567 if (iocp->ioc_count != TRANSPARENT) { 568 /* 569 * We don't support non-transparent ioctls, 570 * i.e. I_STR ioctls 571 */ 572 err = EINVAL; 573 break; 574 } 575 tmp = (int)(*(intptr_t *)mp->b_cont->b_rptr); 576 cycles = tmp & 0xffff; 577 msecs = (tmp >> 16) & 0xffff; 578 579 if (cycles == 0) 580 frequency = UINT16_MAX; 581 else if (cycles == UINT16_MAX) 582 frequency = 0; 583 else { 584 frequency = (PIT_HZ + cycles / 2) / cycles; 585 if (frequency > UINT16_MAX) 586 frequency = UINT16_MAX; 587 } 588 589 err = beep_mktone(frequency, msecs); 590 break; 591 592 case KIOCSLED: 593 err = miocpullup(mp, sizeof (uchar_t)); 594 if (err != 0) 595 break; 596 597 kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr; 598 kbdsetled(kbdd); 599 break; 600 601 case KIOCGLED: 602 if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) { 603 ioctlrespsize = sizeof (int); 604 goto allocfailure; 605 } 606 *(uchar_t *)datap->b_wptr = kbdd->led_state; 607 datap->b_wptr += sizeof (uchar_t); 608 if (mp->b_cont) /* free msg to prevent memory leak */ 609 freemsg(mp->b_cont); 610 mp->b_cont = datap; 611 iocp->ioc_count = sizeof (uchar_t); 612 break; 613 614 case VUIDGFORMAT: 615 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 616 ioctlrespsize = sizeof (int); 617 goto allocfailure; 618 } 619 *(int *)datap->b_wptr = 620 (kbdd->kbdd_translate == TR_EVENT || 621 kbdd->kbdd_translate == TR_UNTRANS_EVENT) ? 622 VUID_FIRM_EVENT: VUID_NATIVE; 623 datap->b_wptr += sizeof (int); 624 if (mp->b_cont) /* free msg to prevent memory leak */ 625 freemsg(mp->b_cont); 626 mp->b_cont = datap; 627 iocp->ioc_count = sizeof (int); 628 break; 629 630 case KIOCGTRANS: 631 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 632 ioctlrespsize = sizeof (int); 633 goto allocfailure; 634 } 635 *(int *)datap->b_wptr = kbdd->kbdd_translate; 636 datap->b_wptr += sizeof (int); 637 if (mp->b_cont) /* free msg to prevent memory leak */ 638 freemsg(mp->b_cont); 639 mp->b_cont = datap; 640 iocp->ioc_count = sizeof (int); 641 break; 642 643 case VUIDSADDR: 644 err = miocpullup(mp, sizeof (Vuid_addr_probe)); 645 if (err != 0) 646 break; 647 648 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 649 switch (addr_probe->base) { 650 651 case ASCII_FIRST: 652 addr_ptr = &kbdd->kbdd_ascii_addr; 653 break; 654 655 case TOP_FIRST: 656 addr_ptr = &kbdd->kbdd_top_addr; 657 break; 658 659 case VKEY_FIRST: 660 addr_ptr = &kbdd->kbdd_vkey_addr; 661 break; 662 663 default: 664 err = ENODEV; 665 } 666 if ((err == 0) && (*addr_ptr != addr_probe->data.next)) { 667 *addr_ptr = addr_probe->data.next; 668 goto output_format_change; 669 } 670 break; 671 672 case VUIDGADDR: 673 err = miocpullup(mp, sizeof (Vuid_addr_probe)); 674 if (err != 0) 675 break; 676 677 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 678 switch (addr_probe->base) { 679 680 case ASCII_FIRST: 681 addr_probe->data.current = kbdd->kbdd_ascii_addr; 682 break; 683 684 case TOP_FIRST: 685 addr_probe->data.current = kbdd->kbdd_top_addr; 686 break; 687 688 case VKEY_FIRST: 689 addr_probe->data.current = kbdd->kbdd_vkey_addr; 690 break; 691 692 default: 693 err = ENODEV; 694 } 695 break; 696 697 case KIOCTRANSABLE: 698 err = miocpullup(mp, sizeof (int)); 699 if (err != 0) 700 break; 701 702 if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) { 703 kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr; 704 kbdreset(kbdd, HARD_RESET); 705 goto output_format_change; 706 } 707 break; 708 709 case KIOCGTRANSABLE: 710 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 711 ioctlrespsize = sizeof (int); 712 goto allocfailure; 713 } 714 *(int *)datap->b_wptr = kbdd->kbdd_translatable; 715 datap->b_wptr += sizeof (int); 716 if (mp->b_cont) /* free msg to prevent memory leak */ 717 freemsg(mp->b_cont); 718 mp->b_cont = datap; 719 iocp->ioc_count = sizeof (int); 720 break; 721 722 case KIOCSCOMPAT: 723 err = miocpullup(mp, sizeof (int)); 724 if (err != 0) 725 break; 726 727 kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr; 728 break; 729 730 case KIOCGCOMPAT: 731 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 732 ioctlrespsize = sizeof (int); 733 goto allocfailure; 734 } 735 *(int *)datap->b_wptr = kbdd->kbdd_compat; 736 datap->b_wptr += sizeof (int); 737 if (mp->b_cont) /* free msg to prevent memory leak */ 738 freemsg(mp->b_cont); 739 mp->b_cont = datap; 740 iocp->ioc_count = sizeof (int); 741 break; 742 743 case KIOCSETKEY: 744 err = miocpullup(mp, sizeof (struct kiockey)); 745 if (err != 0) 746 break; 747 748 err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr, 749 iocp->ioc_cr); 750 /* 751 * Since this only affects any subsequent key presses, 752 * don't goto output_format_change. One might want to 753 * toggle the keytable entries dynamically. 754 */ 755 break; 756 757 case KIOCGETKEY: 758 err = miocpullup(mp, sizeof (struct kiockey)); 759 if (err != 0) 760 break; 761 762 err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr); 763 break; 764 765 case KIOCSKEY: 766 err = miocpullup(mp, sizeof (struct kiockeymap)); 767 if (err != 0) 768 break; 769 770 err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr, 771 iocp->ioc_cr); 772 /* 773 * Since this only affects any subsequent key presses, 774 * don't goto output_format_change. One might want to 775 * toggle the keytable entries dynamically. 776 */ 777 break; 778 779 case KIOCGKEY: 780 err = miocpullup(mp, sizeof (struct kiockeymap)); 781 if (err != 0) 782 break; 783 784 err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr); 785 break; 786 787 case KIOCSDIRECT: 788 goto output_format_change; 789 790 case KIOCGDIRECT: 791 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 792 ioctlrespsize = sizeof (int); 793 goto allocfailure; 794 } 795 *(int *)datap->b_wptr = 1; /* always direct */ 796 datap->b_wptr += sizeof (int); 797 if (mp->b_cont) /* free msg to prevent memory leak */ 798 freemsg(mp->b_cont); 799 mp->b_cont = datap; 800 iocp->ioc_count = sizeof (int); 801 break; 802 803 case KIOCTYPE: 804 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 805 ioctlrespsize = sizeof (int); 806 goto allocfailure; 807 } 808 *(int *)datap->b_wptr = kbdd->kbdd_state.k_id; 809 datap->b_wptr += sizeof (int); 810 if (mp->b_cont) /* free msg to prevent memory leak */ 811 freemsg(mp->b_cont); 812 mp->b_cont = datap; 813 iocp->ioc_count = sizeof (int); 814 break; 815 816 case KIOCLAYOUT: 817 if ((datap = kbdd->kbdd_replypending) != NULL) { 818 /* 819 * There was an earlier KIOCLAYOUT pending; presumably, 820 * it timed out. Throw the reply away. 821 */ 822 kbdd->kbdd_replypending = NULL; 823 freemsg(datap); 824 } 825 826 if (kbdd->kbdd_state.k_id == KB_SUN4 || 827 kbdd->kbdd_state.k_id == KB_PC) { 828 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 829 ioctlrespsize = sizeof (int); 830 goto allocfailure; 831 } 832 iocp->ioc_rval = 0; 833 iocp->ioc_error = 0; /* brain rot */ 834 iocp->ioc_count = sizeof (int); 835 if (mp->b_cont) /* free msg to prevent memory leak */ 836 freemsg(mp->b_cont); 837 mp->b_cont = datap; 838 mp->b_datap->db_type = M_IOCACK; 839 kbdd->kbdd_replypending = mp; 840 kbdcmd(q, (char)KBD_CMD_GETLAYOUT); 841 if (kbdd->kbdd_layoutid) 842 (void) quntimeout(q, kbdd->kbdd_layoutid); 843 kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout, 844 kbdd, hz / 5); 845 return; /* wait for reply from keyboard */ 846 } else { 847 /* 848 * Not a Type 4 keyboard; return an immediate error. 849 */ 850 err = EINVAL; 851 break; 852 } 853 854 case KIOCGRPTDELAY: 855 /* 856 * Report the autorepeat delay, unit in millisecond 857 */ 858 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 859 ioctlrespsize = sizeof (int); 860 goto allocfailure; 861 } 862 *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay); 863 datap->b_wptr += sizeof (int); 864 865 /* free msg to prevent memory leak */ 866 if (mp->b_cont != NULL) 867 freemsg(mp->b_cont); 868 mp->b_cont = datap; 869 iocp->ioc_count = sizeof (int); 870 break; 871 872 case KIOCSRPTDELAY: 873 /* 874 * Set the autorepeat delay 875 */ 876 err = miocpullup(mp, sizeof (int)); 877 878 if (err != 0) 879 break; 880 881 /* validate the input */ 882 if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) { 883 err = EINVAL; 884 break; 885 } 886 kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 887 if (kbd_repeatdelay <= 0) 888 kbd_repeatdelay = 1; 889 break; 890 891 case KIOCGRPTRATE: 892 /* 893 * Report the autorepeat rate 894 */ 895 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 896 ioctlrespsize = sizeof (int); 897 goto allocfailure; 898 } 899 *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate); 900 datap->b_wptr += sizeof (int); 901 902 /* free msg to prevent memory leak */ 903 if (mp->b_cont != NULL) 904 freemsg(mp->b_cont); 905 mp->b_cont = datap; 906 iocp->ioc_count = sizeof (int); 907 break; 908 909 case KIOCSRPTRATE: 910 /* 911 * Set the autorepeat rate 912 */ 913 err = miocpullup(mp, sizeof (int)); 914 915 if (err != 0) 916 break; 917 918 /* validate the input */ 919 if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) { 920 err = EINVAL; 921 break; 922 } 923 kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 924 if (kbd_repeatrate <= 0) 925 kbd_repeatrate = 1; 926 break; 927 928 default: 929 putnext(q, mp); /* pass it down the line */ 930 return; 931 } 932 goto done; 933 934 output_format_change: 935 kbdflush(kbdd); 936 937 done: 938 if (err != 0) { 939 iocp->ioc_rval = 0; 940 iocp->ioc_error = err; 941 mp->b_datap->db_type = M_IOCNAK; 942 } else { 943 iocp->ioc_rval = 0; 944 iocp->ioc_error = 0; /* brain rot */ 945 mp->b_datap->db_type = M_IOCACK; 946 } 947 qreply(q, mp); 948 return; 949 950 allocfailure: 951 /* 952 * We needed to allocate something to handle this "ioctl", but 953 * couldn't; save this "ioctl" and arrange to get called back when 954 * it's more likely that we can get what we need. 955 * If there's already one being saved, throw it out, since it 956 * must have timed out. 957 */ 958 if (kbdd->kbdd_iocpending != NULL) 959 freemsg(kbdd->kbdd_iocpending); 960 kbdd->kbdd_iocpending = mp; 961 if (kbdd->kbdd_bufcallid) 962 qunbufcall(q, kbdd->kbdd_bufcallid); 963 kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI, 964 kbdreioctl, kbdd); 965 } 966 967 static void 968 kbdflush(register struct kbddata *kbdd) 969 { 970 register queue_t *q; 971 972 /* Flush pending data already sent upstream */ 973 if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL) 974 (void) putnextctl1(q, M_FLUSH, FLUSHR); 975 /* Flush pending ups */ 976 bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 977 kbdcancelrpt(kbdd); 978 } 979 980 /* 981 * Pass keycode upstream, either translated or untranslated. 982 */ 983 static void 984 kbduse(register struct kbddata *kbdd, unsigned keycode) 985 { 986 register queue_t *readq; 987 988 #ifdef KBD_DEBUG 989 if (kbd_input_debug) printf("KBD USE key=%d\n", keycode); 990 #endif 991 992 if ((readq = kbdd->kbdd_readq) == NULL) 993 return; 994 if (!kbdd->kbdd_translatable || 995 kbdd->kbdd_translate == TR_NONE) 996 kbdputcode(keycode, readq); 997 else 998 kbdtranslate(kbdd, keycode, readq); 999 } 1000 1001 static void 1002 kbd_beep_on(void *arg) 1003 { 1004 kbdcmd((queue_t *)arg, KBD_CMD_BELL); 1005 } 1006 1007 1008 static void 1009 kbd_beep_off(void *arg) 1010 { 1011 kbdcmd((queue_t *)arg, KBD_CMD_NOBELL); 1012 } 1013 1014 1015 /* 1016 * kbdclick is used to remember the current click value of the 1017 * Sun-3 keyboard. This brain damaged keyboard will reset the 1018 * clicking to the "default" value after a reset command and 1019 * there is no way to read out the current click value. We 1020 * cannot send a click command immediately after the reset 1021 * command or the keyboard gets screwed up. So we wait until 1022 * we get the ID byte before we send back the click command. 1023 * Unfortunately, this means that there is a small window 1024 * where the keyboard can click when it really shouldn't be. 1025 * A value of -1 means that kbdclick has not been initialized yet. 1026 */ 1027 static int kbdclick = -1; 1028 1029 /* 1030 * Send command byte to keyboard, if you can. 1031 */ 1032 static void 1033 kbdcmd(register queue_t *q, char cmd) 1034 { 1035 register mblk_t *bp; 1036 1037 if (canput(q)) { 1038 if ((bp = allocb(1, BPRI_MED)) == NULL) 1039 cmn_err(CE_WARN, 1040 "kbdcmd: Can't allocate block for command"); 1041 else { 1042 *bp->b_wptr++ = cmd; 1043 putnext(q, bp); 1044 if (cmd == KBD_CMD_NOCLICK) 1045 kbdclick = 0; 1046 else if (cmd == KBD_CMD_CLICK) 1047 kbdclick = 1; 1048 } 1049 } 1050 } 1051 1052 /* 1053 * Update the keyboard LEDs to match the current keyboard state. 1054 * Do this only on Type 4 keyboards; other keyboards don't support the 1055 * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs). 1056 */ 1057 static void 1058 kbdsetled(register struct kbddata *kbdd) 1059 { 1060 if (kbdd->kbdd_state.k_id == KB_SUN4 || 1061 kbdd->kbdd_state.k_id == KB_PC) { 1062 kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED); 1063 kbdcmd(kbdd->kbdd_writeq, kbdd->led_state); 1064 } 1065 } 1066 1067 /* 1068 * Reset the keyboard 1069 */ 1070 static void 1071 kbdreset(register struct kbddata *kbdd, uint_t hard_reset) 1072 { 1073 register struct keyboardstate *k; 1074 1075 k = &kbdd->kbdd_state; 1076 if (kbdd->kbdd_translatable) { 1077 k->k_idstate = KID_NONE; 1078 k->k_id = -1; 1079 k->k_state = NORMAL; 1080 if (hard_reset) 1081 kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET); 1082 } else { 1083 bzero(k, sizeof (struct keyboardstate)); 1084 k->k_id = KB_ASCII; 1085 k->k_idstate = KID_OK; 1086 } 1087 } 1088 1089 /* 1090 * Old special codes. 1091 */ 1092 #define OLD_SHIFTKEYS 0x80 1093 #define OLD_BUCKYBITS 0x90 1094 #define OLD_FUNNY 0xA0 1095 #define OLD_FA_UMLAUT 0xA9 1096 #define OLD_FA_CFLEX 0xAA 1097 #define OLD_FA_TILDE 0xAB 1098 #define OLD_FA_CEDILLA 0xAC 1099 #define OLD_FA_ACUTE 0xAD 1100 #define OLD_FA_GRAVE 0xAE 1101 #define OLD_ISOCHAR 0xAF 1102 #define OLD_S