# 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.485 -> 1.486 # drivers/usb/serial/usbserial.c 1.32 -> 1.33 # drivers/usb/serial/usb-serial.h 1.9 -> 1.10 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/06/14 greg@kroah.com 1.486 # USB: usb-serial api changes # - added calc_num_ports() callback so that driver can override the # fixed num_ports value after querying the device. # - split startup() callback into probe() and attach() in anticipation # of the driverfs api changes # - probe() is called before the usb_serial structure is set up, # and can be used to download firmware to a device, and other # early initialization. # - attach() is called after the usb_serial structure is completely # setup, allowing the device to create private structures, and # have full access to the device. # -------------------------------------------- # diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h --- a/drivers/usb/serial/usb-serial.h Fri Jun 14 14:15:26 2002 +++ b/drivers/usb/serial/usb-serial.h Fri Jun 14 14:15:26 2002 @@ -130,9 +130,20 @@ * @num_bulk_in: the number of bulk in endpoints this device will have. * @num_bulk_out: the number of bulk out endpoints this device will have. * @num_ports: the number of different ports this device will have. - * @startup: pointer to the driver's startup function. This will be called - * when the driver is inserted into the system. Return 0 to continue - * on with the initialization sequence. Anything else will abort it. + * @calc_num_ports: pointer to a function to determine how many ports this + * device has dynamically. It will be called after the probe() + * callback is called, but before attach() + * @probe: pointer to the driver's probe function. + * This will be called when the device is inserted into the system, + * but before the device has been fully initialized by the usb_serial + * subsystem. Use this function to download any firmware to the device, + * or any other early initialization that might be needed. + * Return 0 to continue on with the initialization sequence. Anything + * else will abort it. + * @attach: pointer to the driver's attach function. + * This will be called when the struct usb_serial structure is fully set + * set up. Do any local initialization of the device, or any private + * memory structure allocation at this point in time. * @shutdown: pointer to the driver's shutdown function. This will be * called when the device is removed from the system. * @@ -153,7 +164,10 @@ struct list_head driver_list; - int (*startup) (struct usb_serial *serial); + 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); /* serial function calls */ diff -Nru a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c --- a/drivers/usb/serial/usbserial.c Fri Jun 14 14:15:26 2002 +++ b/drivers/usb/serial/usbserial.c Fri Jun 14 14:15:26 2002 @@ -433,9 +433,8 @@ return serial_table[minor]; } -static struct usb_serial *get_free_serial (int num_ports, unsigned int *minor) +static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_ports, unsigned int *minor) { - struct usb_serial *serial = NULL; unsigned int i, j; int good_spot; @@ -453,11 +452,14 @@ if (good_spot == 0) continue; - if (!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) { - err(__FUNCTION__ " - Out of memory"); - return NULL; + if (!serial) { + serial = kmalloc(sizeof(*serial), GFP_KERNEL); + if (!serial) { + err(__FUNCTION__ " - Out of memory"); + return NULL; + } + memset(serial, 0, sizeof(*serial)); } - memset(serial, 0, sizeof(struct usb_serial)); serial->magic = USB_SERIAL_MAGIC; serial_table[i] = serial; *minor = i; @@ -1140,6 +1142,27 @@ wake_up_interruptible(&tty->write_wait); } +static struct usb_serial * create_serial (struct usb_device *dev, + struct usb_interface *interface, + struct usb_serial_device_type *type) +{ + struct usb_serial *serial; + + serial = kmalloc (sizeof (*serial), GFP_KERNEL); + if (!serial) { + err ("%s - out of memory", __FUNCTION__); + return NULL; + } + memset (serial, 0, sizeof(*serial)); + serial->dev = dev; + serial->type = type; + serial->interface = interface; + serial->vendor = dev->descriptor.idVendor; + serial->product = dev->descriptor.idProduct; + + return serial; +} + static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) { @@ -1161,7 +1184,7 @@ int num_interrupt_in = 0; int num_bulk_in = 0; int num_bulk_out = 0; - int num_ports; + int num_ports = 0; int max_endpoints; const struct usb_device_id *id_pattern = NULL; @@ -1184,6 +1207,27 @@ return(NULL); } + /* if this device type has a probe function, call it */ + if (type->probe) { + serial = create_serial (dev, interface, type); + if (!serial) { + err ("%s - out of memory", __FUNCTION__); + return NULL; + } + + if (type->owner) + __MOD_INC_USE_COUNT(type->owner); + retval = type->probe (serial); + if (type->owner) + __MOD_DEC_USE_COUNT(type->owner); + + if (retval < 0) { + dbg ("sub driver rejected device"); + kfree (serial); + return NULL; + } + } + /* descriptor matches, let's find the endpoints needed */ /* check out the endpoints */ iface_desc = &interface->altsetting[0]; @@ -1251,11 +1295,30 @@ err("Generic device with no bulk out, not allowed."); return NULL; } - } else + } #endif - num_ports = type->num_ports; + if (!num_ports) { + /* if this device type has a calc_num_ports function, call it */ + if (type->calc_num_ports) { + if (!serial) { + serial = create_serial (dev, interface, type); + if (!serial) { + err ("%s - out of memory", __FUNCTION__); + return NULL; + } + } - serial = get_free_serial (num_ports, &minor); + if (type->owner) + __MOD_INC_USE_COUNT(type->owner); + num_ports = type->calc_num_ports (serial); + if (type->owner) + __MOD_DEC_USE_COUNT(type->owner); + } + if (!num_ports) + num_ports = type->num_ports; + } + + serial = get_free_serial (serial, num_ports, &minor); if (serial == NULL) { err("No more free serial devices"); return NULL; @@ -1272,17 +1335,6 @@ serial->vendor = dev->descriptor.idVendor; serial->product = dev->descriptor.idProduct; - /* if this device type has a startup function, call it */ - if (type->startup) { - if (type->owner) - __MOD_INC_USE_COUNT(type->owner); - retval = type->startup (serial); - if (type->owner) - __MOD_DEC_USE_COUNT(type->owner); - if (retval) - goto probe_error; - } - /* set up the endpoint information */ for (i = 0; i < num_bulk_in; ++i) { endpoint = bulk_in_endpoint[i]; @@ -1372,6 +1424,22 @@ port->tqueue.routine = port_softint; port->tqueue.data = port; init_MUTEX (&port->sem); + } + + /* if this device type has an attach function, call it */ + if (type->attach) { + if (type->owner) + __MOD_INC_USE_COUNT(type->owner); + retval = type->attach (serial); + if (type->owner) + __MOD_DEC_USE_COUNT(type->owner); + if (retval < 0) + goto probe_error; + if (retval > 0) { + /* quietly accept this device, but don't bind to a serial port + * as it's about to disappear */ + return serial; + } } /* initialize the devfs nodes for this device and let the user know what ports we are bound to */