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