⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ark3116.c

📁 采用ark 3116芯片组的usb转rs232接口线的linux下驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*,-----------------------------------------------------------------------------------------.| 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||-----------------------------------------------------------------------------------------|| CHANGES:| 26.04.06 * changed uwb bulk read callback, should now work with kernel 2.6.16|| 15.04.06 * changed version names to 0.x.y|          * added changes made by Erik (Makefile)|          * removed debug=1 & added kernel parameter |            -> "insmod ark3116.ko debug=1" to activate debug msgs|          * i guess i found the modem control status register (0x0006), |            ark3116_tiocmget returns some data now (UNTESTED)|          * added open() function & usb urb stuff (copied from generic.c)|          * changed some init stuff... i still do not know what many lines do|          * added 75 & 460800 baud|| 13.04.06 * removed compile error when used with newer libusb |            (removed .owner in usb_driver struct init)|| 11.04.06 * added more baudrates, now supports: 150,300,600,1200,1800,2400,4800,9600,|            19200,38400,57600,115200,230400 (tested, ok!)|          * tested baudrate 75 & 460800 -> do not work -> maybe there is a prescaler!|          * tested data bit width: 6N1,7N1 & 8N1 are working |          * added some more functions & debug info |          * tried to implement .._open(), but with this the usb init does no longer work!|| 09.04.06 * added support for data bitcount, parity and stop bit selection UNTESTED!| 08.04.06 * first version||-----------------------------------------------------------------------------------------| Author   : Simon Schulz [ark3116_driver<AT>auctionant.de]|-----------------------------------------------------------------------------------------| License:| 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.| This program is distributed in the hope that it will be useful, but|| WITHOUT ANY WARRANTY;|| without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR| PURPOSE. See the GNU General Public License for more details.|| You should have received a copy of the GNU General Public License along with| this program; if not, write to the Free Software Foundation, Inc., 51| Franklin St, Fifth Floor, Boston, MA 02110, USA|| http://www.gnu.de/gpl-ger.html`-----------------------------------------------------------------------------------------*/#include <linux/kernel.h>#include <linux/init.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/slab.h>#include <linux/usb.h>#include <asm/uaccess.h>#include "usb-serial.h"static int debug;static int ark3116_attach(struct usb_serial *serial);static void ark3116_set_termios(struct usb_serial_port *port, struct termios * old);static int ark3116_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);static int ark3116_tiocmget (struct usb_serial_port *port, struct file *file);static int ark3116_open (struct usb_serial_port *port, struct file *filp);static void ark3116_read_bulk_callback (struct urb *urb, struct pt_regs *regs);static struct usb_device_id id_table [] = {	{ USB_DEVICE(0x6547, 0x0232) },	{ },};MODULE_DEVICE_TABLE(usb, id_table);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,	.open = ark3116_open,};struct ark3116_private {	spinlock_t lock;	u8 termios_initialized;};#define ARK3116_SND(seq, a,b,c,d) { rst = usb_control_msg(serial->dev,usb_sndctrlpipe(serial->dev,0), a,b,c,d,NULL,0x00, 1000); dbg("%03d > ok",seq); }#define ARK3116_RCV(seq, a,b,c,d, expected) {rst = usb_control_msg(serial->dev,usb_rcvctrlpipe(serial->dev,0),a,b,c,d,buf,0x0000001, 1000);  if (rst) dbg("%03d < %d bytes [0x%02X] expected [0x%02X]",seq,rst,buf[0],expected); else dbg("%03d < 0 bytes", seq);}#define ARK3116_RCV_QUIET(a,b,c,d){rst = usb_control_msg(serial->dev,usb_rcvctrlpipe(serial->dev,0),a,b,c,d,buf,0x0000001, 1000);}static int ark3116_attach(struct usb_serial *serial) {	char *buf;	struct ark3116_private *priv;	int rst;	int i;	rst=0;		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);	}		buf = kmalloc(1, GFP_KERNEL);	if (!buf) {		dbg("error kmalloc -> out of mem ?");		goto cleanup;	}	//3	ARK3116_SND( 3,0xFE,0x40,0x0008,0x0002);	ARK3116_SND( 4,0xFE,0x40,0x0008,0x0001);	ARK3116_SND( 5,0xFE,0x40,0x0000,0x0008);	ARK3116_SND( 6,0xFE,0x40,0x0000,0x000B);		//<-- seq7	ARK3116_RCV( 7,0xFE,0xC0,0x0000,0x0003, 0x00);	ARK3116_SND( 8,0xFE,0x40,0x0080,0x0003);	ARK3116_SND( 9,0xFE,0x40,0x001A,0x0000);	ARK3116_SND(10,0xFE,0x40,0x0000,0x0001);	ARK3116_SND(11,0xFE,0x40,0x0000,0x0003);		//<-- seq12	ARK3116_RCV(12,0xFE,0xC0,0x0000,0x0004, 0x00);	ARK3116_SND(13,0xFE,0x40,0x0000,0x0004);	//14	ARK3116_RCV(14,0xFE,0xC0,0x0000,0x0004, 0x00);	ARK3116_SND(15,0xFE,0x40,0x0000,0x0004);	//16	ARK3116_RCV(16,0xFE,0xC0,0x0000,0x0004, 0x00);	//--> seq17	ARK3116_SND(17,0xFE,0x40,0x0001,0x0004);	//<-- seq18	ARK3116_RCV(18,0xFE,0xC0,0x0000,0x0004, 0x01);	//--> seq19	ARK3116_SND(19,0xFE,0x40,0x0003,0x0004);	//<-- seq20	//seems like serial port status info (RTS, CTS,...)	ARK3116_RCV(20,0xFE,0xC0,0x0000,0x0006, 0xFF); //returns modem control line status ?!	//set 9600 baud & do some init ?!	ARK3116_SND(147,0xFE,0x40,0x0083,0x0003);	ARK3116_SND(148,0xFE,0x40,0x0038,0x0000);	ARK3116_SND(149,0xFE,0x40,0x0001,0x0001);	ARK3116_SND(150,0xFE,0x40,0x0003,0x0003);	ARK3116_RCV(151,0xFE,0xC0,0x0000,0x0004,0x03);	ARK3116_SND(152,0xFE,0x40,0x0000,0x0003);	ARK3116_RCV(153,0xFE,0xC0,0x0000,0x0003,0x00);	ARK3116_SND(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;	int rst;	char *buf;	int result = 0;	dbg("%s -  port %d", __FUNCTION__, port->number);	buf = kmalloc(1, GFP_KERNEL);	if (!buf) {		dbg("error kmalloc -> out of mem ?");	        return -ENOMEM;	}	//init stolen from generic.c:		/* force low_latency on so that our tty_push actually forces the data through,	 * otherwise it is scheduled, and with high data rates (like with OHCI) data	 * can get lost. */	if (port->tty)		port->tty->low_latency = 1;	/* if we have a bulk interrupt, start reading from it */	if (serial->num_bulk_in) {		/* Start reading from the device */		usb_fill_bulk_urb (port->read_urb, serial->dev,				usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),				port->read_urb->transfer_buffer,				port->read_urb->transfer_buffer_length,				((serial->type->read_bulk_callback) ?				 serial->type->read_bulk_callback :				 ark3116_read_bulk_callback),				port);		result = usb_submit_urb(port->read_urb, GFP_KERNEL);		if (result)			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);	}	//open	ARK3116_RCV( 111,0xFE,0xC0,0x0000,0x0003, 0x02); //returns 2		ARK3116_SND( 112,0xFE,0x40,0x0082,0x0003);		ARK3116_SND( 113,0xFE,0x40,0x001A,0x0000);	ARK3116_SND( 114,0xFE,0x40,0x0000,0x0001);	ARK3116_SND( 115,0xFE,0x40,0x0002,0x0003);		ARK3116_RCV( 116,0xFE,0xC0,0x0000,0x0004, 0x03); //returns 3	ARK3116_SND( 117,0xFE,0x40,0x0002,0x0004);		ARK3116_RCV( 118,0xFE,0xC0,0x0000,0x0004, 0x02); //returns 2

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -