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