summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/ukbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/ukbd.c')
-rw-r--r--sys/dev/usb/ukbd.c1538
1 files changed, 0 insertions, 1538 deletions
diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c
deleted file mode 100644
index 5a7c9fc..0000000
--- a/sys/dev/usb/ukbd.c
+++ /dev/null
@@ -1,1538 +0,0 @@
-/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (lennart@augustsson.net) at
- * Carlstedt Research & Technology.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
- */
-
-#include "opt_compat.h"
-#include "opt_kbd.h"
-#include "opt_ukbd.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/ioccom.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/file.h>
-#include <sys/limits.h>
-#include <sys/selinfo.h>
-#include <sys/sysctl.h>
-#include <sys/uio.h>
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbhid.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include "usbdevs.h"
-#include <dev/usb/usb_quirks.h>
-#include <dev/usb/hid.h>
-
-#include <sys/kbio.h>
-#include <dev/kbd/kbdreg.h>
-
-#define UKBD_EMULATE_ATSCANCODE 1
-
-#define DRIVER_NAME "ukbd"
-
-#define delay(d) DELAY(d)
-
-#ifdef USB_DEBUG
-#define DPRINTF(x) if (ukbddebug) printf x
-#define DPRINTFN(n,x) if (ukbddebug>(n)) printf x
-int ukbddebug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW, 0, "USB ukbd");
-SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, debug, CTLFLAG_RW,
- &ukbddebug, 0, "ukbd debug level");
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n,x)
-#endif
-
-#define UPROTO_BOOT_KEYBOARD 1
-
-#define NKEYCODE 6
-
-struct ukbd_data {
- u_int8_t modifiers;
-#define MOD_CONTROL_L 0x01
-#define MOD_CONTROL_R 0x10
-#define MOD_SHIFT_L 0x02
-#define MOD_SHIFT_R 0x20
-#define MOD_ALT_L 0x04
-#define MOD_ALT_R 0x40
-#define MOD_WIN_L 0x08
-#define MOD_WIN_R 0x80
- u_int8_t reserved;
- u_int8_t keycode[NKEYCODE];
-};
-
-#define MAXKEYS (NMOD+2*NKEYCODE)
-
-typedef struct ukbd_softc {
- device_t sc_dev; /* base device */
-} ukbd_softc_t;
-
-#define UKBD_CHUNK 128 /* chunk size for read */
-#define UKBD_BSIZE 1020 /* buffer size */
-
-typedef void usbd_intr_t(usbd_xfer_handle, usbd_private_handle, usbd_status);
-typedef void usbd_disco_t(void *);
-
-static usbd_intr_t ukbd_intr;
-static int ukbd_driver_load(module_t mod, int what, void *arg);
-
-static device_probe_t ukbd_match;
-static device_attach_t ukbd_attach;
-static device_detach_t ukbd_detach;
-static device_resume_t ukbd_resume;
-
-static device_method_t ukbd_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ukbd_match),
- DEVMETHOD(device_attach, ukbd_attach),
- DEVMETHOD(device_detach, ukbd_detach),
- DEVMETHOD(device_resume, ukbd_resume),
-
- { 0, 0 }
-};
-
-static driver_t ukbd_driver = {
- "ukbd",
- ukbd_methods,
- sizeof(struct ukbd_softc)
-};
-
-static devclass_t ukbd_devclass;
-
-MODULE_DEPEND(ukbd, usb, 1, 1, 1);
-DRIVER_MODULE(ukbd, uhub, ukbd_driver, ukbd_devclass, ukbd_driver_load, 0);
-
-static int
-ukbd_match(device_t self)
-{
- struct usb_attach_arg *uaa = device_get_ivars(self);
-
- keyboard_switch_t *sw;
- void *arg[2];
- int unit = device_get_unit(self);
-
- sw = kbd_get_switch(DRIVER_NAME);
- if (sw == NULL)
- return (UMATCH_NONE);
-
- arg[0] = (void *)uaa;
- arg[1] = (void *)ukbd_intr;
- if ((*sw->probe)(unit, (void *)arg, 0))
- return (UMATCH_NONE);
-
- if (usbd_get_quirks(uaa->device)->uq_flags & UQ_KBD_IGNORE)
- return (UMATCH_NONE);
-
- return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
-}
-
-static int
-ukbd_attach(device_t self)
-{
- struct ukbd_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
- usbd_interface_handle iface = uaa->iface;
- usb_interface_descriptor_t *id;
-
- keyboard_switch_t *sw;
- keyboard_t *kbd;
- void *arg[2];
- int unit = device_get_unit(self);
-
- sc->sc_dev = self;
- sw = kbd_get_switch(DRIVER_NAME);
- if (sw == NULL)
- return ENXIO;
-
- id = usbd_get_interface_descriptor(iface);
-
- arg[0] = (void *)uaa;
- arg[1] = (void *)ukbd_intr;
- kbd = NULL;
- if ((*sw->probe)(unit, (void *)arg, 0))
- return ENXIO;
- if ((*sw->init)(unit, &kbd, (void *)arg, 0))
- return ENXIO;
- (*sw->enable)(kbd);
-
-#ifdef KBD_INSTALL_CDEV
- if (kbd_attach(kbd))
- return ENXIO;
-#endif
- if (bootverbose)
- (*sw->diag)(kbd, bootverbose);
-
- return 0;
-}
-
-int
-ukbd_detach(device_t self)
-{
- keyboard_t *kbd;
- int error;
-
- kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME,
- device_get_unit(self)));
- if (kbd == NULL) {
- DPRINTF(("%s: keyboard not attached!?\n", device_get_nameunit(self)));
- return ENXIO;
- }
- kbdd_disable(kbd);
-
-#ifdef KBD_INSTALL_CDEV
- error = kbd_detach(kbd);
- if (error)
- return error;
-#endif
- error = kbdd_term(kbd);
- if (error)
- return error;
-
- DPRINTF(("%s: disconnected\n", device_get_nameunit(self)));
-
- return (0);
-}
-
-static int
-ukbd_resume(device_t self)
-{
- keyboard_t *kbd;
-
- kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME,
- device_get_unit(self)));
- if (kbd)
- kbdd_clear_state(kbd);
- return (0);
-}
-
-void
-ukbd_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
-{
- keyboard_t *kbd = (keyboard_t *)addr;
-
- kbdd_intr(kbd, (void *)status);
-}
-
-#define UKBD_DEFAULT 0
-
-#define KEY_ERROR 0x01
-
-#define KEY_PRESS 0
-#define KEY_RELEASE 0x400
-#define KEY_INDEX(c) ((c) & ~KEY_RELEASE)
-
-#define SCAN_PRESS 0
-#define SCAN_RELEASE 0x80
-#define SCAN_PREFIX_E0 0x100
-#define SCAN_PREFIX_E1 0x200
-#define SCAN_PREFIX_CTL 0x400
-#define SCAN_PREFIX_SHIFT 0x800
-#define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL \
- | SCAN_PREFIX_SHIFT)
-#define SCAN_CHAR(c) ((c) & 0x7f)
-
-#define NMOD 8
-static struct {
- int mask, key;
-} ukbd_mods[NMOD] = {
- { MOD_CONTROL_L, 0xe0 },
- { MOD_CONTROL_R, 0xe4 },
- { MOD_SHIFT_L, 0xe1 },
- { MOD_SHIFT_R, 0xe5 },
- { MOD_ALT_L, 0xe2 },
- { MOD_ALT_R, 0xe6 },
- { MOD_WIN_L, 0xe3 },
- { MOD_WIN_R, 0xe7 },
-};
-
-#define NN 0 /* no translation */
-/*
- * Translate USB keycodes to AT keyboard scancodes.
- */
-/*
- * FIXME: Mac USB keyboard generates:
- * 0x53: keypad NumLock/Clear
- * 0x66: Power
- * 0x67: keypad =
- * 0x68: F13
- * 0x69: F14
- * 0x6a: F15
- */
-static u_int8_t ukbd_trtab[256] = {
- 0, 0, 0, 0, 30, 48, 46, 32, /* 00 - 07 */
- 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */
- 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */
- 22, 47, 17, 45, 21, 44, 2, 3, /* 18 - 1F */
- 4, 5, 6, 7, 8, 9, 10, 11, /* 20 - 27 */
- 28, 1, 14, 15, 57, 12, 13, 26, /* 28 - 2F */
- 27, 43, 43, 39, 40, 41, 51, 52, /* 30 - 37 */
- 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */
- 65, 66, 67, 68, 87, 88, 92, 70, /* 40 - 47 */
- 104, 102, 94, 96, 103, 99, 101, 98, /* 48 - 4F */
- 97, 100, 95, 69, 91, 55, 74, 78, /* 50 - 57 */
- 89, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */
- 72, 73, 82, 83, 86, 107, 122, NN, /* 60 - 67 */
- NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */
- NN, NN, NN, NN, 115, 108, 111, 113, /* 70 - 77 */
- 109, 110, 112, 118, 114, 116, 117, 119, /* 78 - 7F */
- 121, 120, NN, NN, NN, NN, NN, 115, /* 80 - 87 */
- 112, 125, 121, 123, NN, NN, NN, NN, /* 88 - 8F */
- NN, NN, NN, NN, NN, NN, NN, NN, /* 90 - 97 */
- NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9F */
- NN, NN, NN, NN, NN, NN, NN, NN, /* A0 - A7 */
- NN, NN, NN, NN, NN, NN, NN, NN, /* A8 - AF */
- NN, NN, NN, NN, NN, NN, NN, NN, /* B0 - B7 */
- NN, NN, NN, NN, NN, NN, NN, NN, /* B8 - BF */
- NN, NN, NN, NN, NN, NN, NN, NN, /* C0 - C7 */
- NN, NN, NN, NN, NN, NN, NN, NN, /* C8 - CF */
- NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */
- NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */
- 29, 42, 56, 105, 90, 54, 93, 106, /* E0 - E7 */
- NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */
- NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */
- NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */
-};
-
-typedef struct ukbd_state {
- usbd_interface_handle ks_iface; /* interface */
- usbd_pipe_handle ks_intrpipe; /* interrupt pipe */
- struct usb_attach_arg *ks_uaa;
- int ks_ep_addr;
-
- struct ukbd_data ks_ndata;
- struct ukbd_data ks_odata;
- u_long ks_ntime[NKEYCODE];
- u_long ks_otime[NKEYCODE];
-
-#define INPUTBUFSIZE (NMOD + 2*NKEYCODE)
- u_int ks_input[INPUTBUFSIZE]; /* input buffer */
- int ks_inputs;
- int ks_inputhead;
- int ks_inputtail;
-
- int ks_ifstate;
-#define INTRENABLED (1 << 0)
-#define DISCONNECTED (1 << 1)
-
- struct callout ks_timeout_handle;
-
- int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
- int ks_flags; /* flags */
-#define COMPOSE (1 << 0)
- int ks_polling;
- int ks_state; /* shift/lock key state */
- int ks_accents; /* accent key index (> 0) */
- u_int ks_composed_char; /* composed char code (> 0) */
-#ifdef UKBD_EMULATE_ATSCANCODE
- u_int ks_buffered_char[2];
- u_int8_t ks_leds; /* store for async led requests */
-#endif
-} ukbd_state_t;
-
-/* keyboard driver declaration */
-static int ukbd_configure(int flags);
-static kbd_probe_t ukbd_probe;
-static kbd_init_t ukbd_init;
-static kbd_term_t ukbd_term;
-static kbd_intr_t ukbd_interrupt;
-static kbd_test_if_t ukbd_test_if;
-static kbd_enable_t ukbd_enable;
-static kbd_disable_t ukbd_disable;
-static kbd_read_t ukbd_read;
-static kbd_check_t ukbd_check;
-static kbd_read_char_t ukbd_read_char;
-static kbd_check_char_t ukbd_check_char;
-static kbd_ioctl_t ukbd_ioctl;
-static kbd_lock_t ukbd_lock;
-static kbd_clear_state_t ukbd_clear_state;
-static kbd_get_state_t ukbd_get_state;
-static kbd_set_state_t ukbd_set_state;
-static kbd_poll_mode_t ukbd_poll;
-
-keyboard_switch_t ukbdsw = {
- ukbd_probe,
- ukbd_init,
- ukbd_term,
- ukbd_interrupt,
- ukbd_test_if,
- ukbd_enable,
- ukbd_disable,
- ukbd_read,
- ukbd_check,
- ukbd_read_char,
- ukbd_check_char,
- ukbd_ioctl,
- ukbd_lock,
- ukbd_clear_state,
- ukbd_get_state,
- ukbd_set_state,
- genkbd_get_fkeystr,
- ukbd_poll,
- genkbd_diag,
-};
-
-KEYBOARD_DRIVER(ukbd, ukbdsw, ukbd_configure);
-
-/* local functions */
-static int ukbd_enable_intr(keyboard_t *kbd, int on,
- usbd_intr_t *func);
-static void ukbd_timeout(void *arg);
-
-static int ukbd_getc(ukbd_state_t *state, int wait);
-static int probe_keyboard(struct usb_attach_arg *uaa, int flags);
-static int init_keyboard(ukbd_state_t *state, int *type,
- int flags);
-static void set_leds(ukbd_state_t *state, int leds);
-static int set_typematic(keyboard_t *kbd, int code);
-#ifdef UKBD_EMULATE_ATSCANCODE
-static int keycode2scancode(int keycode, int shift, int up);
-#endif
-
-/* local variables */
-
-/* the initial key map, accent map and fkey strings */
-#if defined(UKBD_DFLT_KEYMAP) && !defined(KLD_MODULE)
-#define KBD_DFLT_KEYMAP
-#include "ukbdmap.h"
-#endif
-#include <dev/kbd/kbdtables.h>
-
-/* structures for the default keyboard */
-static keyboard_t default_kbd;
-static ukbd_state_t default_kbd_state;
-static keymap_t default_keymap;
-static accentmap_t default_accentmap;
-static fkeytab_t default_fkeytab[NUM_FKEYS];
-
-/*
- * The back door to the keyboard driver!
- * This function is called by the console driver, via the kbdio module,
- * to tickle keyboard drivers when the low-level console is being initialized.
- * Almost nothing in the kernel has been initialied yet. Try to probe
- * keyboards if possible.
- * NOTE: because of the way the low-level conole is initialized, this routine
- * may be called more than once!!
- */
-static int
-ukbd_configure(int flags)
-{
- return 0;
-
-#if 0 /* not yet */
- keyboard_t *kbd;
- device_t device;
- struct usb_attach_arg *uaa;
- void *arg[2];
-
- device = devclass_get_device(ukbd_devclass, UKBD_DEFAULT);
- if (device == NULL)
- return 0;
- uaa = (struct usb_attach_arg *)device_get_ivars(device);
- if (uaa == NULL)
- return 0;
-
- /* probe the default keyboard */
- arg[0] = (void *)uaa;
- arg[1] = (void *)ukbd_intr;
- kbd = NULL;
- if (ukbd_probe(UKBD_DEFAULT, arg, flags))
- return 0;
- if (ukbd_init(UKBD_DEFAULT, &kbd, arg, flags))
- return 0;
-
- /* return the number of found keyboards */
- return 1;
-#endif
-}
-
-/* low-level functions */
-
-/* detect a keyboard */
-static int
-ukbd_probe(int unit, void *arg, int flags)
-{
- void **data;
- struct usb_attach_arg *uaa;
-
- data = (void **)arg;
- uaa = (struct usb_attach_arg *)data[0];
-
- /* XXX */
- if (unit == UKBD_DEFAULT) {
- if (KBD_IS_PROBED(&default_kbd))
- return 0;
- }
- if (probe_keyboard(uaa, flags))
- return ENXIO;
- return 0;
-}
-
-/* reset and initialize the device */
-static int
-ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
-{
- keyboard_t *kbd;
- ukbd_state_t *state;
- keymap_t *keymap;
- accentmap_t *accmap;
- fkeytab_t *fkeymap;
- int fkeymap_size;
- void **data = (void **)arg;
- struct usb_attach_arg *uaa = (struct usb_attach_arg *)data[0];
-
- /* XXX */
- if (unit == UKBD_DEFAULT) {
- *kbdp = kbd = &default_kbd;
- if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd))
- return 0;
- state = &default_kbd_state;
- keymap = &default_keymap;
- accmap = &default_accentmap;
- fkeymap = default_fkeytab;
- fkeymap_size =
- sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);
- } else if (*kbdp == NULL) {
- *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT);
- if (kbd == NULL)
- return ENOMEM;
- bzero(kbd, sizeof(*kbd));
- state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT);
- keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT);
- accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT);
- fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT);
- fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
- if ((state == NULL) || (keymap == NULL) || (accmap == NULL)
- || (fkeymap == NULL)) {
- if (state != NULL)
- free(state, M_DEVBUF);
- if (keymap != NULL)
- free(keymap, M_DEVBUF);
- if (accmap != NULL)
- free(accmap, M_DEVBUF);
- if (fkeymap != NULL)
- free(fkeymap, M_DEVBUF);
- free(kbd, M_DEVBUF);
- return ENOMEM;
- }
- } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
- return 0;
- } else {
- kbd = *kbdp;
- state = (ukbd_state_t *)kbd->kb_data;
- keymap = kbd->kb_keymap;
- accmap = kbd->kb_accentmap;
- fkeymap = kbd->kb_fkeytab;
- fkeymap_size = kbd->kb_fkeytab_size;
- }
-
- if (!KBD_IS_PROBED(kbd)) {
- kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, 0, 0);
- bzero(state, sizeof(*state));
- bcopy(&key_map, keymap, sizeof(key_map));
- bcopy(&accent_map, accmap, sizeof(accent_map));
- bcopy(fkey_tab, fkeymap,
- imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
- kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
- kbd->kb_data = (void *)state;
-
- if (probe_keyboard(uaa, flags))
- return ENXIO;
- else
- KBD_FOUND_DEVICE(kbd);
- ukbd_clear_state(kbd);
- state->ks_mode = K_XLATE;
- state->ks_iface = uaa->iface;
- state->ks_uaa = uaa;
- state->ks_ifstate = 0;
- callout_init(&state->ks_timeout_handle, 0);
- /*
- * FIXME: set the initial value for lock keys in ks_state
- * according to the BIOS data?
- */
- KBD_PROBE_DONE(kbd);
- }
- if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
- if (KBD_HAS_DEVICE(kbd)
- && init_keyboard((ukbd_state_t *)kbd->kb_data,
- &kbd->kb_type, kbd->kb_flags)) {
- kbd->kb_flags = 0;
- /* XXX: Missing free()'s */
- return ENXIO;
- }
- ukbd_ioctl(kbd, KDSETLED, (caddr_t)&(state->ks_state));
- KBD_INIT_DONE(kbd);
- }
- if (!KBD_IS_CONFIGURED(kbd)) {
- if (kbd_register(kbd) < 0) {
- kbd->kb_flags = 0;
- /* XXX: Missing free()'s */
- return ENXIO;
- }
- if (ukbd_enable_intr(kbd, TRUE, (usbd_intr_t *)data[1]) == 0)
- ukbd_timeout((void *)kbd);
- KBD_CONFIG_DONE(kbd);
- }
-
- return 0;
-}
-
-static int
-ukbd_enable_intr(keyboard_t *kbd, int on, usbd_intr_t *func)
-{
- ukbd_state_t *state = (ukbd_state_t *)kbd->kb_data;
- usbd_status err;
-
- if (on) {
- /* Set up interrupt pipe. */
- if (state->ks_ifstate & INTRENABLED)
- return EBUSY;
-
- state->ks_ifstate |= INTRENABLED;
- err = usbd_open_pipe_intr(state->ks_iface, state->ks_ep_addr,
- USBD_SHORT_XFER_OK,
- &state->ks_intrpipe, kbd,
- &state->ks_ndata,
- sizeof(state->ks_ndata), func,
- USBD_DEFAULT_INTERVAL);
- if (err)
- return (EIO);
- } else {
- /* Disable interrupts. */
- usbd_abort_pipe(state->ks_intrpipe);
- usbd_close_pipe(state->ks_intrpipe);
-
- state->ks_ifstate &= ~INTRENABLED;
- }
-
- return (0);
-}
-
-/* finish using this keyboard */
-static int
-ukbd_term(keyboard_t *kbd)
-{
- ukbd_state_t *state;
- int error;
- int s;
-
- s = splusb();
-
- state = (ukbd_state_t *)kbd->kb_data;
- DPRINTF(("ukbd_term: ks_ifstate=0x%x\n", state->ks_ifstate));
-
- callout_stop(&state->ks_timeout_handle);
-
- if (state->ks_ifstate & INTRENABLED)
- ukbd_enable_intr(kbd, FALSE, NULL);
- if (state->ks_ifstate & INTRENABLED) {
- splx(s);
- DPRINTF(("ukbd_term: INTRENABLED!\n"));
- return ENXIO;
- }
-
- error = kbd_unregister(kbd);
- DPRINTF(("ukbd_term: kbd_unregister() %d\n", error));
- if (error == 0) {
- kbd->kb_flags = 0;
- if (kbd != &default_kbd) {
- free(kbd->kb_keymap, M_DEVBUF);
- free(kbd->kb_accentmap, M_DEVBUF);
- free(kbd->kb_fkeytab, M_DEVBUF);
- free(state, M_DEVBUF);
- free(kbd, M_DEVBUF);
- }
- }
-
- splx(s);
- return error;
-}
-
-
-/* keyboard interrupt routine */
-
-static void
-ukbd_timeout(void *arg)
-{
- keyboard_t *kbd;
- ukbd_state_t *state;
- int s;
-
- kbd = (keyboard_t *)arg;
- state = (ukbd_state_t *)kbd->kb_data;
- s = splusb();
- kbdd_intr(kbd, (void *)USBD_NORMAL_COMPLETION);
- callout_reset(&state->ks_timeout_handle, hz / 40, ukbd_timeout, arg);
- splx(s);
-}
-
-static int
-ukbd_interrupt(keyboard_t *kbd, void *arg)
-{
- usbd_status status = (usbd_status)arg;
- ukbd_state_t *state;
- struct ukbd_data *ud;
- struct timeval tv;
- u_long now;
- int mod, omod;
- int key, c;
- int i, j;
-
- DPRINTFN(5, ("ukbd_intr: status=%d\n", status));
- if (status == USBD_CANCELLED)
- return 0;
-
- state = (ukbd_state_t *)kbd->kb_data;
- ud = &state->ks_ndata;
-
- if (status != USBD_NORMAL_COMPLETION) {
- DPRINTF(("ukbd_intr: status=%d\n", status));
- if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(state->ks_intrpipe);
- return 0;
- }
-
- if (ud->keycode[0] == KEY_ERROR)
- return 0; /* ignore */
-
- getmicrouptime(&tv);
- now = (u_long)tv.tv_sec*1000 + (u_long)tv.tv_usec/1000;
-
-#define ADDKEY1(c) \
- if (state->ks_inputs < INPUTBUFSIZE) { \
- state->ks_input[state->ks_inputtail] = (c); \
- ++state->ks_inputs; \
- state->ks_inputtail = (state->ks_inputtail + 1)%INPUTBUFSIZE; \
- }
-
- mod = ud->modifiers;
- omod = state->ks_odata.modifiers;
- if (mod != omod) {
- for (i = 0; i < NMOD; i++)
- if (( mod & ukbd_mods[i].mask) !=
- (omod & ukbd_mods[i].mask))
- ADDKEY1(ukbd_mods[i].key |
- (mod & ukbd_mods[i].mask
- ? KEY_PRESS : KEY_RELEASE));
- }
-
- /* Check for released keys. */
- for (i = 0; i < NKEYCODE; i++) {
- key = state->ks_odata.keycode[i];
- if (key == 0)
- continue;
- for (j = 0; j < NKEYCODE; j++) {
- if (ud->keycode[j] == 0)
- continue;
- if (key == ud->keycode[j])
- goto rfound;
- }
- ADDKEY1(key | KEY_RELEASE);
- rfound:
- ;
- }
-
- /* Check for pressed keys. */
- for (i = 0; i < NKEYCODE; i++) {
- key = ud->keycode[i];
- if (key == 0)
- continue;
- state->ks_ntime[i] = now + kbd->kb_delay1;
- for (j = 0; j < NKEYCODE; j++) {
- if (state->ks_odata.keycode[j] == 0)
- continue;
- if (key == state->ks_odata.keycode[j]) {
- state->ks_ntime[i] = state->ks_otime[j];
- if (state->ks_otime[j] > now)
- goto pfound;
- state->ks_ntime[i] = now + kbd->kb_delay2;
- break;
- }
- }
- ADDKEY1(key | KEY_PRESS);
- /*
- * If any other key is presently down, force its repeat to be
- * well in the future (100s). This makes the last key to be
- * pressed do the autorepeat.
- */
- for (j = 0; j < NKEYCODE; j++) {
- if (j != i)
- state->ks_ntime[j] = now + 100 * 1000;
- }
- pfound:
- ;
- }
-
- state->ks_odata = *ud;
- bcopy(state->ks_ntime, state->ks_otime, sizeof(state->ks_ntime));
- if (state->ks_inputs <= 0)
- return 0;
-
-#ifdef USB_DEBUG
- for (i = state->ks_inputhead, j = 0; j < state->ks_inputs; ++j,
- i = (i + 1)%INPUTBUFSIZE) {
- c = state->ks_input[i];
- DPRINTF(("0x%x (%d) %s\n", c, c,
- (c & KEY_RELEASE) ? "released":"pressed"));
- }
- if (ud->modifiers)
- DPRINTF(("mod:0x%04x ", ud->modifiers));
- for (i = 0; i < NKEYCODE; i++) {
- if (ud->keycode[i])
- DPRINTF(("%d ", ud->keycode[i]));
- }
- DPRINTF(("\n"));
-#endif /* USB_DEBUG */
-
- if (state->ks_polling)
- return 0;
-
- if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
- /* let the callback function to process the input */
- (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
- kbd->kb_callback.kc_arg);
- } else {
- /* read and discard the input; no one is waiting for it */
- do {
- c = ukbd_read_char(kbd, FALSE);
- } while (c != NOKEY);
- }
-
- return 0;
-}
-
-static int
-ukbd_getc(ukbd_state_t *state, int wait)
-{
- int c;
- int s;
-
- if (state->ks_polling) {
- DPRINTFN(1,("ukbd_getc: polling\n"));
- s = splusb();
- while (state->ks_inputs <= 0) {
- usbd_dopoll(state->ks_iface);
- if (wait == FALSE)
- break;
- }
- splx(s);
- }
- s = splusb();
- if (state->ks_inputs <= 0) {
- c = -1;
- } else {
- c = state->ks_input[state->ks_inputhead];
- --state->ks_inputs;
- state->ks_inputhead = (state->ks_inputhead + 1)%INPUTBUFSIZE;
- }
- splx(s);
- return c;
-}
-
-/* test the interface to the device */
-static int
-ukbd_test_if(keyboard_t *kbd)
-{
- return 0;
-}
-
-/*
- * Enable the access to the device; until this function is called,
- * the client cannot read from the keyboard.
- */
-static int
-ukbd_enable(keyboard_t *kbd)
-{
- int s;
-
- s = splusb();
- KBD_ACTIVATE(kbd);
- splx(s);
- return 0;
-}
-
-/* disallow the access to the device */
-static int
-ukbd_disable(keyboard_t *kbd)
-{
- int s;
-
- s = splusb();
- KBD_DEACTIVATE(kbd);
- splx(s);
- return 0;
-}
-
-/* read one byte from the keyboard if it's allowed */
-static int
-ukbd_read(keyboard_t *kbd, int wait)
-{
- ukbd_state_t *state;
- int usbcode;
-#ifdef UKBD_EMULATE_ATSCANCODE
- int keycode;
- int scancode;
-#endif
-
- state = (ukbd_state_t *)kbd->kb_data;
-#ifdef UKBD_EMULATE_ATSCANCODE
- if (state->ks_buffered_char[0]) {
- scancode = state->ks_buffered_char[0];
- if (scancode & SCAN_PREFIX) {
- state->ks_buffered_char[0] = scancode & ~SCAN_PREFIX;
- return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
- } else {
- state->ks_buffered_char[0] = state->ks_buffered_char[1];
- state->ks_buffered_char[1] = 0;
- return scancode;
- }
- }
-#endif /* UKBD_EMULATE_ATSCANCODE */
-
- /* XXX */
- usbcode = ukbd_getc(state, wait);
- if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1))
- return -1;
- ++kbd->kb_count;
-#ifdef UKBD_EMULATE_ATSCANCODE
- keycode = ukbd_trtab[KEY_INDEX(usbcode)];
- if (keycode == NN)
- return -1;
-
- scancode = keycode2scancode(keycode, state->ks_ndata.modifiers,
- usbcode & KEY_RELEASE);
- if (scancode & SCAN_PREFIX) {
- if (scancode & SCAN_PREFIX_CTL) {
- state->ks_buffered_char[0] =
- 0x1d | (scancode & SCAN_RELEASE); /* Ctrl */
- state->ks_buffered_char[1] = scancode & ~SCAN_PREFIX;
- } else if (scancode & SCAN_PREFIX_SHIFT) {
- state->ks_buffered_char[0] =
- 0x2a | (scancode & SCAN_RELEASE); /* Shift */
- state->ks_buffered_char[1] =
- scancode & ~SCAN_PREFIX_SHIFT;
- } else {
- state->ks_buffered_char[0] = scancode & ~SCAN_PREFIX;
- state->ks_buffered_char[1] = 0;
- }
- return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
- }
- return scancode;
-#else /* !UKBD_EMULATE_ATSCANCODE */
- return usbcode;
-#endif /* UKBD_EMULATE_ATSCANCODE */
-}
-
-/* check if data is waiting */
-static int
-ukbd_check(keyboard_t *kbd)
-{
- if (!KBD_IS_ACTIVE(kbd))
- return FALSE;
-#ifdef UKBD_EMULATE_ATSCANCODE
- if (((ukbd_state_t *)kbd->kb_data)->ks_buffered_char[0])
- return TRUE;
-#endif
- if (((ukbd_state_t *)kbd->kb_data)->ks_inputs > 0)
- return TRUE;
- return FALSE;
-}
-
-/* read char from the keyboard */
-static u_int
-ukbd_read_char(keyboard_t *kbd, int wait)
-{
- ukbd_state_t *state;
- u_int action;
- int usbcode;
- int keycode;
-#ifdef UKBD_EMULATE_ATSCANCODE
- int scancode;
-#endif
-
- state = (ukbd_state_t *)kbd->kb_data;
-next_code:
- /* do we have a composed char to return? */
- if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
- action = state->ks_composed_char;
- state->ks_composed_char = 0;
- if (action > UCHAR_MAX)
- return ERRKEY;
- return action;
- }
-
-#ifdef UKBD_EMULATE_ATSCANCODE
- /* do we have a pending raw scan code? */
- if (state->ks_mode == K_RAW) {
- if (state->ks_buffered_char[0]) {
- scancode = state->ks_buffered_char[0];
- if (scancode & SCAN_PREFIX) {
- state->ks_buffered_char[0] =
- scancode & ~SCAN_PREFIX;
- return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
- } else {
- state->ks_buffered_char[0] =
- state->ks_buffered_char[1];
- state->ks_buffered_char[1] = 0;
- return scancode;
- }
- }
- }
-#endif /* UKBD_EMULATE_ATSCANCODE */
-
- /* see if there is something in the keyboard port */
- /* XXX */
- usbcode = ukbd_getc(state, wait);
- if (usbcode == -1)
- return NOKEY;
- ++kbd->kb_count;
-
-#ifdef UKBD_EMULATE_ATSCANCODE
- /* USB key index -> key code -> AT scan code */
- keycode = ukbd_trtab[KEY_INDEX(usbcode)];
- if (keycode == NN)
- return NOKEY;
-
- /* return an AT scan code for the K_RAW mode */
- if (state->ks_mode == K_RAW) {
- scancode = keycode2scancode(keycode, state->ks_ndata.modifiers,
- usbcode & KEY_RELEASE);
- if (scancode & SCAN_PREFIX) {
- if (scancode & SCAN_PREFIX_CTL) {
- state->ks_buffered_char[0] =
- 0x1d | (scancode & SCAN_RELEASE);
- state->ks_buffered_char[1] =
- scancode & ~SCAN_PREFIX;
- } else if (scancode & SCAN_PREFIX_SHIFT) {
- state->ks_buffered_char[0] =
- 0x2a | (scancode & SCAN_RELEASE);
- state->ks_buffered_char[1] =
- scancode & ~SCAN_PREFIX_SHIFT;
- } else {
- state->ks_buffered_char[0] =
- scancode & ~SCAN_PREFIX;
- state->ks_buffered_char[1] = 0;
- }
- return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
- }
- return scancode;
- }
-#else /* !UKBD_EMULATE_ATSCANCODE */
- /* return the byte as is for the K_RAW mode */
- if (state->ks_mode == K_RAW)
- return usbcode;
-
- /* USB key index -> key code */
- keycode = ukbd_trtab[KEY_INDEX(usbcode)];
- if (keycode == NN)
- return NOKEY;
-#endif /* UKBD_EMULATE_ATSCANCODE */
-
- switch (keycode) {
- case 0x38: /* left alt (compose key) */
- if (usbcode & KEY_RELEASE) {
- if (state->ks_flags & COMPOSE) {
- state->ks_flags &= ~COMPOSE;
- if (state->ks_composed_char > UCHAR_MAX)
- state->ks_composed_char = 0;
- }
- } else {
- if (!(state->ks_flags & COMPOSE)) {
- state->ks_flags |= COMPOSE;
- state->ks_composed_char = 0;
- }
- }
- break;
- /* XXX: I don't like these... */
- case 0x5c: /* print screen */
- if (state->ks_flags & ALTS)
- keycode = 0x54; /* sysrq */
- break;
- case 0x68: /* pause/break */
- if (state->ks_flags & CTLS)
- keycode = 0x6c; /* break */
- break;
- }
-
- /* return the key code in the K_CODE mode */
- if (usbcode & KEY_RELEASE)
- keycode |= SCAN_RELEASE;
- if (state->ks_mode == K_CODE)
- return keycode;
-
- /* compose a character code */
- if (state->ks_flags & COMPOSE) {
- switch (keycode) {
- /* key pressed, process it */
- case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */
- state->ks_composed_char *= 10;
- state->ks_composed_char += keycode - 0x40;
- if (state->ks_composed_char > UCHAR_MAX)
- return ERRKEY;
- goto next_code;
- case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */
- state->ks_composed_char *= 10;
- state->ks_composed_char += keycode - 0x47;
- if (state->ks_composed_char > UCHAR_MAX)
- return ERRKEY;
- goto next_code;
- case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */
- state->ks_composed_char *= 10;
- state->ks_composed_char += keycode - 0x4E;
- if (state->ks_composed_char > UCHAR_MAX)
- return ERRKEY;
- goto next_code;
- case 0x52: /* keypad 0 */
- state->ks_composed_char *= 10;
- if (state->ks_composed_char > UCHAR_MAX)
- return ERRKEY;
- goto next_code;
-
- /* key released, no interest here */
- case SCAN_RELEASE | 0x47:
- case SCAN_RELEASE | 0x48:
- case SCAN_RELEASE | 0x49: /* keypad 7,8,9 */
- case SCAN_RELEASE | 0x4B:
- case SCAN_RELEASE | 0x4C:
- case SCAN_RELEASE | 0x4D: /* keypad 4,5,6 */
- case SCAN_RELEASE | 0x4F:
- case SCAN_RELEASE | 0x50:
- case SCAN_RELEASE | 0x51: /* keypad 1,2,3 */
- case SCAN_RELEASE | 0x52: /* keypad 0 */
- goto next_code;
-
- case 0x38: /* left alt key */
- break;
-
- default:
- if (state->ks_composed_char > 0) {
- state->ks_flags &= ~COMPOSE;
- state->ks_composed_char = 0;
- return ERRKEY;
- }
- break;
- }
- }
-
- /* keycode to key action */
- action = genkbd_keyaction(kbd, SCAN_CHAR(keycode),
- keycode & SCAN_RELEASE, &state->ks_state,
- &state->ks_accents);
- if (action == NOKEY)
- goto next_code;
- else
- return action;
-}
-
-/* check if char is waiting */
-static int
-ukbd_check_char(keyboard_t *kbd)
-{
- ukbd_state_t *state;
-
- if (!KBD_IS_ACTIVE(kbd))
- return FALSE;
- state = (ukbd_state_t *)kbd->kb_data;
- if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
- return TRUE;
- return ukbd_check(kbd);
-}
-
-/* some useful control functions */
-static int
-ukbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
-{
- /* trasnlate LED_XXX bits into the device specific bits */
- static u_char ledmap[8] = {
- 0, 2, 1, 3, 4, 6, 5, 7,
- };
- ukbd_state_t *state = kbd->kb_data;
- int s;
- int i;
-#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
- defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
- int ival;
-#endif
-
- s = splusb();
- switch (cmd) {
-
- case KDGKBMODE: /* get keyboard mode */
- *(int *)arg = state->ks_mode;
- break;
-#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
- defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
- case _IO('K', 7):
- ival = IOCPARM_IVAL(arg);
- arg = (caddr_t)&ival;
- /* FALLTHROUGH */
-#endif
- case KDSKBMODE: /* set keyboard mode */
- switch (*(int *)arg) {
- case K_XLATE:
- if (state->ks_mode != K_XLATE) {
- /* make lock key state and LED state match */
- state->ks_state &= ~LOCK_MASK;
- state->ks_state |= KBD_LED_VAL(kbd);
- }
- /* FALLTHROUGH */
- case K_RAW:
- case K_CODE:
- if (state->ks_mode != *(int *)arg) {
- ukbd_clear_state(kbd);
- state->ks_mode = *(int *)arg;
- }
- break;
- default:
- splx(s);
- return EINVAL;
- }
- break;
-
- case KDGETLED: /* get keyboard LED */
- *(int *)arg = KBD_LED_VAL(kbd);
- break;
-#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
- defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
- case _IO('K', 66):
- ival = IOCPARM_IVAL(arg);
- arg = (caddr_t)&ival;
- /* FALLTHROUGH */
-#endif
- case KDSETLED: /* set keyboard LED */
- /* NOTE: lock key state in ks_state won't be changed */
- if (*(int *)arg & ~LOCK_MASK) {
- splx(s);
- return EINVAL;
- }
- i = *(int *)arg;
- /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
- if (state->ks_mode == K_XLATE &&
- kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
- if (i & ALKED)
- i |= CLKED;
- else
- i &= ~CLKED;
- }
- if (KBD_HAS_DEVICE(kbd)) {
- set_leds(state, ledmap[i & LED_MASK]);
- /* XXX: error check? */
- }
- KBD_LED_VAL(kbd) = *(int *)arg;
- break;
-
- case KDGKBSTATE: /* get lock key state */
- *(int *)arg = state->ks_state & LOCK_MASK;
- break;
-#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
- defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
- case _IO('K', 20):
- ival = IOCPARM_IVAL(arg);
- arg = (caddr_t)&ival;
- /* FALLTHROUGH */
-#endif
- case KDSKBSTATE: /* set lock key state */
- if (*(int *)arg & ~LOCK_MASK) {
- splx(s);
- return EINVAL;
- }
- state->ks_state &= ~LOCK_MASK;
- state->ks_state |= *(int *)arg;
- splx(s);
- /* set LEDs and quit */
- return ukbd_ioctl(kbd, KDSETLED, arg);
-
- case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
- splx(s);
- if (!KBD_HAS_DEVICE(kbd))
- return 0;
- if (((int *)arg)[1] < 0)
- return EINVAL;
- if (((int *)arg)[0] < 0)
- return EINVAL;
- else if (((int *)arg)[0] == 0) /* fastest possible value */
- kbd->kb_delay1 = 200;
- else
- kbd->kb_delay1 = ((int *)arg)[0];
- kbd->kb_delay2 = ((int *)arg)[1];
- return 0;
-
-#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
- defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
- case _IO('K', 67):
- ival = IOCPARM_IVAL(arg);
- arg = (caddr_t)&ival;
- /* FALLTHROUGH */
-#endif
- case KDSETRAD: /* set keyboard repeat rate (old interface) */
- splx(s);
- return set_typematic(kbd, *(int *)arg);
-
- case PIO_KEYMAP: /* set keyboard translation table */
- case PIO_KEYMAPENT: /* set keyboard translation table entry */
- case PIO_DEADKEYMAP: /* set accent key translation table */
- state->ks_accents = 0;
- /* FALLTHROUGH */
- default:
- splx(s);
- return genkbd_commonioctl(kbd, cmd, arg);
-
-#ifdef USB_DEBUG
- case USB_SETDEBUG:
- ukbddebug = *(int *)arg;
- break;
-#endif
- }
-
- splx(s);
- return 0;
-}
-
-/* lock the access to the keyboard */
-static int
-ukbd_lock(keyboard_t *kbd, int lock)
-{
- /* XXX ? */
- return TRUE;
-}
-
-/* clear the internal state of the keyboard */
-static void
-ukbd_clear_state(keyboard_t *kbd)
-{
- ukbd_state_t *state;
-
- state = (ukbd_state_t *)kbd->kb_data;
- state->ks_flags = 0;
- state->ks_polling = 0;
- state->ks_state &= LOCK_MASK; /* preserve locking key state */
- state->ks_accents = 0;
- state->ks_composed_char = 0;
-#ifdef UKBD_EMULATE_ATSCANCODE
- state->ks_buffered_char[0] = 0;
- state->ks_buffered_char[1] = 0;
-#endif
- bzero(&state->ks_ndata, sizeof(state->ks_ndata));
- bzero(&state->ks_odata, sizeof(state->ks_odata));
- bzero(&state->ks_ntime, sizeof(state->ks_ntime));
- bzero(&state->ks_otime, sizeof(state->ks_otime));
-}
-
-/* save the internal state */
-static int
-ukbd_get_state(keyboard_t *kbd, void *buf, size_t len)
-{
- if (len == 0)
- return sizeof(ukbd_state_t);
- if (len < sizeof(ukbd_state_t))
- return -1;
- bcopy(kbd->kb_data, buf, sizeof(ukbd_state_t));
- return 0;
-}
-
-/* set the internal state */
-static int
-ukbd_set_state(keyboard_t *kbd, void *buf, size_t len)
-{
- if (len < sizeof(ukbd_state_t))
- return ENOMEM;
- bcopy(buf, kbd->kb_data, sizeof(ukbd_state_t));
- return 0;
-}
-
-static int
-ukbd_poll(keyboard_t *kbd, int on)
-{
- ukbd_state_t *state;
- usbd_device_handle dev;
- int s;
-
- state = (ukbd_state_t *)kbd->kb_data;
- usbd_interface2device_handle(state->ks_iface, &dev);
-
- s = splusb();
- if (on) {
- ++state->ks_polling;
- if (state->ks_polling == 1)
- usbd_set_polling(dev, on);
- } else {
- --state->ks_polling;
- if (state->ks_polling == 0)
- usbd_set_polling(dev, on);
- }
- splx(s);
- return 0;
-}
-
-/* local functions */
-
-static int
-probe_keyboard(struct usb_attach_arg *uaa, int flags)
-{
- usb_interface_descriptor_t *id;
-
- if (!uaa->iface) /* we attach to ifaces only */
- return EINVAL;
-
- /* Check that this is a keyboard that speaks the boot protocol. */
- id = usbd_get_interface_descriptor(uaa->iface);
- if (id
- && id->bInterfaceClass == UICLASS_HID
- && id->bInterfaceSubClass == UISUBCLASS_BOOT
- && id->bInterfaceProtocol == UPROTO_BOOT_KEYBOARD)
- return 0; /* found it */
-
- return EINVAL;
-}
-
-static int
-init_keyboard(ukbd_state_t *state, int *type, int flags)
-{
- usb_endpoint_descriptor_t *ed;
-
- *type = KB_OTHER;
-
- state->ks_ifstate |= DISCONNECTED;
-
- ed = usbd_interface2endpoint_descriptor(state->ks_iface, 0);
- if (!ed) {
- printf("ukbd: could not read endpoint descriptor\n");
- return EIO;
- }
-
- DPRINTFN(10,("ukbd:init_keyboard: \
-bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d bInterval=%d\n",
- ed->bLength, ed->bDescriptorType,
- UE_GET_ADDR(ed->bEndpointAddress),
- UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN ? "in":"out",
- UE_GET_XFERTYPE(ed->bmAttributes),
- UGETW(ed->wMaxPacketSize), ed->bInterval));
-
- if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
- UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) {
- printf("ukbd: unexpected endpoint\n");
- return EINVAL;
- }
-
- /* Ignore if SETIDLE fails since it is not crucial. */
- usbd_set_idle(state->ks_iface, 0, 0);
-
- state->ks_ep_addr = ed->bEndpointAddress;
- state->ks_ifstate &= ~DISCONNECTED;
-
- return 0;
-}
-
-static void
-set_leds(ukbd_state_t *state, int leds)
-{
-
- DPRINTF(("ukbd:set_leds: state=%p leds=%d\n", state, leds));
- state->ks_leds = leds;
- usbd_set_report_async(state->ks_iface, UHID_OUTPUT_REPORT, 0,
- &state->ks_leds, 1);
-}
-
-static int
-set_typematic(keyboard_t *kbd, int code)
-{
- static int delays[] = { 250, 500, 750, 1000 };
- static int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63,
- 68, 76, 84, 92, 100, 110, 118, 126,
- 136, 152, 168, 184, 200, 220, 236, 252,
- 272, 304, 336, 368, 400, 440, 472, 504 };
-
- if (code & ~0x7f)
- return EINVAL;
- kbd->kb_delay1 = delays[(code >> 5) & 3];
- kbd->kb_delay2 = rates[code & 0x1f];
- return 0;
-}
-
-#ifdef UKBD_EMULATE_ATSCANCODE
-static int
-keycode2scancode(int keycode, int shift, int up)
-{
- static int scan[] = {
- 0x1c, 0x1d, 0x35,
- 0x37 | SCAN_PREFIX_SHIFT, /* PrintScreen */
- 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f,
- 0x50, 0x51, 0x52, 0x53,
- 0x46, /* XXX Pause/Break */
- 0x5b, 0x5c, 0x5d,
- /* SUN TYPE 6 USB KEYBOARD */
- 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
- 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e,
- 0x20,
- };
- int scancode;
-
- scancode = keycode;
- if ((keycode >= 89) && (keycode < 89 + sizeof(scan)/sizeof(scan[0])))
- scancode = scan[keycode - 89] | SCAN_PREFIX_E0;
- /* Pause/Break */
- if ((keycode == 104) && !(shift & (MOD_CONTROL_L | MOD_CONTROL_R)))
- scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL;
- if (shift & (MOD_SHIFT_L | MOD_SHIFT_R))
- scancode &= ~SCAN_PREFIX_SHIFT;
- return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS));
-}
-#endif /* UKBD_EMULATE_ATSCANCODE */
-
-static int
-ukbd_driver_load(module_t mod, int what, void *arg)
-{
- switch (what) {
- case MOD_LOAD:
- kbd_add_driver(&ukbd_kbd_driver);
- break;
- case MOD_UNLOAD:
- kbd_delete_driver(&ukbd_kbd_driver);
- break;
- }
- return usbd_driver_load(mod, what, arg);
-}
OpenPOWER on IntegriCloud