Linux Audio

Check our new training course

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