예제 #1
0
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;

}
예제 #2
0
//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;

}
예제 #3
0
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;
}
예제 #4
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;
}