[BACK]Return to usb_subr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/usb_subr.c, Revision 1.143.6.1

1.143.6.1! mjf         1: /*     $NetBSD: usb_subr.c,v 1.148 2007/06/30 09:17:45 mlelstv Exp $   */
1.56      augustss    2: /*     $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $   */
1.1       augustss    3:
                      4: /*
1.121     mycroft     5:  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
1.1       augustss    6:  * All rights reserved.
                      7:  *
1.9       augustss    8:  * This code is derived from software contributed to The NetBSD Foundation
1.76      augustss    9:  * by Lennart Augustsson (lennart@augustsson.net) at
1.9       augustss   10:  * Carlstedt Research & Technology.
1.1       augustss   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:  */
1.91      lukem      40:
                     41: #include <sys/cdefs.h>
1.143.6.1! mjf        42: __KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.148 2007/06/30 09:17:45 mlelstv Exp $");
1.104     martin     43:
1.140     pavel      44: #include "opt_compat_netbsd.h"
1.104     martin     45: #include "opt_usbverbose.h"
1.1       augustss   46:
                     47: #include <sys/param.h>
                     48: #include <sys/systm.h>
                     49: #include <sys/kernel.h>
                     50: #include <sys/malloc.h>
1.37      augustss   51: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.1       augustss   52: #include <sys/device.h>
1.56      augustss   53: #include <sys/select.h>
1.18      augustss   54: #elif defined(__FreeBSD__)
                     55: #include <sys/module.h>
                     56: #include <sys/bus.h>
                     57: #endif
1.1       augustss   58: #include <sys/proc.h>
1.46      augustss   59:
                     60: #include <machine/bus.h>
1.1       augustss   61:
                     62: #include <dev/usb/usb.h>
                     63:
                     64: #include <dev/usb/usbdi.h>
                     65: #include <dev/usb/usbdi_util.h>
                     66: #include <dev/usb/usbdivar.h>
                     67: #include <dev/usb/usbdevs.h>
                     68: #include <dev/usb/usb_quirks.h>
                     69:
1.27      augustss   70: #if defined(__FreeBSD__)
                     71: #include <machine/clock.h>
                     72: #define delay(d)         DELAY(d)
                     73: #endif
                     74:
1.1       augustss   75: #ifdef USB_DEBUG
1.35      augustss   76: #define DPRINTF(x)     if (usbdebug) logprintf x
                     77: #define DPRINTFN(n,x)  if (usbdebug>(n)) logprintf x
1.1       augustss   78: extern int usbdebug;
                     79: #else
                     80: #define DPRINTF(x)
                     81: #define DPRINTFN(n,x)
                     82: #endif
                     83:
1.82      augustss   84: Static usbd_status usbd_set_config(usbd_device_handle, int);
1.124     augustss   85: Static void usbd_devinfo(usbd_device_handle, int, char *, size_t);
1.123     augustss   86: Static void usbd_devinfo_vp(usbd_device_handle dev,
1.139     pavel      87:                            char *v,
                     88:                            char *p, int usedev,
                     89:                            int useencoded );
1.78      augustss   90: Static int usbd_getnewaddr(usbd_bus_handle bus);
1.56      augustss   91: #if defined(__NetBSD__)
1.118     drochner   92: Static int usbd_print(void *, const char *);
1.143.6.1! mjf        93: Static int usbd_ifprint(void *, const char *);
1.118     drochner   94: Static int usbd_submatch(device_ptr_t, struct cfdata *,
1.129     drochner   95:                         const int *, void *);
1.143.6.1! mjf        96: Static int usbd_ifsubmatch(device_ptr_t, struct cfdata *,
        !            97:                           const int *, void *);
1.37      augustss   98: #elif defined(__OpenBSD__)
1.78      augustss   99: Static int usbd_print(void *aux, const char *pnp);
                    100: Static int usbd_submatch(device_ptr_t, void *, void *);
1.18      augustss  101: #endif
1.78      augustss  102: Static void usbd_free_iface_data(usbd_device_handle dev, int ifcno);
                    103: Static void usbd_kill_pipe(usbd_pipe_handle);
                    104: Static usbd_status usbd_probe_and_attach(device_ptr_t parent,
                    105:                                 usbd_device_handle dev, int port, int addr);
1.1       augustss  106:
1.69      augustss  107: Static u_int32_t usb_cookie_no = 0;
1.27      augustss  108:
1.1       augustss  109: #ifdef USBVERBOSE
                    110: typedef u_int16_t usb_vendor_id_t;
                    111: typedef u_int16_t usb_product_id_t;
                    112:
                    113: /*
                    114:  * Descriptions of of known vendors and devices ("products").
                    115:  */
1.122     mycroft   116: struct usb_vendor {
                    117:        usb_vendor_id_t         vendor;
1.126     christos  118:        const char              *vendorname;
1.122     mycroft   119: };
                    120: struct usb_product {
1.1       augustss  121:        usb_vendor_id_t         vendor;
                    122:        usb_product_id_t        product;
1.126     christos  123:        const char              *productname;
1.1       augustss  124: };
                    125:
                    126: #include <dev/usb/usbdevs_data.h>
                    127: #endif /* USBVERBOSE */
                    128:
1.84      jdolecek  129: Static const char * const usbd_error_strs[] = {
1.12      augustss  130:        "NORMAL_COMPLETION",
                    131:        "IN_PROGRESS",
                    132:        "PENDING_REQUESTS",
                    133:        "NOT_STARTED",
                    134:        "INVAL",
                    135:        "NOMEM",
                    136:        "CANCELLED",
                    137:        "BAD_ADDRESS",
                    138:        "IN_USE",
                    139:        "NO_ADDR",
                    140:        "SET_ADDR_FAILED",
                    141:        "NO_POWER",
                    142:        "TOO_DEEP",
                    143:        "IOERROR",
                    144:        "NOT_CONFIGURED",
                    145:        "TIMEOUT",
                    146:        "SHORT_XFER",
                    147:        "STALLED",
1.33      augustss  148:        "INTERRUPTED",
1.12      augustss  149:        "XXX",
                    150: };
1.1       augustss  151:
1.42      thorpej   152: const char *
1.78      augustss  153: usbd_errstr(usbd_status err)
1.39      augustss  154: {
                    155:        static char buffer[5];
                    156:
1.42      thorpej   157:        if (err < USBD_ERROR_MAX) {
1.39      augustss  158:                return usbd_error_strs[err];
                    159:        } else {
                    160:                snprintf(buffer, sizeof buffer, "%d", err);
                    161:                return buffer;
                    162:        }
                    163: }
                    164:
1.13      augustss  165: usbd_status
1.78      augustss  166: usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid,
1.114     mycroft   167:                     usb_string_descriptor_t *sdesc, int *sizep)
1.13      augustss  168: {
                    169:        usb_device_request_t req;
1.116     mycroft   170:        usbd_status err;
                    171:        int actlen;
1.13      augustss  172:
                    173:        req.bmRequestType = UT_READ_DEVICE;
                    174:        req.bRequest = UR_GET_DESCRIPTOR;
                    175:        USETW2(req.wValue, UDESC_STRING, sindex);
                    176:        USETW(req.wIndex, langid);
1.143.6.1! mjf       177:        USETW(req.wLength, 2);  /* only size byte first */
1.116     mycroft   178:        err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
                    179:                &actlen, USBD_DEFAULT_TIMEOUT);
                    180:        if (err)
                    181:                return (err);
                    182:
1.143.6.1! mjf       183:        if (actlen < 2)
        !           184:                return (USBD_SHORT_XFER);
        !           185:
        !           186:        USETW(req.wLength, sdesc->bLength);     /* the whole string */
        !           187:        err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
        !           188:                &actlen, USBD_DEFAULT_TIMEOUT);
        !           189:        if (err)
        !           190:                return (err);
        !           191:
1.116     mycroft   192:        if (actlen != sdesc->bLength) {
                    193:                DPRINTFN(-1, ("usbd_get_string_desc: expected %d, got %d\n",
                    194:                    sdesc->bLength, actlen));
                    195:        }
                    196:
                    197:        *sizep = actlen;
                    198:        return (USBD_NORMAL_COMPLETION);
1.13      augustss  199: }
                    200:
1.128     enami     201: static void
                    202: usbd_trim_spaces(char *p)
1.83      augustss  203: {
1.128     enami     204:        char *q, *e;
1.83      augustss  205:
1.128     enami     206:        q = e = p;
                    207:        while (*q == ' ')               /* skip leading spaces */
1.85      augustss  208:                q++;
1.128     enami     209:        while ((*p = *q++))             /* copy string */
                    210:                if (*p++ != ' ')        /* remember last non-space */
                    211:                        e = p;
                    212:        *e = '\0';                      /* kill trailing spaces */
1.83      augustss  213: }
                    214:
1.123     augustss  215: Static void
1.139     pavel     216: usbd_devinfo_vp(usbd_device_handle dev, char *v,
                    217:                char *p, int usedev, int useencoded)
