1. 简介
ADB 是 Android 环境下非常好用的调试工具。它是 client-server架构,由三部分组成:
- 1、client (
adb
),运行于开发机器 (Host
) ,你可以在shell中调用adb命令,其它的Android工具比如ADT插件和DDMS也包含adb client。 - 2、server (
adb server
),作为后台进程同样运行于开发机器 (Host
) ,server负责管理client和运行于目标机器或者emulator的守护进程之间的通信,就像一座桥一样。 - 3、daemon (
adbd
),运行于目标机 (Target
) 或者emulator的守护进程。
本文并不想分析 ADB 的详细工作原理,而是聚焦于在一个普通的 Linux 环境中怎么配置起 ADBD 服务,让普通的 Linux 也能使用 ADB 工具来进行调试。
2. ADBD 源码
Android 的原生 ADBD 是需要和 Java Framework通讯的,并不能直接运行在普通 Linux 环境上。你得找到一份能在普通 Linux 环境上运行的 ADBD 的源码,在 github 上找到以下参考:
1.adbd-linux
2.Android Debug Bridge daemon implementation in RT-Thread
3.android-adbd-for-linux
4.adbd for linux
首先把源码编译生成 adbd
可执行文件。
3. Gadget Device 配置
准备好用户态的 adbd
程序以后,还需要创建好好对应的 gadget device。
3.1 functionfs
在 Usb device 详解 一文中描述了 gadget device
的注册方法,通过 Legacy
或者 Configfs
方式创建一个 composite device
,这个 composite device
可以包含多个 function
。
但是通常情况下 gadget driver
中 function
只能在内核态操作 endpoint
,能不能把 endpoint
的直接呈现到用户态?这样用户直接读写 endpoint
效率更高,而且可以把复杂的逻辑放在用户态从而简化内核态的逻辑。
functionfs
就是为了实现上述的设想而诞生的,它通过注册一个文件系统的方式把 endpoint
呈现到了用户态。
而 adbd
就是使用 functionfs
来读写 usb 数据的,所以我们要配置起 functionfs
。
和之前一样配置起 functionfs
的 gadget device
,有 Legacy
和 Configfs
两种方式。
3.2 legacy 方式配置 functionfs
Legacy
方式内核提供了一个 drivers/usb/gadget/legacy/g_ffs.c
驱动,可以先把它编译成独立的 ko 文件 g_ffs.ko
来使用。
- 1、插入
g_ffs.ko
驱动。注册functionfs
文件系统:
$ insmod g_ffs.ko idVendor=0x18d1 idProduct=0x4e26 functions=mtp,hid,adb
- 2.1、挂载
mtp
的functionfs
文件系统,并启动mtp
服务:
$ mkdir /dev/ffs-mtp && mount -t functionfs mtp /dev/ffs-mtp
$ ( cd /dev/ffs-mtp && mtp-daemon ) &
- 2.2、挂载
hid
的functionfs
文件系统,并启动hid
服务:
$ mkdir /dev/ffs-hid && mount -t functionfs hid /dev/ffs-hid
$ ( cd /dev/ffs-hid && hid-daemon ) &
- 2.3、挂载
adbd
的functionfs
文件系统,并启动adbd
服务:
$ mkdir -p /dev/usb-ffs/adb
$ mount -o uid=2000,gid=2000 -t functionfs adb /dev/usb-ffs/adb
$ adbd&
3.3 configfs 方式配置 functionfs
Configfs
方式内核提供了一个 drivers/usb/gadget/function/f_fs.c
function,将其编译进内核,然后就可以通过 configfs
文件系统来进行配置:
# 挂载 configfs
mount -t configfs none /sys/kernel/config
cd /sys/kernel/config/usb_gadget