# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.593   -> 1.594  
#       include/linux/usbdevice_fs.h    1.4     -> 1.5    
#        include/linux/usb.h    1.23    -> 1.24   
#       drivers/usb/core/devio.c        1.23    -> 1.24   
#       drivers/usb/core/usb.c  1.38    -> 1.39   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/04/08      [EMAIL PROTECTED]     1.594
# [PATCH] usbfs disconnect
# 
# This was originally created by David many months ago and posted to the
# list, but not put into the kernel.
# 
# I modified the original patch to:
# -patch against the 2.5.7 kernel
# -use the 'real' interface number, not position (to do this I added 2
#  methods in usb.c)
# --------------------------------------------
#
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c  Mon Apr  8 15:49:14 2002
+++ b/drivers/usb/core/devio.c  Mon Apr  8 15:49:14 2002
@@ -1057,6 +1057,8 @@
        int                     size;
        void                    *buf = 0;
        int                     retval = 0;
+       struct usb_interface    *ifp = 0;
+       struct usb_driver       *driver = 0;
 
        /* get input parameters and alloc buffer */
        if (copy_from_user(&ctrl, (void *) arg, sizeof (ctrl)))
@@ -1074,33 +1076,41 @@
                }
        }
 
-       /* ioctl to device */
-       if (ctrl.ifno < 0) {
-               switch (ctrl.ioctl_code) {
-               /* access/release token for issuing control messages
-                * ask a particular driver to bind/unbind, ... etc
-                */
-               }
-               retval = -ENOSYS;
+       if (!ps->dev)
+               retval = -ENODEV;
+       else if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
+               retval = -EINVAL;
+       else switch (ctrl.ioctl_code) {
 
-       /* ioctl to the driver which has claimed a given interface */
-       } else {
-               struct usb_interface    *ifp = 0;
-               if (!ps->dev)
-                       retval = -ENODEV;
-               else if (ctrl.ifno >= ps->dev->actconfig->bNumInterfaces)
+       /* disconnect kernel driver from interface, leaving it unbound.  */
+       case USBDEVFS_DISCONNECT:
+               driver = ifp->driver;
+               if (driver) {
+                       down (&driver->serialize);
+                       dbg ("disconnect '%s' from dev %d interface %d",
+                               driver->name, ps->dev->devnum, ctrl.ifno);
+                       driver->disconnect (ps->dev, ifp->private_data);
+                       usb_driver_release_interface (driver, ifp);
+                       up (&driver->serialize);
+               } else
                        retval = -EINVAL;
+               break;
+
+       /* let kernel drivers try to (re)bind to the interface */
+       case USBDEVFS_CONNECT:
+               usb_find_interface_driver_for_ifnum (ps->dev, ctrl.ifno);
+               break;
+
+       /* talk directly to the interface's driver */
+       default:
+               driver = ifp->driver;
+               if (driver == 0 || driver->ioctl == 0)
+                       retval = -ENOSYS;
                else {
-                       if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
-                               retval = -EINVAL;
-                       else if (ifp->driver == 0 || ifp->driver->ioctl == 0)
-                               retval = -ENOSYS;
-               }
-               if (retval == 0) {
                        if (ifp->driver->owner)
                                __MOD_INC_USE_COUNT(ifp->driver->owner);
                        /* ifno might usefully be passed ... */
-                       retval = ifp->driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
+                       retval = driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
                        /* size = min_t(int, size, retval)? */
                        if (ifp->driver->owner)
                                __MOD_DEC_USE_COUNT(ifp->driver->owner);
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c    Mon Apr  8 15:49:14 2002
+++ b/drivers/usb/core/usb.c    Mon Apr  8 15:49:14 2002
@@ -196,6 +196,26 @@
        usbfs_update_special();
 }
 
+/*
+ * usb_ifnum_to_ifpos - convert the interface _number_ (as in 
+interface.bInterfaceNumber)
+ * to the interface _position_ (as in dev->actconfig->interface + position)
+ * @dev: the device to use
+ * @ifnum: the interface number (bInterfaceNumber); not interface position
+ *
+ * Note that the number is the same as the position for all interfaces _except_
+ * devices with interfaces not sequentially numbered (e.g., 0, 2, 3, etc).
+ */
+int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum)
+{
+       int i;
+
+       for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
+               if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == 
+ifnum)
+                       return i;
+
+       return -EINVAL;
+}
+
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
  * @dev: the device whose current configuration is considered
@@ -570,6 +590,23 @@
        return -1;
 }
 
+/*
+ * usb_find_interface_driver_for_ifnum - convert ifnum to ifpos via
+ * usb_ifnum_to_ifpos and call usb_find_interface_driver().
+ * @dev: the device to use
+ * @ifnum: the interface number (bInterfaceNumber); not interface position!
+ *
+ * Note usb_find_interface_driver's ifnum parameter is actually interface position.
+ */
+int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned ifnum)
+{
+       int ifpos = usb_ifnum_to_ifpos(dev, ifnum);
+
+       if (0 > ifpos)
+               return -EINVAL;
+
+       return usb_find_interface_driver(dev, ifpos);
+}
 
 #ifdef CONFIG_HOTPLUG
 
@@ -2636,6 +2673,7 @@
  * into the kernel, and other device drivers are built as modules,
  * then these symbols need to be exported for the modules to use.
  */
+EXPORT_SYMBOL(usb_ifnum_to_ifpos);
 EXPORT_SYMBOL(usb_ifnum_to_if);
 EXPORT_SYMBOL(usb_epnum_to_ep_desc);
 
@@ -2647,6 +2685,7 @@
 EXPORT_SYMBOL(usb_free_dev);
 EXPORT_SYMBOL(usb_inc_dev_use);
 
+EXPORT_SYMBOL(usb_find_interface_driver_for_ifnum);
 EXPORT_SYMBOL(usb_driver_claim_interface);
 EXPORT_SYMBOL(usb_interface_claimed);
 EXPORT_SYMBOL(usb_driver_release_interface);
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h       Mon Apr  8 15:49:14 2002
+++ b/include/linux/usb.h       Mon Apr  8 15:49:14 2002
@@ -305,6 +305,7 @@
 } __attribute__ ((packed));
 
 /* helpers for driver access to descriptors */
+extern int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum);
 extern struct usb_interface *
        usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
 extern struct usb_endpoint_descriptor *
@@ -1052,6 +1053,7 @@
 #define usb_dec_dev_use usb_free_dev
 
 /* used these for multi-interface device registration */
+extern int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned int 
+ifnum);
 extern void usb_driver_claim_interface(struct usb_driver *driver,
                        struct usb_interface *iface, void* priv);
 extern int usb_interface_claimed(struct usb_interface *iface);
diff -Nru a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
--- a/include/linux/usbdevice_fs.h      Mon Apr  8 15:49:14 2002
+++ b/include/linux/usbdevice_fs.h      Mon Apr  8 15:49:14 2002
@@ -142,6 +142,8 @@
 #define USBDEVFS_HUB_PORTINFO      _IOR('U', 19, struct usbdevfs_hub_portinfo)
 #define USBDEVFS_RESET             _IO('U', 20)
 #define USBDEVFS_CLEAR_HALT        _IOR('U', 21, unsigned int)
+#define USBDEVFS_DISCONNECT        _IO('U', 22)
+#define USBDEVFS_CONNECT           _IO('U', 23)
 
 /* --------------------------------------------------------------------- */
 

_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Sponsored by http://www.ThinkGeek.com/

Reply via email to