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