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

📄 usersu.c

📁 USb in User space, a kernel module that use usb layer
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * usu.c * * Author : Lionetti Salvatore <salvatorelionetti@yahoo.it> * License: GPL * *  "Usb in User Space" driver try to hide usb work, exposing simple object like file with only one reader/writer. *  Have different struct for different behavior: *   - isoc: reduce work during complete(), preallocating n urb, just switch between urb, *   	     start input endpoint when were data requested. *   - other: BuffReadT, organize data in ram area. *   	      start input endpoint on probe *   Now is !supported more interface of same type. *   File exposed are sequential, with no lseek()/ppos. * *   Interrupt(0x81) & Command(0x00) endpoint are linked in only one entity (now name='intr'). * * 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 program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include<linux/module.h>#include<linux/kernel.h> /* Added in 2.6.15.*/#include<linux/usb.h>#include<linux/timer.h>#include<linux/proc_fs.h>#include<linux/slab.h> 		/* To have SLAB_ATOMIC.		*/#include<asm/uaccess.h> 	/*  	   copy_from_user().	*/#include<linux/delay.h> 	/* 	   mdelay(msec).	*//*#include<linux/sched.h>  	* 	   sched_clock().	Link !found.*//*#include<asm/spinlock.h> 	*	   spin_lock*(). 	Have redefinition error.*/#include<asm/semaphore.h>	/* 	   semaphore.    	*/#include"msgq.h"		/*	   dataQ_T		*/#include"urbAsByteStream.h"	/* 	   urbDataT.		*/#include"diag.h"#include"util.h"		/*	   PRINT(), Snprintf()  *//* One can choice /proc or /dev */#include"usu_config.h"	/* Now only select underlyng fs.*/MODULE_LICENSE("GPL");int commandEcho=0;#define ISOC_URBSPRE 3#define ISOC_BYTESxP 17#define ISOC_NUMBOfP 3#define DATAQ_NUMOFB 5000/*  * ==========START=========== * ===     Usb driver     ===  * ==========================  */static struct LinkT topol[]={	{{0x00, 6}}, /* Never pass under our probe() because already created.*/	{{0x81, 6}},	{{0x02, 7}},	{{0x82, 7}},	{{0x03, 10}},	{{0x83, 10}},};struct usb_device_id idta[] = {	{USB_DEVICE(0x50d,0x012)}, /* Belkin.*/	{USB_DEVICE(0xa12,0x001)}, /* Surecom.*/	{USB_DEVICE(1131,1001)},   /* Sitel.*//*	{USB_DEVICE(0xea0,0x2168)}, * UsbPen.*/	{}};/*  * ===========END============ * ===     Usb driver     ===  * ==========================  */static void* blocks[]={	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,	/* 0..9   BuffRead.*/			NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,};	/* 10..19 DoubleBuff.*//* Utility function.*/char* usb_getTypeStr(int addr) {	int type = (addr & USB_ENDPOINT_XFERTYPE_MASK);	char* typeStr[] = {"ctrl","isoc","bulk","intr","unkn"};	if (type<0 && type>3) type = 4;	return typeStr[type];}char* usb_getDirStr(int addr) {	int diri = (addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;	return (diri?"ing":"usc");}int USBDo_send(struct usb_device* dev, char dest, unsigned char* data, int len);int USBDo_dumpUrb(struct urb *urb,char* buf,int len);static struct usb_device* dev=NULL;static int nurb_submitted = 0;static int stop_submit = 0;static int log = 0;/* Some common code.*/#define KMALLOC_FLAG GFP_ATOMIC/* 				procfs * blocks[l]->data (void*) * 	    ->name * 	    ->read_proc * 	    ->write_proc * 	    ->owner */ typedef int (*usbdo_fsProcT)(char *buf, unsigned int len, void *data);typedef struct _FsEntryT {	void* data;	char name[100];	usbdo_fsProcT read_proc;	usbdo_fsProcT write_proc;		int isOpen; /* 1 when file is opened.*/} FsEntryT;FsEntryT usbdo_fsEntry[16];static int usbdo_nofFiles=0;#ifdef USE_PROC_FSstatic struct file_operations usbdo_fsOps;static struct proc_dir_entry* usbdo_fs=NULL;static FsEntryT* usbdo_createFile(int bmAttr) {	FsEntryT* data;	struct proc_dir_entry* pe;	char* nome;	data = NULL; pe = NULL; nome = NULL;	PRINT("Creating procfs...");	nome = usb_getTypeStr(bmAttr);	if (!usbdo_fs) usbdo_fs = proc_mkdir("USBDo",NULL);	if (usbdo_fs) pe = create_proc_entry(nome,0666,usbdo_fs);	if (pe) {		pe->proc_fops = &usbdo_fsOps;		/*		pe->read_proc = ProcFsRead;		pe->write_proc = ProcFsWrite; NULL as default.*/		pe->owner = THIS_MODULE;		pe->data = (void*)usbdo_nofFiles;				data = &usbdo_fsEntry[usbdo_nofFiles];		strncpy(data->name, nome, 100);		usbdo_nofFiles++;	}	return data;}static void usbdo_deleteFile(int bmAttr) {	char* nome = NULL;	PRINT("Deleting procfs...");	nome = usb_getTypeStr(bmAttr);	remove_proc_entry(nome,usbdo_fs);	usbdo_nofFiles--;	if (usbdo_nofFiles==0) {		PRINT("Removing /proc/USBDo");		remove_proc_entry("USBDo",NULL);		usbdo_fs = NULL;	}}#if 0int ProcFsRead( char* page, char** start, 		off_t off, int count,		int *eof, void* data){	int ritorno = usbdo_fsEntry[(int)data].read_proc(page,count,usbdo_fsEntry[(int)data].data);	if (ritorno<0) *eof=1;	else *start=(char*)ritorno;	return ritorno;}int ProcFsWrite( struct file *file,		 const char *buffer,		 unsigned long count,		 void *data){	return usbdo_fsEntry[(int)data].write_proc(buffer,count,usbdo_fsEntry[(int)data].data);}#endifstatic ssize_t ProcFsRead(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos){	struct inode *inode = file->f_dentry->d_inode;	struct proc_dir_entry * pe;	int ritorno;		pe = PDE(inode);	ritorno = usbdo_fsEntry[(int)pe->data].read_proc(buf,nbytes,usbdo_fsEntry[(int)pe->data].data);	if (log) PRINT("ProcFsRead(%d)=%d",nbytes,ritorno);	return ritorno;}static ssize_t ProcFsWrite(struct file *file, const char __user *buffer, size_t count, loff_t *ppos){	struct inode *inode = file->f_dentry->d_inode;	struct proc_dir_entry * pe;	int ritorno;		pe = PDE(inode);	ritorno = usbdo_fsEntry[(int)pe->data].write_proc((char*)buffer,count,usbdo_fsEntry[(int)pe->data].data);	if (log) PRINT("ProcFsWrite(%d)=%d",count,ritorno);	return ritorno;}static struct file_operations usbdo_fsOps = {	.read		= ProcFsRead,	.write		= ProcFsWrite,};#else#include <linux/devfs_fs_kernel.h>#define USU_CHARFS_MAJOR 238static struct file_operations usbdo_fsOps;static FsEntryT* usbdo_createFile(int bmAttr) {	FsEntryT* data;	char* nome;	int ret = -EBUSY;	data=&usbdo_fsEntry[usbdo_nofFiles]; nome = NULL;	if (usbdo_nofFiles==0) {		ret = register_chrdev(238,"usu",&usbdo_fsOps);		if (ret==0) ret = devfs_mk_dir("usu");	}	if (ret == 0) {		PRINT("Creating fsentry...");		nome = usb_getTypeStr(bmAttr);		strncpy(data->name, nome, 100);		/* Select from 	usb pipe -> 	minor.		 * 		0		0		 * 		1		2		 * 		2		1		 * 		3		0		 */		usbdo_nofFiles++;	}	return data;}static void usbdo_deleteFile(int bmAttr) {	PRINT("Deleting fsentry...");	usbdo_nofFiles--;	if (usbdo_nofFiles==0) {		PRINT("Removing /dev/");		devfs_remove("usu");		unregister_chrdev(238, "usu");	}}static int CharFsOpen(struct inode *inode, struct file *file){	PRINT("open(inode 0x%p, file 0x%p) priv(%p)",inode,file,file->private_data);	if (file->private_data==NULL) {	       file->private_data = (void*) MINOR(inode->i_rdev);	       PRINT("->(%p)",file->private_data);	}	PRINT(" (maj,min)=(%d,%d)",MAJOR(inode->i_rdev), MINOR(inode->i_rdev));	PRINT("\n");	return 0;}static int CharFsRelease(struct inode *inode, struct file *file){	PRINT("close(inode 0x%p, file 0x%p) priv(%p)",inode,file,file->private_data);	if (file->private_data) {	       file->private_data = (void*) 0;	       PRINT("->(%p)",file->private_data);	}	PRINT(" (maj,min)=(%d,%d)",MAJOR(inode->i_rdev), MINOR(inode->i_rdev));	PRINT("\n");	return 0;}static ssize_t CharFsRead(struct file *file,  char __user *buffer, size_t count, loff_t *ppos){	int minor = (int) file->private_data;	return usbdo_fsEntry[minor].read_proc(buffer,count,usbdo_fsEntry[minor].data);}static ssize_t CharFsWrite(struct file *file,  const char __user *buffer, size_t count, loff_t *ppos){	int minor = (int) file->private_data;	return  usbdo_fsEntry[minor].write_proc((char*)buffer,count,usbdo_fsEntry[minor].data);}static struct file_operations usbdo_fsOps={	.owner =	THIS_MODULE,	.open =		CharFsOpen,	.read =         CharFsRead,	.write =        CharFsWrite,	.release =	CharFsRelease,};#endifstruct BuffReadT {	struct dataQ_T dq;	atomic_t mutuaEsclusione;};int BuffRead_read(char* page, unsigned int count, void* data){	int ritorno=0;	int whoR=0/*(int)data*/;	struct BuffReadT *br=(struct BuffReadT*)data;	if (count>0) ritorno=readQ(&(br->dq),whoR,page,count);	if (log) PRINT("readQ(count=%d,spare=%d)=%d",count,br->dq.spar[whoR],ritorno);		if (ritorno<0)		err("readBulk(): ret %d.",ritorno);	return ritorno;}/* From /kernel/sched.c: to show stack free space. This is a local symbolvoid show_state() {}*/int BuffRead_write(char *buffer, unsigned int count, void *data){	int ritorno;	struct BuffReadT* br=(struct BuffReadT*)data;	char* kdata;		ritorno = -ENOMEM;	kdata=kzalloc(count,KMALLOC_FLAG);	if (kdata) {		ritorno = -EFAULT;		if (copy_from_user(kdata,buffer,count)==0) {			char cmd = kdata[0];			if (cmd=='q') {				char buf[3000];				int len=2900;				dumpQ(&(br->dq),buf,len);				/*show_state();*/				buf[len]='\x0';				PRINT("%s",buf);				log = (log + 1) % 2;				PRINT("log %s.",log?"enabled":"disabled");			} else if (cmd=='r') {				reseQ(&(br->dq));			} else if (cmd=='t') {				testUrbD();			} else if (cmd=='Q') {				testQ();			} else {				int l;				char dest;				FsEntryT* pe;				struct urb* urb; 				pe = NULL; dest = 'u' /* unkn */; urb = (struct urb*) br->dq.context;				if (commandEcho) writeQ(&(br->dq),kdata,count);				for (l=0; l<sizeof(blocks)/sizeof(blocks[0]); l++) {					pe = blocks[l];					if (pe && pe->data == (void*) br) {						dest = usb_getTypeStr(pipe2addr(urb->pipe))[0];					}				}				ritorno=USBDo_send(dev,dest,kdata,count);			}		}		kfree(kdata);	}	return ritorno;	}void BuffRead_complete(struct urb *ingr_urb,struct pt_regs* regs) {	int ritorno=ingr_urb->status;	struct BuffReadT* br=(struct BuffReadT*)ingr_urb->context;	char buf[160];	int len=150;		int addr = pipe2addr(ingr_urb->pipe);	char* dire = usb_getDirStr(addr);	char* tipo = usb_getTypeStr(addr);	nurb_submitted--;		/* 	 * So if any error, but some data, however remember bytes.	 * return error ?.	 */		if (log) PRINT("%s %s!",dire,tipo);	if (ritorno==0 && dire[0]=='i' && ingr_urb->actual_length>0) {		ritorno = writeQ(&(br->dq), ingr_urb->transfer_buffer, ingr_urb->actual_length);		if (log) PRINT("writeQ()=%d",ritorno);	}	if (log) {		USBDo_dumpUrb(ingr_urb,buf,len);		buf[len]='\x0'; PRINT("%s",buf);	}	/* For kernel 2.4 is !necessary.*/	if (dire[0]=='i' && !stop_submit) {		ingr_urb->dev=dev;		ingr_urb->status=0;		ritorno=usb_submit_urb(ingr_urb, KMALLOC_FLAG);		if (ritorno==0) nurb_submitted++;		if (log) PRINT("(resubmit res=%d)",ritorno);	}}static int BuffRead_probe(int blockId, struct usb_endpoint_descriptor* endpoint) {	int ritorno = 0;	/* 3-1) Create object if !already.*/	if (blocks[blockId]==NULL) {		FsEntryT* data;		struct BuffReadT *br;		char *buf;		buf = NULL; br = NULL;		data = usbdo_createFile(endpoint->bmAttributes);		if (data)  br  = kzalloc(sizeof(*br)	,KMALLOC_FLAG);		if (br)    buf = kzalloc(DATAQ_NUMOFB	,KMALLOC_FLAG);		if (data) data->data = (void*) br;		if (br)	  {			initQ(&(br->dq),buf,DATAQ_NUMOFB); br->dq.wrSrc = KERN;			atomic_set(&(br->mutuaEsclusione),1);		}		if (data) {			data->read_proc = BuffRead_read;			data->write_proc = BuffRead_write;			/*data->owner = THIS_MODULE;*/		}		blocks[blockId] = /*ritorno?NULL:*/(void*) data;			if (data==NULL)			ritorno=-ENOENT;		else 	if (buf==NULL)			ritorno=-ENOMEM;		PRINT("%s",ritorno?"NOOK!!!":"OK");	}	/* 3-2) Start input endpoint (only for !isoc transfer).*/	if (ritorno==0)	if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_IN) {		FsEntryT* data;		struct urb *urb;		int pipe;		char* bf;		int size;/*		dma_addr_t dma;*/		urb = NULL; bf = NULL; size=0;		data = (FsEntryT*) blocks[blockId];		PRINT("Allocating&start input urb...");		urb = usb_alloc_urb(0, KMALLOC_FLAG);		((struct BuffReadT*)(data->data))->dq.context = (void*) urb;		if (urb) {			size = le16_to_cpu(endpoint->wMaxPacketSize);			bf = kzalloc(size,KMALLOC_FLAG);/*usb_buffer_alloc(dev,size,GFP_KERNEL*SLAB_ATOMIC*,&dma);*/		}				if (urb==NULL || bf==NULL)			ritorno = -ENOMEM;		if (ritorno==0) {		switch (endpoint->bmAttributes){			/*			case USB_ENDPOINT_XFER_CONTROL:			{				pipe=usb_rcvintpipe(dev,endpoint->bEndpointAddress);				break;			}*/			case USB_ENDPOINT_XFER_INT:			{				pipe=usb_rcvintpipe(dev,endpoint->bEndpointAddress);				usb_fill_int_urb(urb,dev,pipe,bf,size,BuffRead_complete,NULL,endpoint->bInterval);				break;			}			case USB_ENDPOINT_XFER_BULK:			{				pipe=usb_rcvbulkpipe(dev,endpoint->bEndpointAddress);				usb_fill_bulk_urb(urb,dev,pipe,bf,size,BuffRead_complete,NULL);				break;			}			default: break;		}		urb->context = data->data;

⌨️ 快捷键说明

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