1 /* $NetBSD: ukbd.c,v 1.74 2001/11/28 05:45:28 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net) at 9 * Carlstedt Research & Technology. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * HID spec: http://www.usb.org/developers/data/devclass/hid1_1.pdf 42 */ 43 44 #include <sys/cdefs.h> 45 __KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.74 2001/11/28 05:45:28 lukem Exp $"); 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/callout.h> 50 #include <sys/kernel.h> 51 #include <sys/device.h> 52 #include <sys/ioctl.h> 53 #include <sys/tty.h> 54 #include <sys/file.h> 55 #include <sys/select.h> 56 #include <sys/proc.h> 57 #include <sys/vnode.h> 58 #include <sys/poll.h> 59 60 #include <dev/usb/usb.h> 61 #include <dev/usb/usbhid.h> 62 63 #include <dev/usb/usbdi.h> 64 #include <dev/usb/usbdi_util.h> 65 #include <dev/usb/usbdevs.h> 66 #include <dev/usb/usb_quirks.h> 67 #include <dev/usb/hid.h> 68 #include <dev/usb/ukbdvar.h> 69 70 #include <dev/wscons/wsconsio.h> 71 #include <dev/wscons/wskbdvar.h> 72 #include <dev/wscons/wsksymdef.h> 73 #include <dev/wscons/wsksymvar.h> 74 75 #include "opt_wsdisplay_compat.h" 76 #include "opt_ddb.h" 77 78 #ifdef UKBD_DEBUG 79 #define DPRINTF(x) if (ukbddebug) logprintf x 80 #define DPRINTFN(n,x) if (ukbddebug>(n)) logprintf x 81 int ukbddebug = 0; 82 #else 83 #define DPRINTF(x) 84 #define DPRINTFN(n,x) 85 #endif 86 87 #define NKEYCODE 6 88 89 #define NUM_LOCK 0x01 90 #define CAPS_LOCK 0x02 91 #define SCROLL_LOCK 0x04 92 93 struct ukbd_data { 94 u_int8_t modifiers; 95 #define MOD_CONTROL_L 0x01 96 #define MOD_CONTROL_R 0x10 97 #define MOD_SHIFT_L 0x02 98 #define MOD_SHIFT_R 0x20 99 #define MOD_ALT_L 0x04 100 #define MOD_ALT_R 0x40 101 #define MOD_WIN_L 0x08 102 #define MOD_WIN_R 0x80 103 u_int8_t reserved; 104 u_int8_t keycode[NKEYCODE]; 105 }; 106 107 #define PRESS 0x000 108 #define RELEASE 0x100 109 #define CODEMASK 0x0ff 110 111 /* Translate USB bitmap to USB keycode. */ 112 #define NMOD 8 113 Static const struct { 114 int mask, key; 115 } ukbd_mods[NMOD] = { 116 { MOD_CONTROL_L, 224 }, 117 { MOD_CONTROL_R, 228 }, 118 { MOD_SHIFT_L, 225 }, 119 { MOD_SHIFT_R, 229 }, 120 { MOD_ALT_L, 226 }, 121 { MOD_ALT_R, 230 }, 122 { MOD_WIN_L, 227 }, 123 { MOD_WIN_R, 231 }, 124 }; 125 126 #if defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) 127 #define NN 0 /* no translation */ 128 /* 129 * Translate USB keycodes to US keyboard XT scancodes. 130 * Scancodes >= 128 represent EXTENDED keycodes. 131 */ 132 Static const u_int8_t ukbd_trtab[256] = { 133 NN, NN, NN, NN, 30, 48, 46, 32, /* 00 - 07 */ 134 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */ 135 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */ 136 22, 47, 17, 45, 21, 44, 2, 3, /* 18 - 1F */ 137 4, 5, 6, 7, 8, 9, 10, 11, /* 20 - 27 */ 138 28, 1, 14, 15, 57, 12, 13, 26, /* 28 - 2F */ 139 27, 43, 43, 39, 40, 41, 51, 52, /* 30 - 37 */ 140 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */ 141 65, 66, 67, 68, 87, 88, 170, 70, /* 40 - 47 */ 142 127, 210, 199, 201, 211, 207, 209, 205, /* 48 - 4F */ 143 203, 208, 200, 69, 181, 55, 74, 78, /* 50 - 57 */ 144 156, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */ 145 72, 73, 82, 83, 86, 221, NN, NN, /* 60 - 67 */ 146 NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */ 147 NN, NN, NN, NN, NN, NN, NN, NN, /* 70 - 77 */ 148 NN, NN, NN, NN, NN, NN, NN, NN, /* 78 - 7F */ 149 NN, NN, NN, NN, NN, NN, NN, NN, /* 80 - 87 */ 150 NN, NN, NN, NN, NN, NN, NN, NN, /* 88 - 8F */ 151 NN, NN, NN, NN, NN, NN, NN, NN, /* 90 - 97 */ 152 NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9F */ 153 NN, NN, NN, NN, NN, NN, NN, NN, /* A0 - A7 */ 154 NN, NN, NN, NN, NN, NN, NN, NN, /* A8 - AF */ 155 NN, NN, NN, NN, NN, NN, NN, NN, /* B0 - B7 */ 156 NN, NN, NN, NN, NN, NN, NN, NN, /* B8 - BF */ 157 NN, NN, NN, NN, NN, NN, NN, NN, /* C0 - C7 */ 158 NN, NN, NN, NN, NN, NN, NN, NN, /* C8 - CF */ 159 NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ 160 NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ 161 29, 42, 56, 219, 157, 54, 184,220, /* E0 - E7 */ 162 NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ 163 NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ 164 NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ 165 }; 166 #endif /* defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) */ 167 168 #define KEY_ERROR 0x01 169 170 #define MAXKEYS (NMOD+2*NKEYCODE) 171 172 struct ukbd_softc { 173 USBBASEDEVICE sc_dev; /* base device */ 174 usbd_device_handle sc_udev; 175 usbd_interface_handle sc_iface; /* interface */ 176 usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ 177 int sc_ep_addr; 178 179 struct ukbd_data sc_ndata; 180 struct ukbd_data sc_odata; 181 182 char sc_enabled; 183 184 int sc_console_keyboard; /* we are the console keyboard */ 185 186 char sc_debounce; /* for quirk handling */ 187 usb_callout_t sc_delay; /* for quirk handling */ 188 struct ukbd_data sc_data; /* for quirk handling */ 189 190 int sc_leds; 191 #if defined(__NetBSD__) 192 usb_callout_t sc_rawrepeat_ch; 193 194 struct device *sc_wskbddev; 195 #if defined(WSDISPLAY_COMPAT_RAWKBD) 196 #define REP_DELAY1 400 197 #define REP_DELAYN 100 198 int sc_rawkbd; 199 int sc_nrep; 200 char sc_rep[MAXKEYS]; 201 #endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */ 202 203 int sc_polling; 204 int sc_npollchar; 205 u_int16_t sc_pollchars[MAXKEYS]; 206 #endif /* defined(__NetBSD__) */ 207 208 u_char sc_dying; 209 }; 210 211 #ifdef UKBD_DEBUG 212 #define UKBDTRACESIZE 64 213 struct ukbdtraceinfo { 214 int unit; 215 struct timeval tv; 216 struct ukbd_data ud; 217 }; 218 struct ukbdtraceinfo ukbdtracedata[UKBDTRACESIZE]; 219 int ukbdtraceindex = 0; 220 int ukbdtrace = 0; 221 void ukbdtracedump(void); 222 void 223 ukbdtracedump(void) 224 { 225 int i; 226 for (i = 0; i < UKBDTRACESIZE; i++) { 227 struct ukbdtraceinfo *p = 228 &ukbdtracedata[(i+ukbdtraceindex)%UKBDTRACESIZE]; 229 printf("%lu.%06lu: mod=0x%02x key0=0x%02x key1=0x%02x " 230 "key2=0x%02x key3=0x%02x\n", 231 p->tv.tv_sec, p->tv.tv_usec, 232 p->ud.modifiers, p->ud.keycode[0], p->ud.keycode[1], 233 p->ud.keycode[2], p->ud.keycode[3]); 234 } 235 } 236 #endif 237 238 #define UKBDUNIT(dev) (minor(dev)) 239 #define UKBD_CHUNK 128 /* chunk size for read */ 240 #define UKBD_BSIZE 1020 /* buffer size */ 241 242 Static int ukbd_is_console; 243 244 Static void ukbd_cngetc(void *, u_int *, int *); 245 Static void ukbd_cnpollc(void *, int); 246 247 #if defined(__NetBSD__) 248 const struct wskbd_consops ukbd_consops = { 249 ukbd_cngetc, 250 ukbd_cnpollc, 251 }; 252 #endif 253 254 Static void ukbd_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); 255 Static void ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud); 256 Static void ukbd_delayed_decode(void *addr); 257 258 Static int ukbd_enable(void *, int); 259 Static void ukbd_set_leds(void *, int); 260 261 #if defined(__NetBSD__) 262 Static int ukbd_ioctl(void *, u_long, caddr_t, int, struct proc *); 263 #ifdef WSDISPLAY_COMPAT_RAWKBD 264 Static void ukbd_rawrepeat(void *v); 265 #endif 266 267 const struct wskbd_accessops ukbd_accessops = { 268 ukbd_enable, 269 ukbd_set_leds, 270 ukbd_ioctl, 271 }; 272 273 extern const struct wscons_keydesc ukbd_keydesctab[]; 274 275 const struct wskbd_mapdata ukbd_keymapdata = { 276 ukbd_keydesctab, 277 #ifdef UKBD_LAYOUT 278 UKBD_LAYOUT, 279 #else 280 KB_US, 281 #endif 282 }; 283 #endif 284 285 USB_DECLARE_DRIVER(ukbd); 286 287 USB_MATCH(ukbd) 288 { 289 USB_MATCH_START(ukbd, uaa); 290 usb_interface_descriptor_t *id; 291 292 /* Check that this is a keyboard that speaks the boot protocol. */ 293 if (uaa->iface == NULL) 294 return (UMATCH_NONE); 295 id = usbd_get_interface_descriptor(uaa->iface); 296 if (id == NULL || 297 id->bInterfaceClass != UICLASS_HID || 298 id->bInterfaceSubClass != UISUBCLASS_BOOT || 299 id->bInterfaceProtocol != UIPROTO_BOOT_KEYBOARD) 300 return (UMATCH_NONE); 301 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); 302 } 303 304 USB_ATTACH(ukbd) 305 { 306 USB_ATTACH_START(ukbd, sc, uaa); 307 usbd_interface_handle iface = uaa->iface; 308 usb_interface_descriptor_t *id; 309 usb_endpoint_descriptor_t *ed; 310 usbd_status err; 311 u_int32_t qflags; 312 char devinfo[1024]; 313 #if defined(__NetBSD__) 314 struct wskbddev_attach_args a; 315 #else 316 int i; 317 #endif 318 319 sc->sc_udev = uaa->device; 320 sc->sc_iface = iface; 321 id = usbd_get_interface_descriptor(iface); 322 usbd_devinfo(uaa->device, 0, devinfo); 323 USB_ATTACH_SETUP; 324 printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), 325 devinfo, id->bInterfaceClass, id->bInterfaceSubClass); 326 327 ed = usbd_interface2endpoint_descriptor(iface, 0); 328 if (ed == NULL) { 329 printf("%s: could not read endpoint descriptor\n", 330 USBDEVNAME(sc->sc_dev)); 331 USB_ATTACH_ERROR_RETURN; 332 } 333 334 DPRINTFN(10,("ukbd_attach: bLength=%d bDescriptorType=%d " 335 "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" 336 " bInterval=%d\n", 337 ed->bLength, ed->bDescriptorType, 338 ed->bEndpointAddress & UE_ADDR, 339 UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", 340 ed->bmAttributes & UE_XFERTYPE, 341 UGETW(ed->wMaxPacketSize), ed->bInterval)); 342 343 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || 344 (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { 345 printf("%s: unexpected endpoint\n", 346 USBDEVNAME(sc->sc_dev)); 347 USB_ATTACH_ERROR_RETURN; 348 } 349 350 qflags = usbd_get_quirks(uaa->device)->uq_flags; 351 if ((qflags & UQ_NO_SET_PROTO) == 0) { 352 err = usbd_set_protocol(iface, 0); 353 DPRINTFN(5, ("ukbd_attach: protocol set\n")); 354 if (err) { 355 printf("%s: set protocol failed\n", 356 USBDEVNAME(sc->sc_dev)); 357 USB_ATTACH_ERROR_RETURN; 358 } 359 } 360 sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0; 361 362 /* Ignore if SETIDLE fails since it is not crucial. */ 363 (void)usbd_set_idle(iface, 0, 0); 364 365 sc->sc_ep_addr = ed->bEndpointAddress; 366 367 /* 368 * Remember if we're the console keyboard. 369 * 370 * XXX This always picks the first keyboard on the 371 * first USB bus, but what else can we really do? 372 */ 373 if ((sc->sc_console_keyboard = ukbd_is_console) != 0) { 374 /* Don't let any other keyboard have it. */ 375 ukbd_is_console = 0; 376 } 377 378 if (sc->sc_console_keyboard) { 379 DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc)); 380 wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata); 381 ukbd_enable(sc, 1); 382 } 383 384 a.console = sc->sc_console_keyboard; 385 386 a.keymap = &ukbd_keymapdata; 387 388 a.accessops = &ukbd_accessops; 389 a.accesscookie = sc; 390 391 usb_callout_init(sc->sc_rawrepeat_ch); 392 393 usb_callout_init(sc->sc_delay); 394 395 /* Flash the leds; no real purpose, just shows we're alive. */ 396 ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS); 397 usbd_delay_ms(uaa->device, 400); 398 ukbd_set_leds(sc, 0); 399 400 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 401 USBDEV(sc->sc_dev)); 402 403 sc->sc_wskbddev = config_found(self, &a, wskbddevprint); 404 405 USB_ATTACH_SUCCESS_RETURN; 406 } 407 408 int 409 ukbd_enable(void *v, int on) 410 { 411 struct ukbd_softc *sc = v; 412 usbd_status err; 413 414 if (on && sc->sc_dying) 415 return (EIO); 416 417 /* Should only be called to change state */ 418 if (sc->sc_enabled == on) { 419 #ifdef DIAGNOSTIC 420 printf("ukbd_enable: %s: bad call on=%d\n", 421 USBDEVNAME(sc->sc_dev), on); 422 #endif 423 return (EBUSY); 424 } 425 426 DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on)); 427 if (on) { 428 /* Set up interrupt pipe. */ 429 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, 430 USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, 431 &sc->sc_ndata, sizeof(sc->sc_ndata), ukbd_intr, 432 USBD_DEFAULT_INTERVAL); 433 if (err) 434 return (EIO); 435 } else { 436 /* Disable interrupts. */ 437 usbd_abort_pipe(sc->sc_intrpipe); 438 usbd_close_pipe(sc->sc_intrpipe); 439 sc->sc_intrpipe = NULL; 440 } 441 sc->sc_enabled = on; 442 443 return (0); 444 } 445 446 int 447 ukbd_activate(device_ptr_t self, enum devact act) 448 { 449 struct ukbd_softc *sc = (struct ukbd_softc *)self; 450 int rv = 0; 451 452 switch (act) { 453 case DVACT_ACTIVATE: 454 return (EOPNOTSUPP); 455 break; 456 457 case DVACT_DEACTIVATE: 458 if (sc->sc_wskbddev != NULL) 459 rv = config_deactivate(sc->sc_wskbddev); 460 sc->sc_dying = 1; 461 break; 462 } 463 return (rv); 464 } 465 466 USB_DETACH(ukbd) 467 { 468 USB_DETACH_START(ukbd, sc); 469 int rv = 0; 470 471 DPRINTF(("ukbd_detach: sc=%p flags=%d\n", sc, flags)); 472 473 if (sc->sc_console_keyboard) { 474 #if 0 475 /* 476 * XXX Should probably disconnect our consops, 477 * XXX and either notify some other keyboard that 478 * XXX it can now be the console, or if there aren't 479 * XXX any more USB keyboards, set ukbd_is_console 480 * XXX back to 1 so that the next USB keyboard attached 481 * XXX to the system will get it. 482 */ 483 panic("ukbd_detach: console keyboard"); 484 #else 485 /* 486 * Disconnect our consops and set ukbd_is_console 487 * back to 1 so that the next USB keyboard attached 488 * to the system will get it. 489 * XXX Should notify some other keyboard that it can be 490 * XXX console, if there are any other keyboards. 491 */ 492 printf("%s: was console keyboard\n", USBDEVNAME(sc->sc_dev)); 493 wskbd_cndetach(); 494 ukbd_is_console = 1; 495 #endif 496 } 497 /* No need to do reference counting of ukbd, wskbd has all the goo. */ 498 if (sc->sc_wskbddev != NULL) 499 rv = config_detach(sc->sc_wskbddev, flags); 500 501 /* The console keyboard does not get a disable call, so check pipe. */ 502 if (sc->sc_intrpipe != NULL) { 503 usbd_abort_pipe(sc->sc_intrpipe); 504 usbd_close_pipe(sc->sc_intrpipe); 505 sc->sc_intrpipe = NULL; 506 } 507 508 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 509 USBDEV(sc->sc_dev)); 510 511 return (rv); 512 } 513 514 void 515 ukbd_intr(xfer, addr, status) 516 usbd_xfer_handle xfer; 517 usbd_private_handle addr; 518 usbd_status status; 519 { 520 struct ukbd_softc *sc = addr; 521 struct ukbd_data *ud = &sc->sc_ndata; 522 523 DPRINTFN(5, ("ukbd_intr: status=%d\n", status)); 524 if (status == USBD_CANCELLED) 525 return; 526 527 if (status) { 528 DPRINTF(("ukbd_intr: status=%d\n", status)); 529 if (status == USBD_STALLED) 530 usbd_clear_endpoint_stall_async(sc->sc_intrpipe); 531 return; 532 } 533 534 if (sc->sc_debounce && !sc->sc_polling) { 535 /* 536 * Some keyboards have a peculiar quirk. They sometimes 537 * generate a key up followed by a key down for the same 538 * key after about 10 ms. 539 * We avoid this bug by holding off decoding for 20 ms. 540 */ 541 sc->sc_data = *ud; 542 usb_callout(sc->sc_delay, hz / 50, ukbd_delayed_decode, sc); 543 #ifdef DDB 544 } else if (sc->sc_console_keyboard && !sc->sc_polling) { 545 /* 546 * For the console keyboard we can't deliver CTL-ALT-ESC 547 * from the interrupt routine. Doing so would start 548 * polling from inside the interrupt routine and that 549 * loses bigtime. 550 */ 551 sc->sc_data = *ud; 552 usb_callout(sc->sc_delay, 1, ukbd_delayed_decode, sc); 553 #endif 554 } else { 555 ukbd_decode(sc, ud); 556 } 557 } 558 559 void 560 ukbd_delayed_decode(void *addr) 561 { 562 struct ukbd_softc *sc = addr; 563 564 ukbd_decode(sc, &sc->sc_data); 565 } 566 567 void 568 ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud) 569 { 570 int mod, omod; 571 u_int16_t ibuf[MAXKEYS]; /* chars events */ 572 int s; 573 int nkeys, i, j; 574 int key; 575 #define ADDKEY(c) ibuf[nkeys++] = (c) 576 577 #ifdef UKBD_DEBUG 578 /* 579 * Keep a trace of the last events. Using printf changes the 580 * timing, so this can be useful sometimes. 581 */ 582 if (ukbdtrace) { 583 struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex]; 584 p->unit = sc->sc_dev.dv_unit; 585 microtime(&p->tv); 586 p->ud = *ud; 587 if (++ukbdtraceindex >= UKBDTRACESIZE) 588 ukbdtraceindex = 0; 589 } 590 if (ukbddebug > 5) { 591 struct timeval tv; 592 microtime(&tv); 593 DPRINTF((" at %lu.%06lu mod=0x%02x key0=0x%02x key1=0x%02x " 594 "key2=0x%02x key3=0x%02x\n", 595 tv.tv_sec, tv.tv_usec, 596 ud->modifiers, ud->keycode[0], ud->keycode[1], 597 ud->keycode[2], ud->keycode[3])); 598 } 599 #endif 600 601 if (ud->keycode[0] == KEY_ERROR) { 602 DPRINTF(("ukbd_intr: KEY_ERROR\n")); 603 return; /* ignore */ 604 } 605 nkeys = 0; 606 mod = ud->modifiers; 607 omod = sc->sc_odata.modifiers; 608 if (mod != omod) 609 for (i = 0; i < NMOD; i++) 610 if (( mod & ukbd_mods[i].mask) != 611 (omod & ukbd_mods[i].mask)) 612 ADDKEY(ukbd_mods[i].key | 613 (mod & ukbd_mods[i].mask 614 ? PRESS : RELEASE)); 615 if (memcmp(ud->keycode, sc->sc_odata.keycode, NKEYCODE) != 0) { 616 /* Check for released keys. */ 617 for (i = 0; i < NKEYCODE; i++) { 618 key = sc->sc_odata.keycode[i]; 619 if (key == 0) 620 continue; 621 for (j = 0; j < NKEYCODE; j++) 622 if (key == ud->keycode[j]) 623 goto rfound; 624 DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key)); 625 ADDKEY(key | RELEASE); 626 rfound: 627 ; 628 } 629 630 /* Check for pressed keys. */ 631 for (i = 0; i < NKEYCODE; i++) { 632 key = ud->keycode[i]; 633 if (key == 0) 634 continue; 635 for (j = 0; j < NKEYCODE; j++) 636 if (key == sc->sc_odata.keycode[j]) 637 goto pfound; 638 DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key)); 639 ADDKEY(key | PRESS); 640 pfound: 641 ; 642 } 643 } 644 sc->sc_odata = *ud; 645 646 if (nkeys == 0) 647 return; 648 649 if (sc->sc_polling) { 650 DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0])); 651 memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t)); 652 sc->sc_npollchar = nkeys; 653 return; 654 } 655 #ifdef WSDISPLAY_COMPAT_RAWKBD 656 if (sc->sc_rawkbd) { 657 char cbuf[MAXKEYS * 2]; 658 int c; 659 int npress; 660 661 for (npress = i = j = 0; i < nkeys; i++) { 662 key = ibuf[i]; 663 c = ukbd_trtab[key & CODEMASK]; 664 if (c == NN) 665 continue; 666 if (c & 0x80) 667 cbuf[j++] = 0xe0; 668 cbuf[j] = c & 0x7f; 669 if (key & RELEASE) 670 cbuf[j] |= 0x80; 671 else { 672 /* remember pressed keys for autorepeat */ 673 if (c & 0x80) 674 sc->sc_rep[npress++] = 0xe0; 675 sc->sc_rep[npress++] = c & 0x7f; 676 } 677 DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n", 678 c & 0x80 ? "0xe0 " : "", 679 cbuf[j])); 680 j++; 681 } 682 s = spltty(); 683 wskbd_rawinput(sc->sc_wskbddev, cbuf, j); 684 splx(s); 685 usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc); 686 if (npress != 0) { 687 sc->sc_nrep = npress; 688 usb_callout(sc->sc_rawrepeat_ch, 689 hz * REP_DELAY1 / 1000, ukbd_rawrepeat, sc); 690 } 691 return; 692 } 693 #endif 694 695 s = spltty(); 696 for (i = 0; i < nkeys; i++) { 697 key = ibuf[i]; 698 wskbd_input(sc->sc_wskbddev, 699 key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN, 700 key&CODEMASK); 701 } 702 splx(s); 703 } 704 705 void 706 ukbd_set_leds(void *v, int leds) 707 { 708 struct ukbd_softc *sc = v; 709 u_int8_t res; 710 711 DPRINTF(("ukbd_set_leds: sc=%p leds=%d, sc_leds=%d\n", 712 sc, leds, sc->sc_leds)); 713 714 if (sc->sc_dying) 715 return; 716 717 if (sc->sc_leds == leds) 718 return; 719 sc->sc_leds = leds; 720 res = 0; 721 if (leds & WSKBD_LED_SCROLL) 722 res |= SCROLL_LOCK; 723 if (leds & WSKBD_LED_NUM) 724 res |= NUM_LOCK; 725 if (leds & WSKBD_LED_CAPS) 726 res |= CAPS_LOCK; 727 res |= leds & 0xf8; 728 usbd_set_report_async(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1); 729 } 730 731 #ifdef WSDISPLAY_COMPAT_RAWKBD 732 void 733 ukbd_rawrepeat(void *v) 734 { 735 struct ukbd_softc *sc = v; 736 int s; 737 738 s = spltty(); 739 wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep); 740 splx(s); 741 usb_callout(sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000, 742 ukbd_rawrepeat, sc); 743 } 744 #endif 745 746 int 747 ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 748 { 749 struct ukbd_softc *sc = v; 750 751 switch (cmd) { 752 case WSKBDIO_GTYPE: 753 *(int *)data = WSKBD_TYPE_USB; 754 return (0); 755 case WSKBDIO_SETLEDS: 756 ukbd_set_leds(v, *(int *)data); 757 return (0); 758 case WSKBDIO_GETLEDS: 759 *(int *)data = sc->sc_leds; 760 return (0); 761 #ifdef WSDISPLAY_COMPAT_RAWKBD 762 case WSKBDIO_SETMODE: 763 DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data)); 764 sc->sc_rawkbd = *(int *)data == WSKBD_RAW; 765 usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc); 766 return (0); 767 #endif 768 } 769 return (-1); 770 } 771 772 /* 773 * This is a hack to work around some broken ports that don't call 774 * cnpollc() before cngetc(). 775 */ 776 static int pollenter, warned; 777 778 /* Console interface. */ 779 void 780 ukbd_cngetc(void *v, u_int *type, int *data) 781 { 782 struct ukbd_softc *sc = v; 783 int s; 784 int c; 785 int broken; 786 787 if (pollenter == 0) { 788 if (!warned) { 789 printf("\n" 790 "This port is broken, it does not call cnpollc() before calling cngetc().\n" 791 "This should be fixed, but it will work anyway (for now).\n"); 792 warned = 1; 793 } 794 broken = 1; 795 ukbd_cnpollc(v, 1); 796 } else 797 broken = 0; 798 799 DPRINTFN(0,("ukbd_cngetc: enter\n")); 800 s = splusb(); 801 sc->sc_polling = 1; 802 while(sc->sc_npollchar <= 0) 803 usbd_dopoll(sc->sc_iface); 804 sc->sc_polling = 0; 805 c = sc->sc_pollchars[0]; 806 sc->sc_npollchar--; 807 memcpy(sc->sc_pollchars, sc->sc_pollchars+1, 808 sc->sc_npollchar * sizeof(u_int16_t)); 809 *type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 810 *data = c & CODEMASK; 811 splx(s); 812 DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", c)); 813 if (broken) 814 ukbd_cnpollc(v, 0); 815 } 816 817 void 818 ukbd_cnpollc(void *v, int on) 819 { 820 struct ukbd_softc *sc = v; 821 usbd_device_handle dev; 822 823 DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on)); 824 825 usbd_interface2device_handle(sc->sc_iface,&dev); 826 if (on) pollenter++; else pollenter--; 827 usbd_set_polling(dev, on); 828 } 829 830 int 831 ukbd_cnattach(void) 832 { 833 834 /* 835 * XXX USB requires too many parts of the kernel to be running 836 * XXX in order to work, so we can't do much for the console 837 * XXX keyboard until autconfiguration has run its course. 838 */ 839 ukbd_is_console = 1; 840 return (0); 841 } 842