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

📄 usbd-inline.h

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 H
字号:
/* * linux/drivers/usbd/usb-inline.h - additional USB Device Core support * * Copyright (c) 2000, 2001, 2002 Lineo * Copyright (c) 2001 Hewlett Packard * * By:  *      Stuart Lynne <sl@lineo.com>,  *      Tom Rushworth <tbr@lineo.com>,  *      Bruce Balden <balden@lineo.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 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., 675 Mass Ave, Cambridge, MA 02139, USA. * *//* * Initialize an urb_link to be a single element list. * If the urb_link is being used as a distinguished list head * the list is empty when the head is the only link in the list. */static __inline__ void urb_link_init (urb_link * ul){	if (ul) {		ul->prev = ul->next = ul;	}}/* * Detach an urb_link from a list, and set it * up as a single element list, so no dangling * pointers can be followed, and so it can be * joined to another list if so desired. * * Called from interrupt. */static __inline__ void urb_detach_irq (struct urb *urb){	if (urb) {		urb_link *ul = &urb->link;		ul->next->prev = ul->prev;		ul->prev->next = ul->next;		urb_link_init (ul);	}}/* * Return the first urb_link in a list with a distinguished * head "hd", or NULL if the list is empty.  This will also * work as a predicate, returning NULL if empty, and non-NULL * otherwise. * * Called from interrupt. */static __inline__ urb_link *first_urb_link_irq (urb_link * hd){	urb_link *nx;	if (NULL != hd && NULL != (nx = hd->next) && nx != hd) {		// There is at least one element in the list		// (besides the distinguished head).		return (nx);	}	// The list is empty	return (NULL);}/* * Return the first urb in a list with a distinguished * head "hd", or NULL if the list is empty. * * Called from interrupt. */static __inline__ struct urb *first_urb_irq (urb_link * hd){	urb_link *nx;	if (NULL == (nx = first_urb_link_irq (hd))) {		// The list is empty		return (NULL);	}	return (p2surround (struct urb, link, nx));}/* * Detach and return the first urb in a list with a distinguished * head "hd", or NULL if the list is empty. */static __inline__ struct urb *first_urb_detached_irq (urb_link * hd){	struct urb *urb;	if ((urb = first_urb_irq (hd))) {		urb_detach_irq (urb);	}	return urb;}/* * Detach and return the first urb in a list with a distinguished * head "hd", or NULL if the list is empty. * * Can be called from non-interrupt context. * */static __inline__ struct urb *first_urb_detached (urb_link * hd){	struct urb *urb;	unsigned long flags;	local_irq_save (flags);	urb = first_urb_detached_irq (hd);	local_irq_restore (flags);	return urb;}/* * Append an urb_link (or a whole list of * urb_links) to the tail of another list * of urb_links. */static __inline__ void urb_append_irq (urb_link * hd, struct urb *urb){	// XXX XXX _urb_detach(urb);	if (hd && urb) {		urb_link *new = &urb->link;#ifdef C2L_SINGLETON_ONLY		// This _assumes_ the new urb is a singleton,		// but allows it to have an uninitialized link.		//printk(KERN_DEBUG"urb_append: hd: %p n:%p p:%p new: %p n:%p p:%p\n", hd, hd->next, hd->prev, new, new->next, new->prev);		new->prev = hd->prev;		new->next = hd;		hd->prev->next = new;		hd->prev = new;#else		// This allows the new urb to be a list of urbs,		// with new pointing at the first, but the link		// must be initialized.		// Order is important here...		urb_link *pul = hd->prev;		new->prev->next = hd;		hd->prev = new->prev;		new->prev = pul;		pul->next = new;#endif	}}#if 0/** * usbd_dealloc_urb - deallocate an URB and associated buffer * @urb: pointer to an urb structure * * Deallocate an urb structure and associated data. */static __inline__ void usbd_dealloc_urb (struct urb *urb){	if (urb) {		if (urb->buffer) {			if (urb->function_instance && urb->function_instance->function_driver->ops->dealloc_urb_data) {				urb->function_instance->function_driver->ops->dealloc_urb_data (urb);			} 			else {				kfree (urb->buffer);			}		}		kfree (urb);	}}#elsevoid usbd_dealloc_urb (struct urb *urb);#endif/** * usbd_schedule_device_bh - schedule bottom half * * Schedule the device bottom half. This runs from timer tick so is equivalent * to interrupt but at lower priority. * */static __inline__ void usbd_schedule_device_bh (struct usb_device_instance *device){	if (device && (device->status != USBD_CLOSING) && !device->device_bh.sync) {#ifdef CONFIG_ARCH_PXA		usbd_device_bh (device);#else		queue_task (&device->device_bh, &tq_immediate);		mark_bh (IMMEDIATE_BH);#endif	}}/** * usbd_schedule_function_bh - schedule bottom half * * Schedule the function bottom half. This runs as a process. * */static __inline__ void usbd_schedule_function_bh (struct usb_device_instance *device){	if (device && (device->status != USBD_CLOSING) && !device->function_bh.sync) {		schedule_task (&device->function_bh);	}}#if 0/** * usbd_recv_urb_irq - process a received urb * @urb: pointer to an urb structure * * Used by a USB Bus interface driver to pass received data in a URB to the * appropriate USB Function driver via the endpoints receive queue. * * Called from interrupt. * */static __inline__ void usbd_recv_urb_irq (struct urb *urb){	if (urb) {		urb->status = RECV_OK;		urb->jiffies = jiffies;		/* XXX XXX		   {		   unsigned long flags;		   local_irq_save(flags);		 */		urb_append_irq (&(urb->endpoint->rcv), urb);		/*		   local_irq_restore(flags);		   }   		 */		usbd_schedule_device_bh (urb->device);	}}#endif/** * usbd_recycle_urb - recycle a received urb * @urb: pointer to an urb structure * * Used by a USB Function interface driver to recycle an urb. * */static __inline__ void usbd_recycle_urb (struct urb *urb){	if (urb) {		urb->actual_length = 0;		urb->status = RECV_READY;		urb->jiffies = jiffies;		{			unsigned long flags;			local_irq_save (flags);			urb_append_irq (&(urb->endpoint->rdy), urb);			local_irq_restore (flags);		}	}}/** * usbd_send_urb - submit a urb to send * @urb: pointer to an urb structure * * Used by a USB Function driver to submit data to be sent in an urb to the * appropriate USB Bus driver via the endpoints transmit queue. * * This is NOT called from interrupts. * */static __inline__ int usbd_send_urb (struct urb *urb){	if (urb && urb->endpoint && (urb->device->status == USBD_OK)) {		//urb->device->urbs_queued++;		urb->status = SEND_IN_PROGRESS;		urb->jiffies = jiffies;		{			unsigned long flags;			local_irq_save (flags);			urb_append_irq (&(urb->endpoint->tx), urb);			local_irq_restore (flags);		}		return urb->device->bus->driver->ops->send_urb (urb);	}	printk (KERN_ERR "usbd_send_urb: !USBD_OK\n");	return -EINVAL;}/* * * usbd_urb_sent_irq - tell function that an urb has been transmitted. * @urb: pointer to an urb structure * * Must be called from an interrupt or with interrupts disabled. * * Used by a USB Bus driver to pass a sent urb back to the function  * driver via the endpoints done queue. * * Called from interrupt. */static __inline__ void usbd_urb_sent_irq (struct urb *urb, int rc){	if (urb) {		urb->status = rc;		urb->jiffies = jiffies;		/* XXX XXX		   {		   unsigned long flags;		   local_irq_save(flags);		 */		urb_append_irq (&(urb->endpoint->done), urb);		/*		   local_irq_restore(flags);		   }   		 */		usbd_schedule_device_bh (urb->device);	}}/** * usbd_recv_setup - process a received urb * @urb: pointer to an urb structure * * Used by a USB Bus interface driver to pass received data in a URB to the * appropriate USB Function driver. */static __inline__ int usbd_recv_setup (struct urb *urb){	struct usb_function_instance *function_instance;#ifdef CONFIG_USBD_EP0_SUPPORT	int i;#else	int port = 0;		// XXX compound devices#endif#ifdef CONFIG_USBD_EP0_SUPPORT	if (urb && !(urb->device->status == USBD_CLOSING)) {		switch ( urb->device_request.bmRequestType & USB_REQ_TYPE_MASK ) {		case USB_REQ_TYPE_STANDARD:			function_instance = urb->device->ep0;			if ( function_instance!=NULL 			     && function_instance->function_driver->ops->recv_setup!=NULL )				return function_instance->function_driver->ops->recv_setup( urb );			return 1;		case USB_REQ_TYPE_VENDOR:		case USB_REQ_TYPE_CLASS:			for ( i=0; i<urb->device->functions; i++ ) {				function_instance = urb->device->function_instance_array + i;				if ( function_instance!=NULL &&				     function_instance->function_driver->ops->recv_setup!=NULL )					return function_instance->function_driver->ops->recv_setup( urb );			}			return 1;		default:			break;		}	}#else	if (urb && !(urb->device->status == USBD_CLOSING)) {		//printk(KERN_DEBUG"usbd_recv_setup: %p request: %x vendor: %d\n", 		//      urb, urb->device_request.bmRequestType, (urb->device_request.bmRequestType&USB_REQ_TYPE_MASK)!=0);		function_instance = ((urb->device_request.bmRequestType & USB_REQ_TYPE_MASK) == 0) ? 			urb->device->ep0 : urb->device->function_instance_array + port;		if (function_instance == NULL) {			printk (KERN_ERR "usbd_recv_setup: endpoint: %d function_instance NULL\n", 					urb->endpoint->endpoint_address);			return 1;		}		if (function_instance->function_driver->ops->recv_setup == NULL) {			printk (KERN_ERR "usbd_recv_setup: recv_setup NULL\n");			return 1;		}		return function_instance->function_driver->ops->recv_setup (urb);	}#endif	printk (KERN_ERR "usbd_recv_setup: !USBD_OK\n");	return -EINVAL;}/** * usbd_rcv_complete_irq - complete a receive * @endpoint: * @len: * @urb_bad: * * Called from rcv interrupt to complete. */static __inline__ void usbd_rcv_complete_irq (struct usb_endpoint_instance *endpoint, int len, int urb_bad){	// XXX XXX	//return;	if (endpoint) {		struct urb *rcv_urb;		//printk(KERN_ERR"usbd_rcv_complete: len: %d urb: %p\n", len, endpoint->rcv_urb);		// if we had an urb then update actual_length, dispatch if neccessary		if ((rcv_urb = endpoint->rcv_urb)) {			//printk(KERN_ERR"usbd_rcv_complete: actual: %d buffer: %d\n", 			//rcv_urb->actual_length, rcv_urb->buffer_length);			// check the urb is ok, are we adding data less than the packetsize			if (!urb_bad && (rcv_urb->device->status == USBD_OK) && (len <= endpoint->rcv_packetSize)) {				// increment the received data size				rcv_urb->actual_length += len;				// if the current received data is short (less than full packetsize) which				// indicates the end of the bulk transfer, we have received the maximum				// transfersize, or if we do not have enough room to receive another packet 				// then pass this data up to the function driver				if (((len < endpoint->rcv_packetSize) ||							(rcv_urb->actual_length >= endpoint->rcv_transferSize) || 							(rcv_urb->actual_length >= 							 (rcv_urb->buffer_length - endpoint->rcv_packetSize))))				{					//printk(KERN_ERR"usbd_rcv_complete: finishing %p\n", rcv_urb);					endpoint->rcv_urb = NULL;					rcv_urb->status = RECV_OK;					rcv_urb->jiffies = jiffies;					urb_append_irq (&(rcv_urb->endpoint->rcv), rcv_urb);					usbd_schedule_device_bh (rcv_urb->device);                                        //printk(KERN_INFO"cmplt: %p\n", rcv_urb);					rcv_urb = NULL;				}			} 			else {				printk (KERN_ERR "usbd_rcv_complete: RECV_ERROR actual: %d buffer: %d urb_bad: %d\n", 						rcv_urb->actual_length, rcv_urb->buffer_length, urb_bad);				// XXX TEST rcv_urb->actual_length = 0;				// XXX TEST printk(KERN_ERR"too large %d %d\n", len, endpoint->rcv_packetSize);				rcv_urb->actual_length = 0;				rcv_urb->status = RECV_ERROR;				rcv_urb->jiffies = jiffies;				urb_append_irq (&(rcv_urb->endpoint->rcv), rcv_urb);				usbd_schedule_device_bh (rcv_urb->device);				rcv_urb = NULL;			}		} 		else {			printk (KERN_ERR "usbd_rcv_complete: no rcv_urb!\n");		}		// if we don't have an urb see if we can get one		if (!rcv_urb) {			endpoint->rcv_urb = first_urb_detached_irq (&endpoint->rdy);		}	} 	else {		printk (KERN_ERR "usbd_rcv_complete: no endpoint!\n");	}}/** * usbd_tx_complete_irq - complete a transmit * @endpoint: * @resetart:  * * Called from tx interrupt to complete. */static __inline__ void usbd_tx_complete_irq (struct usb_endpoint_instance *endpoint, int restart){	if (endpoint) {		struct urb *tx_urb;		// if we have a tx_urb advance or reset, finish if complete		if ((tx_urb = endpoint->tx_urb)) {			if (!restart) {				//int sent = MIN(endpoint->last,endpoint->tx_packetSize);				int sent = endpoint->last;				//endpoint->sent += endpoint->last;				endpoint->sent += sent;				endpoint->last -= sent;			}			else {				endpoint->last = 0;			}			//printk(KERN_INFO"cmplt: act: %d last: %d sent: %d\n", 			//		endpoint->tx_urb->actual_length,			//		endpoint->last, endpoint->sent);			if ((tx_urb->device->status == USBD_OK) && (endpoint->tx_urb->actual_length - endpoint->sent) <= 0) {				if (endpoint->endpoint_address) {					usbd_urb_sent_irq (endpoint->tx_urb, SEND_FINISHED_OK);				}				endpoint->tx_urb = NULL;				endpoint->last = endpoint->sent = 0;				//printk(KERN_INFO"cmplt: finished\n");			}		}		// if we do not have a tx_urb see if we can get one		if (endpoint->endpoint_address && !endpoint->tx_urb && 				(endpoint->tx_urb = first_urb_detached_irq (&endpoint->tx))) 		{			endpoint->last = endpoint->sent = 0;		}	} 	else {		printk (KERN_ERR "usbd_tx_complete_irq: no endpoint!\n");	}}

⌨️ 快捷键说明

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