Porting Libusb for Android on the Beagleboard in 5 steps

USB & Android
USB & Android

It is long overdue to talk about porting specific projects to Android. It is astonishingly easy to do so with the Android platform.
Since we are using USB for our project we found it convenient to work with libusb 1.0. Using the Beagleboard we are able to make use of the USB 2.0 high speed functionality of libusb.

Libusb itself consists of a shared library and two sample applications. One of those applications is the lsusb command which lists connected USB devices in the console.

These five Steps is all it takes to port the existing libusb open source project to the Android platform.



1. Get the libusb-1.0 sources [link] and create an empty “libusb-1.0.3″ folder in the external directory of your Android sources. Unpack the libusb folder into the new directory.

2. Create Android.mk files in each of the libusb directories. In the top folder your Android.mk just calls your mk files in the libusb subfolders :

LOCAL_PATH := $(call my-dir)
subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
libusb \
))
include $(subdirs)
LOCAL_PATH := $(call my-dir)
ubdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
		libusb \
))
include $(subdirs)

in the libusb folder add the following Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
 core.c \
 descriptor.c \
 io.c \
 sync.c \
 os/linux_usbfs.c

LOCAL_C_INCLUDES += \
external/libusb-1.0.3/ \
external/libusb-1.0.3/libusb/ \
external/libusb-1.0.3/libusb/os

LOCAL_MODULE:= libusb
include $(BUILD_SHARED_LIBRARY)

You see the syntax of these Android.mk files is very simple. You just tell the compiler what modules you want to include and where your header files are.

3. Soon we are ready to compile the library; if we do so now, we will notice that the macro TIMESPEC_TO_TIMEVAL is not defined by the sources inside Android. To overcome this problem we just need to define the macro in the lubusb/io.c file.

#define TIMESPEC_TO_TIMEVAL(tv, ts)                                     \
        do {                                                            \
                (tv)->tv_sec = (ts)->tv_sec;                            \
                (tv)->tv_usec = (ts)->tv_nsec / 1000;                   \
        } while (0)

If you compile your libusb now, there is going to be the following error: build/tools/apriori/prelinkmap.c(137): library ‘libusb.so’ not in prelink map. This is because Android keeps track of all the shared libraries of the root file system (RFS). Therefore we need to add the library to the prelinked map found in ./build/core/prelink-linux-arm.map. We did so and just added libusb.so below libqcamera.so.

libqcamera.so       0xA9400000
libusb.so           0xA8000000

You are now all set to compile libusb. Execute the following commands in your Android root directory:

$ . build/envsetup.sh
$ choosecombo

Choose your build variant. Afterwards you can compile the whole RFS with make or just that one project:

mmm -j4 /external/libusb

4. Your library is ready… but your usb-file system is almost certainly not mounted yet. In your init.rc of the RFS add the following command to mount your USBFS.

mount usbfs none /proc/bus/usb -o devmode=0666

Add the line somewhere below the “on boot” event.

5. Now we need to compile lsusb. The sources are located in the examples folder of libusb. Create a folder lsusb in the ./external directory of the Android sources. Copy the lsusb.c module into it and create a Android.mk file:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES:= lsusb.c
LOCAL_MODULE := lsusb
LOCAL_C_INCLUDES += external/libusb-1.0.3/
LOCAL_SHARED_LIBRARIES := libc libusb
include $(BUILD_EXECUTABLE)

Execute the build command:

mmm -j4 /external/lsusb

and we are done! Congratulations! You just ported an entirely non-Android specific project to your Android platform!

Simply execute lsusb in your Android shell to verify if everything worked properly.

Update 15.07.2011
Thank you for all your comments. With the new Android versions there are a few things that changed for the tutorial.

  • 1. To correct the devmode you now need to adjust the uevent.rc file rather than the init.rc.
  • 2. The Android.mk requires LOCAL_MODULE_TAGS since Froyo. (for ex. LOCAL_MODULE_TAGS = eng user)
  • 3. It became pretty easy to exclude files from the prelinked map. Add LOCAL_PRELINK_MODULE := false to your Android mk files.
  • 4. As “kos” pointed out the sources will now compile when using ./configure –disable-timerfd before building to avoid compiling errors.

48 thoughts on “Porting Libusb for Android on the Beagleboard in 5 steps”

  1. Pingback: Kylie Batt
  2. lsusb only displays vendor ID and device ID, while i wanna check the Vendor name and Device name. How could i do that?

  3. hi , i use adb shell to type lsusb but it show usb_init is fail,so i check libusb code i discover /proc/bus/usb is exist but no any usb device node so it is fail, so can anyone can tell me how to simulate usb device on android or how to solve this is issue ?
    thanks

  4. I am getting the following error when building lsusb (mmm -j4 /external/lsusb):

    make: *** No rule to make target `/lsusb.c’, needed by `out/target/product/passion/obj/EXECUTABLES/lsusb_intermediates/lsusb.o’. Stop.

    I believe the problem has to do with the ‘/’ in front of lsusb.c above.

    I have created the Android.mk file as stated above. libusb builds successfully. Are any other makefiles required or any modifications to Android/platform makefiles required?

    Any ideas?

    Thanks.

  5. Can we transfer the data (with folders, files, …) into USB pendrive which is enabled to target board? Can you tell how to mount file system for the USB pendrive to transfer the dat to nad from the device through the libusb.
    What are the steps we have to do?
    Anyone knows please forward me.

  6. lsusb executable command works fine but, the files in /proc/bus/usb are not exist, the info for the ports are not exits, where could i find.
    please help me.

  7. Can we transfer the data (with folders, files, …) into USB pendrive which is enabled to target board? Can you tell how to mount file system for the USB pendrive to transfer the data to and from the device through the libusb shared object.
    what modification to do it?
    What are the steps we have to do?
    Anyone knows please forward me.

  8. I have a few questions regarding libusb, maybe I am missing the point but I do not understand how/where the libusb.so file is transfered on the device.

    In step 3, the libusb is build. This should output a libusb.so, right?
    In step 4, the USBFS is mounted (this step is on the device).

    My question is how can this work, if the libusb.so file is not copied to- or installed on the device?

    My other question is: how do you write the mount command in the init.rc file, since this file is write protected?

    Can somebody please explain?

    1. Hello Jelle!

      If you are using your Beagleboard then you also should have write permission to the root file system. Or you can change your init.rc upon Android build time. Or even better, copy your own init.rc to the out folder after building.

      You can compile libusb for your RFS, for that purpose you can download the Android sources of libusb and place them in your external folder. Refer to http://web.fhnw.ch/technik/projekte/eit/Fruehling2010/DiCerRud/files/changestorfs.tar.gz for the Files.

      Try this line in init.rc to mount the usbfs:
      mount usbfs none /proc/bus/usb devmode=0666

      You can find the complete file here:
      http://web.fhnw.ch/technik/projekte/eit/Fruehling2010/DiCerRud/files/binaries.tar.gz

      I hope this will get you rolling. :)

      Cheers
      Manuel

  9. im getting compilation error wiith above steps in android 2.2 for beagleboard with libusb.

    external/libusb-1.0.8/libusb/io.c:1037: warning: implicit declaration of function ‘timerfd_create’
    external/libusb-1.0.8/libusb/io.c:1038: error: ‘TFD_NONBLOCK’ undeclared (first use in this function)
    external/libusb-1.0.8/libusb/io.c:1038: error: (Each undeclared identifier is reported only once
    external/libusb-1.0.8/libusb/io.c:1038: error: for each function it appears in.)

    1. Hello There,

      I have not yet tried to compile it with 2.2, nor with gingerbread… Are you crosscompiling in the the Android environment (i.e. using mmm)?

  10. @Manuel Di Cerbo
    OK ,i was able to compile it with 2.2,but with –disable-timerfd support….as sys/timerfd.h is not there in android and linux/timerfd is there but with limited support.
    Did you faced any such problem.

  11. Manuel,

    Thanks for posting this useful guide.

    I am building this for a Android 2.2 archos tablet. After building libusb and lsusb I copied them to system/lib and system/bin folders respectively on the target device. When I run lsusb on the tablet I get the following error:

    # lsusb
    link_image[1995]: failed to link lsusb
    CANNOT LINK EXECUTABLE

    Appreciate any help,
    Thx

  12. Hi there,

    it looks like the lsusb.so is not found on the system (my guess). Maybe it is a permission problem? Is libusb executable?
    To investigate I would try to link against another library or even create your own test-library… If I had to guess I’d say it’s probably not directly related to libusb.

    Hope it helps to get a start…

  13. Hi,

    Please help me out, I successfully ported ur libusb & lsusb to eclair, but the thing is when I issue lsusb its displaying nothing, what might be missing, m I need to enable something in kernel configuration for this, please let me know.

    Thanks Regards,
    Santosh

    1. It seems that you have not mounted the USB File System. To do so, you can either use mount from the console or just add this line to your init.rc script:

      intit.rc:
      ….
      mount usbfs none /proc/bus/usb devmode=0666

      shell command:
      mount -t usbdevfs none /proc/bus/usb

      Note: I didn’t test the shell command, I found it under: http://ubuntuforums.org/showthread.php?t=879275 although I am pretty sure it will do :)

      Cheers
      Manuel

  14. Hiya,

    THANK YOU for making this information available. I have an important project for work and I plan to follow your instructions to solve a difficult problem we have. I hope to report back soon with good news thanks to you.

  15. Hi,
    Thank you so much for the instructions, i have successfully ported lsusb and got a native application running via terminal emulator on the device. But i have a bit of a problem regarding permission when exporting the same user space driver to android application.
    i encounter permission denied while i try to do libusb_init(); using a java application

    Could you be kind enough to guide me further on this

    Thanks and Regards
    Pramit

    1. Dear Pramit

      If you are using the Gingerbread build then you need to adjust your uevent.rc file to fix the permission issue.
      Look for the line

      /dev/bus/usb/* 0660
      and replace it with
      /dev/bus/usb/* 0666

      Cheers
      Manuel

  16. Dear Manuel,

    Hi, I am porting libusb to android tablet with gingerbread(2.3.3).

    I tried to compile according to this site.
    But I am getting compile error message as following.

    ===============quote================

    jun@jun-laptop:~/WORKING_DIRECTORY/external/libusb-1.0.3$ mm
    ============================================
    PLATFORM_VERSION_CODENAME=REL
    PLATFORM_VERSION=2.3.3
    TARGET_PRODUCT=generic
    TARGET_BUILD_VARIANT=eng
    TARGET_SIMULATOR=false
    TARGET_BUILD_TYPE=release
    TARGET_BUILD_APPS=
    TARGET_ARCH=arm
    HOST_ARCH=x86
    HOST_OS=linux
    HOST_BUILD_TYPE=release
    BUILD_ID=GRI40
    ============================================
    make: Entering directory `/home/jun/WORKING_DIRECTORY’
    target thumb C: libusb <= external/libusb-1.0.3/libusb/core.c
    external/libusb-1.0.3/libusb/core.c:21:20: error: config.h: No such file or directory
    In file included from external/libusb-1.0.3/libusb/core.c:33:
    external/libusb-1.0.3/libusb/libusbi.h: In function 'usbi_transfer_get_os_priv':
    external/libusb-1.0.3/libusb/libusbi.h:257: warning: pointer of type 'void *' used in arithmetic
    external/libusb-1.0.3/libusb/libusbi.h:258: warning: pointer of type 'void *' used in arithmetic
    external/libusb-1.0.3/libusb/libusbi.h:259: warning: pointer of type 'void *' used in arithmetic
    external/libusb-1.0.3/libusb/core.c:40:2: error: #error "Unsupported OS"
    external/libusb-1.0.3/libusb/core.c: At top level:
    external/libusb-1.0.3/libusb/core.c:602: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'ssize_t'
    external/libusb-1.0.3/libusb/core.c:649: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
    external/libusb-1.0.3/libusb/core.c:670: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'uint8_t'
    external/libusb-1.0.3/libusb/core.c:680: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'uint8_t'
    external/libusb-1.0.3/libusb/core.c:726: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:775: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:811: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'libusb_device'
    external/libusb-1.0.3/libusb/core.c:824: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
    external/libusb-1.0.3/libusb/core.c:868: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:959: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'libusb_device_handle'
    external/libusb-1.0.3/libusb/core.c:1017: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
    external/libusb-1.0.3/libusb/core.c:1078: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'libusb_device'
    external/libusb-1.0.3/libusb/core.c:1103: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1172: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1203: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1240: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1285: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1320: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1346: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1365: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1388: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1413: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1452: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
    external/libusb-1.0.3/libusb/core.c:1466: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    external/libusb-1.0.3/libusb/core.c:1523: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
    make: *** [out/target/product/generic/obj/SHARED_LIBRARIES/libusb_intermediates/core.o] Error 1
    make: Leaving directory `/home/jun/WORKING_DIRECTORY'
    ================unquote===================
    Why I got compile error message?
    Do I have wrong procedure?

    Please help me.

    Yours sincerely
    Jun

  17. Hi Jun

    this sounds really really strange … did you take our sources?

    external/libusb-1.0.3/libusb/core.c:21:20: error: config.h: No such file or directory

    seems to be the core problem…

    Regards
    Manuel

  18. Hi Manuel,
    First, thanks for writing the tutorial. I am running gingerbread.

    Had the same problem as Jun. I realized I have to run “./configure –disable-timerfd” before, to get the config.h. Then everything compiles as you said.

    Also, had to add some sort of LOCAL_MODULE_TAGS in the Android.mk

    Maybe you could add these steps to the tutorial.

    1. Hi kos

      Thanks a lot! It seems indeed the better choice to use configure rather than to modify the source code, I didn’t know that. Will update the post :)

      Regards
      Manuel

  19. hi,
    great posted will sure make use of it. i also had a question related to porting specific projects to android (specifically x86 but that shouldn’t be of any issue). Anyway i wanted to try port a project (currently runs in other Linux distro ie.ubuntu), but im still trying to figure out the compilation issues, the project im working on is built around gnu compiler which and makes use of gun libc. Where in android its pretty much bionic, so i guess my question is where do i start with compiling this projects source code against bionic libc. I thought if i can first get it to compile against the bionic libc, then i can later sort out the issues with it running with android. i was even possibly thinking if possible i could even have my android source tree separate from this projects source atleast while trying to amend the differences with compiling, but would later integrate this project into my android tree once the libc issues have been sorted. not soo sure if this part is possible, im fears are building within my android source tree could mess things up.

  20. i have one external device in which FDTI FT232BM chip and It is a USB device that emulates a RS232 interface. ), it appears as a RS232 port to talk to the Atmel AT90LS8535 processor …. so i need to read data from external device and display on my android device.
    1) it’s possible to read data from external device and display in android device ?
    2) specific android os require or any android OS working ?
    3) Android native programme create for this functionality ?
    4) Porting libusb help for my project ?

    1. Hi Samit

      1) Yes of course, you need to pass the data through JNI tough if you want to program with Java.
      2) I don’t really know what you mean, but it will work with any android since we just use linux features…
      3) You are going to be writing NDK code, yes, to glue the native code together with the Java side
      4) You won’t require libusb, just use the Serial FTDI driver as described in our blogpost http://android.serverbox.ch/?p=285.

      Regards
      Manuel

  21. Hi guys,

    What Linux distro does your Beagle Board run and how does it expose USB ports? You know that libusb needs file-type devices either as /proc/usb/001/001 or /dev/bus/usb/001/001 e.g. for USB device 1 on bus 1.

    I have an Android box where the device would rather show as /dev/usbdev1.1. I found that libusb works when I create a ‘fake’ directory /dev/bus/usb/001 and hard link the node 001 to /dev/usbdev1.1. It works insofar as that I can use libusb to enumerate devices and query configurations — haven’t tried I/O yet. A patch to libusb might make it pick up devices from /dev/usbdevX.X straight away.

    1. Hey Hank

      Thanks for pointing that issue out… We have used the Rowboat distro on the BB xM (gingerbread) and as I remember the devfs was in the form /proc/bus/usb/001/001 … I guess it would be nice if the guys from libusb would consider the alternative notation to pick it up.

      Regards
      Manuel

  22. Hey Manuel,
    This is a great guide. I’ve never used libusb before, but I am doing a project right now on a Beagleboard xM with Gingerbread Dev Kit 2.1. I need to do communicate over the USB with a Zigbee modem and I was wondering if libusb can be used to do the read/write in that case. Thanks

    1. Hello Fern_G

      Thank you for your comment. I guess that your ZigBee module will probably offer you a serial device (dev/ttyUSB0 or similar) when you connect it. As long as you have your USB-Serial drivers installed you are good to go without the need of programming USB. You can use a serial API (look for a “terminos”-tutorial). Mind that I have never actually worked with a Zigbee-Module… but I read a datasheet a while back.

      Hope that helps :)

      Regards
      Manuel

      PS: Actually I wrote a post that includes some “serial” code: http://android.serverbox.ch/wp-content/uploads/2011/06/simpleserial.zip on http://android.serverbox.ch/?p=285
      Be sure that your serial device (the /dev/ttyUSB0) has the right permission for your code.

  23. Thanks for the speedy reply Manuel,
    Do i require a device specific driver for all the devices I want to communicate with them over the USB? (I’ll need to eventually read/write to other devices such as a laptop, PLC modem over a USB-rs232 adapter) Or does libusb let me skip all the driver level coding? Sorry I am kind of an amateur with serial communication.

    1. Hey Fern

      Happy to help :) Well you need your kernel drivers for all the hardware you want to use. Most of the “standard” drivers are already available. If you look for a specific driver however (profilic, ftdi serial driver for instance) you might be required to build those kernel modules (or statically add them to your kernel).
      In your case you will be skipping USB-coding entirely since there are already drivers that let you easily communicate :)

      Regards
      Manuel

  24. HI Manuel,

    i have to establish a communication between an external device and an android device by using usb to serial port.

    but i am facing some issues, when i plug in the external device to Ubuntu, ttyACM* has been created, but it is not recognized on the android device.

    i’ve problem to install the cdc-acm.ko to the android device.

    Can i use the above guideline to achieve my goal? or do u have other option for me? The device is not FTDI.

    Thanks a lot!

  25. Hi ,
    I have followed all the steps but i am getting following error when i am trying to build the source

    make: *** No rule to make target `out/host/linux-x86/bin/acp’, needed by `out/target/product/generic/symbols/system/lib/libusb.so’. Stop.

    Please tell me the possible source of error. I am stuck on this error ..

    Warm Regards,
    Vineet Pant

  26. My buddy helped me ou and I was able to build libusb and lsusb..
    I am no sure if it will work but it built..

    In the User space ..
    source build/envsetup.sh
    lunch <— choose the right option.

    $ sudo apt-get install libtool automake autoconf
    In folder external/libusb-1.0.3/
    $ ./autogen.sh
    $ ./configure –disable-timerfd ## This makes config.h

    My Android.mk file
    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)

    LOCAL_SRC_FILES:= \
    core.c \
    descriptor.c \
    io.c \
    sync.c \
    os/linux_usbfs.c \
    os/threads_posix.c \

    LOCAL_C_INCLUDES += \
    external/libusb-1.0.3/ \
    external/libusb-1.0.3/libusb/ \
    external/libusb-1.0.3/libusb/os

    LOCAL_CFLAGS += -DLIBUSB_DESCRIBE=""

    LOCAL_MODULE:= libusb
    LOCAL_MODULE_TAGS:= debug
    LOCAL_PRELINK_MODULE:= false
    include $(BUILD_SHARED_LIBRARY)
    Inside external/libusb-1.0.3/libusb :

    $ mm

    For lsusb:
    Android.mk
    LOCAL_PATH:= $(call my-dir)

    include $(CLEAR_VARS)
    LOCAL_SRC_FILES:= lsusb.c
    LOCAL_MODULE := lsusb
    LOCAL_C_INCLUDES += external/libusb-1.0.3/
    LOCAL_C_INCLUDES += external/libusb-1.0.3/libusb/
    LOCAL_SHARED_LIBRARIES := libc libusb
    LOCAL_MODULE_TAGS := debug
    include $(BUILD_EXECUTABLE)

    1. checking build system type… Invalid configuration `–-disable-timerfd’: machine `–-disable’ not recognized
      configure: error: /bin/bash ./config.sub –-disable-timerfd failed

      I am getting the above error. Any insight ??

      Thank you
      Muthuvel

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>