1 /* $NetBSD: kbd.c,v 1.38 2002/01/28 09:57:00 aymeric Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * kbd.c 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.38 2002/01/28 09:57:00 aymeric Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/device.h> 44 #include <sys/ioctl.h> 45 #include <sys/tty.h> 46 #include <sys/proc.h> 47 #include <sys/file.h> 48 #include <sys/kernel.h> 49 #include <sys/syslog.h> 50 #include <sys/signalvar.h> 51 #include <dev/cons.h> 52 #include <machine/cpu.h> 53 #include <amiga/amiga/device.h> 54 #include <amiga/amiga/custom.h> 55 #ifdef DRACO 56 #include <m68k/asm_single.h> 57 #include <amiga/amiga/drcustom.h> 58 #endif 59 #include <amiga/amiga/cia.h> 60 #include <amiga/dev/itevar.h> 61 #include <amiga/dev/kbdreg.h> 62 #include <amiga/dev/kbdmap.h> 63 #include <amiga/dev/event_var.h> 64 #include <amiga/dev/vuid_event.h> 65 66 #include "kbd.h" 67 #include "ite.h" 68 69 /* WSKBD */ 70 71 /* 72 * If NWSKBD>0 we try to attach an wskbd device to us. What follows 73 * is definitions of callback functions and structures that are passed 74 * to wscons when initializing. 75 */ 76 77 /* 78 * Now with wscons this driver exhibits some weird behaviour. 79 * It may act both as a driver of its own and the md part of the 80 * wskbd driver. Therefore it can be accessed through /dev/kbd 81 * and /dev/wskbd0 both. 82 * 83 * The data from they keyboard may end up in at least four different 84 * places: 85 * - If this driver has been opened (/dev/kbd) and the 86 * direct mode (TIOCDIRECT) has been set, data goes to 87 * the process who opened the device. Data will transmit itself 88 * as described by the firm_event structure. 89 * - If wskbd support is compiled in and a wskbd driver has been 90 * attached then the data is sent to it. Wskbd in turn may 91 * - Send the data in the wscons_event form to a process that 92 * has opened /dev/wskbd0 93 * - Feed the data to a virtual terminal. 94 * - If an ite is present the data may be fed to it. 95 */ 96 97 #include "wskbd.h" 98 99 #if NWSKBD>0 100 #include <dev/wscons/wsconsio.h> 101 #include <dev/wscons/wskbdvar.h> 102 #include <dev/wscons/wsksymdef.h> 103 #include <dev/wscons/wsksymvar.h> 104 #include <amiga/dev/wskbdmap_amiga.h> 105 106 /* accessops */ 107 int kbd_enable(void *, int); 108 void kbd_set_leds(void *, int); 109 int kbd_ioctl(void *, u_long, caddr_t, int, struct proc *); 110 111 /* console ops */ 112 void kbd_getc(void *, u_int *, int *); 113 void kbd_pollc(void *, int); 114 void kbd_bell(void *, u_int, u_int, u_int); 115 116 static struct wskbd_accessops kbd_accessops = { 117 kbd_enable, 118 kbd_set_leds, 119 kbd_ioctl 120 }; 121 122 static struct wskbd_consops kbd_consops = { 123 kbd_getc, 124 kbd_pollc, 125 kbd_bell 126 }; 127 128 /* 129 * Pointer to keymaps. They are defined in wskbdmap_amiga.c. 130 */ 131 static struct wskbd_mapdata kbd_mapdata = { 132 amigakbd_keydesctab, 133 KB_US 134 }; 135 136 #endif /* WSKBD */ 137 138 139 #include <sys/conf.h> 140 #include <machine/conf.h> 141 142 struct kbd_softc { 143 int k_event_mode; /* if true, collect events, else pass to ite */ 144 struct evvar k_events; /* event queue state */ 145 #ifdef DRACO 146 u_char k_rlprfx; /* MF-II rel. prefix has been seen */ 147 u_char k_mf2; 148 #endif 149 150 #if NWSKBD>0 151 struct device *k_wskbddev; /* pointer to wskbd for sending strokes */ 152 int k_pollingmode; /* polling mode on? whatever it isss... */ 153 #endif 154 }; 155 struct kbd_softc kbd_softc; 156 157 int kbdmatch(struct device *, struct cfdata *, void *); 158 void kbdattach(struct device *, struct device *, void *); 159 void kbdintr(int); 160 void kbdstuffchar(u_char); 161 162 int drkbdgetc(void); 163 int drkbdrputc(u_int8_t); 164 int drkbdputc(u_int8_t); 165 int drkbdputc2(u_int8_t, u_int8_t); 166 int drkbdwaitfor(int); 167 168 struct cfattach kbd_ca = { 169 sizeof(struct device), kbdmatch, kbdattach 170 }; 171 172 /*ARGSUSED*/ 173 int 174 kbdmatch(struct device *pdp, struct cfdata *cfp, void *auxp) 175 { 176 177 if (matchname((char *)auxp, "kbd")) 178 return(1); 179 return(0); 180 } 181 182 /*ARGSUSED*/ 183 void 184 kbdattach(struct device *pdp, struct device *dp, void *auxp) 185 { 186 #ifdef DRACO 187 kbdenable(); 188 if (kbd_softc.k_mf2) 189 printf(": QuickLogic type MF-II\n"); 190 else 191 printf(": CIA A type Amiga\n"); 192 #else 193 printf(": CIA A type Amiga\n"); 194 #endif 195 196 #if NWSKBD>0 197 if (dp != NULL) { 198 /* 199 * Try to attach the wskbd. 200 */ 201 struct wskbddev_attach_args waa; 202 203 /* Maybe should be done before this?... */ 204 wskbd_cnattach(&kbd_consops, NULL, &kbd_mapdata); 205 206 waa.console = 1; 207 waa.keymap = &kbd_mapdata; 208 waa.accessops = &kbd_accessops; 209 waa.accesscookie = NULL; 210 kbd_softc.k_wskbddev = config_found(dp, &waa, wskbddevprint); 211 212 kbd_softc.k_pollingmode = 0; 213 } 214 kbdenable(); 215 #endif /* WSKBD */ 216 } 217 218 /* definitions for amiga keyboard encoding. */ 219 #define KEY_CODE(c) ((c) & 0x7f) 220 #define KEY_UP(c) ((c) & 0x80) 221 222 #define DATLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT) 223 #define DATHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDDATOUT) 224 225 #define CLKLO single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT) 226 #define CLKHI single_inst_bset_b(draco_ioct->io_control, DRCNTRL_KBDCLKOUT) 227 228 void 229 kbdenable(void) 230 { 231 static int kbd_inited = 0; 232 233 int s; 234 235 #ifdef DRACO 236 int id; 237 #endif 238 /* 239 * collides with external ints from SCSI, watch out for this when 240 * enabling/disabling interrupts there !! 241 */ 242 s = splhigh(); /* don't lower; might be called from early ddb */ 243 if (kbd_inited) { 244 splx(s); 245 return; 246 } 247 kbd_inited = 1; 248 #ifdef DRACO 249 if (is_draco()) { 250 251 CLKLO; 252 delay(5000); 253 draco_ioct->io_kbdrst = 0; 254 255 if (drkbdputc(0xf2)) 256 goto LnoMFII; 257 258 id = drkbdgetc() << 8; 259 id |= drkbdgetc(); 260 261 if (id != 0xab83) 262 goto LnoMFII; 263 264 if (drkbdputc2(0xf0, 3)) /* mode 3 */ 265 goto LnoMFII; 266 267 if (drkbdputc(0xf8)) /* make/break, no typematic */ 268 goto LnoMFII; 269 270 if (drkbdputc(0xf4)) /* enable */ 271 goto LnoMFII; 272 kbd_softc.k_mf2 = 1; 273 single_inst_bclr_b(draco_ioct->io_control, DRCNTRL_KBDINTENA); 274 275 ciaa.icr = CIA_ICR_SP; /* CIA SP interrupt disable */ 276 ciaa.cra &= ~(1<<6); /* serial line == input */ 277 splx(s); 278 return; 279 280 LnoMFII: 281 kbd_softc.k_mf2 = 0; 282 single_inst_bset_b(*draco_intena, DRIRQ_INT2); 283 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; 284 /* SP interrupt enable */ 285 ciaa.cra &= ~(1<<6); /* serial line == input */ 286 splx(s); 287 return; 288 289 } else { 290 #endif 291 custom.intena = INTF_SETCLR | INTF_PORTS; 292 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP; /* SP interrupt enable */ 293 ciaa.cra &= ~(1<<6); /* serial line == input */ 294 #ifdef DRACO 295 } 296 #endif 297 kbd_softc.k_event_mode = 0; 298 kbd_softc.k_events.ev_io = 0; 299 splx(s); 300 } 301 302 #ifdef DRACO 303 /* 304 * call this with kbd interupt blocked 305 */ 306 307 int 308 drkbdgetc(void) 309 { 310 u_int8_t in; 311 312 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0); 313 in = draco_ioct->io_kbddata; 314 draco_ioct->io_kbdrst = 0; 315 316 return in; 317 } 318 319 #define WAIT0 if (drkbdwaitfor(0)) goto Ltimeout 320 #define WAIT1 if (drkbdwaitfor(DRSTAT_KBDCLKIN)) goto Ltimeout 321 322 int 323 drkbdwaitfor(int bit) 324 { 325 int i; 326 327 328 329 i = 60000; /* about 50 ms max */ 330 331 do { 332 if ((draco_ioct->io_status & DRSTAT_KBDCLKIN) == bit) 333 return 0; 334 335 } while (--i >= 0); 336 337 return 1; 338 } 339 340 /* 341 * Output a raw byte to the keyboard (+ parity and stop bit). 342 * return 0 on success, 1 on timeout. 343 */ 344 int 345 drkbdrputc(u_int8_t c) 346 { 347 u_int8_t parity; 348 int bitcnt; 349 350 DATLO; CLKHI; WAIT1; 351 parity = 0; 352 353 for (bitcnt=7; bitcnt >= 0; bitcnt--) { 354 WAIT0; 355 if (c & 1) { 356 DATHI; 357 } else { 358 ++parity; 359 DATLO; 360 } 361 c >>= 1; 362 WAIT1; 363 } 364 WAIT0; 365 /* parity bit */ 366 if (parity & 1) { 367 DATLO; 368 } else { 369 DATHI; 370 } 371 WAIT1; 372 /* stop bit */ 373 WAIT0; DATHI; WAIT1; 374 375 WAIT0; /* XXX should check the ack bit here... */ 376 WAIT1; 377 draco_ioct->io_kbdrst = 0; 378 return 0; 379 380 Ltimeout: 381 DATHI; 382 draco_ioct->io_kbdrst = 0; 383 return 1; 384 } 385 386 /* 387 * Output one cooked byte to the keyboard, with wait for ACK or RESEND, 388 * and retry if necessary. 0 == success, 1 == timeout 389 */ 390 int 391 drkbdputc(u_int8_t c) 392 { 393 int rc; 394 395 do { 396 if (drkbdrputc(c)) 397 return(-1); 398 399 rc = drkbdgetc(); 400 } while (rc == 0xfe); 401 return (!(rc == 0xfa)); 402 } 403 404 /* 405 * same for twobyte sequence 406 */ 407 408 int 409 drkbdputc2(u_int8_t c1, u_int8_t c2) 410 { 411 int rc; 412 413 do { 414 do { 415 if (drkbdrputc(c1)) 416 return(-1); 417 418 rc = drkbdgetc(); 419 } while (rc == 0xfe); 420 if (rc != 0xfa) 421 return (-1); 422 423 if (drkbdrputc(c2)) 424 return(-1); 425 426 rc = drkbdgetc(); 427 } while (rc == 0xfe); 428 return (!(rc == 0xfa)); 429 } 430 #endif 431 432 int 433 kbdopen(dev_t dev, int flags, int mode, struct proc *p) 434 { 435 436 kbdenable(); 437 if (kbd_softc.k_events.ev_io) 438 return EBUSY; 439 440 kbd_softc.k_events.ev_io = p; 441 ev_init(&kbd_softc.k_events); 442 return (0); 443 } 444 445 int 446 kbdclose(dev_t dev, int flags, int mode, struct proc *p) 447 { 448 449 /* Turn off event mode, dump the queue */ 450 kbd_softc.k_event_mode = 0; 451 ev_fini(&kbd_softc.k_events); 452 kbd_softc.k_events.ev_io = NULL; 453 return (0); 454 } 455 456 int 457 kbdread(dev_t dev, struct uio *uio, int flags) 458 { 459 return ev_read (&kbd_softc.k_events, uio, flags); 460 } 461 462 int 463 kbdioctl(dev_t dev, u_long cmd, register caddr_t data, int flag, 464 struct proc *p) 465 { 466 register struct kbd_softc *k = &kbd_softc; 467 468 switch (cmd) { 469 case KIOCTRANS: 470 if (*(int *)data == TR_UNTRANS_EVENT) 471 return 0; 472 break; 473 474 case KIOCGTRANS: 475 /* Get translation mode */ 476 *(int *)data = TR_UNTRANS_EVENT; 477 return 0; 478 479 case KIOCSDIRECT: 480 k->k_event_mode = *(int *)data; 481 return 0; 482 483 case FIONBIO: /* we will remove this someday (soon???) */ 484 return 0; 485 486 case FIOASYNC: 487 k->k_events.ev_async = *(int *)data != 0; 488 return 0; 489 490 case TIOCSPGRP: 491 if (*(int *)data != k->k_events.ev_io->p_pgid) 492 return EPERM; 493 return 0; 494 495 default: 496 return ENOTTY; 497 } 498 499 /* We identified the ioctl, but we do not handle it. */ 500 return EOPNOTSUPP; /* misuse, but what the heck */ 501 } 502 503 int 504 kbdpoll(dev_t dev, int events, struct proc *p) 505 { 506 return ev_poll (&kbd_softc.k_events, events, p); 507 } 508 509 510 void 511 kbdintr(int mask) 512 { 513 u_char c; 514 #ifdef KBDRESET 515 static int reset_warn; 516 #endif 517 518 /* 519 * now only invoked from generic CIA interrupt handler if there *is* 520 * a keyboard interrupt pending 521 */ 522 523 c = ~ciaa.sdr; /* keyboard data is inverted */ 524 /* ack */ 525 ciaa.cra |= (1 << 6); /* serial line output */ 526 #ifdef KBDRESET 527 if (reset_warn && c == 0xf0) { 528 #ifdef DEBUG 529 printf ("kbdintr: !!!! Reset Warning !!!!\n"); 530 #endif 531 bootsync(); 532 reset_warn = 0; 533 DELAY(30000000); 534 } 535 #endif 536 /* wait 200 microseconds (for bloody Cherry keyboards..) */ 537 DELAY(2000); /* fudge delay a bit for some keyboards */ 538 ciaa.cra &= ~(1 << 6); 539 540 /* process the character */ 541 c = (c >> 1) | (c << 7); /* rotate right once */ 542 543 #ifdef KBDRESET 544 if (c == 0x78) { 545 #ifdef DEBUG 546 printf ("kbdintr: Reset Warning started\n"); 547 #endif 548 ++reset_warn; 549 return; 550 } 551 #endif 552 kbdstuffchar(c); 553 } 554 555 #ifdef DRACO 556 /* maps MF-II keycodes to Amiga keycodes */ 557 558 const u_char drkbdtab[] = { 559 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 560 0x45, 0xff, 0xff, 0xff, 0xff, 0x42, 0x00, 0x51, 561 562 0xff, 0x64, 0x60, 0x30, 0x63, 0x10, 0x01, 0x52, 563 0xff, 0x66, 0x31, 0x21, 0x20, 0x11, 0x02, 0x53, 564 565 0xff, 0x33, 0x32, 0x22, 0x12, 0x04, 0x03, 0x54, 566 0xff, 0x40, 0x34, 0x23, 0x14, 0x13, 0x05, 0x55, 567 568 0xff, 0x36, 0x35, 0x25, 0x24, 0x15, 0x06, 0x56, 569 0xff, 0x67, 0x37, 0x26, 0x16, 0x07, 0x08, 0x57, 570 /* --- */ 571 0xff, 0x38, 0x27, 0x17, 0x18, 0x0a, 0x09, 0x58, 572 0xff, 0x39, 0x3a, 0x28, 0x29, 0x19, 0x0b, 0x59, 573 574 0xff, 0xff, 0x2a, 0x2b, 0x1a, 0x0c, 0x4b, 0xff, 575 0x65, 0x61, 0x44, 0x1b, 0xff, 0xff, 0x6f, 0xff, 576 577 0x4d, 0x4f, 0xff, 0x4c, 0x0d, 0xff, 0x41, 0x46, 578 0xff, 0x1d, 0x4e, 0x2d, 0x3d, 0x4a, 0x5f, 0x62, 579 580 0x0f, 0x3c, 0x1e, 0x2e, 0x2f, 0x3e, 0x5a, 0x5b, 581 0xff, 0x43, 0x1f, 0xff, 0x5e, 0x3f, 0x5c, 0xff, 582 /* --- */ 583 0xff, 0xff, 0xff, 0xff, 0x5d 584 }; 585 #endif 586 587 588 int 589 kbdgetcn(void) 590 { 591 int s; 592 u_char ints, mask, c, in; 593 594 #ifdef DRACO 595 if (is_draco() && kbd_softc.k_mf2) { 596 do { 597 c = 0; 598 s = spltty (); 599 while ((draco_ioct->io_status & DRSTAT_KBDRECV) == 0); 600 in = draco_ioct->io_kbddata; 601 draco_ioct->io_kbdrst = 0; 602 if (in == 0xF0) { /* release prefix */ 603 c = 0x80; 604 while ((draco_ioct->io_status & 605 DRSTAT_KBDRECV) == 0); 606 in = draco_ioct->io_kbddata; 607 draco_ioct->io_kbdrst = 0; 608 } 609 splx(s); 610 #ifdef DRACORAWKEYDEBUG 611 printf("<%02x>", in); 612 #endif 613 c |= in>=sizeof(drkbdtab) ? 0xff : drkbdtab[in]; 614 } while (c == 0xff); 615 return (c); 616 } 617 #endif 618 s = spltty(); 619 for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP); 620 ints |= mask) ; 621 622 in = ciaa.sdr; 623 c = ~in; 624 625 /* ack */ 626 ciaa.cra |= (1 << 6); /* serial line output */ 627 ciaa.sdr = 0xff; /* ack */ 628 /* wait 200 microseconds */ 629 DELAY(2000); /* XXXX only works as long as DELAY doesn't 630 * use a timer and waits.. */ 631 ciaa.cra &= ~(1 << 6); 632 ciaa.sdr = in; 633 634 splx (s); 635 c = (c >> 1) | (c << 7); 636 637 /* take care that no CIA-interrupts are lost */ 638 if (ints) 639 dispatch_cia_ints (0, ints); 640 641 return c; 642 } 643 644 void 645 kbdstuffchar(u_char c) 646 { 647 struct firm_event *fe; 648 struct kbd_softc *k = &kbd_softc; 649 int put; 650 651 #if NWSKBD>0 652 /* 653 * If we have attached a wskbd and not in polling mode and 654 * nobody has opened us directly, then send the keystroke 655 * to the wskbd. 656 */ 657 658 if (kbd_softc.k_pollingmode == 0 659 && kbd_softc.k_wskbddev != NULL 660 && k->k_event_mode == 0) { 661 wskbd_input(kbd_softc.k_wskbddev, 662 KEY_UP(c) ? 663 WSCONS_EVENT_KEY_UP : 664 WSCONS_EVENT_KEY_DOWN, 665 KEY_CODE(c)); 666 return; 667 } 668 669 #endif /* NWSKBD */ 670 671 /* 672 * If not in event mode, deliver straight to ite to process 673 * key stroke 674 */ 675 676 if (! k->k_event_mode) { 677 #if NITE>0 678 ite_filter (c, ITEFILT_TTY); 679 #endif 680 return; 681 } 682 683 /* 684 * Keyboard is generating events. Turn this keystroke into an 685 * event and put it in the queue. If the queue is full, the 686 * keystroke is lost (sorry!). 687 */ 688 689 put = k->k_events.ev_put; 690 fe = &k->k_events.ev_q[put]; 691 put = (put + 1) % EV_QSIZE; 692 if (put == k->k_events.ev_get) { 693 log(LOG_WARNING, "keyboard event queue overflow\n"); 694 /* ??? */ 695 return; 696 } 697 fe->id = KEY_CODE(c); 698 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN; 699 fe->time = time; 700 k->k_events.ev_put = put; 701 EV_WAKEUP(&k->k_events); 702 } 703 704 705 #ifdef DRACO 706 void 707 drkbdintr(void) 708 { 709 u_char in; 710 struct kbd_softc *k = &kbd_softc; 711 712 in = draco_ioct->io_kbddata; 713 draco_ioct->io_kbdrst = 0; 714 715 if (in == 0xF0) 716 k->k_rlprfx = 0x80; 717 else { 718 kbdstuffchar(in>=sizeof(drkbdtab) ? 0xff : 719 drkbdtab[in] | k->k_rlprfx); 720 k->k_rlprfx = 0; 721 } 722 } 723 724 #endif 725 726 727 #if NWSKBD>0 728 /* 729 * These are the callback functions that are passed to wscons. 730 * They really don't do anything worth noting, just call the 731 * other functions above. 732 */ 733 734 int 735 kbd_enable(void *c, int on) 736 { 737 /* Wonder what this is supposed to do... */ 738 return (0); 739 } 740 741 void 742 kbd_set_leds(void *c, int leds) 743 { 744 } 745 746 int 747 kbd_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc *p) 748 { 749 switch (cmd) 750 { 751 case WSKBDIO_COMPLEXBELL: 752 return 0; 753 case WSKBDIO_SETLEDS: 754 return 0; 755 case WSKBDIO_GETLEDS: 756 *(int*)data = 0; 757 return 0; 758 case WSKBDIO_GTYPE: 759 *(u_int*)data = WSKBD_TYPE_AMIGA; 760 return 0; 761 } 762 763 /* We are supposed to return -1 to wscons if we didn't understand */ 764 return (-1); 765 } 766 767 void 768 kbd_getc(void *c, u_int *type, int *data) 769 { 770 int key; 771 772 key = kbdgetcn(); 773 774 *data = KEY_CODE(key); 775 *type = KEY_UP(key) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 776 } 777 778 void 779 kbd_pollc(void *c, int on) 780 { 781 kbd_softc.k_pollingmode = on; 782 } 783 784 void 785 kbd_bell(void *c, u_int x, u_int y, u_int z) 786 { 787 } 788 #endif /* WSKBD */ 789