Re: add ZTE EV_DO to a proper driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jul 26, 2012 at 05:51:59PM +0300, nirinA raseliarison wrote:
> hi Greg,
> 
> Le Thu, 26 Jul 2012 01:04:08 +0300, Greg KH <gregkh@xxxxxxxxxxxxxxxxxxx> a
> écrit:
> 
> >On Wed, Jul 25, 2012 at 12:51:34PM -0700, nirinA raseliarison wrote:
> >>hello there,
> >>i have an usb modem zte ev-do that i used with kernel from
> >>2.6.29 up to 3.5.
> >>since 3.5, i got the following message:
> >>
> >>    [77496.664090] usb 5-2: udev 10, busnum 5, minor = 521
> >>    [77496.664097] usb 5-2: New USB device found, idVendor=19d2,
> >>idProduct=ffff
> >>    [77496.664102] usb 5-2: New USB device strings: Mfr=1,
> >>Product=2, SerialNumber=0
> >>    [77496.664107] usb 5-2: Product: ZTE CDMA Tech
> >>    [77496.664112] usb 5-2: Manufacturer: ZTE, Incorporated
> >>    [77496.664226] usb 5-2: usb_probe_device
> >>    [77496.664232] usb 5-2: configuration #1 chosen from 1 choice
> >>    [77496.667119] usb 5-2: adding 5-2:1.0 (config #1, interface 0)
> >>    [77496.670161] usbserial_generic 5-2:1.0: usb_probe_interface
> >>    [77496.670169] usbserial_generic 5-2:1.0:
> >>usb_probe_interface - got id
> >>    [77496.670177] usbserial_generic 5-2:1.0: The "generic"
> >>usb-serial driver is only for testing and
> >>     one-off prototypes.
> >>    [77496.670182] usbserial_generic 5-2:1.0: Tell
> >>linux-usb@xxxxxxxxxxxxxxx to add your device to a
> >>    proper driver.
> >>    [77496.670186] usbserial_generic 5-2:1.0: generic converter detected
> >>    [77496.670276] usb 5-2: generic converter now attached to ttyUSB0
> >>
> >>i would be nice to have a driver for this device in the kernel.
> >>the device is shipped with sources to build its modules. if i understand
> >>correctly thet are released under GPL, so i attached them below.
> >>this is portion of Makefile i used:
> >>
> >>    obj-m := ztemt.o
> >>    ztemt-objs := usb-serial.o bus.o generic.o ezusb.o zte_ev.o
> >
> >Ick, that's not really the "proper" way to support this device, but I
> >can take the file below and write a real driver for it.  Can you test a
> >patch if I create it?
> 
> yes, of course, i can test it.

Very sorry for the delay, but I think I have a first cut at this.

Can you try the patch attached to this mail, it was made against the
3.6-rc2 kernel, but should apply cleanly to the 3.5 kernel and probably
older ones as well.

Can you enable this driver and let me know if it works properly for you
or not?

thanks,

greg k-h

>From d64205dd2aa4fe344230514afd3e8ac6377960f7 Mon Sep 17 00:00:00 2001
From: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 17 Aug 2012 16:59:51 -0700
Subject: [PATCH] USB: serial: add zte_ev.c driver

Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
 drivers/usb/serial/Kconfig  |    8 +
 drivers/usb/serial/Makefile |    1 
 drivers/usb/serial/zte_ev.c |  315 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 324 insertions(+)

--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -660,6 +660,14 @@ config USB_SERIAL_ZIO
 	  To compile this driver as a module, choose M here: the
 	  module will be called zio.
 
+config USB_SERIAL_ZTE
+	tristate "ZTE USB serial driver"
+	help
+	  Say Y here if you want to use a ZTE USB to serial device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called zte.
+
 config USB_SERIAL_SSU100
 	tristate "USB Quatech SSU-100 Single Port Serial Driver"
 	help
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -63,3 +63,4 @@ obj-$(CONFIG_USB_SERIAL_WHITEHEAT)		+= w
 obj-$(CONFIG_USB_SERIAL_XIRCOM)			+= keyspan_pda.o
 obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL)		+= vivopay-serial.o
 obj-$(CONFIG_USB_SERIAL_ZIO)			+= zio.o
+obj-$(CONFIG_USB_SERIAL_ZTE)			+= zte_ev.o
--- /dev/null
+++ b/drivers/usb/serial/zte_ev.c
@@ -0,0 +1,315 @@
+/*
+ * ZTE_EV USB serial driver
+ *
+ * Copyright (C) 2012 Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
+ * Copyright (C) 2012 Linux Foundation
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/uaccess.h>
+
+#define  MAX_SETUP_DATA_SIZE	32
+
+static int debug;
+
+static int zte_ev_usb_serial_open(struct tty_struct *tty,
+				  struct usb_serial_port *port)
+{
+	struct usb_device *udev = port->serial->dev;
+	struct device *dev = &port->dev;
+	int result = 0;
+	int len;
+	unsigned char *buf;
+
+	if (port->number != 0)
+		return -ENODEV;
+
+	buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL);
+	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,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+
+	/* send  2st cmd and recieve 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
+	 */
+	len = 0x0007;
+	result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0x21, 0xa1,
+				 0x0000, 0x0000, buf, len,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(&port->dev, "result = %d\n", result);
+	if (result == len)
+		usb_serial_debug_data(debug, &port->dev, __func__, len, buf);
+
+	/* send 3 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
+	 */
+	len = 0x0007;
+	buf[0] = 0x80;
+	buf[1] = 0x25;
+	buf[2] = 0x00;
+	buf[3] = 0x00;
+	buf[4] = 0x00;
+	buf[5] = 0x00;
+	buf[6] = 0x08;
+	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				 0x20, 0x21,
+				 0x0000, 0x0000, buf, len,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+	if (result == len)
+		usb_serial_debug_data(debug, dev, __func__, len, buf);
+
+	/* send 4 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,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+
+	/* send 5 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
+	 */
+	len = 0x0007;
+	result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0x21, 0xa1,
+				 0x0000, 0x0000, buf, len,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+	if (result == len)
+		usb_serial_debug_data(debug, dev, __func__, len, buf);
+
+	/* send 6 cmd */
+	/*
+	 * 16.0  CTL    21 20 00 00  00 00 07 00    CLASS               34.1.0
+	 * 16.0  DO     80 25 00 00  00 00 08
+	 */
+	len = 0x0007;
+	buf[0] = 0x80;
+	buf[1] = 0x25;
+	buf[2] = 0x00;
+	buf[3] = 0x00;
+	buf[4] = 0x00;
+	buf[5] = 0x00;
+	buf[6] = 0x08;
+	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				 0x20, 0x21,
+				 0x0000, 0x0000, buf, len,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+	if (result == len)
+		usb_serial_debug_data(debug, dev, __func__, len, buf);
+	kfree(buf);
+
+	return usb_serial_generic_open(tty, port);
+}
+
+/*
+ *       CTL    21 22 02 00  00 00 00 00         CLASS               338.1.0
+ *
+ * 16.1  DI     a1 20 00 00  00 00 02 00  02 00  . ........          340.1.0
+ * 16.0  CTL    21 22 03 00  00 00 00 00         CLASS               341.1.0
+ *
+ * 16.0  CTL    a1 21 00 00  00 00 07 00         CLASS               346.1.0(3)
+ * 16.0  DI     00 08 07 00  00 00 08            .......             346.2.0
+ *
+ * 16.0  CTL    21 20 00 00  00 00 07 00         CLASS               349.1.0
+ * 16.0  DO     00 c2 01 00  00 00 08            .......             349.2.0
+ *
+ * 16.0  CTL    21 22 03 00  00 00 00 00         CLASS               350.1.0(2)
+ *
+ * 16.0  CTL    a1 21 00 00  00 00 07 00         CLASS               352.1.0
+ * 16.0  DI     00 c2 01 00  00 00 08            .......             352.2.0
+ *
+ * 16.1  DI     a1 20 00 00  00 00 02 00  02 00  . ........          353.1.0
+ *
+ * 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
+ *
+ * 16.0  CTL    21 22 03 00  00 00 00 00
+*/
+
+static void zte_ev_usb_serial_close(struct usb_serial_port *port)
+{
+	struct usb_device *udev = port->serial->dev;
+	struct device *dev = &port->dev;
+	int result = 0;
+	int len;
+	unsigned char *buf;
+
+	if (port->number != 0)
+		return;
+
+	buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL);
+	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,
+				 HZ * 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,
+				 HZ * 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
+	 */
+	len = 0x0007;
+	result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0x21, 0xa1,
+				 0x0000, 0x0000, buf, len,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+	if (result == len)
+		usb_serial_debug_data(debug, dev, __func__, len, buf);
+
+	/* send 4 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
+	 */
+	len = 0x0007;
+	buf[0] = 0x00;
+	buf[1] = 0xc2;
+	buf[2] = 0x01;
+	buf[3] = 0x00;
+	buf[4] = 0x00;
+	buf[5] = 0x00;
+	buf[6] = 0x08;
+	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				 0x20, 0x21,
+				 0x0000, 0x0000, buf, len,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+	if (result == len)
+		usb_serial_debug_data(debug, dev, __func__, len, buf);
+
+	/* send 5 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,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+
+	/* send 6 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
+	 */
+	len = 0x0007;
+	result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0x21, 0xa1,
+				 0x0000, 0x0000, buf, len,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+	if (result == len)
+		usb_serial_debug_data(debug, dev, __func__, len, buf);
+
+	/* send 7 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
+	 */
+	len = 0x0007;
+	buf[0] = 0x00;
+	buf[1] = 0xc2;
+	buf[2] = 0x01;
+	buf[3] = 0x00;
+	buf[4] = 0x00;
+	buf[5] = 0x00;
+	buf[6] = 0x08;
+	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				 0x20, 0x21,
+				 0x0000, 0x0000, buf, len,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+	if (result == len)
+		usb_serial_debug_data(debug, dev, __func__, len, buf);
+
+	/* send 8 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,
+				 HZ * USB_CTRL_GET_TIMEOUT);
+	dev_dbg(dev, "result = %d\n", result);
+
+	kfree(buf);
+
+	usb_serial_generic_close(port);
+}
+
+static const struct usb_device_id id_table[] = {
+	{ USB_DEVICE(0x19d2, 0xffff) },	/* AC8700 */
+	{ USB_DEVICE(0x19d2, 0xfffe) },
+	{ USB_DEVICE(0x19d2, 0xfffd) }, /* MG880 */
+	{ USB_DEVICE(0x05C6, 0x3197) },
+	{ USB_DEVICE(0x05C6, 0x6000) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_serial_driver zio_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"zte_ev",
+	},
+	.id_table =		id_table,
+	.num_ports =		1,
+	.open =			zte_ev_usb_serial_open,
+	.close =		zte_ev_usb_serial_close,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+	&zio_device, NULL
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+MODULE_LICENSE("GPL v2");
+
+

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux