This patch extends the "option" driver with a few more devices,
some of which are actually connected to USB the "right" way --
as opposed to doing it via PCMCIA and OHCI.

Signed-Off-By: Matthias Urlichs <[EMAIL PROTECTED]>

---

--- a/drivers/usb/serial/Kconfig        2006-06-02 11:45:27.701919000 +0200
+++ b/drivers/usb/serial/Kconfig        2006-06-01 23:03:55.000000000 +0200
@@ -491,12 +491,30 @@
          module will be called keyspan_pda.
 
 config USB_SERIAL_OPTION
-       tristate "USB Option PCMCIA serial driver"
-       depends on USB_SERIAL && USB_OHCI_HCD && PCCARD
+       tristate "USB driver for GSM modems"
+       depends on USB_SERIAL
        help
-         Say Y here if you want to use an Option card. This is a
-         GSM card, controlled by three serial ports which are connected
-         via an OHCI adapter located on a PC card.
+         Say Y here if you have a GSM modem that's connected to USB.
+
+         To compile this driver as a module, choose M here: the
+         module will be called option.
+
+         If this driver doesn't recognize your device,
+         it might be accessible via the FTDI_SIO driver.
+
+config USB_SERIAL_OPTION_PCCARD
+       tristate "driver for GSM modems on PCMCIA cards"
+       depends on USB_SERIAL
+       select PCCARD
+       select USB_OHCI_HCD
+       select USB_SERIAL_OPTION
+       help
+         Say Y here if you have an "Option" GSM PCMCIA card
+         (or an OEM version: branded Huawei, Audiovox, or Novatel).
+
+         These cards feature a built-in OHCI-USB adapter and an
+         internally-connected GSM modem. The USB bus is not
+         accessible externally.
 
          To compile this driver as a module, choose M here: the
          module will be called option.
--- a/drivers/usb/serial/option.c       2006-06-02 11:20:45.164603000 +0200
+++ b/drivers/usb/serial/option.c       2006-06-02 11:20:21.688405738 +0200
@@ -1,5 +1,5 @@
 /*
-  Option Card (PCMCIA to) USB to Serial Driver
+  USB Driver for GSM modems
 
   Copyright (C) 2005  Matthias Urlichs <[EMAIL PROTECTED]>
 
@@ -28,15 +28,34 @@
   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 :-/
+  2006-04-10  v0.5   fixed two array overrun errors :-/
+  2006-04-21  v0.5.1 added support for Sierra Wireless MC8755
+  2006-05-15  v0.6   re-enable multi-port support
+  2006-06-01  v0.6.1 add COBRA
+  2006-06-01  v0.6.2 add backwards-compatibility stuff
+  2006-06-01  v0.6.3 add Novatel Wireless
+  2006-06-01  v0.7   Option => GSM
 
   Work sponsored by: Sigos GmbH, Germany <[EMAIL PROTECTED]>
 
+  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) and multiplex (Sierra) 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.4"
+#define DRIVER_VERSION "v0.7.0"
 #define DRIVER_AUTHOR "Matthias Urlichs <[EMAIL PROTECTED]>"
-#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver"
+#define DRIVER_DESC "USB Driver for GSM modems"
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -74,22 +93,45 @@
 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 OPTION_PRODUCT_OLD             0x5000
-#define OPTION_PRODUCT_FUSION  0x6000
-#define OPTION_PRODUCT_FUSION2 0x6300
-#define HUAWEI_PRODUCT_E600     0x1001
-#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
+#define OPTION_VENDOR_ID                0x0AF0
+#define HUAWEI_VENDOR_ID                0x12D1
+#define AUDIOVOX_VENDOR_ID              0x0F3D
+#define SIERRAWIRELESS_VENDOR_ID        0x1199
+#define NOVATELWIRELESS_VENDOR_ID       0x1410
+
+#define OPTION_PRODUCT_OLD              0x5000
+#define OPTION_PRODUCT_FUSION           0x6000
+#define OPTION_PRODUCT_FUSION2          0x6300
+#define OPTION_PRODUCT_COBRA            0x6500
+#define HUAWEI_PRODUCT_E600             0x1001
+#define AUDIOVOX_PRODUCT_AIRCARD        0x0112
+#define SIERRAWIRELESS_PRODUCT_MC8755   0x6802
+#define NOVATELWIRELESS_PRODUCT_U740    0x1400
 
 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(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
        { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
+       { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
+       { } /* Terminating entry */
+};
+
+static struct usb_device_id option_ids1[] = {
+       { 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(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+       { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
+       { } /* Terminating entry */
+};
+static struct usb_device_id option_ids3[] = {
+       { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
        { } /* Terminating entry */
 };
 
@@ -111,12 +153,39 @@
                .owner =        THIS_MODULE,
                .name =         "option",
        },
-       .description       = "Option 3G data card",
-       .id_table          = option_ids,
+       .description       = "GSM modem (3-port)",
+       .id_table          = option_ids3,
        .num_interrupt_in  = NUM_DONT_CARE,
        .num_bulk_in       = NUM_DONT_CARE,
        .num_bulk_out      = NUM_DONT_CARE,
-       .num_ports         = 1, /* 3, but the card reports its ports separately 
*/
+       .num_ports         = 3,
+       .open              = option_open,
+       .close             = option_close,
+       .write             = option_write,
+       .write_room        = option_write_room,
+       .chars_in_buffer   = option_chars_in_buffer,
+       .throttle          = option_rx_throttle,
+       .unthrottle        = option_rx_unthrottle,
+       .set_termios       = option_set_termios,
+       .break_ctl         = option_break_ctl,
+       .tiocmget          = option_tiocmget,
+       .tiocmset          = option_tiocmset,
+       .attach            = option_startup,
+       .shutdown          = option_shutdown,
+       .read_int_callback = option_instat_callback,
+};
+
+static struct usb_serial_driver option_1port_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "option",
+       },
+       .description       = "GSM modem (1-port)",
+       .id_table          = option_ids1,
+       .num_interrupt_in  = NUM_DONT_CARE,
+       .num_bulk_in       = NUM_DONT_CARE,
+       .num_bulk_out      = NUM_DONT_CARE,
+       .num_ports         = 1,
        .open              = option_open,
        .close             = option_close,
        .write             = option_write,
@@ -170,6 +239,9 @@
 static int __init option_init(void)
 {
        int retval;
+       retval = usb_serial_register(&option_1port_device);
+       if (retval)
+               goto failed_1port_device_register;
        retval = usb_serial_register(&option_3port_device);
        if (retval)
                goto failed_3port_device_register;
@@ -184,6 +256,8 @@
 failed_driver_register:
        usb_serial_deregister (&option_3port_device);
 failed_3port_device_register:
+       usb_serial_deregister (&option_1port_device);
+failed_1port_device_register:
        return retval;
 }
 
@@ -191,6 +265,7 @@
 {
        usb_deregister (&option_driver);
        usb_serial_deregister (&option_3port_device);
+       usb_serial_deregister (&option_1port_device);
 }
 
 module_init(option_init);
@@ -573,27 +648,30 @@
 /* Setup urbs */
 static void option_setup_urbs(struct usb_serial *serial)
 {
-       int j;
+       int i,j;
        struct usb_serial_port *port;
        struct option_port_private *portdata;
 
        dbg("%s", __FUNCTION__);
 
-       port = serial->port[0];
-       portdata = usb_get_serial_port_data(port);
+       
+       for (i = 0; i < serial->num_ports; i++) {
+               port = serial->port[i];
+               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);
+               }
        }
 }
 
-- 
Matthias Urlichs   |   {M:U} IT Design @ m-u-it.de   |  [EMAIL PROTECTED]
Disclaimer: The quote was selected randomly. Really. | http://smurf.noris.de
 - -
Last year we drove across the country...  We switched on the driving...
every half mile.  We had one cassette tape to listen to on the entire trip.
I don't remember what it was.
                -- Steven Wright

Attachment: signature.asc
Description: Digital signature

_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to