static int hci_submit_urb (struct urb * urb) { hci_t * hci; unsigned int pipe = urb->pipe; unsigned long flags; int ret; if (!urb->dev || !urb->dev->bus || urb->hcpriv) return -EINVAL; if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) return -EPIPE; hci = (hci_t *) urb->dev->bus->hcpriv; /* a request to the virtual root hub */ if (usb_pipedevice (pipe) == hci->rh.devnum) { return rh_submit_urb (urb); } if (urb_debug) urb_print (urb, "SUB", usb_pipein (pipe)); /* queue the URB to its endpoint-queue */ spin_lock_irqsave (&usb_urb_lock, flags); ret = hcs_urb_queue (hci, urb); spin_unlock_irqrestore (&usb_urb_lock, flags); return ret; }
//transfer buffer must be aligned on an 8 bytes boundary static int hci_submit_urb (urb_t * urb) { hci_t * hci; unsigned int pipe = urb->pipe; unsigned long flags; int ret; if (!urb->dev || !urb->dev->bus || urb->hcpriv) return -EINVAL; #if BURST_TRANSFER_SIZE >= 8 if ( ((int)urb->transfer_buffer) & 7) { if ( (urb->transfer_buffer_length >8) || ( ( ((int)urb->transfer_buffer) & 1 ) && (urb->transfer_buffer_length >1) ) ) { printk(KERN_ERR __FILE__ ": improper alignment, size %d bytes\n",urb->transfer_buffer_length); return -EINVAL; } } #endif if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) return -EPIPE; hci = (hci_t *) urb->dev->bus->hcpriv; /* a request to the virtual root hub */ if (usb_pipedevice (pipe) == hci->rh.devnum) { return rh_submit_urb (urb); } if (urb_debug) urb_print (urb, "SUB", usb_pipein (pipe)); /* queue the URB to its endpoint-queue */ spin_lock_irqsave (&hci->urb_list_lock, flags); ret = hcs_urb_queue (hci, urb); spin_unlock_irqrestore (&hci->urb_list_lock, flags); return ret; }
static int hcs_return_urb (hci_t * hci, struct urb * urb, int resub_ok) { struct usb_device * dev = urb->dev; int resubmit = 0; if (urb_debug) urb_print (urb, "RET", usb_pipeout (urb->pipe)); resubmit = urb->interval && resub_ok; urb->dev = urb->hcpriv = NULL; if (urb->complete) urb->complete (urb); /* call complete */ if (resubmit) { /* requeue the URB */ urb->dev = dev; hcs_urb_queue (hci, urb); } return 0; }
static int hcs_return_urb (hci_t * hci, urb_t * urb, int resub_ok) { int resubmit = 0; struct dmaWork* dw=NULL; if (urb_debug) urb_print (urb, "RET", usb_pipeout (urb->pipe)); resubmit = urb->interval && resub_ok; if (!resubmit) { urb->dev = NULL; dw = urb->hcpriv; urb->hcpriv = NULL; } if (urb->complete) { if ((!resubmit)||!IntervalStatus(urb)) { urb->complete (urb); /* call complete */ } } if (resubmit) { /* requeue the URB */ if (!usb_pipeint (urb->pipe) || (urb->interval==0)) { urb->start_frame = hci->frame_no; hcs_urb_queue (hci, urb); } else { urb->start_frame = hci->frame_no + urb->interval; list_add (&urb->urb_list, &hci->waiting_intr_list); hc116x_enable_sofint(hci); } } else { if (dw) FreeDmaWork(hci,dw); //this also wakes anyone waiting on its destruction } return 0; }