usb_subr.c revision 1.19 1 /* $NetBSD: usb_subr.c,v 1.19 1998/12/28 20:14:00 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;
703
704 #if defined(__FreeBSD__)
705 /* XXX isn't it bad to build &uaa into a value that has a lifetime
706 longer than this function call? */
707 bdevice bdev;
708 bdev = device_add_child(*parent, NULL, -1, &uaa);
709 if (bdev) {
710 printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
711 return (USBD_INVAL);
712 }
713 #endif
714
715 uaa.device = dev;
716 uaa.iface = 0;
717 uaa.usegeneric = 0;
718 uaa.port = port;
719 uaa.configno = UHUB_UNK_CONFIGURATION;
720 uaa.ifaceno = UHUB_UNK_INTERFACE;
721
722 /* First try with device specific drivers. */
723 if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
724 return (USBD_NORMAL_COMPLETION);
725
726 DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
727
728 /* Next try with interface drivers. */
729 for (confi = 0; confi < dd->bNumConfigurations; confi++) {
730 DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
731 confi));
732 r = usbd_set_config_index(dev, confi, 1);
733 if (r != USBD_NORMAL_COMPLETION) {
734 #ifdef USB_DEBUG
735 DPRINTF(("%s: port %d, set config at addr %d failed, "
736 "error=%d(%s)\n", USBDEVNAME(*parent), port,
737 addr, r, usbd_error_strs[r]));
738 #else
739 printf("%s: port %d, set config at addr %d failed\n",
740 USBDEVNAME(*parent), port, addr);
741 #endif
742 return (r);
743 }
744 uaa.configno = confi;
745 for (found = i = 0; i < dev->cdesc->bNumInterface; i++) {
746 uaa.iface = &dev->ifaces[i];
747 uaa.ifaceno = dev->ifaces[i].idesc->bInterfaceNumber;
748 if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
749 usbd_submatch))
750 found++;
751 }
752 if (found != 0)
753 return (USBD_NORMAL_COMPLETION);
754 }
755 /* No interfaces were attach in any of the configurations. */
756 if (dd->bNumConfigurations > 0)
757 usbd_set_config_index(dev, 0, 0);
758
759 DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
760
761 /* Finally try the generic driver. */
762 uaa.iface = 0;
763 uaa.usegeneric = 1;
764 uaa.configno = UHUB_UNK_CONFIGURATION;
765 uaa.ifaceno = UHUB_UNK_INTERFACE;
766 if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
767 return (USBD_NORMAL_COMPLETION);
768
769 /*
770 * The generic attach failed, but leave the device as it is.
771 * We just did not find any drivers, that's all. The device is
772 * fully operational and not harming anyone.
773 */
774 DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
775 return (USBD_NORMAL_COMPLETION);
776 }
777
778
779
780 /*
781 * Called when a new device has been put in the powered state,
782 * but not yet in the addressed state.
783 * Get initial descriptor, set the address, get full descriptor,
784 * and attach a driver.
785 */
786 usbd_status
787 usbd_new_device(parent, bus, depth, lowspeed, port, up)
788 bdevice *parent;
789 usbd_bus_handle bus;
790 int depth;
791 int lowspeed;
792 int port;
793 struct usbd_port *up;
794 {
795 usbd_device_handle dev;
796 usb_device_descriptor_t *dd;
797 usbd_status r;
798 int addr;
799 int i;
800
801 DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n",
802 bus, depth, lowspeed));
803 addr = usbd_getnewaddr(bus);
804 if (addr < 0) {
805 printf("%s: No free USB addresses, new device ignored.\n",
806 USBDEVNAME(bus->bdev));
807 return (USBD_NO_ADDR);
808 }
809
810 dev = malloc(sizeof *dev, M_USB, M_NOWAIT);
811 if (dev == 0)
812 return (USBD_NOMEM);
813 memset(dev, 0, sizeof(*dev));
814
815 dev->bus = bus;
816
817 /* Set up default endpoint handle. */
818 dev->def_ep.edesc = &dev->def_ep_desc;
819 dev->def_ep.state = USBD_ENDPOINT_ACTIVE;
820
821 /* Set up default endpoint descriptor. */
822 dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
823 dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
824 dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
825 dev->def_ep_desc.bmAttributes = UE_CONTROL;
826 USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
827 dev->def_ep_desc.bInterval = 0;
828
829 dev->state = USBD_DEVICE_DEFAULT;
830 dev->quirks = &usbd_no_quirk;
831 dev->address = USB_START_ADDR;
832 dev->ddesc.bMaxPacketSize = 0;
833 dev->lowspeed = lowspeed != 0;
834 dev->depth = depth;
835 dev->powersrc = up;
836
837 /* Establish the the default pipe. */
838 r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
839 if (r != USBD_NORMAL_COMPLETION) {
840 usbd_remove_device(dev, up);
841 return (r);
842 }
843
844 up->device = dev;
845 dd = &dev->ddesc;
846 /* Try a few times in case the device is slow (i.e. outside specs.) */
847 for (i = 0; i < 5; i++) {
848 /* Get the first 8 bytes of the device descriptor. */
849 r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
850 if (r == USBD_NORMAL_COMPLETION)
851 break;
852 usbd_delay_ms(dev->bus, 200);
853 }
854 if (r != USBD_NORMAL_COMPLETION) {
855 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
856 "failed\n",
857 addr));
858 usbd_remove_device(dev, up);
859 return (r);
860 }
861
862 if (dd->bDescriptorType != UDESC_DEVICE) {
863 /* Illegal device descriptor */
864 DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
865 dd->bDescriptorType));
866 usbd_remove_device(dev, up);
867 return (USBD_INVAL);
868 }
869
870 DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
871 "subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",
872 addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
873 dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed));
874
875 USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
876
877 /* Get the full device descriptor. */
878 r = usbd_get_device_desc(dev, dd);
879 if (r != USBD_NORMAL_COMPLETION) {
880 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
881 "failed\n", addr));
882 usbd_remove_device(dev, up);
883 return (r);
884 }
885
886 /* Figure out what's wrong with this device. */
887 dev->quirks = usbd_find_quirk(dd);
888
889 /* Set the address */
890 r = usbd_set_address(dev, addr);
891 if (r != USBD_NORMAL_COMPLETION) {
892 DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
893 r = USBD_SET_ADDR_FAILED;
894 usbd_remove_device(dev, up);
895 return (r);
896 }
897 /* Allow device time to set new address */
898 usbd_delay_ms(dev->bus, USB_SET_ADDRESS_SETTLE);
899
900 dev->address = addr; /* New device address now */
901 dev->state = USBD_DEVICE_ADDRESSED;
902 bus->devices[addr] = dev;
903
904 /* Assume 100mA bus powered for now. Changed when configured. */
905 dev->power = USB_MIN_POWER;
906 dev->self_powered = 0;
907
908 DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
909 addr, dev, parent));
910
911 r = usbd_probe_and_attach(parent, dev, port, addr);
912 if (r != USBD_NORMAL_COMPLETION) {
913 usbd_remove_device(dev, up);
914 return (r);
915 }
916
917 return (USBD_NORMAL_COMPLETION);
918 }
919
920 void
921 usbd_remove_device(dev, up)
922 usbd_device_handle dev;
923 struct usbd_port *up;
924 {
925 DPRINTF(("usbd_remove_device: %p\n", dev));
926
927 #if defined(__NetBSD__)
928 /* XXX bit of a hack, only for hubs the detach is called
929 *
930 * easiest solution, register a detach method in the softc, call that
931 * one and pass the device struct to it, or the softc. Whatever.
932 */
933 /*if (dev->bdev && dev->hub)
934 uhub_detach(dev->hub->hubdata);*/
935 #elif defined(__FreeBSD__)
936 if (dev->bdev)
937 device_delete_child(device_get_parent(dev->bdev), dev->bdev);
938 #endif
939
940 if (dev->default_pipe)
941 usbd_kill_pipe(dev->default_pipe);
942 up->device = 0;
943 dev->bus->devices[dev->address] = 0;
944
945 free(dev, M_USB);
946 }
947
948 #if defined(__NetBSD__)
949 int
950 usbd_print(aux, pnp)
951 void *aux;
952 const char *pnp;
953 {
954 struct usb_attach_arg *uaa = aux;
955 char devinfo[1024];
956
957 DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
958 if (pnp) {
959 if (!uaa->usegeneric)
960 return (QUIET);
961 usbd_devinfo(uaa->device, 1, devinfo);
962 printf("%s, %s", devinfo, pnp);
963 }
964 if (uaa->port != 0)
965 printf(" port %d", uaa->port);
966 if (uaa->configno != UHUB_UNK_CONFIGURATION)
967 printf(" configuration %d", uaa->configno);
968 if (uaa->ifaceno != UHUB_UNK_INTERFACE)
969 printf(" interface %d", uaa->ifaceno);
970 return (UNCONF);
971 }
972
973 int
974 usbd_submatch(parent, cf, aux)
975 struct device *parent;
976 struct cfdata *cf;
977 void *aux;
978 {
979 struct usb_attach_arg *uaa = aux;
980
981 if ((uaa->port != 0 &&
982 cf->uhubcf_port != UHUB_UNK_PORT &&
983 cf->uhubcf_port != uaa->port) ||
984 (uaa->configno != UHUB_UNK_CONFIGURATION &&
985 cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&
986 cf->uhubcf_configuration != uaa->configno) ||
987 (uaa->ifaceno != UHUB_UNK_INTERFACE &&
988 cf->uhubcf_interface != UHUB_UNK_INTERFACE &&
989 cf->uhubcf_interface != uaa->ifaceno))
990 return 0;
991 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
992 }
993
994 #elif defined(__FreeBSD__)
995 static void
996 usbd_bus_print_child(device_t bus, device_t dev)
997 {
998 /* FIXME print the device address and the configuration used
999 */
1000 }
1001 #endif
1002
1003 usbd_status
1004 usb_insert_transfer(reqh)
1005 usbd_request_handle reqh;
1006 {
1007 usbd_pipe_handle pipe = reqh->pipe;
1008 usbd_interface_handle iface = pipe->iface;
1009
1010 if (pipe->state == USBD_PIPE_IDLE ||
1011 (iface && iface->state == USBD_INTERFACE_IDLE))
1012 return (USBD_IS_IDLE);
1013 SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
1014 if (pipe->state != USBD_PIPE_ACTIVE ||
1015 (iface && iface->state != USBD_INTERFACE_ACTIVE))
1016 return (USBD_NOT_STARTED);
1017 if (pipe->running)
1018 return (USBD_IN_PROGRESS);
1019 pipe->running = 1;
1020 return (USBD_NORMAL_COMPLETION);
1021 }
1022
1023 void
1024 usb_start_next(pipe)
1025 usbd_pipe_handle pipe;
1026 {
1027 usbd_request_handle reqh;
1028 usbd_status r;
1029
1030 #ifdef DIAGNOSTIC
1031 if (SIMPLEQ_FIRST(&pipe->queue) == 0) {
1032 printf("usb_start_next: empty\n");
1033 return;
1034 }
1035 #endif
1036
1037 /* First remove remove old */
1038 SIMPLEQ_REMOVE_HEAD(&pipe->queue, SIMPLEQ_FIRST(&pipe->queue), next);
1039 if (pipe->state != USBD_PIPE_ACTIVE) {
1040 pipe->running = 0;
1041 return;
1042 }
1043 reqh = SIMPLEQ_FIRST(&pipe->queue);
1044 DPRINTFN(5, ("usb_start_next: start reqh=%p\n", reqh));
1045 if (!reqh)
1046 pipe->running = 0;
1047 else {
1048 r = pipe->methods->start(reqh);
1049 if (r != USBD_IN_PROGRESS) {
1050 printf("usb_start_next: error=%d\n", r);
1051 pipe->running = 0;
1052 /* XXX do what? */
1053 }
1054 }
1055 }
1056
1057 void
1058 usbd_fill_deviceinfo(dev, di)
1059 usbd_device_handle dev;
1060 struct usb_device_info *di;
1061 {
1062 struct usbd_port *p;
1063 int i, r, s;
1064
1065 di->config = dev->config;
1066 usbd_devinfo_vp(dev, di->vendor, di->product);
1067 usbd_printBCD(di->revision, UGETW(dev->ddesc.bcdDevice));
1068 di->class = dev->ddesc.bDeviceClass;
1069 di->power = dev->self_powered ? 0 : dev->power;
1070 di->lowspeed = dev->lowspeed;
1071 di->addr = dev->address;
1072 if (dev->hub) {
1073 for (i = 0;
1074 i < sizeof(di->ports) / sizeof(di->ports[0]) &&
1075 i < dev->hub->hubdesc.bNbrPorts;
1076 i++) {
1077 p = &dev->hub->ports[i];
1078 if (p->device)
1079 r = p->device->address;
1080 else {
1081 s = UGETW(p->status.wPortStatus);
1082 if (s & UPS_PORT_ENABLED)
1083 r = USB_PORT_ENABLED;
1084 else if (s & UPS_SUSPEND)
1085 r = USB_PORT_SUSPENDED;
1086 else if (s & UPS_PORT_POWER)
1087 r = USB_PORT_POWERED;
1088 else
1089 r = USB_PORT_DISABLED;
1090 }
1091 di->ports[i] = r;
1092 }
1093 di->nports = dev->hub->hubdesc.bNbrPorts;
1094 } else
1095 di->nports = 0;
1096 }
1097