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

📄 usb.c

📁 linux下的USB主机端骨架程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 skel_disconnect. *			Thanks to Pete Zaitcev for the fix. * 2001_09_04 - 0.5 - fix devfs bug in skel_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*//* Use our own dbg macro *//***#undef dbg#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)*//* Version Information */#define DRIVER_VERSION "v0.1"#define DRIVER_AUTHOR "ChenMian"#define DRIVER_DESC "USB Test Driver"/* Module paramaters *//***MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");*///Declare a wait queueDECLARE_WAIT_QUEUE_HEAD(rwq);DECLARE_WAIT_QUEUE_HEAD(wwq);//int wwake = 0 , rwake = 0;/* Define these values to match your device */#define USB_SKEL_VENDOR_ID	0x04b4#define USB_SKEL_PRODUCT_ID	0x8613/* table of devices that work with this driver */static struct usb_device_id skel_table [] = {	{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },	{ }					/* Terminating entry */};MODULE_DEVICE_TABLE (usb, skel_table);/* Get a minor range for your devices from the usb maintainer */#define USB_SKEL_MINOR_BASE	0	/* we can have up to this number of device plugged in at once */#define MAX_DEVICES		16/* Structure to hold all of our device specific stuff */struct usb_skel {	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 */	struct urb *		read_urb;		/* the urb used to recieve data */	__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 skel_read	(struct file *file, char *buffer, size_t count, loff_t *ppos);static ssize_t skel_write	(struct file *file, const char *buffer, size_t count, loff_t *ppos);static int skel_ioctl		(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int skel_open		(struct inode *inode, struct file *file);static int skel_release		(struct inode *inode, struct file *file);	static void * skel_probe	(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id);static void skel_disconnect	(struct usb_device *dev, void *ptr);static void skel_write_bulk_callback	(struct urb *urb);static void skel_read_bulk_callback	(struct urb *urb);/* array of pointers to our devices that are currently connected */static struct usb_skel		*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 skel_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:		skel_read,	write:		skel_write,	ioctl:		skel_ioctl,	open:		skel_open,	release:	skel_release,};      /* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver skel_driver = {	name:		"skeleton",	probe:		skel_probe,	disconnect:	skel_disconnect,	fops:		&skel_fops,	minor:		USB_SKEL_MINOR_BASE,	id_table:	skel_table,};/** *	usb_skel_debug_data *//*** static inline void usb_skel_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");}*//** *	skel_delete */static inline void skel_delete (struct usb_skel *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);	if (dev->read_urb != NULL)		usb_free_urb (dev->read_urb);	kfree (dev);}/** *	skel_open */static int skel_open (struct inode *inode, struct file *file){	printk("***The open function has been called !***\n");		struct usb_skel *dev = NULL;	int subminor;	int retval = 0;	//	dbg(__FUNCTION__);	subminor = MINOR (inode->i_rdev) - USB_SKEL_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;}/** *	skel_release */static int skel_release (struct inode *inode, struct file *file){	struct usb_skel *dev;	int retval = 0;	dev = (struct usb_skel *)file->private_data;	if (dev == NULL) {//		dbg (__FUNCTION__ " - object is NULL");		return -ENODEV;	}//	dbg(__FUNCTION__ " - minor %d", dev->minor);	/* lock our minor table */	down (&minor_table_mutex);	/* lock our device */	down (&dev->sem);	if (dev->open_count <= 0) {//		dbg (__FUNCTION__ " - device not opened");		retval = -ENODEV;		goto exit_not_opened;	}	if (dev->udev == NULL) {		/* the device was unplugged before the file was released */		up (&dev->sem);		skel_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;}/** *	skel_read */static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t *ppos){	printk("$$$ The read function has been called ! =%d $$$\n",count);	struct usb_skel *dev;	int retval = 0;	dev = (struct usb_skel *)file->private_data;	//	dbg(__FUNCTION__ " - minor %d, count = %d", dev->minor, count);	/* lock this object */	down (&dev->sem);	/* verify that the device wasn't unplugged */	if (dev->udev == NULL) {		up (&dev->sem);		return -ENODEV;	}		/* do an immediate bulk read to get data from the device *//***	retval = usb_bulk_msg (dev->udev,			       usb_rcvbulkpipe (dev->udev, 						dev->bulk_in_endpointAddr),			       dev->bulk_in_buffer, dev->bulk_in_size,			       &count, HZ*10);*/	usb_fill_bulk_urb(dev->read_urb, dev->udev, 		      usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),		      dev->read_urb->transfer_buffer, dev->bulk_in_size,

⌨️ 快捷键说明

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