File:
[DragonFly] /
src /
sys /
bus /
usb /
usbdi_util.c
Revision
1.5:
download - view:
text,
annotated -
select for diffs
Tue Dec 30 01:01:44 2003 UTC (9 years, 4 months ago) by
dillon
Branches:
MAIN
CVS tags:
HEAD
Bring in the entire FreeBSD-5 USB infrastructure. As of this commit my
USB camera, Hard Drive, Mouse, and Sony memory key all work and I can even
unplug and replug them in without crashing the port.
Not all drivers and subsystems compile as of this commit, but the ones that
do not are very close.
1: /*
2: * $NetBSD: usbdi_util.c,v 1.24 1999/11/17 23:00:50 augustss Exp $
3: * $NetBSD: usbdi_util.c,v 1.36 2001/11/13 06:24:57 lukem Exp $
4: * $FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.31 2003/08/24 17:55:55 obrien Exp $
5: * $DragonFly: src/sys/bus/usb/usbdi_util.c,v 1.5 2003/12/30 01:01:44 dillon Exp $
6: */
7:
8: /*
9: * Copyright (c) 1998 The NetBSD Foundation, Inc.
10: * All rights reserved.
11: *
12: * This code is derived from software contributed to The NetBSD Foundation
13: * by Lennart Augustsson (lennart@augustsson.net) at
14: * Carlstedt Research & Technology.
15: *
16: * Redistribution and use in source and binary forms, with or without
17: * modification, are permitted provided that the following conditions
18: * are met:
19: * 1. Redistributions of source code must retain the above copyright
20: * notice, this list of conditions and the following disclaimer.
21: * 2. Redistributions in binary form must reproduce the above copyright
22: * notice, this list of conditions and the following disclaimer in the
23: * documentation and/or other materials provided with the distribution.
24: * 3. All advertising materials mentioning features or use of this software
25: * must display the following acknowledgement:
26: * This product includes software developed by the NetBSD
27: * Foundation, Inc. and its contributors.
28: * 4. Neither the name of The NetBSD Foundation nor the names of its
29: * contributors may be used to endorse or promote products derived
30: * from this software without specific prior written permission.
31: *
32: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
33: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
34: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
35: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
36: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42: * POSSIBILITY OF SUCH DAMAGE.
43: */
44:
45: #include <sys/param.h>
46: #include <sys/systm.h>
47: #include <sys/kernel.h>
48: #include <sys/malloc.h>
49: #if defined(__NetBSD__) || defined(__OpenBSD__)
50: #include <sys/proc.h>
51: #include <sys/device.h>
52: #elif defined(__FreeBSD__)
53: #include <sys/bus.h>
54: #endif
55:
56: #include "usb.h"
57: #include "usbhid.h"
58:
59: #include "usbdi.h"
60: #include "usbdi_util.h"
61:
62: #ifdef USB_DEBUG
63: #define DPRINTF(x) if (usbdebug) logprintf x
64: #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
65: extern int usbdebug;
66: #else
67: #define DPRINTF(x)
68: #define DPRINTFN(n,x)
69: #endif
70:
71: usbd_status
72: usbd_get_desc(usbd_device_handle dev, int type, int index, int len, void *desc)
73: {
74: usb_device_request_t req;
75:
76: DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n",
77: type, index, len));
78:
79: req.bmRequestType = UT_READ_DEVICE;
80: req.bRequest = UR_GET_DESCRIPTOR;
81: USETW2(req.wValue, type, index);
82: USETW(req.wIndex, 0);
83: USETW(req.wLength, len);
84: return (usbd_do_request(dev, &req, desc));
85: }
86:
87: usbd_status
88: usbd_get_config_desc(usbd_device_handle dev, int confidx,
89: usb_config_descriptor_t *d)
90: {
91: usbd_status err;
92:
93: DPRINTFN(3,("usbd_get_config_desc: confidx=%d\n", confidx));
94: err = usbd_get_desc(dev, UDESC_CONFIG, confidx,
95: USB_CONFIG_DESCRIPTOR_SIZE, d);
96: if (err)
97: return (err);
98: if (d->bDescriptorType != UDESC_CONFIG) {
99: DPRINTFN(-1,("usbd_get_config_desc: confidx=%d, bad desc "
100: "len=%d type=%d\n",
101: confidx, d->bLength, d->bDescriptorType));
102: return (USBD_INVAL);
103: }
104: return (USBD_NORMAL_COMPLETION);
105: }
106:
107: usbd_status
108: usbd_get_config_desc_full(usbd_device_handle dev, int conf, void *d, int size)
109: {
110: DPRINTFN(3,("usbd_get_config_desc_full: conf=%d\n", conf));
111: return (usbd_get_desc(dev, UDESC_CONFIG, conf, size, d));
112: }
113:
114: usbd_status
115: usbd_get_device_desc(usbd_device_handle dev, usb_device_descriptor_t *d)
116: {
117: DPRINTFN(3,("usbd_get_device_desc:\n"));
118: return (usbd_get_desc(dev, UDESC_DEVICE,
119: 0, USB_DEVICE_DESCRIPTOR_SIZE, d));
120: }
121:
122: usbd_status
123: usbd_get_device_status(usbd_device_handle dev, usb_status_t *st)
124: {
125: usb_device_request_t req;
126:
127: req.bmRequestType = UT_READ_DEVICE;
128: req.bRequest = UR_GET_STATUS;
129: USETW(req.wValue, 0);
130: USETW(req.wIndex, 0);
131: USETW(req.wLength, sizeof(usb_status_t));
132: return (usbd_do_request(dev, &req, st));
133: }
134:
135: usbd_status
136: usbd_get_hub_status(usbd_device_handle dev, usb_hub_status_t *st)
137: {
138: usb_device_request_t req;
139:
140: req.bmRequestType = UT_READ_CLASS_DEVICE;
141: req.bRequest = UR_GET_STATUS;
142: USETW(req.wValue, 0);
143: USETW(req.wIndex, 0);
144: USETW(req.wLength, sizeof(usb_hub_status_t));
145: return (usbd_do_request(dev, &req, st));
146: }
147:
148: usbd_status
149: usbd_set_address(usbd_device_handle dev, int addr)
150: {
151: usb_device_request_t req;
152:
153: req.bmRequestType = UT_WRITE_DEVICE;
154: req.bRequest = UR_SET_ADDRESS;
155: USETW(req.wValue, addr);
156: USETW(req.wIndex, 0);
157: USETW(req.wLength, 0);
158: return usbd_do_request(dev, &req, 0);
159: }
160:
161: usbd_status
162: usbd_get_port_status(usbd_device_handle dev, int port, usb_port_status_t *ps)
163: {
164: usb_device_request_t req;
165:
166: req.bmRequestType = UT_READ_CLASS_OTHER;
167: req.bRequest = UR_GET_STATUS;
168: USETW(req.wValue, 0);
169: USETW(req.wIndex, port);
170: USETW(req.wLength, sizeof *ps);
171: return (usbd_do_request(dev, &req, ps));
172: }
173:
174: usbd_status
175: usbd_clear_hub_feature(usbd_device_handle dev, int sel)
176: {
177: usb_device_request_t req;
178:
179: req.bmRequestType = UT_WRITE_CLASS_DEVICE;
180: req.bRequest = UR_CLEAR_FEATURE;
181: USETW(req.wValue, sel);
182: USETW(req.wIndex, 0);
183: USETW(req.wLength, 0);
184: return (usbd_do_request(dev, &req, 0));
185: }
186:
187: usbd_status
188: usbd_set_hub_feature(usbd_device_handle dev, int sel)
189: {
190: usb_device_request_t req;
191:
192: req.bmRequestType = UT_WRITE_CLASS_DEVICE;
193: req.bRequest = UR_SET_FEATURE;
194: USETW(req.wValue, sel);
195: USETW(req.wIndex, 0);
196: USETW(req.wLength, 0);
197: return (usbd_do_request(dev, &req, 0));
198: }
199:
200: usbd_status
201: usbd_clear_port_feature(usbd_device_handle dev, int port, int sel)
202: {
203: usb_device_request_t req;
204:
205: req.bmRequestType = UT_WRITE_CLASS_OTHER;
206: req.bRequest = UR_CLEAR_FEATURE;
207: USETW(req.wValue, sel);
208: USETW(req.wIndex, port);
209: USETW(req.wLength, 0);
210: return (usbd_do_request(dev, &req, 0));
211: }
212:
213: usbd_status
214: usbd_set_port_feature(usbd_device_handle dev, int port, int sel)
215: {
216: usb_device_request_t req;
217:
218: req.bmRequestType = UT_WRITE_CLASS_OTHER;
219: req.bRequest = UR_SET_FEATURE;
220: USETW(req.wValue, sel);
221: USETW(req.wIndex, port);
222: USETW(req.wLength, 0);
223: return (usbd_do_request(dev, &req, 0));
224: }
225:
226:
227: usbd_status
228: usbd_set_protocol(usbd_interface_handle iface, int report)
229: {
230: usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
231: usbd_device_handle dev;
232: usb_device_request_t req;
233:
234: DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n",
235: iface, report, id->bInterfaceNumber));
236: if (id == NULL)
237: return (USBD_IOERROR);
238: usbd_interface2device_handle(iface, &dev);
239: req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
240: req.bRequest = UR_SET_PROTOCOL;
241: USETW(req.wValue, report);
242: USETW(req.wIndex, id->bInterfaceNumber);
243: USETW(req.wLength, 0);
244: return (usbd_do_request(dev, &req, 0));
245: }
246:
247: usbd_status
248: usbd_set_report(usbd_interface_handle iface, int type, int id, void *data,
249: int len)
250: {
251: usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
252: usbd_device_handle dev;
253: usb_device_request_t req;
254:
255: DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
256: if (ifd == NULL)
257: return (USBD_IOERROR);
258: usbd_interface2device_handle(iface, &dev);
259: req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
260: req.bRequest = UR_SET_REPORT;
261: USETW2(req.wValue, type, id);
262: USETW(req.wIndex, ifd->bInterfaceNumber);
263: USETW(req.wLength, len);
264: return (usbd_do_request(dev, &req, data));
265: }
266:
267: usbd_status
268: usbd_set_report_async(usbd_interface_handle iface, int type, int id, void *data,
269: int len)
270: {
271: usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
272: usbd_device_handle dev;
273: usb_device_request_t req;
274:
275: DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len));
276: if (ifd == NULL)
277: return (USBD_IOERROR);
278: usbd_interface2device_handle(iface, &dev);
279: req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
280: req.bRequest = UR_SET_REPORT;
281: USETW2(req.wValue, type, id);
282: USETW(req.wIndex, ifd->bInterfaceNumber);
283: USETW(req.wLength, len);
284: return (usbd_do_request_async(dev, &req, data));
285: }
286:
287: usbd_status
288: usbd_get_report(usbd_interface_handle iface, int type, int id, void *data,
289: int len)
290: {
291: usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
292: usbd_device_handle dev;
293: usb_device_request_t req;
294:
295: DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
296: if (id == 0)
297: return (USBD_IOERROR);
298: usbd_interface2device_handle(iface, &dev);
299: req.bmRequestType = UT_READ_CLASS_INTERFACE;
300: req.bRequest = UR_GET_REPORT;
301: USETW2(req.wValue, type, id);
302: USETW(req.wIndex, ifd->bInterfaceNumber);
303: USETW(req.wLength, len);
304: return (usbd_do_request(dev, &req, data));
305: }
306:
307: usbd_status
308: usbd_set_idle(usbd_interface_handle iface, int duration, int id)
309: {
310: usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
311: usbd_device_handle dev;
312: usb_device_request_t req;
313:
314: DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id));
315: if (ifd == NULL)
316: return (USBD_IOERROR);
317: usbd_interface2device_handle(iface, &dev);
318: req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
319: req.bRequest = UR_SET_IDLE;
320: USETW2(req.wValue, duration, id);
321: USETW(req.wIndex, ifd->bInterfaceNumber);
322: USETW(req.wLength, 0);
323: return (usbd_do_request(dev, &req, 0));
324: }
325:
326: usbd_status
327: usbd_get_report_descriptor(usbd_device_handle dev, int ifcno,
328: int size, void *d)
329: {
330: usb_device_request_t req;
331:
332: req.bmRequestType = UT_READ_INTERFACE;
333: req.bRequest = UR_GET_DESCRIPTOR;
334: USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */
335: USETW(req.wIndex, ifcno);
336: USETW(req.wLength, size);
337: return (usbd_do_request(dev, &req, d));
338: }
339:
340: usb_hid_descriptor_t *
341: usbd_get_hid_descriptor(usbd_interface_handle ifc)
342: {
343: usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc);
344: usbd_device_handle dev;
345: usb_config_descriptor_t *cdesc;
346: usb_hid_descriptor_t *hd;
347: char *p, *end;
348:
349: if (idesc == NULL)
350: return (0);
351: usbd_interface2device_handle(ifc, &dev);
352: cdesc = usbd_get_config_descriptor(dev);
353:
354: p = (char *)idesc + idesc->bLength;
355: end = (char *)cdesc + UGETW(cdesc->wTotalLength);
356:
357: for (; p < end; p += hd->bLength) {
358: hd = (usb_hid_descriptor_t *)p;
359: if (p + hd->bLength <= end && hd->bDescriptorType == UDESC_HID)
360: return (hd);
361: if (hd->bDescriptorType == UDESC_INTERFACE)
362: break;
363: }
364: return (0);
365: }
366:
367: usbd_status
368: usbd_read_report_desc(usbd_interface_handle ifc, void **descp, int *sizep,
369: usb_malloc_type mem)
370: {
371: usb_interface_descriptor_t *id;
372: usb_hid_descriptor_t *hid;
373: usbd_device_handle dev;
374: usbd_status err;
375:
376: usbd_interface2device_handle(ifc, &dev);
377: id = usbd_get_interface_descriptor(ifc);
378: if (id == NULL)
379: return (USBD_INVAL);
380: hid = usbd_get_hid_descriptor(ifc);
381: if (hid == NULL)
382: return (USBD_IOERROR);
383: *sizep = UGETW(hid->descrs[0].wDescriptorLength);
384: *descp = malloc(*sizep, mem, M_NOWAIT);
385: if (*descp == NULL)
386: return (USBD_NOMEM);
387: err = usbd_get_report_descriptor(dev, id->bInterfaceNumber,
388: *sizep, *descp);
389: if (err) {
390: free(*descp, mem);
391: *descp = NULL;
392: return (err);
393: }
394: return (USBD_NORMAL_COMPLETION);
395: }
396:
397: usbd_status
398: usbd_get_config(usbd_device_handle dev, u_int8_t *conf)
399: {
400: usb_device_request_t req;
401:
402: req.bmRequestType = UT_READ_DEVICE;
403: req.bRequest = UR_GET_CONFIG;
404: USETW(req.wValue, 0);
405: USETW(req.wIndex, 0);
406: USETW(req.wLength, 1);
407: return (usbd_do_request(dev, &req, conf));
408: }
409:
410: Static void usbd_bulk_transfer_cb(usbd_xfer_handle xfer,
411: usbd_private_handle priv, usbd_status status);
412: Static void
413: usbd_bulk_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
414: usbd_status status)
415: {
416: wakeup(xfer);
417: }
418:
419: usbd_status
420: usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
421: u_int16_t flags, u_int32_t timeout, void *buf,
422: u_int32_t *size, char *lbl)
423: {
424: usbd_status err;
425: int s, error;
426:
427: usbd_setup_xfer(xfer, pipe, 0, buf, *size,
428: flags, timeout, usbd_bulk_transfer_cb);
429: DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size));
430: s = splusb(); /* don't want callback until tsleep() */
431: err = usbd_transfer(xfer);
432: if (err != USBD_IN_PROGRESS) {
433: splx(s);
434: return (err);
435: }
436: error = tsleep((caddr_t)xfer, PCATCH, lbl, 0);
437: splx(s);
438: if (error) {
439: DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error));
440: usbd_abort_pipe(pipe);
441: return (USBD_INTERRUPTED);
442: }
443: usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
444: DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size));
445: if (err) {
446: DPRINTF(("usbd_bulk_transfer: error=%d\n", err));
447: usbd_clear_endpoint_stall(pipe);
448: }
449: return (err);
450: }
451:
452: Static void usbd_intr_transfer_cb(usbd_xfer_handle xfer,
453: usbd_private_handle priv, usbd_status status);
454: Static void
455: usbd_intr_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
456: usbd_status status)
457: {
458: wakeup(xfer);
459: }
460:
461: usbd_status
462: usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
463: u_int16_t flags, u_int32_t timeout, void *buf,
464: u_int32_t *size, char *lbl)
465: {
466: usbd_status err;
467: int s, error;
468:
469: usbd_setup_xfer(xfer, pipe, 0, buf, *size,
470: flags, timeout, usbd_intr_transfer_cb);
471: DPRINTFN(1, ("usbd_intr_transfer: start transfer %d bytes\n", *size));
472: s = splusb(); /* don't want callback until tsleep() */
473: err = usbd_transfer(xfer);
474: if (err != USBD_IN_PROGRESS) {
475: splx(s);
476: return (err);
477: }
478: error = tsleep(xfer, PCATCH, lbl, 0);
479: splx(s);
480: if (error) {
481: DPRINTF(("usbd_intr_transfer: tsleep=%d\n", error));
482: usbd_abort_pipe(pipe);
483: return (USBD_INTERRUPTED);
484: }
485: usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
486: DPRINTFN(1,("usbd_intr_transfer: transferred %d\n", *size));
487: if (err) {
488: DPRINTF(("usbd_intr_transfer: error=%d\n", err));
489: usbd_clear_endpoint_stall(pipe);
490: }
491: return (err);
492: }
493:
494: void
495: usb_detach_wait(device_ptr_t dv)
496: {
497: DPRINTF(("usb_detach_wait: waiting for %s\n", USBDEVPTRNAME(dv)));
498: if (tsleep(dv, 0, "usbdet", hz * 60))
499: printf("usb_detach_wait: %s didn't detach\n",
500: USBDEVPTRNAME(dv));
501: DPRINTF(("usb_detach_wait: %s done\n", USBDEVPTRNAME(dv)));
502: }
503:
504: void
505: usb_detach_wakeup(device_ptr_t dv)
506: {
507: DPRINTF(("usb_detach_wakeup: for %s\n", USBDEVPTRNAME(dv)));
508: wakeup(dv);
509: }