ukbd.c revision 187259
1184610Salfred#include <sys/cdefs.h> 2184610Salfred__FBSDID("$FreeBSD: head/sys/dev/usb2/input/ukbd2.c 187259 2009-01-15 02:35:40Z thompsa $"); 3184610Salfred 4184610Salfred 5184610Salfred/*- 6184610Salfred * Copyright (c) 1998 The NetBSD Foundation, Inc. 7184610Salfred * All rights reserved. 8184610Salfred * 9184610Salfred * This code is derived from software contributed to The NetBSD Foundation 10184610Salfred * by Lennart Augustsson (lennart@augustsson.net) at 11184610Salfred * Carlstedt Research & Technology. 12184610Salfred * 13184610Salfred * Redistribution and use in source and binary forms, with or without 14184610Salfred * modification, are permitted provided that the following conditions 15184610Salfred * are met: 16184610Salfred * 1. Redistributions of source code must retain the above copyright 17184610Salfred * notice, this list of conditions and the following disclaimer. 18184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 19184610Salfred * notice, this list of conditions and the following disclaimer in the 20184610Salfred * documentation and/or other materials provided with the distribution. 21184610Salfred * 3. All advertising materials mentioning features or use of this software 22184610Salfred * must display the following acknowledgement: 23184610Salfred * This product includes software developed by the NetBSD 24184610Salfred * Foundation, Inc. and its contributors. 25184610Salfred * 4. Neither the name of The NetBSD Foundation nor the names of its 26184610Salfred * contributors may be used to endorse or promote products derived 27184610Salfred * from this software without specific prior written permission. 28184610Salfred * 29184610Salfred * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 30184610Salfred * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 31184610Salfred * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 32184610Salfred * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 33184610Salfred * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 34184610Salfred * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 35184610Salfred * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 36184610Salfred * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 37184610Salfred * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38184610Salfred * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39184610Salfred * POSSIBILITY OF SUCH DAMAGE. 40184610Salfred * 41184610Salfred */ 42184610Salfred 43184610Salfred/* 44184610Salfred * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 45184610Salfred */ 46184610Salfred 47184610Salfred#include "opt_compat.h" 48184610Salfred#include "opt_kbd.h" 49184610Salfred#include "opt_ukbd.h" 50184610Salfred 51184610Salfred#include <dev/usb2/include/usb2_standard.h> 52184610Salfred#include <dev/usb2/include/usb2_mfunc.h> 53184610Salfred#include <dev/usb2/include/usb2_error.h> 54184610Salfred#include <dev/usb2/include/usb2_hid.h> 55184610Salfred 56184610Salfred#define USB_DEBUG_VAR ukbd_debug 57184610Salfred 58184610Salfred#include <dev/usb2/core/usb2_core.h> 59184610Salfred#include <dev/usb2/core/usb2_util.h> 60184610Salfred#include <dev/usb2/core/usb2_debug.h> 61184610Salfred#include <dev/usb2/core/usb2_busdma.h> 62184610Salfred#include <dev/usb2/core/usb2_process.h> 63184610Salfred#include <dev/usb2/core/usb2_transfer.h> 64184610Salfred#include <dev/usb2/core/usb2_request.h> 65184610Salfred#include <dev/usb2/core/usb2_dynamic.h> 66184610Salfred#include <dev/usb2/core/usb2_hid.h> 67184610Salfred 68184610Salfred#include <dev/usb2/input/usb2_input.h> 69184610Salfred 70184610Salfred#include <dev/usb2/quirk/usb2_quirk.h> 71184610Salfred 72184610Salfred#include <sys/ioccom.h> 73184610Salfred#include <sys/filio.h> 74184610Salfred#include <sys/tty.h> 75184610Salfred#include <sys/kbio.h> 76184610Salfred 77184610Salfred#include <dev/kbd/kbdreg.h> 78184610Salfred 79184610Salfred/* the initial key map, accent map and fkey strings */ 80184610Salfred#if defined(UKBD_DFLT_KEYMAP) && !defined(KLD_MODULE) 81184610Salfred#define KBD_DFLT_KEYMAP 82184610Salfred#include "ukbdmap.h" 83184610Salfred#endif 84184610Salfred 85184610Salfred/* the following file must be included after "ukbdmap.h" */ 86184610Salfred#include <dev/kbd/kbdtables.h> 87184610Salfred 88184610Salfred#if USB_DEBUG 89184610Salfredstatic int ukbd_debug = 0; 90184610Salfred 91184610SalfredSYSCTL_NODE(_hw_usb2, OID_AUTO, ukbd, CTLFLAG_RW, 0, "USB ukbd"); 92184610SalfredSYSCTL_INT(_hw_usb2_ukbd, OID_AUTO, debug, CTLFLAG_RW, 93184610Salfred &ukbd_debug, 0, "Debug level"); 94184610Salfred#endif 95184610Salfred 96184610Salfred#define UPROTO_BOOT_KEYBOARD 1 97184610Salfred 98184610Salfred#define UKBD_EMULATE_ATSCANCODE 1 99184610Salfred#define UKBD_DRIVER_NAME "ukbd" 100184610Salfred#define UKBD_NMOD 8 /* units */ 101184610Salfred#define UKBD_NKEYCODE 6 /* units */ 102184610Salfred#define UKBD_IN_BUF_SIZE (2*(UKBD_NMOD + (2*UKBD_NKEYCODE))) /* bytes */ 103184610Salfred#define UKBD_IN_BUF_FULL (UKBD_IN_BUF_SIZE / 2) /* bytes */ 104184610Salfred#define UKBD_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */ 105184610Salfred 106184610Salfredstruct ukbd_data { 107184610Salfred uint8_t modifiers; 108184610Salfred#define MOD_CONTROL_L 0x01 109184610Salfred#define MOD_CONTROL_R 0x10 110184610Salfred#define MOD_SHIFT_L 0x02 111184610Salfred#define MOD_SHIFT_R 0x20 112184610Salfred#define MOD_ALT_L 0x04 113184610Salfred#define MOD_ALT_R 0x40 114184610Salfred#define MOD_WIN_L 0x08 115184610Salfred#define MOD_WIN_R 0x80 116184610Salfred uint8_t reserved; 117184610Salfred uint8_t keycode[UKBD_NKEYCODE]; 118184610Salfred} __packed; 119184610Salfred 120187259Sthompsaenum { 121187259Sthompsa UKBD_INTR_DT, 122187259Sthompsa UKBD_INTR_CS, 123187259Sthompsa UKBD_CTRL_LED, 124187259Sthompsa UKBD_N_TRANSFER = 3, 125187259Sthompsa}; 126187259Sthompsa 127184610Salfredstruct ukbd_softc { 128184610Salfred keyboard_t sc_kbd; 129184610Salfred keymap_t sc_keymap; 130184610Salfred accentmap_t sc_accmap; 131184610Salfred fkeytab_t sc_fkeymap[UKBD_NFKEY]; 132184610Salfred struct usb2_callout sc_callout; 133184610Salfred struct ukbd_data sc_ndata; 134184610Salfred struct ukbd_data sc_odata; 135184610Salfred 136184610Salfred struct usb2_device *sc_udev; 137184610Salfred struct usb2_interface *sc_iface; 138184610Salfred struct usb2_xfer *sc_xfer[UKBD_N_TRANSFER]; 139184610Salfred 140184610Salfred uint32_t sc_ntime[UKBD_NKEYCODE]; 141184610Salfred uint32_t sc_otime[UKBD_NKEYCODE]; 142184610Salfred uint32_t sc_input[UKBD_IN_BUF_SIZE]; /* input buffer */ 143184610Salfred uint32_t sc_time_ms; 144184610Salfred uint32_t sc_composed_char; /* composed char code, if non-zero */ 145184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 146184610Salfred uint32_t sc_buffered_char[2]; 147184610Salfred#endif 148184610Salfred uint32_t sc_flags; /* flags */ 149184610Salfred#define UKBD_FLAG_COMPOSE 0x0001 150184610Salfred#define UKBD_FLAG_POLLING 0x0002 151184610Salfred#define UKBD_FLAG_SET_LEDS 0x0004 152184610Salfred#define UKBD_FLAG_INTR_STALL 0x0008 153184610Salfred#define UKBD_FLAG_ATTACHED 0x0010 154184610Salfred#define UKBD_FLAG_GONE 0x0020 155184610Salfred 156184610Salfred int32_t sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ 157184610Salfred int32_t sc_state; /* shift/lock key state */ 158184610Salfred int32_t sc_accents; /* accent key index (> 0) */ 159184610Salfred 160184610Salfred uint16_t sc_inputs; 161184610Salfred uint16_t sc_inputhead; 162184610Salfred uint16_t sc_inputtail; 163184610Salfred 164184610Salfred uint8_t sc_leds; /* store for async led requests */ 165184610Salfred uint8_t sc_iface_index; 166184610Salfred uint8_t sc_iface_no; 167184610Salfred}; 168184610Salfred 169184610Salfred#define KEY_ERROR 0x01 170184610Salfred 171184610Salfred#define KEY_PRESS 0 172184610Salfred#define KEY_RELEASE 0x400 173184610Salfred#define KEY_INDEX(c) ((c) & 0xFF) 174184610Salfred 175184610Salfred#define SCAN_PRESS 0 176184610Salfred#define SCAN_RELEASE 0x80 177184610Salfred#define SCAN_PREFIX_E0 0x100 178184610Salfred#define SCAN_PREFIX_E1 0x200 179184610Salfred#define SCAN_PREFIX_CTL 0x400 180184610Salfred#define SCAN_PREFIX_SHIFT 0x800 181184610Salfred#define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | \ 182184610Salfred SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT) 183184610Salfred#define SCAN_CHAR(c) ((c) & 0x7f) 184184610Salfred 185184610Salfredstruct ukbd_mods { 186184610Salfred uint32_t mask, key; 187184610Salfred}; 188184610Salfred 189184610Salfredstatic const struct ukbd_mods ukbd_mods[UKBD_NMOD] = { 190184610Salfred {MOD_CONTROL_L, 0xe0}, 191184610Salfred {MOD_CONTROL_R, 0xe4}, 192184610Salfred {MOD_SHIFT_L, 0xe1}, 193184610Salfred {MOD_SHIFT_R, 0xe5}, 194184610Salfred {MOD_ALT_L, 0xe2}, 195184610Salfred {MOD_ALT_R, 0xe6}, 196184610Salfred {MOD_WIN_L, 0xe3}, 197184610Salfred {MOD_WIN_R, 0xe7}, 198184610Salfred}; 199184610Salfred 200184610Salfred#define NN 0 /* no translation */ 201184610Salfred/* 202184610Salfred * Translate USB keycodes to AT keyboard scancodes. 203184610Salfred */ 204184610Salfred/* 205184610Salfred * FIXME: Mac USB keyboard generates: 206184610Salfred * 0x53: keypad NumLock/Clear 207184610Salfred * 0x66: Power 208184610Salfred * 0x67: keypad = 209184610Salfred * 0x68: F13 210184610Salfred * 0x69: F14 211184610Salfred * 0x6a: F15 212184610Salfred */ 213184610Salfredstatic const uint8_t ukbd_trtab[256] = { 214184610Salfred 0, 0, 0, 0, 30, 48, 46, 32, /* 00 - 07 */ 215184610Salfred 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */ 216184610Salfred 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */ 217184610Salfred 22, 47, 17, 45, 21, 44, 2, 3, /* 18 - 1F */ 218184610Salfred 4, 5, 6, 7, 8, 9, 10, 11, /* 20 - 27 */ 219184610Salfred 28, 1, 14, 15, 57, 12, 13, 26, /* 28 - 2F */ 220184610Salfred 27, 43, 43, 39, 40, 41, 51, 52, /* 30 - 37 */ 221184610Salfred 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */ 222184610Salfred 65, 66, 67, 68, 87, 88, 92, 70, /* 40 - 47 */ 223184610Salfred 104, 102, 94, 96, 103, 99, 101, 98, /* 48 - 4F */ 224184610Salfred 97, 100, 95, 69, 91, 55, 74, 78,/* 50 - 57 */ 225184610Salfred 89, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */ 226184610Salfred 72, 73, 82, 83, 86, 107, 122, NN, /* 60 - 67 */ 227184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */ 228184610Salfred NN, NN, NN, NN, 115, 108, 111, 113, /* 70 - 77 */ 229184610Salfred 109, 110, 112, 118, 114, 116, 117, 119, /* 78 - 7F */ 230184610Salfred 121, 120, NN, NN, NN, NN, NN, 115, /* 80 - 87 */ 231184610Salfred 112, 125, 121, 123, NN, NN, NN, NN, /* 88 - 8F */ 232184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* 90 - 97 */ 233184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9F */ 234184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* A0 - A7 */ 235184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* A8 - AF */ 236184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* B0 - B7 */ 237184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* B8 - BF */ 238184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* C0 - C7 */ 239184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* C8 - CF */ 240184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ 241184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ 242184610Salfred 29, 42, 56, 105, 90, 54, 93, 106, /* E0 - E7 */ 243184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ 244184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ 245184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ 246184610Salfred}; 247184610Salfred 248184610Salfred/* prototypes */ 249185948Sthompsastatic void ukbd_timeout(void *); 250185948Sthompsastatic void ukbd_set_leds(struct ukbd_softc *, uint8_t); 251185948Sthompsastatic int ukbd_set_typematic(keyboard_t *, int); 252184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 253185948Sthompsastatic int ukbd_key2scan(struct ukbd_softc *, int, int, int); 254184610Salfred#endif 255185948Sthompsastatic uint32_t ukbd_read_char(keyboard_t *, int); 256185948Sthompsastatic void ukbd_clear_state(keyboard_t *); 257185948Sthompsastatic int ukbd_ioctl(keyboard_t *, u_long, caddr_t); 258185948Sthompsastatic int ukbd_enable(keyboard_t *); 259185948Sthompsastatic int ukbd_disable(keyboard_t *); 260185948Sthompsastatic void ukbd_interrupt(struct ukbd_softc *); 261184610Salfred 262184610Salfredstatic device_probe_t ukbd_probe; 263184610Salfredstatic device_attach_t ukbd_attach; 264184610Salfredstatic device_detach_t ukbd_detach; 265184610Salfredstatic device_resume_t ukbd_resume; 266184610Salfred 267184610Salfredstatic void 268184610Salfredukbd_put_key(struct ukbd_softc *sc, uint32_t key) 269184610Salfred{ 270184610Salfred mtx_assert(&Giant, MA_OWNED); 271184610Salfred 272184610Salfred DPRINTF("0x%02x (%d) %s\n", key, key, 273184610Salfred (key & KEY_RELEASE) ? "released" : "pressed"); 274184610Salfred 275184610Salfred if (sc->sc_inputs < UKBD_IN_BUF_SIZE) { 276184610Salfred sc->sc_input[sc->sc_inputtail] = key; 277184610Salfred ++(sc->sc_inputs); 278184610Salfred ++(sc->sc_inputtail); 279184610Salfred if (sc->sc_inputtail >= UKBD_IN_BUF_SIZE) { 280184610Salfred sc->sc_inputtail = 0; 281184610Salfred } 282184610Salfred } else { 283184610Salfred DPRINTF("input buffer is full\n"); 284184610Salfred } 285184610Salfred} 286184610Salfred 287184610Salfredstatic int32_t 288184610Salfredukbd_get_key(struct ukbd_softc *sc, uint8_t wait) 289184610Salfred{ 290184610Salfred int32_t c; 291184610Salfred 292184610Salfred mtx_assert(&Giant, MA_OWNED); 293184610Salfred 294184610Salfred if (sc->sc_inputs == 0) { 295184610Salfred /* start transfer, if not already started */ 296187259Sthompsa usb2_transfer_start(sc->sc_xfer[UKBD_INTR_DT]); 297184610Salfred } 298184610Salfred if (sc->sc_flags & UKBD_FLAG_POLLING) { 299184610Salfred DPRINTFN(2, "polling\n"); 300184610Salfred 301184610Salfred while (sc->sc_inputs == 0) { 302184610Salfred 303184610Salfred usb2_do_poll(sc->sc_xfer, UKBD_N_TRANSFER); 304184610Salfred 305184610Salfred DELAY(1000); /* delay 1 ms */ 306184610Salfred 307184610Salfred sc->sc_time_ms++; 308184610Salfred 309184610Salfred /* support repetition of keys: */ 310184610Salfred 311184610Salfred ukbd_interrupt(sc); 312184610Salfred 313184610Salfred if (!wait) { 314184610Salfred break; 315184610Salfred } 316184610Salfred } 317184610Salfred } 318184610Salfred if (sc->sc_inputs == 0) { 319184610Salfred c = -1; 320184610Salfred } else { 321184610Salfred c = sc->sc_input[sc->sc_inputhead]; 322184610Salfred --(sc->sc_inputs); 323184610Salfred ++(sc->sc_inputhead); 324184610Salfred if (sc->sc_inputhead >= UKBD_IN_BUF_SIZE) { 325184610Salfred sc->sc_inputhead = 0; 326184610Salfred } 327184610Salfred } 328184610Salfred return (c); 329184610Salfred} 330184610Salfred 331184610Salfredstatic void 332184610Salfredukbd_interrupt(struct ukbd_softc *sc) 333184610Salfred{ 334184610Salfred uint32_t n_mod; 335184610Salfred uint32_t o_mod; 336184610Salfred uint32_t now = sc->sc_time_ms; 337184610Salfred uint32_t dtime; 338184610Salfred uint32_t c; 339184610Salfred uint8_t key; 340184610Salfred uint8_t i; 341184610Salfred uint8_t j; 342184610Salfred 343184610Salfred if (sc->sc_ndata.keycode[0] == KEY_ERROR) { 344184610Salfred goto done; 345184610Salfred } 346184610Salfred n_mod = sc->sc_ndata.modifiers; 347184610Salfred o_mod = sc->sc_odata.modifiers; 348184610Salfred if (n_mod != o_mod) { 349184610Salfred for (i = 0; i < UKBD_NMOD; i++) { 350184610Salfred if ((n_mod & ukbd_mods[i].mask) != 351184610Salfred (o_mod & ukbd_mods[i].mask)) { 352184610Salfred ukbd_put_key(sc, ukbd_mods[i].key | 353184610Salfred ((n_mod & ukbd_mods[i].mask) ? 354184610Salfred KEY_PRESS : KEY_RELEASE)); 355184610Salfred } 356184610Salfred } 357184610Salfred } 358184610Salfred /* Check for released keys. */ 359184610Salfred for (i = 0; i < UKBD_NKEYCODE; i++) { 360184610Salfred key = sc->sc_odata.keycode[i]; 361184610Salfred if (key == 0) { 362184610Salfred continue; 363184610Salfred } 364184610Salfred for (j = 0; j < UKBD_NKEYCODE; j++) { 365184610Salfred if (sc->sc_ndata.keycode[j] == 0) { 366184610Salfred continue; 367184610Salfred } 368184610Salfred if (key == sc->sc_ndata.keycode[j]) { 369184610Salfred goto rfound; 370184610Salfred } 371184610Salfred } 372184610Salfred ukbd_put_key(sc, key | KEY_RELEASE); 373184610Salfredrfound: ; 374184610Salfred } 375184610Salfred 376184610Salfred /* Check for pressed keys. */ 377184610Salfred for (i = 0; i < UKBD_NKEYCODE; i++) { 378184610Salfred key = sc->sc_ndata.keycode[i]; 379184610Salfred if (key == 0) { 380184610Salfred continue; 381184610Salfred } 382184610Salfred sc->sc_ntime[i] = now + sc->sc_kbd.kb_delay1; 383184610Salfred for (j = 0; j < UKBD_NKEYCODE; j++) { 384184610Salfred if (sc->sc_odata.keycode[j] == 0) { 385184610Salfred continue; 386184610Salfred } 387184610Salfred if (key == sc->sc_odata.keycode[j]) { 388184610Salfred 389184610Salfred /* key is still pressed */ 390184610Salfred 391184610Salfred sc->sc_ntime[i] = sc->sc_otime[j]; 392184610Salfred dtime = (sc->sc_otime[j] - now); 393184610Salfred 394184610Salfred if (!(dtime & 0x80000000)) { 395184610Salfred /* time has not elapsed */ 396184610Salfred goto pfound; 397184610Salfred } 398184610Salfred sc->sc_ntime[i] = now + sc->sc_kbd.kb_delay2; 399184610Salfred break; 400184610Salfred } 401184610Salfred } 402184610Salfred ukbd_put_key(sc, key | KEY_PRESS); 403184610Salfred 404184610Salfred /* 405184610Salfred * If any other key is presently down, force its repeat to be 406184610Salfred * well in the future (100s). This makes the last key to be 407184610Salfred * pressed do the autorepeat. 408184610Salfred */ 409184610Salfred for (j = 0; j != UKBD_NKEYCODE; j++) { 410184610Salfred if (j != i) 411184610Salfred sc->sc_ntime[j] = now + (100 * 1000); 412184610Salfred } 413184610Salfredpfound: ; 414184610Salfred } 415184610Salfred 416184610Salfred sc->sc_odata = sc->sc_ndata; 417184610Salfred 418184610Salfred bcopy(sc->sc_ntime, sc->sc_otime, sizeof(sc->sc_otime)); 419184610Salfred 420184610Salfred if (sc->sc_inputs == 0) { 421184610Salfred goto done; 422184610Salfred } 423184610Salfred if (sc->sc_flags & UKBD_FLAG_POLLING) { 424184610Salfred goto done; 425184610Salfred } 426184610Salfred if (KBD_IS_ACTIVE(&sc->sc_kbd) && 427184610Salfred KBD_IS_BUSY(&sc->sc_kbd)) { 428184610Salfred /* let the callback function process the input */ 429184610Salfred (sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT, 430184610Salfred sc->sc_kbd.kb_callback.kc_arg); 431184610Salfred } else { 432184610Salfred /* read and discard the input, no one is waiting for it */ 433184610Salfred do { 434184610Salfred c = ukbd_read_char(&sc->sc_kbd, 0); 435184610Salfred } while (c != NOKEY); 436184610Salfred } 437184610Salfreddone: 438184610Salfred return; 439184610Salfred} 440184610Salfred 441184610Salfredstatic void 442184610Salfredukbd_timeout(void *arg) 443184610Salfred{ 444184610Salfred struct ukbd_softc *sc = arg; 445184610Salfred 446184610Salfred mtx_assert(&Giant, MA_OWNED); 447184610Salfred 448184610Salfred if (!(sc->sc_flags & UKBD_FLAG_POLLING)) { 449184610Salfred sc->sc_time_ms += 25; /* milliseconds */ 450184610Salfred } 451184610Salfred ukbd_interrupt(sc); 452184610Salfred 453184610Salfred usb2_callout_reset(&sc->sc_callout, hz / 40, &ukbd_timeout, sc); 454184610Salfred} 455184610Salfred 456184610Salfredstatic void 457184610Salfredukbd_clear_stall_callback(struct usb2_xfer *xfer) 458184610Salfred{ 459184610Salfred struct ukbd_softc *sc = xfer->priv_sc; 460187259Sthompsa struct usb2_xfer *xfer_other = sc->sc_xfer[UKBD_INTR_DT]; 461184610Salfred 462184610Salfred if (usb2_clear_stall_callback(xfer, xfer_other)) { 463184610Salfred DPRINTF("stall cleared\n"); 464184610Salfred sc->sc_flags &= ~UKBD_FLAG_INTR_STALL; 465184610Salfred usb2_transfer_start(xfer_other); 466184610Salfred } 467184610Salfred} 468184610Salfred 469184610Salfredstatic void 470184610Salfredukbd_intr_callback(struct usb2_xfer *xfer) 471184610Salfred{ 472184610Salfred struct ukbd_softc *sc = xfer->priv_sc; 473184610Salfred uint16_t len = xfer->actlen; 474184610Salfred uint8_t i; 475184610Salfred 476184610Salfred switch (USB_GET_STATE(xfer)) { 477184610Salfred case USB_ST_TRANSFERRED: 478184610Salfred DPRINTF("actlen=%d bytes\n", len); 479184610Salfred 480184610Salfred if (len > sizeof(sc->sc_ndata)) { 481184610Salfred len = sizeof(sc->sc_ndata); 482184610Salfred } 483184610Salfred if (len) { 484184610Salfred bzero(&sc->sc_ndata, sizeof(sc->sc_ndata)); 485184610Salfred usb2_copy_out(xfer->frbuffers, 0, &sc->sc_ndata, len); 486184610Salfred#if USB_DEBUG 487184610Salfred if (sc->sc_ndata.modifiers) { 488184610Salfred DPRINTF("mod: 0x%04x\n", sc->sc_ndata.modifiers); 489184610Salfred } 490184610Salfred for (i = 0; i < UKBD_NKEYCODE; i++) { 491184610Salfred if (sc->sc_ndata.keycode[i]) { 492184610Salfred DPRINTF("[%d] = %d\n", i, sc->sc_ndata.keycode[i]); 493184610Salfred } 494184610Salfred } 495184610Salfred#endif /* USB_DEBUG */ 496184610Salfred ukbd_interrupt(sc); 497184610Salfred } 498184610Salfred case USB_ST_SETUP: 499184610Salfred if (sc->sc_flags & UKBD_FLAG_INTR_STALL) { 500187259Sthompsa usb2_transfer_start(sc->sc_xfer[UKBD_INTR_CS]); 501184610Salfred return; 502184610Salfred } 503184610Salfred if (sc->sc_inputs < UKBD_IN_BUF_FULL) { 504184610Salfred xfer->frlengths[0] = xfer->max_data_length; 505184610Salfred usb2_start_hardware(xfer); 506184610Salfred } else { 507184610Salfred DPRINTF("input queue is full!\n"); 508184610Salfred } 509184610Salfred return; 510184610Salfred 511184610Salfred default: /* Error */ 512184610Salfred DPRINTF("error=%s\n", usb2_errstr(xfer->error)); 513184610Salfred 514184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 515184610Salfred /* try to clear stall first */ 516184610Salfred sc->sc_flags |= UKBD_FLAG_INTR_STALL; 517187259Sthompsa usb2_transfer_start(sc->sc_xfer[UKBD_INTR_CS]); 518184610Salfred } 519184610Salfred return; 520184610Salfred } 521184610Salfred} 522184610Salfred 523184610Salfredstatic void 524184610Salfredukbd_set_leds_callback(struct usb2_xfer *xfer) 525184610Salfred{ 526184610Salfred struct usb2_device_request req; 527184610Salfred uint8_t buf[1]; 528184610Salfred struct ukbd_softc *sc = xfer->priv_sc; 529184610Salfred 530184610Salfred switch (USB_GET_STATE(xfer)) { 531184610Salfred case USB_ST_TRANSFERRED: 532184610Salfred case USB_ST_SETUP: 533184610Salfred if (sc->sc_flags & UKBD_FLAG_SET_LEDS) { 534184610Salfred sc->sc_flags &= ~UKBD_FLAG_SET_LEDS; 535184610Salfred 536184610Salfred req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 537184610Salfred req.bRequest = UR_SET_REPORT; 538184610Salfred USETW2(req.wValue, UHID_OUTPUT_REPORT, 0); 539184610Salfred req.wIndex[0] = sc->sc_iface_no; 540184610Salfred req.wIndex[1] = 0; 541184610Salfred USETW(req.wLength, 1); 542184610Salfred 543184610Salfred buf[0] = sc->sc_leds; 544184610Salfred 545184610Salfred usb2_copy_in(xfer->frbuffers, 0, &req, sizeof(req)); 546184610Salfred usb2_copy_in(xfer->frbuffers + 1, 0, buf, sizeof(buf)); 547184610Salfred 548184610Salfred xfer->frlengths[0] = sizeof(req); 549184610Salfred xfer->frlengths[1] = sizeof(buf); 550184610Salfred xfer->nframes = 2; 551184610Salfred usb2_start_hardware(xfer); 552184610Salfred } 553184610Salfred return; 554184610Salfred 555184610Salfred default: /* Error */ 556184610Salfred DPRINTFN(0, "error=%s\n", usb2_errstr(xfer->error)); 557184610Salfred return; 558184610Salfred } 559184610Salfred} 560184610Salfred 561184610Salfredstatic const struct usb2_config ukbd_config[UKBD_N_TRANSFER] = { 562184610Salfred 563187259Sthompsa [UKBD_INTR_DT] = { 564184610Salfred .type = UE_INTERRUPT, 565184610Salfred .endpoint = UE_ADDR_ANY, 566184610Salfred .direction = UE_DIR_IN, 567184610Salfred .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 568184610Salfred .mh.bufsize = 0, /* use wMaxPacketSize */ 569184610Salfred .mh.callback = &ukbd_intr_callback, 570184610Salfred }, 571184610Salfred 572187259Sthompsa [UKBD_INTR_CS] = { 573184610Salfred .type = UE_CONTROL, 574184610Salfred .endpoint = 0x00, /* Control pipe */ 575184610Salfred .direction = UE_DIR_ANY, 576184610Salfred .mh.bufsize = sizeof(struct usb2_device_request), 577184610Salfred .mh.callback = &ukbd_clear_stall_callback, 578184610Salfred .mh.timeout = 1000, /* 1 second */ 579184610Salfred .mh.interval = 50, /* 50ms */ 580184610Salfred }, 581184610Salfred 582187259Sthompsa [UKBD_CTRL_LED] = { 583184610Salfred .type = UE_CONTROL, 584184610Salfred .endpoint = 0x00, /* Control pipe */ 585184610Salfred .direction = UE_DIR_ANY, 586184610Salfred .mh.bufsize = sizeof(struct usb2_device_request) + 1, 587184610Salfred .mh.callback = &ukbd_set_leds_callback, 588184610Salfred .mh.timeout = 1000, /* 1 second */ 589184610Salfred }, 590184610Salfred}; 591184610Salfred 592184610Salfredstatic int 593184610Salfredukbd_probe(device_t dev) 594184610Salfred{ 595184610Salfred keyboard_switch_t *sw = kbd_get_switch(UKBD_DRIVER_NAME); 596184610Salfred struct usb2_attach_arg *uaa = device_get_ivars(dev); 597184610Salfred 598184610Salfred DPRINTFN(11, "\n"); 599184610Salfred 600184610Salfred if (sw == NULL) { 601184610Salfred return (ENXIO); 602184610Salfred } 603184610Salfred if (uaa->usb2_mode != USB_MODE_HOST) { 604184610Salfred return (ENXIO); 605184610Salfred } 606184610Salfred /* check that the keyboard speaks the boot protocol: */ 607184610Salfred if ((uaa->info.bInterfaceClass == UICLASS_HID) 608184610Salfred && (uaa->info.bInterfaceSubClass == UISUBCLASS_BOOT) 609184610Salfred && (uaa->info.bInterfaceProtocol == UPROTO_BOOT_KEYBOARD)) { 610184610Salfred if (usb2_test_quirk(uaa, UQ_KBD_IGNORE)) 611184610Salfred return (ENXIO); 612184610Salfred else 613184610Salfred return (0); 614184610Salfred } 615184610Salfred return (ENXIO); 616184610Salfred} 617184610Salfred 618184610Salfredstatic int 619184610Salfredukbd_attach(device_t dev) 620184610Salfred{ 621184610Salfred struct ukbd_softc *sc = device_get_softc(dev); 622184610Salfred struct usb2_attach_arg *uaa = device_get_ivars(dev); 623184610Salfred int32_t unit = device_get_unit(dev); 624184610Salfred keyboard_t *kbd = &sc->sc_kbd; 625184610Salfred usb2_error_t err; 626184610Salfred uint16_t n; 627184610Salfred 628184610Salfred if (sc == NULL) { 629184610Salfred return (ENOMEM); 630184610Salfred } 631184610Salfred mtx_assert(&Giant, MA_OWNED); 632184610Salfred 633184610Salfred kbd_init_struct(kbd, UKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0); 634184610Salfred 635184610Salfred kbd->kb_data = (void *)sc; 636184610Salfred 637184610Salfred device_set_usb2_desc(dev); 638184610Salfred 639184610Salfred sc->sc_udev = uaa->device; 640184610Salfred sc->sc_iface = uaa->iface; 641184610Salfred sc->sc_iface_index = uaa->info.bIfaceIndex; 642184610Salfred sc->sc_iface_no = uaa->info.bIfaceNum; 643184610Salfred sc->sc_mode = K_XLATE; 644184610Salfred sc->sc_iface = uaa->iface; 645184610Salfred 646186454Sthompsa usb2_callout_init_mtx(&sc->sc_callout, &Giant, 0); 647184610Salfred 648184610Salfred err = usb2_transfer_setup(uaa->device, 649184610Salfred &uaa->info.bIfaceIndex, sc->sc_xfer, ukbd_config, 650184610Salfred UKBD_N_TRANSFER, sc, &Giant); 651184610Salfred 652184610Salfred if (err) { 653184610Salfred DPRINTF("error=%s\n", usb2_errstr(err)); 654184610Salfred goto detach; 655184610Salfred } 656184610Salfred /* setup default keyboard maps */ 657184610Salfred 658184610Salfred sc->sc_keymap = key_map; 659184610Salfred sc->sc_accmap = accent_map; 660184610Salfred for (n = 0; n < UKBD_NFKEY; n++) { 661184610Salfred sc->sc_fkeymap[n] = fkey_tab[n]; 662184610Salfred } 663184610Salfred 664184610Salfred kbd_set_maps(kbd, &sc->sc_keymap, &sc->sc_accmap, 665184610Salfred sc->sc_fkeymap, UKBD_NFKEY); 666184610Salfred 667184610Salfred KBD_FOUND_DEVICE(kbd); 668184610Salfred 669184610Salfred ukbd_clear_state(kbd); 670184610Salfred 671184610Salfred /* 672184610Salfred * FIXME: set the initial value for lock keys in "sc_state" 673184610Salfred * according to the BIOS data? 674184610Salfred */ 675184610Salfred KBD_PROBE_DONE(kbd); 676184610Salfred 677184610Salfred /* ignore if SETIDLE fails, hence it is not crucial */ 678184610Salfred err = usb2_req_set_idle(sc->sc_udev, &Giant, sc->sc_iface_index, 0, 0); 679184610Salfred 680184610Salfred ukbd_ioctl(kbd, KDSETLED, (caddr_t)&sc->sc_state); 681184610Salfred 682184610Salfred KBD_INIT_DONE(kbd); 683184610Salfred 684184610Salfred if (kbd_register(kbd) < 0) { 685184610Salfred goto detach; 686184610Salfred } 687184610Salfred KBD_CONFIG_DONE(kbd); 688184610Salfred 689184610Salfred ukbd_enable(kbd); 690184610Salfred 691184610Salfred#ifdef KBD_INSTALL_CDEV 692184610Salfred if (kbd_attach(kbd)) { 693184610Salfred goto detach; 694184610Salfred } 695184610Salfred#endif 696184610Salfred sc->sc_flags |= UKBD_FLAG_ATTACHED; 697184610Salfred 698184610Salfred if (bootverbose) { 699184610Salfred genkbd_diag(kbd, bootverbose); 700184610Salfred } 701184610Salfred /* lock keyboard mutex */ 702184610Salfred 703184610Salfred mtx_lock(&Giant); 704184610Salfred 705184610Salfred /* start the keyboard */ 706184610Salfred 707187259Sthompsa usb2_transfer_start(sc->sc_xfer[UKBD_INTR_DT]); 708184610Salfred 709184610Salfred /* start the timer */ 710184610Salfred 711186454Sthompsa ukbd_timeout(sc); 712186454Sthompsa mtx_unlock(&Giant); 713184610Salfred return (0); /* success */ 714184610Salfred 715184610Salfreddetach: 716184610Salfred ukbd_detach(dev); 717184610Salfred return (ENXIO); /* error */ 718184610Salfred} 719184610Salfred 720184610Salfredint 721184610Salfredukbd_detach(device_t dev) 722184610Salfred{ 723184610Salfred struct ukbd_softc *sc = device_get_softc(dev); 724184610Salfred int error; 725184610Salfred 726184610Salfred mtx_assert(&Giant, MA_OWNED); 727184610Salfred 728184610Salfred DPRINTF("\n"); 729184610Salfred 730184610Salfred if (sc->sc_flags & UKBD_FLAG_POLLING) { 731184610Salfred panic("cannot detach polled keyboard!\n"); 732184610Salfred } 733184610Salfred sc->sc_flags |= UKBD_FLAG_GONE; 734184610Salfred 735184610Salfred usb2_callout_stop(&sc->sc_callout); 736184610Salfred 737184610Salfred ukbd_disable(&sc->sc_kbd); 738184610Salfred 739184610Salfred#ifdef KBD_INSTALL_CDEV 740184610Salfred if (sc->sc_flags & UKBD_FLAG_ATTACHED) { 741184610Salfred error = kbd_detach(&sc->sc_kbd); 742184610Salfred if (error) { 743184610Salfred /* usb attach cannot return an error */ 744184610Salfred device_printf(dev, "WARNING: kbd_detach() " 745184610Salfred "returned non-zero! (ignored)\n"); 746184610Salfred } 747184610Salfred } 748184610Salfred#endif 749184610Salfred if (KBD_IS_CONFIGURED(&sc->sc_kbd)) { 750184610Salfred error = kbd_unregister(&sc->sc_kbd); 751184610Salfred if (error) { 752184610Salfred /* usb attach cannot return an error */ 753184610Salfred device_printf(dev, "WARNING: kbd_unregister() " 754184610Salfred "returned non-zero! (ignored)\n"); 755184610Salfred } 756184610Salfred } 757184610Salfred sc->sc_kbd.kb_flags = 0; 758184610Salfred 759184610Salfred usb2_transfer_unsetup(sc->sc_xfer, UKBD_N_TRANSFER); 760184610Salfred 761184610Salfred usb2_callout_drain(&sc->sc_callout); 762184610Salfred 763184610Salfred DPRINTF("%s: disconnected\n", 764184610Salfred device_get_nameunit(dev)); 765184610Salfred 766184610Salfred return (0); 767184610Salfred} 768184610Salfred 769184610Salfredstatic int 770184610Salfredukbd_resume(device_t dev) 771184610Salfred{ 772184610Salfred struct ukbd_softc *sc = device_get_softc(dev); 773184610Salfred 774184610Salfred mtx_assert(&Giant, MA_OWNED); 775184610Salfred 776184610Salfred ukbd_clear_state(&sc->sc_kbd); 777184610Salfred 778184610Salfred return (0); 779184610Salfred} 780184610Salfred 781184610Salfred/* early keyboard probe, not supported */ 782184610Salfredstatic int 783184610Salfredukbd_configure(int flags) 784184610Salfred{ 785184610Salfred return (0); 786184610Salfred} 787184610Salfred 788184610Salfred/* detect a keyboard, not used */ 789184610Salfredstatic int 790184610Salfredukbd__probe(int unit, void *arg, int flags) 791184610Salfred{ 792184610Salfred mtx_assert(&Giant, MA_OWNED); 793184610Salfred return (ENXIO); 794184610Salfred} 795184610Salfred 796184610Salfred/* reset and initialize the device, not used */ 797184610Salfredstatic int 798184610Salfredukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 799184610Salfred{ 800184610Salfred mtx_assert(&Giant, MA_OWNED); 801184610Salfred return (ENXIO); 802184610Salfred} 803184610Salfred 804184610Salfred/* test the interface to the device, not used */ 805184610Salfredstatic int 806184610Salfredukbd_test_if(keyboard_t *kbd) 807184610Salfred{ 808184610Salfred mtx_assert(&Giant, MA_OWNED); 809184610Salfred return (0); 810184610Salfred} 811184610Salfred 812184610Salfred/* finish using this keyboard, not used */ 813184610Salfredstatic int 814184610Salfredukbd_term(keyboard_t *kbd) 815184610Salfred{ 816184610Salfred mtx_assert(&Giant, MA_OWNED); 817184610Salfred return (ENXIO); 818184610Salfred} 819184610Salfred 820184610Salfred/* keyboard interrupt routine, not used */ 821184610Salfredstatic int 822184610Salfredukbd_intr(keyboard_t *kbd, void *arg) 823184610Salfred{ 824184610Salfred mtx_assert(&Giant, MA_OWNED); 825184610Salfred return (0); 826184610Salfred} 827184610Salfred 828184610Salfred/* lock the access to the keyboard, not used */ 829184610Salfredstatic int 830184610Salfredukbd_lock(keyboard_t *kbd, int lock) 831184610Salfred{ 832184610Salfred mtx_assert(&Giant, MA_OWNED); 833184610Salfred return (1); 834184610Salfred} 835184610Salfred 836184610Salfred/* 837184610Salfred * Enable the access to the device; until this function is called, 838184610Salfred * the client cannot read from the keyboard. 839184610Salfred */ 840184610Salfredstatic int 841184610Salfredukbd_enable(keyboard_t *kbd) 842184610Salfred{ 843184610Salfred mtx_assert(&Giant, MA_OWNED); 844184610Salfred KBD_ACTIVATE(kbd); 845184610Salfred return (0); 846184610Salfred} 847184610Salfred 848184610Salfred/* disallow the access to the device */ 849184610Salfredstatic int 850184610Salfredukbd_disable(keyboard_t *kbd) 851184610Salfred{ 852184610Salfred mtx_assert(&Giant, MA_OWNED); 853184610Salfred KBD_DEACTIVATE(kbd); 854184610Salfred return (0); 855184610Salfred} 856184610Salfred 857184610Salfred/* check if data is waiting */ 858184610Salfredstatic int 859184610Salfredukbd_check(keyboard_t *kbd) 860184610Salfred{ 861184610Salfred struct ukbd_softc *sc = kbd->kb_data; 862184610Salfred 863184610Salfred if (!mtx_owned(&Giant)) { 864184610Salfred return (0); /* XXX */ 865184610Salfred } 866184610Salfred mtx_assert(&Giant, MA_OWNED); 867184610Salfred 868184610Salfred if (!KBD_IS_ACTIVE(kbd)) { 869184610Salfred return (0); 870184610Salfred } 871184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 872184610Salfred if (sc->sc_buffered_char[0]) { 873184610Salfred return (1); 874184610Salfred } 875184610Salfred#endif 876184610Salfred if (sc->sc_inputs > 0) { 877184610Salfred return (1); 878184610Salfred } 879184610Salfred return (0); 880184610Salfred} 881184610Salfred 882184610Salfred/* check if char is waiting */ 883184610Salfredstatic int 884184610Salfredukbd_check_char(keyboard_t *kbd) 885184610Salfred{ 886184610Salfred struct ukbd_softc *sc = kbd->kb_data; 887184610Salfred 888184610Salfred if (!mtx_owned(&Giant)) { 889184610Salfred return (0); /* XXX */ 890184610Salfred } 891184610Salfred mtx_assert(&Giant, MA_OWNED); 892184610Salfred 893184610Salfred if (!KBD_IS_ACTIVE(kbd)) { 894184610Salfred return (0); 895184610Salfred } 896184610Salfred if ((sc->sc_composed_char > 0) && 897184610Salfred (!(sc->sc_flags & UKBD_FLAG_COMPOSE))) { 898184610Salfred return (1); 899184610Salfred } 900184610Salfred return (ukbd_check(kbd)); 901184610Salfred} 902184610Salfred 903184610Salfred 904184610Salfred/* read one byte from the keyboard if it's allowed */ 905184610Salfredstatic int 906184610Salfredukbd_read(keyboard_t *kbd, int wait) 907184610Salfred{ 908184610Salfred struct ukbd_softc *sc = kbd->kb_data; 909184610Salfred int32_t usbcode; 910184610Salfred 911184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 912184610Salfred uint32_t keycode; 913184610Salfred uint32_t scancode; 914184610Salfred 915184610Salfred#endif 916184610Salfred 917184610Salfred if (!mtx_owned(&Giant)) { 918184610Salfred return -1; /* XXX */ 919184610Salfred } 920184610Salfred mtx_assert(&Giant, MA_OWNED); 921184610Salfred 922184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 923184610Salfred if (sc->sc_buffered_char[0]) { 924184610Salfred scancode = sc->sc_buffered_char[0]; 925184610Salfred if (scancode & SCAN_PREFIX) { 926184610Salfred sc->sc_buffered_char[0] &= ~SCAN_PREFIX; 927184610Salfred return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); 928184610Salfred } 929184610Salfred sc->sc_buffered_char[0] = sc->sc_buffered_char[1]; 930184610Salfred sc->sc_buffered_char[1] = 0; 931184610Salfred return (scancode); 932184610Salfred } 933184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 934184610Salfred 935184610Salfred /* XXX */ 936184610Salfred usbcode = ukbd_get_key(sc, (wait == FALSE) ? 0 : 1); 937184610Salfred if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) { 938184610Salfred return -1; 939184610Salfred } 940184610Salfred ++(kbd->kb_count); 941184610Salfred 942184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 943184610Salfred keycode = ukbd_trtab[KEY_INDEX(usbcode)]; 944184610Salfred if (keycode == NN) { 945184610Salfred return -1; 946184610Salfred } 947184610Salfred return (ukbd_key2scan(sc, keycode, sc->sc_ndata.modifiers, 948184610Salfred (usbcode & KEY_RELEASE))); 949184610Salfred#else /* !UKBD_EMULATE_ATSCANCODE */ 950184610Salfred return (usbcode); 951184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 952184610Salfred} 953184610Salfred 954184610Salfred/* read char from the keyboard */ 955184610Salfredstatic uint32_t 956184610Salfredukbd_read_char(keyboard_t *kbd, int wait) 957184610Salfred{ 958184610Salfred struct ukbd_softc *sc = kbd->kb_data; 959184610Salfred uint32_t action; 960184610Salfred uint32_t keycode; 961184610Salfred int32_t usbcode; 962184610Salfred 963184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 964184610Salfred uint32_t scancode; 965184610Salfred 966184610Salfred#endif 967184610Salfred if (!mtx_owned(&Giant)) { 968184610Salfred return (NOKEY); /* XXX */ 969184610Salfred } 970184610Salfred mtx_assert(&Giant, MA_OWNED); 971184610Salfred 972184610Salfrednext_code: 973184610Salfred 974184610Salfred /* do we have a composed char to return ? */ 975184610Salfred 976184610Salfred if ((sc->sc_composed_char > 0) && 977184610Salfred (!(sc->sc_flags & UKBD_FLAG_COMPOSE))) { 978184610Salfred 979184610Salfred action = sc->sc_composed_char; 980184610Salfred sc->sc_composed_char = 0; 981184610Salfred 982184610Salfred if (action > 0xFF) { 983184610Salfred goto errkey; 984184610Salfred } 985184610Salfred goto done; 986184610Salfred } 987184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 988184610Salfred 989184610Salfred /* do we have a pending raw scan code? */ 990184610Salfred 991184610Salfred if (sc->sc_mode == K_RAW) { 992184610Salfred scancode = sc->sc_buffered_char[0]; 993184610Salfred if (scancode) { 994184610Salfred if (scancode & SCAN_PREFIX) { 995184610Salfred sc->sc_buffered_char[0] = (scancode & ~SCAN_PREFIX); 996184610Salfred return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); 997184610Salfred } 998184610Salfred sc->sc_buffered_char[0] = sc->sc_buffered_char[1]; 999184610Salfred sc->sc_buffered_char[1] = 0; 1000184610Salfred return (scancode); 1001184610Salfred } 1002184610Salfred } 1003184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 1004184610Salfred 1005184610Salfred /* see if there is something in the keyboard port */ 1006184610Salfred /* XXX */ 1007184610Salfred usbcode = ukbd_get_key(sc, (wait == FALSE) ? 0 : 1); 1008184610Salfred if (usbcode == -1) { 1009184610Salfred return (NOKEY); 1010184610Salfred } 1011184610Salfred ++kbd->kb_count; 1012184610Salfred 1013184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1014184610Salfred /* USB key index -> key code -> AT scan code */ 1015184610Salfred keycode = ukbd_trtab[KEY_INDEX(usbcode)]; 1016184610Salfred if (keycode == NN) { 1017184610Salfred return (NOKEY); 1018184610Salfred } 1019184610Salfred /* return an AT scan code for the K_RAW mode */ 1020184610Salfred if (sc->sc_mode == K_RAW) { 1021184610Salfred return (ukbd_key2scan(sc, keycode, sc->sc_ndata.modifiers, 1022184610Salfred (usbcode & KEY_RELEASE))); 1023184610Salfred } 1024184610Salfred#else /* !UKBD_EMULATE_ATSCANCODE */ 1025184610Salfred 1026184610Salfred /* return the byte as is for the K_RAW mode */ 1027184610Salfred if (sc->sc_mode == K_RAW) { 1028184610Salfred return (usbcode); 1029184610Salfred } 1030184610Salfred /* USB key index -> key code */ 1031184610Salfred keycode = ukbd_trtab[KEY_INDEX(usbcode)]; 1032184610Salfred if (keycode == NN) { 1033184610Salfred return (NOKEY); 1034184610Salfred } 1035184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 1036184610Salfred 1037184610Salfred switch (keycode) { 1038184610Salfred case 0x38: /* left alt (compose key) */ 1039184610Salfred if (usbcode & KEY_RELEASE) { 1040184610Salfred if (sc->sc_flags & UKBD_FLAG_COMPOSE) { 1041184610Salfred sc->sc_flags &= ~UKBD_FLAG_COMPOSE; 1042184610Salfred 1043184610Salfred if (sc->sc_composed_char > 0xFF) { 1044184610Salfred sc->sc_composed_char = 0; 1045184610Salfred } 1046184610Salfred } 1047184610Salfred } else { 1048184610Salfred if (!(sc->sc_flags & UKBD_FLAG_COMPOSE)) { 1049184610Salfred sc->sc_flags |= UKBD_FLAG_COMPOSE; 1050184610Salfred sc->sc_composed_char = 0; 1051184610Salfred } 1052184610Salfred } 1053184610Salfred break; 1054184610Salfred /* XXX: I don't like these... */ 1055184610Salfred case 0x5c: /* print screen */ 1056184610Salfred if (sc->sc_flags & ALTS) { 1057184610Salfred keycode = 0x54; /* sysrq */ 1058184610Salfred } 1059184610Salfred break; 1060184610Salfred case 0x68: /* pause/break */ 1061184610Salfred if (sc->sc_flags & CTLS) { 1062184610Salfred keycode = 0x6c; /* break */ 1063184610Salfred } 1064184610Salfred break; 1065184610Salfred } 1066184610Salfred 1067184610Salfred /* return the key code in the K_CODE mode */ 1068184610Salfred if (usbcode & KEY_RELEASE) { 1069184610Salfred keycode |= SCAN_RELEASE; 1070184610Salfred } 1071184610Salfred if (sc->sc_mode == K_CODE) { 1072184610Salfred return (keycode); 1073184610Salfred } 1074184610Salfred /* compose a character code */ 1075184610Salfred if (sc->sc_flags & UKBD_FLAG_COMPOSE) { 1076184610Salfred switch (keycode) { 1077184610Salfred /* key pressed, process it */ 1078184610Salfred case 0x47: 1079184610Salfred case 0x48: 1080184610Salfred case 0x49: /* keypad 7,8,9 */ 1081184610Salfred sc->sc_composed_char *= 10; 1082184610Salfred sc->sc_composed_char += keycode - 0x40; 1083184610Salfred goto check_composed; 1084184610Salfred 1085184610Salfred case 0x4B: 1086184610Salfred case 0x4C: 1087184610Salfred case 0x4D: /* keypad 4,5,6 */ 1088184610Salfred sc->sc_composed_char *= 10; 1089184610Salfred sc->sc_composed_char += keycode - 0x47; 1090184610Salfred goto check_composed; 1091184610Salfred 1092184610Salfred case 0x4F: 1093184610Salfred case 0x50: 1094184610Salfred case 0x51: /* keypad 1,2,3 */ 1095184610Salfred sc->sc_composed_char *= 10; 1096184610Salfred sc->sc_composed_char += keycode - 0x4E; 1097184610Salfred goto check_composed; 1098184610Salfred 1099184610Salfred case 0x52: /* keypad 0 */ 1100184610Salfred sc->sc_composed_char *= 10; 1101184610Salfred goto check_composed; 1102184610Salfred 1103184610Salfred /* key released, no interest here */ 1104184610Salfred case SCAN_RELEASE | 0x47: 1105184610Salfred case SCAN_RELEASE | 0x48: 1106184610Salfred case SCAN_RELEASE | 0x49: /* keypad 7,8,9 */ 1107184610Salfred case SCAN_RELEASE | 0x4B: 1108184610Salfred case SCAN_RELEASE | 0x4C: 1109184610Salfred case SCAN_RELEASE | 0x4D: /* keypad 4,5,6 */ 1110184610Salfred case SCAN_RELEASE | 0x4F: 1111184610Salfred case SCAN_RELEASE | 0x50: 1112184610Salfred case SCAN_RELEASE | 0x51: /* keypad 1,2,3 */ 1113184610Salfred case SCAN_RELEASE | 0x52: /* keypad 0 */ 1114184610Salfred goto next_code; 1115184610Salfred 1116184610Salfred case 0x38: /* left alt key */ 1117184610Salfred break; 1118184610Salfred 1119184610Salfred default: 1120184610Salfred if (sc->sc_composed_char > 0) { 1121184610Salfred sc->sc_flags &= ~UKBD_FLAG_COMPOSE; 1122184610Salfred sc->sc_composed_char = 0; 1123184610Salfred goto errkey; 1124184610Salfred } 1125184610Salfred break; 1126184610Salfred } 1127184610Salfred } 1128184610Salfred /* keycode to key action */ 1129184610Salfred action = genkbd_keyaction(kbd, SCAN_CHAR(keycode), 1130184610Salfred (keycode & SCAN_RELEASE), 1131184610Salfred &sc->sc_state, &sc->sc_accents); 1132184610Salfred if (action == NOKEY) { 1133184610Salfred goto next_code; 1134184610Salfred } 1135184610Salfreddone: 1136184610Salfred return (action); 1137184610Salfred 1138184610Salfredcheck_composed: 1139184610Salfred if (sc->sc_composed_char <= 0xFF) { 1140184610Salfred goto next_code; 1141184610Salfred } 1142184610Salfrederrkey: 1143184610Salfred return (ERRKEY); 1144184610Salfred} 1145184610Salfred 1146184610Salfred/* some useful control functions */ 1147184610Salfredstatic int 1148184610Salfredukbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 1149184610Salfred{ 1150184610Salfred /* translate LED_XXX bits into the device specific bits */ 1151184610Salfred static const uint8_t ledmap[8] = { 1152184610Salfred 0, 2, 1, 3, 4, 6, 5, 7, 1153184610Salfred }; 1154184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1155184610Salfred int i; 1156184610Salfred 1157184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1158184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1159184610Salfred int ival; 1160184610Salfred 1161184610Salfred#endif 1162184610Salfred if (!mtx_owned(&Giant)) { 1163184610Salfred /* 1164184610Salfred * XXX big problem: If scroll lock is pressed and "printf()" 1165184610Salfred * is called, the CPU will get here, to un-scroll lock the 1166184610Salfred * keyboard. But if "printf()" acquires the "Giant" lock, 1167184610Salfred * there will be a locking order reversal problem, so the 1168184610Salfred * keyboard system must get out of "Giant" first, before the 1169184610Salfred * CPU can proceed here ... 1170184610Salfred */ 1171184610Salfred return (EINVAL); 1172184610Salfred } 1173184610Salfred mtx_assert(&Giant, MA_OWNED); 1174184610Salfred 1175184610Salfred switch (cmd) { 1176184610Salfred case KDGKBMODE: /* get keyboard mode */ 1177184610Salfred *(int *)arg = sc->sc_mode; 1178184610Salfred break; 1179184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1180184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1181184610Salfred case _IO('K', 7): 1182184610Salfred ival = IOCPARM_IVAL(arg); 1183184610Salfred arg = (caddr_t)&ival; 1184184610Salfred /* FALLTHROUGH */ 1185184610Salfred#endif 1186184610Salfred case KDSKBMODE: /* set keyboard mode */ 1187184610Salfred switch (*(int *)arg) { 1188184610Salfred case K_XLATE: 1189184610Salfred if (sc->sc_mode != K_XLATE) { 1190184610Salfred /* make lock key state and LED state match */ 1191184610Salfred sc->sc_state &= ~LOCK_MASK; 1192184610Salfred sc->sc_state |= KBD_LED_VAL(kbd); 1193184610Salfred } 1194184610Salfred /* FALLTHROUGH */ 1195184610Salfred case K_RAW: 1196184610Salfred case K_CODE: 1197184610Salfred if (sc->sc_mode != *(int *)arg) { 1198184610Salfred ukbd_clear_state(kbd); 1199184610Salfred sc->sc_mode = *(int *)arg; 1200184610Salfred } 1201184610Salfred break; 1202184610Salfred default: 1203184610Salfred return (EINVAL); 1204184610Salfred } 1205184610Salfred break; 1206184610Salfred 1207184610Salfred case KDGETLED: /* get keyboard LED */ 1208184610Salfred *(int *)arg = KBD_LED_VAL(kbd); 1209184610Salfred break; 1210184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1211184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1212184610Salfred case _IO('K', 66): 1213184610Salfred ival = IOCPARM_IVAL(arg); 1214184610Salfred arg = (caddr_t)&ival; 1215184610Salfred /* FALLTHROUGH */ 1216184610Salfred#endif 1217184610Salfred case KDSETLED: /* set keyboard LED */ 1218184610Salfred /* NOTE: lock key state in "sc_state" won't be changed */ 1219184610Salfred if (*(int *)arg & ~LOCK_MASK) { 1220184610Salfred return (EINVAL); 1221184610Salfred } 1222184610Salfred i = *(int *)arg; 1223184610Salfred /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ 1224184610Salfred if (sc->sc_mode == K_XLATE && 1225184610Salfred kbd->kb_keymap->n_keys > ALTGR_OFFSET) { 1226184610Salfred if (i & ALKED) 1227184610Salfred i |= CLKED; 1228184610Salfred else 1229184610Salfred i &= ~CLKED; 1230184610Salfred } 1231184610Salfred if (KBD_HAS_DEVICE(kbd)) { 1232184610Salfred ukbd_set_leds(sc, ledmap[i & LED_MASK]); 1233184610Salfred } 1234184610Salfred KBD_LED_VAL(kbd) = *(int *)arg; 1235184610Salfred break; 1236184610Salfred case KDGKBSTATE: /* get lock key state */ 1237184610Salfred *(int *)arg = sc->sc_state & LOCK_MASK; 1238184610Salfred break; 1239184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1240184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1241184610Salfred case _IO('K', 20): 1242184610Salfred ival = IOCPARM_IVAL(arg); 1243184610Salfred arg = (caddr_t)&ival; 1244184610Salfred /* FALLTHROUGH */ 1245184610Salfred#endif 1246184610Salfred case KDSKBSTATE: /* set lock key state */ 1247184610Salfred if (*(int *)arg & ~LOCK_MASK) { 1248184610Salfred return (EINVAL); 1249184610Salfred } 1250184610Salfred sc->sc_state &= ~LOCK_MASK; 1251184610Salfred sc->sc_state |= *(int *)arg; 1252184610Salfred 1253184610Salfred /* set LEDs and quit */ 1254184610Salfred return (ukbd_ioctl(kbd, KDSETLED, arg)); 1255184610Salfred 1256184610Salfred case KDSETREPEAT: /* set keyboard repeat rate (new 1257184610Salfred * interface) */ 1258184610Salfred if (!KBD_HAS_DEVICE(kbd)) { 1259184610Salfred return (0); 1260184610Salfred } 1261184610Salfred if (((int *)arg)[1] < 0) { 1262184610Salfred return (EINVAL); 1263184610Salfred } 1264184610Salfred if (((int *)arg)[0] < 0) { 1265184610Salfred return (EINVAL); 1266184610Salfred } 1267184610Salfred if (((int *)arg)[0] < 200) /* fastest possible value */ 1268184610Salfred kbd->kb_delay1 = 200; 1269184610Salfred else 1270184610Salfred kbd->kb_delay1 = ((int *)arg)[0]; 1271184610Salfred kbd->kb_delay2 = ((int *)arg)[1]; 1272184610Salfred return (0); 1273184610Salfred 1274184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1275184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1276184610Salfred case _IO('K', 67): 1277184610Salfred ival = IOCPARM_IVAL(arg); 1278184610Salfred arg = (caddr_t)&ival; 1279184610Salfred /* FALLTHROUGH */ 1280184610Salfred#endif 1281184610Salfred case KDSETRAD: /* set keyboard repeat rate (old 1282184610Salfred * interface) */ 1283184610Salfred return (ukbd_set_typematic(kbd, *(int *)arg)); 1284184610Salfred 1285184610Salfred case PIO_KEYMAP: /* set keyboard translation table */ 1286184610Salfred case PIO_KEYMAPENT: /* set keyboard translation table 1287184610Salfred * entry */ 1288184610Salfred case PIO_DEADKEYMAP: /* set accent key translation table */ 1289184610Salfred sc->sc_accents = 0; 1290184610Salfred /* FALLTHROUGH */ 1291184610Salfred default: 1292184610Salfred return (genkbd_commonioctl(kbd, cmd, arg)); 1293184610Salfred } 1294184610Salfred 1295184610Salfred return (0); 1296184610Salfred} 1297184610Salfred 1298184610Salfred/* clear the internal state of the keyboard */ 1299184610Salfredstatic void 1300184610Salfredukbd_clear_state(keyboard_t *kbd) 1301184610Salfred{ 1302184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1303184610Salfred 1304184610Salfred if (!mtx_owned(&Giant)) { 1305184610Salfred return; /* XXX */ 1306184610Salfred } 1307184610Salfred mtx_assert(&Giant, MA_OWNED); 1308184610Salfred 1309184610Salfred sc->sc_flags &= ~(UKBD_FLAG_COMPOSE | UKBD_FLAG_POLLING); 1310184610Salfred sc->sc_state &= LOCK_MASK; /* preserve locking key state */ 1311184610Salfred sc->sc_accents = 0; 1312184610Salfred sc->sc_composed_char = 0; 1313184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1314184610Salfred sc->sc_buffered_char[0] = 0; 1315184610Salfred sc->sc_buffered_char[1] = 0; 1316184610Salfred#endif 1317184610Salfred bzero(&sc->sc_ndata, sizeof(sc->sc_ndata)); 1318184610Salfred bzero(&sc->sc_odata, sizeof(sc->sc_odata)); 1319184610Salfred bzero(&sc->sc_ntime, sizeof(sc->sc_ntime)); 1320184610Salfred bzero(&sc->sc_otime, sizeof(sc->sc_otime)); 1321184610Salfred} 1322184610Salfred 1323184610Salfred/* save the internal state, not used */ 1324184610Salfredstatic int 1325184610Salfredukbd_get_state(keyboard_t *kbd, void *buf, size_t len) 1326184610Salfred{ 1327184610Salfred mtx_assert(&Giant, MA_OWNED); 1328184610Salfred return (len == 0) ? 1 : -1; 1329184610Salfred} 1330184610Salfred 1331184610Salfred/* set the internal state, not used */ 1332184610Salfredstatic int 1333184610Salfredukbd_set_state(keyboard_t *kbd, void *buf, size_t len) 1334184610Salfred{ 1335184610Salfred mtx_assert(&Giant, MA_OWNED); 1336184610Salfred return (EINVAL); 1337184610Salfred} 1338184610Salfred 1339184610Salfredstatic int 1340184610Salfredukbd_poll(keyboard_t *kbd, int on) 1341184610Salfred{ 1342184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1343184610Salfred 1344184610Salfred if (!mtx_owned(&Giant)) { 1345184610Salfred return (0); /* XXX */ 1346184610Salfred } 1347184610Salfred mtx_assert(&Giant, MA_OWNED); 1348184610Salfred 1349184610Salfred if (on) { 1350184610Salfred sc->sc_flags |= UKBD_FLAG_POLLING; 1351184610Salfred } else { 1352184610Salfred sc->sc_flags &= ~UKBD_FLAG_POLLING; 1353184610Salfred } 1354184610Salfred return (0); 1355184610Salfred} 1356184610Salfred 1357184610Salfred/* local functions */ 1358184610Salfred 1359184610Salfredstatic void 1360184610Salfredukbd_set_leds(struct ukbd_softc *sc, uint8_t leds) 1361184610Salfred{ 1362184610Salfred DPRINTF("leds=0x%02x\n", leds); 1363184610Salfred 1364184610Salfred sc->sc_leds = leds; 1365184610Salfred sc->sc_flags |= UKBD_FLAG_SET_LEDS; 1366184610Salfred 1367184610Salfred /* start transfer, if not already started */ 1368184610Salfred 1369187259Sthompsa usb2_transfer_start(sc->sc_xfer[UKBD_CTRL_LED]); 1370184610Salfred} 1371184610Salfred 1372184610Salfredstatic int 1373184610Salfredukbd_set_typematic(keyboard_t *kbd, int code) 1374184610Salfred{ 1375184610Salfred static const int delays[] = {250, 500, 750, 1000}; 1376184610Salfred static const int rates[] = {34, 38, 42, 46, 50, 55, 59, 63, 1377184610Salfred 68, 76, 84, 92, 100, 110, 118, 126, 1378184610Salfred 136, 152, 168, 184, 200, 220, 236, 252, 1379184610Salfred 272, 304, 336, 368, 400, 440, 472, 504}; 1380184610Salfred 1381184610Salfred if (code & ~0x7f) { 1382184610Salfred return (EINVAL); 1383184610Salfred } 1384184610Salfred kbd->kb_delay1 = delays[(code >> 5) & 3]; 1385184610Salfred kbd->kb_delay2 = rates[code & 0x1f]; 1386184610Salfred return (0); 1387184610Salfred} 1388184610Salfred 1389184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1390184610Salfredstatic int 1391184610Salfredukbd_key2scan(struct ukbd_softc *sc, int code, int shift, int up) 1392184610Salfred{ 1393184610Salfred static const int scan[] = { 1394184610Salfred 0x1c, 0x1d, 0x35, 1395184610Salfred 0x37 | SCAN_PREFIX_SHIFT, /* PrintScreen */ 1396184610Salfred 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f, 1397184610Salfred 0x50, 0x51, 0x52, 0x53, 1398184610Salfred 0x46, /* XXX Pause/Break */ 1399184610Salfred 0x5b, 0x5c, 0x5d, 1400184610Salfred /* SUN TYPE 6 USB KEYBOARD */ 1401184610Salfred 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 1402184610Salfred 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e, 1403184610Salfred 0x20, 1404184610Salfred }; 1405184610Salfred 1406184610Salfred if ((code >= 89) && (code < (89 + (sizeof(scan) / sizeof(scan[0]))))) { 1407184610Salfred code = scan[code - 89] | SCAN_PREFIX_E0; 1408184610Salfred } 1409184610Salfred /* Pause/Break */ 1410184610Salfred if ((code == 104) && (!(shift & (MOD_CONTROL_L | MOD_CONTROL_R)))) { 1411184610Salfred code = (0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL); 1412184610Salfred } 1413184610Salfred if (shift & (MOD_SHIFT_L | MOD_SHIFT_R)) { 1414184610Salfred code &= ~SCAN_PREFIX_SHIFT; 1415184610Salfred } 1416184610Salfred code |= (up ? SCAN_RELEASE : SCAN_PRESS); 1417184610Salfred 1418184610Salfred if (code & SCAN_PREFIX) { 1419184610Salfred if (code & SCAN_PREFIX_CTL) { 1420184610Salfred /* Ctrl */ 1421184610Salfred sc->sc_buffered_char[0] = (0x1d | (code & SCAN_RELEASE)); 1422184610Salfred sc->sc_buffered_char[1] = (code & ~SCAN_PREFIX); 1423184610Salfred } else if (code & SCAN_PREFIX_SHIFT) { 1424184610Salfred /* Shift */ 1425184610Salfred sc->sc_buffered_char[0] = (0x2a | (code & SCAN_RELEASE)); 1426184610Salfred sc->sc_buffered_char[1] = (code & ~SCAN_PREFIX_SHIFT); 1427184610Salfred } else { 1428184610Salfred sc->sc_buffered_char[0] = (code & ~SCAN_PREFIX); 1429184610Salfred sc->sc_buffered_char[1] = 0; 1430184610Salfred } 1431184610Salfred return ((code & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); 1432184610Salfred } 1433184610Salfred return (code); 1434184610Salfred 1435184610Salfred} 1436184610Salfred 1437184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 1438184610Salfred 1439184610Salfredkeyboard_switch_t ukbdsw = { 1440184610Salfred .probe = &ukbd__probe, 1441184610Salfred .init = &ukbd_init, 1442184610Salfred .term = &ukbd_term, 1443184610Salfred .intr = &ukbd_intr, 1444184610Salfred .test_if = &ukbd_test_if, 1445184610Salfred .enable = &ukbd_enable, 1446184610Salfred .disable = &ukbd_disable, 1447184610Salfred .read = &ukbd_read, 1448184610Salfred .check = &ukbd_check, 1449184610Salfred .read_char = &ukbd_read_char, 1450184610Salfred .check_char = &ukbd_check_char, 1451184610Salfred .ioctl = &ukbd_ioctl, 1452184610Salfred .lock = &ukbd_lock, 1453184610Salfred .clear_state = &ukbd_clear_state, 1454184610Salfred .get_state = &ukbd_get_state, 1455184610Salfred .set_state = &ukbd_set_state, 1456184610Salfred .get_fkeystr = &genkbd_get_fkeystr, 1457184610Salfred .poll = &ukbd_poll, 1458184610Salfred .diag = &genkbd_diag, 1459184610Salfred}; 1460184610Salfred 1461184610SalfredKEYBOARD_DRIVER(ukbd, ukbdsw, ukbd_configure); 1462184610Salfred 1463184610Salfredstatic int 1464184610Salfredukbd_driver_load(module_t mod, int what, void *arg) 1465184610Salfred{ 1466184610Salfred switch (what) { 1467184610Salfred case MOD_LOAD: 1468184610Salfred kbd_add_driver(&ukbd_kbd_driver); 1469184610Salfred break; 1470184610Salfred case MOD_UNLOAD: 1471184610Salfred kbd_delete_driver(&ukbd_kbd_driver); 1472184610Salfred break; 1473184610Salfred } 1474184610Salfred return (0); 1475184610Salfred} 1476184610Salfred 1477184610Salfredstatic devclass_t ukbd_devclass; 1478184610Salfred 1479184610Salfredstatic device_method_t ukbd_methods[] = { 1480184610Salfred DEVMETHOD(device_probe, ukbd_probe), 1481184610Salfred DEVMETHOD(device_attach, ukbd_attach), 1482184610Salfred DEVMETHOD(device_detach, ukbd_detach), 1483184610Salfred DEVMETHOD(device_resume, ukbd_resume), 1484184610Salfred {0, 0} 1485184610Salfred}; 1486184610Salfred 1487184610Salfredstatic driver_t ukbd_driver = { 1488184610Salfred .name = "ukbd", 1489184610Salfred .methods = ukbd_methods, 1490184610Salfred .size = sizeof(struct ukbd_softc), 1491184610Salfred}; 1492184610Salfred 1493184610SalfredDRIVER_MODULE(ukbd, ushub, ukbd_driver, ukbd_devclass, ukbd_driver_load, 0); 1494184610SalfredMODULE_DEPEND(ukbd, usb2_input, 1, 1, 1); 1495184610SalfredMODULE_DEPEND(ukbd, usb2_core, 1, 1, 1); 1496