|
From: Tim R. <ti...@pr...> - 2014-04-14 19:37:12
|
abdullah unutmaz wrote:
>
> I have arranged all the endpoints by checking via lsusb, w.r.t.
> isochronous mode.
>
> I want to learn isochronous because audio device is for only a current
> project,
> projects varies from audio to RF etc.
If it looks like an audio device, you should use the audio APIs.
Seriously. It is simply a waste of time to reinvent all of that
hard-fought and well-tested code in the standard audio class driver.
> I tried every example I found in web, checked all the end point
> descriptors, transfer modes, bLength
> parameters.
You have quite a number of issues here. It looks like you have just
been adding code at random from multiple internet sources, without
really understanding what that code is doing.
As a stylistic issue, don't ever include an absolute path in a C program
like this:
#include </usr/include/libusb-1.0/libusb.h>
Instead, just reference the filename, and put the path in your compiler
options.
Let's take a look at your first routine. You allocate a libusb context,
then enumerate all the devices, then ask the user to pick one, then open
a handle, set configuration, release any kernel driver, and claim an
interface. Those are good steps.
But then you go into a loop 20 times where you allocate a new libusb
context every time and go through all of that process again. DON'T DO
THAT. Once you have a handle to the device, you don't need to do that
any more. In fact, doing so is not going to work; you have already
claimed the interface, so you can't claim it again from another handle.
In the loop, you do "libusb_alloc_transfer" to allocate an isochronous
transfer of MaxPacketSizeIn bytes, which you have hardcoded, currently
at 0x80 bytes. There are several problems with this.
Audio and video devices use "alternate settings" to allow multiple
choices for the bandwidth they reserve. If you do not select an
alternate setting, then your isochronous endpoints do not exist. You
must choose an alternate setting with libusb_set_interface_alt_setting.
Further, the packet size you use must match the value in the alternate
setting you choose. If you are driving one specific device, and you
know exactly what video/audio format you need, and you know exactly
which alternate setting you will need, then you can hardcode the packet
size. In most cases, however, you will need to fetch the list of all
the alternate settings and choose the one that has enough bandwidth for
what you need.
Further, you really do not want to have one packet per transfer. These
streams operate in real-time. You cannot keep up with the device that
way. Try using 8 packets per transfer.
Your libusb_fill_iso_transfer call is wrong. You have to specify three
things: a buffer, the total size of your buffer, and the number of
packets that buffer contains. Your parameters are very confusing. You
have set up your buffer to be 7 bytes long, from a value called
bLengthISOVideoIn. Based on the name, I think you got that number from
the length of the endpoint descriptor. That doesn't have ANYTHING to do
with buffering. All that tells you is how long the endpoint descriptor
itself is.
For now, let's assume that you choose an alternate setting where your
endpoint has a max packet length of 256 bytes. Let's assume you want to
send 8 packets in each transfer. Then, you'll allocate your buffer as:
#define MaxPacketSize 256
#define PacketsPerTransfer 8
unsigned char data[MaxPacketSize * PacketsPerTransfer];
and you'll call
libusb_fill_iso_transfer(xfr, ..., data, sizeof(data),
PacketsPerTransfer, ... );
libusb_set_iso_packet_lengths( xfr, MaxPacketSize );
> Additionally, I have run Valgrind for my program, I got "... possibly
> lost in loss records..." message.
Your problems are not anything that Valgrind can find. You have
fundamental USB issues here.
--
Tim Roberts, ti...@pr...
Providenza & Boekelheide, Inc.
|