Discussion:
LibUSB Interrupt Transfer
jay.k
2013-05-05 20:59:18 UTC
Permalink
I am working on a UVC Compliant USB Webcam.

I am writing a standalone driver for this device using LibUSB instead of
using the UVC driver in the Linux Kernel.

I am facing a issue with sending interrupt packets to this device.

My Interrupt Endpoint descriptor is


bLength: 0x07
bDescriptorType:0x05
bEndpointAddress:0x87 -> Direction: IN - EndpointID: 7
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize:0x0010 = 1 transactions per microframe, 0x10 max bytes
bInterval:0x08


I am allocating interrupt transfers as follows

static struct libusb_transfer *allocate_int_transfer(libusb_device_handle
*handle)
{

struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer)
printf("transfer alloc failure");


unsigned char int_buf[16];
libusb_fill_interrupt_transfer(transfer,handle,0x87,
int_buf, sizeof(int_buf),interrupt_callback, NULL, 0);

return transfer;
}


My Callback function is this:

static void interrupt_callback(struct libusb_transfer *transfer)
{
printf("interrupt_callback status %d\n", transfer->status);
libusb_submit_transfer(transfer);
}


I send the Interrupt transfer in my main loop as follows:

struct libusb_transfer *int_transfer;
int_transfer = allocate_int_transfer(dev_handle);

r = libusb_submit_transfer(int_transfer);
if (r < 0)
printf("interrupt submit fail %d\n", r);


The first line of the trace captured using usbmon facility is
efbdee40 2217417032 S Ii:2:005:7 -115:128 16 <

I have another code written by someone else, which relies on the UVC driver.
It runs successfully and can capture frames from the camera.
The first line of the usbmon trace captured from that code is
f0f700c0 2152410673 S Ii:2:012:7 -115:8 16 <

I am basically trying to reverse engineer and emulate the behaviour of that
code, and accordingly write my code, so I get the exact same behaviour.

We need to set the bInterval of 8 instead of 128.

So is there anyway by which I can tell LibUSB, the value of my bInterval
field of my Interrupt Endpoint, so that my code sends the exact same
interrupt packet as that code?













--
View this message in context: http://libusb.6.n5.nabble.com/LibUSB-Interrupt-Transfer-tp5711901.html
Sent from the LibUSB Dev mailing list archive at Nabble.com.
Alan Stern
2013-05-06 01:40:37 UTC
Permalink
Post by jay.k
I am working on a UVC Compliant USB Webcam.
I am writing a standalone driver for this device using LibUSB instead of
using the UVC driver in the Linux Kernel.
I am facing a issue with sending interrupt packets to this device.
My Interrupt Endpoint descriptor is
bLength: 0x07
bDescriptorType:0x05
bEndpointAddress:0x87 -> Direction: IN - EndpointID: 7
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize:0x0010 = 1 transactions per microframe, 0x10 max bytes
bInterval:0x08
Does your webcam connect at full speed or at high speed?

It makes a difference. At full speed, bInterval = 8 means the interval
is 8 frames (where one frame = 1 ms). But at high speed, bInterval = 8
means the interval is 128 microframes (where 8 microframes = 1 ms).
Post by jay.k
The first line of the trace captured using usbmon facility is
efbdee40 2217417032 S Ii:2:005:7 -115:128 16 <
The 128 value above indicates the interval being used. Whether it is
in frames or microframes depends on the speed of the connection.
Post by jay.k
I have another code written by someone else, which relies on the UVC driver.
It runs successfully and can capture frames from the camera.
The first line of the usbmon trace captured from that code is
f0f700c0 2152410673 S Ii:2:012:7 -115:8 16 <
Here the interval is 8. It's quite possible that this value indicates
a bug in the kernel's UVC driver -- perhaps it really should be 128.
Post by jay.k
I am basically trying to reverse engineer and emulate the behaviour of that
code, and accordingly write my code, so I get the exact same behaviour.
We need to set the bInterval of 8 instead of 128.
So is there anyway by which I can tell LibUSB, the value of my bInterval
field of my Interrupt Endpoint, so that my code sends the exact same
interrupt packet as that code?
No, there is no way to change the interval value (under Linux anyway,
and presumably also under other operating systems). Not only does
libusb not include any API for doing this, the kernel also does not
provide any way for user programs to specify the interval. It always
uses the value in the endpoint descriptor.

Alan Stern
Xiaofan Chen
2013-05-06 14:26:32 UTC
Permalink
Post by Alan Stern
Post by jay.k
I am working on a UVC Compliant USB Webcam.
I am writing a standalone driver for this device using LibUSB instead of
using the UVC driver in the Linux Kernel.
I am facing a issue with sending interrupt packets to this device.
My Interrupt Endpoint descriptor is
bLength: 0x07
bDescriptorType:0x05
bEndpointAddress:0x87 -> Direction: IN - EndpointID: 7
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize:0x0010 = 1 transactions per microframe, 0x10 max bytes
bInterval:0x08
Does your webcam connect at full speed or at high speed?
It makes a difference. At full speed, bInterval = 8 means the interval
is 8 frames (where one frame = 1 ms). But at high speed, bInterval = 8
means the interval is 128 microframes (where 8 microframes = 1 ms).
Post by jay.k
The first line of the trace captured using usbmon facility is
efbdee40 2217417032 S Ii:2:005:7 -115:128 16 <
The 128 value above indicates the interval being used. Whether it is
in frames or microframes depends on the speed of the connection.
Post by jay.k
I have another code written by someone else, which relies on the UVC driver.
It runs successfully and can capture frames from the camera.
The first line of the usbmon trace captured from that code is
f0f700c0 2152410673 S Ii:2:012:7 -115:8 16 <
Here the interval is 8. It's quite possible that this value indicates
a bug in the kernel's UVC driver -- perhaps it really should be 128.
Post by jay.k
I am basically trying to reverse engineer and emulate the behaviour of that
code, and accordingly write my code, so I get the exact same behaviour.
We need to set the bInterval of 8 instead of 128.
So is there anyway by which I can tell LibUSB, the value of my bInterval
field of my Interrupt Endpoint, so that my code sends the exact same
interrupt packet as that code?
No, there is no way to change the interval value (under Linux anyway,
and presumably also under other operating systems). Not only does
libusb not include any API for doing this, the kernel also does not
provide any way for user programs to specify the interval. It always
uses the value in the endpoint descriptor.
What about the kernel UVC driver quirk mentioned here?
http://www.ideasonboard.org/uvc/faq/
UVC_QUIRK_STATUS_INTERVAL 0x00000001
Interpret the status endpoint bInterval value as a number of frame
instead of an exponent value
--
Xiaofan
Alan Stern
2013-05-06 16:31:47 UTC
Permalink
Post by Xiaofan Chen
Post by Alan Stern
Post by jay.k
I am working on a UVC Compliant USB Webcam.
I am writing a standalone driver for this device using LibUSB instead of
using the UVC driver in the Linux Kernel.
I am facing a issue with sending interrupt packets to this device.
My Interrupt Endpoint descriptor is
bLength: 0x07
bDescriptorType:0x05
bEndpointAddress:0x87 -> Direction: IN - EndpointID: 7
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize:0x0010 = 1 transactions per microframe, 0x10 max bytes
bInterval:0x08
Does your webcam connect at full speed or at high speed?
It makes a difference. At full speed, bInterval = 8 means the interval
is 8 frames (where one frame = 1 ms). But at high speed, bInterval = 8
means the interval is 128 microframes (where 8 microframes = 1 ms).
Post by jay.k
The first line of the trace captured using usbmon facility is
efbdee40 2217417032 S Ii:2:005:7 -115:128 16 <
The 128 value above indicates the interval being used. Whether it is
in frames or microframes depends on the speed of the connection.
Post by jay.k
I have another code written by someone else, which relies on the UVC driver.
It runs successfully and can capture frames from the camera.
The first line of the usbmon trace captured from that code is
f0f700c0 2152410673 S Ii:2:012:7 -115:8 16 <
Here the interval is 8. It's quite possible that this value indicates
a bug in the kernel's UVC driver -- perhaps it really should be 128.
Post by jay.k
I am basically trying to reverse engineer and emulate the behaviour of that
code, and accordingly write my code, so I get the exact same behaviour.
We need to set the bInterval of 8 instead of 128.
So is there anyway by which I can tell LibUSB, the value of my bInterval
field of my Interrupt Endpoint, so that my code sends the exact same
interrupt packet as that code?
No, there is no way to change the interval value (under Linux anyway,
and presumably also under other operating systems). Not only does
libusb not include any API for doing this, the kernel also does not
provide any way for user programs to specify the interval. It always
uses the value in the endpoint descriptor.
What about the kernel UVC driver quirk mentioned here?
http://www.ideasonboard.org/uvc/faq/
UVC_QUIRK_STATUS_INTERVAL 0x00000001
Interpret the status endpoint bInterval value as a number of frame
instead of an exponent value
Yes, that could be the explanation. Jay, what does lsusb show for your
webcam? In particular, what are the idVendor, idProduct, and bcdDevice
values?

Alan Stern
jay.k
2013-05-06 16:38:38 UTC
Permalink
The details of my camera are:-

idVendor: 0x046D = Logitech Inc.
idProduct: 0x0802
bcdDevice: 0x0009






--
View this message in context: http://libusb.6.n5.nabble.com/LibUSB-Interrupt-Transfer-tp5711901p5711915.html
Sent from the LibUSB Dev mailing list archive at Nabble.com.
Alan Stern
2013-05-06 17:30:58 UTC
Permalink
Post by jay.k
The details of my camera are:-
idVendor: 0x046D = Logitech Inc.
idProduct: 0x0802
bcdDevice: 0x0009
That isn't the same as any of the entries in the Linux UVC driver, so
I don't know why the interval is getting set to 8 instead of 128. You
could try asking on the linux-usb or linux-media mailing lists.

Regardless of the answer, there is no way to tell libusb to use a
different interval value. In the end, you may find it doesn't matter.

Alan Stern
Peter Stuge
2013-05-06 18:10:51 UTC
Permalink
Post by jay.k
I am writing a standalone driver for this device using LibUSB instead
of using the UVC driver in the Linux Kernel.
Why?
Post by jay.k
I am allocating interrupt transfers as follows
static struct libusb_transfer *allocate_int_transfer(libusb_device_handle
*handle)
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer)
printf("transfer alloc failure");
unsigned char int_buf[16];
libusb_fill_interrupt_transfer(transfer,handle,0x87,
int_buf, sizeof(int_buf),interrupt_callback, NULL, 0);
return transfer;
}
This is not valid. The memory buffer you provide does not exist
once this function has returned.
Post by jay.k
static void interrupt_callback(struct libusb_transfer *transfer)
{
printf("interrupt_callback status %d\n", transfer->status);
libusb_submit_transfer(transfer);
}
This is OK.
Post by jay.k
struct libusb_transfer *int_transfer;
int_transfer = allocate_int_transfer(dev_handle);
r = libusb_submit_transfer(int_transfer);
if (r < 0)
printf("interrupt submit fail %d\n", r);
Also OK.
Post by jay.k
I am basically trying to reverse engineer and emulate the behaviour of
that code, and accordingly write my code, so I get the exact same
behaviour.
Again, why?
Post by jay.k
We need to set the bInterval of 8 instead of 128.
Why do you think so?


