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

📄 hc_simple.c

📁 linux客户机函数定义的实际例子
💻 C
📖 第 1 页 / 共 3 页
字号:
 * (hci->intr_list, hci->bulk_list, hci->iso_list, hci->ctrl_list)
 * For every endpoint the head URB of the queued URBs is linked to one of 
 * those lists.
 * 
 * The rest of the queued URBs of an endpoint are linked into a 
 * private URB list for each endpoint. (hci_dev->ed [endpoint_io].urb_queue)
 * hci_dev->ed [endpoint_io].pipe_head .. points to the head URB which is 
 * in one of the active URB lists.
 * 
 * The index of an endpoint consists of its number and its direction.
 * 
 * The state of an intr and iso URB is 0. 
 * For ctrl URBs the states are US_CTRL_SETUP, US_CTRL_DATA, US_CTRL_ACK
 * Bulk URBs states are US_BULK and US_BULK0 (with 0-len packet)
 * 
 **************************************************************************/

/***************************************************************************
 * Function Name : qu_urb_timeout
 *
 * This function is called when the URB timeout. The function unlinks the 
 * URB. 
 *
 * Input: lurb: URB 
 *
 * Return: none  
 **************************************************************************/
#ifdef HC_URB_TIMEOUT
static void qu_urb_timeout (unsigned long lurb)
{
	struct urb *urb = (struct urb *) lurb;

	DBGFUNC ("enter qu_urb_timeout\n");
	urb->transfer_flags |= USB_TIMEOUT_KILLED;
	hci_unlink_urb (urb);
}
#endif

/***************************************************************************
 * Function Name : qu_pipeindex
 *
 * This function gets the index of the pipe.   
 *
 * Input: pipe: the urb pipe 
 *
 * Return: index  
 **************************************************************************/
static inline int qu_pipeindex (__u32 pipe)
{
	DBGFUNC ("enter qu_pipeindex\n");
	return (usb_pipeendpoint (pipe) << 1) | (usb_pipecontrol (pipe) ? 0 : usb_pipeout (pipe));
}

/***************************************************************************
 * Function Name : qu_seturbstate
 *
 * This function set the state of the URB.  
 * 
 * control pipe: 3 states -- Setup, data, status
 * interrupt and bulk pipe: 1 state -- data    
 *
 * Input: urb = USB request block data structure 
 *        state = the urb state
 *
 * Return: none  
 **************************************************************************/
static inline void qu_seturbstate (struct urb * urb, int state)
{
	DBGFUNC ("enter qu_seturbstate\n");
	urb->pipe &= ~0x1f;
	urb->pipe |= state & 0x1f;
}

/***************************************************************************
 * Function Name : qu_urbstate
 *
 * This function get the current state of the URB.  
 * 
 * Input: urb = USB request block data structure 
 *
 * Return: none  
 **************************************************************************/
static inline int qu_urbstate (struct urb * urb)
{

	DBGFUNC ("enter qu_urbstate\n");

	return urb->pipe & 0x1f;
}

/***************************************************************************
 * Function Name : qu_queue_active_urb
 *
 * This function adds the urb to the appropriate active urb list and set
 * the urb state.
 * 
 * There are four active lists: isochoronous list, interrupt list, 
 * control list, and bulk list.
 * 
 * Input: hci = data structure for the host controller 
 *        urb = USB request block data structure 
 *        ed = endpoint descriptor
 *
 * Return: none  
 **************************************************************************/
static inline void qu_queue_active_urb (hci_t * hci, struct urb * urb, epd_t * ed)
{
	int urb_state = 0;
	DBGFUNC ("enter qu_queue_active_urb\n");
	switch (usb_pipetype (urb->pipe)) {
	case PIPE_CONTROL:
		list_add (&urb->urb_list, &hci->ctrl_list);
		urb_state = US_CTRL_SETUP;
		break;

	case PIPE_BULK:
		list_add (&urb->urb_list, &hci->bulk_list);
		if ((urb->transfer_flags & USB_ZERO_PACKET)
		    && urb->transfer_buffer_length > 0
		    &&
		    ((urb->transfer_buffer_length %
		      usb_maxpacket (urb->dev, urb->pipe,
				     usb_pipeout (urb->pipe))) == 0)) {
			urb_state = US_BULK0;
		}
		break;

	case PIPE_INTERRUPT:
		urb->start_frame = hci->frame_number;
		list_add (&urb->urb_list, &hci->intr_list);
		break;

	case PIPE_ISOCHRONOUS:
		list_add (&urb->urb_list, &hci->iso_list);
		break;
	}

#ifdef HC_URB_TIMEOUT
	if (urb->timeout) {
		ed->timeout.data = (unsigned long) urb;
		ed->timeout.expires = urb->timeout + jiffies;
		ed->timeout.function = qu_urb_timeout;
		add_timer (&ed->timeout);
	}
#endif

	qu_seturbstate (urb, urb_state);
}

/***************************************************************************
 * Function Name : qu_queue_urb
 *
 * This function adds the urb to the endpoint descriptor list 
 * 
 * Input: hci = data structure for the host controller 
 *        urb = USB request block data structure 
 *
 * Return: none  
 **************************************************************************/
static int qu_queue_urb (hci_t * hci, struct urb * urb)
{
	struct hci_device *hci_dev = usb_to_hci (urb->dev);
	epd_t *ed = &hci_dev->ed[qu_pipeindex (urb->pipe)];

	DBGFUNC ("Enter qu_queue_urb\n");

	/* for ISOC transfers calculate start frame index */

	if (usb_pipeisoc (urb->pipe) && urb->transfer_flags & USB_ISO_ASAP) {
		urb->start_frame = ((ed->pipe_head) ? (ed->last_iso + 1) : hci_get_current_frame_number (urb-> dev) + 1) & 0xffff;
	}

	if (ed->pipe_head) {
		__list_add (&urb->urb_list, ed->urb_queue.prev,
			    &(ed->urb_queue));
	} else {
		ed->pipe_head = urb;
		qu_queue_active_urb (hci, urb, ed);
		if (++hci->active_urbs == 1)
			hc_start_int (hci);
	}

	return 0;
}

/***************************************************************************
 * Function Name : qu_next_urb
 *
 * This function removes the URB from the queue and add the next URB to 
 * active list. 
 * 
 * Input: hci = data structure for the host controller 
 *        urb = USB request block data structure 
 *        resub_ok = resubmit flag
 *
 * Return: pointer to the next urb  
 **************************************************************************/
static struct urb *qu_next_urb (hci_t * hci, struct urb * urb, int resub_ok)
{
	struct hci_device *hci_dev = usb_to_hci (urb->dev);
	epd_t *ed = &hci_dev->ed[qu_pipeindex (urb->pipe)];

	DBGFUNC ("enter qu_next_urb\n");
	list_del (&urb->urb_list);
	INIT_LIST_HEAD (&urb->urb_list);
	if (ed->pipe_head == urb) {

#ifdef HC_URB_TIMEOUT
		if (urb->timeout)
			del_timer (&ed->timeout);
#endif

		if (!--hci->active_urbs)
			hc_stop_int (hci);

		if (!list_empty (&ed->urb_queue)) {
			urb = list_entry (ed->urb_queue.next, struct urb, urb_list);
			list_del (&urb->urb_list);
			INIT_LIST_HEAD (&urb->urb_list);
			ed->pipe_head = urb;
			qu_queue_active_urb (hci, urb, ed);
		} else {
			ed->pipe_head = NULL;
			urb = NULL;
		}
	}
	return urb;
}

/***************************************************************************
 * Function Name : qu_return_urb
 *
 * This function is part of the return path.   
 * 
 * Input: hci = data structure for the host controller 
 *        urb = USB request block data structure 
 *        resub_ok = resubmit flag
 *
 * Return: pointer to the next urb  
 **************************************************************************/
