Commit 8274ff48 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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.
parent 15d55742
...@@ -130,9 +130,20 @@ struct usb_serial { ...@@ -130,9 +130,20 @@ struct usb_serial {
* @num_bulk_in: the number of bulk in endpoints this device will have. * @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_bulk_out: the number of bulk out endpoints this device will have.
* @num_ports: the number of different ports 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 * @calc_num_ports: pointer to a function to determine how many ports this
* when the driver is inserted into the system. Return 0 to continue * device has dynamically. It will be called after the probe()
* on with the initialization sequence. Anything else will abort it. * 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 * @shutdown: pointer to the driver's shutdown function. This will be
* called when the device is removed from the system. * called when the device is removed from the system.
* *
...@@ -153,7 +164,10 @@ struct usb_serial_device_type { ...@@ -153,7 +164,10 @@ struct usb_serial_device_type {
struct list_head driver_list; 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); void (*shutdown) (struct usb_serial *serial);
/* serial function calls */ /* serial function calls */
......
...@@ -433,9 +433,8 @@ static struct usb_serial *get_serial_by_minor (unsigned int minor) ...@@ -433,9 +433,8 @@ static struct usb_serial *get_serial_by_minor (unsigned int minor)
return serial_table[minor]; 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; unsigned int i, j;
int good_spot; int good_spot;
...@@ -453,11 +452,14 @@ static struct usb_serial *get_free_serial (int num_ports, unsigned int *minor) ...@@ -453,11 +452,14 @@ static struct usb_serial *get_free_serial (int num_ports, unsigned int *minor)
if (good_spot == 0) if (good_spot == 0)
continue; continue;
if (!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) { if (!serial) {
serial = kmalloc(sizeof(*serial), GFP_KERNEL);
if (!serial) {
err(__FUNCTION__ " - Out of memory"); err(__FUNCTION__ " - Out of memory");
return NULL; return NULL;
} }
memset(serial, 0, sizeof(struct usb_serial)); memset(serial, 0, sizeof(*serial));
}
serial->magic = USB_SERIAL_MAGIC; serial->magic = USB_SERIAL_MAGIC;
serial_table[i] = serial; serial_table[i] = serial;
*minor = i; *minor = i;
...@@ -1140,6 +1142,27 @@ static void port_softint(void *private) ...@@ -1140,6 +1142,27 @@ static void port_softint(void *private)
wake_up_interruptible(&tty->write_wait); 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, static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
...@@ -1161,7 +1184,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1161,7 +1184,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
int num_interrupt_in = 0; int num_interrupt_in = 0;
int num_bulk_in = 0; int num_bulk_in = 0;
int num_bulk_out = 0; int num_bulk_out = 0;
int num_ports; int num_ports = 0;
int max_endpoints; int max_endpoints;
const struct usb_device_id *id_pattern = NULL; const struct usb_device_id *id_pattern = NULL;
...@@ -1184,6 +1207,27 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1184,6 +1207,27 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
return(NULL); 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 */ /* descriptor matches, let's find the endpoints needed */
/* check out the endpoints */ /* check out the endpoints */
iface_desc = &interface->altsetting[0]; iface_desc = &interface->altsetting[0];
...@@ -1251,11 +1295,30 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1251,11 +1295,30 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
err("Generic device with no bulk out, not allowed."); err("Generic device with no bulk out, not allowed.");
return NULL; return NULL;
} }
} else }
#endif #endif
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;
}
}
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; num_ports = type->num_ports;
}
serial = get_free_serial (num_ports, &minor); serial = get_free_serial (serial, num_ports, &minor);
if (serial == NULL) { if (serial == NULL) {
err("No more free serial devices"); err("No more free serial devices");
return NULL; return NULL;
...@@ -1272,17 +1335,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1272,17 +1335,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
serial->vendor = dev->descriptor.idVendor; serial->vendor = dev->descriptor.idVendor;
serial->product = dev->descriptor.idProduct; 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 */ /* set up the endpoint information */
for (i = 0; i < num_bulk_in; ++i) { for (i = 0; i < num_bulk_in; ++i) {
endpoint = bulk_in_endpoint[i]; endpoint = bulk_in_endpoint[i];
...@@ -1374,6 +1426,22 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1374,6 +1426,22 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
init_MUTEX (&port->sem); 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 */ /* 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) { for (i = 0; i < serial->num_ports; ++i) {
tty_register_devfs (&serial_tty_driver, 0, serial->port[i].number); tty_register_devfs (&serial_tty_driver, 0, serial->port[i].number);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment