ukbd.c revision 1.39
1/* $NetBSD: ukbd.c,v 1.39 1999/08/14 14:49:32 augustss 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 (augustss@carlstedt.se) 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/usbhid10.pdf 42 */ 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/device.h> 48#include <sys/ioctl.h> 49#include <sys/tty.h> 50#include <sys/file.h> 51#include <sys/select.h> 52#include <sys/proc.h> 53#include <sys/vnode.h> 54#include <sys/poll.h> 55 56#include <dev/usb/usb.h> 57#include <dev/usb/usbhid.h> 58 59#include <dev/usb/usbdi.h> 60#include <dev/usb/usbdi_util.h> 61#include <dev/usb/usbdevs.h> 62#include <dev/usb/usb_quirks.h> 63#include <dev/usb/hid.h> 64#include <dev/usb/ukbdvar.h> 65 66#include <dev/wscons/wsconsio.h> 67#include <dev/wscons/wskbdvar.h> 68#include <dev/wscons/wsksymdef.h> 69#include <dev/wscons/wsksymvar.h> 70 71#include "opt_wsdisplay_compat.h" 72 73#ifdef USB_DEBUG 74#define DPRINTF(x) if (ukbddebug) logprintf x 75#define DPRINTFN(n,x) if (ukbddebug>(n)) logprintf x 76int ukbddebug = 0; 77#else 78#define DPRINTF(x) 79#define DPRINTFN(n,x) 80#endif 81 82#define UPROTO_BOOT_KEYBOARD 1 83 84#define NKEYCODE 6 85 86#define NUM_LOCK 0x01 87#define CAPS_LOCK 0x02 88#define SCROLL_LOCK 0x04 89 90struct ukbd_data { 91 u_int8_t modifiers; 92#define MOD_CONTROL_L 0x01 93#define MOD_CONTROL_R 0x10 94#define MOD_SHIFT_L 0x02 95#define MOD_SHIFT_R 0x20 96#define MOD_ALT_L 0x04 97#define MOD_ALT_R 0x40 98#define MOD_WIN_L 0x08 99#define MOD_WIN_R 0x80 100 u_int8_t reserved; 101 u_int8_t keycode[NKEYCODE]; 102}; 103 104#define PRESS 0x000 105#define RELEASE 0x100 106#define CODEMASK 0x0ff 107 108/* Translate USB bitmap to USB keycode. */ 109#define NMOD 8 110static struct { 111 int mask, key; 112} ukbd_mods[NMOD] = { 113 { MOD_CONTROL_L, 224 }, 114 { MOD_CONTROL_R, 228 }, 115 { MOD_SHIFT_L, 225 }, 116 { MOD_SHIFT_R, 229 }, 117 { MOD_ALT_L, 226 }, 118 { MOD_ALT_R, 230 }, 119 { MOD_WIN_L, 227 }, 120 { MOD_WIN_R, 231 }, 121}; 122 123#if defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) 124#define NN 0 /* no translation */ 125/* 126 * Translate USB keycodes to US keyboard XT scancodes. 127 * Scancodes >= 128 represent EXTENDED keycodes. 128 */ 129static u_int8_t ukbd_trtab[256] = { 130 NN, NN, NN, NN, 30, 48, 46, 32, /* 00 - 07 */ 131 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */ 132 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */ 133 22, 47, 17, 45, 21, 44, 2, 3, /* 18 - 1F */ 134 4, 5, 6, 7, 8, 9, 10, 11, /* 20 - 27 */ 135 28, 1, 14, 15, 57, 12, 13, 26, /* 28 - 2F */ 136 27, 43, NN, 39, 40, 41, 51, 52, /* 30 - 37 */ 137 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */ 138 65, 66, 67, 68, 87, 88, 170, 70, /* 40 - 47 */ 139 127, 210, 199, 201, 211, 207, 209, 205, /* 48 - 4F */ 140 203, 208, 200, 69, 181, 55, 74, 78, /* 50 - 57 */ 141 156, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */ 142 72, 73, 82, 83, NN, 221, NN, NN, /* 60 - 67 */ 143 NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */ 144 NN, NN, NN, NN, NN, NN, NN, NN, /* 70 - 77 */ 145 NN, NN, NN, NN, NN, NN, NN, NN, /* 78 - 7F */ 146 NN, NN, NN, NN, NN, NN, NN, NN, /* 80 - 87 */ 147 NN, NN, NN, NN, NN, NN, NN, NN, /* 88 - 8F */ 148 NN, NN, NN, NN, NN, NN, NN, NN, /* 90 - 97 */ 149 NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9F */ 150 NN, NN, NN, NN, NN, NN, NN, NN, /* A0 - A7 */ 151 NN, NN, NN, NN, NN, NN, NN, NN, /* A8 - AF */ 152 NN, NN, NN, NN, NN, NN, NN, NN, /* B0 - B7 */ 153 NN, NN, NN, NN, NN, NN, NN, NN, /* B8 - BF */ 154 NN, NN, NN, NN, NN, NN, NN, NN, /* C0 - C7 */ 155 NN, NN, NN, NN, NN, NN, NN, NN, /* C8 - CF */ 156 NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ 157 NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ 158 29, 42, 56, 219, 157, 54, 184,220, /* E0 - E7 */ 159 NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ 160 NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ 161 NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ 162}; 163#endif /* defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) */ 164 165#define KEY_ERROR 0x01 166 167#define MAXKEYS (NMOD+2*NKEYCODE) 168 169struct ukbd_softc { 170 bdevice sc_dev; /* base device */ 171 usbd_interface_handle sc_iface; /* interface */ 172 usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ 173 int sc_ep_addr; 174 175 struct ukbd_data sc_ndata; 176 struct ukbd_data sc_odata; 177 178 char sc_enabled; 179 180 int sc_console_keyboard; /* we are the console keyboard */ 181 182 int sc_leds; 183#if defined(__NetBSD__) 184 struct device *sc_wskbddev; 185#if defined(WSDISPLAY_COMPAT_RAWKBD) 186#define REP_DELAY1 400 187#define REP_DELAYN 100 188 int sc_rawkbd; 189 int sc_nrep; 190 char sc_rep[MAXKEYS]; 191#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */ 192 193 int sc_polling; 194 int sc_npollchar; 195 u_int16_t sc_pollchars[MAXKEYS]; 196#endif /* defined(__NetBSD__) */ 197}; 198 199#define UKBDUNIT(dev) (minor(dev)) 200#define UKBD_CHUNK 128 /* chunk size for read */ 201#define UKBD_BSIZE 1020 /* buffer size */ 202 203int ukbd_is_console; 204 205void ukbd_cngetc __P((void *, u_int *, int *)); 206void ukbd_cnpollc __P((void *, int)); 207 208#if defined(__NetBSD__) 209const struct wskbd_consops ukbd_consops = { 210 ukbd_cngetc, 211 ukbd_cnpollc, 212}; 213#endif 214 215void ukbd_intr __P((usbd_request_handle, usbd_private_handle, usbd_status)); 216 217int ukbd_enable __P((void *, int)); 218void ukbd_set_leds __P((void *, int)); 219 220#if defined(__NetBSD__) 221int ukbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 222void ukbd_rawrepeat __P((void *v)); 223 224const struct wskbd_accessops ukbd_accessops = { 225 ukbd_enable, 226 ukbd_set_leds, 227 ukbd_ioctl, 228}; 229 230extern const struct wscons_keydesc ukbd_keydesctab[]; 231 232const struct wskbd_mapdata ukbd_keymapdata = { 233 ukbd_keydesctab, 234 KB_US, 235}; 236#endif 237 238USB_DECLARE_DRIVER(ukbd); 239 240USB_MATCH(ukbd) 241{ 242 USB_MATCH_START(ukbd, uaa); 243 usb_interface_descriptor_t *id; 244 245 /* Check that this is a keyboard that speaks the boot protocol. */ 246 if (!uaa->iface) 247 return (UMATCH_NONE); 248 id = usbd_get_interface_descriptor(uaa->iface); 249 if (!id || 250 id->bInterfaceClass != UCLASS_HID || 251 id->bInterfaceSubClass != USUBCLASS_BOOT || 252 id->bInterfaceProtocol != UPROTO_BOOT_KEYBOARD) 253 return (UMATCH_NONE); 254 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); 255} 256 257USB_ATTACH(ukbd) 258{ 259 USB_ATTACH_START(ukbd, sc, uaa); 260 usbd_interface_handle iface = uaa->iface; 261 usb_interface_descriptor_t *id; 262 usb_endpoint_descriptor_t *ed; 263 usbd_status r; 264 char devinfo[1024]; 265#if defined(__NetBSD__) 266 struct wskbddev_attach_args a; 267#else 268 int i; 269#endif 270 271 sc->sc_iface = iface; 272 id = usbd_get_interface_descriptor(iface); 273 usbd_devinfo(uaa->device, 0, devinfo); 274 USB_ATTACH_SETUP; 275 printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), 276 devinfo, id->bInterfaceClass, id->bInterfaceSubClass); 277 278 ed = usbd_interface2endpoint_descriptor(iface, 0); 279 if (!ed) { 280 printf("%s: could not read endpoint descriptor\n", 281 USBDEVNAME(sc->sc_dev)); 282 USB_ATTACH_ERROR_RETURN; 283 } 284 285 DPRINTFN(10,("ukbd_attach: bLength=%d bDescriptorType=%d " 286 "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" 287 " bInterval=%d\n", 288 ed->bLength, ed->bDescriptorType, 289 ed->bEndpointAddress & UE_ADDR, 290 ed->bEndpointAddress & UE_IN ? "in" : "out", 291 ed->bmAttributes & UE_XFERTYPE, 292 UGETW(ed->wMaxPacketSize), ed->bInterval)); 293 294 if ((ed->bEndpointAddress & UE_IN) != UE_IN || 295 (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { 296 printf("%s: unexpected endpoint\n", 297 USBDEVNAME(sc->sc_dev)); 298 USB_ATTACH_ERROR_RETURN; 299 } 300 301 if ((usbd_get_quirks(uaa->device)->uq_flags & UQ_NO_SET_PROTO) == 0) { 302 r = usbd_set_protocol(iface, 0); 303 DPRINTFN(5, ("ukbd_attach: protocol set\n")); 304 if (r != USBD_NORMAL_COMPLETION) { 305 printf("%s: set protocol failed\n", 306 USBDEVNAME(sc->sc_dev)); 307 USB_ATTACH_ERROR_RETURN; 308 } 309 } 310 311 /* Ignore if SETIDLE fails since it is not crucial. */ 312 usbd_set_idle(iface, 0, 0); 313 314 sc->sc_ep_addr = ed->bEndpointAddress; 315 316 /* 317 * Remember if we're the console keyboard. 318 * 319 * XXX This always picks the first keyboard on the 320 * first USB bus, but what else can we really do? 321 */ 322 if ((sc->sc_console_keyboard = ukbd_is_console) != 0) { 323 /* Don't let any other keyboard have it. */ 324 ukbd_is_console = 0; 325 } 326 327 if (sc->sc_console_keyboard) { 328 DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc)); 329 wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata); 330 ukbd_enable(sc, 1); 331 } 332 333 a.console = sc->sc_console_keyboard; 334 335 a.keymap = &ukbd_keymapdata; 336 337 a.accessops = &ukbd_accessops; 338 a.accesscookie = sc; 339 340 /* Flash the leds; no real purpose, just shows we're alive. */ 341 ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS); 342 usbd_delay_ms(uaa->device, 400); 343 ukbd_set_leds(sc, 0); 344 345 sc->sc_wskbddev = config_found(self, &a, wskbddevprint); 346 347 USB_ATTACH_SUCCESS_RETURN; 348} 349 350int 351ukbd_enable(v, on) 352 void *v; 353 int on; 354{ 355 struct ukbd_softc *sc = v; 356 usbd_status r; 357 358 /* Should only be called to change state */ 359 if (sc->sc_enabled == on) { 360#ifdef DIAGNOSTIC 361 printf("ukbd_enable: %s: bad call on=%d\n", 362 USBDEVNAME(sc->sc_dev), on); 363#endif 364 return (EBUSY); 365 } 366 367 DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on)); 368 if (on) { 369 /* Set up interrupt pipe. */ 370 r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, 371 USBD_SHORT_XFER_OK, 372 &sc->sc_intrpipe, sc, &sc->sc_ndata, 373 sizeof(sc->sc_ndata), ukbd_intr); 374 if (r != USBD_NORMAL_COMPLETION) 375 return (EIO); 376 } else { 377 /* Disable interrupts. */ 378 usbd_abort_pipe(sc->sc_intrpipe); 379 usbd_close_pipe(sc->sc_intrpipe); 380 } 381 sc->sc_enabled = on; 382 383 return (0); 384} 385 386int 387ukbd_activate(self, act) 388 struct device *self; 389 enum devact act; 390{ 391 return (0); 392} 393 394int 395ukbd_detach(self, flags) 396 struct device *self; 397 int flags; 398{ 399 struct ukbd_softc *sc = (struct ukbd_softc *)self; 400 int rv = 0; 401 402 DPRINTF(("ukbd_detach: sc=%p flags=%d\n", sc, flags)); 403 if (sc->sc_console_keyboard) { 404 /* 405 * XXX Should probably disconnect our consops, 406 * XXX and either notify some other keyboard that 407 * XXX it can now be the console, or if there aren't 408 * XXX any more USB keyboards, set ukbd_is_console 409 * XXX back to 1 so that the next USB keyboard attached 410 * XXX to the system will get it. 411 */ 412 panic("ukbd_detach: console keyboard"); 413 } 414 /* No need to do reference counting of ums, wskbd has all the goo. */ 415 if (sc->sc_wskbddev) 416 rv = config_detach(sc->sc_wskbddev, flags); 417 return (rv); 418} 419 420void 421ukbd_intr(reqh, addr, status) 422 usbd_request_handle reqh; 423 usbd_private_handle addr; 424 usbd_status status; 425{ 426 struct ukbd_softc *sc = addr; 427 struct ukbd_data *ud = &sc->sc_ndata; 428 int mod, omod; 429 u_int16_t ibuf[MAXKEYS]; /* chars events */ 430 int s; 431 int nkeys, i, j; 432 int key; 433#define ADDKEY(c) ibuf[nkeys++] = (c) 434 435 DPRINTFN(5, ("ukbd_intr: status=%d\n", status)); 436 if (status == USBD_CANCELLED) 437 return; 438 439 if (status != USBD_NORMAL_COMPLETION) { 440 DPRINTF(("ukbd_intr: status=%d\n", status)); 441 usbd_clear_endpoint_stall_async(sc->sc_intrpipe); 442 return; 443 } 444 445 DPRINTFN(5, (" mod=0x%02x key0=0x%02x key1=0x%02x\n", 446 ud->modifiers, ud->keycode[0], ud->keycode[1])); 447 448 if (ud->keycode[0] == KEY_ERROR) 449 return; /* ignore */ 450 nkeys = 0; 451 mod = ud->modifiers; 452 omod = sc->sc_odata.modifiers; 453 if (mod != omod) 454 for (i = 0; i < NMOD; i++) 455 if (( mod & ukbd_mods[i].mask) != 456 (omod & ukbd_mods[i].mask)) 457 ADDKEY(ukbd_mods[i].key | 458 (mod & ukbd_mods[i].mask 459 ? PRESS : RELEASE)); 460 if (memcmp(ud->keycode, sc->sc_odata.keycode, NKEYCODE) != 0) { 461 /* Check for released keys. */ 462 for (i = 0; i < NKEYCODE; i++) { 463 key = sc->sc_odata.keycode[i]; 464 if (key == 0) 465 continue; 466 for (j = 0; j < NKEYCODE; j++) 467 if (key == ud->keycode[j]) 468 goto rfound; 469 ADDKEY(key | RELEASE); 470 rfound: 471 ; 472 } 473 474 /* Check for pressed keys. */ 475 for (i = 0; i < NKEYCODE; i++) { 476 key = ud->keycode[i]; 477 if (key == 0) 478 continue; 479 for (j = 0; j < NKEYCODE; j++) 480 if (key == sc->sc_odata.keycode[j]) 481 goto pfound; 482 DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key)); 483 ADDKEY(key | PRESS); 484 pfound: 485 ; 486 } 487 } 488 sc->sc_odata = *ud; 489 490 if (nkeys == 0) 491 return; 492 493 if (sc->sc_polling) { 494 DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0])); 495 memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t)); 496 sc->sc_npollchar = nkeys; 497 return; 498 } 499#ifdef WSDISPLAY_COMPAT_RAWKBD 500 if (sc->sc_rawkbd) { 501 char cbuf[MAXKEYS * 2]; 502 int c; 503 int npress; 504 505 for (npress = i = j = 0; i < nkeys; i++) { 506 key = ibuf[i]; 507 c = ukbd_trtab[key & CODEMASK]; 508 if (c == NN) 509 continue; 510 if (c & 0x80) 511 cbuf[j++] = 0xe0; 512 cbuf[j] = c & 0x7f; 513 if (key & RELEASE) 514 cbuf[j] |= 0x80; 515 else { 516 /* remember pressed keys for autorepeat */ 517 if (c & 0x80) 518 sc->sc_rep[npress++] = 0xe0; 519 sc->sc_rep[npress++] = c & 0x7f; 520 } 521 DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n", 522 c & 0x80 ? "0xe0 " : "", 523 cbuf[j])); 524 j++; 525 } 526 s = spltty(); 527 wskbd_rawinput(sc->sc_wskbddev, cbuf, j); 528 splx(s); 529 untimeout(ukbd_rawrepeat, sc); 530 if (npress != 0) { 531 sc->sc_nrep = npress; 532 timeout(ukbd_rawrepeat, sc, hz * REP_DELAY1 / 1000); 533 } 534 return; 535 } 536#endif 537 538 s = spltty(); 539 for (i = 0; i < nkeys; i++) { 540 key = ibuf[i]; 541 wskbd_input(sc->sc_wskbddev, 542 key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN, 543 key&CODEMASK); 544 } 545 splx(s); 546} 547 548void 549ukbd_set_leds(v, leds) 550 void *v; 551 int leds; 552{ 553 struct ukbd_softc *sc = v; 554 u_int8_t res; 555 556 DPRINTF(("ukbd_set_leds: sc=%p leds=%d\n", sc, leds)); 557 558 sc->sc_leds = leds; 559 res = 0; 560 if (leds & WSKBD_LED_SCROLL) 561 res |= SCROLL_LOCK; 562 if (leds & WSKBD_LED_NUM) 563 res |= NUM_LOCK; 564 if (leds & WSKBD_LED_CAPS) 565 res |= CAPS_LOCK; 566 res |= leds & 0xf8; 567 usbd_set_report_async(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1); 568} 569 570#ifdef WSDISPLAY_COMPAT_RAWKBD 571void 572ukbd_rawrepeat(v) 573 void *v; 574{ 575 struct ukbd_softc *sc = v; 576 int s; 577 578 s = spltty(); 579 wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep); 580 splx(s); 581 timeout(ukbd_rawrepeat, sc, hz * REP_DELAYN / 1000); 582} 583#endif 584 585int 586ukbd_ioctl(v, cmd, data, flag, p) 587 void *v; 588 u_long cmd; 589 caddr_t data; 590 int flag; 591 struct proc *p; 592{ 593 struct ukbd_softc *sc = v; 594 595 switch (cmd) { 596 case WSKBDIO_GTYPE: 597 *(int *)data = WSKBD_TYPE_USB; 598 return (0); 599 case WSKBDIO_SETLEDS: 600 ukbd_set_leds(v, *(int *)data); 601 return (0); 602 case WSKBDIO_GETLEDS: 603 *(int *)data = sc->sc_leds; 604 return (0); 605#ifdef WSDISPLAY_COMPAT_RAWKBD 606 case WSKBDIO_SETMODE: 607 DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data)); 608 sc->sc_rawkbd = *(int *)data == WSKBD_RAW; 609 untimeout(ukbd_rawrepeat, sc); 610 return (0); 611#endif 612 } 613 return (-1); 614} 615 616/* Console interface. */ 617void 618ukbd_cngetc(v, type, data) 619 void *v; 620 u_int *type; 621 int *data; 622{ 623 struct ukbd_softc *sc = v; 624 int s; 625 int c; 626 627 DPRINTFN(-1,("ukbd_cngetc: enter\n")); 628 s = splusb(); 629 sc->sc_polling = 1; 630 while(sc->sc_npollchar <= 0) 631 usbd_dopoll(sc->sc_iface); 632 sc->sc_polling = 0; 633 c = sc->sc_pollchars[0]; 634 sc->sc_npollchar--; 635 memcpy(sc->sc_pollchars, sc->sc_pollchars+1, 636 sc->sc_npollchar * sizeof(u_int16_t)); 637 *type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 638 *data = c & CODEMASK; 639 splx(s); 640 DPRINTFN(-1,("ukbd_cngetc: return 0x%02x\n", c)); 641} 642 643void 644ukbd_cnpollc(v, on) 645 void *v; 646 int on; 647{ 648 struct ukbd_softc *sc = v; 649 650 DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on)); 651 652 usbd_set_polling(sc->sc_iface, on); 653} 654 655int 656ukbd_cnattach() 657{ 658 659 /* 660 * XXX USB requires too many parts of the kernel to be running 661 * XXX in order to work, so we can't do much for the console 662 * XXX keyboard until autconfiguration has run its course. 663 */ 664 ukbd_is_console = 1; 665 return (0); 666} 667