Receiving data from a USB client

3,003 views
Skip to first unread message

Harshad RJ

unread,
Jul 5, 2013, 3:42:25 AM7/5/13
to usb4...@googlegroups.com
Hi,

Firstly, thanks for creating this project. I am sure it will be a great help for the java community!

I am not well versed with USB protocol details. However, I have a fair understanding of it, and have good experience dealing with networking, system programming, and the Java language.

I am trying to connect from a Java application to an Android phone over USB using the ADB protocol. So far I have managed to write to the bulk output end point. And I have verified that parts works correctly using usbmon.

However, I am not receiving any replies from the device. When I compare the usbmon traces with other applications that communicate over USB I see one difference.

ffff880224c95cc0 1628209865 S Bi:3:027:3 -115 24 <

This line from usbmon seems to indicate a preparation of the Bulk input channel 3.

In my app I don't see this. My code is something like this:

inPipe.open()
inPipe.addUsbPipeListener( ... )


However, my listener doesn't receive any callbacks and I don't see any activity on that pipe in usbmon logs. I am perhaps missing something crucial here.

Looking at Pipe.java I am further convinced that I am missing a crucial step. Pipe.open() only toggles a private member and Pipe.addUsbPipeListener only adds it to a list of listeners. I am not able to see what actually prepares the pipe in the lower levels.

thanks,
Harshad

Klaus Reimer

unread,
Jul 5, 2013, 4:25:36 AM7/5/13
to usb4...@googlegroups.com, Harshad RJ
On 07/05/2013 09:42 AM, Harshad RJ wrote:
> In my app I don't see this. My code is something like this:
> *inPipe.open()
> inPipe.addUsbPipeListener( ... )*

So you only open a pipe and wait for data? You are not telling the
device to send something? I think this can't work because the host has
to poll for data.

So in theory you have to do something like this:

1. Add USB Pipe listener to receive the asynchronous data.
2. Open the pipe.
3. Create a IRP with a data buffer large enough for the data sent by the
device.
4. Send this IRP to the device with the asyncSubmit() method.
5. Your pipe listener is called with the received data in the parameter.

You can also do this synchronously by using syncSubmit() instead (Maybe
you are already in a thread and don't care about blocking). Then you
don't need the pipe listener at all.

Unfortunately I don't have an example for you. You may look in the unit
test method "ControlIOTest#testControlIOAsyncSubmitIrp_IN". This test
checks receiving data asynchronously. There is also a Mouse Driver
example in the javax.usb code repo which may be useful (But they use
synchronous communication):

http://javax-usb.cvs.sourceforge.net/viewvc/javax-usb/javax-usb-example/src/

--
Klaus Reimer <http://www.ailis.de/~k/>
[A735 47EC D87B 1F15 C1E9 53D3 AA03 6173 A723 E391]

signature.asc

Harshad RJ

unread,
Jul 5, 2013, 5:14:19 AM7/5/13
to Klaus Reimer, usb4...@googlegroups.com
Thanks Klaus, it worked!

I had tried sending an IRP but hadn't issued it in the right sequence. Your email helped me figure out the right sequence.

--
Harshad RJ

dryggs

unread,
Jul 5, 2013, 10:39:55 AM7/5/13
to usb4...@googlegroups.com, Harshad RJ
Hello Harshad RJ,

I was having some trouble implementing a method to receive from a Interrupt IN endpoint of my USB device. As I saw this, I had a look at the example you attached and didn't get it to work.

When I run the example of the mouse driver, what I get is this:

Found 4 HID-type interfaces.
Found mouse by SubClass/Protocol
Found HID mouse.
Driving HID mouse, move mouse to see movement events.
Press Enter when done.
Unable to submit data buffer to HID mouse : USB error 1: Transfer error on interrupt endpoint: LIBUSB_ERROR_IO


I tried this because when I try to run my application what I get is this:

# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6b614191, pid=6884, tid=2384
#
# JRE version: 7.0_25-b17
# Java VM: Java HotSpot(TM) Client VM (23.25-b01 mixed mode windows-x86 )
# Problematic frame:
# C  [libusb-1.0.dll+0x14191]  windows_clock_gettime_threaded+0x6100
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows

Any ideas what it might be?

Thank you!

Best regards.

dryggs

Harshad RJ

unread,
Jul 6, 2013, 1:47:54 AM7/6/13
to dryggs, usb4...@googlegroups.com
Hi dryggs,

You perhaps have mixed up myself and Klaus. I don't have much knowledge of USB to fully solve my own problems; can't really help  others at this stage :)

best,
--
Harshad RJ

Klaus Reimer

unread,
Jul 6, 2013, 12:32:11 PM7/6/13
to usb4...@googlegroups.com
On 07/05/2013 04:39 PM, dryggs wrote:
> *Found 4 HID-type interfaces.
> Found mouse by SubClass/Protocol
> Found HID mouse.
> Driving HID mouse, move mouse to see movement events.
> Press Enter when done.
> Unable to submit data buffer to HID mouse : USB error 1: Transfer error on
> interrupt endpoint: LIBUSB_ERROR_IO*

I'm note absolutely sure but I guess that you can't access the mouse
with libusb while Windows itself has a driver attached to it.


> I tried this because when I try to run my application what I get is this:
> # C [libusb-1.0.dll+0x14191] windows_clock_gettime_threaded+0x6100

It's hard to help with crashes (especially on Windows and Mac) and
because they normally happen when you are communicating with a device
which I don't own it's hard to reproduce.

If you are familiar with C programming it would help a lot if you could
write a small test C program which directly uses libusbx and which does
the same USB communication where usb4java crashes. If this does crash,
too, then you should consult the libusb Mailing List. If it doesn't then
it may help if you could post the C source and the Java source here.

If you are not able to write such a C program then please try to
minimize your crashing Java application to an absolute minimum and post
it here together with the complete stack trace and logging information.
And also set the environment variable LIBUSB_DEBUG to 4 to get extra
logging info from libusb.
signature.asc

Alejandro Fernandez Herrero

unread,
Jul 6, 2013, 2:50:17 PM7/6/13
to usb4...@googlegroups.com
Harshad

I do think this work is excellent specially for all of us who develop in java.
I'm like you, I can hardly understand the USB paraphernalia.
So if you can share your code to read and write to the device will be helpful for everyone.
How you resolve your listener, etc. 
A small amount of code will help us to understand more.

Thanks.

Alejandro.

Harshad RJ

unread,
Jul 7, 2013, 12:19:43 AM7/7/13
to usb4...@googlegroups.com
Ok, I will try my best.

The Pipe class has a convenient method called syncSubmit(byte[])
This method submits an IRP to the endpoint and byte array is marked as the receiving buffer. If I recall correctly IRP means Interrupt Request Packet (or atleast, I like to think of it that way).

Here's my receive code (in Scala):

 
  def rcvData: Array[Byte] = {
    val data = new Array[Byte](MAX_DATA_SIZE_BYTES)
    val countBytes = inPipe.syncSubmit(data)
    data.take(countBytes)
  }

That's the synchronous version.

The async version is a little more involved:

class Rx_Async(inPipe: UsbPipe) {
  private val queue = new ArrayBlockingQueue[Array[Byte]](2)

  inPipe.addUsbPipeListener(new event.UsbPipeListener {
    def dataEventOccurred(e: event.UsbPipeDataEvent) = {
      val data = e.getData()
      queue.offer(data)
    }

    def errorEventOccurred(e: event.UsbPipeErrorEvent) = {
      println("Error:" + e.getUsbException)
      queue.offer(null)
    }
  })

  def prepareRcv = {
    val data = new Array[Byte](MAX_DATA_SIZE_BYTES)
    inPipe.asyncSubmit(data);
  }

  def rcvData: Array[Byte] = {
    queue.take
  }

}

At first you call rx.prepareRcv(), which returns immediately, and when you actually need the data you call rx.rcvData()

I didn't go much beyond that, as I am stuck understanding the higher-level protocols right now (above USB layer).
If I manage to get more insights I will surely share here.

best,
--
Harshad RJ

Alejandro Fernandez Herrero

unread,
Jul 7, 2013, 12:52:29 PM7/7/13
to usb4...@googlegroups.com
Harshad

Thanks for contributing your code.
I, like you,  find it hard to understand all the nuts and bolts of USB bus.

What I am trying to develop is a driver for a fingerprint reader, but I do not why, when I trying to open the pipe, it is not active.

Thanks

Alejandro.

Harshad RJ

unread,
Jul 9, 2013, 5:57:40 AM7/9/13
to usb4...@googlegroups.com
Klaus,

Can you tell us which version of libusb is included in usb4java? Also, is it a modified version or unchanged from upstream?

thanks,
--
Harshad RJ

Klaus Reimer

unread,
Jul 9, 2013, 7:16:51 AM7/9/13
to usb4...@googlegroups.com
On 07/09/2013 11:57 AM, Harshad RJ wrote:
> Can you tell us which version of libusb is included in usb4java? Also, is
> it a modified version or unchanged from upstream?

On Linux and Windows libusbx-1.0.15 is used.

For Mac I currently use libusb-1.0.16-rc8 because libusbx was too buggy
on Mac.

libusbx and libusb are currently merging back together so I hope in the
future I can use the same library for all operating systems.

I haven't modified these versions. The build script downloads the
original tar balls and compiles them together with the usb4java JNI
wrapper.

The JNI wrapper automatically detects if it is libusb or libusbx so feel
free to compile any libusb/libusbx version yourself and compile usb4java
against it if you have problems with the pre-compiled binaries.
signature.asc

Harshad RJ

unread,
Jul 9, 2013, 8:25:22 AM7/9/13
to usb4...@googlegroups.com

On Tue, Jul 9, 2013 at 4:46 PM, Klaus Reimer <k...@ailis.de> wrote:
On Linux and Windows libusbx-1.0.15 is used.

I am facing some issues; device is disconnecting suddenly. I am not sure if this is my app's problem or something wrong in the various software layers.

Seems like libusbx 1.0.16-rc3 is out. Can you please create a test release of usb4java with this version? I spent some time in compiling by myself as you suggested, but I couldn't manage to. The build is looking for libusb even on Linux, which is confusing, since you say libusbx is required for linux. Am I supposed to override the build scripts?

thanks,
--
Harshad RJ

Harshad RJ

unread,
Jul 9, 2013, 9:38:02 AM7/9/13
to usb4...@googlegroups.com
On Tue, Jul 9, 2013 at 4:46 PM, Klaus Reimer <k...@ailis.de> wrote:
The build script downloads the
original tar balls and compiles them together with the usb4java JNI
wrapper.

Which is the build script that downloads the tar balls? I was trying to build inside the src/main/c directory using autoconf tools

--
Harshad RJ

Klaus Reimer

unread,
Jul 9, 2013, 9:44:46 AM7/9/13
to usb4...@googlegroups.com
On 07/09/2013 03:38 PM, Harshad RJ wrote:
> Which is the build script that downloads the tar balls? I was trying to
> build inside the src/main/c directory using autoconf tools

See here:

https://github.com/kayahr/usb4java/tree/master/src/main/c/build

But these scripts are only meant to build the binaries which are shipped
with usb4java. If you just want to use a locally installed libusb then
it is better to simply compile the usb4java JNI wrapper with the
autoconf tools in src/main/c. If libusb is correctly installed locally
then this should work:

$ ./autogen.sh (Only needed once)
$ ./configure
$ make
signature.asc

Harshad RJ

unread,
Jul 9, 2013, 10:13:02 AM7/9/13
to usb4...@googlegroups.com
Ah thanks. The compile was failing with the the configure/make as well as build script. This is on Ubuntu 13.04. However, I found a workaround:

In usb4java.h, the line which includes libusb.h needs to be changed to:
#include <libusb-1.0/libusb.h>


