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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 /* SunOS-4.0 1.60 */ 29 /* From: SunOS4.0 sundev/kbd.c */ 30 31 /* 32 * Keyboard input streams module - handles conversion of up/down codes to 33 * ASCII or event format. 34 */ 35 #include <sys/types.h> 36 #include <sys/param.h> 37 #include <sys/sysmacros.h> 38 #include <sys/signal.h> 39 #include <sys/termios.h> 40 #include <sys/termio.h> 41 #include <sys/stream.h> 42 #include <sys/stropts.h> 43 #include <sys/strsun.h> 44 #include <sys/kmem.h> 45 #include <sys/file.h> 46 #include <sys/uio.h> 47 #include <sys/errno.h> 48 #include <sys/time.h> 49 #include <sys/consdev.h> 50 #include <sys/kbd.h> 51 #include <sys/kbio.h> 52 #include <sys/kbdreg.h> 53 #include <sys/vuid_event.h> 54 #include <sys/debug.h> 55 #include <sys/ddi.h> 56 #include <sys/sunddi.h> 57 #include <sys/policy.h> 58 59 #include <sys/modctl.h> 60 61 static struct streamtab kbd_info; 62 63 static struct fmodsw fsw = { 64 "kb", 65 &kbd_info, 66 D_MP | D_MTPERMOD 67 }; 68 69 /* 70 * Module linkage information for the kernel. 71 */ 72 73 static struct modlstrmod modlstrmod = { 74 &mod_strmodops, "streams module for keyboard", &fsw 75 }; 76 77 static struct modlinkage modlinkage = { 78 MODREV_1, (void *)&modlstrmod, NULL 79 }; 80 81 int 82 _init(void) 83 { 84 return (mod_install(&modlinkage)); 85 } 86 87 int 88 _fini(void) 89 { 90 return (mod_remove(&modlinkage)); 91 } 92 93 int 94 _info(struct modinfo *modinfop) 95 { 96 return (mod_info(&modlinkage, modinfop)); 97 } 98 99 /* 100 * For now these are shared. 101 * These data structures are static (defined in keytables.c) thus 102 * there is no need to perform any locking. 103 */ 104 extern struct keyboards keytables[]; 105 extern char keystringtab[16][KTAB_STRLEN]; 106 extern struct compose_sequence_t kb_compose_table[]; 107 extern signed char kb_compose_map[]; 108 extern struct fltaccent_sequence_t kb_fltaccent_table[]; 109 extern uchar_t kb_numlock_table[]; 110 111 /* 112 * This value corresponds approximately to max 10 fingers 113 */ 114 static int kbd_downs_size = 15; 115 116 typedef struct key_event { 117 uchar_t key_station; /* Physical key station associated with event */ 118 Firm_event event; /* Event that sent out on down */ 119 } Key_event; 120 struct kbddata { 121 queue_t *kbdd_readq; 122 queue_t *kbdd_writeq; 123 mblk_t *kbdd_iocpending; /* "ioctl" awaiting buffer */ 124 mblk_t *kbdd_replypending; /* "ioctl" reply awaiting result */ 125 int kbdd_flags; /* random flags */ 126 bufcall_id_t kbdd_bufcallid; /* bufcall id */ 127 timeout_id_t kbdd_rptid; /* timeout id for kbdrpt() */ 128 timeout_id_t kbdd_layoutid; /* timeout id for kbdlayout() */ 129 int kbdd_iocid; /* ID of "ioctl" being waited for */ 130 int kbdd_iocerror; /* error return from "ioctl" */ 131 struct keyboardstate kbdd_state; 132 /* 133 * State of keyboard & keyboard 134 * specific settings, e.g., tables 135 */ 136 int kbdd_translate; /* Translate keycodes? */ 137 int kbdd_translatable; /* Keyboard is translatable? */ 138 int kbdd_compat; /* Generating pre-4.1 events? */ 139 short kbdd_ascii_addr; /* Vuid_id_addr for ascii events */ 140 short kbdd_top_addr; /* Vuid_id_addr for top events */ 141 short kbdd_vkey_addr; /* Vuid_id_addr for vkey events */ 142 struct key_event *kbdd_downs; 143 /* 144 * Table of key stations currently down 145 * that have firm events that need 146 * to be matched with up transitions 147 * when kbdd_translate is TR_*EVENT 148 */ 149 int kbdd_downs_entries; /* # of possible entries in kbdd_downs */ 150 uint_t kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */ 151 ushort_t compose_key; /* first compose key */ 152 ushort_t fltaccent_entry; /* floating accent keymap entry */ 153 char led_state; /* current state of LEDs */ 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 } 1512 #endif 1513 kbduse(kbdd, key); 1514 break; 1515 1516 #if defined(__sparc) 1517 case ABORT1: 1518 if (k->k_curkeyboard) { 1519 /* 1520 * Only recognize this as an abort sequence if 1521 * the "hardware" console is set to be this device. 1522 */ 1523 if (key == k->k_curkeyboard->k_abort2 && 1524 rconsvp == wsconsvp) { 1525 DELAY(100000); 1526 abort_sequence_enter((char *)NULL); 1527 k->k_state = NORMAL; 1528 kbduse(kbdd, IDLEKEY); /* fake */ 1529 return; 1530 } else { 1531 kbduse(kbdd, k->k_curkeyboard->k_abort1); 1532 goto normalstate; 1533 } 1534 } 1535 break; 1536 #endif 1537 1538 case COMPOSE1: 1539 case COMPOSE2: 1540 case FLTACCENT: 1541 if (key != IDLEKEY) 1542 kbduse(kbdd, key); 1543 break; 1544 } 1545 } 1546 1547 static void 1548 kbdid(register struct kbddata *kbdd, int id) 1549 { 1550 register struct keyboardstate *k; 1551 int i; 1552 1553 k = &kbdd->kbdd_state; 1554 1555 k->k_idstate = KID_OK; 1556 k->k_shiftmask = 0; 1557 k->k_buckybits = 0; 1558 1559 /* 1560 * Reset k_rptkey to IDLEKEY. We need to cancel 1561 * the autorepeat feature, if any. 1562 */ 1563 if (k->k_rptkey != IDLEKEY) { 1564 if (kbdd->kbdd_rptid) 1565 (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 1566 kbdd->kbdd_rptid = 0; 1567 k->k_rptkey = IDLEKEY; 1568 } 1569 1570 k->k_curkeyboard = NULL; 1571 for (i = 0; keytables[i].table; i++) { 1572 if (keytables[i].id == id) { 1573 k->k_id = id; 1574 k->k_curkeyboard = keytables[i].table; 1575 break; 1576 } 1577 } 1578 if (!k->k_curkeyboard) { 1579 k->k_id = keytables[0].id; 1580 k->k_curkeyboard = keytables[0].table; 1581 cmn_err(CE_WARN, "kbd: Unknown keyboard type, " 1582 "Type %d assumed", k->k_id); 1583 } 1584 } 1585 1586 /* 1587 * This routine determines which table we should look in to decode 1588 * the current keycode. 1589 */ 1590 static struct keymap * 1591 settable(register struct kbddata *kbdd, register uint_t mask) 1592 { 1593 register struct keyboard *kp; 1594 1595 kp = kbdd->kbdd_state.k_curkeyboard; 1596 if (kp == NULL) 1597 return (NULL); 1598 if (mask & UPMASK) 1599 return (kp->k_up); 1600 if (mask & NUMLOCKMASK) 1601 return (kp->k_numlock); 1602 if (mask & CTRLMASK) 1603 return (kp->k_control); 1604 if (mask & ALTGRAPHMASK) 1605 return (kp->k_altgraph); 1606 if (mask & SHIFTMASK) 1607 return (kp->k_shifted); 1608 if (mask & CAPSMASK) 1609 return (kp->k_caps); 1610 return (kp->k_normal); 1611 } 1612 1613 static void 1614 kbdrpt(void *arg) 1615 { 1616 struct kbddata *kbdd = arg; 1617 struct keyboardstate *k; 1618 1619 k = &kbdd->kbdd_state; 1620 #ifdef KBD_DEBUG 1621 if (kbd_rpt_debug) 1622 printf("kbdrpt key %x\n", k->k_rptkey); 1623 #endif 1624 kbdd->kbdd_rptid = 0; 1625 1626 kbdkeyreleased(kbdd, KEYOF(k->k_rptkey)); 1627 kbduse(kbdd, k->k_rptkey); 1628 if (k->k_rptkey != IDLEKEY) { 1629 kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt, 1630 kbdd, kbd_repeatrate); 1631 } 1632 } 1633 1634 static void 1635 kbdcancelrpt(register struct kbddata *kbdd) 1636 { 1637 register struct keyboardstate *k; 1638 1639 k = &kbdd->kbdd_state; 1640 if (k->k_rptkey != IDLEKEY) { 1641 if (kbdd->kbdd_rptid) 1642 (void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid); 1643 kbdd->kbdd_rptid = 0; 1644 k->k_rptkey = IDLEKEY; 1645 } 1646 ASSERT(kbdd->kbdd_rptid == 0); 1647 } 1648 1649 static void 1650 kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q) 1651 { 1652 register uchar_t key; 1653 register unsigned newstate; 1654 unsigned shiftmask; 1655 register ushort_t entry, entrytype; 1656 register char *cp, *bufp; 1657 register struct keyboardstate *k; 1658 ushort_t result_iso; 1659 struct keymap *km; 1660 Firm_event fe; 1661 int i, ret_val; 1662 char buf[14]; 1663 1664 k = &kbdd->kbdd_state; 1665 newstate = STATEOF(keycode); 1666 key = KEYOF(keycode); 1667 1668 #ifdef KBD_DEBUG 1669 if (kbd_input_debug) { 1670 printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n", 1671 keycode, newstate, key); 1672 } 1673 #endif 1674 1675 if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 1676 if (newstate == PRESSED) { 1677 bzero(&fe, sizeof (fe)); 1678 fe.id = key; 1679 fe.value = 1; 1680 kbdqueuepress(kbdd, key, &fe); 1681 } else { 1682 kbdkeyreleased(kbdd, key); 1683 } 1684 return; 1685 } 1686 1687 shiftmask = k->k_shiftmask; 1688 if (newstate == RELEASED) 1689 shiftmask |= UPMASK; 1690 1691 km = settable(kbdd, shiftmask); 1692 if (km == NULL) { /* gross error */ 1693 kbdcancelrpt(kbdd); 1694 return; 1695 } 1696 1697 if (key >= KEYMAP_SIZE) 1698 return; 1699 entry = km->keymap[key]; 1700 1701 if (entry == NONL) { 1702 /* 1703 * NONL appears only in the Num Lock table, and indicates that 1704 * this key is not affected by Num Lock. This means we should 1705 * ask for the table we would have gotten had Num Lock not been 1706 * down, and translate using that table. 1707 */ 1708 km = settable(kbdd, shiftmask & ~NUMLOCKMASK); 1709 if (km == NULL) { /* gross error */ 1710 kbdcancelrpt(kbdd); 1711 return; 1712 } 1713 entry = km->keymap[key]; 1714 } 1715 entrytype = (ushort_t)(entry & 0xFF00) >> 8; 1716 1717 if (entrytype == (SHIFTKEYS >> 8)) { 1718 /* 1719 * Handle the state of toggle shifts specially. 1720 * Ups should be ignored, and downs should be mapped to ups if 1721 * that shift is currently on. 1722 */ 1723 if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) { 1724 if ((1 << (entry & 0x0F)) & k->k_togglemask) { 1725 newstate = RELEASED; /* toggling off */ 1726 } else { 1727 newstate = PRESSED; /* toggling on */ 1728 } 1729 } 1730 } else { 1731 /* 1732 * Handle Compose and floating accent key sequences 1733 */ 1734 if (k->k_state == COMPOSE1) { 1735 if (newstate == RELEASED) 1736 return; 1737 if (entry < ASCII_SET_SIZE) { 1738 if (kb_compose_map[entry] >= 0) { 1739 kbdd->compose_key = entry; 1740 k->k_state = COMPOSE2; 1741 return; 1742 } 1743 } 1744 k->k_state = NORMAL; 1745 kbdd->led_state &= ~LED_COMPOSE; 1746 kbdsetled(kbdd); 1747 return; 1748 } else if (k->k_state == COMPOSE2) { 1749 if (newstate == RELEASED) 1750 return; 1751 k->k_state = NORMAL; /* next state is "normal" */ 1752 kbdd->led_state &= ~LED_COMPOSE; 1753 kbdsetled(kbdd); 1754 if (entry < ASCII_SET_SIZE) { 1755 if (kb_compose_map[entry] >= 0) { 1756 if (kbdd->compose_key <= entry) { 1757 ret_val = kbd_do_compose( 1758 kbdd->compose_key, 1759 entry, 1760 &result_iso); 1761 } else { 1762 ret_val = kbd_do_compose( 1763 entry, 1764 kbdd->compose_key, 1765 &result_iso); 1766 } 1767 if (ret_val == 1) { 1768 if (kbdd->kbdd_translate == 1769 TR_EVENT) { 1770 fe.id = 1771 (kbdd->kbdd_compat ? 1772 ISO_FIRST : EUC_FIRST) 1773 + result_iso; 1774 fe.value = 1; 1775 kbdqueueevent( 1776 kbdd, 1777 &fe); 1778 } else if ( 1779 kbdd->kbdd_translate == 1780 TR_ASCII) 1781 kbdputcode( 1782 result_iso, 1783 q); 1784 } 1785 } 1786 } 1787 return; 1788 } else if (k->k_state == FLTACCENT) { 1789 if (newstate == RELEASED) 1790 return; 1791 k->k_state = NORMAL; /* next state is "normal" */ 1792 for (i = 0; 1793 (kb_fltaccent_table[i].fa_entry 1794 != kbdd->fltaccent_entry) || 1795 (kb_fltaccent_table[i].ascii != entry); 1796 i++) { 1797 if (kb_fltaccent_table[i].fa_entry == 0) 1798 /* Invalid second key: ignore key */ 1799 return; 1800 } 1801 if (kbdd->kbdd_translate == TR_EVENT) { 1802 fe.id = (kbdd->kbdd_compat ? 1803 ISO_FIRST : EUC_FIRST) 1804 + kb_fltaccent_table[i].iso; 1805 fe.value = 1; 1806 kbdqueueevent(kbdd, &fe); 1807 } else if (kbdd->kbdd_translate == TR_ASCII) 1808 kbdputcode(kb_fltaccent_table[i].iso, q); 1809 return; 1810 } 1811 } 1812 1813 /* 1814 * If the key is going down, and it's not one of the keys that doesn't 1815 * auto-repeat, set up the auto-repeat timeout. 1816 * 1817 * The keys that don't auto-repeat are the Compose key, 1818 * the shift keys, the "bucky bit" keys, the "floating accent" keys, 1819 * and the function keys when in TR_EVENT mode. 1820 */ 1821 if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) && 1822 entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) && 1823 entrytype != (FA_CLASS >> 8) && 1824 !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) && 1825 kbdd->kbdd_translate == TR_EVENT)) { 1826 if (k->k_rptkey != keycode) { 1827 kbdcancelrpt(kbdd); 1828 kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd, 1829 kbd_repeatdelay); 1830 k->k_rptkey = keycode; 1831 } 1832 } else if (key == KEYOF(k->k_rptkey)) /* key going up */ 1833 kbdcancelrpt(kbdd); 1834 if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT)) 1835 kbdkeyreleased(kbdd, key); 1836 1837 /* 1838 * We assume here that keys other than shift keys and bucky keys have 1839 * entries in the "up" table that cause nothing to be done, and thus we 1840 * don't have to check for newstate == RELEASED. 1841 */ 1842 switch (entrytype) { 1843 1844 case 0x0: /* regular key */ 1845 switch (kbdd->kbdd_translate) { 1846 1847 case TR_EVENT: 1848 fe.id = entry | k->k_buckybits; 1849 fe.value = 1; 1850 kbdkeypressed(kbdd, key, &fe, entry); 1851 break; 1852 1853 case TR_ASCII: 1854 kbdputcode(entry | k->k_buckybits, q); 1855 break; 1856 } 1857 break; 1858 1859 case SHIFTKEYS >> 8: { 1860 uint_t shiftbit = 1 << (entry & 0x0F); 1861 1862 /* Modify toggle state (see toggle processing above) */ 1863 if (shiftbit & k->k_curkeyboard->k_toggleshifts) { 1864 if (newstate == RELEASED) { 1865 if (shiftbit == CAPSMASK) { 1866 kbdd->led_state &= ~LED_CAPS_LOCK; 1867 kbdsetled(kbdd); 1868 } else if (shiftbit == NUMLOCKMASK) { 1869 kbdd->led_state &= ~LED_NUM_LOCK; 1870 kbdsetled(kbdd); 1871 } 1872 k->k_togglemask &= ~shiftbit; 1873 } else { 1874 if (shiftbit == CAPSMASK) { 1875 kbdd->led_state |= LED_CAPS_LOCK; 1876 kbdsetled(kbdd); 1877 } else if (shiftbit == NUMLOCKMASK) { 1878 kbdd->led_state |= LED_NUM_LOCK; 1879 kbdsetled(kbdd); 1880 } 1881 k->k_togglemask |= shiftbit; 1882 } 1883 } 1884 1885 if (newstate == RELEASED) 1886 k->k_shiftmask &= ~shiftbit; 1887 else 1888 k->k_shiftmask |= shiftbit; 1889 1890 if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 1891 /* 1892 * Relying on ordinal correspondence between 1893 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL & 1894 * kbd.h CAPSLOCK-RIGHTCTRL in order to 1895 * correctly translate entry into fe.id. 1896 */ 1897 fe.id = SHIFT_CAPSLOCK + (entry & 0x0F); 1898 fe.value = 1; 1899 kbdkeypressed(kbdd, key, &fe, fe.id); 1900 } 1901 break; 1902 } 1903 1904 case BUCKYBITS >> 8: 1905 k->k_buckybits ^= 1 << (7 + (entry & 0x0F)); 1906 if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) { 1907 /* 1908 * Relying on ordinal correspondence between 1909 * vuid_event.h SHIFT_META-SHIFT_TOP & 1910 * kbd.h METABIT-SYSTEMBIT in order to 1911 * correctly translate entry into fe.id. 1912 */ 1913 fe.id = SHIFT_META + (entry & 0x0F); 1914 fe.value = 1; 1915 kbdkeypressed(kbdd, key, &fe, fe.id); 1916 } 1917 break; 1918 1919 case FUNNY >> 8: 1920 switch (entry) { 1921 case NOP: 1922 break; 1923 1924 case IDLE: 1925 /* Fall thru into RESET code */ 1926 /* FALLTHRU */ 1927 case RESET: 1928 gotreset: 1929 k->k_shiftmask &= k->k_curkeyboard->k_idleshifts; 1930 k->k_shiftmask |= k->k_togglemask; 1931 k->k_buckybits &= k->k_curkeyboard->k_idlebuckys; 1932 kbdcancelrpt(kbdd); 1933 kbdreleaseall(kbdd); 1934 break; 1935 1936 case ERROR: 1937 cmn_err(CE_WARN, "kbd: Error detected"); 1938 goto gotreset; 1939 1940 case COMPOSE: 1941 k->k_state = COMPOSE1; 1942 kbdd->led_state |= LED_COMPOSE; 1943 kbdsetled(kbdd); 1944 break; 1945 /* 1946 * Remember when adding new entries that, 1947 * if they should NOT auto-repeat, 1948 * they should be put into the IF statement 1949 * just above this switch block. 1950 */ 1951 default: 1952 goto badentry; 1953 } 1954 break; 1955 1956 case FA_CLASS >> 8: 1957 if (k->k_state == NORMAL) { 1958 kbdd->fltaccent_entry = entry; 1959 k->k_state = FLTACCENT; 1960 } 1961 return; 1962 1963 case STRING >> 8: 1964 cp = &keystringtab[entry & 0x0F][0]; 1965 while (*cp != '\0') { 1966 switch (kbdd->kbdd_translate) { 1967 1968 case TR_EVENT: 1969 kbd_send_esc_event(*cp, kbdd); 1970 break; 1971 1972 case TR_ASCII: 1973 kbdputcode((uchar_t)*cp, q); 1974 break; 1975 } 1976 cp++; 1977 } 1978 break; 1979 1980 case FUNCKEYS >> 8: 1981 switch (kbdd->kbdd_translate) { 1982 1983 case TR_ASCII: 1984 bufp = buf; 1985 cp = strsetwithdecimal(bufp + 2, 1986 (uint_t)((entry & 0x003F) + 192), 1987 sizeof (buf) - 5); 1988 *bufp++ = '\033'; /* Escape */ 1989 *bufp++ = '['; 1990 while (*cp != '\0') 1991 *bufp++ = *cp++; 1992 *bufp++ = 'z'; 1993 *bufp = '\0'; 1994 kbdputbuf(buf, q); 1995 break; 1996 1997 case TR_EVENT: 1998 /* 1999 * Take advantage of the similar 2000 * ordering of kbd.h function keys and 2001 * vuid_event.h function keys to do a 2002 * simple translation to achieve a 2003 * mapping between the 2 different 2004 * address spaces. 2005 */ 2006 fe.id = (entry & 0x003F) + KEY_LEFTFIRST; 2007 fe.value = 1; 2008 /* 2009 * Assume "up" table only generates 2010 * shift changes. 2011 */ 2012 kbdkeypressed(kbdd, key, &fe, fe.id); 2013 /* 2014 * Function key events can be expanded 2015 * by terminal emulator software to 2016 * produce the standard escape sequence 2017 * generated by the TR_ASCII case above 2018 * if a function key event is not used 2019 * by terminal emulator software 2020 * directly. 2021 */ 2022 break; 2023 } 2024 break; 2025 2026 /* 2027 * Remember when adding new entries that, 2028 * if they should NOT auto-repeat, 2029 * they should be put into the IF statement 2030 * just above this switch block. 2031 */ 2032 case PADKEYS >> 8: 2033 switch (kbdd->kbdd_translate) { 2034 2035 case TR_ASCII: 2036 kbdputcode(kb_numlock_table[entry&0x1F], q); 2037 break; 2038 2039 case TR_EVENT: 2040 /* 2041 * Take advantage of the similar 2042 * ordering of kbd.h keypad keys and 2043 * vuid_event.h keypad keys to do a 2044 * simple translation to achieve a 2045 * mapping between the 2 different 2046 * address spaces. 2047 */ 2048 fe.id = (entry & 0x001F) + VKEY_FIRSTPAD; 2049 fe.value = 1; 2050 /* 2051 * Assume "up" table only generates 2052 * shift changes. 2053 */ 2054 kbdkeypressed(kbdd, key, &fe, fe.id); 2055 /* 2056 * Keypad key events can be expanded 2057 * by terminal emulator software to 2058 * produce the standard ascii character 2059 * generated by the TR_ASCII case above 2060 * if a keypad key event is not used 2061 * by terminal emulator software 2062 * directly. 2063 */ 2064 break; 2065 } 2066 2067 badentry: 2068 break; 2069 } 2070 } 2071 2072 static int 2073 kbd_do_compose(ushort_t first_entry, ushort_t second_entry, 2074 ushort_t *result_iso_ptr) 2075 { 2076 struct compose_sequence_t *ptr; 2077 2078 ptr = &kb_compose_table[kb_compose_map[first_entry]]; 2079 while (ptr->first == first_entry) { 2080 if (ptr->second == second_entry) { 2081 *result_iso_ptr = ptr->iso; 2082 return (1); 2083 } 2084 ptr++; 2085 } 2086 return (0); 2087 } 2088 2089 static void 2090 kbd_send_esc_event(char c, register struct kbddata *kbdd) 2091 { 2092 Firm_event fe; 2093 2094 fe.id = c; 2095 fe.value = 1; 2096 fe.pair_type = FE_PAIR_NONE; 2097 fe.pair = 0; 2098 /* 2099 * Pretend as if each cp pushed and released 2100 * Calling kbdqueueevent avoids addr translation 2101 * and pair base determination of kbdkeypressed. 2102 */ 2103 kbdqueueevent(kbdd, &fe); 2104 fe.value = 0; 2105 kbdqueueevent(kbdd, &fe); 2106 } 2107 2108 char * 2109 strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs) 2110 { 2111 int hradix = 5; 2112 char *bp; 2113 int lowbit; 2114 char *tab = "0123456789abcdef"; 2115 2116 bp = buf + maxdigs; 2117 *(--bp) = '\0'; 2118 while (val) { 2119 lowbit = val & 1; 2120 val = (val >> 1); 2121 *(--bp) = tab[val % hradix * 2 + lowbit]; 2122 val /= hradix; 2123 } 2124 return (bp); 2125 } 2126 2127 static void 2128 kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe, 2129 ushort_t base) 2130 { 2131 register struct keyboardstate *k; 2132 register short id_addr; 2133 2134 /* Set pair values */ 2135 if (fe->id < (ushort_t)VKEY_FIRST) { 2136 /* 2137 * If CTRLed, find the ID that would have been used had it 2138 * not been CTRLed. 2139 */ 2140 k = &kbdd->kbdd_state; 2141 if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) { 2142 struct keymap *km; 2143 2144 km = settable(kbdd, 2145 k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK)); 2146 if (km == NULL) 2147 return; 2148 base = km->keymap[key_station]; 2149 } 2150 if (base != fe->id) { 2151 fe->pair_type = FE_PAIR_SET; 2152 fe->pair = base; 2153 goto send; 2154 } 2155 } 2156 fe->pair_type = FE_PAIR_NONE; 2157 fe->pair = 0; 2158 send: 2159 /* Adjust event id address for multiple keyboard/workstation support */ 2160 switch (vuid_id_addr(fe->id)) { 2161 case ASCII_FIRST: 2162 id_addr = kbdd->kbdd_ascii_addr; 2163 break; 2164 case TOP_FIRST: 2165 id_addr = kbdd->kbdd_top_addr; 2166 break; 2167 case VKEY_FIRST: 2168 id_addr = kbdd->kbdd_vkey_addr; 2169 break; 2170 default: 2171 id_addr = vuid_id_addr(fe->id); 2172 } 2173 fe->id = vuid_id_offset(fe->id) | id_addr; 2174 kbdqueuepress(kbdd, key_station, fe); 2175 } 2176 2177 static void 2178 kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe) 2179 { 2180 register struct key_event *ke, *ke_free; 2181 register int i; 2182 2183 if (key_station == IDLEKEY) 2184 return; 2185 #ifdef KBD_DEBUG 2186 if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station); 2187 #endif 2188 ke_free = 0; 2189 /* Scan table of down key stations */ 2190 if (kbdd->kbdd_translate == TR_EVENT || 2191 kbdd->kbdd_translate == TR_UNTRANS_EVENT) { 2192 for (i = 0, ke = kbdd->kbdd_downs; 2193 i < kbdd->kbdd_downs_entries; 2194 i++, ke++) { 2195 /* Keycode already down? */ 2196 if (ke->key_station == key_station) { 2197 #ifdef KBD_DEBUG 2198 printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i); 2199 #endif 2200 goto add_event; 2201 } 2202 if (ke->key_station == 0) 2203 ke_free = ke; 2204 } 2205 if (ke_free) { 2206 ke = ke_free; 2207 goto add_event; 2208 } 2209 cmn_err(CE_WARN, "kbd: Too many keys down!"); 2210 ke = kbdd->kbdd_downs; 2211 } 2212 add_event: 2213 ke->key_station = key_station; 2214 ke->event = *fe; 2215 kbdqueueevent(kbdd, fe); 2216 } 2217 2218 static void 2219 kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station) 2220 { 2221 register struct key_event *ke; 2222 register int i; 2223 2224 if (key_station == IDLEKEY) 2225 return; 2226 #ifdef KBD_DEBUG 2227 if (kbd_input_debug) 2228 printf("KBD RELEASE key=%d\n", key_station); 2229 #endif 2230 if (kbdd->kbdd_translate != TR_EVENT && 2231 kbdd->kbdd_translate != TR_UNTRANS_EVENT) 2232 return; 2233 /* Scan table of down key stations */ 2234 for (i = 0, ke = kbdd->kbdd_downs; 2235 i < kbdd->kbdd_downs_entries; 2236 i++, ke++) { 2237 /* Found? */ 2238 if (ke->key_station == key_station) { 2239 ke->key_station = 0; 2240 ke->event.value = 0; 2241 kbdqueueevent(kbdd, &ke->event); 2242 } 2243 } 2244 2245 /* 2246 * Ignore if couldn't find because may be called twice 2247 * for the same key station in the case of the kbdrpt 2248 * routine being called unnecessarily. 2249 */ 2250 } 2251 2252 static void 2253 kbdreleaseall(struct kbddata *kbdd) 2254 { 2255 register struct key_event *ke; 2256 register int i; 2257 2258 #ifdef KBD_DEBUG 2259 if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n"); 2260 #endif 2261 /* Scan table of down key stations */ 2262 for (i = 0, ke = kbdd->kbdd_downs; 2263 i < kbdd->kbdd_downs_entries; i++, ke++) { 2264 /* Key station not zero */ 2265 if (ke->key_station) 2266 kbdkeyreleased(kbdd, ke->key_station); 2267 /* kbdkeyreleased resets kbdd_downs entry */ 2268 } 2269 } 2270 2271 /* 2272 * Pass a keycode up the stream, if you can, otherwise throw it away. 2273 */ 2274 static void 2275 kbdputcode(uint_t code, queue_t *q) 2276 { 2277 register mblk_t *bp; 2278 2279 if (!canput(q)) 2280 cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode"); 2281 else { 2282 if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) 2283 cmn_err(CE_WARN, 2284 "kbdputcode: Can't allocate block for keycode"); 2285 else { 2286 *bp->b_wptr++ = code; 2287 putnext(q, bp); 2288 } 2289 } 2290 } 2291 2292 /* 2293 * Pass generated keycode sequence to upstream, if possible. 2294 */ 2295 static void 2296 kbdputbuf(char *buf, queue_t *q) 2297 { 2298 register mblk_t *bp; 2299 2300 if (!canput(q)) 2301 cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode"); 2302 else { 2303 if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) 2304 cmn_err(CE_WARN, 2305 "kbdputbuf: Can't allocate block for keycode"); 2306 else { 2307 while (*buf) { 2308 *bp->b_wptr++ = *buf; 2309 buf++; 2310 } 2311 putnext(q, bp); 2312 } 2313 } 2314 } 2315 2316 /* 2317 * Pass a VUID "firm event" up the stream, if you can. 2318 */ 2319 static void 2320 kbdqueueevent(struct kbddata *kbdd, Firm_event *fe) 2321 { 2322 register queue_t *q; 2323 register mblk_t *bp; 2324 2325 if ((q = kbdd->kbdd_readq) == NULL) 2326 return; 2327 if (!canput(q)) { 2328 if (kbd_overflow_msg) 2329 cmn_err(CE_WARN, 2330 "kbd: Buffer flushed when overflowed"); 2331 kbdflush(kbdd); 2332 kbd_overflow_cnt++; 2333 } else { 2334 if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) 2335 cmn_err(CE_WARN, 2336 "kbdqueueevent: Can't allocate block for event"); 2337 else { 2338 #if 1 /* XX64 */ 2339 struct timeval now; 2340 2341 /* 2342 * XX64: This is something of a compromise. It 2343 * seems justifiable based on the usage of these 2344 * timestamps as an ordering relation as opposed 2345 * to a strict timing thing. 2346 * 2347 * But should we restore Firm_event's time stamp 2348 * to be a timeval, and send 32-bit and 64-bit 2349 * events up the pipe? 2350 */ 2351 uniqtime(&now); 2352 TIMEVAL_TO_TIMEVAL32(&fe->time, &now); 2353 #else 2354 uniqtime(&fe->time); 2355 #endif 2356 *(Firm_event *)bp->b_wptr = *fe; 2357 bp->b_wptr += sizeof (Firm_event); 2358 putnext(q, bp); 2359 } 2360 } 2361 } 2362