1.1       augustss  218: {
                    219:        usb_device_descriptor_t *udd = &dev->ddesc;
1.2       is        220: #ifdef USBVERBOSE
1.122     mycroft   221:        int n;
1.2       is        222: #endif
1.1       augustss  223:
1.128     enami     224:        v[0] = p[0] = '\0';
                    225:        if (dev == NULL)
1.52      augustss  226:                return;
                    227:
1.82      augustss  228:        if (usedev) {
1.139     pavel     229:                if (usbd_get_string0(dev, udd->iManufacturer, v, useencoded) ==
1.128     enami     230:                    USBD_NORMAL_COMPLETION)
                    231:                        usbd_trim_spaces(v);
1.139     pavel     232:                if (usbd_get_string0(dev, udd->iProduct, p, useencoded) ==
1.128     enami     233:                    USBD_NORMAL_COMPLETION)
                    234:                        usbd_trim_spaces(p);
1.82      augustss  235:        }
1.128     enami     236:        /* There is no need for strlcpy & snprintf below. */
1.1       augustss  237: #ifdef USBVERBOSE
1.128     enami     238:        if (v[0] == '\0')
1.122     mycroft   239:                for (n = 0; n < usb_nvendors; n++)
1.128     enami     240:                        if (usb_vendors[n].vendor == UGETW(udd->idVendor)) {
                    241:                                strcpy(v, usb_vendors[n].vendorname);
                    242:                                break;
                    243:                        }
                    244:        if (p[0] == '\0')
1.122     mycroft   245:                for (n = 0; n < usb_nproducts; n++)
                    246:                        if (usb_products[n].vendor == UGETW(udd->idVendor) &&
1.128     enami     247:                            usb_products[n].product == UGETW(udd->idProduct)) {
                    248:                                strcpy(p, usb_products[n].productname);
                    249:                                break;
                    250:                        }
1.1       augustss  251: #endif
1.128     enami     252:        if (v[0] == '\0')
1.123     augustss  253:                sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
1.128     enami     254:        if (p[0] == '\0')
1.123     augustss  255:                sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
1.1       augustss  256: }
                    257:
                    258: int
1.113     itojun    259: usbd_printBCD(char *cp, size_t l, int bcd)
1.1       augustss  260: {
1.113     itojun    261:        return (snprintf(cp, l, "%x.%02x", bcd >> 8, bcd & 0xff));
1.1       augustss  262: }
                    263:
1.124     augustss  264: Static void
1.113     itojun    265: usbd_devinfo(usbd_device_handle dev, int showclass, char *cp, size_t l)
1.1       augustss  266: {
                    267:        usb_device_descriptor_t *udd = &dev->ddesc;
1.133     christos  268:        char *vendor, *product;
1.1       augustss  269:        int bcdDevice, bcdUSB;
1.113     itojun    270:        char *ep;
                    271:
1.133     christos  272:        vendor = malloc(USB_MAX_ENCODED_STRING_LEN * 2, M_USB, M_NOWAIT);
                    273:        if (vendor == NULL) {
                    274:                *cp = '\0';
                    275:                return;
                    276:        }
                    277:        product = &vendor[USB_MAX_ENCODED_STRING_LEN];
                    278:
1.113     itojun    279:        ep = cp + l;
1.1       augustss  280:
1.139     pavel     281:        usbd_devinfo_vp(dev, vendor, product, 1, 1);
1.113     itojun    282:        cp += snprintf(cp, ep - cp, "%s %s", vendor, product);
1.1       augustss  283:        if (showclass)
1.113     itojun    284:                cp += snprintf(cp, ep - cp, ", class %d/%d",
                    285:                    udd->bDeviceClass, udd->bDeviceSubClass);
1.1       augustss  286:        bcdUSB = UGETW(udd->bcdUSB);
                    287:        bcdDevice = UGETW(udd->bcdDevice);
1.113     itojun    288:        cp += snprintf(cp, ep - cp, ", rev ");
                    289:        cp += usbd_printBCD(cp, ep - cp, bcdUSB);
1.1       augustss  290:        *cp++ = '/';
1.113     itojun    291:        cp += usbd_printBCD(cp, ep - cp, bcdDevice);
                    292:        cp += snprintf(cp, ep - cp, ", addr %d", dev->address);
1.10      augustss  293:        *cp = 0;
1.133     christos  294:        free(vendor, M_USB);
1.1       augustss  295: }
                    296:
1.124     augustss  297: char *
                    298: usbd_devinfo_alloc(usbd_device_handle dev, int showclass)
                    299: {
                    300:        char *devinfop;
                    301:
                    302:        devinfop = malloc(DEVINFOSIZE, M_TEMP, M_WAITOK);
                    303:        usbd_devinfo(dev, showclass, devinfop, DEVINFOSIZE);
                    304:        return devinfop;
                    305: }
                    306:
                    307: void
                    308: usbd_devinfo_free(char *devinfop)
                    309: {
                    310:        free(devinfop, M_TEMP);
                    311: }
                    312:
1.1       augustss  313: /* Delay for a certain number of ms */
                    314: void
1.78      augustss  315: usb_delay_ms(usbd_bus_handle bus, u_int ms)
1.1       augustss  316: {
                    317:        /* Wait at least two clock ticks so we know the time has passed. */
1.64      augustss  318:        if (bus->use_polling || cold)
1.1       augustss  319:                delay((ms+1) * 1000);
                    320:        else
                    321:                tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
                    322: }
                    323:
1.23      augustss  324: /* Delay given a device handle. */
                    325: void
1.78      augustss  326: usbd_delay_ms(usbd_device_handle dev, u_int ms)
1.23      augustss  327: {
                    328:        usb_delay_ms(dev->bus, ms);
                    329: }
                    330:
1.1       augustss  331: usbd_status
1.78      augustss  332: usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps)
1.1       augustss  333: {
                    334:        usb_device_request_t req;
1.53      augustss  335:        usbd_status err;
1.1       augustss  336:        int n;
1.99      augustss  337:
1.1       augustss  338:        req.bmRequestType = UT_WRITE_CLASS_OTHER;
                    339:        req.bRequest = UR_SET_FEATURE;
                    340:        USETW(req.wValue, UHF_PORT_RESET);
                    341:        USETW(req.wIndex, port);
                    342:        USETW(req.wLength, 0);
1.53      augustss  343:        err = usbd_do_request(dev, &req, 0);
1.39      augustss  344:        DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n",
1.53      augustss  345:                    port, usbd_errstr(err)));
                    346:        if (err)
                    347:                return (err);
1.1       augustss  348:        n = 10;
                    349:        do {
                    350:                /* Wait for device to recover from reset. */
1.23      augustss  351:                usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
1.53      augustss  352:                err = usbd_get_port_status(dev, port, ps);
                    353:                if (err) {
                    354:                        DPRINTF(("usbd_reset_port: get status failed %d\n",
                    355:                                 err));
                    356:                        return (err);
1.1       augustss  357:                }
1.92      augustss  358:                /* If the device disappeared, just give up. */
                    359:                if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS))
                    360:                        return (USBD_NORMAL_COMPLETION);
1.1       augustss  361:        } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
1.73      augustss  362:        if (n == 0)
                    363:                return (USBD_TIMEOUT);
1.53      augustss  364:        err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
1.1       augustss  365: #ifdef USB_DEBUG
1.53      augustss  366:        if (err)
                    367:                DPRINTF(("usbd_reset_port: clear port feature failed %d\n",
                    368:                         err));
1.1       augustss  369: #endif
1.18      augustss  370:
                    371:        /* Wait for the device to recover from reset. */
1.23      augustss  372:        usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
1.53      augustss  373:        return (err);
1.1       augustss  374: }
                    375:
1.12      augustss  376: usb_interface_descriptor_t *
1.78      augustss  377: usbd_find_idesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx)
1.12      augustss  378: {
                    379:        char *p = (char *)cd;
                    380:        char *end = p + UGETW(cd->wTotalLength);
                    381:        usb_interface_descriptor_t *d;
1.19      augustss  382:        int curidx, lastidx, curaidx = 0;
1.12      augustss  383:
1.19      augustss  384:        for (curidx = lastidx = -1; p < end; ) {
1.12      augustss  385:                d = (usb_interface_descriptor_t *)p;
1.18      augustss  386:                DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
1.99      augustss  387:                            "type=%d\n",
1.18      augustss  388:                            ifaceidx, curidx, altidx, curaidx,
                    389:                            d->bLength, d->bDescriptorType));
1.12      augustss  390:                if (d->bLength == 0) /* bad descriptor */
                    391:                        break;
                    392:                p += d->bLength;
                    393:                if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
1.19      augustss  394:                        if (d->bInterfaceNumber != lastidx) {
                    395:                                lastidx = d->bInterfaceNumber;
1.12      augustss  396:                                curidx++;
                    397:                                curaidx = 0;
                    398:                        } else
                    399:                                curaidx++;
                    400:                        if (ifaceidx == curidx && altidx == curaidx)
                    401:                                return (d);
                    402:                }
                    403:        }
1.58      augustss  404:        return (NULL);
1.12      augustss  405: }
                    406:
                    407: usb_endpoint_descriptor_t *
1.99      augustss  408: usbd_find_edesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx,
1.78      augustss  409:                int endptidx)
1.12      augustss  410: {
                    411:        char *p = (char *)cd;
                    412:        char *end = p + UGETW(cd->wTotalLength);
                    413:        usb_interface_descriptor_t *d;
                    414:        usb_endpoint_descriptor_t *e;
                    415:        int curidx;
                    416:
                    417:        d = usbd_find_idesc(cd, ifaceidx, altidx);
1.53      augustss  418:        if (d == NULL)
1.58      augustss  419:                return (NULL);
1.12      augustss  420:        if (endptidx >= d->bNumEndpoints) /* quick exit */
1.58      augustss  421:                return (NULL);
1.12      augustss  422:
                    423:        curidx = -1;
                    424:        for (p = (char *)d + d->bLength; p < end; ) {
                    425:                e = (usb_endpoint_descriptor_t *)p;
                    426:                if (e->bLength == 0) /* bad descriptor */
                    427:                        break;
                    428:                p += e->bLength;
                    429:                if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
1.58      augustss  430:                        return (NULL);
1.12      augustss  431:                if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
                    432:                        curidx++;
                    433:                        if (curidx == endptidx)
                    434:                                return (e);
                    435:                }
1.1       augustss  436:        }
1.58      augustss  437:        return (NULL);
1.1       augustss  438: }
                    439:
                    440: usbd_status
1.78      augustss  441: usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx)
1.1       augustss  442: {
1.12      augustss  443:        usbd_interface_handle ifc = &dev->ifaces[ifaceidx];
1.77      augustss  444:        usb_interface_descriptor_t *idesc;
1.1       augustss  445:        char *p, *end;
                    446:        int endpt, nendpt;
                    447:
1.18      augustss  448:        DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
1.14      drochner  449:                    ifaceidx, altidx));
1.77      augustss  450:        idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
                    451:        if (idesc == NULL)
                    452:                return (USBD_INVAL);
1.1       augustss  453:        ifc->device = dev;
1.77      augustss  454:        ifc->idesc = idesc;
1.13      augustss  455:        ifc->index = ifaceidx;
                    456:        ifc->altindex = altidx;
1.1       augustss  457:        nendpt = ifc->idesc->bNumEndpoints;
1.59      augustss  458:        DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
1.1       augustss  459:        if (nendpt != 0) {
                    460:                ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
                    461:                                        M_USB, M_NOWAIT);
1.58      augustss  462:                if (ifc->endpoints == NULL)
1.1       augustss  463:                        return (USBD_NOMEM);
                    464:        } else
1.58      augustss  465:                ifc->endpoints = NULL;
                    466:        ifc->priv = NULL;
1.1       augustss  467:        p = (char *)ifc->idesc + ifc->idesc->bLength;
                    468:        end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
1.19      augustss  469: #define ed ((usb_endpoint_descriptor_t *)p)
1.1       augustss  470:        for (endpt = 0; endpt < nendpt; endpt++) {
                    471:                DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt));
                    472:                for (; p < end; p += ed->bLength) {
1.14      drochner  473:                        DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p "
                    474:                                     "len=%d type=%d\n",
1.1       augustss  475:                                 p, end, ed->bLength, ed->bDescriptorType));
1.24      augustss  476:                        if (p + ed->bLength <= end && ed->bLength != 0 &&
1.1       augustss  477:                            ed->bDescriptorType == UDESC_ENDPOINT)
1.24      augustss  478:                                goto found;
1.59      augustss  479:                        if (ed->bLength == 0 ||
                    480:                            ed->bDescriptorType == UDESC_INTERFACE)
1.1       augustss  481:                                break;
                    482:                }
1.24      augustss  483:                /* passed end, or bad desc */
1.95      augustss  484:                printf("usbd_fill_iface_data: bad descriptor(s): %s\n",
                    485:                       ed->bLength == 0 ? "0 length" :
                    486:                       ed->bDescriptorType == UDESC_INTERFACE ? "iface desc":
                    487:                       "out of data");
1.24      augustss  488:                goto bad;
                    489:        found:
1.1       augustss  490:                ifc->endpoints[endpt].edesc = ed;
1.95      augustss  491:                if (dev->speed == USB_SPEED_HIGH) {
                    492:                        u_int mps;
                    493:                        /* Control and bulk endpoints have max packet limits. */
                    494:                        switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
                    495:                        case UE_CONTROL:
                    496:                                mps = USB_2_MAX_CTRL_PACKET;
                    497:                                goto check;
                    498:                        case UE_BULK:
                    499:                                mps = USB_2_MAX_BULK_PACKET;
                    500:                        check:
                    501:                                if (UGETW(ed->wMaxPacketSize) != mps) {
                    502:                                        USETW(ed->wMaxPacketSize, mps);
                    503: #ifdef DIAGNOSTIC
                    504:                                        printf("usbd_fill_iface_data: bad max "
                    505:                                               "packet size\n");
                    506: #endif
                    507:                                }
                    508:                                break;
                    509:                        default:
                    510:                                break;
                    511:                        }
                    512:                }
1.1       augustss  513:                ifc->endpoints[endpt].refcnt = 0;
1.24      augustss  514:                p += ed->bLength;
1.1       augustss  515:        }
1.19      augustss  516: #undef ed
1.1       augustss  517:        LIST_INIT(&ifc->pipes);
                    518:        return (USBD_NORMAL_COMPLETION);
1.24      augustss  519:
1.1       augustss  520:  bad:
1.77      augustss  521:        if (ifc->endpoints != NULL) {
1.59      augustss  522:                free(ifc->endpoints, M_USB);
1.77      augustss  523:                ifc->endpoints = NULL;
                    524:        }
1.24      augustss  525:        return (USBD_INVAL);
1.1       augustss  526: }
                    527:
                    528: void
1.78      augustss  529: usbd_free_iface_data(usbd_device_handle dev, int ifcno)
1.1       augustss  530: {
                    531:        usbd_interface_handle ifc = &dev->ifaces[ifcno];
                    532:        if (ifc->endpoints)
                    533:                free(ifc->endpoints, M_USB);
                    534: }
                    535:
1.69      augustss  536: Static usbd_status
1.78      augustss  537: usbd_set_config(usbd_device_handle dev, int conf)
1.7       augustss  538: {
                    539:        usb_device_request_t req;
                    540:
                    541:        req.bmRequestType = UT_WRITE_DEVICE;
                    542:        req.bRequest = UR_SET_CONFIG;
                    543:        USETW(req.wValue, conf);
                    544:        USETW(req.wIndex, 0);
                    545:        USETW(req.wLength, 0);
                    546:        return (usbd_do_request(dev, &req, 0));
                    547: }
                    548:
1.1       augustss  549: usbd_status
1.78      augustss  550: usbd_set_config_no(usbd_device_handle dev, int no, int msg)
1.1       augustss  551: {
1.12      augustss  552:        int index;
                    553:        usb_config_descriptor_t cd;
1.53      augustss  554:        usbd_status err;
1.12      augustss  555:
1.75      augustss  556:        if (no == USB_UNCONFIG_NO)
                    557:                return (usbd_set_config_index(dev, USB_UNCONFIG_INDEX, msg));
                    558:
1.12      augustss  559:        DPRINTFN(5,("usbd_set_config_no: %d\n", no));
                    560:        /* Figure out what config index to use. */
                    561:        for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
1.53      augustss  562:                err = usbd_get_config_desc(dev, index, &cd);
                    563:                if (err)
                    564:                        return (err);
1.12      augustss  565:                if (cd.bConfigurationValue == no)
                    566:                        return (usbd_set_config_index(dev, index, msg));
                    567:        }
                    568:        return (USBD_INVAL);
                    569: }
                    570:
                    571: usbd_status
1.78      augustss  572: usbd_set_config_index(usbd_device_handle dev, int index, int msg)
1.12      augustss  573: {
1.1       augustss  574:        usb_config_descriptor_t cd, *cdp;
1.53      augustss  575:        usbd_status err;
1.103     augustss  576:        int i, ifcidx, nifc, len, selfpowered, power;
1.1       augustss  577:
1.12      augustss  578:        DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
1.1       augustss  579:
1.143.6.1! mjf       580:        if (index >= dev->ddesc.bNumConfigurations &&
        !           581:            index != USB_UNCONFIG_NO) {
        !           582:                /* panic? */
        !           583:                printf("usbd_set_config_index: illegal index\n");
        !           584:                return (USBD_INVAL);
        !           585:        }
        !           586:
1.1       augustss  587:        /* XXX check that all interfaces are idle */
1.75      augustss  588:        if (dev->config != USB_UNCONFIG_NO) {
1.12      augustss  589:                DPRINTF(("usbd_set_config_index: free old config\n"));
1.1       augustss  590:                /* Free all configuration data structures. */
                    591:                nifc = dev->cdesc->bNumInterface;
1.12      augustss  592:                for (ifcidx = 0; ifcidx < nifc; ifcidx++)
                    593:                        usbd_free_iface_data(dev, ifcidx);
1.1       augustss  594:                free(dev->ifaces, M_USB);
                    595:                free(dev->cdesc, M_USB);
1.57      augustss  596:                dev->ifaces = NULL;
                    597:                dev->cdesc = NULL;
1.75      augustss  598:                dev->config = USB_UNCONFIG_NO;
                    599:        }
                    600:
                    601:        if (index == USB_UNCONFIG_INDEX) {
                    602:                /* We are unconfiguring the device, so leave unallocated. */
                    603:                DPRINTF(("usbd_set_config_index: set config 0\n"));
                    604:                err = usbd_set_config(dev, USB_UNCONFIG_NO);
1.136     christos  605:                if (err) {
1.75      augustss  606:                        DPRINTF(("usbd_set_config_index: setting config=0 "
                    607:                                 "failed, error=%s\n", usbd_errstr(err)));
1.136     christos  608:                }
1.75      augustss  609:                return (err);
1.1       augustss  610:        }
                    611:
1.74      augustss  612:        /* Get the short descriptor. */
1.53      augustss  613:        err = usbd_get_config_desc(dev, index, &cd);
                    614:        if (err)
                    615:                return (err);
1.1       augustss  616:        len = UGETW(cd.wTotalLength);
                    617:        cdp = malloc(len, M_USB, M_NOWAIT);
1.53      augustss  618:        if (cdp == NULL)
1.1       augustss  619:                return (USBD_NOMEM);
1.103     augustss  620:
                    621:        /* Get the full descriptor.  Try a few times for slow devices. */
                    622:        for (i = 0; i < 3; i++) {
                    623:                err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
                    624:                if (!err)
                    625:                        break;
                    626:                usbd_delay_ms(dev, 200);
                    627:        }
1.53      augustss  628:        if (err)
1.1       augustss  629:                goto bad;
1.103     augustss  630:
1.18      augustss  631:        if (cdp->bDescriptorType != UDESC_CONFIG) {
                    632:                DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
                    633:                             cdp->bDescriptorType));
