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