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

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/usb/usb_subr.c between version 1.152 and 1.152.4.4

version 1.152, 2008/04/05 16:35:35 version 1.152.4.4, 2009/09/16 13:37:58
Line 17 
Line 17 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software  
  *    must display the following acknowledgement:  
  *        This product includes software developed by the NetBSD  
  *        Foundation, Inc. and its contributors.  
  * 4. Neither the name of The NetBSD Foundation nor the names of its  
  *    contributors may be used to endorse or promote products derived  
  *    from this software without specific prior written permission.  
  *   *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS   * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Line 48  __KERNEL_RCSID(0, "$NetBSD$");
Line 41  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/kernel.h>  #include <sys/kernel.h>
 #include <sys/malloc.h>  #include <sys/malloc.h>
 #if defined(__NetBSD__) || defined(__OpenBSD__)  
 #include <sys/device.h>  #include <sys/device.h>
 #include <sys/select.h>  #include <sys/select.h>
 #elif defined(__FreeBSD__)  
 #include <sys/module.h>  
 #include <sys/bus.h>  
 #endif  
 #include <sys/proc.h>  #include <sys/proc.h>
   
 #include <sys/bus.h>  #include <sys/bus.h>
Line 67  __KERNEL_RCSID(0, "$NetBSD$");
Line 55  __KERNEL_RCSID(0, "$NetBSD$");
 #include <dev/usb/usbdevs.h>  #include <dev/usb/usbdevs.h>
 #include <dev/usb/usb_quirks.h>  #include <dev/usb/usb_quirks.h>
   
 #if defined(__FreeBSD__)  #include "locators.h"
 #include <machine/clock.h>  
 #define delay(d)         DELAY(d)  
 #endif  
   
 #ifdef USB_DEBUG  #ifdef USB_DEBUG
 #define DPRINTF(x)      if (usbdebug) logprintf x  #define DPRINTF(x)      if (usbdebug) logprintf x
Line 88  Static void usbd_devinfo_vp(usbd_device_
Line 73  Static void usbd_devinfo_vp(usbd_device_
                             char *p, int usedev,                              char *p, int usedev,
                             int useencoded );                              int useencoded );
 Static int usbd_getnewaddr(usbd_bus_handle bus);  Static int usbd_getnewaddr(usbd_bus_handle bus);
 #if defined(__NetBSD__)  
 Static int usbd_print(void *, const char *);  Static int usbd_print(void *, const char *);
 Static int usbd_ifprint(void *, const char *);  Static int usbd_ifprint(void *, const char *);
 Static int usbd_submatch(device_ptr_t, struct cfdata *,  
                          const int *, void *);  
 Static int usbd_ifsubmatch(device_ptr_t, struct cfdata *,  
                            const int *, void *);  
 #elif defined(__OpenBSD__)  
 Static int usbd_print(void *aux, const char *pnp);  
 Static int usbd_submatch(device_ptr_t, void *, void *);  
 #endif  
 Static void usbd_free_iface_data(usbd_device_handle dev, int ifcno);  Static void usbd_free_iface_data(usbd_device_handle dev, int ifcno);
 Static void usbd_kill_pipe(usbd_pipe_handle);  Static void usbd_kill_pipe(usbd_pipe_handle);
 Static usbd_status usbd_probe_and_attach(device_ptr_t parent,  usbd_status usbd_attach_roothub(device_t, usbd_device_handle);
                                  usbd_device_handle dev, int port, int addr);  Static usbd_status usbd_probe_and_attach(device_t parent,
                                    usbd_device_handle dev, int port, int addr);
   
 Static u_int32_t usb_cookie_no = 0;  Static u_int32_t usb_cookie_no = 0;
   
Line 578  usbd_set_config_index(usbd_device_handle
Line 555  usbd_set_config_index(usbd_device_handle
         DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));          DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
   
         if (index >= dev->ddesc.bNumConfigurations &&          if (index >= dev->ddesc.bNumConfigurations &&
             index != USB_UNCONFIG_NO) {              index != USB_UNCONFIG_INDEX) {
                 /* panic? */                  /* panic? */
                 printf("usbd_set_config_index: illegal index\n");                  printf("usbd_set_config_index: illegal index\n");
                 return (USBD_INVAL);                  return (USBD_INVAL);
Line 663  usbd_set_config_index(usbd_device_handle
Line 640  usbd_set_config_index(usbd_device_handle
                 if (msg)                  if (msg)
                         printf("%s: device addr %d (config %d): "                          printf("%s: device addr %d (config %d): "
                                  "can't set self powered configuration\n",                                   "can't set self powered configuration\n",
                                USBDEVNAME(dev->bus->bdev), dev->address,                                 device_xname(dev->bus->bdev), dev->address,
                                cdp->bConfigurationValue);                                 cdp->bConfigurationValue);
                 err = USBD_NO_POWER;                  err = USBD_NO_POWER;
                 goto bad;                  goto bad;
Line 788  usbd_getnewaddr(usbd_bus_handle bus)
Line 765  usbd_getnewaddr(usbd_bus_handle bus)
         return (-1);          return (-1);
 }  }
   
   
 usbd_status  usbd_status
 usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,  usbd_attach_roothub(device_t parent, usbd_device_handle dev)
                       int port, int addr)  
 {  {
         struct usb_attach_arg uaa;          struct usb_attach_arg uaa;
         struct usbif_attach_arg uiaa;  
         usb_device_descriptor_t *dd = &dev->ddesc;          usb_device_descriptor_t *dd = &dev->ddesc;
         int found, i, confi, nifaces;          device_t dv;
         usbd_status err;  
         device_ptr_t dv;  
         usbd_interface_handle *ifaces;  
   
 #if defined(__FreeBSD__)          uaa.device = dev;
         /*          uaa.usegeneric = 0;
          * XXX uaa is a static var. Not a problem as it _should_ be used only          uaa.port = 0;
          * during probe and attach. Should be changed however.          uaa.vendor = UGETW(dd->idVendor);
          */          uaa.product = UGETW(dd->idProduct);
         device_t bdev;          uaa.release = UGETW(dd->bcdDevice);
         bdev = device_add_child(parent, NULL, -1, &uaa);          uaa.class = dd->bDeviceClass;
         if (!bdev) {          uaa.subclass = dd->bDeviceSubClass;
             printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));          uaa.proto = dd->bDeviceProtocol;
             return (USBD_INVAL);  
           dv = config_found_ia(parent, "usbroothubif", &uaa, 0);
           if (dv) {
                   dev->subdevs = malloc(sizeof dv, M_USB, M_NOWAIT);
                   if (dev->subdevs == NULL)
                           return (USBD_NOMEM);
                   dev->subdevs[0] = dv;
                   dev->subdevlen = 1;
         }          }
         device_quiet(bdev);          return (USBD_NORMAL_COMPLETION);
 #endif  }
   
   static usbd_status
   usbd_attachwholedevice(device_t parent, usbd_device_handle dev, int port,
           int usegeneric)
   {
           struct usb_attach_arg uaa;
           usb_device_descriptor_t *dd = &dev->ddesc;
           device_t dv;
           int dlocs[USBDEVIFCF_NLOCS];
   
         uaa.device = dev;          uaa.device = dev;
         uaa.usegeneric = 0;          uaa.usegeneric = usegeneric;
         uaa.port = port;          uaa.port = port;
         uaa.vendor = UGETW(dd->idVendor);          uaa.vendor = UGETW(dd->idVendor);
         uaa.product = UGETW(dd->idProduct);          uaa.product = UGETW(dd->idProduct);
Line 825  usbd_probe_and_attach(device_ptr_t paren
Line 812  usbd_probe_and_attach(device_ptr_t paren
         uaa.subclass = dd->bDeviceSubClass;          uaa.subclass = dd->bDeviceSubClass;
         uaa.proto = dd->bDeviceProtocol;          uaa.proto = dd->bDeviceProtocol;
   
         /* First try with device specific drivers. */          dlocs[USBDEVIFCF_PORT] = uaa.port;
         DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));          dlocs[USBDEVIFCF_VENDOR] = uaa.vendor;
         dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);          dlocs[USBDEVIFCF_PRODUCT] = uaa.product;
           dlocs[USBDEVIFCF_RELEASE] = uaa.release;
           /* the rest is historical ballast */
           dlocs[USBDEVIFCF_CONFIGURATION] = -1;
           dlocs[USBDEVIFCF_INTERFACE] = -1;
   
           dv = config_found_sm_loc(parent, "usbdevif", dlocs, &uaa, usbd_print,
                                    config_stdsubmatch);
         if (dv) {          if (dv) {
                 dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);                  dev->subdevs = malloc(sizeof dv, M_USB, M_NOWAIT);
                 if (dev->subdevs == NULL)                  if (dev->subdevs == NULL)
                         return (USBD_NOMEM);                          return (USBD_NOMEM);
                 dev->subdevs[0] = dv;                  dev->subdevs[0] = dv;
                 dev->subdevs[1] = 0;                  dev->subdevlen = 1;
                 return (USBD_NORMAL_COMPLETION);                  dev->nifaces_claimed = 1; /* XXX */
         }          }
           return (USBD_NORMAL_COMPLETION);
   }
   
         DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));  static usbd_status
   usbd_attachinterfaces(device_t parent, usbd_device_handle dev,
                         int port, const int *locators)
   {
           struct usbif_attach_arg uiaa;
           int ilocs[USBIFIFCF_NLOCS];
           usb_device_descriptor_t *dd = &dev->ddesc;
           int nifaces;
           usbd_interface_handle *ifaces;
           int i, j, loc;
           device_t dv;
   
           nifaces = dev->cdesc->bNumInterface;
           ifaces = malloc(nifaces * sizeof(*ifaces), M_USB, M_NOWAIT|M_ZERO);
           if (!ifaces)
                   return (USBD_NOMEM);
           for (i = 0; i < nifaces; i++)
                   if (!dev->subdevs[i])
                           ifaces[i] = &dev->ifaces[i];
   
         uiaa.device = dev;          uiaa.device = dev;
         uiaa.port = port;          uiaa.port = port;
         uiaa.vendor = UGETW(dd->idVendor);          uiaa.vendor = UGETW(dd->idVendor);
         uiaa.product = UGETW(dd->idProduct);          uiaa.product = UGETW(dd->idProduct);
         uiaa.release = UGETW(dd->bcdDevice);          uiaa.release = UGETW(dd->bcdDevice);
           uiaa.configno = dev->cdesc->bConfigurationValue;
           uiaa.ifaces = ifaces;
           uiaa.nifaces = nifaces;
           ilocs[USBIFIFCF_PORT] = uiaa.port;
           ilocs[USBIFIFCF_VENDOR] = uiaa.vendor;
           ilocs[USBIFIFCF_PRODUCT] = uiaa.product;
           ilocs[USBIFIFCF_RELEASE] = uiaa.release;
           ilocs[USBIFIFCF_CONFIGURATION] = uiaa.configno;
   
           for (i = 0; i < nifaces; i++) {
                   if (!ifaces[i])
                           continue; /* interface already claimed */
                   uiaa.iface = ifaces[i];
                   uiaa.class = ifaces[i]->idesc->bInterfaceClass;
                   uiaa.subclass = ifaces[i]->idesc->bInterfaceSubClass;
                   uiaa.proto = ifaces[i]->idesc->bInterfaceProtocol;
                   uiaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
                   ilocs[USBIFIFCF_INTERFACE] = uiaa.ifaceno;
                   if (locators != NULL) {
                           loc = locators[USBIFIFCF_CONFIGURATION];
                           if (loc != USBIFIFCF_CONFIGURATION_DEFAULT &&
                               loc != uiaa.configno)
                                   continue;
                           loc = locators[USBIFIFCF_INTERFACE];
                           if (loc != USBIFIFCF_INTERFACE && loc != uiaa.ifaceno)
                                   continue;
                   }
                   dv = config_found_sm_loc(parent, "usbifif", ilocs, &uiaa,
                                            usbd_ifprint, config_stdsubmatch);
                   if (!dv)
                           continue;
                   ifaces[i] = 0; /* claim */
                   /* account for ifaces claimed by the driver behind our back */
                   for (j = 0; j < nifaces; j++) {
                           if (!ifaces[j] && !dev->subdevs[j]) {
                                   dev->subdevs[j] = dv;
                                   dev->nifaces_claimed++;
                           }
                   }
           }
   
           free(ifaces, M_USB);
           return (USBD_NORMAL_COMPLETION);
   }
   
   usbd_status
   usbd_probe_and_attach(device_t parent, usbd_device_handle dev,
                         int port, int addr)
   {
           usb_device_descriptor_t *dd = &dev->ddesc;
           int confi, nifaces;
           usbd_status err;
   
           /* First try with device specific drivers. */
           DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
           err = usbd_attachwholedevice(parent, dev, port, 0);
           if (dev->nifaces_claimed || err)
                   return (err);
           DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
   
         DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",          DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
                  dd->bNumConfigurations));                   dd->bNumConfigurations));
         /* Next try with interface drivers. */  
         for (confi = 0; confi < dd->bNumConfigurations; confi++) {          for (confi = 0; confi < dd->bNumConfigurations; confi++) {
                 DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",                  DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
                             confi));                              confi));
Line 855  usbd_probe_and_attach(device_ptr_t paren
Line 927  usbd_probe_and_attach(device_ptr_t paren
                 if (err) {                  if (err) {
 #ifdef USB_DEBUG  #ifdef USB_DEBUG
                         DPRINTF(("%s: port %d, set config at addr %d failed, "                          DPRINTF(("%s: port %d, set config at addr %d failed, "
                                  "error=%s\n", USBDEVPTRNAME(parent), port,                              "error=%s\n", device_xname(parent), port,
                                  addr, usbd_errstr(err)));                              addr, usbd_errstr(err)));
 #else  #else
                         printf("%s: port %d, set config at addr %d failed\n",                          printf("%s: port %d, set config at addr %d failed\n",
                                USBDEVPTRNAME(parent), port, addr);                              device_xname(parent), port, addr);
 #endif  #endif
 #if defined(__FreeBSD__)                          return (err);
                         device_delete_child(parent, bdev);  
 #endif  
   
                         return (err);  
                 }                  }
                 nifaces = dev->cdesc->bNumInterface;                  nifaces = dev->cdesc->bNumInterface;
                 uiaa.configno = dev->cdesc->bConfigurationValue;                  dev->subdevs = malloc(nifaces * sizeof(device_t), M_USB,
                 ifaces = malloc(nifaces * sizeof(*ifaces), M_USB, M_NOWAIT);                                        M_NOWAIT|M_ZERO);
                 if (ifaces == NULL)                  if (dev->subdevs == NULL)
                         goto nomem;  
                 for (i = 0; i < nifaces; i++)  
                         ifaces[i] = &dev->ifaces[i];  
                 uiaa.ifaces = ifaces;  
                 uiaa.nifaces = nifaces;  
                 dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);  
                 if (dev->subdevs == NULL) {  
                         free(ifaces, M_USB);  
 nomem:  
 #if defined(__FreeBSD__)  
                         device_delete_child(parent, bdev);  
 #endif  
                         return (USBD_NOMEM);                          return (USBD_NOMEM);
                 }                  dev->subdevlen = nifaces;
   
                 found = 0;                  err = usbd_attachinterfaces(parent, dev, port, NULL);
                 for (i = 0; i < nifaces; i++) {  
                         if (ifaces[i] == NULL)                  if (!dev->nifaces_claimed) {
                                 continue; /* interface already claimed */                          free(dev->subdevs, M_USB);
                         uiaa.iface = ifaces[i];                          dev->subdevs = 0;
                         uiaa.class = ifaces[i]->idesc->bInterfaceClass;                          dev->subdevlen = 0;
                         uiaa.subclass = ifaces[i]->idesc->bInterfaceSubClass;  
                         uiaa.proto = ifaces[i]->idesc->bInterfaceProtocol;  
                         uiaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;  
                         dv = USB_DO_IFATTACH(dev, bdev, parent, &uiaa, usbd_ifprint,  
                                              usbd_ifsubmatch);  
                         if (dv != NULL) {  
                                 dev->subdevs[found++] = dv;  
                                 dev->subdevs[found] = 0;  
                                 ifaces[i] = 0; /* consumed */  
   
 #if defined(__FreeBSD__)  
                                 /* create another child for the next iface */  
                                 bdev = device_add_child(parent, NULL, -1,&uaa);  
                                 if (!bdev) {  
                                         printf("%s: Device creation failed\n",  
                                         USBDEVNAME(dev->bus->bdev));  
                                         free(ifaces, M_USB);  
                                         return (USBD_NORMAL_COMPLETION);  
                                 }  
                                 device_quiet(bdev);  
 #endif  
                         }  
                 }  
                 if (found != 0) {  
 #if defined(__FreeBSD__)  
                         /* remove the last created child again; it is unused */  
                         device_delete_child(parent, bdev);  
 #endif  
                         free(ifaces, M_USB);  
                         return (USBD_NORMAL_COMPLETION);  
                 }                  }
                 free(ifaces, M_USB);                  if (dev->nifaces_claimed || err)
                 free(dev->subdevs, M_USB);                          return (err);
                 dev->subdevs = 0;  
         }          }
         /* No interfaces were attached in any of the configurations. */          /* No interfaces were attached in any of the configurations. */
   
