Home | History | Annotate | Line # | Download | only in usb
ukbd.c revision 1.1
      1  1.1  augustss /*	$NetBSD: ukbd.c,v 1.1 1998/07/12 19:52:00 augustss 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.1  augustss  * Author: Lennart Augustsson <augustss (at) carlstedt.se>
      8  1.1  augustss  *         Carlstedt Research & Technology
      9  1.1  augustss  *
     10  1.1  augustss  * Redistribution and use in source and binary forms, with or without
     11  1.1  augustss  * modification, are permitted provided that the following conditions
     12  1.1  augustss  * are met:
     13  1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     14  1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     15  1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  augustss  *    documentation and/or other materials provided with the distribution.
     18  1.1  augustss  * 3. All advertising materials mentioning features or use of this software
     19  1.1  augustss  *    must display the following acknowledgement:
     20  1.1  augustss  *        This product includes software developed by the NetBSD
     21  1.1  augustss  *        Foundation, Inc. and its contributors.
     22  1.1  augustss  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.1  augustss  *    contributors may be used to endorse or promote products derived
     24  1.1  augustss  *    from this software without specific prior written permission.
     25  1.1  augustss  *
     26  1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     37  1.1  augustss  */
     38  1.1  augustss 
     39  1.1  augustss 
     40  1.1  augustss #include <sys/param.h>
     41  1.1  augustss #include <sys/systm.h>
     42  1.1  augustss #include <sys/kernel.h>
     43  1.1  augustss #include <sys/malloc.h>
     44  1.1  augustss #include <sys/device.h>
     45  1.1  augustss #include <sys/ioctl.h>
     46  1.1  augustss #include <sys/tty.h>
     47  1.1  augustss #include <sys/file.h>
     48  1.1  augustss #include <sys/select.h>
     49  1.1  augustss #include <sys/proc.h>
     50  1.1  augustss #include <sys/vnode.h>
     51  1.1  augustss #include <sys/device.h>
     52  1.1  augustss #include <sys/poll.h>
     53  1.1  augustss 
     54  1.1  augustss #include <dev/usb/usb.h>
     55  1.1  augustss 
     56  1.1  augustss #include <dev/usb/usbdi.h>
     57  1.1  augustss #include <dev/usb/usbdi_util.h>
     58  1.1  augustss #include <dev/usb/usbdevs.h>
     59  1.1  augustss #include <dev/usb/usb_quirks.h>
     60  1.1  augustss #include <dev/usb/hid.h>
     61  1.1  augustss 
     62  1.1  augustss #ifdef USB_DEBUG
     63  1.1  augustss #define DPRINTF(x)	if (ukbddebug) printf x
     64  1.1  augustss #define DPRINTFN(n,x)	if (ukbddebug>(n)) printf x
     65  1.1  augustss int	ukbddebug = 0;
     66  1.1  augustss #else
     67  1.1  augustss #define DPRINTF(x)
     68  1.1  augustss #define DPRINTFN(n,x)
     69  1.1  augustss #endif
     70  1.1  augustss 
     71  1.1  augustss #define UPROTO_BOOT_KEYBOARD 1
     72  1.1  augustss 
     73  1.1  augustss #define NKEYCODE 6
     74  1.1  augustss 
     75  1.1  augustss struct ukbd_data {
     76  1.1  augustss 	u_int8_t	modifiers;
     77  1.1  augustss #define MOD_CONTROL_L	0x01
     78  1.1  augustss #define MOD_CONTROL_R	0x10
     79  1.1  augustss #define MOD_SHIFT_L	0x02
     80  1.1  augustss #define MOD_SHIFT_R	0x20
     81  1.1  augustss #define MOD_ALT_L	0x04
     82  1.1  augustss #define MOD_ALT_R	0x40
     83  1.1  augustss #define MOD_WIN_L	0x08
     84  1.1  augustss #define MOD_WIN_R	0x80
     85  1.1  augustss 	u_int8_t	reserved;
     86  1.1  augustss 	u_int8_t	keycode[NKEYCODE];
     87  1.1  augustss };
     88  1.1  augustss 
     89  1.1  augustss #define PRESS 0
     90  1.1  augustss #define RELEASE 0x80
     91  1.1  augustss 
     92  1.1  augustss #define NMOD 6
     93  1.1  augustss static struct {
     94  1.1  augustss 	int mask, key;
     95  1.1  augustss } ukbd_mods[NMOD] = {
     96  1.1  augustss 	{ MOD_CONTROL_L, 29 },
     97  1.1  augustss 	{ MOD_CONTROL_R, 58 },
     98  1.1  augustss 	{ MOD_SHIFT_L,   42 },
     99  1.1  augustss 	{ MOD_SHIFT_R,   54 },
    100  1.1  augustss 	{ MOD_ALT_L,     56 },
    101  1.1  augustss 	{ MOD_ALT_R,     56 },
    102  1.1  augustss };
    103  1.1  augustss 
    104  1.1  augustss #define XX 0
    105  1.1  augustss /* Translate USB keycodes to US keyboard scancodes. */
    106  1.1  augustss /* XXX very incomplete */
    107  1.1  augustss static char ukbd_trtab[256] = {
    108  1.1  augustss 	   0,   0,   0,   0,  30,  48,  46,  32,
    109  1.1  augustss 	  18,  33,  34,  35,  23,  36,  37,  38,
    110  1.1  augustss 	  50,  49,  24,  25,  16,  19,  31,  20,
    111  1.1  augustss 	  22,  47,  17,  45,  21,  44,   2,   3,
    112  1.1  augustss 	   4,   5,   6,   7,   8,   9,  10,  11,
    113  1.1  augustss 	  28,   1,  14,  15,  57,  12,  13,  26,
    114  1.1  augustss 	  27,  43,  XX,  39,  40,  41,  51,  52,
    115  1.1  augustss 	  53,  58,  59,  60,  61,  62,  63,  64,
    116  1.1  augustss 	  65,  66,  67,  68,  87,  88,  XX,  70,
    117  1.1  augustss 	  XX,  XX,  XX,  XX,  XX,
    118  1.1  augustss };
    119  1.1  augustss 
    120  1.1  augustss #define KEY_ERROR 0x01
    121  1.1  augustss 
    122  1.1  augustss struct ukbd_softc {
    123  1.1  augustss 	struct device sc_dev;		/* base device */
    124  1.1  augustss 	usbd_interface_handle sc_iface;	/* interface */
    125  1.1  augustss 	usbd_pipe_handle sc_intrpipe;	/* interrupt pipe */
    126  1.1  augustss 	int sc_ep_addr;
    127  1.1  augustss 
    128  1.1  augustss 	struct ukbd_data sc_ndata;
    129  1.1  augustss 	struct ukbd_data sc_odata;
    130  1.1  augustss 
    131  1.1  augustss 	struct clist sc_q;
    132  1.1  augustss 	struct selinfo sc_rsel;
    133  1.1  augustss 	u_char sc_state;	/* keyboard driver state */
    134  1.1  augustss #define	UKBD_OPEN	0x01	/* device is open */
    135  1.1  augustss #define	UKBD_ASLP	0x02	/* waiting for keyboard data */
    136  1.1  augustss #define UKBD_NEEDCLEAR	0x04	/* needs clearing endpoint stall */
    137  1.1  augustss 
    138  1.1  augustss 	int sc_disconnected;		/* device is gone */
    139  1.1  augustss };
    140  1.1  augustss 
    141  1.1  augustss #define	UKBDUNIT(dev)	(minor(dev))
    142  1.1  augustss #define	UKBD_CHUNK	128	/* chunk size for read */
    143  1.1  augustss #define	UKBD_BSIZE	1020	/* buffer size */
    144  1.1  augustss 
    145  1.1  augustss int ukbd_match __P((struct device *, struct cfdata *, void *));
    146  1.1  augustss void ukbd_attach __P((struct device *, struct device *, void *));
    147  1.1  augustss 
    148  1.1  augustss int ukbdopen __P((dev_t, int, int, struct proc *));
    149  1.1  augustss int ukbdclose __P((dev_t, int, int, struct proc *p));
    150  1.1  augustss int ukbdread __P((dev_t, struct uio *uio, int));
    151  1.1  augustss int ukbdioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
    152  1.1  augustss int ukbdpoll __P((dev_t, int, struct proc *));
    153  1.1  augustss void ukbd_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
    154  1.1  augustss void ukbd_disco __P((void *));
    155  1.1  augustss 
    156  1.1  augustss extern struct cfdriver ukbd_cd;
    157  1.1  augustss 
    158  1.1  augustss struct cfattach ukbd_ca = {
    159  1.1  augustss 	sizeof(struct ukbd_softc), ukbd_match, ukbd_attach
    160  1.1  augustss };
    161  1.1  augustss 
    162  1.1  augustss int
    163  1.1  augustss ukbd_match(parent, match, aux)
    164  1.1  augustss 	struct device *parent;
    165  1.1  augustss 	struct cfdata *match;
    166  1.1  augustss 	void *aux;
    167  1.1  augustss {
    168  1.1  augustss 	struct usb_attach_arg *uaa = (struct usb_attach_arg *)aux;
    169  1.1  augustss 	usb_interface_descriptor_t *id;
    170  1.1  augustss 
    171  1.1  augustss 	/* Check that this is a keyboard that speaks the boot protocol. */
    172  1.1  augustss 	if (!uaa->iface)
    173  1.1  augustss 		return (UMATCH_NONE);
    174  1.1  augustss 	id = usbd_get_interface_descriptor(uaa->iface);
    175  1.1  augustss 	if (id->bInterfaceClass != UCLASS_HID ||
    176  1.1  augustss 	    id->bInterfaceSubClass != USUBCLASS_BOOT ||
    177  1.1  augustss 	    id->bInterfaceProtocol != UPROTO_BOOT_KEYBOARD)
    178  1.1  augustss 		return (UMATCH_NONE);
    179  1.1  augustss 	return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
    180  1.1  augustss }
    181  1.1  augustss 
    182  1.1  augustss void
    183  1.1  augustss ukbd_attach(parent, self, aux)
    184  1.1  augustss 	struct device *parent;
    185  1.1  augustss 	struct device *self;
    186  1.1  augustss 	void *aux;
    187  1.1  augustss {
    188  1.1  augustss 	struct ukbd_softc *sc = (struct ukbd_softc *)self;
    189  1.1  augustss 	struct usb_attach_arg *uaa = aux;
    190  1.1  augustss 	usbd_interface_handle iface = uaa->iface;
    191  1.1  augustss 	usb_interface_descriptor_t *id;
    192  1.1  augustss 	usb_endpoint_descriptor_t *ed;
    193  1.1  augustss 	usbd_status r;
    194  1.1  augustss 	char devinfo[1024];
    195  1.1  augustss 
    196  1.1  augustss 	sc->sc_disconnected = 1;
    197  1.1  augustss 	sc->sc_iface = iface;
    198  1.1  augustss 	id = usbd_get_interface_descriptor(iface);
    199  1.1  augustss 	usbd_devinfo(uaa->device, 0, devinfo);
    200  1.1  augustss 	printf(": %s (interface class %d/%d)\n", devinfo,
    201  1.1  augustss 	       id->bInterfaceClass, id->bInterfaceSubClass);
    202  1.1  augustss 	ed = usbd_interface2endpoint_descriptor(iface, 0);
    203  1.1  augustss 	if (!ed) {
    204  1.1  augustss 		printf("%s: could not read endpoint descriptor\n",
    205  1.1  augustss 		       sc->sc_dev.dv_xname);
    206  1.1  augustss 		return;
    207  1.1  augustss 	}
    208  1.1  augustss 
    209  1.1  augustss 	DPRINTFN(10,("ukbd_attach: \
    210  1.1  augustss bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d bInterval=%d\n",
    211  1.1  augustss 	       ed->bLength, ed->bDescriptorType, ed->bEndpointAddress & UE_ADDR,
    212  1.1  augustss 	       ed->bEndpointAddress & UE_IN ? "in" : "out",
    213  1.1  augustss 	       ed->bmAttributes & UE_XFERTYPE,
    214  1.1  augustss 	       UGETW(ed->wMaxPacketSize), ed->bInterval));
    215  1.1  augustss 
    216  1.1  augustss 	if ((ed->bEndpointAddress & UE_IN) != UE_IN ||
    217  1.1  augustss 	    (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
    218  1.1  augustss 		printf("%s: unexpected endpoint\n",
    219  1.1  augustss 		       sc->sc_dev.dv_xname);
    220  1.1  augustss 		return;
    221  1.1  augustss 	}
    222  1.1  augustss 
    223  1.1  augustss 	if ((usbd_get_quirks(uaa->device)->uq_flags & UQ_NO_SET_PROTO) == 0) {
    224  1.1  augustss 		r = usbd_set_protocol(iface, 0);
    225  1.1  augustss 		DPRINTFN(5, ("ukbd_attach: protocol set\n"));
    226  1.1  augustss 		if (r != USBD_NORMAL_COMPLETION) {
    227  1.1  augustss 			printf("%s: set protocol failed\n",
    228  1.1  augustss 			       sc->sc_dev.dv_xname);
    229  1.1  augustss 			return;
    230  1.1  augustss 		}
    231  1.1  augustss 	}
    232  1.1  augustss 
    233  1.1  augustss 	sc->sc_ep_addr = ed->bEndpointAddress;
    234  1.1  augustss 	sc->sc_disconnected = 0;
    235  1.1  augustss }
    236  1.1  augustss 
    237  1.1  augustss void
    238  1.1  augustss ukbd_disco(p)
    239  1.1  augustss 	void *p;
    240  1.1  augustss {
    241  1.1  augustss 	struct ukbd_softc *sc = p;
    242  1.1  augustss 	sc->sc_disconnected = 1;
    243  1.1  augustss }
    244  1.1  augustss 
    245  1.1  augustss void
    246  1.1  augustss ukbd_intr(reqh, addr, status)
    247  1.1  augustss 	usbd_request_handle reqh;
    248  1.1  augustss 	usbd_private_handle addr;
    249  1.1  augustss 	usbd_status status;
    250  1.1  augustss {
    251  1.1  augustss 	struct ukbd_softc *sc = addr;
    252  1.1  augustss 	struct ukbd_data *ud = &sc->sc_ndata;
    253  1.1  augustss 	int mod, omod;
    254  1.1  augustss 	char ibuf[NMOD+2*NKEYCODE];	/* chars events */
    255  1.1  augustss 	int nkeys, i, j;
    256  1.1  augustss 	int key, ch;
    257  1.1  augustss #define ADDKEY(c) ibuf[nkeys++] = (c)
    258  1.1  augustss 
    259  1.1  augustss 	DPRINTFN(5, ("ukbd_intr: status=%d\n", status));
    260  1.1  augustss 	if (status == USBD_CANCELLED)
    261  1.1  augustss 		return;
    262  1.1  augustss 
    263  1.1  augustss 	if (status != USBD_NORMAL_COMPLETION) {
    264  1.1  augustss 		DPRINTF(("ukbd_intr: status=%d\n", status));
    265  1.1  augustss 		sc->sc_state |= UKBD_NEEDCLEAR;
    266  1.1  augustss 		return;
    267  1.1  augustss 	}
    268  1.1  augustss 
    269  1.1  augustss 	DPRINTFN(5, ("          mod=0x%02x key0=0x%02x key1=0x%02x\n",
    270  1.1  augustss 		     ud->modifiers, ud->keycode[0], ud->keycode[1]));
    271  1.1  augustss 
    272  1.1  augustss 	if (ud->keycode[0] == KEY_ERROR)
    273  1.1  augustss 		return;		/* ignore  */
    274  1.1  augustss 	nkeys = 0;
    275  1.1  augustss 	mod = ud->modifiers;
    276  1.1  augustss 	omod = sc->sc_odata.modifiers;
    277  1.1  augustss 	if (mod != omod)
    278  1.1  augustss 		for (i = 0; i < NMOD; i++)
    279  1.1  augustss 			if (( mod & ukbd_mods[i].mask) !=
    280  1.1  augustss 			    (omod & ukbd_mods[i].mask))
    281  1.1  augustss 				ADDKEY(ukbd_mods[i].key |
    282  1.1  augustss 				       (mod & ukbd_mods[i].mask
    283  1.1  augustss 					  ? PRESS : RELEASE));
    284  1.1  augustss 	if (memcmp(ud->keycode, sc->sc_odata.keycode, NKEYCODE) != 0) {
    285  1.1  augustss 		/* Check for released keys. */
    286  1.1  augustss 		for (i = 0; i < NKEYCODE; i++) {
    287  1.1  augustss 			key = sc->sc_odata.keycode[i];
    288  1.1  augustss 			if (key == 0)
    289  1.1  augustss 				continue;
    290  1.1  augustss 			for (j = 0; j < NKEYCODE; j++)
    291  1.1  augustss 				if (key == ud->keycode[j])
    292  1.1  augustss 					goto rfound;
    293  1.1  augustss 			ch = ukbd_trtab[key];
    294  1.1  augustss 			if (ch)
    295  1.1  augustss 				ADDKEY(ch | RELEASE);
    296  1.1  augustss 		rfound:
    297  1.1  augustss 			;
    298  1.1  augustss 		}
    299  1.1  augustss 
    300  1.1  augustss 		/* Check for pressed keys. */
    301  1.1  augustss 		for (i = 0; i < NKEYCODE; i++) {
    302  1.1  augustss 			key = ud->keycode[i];
    303  1.1  augustss 			if (key == 0)
    304  1.1  augustss 				continue;
    305  1.1  augustss 			for (j = 0; j < NKEYCODE; j++)
    306  1.1  augustss 				if (key == sc->sc_odata.keycode[j])
    307  1.1  augustss 					goto pfound;
    308  1.1  augustss 			ch = ukbd_trtab[key];
    309  1.1  augustss 			if (ch)
    310  1.1  augustss 				ADDKEY(ch | PRESS);
    311  1.1  augustss 		pfound:
    312  1.1  augustss 			;
    313  1.1  augustss 		}
    314  1.1  augustss 	}
    315  1.1  augustss 	sc->sc_odata = *ud;
    316  1.1  augustss 
    317  1.1  augustss 	if (nkeys) {
    318  1.1  augustss 		b_to_q(ibuf, nkeys, &sc->sc_q);
    319  1.1  augustss 
    320  1.1  augustss 		if (sc->sc_state & UKBD_ASLP) {
    321  1.1  augustss 			sc->sc_state &= ~UKBD_ASLP;
    322  1.1  augustss 			DPRINTFN(5, ("ukbd_intr: waking %p\n", sc));
    323  1.1  augustss 			wakeup((caddr_t)sc);
    324  1.1  augustss 		}
    325  1.1  augustss 		selwakeup(&sc->sc_rsel);
    326  1.1  augustss 	}
    327  1.1  augustss }
    328  1.1  augustss 
    329  1.1  augustss int
    330  1.1  augustss ukbdopen(dev, flag, mode, p)
    331  1.1  augustss 	dev_t dev;
    332  1.1  augustss 	int flag;
    333  1.1  augustss 	int mode;
    334  1.1  augustss 	struct proc *p;
    335  1.1  augustss {
    336  1.1  augustss 	int unit = UKBDUNIT(dev);
    337  1.1  augustss 	struct ukbd_softc *sc;
    338  1.1  augustss 	usbd_status r;
    339  1.1  augustss 
    340  1.1  augustss 	if (unit >= ukbd_cd.cd_ndevs)
    341  1.1  augustss 		return ENXIO;
    342  1.1  augustss 	sc = ukbd_cd.cd_devs[unit];
    343  1.1  augustss 	if (!sc)
    344  1.1  augustss 		return ENXIO;
    345  1.1  augustss 
    346  1.1  augustss 	DPRINTF(("ukbdopen: sc=%p, disco=%d\n", sc, sc->sc_disconnected));
    347  1.1  augustss 
    348  1.1  augustss 	if (sc->sc_disconnected)
    349  1.1  augustss 		return (EIO);
    350  1.1  augustss 
    351  1.1  augustss 	if (sc->sc_state & UKBD_OPEN)
    352  1.1  augustss 		return EBUSY;
    353  1.1  augustss 
    354  1.1  augustss 	if (clalloc(&sc->sc_q, UKBD_BSIZE, 0) == -1)
    355  1.1  augustss 		return ENOMEM;
    356  1.1  augustss 
    357  1.1  augustss 	sc->sc_state |= UKBD_OPEN;
    358  1.1  augustss 
    359  1.1  augustss 	/* Set up interrupt pipe. */
    360  1.1  augustss 	r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
    361  1.1  augustss 				USBD_SHORT_XFER_OK,
    362  1.1  augustss 				&sc->sc_intrpipe, sc, &sc->sc_ndata,
    363  1.1  augustss 				sizeof(sc->sc_ndata), ukbd_intr);
    364  1.1  augustss 	if (r != USBD_NORMAL_COMPLETION) {
    365  1.1  augustss 		DPRINTF(("ukbdopen: usbd_open_pipe_intr failed, error=%d\n",r));
    366  1.1  augustss 		sc->sc_state &= ~UKBD_OPEN;
    367  1.1  augustss 		clfree(&sc->sc_q);
    368  1.1  augustss 		return (EIO);
    369  1.1  augustss 	}
    370  1.1  augustss 	usbd_set_disco(sc->sc_intrpipe, ukbd_disco, sc);
    371  1.1  augustss 	return 0;
    372  1.1  augustss }
    373  1.1  augustss 
    374  1.1  augustss int
    375  1.1  augustss ukbdclose(dev, flag, mode, p)
    376  1.1  augustss 	dev_t dev;
    377  1.1  augustss 	int flag;
    378  1.1  augustss 	int mode;
    379  1.1  augustss 	struct proc *p;
    380  1.1  augustss {
    381  1.1  augustss 	struct ukbd_softc *sc = ukbd_cd.cd_devs[UKBDUNIT(dev)];
    382  1.1  augustss 
    383  1.1  augustss 	if (sc->sc_disconnected)
    384  1.1  augustss 		return (EIO);
    385  1.1  augustss 
    386  1.1  augustss 	/* Disable interrupts. */
    387  1.1  augustss 	usbd_abort_pipe(sc->sc_intrpipe);
    388  1.1  augustss 	usbd_close_pipe(sc->sc_intrpipe);
    389  1.1  augustss 
    390  1.1  augustss 	sc->sc_state &= ~UKBD_OPEN;
    391  1.1  augustss 
    392  1.1  augustss 	clfree(&sc->sc_q);
    393  1.1  augustss 
    394  1.1  augustss 	return 0;
    395  1.1  augustss }
    396  1.1  augustss 
    397  1.1  augustss int
    398  1.1  augustss ukbdread(dev, uio, flag)
    399  1.1  augustss 	dev_t dev;
    400  1.1  augustss 	struct uio *uio;
    401  1.1  augustss 	int flag;
    402  1.1  augustss {
    403  1.1  augustss 	struct ukbd_softc *sc = ukbd_cd.cd_devs[UKBDUNIT(dev)];
    404  1.1  augustss 	int s;
    405  1.1  augustss 	int error = 0;
    406  1.1  augustss 	size_t length;
    407  1.1  augustss 	u_char buffer[UKBD_CHUNK];
    408  1.1  augustss 
    409  1.1  augustss 	if (sc->sc_disconnected)
    410  1.1  augustss 		return (EIO);
    411  1.1  augustss 
    412  1.1  augustss 	/* Block until keyboard activity occured. */
    413  1.1  augustss 	s = spltty();
    414  1.1  augustss 	while (sc->sc_q.c_cc == 0) {
    415  1.1  augustss 		if (flag & IO_NDELAY) {
    416  1.1  augustss 			splx(s);
    417  1.1  augustss 			return EWOULDBLOCK;
    418  1.1  augustss 		}
    419  1.1  augustss 		sc->sc_state |= UKBD_ASLP;
    420  1.1  augustss 		DPRINTFN(5, ("ukbdread: sleep on %p\n", sc));
    421  1.1  augustss 		error = tsleep((caddr_t)sc, PZERO | PCATCH, "ukbdrea", 0);
    422  1.1  augustss 		DPRINTFN(5, ("ukbdread: woke, error=%d\n", error));
    423  1.1  augustss 		if (error) {
    424  1.1  augustss 			sc->sc_state &= ~UKBD_ASLP;
    425  1.1  augustss 			splx(s);
    426  1.1  augustss 			return error;
    427  1.1  augustss 		}
    428  1.1  augustss 	}
    429  1.1  augustss 	splx(s);
    430  1.1  augustss 
    431  1.1  augustss 	/* Transfer as many chunks as possible. */
    432  1.1  augustss 	while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
    433  1.1  augustss 		length = min(sc->sc_q.c_cc, uio->uio_resid);
    434  1.1  augustss 		if (length > sizeof(buffer))
    435  1.1  augustss 			length = sizeof(buffer);
    436  1.1  augustss 
    437  1.1  augustss 		/* Remove a small chunk from the input queue. */
    438  1.1  augustss 		(void) q_to_b(&sc->sc_q, buffer, length);
    439  1.1  augustss 		DPRINTFN(5, ("ukbdread: got %d chars\n", length));
    440  1.1  augustss 
    441  1.1  augustss 		/* Copy the data to the user process. */
    442  1.1  augustss 		if ((error = uiomove(buffer, length, uio)) != 0)
    443  1.1  augustss 			break;
    444  1.1  augustss 	}
    445  1.1  augustss 
    446  1.1  augustss 	return error;
    447  1.1  augustss }
    448  1.1  augustss 
    449  1.1  augustss int
    450  1.1  augustss ukbdioctl(dev, cmd, addr, flag, p)
    451  1.1  augustss 	dev_t dev;
    452  1.1  augustss 	u_long cmd;
    453  1.1  augustss 	caddr_t addr;
    454  1.1  augustss 	int flag;
    455  1.1  augustss 	struct proc *p;
    456  1.1  augustss {
    457  1.1  augustss 	struct ukbd_softc *sc = ukbd_cd.cd_devs[UKBDUNIT(dev)];
    458  1.1  augustss 
    459  1.1  augustss 	if (sc->sc_disconnected)
    460  1.1  augustss 		return (EIO);
    461  1.1  augustss 
    462  1.1  augustss 	return EINVAL;
    463  1.1  augustss }
    464  1.1  augustss 
    465  1.1  augustss int
    466  1.1  augustss ukbdpoll(dev, events, p)
    467  1.1  augustss 	dev_t dev;
    468  1.1  augustss 	int events;
    469  1.1  augustss 	struct proc *p;
    470  1.1  augustss {
    471  1.1  augustss 	struct ukbd_softc *sc = ukbd_cd.cd_devs[UKBDUNIT(dev)];
    472  1.1  augustss 	int revents = 0;
    473  1.1  augustss 	int s;
    474  1.1  augustss 
    475  1.1  augustss 	if (sc->sc_disconnected)
    476  1.1  augustss 		return (EIO);
    477  1.1  augustss 
    478  1.1  augustss 	s = spltty();
    479  1.1  augustss 	if (events & (POLLIN | POLLRDNORM))
    480  1.1  augustss 		if (sc->sc_q.c_cc > 0)
    481  1.1  augustss 			revents |= events & (POLLIN | POLLRDNORM);
    482  1.1  augustss 		else
    483  1.1  augustss 			selrecord(p, &sc->sc_rsel);
    484  1.1  augustss 
    485  1.1  augustss 	splx(s);
    486  1.1  augustss 	return (revents);
    487  1.1  augustss }
    488