Need help with usb bulk timeouts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I'm trying to write a driver for a usb device that requires a large bulk out transfer to patch the firmware. I borrowed the bulk out code from mass storage's transport.c, but still can't seem to get this to work (the device does work under windows, and I have no problem with control transfers). After calling usb_submit_urb(), the blocking callback returns almost immediately with a value 0f 0, and actual_len of 0. The urb->status is -ETIMEOUT. A catc trace shows that the first packet tries to go out 3 times but apparantly doesn't get either an ACK or a NAK. My controller is uhci, so I dug through that code and it looks like it may keep retrying until it times out. My suspicion is that the device is a little slow (on top of delays in the analyser and an external hub), so I'd like to try changing the timeout value but I can't find where to do this. Can I do this with a parameter change without having to recompile the kernel? If not, can someone point me to where the timeout value is set? I've also pasted the relevant code below if anyone can find something stupid that I've done. Thanks,

Steve

------------------
int stv674_send_bulk_msg(struct stv674_camera* cam,
void* data,
int data_len)
{
int status = 0;
unsigned int actual_len = 0;
struct urb* burb = cam->bulk_out_strmbuf.urb;
struct completion bulk_done;

DBG("stv674_send_bulk_msg(): len = 0x%0X, data = 0x%0X\n",
data_len, (u32)data);

status = stv674_usb_set_alternate(cam, USBIF_BULK);

/* Finish initializing the URB, send the data, then wait
* for completion
*/
init_completion(&bulk_done);

down(&(cam->bulk_urb_sem)); /* Lock URB */
burb->transfer_buffer = data;
burb->transfer_buffer_length = data_len;
burb->actual_length = 0;
burb->error_count = 0;
burb->transfer_flags = USB_ASYNC_UNLINK;
burb->complete = stv674_usb_blocking_completion;
burb->context = &bulk_done;

/* Submit the urb. */
status = usb_submit_urb(burb);
if (status) {
/* Something went wrong */
up(&(cam->bulk_urb_sem));
ERR("Error from usb_submit_urb(burb): %d\n", status);
return status;
}

/* Wait for completion of the URB */
up(&(cam->bulk_urb_sem));
wait_for_completion(&bulk_done);

down(&(cam->bulk_urb_sem));

actual_len = burb->actual_length;

DBG("stv674_send_bulk_msg(): ret = %d, actual len = 0x%0X\n",
status, actual_len);
DBG("stv674_send_bulk_msg(): URB status = %d\n", burb->status);
up(&(cam->bulk_urb_sem));

// usb_unlink_urb(burb);
return status;
}

/******************************************************************************
*
* stv674_usb_blocking_completion
*

*****************************************************************************/
static void stv674_usb_blocking_completion(struct urb* urb)
{
struct completion *urb_done_ptr = (struct completion *)urb->context;

DBG("Enter blocking completion\n");
complete(urb_done_ptr);

DBG("Leaving blocking completion\n");
}

--
Steve Miller
Software Engineer
STMicroelectronics
phone (602) 485-2014

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive: http://mail.nl.linux.org/kernelnewbies/
FAQ: http://kernelnewbies.org/faq/



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux