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

📄 de1_drv.c

📁 linux嵌入式课程实践中的一个关于声卡驱动程序 。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * CY7C67200/300 OTG Design Example Driver * * Copyright (c) 2002, 2003 by Cypress Semiconductor Inc. *  *	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. * * * * History: * */#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>#include "de1_drv.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.3"#define DRIVER_AUTHOR "usbapps@cypress.com"#define DRIVER_DESC "CY7C67200/300 OTG Design Example Driver"#define DE1_DEVICE_NAME "DE1"/* Module paramaters */MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");/* Define these values to match your device */#define USB_OTG_DE1_VENDOR_ID	0x04b4#define USB_OTG_DE1_PRODUCT_ID	0xDE01#define DEVICE_CONNECTED		1#define DEVICE_NOTCONNECTED		0#define DE1_BUFFER_SIZE			64#define DE1_DEVICE_MAJOR		253#define A_DEV			0#define B_DEV 			1/* table of devices that work with this driver */static struct usb_device_id otg_de1_table [] = {	{ USB_DEVICE(USB_OTG_DE1_VENDOR_ID, USB_OTG_DE1_PRODUCT_ID) },	{ }					/* Terminating entry */};MODULE_DEVICE_TABLE (usb, otg_de1_table);/* Get a minor range for your devices from the usb maintainer */#define USB_OTG_DE1_MINOR_BASE	200	/* we can have up to this number of device plugged in at once */#define MAX_DEVICES		  	1#define INTERRUPT_REQ_SIZE		4	/* data request size for interrupt endpoint */#define INTERRUPT_EP_INTERVAL 	100 /* interval for interrupt endpoint in millisecond */#define DE_REPORT_INVALID	   	0#define DE_REPORT_VALID			1/* Structure to hold all of our device specific stuff */struct USB_OTG_DE1 {	struct usb_device *	udev;			/* save off the usb device pointer */	struct usb_interface *	interface;	/* the interface for this device */	unsigned char		major;			/* the starting minor number for this device */	unsigned char		connect_state;  /* connect state of the device */	unsigned char * 	int_in_buffer;	/* the buffer to receive interrupt data */	int					int_in_size;	/* the size of the receive interrupt buffer */	struct urb *		int_in_urb;  	/* the urb used to receive interrupt data */	__u8				int_in_endpointAddr;	/* the address of the interrupt in endpoint */	__u8				de_rpt_valid;	unsigned char *		de_rpt_buffer;	unsigned char * 	int_out_buffer;	/* the buffer to receive interrupt data */	int					int_out_size;	/* the size of the receive interrupt buffer */	__u8				int_out_endpointAddr;	/* the address of the interrupt in endpoint */	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 *		bulk_out_urb;  		/* the urb used to send bulk out data */	__u8				bulk_out_endpointAddr;	/* the address of the bulk in 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 */};/* local function prototypes */static ssize_t 	otg_de1_read	(struct file *file, char *buffer, size_t count, loff_t *ppos);static ssize_t 	otg_de1_write	(struct file *file, const char *buffer, size_t count, loff_t *ppos);static int 		otg_de1_ioctl  	(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int 		otg_de1_open   	(struct inode *inode, struct file *file);static int 		otg_de1_release	(struct inode *inode, struct file *file);	static void * 	otg_de1_probe	(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id);static void 	otg_de1_disconnect	(struct usb_device *dev, void *ptr);static void 	otg_de1_write_bulk_callback	(struct urb *urb);static void 	otg_de1_int_in_callback (struct urb *urb);/* DE1 structure */static struct USB_OTG_DE1 		*dev = NULL;/* * File operations needed when we register this driver. */static struct file_operations otg_de1_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:		otg_de1_read,	write:		otg_de1_write,	ioctl:		otg_de1_ioctl,	open:		otg_de1_open,	release:	otg_de1_release,};      /* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver otg_de1_driver = {	name:		"otg_de1",	probe:		otg_de1_probe,	disconnect:	otg_de1_disconnect,	fops:		&otg_de1_fops,	minor:		USB_OTG_DE1_MINOR_BASE,	id_table:	otg_de1_table,};/** *	USB_OTG_DE1_debug_data */static inline void USB_OTG_DE1_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");}/** *	otg_de1_delete */static inline void otg_de1_delete (struct USB_OTG_DE1 *dev){	/* Release buffers and URB(s) */	if (dev != NULL) {		/* Free bulk in buffer */		if (dev->bulk_in_buffer != NULL)			kfree (dev->bulk_in_buffer);		/* Free bulk out buffer and urb */		if (dev->bulk_out_buffer != NULL)			kfree (dev->bulk_out_buffer);		if (dev->bulk_out_urb != NULL)			usb_free_urb(dev->bulk_out_urb);		/* Free interrupt buffer and urb */		if (dev->int_in_buffer != NULL)			kfree (dev->int_in_buffer);		if (dev->int_in_urb != NULL)			usb_free_urb(dev->int_in_urb);		/* Free interrupt out buffer */		if (dev->int_out_buffer != NULL)			kfree (dev->int_out_buffer);		/* Free report buffer */		if (dev->de_rpt_buffer != NULL)			kfree (dev->de_rpt_buffer);		/* Free device structure */		kfree (dev);	}	}/** *	otg_de1_open */static int otg_de1_open (struct inode *inode, struct file *file){	int retval = 0;		//info ("Cypress OTG device open");	dbg(__FUNCTION__);	if (dev == NULL) {		dbg(__FUNCTION__ " - object is NULL");		return -ENODEV;	}	if (dev->open_count > 0) {		err(__FUNCTION__ " - Device already open!");		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 this device */	down (&dev->sem);	/* 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;}/** *	otg_de1_release */static int otg_de1_release (struct inode *inode, struct file *file){	int retval = 0;	if (dev == NULL) {		dbg (__FUNCTION__ " - object is NULL");		return -ENODEV;	}	/* lock our device */	down (&dev->sem);	if (dev->open_count <= 0) {		dbg (__FUNCTION__ " - device not opened");		retval = -ENODEV;		goto exit_not_opened;	}	/* 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->bulk_out_urb);		dev->open_count = 0;	}	/* decrement our usage count for the module */	MOD_DEC_USE_COUNT;exit_not_opened:	up (&dev->sem);	return retval;}/** *	otg_de1_read */static ssize_t otg_de1_read (struct file *file, char *buffer, size_t count, loff_t *ppos){	int retval = 0;	if (dev == NULL) {		dbg (__FUNCTION__ " - object is NULL");		return -ENODEV;	}//	dbg(__FUNCTION__ " - count = %d", count);	/* lock this object */	down (&dev->sem);	/* verify that the device wasn't unplugged */	if ((dev->udev == NULL) || (dev->connect_state != DEVICE_CONNECTED)){		up (&dev->sem);		return -ENODEV;	}		if (count > 0) {		/* 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);		/* If the read was successful, copy the data to userspace */		if (!retval) {			if (copy_to_user (buffer, dev->bulk_in_buffer, count))				retval = -EFAULT;			else				retval = count;		}	} else {  	    dbg(__FUNCTION__ " - read negative or zero bytes");	}	/* unlock the device */	up (&dev->sem);	return retval;}/** *	otg_de1_write */static ssize_t otg_de1_write (struct file *file, const char *buffer, size_t count, loff_t *ppos){	ssize_t bytes_written = 0;	int retval = 0;	if (dev == NULL) {		dbg (__FUNCTION__ " - object is NULL");		return -ENODEV;	}//	dbg(__FUNCTION__ " - count = %d", count);	/* lock this object */	down (&dev->sem);	/* verify that the device wasn't unplugged */	if ((dev->udev == NULL) || (dev->connect_state != DEVICE_CONNECTED)) {		retval = -ENODEV;		goto exit;	}	/* verify that we actually have some data to write */	if (count == 0) {		dbg(__FUNCTION__ " - write request of 0 bytes");		goto exit;	}	/* see if we are already in the middle of a write */	if (dev->bulk_out_urb->status == -EINPROGRESS) {		dbg (__FUNCTION__ " - already writing");		goto exit;	}   	/* we can only write as much as 1 urb will hold */	bytes_written = (ssize_t) min(count, dev->bulk_out_size);	/* copy the data from userspace into our urb */	if (copy_from_user(dev->bulk_out_buffer, buffer, 			   		   bytes_written)) {		retval = -EFAULT;		goto exit;	}	/* set up our urb */	FILL_BULK_URB(dev->bulk_out_urb, dev->udev, 

⌨️ 快捷键说明

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