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