usb_subr.c revision 1.15 1 /* $NetBSD: usb_subr.c,v 1.15 1998/12/10 16:13:48 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 #include <sys/device.h>
45 #include <sys/proc.h>
46 #include <sys/select.h>
47
48 #include <dev/usb/usb.h>
49
50 #include <dev/usb/usbdi.h>
51 #include <dev/usb/usbdi_util.h>
52 #include <dev/usb/usbdivar.h>
53 #include <dev/usb/usbdevs.h>
54 #include <dev/usb/usb_quirks.h>
55
56 #include "opt_usbverbose.h"
57
58 #ifdef USB_DEBUG
59 #define DPRINTF(x) if (usbdebug) printf x
60 #define DPRINTFN(n,x) if (usbdebug>(n)) printf x
61 extern int usbdebug;
62 #else
63 #define DPRINTF(x)
64 #define DPRINTFN(n,x)
65 #endif
66
67 static usbd_status usbd_set_config __P((usbd_device_handle, int));
68 char *usbd_get_string __P((usbd_device_handle, int, char *));
69 usbd_status usbd_get_desc __P((usbd_device_handle dev, int type,
70 int index, int len, void *desc));
71 int usbd_getnewaddr __P((usbd_bus_handle bus));
72 int usbd_print __P((void *aux, const char *pnp));
73 int usbd_submatch __P((struct device *, struct cfdata *cf, void *));
74 usb_interface_descriptor_t *usbd_find_idesc __P((usb_config_descriptor_t *cd,
75 int ifaceidx, int altidx));
76 void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno));
77 void usbd_kill_pipe __P((usbd_pipe_handle));
78
79 #ifdef USBVERBOSE
80 typedef u_int16_t usb_vendor_id_t;
81 typedef u_int16_t usb_product_id_t;
82
83 /*
84 * Descriptions of of known vendors and devices ("products").
85 */
86 struct usb_knowndev {
87 usb_vendor_id_t vendor;
88 usb_product_id_t product;
89 int flags;
90 char *vendorname, *productname;
91 };
92 #define USB_KNOWNDEV_NOPROD 0x01 /* match on vendor only */
93
94 #include <dev/usb/usbdevs_data.h>
95 #endif /* USBVERBOSE */
96
97 #ifdef USB_DEBUG
98 char *usbd_error_strs[] = {
99 "NORMAL_COMPLETION",
100 "IN_PROGRESS",
101 "PENDING_REQUESTS",
102 "NOT_STARTED",
103 "INVAL",
104 "IS_IDLE",
105 "NOMEM",
106 "CANCELLED",
107 "BAD_ADDRESS",
108 "IN_USE",
109 "INTERFACE_NOT_ACTIVE",
110 "NO_ADDR",
111 "SET_ADDR_FAILED",
112 "NO_POWER",
113 "TOO_DEEP",
114 "IOERROR",
115 "NOT_CONFIGURED",
116 "TIMEOUT",
117 "SHORT_XFER",
118 "STALLED",
119 "XXX",
120 };
121 #endif
122
123 usbd_status
124 usbd_get_string_desc(dev, sindex, langid, sdesc)
125 usbd_device_handle dev;
126 int sindex;
127 int langid;
128 usb_string_descriptor_t *sdesc;
129 {
130 usb_device_request_t req;
131 usbd_status r;
132
133 req.bmRequestType = UT_READ_DEVICE;
134 req.bRequest = UR_GET_DESCRIPTOR;
135 USETW2(req.wValue, UDESC_STRING, sindex);
136 USETW(req.wIndex, langid);
137 USETW(req.wLength, 1); /* only size byte first */
138 r = usbd_do_request(dev, &req, sdesc);
139 if (r != USBD_NORMAL_COMPLETION)
140 return (r);
141 USETW(req.wLength, sdesc->bLength); /* the whole string */
142 return (usbd_do_request(dev, &req, sdesc));
143 }
144
145 char *
146 usbd_get_string(dev, si, buf)
147 usbd_device_handle dev;
148 int si;
149 char *buf;
150 {
151 int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE;
152 usb_string_descriptor_t us;
153 char *s;
154 int i, n;
155 u_int16_t c;
156 usbd_status r;
157
158 if (si == 0)
159 return (0);
160 if (dev->quirks->uq_flags & UQ_NO_STRINGS)
161 return (0);
162 r = usbd_get_string_desc(dev, si, 0, &us);
163 if (r != USBD_NORMAL_COMPLETION)
164 return (0);
165 s = buf;
166 n = us.bLength / 2 - 1;
167 for (i = 0; i < n; i++) {
168 c = UGETW(us.bString[i]);
169 /* Convert from Unicode, handle buggy strings. */
170 if ((c & 0xff00) == 0)
171 *s++ = c;
172 else if ((c & 0x00ff) == 0 && swap)
173 *s++ = c >> 8;
174 else
175 *s++ = '?';
176 }
177 *s++ = 0;
178 return buf;
179 }
180
181 void
182 usbd_devinfo_vp(dev, v, p)
183 usbd_device_handle dev;
184 char *v, *p;
185 {
186 usb_device_descriptor_t *udd = &dev->ddesc;
187 char *vendor = 0, *product = 0;
188 #ifdef USBVERBOSE
189 struct usb_knowndev *kdp;
190 #endif
191
192 vendor = usbd_get_string(dev, udd->iManufacturer, v);
193 product = usbd_get_string(dev, udd->iProduct, p);
194 #ifdef USBVERBOSE
195 if (!vendor) {
196 for(kdp = usb_knowndevs;
197 kdp->vendorname != NULL;
198 kdp++) {
199 if (kdp->vendor == UGETW(udd->idVendor) &&
200 (kdp->product == UGETW(udd->idProduct) ||
201 (kdp->flags & USB_KNOWNDEV_NOPROD) != 0))
202 break;
203 }
204 if (kdp->vendorname == NULL)
205 vendor = product = NULL;
206 else {
207 vendor = kdp->vendorname;
208 product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ?
209 kdp->productname : NULL;
210 }
211 }
212 #endif
213 if (vendor)
214 strcpy(v, vendor);
215 else
216 sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
217 if (product)
218 strcpy(p, product);
219 else
220 sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
221 }
222
223 int
224 usbd_printBCD(cp, bcd)
225 char *cp;
226 int bcd;
227 {
228 return (sprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff));
229 }
230
231 void
232 usbd_devinfo(dev, showclass, cp)
233 usbd_device_handle dev;
234 int showclass;
235 char *cp;
236 {
237 usb_device_descriptor_t *udd = &dev->ddesc;
238 char vendor[USB_MAX_STRING_LEN];
239 char product[USB_MAX_STRING_LEN];
240 int bcdDevice, bcdUSB;
241
242 usbd_devinfo_vp(dev, vendor, product);
243 cp += sprintf(cp, "%s %s", vendor, product);
244 if (showclass)
245 cp += sprintf(cp, ", class %d/%d",
246 udd->bDeviceClass, udd->bDeviceSubClass);
247 bcdUSB = UGETW(udd->bcdUSB);
248 bcdDevice = UGETW(udd->bcdDevice);
249 cp += sprintf(cp, ", rev ");
250 cp += usbd_printBCD(cp, bcdUSB);
251 *cp++ = '/';
252 cp += usbd_printBCD(cp, bcdDevice);
253 cp += sprintf(cp, ", addr %d", dev->address);
254 *cp = 0;
255 }
256
257 /* Delay for a certain number of ms */
258 void
259 usbd_delay_ms(bus, ms)
260 usbd_bus_handle bus;
261 int ms;
262 {
263 /* Wait at least two clock ticks so we know the time has passed. */
264 if (bus->use_polling)
265 delay((ms+1) * 1000);
266 else
267 tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
268 }
269
270 usbd_status
271 usbd_reset_port(dev, port, ps)
272 usbd_device_handle dev;
273 int port;
274 usb_port_status_t *ps;
275 {
276 usb_device_request_t req;
277 usbd_status r;
278 int n;
279
280 req.bmRequestType = UT_WRITE_CLASS_OTHER;
281 req.bRequest = UR_SET_FEATURE;
282 USETW(req.wValue, UHF_PORT_RESET);
283 USETW(req.wIndex, port);
284 USETW(req.wLength, 0);
285 r = usbd_do_request(dev, &req, 0);
286 DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%d(%s)\n",
287 port, r, usbd_error_strs[r]));
288 if (r != USBD_NORMAL_COMPLETION)
289 return (r);
290 n = 10;
291 do {
292 /* Wait for device to recover from reset. */
293 usbd_delay_ms(dev->bus, USB_PORT_RESET_DELAY);
294 r = usbd_get_port_status(dev, port, ps);
295 if (r != USBD_NORMAL_COMPLETION) {
296 DPRINTF(("usbd_reset_port: get status failed %d\n",r));
297 return (r);
298 }
299 } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
300 if (n == 0) {
301 printf("usbd_reset_port: timeout\n");
302 return (USBD_IOERROR);
303 }
304 r = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
305 #ifdef USB_DEBUG
306 if (r != USBD_NORMAL_COMPLETION)
307 DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r));
308 #endif
309 return (r);
310 }
311
312 usb_interface_descriptor_t *
313 usbd_find_idesc(cd, ifaceidx, altidx)
314 usb_config_descriptor_t *cd;
315 int ifaceidx;
316 int altidx;
317 {
318 char *p = (char *)cd;
319 char *end = p + UGETW(cd->wTotalLength);
320 usb_interface_descriptor_t *d;
321 int curidx, lastno, curaidx;
322
323 for (curidx = lastno = -1; p < end; ) {
324 d = (usb_interface_descriptor_t *)p;
325 if (d->bLength == 0) /* bad descriptor */
326 break;
327 p += d->bLength;
328 if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
329 if (d->bInterfaceNumber != lastno) {
330 lastno = d->bInterfaceNumber;
331 curidx++;
332 curaidx = 0;
333 } else
334 curaidx++;
335 if (ifaceidx == curidx && altidx == curaidx)
336 return (d);
337 }
338 }
339 return (0);
340 }
341
342 usb_endpoint_descriptor_t *
343 usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
344 usb_config_descriptor_t *cd;
345 int ifaceidx;
346 int altidx;
347 int endptidx;
348 {
349 char *p = (char *)cd;
350 char *end = p + UGETW(cd->wTotalLength);
351 usb_interface_descriptor_t *d;
352 usb_endpoint_descriptor_t *e;
353 int curidx;
354
355 d = usbd_find_idesc(cd, ifaceidx, altidx);
356 if (!d)
357 return (0);
358 if (endptidx >= d->bNumEndpoints) /* quick exit */
359 return (0);
360
361 curidx = -1;
362 for (p = (char *)d + d->bLength; p < end; ) {
363 e = (usb_endpoint_descriptor_t *)p;
364 if (e->bLength == 0) /* bad descriptor */
365 break;
366 p += e->bLength;
367 if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
368 return (0);
369 if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
370 curidx++;
371 if (curidx == endptidx)
372 return (e);
373 }
374 }
375 return (0);
376 }
377
378 usbd_status
379 usbd_fill_iface_data(dev, ifaceidx, altidx)
380 usbd_device_handle dev;
381 int ifaceidx;
382 int altidx;
383 {
384 usbd_interface_handle ifc = &dev->ifaces[ifaceidx];
385 usb_endpoint_descriptor_t *ed;
386 char *p, *end;
387 int endpt, nendpt;
388 usbd_status r;
389
390 DPRINTFN(5,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
391 ifaceidx, altidx));
392 ifc->device = dev;
393 ifc->idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
394 ifc->index = ifaceidx;
395 ifc->altindex = altidx;
396 if (ifc->idesc == 0)
397 return (USBD_INVAL);
398 nendpt = ifc->idesc->bNumEndpoints;
399 DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt));
400 if (nendpt != 0) {
401 ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
402 M_USB, M_NOWAIT);
403 if (ifc->endpoints == 0)
404 return (USBD_NOMEM);
405 } else
406 ifc->endpoints = 0;
407 ifc->priv = 0;
408 p = (char *)ifc->idesc + ifc->idesc->bLength;
409 end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
410 for (endpt = 0; endpt < nendpt; endpt++) {
411 DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt));
412 for (; p < end; p += ed->bLength) {
413 ed = (usb_endpoint_descriptor_t *)p;
414 DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p "
415 "len=%d type=%d\n",
416 p, end, ed->bLength, ed->bDescriptorType));
417 if (p + ed->bLength <= end &&
418 ed->bDescriptorType == UDESC_ENDPOINT)
419 goto found;
420 if (ed->bDescriptorType == UDESC_INTERFACE)
421 break;
422 }
423 r = USBD_INVAL;
424 goto bad;
425 found:
426 ifc->endpoints[endpt].edesc = ed;
427 ifc->endpoints[endpt].state = USBD_ENDPOINT_ACTIVE;
428 ifc->endpoints[endpt].refcnt = 0;
429 ifc->endpoints[endpt].toggle = 0;
430 }
431 LIST_INIT(&ifc->pipes);
432 ifc->state = USBD_INTERFACE_ACTIVE;
433 return (USBD_NORMAL_COMPLETION);
434 bad:
435 free(ifc->endpoints, M_USB);
436 return (r);
437 }
438
439 void
440 usbd_free_iface_data(dev, ifcno)
441 usbd_device_handle dev;
442 int ifcno;
443 {
444 usbd_interface_handle ifc = &dev->ifaces[ifcno];
445 if (ifc->endpoints)
446 free(ifc->endpoints, M_USB);
447 }
448
449 static usbd_status
450 usbd_set_config(dev, conf)
451 usbd_device_handle dev;
452 int conf;
453 {
454 usb_device_request_t req;
455
456 req.bmRequestType = UT_WRITE_DEVICE;
457 req.bRequest = UR_SET_CONFIG;
458 USETW(req.wValue, conf);
459 USETW(req.wIndex, 0);
460 USETW(req.wLength, 0);
461 return (usbd_do_request(dev, &req, 0));
462 }
463
464 usbd_status
465 usbd_set_config_no(dev, no, msg)
466 usbd_device_handle dev;
467 int no;
468 int msg;
469 {
470 int index;
471 usb_config_descriptor_t cd;
472 usbd_status r;
473
474 DPRINTFN(5,("usbd_set_config_no: %d\n", no));
475 /* Figure out what config index to use. */
476 for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
477 r = usbd_get_config_desc(dev, index, &cd);
478 if (r != USBD_NORMAL_COMPLETION)
479 return (r);
480 if (cd.bConfigurationValue == no)
481 return (usbd_set_config_index(dev, index, msg));
482 }
483 return (USBD_INVAL);
484 }
485
486 usbd_status
487 usbd_set_config_index(dev, index, msg)
488 usbd_device_handle dev;
489 int index;
490 int msg;
491 {
492 usb_status_t ds;
493 usb_hub_status_t hs;
494 usb_config_descriptor_t cd, *cdp;
495 usbd_status r;
496 int ifcidx, nifc, len, selfpowered, power;
497
498 DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
499
500 /* XXX check that all interfaces are idle */
501 if (dev->config != 0) {
502 DPRINTF(("usbd_set_config_index: free old config\n"));
503 /* Free all configuration data structures. */
504 nifc = dev->cdesc->bNumInterface;
505 for (ifcidx = 0; ifcidx < nifc; ifcidx++)
506 usbd_free_iface_data(dev, ifcidx);
507 free(dev->ifaces, M_USB);
508 free(dev->cdesc, M_USB);
509 dev->ifaces = 0;
510 dev->cdesc = 0;
511 dev->config = 0;
512 dev->state = USBD_DEVICE_ADDRESSED;
513 }
514
515 /* Figure out what config number to use. */
516 r = usbd_get_config_desc(dev, index, &cd);
517 if (r != USBD_NORMAL_COMPLETION)
518 return (r);
519 len = UGETW(cd.wTotalLength);
520 cdp = malloc(len, M_USB, M_NOWAIT);
521 if (cdp == 0)
522 return (USBD_NOMEM);
523 r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
524 if (r != USBD_NORMAL_COMPLETION)
525 goto bad;
526 selfpowered = 0;
527 if (cdp->bmAttributes & UC_SELF_POWERED) {
528 /* May be self powered. */
529 if (cdp->bmAttributes & UC_BUS_POWERED) {
530 /* Must ask device. */
531 if (dev->quirks->uq_flags & UQ_HUB_POWER) {
532 /* Buggy hub, use hub descriptor. */
533 r = usbd_get_hub_status(dev, &hs);
534 if (r == USBD_NORMAL_COMPLETION &&
535 !(UGETW(hs.wHubStatus) & UHS_LOCAL_POWER))
536 selfpowered = 1;
537 } else {
538 r = usbd_get_device_status(dev, &ds);
539 if (r == USBD_NORMAL_COMPLETION &&
540 (UGETW(ds.wStatus) & UDS_SELF_POWERED))
541 selfpowered = 1;
542 }
543 DPRINTF(("usbd_set_config_index: status=0x%04x, "
544 "error=%d(%s)\n",
545 UGETW(ds.wStatus), r, usbd_error_strs[r]));
546 } else
547 selfpowered = 1;
548 }
549 DPRINTF(("usbd_set_config_index: (addr %d) attr=0x%02x, "
550 "selfpowered=%d, power=%d, powerquirk=%x\n",
551 dev->address, cdp->bmAttributes,
552 selfpowered, cdp->bMaxPower * 2,
553 dev->quirks->uq_flags & UQ_HUB_POWER));
554 #ifdef USB_DEBUG
555 if (!dev->powersrc) {
556 printf("usbd_set_config_index: No power source?\n");
557 return (USBD_IOERROR);
558 }
559 #endif
560 power = cdp->bMaxPower * 2;
561 if (power > dev->powersrc->power) {
562 /* XXX print nicer message. */
563 if (msg)
564 printf("%s: device addr %d (config %d) exceeds "
565 "power budget, %d mA > %d mA\n",
566 dev->bus->bdev.dv_xname, dev->address,
567 cdp->bConfigurationValue,
568 power, dev->powersrc->power);
569 r = USBD_NO_POWER;
570 goto bad;
571 }
572 dev->power = power;
573 dev->self_powered = selfpowered;
574
575 r = usbd_set_config(dev, cdp->bConfigurationValue);
576 if (r != USBD_NORMAL_COMPLETION) {
577 DPRINTF(("usbd_set_config_index: setting config=%d failed, "
578 "error=%d(%s)\n",
579 cdp->bConfigurationValue, r, usbd_error_strs[r]));
580 goto bad;
581 }
582 DPRINTF(("usbd_set_config_index: setting new config %d\n",
583 cdp->bConfigurationValue));
584 nifc = cdp->bNumInterface;
585 dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
586 M_USB, M_NOWAIT);
587 if (dev->ifaces == 0) {
588 r = USBD_NOMEM;
589 goto bad;
590 }
591 DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
592 dev->cdesc = cdp;
593 dev->config = cdp->bConfigurationValue;
594 dev->state = USBD_DEVICE_CONFIGURED;
595 for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
596 r = usbd_fill_iface_data(dev, ifcidx, 0);
597 if (r != USBD_NORMAL_COMPLETION) {
598 while (--ifcidx >= 0)
599 usbd_free_iface_data(dev, ifcidx);
600 goto bad;
601 }
602 }
603
604 return (USBD_NORMAL_COMPLETION);
605
606 bad:
607 free(cdp, M_USB);
608 return (r);
609 }
610
611 /* XXX add function for alternate settings */
612
613 usbd_status
614 usbd_setup_pipe(dev, iface, ep, pipe)
615 usbd_device_handle dev;
616 usbd_interface_handle iface;
617 struct usbd_endpoint *ep;
618 usbd_pipe_handle *pipe;
619 {
620 usbd_pipe_handle p;
621 usbd_status r;
622
623 DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
624 dev, iface, ep, pipe));
625 p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
626 if (p == 0)
627 return (USBD_NOMEM);
628 p->device = dev;
629 p->iface = iface;
630 p->state = USBD_PIPE_ACTIVE;
631 p->endpoint = ep;
632 ep->refcnt++;
633 p->refcnt = 1;
634 p->intrreqh = 0;
635 p->running = 0;
636 SIMPLEQ_INIT(&p->queue);
637 r = dev->bus->open_pipe(p);
638 if (r != USBD_NORMAL_COMPLETION) {
639 DPRINTF(("usbd_setup_pipe: endpoint=%d failed, error=%d(%s)\n",
640 ep->edesc->bEndpointAddress, r, usbd_error_strs[r]));
641 free(p, M_USB);
642 return (r);
643 }
644 *pipe = p;
645 return (USBD_NORMAL_COMPLETION);
646 }
647
648 /* Abort the device control pipe. */
649 void
650 usbd_kill_pipe(pipe)
651 usbd_pipe_handle pipe;
652 {
653 pipe->methods->close(pipe);
654 pipe->endpoint->refcnt--;
655 free(pipe, M_USB);
656 }
657
658 int
659 usbd_getnewaddr(bus)
660 usbd_bus_handle bus;
661 {
662 int i;
663
664 for (i = 1; i < USB_MAX_DEVICES; i++)
665 if (bus->devices[i] == 0)
666 return (i);
667 return (-1);
668 }
669
670 /*
671 * Called when a new device has been put in the powered state,
672 * but not yet in the addressed state.
673 * Get initial descriptor, set the address, get full descriptor,
674 * and attach a driver.
675 */
676 usbd_status
677 usbd_new_device(parent, bus, depth, lowspeed, port, up)
678 struct device *parent;
679 usbd_bus_handle bus;
680 int depth;
681 int lowspeed;
682 int port;
683 struct usbd_port *up;
684 {
685 usbd_device_handle dev;
686 usb_device_descriptor_t *d;
687 usbd_status r;
688 struct usb_attach_arg uaa;
689 int addr;
690 int found, i, confi;
691
692 DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n",
693 bus, depth, lowspeed));
694 addr = usbd_getnewaddr(bus);
695 if (addr < 0) {
696 printf("%s: No free USB addresses, new device ignored.\n",
697 bus->bdev.dv_xname);
698 return (USBD_NO_ADDR);
699 }
700
701 dev = malloc(sizeof *dev, M_USB, M_NOWAIT);
702 if (dev == 0)
703 return (USBD_NOMEM);
704 memset(dev, 0, sizeof(*dev));
705
706 dev->bus = bus;
707
708 /* Set up default endpoint handle. */
709 dev->def_ep.edesc = &dev->def_ep_desc;
710 dev->def_ep.state = USBD_ENDPOINT_ACTIVE;
711 dev->def_ep.refcnt = 0;
712 dev->def_ep.toggle = 0; /* XXX */
713
714 /* Set up default endpoint descriptor. */
715 dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
716 dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
717 dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
718 dev->def_ep_desc.bmAttributes = UE_CONTROL;
719 USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
720 dev->def_ep_desc.bInterval = 0;
721
722 dev->state = USBD_DEVICE_DEFAULT;
723 dev->quirks = &usbd_no_quirk;
724 dev->address = USB_START_ADDR;
725 dev->ddesc.bMaxPacketSize = 0;
726 dev->lowspeed = lowspeed != 0;
727 dev->depth = depth;
728 dev->powersrc = up;
729
730 /* Establish the the default pipe. */
731 r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
732 if (r != USBD_NORMAL_COMPLETION)
733 goto bad1;
734
735 up->device = dev;
736 d = &dev->ddesc;
737 /* Try a few times in case the device is slow (i.e. outside specs.) */
738 for (i = 0; i < 5; i++) {
739 /* Get the first 8 bytes of the device descriptor. */
740 r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, d);
741 if (r == USBD_NORMAL_COMPLETION)
742 break;
743 usbd_delay_ms(dev->bus, 200);
744 }
745 if (r != USBD_NORMAL_COMPLETION) {
746 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
747 "failed\n",
748 addr));
749 goto bad;
750 }
751
752 DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
753 "subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",
754 addr, UGETW(d->bcdUSB), d->bDeviceClass, d->bDeviceSubClass,
755 d->bDeviceProtocol, d->bMaxPacketSize, dev->lowspeed));
756
757 USETW(dev->def_ep_desc.wMaxPacketSize, d->bMaxPacketSize);
758
759 /* Get the full device descriptor. */
760 r = usbd_get_device_desc(dev, d);
761 if (r != USBD_NORMAL_COMPLETION) {
762 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
763 "failed\n", addr));
764 goto bad;
765 }
766
767 /* Figure out what's wrong with this device. */
768 dev->quirks = usbd_find_quirk(d);
769
770 /* Set the address */
771 r = usbd_set_address(dev, addr);
772 if (r != USBD_NORMAL_COMPLETION) {
773 DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
774 r = USBD_SET_ADDR_FAILED;
775 goto bad;
776 }
777 dev->address = addr; /* New device address now */
778 dev->state = USBD_DEVICE_ADDRESSED;
779 bus->devices[addr] = dev;
780
781 /* Assume 100mA bus powered for now. Changed when configured. */
782 dev->power = USB_MIN_POWER;
783 dev->self_powered = 0;
784
785 DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
786 addr, dev, parent));
787
788 uaa.device = dev;
789 uaa.iface = 0;
790 uaa.usegeneric = 0;
791 uaa.port = port;
792 uaa.configno = UHUB_UNK_CONFIGURATION;
793 uaa.ifaceno = UHUB_UNK_INTERFACE;
794 /* First try with device specific drivers. */
795 if (config_found_sm(parent, &uaa, usbd_print, usbd_submatch) != 0)
796 return (USBD_NORMAL_COMPLETION);
797
798 DPRINTF(("usbd_new_device: no device driver found\n"));
799
800 /* Next try with interface drivers. */
801 for (confi = 0; confi < d->bNumConfigurations; confi++) {
802 DPRINTFN(1,("usbd_new_device: trying config idx=%d\n", confi));
803 r = usbd_set_config_index(dev, confi, 1);
804 if (r != USBD_NORMAL_COMPLETION) {
805 #ifdef USB_DEBUG
806 DPRINTF(("%s: set config at addr %d failed, "
807 "error=%d(%s)\n",
808 parent->dv_xname, addr, r,
809 usbd_error_strs[r]));
810 #else
811 printf("%s: set config at addr %d failed\n",
812 parent->dv_xname, addr);
813 #endif
814 goto bad;
815 }
816 uaa.configno = confi;
817 for (found = i = 0; i < dev->cdesc->bNumInterface; i++) {
818 uaa.iface = &dev->ifaces[i];
819 uaa.ifaceno = dev->ifaces[i].idesc->bInterfaceNumber;
820 if (config_found_sm(parent, &uaa, usbd_print,
821 usbd_submatch))
822 found++;
823 }
824 if (found != 0)
825 return (USBD_NORMAL_COMPLETION);
826 }
827 /* No interfaces were attached in any of the configurations. */
828 if (d->bNumConfigurations > 0)
829 usbd_set_config_index(dev, 0, 0);
830
831 DPRINTF(("usbd_new_device: no interface drivers found\n"));
832
833 /* Finally try the generic driver. */
834 uaa.iface = 0;
835 uaa.usegeneric = 1;
836 uaa.configno = UHUB_UNK_CONFIGURATION;
837 uaa.ifaceno = UHUB_UNK_INTERFACE;
838 if (config_found_sm(parent, &uaa, usbd_print, usbd_submatch) != 0)
839 return (USBD_NORMAL_COMPLETION);
840
841 DPRINTF(("usbd_new_device: generic attach failed\n"));
842
843 return (USBD_NORMAL_COMPLETION);
844
845 bad:
846 usbd_kill_pipe(dev->default_pipe);
847 bad1:
848 up->device = 0;
849 bus->devices[addr] = 0;
850 free(dev, M_USB);
851 return (r);
852 }
853
854 int
855 usbd_print(aux, pnp)
856 void *aux;
857 const char *pnp;
858 {
859 struct usb_attach_arg *uaa = aux;
860 char devinfo[1024];
861
862 DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
863 if (pnp) {
864 if (!uaa->usegeneric)
865 return (QUIET);
866 usbd_devinfo(uaa->device, 1, devinfo);
867 printf("%s, %s", devinfo, pnp);
868 }
869 if (uaa->port != 0)
870 printf(" port %d", uaa->port);
871 if (uaa->configno != UHUB_UNK_CONFIGURATION)
872 printf(" configuration %d", uaa->configno);
873 if (uaa->ifaceno != UHUB_UNK_INTERFACE)
874 printf(" interface %d", uaa->ifaceno);
875 return (UNCONF);
876 }
877
878 int
879 usbd_submatch(parent, cf, aux)
880 struct device *parent;
881 struct cfdata *cf;
882 void *aux;
883 {
884 struct usb_attach_arg *uaa = aux;
885
886 if ((uaa->port != 0 &&
887 cf->uhubcf_port != UHUB_UNK_PORT &&
888 cf->uhubcf_port != uaa->port) ||
889 (uaa->configno != UHUB_UNK_CONFIGURATION &&
890 cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&
891 cf->uhubcf_configuration != uaa->configno) ||
892 (uaa->ifaceno != UHUB_UNK_INTERFACE &&
893 cf->uhubcf_interface != UHUB_UNK_INTERFACE &&
894 cf->uhubcf_interface != uaa->ifaceno))
895 return 0;
896 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
897 }
898
899 void
900 usbd_fill_deviceinfo(dev, di)
901 usbd_device_handle dev;
902 struct usb_device_info *di;
903 {
904 struct usbd_port *p;
905 int i, r, s;
906
907 di->config = dev->config;
908 usbd_devinfo_vp(dev, di->vendor, di->product);
909 usbd_printBCD(di->revision, UGETW(dev->ddesc.bcdDevice));
910 di->class = dev->ddesc.bDeviceClass;
911 di->power = dev->self_powered ? 0 : dev->power;
912 di->lowspeed = dev->lowspeed;
913 di->addr = dev->address;
914 if (dev->hub) {
915 for (i = 0;
916 i < sizeof(di->ports) / sizeof(di->ports[0]) &&
917 i < dev->hub->hubdesc.bNbrPorts;
918 i++) {
919 p = &dev->hub->ports[i];
920 if (p->device)
921 r = p->device->address;
922 else {
923 s = UGETW(p->status.wPortStatus);
924 if (s & UPS_PORT_ENABLED)
925 r = USB_PORT_ENABLED;
926 else if (s & UPS_SUSPEND)
927 r = USB_PORT_SUSPENDED;
928 else if (s & UPS_PORT_POWER)
929 r = USB_PORT_POWERED;
930 else
931 r = USB_PORT_DISABLED;
932 }
933 di->ports[i] = r;
934 }
935 di->nports = dev->hub->hubdesc.bNbrPorts;
936 } else
937 di->nports = 0;
938 }
939