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