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
mkdir g_adb
cd g_adb
echo "0x18d1" > idVendor
echo "0x4e26" > idProduct
mkdir configs/c.1
# 創建 'ffs' function,這樣就注冊了`functionfs` 文件系統
mkdir functions/ffs.adb
mkdir strings/0x409
mkdir configs/c.1/strings/0x409
echo "0123456789ABCDEF" > strings/0x409/serialnumber
echo "Google Inc." > strings/0x409/manufacturer
echo "FunctionFS gadget (adb)" > strings/0x409/product
echo "Conf 1" > configs/c.1/strings/0x409/configuration
echo 120 > configs/c.1/MaxPower
ln -s functions/ffs.adb configs/c.1
# 用戶態掛載 `adbd` 的 `functionfs` 文件系統
mkdir -p /dev/usb-ffs/adb
mount -o uid=2000,gid=2000 -t functionfs adb /dev/usb-ffs/adb
echo s3c-hsotg > UDC
實際上 adbd 還需要 devpts 和 network 的配置,完整配置腳本如下:
mkdir /dev/pts
mount -t devpts none /dev/pts
mount -t configfs none /sys/kernel/config
cd /sys/kernel/config/usb_gadget
mkdir g_adb
cd g_adb
echo "0x18d1" > idVendor
echo "0x4e26" > idProduct
mkdir configs/c.1
mkdir functions/ffs.adb
mkdir strings/0x409
mkdir configs/c.1/strings/0x409
echo "0123456789ABCDEF" > strings/0x409/serialnumber
echo "Google Inc." > strings/0x409/manufacturer
echo "FunctionFS gadget (adb)" > strings/0x409/product
echo "Conf 1" > configs/c.1/strings/0x409/configuration
echo 120 > configs/c.1/MaxPower
ln -s functions/ffs.adb configs/c.1
mkdir -p /dev/usb-ffs/adb
mount -o uid=2000,gid=2000 -t functionfs adb /dev/usb-ffs/adb
ifconfig lo up
ifconfig
cd /root
adbd&
sleep 1
echo `ls /sys/class/udc/` > /sys/kernel/config/usb_gadget/g_adb/UDC
3.4 adb 使用配置
如果 Host 是 windows 環境,修改 adb_usb.ini 文件,增加 0x4e26 字段,就能正常使用 adb 連接上述 Target 啟動的 adbd 服務了。
參考資料
1.USB/Linux USB Layers/Configfs Composite Gadget/Usage eq. to g ffs.ko
2.ptmx/pts
3.functionfs.rst
4.Android 4.4 Kitkat 使能 USB adb 功能
5.Android開發工具ADB教程之一:ADB概論
6.Android開發工具ADB教程之二:HOST端
7.Android開發工具ADB教程之三:Dalvik虛擬機之jdwp線程
8.ADB 操作命令詳解及用法大全
9.adb和adbd分析
