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