Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / bus / usb / usb_subr.c
1 /*      $NetBSD: usb_subr.c,v 1.76 2000/04/27 15:26:50 augustss Exp $   */
2 /*      $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.23.2.8 2003/01/17 17:46:24 joe Exp $   */
3
4 /*
5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Lennart Augustsson (lennart@augustsson.net) at
10  * Carlstedt Research & Technology.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *        This product includes software developed by the NetBSD
23  *        Foundation, Inc. and its contributors.
24  * 4. Neither the name of The NetBSD Foundation nor the names of its
25  *    contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 #if defined(__NetBSD__) || defined(__OpenBSD__)
46 #include <sys/device.h>
47 #include <sys/select.h>
48 #elif defined(__FreeBSD__)
49 #include <sys/module.h>
50 #include <sys/bus.h>
51 #endif
52 #include <sys/proc.h>
53
54 #include <machine/bus.h>
55
56 #include <dev/usb/usb.h>
57
58 #include <dev/usb/usbdi.h>
59 #include <dev/usb/usbdi_util.h>
60 #include <dev/usb/usbdivar.h>
61 #include <dev/usb/usbdevs.h>
62 #include <dev/usb/usb_quirks.h>
63
64 #if defined(__FreeBSD__)
65 #include <machine/clock.h>
66 #define delay(d)         DELAY(d)
67 #endif
68
69 #ifdef USB_DEBUG
70 #define DPRINTF(x)      if (usbdebug) logprintf x
71 #define DPRINTFN(n,x)   if (usbdebug>(n)) logprintf x
72 extern int usbdebug;
73 #else
74 #define DPRINTF(x)
75 #define DPRINTFN(n,x)
76 #endif
77
78 Static usbd_status      usbd_set_config(usbd_device_handle, int);
79 Static char *usbd_get_string(usbd_device_handle, int, char *);
80 Static int usbd_getnewaddr(usbd_bus_handle bus);
81 #if defined(__NetBSD__)
82 Static int usbd_print(void *aux, const char *pnp);
83 Static int usbd_submatch(device_ptr_t, struct cfdata *cf, void *);
84 #elif defined(__OpenBSD__)
85 Static int usbd_submatch(device_ptr_t, void *, void *);
86 #endif
87 Static void usbd_free_iface_data(usbd_device_handle dev, int ifcno);
88 Static void usbd_kill_pipe(usbd_pipe_handle);
89 Static usbd_status usbd_probe_and_attach 
90         (device_ptr_t parent, usbd_device_handle dev, int port, int addr);
91
92 Static u_int32_t usb_cookie_no = 0;
93
94 #ifdef USBVERBOSE
95 typedef u_int16_t usb_vendor_id_t;
96 typedef u_int16_t usb_product_id_t;
97
98 /*
99  * Descriptions of of known vendors and devices ("products").
100  */
101 struct usb_knowndev {
102         usb_vendor_id_t         vendor;
103         usb_product_id_t        product;
104         int                     flags;
105         char                    *vendorname, *productname;
106 };
107 #define USB_KNOWNDEV_NOPROD     0x01            /* match on vendor only */
108
109 #include <dev/usb/usbdevs_data.h>
110 #endif /* USBVERBOSE */
111
112 Static const char *usbd_error_strs[] = {
113         "NORMAL_COMPLETION",
114         "IN_PROGRESS",
115         "PENDING_REQUESTS",
116         "NOT_STARTED",
117         "INVAL",
118         "NOMEM",
119         "CANCELLED",
120         "BAD_ADDRESS",
121         "IN_USE",
122         "NO_ADDR",
123         "SET_ADDR_FAILED",
124         "NO_POWER",
125         "TOO_DEEP",
126         "IOERROR",
127         "NOT_CONFIGURED",
128         "TIMEOUT",
129         "SHORT_XFER",
130         "STALLED",
131         "INTERRUPTED",
132         "XXX",
133 };
134
135 const char *
136 usbd_errstr(usbd_status err)
137 {
138         static char buffer[5];
139
140         if (err < USBD_ERROR_MAX) {
141                 return usbd_error_strs[err];
142         } else {
143                 snprintf(buffer, sizeof buffer, "%d", err);
144                 return buffer;
145         }
146 }
147
148 usbd_status
149 usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid,
150                      usb_string_descriptor_t *sdesc)
151 {
152         usb_device_request_t req;
153         usbd_status err;
154         int actlen;
155
156         req.bmRequestType = UT_READ_DEVICE;
157         req.bRequest = UR_GET_DESCRIPTOR;
158         USETW2(req.wValue, UDESC_STRING, sindex);
159         USETW(req.wIndex, langid);
160         USETW(req.wLength, 2);  /* only size byte first */
161         err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
162                 &actlen);
163         if (err)
164                 return (err);
165
166         if (actlen < 1)
167                 return (USBD_SHORT_XFER);
168
169         USETW(req.wLength, sdesc->bLength);     /* the whole string */
170         return (usbd_do_request(dev, &req, sdesc));
171 }
172
173 char *
174 usbd_get_string(usbd_device_handle dev, int si, char *buf)
175 {
176         int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE;
177         usb_string_descriptor_t us;
178         char *s;
179         int i, n;
180         u_int16_t c;
181         usbd_status err;
182
183         if (si == 0)
184                 return (0);
185         if (dev->quirks->uq_flags & UQ_NO_STRINGS)
186                 return (0);
187         if (dev->langid == USBD_NOLANG) {
188                 /* Set up default language */
189                 err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us);
190                 if (err || us.bLength < 4) {
191                         dev->langid = 0; /* Well, just pick English then */
192                 } else {
193                         /* Pick the first language as the default. */
194                         dev->langid = UGETW(us.bString[0]);
195                 }
196         }
197         err = usbd_get_string_desc(dev, si, dev->langid, &us);
198         if (err)
199                 return (0);
200         s = buf;
201         n = us.bLength / 2 - 1;
202         for (i = 0; i < n; i++) {
203                 c = UGETW(us.bString[i]);
204                 /* Convert from Unicode, handle buggy strings. */
205                 if ((c & 0xff00) == 0)
206                         *s++ = c;
207                 else if ((c & 0x00ff) == 0 && swap)
208                         *s++ = c >> 8;
209                 else 
210                         *s++ = '?';
211         }
212         *s++ = 0;
213         return (buf);
214 }
215
216 void
217 usbd_devinfo_vp(usbd_device_handle dev, char *v, char *p)
218 {
219         usb_device_descriptor_t *udd = &dev->ddesc;
220         char *vendor = 0, *product = 0;
221 #ifdef USBVERBOSE
222         struct usb_knowndev *kdp;
223 #endif
224
225         if (dev == NULL) {
226                 v[0] = p[0] = '\0';
227                 return;
228         }
229
230         vendor = usbd_get_string(dev, udd->iManufacturer, v);
231         product = usbd_get_string(dev, udd->iProduct, p);
232 #ifdef USBVERBOSE
233         if (vendor == NULL || product == NULL) {
234                 for(kdp = usb_knowndevs;
235                     kdp->vendorname != NULL;
236                     kdp++) {
237                         if (kdp->vendor == UGETW(udd->idVendor) && 
238                             (kdp->product == UGETW(udd->idProduct) ||
239                              (kdp->flags & USB_KNOWNDEV_NOPROD) != 0))
240                                 break;
241                 }
242                 if (kdp->vendorname != NULL) {
243                         if (!vendor)
244                         vendor = kdp->vendorname;
245                         if (!product)
246                         product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ?
247                                 kdp->productname : NULL;
248                 }
249         }
250 #endif
251         if (vendor != NULL)
252                 strcpy(v, vendor);
253         else
254                 sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
255         if (product != NULL)
256                 strcpy(p, product);
257         else
258                 sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
259 }
260
261 int
262 usbd_printBCD(char *cp, int bcd)
263 {
264         return (sprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff));
265 }
266
267 void
268 usbd_devinfo(usbd_device_handle dev, int showclass, char *cp)
269 {
270         usb_device_descriptor_t *udd = &dev->ddesc;
271         char vendor[USB_MAX_STRING_LEN];
272         char product[USB_MAX_STRING_LEN];
273         int bcdDevice, bcdUSB;
274
275         usbd_devinfo_vp(dev, vendor, product);
276         cp += sprintf(cp, "%s %s", vendor, product);
277         if (showclass)
278                 cp += sprintf(cp, ", class %d/%d",
279                               udd->bDeviceClass, udd->bDeviceSubClass);
280         bcdUSB = UGETW(udd->bcdUSB);
281         bcdDevice = UGETW(udd->bcdDevice);
282         cp += sprintf(cp, ", rev ");
283         cp += usbd_printBCD(cp, bcdUSB);
284         *cp++ = '/';
285         cp += usbd_printBCD(cp, bcdDevice);
286         cp += sprintf(cp, ", addr %d", dev->address);
287         *cp = 0;
288 }
289
290 /* Delay for a certain number of ms */
291 void
292 usb_delay_ms(usbd_bus_handle bus, u_int ms)
293 {
294         /* Wait at least two clock ticks so we know the time has passed. */
295         if (bus->use_polling || cold)
296                 delay((ms+1) * 1000);
297         else
298                 tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
299 }
300
301 /* Delay given a device handle. */
302 void
303 usbd_delay_ms(usbd_device_handle dev, u_int ms)
304 {
305         usb_delay_ms(dev->bus, ms);
306 }
307
308 usbd_status
309 usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps)
310 {
311         usb_device_request_t req;
312         usbd_status err;
313         int n;
314         
315         req.bmRequestType = UT_WRITE_CLASS_OTHER;
316         req.bRequest = UR_SET_FEATURE;
317         USETW(req.wValue, UHF_PORT_RESET);
318         USETW(req.wIndex, port);
319         USETW(req.wLength, 0);
320         err = usbd_do_request(dev, &req, 0);
321         DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n",
322                     port, usbd_errstr(err)));
323         if (err)
324                 return (err);
325         n = 10;
326         do {
327                 /* Wait for device to recover from reset. */
328                 usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
329                 err = usbd_get_port_status(dev, port, ps);
330                 if (err) {
331                         DPRINTF(("usbd_reset_port: get status failed %d\n",
332                                  err));
333                         return (err);
334                 }
335         } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
336         if (n == 0)
337                 return (USBD_TIMEOUT);
338         err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
339 #ifdef USB_DEBUG
340         if (err)
341                 DPRINTF(("usbd_reset_port: clear port feature failed %d\n",
342                          err));
343 #endif
344
345         /* Wait for the device to recover from reset. */
346         usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
347         return (err);
348 }
349
350 usb_interface_descriptor_t *
351 usbd_find_idesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx)
352 {
353         char *p = (char *)cd;
354         char *end = p + UGETW(cd->wTotalLength);
355         usb_interface_descriptor_t *d;
356         int curidx, lastidx, curaidx = 0;
357
358         for (curidx = lastidx = -1; p < end; ) {
359                 d = (usb_interface_descriptor_t *)p;
360                 DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
361                             "type=%d\n", 
362                             ifaceidx, curidx, altidx, curaidx,
363                             d->bLength, d->bDescriptorType));
364                 if (d->bLength == 0) /* bad descriptor */
365                         break;
366                 p += d->bLength;
367                 if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
368                         if (d->bInterfaceNumber != lastidx) {
369                                 lastidx = d->bInterfaceNumber;
370                                 curidx++;
371                                 curaidx = 0;
372                         } else
373                                 curaidx++;
374                         if (ifaceidx == curidx && altidx == curaidx)
375                                 return (d);
376                 }
377         }
378         return (NULL);
379 }
380
381 usb_endpoint_descriptor_t *
382 usbd_find_edesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx, 
383                 int endptidx)
384 {
385         char *p = (char *)cd;
386         char *end = p + UGETW(cd->wTotalLength);
387         usb_interface_descriptor_t *d;
388         usb_endpoint_descriptor_t *e;
389         int curidx;
390
391         d = usbd_find_idesc(cd, ifaceidx, altidx);
392         if (d == NULL)
393                 return (NULL);
394         if (endptidx >= d->bNumEndpoints) /* quick exit */
395                 return (NULL);
396
397         curidx = -1;
398         for (p = (char *)d + d->bLength; p < end; ) {
399                 e = (usb_endpoint_descriptor_t *)p;
400                 if (e->bLength == 0) /* bad descriptor */
401                         break;
402                 p += e->bLength;
403                 if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
404                         return (NULL);
405                 if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
406                         curidx++;
407                         if (curidx == endptidx)
408                                 return (e);
409                 }
410         }
411         return (NULL);
412 }
413
414 usbd_status
415 usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx)
416 {
417         usbd_interface_handle ifc = &dev->ifaces[ifaceidx];
418         char *p, *end;
419         int endpt, nendpt;
420
421         DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
422                     ifaceidx, altidx));
423         ifc->device = dev;
424         ifc->idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
425         if (ifc->idesc == 0)
426                 return (USBD_INVAL);
427         ifc->index = ifaceidx;
428         ifc->altindex = altidx;
429         nendpt = ifc->idesc->bNumEndpoints;
430         DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
431         if (nendpt != 0) {
432                 ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
433                                         M_USB, M_NOWAIT);
434                 if (ifc->endpoints == NULL)
435                         return (USBD_NOMEM);
436         } else
437                 ifc->endpoints = NULL;
438         ifc->priv = NULL;
439         p = (char *)ifc->idesc + ifc->idesc->bLength;
440         end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
441 #define ed ((usb_endpoint_descriptor_t *)p)
442         for (endpt = 0; endpt < nendpt; endpt++) {
443                 DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt));
444                 for (; p < end; p += ed->bLength) {
445                         ed = (usb_endpoint_descriptor_t *)p;
446                         DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p "
447                                      "len=%d type=%d\n",
448                                  p, end, ed->bLength, ed->bDescriptorType));
449                         if (p + ed->bLength <= end && ed->bLength != 0 &&
450                             ed->bDescriptorType == UDESC_ENDPOINT)
451                                 goto found;
452                         if (ed->bLength == 0 ||
453                             ed->bDescriptorType == UDESC_INTERFACE)
454                                 break;
455                 }
456                 /* passed end, or bad desc */
457                 DPRINTF(("usbd_fill_iface_data: bad descriptor(s): %s\n",
458                          ed->bLength == 0 ? "0 length" :
459                          ed->bDescriptorType == UDESC_INTERFACE ? "iface desc":
460                          "out of data"));
461                 goto bad;
462         found:
463                 ifc->endpoints[endpt].edesc = ed;
464                 ifc->endpoints[endpt].refcnt = 0;
465                 p += ed->bLength;
466         }
467 #undef ed
468         LIST_INIT(&ifc->pipes);
469         return (USBD_NORMAL_COMPLETION);
470
471  bad:
472         if (ifc->endpoints != NULL)
473                 free(ifc->endpoints, M_USB);
474         return (USBD_INVAL);
475 }
476
477 void
478 usbd_free_iface_data(usbd_device_handle dev, int ifcno)
479 {
480         usbd_interface_handle ifc = &dev->ifaces[ifcno];
481         if (ifc->endpoints)
482                 free(ifc->endpoints, M_USB);
483 }
484
485 Static usbd_status
486 usbd_set_config(usbd_device_handle dev, int conf)
487 {
488         usb_device_request_t req;
489
490         req.bmRequestType = UT_WRITE_DEVICE;
491         req.bRequest = UR_SET_CONFIG;
492         USETW(req.wValue, conf);
493         USETW(req.wIndex, 0);
494         USETW(req.wLength, 0);
495         return (usbd_do_request(dev, &req, 0));
496 }
497
498 usbd_status
499 usbd_set_config_no(usbd_device_handle dev, int no, int msg)
500 {
501         int index;
502         usb_config_descriptor_t cd;
503         usbd_status err;
504
505         if (no == USB_UNCONFIG_NO)
506                 return (usbd_set_config_index(dev, USB_UNCONFIG_INDEX, msg));
507
508         DPRINTFN(5,("usbd_set_config_no: %d\n", no));
509         /* Figure out what config index to use. */
510         for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
511                 err = usbd_get_config_desc(dev, index, &cd);
512                 if (err)
513                         return (err);
514                 if (cd.bConfigurationValue == no)
515                         return (usbd_set_config_index(dev, index, msg));
516         }
517         return (USBD_INVAL);
518 }
519
520 usbd_status
521 usbd_set_config_index(usbd_device_handle dev, int index, int msg)
522 {
523         usb_status_t ds;
524         usb_config_descriptor_t cd, *cdp;
525         usbd_status err;
526         int ifcidx, nifc, len, selfpowered, power;
527
528         DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
529
530         /* XXX check that all interfaces are idle */
531         if (dev->config != USB_UNCONFIG_NO) {
532                 DPRINTF(("usbd_set_config_index: free old config\n"));
533                 /* Free all configuration data structures. */
534                 nifc = dev->cdesc->bNumInterface;
535                 for (ifcidx = 0; ifcidx < nifc; ifcidx++)
536                         usbd_free_iface_data(dev, ifcidx);
537                 free(dev->ifaces, M_USB);
538                 free(dev->cdesc, M_USB);
539                 dev->ifaces = NULL;
540                 dev->cdesc = NULL;
541                 dev->config = USB_UNCONFIG_NO;
542         }
543
544         if (index == USB_UNCONFIG_INDEX) {
545                 /* We are unconfiguring the device, so leave unallocated. */
546                 DPRINTF(("usbd_set_config_index: set config 0\n"));
547                 err = usbd_set_config(dev, USB_UNCONFIG_NO);
548                 if (err)
549                         DPRINTF(("usbd_set_config_index: setting config=0 "
550                                  "failed, error=%s\n", usbd_errstr(err)));
551                 return (err);
552         }
553
554         /* Get the short descriptor. */
555         err = usbd_get_config_desc(dev, index, &cd);
556         if (err)
557                 return (err);
558         len = UGETW(cd.wTotalLength);
559         cdp = malloc(len, M_USB, M_NOWAIT);
560         if (cdp == NULL)
561                 return (USBD_NOMEM);
562         /* Get the full descriptor. */
563         err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
564         if (err)
565                 goto bad;
566         if (cdp->bDescriptorType != UDESC_CONFIG) {
567                 DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
568                              cdp->bDescriptorType));
569                 err = USBD_INVAL;
570                 goto bad;
571         }
572
573         /* Figure out if the device is self or bus powered. */
574         selfpowered = 0;
575         if (!(dev->quirks->uq_flags & UQ_BUS_POWERED) &&
576             (cdp->bmAttributes & UC_SELF_POWERED)) {
577                 /* May be self powered. */
578                 if (cdp->bmAttributes & UC_BUS_POWERED) {
579                         /* Must ask device. */
580                         err = usbd_get_device_status(dev, &ds);
581                         if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED))
582                                 selfpowered = 1;
583                         DPRINTF(("usbd_set_config_index: status=0x%04x, "
584                                  "error=%s\n",
585                                  UGETW(ds.wStatus), usbd_errstr(err)));
586                 } else
587                         selfpowered = 1;
588         }
589         DPRINTF(("usbd_set_config_index: (addr %d) attr=0x%02x, "
590                  "selfpowered=%d, power=%d\n", 
591                  dev->address, cdp->bmAttributes, 
592                  selfpowered, cdp->bMaxPower * 2));
593
594         /* Check if we have enough power. */
595 #ifdef USB_DEBUG
596         if (dev->powersrc == NULL) {
597                 DPRINTF(("usbd_set_config_index: No power source?\n"));
598                 return (USBD_IOERROR);
599         }
600 #endif
601         power = cdp->bMaxPower * 2;
602         if (power > dev->powersrc->power) {
603                 /* XXX print nicer message. */
604                 if (msg)
605                         printf("%s: device addr %d (config %d) exceeds power "
606                                  "budget, %d mA > %d mA\n",
607                                USBDEVNAME(dev->bus->bdev), dev->address, 
608                                cdp->bConfigurationValue, 
609                                power, dev->powersrc->power);
610                 err = USBD_NO_POWER;
611                 goto bad;
612         }
613         dev->power = power;
614         dev->self_powered = selfpowered;
615
616         /* Set the actual configuration value. */
617         DPRINTF(("usbd_set_config_index: set config %d\n",
618                  cdp->bConfigurationValue));
619         err = usbd_set_config(dev, cdp->bConfigurationValue);
620         if (err) {
621                 DPRINTF(("usbd_set_config_index: setting config=%d failed, "
622                          "error=%s\n",
623                          cdp->bConfigurationValue, usbd_errstr(err)));
624                 goto bad;
625         }
626
627         /* Allocate and fill interface data. */
628         nifc = cdp->bNumInterface;
629         dev->ifaces = malloc(nifc * sizeof(struct usbd_interface), 
630                              M_USB, M_NOWAIT);
631         if (dev->ifaces == NULL) {
632                 err = USBD_NOMEM;
633                 goto bad;
634         }
635         DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
636         dev->cdesc = cdp;
637         dev->config = cdp->bConfigurationValue;
638         for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
639                 err = usbd_fill_iface_data(dev, ifcidx, 0);
640                 if (err) {
641                         while (--ifcidx >= 0)
642                                 usbd_free_iface_data(dev, ifcidx);
643                         goto bad;
644                 }
645         }
646
647         return (USBD_NORMAL_COMPLETION);
648
649  bad:
650         free(cdp, M_USB);
651         return (err);
652 }
653
654 /* XXX add function for alternate settings */
655
656 usbd_status
657 usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface,
658                 struct usbd_endpoint *ep, int ival, usbd_pipe_handle *pipe)
659 {
660         usbd_pipe_handle p;
661         usbd_status err;
662
663         DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
664                     dev, iface, ep, pipe));
665         p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
666         if (p == NULL)
667                 return (USBD_NOMEM);
668         p->device = dev;
669         p->iface = iface;
670         p->endpoint = ep;
671         ep->refcnt++;
672         p->refcnt = 1;
673         p->intrxfer = 0;
674         p->running = 0;
675         p->repeat = 0;
676         p->interval = ival;
677         SIMPLEQ_INIT(&p->queue);
678         err = dev->bus->methods->open_pipe(p);
679         if (err) {
680                 DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
681                          "%s\n",
682                          ep->edesc->bEndpointAddress, usbd_errstr(err)));
683                 free(p, M_USB);
684                 return (err);
685         }
686         /* Clear any stall and make sure DATA0 toggle will be used next. */
687         if (UE_GET_ADDR(ep->edesc->bEndpointAddress) != USB_CONTROL_ENDPOINT)
688                 usbd_clear_endpoint_stall(p);
689         *pipe = p;
690         return (USBD_NORMAL_COMPLETION);
691 }
692
693 /* Abort the device control pipe. */
694 void
695 usbd_kill_pipe(usbd_pipe_handle pipe)
696 {
697         pipe->methods->close(pipe);
698         pipe->endpoint->refcnt--;
699         free(pipe, M_USB);
700 }
701
702 int
703 usbd_getnewaddr(usbd_bus_handle bus)
704 {
705         int addr;
706
707         for (addr = 1; addr < USB_MAX_DEVICES; addr++)
708                 if (bus->devices[addr] == 0)
709                         return (addr);
710         return (-1);
711 }
712
713
714 usbd_status
715 usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
716                       int port, int addr)
717 {
718         struct usb_attach_arg uaa;
719         usb_device_descriptor_t *dd = &dev->ddesc;
720         int found, i, confi, nifaces;
721         usbd_status err;
722         device_ptr_t dv;
723         usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
724
725 #if defined(__FreeBSD__)
726         /* 
727          * XXX uaa is a static var. Not a problem as it _should_ be used only
728          * during probe and attach. Should be changed however.
729          */
730         device_t bdev;
731         bdev = device_add_child(parent, NULL, -1);
732         device_set_ivars(bdev, &uaa);
733         if (!bdev) {
734             printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
735             return (USBD_INVAL);
736         }
737         device_quiet(bdev);
738 #endif
739
740         uaa.device = dev;
741         uaa.iface = NULL;
742         uaa.ifaces = NULL;
743         uaa.nifaces = 0;
744         uaa.usegeneric = 0;
745         uaa.port = port;
746         uaa.configno = UHUB_UNK_CONFIGURATION;
747         uaa.ifaceno = UHUB_UNK_INTERFACE;
748         uaa.vendor = UGETW(dd->idVendor);
749         uaa.product = UGETW(dd->idProduct);
750         uaa.release = UGETW(dd->bcdDevice);
751
752         /* First try with device specific drivers. */
753         DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
754         dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
755         if (dv) {
756                 dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
757                 if (dev->subdevs == NULL)
758                         return (USBD_NOMEM);
759                 dev->subdevs[0] = dv;
760                 dev->subdevs[1] = 0;
761                 return (USBD_NORMAL_COMPLETION);
762         }
763
764         DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
765
766         DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
767                  dd->bNumConfigurations));
768         /* Next try with interface drivers. */
769         for (confi = 0; confi < dd->bNumConfigurations; confi++) {
770                 DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
771                             confi));
772                 err = usbd_set_config_index(dev, confi, 1);
773                 if (err) {
774 #ifdef USB_DEBUG
775                         DPRINTF(("%s: port %d, set config at addr %d failed, "
776                                  "error=%s\n", USBDEVPTRNAME(parent), port,
777                                  addr, usbd_errstr(err)));
778 #else
779                         printf("%s: port %d, set config at addr %d failed\n",
780                                USBDEVPTRNAME(parent), port, addr);
781 #endif
782 #if defined(__FreeBSD__)
783                         device_delete_child(parent, bdev);
784 #endif
785
786                         return (err);
787                 }
788                 nifaces = dev->cdesc->bNumInterface;
789                 uaa.configno = dev->cdesc->bConfigurationValue;
790                 for (i = 0; i < nifaces; i++)
791                         ifaces[i] = &dev->ifaces[i];
792                 uaa.ifaces = ifaces;
793                 uaa.nifaces = nifaces;
794                 dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);
795                 if (dev->subdevs == NULL) {
796 #if defined(__FreeBSD__)
797                         device_delete_child(parent, bdev);
798 #endif
799                         return (USBD_NOMEM);
800                 }
801
802                 found = 0;
803                 for (i = 0; i < nifaces; i++) {
804                         if (ifaces[i] == NULL)
805                                 continue; /* interface already claimed */
806                         uaa.iface = ifaces[i];
807                         uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
808                         dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
809                                            usbd_submatch);
810                         if (dv != NULL) {
811                                 dev->subdevs[found++] = dv;
812                                 dev->subdevs[found] = 0;
813                                 ifaces[i] = 0; /* consumed */
814
815 #if defined(__FreeBSD__)
816                                 /* create another child for the next iface */
817                                 bdev = device_add_child(parent, NULL, -1);
818                                 device_set_ivars(bdev, &uaa);
819                                 if (!bdev) {
820                                         printf("%s: Device creation failed\n",
821                                         USBDEVNAME(dev->bus->bdev));
822                                         return (USBD_NORMAL_COMPLETION);
823                                 }
824                                 device_quiet(bdev);
825 #endif
826                         }
827                 }
828                 if (found != 0) {
829 #if defined(__FreeBSD__)
830                         /* remove the last created child again; it is unused */
831                         device_delete_child(parent, bdev);
832 #endif
833                         return (USBD_NORMAL_COMPLETION);
834                 }
835                 free(dev->subdevs, M_USB);
836                 dev->subdevs = 0;
837         }
838         /* No interfaces were attached in any of the configurations. */
839
840         if (dd->bNumConfigurations > 1) /* don't change if only 1 config */
841                 usbd_set_config_index(dev, 0, 0);
842
843         DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
844
845         /* Finally try the generic driver. */
846         uaa.iface = NULL;
847         uaa.usegeneric = 1;
848         uaa.configno = UHUB_UNK_CONFIGURATION;
849         uaa.ifaceno = UHUB_UNK_INTERFACE;
850         uaa.vendor = UHUB_UNK_VENDOR;
851         uaa.product = UHUB_UNK_PRODUCT;
852         uaa.release = UHUB_UNK_RELEASE;
853         dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
854         if (dv != NULL) {
855                 dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
856                 if (dev->subdevs == 0)
857                         return (USBD_NOMEM);
858                 dev->subdevs[0] = dv;
859                 dev->subdevs[1] = 0;
860                 return (USBD_NORMAL_COMPLETION);
861         }
862
863         /* 
864          * The generic attach failed, but leave the device as it is.
865          * We just did not find any drivers, that's all.  The device is
866          * fully operational and not harming anyone.
867          */
868         DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
869 #if defined(__FreeBSD__)
870         device_delete_child(parent, bdev);
871 #endif
872         return (USBD_NORMAL_COMPLETION);
873 }
874
875
876 /*
877  * Called when a new device has been put in the powered state,
878  * but not yet in the addressed state.
879  * Get initial descriptor, set the address, get full descriptor,
880  * and attach a driver.
881  */
882 usbd_status
883 usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth,
884                 int lowspeed, int port, struct usbd_port *up)
885 {
886         usbd_device_handle dev;
887         usb_device_descriptor_t *dd;
888         usbd_status err;
889         int addr;
890         int i;
891
892         DPRINTF(("usbd_new_device bus=%p port=%d depth=%d lowspeed=%d\n",
893                  bus, port, depth, lowspeed));
894         addr = usbd_getnewaddr(bus);
895         if (addr < 0) {
896                 printf("%s: No free USB addresses, new device ignored.\n", 
897                        USBDEVNAME(bus->bdev));
898                 return (USBD_NO_ADDR);
899         }
900
901         dev = malloc(sizeof *dev, M_USB, M_NOWAIT);
902         if (dev == NULL)
903                 return (USBD_NOMEM);
904         memset(dev, 0, sizeof(*dev));
905
906         dev->bus = bus;
907
908         /* Set up default endpoint handle. */
909         dev->def_ep.edesc = &dev->def_ep_desc;
910
911         /* Set up default endpoint descriptor. */
912         dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
913         dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
914         dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
915         dev->def_ep_desc.bmAttributes = UE_CONTROL;
916         USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
917         dev->def_ep_desc.bInterval = 0;
918
919         dev->quirks = &usbd_no_quirk;
920         dev->address = USB_START_ADDR;
921         dev->ddesc.bMaxPacketSize = 0;
922         dev->lowspeed = lowspeed != 0;
923         dev->depth = depth;
924         dev->powersrc = up;
925         dev->langid = USBD_NOLANG;
926         dev->cookie.cookie = ++usb_cookie_no;
927
928         /* Establish the default pipe. */
929         err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
930                               &dev->default_pipe);
931         if (err) {
932                 usbd_remove_device(dev, up);
933                 return (err);
934         }
935
936         up->device = dev;
937         dd = &dev->ddesc;
938         /* Try a few times in case the device is slow (i.e. outside specs.) */
939         for (i = 0; i < 3; i++) {
940                 /* Get the first 8 bytes of the device descriptor. */
941                 err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
942                 if (!err)
943                         break;
944                 usbd_delay_ms(dev, 200);
945         }
946         if (err) {
947                 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
948                               "failed\n", addr));
949                 usbd_remove_device(dev, up);
950                 return (err);
951         }
952
953         DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
954                  "subclass=%d, protocol=%d, maxpacket=%d, len=%d, ls=%d\n", 
955                  addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
956                  dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength, 
957                  dev->lowspeed));
958
959         if (dd->bDescriptorType != UDESC_DEVICE) {
960                 /* Illegal device descriptor */
961                 DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
962                              dd->bDescriptorType));
963                 usbd_remove_device(dev, up);
964                 return (USBD_INVAL);
965         }
966
967         if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) {
968                 DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength));
969                 usbd_remove_device(dev, up);
970                 return (USBD_INVAL);
971         }
972
973         USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
974
975         err = usbd_reload_device_desc(dev);
976         if (err) {
977                 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
978                               "failed\n", addr));
979                 usbd_remove_device(dev, up);
980                 return (err);
981         }
982
983         /* Set the address */
984         err = usbd_set_address(dev, addr);
985         DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
986         if (err) {
987                 DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
988                 err = USBD_SET_ADDR_FAILED;
989                 usbd_remove_device(dev, up);
990                 return (err);
991         }
992         /* Allow device time to set new address */
993         usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
994
995         dev->address = addr;    /* New device address now */
996         bus->devices[addr] = dev;
997
998         /* Assume 100mA bus powered for now. Changed when configured. */
999         dev->power = USB_MIN_POWER;
1000         dev->self_powered = 0;
1001
1002         DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n", 
1003                  addr, dev, parent));
1004
1005         err = usbd_probe_and_attach(parent, dev, port, addr);
1006         if (err) {
1007                 usbd_remove_device(dev, up);
1008                 return (err);
1009         }
1010   
1011         usbd_add_event(USB_EVENT_DEVICE_ATTACH, dev);
1012         return (USBD_NORMAL_COMPLETION);
1013 }
1014
1015 usbd_status
1016 usbd_reload_device_desc(usbd_device_handle dev)
1017 {
1018         usbd_status err;
1019         int i;
1020
1021         /* Get the full device descriptor. */
1022         for (i = 0; i < 3; ++i) {
1023                 err = usbd_get_device_desc(dev, &dev->ddesc);
1024                 if (!err)
1025                         break;
1026                 usbd_delay_ms(dev, 200);
1027         }
1028         if (err)
1029                 return (err);
1030
1031         /* Figure out what's wrong with this device. */
1032         dev->quirks = usbd_find_quirk(&dev->ddesc);
1033
1034         return (USBD_NORMAL_COMPLETION);
1035 }
1036
1037 void
1038 usbd_remove_device(usbd_device_handle dev, struct usbd_port *up)
1039 {
1040         DPRINTF(("usbd_remove_device: %p\n", dev));
1041   
1042         if (dev->default_pipe != NULL)
1043                 usbd_kill_pipe(dev->default_pipe);
1044         up->device = 0;
1045         dev->bus->devices[dev->address] = 0;
1046
1047         free(dev, M_USB);
1048 }
1049
1050 #if defined(__NetBSD__) || defined(__OpenBSD__)
1051 int
1052 usbd_print(void *aux, const char *pnp)
1053 {
1054         struct usb_attach_arg *uaa = aux;
1055         char devinfo[1024];
1056
1057         DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
1058         if (pnp) {
1059                 if (!uaa->usegeneric)
1060                         return (QUIET);
1061                 usbd_devinfo(uaa->device, 1, devinfo);
1062                 printf("%s, %s", devinfo, pnp);
1063         }
1064         if (uaa->port != 0)
1065                 printf(" port %d", uaa->port);
1066         if (uaa->configno != UHUB_UNK_CONFIGURATION)
1067                 printf(" configuration %d", uaa->configno);
1068         if (uaa->ifaceno != UHUB_UNK_INTERFACE)
1069                 printf(" interface %d", uaa->ifaceno);
1070 #if 0
1071         /* 
1072          * It gets very crowded with these locators on the attach line.
1073          * They are not really needed since they are printed in the clear
1074          * by each driver.
1075          */
1076         if (uaa->vendor != UHUB_UNK_VENDOR)
1077                 printf(" vendor 0x%04x", uaa->vendor);
1078         if (uaa->product != UHUB_UNK_PRODUCT)
1079                 printf(" product 0x%04x", uaa->product);
1080         if (uaa->release != UHUB_UNK_RELEASE)
1081                 printf(" release 0x%04x", uaa->release);
1082 #endif
1083         return (UNCONF);
1084 }
1085
1086 #if defined(__NetBSD__)
1087 int
1088 usbd_submatch(struct device *parent, struct cfdata *cf, void *aux)
1089 {
1090 #elif defined(__OpenBSD__)
1091 int
1092 usbd_submatch(struct device *parent, void *match, void *aux)
1093 {
1094         struct cfdata *cf = match;
1095 #endif
1096         struct usb_attach_arg *uaa = aux;
1097
1098         DPRINTFN(5,("usbd_submatch port=%d,%d configno=%d,%d "
1099             "ifaceno=%d,%d vendor=%d,%d product=%d,%d release=%d,%d\n",
1100             uaa->port, cf->uhubcf_port,
1101             uaa->configno, cf->uhubcf_configuration,
1102             uaa->ifaceno, cf->uhubcf_interface,
1103             uaa->vendor, cf->uhubcf_vendor,
1104             uaa->product, cf->uhubcf_product,
1105             uaa->release, cf->uhubcf_release));
1106         if (uaa->port != 0 &&   /* root hub has port 0, it should match */
1107             ((uaa->port != 0 &&
1108              cf->uhubcf_port != UHUB_UNK_PORT &&
1109              cf->uhubcf_port != uaa->port) ||
1110             (uaa->configno != UHUB_UNK_CONFIGURATION &&
1111              cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&
1112              cf->uhubcf_configuration != uaa->configno) ||
1113             (uaa->ifaceno != UHUB_UNK_INTERFACE &&
1114              cf->uhubcf_interface != UHUB_UNK_INTERFACE &&
1115              cf->uhubcf_interface != uaa->ifaceno) ||
1116             (uaa->vendor != UHUB_UNK_VENDOR &&
1117              cf->uhubcf_vendor != UHUB_UNK_VENDOR &&
1118              cf->uhubcf_vendor != uaa->vendor) ||
1119             (uaa->product != UHUB_UNK_PRODUCT &&
1120              cf->uhubcf_product != UHUB_UNK_PRODUCT &&
1121              cf->uhubcf_product != uaa->product) ||
1122             (uaa->release != UHUB_UNK_RELEASE &&
1123              cf->uhubcf_release != UHUB_UNK_RELEASE &&
1124              cf->uhubcf_release != uaa->release)
1125            )
1126            )
1127                 return 0;
1128         return ((*cf->cf_attach->ca_match)(parent, cf, aux));
1129 }
1130
1131 #endif
1132
1133 void
1134 usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di)
1135 {
1136         struct usbd_port *p;
1137         int i, err, s;
1138
1139         di->udi_bus = USBDEVUNIT(dev->bus->bdev);
1140         di->udi_addr = dev->address;
1141
1142         if (dev->subdevs) {
1143                 for (i = 0; dev->subdevs[i] &&
1144                             i < USB_MAX_DEVNAMES; i++) {
1145                         strncpy(di->udi_devnames[i], USBDEVPTRNAME(dev->subdevs[i]),
1146                                 USB_MAX_DEVNAMELEN);
1147                         di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0'; /* terminate */
1148                 }
1149         } else {
1150                 i = 0;
1151         }
1152         for (/*i is set */; i < USB_MAX_DEVNAMES; i++)
1153                 di->udi_devnames[i][0] = 0;                     /* empty */
1154
1155         usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product);
1156         usbd_printBCD(di->udi_release, UGETW(dev->ddesc.bcdDevice));
1157         di->udi_vendorNo = UGETW(dev->ddesc.idVendor);
1158         di->udi_productNo = UGETW(dev->ddesc.idProduct);
1159         di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice);
1160         di->udi_class = dev->ddesc.bDeviceClass;
1161         di->udi_subclass = dev->ddesc.bDeviceSubClass;
1162         di->udi_protocol = dev->ddesc.bDeviceProtocol;
1163         di->udi_config = dev->config;
1164         di->udi_power = dev->self_powered ? 0 : dev->power;
1165         di->udi_lowspeed = dev->lowspeed;
1166
1167         if (dev->hub) {
1168                 for (i = 0; 
1169                      i < sizeof(di->udi_ports) / sizeof(di->udi_ports[0]) &&
1170                              i < dev->hub->hubdesc.bNbrPorts;
1171                      i++) {
1172                         p = &dev->hub->ports[i];
1173                         if (p->device)
1174                                 err = p->device->address;
1175                         else {
1176                                 s = UGETW(p->status.wPortStatus);
1177                                 if (s & UPS_PORT_ENABLED)
1178                                         err = USB_PORT_ENABLED;
1179                                 else if (s & UPS_SUSPEND)
1180                                         err = USB_PORT_SUSPENDED;
1181                                 else if (s & UPS_PORT_POWER)
1182                                         err = USB_PORT_POWERED;
1183                                 else
1184                                         err = USB_PORT_DISABLED;
1185                         }
1186                         di->udi_ports[i] = err;
1187                 }
1188                 di->udi_nports = dev->hub->hubdesc.bNbrPorts;
1189         } else
1190                 di->udi_nports = 0;
1191 }
1192
1193 void
1194 usb_free_device(usbd_device_handle dev)
1195 {
1196         int ifcidx, nifc;
1197
1198         if (dev->default_pipe != NULL)
1199                 usbd_kill_pipe(dev->default_pipe);
1200         if (dev->ifaces != NULL) {
1201                 nifc = dev->cdesc->bNumInterface;
1202                 for (ifcidx = 0; ifcidx < nifc; ifcidx++)
1203                         usbd_free_iface_data(dev, ifcidx);
1204                 free(dev->ifaces, M_USB);
1205         }
1206         if (dev->cdesc != NULL)
1207                 free(dev->cdesc, M_USB);
1208         if (dev->subdevs != NULL)
1209                 free(dev->subdevs, M_USB);
1210         free(dev, M_USB);
1211 }
1212
1213 /*
1214  * The general mechanism for detaching drivers works as follows: Each
1215  * driver is responsible for maintaining a reference count on the
1216  * number of outstanding references to its softc (e.g.  from
1217  * processing hanging in a read or write).  The detach method of the
1218  * driver decrements this counter and flags in the softc that the
1219  * driver is dying and then wakes any sleepers.  It then sleeps on the
1220  * softc.  Each place that can sleep must maintain the reference
1221  * count.  When the reference count drops to -1 (0 is the normal value
1222  * of the reference count) the a wakeup on the softc is performed
1223  * signaling to the detach waiter that all references are gone.
1224  */
1225
1226 /*
1227  * Called from process context when we discover that a port has
1228  * been disconnected.
1229  */
1230 void
1231 usb_disconnect_port(struct usbd_port *up, device_ptr_t parent)
1232 {
1233         usbd_device_handle dev = up->device;
1234         const char *hubname = USBDEVPTRNAME(parent);
1235         int i;
1236
1237         DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n", 
1238                     up, dev, up->portno));
1239
1240 #ifdef DIAGNOSTIC
1241         if (dev == NULL) {
1242                 printf("usb_disconnect_port: no device\n");
1243                 return;
1244         }
1245 #endif
1246
1247         if (dev->cdesc == NULL) {
1248                 /* Partially attached device, just drop it. */
1249                 dev->bus->devices[dev->address] = 0;
1250                 up->device = 0;
1251                 return;
1252         }
1253
1254         usbd_add_event(USB_EVENT_DEVICE_DETACH, dev);
1255
1256         if (dev->subdevs != NULL) {
1257                 DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
1258                 for (i = 0; dev->subdevs[i]; i++) {
1259                         printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]), 
1260                                hubname);
1261                         if (up->portno != 0)
1262                                 printf(" port %d", up->portno);
1263                         printf(" (addr %d) disconnected\n", dev->address);
1264 #if defined(__NetBSD__) || defined(__OpenBSD__)
1265                         config_detach(dev->subdevs[i], DETACH_FORCE);
1266 #elif defined(__FreeBSD__)
1267                         device_delete_child(device_get_parent(dev->subdevs[i]),
1268                                             dev->subdevs[i]);
1269 #endif
1270
1271                 }
1272         }
1273
1274         /*usbd_add_event(USB_EVENT_DEVICE_DETACH, dev);*/
1275         dev->bus->devices[dev->address] = NULL;
1276         up->device = NULL;
1277         usb_free_device(dev);
1278 }
1279
1280 #ifdef __OpenBSD__
1281 void *usb_realloc(void *p, u_int size, int pool, int flags)
1282 {
1283         void *q;
1284
1285         q = malloc(size, pool, flags);
1286         if (q == NULL)
1287                 return (NULL);
1288         bcopy(p, q, size);
1289         free(p, pool);
1290         return (q);
1291 }
1292 #endif