Hi,

this incorporates Greg's suggestions. I am still working at understanding
the driverfs code. So that is not cleaned up.

        Regards
                Oliver

You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================


[EMAIL PROTECTED], 2002-10-11 21:51:28+02:00, [EMAIL PROTECTED]
  - proper configuration change handling




diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c    Fri Oct 11 21:52:51 2002
+++ b/drivers/usb/core/hub.c    Fri Oct 11 21:52:51 2002
@@ -1236,7 +1236,7 @@
                return 1;
        }
 
-       ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue);
+       ret = usb_physical_set_conf(dev, dev->actconfig->bConfigurationValue);
        if (ret < 0) {
                err("failed to set dev %s active configuration (error=%d)",
                        dev->devpath, ret);
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c        Fri Oct 11 21:52:51 2002
+++ b/drivers/usb/core/message.c        Fri Oct 11 21:52:51 2002
@@ -838,6 +838,54 @@
 }
 
 /**
+ * usb_physical_set_conf - send the actual message changing configuration
+ * @dev: the device whose configuration is being updated
+ * @configuration: the configuration being chosen.
+ * Context: !in_interrupt ()
+ *
+ * Caller must make sure that disconnect processing waits for this to 
complete
+ */
+static inline struct usb_config_descriptor *find_valid_config(struct 
usb_device *dev, int configuration)
+{
+       int i;
+
+       for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
+               if (dev->config[i].bConfigurationValue == configuration) {
+                       return &dev->config[i];
+
+               }
+       }
+       
+       return NULL;
+}
+
+int usb_physical_set_conf(struct usb_device *dev, int configuration)
+{
+       int r;
+       struct usb_config_descriptor *cp;
+       
+       r = -EINVAL;
+       cp = find_valid_config(dev, configuration);
+       if (!cp)
+               goto err;
+
+       r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                               USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+                               NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+       if (r)
+               goto err;
+
+       dev->actconfig = cp;
+       dev->toggle[0] = 0;
+       dev->toggle[1] = 0;
+       usb_set_maxpacket(dev);
+
+err:
+       return r;
+
+}
+
+/**
  * usb_set_configuration - Makes a particular device setting be current
  * @dev: the device whose configuration is being updated
  * @configuration: the configuration being chosen.
@@ -871,7 +919,7 @@
 {
        int i, ret;
        struct usb_config_descriptor *cp = NULL;
-       
+
        for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
                if (dev->config[i].bConfigurationValue == configuration) {
                        cp = &dev->config[i];
@@ -883,17 +931,28 @@
                return -EINVAL;
        }
 
-       if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-                       NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
-               return ret;
+       down(&dev->serialize);
 
-       dev->actconfig = cp;
-       dev->toggle[0] = 0;
-       dev->toggle[1] = 0;
-       usb_set_maxpacket(dev);
+       for (i = 0; i < USB_MAXCHILDREN; i++) {
+               struct usb_device **child = dev->children + i;
+               if (*child) {
+                       ret = -EBUSY;
+                       goto err; /* refuse if children were harmed */
+               }
+       }
+
+       usb_reap_interfaces(dev); /* get rid of all interfaces */
+
+       if ((ret = usb_physical_set_conf(dev, configuration)))
+               goto err;
+
+       dev->desired_conf = configuration; /* for pm */
+
+       ret = usb_logical_register_dev(dev); /* reevaluate device */
 
