View | Details | Raw Unified | Return to bug 263995 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/conf/files (+1 lines)
Lines 1812-1817 dev/gpio/gpiobus_if.m optional gpio Link Here
1812
dev/gpio/gpiopps.c		optional gpiopps fdt
1812
dev/gpio/gpiopps.c		optional gpiopps fdt
1813
dev/gpio/ofw_gpiobus.c		optional fdt gpio
1813
dev/gpio/ofw_gpiobus.c		optional fdt gpio
1814
dev/hid/bcm5974.c		optional bcm5974
1814
dev/hid/bcm5974.c		optional bcm5974
1815
dev/hid/fido.c			optional fido
1815
dev/hid/hconf.c			optional hconf
1816
dev/hid/hconf.c			optional hconf
1816
dev/hid/hcons.c			optional hcons
1817
dev/hid/hcons.c			optional hcons
1817
dev/hid/hgame.c			optional hgame
1818
dev/hid/hgame.c			optional hgame
(-)b/sys/dev/hid/fido.c (+582 lines)
Added Link Here
1
/*-
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3
 *
4
 * Copyright (c) 2020, 2022 Vladimir Kondratyev <wulf@FreeBSD.org>
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 */
27
28
#include "opt_hid.h"
29
30
#include <sys/param.h>
31
#ifdef COMPAT_FREEBSD32
32
#include <sys/abi_compat.h>
33
#endif
34
#include <sys/bus.h>
35
#include <sys/conf.h>
36
#include <sys/fcntl.h>
37
#include <sys/filio.h>
38
#include <sys/ioccom.h>
39
#include <sys/kernel.h>
40
#include <sys/lock.h>
41
#include <sys/malloc.h>
42
#include <sys/module.h>
43
#include <sys/mutex.h>
44
#include <sys/poll.h>
45
#include <sys/priv.h>
46
#include <sys/proc.h>
47
#include <sys/selinfo.h>
48
#include <sys/sysctl.h>
49
#include <sys/systm.h>
50
#include <sys/uio.h>
51
52
#include <dev/evdev/input.h>
53
54
#define HID_DEBUG_VAR	fido_debug
55
#include <dev/hid/hid.h>
56
#include <dev/hid/hidbus.h>
57
#include <dev/hid/hidquirk.h>
58
59
#include <dev/usb/usb_ioctl.h>
60
61
#ifdef HID_DEBUG
62
static int fido_debug = 0;
63
static SYSCTL_NODE(_hw_hid, OID_AUTO, fido, CTLFLAG_RW, 0, "Yubico FIDO key");
64
SYSCTL_INT(_hw_hid_fido, OID_AUTO, debug, CTLFLAG_RWTUN,
65
    &fido_debug, 0, "Debug level");
66
#endif
67
68
#define	FIDO_MAKE_UHID_ALIAS
69
#define	GID_U2F			116
70
#define	FIDO_REPORT_SIZE	64
71
#define	FIDO_REPORT_NUM		2
72
73
/* A match on these entries will load hms */
74
static const struct hid_device_id fido_devs[] = {
75
	{ HID_BUS(BUS_USB), HID_TLC(HUP_FIDO, HUF_U2FHID) },
76
};
77
78
struct fido_softc {
79
	device_t sc_dev;		/* base device */
80
	struct cdev *dev;
81
82
	struct mtx sc_mtx;		/* hidbus private mutex */
83
	struct hid_rdesc_info *sc_rdesc;
84
	struct selinfo sc_rsel;
85
	struct {			/* driver state */
86
		bool	open:1;		/* device is open */
87
		bool	aslp:1;		/* waiting for device data in read() */
88
		bool	sel:1;		/* waiting for device data in poll() */
89
		int	reserved:29;
90
	} sc_state;
91
	int sc_fflags;			/* access mode for open lifetime */
92
93
	int sc_head;
94
	int sc_tail;
95
	uint8_t sc_q[FIDO_REPORT_SIZE * FIDO_REPORT_NUM];
96
};
97
98
static d_open_t		fido_open;
99
static d_read_t		fido_read;
100
static d_write_t	fido_write;
101
static d_ioctl_t	fido_ioctl;
102
static d_poll_t		fido_poll;
103
static d_kqfilter_t	fido_kqfilter;
104
105
static d_priv_dtor_t	fido_dtor;
106
107
static struct cdevsw fido_cdevsw = {
108
	.d_version =	D_VERSION,
109
	.d_open =	fido_open,
110
	.d_read =	fido_read,
111
	.d_write =	fido_write,
112
	.d_ioctl =	fido_ioctl,
113
	.d_poll =	fido_poll,
114
	.d_kqfilter =	fido_kqfilter,
115
	.d_name =	"fido",
116
};
117
118
static hid_intr_t	fido_intr;
119
120
static device_probe_t	fido_probe;
121
static device_attach_t	fido_attach;
122
static device_detach_t	fido_detach;
123
124
static int		fido_kqread(struct knote *, long);
125
static void		fido_kqdetach(struct knote *);
126
static void		fido_notify(struct fido_softc *);
127
128
static struct filterops fido_filterops_read = {
129
	.f_isfd =	1,
130
	.f_detach =	fido_kqdetach,
131
	.f_event =	fido_kqread,
132
};
133
134
static int
135
fido_probe(device_t self)
136
{
137
	int error;
138
139
	error = HIDBUS_LOOKUP_DRIVER_INFO(self, fido_devs);
140
	if (error != 0)
141
                return (error);
142
143
	hidbus_set_desc(self, NULL);
144
145
	return (BUS_PROBE_GENERIC);
146
}
147
148
static int
149
fido_attach(device_t self)
150
{
151
	struct fido_softc *sc = device_get_softc(self);
152
	struct hid_device_info *hw = __DECONST(struct hid_device_info *,
153
	    hid_get_device_info(self));
154
	struct make_dev_args mda;
155
	int error;
156
157
	sc->sc_dev = self;
158
	sc->sc_rdesc = hidbus_get_rdesc_info(self);
159
160
	if (sc->sc_rdesc->data == NULL || sc->sc_rdesc->len == 0)
161
		return (ENXIO);
162
163
	mtx_init(&sc->sc_mtx, "fido lock", NULL, MTX_DEF);
164
	knlist_init_mtx(&sc->sc_rsel.si_note, &sc->sc_mtx);
165
166
	make_dev_args_init(&mda);
167
	mda.mda_flags = MAKEDEV_WAITOK;
168
	mda.mda_devsw = &fido_cdevsw;
169
	mda.mda_uid = UID_ROOT;
170
	mda.mda_gid = GID_U2F;
171
	mda.mda_mode = 0660;
172
	mda.mda_si_drv1 = sc;
173
174
	error = make_dev_s(&mda, &sc->dev, "fido%d", device_get_unit(self));
175
	if (error) {
176
		device_printf(self, "Can not create character device\n");
177
		fido_detach(self);
178
		return (error);
179
	}
180
#ifdef FIDO_MAKE_UHID_ALIAS
181
	(void)make_dev_alias(sc->dev, "uhid%d", device_get_unit(self));
182
#endif
183
184
	hid_add_dynamic_quirk(hw, HQ_NO_READAHEAD);
185
186
	hidbus_set_lock(self, &sc->sc_mtx);
187
	hidbus_set_intr(self, fido_intr, sc);
188
189
	return (0);
190
}
191
192
static int
193
fido_detach(device_t self)
194
{
195
	struct fido_softc *sc = device_get_softc(self);
196
197
	DPRINTF("sc=%p\n", sc);
198
199
	if (sc->dev != NULL) {
200
		mtx_lock(&sc->sc_mtx);
201
		sc->dev->si_drv1 = NULL;
202
		/* Wake everyone */
203
		fido_notify(sc);
204
		mtx_unlock(&sc->sc_mtx);
205
		destroy_dev(sc->dev);
206
	}
207
208
	knlist_clear(&sc->sc_rsel.si_note, 0);
209
	knlist_destroy(&sc->sc_rsel.si_note);
210
	seldrain(&sc->sc_rsel);
211
	mtx_destroy(&sc->sc_mtx);
212
213
	return (0);
214
}
215
216
void
217
fido_intr(void *context, void *buf, hid_size_t len)
218
{
219
	struct fido_softc *sc = context;
220
	int next;
221
222
	mtx_assert(&sc->sc_mtx, MA_OWNED);
223
224
	DPRINTFN(5, "len=%d\n", len);
225
	DPRINTFN(5, "data = %*D\n", len, buf, " ");
226
227
	next = (sc->sc_tail + 1) % FIDO_REPORT_NUM;
228
	if (next == sc->sc_head)
229
		return;
230
231
	if (len > FIDO_REPORT_SIZE)
232
		len = FIDO_REPORT_SIZE;
233
234
	bcopy(buf, sc->sc_q + sc->sc_tail * FIDO_REPORT_SIZE, len);
235
236
	/* Make sure we don't process old data */
237
	if (len < FIDO_REPORT_SIZE)
238
		bzero(sc->sc_q + sc->sc_tail * FIDO_REPORT_SIZE + len,
239
		    FIDO_REPORT_SIZE - len);
240
241
	sc->sc_tail = next;
242
243
	fido_notify(sc);
244
}
245
246
static int
247
fido_open(struct cdev *dev, int flag, int mode, struct thread *td)
248
{
249
	struct fido_softc *sc = dev->si_drv1;
250
	int error;
251
252
	if (sc == NULL)
253
		return (ENXIO);
254
255
	DPRINTF("sc=%p\n", sc);
256
257
	mtx_lock(&sc->sc_mtx);
258
	if (sc->sc_state.open) {
259
		mtx_unlock(&sc->sc_mtx);
260
		return (EBUSY);
261
	}
262
	sc->sc_state.open = true;
263
	mtx_unlock(&sc->sc_mtx);
264
265
	error = devfs_set_cdevpriv(sc, fido_dtor);
266
	if (error != 0) {
267
		mtx_lock(&sc->sc_mtx);
268
		sc->sc_state.open = false;
269
		mtx_unlock(&sc->sc_mtx);
270
		return (error);
271
	}
272
273
	/* Set up interrupt pipe. */
274
	sc->sc_head = sc->sc_tail = 0;
275
	sc->sc_fflags = flag;
276
277
	return (0);
278
}
279
280
281
static void
282
fido_dtor(void *data)
283
{
284
	struct fido_softc *sc = data;
285
286
	/* Disable interrupts. */
287
	hidbus_intr_stop(sc->sc_dev);
288
289
	mtx_lock(&sc->sc_mtx);
290
	sc->sc_state.open = false;
291
	mtx_unlock(&sc->sc_mtx);
292
}
293
294
static int
295
fido_read(struct cdev *dev, struct uio *uio, int flag)
296
{
297
	struct fido_softc *sc = dev->si_drv1;
298
	size_t length;
299
	int error;
300
301
	DPRINTFN(1, "\n");
302
303
	if (sc == NULL)
304
		return (EIO);
305
306
	hidbus_intr_start(sc->sc_dev);
307
308
	mtx_lock(&sc->sc_mtx);
309
	if (dev->si_drv1 == NULL) {
310
		error = EIO;
311
		goto exit;
312
	}
313
314
	while (sc->sc_tail == sc->sc_head) {
315
		if (flag & O_NONBLOCK) {
316
			error = EWOULDBLOCK;
317
			goto exit;
318
		}
319
		sc->sc_state.aslp = true;
320
		DPRINTFN(5, "sleep on %p\n", &sc->sc_q);
321
		error = mtx_sleep(&sc->sc_q, &sc->sc_mtx, PZERO | PCATCH,
322
		    "fidord", 0);
323
		DPRINTFN(5, "woke, error=%d\n", error);
324
		if (dev->si_drv1 == NULL)
325
			error = EIO;
326
		if (error) {
327
			sc->sc_state.aslp = false;
328
			goto exit;
329
		}
330
	}
331
332
	while (sc->sc_tail != sc->sc_head && uio->uio_resid > 0) {
333
		length = min(uio->uio_resid, FIDO_REPORT_SIZE);
334
		mtx_unlock(&sc->sc_mtx);
335
336
		/* Copy the data to the user process. */
337
		DPRINTFN(5, "got %lu chars\n", (u_long)length);
338
		error = uiomove(sc->sc_q + sc->sc_head * FIDO_REPORT_SIZE,
339
		    length, uio);
340
341
		mtx_lock(&sc->sc_mtx);
342
		if (error != 0)
343
			goto exit;
344
		/* Remove a small chunk from the input queue. */
345
		sc->sc_head = (sc->sc_head + 1) % FIDO_REPORT_NUM;
346
	}
347
exit:
348
	mtx_unlock(&sc->sc_mtx);
349
350
	return (error);
351
}
352
353
static int
354
fido_write(struct cdev *dev, struct uio *uio, int flag)
355
{
356
	uint8_t buf[FIDO_REPORT_SIZE];
357
	struct fido_softc *sc = dev->si_drv1;
358
	int error;
359
360
	DPRINTFN(1, "\n");
361
362
	if (sc == NULL)
363
		return (EIO);
364
365
	if (uio->uio_resid != FIDO_REPORT_SIZE)
366
		return (EINVAL);
367
	error = uiomove(buf, uio->uio_resid, uio);
368
	if (error == 0)
369
		error = hid_write(sc->sc_dev, buf, FIDO_REPORT_SIZE);
370
371
	return (error);
372
}
373
374
#ifdef COMPAT_FREEBSD32
375
static void
376
update_ugd32(const struct usb_gen_descriptor *ugd,
377
    struct usb_gen_descriptor32 *ugd32)
378
{
379
	/* Don't update hgd_data pointer */
380
	CP(*ugd, *ugd32, ugd_lang_id);
381
	CP(*ugd, *ugd32, ugd_maxlen);
382
	CP(*ugd, *ugd32, ugd_actlen);
383
	CP(*ugd, *ugd32, ugd_offset);
384
	CP(*ugd, *ugd32, ugd_config_index);
385
	CP(*ugd, *ugd32, ugd_string_index);
386
	CP(*ugd, *ugd32, ugd_iface_index);
387
	CP(*ugd, *ugd32, ugd_altif_index);
388
	CP(*ugd, *ugd32, ugd_endpt_index);
389
	CP(*ugd, *ugd32, ugd_report_type);
390
	/* Don't update reserved */
391
}
392
#endif
393
394
static int
395
fido_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
396
    struct thread *td)
397
{
398
#ifdef COMPAT_FREEBSD32
399
	struct usb_gen_descriptor local_ugd;
400
	struct usb_gen_descriptor32 *ugd32 = NULL;
401
#endif
402
	struct fido_softc *sc = dev->si_drv1;
403
	struct usb_gen_descriptor *ugd = (struct usb_gen_descriptor *)addr;
404
	uint32_t size;
405
406
	DPRINTFN(2, "cmd=%lx\n", cmd);
407
408
	if (sc == NULL)
409
		return (EIO);
410
411
#ifdef COMPAT_FREEBSD32
412
	switch (cmd) {
413
	case USB_GET_REPORT_DESC32:
414
		cmd = _IOC_NEWTYPE(cmd, struct usb_gen_descriptor);
415
		ugd32 = (struct usb_gen_descriptor32 *)addr;
416
		ugd = &local_ugd;
417
		PTRIN_CP(*ugd32, *ugd, ugd_data);
418
		CP(*ugd32, *ugd, ugd_lang_id);
419
		CP(*ugd32, *ugd, ugd_maxlen);
420
		CP(*ugd32, *ugd, ugd_actlen);
421
		CP(*ugd32, *ugd, ugd_offset);
422
		CP(*ugd32, *ugd, ugd_config_index);
423
		CP(*ugd32, *ugd, ugd_string_index);
424
		CP(*ugd32, *ugd, ugd_iface_index);
425
		CP(*ugd32, *ugd, ugd_altif_index);
426
		CP(*ugd32, *ugd, ugd_endpt_index);
427
		CP(*ugd32, *ugd, ugd_report_type);
428
		/* Don't copy reserved */
429
		break;
430
	}
431
#endif
432
433
	/* fixed-length ioctls handling */
434
	switch (cmd) {
435
	case FIONBIO:
436
		/* All handled in the upper FS layer. */
437
		return (0);
438
439
	case USB_GET_REPORT_DESC:
440
		if (sc->sc_rdesc->data == NULL || sc->sc_rdesc->len == 0)
441
			return (EOPNOTSUPP);
442
		if (sc->sc_rdesc->len > ugd->ugd_maxlen) {
443
			size = ugd->ugd_maxlen;
444
		} else {
445
			size = sc->sc_rdesc->len;
446
		}
447
		ugd->ugd_actlen = size;
448
#ifdef COMPAT_FREEBSD32
449
		if (ugd32 != NULL)
450
			update_ugd32(ugd, ugd32);
451
#endif
452
		if (ugd->ugd_data == NULL)
453
			return (0);		/* descriptor length only */
454
455
		return (copyout(sc->sc_rdesc->data, ugd->ugd_data, size));
456
457
	case USB_GET_DEVICEINFO:
458
		return(hid_ioctl(
459
		    sc->sc_dev, USB_GET_DEVICEINFO, (uintptr_t)addr));
460
	}
461
462
	return (ENOTTY);
463
}
464
465
static int
466
fido_poll(struct cdev *dev, int events, struct thread *td)
467
{
468
	struct fido_softc *sc = dev->si_drv1;
469
	int revents = 0;
470
471
	if (sc == NULL)
472
                return (POLLHUP);
473
474
	if (events & (POLLOUT | POLLWRNORM) && (sc->sc_fflags & FWRITE))
475
		revents |= events & (POLLOUT | POLLWRNORM);
476
	if (events & (POLLIN | POLLRDNORM) && (sc->sc_fflags & FREAD)) {
477
		hidbus_intr_start(sc->sc_dev);
478
		mtx_lock(&sc->sc_mtx);
479
		if (sc->sc_head != sc->sc_tail)
480
			revents |= events & (POLLIN | POLLRDNORM);
481
		else {
482
			sc->sc_state.sel = true;
483
			selrecord(td, &sc->sc_rsel);
484
		}
485
		mtx_unlock(&sc->sc_mtx);
486
	}
487
488
	return (revents);
489
}
490
491
static int
492
fido_kqfilter(struct cdev *dev, struct knote *kn)
493
{
494
	struct fido_softc *sc = dev->si_drv1;
495
496
	if (sc == NULL)
497
		return (ENXIO);
498
499
	switch(kn->kn_filter) {
500
	case EVFILT_READ:
501
		if (sc->sc_fflags & FREAD) {
502
			hidbus_intr_start(sc->sc_dev);
503
			kn->kn_fop = &fido_filterops_read;
504
			break;
505
		}
506
		/* FALLTHROUGH */
507
	default:
508
		return(EINVAL);
509
	}
510
	kn->kn_hook = sc;
511
512
	knlist_add(&sc->sc_rsel.si_note, kn, 0);
513
	return (0);
514
}
515
516
static int
517
fido_kqread(struct knote *kn, long hint)
518
{
519
	struct fido_softc *sc = kn->kn_hook;
520
	int ret;
521
522
	mtx_assert(&sc->sc_mtx, MA_OWNED);
523
524
	if (sc->dev->si_drv1 == NULL) {
525
		kn->kn_flags |= EV_EOF;
526
		ret = 1;
527
	} else
528
		ret = (sc->sc_head != sc->sc_tail) ? 1 : 0;
529
530
	return (ret);
531
}
532
533
static void
534
fido_kqdetach(struct knote *kn)
535
{
536
	struct fido_softc *sc = kn->kn_hook;
537
538
	knlist_remove(&sc->sc_rsel.si_note, kn, 0);
539
}
540
541
static void
542
fido_notify(struct fido_softc *sc)
543
{
544
	mtx_assert(&sc->sc_mtx, MA_OWNED);
545
546
	if (sc->sc_state.aslp) {
547
		sc->sc_state.aslp = false;
548
		DPRINTFN(5, "waking %p\n", &sc->sc_q);
549
		wakeup(&sc->sc_q);
550
	}
551
	if (sc->sc_state.sel) {
552
		sc->sc_state.sel = false;
553
		selwakeuppri(&sc->sc_rsel, PZERO);
554
	}
555
	KNOTE_LOCKED(&sc->sc_rsel.si_note, 0);
556
}
557
558
static device_method_t fido_methods[] = {
559
	/* Device interface */
560
	DEVMETHOD(device_probe,		fido_probe),
561
	DEVMETHOD(device_attach,	fido_attach),
562
	DEVMETHOD(device_detach,	fido_detach),
563
564
	DEVMETHOD_END
565
};
566
567
static driver_t fido_driver = {
568
#ifdef FIDO_MAKE_UHID_ALIAS
569
	"uhid",
570
#else
571
	"fido",
572
#endif
573
	fido_methods,
574
	sizeof(struct fido_softc)
575
};
576
577
DRIVER_MODULE(fido, hidbus, fido_driver, NULL, NULL);
578
MODULE_DEPEND(fido, hidbus, 1, 1, 1);
579
MODULE_DEPEND(fido, hid, 1, 1, 1);
580
MODULE_DEPEND(fido, usb, 1, 1, 1);
581
MODULE_VERSION(fido, 1);
582
HID_PNP_INFO(fido_devs);
(-)b/sys/dev/hid/hid.h (+4 lines)
Lines 58-63 Link Here
58
#define	HUP_SCALE		0x008c
58
#define	HUP_SCALE		0x008c
59
#define	HUP_CAMERA_CONTROL	0x0090
59
#define	HUP_CAMERA_CONTROL	0x0090
60
#define	HUP_ARCADE		0x0091
60
#define	HUP_ARCADE		0x0091
61
#define	HUP_FIDO		0xf1d0
61
#define	HUP_MICROSOFT		0xff00
62
#define	HUP_MICROSOFT		0xff00
62
63
63
/* Usages, generic desktop */
64
/* Usages, generic desktop */
Lines 162-167 Link Here
162
#define	HUC_HEADPHONE		0x0005
163
#define	HUC_HEADPHONE		0x0005
163
#define	HUC_AC_PAN		0x0238
164
#define	HUC_AC_PAN		0x0238
164
165
166
/* Usages, FIDO */
167
#define	HUF_U2FHID		0x0001
168
165
#define	HID_USAGE2(p,u)		(((p) << 16) | (u))
169
#define	HID_USAGE2(p,u)		(((p) << 16) | (u))
166
#define	HID_GET_USAGE(u)	((u) & 0xffff)
170
#define	HID_GET_USAGE(u)	((u) & 0xffff)
167
#define	HID_GET_USAGE_PAGE(u)	(((u) >> 16) & 0xffff)
171
#define	HID_GET_USAGE_PAGE(u)	(((u) >> 16) & 0xffff)
(-)b/sys/dev/hid/hidbus.c (-26 / +15 lines)
Lines 68-74 struct hidbus_ivars { Link Here
68
	struct mtx			*mtx;		/* child intr mtx */
68
	struct mtx			*mtx;		/* child intr mtx */
69
	hid_intr_t			*intr_handler;	/* executed under mtx*/
69
	hid_intr_t			*intr_handler;	/* executed under mtx*/
70
	void				*intr_ctx;
70
	void				*intr_ctx;
71
	unsigned int			refcnt;		/* protected by mtx */
71
	bool				active;		/* protected by mtx */
72
	struct epoch_context		epoch_ctx;
72
	struct epoch_context		epoch_ctx;
73
	CK_STAILQ_ENTRY(hidbus_ivars)	link;
73
	CK_STAILQ_ENTRY(hidbus_ivars)	link;
74
};
74
};
Lines 403-409 hidbus_child_detached(device_t bus, device_t child) Link Here
403
	struct hidbus_softc *sc = device_get_softc(bus);
403
	struct hidbus_softc *sc = device_get_softc(bus);
404
	struct hidbus_ivars *tlc = device_get_ivars(child);
404
	struct hidbus_ivars *tlc = device_get_ivars(child);
405
405
406
	KASSERT(tlc->refcnt == 0, ("Child device is running"));
406
	KASSERT(!tlc->active, ("Child device is running"));
407
	tlc->mtx = &sc->mtx;
407
	tlc->mtx = &sc->mtx;
408
	tlc->intr_handler = NULL;
408
	tlc->intr_handler = NULL;
409
	tlc->flags &= ~HIDBUS_FLAG_CAN_POLL;
409
	tlc->flags &= ~HIDBUS_FLAG_CAN_POLL;
Lines 428-434 hidbus_child_deleted(device_t bus, device_t child) Link Here
428
	struct hidbus_ivars *tlc = device_get_ivars(child);
428
	struct hidbus_ivars *tlc = device_get_ivars(child);
429
429
430
	sx_xlock(&sc->sx);
430
	sx_xlock(&sc->sx);
431
	KASSERT(tlc->refcnt == 0, ("Child device is running"));
431
	KASSERT(!tlc->active, ("Child device is running"));
432
	CK_STAILQ_REMOVE(&sc->tlcs, tlc, hidbus_ivars, link);
432
	CK_STAILQ_REMOVE(&sc->tlcs, tlc, hidbus_ivars, link);
433
	sx_unlock(&sc->sx);
433
	sx_unlock(&sc->sx);
434
	epoch_call(INPUT_EPOCH, hidbus_ivar_dtor, &tlc->epoch_ctx);
434
	epoch_call(INPUT_EPOCH, hidbus_ivar_dtor, &tlc->epoch_ctx);
Lines 579-585 hidbus_intr(void *context, void *buf, hid_size_t len) Link Here
579
	if (!HID_IN_POLLING_MODE())
579
	if (!HID_IN_POLLING_MODE())
580
		epoch_enter_preempt(INPUT_EPOCH, &et);
580
		epoch_enter_preempt(INPUT_EPOCH, &et);
581
	CK_STAILQ_FOREACH(tlc, &sc->tlcs, link) {
581
	CK_STAILQ_FOREACH(tlc, &sc->tlcs, link) {
582
		if (tlc->refcnt == 0 || tlc->intr_handler == NULL)
582
		if (!tlc->active || tlc->intr_handler == NULL)
583
			continue;
583
			continue;
584
		if (HID_IN_POLLING_MODE()) {
584
		if (HID_IN_POLLING_MODE()) {
585
			if ((tlc->flags & HIDBUS_FLAG_CAN_POLL) != 0)
585
			if ((tlc->flags & HIDBUS_FLAG_CAN_POLL) != 0)
Lines 609-629 hidbus_intr_start(device_t child) Link Here
609
	device_t bus = device_get_parent(child);
609
	device_t bus = device_get_parent(child);
610
	struct hidbus_softc *sc = device_get_softc(bus);
610
	struct hidbus_softc *sc = device_get_softc(bus);
611
	struct hidbus_ivars *ivar = device_get_ivars(child);
611
	struct hidbus_ivars *ivar = device_get_ivars(child);
612
	struct hidbus_ivars *tlc;
613
	bool refcnted = false;
614
	int error;
612
	int error;
615
613
616
	if (sx_xlock_sig(&sc->sx) != 0)
614
	if (sx_xlock_sig(&sc->sx) != 0)
617
		return (EINTR);
615
		return (EINTR);
618
	CK_STAILQ_FOREACH(tlc, &sc->tlcs, link) {
616
	mtx_lock(ivar->mtx);
619
		refcnted |= (tlc->refcnt != 0);
617
	ivar->active = true;
620
		if (tlc == ivar) {
618
	mtx_unlock(ivar->mtx);
621
			mtx_lock(tlc->mtx);
619
	error = HID_INTR_START(device_get_parent(bus));
622
			++tlc->refcnt;
623
			mtx_unlock(tlc->mtx);
624
		}
625
	}
626
	error = refcnted ? 0 : HID_INTR_START(device_get_parent(bus));
627
	sx_unlock(&sc->sx);
620
	sx_unlock(&sc->sx);
628
621
629
	return (error);
622
	return (error);
Lines 636-656 hidbus_intr_stop(device_t child) Link Here
636
	struct hidbus_softc *sc = device_get_softc(bus);
629
	struct hidbus_softc *sc = device_get_softc(bus);
637
	struct hidbus_ivars *ivar = device_get_ivars(child);
630
	struct hidbus_ivars *ivar = device_get_ivars(child);
638
	struct hidbus_ivars *tlc;
631
	struct hidbus_ivars *tlc;
639
	bool refcnted = false;
632
	bool active = false;
640
	int error;
633
	int error;
641
634
642
	if (sx_xlock_sig(&sc->sx) != 0)
635
	if (sx_xlock_sig(&sc->sx) != 0)
643
		return (EINTR);
636
		return (EINTR);
644
	CK_STAILQ_FOREACH(tlc, &sc->tlcs, link) {
637
	mtx_lock(ivar->mtx);
645
		if (tlc == ivar) {
638
	ivar->active = false;
646
			mtx_lock(tlc->mtx);
639
	mtx_unlock(ivar->mtx);
647
			MPASS(tlc->refcnt != 0);
640
	CK_STAILQ_FOREACH(tlc, &sc->tlcs, link)
648
			--tlc->refcnt;
641
		active |= tlc->active;
649
			mtx_unlock(tlc->mtx);
642
	error = active ? 0 : HID_INTR_STOP(device_get_parent(bus));
650
		}
651
		refcnted |= (tlc->refcnt != 0);
652
	}
653
	error = refcnted ? 0 : HID_INTR_STOP(device_get_parent(bus));
654
	sx_unlock(&sc->sx);
643
	sx_unlock(&sc->sx);
655
644
656
	return (error);
645
	return (error);
(-)b/sys/dev/hid/hidquirk.h (+1 lines)
Lines 51-56 Link Here
51
	HQ(IS_XBOX360GP), 	/* device is XBox 360 GamePad */	\
51
	HQ(IS_XBOX360GP), 	/* device is XBox 360 GamePad */	\
52
	HQ(NOWRITE),		/* device does not support writes */	\
52
	HQ(NOWRITE),		/* device does not support writes */	\
53
	HQ(IICHID_SAMPLING),	/* IIC backend runs in sampling mode */	\
53
	HQ(IICHID_SAMPLING),	/* IIC backend runs in sampling mode */	\
54
	HQ(NO_READAHEAD),	/* Disable interrupt after one report */\
54
									\
55
									\
55
	/* Various quirks */						\
56
	/* Various quirks */						\
56
	HQ(HID_IGNORE),		/* device should be ignored by hid class */ \
57
	HQ(HID_IGNORE),		/* device should be ignored by hid class */ \
(-)b/sys/dev/hid/hidraw.c (-2 / +4 lines)
Lines 379-386 hidraw_open(struct cdev *dev, int flag, int mode, struct thread *td) Link Here
379
	sc->sc_head = sc->sc_tail = 0;
379
	sc->sc_head = sc->sc_tail = 0;
380
	sc->sc_fflags = flag;
380
	sc->sc_fflags = flag;
381
381
382
	hidbus_intr_start(sc->sc_dev);
383
384
	return (0);
382
	return (0);
385
}
383
}
386
384
Lines 418-423 hidraw_read(struct cdev *dev, struct uio *uio, int flag) Link Here
418
	if (sc == NULL)
416
	if (sc == NULL)
419
		return (EIO);
417
		return (EIO);
420
418
419
	hidbus_intr_start(sc->sc_dev);
420
421
	mtx_lock(&sc->sc_mtx);
421
	mtx_lock(&sc->sc_mtx);
422
	error = dev->si_drv1 == NULL ? EIO : hidraw_lock_queue(sc, false);
422
	error = dev->si_drv1 == NULL ? EIO : hidraw_lock_queue(sc, false);
423
	if (error != 0) {
423
	if (error != 0) {
Lines 882-887 hidraw_poll(struct cdev *dev, int events, struct thread *td) Link Here
882
	if (events & (POLLOUT | POLLWRNORM) && (sc->sc_fflags & FWRITE))
882
	if (events & (POLLOUT | POLLWRNORM) && (sc->sc_fflags & FWRITE))
883
		revents |= events & (POLLOUT | POLLWRNORM);
883
		revents |= events & (POLLOUT | POLLWRNORM);
884
	if (events & (POLLIN | POLLRDNORM) && (sc->sc_fflags & FREAD)) {
884
	if (events & (POLLIN | POLLRDNORM) && (sc->sc_fflags & FREAD)) {
885
		hidbus_intr_start(sc->sc_dev);
885
		mtx_lock(&sc->sc_mtx);
886
		mtx_lock(&sc->sc_mtx);
886
		if (sc->sc_head != sc->sc_tail)
887
		if (sc->sc_head != sc->sc_tail)
887
			revents |= events & (POLLIN | POLLRDNORM);
888
			revents |= events & (POLLIN | POLLRDNORM);
Lines 907-912 hidraw_kqfilter(struct cdev *dev, struct knote *kn) Link Here
907
	switch(kn->kn_filter) {
908
	switch(kn->kn_filter) {
908
	case EVFILT_READ:
909
	case EVFILT_READ:
909
		if (sc->sc_fflags & FREAD) {
910
		if (sc->sc_fflags & FREAD) {
911
			hidbus_intr_start(sc->sc_dev);
910
			kn->kn_fop = &hidraw_filterops_read;
912
			kn->kn_fop = &hidraw_filterops_read;
911
			break;
913
			break;
912
		}
914
		}
(-)b/sys/dev/hid/ietp.c (-8 / +23 lines)
Lines 105-110 struct ietp_softc { Link Here
105
	device_t		dev;
105
	device_t		dev;
106
106
107
	struct evdev_dev	*evdev;
107
	struct evdev_dev	*evdev;
108
	bool			open;
108
	uint8_t			report_id;
109
	uint8_t			report_id;
109
	hid_size_t		report_len;
110
	hid_size_t		report_len;
110
111
Lines 208-220 static const struct evdev_methods ietp_evdev_methods = { Link Here
208
static int
209
static int
209
ietp_ev_open(struct evdev_dev *evdev)
210
ietp_ev_open(struct evdev_dev *evdev)
210
{
211
{
211
	return (hidbus_intr_start(evdev_get_softc(evdev)));
212
	struct ietp_softc *sc = evdev_get_softc(evdev);
213
	int error;
214
215
	error = hidbus_intr_start(sc->dev);
216
	if (error == 0)
217
		sc->open = true;
218
	return (error);
212
}
219
}
213
220
214
static int
221
static int
215
ietp_ev_close(struct evdev_dev *evdev)
222
ietp_ev_close(struct evdev_dev *evdev)
216
{
223
{
217
	return (hidbus_intr_stop(evdev_get_softc(evdev)));
224
	struct ietp_softc *sc = evdev_get_softc(evdev);
225
	int error;
226
227
	error = hidbus_intr_stop(sc->dev);
228
	if (error == 0)
229
		sc->open = false;
230
	return (error);
218
}
231
}
219
232
220
static int
233
static int
Lines 266-272 ietp_attach(struct ietp_softc *sc) Link Here
266
	evdev_set_id(sc->evdev, hw->idBus, hw->idVendor, hw->idProduct,
279
	evdev_set_id(sc->evdev, hw->idBus, hw->idVendor, hw->idProduct,
267
	    hw->idVersion);
280
	    hw->idVersion);
268
	evdev_set_serial(sc->evdev, hw->serial);
281
	evdev_set_serial(sc->evdev, hw->serial);
269
	evdev_set_methods(sc->evdev, sc->dev, &ietp_evdev_methods);
282
	evdev_set_methods(sc->evdev, sc, &ietp_evdev_methods);
270
	evdev_set_flag(sc->evdev, EVDEV_FLAG_MT_STCOMPAT);
283
	evdev_set_flag(sc->evdev, EVDEV_FLAG_MT_STCOMPAT);
271
	evdev_set_flag(sc->evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */
284
	evdev_set_flag(sc->evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */
272
285
Lines 541-551 ietp_iic_set_absolute_mode(device_t dev, bool enable) Link Here
541
	 * Some ASUS touchpads need to be powered on to enter absolute mode.
554
	 * Some ASUS touchpads need to be powered on to enter absolute mode.
542
	 */
555
	 */
543
	require_wakeup = false;
556
	require_wakeup = false;
544
	for (i = 0; i < nitems(special_fw); i++) {
557
	if (!sc->open) {
545
		if (sc->ic_type == special_fw[i].ic_type &&
558
		for (i = 0; i < nitems(special_fw); i++) {
546
		    sc->product_id == special_fw[i].product_id) {
559
			if (sc->ic_type == special_fw[i].ic_type &&
547
			require_wakeup = true;
560
			    sc->product_id == special_fw[i].product_id) {
548
			break;
561
				require_wakeup = true;
562
				break;
563
			}
549
		}
564
		}
550
	}
565
	}
551
566
(-)b/sys/dev/iicbus/iichid.c (-1 / +2 lines)
Lines 838-844 iichid_intr_start(device_t dev) Link Here
838
838
839
	sc = device_get_softc(dev);
839
	sc = device_get_softc(dev);
840
	DPRINTF(sc, "iichid device open\n");
840
	DPRINTF(sc, "iichid device open\n");
841
	iichid_set_power_state(sc, IICHID_PS_ON, IICHID_PS_NULL);
841
	if (!sc->open)
842
		iichid_set_power_state(sc, IICHID_PS_ON, IICHID_PS_NULL);
842
843
843
	return (0);
844
	return (0);
844
}
845
}
(-)b/sys/dev/usb/input/uhid.c (-1 / +2 lines)
Lines 687-697 static int Link Here
687
uhid_ioctl_post(struct usb_fifo *fifo, u_long cmd, void *addr,
687
uhid_ioctl_post(struct usb_fifo *fifo, u_long cmd, void *addr,
688
    int fflags)
688
    int fflags)
689
{
689
{
690
	struct uhid_softc *sc = usb_fifo_softc(fifo);
690
	int error;
691
	int error;
691
692
692
	switch (cmd) {
693
	switch (cmd) {
693
	case USB_GET_DEVICEINFO:
694
	case USB_GET_DEVICEINFO:
694
		error = ugen_fill_deviceinfo(fifo, addr);
695
		error = ugen_fill_deviceinfo(sc->sc_udev, addr);
695
		break;
696
		break;
696
697
697
	default:
698
	default:
(-)b/sys/dev/usb/input/usbhid.c (-1 / +8 lines)
Lines 69-74 __FBSDID("$FreeBSD$"); Link Here
69
#include <dev/usb/usbhid.h>
69
#include <dev/usb/usbhid.h>
70
#include <dev/usb/usb_core.h>
70
#include <dev/usb/usb_core.h>
71
#include <dev/usb/usb_ioctl.h>
71
#include <dev/usb/usb_ioctl.h>
72
#include <dev/usb/usb_generic.h>
72
#include <dev/usb/usb_util.h>
73
#include <dev/usb/usb_util.h>
73
74
74
#define	USB_DEBUG_VAR usbhid_debug
75
#define	USB_DEBUG_VAR usbhid_debug
Lines 117-122 struct usbhid_xfer_ctx { Link Here
117
	void *cb_ctx;
118
	void *cb_ctx;
118
	int waiters;
119
	int waiters;
119
	bool influx;
120
	bool influx;
121
	bool no_readahead;
120
};
122
};
121
123
122
struct usbhid_softc {
124
struct usbhid_softc {
Lines 275-281 usbhid_intr_handler_cb(struct usbhid_xfer_ctx *xfer_ctx) Link Here
275
	sc->sc_intr_handler(sc->sc_intr_ctx, xfer_ctx->buf,
277
	sc->sc_intr_handler(sc->sc_intr_ctx, xfer_ctx->buf,
276
	    xfer_ctx->req.intr.actlen);
278
	    xfer_ctx->req.intr.actlen);
277
279
278
	return (0);
280
	return (xfer_ctx->no_readahead ? ECANCELED : 0);
279
}
281
}
280
282
281
static int
283
static int
Lines 433-438 usbhid_intr_start(device_t dev) Link Here
433
		.cb = usbhid_intr_handler_cb,
435
		.cb = usbhid_intr_handler_cb,
434
		.cb_ctx = sc,
436
		.cb_ctx = sc,
435
		.buf = sc->sc_intr_buf,
437
		.buf = sc->sc_intr_buf,
438
		.no_readahead = hid_test_quirk(&sc->sc_hw, HQ_NO_READAHEAD),
436
	};
439
	};
437
	sc->sc_xfer_ctx[POLL_XFER(USBHID_INTR_IN_DT)] = (struct usbhid_xfer_ctx) {
440
	sc->sc_xfer_ctx[POLL_XFER(USBHID_INTR_IN_DT)] = (struct usbhid_xfer_ctx) {
438
		.req.intr.maxlen =
441
		.req.intr.maxlen =
Lines 703-708 usbhid_ioctl(device_t dev, unsigned long cmd, uintptr_t data) Link Here
703
		if (error == 0)
706
		if (error == 0)
704
			ucr->ucr_actlen = UGETW(req.ctrl.wLength);
707
			ucr->ucr_actlen = UGETW(req.ctrl.wLength);
705
		break;
708
		break;
709
	case USB_GET_DEVICEINFO:
710
		error = ugen_fill_deviceinfo(sc->sc_udev,
711
		    (struct usb_device_info *)data);
712
		break;
706
	default:
713
	default:
707
		error = EINVAL;
714
		error = EINVAL;
708
	}
715
	}
(-)b/sys/dev/usb/usb_generic.c (-5 / +2 lines)
Lines 829-841 ugen_get_iface_driver(struct usb_fifo *f, struct usb_gen_descriptor *ugd) Link Here
829
 * Else: Failure
829
 * Else: Failure
830
 *------------------------------------------------------------------------*/
830
 *------------------------------------------------------------------------*/
831
int
831
int
832
ugen_fill_deviceinfo(struct usb_fifo *f, struct usb_device_info *di)
832
ugen_fill_deviceinfo(struct usb_device *udev, struct usb_device_info *di)
833
{
833
{
834
	struct usb_device *udev;
835
	struct usb_device *hub;
834
	struct usb_device *hub;
836
835
837
	udev = f->udev;
838
839
	bzero(di, sizeof(di[0]));
836
	bzero(di, sizeof(di[0]));
840
837
841
	di->udi_bus = device_get_unit(udev->bus->bdev);
838
	di->udi_bus = device_get_unit(udev->bus->bdev);
Lines 2307-2313 ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags) Link Here
2307
2304
2308
	case USB_DEVICEINFO:
2305
	case USB_DEVICEINFO:
2309
	case USB_GET_DEVICEINFO:
2306
	case USB_GET_DEVICEINFO:
2310
		error = ugen_fill_deviceinfo(f, addr);
2307
		error = ugen_fill_deviceinfo(f->udev, addr);
2311
		break;
2308
		break;
2312
2309
2313
	case USB_DEVICESTATS:
2310
	case USB_DEVICESTATS:
(-)b/sys/dev/usb/usb_generic.h (-1 / +2 lines)
Lines 31-36 Link Here
31
31
32
extern struct usb_fifo_methods usb_ugen_methods;
32
extern struct usb_fifo_methods usb_ugen_methods;
33
int	ugen_do_request(struct usb_fifo *f, struct usb_ctl_request *ur);
33
int	ugen_do_request(struct usb_fifo *f, struct usb_ctl_request *ur);
34
int	ugen_fill_deviceinfo(struct usb_fifo *f, struct usb_device_info *di);
34
int	ugen_fill_deviceinfo(struct usb_device *udev,
35
	    struct usb_device_info *di);
35
36
36
#endif					/* _USB_GENERIC_H_ */
37
#endif					/* _USB_GENERIC_H_ */
(-)b/sys/modules/hid/Makefile (+1 lines)
Lines 9-14 SUBDIR = \ Link Here
9
9
10
SUBDIR += \
10
SUBDIR += \
11
	bcm5974 \
11
	bcm5974 \
12
	fido \
12
	hconf \
13
	hconf \
13
	hcons \
14
	hcons \
14
	hgame \
15
	hgame \
(-)b/sys/modules/hid/fido/Makefile (+10 lines)
Added Link Here
1
# $FreeBSD$
2
3
.PATH: ${SRCTOP}/sys/dev/hid
4
5
KMOD=	fido
6
SRCS=	fido.c
7
SRCS+=	opt_hid.h
8
SRCS+=	bus_if.h device_if.h
9
10
.include <bsd.kmod.mk>

Return to bug 263995