1 /* 2 * Copyright (C) 2006 3 * Simon Schulz (ark3116_driver <at> auctionant.de) 4 * 5 * ark3116 6 * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547, 7 * productid=0x0232) (used in a datacable called KQ-U8A) 8 * 9 * - based on code by krisfx -> thanks !! 10 * (see http://www.linuxquestions.org/questions/showthread.php?p=2184457#post2184457) 11 * 12 * - based on logs created by usbsnoopy 13 * 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. 18 */ 19 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> 28 29 30 static int debug; 31 32 static struct usb_device_id id_table [] = { 33 { USB_DEVICE(0x6547, 0x0232) }, 34 { USB_DEVICE(0x18ec, 0x3118) }, /* USB to IrDA adapter */ 35 { }, 36 }; 37 MODULE_DEVICE_TABLE(usb, id_table); 38 39 static int is_irda(struct usb_serial *serial) 40 { 41 struct usb_device *dev = serial->dev; 42 if (le16_to_cpu(dev->descriptor.idVendor) == 0x18ec && 43 le16_to_cpu(dev->descriptor.idProduct) == 0x3118) 44 return 1; 45 return 0; 46 } 47 48 static inline void ARK3116_SND(struct usb_serial *serial, int seq, 49 __u8 request, __u8 requesttype, 50 __u16 value, __u16 index) 51 { 52 int result; 53 result = usb_control_msg(serial->dev, 54 usb_sndctrlpipe(serial->dev, 0), 55 request, requesttype, value, index, 56 NULL, 0x00, 1000); 57 dbg("%03d > ok", seq); 58 } 59 60 static inline void ARK3116_RCV(struct usb_serial *serial, int seq, 61 __u8 request, __u8 requesttype, 62 __u16 value, __u16 index, __u8 expected, 63 char *buf) 64 { 65 int result; 66 result = usb_control_msg(serial->dev, 67 usb_rcvctrlpipe(serial->dev, 0), 68 request, requesttype, value, index, 69 buf, 0x0000001, 1000); 70 if (result) 71 dbg("%03d < %d bytes [0x%02X]", seq, result, 72 ((unsigned char *)buf)[0]); 73 else 74 dbg("%03d < 0 bytes", seq); 75 } 76 77 static inline void ARK3116_RCV_QUIET(struct usb_serial *serial, 78 __u8 request, __u8 requesttype, 79 __u16 value, __u16 index, char *buf) 80 { 81 usb_control_msg(serial->dev, 82 usb_rcvctrlpipe(serial->dev, 0), 83 request, requesttype, value, index, 84 buf, 0x0000001, 1000); 85 } 86 87 static int ark3116_attach(struct usb_serial *serial) 88 { 89 char *buf; 90 91 buf = kmalloc(1, GFP_KERNEL); 92 if (!buf) { 93 dbg("error kmalloc -> out of mem?"); 94 return -ENOMEM; 95 } 96 97 if (is_irda(serial)) 98 dbg("IrDA mode"); 99 100 /* 3 */ 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, 105 0x000B); 106 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); 111 } 112 113 /* <-- seq7 */ 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); 119 120 /* <-- seq12 */ 121 ARK3116_RCV(serial, 12, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); 122 ARK3116_SND(serial, 13, 0xFE, 0x40, 0x0000, 0x0004); 123 124 /* 14 */ 125 ARK3116_RCV(serial, 14, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); 126 ARK3116_SND(serial, 15, 0xFE, 0x40, 0x0000, 0x0004); 127 128 /* 16 */ 129 ARK3116_RCV(serial, 16, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); 130 /* --> seq17 */ 131 ARK3116_SND(serial, 17, 0xFE, 0x40, 0x0001, 0x0004); 132 133 /* <-- seq18 */ 134 ARK3116_RCV(serial, 18, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf); 135 136 /* --> seq19 */ 137 ARK3116_SND(serial, 19, 0xFE, 0x40, 0x0003, 0x0004); 138 139 /* <-- seq20 */ 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); 143 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); 148 if (is_irda(serial)) 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); 155 156 kfree(buf); 157 return 0; 158 } 159 160 static void ark3116_init_termios(struct tty_struct *tty) 161 { 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; 168 } 169 170 static void ark3116_set_termios(struct tty_struct *tty, 171 struct usb_serial_port *port, 172 struct ktermios *old_termios) 173 { 174 struct usb_serial *serial = port->serial; 175 struct ktermios *termios = tty->termios; 176 unsigned int cflag = termios->c_cflag; 177 int baud; 178 int ark3116_baud; 179 char *buf; 180 char config; 181 182 config = 0; 183 184 dbg("%s - port %d", __func__, port->number); 185 186 187 cflag = termios->c_cflag; 188 termios->c_cflag &= ~(CMSPAR|CRTSCTS); 189 190 buf = kmalloc(1, GFP_KERNEL); 191 if (!buf) { 192 dbg("error kmalloc"); 193 *termios = *old_termios; 194 return; 195 } 196 197 /* set data bit count (8/7/6/5) */ 198 if (cflag & CSIZE) { 199 switch (cflag & CSIZE) { 200 case CS5: 201 config |= 0x00; 202 dbg("setting CS5"); 203 break; 204 case CS6: 205 config |= 0x01; 206 dbg("setting CS6"); 207 break; 208 case CS7: 209 config |= 0x02; 210 dbg("setting CS7"); 211 break; 212 default: 213 dbg("CSIZE was set but not CS5-CS8, using CS8!"); 214 /* fall through */ 215 case CS8: 216 config |= 0x03; 217 dbg("setting CS8"); 218 break; 219 } 220 } 221 222 /* set parity (NONE/EVEN/ODD) */ 223 if (cflag & PARENB) { 224 if (cflag & PARODD) { 225 config |= 0x08; 226 dbg("setting parity to ODD"); 227 } else { 228 config |= 0x18; 229 dbg("setting parity to EVEN"); 230 } 231 } else { 232 dbg("setting parity to NONE"); 233 } 234 235 /* set stop bit (1/2) */ 236 if (cflag & CSTOPB) { 237 config |= 0x04; 238 dbg("setting 2 stop bits"); 239 } else { 240 dbg("setting 1 stop bit"); 241 } 242 243 /* set baudrate */ 244 baud = tty_get_baud_rate(tty); 245 246 switch (baud) { 247 case 75: 248 case 150: 249 case 300: 250 case 600: 251 case 1200: 252 case 1800: 253 case 2400: 254 case 4800: 255 case 9600: 256 case 19200: 257 case 38400: 258 case 57600: 259 case 115200: 260 case 230400: 261 case 460800: 262 /* Report the resulting rate back to the caller */ 263 tty_encode_baud_rate(tty, baud, baud); 264 break; 265 /* set 9600 as default (if given baudrate is invalid for example) */ 266 default: 267 tty_encode_baud_rate(tty, 9600, 9600); 268 case 0: 269 baud = 9600; 270 } 271 272 /* 273 * found by try'n'error, be careful, maybe there are other options 274 * for multiplicator etc! (3.5 for example) 275 */ 276 if (baud == 460800) 277 /* strange, for 460800 the formula is wrong 278 * if using round() then 9600baud is wrong) */ 279 ark3116_baud = 7; 280 else 281 ark3116_baud = 3000000 / baud; 282 283 /* ? */ 284 ARK3116_RCV(serial, 0, 0xFE, 0xC0, 0x0000, 0x0003, 0x03, buf); 285 286 /* offset = buf[0]; */ 287 /* offset = 0x03; */ 288 /* dbg("using 0x%04X as target for 0x0003:", 0x0080 + offset); */ 289 290 /* set baudrate */ 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); 298 299 /* ? */ 300 ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); 301 ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); 302 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); 307 308 if (cflag & CRTSCTS) 309 dbg("CRTSCTS not supported by chipset?!"); 310 311 /* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */ 312 313 kfree(buf); 314 315 return; 316 } 317 318 static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) 319 { 320 struct ktermios tmp_termios; 321 struct usb_serial *serial = port->serial; 322 char *buf; 323 int result = 0; 324 325 dbg("%s - port %d", __func__, port->number); 326 327 buf = kmalloc(1, GFP_KERNEL); 328 if (!buf) { 329 dbg("error kmalloc -> out of mem?"); 330 return -ENOMEM; 331 } 332 333 result = usb_serial_generic_open(tty, port); 334 if (result) 335 goto err_out; 336 337 /* open */ 338 ARK3116_RCV(serial, 111, 0xFE, 0xC0, 0x0000, 0x0003, 0x02, buf); 339 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); 344 345 ARK3116_RCV(serial, 116, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); 346 ARK3116_SND(serial, 117, 0xFE, 0x40, 0x0002, 0x0004); 347 348 ARK3116_RCV(serial, 118, 0xFE, 0xC0, 0x0000, 0x0004, 0x02, buf); 349 ARK3116_SND(serial, 119, 0xFE, 0x40, 0x0000, 0x0004); 350 351 ARK3116_RCV(serial, 120, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); 352 353 ARK3116_SND(serial, 121, 0xFE, 0x40, 0x0001, 0x0004); 354 355 ARK3116_RCV(serial, 122, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf); 356 357 ARK3116_SND(serial, 123, 0xFE, 0x40, 0x0003, 0x0004); 358 359 /* returns different values (control lines?!) */ 360 ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf); 361 362 /* initialise termios */ 363 if (tty) 364 ark3116_set_termios(tty, port, &tmp_termios); 365 366 err_out: 367 kfree(buf); 368 369 return result; 370 } 371 372 static int ark3116_ioctl(struct tty_struct *tty, struct file *file, 373 unsigned int cmd, unsigned long arg) 374 { 375 struct usb_serial_port *port = tty->driver_data; 376 struct serial_struct serstruct; 377 void __user *user_arg = (void __user *)arg; 378 379 switch (cmd) { 380 case TIOCGSERIAL: 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; 388 389 if (copy_to_user(user_arg, &serstruct, sizeof(serstruct))) 390 return -EFAULT; 391 392 return 0; 393 case TIOCSSERIAL: 394 if (copy_from_user(&serstruct, user_arg, sizeof(serstruct))) 395 return -EFAULT; 396 return 0; 397 default: 398 dbg("%s cmd 0x%04x not supported", __func__, cmd); 399 break; 400 } 401 402 return -ENOIOCTLCMD; 403 } 404 405 static int ark3116_tiocmget(struct tty_struct *tty, struct file *file) 406 { 407 struct usb_serial_port *port = tty->driver_data; 408 struct usb_serial *serial = port->serial; 409 char *buf; 410 char temp; 411 412 /* seems like serial port status info (RTS, CTS, ...) is stored 413 * in reg(?) 0x0006 414 * pcb connection point 11 = GND -> sets bit4 of response 415 * pcb connection point 7 = GND -> sets bit6 of response 416 */ 417 418 buf = kmalloc(1, GFP_KERNEL); 419 if (!buf) { 420 dbg("error kmalloc"); 421 return -ENOMEM; 422 } 423 424 /* read register */ 425 ARK3116_RCV_QUIET(serial, 0xFE, 0xC0, 0x0000, 0x0006, buf); 426 temp = buf[0]; 427 kfree(buf); 428 429 /* i do not really know if bit4=CTS and bit6=DSR... just a 430 * quick guess! 431 */ 432 return (temp & (1<<4) ? TIOCM_CTS : 0) 433 | (temp & (1<<6) ? TIOCM_DSR : 0); 434 } 435 436 static struct usb_driver ark3116_driver = { 437 .name = "ark3116", 438 .probe = usb_serial_probe, 439 .disconnect = usb_serial_disconnect, 440 .id_table = id_table, 441 .no_dynamic_id = 1, 442 }; 443 444 static struct usb_serial_driver ark3116_device = { 445 .driver = { 446 .owner = THIS_MODULE, 447 .name = "ark3116", 448 }, 449 .id_table = id_table, 450 .usb_driver = &ark3116_driver, 451 .num_ports = 1, 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, 458 }; 459 460 static int __init ark3116_init(void) 461 { 462 int retval; 463 464 retval = usb_serial_register(&ark3116_device); 465 if (retval) 466 return retval; 467 retval = usb_register(&ark3116_driver); 468 if (retval) 469 usb_serial_deregister(&ark3116_device); 470 return retval; 471 } 472 473 static void __exit ark3116_exit(void) 474 { 475 usb_deregister(&ark3116_driver); 476 usb_serial_deregister(&ark3116_device); 477 } 478 479 module_init(ark3116_init); 480 module_exit(ark3116_exit); 481 MODULE_LICENSE("GPL"); 482 483 module_param(debug, bool, S_IRUGO | S_IWUSR); 484 MODULE_PARM_DESC(debug, "Debug enabled or not"); 485 486