📄 hc_simple_isp116x.c
字号:
}#endif qu_seturbstate (urb, urb_state);}static int qu_queue_urb (hci_t * hci, struct urb * urb){ struct hci_device * hci_dev = usb_to_hci (urb->dev); epd_t * ed = &hci_dev->ed [qu_pipeindex (urb->pipe)]; /* 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) + 3) & 0xffff; if (!(ed->pipe_head)){ ed->last_iso = urb->start_frame; } } 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;}/*-------------------------------------------------------------------------*//* return path (after transfer) * remove URB from queue and return it to the api layer * */static struct urb * remove_urb (hci_t * hci, struct urb * urb){ int i; struct hci_device * hci_dev = usb_to_hci (urb->dev); for (i = 0; i < 32; i++) { INIT_LIST_HEAD (&(hci_dev->ed [i].urb_queue)); hci_dev->ed [i].pipe_head = NULL; }}static struct urb * qu_next_urb (hci_t * hci, struct urb * urb, int resub_ok){ struct hci_device * hci_dev = usb_to_hci (urb->dev); epd_t * ed = &hci_dev->ed [qu_pipeindex (urb->pipe)]; 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, struct urb, 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;}static struct urb * qu_return_urb (hci_t * hci, struct urb * urb, int resub_ok){ struct urb * next_urb; next_urb = qu_next_urb (hci, urb, resub_ok); hcs_return_urb (hci, urb, resub_ok); return next_urb;}/*-------------------------------------------------------------------------*//*-------------------------------------------------------------------------*//* SCHEDULE operations * * * * */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; struct urb * urb; hci->td_array->len = 0; while (lh != list_lh) { urb = list_entry (lh, struct urb, 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;}static int sh_scan_urb_list (hci_t * hci, struct list_head * list_lh){ struct list_head * lh; struct urb * urb; list_for_each (lh, list_lh) { urb = list_entry (lh, struct urb, urb_list); if (!usb_pipeint (urb->pipe) || (((hci->frame_number - urb->start_frame) & 0x7ff) >= urb->interval)) { if (!sh_add_packet (hci, urb)) return 0; else { urb->start_frame = hci->frame_number; } } } return 1;}/*-------------------------------------------------------------------------*//* scan lists of active URBs and construct a schedule for a frame * */static int sh_schedule_trans (hci_t * hci){ int units_left; struct list_head * lh; hci->td_array->len = 0; units_left = sh_scan_urb_list (hci, &hci->intr_list); if (units_left) { /* add CTRL transfers */ units_left = sh_scan_urb_list (hci, &hci->ctrl_list); } if (units_left) { /* add BULK transfers */ sh_scan_urb_list (hci, &hci->bulk_list); } /* be fair to each BULK URB (move list head around) */ if (!list_empty (&hci->bulk_list)) { lh = hci->bulk_list.next; list_del (&hci->bulk_list); list_add (&hci->bulk_list, lh); } return 0;}/*-------------------------------------------------------------------------*//* add some parts of the active URB to the schedule * */static int sh_add_packet (hci_t * hci, struct urb * 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; 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; iso = 1; i = hci->frame_number - urb->start_frame; hci->td_array = &hci->i_td_array [i & 1]; if (i == 1) hci->i_td_array[0].len = 1; data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; len = urb->iso_frame_desc[i].length; break; case PIPE_BULK: /* BULK and BULK0 */ case PIPE_INTERRUPT: pid = out ? PID_OUT : PID_IN; len = urb->transfer_buffer_length - urb->actual_length; data = urb->transfer_buffer + urb->actual_length; toggle = usb_gettoggle (urb->dev, endpoint, out); break; case PIPE_CONTROL: switch (qu_urbstate (urb)) { case US_CTRL_SETUP: len = 8; pid = PID_SETUP; data = urb->setup_packet; toggle = 0; break; case US_CTRL_DATA: if (urb->transfer_buffer_length != 0) { pid = out ? PID_OUT : PID_IN; len = urb->transfer_buffer_length - urb->actual_length; data = urb->transfer_buffer + urb->actual_length; toggle = (urb->actual_length & maxps) ? 0 : 1; usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), toggle); break; } else /* correct state and fall through */ qu_seturbstate (urb, US_CTRL_ACK); case US_CTRL_ACK: len = 0; /* reply in opposite direction */ pid = !out ? PID_OUT : PID_IN; toggle = 1; usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), toggle); break; } } ret = hc_add_trans (hci, len, data, toggle, maxps, slow, endpoint, address, pid, iso);#ifdef DEBUG1 printk("urb->start_frame =%d hci->frame_number=%d\n", urb->start_frame,hci->frame_number); printk("transfer_pa: addr:%d ep:%d pid:%x tog:%x iso:%x sl:%x max:%d\n len:%d ret:%d data:%p left:%d\n", address, endpoint, pid, toggle, iso, slow, maxps, len, ret, data, hci->hp.units_left);#endif if (ret >= 0) { hci->td_array->td [hci->td_array->len].urb = urb; hci->td_array->td [hci->td_array->len].len = ret; hci->td_array->td [hci->td_array->len].iso_index = i; hci->td_array->len = 1; return 1; } return 0;}/*-------------------------------------------------------------------------*//* parse the done_list * */static int sh_done_list (hci_t * hci){ int actbytes; int active = 0; void * data = NULL;// void * data_urb = NULL; int cc; int maxps; int toggle; struct urb * urb; int urb_state; int ret = 1; /* -1 parse abbort, 1 parse ok, 0 last element */ int trans = 0; int len; int iso_index = 0; for (trans = 0; ret && trans < hci->td_array->len && trans < MAX_TRANS; trans++) { urb = hci->td_array->td [trans].urb; len = hci->td_array->td [trans].len; if (usb_pipeisoc (urb->pipe)) { iso_index = hci->td_array->td [trans].iso_index; data = urb->transfer_buffer + urb->iso_frame_desc [iso_index].offset; toggle = 0; } else { data = urb->transfer_buffer + urb->actual_length; toggle = usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); } urb_state = qu_urbstate (urb); ret = hc_parse_trans (hci, &actbytes, data, &cc, &toggle, len); maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)); if (maxps == 0) maxps = 8;#ifdef DEBUG1 printk("hc USB %d error %d in frame %d ep %d out %d addr %d actbytes %d:%p tog %d\n", urb->error_count, cc, hci->frame_number, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), usb_pipedevice (urb->pipe), actbytes, data, toggle);#endif if (cc != TD_NOTACCESSED) { active = (urb_state != US_CTRL_SETUP) && (actbytes && !(actbytes & (maxps - 1)) && (urb->transfer_buffer_length != urb->actual_length + actbytes));#ifdef DEBUG1 printk("hc USBx active %d, cc %x, urb_state %x, ret %x\n", active, cc, urb_state, ret);#endif if (!(urb->transfer_flags & USB_DISABLE_SPD) && cc == TD_DATAUNDERRUN) cc = 0; if (cc) { /* last packet has an error */ if (hc_error_verbose) printk("hc USB %d error %d in frame %d ep %d out %d addr %d au: %d\n", urb->error_count, cc, hci->frame_number, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), usb_pipedevice (urb->pipe), hci->active_urbs); if (++urb->error_count > 3 || cc == TD_CC_STALL) { active = 0; urb_state = 0; /* return */ } else { active = 1; } } else urb->error_count = 0; if (urb_state != US_CTRL_SETUP) { /* no error */ urb->actual_length += actbytes; usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), toggle); } if (usb_pipeisoc (urb->pipe)) { urb->iso_frame_desc [iso_index].actual_length = actbytes; urb->iso_frame_desc [iso_index].status = cc_to_error [cc]; active = (iso_index < urb->number_of_packets - 1); } if (!active) { if (!(urb_state--)) { urb->status = cc_to_error [cc]; qu_return_urb (hci, urb, 1); } else { qu_seturbstate (urb, urb_state); } } } else urb->error_count = 0; } hci->td_array->len = 0; return ret;}/*-------------------------------------------------------------------------*//* scan the delete list (qu_return_urb removes URB from list) * */static void sh_del_list (hci_t * hci){ struct list_head * lh = &hci->del_list; struct urb * urb; if (!list_empty (lh)) { do { lh = lh->next; urb = list_entry (lh, struct urb, urb_list); qu_return_urb (hci, urb, 0); } while (!list_empty (lh)); wake_up (&hci->waitq); } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -