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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel