]> oss.titaniummirror.com Git - cp210x.git/commitdiff
Support Ubuntu 14.04 Trusty Tahr
authorR. Steve McKown <rsmckown@gmail.com>
Mon, 18 Aug 2014 16:33:43 +0000 (10:33 -0600)
committerR. Steve McKown <rsmckown@gmail.com>
Mon, 18 Aug 2014 17:35:59 +0000 (11:35 -0600)
* Merge cp210x.c changes for trusty from kernel 3.13 source
* Update build for 3.13 kernels

src/Makefile313 [new file with mode: 0644]
src/configure
src/cp210x.c

diff --git a/src/Makefile313 b/src/Makefile313
new file mode 100644 (file)
index 0000000..dfb38f5
--- /dev/null
@@ -0,0 +1,7 @@
+# CP2101/CP2102/CP2103 3.13 makefile
+
+EXTRA_CFLAGS += -I$(LINUX_INCLUDE) -I$(LINUX_KERNEL)/drivers/usb/serial -DLINUX26
+
+obj-m := cp210x.o
+
+cp210x-objs := $(OBJS)
index 1d20a181385529f52e49501287e70f5e64283d2c..32725a2c9e050340475e852217a1dd79ddf4777d 100755 (executable)
@@ -24,21 +24,21 @@ CONFIG_FILE="Makefile.config"
 
 while (($# > 0)) ; do
     if [ "$1" == "-help" ] || [ "$1" == "-h" ] ; then
-        usage
+       usage
        exit 0   
     elif [ "$1" == "-kinc" ] ; then
        if [ "$2" == "" ] ; then
            usage
            exit 1
        fi
-        LINUX_INCLUDE="$2"
+       LINUX_INCLUDE="$2"
        shift 2
     elif [ "$1" == "-kpath" ] ; then
        if [ "$2" == "" ] ; then
            usage
            exit 1
        fi
-        LINUX_KERNEL="$2"
+       LINUX_KERNEL="$2"
        shift 2
     elif [ "$1" == "-kver" ] ; then
        if [ "$2" == "" ] ; then
@@ -52,11 +52,11 @@ while (($# > 0)) ; do
            usage
            exit 1
        fi
-        INSTALL_PREFIX="$2"
+       INSTALL_PREFIX="$2"
        shift 2
     else
-        echo "ERROR: Unknown option $1"
-        exit 1
+       echo "ERROR: Unknown option $1"
+       exit 1
     fi
 done
 
@@ -88,14 +88,29 @@ KVER1=`echo $KVER | awk -F . -- '{ print $1 }'`
 KVER2=`echo $KVER | awk -F . -- '{ print $2 }'`
 KVER3=`echo $KVER | sed -e "s/$KVER1\\.$KVER2\\.//g"`
 
-case $KVER2 in
-    4)
-       makefile="Makefile24"
-       EXT=".o"
+case $KVER1 in
+    2)
+       case $KVER2 in
+           4)
+               makefile="Makefile24"
+               EXT=".o"
+               ;;
+           6)
+               makefile="Makefile26"
+               EXT=".ko"
+               ;;
+       esac
        ;;
-    6)
-       makefile="Makefile26"
+    3)
        EXT=".ko"
+       case $KVER2 in
+           2)
+               makefile="Makefile32"
+               ;;
+           13)
+               makefile="Makefile313"
+               ;;
+       esac
        ;;
 esac
 
index 1c25ecba256916b62b0536280109341b989fa2e8..bda81d3badb0537f3e5538581653f245d317b4c9 100644 (file)
@@ -36,8 +36,7 @@
  */
 static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);
 static void cp210x_close(struct usb_serial_port *);
-static void cp210x_get_termios(struct tty_struct *,
-       struct usb_serial_port *port);
+static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *);
 static void cp210x_get_termios_port(struct usb_serial_port *port,
        unsigned int *cflagp, unsigned int *baudp);
 static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
@@ -51,10 +50,8 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port,
 static void cp210x_break_ctl(struct tty_struct *, int);
 static int cp210x_startup(struct usb_serial *);
 static void cp210x_release(struct usb_serial *);
-static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
 static int cp210x_ioctl(struct tty_struct *, unsigned int, unsigned long);
