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

📄 usersu.c

📁 USb in User space, a kernel module that use usb layer
💻 C
📖 第 1 页 / 共 3 页
字号:
				}				PRINT("}");			}			blocks[blockId] = (void*) db;			ritorno = 0;		}	}	db = (struct DoubleBuffT*) blocks[blockId];	if (log) {PRINT("db(%p)",db);}	/* However allocate urb separate from data. usb_buffer_alloc seem to be more complicated,	 * so we use to separe kmalloc() of mdata from data one's.*/	if (ritorno==0) {		int size, allp;		char *bf;		struct urb *urb, *curb;/*		dma_addr_t dma;*/		struct urbDataT* places;		urb = NULL; bf = NULL; curb = NULL; places = NULL;		size = ISOC_BYTESxP;		allp = ISOC_NUMBOfP;		urb = kzalloc(ISOC_URBSPRE*getUrbSize(allp), KMALLOC_FLAG);		ritorno = -ENOMEM;		if (urb) {			if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_IN)				places = db->istream.places;			else				places = db->ostream.places;			for (l=0; l<ISOC_URBSPRE; l++) {				curb = getUrbAddr(urb,l,allp);				usb_init_urb(curb);				places[l].urb=curb;			}			if (log) {				PRINT("places=0x%p urb={",places);				for (l=0; l<ISOC_URBSPRE; l++) {					PRINT("%p ",curb);				}				PRINT("}");			}			bf = kzalloc(ISOC_URBSPRE*size*allp,KMALLOC_FLAG)/*usb_buffer_alloc(dev,ISOC_URBSPRE*size*allp,KMALLOC_FLAG,&dma)*/;			if (bf) {				for (l=0; l<ISOC_URBSPRE; l++) {					curb = getUrbAddr(urb,l,allp);					curb->transfer_buffer = bf + getUrbSize(allp)*l;/*					curb->transfer_dma = dma;					if (dma != (~(dma_addr_t) 0))						curb->transfer_dma += getUrbSize(allp)*l;*/					/* alloc_urb, if !capable for dma transfer, ret dma=-1.*/				}				if (log) {					PRINT("buff={");					for (l=0; l<ISOC_URBSPRE; l++) {						PRINT("%p ",curb->transfer_buffer);					}					PRINT("}");				}				ritorno = 0;			}		}		if (ritorno == 0) {			int k;			if (log) {PRINT("urb: filling.");}			for (l=0; l<ISOC_URBSPRE; l++) {			curb = getUrbAddr(urb,l,allp);			if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_IN) {				curb->pipe = usb_rcvisocpipe(dev,endpoint->bEndpointAddress);				curb->context=(void*) &(db->istream);			} else {				curb->pipe = usb_sndisocpipe(dev,endpoint->bEndpointAddress);				curb->context=(void*) &(db->ostream);			}			curb->interval = endpoint->bInterval;			curb->transfer_buffer_length=allp*size;			curb->number_of_packets=allp;			curb->complete=DoubleBuff_complete;			curb->dev=dev;			curb->transfer_flags=URB_ISO_ASAP;						for (k=0; k<allp; k++) {				curb->iso_frame_desc[k].offset=k*size;				curb->iso_frame_desc[k].length=size;				curb->iso_frame_desc[k].actual_length=0;				curb->iso_frame_desc[k].status=0;			}#if 0			/* 			 * Here we only setup 'static' data for urb.			 * read()'ll be only actor that'll start urb.			 */			/* 			 * Start only input urb. If start output, we have error -22 = -EINVAL,			 * so probe'll stop with error.			 */			if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_IN) {				nurb_submitted++;				ritorno=usb_submit_urb(curb, GFP_KERNEL);				PRINT("submit_urb...%d,",ritorno);			}#endif			} /* for (l=0, l<3, l++) */		}	}	return ritorno;}void release_nowork(struct kref *kref) {}static int DoubleBuff_disco(int blockId, struct usb_endpoint_descriptor* endpoint) {	int ritorno;	stop_submit=1;	ritorno = 0;	if (ritorno==0) {		int size, allp;		char *bf;		struct urb* urb;		struct DoubleBuffT* db;		int l;		urb = NULL; bf = NULL; db = NULL;		size = ISOC_BYTESxP;		allp = ISOC_NUMBOfP;		db = (struct DoubleBuffT*) blocks[blockId];		if (log) {PRINT("db=blocks[%d]=0x%p",blockId,blocks[blockId]);}		if (db) {			char buf[300];			struct urbDataT* ud;			ud = NULL;			if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_IN) {				ud = &(db->istream.places[0]);				buf[0]='i';			} else {				ud = &(db->ostream.places[0]);				buf[0]='u';			}			if (log) {				PRINT("CLEAR ALL %s PLACE %p!",buf[0]=='i'?"INPUT":"OUTPUT",ud);				dumpUrbD(ud,buf,280); buf[280]='\x0'; PRINT("%s",buf);			}			urb = ud->urb;			ud->urb = NULL;		}		if (urb) bf = urb->transfer_buffer;		if (bf) {			if (log) {PRINT("CLEAR BUFF!");}			kfree(bf);/*			usb_buffer_free(dev, ISOC_URBSPRE*size*allp, bf, urb->transfer_dma);*/		}		if (urb) {			if (log) {PRINT("CLEAR URB!");}			for (l=0; l<ISOC_URBSPRE; l++)				kref_put(&(urb[l].kref), release_nowork);			kfree(urb);		}		if (((db->istream.places)[0]).urb == NULL && ((db->ostream.places)[0]).urb == NULL) {			if (log) {PRINT("CLEAR MAIN STRUCT!");}			kfree(db);			usbdo_deleteFile(endpoint->bmAttributes);			blocks[blockId] = NULL;		}	}	{		int l;		for (l=10; l<19; l++)			if (blocks[l])				break;		if (l==20) {			PRINT("set_interface()");			ritorno = usb_set_interface(dev,1,0);		}	}	return ritorno;}#if 0 /* To use with struct.pl.*/struct list_head {	struct list_head *next;	struct list_head *prev;};struct timer_list {	struct list_head list;	int expires;	int data;	void *function;};struct spinlock_t {	int lock;};struct dma_addr_t {	int dma_addr;};struct iso_packet_descriptor {	int offset;	int length;	int actual_length;	int status;};struct urb {	spinlock_t lock;	void* hcipriv;	struct list_head urb_list;	struct urb* urb_next;	struct usb_device* dev;	int pipe;	int status;	int transfer_flags;	void *transfer_buffer;	dma_addr_t transfer_dma;	int transfer_buffer_length;	int actual_length;	int bandwidth;	char *setup_packet;	dma_addr_t setup_dma;	int start_frame;	int numer_of_packets;	int interval;	int error_count;	int timeout;	void* context;	void* complete;	struct iso_packet_descriptor iso_frame_desc[0];};#endif#if 0struct usu_deviceT {	struct urb* intr_urb;	struct urb* isoc_urb;	struct urb* isoc_usc_urb;	struct dataQ_T isoc_usc_dataQ;	struct dataQ_T isoc_usc_mdataQ;	char isoc_data[3*50000];	struct usb_device *dev;	struct timer_list tempo;	struct dataQ_T isocQ_ing;	struct dataQ_T isocQ_usc;	struct dataQ_T bulkQ_ing;	struct dataQ_T intrQ_ing;	struct semaphore bulkSem;	struct semaphore intrSem;	struct proc_dir_entry* isobf;	struct proc_dir_entry* isocf;	struct proc_dir_entry* procf;	struct proc_dir_entry* procd;/*	struct circBuff intrBuffer;*/	struct endP_T isoc_usc_ep;	int intIsStopped;	int nOfZero;	spinlock_t dataav_lock;} usu_device;#endif/* About 600 char.*/int USBDo_dumpUrb(struct urb *urb,char* buf,int len) {	int l=0;	Snprintf("urb:%p",urb);	if (urb) {	Snprintf("dev:%p",urb->dev);	Snprintf("pipe:%08X",urb->pipe);	Snprintf("stat:%d",urb->status);	Snprintf("transf_flag:%08X",urb->transfer_flags);	Snprintf("transf_buff:%p",urb->transfer_buffer);	Snprintf("transf_dma:%08x",urb->transfer_dma);	Snprintf("transf_blen:%d",urb->transfer_buffer_length);	Snprintf("actual_len:%d",urb->actual_length);	Snprintf("setup_pack:%p",urb->setup_packet);	Snprintf("start_fram:%p",(void*)urb->start_frame);	Snprintf("numOf_pack:%d",urb->number_of_packets);	Snprintf("interval:%d",urb->interval);	Snprintf("erro_cnt:%d",urb->error_count);	Snprintf("context:%p",urb->context);	Snprintf("complete:%p",urb->complete);	if (urb->number_of_packets<1000 && urb->number_of_packets>0) {		int k,trx_min,trx_max,err_min,err_max;		trx_min=trx_max=0; /* !correct but adjusted in a little.*/		err_min=err_max=0;		for (k=0;k<urb->number_of_packets;k++) {			int act_len=urb->iso_frame_desc[k].actual_length;			int err_cur=urb->iso_frame_desc[k].status;			if (k) {			if (act_len>trx_max) trx_max=act_len;			if (act_len<trx_min) trx_min=act_len;			if (err_cur>err_max) err_max=err_cur;			if (err_cur<err_min) err_min=err_cur;			} else {trx_min=act_len;trx_max=act_len; err_min=err_max=err_cur;}		}		Snprintf("iso:actual_len(min,max)=(%d,%d) status(min,max)=(%d,%d)",trx_min,trx_max,err_min,err_max);	}	}	return l;}/* Send bytes syncronously to usb subsystem. *  ogf = {'\1:5'} *  ocf = ... *  data, len contain remaining bytes, *  dest = {'i', 'b'}, mean interrupt, bulk. */int USBDo_send(/*unsigned char ocf, unsigned char ogf, */struct usb_device* dv, char dest, unsigned char* data, int len) {	int ritorno=0;	int ret_len=0;	if (dev) {		if (log) PRINT("USBDo_send(dest=%c,len=%d)...",dest,len);		if (dest=='i') {		ritorno = usb_control_msg(dv,					  usb_sndctrlpipe(dev, 0),					  0,USB_TYPE_CLASS,0,0,					  data, len,					  0/* wait undef, no kill_urb() called. USB_COMMAND_TIMEOUT*/);		ret_len=ritorno;		} else if (dest=='b') {		ritorno=usb_bulk_msg(dv,				     usb_sndbulkpipe(dev, 2),				     data, len, 				     &ret_len,				     0/*5000*/);		} else {		PRINT("USBDo_send(): unrecognized dest %x\n",dest);		}		if (log) PRINT("Ok(ret %d, len %d).", ritorno,ret_len);	} else PRINT("Device4USBDo !yet recognized. No send were done.\n");	if (ritorno>=0)		ritorno=ret_len;	return ritorno;}/*  * <0 mean !found, * >=0 mean found, one can use result as index interface[]. */static unsigned int usb_if_to_ifnum(struct usb_interface *intf) {	int ritorno=-1;	int i;	struct usb_device *dev=interface_to_usbdev(intf);	for (i=0; (i<dev->actconfig->desc.bNumInterfaces) && (ritorno==-1); i++) {		if (dev->actconfig->interface[i]==intf)			ritorno=i;	}	return ritorno;}enum IntfWorkT {PROBE, DISCONNECT}; int USBDo_IntfWork(struct usb_interface *intf, enum IntfWorkT work) {	int ritorno,l;	char* tmp=NULL;	ritorno=0;	{ /* Just print header.*/		switch (work) {			case PROBE: tmp="probe"; break;			case DISCONNECT: tmp="disco"; break;			default:    tmp="unkno"; break;		}		if (dev==NULL) {			dev=usb_get_dev(interface_to_usbdev(intf));			PRINT("\nUSBDo_%s. (%x,%x)", tmp,dev->descriptor.idVendor, dev->descriptor.idProduct);		}		PRINT("\nUSBDo_%s: (dev=0x%p, interface=%d curAltSet=%d numAltSet=%d)",tmp,dev,usb_if_to_ifnum(intf),intf->cur_altsetting->desc.bAlternateSetting,intf->num_altsetting);	}	/* 1) For each endpoint provided by device.*/	for (l=0; (l<intf->cur_altsetting->desc.bNumEndpoints) && (ritorno==0) ; l++) {		struct usb_endpoint_descriptor *endpoint; 		endpoint=&(intf->cur_altsetting->endpoint[l].desc);		PRINT("\n\t(EndPAddr,bmAttr,ifNum,currAltSet,numAltSet)=(0x%x,%d,%d,%d).",			endpoint->bEndpointAddress,			endpoint->bmAttributes,			usb_if_to_ifnum(intf),			intf->num_altsetting);		/* 2) Endpoint specific code: start with searching if endpoint will to be managed.*/		{			int k;			int managed;			managed = 0;			for (k=0; k<sizeof(topol)/sizeof(struct LinkT); k++) {/*				PRINT("Comparing (%x vs %x).",endpoint->bmAttributes,topol[k].blockId[0]);*/				if (topol[k].blockId[0] == endpoint->bEndpointAddress) {					int blockId = topol[k].blockId[1];					PRINT("\n\tEndpoint managed.");					managed++;					/* 3) determine type and create object.*/					switch (work) {						case PROBE:							if (blockId>=0  && blockId<10) 							ritorno = BuffRead_probe(blockId,endpoint);							if (blockId>=10 && blockId<20)							ritorno = DoubleBuff_probe(blockId,endpoint);							break;						case DISCONNECT:							if (blockId>=0  && blockId<10) 							ritorno = BuffRead_disco(blockId,endpoint);							if (blockId>=10 && blockId<20)							ritorno = DoubleBuff_disco(blockId,endpoint);							break;					}					PRINT("ret (%d)%s",ritorno,ritorno?"ERR":"Ok");				} /* if (endpoint==managed).*/			} /* for each endpoint_managed.*/			if (!managed) PRINT("\n\tSkipped(!managed).");		} /* Endpoint specific code.*/	} /* for each endpoint exposed by device.*/	PRINT("\n/USBDo_%s=%d",tmp,ritorno);	return ritorno;}int USBDo_probe(struct usb_interface *intf, const struct usb_device_id *id_table) {	return USBDo_IntfWork(intf, PROBE);}void USBDo_deregister(struct usb_interface *intf) {	USBDo_IntfWork(intf, DISCONNECT);}/* Without this kernel never call .probe.*/MODULE_DEVICE_TABLE (usb, idta);static struct usb_driver USBDo = {	.owner = THIS_MODULE,	.name = "USBDo",	.probe = USBDo_probe, 	.disconnect = USBDo_deregister,	/*.driver_list = {0, 0},	 * without this module is loaded but !linked with device.	 */	.id_table = idta,};/* static struct usb_driver USBDo = { "name", &USBDo_probe, &USBDo_disconnect,NULL,NULL,0,NULL,NULL,NULL }; *//*  * ========================== * === Module load/unload ===  * ==========================  */int a(void) {	int ritorno=-ENOMEM;	PRINT("\n === Cerco di inserire USBDo!... === ");	ritorno=usb_register(&USBDo);	PRINT("%s.",ritorno?"Err!":"Ok");	PRINT("ret (%d)", ritorno);	return ritorno;}void b(void) {	PRINT("\nDeregistro USBDo!...");	usb_deregister(&USBDo);/*	USBDo_deregister(); without interface, we do not know what delete. NULL can be delete all. *	Is >simple to remeber all intf during probe. Perhaps usb layer have a list for such object. * *	First deregister, then wait urb to complete. If invert operation urb never complete.*/	PRINT("Ok");	{		int k;#if 0		int blocksAllocated=0;		for (k=0; k<sizeof(blocks)/sizeof(blocks[0]); k++)			if (blocks[k])				blocksAllocated++;		if (blocksAllocated==0) {			PRINT("Removing /proc/USBDo");			remove_proc_entry("USBDo",NULL);			usbdo_fs = NULL;		}#endif		PRINT("Waiting for %d urb to complete...",nurb_submitted);		k=100;		while (nurb_submitted>0 && k--)			mdelay(10);				PRINT("Ok");		if (nurb_submitted) PRINT(" %d URB REMAIN SUBMITTED.",nurb_submitted);	}}module_init(a);module_exit(b);

⌨️ 快捷键说明

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