Annotation of src/sys/dev/usb/usbdi_util.c, Revision 1.77
1.77 ! maxv 1: /* $NetBSD: usbdi_util.c,v 1.76 2020/02/08 07:53:23 maxv Exp $ */
1.1 augustss 2:
3: /*
1.57 mrg 4: * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc.
1.1 augustss 5: * All rights reserved.
6: *
1.5 augustss 7: * This code is derived from software contributed to The NetBSD Foundation
1.30 augustss 8: * by Lennart Augustsson (lennart@augustsson.net) at
1.57 mrg 9: * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au).
1.1 augustss 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: */
1.36 lukem 32:
33: #include <sys/cdefs.h>
1.77 ! maxv 34: __KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.76 2020/02/08 07:53:23 maxv Exp $");
1.63 skrll 35:
36: #ifdef _KERNEL_OPT
37: #include "opt_usb.h"
38: #endif
1.1 augustss 39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/kernel.h>
1.65 skrll 43: #include <sys/kmem.h>
1.1 augustss 44: #include <sys/proc.h>
1.14 augustss 45: #include <sys/device.h>
1.57 mrg 46: #include <sys/bus.h>
1.1 augustss 47:
48: #include <dev/usb/usb.h>
49: #include <dev/usb/usbhid.h>
50: #include <dev/usb/usbdi.h>
1.57 mrg 51: #include <dev/usb/usbdivar.h>
1.1 augustss 52: #include <dev/usb/usbdi_util.h>
1.72 manu 53: #include <dev/usb/usb_quirks.h>
1.63 skrll 54: #include <dev/usb/usbhist.h>
1.1 augustss 55:
1.65 skrll 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)
1.1 augustss 58:
59: usbd_status
1.65 skrll 60: usbd_get_desc(struct usbd_device *dev, int type, int index, int len, void *desc)
1.1 augustss 61: {
62: usb_device_request_t req;
1.72 manu 63: usbd_status err;
1.1 augustss 64:
1.75 mrg 65: USBHIST_FUNC();
66: USBHIST_CALLARGS(usbdebug, "type=%jd, index=%jd, len=%jd",
67: type, index, len, 0);
1.26 augustss 68:
1.72 manu 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:
1.1 augustss 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);
1.72 manu 86: err = usbd_do_request(dev, &req, desc);
87:
88: out:
89: return err;
1.1 augustss 90: }
91:
92: usbd_status
1.65 skrll 93: usbd_get_config_desc(struct usbd_device *dev, int confidx,
1.31 augustss 94: usb_config_descriptor_t *d)
1.1 augustss 95: {
1.75 mrg 96: USBHIST_FUNC();
97: USBHIST_CALLARGS(usbdebug, "confidx=%jd", confidx, 0, 0, 0);
1.23 augustss 98: usbd_status err;
1.9 augustss 99:
1.40 augustss 100: err = usbd_get_desc(dev, UDESC_CONFIG, confidx,
1.26 augustss 101: USB_CONFIG_DESCRIPTOR_SIZE, d);
1.23 augustss 102: if (err)
1.65 skrll 103: return err;
1.9 augustss 104: if (d->bDescriptorType != UDESC_CONFIG) {
1.70 pgoyette 105: DPRINTFN(1, "confidx=%jd, bad desc len=%d type=%d",
1.65 skrll 106: confidx, d->bLength, d->bDescriptorType, 0);
107: return USBD_INVAL;
1.9 augustss 108: }
1.65 skrll 109: return USBD_NORMAL_COMPLETION;
1.1 augustss 110: }
111:
112: usbd_status
1.65 skrll 113: usbd_get_config_desc_full(struct usbd_device *dev, int conf, void *d, int size)
1.4 augustss 114: {
1.75 mrg 115: USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "conf=%jd", conf, 0, 0, 0);
1.65 skrll 116:
117: return usbd_get_desc(dev, UDESC_CONFIG, conf, size, d);
1.4 augustss 118: }
119:
120: usbd_status
1.65 skrll 121: usbd_get_bos_desc(struct usbd_device *dev, int confidx,
1.64 skrll 122: usb_bos_descriptor_t *d)
123: {
1.75 mrg 124: USBHIST_FUNC();
125: USBHIST_CALLARGS(usbdebug, "confidx=%jd", confidx, 0, 0, 0);
1.64 skrll 126: usbd_status err;
127:
128: err = usbd_get_desc(dev, UDESC_BOS, confidx,
129: USB_BOS_DESCRIPTOR_SIZE, d);
130: if (err)
1.69 skrll 131: return err;
1.64 skrll 132: if (d->bDescriptorType != UDESC_BOS) {
1.70 pgoyette 133: DPRINTFN(1, "confidx=%jd, bad desc len=%d type=%d",
1.65 skrll 134: confidx, d->bLength, d->bDescriptorType, 0);
135: return USBD_INVAL;
1.64 skrll 136: }
1.65 skrll 137: return USBD_NORMAL_COMPLETION;
1.64 skrll 138: }
139:
140: usbd_status
1.65 skrll 141: usbd_get_bos_desc_full(struct usbd_device *dev, int conf, void *d, int size)
1.64 skrll 142: {
1.75 mrg 143: USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "conf=%jd", conf, 0, 0, 0);
1.65 skrll 144:
145: return usbd_get_desc(dev, UDESC_BOS, conf, size, d);
1.64 skrll 146: }
147:
148: usbd_status
1.65 skrll 149: usbd_get_device_desc(struct usbd_device *dev, usb_device_descriptor_t *d)
1.1 augustss 150: {
1.65 skrll 151: USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
152:
1.69 skrll 153: return usbd_get_desc(dev, UDESC_DEVICE,
154: 0, USB_DEVICE_DESCRIPTOR_SIZE, d);
1.1 augustss 155: }
156:
1.77 ! maxv 157: /* -------------------------------------------------------------------------- */
! 158:
1.1 augustss 159: usbd_status
1.65 skrll 160: usbd_get_device_status(struct usbd_device *dev, usb_status_t *st)
1.1 augustss 161: {
1.65 skrll 162: USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
1.1 augustss 163: usb_device_request_t req;
164:
165: req.bmRequestType = UT_READ_DEVICE;
166: req.bRequest = UR_GET_STATUS;
167: USETW(req.wValue, 0);
168: USETW(req.wIndex, 0);
169: USETW(req.wLength, sizeof(usb_status_t));
1.65 skrll 170: return usbd_do_request(dev, &req, st);
1.40 augustss 171: }
1.1 augustss 172:
173: usbd_status
1.65 skrll 174: usbd_get_hub_status(struct usbd_device *dev, usb_hub_status_t *st)
1.1 augustss 175: {
1.75 mrg 176: USBHIST_FUNC();
177: USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0);
1.1 augustss 178: usb_device_request_t req;
179:
180: req.bmRequestType = UT_READ_CLASS_DEVICE;
181: req.bRequest = UR_GET_STATUS;
182: USETW(req.wValue, 0);
183: USETW(req.wIndex, 0);
184: USETW(req.wLength, sizeof(usb_hub_status_t));
1.65 skrll 185: return usbd_do_request(dev, &req, st);
1.40 augustss 186: }
1.1 augustss 187:
188: usbd_status
1.65 skrll 189: usbd_get_port_status(struct usbd_device *dev, int port, usb_port_status_t *ps)
1.1 augustss 190: {
1.75 mrg 191: USBHIST_FUNC();
192: USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd",
193: (uintptr_t)dev, port, 0, 0);
1.1 augustss 194: usb_device_request_t req;
195:
196: req.bmRequestType = UT_READ_CLASS_OTHER;
197: req.bRequest = UR_GET_STATUS;
198: USETW(req.wValue, 0);
199: USETW(req.wIndex, port);
1.65 skrll 200: USETW(req.wLength, sizeof(*ps));
201: return usbd_do_request(dev, &req, ps);
202: }
203:
204: /* USB 3.1 10.16.2.6, 10.16.2.6.3 */
205: usbd_status
206: usbd_get_port_status_ext(struct usbd_device *dev, int port,
207: usb_port_status_ext_t *pse)
208: {
1.75 mrg 209: USBHIST_FUNC();
210: USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd",
211: (uintptr_t)dev, port, 0, 0);
1.65 skrll 212: usb_device_request_t req;
213:
214: req.bmRequestType = UT_READ_CLASS_OTHER;
215: req.bRequest = UR_GET_STATUS;
216: USETW2(req.wValue, 0, UR_PST_EXT_PORT_STATUS);
217: USETW(req.wIndex, port);
218: USETW(req.wLength, sizeof(*pse));
1.69 skrll 219: return usbd_do_request(dev, &req, pse);
1.16 augustss 220: }
221:
1.77 ! maxv 222: /* -------------------------------------------------------------------------- */
! 223:
1.16 augustss 224: usbd_status
1.65 skrll 225: usbd_clear_hub_feature(struct usbd_device *dev, int sel)
1.16 augustss 226: {
1.75 mrg 227: USBHIST_FUNC();
228: USBHIST_CALLARGS(usbdebug, "dev %#jx sel %jd",
229: (uintptr_t)dev, sel, 0, 0);
1.16 augustss 230: usb_device_request_t req;
231:
232: req.bmRequestType = UT_WRITE_CLASS_DEVICE;
233: req.bRequest = UR_CLEAR_FEATURE;
234: USETW(req.wValue, sel);
235: USETW(req.wIndex, 0);
236: USETW(req.wLength, 0);
1.65 skrll 237: return usbd_do_request(dev, &req, 0);
1.16 augustss 238: }
239:
240: usbd_status
1.65 skrll 241: usbd_set_hub_feature(struct usbd_device *dev, int sel)
1.16 augustss 242: {
1.75 mrg 243: USBHIST_FUNC();
244: USBHIST_CALLARGS(usbdebug,
245: "dev %#jx sel %jd", (uintptr_t)dev, sel, 0, 0);
1.16 augustss 246: usb_device_request_t req;
247:
248: req.bmRequestType = UT_WRITE_CLASS_DEVICE;
249: req.bRequest = UR_SET_FEATURE;
250: USETW(req.wValue, sel);
251: USETW(req.wIndex, 0);
252: USETW(req.wLength, 0);
1.65 skrll 253: return usbd_do_request(dev, &req, 0);
1.1 augustss 254: }
255:
256: usbd_status
1.65 skrll 257: usbd_clear_port_feature(struct usbd_device *dev, int port, int sel)
1.1 augustss 258: {
1.75 mrg 259: USBHIST_FUNC();
260: USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd sel %jd",
261: (uintptr_t)dev, port, sel, 0);
1.1 augustss 262: usb_device_request_t req;
263:
264: req.bmRequestType = UT_WRITE_CLASS_OTHER;
265: req.bRequest = UR_CLEAR_FEATURE;
266: USETW(req.wValue, sel);
267: USETW(req.wIndex, port);
268: USETW(req.wLength, 0);
1.65 skrll 269: return usbd_do_request(dev, &req, 0);
1.1 augustss 270: }
271:
272: usbd_status
1.65 skrll 273: usbd_set_port_feature(struct usbd_device *dev, int port, int sel)
1.1 augustss 274: {
1.75 mrg 275: USBHIST_FUNC();
276: USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd sel %.d",
277: (uintptr_t)dev, sel, 0, 0);
1.1 augustss 278: usb_device_request_t req;
279:
280: req.bmRequestType = UT_WRITE_CLASS_OTHER;
281: req.bRequest = UR_SET_FEATURE;
282: USETW(req.wValue, sel);
283: USETW(req.wIndex, port);
284: USETW(req.wLength, 0);
1.65 skrll 285: return usbd_do_request(dev, &req, 0);
1.1 augustss 286: }
287:
1.39 augustss 288: usbd_status
1.65 skrll 289: usbd_set_port_u1_timeout(struct usbd_device *dev, int port, int timeout)
290: {
1.75 mrg 291: USBHIST_FUNC();
292: USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd timeout %.d",
293: (uintptr_t)dev, port, timeout, 0);
1.65 skrll 294: usb_device_request_t req;
295:
296: req.bmRequestType = UT_WRITE_CLASS_OTHER;
297: req.bRequest = UR_SET_FEATURE;
298: USETW(req.wValue, UHF_PORT_U1_TIMEOUT);
299: USETW2(req.wIndex, timeout, port);
300: USETW(req.wLength, 0);
301: return usbd_do_request(dev, &req, 0);
302: }
303:
304: usbd_status
305: usbd_set_port_u2_timeout(struct usbd_device *dev, int port, int timeout)
306: {
1.75 mrg 307: USBHIST_FUNC();
308: USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd timeout %jd",
309: (uintptr_t)dev, port, timeout, 0);
1.65 skrll 310: usb_device_request_t req;
311:
312: req.bmRequestType = UT_WRITE_CLASS_OTHER;
313: req.bRequest = UR_SET_FEATURE;
314: USETW(req.wValue, UHF_PORT_U2_TIMEOUT);
315: USETW2(req.wIndex, timeout, port);
316: USETW(req.wLength, 0);
317: return usbd_do_request(dev, &req, 0);
318: }
319:
320: usbd_status
1.76 maxv 321: usbd_clear_endpoint_feature(struct usbd_device *dev, int epaddr, int sel)
322: {
323: USBHIST_FUNC();
324: usb_device_request_t req;
325:
326: req.bmRequestType = UT_WRITE_ENDPOINT;
327: req.bRequest = UR_CLEAR_FEATURE;
328: USETW(req.wValue, sel);
329: USETW(req.wIndex, epaddr);
330: USETW(req.wLength, 0);
331: return usbd_do_request(dev, &req, 0);
332: }
333:
1.77 ! maxv 334: /* -------------------------------------------------------------------------- */
! 335:
! 336: usbd_status
! 337: usbd_get_config(struct usbd_device *dev, uint8_t *conf)
! 338: {
! 339: USBHIST_FUNC();
! 340: USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0);
! 341: usb_device_request_t req;
! 342:
! 343: req.bmRequestType = UT_READ_DEVICE;
! 344: req.bRequest = UR_GET_CONFIG;
! 345: USETW(req.wValue, 0);
! 346: USETW(req.wIndex, 0);
! 347: USETW(req.wLength, 1);
! 348: return usbd_do_request(dev, &req, conf);
! 349: }
! 350:
! 351: usbd_status
! 352: usbd_set_address(struct usbd_device *dev, int addr)
! 353: {
! 354: USBHIST_FUNC();
! 355: USBHIST_CALLARGS(usbdebug, "dev %#jx addr %jd",
! 356: (uintptr_t)dev, addr, 0, 0);
! 357: usb_device_request_t req;
! 358:
! 359: req.bmRequestType = UT_WRITE_DEVICE;
! 360: req.bRequest = UR_SET_ADDRESS;
! 361: USETW(req.wValue, addr);
! 362: USETW(req.wIndex, 0);
! 363: USETW(req.wLength, 0);
! 364: return usbd_do_request(dev, &req, 0);
! 365: }
! 366:
! 367: usbd_status
! 368: usbd_set_idle(struct usbd_interface *iface, int duration, int id)
! 369: {
! 370: usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
! 371: struct usbd_device *dev;
! 372: usb_device_request_t req;
! 373:
! 374: USBHIST_FUNC();
! 375: USBHIST_CALLARGS(usbdebug, "duration %jd id %jd", duration, id, 0, 0);
! 376:
! 377: if (ifd == NULL)
! 378: return USBD_IOERROR;
! 379: usbd_interface2device_handle(iface, &dev);
! 380: req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
! 381: req.bRequest = UR_SET_IDLE;
! 382: USETW2(req.wValue, duration, id);
! 383: USETW(req.wIndex, ifd->bInterfaceNumber);
! 384: USETW(req.wLength, 0);
! 385: return usbd_do_request(dev, &req, 0);
! 386: }
! 387:
! 388: /* -------------------------------------------------------------------------- */
! 389:
1.76 maxv 390: usbd_status
1.65 skrll 391: usbd_get_protocol(struct usbd_interface *iface, uint8_t *report)
1.39 augustss 392: {
393: usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
1.65 skrll 394: struct usbd_device *dev;
1.39 augustss 395: usb_device_request_t req;
396:
1.75 mrg 397: USBHIST_FUNC();
398: USBHIST_CALLARGS(usbdebug, "iface=%#jx, endpt=%jd",
399: (uintptr_t)iface, id->bInterfaceNumber, 0, 0);
1.65 skrll 400:
1.39 augustss 401: if (id == NULL)
1.65 skrll 402: return USBD_IOERROR;
1.68 maya 403:
1.39 augustss 404: usbd_interface2device_handle(iface, &dev);
405: req.bmRequestType = UT_READ_CLASS_INTERFACE;
406: req.bRequest = UR_GET_PROTOCOL;
407: USETW(req.wValue, 0);
408: USETW(req.wIndex, id->bInterfaceNumber);
409: USETW(req.wLength, 1);
1.65 skrll 410: return usbd_do_request(dev, &req, report);
1.39 augustss 411: }
1.1 augustss 412:
413: usbd_status
1.65 skrll 414: usbd_set_protocol(struct usbd_interface *iface, int report)
1.1 augustss 415: {
416: usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
1.65 skrll 417: struct usbd_device *dev;
1.1 augustss 418: usb_device_request_t req;
419:
1.75 mrg 420: USBHIST_FUNC();
421: USBHIST_CALLARGS(usbdebug, "iface=%#jx, report=%jd, endpt=%jd",
422: (uintptr_t)iface, report, id->bInterfaceNumber, 0);
1.65 skrll 423:
1.67 maya 424: if (id == NULL)
425: return USBD_IOERROR;
426:
1.37 augustss 427: usbd_interface2device_handle(iface, &dev);
1.1 augustss 428: req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
429: req.bRequest = UR_SET_PROTOCOL;
430: USETW(req.wValue, report);
431: USETW(req.wIndex, id->bInterfaceNumber);
432: USETW(req.wLength, 0);
1.65 skrll 433: return usbd_do_request(dev, &req, 0);
1.1 augustss 434: }
435:
1.77 ! maxv 436: /* -------------------------------------------------------------------------- */
! 437:
1.1 augustss 438: usbd_status
1.65 skrll 439: usbd_set_report(struct usbd_interface *iface, int type, int id, void *data,
1.31 augustss 440: int len)
1.1 augustss 441: {
442: usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
1.65 skrll 443: struct usbd_device *dev;
1.1 augustss 444: usb_device_request_t req;
445:
1.75 mrg 446: USBHIST_FUNC();
447: USBHIST_CALLARGS(usbdebug, "len=%jd", len, 0, 0, 0);
1.65 skrll 448:
1.23 augustss 449: if (ifd == NULL)
1.65 skrll 450: return USBD_IOERROR;
1.37 augustss 451: usbd_interface2device_handle(iface, &dev);
1.1 augustss 452: req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
453: req.bRequest = UR_SET_REPORT;
1.2 augustss 454: USETW2(req.wValue, type, id);
455: USETW(req.wIndex, ifd->bInterfaceNumber);
456: USETW(req.wLength, len);
1.65 skrll 457: return usbd_do_request(dev, &req, data);
1.3 augustss 458: }
459:
460: usbd_status
1.65 skrll 461: usbd_get_report(struct usbd_interface *iface, int type, int id, void *data,
1.31 augustss 462: int len)
1.2 augustss 463: {
464: usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
1.65 skrll 465: struct usbd_device *dev;
1.2 augustss 466: usb_device_request_t req;
467:
1.75 mrg 468: USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "len=%jd", len, 0, 0, 0);
1.65 skrll 469:
1.28 augustss 470: if (ifd == NULL)
1.65 skrll 471: return USBD_IOERROR;
1.37 augustss 472: usbd_interface2device_handle(iface, &dev);
1.2 augustss 473: req.bmRequestType = UT_READ_CLASS_INTERFACE;
474: req.bRequest = UR_GET_REPORT;
1.1 augustss 475: USETW2(req.wValue, type, id);
476: USETW(req.wIndex, ifd->bInterfaceNumber);
477: USETW(req.wLength, len);
1.65 skrll 478: return usbd_do_request(dev, &req, data);
1.1 augustss 479: }
480:
481: usbd_status
1.65 skrll 482: usbd_get_report_descriptor(struct usbd_device *dev, int ifcno,
1.31 augustss 483: int size, void *d)
1.1 augustss 484: {
1.75 mrg 485: USBHIST_FUNC();
486: USBHIST_CALLARGS(usbdebug, "dev %#jx ifcno %jd size %jd",
487: (uintptr_t)dev, ifcno, size, 0);
1.1 augustss 488: usb_device_request_t req;
489:
490: req.bmRequestType = UT_READ_INTERFACE;
491: req.bRequest = UR_GET_DESCRIPTOR;
1.35 augustss 492: USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */
1.6 augustss 493: USETW(req.wIndex, ifcno);
1.1 augustss 494: USETW(req.wLength, size);
1.65 skrll 495: return usbd_do_request(dev, &req, d);
1.1 augustss 496: }
497:
1.77 ! maxv 498: /* -------------------------------------------------------------------------- */
! 499:
1.1 augustss 500: usb_hid_descriptor_t *
1.65 skrll 501: usbd_get_hid_descriptor(struct usbd_interface *ifc)
1.1 augustss 502: {
503: usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc);
1.65 skrll 504: struct usbd_device *dev;
1.1 augustss 505: usb_config_descriptor_t *cdesc;
506: usb_hid_descriptor_t *hd;
507: char *p, *end;
508:
1.23 augustss 509: if (idesc == NULL)
1.65 skrll 510: return NULL;
1.41 augustss 511: usbd_interface2device_handle(ifc, &dev);
1.1 augustss 512: cdesc = usbd_get_config_descriptor(dev);
513:
514: p = (char *)idesc + idesc->bLength;
515: end = (char *)cdesc + UGETW(cdesc->wTotalLength);
516:
517: for (; p < end; p += hd->bLength) {
518: hd = (usb_hid_descriptor_t *)p;
1.74 maxv 519: if (p + hd->bLength <= end &&
520: hd->bLength >= USB_HID_DESCRIPTOR_SIZE(0) &&
521: hd->bDescriptorType == UDESC_HID)
1.65 skrll 522: return hd;
1.1 augustss 523: if (hd->bDescriptorType == UDESC_INTERFACE)
524: break;
525: }
1.65 skrll 526: return NULL;
1.1 augustss 527: }
528:
529: usbd_status
1.65 skrll 530: usbd_read_report_desc(struct usbd_interface *ifc, void **descp, int *sizep)
1.1 augustss 531: {
1.6 augustss 532: usb_interface_descriptor_t *id;
1.1 augustss 533: usb_hid_descriptor_t *hid;
1.65 skrll 534: struct usbd_device *dev;
1.23 augustss 535: usbd_status err;
1.1 augustss 536:
1.37 augustss 537: usbd_interface2device_handle(ifc, &dev);
1.6 augustss 538: id = usbd_get_interface_descriptor(ifc);
1.23 augustss 539: if (id == NULL)
1.65 skrll 540: return USBD_INVAL;
1.1 augustss 541: hid = usbd_get_hid_descriptor(ifc);
1.25 augustss 542: if (hid == NULL)
1.65 skrll 543: return USBD_IOERROR;
1.1 augustss 544: *sizep = UGETW(hid->descrs[0].wDescriptorLength);
1.74 maxv 545: if (*sizep == 0)
546: return USBD_INVAL;
1.65 skrll 547: *descp = kmem_alloc(*sizep, KM_SLEEP);
1.35 augustss 548: err = usbd_get_report_descriptor(dev, id->bInterfaceNumber,
549: *sizep, *descp);
1.23 augustss 550: if (err) {
1.65 skrll 551: kmem_free(*descp, *sizep);
1.34 augustss 552: *descp = NULL;
1.65 skrll 553: return err;
1.1 augustss 554: }
1.65 skrll 555: return USBD_NORMAL_COMPLETION;
1.7 augustss 556: }
557:
1.40 augustss 558: usbd_status
1.65 skrll 559: usbd_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
560: uint16_t flags, uint32_t timeout, void *buf, uint32_t *size)
1.10 augustss 561: {
1.23 augustss 562: usbd_status err;
1.10 augustss 563:
1.75 mrg 564: USBHIST_FUNC();
565: USBHIST_CALLARGS(usbdebug, "start transfer %jd bytes", *size, 0, 0, 0);
1.63 skrll 566:
1.65 skrll 567: usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL);
1.61 skrll 568: err = usbd_sync_transfer_sig(xfer);
1.57 mrg 569:
570: usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
1.70 pgoyette 571: DPRINTFN(1, "transferred %jd", *size, 0, 0, 0);
1.23 augustss 572: if (err) {
1.10 augustss 573: usbd_clear_endpoint_stall(pipe);
574: }
1.70 pgoyette 575: USBHIST_LOG(usbdebug, "<- done xfer %#jx err %d", (uintptr_t)xfer,
576: err, 0, 0);
1.61 skrll 577:
1.65 skrll 578: return err;
1.10 augustss 579: }
580:
1.42 augustss 581: usbd_status
1.65 skrll 582: usbd_intr_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
583: uint16_t flags, uint32_t timeout, void *buf, uint32_t *size)
1.42 augustss 584: {
585: usbd_status err;
586:
1.75 mrg 587: USBHIST_FUNC();
588: USBHIST_CALLARGS(usbdebug, "start transfer %jd bytes", *size, 0, 0, 0);
1.63 skrll 589:
1.65 skrll 590: usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL);
1.61 skrll 591:
1.57 mrg 592: err = usbd_sync_transfer_sig(xfer);
1.61 skrll 593:
1.57 mrg 594: usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
1.61 skrll 595:
1.70 pgoyette 596: DPRINTFN(1, "transferred %jd", *size, 0, 0, 0);
1.42 augustss 597: if (err) {
598: usbd_clear_endpoint_stall(pipe);
599: }
1.70 pgoyette 600: USBHIST_LOG(usbdebug, "<- done xfer %#jx err %jd", (uintptr_t)xfer,
601: err, 0, 0);
1.63 skrll 602:
1.65 skrll 603: return err;
1.42 augustss 604: }
605:
1.14 augustss 606: void
1.56 mrg 607: usb_detach_waitold(device_t dv)
1.14 augustss 608: {
1.75 mrg 609: USBHIST_FUNC();
610: USBHIST_CALLARGS(usbdebug, "waiting for dv %#jx",
611: (uintptr_t)dv, 0, 0, 0);
1.65 skrll 612:
1.57 mrg 613: if (tsleep(dv, PZERO, "usbdet", hz * 60)) /* XXXSMP ok */
1.71 msaitoh 614: aprint_error_dev(dv, "usb_detach_waitold: didn't detach\n");
1.65 skrll 615: DPRINTFN(1, "done", 0, 0, 0, 0);
1.40 augustss 616: }
1.14 augustss 617:
618: void
1.56 mrg 619: usb_detach_wakeupold(device_t dv)
1.14 augustss 620: {
1.75 mrg 621: USBHIST_FUNC();
622: USBHIST_CALLARGS(usbdebug, "for dv %#jx", (uintptr_t)dv, 0, 0, 0);
1.65 skrll 623:
1.57 mrg 624: wakeup(dv); /* XXXSMP ok */
1.40 augustss 625: }
1.38 augustss 626:
1.48 drochner 627: const usb_cdc_descriptor_t *
1.65 skrll 628: usb_find_desc(struct usbd_device *dev, int type, int subtype)
1.38 augustss 629: {
1.41 augustss 630: usbd_desc_iter_t iter;
1.48 drochner 631: const usb_cdc_descriptor_t *desc;
1.41 augustss 632:
633: usb_desc_iter_init(dev, &iter);
634: for (;;) {
1.48 drochner 635: desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter);
1.41 augustss 636: if (!desc || (desc->bDescriptorType == type &&
1.48 drochner 637: (subtype == USBD_CDCSUBTYPE_ANY ||
1.41 augustss 638: subtype == desc->bDescriptorSubtype)))
639: break;
1.38 augustss 640: }
1.41 augustss 641: return desc;
1.38 augustss 642: }
1.43 itohy 643:
644: /* same as usb_find_desc(), but searches only in the specified interface. */
1.48 drochner 645: const usb_cdc_descriptor_t *
1.65 skrll 646: usb_find_desc_if(struct usbd_device *dev, int type, int subtype,
1.43 itohy 647: usb_interface_descriptor_t *id)
648: {
649: usbd_desc_iter_t iter;
1.48 drochner 650: const usb_cdc_descriptor_t *desc;
1.43 itohy 651:
1.54 christos 652: if (id == NULL)
653: return usb_find_desc(dev, type, subtype);
654:
1.43 itohy 655: usb_desc_iter_init(dev, &iter);
656:
657: iter.cur = (void *)id; /* start from the interface desc */
658: usb_desc_iter_next(&iter); /* and skip it */
659:
1.48 drochner 660: while ((desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter))
661: != NULL) {
1.43 itohy 662: if (desc->bDescriptorType == UDESC_INTERFACE) {
663: /* we ran into the next interface --- not found */
664: return NULL;
665: }
666: if (desc->bDescriptorType == type &&
1.48 drochner 667: (subtype == USBD_CDCSUBTYPE_ANY ||
1.43 itohy 668: subtype == desc->bDescriptorSubtype))
669: break;
670: }
671: return desc;
672: }
CVSweb <webmaster@jp.NetBSD.org>