Line 935  nomem:
Line 960  nomem:
         DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));          DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
   
         /* Finally try the generic driver. */          /* Finally try the generic driver. */
         uaa.usegeneric = 1;          err = usbd_attachwholedevice(parent, dev, port, 1);
         dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);  
         if (dv != NULL) {  
                 dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);  
                 if (dev->subdevs == 0)  
                         return (USBD_NOMEM);  
                 dev->subdevs[0] = dv;  
                 dev->subdevs[1] = 0;  
                 return (USBD_NORMAL_COMPLETION);  
         }  
   
         /*          /*
          * The generic attach failed, but leave the device as it is.           * The generic attach failed, but leave the device as it is.
Line 952  nomem:
Line 968  nomem:
          * fully operational and not harming anyone.           * fully operational and not harming anyone.
          */           */
         DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));          DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
 #if defined(__FreeBSD__)          return (USBD_NORMAL_COMPLETION);
         device_delete_child(parent, bdev);  
 #endif  
         return (USBD_NORMAL_COMPLETION);  
 }  }
   
   /**
    * Called from uhub_rescan().  usbd_new_device() for the target dev must be
    * called before calling this.
    */
   usbd_status
   usbd_reattach_device(device_t parent, usbd_device_handle dev,
                        int port, const int *locators)
   {
           int i, loc;
   
           if (locators != NULL) {
                   loc = locators[USBIFIFCF_PORT];
                   if (loc != USBIFIFCF_PORT_DEFAULT && loc != port)
                           return USBD_NORMAL_COMPLETION;
                   loc = locators[USBIFIFCF_VENDOR];
                   if (loc != USBIFIFCF_VENDOR_DEFAULT &&
                       loc != UGETW(dev->ddesc.idVendor))
                           return USBD_NORMAL_COMPLETION;
                   loc = locators[USBIFIFCF_PRODUCT];
                   if (loc != USBIFIFCF_PRODUCT_DEFAULT &&
                       loc != UGETW(dev->ddesc.idProduct))
                           return USBD_NORMAL_COMPLETION;
                   loc = locators[USBIFIFCF_RELEASE];
                   if (loc != USBIFIFCF_RELEASE_DEFAULT &&
                       loc != UGETW(dev->ddesc.bcdDevice))
                           return USBD_NORMAL_COMPLETION;
           }
           if (dev->subdevlen == 0) {
                   /* XXX: check USBIFIFCF_CONFIGURATION and
                    * USBIFIFCF_INTERFACE too */
                   return usbd_probe_and_attach(parent, dev, port, dev->address);
           } else if (dev->subdevlen != dev->cdesc->bNumInterface) {
                   /* device-specific or generic driver is already attached. */
                   return USBD_NORMAL_COMPLETION;
           }
           /* Does the device have unconfigured interfaces? */
           for (i = 0; i < dev->subdevlen; i++) {
                   if (dev->subdevs[i] == NULL) {
                           break;
                   }
           }
           if (i >= dev->subdevlen)
                   return USBD_NORMAL_COMPLETION;
           return usbd_attachinterfaces(parent, dev, port, locators);
   }
   
 /*  /*
  * Called when a new device has been put in the powered state,   * Called when a new device has been put in the powered state,
Line 966  nomem:
Line 1024  nomem:
  * and attach a driver.   * and attach a driver.
  */   */
 usbd_status  usbd_status
 usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth,  usbd_new_device(device_t parent, usbd_bus_handle bus, int depth,
                 int speed, int port, struct usbd_port *up)                  int speed, int port, struct usbd_port *up)
 {  {
         usbd_device_handle dev, adev;          usbd_device_handle dev, adev;
         struct usbd_device *hub;          struct usbd_device *hub;
Line 1001  usbd_new_device(device_ptr_t parent, usb
Line 1059  usbd_new_device(device_ptr_t parent, usb
         dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;          dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
         dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;          dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
         dev->def_ep_desc.bmAttributes = UE_CONTROL;          dev->def_ep_desc.bmAttributes = UE_CONTROL;
         USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);          if (speed == USB_SPEED_HIGH)
                   USETW(dev->def_ep_desc.wMaxPacketSize, 64);
           else
                   USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
         dev->def_ep_desc.bInterval = 0;          dev->def_ep_desc.bInterval = 0;
   
         dev->quirks = &usbd_no_quirk;          dev->quirks = &usbd_no_quirk;
Line 1043  usbd_new_device(device_ptr_t parent, usb
Line 1104  usbd_new_device(device_ptr_t parent, usb
                 return (err);                  return (err);
         }          }
   
         /* Set the address.  Do this early; some devices need that. */  
         /* Try a few times in case the device is slow (i.e. outside specs) */  
         DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));  
         for (i = 0; i < 15; i++) {  
                 err = usbd_set_address(dev, addr);  
                 if (!err)  
                         break;  
                 usbd_delay_ms(dev, 200);  
                 if ((i & 3) == 3) {  
                         DPRINTFN(-1,("usbd_new_device: set address %d "  
                             "failed - trying a port reset\n", addr));  
                         usbd_reset_port(up->parent, port, &ps);  
                 }  
         }  
         if (err) {  
                 DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));  
                 err = USBD_SET_ADDR_FAILED;  
                 usbd_remove_device(dev, up);  
                 return (err);  
         }  
         /* Allow device time to set new address */  
         usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);  
         dev->address = addr;    /* New device address now */  
         bus->devices[addr] = dev;  
   
         dd = &dev->ddesc;          dd = &dev->ddesc;
         /* Try a few times in case the device is slow (i.e. outside specs.) */          /* Try a few times in case the device is slow (i.e. outside specs.) */
         for (i = 0; i < 10; i++) {          for (i = 0; i < 10; i++) {
                 /* Get the first 8 bytes of the device descriptor. */                  /* Get the first 8 bytes of the device descriptor. */
                 err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);                  err = usbd_get_desc(dev, UDESC_DEVICE, 0,
                           (speed == USB_SPEED_HIGH) ? USB_DEVICE_DESCRIPTOR_SIZE
                                                     : USB_MAX_IPACKET,
                            dd);
   
                 if (!err)                  if (!err)
                         break;                          break;
                 usbd_delay_ms(dev, 200);                  usbd_delay_ms(dev, 200);
Line 1127  usbd_new_device(device_ptr_t parent, usb
Line 1167  usbd_new_device(device_ptr_t parent, usb
                 return (err);                  return (err);
         }          }
   
           /* Set the address */
           DPRINTFN(5, ("usbd_new_device: setting device address=%d\n", addr));
           err = usbd_set_address(dev, addr);
           if (err) {
                   DPRINTFN(-1, ("usbd_new_device: set address %d failed\n", addr));
                   err = USBD_SET_ADDR_FAILED;
                   usbd_remove_device(dev, up);
                   return err;
           }
   
           /* Allow device time to set new address */
           usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
           dev->address = addr;    /* new device address now */
           bus->devices[addr] = dev;
   
           /* Re-establish the default pipe with the new address. */
           usbd_kill_pipe(dev->default_pipe);
           err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
               &dev->default_pipe);
           if (err) {
                   DPRINTFN(-1, ("usbd_new_device: setup default pipe failed\n"));
                   usbd_remove_device(dev, up);
                   return err;
           }
   
         /* Assume 100mA bus powered for now. Changed when configured. */          /* Assume 100mA bus powered for now. Changed when configured. */
         dev->power = USB_MIN_POWER;          dev->power = USB_MIN_POWER;
         dev->self_powered = 0;          dev->self_powered = 0;
Line 1136  usbd_new_device(device_ptr_t parent, usb
Line 1201  usbd_new_device(device_ptr_t parent, usb
   
         usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);          usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);
   
           if (port == 0) { /* root hub */
                   KASSERT(addr == 1);
                   usbd_attach_roothub(parent, dev);
                   return (USBD_NORMAL_COMPLETION);
           }
   
         err = usbd_probe_and_attach(parent, dev, port, addr);          err = usbd_probe_and_attach(parent, dev, port, addr);
         if (err) {          if (err) {
                 usbd_remove_device(dev, up);                  usbd_remove_device(dev, up);
                 return (err);                  return (err);
         }          }
   
         return (USBD_NORMAL_COMPLETION);          return (USBD_NORMAL_COMPLETION);
 }  }
   
 usbd_status  usbd_status
Line 1174  usbd_remove_device(usbd_device_handle de
Line 1245  usbd_remove_device(usbd_device_handle de
         free(dev, M_USB);          free(dev, M_USB);
 }  }
   
 #if defined(__NetBSD__) || defined(__OpenBSD__)  
 int  int
 usbd_print(void *aux, const char *pnp)  usbd_print(void *aux, const char *pnp)
 {  {
Line 1191  usbd_print(void *aux, const char *pnp)
Line 1261  usbd_print(void *aux, const char *pnp)
                 aprint_normal("%s, %s", devinfo, pnp);                  aprint_normal("%s, %s", devinfo, pnp);
                 free(devinfo, M_TEMP);                  free(devinfo, M_TEMP);
         }          }
         if (uaa->port != 0)          aprint_normal(" port %d", uaa->port);
                 aprint_normal(" port %d", uaa->port);  
 #if 0  #if 0
         /*          /*
          * It gets very crowded with these locators on the attach line.           * It gets very crowded with these locators on the attach line.
Line 1217  usbd_ifprint(void *aux, const char *pnp)
Line 1286  usbd_ifprint(void *aux, const char *pnp)
         DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));          DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
         if (pnp)          if (pnp)
                 return (QUIET);                  return (QUIET);
         if (uaa->port != 0)          aprint_normal(" port %d", uaa->port);
                 aprint_normal(" port %d", uaa->port);          aprint_normal(" configuration %d", uaa->configno);
         if (uaa->configno != UHUB_UNK_CONFIGURATION)          aprint_normal(" interface %d", uaa->ifaceno);
                 aprint_normal(" configuration %d", uaa->configno);  
         if (uaa->ifaceno != UHUB_UNK_INTERFACE)  
                 aprint_normal(" interface %d", uaa->ifaceno);  
 #if 0  #if 0
         /*          /*
          * It gets very crowded with these locators on the attach line.           * It gets very crowded with these locators on the attach line.
Line 1239  usbd_ifprint(void *aux, const char *pnp)
Line 1305  usbd_ifprint(void *aux, const char *pnp)
         return (UNCONF);          return (UNCONF);
 }  }
   
 #if defined(__NetBSD__)  
 int  
 usbd_submatch(struct device *parent, struct cfdata *cf,  
               const int *ldesc, void *aux)  
 {  
 #elif defined(__OpenBSD__)  
 int  
 usbd_submatch(struct device *parent, void *match, void *aux)  
 {  
         struct cfdata *cf = match;  
 #endif  
         struct usb_attach_arg *uaa = aux;  
   
         DPRINTFN(5,("usbd_submatch port=%d,%d "  
             "vendor=%d,%d product=%d,%d release=%d,%d\n",  
             uaa->port, cf->uhubcf_port,  
             uaa->vendor, cf->uhubcf_vendor,  
             uaa->product, cf->uhubcf_product,  
             uaa->release, cf->uhubcf_release));  
         if (uaa->port != 0 &&   /* root hub has port 0, it should match */  
             ((cf->uhubcf_port != UHUB_UNK_PORT &&  
               cf->uhubcf_port != uaa->port) ||  
              (uaa->vendor != UHUB_UNK_VENDOR &&  
               cf->uhubcf_vendor != UHUB_UNK_VENDOR &&  
               cf->uhubcf_vendor != uaa->vendor) ||  
              (uaa->product != UHUB_UNK_PRODUCT &&  
               cf->uhubcf_product != UHUB_UNK_PRODUCT &&  
               cf->uhubcf_product != uaa->product) ||  
              (uaa->release != UHUB_UNK_RELEASE &&  
               cf->uhubcf_release != UHUB_UNK_RELEASE &&  
               cf->uhubcf_release != uaa->release)  
              )  
            )  
                 return 0;  
         return (config_match(parent, cf, aux));  
 }  
   
 int  
 usbd_ifsubmatch(struct device *parent, struct cfdata *cf,  
               const int *ldesc, void *aux)  
 {  
         struct usbif_attach_arg *uaa = aux;  
   
         DPRINTFN(5,("usbd_submatch port=%d,%d configno=%d,%d "  
             "ifaceno=%d,%d vendor=%d,%d product=%d,%d release=%d,%d\n",  
             uaa->port, cf->uhubcf_port,  
             uaa->configno, cf->uhubcf_configuration,  
             uaa->ifaceno, cf->uhubcf_interface,  
             uaa->vendor, cf->uhubcf_vendor,  
             uaa->product, cf->uhubcf_product,  
             uaa->release, cf->uhubcf_release));  
         if (uaa->port != 0 &&   /* root hub has port 0, it should match */  
             ((cf->uhubcf_port != UHUB_UNK_PORT &&  
               cf->uhubcf_port != uaa->port) ||  
              (uaa->configno != UHUB_UNK_CONFIGURATION &&  
               cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&  
               cf->uhubcf_configuration != uaa->configno) ||  
              (uaa->ifaceno != UHUB_UNK_INTERFACE &&  
               cf->uhubcf_interface != UHUB_UNK_INTERFACE &&  
               cf->uhubcf_interface != uaa->ifaceno) ||  
              (uaa->vendor != UHUB_UNK_VENDOR &&  
               cf->uhubcf_vendor != UHUB_UNK_VENDOR &&  
               cf->uhubcf_vendor != uaa->vendor) ||  
              (uaa->product != UHUB_UNK_PRODUCT &&  
               cf->uhubcf_product != UHUB_UNK_PRODUCT &&  
               cf->uhubcf_product != uaa->product) ||  
              (uaa->release != UHUB_UNK_RELEASE &&  
               cf->uhubcf_release != UHUB_UNK_RELEASE &&  
               cf->uhubcf_release != uaa->release)  
              )  
            )  
                 return 0;  
         return (config_match(parent, cf, aux));  
 }  
   
 #endif  
   
 void  void
 usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di,  usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di,
                      int usedev)                       int usedev)
 {  {
         struct usbd_port *p;          struct usbd_port *p;
         int i, err, s;          int i, j, err, s;
   
         di->udi_bus = device_unit(dev->bus->usbctl);          di->udi_bus = device_unit(dev->bus->usbctl);
         di->udi_addr = dev->address;          di->udi_addr = dev->address;
Line 1343  usbd_fill_deviceinfo(usbd_device_handle 
Line 1332  usbd_fill_deviceinfo(usbd_device_handle 
         di->udi_power = dev->self_powered ? 0 : dev->power;          di->udi_power = dev->self_powered ? 0 : dev->power;
         di->udi_speed = dev->speed;          di->udi_speed = dev->speed;
   
         if (dev->subdevs != NULL) {          if (dev->subdevlen > 0) {
                 for (i = 0; dev->subdevs[i] &&                  for (i = 0, j = 0; i < dev->subdevlen &&
                              i < USB_MAX_DEVNAMES; i++) {                               j < USB_MAX_DEVNAMES; i++) {
                         strncpy(di->udi_devnames[i], USBDEVPTRNAME(dev->subdevs[i]),                          if (!dev->subdevs[i])
                                 USB_MAX_DEVNAMELEN);                                  continue;
                         di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';                          strncpy(di->udi_devnames[j],
                 }                              device_xname(dev->subdevs[i]), USB_MAX_DEVNAMELEN);
         } else {                          di->udi_devnames[j][USB_MAX_DEVNAMELEN-1] = '\0';
                 i = 0;                          j++;
         }                  }
         for (/*i is set */; i < USB_MAX_DEVNAMES; i++)          } else {
                 di->udi_devnames[i][0] = 0;                 /* empty */                  j = 0;
           }
           for (/* j is set */; j < USB_MAX_DEVNAMES; j++)
                   di->udi_devnames[j][0] = 0;                 /* empty */
   
         if (dev->hub) {          if (dev->hub) {
                 for (i = 0;                  for (i = 0;
Line 1388  usbd_fill_deviceinfo_old(usbd_device_han
Line 1380  usbd_fill_deviceinfo_old(usbd_device_han
                          int usedev)                           int usedev)
 {  {
         struct usbd_port *p;          struct usbd_port *p;
         int i, err, s;          int i, j, err, s;
   
         di->udi_bus = device_unit(dev->bus->usbctl);          di->udi_bus = device_unit(dev->bus->usbctl);
         di->udi_addr = dev->address;          di->udi_addr = dev->address;
Line 1406  usbd_fill_deviceinfo_old(usbd_device_han
Line 1398  usbd_fill_deviceinfo_old(usbd_device_han
         di->udi_power = dev->self_powered ? 0 : dev->power;          di->udi_power = dev->self_powered ? 0 : dev->power;
         di->udi_speed = dev->speed;          di->udi_speed = dev->speed;
   
         if (dev->subdevs != NULL) {          if (dev->subdevlen > 0) {
                 for (i = 0; dev->subdevs[i] &&                  for (i = 0, j = 0; i < dev->subdevlen &&
                              i < USB_MAX_DEVNAMES; i++) {                               j < USB_MAX_DEVNAMES; i++) {
                         strncpy(di->udi_devnames[i], USBDEVPTRNAME(dev->subdevs[i]),                          if (!dev->subdevs[i])
                                 USB_MAX_DEVNAMELEN);                                  continue;
                         di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';                          strncpy(di->udi_devnames[j],
                               device_xname(dev->subdevs[i]), USB_MAX_DEVNAMELEN);
                           di->udi_devnames[j][USB_MAX_DEVNAMELEN-1] = '\0';
                           j++;
                 }                  }
         } else {          } else {
                 i = 0;                  j = 0;
         }          }
         for (/*i is set */; i < USB_MAX_DEVNAMES; i++)          for (/* j is set */; j < USB_MAX_DEVNAMES; j++)
                 di->udi_devnames[i][0] = 0;              /* empty */                  di->udi_devnames[j][0] = 0;              /* empty */
   
         if (dev->hub) {          if (dev->hub) {
                 for (i = 0;                  for (i = 0;
Line 1462  usb_free_device(usbd_device_handle dev)
Line 1457  usb_free_device(usbd_device_handle dev)
         }          }
         if (dev->cdesc != NULL)          if (dev->cdesc != NULL)
                 free(dev->cdesc, M_USB);                  free(dev->cdesc, M_USB);
         if (dev->subdevs != NULL)          if (dev->subdevlen > 0) {
                 free(dev->subdevs, M_USB);                  free(dev->subdevs, M_USB);
                   dev->subdevlen = 0;
           }
         free(dev, M_USB);          free(dev, M_USB);
 }  }
   
Line 1485  usb_free_device(usbd_device_handle dev)
Line 1482  usb_free_device(usbd_device_handle dev)
  * been disconnected.   * been disconnected.
  */   */
 void  void
 usb_disconnect_port(struct usbd_port *up, device_ptr_t parent)  usb_disconnect_port(struct usbd_port *up, device_t parent)
 {  {
         usbd_device_handle dev = up->device;          usbd_device_handle dev = up->device;
         const char *hubname = USBDEVPTRNAME(parent);          const char *hubname = device_xname(parent);
         int i;          int i;
   
         DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",          DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
Line 1501  usb_disconnect_port(struct usbd_port *up
Line 1498  usb_disconnect_port(struct usbd_port *up
         }          }
 #endif  #endif
   
         if (dev->subdevs != NULL) {          if (dev->subdevlen > 0) {
                 DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));                  DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
                 for (i = 0; dev->subdevs[i]; i++) {                  for (i = 0; i < dev->subdevlen; i++) {
                         printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]),                          if (!dev->subdevs[i])
                                   continue;
                           printf("%s: at %s", device_xname(dev->subdevs[i]),
                                hubname);                                 hubname);
                         if (up->portno != 0)                          if (up->portno != 0)
                                 printf(" port %d", up->portno);                                  printf(" port %d", up->portno);
                         printf(" (addr %d) disconnected\n", dev->address);                          printf(" (addr %d) disconnected\n", dev->address);
                         config_detach(dev->subdevs[i], DETACH_FORCE);                          config_detach(dev->subdevs[i], DETACH_FORCE);
                 }                  }
                   KASSERT(!dev->nifaces_claimed);
         }          }
   
         usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);          usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);
Line 1518  usb_disconnect_port(struct usbd_port *up
Line 1518  usb_disconnect_port(struct usbd_port *up
         up->device = NULL;          up->device = NULL;
         usb_free_device(dev);          usb_free_device(dev);
 }  }
   
 #ifdef __OpenBSD__  
 void *usb_realloc(void *p, u_int size, int pool, int flags)  
 {  
         void *q;  
   
         q = malloc(size, pool, flags);  
         if (q == NULL)  
                 return (NULL);  
         bcopy(p, q, size);  
         free(p, pool);  
         return (q);  
 }  
 #endif  

Legend:
Removed from v.1.152  
changed lines
  Added in v.1.152.4.4

CVSweb <webmaster@jp.NetBSD.org>