Home | History | Annotate | Line # | Download | only in usb
ukbd.c revision 1.72
      1  1.72     lukem /*      $NetBSD: ukbd.c,v 1.72 2001/11/13 06:24:55 lukem 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.63  augustss  * HID spec: http://www.usb.org/developers/data/devclass/hid1_1.pdf
     42  1.17  augustss  */
     43  1.72     lukem 
     44  1.72     lukem #include <sys/cdefs.h>
     45  1.72     lukem __KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.72 2001/11/13 06:24:55 lukem 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.1  augustss #include <dev/usb/hid.h>
     68  1.31   thorpej #include <dev/usb/ukbdvar.h>
     69   1.1  augustss 
     70   1.2  augustss #include <dev/wscons/wsconsio.h>
     71   1.2  augustss #include <dev/wscons/wskbdvar.h>
     72   1.2  augustss #include <dev/wscons/wsksymdef.h>
     73   1.2  augustss #include <dev/wscons/wsksymvar.h>
     74   1.2  augustss 
     75   1.2  augustss #include "opt_wsdisplay_compat.h"
     76  1.69  augustss #include "opt_ddb.h"
     77  1.21  augustss 
     78  1.62  augustss #ifdef UKBD_DEBUG
     79  1.39  augustss #define DPRINTF(x)	if (ukbddebug) logprintf x
     80  1.39  augustss #define DPRINTFN(n,x)	if (ukbddebug>(n)) logprintf x
     81   1.1  augustss int	ukbddebug = 0;
     82   1.1  augustss #else
     83   1.1  augustss #define DPRINTF(x)
     84   1.1  augustss #define DPRINTFN(n,x)
     85   1.1  augustss #endif
     86   1.1  augustss 
     87   1.1  augustss #define NKEYCODE 6
     88   1.1  augustss 
     89   1.2  augustss #define NUM_LOCK 0x01
     90   1.2  augustss #define CAPS_LOCK 0x02
     91   1.2  augustss #define SCROLL_LOCK 0x04
     92   1.2  augustss 
     93   1.1  augustss struct ukbd_data {
     94   1.1  augustss 	u_int8_t	modifiers;
     95   1.1  augustss #define MOD_CONTROL_L	0x01
     96   1.1  augustss #define MOD_CONTROL_R	0x10
     97   1.1  augustss #define MOD_SHIFT_L	0x02
     98   1.1  augustss #define MOD_SHIFT_R	0x20
     99   1.1  augustss #define MOD_ALT_L	0x04
    100   1.1  augustss #define MOD_ALT_R	0x40
    101   1.1  augustss #define MOD_WIN_L	0x08
    102   1.1  augustss #define MOD_WIN_R	0x80
    103   1.1  augustss 	u_int8_t	reserved;
    104   1.1  augustss 	u_int8_t	keycode[NKEYCODE];
    105   1.1  augustss };
    106   1.1  augustss 
    107  1.23  augustss #define PRESS    0x000
    108  1.23  augustss #define RELEASE  0x100
    109  1.23  augustss #define CODEMASK 0x0ff
    110   1.1  augustss 
    111  1.23  augustss /* Translate USB bitmap to USB keycode. */
    112  1.27  augustss #define NMOD 8
    113  1.65  jdolecek Static const struct {
    114   1.1  augustss 	int mask, key;
    115   1.1  augustss } ukbd_mods[NMOD] = {
    116  1.23  augustss 	{ MOD_CONTROL_L, 224 },
    117  1.23  augustss 	{ MOD_CONTROL_R, 228 },
    118  1.23  augustss 	{ MOD_SHIFT_L,   225 },
    119  1.23  augustss 	{ MOD_SHIFT_R,   229 },
    120  1.23  augustss 	{ MOD_ALT_L,     226 },
    121  1.23  augustss 	{ MOD_ALT_R,     230 },
    122  1.27  augustss 	{ MOD_WIN_L,     227 },
    123  1.27  augustss 	{ MOD_WIN_R,     231 },
    124   1.1  augustss };
    125   1.1  augustss 
    126  1.23  augustss #if defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD)
    127   1.5  augustss #define NN 0			/* no translation */
    128  1.19  augustss /*
    129  1.23  augustss  * Translate USB keycodes to US keyboard XT scancodes.
    130  1.19  augustss  * Scancodes >= 128 represent EXTENDED keycodes.
    131  1.19  augustss  */
    132  1.65  jdolecek Static const u_int8_t ukbd_trtab[256] = {
    133  1.23  augustss 	  NN,  NN,  NN,  NN,  30,  48,  46,  32, /* 00 - 07 */
    134   1.5  augustss 	  18,  33,  34,  35,  23,  36,  37,  38, /* 08 - 0F */
    135   1.5  augustss 	  50,  49,  24,  25,  16,  19,  31,  20, /* 10 - 17 */
    136   1.5  augustss 	  22,  47,  17,  45,  21,  44,   2,   3, /* 18 - 1F */
    137   1.5  augustss 	   4,   5,   6,   7,   8,   9,  10,  11, /* 20 - 27 */
    138   1.5  augustss 	  28,   1,  14,  15,  57,  12,  13,  26, /* 28 - 2F */
    139  1.61  augustss 	  27,  43,  43,  39,  40,  41,  51,  52, /* 30 - 37 */
    140   1.5  augustss 	  53,  58,  59,  60,  61,  62,  63,  64, /* 38 - 3F */
    141   1.5  augustss 	  65,  66,  67,  68,  87,  88, 170,  70, /* 40 - 47 */
    142   1.5  augustss 	 127, 210, 199, 201, 211, 207, 209, 205, /* 48 - 4F */
    143   1.5  augustss 	 203, 208, 200,  69, 181,  55,  74,  78, /* 50 - 57 */
    144   1.5  augustss 	 156,  79,  80,  81,  75,  76,  77,  71, /* 58 - 5F */
    145  1.61  augustss           72,  73,  82,  83,  86, 221,  NN,  NN, /* 60 - 67 */
    146   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* 68 - 6F */
    147  1.27  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* 70 - 77 */
    148   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* 78 - 7F */
    149   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* 80 - 87 */
    150   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* 88 - 8F */
    151   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* 90 - 97 */
    152   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* 98 - 9F */
    153   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* A0 - A7 */
    154   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* A8 - AF */
    155   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* B0 - B7 */
    156   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* B8 - BF */
    157   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* C0 - C7 */
    158   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* C8 - CF */
    159   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* D0 - D7 */
    160   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* D8 - DF */
    161  1.26  augustss           29,  42,  56, 219,  157, 54,  184,220, /* E0 - E7 */
    162  1.26  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* E8 - EF */
    163   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* F0 - F7 */
    164   1.5  augustss           NN,  NN,  NN,  NN,  NN,  NN,  NN,  NN, /* F8 - FF */
    165   1.1  augustss };
    166  1.23  augustss #endif /* defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) */
    167   1.1  augustss 
    168   1.1  augustss #define KEY_ERROR 0x01
    169   1.1  augustss 
    170  1.20  augustss #define MAXKEYS (NMOD+2*NKEYCODE)
    171  1.20  augustss 
    172   1.1  augustss struct ukbd_softc {
    173  1.43  augustss 	USBBASEDEVICE	sc_dev;		/* base device */
    174  1.55  augustss 	usbd_device_handle sc_udev;
    175   1.1  augustss 	usbd_interface_handle sc_iface;	/* interface */
    176   1.1  augustss 	usbd_pipe_handle sc_intrpipe;	/* interrupt pipe */
    177   1.1  augustss 	int sc_ep_addr;
    178   1.1  augustss 
    179   1.1  augustss 	struct ukbd_data sc_ndata;
    180   1.1  augustss 	struct ukbd_data sc_odata;
    181   1.1  augustss 
    182   1.9  augustss 	char sc_enabled;
    183   1.1  augustss 
    184  1.29   thorpej 	int sc_console_keyboard;	/* we are the console keyboard */
    185  1.29   thorpej 
    186  1.62  augustss 	char sc_debounce;		/* for quirk handling */
    187  1.70  augustss 	usb_callout_t sc_delay;		/* for quirk handling */
    188  1.62  augustss 	struct ukbd_data sc_data;	/* for quirk handling */
    189  1.62  augustss 
    190   1.2  augustss 	int sc_leds;
    191  1.16  augustss #if defined(__NetBSD__)
    192  1.70  augustss 	usb_callout_t sc_rawrepeat_ch;
    193  1.57   thorpej 
    194   1.2  augustss 	struct device *sc_wskbddev;
    195  1.23  augustss #if defined(WSDISPLAY_COMPAT_RAWKBD)
    196  1.20  augustss #define REP_DELAY1 400
    197  1.20  augustss #define REP_DELAYN 100
    198   1.2  augustss 	int sc_rawkbd;
    199  1.20  augustss 	int sc_nrep;
    200  1.20  augustss 	char sc_rep[MAXKEYS];
    201  1.23  augustss #endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
    202   1.3  augustss 
    203   1.3  augustss 	int sc_polling;
    204  1.23  augustss 	int sc_npollchar;
    205  1.23  augustss 	u_int16_t sc_pollchars[MAXKEYS];
    206  1.23  augustss #endif /* defined(__NetBSD__) */
    207  1.40  augustss 
    208  1.40  augustss 	u_char sc_dying;
    209   1.1  augustss };
    210   1.1  augustss 
    211  1.62  augustss #ifdef UKBD_DEBUG
    212  1.62  augustss #define UKBDTRACESIZE 64
    213  1.62  augustss struct ukbdtraceinfo {
    214  1.62  augustss 	int unit;
    215  1.62  augustss 	struct timeval tv;
    216  1.62  augustss 	struct ukbd_data ud;
    217  1.62  augustss };
    218  1.62  augustss struct ukbdtraceinfo ukbdtracedata[UKBDTRACESIZE];
    219  1.62  augustss int ukbdtraceindex = 0;
    220  1.62  augustss int ukbdtrace = 0;
    221  1.62  augustss void ukbdtracedump(void);
    222  1.62  augustss void
    223  1.62  augustss ukbdtracedump(void)
    224  1.62  augustss {
    225  1.62  augustss 	int i;
    226  1.62  augustss 	for (i = 0; i < UKBDTRACESIZE; i++) {
    227  1.62  augustss 		struct ukbdtraceinfo *p =
    228  1.62  augustss 		    &ukbdtracedata[(i+ukbdtraceindex)%UKBDTRACESIZE];
    229  1.62  augustss 		printf("%lu.%06lu: mod=0x%02x key0=0x%02x key1=0x%02x "
    230  1.62  augustss 		       "key2=0x%02x key3=0x%02x\n",
    231  1.62  augustss 		       p->tv.tv_sec, p->tv.tv_usec,
    232  1.62  augustss 		       p->ud.modifiers, p->ud.keycode[0], p->ud.keycode[1],
    233  1.62  augustss 		       p->ud.keycode[2], p->ud.keycode[3]);
    234  1.62  augustss 	}
    235  1.62  augustss }
    236  1.62  augustss #endif
    237  1.62  augustss 
    238   1.1  augustss #define	UKBDUNIT(dev)	(minor(dev))
    239   1.1  augustss #define	UKBD_CHUNK	128	/* chunk size for read */
    240   1.1  augustss #define	UKBD_BSIZE	1020	/* buffer size */
    241   1.1  augustss 
    242  1.58  augustss Static int	ukbd_is_console;
    243  1.31   thorpej 
    244  1.60  augustss Static void	ukbd_cngetc(void *, u_int *, int *);
    245  1.60  augustss Static void	ukbd_cnpollc(void *, int);
    246   1.3  augustss 
    247  1.16  augustss #if defined(__NetBSD__)
    248   1.8  drochner const struct wskbd_consops ukbd_consops = {
    249   1.8  drochner 	ukbd_cngetc,
    250   1.8  drochner 	ukbd_cnpollc,
    251   1.8  drochner };
    252  1.16  augustss #endif
    253   1.8  drochner 
    254  1.60  augustss Static void	ukbd_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
    255  1.62  augustss Static void	ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud);
    256  1.62  augustss Static void	ukbd_delayed_decode(void *addr);
    257   1.2  augustss 
    258  1.60  augustss Static int	ukbd_enable(void *, int);
    259  1.60  augustss Static void	ukbd_set_leds(void *, int);
    260  1.23  augustss 
    261  1.16  augustss #if defined(__NetBSD__)
    262  1.60  augustss Static int	ukbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
    263  1.48    mjacob #ifdef WSDISPLAY_COMPAT_RAWKBD
    264  1.60  augustss Static void	ukbd_rawrepeat(void *v);
    265  1.48    mjacob #endif
    266   1.1  augustss 
    267   1.8  drochner const struct wskbd_accessops ukbd_accessops = {
    268   1.8  drochner 	ukbd_enable,
    269   1.8  drochner 	ukbd_set_leds,
    270   1.8  drochner 	ukbd_ioctl,
    271   1.8  drochner };
    272   1.8  drochner 
    273  1.23  augustss extern const struct wscons_keydesc ukbd_keydesctab[];
    274  1.23  augustss 
    275   1.8  drochner const struct wskbd_mapdata ukbd_keymapdata = {
    276  1.23  augustss 	ukbd_keydesctab,
    277  1.66  augustss #ifdef UKBD_LAYOUT
    278  1.66  augustss 	UKBD_LAYOUT,
    279  1.66  augustss #else
    280   1.8  drochner 	KB_US,
    281  1.66  augustss #endif
    282   1.8  drochner };
    283  1.16  augustss #endif
    284   1.8  drochner 
    285  1.16  augustss USB_DECLARE_DRIVER(ukbd);
    286   1.1  augustss 
    287  1.16  augustss USB_MATCH(ukbd)
    288   1.1  augustss {
    289  1.16  augustss 	USB_MATCH_START(ukbd, uaa);
    290   1.1  augustss 	usb_interface_descriptor_t *id;
    291   1.1  augustss 
    292   1.1  augustss 	/* Check that this is a keyboard that speaks the boot protocol. */
    293  1.47  augustss 	if (uaa->iface == NULL)
    294   1.1  augustss 		return (UMATCH_NONE);
    295   1.1  augustss 	id = usbd_get_interface_descriptor(uaa->iface);
    296  1.47  augustss 	if (id == NULL ||
    297  1.56  augustss 	    id->bInterfaceClass != UICLASS_HID ||
    298  1.56  augustss 	    id->bInterfaceSubClass != UISUBCLASS_BOOT ||
    299  1.56  augustss 	    id->bInterfaceProtocol != UIPROTO_BOOT_KEYBOARD)
    300   1.1  augustss 		return (UMATCH_NONE);
    301   1.1  augustss 	return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
    302   1.1  augustss }
    303   1.1  augustss 
    304  1.16  augustss USB_ATTACH(ukbd)
    305   1.1  augustss {
    306  1.16  augustss 	USB_ATTACH_START(ukbd, sc, uaa);
    307   1.1  augustss 	usbd_interface_handle iface = uaa->iface;
    308   1.1  augustss 	usb_interface_descriptor_t *id;
    309   1.1  augustss 	usb_endpoint_descriptor_t *ed;
    310  1.47  augustss 	usbd_status err;
    311  1.62  augustss 	u_int32_t qflags;
    312   1.1  augustss 	char devinfo[1024];
    313  1.16  augustss #if defined(__NetBSD__)
    314   1.2  augustss 	struct wskbddev_attach_args a;
    315  1.16  augustss #else
    316  1.16  augustss 	int i;
    317  1.16  augustss #endif
    318   1.1  augustss 
    319  1.55  augustss 	sc->sc_udev = uaa->device;
    320   1.1  augustss 	sc->sc_iface = iface;
    321   1.1  augustss 	id = usbd_get_interface_descriptor(iface);
    322   1.1  augustss 	usbd_devinfo(uaa->device, 0, devinfo);
    323  1.16  augustss 	USB_ATTACH_SETUP;
    324  1.16  augustss 	printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
    325  1.12  augustss 	       devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
    326  1.16  augustss 
    327   1.1  augustss 	ed = usbd_interface2endpoint_descriptor(iface, 0);
    328  1.47  augustss 	if (ed == NULL) {
    329   1.1  augustss 		printf("%s: could not read endpoint descriptor\n",
    330  1.16  augustss 		       USBDEVNAME(sc->sc_dev));
    331  1.16  augustss 		USB_ATTACH_ERROR_RETURN;
    332   1.1  augustss 	}
    333   1.1  augustss 
    334  1.15  augustss 	DPRINTFN(10,("ukbd_attach: bLength=%d bDescriptorType=%d "
    335  1.15  augustss 		     "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
    336  1.15  augustss 		     " bInterval=%d\n",
    337  1.15  augustss 		     ed->bLength, ed->bDescriptorType,
    338  1.15  augustss 		     ed->bEndpointAddress & UE_ADDR,
    339  1.42  augustss 		     UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
    340  1.15  augustss 		     ed->bmAttributes & UE_XFERTYPE,
    341  1.15  augustss 		     UGETW(ed->wMaxPacketSize), ed->bInterval));
    342   1.1  augustss 
    343  1.42  augustss 	if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
    344   1.1  augustss 	    (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
    345   1.1  augustss 		printf("%s: unexpected endpoint\n",
    346  1.16  augustss 		       USBDEVNAME(sc->sc_dev));
    347  1.16  augustss 		USB_ATTACH_ERROR_RETURN;
    348   1.1  augustss 	}
    349   1.1  augustss 
    350  1.62  augustss 	qflags = usbd_get_quirks(uaa->device)->uq_flags;
    351  1.62  augustss 	if ((qflags & UQ_NO_SET_PROTO) == 0) {
    352  1.47  augustss 		err = usbd_set_protocol(iface, 0);
    353   1.1  augustss 		DPRINTFN(5, ("ukbd_attach: protocol set\n"));
    354  1.47  augustss 		if (err) {
    355   1.1  augustss 			printf("%s: set protocol failed\n",
    356  1.47  augustss 			    USBDEVNAME(sc->sc_dev));
    357  1.16  augustss 			USB_ATTACH_ERROR_RETURN;
    358   1.1  augustss 		}
    359   1.1  augustss 	}
    360  1.62  augustss 	sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0;
    361  1.20  augustss 
    362   1.6  augustss 	/* Ignore if SETIDLE fails since it is not crucial. */
    363  1.62  augustss 	(void)usbd_set_idle(iface, 0, 0);
    364   1.1  augustss 
    365   1.1  augustss 	sc->sc_ep_addr = ed->bEndpointAddress;
    366   1.2  augustss 
    367  1.29   thorpej 	/*
    368  1.29   thorpej 	 * Remember if we're the console keyboard.
    369  1.29   thorpej 	 *
    370  1.31   thorpej 	 * XXX This always picks the first keyboard on the
    371  1.31   thorpej 	 * first USB bus, but what else can we really do?
    372  1.29   thorpej 	 */
    373  1.31   thorpej 	if ((sc->sc_console_keyboard = ukbd_is_console) != 0) {
    374  1.29   thorpej 		/* Don't let any other keyboard have it. */
    375  1.31   thorpej 		ukbd_is_console = 0;
    376  1.29   thorpej 	}
    377  1.29   thorpej 
    378  1.31   thorpej 	if (sc->sc_console_keyboard) {
    379  1.32  augustss 		DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
    380  1.31   thorpej 		wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
    381  1.34  wrstuden 		ukbd_enable(sc, 1);
    382  1.31   thorpej 	}
    383  1.29   thorpej 
    384  1.29   thorpej 	a.console = sc->sc_console_keyboard;
    385   1.8  drochner 
    386   1.8  drochner 	a.keymap = &ukbd_keymapdata;
    387   1.8  drochner 
    388   1.8  drochner 	a.accessops = &ukbd_accessops;
    389   1.2  augustss 	a.accesscookie = sc;
    390   1.8  drochner 
    391  1.70  augustss 	usb_callout_init(sc->sc_rawrepeat_ch);
    392  1.57   thorpej 
    393  1.70  augustss 	usb_callout_init(sc->sc_delay);
    394  1.62  augustss 
    395  1.19  augustss 	/* Flash the leds; no real purpose, just shows we're alive. */
    396  1.19  augustss 	ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS);
    397  1.23  augustss 	usbd_delay_ms(uaa->device, 400);
    398  1.19  augustss 	ukbd_set_leds(sc, 0);
    399  1.19  augustss 
    400  1.55  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
    401  1.55  augustss 			   USBDEV(sc->sc_dev));
    402  1.64  augustss 
    403  1.64  augustss 	sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
    404  1.55  augustss 
    405  1.16  augustss 	USB_ATTACH_SUCCESS_RETURN;
    406   1.1  augustss }
    407   1.1  augustss 
    408   1.8  drochner int
    409  1.60  augustss ukbd_enable(void *v, int on)
    410   1.8  drochner {
    411   1.9  augustss 	struct ukbd_softc *sc = v;
    412  1.47  augustss 	usbd_status err;
    413   1.9  augustss 
    414  1.40  augustss 	if (on && sc->sc_dying)
    415  1.40  augustss 		return (EIO);
    416  1.40  augustss 
    417  1.38  augustss 	/* Should only be called to change state */
    418  1.38  augustss 	if (sc->sc_enabled == on) {
    419  1.38  augustss #ifdef DIAGNOSTIC
    420  1.38  augustss 		printf("ukbd_enable: %s: bad call on=%d\n",
    421  1.38  augustss 		       USBDEVNAME(sc->sc_dev), on);
    422  1.38  augustss #endif
    423  1.38  augustss 		return (EBUSY);
    424  1.38  augustss 	}
    425  1.38  augustss 
    426  1.33  augustss 	DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on));
    427   1.9  augustss 	if (on) {
    428   1.9  augustss 		/* Set up interrupt pipe. */
    429  1.47  augustss 		err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
    430  1.47  augustss 			  USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc,
    431  1.54  augustss 			  &sc->sc_ndata, sizeof(sc->sc_ndata), ukbd_intr,
    432  1.54  augustss 			  USBD_DEFAULT_INTERVAL);
    433  1.47  augustss 		if (err)
    434   1.9  augustss 			return (EIO);
    435   1.9  augustss 	} else {
    436   1.9  augustss 		/* Disable interrupts. */
    437   1.9  augustss 		usbd_abort_pipe(sc->sc_intrpipe);
    438   1.9  augustss 		usbd_close_pipe(sc->sc_intrpipe);
    439  1.68  augustss 		sc->sc_intrpipe = NULL;
    440   1.9  augustss 	}
    441  1.38  augustss 	sc->sc_enabled = on;
    442   1.9  augustss 
    443   1.8  drochner 	return (0);
    444  1.37  augustss }
    445  1.37  augustss 
    446  1.37  augustss int
    447  1.60  augustss ukbd_activate(device_ptr_t self, enum devact act)
    448  1.37  augustss {
    449  1.40  augustss 	struct ukbd_softc *sc = (struct ukbd_softc *)self;
    450  1.44  augustss 	int rv = 0;
    451  1.40  augustss 
    452  1.40  augustss 	switch (act) {
    453  1.40  augustss 	case DVACT_ACTIVATE:
    454  1.40  augustss 		return (EOPNOTSUPP);
    455  1.40  augustss 		break;
    456  1.40  augustss 
    457  1.40  augustss 	case DVACT_DEACTIVATE:
    458  1.47  augustss 		if (sc->sc_wskbddev != NULL)
    459  1.44  augustss 			rv = config_deactivate(sc->sc_wskbddev);
    460  1.40  augustss 		sc->sc_dying = 1;
    461  1.40  augustss 		break;
    462  1.40  augustss 	}
    463  1.44  augustss 	return (rv);
    464  1.37  augustss }
    465  1.37  augustss 
    466  1.46  augustss USB_DETACH(ukbd)
    467  1.37  augustss {
    468  1.46  augustss 	USB_DETACH_START(ukbd, sc);
    469  1.37  augustss 	int rv = 0;
    470  1.37  augustss 
    471  1.37  augustss 	DPRINTF(("ukbd_detach: sc=%p flags=%d\n", sc, flags));
    472  1.46  augustss 
    473  1.37  augustss 	if (sc->sc_console_keyboard) {
    474  1.50  augustss #if 0
    475  1.37  augustss 		/*
    476  1.37  augustss 		 * XXX Should probably disconnect our consops,
    477  1.37  augustss 		 * XXX and either notify some other keyboard that
    478  1.37  augustss 		 * XXX it can now be the console, or if there aren't
    479  1.37  augustss 		 * XXX any more USB keyboards, set ukbd_is_console
    480  1.37  augustss 		 * XXX back to 1 so that the next USB keyboard attached
    481  1.37  augustss 		 * XXX to the system will get it.
    482  1.37  augustss 		 */
    483  1.37  augustss 		panic("ukbd_detach: console keyboard");
    484  1.50  augustss #else
    485  1.51  augustss 		/*
    486  1.51  augustss 		 * Disconnect our consops and set ukbd_is_console
    487  1.51  augustss 		 * back to 1 so that the next USB keyboard attached
    488  1.51  augustss 		 * to the system will get it.
    489  1.51  augustss 		 * XXX Should notify some other keyboard that it can be
    490  1.51  augustss 		 * XXX console, if there are any other keyboards.
    491  1.51  augustss 		 */
    492  1.51  augustss 		printf("%s: was console keyboard\n", USBDEVNAME(sc->sc_dev));
    493  1.50  augustss 		wskbd_cndetach();
    494  1.50  augustss 		ukbd_is_console = 1;
    495  1.50  augustss #endif
    496  1.37  augustss 	}
    497  1.45  augustss 	/* No need to do reference counting of ukbd, wskbd has all the goo. */
    498  1.47  augustss 	if (sc->sc_wskbddev != NULL)
    499  1.37  augustss 		rv = config_detach(sc->sc_wskbddev, flags);
    500  1.68  augustss 
    501  1.68  augustss 	/* The console keyboard does not get a disable call, so check pipe. */
    502  1.68  augustss 	if (sc->sc_intrpipe != NULL) {
    503  1.68  augustss 		usbd_abort_pipe(sc->sc_intrpipe);
    504  1.68  augustss 		usbd_close_pipe(sc->sc_intrpipe);
    505  1.68  augustss 		sc->sc_intrpipe = NULL;
    506  1.68  augustss 	}
    507  1.55  augustss 
    508  1.55  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    509  1.55  augustss 			   USBDEV(sc->sc_dev));
    510  1.55  augustss 
    511  1.37  augustss 	return (rv);
    512   1.1  augustss }
    513   1.1  augustss 
    514   1.1  augustss void
    515  1.47  augustss ukbd_intr(xfer, addr, status)
    516  1.47  augustss 	usbd_xfer_handle xfer;
    517   1.1  augustss 	usbd_private_handle addr;
    518   1.1  augustss 	usbd_status status;
    519   1.1  augustss {
    520   1.1  augustss 	struct ukbd_softc *sc = addr;
    521   1.1  augustss 	struct ukbd_data *ud = &sc->sc_ndata;
    522   1.1  augustss 
    523   1.1  augustss 	DPRINTFN(5, ("ukbd_intr: status=%d\n", status));
    524   1.1  augustss 	if (status == USBD_CANCELLED)
    525   1.1  augustss 		return;
    526   1.1  augustss 
    527  1.49  augustss 	if (status) {
    528   1.1  augustss 		DPRINTF(("ukbd_intr: status=%d\n", status));
    529  1.67  augustss 		if (status == USBD_STALLED)
    530  1.67  augustss 			usbd_clear_endpoint_stall_async(sc->sc_intrpipe);
    531   1.1  augustss 		return;
    532   1.1  augustss 	}
    533   1.1  augustss 
    534  1.69  augustss 	if (sc->sc_debounce && !sc->sc_polling) {
    535  1.62  augustss 		/*
    536  1.62  augustss 		 * Some keyboards have a peculiar quirk.  They sometimes
    537  1.62  augustss 		 * generate a key up followed by a key down for the same
    538  1.62  augustss 		 * key after about 10 ms.
    539  1.62  augustss 		 * We avoid this bug by holding off decoding for 20 ms.
    540  1.62  augustss 		 */
    541  1.62  augustss 		sc->sc_data = *ud;
    542  1.70  augustss 		usb_callout(sc->sc_delay, hz / 50, ukbd_delayed_decode, sc);
    543  1.69  augustss #if DDB
    544  1.69  augustss 	} else if (sc->sc_console_keyboard && !sc->sc_polling) {
    545  1.69  augustss 		/*
    546  1.69  augustss 		 * For the console keyboard we can't deliver CTL-ALT-ESC
    547  1.69  augustss 		 * from the interrupt routine.  Doing so would start
    548  1.69  augustss 		 * polling from inside the interrupt routine and that
    549  1.69  augustss 		 * loses bigtime.
    550  1.69  augustss 		 */
    551  1.69  augustss 		sc->sc_data = *ud;
    552  1.70  augustss 		usb_callout(sc->sc_delay, 1, ukbd_delayed_decode, sc);
    553  1.69  augustss #endif
    554  1.62  augustss 	} else {
    555  1.62  augustss 		ukbd_decode(sc, ud);
    556  1.62  augustss 	}
    557  1.62  augustss }
    558  1.62  augustss 
    559  1.62  augustss void
    560  1.62  augustss ukbd_delayed_decode(void *addr)
    561  1.62  augustss {
    562  1.62  augustss 	struct ukbd_softc *sc = addr;
    563  1.62  augustss 
    564  1.62  augustss 	ukbd_decode(sc, &sc->sc_data);
    565  1.62  augustss }
    566  1.62  augustss 
    567  1.62  augustss void
    568  1.62  augustss ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud)
    569  1.62  augustss {
    570  1.62  augustss 	int mod, omod;
    571  1.62  augustss 	u_int16_t ibuf[MAXKEYS];	/* chars events */
    572  1.62  augustss 	int s;
    573  1.62  augustss 	int nkeys, i, j;
    574  1.62  augustss 	int key;
    575  1.62  augustss #define ADDKEY(c) ibuf[nkeys++] = (c)
    576  1.62  augustss 
    577  1.62  augustss #ifdef UKBD_DEBUG
    578  1.62  augustss 	/*
    579  1.62  augustss 	 * Keep a trace of the last events.  Using printf changes the
    580  1.62  augustss 	 * timing, so this can be useful sometimes.
    581  1.62  augustss 	 */
    582  1.62  augustss 	if (ukbdtrace) {
    583  1.62  augustss 		struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
    584  1.62  augustss 		p->unit = sc->sc_dev.dv_unit;
    585  1.62  augustss 		microtime(&p->tv);
    586  1.62  augustss 		p->ud = *ud;
    587  1.62  augustss 		if (++ukbdtraceindex >= UKBDTRACESIZE)
    588  1.62  augustss 			ukbdtraceindex = 0;
    589  1.62  augustss 	}
    590  1.62  augustss 	if (ukbddebug > 5) {
    591  1.62  augustss 		struct timeval tv;
    592  1.62  augustss 		microtime(&tv);
    593  1.62  augustss 		DPRINTF((" at %lu.%06lu  mod=0x%02x key0=0x%02x key1=0x%02x "
    594  1.62  augustss 			 "key2=0x%02x key3=0x%02x\n",
    595  1.62  augustss 			 tv.tv_sec, tv.tv_usec,
    596  1.62  augustss 			 ud->modifiers, ud->keycode[0], ud->keycode[1],
    597  1.62  augustss 			 ud->keycode[2], ud->keycode[3]));
    598  1.62  augustss 	}
    599  1.62  augustss #endif
    600   1.1  augustss 
    601  1.53  augustss 	if (ud->keycode[0] == KEY_ERROR) {
    602  1.53  augustss 		DPRINTF(("ukbd_intr: KEY_ERROR\n"));
    603   1.1  augustss 		return;		/* ignore  */
    604  1.53  augustss 	}
    605   1.1  augustss 	nkeys = 0;
    606   1.1  augustss 	mod = ud->modifiers;
    607   1.1  augustss 	omod = sc->sc_odata.modifiers;
    608   1.1  augustss 	if (mod != omod)
    609   1.1  augustss 		for (i = 0; i < NMOD; i++)
    610   1.1  augustss 			if (( mod & ukbd_mods[i].mask) !=
    611   1.1  augustss 			    (omod & ukbd_mods[i].mask))
    612   1.1  augustss 				ADDKEY(ukbd_mods[i].key |
    613   1.1  augustss 				       (mod & ukbd_mods[i].mask
    614   1.1  augustss 					  ? PRESS : RELEASE));
    615   1.1  augustss 	if (memcmp(ud->keycode, sc->sc_odata.keycode, NKEYCODE) != 0) {
    616   1.1  augustss 		/* Check for released keys. */
    617   1.1  augustss 		for (i = 0; i < NKEYCODE; i++) {
    618   1.1  augustss 			key = sc->sc_odata.keycode[i];
    619   1.1  augustss 			if (key == 0)
    620   1.1  augustss 				continue;
    621   1.1  augustss 			for (j = 0; j < NKEYCODE; j++)
    622   1.1  augustss 				if (key == ud->keycode[j])
    623   1.1  augustss 					goto rfound;
    624  1.62  augustss 			DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key));
    625  1.23  augustss 			ADDKEY(key | RELEASE);
    626   1.1  augustss 		rfound:
    627   1.1  augustss 			;
    628   1.1  augustss 		}
    629   1.1  augustss 
    630   1.1  augustss 		/* Check for pressed keys. */
    631   1.1  augustss 		for (i = 0; i < NKEYCODE; i++) {
    632   1.1  augustss 			key = ud->keycode[i];
    633   1.1  augustss 			if (key == 0)
    634   1.1  augustss 				continue;
    635   1.1  augustss 			for (j = 0; j < NKEYCODE; j++)
    636   1.1  augustss 				if (key == sc->sc_odata.keycode[j])
    637   1.1  augustss 					goto pfound;
    638  1.23  augustss 			DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key));
    639  1.23  augustss 			ADDKEY(key | PRESS);
    640   1.1  augustss 		pfound:
    641   1.1  augustss 			;
    642   1.1  augustss 		}
    643   1.1  augustss 	}
    644   1.1  augustss 	sc->sc_odata = *ud;
    645   1.1  augustss 
    646  1.20  augustss 	if (nkeys == 0)
    647  1.20  augustss 		return;
    648  1.20  augustss 
    649   1.3  augustss 	if (sc->sc_polling) {
    650  1.23  augustss 		DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0]));
    651  1.23  augustss 		memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t));
    652  1.23  augustss 		sc->sc_npollchar = nkeys;
    653   1.3  augustss 		return;
    654   1.3  augustss 	}
    655  1.20  augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
    656  1.19  augustss 	if (sc->sc_rawkbd) {
    657  1.19  augustss 		char cbuf[MAXKEYS * 2];
    658  1.24  augustss 		int c;
    659  1.20  augustss 		int npress;
    660  1.20  augustss 
    661  1.23  augustss 		for (npress = i = j = 0; i < nkeys; i++) {
    662  1.23  augustss 			key = ibuf[i];
    663  1.23  augustss 			c = ukbd_trtab[key & CODEMASK];
    664  1.23  augustss 			if (c == NN)
    665  1.23  augustss 				continue;
    666  1.19  augustss 			if (c & 0x80)
    667  1.19  augustss 				cbuf[j++] = 0xe0;
    668  1.19  augustss 			cbuf[j] = c & 0x7f;
    669  1.23  augustss 			if (key & RELEASE)
    670  1.19  augustss 				cbuf[j] |= 0x80;
    671  1.20  augustss 			else {
    672  1.23  augustss 				/* remember pressed keys for autorepeat */
    673  1.20  augustss 				if (c & 0x80)
    674  1.20  augustss 					sc->sc_rep[npress++] = 0xe0;
    675  1.20  augustss 				sc->sc_rep[npress++] = c & 0x7f;
    676  1.20  augustss 			}
    677  1.27  augustss 			DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n",
    678  1.27  augustss 				    c & 0x80 ? "0xe0 " : "",
    679  1.27  augustss 				    cbuf[j]));
    680  1.23  augustss 			j++;
    681  1.19  augustss 		}
    682  1.30  augustss 		s = spltty();
    683  1.19  augustss 		wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
    684  1.30  augustss 		splx(s);
    685  1.70  augustss 		usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
    686  1.20  augustss 		if (npress != 0) {
    687  1.20  augustss 			sc->sc_nrep = npress;
    688  1.70  augustss 			usb_callout(sc->sc_rawrepeat_ch,
    689  1.57   thorpej 			    hz * REP_DELAY1 / 1000, ukbd_rawrepeat, sc);
    690  1.20  augustss 		}
    691  1.19  augustss 		return;
    692  1.19  augustss 	}
    693  1.19  augustss #endif
    694  1.19  augustss 
    695  1.30  augustss 	s = spltty();
    696   1.2  augustss 	for (i = 0; i < nkeys; i++) {
    697  1.23  augustss 		key = ibuf[i];
    698   1.2  augustss 		wskbd_input(sc->sc_wskbddev,
    699  1.23  augustss 		    key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
    700  1.23  augustss 		    key&CODEMASK);
    701  1.20  augustss 	}
    702  1.30  augustss 	splx(s);
    703   1.1  augustss }
    704   1.1  augustss 
    705   1.2  augustss void
    706  1.60  augustss ukbd_set_leds(void *v, int leds)
    707   1.1  augustss {
    708   1.2  augustss 	struct ukbd_softc *sc = v;
    709   1.2  augustss 	u_int8_t res;
    710   1.1  augustss 
    711  1.71  augustss 	DPRINTF(("ukbd_set_leds: sc=%p leds=%d, sc_leds=%d\n",
    712  1.71  augustss 		 sc, leds, sc->sc_leds));
    713  1.40  augustss 
    714  1.40  augustss 	if (sc->sc_dying)
    715  1.40  augustss 		return;
    716   1.1  augustss 
    717  1.71  augustss 	if (sc->sc_leds == leds)
    718  1.71  augustss 		return;
    719   1.2  augustss 	sc->sc_leds = leds;
    720   1.2  augustss 	res = 0;
    721   1.2  augustss 	if (leds & WSKBD_LED_SCROLL)
    722   1.2  augustss 		res |= SCROLL_LOCK;
    723   1.2  augustss 	if (leds & WSKBD_LED_NUM)
    724   1.2  augustss 		res |= NUM_LOCK;
    725   1.2  augustss 	if (leds & WSKBD_LED_CAPS)
    726   1.2  augustss 		res |= CAPS_LOCK;
    727  1.34  wrstuden 	res |= leds & 0xf8;
    728   1.4  augustss 	usbd_set_report_async(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1);
    729   1.1  augustss }
    730   1.1  augustss 
    731  1.20  augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
    732  1.20  augustss void
    733  1.60  augustss ukbd_rawrepeat(void *v)
    734  1.20  augustss {
    735  1.20  augustss 	struct ukbd_softc *sc = v;
    736  1.30  augustss 	int s;
    737  1.20  augustss 
    738  1.30  augustss 	s = spltty();
    739  1.20  augustss 	wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
    740  1.30  augustss 	splx(s);
    741  1.70  augustss 	usb_callout(sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000,
    742  1.57   thorpej 	    ukbd_rawrepeat, sc);
    743  1.20  augustss }
    744  1.20  augustss #endif
    745  1.20  augustss 
    746   1.1  augustss int
    747  1.60  augustss ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
    748   1.1  augustss {
    749   1.2  augustss 	struct ukbd_softc *sc = v;
    750   1.1  augustss 
    751   1.2  augustss 	switch (cmd) {
    752   1.2  augustss 	case WSKBDIO_GTYPE:
    753  1.20  augustss 		*(int *)data = WSKBD_TYPE_USB;
    754  1.17  augustss 		return (0);
    755   1.2  augustss 	case WSKBDIO_SETLEDS:
    756   1.2  augustss 		ukbd_set_leds(v, *(int *)data);
    757  1.17  augustss 		return (0);
    758   1.2  augustss 	case WSKBDIO_GETLEDS:
    759   1.2  augustss 		*(int *)data = sc->sc_leds;
    760   1.2  augustss 		return (0);
    761   1.2  augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
    762   1.2  augustss 	case WSKBDIO_SETMODE:
    763  1.19  augustss 		DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data));
    764   1.2  augustss 		sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
    765  1.70  augustss 		usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
    766   1.2  augustss 		return (0);
    767   1.2  augustss #endif
    768   1.2  augustss 	}
    769  1.17  augustss 	return (-1);
    770   1.1  augustss }
    771   1.7  augustss 
    772  1.71  augustss /*
    773  1.71  augustss  * This is a hack to work around some broken ports that don't call
    774  1.71  augustss  * cnpollc() before cngetc().
    775  1.71  augustss  */
    776  1.71  augustss static int pollenter, warned;
    777  1.71  augustss 
    778   1.7  augustss /* Console interface. */
    779   1.3  augustss void
    780  1.60  augustss ukbd_cngetc(void *v, u_int *type, int *data)
    781   1.3  augustss {
    782   1.3  augustss 	struct ukbd_softc *sc = v;
    783  1.35  augustss 	int s;
    784   1.4  augustss 	int c;
    785  1.71  augustss 	int broken;
    786  1.71  augustss 
    787  1.71  augustss 	if (pollenter == 0) {
    788  1.71  augustss 		if (!warned) {
    789  1.71  augustss 			printf("\n"
    790  1.71  augustss "This port is broken, it does not call cnpollc() before calling cngetc().\n"
    791  1.71  augustss "This should be fixed, but it will work anyway (for now).\n");
    792  1.71  augustss 			warned = 1;
    793  1.71  augustss 		}
    794  1.71  augustss 		broken = 1;
    795  1.71  augustss 		ukbd_cnpollc(v, 1);
    796  1.71  augustss 	} else
    797  1.71  augustss 		broken = 0;
    798   1.3  augustss 
    799  1.50  augustss 	DPRINTFN(0,("ukbd_cngetc: enter\n"));
    800  1.35  augustss 	s = splusb();
    801   1.3  augustss 	sc->sc_polling = 1;
    802  1.23  augustss 	while(sc->sc_npollchar <= 0)
    803   1.3  augustss 		usbd_dopoll(sc->sc_iface);
    804   1.3  augustss 	sc->sc_polling = 0;
    805  1.23  augustss 	c = sc->sc_pollchars[0];
    806  1.23  augustss 	sc->sc_npollchar--;
    807  1.23  augustss 	memcpy(sc->sc_pollchars, sc->sc_pollchars+1,
    808  1.23  augustss 	       sc->sc_npollchar * sizeof(u_int16_t));
    809   1.6  augustss 	*type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
    810  1.23  augustss 	*data = c & CODEMASK;
    811  1.35  augustss 	splx(s);
    812  1.50  augustss 	DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", c));
    813  1.71  augustss 	if (broken)
    814  1.71  augustss 		ukbd_cnpollc(v, 0);
    815   1.3  augustss }
    816   1.3  augustss 
    817   1.3  augustss void
    818  1.60  augustss ukbd_cnpollc(void *v, int on)
    819   1.3  augustss {
    820   1.6  augustss 	struct ukbd_softc *sc = v;
    821  1.52  augustss 	usbd_device_handle dev;
    822   1.6  augustss 
    823  1.19  augustss 	DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on));
    824   1.6  augustss 
    825  1.52  augustss 	(void)usbd_interface2device_handle(sc->sc_iface,&dev);
    826  1.71  augustss 	if (on) pollenter++; else pollenter--;
    827  1.52  augustss 	usbd_set_polling(dev, on);
    828   1.3  augustss }
    829  1.18  augustss 
    830  1.18  augustss int
    831  1.60  augustss ukbd_cnattach(void)
    832  1.18  augustss {
    833  1.18  augustss 
    834  1.31   thorpej 	/*
    835  1.31   thorpej 	 * XXX USB requires too many parts of the kernel to be running
    836  1.31   thorpej 	 * XXX in order to work, so we can't do much for the console
    837  1.31   thorpej 	 * XXX keyboard until autconfiguration has run its course.
    838  1.31   thorpej 	 */
    839  1.31   thorpej 	ukbd_is_console = 1;
    840  1.18  augustss 	return (0);
    841  1.18  augustss }
    842