#!/bin/bash apt install -y bridge-utils # The IP address shared by the USB network interface creatoedd by this script. NET_IP="192.168.55.1" # The associated netmask. NET_MASK="255.255.0.0" # 定义USB Gadget的根目录,使用官网脚本的通用名称 "pi4" GADGET_NAME="pi4" GADGET_ROOT="/sys/kernel/config/usb_gadget/${GADGET_NAME}" # --- UDC DEVICE 提示 --- # 通常 Raspberry Pi (或类似SoC) 的 dwc2/ci_hdrc 等驱动会自动作为 UDC 设备出现。 # 官网脚本在绑定时直接使用 'UDC' 文件,不需要显式指定 UDC_DEVICE 变量。 # 系统会自动查找可用的 UDC 设备进行绑定。 # 确保脚本以root权限运行 if [ "$(id -u)" -ne 0 ]; then echo "This script must be run as root. Please run with 'sudo'." exit 1 fi echo "--------------------------------------" echo "Configuring USB Gadget for RNDIS ONLY." echo "--------------------------------------" # 1. 检查RNDIS所需的内核模块并确保 g_ether 未加载 echo "Checking and ensuring 'g_mass_storage' and 'g_ether' are not loaded, then loading 'libcomposite'..." # 卸载 g_mass_storage if lsmod | grep -q g_mass_storage; then echo "Unloading g_mass_storage module..." modprobe -r g_mass_storage || { echo "WARNING: Failed to unload g_mass_storage. This might cause issues."; } sleep 1 fi # 卸载 g_ether if lsmod | grep -q g_ether; then echo "Unloading g_ether module..." modprobe -r g_ether || { echo "WARNING: Failed to unload g_ether. This might cause issues."; } sleep 1 fi # libcomposite 是 gadget 框架的基础 if ! lsmod | grep -q libcomposite; then echo "Loading libcomposite module..." modprobe libcomposite || { echo "ERROR: Failed to load libcomposite. Exiting."; exit 1; } fi # 2. 卸载并清理旧的 gadget 配置 (可选,但推荐在测试时使用以确保干净状态) if [ -d "${GADGET_ROOT}" ]; then echo "Disabling existing gadget '${GADGET_NAME}'..." # 尝试解绑当前的 UDC (如果已经绑定) if [ -f "${GADGET_ROOT}/UDC" ]; then current_udc=$(cat "${GADGET_ROOT}/UDC") if [ -n "$current_udc" ]; then echo "Unbinding ${current_udc} from previous gadget..." echo "" > "${GADGET_ROOT}/UDC" # 解绑 UDC sleep 1 fi fi rm -rf "${GADGET_ROOT}" # 删除所有旧的配置 echo "Old gadget configuration removed." sleep 1 fi # 3. 创建新的 gadget 配置 echo "Creating new gadget configuration at ${GADGET_ROOT}..." mkdir -p "${GADGET_ROOT}" cd "${GADGET_ROOT}" || { echo "ERROR: Failed to cd to ${GADGET_ROOT}. Exiting."; exit 1; } # 4. 设置设备描述符 (参考官网脚本的值) echo "Setting device descriptors..." #echo 0x0955 > idVendor # Linux Foundation (官网脚本值) #echo 0x7020 > idProduct # Multifunction Composite Gadget (官网脚本中 RNDIS 启用时使用的值) echo 0x2CA3 > idVendor # Linux Foundation (官网脚本值) echo 0xF003 > idProduct # Multifunction Composite Gadget (官网脚本中 RNDIS 启用时使用的值) echo 0x0001 > bcdDevice # v1.0.0 echo 0x0200 > bcdUSB # USB2 echo 0xEF > bDeviceClass # Miscellaneous Device Class echo 0x02 > bDeviceSubClass # Common Class echo 0x01 > bDeviceProtocol # Interface Association Descriptor (IAD) # 5. 设置字符串描述符 (参考官网脚本的值) echo "Setting string descriptors (Manufacturer, Product, Serial)..." mkdir -p strings/0x409 # English (0x409) echo "NVIDIA" > strings/0x409/manufacturer echo "Linux for Tegra" > strings/0x409/product cat /proc/device-tree/serial-number > strings/0x409/serialnumber # 6. 创建配置 c.1 echo "Creating configuration 'c.1'..." cfg="configs/c.1" mkdir -p "${cfg}/strings/0x409" echo 0x80 > "${cfg}/bmAttributes" # Self-powered echo 250 > "${cfg}/MaxPower" # Max power consumption (250mA) echo "RNDIS" > "${cfg}/strings/0x409/configuration" # Configuration description # 7. 配置 RNDIS 功能 echo "Enabling RNDIS function (rndis.usb0)..." func_rndis="functions/rndis.usb0" mkdir -p "${func_rndis}" ln -sf "${func_rndis}" "${cfg}" # Link RNDIS function to configuration c.1 # RNDIS OS Descriptors for Windows auto-detection (参考官网脚本的值) echo "Setting RNDIS OS Descriptors..." echo 1 > os_desc/use echo 0xcd > os_desc/b_vendor_code echo MSFT100 > os_desc/qw_sign echo "RNDIS" > "${func_rndis}/os_desc/interface.rndis/compatible_id" echo "5162001" > "${func_rndis}/os_desc/interface.rndis/sub_compatible_id" ln -sf "${cfg}" os_desc # 8. 绑定到 UDC 以激活 Gadget echo "Activating USB Gadget..." # 使用 udevadm settle 确保所有设备节点都已创建 udevadm settle -t 5 || : # 直接将可用的 UDC 设备名称写入 UDC 文件。 # 如果系统有多个 UDC,通常会选择第一个可用的。 # 官网脚本也是直接 'ls /sys/class/udc > UDC' 来完成。 UDC_LIST=$(ls /sys/class/udc) if [ -z "$UDC_LIST" ]; then echo "ERROR: No USB Device Controller (UDC) found in /sys/class/udc/. Cannot activate gadget." exit 1 fi echo "${UDC_LIST%% *}" > UDC # 取第一个 UDC 设备名称 echo "USB Gadget successfully activated on ${UDC_LIST%% *}." # 9. 配置 RNDIS 网络接口 echo "Configuring RNDIS network interface (usb0)..." # 等待 usb0 接口出现 echo "Waiting for 'usb0' interface to appear..." interface_ready=0 for i in $(seq 1 15); do # 等待最多15秒,给系统更多时间 if ip link show usb0 &> /dev/null; then echo "'usb0' interface found." interface_ready=1 break fi sleep 1 done if [ "$interface_ready" -eq 0 ]; then echo "ERROR: 'usb0' interface did not appear after 15 seconds. RNDIS network configuration failed." echo " Check kernel modules ('libcomposite' and 'usb_f_rndis' which is part of g_ether function) and dmesg for errors." exit 1 fi # 清理旧的桥接设备 (如果存在) if ip link show pi4br0 &> /dev/null; then echo "Removing existing bridge 'pi4br0'..." brctl delbr pi4br0 sleep 1 fi /sbin/brctl addbr pi4br0 # 创建一个名为 pi4br0 的网络桥接 /sbin/ifconfig pi4br0 "${NET_IP}" netmask "${NET_MASK}" up # 配置桥接接口的IP地址 /sbin/brctl addif pi4br0 usb0 # 将 RNDIS 接口 usb0 添加到桥接 /sbin/ifconfig usb0 up # 确保 usb0 接口被激活 echo "RNDIS network configured to ${NET_IP} on 'pi4br0' (bridging 'usb0')." echo "--------------------------------------" echo "USB Gadget RNDIS setup complete." echo "Connect your device to a PC." echo "--------------------------------------" exit 0