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

📄 t500usb.c

📁 Epson BA-T500USB在Linux 2.4下的设备驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ------------------------------------------------------ * Epson BA-T500 USB driver - 0.1 * * Author: Cedar Peng (cedar.peng@gmail.com) * * History: * * 2007_04_16 - 0.1 - Modified the Linux USB Skeleton drirver to  *                    satisfied BA-T500USB requirement. * * ------------------------------------------------------ * USB Skeleton driver - 0.7 * * Copyright (c) 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. * * * This driver is to be used as a skeleton driver to be able to create a * USB driver quickly.  The design of it is based on the usb-serial and * dc2xx drivers. * * Thanks to Oliver Neukum and David Brownell for their help in debugging * this driver. * * TODO: *	- fix urb->status race condition in write sequence *	- move minor_table to a dynamic list. * * History: * * 2002_02_12 - 0.7 - zero out dev in probe function for devices that do *			not have both a bulk in and bulk out endpoint. *			Thanks to Holger Waechtler for the fix. * 2001_11_05 - 0.6 - fix minor locking problem in t500u_disconnect. *			Thanks to Pete Zaitcev for the fix. * 2001_09_04 - 0.5 - fix devfs bug in t500u_disconnect. Thanks to wim delvaux * 2001_08_21 - 0.4 - more small bug fixes. * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people * 2001_05_01 - 0.1 - first version *  */#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/module.h>#include <linux/spinlock.h>#include <linux/list.h>#include <linux/smp_lock.h>#include <linux/devfs_fs_kernel.h>#include <linux/usb.h>#ifdef CONFIG_USB_DEBUG	static int debug = 1;#else	static int debug;#endif/* Version Information */#define DRIVER_VERSION "v0.1"#define DRIVER_AUTHOR "Cedar Peng, cedar.peng@gmail.com"#define DRIVER_DESC "Epson BA-T500USB driver"/* Module paramaters */MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");/* Define these values to match your device */#define USB_T500U_VENDOR_ID	0x04b8#define USB_T500U_PRODUCT_ID	0x0202/* table of devices that work with this driver */// If you have many devices, you could expand this table.static struct usb_device_id t500u_table [] = {	{ USB_DEVICE(USB_T500U_VENDOR_ID, USB_T500U_PRODUCT_ID) },	{ }					/* Terminating entry */};MODULE_DEVICE_TABLE (usb, t500u_table);/* Get a minor range for your devices from the usb maintainer */#define USB_T500U_MINOR_BASE	200	/* we can have up to this number of device plugged in at once */#define MAX_DEVICES		8/* Structure to hold all of our device specific stuff */struct usb_t500u {	struct usb_device *	udev;			/* save off the usb device pointer */	struct usb_interface *	interface;		/* the interface for this device */	devfs_handle_t		devfs;			/* devfs device node */	unsigned char		minor;			/* the starting minor number for this device */	unsigned char		num_ports;		/* the number of ports this device has */	char			num_interrupt_in;	/* number of interrupt in endpoints we have */	char			num_bulk_in;		/* number of bulk in endpoints we have */	char			num_bulk_out;		/* number of bulk out endpoints we have */	unsigned char *		bulk_in_buffer;		/* the buffer to receive data */	int			bulk_in_size;		/* the size of the receive buffer */	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */	unsigned char *		bulk_out_buffer;	/* the buffer to send data */	int			bulk_out_size;		/* the size of the send buffer */	struct urb *		write_urb;		/* the urb used to send data */	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */	struct tq_struct	tqueue;			/* task queue for line discipline waking up */	int			open_count;		/* number of times this port has been opened */	struct semaphore	sem;			/* locks this structure */};/* the global usb devfs handle */extern devfs_handle_t usb_devfs_handle;/* local function prototypes */static ssize_t t500u_read	(struct file *file, char *buffer, size_t count, loff_t *ppos);static ssize_t t500u_write	(struct file *file, const char *buffer, size_t count, loff_t *ppos);static int t500u_ioctl		(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int t500u_open		(struct inode *inode, struct file *file);static int t500u_release	(struct inode *inode, struct file *file);	static void * t500u_probe	(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id);static void t500u_disconnect	(struct usb_device *dev, void *ptr);static void t500u_write_bulk_callback	(struct urb *urb);/* array of pointers to our devices that are currently connected */static struct usb_t500u		*minor_table[MAX_DEVICES];/* lock to protect the minor_table structure */static DECLARE_MUTEX (minor_table_mutex);/* * File operations needed when we register this driver. * This assumes that this driver NEEDS file operations, * of course, which means that the driver is expected * to have a node in the /dev directory. If the USB * device were for a network interface then the driver * would use "struct net_driver" instead, and a serial * device would use "struct tty_driver".  */static struct file_operations t500u_fops = {	/*	 * The owner field is part of the module-locking	 * mechanism. The idea is that the kernel knows	 * which module to increment the use-counter of	 * BEFORE it calls the device's open() function.	 * This also means that the kernel can decrement	 * the use-counter again before calling release()	 * or should the open() function fail.	 *	 * Not all device structures have an "owner" field	 * yet. "struct file_operations" and "struct net_device"	 * do, while "struct tty_driver" does not. If the struct	 * has an "owner" field, then initialize it to the value	 * THIS_MODULE and the kernel will handle all module	 * locking for you automatically. Otherwise, you must	 * increment the use-counter in the open() function	 * and decrement it again in the release() function	 * yourself.	 */	owner:		THIS_MODULE,	read:		t500u_read,	write:		t500u_write,	ioctl:		t500u_ioctl,	open:		t500u_open,	release:	t500u_release,};      /* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver t500u_driver = {	name:		"t500usb",	probe:		t500u_probe,	disconnect:	t500u_disconnect,	fops:		&t500u_fops,	minor:		USB_T500U_MINOR_BASE,	id_table:	t500u_table,};/** *	usb_t500u_debug_data */static inline void usb_t500u_debug_data (const char *function, int size, const unsigned char *data){	int i;	if (!debug)		return;		printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", 		function, size);	for (i = 0; i < size; ++i) {		printk ("%.2x ", data[i]);	}	printk ("\n");}/** *	t500u_delete */static inline void t500u_delete (struct usb_t500u *dev){	minor_table[dev->minor] = NULL;	if (dev->bulk_in_buffer != NULL)		kfree (dev->bulk_in_buffer);	if (dev->bulk_out_buffer != NULL)		kfree (dev->bulk_out_buffer);	if (dev->write_urb != NULL)		usb_free_urb (dev->write_urb);	kfree (dev);}/** *	t500u_open */static int t500u_open (struct inode *inode, struct file *file){	struct usb_t500u *dev = NULL;	int subminor;	int retval = 0;		subminor = MINOR (inode->i_rdev) - USB_T500U_MINOR_BASE;	if ((subminor < 0) ||	    (subminor >= MAX_DEVICES)) {		return -ENODEV;	}	/* Increment our usage count for the module.	 * This is redundant here, because "struct file_operations"	 * has an "owner" field. This line is included here soley as	 * a reference for drivers using lesser structures... ;-)	 */	MOD_INC_USE_COUNT;	/* lock our minor table and get our local data for this minor */	down (&minor_table_mutex);	dev = minor_table[subminor];	if (dev == NULL) {		up (&minor_table_mutex);		MOD_DEC_USE_COUNT;		return -ENODEV;	}	/* lock this device */	down (&dev->sem);	/* unlock the minor table */	up (&minor_table_mutex);	/* increment our usage count for the driver */	++dev->open_count;	/* save our object in the file's private structure */	file->private_data = dev;	/* unlock this device */	up (&dev->sem);	return retval;}/** *	t500u_release */static int t500u_release (struct inode *inode, struct file *file){	struct usb_t500u *dev;	int retval = 0;	dev = (struct usb_t500u *)file->private_data;	if (dev == NULL) {		return -ENODEV;	}	/* lock our minor table */	down (&minor_table_mutex);	/* lock our device */	down (&dev->sem);	if (dev->open_count <= 0) {		retval = -ENODEV;		goto exit_not_opened;	}	if (dev->udev == NULL) {		/* the device was unplugged before the file was released */		up (&dev->sem);		t500u_delete (dev);		up (&minor_table_mutex);		MOD_DEC_USE_COUNT;		return 0;	}	/* decrement our usage count for the device */	--dev->open_count;	if (dev->open_count <= 0) {		/* shutdown any bulk writes that might be going on */		usb_unlink_urb (dev->write_urb);		dev->open_count = 0;	}	/* decrement our usage count for the module */	MOD_DEC_USE_COUNT;exit_not_opened:	up (&dev->sem);	up (&minor_table_mutex);	return retval;}/** *	t500u_read */static ssize_t t500u_read (struct file *file, char *buffer, size_t count, loff_t *ppos){	struct usb_t500u *dev;	int retval = 0;	dev = (struct usb_t500u *)file->private_data;		/* lock this object */	down (&dev->sem);

⌨️ 快捷键说明

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