Porting Libusb for Android on the Beagleboard in 5 steps
只需 5 步移植 libusb 到 Beagleboard 上的 Android
译自:http://android.serverbox.ch/?p=151
It is long overdue to talk about porting specific projects to Android.
移植指定工程到 Android 上是个长久的话题。
It is astonishingly easy to do so with the Android platform.
基于 Android 平台的移植是异常容易的。
Since we are using USB for our project
we found it convenient to work with libusb 1.0.
由于我们的工程使用 USB ,我们发现使用 libusb 1.0 方便工作。
Using the Beagleboard
we are able to make use of the USB 2.0 high speed functionality of libusb.
使用 Beagleboard 我们能够使用 libusb 的 USB 2.0 高速功能。
Libusb itself consists of a shared library and two sample applications.
Libusb 自身由两个简单的应用程序和一个共享库构成。
One of those applications is the lsusb command which lists connected USB devices in the console.
其中一个应用程序是 lsusb 命令,在控制台上列出已连接 USB 设备。
These five Steps is all
it takes to port the existing libusb open source project to the Android platform.
只需 5 步即可移植存在的 libusb 开源工程到 Android 平台。
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.
从 https://libusb.org/wiki/libusb-1.0 得到 libusb-1.0 源代码,
并且在你的 Android 源代码的 external 目录中创建一个空的 libusb-1.0.3 文件夹。
注:翻译此文时的 libusb 最新版是 libusb-1.0.9 。
Unpack the libusb folder into the new directory.
解包 libusb 文件夹到新目录中。
2.Create Android.mk files in each of the libusb directories.
在 libusb 目录中的每一个文件夹下创建 Android.mk 文件。
In the top folder your Android.mk just calls your mk files
in the libusb subfolders :
在顶级目录中的 Android.mk 文件只需调用 libusb 子目录中的 Android.mk 文件即可,内容如下:
LOCAL_PATH := $(call my-dir)
subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, libusb))
include $(subdirs)
in the libusb folder add the following Android.mk
在 libusb 目录中添加如下 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.
你看这些 Android.mk 文件的语法是非常简单的。
You just tell the compiler what modules you want to include
and where your header files are.
你只需告诉编译器你想要模块包含什么和你的模块需要的头文件在哪里。
注:1. 和 2. 步,我在实现编译 libusb 静态库时,用的文件目录结构如下:
libusb-1.0.9
|-jni
|-将 libusb 解包出来的统统放到新建的 jni 文件夹下,不然 ndk-build 不编译
|-新建一个 Android.mk
|-新建一个 Application.mk
jni/Android.mk 文件内容:
include $(call all-subdir-makefiles)
jni/Application.mk 文件内容:
# 该变量是可选的,指出你的应用程序工程名
APP_MODULES := libusb
jni/libusb/Android.mk 文件内容:(注:不编译全部源代码文件)
# 提供当前文件的路径,必须定义它在你的 Android.mk 文件的开始处
LOCAL_PATH := $(call my-dir)
# CLEAR_VARS 变量是由生成系统已提供的,
# 并且指出一个特殊的 GNU Makefile 文件为你清除除了 LOCAL_PATH 以外的许多的 LOCAL_* 变量,
# 这是必须的,因为全部的生成控制文件是在一个单独的 GNU Make 执行环境中被分析的,
# 在那里所有的变量是全局的。
include $(CLEAR_VARS)
# 该变量是必须定义的,用来标识你的 Android.mk 文件中描述的每个模块,
# 模块名字必须是唯一的,并且不能包含任何的空格。
LOCAL_MODULE:= usb
# 该变量是必须包含将要生成且汇编成一个模块所需的 C / C++ 源文件的列表。
# 注意:不列出头文件和包含文件在这里,因为生成系统将自动地为你估算信赖。
# libusb-0.1.8 只需改成如下源代码文件即可!
#LOCAL_SRC_FILES := usb.c \
# linux.c \
# error.c \
# descriptors.c
LOCAL_SRC_FILES := core.c \
descriptor.c \
io.c \
sync.c \
os/linux_usbfs.c \
os/threads_posix.c
# 一个可选的路径列表,做为 include 搜索路径之一。
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
$(LOCAL_PATH)/os \
$(LOCAL_PATH)/../
# 不定义此 LIBUSB_DESCRIBE 宏会报错的
LOCAL_CFLAGS += -DLIBUSB_DESCRIBE=""
# 编译成静态库
include $(BUILD_STATIC_LIBRARY)
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.
如果我们现在开始做,我们将看到 TIMESPEC_TO_TIMEVAL 宏未在 Android 源代码里面定义的错误。
To overcome this problem we just need to define the macro
in the libusb/io.c file.
对于解决该问题的方法是我们只需在 libusb/io.c 文件中定义此宏即可!
注:按我的静态库编译文件目录结构来看,是在 jni/libusb/io.c 。
#define TIMESPEC_TO_TIMeval_r(tv, ts) \
do { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
} while (0)
注,最好写成:
#ifndef TIMESPEC_TO_TIMEVAL
#define TIMESPEC_TO_TIMeval_r(tv, ts) \
do { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
} while (0)
#endif
If you compile your libusb now,
there is going to be the following error:
如果你现在编译 libusb 的话,将有如下错误:
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).
这是因为 Android 跟踪 root 文件系统(RFS) 的全部共享库。
Therefore we need to add the library to the prelinked map
found in ./build/core/prelink-linux-arm.map.
因此,我们需要添加该库到预链接表中,
该表位于 Android 源代码目录的 ./build/core/prelink-linux-arm.map 。
We did so and just added libusb.so below libqcamera.so.
我们只能在 libqcamera.so 下添加 libusb.so 。
libqcamera.so 0xA9400000
libusb.so 0xA8000000
You are now all set to compile libusb.
你到现在全部设置完毕只差编译 libusb 了。
Execute the following commands in your Android root directory:
在你的 Android 根目录下执行如下命令:
$ . build/envsetup.sh
$ choosecombo
Choose your build variant.
选择你的生成变种。
Afterwards you can compile the whole RFS with make or just that one project:
以后你可以用 make 编译整个 RFS 或仅是其中一个工程。
mmm -j4 /external/libusb
4.Your library is ready…
but your usb-file system is almost certainly not mounted yet.
你的库是准备好了...
但是你的 usb-file 系统是还是几乎无法挂载。
In your init.rc of the RFS add the following command to mount your USBFS.
在你的 RFS 的 init.rc 中添加如下命令来挂载你的 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.
现在我们需要编译 lsusb 。
The sources are located in the examples folder of libusb.
它的源代码位于 libusb-1.0.9/examples 目录中。
Create a folder lsusb in the ./external directory of the Android sources.
在 Android 源代码的 .external 目录 中创建一个 lsusb 文件夹。
Copy the lsusb.c module into it and create a Android.mk file:
拷贝 lsusb.c 文件到 ./external/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_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!
你刚刚移植了一个完全地非 Android 指定的工程到你的 Android 平台!
Simply execute lsusb in your Android shell to verify
if everything worked properly.
如果全部都已工作的话,在你的 Android shell 中简单地执行 lsusb 去做验证。
Update 15.07.2011
更新于 2011年07月15日
Thank you for all your comments.
感谢你的全部注释。
With the new Android versions
there are a few things that changed for the tutorial.
由于新的 Android 版本,以上指南中有几处发生了变化。
1.To correct the devmode you now need to adjust the uevent.rc file
rather than the init.rc.
去纠正 devmode 你现在调整 init.rc 倒不如调整 uevent.rc 。
2. The Android.mk requires LOCAL_MODULE_TAGS since Froyo.
(for ex. LOCAL_MODULE_TAGS = eng user)
从 Froyo 之后 Android.mk 需要 LOCAL_MODULE_TAGS 。
3. It became pretty easy to exclude files from the prelinked map.
从预链接表中排除文件变得相当容易。
Add
添加
LOCAL_PRELINK_MODULE := false
to your Android.mk files.
到你的 Android.mk 文件中。
4. As “kos” pointed out the sources will now compile
when using ./configure –disable-timerfd
before building to avoid compiling errors.
同样地, kos 指出的源代码将马上编译,为了避免一些与 timerfd 相关的编译错误出现,
应在执行 ./configure 配置 libusb 时,加上 –disable-timerfd 参数,如:
./configure –disable-timerfd