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

📄 usb-c2420eb.c

📁 实现IEEE802。15。4协议的开发板的USB驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * USB Chipcon C2420 Evaluation Board - 0.1.1 * * Copyright (C) 2004 Dmitriy Korovkin <korovkin@users.sourceforge.net>, * Based on USB Skeleton byr 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 allows to use Chipcon 2420 Evaluation board  * * Thanks to Oliver Neukum and David Brownell for their help in debugging * this driver. */#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/usb.h>#include "usb-c2420eb.h" EXPORT_NO_SYMBOLS;#define CONFIG_USB_DEBUG#ifdef CONFIG_USB_DEBUG	int debug = 1;#else	int debug = 0;#endif#include "cc2420-functions.h"/* Version Information */#define DRIVER_VERSION "v0.1.1"#define DRIVER_AUTHOR "Dmitriy Korovkin, <korovkin@users.sourceforge.net>"#define DRIVER_DESC "USB C2420EB driver"/* Module paramaters */MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");/* Define these values to match your device */#define C2420EB_VENDOR_ID   0x11a0#define C2420EB_PRODUCT_ID    0xeb10#define C2420EB_PRODUCT_ID1    0xeb11/* table of devices that work with this driver */static struct usb_device_id c2420eb_table [] = {	{ USB_DEVICE(C2420EB_VENDOR_ID, C2420EB_PRODUCT_ID) },	{ USB_DEVICE(C2420EB_VENDOR_ID, C2420EB_PRODUCT_ID1) },	{ }					/* Terminating entry */};MODULE_DEVICE_TABLE (usb, c2420eb_table);/* Get a minor range for your devices from the usb maintainer */#define USB_C2420EB_MINOR_BASE 192	/* we can have up to this number of device plugged in at once */#define MAX_DEVICES	16/* the global usb devfs handle */extern devfs_handle_t usb_devfs_handle;/* local function prototypes */static ssize_t c2420eb_read (struct file *file, char *buffer, size_t count, loff_t *ppos);static ssize_t c2420eb_write (struct file *file, const char *buffer, size_t count, loff_t *ppos);static int c2420eb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int c2420eb_open (struct inode *inode, struct file *file);static int c2420eb_release (struct inode *inode, struct file *file);static void c2420eb_read_callback(struct urb *urb);	static void* c2420eb_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id);static void c2420eb_disconnect (struct usb_device *dev, void *ptr);static void c2420eb_write_bulk_callback (struct urb *urb);/* array of pointers to our devices that are currently connected */static struct c2420eb* 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 c2420eb_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: c2420eb_read,	write: c2420eb_write,	ioctl: c2420eb_ioctl,	open: c2420eb_open,	release: c2420eb_release,};      /* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver c2420eb_driver = {	name: "c2420eb",	probe: c2420eb_probe,	disconnect: c2420eb_disconnect,	fops: &c2420eb_fops,	minor: USB_C2420EB_MINOR_BASE,	id_table: c2420eb_table,};/** * c2420_submitUrb * Function submits URB for reading * dev - device descriptor * idx - index of the read buffer to use * return 0 on success -<error code> otherwise */static inline int c2420_submitReadUrb(struct c2420eb* dev, int idx){	FILL_BULK_URB(dev->read_urb, dev->udev, 		usb_rcvbulkpipe (dev->udev, PACKET_READ_PIPE),		dev->read_buffer[idx].buf, dev->readLen, 		c2420eb_read_callback, dev);	return usb_submit_urb(dev->read_urb);}/** *	c2420eb_debug_data */static inline void c2420eb_debug_data (const char* function, int size, 	const uint8_t* 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");}/** *	c2420eb_delete */static inline void c2420eb_delete (struct c2420eb* dev){	int i; //just an index variable	minor_table[dev->minor] = NULL;	dbg("Bulk in buffer deallocated: %p", dev->bulk_in_buffer);	if (dev->bulk_in_buffer != NULL)		kfree (dev->bulk_in_buffer);	for (i = 0; i < dev->readBufSize; i++)	{		dbg("Bulk in buffer deallocated: %p", dev->read_buffer[i].buf);		if (dev->read_buffer[i].buf != NULL)			kfree (dev->read_buffer[i].buf);	}	dbg("Bulk out buffer deallocated: %p", dev->bulk_out_buffer);	if (dev->bulk_out_buffer != NULL)		kfree (dev->bulk_out_buffer);	dbg("Deallocate write URB %p", dev->write_urb);	if (dev->write_urb != NULL)		usb_free_urb (dev->write_urb);	dbg("Deallocate read URB %p", dev->read_urb);	if (dev->read_urb != NULL)		usb_free_urb (dev->read_urb);	kfree (dev);}/** *	c2420eb_open */static int c2420eb_open (struct inode* inode, struct file* file){	struct c2420eb* dev = NULL; 	int subminor; //minor device number in the area of these devices	int retval = 0; //result of function calls		dbg(__FUNCTION__);	subminor = MINOR (inode->i_rdev) - USB_C2420EB_MINOR_BASE;	/*	 * Note: for now we access odd minored devicess to access communication	 * feature and we access even number to access the internal software	 */		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;	}	//We may use device only once	if (dev->open_count > 0) {		up (&minor_table_mutex);		MOD_DEC_USE_COUNT;		return -EBUSY;	}	/* lock this device */	down (&dev->sem);	/* unlock the minor table */	up (&minor_table_mutex);	if (!dev->open_count) //Start read machine	{		dev->readIdx = 0; //No data available for now		dev->writeIdx = 0; //No data available for now		dev->bufOver = 0; //Let's mark buffer is not overflowed	}	/* increment our usage count for the driver */	spin_lock(&dev->readLock);	++dev->open_count;	spin_unlock(&dev->readLock);	/* save our object in the file's private structure */	file->private_data = dev;	/* unlock this device */	up (&dev->sem);	return retval;}/** *	c2420eb_release */static int c2420eb_release (struct inode* inode, struct file* file){	struct c2420eb* dev;	int retval = 0;	dev = (struct c2420eb*)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);		c2420eb_delete (dev);		up (&minor_table_mutex);		MOD_DEC_USE_COUNT;		return 0;	}	//Switch receiver off	c2420eb_trxOff(dev);	/* decrement our usage count for the device */	spin_lock(&dev->readLock);	--dev->open_count;	spin_unlock(&dev->readLock);	if (dev->open_count <= 0) {		/* shutdown any bulk reads/writes that might be going on */		usb_unlink_urb (dev->write_urb);		usb_unlink_urb (dev->read_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;}/** * c2420eb_read_callback */static void c2420eb_read_callback(struct urb *urb){	struct c2420eb* dev = (struct c2420eb*)urb->context; //device descriptor pointer	int result; //operation result	int newIdx; //new write index	if (dev->open_count > 0 && dev->udev)	{		wake_up_interruptible(&dev->readwq);		if (urb->status == -75)			urb->status = 0;		if (urb->status != 0)			dbg("Error URB status %d", urb->status);		dev->read_buffer[dev->writeIdx].status = urb->status;		dev->read_buffer[dev->writeIdx].len = urb->actual_length;				if (urb->transfer_buffer != dev->read_buffer[dev->writeIdx].buf)			err("Diff buffers");		newIdx = (dev->writeIdx + 1) % dev->readBufSize;		if (newIdx != dev->readIdx)		{	    dev->writeIdx = newIdx;			if ((result = c2420_submitReadUrb(dev, dev->writeIdx)) < 0)		    err("Callback: Unable submit URB %d", result);		}		else		{			spin_lock(&dev->readLock);			dev->bufOver = 1;			spin_unlock(&dev->readLock);			dbg("Overflow");		}	}	return;}/** *	c2420eb_read */static ssize_t c2420eb_read (struct file* file, char* buffer, size_t count, 	loff_t* ppos){	struct c2420eb *dev;	int retval = 0;	int len; //actual length of data to read	bool bufOverflow; //if our read buffer overflows	unsigned long flags; //variable used to store registers	dev = (struct c2420eb*)file->private_data;////	dbg(__FUNCTION__ " - minor %d, count = %d", dev->minor, count);	/* lock this object */	down (&dev->sem);	wait_event_interruptible(dev->readwq, dev->readIdx != dev->writeIdx);			if (signal_pending(current))	{		up (&dev->sem);		return -EINTR;	}	if (dev->read_buffer[dev->readIdx].status == 0)	{		len = (dev->read_buffer[dev->readIdx].len > count)? count:			dev->read_buffer[dev->readIdx].len;		if (copy_to_user (buffer, dev->read_buffer[dev->readIdx].buf, len))			retval = -EFAULT;		else			retval = len;	}	else		retval = dev->read_buffer[dev->readIdx].status;	dev->readIdx = (dev->readIdx + 1) % dev->readBufSize;	spin_lock_irqsave(&dev->readLock, flags); 	bufOverflow = dev->bufOver;	spin_unlock_irqrestore(&dev->readLock, flags);	//If bufOver variable is set, 	//callback will be never called until we submit an URB	if (bufOverflow && dev->udev)	{		dev->writeIdx = (dev->writeIdx + 1) % dev->readBufSize;		dev->bufOver = 0;		if ((retval = c2420_submitReadUrb(dev, dev->writeIdx)) < 0)		{			dev->bufOver = 1;			err("Read: unable to submit URB: %d", retval);		}	}	/* unlock the device */	up (&dev->sem);	return retval;}/** *	c2420eb_write */static ssize_t c2420eb_write (struct file* file, const char* buffer, 	size_t count, loff_t* ppos){	struct c2420eb* dev;	ssize_t bytes_written = 0;	int retval = 0;	dev = (struct c2420eb*)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) 	{		retval = -ENODEV;		goto exit;	}

⌨️ 快捷键说明

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