1 1.95 mrg /* $NetBSD: uhidev.c,v 1.95 2024/02/04 05:43:06 mrg Exp $ */ 2 1.1 augustss 3 1.1 augustss /* 4 1.56 mrg * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. 5 1.1 augustss * All rights reserved. 6 1.1 augustss * 7 1.1 augustss * This code is derived from software contributed to The NetBSD Foundation 8 1.1 augustss * by Lennart Augustsson (lennart (at) augustsson.net) at 9 1.95 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.1 augustss /* 34 1.14 augustss * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 35 1.1 augustss */ 36 1.15 lukem 37 1.15 lukem #include <sys/cdefs.h> 38 1.95 mrg __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.95 2024/02/04 05:43:06 mrg Exp $"); 39 1.66 jakllsch 40 1.66 jakllsch #ifdef _KERNEL_OPT 41 1.66 jakllsch #include "opt_usb.h" 42 1.66 jakllsch #endif 43 1.1 augustss 44 1.1 augustss #include <sys/param.h> 45 1.79 riastrad #include <sys/types.h> 46 1.79 riastrad 47 1.89 riastrad #include <sys/atomic.h> 48 1.79 riastrad #include <sys/conf.h> 49 1.79 riastrad #include <sys/device.h> 50 1.79 riastrad #include <sys/ioctl.h> 51 1.1 augustss #include <sys/kernel.h> 52 1.65 skrll #include <sys/kmem.h> 53 1.79 riastrad #include <sys/lwp.h> 54 1.79 riastrad #include <sys/rndsource.h> 55 1.1 augustss #include <sys/signalvar.h> 56 1.79 riastrad #include <sys/systm.h> 57 1.89 riastrad #include <sys/xcall.h> 58 1.1 augustss 59 1.1 augustss #include <dev/usb/usb.h> 60 1.1 augustss #include <dev/usb/usbhid.h> 61 1.1 augustss 62 1.1 augustss #include <dev/usb/usbdevs.h> 63 1.1 augustss #include <dev/usb/usbdi.h> 64 1.1 augustss #include <dev/usb/usbdi_util.h> 65 1.1 augustss #include <dev/usb/usb_quirks.h> 66 1.1 augustss 67 1.1 augustss #include <dev/usb/uhidev.h> 68 1.73 bouyer #include <dev/hid/hid.h> 69 1.1 augustss 70 1.1 augustss /* Report descriptor for broken Wacom Graphire */ 71 1.1 augustss #include <dev/usb/ugraphire_rdesc.h> 72 1.51 jmcneill /* Report descriptor for game controllers in "XInput" mode */ 73 1.51 jmcneill #include <dev/usb/xinput_rdesc.h> 74 1.62 jmcneill /* Report descriptor for Xbox One controllers */ 75 1.62 jmcneill #include <dev/usb/x1input_rdesc.h> 76 1.1 augustss 77 1.22 drochner #include "locators.h" 78 1.22 drochner 79 1.85 riastrad struct uhidev_softc { 80 1.85 riastrad device_t sc_dev; /* base device */ 81 1.85 riastrad struct usbd_device *sc_udev; 82 1.85 riastrad struct usbd_interface *sc_iface; /* interface */ 83 1.85 riastrad int sc_iep_addr; 84 1.85 riastrad int sc_oep_addr; 85 1.85 riastrad u_int sc_isize; 86 1.85 riastrad 87 1.85 riastrad int sc_repdesc_size; 88 1.85 riastrad void *sc_repdesc; 89 1.85 riastrad 90 1.85 riastrad u_int sc_nrepid; 91 1.90 riastrad struct uhidev { 92 1.90 riastrad struct uhidev_softc *sc_parent; 93 1.90 riastrad device_t sc_dev; 94 1.90 riastrad void (*sc_intr)(void *, void *, u_int); 95 1.90 riastrad void *sc_cookie; 96 1.90 riastrad krndsource_t sc_rndsource; 97 1.90 riastrad int sc_in_rep_size; 98 1.90 riastrad uint8_t sc_report_id; 99 1.90 riastrad uint8_t sc_state; 100 1.90 riastrad #define UHIDEV_OPEN 0x01 /* device is open */ 101 1.90 riastrad #define UHIDEV_STOPPED 0x02 /* xfers are stopped */ 102 1.90 riastrad } *sc_subdevs; 103 1.85 riastrad 104 1.85 riastrad kmutex_t sc_lock; 105 1.85 riastrad kcondvar_t sc_cv; 106 1.85 riastrad 107 1.85 riastrad /* Read/written under sc_lock. */ 108 1.85 riastrad struct lwp *sc_writelock; 109 1.85 riastrad struct lwp *sc_configlock; 110 1.85 riastrad int sc_refcnt; 111 1.85 riastrad int sc_writereportid; 112 1.86 riastrad int sc_stopreportid; 113 1.85 riastrad 114 1.85 riastrad /* 115 1.85 riastrad * - Read under sc_lock, provided sc_refcnt > 0. 116 1.85 riastrad * - Written under sc_configlock only when transitioning to and 117 1.85 riastrad * from sc_refcnt = 0. 118 1.85 riastrad */ 119 1.85 riastrad u_char *sc_ibuf; 120 1.85 riastrad struct usbd_pipe *sc_ipipe; /* input interrupt pipe */ 121 1.85 riastrad struct usbd_pipe *sc_opipe; /* output interrupt pipe */ 122 1.85 riastrad struct usbd_xfer *sc_oxfer; /* write request */ 123 1.85 riastrad usbd_callback sc_writecallback; /* async write request callback */ 124 1.85 riastrad void *sc_writecookie; 125 1.85 riastrad 126 1.85 riastrad u_int sc_flags; 127 1.85 riastrad #define UHIDEV_F_XB1 0x0001 /* Xbox 1 controller */ 128 1.85 riastrad }; 129 1.85 riastrad 130 1.1 augustss #ifdef UHIDEV_DEBUG 131 1.48 dyoung #define DPRINTF(x) if (uhidevdebug) printf x 132 1.48 dyoung #define DPRINTFN(n,x) if (uhidevdebug>(n)) printf x 133 1.1 augustss int uhidevdebug = 0; 134 1.1 augustss #else 135 1.1 augustss #define DPRINTF(x) 136 1.1 augustss #define DPRINTFN(n,x) 137 1.1 augustss #endif 138 1.1 augustss 139 1.87 riastrad static void uhidev_intr(struct usbd_xfer *, void *, usbd_status); 140 1.1 augustss 141 1.87 riastrad static int uhidev_maxrepid(void *, int); 142 1.87 riastrad static int uhidevprint(void *, const char *); 143 1.1 augustss 144 1.76 maxv static int uhidev_match(device_t, cfdata_t, void *); 145 1.76 maxv static void uhidev_attach(device_t, device_t, void *); 146 1.76 maxv static void uhidev_childdet(device_t, device_t); 147 1.76 maxv static int uhidev_detach(device_t, int); 148 1.75 mrg 149 1.41 cube CFATTACH_DECL2_NEW(uhidev, sizeof(struct uhidev_softc), uhidev_match, 150 1.91 riastrad uhidev_attach, uhidev_detach, NULL, NULL, uhidev_childdet); 151 1.1 augustss 152 1.76 maxv static int 153 1.48 dyoung uhidev_match(device_t parent, cfdata_t match, void *aux) 154 1.1 augustss { 155 1.65 skrll struct usbif_attach_arg *uiaa = aux; 156 1.6 augustss 157 1.51 jmcneill /* Game controllers in "XInput" mode */ 158 1.65 skrll if (USBIF_IS_XINPUT(uiaa)) 159 1.51 jmcneill return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; 160 1.62 jmcneill /* Xbox One controllers */ 161 1.69 skrll if (USBIF_IS_X1INPUT(uiaa) && uiaa->uiaa_ifaceno == 0) 162 1.62 jmcneill return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; 163 1.62 jmcneill 164 1.65 skrll if (uiaa->uiaa_class != UICLASS_HID) 165 1.65 skrll return UMATCH_NONE; 166 1.65 skrll if (usbd_get_quirks(uiaa->uiaa_device)->uq_flags & UQ_HID_IGNORE) 167 1.65 skrll return UMATCH_NONE; 168 1.65 skrll return UMATCH_IFACECLASS_GENERIC; 169 1.1 augustss } 170 1.1 augustss 171 1.76 maxv static void 172 1.48 dyoung uhidev_attach(device_t parent, device_t self, void *aux) 173 1.1 augustss { 174 1.48 dyoung struct uhidev_softc *sc = device_private(self); 175 1.65 skrll struct usbif_attach_arg *uiaa = aux; 176 1.65 skrll struct usbd_interface *iface = uiaa->uiaa_iface; 177 1.1 augustss usb_interface_descriptor_t *id; 178 1.1 augustss usb_endpoint_descriptor_t *ed; 179 1.1 augustss struct uhidev_attach_arg uha; 180 1.42 drochner device_t dev; 181 1.44 rafal int maxinpktsize, size, nrepid, repid, repsz; 182 1.32 christos int *repsizes; 183 1.25 skrll int i; 184 1.19 jdolecek void *desc; 185 1.20 augustss const void *descptr; 186 1.1 augustss usbd_status err; 187 1.26 augustss char *devinfop; 188 1.28 drochner int locs[UHIDBUSCF_NLOCS]; 189 1.6 augustss 190 1.41 cube sc->sc_dev = self; 191 1.65 skrll sc->sc_udev = uiaa->uiaa_device; 192 1.1 augustss sc->sc_iface = iface; 193 1.43 plunky 194 1.43 plunky aprint_naive("\n"); 195 1.43 plunky aprint_normal("\n"); 196 1.43 plunky 197 1.65 skrll mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); 198 1.79 riastrad cv_init(&sc->sc_cv, "uhidev"); 199 1.79 riastrad sc->sc_writelock = NULL; 200 1.79 riastrad sc->sc_configlock = NULL; 201 1.86 riastrad sc->sc_refcnt = 0; 202 1.86 riastrad sc->sc_writereportid = -1; 203 1.86 riastrad sc->sc_stopreportid = -1; 204 1.56 mrg 205 1.1 augustss id = usbd_get_interface_descriptor(iface); 206 1.26 augustss 207 1.65 skrll devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0); 208 1.41 cube aprint_normal_dev(self, "%s, iclass %d/%d\n", 209 1.26 augustss devinfop, id->bInterfaceClass, id->bInterfaceSubClass); 210 1.26 augustss usbd_devinfo_free(devinfop); 211 1.1 augustss 212 1.38 jmcneill if (!pmf_device_register(self, NULL, NULL)) 213 1.38 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 214 1.38 jmcneill 215 1.72 ryoon if (uiaa->uiaa_vendor == USB_VENDOR_WACOM) { 216 1.72 ryoon if (uiaa->uiaa_product == USB_PRODUCT_WACOM_XD0912U) { 217 1.72 ryoon /* 218 1.72 ryoon * Wacom Intuos2 (XD-0912-U) requires longer idle time to 219 1.72 ryoon * initialize the device with 0x0202. 220 1.72 ryoon */ 221 1.72 ryoon DELAY(500000); 222 1.72 ryoon } 223 1.72 ryoon } 224 1.1 augustss (void)usbd_set_idle(iface, 0, 0); 225 1.1 augustss 226 1.94 jmcneill if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_NO_SET_PROTO) == 0) 227 1.1 augustss (void)usbd_set_protocol(iface, 1); 228 1.1 augustss 229 1.44 rafal maxinpktsize = 0; 230 1.25 skrll sc->sc_iep_addr = sc->sc_oep_addr = -1; 231 1.25 skrll for (i = 0; i < id->bNumEndpoints; i++) { 232 1.25 skrll ed = usbd_interface2endpoint_descriptor(iface, i); 233 1.25 skrll if (ed == NULL) { 234 1.41 cube aprint_error_dev(self, 235 1.41 cube "could not read endpoint descriptor\n"); 236 1.48 dyoung return; 237 1.25 skrll } 238 1.25 skrll 239 1.25 skrll DPRINTFN(10,("uhidev_attach: bLength=%d bDescriptorType=%d " 240 1.25 skrll "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" 241 1.25 skrll " bInterval=%d\n", 242 1.25 skrll ed->bLength, ed->bDescriptorType, 243 1.25 skrll ed->bEndpointAddress & UE_ADDR, 244 1.25 skrll UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", 245 1.25 skrll ed->bmAttributes & UE_XFERTYPE, 246 1.25 skrll UGETW(ed->wMaxPacketSize), ed->bInterval)); 247 1.25 skrll 248 1.25 skrll if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 249 1.25 skrll (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { 250 1.44 rafal maxinpktsize = UGETW(ed->wMaxPacketSize); 251 1.25 skrll sc->sc_iep_addr = ed->bEndpointAddress; 252 1.25 skrll } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 253 1.25 skrll (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { 254 1.25 skrll sc->sc_oep_addr = ed->bEndpointAddress; 255 1.25 skrll } else { 256 1.41 cube aprint_verbose_dev(self, "endpoint %d: ignored\n", i); 257 1.25 skrll } 258 1.1 augustss } 259 1.1 augustss 260 1.25 skrll /* 261 1.25 skrll * Check that we found an input interrupt endpoint. The output interrupt 262 1.25 skrll * endpoint is optional 263 1.25 skrll */ 264 1.25 skrll if (sc->sc_iep_addr == -1) { 265 1.41 cube aprint_error_dev(self, "no input interrupt endpoint\n"); 266 1.48 dyoung return; 267 1.1 augustss } 268 1.1 augustss 269 1.1 augustss /* XXX need to extend this */ 270 1.20 augustss descptr = NULL; 271 1.65 skrll if (uiaa->uiaa_vendor == USB_VENDOR_WACOM) { 272 1.72 ryoon static uByte reportbuf[3]; 273 1.17 augustss 274 1.1 augustss /* The report descriptor for the Wacom Graphire is broken. */ 275 1.65 skrll switch (uiaa->uiaa_product) { 276 1.33 ghen case USB_PRODUCT_WACOM_GRAPHIRE3_4X5: 277 1.33 ghen case USB_PRODUCT_WACOM_GRAPHIRE3_6X8: 278 1.33 ghen case USB_PRODUCT_WACOM_GRAPHIRE4_4X5: /* The 6x8 too? */ 279 1.17 augustss /* 280 1.17 augustss * The Graphire3 needs 0x0202 to be written to 281 1.17 augustss * feature report ID 2 before it'll start 282 1.17 augustss * returning digitizer data. 283 1.17 augustss */ 284 1.72 ryoon reportbuf[0] = 0x02; 285 1.72 ryoon reportbuf[1] = 0x02; 286 1.65 skrll usbd_set_report(uiaa->uiaa_iface, UHID_FEATURE_REPORT, 2, 287 1.72 ryoon &reportbuf, 2); 288 1.17 augustss 289 1.65 skrll size = sizeof(uhid_graphire3_4x5_report_descr); 290 1.17 augustss descptr = uhid_graphire3_4x5_report_descr; 291 1.17 augustss break; 292 1.72 ryoon case USB_PRODUCT_WACOM_GRAPHIRE: 293 1.72 ryoon case USB_PRODUCT_WACOM_GRAPHIRE2: 294 1.72 ryoon case USB_PRODUCT_WACOM_XD0912U: 295 1.72 ryoon case USB_PRODUCT_WACOM_CTH690K0: 296 1.72 ryoon reportbuf[0] = 0x02; 297 1.72 ryoon reportbuf[1] = 0x02; 298 1.72 ryoon usbd_set_report(uiaa->uiaa_iface, UHID_FEATURE_REPORT, 2, 299 1.72 ryoon &reportbuf, 2); 300 1.72 ryoon break; 301 1.20 augustss default: 302 1.20 augustss /* Keep descriptor */ 303 1.20 augustss break; 304 1.17 augustss } 305 1.17 augustss } 306 1.65 skrll if (USBIF_IS_XINPUT(uiaa)) { 307 1.65 skrll size = sizeof(uhid_xinput_report_descr); 308 1.51 jmcneill descptr = uhid_xinput_report_descr; 309 1.51 jmcneill } 310 1.65 skrll if (USBIF_IS_X1INPUT(uiaa)) { 311 1.62 jmcneill sc->sc_flags |= UHIDEV_F_XB1; 312 1.65 skrll size = sizeof(uhid_x1input_report_descr); 313 1.62 jmcneill descptr = uhid_x1input_report_descr; 314 1.62 jmcneill } 315 1.17 augustss 316 1.17 augustss if (descptr) { 317 1.65 skrll desc = kmem_alloc(size, KM_SLEEP); 318 1.70 chs err = USBD_NORMAL_COMPLETION; 319 1.70 chs memcpy(desc, descptr, size); 320 1.1 augustss } else { 321 1.1 augustss desc = NULL; 322 1.65 skrll err = usbd_read_report_desc(uiaa->uiaa_iface, &desc, &size); 323 1.1 augustss } 324 1.1 augustss if (err) { 325 1.41 cube aprint_error_dev(self, "no report descriptor\n"); 326 1.48 dyoung return; 327 1.1 augustss } 328 1.6 augustss 329 1.65 skrll if (uiaa->uiaa_vendor == USB_VENDOR_HOSIDEN && 330 1.65 skrll uiaa->uiaa_product == USB_PRODUCT_HOSIDEN_PPP) { 331 1.27 augustss static uByte reportbuf[] = { 1 }; 332 1.27 augustss /* 333 1.58 skrll * This device was sold by Konami with its ParaParaParadise 334 1.27 augustss * game for PlayStation2. It needs to be "turned on" 335 1.27 augustss * before it will send any reports. 336 1.27 augustss */ 337 1.27 augustss 338 1.65 skrll usbd_set_report(uiaa->uiaa_iface, UHID_FEATURE_REPORT, 0, 339 1.65 skrll &reportbuf, sizeof(reportbuf)); 340 1.27 augustss } 341 1.27 augustss 342 1.65 skrll if (uiaa->uiaa_vendor == USB_VENDOR_LOGITECH && 343 1.65 skrll uiaa->uiaa_product == USB_PRODUCT_LOGITECH_CBT44 && size == 0xb1) { 344 1.47 jakllsch uint8_t *data = desc; 345 1.47 jakllsch /* 346 1.47 jakllsch * This device has a odd USAGE_MINIMUM value that would 347 1.47 jakllsch * cause the multimedia keys to have their usage number 348 1.47 jakllsch * shifted up one usage. Adjust so the usages are sane. 349 1.47 jakllsch */ 350 1.47 jakllsch 351 1.47 jakllsch if (data[0x56] == 0x19 && data[0x57] == 0x01 && 352 1.47 jakllsch data[0x58] == 0x2a && data[0x59] == 0x8c) 353 1.47 jakllsch data[0x57] = 0x00; 354 1.47 jakllsch } 355 1.47 jakllsch 356 1.52 aymeric /* 357 1.52 aymeric * Enable the Six Axis and DualShock 3 controllers. 358 1.52 aymeric * See http://ps3.jim.sh/sixaxis/usb/ 359 1.52 aymeric */ 360 1.65 skrll if (uiaa->uiaa_vendor == USB_VENDOR_SONY && 361 1.65 skrll uiaa->uiaa_product == USB_PRODUCT_SONY_PS3CONTROLLER) { 362 1.52 aymeric usb_device_request_t req; 363 1.52 aymeric char data[17]; 364 1.52 aymeric int actlen; 365 1.52 aymeric 366 1.52 aymeric req.bmRequestType = UT_READ_CLASS_INTERFACE; 367 1.52 aymeric req.bRequest = 1; 368 1.52 aymeric USETW(req.wValue, 0x3f2); 369 1.52 aymeric USETW(req.wIndex, 0); 370 1.65 skrll USETW(req.wLength, sizeof(data)); 371 1.52 aymeric 372 1.52 aymeric usbd_do_request_flags(sc->sc_udev, &req, data, 373 1.52 aymeric USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT); 374 1.52 aymeric } 375 1.52 aymeric 376 1.1 augustss sc->sc_repdesc = desc; 377 1.1 augustss sc->sc_repdesc_size = size; 378 1.1 augustss 379 1.65 skrll uha.uiaa = uiaa; 380 1.1 augustss nrepid = uhidev_maxrepid(desc, size); 381 1.1 augustss if (nrepid < 0) 382 1.48 dyoung return; 383 1.1 augustss if (nrepid > 0) 384 1.41 cube aprint_normal_dev(self, "%d report ids\n", nrepid); 385 1.1 augustss nrepid++; 386 1.65 skrll repsizes = kmem_alloc(nrepid * sizeof(*repsizes), KM_SLEEP); 387 1.79 riastrad sc->sc_subdevs = kmem_zalloc(nrepid * sizeof(sc->sc_subdevs[0]), 388 1.65 skrll KM_SLEEP); 389 1.44 rafal 390 1.44 rafal /* Just request max packet size for the interrupt pipe */ 391 1.44 rafal sc->sc_isize = maxinpktsize; 392 1.1 augustss sc->sc_nrepid = nrepid; 393 1.1 augustss 394 1.68 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 395 1.1 augustss 396 1.1 augustss for (repid = 0; repid < nrepid; repid++) { 397 1.1 augustss repsz = hid_report_size(desc, size, hid_input, repid); 398 1.1 augustss DPRINTF(("uhidev_match: repid=%d, repsz=%d\n", repid, repsz)); 399 1.2 augustss repsizes[repid] = repsz; 400 1.1 augustss } 401 1.44 rafal 402 1.1 augustss DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize)); 403 1.1 augustss 404 1.1 augustss for (repid = 0; repid < nrepid; repid++) { 405 1.90 riastrad struct uhidev *scd = &sc->sc_subdevs[repid]; 406 1.90 riastrad 407 1.90 riastrad scd->sc_parent = sc; 408 1.90 riastrad scd->sc_report_id = repid; 409 1.90 riastrad scd->sc_in_rep_size = repsizes[repid]; 410 1.90 riastrad 411 1.1 augustss DPRINTF(("uhidev_match: try repid=%d\n", repid)); 412 1.1 augustss if (hid_report_size(desc, size, hid_input, repid) == 0 && 413 1.1 augustss hid_report_size(desc, size, hid_output, repid) == 0 && 414 1.1 augustss hid_report_size(desc, size, hid_feature, repid) == 0) { 415 1.5 augustss ; /* already NULL in sc->sc_subdevs[repid] */ 416 1.1 augustss } else { 417 1.90 riastrad uha.parent = scd; 418 1.1 augustss uha.reportid = repid; 419 1.28 drochner locs[UHIDBUSCF_REPORTID] = repid; 420 1.22 drochner 421 1.80 thorpej dev = config_found(self, &uha, uhidevprint, 422 1.81 thorpej CFARGS(.submatch = config_stdsubmatch, 423 1.81 thorpej .locators = locs)); 424 1.90 riastrad sc->sc_subdevs[repid].sc_dev = dev; 425 1.90 riastrad if (dev == NULL) 426 1.90 riastrad continue; 427 1.90 riastrad /* 428 1.90 riastrad * XXXSMP -- could be detached in the middle of 429 1.90 riastrad * sleeping for allocation in rnd_attach_source 430 1.90 riastrad */ 431 1.90 riastrad rnd_attach_source(&scd->sc_rndsource, 432 1.90 riastrad device_xname(dev), RND_TYPE_TTY, RND_FLAG_DEFAULT); 433 1.1 augustss } 434 1.1 augustss } 435 1.65 skrll kmem_free(repsizes, nrepid * sizeof(*repsizes)); 436 1.1 augustss 437 1.48 dyoung return; 438 1.1 augustss } 439 1.1 augustss 440 1.87 riastrad static int 441 1.1 augustss uhidev_maxrepid(void *buf, int len) 442 1.1 augustss { 443 1.1 augustss struct hid_data *d; 444 1.1 augustss struct hid_item h; 445 1.1 augustss int maxid; 446 1.1 augustss 447 1.1 augustss maxid = -1; 448 1.1 augustss h.report_ID = 0; 449 1.1 augustss for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); ) 450 1.74 jakllsch if ((int)h.report_ID > maxid) 451 1.1 augustss maxid = h.report_ID; 452 1.1 augustss hid_end_parse(d); 453 1.92 riastrad return MIN(maxid, UHIDEV_MAXREPID); 454 1.1 augustss } 455 1.1 augustss 456 1.87 riastrad static int 457 1.1 augustss uhidevprint(void *aux, const char *pnp) 458 1.1 augustss { 459 1.1 augustss struct uhidev_attach_arg *uha = aux; 460 1.1 augustss 461 1.1 augustss if (pnp) 462 1.12 thorpej aprint_normal("uhid at %s", pnp); 463 1.1 augustss if (uha->reportid != 0) 464 1.12 thorpej aprint_normal(" reportid %d", uha->reportid); 465 1.65 skrll return UNCONF; 466 1.1 augustss } 467 1.1 augustss 468 1.76 maxv static void 469 1.39 dyoung uhidev_childdet(device_t self, device_t child) 470 1.39 dyoung { 471 1.39 dyoung int i; 472 1.39 dyoung struct uhidev_softc *sc = device_private(self); 473 1.39 dyoung 474 1.39 dyoung for (i = 0; i < sc->sc_nrepid; i++) { 475 1.90 riastrad if (sc->sc_subdevs[i].sc_dev == child) 476 1.39 dyoung break; 477 1.39 dyoung } 478 1.39 dyoung KASSERT(i < sc->sc_nrepid); 479 1.90 riastrad sc->sc_subdevs[i].sc_dev = NULL; 480 1.90 riastrad /* 481 1.90 riastrad * XXXSMP -- could be reattached in the middle of sleeping for 482 1.90 riastrad * lock on sources to delete this in rnd_attach_source 483 1.90 riastrad * 484 1.90 riastrad * (Actually this can't happen right now because there's no 485 1.90 riastrad * rescan method, but if there were, it could.) 486 1.90 riastrad */ 487 1.90 riastrad rnd_detach_source(&sc->sc_subdevs[i].sc_rndsource); 488 1.39 dyoung } 489 1.39 dyoung 490 1.76 maxv static int 491 1.48 dyoung uhidev_detach(device_t self, int flags) 492 1.1 augustss { 493 1.48 dyoung struct uhidev_softc *sc = device_private(self); 494 1.90 riastrad int rv; 495 1.1 augustss 496 1.1 augustss DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags)); 497 1.1 augustss 498 1.79 riastrad /* 499 1.79 riastrad * Try to detach all our children. If anything fails, bail. 500 1.79 riastrad * Failure can happen if this is from drvctl -d; of course, if 501 1.79 riastrad * this is a USB device being yanked, flags will have 502 1.79 riastrad * DETACH_FORCE and the children will not have the option of 503 1.91 riastrad * refusing detachment. If they do detach, the pipes can no 504 1.91 riastrad * longer be in use. 505 1.79 riastrad */ 506 1.90 riastrad rv = config_detach_children(self, flags); 507 1.91 riastrad if (rv) 508 1.90 riastrad return rv; 509 1.1 augustss 510 1.79 riastrad KASSERTMSG(sc->sc_refcnt == 0, 511 1.79 riastrad "%s: %d refs remain", device_xname(sc->sc_dev), sc->sc_refcnt); 512 1.79 riastrad KASSERT(sc->sc_opipe == NULL); 513 1.79 riastrad KASSERT(sc->sc_ipipe == NULL); 514 1.79 riastrad KASSERT(sc->sc_ibuf == NULL); 515 1.79 riastrad 516 1.79 riastrad if (sc->sc_repdesc != NULL) { 517 1.79 riastrad kmem_free(sc->sc_repdesc, sc->sc_repdesc_size); 518 1.79 riastrad sc->sc_repdesc = NULL; 519 1.79 riastrad } 520 1.79 riastrad if (sc->sc_subdevs != NULL) { 521 1.79 riastrad int nrepid = sc->sc_nrepid; 522 1.79 riastrad kmem_free(sc->sc_subdevs, nrepid * sizeof(sc->sc_subdevs[0])); 523 1.79 riastrad sc->sc_subdevs = NULL; 524 1.79 riastrad } 525 1.79 riastrad 526 1.68 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 527 1.1 augustss 528 1.38 jmcneill pmf_device_deregister(self); 529 1.79 riastrad KASSERT(sc->sc_configlock == NULL); 530 1.79 riastrad KASSERT(sc->sc_writelock == NULL); 531 1.79 riastrad cv_destroy(&sc->sc_cv); 532 1.56 mrg mutex_destroy(&sc->sc_lock); 533 1.38 jmcneill 534 1.65 skrll return rv; 535 1.1 augustss } 536 1.1 augustss 537 1.87 riastrad static void 538 1.65 skrll uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) 539 1.1 augustss { 540 1.1 augustss struct uhidev_softc *sc = addr; 541 1.1 augustss struct uhidev *scd; 542 1.1 augustss u_char *p; 543 1.1 augustss u_int rep; 544 1.65 skrll uint32_t cc; 545 1.1 augustss 546 1.1 augustss usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 547 1.1 augustss 548 1.1 augustss #ifdef UHIDEV_DEBUG 549 1.1 augustss if (uhidevdebug > 5) { 550 1.65 skrll uint32_t i; 551 1.6 augustss 552 1.1 augustss DPRINTF(("uhidev_intr: status=%d cc=%d\n", status, cc)); 553 1.1 augustss DPRINTF(("uhidev_intr: data =")); 554 1.1 augustss for (i = 0; i < cc; i++) 555 1.1 augustss DPRINTF((" %02x", sc->sc_ibuf[i])); 556 1.1 augustss DPRINTF(("\n")); 557 1.1 augustss } 558 1.1 augustss #endif 559 1.1 augustss 560 1.1 augustss if (status == USBD_CANCELLED) 561 1.1 augustss return; 562 1.1 augustss 563 1.1 augustss if (status != USBD_NORMAL_COMPLETION) { 564 1.48 dyoung DPRINTF(("%s: interrupt status=%d\n", device_xname(sc->sc_dev), 565 1.3 augustss status)); 566 1.25 skrll usbd_clear_endpoint_stall_async(sc->sc_ipipe); 567 1.1 augustss return; 568 1.1 augustss } 569 1.1 augustss 570 1.1 augustss p = sc->sc_ibuf; 571 1.1 augustss if (sc->sc_nrepid != 1) 572 1.1 augustss rep = *p++, cc--; 573 1.1 augustss else 574 1.1 augustss rep = 0; 575 1.1 augustss if (rep >= sc->sc_nrepid) { 576 1.1 augustss printf("uhidev_intr: bad repid %d\n", rep); 577 1.1 augustss return; 578 1.1 augustss } 579 1.90 riastrad scd = &sc->sc_subdevs[rep]; 580 1.77 christos DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=%#x\n", 581 1.90 riastrad rep, scd, scd->sc_state)); 582 1.89 riastrad if (!(atomic_load_acquire(&scd->sc_state) & UHIDEV_OPEN)) 583 1.1 augustss return; 584 1.46 jakllsch #ifdef UHIDEV_DEBUG 585 1.46 jakllsch if (scd->sc_in_rep_size != cc) { 586 1.46 jakllsch DPRINTF(("%s: expected %d bytes, got %d\n", 587 1.48 dyoung device_xname(sc->sc_dev), scd->sc_in_rep_size, cc)); 588 1.46 jakllsch } 589 1.46 jakllsch #endif 590 1.46 jakllsch if (cc == 0) { 591 1.46 jakllsch DPRINTF(("%s: 0-length input ignored\n", 592 1.48 dyoung device_xname(sc->sc_dev))); 593 1.23 augustss return; 594 1.23 augustss } 595 1.90 riastrad rnd_add_uint32(&scd->sc_rndsource, (uintptr_t)(sc->sc_ibuf)); 596 1.90 riastrad scd->sc_intr(scd->sc_cookie, p, cc); 597 1.1 augustss } 598 1.1 augustss 599 1.1 augustss void 600 1.90 riastrad uhidev_get_report_desc(struct uhidev *scd, void **desc, int *size) 601 1.1 augustss { 602 1.90 riastrad struct uhidev_softc *sc = scd->sc_parent; 603 1.90 riastrad 604 1.1 augustss *desc = sc->sc_repdesc; 605 1.1 augustss *size = sc->sc_repdesc_size; 606 1.1 augustss } 607 1.1 augustss 608 1.79 riastrad static int 609 1.79 riastrad uhidev_config_enter(struct uhidev_softc *sc) 610 1.79 riastrad { 611 1.79 riastrad int error; 612 1.79 riastrad 613 1.79 riastrad KASSERT(mutex_owned(&sc->sc_lock)); 614 1.79 riastrad 615 1.79 riastrad for (;;) { 616 1.79 riastrad if (sc->sc_configlock == NULL) 617 1.79 riastrad break; 618 1.79 riastrad error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock); 619 1.79 riastrad if (error) 620 1.79 riastrad return error; 621 1.79 riastrad } 622 1.79 riastrad 623 1.79 riastrad sc->sc_configlock = curlwp; 624 1.79 riastrad return 0; 625 1.79 riastrad } 626 1.79 riastrad 627 1.79 riastrad static void 628 1.79 riastrad uhidev_config_enter_nointr(struct uhidev_softc *sc) 629 1.79 riastrad { 630 1.79 riastrad 631 1.79 riastrad KASSERT(mutex_owned(&sc->sc_lock)); 632 1.79 riastrad 633 1.79 riastrad while (sc->sc_configlock) 634 1.79 riastrad cv_wait(&sc->sc_cv, &sc->sc_lock); 635 1.79 riastrad sc->sc_configlock = curlwp; 636 1.79 riastrad } 637 1.79 riastrad 638 1.79 riastrad static void 639 1.79 riastrad uhidev_config_exit(struct uhidev_softc *sc) 640 1.79 riastrad { 641 1.79 riastrad 642 1.79 riastrad KASSERT(mutex_owned(&sc->sc_lock)); 643 1.79 riastrad KASSERTMSG(sc->sc_configlock == curlwp, "%s: migrated from %p to %p", 644 1.79 riastrad device_xname(sc->sc_dev), curlwp, sc->sc_configlock); 645 1.79 riastrad 646 1.79 riastrad sc->sc_configlock = NULL; 647 1.79 riastrad cv_broadcast(&sc->sc_cv); 648 1.79 riastrad } 649 1.79 riastrad 650 1.79 riastrad /* 651 1.79 riastrad * uhidev_open_pipes(sc) 652 1.79 riastrad * 653 1.79 riastrad * Ensure the pipes of the softc are open. Caller must hold 654 1.79 riastrad * sc_lock, which may be released and reacquired. 655 1.79 riastrad */ 656 1.79 riastrad static int 657 1.79 riastrad uhidev_open_pipes(struct uhidev_softc *sc) 658 1.1 augustss { 659 1.1 augustss usbd_status err; 660 1.25 skrll int error; 661 1.1 augustss 662 1.79 riastrad KASSERT(mutex_owned(&sc->sc_lock)); 663 1.79 riastrad 664 1.79 riastrad /* 665 1.79 riastrad * If the pipes are already open, just increment the reference 666 1.92 riastrad * count. The reference count is limited by the number of 667 1.92 riastrad * report ids, so this can't overflow. 668 1.79 riastrad */ 669 1.79 riastrad if (sc->sc_refcnt) { 670 1.92 riastrad KASSERT(sc->sc_refcnt < UHIDEV_MAXREPID); 671 1.79 riastrad sc->sc_refcnt++; 672 1.65 skrll return 0; 673 1.60 skrll } 674 1.1 augustss 675 1.79 riastrad /* 676 1.79 riastrad * If there's no input data to prepare, don't bother with the 677 1.79 riastrad * pipes. We assume any device that does output also does 678 1.79 riastrad * input; if you have a device where this is wrong, then 679 1.79 riastrad * uhidev_write will fail gracefully (it checks sc->sc_opipe), 680 1.79 riastrad * and you can use that device to test the changes needed to 681 1.79 riastrad * open the output pipe here. 682 1.79 riastrad */ 683 1.1 augustss if (sc->sc_isize == 0) 684 1.65 skrll return 0; 685 1.1 augustss 686 1.79 riastrad /* 687 1.87 riastrad * Lock the configuration and release sc_lock -- we may sleep 688 1.87 riastrad * to allocate. If someone else got in first, we're done; 689 1.79 riastrad * otherwise open the pipes. 690 1.79 riastrad */ 691 1.79 riastrad error = uhidev_config_enter(sc); 692 1.79 riastrad if (error) 693 1.79 riastrad goto out; 694 1.79 riastrad if (sc->sc_refcnt) { 695 1.92 riastrad KASSERT(sc->sc_refcnt < UHIDEV_MAXREPID); 696 1.92 riastrad sc->sc_refcnt++; 697 1.92 riastrad error = 0; 698 1.79 riastrad goto out0; 699 1.79 riastrad } 700 1.79 riastrad mutex_exit(&sc->sc_lock); 701 1.79 riastrad 702 1.79 riastrad /* Allocate an input buffer. */ 703 1.65 skrll sc->sc_ibuf = kmem_alloc(sc->sc_isize, KM_SLEEP); 704 1.1 augustss 705 1.25 skrll /* Set up input interrupt pipe. */ 706 1.79 riastrad DPRINTF(("%s: isize=%d, ep=0x%02x\n", __func__, sc->sc_isize, 707 1.25 skrll sc->sc_iep_addr)); 708 1.58 skrll 709 1.25 skrll err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr, 710 1.25 skrll USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf, 711 1.1 augustss sc->sc_isize, uhidev_intr, USBD_DEFAULT_INTERVAL); 712 1.25 skrll if (err != USBD_NORMAL_COMPLETION) { 713 1.1 augustss DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " 714 1.25 skrll "error=%d\n", err)); 715 1.25 skrll error = EIO; 716 1.25 skrll goto out1; 717 1.25 skrll } 718 1.25 skrll 719 1.25 skrll /* 720 1.25 skrll * Set up output interrupt pipe if an output interrupt endpoint 721 1.25 skrll * exists. 722 1.25 skrll */ 723 1.25 skrll if (sc->sc_oep_addr != -1) { 724 1.78 christos DPRINTF(("uhidev_open: oep=0x%02x\n", sc->sc_oep_addr)); 725 1.25 skrll 726 1.25 skrll err = usbd_open_pipe(sc->sc_iface, sc->sc_oep_addr, 727 1.25 skrll 0, &sc->sc_opipe); 728 1.25 skrll 729 1.25 skrll if (err != USBD_NORMAL_COMPLETION) { 730 1.25 skrll DPRINTF(("uhidev_open: usbd_open_pipe failed, " 731 1.25 skrll "error=%d\n", err)); 732 1.25 skrll error = EIO; 733 1.25 skrll goto out2; 734 1.25 skrll } 735 1.25 skrll DPRINTF(("uhidev_open: sc->sc_opipe=%p\n", sc->sc_opipe)); 736 1.25 skrll 737 1.65 skrll error = usbd_create_xfer(sc->sc_opipe, UHIDEV_OSIZE, 0, 0, 738 1.65 skrll &sc->sc_oxfer); 739 1.65 skrll if (error) { 740 1.25 skrll DPRINTF(("uhidev_open: couldn't allocate an xfer\n")); 741 1.25 skrll goto out3; 742 1.25 skrll } 743 1.62 jmcneill 744 1.62 jmcneill if (sc->sc_flags & UHIDEV_F_XB1) { 745 1.62 jmcneill uint8_t init_data[] = { 0x05, 0x20 }; 746 1.62 jmcneill int init_data_len = sizeof(init_data); 747 1.62 jmcneill err = usbd_intr_transfer(sc->sc_oxfer, sc->sc_opipe, 0, 748 1.65 skrll USBD_NO_TIMEOUT, init_data, &init_data_len); 749 1.62 jmcneill if (err != USBD_NORMAL_COMPLETION) { 750 1.62 jmcneill DPRINTF(("uhidev_open: xb1 init failed, " 751 1.62 jmcneill "error=%d\n", err)); 752 1.62 jmcneill error = EIO; 753 1.62 jmcneill goto out4; 754 1.62 jmcneill } 755 1.62 jmcneill } 756 1.1 augustss } 757 1.58 skrll 758 1.79 riastrad /* Success! */ 759 1.79 riastrad mutex_enter(&sc->sc_lock); 760 1.79 riastrad KASSERTMSG(sc->sc_refcnt == 0, "%d refs spuriously acquired", 761 1.79 riastrad sc->sc_refcnt); 762 1.79 riastrad sc->sc_refcnt++; 763 1.79 riastrad goto out0; 764 1.79 riastrad 765 1.79 riastrad out4: if (sc->sc_oxfer) { 766 1.79 riastrad usbd_abort_pipe(sc->sc_opipe); 767 1.65 skrll usbd_destroy_xfer(sc->sc_oxfer); 768 1.79 riastrad sc->sc_oxfer = NULL; 769 1.79 riastrad } 770 1.79 riastrad out3: if (sc->sc_opipe) { 771 1.79 riastrad usbd_close_pipe(sc->sc_opipe); 772 1.79 riastrad sc->sc_opipe = NULL; 773 1.79 riastrad } 774 1.79 riastrad out2: if (sc->sc_ipipe) { 775 1.79 riastrad usbd_abort_pipe(sc->sc_ipipe); 776 1.79 riastrad usbd_close_pipe(sc->sc_ipipe); 777 1.79 riastrad sc->sc_ipipe = NULL; 778 1.79 riastrad } 779 1.79 riastrad out1: kmem_free(sc->sc_ibuf, sc->sc_isize); 780 1.79 riastrad sc->sc_ibuf = NULL; 781 1.56 mrg mutex_enter(&sc->sc_lock); 782 1.79 riastrad out0: KASSERT(mutex_owned(&sc->sc_lock)); 783 1.79 riastrad uhidev_config_exit(sc); 784 1.79 riastrad out: KASSERT(mutex_owned(&sc->sc_lock)); 785 1.25 skrll return error; 786 1.1 augustss } 787 1.1 augustss 788 1.79 riastrad static void 789 1.79 riastrad uhidev_close_pipes(struct uhidev_softc *sc) 790 1.63 mrg { 791 1.63 mrg 792 1.79 riastrad KASSERT(mutex_owned(&sc->sc_lock)); 793 1.79 riastrad KASSERTMSG(sc->sc_refcnt > 0, "%s: refcnt fouled: %d", 794 1.79 riastrad device_xname(sc->sc_dev), sc->sc_refcnt); 795 1.79 riastrad 796 1.79 riastrad /* If this isn't the last reference, just decrement. */ 797 1.79 riastrad if (sc->sc_refcnt > 1) { 798 1.79 riastrad sc->sc_refcnt--; 799 1.79 riastrad return; 800 1.79 riastrad } 801 1.79 riastrad 802 1.79 riastrad /* 803 1.79 riastrad * Lock the configuration and release sc_lock so we may sleep 804 1.79 riastrad * to free memory. We're not waiting for anyone to allocate or 805 1.79 riastrad * free anything. 806 1.79 riastrad */ 807 1.79 riastrad uhidev_config_enter_nointr(sc); 808 1.79 riastrad 809 1.79 riastrad /* 810 1.79 riastrad * If someone else acquired a reference while we were waiting 811 1.79 riastrad * for the config lock, nothing more for us to do. 812 1.79 riastrad */ 813 1.79 riastrad if (sc->sc_refcnt > 1) { 814 1.79 riastrad sc->sc_refcnt--; 815 1.79 riastrad uhidev_config_exit(sc); 816 1.79 riastrad return; 817 1.79 riastrad } 818 1.79 riastrad 819 1.79 riastrad /* 820 1.79 riastrad * We're the last reference and committed to closing the pipes. 821 1.79 riastrad * Decrement the reference count before we release the lock -- 822 1.79 riastrad * access to the pipes is allowed as long as the reference 823 1.79 riastrad * count is positive, so this forces all new opens to wait 824 1.79 riastrad * until the config lock is released. 825 1.79 riastrad */ 826 1.79 riastrad KASSERTMSG(sc->sc_refcnt == 1, "%s: refcnt fouled: %d", 827 1.79 riastrad device_xname(sc->sc_dev), sc->sc_refcnt); 828 1.79 riastrad sc->sc_refcnt--; 829 1.79 riastrad mutex_exit(&sc->sc_lock); 830 1.79 riastrad 831 1.79 riastrad if (sc->sc_oxfer) { 832 1.63 mrg usbd_abort_pipe(sc->sc_opipe); 833 1.79 riastrad usbd_destroy_xfer(sc->sc_oxfer); 834 1.79 riastrad sc->sc_oxfer = NULL; 835 1.79 riastrad } 836 1.79 riastrad if (sc->sc_opipe) { 837 1.63 mrg usbd_close_pipe(sc->sc_opipe); 838 1.63 mrg sc->sc_opipe = NULL; 839 1.63 mrg } 840 1.79 riastrad if (sc->sc_ipipe) { 841 1.63 mrg usbd_abort_pipe(sc->sc_ipipe); 842 1.63 mrg usbd_close_pipe(sc->sc_ipipe); 843 1.63 mrg sc->sc_ipipe = NULL; 844 1.63 mrg } 845 1.79 riastrad kmem_free(sc->sc_ibuf, sc->sc_isize); 846 1.79 riastrad sc->sc_ibuf = NULL; 847 1.79 riastrad 848 1.79 riastrad mutex_enter(&sc->sc_lock); 849 1.79 riastrad uhidev_config_exit(sc); 850 1.79 riastrad KASSERTMSG(sc->sc_refcnt == 0, "%s: refcnt fouled: %d", 851 1.79 riastrad device_xname(sc->sc_dev), sc->sc_refcnt); 852 1.79 riastrad } 853 1.79 riastrad 854 1.79 riastrad int 855 1.90 riastrad uhidev_open(struct uhidev *scd, void (*intr)(void *, void *, u_int), 856 1.90 riastrad void *cookie) 857 1.79 riastrad { 858 1.79 riastrad struct uhidev_softc *sc = scd->sc_parent; 859 1.79 riastrad int error; 860 1.79 riastrad 861 1.79 riastrad mutex_enter(&sc->sc_lock); 862 1.79 riastrad 863 1.79 riastrad DPRINTF(("uhidev_open(%s, report %d = %s): state=%x refcnt=%d\n", 864 1.79 riastrad device_xname(sc->sc_dev), 865 1.79 riastrad scd->sc_report_id, 866 1.79 riastrad device_xname(scd->sc_dev), 867 1.79 riastrad scd->sc_state, 868 1.79 riastrad sc->sc_refcnt)); 869 1.63 mrg 870 1.79 riastrad /* Mark the report id open. This is an exclusive lock. */ 871 1.79 riastrad if (scd->sc_state & UHIDEV_OPEN) { 872 1.79 riastrad error = EBUSY; 873 1.88 riastrad goto out; 874 1.63 mrg } 875 1.90 riastrad scd->sc_intr = intr; 876 1.90 riastrad scd->sc_cookie = cookie; 877 1.89 riastrad atomic_store_release(&scd->sc_state, scd->sc_state | UHIDEV_OPEN); 878 1.79 riastrad 879 1.79 riastrad /* Open the pipes which are shared by all report ids. */ 880 1.79 riastrad error = uhidev_open_pipes(sc); 881 1.79 riastrad if (error) 882 1.88 riastrad goto out; 883 1.79 riastrad 884 1.79 riastrad /* Success! */ 885 1.88 riastrad error = 0; 886 1.79 riastrad 887 1.88 riastrad out: if (error) { 888 1.88 riastrad KASSERTMSG(scd->sc_state & UHIDEV_OPEN, 889 1.88 riastrad "%s: report id %d: closed while opening", 890 1.88 riastrad device_xname(sc->sc_dev), scd->sc_report_id); 891 1.89 riastrad atomic_store_relaxed(&scd->sc_state, 892 1.89 riastrad scd->sc_state & ~UHIDEV_OPEN); 893 1.88 riastrad } 894 1.88 riastrad mutex_exit(&sc->sc_lock); 895 1.79 riastrad return error; 896 1.63 mrg } 897 1.63 mrg 898 1.86 riastrad /* 899 1.86 riastrad * uhidev_stop(scd) 900 1.86 riastrad * 901 1.86 riastrad * Make all current and future output reports or xfers by scd to 902 1.86 riastrad * the output pipe to fail. Caller must then ensure no more will 903 1.86 riastrad * be submitted and then call uhidev_close. 904 1.86 riastrad * 905 1.86 riastrad * Side effect: If uhidev_write was in progress for this scd, 906 1.86 riastrad * blocks all other uhidev_writes until uhidev_close on this scd. 907 1.86 riastrad * 908 1.86 riastrad * May sleep but only for a short duration to wait for USB 909 1.86 riastrad * transfer completion callbacks to run. 910 1.86 riastrad */ 911 1.63 mrg void 912 1.79 riastrad uhidev_stop(struct uhidev *scd) 913 1.1 augustss { 914 1.1 augustss struct uhidev_softc *sc = scd->sc_parent; 915 1.1 augustss 916 1.56 mrg mutex_enter(&sc->sc_lock); 917 1.86 riastrad 918 1.86 riastrad /* Prevent further writes on this report from starting. */ 919 1.89 riastrad atomic_store_relaxed(&scd->sc_state, scd->sc_state | UHIDEV_STOPPED); 920 1.86 riastrad 921 1.86 riastrad /* If there's no output pipe at all, nothing to do. */ 922 1.86 riastrad if (sc->sc_opipe == NULL) 923 1.86 riastrad goto out; 924 1.86 riastrad 925 1.86 riastrad /* 926 1.86 riastrad * If there's no write on this report in progress, nothing to 927 1.86 riastrad * do -- any subsequent attempts will be prevented by 928 1.86 riastrad * UHIDEV_STOPPED. 929 1.86 riastrad */ 930 1.86 riastrad if (sc->sc_writereportid != scd->sc_report_id) 931 1.86 riastrad goto out; 932 1.86 riastrad 933 1.86 riastrad /* 934 1.86 riastrad * Caller must wait for uhidev_open to succeed before calling 935 1.86 riastrad * uhidev_write, and must wait for all uhidev_writes to return 936 1.86 riastrad * before calling uhidev_close, so neither on can be in flight 937 1.86 riastrad * right now. 938 1.86 riastrad * 939 1.86 riastrad * Suspend the pipe, but hold up uhidev_write from any report 940 1.86 riastrad * until we confirm this one has finished. We will resume the 941 1.86 riastrad * pipe only after all uhidev_writes on this report have 942 1.86 riastrad * finished -- when the caller calls uhidev_close. 943 1.86 riastrad */ 944 1.86 riastrad KASSERTMSG(sc->sc_stopreportid == -1, "%d", sc->sc_stopreportid); 945 1.86 riastrad sc->sc_stopreportid = scd->sc_report_id; 946 1.56 mrg mutex_exit(&sc->sc_lock); 947 1.56 mrg 948 1.86 riastrad usbd_suspend_pipe(sc->sc_opipe); 949 1.86 riastrad 950 1.86 riastrad mutex_enter(&sc->sc_lock); 951 1.86 riastrad KASSERT(sc->sc_stopreportid == scd->sc_report_id); 952 1.86 riastrad sc->sc_stopreportid = scd->sc_report_id; 953 1.86 riastrad cv_broadcast(&sc->sc_cv); 954 1.86 riastrad out: mutex_exit(&sc->sc_lock); 955 1.79 riastrad } 956 1.79 riastrad 957 1.86 riastrad /* 958 1.86 riastrad * uhidev_close(scd) 959 1.86 riastrad * 960 1.86 riastrad * Close a uhidev previously opened with uhidev_open. If writes 961 1.86 riastrad * had been stopped with uhidev_stop, allow writes at other report 962 1.86 riastrad * ids again. 963 1.86 riastrad */ 964 1.79 riastrad void 965 1.79 riastrad uhidev_close(struct uhidev *scd) 966 1.79 riastrad { 967 1.79 riastrad struct uhidev_softc *sc = scd->sc_parent; 968 1.1 augustss 969 1.79 riastrad mutex_enter(&sc->sc_lock); 970 1.58 skrll 971 1.79 riastrad DPRINTF(("uhidev_close(%s, report %d = %s): state=%x refcnt=%d\n", 972 1.79 riastrad device_xname(sc->sc_dev), 973 1.79 riastrad scd->sc_report_id, 974 1.79 riastrad device_xname(scd->sc_dev), 975 1.79 riastrad scd->sc_state, 976 1.79 riastrad sc->sc_refcnt)); 977 1.79 riastrad 978 1.79 riastrad KASSERTMSG(scd->sc_state & UHIDEV_OPEN, 979 1.79 riastrad "%s: report id %d: unpaired close", 980 1.79 riastrad device_xname(sc->sc_dev), scd->sc_report_id); 981 1.86 riastrad 982 1.86 riastrad /* 983 1.86 riastrad * If the caller had issued uhidev_stop to interrupt a write 984 1.86 riastrad * for this report, then resume the pipe now that no further 985 1.86 riastrad * uhidev_write on the same report is possible, and wake anyone 986 1.86 riastrad * trying to write on other reports. 987 1.86 riastrad */ 988 1.86 riastrad if (sc->sc_stopreportid == scd->sc_report_id) { 989 1.86 riastrad KASSERT(scd->sc_state & UHIDEV_STOPPED); 990 1.86 riastrad mutex_exit(&sc->sc_lock); 991 1.86 riastrad 992 1.86 riastrad usbd_resume_pipe(sc->sc_opipe); 993 1.86 riastrad 994 1.86 riastrad mutex_enter(&sc->sc_lock); 995 1.86 riastrad KASSERT(sc->sc_stopreportid == scd->sc_report_id); 996 1.86 riastrad KASSERT(scd->sc_state & UHIDEV_STOPPED); 997 1.86 riastrad sc->sc_stopreportid = -1; 998 1.86 riastrad cv_broadcast(&sc->sc_cv); 999 1.86 riastrad } 1000 1.86 riastrad 1001 1.86 riastrad /* 1002 1.86 riastrad * Close our reference to the pipes, and mark our report as no 1003 1.86 riastrad * longer open. If it was stopped, clear that too -- drivers 1004 1.86 riastrad * are forbidden from issuing writes after uhidev_close anyway. 1005 1.86 riastrad */ 1006 1.86 riastrad KASSERT(scd->sc_state & UHIDEV_OPEN); 1007 1.79 riastrad uhidev_close_pipes(sc); 1008 1.86 riastrad KASSERT(scd->sc_state & UHIDEV_OPEN); 1009 1.89 riastrad atomic_store_relaxed(&scd->sc_state, 1010 1.89 riastrad scd->sc_state & ~(UHIDEV_OPEN | UHIDEV_STOPPED)); 1011 1.65 skrll 1012 1.89 riastrad /* 1013 1.89 riastrad * Make sure the next uhidev_intr (which runs in softint, like 1014 1.89 riastrad * XC_HIGHPRI) notices that UHIDEV_OPEN is cleared, and wait 1015 1.89 riastrad * for any current one to finish, in case the pipe is still 1016 1.89 riastrad * open for other report ids. 1017 1.89 riastrad * 1018 1.89 riastrad * We must drop the lock while doing this, because 1019 1.89 riastrad * uhidev_write_callback takes the lock in softint context and 1020 1.89 riastrad * it could deadlock with the xcall softint. 1021 1.90 riastrad * 1022 1.90 riastrad * It is safe to drop the lock now before zeroing sc_intr and 1023 1.90 riastrad * sc_cookie because the driver is obligated not to reopen 1024 1.90 riastrad * until after uhidev_close returns. 1025 1.89 riastrad */ 1026 1.79 riastrad mutex_exit(&sc->sc_lock); 1027 1.89 riastrad xc_barrier(XC_HIGHPRI); 1028 1.90 riastrad mutex_enter(&sc->sc_lock); 1029 1.90 riastrad KASSERT((scd->sc_state & UHIDEV_OPEN) == 0); 1030 1.90 riastrad scd->sc_intr = NULL; 1031 1.90 riastrad scd->sc_cookie = NULL; 1032 1.90 riastrad 1033 1.90 riastrad mutex_exit(&sc->sc_lock); 1034 1.1 augustss } 1035 1.1 augustss 1036 1.1 augustss usbd_status 1037 1.1 augustss uhidev_set_report(struct uhidev *scd, int type, void *data, int len) 1038 1.1 augustss { 1039 1.13 dsainty char *buf; 1040 1.13 dsainty usbd_status retstat; 1041 1.13 dsainty 1042 1.13 dsainty if (scd->sc_report_id == 0) 1043 1.13 dsainty return usbd_set_report(scd->sc_parent->sc_iface, type, 1044 1.13 dsainty scd->sc_report_id, data, len); 1045 1.13 dsainty 1046 1.65 skrll buf = kmem_alloc(len + 1, KM_SLEEP); 1047 1.13 dsainty buf[0] = scd->sc_report_id; 1048 1.13 dsainty memcpy(buf+1, data, len); 1049 1.13 dsainty 1050 1.13 dsainty retstat = usbd_set_report(scd->sc_parent->sc_iface, type, 1051 1.18 dsainty scd->sc_report_id, buf, len + 1); 1052 1.13 dsainty 1053 1.65 skrll kmem_free(buf, len + 1); 1054 1.1 augustss 1055 1.13 dsainty return retstat; 1056 1.1 augustss } 1057 1.1 augustss 1058 1.1 augustss usbd_status 1059 1.1 augustss uhidev_get_report(struct uhidev *scd, int type, void *data, int len) 1060 1.1 augustss { 1061 1.6 augustss return usbd_get_report(scd->sc_parent->sc_iface, type, 1062 1.1 augustss scd->sc_report_id, data, len); 1063 1.1 augustss } 1064 1.25 skrll 1065 1.25 skrll usbd_status 1066 1.83 riastrad uhidev_write(struct uhidev *scd, void *data, int len) 1067 1.25 skrll { 1068 1.83 riastrad struct uhidev_softc *sc = scd->sc_parent; 1069 1.79 riastrad usbd_status err; 1070 1.25 skrll 1071 1.25 skrll DPRINTF(("uhidev_write: data=%p, len=%d\n", data, len)); 1072 1.25 skrll 1073 1.25 skrll if (sc->sc_opipe == NULL) 1074 1.25 skrll return USBD_INVAL; 1075 1.25 skrll 1076 1.79 riastrad mutex_enter(&sc->sc_lock); 1077 1.79 riastrad KASSERT(sc->sc_refcnt); 1078 1.93 riastrad KASSERT(scd->sc_state & UHIDEV_OPEN); 1079 1.79 riastrad for (;;) { 1080 1.86 riastrad if (scd->sc_state & UHIDEV_STOPPED) { 1081 1.86 riastrad err = USBD_CANCELLED; 1082 1.86 riastrad goto out; 1083 1.86 riastrad } 1084 1.86 riastrad if (sc->sc_writelock == NULL && sc->sc_stopreportid == -1) 1085 1.79 riastrad break; 1086 1.79 riastrad if (cv_wait_sig(&sc->sc_cv, &sc->sc_lock)) { 1087 1.79 riastrad err = USBD_INTERRUPTED; 1088 1.79 riastrad goto out; 1089 1.79 riastrad } 1090 1.79 riastrad } 1091 1.79 riastrad sc->sc_writelock = curlwp; 1092 1.83 riastrad sc->sc_writereportid = scd->sc_report_id; 1093 1.79 riastrad mutex_exit(&sc->sc_lock); 1094 1.79 riastrad 1095 1.25 skrll #ifdef UHIDEV_DEBUG 1096 1.25 skrll if (uhidevdebug > 50) { 1097 1.25 skrll 1098 1.65 skrll uint32_t i; 1099 1.65 skrll uint8_t *d = data; 1100 1.25 skrll 1101 1.25 skrll DPRINTF(("uhidev_write: data =")); 1102 1.25 skrll for (i = 0; i < len; i++) 1103 1.25 skrll DPRINTF((" %02x", d[i])); 1104 1.25 skrll DPRINTF(("\n")); 1105 1.25 skrll } 1106 1.25 skrll #endif 1107 1.79 riastrad err = usbd_intr_transfer(sc->sc_oxfer, sc->sc_opipe, 0, 1108 1.79 riastrad USBD_NO_TIMEOUT, data, &len); 1109 1.79 riastrad 1110 1.79 riastrad mutex_enter(&sc->sc_lock); 1111 1.79 riastrad KASSERT(sc->sc_refcnt); 1112 1.93 riastrad KASSERT(scd->sc_state & UHIDEV_OPEN); 1113 1.79 riastrad KASSERTMSG(sc->sc_writelock == curlwp, "%s: migrated from %p to %p", 1114 1.79 riastrad device_xname(sc->sc_dev), curlwp, sc->sc_writelock); 1115 1.83 riastrad KASSERTMSG(sc->sc_writereportid == scd->sc_report_id, 1116 1.83 riastrad "%s: changed write report ids from %d to %d", 1117 1.83 riastrad device_xname(sc->sc_dev), scd->sc_report_id, sc->sc_writereportid); 1118 1.83 riastrad sc->sc_writereportid = -1; 1119 1.79 riastrad sc->sc_writelock = NULL; 1120 1.79 riastrad cv_broadcast(&sc->sc_cv); 1121 1.79 riastrad out: mutex_exit(&sc->sc_lock); 1122 1.79 riastrad return err; 1123 1.25 skrll } 1124 1.84 riastrad 1125 1.84 riastrad static void 1126 1.84 riastrad uhidev_write_callback(struct usbd_xfer *xfer, void *cookie, usbd_status err) 1127 1.84 riastrad { 1128 1.84 riastrad struct uhidev_softc *sc = cookie; 1129 1.84 riastrad usbd_callback writecallback; 1130 1.84 riastrad void *writecookie; 1131 1.84 riastrad 1132 1.84 riastrad if (err) { 1133 1.84 riastrad if (err != USBD_CANCELLED) 1134 1.84 riastrad usbd_clear_endpoint_stall_async(sc->sc_opipe); 1135 1.84 riastrad } 1136 1.84 riastrad 1137 1.84 riastrad mutex_enter(&sc->sc_lock); 1138 1.84 riastrad KASSERT(sc->sc_writelock == (void *)1); 1139 1.84 riastrad writecallback = sc->sc_writecallback; 1140 1.84 riastrad writecookie = sc->sc_writecookie; 1141 1.84 riastrad sc->sc_writereportid = -1; 1142 1.84 riastrad sc->sc_writelock = NULL; 1143 1.84 riastrad sc->sc_writecallback = NULL; 1144 1.84 riastrad sc->sc_writecookie = NULL; 1145 1.84 riastrad cv_broadcast(&sc->sc_cv); 1146 1.84 riastrad mutex_exit(&sc->sc_lock); 1147 1.84 riastrad 1148 1.84 riastrad (*writecallback)(xfer, writecookie, err); 1149 1.84 riastrad } 1150 1.84 riastrad 1151 1.84 riastrad usbd_status 1152 1.84 riastrad uhidev_write_async(struct uhidev *scd, void *data, int len, int flags, 1153 1.84 riastrad int timo, usbd_callback writecallback, void *writecookie) 1154 1.84 riastrad { 1155 1.84 riastrad struct uhidev_softc *sc = scd->sc_parent; 1156 1.84 riastrad usbd_status err; 1157 1.84 riastrad 1158 1.84 riastrad DPRINTF(("%s: data=%p, len=%d\n", __func__, data, len)); 1159 1.84 riastrad 1160 1.84 riastrad if (sc->sc_opipe == NULL) 1161 1.84 riastrad return USBD_INVAL; 1162 1.84 riastrad 1163 1.84 riastrad mutex_enter(&sc->sc_lock); 1164 1.84 riastrad KASSERT(sc->sc_refcnt); 1165 1.93 riastrad KASSERT(scd->sc_state & UHIDEV_OPEN); 1166 1.86 riastrad if (scd->sc_state & UHIDEV_STOPPED) { 1167 1.86 riastrad err = USBD_CANCELLED; 1168 1.86 riastrad goto out; 1169 1.86 riastrad } 1170 1.86 riastrad if (sc->sc_writelock != NULL || sc->sc_stopreportid != -1) { 1171 1.84 riastrad err = USBD_IN_USE; 1172 1.84 riastrad goto out; 1173 1.84 riastrad } 1174 1.84 riastrad sc->sc_writelock = (void *)1; /* XXX no lwp to attribute async xfer */ 1175 1.84 riastrad sc->sc_writereportid = scd->sc_report_id; 1176 1.84 riastrad sc->sc_writecallback = writecallback; 1177 1.84 riastrad sc->sc_writecookie = writecookie; 1178 1.84 riastrad usbd_setup_xfer(sc->sc_oxfer, sc, data, len, flags, timo, 1179 1.84 riastrad uhidev_write_callback); 1180 1.84 riastrad err = usbd_transfer(sc->sc_oxfer); 1181 1.84 riastrad switch (err) { 1182 1.84 riastrad case USBD_IN_PROGRESS: 1183 1.84 riastrad break; 1184 1.84 riastrad case USBD_NORMAL_COMPLETION: 1185 1.84 riastrad panic("unexpected normal completion of async xfer under lock"); 1186 1.84 riastrad default: /* error */ 1187 1.84 riastrad sc->sc_writelock = NULL; 1188 1.84 riastrad sc->sc_writereportid = -1; 1189 1.84 riastrad sc->sc_writecallback = NULL; 1190 1.84 riastrad sc->sc_writecookie = NULL; 1191 1.84 riastrad cv_broadcast(&sc->sc_cv); 1192 1.84 riastrad } 1193 1.84 riastrad out: mutex_exit(&sc->sc_lock); 1194 1.84 riastrad return err; 1195 1.84 riastrad } 1196