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

📄 auerswald.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Values of urb->status or results of usb_submit_urb():0		Initial, OK-EINPROGRESS	during submission until end-ENOENT		if urb is unlinked-ETIMEDOUT	Transfer timed out, NAK-ENOMEM		Memory Overflow-ENODEV		Specified USB-device or bus doesn't exist-ENXIO		URB already queued-EINVAL		a) Invalid transfer type specified (or not supported)		b) Invalid interrupt interval (0n256)-EAGAIN		a) Specified ISO start frame too early		b) (using ISO-ASAP) Too much scheduled for the future wait some time and try again.-EFBIG		Too much ISO frames requested (currently uhci900)-EPIPE		Specified pipe-handle/Endpoint is already stalled-EMSGSIZE	Endpoint message size is zero, do interface/alternate setting-EPROTO		a) Bitstuff error		b) Unknown USB error-EILSEQ		CRC mismatch-ENOSR		Buffer error-EREMOTEIO	Short packet detected-EXDEV		ISO transfer only partially completed look at individual frame status for details-EINVAL		ISO madness, if this happens: Log off and go home-EOVERFLOW	babble*//* check if a status code allows a retry */static int auerswald_status_retry (int status){	switch (status) {	case 0:	case -ETIMEDOUT:	case -EOVERFLOW:	case -EAGAIN:	case -EPIPE:	case -EPROTO:	case -EILSEQ:	case -ENOSR:	case -EREMOTEIO:		return 1; /* do a retry */	}	return 0;	/* no retry possible */}/* Completion of asynchronous write block */static void auerchar_ctrlwrite_complete (struct urb * urb, struct pt_regs *regs){	pauerbuf_t bp = (pauerbuf_t) urb->context;	pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));	dbg ("auerchar_ctrlwrite_complete called");	/* reuse the buffer */	auerbuf_releasebuf (bp);	/* Wake up all processes waiting for a buffer */	wake_up (&cp->bufferwait);}/* Completion handler for dummy retry packet */static void auerswald_ctrlread_wretcomplete (struct urb * urb, struct pt_regs *regs){        pauerbuf_t bp = (pauerbuf_t) urb->context;        pauerswald_t cp;	int ret;        dbg ("auerswald_ctrlread_wretcomplete called");        dbg ("complete with status: %d", urb->status);	cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));	/* check if it is possible to advance */	if (!auerswald_status_retry (urb->status) || !cp->usbdev) {		/* reuse the buffer */		err ("control dummy: transmission error %d, can not retry", urb->status);		auerbuf_releasebuf (bp);		/* Wake up all processes waiting for a buffer */		wake_up (&cp->bufferwait);		return;	}	/* fill the control message */	bp->dr->bRequestType = AUT_RREQ;	bp->dr->bRequest     = AUV_RBLOCK;	bp->dr->wLength      = bp->dr->wValue;	/* temporary stored */	bp->dr->wValue       = cpu_to_le16 (1);	/* Retry Flag */	/* bp->dr->index    = channel id;          remains */	usb_fill_control_urb (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0),                          (unsigned char*)bp->dr, bp->bufp, le16_to_cpu (bp->dr->wLength),		          auerswald_ctrlread_complete,bp);	/* submit the control msg as next paket */	ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1);        if (ret) {        	dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);        	bp->urbp->status = ret;        	auerswald_ctrlread_complete (bp->urbp, NULL);    	}}/* completion handler for receiving of control messages */static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs){        unsigned int  serviceid;        pauerswald_t  cp;        pauerscon_t   scp;        pauerbuf_t    bp  = (pauerbuf_t) urb->context;	int ret;        dbg ("auerswald_ctrlread_complete called");	cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));	/* check if there is valid data in this urb */        if (urb->status) {		dbg ("complete with non-zero status: %d", urb->status);		/* should we do a retry? */		if (!auerswald_status_retry (urb->status)		 || !cp->usbdev		 || (cp->version < AUV_RETRY)                 || (bp->retries >= AU_RETRIES)) {			/* reuse the buffer */			err ("control read: transmission error %d, can not retry", urb->status);			auerbuf_releasebuf (bp);			/* Wake up all processes waiting for a buffer */			wake_up (&cp->bufferwait);			return;		}		bp->retries++;		dbg ("Retry count = %d", bp->retries);		/* send a long dummy control-write-message to allow device firmware to react */		bp->dr->bRequestType = AUT_WREQ;		bp->dr->bRequest     = AUV_DUMMY;		bp->dr->wValue       = bp->dr->wLength; /* temporary storage */		// bp->dr->wIndex    channel ID remains		bp->dr->wLength      = cpu_to_le16 (32); /* >= 8 bytes */		usb_fill_control_urb (bp->urbp, cp->usbdev, usb_sndctrlpipe (cp->usbdev, 0),  			(unsigned char*)bp->dr, bp->bufp, 32,	   		auerswald_ctrlread_wretcomplete,bp);		/* submit the control msg as next paket */       		ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1);       		if (ret) {               		dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);               		bp->urbp->status = ret;               		auerswald_ctrlread_wretcomplete (bp->urbp, regs);		}                return;        }        /* get the actual bytecount (incl. headerbyte) */        bp->len = urb->actual_length;        serviceid = bp->bufp[0] & AUH_TYPEMASK;        dbg ("Paket with serviceid %d and %d bytes received", serviceid, bp->len);        /* dispatch the paket */        scp = cp->services[serviceid];        if (scp) {                /* look, Ma, a listener! */                scp->dispatch (scp, bp);        }        /* release the paket */        auerbuf_releasebuf (bp);	/* Wake up all processes waiting for a buffer */	wake_up (&cp->bufferwait);}/*-------------------------------------------------------------------*//* Handling of Interrupt Endpoint                                    *//* This interrupt Endpoint is used to inform the host about waiting   messages from the USB device.*//* int completion handler. */static void auerswald_int_complete (struct urb * urb, struct pt_regs *regs){        unsigned long flags;        unsigned  int channelid;        unsigned  int bytecount;        int ret;        pauerbuf_t   bp = NULL;        pauerswald_t cp = (pauerswald_t) urb->context;        dbg ("%s called", __FUNCTION__);	switch (urb->status) {	case 0:		/* success */		break;	case -ECONNRESET:	case -ENOENT:	case -ESHUTDOWN:		/* this urb is terminated, clean up */		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);		return;	default:		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);		goto exit;	}        /* check if all needed data was received */	if (urb->actual_length < AU_IRQMINSIZE) {                dbg ("invalid data length received: %d bytes", urb->actual_length);		goto exit;        }        /* check the command code */        if (cp->intbufp[0] != AU_IRQCMDID) {                dbg ("invalid command received: %d", cp->intbufp[0]);		goto exit;        }        /* check the command type */        if (cp->intbufp[1] != AU_BLOCKRDY) {                dbg ("invalid command type received: %d", cp->intbufp[1]);		goto exit;        }        /* now extract the information */        channelid = cp->intbufp[2];        bytecount = (unsigned char)cp->intbufp[3];        bytecount |= (unsigned char)cp->intbufp[4] << 8;        /* check the channel id */        if (channelid >= AUH_TYPESIZE) {                dbg ("invalid channel id received: %d", channelid);		goto exit;        }        /* check the byte count */        if (bytecount > (cp->maxControlLength+AUH_SIZE)) {                dbg ("invalid byte count received: %d", bytecount);		goto exit;        }        dbg ("Service Channel = %d", channelid);        dbg ("Byte Count = %d", bytecount);        /* get a buffer for the next data paket */        spin_lock_irqsave (&cp->bufctl.lock, flags);        if (!list_empty (&cp->bufctl.free_buff_list)) {                /* yes: get the entry */                struct list_head *tmp = cp->bufctl.free_buff_list.next;                list_del (tmp);                bp = list_entry (tmp, auerbuf_t, buff_list);        }        spin_unlock_irqrestore (&cp->bufctl.lock, flags);        /* if no buffer available: skip it */        if (!bp) {                dbg ("auerswald_int_complete: no data buffer available");                /* can we do something more?		   This is a big problem: if this int packet is ignored, the		   device will wait forever and not signal any more data.		   The only real solution is: having enough buffers!		   Or perhaps temporary disabling the int endpoint?		*/		goto exit;        }	/* fill the control message */        bp->dr->bRequestType = AUT_RREQ;	bp->dr->bRequest     = AUV_RBLOCK;	bp->dr->wValue       = cpu_to_le16 (0);	bp->dr->wIndex       = cpu_to_le16 (channelid | AUH_DIRECT | AUH_UNSPLIT);	bp->dr->wLength      = cpu_to_le16 (bytecount);	usb_fill_control_urb (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0),                          (unsigned char*)bp->dr, bp->bufp, bytecount,		          auerswald_ctrlread_complete,bp);        /* submit the control msg */        ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);        if (ret) {                dbg ("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret);                bp->urbp->status = ret;                auerswald_ctrlread_complete( bp->urbp, NULL);		/* here applies the same problem as above: device locking! */        }exit:	ret = usb_submit_urb (urb, GFP_ATOMIC);	if (ret)		err ("%s - usb_submit_urb failed with result %d",		     __FUNCTION__, ret);}/* int memory deallocation   NOTE: no mutex please!*/static void auerswald_int_free (pauerswald_t cp){	if (cp->inturbp) {		usb_free_urb(cp->inturbp);		cp->inturbp = NULL;	}	kfree(cp->intbufp);	cp->intbufp = NULL;}/* This function is called to activate the interrupt   endpoint. This function returns 0 if successful or an error code.   NOTE: no mutex please!*/static int auerswald_int_open (pauerswald_t cp){        int ret;	struct usb_host_endpoint *ep;	int irqsize;	dbg ("auerswald_int_open");	ep = cp->usbdev->ep_in[AU_IRQENDP];	if (!ep) {		ret = -EFAULT;  		goto intoend;    	}	irqsize = le16_to_cpu(ep->desc.wMaxPacketSize);	cp->irqsize = irqsize;	/* allocate the urb and data buffer */        if (!cp->inturbp) {                cp->inturbp = usb_alloc_urb (0, GFP_KERNEL);                if (!cp->inturbp) {                        ret = -ENOMEM;                        goto intoend;                }        }        if (!cp->intbufp) {                cp->intbufp = (char *) kmalloc (irqsize, GFP_KERNEL);                if (!cp->intbufp) {                        ret = -ENOMEM;                        goto intoend;                }        }        /* setup urb */        usb_fill_int_urb (cp->inturbp, cp->usbdev,			usb_rcvintpipe (cp->usbdev,AU_IRQENDP), cp->intbufp,			irqsize, auerswald_int_complete, cp, ep->desc.bInterval);        /* start the urb */	cp->inturbp->status = 0;	/* needed! */	ret = usb_submit_urb (cp->inturbp, GFP_KERNEL);intoend:        if (ret < 0) {                /* activation of interrupt endpoint has failed. Now clean up. */                dbg ("auerswald_int_open: activation of int endpoint failed");                /* deallocate memory */                auerswald_int_free (cp);        }        return ret;}/* This function is called to deactivate the interrupt   endpoint. This function returns 0 if successful or an error code.   NOTE: no mutex please!*/static void auerswald_int_release (pauerswald_t cp){        dbg ("auerswald_int_release");        /* stop the int endpoint */        if (cp->inturbp)                usb_kill_urb (cp->inturbp);        /* deallocate memory */        auerswald_int_free (cp);}/* --------------------------------------------------------------------- *//* Helper functions                                                      *//* wake up waiting readers */static void auerchar_disconnect (pauerscon_t scp){        pauerchar_t ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext)));	dbg ("auerchar_disconnect called");	ccp->removed = 1;	wake_up (&ccp->readwait);}/* dispatch a read paket to a waiting character device */static void auerchar_ctrlread_dispatch (pauerscon_t scp, pauerbuf_t bp){	unsigned long flags;        pauerchar_t ccp;        pauerbuf_t newbp = NULL;        char * charp;        dbg ("auerchar_ctrlread_dispatch called");        ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext)));        /* get a read buffer from character device context */        spin_lock_irqsave (&ccp->bufctl.lock, flags);        if (!list_empty (&ccp->bufctl.free_buff_list)) {                /* yes: get the entry */                struct list_head *tmp = ccp->bufctl.free_buff_list.next;                list_del (tmp);                newbp = list_entry (tmp, auerbuf_t, buff_list);        }        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);        if (!newbp) {                dbg ("No read buffer available, discard paket!");                return;     /* no buffer, no dispatch */        }        /* copy information to new buffer element           (all buffers have the same length) */        charp = newbp->bufp;        newbp->bufp = bp->bufp;        bp->bufp = charp;

⌨️ 快捷键说明

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