On Mon, 2 Oct 2006, Mike Panetta wrote:

> > This is very unclear.  Why do you want to disable the ports?  Why not
> > simply fail to enable them in the first place?
> Mainly because I do not know how to do that?  Is there a way to tell the 
> EHCI driver to not enable certain root hub ports?

No, there isn't.  Not at present.

> > If you don't want to use the built-in CF card reader, why not unplug (or
> > cut!) the cable connecting it to the EHCI controller?
> 
> Because its hardwired on the circuit board.  I suppose we could reverse 
> engineer the motherboard (its a VIA mini itx board) to do this, but 
> doing it in software is a much preferred solution as we can RMA the 
> boards back to VIA if something goes wrong with them.

Okay, fair enough.

> > Or put it another why: If you do want the port to be enabled so you can
> > access it, then why disable it in the first place?
> Because we are using 2 different motherboards and one does not have the 
> bad hardware issues.  We are trying to release a product and not have to 
> worry about there being 2 different kernel versions to support (one with 
> the ports enabled and one with the ports disabled in the driver).  If 
> there is another way to enable/disable ports in software that I do not 
> know about then that should work fine.

I get the picture.

What you really need is a new interface to the hub driver, not to 
ehci-hcd.  The patch below will do what you want.  It creates a new 
directory /sys/class/usb_hub/ with entries for each of the hubs, including 
root hubs, on the system.

Inside each of those directories is a file named "ignore".  Just like in 
the previous patch, the file contains a list of port numbers.  Ports 
listed in the file will be ignored by the hub driver -- they will remain 
permanently disabled.  Or until you remove them from the file.

The patch is meant for 2.6.18.

Alan Stern


Index: 2.6.18/drivers/usb/core/hub.c
===================================================================
--- 2.6.18.orig/drivers/usb/core/hub.c
+++ 2.6.18/drivers/usb/core/hub.c
@@ -31,6 +31,9 @@
 #include "hcd.h"
 #include "hub.h"
 
+
+static struct class *usb_hub_class;
+
 /* Protect struct usb_device->state and ->children members
  * Note: Both are also protected by ->dev.sem, except that ->state can
  * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
@@ -550,6 +553,57 @@ static void hub_post_reset(struct usb_in
 }
 
 
+/* Display the ports we are ignoring */
+static ssize_t show_ignore(struct class_device *class_dev, char *buf)
+{
+       struct usb_hub          *hub = class_get_devdata(class_dev);
+       int                     count = PAGE_SIZE;
+       int                     port1, n;
+       char                    *ptr = buf;
+
+       for (port1 = 1; port1 <= hub->hdev->maxchild; ++port1) {
+               if (test_bit(port1, hub->ignore_bits)) {
+                       n = scnprintf(ptr, count, "%d\n", port1);
+                       ptr += n;
+                       count -= n;
+               }
+       }
+       return ptr - buf;
+}
+
+/*
+ * Ignore or unignore a port.
+ * Syntax is "[-]portnum", where a leading '-' sign means
+ * stop ignoring (handle the port normally).
+ */
+static ssize_t store_ignore(struct class_device *class_dev,
+                const char *buf, size_t count)
+{
+       struct usb_hub          *hub = class_get_devdata(class_dev);
+       int                     port1;
+       int                     ignore = 1;
+
+       if (sscanf (buf, "%d", &port1) != 1)
+               return -EINVAL;
+       if (port1 < 0) {
+               port1 = - port1;
+               ignore = 0;             /* Stop ignoring */
+       }
+       if (port1 <= 0 || port1 > hub->hdev->maxchild)
+               return -ENOENT;
+       if (ignore)
+               set_bit(port1, hub->ignore_bits);
+       else if (!test_and_clear_bit(port1, hub->ignore_bits))
+               return count;
+
+       /* See what the port's doing ASAP */
+       set_bit(port1, hub->change_bits);
+       kick_khubd(hub);
+       return count;
+}
+static CLASS_DEVICE_ATTR(ignore, S_IRUGO | S_IWUSR, show_ignore, store_ignore);
+
+
 static int hub_configure(struct usb_hub *hub,
        struct usb_endpoint_descriptor *endpoint)
 {
@@ -788,6 +842,10 @@ static int hub_configure(struct usb_hub 
 
        hub_power_on(hub);
        hub_activate(hub);
+
+       /* we don't really care if this fails */
+       ret = class_device_create_file(hub->class_dev,
+                       &class_device_attr_ignore);
        return 0;
 
 fail:
@@ -804,6 +862,12 @@ static void hub_disconnect(struct usb_in
        struct usb_hub *hub = usb_get_intfdata (intf);
        struct usb_device *hdev;
 
+       if (hub->class_dev) {
+               class_device_remove_file(hub->class_dev,
+                               &class_device_attr_ignore);
+               class_device_unregister(hub->class_dev);
+       }
+
        /* Disconnect all children and quiesce the hub */
        hub->error = 0;
        hub_pre_reset(intf);
@@ -896,9 +960,19 @@ descriptor_error:
        if (hdev->speed == USB_SPEED_HIGH)
                highspeed_hubs++;
 
+       hub->class_dev = class_device_create(usb_hub_class, NULL,
+                       MKDEV(0,0), &hdev->dev,
+                       "usbhub%d.%d", hdev->bus->busnum, hdev->devnum);
+       if (IS_ERR(hub->class_dev)) {
+               hub->class_dev = NULL;
+               goto fail;
+       }
+       class_set_devdata(hub->class_dev, hub);
+
        if (hub_configure(hub, endpoint) >= 0)
                return 0;
 
+fail:
        hub_disconnect (intf);
        return -ENODEV;
 }
@@ -2542,7 +2616,9 @@ static void hub_port_connect_change(stru
                portstatus = status;
        }
 
-       /* Return now if nothing is connected */
+       /* Return now if we are ignoring the port or nothing is connected */
+       if (test_bit(port1, hub->ignore_bits))
+               goto done;
        if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
 
                /* maybe switch power back on (e.g. root hub was reset) */
@@ -2948,6 +3024,10 @@ static struct usb_driver hub_driver = {
 
 int usb_hub_init(void)
 {
+       usb_hub_class = class_create(THIS_MODULE, "usb_hub");
+       if (IS_ERR(usb_hub_class))
+               return PTR_ERR(usb_hub_class);
+
        if (usb_register(&hub_driver) < 0) {
                printk(KERN_ERR "%s: can't register hub driver\n",
                        usbcore_name);
@@ -2977,6 +3057,7 @@ void usb_hub_cleanup(void)
         * individual hub resources. -greg
         */
        usb_deregister(&hub_driver);
+       class_destroy(usb_hub_class);
 } /* usb_hub_cleanup() */
 
 static int config_descriptors_changed(struct usb_device *udev)
Index: 2.6.18/drivers/usb/core/hub.h
===================================================================
--- 2.6.18.orig/drivers/usb/core/hub.h
+++ 2.6.18/drivers/usb/core/hub.h
@@ -196,6 +196,7 @@ struct usb_hub {
        struct device           *intfdev;       /* the "interface" device */
        struct usb_device       *hdev;
        struct urb              *urb;           /* for interrupt polling pipe */
+       struct class_device     *class_dev;
 
        /* buffer for urb ... with extra space in case of babble */
        char                    (*buffer)[8];
@@ -213,6 +214,7 @@ struct usb_hub {
        unsigned long           change_bits[1]; /* ports with logical connect
                                                        status change */
        unsigned long           busy_bits[1];   /* ports being reset */
+       unsigned long           ignore_bits[1]; /* ports to ignore */
 #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
 #error event_bits[] is too short!
 #endif


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to