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