树莓派4 Bookworm系统模拟键鼠遇BrokenPipeError问题求助
树莓派4 Bookworm系统模拟USB键鼠报错排查与解决方案
在运行Bookworm系统、Kernel 6.1.21版本的树莓派4上尝试模拟USB键盘和鼠标,已完成启动脚本与内核模块配置,但执行Python代码时出现错误:BrokenPipeError: [Errno 108] Cannot send after transport endpoint shutdown。现有可行案例多基于旧内核版本或针对Pi Zero,以下是适配Bookworm的排查方向与解决方案。
报错的Python代码
NULL_CHAR = chr(0) # 键盘 def write_report(report): with open('/dev/hidg0', 'rb+') as fd: fd.write(report.encode()) write_report(NULL_CHAR*2+chr(6)+chr(7)+chr(8)+chr(9)+chr(10)+chr(11)) write_report(NULL_CHAR*8) # 鼠标 def ms_write(report): with open("/dev/hidg1", "wb+") as fd: fd.write(report.encode()) ms_write(NULL_CHAR+chr(100)+NULL_CHAR) ms_write(NULL_CHAR*3)
初始化bash脚本
#!/bin/bash # 初始化设备,添加必要内核模块 set -e reboot_required=0 # 确保使用支持OTG的dwc2 USB驱动 if ! grep "dtoverlay=dwc2" /boot/config.txt; then echo "dtoverlay=dwc2" >> /boot/config.txt reboot_required=1 fi # 启用对应内核模块 if ! grep "dwc2" /etc/modules; then echo "dwc2" >> /etc/modules reboot_required=1 fi if [ $reboot_required -eq 1 ]; then echo "请重启设备使初始化生效" else echo "所有设置已完成" fi
USB Gadget设置脚本
#!/bin/bash set -e modprobe libcomposite cd /sys/kernel/config/usb_gadget/ mkdir -p pihid cd pihid echo 0x1d6b > idVendor # Linux Foundation echo 0x0104 > idProduct # 多功能复合设备 echo 0x0100 > bcdDevice # v1.0.0 echo 0x0200 > bcdUSB # USB2 mkdir -p strings/0x409 echo "fedcba9876543210" > strings/0x409/serialnumber echo "test" > strings/0x409/manufacturer echo "PiHID" > strings/0x409/product mkdir -p configs/c.1/strings/0x409 echo "Config 1: ECM network" > configs/c.1/strings/0x409/configuration echo 250 > configs/c.1/MaxPower # 添加键盘功能 mkdir -p functions/hid.usb0 echo 1 > functions/hid.usb0/protocol echo 1 > functions/hid.usb0/subclass echo 8 > functions/hid.usb0/report_length echo -ne \\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\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc ln -s functions/hid.usb0 configs/c.1/ # 添加鼠标功能 mkdir -p functions/hid.usb1 echo 2 > functions/hid.usb1/protocol echo 2 > functions/hid.usb1/subclass echo 8 > functions/hid.usb1/report_length echo -ne \\x05\\x01\\x09\\x02\\xA1\\x01\\x09\\x01\\xA1\\x00\\x05\\x09\\x19\\x01\\x29\\x03\\x15\\x00\\x25\\x01\\x95\\x03\\x75\\x01\\x81\\x02\\x95\\x01\\x75\\x05\\x81\\x03\\x05\\x01\\x09\\x30\\x09\\x31\\x15\\x81\\x25\\x7F\\x75\\x08\\x95\\x02\\x81\\x06\\xC0\\xC0 > functions/hid.usb1/report_desc ln -s functions/hid.usb1 configs/c.1/ ls /sys/class/udc > UDC # chmod 777 /dev/hidg0 # chmod 777 /dev/hidg1
/etc/rc.local配置
# 鼠标模拟器配置 sudo /home/martinval/projects/hid/mouse_keyb.sh sudo chmod -R 777 /dev/hidg0 sudo chmod -R 777 /dev/hidg1
排查方向与解决方案
1. 调整USB Gadget启动时机(关键)
Bookworm采用systemd管理启动,rc.local执行过早,可能USB Gadget节点还未创建或初始化完成。建议将设置脚本改为systemd服务:
- 创建服务文件
/etc/systemd/system/hid-gadget.service:[Unit] Description=USB HID Gadget 初始化服务 After=multi-user.target [Service] Type=oneshot ExecStart=/home/martinval/projects/hid/mouse_keyb.sh ExecStartPost=/bin/chmod 777 /dev/hidg0 /dev/hidg1 RemainAfterExit=yes [Install] WantedBy=multi-user.target - 启用并启动服务:
sudo systemctl daemon-reload sudo systemctl enable --now hid-gadget.service - 移除rc.local中的对应配置,避免重复执行。
2. 修复HID报告长度不匹配
设置脚本中鼠标的report_length设为8,但Python代码仅发送3字节报告,长度不匹配会导致传输端点异常:
- 方案一:修改设置脚本中鼠标的
report_length为3:echo 3 > functions/hid.usb1/report_length - 方案二:调整Python代码发送8字节鼠标报告:
ms_write(NULL_CHAR*8) ms_write(NULL_CHAR*8)
3. 用udev规则自动设置权限
手动chmod时机不可靠,创建udev规则自动赋予权限:
- 创建文件
/etc/udev/rules.d/99-hidg.rules:SUBSYSTEM=="usb", KERNEL=="hidg[0-1]", MODE="0777" - 重启udev服务:
sudo udevadm control --reload-rules sudo udevadm trigger
4. 规范内核模块加载方式
Bookworm推荐用modules-load.d配置模块加载,替代/etc/modules:
- 创建文件
/etc/modules-load.d/hid-gadget.conf:dwc2 libcomposite - 移除/etc/modules中的dwc2条目。
5. 确认Pi4的OTG连接
树莓派4仅USB-C口支持OTG模式,确保将USB线连接到USB-C口,而非USB-A口,否则无法作为USB设备被识别。
内容的提问来源于stack exchange,提问作者martinval
相关产品推荐
相关产品推荐

