Home | History | Annotate | Line # | Download | only in usb
uhid.c revision 1.114.2.1
      1  1.114.2.1   thorpej /*	$NetBSD: uhid.c,v 1.114.2.1 2020/12/14 14:38:09 thorpej Exp $	*/
      2        1.1  augustss 
      3        1.1  augustss /*
      4       1.88       mrg  * Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc.
      5        1.1  augustss  * All rights reserved.
      6        1.1  augustss  *
      7        1.6  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8       1.38  augustss  * by Lennart Augustsson (lennart (at) augustsson.net) at
      9       1.88       mrg  * Carlstedt Research & Technology and Matthew R. Green (mrg (at) eterna.com.au).
     10        1.1  augustss  *
     11        1.1  augustss  * Redistribution and use in source and binary forms, with or without
     12        1.1  augustss  * modification, are permitted provided that the following conditions
     13        1.1  augustss  * are met:
     14        1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     15        1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     16        1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     17        1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     18        1.1  augustss  *    documentation and/or other materials provided with the distribution.
     19        1.1  augustss  *
     20        1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21        1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22        1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23        1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24        1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25        1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26        1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27        1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28        1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29        1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30        1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     31        1.1  augustss  */
     32        1.1  augustss 
     33       1.15  augustss /*
     34       1.57  augustss  * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
     35       1.15  augustss  */
     36       1.46     lukem 
     37       1.46     lukem #include <sys/cdefs.h>
     38  1.114.2.1   thorpej __KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.114.2.1 2020/12/14 14:38:09 thorpej Exp $");
     39       1.73     pavel 
     40       1.89  christos #ifdef _KERNEL_OPT
     41       1.73     pavel #include "opt_compat_netbsd.h"
     42       1.96  jakllsch #include "opt_usb.h"
     43       1.89  christos #endif
     44        1.1  augustss 
     45        1.1  augustss #include <sys/param.h>
     46  1.114.2.1   thorpej #include <sys/types.h>
     47  1.114.2.1   thorpej 
     48  1.114.2.1   thorpej #include <sys/atomic.h>
     49  1.114.2.1   thorpej #include <sys/compat_stub.h>
     50  1.114.2.1   thorpej #include <sys/conf.h>
     51  1.114.2.1   thorpej #include <sys/device.h>
     52  1.114.2.1   thorpej #include <sys/file.h>
     53  1.114.2.1   thorpej #include <sys/intr.h>
     54  1.114.2.1   thorpej #include <sys/ioctl.h>
     55        1.1  augustss #include <sys/kernel.h>
     56       1.95     skrll #include <sys/kmem.h>
     57  1.114.2.1   thorpej #include <sys/poll.h>
     58  1.114.2.1   thorpej #include <sys/proc.h>
     59  1.114.2.1   thorpej #include <sys/select.h>
     60       1.37  augustss #include <sys/signalvar.h>
     61  1.114.2.1   thorpej #include <sys/systm.h>
     62        1.1  augustss #include <sys/tty.h>
     63        1.1  augustss #include <sys/vnode.h>
     64        1.1  augustss 
     65        1.1  augustss #include <dev/usb/usb.h>
     66        1.1  augustss #include <dev/usb/usbhid.h>
     67        1.1  augustss 
     68       1.42  augustss #include <dev/usb/usbdevs.h>
     69        1.1  augustss #include <dev/usb/usbdi.h>
     70        1.1  augustss #include <dev/usb/usbdi_util.h>
     71        1.1  augustss #include <dev/usb/usb_quirks.h>
     72      1.101    bouyer #include <dev/hid/hid.h>
     73        1.1  augustss 
     74       1.47  augustss #include <dev/usb/uhidev.h>
     75       1.42  augustss 
     76      1.108       mrg #include "ioconf.h"
     77      1.108       mrg 
     78       1.26  augustss #ifdef UHID_DEBUG
     79       1.84    dyoung #define DPRINTF(x)	if (uhiddebug) printf x
     80       1.84    dyoung #define DPRINTFN(n,x)	if (uhiddebug>(n)) printf x
     81        1.1  augustss int	uhiddebug = 0;
     82        1.1  augustss #else
     83        1.1  augustss #define DPRINTF(x)
     84        1.1  augustss #define DPRINTFN(n,x)
     85        1.1  augustss #endif
     86        1.1  augustss 
     87        1.1  augustss struct uhid_softc {
     88       1.47  augustss 	struct uhidev sc_hdev;
     89        1.1  augustss 
     90  1.114.2.1   thorpej 	kmutex_t sc_lock;
     91       1.88       mrg 	kcondvar_t sc_cv;
     92       1.88       mrg 	kcondvar_t sc_detach_cv;
     93       1.88       mrg 
     94        1.1  augustss 	int sc_isize;
     95        1.1  augustss 	int sc_osize;
     96        1.2  augustss 	int sc_fsize;
     97        1.1  augustss 
     98       1.33  augustss 	u_char *sc_obuf;
     99        1.1  augustss 
    100       1.93       mrg 	struct clist sc_q;	/* protected by sc_lock */
    101        1.1  augustss 	struct selinfo sc_rsel;
    102       1.84    dyoung 	proc_t *sc_async;	/* process that wants SIGIO */
    103       1.80        ad 	void *sc_sih;
    104  1.114.2.1   thorpej 	volatile uint32_t sc_state;	/* driver state */
    105       1.47  augustss #define UHID_IMMED	0x02	/* return read data immediately */
    106       1.18  augustss 
    107       1.18  augustss 	int sc_refcnt;
    108      1.112  christos 	int sc_raw;
    109  1.114.2.1   thorpej 	u_char sc_open;
    110       1.18  augustss 	u_char sc_dying;
    111        1.1  augustss };
    112        1.1  augustss 
    113        1.1  augustss #define	UHIDUNIT(dev)	(minor(dev))
    114        1.1  augustss #define	UHID_CHUNK	128	/* chunk size for read */
    115        1.1  augustss #define	UHID_BSIZE	1020	/* buffer size */
    116        1.1  augustss 
    117      1.109      maxv static dev_type_open(uhidopen);
    118      1.109      maxv static dev_type_close(uhidclose);
    119      1.109      maxv static dev_type_read(uhidread);
    120      1.109      maxv static dev_type_write(uhidwrite);
    121      1.109      maxv static dev_type_ioctl(uhidioctl);
    122      1.109      maxv static dev_type_poll(uhidpoll);
    123      1.109      maxv static dev_type_kqfilter(uhidkqfilter);
    124       1.53   gehenna 
    125       1.53   gehenna const struct cdevsw uhid_cdevsw = {
    126       1.90  dholland 	.d_open = uhidopen,
    127       1.90  dholland 	.d_close = uhidclose,
    128       1.90  dholland 	.d_read = uhidread,
    129       1.90  dholland 	.d_write = uhidwrite,
    130       1.90  dholland 	.d_ioctl = uhidioctl,
    131       1.90  dholland 	.d_stop = nostop,
    132       1.90  dholland 	.d_tty = notty,
    133       1.90  dholland 	.d_poll = uhidpoll,
    134       1.90  dholland 	.d_mmap = nommap,
    135       1.90  dholland 	.d_kqfilter = uhidkqfilter,
    136       1.92  dholland 	.d_discard = nodiscard,
    137       1.93       mrg 	.d_flag = D_OTHER
    138       1.53   gehenna };
    139       1.19  augustss 
    140       1.95     skrll Static void uhid_intr(struct uhidev *, void *, u_int);
    141       1.18  augustss 
    142       1.95     skrll Static int uhid_do_read(struct uhid_softc *, struct uio *, int);
    143       1.95     skrll Static int uhid_do_write(struct uhid_softc *, struct uio *, int);
    144       1.76  christos Static int uhid_do_ioctl(struct uhid_softc*, u_long, void *, int, struct lwp *);
    145        1.1  augustss 
    146      1.109      maxv static int	uhid_match(device_t, cfdata_t, void *);
    147      1.109      maxv static void	uhid_attach(device_t, device_t, void *);
    148      1.109      maxv static int	uhid_detach(device_t, int);
    149      1.109      maxv static int	uhid_activate(device_t, enum devact);
    150      1.108       mrg 
    151       1.98   msaitoh CFATTACH_DECL_NEW(uhid, sizeof(struct uhid_softc), uhid_match, uhid_attach,
    152       1.98   msaitoh     uhid_detach, uhid_activate);
    153        1.1  augustss 
    154      1.109      maxv static int
    155       1.82      cube uhid_match(device_t parent, cfdata_t match, void *aux)
    156        1.1  augustss {
    157       1.66      tron #ifdef UHID_DEBUG
    158       1.47  augustss 	struct uhidev_attach_arg *uha = aux;
    159       1.66      tron #endif
    160       1.47  augustss 
    161       1.47  augustss 	DPRINTF(("uhid_match: report=%d\n", uha->reportid));
    162       1.47  augustss 
    163       1.65  augustss 	if (match->cf_flags & 1)
    164       1.93       mrg 		return UMATCH_HIGHEST;
    165       1.67  augustss 	else
    166       1.93       mrg 		return UMATCH_IFACECLASS_GENERIC;
    167        1.1  augustss }
    168        1.1  augustss 
    169      1.109      maxv static void
    170       1.82      cube uhid_attach(device_t parent, device_t self, void *aux)
    171        1.1  augustss {
    172       1.82      cube 	struct uhid_softc *sc = device_private(self);
    173       1.47  augustss 	struct uhidev_attach_arg *uha = aux;
    174       1.47  augustss 	int size, repid;
    175        1.1  augustss 	void *desc;
    176       1.52  augustss 
    177       1.82      cube 	sc->sc_hdev.sc_dev = self;
    178       1.79     rmind 	selinit(&sc->sc_rsel);
    179       1.47  augustss 	sc->sc_hdev.sc_intr = uhid_intr;
    180       1.47  augustss 	sc->sc_hdev.sc_parent = uha->parent;
    181       1.47  augustss 	sc->sc_hdev.sc_report_id = uha->reportid;
    182       1.47  augustss 
    183       1.47  augustss 	uhidev_get_report_desc(uha->parent, &desc, &size);
    184       1.47  augustss 	repid = uha->reportid;
    185       1.47  augustss 	sc->sc_isize = hid_report_size(desc, size, hid_input,   repid);
    186       1.47  augustss 	sc->sc_osize = hid_report_size(desc, size, hid_output,  repid);
    187       1.47  augustss 	sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid);
    188      1.112  christos 	sc->sc_raw =  hid_is_collection(desc, size, uha->reportid,
    189      1.112  christos 	    HID_USAGE2(HUP_FIDO, HUF_U2FHID));
    190        1.1  augustss 
    191       1.82      cube 	aprint_naive("\n");
    192       1.82      cube 	aprint_normal(": input=%d, output=%d, feature=%d\n",
    193       1.47  augustss 	       sc->sc_isize, sc->sc_osize, sc->sc_fsize);
    194       1.32  augustss 
    195       1.95     skrll 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
    196       1.88       mrg 	cv_init(&sc->sc_cv, "uhidrea");
    197       1.88       mrg 	cv_init(&sc->sc_detach_cv, "uhiddet");
    198       1.88       mrg 
    199       1.78  drochner 	if (!pmf_device_register(self, NULL, NULL))
    200       1.78  drochner 		aprint_error_dev(self, "couldn't establish power handler\n");
    201       1.78  drochner 
    202       1.84    dyoung 	return;
    203        1.1  augustss }
    204        1.1  augustss 
    205      1.109      maxv static int
    206       1.84    dyoung uhid_activate(device_t self, enum devact act)
    207       1.18  augustss {
    208       1.82      cube 	struct uhid_softc *sc = device_private(self);
    209       1.21  augustss 
    210       1.21  augustss 	switch (act) {
    211       1.21  augustss 	case DVACT_DEACTIVATE:
    212       1.21  augustss 		sc->sc_dying = 1;
    213       1.83    dyoung 		return 0;
    214       1.83    dyoung 	default:
    215       1.83    dyoung 		return EOPNOTSUPP;
    216       1.21  augustss 	}
    217       1.12  augustss }
    218       1.12  augustss 
    219      1.109      maxv static int
    220       1.82      cube uhid_detach(device_t self, int flags)
    221        1.1  augustss {
    222       1.82      cube 	struct uhid_softc *sc = device_private(self);
    223       1.18  augustss 	int maj, mn;
    224       1.18  augustss 
    225       1.18  augustss 	DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags));
    226        1.3  augustss 
    227  1.114.2.1   thorpej 	/* Prevent new I/O operations, and interrupt any pending reads.  */
    228  1.114.2.1   thorpej 	mutex_enter(&sc->sc_lock);
    229       1.18  augustss 	sc->sc_dying = 1;
    230  1.114.2.1   thorpej 	cv_broadcast(&sc->sc_cv);
    231  1.114.2.1   thorpej 	mutex_exit(&sc->sc_lock);
    232       1.18  augustss 
    233  1.114.2.1   thorpej 	/* Interrupt any pending uhidev_write.  */
    234  1.114.2.1   thorpej 	uhidev_stop(&sc->sc_hdev);
    235       1.91  christos 
    236  1.114.2.1   thorpej 	/* Wait for I/O operations to complete.  */
    237       1.88       mrg 	mutex_enter(&sc->sc_lock);
    238  1.114.2.1   thorpej 	while (sc->sc_refcnt) {
    239  1.114.2.1   thorpej 		DPRINTF(("%s: open=%d refcnt=%d\n", __func__,
    240  1.114.2.1   thorpej 			sc->sc_open, sc->sc_refcnt));
    241  1.114.2.1   thorpej 		cv_wait(&sc->sc_detach_cv, &sc->sc_lock);
    242       1.18  augustss 	}
    243       1.88       mrg 	mutex_exit(&sc->sc_lock);
    244       1.18  augustss 
    245  1.114.2.1   thorpej 	pmf_device_deregister(self);
    246  1.114.2.1   thorpej 
    247       1.18  augustss 	/* locate the major number */
    248       1.53   gehenna 	maj = cdevsw_lookup_major(&uhid_cdevsw);
    249       1.18  augustss 
    250       1.18  augustss 	/* Nuke the vnodes for any open instances (calls close). */
    251       1.69   thorpej 	mn = device_unit(self);
    252       1.18  augustss 	vdevgone(maj, mn, mn, VCHR);
    253       1.47  augustss 
    254  1.114.2.1   thorpej 	/*
    255  1.114.2.1   thorpej 	 * Wait for close to finish.
    256  1.114.2.1   thorpej 	 *
    257  1.114.2.1   thorpej 	 * XXX I assumed that vdevgone would synchronously call close,
    258  1.114.2.1   thorpej 	 * and not return before it has completed, but empirically the
    259  1.114.2.1   thorpej 	 * assertion of sc->sc_open == 0 below fires if we don't wait
    260  1.114.2.1   thorpej 	 * here.  Someone^TM should carefully examine vdevgone to
    261  1.114.2.1   thorpej 	 * ascertain what it guarantees, and audit all other users of
    262  1.114.2.1   thorpej 	 * it accordingly.
    263  1.114.2.1   thorpej 	 */
    264  1.114.2.1   thorpej 	mutex_enter(&sc->sc_lock);
    265  1.114.2.1   thorpej 	while (sc->sc_open) {
    266  1.114.2.1   thorpej 		DPRINTF(("%s: open=%d\n", __func__, sc->sc_open));
    267  1.114.2.1   thorpej 		cv_wait(&sc->sc_detach_cv, &sc->sc_lock);
    268  1.114.2.1   thorpej 	}
    269  1.114.2.1   thorpej 	mutex_exit(&sc->sc_lock);
    270  1.114.2.1   thorpej 
    271  1.114.2.1   thorpej 	KASSERT(sc->sc_open == 0);
    272  1.114.2.1   thorpej 	KASSERT(sc->sc_refcnt == 0);
    273  1.114.2.1   thorpej 
    274       1.88       mrg 	cv_destroy(&sc->sc_cv);
    275       1.88       mrg 	cv_destroy(&sc->sc_detach_cv);
    276       1.88       mrg 	mutex_destroy(&sc->sc_lock);
    277       1.79     rmind 	seldestroy(&sc->sc_rsel);
    278       1.18  augustss 
    279       1.93       mrg 	return 0;
    280        1.1  augustss }
    281        1.1  augustss 
    282        1.1  augustss void
    283       1.47  augustss uhid_intr(struct uhidev *addr, void *data, u_int len)
    284        1.1  augustss {
    285       1.47  augustss 	struct uhid_softc *sc = (struct uhid_softc *)addr;
    286        1.1  augustss 
    287       1.33  augustss #ifdef UHID_DEBUG
    288       1.33  augustss 	if (uhiddebug > 5) {
    289       1.95     skrll 		uint32_t i;
    290       1.52  augustss 
    291       1.33  augustss 		DPRINTF(("uhid_intr: data ="));
    292       1.47  augustss 		for (i = 0; i < len; i++)
    293       1.51  augustss 			DPRINTF((" %02x", ((u_char *)data)[i]));
    294       1.33  augustss 		DPRINTF(("\n"));
    295       1.33  augustss 	}
    296       1.33  augustss #endif
    297        1.1  augustss 
    298       1.88       mrg 	mutex_enter(&sc->sc_lock);
    299       1.47  augustss 	(void)b_to_q(data, len, &sc->sc_q);
    300       1.52  augustss 
    301  1.114.2.1   thorpej 	DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q));
    302  1.114.2.1   thorpej 	cv_broadcast(&sc->sc_cv);
    303  1.114.2.1   thorpej 	selnotify(&sc->sc_rsel, 0, NOTE_SUBMIT);
    304  1.114.2.1   thorpej 	if (atomic_load_relaxed(&sc->sc_async) != NULL) {
    305  1.114.2.1   thorpej 		mutex_enter(&proc_lock);
    306  1.114.2.1   thorpej 		if (sc->sc_async != NULL) {
    307  1.114.2.1   thorpej 			DPRINTFN(3, ("uhid_intr: sending SIGIO to %jd\n",
    308  1.114.2.1   thorpej 				(intmax_t)sc->sc_async->p_pid));
    309  1.114.2.1   thorpej 			psignal(sc->sc_async, SIGIO);
    310  1.114.2.1   thorpej 		}
    311  1.114.2.1   thorpej 		mutex_exit(&proc_lock);
    312       1.37  augustss 	}
    313       1.88       mrg 	mutex_exit(&sc->sc_lock);
    314        1.1  augustss }
    315        1.1  augustss 
    316      1.109      maxv static int
    317       1.88       mrg uhidopen(dev_t dev, int flag, int mode, struct lwp *l)
    318        1.1  augustss {
    319       1.25  augustss 	struct uhid_softc *sc;
    320       1.47  augustss 	int error;
    321       1.25  augustss 
    322       1.84    dyoung 	sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
    323       1.84    dyoung 	if (sc == NULL)
    324       1.84    dyoung 		return ENXIO;
    325        1.1  augustss 
    326       1.18  augustss 	DPRINTF(("uhidopen: sc=%p\n", sc));
    327        1.1  augustss 
    328       1.93       mrg 	/*
    329  1.114.2.1   thorpej 	 * Try to open.  If dying, or if already open (or opening),
    330  1.114.2.1   thorpej 	 * fail -- opens are exclusive.
    331       1.93       mrg 	 */
    332  1.114.2.1   thorpej 	mutex_enter(&sc->sc_lock);
    333  1.114.2.1   thorpej 	if (sc->sc_dying) {
    334  1.114.2.1   thorpej 		mutex_exit(&sc->sc_lock);
    335  1.114.2.1   thorpej 		return ENXIO;
    336  1.114.2.1   thorpej 	}
    337  1.114.2.1   thorpej 	if (sc->sc_open) {
    338      1.107       mrg 		mutex_exit(&sc->sc_lock);
    339       1.93       mrg 		return EBUSY;
    340       1.93       mrg 	}
    341  1.114.2.1   thorpej 	sc->sc_open = 1;
    342  1.114.2.1   thorpej 	atomic_store_relaxed(&sc->sc_state, 0);
    343      1.107       mrg 	mutex_exit(&sc->sc_lock);
    344      1.107       mrg 
    345  1.114.2.1   thorpej 	/* uhid interrupts aren't enabled yet, so setup sc_q now */
    346       1.93       mrg 	if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) {
    347  1.114.2.1   thorpej 		error = ENOMEM;
    348  1.114.2.1   thorpej 		goto fail0;
    349       1.93       mrg 	}
    350       1.93       mrg 
    351  1.114.2.1   thorpej 	/* Allocate an output buffer if needed.  */
    352       1.97   mlelstv 	if (sc->sc_osize > 0)
    353       1.97   mlelstv 		sc->sc_obuf = kmem_alloc(sc->sc_osize, KM_SLEEP);
    354       1.97   mlelstv 	else
    355       1.97   mlelstv 		sc->sc_obuf = NULL;
    356       1.88       mrg 
    357  1.114.2.1   thorpej 	/* Paranoia: reset SIGIO before enabling interrputs.  */
    358      1.114        ad 	mutex_enter(&proc_lock);
    359  1.114.2.1   thorpej 	atomic_store_relaxed(&sc->sc_async, NULL);
    360      1.114        ad 	mutex_exit(&proc_lock);
    361       1.37  augustss 
    362  1.114.2.1   thorpej 	/* Open the uhidev -- after this point we can get interrupts.  */
    363  1.114.2.1   thorpej 	error = uhidev_open(&sc->sc_hdev);
    364  1.114.2.1   thorpej 	if (error)
    365  1.114.2.1   thorpej 		goto fail1;
    366  1.114.2.1   thorpej 
    367  1.114.2.1   thorpej 	/* We are open for business.  */
    368  1.114.2.1   thorpej 	mutex_enter(&sc->sc_lock);
    369  1.114.2.1   thorpej 	sc->sc_open = 2;
    370  1.114.2.1   thorpej 	mutex_exit(&sc->sc_lock);
    371  1.114.2.1   thorpej 
    372       1.93       mrg 	return 0;
    373  1.114.2.1   thorpej 
    374  1.114.2.1   thorpej fail2: __unused
    375  1.114.2.1   thorpej 	mutex_enter(&sc->sc_lock);
    376  1.114.2.1   thorpej 	KASSERT(sc->sc_open == 2);
    377  1.114.2.1   thorpej 	sc->sc_open = 1;
    378  1.114.2.1   thorpej 	mutex_exit(&sc->sc_lock);
    379  1.114.2.1   thorpej 	uhidev_close(&sc->sc_hdev);
    380  1.114.2.1   thorpej fail1:	selnotify(&sc->sc_rsel, POLLHUP, 0);
    381  1.114.2.1   thorpej 	mutex_enter(&proc_lock);
    382  1.114.2.1   thorpej 	atomic_store_relaxed(&sc->sc_async, NULL);
    383  1.114.2.1   thorpej 	mutex_exit(&proc_lock);
    384  1.114.2.1   thorpej 	if (sc->sc_osize > 0) {
    385  1.114.2.1   thorpej 		kmem_free(sc->sc_obuf, sc->sc_osize);
    386  1.114.2.1   thorpej 		sc->sc_obuf = NULL;
    387  1.114.2.1   thorpej 	}
    388  1.114.2.1   thorpej 	clfree(&sc->sc_q);
    389  1.114.2.1   thorpej fail0:	mutex_enter(&sc->sc_lock);
    390  1.114.2.1   thorpej 	KASSERT(sc->sc_open == 1);
    391  1.114.2.1   thorpej 	sc->sc_open = 0;
    392  1.114.2.1   thorpej 	cv_broadcast(&sc->sc_detach_cv);
    393  1.114.2.1   thorpej 	atomic_store_relaxed(&sc->sc_state, 0);
    394  1.114.2.1   thorpej 	mutex_exit(&sc->sc_lock);
    395  1.114.2.1   thorpej 	return error;
    396        1.1  augustss }
    397        1.1  augustss 
    398      1.109      maxv static int
    399       1.88       mrg uhidclose(dev_t dev, int flag, int mode, struct lwp *l)
    400        1.1  augustss {
    401       1.25  augustss 	struct uhid_softc *sc;
    402       1.25  augustss 
    403       1.84    dyoung 	sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
    404        1.1  augustss 
    405        1.1  augustss 	DPRINTF(("uhidclose: sc=%p\n", sc));
    406        1.1  augustss 
    407  1.114.2.1   thorpej 	/* We are closing up shop.  Prevent new opens until we're done.  */
    408  1.114.2.1   thorpej 	mutex_enter(&sc->sc_lock);
    409  1.114.2.1   thorpej 	KASSERT(sc->sc_open == 2);
    410  1.114.2.1   thorpej 	sc->sc_open = 1;
    411  1.114.2.1   thorpej 	mutex_exit(&sc->sc_lock);
    412  1.114.2.1   thorpej 
    413  1.114.2.1   thorpej 	/* Prevent further interrupts.  */
    414  1.114.2.1   thorpej 	uhidev_close(&sc->sc_hdev);
    415  1.114.2.1   thorpej 
    416  1.114.2.1   thorpej 	/* Hang up all select/poll.  */
    417  1.114.2.1   thorpej 	selnotify(&sc->sc_rsel, POLLHUP, 0);
    418  1.114.2.1   thorpej 
    419  1.114.2.1   thorpej 	/* Reset SIGIO.  */
    420      1.114        ad 	mutex_enter(&proc_lock);
    421  1.114.2.1   thorpej 	atomic_store_relaxed(&sc->sc_async, NULL);
    422      1.114        ad 	mutex_exit(&proc_lock);
    423       1.88       mrg 
    424  1.114.2.1   thorpej 	/* Free the buffer and queue.  */
    425  1.114.2.1   thorpej 	if (sc->sc_osize > 0) {
    426  1.114.2.1   thorpej 		kmem_free(sc->sc_obuf, sc->sc_osize);
    427  1.114.2.1   thorpej 		sc->sc_obuf = NULL;
    428  1.114.2.1   thorpej 	}
    429  1.114.2.1   thorpej 	clfree(&sc->sc_q);
    430       1.93       mrg 
    431  1.114.2.1   thorpej 	/* All set.  We are now closed.  */
    432  1.114.2.1   thorpej 	mutex_enter(&sc->sc_lock);
    433  1.114.2.1   thorpej 	KASSERT(sc->sc_open == 1);
    434  1.114.2.1   thorpej 	sc->sc_open = 0;
    435  1.114.2.1   thorpej 	cv_broadcast(&sc->sc_detach_cv);
    436  1.114.2.1   thorpej 	atomic_store_relaxed(&sc->sc_state, 0);
    437  1.114.2.1   thorpej 	mutex_exit(&sc->sc_lock);
    438       1.93       mrg 
    439  1.114.2.1   thorpej 	return 0;
    440  1.114.2.1   thorpej }
    441       1.93       mrg 
    442  1.114.2.1   thorpej static int
    443  1.114.2.1   thorpej uhid_enter(dev_t dev, struct uhid_softc **scp)
    444  1.114.2.1   thorpej {
    445  1.114.2.1   thorpej 	struct uhid_softc *sc;
    446  1.114.2.1   thorpej 	int error;
    447       1.93       mrg 
    448  1.114.2.1   thorpej 	/* XXX need to hold reference to device */
    449  1.114.2.1   thorpej 	sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
    450  1.114.2.1   thorpej 	if (sc == NULL)
    451  1.114.2.1   thorpej 		return ENXIO;
    452       1.37  augustss 
    453  1.114.2.1   thorpej 	mutex_enter(&sc->sc_lock);
    454  1.114.2.1   thorpej 	KASSERT(sc->sc_open == 2);
    455  1.114.2.1   thorpej 	if (sc->sc_dying) {
    456  1.114.2.1   thorpej 		error = ENXIO;
    457  1.114.2.1   thorpej 	} else if (sc->sc_refcnt == INT_MAX) {
    458  1.114.2.1   thorpej 		error = EBUSY;
    459  1.114.2.1   thorpej 	} else {
    460  1.114.2.1   thorpej 		*scp = sc;
    461  1.114.2.1   thorpej 		sc->sc_refcnt++;
    462  1.114.2.1   thorpej 		error = 0;
    463  1.114.2.1   thorpej 	}
    464  1.114.2.1   thorpej 	mutex_exit(&sc->sc_lock);
    465  1.114.2.1   thorpej 
    466  1.114.2.1   thorpej 	return error;
    467  1.114.2.1   thorpej }
    468  1.114.2.1   thorpej 
    469  1.114.2.1   thorpej static void
    470  1.114.2.1   thorpej uhid_exit(struct uhid_softc *sc)
    471  1.114.2.1   thorpej {
    472  1.114.2.1   thorpej 
    473  1.114.2.1   thorpej 	mutex_enter(&sc->sc_lock);
    474  1.114.2.1   thorpej 	KASSERT(sc->sc_open == 2);
    475  1.114.2.1   thorpej 	KASSERT(sc->sc_refcnt > 0);
    476  1.114.2.1   thorpej 	if (--sc->sc_refcnt == 0)
    477  1.114.2.1   thorpej 		cv_broadcast(&sc->sc_detach_cv);
    478  1.114.2.1   thorpej 	mutex_exit(&sc->sc_lock);
    479        1.1  augustss }
    480        1.1  augustss 
    481      1.110      maxv Static int
    482       1.39  augustss uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag)
    483        1.1  augustss {
    484        1.1  augustss 	int error = 0;
    485       1.47  augustss 	int extra;
    486        1.1  augustss 	size_t length;
    487        1.1  augustss 	u_char buffer[UHID_CHUNK];
    488       1.27  augustss 	usbd_status err;
    489        1.1  augustss 
    490        1.1  augustss 	DPRINTFN(1, ("uhidread\n"));
    491  1.114.2.1   thorpej 	if (atomic_load_relaxed(&sc->sc_state) & UHID_IMMED) {
    492        1.2  augustss 		DPRINTFN(1, ("uhidread immed\n"));
    493       1.47  augustss 		extra = sc->sc_hdev.sc_report_id != 0;
    494      1.111      maxv 		if (sc->sc_isize + extra > sizeof(buffer))
    495      1.111      maxv 			return ENOBUFS;
    496       1.47  augustss 		err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
    497       1.47  augustss 					buffer, sc->sc_isize + extra);
    498       1.27  augustss 		if (err)
    499       1.93       mrg 			return EIO;
    500       1.93       mrg 		return uiomove(buffer+extra, sc->sc_isize, uio);
    501        1.2  augustss 	}
    502        1.2  augustss 
    503       1.88       mrg 	mutex_enter(&sc->sc_lock);
    504        1.1  augustss 	while (sc->sc_q.c_cc == 0) {
    505        1.1  augustss 		if (flag & IO_NDELAY) {
    506       1.88       mrg 			mutex_exit(&sc->sc_lock);
    507       1.93       mrg 			return EWOULDBLOCK;
    508        1.1  augustss 		}
    509  1.114.2.1   thorpej 		if (sc->sc_dying) {
    510  1.114.2.1   thorpej 			mutex_exit(&sc->sc_lock);
    511  1.114.2.1   thorpej 			return EIO;
    512  1.114.2.1   thorpej 		}
    513       1.44      yamt 		DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q));
    514       1.88       mrg 		error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock);
    515        1.1  augustss 		DPRINTFN(5, ("uhidread: woke, error=%d\n", error));
    516        1.1  augustss 		if (error) {
    517       1.18  augustss 			break;
    518        1.1  augustss 		}
    519        1.1  augustss 	}
    520        1.1  augustss 
    521        1.1  augustss 	/* Transfer as many chunks as possible. */
    522       1.18  augustss 	while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) {
    523      1.102  riastrad 		length = uimin(sc->sc_q.c_cc, uio->uio_resid);
    524        1.1  augustss 		if (length > sizeof(buffer))
    525        1.1  augustss 			length = sizeof(buffer);
    526        1.1  augustss 
    527        1.1  augustss 		/* Remove a small chunk from the input queue. */
    528        1.1  augustss 		(void) q_to_b(&sc->sc_q, buffer, length);
    529       1.29  augustss 		DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length));
    530        1.1  augustss 
    531        1.1  augustss 		/* Copy the data to the user process. */
    532       1.93       mrg 		mutex_exit(&sc->sc_lock);
    533        1.1  augustss 		if ((error = uiomove(buffer, length, uio)) != 0)
    534       1.93       mrg 			return error;
    535       1.93       mrg 		mutex_enter(&sc->sc_lock);
    536        1.1  augustss 	}
    537        1.1  augustss 
    538       1.93       mrg 	mutex_exit(&sc->sc_lock);
    539       1.93       mrg 	return error;
    540        1.1  augustss }
    541        1.1  augustss 
    542      1.109      maxv static int
    543       1.39  augustss uhidread(dev_t dev, struct uio *uio, int flag)
    544        1.1  augustss {
    545       1.25  augustss 	struct uhid_softc *sc;
    546       1.25  augustss 	int error;
    547       1.25  augustss 
    548  1.114.2.1   thorpej 	error = uhid_enter(dev, &sc);
    549  1.114.2.1   thorpej 	if (error)
    550  1.114.2.1   thorpej 		return error;
    551       1.18  augustss 	error = uhid_do_read(sc, uio, flag);
    552  1.114.2.1   thorpej 	uhid_exit(sc);
    553       1.93       mrg 	return error;
    554       1.18  augustss }
    555       1.18  augustss 
    556      1.110      maxv Static int
    557       1.72  christos uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag)
    558       1.18  augustss {
    559        1.1  augustss 	int error;
    560        1.1  augustss 	int size;
    561       1.27  augustss 	usbd_status err;
    562        1.1  augustss 
    563       1.18  augustss 	DPRINTFN(1, ("uhidwrite\n"));
    564       1.52  augustss 
    565        1.1  augustss 	size = sc->sc_osize;
    566       1.97   mlelstv 	if (uio->uio_resid != size || size == 0)
    567       1.93       mrg 		return EINVAL;
    568       1.18  augustss 	error = uiomove(sc->sc_obuf, size, uio);
    569      1.112  christos #ifdef UHID_DEBUG
    570      1.112  christos 	if (uhiddebug > 5) {
    571      1.112  christos 		uint32_t i;
    572      1.112  christos 
    573      1.112  christos 		DPRINTF(("%s: outdata[%d] =", device_xname(sc->sc_hdev.sc_dev),
    574      1.112  christos 		    error));
    575      1.112  christos 		for (i = 0; i < size; i++)
    576      1.112  christos 			DPRINTF((" %02x", sc->sc_obuf[i]));
    577      1.112  christos 		DPRINTF(("\n"));
    578      1.112  christos 	}
    579      1.112  christos #endif
    580       1.18  augustss 	if (!error) {
    581      1.112  christos 		if (sc->sc_raw)
    582      1.112  christos 			err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf,
    583      1.112  christos 			    size);
    584      1.112  christos 		else
    585      1.112  christos 			err = uhidev_set_report(&sc->sc_hdev,
    586      1.112  christos 			    UHID_OUTPUT_REPORT, sc->sc_obuf, size);
    587      1.112  christos 		if (err) {
    588      1.112  christos 			DPRINTF(("%s: err = %d\n",
    589      1.112  christos 			    device_xname(sc->sc_hdev.sc_dev), err));
    590        1.1  augustss 			error = EIO;
    591      1.112  christos 		}
    592        1.1  augustss 	}
    593       1.18  augustss 
    594       1.93       mrg 	return error;
    595        1.1  augustss }
    596        1.1  augustss 
    597        1.1  augustss int
    598       1.39  augustss uhidwrite(dev_t dev, struct uio *uio, int flag)
    599       1.18  augustss {
    600       1.25  augustss 	struct uhid_softc *sc;
    601       1.25  augustss 	int error;
    602       1.25  augustss 
    603  1.114.2.1   thorpej 	error = uhid_enter(dev, &sc);
    604  1.114.2.1   thorpej 	if (error)
    605  1.114.2.1   thorpej 		return error;
    606       1.18  augustss 	error = uhid_do_write(sc, uio, flag);
    607  1.114.2.1   thorpej 	uhid_exit(sc);
    608       1.93       mrg 	return error;
    609       1.18  augustss }
    610       1.18  augustss 
    611       1.18  augustss int
    612       1.76  christos uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, void *addr,
    613       1.72  christos     int flag, struct lwp *l)
    614        1.1  augustss {
    615        1.1  augustss 	struct usb_ctl_report_desc *rd;
    616        1.2  augustss 	struct usb_ctl_report *re;
    617       1.47  augustss 	u_char buffer[UHID_CHUNK];
    618       1.47  augustss 	int size, extra;
    619       1.27  augustss 	usbd_status err;
    620       1.47  augustss 	void *desc;
    621        1.1  augustss 
    622       1.18  augustss 	DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
    623       1.18  augustss 
    624        1.1  augustss 	switch (cmd) {
    625        1.2  augustss 	case FIONBIO:
    626        1.2  augustss 		/* All handled in the upper FS layer. */
    627       1.37  augustss 		break;
    628       1.37  augustss 
    629       1.37  augustss 	case FIOASYNC:
    630      1.114        ad 		mutex_enter(&proc_lock);
    631       1.37  augustss 		if (*(int *)addr) {
    632      1.111      maxv 			if (sc->sc_async != NULL) {
    633      1.114        ad 				mutex_exit(&proc_lock);
    634       1.93       mrg 				return EBUSY;
    635      1.111      maxv 			}
    636  1.114.2.1   thorpej 			atomic_store_relaxed(&sc->sc_async, l->l_proc);
    637       1.68  christos 			DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", l->l_proc));
    638       1.37  augustss 		} else
    639  1.114.2.1   thorpej 			atomic_store_relaxed(&sc->sc_async, NULL);
    640      1.114        ad 		mutex_exit(&proc_lock);
    641       1.37  augustss 		break;
    642       1.37  augustss 
    643       1.37  augustss 	/* XXX this is not the most general solution. */
    644       1.37  augustss 	case TIOCSPGRP:
    645      1.114        ad 		mutex_enter(&proc_lock);
    646       1.80        ad 		if (sc->sc_async == NULL) {
    647      1.114        ad 			mutex_exit(&proc_lock);
    648       1.93       mrg 			return EINVAL;
    649       1.80        ad 		}
    650       1.80        ad 		if (*(int *)addr != sc->sc_async->p_pgid) {
    651      1.114        ad 			mutex_exit(&proc_lock);
    652       1.93       mrg 			return EPERM;
    653       1.80        ad 		}
    654      1.114        ad 		mutex_exit(&proc_lock);
    655       1.60  jdolecek 		break;
    656       1.60  jdolecek 
    657       1.60  jdolecek 	case FIOSETOWN:
    658      1.114        ad 		mutex_enter(&proc_lock);
    659       1.80        ad 		if (sc->sc_async == NULL) {
    660      1.114        ad 			mutex_exit(&proc_lock);
    661       1.93       mrg 			return EINVAL;
    662       1.80        ad 		}
    663       1.60  jdolecek 		if (-*(int *)addr != sc->sc_async->p_pgid
    664       1.80        ad 		    && *(int *)addr != sc->sc_async->p_pid) {
    665      1.114        ad 			mutex_exit(&proc_lock);
    666       1.93       mrg 			return EPERM;
    667       1.80        ad 		}
    668      1.114        ad 		mutex_exit(&proc_lock);
    669        1.2  augustss 		break;
    670        1.2  augustss 
    671      1.113  christos 	case USB_HID_GET_RAW:
    672      1.113  christos 		*(int *)addr = sc->sc_raw;
    673      1.113  christos 		break;
    674      1.113  christos 
    675      1.113  christos 	case USB_HID_SET_RAW:
    676      1.113  christos 		sc->sc_raw = *(int *)addr;
    677      1.113  christos 		break;
    678      1.113  christos 
    679        1.1  augustss 	case USB_GET_REPORT_DESC:
    680       1.47  augustss 		uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
    681        1.1  augustss 		rd = (struct usb_ctl_report_desc *)addr;
    682      1.102  riastrad 		size = uimin(size, sizeof(rd->ucrd_data));
    683       1.50  christos 		rd->ucrd_size = size;
    684       1.50  christos 		memcpy(rd->ucrd_data, desc, size);
    685        1.1  augustss 		break;
    686        1.2  augustss 
    687        1.2  augustss 	case USB_SET_IMMED:
    688        1.9  augustss 		if (*(int *)addr) {
    689       1.47  augustss 			extra = sc->sc_hdev.sc_report_id != 0;
    690      1.111      maxv 			if (sc->sc_isize + extra > sizeof(buffer))
    691      1.111      maxv 				return ENOBUFS;
    692       1.47  augustss 			err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
    693       1.47  augustss 						buffer, sc->sc_isize + extra);
    694       1.27  augustss 			if (err)
    695       1.93       mrg 				return EOPNOTSUPP;
    696       1.12  augustss 
    697  1.114.2.1   thorpej 			atomic_or_32(&sc->sc_state, UHID_IMMED);
    698        1.9  augustss 		} else
    699  1.114.2.1   thorpej 			atomic_and_32(&sc->sc_state, ~UHID_IMMED);
    700        1.2  augustss 		break;
    701        1.2  augustss 
    702        1.2  augustss 	case USB_GET_REPORT:
    703        1.2  augustss 		re = (struct usb_ctl_report *)addr;
    704       1.50  christos 		switch (re->ucr_report) {
    705        1.2  augustss 		case UHID_INPUT_REPORT:
    706        1.2  augustss 			size = sc->sc_isize;
    707        1.2  augustss 			break;
    708        1.2  augustss 		case UHID_OUTPUT_REPORT:
    709        1.2  augustss 			size = sc->sc_osize;
    710        1.2  augustss 			break;
    711        1.2  augustss 		case UHID_FEATURE_REPORT:
    712        1.2  augustss 			size = sc->sc_fsize;
    713        1.2  augustss 			break;
    714        1.2  augustss 		default:
    715       1.93       mrg 			return EINVAL;
    716        1.2  augustss 		}
    717       1.47  augustss 		extra = sc->sc_hdev.sc_report_id != 0;
    718      1.111      maxv 		if (size + extra > sizeof(re->ucr_data))
    719      1.111      maxv 			return ENOBUFS;
    720       1.50  christos 		err = uhidev_get_report(&sc->sc_hdev, re->ucr_report,
    721       1.50  christos 		    re->ucr_data, size + extra);
    722       1.47  augustss 		if (extra)
    723       1.99      maya 			memmove(re->ucr_data, re->ucr_data+1, size);
    724       1.35  augustss 		if (err)
    725       1.93       mrg 			return EIO;
    726       1.35  augustss 		break;
    727       1.35  augustss 
    728       1.35  augustss 	case USB_SET_REPORT:
    729       1.35  augustss 		re = (struct usb_ctl_report *)addr;
    730       1.50  christos 		switch (re->ucr_report) {
    731       1.35  augustss 		case UHID_INPUT_REPORT:
    732       1.35  augustss 			size = sc->sc_isize;
    733       1.35  augustss 			break;
    734       1.35  augustss 		case UHID_OUTPUT_REPORT:
    735       1.35  augustss 			size = sc->sc_osize;
    736       1.35  augustss 			break;
    737       1.35  augustss 		case UHID_FEATURE_REPORT:
    738       1.35  augustss 			size = sc->sc_fsize;
    739       1.35  augustss 			break;
    740       1.35  augustss 		default:
    741       1.93       mrg 			return EINVAL;
    742       1.35  augustss 		}
    743      1.111      maxv 		if (size > sizeof(re->ucr_data))
    744      1.111      maxv 			return ENOBUFS;
    745       1.50  christos 		err = uhidev_set_report(&sc->sc_hdev, re->ucr_report,
    746       1.50  christos 		    re->ucr_data, size);
    747       1.27  augustss 		if (err)
    748       1.93       mrg 			return EIO;
    749        1.2  augustss 		break;
    750        1.2  augustss 
    751       1.47  augustss 	case USB_GET_REPORT_ID:
    752       1.47  augustss 		*(int *)addr = sc->sc_hdev.sc_report_id;
    753       1.47  augustss 		break;
    754       1.47  augustss 
    755       1.87       erh 	case USB_GET_DEVICE_DESC:
    756       1.87       erh 		*(usb_device_descriptor_t *)addr =
    757       1.87       erh 			*usbd_get_device_descriptor(sc->sc_hdev.sc_parent->sc_udev);
    758       1.87       erh 		break;
    759       1.87       erh 
    760       1.61  jdolecek 	case USB_GET_DEVICEINFO:
    761       1.61  jdolecek 		usbd_fill_deviceinfo(sc->sc_hdev.sc_parent->sc_udev,
    762       1.95     skrll 				     (struct usb_device_info *)addr, 0);
    763       1.61  jdolecek 		break;
    764       1.73     pavel 	case USB_GET_DEVICEINFO_OLD:
    765      1.106  pgoyette 		MODULE_HOOK_CALL(usb_subr_fill_30_hook,
    766      1.103  pgoyette                     (sc->sc_hdev.sc_parent->sc_udev,
    767      1.103  pgoyette 		      (struct usb_device_info_old *)addr, 0,
    768      1.103  pgoyette                       usbd_devinfo_vp, usbd_printBCD),
    769      1.103  pgoyette                     enosys(), err);
    770      1.103  pgoyette 		if (err == 0)
    771      1.103  pgoyette 			return 0;
    772       1.73     pavel 		break;
    773       1.95     skrll 	case USB_GET_STRING_DESC:
    774       1.61  jdolecek 	    {
    775       1.95     skrll 		struct usb_string_desc *si = (struct usb_string_desc *)addr;
    776       1.95     skrll 		err = usbd_get_string_desc(sc->sc_hdev.sc_parent->sc_udev,
    777       1.61  jdolecek 			si->usd_string_index,
    778       1.95     skrll 			si->usd_language_id, &si->usd_desc, &size);
    779       1.95     skrll 		if (err)
    780       1.95     skrll 			return EINVAL;
    781       1.95     skrll 		break;
    782       1.61  jdolecek 	    }
    783       1.61  jdolecek 
    784        1.1  augustss 	default:
    785       1.93       mrg 		return EINVAL;
    786        1.1  augustss 	}
    787       1.93       mrg 	return 0;
    788        1.1  augustss }
    789        1.1  augustss 
    790      1.109      maxv static int
    791       1.76  christos uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
    792       1.18  augustss {
    793       1.25  augustss 	struct uhid_softc *sc;
    794       1.25  augustss 	int error;
    795       1.25  augustss 
    796  1.114.2.1   thorpej 	error = uhid_enter(dev, &sc);
    797  1.114.2.1   thorpej 	if (error)
    798  1.114.2.1   thorpej 		return error;
    799       1.68  christos 	error = uhid_do_ioctl(sc, cmd, addr, flag, l);
    800  1.114.2.1   thorpej 	uhid_exit(sc);
    801       1.93       mrg 	return error;
    802       1.18  augustss }
    803       1.18  augustss 
    804      1.109      maxv static int
    805       1.68  christos uhidpoll(dev_t dev, int events, struct lwp *l)
    806        1.1  augustss {
    807       1.25  augustss 	struct uhid_softc *sc;
    808        1.1  augustss 	int revents = 0;
    809       1.25  augustss 
    810  1.114.2.1   thorpej 	if (uhid_enter(dev, &sc) != 0)
    811  1.114.2.1   thorpej 		return POLLHUP;
    812        1.1  augustss 
    813       1.88       mrg 	mutex_enter(&sc->sc_lock);
    814        1.1  augustss 	if (events & (POLLOUT | POLLWRNORM))
    815        1.1  augustss 		revents |= events & (POLLOUT | POLLWRNORM);
    816        1.4     veego 	if (events & (POLLIN | POLLRDNORM)) {
    817        1.1  augustss 		if (sc->sc_q.c_cc > 0)
    818        1.1  augustss 			revents |= events & (POLLIN | POLLRDNORM);
    819        1.1  augustss 		else
    820       1.68  christos 			selrecord(l, &sc->sc_rsel);
    821        1.4     veego 	}
    822       1.88       mrg 	mutex_exit(&sc->sc_lock);
    823        1.1  augustss 
    824  1.114.2.1   thorpej 	uhid_exit(sc);
    825       1.93       mrg 	return revents;
    826       1.55  jdolecek }
    827       1.55  jdolecek 
    828       1.55  jdolecek static void
    829       1.55  jdolecek filt_uhidrdetach(struct knote *kn)
    830       1.55  jdolecek {
    831       1.55  jdolecek 	struct uhid_softc *sc = kn->kn_hook;
    832       1.55  jdolecek 
    833       1.88       mrg 	mutex_enter(&sc->sc_lock);
    834       1.56  christos 	SLIST_REMOVE(&sc->sc_rsel.sel_klist, kn, knote, kn_selnext);
    835       1.88       mrg 	mutex_exit(&sc->sc_lock);
    836       1.55  jdolecek }
    837       1.55  jdolecek 
    838       1.55  jdolecek static int
    839       1.72  christos filt_uhidread(struct knote *kn, long hint)
    840       1.55  jdolecek {
    841       1.55  jdolecek 	struct uhid_softc *sc = kn->kn_hook;
    842       1.55  jdolecek 
    843  1.114.2.1   thorpej 	if (hint == NOTE_SUBMIT)
    844  1.114.2.1   thorpej 		KASSERT(mutex_owned(&sc->sc_lock));
    845  1.114.2.1   thorpej 	else
    846  1.114.2.1   thorpej 		mutex_enter(&sc->sc_lock);
    847  1.114.2.1   thorpej 
    848       1.55  jdolecek 	kn->kn_data = sc->sc_q.c_cc;
    849  1.114.2.1   thorpej 
    850  1.114.2.1   thorpej 	if (hint == NOTE_SUBMIT)
    851  1.114.2.1   thorpej 		KASSERT(mutex_owned(&sc->sc_lock));
    852  1.114.2.1   thorpej 	else
    853  1.114.2.1   thorpej 		mutex_exit(&sc->sc_lock);
    854  1.114.2.1   thorpej 
    855       1.95     skrll 	return kn->kn_data > 0;
    856       1.55  jdolecek }
    857       1.55  jdolecek 
    858      1.100      maya static const struct filterops uhidread_filtops = {
    859      1.100      maya 	.f_isfd = 1,
    860      1.100      maya 	.f_attach = NULL,
    861      1.100      maya 	.f_detach = filt_uhidrdetach,
    862      1.100      maya 	.f_event = filt_uhidread,
    863      1.100      maya };
    864       1.55  jdolecek 
    865      1.100      maya static const struct filterops uhid_seltrue_filtops = {
    866      1.100      maya 	.f_isfd = 1,
    867      1.100      maya 	.f_attach = NULL,
    868      1.100      maya 	.f_detach = filt_uhidrdetach,
    869      1.100      maya 	.f_event = filt_seltrue,
    870      1.100      maya };
    871       1.55  jdolecek 
    872      1.109      maxv static int
    873       1.55  jdolecek uhidkqfilter(dev_t dev, struct knote *kn)
    874       1.55  jdolecek {
    875       1.55  jdolecek 	struct uhid_softc *sc;
    876       1.55  jdolecek 	struct klist *klist;
    877  1.114.2.1   thorpej 	int error;
    878       1.55  jdolecek 
    879  1.114.2.1   thorpej 	error = uhid_enter(dev, &sc);
    880  1.114.2.1   thorpej 	if (error)
    881  1.114.2.1   thorpej 		return error;
    882       1.55  jdolecek 
    883       1.55  jdolecek 	switch (kn->kn_filter) {
    884       1.55  jdolecek 	case EVFILT_READ:
    885       1.56  christos 		klist = &sc->sc_rsel.sel_klist;
    886       1.55  jdolecek 		kn->kn_fop = &uhidread_filtops;
    887       1.55  jdolecek 		break;
    888       1.55  jdolecek 	case EVFILT_WRITE:
    889       1.56  christos 		klist = &sc->sc_rsel.sel_klist;
    890       1.55  jdolecek 		kn->kn_fop = &uhid_seltrue_filtops;
    891       1.55  jdolecek 		break;
    892       1.55  jdolecek 	default:
    893  1.114.2.1   thorpej 		error = EINVAL;
    894  1.114.2.1   thorpej 		goto out;
    895       1.55  jdolecek 	}
    896       1.55  jdolecek 
    897       1.55  jdolecek 	kn->kn_hook = sc;
    898       1.55  jdolecek 
    899       1.88       mrg 	mutex_enter(&sc->sc_lock);
    900       1.55  jdolecek 	SLIST_INSERT_HEAD(klist, kn, kn_selnext);
    901       1.88       mrg 	mutex_exit(&sc->sc_lock);
    902       1.55  jdolecek 
    903  1.114.2.1   thorpej out:	uhid_exit(sc);
    904  1.114.2.1   thorpej 	return error;
    905        1.1  augustss }
    906