tags:

views:

1509

answers:

4

The situation is this: I have a USB device (a custom device I'm trying to talk to) with two endpoints, one writing to the device, one reading from the device. Both are bulk transfers. Every communication transaction takes the form of (1) Write a command to the device (2) Read the response. I'm using libusb (version 0.1 rather than the 1.0 beta) to actually perform the communications.

On Windows, all is well. I can connect the device, claim the interface and communicate happily. However, in Ubuntu (a standard Hardy desktop install), whilst I can connect to the device and write to it, all read operations fail with the error "error submitting URB: Invalid argument" reported from libusb (error code -22).

If I check /var/log/messages I see a warning message logged for the same time as the read was attempted: "sysfs: duplicate filename 'usbdev4.3_ep81' can not be created" - which tallies with the device (it is indeed on that bus and it's endpoint 81 I'm trying to read from).

So... anyone seen a similar problem using libusb, or have any idea how to fix it?

+1  A: 

I haven't used libusb in quite some time -- but the sysfs error indicates that this is likely to be a kernel problem rather than a libusb one, so I'd start by trying to track that one down. (Not much point in trying to work with libusb until you're sure your kernel is talking to the device correctly).

Does the patch at http://kerneltrap.org/mailarchive/linux-usb-devel/2007/10/17/345922 apply to your kernel? (If so, does it fix the issue?)

Charles Duffy
I stepped down into the code, and it does indeed seem to be a kernel level problem (the error code is propagating all the way up from the ioctl call that should be performing the transfer). I'll take a look at the patch and report back. Cheers!
Throctukes
Nope, didn't fix it. I applied the patch and still see exactly the same problem when using the patched kernel. Which is weird, because it looks like the patch addresses this very issue.
Throctukes
A: 

You can try WinDriver it's a commercial tool but have free full function evaluation (somehow time limited). You can check with WinDriver and if problem is reproducible it's might be device or your protocol fault. You did not give enough information to determine or analyze.

Ilya
I'm currently porting away from WinDriver. On Windows I have communications with no problems using both the old WinDriver code and the new libusb code. I don't have the linux version of WinDriver, and to be honest it's going to be a very last resort step to get it.
Throctukes
+1  A: 

I had to do some hacking to udev rules to get the device created with the right permissions for libusb to work. Like so:

SUBSYSTEM=="usb" ATTRS{idVendor}=="0a81", ATTRS{idProduct}=="0701", \
                MODE="0666" SYMLINK+="missile_launcher"

(This was an usb missile launcher I was writing a driver for.

Also this snippet was required to not clash with the kernel.

if(LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP)
{
    // Detach kernel driver (usbhid) from device interface. (Linux hack)
    usb_detach_kernel_driver_np(launcher, 0);
    usb_detach_kernel_driver_np(launcher, 1);
}

I'm not sure how this relates to your problem, but atleast there are two possible points of failure that might be involved.

John Nilsson
Ah, I see you've got different permissions set for the device in the udev rules (I have MODE="660" but also GROUP="plugdev", which should achieve the same thing shouldn't it?). Where do you put the snippet in relation to the rest of the calls?
Throctukes
Should, as long as the program is executed as a member of plugdev. But then again "should" isn't exactly a reliable fact ;)Regarding the snippet I have it right after I usb_open() the device before touching configurations and interfaces.
John Nilsson
Tried them both out, no joy. I'm beginning to wonder if there's maybe a problem on the device that Windows papers over and ignores, but that Linux is sulking about.
Throctukes
+1  A: 

Turns out it was a misconfiguration in the descriptors on the device itself. lsusb -v showed an extra interface which was never used, which had a single isochronous endpoint 0x81. Since this was never used (and had never been tested as far as I could see, so quite possibly not even defined correctly) I removed it from the device descriptors completely (in the firmware).

And now I have a fully working device. Why linux refused to read from the device but Windows worked fine I don't know, but it definitely sent me on a wild goose chase.

Throctukes