1.53      augustss  634:                err = USBD_INVAL;
1.18      augustss  635:                goto bad;
                    636:        }
1.74      augustss  637:
1.142     drochner  638:        /*
                    639:         * Figure out if the device is self or bus powered.
                    640:         */
                    641: #if 0 /* XXX various devices don't report the power state correctly */
1.1       augustss  642:        selfpowered = 0;
1.141     drochner  643:        err = usbd_get_device_status(dev, &ds);
                    644:        if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED))
                    645:                selfpowered = 1;
1.142     drochner  646: #endif
                    647:        /*
                    648:         * Use the power state in the configuration we are going
                    649:         * to set. This doesn't necessarily reflect the actual
                    650:         * power state of the device; the driver can control this
                    651:         * by choosing the appropriate configuration.
                    652:         */
                    653:        selfpowered = !!(cdp->bmAttributes & UC_SELF_POWERED);
1.141     drochner  654:
1.81      augustss  655:        DPRINTF(("usbd_set_config_index: (addr %d) cno=%d attr=0x%02x, "
                    656:                 "selfpowered=%d, power=%d\n",
1.99      augustss  657:                 cdp->bConfigurationValue, dev->address, cdp->bmAttributes,
1.33      augustss  658:                 selfpowered, cdp->bMaxPower * 2));
1.74      augustss  659:
                    660:        /* Check if we have enough power. */
1.142     drochner  661: #if 0 /* this is a no-op, see above */
1.141     drochner  662:        if ((cdp->bmAttributes & UC_SELF_POWERED) && !selfpowered) {
                    663:                if (msg)
                    664:                        printf("%s: device addr %d (config %d): "
                    665:                                 "can't set self powered configuration\n",
                    666:                               USBDEVNAME(dev->bus->bdev), dev->address,
                    667:                               cdp->bConfigurationValue);
                    668:                err = USBD_NO_POWER;
                    669:                goto bad;
                    670:        }
1.142     drochner  671: #endif
1.1       augustss  672: #ifdef USB_DEBUG
1.53      augustss  673:        if (dev->powersrc == NULL) {
1.44      augustss  674:                DPRINTF(("usbd_set_config_index: No power source?\n"));
1.141     drochner  675:                err = USBD_IOERROR;
                    676:                goto bad;
1.1       augustss  677:        }
                    678: #endif
                    679:        power = cdp->bMaxPower * 2;
                    680:        if (power > dev->powersrc->power) {
1.81      augustss  681:                DPRINTF(("power exceeded %d %d\n", power,dev->powersrc->power));
1.1       augustss  682:                /* XXX print nicer message. */
1.7       augustss  683:                if (msg)
1.18      augustss  684:                        printf("%s: device addr %d (config %d) exceeds power "
                    685:                                 "budget, %d mA > %d mA\n",
1.99      augustss  686:                               USBDEVNAME(dev->bus->bdev), dev->address,
                    687:                               cdp->bConfigurationValue,
1.7       augustss  688:                               power, dev->powersrc->power);
1.53      augustss  689:                err = USBD_NO_POWER;
1.1       augustss  690:                goto bad;
                    691:        }
                    692:        dev->power = power;
                    693:        dev->self_powered = selfpowered;
                    694:
1.74      augustss  695:        /* Set the actual configuration value. */
1.18      augustss  696:        DPRINTF(("usbd_set_config_index: set config %d\n",
                    697:                 cdp->bConfigurationValue));
1.53      augustss  698:        err = usbd_set_config(dev, cdp->bConfigurationValue);
                    699:        if (err) {
1.14      drochner  700:                DPRINTF(("usbd_set_config_index: setting config=%d failed, "
1.39      augustss  701:                         "error=%s\n",
1.53      augustss  702:                         cdp->bConfigurationValue, usbd_errstr(err)));
1.1       augustss  703:                goto bad;
                    704:        }
1.74      augustss  705:
                    706:        /* Allocate and fill interface data. */
1.1       augustss  707:        nifc = cdp->bNumInterface;
1.99      augustss  708:        dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
1.1       augustss  709:                             M_USB, M_NOWAIT);
1.58      augustss  710:        if (dev->ifaces == NULL) {
1.53      augustss  711:                err = USBD_NOMEM;
1.1       augustss  712:                goto bad;
                    713:        }
1.12      augustss  714:        DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
1.1       augustss  715:        dev->cdesc = cdp;
                    716:        dev->config = cdp->bConfigurationValue;
1.12      augustss  717:        for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
1.53      augustss  718:                err = usbd_fill_iface_data(dev, ifcidx, 0);
                    719:                if (err) {
1.12      augustss  720:                        while (--ifcidx >= 0)
                    721:                                usbd_free_iface_data(dev, ifcidx);
1.1       augustss  722:                        goto bad;
                    723:                }
                    724:        }
                    725:
                    726:        return (USBD_NORMAL_COMPLETION);
                    727:
                    728:  bad:
                    729:        free(cdp, M_USB);
1.53      augustss  730:        return (err);
1.1       augustss  731: }
                    732:
                    733: /* XXX add function for alternate settings */
                    734:
                    735: usbd_status
1.78      augustss  736: usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface,
                    737:                struct usbd_endpoint *ep, int ival, usbd_pipe_handle *pipe)
1.1       augustss  738: {
                    739:        usbd_pipe_handle p;
1.53      augustss  740:        usbd_status err;
1.1       augustss  741:
                    742:        DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
                    743:                    dev, iface, ep, pipe));
                    744:        p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
1.53      augustss  745:        if (p == NULL)
1.1       augustss  746:                return (USBD_NOMEM);
                    747:        p->device = dev;
                    748:        p->iface = iface;
                    749:        p->endpoint = ep;
                    750:        ep->refcnt++;
                    751:        p->refcnt = 1;
1.53      augustss  752:        p->intrxfer = 0;
1.1       augustss  753:        p->running = 0;
1.70      augustss  754:        p->aborting = 0;
1.34      augustss  755:        p->repeat = 0;
1.63      augustss  756:        p->interval = ival;
1.1       augustss  757:        SIMPLEQ_INIT(&p->queue);
1.53      augustss  758:        err = dev->bus->methods->open_pipe(p);
                    759:        if (err) {
1.39      augustss  760:                DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
                    761:                         "%s\n",
1.53      augustss  762:                         ep->edesc->bEndpointAddress, usbd_errstr(err)));
1.1       augustss  763:                free(p, M_USB);
1.53      augustss  764:                return (err);
1.1       augustss  765:        }
                    766:        *pipe = p;
                    767:        return (USBD_NORMAL_COMPLETION);
                    768: }
                    769:
                    770: /* Abort the device control pipe. */
                    771: void
1.78      augustss  772: usbd_kill_pipe(usbd_pipe_handle pipe)
1.1       augustss  773: {
1.89      augustss  774:        usbd_abort_pipe(pipe);
1.1       augustss  775:        pipe->methods->close(pipe);
                    776:        pipe->endpoint->refcnt--;
                    777:        free(pipe, M_USB);
                    778: }
                    779:
                    780: int
1.78      augustss  781: usbd_getnewaddr(usbd_bus_handle bus)
1.1       augustss  782: {
1.18      augustss  783:        int addr;
1.1       augustss  784:
1.18      augustss  785:        for (addr = 1; addr < USB_MAX_DEVICES; addr++)
                    786:                if (bus->devices[addr] == 0)
                    787:                        return (addr);
1.1       augustss  788:        return (-1);
                    789: }
                    790:
1.18      augustss  791:
                    792: usbd_status
1.78      augustss  793: usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
                    794:                      int port, int addr)
1.18      augustss  795: {
                    796:        struct usb_attach_arg uaa;
1.143.6.1! mjf       797:        struct usbif_attach_arg uiaa;
1.18      augustss  798:        usb_device_descriptor_t *dd = &dev->ddesc;
1.53      augustss  799:        int found, i, confi, nifaces;
                    800:        usbd_status err;
1.43      augustss  801:        device_ptr_t dv;
1.132     christos  802:        usbd_interface_handle *ifaces;
1.18      augustss  803:
                    804: #if defined(__FreeBSD__)
1.99      augustss  805:        /*
1.28      augustss  806:         * XXX uaa is a static var. Not a problem as it _should_ be used only
                    807:         * during probe and attach. Should be changed however.
                    808:         */
1.43      augustss  809:        device_t bdev;
1.52      augustss  810:        bdev = device_add_child(parent, NULL, -1, &uaa);
1.26      augustss  811:        if (!bdev) {
1.18      augustss  812:            printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
                    813:            return (USBD_INVAL);
                    814:        }
1.52      augustss  815:        device_quiet(bdev);
1.18      augustss  816: #endif
                    817:
                    818:        uaa.device = dev;
                    819:        uaa.usegeneric = 0;
                    820:        uaa.port = port;
1.32      augustss  821:        uaa.vendor = UGETW(dd->idVendor);
                    822:        uaa.product = UGETW(dd->idProduct);
                    823:        uaa.release = UGETW(dd->bcdDevice);
1.143.6.1! mjf       824:        uaa.class = dd->bDeviceClass;
        !           825:        uaa.subclass = dd->bDeviceSubClass;
        !           826:        uaa.proto = dd->bDeviceProtocol;
1.18      augustss  827:
                    828:        /* First try with device specific drivers. */
1.60      augustss  829:        DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
1.34      augustss  830:        dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
                    831:        if (dv) {
                    832:                dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
1.57      augustss  833:                if (dev->subdevs == NULL)
1.34      augustss  834:                        return (USBD_NOMEM);
                    835:                dev->subdevs[0] = dv;
                    836:                dev->subdevs[1] = 0;
1.18      augustss  837:                return (USBD_NORMAL_COMPLETION);
1.34      augustss  838:        }
1.18      augustss  839:
                    840:        DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
                    841:
1.143.6.1! mjf       842:        uiaa.device = dev;
        !           843:        uiaa.port = port;
        !           844:        uiaa.vendor = UGETW(dd->idVendor);
        !           845:        uiaa.product = UGETW(dd->idProduct);
        !           846:        uiaa.release = UGETW(dd->bcdDevice);
        !           847:
1.60      augustss  848:        DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
                    849:                 dd->bNumConfigurations));
1.18      augustss  850:        /* Next try with interface drivers. */
                    851:        for (confi = 0; confi < dd->bNumConfigurations; confi++) {
                    852:                DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
                    853:                            confi));
1.53      augustss  854:                err = usbd_set_config_index(dev, confi, 1);
                    855:                if (err) {
1.18      augustss  856: #ifdef USB_DEBUG
                    857:                        DPRINTF(("%s: port %d, set config at addr %d failed, "
1.43      augustss  858:                                 "error=%s\n", USBDEVPTRNAME(parent), port,
1.53      augustss  859:                                 addr, usbd_errstr(err)));
1.18      augustss  860: #else
                    861:                        printf("%s: port %d, set config at addr %d failed\n",
1.43      augustss  862:                               USBDEVPTRNAME(parent), port, addr);
1.18      augustss  863: #endif
1.27      augustss  864: #if defined(__FreeBSD__)
1.52      augustss  865:                        device_delete_child(parent, bdev);
1.27      augustss  866: #endif
1.52      augustss  867:
1.53      augustss  868:                        return (err);
1.18      augustss  869:                }
1.20      augustss  870:                nifaces = dev->cdesc->bNumInterface;
1.143.6.1! mjf       871:                uiaa.configno = dev->cdesc->bConfigurationValue;
1.132     christos  872:                ifaces = malloc(nifaces * sizeof(*ifaces), M_USB, M_NOWAIT);
                    873:                if (ifaces == NULL)
                    874:                        goto nomem;
1.20      augustss  875:                for (i = 0; i < nifaces; i++)
                    876:                        ifaces[i] = &dev->ifaces[i];
1.143.6.1! mjf       877:                uiaa.ifaces = ifaces;
        !           878:                uiaa.nifaces = nifaces;
1.34      augustss  879:                dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);
1.57      augustss  880:                if (dev->subdevs == NULL) {
1.132     christos  881:                        free(ifaces, M_USB);
                    882: nomem:
1.52      augustss  883: #if defined(__FreeBSD__)
                    884:                        device_delete_child(parent, bdev);
                    885: #endif
1.34      augustss  886:                        return (USBD_NOMEM);
1.52      augustss  887:                }
                    888:
                    889:                found = 0;
                    890:                for (i = 0; i < nifaces; i++) {
1.53      augustss  891:                        if (ifaces[i] == NULL)
1.20      augustss  892:                                continue; /* interface already claimed */
1.143.6.1! mjf       893:                        uiaa.iface = ifaces[i];
        !           894:                        uiaa.class = ifaces[i]->idesc->bInterfaceClass;
        !           895:                        uiaa.subclass = ifaces[i]->idesc->bInterfaceSubClass;
        !           896:                        uiaa.proto = ifaces[i]->idesc->bInterfaceProtocol;
        !           897:                        uiaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
        !           898:                        dv = USB_DO_IFATTACH(dev, bdev, parent, &uiaa, usbd_ifprint,
        !           899:                                             usbd_ifsubmatch);
1.53      augustss  900:                        if (dv != NULL) {
1.34      augustss  901:                                dev->subdevs[found++] = dv;
                    902:                                dev->subdevs[found] = 0;
1.20      augustss  903:                                ifaces[i] = 0; /* consumed */
1.52      augustss  904:
                    905: #if defined(__FreeBSD__)
                    906:                                /* create another child for the next iface */
                    907:                                bdev = device_add_child(parent, NULL, -1,&uaa);
                    908:                                if (!bdev) {
                    909:                                        printf("%s: Device creation failed\n",
                    910:                                        USBDEVNAME(dev->bus->bdev));
1.132     christos  911:                                        free(ifaces, M_USB);
1.52      augustss  912:                                        return (USBD_NORMAL_COMPLETION);
                    913:                                }
                    914:                                device_quiet(bdev);
                    915: #endif
1.20      augustss  916:                        }
1.18      augustss  917:                }
1.52      augustss  918:                if (found != 0) {
                    919: #if defined(__FreeBSD__)
                    920:                        /* remove the last created child again; it is unused */
                    921:                        device_delete_child(parent, bdev);
                    922: #endif
1.132     christos  923:                        free(ifaces, M_USB);
1.18      augustss  924:                        return (USBD_NORMAL_COMPLETION);
1.52      augustss  925:                }
1.132     christos  926:                free(ifaces, M_USB);
1.34      augustss  927:                free(dev->subdevs, M_USB);
                    928:                dev->subdevs = 0;
1.18      augustss  929:        }
1.21      augustss  930:        /* No interfaces were attached in any of the configurations. */
1.34      augustss  931:
                    932:        if (dd->bNumConfigurations > 1) /* don't change if only 1 config */
1.18      augustss  933:                usbd_set_config_index(dev, 0, 0);
                    934:
                    935:        DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
                    936:
                    937:        /* Finally try the generic driver. */
                    938:        uaa.usegeneric = 1;
1.34      augustss  939:        dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
1.53      augustss  940:        if (dv != NULL) {
1.34      augustss  941:                dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
                    942:                if (dev->subdevs == 0)
                    943:                        return (USBD_NOMEM);
                    944:                dev->subdevs[0] = dv;
                    945:                dev->subdevs[1] = 0;
1.18      augustss  946:                return (USBD_NORMAL_COMPLETION);
1.34      augustss  947:        }
1.18      augustss  948:
1.99      augustss  949:        /*
1.18      augustss  950:         * The generic attach failed, but leave the device as it is.
                    951:         * We just did not find any drivers, that's all.  The device is
                    952:         * fully operational and not harming anyone.
                    953:         */
                    954:        DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
1.27      augustss  955: #if defined(__FreeBSD__)
1.52      augustss  956:        device_delete_child(parent, bdev);
1.27      augustss  957: #endif
                    958:        return (USBD_NORMAL_COMPLETION);
1.18      augustss  959: }
                    960:
                    961:
1.1       augustss  962: /*
                    963:  * Called when a new device has been put in the powered state,
                    964:  * but not yet in the addressed state.
                    965:  * Get initial descriptor, set the address, get full descriptor,
                    966:  * and attach a driver.
                    967:  */
                    968: usbd_status
