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分析