使用 PyUSB 发送 HID 报告

问题描述 投票:0回答:2

更新


我成功发送了数据。对于遇到同样问题的人,我使用了以下代码:

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]

Sending data using SimpleHIDwrite

我对 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
python windows usb hid pyusb
2个回答
8
投票

这就是您使用 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 行代码。自己做决定。


隐藏101

来自评论...您问的“HID 报告”是什么?

“HID报告”是HID协议中的有效负载数据。当您移动鼠标或单击其按钮时,坐标增量 + 按下的按钮位图会通过鼠标内的微控制器打包到 HID 报告 中,然后该报告通过 HID 发送到主机。 (发送通过 USB – 或蓝牙 – 或 BLE – 或 Zigbee – ……无论在任何特定用例中 HID 位于其之上的传输层是什么。)

HID 支持许多不同的设备:

  • 游戏手柄,

  • 条形码扫描仪,

  • 键盘,

    • 不仅仅是常见的 104 键键盘 — 各种键盘:独立数字键盘、笑话键盘、用于“奇怪”应用程序的键盘:

      tiny 3-key joke keyboard

  • 指纹扫描仪,

  • 街机舞蹈垫:

    dance-dance-revolution floor pads in use

  • USB 显微镜中的按扣按钮:

    USB microscope with SNAP button annotated

  • 触摸屏的触摸部分,

  • 赛车模拟器方向盘和踏板,

  • 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 并不困难,但有一个更简单的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.