static struct urb *qu_return_urb (hci_t * hci, struct urb * urb, int resub_ok)
{
	struct urb *next_urb;

	DBGFUNC ("enter qu_return_rub\n");
	next_urb = qu_next_urb (hci, urb, resub_ok);
	hcs_return_urb (hci, urb, resub_ok);
	return next_urb;
}

/***************************************************************************
 * Function Name : sh_scan_iso_urb_list
 *
 * This function goes throught the isochronous urb list and schedule the 
 * the transfer.   
 *
 * Note: This function has not tested yet
 * 
 * Input: hci = data structure for the host controller 
 *        list_lh = pointer to the isochronous list 
 *        frame_number = the frame number 
 *
 * Return: 0 = unsuccessful; 1 = successful  
 **************************************************************************/
static int sh_scan_iso_urb_list (hci_t * hci, struct list_head *list_lh,
				 int frame_number)
{
	struct list_head *lh = list_lh->next;
	struct urb *urb;

	DBGFUNC ("enter sh_scan_iso_urb_list\n");
	hci->td_array->len = 0;

	while (lh != list_lh) {
		urb = list_entry (lh, struct urb, urb_list);
		lh = lh->next;
		if (((frame_number - urb->start_frame) & 0x7ff) <
		    urb->number_of_packets) {
			if (!sh_add_packet (hci, urb)) {
				return 0;
			} else {
				if (((frame_number -
				      urb->start_frame) & 0x7ff) > 0x400) {
					if (qu_urbstate (urb) > 0)
						urb = qu_return_urb (hci, urb, 1);
					else
						urb = qu_next_urb (hci, urb, 1);

					if (lh == list_lh && urb)
						lh = &urb->urb_list;
				}
			}
		}
	}
	return 1;
}

/***************************************************************************
 * Function Name : sh_scan_urb_list
 *
 * This function goes through the urb list and schedule the 
 * the transaction.   
 * 
 * Input: hci = data structure for the host controller 
 *        list_lh = pointer to the isochronous list 
 *
 * Return: 0 = unsuccessful; 1 = successful  
 **************************************************************************/
static int sh_scan_urb_list (hci_t * hci, struct list_head *list_lh)
{
	struct list_head *lh = NULL;
	struct urb *urb;

	if (list_lh == NULL) {
		DBGERR ("sh_scan_urb_list: error, list_lh == NULL\n");
	}

	DBGFUNC ("enter sh_scan_urb_list: frame# \n");

	list_for_each (lh, list_lh) {
		urb = list_entry (lh, struct urb, urb_list);
		if (urb == NULL)
			return 1;
		if (!usb_pipeint (urb->pipe)
		    || (((hci->frame_number - urb->start_frame)
			 & 0x7ff) >= urb->interval)) {
			DBGVERBOSE ("sh_scan_urb_list !INT: %d fr_no: %d int: %d pint: %d\n",
				    urb->start_frame, hci->frame_number, urb->interval,
				    usb_pipeint (urb->pipe));
			if (!sh_add_packet (hci, urb)) {
				return 0;
			} else {
				DBGVERBOSE ("INT: start: %d fr_no: %d int: %d pint: %d\n",
					    urb->start_frame, hci->frame_number,
					    urb->interval, usb_pipeint (urb->pipe));
				urb->start_frame = hci->frame_number;
				return 0;

			}
		}
	}
	return 1;
}

/***************************************************************************
 * Function Name : sh_shedule_trans
 *
 * This function schedule the USB transaction.
 * This function will process the endpoint in the following order: 
 * interrupt, control, and bulk.    
 * 
 * Input: hci = data structure for the host controller 
 *        isSOF = flag indicate if Start Of Frame has occurred 
 *
 * Return: 0   
 **************************************************************************/
static int sh_schedule_trans (hci_t * hci, int isSOF)
{
	int units_left = 1;

⌨️ 快捷键说明

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