usb_subr.c revision 1.18 1 /* $NetBSD: usb_subr.c,v 1.18 1998/12/26 12:53:03 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, lastno, curaidx = 0;
330
331 for (curidx = lastno = -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 != lastno) {
342 lastno = 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 usb_endpoint_descriptor_t *ed;
398 char *p, *end;
399 int endpt, nendpt;
400 usbd_status r;
401
402 DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
403 ifaceidx, altidx));
404 ifc->device = dev;
405 ifc->idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
406 ifc->index = ifaceidx;
407 ifc->altindex = altidx;
408 if (ifc->idesc == 0)
409 return (USBD_INVAL);
410 nendpt = ifc->idesc->bNumEndpoints;
411 DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt));
412 if (nendpt != 0) {
413 ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
414 M_USB, M_NOWAIT);
415 if (ifc->endpoints == 0)
416 return (USBD_NOMEM);
417 } else
418 ifc->endpoints = 0;
419 ifc->priv = 0;
420 p = (char *)ifc->idesc + ifc->idesc->bLength;
421 end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
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 goto found;
432 if (ed->bDescriptorType == UDESC_INTERFACE)
433 break;
434 }
435 r = USBD_INVAL;
436 goto bad;
437 found:
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 LIST_INIT(&ifc->pipes);
444 ifc->state = USBD_INTERFACE_ACTIVE;
445 return (USBD_NORMAL_COMPLETION);
446 bad:
447 free(ifc->endpoints, M_USB);
448 return (r);
449 }
450
451 void
452 usbd_free_iface_data(dev, ifcno)
453 usbd_device_handle dev;
454 int ifcno;
455 {
456 usbd_interface_handle ifc = &dev->ifaces[ifcno];
457 if (ifc->endpoints)
458 free(ifc->endpoints, M_USB);
459 }
460
461 static usbd_status
462 usbd_set_config(dev, conf)
463 usbd_device_handle dev;
464 int conf;
465 {
466 usb_device_request_t req;
467
468 req.bmRequestType = UT_WRITE_DEVICE;
469 req.bRequest = UR_SET_CONFIG;
470 USETW(req.wValue, conf);
471 USETW(req.wIndex, 0);
472 USETW(req.wLength, 0);
473 return (usbd_do_request(dev, &req, 0));
474 }
475
476 usbd_status
477 usbd_set_config_no(dev, no, msg)
478 usbd_device_handle dev;
479 int no;
480 int msg;
481 {
482 int index;
483 usb_config_descriptor_t cd;
484 usbd_status r;
485
486 DPRINTFN(5,("usbd_set_config_no: %d\n", no));
487 /* Figure out what config index to use. */
488 for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
489 r = usbd_get_config_desc(dev, index, &cd);
490 if (r != USBD_NORMAL_COMPLETION)
491 return (r);
492 if (cd.bConfigurationValue == no)
493 return (usbd_set_config_index(dev, index, msg));
494 }
495 return (USBD_INVAL);
496 }
497
498 usbd_status
499 usbd_set_config_index(dev, index, msg)
500 usbd_device_handle dev;
501 int index;
502 int msg;
503 {
504 usb_status_t ds;
505 usb_hub_status_t hs;
506 usb_config_descriptor_t cd, *cdp;
507 usbd_status r;
508 int ifcidx, nifc, len, selfpowered, power;
509
510 DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
511
512 /* XXX check that all interfaces are idle */
513 if (dev->config != 0) {
514 DPRINTF(("usbd_set_config_index: free old config\n"));
515 /* Free all configuration data structures. */
516 nifc = dev->cdesc->bNumInterface;
517 for (ifcidx = 0; ifcidx < nifc; ifcidx++)
518 usbd_free_iface_data(dev, ifcidx);
519 free(dev->ifaces, M_USB);
520 free(dev->cdesc, M_USB);
521 dev->ifaces = 0;
522 dev->cdesc = 0;
523 dev->config = 0;
524 dev->state = USBD_DEVICE_ADDRESSED;
525 }
526
527 /* Figure out what config number to use. */
528 r = usbd_get_config_desc(dev, index, &cd);
529 if (r != USBD_NORMAL_COMPLETION)
530 return (r);
531 len = UGETW(cd.wTotalLength);
532 cdp = malloc(len, M_USB, M_NOWAIT);
533 if (cdp == 0)
534 return (USBD_NOMEM);
535 r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
536 if (r != USBD_NORMAL_COMPLETION)
537 goto bad;
538 if (cdp->bDescriptorType != UDESC_CONFIG) {
539 DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
540 cdp->bDescriptorType));
541 r = USBD_INVAL;
542 goto bad;
543 }
544 selfpowered = 0;
545 if (cdp->bmAttributes & UC_SELF_POWERED) {
546 /* May be self powered. */
547 if (cdp->bmAttributes & UC_BUS_POWERED) {
548 /* Must ask device. */
549 if (dev->quirks->uq_flags & UQ_HUB_POWER) {
550 /* Buggy hub, use hub descriptor. */
551 r = usbd_get_hub_status(dev, &hs);
552 if (r == USBD_NORMAL_COMPLETION &&
553 !(UGETW(hs.wHubStatus) & UHS_LOCAL_POWER))
554 selfpowered = 1;
555 } else {
556 r = usbd_get_device_status(dev, &ds);
557 if (r == USBD_NORMAL_COMPLETION &&
558 (UGETW(ds.wStatus) & UDS_SELF_POWERED))
559 selfpowered = 1;
560 }
561 DPRINTF(("usbd_set_config_index: status=0x%04x, "
562 "error=%d(%s)\n",
563 UGETW(ds.wStatus), r, usbd_error_strs[r]));
564 } else
565 selfpowered = 1;
566 }
567 DPRINTF(("usbd_set_config_index: (addr %d) attr=0x%02x, "
568 "selfpowered=%d, power=%d, powerquirk=%x\n",
569 dev->address, cdp->bmAttributes,
570 selfpowered, cdp->bMaxPower * 2,
571 dev->quirks->uq_flags & UQ_HUB_POWER));
572 #ifdef USB_DEBUG
573 if (!dev->powersrc) {
574 printf("usbd_set_config_index: No power source?\n");
575 return (USBD_IOERROR);
576 }
577 #endif
578 power = cdp->bMaxPower * 2;
579 if (power > dev->powersrc->power) {
580 /* XXX print nicer message. */
581 if (msg)
582 printf("%s: device addr %d (config %d) exceeds power "
583 "budget, %d mA > %d mA\n",
584 USBDEVNAME(dev->bus->bdev), dev->address,
585 cdp->bConfigurationValue,
586 power, dev->powersrc->power);
587 r = USBD_NO_POWER;
588 goto bad;
589 }
590 dev->power = power;
591 dev->self_powered = selfpowered;
592
593 DPRINTF(("usbd_set_config_index: set config %d\n",
594 cdp->bConfigurationValue));
595 r = usbd_set_config(dev, cdp->bConfigurationValue);
596 if (r != USBD_NORMAL_COMPLETION) {
597 DPRINTF(("usbd_set_config_index: setting config=%d failed, "
598 "error=%d(%s)\n",
599 cdp->bConfigurationValue, r, usbd_error_strs[r]));
600 goto bad;
601 }
602 DPRINTF(("usbd_set_config_index: setting new config %d\n",
603 cdp->bConfigurationValue));
604 nifc = cdp->bNumInterface;
605 dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
606 M_USB, M_NOWAIT);
607 if (dev->ifaces == 0) {
608 r = USBD_NOMEM;
609 goto bad;
610 }
611 DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
612 dev->cdesc = cdp;
613 dev->config = cdp->bConfigurationValue;
614 dev->state = USBD_DEVICE_CONFIGURED;
615 for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
616 r = usbd_fill_iface_data(dev, ifcidx, 0);
617 if (r != USBD_NORMAL_COMPLETION) {
618 while (--ifcidx >= 0)
619 usbd_free_iface_data(dev, ifcidx);
620 goto bad;
621 }
622 }
623
624 return (USBD_NORMAL_COMPLETION);
625
626 bad:
627 free(cdp, M_USB);
628 return (r);
629 }
630
631 /* XXX add function for alternate settings */
632
633 usbd_status
634 usbd_setup_pipe(dev, iface, ep, pipe)
635 usbd_device_handle dev;
636 usbd_interface_handle iface;
637 struct usbd_endpoint *ep;
638 usbd_pipe_handle *pipe;
639 {
640 usbd_pipe_handle p;
641 usbd_status r;
642
643 DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
644 dev, iface, ep, pipe));
645 p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
646 if (p == 0)
647 return (USBD_NOMEM);
648 p->device = dev;
649 p->iface = iface;
650 p->state = USBD_PIPE_ACTIVE;
651 p->endpoint = ep;
652 ep->refcnt++;
653 p->refcnt = 1;
654 p->intrreqh = 0;
655 p->running = 0;
656 SIMPLEQ_INIT(&p->queue);
657 r = dev->bus->open_pipe(p);
658 if (r != USBD_NORMAL_COMPLETION) {
659 DPRINTF(("usbd_setup_pipe: endpoint=%d failed, error=%d(%s)\n",
660 ep->edesc->bEndpointAddress, r, usbd_error_strs[r]));
661 free(p, M_USB);
662 return (r);
663 }
664 *pipe = p;
665 return (USBD_NORMAL_COMPLETION);
666 }
667
668 /* Abort the device control pipe. */
669 void
670 usbd_kill_pipe(pipe)
671 usbd_pipe_handle pipe;
672 {
673 pipe->methods->close(pipe);
674 pipe->endpoint->refcnt--;
675 free(pipe, M_USB);
676 }
677
678 int
679 usbd_getnewaddr(bus)
680 usbd_bus_handle bus;
681 {
682 int addr;
683
684 for (addr = 1; addr < USB_MAX_DEVICES; addr++)
685 if (bus->devices[addr] == 0)
686 return (addr);
687 return (-1);
688 }
689
690
691 usbd_status
692 usbd_probe_and_attach(parent, dev, port, addr)
693 bdevice *parent;
694 usbd_device_handle dev;
695 int port;
696 int addr;
697 {
698 struct usb_attach_arg uaa;
699 usb_device_descriptor_t *dd = &dev->ddesc;
700 int r, found, i, confi;
701
702 #if defined(__FreeBSD__)
703 /* XXX isn't it bad to build &uaa into a value that has a lifetime
704 longer than this function call? */
705 bdevice bdev;
706 bdev = device_add_child(*parent, NULL, -1, &uaa);
707 if (bdev) {
708 printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
709 return (USBD_INVAL);
710 }
711 #endif
712
713 uaa.device = dev;
714 uaa.iface = 0;
715 uaa.usegeneric = 0;
716 uaa.port = port;
717 uaa.configno = UHUB_UNK_CONFIGURATION;
718 uaa.ifaceno = UHUB_UNK_INTERFACE;
719
720 /* First try with device specific drivers. */
721 if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
722 return (USBD_NORMAL_COMPLETION);
723
724 DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
725
726 /* Next try with interface drivers. */
727 for (confi = 0; confi < dd->bNumConfigurations; confi++) {
728 DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
729 confi));
730 r = usbd_set_config_index(dev, confi, 1);
731 if (r != USBD_NORMAL_COMPLETION) {
732 #ifdef USB_DEBUG
733 DPRINTF(("%s: port %d, set config at addr %d failed, "
734 "error=%d(%s)\n", USBDEVNAME(*parent), port,
735 addr, r, usbd_error_strs[r]));
736 #else
737 printf("%s: port %d, set config at addr %d failed\n",
738 USBDEVNAME(*parent), port, addr);
739 #endif
740 return (r);
741 }
742 uaa.configno = confi;
743 for (found = i = 0; i < dev->cdesc->bNumInterface; i++) {
744 uaa.iface = &dev->ifaces[i];
745 uaa.ifaceno = dev->ifaces[i].idesc->bInterfaceNumber;
746 if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
747 usbd_submatch))
748 found++;
749 }
750 if (found != 0)
751 return (USBD_NORMAL_COMPLETION);
752 }
753 /* No interfaces were attach in any of the configurations. */
754 if (dd->bNumConfigurations > 0)
755 usbd_set_config_index(dev, 0, 0);
756
757 DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
758
759 /* Finally try the generic driver. */
760 uaa.iface = 0;
761 uaa.usegeneric = 1;
762 uaa.configno = UHUB_UNK_CONFIGURATION;
763 uaa.ifaceno = UHUB_UNK_INTERFACE;
764 if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
765 return (USBD_NORMAL_COMPLETION);
766
767 /*
768 * The generic attach failed, but leave the device as it is.
769 * We just did not find any drivers, that's all. The device is
770 * fully operational and not harming anyone.
771 */
772 DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
773 return (USBD_NORMAL_COMPLETION);
774 }
775
776
777
778 /*
779 * Called when a new device has been put in the powered state,
780 * but not yet in the addressed state.
781 * Get initial descriptor, set the address, get full descriptor,
782 * and attach a driver.
783 */
784 usbd_status
785 usbd_new_device(parent, bus, depth, lowspeed, port, up)
786 bdevice *parent;
787 usbd_bus_handle bus;
788 int depth;
789 int lowspeed;
790 int port;
791 struct usbd_port *up;
792 {
793 usbd_device_handle dev;
794 usb_device_descriptor_t *dd;
795 usbd_status r;
796 int addr;
797 int i;
798
799 DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n",
800 bus, depth, lowspeed));
801 addr = usbd_getnewaddr(bus);
802 if (addr < 0) {
803 printf("%s: No free USB addresses, new device ignored.\n",
804 USBDEVNAME(bus->bdev));
805 return (USBD_NO_ADDR);
806 }
807
808 dev = malloc(sizeof *dev, M_USB, M_NOWAIT);
809 if (dev == 0)
810 return (USBD_NOMEM);
811 memset(dev, 0, sizeof(*dev));
812
813 dev->bus = bus;
814
815 /* Set up default endpoint handle. */
816 dev->def_ep.edesc = &dev->def_ep_desc;
817 dev->def_ep.state = USBD_ENDPOINT_ACTIVE;
818
819 /* Set up default endpoint descriptor. */
820 dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
821 dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
822 dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
823 dev->def_ep_desc.bmAttributes = UE_CONTROL;
824 USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
825 dev->def_ep_desc.bInterval = 0;
826
827 dev->state = USBD_DEVICE_DEFAULT;
828 dev->quirks = &usbd_no_quirk;
829 dev->address = USB_START_ADDR;
830 dev->ddesc.bMaxPacketSize = 0;
831 dev->lowspeed = lowspeed != 0;
832 dev->depth = depth;
833 dev->powersrc = up;
834
835 /* Establish the the default pipe. */
836 r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
837 if (r != USBD_NORMAL_COMPLETION) {
838 usbd_remove_device(dev, up);
839 return r;
840 }
841
842 up->device = dev;
843 dd = &dev->ddesc;
844 /* Try a few times in case the device is slow (i.e. outside specs.) */
845 for (i = 0; i < 5; i++) {
846 /* Get the first 8 bytes of the device descriptor. */
847 r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
848 if (r == USBD_NORMAL_COMPLETION)
849 break;
850 usbd_delay_ms(dev->bus, 200);
851 }
852 if (r != USBD_NORMAL_COMPLETION) {
853 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
854 "failed\n",
855 addr));
856 usbd_remove_device(dev, up);
857 return (r);
858 }
859
860 if (dd->bDescriptorType != UDESC_DEVICE) {
861 /* Illegal device descriptor */
862 DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
863 dd->bDescriptorType));
864 usbd_remove_device(dev, up);
865 return (USBD_INVAL);
866 }
867
868 DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
869 "subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",
870 addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
871 dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed));
872
873 USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
874
875 /* Get the full device descriptor. */
876 r = usbd_get_device_desc(dev, dd);
877 if (r != USBD_NORMAL_COMPLETION) {
878 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
879 "failed\n", addr));
880 usbd_remove_device(dev, up);
881 return (r);
882 }
883
884 /* Figure out what's wrong with this device. */
885 dev->quirks = usbd_find_quirk(dd);
886
887 /* Set the address */
888 r = usbd_set_address(dev, addr);
889 if (r != USBD_NORMAL_COMPLETION) {
890 DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
891 r = USBD_SET_ADDR_FAILED;
892 usbd_remove_device(dev, up);
893 return (r);
894 }
895 /* Allow device time to set new address */
896 usbd_delay_ms(dev->bus, USB_SET_ADDRESS_SETTLE);
897
898 dev->address = addr; /* New device address now */
899 dev->state = USBD_DEVICE_ADDRESSED;
900 bus->devices[addr] = dev;
901
902 /* Assume 100mA bus powered for now. Changed when configured. */
903 dev->power = USB_MIN_POWER;
904 dev->self_powered = 0;
905
906 DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
907 addr, dev, parent));
908
909 r = usbd_probe_and_attach(parent, dev, port, addr);
910 if (r != USBD_NORMAL_COMPLETION) {
911 usbd_remove_device(dev, up);
912 return (r);
913 }
914
915 return (USBD_NORMAL_COMPLETION);
916 }
917
918 void
919 usbd_remove_device(dev, up)
920 usbd_device_handle dev;
921 struct usbd_port *up;
922 {
923 DPRINTF(("usbd_remove_device: %p\n", dev));
924
925 #if defined(__NetBSD__)
926 /* XXX bit of a hack, only for hubs the detach is called
927 *
928 * easiest solution, register a detach method in the softc, call that
929 * one and pass the device struct to it, or the softc. Whatever.
930 */
931 /*if (dev->bdev && dev->hub)
932 uhub_detach(dev->hub->hubdata);*/
933 #elif defined(__FreeBSD__)
934 if (dev->bdev)
935 device_delete_child(device_get_parent(dev->bdev), dev->bdev);
936 #endif
937
938 if (dev->default_pipe)
939 usbd_kill_pipe(dev->default_pipe);
940 up->device = 0;
941 dev->bus->devices[dev->address] = 0;
942
943 free(dev, M_USB);
944 }
945
946 #if defined(__NetBSD__)
947 int
948 usbd_print(aux, pnp)
949 void *aux;
950 const char *pnp;
951 {
952 struct usb_attach_arg *uaa = aux;
953 char devinfo[1024];
954
955 DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
956 if (pnp) {
957 if (!uaa->usegeneric)
958 return (QUIET);
959 usbd_devinfo(uaa->device, 1, devinfo);
960 printf("%s, %s", devinfo, pnp);
961 }
962 if (uaa->port != 0)
963 printf(" port %d", uaa->port);
964 if (uaa->configno != UHUB_UNK_CONFIGURATION)
965 printf(" configuration %d", uaa->configno);
966 if (uaa->ifaceno != UHUB_UNK_INTERFACE)
967 printf(" interface %d", uaa->ifaceno);
968 return (UNCONF);
969 }
970
971 int
972 usbd_submatch(parent, cf, aux)
973 struct device *parent;
974 struct cfdata *cf;
975 void *aux;
976 {
977 struct usb_attach_arg *uaa = aux;
978
979 if ((uaa->port != 0 &&
980 cf->uhubcf_port != UHUB_UNK_PORT &&
981 cf->uhubcf_port != uaa->port) ||
982 (uaa->configno != UHUB_UNK_CONFIGURATION &&
983 cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&
984 cf->uhubcf_configuration != uaa->configno) ||
985 (uaa->ifaceno != UHUB_UNK_INTERFACE &&
986 cf->uhubcf_interface != UHUB_UNK_INTERFACE &&
987 cf->uhubcf_interface != uaa->ifaceno))
988 return 0;
989 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
990 }
991
992 #elif defined(__FreeBSD__)
993 static void
994 usbd_bus_print_child(device_t bus, device_t dev)
995 {
996 /* FIXME print the device address and the configuration used
997 */
998 }
999 #endif
1000
1001 void
1002 usbd_fill_deviceinfo(dev, di)
1003 usbd_device_handle dev;
1004 struct usb_device_info *di;
1005 {
1006 struct usbd_port *p;
1007 int i, r, s;
1008
1009 di->config = dev->config;
1010 usbd_devinfo_vp(dev, di->vendor, di->product);
1011 usbd_printBCD(di->revision, UGETW(dev->ddesc.bcdDevice));
1012 di->class = dev->ddesc.bDeviceClass;
1013 di->power = dev->self_powered ? 0 : dev->power;
1014 di->lowspeed = dev->lowspeed;
1015 di->addr = dev->address;
1016 if (dev->hub) {
1017 for (i = 0;
1018 i < sizeof(di->ports) / sizeof(di->ports[0]) &&
1019 i < dev->hub->hubdesc.bNbrPorts;
1020 i++) {
1021 p = &dev->hub->ports[i];
1022 if (p->device)
1023 r = p->device->address;
1024 else {
1025 s = UGETW(p->status.wPortStatus);
1026 if (s & UPS_PORT_ENABLED)
1027 r = USB_PORT_ENABLED;
1028 else if (s & UPS_SUSPEND)
1029 r = USB_PORT_SUSPENDED;
1030 else if (s & UPS_PORT_POWER)
1031 r = USB_PORT_POWERED;
1032 else
1033 r = USB_PORT_DISABLED;
1034 }
1035 di->ports[i] = r;
1036 }
1037 di->nports = dev->hub->hubdesc.bNbrPorts;
1038 } else
1039 di->nports = 0;
1040 }
1041