更新
我成功发送了数据。对于遇到同样问题的人,我使用了以下代码:
data=[0x00, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0x00, 0x00]
result=dev.ctrl_transfer(0x21, 0x9, wValue=0x200, wIndex=0x00, data_or_wLength=data)
(这是基于此处发布的答案:链接)
但是我不太明白,为什么我必须使用
bmRequestType=0x21
bRequest=0x9
wValue=0x200
解释是什么?
初始请求:
我正在拼命尝试使用 PyUSB 向 HID 设备发送简单的报告。
使用“SimpleHIDwrite”我确认该设备按预期工作。我想发送此数据:
报告ID:00
数据:[00,04,04,FF,FF,FF,00,00]
我对 Python 和 USB 还很陌生,我不知道如何使用 dev.ctrl_transfer 或 dev.write 来做到这一点。
另外,有一些关于向 HID 设备发送数据的帖子,但我不知道如何解决我的问题。我该如何解决它?
以下是更多详细信息:
# Based on https://github.com/walac/pyusb/blob/master/docs/tutorial.rst
import usb.core
import usb.util
# Find our device
# dev = usb.core.find(idVendor=0xfffe, idProduct=0x0001)
dev = usb.core.find(idVendor=0x1781, idProduct=0x8c0)
# Was it found?
if dev is None:
raise ValueError('Device not found')
dev.set_configuration()
cfg = dev[0]
intf = cfg[(0,0)]
ep = intf[0]
# dev.write(ep.bEndpointAddress, [0x00, 0x00,0x04,0x04,0xFF,0xFF,0xFF,0x00, 0x00], 1000)
# dev.ctrl_transfer(bmRequestType, bRequest, wValue=0, wIndex=0, data_or_wLength=None, timeout=None)
print("print ep")
print(ep)
print("print cfg")
print(cfg)
print("print intf")
print(intf)
上面脚本的结果是这样的:
print ep
ENDPOINT 0x81: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x8 (8 bytes)
bInterval : 0xa
print cfg
CONFIGURATION 1: 100 mA ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x22 (34 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0x80 Bus Powered
bMaxPower : 0x32 (100 mA)
INTERFACE 0: Human Interface Device ====================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x1
bInterfaceClass : 0x3 Human Interface Device
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x0
ENDPOINT 0x81: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x8 (8 bytes)
bInterval : 0xa
print intf
INTERFACE 0: Human Interface Device ====================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x1
bInterfaceClass : 0x3 Human Interface Device
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x0
ENDPOINT 0x81: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x8 (8 bytes)
bInterval : 0xa
Process finished with exit code 0
这就是您使用 just PyUSB 执行 HID 所需的全部内容:
def hid_set_report(dev, report):
""" Implements HID SetReport via USB control transfer """
dev.ctrl_transfer(
0x21, # REQUEST_TYPE_CLASS | RECIPIENT_INTERFACE | ENDPOINT_OUT
9, # SET_REPORT
0x200, # "Vendor" Descriptor Type + 0 Descriptor Index
0, # USB interface № 0
report # the HID payload as a byte array -- e.g. from struct.pack()
)
def hid_get_report(dev):
""" Implements HID GetReport via USB control transfer """
return dev.ctrl_transfer(
0xA1, # REQUEST_TYPE_CLASS | RECIPIENT_INTERFACE | ENDPOINT_IN
1, # GET_REPORT
0x200, # "Vendor" Descriptor Type + 0 Descriptor Index
0, # USB interface № 0
64 # max reply size
)
没有必要加入库包装器的潮流。你是工程师还是什么?只需阅读文档。该协议不会很快改变。
最后,是的。我见过的所有四个 libusbhid 都是用可怕的 C 语言编写的,并且依赖于更多的库。基本上只有 10 行代码。自己做决定。
来自评论...您问的“HID 报告”是什么?
“HID报告”是HID协议中的有效负载数据。当您移动鼠标或单击其按钮时,坐标增量 + 按下的按钮位图会通过鼠标内的微控制器打包到 HID 报告 中,然后该报告通过 HID 发送到主机。 (发送通过 USB – 或蓝牙 – 或 BLE – 或 Zigbee – ……无论在任何特定用例中 HID 位于其之上的传输层是什么。)
HID 支持许多不同的设备:
游戏手柄,
条形码扫描仪,
键盘,
不仅仅是常见的 104 键键盘 — 各种键盘:独立数字键盘、笑话键盘、用于“奇怪”应用程序的键盘:
指纹扫描仪,
街机舞蹈垫:
USB 显微镜中的按扣按钮:
触摸屏的触摸部分,
赛车模拟器方向盘和踏板,
Wii 远程运动传感器控制器,
等等,等等,等等。
如果你仔细想想,你会发现为了支持如此巨大的各种输入设备——最好有一个抽象的事物,它携带设备必须发送的任何数据,但封装了特定于设备的细节。然后,大多数 HID 都会抽象且统一地对待那个“东西”。那东西就是 HID 报告。
我上面的 2 个函数,hid_get_report()
hid_set_report()
执行相同的操作:它们抽象地处理 HID 报告。我不知道你有什么应用程序;我无法预测您的 HID 设备可以做什么;因此,我必须抽象地对待 hid-report,简单地将其视为不透明的字节数组。
该字节数组的具体格式由 HID 描述符描述。它因每个特定设备而异。例如,3 按钮 1 滚轮鼠标的 HID 描述符会显示“我有 2 个相对轴、3 个按钮和 1 个滚轮”,并进一步详细说明其 HID 报告的长度以及字节数它以什么编码风格携带哪些输入特征。
...如果仍然不清楚如何使用这两个功能 - 也许可以参考这个 HID 教程
,它深入地逐位解释了 HID 报告。不要使用 PyUSB(除非您也需要其他协议)。管理 HID 并不困难,但有一个更简单的解决方案。HIDAPI 是一个管理协议的 C 语言库
,并且还有Python 包装器 可用。 此外,它还隐藏了从操作系统夺回控制权的必要性,操作系统可识别连接时的 HID 协议并安装自己的驱动程序。