X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fserial%2Foption.c;h=5cf2b80add7aa01ede3b1a588dc5c002d6dbccb8;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=c856e6f40e22c5ff7716e5d01f18c50a9c2b1bc0;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c856e6f40..5cf2b80ad 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1,5 +1,5 @@ /* - USB Driver for GSM modems + Option Card (PCMCIA to) USB to Serial Driver Copyright (C) 2005 Matthias Urlichs @@ -9,29 +9,36 @@ Portions copied from the Keyspan driver by Hugh Blemings - History: see the git log. + History: + + 2005-05-19 v0.1 Initial version, based on incomplete docs + and analysis of misbehavior with the standard driver + 2005-05-20 v0.2 Extended the input buffer to avoid losing + random 64-byte chunks of data + 2005-05-21 v0.3 implemented chars_in_buffer() + turned on low_latency + simplified the code somewhat + 2005-05-24 v0.4 option_write() sometimes deadlocked under heavy load + removed some dead code + added sponsor notice + coding style clean-up + 2005-06-20 v0.4.1 add missing braces :-/ + killed end-of-line whitespace + 2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2 + 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard + 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes + wants to send >2000 bytes. + 2006-04-10 v0.4.2 fixed two array overrun errors :-/ Work sponsored by: Sigos GmbH, Germany - This driver exists because the "normal" serial driver doesn't work too well - with GSM modems. Issues: - - data loss -- one single Receive URB is not nearly enough - - nonstandard flow (Option devices) control - - controlling the baud rate doesn't make sense - - This driver is named "option" because the most common device it's - used for is a PC-Card (with an internal OHCI-USB interface, behind - which the GSM interface sits), made by Option Inc. - - Some of the "one port" devices actually exhibit multiple USB instances - on the USB bus. This is not a bug, these ports are used for different - device features. */ -#define DRIVER_VERSION "v0.7.1" +#define DRIVER_VERSION "v0.4" #define DRIVER_AUTHOR "Matthias Urlichs " -#define DRIVER_DESC "USB Driver for GSM modems" +#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver" +#include #include #include #include @@ -39,7 +46,7 @@ #include #include #include -#include +#include "usb-serial.h" /* Function prototypes */ static int option_open(struct usb_serial_port *port, struct file *filp); @@ -67,45 +74,22 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file, static int option_send_setup(struct usb_serial_port *port); /* Vendor and product IDs */ -#define OPTION_VENDOR_ID 0x0AF0 -#define HUAWEI_VENDOR_ID 0x12D1 -#define AUDIOVOX_VENDOR_ID 0x0F3D -#define NOVATELWIRELESS_VENDOR_ID 0x1410 -#define ANYDATA_VENDOR_ID 0x16d5 - -#define OPTION_PRODUCT_OLD 0x5000 -#define OPTION_PRODUCT_FUSION 0x6000 -#define OPTION_PRODUCT_FUSION2 0x6300 -#define OPTION_PRODUCT_COBRA 0x6500 -#define OPTION_PRODUCT_COBRA2 0x6600 -#define HUAWEI_PRODUCT_E600 0x1001 -#define AUDIOVOX_PRODUCT_AIRCARD 0x0112 -#define NOVATELWIRELESS_PRODUCT_U740 0x1400 -#define ANYDATA_PRODUCT_ID 0x6501 +#define OPTION_VENDOR_ID 0x0AF0 +#define HUAWEI_VENDOR_ID 0x12D1 +#define AUDIOVOX_VENDOR_ID 0x0F3D -static struct usb_device_id option_ids[] = { - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, - { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, - { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, - { } /* Terminating entry */ -}; +#define OPTION_PRODUCT_OLD 0x5000 +#define OPTION_PRODUCT_FUSION 0x6000 +#define OPTION_PRODUCT_FUSION2 0x6300 +#define HUAWEI_PRODUCT_E600 0x1001 +#define AUDIOVOX_PRODUCT_AIRCARD 0x0112 -static struct usb_device_id option_ids1[] = { +static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, - { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -122,18 +106,17 @@ static struct usb_driver option_driver = { /* The card has three separate interfaces, which the serial driver * recognizes separately, thus num_port=1. */ - -static struct usb_serial_driver option_1port_device = { +static struct usb_serial_driver option_3port_device = { .driver = { .owner = THIS_MODULE, - .name = "option1", + .name = "option", }, - .description = "GSM modem (1-port)", - .id_table = option_ids1, + .description = "Option 3G data card", + .id_table = option_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE, - .num_ports = 1, + .num_ports = 1, /* 3, but the card reports its ports separately */ .open = option_open, .close = option_close, .write = option_write, @@ -187,9 +170,9 @@ struct option_port_private { static int __init option_init(void) { int retval; - retval = usb_serial_register(&option_1port_device); + retval = usb_serial_register(&option_3port_device); if (retval) - goto failed_1port_device_register; + goto failed_3port_device_register; retval = usb_register(&option_driver); if (retval) goto failed_driver_register; @@ -199,15 +182,15 @@ static int __init option_init(void) return 0; failed_driver_register: - usb_serial_deregister (&option_1port_device); -failed_1port_device_register: + usb_serial_deregister (&option_3port_device); +failed_3port_device_register: return retval; } static void __exit option_exit(void) { usb_deregister (&option_driver); - usb_serial_deregister (&option_1port_device); + usb_serial_deregister (&option_3port_device); } module_init(option_init); @@ -382,7 +365,8 @@ static void option_outdat_callback(struct urb *urb, struct pt_regs *regs) port = (struct usb_serial_port *) urb->context; - usb_serial_port_softint(port); + if (port->open_count) + schedule_work(&port->work); } static void option_instat_callback(struct urb *urb, struct pt_regs *regs) @@ -589,29 +573,27 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint, /* Setup urbs */ static void option_setup_urbs(struct usb_serial *serial) { - int i,j; + int j; struct usb_serial_port *port; struct option_port_private *portdata; dbg("%s", __FUNCTION__); - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = usb_get_serial_port_data(port); + port = serial->port[0]; + portdata = usb_get_serial_port_data(port); /* Do indat endpoints first */ - for (j = 0; j < N_IN_URB; ++j) { - portdata->in_urbs[j] = option_setup_urb (serial, - port->bulk_in_endpointAddress, USB_DIR_IN, port, - portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); - } + for (j = 0; j < N_IN_URB; ++j) { + portdata->in_urbs[j] = option_setup_urb (serial, + port->bulk_in_endpointAddress, USB_DIR_IN, port, + portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); + } - /* outdat endpoints */ - for (j = 0; j < N_OUT_URB; ++j) { - portdata->out_urbs[j] = option_setup_urb (serial, - port->bulk_out_endpointAddress, USB_DIR_OUT, port, - portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); - } + /* outdat endpoints */ + for (j = 0; j < N_OUT_URB; ++j) { + portdata->out_urbs[j] = option_setup_urb (serial, + port->bulk_out_endpointAddress, USB_DIR_OUT, port, + portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); } }