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

📄 hc_simple.c

📁 基于linux嵌入式操作系统,sl811芯片的usb驱动源代码以及例子和Makefile.
💻 C
📖 第 1 页 / 共 3 页
字号:
      		    if (hci->td_array->len != 0)    {        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 + -