📄 hc_simple.c
字号:
* 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; DBGFUNC ("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) { DBGFUNC ("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) { DBGFUNC ("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) { DBGFUNC ("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: hci = data structure for the host controller * urb = USB request block data structure * ed = endpoint descriptor * * Return: none **************************************************************************/static inline void qu_queue_active_urb (hci_t * hci, urb_t * urb, epd_t * ed) { int urb_state = 0; DBGFUNC ("enter qu_queue_active_urb\n"); switch (usb_pipetype (urb->pipe)) { case PIPE_CONTROL: list_add (&urb->urb_list, &hci->ctrl_list); urb_state = US_CTRL_SETUP; break; case PIPE_BULK: list_add (&urb->urb_list, &hci->bulk_list); 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; } break; case PIPE_INTERRUPT: urb->start_frame = hci->frame_number; list_add (&urb->urb_list, &hci->intr_list); break; case PIPE_ISOCHRONOUS: list_add (&urb->urb_list, &hci->iso_list); 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 (hci_t * hci, urb_t * urb){ struct hci_device * hci_dev = usb_to_hci (urb->dev); epd_t * ed = &hci_dev->ed [qu_pipeindex (urb->pipe)]; DBGFUNC ("Enter qu_queue_urb\n"); /* for ISOC transfers calculate start frame index */ if (usb_pipeisoc (urb->pipe) && urb->transfer_flags & USB_ISO_ASAP) { urb->start_frame = ((ed->pipe_head)? (ed->last_iso + 1): hci_get_current_frame_number (urb->dev) + 1) & 0xffff; } if (ed->pipe_head) { __list_add (&urb->urb_list, ed->urb_queue.prev, &(ed->urb_queue)); } else { ed->pipe_head = urb; qu_queue_active_urb (hci, urb, ed); if (++hci->active_urbs == 1) hc_start_int (hci); } return 0;}/*************************************************************************** * Function Name : qu_next_urb * * This function removes the URB from the queue and add the next URB to * active list. * * Input: hci = data structure for the host controller * urb = USB request block data structure * resub_ok = resubmit flag * * Return: pointer to the next urb **************************************************************************/static urb_t * qu_next_urb (hci_t * hci, urb_t * urb, int resub_ok) { struct hci_device * hci_dev = usb_to_hci (urb->dev); epd_t * ed = &hci_dev->ed [qu_pipeindex (urb->pipe)]; DBGFUNC ("enter qu_next_urb\n"); list_del (&urb->urb_list); INIT_LIST_HEAD (&urb->urb_list); if (ed->pipe_head == urb) {#ifdef HC_URB_TIMEOUT if (urb->timeout) del_timer (&ed->timeout);#endif if (!--hci->active_urbs) hc_stop_int (hci); if (!list_empty (&ed->urb_queue)) { urb = list_entry (ed->urb_queue.next, urb_t, urb_list); list_del (&urb->urb_list); INIT_LIST_HEAD (&urb->urb_list); ed->pipe_head = urb; qu_queue_active_urb (hci, urb, ed); } else { ed->pipe_head = NULL; urb = NULL; } } return urb;}/*************************************************************************** * Function Name : qu_return_urb * * This function is part of the return path. * * Input: hci = data structure for the host controller * urb = USB request block data structure * resub_ok = resubmit flag * * Return: pointer to the next urb **************************************************************************/static urb_t * qu_return_urb (hci_t * hci, urb_t * urb, int resub_ok) { urb_t * next_urb; DBGFUNC ("enter qu_return_rub\n"); next_urb = qu_next_urb (hci, urb, resub_ok); hcs_return_urb (hci, urb, resub_ok); return next_urb; }/*************************************************************************** * Function Name : sh_scan_iso_urb_list * * This function goes throught the isochronous urb list and schedule the * the transfer. * * Note: This function has not tested yet * * Input: hci = data structure for the host controller * list_lh = pointer to the isochronous list * frame_number = the frame number * * Return: 0 = unsuccessful; 1 = successful **************************************************************************/static int sh_scan_iso_urb_list (hci_t * hci, struct list_head * list_lh, int frame_number) { struct list_head * lh = list_lh->next; urb_t * urb; DBGFUNC ("enter sh_scan_iso_urb_list\n"); hci->td_array->len = 0; while (lh != list_lh) { urb = list_entry (lh, urb_t, urb_list); lh = lh->next; if (((frame_number - urb->start_frame) & 0x7ff) < urb->number_of_packets) { if (!sh_add_packet (hci, urb)) { return 0; } else { if (((frame_number - urb->start_frame) & 0x7ff) > 0x400) { if (qu_urbstate(urb) > 0) urb = qu_return_urb (hci, urb, 1); else urb = qu_next_urb (hci, urb, 1); if (lh == list_lh && urb) lh = &urb->urb_list; } } } } return 1;}/*************************************************************************** * Function Name : sh_scan_urb_list * * This function goes through the urb list and schedule the * the transaction. * * Input: hci = data structure for the host controller * list_lh = pointer to the isochronous list * * Return: 0 = unsuccessful; 1 = successful **************************************************************************/static int sh_scan_urb_list (hci_t * hci, struct list_head * list_lh) { struct list_head * lh = NULL; urb_t * urb; if (list_lh == NULL) { DBGERR ("sh_scan_urb_list: error, list_lh == NULL\n"); } DBGFUNC ("enter sh_scan_urb_list: frame# \n"); list_for_each (lh, list_lh) { urb = list_entry (lh, urb_t, urb_list); if (urb == NULL) return 1; if (!usb_pipeint (urb->pipe) ||(((hci->frame_number - urb->start_frame) & 0x7ff) >= urb->interval)) { DBGVERBOSE("sh_scan_urb_list !INT: %d fr_no: %d int: %d pint: %d\n", urb->start_frame, hci->frame_number, urb->interval, usb_pipeint (urb->pipe)); if (!sh_add_packet (hci, urb)) { return 0; } else { DBGVERBOSE("INT: start: %d fr_no: %d int: %d pint: %d\n", urb->start_frame, hci->frame_number, urb->interval, usb_pipeint (urb->pipe)); urb->start_frame = hci->frame_number; return 0; } } } return 1;}/*************************************************************************** * Function Name : sh_shedule_trans * * This function schedule the USB transaction. * This function will process the endpoint in the following order: * interrupt, control, and bulk. * * Input: hci = data structure for the host controller * isSOF = flag indicate if Start Of Frame has occurred * * Return: 0 **************************************************************************/static int sh_schedule_trans (hci_t * hci, int isSOF){ int units_left = 1; struct list_head * lh; if (hci == NULL) { DBGERR ("sh_schedule_trans: hci == NULL\n"); return 0; } if (hci->td_array == NULL) { DBGERR ("sh_schedule_trans: hci->td_array == NULL\n"); return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -