diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/usb/files.usb | 8 | ||||
-rw-r--r-- | sys/dev/usb/ukbd.c | 720 | ||||
-rw-r--r-- | sys/dev/usb/ukbdmap.c | 175 | ||||
-rw-r--r-- | sys/dev/usb/ukbdvar.h | 45 |
4 files changed, 947 insertions, 1 deletions
diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb index 36429e5ee61..7b6f36f6e46 100644 --- a/sys/dev/usb/files.usb +++ b/sys/dev/usb/files.usb @@ -1,4 +1,4 @@ -# $OpenBSD: files.usb,v 1.12 2000/07/04 11:44:20 fgsch Exp $ +# $OpenBSD: files.usb,v 1.13 2000/09/06 22:46:01 rahnds Exp $ # $NetBSD: files.usb,v 1.16 2000/02/14 20:29:54 augustss Exp $ # # Config file and device description for machine-independent USB code. @@ -46,6 +46,12 @@ device uhid attach uhid at uhub file dev/usb/uhid.c uhid needs-flag +# Keyboards +device ukbd: wskbddev +attach ukbd at uhub +file dev/usb/ukbd.c ukbd needs-flag +file dev/usb/ukbdmap.c ukbd + # Printers device ulpt attach ulpt at uhub diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c new file mode 100644 index 00000000000..4ccc1f062b1 --- /dev/null +++ b/sys/dev/usb/ukbd.c @@ -0,0 +1,720 @@ +/* $NetBSD: ukbd.c,v 1.60 2000/06/01 14:29:00 augustss Exp $ */ + +/* + * 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. + */ + +/* + * HID spec: http://www.usb.org/developers/data/usbhid10.pdf + */ + +#include <sys/param.h> +#include <sys/systm.h> +/* +#include <sys/callout.h> +*/ +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/file.h> +#include <sys/select.h> +#include <sys/proc.h> +#include <sys/vnode.h> +#include <sys/poll.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbhid.h> + +#include <dev/usb/usbdi.h> +#include <dev/usb/usbdi_util.h> +#include <dev/usb/usbdevs.h> +#include <dev/usb/usb_quirks.h> +#include <dev/usb/hid.h> +#include <dev/usb/ukbdvar.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wskbdvar.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> + +#if defined(__NetBSD__) +#include "opt_wsdisplay_compat.h" +#endif /* __NetBSD__ */ + +#ifdef USB_DEBUG +#define DPRINTF(x) if (ukbddebug) logprintf x +#define DPRINTFN(n,x) if (ukbddebug>(n)) logprintf x +int ukbddebug = 0; +#else +#define DPRINTF(x) +#define DPRINTFN(n,x) +#endif + +#define NKEYCODE 6 + +#define NUM_LOCK 0x01 +#define CAPS_LOCK 0x02 +#define SCROLL_LOCK 0x04 + +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 PRESS 0x000 +#define RELEASE 0x100 +#define CODEMASK 0x0ff + +/* Translate USB bitmap to USB keycode. */ +#define NMOD 8 +Static struct { + int mask, key; +} ukbd_mods[NMOD] = { + { MOD_CONTROL_L, 224 }, + { MOD_CONTROL_R, 228 }, + { MOD_SHIFT_L, 225 }, + { MOD_SHIFT_R, 229 }, + { MOD_ALT_L, 226 }, + { MOD_ALT_R, 230 }, + { MOD_WIN_L, 227 }, + { MOD_WIN_R, 231 }, +}; + +#if defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) +#define NN 0 /* no translation */ +/* + * Translate USB keycodes to US keyboard XT scancodes. + * Scancodes >= 128 represent EXTENDED keycodes. + */ +Static u_int8_t ukbd_trtab[256] = { + NN, NN, NN, NN, 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, NN, 39, 40, 41, 51, 52, /* 30 - 37 */ + 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */ + 65, 66, 67, 68, 87, 88, 170, 70, /* 40 - 47 */ + 127, 210, 199, 201, 211, 207, 209, 205, /* 48 - 4F */ + 203, 208, 200, 69, 181, 55, 74, 78, /* 50 - 57 */ + 156, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */ + 72, 73, 82, 83, NN, 221, NN, NN, /* 60 - 67 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 70 - 77 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 78 - 7F */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 80 - 87 */ + NN, NN, NN, NN, 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, 219, 157, 54, 184,220, /* 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 */ +}; +#endif /* defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) */ + +#define KEY_ERROR 0x01 + +#define MAXKEYS (NMOD+2*NKEYCODE) + +struct ukbd_softc { + USBBASEDEVICE sc_dev; /* base device */ + usbd_device_handle sc_udev; + usbd_interface_handle sc_iface; /* interface */ + usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ + int sc_ep_addr; + + struct ukbd_data sc_ndata; + struct ukbd_data sc_odata; + + char sc_enabled; + + int sc_console_keyboard; /* we are the console keyboard */ + + int sc_leds; +#if defined(__NetBSD__) + struct callout sc_rawrepeat_ch; +#endif /* __NetBSD__ */ + +#if defined(__NetBSD__) || defined(__OpenBSD__) + + struct device *sc_wskbddev; +#if defined(WSDISPLAY_COMPAT_RAWKBD) +#define REP_DELAY1 400 +#define REP_DELAYN 100 + int sc_rawkbd; + int sc_nrep; + char sc_rep[MAXKEYS]; +#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */ + + int sc_polling; + int sc_npollchar; + u_int16_t sc_pollchars[MAXKEYS]; +#endif /* defined(__NetBSD__) */ + + u_char sc_dying; +}; + +#define UKBDUNIT(dev) (minor(dev)) +#define UKBD_CHUNK 128 /* chunk size for read */ +#define UKBD_BSIZE 1020 /* buffer size */ + +Static int ukbd_is_console = 0; + + +Static void ukbd_cngetc(void *, u_int *, int *); +Static void ukbd_cnpollc(void *, int); + +#if defined(__NetBSD__) || defined(__OpenBSD__) +const struct wskbd_consops ukbd_consops = { + ukbd_cngetc, + ukbd_cnpollc, +}; +#endif + +Static void ukbd_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); + +Static int ukbd_enable(void *, int); +Static void ukbd_set_leds(void *, int); + +#if defined(__NetBSD__) || defined(__OpenBSD__) +Static int ukbd_ioctl(void *, u_long, caddr_t, int, struct proc *); +#ifdef WSDISPLAY_COMPAT_RAWKBD +Static void ukbd_rawrepeat(void *v); +#endif + +const struct wskbd_accessops ukbd_accessops = { + ukbd_enable, + ukbd_set_leds, + ukbd_ioctl, +}; + +extern const struct wscons_keydesc ukbd_keydesctab[]; + +const struct wskbd_mapdata ukbd_keymapdata = { + ukbd_keydesctab, + KB_US, +}; +#endif + +USB_DECLARE_DRIVER(ukbd); + +USB_MATCH(ukbd) +{ + USB_MATCH_START(ukbd, uaa); + usb_interface_descriptor_t *id; + + /* Check that this is a keyboard that speaks the boot protocol. */ + if (uaa->iface == NULL) + return (UMATCH_NONE); + id = usbd_get_interface_descriptor(uaa->iface); + if (id == NULL || + id->bInterfaceClass != UICLASS_HID || + id->bInterfaceSubClass != UISUBCLASS_BOOT || + id->bInterfaceProtocol != UIPROTO_BOOT_KEYBOARD) + return (UMATCH_NONE); + return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); +} + +USB_ATTACH(ukbd) +{ + USB_ATTACH_START(ukbd, sc, uaa); + usbd_interface_handle iface = uaa->iface; + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed; + usbd_status err; + char devinfo[1024]; +#if defined(__NetBSD__) || defined(__OpenBSD__) + struct wskbddev_attach_args a; +#else + int i; +#endif + + sc->sc_udev = uaa->device; + sc->sc_iface = iface; + id = usbd_get_interface_descriptor(iface); + usbd_devinfo(uaa->device, 0, devinfo); + USB_ATTACH_SETUP; + printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), + devinfo, id->bInterfaceClass, id->bInterfaceSubClass); + + ed = usbd_interface2endpoint_descriptor(iface, 0); + if (ed == NULL) { + printf("%s: could not read endpoint descriptor\n", + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; + } + + DPRINTFN(10,("ukbd_attach: bLength=%d bDescriptorType=%d " + "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" + " bInterval=%d\n", + ed->bLength, ed->bDescriptorType, + ed->bEndpointAddress & UE_ADDR, + UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", + ed->bmAttributes & UE_XFERTYPE, + UGETW(ed->wMaxPacketSize), ed->bInterval)); + + if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || + (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { + printf("%s: unexpected endpoint\n", + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; + } + + if ((usbd_get_quirks(uaa->device)->uq_flags & UQ_NO_SET_PROTO) == 0) { + err = usbd_set_protocol(iface, 0); + DPRINTFN(5, ("ukbd_attach: protocol set\n")); + if (err) { + printf("%s: set protocol failed\n", + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; + } + } + + /* Ignore if SETIDLE fails since it is not crucial. */ + usbd_set_idle(iface, 0, 0); + + sc->sc_ep_addr = ed->bEndpointAddress; + + /* + * Remember if we're the console keyboard. + * + * XXX This always picks the first keyboard on the + * first USB bus, but what else can we really do? + */ + if ((sc->sc_console_keyboard = ukbd_is_console) != 0) { + /* Don't let any other keyboard have it. */ + ukbd_is_console = 0; + } + + if (sc->sc_console_keyboard) { + DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc)); + wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata); + ukbd_enable(sc, 1); + } + + a.console = sc->sc_console_keyboard; + + a.keymap = &ukbd_keymapdata; + + a.accessops = &ukbd_accessops; + a.accesscookie = sc; + +#if defined(__NetBSD__) + callout_init(&sc->sc_rawrepeat_ch); +#endif /* __NetBSD__ */ + + /* Flash the leds; no real purpose, just shows we're alive. */ + ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS); + usbd_delay_ms(uaa->device, 400); + ukbd_set_leds(sc, 0); + + sc->sc_wskbddev = config_found(self, &a, wskbddevprint); + + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + + USB_ATTACH_SUCCESS_RETURN; +} + +int +ukbd_enable(void *v, int on) +{ + struct ukbd_softc *sc = v; + usbd_status err; + + if (on && sc->sc_dying) + return (EIO); + + /* Should only be called to change state */ + if (sc->sc_enabled == on) { +#ifdef DIAGNOSTIC + printf("ukbd_enable: %s: bad call on=%d\n", + USBDEVNAME(sc->sc_dev), on); +#endif + return (EBUSY); + } + + DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on)); + if (on) { + /* Set up interrupt pipe. */ + err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, + USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, + &sc->sc_ndata, sizeof(sc->sc_ndata), ukbd_intr, + USBD_DEFAULT_INTERVAL); + if (err) + return (EIO); + } else { + /* Disable interrupts. */ + usbd_abort_pipe(sc->sc_intrpipe); + usbd_close_pipe(sc->sc_intrpipe); + } + sc->sc_enabled = on; + + return (0); +} + +int +ukbd_activate(device_ptr_t self, enum devact act) +{ + struct ukbd_softc *sc = (struct ukbd_softc *)self; + int rv = 0; + + switch (act) { + case DVACT_ACTIVATE: + return (EOPNOTSUPP); + break; + + case DVACT_DEACTIVATE: + if (sc->sc_wskbddev != NULL) + rv = config_deactivate(sc->sc_wskbddev); + sc->sc_dying = 1; + break; + } + return (rv); +} + +USB_DETACH(ukbd) +{ + USB_DETACH_START(ukbd, sc); + int rv = 0; + + DPRINTF(("ukbd_detach: sc=%p flags=%d\n", sc, flags)); + + if (sc->sc_console_keyboard) { +#if 0 + /* + * XXX Should probably disconnect our consops, + * XXX and either notify some other keyboard that + * XXX it can now be the console, or if there aren't + * XXX any more USB keyboards, set ukbd_is_console + * XXX back to 1 so that the next USB keyboard attached + * XXX to the system will get it. + */ + panic("ukbd_detach: console keyboard"); +#else + /* + * Disconnect our consops and set ukbd_is_console + * back to 1 so that the next USB keyboard attached + * to the system will get it. + * XXX Should notify some other keyboard that it can be + * XXX console, if there are any other keyboards. + */ + printf("%s: was console keyboard\n", USBDEVNAME(sc->sc_dev)); + wskbd_cndetach(); + ukbd_is_console = 1; +#endif + } + /* No need to do reference counting of ukbd, wskbd has all the goo. */ + if (sc->sc_wskbddev != NULL) + rv = config_detach(sc->sc_wskbddev, flags); + + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + + return (rv); +} + +void +ukbd_intr(xfer, addr, status) + usbd_xfer_handle xfer; + usbd_private_handle addr; + usbd_status status; +{ + struct ukbd_softc *sc = addr; + struct ukbd_data *ud = &sc->sc_ndata; + int mod, omod; + u_int16_t ibuf[MAXKEYS]; /* chars events */ + int s; + int nkeys, i, j; + int key; +#define ADDKEY(c) ibuf[nkeys++] = (c) + + DPRINTFN(5, ("ukbd_intr: status=%d\n", status)); + if (status == USBD_CANCELLED) + return; + + if (status) { + DPRINTF(("ukbd_intr: status=%d\n", status)); + usbd_clear_endpoint_stall_async(sc->sc_intrpipe); + return; + } + + DPRINTFN(5, (" mod=0x%02x key0=0x%02x key1=0x%02x\n", + ud->modifiers, ud->keycode[0], ud->keycode[1])); + + if (ud->keycode[0] == KEY_ERROR) { + DPRINTF(("ukbd_intr: KEY_ERROR\n")); + return; /* ignore */ + } + nkeys = 0; + mod = ud->modifiers; + omod = sc->sc_odata.modifiers; + if (mod != omod) + for (i = 0; i < NMOD; i++) + if (( mod & ukbd_mods[i].mask) != + (omod & ukbd_mods[i].mask)) + ADDKEY(ukbd_mods[i].key | + (mod & ukbd_mods[i].mask + ? PRESS : RELEASE)); + if (memcmp(ud->keycode, sc->sc_odata.keycode, NKEYCODE) != 0) { + /* Check for released keys. */ + for (i = 0; i < NKEYCODE; i++) { + key = sc->sc_odata.keycode[i]; + if (key == 0) + continue; + for (j = 0; j < NKEYCODE; j++) + if (key == ud->keycode[j]) + goto rfound; + ADDKEY(key | RELEASE); + rfound: + ; + } + + /* Check for pressed keys. */ + for (i = 0; i < NKEYCODE; i++) { + key = ud->keycode[i]; + if (key == 0) + continue; + for (j = 0; j < NKEYCODE; j++) + if (key == sc->sc_odata.keycode[j]) + goto pfound; + DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key)); + ADDKEY(key | PRESS); + pfound: + ; + } + } + sc->sc_odata = *ud; + + if (nkeys == 0) + return; + + if (sc->sc_polling) { + DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0])); + memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t)); + sc->sc_npollchar = nkeys; + return; + } +#ifdef WSDISPLAY_COMPAT_RAWKBD + if (sc->sc_rawkbd) { + char cbuf[MAXKEYS * 2]; + int c; + int npress; + + for (npress = i = j = 0; i < nkeys; i++) { + key = ibuf[i]; + c = ukbd_trtab[key & CODEMASK]; + if (c == NN) + continue; + if (c & 0x80) + cbuf[j++] = 0xe0; + cbuf[j] = c & 0x7f; + if (key & RELEASE) + cbuf[j] |= 0x80; + else { + /* remember pressed keys for autorepeat */ + if (c & 0x80) + sc->sc_rep[npress++] = 0xe0; + sc->sc_rep[npress++] = c & 0x7f; + } + DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n", + c & 0x80 ? "0xe0 " : "", + cbuf[j])); + j++; + } + s = spltty(); + wskbd_rawinput(sc->sc_wskbddev, cbuf, j); + splx(s); +#if defined(__NetBSD__) + callout_stop(&sc->sc_rawrepeat_ch); +#endif /* __NetBSD__ */ + if (npress != 0) { + sc->sc_nrep = npress; +#if defined(__NetBSD__) + callout_reset(&sc->sc_rawrepeat_ch, + hz * REP_DELAY1 / 1000, ukbd_rawrepeat, sc); +#endif /* __NetBSD__ */ + } + return; + } +#endif + + s = spltty(); + for (i = 0; i < nkeys; i++) { + key = ibuf[i]; + wskbd_input(sc->sc_wskbddev, + key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN, + key&CODEMASK); + } + splx(s); +} + +void +ukbd_set_leds(void *v, int leds) +{ + struct ukbd_softc *sc = v; + u_int8_t res; + + DPRINTF(("ukbd_set_leds: sc=%p leds=%d\n", sc, leds)); + + if (sc->sc_dying) + return; + + sc->sc_leds = leds; + res = 0; + if (leds & WSKBD_LED_SCROLL) + res |= SCROLL_LOCK; + if (leds & WSKBD_LED_NUM) + res |= NUM_LOCK; + if (leds & WSKBD_LED_CAPS) + res |= CAPS_LOCK; + res |= leds & 0xf8; + usbd_set_report_async(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1); +} + +#ifdef WSDISPLAY_COMPAT_RAWKBD +void +ukbd_rawrepeat(void *v) +{ + struct ukbd_softc *sc = v; + int s; + + s = spltty(); + wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep); + splx(s); +#if defined(__NetBSD__) + callout_reset(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000, + ukbd_rawrepeat, sc); +#endif /* __NetBSD__ */ +} +#endif + +int +ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct ukbd_softc *sc = v; + + switch (cmd) { + case WSKBDIO_GTYPE: + *(int *)data = WSKBD_TYPE_USB; + return (0); + case WSKBDIO_SETLEDS: + ukbd_set_leds(v, *(int *)data); + return (0); + case WSKBDIO_GETLEDS: + *(int *)data = sc->sc_leds; + return (0); +#ifdef WSDISPLAY_COMPAT_RAWKBD + case WSKBDIO_SETMODE: + DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data)); + sc->sc_rawkbd = *(int *)data == WSKBD_RAW; +#if defined(__NetBSD__) + callout_stop(&sc->sc_rawrepeat_ch); +#endif /* __NetBSD__ */ + return (0); +#endif + } + return (-1); +} + +/* Console interface. */ +void +ukbd_cngetc(void *v, u_int *type, int *data) +{ + struct ukbd_softc *sc = v; + int s; + int c; + + DPRINTFN(0,("ukbd_cngetc: enter\n")); + s = splusb(); + sc->sc_polling = 1; + while(sc->sc_npollchar <= 0) + usbd_dopoll(sc->sc_iface); + sc->sc_polling = 0; + c = sc->sc_pollchars[0]; + sc->sc_npollchar--; + memcpy(sc->sc_pollchars, sc->sc_pollchars+1, + sc->sc_npollchar * sizeof(u_int16_t)); + *type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; + *data = c & CODEMASK; + splx(s); + DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", c)); +} + +void +ukbd_cnpollc(void *v, int on) +{ + struct ukbd_softc *sc = v; + usbd_device_handle dev; + + DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on)); + + (void)usbd_interface2device_handle(sc->sc_iface,&dev); + usbd_set_polling(dev, on); +} + +int +ukbd_cnattach(void) +{ + + /* + * XXX USB requires too many parts of the kernel to be running + * XXX in order to work, so we can't do much for the console + * XXX keyboard until autconfiguration has run its course. + */ + ukbd_is_console = 1; + return (0); +} diff --git a/sys/dev/usb/ukbdmap.c b/sys/dev/usb/ukbdmap.c new file mode 100644 index 00000000000..98c19e57969 --- /dev/null +++ b/sys/dev/usb/ukbdmap.c @@ -0,0 +1,175 @@ +/* $NetBSD: ukbdmap.c,v 1.5 2000/04/27 15:26:49 augustss Exp $ */ + +/* + * Copyright (c) 1999 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/types.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> + +#include <dev/usb/usb_port.h> + +#define KC(n) KS_KEYCODE(n) + +Static const keysym_t ukbd_keydesc_us[] = { +/* pos command normal shifted */ + KC(4), KS_a, + KC(5), KS_b, + KC(6), KS_c, + KC(7), KS_d, + KC(8), KS_e, + KC(9), KS_f, + KC(10), KS_g, + KC(11), KS_h, + KC(12), KS_i, + KC(13), KS_j, + KC(14), KS_k, + KC(15), KS_l, + KC(16), KS_m, + KC(17), KS_n, + KC(18), KS_o, + KC(19), KS_p, + KC(20), KS_q, + KC(21), KS_r, + KC(22), KS_s, + KC(23), KS_t, + KC(24), KS_u, + KC(25), KS_v, + KC(26), KS_w, + KC(27), KS_x, + KC(28), KS_y, + KC(29), KS_z, + KC(30), KS_1, KS_exclam, + KC(31), KS_2, KS_at, + KC(32), KS_3, KS_numbersign, + KC(33), KS_4, KS_dollar, + KC(34), KS_5, KS_percent, + KC(35), KS_6, KS_asciicircum, + KC(36), KS_7, KS_ampersand, + KC(37), KS_8, KS_asterisk, + KC(38), KS_9, KS_parenleft, + KC(39), KS_0, KS_parenright, + KC(40), KS_Return, + KC(41), KS_Cmd_Debugger, KS_Escape, + KC(42), KS_BackSpace, + KC(43), KS_Tab, + KC(44), KS_space, + KC(45), KS_minus, KS_underscore, + KC(46), KS_equal, KS_plus, + KC(47), KS_bracketleft, KS_braceleft, + KC(48), KS_bracketright,KS_braceright, + KC(49), KS_backslash, KS_bar, + KC(50), KS_numbersign, KS_asciitilde, + KC(51), KS_semicolon, KS_colon, + KC(52), KS_apostrophe, KS_quotedbl, + KC(53), KS_grave, KS_asciitilde, + KC(54), KS_comma, KS_less, + KC(55), KS_period, KS_greater, + KC(56), KS_slash, KS_question, + KC(57), KS_Caps_Lock, + KC(58), KS_Cmd_Screen0, KS_f1, + KC(59), KS_Cmd_Screen1, KS_f2, + KC(60), KS_Cmd_Screen2, KS_f3, + KC(61), KS_Cmd_Screen3, KS_f4, + KC(62), KS_Cmd_Screen4, KS_f5, + KC(63), KS_Cmd_Screen5, KS_f6, + KC(64), KS_Cmd_Screen6, KS_f7, + KC(65), KS_Cmd_Screen7, KS_f8, + KC(66), KS_Cmd_Screen8, KS_f9, + KC(67), KS_Cmd_Screen9, KS_f10, + KC(68), KS_f11, + KC(69), KS_f12, + KC(70), KS_Print_Screen, + KC(71), KS_Hold_Screen, + KC(72), KS_Pause, + KC(73), KS_Insert, + KC(74), KS_Home, + KC(75), KS_Prior, + KC(76), KS_Delete, + KC(77), KS_End, + KC(78), KS_Next, + KC(79), KS_Right, + KC(80), KS_Left, + KC(81), KS_Down, + KC(82), KS_Up, + KC(83), KS_Num_Lock, + KC(84), KS_KP_Divide, + KC(85), KS_KP_Multiply, + KC(86), KS_KP_Subtract, + KC(87), KS_KP_Add, + KC(88), KS_KP_Enter, + KC(89), KS_KP_End, KS_KP_1, + KC(90), KS_KP_Down, KS_KP_2, + KC(91), KS_KP_Next, KS_KP_3, + KC(92), KS_KP_Left, KS_KP_4, + KC(93), KS_KP_Begin, KS_KP_5, + KC(94), KS_KP_Right, KS_KP_6, + KC(95), KS_KP_Home, KS_KP_7, + KC(96), KS_KP_Up, KS_KP_8, + KC(97), KS_KP_Prior, KS_KP_9, + KC(98), KS_KP_Insert, KS_KP_0, + KC(99), KS_KP_Delete, KS_KP_Decimal, + KC(100), KS_backslash, KS_bar, + KC(101), KS_Menu, +/* ... many unmapped keys ... */ + KC(224), KS_Cmd1, KS_Control_L, + KC(225), KS_Shift_L, + KC(226), KS_Cmd2, KS_Alt_L, + KC(227), KS_Meta_L, + KC(228), KS_Control_R, + KC(229), KS_Shift_R, + KC(230), KS_Alt_R, KS_Multi_key, + KC(231), KS_Meta_R, +}; + +Static const keysym_t ukbd_keydesc_swapctrlcaps[] = { +/* pos command normal shifted */ + KC(57), KS_Control_L, + KC(224), KS_Cmd1, KS_Caps_Lock, +}; + +#define KBD_MAP(name, base, map) \ + { name, base, sizeof(map)/sizeof(keysym_t), map } + +const struct wscons_keydesc ukbd_keydesctab[] = { + KBD_MAP(KB_US, 0, ukbd_keydesc_us), + KBD_MAP(KB_US | KB_SWAPCTRLCAPS, KB_US, ukbd_keydesc_swapctrlcaps), + {0, 0, 0, 0} +}; + +#undef KBD_MAP +#undef KC diff --git a/sys/dev/usb/ukbdvar.h b/sys/dev/usb/ukbdvar.h new file mode 100644 index 00000000000..e49f9629270 --- /dev/null +++ b/sys/dev/usb/ukbdvar.h @@ -0,0 +1,45 @@ +/* $NetBSD: ukbdvar.h,v 1.2 2000/06/01 14:29:00 augustss Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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. + */ + +#ifndef _DEV_USB_UKBDVAR_H_ +#define _DEV_USB_UKBDVAR_H_ + +int ukbd_cnattach(void); + +#endif /* _DEV_USB_UKBDVAR_H_ */ |