1 1.129 mrg /* $NetBSD: uhid.c,v 1.129 2024/02/04 05:43:06 mrg 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.129 mrg * Carlstedt Research & Technology and Matthew R. Green (mrg (at) eterna23.net). 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.129 mrg __KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.129 2024/02/04 05:43:06 mrg 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.115 riastrad #include <sys/types.h> 47 1.115 riastrad 48 1.115 riastrad #include <sys/atomic.h> 49 1.115 riastrad #include <sys/compat_stub.h> 50 1.115 riastrad #include <sys/conf.h> 51 1.115 riastrad #include <sys/device.h> 52 1.115 riastrad #include <sys/file.h> 53 1.115 riastrad #include <sys/intr.h> 54 1.115 riastrad #include <sys/ioctl.h> 55 1.1 augustss #include <sys/kernel.h> 56 1.95 skrll #include <sys/kmem.h> 57 1.115 riastrad #include <sys/poll.h> 58 1.115 riastrad #include <sys/proc.h> 59 1.115 riastrad #include <sys/select.h> 60 1.37 augustss #include <sys/signalvar.h> 61 1.115 riastrad #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.123 riastrad device_t sc_dev; 89 1.123 riastrad struct uhidev *sc_hdev; 90 1.122 riastrad struct usbd_device *sc_udev; 91 1.123 riastrad uint8_t sc_report_id; 92 1.1 augustss 93 1.115 riastrad kmutex_t sc_lock; 94 1.88 mrg kcondvar_t sc_cv; 95 1.88 mrg 96 1.1 augustss int sc_isize; 97 1.1 augustss int sc_osize; 98 1.2 augustss int sc_fsize; 99 1.1 augustss 100 1.33 augustss u_char *sc_obuf; 101 1.1 augustss 102 1.93 mrg struct clist sc_q; /* protected by sc_lock */ 103 1.1 augustss struct selinfo sc_rsel; 104 1.84 dyoung proc_t *sc_async; /* process that wants SIGIO */ 105 1.80 ad void *sc_sih; 106 1.115 riastrad volatile uint32_t sc_state; /* driver state */ 107 1.47 augustss #define UHID_IMMED 0x02 /* return read data immediately */ 108 1.18 augustss 109 1.112 christos int sc_raw; 110 1.120 riastrad enum { 111 1.120 riastrad UHID_CLOSED, 112 1.120 riastrad UHID_OPENING, 113 1.120 riastrad UHID_OPEN, 114 1.120 riastrad } sc_open; 115 1.120 riastrad bool sc_closing; 116 1.1 augustss }; 117 1.1 augustss 118 1.1 augustss #define UHIDUNIT(dev) (minor(dev)) 119 1.1 augustss #define UHID_CHUNK 128 /* chunk size for read */ 120 1.1 augustss #define UHID_BSIZE 1020 /* buffer size */ 121 1.1 augustss 122 1.109 maxv static dev_type_open(uhidopen); 123 1.120 riastrad static dev_type_cancel(uhidcancel); 124 1.109 maxv static dev_type_close(uhidclose); 125 1.109 maxv static dev_type_read(uhidread); 126 1.109 maxv static dev_type_write(uhidwrite); 127 1.109 maxv static dev_type_ioctl(uhidioctl); 128 1.109 maxv static dev_type_poll(uhidpoll); 129 1.109 maxv static dev_type_kqfilter(uhidkqfilter); 130 1.53 gehenna 131 1.53 gehenna const struct cdevsw uhid_cdevsw = { 132 1.90 dholland .d_open = uhidopen, 133 1.120 riastrad .d_cancel = uhidcancel, 134 1.90 dholland .d_close = uhidclose, 135 1.90 dholland .d_read = uhidread, 136 1.90 dholland .d_write = uhidwrite, 137 1.90 dholland .d_ioctl = uhidioctl, 138 1.90 dholland .d_stop = nostop, 139 1.90 dholland .d_tty = notty, 140 1.90 dholland .d_poll = uhidpoll, 141 1.90 dholland .d_mmap = nommap, 142 1.90 dholland .d_kqfilter = uhidkqfilter, 143 1.92 dholland .d_discard = nodiscard, 144 1.120 riastrad .d_cfdriver = &uhid_cd, 145 1.120 riastrad .d_devtounit = dev_minor_unit, 146 1.93 mrg .d_flag = D_OTHER 147 1.53 gehenna }; 148 1.19 augustss 149 1.123 riastrad static void uhid_intr(void *, void *, u_int); 150 1.1 augustss 151 1.109 maxv static int uhid_match(device_t, cfdata_t, void *); 152 1.109 maxv static void uhid_attach(device_t, device_t, void *); 153 1.109 maxv static int uhid_detach(device_t, int); 154 1.108 mrg 155 1.98 msaitoh CFATTACH_DECL_NEW(uhid, sizeof(struct uhid_softc), uhid_match, uhid_attach, 156 1.120 riastrad uhid_detach, NULL); 157 1.1 augustss 158 1.109 maxv static int 159 1.82 cube uhid_match(device_t parent, cfdata_t match, void *aux) 160 1.1 augustss { 161 1.66 tron #ifdef UHID_DEBUG 162 1.47 augustss struct uhidev_attach_arg *uha = aux; 163 1.66 tron #endif 164 1.47 augustss 165 1.47 augustss DPRINTF(("uhid_match: report=%d\n", uha->reportid)); 166 1.47 augustss 167 1.65 augustss if (match->cf_flags & 1) 168 1.93 mrg return UMATCH_HIGHEST; 169 1.67 augustss else 170 1.93 mrg return UMATCH_IFACECLASS_GENERIC; 171 1.1 augustss } 172 1.1 augustss 173 1.109 maxv static void 174 1.82 cube uhid_attach(device_t parent, device_t self, void *aux) 175 1.1 augustss { 176 1.82 cube struct uhid_softc *sc = device_private(self); 177 1.47 augustss struct uhidev_attach_arg *uha = aux; 178 1.47 augustss int size, repid; 179 1.1 augustss void *desc; 180 1.52 augustss 181 1.123 riastrad sc->sc_dev = self; 182 1.123 riastrad sc->sc_hdev = uha->parent; 183 1.123 riastrad sc->sc_udev = uha->uiaa->uiaa_device; 184 1.123 riastrad sc->sc_report_id = uha->reportid; 185 1.123 riastrad 186 1.79 rmind selinit(&sc->sc_rsel); 187 1.122 riastrad 188 1.47 augustss uhidev_get_report_desc(uha->parent, &desc, &size); 189 1.47 augustss repid = uha->reportid; 190 1.47 augustss sc->sc_isize = hid_report_size(desc, size, hid_input, repid); 191 1.47 augustss sc->sc_osize = hid_report_size(desc, size, hid_output, repid); 192 1.47 augustss sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid); 193 1.112 christos sc->sc_raw = hid_is_collection(desc, size, uha->reportid, 194 1.112 christos HID_USAGE2(HUP_FIDO, HUF_U2FHID)); 195 1.1 augustss 196 1.82 cube aprint_naive("\n"); 197 1.82 cube aprint_normal(": input=%d, output=%d, feature=%d\n", 198 1.47 augustss sc->sc_isize, sc->sc_osize, sc->sc_fsize); 199 1.32 augustss 200 1.95 skrll mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); 201 1.88 mrg cv_init(&sc->sc_cv, "uhidrea"); 202 1.88 mrg 203 1.78 drochner if (!pmf_device_register(self, NULL, NULL)) 204 1.78 drochner aprint_error_dev(self, "couldn't establish power handler\n"); 205 1.78 drochner 206 1.84 dyoung return; 207 1.1 augustss } 208 1.1 augustss 209 1.109 maxv static int 210 1.82 cube uhid_detach(device_t self, int flags) 211 1.1 augustss { 212 1.82 cube struct uhid_softc *sc = device_private(self); 213 1.18 augustss int maj, mn; 214 1.18 augustss 215 1.18 augustss DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags)); 216 1.3 augustss 217 1.115 riastrad pmf_device_deregister(self); 218 1.115 riastrad 219 1.18 augustss /* locate the major number */ 220 1.53 gehenna maj = cdevsw_lookup_major(&uhid_cdevsw); 221 1.18 augustss 222 1.18 augustss /* Nuke the vnodes for any open instances (calls close). */ 223 1.69 thorpej mn = device_unit(self); 224 1.18 augustss vdevgone(maj, mn, mn, VCHR); 225 1.47 augustss 226 1.120 riastrad KASSERTMSG(sc->sc_open == UHID_CLOSED, "open=%d", (int)sc->sc_open); 227 1.115 riastrad 228 1.88 mrg cv_destroy(&sc->sc_cv); 229 1.88 mrg mutex_destroy(&sc->sc_lock); 230 1.79 rmind seldestroy(&sc->sc_rsel); 231 1.18 augustss 232 1.93 mrg return 0; 233 1.1 augustss } 234 1.1 augustss 235 1.120 riastrad static void 236 1.123 riastrad uhid_intr(void *cookie, void *data, u_int len) 237 1.1 augustss { 238 1.123 riastrad struct uhid_softc *sc = cookie; 239 1.1 augustss 240 1.33 augustss #ifdef UHID_DEBUG 241 1.33 augustss if (uhiddebug > 5) { 242 1.95 skrll uint32_t i; 243 1.52 augustss 244 1.33 augustss DPRINTF(("uhid_intr: data =")); 245 1.47 augustss for (i = 0; i < len; i++) 246 1.51 augustss DPRINTF((" %02x", ((u_char *)data)[i])); 247 1.33 augustss DPRINTF(("\n")); 248 1.33 augustss } 249 1.33 augustss #endif 250 1.1 augustss 251 1.88 mrg mutex_enter(&sc->sc_lock); 252 1.47 augustss (void)b_to_q(data, len, &sc->sc_q); 253 1.52 augustss 254 1.115 riastrad DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q)); 255 1.115 riastrad cv_broadcast(&sc->sc_cv); 256 1.115 riastrad selnotify(&sc->sc_rsel, 0, NOTE_SUBMIT); 257 1.116 riastrad if (atomic_load_relaxed(&sc->sc_async) != NULL) { 258 1.116 riastrad mutex_enter(&proc_lock); 259 1.116 riastrad if (sc->sc_async != NULL) { 260 1.116 riastrad DPRINTFN(3, ("uhid_intr: sending SIGIO to %jd\n", 261 1.116 riastrad (intmax_t)sc->sc_async->p_pid)); 262 1.116 riastrad psignal(sc->sc_async, SIGIO); 263 1.116 riastrad } 264 1.116 riastrad mutex_exit(&proc_lock); 265 1.37 augustss } 266 1.88 mrg mutex_exit(&sc->sc_lock); 267 1.1 augustss } 268 1.1 augustss 269 1.109 maxv static int 270 1.88 mrg uhidopen(dev_t dev, int flag, int mode, struct lwp *l) 271 1.1 augustss { 272 1.120 riastrad struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 273 1.47 augustss int error; 274 1.25 augustss 275 1.120 riastrad DPRINTF(("uhidopen: sc=%p\n", sc)); 276 1.84 dyoung if (sc == NULL) 277 1.84 dyoung return ENXIO; 278 1.1 augustss 279 1.93 mrg /* 280 1.120 riastrad * Try to open. If closing in progress, give up. If already 281 1.120 riastrad * open (or opening), fail -- opens are exclusive. 282 1.93 mrg */ 283 1.115 riastrad mutex_enter(&sc->sc_lock); 284 1.120 riastrad if (sc->sc_open != UHID_CLOSED || sc->sc_closing) { 285 1.107 mrg mutex_exit(&sc->sc_lock); 286 1.93 mrg return EBUSY; 287 1.93 mrg } 288 1.120 riastrad sc->sc_open = UHID_OPENING; 289 1.115 riastrad atomic_store_relaxed(&sc->sc_state, 0); 290 1.107 mrg mutex_exit(&sc->sc_lock); 291 1.107 mrg 292 1.115 riastrad /* uhid interrupts aren't enabled yet, so setup sc_q now */ 293 1.93 mrg if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) { 294 1.115 riastrad error = ENOMEM; 295 1.115 riastrad goto fail0; 296 1.93 mrg } 297 1.93 mrg 298 1.115 riastrad /* Allocate an output buffer if needed. */ 299 1.97 mlelstv if (sc->sc_osize > 0) 300 1.97 mlelstv sc->sc_obuf = kmem_alloc(sc->sc_osize, KM_SLEEP); 301 1.97 mlelstv else 302 1.97 mlelstv sc->sc_obuf = NULL; 303 1.88 mrg 304 1.127 andvar /* Paranoia: reset SIGIO before enabling interrupts. */ 305 1.114 ad mutex_enter(&proc_lock); 306 1.116 riastrad atomic_store_relaxed(&sc->sc_async, NULL); 307 1.114 ad mutex_exit(&proc_lock); 308 1.37 augustss 309 1.115 riastrad /* Open the uhidev -- after this point we can get interrupts. */ 310 1.123 riastrad error = uhidev_open(sc->sc_hdev, &uhid_intr, sc); 311 1.115 riastrad if (error) 312 1.115 riastrad goto fail1; 313 1.115 riastrad 314 1.115 riastrad /* We are open for business. */ 315 1.115 riastrad mutex_enter(&sc->sc_lock); 316 1.120 riastrad sc->sc_open = UHID_OPEN; 317 1.115 riastrad mutex_exit(&sc->sc_lock); 318 1.115 riastrad 319 1.93 mrg return 0; 320 1.115 riastrad 321 1.115 riastrad fail1: selnotify(&sc->sc_rsel, POLLHUP, 0); 322 1.115 riastrad mutex_enter(&proc_lock); 323 1.116 riastrad atomic_store_relaxed(&sc->sc_async, NULL); 324 1.115 riastrad mutex_exit(&proc_lock); 325 1.115 riastrad if (sc->sc_osize > 0) { 326 1.115 riastrad kmem_free(sc->sc_obuf, sc->sc_osize); 327 1.115 riastrad sc->sc_obuf = NULL; 328 1.115 riastrad } 329 1.115 riastrad clfree(&sc->sc_q); 330 1.115 riastrad fail0: mutex_enter(&sc->sc_lock); 331 1.120 riastrad KASSERT(sc->sc_open == UHID_OPENING); 332 1.120 riastrad sc->sc_open = UHID_CLOSED; 333 1.115 riastrad atomic_store_relaxed(&sc->sc_state, 0); 334 1.115 riastrad mutex_exit(&sc->sc_lock); 335 1.115 riastrad return error; 336 1.1 augustss } 337 1.1 augustss 338 1.109 maxv static int 339 1.120 riastrad uhidcancel(dev_t dev, int flag, int mode, struct lwp *l) 340 1.120 riastrad { 341 1.120 riastrad struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 342 1.120 riastrad 343 1.120 riastrad DPRINTF(("uhidcancel: sc=%p\n", sc)); 344 1.120 riastrad if (sc == NULL) 345 1.120 riastrad return 0; 346 1.120 riastrad 347 1.120 riastrad /* 348 1.120 riastrad * Mark it closing, wake any waiters, and suspend output. 349 1.120 riastrad * After this point, no new xfers can be submitted. 350 1.120 riastrad */ 351 1.120 riastrad mutex_enter(&sc->sc_lock); 352 1.120 riastrad sc->sc_closing = true; 353 1.120 riastrad cv_broadcast(&sc->sc_cv); 354 1.120 riastrad mutex_exit(&sc->sc_lock); 355 1.120 riastrad 356 1.123 riastrad uhidev_stop(sc->sc_hdev); 357 1.120 riastrad 358 1.120 riastrad return 0; 359 1.120 riastrad } 360 1.120 riastrad 361 1.120 riastrad static int 362 1.88 mrg uhidclose(dev_t dev, int flag, int mode, struct lwp *l) 363 1.1 augustss { 364 1.120 riastrad struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 365 1.1 augustss 366 1.1 augustss DPRINTF(("uhidclose: sc=%p\n", sc)); 367 1.120 riastrad if (sc == NULL) 368 1.120 riastrad return 0; 369 1.1 augustss 370 1.115 riastrad mutex_enter(&sc->sc_lock); 371 1.120 riastrad KASSERT(sc->sc_closing); 372 1.120 riastrad KASSERTMSG(sc->sc_open == UHID_OPEN || sc->sc_open == UHID_CLOSED, 373 1.120 riastrad "sc_open=%d", sc->sc_open); 374 1.120 riastrad if (sc->sc_open == UHID_CLOSED) 375 1.120 riastrad goto out; 376 1.120 riastrad 377 1.120 riastrad /* Release the lock while we free things. */ 378 1.115 riastrad mutex_exit(&sc->sc_lock); 379 1.115 riastrad 380 1.115 riastrad /* Prevent further interrupts. */ 381 1.123 riastrad uhidev_close(sc->sc_hdev); 382 1.115 riastrad 383 1.115 riastrad /* Hang up all select/poll. */ 384 1.115 riastrad selnotify(&sc->sc_rsel, POLLHUP, 0); 385 1.115 riastrad 386 1.115 riastrad /* Reset SIGIO. */ 387 1.114 ad mutex_enter(&proc_lock); 388 1.116 riastrad atomic_store_relaxed(&sc->sc_async, NULL); 389 1.114 ad mutex_exit(&proc_lock); 390 1.88 mrg 391 1.115 riastrad /* Free the buffer and queue. */ 392 1.115 riastrad if (sc->sc_osize > 0) { 393 1.115 riastrad kmem_free(sc->sc_obuf, sc->sc_osize); 394 1.115 riastrad sc->sc_obuf = NULL; 395 1.115 riastrad } 396 1.115 riastrad clfree(&sc->sc_q); 397 1.115 riastrad 398 1.120 riastrad mutex_enter(&sc->sc_lock); 399 1.120 riastrad 400 1.115 riastrad /* All set. We are now closed. */ 401 1.120 riastrad sc->sc_open = UHID_CLOSED; 402 1.120 riastrad out: KASSERT(sc->sc_open == UHID_CLOSED); 403 1.120 riastrad sc->sc_closing = false; 404 1.115 riastrad atomic_store_relaxed(&sc->sc_state, 0); 405 1.115 riastrad mutex_exit(&sc->sc_lock); 406 1.93 mrg 407 1.115 riastrad return 0; 408 1.115 riastrad } 409 1.115 riastrad 410 1.115 riastrad static int 411 1.120 riastrad uhidread(dev_t dev, struct uio *uio, int flag) 412 1.1 augustss { 413 1.120 riastrad struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 414 1.1 augustss int error = 0; 415 1.47 augustss int extra; 416 1.1 augustss size_t length; 417 1.1 augustss u_char buffer[UHID_CHUNK]; 418 1.27 augustss usbd_status err; 419 1.1 augustss 420 1.1 augustss DPRINTFN(1, ("uhidread\n")); 421 1.115 riastrad if (atomic_load_relaxed(&sc->sc_state) & UHID_IMMED) { 422 1.2 augustss DPRINTFN(1, ("uhidread immed\n")); 423 1.123 riastrad extra = sc->sc_report_id != 0; 424 1.111 maxv if (sc->sc_isize + extra > sizeof(buffer)) 425 1.111 maxv return ENOBUFS; 426 1.123 riastrad err = uhidev_get_report(sc->sc_hdev, UHID_INPUT_REPORT, 427 1.47 augustss buffer, sc->sc_isize + extra); 428 1.27 augustss if (err) 429 1.93 mrg return EIO; 430 1.93 mrg return uiomove(buffer+extra, sc->sc_isize, uio); 431 1.2 augustss } 432 1.2 augustss 433 1.88 mrg mutex_enter(&sc->sc_lock); 434 1.1 augustss while (sc->sc_q.c_cc == 0) { 435 1.1 augustss if (flag & IO_NDELAY) { 436 1.88 mrg mutex_exit(&sc->sc_lock); 437 1.93 mrg return EWOULDBLOCK; 438 1.1 augustss } 439 1.120 riastrad if (sc->sc_closing) { 440 1.115 riastrad mutex_exit(&sc->sc_lock); 441 1.115 riastrad return EIO; 442 1.115 riastrad } 443 1.44 yamt DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q)); 444 1.88 mrg error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock); 445 1.1 augustss DPRINTFN(5, ("uhidread: woke, error=%d\n", error)); 446 1.1 augustss if (error) { 447 1.18 augustss break; 448 1.1 augustss } 449 1.1 augustss } 450 1.1 augustss 451 1.1 augustss /* Transfer as many chunks as possible. */ 452 1.18 augustss while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) { 453 1.102 riastrad length = uimin(sc->sc_q.c_cc, uio->uio_resid); 454 1.1 augustss if (length > sizeof(buffer)) 455 1.1 augustss length = sizeof(buffer); 456 1.1 augustss 457 1.1 augustss /* Remove a small chunk from the input queue. */ 458 1.1 augustss (void) q_to_b(&sc->sc_q, buffer, length); 459 1.29 augustss DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length)); 460 1.1 augustss 461 1.1 augustss /* Copy the data to the user process. */ 462 1.93 mrg mutex_exit(&sc->sc_lock); 463 1.1 augustss if ((error = uiomove(buffer, length, uio)) != 0) 464 1.93 mrg return error; 465 1.93 mrg mutex_enter(&sc->sc_lock); 466 1.1 augustss } 467 1.1 augustss 468 1.93 mrg mutex_exit(&sc->sc_lock); 469 1.93 mrg return error; 470 1.1 augustss } 471 1.1 augustss 472 1.109 maxv static int 473 1.120 riastrad uhidwrite(dev_t dev, struct uio *uio, int flag) 474 1.18 augustss { 475 1.120 riastrad struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 476 1.1 augustss int error; 477 1.1 augustss int size; 478 1.27 augustss usbd_status err; 479 1.1 augustss 480 1.18 augustss DPRINTFN(1, ("uhidwrite\n")); 481 1.52 augustss 482 1.1 augustss size = sc->sc_osize; 483 1.97 mlelstv if (uio->uio_resid != size || size == 0) 484 1.93 mrg return EINVAL; 485 1.18 augustss error = uiomove(sc->sc_obuf, size, uio); 486 1.112 christos #ifdef UHID_DEBUG 487 1.112 christos if (uhiddebug > 5) { 488 1.112 christos uint32_t i; 489 1.112 christos 490 1.123 riastrad DPRINTF(("%s: outdata[%d] =", device_xname(sc->sc_dev), 491 1.112 christos error)); 492 1.112 christos for (i = 0; i < size; i++) 493 1.112 christos DPRINTF((" %02x", sc->sc_obuf[i])); 494 1.112 christos DPRINTF(("\n")); 495 1.112 christos } 496 1.112 christos #endif 497 1.18 augustss if (!error) { 498 1.112 christos if (sc->sc_raw) 499 1.123 riastrad err = uhidev_write(sc->sc_hdev, sc->sc_obuf, size); 500 1.112 christos else 501 1.123 riastrad err = uhidev_set_report(sc->sc_hdev, 502 1.112 christos UHID_OUTPUT_REPORT, sc->sc_obuf, size); 503 1.112 christos if (err) { 504 1.112 christos DPRINTF(("%s: err = %d\n", 505 1.123 riastrad device_xname(sc->sc_dev), err)); 506 1.1 augustss error = EIO; 507 1.112 christos } 508 1.1 augustss } 509 1.18 augustss 510 1.93 mrg return error; 511 1.1 augustss } 512 1.1 augustss 513 1.120 riastrad static int 514 1.120 riastrad uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 515 1.1 augustss { 516 1.120 riastrad struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 517 1.1 augustss struct usb_ctl_report_desc *rd; 518 1.2 augustss struct usb_ctl_report *re; 519 1.47 augustss u_char buffer[UHID_CHUNK]; 520 1.47 augustss int size, extra; 521 1.27 augustss usbd_status err; 522 1.47 augustss void *desc; 523 1.1 augustss 524 1.18 augustss DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); 525 1.18 augustss 526 1.1 augustss switch (cmd) { 527 1.2 augustss case FIONBIO: 528 1.2 augustss /* All handled in the upper FS layer. */ 529 1.37 augustss break; 530 1.37 augustss 531 1.37 augustss case FIOASYNC: 532 1.114 ad mutex_enter(&proc_lock); 533 1.37 augustss if (*(int *)addr) { 534 1.111 maxv if (sc->sc_async != NULL) { 535 1.114 ad mutex_exit(&proc_lock); 536 1.93 mrg return EBUSY; 537 1.111 maxv } 538 1.116 riastrad atomic_store_relaxed(&sc->sc_async, l->l_proc); 539 1.68 christos DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", l->l_proc)); 540 1.37 augustss } else 541 1.116 riastrad atomic_store_relaxed(&sc->sc_async, NULL); 542 1.114 ad mutex_exit(&proc_lock); 543 1.37 augustss break; 544 1.37 augustss 545 1.37 augustss /* XXX this is not the most general solution. */ 546 1.37 augustss case TIOCSPGRP: 547 1.114 ad mutex_enter(&proc_lock); 548 1.80 ad if (sc->sc_async == NULL) { 549 1.114 ad mutex_exit(&proc_lock); 550 1.93 mrg return EINVAL; 551 1.80 ad } 552 1.80 ad if (*(int *)addr != sc->sc_async->p_pgid) { 553 1.114 ad mutex_exit(&proc_lock); 554 1.93 mrg return EPERM; 555 1.80 ad } 556 1.114 ad mutex_exit(&proc_lock); 557 1.60 jdolecek break; 558 1.60 jdolecek 559 1.60 jdolecek case FIOSETOWN: 560 1.114 ad mutex_enter(&proc_lock); 561 1.80 ad if (sc->sc_async == NULL) { 562 1.114 ad mutex_exit(&proc_lock); 563 1.93 mrg return EINVAL; 564 1.80 ad } 565 1.60 jdolecek if (-*(int *)addr != sc->sc_async->p_pgid 566 1.80 ad && *(int *)addr != sc->sc_async->p_pid) { 567 1.114 ad mutex_exit(&proc_lock); 568 1.93 mrg return EPERM; 569 1.80 ad } 570 1.114 ad mutex_exit(&proc_lock); 571 1.2 augustss break; 572 1.2 augustss 573 1.113 christos case USB_HID_GET_RAW: 574 1.113 christos *(int *)addr = sc->sc_raw; 575 1.113 christos break; 576 1.113 christos 577 1.113 christos case USB_HID_SET_RAW: 578 1.113 christos sc->sc_raw = *(int *)addr; 579 1.113 christos break; 580 1.113 christos 581 1.1 augustss case USB_GET_REPORT_DESC: 582 1.123 riastrad uhidev_get_report_desc(sc->sc_hdev, &desc, &size); 583 1.1 augustss rd = (struct usb_ctl_report_desc *)addr; 584 1.102 riastrad size = uimin(size, sizeof(rd->ucrd_data)); 585 1.50 christos rd->ucrd_size = size; 586 1.50 christos memcpy(rd->ucrd_data, desc, size); 587 1.1 augustss break; 588 1.2 augustss 589 1.2 augustss case USB_SET_IMMED: 590 1.9 augustss if (*(int *)addr) { 591 1.123 riastrad extra = sc->sc_report_id != 0; 592 1.111 maxv if (sc->sc_isize + extra > sizeof(buffer)) 593 1.111 maxv return ENOBUFS; 594 1.123 riastrad err = uhidev_get_report(sc->sc_hdev, UHID_INPUT_REPORT, 595 1.47 augustss buffer, sc->sc_isize + extra); 596 1.27 augustss if (err) 597 1.93 mrg return EOPNOTSUPP; 598 1.12 augustss 599 1.115 riastrad atomic_or_32(&sc->sc_state, UHID_IMMED); 600 1.9 augustss } else 601 1.115 riastrad atomic_and_32(&sc->sc_state, ~UHID_IMMED); 602 1.2 augustss break; 603 1.2 augustss 604 1.2 augustss case USB_GET_REPORT: 605 1.2 augustss re = (struct usb_ctl_report *)addr; 606 1.50 christos switch (re->ucr_report) { 607 1.2 augustss case UHID_INPUT_REPORT: 608 1.2 augustss size = sc->sc_isize; 609 1.2 augustss break; 610 1.2 augustss case UHID_OUTPUT_REPORT: 611 1.2 augustss size = sc->sc_osize; 612 1.2 augustss break; 613 1.2 augustss case UHID_FEATURE_REPORT: 614 1.2 augustss size = sc->sc_fsize; 615 1.2 augustss break; 616 1.2 augustss default: 617 1.93 mrg return EINVAL; 618 1.2 augustss } 619 1.123 riastrad extra = sc->sc_report_id != 0; 620 1.111 maxv if (size + extra > sizeof(re->ucr_data)) 621 1.111 maxv return ENOBUFS; 622 1.123 riastrad err = uhidev_get_report(sc->sc_hdev, re->ucr_report, 623 1.50 christos re->ucr_data, size + extra); 624 1.47 augustss if (extra) 625 1.99 maya memmove(re->ucr_data, re->ucr_data+1, size); 626 1.35 augustss if (err) 627 1.93 mrg return EIO; 628 1.35 augustss break; 629 1.35 augustss 630 1.35 augustss case USB_SET_REPORT: 631 1.35 augustss re = (struct usb_ctl_report *)addr; 632 1.50 christos switch (re->ucr_report) { 633 1.35 augustss case UHID_INPUT_REPORT: 634 1.35 augustss size = sc->sc_isize; 635 1.35 augustss break; 636 1.35 augustss case UHID_OUTPUT_REPORT: 637 1.35 augustss size = sc->sc_osize; 638 1.35 augustss break; 639 1.35 augustss case UHID_FEATURE_REPORT: 640 1.35 augustss size = sc->sc_fsize; 641 1.35 augustss break; 642 1.35 augustss default: 643 1.93 mrg return EINVAL; 644 1.35 augustss } 645 1.111 maxv if (size > sizeof(re->ucr_data)) 646 1.111 maxv return ENOBUFS; 647 1.123 riastrad err = uhidev_set_report(sc->sc_hdev, re->ucr_report, 648 1.50 christos re->ucr_data, size); 649 1.27 augustss if (err) 650 1.93 mrg return EIO; 651 1.2 augustss break; 652 1.2 augustss 653 1.47 augustss case USB_GET_REPORT_ID: 654 1.123 riastrad *(int *)addr = sc->sc_report_id; 655 1.47 augustss break; 656 1.47 augustss 657 1.87 erh case USB_GET_DEVICE_DESC: 658 1.87 erh *(usb_device_descriptor_t *)addr = 659 1.122 riastrad *usbd_get_device_descriptor(sc->sc_udev); 660 1.87 erh break; 661 1.87 erh 662 1.61 jdolecek case USB_GET_DEVICEINFO: 663 1.122 riastrad usbd_fill_deviceinfo(sc->sc_udev, 664 1.95 skrll (struct usb_device_info *)addr, 0); 665 1.61 jdolecek break; 666 1.128 christos case USB_GET_DEVICEINFO_30: 667 1.106 pgoyette MODULE_HOOK_CALL(usb_subr_fill_30_hook, 668 1.122 riastrad (sc->sc_udev, 669 1.128 christos (struct usb_device_info30 *)addr, 0, 670 1.103 pgoyette usbd_devinfo_vp, usbd_printBCD), 671 1.103 pgoyette enosys(), err); 672 1.103 pgoyette if (err == 0) 673 1.103 pgoyette return 0; 674 1.73 pavel break; 675 1.95 skrll case USB_GET_STRING_DESC: 676 1.61 jdolecek { 677 1.95 skrll struct usb_string_desc *si = (struct usb_string_desc *)addr; 678 1.122 riastrad err = usbd_get_string_desc(sc->sc_udev, 679 1.61 jdolecek si->usd_string_index, 680 1.95 skrll si->usd_language_id, &si->usd_desc, &size); 681 1.95 skrll if (err) 682 1.95 skrll return EINVAL; 683 1.95 skrll break; 684 1.61 jdolecek } 685 1.61 jdolecek 686 1.1 augustss default: 687 1.93 mrg return EINVAL; 688 1.1 augustss } 689 1.93 mrg return 0; 690 1.1 augustss } 691 1.1 augustss 692 1.109 maxv static int 693 1.68 christos uhidpoll(dev_t dev, int events, struct lwp *l) 694 1.1 augustss { 695 1.120 riastrad struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 696 1.1 augustss int revents = 0; 697 1.25 augustss 698 1.88 mrg mutex_enter(&sc->sc_lock); 699 1.1 augustss if (events & (POLLOUT | POLLWRNORM)) 700 1.1 augustss revents |= events & (POLLOUT | POLLWRNORM); 701 1.4 veego if (events & (POLLIN | POLLRDNORM)) { 702 1.1 augustss if (sc->sc_q.c_cc > 0) 703 1.1 augustss revents |= events & (POLLIN | POLLRDNORM); 704 1.1 augustss else 705 1.68 christos selrecord(l, &sc->sc_rsel); 706 1.4 veego } 707 1.88 mrg mutex_exit(&sc->sc_lock); 708 1.1 augustss 709 1.93 mrg return revents; 710 1.55 jdolecek } 711 1.55 jdolecek 712 1.55 jdolecek static void 713 1.55 jdolecek filt_uhidrdetach(struct knote *kn) 714 1.55 jdolecek { 715 1.55 jdolecek struct uhid_softc *sc = kn->kn_hook; 716 1.55 jdolecek 717 1.88 mrg mutex_enter(&sc->sc_lock); 718 1.117 thorpej selremove_knote(&sc->sc_rsel, kn); 719 1.88 mrg mutex_exit(&sc->sc_lock); 720 1.55 jdolecek } 721 1.55 jdolecek 722 1.55 jdolecek static int 723 1.72 christos filt_uhidread(struct knote *kn, long hint) 724 1.55 jdolecek { 725 1.55 jdolecek struct uhid_softc *sc = kn->kn_hook; 726 1.55 jdolecek 727 1.115 riastrad if (hint == NOTE_SUBMIT) 728 1.115 riastrad KASSERT(mutex_owned(&sc->sc_lock)); 729 1.115 riastrad else 730 1.115 riastrad mutex_enter(&sc->sc_lock); 731 1.115 riastrad 732 1.55 jdolecek kn->kn_data = sc->sc_q.c_cc; 733 1.115 riastrad 734 1.115 riastrad if (hint == NOTE_SUBMIT) 735 1.115 riastrad KASSERT(mutex_owned(&sc->sc_lock)); 736 1.115 riastrad else 737 1.115 riastrad mutex_exit(&sc->sc_lock); 738 1.115 riastrad 739 1.95 skrll return kn->kn_data > 0; 740 1.55 jdolecek } 741 1.55 jdolecek 742 1.100 maya static const struct filterops uhidread_filtops = { 743 1.118 thorpej .f_flags = FILTEROP_ISFD, 744 1.100 maya .f_attach = NULL, 745 1.100 maya .f_detach = filt_uhidrdetach, 746 1.100 maya .f_event = filt_uhidread, 747 1.100 maya }; 748 1.55 jdolecek 749 1.109 maxv static int 750 1.55 jdolecek uhidkqfilter(dev_t dev, struct knote *kn) 751 1.55 jdolecek { 752 1.120 riastrad struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 753 1.55 jdolecek 754 1.55 jdolecek switch (kn->kn_filter) { 755 1.55 jdolecek case EVFILT_READ: 756 1.55 jdolecek kn->kn_fop = &uhidread_filtops; 757 1.119 thorpej kn->kn_hook = sc; 758 1.119 thorpej mutex_enter(&sc->sc_lock); 759 1.119 thorpej selrecord_knote(&sc->sc_rsel, kn); 760 1.119 thorpej mutex_exit(&sc->sc_lock); 761 1.125 christos return 0; 762 1.119 thorpej 763 1.55 jdolecek case EVFILT_WRITE: 764 1.119 thorpej kn->kn_fop = &seltrue_filtops; 765 1.125 christos return 0; 766 1.119 thorpej 767 1.55 jdolecek default: 768 1.125 christos return EINVAL; 769 1.55 jdolecek } 770 1.1 augustss } 771