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 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
70static int hidraw_debug = 0;
71static SYSCTL_NODE(_hw_hid, OID_AUTO, hidraw, CTLFLAG_RW, 0,
72    "HID raw interface");
73SYSCTL_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
88struct 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
120struct 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
144static d_open_t		hidraw_open;
145static d_read_t		hidraw_read;
146static d_write_t	hidraw_write;
147static d_ioctl_t	hidraw_ioctl;
148static d_poll_t		hidraw_poll;
149static d_kqfilter_t	hidraw_kqfilter;
150
151static d_priv_dtor_t	hidraw_dtor;
152
153static 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
164static hid_intr_t	hidraw_intr;
165
166static device_identify_t hidraw_identify;
167static device_probe_t	hidraw_probe;
168static device_attach_t	hidraw_attach;
169static device_detach_t	hidraw_detach;
170
171static int		hidraw_kqread(struct knote *, long);
172static void		hidraw_kqdetach(struct knote *);
173static void		hidraw_notify(struct hidraw_softc *);
174
175static struct filterops hidraw_filterops_read = {
176	.f_isfd =	1,
177	.f_detach =	hidraw_kqdetach,
178	.f_event =	hidraw_kqread,
179};
180
181static void
182hidraw_identify(driver_t *driver, device_t parent)
183{
184	device_t child;
185
186	if (device_find_child(parent, "hidraw", -1) == 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
194static int
195hidraw_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
206static int
207hidraw_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
248static int
249hidraw_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
272void
273hidraw_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
298static inline int
299hidraw_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
327static inline void
328hidraw_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
339static int
340hidraw_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
385static void
386hidraw_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
406static int
407hidraw_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	}
479exit:
480	hidraw_unlock_queue(sc);
481	mtx_unlock(&sc->sc_mtx);
482
483	return (error);
484}
485
486static int
487hidraw_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
537static void
538update_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
556static int
557hidraw_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	int id, len;
574	int error = 0;
575
576	DPRINTFN(2, "cmd=%lx\n", cmd);
577
578	sc = dev->si_drv1;
579	if (sc == NULL)
580		return (EIO);
581
582	hgd = (struct hidraw_gen_descriptor *)addr;
583
584#ifdef COMPAT_FREEBSD32
585	switch (cmd) {
586	case HIDRAW_GET_REPORT_DESC32:
587	case HIDRAW_GET_REPORT32:
588	case HIDRAW_SET_REPORT_DESC32:
589	case HIDRAW_SET_REPORT32:
590		cmd = _IOC_NEWTYPE(cmd, struct hidraw_gen_descriptor);
591		hgd32 = (struct hidraw_gen_descriptor32 *)addr;
592		hgd = &local_hgd;
593		PTRIN_CP(*hgd32, *hgd, hgd_data);
594		CP(*hgd32, *hgd, hgd_lang_id);
595		CP(*hgd32, *hgd, hgd_maxlen);
596		CP(*hgd32, *hgd, hgd_actlen);
597		CP(*hgd32, *hgd, hgd_offset);
598		CP(*hgd32, *hgd, hgd_config_index);
599		CP(*hgd32, *hgd, hgd_string_index);
600		CP(*hgd32, *hgd, hgd_iface_index);
601		CP(*hgd32, *hgd, hgd_altif_index);
602		CP(*hgd32, *hgd, hgd_endpt_index);
603		CP(*hgd32, *hgd, hgd_report_type);
604		/* Don't copy reserved */
605		break;
606	}
607#endif
608
609	/* fixed-length ioctls handling */
610	switch (cmd) {
611	case FIONBIO:
612		/* All handled in the upper FS layer. */
613		return (0);
614
615	case FIOASYNC:
616		mtx_lock(&sc->sc_mtx);
617		if (*(int *)addr) {
618			if (sc->sc_async == NULL) {
619				sc->sc_async = td->td_proc;
620				DPRINTF("FIOASYNC %p\n", sc->sc_async);
621			} else
622				error = EBUSY;
623		} else
624			sc->sc_async = NULL;
625		mtx_unlock(&sc->sc_mtx);
626		return (error);
627
628	/* XXX this is not the most general solution. */
629	case TIOCSPGRP:
630		mtx_lock(&sc->sc_mtx);
631		if (sc->sc_async == NULL)
632			error = EINVAL;
633		else if (*(int *)addr != sc->sc_async->p_pgid)
634			error = EPERM;
635		mtx_unlock(&sc->sc_mtx);
636		return (error);
637
638	case HIDRAW_GET_REPORT_DESC:
639		if (sc->sc_rdesc->data == NULL || sc->sc_rdesc->len == 0)
640			return (EOPNOTSUPP);
641		mtx_lock(&sc->sc_mtx);
642		sc->sc_state.uhid = true;
643		mtx_unlock(&sc->sc_mtx);
644		if (sc->sc_rdesc->len > hgd->hgd_maxlen) {
645			size = hgd->hgd_maxlen;
646		} else {
647			size = sc->sc_rdesc->len;
648		}
649		hgd->hgd_actlen = size;
650#ifdef COMPAT_FREEBSD32
651		if (hgd32 != NULL)
652			update_hgd32(hgd, hgd32);
653#endif
654		if (hgd->hgd_data == NULL)
655			return (0);		/* descriptor length only */
656
657		return (copyout(sc->sc_rdesc->data, hgd->hgd_data, size));
658
659
660	case HIDRAW_SET_REPORT_DESC:
661		if (!(sc->sc_fflags & FWRITE))
662			return (EPERM);
663
664		/* check privileges */
665		error = priv_check(curthread, PRIV_DRIVER);
666		if (error)
667			return (error);
668
669		/* Stop interrupts and clear input report buffer */
670		mtx_lock(&sc->sc_mtx);
671		sc->sc_tail = sc->sc_head = 0;
672		error = hidraw_lock_queue(sc, true);
673		if (error == 0)
674			sc->sc_state.quiet = true;
675		mtx_unlock(&sc->sc_mtx);
676		if (error != 0)
677			return (error);
678
679		buf = HIDRAW_LOCAL_ALLOC(local_buf, hgd->hgd_maxlen);
680		error = copyin(hgd->hgd_data, buf, hgd->hgd_maxlen);
681		if (error == 0) {
682			bus_topo_lock();
683			error = hid_set_report_descr(sc->sc_dev, buf,
684			    hgd->hgd_maxlen);
685			bus_topo_unlock();
686		}
687		HIDRAW_LOCAL_FREE(local_buf, buf);
688
689		/* Realloc hidraw input queue */
690		if (error == 0)
691			sc->sc_q = realloc(sc->sc_q,
692			    sc->sc_rdesc->rdsize * HIDRAW_BUFFER_SIZE,
693			    M_DEVBUF, M_ZERO | M_WAITOK);
694
695		/* Start interrupts again */
696		mtx_lock(&sc->sc_mtx);
697		sc->sc_state.quiet = false;
698		hidraw_unlock_queue(sc);
699		mtx_unlock(&sc->sc_mtx);
700		return (error);
701	case HIDRAW_SET_IMMED:
702		if (!(sc->sc_fflags & FREAD))
703			return (EPERM);
704		if (*(int *)addr) {
705			/* XXX should read into ibuf, but does it matter? */
706			size = sc->sc_rdesc->isize;
707			buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
708			error = hid_get_report(sc->sc_dev, buf, size, NULL,
709			    HID_INPUT_REPORT, sc->sc_rdesc->iid);
710			HIDRAW_LOCAL_FREE(local_buf, buf);
711			if (error)
712				return (EOPNOTSUPP);
713
714			mtx_lock(&sc->sc_mtx);
715			sc->sc_state.immed = true;
716			mtx_unlock(&sc->sc_mtx);
717		} else {
718			mtx_lock(&sc->sc_mtx);
719			sc->sc_state.immed = false;
720			mtx_unlock(&sc->sc_mtx);
721		}
722		return (0);
723
724	case HIDRAW_GET_REPORT:
725		if (!(sc->sc_fflags & FREAD))
726			return (EPERM);
727		switch (hgd->hgd_report_type) {
728		case HID_INPUT_REPORT:
729			size = sc->sc_rdesc->isize;
730			id = sc->sc_rdesc->iid;
731			break;
732		case HID_OUTPUT_REPORT:
733			size = sc->sc_rdesc->osize;
734			id = sc->sc_rdesc->oid;
735			break;
736		case HID_FEATURE_REPORT:
737			size = sc->sc_rdesc->fsize;
738			id = sc->sc_rdesc->fid;
739			break;
740		default:
741			return (EINVAL);
742		}
743		if (id != 0) {
744			error = copyin(hgd->hgd_data, &id, 1);
745			if (error != 0)
746				return (error);
747		}
748		size = MIN(hgd->hgd_maxlen, size);
749		buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
750		error = hid_get_report(sc->sc_dev, buf, size, NULL,
751		    hgd->hgd_report_type, id);
752		if (!error)
753			error = copyout(buf, hgd->hgd_data, size);
754		HIDRAW_LOCAL_FREE(local_buf, buf);
755#ifdef COMPAT_FREEBSD32
756		/*
757		 * HIDRAW_GET_REPORT is declared _IOWR, but hgd is not written
758		 * so we don't call update_hgd32().
759		 */
760#endif
761		return (error);
762
763	case HIDRAW_SET_REPORT:
764		if (!(sc->sc_fflags & FWRITE))
765			return (EPERM);
766		switch (hgd->hgd_report_type) {
767		case HID_INPUT_REPORT:
768			size = sc->sc_rdesc->isize;
769			id = sc->sc_rdesc->iid;
770			break;
771		case HID_OUTPUT_REPORT:
772			size = sc->sc_rdesc->osize;
773			id = sc->sc_rdesc->oid;
774			break;
775		case HID_FEATURE_REPORT:
776			size = sc->sc_rdesc->fsize;
777			id = sc->sc_rdesc->fid;
778			break;
779		default:
780			return (EINVAL);
781		}
782		size = MIN(hgd->hgd_maxlen, size);
783		buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
784		error = copyin(hgd->hgd_data, buf, size);
785		if (error == 0) {
786			if (id != 0)
787				id = *(uint8_t *)buf;
788			error = hid_set_report(sc->sc_dev, buf, size,
789			    hgd->hgd_report_type, id);
790		}
791		HIDRAW_LOCAL_FREE(local_buf, buf);
792		return (error);
793
794	case HIDRAW_GET_REPORT_ID:
795		*(int *)addr = 0;	/* XXX: we only support reportid 0? */
796		return (0);
797
798	case HIDRAW_GET_DEVICEINFO:
799		hdi = (struct hidraw_device_info *)addr;
800		bzero(hdi, sizeof(struct hidraw_device_info));
801		hdi->hdi_product = sc->sc_hw->idProduct;
802		hdi->hdi_vendor = sc->sc_hw->idVendor;
803		hdi->hdi_version = sc->sc_hw->idVersion;
804		hdi->hdi_bustype = sc->sc_hw->idBus;
805		strlcpy(hdi->hdi_name, sc->sc_hw->name,
806		    sizeof(hdi->hdi_name));
807		strlcpy(hdi->hdi_phys, device_get_nameunit(sc->sc_dev),
808		    sizeof(hdi->hdi_phys));
809		strlcpy(hdi->hdi_uniq, sc->sc_hw->serial,
810		    sizeof(hdi->hdi_uniq));
811		snprintf(hdi->hdi_release, sizeof(hdi->hdi_release), "%x.%02x",
812		    sc->sc_hw->idVersion >> 8, sc->sc_hw->idVersion & 0xff);
813		return(0);
814
815	case HIDIOCGRDESCSIZE:
816		*(int *)addr = sc->sc_hw->rdescsize;
817		return (0);
818
819	case HIDIOCGRDESC:
820		hrd = *(struct hidraw_report_descriptor **)addr;
821		error = copyin(&hrd->size, &size, sizeof(uint32_t));
822		if (error)
823			return (error);
824		/*
825		 * HID_MAX_DESCRIPTOR_SIZE-1 is a limit of report descriptor
826		 * size in current Linux implementation.
827		 */
828		if (size >= HID_MAX_DESCRIPTOR_SIZE)
829			return (EINVAL);
830		buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
831		error = hid_get_rdesc(sc->sc_dev, buf, size);
832		if (error == 0) {
833			size = MIN(size, sc->sc_rdesc->len);
834			error = copyout(buf, hrd->value, size);
835		}
836		HIDRAW_LOCAL_FREE(local_buf, buf);
837		return (error);
838
839	case HIDIOCGRAWINFO:
840		hd = (struct hidraw_devinfo *)addr;
841		hd->bustype = sc->sc_hw->idBus;
842		hd->vendor = sc->sc_hw->idVendor;
843		hd->product = sc->sc_hw->idProduct;
844		return (0);
845	}
846
847	/* variable-length ioctls handling */
848	len = IOCPARM_LEN(cmd);
849	switch (IOCBASECMD(cmd)) {
850	case HIDIOCGRAWNAME(0):
851		strlcpy(addr, sc->sc_hw->name, len);
852		td->td_retval[0] = min(strlen(sc->sc_hw->name) + 1, len);
853		return (0);
854
855	case HIDIOCGRAWPHYS(0):
856		devname = device_get_nameunit(sc->sc_dev);
857		strlcpy(addr, devname, len);
858		td->td_retval[0] = min(strlen(devname) + 1, len);
859		return (0);
860
861	case HIDIOCSFEATURE(0):
862		if (!(sc->sc_fflags & FWRITE))
863			return (EPERM);
864		if (len < 2)
865			return (EINVAL);
866		id = *(uint8_t *)addr;
867		if (id == 0) {
868			addr = (uint8_t *)addr + 1;
869			len--;
870		}
871		return (hid_set_report(sc->sc_dev, addr, len,
872		    HID_FEATURE_REPORT, id));
873
874	case HIDIOCGFEATURE(0):
875		if (!(sc->sc_fflags & FREAD))
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		return (hid_get_report(sc->sc_dev, addr, len, NULL,
885		    HID_FEATURE_REPORT, id));
886
887	case HIDIOCGRAWUNIQ(0):
888		strlcpy(addr, sc->sc_hw->serial, len);
889		td->td_retval[0] = min(strlen(sc->sc_hw->serial) + 1, len);
890		return (0);
891	}
892
893	return (EINVAL);
894}
895
896static int
897hidraw_poll(struct cdev *dev, int events, struct thread *td)
898{
899	struct hidraw_softc *sc;
900	int revents = 0;
901
902	sc = dev->si_drv1;
903	if (sc == NULL)
904		return (POLLHUP);
905
906	if (events & (POLLOUT | POLLWRNORM) && (sc->sc_fflags & FWRITE))
907		revents |= events & (POLLOUT | POLLWRNORM);
908	if (events & (POLLIN | POLLRDNORM) && (sc->sc_fflags & FREAD)) {
909		mtx_lock(&sc->sc_mtx);
910		if (sc->sc_head != sc->sc_tail)
911			revents |= events & (POLLIN | POLLRDNORM);
912		else {
913			sc->sc_state.sel = true;
914			selrecord(td, &sc->sc_rsel);
915		}
916		mtx_unlock(&sc->sc_mtx);
917	}
918
919	return (revents);
920}
921
922static int
923hidraw_kqfilter(struct cdev *dev, struct knote *kn)
924{
925	struct hidraw_softc *sc;
926
927	sc = dev->si_drv1;
928	if (sc == NULL)
929		return (ENXIO);
930
931	switch(kn->kn_filter) {
932	case EVFILT_READ:
933		if (sc->sc_fflags & FREAD) {
934			kn->kn_fop = &hidraw_filterops_read;
935			break;
936		}
937		/* FALLTHROUGH */
938	default:
939		return(EINVAL);
940	}
941	kn->kn_hook = sc;
942
943	knlist_add(&sc->sc_rsel.si_note, kn, 0);
944	return (0);
945}
946
947static int
948hidraw_kqread(struct knote *kn, long hint)
949{
950	struct hidraw_softc *sc;
951	int ret;
952
953	sc = kn->kn_hook;
954
955	mtx_assert(&sc->sc_mtx, MA_OWNED);
956
957	if (sc->dev->si_drv1 == NULL) {
958		kn->kn_flags |= EV_EOF;
959		ret = 1;
960	} else
961		ret = (sc->sc_head != sc->sc_tail) ? 1 : 0;
962
963	return (ret);
964}
965
966static void
967hidraw_kqdetach(struct knote *kn)
968{
969	struct hidraw_softc *sc;
970
971	sc = kn->kn_hook;
972	knlist_remove(&sc->sc_rsel.si_note, kn, 0);
973}
974
975static void
976hidraw_notify(struct hidraw_softc *sc)
977{
978
979	mtx_assert(&sc->sc_mtx, MA_OWNED);
980
981	if (sc->sc_state.aslp) {
982		sc->sc_state.aslp = false;
983		DPRINTFN(5, "waking %p\n", &sc->sc_q);
984		wakeup(&sc->sc_q);
985	}
986	if (sc->sc_state.sel) {
987		sc->sc_state.sel = false;
988		selwakeuppri(&sc->sc_rsel, PZERO);
989	}
990	if (sc->sc_async != NULL) {
991		DPRINTFN(3, "sending SIGIO %p\n", sc->sc_async);
992		PROC_LOCK(sc->sc_async);
993		kern_psignal(sc->sc_async, SIGIO);
994		PROC_UNLOCK(sc->sc_async);
995	}
996	KNOTE_LOCKED(&sc->sc_rsel.si_note, 0);
997}
998
999static device_method_t hidraw_methods[] = {
1000	/* Device interface */
1001	DEVMETHOD(device_identify,	hidraw_identify),
1002	DEVMETHOD(device_probe,		hidraw_probe),
1003	DEVMETHOD(device_attach,	hidraw_attach),
1004	DEVMETHOD(device_detach,	hidraw_detach),
1005
1006	DEVMETHOD_END
1007};
1008
1009static driver_t hidraw_driver = {
1010	"hidraw",
1011	hidraw_methods,
1012	sizeof(struct hidraw_softc)
1013};
1014
1015DRIVER_MODULE(hidraw, hidbus, hidraw_driver, NULL, NULL);
1016MODULE_DEPEND(hidraw, hidbus, 1, 1, 1);
1017MODULE_DEPEND(hidraw, hid, 1, 1, 1);
1018MODULE_VERSION(hidraw, 1);
1019