1 1.88 mrg /* $NetBSD: usbdi_util.c,v 1.88 2024/02/04 05:43:06 mrg Exp $ */ 2 1.1 augustss 3 1.1 augustss /* 4 1.57 mrg * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc. 5 1.1 augustss * All rights reserved. 6 1.1 augustss * 7 1.5 augustss * This code is derived from software contributed to The NetBSD Foundation 8 1.30 augustss * by Lennart Augustsson (lennart (at) augustsson.net) at 9 1.88 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.36 lukem 33 1.36 lukem #include <sys/cdefs.h> 34 1.88 mrg __KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.88 2024/02/04 05:43:06 mrg Exp $"); 35 1.63 skrll 36 1.63 skrll #ifdef _KERNEL_OPT 37 1.63 skrll #include "opt_usb.h" 38 1.63 skrll #endif 39 1.1 augustss 40 1.1 augustss #include <sys/param.h> 41 1.1 augustss #include <sys/systm.h> 42 1.1 augustss #include <sys/kernel.h> 43 1.65 skrll #include <sys/kmem.h> 44 1.1 augustss #include <sys/proc.h> 45 1.14 augustss #include <sys/device.h> 46 1.57 mrg #include <sys/bus.h> 47 1.1 augustss 48 1.1 augustss #include <dev/usb/usb.h> 49 1.1 augustss #include <dev/usb/usbhid.h> 50 1.1 augustss #include <dev/usb/usbdi.h> 51 1.57 mrg #include <dev/usb/usbdivar.h> 52 1.1 augustss #include <dev/usb/usbdi_util.h> 53 1.72 manu #include <dev/usb/usb_quirks.h> 54 1.63 skrll #include <dev/usb/usbhist.h> 55 1.1 augustss 56 1.65 skrll #define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(usbdebug,1,FMT,A,B,C,D) 57 1.65 skrll #define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(usbdebug,N,FMT,A,B,C,D) 58 1.1 augustss 59 1.1 augustss usbd_status 60 1.65 skrll usbd_get_desc(struct usbd_device *dev, int type, int index, int len, void *desc) 61 1.1 augustss { 62 1.1 augustss usb_device_request_t req; 63 1.72 manu usbd_status err; 64 1.1 augustss 65 1.75 mrg USBHIST_FUNC(); 66 1.75 mrg USBHIST_CALLARGS(usbdebug, "type=%jd, index=%jd, len=%jd", 67 1.75 mrg type, index, len, 0); 68 1.26 augustss 69 1.72 manu /* 70 1.72 manu * Provide hard-coded configuration descriptors 71 1.72 manu * for devices that may corrupt it. This cannot 72 1.72 manu * be done for device descriptors which are used 73 1.72 manu * to identify the device. 74 1.72 manu */ 75 1.72 manu if (type != UDESC_DEVICE && 76 1.72 manu dev->ud_quirks->uq_flags & UQ_DESC_CORRUPT) { 77 1.72 manu err = usbd_get_desc_fake(dev, type, index, len, desc); 78 1.72 manu goto out; 79 1.72 manu } 80 1.72 manu 81 1.1 augustss req.bmRequestType = UT_READ_DEVICE; 82 1.1 augustss req.bRequest = UR_GET_DESCRIPTOR; 83 1.1 augustss USETW2(req.wValue, type, index); 84 1.1 augustss USETW(req.wIndex, 0); 85 1.1 augustss USETW(req.wLength, len); 86 1.72 manu err = usbd_do_request(dev, &req, desc); 87 1.72 manu 88 1.72 manu out: 89 1.72 manu return err; 90 1.1 augustss } 91 1.1 augustss 92 1.1 augustss usbd_status 93 1.65 skrll usbd_get_config_desc(struct usbd_device *dev, int confidx, 94 1.31 augustss usb_config_descriptor_t *d) 95 1.1 augustss { 96 1.75 mrg USBHIST_FUNC(); 97 1.75 mrg USBHIST_CALLARGS(usbdebug, "confidx=%jd", confidx, 0, 0, 0); 98 1.23 augustss usbd_status err; 99 1.9 augustss 100 1.40 augustss err = usbd_get_desc(dev, UDESC_CONFIG, confidx, 101 1.26 augustss USB_CONFIG_DESCRIPTOR_SIZE, d); 102 1.23 augustss if (err) 103 1.65 skrll return err; 104 1.9 augustss if (d->bDescriptorType != UDESC_CONFIG) { 105 1.82 christos DPRINTFN(1, "confidx=%jd, bad desc len=%jd type=%jd", 106 1.65 skrll confidx, d->bLength, d->bDescriptorType, 0); 107 1.65 skrll return USBD_INVAL; 108 1.9 augustss } 109 1.65 skrll return USBD_NORMAL_COMPLETION; 110 1.1 augustss } 111 1.1 augustss 112 1.1 augustss usbd_status 113 1.65 skrll usbd_get_config_desc_full(struct usbd_device *dev, int conf, void *d, int size) 114 1.4 augustss { 115 1.75 mrg USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "conf=%jd", conf, 0, 0, 0); 116 1.65 skrll 117 1.65 skrll return usbd_get_desc(dev, UDESC_CONFIG, conf, size, d); 118 1.4 augustss } 119 1.4 augustss 120 1.4 augustss usbd_status 121 1.65 skrll usbd_get_bos_desc(struct usbd_device *dev, int confidx, 122 1.64 skrll usb_bos_descriptor_t *d) 123 1.64 skrll { 124 1.75 mrg USBHIST_FUNC(); 125 1.75 mrg USBHIST_CALLARGS(usbdebug, "confidx=%jd", confidx, 0, 0, 0); 126 1.64 skrll usbd_status err; 127 1.64 skrll 128 1.64 skrll err = usbd_get_desc(dev, UDESC_BOS, confidx, 129 1.64 skrll USB_BOS_DESCRIPTOR_SIZE, d); 130 1.64 skrll if (err) 131 1.69 skrll return err; 132 1.64 skrll if (d->bDescriptorType != UDESC_BOS) { 133 1.82 christos DPRINTFN(1, "confidx=%jd, bad desc len=%jd type=%jd", 134 1.65 skrll confidx, d->bLength, d->bDescriptorType, 0); 135 1.65 skrll return USBD_INVAL; 136 1.64 skrll } 137 1.65 skrll return USBD_NORMAL_COMPLETION; 138 1.64 skrll } 139 1.64 skrll 140 1.64 skrll usbd_status 141 1.65 skrll usbd_get_device_desc(struct usbd_device *dev, usb_device_descriptor_t *d) 142 1.1 augustss { 143 1.65 skrll USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 144 1.65 skrll 145 1.69 skrll return usbd_get_desc(dev, UDESC_DEVICE, 146 1.69 skrll 0, USB_DEVICE_DESCRIPTOR_SIZE, d); 147 1.1 augustss } 148 1.1 augustss 149 1.78 maxv /* 150 1.78 maxv * Get the first 8 bytes of the device descriptor. 151 1.78 maxv * Do as Windows does: try to read 64 bytes -- there are devices which 152 1.78 maxv * recognize the initial descriptor fetch (before the control endpoint's 153 1.78 maxv * MaxPacketSize is known by the host) by exactly this length. 154 1.78 maxv */ 155 1.78 maxv usbd_status 156 1.78 maxv usbd_get_initial_ddesc(struct usbd_device *dev, usb_device_descriptor_t *desc) 157 1.78 maxv { 158 1.78 maxv USBHIST_FUNC(); 159 1.78 maxv USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0); 160 1.78 maxv usb_device_request_t req; 161 1.78 maxv char buf[64]; 162 1.78 maxv int res, actlen; 163 1.78 maxv 164 1.78 maxv req.bmRequestType = UT_READ_DEVICE; 165 1.78 maxv req.bRequest = UR_GET_DESCRIPTOR; 166 1.78 maxv USETW2(req.wValue, UDESC_DEVICE, 0); 167 1.78 maxv USETW(req.wIndex, 0); 168 1.78 maxv USETW(req.wLength, 8); 169 1.78 maxv res = usbd_do_request_flags(dev, &req, buf, USBD_SHORT_XFER_OK, 170 1.78 maxv &actlen, USBD_DEFAULT_TIMEOUT); 171 1.78 maxv if (res) 172 1.78 maxv return res; 173 1.78 maxv if (actlen < 8) 174 1.78 maxv return USBD_SHORT_XFER; 175 1.78 maxv memcpy(desc, buf, 8); 176 1.78 maxv return USBD_NORMAL_COMPLETION; 177 1.78 maxv } 178 1.78 maxv 179 1.78 maxv usbd_status 180 1.78 maxv usbd_get_string_desc(struct usbd_device *dev, int sindex, int langid, 181 1.78 maxv usb_string_descriptor_t *sdesc, int *sizep) 182 1.78 maxv { 183 1.78 maxv USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 184 1.78 maxv usb_device_request_t req; 185 1.78 maxv usbd_status err; 186 1.78 maxv int actlen; 187 1.78 maxv 188 1.78 maxv /* 189 1.78 maxv * Pass a full-sized buffer to usbd_do_request_len(). At least 190 1.78 maxv * one device has been seen returning additional data beyond the 191 1.78 maxv * provided buffers (2-bytes written shortly after the request 192 1.78 maxv * claims to have completed and returned the 2 byte header, 193 1.78 maxv * corrupting other memory.) 194 1.78 maxv */ 195 1.78 maxv req.bmRequestType = UT_READ_DEVICE; 196 1.78 maxv req.bRequest = UR_GET_DESCRIPTOR; 197 1.78 maxv USETW2(req.wValue, UDESC_STRING, sindex); 198 1.78 maxv USETW(req.wIndex, langid); 199 1.78 maxv USETW(req.wLength, 2); /* only size byte first */ 200 1.78 maxv err = usbd_do_request_len(dev, &req, sizeof(*sdesc), sdesc, 201 1.78 maxv USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT); 202 1.78 maxv if (err) 203 1.78 maxv return err; 204 1.78 maxv 205 1.78 maxv if (actlen < 2) 206 1.78 maxv return USBD_SHORT_XFER; 207 1.78 maxv 208 1.78 maxv if (sdesc->bLength > sizeof(*sdesc)) 209 1.78 maxv return USBD_INVAL; 210 1.78 maxv USETW(req.wLength, sdesc->bLength); /* the whole string */ 211 1.78 maxv err = usbd_do_request_len(dev, &req, sizeof(*sdesc), sdesc, 212 1.78 maxv USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT); 213 1.78 maxv if (err) 214 1.78 maxv return err; 215 1.78 maxv 216 1.78 maxv if (actlen != sdesc->bLength) { 217 1.78 maxv DPRINTF("expected %jd, got %jd", sdesc->bLength, actlen, 0, 0); 218 1.78 maxv } 219 1.78 maxv 220 1.78 maxv *sizep = actlen; 221 1.78 maxv return USBD_NORMAL_COMPLETION; 222 1.78 maxv } 223 1.78 maxv 224 1.77 maxv /* -------------------------------------------------------------------------- */ 225 1.77 maxv 226 1.1 augustss usbd_status 227 1.65 skrll usbd_get_device_status(struct usbd_device *dev, usb_status_t *st) 228 1.1 augustss { 229 1.65 skrll USBHIST_FUNC(); USBHIST_CALLED(usbdebug); 230 1.1 augustss usb_device_request_t req; 231 1.1 augustss 232 1.1 augustss req.bmRequestType = UT_READ_DEVICE; 233 1.1 augustss req.bRequest = UR_GET_STATUS; 234 1.1 augustss USETW(req.wValue, 0); 235 1.1 augustss USETW(req.wIndex, 0); 236 1.1 augustss USETW(req.wLength, sizeof(usb_status_t)); 237 1.65 skrll return usbd_do_request(dev, &req, st); 238 1.40 augustss } 239 1.1 augustss 240 1.1 augustss usbd_status 241 1.65 skrll usbd_get_hub_status(struct usbd_device *dev, usb_hub_status_t *st) 242 1.1 augustss { 243 1.75 mrg USBHIST_FUNC(); 244 1.75 mrg USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0); 245 1.1 augustss usb_device_request_t req; 246 1.1 augustss 247 1.1 augustss req.bmRequestType = UT_READ_CLASS_DEVICE; 248 1.1 augustss req.bRequest = UR_GET_STATUS; 249 1.1 augustss USETW(req.wValue, 0); 250 1.1 augustss USETW(req.wIndex, 0); 251 1.1 augustss USETW(req.wLength, sizeof(usb_hub_status_t)); 252 1.65 skrll return usbd_do_request(dev, &req, st); 253 1.40 augustss } 254 1.1 augustss 255 1.1 augustss usbd_status 256 1.65 skrll usbd_get_port_status(struct usbd_device *dev, int port, usb_port_status_t *ps) 257 1.1 augustss { 258 1.75 mrg USBHIST_FUNC(); 259 1.75 mrg USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd", 260 1.75 mrg (uintptr_t)dev, port, 0, 0); 261 1.1 augustss usb_device_request_t req; 262 1.1 augustss 263 1.1 augustss req.bmRequestType = UT_READ_CLASS_OTHER; 264 1.1 augustss req.bRequest = UR_GET_STATUS; 265 1.1 augustss USETW(req.wValue, 0); 266 1.1 augustss USETW(req.wIndex, port); 267 1.65 skrll USETW(req.wLength, sizeof(*ps)); 268 1.65 skrll return usbd_do_request(dev, &req, ps); 269 1.65 skrll } 270 1.65 skrll 271 1.65 skrll /* USB 3.1 10.16.2.6, 10.16.2.6.3 */ 272 1.65 skrll usbd_status 273 1.65 skrll usbd_get_port_status_ext(struct usbd_device *dev, int port, 274 1.65 skrll usb_port_status_ext_t *pse) 275 1.65 skrll { 276 1.75 mrg USBHIST_FUNC(); 277 1.75 mrg USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd", 278 1.75 mrg (uintptr_t)dev, port, 0, 0); 279 1.65 skrll usb_device_request_t req; 280 1.65 skrll 281 1.65 skrll req.bmRequestType = UT_READ_CLASS_OTHER; 282 1.65 skrll req.bRequest = UR_GET_STATUS; 283 1.65 skrll USETW2(req.wValue, 0, UR_PST_EXT_PORT_STATUS); 284 1.65 skrll USETW(req.wIndex, port); 285 1.65 skrll USETW(req.wLength, sizeof(*pse)); 286 1.69 skrll return usbd_do_request(dev, &req, pse); 287 1.16 augustss } 288 1.16 augustss 289 1.77 maxv /* -------------------------------------------------------------------------- */ 290 1.77 maxv 291 1.16 augustss usbd_status 292 1.65 skrll usbd_clear_hub_feature(struct usbd_device *dev, int sel) 293 1.16 augustss { 294 1.75 mrg USBHIST_FUNC(); 295 1.75 mrg USBHIST_CALLARGS(usbdebug, "dev %#jx sel %jd", 296 1.75 mrg (uintptr_t)dev, sel, 0, 0); 297 1.16 augustss usb_device_request_t req; 298 1.16 augustss 299 1.16 augustss req.bmRequestType = UT_WRITE_CLASS_DEVICE; 300 1.16 augustss req.bRequest = UR_CLEAR_FEATURE; 301 1.16 augustss USETW(req.wValue, sel); 302 1.16 augustss USETW(req.wIndex, 0); 303 1.16 augustss USETW(req.wLength, 0); 304 1.65 skrll return usbd_do_request(dev, &req, 0); 305 1.16 augustss } 306 1.16 augustss 307 1.16 augustss usbd_status 308 1.65 skrll usbd_set_hub_feature(struct usbd_device *dev, int sel) 309 1.16 augustss { 310 1.75 mrg USBHIST_FUNC(); 311 1.75 mrg USBHIST_CALLARGS(usbdebug, 312 1.75 mrg "dev %#jx sel %jd", (uintptr_t)dev, sel, 0, 0); 313 1.16 augustss usb_device_request_t req; 314 1.16 augustss 315 1.16 augustss req.bmRequestType = UT_WRITE_CLASS_DEVICE; 316 1.16 augustss req.bRequest = UR_SET_FEATURE; 317 1.16 augustss USETW(req.wValue, sel); 318 1.16 augustss USETW(req.wIndex, 0); 319 1.16 augustss USETW(req.wLength, 0); 320 1.65 skrll return usbd_do_request(dev, &req, 0); 321 1.1 augustss } 322 1.1 augustss 323 1.1 augustss usbd_status 324 1.65 skrll usbd_clear_port_feature(struct usbd_device *dev, int port, int sel) 325 1.1 augustss { 326 1.75 mrg USBHIST_FUNC(); 327 1.75 mrg USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd sel %jd", 328 1.75 mrg (uintptr_t)dev, port, sel, 0); 329 1.1 augustss usb_device_request_t req; 330 1.1 augustss 331 1.1 augustss req.bmRequestType = UT_WRITE_CLASS_OTHER; 332 1.1 augustss req.bRequest = UR_CLEAR_FEATURE; 333 1.1 augustss USETW(req.wValue, sel); 334 1.1 augustss USETW(req.wIndex, port); 335 1.1 augustss USETW(req.wLength, 0); 336 1.65 skrll return usbd_do_request(dev, &req, 0); 337 1.1 augustss } 338 1.1 augustss 339 1.1 augustss usbd_status 340 1.65 skrll usbd_set_port_feature(struct usbd_device *dev, int port, int sel) 341 1.1 augustss { 342 1.75 mrg USBHIST_FUNC(); 343 1.75 mrg USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd sel %.d", 344 1.75 mrg (uintptr_t)dev, sel, 0, 0); 345 1.1 augustss usb_device_request_t req; 346 1.1 augustss 347 1.1 augustss req.bmRequestType = UT_WRITE_CLASS_OTHER; 348 1.1 augustss req.bRequest = UR_SET_FEATURE; 349 1.1 augustss USETW(req.wValue, sel); 350 1.1 augustss USETW(req.wIndex, port); 351 1.1 augustss USETW(req.wLength, 0); 352 1.65 skrll return usbd_do_request(dev, &req, 0); 353 1.1 augustss } 354 1.1 augustss 355 1.39 augustss usbd_status 356 1.65 skrll usbd_set_port_u1_timeout(struct usbd_device *dev, int port, int timeout) 357 1.65 skrll { 358 1.75 mrg USBHIST_FUNC(); 359 1.75 mrg USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd timeout %.d", 360 1.75 mrg (uintptr_t)dev, port, timeout, 0); 361 1.65 skrll usb_device_request_t req; 362 1.65 skrll 363 1.65 skrll req.bmRequestType = UT_WRITE_CLASS_OTHER; 364 1.65 skrll req.bRequest = UR_SET_FEATURE; 365 1.65 skrll USETW(req.wValue, UHF_PORT_U1_TIMEOUT); 366 1.65 skrll USETW2(req.wIndex, timeout, port); 367 1.65 skrll USETW(req.wLength, 0); 368 1.65 skrll return usbd_do_request(dev, &req, 0); 369 1.65 skrll } 370 1.65 skrll 371 1.65 skrll usbd_status 372 1.65 skrll usbd_set_port_u2_timeout(struct usbd_device *dev, int port, int timeout) 373 1.65 skrll { 374 1.75 mrg USBHIST_FUNC(); 375 1.75 mrg USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd timeout %jd", 376 1.75 mrg (uintptr_t)dev, port, timeout, 0); 377 1.65 skrll usb_device_request_t req; 378 1.65 skrll 379 1.65 skrll req.bmRequestType = UT_WRITE_CLASS_OTHER; 380 1.65 skrll req.bRequest = UR_SET_FEATURE; 381 1.65 skrll USETW(req.wValue, UHF_PORT_U2_TIMEOUT); 382 1.65 skrll USETW2(req.wIndex, timeout, port); 383 1.65 skrll USETW(req.wLength, 0); 384 1.65 skrll return usbd_do_request(dev, &req, 0); 385 1.65 skrll } 386 1.65 skrll 387 1.65 skrll usbd_status 388 1.76 maxv usbd_clear_endpoint_feature(struct usbd_device *dev, int epaddr, int sel) 389 1.76 maxv { 390 1.76 maxv USBHIST_FUNC(); 391 1.79 skrll USBHIST_CALLARGS(usbdebug, "dev %#jx epaddr %jd sel %jd", 392 1.79 skrll (uintptr_t)dev, epaddr, sel, 0); 393 1.76 maxv usb_device_request_t req; 394 1.76 maxv 395 1.76 maxv req.bmRequestType = UT_WRITE_ENDPOINT; 396 1.76 maxv req.bRequest = UR_CLEAR_FEATURE; 397 1.76 maxv USETW(req.wValue, sel); 398 1.76 maxv USETW(req.wIndex, epaddr); 399 1.76 maxv USETW(req.wLength, 0); 400 1.76 maxv return usbd_do_request(dev, &req, 0); 401 1.76 maxv } 402 1.76 maxv 403 1.77 maxv /* -------------------------------------------------------------------------- */ 404 1.77 maxv 405 1.77 maxv usbd_status 406 1.77 maxv usbd_get_config(struct usbd_device *dev, uint8_t *conf) 407 1.77 maxv { 408 1.77 maxv USBHIST_FUNC(); 409 1.77 maxv USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0); 410 1.77 maxv usb_device_request_t req; 411 1.77 maxv 412 1.77 maxv req.bmRequestType = UT_READ_DEVICE; 413 1.77 maxv req.bRequest = UR_GET_CONFIG; 414 1.77 maxv USETW(req.wValue, 0); 415 1.77 maxv USETW(req.wIndex, 0); 416 1.77 maxv USETW(req.wLength, 1); 417 1.77 maxv return usbd_do_request(dev, &req, conf); 418 1.77 maxv } 419 1.77 maxv 420 1.77 maxv usbd_status 421 1.78 maxv usbd_set_config(struct usbd_device *dev, int conf) 422 1.78 maxv { 423 1.78 maxv USBHIST_FUNC(); 424 1.78 maxv USBHIST_CALLARGS(usbdebug, "dev %#jx conf %jd", 425 1.78 maxv (uintptr_t)dev, conf, 0, 0); 426 1.78 maxv usb_device_request_t req; 427 1.78 maxv 428 1.78 maxv req.bmRequestType = UT_WRITE_DEVICE; 429 1.78 maxv req.bRequest = UR_SET_CONFIG; 430 1.78 maxv USETW(req.wValue, conf); 431 1.78 maxv USETW(req.wIndex, 0); 432 1.78 maxv USETW(req.wLength, 0); 433 1.78 maxv return usbd_do_request(dev, &req, 0); 434 1.78 maxv } 435 1.78 maxv 436 1.78 maxv usbd_status 437 1.77 maxv usbd_set_address(struct usbd_device *dev, int addr) 438 1.77 maxv { 439 1.77 maxv USBHIST_FUNC(); 440 1.77 maxv USBHIST_CALLARGS(usbdebug, "dev %#jx addr %jd", 441 1.77 maxv (uintptr_t)dev, addr, 0, 0); 442 1.77 maxv usb_device_request_t req; 443 1.77 maxv 444 1.77 maxv req.bmRequestType = UT_WRITE_DEVICE; 445 1.77 maxv req.bRequest = UR_SET_ADDRESS; 446 1.77 maxv USETW(req.wValue, addr); 447 1.77 maxv USETW(req.wIndex, 0); 448 1.77 maxv USETW(req.wLength, 0); 449 1.77 maxv return usbd_do_request(dev, &req, 0); 450 1.77 maxv } 451 1.77 maxv 452 1.77 maxv usbd_status 453 1.77 maxv usbd_set_idle(struct usbd_interface *iface, int duration, int id) 454 1.77 maxv { 455 1.77 maxv usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); 456 1.77 maxv struct usbd_device *dev; 457 1.77 maxv usb_device_request_t req; 458 1.77 maxv 459 1.77 maxv USBHIST_FUNC(); 460 1.77 maxv USBHIST_CALLARGS(usbdebug, "duration %jd id %jd", duration, id, 0, 0); 461 1.77 maxv 462 1.77 maxv if (ifd == NULL) 463 1.77 maxv return USBD_IOERROR; 464 1.77 maxv usbd_interface2device_handle(iface, &dev); 465 1.77 maxv req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 466 1.77 maxv req.bRequest = UR_SET_IDLE; 467 1.77 maxv USETW2(req.wValue, duration, id); 468 1.77 maxv USETW(req.wIndex, ifd->bInterfaceNumber); 469 1.77 maxv USETW(req.wLength, 0); 470 1.77 maxv return usbd_do_request(dev, &req, 0); 471 1.77 maxv } 472 1.77 maxv 473 1.77 maxv /* -------------------------------------------------------------------------- */ 474 1.77 maxv 475 1.76 maxv usbd_status 476 1.65 skrll usbd_get_protocol(struct usbd_interface *iface, uint8_t *report) 477 1.39 augustss { 478 1.39 augustss usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); 479 1.65 skrll struct usbd_device *dev; 480 1.39 augustss usb_device_request_t req; 481 1.39 augustss 482 1.75 mrg USBHIST_FUNC(); 483 1.75 mrg USBHIST_CALLARGS(usbdebug, "iface=%#jx, endpt=%jd", 484 1.75 mrg (uintptr_t)iface, id->bInterfaceNumber, 0, 0); 485 1.65 skrll 486 1.39 augustss if (id == NULL) 487 1.65 skrll return USBD_IOERROR; 488 1.68 maya 489 1.39 augustss usbd_interface2device_handle(iface, &dev); 490 1.39 augustss req.bmRequestType = UT_READ_CLASS_INTERFACE; 491 1.39 augustss req.bRequest = UR_GET_PROTOCOL; 492 1.39 augustss USETW(req.wValue, 0); 493 1.39 augustss USETW(req.wIndex, id->bInterfaceNumber); 494 1.39 augustss USETW(req.wLength, 1); 495 1.65 skrll return usbd_do_request(dev, &req, report); 496 1.39 augustss } 497 1.1 augustss 498 1.1 augustss usbd_status 499 1.65 skrll usbd_set_protocol(struct usbd_interface *iface, int report) 500 1.1 augustss { 501 1.1 augustss usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); 502 1.65 skrll struct usbd_device *dev; 503 1.1 augustss usb_device_request_t req; 504 1.1 augustss 505 1.75 mrg USBHIST_FUNC(); 506 1.75 mrg USBHIST_CALLARGS(usbdebug, "iface=%#jx, report=%jd, endpt=%jd", 507 1.75 mrg (uintptr_t)iface, report, id->bInterfaceNumber, 0); 508 1.65 skrll 509 1.67 maya if (id == NULL) 510 1.67 maya return USBD_IOERROR; 511 1.67 maya 512 1.37 augustss usbd_interface2device_handle(iface, &dev); 513 1.1 augustss req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 514 1.1 augustss req.bRequest = UR_SET_PROTOCOL; 515 1.1 augustss USETW(req.wValue, report); 516 1.1 augustss USETW(req.wIndex, id->bInterfaceNumber); 517 1.1 augustss USETW(req.wLength, 0); 518 1.65 skrll return usbd_do_request(dev, &req, 0); 519 1.1 augustss } 520 1.1 augustss 521 1.77 maxv /* -------------------------------------------------------------------------- */ 522 1.77 maxv 523 1.1 augustss usbd_status 524 1.65 skrll usbd_set_report(struct usbd_interface *iface, int type, int id, void *data, 525 1.31 augustss int len) 526 1.1 augustss { 527 1.1 augustss usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); 528 1.65 skrll struct usbd_device *dev; 529 1.1 augustss usb_device_request_t req; 530 1.1 augustss 531 1.75 mrg USBHIST_FUNC(); 532 1.75 mrg USBHIST_CALLARGS(usbdebug, "len=%jd", len, 0, 0, 0); 533 1.65 skrll 534 1.23 augustss if (ifd == NULL) 535 1.65 skrll return USBD_IOERROR; 536 1.37 augustss usbd_interface2device_handle(iface, &dev); 537 1.1 augustss req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 538 1.1 augustss req.bRequest = UR_SET_REPORT; 539 1.2 augustss USETW2(req.wValue, type, id); 540 1.2 augustss USETW(req.wIndex, ifd->bInterfaceNumber); 541 1.2 augustss USETW(req.wLength, len); 542 1.65 skrll return usbd_do_request(dev, &req, data); 543 1.3 augustss } 544 1.3 augustss 545 1.3 augustss usbd_status 546 1.65 skrll usbd_get_report(struct usbd_interface *iface, int type, int id, void *data, 547 1.31 augustss int len) 548 1.2 augustss { 549 1.2 augustss usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); 550 1.65 skrll struct usbd_device *dev; 551 1.2 augustss usb_device_request_t req; 552 1.2 augustss 553 1.75 mrg USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "len=%jd", len, 0, 0, 0); 554 1.65 skrll 555 1.28 augustss if (ifd == NULL) 556 1.65 skrll return USBD_IOERROR; 557 1.37 augustss usbd_interface2device_handle(iface, &dev); 558 1.2 augustss req.bmRequestType = UT_READ_CLASS_INTERFACE; 559 1.2 augustss req.bRequest = UR_GET_REPORT; 560 1.1 augustss USETW2(req.wValue, type, id); 561 1.1 augustss USETW(req.wIndex, ifd->bInterfaceNumber); 562 1.1 augustss USETW(req.wLength, len); 563 1.65 skrll return usbd_do_request(dev, &req, data); 564 1.1 augustss } 565 1.1 augustss 566 1.1 augustss usbd_status 567 1.65 skrll usbd_get_report_descriptor(struct usbd_device *dev, int ifcno, 568 1.31 augustss int size, void *d) 569 1.1 augustss { 570 1.75 mrg USBHIST_FUNC(); 571 1.75 mrg USBHIST_CALLARGS(usbdebug, "dev %#jx ifcno %jd size %jd", 572 1.75 mrg (uintptr_t)dev, ifcno, size, 0); 573 1.1 augustss usb_device_request_t req; 574 1.1 augustss 575 1.1 augustss req.bmRequestType = UT_READ_INTERFACE; 576 1.1 augustss req.bRequest = UR_GET_DESCRIPTOR; 577 1.35 augustss USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */ 578 1.6 augustss USETW(req.wIndex, ifcno); 579 1.1 augustss USETW(req.wLength, size); 580 1.65 skrll return usbd_do_request(dev, &req, d); 581 1.1 augustss } 582 1.1 augustss 583 1.77 maxv /* -------------------------------------------------------------------------- */ 584 1.77 maxv 585 1.1 augustss usb_hid_descriptor_t * 586 1.65 skrll usbd_get_hid_descriptor(struct usbd_interface *ifc) 587 1.1 augustss { 588 1.1 augustss usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc); 589 1.65 skrll struct usbd_device *dev; 590 1.1 augustss usb_config_descriptor_t *cdesc; 591 1.1 augustss usb_hid_descriptor_t *hd; 592 1.1 augustss char *p, *end; 593 1.1 augustss 594 1.23 augustss if (idesc == NULL) 595 1.65 skrll return NULL; 596 1.41 augustss usbd_interface2device_handle(ifc, &dev); 597 1.1 augustss cdesc = usbd_get_config_descriptor(dev); 598 1.1 augustss 599 1.1 augustss p = (char *)idesc + idesc->bLength; 600 1.1 augustss end = (char *)cdesc + UGETW(cdesc->wTotalLength); 601 1.1 augustss 602 1.85 riastrad for (; end - p >= sizeof(*hd); p += hd->bLength) { 603 1.1 augustss hd = (usb_hid_descriptor_t *)p; 604 1.85 riastrad if (hd->bLength < sizeof(*hd) || hd->bLength > end - p) 605 1.85 riastrad break; 606 1.85 riastrad if (hd->bLength >= USB_HID_DESCRIPTOR_SIZE(0) && 607 1.74 maxv hd->bDescriptorType == UDESC_HID) 608 1.65 skrll return hd; 609 1.1 augustss if (hd->bDescriptorType == UDESC_INTERFACE) 610 1.1 augustss break; 611 1.1 augustss } 612 1.65 skrll return NULL; 613 1.1 augustss } 614 1.1 augustss 615 1.1 augustss usbd_status 616 1.65 skrll usbd_read_report_desc(struct usbd_interface *ifc, void **descp, int *sizep) 617 1.1 augustss { 618 1.6 augustss usb_interface_descriptor_t *id; 619 1.1 augustss usb_hid_descriptor_t *hid; 620 1.65 skrll struct usbd_device *dev; 621 1.23 augustss usbd_status err; 622 1.1 augustss 623 1.37 augustss usbd_interface2device_handle(ifc, &dev); 624 1.6 augustss id = usbd_get_interface_descriptor(ifc); 625 1.23 augustss if (id == NULL) 626 1.65 skrll return USBD_INVAL; 627 1.1 augustss hid = usbd_get_hid_descriptor(ifc); 628 1.25 augustss if (hid == NULL) 629 1.65 skrll return USBD_IOERROR; 630 1.1 augustss *sizep = UGETW(hid->descrs[0].wDescriptorLength); 631 1.74 maxv if (*sizep == 0) 632 1.74 maxv return USBD_INVAL; 633 1.65 skrll *descp = kmem_alloc(*sizep, KM_SLEEP); 634 1.35 augustss err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 635 1.35 augustss *sizep, *descp); 636 1.23 augustss if (err) { 637 1.65 skrll kmem_free(*descp, *sizep); 638 1.34 augustss *descp = NULL; 639 1.65 skrll return err; 640 1.1 augustss } 641 1.65 skrll return USBD_NORMAL_COMPLETION; 642 1.7 augustss } 643 1.7 augustss 644 1.40 augustss usbd_status 645 1.65 skrll usbd_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe, 646 1.65 skrll uint16_t flags, uint32_t timeout, void *buf, uint32_t *size) 647 1.10 augustss { 648 1.23 augustss usbd_status err; 649 1.10 augustss 650 1.75 mrg USBHIST_FUNC(); 651 1.75 mrg USBHIST_CALLARGS(usbdebug, "start transfer %jd bytes", *size, 0, 0, 0); 652 1.63 skrll 653 1.65 skrll usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL); 654 1.61 skrll err = usbd_sync_transfer_sig(xfer); 655 1.57 mrg 656 1.57 mrg usbd_get_xfer_status(xfer, NULL, NULL, size, NULL); 657 1.70 pgoyette DPRINTFN(1, "transferred %jd", *size, 0, 0, 0); 658 1.23 augustss if (err) { 659 1.10 augustss usbd_clear_endpoint_stall(pipe); 660 1.10 augustss } 661 1.82 christos USBHIST_LOG(usbdebug, "<- done xfer %#jx err %jd", (uintptr_t)xfer, 662 1.70 pgoyette err, 0, 0); 663 1.61 skrll 664 1.65 skrll return err; 665 1.10 augustss } 666 1.10 augustss 667 1.42 augustss usbd_status 668 1.65 skrll usbd_intr_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe, 669 1.65 skrll uint16_t flags, uint32_t timeout, void *buf, uint32_t *size) 670 1.42 augustss { 671 1.42 augustss usbd_status err; 672 1.42 augustss 673 1.75 mrg USBHIST_FUNC(); 674 1.75 mrg USBHIST_CALLARGS(usbdebug, "start transfer %jd bytes", *size, 0, 0, 0); 675 1.63 skrll 676 1.65 skrll usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL); 677 1.61 skrll 678 1.57 mrg err = usbd_sync_transfer_sig(xfer); 679 1.61 skrll 680 1.57 mrg usbd_get_xfer_status(xfer, NULL, NULL, size, NULL); 681 1.61 skrll 682 1.70 pgoyette DPRINTFN(1, "transferred %jd", *size, 0, 0, 0); 683 1.42 augustss if (err) { 684 1.42 augustss usbd_clear_endpoint_stall(pipe); 685 1.42 augustss } 686 1.70 pgoyette USBHIST_LOG(usbdebug, "<- done xfer %#jx err %jd", (uintptr_t)xfer, 687 1.70 pgoyette err, 0, 0); 688 1.63 skrll 689 1.65 skrll return err; 690 1.42 augustss } 691 1.42 augustss 692 1.14 augustss void 693 1.56 mrg usb_detach_waitold(device_t dv) 694 1.14 augustss { 695 1.75 mrg USBHIST_FUNC(); 696 1.75 mrg USBHIST_CALLARGS(usbdebug, "waiting for dv %#jx", 697 1.75 mrg (uintptr_t)dv, 0, 0, 0); 698 1.65 skrll 699 1.57 mrg if (tsleep(dv, PZERO, "usbdet", hz * 60)) /* XXXSMP ok */ 700 1.71 msaitoh aprint_error_dev(dv, "usb_detach_waitold: didn't detach\n"); 701 1.65 skrll DPRINTFN(1, "done", 0, 0, 0, 0); 702 1.40 augustss } 703 1.14 augustss 704 1.14 augustss void 705 1.56 mrg usb_detach_wakeupold(device_t dv) 706 1.14 augustss { 707 1.75 mrg USBHIST_FUNC(); 708 1.75 mrg USBHIST_CALLARGS(usbdebug, "for dv %#jx", (uintptr_t)dv, 0, 0, 0); 709 1.65 skrll 710 1.57 mrg wakeup(dv); /* XXXSMP ok */ 711 1.40 augustss } 712 1.38 augustss 713 1.80 maxv /* -------------------------------------------------------------------------- */ 714 1.80 maxv 715 1.80 maxv void 716 1.80 maxv usb_desc_iter_init(struct usbd_device *dev, usbd_desc_iter_t *iter) 717 1.80 maxv { 718 1.80 maxv const usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); 719 1.80 maxv 720 1.80 maxv iter->cur = (const uByte *)cd; 721 1.80 maxv iter->end = (const uByte *)cd + UGETW(cd->wTotalLength); 722 1.80 maxv } 723 1.80 maxv 724 1.80 maxv const usb_descriptor_t * 725 1.80 maxv usb_desc_iter_peek(usbd_desc_iter_t *iter) 726 1.80 maxv { 727 1.80 maxv const usb_descriptor_t *desc; 728 1.80 maxv 729 1.85 riastrad if (iter->end - iter->cur < sizeof(usb_descriptor_t)) { 730 1.80 maxv if (iter->cur != iter->end) 731 1.80 maxv printf("%s: bad descriptor\n", __func__); 732 1.80 maxv return NULL; 733 1.80 maxv } 734 1.80 maxv desc = (const usb_descriptor_t *)iter->cur; 735 1.81 maxv if (desc->bLength < USB_DESCRIPTOR_SIZE) { 736 1.81 maxv printf("%s: descriptor length too small\n", __func__); 737 1.80 maxv return NULL; 738 1.80 maxv } 739 1.85 riastrad if (desc->bLength > iter->end - iter->cur) { 740 1.80 maxv printf("%s: descriptor length too large\n", __func__); 741 1.80 maxv return NULL; 742 1.80 maxv } 743 1.80 maxv return desc; 744 1.80 maxv } 745 1.80 maxv 746 1.80 maxv const usb_descriptor_t * 747 1.80 maxv usb_desc_iter_next(usbd_desc_iter_t *iter) 748 1.80 maxv { 749 1.80 maxv const usb_descriptor_t *desc = usb_desc_iter_peek(iter); 750 1.86 riastrad 751 1.80 maxv if (desc == NULL) 752 1.80 maxv return NULL; 753 1.85 riastrad KASSERT(desc->bLength <= iter->end - iter->cur); 754 1.80 maxv iter->cur += desc->bLength; 755 1.80 maxv return desc; 756 1.80 maxv } 757 1.80 maxv 758 1.86 riastrad /* 759 1.86 riastrad * Return the next interface descriptor, skipping over any other 760 1.86 riastrad * descriptors. Returns NULL at the end or on error. 761 1.86 riastrad */ 762 1.80 maxv const usb_interface_descriptor_t * 763 1.80 maxv usb_desc_iter_next_interface(usbd_desc_iter_t *iter) 764 1.80 maxv { 765 1.80 maxv const usb_descriptor_t *desc; 766 1.80 maxv 767 1.80 maxv while ((desc = usb_desc_iter_peek(iter)) != NULL && 768 1.86 riastrad desc->bDescriptorType != UDESC_INTERFACE) { 769 1.80 maxv usb_desc_iter_next(iter); 770 1.80 maxv } 771 1.80 maxv 772 1.87 riastrad if ((desc = usb_desc_iter_next(iter)) == NULL || 773 1.87 riastrad desc->bLength < sizeof(usb_interface_descriptor_t)) 774 1.87 riastrad return NULL; 775 1.87 riastrad KASSERT(desc->bDescriptorType == UDESC_INTERFACE); 776 1.87 riastrad return (const usb_interface_descriptor_t *)desc; 777 1.80 maxv } 778 1.80 maxv 779 1.86 riastrad /* 780 1.86 riastrad * Returns the next non-interface descriptor, returning NULL when the 781 1.86 riastrad * next descriptor would be an interface descriptor. 782 1.86 riastrad */ 783 1.80 maxv const usb_descriptor_t * 784 1.80 maxv usb_desc_iter_next_non_interface(usbd_desc_iter_t *iter) 785 1.80 maxv { 786 1.80 maxv const usb_descriptor_t *desc; 787 1.80 maxv 788 1.80 maxv if ((desc = usb_desc_iter_peek(iter)) != NULL && 789 1.86 riastrad desc->bDescriptorType != UDESC_INTERFACE) { 790 1.80 maxv return usb_desc_iter_next(iter); 791 1.80 maxv } else { 792 1.80 maxv return NULL; 793 1.80 maxv } 794 1.80 maxv } 795 1.80 maxv 796 1.48 drochner const usb_cdc_descriptor_t * 797 1.65 skrll usb_find_desc(struct usbd_device *dev, int type, int subtype) 798 1.38 augustss { 799 1.41 augustss usbd_desc_iter_t iter; 800 1.48 drochner const usb_cdc_descriptor_t *desc; 801 1.41 augustss 802 1.41 augustss usb_desc_iter_init(dev, &iter); 803 1.41 augustss for (;;) { 804 1.48 drochner desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter); 805 1.86 riastrad if (desc == NULL) 806 1.86 riastrad break; 807 1.86 riastrad if (desc->bDescriptorType != type) 808 1.86 riastrad continue; 809 1.86 riastrad if (subtype == USBD_CDCSUBTYPE_ANY || 810 1.86 riastrad subtype == desc->bDescriptorSubtype) 811 1.41 augustss break; 812 1.38 augustss } 813 1.41 augustss return desc; 814 1.38 augustss } 815 1.43 itohy 816 1.86 riastrad /* 817 1.86 riastrad * Same as usb_find_desc(), but searches only in the specified 818 1.86 riastrad * interface. 819 1.86 riastrad */ 820 1.48 drochner const usb_cdc_descriptor_t * 821 1.65 skrll usb_find_desc_if(struct usbd_device *dev, int type, int subtype, 822 1.86 riastrad usb_interface_descriptor_t *id) 823 1.43 itohy { 824 1.43 itohy usbd_desc_iter_t iter; 825 1.48 drochner const usb_cdc_descriptor_t *desc; 826 1.43 itohy 827 1.54 christos if (id == NULL) 828 1.54 christos return usb_find_desc(dev, type, subtype); 829 1.54 christos 830 1.43 itohy usb_desc_iter_init(dev, &iter); 831 1.43 itohy 832 1.43 itohy iter.cur = (void *)id; /* start from the interface desc */ 833 1.43 itohy usb_desc_iter_next(&iter); /* and skip it */ 834 1.43 itohy 835 1.48 drochner while ((desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter)) 836 1.86 riastrad != NULL) { 837 1.43 itohy if (desc->bDescriptorType == UDESC_INTERFACE) { 838 1.43 itohy /* we ran into the next interface --- not found */ 839 1.43 itohy return NULL; 840 1.43 itohy } 841 1.43 itohy if (desc->bDescriptorType == type && 842 1.48 drochner (subtype == USBD_CDCSUBTYPE_ANY || 843 1.43 itohy subtype == desc->bDescriptorSubtype)) 844 1.43 itohy break; 845 1.43 itohy } 846 1.43 itohy return desc; 847 1.43 itohy } 848