3 * Simon Schulz (ark3116_driver <at> auctionant.de)
6 * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547,
7 * productid=0x0232) (used in a datacable called KQ-U8A)
9 * - based on code by krisfx -> thanks !!
10 * (see http://www.linuxquestions.org/questions/showthread.php?p=2184457#post2184457)
12 * - based on logs created by usbsnoopy
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
20 #include <linux/kernel.h>
21 #include <linux/init.h>
22 #include <linux/tty.h>
23 #include <linux/module.h>
24 #include <linux/usb.h>
25 #include <linux/usb/serial.h>
26 #include <linux/serial.h>
27 #include <linux/uaccess.h>
32 static struct usb_device_id id_table
[] = {
33 { USB_DEVICE(0x6547, 0x0232) },
34 { USB_DEVICE(0x18ec, 0x3118) }, /* USB to IrDA adapter */
37 MODULE_DEVICE_TABLE(usb
, id_table
);
39 static int is_irda(struct usb_serial
*serial
)
41 struct usb_device
*dev
= serial
->dev
;
42 if (le16_to_cpu(dev
->descriptor
.idVendor
) == 0x18ec &&
43 le16_to_cpu(dev
->descriptor
.idProduct
) == 0x3118)
48 static inline void ARK3116_SND(struct usb_serial
*serial
, int seq
,
49 __u8 request
, __u8 requesttype
,
50 __u16 value
, __u16 index
)
53 result
= usb_control_msg(serial
->dev
,
54 usb_sndctrlpipe(serial
->dev
, 0),
55 request
, requesttype
, value
, index
,
57 dbg("%03d > ok", seq
);
60 static inline void ARK3116_RCV(struct usb_serial
*serial
, int seq
,
61 __u8 request
, __u8 requesttype
,
62 __u16 value
, __u16 index
, __u8 expected
,
66 result
= usb_control_msg(serial
->dev
,
67 usb_rcvctrlpipe(serial
->dev
, 0),
68 request
, requesttype
, value
, index
,
69 buf
, 0x0000001, 1000);
71 dbg("%03d < %d bytes [0x%02X]", seq
, result
,
72 ((unsigned char *)buf
)[0]);
74 dbg("%03d < 0 bytes", seq
);
77 static inline void ARK3116_RCV_QUIET(struct usb_serial
*serial
,
78 __u8 request
, __u8 requesttype
,
79 __u16 value
, __u16 index
, char *buf
)
81 usb_control_msg(serial
->dev
,
82 usb_rcvctrlpipe(serial
->dev
, 0),
83 request
, requesttype
, value
, index
,
84 buf
, 0x0000001, 1000);
87 static int ark3116_attach(struct usb_serial
*serial
)
91 buf
= kmalloc(1, GFP_KERNEL
);
93 dbg("error kmalloc -> out of mem?");
101 ARK3116_SND(serial
, 3, 0xFE, 0x40, 0x0008, 0x0002);
102 ARK3116_SND(serial
, 4, 0xFE, 0x40, 0x0008, 0x0001);
103 ARK3116_SND(serial
, 5, 0xFE, 0x40, 0x0000, 0x0008);
104 ARK3116_SND(serial
, 6, 0xFE, 0x40, is_irda(serial
) ? 0x0001 : 0x0000,
107 if (is_irda(serial
)) {
108 ARK3116_SND(serial
, 1001, 0xFE, 0x40, 0x0000, 0x000C);
109 ARK3116_SND(serial
, 1002, 0xFE, 0x40, 0x0041, 0x000D);
110 ARK3116_SND(serial
, 1003, 0xFE, 0x40, 0x0001, 0x000A);
114 ARK3116_RCV(serial
, 7, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf
);
115 ARK3116_SND(serial
, 8, 0xFE, 0x40, 0x0080, 0x0003);
116 ARK3116_SND(serial
, 9, 0xFE, 0x40, 0x001A, 0x0000);
117 ARK3116_SND(serial
, 10, 0xFE, 0x40, 0x0000, 0x0001);
118 ARK3116_SND(serial
, 11, 0xFE, 0x40, 0x0000, 0x0003);
121 ARK3116_RCV(serial
, 12, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf
);
122 ARK3116_SND(serial
, 13, 0xFE, 0x40, 0x0000, 0x0004);
125 ARK3116_RCV(serial
, 14, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf
);
126 ARK3116_SND(serial
, 15, 0xFE, 0x40, 0x0000, 0x0004);
129 ARK3116_RCV(serial
, 16, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf
);
131 ARK3116_SND(serial
, 17, 0xFE, 0x40, 0x0001, 0x0004);
134 ARK3116_RCV(serial
, 18, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf
);
137 ARK3116_SND(serial
, 19, 0xFE, 0x40, 0x0003, 0x0004);
140 /* seems like serial port status info (RTS, CTS, ...) */
141 /* returns modem control line status?! */
142 ARK3116_RCV(serial
, 20, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf
);
144 /* set 9600 baud & do some init?! */
145 ARK3116_SND(serial
, 147, 0xFE, 0x40, 0x0083, 0x0003);
146 ARK3116_SND(serial
, 148, 0xFE, 0x40, 0x0038, 0x0000);
147 ARK3116_SND(serial
, 149, 0xFE, 0x40, 0x0001, 0x0001);
149 ARK3116_SND(serial
, 1004, 0xFE, 0x40, 0x0000, 0x0009);
150 ARK3116_SND(serial
, 150, 0xFE, 0x40, 0x0003, 0x0003);
151 ARK3116_RCV(serial
, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf
);
152 ARK3116_SND(serial
, 152, 0xFE, 0x40, 0x0000, 0x0003);
153 ARK3116_RCV(serial
, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf
);
154 ARK3116_SND(serial
, 154, 0xFE, 0x40, 0x0003, 0x0003);
160 static void ark3116_init_termios(struct tty_struct
*tty
)
162 struct ktermios
*termios
= tty
->termios
;
163 *termios
= tty_std_termios
;
164 termios
->c_cflag
= B9600
| CS8
165 | CREAD
| HUPCL
| CLOCAL
;
166 termios
->c_ispeed
= 9600;
167 termios
->c_ospeed
= 9600;
170 static void ark3116_set_termios(struct tty_struct
*tty
,
171 struct usb_serial_port
*port
,
172 struct ktermios
*old_termios
)
174 struct usb_serial
*serial
= port
->serial
;
175 struct ktermios
*termios
= tty
->termios
;
176 unsigned int cflag
= termios
->c_cflag
;
184 dbg("%s - port %d", __func__
, port
->number
);
187 cflag
= termios
->c_cflag
;
188 termios
->c_cflag
&= ~(CMSPAR
|CRTSCTS
);
190 buf
= kmalloc(1, GFP_KERNEL
);
192 dbg("error kmalloc");
193 *termios
= *old_termios
;
197 /* set data bit count (8/7/6/5) */
199 switch (cflag
& CSIZE
) {
213 dbg("CSIZE was set but not CS5-CS8, using CS8!");
222 /* set parity (NONE/EVEN/ODD) */
223 if (cflag
& PARENB
) {
224 if (cflag
& PARODD
) {
226 dbg("setting parity to ODD");
229 dbg("setting parity to EVEN");
232 dbg("setting parity to NONE");
235 /* set stop bit (1/2) */
236 if (cflag
& CSTOPB
) {
238 dbg("setting 2 stop bits");
240 dbg("setting 1 stop bit");
244 baud
= tty_get_baud_rate(tty
);
262 /* Report the resulting rate back to the caller */
263 tty_encode_baud_rate(tty
, baud
, baud
);
265 /* set 9600 as default (if given baudrate is invalid for example) */
267 tty_encode_baud_rate(tty
, 9600, 9600);
273 * found by try'n'error, be careful, maybe there are other options
274 * for multiplicator etc! (3.5 for example)
277 /* strange, for 460800 the formula is wrong
278 * if using round() then 9600baud is wrong) */
281 ark3116_baud
= 3000000 / baud
;
284 ARK3116_RCV(serial
, 0, 0xFE, 0xC0, 0x0000, 0x0003, 0x03, buf
);
286 /* offset = buf[0]; */
288 /* dbg("using 0x%04X as target for 0x0003:", 0x0080 + offset); */
291 dbg("setting baudrate to %d (->reg=%d)", baud
, ark3116_baud
);
292 ARK3116_SND(serial
, 147, 0xFE, 0x40, 0x0083, 0x0003);
293 ARK3116_SND(serial
, 148, 0xFE, 0x40,
294 (ark3116_baud
& 0x00FF), 0x0000);
295 ARK3116_SND(serial
, 149, 0xFE, 0x40,
296 (ark3116_baud
& 0xFF00) >> 8, 0x0001);
297 ARK3116_SND(serial
, 150, 0xFE, 0x40, 0x0003, 0x0003);
300 ARK3116_RCV(serial
, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf
);
301 ARK3116_SND(serial
, 152, 0xFE, 0x40, 0x0000, 0x0003);
303 /* set data bit count, stop bit count & parity: */
304 dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config
);
305 ARK3116_RCV(serial
, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf
);
306 ARK3116_SND(serial
, 154, 0xFE, 0x40, config
, 0x0003);
309 dbg("CRTSCTS not supported by chipset?!");
311 /* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */
318 static int ark3116_open(struct tty_struct
*tty
, struct usb_serial_port
*port
)
320 struct ktermios tmp_termios
;
321 struct usb_serial
*serial
= port
->serial
;
325 dbg("%s - port %d", __func__
, port
->number
);
327 buf
= kmalloc(1, GFP_KERNEL
);
329 dbg("error kmalloc -> out of mem?");
333 result
= usb_serial_generic_open(tty
, port
);
338 ARK3116_RCV(serial
, 111, 0xFE, 0xC0, 0x0000, 0x0003, 0x02, buf
);
340 ARK3116_SND(serial
, 112, 0xFE, 0x40, 0x0082, 0x0003);
341 ARK3116_SND(serial
, 113, 0xFE, 0x40, 0x001A, 0x0000);
342 ARK3116_SND(serial
, 114, 0xFE, 0x40, 0x0000, 0x0001);
343 ARK3116_SND(serial
, 115, 0xFE, 0x40, 0x0002, 0x0003);
345 ARK3116_RCV(serial
, 116, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf
);
346 ARK3116_SND(serial
, 117, 0xFE, 0x40, 0x0002, 0x0004);
348 ARK3116_RCV(serial
, 118, 0xFE, 0xC0, 0x0000, 0x0004, 0x02, buf
);
349 ARK3116_SND(serial
, 119, 0xFE, 0x40, 0x0000, 0x0004);
351 ARK3116_RCV(serial
, 120, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf
);
353 ARK3116_SND(serial
, 121, 0xFE, 0x40, 0x0001, 0x0004);
355 ARK3116_RCV(serial
, 122, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf
);
357 ARK3116_SND(serial
, 123, 0xFE, 0x40, 0x0003, 0x0004);
359 /* returns different values (control lines?!) */
360 ARK3116_RCV(serial
, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf
);
362 /* initialise termios */
364 ark3116_set_termios(tty
, port
, &tmp_termios
);
372 static int ark3116_ioctl(struct tty_struct
*tty
, struct file
*file
,
373 unsigned int cmd
, unsigned long arg
)
375 struct usb_serial_port
*port
= tty
->driver_data
;
376 struct serial_struct serstruct
;
377 void __user
*user_arg
= (void __user
*)arg
;
381 /* XXX: Some of these values are probably wrong. */
382 memset(&serstruct
, 0, sizeof(serstruct
));
383 serstruct
.type
= PORT_16654
;
384 serstruct
.line
= port
->serial
->minor
;
385 serstruct
.port
= port
->number
;
386 serstruct
.custom_divisor
= 0;
387 serstruct
.baud_base
= 460800;
389 if (copy_to_user(user_arg
, &serstruct
, sizeof(serstruct
)))
394 if (copy_from_user(&serstruct
, user_arg
, sizeof(serstruct
)))
398 dbg("%s cmd 0x%04x not supported", __func__
, cmd
);
405 static int ark3116_tiocmget(struct tty_struct
*tty
, struct file
*file
)
407 struct usb_serial_port
*port
= tty
->driver_data
;
408 struct usb_serial
*serial
= port
->serial
;
412 /* seems like serial port status info (RTS, CTS, ...) is stored
414 * pcb connection point 11 = GND -> sets bit4 of response
415 * pcb connection point 7 = GND -> sets bit6 of response
418 buf
= kmalloc(1, GFP_KERNEL
);
420 dbg("error kmalloc");
425 ARK3116_RCV_QUIET(serial
, 0xFE, 0xC0, 0x0000, 0x0006, buf
);
429 /* i do not really know if bit4=CTS and bit6=DSR... just a
432 return (temp
& (1<<4) ? TIOCM_CTS
: 0)
433 | (temp
& (1<<6) ? TIOCM_DSR
: 0);
436 static struct usb_driver ark3116_driver
= {
438 .probe
= usb_serial_probe
,
439 .disconnect
= usb_serial_disconnect
,
440 .id_table
= id_table
,
444 static struct usb_serial_driver ark3116_device
= {
446 .owner
= THIS_MODULE
,
449 .id_table
= id_table
,
450 .usb_driver
= &ark3116_driver
,
452 .attach
= ark3116_attach
,
453 .set_termios
= ark3116_set_termios
,
454 .init_termios
= ark3116_init_termios
,
455 .ioctl
= ark3116_ioctl
,
456 .tiocmget
= ark3116_tiocmget
,
457 .open
= ark3116_open
,
460 static int __init
ark3116_init(void)
464 retval
= usb_serial_register(&ark3116_device
);
467 retval
= usb_register(&ark3116_driver
);
469 usb_serial_deregister(&ark3116_device
);
473 static void __exit
ark3116_exit(void)
475 usb_deregister(&ark3116_driver
);
476 usb_serial_deregister(&ark3116_device
);
479 module_init(ark3116_init
);
480 module_exit(ark3116_exit
);
481 MODULE_LICENSE("GPL");
483 module_param(debug
, bool, S_IRUGO
| S_IWUSR
);
484 MODULE_PARM_DESC(debug
, "Debug enabled or not");