|
From: Alan S. <st...@ro...> - 2009-04-23 19:51:58
|
On Thu, 23 Apr 2009, Jens Thoms Toerring wrote:
> Hi,
>
> I'm still having problems with the camera I was writing
> about a few days ago. It worked well with libusb-0.1 but
> when trying to use libusb-1.0 reading data from the device
> fails. What I do is the following (error checking not shown
> but present in the code for each function call and everything
> looks quite fine until the last step):
>
> a) libusb_init( NULL );
>
> b) libusb_set_debug( NULL, 3 );
>
> c) cnt = libusb_get_device_list( NULL, &list );
> for ( i = 0; i < cnt; i++ )
> {
> struct libusb_device_descriptor desc;
> if ( libusb_get_device_descriptor( list[ i ], &desc ) == 0
> && desc.idVendor == 0x184c
> && desc.idProduct == 0x0000 )
> {
> dev = list[ i ];
> break;
> }
> }
>
> d) libusb_open( dev, &udev );
>
> e) libusb_free_device_list( list, 1 );
>
> f) libusb_set_configuration( udev, 1 );
>
> g) libusb_claim_interface( udev, 0 );
>
> h) libusb_set_interface_alt_setting( udev, 0, 0 );
>
> i) set up buffer with data to be send to device, then
>
> libusb_bulk_transfer( udev, 4, buf, len, &cnt, 0 );
>
> This works and len == cnt afterwards
>
> j) On trying to read the reply the device is supposed to send
>
> libusb_bulk_transfer( udev, 8, readbuf, 64, &cnt, 0 );
If you're trying to read from an endpoint then the address should have
the 0x80 bit set. So instead of 8, you probably want to say 0x88.
Otherwise you're telling the system that you want to write, not read!
> the call fails returns -1 and the debug output is
>
> libusb:error [submit_bulk_transfer] submiturb failed error -1 errno=2
>
> The same code (modulo the required changes) works with libusb-0.1,
> thus I am pretty sure that what I send to the device etc. is correct
> and should result in a reply.
The old libusb would silently make corrections like this for you. The
newer version doesn't.
> As far as I can see (going by the documentation in the kernel) -2
> (ENOENT) means "specified interface or endpoint does not exist or
> is not enabled". Now there's something in the 'dmesg' output for
> the device that looks a bit suspicious to me but which I am not
> sure if it's relevant:
>
> usb 1-3: new high speed USB device using ehci_hcd and address 17
> usb 1-3: config 1 interface 0 altsetting 0 bulk endpoint 0x2 has invalid maxpacket 64
> usb 1-3: config 1 interface 0 altsetting 0 bulk endpoint 0x4 has invalid maxpacket 64
> usb 1-3: config 1 interface 0 altsetting 0 bulk endpoint 0x86 has invalid maxpacket 64
> usb 1-3: config 1 interface 0 altsetting 0 bulk endpoint 0x88 has invalid maxpacket 64
Those are just warnings, not errors. They shouldn't affect the
operation of your program.
> usb 1-3: configuration #1 chosen from 1 choice
> usb 1-3: New USB device found, idVendor=184c, idProduct=0000
> usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> usb 1-3: Product: Clear Shot II Camera
> usb 1-3: Manufacturer: Centice Corporation
> usb 1-3: SerialNumber: 0000044
>
> In contrast to this output the documentation for the camera expli-
> citely says that 64 is the max packet size for all endpoints. Could
> this explain why reading from the device fails with ENOENT? (But
> why is a writing data to it working then?)
The camera's design is not compliant with the USB-2.0 specification,
which states that all high-speed bulk endpoints must have a maxpacket
size of 512. Nevertheless, Linux will accept other values and use
them.
The reason your program failed is because it tried to read from an OUT
endpoint. A non-existent OUT endpoint, in fact, as you can see from
the lsusb output. There is no endpoint with address 8 listed.
> Finally one more question out of mere curiosity: how does one
> deduce from the device data if a configuration is low, full or
> high speed?
Do you mean the current configuration, as presented by libusb? That
always corresponds to the device's current connect speed -- in general
you can't deduce the speed merely from the data in the configuration
itself.
Which reduces the problem to determining the current connect speed. I
don't know if libusb-1.0 makes that information available or not.
> Is all one can go by the maximum packet size or is
> this information somewhere in the output of lsusb and I'm just
> too stupid to figure it out?
You can guess from the maxpacket sizes, but you won't always be right.
For example, the sizes in your lsusb output would lead one to guess
that the connection was full speed, but in fact it was high speed and
the sizes were buggy.
lsusb does not tell you what speed the current connection is. You have
to get the speed from somewhere else, such as sysfs. Look in
/sys/bus/usb/devices/.../speed
where you have to fill in the "..." with the appropriate device name.
Or you can look in /proc/bus/usb/devices (not all distributions make
that file available, so you may have to do "mount -t usbfs none
/proc/bus/usb" first.)
Alan Stern
|