1 /*- 2 * Copyright (c) 1992 The Regents of the University of California. 3 * 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 7.2 (Berkeley) 12/20/92 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_autorepeat __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 static void dtop_keyboard_repeat __P((dtop_device_t)); 107 108 struct tty dtop_tty[NDTOP]; 109 void (*dtopDivertXInput)(); /* X windows keyboard input routine */ 110 void (*dtopMouseEvent)(); /* X windows mouse motion event routine */ 111 void (*dtopMouseButtons)(); /* X windows mouse buttons event routine */ 112 113 #define DTOP_MAX_POLL 0x7fff /* about half a sec */ 114 115 typedef volatile unsigned int *data_reg_t; /* uC */ 116 #define DTOP_GET_BYTE(data) (((*(data)) >> 8) & 0xff) 117 #define DTOP_PUT_BYTE(data,c) { *(data) = (c) << 8; } 118 119 typedef volatile unsigned int *poll_reg_t; /* SIR */ 120 #define DTOP_RX_AVAIL(poll) (*(poll) & 1) 121 #define DTOP_TX_AVAIL(poll) (*(poll) & 2) 122 123 #define GET_SHORT(b0,b1) (((b0)<<8)|(b1)) 124 125 /* 126 * Driver status 127 */ 128 struct dtop_softc { 129 data_reg_t data; 130 poll_reg_t poll; 131 char polling_mode; 132 char probed_once; 133 short bad_pkts; 134 135 struct dtop_ds { 136 int (*handler)(); 137 dtop_device status; 138 } device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1]; 139 140 # define DTOP_DEVICE_NO(address) (((address)-DTOP_ADDR_FIRST)>>1) 141 142 } dtop_softc[NDTOP]; 143 144 typedef struct dtop_softc *dtop_softc_t; 145 struct tty dtop_tty[NDTOP]; 146 147 /* 148 * lk201 keyboard divisions and up/down mode key bitmap. 149 */ 150 #define NUMDIVS 14 151 static u_char divbeg[NUMDIVS] = {0xbf, 0x91, 0xbc, 0xbd, 0xb0, 0xad, 0xa6, 152 0xa9, 0x88, 0x56, 0x63, 0x6f, 0x7b, 0x7e}; 153 static u_char divend[NUMDIVS] = {0xff, 0xa5, 0xbc, 0xbe, 0xb2, 0xaf, 0xa8, 154 0xac, 0x90, 0x62, 0x6e, 0x7a, 0x7d, 0x87}; 155 /* 156 * Initial defaults, groups 5 and 6 are up/down 157 */ 158 static u_long keymodes[8] = {0, 0, 0, 0, 0, 0x0003e000, 0, 0}; 159 160 /* 161 * Definition of the driver for the auto-configuration program. 162 */ 163 int dtopprobe(); 164 void dtopintr(); 165 struct driver dtopdriver = { 166 "dtop", dtopprobe, 0, 0, dtopintr, 167 }; 168 169 dtopprobe(cp) 170 struct pmax_ctlr *cp; 171 { 172 register struct tty *tp; 173 register int cntr; 174 int dtopunit = cp->pmax_unit, i, s; 175 dtop_softc_t dtop; 176 177 if (dtopunit >= NDTOP) 178 return (0); 179 if (badaddr(cp->pmax_addr, 2)) 180 return (0); 181 dtop = &dtop_softc[dtopunit]; 182 183 dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR); 184 dtop->data = (data_reg_t)cp->pmax_addr; 185 186 for (i = 0; i < DTOP_MAX_DEVICES; i++) 187 dtop->device[i].handler = dtop_null_device_handler; 188 189 /* a lot more needed here, fornow: */ 190 dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler; 191 dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler; 192 dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.poll_frequency = 193 (hz * 5) / 100; /* x0.01 secs */ 194 dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state = 195 K_AR_IDLE; 196 197 /* 198 * Sometimes a first interrupt gets lost, so just in case 199 * poke it now. 200 */ 201 dtopintr(dtopunit); 202 dtop->probed_once = 1; 203 printf("dtop%d at nexus0 csr 0x%x priority %d\n", 204 cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 205 return (1); 206 } 207 208 dtopopen(dev, flag, mode, p) 209 dev_t dev; 210 int flag, mode; 211 struct proc *p; 212 { 213 register struct tty *tp; 214 register int unit; 215 int s, error = 0; 216 217 unit = minor(dev); 218 if (unit >= NDTOP) 219 return (ENXIO); 220 tp = &dtop_tty[unit]; 221 tp->t_oproc = dtopstart; 222 tp->t_param = dtopparam; 223 tp->t_dev = dev; 224 if ((tp->t_state & TS_ISOPEN) == 0) { 225 tp->t_state |= TS_WOPEN; 226 ttychars(tp); 227 if (tp->t_ispeed == 0) { 228 tp->t_iflag = TTYDEF_IFLAG; 229 tp->t_oflag = TTYDEF_OFLAG; 230 tp->t_cflag = TTYDEF_CFLAG; 231 tp->t_lflag = TTYDEF_LFLAG; 232 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 233 } 234 (void) dtopparam(tp, &tp->t_termios); 235 ttsetwater(tp); 236 } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 237 return (EBUSY); 238 s = spltty(); 239 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 240 !(tp->t_state & TS_CARR_ON)) { 241 tp->t_state |= TS_WOPEN; 242 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 243 ttopen, 0)) 244 break; 245 } 246 splx(s); 247 if (error) 248 return (error); 249 error = (*linesw[tp->t_line].l_open)(dev, tp); 250 return (error); 251 } 252 253 /*ARGSUSED*/ 254 dtopclose(dev, flag, mode, p) 255 dev_t dev; 256 int flag, mode; 257 struct proc *p; 258 { 259 register struct tty *tp; 260 register int unit; 261 262 unit = minor(dev); 263 tp = &dtop_tty[unit]; 264 (*linesw[tp->t_line].l_close)(tp, flag); 265 return (ttyclose(tp)); 266 } 267 268 dtopread(dev, uio, flag) 269 dev_t dev; 270 struct uio *uio; 271 { 272 register struct tty *tp; 273 274 tp = &dtop_tty[minor(dev)]; 275 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 276 } 277 278 dtopwrite(dev, uio, flag) 279 dev_t dev; 280 struct uio *uio; 281 { 282 register struct tty *tp; 283 284 tp = &dtop_tty[minor(dev)]; 285 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 286 } 287 288 /*ARGSUSED*/ 289 dtopioctl(dev, cmd, data, flag, p) 290 dev_t dev; 291 int cmd; 292 caddr_t data; 293 int flag; 294 struct proc *p; 295 { 296 register struct tty *tp; 297 register int unit = minor(dev); 298 int error; 299 300 tp = &dtop_tty[unit]; 301 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 302 if (error >= 0) 303 return (error); 304 error = ttioctl(tp, cmd, data, flag); 305 if (error >= 0) 306 return (error); 307 308 switch (cmd) { 309 310 case TIOCSBRK: 311 ttyoutput(0, tp); 312 break; 313 314 case TIOCCBRK: 315 ttyoutput(0, tp); 316 break; 317 318 case TIOCMGET: 319 *(int *)data = DML_DTR | DML_DSR | DML_CAR; 320 break; 321 322 default: 323 return (ENOTTY); 324 } 325 return (0); 326 } 327 328 /* 329 * Interrupt routine 330 */ 331 void 332 dtopintr(unit) 333 int unit; 334 { 335 dtop_message msg; 336 int devno; 337 dtop_softc_t dtop; 338 339 dtop = &dtop_softc[unit]; 340 if (dtop_get_packet(dtop, &msg) < 0) { 341 if (dtop->probed_once) 342 printf("%s", "dtop: overrun (or stray)\n"); 343 return; 344 } 345 346 devno = DTOP_DEVICE_NO(msg.src_address); 347 if (devno < 0 || devno > 15) 348 return; 349 350 (void) (*dtop->device[devno].handler) 351 (&dtop->device[devno].status, &msg, 352 DTOP_EVENT_RECEIVE_PACKET, 0); 353 } 354 355 void 356 dtopstart(tp) 357 register struct tty *tp; 358 { 359 register int cc; 360 int s; 361 362 s = spltty(); 363 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 364 goto out; 365 if (tp->t_outq.c_cc <= tp->t_lowat) { 366 if (tp->t_state & TS_ASLEEP) { 367 tp->t_state &= ~TS_ASLEEP; 368 wakeup((caddr_t)&tp->t_outq); 369 } 370 selwakeup(&tp->t_wsel); 371 } 372 if (tp->t_outq.c_cc == 0) 373 goto out; 374 /* handle console specially */ 375 if (tp == dtop_tty) { 376 while (tp->t_outq.c_cc > 0) { 377 cc = getc(&tp->t_outq) & 0x7f; 378 cnputc(cc); 379 } 380 /* 381 * After we flush the output queue we may need to wake 382 * up the process that made the output. 383 */ 384 if (tp->t_outq.c_cc <= tp->t_lowat) { 385 if (tp->t_state & TS_ASLEEP) { 386 tp->t_state &= ~TS_ASLEEP; 387 wakeup((caddr_t)&tp->t_outq); 388 } 389 selwakeup(&tp->t_wsel); 390 } 391 } 392 out: 393 splx(s); 394 } 395 396 void 397 dtopKBDPutc(dev, c) 398 dev_t dev; 399 int c; 400 { 401 register int i; 402 static int param = 0, cmd, mod, typ; 403 static u_char parms[2]; 404 405 /* 406 * Emulate the lk201 command codes. 407 */ 408 if (param == 0) { 409 typ = (c & 0x1); 410 cmd = ((c >> 3) & 0xf); 411 mod = ((c >> 1) & 0x3); 412 } else 413 parms[param - 1] = (c & 0x7f); 414 if (c & 0x80) { 415 if (typ) { 416 /* 417 * A peripheral command code. Someday this driver 418 * should know how to send commands to the lk501, 419 * but until then this is all essentially a no-op. 420 */ 421 ; 422 } else { 423 /* 424 * Set modes. These have to be emulated in software. 425 */ 426 if (cmd > 0 && cmd < 15) { 427 cmd--; 428 if (mod & 0x2) 429 for (i = divbeg[cmd]; i <= divend[cmd]; i++) 430 keymodes[i >> 5] |= 431 (1 << (i & 0x1f)); 432 else 433 for (i = divbeg[cmd]; i <= divend[cmd]; i++) 434 keymodes[i >> 5] &= 435 ~(1 << (i & 0x1f)); 436 } 437 } 438 param = 0; 439 } else if (++param > 2) 440 param = 2; 441 } 442 443 /* 444 * Take a packet off dtop interface 445 * A packet MUST be there, this is not checked for. 446 */ 447 #define DTOP_ESC_CHAR 0xf8 448 dtop_escape(c) 449 { 450 /* I donno much about this stuff.. */ 451 switch (c) { 452 case 0xe8: return (0xf8); 453 case 0xe9: return (0xf9); 454 case 0xea: return (0xfa); 455 case 0xeb: return (0xfb); 456 default: /* printf("{esc %x}", c); */ 457 return (c); 458 } 459 } 460 461 dtop_get_packet(dtop, pkt) 462 dtop_softc_t dtop; 463 dtop_message_t pkt; 464 { 465 register poll_reg_t poll; 466 register data_reg_t data; 467 register int max, i, len; 468 register unsigned char c; 469 470 poll = dtop->poll; 471 data = dtop->data; 472 473 /* 474 * The interface does not handle us the first byte, 475 * which is our address and cannot ever be anything 476 * else but 0x50. This is a good thing, it makes 477 * the average packet exactly one word long, too. 478 */ 479 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 480 DELAY(1); 481 if (max == DTOP_MAX_POLL) 482 goto bad; 483 pkt->src_address = DTOP_GET_BYTE(data); 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->code.bits = DTOP_GET_BYTE(data); 490 491 /* 492 * Now get data and checksum 493 */ 494 len = pkt->code.val.len + 1; 495 c = 0; 496 for (i = 0; i < len; i++) { 497 again: 498 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 499 DELAY(1); 500 if (max == DTOP_MAX_POLL) 501 goto bad; 502 if (c == DTOP_ESC_CHAR) { 503 c = dtop_escape(DTOP_GET_BYTE(data) & 0xff); 504 } else { 505 c = DTOP_GET_BYTE(data); 506 if (c == DTOP_ESC_CHAR) 507 goto again; 508 } 509 pkt->body[i] = c; 510 } 511 return (len); 512 bad: 513 dtop->bad_pkts++; 514 return (-1); 515 } 516 517 /* 518 * Get a keyboard char for the console 519 */ 520 dtopKBDGetc() 521 { 522 register int c; 523 dtop_softc_t dtop; 524 525 dtop = &dtop_softc[0]; 526 again: 527 c = -1; 528 529 /* 530 * Now check keyboard 531 */ 532 if (DTOP_RX_AVAIL(dtop->poll)) { 533 534 dtop_message msg; 535 struct dtop_ds *ds; 536 537 if (dtop_get_packet(dtop, &msg) >= 0) { 538 539 ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)]; 540 if (ds->handler == dtop_keyboard_handler) { 541 542 c = dtop_keyboard_handler( 543 &ds->status, &msg, 544 DTOP_EVENT_RECEIVE_PACKET, -1); 545 546 if (c > 0) return c; 547 548 c = -1; 549 } 550 } 551 } 552 553 if (c == -1) { 554 DELAY(100); 555 goto again; 556 } 557 558 return c; 559 } 560 561 int 562 dtopparam(tp, t) 563 struct tty *tp; 564 struct termios *t; 565 { 566 if (tp->t_ispeed == 0) 567 ttymodem(tp, 0); 568 else 569 /* called too early to invoke ttymodem, sigh */ 570 tp->t_state |= TS_CARR_ON; 571 return (0); 572 } 573 574 /* 575 * Stop output on a line. 576 */ 577 /*ARGSUSED*/ 578 dtopstop(tp, flag) 579 register struct tty *tp; 580 int flag; 581 { 582 int s; 583 584 s = spltty(); 585 if (tp->t_state & TS_BUSY) { 586 if (!(tp->t_state & TS_TTSTOP)) 587 tp->t_state |= TS_FLUSH; 588 } 589 splx(s); 590 } 591 592 /* 593 * Default handler function 594 */ 595 int 596 dtop_null_device_handler(dev, msg, event, outc) 597 dtop_device_t dev; 598 dtop_message_t msg; 599 int event; 600 int outc; 601 { 602 /* See if the message was to the default address (powerup) */ 603 604 /* Uhmm, donno how to handle this. Drop it */ 605 if (event == DTOP_EVENT_RECEIVE_PACKET) 606 dev->unknown_report = *msg; 607 return 0; 608 } 609 610 /* 611 * Handler for locator devices (mice) 612 */ 613 int 614 dtop_locator_handler(dev, msg, event, outc) 615 dtop_device_t dev; 616 dtop_message_t msg; 617 int event; 618 int outc; 619 { 620 register unsigned short buttons; 621 register short coord; 622 register int moved = 0; 623 static MouseReport currentRep; 624 register MouseReport *mrp = ¤tRep; 625 626 if (dtopMouseButtons) { 627 mrp->state = 0; 628 /* 629 * Do the position first 630 */ 631 coord = GET_SHORT(msg->body[2], msg->body[3]); 632 if (coord < 0) { 633 coord = -coord; 634 moved = 1; 635 } else if (coord > 0) { 636 mrp->state |= MOUSE_X_SIGN; 637 moved = 1; 638 } 639 mrp->dx = (coord & 0x1f); 640 coord = GET_SHORT(msg->body[4], msg->body[5]); 641 if (coord < 0) { 642 coord = -coord; 643 moved = 1; 644 } else if (coord > 0) { 645 mrp->state |= MOUSE_Y_SIGN; 646 moved = 1; 647 } 648 mrp->dy = (coord & 0x1f); 649 650 /* 651 * Time for the buttons now 652 */ 653 buttons = GET_SHORT(msg->body[0], msg->body[1]); 654 mrp->state |= (buttons & 0x7); 655 if (moved) 656 (*dtopMouseEvent)(mrp); 657 (*dtopMouseButtons)(mrp); 658 } 659 return (0); 660 } 661 662 /* 663 * Handler for keyboard devices 664 * Special case: outc set for recv packet means 665 * we are inside the kernel debugger 666 */ 667 int 668 dtop_keyboard_handler(dev, msg, event, outc) 669 dtop_device_t dev; 670 dtop_message_t msg; 671 int event; 672 int outc; 673 { 674 register u_char *ls, *le, *ns, *ne; 675 u_char save[11], retc; 676 int msg_len, c; 677 struct tty *tp = &dtop_tty[0]; 678 679 /* 680 * Fiddle about emulating an lk201 keyboard. The lk501 681 * designers carefully ensured that keyboard handlers could be 682 * stateless, then we turn around and use lots of state to 683 * emulate the stateful lk201, since the X11R5 X servers 684 * only know about the lk201... (oh well) 685 */ 686 msg_len = msg->code.val.len; 687 688 /* Check for errors */ 689 c = msg->body[0]; 690 if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) { 691 printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]); 692 if (c != DTOP_KBD_OUT_ERR) return -1; 693 /* spec sez if scan list overflow still there is data */ 694 msg->body[0] = 0; 695 } 696 697 dev->keyboard.last_msec = TO_MS(time); 698 699 switch (dev->keyboard.k_ar_state) { 700 case K_AR_IDLE: 701 if (outc != 0xff) /* from debugger, might be too early */ 702 dtop_keyboard_autorepeat(dev); 703 /* fall through */ 704 case K_AR_TRIGGER: 705 dev->keyboard.k_ar_state = K_AR_ACTIVE; 706 break; 707 case K_AR_ACTIVE: 708 break; 709 case K_AR_OFF: 710 printf("dtop keyb off?\n"); 711 dev->keyboard.k_ar_state = K_AR_IDLE; 712 } 713 714 /* 715 * To make things readable, do a first pass cancelling out 716 * all keys that are still pressed, and a second one generating 717 * events. While generating events, do the upstrokes first 718 * from oldest to youngest, then the downstrokes from oldest 719 * to youngest. This copes with lost packets and provides 720 * a reasonable model even if scans are too slow. 721 */ 722 723 /* make a copy of new state first */ 724 if (msg_len == 1) 725 save[0] = msg->body[0]; 726 else if (msg_len > 0) 727 bcopy(msg->body, save, msg_len); 728 729 /* 730 * Cancel out any keys in both the last and current message as 731 * they are unchanged. 732 */ 733 if (msg_len > 0 && dev->keyboard.last_codes_count > 0) { 734 ls = dev->keyboard.last_codes; 735 le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count]; 736 ne = &msg->body[msg_len]; 737 for (; ls < le; ls++) { 738 for (ns = msg->body; ns < ne; ns++) 739 if (*ls == *ns) { 740 *ls = *ns = 0; 741 break; 742 } 743 } 744 } 745 746 /* 747 * Now generate all upstrokes 748 */ 749 le = dev->keyboard.last_codes; 750 ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1]; 751 for ( ; ls >= le; ls--) 752 if (c = *ls) { 753 (void) kbdMapChar(c); 754 755 if (outc == 0 && dtopDivertXInput && 756 (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f)))) 757 (*dtopDivertXInput)(c); 758 } 759 /* 760 * And finally the downstrokes 761 */ 762 ne = (char*)msg->body; 763 ns = (char*)&msg->body[msg_len - 1]; 764 retc = 0; 765 for ( ; ns >= ne; ns--) 766 if (*ns) { 767 c = kbdMapChar(*ns); 768 if (outc == 0) { 769 if (dtopDivertXInput) { 770 (*dtopDivertXInput)(*ns); 771 c = -1; /* consumed by X */ 772 } else if (c >= 0) 773 (*linesw[tp->t_line].l_rint)(c, tp); 774 } 775 /* return the related keycode anyways */ 776 if ((c >= 0) && (retc == 0)) 777 retc = c; 778 } 779 outc = retc; 780 /* install new scan state */ 781 if (msg_len == 1) 782 dev->keyboard.last_codes[0] = save[0]; 783 else if (msg_len > 0) 784 bcopy(save, dev->keyboard.last_codes, msg_len); 785 dev->keyboard.last_codes_count = msg_len; 786 return (outc); 787 } 788 789 /* 790 * Timeout routine to do autorepeat. 791 */ 792 void 793 dtop_keyboard_autorepeat(arg) 794 void *arg; 795 { 796 dtop_device_t dev = (dtop_device_t)arg; 797 int s; 798 799 s = spltty(); 800 if (dev->keyboard.k_ar_state != K_AR_IDLE) 801 dtop_keyboard_repeat(dev); 802 803 if (dev->keyboard.k_ar_state == K_AR_OFF) 804 dev->keyboard.k_ar_state = K_AR_IDLE; 805 else 806 timeout(dtop_keyboard_autorepeat, dev, dev->keyboard.poll_frequency); 807 808 splx(s); 809 } 810 811 /* 812 * See if an autorepeat is required. 813 */ 814 static void 815 dtop_keyboard_repeat(dev) 816 dtop_device_t dev; 817 { 818 register int i, c; 819 register u_int t, t0; 820 struct tty *tp = dtop_tty; 821 822 for (i = 0; i < dev->keyboard.last_codes_count; i++) { 823 c = (int)dev->keyboard.last_codes[i]; 824 if (c != DTOP_KBD_EMPTY && 825 (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))) == 0) { 826 /* 827 * Got a char. See if enough time from stroke, 828 * or from last repeat. 829 */ 830 t0 = (dev->keyboard.k_ar_state == K_AR_TRIGGER) ? 30 : 500; 831 t = TO_MS(time); 832 if ((t - dev->keyboard.last_msec) < t0) 833 return; 834 835 dev->keyboard.k_ar_state = K_AR_TRIGGER; 836 837 if (dtopDivertXInput) { 838 (*dtopDivertXInput)(KEY_REPEAT); 839 return; 840 } 841 842 if ((c = kbdMapChar(KEY_REPEAT)) >= 0) 843 (*linesw[tp->t_line].l_rint)(c, tp); 844 return; 845 } 846 } 847 dev->keyboard.k_ar_state = K_AR_OFF; 848 } 849 #endif 850