Refactor and use the usb-serial infrastructure for line-control
handling.

This driver has been implemented based on sniffed traffic. A closer look
at the requests sent during open and close reveals that these request
appear to be standard CDC requests. If this is the case, then the
control requests lack the interface argument.

This patch will also make sure that the control lines are lowered at
close (when HUPCL is set), something which could affect some modem
reconnection issues that have been reported.

Signed-off-by: Johan Hovold <jo...@kernel.org>
---
 drivers/usb/serial/zte_ev.c | 90 +++++++++++++--------------------------------
 1 file changed, 26 insertions(+), 64 deletions(-)

diff --git a/drivers/usb/serial/zte_ev.c b/drivers/usb/serial/zte_ev.c
index e40ab739c4a6..927c0d074e40 100644
--- a/drivers/usb/serial/zte_ev.c
+++ b/drivers/usb/serial/zte_ev.c
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/usb/cdc.h>
 #include <linux/usb/serial.h>
 #include <linux/uaccess.h>
 
@@ -31,6 +32,30 @@ static void debug_data(struct device *dev, const char 
*function, int len,
                        len, len, data);
 }
 
+void zte_ev_usb_serial_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct usb_serial *serial = port->serial;
+       struct usb_interface_descriptor *desc =
+                               &serial->interface->cur_altsetting->desc;
+       unsigned int val;
+       int res;
+
+       if (on)
+               val = 0x03;
+       else
+               val = 0;
+
+       res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                               USB_CDC_REQ_SET_CONTROL_LINE_STATE,
+                               USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                               val, desc->bInterfaceNumber,
+                               NULL, 0, USB_CTRL_GET_TIMEOUT);
+       if (res) {
+               dev_err(&port->dev, "%s - failed to set control lines: %d\n",
+                               __func__, res);
+       }
+};
+
 static int zte_ev_usb_serial_open(struct tty_struct *tty,
                                  struct usb_serial_port *port)
 {
@@ -44,15 +69,6 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
        if (!buf)
                return -ENOMEM;
 
-       /* send 1st ctl cmd(CTL    21 22 01 00  00 00 00 00) */
-       len = 0;
-       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                0x22, 0x21,
-                                0x0001, 0x0000, NULL, len,
-                                USB_CTRL_GET_TIMEOUT);
-       dev_dbg(dev, "result = %d\n", result);
-
-       /* send 2st cmd and receive data */
        /*
         * 16.0  CTL    a1 21 00 00  00 00 07 00   CLASS              25.1.0(5)
         * 16.0  DI     00 96 00 00  00 00 08
@@ -64,7 +80,6 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
                                 USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
-       /* send 3rd cmd */
        /*
         * 16.0 CTL    21 20 00 00  00 00 07 00    CLASS                30.1.0
         * 16.0 DO     80 25 00 00  00 00 08       .%.....              30.2.0
@@ -83,18 +98,6 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
                                 USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
-       /* send 4th cmd */
-       /*
-        * 16.0 CTL    21 22 03 00  00 00 00 00
-        */
-       len = 0;
-       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                0x22, 0x21,
-                                0x0003, 0x0000, NULL, len,
-                                USB_CTRL_GET_TIMEOUT);
-       dev_dbg(dev, "result = %d\n", result);
-
-       /* send 5th cmd */
        /*
         * 16.0  CTL    a1 21 00 00  00 00 07 00   CLASS               33.1.0
         * 16.0  DI     80 25 00 00  00 00 08
@@ -166,23 +169,6 @@ static void zte_ev_usb_serial_close(struct usb_serial_port 
*port)
        if (!buf)
                return;
 
-       /* send 1st ctl cmd(CTL    21 22 02 00  00 00 00 00) */
-       len = 0;
-       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                0x22, 0x21,
-                                0x0002, 0x0000, NULL, len,
-                                USB_CTRL_GET_TIMEOUT);
-       dev_dbg(dev, "result = %d\n", result);
-
-       /* send 2st ctl cmd(CTL    21 22 03 00  00 00 00 00 ) */
-       len = 0;
-       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                0x22, 0x21,
-                                0x0003, 0x0000, NULL, len,
-                                USB_CTRL_GET_TIMEOUT);
-       dev_dbg(dev, "result = %d\n", result);
-
-       /* send  3st cmd and recieve data */
        /*
         * 16.0  CTL    a1 21 00 00  00 00 07 00      CLASS         25.1.0(5)
         * 16.0  DI     00 08 07 00  00 00 08
@@ -194,7 +180,6 @@ static void zte_ev_usb_serial_close(struct usb_serial_port 
*port)
                                 USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
-       /* send 4th cmd */
        /*
         * 16.0 CTL    21 20 00 00  00 00 07 00      CLASS            30.1.0
         * 16.0  DO    00 c2 01 00  00 00 08         .%.....          30.2.0
@@ -213,18 +198,6 @@ static void zte_ev_usb_serial_close(struct usb_serial_port 
*port)
                                 USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
-       /* send 5th cmd */
-       /*
-        * 16.0 CTL    21 22 03 00  00 00 00 00
-        */
-       len = 0;
-       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                0x22, 0x21,
-                                0x0003, 0x0000, NULL, len,
-                                USB_CTRL_GET_TIMEOUT);
-       dev_dbg(dev, "result = %d\n", result);
-
-       /* send 6th cmd */
        /*
         * 16.0  CTL    a1 21 00 00  00 00 07 00        CLASS          33.1.0
         * 16.0  DI     00 c2 01 00  00 00 08
@@ -236,7 +209,6 @@ static void zte_ev_usb_serial_close(struct usb_serial_port 
*port)
                                 USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
-       /* send 7th cmd */
        /*
         * 16.0  CTL    21 20 00 00  00 00 07 00  CLASS               354.1.0
         * 16.0  DO     00 c2 01 00  00 00 08     .......             354.2.0
@@ -255,17 +227,6 @@ static void zte_ev_usb_serial_close(struct usb_serial_port 
*port)
                                 USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
-       /* send 8th cmd */
-       /*
-        * 16.0 CTL    21 22 03 00  00 00 00 00
-        */
-       len = 0;
-       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                0x22, 0x21,
-                                0x0003, 0x0000, NULL, len,
-                                USB_CTRL_GET_TIMEOUT);
-       dev_dbg(dev, "result = %d\n", result);
-
        kfree(buf);
 
        usb_serial_generic_close(port);
@@ -307,6 +268,7 @@ static struct usb_serial_driver zio_device = {
        .num_ports =            1,
        .open =                 zte_ev_usb_serial_open,
        .close =                zte_ev_usb_serial_close,
+       .dtr_rts =              zte_ev_usb_serial_dtr_rts,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
-- 
1.8.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to