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