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 + -
显示快捷键?