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