Mac通过USB-C模拟HID控制碎屏Android设备超时问题求助
解决Mac通过USB-C控制Android光标(无外部硬件)的问题
优先推荐:用ADB快速实现(无需PyUSB)
如果你的Android设备已经开启USB调试,直接用ADB命令就能控制光标,这是官方支持的方案,比PyUSB简单得多:
- 移动光标:
adb shell input mouse move <dx> <dy>(dx/dy为相对位移值) - 左键点击:
adb shell input mouse click 1(2为右键,3为中键) - 绝对坐标滑动:
adb shell input swipe <x1> <y1> <x2> <y2>
只要Mac上安装了ADB,USB连接设备并授权调试,就能直接运行这些命令,完全不需要编写复杂代码。
如果你坚持用PyUSB实现,修正以下核心问题
1. 设备端必须开启的前置选项
- 开启开发者选项(连续点击设备系统版本号)
- 开启USB调试
- 开启USB模拟输入设备(部分设备叫“外设模式”,在开发者选项的「USB配置」中选择「鼠标/键盘」或「输入设备」)
- 连接Mac时,设备端选择「文件传输」或「MTP」模式(避免仅充电模式)
2. 代码中的关键错误修正
错误1:硬编码设备ID
你代码中使用的0x18d1/0x4ee1是Google测试设备ID,需替换为你自己设备的ID。在Mac终端运行以下命令获取设备ID:
system_profiler SPUSBDataType
找到你的Android设备条目,复制Vendor ID和Product ID(例如三星设备通常为0x04e8)。
错误2:选择正确的HID接口
Android的HID输入接口并非默认的接口0,需要遍历配置找到HID类接口(bInterfaceClass=3):
def find_hid_interface(cfg): for intf in cfg: if intf.bInterfaceClass == 3: # HID类标识 return intf return None
错误3:HID报告格式错误
标准鼠标HID报告为4字节固定格式:
- 字节0:按钮状态(bit0=左键,bit1=右键,bit2=中键)
- 字节1:相对位移dx(范围-128到127)
- 字节2:相对位移dy(范围-128到127)
- 字节3:滚轮位移
你的send_mouse_command函数使用了5字节数据,不符合标准格式,需改为4字节。
错误4:控制传输参数错误
HID协议的SET_REPORT请求应使用0x09作为bRequest,而非0x01,同时需指定报告类型为输出报告:
def send_mouse_control_transfer(dev, intf_num, dx, dy, buttons=0): bmRequestType = usb.util.build_request_type( usb.util.CTRL_OUT, usb.util.CTRL_TYPE_CLASS, usb.util.CTRL_RECIPIENT_INTERFACE ) try: dev.ctrl_transfer( bmRequestType, 0x09, # SET_REPORT请求码 wValue=0x0200, # 高字节为报告类型(0x02=输出报告),低字节为报告ID wIndex=intf_num, data=[buttons, dx & 0xFF, dy & 0xFF, 0] # 符合标准的鼠标报告数据 ) except usb.core.USBError as e: print(f"控制传输失败: {e}")
错误5:Mac USB权限问题
PyUSB在Mac上需要系统权限,解决方法:
- 用
sudo运行脚本:sudo python3 your_script.py - 确保已安装libusb依赖:
brew install libusb
修正后的完整代码
import usb.core import usb.util def find_android_device(vendor_id, product_id): dev = usb.core.find(idVendor=vendor_id, idProduct=product_id) return dev def find_hid_interface(cfg): for intf in cfg: if intf.bInterfaceClass == 3: return intf return None def send_mouse_hid_report(ep, dx, dy, buttons=0): # 标准HID鼠标报告格式:[按钮状态, dx, dy, 滚轮] data = [buttons, dx & 0xFF, dy & 0xFF, 0] try: ep.write(data) except usb.core.USBError as e: print(f"端点写入失败: {e}") def send_mouse_control_transfer(dev, intf_num, dx, dy, buttons=0): bmRequestType = usb.util.build_request_type( usb.util.CTRL_OUT, usb.util.CTRL_TYPE_CLASS, usb.util.CTRL_RECIPIENT_INTERFACE ) try: dev.ctrl_transfer( bmRequestType, 0x09, wValue=0x0200, wIndex=intf_num, data=[buttons, dx & 0xFF, dy & 0xFF, 0] ) except usb.core.USBError as e: print(f"控制传输失败: {e}") # 替换为你自己设备的Vendor ID和Product ID VENDOR_ID = 0x18d1 # 示例值,需替换 PRODUCT_ID = 0x4ee1 # 示例值,需替换 android_device = find_android_device(VENDOR_ID, PRODUCT_ID) if android_device is not None: cfg = android_device.get_active_configuration() intf = find_hid_interface(cfg) if intf is None: print("未找到HID接口,请检查设备USB配置") exit() intf_num = intf.bInterfaceNumber # 分离内核驱动(如果设备已挂载) if android_device.is_kernel_driver_active(intf_num): try: android_device.detach_kernel_driver(intf_num) except usb.core.USBError as e: print(f"分离驱动失败: {e}") # 查找HID输出端点 ep = usb.util.find_descriptor( intf, custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT ) if ep is None: print("未找到输出端点") exit() # 测试光标移动 send_mouse_hid_report(ep, 5, 5) # 向右下移动5单位 send_mouse_control_transfer(android_device, intf_num, 10, 10) # 释放资源(可选) usb.util.dispose_resources(android_device) else: print("未找到Android设备,请检查USB连接和设备ID")
常见问题排查
- 超时错误:检查设备是否开启USB模拟输入、接口是否正确、运行脚本是否有足够权限
- 设备找不到:确认USB连接正常、设备ID正确、Mac已识别设备
- 无响应:尝试重启设备开发者选项、重新插拔USB、更换USB-C端口
内容的提问来源于stack exchange,提问作者the.Legend
相关产品推荐
相关产品推荐

