cy7c67200_300_hcd_rh.c

来自「linux嵌入式课程实践中的一个关于声卡驱动程序 。」· C语言 代码 · 共 1,002 行 · 第 1/2 页

C
1,002
字号
    *(__u8 *) data = 0;	       ret = *(__u8 *) data;    /* Has the port status change within the root hub: It checks for     *      -- Port Connect Status change     *      -- Port Enable Change     */      for ( i = 0; i < num_ports; i++)     {        *(__u8 *) (data + (i + 1) / 8) |= (((get_port_stat_change (hci, port_num) >> 16)		    & (PORT_CONNECT_STAT | PORT_ENABLE_STAT)) ? 1: 0) <<                     ((i + 1) % 8);	ret += *(__u8 *) (data + (i + 1) / 8);			/* After the port change is read, it should be reset so the next time 	 * is it doesn't trigger a change again */		    }    len = i/8 + 1;  	    if (ret > 0)     { 	memcpy (rh_data, (void *) data, min (len, min (rh_len, sizeof(data))));	return len;    }	    return 0;}/*************************************************************************** * Function Name : rh_int_timer_do *  * This function is called when the timer expires.  It gets the the port  * change data and pass along to the upper protocol. *  * Note:  The virtual root hub interrupt pipe are polled by the timer *        every "interval" ms * * Input:  ptr = ptr to the urb * * Return: none   **************************************************************************/static void rh_int_timer_do (unsigned long ptr){    int len;     urb_t * urb = (urb_t *) ptr;	int port_num = -1;	cy_priv_t * cy_priv;    hci_t * hci;//	int i;//    cy_dbg("enter rh_int_timer_do\n");	if (urb == NULL)	{		cy_err("rh_int_timer_do: error, urb = 0x%x", 				(unsigned long) urb);		return;//		return ERROR;	}	cy_priv = urb->dev->bus->hcpriv;	if (cy_priv == NULL)	{		cy_err("rh_int_timer_do: error, cy_priv = 0x%x", 				(unsigned long) cy_priv);		return;//		return ERROR;		}	hci = cy_priv->hci;	if (hci == NULL)	{		cy_err("rh_int_timer_do: error, hci = 0x%x", 				(unsigned long) hci);		return;//		return ERROR;		}    port_num = get_port_num_from_urb(cy_priv, urb);	if (port_num == ERROR)	{		cy_err("rh_int_timer_do: can't find port num\n");			return;//		return ERROR;	}    if(hci->port[port_num].rh.send)     { //        cy_dbg("rh_int_timer_do: urb->transfer_buffer = 0x%x, urb->transfer_buffer_length = %d\n",//			urb->transfer_buffer, urb->transfer_buffer_length);        len = rh_send_irq (hci, urb->transfer_buffer,                            urb->transfer_buffer_length, port_num);		if (len > 0)          {		    urb->actual_length = len;		    if (urb_debug == 2)		        urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe));		    if (urb->complete)            {				urb->complete (urb);            }		}    } //	cy_dbg("rh_int_timer_do: exiting, urb = 0x%x, port_num = %d\n", (unsigned long) urb, port_num);    /* re-activate the timer */    rh_init_int_timer (urb, port_num);}/*************************************************************************** * Function Name : rh_init_int_timer *  * This function creates a timer that act as interrupt pipe in the * virtual hub.    *  * Note:  The virtual root hub's interrupt pipe are polled by the timer *        every "interval" ms * * Input: urb = USB request block  * * Return: 0   **************************************************************************/static int rh_init_int_timer (urb_t * urb, int port_num) {    cy_priv_t * cy_priv =  urb->dev->bus->hcpriv;    hci_t * hci = cy_priv->hci;    hci->port[port_num].rh.interval = urb->interval;	//	cy_dbg("rh_init_int_timer: urb = 0x%x, port_num = %d\n", (unsigned long) urb, port_num);	if (cy_priv == NULL || hci == NULL)	{		cy_err("rh_init_int_timer: error! cy_priv = 0x%x, hci = 0x%x\n", cy_priv, hci);	}    init_timer (&hci->port[port_num].rh.rh_int_timer);    hci->port[port_num].rh.rh_int_timer.function = rh_int_timer_do;    hci->port[port_num].rh.rh_int_timer.data = (unsigned long) urb;    hci->port[port_num].rh.rh_int_timer.expires = jiffies +                (HZ * (urb->interval < 30? 30: urb->interval)) / 1000;    add_timer (&hci->port[port_num].rh.rh_int_timer);	    return 0;}/*-------------------------------------------------------------------------*//* helper macro */#define OK(x) 			len = (x); break/*************************************************************************** * Function Name : rh_submit_urb *  * This function handles all USB request to the the virtual root hub *  * Input: urb = USB request block  * * Return: 0   **************************************************************************/int rh_submit_urb (urb_t * urb, int port_num){    struct usb_device * usb_dev = urb->dev;	cy_priv_t * cy_priv = usb_dev->bus->hcpriv;    hci_t * hci = cy_priv->hci;    unsigned int pipe = urb->pipe;    devrequest * cmd = (devrequest *) urb->setup_packet;    void * data = urb->transfer_buffer;    int leni = urb->transfer_buffer_length;    int len = 0;    int status = TD_CC_NOERROR;    __u32 datab[4];    __u8  * data_buf = (__u8 *) datab;	    __u16 bmRType_bReq;    __u16 wValue;     __u16 wIndex;    __u16 wLength;    cy_dbg("enter rh_submit_urb\n");    if (usb_pipeint(pipe))     {        hci->port[port_num].rh.urb =  urb;	    hci->port[port_num].rh.send = 1;	    hci->port[port_num].rh.interval = urb->interval;	    rh_init_int_timer(urb, port_num);	    urb->status = cc_to_error (TD_CC_NOERROR);			return 0;    }    bmRType_bReq  = cmd->requesttype | (cmd->request << 8);    wValue        = le16_to_cpu (cmd->value);    wIndex        = le16_to_cpu (cmd->index);    wLength       = le16_to_cpu (cmd->length);    cy_dbg("rh_submit_urb, req = %d(%x) len=%d", bmRType_bReq,		bmRType_bReq, wLength);    switch (bmRType_bReq)     {	/* Request Destination:	   without flags: Device, 	   RH_INTERFACE: interface, 	   RH_ENDPOINT: endpoint,	   RH_CLASS means HUB here, 	   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 	*/  	case RH_GET_STATUS: 				 			    *(__u16 *) data_buf = cpu_to_le16 (1); OK (2);	    case RH_GET_STATUS | RH_INTERFACE: 	 			    *(__u16 *) data_buf = cpu_to_le16 (0); OK (2);	  	case RH_GET_STATUS | RH_ENDPOINT:	 			    *(__u16 *) data_buf = cpu_to_le16 (0); OK (2);   	 	case RH_GET_STATUS | RH_CLASS: 				  	    *(__u32 *) data_buf = cpu_to_le32 (0); OK (4);	 	case RH_GET_STATUS | RH_OTHER | RH_CLASS: 		    *(__u32 *) data_buf = cpu_to_le32 (get_port_stat_change(hci, port_num));             OK (4);	case RH_CLEAR_FEATURE | RH_ENDPOINT:  	    switch (wValue)             {		case (RH_ENDPOINT_STALL): OK (0);	    }	    break;	case RH_CLEAR_FEATURE | RH_CLASS:	    switch (wValue)             {		case RH_C_HUB_LOCAL_POWER:		    OK(0);		                case (RH_C_HUB_OVER_CURRENT): 		    /* Over Current Not Implemented */		    OK (0);	    }	    break;			case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:	    switch (wValue)             {		case (RH_PORT_ENABLE): 			                    clr_port_stat (hci, PORT_ENABLE_STAT, port_num);		    OK (0);		        case (RH_PORT_SUSPEND):			                    clr_port_stat (hci, PORT_SUSPEND_STAT, port_num);		    OK (0);				case (RH_PORT_POWER):			                    clr_port_stat (hci, PORT_POWER_STAT, port_num);	            OK (0);				case (RH_C_PORT_CONNECTION):	                    clr_port_change (hci, PORT_CONNECT_STAT, port_num);  	            OK (0);				case (RH_C_PORT_ENABLE):		                    clr_port_change (hci, PORT_ENABLE_STAT, port_num);	  	    OK (0);				case (RH_C_PORT_SUSPEND):		                    clr_port_change (hci, PORT_SUSPEND_STAT, port_num);	            OK (0);				case (RH_C_PORT_OVER_CURRENT):	                    clr_port_change (hci, PORT_OVER_CURRENT_STAT, port_num);		    OK (0);				case (RH_C_PORT_RESET):			                    clr_port_change (hci, PORT_RESET_STAT, port_num);		    OK (0); 		}		break; 	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:	    switch (wValue)             {		case (RH_PORT_SUSPEND):			                    set_port_stat(hci, PORT_SUSPEND_STAT, port_num);		    OK (0); 				case (RH_PORT_RESET):                     set_port_stat(hci, PORT_RESET_STAT, port_num);                    // hc_host_usb_reset(cy_priv, port_num );                    clr_port_change (hci, PORT_CONNECT_CHANGE                                    | PORT_ENABLE_CHANGE | PORT_SUSPEND_CHANGE                                    | PORT_OVER_CURRENT_CHANGE, port_num);                    set_port_change(hci, PORT_RESET_CHANGE, port_num);                    clr_port_stat(hci, PORT_RESET_STAT, port_num);                    set_port_stat(hci, PORT_ENABLE_STAT, port_num);                                                		    OK (0);		        case (RH_PORT_POWER):			                    set_port_stat(hci, PORT_POWER_STAT, port_num);		    OK (0); 		        case (RH_PORT_ENABLE):                     set_port_stat(hci, PORT_ENABLE_STAT, port_num);		    OK (0);		}		break;	case RH_SET_ADDRESS:			hci->port[port_num].rh.devnum = wValue;			OK(0);	case RH_GET_DESCRIPTOR:	    cy_dbg("rh_submit_urb: RH_GET_DESCRIPTOR, wValue = 0x%x\n",                         wValue);	    switch ((wValue & 0xff00) >> 8)             {		case (0x01): /* device descriptor */		    len = min (leni, min (sizeof (root_hub_dev_des[port_num]), wLength));		    data_buf = root_hub_dev_des[port_num]; OK(len);		        case (0x02): /* configuration descriptor */		    len = min (leni, min (sizeof (root_hub_config_des[port_num]),                                wLength));		    data_buf = root_hub_config_des[port_num]; OK(len);		        case (0x03): /* string descriptors */		    len = usb_root_hub_string (wValue & 0xff,(int)(long) port_num,                                                "CY7C67200/300", data, wLength);		    if (len > 0)             {		        data_buf = data;				OK (min (leni, len));		    }				default: 		    status = bmHOST_STATMASK_STALL;	    }	    break;			case RH_GET_DESCRIPTOR | RH_CLASS:	    data_buf [0] = 9;		// min length;	    data_buf [1] = 0x29;	    data_buf [2] = 1;		// # of downstream port	    data_buf [3] = 0;	    datab [1] = 0;	    data_buf [5] = 50;		// 100 ms for port reset	    data_buf [7] = 0xfc;        // which port is attachable	    if (data_buf [2] < 7)             {	        data_buf [8] = 0xff;	    }             else             {	    }					    len = min (leni, min (data_buf [0], wLength));	    OK (len);	 	case RH_GET_CONFIGURATION: 		    *(__u8 *) data_buf = 0x01; 	    OK (1);	case RH_SET_CONFIGURATION: 		    OK (0);	default: 	    cy_err("unsupported root hub command");	    status = bmHOST_STATMASK_STALL;    }	    len = min(len, leni);    if (data != data_buf)        memcpy (data, data_buf, len);    urb->actual_length = len;    urb->status = cc_to_error (status);    urb->hcpriv = NULL;    urb->dev = NULL;    if (urb->complete)    {    	urb->complete (urb);    }	    return 0;}/*************************************************************************** * Function Name : rh_unlink_urb *  * This function unlinks the URB  *  * Input: urb = USB request block  * * Return: 0   **************************************************************************/int rh_unlink_urb (urb_t * urb, int port_num){    cy_priv_t * cy_priv = urb->dev->bus->hcpriv;    hci_t * hci = cy_priv->hci;     cy_dbg("enter rh_unlink_urb\n");    if (hci->port[port_num].rh.urb == urb)     {		hci->port[port_num].rh.send = 0;		del_timer (&hci->port[port_num].rh.rh_int_timer);		hci->port[port_num].rh.urb = NULL;		urb->hcpriv = NULL;		usb_dec_dev_use(urb->dev);		urb->dev = NULL;		if (urb->transfer_flags & USB_ASYNC_UNLINK)         {		    urb->status = -ECONNRESET;		    if (urb->complete)	        {		        urb->complete (urb);	        }		}     	else	   		urb->status = -ENOENT;    }    return 0;}/*************************************************************************** * Function Name : rh_connect_rh *  * This function connect the virtual root hub to the USB stack  *  * Input: urb = USB request block  * * Return: 0   **************************************************************************/ int rh_connect_rh (cy_priv_t * cy_priv, int port_num) {    struct usb_device  * usb_dev = NULL; 	hci_t * hci = cy_priv->hci;    hci->port[port_num].rh.devnum = 0;	cy_dbg("enter rh_connect_rh, port_num = 0x%x\n", port_num);	if (hci == NULL)	{		cy_err("rh_connect_rh: hci is NULL!\n");	}	if (hci->port[port_num].bus == NULL)	{		cy_err("rh_connect_rh: hci->port[port_num].bus is NULL!\n");	}	cy_dbg("rh_connect_rh: hci->port[%d].bus = 0x%x\n",             port_num, hci->port[port_num].bus);    usb_dev = usb_alloc_dev (NULL, hci->port[port_num].bus);    if (!usb_dev)	{		cy_err("rh_connect_rh: usb_dev == NULL!\n");        return -ENOMEM;	} 		cy_dbg("rh_connect_rh: usb_dev->bus = 0x%x, busnu = 0x%x\n",             usb_dev->bus, usb_dev->bus->busnum);	if (usb_dev->bus == NULL)	{		cy_err("rh_connect_rh: usb_dev->bus is 0x%x, "               "hci->port[%d].bus = 0x%x, usb_dev = 0x%x\n",		       usb_dev->bus, port_num, hci->port[port_num].bus, usb_dev);	}    hci->port[port_num].bus->root_hub = usb_dev;    usb_connect (usb_dev);    if (usb_new_device (usb_dev) != 0)     {        usb_free_dev (usb_dev);        return -ENODEV;    }    return 0;} 

⌨️ 快捷键说明

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