aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-05-10 11:24:24 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2006-05-10 11:24:24 -0700
commita9e23f5114a08820f93604f65c0711c2b6ce0be4 (patch)
tree15bd9ad562464ac66a57f929d3cae62ec8ac91b0 /usb
parentfbbd5ef9fa373ca30e5a302a432e5482aafff7fd (diff)
downloadpatches-a9e23f5114a08820f93604f65c0711c2b6ce0be4.tar.gz
added new usb-serial driver
Diffstat (limited to 'usb')
-rw-r--r--usb/usb-serial-ark3116.patch401
1 files changed, 401 insertions, 0 deletions
diff --git a/usb/usb-serial-ark3116.patch b/usb/usb-serial-ark3116.patch
new file mode 100644
index 0000000000000..ad875578d278a
--- /dev/null
+++ b/usb/usb-serial-ark3116.patch
@@ -0,0 +1,401 @@
+---
+ drivers/usb/serial/Kconfig | 10 +
+ drivers/usb/serial/Makefile | 1
+ drivers/usb/serial/ark3116.c | 363 +++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 374 insertions(+)
+
+--- gregkh-2.6.orig/drivers/usb/serial/Kconfig
++++ gregkh-2.6/drivers/usb/serial/Kconfig
+@@ -71,6 +71,16 @@ config USB_SERIAL_ANYDATA
+ To compile this driver as a module, choose M here: the
+ module will be called anydata.
+
++config USB_SERIAL_ARK3116
++ tristate "USB ARK Micro 3116 USB Serial Driver"
++ depends on USB_SERIAL
++ help
++ Say Y here if you want to use a ARK Micro 3116 USB to Serial
++ device.
++
++ To compile this driver as a module, choose M here: the
++ module will be called ark3116
++
+ config USB_SERIAL_BELKIN
+ tristate "USB Belkin and Peracom Single Port Serial Driver"
+ depends on USB_SERIAL
+--- gregkh-2.6.orig/drivers/usb/serial/Makefile
++++ gregkh-2.6/drivers/usb/serial/Makefile
+@@ -13,6 +13,7 @@ usbserial-objs := usb-serial.o generic.o
+
+ obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o
+ obj-$(CONFIG_USB_SERIAL_ANYDATA) += anydata.o
++obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o
+ obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
+ obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o
+ obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
+--- /dev/null
++++ gregkh-2.6/drivers/usb/serial/ark3116.c
+@@ -0,0 +1,363 @@
++/*
++ * ark3116
++ * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547,
++ * productid=0x0232) (used in a datacable called KQ-U8A)
++ *
++ * - based on code by krisfx -> thanks !!
++ * (see http://www.linuxquestions.org/questions/showthread.php?p=2184457#post2184457)
++ *
++ * - based on logs created by usbsnoopy
++ *
++ * Author : Simon Schulz [ark3116_driver<AT>auctionant.de]
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/tty.h>
++#include <linux/module.h>
++#include <linux/usb.h>
++#include "usb-serial.h"
++
++
++static int debug = 1;
++
++static struct usb_device_id id_table [] = {
++ { USB_DEVICE(0x6547, 0x0232) },
++ { },
++};
++MODULE_DEVICE_TABLE(usb, id_table);
++
++struct ark3116_private {
++ spinlock_t lock;
++ u8 termios_initialized;
++};
++
++static inline void ARK3116_SND(struct usb_serial *serial, int seq,
++ __u8 request, __u8 requesttype,
++ __u16 value, __u16 index)
++{
++ int result;
++ result = usb_control_msg(serial->dev,
++ usb_sndctrlpipe(serial->dev,0),
++ request, requesttype, value, index,
++ NULL,0x00, 1000);
++ dbg("%03d > ok",seq);
++}
++
++static inline void ARK3116_RCV(struct usb_serial *serial, int seq,
++ __u8 request, __u8 requesttype,
++ __u16 value, __u16 index, char *buf)
++{
++ int result;
++ result = usb_control_msg(serial->dev,
++ usb_rcvctrlpipe(serial->dev,0),
++ request, requesttype, value, index,
++ buf, 0x0000001, 1000);
++ if (result)
++ dbg("%03d < %d bytes [0x%02X]",seq, result, buf[0]);
++ else
++ dbg("%03d < 0 bytes", seq);
++}
++
++static int ark3116_attach(struct usb_serial *serial)
++{
++ char *buf;
++ struct ark3116_private *priv;
++ int i;
++
++ for (i = 0; i < serial->num_ports; ++i) {
++ priv = kmalloc (sizeof (struct ark3116_private), GFP_KERNEL);
++ if (!priv)
++ goto cleanup;
++ memset (priv, 0x00, sizeof (struct ark3116_private));
++ spin_lock_init(&priv->lock);
++
++ usb_set_serial_port_data(serial->port[i], priv);
++ }
++ return 0;
++
++ buf = kmalloc(1, GFP_KERNEL);
++ if (!buf) {
++ dbg("error kmalloc -> out of mem ?");
++ goto cleanup;
++ }
++
++ //<-- seq7
++ ARK3116_RCV(serial, 7,0xFE,0xC0,0x0000,0x0003, buf);
++
++ //<-- seq12
++ ARK3116_RCV(serial, 12,0xFE,0xC0,0x0000,0x0004, buf);
++
++ //--> seq17
++ ARK3116_SND(serial, 17,0xFE,0x40,0x0001,0x0004);
++
++ //<-- seq18
++ ARK3116_RCV(serial, 18,0xFE,0xC0,0x0000,0x0004, buf);
++
++ //--> seq19
++ ARK3116_SND(serial, 19,0xFE,0x40,0x0003,0x0004);
++
++ //<-- seq20
++ ARK3116_RCV(serial, 20,0xFE,0xC0,0x0000,0x0006, buf);
++
++
++ //set 9600 baud
++ ARK3116_SND(serial, 147,0xFE,0x40,0x0083,0x0003);
++ ARK3116_SND(serial, 148,0xFE,0x40,0x0038,0x0000);
++ ARK3116_SND(serial, 149,0xFE,0x40,0x0001,0x0001);
++ ARK3116_SND(serial, 150,0xFE,0x40,0x0003,0x0003);
++
++ ARK3116_RCV(serial, 151,0xFE,0xC0,0x0000,0x0004, buf);
++ ARK3116_SND(serial, 152,0xFE,0x40,0x0000,0x0003);
++
++ ARK3116_RCV(serial, 153,0xFE,0xC0,0x0000,0x0003, buf);
++ ARK3116_SND(serial, 154,0xFE,0x40,0x0003,0x0003);
++
++ kfree(buf);
++ return(0);
++
++cleanup:
++ for (--i; i>=0; --i)
++ usb_set_serial_port_data(serial->port[i], NULL);
++ return -ENOMEM;
++}
++
++/* strange, if this is used something goes wrong and the port is unusable :-\ */
++/* maybe timing problem ?! */
++/*
++static int ark3116_open(struct usb_serial_port *port, struct file *filp)
++{
++ struct termios tmp_termios;
++ struct usb_serial *serial = port->serial;
++
++ dbg("%s - port %d", __FUNCTION__, port->number);
++
++ //initialise termios:
++ //if (port->tty) {
++ // ark3116_set_termios (port, &tmp_termios);
++ //}
++
++ //ok
++ return(0);
++}
++*/
++
++static void ark3116_set_termios(struct usb_serial_port *port,
++ struct termios *old_termios)
++{
++ struct usb_serial *serial = port->serial;
++ struct ark3116_private *priv = usb_get_serial_port_data(port);
++ unsigned int cflag = port->tty->termios->c_cflag;
++ unsigned long flags;
++ int baud;
++ int ark3116_baud;
++ char *buf;
++ char config;
++
++ config = 0;
++
++ dbg("ark3116_set_termios port %d", port->number);
++
++ if ((!port->tty) || (!port->tty->termios)) {
++ dbg("%s - no tty structures", __FUNCTION__);
++ return;
++ }
++
++ spin_lock_irqsave(&priv->lock, flags);
++ if (!priv->termios_initialized) {
++ *(port->tty->termios) = tty_std_termios;
++ port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
++ priv->termios_initialized = 1;
++ }
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ cflag = port->tty->termios->c_cflag;
++
++ /* check that they really want us to change something: */
++ if (old_termios) {
++ if ((cflag == old_termios->c_cflag) &&
++ (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
++ RELEVANT_IFLAG(old_termios->c_iflag))) {
++ dbg("%s - nothing to change...", __FUNCTION__);
++ return;
++ }
++ }
++
++ buf = kmalloc(1, GFP_KERNEL);
++ if (!buf) {
++ dbg("error kmalloc");
++ return;
++ }
++
++ /* set data bit count (8/7/6/5) */
++ if (cflag & CSIZE){
++ switch (cflag & CSIZE){
++ case CS5:
++ config |= 0x00;
++ dbg("setting CS5");
++ break;
++ case CS6:
++ config |= 0x01;
++ dbg("setting CS6");
++ break;
++ case CS7:
++ config |= 0x02;
++ dbg("setting CS7");
++ break;
++ default:
++ err ("CSIZE was set but not CS5-CS8, using CS8!");
++ case CS8:
++ config |= 0x03;
++ dbg("setting CS8");
++ break;
++ }
++ }
++
++ /* set parity (NONE,EVEN,ODD) */
++ if (cflag & PARENB){
++ if (cflag & PARODD) {
++ config |= 0x08;
++ dbg("setting parity to ODD");
++ } else {
++ config |= 0x18;
++ dbg("setting parity to EVEN");
++ }
++ } else {
++ dbg("setting parity to NONE");
++ }
++
++ /* SET STOPBIT (1/2) */
++ if (cflag & CSTOPB) {
++ config |= 0x04;
++ dbg ("setting 2 stop bits");
++ } else {
++ dbg ("setting 1 stop bit");
++ }
++
++
++ /* set baudrate: */
++ baud = 0;
++ switch (cflag & CBAUD){
++ case B0: err ("Can't do B0 yet"); break;
++ case B150: baud = 150; break;
++ case B300: baud = 300; break;
++ case B600: baud = 600; break;
++ case B1200: baud = 1200; break;
++ case B1800: baud = 1800; break;
++ case B2400: baud = 2400; break;
++ case B4800: baud = 4800; break;
++ case B9600: baud = 9600; break;
++ case B19200: baud = 19200; break;
++ case B38400: baud = 38400; break;
++ case B57600: baud = 57600; break;
++ case B115200: baud = 115200; break;
++ case B230400: baud = 230400; break;
++ default:
++ dbg("does not support the baudrate requested (fix it)");
++ break;
++ }
++
++ /* set 9600 as default (if given baudrate is invalid for example) */
++ if (baud == 0)
++ baud = 9600;
++
++ /*
++ * found by try'n'error, be careful, maybe there are other options
++ * for multiplicator etc!
++ */
++ ark3116_baud = 3000000 / baud;
++
++ /* ? */
++ ARK3116_SND(serial, 147,0xFE,0x40,0x0083,0x0003);
++
++ /* set baudrate */
++ dbg("setting baudrate to %d (->reg=%d)",baud,ark3116_baud);
++ ARK3116_SND(serial, 148,0xFE,0x40,(ark3116_baud & 0x00FF) ,0x0000);
++ ARK3116_SND(serial, 149,0xFE,0x40,(ark3116_baud & 0xFF00)>>8,0x0001);
++
++ /* ? */
++ ARK3116_SND(serial, 150,0xFE,0x40,0x0003,0x0003);
++
++ /* ? */
++ ARK3116_RCV(serial, 151,0xFE,0xC0,0x0000,0x0004, buf);
++ ARK3116_SND(serial, 152,0xFE,0x40,0x0000,0x0003);
++
++ /* set data bit count, stop bit count & parity: */
++ dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config);
++ ARK3116_RCV(serial, 153,0xFE,0xC0,0x0000,0x0003, buf);
++ ARK3116_SND(serial, 154,0xFE,0x40,config,0x0003);
++
++ if (cflag & CRTSCTS)
++ dbg("CRTSCTS not supported by chipset ?!");
++
++ kfree(buf);
++ return;
++}
++
++static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ dbg("ioctl not supported yet...");
++ return -ENOIOCTLCMD;
++}
++
++static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
++{
++ dbg("tiocmget not supported yet...");
++ return 0;
++}
++
++static struct usb_driver ark3116_driver = {
++ .name = "ark3116",
++ .probe = usb_serial_probe,
++ .disconnect = usb_serial_disconnect,
++ .id_table = id_table,
++};
++
++static struct usb_serial_driver ark3116_device = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "ark3116",
++ },
++ .id_table = id_table,
++ .num_interrupt_in = 1,
++ .num_bulk_in = 1,
++ .num_bulk_out = 1,
++ .num_ports = 1,
++ .attach = ark3116_attach,
++ .set_termios = ark3116_set_termios,
++ .ioctl = ark3116_ioctl,
++ .tiocmget = ark3116_tiocmget,
++};
++
++static int __init ark3116_init(void)
++{
++ int retval;
++
++ retval = usb_serial_register(&ark3116_device);
++ if (retval)
++ return retval;
++ retval = usb_register(&ark3116_driver);
++ if (retval)
++ usb_serial_deregister(&ark3116_device);
++ return retval;
++}
++
++static void __exit ark3116_exit(void)
++{
++ usb_deregister(&ark3116_driver);
++ usb_serial_deregister(&ark3116_device);
++}
++
++module_init(ark3116_init);
++module_exit(ark3116_exit);
++MODULE_LICENSE("GPL");
++
++module_param(debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Debug enabled or not");
++