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