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