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

📄 ti_usb_3410_5052.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* vi: ts=8 sw=8 * * TI 3410/5052 USB Serial Driver * * Copyright (C) 2004 Texas Instruments * * This driver is based on the Linux io_ti driver, which is *   Copyright (C) 2000-2002 Inside Out Networks *   Copyright (C) 2001-2002 Greg Kroah-Hartman * * 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. * * For questions or problems with this driver, contact Texas Instruments * technical support, or Al Borchers <alborchers@steinerpoint.com>, or * Peter Berger <pberger@brimson.com>. *  * This driver needs this hotplug script in /etc/hotplug/usb/ti_usb_3410_5052 * or in /etc/hotplug.d/usb/ti_usb_3410_5052.hotplug to set the device * configuration. * * #!/bin/bash * * BOOT_CONFIG=1 * ACTIVE_CONFIG=2 * * if [[ "$ACTION" != "add" ]] * then * 	exit * fi * * CONFIG_PATH=/sys${DEVPATH%/?*}/bConfigurationValue * * if [[ 0`cat $CONFIG_PATH` -ne $BOOT_CONFIG ]] * then * 	exit * fi * * PRODUCT=${PRODUCT%/?*}		# delete version * VENDOR_ID=`printf "%d" 0x${PRODUCT%/?*}` * PRODUCT_ID=`printf "%d" 0x${PRODUCT#*?/}` * * PARAM_PATH=/sys/module/ti_usb_3410_5052/parameters * * function scan() { * 	s=$1 * 	shift * 	for i * 	do * 		if [[ $s -eq $i ]] * 		then * 			return 0 * 		fi * 	done * 	return 1 * } * * IFS=$IFS, * * if (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_3410` && * scan $PRODUCT_ID 13328 `cat $PARAM_PATH/product_3410`) || * (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_5052` && * scan $PRODUCT_ID 20562 20818 20570 20575 `cat $PARAM_PATH/product_5052`) * then * 	echo $ACTIVE_CONFIG > $CONFIG_PATH * fi */#include <linux/config.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/tty.h>#include <linux/tty_driver.h>#include <linux/tty_flip.h>#include <linux/module.h>#include <linux/spinlock.h>#include <linux/ioctl.h>#include <linux/serial.h>#include <linux/circ_buf.h>#include <asm/uaccess.h>#include <asm/semaphore.h>#include <linux/usb.h>#include "usb-serial.h"#include "ti_usb_3410_5052.h"#include "ti_fw_3410.h"		/* firmware image for 3410 */#include "ti_fw_5052.h"		/* firmware image for 5052 *//* Defines */#define TI_DRIVER_VERSION	"v0.9"#define TI_DRIVER_AUTHOR	"Al Borchers <alborchers@steinerpoint.com>"#define TI_DRIVER_DESC		"TI USB 3410/5052 Serial Driver"#define TI_FIRMWARE_BUF_SIZE	16284#define TI_WRITE_BUF_SIZE	1024#define TI_TRANSFER_TIMEOUT	2#define TI_DEFAULT_LOW_LATENCY	0#define TI_DEFAULT_CLOSING_WAIT	4000		/* in .01 secs *//* supported setserial flags */#define TI_SET_SERIAL_FLAGS	(ASYNC_LOW_LATENCY)/* read urb states */#define TI_READ_URB_RUNNING	0#define TI_READ_URB_STOPPING	1#define TI_READ_URB_STOPPED	2#define TI_EXTRA_VID_PID_COUNT	5/* Structures */struct ti_port {	int			tp_is_open;	__u8			tp_msr;	__u8			tp_lsr;	__u8			tp_shadow_mcr;	__u8			tp_uart_mode;	/* 232 or 485 modes */	unsigned int		tp_uart_base_addr;	int			tp_flags;	int			tp_closing_wait;/* in .01 secs */	struct async_icount	tp_icount;	wait_queue_head_t	tp_msr_wait;	/* wait for msr change */	wait_queue_head_t	tp_write_wait;	struct ti_device	*tp_tdev;	struct usb_serial_port	*tp_port;	spinlock_t		tp_lock;	int			tp_read_urb_state;	int			tp_write_urb_in_use;	struct circ_buf		*tp_write_buf;};struct ti_device {	struct semaphore	td_open_close_sem;	int			td_open_port_count;	struct usb_serial	*td_serial;	int			td_is_3410;	int			td_urb_error;};/* Function Declarations */static int ti_startup(struct usb_serial *serial);static void ti_shutdown(struct usb_serial *serial);static int ti_open(struct usb_serial_port *port, struct file *file);static void ti_close(struct usb_serial_port *port, struct file *file);static int ti_write(struct usb_serial_port *port, const unsigned char *data,	int count);static int ti_write_room(struct usb_serial_port *port);static int ti_chars_in_buffer(struct usb_serial_port *port);static void ti_throttle(struct usb_serial_port *port);static void ti_unthrottle(struct usb_serial_port *port);static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);static void ti_set_termios(struct usb_serial_port *port,	struct termios *old_termios);static int ti_tiocmget(struct usb_serial_port *port, struct file *file);static int ti_tiocmset(struct usb_serial_port *port, struct file *file,	unsigned int set, unsigned int clear);static void ti_break(struct usb_serial_port *port, int break_state);static void ti_interrupt_callback(struct urb *urb, struct pt_regs *regs);static void ti_bulk_in_callback(struct urb *urb, struct pt_regs *regs);static void ti_bulk_out_callback(struct urb *urb, struct pt_regs *regs);static void ti_recv(struct device *dev, struct tty_struct *tty,	unsigned char *data, int length);static void ti_send(struct ti_port *tport);static int ti_set_mcr(struct ti_port *tport, unsigned int mcr);static int ti_get_lsr(struct ti_port *tport);static int ti_get_serial_info(struct ti_port *tport,	struct serial_struct __user *ret_arg);static int ti_set_serial_info(struct ti_port *tport,	struct serial_struct __user *new_arg);static void ti_handle_new_msr(struct ti_port *tport, __u8 msr);static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush);static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty);static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty);static int ti_command_out_sync(struct ti_device *tdev, __u8 command,	__u16 moduleid, __u16 value, __u8 *data, int size);static int ti_command_in_sync(struct ti_device *tdev, __u8 command,	__u16 moduleid, __u16 value, __u8 *data, int size);static int ti_write_byte(struct ti_device *tdev, unsigned long addr,	__u8 mask, __u8 byte);static int ti_download_firmware(struct ti_device *tdev,	unsigned char *firmware, unsigned int firmware_size);/* circular buffer */static struct circ_buf *ti_buf_alloc(void);static void ti_buf_free(struct circ_buf *cb);static void ti_buf_clear(struct circ_buf *cb);static int ti_buf_data_avail(struct circ_buf *cb);static int ti_buf_space_avail(struct circ_buf *cb);static int ti_buf_put(struct circ_buf *cb, const char *buf, int count);static int ti_buf_get(struct circ_buf *cb, char *buf, int count);/* Data *//* module parameters */static int debug;static int low_latency = TI_DEFAULT_LOW_LATENCY;static int closing_wait = TI_DEFAULT_CLOSING_WAIT;static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT];static int vendor_3410_count;static ushort product_3410[TI_EXTRA_VID_PID_COUNT];static int product_3410_count;static ushort vendor_5052[TI_EXTRA_VID_PID_COUNT];static int vendor_5052_count;static ushort product_5052[TI_EXTRA_VID_PID_COUNT];static int product_5052_count;/* supported devices *//* the array dimension is the number of default entries plus *//* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating *//* null entry */static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = {	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },};static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },	{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },};static struct usb_device_id ti_id_table_combined[] = {	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },	{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },	{ }};static struct usb_driver ti_usb_driver = {	.owner			= THIS_MODULE,	.name			= "ti_usb_3410_5052",	.probe			= usb_serial_probe,	.disconnect		= usb_serial_disconnect,	.id_table		= ti_id_table_combined,};static struct usb_serial_driver ti_1port_device = {	.driver = {		.owner		= THIS_MODULE,		.name		= "ti_usb_3410_5052_1",	},	.description		= "TI USB 3410 1 port adapter",	.id_table		= ti_id_table_3410,	.num_interrupt_in	= 1,	.num_bulk_in		= 1,	.num_bulk_out		= 1,	.num_ports		= 1,	.attach			= ti_startup,	.shutdown		= ti_shutdown,	.open			= ti_open,	.close			= ti_close,	.write			= ti_write,	.write_room		= ti_write_room,	.chars_in_buffer	= ti_chars_in_buffer,	.throttle		= ti_throttle,	.unthrottle		= ti_unthrottle,	.ioctl			= ti_ioctl,	.set_termios		= ti_set_termios,	.tiocmget		= ti_tiocmget,	.tiocmset		= ti_tiocmset,	.break_ctl		= ti_break,	.read_int_callback	= ti_interrupt_callback,	.read_bulk_callback	= ti_bulk_in_callback,	.write_bulk_callback	= ti_bulk_out_callback,};static struct usb_serial_driver ti_2port_device = {	.driver = {		.owner		= THIS_MODULE,		.name		= "ti_usb_3410_5052_2",	},	.description		= "TI USB 5052 2 port adapter",	.id_table		= ti_id_table_5052,	.num_interrupt_in	= 1,	.num_bulk_in		= 2,	.num_bulk_out		= 2,	.num_ports		= 2,	.attach			= ti_startup,	.shutdown		= ti_shutdown,	.open			= ti_open,	.close			= ti_close,	.write			= ti_write,	.write_room		= ti_write_room,	.chars_in_buffer	= ti_chars_in_buffer,	.throttle		= ti_throttle,	.unthrottle		= ti_unthrottle,	.ioctl			= ti_ioctl,	.set_termios		= ti_set_termios,	.tiocmget		= ti_tiocmget,	.tiocmset		= ti_tiocmset,	.break_ctl		= ti_break,	.read_int_callback	= ti_interrupt_callback,	.read_bulk_callback	= ti_bulk_in_callback,	.write_bulk_callback	= ti_bulk_out_callback,};/* Module */MODULE_AUTHOR(TI_DRIVER_AUTHOR);MODULE_DESCRIPTION(TI_DRIVER_DESC);MODULE_VERSION(TI_DRIVER_VERSION);MODULE_LICENSE("GPL");module_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes");module_param(low_latency, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(low_latency, "TTY low_latency flag, 0=off, 1=on, default is off");module_param(closing_wait, int, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain in close, in .01 secs, default is 4000");module_param_array(vendor_3410, ushort, &vendor_3410_count, S_IRUGO);MODULE_PARM_DESC(vendor_3410, "Vendor ids for 3410 based devices, 1-5 short integers");module_param_array(product_3410, ushort, &product_3410_count, S_IRUGO);MODULE_PARM_DESC(product_3410, "Product ids for 3410 based devices, 1-5 short integers");module_param_array(vendor_5052, ushort, &vendor_5052_count, S_IRUGO);MODULE_PARM_DESC(vendor_5052, "Vendor ids for 5052 based devices, 1-5 short integers");module_param_array(product_5052, ushort, &product_5052_count, S_IRUGO);MODULE_PARM_DESC(product_5052, "Product ids for 5052 based devices, 1-5 short integers");MODULE_DEVICE_TABLE(usb, ti_id_table_combined);/* Functions */static int __init ti_init(void){	int i,j;	int ret;	/* insert extra vendor and product ids */	j = sizeof(ti_id_table_3410)/sizeof(struct usb_device_id)		- TI_EXTRA_VID_PID_COUNT - 1;	for (i=0; i<min(vendor_3410_count,product_3410_count); i++,j++) {		ti_id_table_3410[j].idVendor = vendor_3410[i];		ti_id_table_3410[j].idProduct = product_3410[i];		ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;	}	j = sizeof(ti_id_table_5052)/sizeof(struct usb_device_id)		- TI_EXTRA_VID_PID_COUNT - 1;	for (i=0; i<min(vendor_5052_count,product_5052_count); i++,j++) {		ti_id_table_5052[j].idVendor = vendor_5052[i];		ti_id_table_5052[j].idProduct = product_5052[i];		ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;	}	ret = usb_serial_register(&ti_1port_device);	if (ret)		goto failed_1port;	ret = usb_serial_register(&ti_2port_device);	if (ret)		goto failed_2port;	ret = usb_register(&ti_usb_driver);	if (ret)		goto failed_usb;	info(TI_DRIVER_DESC " " TI_DRIVER_VERSION);	return 0;failed_usb:	usb_serial_deregister(&ti_2port_device);failed_2port:	usb_serial_deregister(&ti_1port_device);failed_1port:	return ret;}static void __exit ti_exit(void){	usb_serial_deregister(&ti_1port_device);	usb_serial_deregister(&ti_2port_device);	usb_deregister(&ti_usb_driver);}module_init(ti_init);module_exit(ti_exit);static int ti_startup(struct usb_serial *serial){	struct ti_device *tdev;	struct ti_port *tport;	struct usb_device *dev = serial->dev;	int status;	int i;	dbg("%s - product 0x%4X, num configurations %d, configuration value %d",	    __FUNCTION__, le16_to_cpu(dev->descriptor.idProduct),	    dev->descriptor.bNumConfigurations,	    dev->actconfig->desc.bConfigurationValue);	/* create device structure */	tdev = kmalloc(sizeof(struct ti_device), GFP_KERNEL);	if (tdev == NULL) {		dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);		return -ENOMEM;	}	memset(tdev, 0, sizeof(struct ti_device));	sema_init(&tdev->td_open_close_sem, 1);	tdev->td_serial = serial;	usb_set_serial_data(serial, tdev);	/* determine device type */	if (usb_match_id(serial->interface, ti_id_table_3410))		tdev->td_is_3410 = 1;	dbg("%s - device type is %s", __FUNCTION__, tdev->td_is_3410 ? "3410" : "5052");	/* if we have only 1 configuration, download firmware */	if (dev->descriptor.bNumConfigurations == 1) {		if (tdev->td_is_3410)			status = ti_download_firmware(tdev, ti_fw_3410,				sizeof(ti_fw_3410));		else			status = ti_download_firmware(tdev, ti_fw_5052,				sizeof(ti_fw_5052));		if (status)			goto free_tdev;		/* 3410 must be reset, 5052 resets itself */		if (tdev->td_is_3410) {			msleep_interruptible(100);			usb_reset_device(dev);		}		status = -ENODEV;		goto free_tdev;	} 	/* the second configuration must be set (in sysfs by hotplug script) */	if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) {		status = -ENODEV;		goto free_tdev;

⌨️ 快捷键说明

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