1 /*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ralph Campbell and Rick Macklem. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)dtop.c 8.1 (Berkeley) 06/10/93 11 */ 12 13 /* 14 * Mach Operating System 15 * Copyright (c) 1991,1990,1989 Carnegie Mellon University 16 * All Rights Reserved. 17 * 18 * Permission to use, copy, modify and distribute this software and its 19 * documentation is hereby granted, provided that both the copyright 20 * notice and this permission notice appear in all copies of the 21 * software, derivative works or modified versions, and any portions 22 * thereof, and that both notices appear in supporting documentation. 23 * 24 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 25 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 26 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 27 * 28 * Carnegie Mellon requests users of this software to return to 29 * 30 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 31 * School of Computer Science 32 * Carnegie Mellon University 33 * Pittsburgh PA 15213-3890 34 * 35 * any improvements or extensions that they make and grant Carnegie the 36 * rights to redistribute these changes. 37 */ 38 /* 39 * Author: Alessandro Forin, Carnegie Mellon University 40 * 41 * Hardware-level operations for the Desktop serial line 42 * bus (i2c aka ACCESS). 43 */ 44 /************************************************************ 45 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, 46 and the Massachusetts Institute of Technology, Cambridge, Massachusetts. 47 48 All Rights Reserved 49 50 Permission to use, copy, modify, and distribute this software and its 51 documentation for any purpose and without fee is hereby granted, 52 provided that the above copyright notice appear in all copies and that 53 both that copyright notice and this permission notice appear in 54 supporting documentation, and that the names of Digital or MIT not be 55 used in advertising or publicity pertaining to distribution of the 56 software without specific, written prior permission. 57 58 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 59 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 60 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 61 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 62 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 63 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 64 SOFTWARE. 65 66 ********************************************************/ 67 68 #include <dtop.h> 69 #if NDTOP > 0 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/ioctl.h> 73 #include <sys/tty.h> 74 #include <sys/proc.h> 75 #include <sys/map.h> 76 #include <sys/buf.h> 77 #include <sys/conf.h> 78 #include <sys/file.h> 79 #include <sys/uio.h> 80 #include <sys/kernel.h> 81 #include <sys/syslog.h> 82 83 #include <machine/pmioctl.h> 84 #include <machine/machConst.h> 85 #include <machine/dc7085cons.h> 86 87 #include <pmax/pmax/pmaxtype.h> 88 #include <pmax/pmax/maxine.h> 89 #include <pmax/pmax/asic.h> 90 91 #include <pmax/dev/device.h> 92 #include <pmax/dev/dtopreg.h> 93 #include <pmax/dev/fbreg.h> 94 95 extern int pmax_boardtype; 96 97 extern int ttrstrt __P((void *)); 98 void dtop_keyboard_repeat __P((void *)); 99 int dtop_null_device_handler __P((dtop_device_t, dtop_message_t, int, int)); 100 int dtop_locator_handler __P((dtop_device_t, dtop_message_t, int, int)); 101 int dtop_keyboard_handler __P((dtop_device_t, dtop_message_t, int, int)); 102 int dtopparam __P((struct tty *, struct termios *)); 103 int dtopstop __P((struct tty *, int)); 104 void dtopstart __P((struct tty *)); 105 void dtopKBDPutc __P((dev_t, int)); 106 107 struct tty dtop_tty[NDTOP]; 108 void (*dtopDivertXInput)(); /* X windows keyboard input routine */ 109 void (*dtopMouseEvent)(); /* X windows mouse motion event routine */ 110 void (*dtopMouseButtons)(); /* X windows mouse buttons event routine */ 111 112 #define DTOP_MAX_POLL 0x7fff /* about half a sec */ 113 114 typedef volatile unsigned int *data_reg_t; /* uC */ 115 #define DTOP_GET_BYTE(data) (((*(data)) >> 8) & 0xff) 116 #define DTOP_PUT_BYTE(data,c) { *(data) = (c) << 8; } 117 118 typedef volatile unsigned int *poll_reg_t; /* SIR */ 119 #define DTOP_RX_AVAIL(poll) (*(poll) & 1) 120 #define DTOP_TX_AVAIL(poll) (*(poll) & 2) 121 122 #define GET_SHORT(b0,b1) (((b0)<<8)|(b1)) 123 124 /* 125 * Driver status 126 */ 127 struct dtop_softc { 128 data_reg_t data; 129 poll_reg_t poll; 130 char polling_mode; 131 char probed_once; 132 short bad_pkts; 133 134 struct dtop_ds { 135 int (*handler)(); 136 dtop_device status; 137 } device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1]; 138 139 # define DTOP_DEVICE_NO(address) (((address)-DTOP_ADDR_FIRST)>>1) 140 141 } dtop_softc[NDTOP]; 142 143 typedef struct dtop_softc *dtop_softc_t; 144 struct tty dtop_tty[NDTOP]; 145 146 /* 147 * lk201 keyboard divisions and up/down mode key bitmap. 148 */ 149 #define NUMDIVS 14 150 static u_char divbeg[NUMDIVS] = {0xbf, 0x91, 0xbc, 0xbd, 0xb0, 0xad, 0xa6, 151 0xa9, 0x88, 0x56, 0x63, 0x6f, 0x7b, 0x7e}; 152 static u_char divend[NUMDIVS] = {0xff, 0xa5, 0xbc, 0xbe, 0xb2, 0xaf, 0xa8, 153 0xac, 0x90, 0x62, 0x6e, 0x7a, 0x7d, 0x87}; 154 /* 155 * Initial defaults, groups 5 and 6 are up/down 156 */ 157 static u_long keymodes[8] = {0, 0, 0, 0, 0, 0x0003e000, 0, 0}; 158 159 /* 160 * Definition of the driver for the auto-configuration program. 161 */ 162 int dtopprobe(); 163 void dtopintr(); 164 struct driver dtopdriver = { 165 "dtop", dtopprobe, 0, 0, dtopintr, 166 }; 167 168 dtopprobe(cp) 169 struct pmax_ctlr *cp; 170 { 171 register struct tty *tp; 172 register int cntr; 173 int dtopunit = cp->pmax_unit, i, s; 174 dtop_softc_t dtop; 175 176 if (dtopunit >= NDTOP) 177 return (0); 178 if (badaddr(cp->pmax_addr, 2)) 179 return (0); 180 dtop = &dtop_softc[dtopunit]; 181 182 dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR); 183 dtop->data = (data_reg_t)cp->pmax_addr; 184 185 for (i = 0; i < DTOP_MAX_DEVICES; i++) 186 dtop->device[i].handler = dtop_null_device_handler; 187 188 /* a lot more needed here, fornow: */ 189 dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler; 190 dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler; 191 dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state = 192 K_AR_IDLE; 193 194 dtop->probed_once = 1; 195 printf("dtop%d at nexus0 csr 0x%x priority %d\n", 196 cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 197 return (1); 198 } 199 200 dtopopen(dev, flag, mode, p) 201 dev_t dev; 202 int flag, mode; 203 struct proc *p; 204 { 205 register struct tty *tp; 206 register int unit; 207 int s, error = 0; 208 209 unit = minor(dev); 210 if (unit >= NDTOP) 211 return (ENXIO); 212 tp = &dtop_tty[unit]; 213 tp->t_oproc = dtopstart; 214 tp->t_param = dtopparam; 215 tp->t_dev = dev; 216 if ((tp->t_state & TS_ISOPEN) == 0) { 217 tp->t_state |= TS_WOPEN; 218 ttychars(tp); 219 if (tp->t_ispeed == 0) { 220 tp->t_iflag = TTYDEF_IFLAG; 221 tp->t_oflag = TTYDEF_OFLAG; 222 tp->t_cflag = TTYDEF_CFLAG; 223 tp->t_lflag = TTYDEF_LFLAG; 224 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 225 } 226 (void) dtopparam(tp, &tp->t_termios); 227 ttsetwater(tp); 228 } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 229 return (EBUSY); 230 s = spltty(); 231 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 232 !(tp->t_state & TS_CARR_ON)) { 233 tp->t_state |= TS_WOPEN; 234 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 235 ttopen, 0)) 236 break; 237 } 238 splx(s); 239 if (error) 240 return (error); 241 error = (*linesw[tp->t_line].l_open)(dev, tp); 242 return (error); 243 } 244 245 /*ARGSUSED*/ 246 dtopclose(dev, flag, mode, p) 247 dev_t dev; 248 int flag, mode; 249 struct proc *p; 250 { 251 register struct tty *tp; 252 register int unit; 253 254 unit = minor(dev); 255 tp = &dtop_tty[unit]; 256 (*linesw[tp->t_line].l_close)(tp, flag); 257 return (ttyclose(tp)); 258 } 259 260 dtopread(dev, uio, flag) 261 dev_t dev; 262 struct uio *uio; 263 { 264 register struct tty *tp; 265 266 tp = &dtop_tty[minor(dev)]; 267 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 268 } 269 270 dtopwrite(dev, uio, flag) 271 dev_t dev; 272 struct uio *uio; 273 { 274 register struct tty *tp; 275 276 tp = &dtop_tty[minor(dev)]; 277 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 278 } 279 280 /*ARGSUSED*/ 281 dtopioctl(dev, cmd, data, flag, p) 282 dev_t dev; 283 int cmd; 284 caddr_t data; 285 int flag; 286 struct proc *p; 287 { 288 register struct tty *tp; 289 register int unit = minor(dev); 290 int error; 291 292 tp = &dtop_tty[unit]; 293 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 294 if (error >= 0) 295 return (error); 296 error = ttioctl(tp, cmd, data, flag); 297 if (error >= 0) 298 return (error); 299 300 switch (cmd) { 301 302 case TIOCSBRK: 303 ttyoutput(0, tp); 304 break; 305 306 case TIOCCBRK: 307 ttyoutput(0, tp); 308 break; 309 310 case TIOCMGET: 311 *(int *)data = DML_DTR | DML_DSR | DML_CAR; 312 break; 313 314 default: 315 return (ENOTTY); 316 } 317 return (0); 318 } 319 320 /* 321 * Interrupt routine 322 */ 323 void 324 dtopintr(unit) 325 int unit; 326 { 327 dtop_message msg; 328 int devno; 329 dtop_softc_t dtop; 330 331 dtop = &dtop_softc[unit]; 332 if (dtop_get_packet(dtop, &msg) < 0) { 333 #ifdef DIAGNOSTIC 334 printf("dtop: overrun (or stray)\n"); 335 #endif 336 /* 337 * Ugh! The most common occurrence of a data overrun is upon a 338 * key press and the result is a software generated "stuck key". 339 * All I can think to do is fake an "all keys up" whenever a 340 * data overrun occurs. 341 */ 342 msg.src_address = 0x6c; 343 msg.code.val.len = 1; 344 msg.body[0] = DTOP_KBD_EMPTY; 345 } 346 347 /* 348 * If not probed yet, just throw the data away. 349 */ 350 if (!dtop->probed_once) 351 return; 352 353 devno = DTOP_DEVICE_NO(msg.src_address); 354 if (devno < 0 || devno > 15) 355 return; 356 (void) (*dtop->device[devno].handler) 357 (&dtop->device[devno].status, &msg, 358 DTOP_EVENT_RECEIVE_PACKET, 0); 359 } 360 361 void 362 dtopstart(tp) 363 register struct tty *tp; 364 { 365 register int cc; 366 int s; 367 368 s = spltty(); 369 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 370 goto out; 371 if (tp->t_outq.c_cc <= tp->t_lowat) { 372 if (tp->t_state & TS_ASLEEP) { 373 tp->t_state &= ~TS_ASLEEP; 374 wakeup((caddr_t)&tp->t_outq); 375 } 376 selwakeup(&tp->t_wsel); 377 } 378 if (tp->t_outq.c_cc == 0) 379 goto out; 380 /* handle console specially */ 381 if (tp == dtop_tty) { 382 while (tp->t_outq.c_cc > 0) { 383 cc = getc(&tp->t_outq) & 0x7f; 384 cnputc(cc); 385 } 386 /* 387 * After we flush the output queue we may need to wake 388 * up the process that made the output. 389 */ 390 if (tp->t_outq.c_cc <= tp->t_lowat) { 391 if (tp->t_state & TS_ASLEEP) { 392 tp->t_state &= ~TS_ASLEEP; 393 wakeup((caddr_t)&tp->t_outq); 394 } 395 selwakeup(&tp->t_wsel); 396 } 397 } 398 out: 399 splx(s); 400 } 401 402 void 403 dtopKBDPutc(dev, c) 404 dev_t dev; 405 int c; 406 { 407 register int i; 408 static int param = 0, cmd, mod, typ; 409 static u_char parms[2]; 410 411 /* 412 * Emulate the lk201 command codes. 413 */ 414 if (param == 0) { 415 typ = (c & 0x1); 416 cmd = ((c >> 3) & 0xf); 417 mod = ((c >> 1) & 0x3); 418 } else 419 parms[param - 1] = (c & 0x7f); 420 if (c & 0x80) { 421 if (typ) { 422 /* 423 * A peripheral command code. Someday this driver 424 * should know how to send commands to the lk501, 425 * but until then this is all essentially a no-op. 426 */ 427 ; 428 } else { 429 /* 430 * Set modes. These have to be emulated in software. 431 */ 432 if (cmd > 0 && cmd < 15) { 433 cmd--; 434 if (mod & 0x2) 435 for (i = divbeg[cmd]; i <= divend[cmd]; i++) 436 keymodes[i >> 5] |= 437 (1 << (i & 0x1f)); 438 else 439 for (i = divbeg[cmd]; i <= divend[cmd]; i++) 440 keymodes[i >> 5] &= 441 ~(1 << (i & 0x1f)); 442 } 443 } 444 param = 0; 445 } else if (++param > 2) 446 param = 2; 447 } 448 449 /* 450 * Take a packet off dtop interface 451 * A packet MUST be there, this is not checked for. 452 */ 453 #define DTOP_ESC_CHAR 0xf8 454 dtop_escape(c) 455 { 456 /* I donno much about this stuff.. */ 457 switch (c) { 458 case 0xe8: return (0xf8); 459 case 0xe9: return (0xf9); 460 case 0xea: return (0xfa); 461 case 0xeb: return (0xfb); 462 default: /* printf("{esc %x}", c); */ 463 return (c); 464 } 465 } 466 467 dtop_get_packet(dtop, pkt) 468 dtop_softc_t dtop; 469 dtop_message_t pkt; 470 { 471 register poll_reg_t poll; 472 register data_reg_t data; 473 register int max, i, len; 474 register unsigned char c; 475 476 poll = dtop->poll; 477 data = dtop->data; 478 479 /* 480 * The interface does not handle us the first byte, 481 * which is our address and cannot ever be anything 482 * else but 0x50. This is a good thing, it makes 483 * the average packet exactly one word long, too. 484 */ 485 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 486 DELAY(1); 487 if (max == DTOP_MAX_POLL) 488 goto bad; 489 pkt->src_address = DTOP_GET_BYTE(data); 490 491 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 492 DELAY(1); 493 if (max == DTOP_MAX_POLL) 494 goto bad; 495 pkt->code.bits = DTOP_GET_BYTE(data); 496 497 /* 498 * Now get data and checksum 499 */ 500 len = pkt->code.val.len + 1; 501 c = 0; 502 for (i = 0; i < len; i++) { 503 again: 504 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 505 DELAY(1); 506 if (max == DTOP_MAX_POLL) 507 goto bad; 508 if (c == DTOP_ESC_CHAR) { 509 c = dtop_escape(DTOP_GET_BYTE(data) & 0xff); 510 } else { 511 c = DTOP_GET_BYTE(data); 512 if (c == DTOP_ESC_CHAR) 513 goto again; 514 } 515 pkt->body[i] = c; 516 } 517 return (len); 518 bad: 519 dtop->bad_pkts++; 520 return (-1); 521 } 522 523 /* 524 * Get a keyboard char for the console 525 */ 526 dtopKBDGetc() 527 { 528 register int c; 529 dtop_softc_t dtop; 530 531 dtop = &dtop_softc[0]; 532 again: 533 c = -1; 534 535 /* 536 * Now check keyboard 537 */ 538 if (DTOP_RX_AVAIL(dtop->poll)) { 539 540 dtop_message msg; 541 struct dtop_ds *ds; 542 543 if (dtop_get_packet(dtop, &msg) >= 0) { 544 545 ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)]; 546 if (ds->handler == dtop_keyboard_handler) { 547 548 c = dtop_keyboard_handler( 549 &ds->status, &msg, 550 DTOP_EVENT_RECEIVE_PACKET, -1); 551 552 if (c > 0) return c; 553 554 c = -1; 555 } 556 } 557 } 558 559 if (c == -1) { 560 DELAY(100); 561 goto again; 562 } 563 564 return c; 565 } 566 567 int 568 dtopparam(tp, t) 569 struct tty *tp; 570 struct termios *t; 571 { 572 if (tp->t_ispeed == 0) 573 ttymodem(tp, 0); 574 else 575 /* called too early to invoke ttymodem, sigh */ 576 tp->t_state |= TS_CARR_ON; 577 return (0); 578 } 579 580 /* 581 * Stop output on a line. 582 */ 583 /*ARGSUSED*/ 584 dtopstop(tp, flag) 585 register struct tty *tp; 586 int flag; 587 { 588 int s; 589 590 s = spltty(); 591 if (tp->t_state & TS_BUSY) { 592 if (!(tp->t_state & TS_TTSTOP)) 593 tp->t_state |= TS_FLUSH; 594 } 595 splx(s); 596 } 597 598 /* 599 * Default handler function 600 */ 601 int 602 dtop_null_device_handler(dev, msg, event, outc) 603 dtop_device_t dev; 604 dtop_message_t msg; 605 int event; 606 int outc; 607 { 608 /* See if the message was to the default address (powerup) */ 609 610 /* Uhmm, donno how to handle this. Drop it */ 611 if (event == DTOP_EVENT_RECEIVE_PACKET) 612 dev->unknown_report = *msg; 613 return 0; 614 } 615 616 /* 617 * Handler for locator devices (mice) 618 */ 619 int 620 dtop_locator_handler(dev, msg, event, outc) 621 dtop_device_t dev; 622 dtop_message_t msg; 623 int event; 624 int outc; 625 { 626 register unsigned short buttons; 627 register short coord; 628 register int moved = 0; 629 static MouseReport currentRep; 630 register MouseReport *mrp = ¤tRep; 631 632 if (dtopMouseButtons) { 633 mrp->state = 0; 634 /* 635 * Do the position first 636 */ 637 coord = GET_SHORT(msg->body[2], msg->body[3]); 638 if (coord < 0) { 639 coord = -coord; 640 moved = 1; 641 } else if (coord > 0) { 642 mrp->state |= MOUSE_X_SIGN; 643 moved = 1; 644 } 645 mrp->dx = (coord & 0x1f); 646 coord = GET_SHORT(msg->body[4], msg->body[5]); 647 if (coord < 0) { 648 coord = -coord; 649 moved = 1; 650 } else if (coord > 0) { 651 mrp->state |= MOUSE_Y_SIGN; 652 moved = 1; 653 } 654 mrp->dy = (coord & 0x1f); 655 656 /* 657 * Time for the buttons now 658 * Shuffle button bits around to serial mouse order. 659 */ 660 buttons = GET_SHORT(msg->body[0], msg->body[1]); 661 mrp->state |= (((buttons >> 1) & 0x3) | ((buttons << 2) & 0x4)); 662 if (moved) 663 (*dtopMouseEvent)(mrp); 664 (*dtopMouseButtons)(mrp); 665 } 666 return (0); 667 } 668 669 /* 670 * Handler for keyboard devices 671 * Special case: outc set for recv packet means 672 * we are inside the kernel debugger 673 */ 674 int 675 dtop_keyboard_handler(dev, msg, event, outc) 676 dtop_device_t dev; 677 dtop_message_t msg; 678 int event; 679 int outc; 680 { 681 register u_char *ls, *le, *ns, *ne; 682 u_char save[11], retc; 683 int msg_len, c, s; 684 struct tty *tp = &dtop_tty[0]; 685 686 /* 687 * Fiddle about emulating an lk201 keyboard. The lk501 688 * designers carefully ensured that keyboard handlers could be 689 * stateless, then we turn around and use lots of state to 690 * emulate the stateful lk201, since the X11R5 X servers 691 * only know about the lk201... (oh well) 692 */ 693 /* 694 * Turn off any autorepeat timeout. 695 */ 696 s = splhigh(); 697 if (dev->keyboard.k_ar_state != K_AR_IDLE) { 698 dev->keyboard.k_ar_state = K_AR_IDLE; 699 untimeout(dtop_keyboard_repeat, (void *)dev); 700 } 701 splx(s); 702 msg_len = msg->code.val.len; 703 704 /* Check for errors */ 705 c = msg->body[0]; 706 if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) { 707 printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]); 708 #ifdef notdef 709 if (c != DTOP_KBD_OUT_ERR) return -1; 710 #endif 711 /* 712 * Fake an "all ups" to avoid the stuck key syndrome. 713 */ 714 c = msg->body[0] = DTOP_KBD_EMPTY; 715 msg_len = 1; 716 } 717 718 dev->keyboard.last_msec = TO_MS(time); 719 /* 720 * To make things readable, do a first pass cancelling out 721 * all keys that are still pressed, and a second one generating 722 * events. While generating events, do the upstrokes first 723 * from oldest to youngest, then the downstrokes from oldest 724 * to youngest. This copes with lost packets and provides 725 * a reasonable model even if scans are too slow. 726 */ 727 728 /* make a copy of new state first */ 729 if (msg_len == 1) 730 save[0] = msg->body[0]; 731 else if (msg_len > 0) 732 bcopy(msg->body, save, msg_len); 733 734 /* 735 * Cancel out any keys in both the last and current message as 736 * they are unchanged. 737 */ 738 if (msg_len > 0 && dev->keyboard.last_codes_count > 0) { 739 ls = dev->keyboard.last_codes; 740 le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count]; 741 ne = &msg->body[msg_len]; 742 for (; ls < le; ls++) { 743 for (ns = msg->body; ns < ne; ns++) 744 if (*ls == *ns) { 745 *ls = *ns = 0; 746 break; 747 } 748 } 749 } 750 751 /* 752 * Now generate all upstrokes 753 */ 754 le = dev->keyboard.last_codes; 755 ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1]; 756 for ( ; ls >= le; ls--) 757 if (c = *ls) { 758 (void) kbdMapChar(c); 759 760 if (outc == 0 && dtopDivertXInput && 761 (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f)))) 762 (*dtopDivertXInput)(c); 763 } 764 /* 765 * And finally the downstrokes 766 */ 767 ne = (char*)msg->body; 768 ns = (char*)&msg->body[msg_len - 1]; 769 retc = 0; 770 for ( ; ns >= ne; ns--) 771 if (*ns) { 772 c = kbdMapChar(*ns); 773 if (outc == 0) { 774 if (dtopDivertXInput) { 775 (*dtopDivertXInput)(*ns); 776 c = -1; /* consumed by X */ 777 } else if (c >= 0) 778 (*linesw[tp->t_line].l_rint)(c, tp); 779 dev->keyboard.k_ar_state = K_AR_ACTIVE; 780 } 781 /* return the related keycode anyways */ 782 if ((c >= 0) && (retc == 0)) 783 retc = c; 784 } 785 outc = retc; 786 /* install new scan state */ 787 if (msg_len == 1) 788 dev->keyboard.last_codes[0] = save[0]; 789 else if (msg_len > 0) 790 bcopy(save, dev->keyboard.last_codes, msg_len); 791 dev->keyboard.last_codes_count = msg_len; 792 if (dev->keyboard.k_ar_state == K_AR_ACTIVE) 793 timeout(dtop_keyboard_repeat, (void *)dev, hz / 2); 794 return (outc); 795 } 796 797 /* 798 * Do an autorepeat as required. 799 */ 800 void 801 dtop_keyboard_repeat(arg) 802 void *arg; 803 { 804 dtop_device_t dev = (dtop_device_t)arg; 805 register int i, c; 806 struct tty *tp = dtop_tty; 807 int s = spltty(), gotone = 0; 808 809 for (i = 0; i < dev->keyboard.last_codes_count; i++) { 810 c = (int)dev->keyboard.last_codes[i]; 811 if (c != DTOP_KBD_EMPTY && 812 (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))) == 0) { 813 dev->keyboard.k_ar_state = K_AR_TRIGGER; 814 if (dtopDivertXInput) { 815 (*dtopDivertXInput)(KEY_REPEAT); 816 gotone = 1; 817 continue; 818 } 819 820 if ((c = kbdMapChar(KEY_REPEAT)) >= 0) { 821 (*linesw[tp->t_line].l_rint)(c, tp); 822 gotone = 1; 823 } 824 } 825 } 826 if (gotone) 827 timeout(dtop_keyboard_repeat, arg, hz / 20); 828 else 829 dev->keyboard.k_ar_state = K_AR_IDLE; 830 splx(s); 831 } 832 #endif 833