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

📄 hc_simple.c

📁 This is cypress sl811 driver. I think it is very useful. Thankyou.
💻 C
📖 第 1 页 / 共 3 页
字号:
    {
        DBGERR ("ERROR: schedule, hci->td_array->len = 0x%x, s/b: 0\n",
		hci->td_array->len);
    }


    /* schedule the next available interrupt transfer or the next
     * stage of the interrupt transfer */

    if (hci->td_array->len == 0 && !list_empty(&hci->intr_list)) 
    {
        units_left = sh_scan_urb_list (hci, &hci->intr_list);
    }

    /* schedule the next available control transfer or the next
     * stage of the control transfer */
    
    if (hci->td_array->len == 0 && !list_empty(&hci->ctrl_list)
        && units_left > 0)
    {	
	units_left = sh_scan_urb_list (hci, &hci->ctrl_list);
    }

    /* schedule the next available bulk transfer or the next
     * stage of the bulk transfer */
 
    if (hci->td_array->len == 0 && !list_empty(&hci->bulk_list)
        && units_left > 0)
    {
	sh_scan_urb_list (hci, &hci->bulk_list);

        /* be fair to each BULK URB (move list head around) 
	 * only when the new SOF happens */
	
	lh = hci->bulk_list.next;
	list_del (&hci->bulk_list);
	list_add (&hci->bulk_list, lh);
    }
    return 0;
}

/***************************************************************************
 * Function Name : sh_add_packet
 *
 * This function forms the packet and transmit the packet. This function
 * will handle all endpoint type: isochoronus, interrupt, control, and 
 * bulk.
 * 
 * Input: hci = data structure for the host controller 
 *        urb = USB request block data structure 
 *
 * Return: 0 = unsucessful; 1 = successful   
 **************************************************************************/

static int sh_add_packet (hci_t * hci, urb_t * urb)
{
    __u8 * data = NULL;
    int len = 0;
    int toggle = 0;
    int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));
    int endpoint = usb_pipeendpoint (urb->pipe);
    int address = usb_pipedevice (urb->pipe);
    int slow = usb_pipeslow (urb->pipe);
    int out = usb_pipeout (urb->pipe);
    int pid = 0;
    int ret;
    int i = 0;
    int iso = 0;
	
    DBGFUNC ("enter sh_add_packet\n");
    if (maxps == 0) 
        maxps = 8;

    /* calculate len, toggle bit and add the transaction */
    switch (usb_pipetype (urb->pipe)) 
    {
	case PIPE_ISOCHRONOUS:
	    pid = out ? PID_OUT : PID_IN;
	    iso = 1;
	    i = hci->frame_number - urb->start_frame;
	    data = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
	    len = urb->iso_frame_desc[i].length;
  	    break;
			
	case PIPE_BULK: /* BULK and BULK0 */
	case PIPE_INTERRUPT:
	    pid = out ? PID_OUT : PID_IN;	
	    len = urb->transfer_buffer_length - urb->actual_length;
	    data = urb->transfer_buffer + urb->actual_length;
	    toggle = usb_gettoggle (urb->dev, endpoint, out);
	    break;

	case PIPE_CONTROL:
	    switch (qu_urbstate (urb)) 
            {
	        case US_CTRL_SETUP:	
		    len = 8;
		    pid = PID_SETUP;
		    data = urb->setup_packet;
		    toggle = 0;
		    break;

		case US_CTRL_DATA:
		    if (!hci->last_packet_nak)
		    {
		        /* The last packet received is not a nak:
		         * reset the nak count
			 */

			hci->nakCnt = 0;
		    }
		    if (urb->transfer_buffer_length != 0) 
                    {
		        pid = out ? PID_OUT : PID_IN;	
			len = urb->transfer_buffer_length - urb->actual_length;
			data = urb->transfer_buffer + urb->actual_length;
			toggle = (urb->actual_length & maxps) ? 0 : 1;
			usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), 
			usb_pipeout (urb->pipe), toggle);
			break;
		    } 
                    else
                    {
		        /* correct state and fall through */
			qu_seturbstate (urb, US_CTRL_ACK);
		    }				
		
                case US_CTRL_ACK:
		    len = 0;
		    
                    /* reply in opposite direction */
		    pid = !out ? PID_OUT : PID_IN; 
		    toggle = 1;
		    usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), 
		    usb_pipeout (urb->pipe), toggle);
		    break;
	    }
    }


    ret = hc_add_trans (hci, len, data, toggle, maxps, slow, 
  		        endpoint, address, pid, iso, qu_urbstate(urb));

    DBGVERBOSE("transfer_pa: addr:%d ep:%d pid:%x tog:%x iso:%x sl:%x "
               "max:%d\n len:%d ret:%d data:%p left:%d\n",	address, 
               endpoint, pid, toggle, iso, slow, maxps, len, ret, data, 
                    hci->hp.units_left);
	
    if (ret >= 0) 
    {
        hci->td_array->td [hci->td_array->len].urb = urb;
	hci->td_array->td [hci->td_array->len].len = ret;
	hci->td_array->td [hci->td_array->len].iso_index = i;
	hci->td_array->len ++;
        hci->active_trans = 1;	
	return 1;
    }
    return 0;
}

