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

📄 whiteheat.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * USB ConnectTech WhiteHEAT driver * *	Copyright (C) 1999 - 2001 *	    Greg Kroah-Hartman (greg@kroah.com) * *	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. * * See Documentation/usb/usb-serial.txt for more information on using this driver * * (05/30/2001) gkh *	switched from using spinlock to a semaphore, which fixes lots of problems. * * (04/08/2001) gb *	Identify version on module load. *  * 2001_Mar_19 gkh *	Fixed MOD_INC and MOD_DEC logic, the ability to open a port more  *	than once, and the got the proper usb_device_id table entries so *	the driver works again. * * (11/01/2000) Adam J. Richter *	usb_device_id table support *  * (10/05/2000) gkh *	Fixed bug with urb->dev not being set properly, now that the usb *	core needs it. *  * (10/03/2000) smd *	firmware is improved to guard against crap sent to device *	firmware now replies CMD_FAILURE on bad things *	read_callback fix you provided for private info struct *	command_finished now indicates success or fail *	setup_port struct now packed to avoid gcc padding *	firmware uses 1 based port numbering, driver now handles that * * (09/11/2000) gkh *	Removed DEBUG #ifdefs with call to usb_serial_debug_data * * (07/19/2000) gkh *	Added module_init and module_exit functions to handle the fact that this *	driver is a loadable module now. *	Fixed bug with port->minor that was found by Al Borchers * * (07/04/2000) gkh *	Added support for port settings. Baud rate can now be changed. Line signals *	are not transferred to and from the tty layer yet, but things seem to be  *	working well now. * * (05/04/2000) gkh *	First cut at open and close commands. Data can flow through the ports at *	default speeds now. * * (03/26/2000) gkh *	Split driver up into device specific pieces. *  */#include <linux/config.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/errno.h>#include <linux/poll.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/fcntl.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/usb.h>#ifdef CONFIG_USB_SERIAL_DEBUG	static int debug = 1;#else	static int debug;#endif#include "usb-serial.h"#include "whiteheat_fw.h"		/* firmware for the ConnectTech WhiteHEAT device */#include "whiteheat.h"			/* WhiteHEAT specific commands *//* * Version Information */#define DRIVER_VERSION "v1.1"#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"#define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"#define CONNECT_TECH_VENDOR_ID		0x0710#define CONNECT_TECH_FAKE_WHITE_HEAT_ID	0x0001#define CONNECT_TECH_WHITE_HEAT_ID	0x8001/*   ID tables for whiteheat are unusual, because we want to different   things for different versions of the device.  Eventually, this   will be doable from a single table.  But, for now, we define two   separate ID tables, and then a third table that combines them   just for the purpose of exporting the autoloading information.*/static __devinitdata struct usb_device_id id_table_std [] = {	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_WHITE_HEAT_ID) },	{ }						/* Terminating entry */};static __devinitdata struct usb_device_id id_table_prerenumeration [] = {	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_FAKE_WHITE_HEAT_ID) },	{ }						/* Terminating entry */};static __devinitdata struct usb_device_id id_table_combined [] = {	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_WHITE_HEAT_ID) },	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_FAKE_WHITE_HEAT_ID) },	{ }						/* Terminating entry */};MODULE_DEVICE_TABLE (usb, id_table_combined);/* function prototypes for the Connect Tech WhiteHEAT serial converter */static int  whiteheat_open		(struct usb_serial_port *port, struct file *filp);static void whiteheat_close		(struct usb_serial_port *port, struct file *filp);static int  whiteheat_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);static void whiteheat_set_termios	(struct usb_serial_port *port, struct termios * old);static void whiteheat_throttle		(struct usb_serial_port *port);static void whiteheat_unthrottle	(struct usb_serial_port *port);static int  whiteheat_startup		(struct usb_serial *serial);static void whiteheat_shutdown		(struct usb_serial *serial);static struct usb_serial_device_type whiteheat_fake_device = {	name:			"Connect Tech - WhiteHEAT - (prerenumeration)",	id_table:		id_table_prerenumeration,	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */	num_interrupt_in:	NUM_DONT_CARE,	num_bulk_in:		NUM_DONT_CARE,	num_bulk_out:		NUM_DONT_CARE,	num_ports:		1,	startup:		whiteheat_startup	};static struct usb_serial_device_type whiteheat_device = {	name:			"Connect Tech - WhiteHEAT",	id_table:		id_table_std,	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */	num_interrupt_in:	NUM_DONT_CARE,	num_bulk_in:		NUM_DONT_CARE,	num_bulk_out:		NUM_DONT_CARE,	num_ports:		4,	open:			whiteheat_open,	close:			whiteheat_close,	throttle:		whiteheat_throttle,	unthrottle:		whiteheat_unthrottle,	ioctl:			whiteheat_ioctl,	set_termios:		whiteheat_set_termios,	shutdown:		whiteheat_shutdown,};struct whiteheat_private {	__u8			command_finished;	wait_queue_head_t	wait_command;	/* for handling sleeping while waiting for a command to finish */};/* local function prototypes */static inline void set_rts	(struct usb_serial_port *port, unsigned char rts);static inline void set_dtr	(struct usb_serial_port *port, unsigned char dtr);static inline void set_break	(struct usb_serial_port *port, unsigned char brk);#define COMMAND_PORT		4#define COMMAND_TIMEOUT		(2*HZ)	/* 2 second timeout for a command *//***************************************************************************** * Connect Tech's White Heat specific driver functions *****************************************************************************/static void command_port_write_callback (struct urb *urb){	dbg (__FUNCTION__);	if (urb->status) {		dbg ("nonzero urb status: %d", urb->status);		return;	}	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer);	return;}static void command_port_read_callback (struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);	struct whiteheat_private *info;	unsigned char *data = urb->transfer_buffer;	int result;	dbg (__FUNCTION__);	if (urb->status) {		dbg (__FUNCTION__ " - nonzero urb status: %d", urb->status);		return;	}	if (!serial) {		dbg(__FUNCTION__ " - bad serial pointer, exiting");		return;	}		usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);	info = (struct whiteheat_private *)port->private;	if (!info) {		dbg (__FUNCTION__ " - info is NULL, exiting.");		return;	}	/* right now, if the command is COMMAND_COMPLETE, just flip the bit saying the command finished */	/* in the future we're going to have to pay attention to the actual command that completed */	if (data[0] == WHITEHEAT_CMD_COMPLETE) {		info->command_finished = WHITEHEAT_CMD_COMPLETE;		wake_up_interruptible(&info->wait_command);	}		if (data[0] == WHITEHEAT_CMD_FAILURE) {		info->command_finished = WHITEHEAT_CMD_FAILURE;		wake_up_interruptible(&info->wait_command);	}		/* Continue trying to always read */	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,		      command_port_read_callback, port);	result = usb_submit_urb(port->read_urb);	if (result)		dbg(__FUNCTION__ " - failed resubmitting read urb, error %d", result);}static int whiteheat_send_cmd (struct usb_serial *serial, __u8 command, __u8 *data, __u8 datasize){	struct whiteheat_private *info;	struct usb_serial_port *port;	int timeout;	__u8 *transfer_buffer;	int retval = 0;	dbg(__FUNCTION__" - command %d", command);	port = &serial->port[COMMAND_PORT];	info = (struct whiteheat_private *)port->private;	info->command_finished = FALSE;		transfer_buffer = (__u8 *)port->write_urb->transfer_buffer;	transfer_buffer[0] = command;	memcpy (&transfer_buffer[1], data, datasize);	port->write_urb->transfer_buffer_length = datasize + 1;	port->write_urb->dev = serial->dev;	retval = usb_submit_urb (port->write_urb);	if (retval) {		dbg (__FUNCTION__" - submit urb failed");		goto exit;	}	/* wait for the command to complete */	timeout = COMMAND_TIMEOUT;	while (timeout && (info->command_finished == FALSE)) {		timeout = interruptible_sleep_on_timeout (&info->wait_command, timeout);	}	if (info->command_finished == FALSE) {		dbg (__FUNCTION__ " - command timed out.");		retval = -ETIMEDOUT;		goto exit;	}	if (info->command_finished == WHITEHEAT_CMD_FAILURE) {		dbg (__FUNCTION__ " - command failed.");		retval = -EIO;		goto exit;	}	if (info->command_finished == WHITEHEAT_CMD_COMPLETE)		dbg (__FUNCTION__ " - command completed.");exit:	return retval;}static int whiteheat_open (struct usb_serial_port *port, struct file *filp){	struct whiteheat_min_set	open_command;	struct usb_serial_port 		*command_port;	struct whiteheat_private	*info;	int				retval = 0;	dbg(__FUNCTION__" - port %d", port->number);	down (&port->sem);	++port->open_count;	MOD_INC_USE_COUNT;		if (!port->active) {		port->active = 1;		/* set up some stuff for our command port */		command_port = &port->serial->port[COMMAND_PORT];		if (command_port->private == NULL) {			info = (struct whiteheat_private *)kmalloc (sizeof(struct whiteheat_private), GFP_KERNEL);			if (info == NULL) {				err(__FUNCTION__ " - out of memory");				retval = -ENOMEM;				goto error_exit;			}						init_waitqueue_head(&info->wait_command);			command_port->private = info;			command_port->write_urb->complete = command_port_write_callback;			command_port->read_urb->complete = command_port_read_callback;			command_port->read_urb->dev = port->serial->dev;			command_port->tty = port->tty;		/* need this to "fake" our our sanity check macros */			retval = usb_submit_urb (command_port->read_urb);			if (retval) {				err(__FUNCTION__ " - failed submitting read urb, error %d", retval);				goto error_exit;			}		}				/* Start reading from the device */		port->read_urb->dev = port->serial->dev;

⌨️ 快捷键说明

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