FYI, here's a patch I just added to my 2.5 bk trees that adds driver core bus support for the usb-serial drivers. Now all of the different ports show up in sysfs individually, which will make things easier in the future.
It also shows what ports are attached to what drivers, as this snippet of /sys on my box illustrates: | `-- usb-serial | |-- devices | | |-- ttyUSB0 -> ../../../devices/pci0/00:1f.2/usb1/1-1/1-1.3/ttyUSB0 | | |-- ttyUSB1 -> ../../../devices/pci0/00:1f.2/usb1/1-1/1-1.3/ttyUSB1 | | |-- ttyUSB2 -> ../../../devices/pci0/00:1f.2/usb1/1-1/1-1.3/ttyUSB2 | | |-- ttyUSB3 -> ../../../devices/pci0/00:1f.2/usb1/1-1/1-1.3/ttyUSB3 | | `-- ttyUSB4 -> ../../../devices/pci0/00:1e.0/01:0d.1/usb4/4-1/ttyUSB4 | `-- drivers | |-- Edgeport 1 port ^B | |-- Edgeport 2 port ^B | |-- Edgeport 4 port ^B | | |-- ttyUSB0 -> ../../../../devices/pci0/00:1f.2/usb1/1-1/1-1.3/ttyUSB0 | | |-- ttyUSB1 -> ../../../../devices/pci0/00:1f.2/usb1/1-1/1-1.3/ttyUSB1 | | |-- ttyUSB2 -> ../../../../devices/pci0/00:1f.2/usb1/1-1/1-1.3/ttyUSB2 | | `-- ttyUSB3 -> ../../../../devices/pci0/00:1f.2/usb1/1-1/1-1.3/ttyUSB3 | |-- Edgeport 8 port ^B | |-- Edgeport TI 1 po^B | | `-- ttyUSB4 -> |../../../../devices/pci0/00:1e.0/01:0d.1/usb4/4-1/ttyUSB4 | |-- Edgeport TI 2 po^B | `-- Generic yes, I'll fix up the naming issues :) The nicest part of this patch was that it didn't involve changing any of the individual usb-serial drivers. Comments welcomed. thanks, greg k-h diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c --- a/drivers/usb/serial/usb-serial.c Tue Dec 10 17:00:41 2002 +++ b/drivers/usb/serial/usb-serial.c Tue Dec 10 17:00:41 2002 @@ -14,6 +14,10 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (12/10/2002) gkh + * Split the ports off into their own struct device, and added a + * usb-serial bus driver. + * * (11/19/2002) gkh * removed a few #ifdefs for the generic code and cleaned up the failure * logic in initialization. @@ -345,7 +349,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.8" +#define DRIVER_VERSION "v2.0" #define DRIVER_AUTHOR "Greg Kroah-Hartman, [EMAIL PROTECTED], http://www.kroah.com/linux/" #define DRIVER_DESC "USB Serial Driver core" @@ -385,6 +389,32 @@ static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ static LIST_HEAD(usb_serial_driver_list); +static int usb_serial_device_match (struct device *dev, struct device_driver *drv) +{ + struct usb_serial_device_type *driver; + const struct usb_serial_port *port; + + /* + * drivers are already assigned to ports in serial_probe so it's + * a simple check here. + */ + port = to_usb_serial_port(dev); + if (!port) + return 0; + + driver = to_usb_serial_driver(drv); + + if (driver == port->serial->type) + return 1; + + return 0; +} + +static struct bus_type usb_serial_bus_type = { + .name = "usb-serial", + .match = usb_serial_device_match, +}; + struct usb_serial *usb_serial_get_by_minor (unsigned int minor) { return serial_table[minor]; @@ -1132,11 +1162,17 @@ } } - /* initialize the devfs nodes for this device and let the user know what ports we are bound to */ - for (i = 0; i < serial->num_ports; ++i) { - tty_register_devfs (&serial_tty_driver, 0, serial->port[i].number); - info("%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)", - type->name, serial->port[i].number, serial->port[i].number); + /* register all of the individual ports with the driver core */ + for (i = 0; i < num_ports; ++i) { + port = &serial->port[i]; + port->dev.parent = &serial->dev->dev; + port->dev.driver = NULL; + port->dev.bus = &usb_serial_bus_type; + + snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", +port->number); + snprintf (&port->dev.name[0], sizeof(port->dev.name), "usb serial port +%d", port->number); + dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id); + device_register (&port->dev); } usb_serial_console_init (debug, minor); @@ -1204,6 +1240,9 @@ serial_shutdown (serial); for (i = 0; i < serial->num_ports; ++i) + device_unregister(&serial->port[i].dev); + + for (i = 0; i < serial->num_ports; ++i) serial->port[i].open_count = 0; for (i = 0; i < serial->num_bulk_in; ++i) { @@ -1233,12 +1272,6 @@ if (port->interrupt_in_buffer) kfree (port->interrupt_in_buffer); } - - for (i = 0; i < serial->num_ports; ++i) { - tty_unregister_devfs (&serial_tty_driver, serial->port[i].number); - info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->port[i].number); - } - /* return the minor range that this device had */ return_serial (serial); @@ -1294,6 +1327,8 @@ serial_table[i] = NULL; } + bus_register(&usb_serial_bus_type); + /* register the generic driver, if we should */ result = usb_serial_generic_register(debug); if (result < 0) { @@ -1341,21 +1376,103 @@ usb_deregister(&usb_serial_driver); tty_unregister_driver(&serial_tty_driver); + bus_unregister(&usb_serial_bus_type); } module_init(usb_serial_init); module_exit(usb_serial_exit); +static int usb_serial_device_probe (struct device *dev) +{ + struct usb_serial_device_type *driver; + struct usb_serial_port *port; + int retval = 0; + int minor; + + port = to_usb_serial_port(dev); + if (!port) { + retval = -ENODEV; + goto exit; + } + + driver = port->serial->type; + if (driver->port_probe) { + if (!try_module_get(driver->owner)) { + err ("module get failed, exiting"); + retval = -EIO; + goto exit; + } + retval = driver->port_probe (port); + module_put(driver->owner); + if (retval) + goto exit; + } + + minor = port->number; + + tty_register_devfs (&serial_tty_driver, 0, minor); + info("%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)", + driver->name, minor, minor); + +exit: + return retval; +} + +static int usb_serial_device_remove (struct device *dev) +{ + struct usb_serial_device_type *driver; + struct usb_serial_port *port; + int retval = 0; + int minor; + + port = to_usb_serial_port(dev); + if (!port) { + return -ENODEV; + } + + driver = port->serial->type; + if (driver->port_remove) { + if (!try_module_get(driver->owner)) { + err ("module get failed, exiting"); + retval = -EIO; + goto exit; + } + retval = driver->port_remove (port); + module_put(driver->owner); + } +exit: + minor = port->number; + tty_unregister_devfs (&serial_tty_driver, minor); + info("%s converter now disconnected from ttyUSB%d", + driver->name, minor); + + return retval; +} int usb_serial_register(struct usb_serial_device_type *new_device) { + int retval; + /* Add this device to our list of devices */ list_add(&new_device->driver_list, &usb_serial_driver_list); - info ("USB Serial support registered for %s", new_device->name); + new_device->driver.name = (char *)new_device->name; + new_device->driver.bus = &usb_serial_bus_type; + new_device->driver.probe = usb_serial_device_probe; + new_device->driver.remove = usb_serial_device_remove; + + retval = driver_register(&new_device->driver); + + if (!retval) { + info("USB Serial support registered for %s", + new_device->name); + } else { + err("problem %d when registering driver %s", + retval, new_device->name); + } - return 0; + return retval; } diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h --- a/drivers/usb/serial/usb-serial.h Tue Dec 10 17:00:41 2002 +++ b/drivers/usb/serial/usb-serial.h Tue Dec 10 17:00:41 2002 @@ -121,7 +121,9 @@ int open_count; struct semaphore sem; void * private; + struct device dev; }; +#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev) /** * usb_serial - structure used by the usb-serial core for a device @@ -206,13 +208,17 @@ char num_ports; struct list_head driver_list; - + struct device_driver driver; + int (*probe) (struct usb_serial *serial); int (*attach) (struct usb_serial *serial); int (*calc_num_ports) (struct usb_serial *serial); void (*shutdown) (struct usb_serial *serial); + int (*port_probe) (struct usb_serial_port *port); + int (*port_remove) (struct usb_serial_port *port); + /* serial function calls */ int (*open) (struct usb_serial_port *port, struct file * filp); void (*close) (struct usb_serial_port *port, struct file * filp); @@ -229,6 +235,7 @@ void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs); void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs); }; +#define to_usb_serial_driver(d) container_of(d, struct usb_serial_device_type, driver) extern int usb_serial_register(struct usb_serial_device_type *new_device); extern void usb_serial_deregister(struct usb_serial_device_type *device); ------------------------------------------------------- This sf.net email is sponsored by: With Great Power, Comes Great Responsibility Learn to use your power at OSDN's High Performance Computing Channel http://hpc.devchannel.org/ _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
