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 60 static struct streamtab kbd_info; 61 62 static struct fmodsw fsw = { 63 "kb", 64 &kbd_info, 65 D_MP | D_MTPERMOD 66 }; 67 68 /* 69 * Module linkage information for the kernel. 70 */ 71 72 static struct modlstrmod modlstrmod = { 73 &mod_strmodops, "streams module for keyboard", &fsw 74 }; 75 76 static struct modlinkage modlinkage = { 77 MODREV_1, (void *)&modlstrmod, NULL 78 }; 79 80 int 81 _init(void) 82 { 83 return (mod_install(&modlinkage)); 84 } 85 86 int 87 _fini(void) 88 { 89 return (mod_remove(&modlinkage)); 90 } 91 92 int 93 _info(struct modinfo *modinfop) 94 { 95 return (mod_info(&modlinkage, modinfop)); 96 } 97 98 /* 99 * For now these are shared. 100 * These data structures are static (defined in keytables.c) thus 101 * there is no need to perform any locking. 102 */ 103 extern struct keyboards keytables[]; 104 extern char keystringtab[16][KTAB_STRLEN]; 105 extern struct compose_sequence_t kb_compose_table[]; 106 extern signed char kb_compose_map[]; 107 extern struct fltaccent_sequence_t kb_fltaccent_table[]; 108 extern uchar_t kb_numlock_table[]; 109 110 /* 111 * This value corresponds approximately to max 10 fingers 112 */ 113 static int kbd_downs_size = 15; 114 115 typedef struct key_event { 116 uchar_t key_station; /* Physical key station associated with event */ 117 Firm_event event; /* Event that sent out on down */ 118 } Key_event; 119 struct kbddata { 120 queue_t *kbdd_readq; 121 queue_t *kbdd_writeq; 122 mblk_t *kbdd_iocpending; /* "ioctl" awaiting buffer */ 123 mblk_t *kbdd_replypending; /* "ioctl" reply awaiting result */ 124 int kbdd_flags; /* random flags */ 125 bufcall_id_t kbdd_bufcallid; /* bufcall id */ 126 timeout_id_t kbdd_rptid; /* timeout id for kbdrpt() */ 127 timeout_id_t kbdd_layoutid; /* timeout id for kbdlayout() */ 128 int kbdd_iocid; /* ID of "ioctl" being waited for */ 129 int kbdd_iocerror; /* error return from "ioctl" */ 130 struct keyboardstate kbdd_state; 131 /* 132 * State of keyboard & keyboard 133 * specific settings, e.g., tables 134 */ 135 int kbdd_translate; /* Translate keycodes? */ 136 int kbdd_translatable; /* Keyboard is translatable? */ 137 int kbdd_compat; /* Generating pre-4.1 events? */ 138 short kbdd_ascii_addr; /* Vuid_id_addr for ascii events */ 139 short kbdd_top_addr; /* Vuid_id_addr for top events */ 140 short kbdd_vkey_addr; /* Vuid_id_addr for vkey events */ 141 struct key_event *kbdd_downs; 142 /* 143 * Table of key stations currently down 144 * that have firm events that need 145 * to be matched with up transitions 146 * when kbdd_translate is TR_*EVENT 147 */ 148 int kbdd_downs_entries; /* # of possible entries in kbdd_downs */ 149 uint_t kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */ 150 ushort_t compose_key; /* first compose key */ 151 ushort_t fltaccent_entry; /* floating accent keymap entry */ 152 char led_state; /* current state of LEDs */ 153 }; 154 155 #define KBD_OPEN 0x00000001 /* keyboard is open for business */ 156 #define KBD_IOCWAIT 0x00000002 /* "open" waiting for "ioctl" to finish */ 157 158 #define NO_HARD_RESET 0 /* don't do hard reset */ 159 #define HARD_RESET 1 /* do hard reset */ 160 161 162 /* 163 * Constants setup during the first open of a kbd (so that they can be patched 164 * for debugging purposes). 165 */ 166 static int kbd_repeatrate; 167 static int kbd_repeatdelay; 168 169 static int kbd_overflow_cnt; /* Number of times kbd overflowed input q */ 170 static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */ 171 172 #ifdef KBD_DEBUG 173 int kbd_debug = 0; 174 int kbd_ra_debug = 0; 175 int kbd_raw_debug = 0; 176 int kbd_rpt_debug = 0; 177 int kbd_input_debug = 0; 178 #endif /* KBD_DEBUG */ 179 180 static int kbdopen(queue_t *, dev_t *, int, int, cred_t *); 181 static int kbdclose(queue_t *, int, cred_t *); 182 static void kbdwput(queue_t *, mblk_t *); 183 static void kbdrput(queue_t *, mblk_t *); 184 185 static struct module_info kbdmiinfo = { 186 0, 187 "kb", 188 0, 189 INFPSZ, 190 2048, 191 128 192 }; 193 194 static struct qinit kbdrinit = { 195 (int (*)())kbdrput, 196 (int (*)())NULL, 197 kbdopen, 198 kbdclose, 199 (int (*)())NULL, 200 &kbdmiinfo 201 }; 202 203 static struct module_info kbdmoinfo = { 204 0, 205 "kb", 206 0, 207 INFPSZ, 208 2048, 209 128 210 }; 211 212 static struct qinit kbdwinit = { 213 (int (*)())kbdwput, 214 (int (*)())NULL, 215 kbdopen, 216 kbdclose, 217 (int (*)())NULL, 218 &kbdmoinfo 219 }; 220 221 static struct streamtab kbd_info = { 222 &kbdrinit, 223 &kbdwinit, 224 NULL, 225 NULL, 226 }; 227 228 static void kbdreioctl(void *); 229 static void kbdioctl(queue_t *, mblk_t *); 230 static void kbdflush(struct kbddata *); 231 static void kbduse(struct kbddata *, unsigned); 232 static void kbdsetled(struct kbddata *); 233 static void kbdcmd(queue_t *, char); 234 static void kbdreset(struct kbddata *, uint_t); 235 static int kbdsetkey(struct kbddata *, struct kiockey *, cred_t *); 236 static int kbdgetkey(struct kbddata *, struct kiockey *); 237 static int kbdskey(struct kbddata *, struct kiockeymap *, cred_t *); 238 static int kbdgkey(struct kbddata *, struct kiockeymap *); 239 static void kbdlayouttimeout(void *); 240 static void kbdinput(struct kbddata *, unsigned); 241 static void kbdid(struct kbddata *, int); 242 static struct keymap *settable(struct kbddata *, uint_t); 243 static void kbdrpt(void *); 244 static void kbdcancelrpt(struct kbddata *); 245 static void kbdtranslate(struct kbddata *, unsigned, queue_t *); 246 static int kbd_do_compose(ushort_t, ushort_t, ushort_t *); 247 static void kbd_send_esc_event(char, struct kbddata *); 248 char *strsetwithdecimal(char *, uint_t, uint_t); 249 static void kbdkeypressed(struct kbddata *, uchar_t, Firm_event *, 250 ushort_t); 251 static void kbdqueuepress(struct kbddata *, uchar_t, Firm_event *); 252 static void kbdkeyreleased(struct kbddata *, uchar_t); 253 static void kbdreleaseall(struct kbddata *); 254 static void kbdputcode(uint_t, queue_t *); 255 static void kbdputbuf(char *, queue_t *); 256 static void kbdqueueevent(struct kbddata *, Firm_event *); 257 258 /* 259 * Dummy qbufcall callback routine used by open and close. 260 * The framework will wake up qwait_sig when we return from 261 * this routine (as part of leaving the perimeters.) 262 * (The framework enters the perimeters before calling the qbufcall() callback 263 * and leaves the perimeters after the callback routine has executed. The 264 * framework performs an implicit wakeup of any thread in qwait/qwait_sig 265 * when it leaves the perimeter. See qwait(9E).) 266 */ 267 /* ARGSUSED */ 268 static void dummy_callback(void *arg) 269 {} 270 271 272 /* 273 * Open a keyboard. 274 * Ttyopen sets line characteristics 275 */ 276 /* ARGSUSED */ 277 static int 278 kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) 279 { 280 register int error; 281 register struct kbddata *kbdd; 282 mblk_t *mp; 283 mblk_t *datap; 284 register struct iocblk *iocb; 285 register struct termios *cb; 286 287 /* Set these up only once so that they could be changed from adb */ 288 if (!kbd_repeatrate) { 289 kbd_repeatrate = (hz+29)/30; 290 kbd_repeatdelay = hz/2; 291 } 292 293 if (q->q_ptr != NULL) 294 return (0); /* already attached */ 295 296 /* 297 * Only allow open requests to succeed for privileged users. This 298 * necessary to prevent users from pushing the "kb" module again 299 * on the stream associated with /dev/kbd. 300 */ 301 if (secpolicy_console(crp) != 0) { 302 return (EPERM); 303 } 304 305 306 switch (sflag) { 307 308 case MODOPEN: 309 break; 310 311 case CLONEOPEN: 312 return (EINVAL); /* No Bozos! */ 313 } 314 315 /* allocate keyboard */ 316 317 kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP); 318 319 320 /* 321 * Set up queue pointers, so that the "put" procedure will accept 322 * the reply to the "ioctl" message we send down. 323 */ 324 q->q_ptr = kbdd; 325 WR(q)->q_ptr = kbdd; 326 327 qprocson(q); 328 329 /* 330 * Setup tty modes. 331 */ 332 while ((mp = mkiocb(TCSETSF)) == NULL) { 333 timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI, 334 dummy_callback, NULL); 335 if (!qwait_sig(q)) { 336 qunbufcall(q, id); 337 kmem_free(kbdd, sizeof (struct kbddata)); 338 qprocsoff(q); 339 340 return (EINTR); 341 } 342 } 343 while ((datap = allocb(sizeof (struct termios), BPRI_HI)) == 344 NULL) { 345 timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI, 346 dummy_callback, NULL); 347 if (!qwait_sig(q)) { 348 qunbufcall(q, id); 349 freemsg(mp); 350 kmem_free(kbdd, sizeof (struct kbddata)); 351 qprocsoff(q); 352 353 return (EINTR); 354 } 355 } 356 357 iocb = (struct iocblk *)mp->b_rptr; 358 iocb->ioc_count = sizeof (struct termios); 359 360 cb = (struct termios *)datap->b_rptr; 361 cb->c_iflag = 0; 362 cb->c_oflag = 0; 363 cb->c_cflag = CREAD|CS8|B1200; 364 cb->c_lflag = 0; 365 bzero(cb->c_cc, NCCS); 366 datap->b_wptr += sizeof (struct termios); 367 mp->b_cont = datap; 368 kbdd->kbdd_flags |= KBD_IOCWAIT; /* indicate that we're */ 369 kbdd->kbdd_iocid = iocb->ioc_id; /* waiting for this response */ 370 putnext(WR(q), mp); 371 372 /* 373 * Now wait for it. Let our read queue put routine wake us up 374 * when it arrives. 375 */ 376 while (kbdd->kbdd_flags & KBD_IOCWAIT) { 377 if (!qwait_sig(q)) { 378 error = EINTR; 379 goto error; 380 } 381 } 382 if ((error = kbdd->kbdd_iocerror) != 0) 383 goto error; 384 385 /* 386 * Set up private data. 387 */ 388 kbdd->kbdd_readq = q; 389 kbdd->kbdd_writeq = WR(q); 390 kbdd->kbdd_iocpending = NULL; 391 kbdd->kbdd_translatable = TR_CAN; 392 kbdd->kbdd_translate = TR_ASCII; 393 kbdd->kbdd_compat = 1; 394 kbdd->kbdd_ascii_addr = ASCII_FIRST; 395 kbdd->kbdd_top_addr = TOP_FIRST; 396 kbdd->kbdd_vkey_addr = VKEY_FIRST; 397 /* Allocate dynamic memory for downs table */ 398 kbdd->kbdd_downs_entries = kbd_downs_size; 399 kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event); 400 kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP); 401 kbdd->kbdd_flags = KBD_OPEN; 402 kbdd->led_state = 0; 403 404 /* 405 * Reset kbd. 406 */ 407 kbdreset(kbdd, HARD_RESET); 408 409 return (0); 410 411 error: 412 qprocsoff(q); 413 kmem_free(kbdd, sizeof (struct kbddata)); 414 return (error); 415 } 416 417 /* 418 * Close a keyboard. 419 */ 420 /* ARGSUSED1 */ 421 static int 422 kbdclose(register queue_t *q, int flag, cred_t *crp) 423 { 424 register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 425 register mblk_t *mp; 426 427 qprocsoff(q); 428 /* 429 * Since we're about to destroy our private data, turn off 430 * our open flag first, so we don't accept any more input 431 * and try to use that data. 432 */ 433 kbdd->kbdd_flags = 0; 434 435 if ((mp = kbdd->kbdd_replypending) != NULL) { 436 /* 437 * There was a KIOCLAYOUT pending; presumably, it timed out. 438 * Throw the reply away. 439 */ 440 kbdd->kbdd_replypending = NULL; 441 freemsg(mp); 442 } 443 444 /* clear all timeouts */ 445 if (kbdd->kbdd_bufcallid) 446 qunbufcall(q, kbdd->kbdd_bufcallid); 447 if (kbdd->kbdd_rptid) 448 (void) quntimeout(q, kbdd->kbdd_rptid); 449 if (kbdd->kbdd_layoutid) 450 (void) quntimeout(q, kbdd->kbdd_layoutid); 451 kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 452 kmem_free(kbdd, sizeof (struct kbddata)); 453 return (0); 454 } 455 456 /* 457 * Line discipline output queue put procedure: handles M_IOCTL 458 * messages. 459 */ 460 static void 461 kbdwput(register queue_t *q, register mblk_t *mp) 462 { 463 /* 464 * Process M_FLUSH, and some M_IOCTL, messages here; pass 465 * everything else down. 466 */ 467 switch (mp->b_datap->db_type) { 468 469 case M_FLUSH: 470 if (*mp->b_rptr & FLUSHW) 471 flushq(q, FLUSHDATA); 472 if (*mp->b_rptr & FLUSHR) 473 flushq(RD(q), FLUSHDATA); 474 475 default: 476 putnext(q, mp); /* pass it down the line */ 477 break; 478 479 case M_IOCTL: 480 kbdioctl(q, mp); 481 break; 482 } 483 } 484 485 486 static void 487 kbdreioctl(void *kbdd_addr) 488 { 489 struct kbddata *kbdd = kbdd_addr; 490 queue_t *q; 491 mblk_t *mp; 492 493 kbdd->kbdd_bufcallid = 0; 494 q = kbdd->kbdd_writeq; 495 if ((mp = kbdd->kbdd_iocpending) != NULL) { 496 kbdd->kbdd_iocpending = NULL; /* not pending any more */ 497 kbdioctl(q, mp); 498 } 499 } 500 501 static void 502 kbdioctl(register queue_t *q, register mblk_t *mp) 503 { 504 register struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 505 register struct iocblk *iocp; 506 register short new_translate; 507 register Vuid_addr_probe *addr_probe; 508 register short *addr_ptr; 509 mblk_t *datap; 510 size_t ioctlrespsize; 511 int err = 0; 512 513 iocp = (struct iocblk *)mp->b_rptr; 514 515 switch (iocp->ioc_cmd) { 516 517 case VUIDSFORMAT: 518 err = miocpullup(mp, sizeof (int)); 519 if (err != 0) 520 break; 521 522 new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ? 523 TR_ASCII : TR_EVENT; 524 if (new_translate == kbdd->kbdd_translate) 525 break; 526 kbdd->kbdd_translate = new_translate; 527 goto output_format_change; 528 529 case KIOCTRANS: 530 err = miocpullup(mp, sizeof (int)); 531 if (err != 0) 532 break; 533 534 new_translate = *(int *)mp->b_cont->b_rptr; 535 if (new_translate == kbdd->kbdd_translate) 536 break; 537 kbdd->kbdd_translate = new_translate; 538 goto output_format_change; 539 540 case KIOCCMD: 541 err = miocpullup(mp, sizeof (int)); 542 if (err != 0) 543 break; 544 545 kbdcmd(q, (char)(*(int *)mp->b_cont->b_rptr)); 546 break; 547 548 case KIOCSLED: 549 err = miocpullup(mp, sizeof (uchar_t)); 550 if (err != 0) 551 break; 552 553 kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr; 554 kbdsetled(kbdd); 555 break; 556 557 case KIOCGLED: 558 if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) { 559 ioctlrespsize = sizeof (int); 560 goto allocfailure; 561 } 562 *(uchar_t *)datap->b_wptr = kbdd->led_state; 563 datap->b_wptr += sizeof (uchar_t); 564 if (mp->b_cont) /* free msg to prevent memory leak */ 565 freemsg(mp->b_cont); 566 mp->b_cont = datap; 567 iocp->ioc_count = sizeof (uchar_t); 568 break; 569 570 case VUIDGFORMAT: 571 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 572 ioctlrespsize = sizeof (int); 573 goto allocfailure; 574 } 575 *(int *)datap->b_wptr = 576 (kbdd->kbdd_translate == TR_EVENT || 577 kbdd->kbdd_translate == TR_UNTRANS_EVENT) ? 578 VUID_FIRM_EVENT: VUID_NATIVE; 579 datap->b_wptr += sizeof (int); 580 if (mp->b_cont) /* free msg to prevent memory leak */ 581 freemsg(mp->b_cont); 582 mp->b_cont = datap; 583 iocp->ioc_count = sizeof (int); 584 break; 585 586 case KIOCGTRANS: 587 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 588 ioctlrespsize = sizeof (int); 589 goto allocfailure; 590 } 591 *(int *)datap->b_wptr = kbdd->kbdd_translate; 592 datap->b_wptr += sizeof (int); 593 if (mp->b_cont) /* free msg to prevent memory leak */ 594 freemsg(mp->b_cont); 595 mp->b_cont = datap; 596 iocp->ioc_count = sizeof (int); 597 break; 598 599 case VUIDSADDR: 600 err = miocpullup(mp, sizeof (Vuid_addr_probe)); 601 if (err != 0) 602 break; 603 604 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 605 switch (addr_probe->base) { 606 607 case ASCII_FIRST: 608 addr_ptr = &kbdd->kbdd_ascii_addr; 609 break; 610 611 case TOP_FIRST: 612 addr_ptr = &kbdd->kbdd_top_addr; 613 break; 614 615 case VKEY_FIRST: 616 addr_ptr = &kbdd->kbdd_vkey_addr; 617 break; 618 619 default: 620 err = ENODEV; 621 } 622 if ((err == 0) && (*addr_ptr != addr_probe->data.next)) { 623 *addr_ptr = addr_probe->data.next; 624 goto output_format_change; 625 } 626 break; 627 628 case VUIDGADDR: 629 err = miocpullup(mp, sizeof (Vuid_addr_probe)); 630 if (err != 0) 631 break; 632 633 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 634 switch (addr_probe->base) { 635 636 case ASCII_FIRST: 637 addr_probe->data.current = kbdd->kbdd_ascii_addr; 638 break; 639 640 case TOP_FIRST: 641 addr_probe->data.current = kbdd->kbdd_top_addr; 642 break; 643 644 case VKEY_FIRST: 645 addr_probe->data.current = kbdd->kbdd_vkey_addr; 646 break; 647 648 default: 649 err = ENODEV; 650 } 651 break; 652 653 case KIOCTRANSABLE: 654 err = miocpullup(mp, sizeof (int)); 655 if (err != 0) 656 break; 657 658 if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) { 659 kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr; 660 kbdreset(kbdd, HARD_RESET); 661 goto output_format_change; 662 } 663 break; 664 665 case KIOCGTRANSABLE: 666 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 667 ioctlrespsize = sizeof (int); 668 goto allocfailure; 669 } 670 *(int *)datap->b_wptr = kbdd->kbdd_translatable; 671 datap->b_wptr += sizeof (int); 672 if (mp->b_cont) /* free msg to prevent memory leak */ 673 freemsg(mp->b_cont); 674 mp->b_cont = datap; 675 iocp->ioc_count = sizeof (int); 676 break; 677 678 case KIOCSCOMPAT: 679 err = miocpullup(mp, sizeof (int)); 680 if (err != 0) 681 break; 682 683 kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr; 684 break; 685 686 case KIOCGCOMPAT: 687 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 688 ioctlrespsize = sizeof (int); 689 goto allocfailure; 690 } 691 *(int *)datap->b_wptr = kbdd->kbdd_compat; 692 datap->b_wptr += sizeof (int); 693 if (mp->b_cont) /* free msg to prevent memory leak */ 694 freemsg(mp->b_cont); 695 mp->b_cont = datap; 696 iocp->ioc_count = sizeof (int); 697 break; 698 699 case KIOCSETKEY: 700 err = miocpullup(mp, sizeof (struct kiockey)); 701 if (err != 0) 702 break; 703 704 err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr, 705 iocp->ioc_cr); 706 /* 707 * Since this only affects any subsequent key presses, 708 * don't goto output_format_change. One might want to 709 * toggle the keytable entries dynamically. 710 */ 711 break; 712 713 case KIOCGETKEY: 714 err = miocpullup(mp, sizeof (struct kiockey)); 715 if (err != 0) 716 break; 717 718 err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr); 719 break; 720 721 case KIOCSKEY: 722 err = miocpullup(mp, sizeof (struct kiockeymap)); 723 if (err != 0) 724 break; 725 726 err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr, 727 iocp->ioc_cr); 728 /* 729 * Since this only affects any subsequent key presses, 730 * don't goto output_format_change. One might want to 731 * toggle the keytable entries dynamically. 732 */ 733 break; 734 735 case KIOCGKEY: 736 err = miocpullup(mp, sizeof (struct kiockeymap)); 737 if (err != 0) 738 break; 739 740 err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr); 741 break; 742 743 case KIOCSDIRECT: 744 goto output_format_change; 745 746 case KIOCGDIRECT: 747 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 748 ioctlrespsize = sizeof (int); 749 goto allocfailure; 750 } 751 *(int *)datap->b_wptr = 1; /* always direct */ 752 datap->b_wptr += sizeof (int); 753 if (mp->b_cont) /* free msg to prevent memory leak */ 754 freemsg(mp->b_cont); 755 mp->b_cont = datap; 756 iocp->ioc_count = sizeof (int); 757 break; 758 759 case KIOCTYPE: 760 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 761 ioctlrespsize = sizeof (int); 762 goto allocfailure; 763 } 764 *(int *)datap->b_wptr = kbdd->kbdd_state.k_id; 765 datap->b_wptr += sizeof (int); 766 if (mp->b_cont) /* free msg to prevent memory leak */ 767 freemsg(mp->b_cont); 768 mp->b_cont = datap; 769 iocp->ioc_count = sizeof (int); 770 break; 771 772 case KIOCLAYOUT: 773 if ((datap = kbdd->kbdd_replypending) != NULL) { 774 /* 775 * There was an earlier KIOCLAYOUT pending; presumably, 776 * it timed out. Throw the reply away. 777 */ 778 kbdd->kbdd_replypending = NULL; 779 freemsg(datap); 780 } 781 782 if (kbdd->kbdd_state.k_id == KB_SUN4 || 783 kbdd->kbdd_state.k_id == KB_PC) { 784 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 785 ioctlrespsize = sizeof (int); 786 goto allocfailure; 787 } 788 iocp->ioc_rval = 0; 789 iocp->ioc_error = 0; /* brain rot */ 790 iocp->ioc_count = sizeof (int); 791 if (mp->b_cont) /* free msg to prevent memory leak */ 792 freemsg(mp->b_cont); 793 mp->b_cont = datap; 794 mp->b_datap->db_type = M_IOCACK; 795 kbdd->kbdd_replypending = mp; 796 kbdcmd(q, (char)KBD_CMD_GETLAYOUT); 797 if (kbdd->kbdd_layoutid) 798 (void) quntimeout(q, kbdd->kbdd_layoutid); 799 kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout, 800 kbdd, hz / 5); 801 return; /* wait for reply from keyboard */ 802 } else { 803 /* 804 * Not a Type 4 keyboard; return an immediate error. 805 */ 806 err = EINVAL; 807 break; 808 } 809 810 case KIOCGRPTDELAY: 811 /* 812 * Report the autorepeat delay, unit in millisecond 813 */ 814 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 815 ioctlrespsize = sizeof (int); 816 goto allocfailure; 817 } 818 *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay); 819 datap->b_wptr += sizeof (int); 820 821 /* free msg to prevent memory leak */ 822 if (mp->b_cont != NULL) 823 freemsg(mp->b_cont); 824 mp->b_cont = datap; 825 iocp->ioc_count = sizeof (int); 826 break; 827 828 case KIOCSRPTDELAY: 829 /* 830 * Set the autorepeat delay 831 */ 832 err = miocpullup(mp, sizeof (int)); 833 834 if (err != 0) 835 break; 836 837 /* validate the input */ 838 if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) { 839 err = EINVAL; 840 break; 841 } 842 kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 843 if (kbd_repeatdelay <= 0) 844 kbd_repeatdelay = 1; 845 break; 846 847 case KIOCGRPTRATE: 848 /* 849 * Report the autorepeat rate 850 */ 851 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 852 ioctlrespsize = sizeof (int); 853 goto allocfailure; 854 } 855 *(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate); 856 datap->b_wptr += sizeof (int); 857 858 /* free msg to prevent memory leak */ 859 if (mp->b_cont != NULL) 860 freemsg(mp->b_cont); 861 mp->b_cont = datap; 862 iocp->ioc_count = sizeof (int); 863 break; 864 865 case KIOCSRPTRATE: 866 /* 867 * Set the autorepeat rate 868 */ 869 err = miocpullup(mp, sizeof (int)); 870 871 if (err != 0) 872 break; 873 874 /* validate the input */ 875 if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) { 876 err = EINVAL; 877 break; 878 } 879 kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr); 880 if (kbd_repeatrate <= 0) 881 kbd_repeatrate = 1; 882 break; 883 884 default: 885 putnext(q, mp); /* pass it down the line */ 886 return; 887 } 888 goto done; 889 890 output_format_change: 891 kbdflush(kbdd); 892 893 done: 894 if (err != 0) { 895 iocp->ioc_rval = 0; 896 iocp->ioc_error = err; 897 mp->b_datap->db_type = M_IOCNAK; 898 } else { 899 iocp->ioc_rval = 0; 900 iocp->ioc_error = 0; /* brain rot */ 901 mp->b_datap->db_type = M_IOCACK; 902 } 903 qreply(q, mp); 904 return; 905 906 allocfailure: 907 /* 908 * We needed to allocate something to handle this "ioctl", but 909 * couldn't; save this "ioctl" and arrange to get called back when 910 * it's more likely that we can get what we need. 911 * If there's already one being saved, throw it out, since it 912 * must have timed out. 913 */ 914 if (kbdd->kbdd_iocpending != NULL) 915 freemsg(kbdd->kbdd_iocpending); 916 kbdd->kbdd_iocpending = mp; 917 if (kbdd->kbdd_bufcallid) 918 qunbufcall(q, kbdd->kbdd_bufcallid); 919 kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI, 920 kbdreioctl, kbdd); 921 } 922 923 static void 924 kbdflush(register struct kbddata *kbdd) 925 { 926 register queue_t *q; 927 928 /* Flush pending data already sent upstream */ 929 if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL) 930 (void) putnextctl1(q, M_FLUSH, FLUSHR); 931 /* Flush pending ups */ 932 bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes); 933 kbdcancelrpt(kbdd); 934 } 935 936 /* 937 * Pass keycode upstream, either translated or untranslated. 938 */ 939 static void 940 kbduse(register struct kbddata *kbdd, unsigned keycode) 941 { 942 register queue_t *readq; 943 944 #ifdef KBD_DEBUG 945 if (kbd_input_debug) printf("KBD USE key=%d\n", keycode); 946 #endif 947 948 if ((readq = kbdd->kbdd_readq) == NULL) 949 return; 950 if (!kbdd->kbdd_translatable || 951 kbdd->kbdd_translate == TR_NONE) 952 kbdputcode(keycode, readq); 953 else 954 kbdtranslate(kbdd, keycode, readq); 955 } 956 957 /* 958 * kbdclick is used to remember the current click value of the 959 * Sun-3 keyboard. This brain damaged keyboard will reset the 960 * clicking to the "default" value after a reset command and 961 * there is no way to read out the current click value. We 962 * cannot send a click command immediately after the reset 963 * command or the keyboard gets screwed up. So we wait until 964 * we get the ID byte before we send back the click command. 965 * Unfortunately, this means that there is a small window 966 * where the keyboard can click when it really shouldn't be. 967 * A value of -1 means that kbdclick has not been initialized yet. 968 */ 969 static int kbdclick = -1; 970 971 /* 972 * Send command byte to keyboard, if you can. 973 */ 974 static void 975 kbdcmd(register queue_t *q, char cmd) 976 { 977 register mblk_t *bp; 978 979 if (canput(q)) { 980 if ((bp = allocb(1, BPRI_MED)) == NULL) 981 cmn_err(CE_WARN, 982 "kbdcmd: Can't allocate block for command"); 983 else { 984 *bp->b_wptr++ = cmd; 985 putnext(q, bp); 986 if (cmd == KBD_CMD_NOCLICK) 987 kbdclick = 0; 988 else if (cmd == KBD_CMD_CLICK) 989 kbdclick = 1; 990 } 991 } 992 } 993 994 /* 995 * Update the keyboard LEDs to match the current keyboard state. 996 * Do this only on Type 4 keyboards; other keyboards don't support the 997 * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs). 998 */ 999 static void 1000 kbdsetled(register struct kbddata *kbdd) 1001 { 1002 if (kbdd->kbdd_state.k_id == KB_SUN4 || 1003 kbdd->kbdd_state.k_id == KB_PC) { 1004 kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED); 1005 kbdcmd(kbdd->kbdd_writeq, kbdd->led_state); 1006 } 1007 } 1008 1009 /* 1010 * Reset the keyboard 1011 */ 1012 static void 1013 kbdreset(register struct kbddata *kbdd, uint_t hard_reset) 1014 { 1015 register struct keyboardstate *k; 1016 1017 k = &kbdd->kbdd_state; 1018 if (kbdd->kbdd_translatable) { 1019 k->k_idstate = KID_NONE; 1020 k->k_id = -1; 1021 k->k_state = NORMAL; 1022 if (hard_reset) 1023 kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET); 1024 } else { 1025 bzero(k, sizeof (struct keyboardstate)); 1026 k->k_id = KB_ASCII; 1027 k->k_idstate = KID_OK; 1028 } 1029 } 1030 1031 /* 1032 * Old special codes. 1033 */ 1034 #define OLD_SHIFTKEYS 0x80 1035 #define OLD_BUCKYBITS 0x90 1036 #define OLD_FUNNY 0xA0 1037 #define OLD_FA_UMLAUT 0xA9 1038 #define OLD_FA_CFLEX 0xAA 1039 #define OLD_FA_TILDE 0xAB 1040 #define OLD_FA_CEDILLA 0xAC 1041 #define OLD_FA_ACUTE 0xAD 1042 #define OLD_FA_GRAVE 0xAE 1043 #define OLD_ISOCHAR 0xAF 1044 #define OLD_STRING 0xB0 1045 #define OLD_LEFTFUNC 0xC0 1046 #define OLD_RIGHTFUNC 0xD0 1047 #define OLD_TOPFUNC 0xE0 1048 #define OLD_BOTTOMFUNC 0xF0 1049 1050 /* 1051 * Map old special codes to new ones. 1052 * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F. 1053 */ 1054 static ushort_t special_old_to_new[] = { 1055 SHIFTKEYS, 1056 BUCKYBITS, 1057 FUNNY, 1058 STRING, 1059 LEFTFUNC, 1060 RIGHTFUNC, 1061 TOPFUNC, 1062 BOTTOMFUNC, 1063 }; 1064 1065 /* 1066 * Set individual keystation translation from old-style entry. 1067 * TODO: Have each keyboard own own translation tables. 1068 */ 1069 static int 1070 kbdsetkey(register struct kbddata *kbdd, struct kiockey *key, cred_t *cr) 1071 { 1072 int strtabindex, i; 1073 struct keymap *km; 1074 register int tablemask; 1075 register ushort_t entry; 1076 1077 if (key->kio_station >= KEYMAP_SIZE) 1078 return (EINVAL); 1079 if (kbdd->kbdd_state.k_curkeyboard == NULL) 1080 return (EINVAL); 1081 tablemask = key->kio_tablemask; 1082 if (tablemask == KIOCABORT1) { 1083 if (secpolicy_console(cr) != 0) 1084 return (EPERM); 1085 kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station; 1086 return (0); 1087 } 1088 if (tablemask == KIOCABORT2) { 1089 if (secpolicy_console(cr) != 0) 1090 return (EPERM); 1091 kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station; 1092 return (0); 1093 } 1094 if ((tablemask & ALTGRAPHMASK) || 1095 (km = settable(kbdd, (uint_t)tablemask)) == NULL) 1096 return (EINVAL); 1097 if (key->kio_entry >= (uchar_t)OLD_STRING && 1098 key->kio_entry <= (uchar_t)(OLD_STRING + 15)) { 1099 strtabindex = key->kio_entry - OLD_STRING; 1100 for (i = 0; i < KTAB_STRLEN; i++) 1101 keystringtab[strtabindex][i] = key->kio_string[i]; 1102 keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 1103 } 1104 entry = key->kio_entry; 1105 /* 1106 * There's nothing we need do with OLD_ISOCHAR. 1107 */ 1108 if (entry != OLD_ISOCHAR) { 1109 if (entry & 0x80) { 1110 if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE) 1111 entry = FA_CLASS + (entry & 0x0F) - 9; 1112 else 1113 entry = 1114 special_old_to_new[entry >> 4 & 0x07] 1115 + (entry & 0x0F); 1116 } 1117 } 1118 km->keymap[key->kio_station] = entry; 1119 return (0); 1120 } 1121 1122 /* 1123 * Map new special codes to old ones. 1124 * Indexed by (new special code) >> 8; add (new special code) & 0xFF. 1125 */ 1126 static uchar_t special_new_to_old[] = { 1127 0, /* normal */ 1128 OLD_SHIFTKEYS, /* SHIFTKEYS */ 1129 OLD_BUCKYBITS, /* BUCKYBITS */ 1130 OLD_FUNNY, /* FUNNY */ 1131 OLD_FA_UMLAUT, /* FA_CLASS */ 1132 OLD_STRING, /* STRING */ 1133 OLD_LEFTFUNC, /* FUNCKEYS */ 1134 }; 1135 1136 /* 1137 * Get individual keystation translation as old-style entry. 1138 */ 1139 static int 1140 kbdgetkey(register struct kbddata *kbdd, struct kiockey *key) 1141 { 1142 int strtabindex, i; 1143 struct keymap *km; 1144 register ushort_t entry; 1145 1146 if (key->kio_station >= KEYMAP_SIZE) 1147 return (EINVAL); 1148 if (kbdd->kbdd_state.k_curkeyboard == NULL) 1149 return (EINVAL); 1150 if (key->kio_tablemask == KIOCABORT1) { 1151 key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1; 1152 return (0); 1153 } 1154 if (key->kio_tablemask == KIOCABORT2) { 1155 key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2; 1156 return (0); 1157 } 1158 if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 1159 return (EINVAL); 1160 entry = km->keymap[key->kio_station]; 1161 if (entry & 0xFF00) 1162 key->kio_entry = 1163 special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8] 1164 + (entry & 0x00FF); 1165 else { 1166 if (entry & 0x80) 1167 key->kio_entry = (ushort_t)OLD_ISOCHAR; /* you lose */ 1168 else 1169 key->kio_entry = (ushort_t)entry; 1170 } 1171 if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) { 1172 strtabindex = entry - STRING; 1173 for (i = 0; i < KTAB_STRLEN; i++) 1174 key->kio_string[i] = keystringtab[strtabindex][i]; 1175 } 1176 return (0); 1177 } 1178 1179 /* 1180 * Set individual keystation translation from new-style entry. 1181 * TODO: Have each keyboard own own translation tables. 1182 */ 1183 static int 1184 kbdskey(register struct kbddata *kbdd, struct kiockeymap *key, cred_t *cr) 1185 { 1186 int strtabindex, i; 1187 struct keymap *km; 1188 1189 if (key->kio_station >= KEYMAP_SIZE) 1190 return (EINVAL); 1191 if (kbdd->kbdd_state.k_curkeyboard == NULL) 1192 return (EINVAL); 1193 if (key->kio_tablemask == KIOCABORT1) { 1194 if (secpolicy_console(cr) != 0) 1195 return (EPERM); 1196 kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station; 1197 return (0); 1198 } 1199 if (key->kio_tablemask == KIOCABORT2) { 1200 if (secpolicy_console(cr) != 0) 1201 return (EPERM); 1202 kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station; 1203 return (0); 1204 } 1205 if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 1206 return (EINVAL); 1207 if (key->kio_entry >= STRING && 1208 key->kio_entry <= (ushort_t)(STRING + 15)) { 1209 strtabindex = key->kio_entry-STRING; 1210 for (i = 0; i < KTAB_STRLEN; i++) 1211 keystringtab[strtabindex][i] = key->kio_string[i]; 1212 keystringtab[strtabindex][KTAB_STRLEN-1] = '\0'; 1213 } 1214 km->keymap[key->kio_station] = key->kio_entry; 1215 return (0); 1216 } 1217 1218 /* 1219 * Get individual keystation translation as new-style entry. 1220 */ 1221 static int 1222 kbdgkey(register struct kbddata *kbdd, struct kiockeymap *key) 1223 { 1224 int strtabindex, i; 1225 struct keymap *km; 1226 1227 if (key->kio_station >= KEYMAP_SIZE) 1228 return (EINVAL); 1229 if (kbdd->kbdd_state.k_curkeyboard == NULL) 1230 return (EINVAL); 1231 if (key->kio_tablemask == KIOCABORT1) { 1232 key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1; 1233 return (0); 1234 } 1235 if (key->kio_tablemask == KIOCABORT2) { 1236 key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2; 1237 return (0); 1238 } 1239 if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL) 1240 return (EINVAL); 1241 key->kio_entry = km->keymap[key->kio_station]; 1242 if (key->kio_entry >= STRING && 1243 key->kio_entry <= (ushort_t)(STRING + 15)) { 1244 strtabindex = key->kio_entry-STRING; 1245 for (i = 0; i < KTAB_STRLEN; i++) 1246 key->kio_string[i] = keystringtab[strtabindex][i]; 1247 } 1248 return (0); 1249 } 1250 1251 static void 1252 kbdlayouttimeout(void *arg) 1253 { 1254 struct kbddata *kbdd = arg; 1255 mblk_t *mp; 1256 1257 kbdd->kbdd_layoutid = 0; 1258 1259 /* 1260 * Timed out waiting for reply to "get keyboard layout" command. 1261 * Return an ETIME error. 1262 */ 1263 if ((mp = kbdd->kbdd_replypending) != NULL) { 1264 kbdd->kbdd_replypending = NULL; 1265 mp->b_datap->db_type = M_IOCNAK; 1266 ((struct iocblk *)mp->b_rptr)->ioc_error = ETIME; 1267 putnext(kbdd->kbdd_readq, mp); 1268 } 1269 } 1270 1271 /* 1272 * Put procedure for input from driver end of stream (read queue). 1273 */ 1274 static void 1275 kbdrput(register queue_t *q, register mblk_t *mp) 1276 { 1277 struct kbddata *kbdd = (struct kbddata *)q->q_ptr; 1278 register mblk_t *bp; 1279 register uchar_t *readp; 1280 struct iocblk *iocp; 1281 1282 if (kbdd == 0) { 1283 freemsg(mp); /* nobody's listening */ 1284 return; 1285 } 1286 1287 switch (mp->b_datap->db_type) { 1288 1289 case M_FLUSH: 1290 if (*mp->b_rptr & FLUSHW) 1291 flushq(WR(q), FLUSHDATA); 1292 if (*mp->b_rptr & FLUSHR) 1293 flushq(q, FLUSHDATA); 1294 1295 default: 1296 putnext(q, mp); 1297 return; 1298 1299 case M_BREAK: 1300 /* 1301 * Will get M_BREAK only if this is not the system 1302 * keyboard, otherwise serial port will eat break 1303 * and call kmdb/OBP, without passing anything up. 1304 */ 1305 freemsg(mp); 1306 return; 1307 1308 case M_IOCACK: 1309 case M_IOCNAK: 1310 /* 1311 * If we are doing an "ioctl" ourselves, check if this 1312 * is the reply to that code. If so, wake up the 1313 * "open" routine, and toss the reply, otherwise just 1314 * pass it up. 1315 */ 1316 iocp = (struct iocblk *)mp->b_rptr; 1317 if (!(kbdd->kbdd_flags & KBD_IOCWAIT) || 1318 iocp->ioc_id != kbdd->kbdd_iocid) { 1319 /* 1320 * This isn't the reply we're looking for. Move along. 1321 */ 1322 if (kbdd->kbdd_flags & KBD_OPEN) 1323 putnext(q, mp); 1324 else 1325 freemsg(mp); /* not ready to listen */ 1326 } else { 1327 kbdd->kbdd_flags &= ~KBD_IOCWAIT; 1328 kbdd->kbdd_iocerror = iocp->ioc_error; 1329 freemsg(mp); 1330 } 1331 return; 1332 1333 case M_DATA: 1334 if (!(kbdd->kbdd_flags & KBD_OPEN)) { 1335 freemsg(mp); /* not read to listen */ 1336 return; 1337 } 1338 break; 1339 } 1340 1341 /* 1342 * A data message, consisting of bytes from the keyboard. 1343 * Ram them through our state machine. 1344 */ 1345 bp = mp; 1346 1347 do { 1348 readp = bp->b_rptr; 1349 while (readp < bp->b_wptr) 1350 kbdinput(kbdd, *readp++); 1351 bp->b_rptr = readp; 1352 } while ((bp = bp->b_cont) != NULL); /* next block, if any */ 1353 1354 freemsg(mp); 1355 } 1356 1357 /* 1358 * A keypress was received. Process it through the state machine 1359 * to check for aborts. 1360 */ 1361 static void 1362 kbdinput(register struct kbddata *kbdd, register unsigned key) 1363 { 1364 register struct keyboardstate *k; 1365 register mblk_t *mp; 1366 1367 k = &kbdd->kbdd_state; 1368 #ifdef KBD_DEBUG 1369 if (kbd_input_debug) 1370 printf("kbdinput key %x\n", key); 1371 #endif 1372 1373 switch (k->k_idstate) { 1374 1375 case KID_NONE: 1376 if (key == RESETKEY) { 1377 k->k_idstate = KID_GOT_PREFACE; 1378 } else { 1379 kbdreset(kbdd, HARD_RESET); 1380 /* allows hot plug of kbd after booting without kbd */ 1381 } 1382 return; 1383 1384 case KID_GOT_PREFACE: 1385 kbdid(kbdd, (int)key); 1386 1387 /* 1388 * We just did a reset command to a Type 3 or Type 4 1389 * keyboard which sets the click back to the default 1390 * (which is currently ON!). We use the kbdclick 1391 * variable to see if the keyboard should be turned on 1392 * or off. If it has not been set, then we use the 1393 * keyboard-click? property. 1394 */ 1395 switch (kbdclick) { 1396 case 0: 1397 kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK); 1398 break; 1399 case 1: 1400 kbdcmd(kbdd->kbdd_writeq, KBD_CMD_CLICK); 1401 break; 1402 case -1: 1403 default: 1404 { 1405 char wrkbuf[8]; 1406 int len; 1407 1408 kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK); 1409 1410 bzero(wrkbuf, 8); 1411 len = 7; 1412 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, 1413 ddi_root_node(), 0, "keyboard-click?", 1414 (caddr_t)wrkbuf, &len) == 1415 DDI_PROP_SUCCESS && 1416 len > 0 && len < 8) { 1417 if (strcmp(wrkbuf, "true") == 0) { 1418 kbdcmd(kbdd->kbdd_writeq, 1419 KBD_CMD_CLICK); 1420 } 1421 } 1422 } 1423 break; 1424 } 1425 /* 1426 * A keyboard reset clears the LEDs. 1427 * Restore the LEDs from the last value we set 1428 * them to. 1429 */ 1430 kbdsetled(kbdd); 1431 return; 1432 1433 case KID_OK: 1434 switch (key) { 1435 1436 #if defined(KBD_PRESSED_PREFIX) 1437 case KBD_PRESSED_PREFIX: 1438 k->k_idstate = KID_GOT_PRESSED; 1439 return; 1440 #endif 1441 1442 #if defined(KBD_RELEASED_PREFIX) 1443 case KBD_RELEASED_PREFIX: 1444 k->k_idstate = KID_GOT_RELEASED; 1445 return; 1446 #endif 1447 1448 case 0: 1449 kbdreset(kbdd, HARD_RESET); 1450 return; 1451 1452 /* 1453 * we want to check for ID only if we are in 1454 * translatable mode. 1455 */ 1456 case RESETKEY: 1457 kbdreset(kbdd, NO_HARD_RESET); 1458 if (k->k_idstate == KID_NONE) { 1459 k->k_idstate = KID_GOT_PREFACE; 1460 } 1461 return; 1462 1463 case LAYOUTKEY: 1464 k->k_idstate = KID_GOT_LAYOUT; 1465 return; 1466 } 1467 break; 1468 1469 #if defined(KBD_PRESSED_PREFIX) 1470 case KID_GOT_PRESSED: 1471 key = BUILDKEY(key, PRESSED); 1472 k->k_idstate = KID_OK; 1473 break; 1474 #endif 1475 #if defined(KBD_RELEASED_PREFIX) 1476 case KID_GOT_RELEASED: 1477 key = BUILDKEY(key, RELEASED); 1478 k->k_idstate = KID_OK; 1479 break; 1480 #endif 1481 1482 case KID_GOT_LAYOUT: 1483 if (kbdd->kbdd_layoutid) 1484 (void) quntimeout(kbdd->kbdd_readq, 1485 kbdd->kbdd_layoutid); 1486 if ((mp = kbdd->kbdd_replypending) != NULL) { 1487 kbdd->kbdd_replypending = NULL; 1488 *(int *)mp->b_cont->b_wptr = key; 1489 mp->b_cont->b_wptr += sizeof (int); 1490 putnext(kbdd->kbdd_readq, mp); 1491 } 1492 k->k_idstate = KID_OK; 1493 return; 1494 } 1495 1496 switch (k->k_state) { 1497 1498 #if defined(__sparc) 1499 normalstate: 1500 k->k_state = NORMAL; 1501 /* FALLTHRU */ 1502 #endif 1503 case NORMAL: 1504 #if defined(__sparc) 1505 if (k->k_curkeyboard) { 1506 if (key == k->k_curkeyboard->k_abort1) { 1507 k->k_state = ABORT1; 1508 break; 1509 } 1510 if ((key == k->k_curkeyboard->k_newabort1) || 1511 (key == k->k_curkeyboard->k_newabort1a)) { 1512 k->k_state = NEWABORT1; 1513 break; 1514 } 1515 } 1516 #endif 1517 kbduse(kbdd, key); 1518 break; 1519 1520 #if defined(__sparc) 1521 case ABORT1: 1522 if (k->k_curkeyboard) { 1523 /* 1524 * Only recognize this as an abort sequence if 1525 * the "hardware" console is set to be this device. 1526 */ 1527 if (key == k->k_curkeyboard->k_abort2 && 1528 rconsvp == wsconsvp) { 1529 DELAY(100000); 1530 abort_sequence_enter((char *)NULL); 1531 k->k_state = NORMAL; 1532 kbduse(kbdd, IDLEKEY); /* fake */ 1533 return; 1534 } else { 1535 kbduse(kbdd, k->k_curkeyboard->k_abort1); 1536 goto normalstate; 1537 } 1538 } 1539 break; 1540 case NEWABORT1: 1541 if (k->k_curkeyboard) { 1542 /* 1543 * Only recognize this as an abort sequence if 1544 * the "hardware" console is set to be this device. 1545 */ 1546 if (key == k->k_curkeyboard->k_newabort2 && 1547 rconsvp == wsconsvp) { 1548 DELAY(100000); 1549 abort_sequence_enter((char *)NULL); 1550 k->k_state = NORMAL; 1551 kbduse(kbdd, IDLEKEY); /* fake */ 1552 return; 1553 } else { 1554 kbduse(kbdd, k->k_curkeyboard->k_newabort1); 1555 goto normalstate; 1556 } 1557 } 1558 break; 1559 #endif 1560 1561 case COMPOSE1: 1562 case COMPOSE2: 1563 case FLTACCENT: 1564 if (key != IDLEKEY) 1565 kbduse(kbdd, key); 1566 break; 1567 } 1568 } 1569 1570 static void 1571 kbdid(register struct kbddata *kbdd, int id) 1572 { 1573 register struct keyboardstate *k; 1574 int i; 1575 1576 k = &kbdd->kbdd_state; 1577 1578 k->k_idstate = KID_OK; 1579 k->k_shiftmask = 0; 1580 k->k_buckybits = 0; 1581 1582 /* 1583 * Reset k_rptkey to IDLEKEY. We need to cancel 1584 * the autorepeat feature, if any. 1585 */ 1586 if (k->k_rptkey != IDLEKEY) { 1587 if (kbdd->kbdd_rptid) 1588 (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 1589 kbdd->kbdd_rptid = 0; 1590 k->k_rptkey = IDLEKEY; 1591 } 1592 1593 k->k_curkeyboard = NULL; 1594 for (i = 0; keytables[i].table; i++) { 1595 if (keytables[i].id == id) { 1596 k->k_id = id; 1597 k->k_curkeyboard = keytables[i].table; 1598 break; 1599 } 1600 } 1601 if (!k->k_curkeyboard) { 1602 k->k_id = keytables[0].id; 1603 k->k_curkeyboard = keytables[0].table; 1604 cmn_err(CE_WARN, "kbd: Unknown keyboard type, " 1605 "Type %d assumed", k->k_id); 1606 } 1607 } 1608 1609 /* 1610 * This routine determines which table we should look in to decode 1611 * the current keycode. 1612 */ 1613 static struct keymap * 1614 settable(register struct kbddata *kbdd, register uint_t mask) 1615 { 1616 register struct keyboard *kp; 1617 1618 kp = kbdd->kbdd_state.k_curkeyboard; 1619 if (kp == NULL) 1620 return (NULL); 1621 if (mask & UPMASK) 1622 return (kp->k_up); 1623 if (mask & NUMLOCKMASK) 1624 return (kp->k_numlock); 1625 if (mask & CTRLMASK) 1626 return (kp->k_control); 1627 if (mask & ALTGRAPHMASK) 1628 return (kp->k_altgraph); 1629 if (mask & SHIFTMASK) 1630 return (kp->k_shifted); 1631 if (mask & CAPSMASK) 1632 return (kp->k_caps); 1633 return (kp->k_normal); 1634 } 1635 1636 static void 1637 kbdrpt(void *arg) 1638 { 1639 struct kbddata *kbdd = arg; 1640 struct keyboardstate *k; 1641 1642 k = &kbdd->kbdd_state; 1643 #ifdef KBD_DEBUG 1644 if (kbd_rpt_debug) 1645 printf("kbdrpt key %x\n", k->k_rptkey); 1646 #endif 1647 kbdd->kbdd_rptid = 0; 1648 1649 kbdkeyreleased(kbdd, KEYOF(k->k_rptkey)); 1650 kbduse(kbdd, k->k_rptkey); 1651 if (k->k_rptkey != IDLEKEY) { 1652 kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt, 1653 kbdd, kbd_repeatrate); 1654 } 1655 } 1656 1657 static void 1658 kbdcancelrpt(register struct kbddata *kbdd) 1659 { 1660 register struct keyboardstate *k; 1661 1662 k = &kbdd->kbdd_state; 1663 if (k->k_rptkey != IDLEKEY) { 1664 if (kbdd->kbdd_rptid) 1665 (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 1666 kbdd->kbdd_rptid = 0; 1667 k->k_rptkey = IDLEKEY; 1668 } 1669 ASSERT(kbdd->kbdd_rptid == 0); 1670 } 1671 1672 static void 1673 kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q) 1674 { 1675 register uchar_t key; 1676 register unsigned newstate; 1677 unsigned shiftmask; 1678 register ushort_t entry, entrytype; 1679 register char *cp, *bufp; 1680 register struct keyboardstate *k; 1681 ushort_t result_iso; 1682 struct keymap *km; 1683 Firm_event fe; 1684 int i, ret_val; 1685 char buf[14]; 1686 1687 k = &kbdd->kbdd_state; 1688 newstate = STATEOF(keycode); 1689 key = KEYOF(keycode); 1690 1691 #ifdef KBD_DEBUG 1692 if (kbd_input_debug) { 1693 printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n", 1694 keycode, newstate, key); 1695 } 1696 #endif 1697 1698 if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 1699 if (newstate == PRESSED) { 1700 bzero(&fe, sizeof (fe)); 1701 fe.id = key; 1702 fe.value = 1; 1703 kbdqueuepress(kbdd, key, &fe); 1704 } else { 1705 kbdkeyreleased(kbdd, key); 1706 } 1707 return; 1708 } 1709 1710 shiftmask = k->k_shiftmask; 1711 if (newstate == RELEASED) 1712 shiftmask |= UPMASK; 1713 1714 km = settable(kbdd, shiftmask); 1715 if (km == NULL) { /* gross error */ 1716 kbdcancelrpt(kbdd); 1717 return; 1718 } 1719 1720 if (key >= KEYMAP_SIZE) 1721 return; 1722 entry = km->keymap[key]; 1723 1724 if (entry == NONL) { 1725 /* 1726 * NONL appears only in the Num Lock table, and indicates that 1727 * this key is not affected by Num Lock. This means we should 1728 * ask for the table we would have gotten had Num Lock not been 1729 * down, and translate using that table. 1730 */ 1731 km = settable(kbdd, shiftmask & ~NUMLOCKMASK); 1732 if (km == NULL) { /* gross error */ 1733 kbdcancelrpt(kbdd); 1734 return; 1735 } 1736 entry = km->keymap[key]; 1737 } 1738 entrytype = (ushort_t)(entry & 0xFF00) >> 8; 1739 1740 if (entrytype == (SHIFTKEYS >> 8)) { 1741 /* 1742 * Handle the state of toggle shifts specially. 1743 * Ups should be ignored, and downs should be mapped to ups if 1744 * that shift is currently on. 1745 */ 1746 if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) { 1747 if ((1 << (entry & 0x0F)) & k->k_togglemask) { 1748 newstate = RELEASED; /* toggling off */ 1749 } else { 1750 newstate = PRESSED; /* toggling on */ 1751 } 1752 } 1753 } else { 1754 /* 1755 * Handle Compose and floating accent key sequences 1756 */ 1757 if (k->k_state == COMPOSE1) { 1758 if (newstate == RELEASED) 1759 return; 1760 if (entry < ASCII_SET_SIZE) { 1761 if (kb_compose_map[entry] >= 0) { 1762 kbdd->compose_key = entry; 1763 k->k_state = COMPOSE2; 1764 return; 1765 } 1766 } 1767 k->k_state = NORMAL; 1768 kbdd->led_state &= ~LED_COMPOSE; 1769 kbdsetled(kbdd); 1770 return; 1771 } else if (k->k_state == COMPOSE2) { 1772 if (newstate == RELEASED) 1773 return; 1774 k->k_state = NORMAL; /* next state is "normal" */ 1775 kbdd->led_state &= ~LED_COMPOSE; 1776 kbdsetled(kbdd); 1777 if (entry < ASCII_SET_SIZE) { 1778 if (kb_compose_map[entry] >= 0) { 1779 if (kbdd->compose_key <= entry) { 1780 ret_val = kbd_do_compose( 1781 kbdd->compose_key, 1782 entry, 1783 &result_iso); 1784 } else { 1785 ret_val = kbd_do_compose( 1786 entry, 1787 kbdd->compose_key, 1788 &result_iso); 1789 } 1790 if (ret_val == 1) { 1791 if (kbdd->kbdd_translate == 1792 TR_EVENT) { 1793 fe.id = 1794 (kbdd->kbdd_compat ? 1795 ISO_FIRST : EUC_FIRST) 1796 + result_iso; 1797 fe.value = 1; 1798 kbdqueueevent( 1799 kbdd, 1800 &fe); 1801 } else if ( 1802 kbdd->kbdd_translate == 1803 TR_ASCII) 1804 kbdputcode( 1805 result_iso, 1806 q); 1807 } 1808 } 1809 } 1810 return; 1811 } else if (k->k_state == FLTACCENT) { 1812 if (newstate == RELEASED) 1813 return; 1814 k->k_state = NORMAL; /* next state is "normal" */ 1815 for (i = 0; 1816 (kb_fltaccent_table[i].fa_entry 1817 != kbdd->fltaccent_entry) || 1818 (kb_fltaccent_table[i].ascii != entry); 1819 i++) { 1820 if (kb_fltaccent_table[i].fa_entry == 0) 1821 /* Invalid second key: ignore key */ 1822 return; 1823 } 1824 if (kbdd->kbdd_translate == TR_EVENT) { 1825 fe.id = (kbdd->kbdd_compat ? 1826 ISO_FIRST : EUC_FIRST) 1827 + kb_fltaccent_table[i].iso; 1828 fe.value = 1; 1829 kbdqueueevent(kbdd, &fe); 1830 } else if (kbdd->kbdd_translate == TR_ASCII) 1831 kbdputcode(kb_fltaccent_table[i].iso, q); 1832 return; 1833 } 1834 } 1835 1836 /* 1837 * If the key is going down, and it's not one of the keys that doesn't 1838 * auto-repeat, set up the auto-repeat timeout. 1839 * 1840 * The keys that don't auto-repeat are the Compose key, 1841 * the shift keys, the "bucky bit" keys, the "floating accent" keys, 1842 * and the function keys when in TR_EVENT mode. 1843 */ 1844 if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) && 1845 entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) && 1846 entrytype != (FA_CLASS >> 8) && 1847 !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) && 1848 kbdd->kbdd_translate == TR_EVENT)) { 1849 if (k->k_rptkey != keycode) { 1850 kbdcancelrpt(kbdd); 1851 kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd, 1852 kbd_repeatdelay); 1853 k->k_rptkey = keycode; 1854 } 1855 } else if (key == KEYOF(k->k_rptkey)) /* key going up */ 1856 kbdcancelrpt(kbdd); 1857 if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT)) 1858 kbdkeyreleased(kbdd, key); 1859 1860 /* 1861 * We assume here that keys other than shift keys and bucky keys have 1862 * entries in the "up" table that cause nothing to be done, and thus we 1863 * don't have to check for newstate == RELEASED. 1864 */ 1865 switch (entrytype) { 1866 1867 case 0x0: /* regular key */ 1868 switch (kbdd->kbdd_translate) { 1869 1870 case TR_EVENT: 1871 fe.id = entry | k->k_buckybits; 1872 fe.value = 1; 1873 kbdkeypressed(kbdd, key, &fe, entry); 1874 break; 1875 1876 case TR_ASCII: 1877 kbdputcode(entry | k->k_buckybits, q); 1878 break; 1879 } 1880 break; 1881 1882 case SHIFTKEYS >> 8: { 1883 uint_t shiftbit = 1 << (entry & 0x0F); 1884 1885 /* Modify toggle state (see toggle processing above) */ 1886 if (shiftbit & k->k_curkeyboard->k_toggleshifts) { 1887 if (newstate == RELEASED) { 1888 if (shiftbit == CAPSMASK) { 1889 kbdd->led_state &= ~LED_CAPS_LOCK; 1890 kbdsetled(kbdd); 1891 } else if (shiftbit == NUMLOCKMASK) { 1892 kbdd->led_state &= ~LED_NUM_LOCK; 1893 kbdsetled(kbdd); 1894 } 1895 k->k_togglemask &= ~shiftbit; 1896 } else { 1897 if (shiftbit == CAPSMASK) { 1898 kbdd->led_state |= LED_CAPS_LOCK; 1899 kbdsetled(kbdd); 1900 } else if (shiftbit == NUMLOCKMASK) { 1901 kbdd->led_state |= LED_NUM_LOCK; 1902 kbdsetled(kbdd); 1903 } 1904 k->k_togglemask |= shiftbit; 1905 } 1906 } 1907 1908 if (newstate == RELEASED) 1909 k->k_shiftmask &= ~shiftbit; 1910 else 1911 k->k_shiftmask |= shiftbit; 1912 1913 if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 1914 /* 1915 * Relying on ordinal correspondence between 1916 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL & 1917 * kbd.h CAPSLOCK-RIGHTCTRL in order to 1918 * correctly translate entry into fe.id. 1919 */ 1920 fe.id = SHIFT_CAPSLOCK + (entry & 0x0F); 1921 fe.value = 1; 1922 kbdkeypressed(kbdd, key, &fe, fe.id); 1923 } 1924 break; 1925 } 1926 1927 case BUCKYBITS >> 8: 1928 k->k_buckybits ^= 1 << (7 + (entry & 0x0F)); 1929 if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 1930 /* 1931 * Relying on ordinal correspondence between 1932 * vuid_event.h SHIFT_META-SHIFT_TOP & 1933 * kbd.h METABIT-SYSTEMBIT in order to 1934 * correctly translate entry into fe.id. 1935 */ 1936 fe.id = SHIFT_META + (entry & 0x0F); 1937 fe.value = 1; 1938 kbdkeypressed(kbdd, key, &fe, fe.id); 1939 } 1940 break; 1941 1942 case FUNNY >> 8: 1943 switch (entry) { 1944 case NOP: 1945 break; 1946 1947 case IDLE: 1948 /* Fall thru into RESET code */ 1949 /* FALLTHRU */ 1950 case RESET: 1951 gotreset: 1952 k->k_shiftmask &= k->k_curkeyboard->k_idleshifts; 1953 k->k_shiftmask |= k->k_togglemask; 1954 k->k_buckybits &= k->k_curkeyboard->k_idlebuckys; 1955 kbdcancelrpt(kbdd); 1956 kbdreleaseall(kbdd); 1957 break; 1958 1959 case ERROR: 1960 cmn_err(CE_WARN, "kbd: Error detected"); 1961 goto gotreset; 1962 1963 case COMPOSE: 1964 k->k_state = COMPOSE1; 1965 kbdd->led_state |= LED_COMPOSE; 1966 kbdsetled(kbdd); 1967 break; 1968 /* 1969 * Remember when adding new entries that, 1970 * if they should NOT auto-repeat, 1971 * they should be put into the IF statement 1972 * just above this switch block. 1973 */ 1974 default: 1975 goto badentry; 1976 } 1977 break; 1978 1979 case FA_CLASS >> 8: 1980 if (k->k_state == NORMAL) { 1981 kbdd->fltaccent_entry = entry; 1982 k->k_state = FLTACCENT; 1983 } 1984 return; 1985 1986 case STRING >> 8: 1987 cp = &keystringtab[entry & 0x0F][0]; 1988 while (*cp != '\0') { 1989 switch (kbdd->kbdd_translate) { 1990 1991 case TR_EVENT: 1992 kbd_send_esc_event(*cp, kbdd); 1993 break; 1994 1995 case TR_ASCII: 1996 kbdputcode((uchar_t)*cp, q); 1997 break; 1998 } 1999 cp++; 2000 } 2001 break; 2002 2003 case FUNCKEYS >> 8: 2004 switch (kbdd->kbdd_translate) { 2005 2006 case TR_ASCII: 2007 bufp = buf; 2008 cp = strsetwithdecimal(bufp + 2, 2009 (uint_t)((entry & 0x003F) + 192), 2010 sizeof (buf) - 5); 2011 *bufp++ = '\033'; /* Escape */ 2012 *bufp++ = '['; 2013 while (*cp != '\0') 2014 *bufp++ = *cp++; 2015 *bufp++ = 'z'; 2016 *bufp = '\0'; 2017 kbdputbuf(buf, q); 2018 break; 2019 2020 case TR_EVENT: 2021 /* 2022 * Take advantage of the similar 2023 * ordering of kbd.h function keys and 2024 * vuid_event.h function keys to do a 2025 * simple translation to achieve a 2026 * mapping between the 2 different 2027 * address spaces. 2028 */ 2029 fe.id = (entry & 0x003F) + KEY_LEFTFIRST; 2030 fe.value = 1; 2031 /* 2032 * Assume "up" table only generates 2033 * shift changes. 2034 */ 2035 kbdkeypressed(kbdd, key, &fe, fe.id); 2036 /* 2037 * Function key events can be expanded 2038 * by terminal emulator software to 2039 * produce the standard escape sequence 2040 * generated by the TR_ASCII case above 2041 * if a function key event is not used 2042 * by terminal emulator software 2043 * directly. 2044 */ 2045 break; 2046 } 2047 break; 2048 2049 /* 2050 * Remember when adding new entries that, 2051 * if they should NOT auto-repeat, 2052 * they should be put into the IF statement 2053 * just above this switch block. 2054 */ 2055 case PADKEYS >> 8: 2056 switch (kbdd->kbdd_translate) { 2057 2058 case TR_ASCII: 2059 kbdputcode(kb_numlock_table[entry&0x1F], q); 2060 break; 2061 2062 case TR_EVENT: 2063 /* 2064 * Take advantage of the similar 2065 * ordering of kbd.h keypad keys and 2066 * vuid_event.h keypad keys to do a 2067 * simple translation to achieve a 2068 * mapping between the 2 different 2069 * address spaces. 2070 */ 2071 fe.id = (entry & 0x001F) + VKEY_FIRSTPAD; 2072 fe.value = 1; 2073 /* 2074 * Assume "up" table only generates 2075 * shift changes. 2076 */ 2077 kbdkeypressed(kbdd, key, &fe, fe.id); 2078 /* 2079 * Keypad key events can be expanded 2080 * by terminal emulator software to 2081 * produce the standard ascii character 2082 * generated by the TR_ASCII case above 2083 * if a keypad key event is not used 2084 * by terminal emulator software 2085 * directly. 2086 */ 2087 break; 2088 } 2089 2090 badentry: 2091 break; 2092 } 2093 } 2094 2095 static int 2096 kbd_do_compose(ushort_t first_entry, ushort_t second_entry, 2097 ushort_t *result_iso_ptr) 2098 { 2099 struct compose_sequence_t *ptr; 2100 2101 ptr = &kb_compose_table[kb_compose_map[first_entry]]; 2102 while (ptr->first == first_entry) { 2103 if (ptr->second == second_entry) { 2104 *result_iso_ptr = ptr->iso; 2105 return (1); 2106 } 2107 ptr++; 2108 } 2109 return (0); 2110 } 2111 2112 static void 2113 kbd_send_esc_event(char c, register struct kbddata *kbdd) 2114 { 2115 Firm_event fe; 2116 2117 fe.id = c; 2118 fe.value = 1; 2119 fe.pair_type = FE_PAIR_NONE; 2120 fe.pair = 0; 2121 /* 2122 * Pretend as if each cp pushed and released 2123 * Calling kbdqueueevent avoids addr translation 2124 * and pair base determination of kbdkeypressed. 2125 */ 2126 kbdqueueevent(kbdd, &fe); 2127 fe.value = 0; 2128 kbdqueueevent(kbdd, &fe); 2129 } 2130 2131 char * 2132 strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs) 2133 { 2134 int hradix = 5; 2135 char *bp; 2136 int lowbit; 2137 char *tab = "0123456789abcdef"; 2138 2139 bp = buf + maxdigs; 2140 *(--bp) = '\0'; 2141 while (val) { 2142 lowbit = val & 1; 2143 val = (val >> 1); 2144 *(--bp) = tab[val % hradix * 2 + lowbit]; 2145 val /= hradix; 2146 } 2147 return (bp); 2148 } 2149 2150 static void 2151 kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe, 2152 ushort_t base) 2153 { 2154 register struct keyboardstate *k; 2155 register short id_addr; 2156 2157 /* Set pair values */ 2158 if (fe->id < (ushort_t)VKEY_FIRST) { 2159 /* 2160 * If CTRLed, find the ID that would have been used had it 2161 * not been CTRLed. 2162 */ 2163 k = &kbdd->kbdd_state; 2164 if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) { 2165 struct keymap *km; 2166 2167 km = settable(kbdd, 2168 k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK)); 2169 if (km == NULL) 2170 return; 2171 base = km->keymap[key_station]; 2172 } 2173 if (base != fe->id) { 2174 fe->pair_type = FE_PAIR_SET; 2175 fe->pair = base; 2176 goto send; 2177 } 2178 } 2179 fe->pair_type = FE_PAIR_NONE; 2180 fe->pair = 0; 2181 send: 2182 /* Adjust event id address for multiple keyboard/workstation support */ 2183 switch (vuid_id_addr(fe->id)) { 2184 case ASCII_FIRST: 2185 id_addr = kbdd->kbdd_ascii_addr; 2186 break; 2187 case TOP_FIRST: 2188 id_addr = kbdd->kbdd_top_addr; 2189 break; 2190 case VKEY_FIRST: 2191 id_addr = kbdd->kbdd_vkey_addr; 2192 break; 2193 default: 2194 id_addr = vuid_id_addr(fe->id); 2195 } 2196 fe->id = vuid_id_offset(fe->id) | id_addr; 2197 kbdqueuepress(kbdd, key_station, fe); 2198 } 2199 2200 static void 2201 kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe) 2202 { 2203 register struct key_event *ke, *ke_free; 2204 register int i; 2205 2206 if (key_station == IDLEKEY) 2207 return; 2208 #ifdef KBD_DEBUG 2209 if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station); 2210 #endif 2211 ke_free = 0; 2212 /* Scan table of down key stations */ 2213 if (kbdd->kbdd_translate == TR_EVENT || 2214 kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 2215 for (i = 0, ke = kbdd->kbdd_downs; 2216 i < kbdd->kbdd_downs_entries; 2217 i++, ke++) { 2218 /* Keycode already down? */ 2219 if (ke->key_station == key_station) { 2220 #ifdef KBD_DEBUG 2221 printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i); 2222 #endif 2223 goto add_event; 2224 } 2225 if (ke->key_station == 0) 2226 ke_free = ke; 2227 } 2228 if (ke_free) { 2229 ke = ke_free; 2230 goto add_event; 2231 } 2232 cmn_err(CE_WARN, "kbd: Too many keys down!"); 2233 ke = kbdd->kbdd_downs; 2234 } 2235 add_event: 2236 ke->key_station = key_station; 2237 ke->event = *fe; 2238 kbdqueueevent(kbdd, fe); 2239 } 2240 2241 static void 2242 kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station) 2243 { 2244 register struct key_event *ke; 2245 register int i; 2246 2247 if (key_station == IDLEKEY) 2248 return; 2249 #ifdef KBD_DEBUG 2250 if (kbd_input_debug) 2251 printf("KBD RELEASE key=%d\n", key_station); 2252 #endif 2253 if (kbdd->kbdd_translate != TR_EVENT && 2254 kbdd->kbdd_translate != TR_UNTRANS_EVENT) 2255 return; 2256 /* Scan table of down key stations */ 2257 for (i = 0, ke = kbdd->kbdd_downs; 2258 i < kbdd->kbdd_downs_entries; 2259 i++, ke++) { 2260 /* Found? */ 2261 if (ke->key_station == key_station) { 2262 ke->key_station = 0; 2263 ke->event.value = 0; 2264 kbdqueueevent(kbdd, &ke->event); 2265 } 2266 } 2267 2268 /* 2269 * Ignore if couldn't find because may be called twice 2270 * for the same key station in the case of the kbdrpt 2271 * routine being called unnecessarily. 2272 */ 2273 } 2274 2275 static void 2276 kbdreleaseall(struct kbddata *kbdd) 2277 { 2278 register struct key_event *ke; 2279 register int i; 2280 2281 #ifdef KBD_DEBUG 2282 if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n"); 2283 #endif 2284 /* Scan table of down key stations */ 2285 for (i = 0, ke = kbdd->kbdd_downs; 2286 i < kbdd->kbdd_downs_entries; i++, ke++) { 2287 /* Key station not zero */ 2288 if (ke->key_station) 2289 kbdkeyreleased(kbdd, ke->key_station); 2290 /* kbdkeyreleased resets kbdd_downs entry */ 2291 } 2292 } 2293 2294 /* 2295 * Pass a keycode up the stream, if you can, otherwise throw it away. 2296 */ 2297 static void 2298 kbdputcode(uint_t code, queue_t *q) 2299 { 2300 register mblk_t *bp; 2301 2302 if (!canput(q)) 2303 cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode"); 2304 else { 2305 if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) 2306 cmn_err(CE_WARN, 2307 "kbdputcode: Can't allocate block for keycode"); 2308 else { 2309 *bp->b_wptr++ = code; 2310 putnext(q, bp); 2311 } 2312 } 2313 } 2314 2315 /* 2316 * Pass generated keycode sequence to upstream, if possible. 2317 */ 2318 static void 2319 kbdputbuf(char *buf, queue_t *q) 2320 { 2321 register mblk_t *bp; 2322 2323 if (!canput(q)) 2324 cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode"); 2325 else { 2326 if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) 2327 cmn_err(CE_WARN, 2328 "kbdputbuf: Can't allocate block for keycode"); 2329 else { 2330 while (*buf) { 2331 *bp->b_wptr++ = *buf; 2332 buf++; 2333 } 2334 putnext(q, bp); 2335 } 2336 } 2337 } 2338 2339 /* 2340 * Pass a VUID "firm event" up the stream, if you can. 2341 */ 2342 static void 2343 kbdqueueevent(struct kbddata *kbdd, Firm_event *fe) 2344 { 2345 register queue_t *q; 2346 register mblk_t *bp; 2347 2348 if ((q = kbdd->kbdd_readq) == NULL) 2349 return; 2350 if (!canput(q)) { 2351 if (kbd_overflow_msg) 2352 cmn_err(CE_WARN, 2353 "kbd: Buffer flushed when overflowed"); 2354 kbdflush(kbdd); 2355 kbd_overflow_cnt++; 2356 } else { 2357 if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) 2358 cmn_err(CE_WARN, 2359 "kbdqueueevent: Can't allocate block for event"); 2360 else { 2361 #if 1 /* XX64 */ 2362 struct timeval now; 2363 2364 /* 2365 * XX64: This is something of a compromise. It 2366 * seems justifiable based on the usage of these 2367 * timestamps as an ordering relation as opposed 2368 * to a strict timing thing. 2369 * 2370 * But should we restore Firm_event's time stamp 2371 * to be a timeval, and send 32-bit and 64-bit 2372 * events up the pipe? 2373 */ 2374 uniqtime(&now); 2375 TIMEVAL_TO_TIMEVAL32(&fe->time, &now); 2376 #else 2377 uniqtime(&fe->time); 2378 #endif 2379 *(Firm_event *)bp->b_wptr = *fe; 2380 bp->b_wptr += sizeof (Firm_event); 2381 putnext(q, bp); 2382 } 2383 } 2384 } 2385