cy7c67200_300_hcd_simple.c

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

C
2,186
字号
    hci = cy_priv->hci;    hci_dev = usb_to_hci (urb->dev);	if (hci_dev != NULL) 	    ed = &hci_dev->ed [qu_pipeindex (urb->pipe)];    if ((hci == NULL) || (cy_priv == NULL) || hci_dev == NULL || ed == NULL)    {        HWTrace(0xCF);        cy_err("hci_unlink_urb: error hci = 0x%x, cy_priv = 0x%x, hci_dev = 0x%x, ed = 0x%x\n",               (int) hci, (int) cy_priv, (int) hci_dev, (int) ed);        return ERROR;    }    /* a request to the virtual root hub */    for (i = 0; i < MAX_NUM_PORT; i++)    {        if (hci->valid_host_port[i] == 1) {            if (usb_pipedevice (urb->pipe) == hci->port[i].rh.devnum)             {                /* The urb belong to the root hub, so send to root hub */                HWTrace (0xC1);                return rh_unlink_urb (urb, i);             }            if (urb->dev->bus->busnum == hci->port[i].bus->busnum)            {                /* need port_num for non root hub urbs */                port_num = i;            }        }    }    if (port_num == -1)    {        cy_err("hci_unlink_urb: unknown port number\n");    }    if (urb_debug)        urb_print (urb, "UNLINK", 1);            spin_lock_irqsave (&usb_urb_lock, int_flags);	/* Release int/iso bandwidth */	if (urb->bandwidth) {		switch (usb_pipetype(urb->pipe)) {		case PIPE_INTERRUPT:			usb_release_bandwidth (urb->dev, urb, 0);			break;		case PIPE_ISOCHRONOUS:			usb_release_bandwidth (urb->dev, urb, 1);			break;		default:			break;		}	}    if (!list_empty (&urb->urb_list) && urb->status == USB_ST_URB_PENDING)     {         /* URB active? */            if (urb->transfer_flags & (USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED))         {             /* asynchron with callback */            HWTrace (0xC2);                        list_del (&urb->urb_list); /* relink the urb to the del list */            list_add (&urb->urb_list, &hci->port[port_num].del_list);			if (ed->pipe_head == urb)				ed->pipe_head = NULL;            spin_unlock_irqrestore (&usb_urb_lock, int_flags);        }         else         {             /* synchron without callback */            HWTrace (0xC3);            add_wait_queue (&hci->waitq, &wait);                  set_current_state (TASK_UNINTERRUPTIBLE);            comp = urb->complete;            urb->complete = NULL;                    list_del (&urb->urb_list); /* relink the urb to the del list */            list_add (&urb->urb_list, &hci->port[port_num].del_list);            spin_unlock_irqrestore (&usb_urb_lock, int_flags);                            schedule_timeout(HZ/50);            if (!list_empty (&urb->urb_list))                list_del (&urb->urb_list);        			if (ed->pipe_head == urb)				ed->pipe_head = NULL;            urb->complete = comp;            urb->hcpriv = NULL;            remove_wait_queue (&hci->waitq, &wait);         }    }     else     {         /* hcd does not own URB but we keep the driver happy anyway */        spin_unlock_irqrestore (&usb_urb_lock, int_flags);                    if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK))         {               HWTrace (0xC4);            urb->status = -ENOENT;            urb->actual_length = 0;                           urb->complete (urb);  // DO WE NEED TO DO THIS??            urb->status = 0;            }        else         {            HWTrace (0xC5);            urb->status = -ENOENT;        }       }       return 0;}/*************************************************************************** * Function Name : hci_alloc_dev * * This function allocates private data space for the usb device and  * initialize the endpoint descriptor heads. * * Input: usb_dev = pointer to the usb device  * * Return: 0 if success or error code  **************************************************************************/static int hci_alloc_dev (struct usb_device * usb_dev){    struct hci_device * dev;    int i;        cy_dbg("enter hci_alloc_dev\n");    HWTrace(0xBEF0);    dev = kmalloc (sizeof (*dev), GFP_KERNEL);    if (!dev)    return -ENOMEM;            memset (dev, 0, sizeof (*dev));    for (i = 0; i < NUM_EDS; i++)     {        INIT_LIST_HEAD (&(dev->ed [i].urb_queue));        dev->ed [i].pipe_head = NULL;        dev->ed [i].last_iso = 0;    }    usb_dev->hcpriv = dev;        cy_dbg("USB HC dev alloc %d bytes\n", sizeof (*dev));            return 0;}/*************************************************************************** * Function Name : hci_free_dev * * This function de-allocates private data space for the usb devic * * Input: usb_dev = pointer to the usb device  * * Return: 0   **************************************************************************/static int hci_free_dev (struct usb_device * usb_dev){    cy_dbg("enter hci_free_dev\n");            if (usb_dev->hcpriv)	    kfree (usb_dev->hcpriv);    usb_dev->hcpriv = NULL;    return 0;}/*************************************************************************** * Function Name : hci_get_current_frame_number * * This function get the current USB frame number * * Input: usb_dev = pointer to the usb device  * * Return: frame number   **************************************************************************/int hci_get_current_frame_number (struct usb_device *usb_dev) {    cy_priv_t * cy_priv = usb_dev->bus->hcpriv;    hci_t * hci = cy_priv->hci;    int port_num = -1;    cy_dbg("enter hci_get_current_frame_number\n");           if ((hci == NULL) || (cy_priv == NULL))    {        cy_err("hci_get_current_frame_number: error hci = 0x%x, cy_priv = 0x%x\n", (int) hci,                 (int) cy_priv);        return ERROR;    }    port_num = get_port_num_from_dev(cy_priv, usb_dev);    if (port_num == ERROR)    {        cy_err("hci_get_current_frame_number: can't find port num\n");          return ERROR;    }        /* Get the right port */    return (cy67x00_get_current_frame_number (cy_priv, port_num));}/*************************************************************************** * List of all io-functions  **************************************************************************/ struct usb_operations hci_device_operations = {    hci_alloc_dev,    hci_free_dev,    hci_get_current_frame_number,    hci_submit_urb,    hci_unlink_urb,    hc_otg_end_session,    hc_otg_offer_hnp};/*************************************************************************** * URB queueing: *  * For each type of transfer (INTR, BULK, ISO, CTRL) there is a list of  * active URBs. * (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_TIMEOUTstatic void qu_urb_timeout (unsigned long lurb) {    urb_t * urb = (urb_t *) lurb;    cy_dbg("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) {    cy_dbg("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) {    cy_dbg("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) {    cy_dbg("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: cy_priv  = private data structure *        urb      = USB request block data structure  *        ed       = endpoint descriptor *        port_num = port number * * Return: none   **************************************************************************/static inline void qu_queue_active_urb (cy_priv_t * cy_priv, urb_t * urb, epd_t * ed, int port_num) {    int urb_state = 0;    hci_t * hci = cy_priv->hci;    cy_dbg("enter qu_queue_active_urb\n");    HWTrace(0x30);    switch (usb_pipetype (urb->pipe))     {    case PIPE_CONTROL:        HWData(&urb->urb_list);		HWData(&hci->port[port_num].ctrl_list);        list_add (&urb->urb_list, &hci->port[port_num].ctrl_list);#ifdef CY        urb_state = US_CTRL_SETUP;#endif        HWTrace(0x31);        break;            case PIPE_BULK:        list_add (&urb->urb_list, &hci->port[port_num].bulk_list);#ifdef CY              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;        }#endif            HWTrace(0x32);        break;            case PIPE_INTERRUPT:        urb->start_frame = cy67x00_get_current_frame_number (cy_priv, port_num);        list_add (&urb->urb_list, &hci->port[port_num].intr_list);        HWTrace(0x33);        break;            case PIPE_ISOCHRONOUS:        printk("qu_queue_active_urb: add urb to iso_list, start_frame =	"                "0x%x, # Pkts = 0x%x, err Cnt = 0x%x\n ", urb->start_frame,                     urb->number_of_packets, urb->error_count);//        HWData(&urb->urb_list);//        HWData(port_num);        list_add (&urb->urb_list, &hci->port[port_num].iso_list);//        HWTrace(0x34);        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 (cy_priv_t * cy_priv, urb_t * urb, int port_num){    hci_t * hci = cy_priv->hci;    struct hci_device * hci_dev = usb_to_hci (urb->dev);    epd_t * ed = &hci_dev->ed [qu_pipeindex (urb->pipe)];

⌨️ 快捷键说明

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