How do I generate the:
usb4java-*.jar           (The full JAR with native libraries included)

I suspect this involves maven, but I don't have much knowledge of it. Any tips would be appreciated.

--
Harshad RJ

Klaus Reimer

unread,
Jul 9, 2013, 11:03:30 AM7/9/13
to usb4...@googlegroups.com
On 07/09/2013 04:13 PM, Harshad RJ wrote:
> Ah thanks. The compile was failing with the the configure/make as well
> as build script. This is on Ubuntu 13.04. However, I found a workaround:
> In usb4java.h, the line which includes libusb.h needs to be changed to:
> #include <*libusb-1.0*/libusb.h>

Not a good solution. The libusb team doesn't like this at all. The
include path is automatically manages by pkgconfig. Did you install
libusb manually? Ubuntu has a package for it (libusb-1.0-0-dev).

I'm using the same Ubuntu version and compilation works fine here.

What are the exact error messages you are getting when compiling the beast?


> How do I generate the:
> usb4java-*.jar (The full JAR with native libraries included)

You don't have to. Just use the usb4java-nonatives.jar and place your
native libs into your own project in the class path under the path
de/ailis/usb4java/libusb/linux-x86 (Or linux-x86_64, if you are using 64
bit linux).
signature.asc

Harshad RJ

unread,
Jul 9, 2013, 12:31:45 PM7/9/13
to usb4...@googlegroups.com
On Tue, Jul 9, 2013 at 8:33 PM, Klaus Reimer <k...@ailis.de> wrote:
On 07/09/2013 04:13 PM, Harshad RJ wrote:

Not a good solution. The libusb team doesn't like this at all. The
include path is automatically manages by pkgconfig. Did you install
libusb manually? Ubuntu has a package for it (libusb-1.0-0-dev).

I used the package. pkg-config --cflags libusb doesn't return anything.  However pkg-config --cflags libusb-1.0 works.


 
What are the exact error messages you are getting when compiling the beast?

Just that one error: libusb.h not found

 
You don't have to. Just use the usb4java-nonatives.jar and place your
native libs into your own project in the class path under the path
de/ailis/usb4java/libusb/linux-x86 (Or linux-x86_64, if you are using 64
bit linux).

Yeah, but making the full jar would help in testing different versions, since I am already using the full jar.

If it's too complex to document, let it go; I can manage with the exploded jar.

--
Harshad RJ

Klaus Reimer

unread,
Jul 9, 2013, 12:35:30 PM7/9/13
to usb4...@googlegroups.com
On 07/09/2013 06:31 PM, Harshad RJ wrote:
> I used the package. pkg-config --cflags libusb doesn't return anything.
> However pkg-config --cflags libusb-1.0 works.

Same here. Looks correct. What's the output? Should be:

-I/usr/include/libusb-1.0
signature.asc

Klaus Reimer

unread,
Jul 9, 2013, 12:37:45 PM7/9/13
to usb4...@googlegroups.com
On 07/09/2013 02:25 PM, Harshad RJ wrote:
> Seems like libusbx 1.0.16-rc3 is out. Can you please create a test
> release of usb4java with this version?

I upgraded the current HEAD to libusbx 1.0.16-rc3. I also had to rename
some stuff because they renamed the getPortPath to getPortNumbers.

If you want to try this out then you can use the latest snapshot from here:

http://nexus.ailis.de/content/groups/public/de/ailis/usb4java/usb4java/1.0.1-SNAPSHOT/

But only the linux binaries are up-to-date. Haven't recompiled Windows
and Mac yet.
signature.asc

Harshad RJ

unread,
Jul 9, 2013, 1:54:43 PM7/9/13
to usb4...@googlegroups.com


On Tuesday, 9 July 2013 22:05:30 UTC+5:30, Klaus Reimer wrote:
Same here. Looks correct. What's the output? Should be:

  -I/usr/include/libusb-1.0

That's the output. But it isn't used by the config script. It uses "--cflags libusb" instead (I think).
Reply all
Reply to author
Forward
0 new messages