patch-2.3.99-pre6 linux/drivers/usb/serial/usbserial.c
Next file: linux/drivers/usb/uhci-debug.h
Previous file: linux/drivers/usb/serial/usb-serial.h
Back to the patch index
Back to the overall index
- Lines: 563
- Date:
Mon Apr 24 16:15:01 2000
- Orig file:
v2.3.99-pre5/linux/drivers/usb/serial/usbserial.c
- Orig date:
Tue Apr 11 15:09:20 2000
diff -u --recursive --new-file v2.3.99-pre5/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
@@ -14,6 +14,14 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (04/23/2000) gkh
+ * Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports.
+ * Moved when the startup code printed out the devices that are supported.
+ *
+ * (04/19/2000) gkh
+ * Added driver for ZyXEL omni.net lcd plus ISDN TA
+ * Made startup info message specify which drivers were compiled in.
+ *
* (04/03/2000) gkh
* Changed the probe process to remove the module unload races.
* Changed where the tty layer gets initialized to have devfs work nicer.
@@ -211,6 +219,7 @@
#include "usb-serial.h"
+#define MAX(a,b) (((a)>(b))?(a):(b))
/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
/* need to always compile these in, as some of the other devices use these functions as their own. */
@@ -270,6 +279,9 @@
&keyspan_pda_fake_device,
&keyspan_pda_device,
#endif
+#ifdef CONFIG_USB_SERIAL_OMNINET
+ &zyxel_omninet_device,
+#endif
NULL
};
@@ -424,14 +436,9 @@
return -ENODEV;
}
- /* set up our port structure */
+ /* set up our port structure making the tty driver remember our port object, and us it */
portNumber = MINOR(tty->device) - serial->minor;
port = &serial->port[portNumber];
- port->number = portNumber;
- port->serial = serial;
- port->magic = USB_SERIAL_PORT_MAGIC;
-
- /* make the tty driver remember our port object, and us it */
tty->driver_data = port;
port->tty = tty;
@@ -996,236 +1003,248 @@
int num_bulk_in = 0;
int num_bulk_out = 0;
int num_ports;
+ int max_endpoints;
- /* loop through our list of known serial converters, and see if this device matches */
- device_num = 0;
- while (usb_serial_devices[device_num] != NULL) {
+ /* loop through our list of known serial converters, and see if this
+ device matches. */
+ for (device_num = 0; usb_serial_devices[device_num]; device_num++) {
type = usb_serial_devices[device_num];
- dbg ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct));
+ dbg ("Looking at %s Vendor id=%.4x Product id=%.4x",
+ type->name, *(type->idVendor), *(type->idProduct));
/* look at the device descriptor */
if ((dev->descriptor.idVendor == *(type->idVendor)) &&
(dev->descriptor.idProduct == *(type->idProduct))) {
+ dbg("descriptor matches");
+ break;
+ }
+ }
+ if (!usb_serial_devices[device_num]) {
+ /* no match */
+ dbg("none matched");
+ return(NULL);
+ }
- dbg("descriptor matches...looking at the endpoints");
-
- /* descriptor matches, let's try to find the endpoints needed */
- interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;
+ /* descriptor matches, let's find the endpoints needed */
+ interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;
- /* check out the endpoints */
- interface = &dev->actconfig->interface[ifnum].altsetting[0];
- for (i = 0; i < interface->bNumEndpoints; ++i) {
- endpoint = &interface->endpoint[i];
-
- if ((endpoint->bEndpointAddress & 0x80) &&
- ((endpoint->bmAttributes & 3) == 0x02)) {
- /* we found a bulk in endpoint */
- dbg("found bulk in");
- bulk_in_pipe = HAS;
- bulk_in_endpoint[num_bulk_in] = endpoint;
- ++num_bulk_in;
- }
-
- if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
- ((endpoint->bmAttributes & 3) == 0x02)) {
- /* we found a bulk out endpoint */
- dbg("found bulk out");
- bulk_out_pipe = HAS;
- bulk_out_endpoint[num_bulk_out] = endpoint;
- ++num_bulk_out;
- }
+ /* check out the endpoints */
+ interface = &dev->actconfig->interface[ifnum].altsetting[0];
+ for (i = 0; i < interface->bNumEndpoints; ++i) {
+ endpoint = &interface->endpoint[i];
- if ((endpoint->bEndpointAddress & 0x80) &&
- ((endpoint->bmAttributes & 3) == 0x03)) {
- /* we found a interrupt in endpoint */
- dbg("found interrupt in");
- interrupt_pipe = HAS;
- interrupt_in_endpoint[num_interrupt_in] = endpoint;
- ++num_interrupt_in;
- }
+ if ((endpoint->bEndpointAddress & 0x80) &&
+ ((endpoint->bmAttributes & 3) == 0x02)) {
+ /* we found a bulk in endpoint */
+ dbg("found bulk in");
+ bulk_in_pipe = HAS;
+ bulk_in_endpoint[num_bulk_in] = endpoint;
+ ++num_bulk_in;
+ }
- }
+ if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+ ((endpoint->bmAttributes & 3) == 0x02)) {
+ /* we found a bulk out endpoint */
+ dbg("found bulk out");
+ bulk_out_pipe = HAS;
+ bulk_out_endpoint[num_bulk_out] = endpoint;
+ ++num_bulk_out;
+ }
+
+ if ((endpoint->bEndpointAddress & 0x80) &&
+ ((endpoint->bmAttributes & 3) == 0x03)) {
+ /* we found a interrupt in endpoint */
+ dbg("found interrupt in");
+ interrupt_pipe = HAS;
+ interrupt_in_endpoint[num_interrupt_in] = endpoint;
+ ++num_interrupt_in;
+ }
+ }
- /* verify that we found all of the endpoints that we need */
- if ((interrupt_pipe & type->needs_interrupt_in) &&
- (bulk_in_pipe & type->needs_bulk_in) &&
- (bulk_out_pipe & type->needs_bulk_out)) {
- /* found all that we need */
- MOD_INC_USE_COUNT;
- info("%s converter detected", type->name);
+ /* verify that we found all of the endpoints that we need */
+ if (!((interrupt_pipe & type->needs_interrupt_in) &&
+ (bulk_in_pipe & type->needs_bulk_in) &&
+ (bulk_out_pipe & type->needs_bulk_out))) {
+ /* nope, they don't match what we expected */
+ info("descriptors matched, but endpoints did not");
+ return NULL;
+ }
-#ifdef CONFIG_USB_SERIAL_GENERIC
- if (type == &generic_device)
- num_ports = num_bulk_out;
- else
-#endif
- num_ports = type->num_ports;
+ /* found all that we need */
+ MOD_INC_USE_COUNT;
+ info("%s converter detected", type->name);
- serial = get_free_serial (num_ports, &minor);
- if (serial == NULL) {
- err("No more free serial devices");
- MOD_DEC_USE_COUNT;
- return NULL;
- }
-
- serial->dev = dev;
- serial->type = type;
- serial->minor = minor;
- serial->num_ports = num_ports;
- serial->num_bulk_in = num_bulk_in;
- serial->num_bulk_out = num_bulk_out;
- serial->num_interrupt_in = num_interrupt_in;
-
- /* initialize a tty_driver for this device */
- serial->tty_driver = usb_serial_tty_driver_init (serial);
- if (serial->tty_driver == NULL) {
- err("Can't create a tty_serial_driver");
- goto probe_error;
- }
-
- if (tty_register_driver (serial->tty_driver)) {
- err("failed to register tty driver");
- goto probe_error;
- }
-
- /* collect interrupt_in endpoints now, because
- the keyspan_pda startup function needs
- to know about them */
- for (i = 0; i < num_interrupt_in; ++i) {
- port = &serial->port[i];
- buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize;
- port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
- if (!port->interrupt_in_buffer) {
- err("Couldn't allocate interrupt_in_buffer");
- goto probe_error;
- }
- port->interrupt_in_endpoint = interrupt_in_endpoint[i];
- }
-
- /* if this device type has a startup function, call it */
- if (type->startup) {
- if (type->startup (serial)) {
- goto probe_error;
- }
- }
-
- /* set up the endpoint information */
- for (i = 0; i < num_bulk_in; ++i) {
- port = &serial->port[i];
- port->read_urb = usb_alloc_urb (0);
- if (!port->read_urb) {
- err("No free urbs available");
- goto probe_error;
- }
- buffer_size = bulk_in_endpoint[i]->wMaxPacketSize;
- port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
- if (!port->bulk_in_buffer) {
- err("Couldn't allocate bulk_in_buffer");
- goto probe_error;
- }
- if (serial->type->read_bulk_callback) {
- FILL_BULK_URB(port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
- port->bulk_in_buffer, buffer_size, serial->type->read_bulk_callback, port);
- } else {
- FILL_BULK_URB(port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
- port->bulk_in_buffer, buffer_size, generic_read_bulk_callback, port);
- }
- }
-
- for (i = 0; i < num_bulk_out; ++i) {
- port = &serial->port[i];
- port->write_urb = usb_alloc_urb(0);
- if (!port->write_urb) {
- err("No free urbs available");
- goto probe_error;
- }
- port->bulk_out_size = bulk_out_endpoint[i]->wMaxPacketSize;
- port->bulk_out_buffer = kmalloc (port->bulk_out_size, GFP_KERNEL);
- if (!port->bulk_out_buffer) {
- err("Couldn't allocate bulk_out_buffer");
- goto probe_error;
- }
- if (serial->type->write_bulk_callback) {
- FILL_BULK_URB(port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
- port->bulk_out_buffer, port->bulk_out_size, serial->type->write_bulk_callback, port);
- } else {
- FILL_BULK_URB(port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
- port->bulk_out_buffer, port->bulk_out_size, generic_write_bulk_callback, port);
- }
- }
-
-#if 0 /* use this code when WhiteHEAT is up and running */
- for (i = 0; i < num_interrupt_in; ++i) {
- port = &serial->port[i];
- port->control_urb = usb_alloc_urb(0);
- if (!port->control_urb) {
- err("No free urbs available");
- goto probe_error;
- }
- buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize;
- port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
- if (!port->interrupt_in_buffer) {
- err("Couldn't allocate interrupt_in_buffer");
- goto probe_error;
- }
- FILL_INT_URB(port->control_urb, dev, usb_rcvintpipe (dev, interrupt_in_endpoint[i]->bEndpointAddress),
- port->interrupt_in_buffer, buffer_size, serial_control_irq,
- port, interrupt_in_endpoint[i]->bInterval);
- }
+#ifdef CONFIG_USB_SERIAL_GENERIC
+ if (type == &generic_device) {
+ num_ports = num_bulk_out;
+ if (num_ports == 0) {
+ err("Generic device with no bulk out, not allowed.");
+ MOD_DEC_USE_COUNT;
+ return NULL;
+ }
+ } else
#endif
+ num_ports = type->num_ports;
- for (i = 0; i < serial->num_ports; ++i) {
- info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i);
- }
-
- return serial;
- } else {
- info("descriptors matched, but endpoints did not");
- }
+ serial = get_free_serial (num_ports, &minor);
+ if (serial == NULL) {
+ err("No more free serial devices");
+ MOD_DEC_USE_COUNT;
+ return NULL;
+ }
+
+ serial->dev = dev;
+ serial->type = type;
+ serial->minor = minor;
+ serial->num_ports = num_ports;
+ serial->num_bulk_in = num_bulk_in;
+ serial->num_bulk_out = num_bulk_out;
+ serial->num_interrupt_in = num_interrupt_in;
+
+ /* initialize a tty_driver for this device */
+ serial->tty_driver = usb_serial_tty_driver_init (serial);
+ if (serial->tty_driver == NULL) {
+ err("Can't create a tty_serial_driver");
+ goto probe_error;
+ }
+
+ if (tty_register_driver (serial->tty_driver)) {
+ err("failed to register tty driver");
+ goto probe_error;
+ }
+
+ /* if this device type has a startup function, call it */
+ if (type->startup) {
+ if (type->startup (serial)) {
+ goto probe_error;
}
-
- /* look at the next type in our list */
- ++device_num;
}
-probe_error:
- if (serial) {
- for (i = 0; i < num_bulk_in; ++i) {
- port = &serial->port[i];
- if (port->read_urb)
- usb_free_urb (port->read_urb);
- if (serial->port[i].bulk_in_buffer[i])
- kfree (serial->port[i].bulk_in_buffer);
+ /* set up the endpoint information */
+ for (i = 0; i < num_bulk_in; ++i) {
+ endpoint = bulk_in_endpoint[i];
+ port = &serial->port[i];
+ port->read_urb = usb_alloc_urb (0);
+ if (!port->read_urb) {
+ err("No free urbs available");
+ goto probe_error;
}
- for (i = 0; i < num_bulk_out; ++i) {
- port = &serial->port[i];
- if (port->write_urb)
- usb_free_urb (port->write_urb);
- if (serial->port[i].bulk_out_buffer)
- kfree (serial->port[i].bulk_out_buffer);
+ buffer_size = endpoint->wMaxPacketSize;
+ port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!port->bulk_in_buffer) {
+ err("Couldn't allocate bulk_in_buffer");
+ goto probe_error;
}
- for (i = 0; i < num_interrupt_in; ++i) {
- port = &serial->port[i];
- if (port->control_urb)
- usb_free_urb (port->control_urb);
- if (serial->port[i].interrupt_in_buffer)
- kfree (serial->port[i].interrupt_in_buffer);
+ FILL_BULK_URB(port->read_urb, dev,
+ usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
+ port->bulk_in_buffer, buffer_size,
+ ((serial->type->read_bulk_callback) ?
+ serial->type->read_bulk_callback :
+ generic_read_bulk_callback),
+ port);
+ }
+
+ for (i = 0; i < num_bulk_out; ++i) {
+ endpoint = bulk_out_endpoint[i];
+ port = &serial->port[i];
+ port->write_urb = usb_alloc_urb(0);
+ if (!port->write_urb) {
+ err("No free urbs available");
+ goto probe_error;
}
-
- /* return the minor range that this device had */
- return_serial (serial);
-
- /* if this device has a tty_driver, then unregister it and free it */
- if (serial->tty_driver) {
- tty_unregister_driver (serial->tty_driver);
- kfree (serial->tty_driver);
- serial->tty_driver = NULL;
+ buffer_size = endpoint->wMaxPacketSize;
+ port->bulk_out_size = buffer_size;
+ port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!port->bulk_out_buffer) {
+ err("Couldn't allocate bulk_out_buffer");
+ goto probe_error;
+ }
+ FILL_BULK_URB(port->write_urb, dev,
+ usb_sndbulkpipe(dev, endpoint->bEndpointAddress),
+ port->bulk_out_buffer, buffer_size,
+ ((serial->type->write_bulk_callback) ?
+ serial->type->write_bulk_callback :
+ generic_write_bulk_callback),
+ port);
+ }
+
+ for (i = 0; i < num_interrupt_in; ++i) {
+ endpoint = interrupt_in_endpoint[i];
+ port = &serial->port[i];
+ port->interrupt_in_urb = usb_alloc_urb(0);
+ if (!port->interrupt_in_urb) {
+ err("No free urbs available");
+ goto probe_error;
}
+ buffer_size = endpoint->wMaxPacketSize;
+ port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!port->interrupt_in_buffer) {
+ err("Couldn't allocate interrupt_in_buffer");
+ goto probe_error;
+ }
+ FILL_INT_URB(port->interrupt_in_urb, dev,
+ usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+ port->interrupt_in_buffer, buffer_size,
+ serial->type->read_int_callback,
+ port,
+ endpoint->bInterval);
+ }
+
+ /* initialize some parts of the port structures */
+ /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
+ max_endpoints = MAX(num_bulk_in, num_bulk_out);
+ max_endpoints = MAX(max_endpoints, num_interrupt_in);
+ for (i = 0; i < max_endpoints; ++i) {
+ port = &serial->port[i];
+ port->number = i;
+ port->serial = serial;
+ port->magic = USB_SERIAL_PORT_MAGIC;
+ }
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ info("%s converter now attached to ttyUSB%d",
+ type->name, serial->minor + i);
+ }
+
+ return serial; /* success */
- /* free up any memory that we allocated */
- kfree (serial);
- MOD_DEC_USE_COUNT;
+
+probe_error:
+ for (i = 0; i < num_bulk_in; ++i) {
+ port = &serial->port[i];
+ if (port->read_urb)
+ usb_free_urb (port->read_urb);
+ if (port->bulk_in_buffer)
+ kfree (port->bulk_in_buffer);
+ }
+ for (i = 0; i < num_bulk_out; ++i) {
+ port = &serial->port[i];
+ if (port->write_urb)
+ usb_free_urb (port->write_urb);
+ if (port->bulk_out_buffer)
+ kfree (port->bulk_out_buffer);
+ }
+ for (i = 0; i < num_interrupt_in; ++i) {
+ port = &serial->port[i];
+ if (port->interrupt_in_urb)
+ usb_free_urb (port->interrupt_in_urb);
+ if (port->interrupt_in_buffer)
+ kfree (port->interrupt_in_buffer);
}
+
+ /* return the minor range that this device had */
+ return_serial (serial);
+
+ /* if this device has a tty_driver, then unregister it and free it */
+ if (serial->tty_driver) {
+ tty_unregister_driver (serial->tty_driver);
+ kfree (serial->tty_driver);
+ serial->tty_driver = NULL;
+ }
+
+ /* free up any memory that we allocated */
+ kfree (serial);
+ MOD_DEC_USE_COUNT;
return NULL;
}
@@ -1237,6 +1256,9 @@
int i;
if (serial) {
+ if (serial->type->shutdown)
+ serial->type->shutdown(serial);
+
for (i = 0; i < serial->num_ports; ++i)
serial->port[i].active = 0;
@@ -1260,9 +1282,9 @@
}
for (i = 0; i < serial->num_interrupt_in; ++i) {
port = &serial->port[i];
- if (port->control_urb) {
- usb_unlink_urb (port->control_urb);
- usb_free_urb (port->control_urb);
+ if (port->interrupt_in_urb) {
+ usb_unlink_urb (port->interrupt_in_urb);
+ usb_free_urb (port->interrupt_in_urb);
}
if (port->interrupt_in_buffer)
kfree (port->interrupt_in_buffer);
@@ -1295,18 +1317,32 @@
int usb_serial_init(void)
{
int i;
+ int something;
+ int result;
/* Initalize our global data */
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
serial_table[i] = NULL;
}
+ /* tell the world what devices this driver currently supports */
+ something = 0;
+ for (i = 0; usb_serial_devices[i]; ++i) {
+ if (!strstr (usb_serial_devices[i]->name, "prerenumeration")) {
+ info ("USB Serial support registered for %s", usb_serial_devices[i]->name);
+ something = 1;
+ }
+ }
+ if (!something)
+ info ("USB Serial driver is not configured for any devices!");
+
/* register the USB driver */
- if (usb_register(&usb_serial_driver) < 0) {
+ result = usb_register(&usb_serial_driver);
+ if (result < 0) {
+ err("usb_register failed for the usb-serial driver. Error number %d", result);
return -1;
}
-
- info("support registered");
+
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)