-
-static int debug;
+static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
@@ -62,6 +59,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
        { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
        { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
+       { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */
        { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
        { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
        { USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
@@ -69,6 +67,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
        { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
        { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
+       { USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */
        { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
        { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
        { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
@@ -84,6 +83,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
        { USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */
        { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
+       { USB_DEVICE(0x10C4, 0x80C4) }, /* Cygnal Integrated Products, Inc., Optris infrared thermometer */
        { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
        { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */
        { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
@@ -92,8 +92,10 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
        { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
        { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+       { USB_DEVICE(0x2405, 0x0003) }, /* West Mountain Radio RIGblaster Advantage */
        { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
        { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
+       { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */
        { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
        { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
        { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
@@ -108,6 +110,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
        { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */
        { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */
+       { USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */
        { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */
        { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
        { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
@@ -120,8 +123,11 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
        { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
        { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
+       { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
        { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
        { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
+       { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
+       { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
        { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
@@ -135,7 +141,13 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */
        { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
        { USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */
+       { USB_DEVICE(0x166A, 0x0201) }, /* Clipsal 5500PACA C-Bus Pascal Automation Controller */
+       { USB_DEVICE(0x166A, 0x0301) }, /* Clipsal 5800PC C-Bus Wireless PC Interface */
        { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
+       { USB_DEVICE(0x166A, 0x0304) }, /* Clipsal 5000CT2 C-Bus Black and White Touchscreen */
+       { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */
+       { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */
+       { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */
        { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
        { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
        { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
@@ -146,32 +158,48 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
        { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
        { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+       { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
+       { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
        { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
+       { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
+       { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
+       { USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */
+       { USB_DEVICE(0x1FB9, 0x0200) }, /* Lake Shore Model 218A Temperature Monitor */
+       { USB_DEVICE(0x1FB9, 0x0201) }, /* Lake Shore Model 219 Temperature Monitor */
+       { USB_DEVICE(0x1FB9, 0x0202) }, /* Lake Shore Model 233 Temperature Transmitter */
+       { USB_DEVICE(0x1FB9, 0x0203) }, /* Lake Shore Model 235 Temperature Transmitter */
+       { USB_DEVICE(0x1FB9, 0x0300) }, /* Lake Shore Model 335 Temperature Controller */
+       { USB_DEVICE(0x1FB9, 0x0301) }, /* Lake Shore Model 336 Temperature Controller */
+       { USB_DEVICE(0x1FB9, 0x0302) }, /* Lake Shore Model 350 Temperature Controller */
+       { USB_DEVICE(0x1FB9, 0x0303) }, /* Lake Shore Model 371 AC Bridge */
+       { USB_DEVICE(0x1FB9, 0x0400) }, /* Lake Shore Model 411 Handheld Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0401) }, /* Lake Shore Model 425 Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0402) }, /* Lake Shore Model 455A Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0403) }, /* Lake Shore Model 475A Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0404) }, /* Lake Shore Model 465 Three Axis Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0600) }, /* Lake Shore Model 625A Superconducting MPS */
+       { USB_DEVICE(0x1FB9, 0x0601) }, /* Lake Shore Model 642A Magnet Power Supply */
+       { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */
+       { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */
+       { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */
        { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
+       { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
+       { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */
        { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
        { } /* Terminating Entry */
 };
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
-struct cp210x_port_private {
+struct cp210x_serial_private {
        __u8                    bInterfaceNumber;
 };
 
-static struct usb_driver cp210x_driver = {
-       .name           = "cp210x",
-       .probe          = usb_serial_probe,
-       .disconnect     = usb_serial_disconnect,
-       .id_table       = id_table,
-       .no_dynamic_id  =       1,
-};
-
 static struct usb_serial_driver cp210x_device = {
        .driver = {
                .owner =        THIS_MODULE,
-               .name =         "cp210x",
+               .name =         "cp210x",
        },
-       .usb_driver             = &cp210x_driver,
        .id_table               = id_table,
        .num_ports              = 1,
        .bulk_in_size           = 256,
@@ -181,16 +209,22 @@ static struct usb_serial_driver cp210x_device = {
        .ioctl                  = cp210x_ioctl,
        .break_ctl              = cp210x_break_ctl,
        .set_termios            = cp210x_set_termios,
-       .tiocmget               = cp210x_tiocmget,
+       .tiocmget               = cp210x_tiocmget,
        .tiocmset               = cp210x_tiocmset,
        .attach                 = cp210x_startup,
        .release                = cp210x_release,
        .dtr_rts                = cp210x_dtr_rts
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+       &cp210x_device, NULL
+};
+
 /* Config request types */
-#define REQTYPE_HOST_TO_DEVICE 0x41
-#define REQTYPE_DEVICE_TO_HOST 0xc1
+#define REQTYPE_HOST_TO_INTERFACE      0x41
+#define REQTYPE_INTERFACE_TO_HOST      0xc1
+#define REQTYPE_HOST_TO_DEVICE 0x40
+#define REQTYPE_DEVICE_TO_HOST 0xc0
 
 /* Config request codes */
 #define CP210X_IFC_ENABLE      0x00
@@ -414,7 +448,7 @@ static int cp210x_ctlmsg(struct usb_serial_port *port, u8 request,
        }
        kfree(tbuf);
        if (ret < 0 && ret != -EPIPE) {
-               dev_printk(KERN_DEBUG, &dev->dev,
+               dev_dbg(&port->dev,
                        "cp210x: ctl failed cmd rqt %u rq %u len %u ret %d\n",
                        requestype, request, size, ret);
        }
@@ -423,7 +457,7 @@ static int cp210x_ctlmsg(struct usb_serial_port *port, u8 request,
 
 static int cp210x_reset(struct usb_serial_port *port)
 {
-       dbg("%s", __func__);
+       dev_dbg(&port->dev, "%s", __func__);
 
        /* Instructing the CP210X to reset seems to work more reliably than
         * calling usb_reset_device().
@@ -452,7 +486,7 @@ static int cp210x_get_partnum(struct usb_serial_port *port)
                                _partnum = CP210x_PART_UNKNOWN;
                }
        }
-       dbg("%s - partnum %u", __func__, _partnum);
+       dev_dbg(&port->dev, "%s - partnum %u", __func__, _partnum);
        return _partnum;
 }
 
@@ -474,14 +508,16 @@ static int cp210x_setstr(struct usb_serial_port *port, int cmd, __le16 *usbstr)
        int len = ((u8 *)usbstr)[0];
        int ret = cp210x_ctlmsg(port, 0xff, USB_TYPE_VENDOR,
                        0x3700 | (cmd & 0xff), 0, usbstr, len);
-       dbg("%s - cmd 0x%02x len %d ret %d", __func__, cmd, len, ret);
+       dev_dbg(&port->dev, "%s - cmd 0x%02x len %d ret %d", __func__, cmd,
+                       len, ret);
        return ret;
 }
 
 /* Set all gpio simultaneously */
 static int cp210x_gpioset(struct usb_serial_port *port, u8 gpio)
 {
-       dbg("%s - port %d, gpio = 0x%.2x", __func__, port->number, gpio);
+       dev_dbg(&port->dev, "%s - port %d, gpio = 0x%.2x", __func__,
+                       port->port_number, gpio);
 
        return cp210x_ctlmsg(port, 0xff, USB_TYPE_VENDOR,
                        0x37e1, ((uint16_t)gpio << 8) | GPIO_MASK, NULL, 0);
@@ -510,7 +546,8 @@ static int cp210x_gpiosetb(struct usb_serial_port *port, u8 set, u8 clear)
        if (clear & GPIO_3)
                gpio = (gpio & ~(GPIO_3 << 8))|GPIO_3;
 
-       dbg("%s - port %d, gpiob = 0x%.4x", __func__, port->number, gpio);
+       dev_dbg(&port->dev, "%s - port %d, gpiob = 0x%.4x", __func__,
+                       port->port_number, gpio);
 
        return cp210x_ctlmsg(port, 0xff, USB_TYPE_VENDOR,
                        0x37e1, gpio, NULL, 0);
@@ -520,12 +557,12 @@ static int cp210x_gpioget(struct usb_serial_port *port, u8 *gpio)
 {
        int ret;
 
-       dbg("%s - port %d", __func__, port->number);
+       dev_dbg(&port->dev, "%s - port %d", __func__, port->port_number);
 
        ret = cp210x_ctlmsg(port, 0xff, USB_DIR_IN|USB_TYPE_VENDOR,
                        0x00c2, 0, gpio, 1);
 
-       dbg("%s - gpio = 0x%.2x (%d)", __func__, *gpio, ret);
+       dev_dbg(&port->dev, "%s - gpio = 0x%.2x (%d)", __func__, *gpio, ret);
 
        return (ret == 1) ? 0 : -1;
 }
@@ -536,7 +573,7 @@ static int cp210x_portconfset(struct usb_serial_port *port,
        struct cp210x_port_config lconfig;
        int ret;
 
-       dbg("%s", __func__);
+       dev_dbg(&port->dev, "%s", __func__);
 
        memcpy(&lconfig, config, sizeof(lconfig));
 
@@ -564,7 +601,7 @@ static int cp210x_portconfget(struct usb_serial_port *port,
 {
        int ret;
 
-       dbg("%s", __func__);
+       dev_dbg(&port->dev, "%s", __func__);
 
        ret = cp210x_ctlmsg(port, 0xff, USB_DIR_IN|USB_TYPE_VENDOR,
                        0x370c, 0, config, sizeof(struct cp210x_port_config));
@@ -601,12 +638,12 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
                unsigned int *data, int size)
 {
        struct usb_serial *serial = port->serial;
-       struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+       struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
        __le32 *buf;
        int result, i, length;
 
        /* Number of integers required to contain the array */
-       length = (((size - 1) | 3) + 1)/4;
+       length = (((size - 1) | 3) + 1) / 4;
 
        buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
        if (!buf) {
@@ -616,8 +653,8 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
 
        /* Issue the request, attempting to read 'size' bytes */
        result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-                               request, REQTYPE_DEVICE_TO_HOST, 0x0000,
-                               port_priv->bInterfaceNumber, buf, size,
+                               request, REQTYPE_INTERFACE_TO_HOST, 0x0000,
+                               spriv->bInterfaceNumber, buf, size,
                                USB_CTRL_GET_TIMEOUT);
 
        /* Convert data into an array of integers */
@@ -627,10 +664,12 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
        kfree(buf);
 
        if (result != size) {
-               dbg("%s - Unable to send config request, "
-                               "request=0x%x size=%d result=%d\n",
-                               __func__, request, size, result);
-               return -EPROTO;
+               dev_dbg(&port->dev, "%s - Unable to send config request, request=0x%x size=%d result=%d\n",
+                       __func__, request, size, result);
+               if (result > 0)
+                       result = -EPROTO;
+
+               return result;
        }
 
        return 0;
@@ -646,17 +685,16 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
                unsigned int *data, int size)
 {
        struct usb_serial *serial = port->serial;
-       struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+       struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
        __le32 *buf;
        int result, i, length;
 
        /* Number of integers required to contain the array */
-       length = (((size - 1) | 3) + 1)/4;
+       length = (((size - 1) | 3) + 1) / 4;
 
        buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
        if (!buf) {
-               dev_err(&port->dev, "%s - out of memory.\n",
-                               __func__);
+               dev_err(&port->dev, "%s - out of memory.\n", __func__);
                return -ENOMEM;
        }
 
@@ -667,24 +705,26 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
        if (size > 2) {
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0),
-                               request, REQTYPE_HOST_TO_DEVICE, 0x0000,
-                               port_priv->bInterfaceNumber, buf, size,
+                               request, REQTYPE_HOST_TO_INTERFACE, 0x0000,
+                               spriv->bInterfaceNumber, buf, size,
                                USB_CTRL_SET_TIMEOUT);
        } else {
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0),
-                               request, REQTYPE_HOST_TO_DEVICE, data[0],
-                               port_priv->bInterfaceNumber, NULL, 0,
+                               request, REQTYPE_HOST_TO_INTERFACE, data[0],
+                               spriv->bInterfaceNumber, NULL, 0,
                                USB_CTRL_SET_TIMEOUT);
        }
 
        kfree(buf);
 
        if ((size > 2 && result != size) || result < 0) {
-               dbg("%s - Unable to send request, "
-                               "request=0x%x size=%d result=%d\n",
-                               __func__, request, size, result);
-               return -EPROTO;
+               dev_dbg(&port->dev, "%s - Unable to send request, request=0x%x size=%d result=%d\n",
+                       __func__, request, size, result);
+               if (result > 0)
+                       result = -EPROTO;
+
+               return result;
        }
 
        return 0;
@@ -705,7 +745,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,
  * cp210x_quantise_baudrate
  * Quantises the baud rate as per AN205 Table 1
  */
-static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
+static unsigned int cp210x_quantise_baudrate(unsigned int baud)
+{
        if (baud <= 300)
                baud = 300;
        else if (baud <= 600)      baud = 600;
@@ -744,12 +785,13 @@ static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
 
 static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
-       dbg("%s - port %d", __func__, port->number);
+       int result;
 
-       if (cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_ENABLE)) {
-               dev_err(&port->dev, "%s - Unable to enable UART\n",
-                               __func__);
-               return -EPROTO;
+       result = cp210x_set_config_single(port, CP210X_IFC_ENABLE,
+                                                               UART_ENABLE);
+       if (result) {
+               dev_err(&port->dev, "%s - Unable to enable UART\n", __func__);
+               return result;
        }
 
        /* Configure the termios structure */
@@ -764,25 +806,30 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 static void cp210x_close(struct usb_serial_port *port)
 {
-       dbg("%s - port %d", __func__, port->number);
-
        usb_serial_generic_close(port);
-
-       mutex_lock(&port->serial->disc_mutex);
-       if (!port->serial->disconnected)
-               cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
-       mutex_unlock(&port->serial->disc_mutex);
+       cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
 }
 
-static int cp210x_ioctl(struct tty_struct *tty,
-               unsigned int cmd, unsigned long arg)
+static int cp210x_ioctl(struct tty_struct *tty, unsigned int cmd,
+               unsigned long arg)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+       dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x", __func__,
+                       port->port_number, cmd);
 
        switch (cmd) {
 
+       case TIOCMGET:
+       {
+               int result = cp210x_tiocmget(tty);
+               if (copy_to_user((int __user *)&arg, &result, sizeof(int)))
+                       return -EFAULT;
+               return 0;
+       }
+       break;
+
+       case TIOCMSET:
        case TIOCMBIS:
        case TIOCMBIC:
        {
@@ -791,6 +838,7 @@ static int cp210x_ioctl(struct tty_struct *tty,
                if (copy_from_user(&val, (int __user *)&arg, sizeof(int)))
                        return -EFAULT;
 
+               /* this looks wrong: TIOCMSET isn't going to work right */
                if (cp210x_tiocmset(tty, (cmd == TIOCMBIC) ? 0 : val,
                                        (cmd == TIOCMBIC) ? val : 0))
                        return -EFAULT;
@@ -910,7 +958,7 @@ static int cp210x_ioctl(struct tty_struct *tty,
        break;
 
        default:
-       dbg("%s not supported = 0x%04x", __func__, cmd);
+       dev_dbg(&port->dev, "%s not supported = 0x%04x", __func__, cmd);
        break;
        }
 
@@ -930,11 +978,9 @@ static void cp210x_get_termios(struct tty_struct *tty,
 
        if (tty) {
                cp210x_get_termios_port(tty->driver_data,
-                       &tty->termios->c_cflag, &baud);
+                       &tty->termios.c_cflag, &baud);
                tty_encode_baud_rate(tty, baud, baud);
-       }
-
-       else {
+       } else {
                unsigned int cflag;
                cflag = 0;
                cp210x_get_termios_port(port, &cflag, &baud);
@@ -948,15 +994,14 @@ static void cp210x_get_termios(struct tty_struct *tty,
 static void cp210x_get_termios_port(struct usb_serial_port *port,
        unsigned int *cflagp, unsigned int *baudp)
 {
+       struct device *dev = &port->dev;
        unsigned int cflag, modem_ctl[4];
        unsigned int baud;
        unsigned int bits;
 
-       dbg("%s - port %d", __func__, port->number);
-
        cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);
 
-       dbg("%s - baud rate = %d", __func__, baud);
+       dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud);
        *baudp = baud;
 
        cflag = *cflagp;
@@ -965,31 +1010,30 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
        cflag &= ~CSIZE;
        switch (bits & BITS_DATA_MASK) {
        case BITS_DATA_5:
-               dbg("%s - data bits = 5", __func__);
+               dev_dbg(dev, "%s - data bits = 5\n", __func__);
                cflag |= CS5;
                break;
        case BITS_DATA_6:
-               dbg("%s - data bits = 6", __func__);
+               dev_dbg(dev, "%s - data bits = 6\n", __func__);
                cflag |= CS6;
                break;
        case BITS_DATA_7:
-               dbg("%s - data bits = 7", __func__);
+               dev_dbg(dev, "%s - data bits = 7\n", __func__);
                cflag |= CS7;
                break;
        case BITS_DATA_8:
-               dbg("%s - data bits = 8", __func__);
+               dev_dbg(dev, "%s - data bits = 8\n", __func__);
                cflag |= CS8;
                break;
        case BITS_DATA_9:
-               dbg("%s - data bits = 9 (not supported, using 8 data bits)",
-                                                               __func__);
+               dev_dbg(dev, "%s - data bits = 9 (not supported, using 8 data bits)\n", __func__);
                cflag |= CS8;
                bits &= ~BITS_DATA_MASK;
                bits |= BITS_DATA_8;
                cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
                break;
        default:
-               dbg("%s - Unknown number of data bits, using 8", __func__);
+               dev_dbg(dev, "%s - Unknown number of data bits, using 8\n", __func__);
                cflag |= CS8;
                bits &= ~BITS_DATA_MASK;
                bits |= BITS_DATA_8;
@@ -999,34 +1043,29 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
 
        switch (bits & BITS_PARITY_MASK) {
        case BITS_PARITY_NONE:
-               dbg("%s - parity = NONE", __func__);
+               dev_dbg(dev, "%s - parity = NONE\n", __func__);
                cflag &= ~PARENB;
                break;
        case BITS_PARITY_ODD:
-               dbg("%s - parity = ODD", __func__);
+               dev_dbg(dev, "%s - parity = ODD\n", __func__);
                cflag |= (PARENB|PARODD);
                break;
        case BITS_PARITY_EVEN:
-               dbg("%s - parity = EVEN", __func__);
+               dev_dbg(dev, "%s - parity = EVEN\n", __func__);
                cflag &= ~PARODD;
                cflag |= PARENB;
                break;
        case BITS_PARITY_MARK:
-               dbg("%s - parity = MARK (not supported, disabling parity)",
-                               __func__);
-               cflag &= ~PARENB;
-               bits &= ~BITS_PARITY_MASK;
-               cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
+               dev_dbg(dev, "%s - parity = MARK\n", __func__);
+               cflag |= (PARENB|PARODD|CMSPAR);
                break;
        case BITS_PARITY_SPACE:
-               dbg("%s - parity = SPACE (not supported, disabling parity)",
-                               __func__);
-               cflag &= ~PARENB;
-               bits &= ~BITS_PARITY_MASK;
-               cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
+               dev_dbg(dev, "%s - parity = SPACE\n", __func__);
+               cflag &= ~PARODD;
+               cflag |= (PARENB|CMSPAR);
                break;
        default:
-               dbg("%s - Unknown parity mode, disabling parity", __func__);
+               dev_dbg(dev, "%s - Unknown parity mode, disabling parity\n", __func__);
                cflag &= ~PARENB;
                bits &= ~BITS_PARITY_MASK;
                cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
@@ -1036,21 +1075,19 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
        cflag &= ~CSTOPB;
        switch (bits & BITS_STOP_MASK) {
        case BITS_STOP_1:
-               dbg("%s - stop bits = 1", __func__);
+               dev_dbg(dev, "%s - stop bits = 1\n", __func__);
                break;
        case BITS_STOP_1_5:
-               dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)",
-                                                               __func__);
+               dev_dbg(dev, "%s - stop bits = 1.5 (not supported, using 1 stop bit)\n", __func__);
                bits &= ~BITS_STOP_MASK;
                cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
                break;
        case BITS_STOP_2:
-               dbg("%s - stop bits = 2", __func__);
+               dev_dbg(dev, "%s - stop bits = 2\n", __func__);
                cflag |= CSTOPB;
                break;
        default:
-               dbg("%s - Unknown number of stop bits, using 1 stop bit",
-                                                               __func__);
+               dev_dbg(dev, "%s - Unknown number of stop bits, using 1 stop bit\n", __func__);
                bits &= ~BITS_STOP_MASK;
                cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2);
                break;
@@ -1058,10 +1095,10 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
 
        cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16);
        if (modem_ctl[0] & 0x0008) {
-               dbg("%s - flow control = CRTSCTS", __func__);
+               dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
                cflag |= CRTSCTS;
        } else {
-               dbg("%s - flow control = NONE", __func__);
+               dev_dbg(dev, "%s - flow control = NONE\n", __func__);
                cflag &= ~CRTSCTS;
        }
 
@@ -1099,7 +1136,7 @@ static void cp210x_change_speed(struct tty_struct *tty,
 {
        u32 baud;
 
-       baud = tty->termios->c_ospeed;
+       baud = tty->termios.c_ospeed;
 
        /* This maps the requested rate to a rate valid on cp2102 or cp2103,
         * or to an arbitrary rate in [1M,2M].
@@ -1108,7 +1145,7 @@ static void cp210x_change_speed(struct tty_struct *tty,
         */
        baud = cp210x_quantise_baudrate(baud);
 
-       dbg("%s - setting baud rate to %u", __func__, baud);
+       dev_dbg(&port->dev, "%s - setting baud rate to %u\n", __func__, baud);
        if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud,
                                                        sizeof(baud))) {
                dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);
@@ -1124,20 +1161,15 @@ static void cp210x_change_speed(struct tty_struct *tty,
 static void cp210x_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios)
 {
+       struct device *dev = &port->dev;
        unsigned int cflag, old_cflag;
        unsigned int bits;
        unsigned int modem_ctl[4];
 
-       dbg("%s - port %d", __func__, port->number);
-
-       if (!tty)
-               return;
-
-       tty->termios->c_cflag &= ~CMSPAR;
-       cflag = tty->termios->c_cflag;
+       cflag = tty->termios.c_cflag;
        old_cflag = old_termios->c_cflag;
 
-       if (tty->termios->c_ospeed != old_termios->c_ospeed)
+       if (tty->termios.c_ospeed != old_termios->c_ospeed)
                cp210x_change_speed(tty, port, old_termios);
 
        /* If the number of data bits is to be updated */
@@ -1147,51 +1179,58 @@ static void cp210x_set_termios(struct tty_struct *tty,
                switch (cflag & CSIZE) {
                case CS5:
                        bits |= BITS_DATA_5;
-                       dbg("%s - data bits = 5", __func__);
+                       dev_dbg(dev, "%s - data bits = 5\n", __func__);
                        break;
                case CS6:
                        bits |= BITS_DATA_6;
-                       dbg("%s - data bits = 6", __func__);
+                       dev_dbg(dev, "%s - data bits = 6\n", __func__);
                        break;
                case CS7:
                        bits |= BITS_DATA_7;
-                       dbg("%s - data bits = 7", __func__);
+                       dev_dbg(dev, "%s - data bits = 7\n", __func__);
                        break;
                case CS8:
                        bits |= BITS_DATA_8;
-                       dbg("%s - data bits = 8", __func__);
+                       dev_dbg(dev, "%s - data bits = 8\n", __func__);
                        break;
                /*case CS9:
                        bits |= BITS_DATA_9;
-                       dbg("%s - data bits = 9", __func__);
+                       dev_dbg(dev, "%s - data bits = 9\n", __func__);
                        break;*/
                default:
-                       dbg("cp210x driver does not "
-                                       "support the number of bits requested,"
-                                       " using 8 bit mode\n");
-                               bits |= BITS_DATA_8;
-                               break;
+                       dev_dbg(dev, "cp210x driver does not support the number of bits requested, using 8 bit mode\n");
+                       bits |= BITS_DATA_8;
+                       break;
                }
                if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
-                       dbg("Number of data bits requested "
-                                       "not supported by device\n");
+                       dev_dbg(dev, "Number of data bits requested not supported by device\n");
        }
 
-       if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) {
+       if ((cflag     & (PARENB|PARODD|CMSPAR)) !=
+           (old_cflag & (PARENB|PARODD|CMSPAR))) {
                cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2);
                bits &= ~BITS_PARITY_MASK;
                if (cflag & PARENB) {
-                       if (cflag & PARODD) {
-                               bits |= BITS_PARITY_ODD;
-                               dbg("%s - parity = ODD", __func__);
+                       if (cflag & CMSPAR) {
+                               if (cflag & PARODD) {
+                                       bits |= BITS_PARITY_MARK;
+                                       dev_dbg(dev, "%s - parity = MARK\n", __func__);
+                               } else {
+                                       bits |= BITS_PARITY_SPACE;
+                                       dev_dbg(dev, "%s - parity = SPACE\n", __func__);
+                               }
                        } else {
-                               bits |= BITS_PARITY_EVEN;
-                               dbg("%s - parity = EVEN", __func__);
+                               if (cflag & PARODD) {
+                                       bits |= BITS_PARITY_ODD;
+                                       dev_dbg(dev, "%s - parity = ODD\n", __func__);
+                               } else {
+                                       bits |= BITS_PARITY_EVEN;
+                                       dev_dbg(dev, "%s - parity = EVEN\n", __func__);
+                               }
                        }
                }
                if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
-                       dbg("Parity mode not supported "
-                                       "by device\n");
+                       dev_dbg(dev, "Parity mode not supported by device\n");
        }
 
        if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
@@ -1199,43 +1238,42 @@ static void cp210x_set_termios(struct tty_struct *tty,
                bits &= ~BITS_STOP_MASK;
                if (cflag & CSTOPB) {
                        bits |= BITS_STOP_2;
-                       dbg("%s - stop bits = 2", __func__);
+                       dev_dbg(dev, "%s - stop bits = 2\n", __func__);
                } else {
                        bits |= BITS_STOP_1;
-                       dbg("%s - stop bits = 1", __func__);
+                       dev_dbg(dev, "%s - stop bits = 1\n", __func__);
                }
                if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
-                       dbg("Number of stop bits requested "
-                                       "not supported by device\n");
+                       dev_dbg(dev, "Number of stop bits requested not supported by device\n");
        }
 
        if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
                cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16);
-               dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
-                               __func__, modem_ctl[0], modem_ctl[1],
-                               modem_ctl[2], modem_ctl[3]);
+               dev_dbg(dev, "%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x\n",
+                       __func__, modem_ctl[0], modem_ctl[1],
+                       modem_ctl[2], modem_ctl[3]);
 
                if (cflag & CRTSCTS) {
                        modem_ctl[0] &= ~0x7B;
                        modem_ctl[0] |= 0x09;
                        modem_ctl[1] = 0x80;
-                       dbg("%s - flow control = CRTSCTS", __func__);
+                       dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
                } else {
                        modem_ctl[0] &= ~0x7B;
                        modem_ctl[0] |= 0x01;
                        modem_ctl[1] |= 0x40;
-                       dbg("%s - flow control = NONE", __func__);
+                       dev_dbg(dev, "%s - flow control = NONE\n", __func__);
                }
 
-               dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
-                               __func__, modem_ctl[0], modem_ctl[1],
-                               modem_ctl[2], modem_ctl[3]);
+               dev_dbg(dev, "%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x\n",
+                       __func__, modem_ctl[0], modem_ctl[1],
+                       modem_ctl[2], modem_ctl[3]);
                cp210x_set_config(port, CP210X_SET_FLOW, modem_ctl, 16);
        }
 
 }
 
-static int cp210x_tiocmset (struct tty_struct *tty,
+static int cp210x_tiocmset(struct tty_struct *tty,
                unsigned int set, unsigned int clear)
 {
        struct usb_serial_port *port = tty->driver_data;
@@ -1247,8 +1285,6 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port,
 {
        unsigned int control = 0;
 
-       dbg("%s - port %d", __func__, port->number);
-
        if (set & TIOCM_RTS) {
                control |= CONTROL_RTS;
                control |= CONTROL_WRITE_RTS;
@@ -1266,7 +1302,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port,
                control |= CONTROL_WRITE_DTR;
        }
 
-       dbg("%s - control = 0x%.4x", __func__, control);
+       dev_dbg(&port->dev, "%s - control = 0x%.4x\n", __func__, control);
 
        return cp210x_set_config(port, CP210X_SET_MHS, &control, 2);
 }
@@ -1279,14 +1315,12 @@ static void cp210x_dtr_rts(struct usb_serial_port *p, int on)
                cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS);
 }
 
-static int cp210x_tiocmget (struct tty_struct *tty)
+static int cp210x_tiocmget(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        unsigned int control;
        int result;
 
-       dbg("%s - port %d", __func__, port->number);
-
        cp210x_get_config(port, CP210X_GET_MDMSTS, &control, 1);
 
        result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
@@ -1296,94 +1330,55 @@ static int cp210x_tiocmget (struct tty_struct *tty)
                |((control & CONTROL_RING)? TIOCM_RI  : 0)
                |((control & CONTROL_DCD) ? TIOCM_CD  : 0);
 
-       dbg("%s - control = 0x%.2x", __func__, control);
+       dev_dbg(&port->dev, "%s - control = 0x%.2x\n", __func__, control);
 
        return result;
 }
 
-static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
+static void cp210x_break_ctl(struct tty_struct *tty, int break_state)
 {
        struct usb_serial_port *port = tty->driver_data;
        unsigned int state;
 
-       dbg("%s - port %d", __func__, port->number);
        if (break_state == 0)
                state = BREAK_OFF;
        else
                state = BREAK_ON;
-       dbg("%s - turning break %s", __func__,
-                       state == BREAK_OFF ? "off" : "on");
+       dev_dbg(&port->dev, "%s - turning break %s\n", __func__,
+               state == BREAK_OFF ? "off" : "on");
        cp210x_set_config(port, CP210X_SET_BREAK, &state, 2);
 }
 
 static int cp210x_startup(struct usb_serial *serial)
 {
-       struct cp210x_port_private *port_priv;
-       int i;
+       struct usb_host_interface *cur_altsetting;
+       struct cp210x_serial_private *spriv;
 
        /* cp210x buffers behave strangely unless device is reset */
        usb_reset_device(serial->dev);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
-               if (!port_priv)
-                       return -ENOMEM;
+       spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+       if (!spriv)
+               return -ENOMEM;
 
-               memset(port_priv, 0x00, sizeof(*port_priv));
-               port_priv->bInterfaceNumber =
-                   serial->interface->cur_altsetting->desc.bInterfaceNumber;
+       cur_altsetting = serial->interface->cur_altsetting;
+       spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber;
 
-               usb_set_serial_port_data(serial->port[i], port_priv);
-       }
+       usb_set_serial_data(serial, spriv);
 
        return 0;
 }
 
 static void cp210x_release(struct usb_serial *serial)
 {
-       struct cp210x_port_private *port_priv;
-       int i;
+       struct cp210x_serial_private *spriv;
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(port_priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
+       spriv = usb_get_serial_data(serial);
+       kfree(spriv);
 }
 
-static int __init cp210x_init(void)
-{
-       int retval;
-
-       retval = usb_serial_register(&cp210x_device);
-       if (retval)
-               return retval; /* Failed to register */
-
-       retval = usb_register(&cp210x_driver);
-       if (retval) {
-               /* Failed to register */
-               usb_serial_deregister(&cp210x_device);
-               return retval;
-       }
-
-       /* Success */
-       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-              DRIVER_DESC "\n");
-       return 0;
-}
-
-static void __exit cp210x_exit(void)
-{
-       usb_deregister(&cp210x_driver);
-       usb_serial_deregister(&cp210x_device);
-}
-
-module_init(cp210x_init);
-module_exit(cp210x_exit);
+module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable verbose debugging messages");