1.78      augustss  969: usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth,
1.94      augustss  970:                int speed, int port, struct usbd_port *up)
1.1       augustss  971: {
1.120     augustss  972:        usbd_device_handle dev, adev;
1.94      augustss  973:        struct usbd_device *hub;
1.18      augustss  974:        usb_device_descriptor_t *dd;
1.107     augustss  975:        usb_port_status_t ps;
1.53      augustss  976:        usbd_status err;
1.1       augustss  977:        int addr;
1.18      augustss  978:        int i;
1.120     augustss  979:        int p;
1.1       augustss  980:
1.94      augustss  981:        DPRINTF(("usbd_new_device bus=%p port=%d depth=%d speed=%d\n",
                    982:                 bus, port, depth, speed));
1.1       augustss  983:        addr = usbd_getnewaddr(bus);
                    984:        if (addr < 0) {
1.99      augustss  985:                printf("%s: No free USB addresses, new device ignored.\n",
1.18      augustss  986:                       USBDEVNAME(bus->bdev));
1.1       augustss  987:                return (USBD_NO_ADDR);
                    988:        }
                    989:
1.97      tsutsui   990:        dev = malloc(sizeof *dev, M_USB, M_NOWAIT|M_ZERO);
1.53      augustss  991:        if (dev == NULL)
1.1       augustss  992:                return (USBD_NOMEM);
                    993:
                    994:        dev->bus = bus;
                    995:
                    996:        /* Set up default endpoint handle. */
                    997:        dev->def_ep.edesc = &dev->def_ep_desc;
                    998:
                    999:        /* Set up default endpoint descriptor. */
                   1000:        dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
                   1001:        dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
                   1002:        dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
                   1003:        dev->def_ep_desc.bmAttributes = UE_CONTROL;
                   1004:        USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
                   1005:        dev->def_ep_desc.bInterval = 0;
                   1006:
                   1007:        dev->quirks = &usbd_no_quirk;
                   1008:        dev->address = USB_START_ADDR;
1.4       augustss 1009:        dev->ddesc.bMaxPacketSize = 0;
1.1       augustss 1010:        dev->depth = depth;
                   1011:        dev->powersrc = up;
1.94      augustss 1012:        dev->myhub = up->parent;
1.120     augustss 1013:
                   1014:        up->device = dev;
                   1015:
                   1016:        /* Locate port on upstream high speed hub */
                   1017:        for (adev = dev, hub = up->parent;
1.94      augustss 1018:             hub != NULL && hub->speed != USB_SPEED_HIGH;
1.120     augustss 1019:             adev = hub, hub = hub->myhub)
1.94      augustss 1020:                ;
1.120     augustss 1021:        if (hub) {
                   1022:                for (p = 0; p < hub->hub->hubdesc.bNbrPorts; p++) {
                   1023:                        if (hub->hub->ports[p].device == adev) {
                   1024:                                dev->myhsport = &hub->hub->ports[p];
                   1025:                                goto found;
                   1026:                        }
                   1027:                }
                   1028:                panic("usbd_new_device: cannot find HS port\n");
                   1029:        found:
                   1030:                DPRINTFN(1,("usbd_new_device: high speed port %d\n", p));
                   1031:        } else {
                   1032:                dev->myhsport = NULL;
                   1033:        }
1.94      augustss 1034:        dev->speed = speed;
1.22      augustss 1035:        dev->langid = USBD_NOLANG;
1.50      augustss 1036:        dev->cookie.cookie = ++usb_cookie_no;
1.1       augustss 1037:
1.67      soren    1038:        /* Establish the default pipe. */
1.63      augustss 1039:        err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
                   1040:                              &dev->default_pipe);
1.53      augustss 1041:        if (err) {
1.18      augustss 1042:                usbd_remove_device(dev, up);
1.53      augustss 1043:                return (err);
1.18      augustss 1044:        }
1.1       augustss 1045:
1.111     augustss 1046:        /* Set the address.  Do this early; some devices need that. */
1.143.6.1! mjf      1047:        /* Try a few times in case the device is slow (i.e. outside specs) */
1.111     augustss 1048:        DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
1.143.6.1! mjf      1049:        for (i = 0; i < 15; i++) {
        !          1050:                err = usbd_set_address(dev, addr);
        !          1051:                if (!err)
        !          1052:                        break;
        !          1053:                usbd_delay_ms(dev, 200);
        !          1054:                if ((i & 3) == 3) {
        !          1055:                        DPRINTFN(-1,("usbd_new_device: set address %d "
        !          1056:                            "failed - trying a port reset\n", addr));
        !          1057:                        usbd_reset_port(up->parent, port, &ps);
        !          1058:                }
        !          1059:        }
1.111     augustss 1060:        if (err) {
                   1061:                DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
                   1062:                err = USBD_SET_ADDR_FAILED;
                   1063:                usbd_remove_device(dev, up);
                   1064:                return (err);
                   1065:        }
                   1066:        /* Allow device time to set new address */
                   1067:        usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
                   1068:        dev->address = addr;    /* New device address now */
                   1069:        bus->devices[addr] = dev;
                   1070:
1.18      augustss 1071:        dd = &dev->ddesc;
1.6       augustss 1072:        /* Try a few times in case the device is slow (i.e. outside specs.) */
1.107     augustss 1073:        for (i = 0; i < 10; i++) {
1.6       augustss 1074:                /* Get the first 8 bytes of the device descriptor. */
1.53      augustss 1075:                err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
                   1076:                if (!err)
1.6       augustss 1077:                        break;
1.23      augustss 1078:                usbd_delay_ms(dev, 200);
1.107     augustss 1079:                if ((i & 3) == 3)
                   1080:                        usbd_reset_port(up->parent, port, &ps);
1.6       augustss 1081:        }
1.53      augustss 1082:        if (err) {
1.14      drochner 1083:                DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
1.53      augustss 1084:                              "failed\n", addr));
1.18      augustss 1085:                usbd_remove_device(dev, up);
1.53      augustss 1086:                return (err);
1.95      augustss 1087:        }
                   1088:
                   1089:        if (speed == USB_SPEED_HIGH) {
                   1090:                /* Max packet size must be 64 (sec 5.5.3). */
                   1091:                if (dd->bMaxPacketSize != USB_2_MAX_CTRL_PACKET) {
                   1092: #ifdef DIAGNOSTIC
                   1093:                        printf("usbd_new_device: addr=%d bad max packet size\n",
                   1094:                               addr);
                   1095: #endif
                   1096:                        dd->bMaxPacketSize = USB_2_MAX_CTRL_PACKET;
                   1097:                }
1.18      augustss 1098:        }
                   1099:
1.39      augustss 1100:        DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
1.99      augustss 1101:                 "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n",
1.39      augustss 1102:                 addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
1.99      augustss 1103:                 dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength,
1.94      augustss 1104:                 dev->speed));
1.39      augustss 1105:
1.18      augustss 1106:        if (dd->bDescriptorType != UDESC_DEVICE) {
                   1107:                /* Illegal device descriptor */
                   1108:                DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
                   1109:                             dd->bDescriptorType));
                   1110:                usbd_remove_device(dev, up);
                   1111:                return (USBD_INVAL);
1.1       augustss 1112:        }
                   1113:
1.39      augustss 1114:        if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) {
                   1115:                DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength));
                   1116:                usbd_remove_device(dev, up);
                   1117:                return (USBD_INVAL);
                   1118:        }
1.4       augustss 1119:
1.18      augustss 1120:        USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
1.1       augustss 1121:
1.62      augustss 1122:        err = usbd_reload_device_desc(dev);
1.53      augustss 1123:        if (err) {
1.14      drochner 1124:                DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
                   1125:                              "failed\n", addr));
1.18      augustss 1126:                usbd_remove_device(dev, up);
1.53      augustss 1127:                return (err);
1.1       augustss 1128:        }
                   1129:
                   1130:        /* Assume 100mA bus powered for now. Changed when configured. */
                   1131:        dev->power = USB_MIN_POWER;
                   1132:        dev->self_powered = 0;
                   1133:
1.99      augustss 1134:        DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
1.1       augustss 1135:                 addr, dev, parent));
1.99      augustss 1136:
1.65      augustss 1137:        usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);
1.1       augustss 1138:
1.53      augustss 1139:        err = usbd_probe_and_attach(parent, dev, port, addr);
                   1140:        if (err) {
1.18      augustss 1141:                usbd_remove_device(dev, up);
1.53      augustss 1142:                return (err);
1.18      augustss 1143:        }
1.65      augustss 1144:
1.18      augustss 1145:        return (USBD_NORMAL_COMPLETION);
1.62      augustss 1146: }
                   1147:
                   1148: usbd_status
1.78      augustss 1149: usbd_reload_device_desc(usbd_device_handle dev)
1.62      augustss 1150: {
                   1151:        usbd_status err;
                   1152:
                   1153:        /* Get the full device descriptor. */
                   1154:        err = usbd_get_device_desc(dev, &dev->ddesc);
                   1155:        if (err)
                   1156:                return (err);
                   1157:
                   1158:        /* Figure out what's wrong with this device. */
                   1159:        dev->quirks = usbd_find_quirk(&dev->ddesc);
                   1160:
                   1161:        return (USBD_NORMAL_COMPLETION);
1.18      augustss 1162: }
1.1       augustss 1163:
1.18      augustss 1164: void
1.78      augustss 1165: usbd_remove_device(usbd_device_handle dev, struct usbd_port *up)
1.18      augustss 1166: {
                   1167:        DPRINTF(("usbd_remove_device: %p\n", dev));
1.99      augustss 1168:
1.53      augustss 1169:        if (dev->default_pipe != NULL)
1.18      augustss 1170:                usbd_kill_pipe(dev->default_pipe);
1.120     augustss 1171:        up->device = NULL;
                   1172:        dev->bus->devices[dev->address] = NULL;
1.1       augustss 1173:
                   1174:        free(dev, M_USB);
                   1175: }
                   1176:
1.37      augustss 1177: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.1       augustss 1178: int
1.78      augustss 1179: usbd_print(void *aux, const char *pnp)
1.1       augustss 1180: {
                   1181:        struct usb_attach_arg *uaa = aux;
                   1182:
                   1183:        DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
                   1184:        if (pnp) {
1.134     christos 1185: #define USB_DEVINFO 1024
                   1186:                char *devinfo;
1.1       augustss 1187:                if (!uaa->usegeneric)
                   1188:                        return (QUIET);
1.134     christos 1189:                devinfo = malloc(USB_DEVINFO, M_TEMP, M_WAITOK);
                   1190:                usbd_devinfo(uaa->device, 1, devinfo, USB_DEVINFO);
1.101     thorpej  1191:                aprint_normal("%s, %s", devinfo, pnp);
1.134     christos 1192:                free(devinfo, M_TEMP);
1.1       augustss 1193:        }
                   1194:        if (uaa->port != 0)
1.101     thorpej  1195:                aprint_normal(" port %d", uaa->port);
1.143.6.1! mjf      1196: #if 0
        !          1197:        /*
        !          1198:         * It gets very crowded with these locators on the attach line.
        !          1199:         * They are not really needed since they are printed in the clear
        !          1200:         * by each driver.
        !          1201:         */
        !          1202:        if (uaa->vendor != UHUB_UNK_VENDOR)
        !          1203:                aprint_normal(" vendor 0x%04x", uaa->vendor);
        !          1204:        if (uaa->product != UHUB_UNK_PRODUCT)
        !          1205:                aprint_normal(" product 0x%04x", uaa->product);
        !          1206:        if (uaa->release != UHUB_UNK_RELEASE)
        !          1207:                aprint_normal(" release 0x%04x", uaa->release);
        !          1208: #endif
        !          1209:        return (UNCONF);
        !          1210: }
        !          1211:
        !          1212: int
        !          1213: usbd_ifprint(void *aux, const char *pnp)
        !          1214: {
        !          1215:        struct usbif_attach_arg *uaa = aux;
        !          1216:
        !          1217:        DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
        !          1218:        if (pnp)
        !          1219:                return (QUIET);
        !          1220:        if (uaa->port != 0)
        !          1221:                aprint_normal(" port %d", uaa->port);
1.11      augustss 1222:        if (uaa->configno != UHUB_UNK_CONFIGURATION)
1.101     thorpej  1223:                aprint_normal(" configuration %d", uaa->configno);
1.11      augustss 1224:        if (uaa->ifaceno != UHUB_UNK_INTERFACE)
1.101     thorpej  1225:                aprint_normal(" interface %d", uaa->ifaceno);
1.32      augustss 1226: #if 0
1.99      augustss 1227:        /*
1.32      augustss 1228:         * It gets very crowded with these locators on the attach line.
                   1229:         * They are not really needed since they are printed in the clear
                   1230:         * by each driver.
                   1231:         */
                   1232:        if (uaa->vendor != UHUB_UNK_VENDOR)
1.101     thorpej  1233:                aprint_normal(" vendor 0x%04x", uaa->vendor);
1.32      augustss 1234:        if (uaa->product != UHUB_UNK_PRODUCT)
1.101     thorpej  1235:                aprint_normal(" product 0x%04x", uaa->product);
1.32      augustss 1236:        if (uaa->release != UHUB_UNK_RELEASE)
1.101     thorpej  1237:                aprint_normal(" release 0x%04x", uaa->release);
1.32      augustss 1238: #endif
1.1       augustss 1239:        return (UNCONF);
                   1240: }
                   1241:
1.37      augustss 1242: #if defined(__NetBSD__)
1.1       augustss 1243: int
1.118     drochner 1244: usbd_submatch(struct device *parent, struct cfdata *cf,
1.138     christos 1245:              const int *ldesc, void *aux)
1.1       augustss 1246: {
1.37      augustss 1247: #elif defined(__OpenBSD__)
                   1248: int
1.78      augustss 1249: usbd_submatch(struct device *parent, void *match, void *aux)
1.37      augustss 1250: {
                   1251:        struct cfdata *cf = match;
                   1252: #endif
1.1       augustss 1253:        struct usb_attach_arg *uaa = aux;
                   1254:
1.143.6.1! mjf      1255:        DPRINTFN(5,("usbd_submatch port=%d,%d "
        !          1256:            "vendor=%d,%d product=%d,%d release=%d,%d\n",
        !          1257:            uaa->port, cf->uhubcf_port,
        !          1258:            uaa->vendor, cf->uhubcf_vendor,
        !          1259:            uaa->product, cf->uhubcf_product,
        !          1260:            uaa->release, cf->uhubcf_release));
        !          1261:        if (uaa->port != 0 &&   /* root hub has port 0, it should match */
        !          1262:            ((cf->uhubcf_port != UHUB_UNK_PORT &&
        !          1263:              cf->uhubcf_port != uaa->port) ||
        !          1264:             (uaa->vendor != UHUB_UNK_VENDOR &&
        !          1265:              cf->uhubcf_vendor != UHUB_UNK_VENDOR &&
        !          1266:              cf->uhubcf_vendor != uaa->vendor) ||
        !          1267:             (uaa->product != UHUB_UNK_PRODUCT &&
        !          1268:              cf->uhubcf_product != UHUB_UNK_PRODUCT &&
        !          1269:              cf->uhubcf_product != uaa->product) ||
        !          1270:             (uaa->release != UHUB_UNK_RELEASE &&
        !          1271:              cf->uhubcf_release != UHUB_UNK_RELEASE &&
        !          1272:              cf->uhubcf_release != uaa->release)
        !          1273:             )
        !          1274:           )
        !          1275:                return 0;
        !          1276:        return (config_match(parent, cf, aux));
        !          1277: }
        !          1278:
        !          1279: int
        !          1280: usbd_ifsubmatch(struct device *parent, struct cfdata *cf,
        !          1281:              const int *ldesc, void *aux)
        !          1282: {
        !          1283:        struct usbif_attach_arg *uaa = aux;
        !          1284:
1.72      augustss 1285:        DPRINTFN(5,("usbd_submatch port=%d,%d configno=%d,%d "
                   1286:            "ifaceno=%d,%d vendor=%d,%d product=%d,%d release=%d,%d\n",
                   1287:            uaa->port, cf->uhubcf_port,
                   1288:            uaa->configno, cf->uhubcf_configuration,
                   1289:            uaa->ifaceno, cf->uhubcf_interface,
                   1290:            uaa->vendor, cf->uhubcf_vendor,
                   1291:            uaa->product, cf->uhubcf_product,
                   1292:            uaa->release, cf->uhubcf_release));
                   1293:        if (uaa->port != 0 &&   /* root hub has port 0, it should match */
1.117     drochner 1294:            ((cf->uhubcf_port != UHUB_UNK_PORT &&
1.72      augustss 1295:              cf->uhubcf_port != uaa->port) ||
                   1296:             (uaa->configno != UHUB_UNK_CONFIGURATION &&
                   1297:              cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&
                   1298:              cf->uhubcf_configuration != uaa->configno) ||
                   1299:             (uaa->ifaceno != UHUB_UNK_INTERFACE &&
                   1300:              cf->uhubcf_interface != UHUB_UNK_INTERFACE &&
                   1301:              cf->uhubcf_interface != uaa->ifaceno) ||
                   1302:             (uaa->vendor != UHUB_UNK_VENDOR &&
                   1303:              cf->uhubcf_vendor != UHUB_UNK_VENDOR &&
                   1304:              cf->uhubcf_vendor != uaa->vendor) ||
                   1305:             (uaa->product != UHUB_UNK_PRODUCT &&
                   1306:              cf->uhubcf_product != UHUB_UNK_PRODUCT &&
                   1307:              cf->uhubcf_product != uaa->product) ||
                   1308:             (uaa->release != UHUB_UNK_RELEASE &&
                   1309:              cf->uhubcf_release != UHUB_UNK_RELEASE &&
                   1310:              cf->uhubcf_release != uaa->release)
                   1311:             )
1.32      augustss 1312:           )
1.1       augustss 1313:                return 0;
1.100     thorpej  1314:        return (config_match(parent, cf, aux));
1.13      augustss 1315: }
1.18      augustss 1316:
                   1317: #endif
1.13      augustss 1318:
                   1319: void
1.82      augustss 1320: usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di,
                   1321:                     int usedev)
1.13      augustss 1322: {
                   1323:        struct usbd_port *p;
1.56      augustss 1324:        int i, err, s;
1.13      augustss 1325:
1.98      christos 1326:        di->udi_bus = USBDEVUNIT(dev->bus->bdev);
                   1327:        di->udi_addr = dev->address;
                   1328:        di->udi_cookie = dev->cookie;
1.139     pavel    1329:        usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product, usedev, 1);
1.113     itojun   1330:        usbd_printBCD(di->udi_release, sizeof(di->udi_release),
                   1331:            UGETW(dev->ddesc.bcdDevice));
1.123     augustss 1332:        di->udi_serial[0] = 0;
                   1333:        if (usedev)
                   1334:                (void)usbd_get_string(dev, dev->ddesc.iSerialNumber,
                   1335:                                      di->udi_serial);
1.98      christos 1336:        di->udi_vendorNo = UGETW(dev->ddesc.idVendor);
                   1337:        di->udi_productNo = UGETW(dev->ddesc.idProduct);
                   1338:        di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice);
                   1339:        di->udi_class = dev->ddesc.bDeviceClass;
                   1340:        di->udi_subclass = dev->ddesc.bDeviceSubClass;
                   1341:        di->udi_protocol = dev->ddesc.bDeviceProtocol;
                   1342:        di->udi_config = dev->config;
                   1343:        di->udi_power = dev->self_powered ? 0 : dev->power;
                   1344:        di->udi_speed = dev->speed;
1.65      augustss 1345:
                   1346:        if (dev->subdevs != NULL) {
                   1347:                for (i = 0; dev->subdevs[i] &&
                   1348:                             i < USB_MAX_DEVNAMES; i++) {
1.98      christos 1349:                        strncpy(di->udi_devnames[i], USBDEVPTRNAME(dev->subdevs[i]),
1.65      augustss 1350:                                USB_MAX_DEVNAMELEN);
1.98      christos 1351:                        di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';
1.65      augustss 1352:                 }
                   1353:         } else {
                   1354:                 i = 0;
                   1355:         }
                   1356:         for (/*i is set */; i < USB_MAX_DEVNAMES; i++)
1.98      christos 1357:                 di->udi_devnames[i][0] = 0;                 /* empty */
1.65      augustss 1358:
1.13      augustss 1359:        if (dev->hub) {
1.99      augustss 1360:                for (i = 0;
1.98      christos 1361:                     i < sizeof(di->udi_ports) / sizeof(di->udi_ports[0]) &&
1.13      augustss 1362:                             i < dev->hub->hubdesc.bNbrPorts;
                   1363:                     i++) {
                   1364:                        p = &dev->hub->ports[i];
                   1365:                        if (p->device)
1.56      augustss 1366:                                err = p->device->address;
1.13      augustss 1367:                        else {
                   1368:                                s = UGETW(p->status.wPortStatus);
                   1369:                                if (s & UPS_PORT_ENABLED)
1.56      augustss 1370:                                        err = USB_PORT_ENABLED;
1.13      augustss 1371:                                else if (s & UPS_SUSPEND)
1.56      augustss 1372:                                        err = USB_PORT_SUSPENDED;
1.13      augustss 1373:                                else if (s & UPS_PORT_POWER)
1.56      augustss 1374:                                        err = USB_PORT_POWERED;
1.13      augustss 1375:                                else
1.56      augustss 1376:                                        err = USB_PORT_DISABLED;
1.13      augustss 1377:                        }
1.98      christos 1378:                        di->udi_ports[i] = err;
1.13      augustss 1379:                }
1.98      christos 1380:                di->udi_nports = dev->hub->hubdesc.bNbrPorts;
1.13      augustss 1381:        } else
1.98      christos 1382:                di->udi_nports = 0;
1.34      augustss 1383: }
                   1384:
1.139     pavel    1385: #ifdef COMPAT_30
                   1386: void
                   1387: usbd_fill_deviceinfo_old(usbd_device_handle dev, struct usb_device_info_old *di,
                   1388:                          int usedev)
                   1389: {
                   1390:        struct usbd_port *p;
                   1391:        int i, err, s;
                   1392:
                   1393:        di->udi_bus = USBDEVUNIT(dev->bus->bdev);
                   1394:        di->udi_addr = dev->address;
                   1395:        di->udi_cookie = dev->cookie;
                   1396:        usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product, usedev, 0);
                   1397:        usbd_printBCD(di->udi_release, sizeof(di->udi_release),
                   1398:            UGETW(dev->ddesc.bcdDevice));
                   1399:        di->udi_vendorNo = UGETW(dev->ddesc.idVendor);
                   1400:        di->udi_productNo = UGETW(dev->ddesc.idProduct);
                   1401:        di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice);
                   1402:        di->udi_class = dev->ddesc.bDeviceClass;
                   1403:        di->udi_subclass = dev->ddesc.bDeviceSubClass;
                   1404:        di->udi_protocol = dev->ddesc.bDeviceProtocol;
                   1405:        di->udi_config = dev->config;
                   1406:        di->udi_power = dev->self_powered ? 0 : dev->power;
                   1407:        di->udi_speed = dev->speed;
                   1408:
                   1409:        if (dev->subdevs != NULL) {
                   1410:                for (i = 0; dev->subdevs[i] &&
                   1411:                             i < USB_MAX_DEVNAMES; i++) {
                   1412:                        strncpy(di->udi_devnames[i], USBDEVPTRNAME(dev->subdevs[i]),
                   1413:                                USB_MAX_DEVNAMELEN);
                   1414:                        di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';
                   1415:                }
                   1416:        } else {
                   1417:                i = 0;
                   1418:        }
                   1419:        for (/*i is set */; i < USB_MAX_DEVNAMES; i++)
                   1420:                di->udi_devnames[i][0] = 0;              /* empty */
                   1421:
                   1422:        if (dev->hub) {
                   1423:                for (i = 0;
                   1424:                     i < sizeof(di->udi_ports) / sizeof(di->udi_ports[0]) &&
                   1425:                             i < dev->hub->hubdesc.bNbrPorts;
                   1426:                     i++) {
                   1427:                        p = &dev->hub->ports[i];
                   1428:                        if (p->device)
                   1429:                                err = p->device->address;
                   1430:                        else {
                   1431:                                s = UGETW(p->status.wPortStatus);
                   1432:                                if (s & UPS_PORT_ENABLED)
                   1433:                                        err = USB_PORT_ENABLED;
                   1434:                                else if (s & UPS_SUSPEND)
                   1435:                                        err = USB_PORT_SUSPENDED;
                   1436:                                else if (s & UPS_PORT_POWER)
                   1437:                                        err = USB_PORT_POWERED;
                   1438:                                else
                   1439:                                        err = USB_PORT_DISABLED;
                   1440:                        }
                   1441:                        di->udi_ports[i] = err;
                   1442:                }
                   1443:                di->udi_nports = dev->hub->hubdesc.bNbrPorts;
                   1444:        } else
                   1445:                di->udi_nports = 0;
                   1446: }
                   1447: #endif
                   1448:
                   1449:
1.34      augustss 1450: void
1.78      augustss 1451: usb_free_device(usbd_device_handle dev)
1.34      augustss 1452: {
                   1453:        int ifcidx, nifc;
                   1454:
1.53      augustss 1455:        if (dev->default_pipe != NULL)
1.34      augustss 1456:                usbd_kill_pipe(dev->default_pipe);
1.53      augustss 1457:        if (dev->ifaces != NULL) {
1.34      augustss 1458:                nifc = dev->cdesc->bNumInterface;
                   1459:                for (ifcidx = 0; ifcidx < nifc; ifcidx++)
                   1460:                        usbd_free_iface_data(dev, ifcidx);
                   1461:                free(dev->ifaces, M_USB);
                   1462:        }
1.53      augustss 1463:        if (dev->cdesc != NULL)
1.34      augustss 1464:                free(dev->cdesc, M_USB);
1.53      augustss 1465:        if (dev->subdevs != NULL)
1.34      augustss 1466:                free(dev->subdevs, M_USB);
                   1467:        free(dev, M_USB);
1.1       augustss 1468: }
1.47      augustss 1469:
                   1470: /*
                   1471:  * The general mechanism for detaching drivers works as follows: Each
                   1472:  * driver is responsible for maintaining a reference count on the
                   1473:  * number of outstanding references to its softc (e.g.  from
                   1474:  * processing hanging in a read or write).  The detach method of the
                   1475:  * driver decrements this counter and flags in the softc that the
                   1476:  * driver is dying and then wakes any sleepers.  It then sleeps on the
                   1477:  * softc.  Each place that can sleep must maintain the reference
                   1478:  * count.  When the reference count drops to -1 (0 is the normal value
                   1479:  * of the reference count) the a wakeup on the softc is performed
                   1480:  * signaling to the detach waiter that all references are gone.
                   1481:  */
                   1482:
                   1483: /*
                   1484:  * Called from process context when we discover that a port has
                   1485:  * been disconnected.
                   1486:  */
                   1487: void
1.78      augustss 1488: usb_disconnect_port(struct usbd_port *up, device_ptr_t parent)
1.47      augustss 1489: {
                   1490:        usbd_device_handle dev = up->device;
1.51      augustss 1491:        char *hubname = USBDEVPTRNAME(parent);
1.47      augustss 1492:        int i;
                   1493:
1.99      augustss 1494:        DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
1.47      augustss 1495:                    up, dev, up->portno));
1.48      augustss 1496:
                   1497: #ifdef DIAGNOSTIC
1.57      augustss 1498:        if (dev == NULL) {
1.48      augustss 1499:                printf("usb_disconnect_port: no device\n");
                   1500:                return;
                   1501:        }
                   1502: #endif
1.47      augustss 1503:
1.55      augustss 1504:        if (dev->subdevs != NULL) {
1.57      augustss 1505:                DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
1.47      augustss 1506:                for (i = 0; dev->subdevs[i]; i++) {
1.99      augustss 1507:                        printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]),
1.51      augustss 1508:                               hubname);
                   1509:                        if (up->portno != 0)
                   1510:                                printf(" port %d", up->portno);
                   1511:                        printf(" (addr %d) disconnected\n", dev->address);
1.47      augustss 1512:                        config_detach(dev->subdevs[i], DETACH_FORCE);
1.110     drochner 1513:                        dev->subdevs[i] = 0;
1.47      augustss 1514:                }
                   1515:        }
                   1516:
1.65      augustss 1517:        usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);
1.57      augustss 1518:        dev->bus->devices[dev->address] = NULL;
                   1519:        up->device = NULL;
1.47      augustss 1520:        usb_free_device(dev);
                   1521: }
                   1522:
1.54      augustss 1523: #ifdef __OpenBSD__
1.79      augustss 1524: void *usb_realloc(void *p, u_int size, int pool, int flags)
1.54      augustss 1525: {
                   1526:        void *q;
                   1527:
                   1528:        q = malloc(size, pool, flags);
                   1529:        if (q == NULL)
                   1530:                return (NULL);
                   1531:        bcopy(p, q, size);
                   1532:        free(p, pool);
                   1533:        return (q);
                   1534: }
                   1535: #endif

CVSweb <webmaster@jp.NetBSD.org>