Paul Cornelius
2015-08-08 04:14:35 UTC
I found a bug in usb.util.py in the function get_string. This function
was failing with an "Overflow" error on my Windows 8.1 machine, using
Python 3.3 and libusb-1.0.
If this function is called with the default value for langid (None), it
first makes a call to get_descriptor to obtain a list of languages
supported by the device. This second parameter of this function call is
the size of the reply buffer, which was equal to 1024. But a comment in
the libusb-1.0 source (descriptor.c, function
libusb_get_string_descriptor_ascii) reads: /* Some devices choke on size
call to reduce the buffer size parameter to 255 the error disappeared.
I also thought it would be good to limit the size of any buffer passed
to get_string. My modified function now reads as follows:
defget_string(dev,length,index,langid=None):
r"""Retrieve a string descriptor from the device.
dev is the Device object to which the request will be
sent to.
length is the length of string in number of characters.
index is the string descriptor index and langid is the Language
ID of the descriptor. If langid is omitted, the string descriptor
of the first Language ID will be returned.
The return value is the unicode string present in the descriptor.
"""
fromusb.controlimportget_descriptor
iflangidisNone:
# Asking for the zero'th index is special - it returns a string
# descriptor that contains all the language IDs supported by the device.
# Typically there aren't many - often only one. The language IDs are 16
# bit numbers, and they start at the third byte in the descriptor. See
# USB 2.0 specification section 9.6.7 for more information.
#
# Note from libusb 1.0 sources (descriptor.c)
buf=get_descriptor(
dev,
255,
DESC_TYPE_STRING,
0
)
assertlen(buf)>=4
langid=buf[2]|(buf[3]<<8)
lenstr=length*2+2
iflenstr>255:
raiseValueError("String buffer length too long")
buf=get_descriptor(
dev,
length*2+2,# string is utf16 + 2 bytes of the descriptor
DESC_TYPE_STRING,
index,
langid
)
returnbuf[2:].tostring().decode('utf-16-le')
Paul Cornelius
was failing with an "Overflow" error on my Windows 8.1 machine, using
Python 3.3 and libusb-1.0.
If this function is called with the default value for langid (None), it
first makes a call to get_descriptor to obtain a list of languages
supported by the device. This second parameter of this function call is
the size of the reply buffer, which was equal to 1024. But a comment in
the libusb-1.0 source (descriptor.c, function
libusb_get_string_descriptor_ascii) reads: /* Some devices choke on size
255 */.
And it seems to be true. When I changed the get_descriptor functioncall to reduce the buffer size parameter to 255 the error disappeared.
I also thought it would be good to limit the size of any buffer passed
to get_string. My modified function now reads as follows:
defget_string(dev,length,index,langid=None):
r"""Retrieve a string descriptor from the device.
dev is the Device object to which the request will be
sent to.
length is the length of string in number of characters.
index is the string descriptor index and langid is the Language
ID of the descriptor. If langid is omitted, the string descriptor
of the first Language ID will be returned.
The return value is the unicode string present in the descriptor.
"""
fromusb.controlimportget_descriptor
iflangidisNone:
# Asking for the zero'th index is special - it returns a string
# descriptor that contains all the language IDs supported by the device.
# Typically there aren't many - often only one. The language IDs are 16
# bit numbers, and they start at the third byte in the descriptor. See
# USB 2.0 specification section 9.6.7 for more information.
#
# Note from libusb 1.0 sources (descriptor.c)
buf=get_descriptor(
dev,
255,
DESC_TYPE_STRING,
0
)
assertlen(buf)>=4
langid=buf[2]|(buf[3]<<8)
lenstr=length*2+2
iflenstr>255:
raiseValueError("String buffer length too long")
buf=get_descriptor(
dev,
length*2+2,# string is utf16 + 2 bytes of the descriptor
DESC_TYPE_STRING,
index,
langid
)
returnbuf[2:].tostring().decode('utf-16-le')
Paul Cornelius