1184610Salfred#include <sys/cdefs.h> 2184610Salfred__FBSDID("$FreeBSD: stable/11/sys/dev/usb/input/ukbd.c 359559 2020-04-02 07:42:29Z hselasky $"); 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 * 22184610Salfred * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23184610Salfred * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24184610Salfred * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25184610Salfred * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26184610Salfred * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27184610Salfred * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28184610Salfred * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29184610Salfred * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30184610Salfred * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31184610Salfred * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32184610Salfred * POSSIBILITY OF SUCH DAMAGE. 33184610Salfred * 34184610Salfred */ 35184610Salfred 36184610Salfred/* 37184610Salfred * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 38184610Salfred */ 39184610Salfred 40184610Salfred#include "opt_compat.h" 41184610Salfred#include "opt_kbd.h" 42184610Salfred#include "opt_ukbd.h" 43307764Sgonzo#include "opt_evdev.h" 44184610Salfred 45194677Sthompsa#include <sys/stdint.h> 46194677Sthompsa#include <sys/stddef.h> 47194677Sthompsa#include <sys/param.h> 48194677Sthompsa#include <sys/queue.h> 49194677Sthompsa#include <sys/types.h> 50194677Sthompsa#include <sys/systm.h> 51194677Sthompsa#include <sys/kernel.h> 52194677Sthompsa#include <sys/bus.h> 53194677Sthompsa#include <sys/module.h> 54194677Sthompsa#include <sys/lock.h> 55194677Sthompsa#include <sys/mutex.h> 56194677Sthompsa#include <sys/condvar.h> 57194677Sthompsa#include <sys/sysctl.h> 58194677Sthompsa#include <sys/sx.h> 59194677Sthompsa#include <sys/unistd.h> 60194677Sthompsa#include <sys/callout.h> 61194677Sthompsa#include <sys/malloc.h> 62194677Sthompsa#include <sys/priv.h> 63223989Shselasky#include <sys/proc.h> 64223989Shselasky#include <sys/sched.h> 65198152Sthompsa#include <sys/kdb.h> 66194677Sthompsa 67188942Sthompsa#include <dev/usb/usb.h> 68194677Sthompsa#include <dev/usb/usbdi.h> 69194677Sthompsa#include <dev/usb/usbdi_util.h> 70188942Sthompsa#include <dev/usb/usbhid.h> 71184610Salfred 72184610Salfred#define USB_DEBUG_VAR ukbd_debug 73188942Sthompsa#include <dev/usb/usb_debug.h> 74184610Salfred 75188942Sthompsa#include <dev/usb/quirk/usb_quirk.h> 76184610Salfred 77307775Sgonzo#ifdef EVDEV_SUPPORT 78307764Sgonzo#include <dev/evdev/input.h> 79307764Sgonzo#include <dev/evdev/evdev.h> 80307764Sgonzo#endif 81307764Sgonzo 82184610Salfred#include <sys/ioccom.h> 83184610Salfred#include <sys/filio.h> 84184610Salfred#include <sys/kbio.h> 85184610Salfred 86184610Salfred#include <dev/kbd/kbdreg.h> 87184610Salfred 88184610Salfred/* the initial key map, accent map and fkey strings */ 89184610Salfred#if defined(UKBD_DFLT_KEYMAP) && !defined(KLD_MODULE) 90184610Salfred#define KBD_DFLT_KEYMAP 91184610Salfred#include "ukbdmap.h" 92184610Salfred#endif 93184610Salfred 94184610Salfred/* the following file must be included after "ukbdmap.h" */ 95184610Salfred#include <dev/kbd/kbdtables.h> 96184610Salfred 97207077Sthompsa#ifdef USB_DEBUG 98184610Salfredstatic int ukbd_debug = 0; 99196489Salfredstatic int ukbd_no_leds = 0; 100253332Shselaskystatic int ukbd_pollrate = 0; 101184610Salfred 102253332Shselaskystatic SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW, 0, "USB keyboard"); 103267992ShselaskySYSCTL_INT(_hw_usb_ukbd, OID_AUTO, debug, CTLFLAG_RWTUN, 104184610Salfred &ukbd_debug, 0, "Debug level"); 105267992ShselaskySYSCTL_INT(_hw_usb_ukbd, OID_AUTO, no_leds, CTLFLAG_RWTUN, 106196489Salfred &ukbd_no_leds, 0, "Disables setting of keyboard leds"); 107267992ShselaskySYSCTL_INT(_hw_usb_ukbd, OID_AUTO, pollrate, CTLFLAG_RWTUN, 108253332Shselasky &ukbd_pollrate, 0, "Force this polling rate, 1-1000Hz"); 109184610Salfred#endif 110184610Salfred 111184610Salfred#define UKBD_EMULATE_ATSCANCODE 1 112184610Salfred#define UKBD_DRIVER_NAME "ukbd" 113358216Shselasky#define UKBD_NKEYCODE 256 /* units */ 114358216Shselasky#define UKBD_IN_BUF_SIZE (4 * UKBD_NKEYCODE) /* scancodes */ 115358216Shselasky#define UKBD_IN_BUF_FULL ((UKBD_IN_BUF_SIZE / 2) - 1) /* scancodes */ 116184610Salfred#define UKBD_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */ 117223755Shselasky#define UKBD_BUFFER_SIZE 64 /* bytes */ 118358216Shselasky#define UKBD_KEY_PRESSED(map, key) ({ \ 119358216Shselasky CTASSERT((key) >= 0 && (key) < UKBD_NKEYCODE); \ 120358216Shselasky ((map)[(key) / 64] & (1ULL << ((key) % 64))); \ 121358216Shselasky}) 122184610Salfred 123358216Shselasky#define MOD_EJECT 0x01 124358216Shselasky#define MOD_FN 0x02 125358216Shselasky 126184610Salfredstruct ukbd_data { 127358216Shselasky uint64_t bitmap[howmany(UKBD_NKEYCODE, 64)]; 128192925Sthompsa}; 129184610Salfred 130187259Sthompsaenum { 131305644Shselasky UKBD_INTR_DT_0, 132305644Shselasky UKBD_INTR_DT_1, 133187259Sthompsa UKBD_CTRL_LED, 134192925Sthompsa UKBD_N_TRANSFER, 135187259Sthompsa}; 136187259Sthompsa 137184610Salfredstruct ukbd_softc { 138184610Salfred keyboard_t sc_kbd; 139184610Salfred keymap_t sc_keymap; 140184610Salfred accentmap_t sc_accmap; 141184610Salfred fkeytab_t sc_fkeymap[UKBD_NFKEY]; 142358216Shselasky uint64_t sc_loc_key_valid[howmany(UKBD_NKEYCODE, 64)]; 143192925Sthompsa struct hid_location sc_loc_apple_eject; 144192925Sthompsa struct hid_location sc_loc_apple_fn; 145358216Shselasky struct hid_location sc_loc_key[UKBD_NKEYCODE]; 146223755Shselasky struct hid_location sc_loc_numlock; 147223755Shselasky struct hid_location sc_loc_capslock; 148223755Shselasky struct hid_location sc_loc_scrolllock; 149192984Sthompsa struct usb_callout sc_callout; 150184610Salfred struct ukbd_data sc_ndata; 151184610Salfred struct ukbd_data sc_odata; 152184610Salfred 153203896Sthompsa struct thread *sc_poll_thread; 154192984Sthompsa struct usb_device *sc_udev; 155192984Sthompsa struct usb_interface *sc_iface; 156192984Sthompsa struct usb_xfer *sc_xfer[UKBD_N_TRANSFER]; 157307775Sgonzo#ifdef EVDEV_SUPPORT 158307764Sgonzo struct evdev_dev *sc_evdev; 159307764Sgonzo#endif 160184610Salfred 161358215Shselasky sbintime_t sc_co_basetime; 162358215Shselasky int sc_delay; 163358216Shselasky uint32_t sc_repeat_time; 164184610Salfred uint32_t sc_input[UKBD_IN_BUF_SIZE]; /* input buffer */ 165184610Salfred uint32_t sc_time_ms; 166184610Salfred uint32_t sc_composed_char; /* composed char code, if non-zero */ 167184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 168184610Salfred uint32_t sc_buffered_char[2]; 169184610Salfred#endif 170184610Salfred uint32_t sc_flags; /* flags */ 171223755Shselasky#define UKBD_FLAG_COMPOSE 0x00000001 172223755Shselasky#define UKBD_FLAG_POLLING 0x00000002 173223755Shselasky#define UKBD_FLAG_SET_LEDS 0x00000004 174223755Shselasky#define UKBD_FLAG_ATTACHED 0x00000010 175223755Shselasky#define UKBD_FLAG_GONE 0x00000020 176184610Salfred 177223755Shselasky#define UKBD_FLAG_HID_MASK 0x003fffc0 178223755Shselasky#define UKBD_FLAG_APPLE_EJECT 0x00000040 179223755Shselasky#define UKBD_FLAG_APPLE_FN 0x00000080 180223755Shselasky#define UKBD_FLAG_APPLE_SWAP 0x00000100 181223755Shselasky#define UKBD_FLAG_NUMLOCK 0x00080000 182223755Shselasky#define UKBD_FLAG_CAPSLOCK 0x00100000 183223755Shselasky#define UKBD_FLAG_SCROLLLOCK 0x00200000 184223755Shselasky 185203896Sthompsa int sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ 186203896Sthompsa int sc_state; /* shift/lock key state */ 187203896Sthompsa int sc_accents; /* accent key index (> 0) */ 188304124Shselasky int sc_polling; /* polling recursion count */ 189223755Shselasky int sc_led_size; 190223755Shselasky int sc_kbd_size; 191184610Salfred 192184610Salfred uint16_t sc_inputs; 193184610Salfred uint16_t sc_inputhead; 194184610Salfred uint16_t sc_inputtail; 195184610Salfred 196184610Salfred uint8_t sc_leds; /* store for async led requests */ 197184610Salfred uint8_t sc_iface_index; 198184610Salfred uint8_t sc_iface_no; 199223755Shselasky uint8_t sc_id_apple_eject; 200223755Shselasky uint8_t sc_id_apple_fn; 201358216Shselasky uint8_t sc_id_loc_key[UKBD_NKEYCODE]; 202223755Shselasky uint8_t sc_id_numlock; 203223755Shselasky uint8_t sc_id_capslock; 204223755Shselasky uint8_t sc_id_scrolllock; 205192925Sthompsa uint8_t sc_kbd_id; 206358216Shselasky uint8_t sc_repeat_key; 207223755Shselasky 208223755Shselasky uint8_t sc_buffer[UKBD_BUFFER_SIZE]; 209184610Salfred}; 210184610Salfred 211358216Shselasky#define KEY_NONE 0x00 212184610Salfred#define KEY_ERROR 0x01 213184610Salfred 214184610Salfred#define KEY_PRESS 0 215184610Salfred#define KEY_RELEASE 0x400 216184610Salfred#define KEY_INDEX(c) ((c) & 0xFF) 217184610Salfred 218184610Salfred#define SCAN_PRESS 0 219184610Salfred#define SCAN_RELEASE 0x80 220184610Salfred#define SCAN_PREFIX_E0 0x100 221184610Salfred#define SCAN_PREFIX_E1 0x200 222184610Salfred#define SCAN_PREFIX_CTL 0x400 223184610Salfred#define SCAN_PREFIX_SHIFT 0x800 224184610Salfred#define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | \ 225184610Salfred SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT) 226184610Salfred#define SCAN_CHAR(c) ((c) & 0x7f) 227184610Salfred 228228765Savg#define UKBD_LOCK() mtx_lock(&Giant) 229228765Savg#define UKBD_UNLOCK() mtx_unlock(&Giant) 230228765Savg 231228765Savg#ifdef INVARIANTS 232228765Savg 233228765Savg/* 234228765Savg * Assert that the lock is held in all contexts 235228765Savg * where the code can be executed. 236228765Savg */ 237228765Savg#define UKBD_LOCK_ASSERT() mtx_assert(&Giant, MA_OWNED) 238228765Savg 239228765Savg/* 240228765Savg * Assert that the lock is held in the contexts 241228765Savg * where it really has to be so. 242228765Savg */ 243228765Savg#define UKBD_CTX_LOCK_ASSERT() \ 244228765Savg do { \ 245228765Savg if (!kdb_active && panicstr == NULL) \ 246228765Savg mtx_assert(&Giant, MA_OWNED); \ 247228765Savg } while (0) 248228765Savg#else 249228765Savg 250228765Savg#define UKBD_LOCK_ASSERT() (void)0 251228765Savg#define UKBD_CTX_LOCK_ASSERT() (void)0 252228765Savg 253228765Savg#endif 254228765Savg 255184610Salfred#define NN 0 /* no translation */ 256184610Salfred/* 257184610Salfred * Translate USB keycodes to AT keyboard scancodes. 258184610Salfred */ 259184610Salfred/* 260184610Salfred * FIXME: Mac USB keyboard generates: 261184610Salfred * 0x53: keypad NumLock/Clear 262184610Salfred * 0x66: Power 263184610Salfred * 0x67: keypad = 264184610Salfred * 0x68: F13 265184610Salfred * 0x69: F14 266184610Salfred * 0x6a: F15 267291146Shselasky * 268291146Shselasky * USB Apple Keyboard JIS generates: 269291146Shselasky * 0x90: Kana 270291146Shselasky * 0x91: Eisu 271184610Salfred */ 272184610Salfredstatic const uint8_t ukbd_trtab[256] = { 273184610Salfred 0, 0, 0, 0, 30, 48, 46, 32, /* 00 - 07 */ 274184610Salfred 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */ 275184610Salfred 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */ 276184610Salfred 22, 47, 17, 45, 21, 44, 2, 3, /* 18 - 1F */ 277184610Salfred 4, 5, 6, 7, 8, 9, 10, 11, /* 20 - 27 */ 278184610Salfred 28, 1, 14, 15, 57, 12, 13, 26, /* 28 - 2F */ 279184610Salfred 27, 43, 43, 39, 40, 41, 51, 52, /* 30 - 37 */ 280184610Salfred 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */ 281184610Salfred 65, 66, 67, 68, 87, 88, 92, 70, /* 40 - 47 */ 282184610Salfred 104, 102, 94, 96, 103, 99, 101, 98, /* 48 - 4F */ 283184610Salfred 97, 100, 95, 69, 91, 55, 74, 78,/* 50 - 57 */ 284184610Salfred 89, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */ 285184610Salfred 72, 73, 82, 83, 86, 107, 122, NN, /* 60 - 67 */ 286184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */ 287184610Salfred NN, NN, NN, NN, 115, 108, 111, 113, /* 70 - 77 */ 288184610Salfred 109, 110, 112, 118, 114, 116, 117, 119, /* 78 - 7F */ 289197999Shrs 121, 120, NN, NN, NN, NN, NN, 123, /* 80 - 87 */ 290358213Shselasky 124, 125, 126, 127, 128, NN, NN, NN, /* 88 - 8F */ 291291146Shselasky 129, 130, NN, NN, NN, NN, NN, NN, /* 90 - 97 */ 292184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9F */ 293184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* A0 - A7 */ 294184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* A8 - AF */ 295184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* B0 - B7 */ 296184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* B8 - BF */ 297184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* C0 - C7 */ 298184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* C8 - CF */ 299184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ 300184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ 301184610Salfred 29, 42, 56, 105, 90, 54, 93, 106, /* E0 - E7 */ 302184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ 303184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ 304184610Salfred NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ 305184610Salfred}; 306184610Salfred 307223755Shselaskystatic const uint8_t ukbd_boot_desc[] = { 308223755Shselasky 0x05, 0x01, 0x09, 0x06, 0xa1, 309223755Shselasky 0x01, 0x05, 0x07, 0x19, 0xe0, 310223755Shselasky 0x29, 0xe7, 0x15, 0x00, 0x25, 311223755Shselasky 0x01, 0x75, 0x01, 0x95, 0x08, 312223755Shselasky 0x81, 0x02, 0x95, 0x01, 0x75, 313223755Shselasky 0x08, 0x81, 0x01, 0x95, 0x03, 314223755Shselasky 0x75, 0x01, 0x05, 0x08, 0x19, 315223755Shselasky 0x01, 0x29, 0x03, 0x91, 0x02, 316223755Shselasky 0x95, 0x05, 0x75, 0x01, 0x91, 317223755Shselasky 0x01, 0x95, 0x06, 0x75, 0x08, 318223755Shselasky 0x15, 0x00, 0x26, 0xff, 0x00, 319223755Shselasky 0x05, 0x07, 0x19, 0x00, 0x2a, 320223755Shselasky 0xff, 0x00, 0x81, 0x00, 0xc0 321223755Shselasky}; 322223755Shselasky 323184610Salfred/* prototypes */ 324185948Sthompsastatic void ukbd_timeout(void *); 325185948Sthompsastatic void ukbd_set_leds(struct ukbd_softc *, uint8_t); 326185948Sthompsastatic int ukbd_set_typematic(keyboard_t *, int); 327184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 328358216Shselaskystatic uint32_t ukbd_atkeycode(int, const uint64_t *); 329358216Shselaskystatic int ukbd_key2scan(struct ukbd_softc *, int, const uint64_t *, int); 330184610Salfred#endif 331185948Sthompsastatic uint32_t ukbd_read_char(keyboard_t *, int); 332185948Sthompsastatic void ukbd_clear_state(keyboard_t *); 333185948Sthompsastatic int ukbd_ioctl(keyboard_t *, u_long, caddr_t); 334185948Sthompsastatic int ukbd_enable(keyboard_t *); 335185948Sthompsastatic int ukbd_disable(keyboard_t *); 336185948Sthompsastatic void ukbd_interrupt(struct ukbd_softc *); 337203896Sthompsastatic void ukbd_event_keyinput(struct ukbd_softc *); 338184610Salfred 339184610Salfredstatic device_probe_t ukbd_probe; 340184610Salfredstatic device_attach_t ukbd_attach; 341184610Salfredstatic device_detach_t ukbd_detach; 342184610Salfredstatic device_resume_t ukbd_resume; 343184610Salfred 344307775Sgonzo#ifdef EVDEV_SUPPORT 345307777Sgonzostatic const struct evdev_methods ukbd_evdev_methods = { 346307764Sgonzo .ev_event = evdev_ev_kbd_event, 347307764Sgonzo}; 348307764Sgonzo#endif 349307764Sgonzo 350358216Shselaskystatic bool 351196489Salfredukbd_any_key_pressed(struct ukbd_softc *sc) 352196489Salfred{ 353358216Shselasky bool ret = false; 354358216Shselasky unsigned i; 355196489Salfred 356358216Shselasky for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++) 357358216Shselasky ret |= (sc->sc_odata.bitmap[i] != 0); 358358216Shselasky return (ret); 359358216Shselasky} 360196489Salfred 361358216Shselaskystatic bool 362358216Shselaskyukbd_any_key_valid(struct ukbd_softc *sc) 363358216Shselasky{ 364358216Shselasky bool ret = false; 365358216Shselasky unsigned i; 366358216Shselasky 367358216Shselasky for (i = 0; i != howmany(UKBD_NKEYCODE, 64); i++) 368358216Shselasky ret |= (sc->sc_loc_key_valid[i] != 0); 369358216Shselasky return (ret); 370196489Salfred} 371196489Salfred 372358216Shselaskystatic bool 373358216Shselaskyukbd_is_modifier_key(uint32_t key) 374358216Shselasky{ 375358216Shselasky 376358216Shselasky return (key >= 0xe0 && key <= 0xe7); 377358216Shselasky} 378358216Shselasky 379184610Salfredstatic void 380196489Salfredukbd_start_timer(struct ukbd_softc *sc) 381196489Salfred{ 382358215Shselasky sbintime_t delay, now, prec; 383358215Shselasky 384358215Shselasky now = sbinuptime(); 385358215Shselasky 386358215Shselasky /* check if initial delay passed and fallback to key repeat delay */ 387358215Shselasky if (sc->sc_delay == 0) 388358215Shselasky sc->sc_delay = sc->sc_kbd.kb_delay2; 389358215Shselasky 390358215Shselasky /* compute timeout */ 391358215Shselasky delay = SBT_1MS * sc->sc_delay; 392358215Shselasky sc->sc_co_basetime += delay; 393358215Shselasky 394358215Shselasky /* check if we are running behind */ 395358215Shselasky if (sc->sc_co_basetime < now) 396358215Shselasky sc->sc_co_basetime = now; 397358215Shselasky 398358215Shselasky /* This is rarely called, so prefer precision to efficiency. */ 399358215Shselasky prec = qmin(delay >> 7, SBT_1MS * 10); 400358215Shselasky callout_reset_sbt(&sc->sc_callout.co, sc->sc_co_basetime, prec, 401358215Shselasky ukbd_timeout, sc, C_ABSOLUTE); 402196489Salfred} 403196489Salfred 404196489Salfredstatic void 405184610Salfredukbd_put_key(struct ukbd_softc *sc, uint32_t key) 406184610Salfred{ 407184610Salfred 408228765Savg UKBD_CTX_LOCK_ASSERT(); 409228765Savg 410184610Salfred DPRINTF("0x%02x (%d) %s\n", key, key, 411184610Salfred (key & KEY_RELEASE) ? "released" : "pressed"); 412184610Salfred 413307775Sgonzo#ifdef EVDEV_SUPPORT 414307764Sgonzo if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD && sc->sc_evdev != NULL) { 415307764Sgonzo evdev_push_event(sc->sc_evdev, EV_KEY, 416307764Sgonzo evdev_hid2key(KEY_INDEX(key)), !(key & KEY_RELEASE)); 417307764Sgonzo evdev_sync(sc->sc_evdev); 418307764Sgonzo } 419307764Sgonzo#endif 420307764Sgonzo 421184610Salfred if (sc->sc_inputs < UKBD_IN_BUF_SIZE) { 422184610Salfred sc->sc_input[sc->sc_inputtail] = key; 423184610Salfred ++(sc->sc_inputs); 424184610Salfred ++(sc->sc_inputtail); 425184610Salfred if (sc->sc_inputtail >= UKBD_IN_BUF_SIZE) { 426184610Salfred sc->sc_inputtail = 0; 427184610Salfred } 428184610Salfred } else { 429184610Salfred DPRINTF("input buffer is full\n"); 430184610Salfred } 431184610Salfred} 432184610Salfred 433195960Salfredstatic void 434228765Savgukbd_do_poll(struct ukbd_softc *sc, uint8_t wait) 435223989Shselasky{ 436223989Shselasky 437228765Savg UKBD_CTX_LOCK_ASSERT(); 438228765Savg KASSERT((sc->sc_flags & UKBD_FLAG_POLLING) != 0, 439228765Savg ("ukbd_do_poll called when not polling\n")); 440195960Salfred DPRINTFN(2, "polling\n"); 441195960Salfred 442228765Savg if (!kdb_active && !SCHEDULER_STOPPED()) { 443228765Savg /* 444228765Savg * In this context the kernel is polling for input, 445228765Savg * but the USB subsystem works in normal interrupt-driven 446228765Savg * mode, so we just wait on the USB threads to do the job. 447228765Savg * Note that we currently hold the Giant, but it's also used 448228765Savg * as the transfer mtx, so we must release it while waiting. 449228765Savg */ 450203896Sthompsa while (sc->sc_inputs == 0) { 451228765Savg /* 452228765Savg * Give USB threads a chance to run. Note that 453228765Savg * kern_yield performs DROP_GIANT + PICKUP_GIANT. 454228765Savg */ 455228765Savg kern_yield(PRI_UNCHANGED); 456203896Sthompsa if (!wait) 457203896Sthompsa break; 458203896Sthompsa } 459228765Savg return; 460203896Sthompsa } 461198152Sthompsa 462195960Salfred while (sc->sc_inputs == 0) { 463195960Salfred 464195960Salfred usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER); 465195960Salfred 466196489Salfred /* Delay-optimised support for repetition of keys */ 467196489Salfred if (ukbd_any_key_pressed(sc)) { 468196489Salfred /* a key is pressed - need timekeeping */ 469196489Salfred DELAY(1000); 470195960Salfred 471196489Salfred /* 1 millisecond has passed */ 472196489Salfred sc->sc_time_ms += 1; 473196489Salfred } 474195960Salfred 475195960Salfred ukbd_interrupt(sc); 476195960Salfred 477195960Salfred if (!wait) 478195960Salfred break; 479195960Salfred } 480195960Salfred} 481195960Salfred 482184610Salfredstatic int32_t 483184610Salfredukbd_get_key(struct ukbd_softc *sc, uint8_t wait) 484184610Salfred{ 485184610Salfred int32_t c; 486184610Salfred 487228765Savg UKBD_CTX_LOCK_ASSERT(); 488228765Savg KASSERT((!kdb_active && !SCHEDULER_STOPPED()) 489228765Savg || (sc->sc_flags & UKBD_FLAG_POLLING) != 0, 490228765Savg ("not polling in kdb or panic\n")); 491184610Salfred 492261228Shselasky if (sc->sc_inputs == 0 && 493261228Shselasky (sc->sc_flags & UKBD_FLAG_GONE) == 0) { 494184610Salfred /* start transfer, if not already started */ 495305644Shselasky usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_0]); 496305644Shselasky usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_1]); 497184610Salfred } 498203896Sthompsa 499203896Sthompsa if (sc->sc_flags & UKBD_FLAG_POLLING) 500195960Salfred ukbd_do_poll(sc, wait); 501203896Sthompsa 502184610Salfred if (sc->sc_inputs == 0) { 503184610Salfred c = -1; 504184610Salfred } else { 505184610Salfred c = sc->sc_input[sc->sc_inputhead]; 506184610Salfred --(sc->sc_inputs); 507184610Salfred ++(sc->sc_inputhead); 508184610Salfred if (sc->sc_inputhead >= UKBD_IN_BUF_SIZE) { 509184610Salfred sc->sc_inputhead = 0; 510184610Salfred } 511184610Salfred } 512184610Salfred return (c); 513184610Salfred} 514184610Salfred 515184610Salfredstatic void 516184610Salfredukbd_interrupt(struct ukbd_softc *sc) 517184610Salfred{ 518358216Shselasky const uint32_t now = sc->sc_time_ms; 519358216Shselasky unsigned key; 520184610Salfred 521228765Savg UKBD_CTX_LOCK_ASSERT(); 522228765Savg 523359559Shselasky /* Check for modifier key changes first */ 524359559Shselasky for (key = 0xe0; key != 0xe8; key++) { 525359559Shselasky const uint64_t mask = 1ULL << (key % 64); 526359559Shselasky const uint64_t delta = 527359559Shselasky sc->sc_odata.bitmap[key / 64] ^ 528359559Shselasky sc->sc_ndata.bitmap[key / 64]; 529359559Shselasky 530359559Shselasky if (delta & mask) { 531359559Shselasky if (sc->sc_odata.bitmap[key / 64] & mask) 532359559Shselasky ukbd_put_key(sc, key | KEY_RELEASE); 533359559Shselasky else 534359559Shselasky ukbd_put_key(sc, key | KEY_PRESS); 535359559Shselasky } 536359559Shselasky } 537359559Shselasky 538358216Shselasky /* Check for key changes */ 539358216Shselasky for (key = 0; key != UKBD_NKEYCODE; key++) { 540358216Shselasky const uint64_t mask = 1ULL << (key % 64); 541358216Shselasky const uint64_t delta = 542358216Shselasky sc->sc_odata.bitmap[key / 64] ^ 543358216Shselasky sc->sc_ndata.bitmap[key / 64]; 544203896Sthompsa 545358216Shselasky if (mask == 1 && delta == 0) { 546358216Shselasky key += 63; 547358216Shselasky continue; /* skip empty areas */ 548359559Shselasky } else if (ukbd_is_modifier_key(key)) { 549359559Shselasky continue; 550358216Shselasky } else if (delta & mask) { 551358216Shselasky if (sc->sc_odata.bitmap[key / 64] & mask) { 552358216Shselasky ukbd_put_key(sc, key | KEY_RELEASE); 553184610Salfred 554358216Shselasky /* clear repeating key, if any */ 555358216Shselasky if (sc->sc_repeat_key == key) 556358216Shselasky sc->sc_repeat_key = 0; 557358216Shselasky } else { 558358216Shselasky ukbd_put_key(sc, key | KEY_PRESS); 559184610Salfred 560358697Shselasky sc->sc_co_basetime = sbinuptime(); 561358697Shselasky sc->sc_delay = sc->sc_kbd.kb_delay1; 562358697Shselasky ukbd_start_timer(sc); 563184610Salfred 564358216Shselasky /* set repeat time for last key */ 565358216Shselasky sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; 566358216Shselasky sc->sc_repeat_key = key; 567184610Salfred } 568184610Salfred } 569184610Salfred } 570184610Salfred 571358216Shselasky /* synchronize old data with new data */ 572184610Salfred sc->sc_odata = sc->sc_ndata; 573358216Shselasky 574358216Shselasky /* check if last key is still pressed */ 575358216Shselasky if (sc->sc_repeat_key != 0) { 576358216Shselasky const int32_t dtime = (sc->sc_repeat_time - now); 577184610Salfred 578358216Shselasky /* check if time has elapsed */ 579358216Shselasky if (dtime <= 0) { 580358216Shselasky ukbd_put_key(sc, sc->sc_repeat_key | KEY_PRESS); 581358216Shselasky sc->sc_repeat_time = now + sc->sc_kbd.kb_delay2; 582358216Shselasky } 583358216Shselasky } 584184610Salfred 585358216Shselasky /* wakeup keyboard system */ 586203896Sthompsa ukbd_event_keyinput(sc); 587203896Sthompsa} 588203896Sthompsa 589203896Sthompsastatic void 590203896Sthompsaukbd_event_keyinput(struct ukbd_softc *sc) 591203896Sthompsa{ 592203896Sthompsa int c; 593203896Sthompsa 594228765Savg UKBD_CTX_LOCK_ASSERT(); 595228765Savg 596228765Savg if ((sc->sc_flags & UKBD_FLAG_POLLING) != 0) 597203896Sthompsa return; 598203896Sthompsa 599203896Sthompsa if (sc->sc_inputs == 0) 600203896Sthompsa return; 601203896Sthompsa 602184610Salfred if (KBD_IS_ACTIVE(&sc->sc_kbd) && 603184610Salfred KBD_IS_BUSY(&sc->sc_kbd)) { 604184610Salfred /* let the callback function process the input */ 605184610Salfred (sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT, 606184610Salfred sc->sc_kbd.kb_callback.kc_arg); 607184610Salfred } else { 608184610Salfred /* read and discard the input, no one is waiting for it */ 609184610Salfred do { 610184610Salfred c = ukbd_read_char(&sc->sc_kbd, 0); 611184610Salfred } while (c != NOKEY); 612184610Salfred } 613184610Salfred} 614184610Salfred 615184610Salfredstatic void 616184610Salfredukbd_timeout(void *arg) 617184610Salfred{ 618184610Salfred struct ukbd_softc *sc = arg; 619184610Salfred 620228765Savg UKBD_LOCK_ASSERT(); 621184610Salfred 622358215Shselasky sc->sc_time_ms += sc->sc_delay; 623358215Shselasky sc->sc_delay = 0; 624203896Sthompsa 625184610Salfred ukbd_interrupt(sc); 626184610Salfred 627203896Sthompsa /* Make sure any leftover key events gets read out */ 628203896Sthompsa ukbd_event_keyinput(sc); 629203896Sthompsa 630203896Sthompsa if (ukbd_any_key_pressed(sc) || (sc->sc_inputs != 0)) { 631196489Salfred ukbd_start_timer(sc); 632196489Salfred } 633184610Salfred} 634184610Salfred 635358216Shselaskystatic uint32_t 636358216Shselaskyukbd_apple_fn(uint32_t keycode) 637358216Shselasky{ 638192925Sthompsa switch (keycode) { 639192925Sthompsa case 0x28: return 0x49; /* RETURN -> INSERT */ 640192925Sthompsa case 0x2a: return 0x4c; /* BACKSPACE -> DEL */ 641192925Sthompsa case 0x50: return 0x4a; /* LEFT ARROW -> HOME */ 642192925Sthompsa case 0x4f: return 0x4d; /* RIGHT ARROW -> END */ 643192925Sthompsa case 0x52: return 0x4b; /* UP ARROW -> PGUP */ 644192925Sthompsa case 0x51: return 0x4e; /* DOWN ARROW -> PGDN */ 645192925Sthompsa default: return keycode; 646192925Sthompsa } 647192925Sthompsa} 648184610Salfred 649358216Shselaskystatic uint32_t 650358216Shselaskyukbd_apple_swap(uint32_t keycode) 651358216Shselasky{ 652192925Sthompsa switch (keycode) { 653192925Sthompsa case 0x35: return 0x64; 654192925Sthompsa case 0x64: return 0x35; 655192925Sthompsa default: return keycode; 656184610Salfred } 657184610Salfred} 658184610Salfred 659184610Salfredstatic void 660194677Sthompsaukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) 661184610Salfred{ 662194677Sthompsa struct ukbd_softc *sc = usbd_xfer_softc(xfer); 663194677Sthompsa struct usb_page_cache *pc; 664358216Shselasky uint32_t i; 665192925Sthompsa uint8_t id; 666358216Shselasky uint8_t modifiers; 667358216Shselasky int offset; 668194677Sthompsa int len; 669184610Salfred 670228765Savg UKBD_LOCK_ASSERT(); 671228765Savg 672194677Sthompsa usbd_xfer_status(xfer, &len, NULL, NULL, NULL); 673194677Sthompsa pc = usbd_xfer_get_frame(xfer, 0); 674194677Sthompsa 675184610Salfred switch (USB_GET_STATE(xfer)) { 676184610Salfred case USB_ST_TRANSFERRED: 677184610Salfred DPRINTF("actlen=%d bytes\n", len); 678184610Salfred 679192925Sthompsa if (len == 0) { 680192925Sthompsa DPRINTF("zero length data\n"); 681192925Sthompsa goto tr_setup; 682192925Sthompsa } 683192925Sthompsa 684192925Sthompsa if (sc->sc_kbd_id != 0) { 685192925Sthompsa /* check and remove HID ID byte */ 686194677Sthompsa usbd_copy_out(pc, 0, &id, 1); 687223755Shselasky offset = 1; 688223755Shselasky len--; 689223755Shselasky if (len == 0) { 690223755Shselasky DPRINTF("zero length data\n"); 691192925Sthompsa goto tr_setup; 692192925Sthompsa } 693192925Sthompsa } else { 694192925Sthompsa offset = 0; 695223755Shselasky id = 0; 696192925Sthompsa } 697192925Sthompsa 698223755Shselasky if (len > UKBD_BUFFER_SIZE) 699223755Shselasky len = UKBD_BUFFER_SIZE; 700192925Sthompsa 701223755Shselasky /* get data */ 702223755Shselasky usbd_copy_out(pc, offset, sc->sc_buffer, len); 703192925Sthompsa 704223755Shselasky /* clear temporary storage */ 705223755Shselasky memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); 706192925Sthompsa 707358216Shselasky /* clear modifiers */ 708358216Shselasky modifiers = 0; 709358216Shselasky 710223755Shselasky /* scan through HID data */ 711223755Shselasky if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && 712223755Shselasky (id == sc->sc_id_apple_eject)) { 713223755Shselasky if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_eject)) 714358216Shselasky modifiers |= MOD_EJECT; 715223755Shselasky } 716223755Shselasky if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && 717223755Shselasky (id == sc->sc_id_apple_fn)) { 718223755Shselasky if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_fn)) 719358216Shselasky modifiers |= MOD_FN; 720223755Shselasky } 721192925Sthompsa 722358216Shselasky for (i = 0; i != UKBD_NKEYCODE; i++) { 723358216Shselasky const uint64_t valid = sc->sc_loc_key_valid[i / 64]; 724358216Shselasky const uint64_t mask = 1ULL << (i % 64); 725223755Shselasky 726358216Shselasky if (mask == 1 && valid == 0) { 727358216Shselasky i += 63; 728358216Shselasky continue; /* skip empty areas */ 729358216Shselasky } else if (~valid & mask) { 730358216Shselasky continue; /* location is not valid */ 731358216Shselasky } else if (id != sc->sc_id_loc_key[i]) { 732358216Shselasky continue; /* invalid HID ID */ 733358216Shselasky } else if (i == 0) { 734358453Shselasky struct hid_location tmp_loc = sc->sc_loc_key[0]; 735358453Shselasky /* range check array size */ 736358453Shselasky if (tmp_loc.count > UKBD_NKEYCODE) 737358453Shselasky tmp_loc.count = UKBD_NKEYCODE; 738358453Shselasky while (tmp_loc.count--) { 739358216Shselasky uint32_t key = 740358453Shselasky hid_get_data_unsigned(sc->sc_buffer, len, &tmp_loc); 741358453Shselasky /* advance to next location */ 742358453Shselasky tmp_loc.pos += tmp_loc.size; 743358216Shselasky if (modifiers & MOD_FN) 744358216Shselasky key = ukbd_apple_fn(key); 745358216Shselasky if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) 746358216Shselasky key = ukbd_apple_swap(key); 747358216Shselasky if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE) 748358216Shselasky continue; 749358216Shselasky /* set key in bitmap */ 750358216Shselasky sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64); 751358216Shselasky } 752358216Shselasky } else if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_key[i])) { 753358216Shselasky uint32_t key = i; 754358216Shselasky 755358216Shselasky if (modifiers & MOD_FN) 756358216Shselasky key = ukbd_apple_fn(key); 757358216Shselasky if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) 758358216Shselasky key = ukbd_apple_swap(key); 759358216Shselasky if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE) 760358216Shselasky continue; 761358216Shselasky /* set key in bitmap */ 762358216Shselasky sc->sc_ndata.bitmap[key / 64] |= 1ULL << (key % 64); 763184610Salfred } 764223755Shselasky } 765358216Shselasky#ifdef USB_DEBUG 766358216Shselasky DPRINTF("modifiers = 0x%04x\n", modifiers); 767358216Shselasky for (i = 0; i != UKBD_NKEYCODE; i++) { 768358216Shselasky const uint64_t valid = sc->sc_ndata.bitmap[i / 64]; 769358216Shselasky const uint64_t mask = 1ULL << (i % 64); 770223755Shselasky 771358216Shselasky if (valid & mask) 772358216Shselasky DPRINTF("Key 0x%02x pressed\n", i); 773223755Shselasky } 774223755Shselasky#endif 775223755Shselasky ukbd_interrupt(sc); 776192925Sthompsa 777184610Salfred case USB_ST_SETUP: 778192925Sthompsatr_setup: 779184610Salfred if (sc->sc_inputs < UKBD_IN_BUF_FULL) { 780194677Sthompsa usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 781194228Sthompsa usbd_transfer_submit(xfer); 782184610Salfred } else { 783184610Salfred DPRINTF("input queue is full!\n"); 784184610Salfred } 785192925Sthompsa break; 786184610Salfred 787184610Salfred default: /* Error */ 788194677Sthompsa DPRINTF("error=%s\n", usbd_errstr(error)); 789184610Salfred 790194677Sthompsa if (error != USB_ERR_CANCELLED) { 791184610Salfred /* try to clear stall first */ 792194677Sthompsa usbd_xfer_set_stall(xfer); 793192925Sthompsa goto tr_setup; 794184610Salfred } 795192925Sthompsa break; 796184610Salfred } 797184610Salfred} 798184610Salfred 799184610Salfredstatic void 800194677Sthompsaukbd_set_leds_callback(struct usb_xfer *xfer, usb_error_t error) 801184610Salfred{ 802223755Shselasky struct ukbd_softc *sc = usbd_xfer_softc(xfer); 803192984Sthompsa struct usb_device_request req; 804194677Sthompsa struct usb_page_cache *pc; 805223755Shselasky uint8_t id; 806223755Shselasky uint8_t any; 807223755Shselasky int len; 808184610Salfred 809228765Savg UKBD_LOCK_ASSERT(); 810228765Savg 811207077Sthompsa#ifdef USB_DEBUG 812196489Salfred if (ukbd_no_leds) 813196489Salfred return; 814196489Salfred#endif 815196489Salfred 816184610Salfred switch (USB_GET_STATE(xfer)) { 817184610Salfred case USB_ST_TRANSFERRED: 818184610Salfred case USB_ST_SETUP: 819223755Shselasky if (!(sc->sc_flags & UKBD_FLAG_SET_LEDS)) 820223755Shselasky break; 821223755Shselasky sc->sc_flags &= ~UKBD_FLAG_SET_LEDS; 822184610Salfred 823223755Shselasky req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 824223755Shselasky req.bRequest = UR_SET_REPORT; 825223755Shselasky USETW2(req.wValue, UHID_OUTPUT_REPORT, 0); 826223755Shselasky req.wIndex[0] = sc->sc_iface_no; 827223755Shselasky req.wIndex[1] = 0; 828223755Shselasky req.wLength[1] = 0; 829184610Salfred 830223755Shselasky memset(sc->sc_buffer, 0, UKBD_BUFFER_SIZE); 831223755Shselasky 832223755Shselasky id = 0; 833223755Shselasky any = 0; 834223755Shselasky 835223755Shselasky /* Assumption: All led bits must be in the same ID. */ 836223755Shselasky 837223755Shselasky if (sc->sc_flags & UKBD_FLAG_NUMLOCK) { 838223755Shselasky if (sc->sc_leds & NLKED) { 839223755Shselasky hid_put_data_unsigned(sc->sc_buffer + 1, UKBD_BUFFER_SIZE - 1, 840223755Shselasky &sc->sc_loc_numlock, 1); 841192925Sthompsa } 842223755Shselasky id = sc->sc_id_numlock; 843223755Shselasky any = 1; 844223755Shselasky } 845184610Salfred 846223755Shselasky if (sc->sc_flags & UKBD_FLAG_SCROLLLOCK) { 847223755Shselasky if (sc->sc_leds & SLKED) { 848223755Shselasky hid_put_data_unsigned(sc->sc_buffer + 1, UKBD_BUFFER_SIZE - 1, 849223755Shselasky &sc->sc_loc_scrolllock, 1); 850223755Shselasky } 851223755Shselasky id = sc->sc_id_scrolllock; 852223755Shselasky any = 1; 853223755Shselasky } 854184610Salfred 855223755Shselasky if (sc->sc_flags & UKBD_FLAG_CAPSLOCK) { 856223755Shselasky if (sc->sc_leds & CLKED) { 857223755Shselasky hid_put_data_unsigned(sc->sc_buffer + 1, UKBD_BUFFER_SIZE - 1, 858223755Shselasky &sc->sc_loc_capslock, 1); 859223755Shselasky } 860223755Shselasky id = sc->sc_id_capslock; 861223755Shselasky any = 1; 862184610Salfred } 863223755Shselasky 864223755Shselasky /* if no leds, nothing to do */ 865223755Shselasky if (!any) 866223755Shselasky break; 867223755Shselasky 868307775Sgonzo#ifdef EVDEV_SUPPORT 869307764Sgonzo if (sc->sc_evdev != NULL) 870307764Sgonzo evdev_push_leds(sc->sc_evdev, sc->sc_leds); 871307764Sgonzo#endif 872307764Sgonzo 873223755Shselasky /* range check output report length */ 874223755Shselasky len = sc->sc_led_size; 875223755Shselasky if (len > (UKBD_BUFFER_SIZE - 1)) 876223755Shselasky len = (UKBD_BUFFER_SIZE - 1); 877223755Shselasky 878223755Shselasky /* check if we need to prefix an ID byte */ 879223755Shselasky sc->sc_buffer[0] = id; 880223755Shselasky 881223755Shselasky pc = usbd_xfer_get_frame(xfer, 1); 882223755Shselasky if (id != 0) { 883223755Shselasky len++; 884223755Shselasky usbd_copy_in(pc, 0, sc->sc_buffer, len); 885223755Shselasky } else { 886223755Shselasky usbd_copy_in(pc, 0, sc->sc_buffer + 1, len); 887223755Shselasky } 888223755Shselasky req.wLength[0] = len; 889223755Shselasky usbd_xfer_set_frame_len(xfer, 1, len); 890223755Shselasky 891223755Shselasky DPRINTF("len=%d, id=%d\n", len, id); 892223755Shselasky 893223755Shselasky /* setup control request last */ 894223755Shselasky pc = usbd_xfer_get_frame(xfer, 0); 895223755Shselasky usbd_copy_in(pc, 0, &req, sizeof(req)); 896223755Shselasky usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); 897223755Shselasky 898223755Shselasky /* start data transfer */ 899223755Shselasky usbd_xfer_set_frames(xfer, 2); 900223755Shselasky usbd_transfer_submit(xfer); 901196489Salfred break; 902184610Salfred 903184610Salfred default: /* Error */ 904212128Sthompsa DPRINTFN(1, "error=%s\n", usbd_errstr(error)); 905196489Salfred break; 906184610Salfred } 907184610Salfred} 908184610Salfred 909192984Sthompsastatic const struct usb_config ukbd_config[UKBD_N_TRANSFER] = { 910184610Salfred 911305644Shselasky [UKBD_INTR_DT_0] = { 912184610Salfred .type = UE_INTERRUPT, 913184610Salfred .endpoint = UE_ADDR_ANY, 914184610Salfred .direction = UE_DIR_IN, 915190734Sthompsa .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 916190734Sthompsa .bufsize = 0, /* use wMaxPacketSize */ 917190734Sthompsa .callback = &ukbd_intr_callback, 918184610Salfred }, 919184610Salfred 920305644Shselasky [UKBD_INTR_DT_1] = { 921305644Shselasky .type = UE_INTERRUPT, 922305644Shselasky .endpoint = UE_ADDR_ANY, 923305644Shselasky .direction = UE_DIR_IN, 924305644Shselasky .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 925305644Shselasky .bufsize = 0, /* use wMaxPacketSize */ 926305644Shselasky .callback = &ukbd_intr_callback, 927305644Shselasky }, 928305644Shselasky 929187259Sthompsa [UKBD_CTRL_LED] = { 930184610Salfred .type = UE_CONTROL, 931184610Salfred .endpoint = 0x00, /* Control pipe */ 932184610Salfred .direction = UE_DIR_ANY, 933223755Shselasky .bufsize = sizeof(struct usb_device_request) + UKBD_BUFFER_SIZE, 934190734Sthompsa .callback = &ukbd_set_leds_callback, 935190734Sthompsa .timeout = 1000, /* 1 second */ 936184610Salfred }, 937184610Salfred}; 938184610Salfred 939223521Shselasky/* A match on these entries will load ukbd */ 940223521Shselaskystatic const STRUCT_USB_HOST_ID __used ukbd_devs[] = { 941223521Shselasky {USB_IFACE_CLASS(UICLASS_HID), 942223521Shselasky USB_IFACE_SUBCLASS(UISUBCLASS_BOOT), 943223521Shselasky USB_IFACE_PROTOCOL(UIPROTO_BOOT_KEYBOARD),}, 944223521Shselasky}; 945223521Shselasky 946184610Salfredstatic int 947184610Salfredukbd_probe(device_t dev) 948184610Salfred{ 949184610Salfred keyboard_switch_t *sw = kbd_get_switch(UKBD_DRIVER_NAME); 950192984Sthompsa struct usb_attach_arg *uaa = device_get_ivars(dev); 951194067Sthompsa void *d_ptr; 952194067Sthompsa int error; 953194067Sthompsa uint16_t d_len; 954184610Salfred 955228765Savg UKBD_LOCK_ASSERT(); 956184610Salfred DPRINTFN(11, "\n"); 957184610Salfred 958184610Salfred if (sw == NULL) { 959184610Salfred return (ENXIO); 960184610Salfred } 961192499Sthompsa if (uaa->usb_mode != USB_MODE_HOST) { 962184610Salfred return (ENXIO); 963184610Salfred } 964194067Sthompsa 965194067Sthompsa if (uaa->info.bInterfaceClass != UICLASS_HID) 966194067Sthompsa return (ENXIO); 967194067Sthompsa 968245248Shselasky if (usb_test_quirk(uaa, UQ_KBD_IGNORE)) 969245248Shselasky return (ENXIO); 970245248Shselasky 971194067Sthompsa if ((uaa->info.bInterfaceSubClass == UISUBCLASS_BOOT) && 972245248Shselasky (uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD)) 973245248Shselasky return (BUS_PROBE_DEFAULT); 974194067Sthompsa 975194228Sthompsa error = usbd_req_get_hid_desc(uaa->device, NULL, 976194067Sthompsa &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex); 977194067Sthompsa 978194067Sthompsa if (error) 979194067Sthompsa return (ENXIO); 980194067Sthompsa 981245248Shselasky if (hid_is_keyboard(d_ptr, d_len)) { 982245248Shselasky if (hid_is_mouse(d_ptr, d_len)) { 983245248Shselasky /* 984245248Shselasky * NOTE: We currently don't support USB mouse 985245248Shselasky * and USB keyboard on the same USB endpoint. 986245248Shselasky * Let "ums" driver win. 987245248Shselasky */ 988194067Sthompsa error = ENXIO; 989245248Shselasky } else { 990222051Savg error = BUS_PROBE_DEFAULT; 991245248Shselasky } 992245248Shselasky } else { 993194067Sthompsa error = ENXIO; 994245248Shselasky } 995194067Sthompsa free(d_ptr, M_TEMP); 996194067Sthompsa return (error); 997184610Salfred} 998184610Salfred 999223755Shselaskystatic void 1000223755Shselaskyukbd_parse_hid(struct ukbd_softc *sc, const uint8_t *ptr, uint32_t len) 1001223755Shselasky{ 1002223755Shselasky uint32_t flags; 1003358216Shselasky uint32_t key; 1004223755Shselasky 1005223755Shselasky /* reset detected bits */ 1006223755Shselasky sc->sc_flags &= ~UKBD_FLAG_HID_MASK; 1007223755Shselasky 1008358216Shselasky /* reset detected keys */ 1009358216Shselasky memset(sc->sc_loc_key_valid, 0, sizeof(sc->sc_loc_key_valid)); 1010358216Shselasky 1011223755Shselasky /* check if there is an ID byte */ 1012223755Shselasky sc->sc_kbd_size = hid_report_size(ptr, len, 1013223755Shselasky hid_input, &sc->sc_kbd_id); 1014223755Shselasky 1015223755Shselasky /* investigate if this is an Apple Keyboard */ 1016223755Shselasky if (hid_locate(ptr, len, 1017223755Shselasky HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT), 1018223755Shselasky hid_input, 0, &sc->sc_loc_apple_eject, &flags, 1019223755Shselasky &sc->sc_id_apple_eject)) { 1020223755Shselasky if (flags & HIO_VARIABLE) 1021223755Shselasky sc->sc_flags |= UKBD_FLAG_APPLE_EJECT | 1022223755Shselasky UKBD_FLAG_APPLE_SWAP; 1023223755Shselasky DPRINTFN(1, "Found Apple eject-key\n"); 1024223755Shselasky } 1025223755Shselasky if (hid_locate(ptr, len, 1026223755Shselasky HID_USAGE2(0xFFFF, 0x0003), 1027223755Shselasky hid_input, 0, &sc->sc_loc_apple_fn, &flags, 1028223755Shselasky &sc->sc_id_apple_fn)) { 1029223755Shselasky if (flags & HIO_VARIABLE) 1030223755Shselasky sc->sc_flags |= UKBD_FLAG_APPLE_FN; 1031223755Shselasky DPRINTFN(1, "Found Apple FN-key\n"); 1032223755Shselasky } 1033358216Shselasky 1034223755Shselasky /* figure out event buffer */ 1035223755Shselasky if (hid_locate(ptr, len, 1036223755Shselasky HID_USAGE2(HUP_KEYBOARD, 0x00), 1037358216Shselasky hid_input, 0, &sc->sc_loc_key[0], &flags, 1038358216Shselasky &sc->sc_id_loc_key[0])) { 1039254572Shselasky if (flags & HIO_VARIABLE) { 1040254572Shselasky DPRINTFN(1, "Ignoring keyboard event control\n"); 1041254572Shselasky } else { 1042358216Shselasky sc->sc_loc_key_valid[0] |= 1; 1043254572Shselasky DPRINTFN(1, "Found keyboard event array\n"); 1044254572Shselasky } 1045223755Shselasky } 1046223755Shselasky 1047358216Shselasky /* figure out the keys */ 1048358216Shselasky for (key = 1; key != UKBD_NKEYCODE; key++) { 1049358216Shselasky if (hid_locate(ptr, len, 1050358216Shselasky HID_USAGE2(HUP_KEYBOARD, key), 1051358216Shselasky hid_input, 0, &sc->sc_loc_key[key], &flags, 1052358216Shselasky &sc->sc_id_loc_key[key])) { 1053358216Shselasky if (flags & HIO_VARIABLE) { 1054358216Shselasky sc->sc_loc_key_valid[key / 64] |= 1055358216Shselasky 1ULL << (key % 64); 1056358216Shselasky DPRINTFN(1, "Found key 0x%02x\n", key); 1057358216Shselasky } 1058358216Shselasky } 1059358216Shselasky } 1060358216Shselasky 1061223755Shselasky /* figure out leds on keyboard */ 1062223755Shselasky sc->sc_led_size = hid_report_size(ptr, len, 1063223755Shselasky hid_output, NULL); 1064223755Shselasky 1065223755Shselasky if (hid_locate(ptr, len, 1066223755Shselasky HID_USAGE2(HUP_LEDS, 0x01), 1067223755Shselasky hid_output, 0, &sc->sc_loc_numlock, &flags, 1068223755Shselasky &sc->sc_id_numlock)) { 1069223755Shselasky if (flags & HIO_VARIABLE) 1070223755Shselasky sc->sc_flags |= UKBD_FLAG_NUMLOCK; 1071223755Shselasky DPRINTFN(1, "Found keyboard numlock\n"); 1072223755Shselasky } 1073223755Shselasky if (hid_locate(ptr, len, 1074223755Shselasky HID_USAGE2(HUP_LEDS, 0x02), 1075223755Shselasky hid_output, 0, &sc->sc_loc_capslock, &flags, 1076223755Shselasky &sc->sc_id_capslock)) { 1077223755Shselasky if (flags & HIO_VARIABLE) 1078223755Shselasky sc->sc_flags |= UKBD_FLAG_CAPSLOCK; 1079223755Shselasky DPRINTFN(1, "Found keyboard capslock\n"); 1080223755Shselasky } 1081223755Shselasky if (hid_locate(ptr, len, 1082223755Shselasky HID_USAGE2(HUP_LEDS, 0x03), 1083223755Shselasky hid_output, 0, &sc->sc_loc_scrolllock, &flags, 1084223755Shselasky &sc->sc_id_scrolllock)) { 1085223755Shselasky if (flags & HIO_VARIABLE) 1086223755Shselasky sc->sc_flags |= UKBD_FLAG_SCROLLLOCK; 1087223755Shselasky DPRINTFN(1, "Found keyboard scrolllock\n"); 1088223755Shselasky } 1089223755Shselasky} 1090223755Shselasky 1091184610Salfredstatic int 1092184610Salfredukbd_attach(device_t dev) 1093184610Salfred{ 1094184610Salfred struct ukbd_softc *sc = device_get_softc(dev); 1095192984Sthompsa struct usb_attach_arg *uaa = device_get_ivars(dev); 1096253332Shselasky int unit = device_get_unit(dev); 1097184610Salfred keyboard_t *kbd = &sc->sc_kbd; 1098192925Sthompsa void *hid_ptr = NULL; 1099193045Sthompsa usb_error_t err; 1100184610Salfred uint16_t n; 1101192925Sthompsa uint16_t hid_len; 1102307775Sgonzo#ifdef EVDEV_SUPPORT 1103307764Sgonzo struct evdev_dev *evdev; 1104307764Sgonzo int i; 1105307764Sgonzo#endif 1106253332Shselasky#ifdef USB_DEBUG 1107253332Shselasky int rate; 1108253332Shselasky#endif 1109228765Savg UKBD_LOCK_ASSERT(); 1110228765Savg 1111184610Salfred kbd_init_struct(kbd, UKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0); 1112184610Salfred 1113184610Salfred kbd->kb_data = (void *)sc; 1114184610Salfred 1115194228Sthompsa device_set_usb_desc(dev); 1116184610Salfred 1117184610Salfred sc->sc_udev = uaa->device; 1118184610Salfred sc->sc_iface = uaa->iface; 1119184610Salfred sc->sc_iface_index = uaa->info.bIfaceIndex; 1120184610Salfred sc->sc_iface_no = uaa->info.bIfaceNum; 1121184610Salfred sc->sc_mode = K_XLATE; 1122184610Salfred 1123194228Sthompsa usb_callout_init_mtx(&sc->sc_callout, &Giant, 0); 1124184610Salfred 1125305644Shselasky#ifdef UKBD_NO_POLLING 1126194228Sthompsa err = usbd_transfer_setup(uaa->device, 1127184610Salfred &uaa->info.bIfaceIndex, sc->sc_xfer, ukbd_config, 1128184610Salfred UKBD_N_TRANSFER, sc, &Giant); 1129305644Shselasky#else 1130305644Shselasky /* 1131305644Shselasky * Setup the UKBD USB transfers one by one, so they are memory 1132305644Shselasky * independent which allows for handling panics triggered by 1133305644Shselasky * the keyboard driver itself, typically via CTRL+ALT+ESC 1134305644Shselasky * sequences. Or if the USB keyboard driver was processing a 1135305644Shselasky * key at the moment of panic. 1136305644Shselasky */ 1137305644Shselasky for (n = 0; n != UKBD_N_TRANSFER; n++) { 1138305644Shselasky err = usbd_transfer_setup(uaa->device, 1139305644Shselasky &uaa->info.bIfaceIndex, sc->sc_xfer + n, ukbd_config + n, 1140305644Shselasky 1, sc, &Giant); 1141305644Shselasky if (err) 1142305644Shselasky break; 1143305644Shselasky } 1144305644Shselasky#endif 1145184610Salfred 1146184610Salfred if (err) { 1147194228Sthompsa DPRINTF("error=%s\n", usbd_errstr(err)); 1148184610Salfred goto detach; 1149184610Salfred } 1150184610Salfred /* setup default keyboard maps */ 1151184610Salfred 1152184610Salfred sc->sc_keymap = key_map; 1153184610Salfred sc->sc_accmap = accent_map; 1154184610Salfred for (n = 0; n < UKBD_NFKEY; n++) { 1155184610Salfred sc->sc_fkeymap[n] = fkey_tab[n]; 1156184610Salfred } 1157184610Salfred 1158184610Salfred kbd_set_maps(kbd, &sc->sc_keymap, &sc->sc_accmap, 1159184610Salfred sc->sc_fkeymap, UKBD_NFKEY); 1160184610Salfred 1161184610Salfred KBD_FOUND_DEVICE(kbd); 1162184610Salfred 1163184610Salfred ukbd_clear_state(kbd); 1164184610Salfred 1165184610Salfred /* 1166184610Salfred * FIXME: set the initial value for lock keys in "sc_state" 1167184610Salfred * according to the BIOS data? 1168184610Salfred */ 1169184610Salfred KBD_PROBE_DONE(kbd); 1170184610Salfred 1171223755Shselasky /* get HID descriptor */ 1172194228Sthompsa err = usbd_req_get_hid_desc(uaa->device, NULL, &hid_ptr, 1173192925Sthompsa &hid_len, M_TEMP, uaa->info.bIfaceIndex); 1174223755Shselasky 1175192925Sthompsa if (err == 0) { 1176223755Shselasky DPRINTF("Parsing HID descriptor of %d bytes\n", 1177223755Shselasky (int)hid_len); 1178192925Sthompsa 1179223755Shselasky ukbd_parse_hid(sc, hid_ptr, hid_len); 1180192925Sthompsa 1181192925Sthompsa free(hid_ptr, M_TEMP); 1182192925Sthompsa } 1183192925Sthompsa 1184223755Shselasky /* check if we should use the boot protocol */ 1185223755Shselasky if (usb_test_quirk(uaa, UQ_KBD_BOOTPROTO) || 1186358216Shselasky (err != 0) || ukbd_any_key_valid(sc) == false) { 1187223755Shselasky 1188223755Shselasky DPRINTF("Forcing boot protocol\n"); 1189223755Shselasky 1190223755Shselasky err = usbd_req_set_protocol(sc->sc_udev, NULL, 1191223755Shselasky sc->sc_iface_index, 0); 1192223755Shselasky 1193223755Shselasky if (err != 0) { 1194223755Shselasky DPRINTF("Set protocol error=%s (ignored)\n", 1195223755Shselasky usbd_errstr(err)); 1196223755Shselasky } 1197223755Shselasky 1198223755Shselasky ukbd_parse_hid(sc, ukbd_boot_desc, sizeof(ukbd_boot_desc)); 1199223755Shselasky } 1200223755Shselasky 1201184610Salfred /* ignore if SETIDLE fails, hence it is not crucial */ 1202223755Shselasky usbd_req_set_idle(sc->sc_udev, NULL, sc->sc_iface_index, 0, 0); 1203184610Salfred 1204184610Salfred ukbd_ioctl(kbd, KDSETLED, (caddr_t)&sc->sc_state); 1205184610Salfred 1206184610Salfred KBD_INIT_DONE(kbd); 1207184610Salfred 1208184610Salfred if (kbd_register(kbd) < 0) { 1209184610Salfred goto detach; 1210184610Salfred } 1211184610Salfred KBD_CONFIG_DONE(kbd); 1212184610Salfred 1213184610Salfred ukbd_enable(kbd); 1214184610Salfred 1215184610Salfred#ifdef KBD_INSTALL_CDEV 1216184610Salfred if (kbd_attach(kbd)) { 1217184610Salfred goto detach; 1218184610Salfred } 1219184610Salfred#endif 1220307764Sgonzo 1221307775Sgonzo#ifdef EVDEV_SUPPORT 1222307764Sgonzo evdev = evdev_alloc(); 1223307764Sgonzo evdev_set_name(evdev, device_get_desc(dev)); 1224307764Sgonzo evdev_set_phys(evdev, device_get_nameunit(dev)); 1225307764Sgonzo evdev_set_id(evdev, BUS_USB, uaa->info.idVendor, 1226307764Sgonzo uaa->info.idProduct, 0); 1227307764Sgonzo evdev_set_serial(evdev, usb_get_serial(uaa->device)); 1228307764Sgonzo evdev_set_methods(evdev, kbd, &ukbd_evdev_methods); 1229307764Sgonzo evdev_support_event(evdev, EV_SYN); 1230307764Sgonzo evdev_support_event(evdev, EV_KEY); 1231307764Sgonzo if (sc->sc_flags & (UKBD_FLAG_NUMLOCK | UKBD_FLAG_CAPSLOCK | 1232307764Sgonzo UKBD_FLAG_SCROLLLOCK)) 1233307764Sgonzo evdev_support_event(evdev, EV_LED); 1234307764Sgonzo evdev_support_event(evdev, EV_REP); 1235307764Sgonzo 1236307764Sgonzo for (i = 0x00; i <= 0xFF; i++) 1237307764Sgonzo evdev_support_key(evdev, evdev_hid2key(i)); 1238307764Sgonzo if (sc->sc_flags & UKBD_FLAG_NUMLOCK) 1239307764Sgonzo evdev_support_led(evdev, LED_NUML); 1240307764Sgonzo if (sc->sc_flags & UKBD_FLAG_CAPSLOCK) 1241307764Sgonzo evdev_support_led(evdev, LED_CAPSL); 1242307764Sgonzo if (sc->sc_flags & UKBD_FLAG_SCROLLLOCK) 1243307764Sgonzo evdev_support_led(evdev, LED_SCROLLL); 1244307764Sgonzo 1245307764Sgonzo if (evdev_register(evdev)) 1246307764Sgonzo evdev_free(evdev); 1247307764Sgonzo else 1248307764Sgonzo sc->sc_evdev = evdev; 1249307764Sgonzo#endif 1250307764Sgonzo 1251184610Salfred sc->sc_flags |= UKBD_FLAG_ATTACHED; 1252184610Salfred 1253184610Salfred if (bootverbose) { 1254356012Skevans kbdd_diag(kbd, bootverbose); 1255184610Salfred } 1256184610Salfred 1257253332Shselasky#ifdef USB_DEBUG 1258253332Shselasky /* check for polling rate override */ 1259253332Shselasky rate = ukbd_pollrate; 1260253332Shselasky if (rate > 0) { 1261253332Shselasky if (rate > 1000) 1262253332Shselasky rate = 1; 1263253332Shselasky else 1264253332Shselasky rate = 1000 / rate; 1265253332Shselasky 1266253332Shselasky /* set new polling interval in ms */ 1267305644Shselasky usbd_xfer_set_interval(sc->sc_xfer[UKBD_INTR_DT_0], rate); 1268305644Shselasky usbd_xfer_set_interval(sc->sc_xfer[UKBD_INTR_DT_1], rate); 1269253332Shselasky } 1270253332Shselasky#endif 1271184610Salfred /* start the keyboard */ 1272305644Shselasky usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_0]); 1273305644Shselasky usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_1]); 1274184610Salfred 1275184610Salfred return (0); /* success */ 1276184610Salfred 1277184610Salfreddetach: 1278184610Salfred ukbd_detach(dev); 1279184610Salfred return (ENXIO); /* error */ 1280184610Salfred} 1281184610Salfred 1282193315Sthompsastatic int 1283184610Salfredukbd_detach(device_t dev) 1284184610Salfred{ 1285184610Salfred struct ukbd_softc *sc = device_get_softc(dev); 1286184610Salfred int error; 1287184610Salfred 1288228765Savg UKBD_LOCK_ASSERT(); 1289228765Savg 1290184610Salfred DPRINTF("\n"); 1291184610Salfred 1292184610Salfred sc->sc_flags |= UKBD_FLAG_GONE; 1293184610Salfred 1294194228Sthompsa usb_callout_stop(&sc->sc_callout); 1295184610Salfred 1296261228Shselasky /* kill any stuck keys */ 1297261228Shselasky if (sc->sc_flags & UKBD_FLAG_ATTACHED) { 1298261228Shselasky /* stop receiving events from the USB keyboard */ 1299305644Shselasky usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT_0]); 1300305644Shselasky usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT_1]); 1301261228Shselasky 1302261228Shselasky /* release all leftover keys, if any */ 1303261228Shselasky memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); 1304261228Shselasky 1305261228Shselasky /* process releasing of all keys */ 1306261228Shselasky ukbd_interrupt(sc); 1307261228Shselasky } 1308261228Shselasky 1309184610Salfred ukbd_disable(&sc->sc_kbd); 1310184610Salfred 1311184610Salfred#ifdef KBD_INSTALL_CDEV 1312184610Salfred if (sc->sc_flags & UKBD_FLAG_ATTACHED) { 1313184610Salfred error = kbd_detach(&sc->sc_kbd); 1314184610Salfred if (error) { 1315184610Salfred /* usb attach cannot return an error */ 1316184610Salfred device_printf(dev, "WARNING: kbd_detach() " 1317184610Salfred "returned non-zero! (ignored)\n"); 1318184610Salfred } 1319184610Salfred } 1320184610Salfred#endif 1321307764Sgonzo 1322307775Sgonzo#ifdef EVDEV_SUPPORT 1323307764Sgonzo evdev_free(sc->sc_evdev); 1324307764Sgonzo#endif 1325307764Sgonzo 1326184610Salfred if (KBD_IS_CONFIGURED(&sc->sc_kbd)) { 1327184610Salfred error = kbd_unregister(&sc->sc_kbd); 1328184610Salfred if (error) { 1329184610Salfred /* usb attach cannot return an error */ 1330184610Salfred device_printf(dev, "WARNING: kbd_unregister() " 1331184610Salfred "returned non-zero! (ignored)\n"); 1332184610Salfred } 1333184610Salfred } 1334184610Salfred sc->sc_kbd.kb_flags = 0; 1335184610Salfred 1336194228Sthompsa usbd_transfer_unsetup(sc->sc_xfer, UKBD_N_TRANSFER); 1337184610Salfred 1338194228Sthompsa usb_callout_drain(&sc->sc_callout); 1339184610Salfred 1340184610Salfred DPRINTF("%s: disconnected\n", 1341184610Salfred device_get_nameunit(dev)); 1342184610Salfred 1343184610Salfred return (0); 1344184610Salfred} 1345184610Salfred 1346184610Salfredstatic int 1347184610Salfredukbd_resume(device_t dev) 1348184610Salfred{ 1349184610Salfred struct ukbd_softc *sc = device_get_softc(dev); 1350184610Salfred 1351228765Savg UKBD_LOCK_ASSERT(); 1352203896Sthompsa 1353184610Salfred ukbd_clear_state(&sc->sc_kbd); 1354184610Salfred 1355184610Salfred return (0); 1356184610Salfred} 1357184610Salfred 1358184610Salfred/* early keyboard probe, not supported */ 1359184610Salfredstatic int 1360184610Salfredukbd_configure(int flags) 1361184610Salfred{ 1362184610Salfred return (0); 1363184610Salfred} 1364184610Salfred 1365184610Salfred/* detect a keyboard, not used */ 1366184610Salfredstatic int 1367184610Salfredukbd__probe(int unit, void *arg, int flags) 1368184610Salfred{ 1369184610Salfred return (ENXIO); 1370184610Salfred} 1371184610Salfred 1372184610Salfred/* reset and initialize the device, not used */ 1373184610Salfredstatic int 1374184610Salfredukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) 1375184610Salfred{ 1376184610Salfred return (ENXIO); 1377184610Salfred} 1378184610Salfred 1379184610Salfred/* test the interface to the device, not used */ 1380184610Salfredstatic int 1381184610Salfredukbd_test_if(keyboard_t *kbd) 1382184610Salfred{ 1383184610Salfred return (0); 1384184610Salfred} 1385184610Salfred 1386184610Salfred/* finish using this keyboard, not used */ 1387184610Salfredstatic int 1388184610Salfredukbd_term(keyboard_t *kbd) 1389184610Salfred{ 1390184610Salfred return (ENXIO); 1391184610Salfred} 1392184610Salfred 1393184610Salfred/* keyboard interrupt routine, not used */ 1394184610Salfredstatic int 1395184610Salfredukbd_intr(keyboard_t *kbd, void *arg) 1396184610Salfred{ 1397184610Salfred return (0); 1398184610Salfred} 1399184610Salfred 1400184610Salfred/* lock the access to the keyboard, not used */ 1401184610Salfredstatic int 1402184610Salfredukbd_lock(keyboard_t *kbd, int lock) 1403184610Salfred{ 1404184610Salfred return (1); 1405184610Salfred} 1406184610Salfred 1407184610Salfred/* 1408184610Salfred * Enable the access to the device; until this function is called, 1409184610Salfred * the client cannot read from the keyboard. 1410184610Salfred */ 1411184610Salfredstatic int 1412184610Salfredukbd_enable(keyboard_t *kbd) 1413184610Salfred{ 1414228765Savg 1415228765Savg UKBD_LOCK(); 1416184610Salfred KBD_ACTIVATE(kbd); 1417228765Savg UKBD_UNLOCK(); 1418228765Savg 1419184610Salfred return (0); 1420184610Salfred} 1421184610Salfred 1422184610Salfred/* disallow the access to the device */ 1423184610Salfredstatic int 1424184610Salfredukbd_disable(keyboard_t *kbd) 1425184610Salfred{ 1426228765Savg 1427228765Savg UKBD_LOCK(); 1428184610Salfred KBD_DEACTIVATE(kbd); 1429228765Savg UKBD_UNLOCK(); 1430228765Savg 1431184610Salfred return (0); 1432184610Salfred} 1433184610Salfred 1434184610Salfred/* check if data is waiting */ 1435228765Savg/* Currently unused. */ 1436184610Salfredstatic int 1437184610Salfredukbd_check(keyboard_t *kbd) 1438184610Salfred{ 1439184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1440184610Salfred 1441228765Savg UKBD_CTX_LOCK_ASSERT(); 1442228765Savg 1443195960Salfred if (!KBD_IS_ACTIVE(kbd)) 1444195960Salfred return (0); 1445195960Salfred 1446203896Sthompsa if (sc->sc_flags & UKBD_FLAG_POLLING) 1447203896Sthompsa ukbd_do_poll(sc, 0); 1448203896Sthompsa 1449184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1450184610Salfred if (sc->sc_buffered_char[0]) { 1451184610Salfred return (1); 1452184610Salfred } 1453184610Salfred#endif 1454184610Salfred if (sc->sc_inputs > 0) { 1455184610Salfred return (1); 1456184610Salfred } 1457184610Salfred return (0); 1458184610Salfred} 1459184610Salfred 1460184610Salfred/* check if char is waiting */ 1461184610Salfredstatic int 1462228765Savgukbd_check_char_locked(keyboard_t *kbd) 1463184610Salfred{ 1464184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1465184610Salfred 1466228765Savg UKBD_CTX_LOCK_ASSERT(); 1467228765Savg 1468195960Salfred if (!KBD_IS_ACTIVE(kbd)) 1469195960Salfred return (0); 1470195960Salfred 1471184610Salfred if ((sc->sc_composed_char > 0) && 1472184610Salfred (!(sc->sc_flags & UKBD_FLAG_COMPOSE))) { 1473184610Salfred return (1); 1474184610Salfred } 1475184610Salfred return (ukbd_check(kbd)); 1476184610Salfred} 1477184610Salfred 1478228765Savgstatic int 1479228765Savgukbd_check_char(keyboard_t *kbd) 1480228765Savg{ 1481228765Savg int result; 1482184610Salfred 1483228765Savg UKBD_LOCK(); 1484228765Savg result = ukbd_check_char_locked(kbd); 1485228765Savg UKBD_UNLOCK(); 1486228765Savg 1487228765Savg return (result); 1488228765Savg} 1489228765Savg 1490184610Salfred/* read one byte from the keyboard if it's allowed */ 1491228765Savg/* Currently unused. */ 1492184610Salfredstatic int 1493184610Salfredukbd_read(keyboard_t *kbd, int wait) 1494184610Salfred{ 1495184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1496184610Salfred int32_t usbcode; 1497184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1498184610Salfred uint32_t keycode; 1499184610Salfred uint32_t scancode; 1500184610Salfred 1501184610Salfred#endif 1502184610Salfred 1503228765Savg UKBD_CTX_LOCK_ASSERT(); 1504184610Salfred 1505228765Savg if (!KBD_IS_ACTIVE(kbd)) 1506203896Sthompsa return (-1); 1507203896Sthompsa 1508184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1509184610Salfred if (sc->sc_buffered_char[0]) { 1510184610Salfred scancode = sc->sc_buffered_char[0]; 1511184610Salfred if (scancode & SCAN_PREFIX) { 1512184610Salfred sc->sc_buffered_char[0] &= ~SCAN_PREFIX; 1513184610Salfred return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); 1514184610Salfred } 1515184610Salfred sc->sc_buffered_char[0] = sc->sc_buffered_char[1]; 1516184610Salfred sc->sc_buffered_char[1] = 0; 1517184610Salfred return (scancode); 1518184610Salfred } 1519184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 1520184610Salfred 1521184610Salfred /* XXX */ 1522184610Salfred usbcode = ukbd_get_key(sc, (wait == FALSE) ? 0 : 1); 1523195960Salfred if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) 1524195960Salfred return (-1); 1525195960Salfred 1526184610Salfred ++(kbd->kb_count); 1527184610Salfred 1528184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1529358216Shselasky keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.bitmap); 1530184610Salfred if (keycode == NN) { 1531184610Salfred return -1; 1532184610Salfred } 1533358216Shselasky return (ukbd_key2scan(sc, keycode, sc->sc_ndata.bitmap, 1534184610Salfred (usbcode & KEY_RELEASE))); 1535184610Salfred#else /* !UKBD_EMULATE_ATSCANCODE */ 1536184610Salfred return (usbcode); 1537184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 1538184610Salfred} 1539184610Salfred 1540184610Salfred/* read char from the keyboard */ 1541184610Salfredstatic uint32_t 1542228765Savgukbd_read_char_locked(keyboard_t *kbd, int wait) 1543184610Salfred{ 1544184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1545184610Salfred uint32_t action; 1546184610Salfred uint32_t keycode; 1547184610Salfred int32_t usbcode; 1548184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1549184610Salfred uint32_t scancode; 1550184610Salfred#endif 1551195960Salfred 1552228765Savg UKBD_CTX_LOCK_ASSERT(); 1553228765Savg 1554195960Salfred if (!KBD_IS_ACTIVE(kbd)) 1555195960Salfred return (NOKEY); 1556195960Salfred 1557184610Salfrednext_code: 1558184610Salfred 1559184610Salfred /* do we have a composed char to return ? */ 1560184610Salfred 1561184610Salfred if ((sc->sc_composed_char > 0) && 1562184610Salfred (!(sc->sc_flags & UKBD_FLAG_COMPOSE))) { 1563184610Salfred 1564184610Salfred action = sc->sc_composed_char; 1565184610Salfred sc->sc_composed_char = 0; 1566184610Salfred 1567184610Salfred if (action > 0xFF) { 1568184610Salfred goto errkey; 1569184610Salfred } 1570184610Salfred goto done; 1571184610Salfred } 1572184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1573184610Salfred 1574184610Salfred /* do we have a pending raw scan code? */ 1575184610Salfred 1576184610Salfred if (sc->sc_mode == K_RAW) { 1577184610Salfred scancode = sc->sc_buffered_char[0]; 1578184610Salfred if (scancode) { 1579184610Salfred if (scancode & SCAN_PREFIX) { 1580184610Salfred sc->sc_buffered_char[0] = (scancode & ~SCAN_PREFIX); 1581184610Salfred return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); 1582184610Salfred } 1583184610Salfred sc->sc_buffered_char[0] = sc->sc_buffered_char[1]; 1584184610Salfred sc->sc_buffered_char[1] = 0; 1585184610Salfred return (scancode); 1586184610Salfred } 1587184610Salfred } 1588184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 1589184610Salfred 1590184610Salfred /* see if there is something in the keyboard port */ 1591184610Salfred /* XXX */ 1592184610Salfred usbcode = ukbd_get_key(sc, (wait == FALSE) ? 0 : 1); 1593184610Salfred if (usbcode == -1) { 1594184610Salfred return (NOKEY); 1595184610Salfred } 1596184610Salfred ++kbd->kb_count; 1597184610Salfred 1598184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1599184610Salfred /* USB key index -> key code -> AT scan code */ 1600358216Shselasky keycode = ukbd_atkeycode(usbcode, sc->sc_ndata.bitmap); 1601184610Salfred if (keycode == NN) { 1602184610Salfred return (NOKEY); 1603184610Salfred } 1604184610Salfred /* return an AT scan code for the K_RAW mode */ 1605184610Salfred if (sc->sc_mode == K_RAW) { 1606358216Shselasky return (ukbd_key2scan(sc, keycode, sc->sc_ndata.bitmap, 1607184610Salfred (usbcode & KEY_RELEASE))); 1608184610Salfred } 1609184610Salfred#else /* !UKBD_EMULATE_ATSCANCODE */ 1610184610Salfred 1611184610Salfred /* return the byte as is for the K_RAW mode */ 1612184610Salfred if (sc->sc_mode == K_RAW) { 1613184610Salfred return (usbcode); 1614184610Salfred } 1615184610Salfred /* USB key index -> key code */ 1616184610Salfred keycode = ukbd_trtab[KEY_INDEX(usbcode)]; 1617184610Salfred if (keycode == NN) { 1618184610Salfred return (NOKEY); 1619184610Salfred } 1620184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 1621184610Salfred 1622184610Salfred switch (keycode) { 1623184610Salfred case 0x38: /* left alt (compose key) */ 1624184610Salfred if (usbcode & KEY_RELEASE) { 1625184610Salfred if (sc->sc_flags & UKBD_FLAG_COMPOSE) { 1626184610Salfred sc->sc_flags &= ~UKBD_FLAG_COMPOSE; 1627184610Salfred 1628184610Salfred if (sc->sc_composed_char > 0xFF) { 1629184610Salfred sc->sc_composed_char = 0; 1630184610Salfred } 1631184610Salfred } 1632184610Salfred } else { 1633184610Salfred if (!(sc->sc_flags & UKBD_FLAG_COMPOSE)) { 1634184610Salfred sc->sc_flags |= UKBD_FLAG_COMPOSE; 1635184610Salfred sc->sc_composed_char = 0; 1636184610Salfred } 1637184610Salfred } 1638184610Salfred break; 1639184610Salfred } 1640184610Salfred 1641184610Salfred /* return the key code in the K_CODE mode */ 1642184610Salfred if (usbcode & KEY_RELEASE) { 1643184610Salfred keycode |= SCAN_RELEASE; 1644184610Salfred } 1645184610Salfred if (sc->sc_mode == K_CODE) { 1646184610Salfred return (keycode); 1647184610Salfred } 1648184610Salfred /* compose a character code */ 1649184610Salfred if (sc->sc_flags & UKBD_FLAG_COMPOSE) { 1650184610Salfred switch (keycode) { 1651184610Salfred /* key pressed, process it */ 1652184610Salfred case 0x47: 1653184610Salfred case 0x48: 1654184610Salfred case 0x49: /* keypad 7,8,9 */ 1655184610Salfred sc->sc_composed_char *= 10; 1656184610Salfred sc->sc_composed_char += keycode - 0x40; 1657184610Salfred goto check_composed; 1658184610Salfred 1659184610Salfred case 0x4B: 1660184610Salfred case 0x4C: 1661184610Salfred case 0x4D: /* keypad 4,5,6 */ 1662184610Salfred sc->sc_composed_char *= 10; 1663184610Salfred sc->sc_composed_char += keycode - 0x47; 1664184610Salfred goto check_composed; 1665184610Salfred 1666184610Salfred case 0x4F: 1667184610Salfred case 0x50: 1668184610Salfred case 0x51: /* keypad 1,2,3 */ 1669184610Salfred sc->sc_composed_char *= 10; 1670184610Salfred sc->sc_composed_char += keycode - 0x4E; 1671184610Salfred goto check_composed; 1672184610Salfred 1673184610Salfred case 0x52: /* keypad 0 */ 1674184610Salfred sc->sc_composed_char *= 10; 1675184610Salfred goto check_composed; 1676184610Salfred 1677184610Salfred /* key released, no interest here */ 1678184610Salfred case SCAN_RELEASE | 0x47: 1679184610Salfred case SCAN_RELEASE | 0x48: 1680184610Salfred case SCAN_RELEASE | 0x49: /* keypad 7,8,9 */ 1681184610Salfred case SCAN_RELEASE | 0x4B: 1682184610Salfred case SCAN_RELEASE | 0x4C: 1683184610Salfred case SCAN_RELEASE | 0x4D: /* keypad 4,5,6 */ 1684184610Salfred case SCAN_RELEASE | 0x4F: 1685184610Salfred case SCAN_RELEASE | 0x50: 1686184610Salfred case SCAN_RELEASE | 0x51: /* keypad 1,2,3 */ 1687184610Salfred case SCAN_RELEASE | 0x52: /* keypad 0 */ 1688184610Salfred goto next_code; 1689184610Salfred 1690184610Salfred case 0x38: /* left alt key */ 1691184610Salfred break; 1692184610Salfred 1693184610Salfred default: 1694184610Salfred if (sc->sc_composed_char > 0) { 1695184610Salfred sc->sc_flags &= ~UKBD_FLAG_COMPOSE; 1696184610Salfred sc->sc_composed_char = 0; 1697184610Salfred goto errkey; 1698184610Salfred } 1699184610Salfred break; 1700184610Salfred } 1701184610Salfred } 1702184610Salfred /* keycode to key action */ 1703184610Salfred action = genkbd_keyaction(kbd, SCAN_CHAR(keycode), 1704184610Salfred (keycode & SCAN_RELEASE), 1705184610Salfred &sc->sc_state, &sc->sc_accents); 1706184610Salfred if (action == NOKEY) { 1707184610Salfred goto next_code; 1708184610Salfred } 1709184610Salfreddone: 1710184610Salfred return (action); 1711184610Salfred 1712184610Salfredcheck_composed: 1713184610Salfred if (sc->sc_composed_char <= 0xFF) { 1714184610Salfred goto next_code; 1715184610Salfred } 1716184610Salfrederrkey: 1717184610Salfred return (ERRKEY); 1718184610Salfred} 1719184610Salfred 1720228765Savg/* Currently wait is always false. */ 1721228765Savgstatic uint32_t 1722228765Savgukbd_read_char(keyboard_t *kbd, int wait) 1723228765Savg{ 1724228765Savg uint32_t keycode; 1725228765Savg 1726228765Savg UKBD_LOCK(); 1727228765Savg keycode = ukbd_read_char_locked(kbd, wait); 1728228765Savg UKBD_UNLOCK(); 1729228765Savg 1730228765Savg return (keycode); 1731228765Savg} 1732228765Savg 1733184610Salfred/* some useful control functions */ 1734184610Salfredstatic int 1735228765Savgukbd_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg) 1736184610Salfred{ 1737184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1738184610Salfred int i; 1739184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1740184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1741184610Salfred int ival; 1742184610Salfred 1743184610Salfred#endif 1744184610Salfred 1745228765Savg UKBD_LOCK_ASSERT(); 1746228765Savg 1747184610Salfred switch (cmd) { 1748184610Salfred case KDGKBMODE: /* get keyboard mode */ 1749184610Salfred *(int *)arg = sc->sc_mode; 1750184610Salfred break; 1751184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1752184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1753184610Salfred case _IO('K', 7): 1754184610Salfred ival = IOCPARM_IVAL(arg); 1755184610Salfred arg = (caddr_t)&ival; 1756184610Salfred /* FALLTHROUGH */ 1757184610Salfred#endif 1758184610Salfred case KDSKBMODE: /* set keyboard mode */ 1759184610Salfred switch (*(int *)arg) { 1760184610Salfred case K_XLATE: 1761184610Salfred if (sc->sc_mode != K_XLATE) { 1762184610Salfred /* make lock key state and LED state match */ 1763184610Salfred sc->sc_state &= ~LOCK_MASK; 1764184610Salfred sc->sc_state |= KBD_LED_VAL(kbd); 1765184610Salfred } 1766184610Salfred /* FALLTHROUGH */ 1767184610Salfred case K_RAW: 1768184610Salfred case K_CODE: 1769184610Salfred if (sc->sc_mode != *(int *)arg) { 1770228765Savg if ((sc->sc_flags & UKBD_FLAG_POLLING) == 0) 1771203896Sthompsa ukbd_clear_state(kbd); 1772184610Salfred sc->sc_mode = *(int *)arg; 1773184610Salfred } 1774184610Salfred break; 1775184610Salfred default: 1776184610Salfred return (EINVAL); 1777184610Salfred } 1778184610Salfred break; 1779184610Salfred 1780184610Salfred case KDGETLED: /* get keyboard LED */ 1781184610Salfred *(int *)arg = KBD_LED_VAL(kbd); 1782184610Salfred break; 1783184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1784184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1785184610Salfred case _IO('K', 66): 1786184610Salfred ival = IOCPARM_IVAL(arg); 1787184610Salfred arg = (caddr_t)&ival; 1788184610Salfred /* FALLTHROUGH */ 1789184610Salfred#endif 1790184610Salfred case KDSETLED: /* set keyboard LED */ 1791184610Salfred /* NOTE: lock key state in "sc_state" won't be changed */ 1792223755Shselasky if (*(int *)arg & ~LOCK_MASK) 1793184610Salfred return (EINVAL); 1794223755Shselasky 1795184610Salfred i = *(int *)arg; 1796223755Shselasky 1797184610Salfred /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ 1798184610Salfred if (sc->sc_mode == K_XLATE && 1799184610Salfred kbd->kb_keymap->n_keys > ALTGR_OFFSET) { 1800184610Salfred if (i & ALKED) 1801184610Salfred i |= CLKED; 1802184610Salfred else 1803184610Salfred i &= ~CLKED; 1804184610Salfred } 1805223755Shselasky if (KBD_HAS_DEVICE(kbd)) 1806223755Shselasky ukbd_set_leds(sc, i); 1807223755Shselasky 1808184610Salfred KBD_LED_VAL(kbd) = *(int *)arg; 1809184610Salfred break; 1810184610Salfred case KDGKBSTATE: /* get lock key state */ 1811184610Salfred *(int *)arg = sc->sc_state & LOCK_MASK; 1812184610Salfred break; 1813184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1814184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1815184610Salfred case _IO('K', 20): 1816184610Salfred ival = IOCPARM_IVAL(arg); 1817184610Salfred arg = (caddr_t)&ival; 1818184610Salfred /* FALLTHROUGH */ 1819184610Salfred#endif 1820184610Salfred case KDSKBSTATE: /* set lock key state */ 1821184610Salfred if (*(int *)arg & ~LOCK_MASK) { 1822184610Salfred return (EINVAL); 1823184610Salfred } 1824184610Salfred sc->sc_state &= ~LOCK_MASK; 1825184610Salfred sc->sc_state |= *(int *)arg; 1826184610Salfred 1827184610Salfred /* set LEDs and quit */ 1828184610Salfred return (ukbd_ioctl(kbd, KDSETLED, arg)); 1829184610Salfred 1830184610Salfred case KDSETREPEAT: /* set keyboard repeat rate (new 1831184610Salfred * interface) */ 1832184610Salfred if (!KBD_HAS_DEVICE(kbd)) { 1833184610Salfred return (0); 1834184610Salfred } 1835358214Shselasky /* 1836358214Shselasky * Convert negative, zero and tiny args to the same limits 1837358214Shselasky * as atkbd. We could support delays of 1 msec, but 1838358214Shselasky * anything much shorter than the shortest atkbd value 1839358214Shselasky * of 250.34 is almost unusable as well as incompatible. 1840358214Shselasky */ 1841358214Shselasky kbd->kb_delay1 = imax(((int *)arg)[0], 250); 1842358214Shselasky kbd->kb_delay2 = imax(((int *)arg)[1], 34); 1843307775Sgonzo#ifdef EVDEV_SUPPORT 1844307764Sgonzo if (sc->sc_evdev != NULL) 1845307764Sgonzo evdev_push_repeats(sc->sc_evdev, kbd); 1846307764Sgonzo#endif 1847184610Salfred return (0); 1848184610Salfred 1849184610Salfred#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 1850184610Salfred defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 1851184610Salfred case _IO('K', 67): 1852184610Salfred ival = IOCPARM_IVAL(arg); 1853184610Salfred arg = (caddr_t)&ival; 1854184610Salfred /* FALLTHROUGH */ 1855184610Salfred#endif 1856184610Salfred case KDSETRAD: /* set keyboard repeat rate (old 1857184610Salfred * interface) */ 1858184610Salfred return (ukbd_set_typematic(kbd, *(int *)arg)); 1859184610Salfred 1860184610Salfred case PIO_KEYMAP: /* set keyboard translation table */ 1861224126Sed case OPIO_KEYMAP: /* set keyboard translation table 1862224126Sed * (compat) */ 1863184610Salfred case PIO_KEYMAPENT: /* set keyboard translation table 1864184610Salfred * entry */ 1865184610Salfred case PIO_DEADKEYMAP: /* set accent key translation table */ 1866184610Salfred sc->sc_accents = 0; 1867184610Salfred /* FALLTHROUGH */ 1868184610Salfred default: 1869184610Salfred return (genkbd_commonioctl(kbd, cmd, arg)); 1870184610Salfred } 1871184610Salfred 1872184610Salfred return (0); 1873184610Salfred} 1874184610Salfred 1875228765Savgstatic int 1876228765Savgukbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 1877228765Savg{ 1878228765Savg int result; 1879228765Savg 1880228765Savg /* 1881263262Shselasky * XXX Check if someone is calling us from a critical section: 1882262972Shselasky */ 1883262972Shselasky if (curthread->td_critnest != 0) 1884262972Shselasky return (EDEADLK); 1885262972Shselasky 1886262972Shselasky /* 1887228765Savg * XXX KDGKBSTATE, KDSKBSTATE and KDSETLED can be called from any 1888228765Savg * context where printf(9) can be called, which among other things 1889228765Savg * includes interrupt filters and threads with any kinds of locks 1890228765Savg * already held. For this reason it would be dangerous to acquire 1891228765Savg * the Giant here unconditionally. On the other hand we have to 1892228765Savg * have it to handle the ioctl. 1893228765Savg * So we make our best effort to auto-detect whether we can grab 1894228765Savg * the Giant or not. Blame syscons(4) for this. 1895228765Savg */ 1896228765Savg switch (cmd) { 1897228765Savg case KDGKBSTATE: 1898228765Savg case KDSKBSTATE: 1899228765Savg case KDSETLED: 1900228765Savg if (!mtx_owned(&Giant) && !SCHEDULER_STOPPED()) 1901228765Savg return (EDEADLK); /* best I could come up with */ 1902228765Savg /* FALLTHROUGH */ 1903228765Savg default: 1904228765Savg UKBD_LOCK(); 1905228765Savg result = ukbd_ioctl_locked(kbd, cmd, arg); 1906228765Savg UKBD_UNLOCK(); 1907228765Savg return (result); 1908228765Savg } 1909228765Savg} 1910228765Savg 1911228765Savg 1912184610Salfred/* clear the internal state of the keyboard */ 1913184610Salfredstatic void 1914184610Salfredukbd_clear_state(keyboard_t *kbd) 1915184610Salfred{ 1916184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1917184610Salfred 1918228765Savg UKBD_CTX_LOCK_ASSERT(); 1919184610Salfred 1920184610Salfred sc->sc_flags &= ~(UKBD_FLAG_COMPOSE | UKBD_FLAG_POLLING); 1921184610Salfred sc->sc_state &= LOCK_MASK; /* preserve locking key state */ 1922184610Salfred sc->sc_accents = 0; 1923184610Salfred sc->sc_composed_char = 0; 1924184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 1925184610Salfred sc->sc_buffered_char[0] = 0; 1926184610Salfred sc->sc_buffered_char[1] = 0; 1927184610Salfred#endif 1928203896Sthompsa memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); 1929203896Sthompsa memset(&sc->sc_odata, 0, sizeof(sc->sc_odata)); 1930358216Shselasky sc->sc_repeat_time = 0; 1931358216Shselasky sc->sc_repeat_key = 0; 1932184610Salfred} 1933184610Salfred 1934184610Salfred/* save the internal state, not used */ 1935184610Salfredstatic int 1936184610Salfredukbd_get_state(keyboard_t *kbd, void *buf, size_t len) 1937184610Salfred{ 1938184610Salfred return (len == 0) ? 1 : -1; 1939184610Salfred} 1940184610Salfred 1941184610Salfred/* set the internal state, not used */ 1942184610Salfredstatic int 1943184610Salfredukbd_set_state(keyboard_t *kbd, void *buf, size_t len) 1944184610Salfred{ 1945184610Salfred return (EINVAL); 1946184610Salfred} 1947184610Salfred 1948184610Salfredstatic int 1949184610Salfredukbd_poll(keyboard_t *kbd, int on) 1950184610Salfred{ 1951184610Salfred struct ukbd_softc *sc = kbd->kb_data; 1952184610Salfred 1953228765Savg UKBD_LOCK(); 1954304124Shselasky /* 1955304124Shselasky * Keep a reference count on polling to allow recursive 1956304124Shselasky * cngrab() during a panic for example. 1957304124Shselasky */ 1958304124Shselasky if (on) 1959304124Shselasky sc->sc_polling++; 1960305644Shselasky else if (sc->sc_polling > 0) 1961304124Shselasky sc->sc_polling--; 1962304124Shselasky 1963304124Shselasky if (sc->sc_polling != 0) { 1964184610Salfred sc->sc_flags |= UKBD_FLAG_POLLING; 1965203896Sthompsa sc->sc_poll_thread = curthread; 1966184610Salfred } else { 1967184610Salfred sc->sc_flags &= ~UKBD_FLAG_POLLING; 1968358215Shselasky sc->sc_delay = 0; 1969184610Salfred } 1970228765Savg UKBD_UNLOCK(); 1971228765Savg 1972184610Salfred return (0); 1973184610Salfred} 1974184610Salfred 1975184610Salfred/* local functions */ 1976184610Salfred 1977184610Salfredstatic void 1978184610Salfredukbd_set_leds(struct ukbd_softc *sc, uint8_t leds) 1979184610Salfred{ 1980228765Savg 1981228765Savg UKBD_LOCK_ASSERT(); 1982184610Salfred DPRINTF("leds=0x%02x\n", leds); 1983184610Salfred 1984184610Salfred sc->sc_leds = leds; 1985184610Salfred sc->sc_flags |= UKBD_FLAG_SET_LEDS; 1986184610Salfred 1987184610Salfred /* start transfer, if not already started */ 1988184610Salfred 1989194228Sthompsa usbd_transfer_start(sc->sc_xfer[UKBD_CTRL_LED]); 1990184610Salfred} 1991184610Salfred 1992184610Salfredstatic int 1993184610Salfredukbd_set_typematic(keyboard_t *kbd, int code) 1994184610Salfred{ 1995307775Sgonzo#ifdef EVDEV_SUPPORT 1996307764Sgonzo struct ukbd_softc *sc = kbd->kb_data; 1997307764Sgonzo#endif 1998184610Salfred static const int delays[] = {250, 500, 750, 1000}; 1999184610Salfred static const int rates[] = {34, 38, 42, 46, 50, 55, 59, 63, 2000184610Salfred 68, 76, 84, 92, 100, 110, 118, 126, 2001184610Salfred 136, 152, 168, 184, 200, 220, 236, 252, 2002184610Salfred 272, 304, 336, 368, 400, 440, 472, 504}; 2003184610Salfred 2004184610Salfred if (code & ~0x7f) { 2005184610Salfred return (EINVAL); 2006184610Salfred } 2007184610Salfred kbd->kb_delay1 = delays[(code >> 5) & 3]; 2008184610Salfred kbd->kb_delay2 = rates[code & 0x1f]; 2009307775Sgonzo#ifdef EVDEV_SUPPORT 2010307764Sgonzo if (sc->sc_evdev != NULL) 2011307764Sgonzo evdev_push_repeats(sc->sc_evdev, kbd); 2012307764Sgonzo#endif 2013184610Salfred return (0); 2014184610Salfred} 2015184610Salfred 2016184610Salfred#ifdef UKBD_EMULATE_ATSCANCODE 2017358213Shselaskystatic uint32_t 2018358216Shselaskyukbd_atkeycode(int usbcode, const uint64_t *bitmap) 2019358213Shselasky{ 2020358213Shselasky uint32_t keycode; 2021358213Shselasky 2022358213Shselasky keycode = ukbd_trtab[KEY_INDEX(usbcode)]; 2023358216Shselasky 2024358213Shselasky /* 2025358213Shselasky * Translate Alt-PrintScreen to SysRq. 2026358213Shselasky * 2027358213Shselasky * Some or all AT keyboards connected through USB have already 2028358213Shselasky * mapped Alted PrintScreens to an unusual usbcode (0x8a). 2029358213Shselasky * ukbd_trtab translates this to 0x7e, and key2scan() would 2030358213Shselasky * translate that to 0x79 (Intl' 4). Assume that if we have 2031358213Shselasky * an Alted 0x7e here then it actually is an Alted PrintScreen. 2032358213Shselasky * 2033358213Shselasky * The usual usbcode for all PrintScreens is 0x46. ukbd_trtab 2034358213Shselasky * translates this to 0x5c, so the Alt check to classify 0x5c 2035358213Shselasky * is routine. 2036358213Shselasky */ 2037358213Shselasky if ((keycode == 0x5c || keycode == 0x7e) && 2038358216Shselasky (UKBD_KEY_PRESSED(bitmap, 0xe2 /* ALT-L */) || 2039358216Shselasky UKBD_KEY_PRESSED(bitmap, 0xe6 /* ALT-R */))) 2040358213Shselasky return (0x54); 2041358213Shselasky return (keycode); 2042358213Shselasky} 2043358213Shselasky 2044184610Salfredstatic int 2045358216Shselaskyukbd_key2scan(struct ukbd_softc *sc, int code, const uint64_t *bitmap, int up) 2046184610Salfred{ 2047184610Salfred static const int scan[] = { 2048197999Shrs /* 89 */ 2049197999Shrs 0x11c, /* Enter */ 2050197999Shrs /* 90-99 */ 2051197999Shrs 0x11d, /* Ctrl-R */ 2052197999Shrs 0x135, /* Divide */ 2053358212Shselasky 0x137, /* PrintScreen */ 2054197999Shrs 0x138, /* Alt-R */ 2055197999Shrs 0x147, /* Home */ 2056197999Shrs 0x148, /* Up */ 2057197999Shrs 0x149, /* PageUp */ 2058197999Shrs 0x14b, /* Left */ 2059197999Shrs 0x14d, /* Right */ 2060197999Shrs 0x14f, /* End */ 2061197999Shrs /* 100-109 */ 2062197999Shrs 0x150, /* Down */ 2063197999Shrs 0x151, /* PageDown */ 2064197999Shrs 0x152, /* Insert */ 2065197999Shrs 0x153, /* Delete */ 2066358213Shselasky 0x146, /* Pause/Break */ 2067197999Shrs 0x15b, /* Win_L(Super_L) */ 2068197999Shrs 0x15c, /* Win_R(Super_R) */ 2069197999Shrs 0x15d, /* Application(Menu) */ 2070197999Shrs 2071184610Salfred /* SUN TYPE 6 USB KEYBOARD */ 2072197999Shrs 0x168, /* Sun Type 6 Help */ 2073197999Shrs 0x15e, /* Sun Type 6 Stop */ 2074197999Shrs /* 110 - 119 */ 2075197999Shrs 0x15f, /* Sun Type 6 Again */ 2076197999Shrs 0x160, /* Sun Type 6 Props */ 2077197999Shrs 0x161, /* Sun Type 6 Undo */ 2078197999Shrs 0x162, /* Sun Type 6 Front */ 2079197999Shrs 0x163, /* Sun Type 6 Copy */ 2080197999Shrs 0x164, /* Sun Type 6 Open */ 2081197999Shrs 0x165, /* Sun Type 6 Paste */ 2082197999Shrs 0x166, /* Sun Type 6 Find */ 2083197999Shrs 0x167, /* Sun Type 6 Cut */ 2084197999Shrs 0x125, /* Sun Type 6 Mute */ 2085291146Shselasky /* 120 - 130 */ 2086197999Shrs 0x11f, /* Sun Type 6 VolumeDown */ 2087197999Shrs 0x11e, /* Sun Type 6 VolumeUp */ 2088197999Shrs 0x120, /* Sun Type 6 PowerDown */ 2089197999Shrs 2090197999Shrs /* Japanese 106/109 keyboard */ 2091197999Shrs 0x73, /* Keyboard Intl' 1 (backslash / underscore) */ 2092197999Shrs 0x70, /* Keyboard Intl' 2 (Katakana / Hiragana) */ 2093197999Shrs 0x7d, /* Keyboard Intl' 3 (Yen sign) (Not using in jp106/109) */ 2094197999Shrs 0x79, /* Keyboard Intl' 4 (Henkan) */ 2095197999Shrs 0x7b, /* Keyboard Intl' 5 (Muhenkan) */ 2096197999Shrs 0x5c, /* Keyboard Intl' 6 (Keypad ,) (For PC-9821 layout) */ 2097291146Shselasky 0x71, /* Apple Keyboard JIS (Kana) */ 2098291146Shselasky 0x72, /* Apple Keyboard JIS (Eisu) */ 2099184610Salfred }; 2100184610Salfred 2101298300Spfg if ((code >= 89) && (code < (int)(89 + nitems(scan)))) { 2102197999Shrs code = scan[code - 89]; 2103184610Salfred } 2104358212Shselasky /* PrintScreen */ 2105358216Shselasky if (code == 0x137 && (!( 2106358216Shselasky UKBD_KEY_PRESSED(bitmap, 0xe0 /* CTRL-L */) || 2107358216Shselasky UKBD_KEY_PRESSED(bitmap, 0xe4 /* CTRL-R */) || 2108358216Shselasky UKBD_KEY_PRESSED(bitmap, 0xe1 /* SHIFT-L */) || 2109358216Shselasky UKBD_KEY_PRESSED(bitmap, 0xe5 /* SHIFT-R */)))) { 2110358212Shselasky code |= SCAN_PREFIX_SHIFT; 2111358212Shselasky } 2112184610Salfred /* Pause/Break */ 2113358216Shselasky if ((code == 0x146) && (!( 2114358216Shselasky UKBD_KEY_PRESSED(bitmap, 0xe0 /* CTRL-L */) || 2115358216Shselasky UKBD_KEY_PRESSED(bitmap, 0xe4 /* CTRL-R */)))) { 2116184610Salfred code = (0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL); 2117184610Salfred } 2118184610Salfred code |= (up ? SCAN_RELEASE : SCAN_PRESS); 2119184610Salfred 2120184610Salfred if (code & SCAN_PREFIX) { 2121184610Salfred if (code & SCAN_PREFIX_CTL) { 2122184610Salfred /* Ctrl */ 2123184610Salfred sc->sc_buffered_char[0] = (0x1d | (code & SCAN_RELEASE)); 2124184610Salfred sc->sc_buffered_char[1] = (code & ~SCAN_PREFIX); 2125184610Salfred } else if (code & SCAN_PREFIX_SHIFT) { 2126184610Salfred /* Shift */ 2127184610Salfred sc->sc_buffered_char[0] = (0x2a | (code & SCAN_RELEASE)); 2128184610Salfred sc->sc_buffered_char[1] = (code & ~SCAN_PREFIX_SHIFT); 2129184610Salfred } else { 2130184610Salfred sc->sc_buffered_char[0] = (code & ~SCAN_PREFIX); 2131184610Salfred sc->sc_buffered_char[1] = 0; 2132184610Salfred } 2133184610Salfred return ((code & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); 2134184610Salfred } 2135184610Salfred return (code); 2136184610Salfred 2137184610Salfred} 2138184610Salfred 2139184610Salfred#endif /* UKBD_EMULATE_ATSCANCODE */ 2140184610Salfred 2141194099Sthompsastatic keyboard_switch_t ukbdsw = { 2142184610Salfred .probe = &ukbd__probe, 2143184610Salfred .init = &ukbd_init, 2144184610Salfred .term = &ukbd_term, 2145184610Salfred .intr = &ukbd_intr, 2146184610Salfred .test_if = &ukbd_test_if, 2147184610Salfred .enable = &ukbd_enable, 2148184610Salfred .disable = &ukbd_disable, 2149184610Salfred .read = &ukbd_read, 2150184610Salfred .check = &ukbd_check, 2151184610Salfred .read_char = &ukbd_read_char, 2152184610Salfred .check_char = &ukbd_check_char, 2153184610Salfred .ioctl = &ukbd_ioctl, 2154184610Salfred .lock = &ukbd_lock, 2155184610Salfred .clear_state = &ukbd_clear_state, 2156184610Salfred .get_state = &ukbd_get_state, 2157184610Salfred .set_state = &ukbd_set_state, 2158184610Salfred .poll = &ukbd_poll, 2159184610Salfred}; 2160184610Salfred 2161184610SalfredKEYBOARD_DRIVER(ukbd, ukbdsw, ukbd_configure); 2162184610Salfred 2163184610Salfredstatic int 2164184610Salfredukbd_driver_load(module_t mod, int what, void *arg) 2165184610Salfred{ 2166184610Salfred switch (what) { 2167193315Sthompsa case MOD_LOAD: 2168184610Salfred kbd_add_driver(&ukbd_kbd_driver); 2169184610Salfred break; 2170184610Salfred case MOD_UNLOAD: 2171184610Salfred kbd_delete_driver(&ukbd_kbd_driver); 2172184610Salfred break; 2173184610Salfred } 2174184610Salfred return (0); 2175184610Salfred} 2176184610Salfred 2177184610Salfredstatic devclass_t ukbd_devclass; 2178184610Salfred 2179184610Salfredstatic device_method_t ukbd_methods[] = { 2180184610Salfred DEVMETHOD(device_probe, ukbd_probe), 2181184610Salfred DEVMETHOD(device_attach, ukbd_attach), 2182184610Salfred DEVMETHOD(device_detach, ukbd_detach), 2183184610Salfred DEVMETHOD(device_resume, ukbd_resume), 2184246128Ssbz 2185246128Ssbz DEVMETHOD_END 2186184610Salfred}; 2187184610Salfred 2188184610Salfredstatic driver_t ukbd_driver = { 2189184610Salfred .name = "ukbd", 2190184610Salfred .methods = ukbd_methods, 2191184610Salfred .size = sizeof(struct ukbd_softc), 2192184610Salfred}; 2193184610Salfred 2194189275SthompsaDRIVER_MODULE(ukbd, uhub, ukbd_driver, ukbd_devclass, ukbd_driver_load, 0); 2195188942SthompsaMODULE_DEPEND(ukbd, usb, 1, 1, 1); 2196307775Sgonzo#ifdef EVDEV_SUPPORT 2197307775SgonzoMODULE_DEPEND(ukbd, evdev, 1, 1, 1); 2198307775Sgonzo#endif 2199212122SthompsaMODULE_VERSION(ukbd, 1); 2200292080SimpUSB_PNP_HOST_INFO(ukbd_devs); 2201