用Python实现与USB设备的通信

2022-02-28 00:00:00 python usb libusb

问题描述

我要与USB设备通信并向其发送数据。我能够找到该设备,但是在将该设备与内核驱动程序连接时,它提供了USB Error: Resource Busy。以下是我的代码:

import usb

dev = usb.core.find(idVendor=0x0403, idProduct=0x6001)
dev.set_configuration()

cfg = dev.get_active_configuration()

dev.attach_kernel_driver(interface)

interface_number = cfg[(0, 0)].bInterfaceNumber
alternate_settting = usb.control.get_interface(interface_number)
intf = usb.util.find_descriptor(
    cfg, bInterfaceNumber=interface_number,
    bAlternateSetting=alternate_setting)

ep = usb.util.find_descriptor(
    intf, custom_match=lambda e:
    usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)

dev.detach_kernel_driver(interface)

ep.write("" + linea1[:19] + "
" + " " * (20 - len(linea2)) + linea2)

解决方案

假定您使用的是linux,并且libusb-1.0PyUSB的后端库。

根据libusb documentation:

// Detach a kernel driver from an interface.
// If successful, you will then be able to claim the interface and perform I/O.
int libusb_detach_kernel_driver (libusb_device_handle *dev, 
                                 int interface_number)  

// Re-attach an interface's kernel driver, which was previously 
// detached using libusb_detach_kernel_driver().
int libusb_attach_kernel_driver(libusb_device_handle *dev,
                                int interface_number)

因此,基本上,您需要首先调用detach_kernel_driver从设备接口分离已经附加的内核驱动程序(如果有),这样您就可以在代码中与其通信(它可以是您的代码,也可以是与设备接口对话的某个内核驱动程序)。完成后,您可能需要调用attach_kernel_driver重新附加内核驱动程序。

我相信,如果您可以确保没有为给定设备加载内核驱动程序(或者在运行代码之前手动卸载它),那么就不需要调用这些C函数/Python方法中的任何一个。

编辑:

我刚刚让这段代码(基于您的示例)正常工作。注意:为简单起见,我已将detach_kernel_driverattach_kernel_driver的接口编号硬编码为0-我想您应该使其更智能。

import usb

dev = usb.core.find(idVendor=0x0403, idProduct=0x6001)

reattach = False
if dev.is_kernel_driver_active(0):
    reattach = True
    dev.detach_kernel_driver(0)

dev.set_configuration() 
cfg = dev.get_active_configuration() 

interface_number = cfg[(0,0)].bInterfaceNumber 
alternate_settting = usb.control.get_interface(dev, interface_number) 
intf = usb.util.find_descriptor(cfg, bInterfaceNumber = interface_number, 
                            bAlternateSetting = alternate_settting) 

ep = usb.util.find_descriptor(intf,custom_match = 
      lambda e: 
    usb.util.endpoint_direction(e.bEndpointAddress) == 
    usb.util.ENDPOINT_OUT) 
ep.write("test
")

# This is needed to release interface, otherwise attach_kernel_driver fails 
# due to "Resource busy"
usb.util.dispose_resources(dev)

# It may raise USBError if there's e.g. no kernel driver loaded at all
if reattach:
    dev.attach_kernel_driver(0) 

相关文章