/***************************************************************************
 * Function Name : cc_to_error
 *
 * This function maps the SL811HS hardware error code to the linux USB error
 * code.
 * 
 * Input: cc = hardware error code 
 *
 * Return: USB error code   
 **************************************************************************/

static int cc_to_error (int cc)
{
    int errCode = 0;
    if (cc & SL11H_STATMASK_ERROR)
    {
	errCode |= USB_ST_CRC;
    }
    else if (cc & SL11H_STATMASK_OVF)
    {
        errCode |= USB_ST_DATAOVERRUN;
    }
        else if (cc & SL11H_STATMASK_STALL)
    {
 	errCode |= USB_ST_STALL;
    }
    return errCode;
}

/***************************************************************************
 * Function Name : sh_done_list
 *
 * This function process the packet when it has done finish transfer.
 * 
 * 1) It handles hardware error
 * 2) It updates the URB state
 * 3) If the USB transaction is complete, it start the return stack path.
 * 
 * Input: hci = data structure for the host controller 
 *        isExcessNak = flag tells if there excess NAK condition occurred 
 *
 * Return:  urb_state or -1 if the transaction has complete   
 **************************************************************************/

static int sh_done_list (hci_t * hci, int *isExcessNak) 
{
    int actbytes = 0;
    int active = 0;
    void * data = NULL; 
    int cc;
    int maxps;
    int toggle;
    urb_t * urb;
    int urb_state=0;
    int ret = 1; /* -1 parse abbort, 1 parse ok, 0 last element */
    int trans = 0;
    int len;
    int iso_index = 0;
    int out;
    int pid = 0;
    int debugLen = 0;

    *isExcessNak =0;
 
    DBGFUNC("enter sh_done_list: td_array->len = 0x%x\n", hci->td_array->len);

    debugLen = hci->td_array->len;
    if (debugLen > 1)
	DBGERR ("sh_done_list: td_array->len = 0x%x > 1\n", hci->td_array->len);

    for (trans = 0; ret && trans < hci->td_array->len && trans < MAX_TRANS; 
         trans++) 
    {
        urb = hci->td_array->td [trans].urb;
	len = hci->td_array->td [trans].len;
	out = usb_pipeout(urb->pipe);	

	if (usb_pipeisoc (urb->pipe)) 
        {
 	    iso_index = hci->td_array->td [trans].iso_index;
	    data = urb->transfer_buffer + 
                   urb->iso_frame_desc [iso_index].offset;
	    toggle = 0;
	} 
        else 
        {	
	    data = urb->transfer_buffer + urb->actual_length;
	    toggle = usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), 
                                    usb_pipeout (urb->pipe));

	}
        urb_state = qu_urbstate (urb);
	pid = out ? PID_OUT : PID_IN;
	ret = hc_parse_trans (hci, &actbytes, data, &cc, &toggle, len, pid, 
                              urb_state);
	maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));

	if (maxps == 0) 
            maxps = 8;

	active = (urb_state!=US_CTRL_SETUP) && 
		(actbytes && !(actbytes & (maxps-1))); 

	/* If the transfer is not bulk in, then it is necessary to get all
	 * data specify by the urb->transfer_len.
	 */
		
	if (!(usb_pipebulk(urb->pipe) && usb_pipein(urb->pipe)))	
	    active = active && (urb->transfer_buffer_length != 
                                urb->actual_length+actbytes);

	if (urb->transfer_buffer_length == urb->actual_length+actbytes)
	    active = 0;

	if ((cc & (SL11H_STATMASK_ERROR | SL11H_STATMASK_TMOUT | 
                  SL11H_STATMASK_OVF | SL11H_STATMASK_STALL)) 
            && !(cc & SL11H_STATMASK_NAK))
        {
            if (++urb->error_count > 3)  
            {
	        DBGERR ("done_list: excessive error: errcount = 0x%x,
		         cc = 0x%x\n", urb->error_count, cc);
		urb_state =0;   
   		active = 0;
            }
	    else
	    {
	        DBGERR ("done_list: packet err, cc = 0x%x, " 
                        " urb->length = 0x%x, actual_len = 0x%x," 
                        " urb_state =0x%x\n", cc, 
                        urb->transfer_buffer_length, urb->actual_length, 
                        urb_state);
//		if (cc & SL11H_STATMASK_STALL)
//		{
		    /* The USB function is STALLED on a control pipe (0), 
                     * then it needs to send the SETUP command again to 
                     * clear the STALL condition
 		     */
			
//                  if (usb_pipeendpoint (urb->pipe) == 0)
//		    {
//		        urb_state = 2;	
//			active = 0;
//		    }
//		 }
//		 else	
		     active =1;
		
            }
	}
        else
        {
            if (cc & SL11H_STATMASK_NAK) 
	    {
	        if (hci->nakCnt < 0x10000)
	        {
	            hci->nakCnt++;
		    hci->last_packet_nak = 1;
		    active = 1;
		    *isExcessNak = 0;
	        }
	        else
		{
		    DBGERR ("done_list: nak count exceed limit\n");
		    active = 0;
		    *isExcessNak = 1;
		    hci->nakCnt=0;
		}
	    }
	    else 
	    {
	        hci->nakCnt = 0;
		hci->last_packet_nak = 0;
	    }
	    
            if (urb_state != US_CTRL_SETUP) 
            { 
                /* no error */
		urb->actual_length += actbytes;
		usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), 
		               usb_pipeout (urb->pipe),toggle);
	    }
	    if (usb_pipeisoc (urb->pipe)) 
            {
	        urb->iso_frame_desc [iso_index].actual_length = actbytes;
		urb->iso_frame_desc [iso_index].status = cc_to_error (cc);
		active = (iso_index < urb->number_of_packets);
	    }
 	}	
	if (!active)
	{
	    if (!urb_state)
	    {
		urb->status = cc_to_error(cc);
		if (urb->status)
		{
		    DBGERR ("error on received packet: urb->status = 0x%x\n", 
						urb->status);
		}
		hci->td_array->len = 0;
		qu_return_urb(hci, urb, 1);
		return -1;
	    }
	    else
	    {
	         /* We do not want to decrement the urb_state if exceeded nak,
		  * because we need to finish the data stage of the control 
                  * packet 
                  */
		
                 if (!(*isExcessNak))
		    urb_state--;
		 qu_seturbstate(urb, urb_state);
	    }		
        }
    }

    if (urb_state < 0)
	DBGERR ("ERROR: done_list, urb_state = %d, suppose > 0\n", urb_state);
    if (debugLen != hci->td_array->len)
    {
        DBGERR ("ERROR: done_list, debugLen!= td_array->len," 
                "debugLen = 0x%x, hci->td_array->len = 0x%x\n", 
                debugLen, hci->td_array->len);
    }
    
    hci->td_array->len = 0;
	
    return urb_state;
}

⌨️ 快捷键说明

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