• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ZTE_EV USB serial driver
3  *
4  * Copyright (C) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
5  * Copyright (C) 2012 Linux Foundation
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * This driver is based on code found in a ZTE_ENV patch that modified
12  * the usb-serial generic driver.  Comments were left in that I think
13  * show the commands used to talk to the device, but I am not sure.
14  */
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/tty.h>
18 #include <linux/slab.h>
19 #include <linux/module.h>
20 #include <linux/usb.h>
21 #include <linux/usb/serial.h>
22 #include <linux/uaccess.h>
23 
24 #define  MAX_SETUP_DATA_SIZE	32
25 
debug_data(struct device * dev,const char * function,int len,const unsigned char * data,int result)26 static void debug_data(struct device *dev, const char *function, int len,
27 		       const unsigned char *data, int result)
28 {
29 	dev_dbg(dev, "result = %d\n", result);
30 	if (result == len)
31 		dev_dbg(dev, "%s - length = %d, data = %*ph\n", function,
32 			len, len, data);
33 }
34 
zte_ev_usb_serial_open(struct tty_struct * tty,struct usb_serial_port * port)35 static int zte_ev_usb_serial_open(struct tty_struct *tty,
36 				  struct usb_serial_port *port)
37 {
38 	struct usb_device *udev = port->serial->dev;
39 	struct device *dev = &port->dev;
40 	int result = 0;
41 	int len;
42 	unsigned char *buf;
43 
44 	buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL);
45 	if (!buf)
46 		return -ENOMEM;
47 
48 	/* send 1st ctl cmd(CTL    21 22 01 00  00 00 00 00) */
49 	len = 0;
50 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
51 				 0x22, 0x21,
52 				 0x0001, 0x0000, NULL, len,
53 				 USB_CTRL_GET_TIMEOUT);
54 	dev_dbg(dev, "result = %d\n", result);
55 
56 	/* send  2st cmd and recieve data */
57 	/*
58 	 * 16.0  CTL    a1 21 00 00  00 00 07 00   CLASS              25.1.0(5)
59 	 * 16.0  DI     00 96 00 00  00 00 08
60 	 */
61 	len = 0x0007;
62 	result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
63 				 0x21, 0xa1,
64 				 0x0000, 0x0000, buf, len,
65 				 USB_CTRL_GET_TIMEOUT);
66 	debug_data(dev, __func__, len, buf, result);
67 
68 	/* send 3 cmd */
69 	/*
70 	 * 16.0 CTL    21 20 00 00  00 00 07 00    CLASS                30.1.0
71 	 * 16.0 DO     80 25 00 00  00 00 08       .%.....              30.2.0
72 	 */
73 	len = 0x0007;
74 	buf[0] = 0x80;
75 	buf[1] = 0x25;
76 	buf[2] = 0x00;
77 	buf[3] = 0x00;
78 	buf[4] = 0x00;
79 	buf[5] = 0x00;
80 	buf[6] = 0x08;
81 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
82 				 0x20, 0x21,
83 				 0x0000, 0x0000, buf, len,
84 				 USB_CTRL_GET_TIMEOUT);
85 	debug_data(dev, __func__, len, buf, result);
86 
87 	/* send 4 cmd */
88 	/*
89 	 * 16.0 CTL    21 22 03 00  00 00 00 00
90 	 */
91 	len = 0;
92 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
93 				 0x22, 0x21,
94 				 0x0003, 0x0000, NULL, len,
95 				 USB_CTRL_GET_TIMEOUT);
96 	dev_dbg(dev, "result = %d\n", result);
97 
98 	/* send 5 cmd */
99 	/*
100 	 * 16.0  CTL    a1 21 00 00  00 00 07 00   CLASS               33.1.0
101 	 * 16.0  DI     80 25 00 00  00 00 08
102 	 */
103 	len = 0x0007;
104 	result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
105 				 0x21, 0xa1,
106 				 0x0000, 0x0000, buf, len,
107 				 USB_CTRL_GET_TIMEOUT);
108 	debug_data(dev, __func__, len, buf, result);
109 
110 	/* send 6 cmd */
111 	/*
112 	 * 16.0  CTL    21 20 00 00  00 00 07 00    CLASS               34.1.0
113 	 * 16.0  DO     80 25 00 00  00 00 08
114 	 */
115 	len = 0x0007;
116 	buf[0] = 0x80;
117 	buf[1] = 0x25;
118 	buf[2] = 0x00;
119 	buf[3] = 0x00;
120 	buf[4] = 0x00;
121 	buf[5] = 0x00;
122 	buf[6] = 0x08;
123 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
124 				 0x20, 0x21,
125 				 0x0000, 0x0000, buf, len,
126 				 USB_CTRL_GET_TIMEOUT);
127 	debug_data(dev, __func__, len, buf, result);
128 	kfree(buf);
129 
130 	return usb_serial_generic_open(tty, port);
131 }
132 
133 /*
134  *       CTL    21 22 02 00  00 00 00 00         CLASS               338.1.0
135  *
136  * 16.1  DI     a1 20 00 00  00 00 02 00  02 00  . ........          340.1.0
137  * 16.0  CTL    21 22 03 00  00 00 00 00         CLASS               341.1.0
138  *
139  * 16.0  CTL    a1 21 00 00  00 00 07 00         CLASS               346.1.0(3)
140  * 16.0  DI     00 08 07 00  00 00 08            .......             346.2.0
141  *
142  * 16.0  CTL    21 20 00 00  00 00 07 00         CLASS               349.1.0
143  * 16.0  DO     00 c2 01 00  00 00 08            .......             349.2.0
144  *
145  * 16.0  CTL    21 22 03 00  00 00 00 00         CLASS               350.1.0(2)
146  *
147  * 16.0  CTL    a1 21 00 00  00 00 07 00         CLASS               352.1.0
148  * 16.0  DI     00 c2 01 00  00 00 08            .......             352.2.0
149  *
150  * 16.1  DI     a1 20 00 00  00 00 02 00  02 00  . ........          353.1.0
151  *
152  * 16.0  CTL    21 20 00 00  00 00 07 00         CLASS               354.1.0
153  * 16.0  DO     00 c2 01 00  00 00 08            .......             354.2.0
154  *
155  * 16.0  CTL    21 22 03 00  00 00 00 00
156 */
157 
zte_ev_usb_serial_close(struct usb_serial_port * port)158 static void zte_ev_usb_serial_close(struct usb_serial_port *port)
159 {
160 	struct usb_device *udev = port->serial->dev;
161 	struct device *dev = &port->dev;
162 	int result = 0;
163 	int len;
164 	unsigned char *buf;
165 
166 	buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL);
167 	if (!buf)
168 		return;
169 
170 	/* send 1st ctl cmd(CTL    21 22 02 00  00 00 00 00) */
171 	len = 0;
172 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
173 				 0x22, 0x21,
174 				 0x0002, 0x0000, NULL, len,
175 				 USB_CTRL_GET_TIMEOUT);
176 	dev_dbg(dev, "result = %d\n", result);
177 
178 	/* send 2st ctl cmd(CTL    21 22 03 00  00 00 00 00 ) */
179 	len = 0;
180 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
181 				 0x22, 0x21,
182 				 0x0003, 0x0000, NULL, len,
183 				 USB_CTRL_GET_TIMEOUT);
184 	dev_dbg(dev, "result = %d\n", result);
185 
186 	/* send  3st cmd and recieve data */
187 	/*
188 	 * 16.0  CTL    a1 21 00 00  00 00 07 00      CLASS         25.1.0(5)
189 	 * 16.0  DI     00 08 07 00  00 00 08
190 	 */
191 	len = 0x0007;
192 	result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
193 				 0x21, 0xa1,
194 				 0x0000, 0x0000, buf, len,
195 				 USB_CTRL_GET_TIMEOUT);
196 	debug_data(dev, __func__, len, buf, result);
197 
198 	/* send 4 cmd */
199 	/*
200 	 * 16.0 CTL    21 20 00 00  00 00 07 00      CLASS            30.1.0
201 	 * 16.0  DO    00 c2 01 00  00 00 08         .%.....          30.2.0
202 	 */
203 	len = 0x0007;
204 	buf[0] = 0x00;
205 	buf[1] = 0xc2;
206 	buf[2] = 0x01;
207 	buf[3] = 0x00;
208 	buf[4] = 0x00;
209 	buf[5] = 0x00;
210 	buf[6] = 0x08;
211 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
212 				 0x20, 0x21,
213 				 0x0000, 0x0000, buf, len,
214 				 USB_CTRL_GET_TIMEOUT);
215 	debug_data(dev, __func__, len, buf, result);
216 
217 	/* send 5 cmd */
218 	/*
219 	 * 16.0 CTL    21 22 03 00  00 00 00 00
220 	 */
221 	len = 0;
222 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
223 				 0x22, 0x21,
224 				 0x0003, 0x0000, NULL, len,
225 				 USB_CTRL_GET_TIMEOUT);
226 	dev_dbg(dev, "result = %d\n", result);
227 
228 	/* send 6 cmd */
229 	/*
230 	 * 16.0  CTL    a1 21 00 00  00 00 07 00        CLASS          33.1.0
231 	 * 16.0  DI     00 c2 01 00  00 00 08
232 	 */
233 	len = 0x0007;
234 	result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
235 				 0x21, 0xa1,
236 				 0x0000, 0x0000, buf, len,
237 				 USB_CTRL_GET_TIMEOUT);
238 	debug_data(dev, __func__, len, buf, result);
239 
240 	/* send 7 cmd */
241 	/*
242 	 * 16.0  CTL    21 20 00 00  00 00 07 00  CLASS               354.1.0
243 	 * 16.0  DO     00 c2 01 00  00 00 08     .......             354.2.0
244 	 */
245 	len = 0x0007;
246 	buf[0] = 0x00;
247 	buf[1] = 0xc2;
248 	buf[2] = 0x01;
249 	buf[3] = 0x00;
250 	buf[4] = 0x00;
251 	buf[5] = 0x00;
252 	buf[6] = 0x08;
253 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
254 				 0x20, 0x21,
255 				 0x0000, 0x0000, buf, len,
256 				 USB_CTRL_GET_TIMEOUT);
257 	debug_data(dev, __func__, len, buf, result);
258 
259 	/* send 8 cmd */
260 	/*
261 	 * 16.0 CTL    21 22 03 00  00 00 00 00
262 	 */
263 	len = 0;
264 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
265 				 0x22, 0x21,
266 				 0x0003, 0x0000, NULL, len,
267 				 USB_CTRL_GET_TIMEOUT);
268 	dev_dbg(dev, "result = %d\n", result);
269 
270 	kfree(buf);
271 
272 	usb_serial_generic_close(port);
273 }
274 
275 static const struct usb_device_id id_table[] = {
276 	/* AC8710, AC8710T */
277 	{ USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffff, 0xff, 0xff, 0xff) },
278 	 /* AC8700 */
279 	{ USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfffe, 0xff, 0xff, 0xff) },
280 	/* MG880 */
281 	{ USB_DEVICE(0x19d2, 0xfffd) },
282 	{ USB_DEVICE(0x19d2, 0xfffc) },
283 	{ USB_DEVICE(0x19d2, 0xfffb) },
284 	/* AC2726, AC8710_V3 */
285 	{ USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfff1, 0xff, 0xff, 0xff) },
286 	{ USB_DEVICE(0x19d2, 0xfff6) },
287 	{ USB_DEVICE(0x19d2, 0xfff7) },
288 	{ USB_DEVICE(0x19d2, 0xfff8) },
289 	{ USB_DEVICE(0x19d2, 0xfff9) },
290 	{ USB_DEVICE(0x19d2, 0xffee) },
291 	/* AC2716, MC2716 */
292 	{ USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffed, 0xff, 0xff, 0xff) },
293 	/* AD3812 */
294 	{ USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffeb, 0xff, 0xff, 0xff) },
295 	{ USB_DEVICE(0x19d2, 0xffec) },
296 	{ USB_DEVICE(0x05C6, 0x3197) },
297 	{ USB_DEVICE(0x05C6, 0x6000) },
298 	{ USB_DEVICE(0x05C6, 0x9008) },
299 	{ },
300 };
301 MODULE_DEVICE_TABLE(usb, id_table);
302 
303 static struct usb_serial_driver zio_device = {
304 	.driver = {
305 		.owner =	THIS_MODULE,
306 		.name =		"zte_ev",
307 	},
308 	.id_table =		id_table,
309 	.num_ports =		1,
310 	.open =			zte_ev_usb_serial_open,
311 	.close =		zte_ev_usb_serial_close,
312 };
313 
314 static struct usb_serial_driver * const serial_drivers[] = {
315 	&zio_device, NULL
316 };
317 
318 module_usb_serial_driver(serial_drivers, id_table);
319 MODULE_LICENSE("GPL v2");
320