//Peter
jay.k
2013-05-06 18:28:41 UTC
Permalink
jay.k wrote:> I am writing a standalone driver for this device using
LibUSB instead> of using the UVC driver in the Linux Kernel.Why?
*
My aim is to write a usb class driver for this particular camera for
vxWorks
*
I am allocating interrupt transfers as follows> > static struct
libusb_transfer *allocate_int_transfer(libusb_device_handle> *handle)> {>
struct libusb_transfer *transfer = libusb_alloc_transfer(0);> if
(!transfer)> printf("transfer alloc failure");> > > unsigned char
int_buf[16];> libusb_fill_interrupt_transfer(transfer,handle,0x87, >
int_buf, sizeof(int_buf),interrupt_callback, NULL, 0); > > return
transfer;> }This is not valid. The memory buffer you provide does not
existonce this function has returned.
*
Understood
*
My Callback function is this:> > static void interrupt_callback(struct
libusb_transfer *transfer)> {> printf("interrupt_callback status %d\n",
transfer->status);> libusb_submit_transfer(transfer);> }This is OK.> I
send the Interrupt transfer in my main loop as follows:> > struct
libusb_transfer *int_transfer;> int_transfer =
allocate_int_transfer(dev_handle);> > r =
libusb_submit_transfer(int_transfer);> if (r < 0)> printf("interrupt
submit fail %d\n", r); Also OK.> I am basically trying to reverse
engineer and emulate the behaviour of> that code, and accordingly write
my code, so I get the exact same> behaviour.Again, why?
*
I plan to first get this camera working with a standalone driver on linux
and then port it to vxWorks
*
We need to set the bInterval of 8 instead of 128.Why do you think so?In
the usbmon trace of the other code that uses the UVC driver, the
bInterval field was 8,but our code written using LibUSB was this field
set to 128, so we assumed that we were doing something wrong with the
Interrupt
Packet.//Peter------------------------------------------------------------------------------Learn
Graph Databases - Download FREE O'Reilly Book"Graph Databases" is the
definitive new guide to graph databases and their applications. This
200-page book is written by three acclaimed leaders in the field. The
early access version is available now. Download your free book today!
http://p.sf.net/sfu/neotech_d2d_may_______________________________________________libusb-devel
mailing list
https://lists.sourceforge.net/lists/listinfo/libusb-devel
jay.k wrote:> I am writing a standalone driver for this device using
LibUSB instead> of using the UVC driver in the Linux Kernel.Why?> I am
allocating interrupt transfers as follows> > static struct libusb_transfer
*allocate_int_transfer(libusb_device_handle> *handle)> {> > struct
libusb_transfer *transfer = libusb_alloc_transfer(0);> if (!transfer)>
printf("transfer alloc failure");> > > unsigned char int_buf[16];>
libusb_fill_interrupt_transfer(transfer,handle,0x87, > int_buf,
sizeof(int_buf),interrupt_callback, NULL, 0); > > return transfer;>
}This is not valid. The memory buffer you provide does not existonce this
function has returned.> My Callback function is this:> > static void
interrupt_callback(struct libusb_transfer *transfer)> {>
printf("interrupt_callback status %d\n", transfer->status);>
libusb_submit_transfer(transfer);> }This is OK.> I send the Interrupt
transfer in my main loop as follows:> > struct libusb_transfer
*int_transfer;> int_transfer = allocate_int_transfer(dev_handle);> > r
= libusb_submit_transfer(int_transfer);> if (r < 0)>
printf("interrupt submit fail %d\n", r); Also OK.> I am basically trying
to reverse engineer and emulate the behaviour of> that code, and
accordingly write my code, so I get the exact same> behaviour.Again, why?>
We need to set the bInterval of 8 instead of 128.Why do you think
so?//Peter------------------------------------------------------------------------------Learn
Graph Databases - Download FREE O'Reilly Book"Graph Databases" is the
definitive new guide to graph databases and their applications. This
200-page book is written by three acclaimed leaders in the field. The
early access version is available now. Download your free book today!
http://p.sf.net/sfu/neotech_d2d_may_______________________________________________libusb-devel
mailing list
https://lists.sourceforge.net/lists/listinfo/libusb-devel
jay.k wrote:> I am writing a standalone driver for this device using
LibUSB instead> of using the UVC driver in the Linux Kernel.Why?> I am
allocating interrupt transfers as follows> > static struct libusb_transfer
*allocate_int_transfer(libusb_device_handle> *handle)> {> > struct
libusb_transfer *transfer = libusb_alloc_transfer(0);> if (!transfer)>
printf("transfer alloc failure");> > > unsigned char int_buf[16];>
libusb_fill_interrupt_transfer(transfer,handle,0x87, > int_buf,
sizeof(int_buf),interrupt_callback, NULL, 0); > > return transfer;>
}This is not valid. The memory buffer you provide does not existonce this
function has returned.> My Callback function is this:> > static void
interrupt_callback(struct libusb_transfer *transfer)> {>
printf("interrupt_callback status %d\n", transfer->status);>
libusb_submit_transfer(transfer);> }This is OK.> I send the Interrupt
transfer in my main loop as follows:> > struct libusb_transfer
*int_transfer;> int_transfer = allocate_int_transfer(dev_handle);> > r
= libusb_submit_transfer(int_transfer);> if (r < 0)>
printf("interrupt submit fail %d\n", r); Also OK.> I am basically trying
to reverse engineer and emulate the behaviour of> that code, and
accordingly write my code, so I get the exact same> behaviour.Again, why?>
We need to set the bInterval of 8 instead of 128.Why do you think
so?//Peter------------------------------------------------------------------------------Learn
Graph Databases - Download FREE O'Reilly Book"Graph Databases" is the
definitive new guide to graph databases and their applications. This
200-page book is written by three acclaimed leaders in the field. The
early access version is available now. Download your free book today!
http://p.sf.net/sfu/neotech_d2d_may_______________________________________________libusb-devel
mailing list
https://lists.sourceforge.net/lists/listinfo/libusb-devel
jay.k wrote:> I am writing a standalone driver for this device using
LibUSB instead> of using the UVC driver in the Linux Kernel.Why?> I am
allocating interrupt transfers as follows> > static struct libusb_transfer
*allocate_int_transfer(libusb_device_handle> *handle)> {> > struct
libusb_transfer *transfer = libusb_alloc_transfer(0);> if (!transfer)>
printf("transfer alloc failure");> > > unsigned char int_buf[16];>
libusb_fill_interrupt_transfer(transfer,handle,0x87, > int_buf,
sizeof(int_buf),interrupt_callback, NULL, 0); > > return transfer;>
}This is not valid. The memory buffer you provide does not existonce this
function has returned.> My Callback function is this:> > static void
interrupt_callback(struct libusb_transfer *transfer)> {>
printf("interrupt_callback status %d\n", transfer->status);>
libusb_submit_transfer(transfer);> }This is OK.> I send the Interrupt
transfer in my main loop as follows:> > struct libusb_transfer
*int_transfer;> int_transfer = allocate_int_transfer(dev_handle);> > r
= libusb_submit_transfer(int_transfer);> if (r < 0)>
printf("interrupt submit fail %d\n", r); Also OK.> I am basically trying
to reverse engineer and emulate the behaviour of> that code, and
accordingly write my code, so I get the exact same> behaviour.Again, why?>
We need to set the bInterval of 8 instead of 128.Why do you think
so?//Peter------------------------------------------------------------------------------Learn
Graph Databases - Download FREE O'Reilly Book"Graph Databases" is the
definitive new guide to graph databases and their applications. This
200-page book is written by three acclaimed leaders in the field. The
early access version is available now. Download your free book today!
http://p.sf.net/sfu/neotech_d2d_may_______________________________________________libusb-devel
mailing list
https://lists.sourceforge.net/lists/listinfo/libusb-devel
jay.k wrote:> I am writing a standalone driver for this device using
LibUSB instead> of using the UVC driver in the Linux Kernel.Why?> I am
allocating interrupt transfers as follows> > static struct libusb_transfer
*allocate_int_transfer(libusb_device_handle> *handle)> {> > struct
libusb_transfer *transfer = libusb_alloc_transfer(0);> if (!transfer)>
printf("transfer alloc failure");> > > unsigned char int_buf[16];>
libusb_fill_interrupt_transfer(transfer,handle,0x87, > int_buf,
sizeof(int_buf),interrupt_callback, NULL, 0); > > return transfer;>
}This is not valid. The memory buffer you provide does not existonce this
function has returned.> My Callback function is this:> > static void
interrupt_callback(struct libusb_transfer *transfer)> {>
printf("interrupt_callback status %d\n", transfer->status);>
libusb_submit_transfer(transfer);> }This is OK.> I send the Interrupt
transfer in my main loop as follows:> > struct libusb_transfer
*int_transfer;> int_transfer = allocate_int_transfer(dev_handle);> > r
= libusb_submit_transfer(int_transfer);> if (r < 0)>
printf("interrupt submit fail %d\n", r); Also OK.> I am basically trying
to reverse engineer and emulate the behaviour of> that code, and
accordingly write my code, so I get the exact same> behaviour.Again, why?>
We need to set the bInterval of 8 instead of 128.Why do you think
so?//Peter------------------------------------------------------------------------------Learn
Graph Databases - Download FREE O'Reilly Book"Graph Databases" is the
definitive new guide to graph databases and their applications. This
200-page book is written by three acclaimed leaders in the field. The
early access version is available now. Download your free book today!
http://p.sf.net/sfu/neotech_d2d_may_______________________________________________libusb-devel
mailing list
https://lists.sourceforge.net/lists/listinfo/libusb-devel
--
View this message in context: http://libusb.6.n5.nabble.com/LibUSB-Interrupt-Transfer-tp5711901p5711919.html
Sent from the LibUSB Dev mailing list archive at Nabble.com.
Tim Roberts
2013-05-06 20:02:47 UTC
Permalink
Post by jay.k
So is there anyway by which I can tell LibUSB, the value of my bInterval
field of my Interrupt Endpoint, so that my code sends the exact same
interrupt packet as that code?
The bInterval field is not part of the USB packet. It's merely being
reported to you for informational purposes as a courtesy. The interval
and packet scheduling is all handled in layers that are far below you,
based on the descriptors, not based on anything that you provide.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Loading...