]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hid/hidraw.c
zfs: merge openzfs/zfs@14b43fbd9 (master) into main
[FreeBSD/FreeBSD.git] / sys / dev / hid / hidraw.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
3  *
4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Lennart Augustsson (lennart@augustsson.net) at
10  * Carlstedt Research & Technology.
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  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 /*
35  * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
36  */
37
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include "opt_hid.h"
42
43 #include <sys/param.h>
44 #include <sys/bus.h>
45 #include <sys/conf.h>
46 #include <sys/fcntl.h>
47 #include <sys/filio.h>
48 #include <sys/ioccom.h>
49 #include <sys/kernel.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/module.h>
53 #include <sys/mutex.h>
54 #include <sys/poll.h>
55 #include <sys/priv.h>
56 #include <sys/proc.h>
57 #include <sys/selinfo.h>
58 #include <sys/sysctl.h>
59 #include <sys/systm.h>
60 #include <sys/tty.h>
61 #include <sys/uio.h>
62
63 #define HID_DEBUG_VAR   hidraw_debug
64 #include <dev/hid/hid.h>
65 #include <dev/hid/hidbus.h>
66 #include <dev/hid/hidraw.h>
67
68 #ifdef HID_DEBUG
69 static int hidraw_debug = 0;
70 static SYSCTL_NODE(_hw_hid, OID_AUTO, hidraw, CTLFLAG_RW, 0,
71     "HID raw interface");
72 SYSCTL_INT(_hw_hid_hidraw, OID_AUTO, debug, CTLFLAG_RWTUN,
73     &hidraw_debug, 0, "Debug level");
74 #endif
75
76 #define HIDRAW_INDEX            0xFF    /* Arbitrary high value */
77
78 #define HIDRAW_LOCAL_BUFSIZE    64      /* Size of on-stack buffer. */
79 #define HIDRAW_LOCAL_ALLOC(local_buf, size)             \
80         (sizeof(local_buf) > (size) ? (local_buf) :     \
81             malloc((size), M_DEVBUF, M_ZERO | M_WAITOK))
82 #define HIDRAW_LOCAL_FREE(local_buf, buf)               \
83         if ((local_buf) != (buf)) {                     \
84                 free((buf), M_DEVBUF);                  \
85         }
86
87 struct hidraw_softc {
88         device_t sc_dev;                /* base device */
89
90         struct mtx sc_mtx;              /* hidbus private mutex */
91
92         struct hid_rdesc_info *sc_rdesc;
93         const struct hid_device_info *sc_hw;
94
95         uint8_t *sc_q;
96         hid_size_t *sc_qlen;
97         int sc_head;
98         int sc_tail;
99         int sc_sleepcnt;
100
101         struct selinfo sc_rsel;
102         struct proc *sc_async;  /* process that wants SIGIO */
103         struct {                        /* driver state */
104                 bool    open:1;         /* device is open */
105                 bool    aslp:1;         /* waiting for device data in read() */
106                 bool    sel:1;          /* waiting for device data in poll() */
107                 bool    quiet:1;        /* Ignore input data */
108                 bool    immed:1;        /* return read data immediately */
109                 bool    uhid:1;         /* driver switched in to uhid mode */
110                 bool    lock:1;         /* input queue sleepable lock */
111                 bool    flush:1;        /* do not wait for data in read() */
112         } sc_state;
113         int sc_fflags;                  /* access mode for open lifetime */
114
115         struct cdev *dev;
116 };
117
118 static d_open_t         hidraw_open;
119 static d_read_t         hidraw_read;
120 static d_write_t        hidraw_write;
121 static d_ioctl_t        hidraw_ioctl;
122 static d_poll_t         hidraw_poll;
123 static d_kqfilter_t     hidraw_kqfilter;
124
125 static d_priv_dtor_t    hidraw_dtor;
126
127 static struct cdevsw hidraw_cdevsw = {
128         .d_version =    D_VERSION,
129         .d_open =       hidraw_open,
130         .d_read =       hidraw_read,
131         .d_write =      hidraw_write,
132         .d_ioctl =      hidraw_ioctl,
133         .d_poll =       hidraw_poll,
134         .d_kqfilter =   hidraw_kqfilter,
135         .d_name =       "hidraw",
136 };
137
138 static hid_intr_t       hidraw_intr;
139
140 static device_identify_t hidraw_identify;
141 static device_probe_t   hidraw_probe;
142 static device_attach_t  hidraw_attach;
143 static device_detach_t  hidraw_detach;
144
145 static int              hidraw_kqread(struct knote *, long);
146 static void             hidraw_kqdetach(struct knote *);
147 static void             hidraw_notify(struct hidraw_softc *);
148
149 static struct filterops hidraw_filterops_read = {
150         .f_isfd =       1,
151         .f_detach =     hidraw_kqdetach,
152         .f_event =      hidraw_kqread,
153 };
154
155 static void
156 hidraw_identify(driver_t *driver, device_t parent)
157 {
158         device_t child;
159
160         if (device_find_child(parent, "hidraw", -1) == NULL) {
161                 child = BUS_ADD_CHILD(parent, 0, "hidraw",
162                     device_get_unit(parent));
163                 if (child != NULL)
164                         hidbus_set_index(child, HIDRAW_INDEX);
165         }
166 }
167
168 static int
169 hidraw_probe(device_t self)
170 {
171
172         if (hidbus_get_index(self) != HIDRAW_INDEX)
173                 return (ENXIO);
174
175         hidbus_set_desc(self, "Raw HID Device");
176
177         return (BUS_PROBE_GENERIC);
178 }
179
180 static int
181 hidraw_attach(device_t self)
182 {
183         struct hidraw_softc *sc = device_get_softc(self);
184         struct make_dev_args mda;
185         int error;
186
187         sc->sc_dev = self;
188         sc->sc_rdesc = hidbus_get_rdesc_info(self);
189         sc->sc_hw = hid_get_device_info(self);
190
191         /* Hidraw mode does not require report descriptor to work */
192         if (sc->sc_rdesc->data == NULL || sc->sc_rdesc->len == 0)
193                 device_printf(self, "no report descriptor\n");
194
195         mtx_init(&sc->sc_mtx, "hidraw lock", NULL, MTX_DEF);
196         knlist_init_mtx(&sc->sc_rsel.si_note, &sc->sc_mtx);
197
198         make_dev_args_init(&mda);
199         mda.mda_flags = MAKEDEV_WAITOK;
200         mda.mda_devsw = &hidraw_cdevsw;
201         mda.mda_uid = UID_ROOT;
202         mda.mda_gid = GID_OPERATOR;
203         mda.mda_mode = 0600;
204         mda.mda_si_drv1 = sc;
205
206         error = make_dev_s(&mda, &sc->dev, "hidraw%d", device_get_unit(self));
207         if (error) {
208                 device_printf(self, "Can not create character device\n");
209                 hidraw_detach(self);
210                 return (error);
211         }
212 #ifdef HIDRAW_MAKE_UHID_ALIAS
213         (void)make_dev_alias(sc->dev, "uhid%d", device_get_unit(self));
214 #endif
215
216         hidbus_set_lock(self, &sc->sc_mtx);
217         hidbus_set_intr(self, hidraw_intr, sc);
218
219         return (0);
220 }
221
222 static int
223 hidraw_detach(device_t self)
224 {
225         struct hidraw_softc *sc = device_get_softc(self);
226
227         DPRINTF("sc=%p\n", sc);
228
229         if (sc->dev != NULL) {
230                 mtx_lock(&sc->sc_mtx);
231                 sc->dev->si_drv1 = NULL;
232                 /* Wake everyone */
233                 hidraw_notify(sc);
234                 mtx_unlock(&sc->sc_mtx);
235                 destroy_dev(sc->dev);
236         }
237
238         knlist_clear(&sc->sc_rsel.si_note, 0);
239         knlist_destroy(&sc->sc_rsel.si_note);
240         seldrain(&sc->sc_rsel);
241         mtx_destroy(&sc->sc_mtx);
242
243         return (0);
244 }
245
246 void
247 hidraw_intr(void *context, void *buf, hid_size_t len)
248 {
249         struct hidraw_softc *sc = context;
250         int next;
251
252         DPRINTFN(5, "len=%d\n", len);
253         DPRINTFN(5, "data = %*D\n", len, buf, " ");
254
255         next = (sc->sc_tail + 1) % HIDRAW_BUFFER_SIZE;
256         if (sc->sc_state.quiet || next == sc->sc_head)
257                 return;
258
259         bcopy(buf, sc->sc_q + sc->sc_tail * sc->sc_rdesc->rdsize, len);
260
261         /* Make sure we don't process old data */
262         if (len < sc->sc_rdesc->rdsize)
263                 bzero(sc->sc_q + sc->sc_tail * sc->sc_rdesc->rdsize + len,
264                     sc->sc_rdesc->isize - len);
265
266         sc->sc_qlen[sc->sc_tail] = len;
267         sc->sc_tail = next;
268
269         hidraw_notify(sc);
270 }
271
272 static inline int
273 hidraw_lock_queue(struct hidraw_softc *sc, bool flush)
274 {
275         int error = 0;
276
277         mtx_assert(&sc->sc_mtx, MA_OWNED);
278
279         if (flush)
280                 sc->sc_state.flush = true;
281         ++sc->sc_sleepcnt;
282         while (sc->sc_state.lock && error == 0) {
283                 /* Flush is requested. Wakeup all readers and forbid sleeps */
284                 if (flush && sc->sc_state.aslp) {
285                         sc->sc_state.aslp = false;
286                         DPRINTFN(5, "waking %p\n", &sc->sc_q);
287                         wakeup(&sc->sc_q);
288                 }
289                 error = mtx_sleep(&sc->sc_sleepcnt, &sc->sc_mtx,
290                     PZERO | PCATCH, "hidrawio", 0);
291         }
292         --sc->sc_sleepcnt;
293         if (flush)
294                 sc->sc_state.flush = false;
295         if (error == 0)
296                 sc->sc_state.lock = true;
297
298         return (error);
299 }
300
301 static inline void
302 hidraw_unlock_queue(struct hidraw_softc *sc)
303 {
304
305         mtx_assert(&sc->sc_mtx, MA_OWNED);
306         KASSERT(sc->sc_state.lock, ("input buffer is not locked"));
307
308         if (sc->sc_sleepcnt != 0)
309                 wakeup_one(&sc->sc_sleepcnt);
310         sc->sc_state.lock = false;
311 }
312
313 static int
314 hidraw_open(struct cdev *dev, int flag, int mode, struct thread *td)
315 {
316         struct hidraw_softc *sc;
317         int error;
318
319         sc = dev->si_drv1;
320         if (sc == NULL)
321                 return (ENXIO);
322
323         DPRINTF("sc=%p\n", sc);
324
325         mtx_lock(&sc->sc_mtx);
326         if (sc->sc_state.open) {
327                 mtx_unlock(&sc->sc_mtx);
328                 return (EBUSY);
329         }
330         sc->sc_state.open = true;
331         mtx_unlock(&sc->sc_mtx);
332
333         error = devfs_set_cdevpriv(sc, hidraw_dtor);
334         if (error != 0) {
335                 mtx_lock(&sc->sc_mtx);
336                 sc->sc_state.open = false;
337                 mtx_unlock(&sc->sc_mtx);
338                 return (error);
339         }
340
341         sc->sc_q = malloc(sc->sc_rdesc->rdsize * HIDRAW_BUFFER_SIZE, M_DEVBUF,
342             M_ZERO | M_WAITOK);
343         sc->sc_qlen = malloc(sizeof(hid_size_t) * HIDRAW_BUFFER_SIZE, M_DEVBUF,
344             M_ZERO | M_WAITOK);
345
346         /* Set up interrupt pipe. */
347         sc->sc_state.immed = false;
348         sc->sc_async = 0;
349         sc->sc_state.uhid = false;      /* hidraw mode is default */
350         sc->sc_state.quiet = false;
351         sc->sc_head = sc->sc_tail = 0;
352         sc->sc_fflags = flag;
353
354         hidbus_intr_start(sc->sc_dev);
355
356         return (0);
357 }
358
359 static void
360 hidraw_dtor(void *data)
361 {
362         struct hidraw_softc *sc = data;
363
364         DPRINTF("sc=%p\n", sc);
365
366         /* Disable interrupts. */
367         hidbus_intr_stop(sc->sc_dev);
368
369         sc->sc_tail = sc->sc_head = 0;
370         sc->sc_async = 0;
371         free(sc->sc_q, M_DEVBUF);
372         free(sc->sc_qlen, M_DEVBUF);
373         sc->sc_q = NULL;
374
375         mtx_lock(&sc->sc_mtx);
376         sc->sc_state.open = false;
377         mtx_unlock(&sc->sc_mtx);
378 }
379
380 static int
381 hidraw_read(struct cdev *dev, struct uio *uio, int flag)
382 {
383         struct hidraw_softc *sc;
384         size_t length;
385         int error;
386
387         DPRINTFN(1, "\n");
388
389         sc = dev->si_drv1;
390         if (sc == NULL)
391                 return (EIO);
392
393         mtx_lock(&sc->sc_mtx);
394         error = dev->si_drv1 == NULL ? EIO : hidraw_lock_queue(sc, false);
395         if (error != 0) {
396                 mtx_unlock(&sc->sc_mtx);
397                 return (error);
398         }
399
400         if (sc->sc_state.immed) {
401                 mtx_unlock(&sc->sc_mtx);
402                 DPRINTFN(1, "immed\n");
403
404                 error = hid_get_report(sc->sc_dev, sc->sc_q,
405                     sc->sc_rdesc->isize, NULL, HID_INPUT_REPORT,
406                     sc->sc_rdesc->iid);
407                 if (error == 0)
408                         error = uiomove(sc->sc_q, sc->sc_rdesc->isize, uio);
409                 mtx_lock(&sc->sc_mtx);
410                 goto exit;
411         }
412
413         while (sc->sc_tail == sc->sc_head && !sc->sc_state.flush) {
414                 if (flag & O_NONBLOCK) {
415                         error = EWOULDBLOCK;
416                         goto exit;
417                 }
418                 sc->sc_state.aslp = true;
419                 DPRINTFN(5, "sleep on %p\n", &sc->sc_q);
420                 error = mtx_sleep(&sc->sc_q, &sc->sc_mtx, PZERO | PCATCH,
421                     "hidrawrd", 0);
422                 DPRINTFN(5, "woke, error=%d\n", error);
423                 if (dev->si_drv1 == NULL)
424                         error = EIO;
425                 if (error) {
426                         sc->sc_state.aslp = false;
427                         goto exit;
428                 }
429         }
430
431         while (sc->sc_tail != sc->sc_head && uio->uio_resid > 0) {
432                 length = min(uio->uio_resid, sc->sc_state.uhid ?
433                     sc->sc_rdesc->isize : sc->sc_qlen[sc->sc_head]);
434                 mtx_unlock(&sc->sc_mtx);
435
436                 /* Copy the data to the user process. */
437                 DPRINTFN(5, "got %lu chars\n", (u_long)length);
438                 error = uiomove(sc->sc_q + sc->sc_head * sc->sc_rdesc->rdsize,
439                     length, uio);
440
441                 mtx_lock(&sc->sc_mtx);
442                 if (error != 0)
443                         goto exit;
444                 /* Remove a small chunk from the input queue. */
445                 sc->sc_head = (sc->sc_head + 1) % HIDRAW_BUFFER_SIZE;
446                 /*
447                  * In uhid mode transfer as many chunks as possible. Hidraw
448                  * packets are transferred one by one due to different length.
449                  */
450                 if (!sc->sc_state.uhid)
451                         goto exit;
452         }
453 exit:
454         hidraw_unlock_queue(sc);
455         mtx_unlock(&sc->sc_mtx);
456
457         return (error);
458 }
459
460 static int
461 hidraw_write(struct cdev *dev, struct uio *uio, int flag)
462 {
463         uint8_t local_buf[HIDRAW_LOCAL_BUFSIZE], *buf;
464         struct hidraw_softc *sc;
465         int error;
466         int size;
467         size_t buf_offset;
468         uint8_t id = 0;
469
470         DPRINTFN(1, "\n");
471
472         sc = dev->si_drv1;
473         if (sc == NULL)
474                 return (EIO);
475
476         if (sc->sc_rdesc->osize == 0)
477                 return (EOPNOTSUPP);
478
479         buf_offset = 0;
480         if (sc->sc_state.uhid) {
481                 size = sc->sc_rdesc->osize;
482                 if (uio->uio_resid != size)
483                         return (EINVAL);
484         } else {
485                 size = uio->uio_resid;
486                 if (size < 2)
487                         return (EINVAL);
488                 /* Strip leading 0 if the device doesnt use numbered reports */
489                 error = uiomove(&id, 1, uio);
490                 if (error)
491                         return (error);
492                 if (id != 0)
493                         buf_offset++;
494                 else
495                         size--;
496                 /* Check if underlying driver could process this request */
497                 if (size > sc->sc_rdesc->wrsize)
498                         return (ENOBUFS);
499         }
500         buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
501         buf[0] = id;
502         error = uiomove(buf + buf_offset, uio->uio_resid, uio);
503         if (error == 0)
504                 error = hid_write(sc->sc_dev, buf, size);
505         HIDRAW_LOCAL_FREE(local_buf, buf);
506
507         return (error);
508 }
509
510 static int
511 hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
512     struct thread *td)
513 {
514         uint8_t local_buf[HIDRAW_LOCAL_BUFSIZE];
515         void *buf;
516         struct hidraw_softc *sc;
517         struct hidraw_gen_descriptor *hgd;
518         struct hidraw_report_descriptor *hrd;
519         struct hidraw_devinfo *hdi;
520         uint32_t size;
521         int id, len;
522         int error = 0;
523
524         DPRINTFN(2, "cmd=%lx\n", cmd);
525
526         sc = dev->si_drv1;
527         if (sc == NULL)
528                 return (EIO);
529
530         /* fixed-length ioctls handling */
531         switch (cmd) {
532         case FIONBIO:
533                 /* All handled in the upper FS layer. */
534                 return (0);
535
536         case FIOASYNC:
537                 mtx_lock(&sc->sc_mtx);
538                 if (*(int *)addr) {
539                         if (sc->sc_async == NULL) {
540                                 sc->sc_async = td->td_proc;
541                                 DPRINTF("FIOASYNC %p\n", sc->sc_async);
542                         } else
543                                 error = EBUSY;
544                 } else
545                         sc->sc_async = NULL;
546                 mtx_unlock(&sc->sc_mtx);
547                 return (error);
548
549         /* XXX this is not the most general solution. */
550         case TIOCSPGRP:
551                 mtx_lock(&sc->sc_mtx);
552                 if (sc->sc_async == NULL)
553                         error = EINVAL;
554                 else if (*(int *)addr != sc->sc_async->p_pgid)
555                         error = EPERM;
556                 mtx_unlock(&sc->sc_mtx);
557                 return (error);
558
559         case HIDRAW_GET_REPORT_DESC:
560                 if (sc->sc_rdesc->data == NULL || sc->sc_rdesc->len == 0)
561                         return (EOPNOTSUPP);
562                 mtx_lock(&sc->sc_mtx);
563                 sc->sc_state.uhid = true;
564                 mtx_unlock(&sc->sc_mtx);
565                 hgd = (struct hidraw_gen_descriptor *)addr;
566                 if (sc->sc_rdesc->len > hgd->hgd_maxlen) {
567                         size = hgd->hgd_maxlen;
568                 } else {
569                         size = sc->sc_rdesc->len;
570                 }
571                 hgd->hgd_actlen = size;
572                 if (hgd->hgd_data == NULL)
573                         return (0);             /* descriptor length only */
574                 return (copyout(sc->sc_rdesc->data, hgd->hgd_data, size));
575
576
577         case HIDRAW_SET_REPORT_DESC:
578                 if (!(sc->sc_fflags & FWRITE))
579                         return (EPERM);
580
581                 /* check privileges */
582                 error = priv_check(curthread, PRIV_DRIVER);
583                 if (error)
584                         return (error);
585
586                 /* Stop interrupts and clear input report buffer */
587                 mtx_lock(&sc->sc_mtx);
588                 sc->sc_tail = sc->sc_head = 0;
589                 error = hidraw_lock_queue(sc, true);
590                 if (error == 0)
591                         sc->sc_state.quiet = true;
592                 mtx_unlock(&sc->sc_mtx);
593                 if (error != 0)
594                         return(error);
595
596                 hgd = (struct hidraw_gen_descriptor *)addr;
597                 buf = HIDRAW_LOCAL_ALLOC(local_buf, hgd->hgd_maxlen);
598                 copyin(hgd->hgd_data, buf, hgd->hgd_maxlen);
599                 /* Lock newbus around set_report_descr call */
600                 mtx_lock(&Giant);
601                 error = hid_set_report_descr(sc->sc_dev, buf, hgd->hgd_maxlen);
602                 mtx_unlock(&Giant);
603                 HIDRAW_LOCAL_FREE(local_buf, buf);
604
605                 /* Realloc hidraw input queue */
606                 if (error == 0)
607                         sc->sc_q = realloc(sc->sc_q,
608                             sc->sc_rdesc->rdsize * HIDRAW_BUFFER_SIZE,
609                             M_DEVBUF, M_ZERO | M_WAITOK);
610
611                 /* Start interrupts again */
612                 mtx_lock(&sc->sc_mtx);
613                 sc->sc_state.quiet = false;
614                 hidraw_unlock_queue(sc);
615                 mtx_unlock(&sc->sc_mtx);
616                 return (error);
617         case HIDRAW_SET_IMMED:
618                 if (!(sc->sc_fflags & FREAD))
619                         return (EPERM);
620                 if (*(int *)addr) {
621                         /* XXX should read into ibuf, but does it matter? */
622                         size = sc->sc_rdesc->isize;
623                         buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
624                         error = hid_get_report(sc->sc_dev, buf, size, NULL,
625                             HID_INPUT_REPORT, sc->sc_rdesc->iid);
626                         HIDRAW_LOCAL_FREE(local_buf, buf);
627                         if (error)
628                                 return (EOPNOTSUPP);
629
630                         mtx_lock(&sc->sc_mtx);
631                         sc->sc_state.immed = true;
632                         mtx_unlock(&sc->sc_mtx);
633                 } else {
634                         mtx_lock(&sc->sc_mtx);
635                         sc->sc_state.immed = false;
636                         mtx_unlock(&sc->sc_mtx);
637                 }
638                 return (0);
639
640         case HIDRAW_GET_REPORT:
641                 if (!(sc->sc_fflags & FREAD))
642                         return (EPERM);
643                 hgd = (struct hidraw_gen_descriptor *)addr;
644                 switch (hgd->hgd_report_type) {
645                 case HID_INPUT_REPORT:
646                         size = sc->sc_rdesc->isize;
647                         id = sc->sc_rdesc->iid;
648                         break;
649                 case HID_OUTPUT_REPORT:
650                         size = sc->sc_rdesc->osize;
651                         id = sc->sc_rdesc->oid;
652                         break;
653                 case HID_FEATURE_REPORT:
654                         size = sc->sc_rdesc->fsize;
655                         id = sc->sc_rdesc->fid;
656                         break;
657                 default:
658                         return (EINVAL);
659                 }
660                 if (id != 0)
661                         copyin(hgd->hgd_data, &id, 1);
662                 size = MIN(hgd->hgd_maxlen, size);
663                 buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
664                 error = hid_get_report(sc->sc_dev, buf, size, NULL,
665                     hgd->hgd_report_type, id);
666                 if (!error)
667                         error = copyout(buf, hgd->hgd_data, size);
668                 HIDRAW_LOCAL_FREE(local_buf, buf);
669                 return (error);
670
671         case HIDRAW_SET_REPORT:
672                 if (!(sc->sc_fflags & FWRITE))
673                         return (EPERM);
674                 hgd = (struct hidraw_gen_descriptor *)addr;
675                 switch (hgd->hgd_report_type) {
676                 case HID_INPUT_REPORT:
677                         size = sc->sc_rdesc->isize;
678                         id = sc->sc_rdesc->iid;
679                         break;
680                 case HID_OUTPUT_REPORT:
681                         size = sc->sc_rdesc->osize;
682                         id = sc->sc_rdesc->oid;
683                         break;
684                 case HID_FEATURE_REPORT:
685                         size = sc->sc_rdesc->fsize;
686                         id = sc->sc_rdesc->fid;
687                         break;
688                 default:
689                         return (EINVAL);
690                 }
691                 size = MIN(hgd->hgd_maxlen, size);
692                 buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
693                 copyin(hgd->hgd_data, buf, size);
694                 if (id != 0)
695                         id = *(uint8_t *)buf;
696                 error = hid_set_report(sc->sc_dev, buf, size,
697                     hgd->hgd_report_type, id);
698                 HIDRAW_LOCAL_FREE(local_buf, buf);
699                 return (error);
700
701         case HIDRAW_GET_REPORT_ID:
702                 *(int *)addr = 0;       /* XXX: we only support reportid 0? */
703                 return (0);
704
705         case HIDIOCGRDESCSIZE:
706                 *(int *)addr = sc->sc_hw->rdescsize;
707                 return (0);
708
709         case HIDIOCGRDESC:
710                 hrd = *(struct hidraw_report_descriptor **)addr;
711                 error = copyin(&hrd->size, &size, sizeof(uint32_t));
712                 if (error)
713                         return (error);
714                 /*
715                  * HID_MAX_DESCRIPTOR_SIZE-1 is a limit of report descriptor
716                  * size in current Linux implementation.
717                  */
718                 if (size >= HID_MAX_DESCRIPTOR_SIZE)
719                         return (EINVAL);
720                 buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
721                 error = hid_get_rdesc(sc->sc_dev, buf, size);
722                 if (error == 0) {
723                         size = MIN(size, sc->sc_rdesc->len);
724                         error = copyout(buf, hrd->value, size);
725                 }
726                 HIDRAW_LOCAL_FREE(local_buf, buf);
727                 return (error);
728
729         case HIDIOCGRAWINFO:
730                 hdi = (struct hidraw_devinfo *)addr;
731                 hdi->bustype = sc->sc_hw->idBus;
732                 hdi->vendor = sc->sc_hw->idVendor;
733                 hdi->product = sc->sc_hw->idProduct;
734                 return (0);
735         }
736
737         /* variable-length ioctls handling */
738         len = IOCPARM_LEN(cmd);
739         switch (IOCBASECMD(cmd)) {
740         case HIDIOCGRAWNAME(0):
741                 strlcpy(addr, sc->sc_hw->name, len);
742                 return (0);
743
744         case HIDIOCGRAWPHYS(0):
745                 strlcpy(addr, device_get_nameunit(sc->sc_dev), len);
746                 return (0);
747
748         case HIDIOCSFEATURE(0):
749                 if (!(sc->sc_fflags & FWRITE))
750                         return (EPERM);
751                 if (len < 2)
752                         return (EINVAL);
753                 id = *(uint8_t *)addr;
754                 if (id == 0) {
755                         addr = (uint8_t *)addr + 1;
756                         len--;
757                 }
758                 return (hid_set_report(sc->sc_dev, addr, len,
759                     HID_FEATURE_REPORT, id));
760
761         case HIDIOCGFEATURE(0):
762                 if (!(sc->sc_fflags & FREAD))
763                         return (EPERM);
764                 if (len < 2)
765                         return (EINVAL);
766                 id = *(uint8_t *)addr;
767                 if (id == 0) {
768                         addr = (uint8_t *)addr + 1;
769                         len--;
770                 }
771                 return (hid_get_report(sc->sc_dev, addr, len, NULL,
772                     HID_FEATURE_REPORT, id));
773
774         case HIDIOCGRAWUNIQ(0):
775                 strlcpy(addr, sc->sc_hw->serial, len);
776                 return (0);
777         }
778
779         return (EINVAL);
780 }
781
782 static int
783 hidraw_poll(struct cdev *dev, int events, struct thread *td)
784 {
785         struct hidraw_softc *sc;
786         int revents = 0;
787
788         sc = dev->si_drv1;
789         if (sc == NULL)
790                 return (POLLHUP);
791
792         if (events & (POLLOUT | POLLWRNORM) && (sc->sc_fflags & FWRITE))
793                 revents |= events & (POLLOUT | POLLWRNORM);
794         if (events & (POLLIN | POLLRDNORM) && (sc->sc_fflags & FREAD)) {
795                 mtx_lock(&sc->sc_mtx);
796                 if (sc->sc_head != sc->sc_tail)
797                         revents |= events & (POLLIN | POLLRDNORM);
798                 else {
799                         sc->sc_state.sel = true;
800                         selrecord(td, &sc->sc_rsel);
801                 }
802                 mtx_unlock(&sc->sc_mtx);
803         }
804
805         return (revents);
806 }
807
808 static int
809 hidraw_kqfilter(struct cdev *dev, struct knote *kn)
810 {
811         struct hidraw_softc *sc;
812
813         sc = dev->si_drv1;
814         if (sc == NULL)
815                 return (ENXIO);
816
817         switch(kn->kn_filter) {
818         case EVFILT_READ:
819                 if (sc->sc_fflags & FREAD) {
820                         kn->kn_fop = &hidraw_filterops_read;
821                         break;
822                 }
823                 /* FALLTHROUGH */
824         default:
825                 return(EINVAL);
826         }
827         kn->kn_hook = sc;
828
829         knlist_add(&sc->sc_rsel.si_note, kn, 0);
830         return (0);
831 }
832
833 static int
834 hidraw_kqread(struct knote *kn, long hint)
835 {
836         struct hidraw_softc *sc;
837         int ret;
838
839         sc = kn->kn_hook;
840
841         mtx_assert(&sc->sc_mtx, MA_OWNED);
842
843         if (sc->dev->si_drv1 == NULL) {
844                 kn->kn_flags |= EV_EOF;
845                 ret = 1;
846         } else
847                 ret = (sc->sc_head != sc->sc_tail) ? 1 : 0;
848
849         return (ret);
850 }
851
852 static void
853 hidraw_kqdetach(struct knote *kn)
854 {
855         struct hidraw_softc *sc;
856
857         sc = kn->kn_hook;
858         knlist_remove(&sc->sc_rsel.si_note, kn, 0);
859 }
860
861 static void
862 hidraw_notify(struct hidraw_softc *sc)
863 {
864
865         mtx_assert(&sc->sc_mtx, MA_OWNED);
866
867         if (sc->sc_state.aslp) {
868                 sc->sc_state.aslp = false;
869                 DPRINTFN(5, "waking %p\n", &sc->sc_q);
870                 wakeup(&sc->sc_q);
871         }
872         if (sc->sc_state.sel) {
873                 sc->sc_state.sel = false;
874                 selwakeuppri(&sc->sc_rsel, PZERO);
875         }
876         if (sc->sc_async != NULL) {
877                 DPRINTFN(3, "sending SIGIO %p\n", sc->sc_async);
878                 PROC_LOCK(sc->sc_async);
879                 kern_psignal(sc->sc_async, SIGIO);
880                 PROC_UNLOCK(sc->sc_async);
881         }
882         KNOTE_LOCKED(&sc->sc_rsel.si_note, 0);
883 }
884
885 static device_method_t hidraw_methods[] = {
886         /* Device interface */
887         DEVMETHOD(device_identify,      hidraw_identify),
888         DEVMETHOD(device_probe,         hidraw_probe),
889         DEVMETHOD(device_attach,        hidraw_attach),
890         DEVMETHOD(device_detach,        hidraw_detach),
891
892         DEVMETHOD_END
893 };
894
895 static driver_t hidraw_driver = {
896         "hidraw",
897         hidraw_methods,
898         sizeof(struct hidraw_softc)
899 };
900
901 #ifndef HIDRAW_MAKE_UHID_ALIAS
902 devclass_t hidraw_devclass;
903 #endif
904
905 DRIVER_MODULE(hidraw, hidbus, hidraw_driver, hidraw_devclass, NULL, 0);
906 MODULE_DEPEND(hidraw, hidbus, 1, 1, 1);
907 MODULE_DEPEND(hidraw, hid, 1, 1, 1);
908 MODULE_DEPEND(hidraw, usb, 1, 1, 1);
909 MODULE_VERSION(hidraw, 1);