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.

Android, Beagleboard, Kernel and the DSP-Bridge

Application access to the DSP
Application access to the DSP

The Beagleboard features a Digital Signal Processor (TMS320C64x+ DSP). For our spectrum analyzer it would be a very nice feature to calculate the FFT in the DSP.

To access the DSP the Kernel needs to implement the DSP-Bridge driver. However, it is quite challenging to get the driver into the Kernel. Several attempts to patch the Embinux Kernel with the original patches failed. [Embinux Kernel Git Repository]

The good news is that the omap-kernel (linked in the Android Git repository) features the DSP-Bridge driver that we were looking for. [Android omap Kernel Git Repository]

The challenge was to get the Kernel running on the Beagleboard. We had first given up on it since the USB-Host Controller was not working. But after trying every other Kernel (Embinux, 0xdroid, mainline omap kernel, etc.) we gave it another try. Since we are booting an NFS Root File System we needed USB and Ethernet support on startup time. The key is to configure the Beagleboard’s USB-OTG as a Host Device. This can be done in the menuconfig of the Kernel. This was not the only challenge. A Kernel panic occurred when looking for the init file.
The solution was to configure the Kernel properly and including all Android driver modules (which seems kind of obvious at this point). To give you an idea of how the config of the 2.6.29 Android Omap Kernel could look like you can check our .config out here. [.config file]

Android now boots correctly.

Well, there is still one problem though. The Input Event Subsystem seems to be messed up, thus our keyboard and mouse is not working at all.
The Event Input Subsystem works now properly with the above .config file.

To break it down:

Working with the omap-Kernel of the Google Git repositories we can state the following:
Pro:

  • DSP-Bridge Driver
  • Nicely maintained by a big community

Con:

  • USB-Host Controller not working yet (USB OTG in host mode works)

Project Overview

update

During the last few weeks we have been putting together our platform. For an overview of what our platform and application looks like we have put together our Project Application site.  Also be sure to check out our guide for “Debugging Android Applications on the Beagle Board with Eclipse” on our Development Guide.

In the following weeks we are going to brush up our Development Guide and give detailed information about Kernel and Root File System as well as further application porting (i.e. libusb). We also have gathered lots of information about how to work with AIDL for Services and JNI without Androids’ NDK. So stay tuned for fully packed guides and updates.

Changing the uBoot Splash Screen

To change the uBoot Splash you need to compile your own uBoot image and move it to your SD Card or flash it to your System. We recommend to stick with the SD/MMC solution and thus have still a fallback solution on your flash.

You can get the sources for uBoot from the denx git repository.

git clone git://git.denx.de/u-boot.git u-boot-main
cd u-boot-main
git checkout --track -b omap3 origin/master

Download the following u-boot_v1_beagle_logo.patch and patch the files in the u-boot-main folder you just created. Now you may adjust your splash screen. It is stored in the logo.h header file in the beagle board folder.
Display the header file using gedit

gedit board/omap3/beagle/logo.h



edit the header file
edit the header file

To create a new Splash you can use GIMP to export the graphic as “.h” file.
You can then copy the *header_data array to the logo.h and adjust beagle_width and beagle_height to your image size.


Once saved you can now compile your u-Boot.bin with the following commands:

make CROSS_COMPILE=arm-none-linux-gnueabi- mrproper
make CROSS_COMPILE=arm-none-linux-gnueabi- omap3_beagle_config
make CROSS_COMPILE=arm-none-linux-gnueabi-

Note: you can set the CROSS_COMPILE prefix to the path of your favorite cross compiler. We used the Codesourcery toolchain available here.

Done! Copy your u-boot.bin to your MMC/SD card. Insert your card and boot your Beagle Board; you should now see your customized Splash Screen.

Note:
Normally your uBoot is loaded from u-boot.bin on your SD/MMC-Card. Yet all arguments are taken from the NAND-Flash unless you create a boot script on your SD/MMC. More information about how to build a boot script can be found on our Developing on an Embedded System site.

Android Platform Development Kit

PDK HTML Documentation
PDK HTML Documentation

Looking for documentation and information about platform development we stumbeld across the Android PDK (Platform Development Kit) in the development directory of the Android source.

Thanks to the guide found at http://heejindev.wordpress.com/2009/06/18/how-to-build-android-pdk/ we were able to successfully build the html documentation.
To make the documentation work we needed to put the online-pdk directory (./out/target/common/docs/online-pdk/) under our Apache server root.

There is an online version of the PDK at

http://www.kandroid.org/online-pdk/guide/

http://pdk.android.com/online-pdk/guide/index.html