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

📄 hc_simple.c

📁 This is cypress sl811 driver. I think it is very useful. Thankyou.
💻 C
📖 第 1 页 / 共 3 页
字号:
 * 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) 
{
    urb_t * urb = (urb_t *) 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 (urb_t * 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 (urb_t * 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, urb_t * 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, urb_t * 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 urb_t * qu_next_urb (hci_t * hci, urb_t * 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, urb_t, 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 urb_t * qu_return_urb (hci_t * hci, urb_t * urb, int resub_ok) 
{
    urb_t * 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;
    urb_t * urb;

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

    while  (lh != list_lh) 
    {
        urb = list_entry (lh, urb_t, 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;
    urb_t * 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, urb_t, 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;
    struct list_head * lh;

    if (hci == NULL)
    {
       DBGERR ("sh_schedule_trans: hci == NULL\n");
       return 0;
    }
    if (hci->td_array == NULL)
    {
       DBGERR ("sh_schedule_trans: hci->td_array == NULL\n");
       return 0;
    }
      		
    if (hci->td_array->len != 0)

⌨️ 快捷键说明

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