usb_subr.c revision 1.20 1 /* $NetBSD: usb_subr.c,v 1.20 1998/12/28 21:05:26 augustss Exp $ */
2
3 /*
4 * Copyright (c) 1998 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 (augustss (at) carlstedt.se) at
9 * Carlstedt Research & Technology.
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 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #if defined(__NetBSD__)
45 #include <sys/device.h>
46 #elif defined(__FreeBSD__)
47 #include <sys/module.h>
48 #include <sys/bus.h>
49 #endif
50 #include <sys/proc.h>
51 #include <sys/select.h>
52
53 #include <dev/usb/usb.h>
54
55 #include <dev/usb/usbdi.h>
56 #include <dev/usb/usbdi_util.h>
57 #include <dev/usb/usbdivar.h>
58 #include <dev/usb/usbdevs.h>
59 #include <dev/usb/usb_quirks.h>
60
61 #ifdef USB_DEBUG
62 #define DPRINTF(x) if (usbdebug) printf x
63 #define DPRINTFN(n,x) if (usbdebug>(n)) printf x
64 extern int usbdebug;
65 #else
66 #define DPRINTF(x)
67 #define DPRINTFN(n,x)
68 #endif
69
70 static usbd_status usbd_set_config __P((usbd_device_handle, int));
71 char *usbd_get_string __P((usbd_device_handle, int, char *));
72 int usbd_getnewaddr __P((usbd_bus_handle bus));
73 int usbd_print __P((void *aux, const char *pnp));
74 #if defined(__NetBSD__)
75 int usbd_submatch __P((struct device *, struct cfdata *cf, void *));
76 #endif
77 usb_interface_descriptor_t *usbd_find_idesc __P((usb_config_descriptor_t *cd,
78 int ifaceidx, int altidx));
79 void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno));
80 void usbd_kill_pipe __P((usbd_pipe_handle));
81 usbd_status usbd_probe_and_attach
82 __P((bdevice *parent, usbd_device_handle dev, int port, int addr));
83
84 #ifdef USBVERBOSE
85 typedef u_int16_t usb_vendor_id_t;
86 typedef u_int16_t usb_product_id_t;
87
88 /*
89 * Descriptions of of known vendors and devices ("products").
90 */
91 struct usb_knowndev {
92 usb_vendor_id_t vendor;
93 usb_product_id_t product;
94 int flags;
95 char *vendorname, *productname;
96 };
97 #define USB_KNOWNDEV_NOPROD 0x01 /* match on vendor only */
98
99 #include <dev/usb/usbdevs_data.h>
100 #endif /* USBVERBOSE */
101
102 #ifdef USB_DEBUG
103 char *usbd_error_strs[] = {
104 "NORMAL_COMPLETION",
105 "IN_PROGRESS",
106 "PENDING_REQUESTS",
107 "NOT_STARTED",
108 "INVAL",
109 "IS_IDLE",
110 "NOMEM",
111 "CANCELLED",
112 "BAD_ADDRESS",
113 "IN_USE",
114 "INTERFACE_NOT_ACTIVE",
115 "NO_ADDR",
116 "SET_ADDR_FAILED",
117 "NO_POWER",
118 "TOO_DEEP",
119 "IOERROR",
120 "NOT_CONFIGURED",
121 "TIMEOUT",
122 "SHORT_XFER",
123 "STALLED",
124 "XXX",
125 };
126 #endif
127
128 usbd_status
129 usbd_get_string_desc(dev, sindex, langid, sdesc)
130 usbd_device_handle dev;
131 int sindex;
132 int langid;
133 usb_string_descriptor_t *sdesc;
134 {
135 usb_device_request_t req;
136 usbd_status r;
137
138 req.bmRequestType = UT_READ_DEVICE;
139 req.bRequest = UR_GET_DESCRIPTOR;
140 USETW2(req.wValue, UDESC_STRING, sindex);
141 USETW(req.wIndex, langid);
142 USETW(req.wLength, 1); /* only size byte first */
143 r = usbd_do_request(dev, &req, sdesc);
144 if (r != USBD_NORMAL_COMPLETION)
145 return (r);
146 USETW(req.wLength, sdesc->bLength); /* the whole string */
147 return (usbd_do_request(dev, &req, sdesc));
148 }
149
150 char *
151 usbd_get_string(dev, si, buf)
152 usbd_device_handle dev;
153 int si;
154 char *buf;
155 {
156 int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE;
157 usb_string_descriptor_t us;
158 char *s;
159 int i, n;
160 u_int16_t c;
161 usbd_status r;
162
163 if (si == 0)
164 return (0);
165 if (dev->quirks->uq_flags & UQ_NO_STRINGS)
166 return (0);
167 r = usbd_get_string_desc(dev, si, 0, &us);
168 if (r != USBD_NORMAL_COMPLETION)
169 return (0);
170 s = buf;
171 n = us.bLength / 2 - 1;
172 for (i = 0; i < n; i++) {
173 c = UGETW(us.bString[i]);
174 /* Convert from Unicode, handle buggy strings. */
175 if ((c & 0xff00) == 0)
176 *s++ = c;
177 else if ((c & 0x00ff) == 0 && swap)
178 *s++ = c >> 8;
179 else
180 *s++ = '?';
181 }
182 *s++ = 0;
183 return buf;
184 }
185
186 void
187 usbd_devinfo_vp(dev, v, p)
188 usbd_device_handle dev;
189 char *v, *p;
190 {
191 usb_device_descriptor_t *udd = &dev->ddesc;
192 char *vendor = 0, *product = 0;
193 #ifdef USBVERBOSE
194 struct usb_knowndev *kdp;
195 #endif
196
197 vendor = usbd_get_string(dev, udd->iManufacturer, v);
198 product = usbd_get_string(dev, udd->iProduct, p);
199 #ifdef USBVERBOSE
200 if (!vendor) {
201 for(kdp = usb_knowndevs;
202 kdp->vendorname != NULL;
203 kdp++) {
204 if (kdp->vendor == UGETW(udd->idVendor) &&
205 (kdp->product == UGETW(udd->idProduct) ||
206 (kdp->flags & USB_KNOWNDEV_NOPROD) != 0))
207 break;
208 }
209 if (kdp->vendorname == NULL)
210 vendor = product = NULL;
211 else {
212 vendor = kdp->vendorname;
213 product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ?
214 kdp->productname : NULL;
215 }
216 }
217 #endif
218 if (vendor)
219 strcpy(v, vendor);
220 else
221 sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
222 if (product)
223 strcpy(p, product);
224 else
225 sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
226 }
227
228 int
229 usbd_printBCD(cp, bcd)
230 char *cp;
231 int bcd;
232 {
233 return (sprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff));
234 }
235
236 void
237 usbd_devinfo(dev, showclass, cp)
238 usbd_device_handle dev;
239 int showclass;
240 char *cp;
241 {
242 usb_device_descriptor_t *udd = &dev->ddesc;
243 char vendor[USB_MAX_STRING_LEN];
244 char product[USB_MAX_STRING_LEN];
245 int bcdDevice, bcdUSB;
246
247 usbd_devinfo_vp(dev, vendor, product);
248 cp += sprintf(cp, "%s %s", vendor, product);
249 if (showclass)
250 cp += sprintf(cp, ", class %d/%d",
251 udd->bDeviceClass, udd->bDeviceSubClass);
252 bcdUSB = UGETW(udd->bcdUSB);
253 bcdDevice = UGETW(udd->bcdDevice);
254 cp += sprintf(cp, ", rev ");
255 cp += usbd_printBCD(cp, bcdUSB);
256 *cp++ = '/';
257 cp += usbd_printBCD(cp, bcdDevice);
258 cp += sprintf(cp, ", addr %d", dev->address);
259 *cp = 0;
260 }
261
262 /* Delay for a certain number of ms */
263 void
264 usbd_delay_ms(bus, ms)
265 usbd_bus_handle bus;
266 int ms;
267 {
268 /* Wait at least two clock ticks so we know the time has passed. */
269 if (bus->use_polling)
270 delay((ms+1) * 1000);
271 else
272 tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
273 }
274
275 usbd_status
276 usbd_reset_port(dev, port, ps)
277 usbd_device_handle dev;
278 int port;
279 usb_port_status_t *ps;
280 {
281 usb_device_request_t req;
282 usbd_status r;
283 int n;
284
285 req.bmRequestType = UT_WRITE_CLASS_OTHER;
286 req.bRequest = UR_SET_FEATURE;
287 USETW(req.wValue, UHF_PORT_RESET);
288 USETW(req.wIndex, port);
289 USETW(req.wLength, 0);
290 r = usbd_do_request(dev, &req, 0);
291 DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%d(%s)\n",
292 port, r, usbd_error_strs[r]));
293 if (r != USBD_NORMAL_COMPLETION)
294 return (r);
295 n = 10;
296 do {
297 /* Wait for device to recover from reset. */
298 usbd_delay_ms(dev->bus, USB_PORT_RESET_DELAY);
299 r = usbd_get_port_status(dev, port, ps);
300 if (r != USBD_NORMAL_COMPLETION) {
301 DPRINTF(("usbd_reset_port: get status failed %d\n",r));
302 return (r);
303 }
304 } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
305 if (n == 0) {
306 printf("usbd_reset_port: timeout\n");
307 return (USBD_IOERROR);
308 }
309 r = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
310 #ifdef USB_DEBUG
311 if (r != USBD_NORMAL_COMPLETION)
312 DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r));
313 #endif
314
315 /* Wait for the device to recover from reset. */
316 usbd_delay_ms(dev->bus, USB_PORT_RESET_RECOVERY);
317 return (r);
318 }
319
320 usb_interface_descriptor_t *
321 usbd_find_idesc(cd, ifaceidx, altidx)
322 usb_config_descriptor_t *cd;
323 int ifaceidx;
324 int altidx;
325 {
326 char *p = (char *)cd;
327 char *end = p + UGETW(cd->wTotalLength);
328 usb_interface_descriptor_t *d;
329 int curidx, lastidx, curaidx = 0;
330
331 for (curidx = lastidx = -1; p < end; ) {
332 d = (usb_interface_descriptor_t *)p;
333 DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
334 "type=%d\n",
335 ifaceidx, curidx, altidx, curaidx,
336 d->bLength, d->bDescriptorType));
337 if (d->bLength == 0) /* bad descriptor */
338 break;
339 p += d->bLength;
340 if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
341 if (d->bInterfaceNumber != lastidx) {
342 lastidx = d->bInterfaceNumber;
343 curidx++;
344 curaidx = 0;
345 } else
346 curaidx++;
347 if (ifaceidx == curidx && altidx == curaidx)
348 return (d);
349 }
350 }
351 return (0);
352 }
353
354 usb_endpoint_descriptor_t *
355 usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
356 usb_config_descriptor_t *cd;
357 int ifaceidx;
358 int altidx;
359 int endptidx;
360 {
361 char *p = (char *)cd;
362 char *end = p + UGETW(cd->wTotalLength);
363 usb_interface_descriptor_t *d;
364 usb_endpoint_descriptor_t *e;
365 int curidx;
366
367 d = usbd_find_idesc(cd, ifaceidx, altidx);
368 if (!d)
369 return (0);
370 if (endptidx >= d->bNumEndpoints) /* quick exit */
371 return (0);
372
373 curidx = -1;
374 for (p = (char *)d + d->bLength; p < end; ) {
375 e = (usb_endpoint_descriptor_t *)p;
376 if (e->bLength == 0) /* bad descriptor */
377 break;
378 p += e->bLength;
379 if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
380 return (0);
381 if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
382 curidx++;
383 if (curidx == endptidx)
384 return (e);
385 }
386 }
387 return (0);
388 }
389
390 usbd_status
391 usbd_fill_iface_data(dev, ifaceidx, altidx)
392 usbd_device_handle dev;
393 int ifaceidx;
394 int altidx;
395 {
396 usbd_interface_handle ifc = &dev->ifaces[ifaceidx];
397 char *p, *end;
398 int endpt, nendpt;
399 usbd_status r;
400
401 DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
402 ifaceidx, altidx));
403 ifc->device = dev;
404 ifc->idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
405 if (ifc->idesc == 0)
406 return (USBD_INVAL);
407 ifc->index = ifaceidx;
408 ifc->altindex = altidx;
409 nendpt = ifc->idesc->bNumEndpoints;
410 DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt));
411 if (nendpt != 0) {
412 ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
413 M_USB, M_NOWAIT);
414 if (ifc->endpoints == 0)
415 return (USBD_NOMEM);
416 } else
417 ifc->endpoints = 0;
418 ifc->priv = 0;
419 p = (char *)ifc->idesc + ifc->idesc->bLength;
420 end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
421 #define ed ((usb_endpoint_descriptor_t *)p)
422 for (endpt = 0; endpt < nendpt; endpt++) {
423 DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt));
424 for (; p < end; p += ed->bLength) {
425 ed = (usb_endpoint_descriptor_t *)p;
426 DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p "
427 "len=%d type=%d\n",
428 p, end, ed->bLength, ed->bDescriptorType));
429 if (p + ed->bLength <= end &&
430 ed->bDescriptorType == UDESC_ENDPOINT)
431 break;
432 if (ed->bDescriptorType == UDESC_INTERFACE ||
433 ed->bLength == 0) {
434 r = USBD_INVAL;
435 goto bad;
436 }
437 }
438 ifc->endpoints[endpt].edesc = ed;
439 ifc->endpoints[endpt].state = USBD_ENDPOINT_ACTIVE;
440 ifc->endpoints[endpt].refcnt = 0;
441 ifc->endpoints[endpt].toggle = 0;
442 }
443 #undef ed
444 LIST_INIT(&ifc->pipes);
445 ifc->state = USBD_INTERFACE_ACTIVE;
446 return (USBD_NORMAL_COMPLETION);
447 bad:
448 free(ifc->endpoints, M_USB);
449 return (r);
450 }
451
452 void
453 usbd_free_iface_data(dev, ifcno)
454 usbd_device_handle dev;
455 int ifcno;
456 {
457 usbd_interface_handle ifc = &dev->ifaces[ifcno];
458 if (ifc->endpoints)
459 free(ifc->endpoints, M_USB);
460 }
461
462 static usbd_status
463 usbd_set_config(dev, conf)
464 usbd_device_handle dev;
465 int conf;
466 {
467 usb_device_request_t req;
468
469 req.bmRequestType = UT_WRITE_DEVICE;
470 req.bRequest = UR_SET_CONFIG;
471 USETW(req.wValue, conf);
472 USETW(req.wIndex, 0);
473 USETW(req.wLength, 0);
474 return (usbd_do_request(dev, &req, 0));
475 }
476
477 usbd_status
478 usbd_set_config_no(dev, no, msg)
479 usbd_device_handle dev;
480 int no;
481 int msg;
482 {
483 int index;
484 usb_config_descriptor_t cd;
485 usbd_status r;
486
487 DPRINTFN(5,("usbd_set_config_no: %d\n", no));
488 /* Figure out what config index to use. */
489 for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
490 r = usbd_get_config_desc(dev, index, &cd);
491 if (r != USBD_NORMAL_COMPLETION)
492 return (r);
493 if (cd.bConfigurationValue == no)
494 return (usbd_set_config_index(dev, index, msg));
495 }
496 return (USBD_INVAL);
497 }
498
499 usbd_status
500 usbd_set_config_index(dev, index, msg)
501 usbd_device_handle dev;
502 int index;
503 int msg;
504 {
505 usb_status_t ds;
506 usb_hub_status_t hs;
507 usb_config_descriptor_t cd, *cdp;
508 usbd_status r;
509 int ifcidx, nifc, len, selfpowered, power;
510
511 DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
512
513 /* XXX check that all interfaces are idle */
514 if (dev->config != 0) {
515 DPRINTF(("usbd_set_config_index: free old config\n"));
516 /* Free all configuration data structures. */
517 nifc = dev->cdesc->bNumInterface;
518 for (ifcidx = 0; ifcidx < nifc; ifcidx++)
519 usbd_free_iface_data(dev, ifcidx);
520 free(dev->ifaces, M_USB);
521 free(dev->cdesc, M_USB);
522 dev->ifaces = 0;
523 dev->cdesc = 0;
524 dev->config = 0;
525 dev->state = USBD_DEVICE_ADDRESSED;
526 }
527
528 /* Figure out what config number to use. */
529 r = usbd_get_config_desc(dev, index, &cd);
530 if (r != USBD_NORMAL_COMPLETION)
531 return (r);
532 len = UGETW(cd.wTotalLength);
533 cdp = malloc(len, M_USB, M_NOWAIT);
534 if (cdp == 0)
535 return (USBD_NOMEM);
536 r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
537 if (r != USBD_NORMAL_COMPLETION)
538 goto bad;
539 if (cdp->bDescriptorType != UDESC_CONFIG) {
540 DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
541 cdp->bDescriptorType));
542 r = USBD_INVAL;
543 goto bad;
544 }
545 selfpowered = 0;
546 if (cdp->bmAttributes & UC_SELF_POWERED) {
547 /* May be self powered. */
548 if (cdp->bmAttributes & UC_BUS_POWERED) {
549 /* Must ask device. */
550 if (dev->quirks->uq_flags & UQ_HUB_POWER) {
551 /* Buggy hub, use hub descriptor. */
552 r = usbd_get_hub_status(dev, &hs);
553 if (r == USBD_NORMAL_COMPLETION &&
554 !(UGETW(hs.wHubStatus) & UHS_LOCAL_POWER))
555 selfpowered = 1;
556 } else {
557 r = usbd_get_device_status(dev, &ds);
558 if (r == USBD_NORMAL_COMPLETION &&
559 (UGETW(ds.wStatus) & UDS_SELF_POWERED))
560 selfpowered = 1;
561 }
562 DPRINTF(("usbd_set_config_index: status=0x%04x, "
563 "error=%d(%s)\n",
564 UGETW(ds.wStatus), r, usbd_error_strs[r]));
565 } else
566 selfpowered = 1;
567 }
568 DPRINTF(("usbd_set_config_index: (addr %d) attr=0x%02x, "
569 "selfpowered=%d, power=%d, powerquirk=%x\n",
570 dev->address, cdp->bmAttributes,
571 selfpowered, cdp->bMaxPower * 2,
572 dev->quirks->uq_flags & UQ_HUB_POWER));
573 #ifdef USB_DEBUG
574 if (!dev->powersrc) {
575 printf("usbd_set_config_index: No power source?\n");
576 return (USBD_IOERROR);
577 }
578 #endif
579 power = cdp->bMaxPower * 2;
580 if (power > dev->powersrc->power) {
581 /* XXX print nicer message. */
582 if (msg)
583 printf("%s: device addr %d (config %d) exceeds power "
584 "budget, %d mA > %d mA\n",
585 USBDEVNAME(dev->bus->bdev), dev->address,
586 cdp->bConfigurationValue,
587 power, dev->powersrc->power);
588 r = USBD_NO_POWER;
589 goto bad;
590 }
591 dev->power = power;
592 dev->self_powered = selfpowered;
593
594 DPRINTF(("usbd_set_config_index: set config %d\n",
595 cdp->bConfigurationValue));
596 r = usbd_set_config(dev, cdp->bConfigurationValue);
597 if (r != USBD_NORMAL_COMPLETION) {
598 DPRINTF(("usbd_set_config_index: setting config=%d failed, "
599 "error=%d(%s)\n",
600 cdp->bConfigurationValue, r, usbd_error_strs[r]));
601 goto bad;
602 }
603 DPRINTF(("usbd_set_config_index: setting new config %d\n",
604 cdp->bConfigurationValue));
605 nifc = cdp->bNumInterface;
606 dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
607 M_USB, M_NOWAIT);
608 if (dev->ifaces == 0) {
609 r = USBD_NOMEM;
610 goto bad;
611 }
612 DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
613 dev->cdesc = cdp;
614 dev->config = cdp->bConfigurationValue;
615 dev->state = USBD_DEVICE_CONFIGURED;
616 for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
617 r = usbd_fill_iface_data(dev, ifcidx, 0);
618 if (r != USBD_NORMAL_COMPLETION) {
619 while (--ifcidx >= 0)
620 usbd_free_iface_data(dev, ifcidx);
621 goto bad;
622 }
623 }
624
625 return (USBD_NORMAL_COMPLETION);
626
627 bad:
628 free(cdp, M_USB);
629 return (r);
630 }
631
632 /* XXX add function for alternate settings */
633
634 usbd_status
635 usbd_setup_pipe(dev, iface, ep, pipe)
636 usbd_device_handle dev;
637 usbd_interface_handle iface;
638 struct usbd_endpoint *ep;
639 usbd_pipe_handle *pipe;
640 {
641 usbd_pipe_handle p;
642 usbd_status r;
643
644 DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
645 dev, iface, ep, pipe));
646 p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
647 if (p == 0)
648 return (USBD_NOMEM);
649 p->device = dev;
650 p->iface = iface;
651 p->state = USBD_PIPE_ACTIVE;
652 p->endpoint = ep;
653 ep->refcnt++;
654 p->refcnt = 1;
655 p->intrreqh = 0;
656 p->running = 0;
657 SIMPLEQ_INIT(&p->queue);
658 r = dev->bus->open_pipe(p);
659 if (r != USBD_NORMAL_COMPLETION) {
660 DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=%d"
661 "(%s)\n",
662 ep->edesc->bEndpointAddress, r, usbd_error_strs[r]));
663 free(p, M_USB);
664 return (r);
665 }
666 *pipe = p;
667 return (USBD_NORMAL_COMPLETION);
668 }
669
670 /* Abort the device control pipe. */
671 void
672 usbd_kill_pipe(pipe)
673 usbd_pipe_handle pipe;
674 {
675 pipe->methods->close(pipe);
676 pipe->endpoint->refcnt--;
677 free(pipe, M_USB);
678 }
679
680 int
681 usbd_getnewaddr(bus)
682 usbd_bus_handle bus;
683 {
684 int addr;
685
686 for (addr = 1; addr < USB_MAX_DEVICES; addr++)
687 if (bus->devices[addr] == 0)
688 return (addr);
689 return (-1);
690 }
691
692
693 usbd_status
694 usbd_probe_and_attach(parent, dev, port, addr)
695 bdevice *parent;
696 usbd_device_handle dev;
697 int port;
698 int addr;
699 {
700 struct usb_attach_arg uaa;
701 usb_device_descriptor_t *dd = &dev->ddesc;
702 int r, found, i, confi, nifaces;
703 usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
704
705 #if defined(__FreeBSD__)
706 /* XXX isn't it bad to build &uaa into a value that has a lifetime
707 longer than this function call? */
708 bdevice bdev;
709 bdev = device_add_child(*parent, NULL, -1, &uaa);
710 if (bdev) {
711 printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
712 return (USBD_INVAL);
713 }
714 #endif
715
716 uaa.device = dev;
717 uaa.iface = 0;
718 uaa.ifaces = 0;
719 uaa.nifaces = 0;
720 uaa.usegeneric = 0;
721 uaa.port = port;
722 uaa.configno = UHUB_UNK_CONFIGURATION;
723 uaa.ifaceno = UHUB_UNK_INTERFACE;
724
725 /* First try with device specific drivers. */
726 if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
727 return (USBD_NORMAL_COMPLETION);
728
729 DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
730
731 /* Next try with interface drivers. */
732 for (confi = 0; confi < dd->bNumConfigurations; confi++) {
733 DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
734 confi));
735 r = usbd_set_config_index(dev, confi, 1);
736 if (r != USBD_NORMAL_COMPLETION) {
737 #ifdef USB_DEBUG
738 DPRINTF(("%s: port %d, set config at addr %d failed, "
739 "error=%d(%s)\n", USBDEVNAME(*parent), port,
740 addr, r, usbd_error_strs[r]));
741 #else
742 printf("%s: port %d, set config at addr %d failed\n",
743 USBDEVNAME(*parent), port, addr);
744 #endif
745 return (r);
746 }
747 nifaces = dev->cdesc->bNumInterface;
748 uaa.configno = confi;
749 for (i = 0; i < nifaces; i++)
750 ifaces[i] = &dev->ifaces[i];
751 uaa.ifaces = ifaces;
752 uaa.nifaces = nifaces;
753 for (found = i = 0; i < nifaces; i++) {
754 if (!ifaces[i])
755 continue; /* interface already claimed */
756 uaa.iface = ifaces[i];
757 uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
758 if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
759 usbd_submatch)) {
760 found++;
761 ifaces[i] = 0; /* consumed */
762 }
763 }
764 if (found != 0)
765 return (USBD_NORMAL_COMPLETION);
766 }
767 /* No interfaces were attach in any of the configurations. */
768 if (dd->bNumConfigurations > 0)
769 usbd_set_config_index(dev, 0, 0);
770
771 DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
772
773 /* Finally try the generic driver. */
774 uaa.iface = 0;
775 uaa.usegeneric = 1;
776 uaa.configno = UHUB_UNK_CONFIGURATION;
777 uaa.ifaceno = UHUB_UNK_INTERFACE;
778 if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
779 return (USBD_NORMAL_COMPLETION);
780
781 /*
782 * The generic attach failed, but leave the device as it is.
783 * We just did not find any drivers, that's all. The device is
784 * fully operational and not harming anyone.
785 */
786 DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
787 return (USBD_NORMAL_COMPLETION);
788 }
789
790
791
792 /*
793 * Called when a new device has been put in the powered state,
794 * but not yet in the addressed state.
795 * Get initial descriptor, set the address, get full descriptor,
796 * and attach a driver.
797 */
798 usbd_status
799 usbd_new_device(parent, bus, depth, lowspeed, port, up)
800 bdevice *parent;
801 usbd_bus_handle bus;
802 int depth;
803 int lowspeed;
804 int port;
805 struct usbd_port *up;
806 {
807 usbd_device_handle dev;
808 usb_device_descriptor_t *dd;
809 usbd_status r;
810 int addr;
811 int i;
812
813 DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n",
814 bus, depth, lowspeed));
815 addr = usbd_getnewaddr(bus);
816 if (addr < 0) {
817 printf("%s: No free USB addresses, new device ignored.\n",
818 USBDEVNAME(bus->bdev));
819 return (USBD_NO_ADDR);
820 }
821
822 dev = malloc(sizeof *dev, M_USB, M_NOWAIT);
823 if (dev == 0)
824 return (USBD_NOMEM);
825 memset(dev, 0, sizeof(*dev));
826
827 dev->bus = bus;
828
829 /* Set up default endpoint handle. */
830 dev->def_ep.edesc = &dev->def_ep_desc;
831 dev->def_ep.state = USBD_ENDPOINT_ACTIVE;
832
833 /* Set up default endpoint descriptor. */
834 dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
835 dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
836 dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
837 dev->def_ep_desc.bmAttributes = UE_CONTROL;
838 USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
839 dev->def_ep_desc.bInterval = 0;
840
841 dev->state = USBD_DEVICE_DEFAULT;
842 dev->quirks = &usbd_no_quirk;
843 dev->address = USB_START_ADDR;
844 dev->ddesc.bMaxPacketSize = 0;
845 dev->lowspeed = lowspeed != 0;
846 dev->depth = depth;
847 dev->powersrc = up;
848
849 /* Establish the the default pipe. */
850 r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
851 if (r != USBD_NORMAL_COMPLETION) {
852 usbd_remove_device(dev, up);
853 return (r);
854 }
855
856 up->device = dev;
857 dd = &dev->ddesc;
858 /* Try a few times in case the device is slow (i.e. outside specs.) */
859 for (i = 0; i < 5; i++) {
860 /* Get the first 8 bytes of the device descriptor. */
861 r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
862 if (r == USBD_NORMAL_COMPLETION)
863 break;
864 usbd_delay_ms(dev->bus, 200);
865 }
866 if (r != USBD_NORMAL_COMPLETION) {
867 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
868 "failed\n",
869 addr));
870 usbd_remove_device(dev, up);
871 return (r);
872 }
873
874 if (dd->bDescriptorType != UDESC_DEVICE) {
875 /* Illegal device descriptor */
876 DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
877 dd->bDescriptorType));
878 usbd_remove_device(dev, up);
879 return (USBD_INVAL);
880 }
881
882 DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
883 "subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",
884 addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
885 dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed));
886
887 USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
888
889 /* Get the full device descriptor. */
890 r = usbd_get_device_desc(dev, dd);
891 if (r != USBD_NORMAL_COMPLETION) {
892 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
893 "failed\n", addr));
894 usbd_remove_device(dev, up);
895 return (r);
896 }
897
898 /* Figure out what's wrong with this device. */
899 dev->quirks = usbd_find_quirk(dd);
900
901 /* Set the address */
902 r = usbd_set_address(dev, addr);
903 if (r != USBD_NORMAL_COMPLETION) {
904 DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
905 r = USBD_SET_ADDR_FAILED;
906 usbd_remove_device(dev, up);
907 return (r);
908 }
909 /* Allow device time to set new address */
910 usbd_delay_ms(dev->bus, USB_SET_ADDRESS_SETTLE);
911
912 dev->address = addr; /* New device address now */
913 dev->state = USBD_DEVICE_ADDRESSED;
914 bus->devices[addr] = dev;
915
916 /* Assume 100mA bus powered for now. Changed when configured. */
917 dev->power = USB_MIN_POWER;
918 dev->self_powered = 0;
919
920 DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
921 addr, dev, parent));
922
923 r = usbd_probe_and_attach(parent, dev, port, addr);
924 if (r != USBD_NORMAL_COMPLETION) {
925 usbd_remove_device(dev, up);
926 return (r);
927 }
928
929 return (USBD_NORMAL_COMPLETION);
930 }
931
932 void
933 usbd_remove_device(dev, up)
934 usbd_device_handle dev;
935 struct usbd_port *up;
936 {
937 DPRINTF(("usbd_remove_device: %p\n", dev));
938
939 #if defined(__NetBSD__)
940 /* XXX bit of a hack, only for hubs the detach is called
941 *
942 * easiest solution, register a detach method in the softc, call that
943 * one and pass the device struct to it, or the softc. Whatever.
944 */
945 /*if (dev->bdev && dev->hub)
946 uhub_detach(dev->hub->hubdata);*/
947 #elif defined(__FreeBSD__)
948 if (dev->bdev)
949 device_delete_child(device_get_parent(dev->bdev), dev->bdev);
950 #endif
951
952 if (dev->default_pipe)
953 usbd_kill_pipe(dev->default_pipe);
954 up->device = 0;
955 dev->bus->devices[dev->address] = 0;
956
957 free(dev, M_USB);
958 }
959
960 #if defined(__NetBSD__)
961 int
962 usbd_print(aux, pnp)
963 void *aux;
964 const char *pnp;
965 {
966 struct usb_attach_arg *uaa = aux;
967 char devinfo[1024];
968
969 DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
970 if (pnp) {
971 if (!uaa->usegeneric)
972 return (QUIET);
973 usbd_devinfo(uaa->device, 1, devinfo);
974 printf("%s, %s", devinfo, pnp);
975 }
976 if (uaa->port != 0)
977 printf(" port %d", uaa->port);
978 if (uaa->configno != UHUB_UNK_CONFIGURATION)
979 printf(" configuration %d", uaa->configno);
980 if (uaa->ifaceno != UHUB_UNK_INTERFACE)
981 printf(" interface %d", uaa->ifaceno);
982 return (UNCONF);
983 }
984
985 int
986 usbd_submatch(parent, cf, aux)
987 struct device *parent;
988 struct cfdata *cf;
989 void *aux;
990 {
991 struct usb_attach_arg *uaa = aux;
992
993 if ((uaa->port != 0 &&
994 cf->uhubcf_port != UHUB_UNK_PORT &&
995 cf->uhubcf_port != uaa->port) ||
996 (uaa->configno != UHUB_UNK_CONFIGURATION &&
997 cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&
998 cf->uhubcf_configuration != uaa->configno) ||
999 (uaa->ifaceno != UHUB_UNK_INTERFACE &&
1000 cf->uhubcf_interface != UHUB_UNK_INTERFACE &&
1001 cf->uhubcf_interface != uaa->ifaceno))
1002 return 0;
1003 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
1004 }
1005
1006 #elif defined(__FreeBSD__)
1007 static void
1008 usbd_bus_print_child(device_t bus, device_t dev)
1009 {
1010 /* FIXME print the device address and the configuration used
1011 */
1012 }
1013 #endif
1014
1015 usbd_status
1016 usb_insert_transfer(reqh)
1017 usbd_request_handle reqh;
1018 {
1019 usbd_pipe_handle pipe = reqh->pipe;
1020 usbd_interface_handle iface = pipe->iface;
1021
1022 if (pipe->state == USBD_PIPE_IDLE ||
1023 (iface && iface->state == USBD_INTERFACE_IDLE))
1024 return (USBD_IS_IDLE);
1025 SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
1026 if (pipe->state != USBD_PIPE_ACTIVE ||
1027 (iface && iface->state != USBD_INTERFACE_ACTIVE))
1028 return (USBD_NOT_STARTED);
1029 if (pipe->running)
1030 return (USBD_IN_PROGRESS);
1031 pipe->running = 1;
1032 return (USBD_NORMAL_COMPLETION);
1033 }
1034
1035 void
1036 usb_start_next(pipe)
1037 usbd_pipe_handle pipe;
1038 {
1039 usbd_request_handle reqh;
1040 usbd_status r;
1041
1042 #ifdef DIAGNOSTIC
1043 if (SIMPLEQ_FIRST(&pipe->queue) == 0) {
1044 printf("usb_start_next: empty\n");
1045 return;
1046 }
1047 #endif
1048
1049 /* First remove remove old */
1050 SIMPLEQ_REMOVE_HEAD(&pipe->queue, SIMPLEQ_FIRST(&pipe->queue), next);
1051 if (pipe->state != USBD_PIPE_ACTIVE) {
1052 pipe->running = 0;
1053 return;
1054 }
1055 reqh = SIMPLEQ_FIRST(&pipe->queue);
1056 DPRINTFN(5, ("usb_start_next: start reqh=%p\n", reqh));
1057 if (!reqh)
1058 pipe->running = 0;
1059 else {
1060 r = pipe->methods->start(reqh);
1061 if (r != USBD_IN_PROGRESS) {
1062 printf("usb_start_next: error=%d\n", r);
1063 pipe->running = 0;
1064 /* XXX do what? */
1065 }
1066 }
1067 }
1068
1069 void
1070 usbd_fill_deviceinfo(dev, di)
1071 usbd_device_handle dev;
1072 struct usb_device_info *di;
1073 {
1074 struct usbd_port *p;
1075 int i, r, s;
1076
1077 di->config = dev->config;
1078 usbd_devinfo_vp(dev, di->vendor, di->product);
1079 usbd_printBCD(di->revision, UGETW(dev->ddesc.bcdDevice));
1080 di->class = dev->ddesc.bDeviceClass;
1081 di->power = dev->self_powered ? 0 : dev->power;
1082 di->lowspeed = dev->lowspeed;
1083 di->addr = dev->address;
1084 if (dev->hub) {
1085 for (i = 0;
1086 i < sizeof(di->ports) / sizeof(di->ports[0]) &&
1087 i < dev->hub->hubdesc.bNbrPorts;
1088 i++) {
1089 p = &dev->hub->ports[i];
1090 if (p->device)
1091 r = p->device->address;
1092 else {
1093 s = UGETW(p->status.wPortStatus);
1094 if (s & UPS_PORT_ENABLED)
1095 r = USB_PORT_ENABLED;
1096 else if (s & UPS_SUSPEND)
1097 r = USB_PORT_SUSPENDED;
1098 else if (s & UPS_PORT_POWER)
1099 r = USB_PORT_POWERED;
1100 else
1101 r = USB_PORT_DISABLED;
1102 }
1103 di->ports[i] = r;
1104 }
1105 di->nports = dev->hub->hubdesc.bNbrPorts;
1106 } else
1107 di->nports = 0;
1108 }
1109