xref: /linux/drivers/usb/serial/ark3116.c (revision 6e8331ac6973435b1e7604c30f2ad394035b46e1)
1 /*
2  * ark3116
3  * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547,
4  *   productid=0x0232) (used in a datacable called KQ-U8A)
5  *
6  * - based on code by krisfx -> thanks !!
7  *   (see http://www.linuxquestions.org/questions/showthread.php?p=2184457#post2184457)
8  *
9  *  - based on logs created by usbsnoopy
10  *
11  *  Author   : Simon Schulz [ark3116_driver<AT>auctionant.de]
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the
15  * Free Software Foundation; either version 2 of the License, or (at your
16  * option) any later version.
17  */
18 
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/tty.h>
22 #include <linux/module.h>
23 #include <linux/usb.h>
24 #include <linux/usb/serial.h>
25 
26 
27 static int debug;
28 
29 static struct usb_device_id id_table [] = {
30 	{ USB_DEVICE(0x6547, 0x0232) },
31 	{ },
32 };
33 MODULE_DEVICE_TABLE(usb, id_table);
34 
35 struct ark3116_private {
36 	spinlock_t lock;
37 	u8 termios_initialized;
38 };
39 
40 static inline void ARK3116_SND(struct usb_serial *serial, int seq,
41 			       __u8 request, __u8 requesttype,
42 			       __u16 value, __u16 index)
43 {
44 	int result;
45 	result = usb_control_msg(serial->dev,
46 				 usb_sndctrlpipe(serial->dev,0),
47 				 request, requesttype, value, index,
48 				 NULL,0x00, 1000);
49 	dbg("%03d > ok",seq);
50 }
51 
52 static inline void ARK3116_RCV(struct usb_serial *serial, int seq,
53 			       __u8 request, __u8 requesttype,
54 			       __u16 value, __u16 index, __u8 expected,
55 			       char *buf)
56 {
57 	int result;
58 	result = usb_control_msg(serial->dev,
59 			      usb_rcvctrlpipe(serial->dev,0),
60 			      request, requesttype, value, index,
61 			      buf, 0x0000001, 1000);
62 	if (result)
63 		dbg("%03d < %d bytes [0x%02X]",seq, result, buf[0]);
64 	else
65 		dbg("%03d < 0 bytes", seq);
66 }
67 
68 
69 static inline void ARK3116_RCV_QUIET(struct usb_serial *serial,
70 				     __u8 request, __u8 requesttype,
71 				     __u16 value, __u16 index, char *buf)
72 {
73 	usb_control_msg(serial->dev,
74 			usb_rcvctrlpipe(serial->dev,0),
75 			request, requesttype, value, index,
76 			buf, 0x0000001, 1000);
77 }
78 
79 
80 static int ark3116_attach(struct usb_serial *serial)
81 {
82 	char *buf;
83 	struct ark3116_private *priv;
84 	int i;
85 
86 	for (i = 0; i < serial->num_ports; ++i) {
87 		priv = kmalloc (sizeof (struct ark3116_private), GFP_KERNEL);
88 		if (!priv)
89 			goto cleanup;
90 		memset (priv, 0x00, sizeof (struct ark3116_private));
91 		spin_lock_init(&priv->lock);
92 
93 		usb_set_serial_port_data(serial->port[i], priv);
94 	}
95 
96 	buf = kmalloc(1, GFP_KERNEL);
97 	if (!buf) {
98 		dbg("error kmalloc -> out of mem ?");
99 		goto cleanup;
100 	}
101 
102 	/* 3 */
103 	ARK3116_SND(serial, 3,0xFE,0x40,0x0008,0x0002);
104 	ARK3116_SND(serial, 4,0xFE,0x40,0x0008,0x0001);
105 	ARK3116_SND(serial, 5,0xFE,0x40,0x0000,0x0008);
106 	ARK3116_SND(serial, 6,0xFE,0x40,0x0000,0x000B);
107 
108 	/* <-- seq7 */
109 	ARK3116_RCV(serial, 7,0xFE,0xC0,0x0000,0x0003, 0x00, buf);
110 	ARK3116_SND(serial, 8,0xFE,0x40,0x0080,0x0003);
111 	ARK3116_SND(serial, 9,0xFE,0x40,0x001A,0x0000);
112 	ARK3116_SND(serial,10,0xFE,0x40,0x0000,0x0001);
113 	ARK3116_SND(serial,11,0xFE,0x40,0x0000,0x0003);
114 
115 	/* <-- seq12 */
116 	ARK3116_RCV(serial,12,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
117 	ARK3116_SND(serial,13,0xFE,0x40,0x0000,0x0004);
118 
119 	/* 14 */
120 	ARK3116_RCV(serial,14,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
121 	ARK3116_SND(serial,15,0xFE,0x40,0x0000,0x0004);
122 
123 	/* 16 */
124 	ARK3116_RCV(serial,16,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
125 	/* --> seq17 */
126 	ARK3116_SND(serial,17,0xFE,0x40,0x0001,0x0004);
127 
128 	/* <-- seq18 */
129 	ARK3116_RCV(serial,18,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
130 
131 	/* --> seq19 */
132 	ARK3116_SND(serial,19,0xFE,0x40,0x0003,0x0004);
133 
134 
135 	/* <-- seq20 */
136 	/* seems like serial port status info (RTS, CTS,...) */
137 	/* returns modem control line status ?! */
138 	ARK3116_RCV(serial,20,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
139 
140 	/* set 9600 baud & do some init ?! */
141 	ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
142 	ARK3116_SND(serial,148,0xFE,0x40,0x0038,0x0000);
143 	ARK3116_SND(serial,149,0xFE,0x40,0x0001,0x0001);
144 	ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
145 	ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
146 	ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
147 	ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
148 	ARK3116_SND(serial,154,0xFE,0x40,0x0003,0x0003);
149 
150 	kfree(buf);
151 	return(0);
152 
153 cleanup:
154 	for (--i; i>=0; --i)
155 		usb_set_serial_port_data(serial->port[i], NULL);
156 	return -ENOMEM;
157 }
158 
159 static void ark3116_set_termios(struct usb_serial_port *port,
160 				struct termios *old_termios)
161 {
162 	struct usb_serial *serial = port->serial;
163 	struct ark3116_private *priv = usb_get_serial_port_data(port);
164 	unsigned int cflag = port->tty->termios->c_cflag;
165 	unsigned long flags;
166 	int baud;
167 	int ark3116_baud;
168 	char *buf;
169 	char config;
170 
171 	config = 0;
172 
173 	dbg("%s - port %d", __FUNCTION__, port->number);
174 
175 	if ((!port->tty) || (!port->tty->termios)) {
176 		dbg("%s - no tty structures", __FUNCTION__);
177 		return;
178 	}
179 
180 	spin_lock_irqsave(&priv->lock, flags);
181 	if (!priv->termios_initialized) {
182 		*(port->tty->termios) = tty_std_termios;
183 		port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
184 		priv->termios_initialized = 1;
185 	}
186 	spin_unlock_irqrestore(&priv->lock, flags);
187 
188 	cflag = port->tty->termios->c_cflag;
189 
190 	/* check that they really want us to change something: */
191 	if (old_termios) {
192 		if ((cflag == old_termios->c_cflag) &&
193 		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
194 		     RELEVANT_IFLAG(old_termios->c_iflag))) {
195 			dbg("%s - nothing to change...", __FUNCTION__);
196 			return;
197 		}
198 	}
199 
200 	buf = kmalloc(1, GFP_KERNEL);
201 	if (!buf) {
202 		dbg("error kmalloc");
203 		return;
204 	}
205 
206 	/* set data bit count (8/7/6/5) */
207 	if (cflag & CSIZE){
208 		switch (cflag & CSIZE){
209 		case CS5:
210 			config |= 0x00;
211 			dbg("setting CS5");
212 			break;
213 		case CS6:
214 			config |= 0x01;
215 			dbg("setting CS6");
216 			break;
217 		case CS7:
218 			config |= 0x02;
219 			dbg("setting CS7");
220 			break;
221 		default:
222 			err ("CSIZE was set but not CS5-CS8, using CS8!");
223 		case CS8:
224 			config |= 0x03;
225 			dbg("setting CS8");
226 			break;
227 		}
228 	}
229 
230 	/* set parity (NONE,EVEN,ODD) */
231 	if (cflag & PARENB){
232 		if (cflag & PARODD) {
233 			config |= 0x08;
234 			dbg("setting parity to ODD");
235 		} else {
236 			config |= 0x18;
237 			dbg("setting parity to EVEN");
238 		}
239 	} else {
240 		dbg("setting parity to NONE");
241 	}
242 
243 	/* SET STOPBIT (1/2) */
244 	if (cflag & CSTOPB) {
245 		config |= 0x04;
246 		dbg ("setting 2 stop bits");
247 	} else {
248 		dbg ("setting 1 stop bit");
249 	}
250 
251 
252 	/* set baudrate: */
253 	baud = 0;
254 	switch (cflag & CBAUD){
255 		case B0:
256 			err("can't set 0baud, using 9600 instead");
257 			break;
258 		case B75:	baud = 75;	break;
259 		case B150:	baud = 150;	break;
260 		case B300:	baud = 300;	break;
261 		case B600:	baud = 600;	break;
262 		case B1200:	baud = 1200;	break;
263 		case B1800:	baud = 1800;	break;
264 		case B2400:	baud = 2400;	break;
265 		case B4800:	baud = 4800;	break;
266 		case B9600:	baud = 9600;	break;
267 		case B19200:	baud = 19200;	break;
268 		case B38400:	baud = 38400;	break;
269 		case B57600:	baud = 57600;	break;
270 		case B115200:	baud = 115200;	break;
271 		case B230400:	baud = 230400;	break;
272 		case B460800:	baud = 460800;	break;
273 		default:
274 			dbg("does not support the baudrate requested (fix it)");
275 			break;
276 	}
277 
278 	/* set 9600 as default (if given baudrate is invalid for example) */
279 	if (baud == 0)
280 		baud = 9600;
281 
282 	/*
283 	 * found by try'n'error, be careful, maybe there are other options
284 	 * for multiplicator etc!
285 	 */
286 	if (baud == 460800)
287 		/* strange, for 460800 the formula is wrong
288 		 * (dont use round(), then 9600baud is wrong) */
289 		ark3116_baud = 7;
290 	else
291 		ark3116_baud = 3000000 / baud;
292 
293 	/* ? */
294 	ARK3116_RCV(serial,0,0xFE,0xC0,0x0000,0x0003, 0x03, buf);
295 	/* offset = buf[0]; */
296 	/* offset = 0x03; */
297 	/* dbg("using 0x%04X as target for 0x0003:",0x0080+offset); */
298 
299 
300 	/* set baudrate */
301 	dbg("setting baudrate to %d (->reg=%d)",baud,ark3116_baud);
302 	ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
303 	ARK3116_SND(serial,148,0xFE,0x40,(ark3116_baud & 0x00FF)   ,0x0000);
304 	ARK3116_SND(serial,149,0xFE,0x40,(ark3116_baud & 0xFF00)>>8,0x0001);
305 	ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
306 
307 	/* ? */
308 	ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
309 	ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
310 
311 	/* set data bit count, stop bit count & parity: */
312 	dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config);
313 	ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
314 	ARK3116_SND(serial,154,0xFE,0x40,config,0x0003);
315 
316 	if (cflag & CRTSCTS)
317 		dbg("CRTSCTS not supported by chipset ?!");
318 
319 	/* TEST ARK3116_SND(154,0xFE,0x40,0xFFFF, 0x0006); */
320 
321 	kfree(buf);
322 	return;
323 }
324 
325 static int ark3116_open(struct usb_serial_port *port, struct file *filp)
326 {
327 	struct termios tmp_termios;
328 	struct usb_serial *serial = port->serial;
329 	char *buf;
330 	int result = 0;
331 
332 	dbg("%s -  port %d", __FUNCTION__, port->number);
333 
334 	buf = kmalloc(1, GFP_KERNEL);
335 	if (!buf) {
336 		dbg("error kmalloc -> out of mem ?");
337 		return -ENOMEM;
338 	}
339 
340 	result = usb_serial_generic_open(port, filp);
341 	if (result)
342 		return result;
343 
344 	/* open */
345 	ARK3116_RCV(serial,111,0xFE,0xC0,0x0000,0x0003, 0x02, buf);
346 
347 	ARK3116_SND(serial,112,0xFE,0x40,0x0082,0x0003);
348 	ARK3116_SND(serial,113,0xFE,0x40,0x001A,0x0000);
349 	ARK3116_SND(serial,114,0xFE,0x40,0x0000,0x0001);
350 	ARK3116_SND(serial,115,0xFE,0x40,0x0002,0x0003);
351 
352 	ARK3116_RCV(serial,116,0xFE,0xC0,0x0000,0x0004, 0x03, buf);
353 	ARK3116_SND(serial,117,0xFE,0x40,0x0002,0x0004);
354 
355 	ARK3116_RCV(serial,118,0xFE,0xC0,0x0000,0x0004, 0x02, buf);
356 	ARK3116_SND(serial,119,0xFE,0x40,0x0000,0x0004);
357 
358 	ARK3116_RCV(serial,120,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
359 
360 	ARK3116_SND(serial,121,0xFE,0x40,0x0001,0x0004);
361 
362 	ARK3116_RCV(serial,122,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
363 
364 	ARK3116_SND(serial,123,0xFE,0x40,0x0003,0x0004);
365 
366 	/* returns different values (control lines ?!) */
367 	ARK3116_RCV(serial,124,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
368 
369 	/* initialise termios: */
370 	if (port->tty)
371 		ark3116_set_termios(port, &tmp_termios);
372 
373 	kfree(buf);
374 
375 	return result;
376 
377 }
378 
379 static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
380 			 unsigned int cmd, unsigned long arg)
381 {
382 	dbg("ioctl not supported yet...");
383 	return -ENOIOCTLCMD;
384 }
385 
386 static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
387 {
388 	struct usb_serial *serial = port->serial;
389 	char *buf;
390 	char temp;
391 
392 	/* seems like serial port status info (RTS, CTS,...) is stored
393 	 * in reg(?) 0x0006
394 	 * pcb connection point 11 = GND -> sets bit4 of response
395 	 * pcb connection point  7 = GND -> sets bit6 of response
396 	 */
397 
398 	buf = kmalloc(1, GFP_KERNEL);
399 	if (!buf) {
400 		dbg("error kmalloc");
401 		return -ENOMEM;
402 	}
403 
404 	/* read register: */
405 	ARK3116_RCV_QUIET(serial,0xFE,0xC0,0x0000,0x0006,buf);
406 	temp = buf[0];
407 	kfree(buf);
408 
409 	/* i do not really know if bit4=CTS and bit6=DSR... was just a
410 	 * quick guess !!
411 	 */
412 	return  (temp & (1<<4) ? TIOCM_CTS : 0) |
413 	        (temp & (1<<6) ? TIOCM_DSR : 0);
414 }
415 
416 static struct usb_driver ark3116_driver = {
417 	.name =		"ark3116",
418 	.probe =	usb_serial_probe,
419 	.disconnect =	usb_serial_disconnect,
420 	.id_table =	id_table,
421 };
422 
423 static struct usb_serial_driver ark3116_device = {
424 	.driver = {
425 		.owner =	THIS_MODULE,
426 		.name =		"ark3116",
427 	},
428 	.id_table =		id_table,
429 	.num_interrupt_in =	1,
430 	.num_bulk_in =		1,
431 	.num_bulk_out =		1,
432 	.num_ports =		1,
433 	.attach =		ark3116_attach,
434 	.set_termios =		ark3116_set_termios,
435 	.ioctl =		ark3116_ioctl,
436 	.tiocmget =		ark3116_tiocmget,
437 	.open =			ark3116_open,
438 };
439 
440 static int __init ark3116_init(void)
441 {
442 	int retval;
443 
444 	retval = usb_serial_register(&ark3116_device);
445 	if (retval)
446 		return retval;
447 	retval = usb_register(&ark3116_driver);
448 	if (retval)
449 		usb_serial_deregister(&ark3116_device);
450 	return retval;
451 }
452 
453 static void __exit ark3116_exit(void)
454 {
455 	usb_deregister(&ark3116_driver);
456 	usb_serial_deregister(&ark3116_device);
457 }
458 
459 module_init(ark3116_init);
460 module_exit(ark3116_exit);
461 MODULE_LICENSE("GPL");
462 
463 module_param(debug, bool, S_IRUGO | S_IWUSR);
464 MODULE_PARM_DESC(debug, "Debug enabled or not");
465 
466