-       return 0;
+err:
+       up(&dev->serialize);
+       return ret;
 }
 
 
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c    Fri Oct 11 21:52:51 2002
+++ b/drivers/usb/core/usb.c    Fri Oct 11 21:52:51 2002
@@ -75,6 +75,7 @@
 {
        struct usb_interface * intf = to_usb_interface(dev);
        struct usb_driver * driver = to_usb_driver(dev->driver);
+       struct usb_device * udev =  interface_to_usbdev(intf);
        const struct usb_device_id *id;
        int error = -ENODEV;
        int m;
@@ -94,7 +95,9 @@
        if (id) {
                dbg ("%s - got id", __FUNCTION__);
                down (&driver->serialize);
+               down (&udev->serialize);
                error = driver->probe (intf, id);
+               up (&udev->serialize);
                up (&driver->serialize);
        }
        if (!error)
@@ -110,10 +113,12 @@
 {
        struct usb_interface *intf;
        struct usb_driver *driver;
+       struct usb_device *udev;
        int m;
 
        intf = list_entry(dev,struct usb_interface,dev);
        driver = to_usb_driver(dev->driver);
+       udev = interface_to_usbdev(intf);
 
        if (!driver) {
                err("%s does not have a valid driver to work with!",
@@ -132,10 +137,10 @@
        }
 
        /* if we sleep here on an umanaged driver 
-        * the holder of the lock guards against 
+        * the holder of the lock guards against
         * module unload */
        down(&driver->serialize);
-
+       down(&udev->serialize);
        if (intf->driver && intf->driver->disconnect)
                intf->driver->disconnect(intf);
 
@@ -143,6 +148,7 @@
        if (intf->driver)
                usb_driver_release_interface(driver, intf);
 
+       up(&udev->serialize);
        up(&driver->serialize);
        if (driver->owner)
                __MOD_DEC_USE_COUNT(driver->owner);
@@ -317,7 +323,7 @@
  * usb_driver_release_interface - unbind a driver from an interface
  * @driver: the driver to be unbound
  * @iface: the interface from which it will be unbound
- * 
+ *
  * This should be used by drivers to release their claimed interfaces.
  * It is normally called in their disconnect() methods, and only for
  * drivers that bound to more than one interface in their probe().
@@ -761,6 +767,26 @@
        return -1;
 }
 
+/** usb_reap_interfaces - disconnect all interfaces of a usb device
+ *  @dev: pointer to the device whose interfaces shall be disconnected
+ *  Context: !in_interrupt ()
+ *
+ *  Getting rid of interfaces associated with drivers.
+ *  This is for physical disconnection and configuration changes
+ */
+void usb_reap_interfaces(struct usb_device *dev)
+{
+       int i;
+
+       if (dev->actconfig) {
+               for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+                       struct usb_interface *interface = 
+&dev->actconfig->interface[i];
+
+                       /* remove this interface */
+                       put_device(&interface->dev);
+               }
+       }
+}
 /**
  * usb_disconnect - disconnect a device (usbcore-internal)
  * @pdev: pointer to device being disconnected
@@ -792,14 +818,7 @@
                        usb_disconnect(child);
        }
 
-       if (dev->actconfig) {
-               for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
-                       struct usb_interface *interface = 
&dev->actconfig->interface[i];
-
-                       /* remove this interface */
-                       put_device(&interface->dev);
-               }
-       }
+       usb_reap_interfaces(dev);
 
        /* Free the device number and remove the /proc/bus/usb entry */
        if (dev->devnum > 0) {
@@ -923,6 +942,66 @@
 }
 
 /*
+ * Logical reevaluation of a device - for new devices or configuration 
changes
+ */
+int usb_logical_register_dev(struct usb_device *dev)
+{
+       int err;
+       int i;
+       
+       /*
+        * Set the driver for the usb device to point to the "generic" driver.
+        * This prevents the main usb device from being sent to the usb bus
+        * probe function.  Yes, it's a hack, but a nice one :)
+        */
+       dev->dev.driver = &usb_generic_driver;
+       dev->dev.bus = &usb_bus_type;
+       if (dev->dev.bus_id[0] == 0)
+               sprintf (&dev->dev.bus_id[0], "%d-%s",
+                        dev->bus->busnum, dev->devpath);
+       err = device_register (&dev->dev);
+       if (err)
+               return err;
+
+       /* add the USB device specific driverfs files */
+       usb_create_driverfs_dev_files (dev);
+
+       /* Register all of the interfaces for this device with the driver core.
+        * Remember, interfaces get bound to drivers, not devices. */
+       for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+               struct usb_interface *interface = &dev->actconfig->interface[i];
+               struct usb_interface_descriptor *desc = interface->altsetting;
+
+               interface->dev.parent = &dev->dev;
+               interface->dev.driver = NULL;
+               interface->dev.bus = &usb_bus_type;
+               sprintf (&interface->dev.bus_id[0], "%d-%s:%d",
+                        dev->bus->busnum, dev->devpath,
+                        interface->altsetting->bInterfaceNumber);
+               if (!desc->iInterface
+                               || usb_string (dev, desc->iInterface,
+                                       interface->dev.name,
+                                       sizeof interface->dev.name) <= 0) {
+                       /* typically devices won't bother with interface
+                        * descriptions; this is the normal case.  an
+                        * interface's driver might describe it better.
+                        * (also: iInterface is per-altsetting ...)
+                        */
+                       sprintf (&interface->dev.name[0],
+                               "usb-%s-%s interface %d",
+                               dev->bus->bus_name, dev->devpath,
+                               interface->altsetting->bInterfaceNumber);
+               }
+               dbg ("%s - registering %s", __FUNCTION__, interface->dev.bus_id);
+               device_register (&interface->dev);
+               usb_create_driverfs_intf_files (interface);
+       }
+       
+       return 0;
+}
+
+
+/*
  * By the time we get here, the device has gotten a new device ID
  * and is in the default state. We need to identify the thing and
  * get the ball rolling..
@@ -1008,7 +1087,7 @@
        }
 
        /* we set the default configuration here */
