Android USB Gadget 手机模拟真实U盘 操作命令记录
Android USB Gadget 操作命令记录
目标
- 关闭默认
MTP - 保留
ADB - 使用
mass_storage导出一个30G FAT32镜像文件 - backing file 放在
/data/codex_empty_file
连接设备
telnet 10.221.3.83查看当前 USB 属性
getprop | grep usb
getprop persist.sys.usb.config
getprop sys.usb.config
getprop sys.usb.state创建空文件并赋权
touch /data/codex_empty_file
chmod 666 /data/codex_empty_file
ls -l /data/codex_empty_file切换 USB 为 mass_storage + adb
setprop persist.sys.usb.config mass_storage,adb
setprop sys.usb.config mass_storage,adb
sleep 3
getprop persist.sys.usb.config
getprop sys.usb.config
getprop sys.usb.state创建 30G 镜像并格式化为 FAT32
说明:
- 先断开当前 gadget 绑定
- 用
fallocate创建30G镜像文件 - 用
losetup挂到 loop 设备 - 用
mkfs.vfat -F 32格式化成 FAT32
echo '' > /config/usb_gadget/g1/UDC
echo '' > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/file
rm -f /data/codex_empty_file
fallocate -l 30G /data/codex_empty_file
LOOP=$(losetup -f)
echo $LOOP
losetup $LOOP /data/codex_empty_file
mkfs.vfat -F 32 $LOOP
losetup -d $LOOP挂回 USB mass_storage
echo /data/codex_empty_file > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/file
echo 0 > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/cdrom
echo 0 > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/ro
echo 1 > /config/usb_gadget/g1/functions/mass_storage.0/lun.0/removable
echo a600000.dwc3 > /config/usb_gadget/g1/UDC检查最终状态
getprop sys.usb.state
cat /config/usb_gadget/g1/functions/mass_storage.0/lun.0/cdrom
cat /config/usb_gadget/g1/functions/mass_storage.0/lun.0/ro
cat /config/usb_gadget/g1/functions/mass_storage.0/lun.0/removable
cat /config/usb_gadget/g1/functions/mass_storage.0/lun.0/file
ls -lh /data/codex_empty_file期望结果
sys.usb.state = mass_storage,adb
cdrom = 0
ro = 0
removable = 1
file = /data/codex_empty_file常用补充命令
改回仅 ADB
setprop persist.sys.usb.config adb
setprop sys.usb.config adb纯 HID 键盘临时切换并输入字符串
用途:
- 临时把手机切成
纯 HID 键盘 - 向电脑当前焦点窗口输入指定字符串
- 测试完成后再切回
mass_storage + adb
注意:
- 纯 HID 模式下,临时不会保留 U 盘功能
- 切到纯 HID 后,
ADB也可能暂时断开 - 字符会输入到电脑当前有焦点的输入框
1. 在 g2 上准备纯 HID 键盘 gadget
mkdir -p /config/usb_gadget/g2/configs/b.1/strings/0x409
mkdir -p /config/usb_gadget/g2/strings/0x409
mkdir -p /config/usb_gadget/g2/functions/hid.keyboard
echo 0x18d1 > /config/usb_gadget/g2/idVendor
echo 0x4ee7 > /config/usb_gadget/g2/idProduct
echo 0 > /config/usb_gadget/g2/bDeviceClass
echo 0 > /config/usb_gadget/g2/bDeviceSubClass
echo 0 > /config/usb_gadget/g2/bDeviceProtocol
echo CodexHID > /config/usb_gadget/g2/strings/0x409/product
echo OpenAI > /config/usb_gadget/g2/strings/0x409/manufacturer
echo 1234567890 > /config/usb_gadget/g2/strings/0x409/serialnumber
echo 1 > /config/usb_gadget/g2/functions/hid.keyboard/protocol
echo 1 > /config/usb_gadget/g2/functions/hid.keyboard/subclass
echo 8 > /config/usb_gadget/g2/functions/hid.keyboard/report_length
printf '\x05\x01\x09\x06\xA1\x01\x05\x07\x19\xE0\x29\xE7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x01\x95\x05\x75\x01\x05\x08\x19\x01\x29\x05\x91\x02\x95\x01\x75\x03\x91\x01\x95\x06\x75\x08\x15\x00\x25\x65\x05\x07\x19\x00\x29\x65\x81\x00\xC0' > /config/usb_gadget/g2/functions/hid.keyboard/report_desc
rm -f /config/usb_gadget/g2/configs/b.1/f1
ln -s /config/usb_gadget/g2/functions/hid.keyboard /config/usb_gadget/g2/configs/b.1/f12. 切到纯 HID 键盘并输入 qwerrty
setprop sys.usb.config none
sleep 2
echo '' > /config/usb_gadget/g1/UDC 2>/dev/null
echo '' > /config/usb_gadget/g2/UDC 2>/dev/null
sleep 1
echo a600000.dwc3 > /config/usb_gadget/g2/UDC
sleep 4
DEV=/dev/hidg0
[ -e "$DEV" ] || DEV=/dev/hidg1
press() {
code=$1
printf "\x00\x00\x$(printf '%02x' $code)\x00\x00\x00\x00\x00" > "$DEV"
usleep 80000
printf '\x00\x00\x00\x00\x00\x00\x00\x00' > "$DEV"
usleep 80000
}
# q w e r r t y
press 20
press 26
press 8
press 21
press 21
press 23
press 283. 切回稳定模式 U盘 + ADB
setprop sys.usb.config mass_storage,adb
sh /data/adb/service.d/usb_mass_storage_adb.sh
sleep 4
echo '' > /config/usb_gadget/g2/UDC
sleep 1
echo a600000.dwc3 > /config/usb_gadget/g1/UDC4. 恢复后检查
getprop sys.usb.config
getprop sys.usb.state
cat /config/usb_gadget/g1/UDC 2>/dev/null
cat /config/usb_gadget/g2/UDC 2>/dev/null
ls -l /config/usb_gadget/g1/configs/b.1期望结果:
sys.usb.config = mass_storage,adb
sys.usb.state = mass_storage,adb
g1/UDC = a600000.dwc3
g2/UDC = 空开机自动执行的 Magisk 脚本
脚本路径:
/data/adb/service.d/usb_mass_storage_adb.sh作用:
- 开机默认切到
mass_storage,adb - 开机后延迟再次执行
setprop persist.sys.usb.config mass_storage,adb和setprop sys.usb.config mass_storage,adb,防止系统后续又切回mtp,conn_gadget,adb - 如果
/data/codex_empty_file不存在,则自动创建30G FAT32镜像 强制设置:
cdrom=0ro=0removable=1
- 自动启动
busybox telnetd -l bash -p 23 - 当前稳定方案是
U盘 + ADB + telnetd - 不再默认强开
MTP,因为三功能同时存在会导致这台设备 USB 不稳定甚至掉线
核心内容如下:
#!/system/bin/sh
PATH=/sbin:/system/sbin:/system/bin:/system/xbin:/data/data/com.termux/files/usr/bin
IMG=/data/codex_empty_file
SIZE=30G
G=/config/usb_gadget/g1
LUN=$G/functions/mass_storage.0/lun.0
UDC=$(getprop sys.usb.controller)
[ -n "$UDC" ] || UDC=$(getprop ro.boot.usbcontroller)
wait_path() {
p="$1"
i=0
while [ ! -e "$p" ] && [ $i -lt 30 ]; do
sleep 1
i=$((i + 1))
done
[ -e "$p" ]
}
start_telnetd() {
if command -v ss >/dev/null 2>&1; then
ss -ltn 2>/dev/null | grep -q ':23 ' && return 0
fi
if command -v netstat >/dev/null 2>&1; then
netstat -ltn 2>/dev/null | grep -q ':23 ' && return 0
fi
busybox telnetd -l bash -p 23
}
apply_usb_mode() {
setprop persist.sys.usb.config mass_storage,adb
setprop sys.usb.config mass_storage,adb
sleep 2
echo '' > "$G/UDC" 2>/dev/null
echo '' > "$LUN/file" 2>/dev/null
rm -f "$G/configs/b.1/f1" "$G/configs/b.1/f2" "$G/configs/b.1/f3" "$G/configs/b.1/f4" "$G/configs/b.1/f5" "$G/configs/b.1/f6" 2>/dev/null
ln -s ../../../../usb_gadget/g1/functions/mass_storage.0 "$G/configs/b.1/f1" 2>/dev/null
ln -s ../../../../usb_gadget/g1/functions/ffs.adb "$G/configs/b.1/f2" 2>/dev/null
echo 0 > "$LUN/cdrom" 2>/dev/null
echo 0 > "$LUN/ro" 2>/dev/null
echo 1 > "$LUN/removable" 2>/dev/null
echo "$IMG" > "$LUN/file" 2>/dev/null
if [ -n "$UDC" ]; then
echo "$UDC" > "$G/UDC" 2>/dev/null
fi
}
wait_path "$G/UDC" || exit 1
wait_path "$LUN/file" || exit 1
if [ ! -f "$IMG" ]; then
rm -f "$IMG"
fallocate -l "$SIZE" "$IMG" || dd if=/dev/zero of="$IMG" bs=1M count=30720
LOOP=$(losetup -f 2>/dev/null)
if [ -n "$LOOP" ]; then
losetup "$LOOP" "$IMG"
mkfs.vfat -F 32 "$LOOP"
losetup -d "$LOOP"
fi
fi
apply_usb_mode
start_telnetd
(
sleep 15
apply_usb_mode
start_telnetd
sleep 15
apply_usb_mode
start_telnetd
) &查看当前 gadget 配置
ls -l /config/usb_gadget/g1/configs/b.1
find /config/usb_gadget/g1/functions/mass_storage.0 -maxdepth 3 -type f重新绑定 USB 控制器
echo '' > /config/usb_gadget/g1/UDC
echo a600000.dwc3 > /config/usb_gadget/g1/UDC注意事项
- 如果 Windows 识别成
CD 驱动器,检查cdrom是否为0 - 如果电脑侧不刷新,重新插拔 USB 或重新绑定
UDC - 如果 backing file 被占用,修改
ro或重新绑定时可能出现Device or resource busy /sdcard不适合拿来做这种导出镜像,建议放/data