【问题标题】:Trouble using PyUSB to read/write from usb device (timeouts)使用 PyUSB 从 USB 设备读取/写入时出现问题(超时)
【发布时间】:2016-07-29 12:31:03
【问题描述】:

我正在尝试与连接到我的 Ubuntu 16 系统(Python 版本 2.7.12)的设备进行交互。当我尝试写入设备时,我收到了写入超时(与从设备读取类似)。

根据我的小文档,HID接口是在接口3中实现的,除了标准端点(EP)0设备支持EP4 IN(设备到主机)中断传输类型,EP5 OUT(主机到设备)中断传输类型。它还指出 USB Bulk 基于请求-响应消息对,消息格式为 64 字节,第一个字节是“操作码”。对于“获取版本”命令,操作码是 0x02,其余的被忽略。

我是 Python 和 USB 的新手,所以可能有这个错误,但我正在尝试写入“OUT”接口,然后从“IN”接口读取。我注意到,当我将设备插入 Ubuntu 系统时,我得到了一个新设备 /dev/usb/hiddev0 但似乎无法写入该设备,因此尝试连接到接口 3 并获取输入/输出接口。 我还添加了我认为是对 PYUSB_DEBUG 的调用,但我没有看到比没有它更多的输出。

通过以下代码,我确实看到了设备,并且我得到了一个 IN/OUT 接口,但写入/读取总是超时。我不知道我错过了什么。非常感谢您的帮助

import usb.core
import usb.util
from usb.core import *
import sys
import os
import binascii
import time
import serial    
import itertools


idV = 0x2abf
idP = 0x0505

# doesnt seem to write anything to log?!
os.environ['PYUSB_DEBUG'] = 'debug'
#os.environ['PYUSB_LOG_FILENAME'] = "pyusb.log" #never written


print "finding idVendor = {}, idProduct= {}".format(idV, idP)
device = usb.core.find(idVendor=idV, idProduct=idP)

if device is None:
    print ("Device not found")
    exit()


# free up the device from the kernal
for cfg in device:
    for intf in cfg:
        if device.is_kernel_driver_active(intf.bInterfaceNumber):
            try:
                device.detach_kernel_driver(intf.bInterfaceNumber)
            except usb.core.USBError as e:
                sys.exit("Could not detach kernel driver from interface({0}): {1}".format(intf.bInterfaceNumber, str(e)))

# try default conf
print "setting configuration"
device.set_configuration()
print "config set"

print "trying to claim device"
try:
    usb.util.claim_interface(device, 0)
    print "claimed device"
except usb.core.USBError as e:
    print "Error occurred claiming " + str(e)
    sys.exit("Error occurred on claiming")
print "device claimed"

# get enpoint instance
cfg = device.get_active_configuration()
print "***********"
for intf in cfg:
    print "intf= " + str(intf)
print "***********"

# from document:
# The HID interface is implemented on Interface 3, in addition to standard endpoint (er)0, the device supports
# EP4 IN (device to host) interrupt transfer type, and EP5 OUT (host to device) interrupt transfer type
#  Note: EP$ seems to come back as 0x84 while EP5 comes back as 0x05
intf = cfg[(3, 0)]

# get the BULK OUT descriptor
epo = usb.util.find_descriptor(
    intf,
    # match our first out endpoint
    custom_match= \
        lambda e: \
            usb.util.endpoint_direction(e.bEndpointAddress) == \
            usb.util.ENDPOINT_OUT)

assert epo is not None

# get the BULK IN descriptor
epi = usb.util.find_descriptor(
    intf,
    # match our first out endpoint
    custom_match= \
        lambda e: \
            usb.util.endpoint_direction(e.bEndpointAddress) == \
            usb.util.ENDPOINT_IN)

assert epi is not None

print "write the data"
# commands are 64 bytes long, first byte is command code, 02 is 'get version', it doesn't need any of the other bytes set
try:
    # don't think I can use [0x00]*63 because it will be all pointers to same object?, call them out to be safe
    test = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
    mybuff = b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
    #device.write(epo,mybuff,1)         #timeout on write
    #epo.write(mybuff)                  #timeout on write
    epo.write(mybuff.encode('utf-8'))   #timeout on write
except usb.core.USBError as e:
    print "Write USBError: " + str(e)
    sys.exit()

print "done writing"
print "try read?"
try:
    #info = device.read(0x84, 8)
    info = epo.read(epi.bEndpointAddress,epi.wMaxPacketSize)
except usb.core.USBError as e:
    print "Read USBError: " + str(e)
    sys.exit()

print "read: " + str(info)

输出:

finding idVendor = 10943, idProduct= 1285
setting configuration
config set
trying to claim device
claimed device
device claimed
***********
< skipping audio interfaces>
intf=     INTERFACE 3: Human Interface Device ====================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x3
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x2
     bInterfaceClass    :    0x3 Human Interface Device
     bInterfaceSubClass :    0x0
     bInterfaceProtocol :    0x0
     iInterface         :    0x8 PlaylistControl
      ENDPOINT 0x84: Interrupt IN ==========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x84 IN
       bmAttributes     :    0x3 Interrupt
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0xa
      ENDPOINT 0x5: Interrupt OUT ==========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x5 OUT
       bmAttributes     :    0x3 Interrupt
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0xa
***********
write the data
Write USBError: [Errno 110] Operation timed out

【问题讨论】:

  • info = epo.read(epi.bEndpointAddress,epi.wMaxPacketSize) 你确定这不是epi.read...

标签: python pyusb


【解决方案1】:

我假设您在测试代码时重复使用了设备,并且在多次执行代码时会出现问题。你应该使用

usb.util.dispose_resources(device)

在代码的末尾。尝试使用

device.reset()

之后

device = usb.core.find(...)

如果您怀疑之前的代码运行不干净,则在对设备执行任何其他操作之前。

【讨论】:

  • 感谢您的帮助,很抱歉没有早点看这里,我已经放弃了答复,不知道为什么我错过了电子邮件。
  • 我尝试在程序末尾的 device = usb.core.find(...) 和 usb.util.dispose_resources(device) 之后添加 device.reset() 以释放内容,但是仍然没有得到任何地方。虽然我确实认为额外的行可能很有意义。所以我很感激!
  • 很抱歉,reset() 没有解决您的问题。我发现它可以解决我的问题,但另一方面,在数千 reset()s 之后,我的 RaspberryPi 引发了内核恐慌,所以并不像我想象的那么完美。
  • 这是非常有用的信息,只是一般。当您开始使用该库时,PyUSB 将其用户引用到其文档字符串的方式并不是很有帮助。
猜你喜欢
  • 2020-03-25
  • 2022-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-27
  • 2023-01-04
  • 2021-09-07
  • 1970-01-01
相关资源
最近更新 更多