Python 实现 Windows 环境下 Usb Host & Device Hid 通信

目录

一、环境准备

二、遇到的问题:

        1、usb.core.NoBackendError: No backend available

        2、Error: Operation not supported or unimplemented on this platform 或者 Error during SET/GET_REPORT exchange: [Errno 5] Input/Output Error

注意:

Why Do You Need Zadig?

三、代码实现

1、hid 通讯的测试函数 ctrl_transfer

四、测试


一、环境准备

        1、已安装 Python 环境,python --version 确认;

        2、已安装 Usb Module,pip install pywinusb,pip install pyusb;

二、遇到的问题:

        1、usb.core.NoBackendError: No backend available

        (1)pip install libusb1;

        (2)复制 libusb-1.0.dll(Default Path:Python\Lib\site-packages\usb1 to:

                        64-bit Windows: C:\Windows\System32\

                        32-bit Windows: C:\Windows\SysWOW64\

                或者,将 libusb-1.0.dll(Default Path:Python\Lib\site-packages\usb1)的路径直接添加到系统环境变量中,如下图

        2、Error: Operation not supported or unimplemented on this platform 或者 Error during SET/GET_REPORT exchange: [Errno 5] Input/Output Error


        (1)下载 Zadig 工具,给USB设备安装或更新驱动,下载链接 https://zadig.akeo.ie/

        (2)点击Options,勾选 List All Devices,选择需要操作的设备,驱动选择 libusb-win32(WinUSB 或 libusbK),点击 Install Driver 即可,如下图所示:

注意:

        1、如下图,案例中的 Usb Test Device,共有三个 Interface Num,测试时,需要用到哪个 Interface,就需要用 Zadig 安装下对应 Interface 的 Driver;

        2、修改了 Device 设备的 Pid、Vid 等信息后,亦需要用 Zadig 重新安装下所用到的 Interface 的 Driver;

Why Do You Need Zadig?

        Windows does not always allow user-space applications to directly access USB HID devices via libusb or pyusb. By default:

  • HID devices (such as keyboards, mice, game controllers) use the Windows HID driver (hid.dll).
  • The default HID driver does not expose raw USB communication needed for control transfers (ctrl_transfer in pyusb).
  • Zadig replaces the default HID driver with WinUSB, libusb-win32, or libusbK, which allows user-space applications (like Python scripts) to communicate with the USB device directly.

三、代码实现

import usb.core
import usb.util
import logging
import time

logging.basicConfig(level=logging.INFO)

PID = 0x1234
VID = 0x5678

def send_and_receive():
    # Locate the USB device.
    dev = usb.core.find(idVendor=VID, idProduct=PID)
    if dev is None:
        logging.error("Device not found")
        return
    else:
        print(f"Found device: {dev}")

    try:
    
        HID_REPORT_DESCRIPTOR_SIZE = 64  # Change this to the actual descriptor size
        descriptor = dev.ctrl_transfer(0x81, 0x06, 0x2200, 0x0003, HID_REPORT_DESCRIPTOR_SIZE)
        print("HID Report Descriptor:", list(descriptor))

        # ---------------------------
        # 1. Send SET_REPORT (Output Report)
        # ---------------------------
        # bmRequestType = 0x21 (Host-to-device, Class, Interface)
        # bRequest      = 0x09 (SET_REPORT)
        # wValue        = 0x200 (Output Report type, Report ID 0x00)
        # wIndex        = 0x00 (Interface number; adjust if necessary)
        # Data          = data_to_send (example: 64 bytes)


        # Define the 4 bytes to send
        data_to_send = bytearray([0xFF, 0xF7, 0xFF, 0xF7])
        # data_to_send = bytearray([i % 256 for i in range(1, 65)])  # 64 bytes of data
        logging.info("Sending SET_REPORT command...")
        dev.ctrl_transfer(0x21, 0x09, 0x0200, 0x0002, data_to_send)
        logging.info("SET_REPORT sent, Data: %s", list(data_to_send))
        
        # # Optional delay to allow the device time to process the output report.
        # time.sleep(0.1)
        
        # # ---------------------------
        # # 2. Send GET_REPORT (Input Report)
        # # ---------------------------
        # # bmRequestType = 0xA1 (Device-to-host, Class, Interface)
        # # bRequest      = 0x01 (GET_REPORT)
        # # wValue        = 0x100 (Input Report type, Report ID 0x00)
        # # wIndex        = 0x00 (Interface number; adjust if necessary)
        # # Length        = response_length (expected number of bytes)
        response_length = 4  # Adjust this value based on your device's report size
        logging.info("Sending GET_REPORT command...")
        response = dev.ctrl_transfer(0xA1, 0x01, 0x100, 0x0002, response_length)
        logging.info("Received GET_REPORT response: %s", list(response))

        # # Optional delay to allow the device time to process the output report.
        # time.sleep(1)

        # data_to_send = bytearray([0xFF, 0xF7, 0x01, 0x02])
        # # data_to_send = bytearray([i % 256 for i in range(1, 65)])  # 64 bytes of data
        # logging.info("Sending SET_REPORT command...")
        # dev.ctrl_transfer(0x21, 0x09, 0x0200, 0x02, data_to_send)
        # logging.info("SET_REPORT sent, Data: %s", list(data_to_send))
        
        # # Optional delay to allow the device time to process the output report.
        # time.sleep(0.1)
        
    except Exception as e:
        logging.error("Error during SET/GET_REPORT exchange: %s", e)

if __name__ == '__main__':
    send_and_receive()

1、hid 通讯的测试函数 ctrl_transfer

        The ctrl_transfer function in a USB library (like pyusb) is used to send control transfer requests to a USB device. The function typically follows this format:

dev.ctrl_transfer(bmRequestType, bRequest, wValue, wIndex, data_or_length)

For control transfers, the setup packet is always 8 bytes long and consists of these fields:

OffsetField NameSize (Bytes)Description
0bmRequestType1Specifies the request type (direction, type, and recipient).
1bRequest1The specific request code.
2-3wValue2A value that may be required for the request.
4-5wIndex2Usually specifies the interface or endpoint.
6-7wLength2Number of bytes to transfer in the data stage.

四、测试

        1、打开 PowerShell,进入对应的目录下;

        2、执行程序,python test.py,结果如下;

              

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值