-       err = usb_set_configuration(dev, dev->config[0].bConfigurationValue);
+       err = usb_physical_set_conf(dev, dev->config[0].bConfigurationValue);
        if (err) {
                err("failed to set device %d default configuration (error=%d)",
                        dev->devnum, err);
@@ -1026,55 +1105,14 @@
                usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
 #endif
 
-       /*
-        * Set the driver for the usb device to point to the "generic" driver.
-        * This prevents the main usb device from being sent to the usb bus
-        * probe function.  Yes, it's a hack, but a nice one :)
-        */
+
        usb_generic_driver.bus = &usb_bus_type;
        dev->dev.parent = parent;
-       dev->dev.driver = &usb_generic_driver;
-       dev->dev.bus = &usb_bus_type;
-       if (dev->dev.bus_id[0] == 0)
-               sprintf (&dev->dev.bus_id[0], "%d-%s",
-                        dev->bus->busnum, dev->devpath);
-       err = device_register (&dev->dev);
+       
+       err = usb_logical_register_dev(dev);
+       
        if (err)
                return err;
-
-       /* add the USB device specific driverfs files */
-       usb_create_driverfs_dev_files (dev);
-
-       /* Register all of the interfaces for this device with the driver core.
-        * Remember, interfaces get bound to drivers, not devices. */
-       for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
-               struct usb_interface *interface = &dev->actconfig->interface[i];
-               struct usb_interface_descriptor *desc = interface->altsetting;
-
-               interface->dev.parent = &dev->dev;
-               interface->dev.driver = NULL;
-               interface->dev.bus = &usb_bus_type;
-               sprintf (&interface->dev.bus_id[0], "%d-%s:%d",
-                        dev->bus->busnum, dev->devpath,
-                        interface->altsetting->bInterfaceNumber);
-               if (!desc->iInterface
-                               || usb_string (dev, desc->iInterface,
-                                       interface->dev.name,
-                                       sizeof interface->dev.name) <= 0) {
-                       /* typically devices won't bother with interface
-                        * descriptions; this is the normal case.  an
-                        * interface's driver might describe it better.
-                        * (also: iInterface is per-altsetting ...)
-                        */
-                       sprintf (&interface->dev.name[0],
-                               "usb-%s-%s interface %d",
-                               dev->bus->bus_name, dev->devpath,
-                               interface->altsetting->bInterfaceNumber);
-               }
-               dbg ("%s - registering %s", __FUNCTION__, interface->dev.bus_id);
-               device_register (&interface->dev);
-               usb_create_driverfs_intf_files (interface);
-       }
 
        /* add a /proc/bus/usb entry */
        usbfs_add_device(dev);
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h       Fri Oct 11 21:52:51 2002
+++ b/include/linux/usb.h       Fri Oct 11 21:52:51 2002
@@ -375,6 +375,7 @@
 
        int have_langid;                /* whether string_langid is valid yet */
        int string_langid;              /* language ID for strings */
+       int desired_conf;               /* configuration to restore on resume */
 
        void *hcpriv;                   /* Host Controller private data */
        
@@ -1032,6 +1033,9 @@
                struct scatterlist *sg, int n_hw_ents);
 void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
                struct scatterlist *sg, int n_hw_ents);
+void usb_reap_interfaces(struct usb_device *dev);
+int usb_physical_set_conf(struct usb_device *dev, int configuration);
+int usb_logical_register_dev(struct usb_device *dev);
 
 /*-------------------------------------------------------------------*
  *                         SYNCHRONOUS CALL SUPPORT                  *

===================================================================


This BitKeeper patch contains the following changesets:
1.890
## Wrapped with gzip_uu ##


begin 664 bkpatch1735
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
:?ZYVY]R]0L5SH#ONU%&-@?(WX$9?E1D?````
`
end



-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to