📄 patch-2.4.4-sl811hs
字号:
+#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;+ }+ + 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -