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

📄 usersu.c

📁 USb in User space, a kernel module that use usb layer
💻 C
📖 第 1 页 / 共 3 页
字号:
		ritorno=usb_submit_urb(urb, KMALLOC_FLAG);		if (ritorno==0) nurb_submitted++;		} /* if urb allocated.*/	}	return ritorno;}/* Stop when deallocating first endpoint. * * ING  USC	Ordine Probe	Ordine Disconnect * 0x81 0x00	0x81		0x81 * 0x82 0x02	0x02, 0x82	0x02, 0x82 * * This is because in 0x81 0x00, 0x00 is already probed by usbcore. * Now seem !2be a problem. */static int BuffRead_disco(int blockId, struct usb_endpoint_descriptor* endpoint) {	stop_submit=1;	if (blocks[blockId]) {		FsEntryT* data;		char* nome;		char *buf;		struct BuffReadT* br;		struct dataQ_T *dq;		void* context;		data = (FsEntryT*) blocks[blockId]; 		nome = NULL; buf = NULL; context = NULL; br = NULL; dq = NULL;				br = (struct BuffReadT*) data->data;		if (br) buf=br->dq.data;		if (br) context = br->dq.context;				if (buf) kfree(buf);		if (br) kfree(br);		usbdo_deleteFile(endpoint->bmAttributes);		if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_IN) {			struct urb *urb;			char* bf;			urb = (struct urb*) context; bf = NULL;			PRINT("Stopping&deallocating input urb...");			if (urb) bf = urb->transfer_buffer;			usb_unlink_urb(urb);			usb_free_urb(urb);			if (bf) usb_buffer_free(0,0,bf,0);		}		blocks[blockId] = NULL;	}	return 0;}/* This object simply help to produce a 'continuous' stream of data. * Any decoder will be in user space or as hierarchical file operation. * * Internal organization remember c++ stl io: there is a method, perhaps * underflow(), that c++ engine call when strbuf have no data. * * Instead of overload stateInfo, is better preferred new object oriented  * interface container_of() etc. stateInfo exist for simplify little work. */struct ioStreamT {	/* Related to a places of bytes:*/	struct urbDataT places[ISOC_URBSPRE]; 	/* n of urb per direction.*/	int curPlace;			  	/* Only need if >1 place. */	/* To 'immediately' wake-up user world when space/data available.*/	struct semaphore wait4data;	int (*underflow)(struct ioStreamT *i);	atomic_t mutuaEsclusione;	int lastErr;	union {int bytesRx; int bytesTx;};	/* Statistical info.*/	union {int nOfNotsync_read; int nOfNotsync_write;};	int nOfNotsync_intr;	int nOfUrbCompleted;	/* Statistical info, status oriented.*/	int nOfSubmit;};struct DoubleBuffT {	struct ioStreamT istream;	struct ioStreamT ostream;};void DoubleBuff_complete(struct urb *urb,struct pt_regs* regs) {	int ritorno,l,len;	static int lastLen = -1;	static int lastRet = 1;	static int howmRep = 0;	ritorno = 0; len = 0;		nurb_submitted--;	for (l=0; l<urb->number_of_packets; l++) {		ritorno = ritorno?ritorno:urb->iso_frame_desc[l].status;		len += urb->iso_frame_desc[l].actual_length;	}	if (ritorno == lastRet && len == lastLen) {/*		if (log && howmRep==0) {PRINT("isoc_complete(len,status)=(%d,%d).",len,ritorno);}*/		if (log && howmRep==1) {PRINT("...");}		if (howmRep<=1) howmRep++;	} else {		if (log) {PRINT("isoc_complete(len,status)=(%d,%d).",len,ritorno);}		lastLen = len;		lastRet = ritorno;		howmRep = 1;	}	if (!stop_submit) {		/* wake up user only if (status,len)!=(0,0), to avoid heavy load on CPU		 *  - module become unremovable,		 *  - process cat become unkillable.		 *		 * If (!data present) & (!error) silently resubmit_urb()		 * else		 * Stop & wakeup to request attention2who manage bytes.		 */				struct ioStreamT* iost = (struct ioStreamT*) urb->context;		iost->nOfSubmit--;		iost->nOfUrbCompleted++;		if (ritorno==0 && len==0) {			urb->dev=dev;			urb->status=0;			ritorno=usb_submit_urb(urb, KMALLOC_FLAG);			if (ritorno==0) {				nurb_submitted++;				iost->nOfSubmit++;			} else {				PRINT("usb_submit()=NOK!(ret=%d)",ritorno);			}		} else {			if (ritorno==0) iost->bytesRx += len;			up(&(iost->wait4data));		}		iost->lastErr = ritorno;	} else {		PRINT("shutdown.");	}}#if 0/* return * 	0 if ok, * 	<0 if some error. * * If called by complete, queue urb|data. * */void complete_isoc2(struct urb *urb, struct pt_regs *regs) {	int ritorno=0;	struct ioStreamT *ioSt;	int diri;	nurb_submitted--;	diri=usb_pipein(urb->pipe);	ioSt=(struct ioStreamT*) urb->context;	ioSt->nOfUrbCompleted++;	if (stop_submit>0) {		/*usu_device.intIsStopped--;*/		ritorno=-ENODEV;	} else if (!urb) {		ritorno=-EFAULT;	} else {		/* 1) Acquire lock. If fail => return,		 * the owner are working also4us. Ret true if count reach 0.*/		if (!atomic_dec_and_test(&ioSt->mutuaEsclusione)) {			ioSt->nOfNotsync_intr++;			ritorno=-EAGAIN;		}		if (ritorno==0) {			/* iStream:			 * 2-a) if (active=EMPTY)*(backg=EMPTY)*(urb=DONE) => start urb			 * 2-b) if (active=EMPTY)*(backg=FULL )*(urb=DONE) => swap,signal,start urb.			 * urb state={DONE, RUNNING, ERROR}			 *			 * oStream:			 *  active=FULL = curP==curL			 *  back  =EMPTY= status=0 			 * 2-a) if (active=FULL )*(backg=EMPTY)*(urb=DONE) => start urb.*/						if (ioSt->curL==ioSt->curP && urb->status==0) {				int isocLen,l;				isocLen=0;				for (l=0; l<urb->number_of_packets; l++) isocLen+=urb->iso_frame_desc[l].actual_length;/*				iStream.curL=ISOC_NUMBOfP*ISOC_BYTESxP;*/				switch (isocLen) {					case ISOC_NUMBOfP*ISOC_BYTESxP:						{							for (l=0; l<urb->number_of_packets; l++) 								urb->iso_frame_desc[l].actual_length=0;						}					/* Called much probably by read()/write().*/					case 0:						{							if ((diri && isocLen) || !diri) {								ioSt->nOfSwap++;								urb->transfer_buffer=ioSt->curAct;								ioSt->curAct=ioSt->curBac;								ioSt->curBac=urb->transfer_buffer;								ioSt->curP=0;							/* All this hypo is in order2avoid unneeded signal/wait							 * 							 * Read case:							 * if isocLen==0=> must !signal:							 *  - called by Read()							 *  - is the first time,							 *  - urb start later,							 *  - Read()'ll immediatly call wait()							 *							 *  Write case:							 * However signal:							 *  - we know that other Write() must wait							 *  - we don't know if current Write() has							 *    consumend len>0 so return without wait							 *  Sol: now we take 2 (signal,wait)							 */								up(&ioSt->wait4data);							}						/*}						{*/							urb->dev=dev;							urb->status=0;							ritorno=usb_submit_urb(urb,KMALLOC_FLAG);							break;						}					default: {ritorno=-EIO; break;}				}			}		}				atomic_inc(&ioSt->mutuaEsclusione);	}	if (ritorno<0) {		err("complete_isoc2(): ret %d.\n",ritorno);		if (ritorno!=-EAGAIN) ioSt->lastErr=ritorno;	}}#endif/* Return >0 number of bytes. *        <0 error code. */int DoubleBuff_read(char* page, unsigned int count, void* data){	int ritorno=0;	static int stop_on_err = 1;	while (ritorno==0) {		/* Only here we start urb.*/		int l;		struct ioStreamT* ist = &(((struct DoubleBuffT*) data)->istream);		int newCurPlace = -1; /* !valid value: the first submit()Ok will initialize it.*/		int urbRunning = 0;		int stopSearch = 0;		/* 		 * 1) On urb !running, read() & restart()		 *		 * TODO: 1) when there was no more data, here we wait next read() to restart urb.		 */		for (l=0; (l<ISOC_URBSPRE) && (ritorno<=0 && !stopSearch) ; l++) {			struct urbDataT* ud = &(ist->places[(ist->curPlace + l) % ISOC_URBSPRE]);			if (log) {PRINT("\n(l=%d,i=%d)",l,(ist->curPlace+l)%ISOC_URBSPRE);}			ritorno = readUrbD(ud, page, count);			if (log) {PRINT("\nreadUrbd[%d](count=%d)=%d",(ist->curPlace+l)%ISOC_URBSPRE,count,ritorno);}						urbRunning = (ritorno == -EINPROGRESS)/* || (ritorno == -EXDEV)*/;			stopSearch = (ritorno<0 && stop_on_err) && !urbRunning;			/* Dump error on urb.*/			if (ritorno<0 && !urbRunning) {				char buf[500];				PRINT("readUrb() found an urb with error(%d).",ritorno);				USBDo_dumpUrb(ud->urb,buf,480); buf[480]='\x0'; PRINT("%s",buf);			}			if (ritorno>0 || urbRunning || stopSearch) { /* do nothing.*/ } else { /* try2submit urb.*/ 				int k;				ud->urb->status = 0;				ud->urb->actual_length = 0;				for (k=0; k<ud->urb->number_of_packets; k++) {					ud->urb->iso_frame_desc[k].status = 0;					ud->urb->iso_frame_desc[k].actual_length = 0;				}				resetUrbD(ud);				nurb_submitted++;				DoubleBuff_complete(ud->urb,NULL);				ritorno = ritorno<0?ritorno:ist->lastErr;				if (newCurPlace == -1) 					newCurPlace = (ist->curPlace + l) % ISOC_URBSPRE;			}		}		/* 2) wait for data if 		 * 	state(k)  	ing(k)			 * 	((no data)  and (some urb started)) ||		 * 	 (some data)		 *		 * if newCurPlace = curPlace mean no urb submitted because:		 *  - have data 2 read()	ret>0		 *  - all urb submitted fail.	ret<0		 *		 * ret >0 mean:		 *  - (some urb have data) && (some previous stopped urb,if any, have been successfully restarted).		 * ret=0 mean:		 *  - (all urb have no data) && (all urb dave been restarted successfully).		 * ret=-EINPROGRESS if all urb is in progress, so curPlace==newCurPlace => no wait4data => return -EINP.		 * 		 * ret<0, if (!stop_on_err) mean:		 *  - all urb have error on it/during submit().		 * ret<0, if (stop_on_err) mean:		 *  - at least one urb have error on it/during submit().		 *		 * However, if some urb started and have no data, wait for completion.		 */		if (ritorno == -EINPROGRESS)			ritorno = 0;		if (ritorno<=0)			ritorno=down_interruptible(&(ist->wait4data));		ist->curPlace = newCurPlace==-1? ist->curPlace : newCurPlace;		if (log) {PRINT("<while (curPlace,ret)=(%d,%d)>",ist->curPlace, ritorno);}	}	if (ritorno<0)		err("readIsoc2(): ret %d.\n",ritorno);	return ritorno;}int DoubleBuff_write(char *buffer, unsigned int count, void *data){	int ritorno=0;	static int stop_on_err = 1;	while (ritorno==0 && count>0) {		/* Only here we start urb.*/		int l;		struct ioStreamT* ost = &(((struct DoubleBuffT*) data)->ostream);		int newCurPlace = -1; /* !valid value: the first submit()Ok will initialize it.*/		int urbRunning = 0;		int stopSearch = 0;		/* 		 * 1) On urb !running, write() & if EOB => restart()		 */		for (l=0; (l<ISOC_URBSPRE) && (ritorno<=0 && !stopSearch) ; l++) {			struct urbDataT* ud = &(ost->places[(ost->curPlace + l) % ISOC_URBSPRE]);			if (log) {PRINT("\n(l=%d,i=%d)",l,(ost->curPlace+l)%ISOC_URBSPRE);}			ritorno = writeUrbD(ud, (char*)buffer, count);			if (log) {PRINT("\nwriteUrbd[%d](count=%d)=%d",(ost->curPlace+l)%ISOC_URBSPRE,(int)count,ritorno);}						urbRunning = (ritorno == -EINPROGRESS)/* || (ritorno == -EXDEV)*/;			stopSearch = (ritorno<0 && stop_on_err) && !urbRunning;			/* Dump error on urb.*/			if (ritorno<0 && !urbRunning) {				char buf[500];				PRINT("writeUrb() found an urb with error(%d).",ritorno);				USBDo_dumpUrb(ud->urb,buf,480); buf[480]='\x0'; PRINT("%s",buf);			}			if (ritorno>0 || urbRunning || stopSearch) { /* do nothing.*/ } else { /* try2submit urb.*/ 				int k;				ud->urb->status = 0;				ud->urb->actual_length = 0;				for (k=0; k<ud->urb->number_of_packets; k++) {					ud->urb->iso_frame_desc[k].status = 0;					ud->urb->iso_frame_desc[k].actual_length = 0;				}				resetUrbD(ud);				nurb_submitted++;				DoubleBuff_complete(ud->urb,NULL);				ritorno = ritorno<0?ritorno:ost->lastErr;				if (newCurPlace == -1)					newCurPlace = (ost->curPlace + l + 1) % ISOC_URBSPRE;			}		}		/* 2) wait for data if 		 */		/* All urb is in progress. wait4data.*/		if (ritorno == -EINPROGRESS)			ritorno=down_interruptible(&(ost->wait4data));		ost->curPlace = newCurPlace==-1? ost->curPlace : newCurPlace;		if (log) {PRINT("<while (curPlace,ret)=(%d,%d)>",ost->curPlace, ritorno);}	}	if (ritorno<0)		err("writeIsoc2(): ret %d.\n",ritorno);	return ritorno;}	#if 0	while (ritorno==0) {		int spaceAv=1;		if (!atomic_dec_and_test(&oStream.mutuaEsclusione)) oStream.nOfNotsync_write++;		else {		/* 1) See howMany bytes we can write.*/		ritorno=oStream.curL-oStream.curP;		if (ritorno>count) ritorno=count;		/* 2-a) If bytes2Write  =>return avail data.*/		if (ritorno>0) {			memcpy(oStream.curAct + oStream.curP, buffer, ritorno); 			oStream.curP+=ritorno;			oStream.bytesTx+=ritorno;		}		spaceAv=(oStream.curL>oStream.curP);		}		atomic_inc(&oStream.mutuaEsclusione);		/* 2-b) Wait if no space av.		if (ritorno==0 && count)*/		/* 2-c) If we have fill a place => start urb.*/		if (!spaceAv) {			complete_isoc2(usu_device.isoc_usc_urb,0);			/* -EINTR if interrupted.*/			ritorno=down_interruptible(&oStream.wait4data);		}		if (oStream.lastErr<0) ritorno=oStream.lastErr;	}	if (ritorno<0)		err("writeIsoc2(): ret %d.\n",ritorno);	return ritorno;}#endifstatic int getUrbSize(int isocFrame) {	return (sizeof(struct urb)+isocFrame*sizeof(struct usb_iso_packet_descriptor));}static struct urb* getUrbAddr(struct urb* urbBase, int index, int isocFrame) {	char* ret = (char*) urbBase;	ret += index*getUrbSize(isocFrame);	return (struct urb*) ret;}static int DoubleBuff_probe(int blockId, struct usb_endpoint_descriptor* endpoint) {	int ritorno;	struct DoubleBuffT* db;	int l;	ritorno = 0; db = NULL;	if (blocks[blockId]==0) {		PRINT("set_interface()");		ritorno = usb_set_interface(dev,1,5);		if (ritorno == 0) {			PRINT("Ok");			db = (struct DoubleBuffT*)kzalloc(sizeof(struct DoubleBuffT),KMALLOC_FLAG);			ritorno = -ENOMEM;			/* Initialize some data.*/			memset(&(db->istream),0,sizeof(struct ioStreamT));			sema_init(&(db->istream.wait4data),0);			atomic_set(&(db->istream.mutuaEsclusione),1);			memset(&(db->ostream),0,sizeof(struct ioStreamT));			sema_init(&(db->ostream.wait4data),0);			atomic_set(&(db->ostream.mutuaEsclusione),1);		}		if (db) {			/* Create procfs entry. (common code).*/			FsEntryT* data;			data = usbdo_createFile(endpoint->bmAttributes);			if (data) {				data->data = (void*) db;				data->read_proc = DoubleBuff_read;				data->write_proc = DoubleBuff_write;				/*data->owner = THIS_MODULE;*/			}			for (l=0; l<ISOC_URBSPRE; l++) {				resetUrbD(&(db->istream.places[l]));				resetUrbD(&(db->ostream.places[l]));			}			if (log) {				PRINT("i={");				for (l=0; l<ISOC_URBSPRE; l++) {					PRINT("%p ",&(db->istream.places[l]));				}				PRINT("} o={");				for (l=0; l<ISOC_URBSPRE; l++) {					PRINT("%p ",&(db->ostream.places[l]));

⌨️ 快捷键说明

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