Alright. I figured it out. transfer.flags needed to be a byte instead of an int. Silly me. Now I'm getting an error code from ioctl, errno 16, which I think means the device is busy. What a workaholic. I've asked on the libusb mailing list.
好的。我想到了。 transfer.flags需要是一个字节而不是一个int。傻我。现在我从ioctl,errno 16得到一个错误代码,我认为这意味着设备正忙。真是个工作狂。我已经在libusb邮件列表上询问了。
Below is what I have so far. This isn't really that much code. Most of it is ctypes structures for libusb. Scroll down to the bottom to see the actual code where the error occurs.
以下是我到目前为止的情况。这真的不是那么多代码。其中大多数是libusb的ctypes结构。向下滚动到底部以查看发生错误的实际代码。
from ctypes import *
VENDOR_ID = 0x04d8
PRODUCT_ID = 0xc002
_USBLCD_MAX_DATA_LEN = 24
LIBUSB_ENDPOINT_IN = 0x80
LIBUSB_ENDPOINT_OUT = 0x00
class EnumerationType(type(c_uint)):
def __new__(metacls, name, bases, dict):
if not "_members_" in dict:
_members_ = {}
for key,value in dict.items():
if not key.startswith("_"):
_members_[key] = value
dict["_members_"] = _members_
cls = type(c_uint).__new__(metacls, name, bases, dict)
for key,value in cls._members_.items():
globals()[key] = value
return cls
def __contains__(self, value):
return value in self._members_.values()
def __repr__(self):
return "<Enumeration %s>" % self.__name__
class Enumeration(c_uint):
__metaclass__ = EnumerationType
_members_ = {}
def __init__(self, value):
for k,v in self._members_.items():
if v == value:
self.name = k
break
else:
raise ValueError("No enumeration member with value %r" % value)
c_uint.__init__(self, value)
@classmethod
def from_param(cls, param):
if isinstance(param, Enumeration):
if param.__class__ != cls:
raise ValueError("Cannot mix enumeration members")
else:
return param
else:
return cls(param)
def __repr__(self):
return "<member %s=%d of %r>" % (self.name, self.value, self.__class__)
class LIBUSB_TRANSFER_STATUS(Enumeration):
_members_ = {'LIBUSB_TRANSFER_COMPLETED':0,
'LIBUSB_TRANSFER_ERROR':1,
'LIBUSB_TRANSFER_TIMED_OUT':2,
'LIBUSB_TRANSFER_CANCELLED':3,
'LIBUSB_TRANSFER_STALL':4,
'LIBUSB_TRANSFER_NO_DEVICE':5,
'LIBUSB_TRANSFER_OVERFLOW':6}
class LIBUSB_TRANSFER_FLAGS(Enumeration):
_members_ = {'LIBUSB_TRANSFER_SHORT_NOT_OK':1<<0,
'LIBUSB_TRANSFER_FREE_BUFFER':1<<1,
'LIBUSB_TRANSFER_FREE_TRANSFER':1<<2}
class LIBUSB_TRANSFER_TYPE(Enumeration):
_members_ = {'LIBUSB_TRANSFER_TYPE_CONTROL':0,
'LIBUSB_TRANSFER_TYPE_ISOCHRONOUS':1,
'LIBUSB_TRANSFER_TYPE_BULK':2,
'LIBUSB_TRANSFER_TYPE_INTERRUPT':3}
class LIBUSB_CONTEXT(Structure):
pass
class LIBUSB_DEVICE(Structure):
pass
class LIBUSB_DEVICE_HANDLE(Structure):
pass
class LIBUSB_CONTROL_SETUP(Structure):
_fields_ = [("bmRequestType", c_int),
("bRequest", c_int),
("wValue", c_int),
("wIndex", c_int),
("wLength", c_int)]
class LIBUSB_ISO_PACKET_DESCRIPTOR(Structure):
_fields_ = [("length", c_int),
("actual_length", c_int),
("status", LIBUSB_TRANSFER_STATUS)]
class LIBUSB_TRANSFER(Structure):
pass
LIBUSB_TRANSFER_CB_FN = CFUNCTYPE(c_void_p, POINTER(LIBUSB_TRANSFER))
LIBUSB_TRANSFER._fields_ = [("dev_handle", POINTER(LIBUSB_DEVICE_HANDLE)),
("flags", c_ubyte),
("endpoint", c_ubyte),
("type", c_ubyte),
("timeout", c_uint),
("status", LIBUSB_TRANSFER_STATUS),
("length", c_int),
("actual_length", c_int),
("callback", LIBUSB_TRANSFER_CB_FN),
("user_data", c_void_p),
("buffer", POINTER(c_ubyte)),
("num_iso_packets", c_int),
("iso_packet_desc", POINTER(LIBUSB_ISO_PACKET_DESCRIPTOR))]
class TIMEVAL(Structure):
_fields_ = [('tv_sec', c_long), ('tv_usec', c_long)]
lib = cdll.LoadLibrary("libusb-1.0.so")
lib.libusb_open_device_with_vid_pid.restype = POINTER(LIBUSB_DEVICE_HANDLE)
lib.libusb_alloc_transfer.restype = POINTER(LIBUSB_TRANSFER)
def libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, buffer, length, callback, user_data, timeout):
transfer[0].dev_handle = dev_handle
transfer[0].endpoint = chr(endpoint)
transfer[0].type = chr(LIBUSB_TRANSFER_TYPE_INTERRUPT)
transfer[0].timeout = timeout
transfer[0].buffer = buffer
transfer[0].length = length
transfer[0].user_data = user_data
transfer[0].callback = LIBUSB_TRANSFER_CB_FN(callback)
def cb_transfer(transfer):
print "Transfer status %d" % transfer.status
if __name__ == "__main__":
context = POINTER(LIBUSB_CONTEXT)()
lib.libusb_init(None)
transfer = lib.libusb_alloc_transfer(0)
handle = lib.libusb_open_device_with_vid_pid(None, VENDOR_ID, PRODUCT_ID)
size = _USBLCD_MAX_DATA_LEN
buffer = c_char_p(size)
libusb_fill_interrupt_transfer(transfer, handle, LIBUSB_ENDPOINT_IN + 1, buffer, size, cb_transfer, None, 0)
r = lib.libusb_submit_transfer(transfer) # This is returning -2, should be => 0.
if r < 0:
print "libusb_submit_transfer failed", r
while r >= 0:
print "Poll before"
tv = TIMEVAL(1, 0)
r = lib.libusb_handle_events_timeout(None, byref(tv))
print "Poll after", r
3 个解决方案
#1
- Have you checked to make sure the return values of
libusb_alloc_transfer
andlibusb_open_device_with_vid_pid
are valid? - Have you tried annotating the library functions with the appropriate argtypes?
- You may run in to trouble with
transfer[0].callback = LIBUSB_TRANSFER_CB_FN(callback)
—you're not keeping any references to theCFunctionType
object returned fromLIBUSB_TRANSFER_CB_FN()
, and so that object might be getting released and overwritten.
您是否检查过以确保libusb_alloc_transfer和libusb_open_device_with_vid_pid的返回值是否有效?
您是否尝试使用适当的argtypes注释库函数?
您可能会遇到传输[0] .callback = LIBUSB_TRANSFER_CB_FN(回调)的问题 - 您没有保留对从LIBUSB_TRANSFER_CB_FN()返回的CFunctionType对象的任何引用,因此该对象可能会被释放并被覆盖。
The next step, I suppose, would be to install a version of libusb with debugging symbols, boot up GDB, set a breakpoint at libusb_submit_transfer()
, make sure the passed-in libusb_transfer
is sane, and see what's triggering the error to be returned.
我想,下一步是安装带有调试符号的libusb版本,启动GDB,在libusb_submit_transfer()上设置断点,确保传入的libusb_transfer是理智的,并查看触发错误的原因是什么。
#2
Running it as root once fixed the busy flag.
一旦修复了忙碌标志,就以root身份运行它。
#3
where is the initial declaration of transfer? I am not familiar with python, but is this ok to assign values to fields in your struct without defining what data type it should be?
最初的转让声明在哪里?我不熟悉python,但是可以为结构中的字段赋值而不定义它应该是什么数据类型吗?
#1
- Have you checked to make sure the return values of
libusb_alloc_transfer
andlibusb_open_device_with_vid_pid
are valid? - Have you tried annotating the library functions with the appropriate argtypes?
- You may run in to trouble with
transfer[0].callback = LIBUSB_TRANSFER_CB_FN(callback)
—you're not keeping any references to theCFunctionType
object returned fromLIBUSB_TRANSFER_CB_FN()
, and so that object might be getting released and overwritten.
您是否检查过以确保libusb_alloc_transfer和libusb_open_device_with_vid_pid的返回值是否有效?
您是否尝试使用适当的argtypes注释库函数?
您可能会遇到传输[0] .callback = LIBUSB_TRANSFER_CB_FN(回调)的问题 - 您没有保留对从LIBUSB_TRANSFER_CB_FN()返回的CFunctionType对象的任何引用,因此该对象可能会被释放并被覆盖。
The next step, I suppose, would be to install a version of libusb with debugging symbols, boot up GDB, set a breakpoint at libusb_submit_transfer()
, make sure the passed-in libusb_transfer
is sane, and see what's triggering the error to be returned.
我想,下一步是安装带有调试符号的libusb版本,启动GDB,在libusb_submit_transfer()上设置断点,确保传入的libusb_transfer是理智的,并查看触发错误的原因是什么。
#2
Running it as root once fixed the busy flag.
一旦修复了忙碌标志,就以root身份运行它。
#3
where is the initial declaration of transfer? I am not familiar with python, but is this ok to assign values to fields in your struct without defining what data type it should be?
最初的转让声明在哪里?我不熟悉python,但是可以为结构中的字段赋值而不定义它应该是什么数据类型吗?