Annotation of src/sys/dev/usb/uhid.c, Revision 1.44.2.1
1.44.2.1! thorpej 1: /* $NetBSD: uhid.c,v 1.45 2001/10/26 17:58:21 augustss Exp $ */
1.28 augustss 2: /* $FreeBSD: src/sys/dev/usb/uhid.c,v 1.22 1999/11/17 22:33:43 n_hibma Exp $ */
1.1 augustss 3:
4: /*
5: * Copyright (c) 1998 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
1.6 augustss 8: * This code is derived from software contributed to The NetBSD Foundation
1.38 augustss 9: * by Lennart Augustsson (lennart@augustsson.net) at
1.6 augustss 10: * Carlstedt Research & Technology.
1.1 augustss 11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the NetBSD
23: * Foundation, Inc. and its contributors.
24: * 4. Neither the name of The NetBSD Foundation nor the names of its
25: * contributors may be used to endorse or promote products derived
26: * from this software without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38: * POSSIBILITY OF SUCH DAMAGE.
39: */
40:
1.15 augustss 41: /*
1.41 augustss 42: * HID spec: http://www.usb.org/developers/data/devclass/hid1_1.pdf
1.15 augustss 43: */
1.1 augustss 44:
45: #include <sys/param.h>
46: #include <sys/systm.h>
47: #include <sys/kernel.h>
48: #include <sys/malloc.h>
1.37 augustss 49: #include <sys/signalvar.h>
1.20 augustss 50: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.14 augustss 51: #include <sys/device.h>
1.12 augustss 52: #include <sys/ioctl.h>
53: #elif defined(__FreeBSD__)
54: #include <sys/ioccom.h>
55: #include <sys/filio.h>
56: #include <sys/module.h>
57: #include <sys/bus.h>
1.14 augustss 58: #include <sys/ioccom.h>
1.12 augustss 59: #endif
1.18 augustss 60: #include <sys/conf.h>
1.1 augustss 61: #include <sys/tty.h>
62: #include <sys/file.h>
63: #include <sys/select.h>
64: #include <sys/proc.h>
65: #include <sys/vnode.h>
66: #include <sys/poll.h>
67:
68: #include <dev/usb/usb.h>
69: #include <dev/usb/usbhid.h>
70:
1.42 augustss 71: #include <dev/usb/usbdevs.h>
1.1 augustss 72: #include <dev/usb/usbdi.h>
73: #include <dev/usb/usbdi_util.h>
74: #include <dev/usb/hid.h>
75: #include <dev/usb/usb_quirks.h>
76:
1.42 augustss 77: /* Report descriptor for broken Wacom Graphire */
78: #include <dev/usb/ugraphire_rdesc.h>
79:
1.26 augustss 80: #ifdef UHID_DEBUG
1.19 augustss 81: #define DPRINTF(x) if (uhiddebug) logprintf x
82: #define DPRINTFN(n,x) if (uhiddebug>(n)) logprintf x
1.1 augustss 83: int uhiddebug = 0;
84: #else
85: #define DPRINTF(x)
86: #define DPRINTFN(n,x)
87: #endif
88:
89: struct uhid_softc {
1.24 augustss 90: USBBASEDEVICE sc_dev; /* base device */
1.32 augustss 91: usbd_device_handle sc_udev;
1.1 augustss 92: usbd_interface_handle sc_iface; /* interface */
93: usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
94: int sc_ep_addr;
95:
96: int sc_isize;
97: int sc_osize;
1.2 augustss 98: int sc_fsize;
1.1 augustss 99: u_int8_t sc_iid;
100: u_int8_t sc_oid;
1.2 augustss 101: u_int8_t sc_fid;
1.1 augustss 102:
1.33 augustss 103: u_char *sc_ibuf;
104: u_char *sc_obuf;
1.1 augustss 105:
106: void *sc_repdesc;
107: int sc_repdesc_size;
108:
109: struct clist sc_q;
110: struct selinfo sc_rsel;
1.37 augustss 111: struct proc *sc_async; /* process that wants SIGIO */
1.1 augustss 112: u_char sc_state; /* driver state */
113: #define UHID_OPEN 0x01 /* device is open */
1.5 augustss 114: #define UHID_ASLP 0x02 /* waiting for device data */
1.1 augustss 115: #define UHID_NEEDCLEAR 0x04 /* needs clearing endpoint stall */
1.2 augustss 116: #define UHID_IMMED 0x08 /* return read data immediately */
1.18 augustss 117:
118: int sc_refcnt;
119: u_char sc_dying;
1.1 augustss 120: };
121:
122: #define UHIDUNIT(dev) (minor(dev))
123: #define UHID_CHUNK 128 /* chunk size for read */
124: #define UHID_BSIZE 1020 /* buffer size */
125:
1.20 augustss 126: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.19 augustss 127: cdev_decl(uhid);
128: #elif defined(__FreeBSD__)
129: d_open_t uhidopen;
130: d_close_t uhidclose;
131: d_read_t uhidread;
132: d_write_t uhidwrite;
133: d_ioctl_t uhidioctl;
134: d_poll_t uhidpoll;
135:
136: #define UHID_CDEV_MAJOR 122
137:
1.36 augustss 138: Static struct cdevsw uhid_cdevsw = {
1.19 augustss 139: /* open */ uhidopen,
140: /* close */ uhidclose,
141: /* read */ uhidread,
142: /* write */ uhidwrite,
143: /* ioctl */ uhidioctl,
144: /* poll */ uhidpoll,
145: /* mmap */ nommap,
146: /* strategy */ nostrategy,
147: /* name */ "uhid",
148: /* maj */ UHID_CDEV_MAJOR,
149: /* dump */ nodump,
150: /* psize */ nopsize,
151: /* flags */ 0,
152: /* bmaj */ -1
153: };
154: #endif
155:
1.39 augustss 156: Static void uhid_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
1.18 augustss 157:
1.39 augustss 158: Static int uhid_do_read(struct uhid_softc *, struct uio *uio, int);
159: Static int uhid_do_write(struct uhid_softc *, struct uio *uio, int);
160: Static int uhid_do_ioctl(struct uhid_softc*, u_long, caddr_t, int,struct proc*);
1.1 augustss 161:
1.12 augustss 162: USB_DECLARE_DRIVER(uhid);
1.1 augustss 163:
1.12 augustss 164: USB_MATCH(uhid)
1.1 augustss 165: {
1.12 augustss 166: USB_MATCH_START(uhid, uaa);
1.1 augustss 167: usb_interface_descriptor_t *id;
168:
1.28 augustss 169: if (uaa->iface == NULL)
1.1 augustss 170: return (UMATCH_NONE);
171: id = usbd_get_interface_descriptor(uaa->iface);
1.34 augustss 172: if (id == NULL || id->bInterfaceClass != UICLASS_HID)
1.1 augustss 173: return (UMATCH_NONE);
1.43 augustss 174: if (uaa->matchlvl)
175: return (uaa->matchlvl);
1.1 augustss 176: return (UMATCH_IFACECLASS_GENERIC);
177: }
178:
1.12 augustss 179: USB_ATTACH(uhid)
1.1 augustss 180: {
1.12 augustss 181: USB_ATTACH_START(uhid, sc, uaa);
1.1 augustss 182: usbd_interface_handle iface = uaa->iface;
183: usb_interface_descriptor_t *id;
184: usb_endpoint_descriptor_t *ed;
185: int size;
186: void *desc;
1.27 augustss 187: usbd_status err;
1.1 augustss 188: char devinfo[1024];
189:
1.32 augustss 190: sc->sc_udev = uaa->device;
1.1 augustss 191: sc->sc_iface = iface;
192: id = usbd_get_interface_descriptor(iface);
193: usbd_devinfo(uaa->device, 0, devinfo);
1.12 augustss 194: USB_ATTACH_SETUP;
195: printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
1.7 augustss 196: devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
1.12 augustss 197:
1.1 augustss 198: ed = usbd_interface2endpoint_descriptor(iface, 0);
1.27 augustss 199: if (ed == NULL) {
1.1 augustss 200: printf("%s: could not read endpoint descriptor\n",
1.12 augustss 201: USBDEVNAME(sc->sc_dev));
1.18 augustss 202: sc->sc_dying = 1;
1.12 augustss 203: USB_ATTACH_ERROR_RETURN;
1.1 augustss 204: }
205:
1.11 augustss 206: DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d "
207: "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
208: " bInterval=%d\n",
209: ed->bLength, ed->bDescriptorType,
210: ed->bEndpointAddress & UE_ADDR,
1.23 augustss 211: UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
1.11 augustss 212: ed->bmAttributes & UE_XFERTYPE,
213: UGETW(ed->wMaxPacketSize), ed->bInterval));
1.1 augustss 214:
1.23 augustss 215: if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
1.1 augustss 216: (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
1.12 augustss 217: printf("%s: unexpected endpoint\n", USBDEVNAME(sc->sc_dev));
1.18 augustss 218: sc->sc_dying = 1;
1.12 augustss 219: USB_ATTACH_ERROR_RETURN;
1.1 augustss 220: }
221:
222: sc->sc_ep_addr = ed->bEndpointAddress;
223:
1.42 augustss 224: if (uaa->vendor == USB_VENDOR_WACOM &&
225: uaa->product == USB_PRODUCT_WACOM_GRAPHIRE /* &&
226: uaa->revision == 0x???? */) { /* XXX should use revision */
227: /* The report descriptor for the Wacom Graphire is broken. */
228: size = sizeof uhid_graphire_report_descr;
229: desc = malloc(size, M_USBDEV, M_NOWAIT);
230: if (desc == NULL)
231: err = USBD_NOMEM;
232: else {
233: err = USBD_NORMAL_COMPLETION;
234: memcpy(desc, uhid_graphire_report_descr, size);
235: }
236: } else {
237: desc = NULL;
1.44.2.1! thorpej 238: err = usbd_read_report_desc(uaa->iface, &desc, &size,M_USBDEV);
1.42 augustss 239: }
1.27 augustss 240: if (err) {
1.12 augustss 241: printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev));
1.18 augustss 242: sc->sc_dying = 1;
1.12 augustss 243: USB_ATTACH_ERROR_RETURN;
1.1 augustss 244: }
245:
246: (void)usbd_set_idle(iface, 0, 0);
247:
1.2 augustss 248: sc->sc_isize = hid_report_size(desc, size, hid_input, &sc->sc_iid);
249: sc->sc_osize = hid_report_size(desc, size, hid_output, &sc->sc_oid);
250: sc->sc_fsize = hid_report_size(desc, size, hid_feature, &sc->sc_fid);
1.1 augustss 251:
252: sc->sc_repdesc = desc;
253: sc->sc_repdesc_size = size;
1.12 augustss 254:
1.28 augustss 255: #ifdef __FreeBSD__
256: {
257: static int global_init_done = 0;
258:
259: if (!global_init_done) {
260: cdevsw_add(&uhid_cdevsw);
261: global_init_done = 1;
262: }
263: }
264: #endif
265:
1.32 augustss 266: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
267: USBDEV(sc->sc_dev));
268:
1.12 augustss 269: USB_ATTACH_SUCCESS_RETURN;
1.1 augustss 270: }
271:
1.26 augustss 272: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.18 augustss 273: int
1.39 augustss 274: uhid_activate(device_ptr_t self, enum devact act)
1.18 augustss 275: {
1.21 augustss 276: struct uhid_softc *sc = (struct uhid_softc *)self;
277:
278: switch (act) {
279: case DVACT_ACTIVATE:
280: return (EOPNOTSUPP);
281: break;
282:
283: case DVACT_DEACTIVATE:
284: sc->sc_dying = 1;
285: break;
286: }
1.18 augustss 287: return (0);
1.12 augustss 288: }
1.26 augustss 289: #endif
1.12 augustss 290:
1.26 augustss 291: USB_DETACH(uhid)
1.1 augustss 292: {
1.26 augustss 293: USB_DETACH_START(uhid, sc);
294: int s;
295: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.18 augustss 296: int maj, mn;
297:
298: DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags));
1.26 augustss 299: #else
300: DPRINTF(("uhid_detach: sc=%p\n", sc));
301: #endif
1.3 augustss 302:
1.18 augustss 303: sc->sc_dying = 1;
1.27 augustss 304: if (sc->sc_intrpipe != NULL)
1.18 augustss 305: usbd_abort_pipe(sc->sc_intrpipe);
306:
307: if (sc->sc_state & UHID_OPEN) {
308: s = splusb();
309: if (--sc->sc_refcnt >= 0) {
310: /* Wake everyone */
311: wakeup(&sc->sc_q);
312: /* Wait for processes to go away. */
1.24 augustss 313: usb_detach_wait(USBDEV(sc->sc_dev));
1.18 augustss 314: }
315: splx(s);
316: }
317:
1.26 augustss 318: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.18 augustss 319: /* locate the major number */
320: for (maj = 0; maj < nchrdev; maj++)
321: if (cdevsw[maj].d_open == uhidopen)
322: break;
323:
324: /* Nuke the vnodes for any open instances (calls close). */
325: mn = self->dv_unit;
326: vdevgone(maj, mn, mn, VCHR);
1.26 augustss 327: #elif defined(__FreeBSD__)
328: /* XXX not implemented yet */
329: #endif
1.18 augustss 330:
1.40 augustss 331: if (sc->sc_repdesc)
332: free(sc->sc_repdesc, M_USBDEV);
1.32 augustss 333:
334: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
335: USBDEV(sc->sc_dev));
1.18 augustss 336:
337: return (0);
1.1 augustss 338: }
339:
340: void
1.39 augustss 341: uhid_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
1.1 augustss 342: {
343: struct uhid_softc *sc = addr;
344:
1.33 augustss 345: #ifdef UHID_DEBUG
346: if (uhiddebug > 5) {
347: u_int32_t cc, i;
348:
349: usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
350: DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc));
351: DPRINTF(("uhid_intr: data ="));
352: for (i = 0; i < cc; i++)
353: DPRINTF((" %02x", sc->sc_ibuf[i]));
354: DPRINTF(("\n"));
355: }
356: #endif
1.1 augustss 357:
358: if (status == USBD_CANCELLED)
359: return;
360:
361: if (status != USBD_NORMAL_COMPLETION) {
362: DPRINTF(("uhid_intr: status=%d\n", status));
363: sc->sc_state |= UHID_NEEDCLEAR;
364: return;
365: }
366:
367: (void) b_to_q(sc->sc_ibuf, sc->sc_isize, &sc->sc_q);
368:
369: if (sc->sc_state & UHID_ASLP) {
370: sc->sc_state &= ~UHID_ASLP;
1.44 yamt 371: DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q));
1.18 augustss 372: wakeup(&sc->sc_q);
1.1 augustss 373: }
374: selwakeup(&sc->sc_rsel);
1.37 augustss 375: if (sc->sc_async != NULL) {
376: DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async));
377: psignal(sc->sc_async, SIGIO);
378: }
1.1 augustss 379: }
380:
381: int
1.39 augustss 382: uhidopen(dev_t dev, int flag, int mode, struct proc *p)
1.1 augustss 383: {
1.25 augustss 384: struct uhid_softc *sc;
1.27 augustss 385: usbd_status err;
1.25 augustss 386:
1.12 augustss 387: USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc);
1.1 augustss 388:
1.18 augustss 389: DPRINTF(("uhidopen: sc=%p\n", sc));
1.1 augustss 390:
1.18 augustss 391: if (sc->sc_dying)
392: return (ENXIO);
1.1 augustss 393:
394: if (sc->sc_state & UHID_OPEN)
1.12 augustss 395: return (EBUSY);
1.17 augustss 396: sc->sc_state |= UHID_OPEN;
1.1 augustss 397:
1.17 augustss 398: if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) {
399: sc->sc_state &= ~UHID_OPEN;
1.12 augustss 400: return (ENOMEM);
1.17 augustss 401: }
1.1 augustss 402:
1.18 augustss 403: sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
404: sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
1.1 augustss 405:
406: /* Set up interrupt pipe. */
1.27 augustss 407: err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
408: USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf,
1.31 augustss 409: sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL);
1.27 augustss 410: if (err) {
1.11 augustss 411: DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
1.27 augustss 412: "error=%d\n",err));
1.18 augustss 413: free(sc->sc_ibuf, M_USBDEV);
414: free(sc->sc_obuf, M_USBDEV);
1.1 augustss 415: sc->sc_state &= ~UHID_OPEN;
416: return (EIO);
417: }
1.17 augustss 418:
419: sc->sc_state &= ~UHID_IMMED;
420:
1.37 augustss 421: sc->sc_async = 0;
422:
1.12 augustss 423: return (0);
1.1 augustss 424: }
425:
426: int
1.39 augustss 427: uhidclose(dev_t dev, int flag, int mode, struct proc *p)
1.1 augustss 428: {
1.25 augustss 429: struct uhid_softc *sc;
430:
1.12 augustss 431: USB_GET_SC(uhid, UHIDUNIT(dev), sc);
1.1 augustss 432:
433: DPRINTF(("uhidclose: sc=%p\n", sc));
434:
435: /* Disable interrupts. */
436: usbd_abort_pipe(sc->sc_intrpipe);
437: usbd_close_pipe(sc->sc_intrpipe);
1.18 augustss 438: sc->sc_intrpipe = 0;
1.1 augustss 439:
440: clfree(&sc->sc_q);
441:
1.18 augustss 442: free(sc->sc_ibuf, M_USBDEV);
443: free(sc->sc_obuf, M_USBDEV);
1.17 augustss 444:
445: sc->sc_state &= ~UHID_OPEN;
1.1 augustss 446:
1.37 augustss 447: sc->sc_async = 0;
448:
1.12 augustss 449: return (0);
1.1 augustss 450: }
451:
452: int
1.39 augustss 453: uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag)
1.1 augustss 454: {
455: int s;
456: int error = 0;
457: size_t length;
458: u_char buffer[UHID_CHUNK];
1.27 augustss 459: usbd_status err;
1.1 augustss 460:
461: DPRINTFN(1, ("uhidread\n"));
1.2 augustss 462: if (sc->sc_state & UHID_IMMED) {
463: DPRINTFN(1, ("uhidread immed\n"));
464:
1.27 augustss 465: err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
1.16 augustss 466: sc->sc_iid, buffer, sc->sc_isize);
1.27 augustss 467: if (err)
1.2 augustss 468: return (EIO);
469: return (uiomove(buffer, sc->sc_isize, uio));
470: }
471:
1.10 augustss 472: s = splusb();
1.1 augustss 473: while (sc->sc_q.c_cc == 0) {
474: if (flag & IO_NDELAY) {
475: splx(s);
1.18 augustss 476: return (EWOULDBLOCK);
1.1 augustss 477: }
478: sc->sc_state |= UHID_ASLP;
1.44 yamt 479: DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q));
1.18 augustss 480: error = tsleep(&sc->sc_q, PZERO | PCATCH, "uhidrea", 0);
1.1 augustss 481: DPRINTFN(5, ("uhidread: woke, error=%d\n", error));
1.18 augustss 482: if (sc->sc_dying)
483: error = EIO;
1.1 augustss 484: if (error) {
485: sc->sc_state &= ~UHID_ASLP;
1.18 augustss 486: break;
1.1 augustss 487: }
488: if (sc->sc_state & UHID_NEEDCLEAR) {
489: DPRINTFN(-1,("uhidread: clearing stall\n"));
490: sc->sc_state &= ~UHID_NEEDCLEAR;
491: usbd_clear_endpoint_stall(sc->sc_intrpipe);
492: }
493: }
494: splx(s);
495:
496: /* Transfer as many chunks as possible. */
1.18 augustss 497: while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) {
1.1 augustss 498: length = min(sc->sc_q.c_cc, uio->uio_resid);
499: if (length > sizeof(buffer))
500: length = sizeof(buffer);
501:
502: /* Remove a small chunk from the input queue. */
503: (void) q_to_b(&sc->sc_q, buffer, length);
1.29 augustss 504: DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length));
1.1 augustss 505:
506: /* Copy the data to the user process. */
507: if ((error = uiomove(buffer, length, uio)) != 0)
508: break;
509: }
510:
511: return (error);
512: }
513:
514: int
1.39 augustss 515: uhidread(dev_t dev, struct uio *uio, int flag)
1.1 augustss 516: {
1.25 augustss 517: struct uhid_softc *sc;
518: int error;
519:
1.18 augustss 520: USB_GET_SC(uhid, UHIDUNIT(dev), sc);
521:
522: sc->sc_refcnt++;
523: error = uhid_do_read(sc, uio, flag);
524: if (--sc->sc_refcnt < 0)
1.24 augustss 525: usb_detach_wakeup(USBDEV(sc->sc_dev));
1.18 augustss 526: return (error);
527: }
528:
529: int
1.39 augustss 530: uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag)
1.18 augustss 531: {
1.1 augustss 532: int error;
533: int size;
1.27 augustss 534: usbd_status err;
1.1 augustss 535:
1.18 augustss 536: DPRINTFN(1, ("uhidwrite\n"));
537:
538: if (sc->sc_dying)
1.1 augustss 539: return (EIO);
540:
541: size = sc->sc_osize;
542: error = 0;
1.18 augustss 543: if (uio->uio_resid != size)
544: return (EINVAL);
545: error = uiomove(sc->sc_obuf, size, uio);
546: if (!error) {
1.1 augustss 547: if (sc->sc_oid)
1.27 augustss 548: err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
549: sc->sc_obuf[0], sc->sc_obuf+1, size-1);
1.1 augustss 550: else
1.27 augustss 551: err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
552: 0, sc->sc_obuf, size);
553: if (err)
1.1 augustss 554: error = EIO;
555: }
1.18 augustss 556:
1.1 augustss 557: return (error);
558: }
559:
560: int
1.39 augustss 561: uhidwrite(dev_t dev, struct uio *uio, int flag)
1.18 augustss 562: {
1.25 augustss 563: struct uhid_softc *sc;
564: int error;
565:
1.18 augustss 566: USB_GET_SC(uhid, UHIDUNIT(dev), sc);
567:
568: sc->sc_refcnt++;
569: error = uhid_do_write(sc, uio, flag);
570: if (--sc->sc_refcnt < 0)
1.24 augustss 571: usb_detach_wakeup(USBDEV(sc->sc_dev));
1.18 augustss 572: return (error);
573: }
574:
575: int
1.39 augustss 576: uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr,
577: int flag, struct proc *p)
1.1 augustss 578: {
579: struct usb_ctl_report_desc *rd;
1.2 augustss 580: struct usb_ctl_report *re;
581: int size, id;
1.27 augustss 582: usbd_status err;
1.1 augustss 583:
1.18 augustss 584: DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
585:
586: if (sc->sc_dying)
1.1 augustss 587: return (EIO);
588:
589: switch (cmd) {
1.2 augustss 590: case FIONBIO:
591: /* All handled in the upper FS layer. */
1.37 augustss 592: break;
593:
594: case FIOASYNC:
595: if (*(int *)addr) {
596: if (sc->sc_async != NULL)
597: return (EBUSY);
598: sc->sc_async = p;
599: DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", p));
600: } else
601: sc->sc_async = NULL;
602: break;
603:
604: /* XXX this is not the most general solution. */
605: case TIOCSPGRP:
606: if (sc->sc_async == NULL)
607: return (EINVAL);
608: if (*(int *)addr != sc->sc_async->p_pgid)
609: return (EPERM);
1.2 augustss 610: break;
611:
1.1 augustss 612: case USB_GET_REPORT_DESC:
613: rd = (struct usb_ctl_report_desc *)addr;
614: size = min(sc->sc_repdesc_size, sizeof rd->data);
615: rd->size = size;
616: memcpy(rd->data, sc->sc_repdesc, size);
617: break;
1.2 augustss 618:
619: case USB_SET_IMMED:
1.9 augustss 620: if (*(int *)addr) {
1.27 augustss 621: /* XXX should read into ibuf, but does it matter? */
622: err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
623: sc->sc_iid, sc->sc_ibuf, sc->sc_isize);
624: if (err)
1.9 augustss 625: return (EOPNOTSUPP);
1.12 augustss 626:
1.2 augustss 627: sc->sc_state |= UHID_IMMED;
1.9 augustss 628: } else
1.2 augustss 629: sc->sc_state &= ~UHID_IMMED;
630: break;
631:
632: case USB_GET_REPORT:
633: re = (struct usb_ctl_report *)addr;
634: switch (re->report) {
635: case UHID_INPUT_REPORT:
636: size = sc->sc_isize;
637: id = sc->sc_iid;
638: break;
639: case UHID_OUTPUT_REPORT:
640: size = sc->sc_osize;
641: id = sc->sc_oid;
642: break;
643: case UHID_FEATURE_REPORT:
644: size = sc->sc_fsize;
645: id = sc->sc_fid;
646: break;
647: default:
648: return (EINVAL);
649: }
1.27 augustss 650: err = usbd_get_report(sc->sc_iface, re->report, id, re->data,
1.35 augustss 651: size);
652: if (err)
653: return (EIO);
654: break;
655:
656: case USB_SET_REPORT:
657: re = (struct usb_ctl_report *)addr;
658: switch (re->report) {
659: case UHID_INPUT_REPORT:
660: size = sc->sc_isize;
661: id = sc->sc_iid;
662: break;
663: case UHID_OUTPUT_REPORT:
664: size = sc->sc_osize;
665: id = sc->sc_oid;
666: break;
667: case UHID_FEATURE_REPORT:
668: size = sc->sc_fsize;
669: id = sc->sc_fid;
670: break;
671: default:
672: return (EINVAL);
673: }
674: err = usbd_set_report(sc->sc_iface, re->report, id, re->data,
1.27 augustss 675: size);
676: if (err)
1.2 augustss 677: return (EIO);
678: break;
679:
1.1 augustss 680: default:
681: return (EINVAL);
682: }
683: return (0);
684: }
685:
686: int
1.39 augustss 687: uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1.18 augustss 688: {
1.25 augustss 689: struct uhid_softc *sc;
690: int error;
691:
1.18 augustss 692: USB_GET_SC(uhid, UHIDUNIT(dev), sc);
693:
694: sc->sc_refcnt++;
695: error = uhid_do_ioctl(sc, cmd, addr, flag, p);
696: if (--sc->sc_refcnt < 0)
1.24 augustss 697: usb_detach_wakeup(USBDEV(sc->sc_dev));
1.18 augustss 698: return (error);
699: }
700:
701: int
1.39 augustss 702: uhidpoll(dev_t dev, int events, struct proc *p)
1.1 augustss 703: {
1.25 augustss 704: struct uhid_softc *sc;
1.1 augustss 705: int revents = 0;
706: int s;
1.25 augustss 707:
1.12 augustss 708: USB_GET_SC(uhid, UHIDUNIT(dev), sc);
1.1 augustss 709:
1.18 augustss 710: if (sc->sc_dying)
1.1 augustss 711: return (EIO);
712:
1.10 augustss 713: s = splusb();
1.1 augustss 714: if (events & (POLLOUT | POLLWRNORM))
715: revents |= events & (POLLOUT | POLLWRNORM);
1.4 veego 716: if (events & (POLLIN | POLLRDNORM)) {
1.1 augustss 717: if (sc->sc_q.c_cc > 0)
718: revents |= events & (POLLIN | POLLRDNORM);
719: else
720: selrecord(p, &sc->sc_rsel);
1.4 veego 721: }
1.1 augustss 722:
723: splx(s);
724: return (revents);
725: }
1.12 augustss 726:
727: #if defined(__FreeBSD__)
1.28 augustss 728: DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, 0);
1.12 augustss 729: #endif
CVSweb <webmaster@jp.NetBSD.org>