Home | History | Annotate | Line # | Download | only in usb
ukbd.c revision 1.95
      1  1.95  christos /*      $NetBSD: ukbd.c,v 1.95 2007/03/04 06:02:49 christos Exp $        */
      2   1.1  augustss 
      3   1.1  augustss /*
      4   1.1  augustss  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5   1.1  augustss  * All rights reserved.
      6   1.1  augustss  *
      7  1.11  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8  1.59  augustss  * by Lennart Augustsson (lennart (at) augustsson.net) at
      9  1.11  augustss  * Carlstedt Research & Technology.
     10   1.1  augustss  *
     11   1.1  augustss  * Redistribution and use in source and binary forms, with or without
     12   1.1  augustss  * modification, are permitted provided that the following conditions
     13   1.1  augustss  * are met:
     14   1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     15   1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     16   1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     17   1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     18   1.1  augustss  *    documentation and/or other materials provided with the distribution.
     19   1.1  augustss  * 3. All advertising materials mentioning features or use of this software
     20   1.1  augustss  *    must display the following acknowledgement:
     21   1.1  augustss  *        This product includes software developed by the NetBSD
     22   1.1  augustss  *        Foundation, Inc. and its contributors.
     23   1.1  augustss  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24   1.1  augustss  *    contributors may be used to endorse or promote products derived
     25   1.1  augustss  *    from this software without specific prior written permission.
     26   1.1  augustss  *
     27   1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28   1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29   1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30   1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31   1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32   1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33   1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34   1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35   1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36   1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37   1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     38   1.1  augustss  */
     39   1.1  augustss 
     40  1.17  augustss /*
     41  1.85  augustss  * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
     42  1.17  augustss  */
     43  1.72     lukem 
     44  1.72     lukem #include <sys/cdefs.h>
     45  1.95  christos __KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.95 2007/03/04 06:02:49 christos Exp $");
     46  1.17  augustss 
     47   1.1  augustss #include <sys/param.h>
     48   1.1  augustss #include <sys/systm.h>
     49  1.57   thorpej #include <sys/callout.h>
     50   1.1  augustss #include <sys/kernel.h>
     51   1.1  augustss #include <sys/device.h>
     52   1.1  augustss #include <sys/ioctl.h>
     53   1.1  augustss #include <sys/tty.h>
     54   1.1  augustss #include <sys/file.h>
     55   1.1  augustss #include <sys/select.h>
     56   1.1  augustss #include <sys/proc.h>
     57   1.1  augustss #include <sys/vnode.h>
     58   1.1  augustss #include <sys/poll.h>
     59   1.1  augustss 
     60   1.1  augustss #include <dev/usb/usb.h>
     61   1.2  augustss #include <dev/usb/usbhid.h>
     62  1.37  augustss 
     63   1.1  augustss #include <dev/usb/usbdi.h>
     64   1.1  augustss #include <dev/usb/usbdi_util.h>
     65   1.1  augustss #include <dev/usb/usbdevs.h>
     66   1.1  augustss #include <dev/usb/usb_quirks.h>
     67  1.75  augustss #include <dev/usb/uhidev.h>
     68   1.1  augustss #include <dev/usb/hid.h>
     69  1.31   thorpej #include <dev/usb/ukbdvar.h>
     70   1.1  augustss 
     71   1.2  augustss #include <dev/wscons/wsconsio.h>
     72   1.2  augustss #include <dev/wscons/wskbdvar.h>
     73   1.2  augustss #include <dev/wscons/wsksymdef.h>
     74   1.2  augustss #include <dev/wscons/wsksymvar.h>
     75   1.2  augustss 
     76  1.89      cube #include "opt_ukbd_layout.h"
     77   1.2  augustss #include "opt_wsdisplay_compat.h"
     78  1.69  augustss #include "opt_ddb.h"
     79  1.21  augustss 
     80  1.62  augustss #ifdef UKBD_DEBUG
     81  1.39  augustss #define DPRINTF(x)	if (ukbddebug) logprintf x
     82  1.39  augustss #define DPRINTFN(n,x)	if (ukbddebug>(n)) logprintf x
     83   1.1  augustss int	ukbddebug = 0;
     84   1.1  augustss #else
     85   1.1  augustss #define DPRINTF(x)
     86   1.1  augustss #define DPRINTFN(n,x)
     87   1.1  augustss #endif
     88   1.1  augustss 
     89  1.75  augustss #define MAXKEYCODE 6
     90  1.75  augustss #define MAXMOD 8		/* max 32 */
     91   1.2  augustss 
     92   1.1  augustss struct ukbd_data {
     93  1.75  augustss 	u_int32_t	modifiers;
     94  1.75  augustss 	u_int8_t	keycode[MAXKEYCODE];
     95   1.1  augustss };
     96   1.1  augustss 
     97  1.23  augustss #define PRESS    0x000
     98  1.23  augustss #define RELEASE  0x100
     99  1.23  augustss #define CODEMASK 0x0ff
    100   1.1  augustss 
    101  1.23  augustss #if defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD)
    102   1.5  augustss #define NN 0			/* no translation */
    103  1.82  augustss /*
    104  1.23  augustss  * Translate USB keycodes to US keyboard XT scancodes.
    105  1.76  augustss  * Scancodes >= 0x80 represent EXTENDED keycodes.
    106  1.76  augustss  *
    107  1.76  augustss  * See http://www.microsoft.com/HWDEV/TECH/input/Scancode.asp
    108  1.19  augustss  */
    109  1.65  jdolecek Static const u_int8_t ukbd_trtab[256] = {
    110  1.76  augustss       NN,   NN,   NN,   NN, 0x1e, 0x30, 0x2e, 0x20, /* 00 - 07 */
    111  1.76  augustss     0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, /* 08 - 0f */
    112  1.76  augustss     0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, /* 10 - 17 */
    113  1.76  augustss     0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x02, 0x03, /* 18 - 1f */
    114  1.76  augustss     0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 20 - 27 */
    115  1.76  augustss     0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a, /* 28 - 2f */
    116  1.76  augustss     0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34, /* 30 - 37 */
    117  1.76  augustss     0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, /* 38 - 3f */
    118  1.76  augustss     0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xaa, 0x46, /* 40 - 47 */
    119  1.76  augustss     0x7f, 0xd2, 0xc7, 0xc9, 0xd3, 0xcf, 0xd1, 0xcd, /* 48 - 4f */
    120  1.76  augustss     0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e, /* 50 - 57 */
    121  1.76  augustss     0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47, /* 58 - 5f */
    122  1.76  augustss     0x48, 0x49, 0x52, 0x53, 0x56, 0xdd,   NN, 0x59, /* 60 - 67 */
    123  1.76  augustss     0x5d, 0x5e, 0x5f,   NN,   NN,   NN,   NN,   NN, /* 68 - 6f */
    124  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* 70 - 77 */
    125  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* 78 - 7f */
    126  1.76  augustss       NN,   NN,   NN,   NN,   NN, 0x7e,   NN, 0x73, /* 80 - 87 */
    127  1.76  augustss     0x70, 0x7d, 0x79, 0x7b, 0x5c,   NN,   NN,   NN, /* 88 - 8f */
    128  1.76  augustss       NN,   NN, 0x78, 0x77, 0x76,   NN,   NN,   NN, /* 90 - 97 */
    129  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* 98 - 9f */
    130  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* a0 - a7 */
    131  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* a8 - af */
    132  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* b0 - b7 */
    133  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* b8 - bf */
    134  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* c0 - c7 */
    135  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* c8 - cf */
    136  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* d0 - d7 */
    137  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* d8 - df */
    138  1.76  augustss     0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, /* e0 - e7 */
    139  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* e8 - ef */
    140  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* f0 - f7 */
    141  1.76  augustss       NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* f8 - ff */
    142   1.1  augustss };
    143  1.23  augustss #endif /* defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) */
    144   1.1  augustss 
    145   1.1  augustss #define KEY_ERROR 0x01
    146   1.1  augustss 
    147  1.75  augustss #define MAXKEYS (MAXMOD+2*MAXKEYCODE)
    148  1.20  augustss 
    149   1.1  augustss struct ukbd_softc {
    150  1.75  augustss 	struct uhidev sc_hdev;
    151   1.1  augustss 
    152   1.1  augustss 	struct ukbd_data sc_ndata;
    153   1.1  augustss 	struct ukbd_data sc_odata;
    154  1.75  augustss 	struct hid_location sc_modloc[MAXMOD];
    155  1.75  augustss 	u_int sc_nmod;
    156  1.75  augustss 	struct {
    157  1.75  augustss 		u_int32_t mask;
    158  1.75  augustss 		u_int8_t key;
    159  1.75  augustss 	} sc_mods[MAXMOD];
    160  1.75  augustss 
    161  1.75  augustss 	struct hid_location sc_keycodeloc;
    162  1.75  augustss 	u_int sc_nkeycode;
    163   1.1  augustss 
    164   1.9  augustss 	char sc_enabled;
    165   1.1  augustss 
    166  1.29   thorpej 	int sc_console_keyboard;	/* we are the console keyboard */
    167  1.29   thorpej 
    168  1.62  augustss 	char sc_debounce;		/* for quirk handling */
    169  1.70  augustss 	usb_callout_t sc_delay;		/* for quirk handling */
    170  1.62  augustss 	struct ukbd_data sc_data;	/* for quirk handling */
    171  1.62  augustss 
    172  1.75  augustss 	struct hid_location sc_numloc;
    173  1.75  augustss 	struct hid_location sc_capsloc;
    174  1.75  augustss 	struct hid_location sc_scroloc;
    175   1.2  augustss 	int sc_leds;
    176  1.16  augustss #if defined(__NetBSD__)
    177  1.87  augustss 	struct device *sc_wskbddev;
    178  1.57   thorpej 
    179  1.23  augustss #if defined(WSDISPLAY_COMPAT_RAWKBD)
    180  1.87  augustss 	int sc_rawkbd;
    181  1.87  augustss #if defined(UKBD_REPEAT)
    182  1.87  augustss 	usb_callout_t sc_rawrepeat_ch;
    183  1.20  augustss #define REP_DELAY1 400
    184  1.20  augustss #define REP_DELAYN 100
    185  1.20  augustss 	int sc_nrep;
    186  1.20  augustss 	char sc_rep[MAXKEYS];
    187  1.87  augustss #endif /* defined(UKBD_REPEAT) */
    188  1.23  augustss #endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
    189   1.3  augustss 
    190  1.84  augustss 	int sc_spl;
    191   1.3  augustss 	int sc_polling;
    192  1.23  augustss 	int sc_npollchar;
    193  1.23  augustss 	u_int16_t sc_pollchars[MAXKEYS];
    194  1.23  augustss #endif /* defined(__NetBSD__) */
    195  1.40  augustss 
    196  1.40  augustss 	u_char sc_dying;
    197   1.1  augustss };
    198   1.1  augustss 
    199  1.62  augustss #ifdef UKBD_DEBUG
    200  1.62  augustss #define UKBDTRACESIZE 64
    201  1.62  augustss struct ukbdtraceinfo {
    202  1.62  augustss 	int unit;
    203  1.62  augustss 	struct timeval tv;
    204  1.62  augustss 	struct ukbd_data ud;
    205  1.62  augustss };
    206  1.62  augustss struct ukbdtraceinfo ukbdtracedata[UKBDTRACESIZE];
    207  1.62  augustss int ukbdtraceindex = 0;
    208  1.62  augustss int ukbdtrace = 0;
    209  1.62  augustss void ukbdtracedump(void);
    210  1.62  augustss void
    211  1.62  augustss ukbdtracedump(void)
    212  1.62  augustss {
    213  1.62  augustss 	int i;
    214  1.62  augustss 	for (i = 0; i < UKBDTRACESIZE; i++) {
    215  1.82  augustss 		struct ukbdtraceinfo *p =
    216  1.62  augustss 		    &ukbdtracedata[(i+ukbdtraceindex)%UKBDTRACESIZE];
    217  1.62  augustss 		printf("%lu.%06lu: mod=0x%02x key0=0x%02x key1=0x%02x "
    218  1.62  augustss 		       "key2=0x%02x key3=0x%02x\n",
    219  1.62  augustss 		       p->tv.tv_sec, p->tv.tv_usec,
    220  1.62  augustss 		       p->ud.modifiers, p->ud.keycode[0], p->ud.keycode[1],
    221  1.62  augustss 		       p->ud.keycode[2], p->ud.keycode[3]);
    222  1.62  augustss 	}
    223  1.62  augustss }
    224  1.62  augustss #endif
    225  1.62  augustss 
    226   1.1  augustss #define	UKBDUNIT(dev)	(minor(dev))
    227   1.1  augustss #define	UKBD_CHUNK	128	/* chunk size for read */
    228   1.1  augustss #define	UKBD_BSIZE	1020	/* buffer size */
    229   1.1  augustss 
    230  1.58  augustss Static int	ukbd_is_console;
    231  1.31   thorpej 
    232  1.60  augustss Static void	ukbd_cngetc(void *, u_int *, int *);
    233  1.60  augustss Static void	ukbd_cnpollc(void *, int);
    234   1.3  augustss 
    235  1.16  augustss #if defined(__NetBSD__)
    236   1.8  drochner const struct wskbd_consops ukbd_consops = {
    237   1.8  drochner 	ukbd_cngetc,
    238   1.8  drochner 	ukbd_cnpollc,
    239  1.92  christos 	NULL,	/* bell */
    240   1.8  drochner };
    241  1.16  augustss #endif
    242   1.8  drochner 
    243  1.75  augustss Static const char *ukbd_parse_desc(struct ukbd_softc *sc);
    244  1.75  augustss 
    245  1.75  augustss Static void	ukbd_intr(struct uhidev *addr, void *ibuf, u_int len);
    246  1.62  augustss Static void	ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud);
    247  1.62  augustss Static void	ukbd_delayed_decode(void *addr);
    248   1.2  augustss 
    249  1.60  augustss Static int	ukbd_enable(void *, int);
    250  1.60  augustss Static void	ukbd_set_leds(void *, int);
    251  1.23  augustss 
    252  1.16  augustss #if defined(__NetBSD__)
    253  1.95  christos Static int	ukbd_ioctl(void *, u_long, void *, int, struct lwp *);
    254  1.88  jonathan #if  defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT)
    255  1.60  augustss Static void	ukbd_rawrepeat(void *v);
    256  1.48    mjacob #endif
    257   1.1  augustss 
    258   1.8  drochner const struct wskbd_accessops ukbd_accessops = {
    259   1.8  drochner 	ukbd_enable,
    260   1.8  drochner 	ukbd_set_leds,
    261   1.8  drochner 	ukbd_ioctl,
    262   1.8  drochner };
    263   1.8  drochner 
    264  1.23  augustss extern const struct wscons_keydesc ukbd_keydesctab[];
    265  1.23  augustss 
    266   1.8  drochner const struct wskbd_mapdata ukbd_keymapdata = {
    267  1.23  augustss 	ukbd_keydesctab,
    268  1.86  augustss #if defined(UKBD_LAYOUT)
    269  1.66  augustss 	UKBD_LAYOUT,
    270  1.86  augustss #elif defined(PCKBD_LAYOUT)
    271  1.86  augustss 	PCKBD_LAYOUT,
    272  1.66  augustss #else
    273   1.8  drochner 	KB_US,
    274  1.66  augustss #endif
    275   1.8  drochner };
    276  1.16  augustss #endif
    277   1.8  drochner 
    278  1.16  augustss USB_DECLARE_DRIVER(ukbd);
    279   1.1  augustss 
    280  1.75  augustss int
    281  1.94  christos ukbd_match(struct device *parent, struct cfdata *match,
    282  1.93  christos     void *aux)
    283   1.1  augustss {
    284  1.75  augustss 	struct uhidev_attach_arg *uha = aux;
    285  1.75  augustss 	int size;
    286  1.75  augustss 	void *desc;
    287  1.82  augustss 
    288  1.75  augustss 	uhidev_get_report_desc(uha->parent, &desc, &size);
    289  1.75  augustss 	if (!hid_is_collection(desc, size, uha->reportid,
    290  1.75  augustss 			       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
    291   1.1  augustss 		return (UMATCH_NONE);
    292  1.75  augustss 
    293  1.75  augustss 	return (UMATCH_IFACECLASS);
    294   1.1  augustss }
    295   1.1  augustss 
    296  1.75  augustss void
    297  1.94  christos ukbd_attach(struct device *parent, struct device *self, void *aux)
    298   1.1  augustss {
    299  1.75  augustss 	struct ukbd_softc *sc = (struct ukbd_softc *)self;
    300  1.75  augustss 	struct uhidev_attach_arg *uha = aux;
    301  1.62  augustss 	u_int32_t qflags;
    302  1.75  augustss 	const char *parseerr;
    303  1.16  augustss #if defined(__NetBSD__)
    304   1.2  augustss 	struct wskbddev_attach_args a;
    305  1.16  augustss #else
    306  1.16  augustss 	int i;
    307  1.16  augustss #endif
    308  1.82  augustss 
    309  1.75  augustss 	sc->sc_hdev.sc_intr = ukbd_intr;
    310  1.75  augustss 	sc->sc_hdev.sc_parent = uha->parent;
    311  1.75  augustss 	sc->sc_hdev.sc_report_id = uha->reportid;
    312  1.75  augustss 
    313  1.75  augustss 	parseerr = ukbd_parse_desc(sc);
    314  1.75  augustss 	if (parseerr != NULL) {
    315  1.75  augustss 		printf("\n%s: attach failed, %s\n",
    316  1.75  augustss 		       sc->sc_hdev.sc_dev.dv_xname, parseerr);
    317  1.16  augustss 		USB_ATTACH_ERROR_RETURN;
    318   1.1  augustss 	}
    319  1.82  augustss 
    320  1.75  augustss #ifdef DIAGNOSTIC
    321  1.75  augustss 	printf(": %d modifier keys, %d key codes", sc->sc_nmod,
    322  1.75  augustss 	       sc->sc_nkeycode);
    323  1.75  augustss #endif
    324  1.75  augustss 	printf("\n");
    325   1.1  augustss 
    326   1.1  augustss 
    327  1.75  augustss 	qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
    328  1.62  augustss 	sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0;
    329  1.20  augustss 
    330  1.29   thorpej 	/*
    331  1.29   thorpej 	 * Remember if we're the console keyboard.
    332  1.29   thorpej 	 *
    333  1.31   thorpej 	 * XXX This always picks the first keyboard on the
    334  1.31   thorpej 	 * first USB bus, but what else can we really do?
    335  1.29   thorpej 	 */
    336  1.31   thorpej 	if ((sc->sc_console_keyboard = ukbd_is_console) != 0) {
    337  1.29   thorpej 		/* Don't let any other keyboard have it. */
    338  1.31   thorpej 		ukbd_is_console = 0;
    339  1.29   thorpej 	}
    340  1.29   thorpej 
    341  1.31   thorpej 	if (sc->sc_console_keyboard) {
    342  1.32  augustss 		DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
    343  1.31   thorpej 		wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
    344  1.34  wrstuden 		ukbd_enable(sc, 1);
    345  1.31   thorpej 	}
    346  1.29   thorpej 
    347  1.29   thorpej 	a.console = sc->sc_console_keyboard;
    348   1.8  drochner 
    349   1.8  drochner 	a.keymap = &ukbd_keymapdata;
    350   1.8  drochner 
    351   1.8  drochner 	a.accessops = &ukbd_accessops;
    352   1.2  augustss 	a.accesscookie = sc;
    353   1.8  drochner 
    354  1.87  augustss #ifdef UKBD_REPEAT
    355  1.70  augustss 	usb_callout_init(sc->sc_rawrepeat_ch);
    356  1.87  augustss #endif
    357  1.57   thorpej 
    358  1.70  augustss 	usb_callout_init(sc->sc_delay);
    359  1.62  augustss 
    360  1.19  augustss 	/* Flash the leds; no real purpose, just shows we're alive. */
    361  1.19  augustss 	ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS);
    362  1.75  augustss 	usbd_delay_ms(uha->parent->sc_udev, 400);
    363  1.19  augustss 	ukbd_set_leds(sc, 0);
    364  1.19  augustss 
    365  1.64  augustss 	sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
    366  1.55  augustss 
    367  1.16  augustss 	USB_ATTACH_SUCCESS_RETURN;
    368   1.1  augustss }
    369   1.1  augustss 
    370   1.8  drochner int
    371  1.60  augustss ukbd_enable(void *v, int on)
    372   1.8  drochner {
    373   1.9  augustss 	struct ukbd_softc *sc = v;
    374   1.9  augustss 
    375  1.40  augustss 	if (on && sc->sc_dying)
    376  1.40  augustss 		return (EIO);
    377  1.40  augustss 
    378  1.38  augustss 	/* Should only be called to change state */
    379  1.38  augustss 	if (sc->sc_enabled == on) {
    380  1.38  augustss #ifdef DIAGNOSTIC
    381  1.82  augustss 		printf("ukbd_enable: %s: bad call on=%d\n",
    382  1.75  augustss 		       USBDEVNAME(sc->sc_hdev.sc_dev), on);
    383  1.38  augustss #endif
    384  1.38  augustss 		return (EBUSY);
    385  1.38  augustss 	}
    386  1.38  augustss 
    387  1.33  augustss 	DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on));
    388  1.75  augustss 	sc->sc_enabled = on;
    389   1.9  augustss 	if (on) {
    390  1.75  augustss 		return (uhidev_open(&sc->sc_hdev));
    391   1.9  augustss 	} else {
    392  1.75  augustss 		uhidev_close(&sc->sc_hdev);
    393  1.75  augustss 		return (0);
    394   1.9  augustss 	}
    395  1.37  augustss }
    396  1.37  augustss 
    397  1.37  augustss int
    398  1.60  augustss ukbd_activate(device_ptr_t self, enum devact act)
    399  1.37  augustss {
    400  1.40  augustss 	struct ukbd_softc *sc = (struct ukbd_softc *)self;
    401  1.44  augustss 	int rv = 0;
    402  1.40  augustss 
    403  1.40  augustss 	switch (act) {
    404  1.40  augustss 	case DVACT_ACTIVATE:
    405  1.40  augustss 		return (EOPNOTSUPP);
    406  1.40  augustss 
    407  1.40  augustss 	case DVACT_DEACTIVATE:
    408  1.47  augustss 		if (sc->sc_wskbddev != NULL)
    409  1.44  augustss 			rv = config_deactivate(sc->sc_wskbddev);
    410  1.40  augustss 		sc->sc_dying = 1;
    411  1.40  augustss 		break;
    412  1.40  augustss 	}
    413  1.44  augustss 	return (rv);
    414  1.37  augustss }
    415  1.37  augustss 
    416  1.75  augustss int
    417  1.75  augustss ukbd_detach(struct device *self, int flags)
    418  1.37  augustss {
    419  1.75  augustss 	struct ukbd_softc *sc = (struct ukbd_softc *)self;
    420  1.37  augustss 	int rv = 0;
    421  1.37  augustss 
    422  1.37  augustss 	DPRINTF(("ukbd_detach: sc=%p flags=%d\n", sc, flags));
    423  1.46  augustss 
    424  1.37  augustss 	if (sc->sc_console_keyboard) {
    425  1.50  augustss #if 0
    426  1.37  augustss 		/*
    427  1.37  augustss 		 * XXX Should probably disconnect our consops,
    428  1.37  augustss 		 * XXX and either notify some other keyboard that
    429  1.37  augustss 		 * XXX it can now be the console, or if there aren't
    430  1.37  augustss 		 * XXX any more USB keyboards, set ukbd_is_console
    431  1.37  augustss 		 * XXX back to 1 so that the next USB keyboard attached
    432  1.37  augustss 		 * XXX to the system will get it.
    433  1.37  augustss 		 */
    434  1.37  augustss 		panic("ukbd_detach: console keyboard");
    435  1.50  augustss #else
    436  1.51  augustss 		/*
    437  1.51  augustss 		 * Disconnect our consops and set ukbd_is_console
    438  1.51  augustss 		 * back to 1 so that the next USB keyboard attached
    439  1.51  augustss 		 * to the system will get it.
    440  1.51  augustss 		 * XXX Should notify some other keyboard that it can be
    441  1.51  augustss 		 * XXX console, if there are any other keyboards.
    442  1.51  augustss 		 */
    443  1.75  augustss 		printf("%s: was console keyboard\n",
    444  1.75  augustss 		       USBDEVNAME(sc->sc_hdev.sc_dev));
    445  1.50  augustss 		wskbd_cndetach();
    446  1.50  augustss 		ukbd_is_console = 1;
    447  1.50  augustss #endif
    448  1.37  augustss 	}
    449  1.45  augustss 	/* No need to do reference counting of ukbd, wskbd has all the goo. */
    450  1.47  augustss 	if (sc->sc_wskbddev != NULL)
    451  1.37  augustss 		rv = config_detach(sc->sc_wskbddev, flags);
    452  1.68  augustss 
    453  1.68  augustss 	/* The console keyboard does not get a disable call, so check pipe. */
    454  1.75  augustss 	if (sc->sc_hdev.sc_state & UHIDEV_OPEN)
    455  1.75  augustss 		uhidev_close(&sc->sc_hdev);
    456  1.55  augustss 
    457  1.37  augustss 	return (rv);
    458   1.1  augustss }
    459   1.1  augustss 
    460   1.1  augustss void
    461  1.94  christos ukbd_intr(struct uhidev *addr, void *ibuf, u_int len)
    462   1.1  augustss {
    463  1.75  augustss 	struct ukbd_softc *sc = (struct ukbd_softc *)addr;
    464   1.1  augustss 	struct ukbd_data *ud = &sc->sc_ndata;
    465  1.75  augustss 	int i;
    466  1.76  augustss 
    467  1.76  augustss #ifdef UKBD_DEBUG
    468  1.76  augustss 	if (ukbddebug > 5) {
    469  1.76  augustss 		printf("ukbd_intr: data");
    470  1.76  augustss 		for (i = 0; i < len; i++)
    471  1.78  augustss 			printf(" 0x%02x", ((u_char *)ibuf)[i]);
    472  1.76  augustss 		printf("\n");
    473  1.76  augustss 	}
    474  1.76  augustss #endif
    475  1.76  augustss 
    476  1.75  augustss 	ud->modifiers = 0;
    477  1.75  augustss 	for (i = 0; i < sc->sc_nmod; i++)
    478  1.75  augustss 		if (hid_get_data(ibuf, &sc->sc_modloc[i]))
    479  1.80  augustss 			ud->modifiers |= sc->sc_mods[i].mask;
    480  1.75  augustss 	memcpy(ud->keycode, (char *)ibuf + sc->sc_keycodeloc.pos / 8,
    481  1.75  augustss 	       sc->sc_nkeycode);
    482   1.1  augustss 
    483  1.69  augustss 	if (sc->sc_debounce && !sc->sc_polling) {
    484  1.62  augustss 		/*
    485  1.62  augustss 		 * Some keyboards have a peculiar quirk.  They sometimes
    486  1.62  augustss 		 * generate a key up followed by a key down for the same
    487  1.62  augustss 		 * key after about 10 ms.
    488  1.62  augustss 		 * We avoid this bug by holding off decoding for 20 ms.
    489  1.62  augustss 		 */
    490  1.62  augustss 		sc->sc_data = *ud;
    491  1.70  augustss 		usb_callout(sc->sc_delay, hz / 50, ukbd_delayed_decode, sc);
    492  1.74     lukem #ifdef DDB
    493  1.69  augustss 	} else if (sc->sc_console_keyboard && !sc->sc_polling) {
    494  1.69  augustss 		/*
    495  1.69  augustss 		 * For the console keyboard we can't deliver CTL-ALT-ESC
    496  1.69  augustss 		 * from the interrupt routine.  Doing so would start
    497  1.69  augustss 		 * polling from inside the interrupt routine and that
    498  1.69  augustss 		 * loses bigtime.
    499  1.69  augustss 		 */
    500  1.69  augustss 		sc->sc_data = *ud;
    501  1.70  augustss 		usb_callout(sc->sc_delay, 1, ukbd_delayed_decode, sc);
    502  1.69  augustss #endif
    503  1.62  augustss 	} else {
    504  1.62  augustss 		ukbd_decode(sc, ud);
    505  1.62  augustss 	}
    506  1.62  augustss }
    507  1.62  augustss 
    508  1.62  augustss void
    509  1.62  augustss ukbd_delayed_decode(void *addr)
    510  1.62  augustss {
    511  1.62  augustss 	struct ukbd_softc *sc = addr;
    512  1.62  augustss 
    513  1.62  augustss 	ukbd_decode(sc, &sc->sc_data);
    514  1.62  augustss }
    515  1.62  augustss 
    516  1.62  augustss void
    517  1.62  augustss ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud)
    518  1.62  augustss {
    519  1.62  augustss 	int mod, omod;
    520  1.62  augustss 	u_int16_t ibuf[MAXKEYS];	/* chars events */
    521  1.62  augustss 	int s;
    522  1.62  augustss 	int nkeys, i, j;
    523  1.62  augustss 	int key;
    524  1.62  augustss #define ADDKEY(c) ibuf[nkeys++] = (c)
    525  1.62  augustss 
    526  1.62  augustss #ifdef UKBD_DEBUG
    527  1.82  augustss 	/*
    528  1.62  augustss 	 * Keep a trace of the last events.  Using printf changes the
    529  1.62  augustss 	 * timing, so this can be useful sometimes.
    530  1.62  augustss 	 */
    531  1.62  augustss 	if (ukbdtrace) {
    532  1.62  augustss 		struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
    533  1.91   thorpej 		p->unit = device_unit(&sc->sc_hdev.sc_dev);
    534  1.62  augustss 		microtime(&p->tv);
    535  1.62  augustss 		p->ud = *ud;
    536  1.62  augustss 		if (++ukbdtraceindex >= UKBDTRACESIZE)
    537  1.62  augustss 			ukbdtraceindex = 0;
    538  1.62  augustss 	}
    539  1.62  augustss 	if (ukbddebug > 5) {
    540  1.62  augustss 		struct timeval tv;
    541  1.62  augustss 		microtime(&tv);
    542  1.62  augustss 		DPRINTF((" at %lu.%06lu  mod=0x%02x key0=0x%02x key1=0x%02x "
    543  1.62  augustss 			 "key2=0x%02x key3=0x%02x\n",
    544  1.62  augustss 			 tv.tv_sec, tv.tv_usec,
    545  1.62  augustss 			 ud->modifiers, ud->keycode[0], ud->keycode[1],
    546  1.62  augustss 			 ud->keycode[2], ud->keycode[3]));
    547  1.62  augustss 	}
    548  1.62  augustss #endif
    549   1.1  augustss 
    550  1.53  augustss 	if (ud->keycode[0] == KEY_ERROR) {
    551  1.53  augustss 		DPRINTF(("ukbd_intr: KEY_ERROR\n"));
    552   1.1  augustss 		return;		/* ignore  */
    553  1.53  augustss 	}
    554   1.1  augustss 	nkeys = 0;
    555   1.1  augustss 	mod = ud->modifiers;
    556   1.1  augustss 	omod = sc->sc_odata.modifiers;
    557   1.1  augustss 	if (mod != omod)
    558  1.75  augustss 		for (i = 0; i < sc->sc_nmod; i++)
    559  1.82  augustss 			if (( mod & sc->sc_mods[i].mask) !=
    560  1.75  augustss 			    (omod & sc->sc_mods[i].mask))
    561  1.82  augustss 				ADDKEY(sc->sc_mods[i].key |
    562  1.82  augustss 				       (mod & sc->sc_mods[i].mask
    563   1.1  augustss 					  ? PRESS : RELEASE));
    564  1.75  augustss 	if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) {
    565   1.1  augustss 		/* Check for released keys. */
    566  1.75  augustss 		for (i = 0; i < sc->sc_nkeycode; i++) {
    567   1.1  augustss 			key = sc->sc_odata.keycode[i];
    568   1.1  augustss 			if (key == 0)
    569   1.1  augustss 				continue;
    570  1.75  augustss 			for (j = 0; j < sc->sc_nkeycode; j++)
    571   1.1  augustss 				if (key == ud->keycode[j])
    572   1.1  augustss 					goto rfound;
    573  1.62  augustss 			DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key));
    574  1.23  augustss 			ADDKEY(key | RELEASE);
    575   1.1  augustss 		rfound:
    576   1.1  augustss 			;
    577   1.1  augustss 		}
    578  1.82  augustss 
    579   1.1  augustss 		/* Check for pressed keys. */
    580  1.75  augustss 		for (i = 0; i < sc->sc_nkeycode; i++) {
    581   1.1  augustss 			key = ud->keycode[i];
    582   1.1  augustss 			if (key == 0)
    583   1.1  augustss 				continue;
    584  1.75  augustss 			for (j = 0; j < sc->sc_nkeycode; j++)
    585   1.1  augustss 				if (key == sc->sc_odata.keycode[j])
    586   1.1  augustss 					goto pfound;
    587  1.23  augustss 			DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key));
    588  1.23  augustss 			ADDKEY(key | PRESS);
    589   1.1  augustss 		pfound:
    590   1.1  augustss 			;
    591   1.1  augustss 		}
    592   1.1  augustss 	}
    593   1.1  augustss 	sc->sc_odata = *ud;
    594   1.1  augustss 
    595  1.20  augustss 	if (nkeys == 0)
    596  1.20  augustss 		return;
    597  1.20  augustss 
    598   1.3  augustss 	if (sc->sc_polling) {
    599  1.23  augustss 		DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0]));
    600  1.23  augustss 		memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t));
    601  1.23  augustss 		sc->sc_npollchar = nkeys;
    602   1.3  augustss 		return;
    603   1.3  augustss 	}
    604  1.20  augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
    605  1.19  augustss 	if (sc->sc_rawkbd) {
    606  1.79  augustss 		u_char cbuf[MAXKEYS * 2];
    607  1.24  augustss 		int c;
    608  1.20  augustss 		int npress;
    609  1.20  augustss 
    610  1.23  augustss 		for (npress = i = j = 0; i < nkeys; i++) {
    611  1.23  augustss 			key = ibuf[i];
    612  1.23  augustss 			c = ukbd_trtab[key & CODEMASK];
    613  1.23  augustss 			if (c == NN)
    614  1.23  augustss 				continue;
    615  1.19  augustss 			if (c & 0x80)
    616  1.19  augustss 				cbuf[j++] = 0xe0;
    617  1.19  augustss 			cbuf[j] = c & 0x7f;
    618  1.23  augustss 			if (key & RELEASE)
    619  1.19  augustss 				cbuf[j] |= 0x80;
    620  1.87  augustss #if defined(UKBD_REPEAT)
    621  1.20  augustss 			else {
    622  1.23  augustss 				/* remember pressed keys for autorepeat */
    623  1.20  augustss 				if (c & 0x80)
    624  1.20  augustss 					sc->sc_rep[npress++] = 0xe0;
    625  1.20  augustss 				sc->sc_rep[npress++] = c & 0x7f;
    626  1.20  augustss 			}
    627  1.87  augustss #endif
    628  1.82  augustss 			DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n",
    629  1.27  augustss 				    c & 0x80 ? "0xe0 " : "",
    630  1.27  augustss 				    cbuf[j]));
    631  1.23  augustss 			j++;
    632  1.19  augustss 		}
    633  1.30  augustss 		s = spltty();
    634  1.19  augustss 		wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
    635  1.30  augustss 		splx(s);
    636  1.87  augustss #ifdef UKBD_REPEAT
    637  1.70  augustss 		usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
    638  1.20  augustss 		if (npress != 0) {
    639  1.20  augustss 			sc->sc_nrep = npress;
    640  1.70  augustss 			usb_callout(sc->sc_rawrepeat_ch,
    641  1.57   thorpej 			    hz * REP_DELAY1 / 1000, ukbd_rawrepeat, sc);
    642  1.20  augustss 		}
    643  1.87  augustss #endif
    644  1.19  augustss 		return;
    645  1.19  augustss 	}
    646  1.19  augustss #endif
    647  1.19  augustss 
    648  1.30  augustss 	s = spltty();
    649   1.2  augustss 	for (i = 0; i < nkeys; i++) {
    650  1.23  augustss 		key = ibuf[i];
    651  1.82  augustss 		wskbd_input(sc->sc_wskbddev,
    652  1.23  augustss 		    key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
    653  1.23  augustss 		    key&CODEMASK);
    654  1.20  augustss 	}
    655  1.30  augustss 	splx(s);
    656   1.1  augustss }
    657   1.1  augustss 
    658   1.2  augustss void
    659  1.60  augustss ukbd_set_leds(void *v, int leds)
    660   1.1  augustss {
    661   1.2  augustss 	struct ukbd_softc *sc = v;
    662   1.2  augustss 	u_int8_t res;
    663   1.1  augustss 
    664  1.71  augustss 	DPRINTF(("ukbd_set_leds: sc=%p leds=%d, sc_leds=%d\n",
    665  1.71  augustss 		 sc, leds, sc->sc_leds));
    666  1.40  augustss 
    667  1.40  augustss 	if (sc->sc_dying)
    668  1.40  augustss 		return;
    669   1.1  augustss 
    670  1.71  augustss 	if (sc->sc_leds == leds)
    671  1.71  augustss 		return;
    672   1.2  augustss 	sc->sc_leds = leds;
    673   1.2  augustss 	res = 0;
    674  1.75  augustss 	/* XXX not really right */
    675  1.75  augustss 	if ((leds & WSKBD_LED_SCROLL) && sc->sc_scroloc.size == 1)
    676  1.75  augustss 		res |= 1 << sc->sc_scroloc.pos;
    677  1.75  augustss 	if ((leds & WSKBD_LED_NUM) && sc->sc_numloc.size == 1)
    678  1.75  augustss 		res |= 1 << sc->sc_numloc.pos;
    679  1.75  augustss 	if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1)
    680  1.75  augustss 		res |= 1 << sc->sc_capsloc.pos;
    681  1.75  augustss 	uhidev_set_report_async(&sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1);
    682   1.1  augustss }
    683   1.1  augustss 
    684  1.87  augustss #if defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT)
    685  1.20  augustss void
    686  1.60  augustss ukbd_rawrepeat(void *v)
    687  1.20  augustss {
    688  1.20  augustss 	struct ukbd_softc *sc = v;
    689  1.30  augustss 	int s;
    690  1.20  augustss 
    691  1.30  augustss 	s = spltty();
    692  1.20  augustss 	wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
    693  1.30  augustss 	splx(s);
    694  1.70  augustss 	usb_callout(sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000,
    695  1.57   thorpej 	    ukbd_rawrepeat, sc);
    696  1.20  augustss }
    697  1.87  augustss #endif /* defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT) */
    698  1.20  augustss 
    699   1.1  augustss int
    700  1.95  christos ukbd_ioctl(void *v, u_long cmd, void *data, int flag,
    701  1.94  christos     struct lwp *l)
    702   1.1  augustss {
    703   1.2  augustss 	struct ukbd_softc *sc = v;
    704   1.1  augustss 
    705   1.2  augustss 	switch (cmd) {
    706   1.2  augustss 	case WSKBDIO_GTYPE:
    707  1.20  augustss 		*(int *)data = WSKBD_TYPE_USB;
    708  1.17  augustss 		return (0);
    709   1.2  augustss 	case WSKBDIO_SETLEDS:
    710   1.2  augustss 		ukbd_set_leds(v, *(int *)data);
    711  1.17  augustss 		return (0);
    712   1.2  augustss 	case WSKBDIO_GETLEDS:
    713   1.2  augustss 		*(int *)data = sc->sc_leds;
    714   1.2  augustss 		return (0);
    715  1.87  augustss #if defined(WSDISPLAY_COMPAT_RAWKBD)
    716   1.2  augustss 	case WSKBDIO_SETMODE:
    717  1.19  augustss 		DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data));
    718   1.2  augustss 		sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
    719  1.87  augustss #if defined(UKBD_REPEAT)
    720  1.70  augustss 		usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
    721  1.87  augustss #endif
    722   1.2  augustss 		return (0);
    723   1.2  augustss #endif
    724   1.2  augustss 	}
    725  1.81    atatat 	return (EPASSTHROUGH);
    726   1.1  augustss }
    727   1.7  augustss 
    728  1.71  augustss /*
    729  1.71  augustss  * This is a hack to work around some broken ports that don't call
    730  1.71  augustss  * cnpollc() before cngetc().
    731  1.71  augustss  */
    732  1.71  augustss static int pollenter, warned;
    733  1.71  augustss 
    734   1.7  augustss /* Console interface. */
    735   1.3  augustss void
    736  1.60  augustss ukbd_cngetc(void *v, u_int *type, int *data)
    737   1.3  augustss {
    738   1.3  augustss 	struct ukbd_softc *sc = v;
    739   1.4  augustss 	int c;
    740  1.71  augustss 	int broken;
    741  1.71  augustss 
    742  1.71  augustss 	if (pollenter == 0) {
    743  1.71  augustss 		if (!warned) {
    744  1.71  augustss 			printf("\n"
    745  1.71  augustss "This port is broken, it does not call cnpollc() before calling cngetc().\n"
    746  1.71  augustss "This should be fixed, but it will work anyway (for now).\n");
    747  1.71  augustss 			warned = 1;
    748  1.71  augustss 		}
    749  1.71  augustss 		broken = 1;
    750  1.71  augustss 		ukbd_cnpollc(v, 1);
    751  1.71  augustss 	} else
    752  1.71  augustss 		broken = 0;
    753   1.3  augustss 
    754  1.50  augustss 	DPRINTFN(0,("ukbd_cngetc: enter\n"));
    755   1.3  augustss 	sc->sc_polling = 1;
    756  1.23  augustss 	while(sc->sc_npollchar <= 0)
    757  1.75  augustss 		usbd_dopoll(sc->sc_hdev.sc_parent->sc_iface);
    758   1.3  augustss 	sc->sc_polling = 0;
    759  1.23  augustss 	c = sc->sc_pollchars[0];
    760  1.23  augustss 	sc->sc_npollchar--;
    761  1.82  augustss 	memcpy(sc->sc_pollchars, sc->sc_pollchars+1,
    762  1.23  augustss 	       sc->sc_npollchar * sizeof(u_int16_t));
    763   1.6  augustss 	*type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
    764  1.23  augustss 	*data = c & CODEMASK;
    765  1.50  augustss 	DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", c));
    766  1.71  augustss 	if (broken)
    767  1.71  augustss 		ukbd_cnpollc(v, 0);
    768   1.3  augustss }
    769   1.3  augustss 
    770   1.3  augustss void
    771  1.60  augustss ukbd_cnpollc(void *v, int on)
    772   1.3  augustss {
    773   1.6  augustss 	struct ukbd_softc *sc = v;
    774  1.52  augustss 	usbd_device_handle dev;
    775   1.6  augustss 
    776  1.19  augustss 	DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on));
    777   1.6  augustss 
    778  1.75  augustss 	usbd_interface2device_handle(sc->sc_hdev.sc_parent->sc_iface, &dev);
    779  1.84  augustss 	if (on) {
    780  1.84  augustss 		sc->sc_spl = splusb();
    781  1.84  augustss 		pollenter++;
    782  1.84  augustss 	} else {
    783  1.84  augustss 		splx(sc->sc_spl);
    784  1.84  augustss 		pollenter--;
    785  1.84  augustss 	}
    786  1.52  augustss 	usbd_set_polling(dev, on);
    787   1.3  augustss }
    788  1.18  augustss 
    789  1.18  augustss int
    790  1.60  augustss ukbd_cnattach(void)
    791  1.18  augustss {
    792  1.18  augustss 
    793  1.31   thorpej 	/*
    794  1.31   thorpej 	 * XXX USB requires too many parts of the kernel to be running
    795  1.31   thorpej 	 * XXX in order to work, so we can't do much for the console
    796  1.31   thorpej 	 * XXX keyboard until autconfiguration has run its course.
    797  1.31   thorpej 	 */
    798  1.31   thorpej 	ukbd_is_console = 1;
    799  1.18  augustss 	return (0);
    800  1.75  augustss }
    801  1.75  augustss 
    802  1.75  augustss const char *
    803  1.75  augustss ukbd_parse_desc(struct ukbd_softc *sc)
    804  1.75  augustss {
    805  1.75  augustss 	struct hid_data *d;
    806  1.75  augustss 	struct hid_item h;
    807  1.75  augustss 	int size;
    808  1.75  augustss 	void *desc;
    809  1.75  augustss 	int imod;
    810  1.75  augustss 
    811  1.75  augustss 	uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
    812  1.75  augustss 	imod = 0;
    813  1.75  augustss 	sc->sc_nkeycode = 0;
    814  1.75  augustss 	d = hid_start_parse(desc, size, hid_input);
    815  1.75  augustss 	while (hid_get_item(d, &h)) {
    816  1.75  augustss 		/*printf("ukbd: id=%d kind=%d usage=0x%x flags=0x%x pos=%d size=%d cnt=%d\n",
    817  1.75  augustss 		  h.report_ID, h.kind, h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count);*/
    818  1.75  augustss 		if (h.kind != hid_input || (h.flags & HIO_CONST) ||
    819  1.75  augustss 		    HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
    820  1.75  augustss 		    h.report_ID != sc->sc_hdev.sc_report_id)
    821  1.75  augustss 			continue;
    822  1.79  augustss 		DPRINTF(("ukbd: imod=%d usage=0x%x flags=0x%x pos=%d size=%d "
    823  1.79  augustss 			 "cnt=%d\n", imod,
    824  1.79  augustss 			 h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count));
    825  1.75  augustss 		if (h.flags & HIO_VARIABLE) {
    826  1.80  augustss 			if (h.loc.size != 1)
    827  1.80  augustss 				return ("bad modifier size");
    828  1.75  augustss 			/* Single item */
    829  1.75  augustss 			if (imod < MAXMOD) {
    830  1.75  augustss 				sc->sc_modloc[imod] = h.loc;
    831  1.75  augustss 				sc->sc_mods[imod].mask = 1 << imod;
    832  1.75  augustss 				sc->sc_mods[imod].key = HID_GET_USAGE(h.usage);
    833  1.75  augustss 				imod++;
    834  1.75  augustss 			} else
    835  1.75  augustss 				return ("too many modifier keys");
    836  1.75  augustss 		} else {
    837  1.75  augustss 			/* Array */
    838  1.75  augustss 			if (h.loc.size != 8)
    839  1.75  augustss 				return ("key code size != 8");
    840  1.75  augustss 			if (h.loc.count > MAXKEYCODE)
    841  1.75  augustss 				return ("too many key codes");
    842  1.75  augustss 			if (h.loc.pos % 8 != 0)
    843  1.75  augustss 				return ("key codes not on byte boundary");
    844  1.75  augustss 			if (sc->sc_nkeycode != 0)
    845  1.75  augustss 				return ("multiple key code arrays\n");
    846  1.75  augustss 			sc->sc_keycodeloc = h.loc;
    847  1.75  augustss 			sc->sc_nkeycode = h.loc.count;
    848  1.75  augustss 		}
    849  1.75  augustss 	}
    850  1.75  augustss 	sc->sc_nmod = imod;
    851  1.75  augustss 	hid_end_parse(d);
    852  1.75  augustss 
    853  1.75  augustss 	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
    854  1.75  augustss 		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL);
    855  1.75  augustss 	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
    856  1.75  augustss 		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL);
    857  1.75  augustss 	hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
    858  1.75  augustss 		   sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL);
    859  1.75  augustss 
    860  1.75  augustss 	return (NULL);
    861  1.18  augustss }
    862