我正在调试使用libusb-compat和libusb-1.0在Android上打开设备(在Android代码和从connection.getFileDescriptor()
收到的文件描述符中授予的权限),我收到错误:
07-30 11:24:15.673: WARN/System.err(8934): libusb: 0.000122 error [op_get_config_descriptor] open '/dev/bus/usb/001/002' failed, ret=-1 errno=13
我在libusb.h
找不到错误13。
我的调试输出(fprintf)的初始代码(来自libusb-compat)是:
static int initialize_device(struct usb_device *dev)
{
libusb_device *newlib_dev = dev->dev;
int num_configurations;
size_t alloc_size;
int r;
int i;
/* Device descriptor is identical in both libs */
r = libusb_get_device_descriptor(newlib_dev, (struct libusb_device_descriptor *) &dev->descriptor); // Error here!
if (r < 0) {
usbi_err("error %d getting device descriptor", r);
return compat_err(r);
} else {
// 4ntoine
fprintf(stderr, "pid=%i vid=%i serial=%i\n",
dev->descriptor.idProduct, dev->descriptor.idVendor, dev->descriptor.iSerialNumber);
}
num_configurations = dev->descriptor.bNumConfigurations;
alloc_size = sizeof(struct usb_config_descriptor) * num_configurations;
dev->config = malloc(alloc_size);
if (!dev->config)
return -ENOMEM;
memset(dev->config, 0, alloc_size);
/* Even though structures are identical, we can't just use libusb-1.0's
* config descriptors because we have to store all configurations in
* a single flat memory area (libusb-1.0 provides separate allocations).
* we hand-copy libusb-1.0's descriptors into our own structures. */
// 4ntoine
fprintf(stderr, "%i configurations\n", num_configurations);
for (i = 0; i < num_configurations; i++) {
struct libusb_config_descriptor *newlib_config;
r = libusb_get_config_descriptor(newlib_dev, i, &newlib_config);
if (r < 0) {
// 4ntoine
fprintf(stderr, "failed to libusb_get_config_descriptor: %i\n", r);
clear_device(dev);
free(dev->config);
return compat_err(r);
}
// 4ntoine - print information
fprintf(stderr, "Interfaces: %i\n", (int)config->bNumInterfaces);
const libusb_interface *inter;
const libusb_interface_descriptor *interdesc;
const libusb_endpoint_descriptor *epdesc;
for(int i=0; i<(int)config->bNumInterfaces; i++) {
inter = &config->interface[i];
fprintf(stderr, "Number of alternate settings: %i\n", inter->num_altsetting;
for(int j=0; j<inter->num_altsetting; j++) {
interdesc = &inter->altsetting[j];
fprintf(stderr, "Interface Number: %i\n", (int)interdesc->bInterfaceNumber);
fprintf(stderr, "Number of endpoints: %i\n", (int)interdesc->bNumEndpoints);
for(int k=0; k<(int)interdesc->bNumEndpoints; k++) {
epdesc = &interdesc->endpoint[k];
fprintf(stderr, "Descriptor Type: %i\n", (int)epdesc->bDescriptorType);
fprintf(stderr, "EP Address: %i\n", (int)epdesc->bEndpointAddress);
}
}
}
r = copy_config_descriptor(dev->config + i, newlib_config);
libusb_free_config_descriptor(newlib_config);
if (r < 0) {
// 4ntoine
fprintf(stderr, "failed to copy_config_descriptor: %i\n", r);
clear_device(dev);
free(dev->config);
return r;
}
}
/* libusb doesn't implement this and it doesn't seem that important. If
* someone asks for it, we can implement it in v1.1 or later. */
dev->num_children = 0;
dev->children = NULL;
libusb_ref_device(newlib_dev);
return 0;
}
更新:我正在接近解决我的问题。我发现op_get_config_descriptor(linux_usbfs.c)使用设备路径来使用open()获取fd,但它已经从Android连接接收并应该被使用。所以我不得不更改代码以将fd传递给op_get_config_descriptor()并将其重命名为op_get_config_descriptor2():
static int op_get_config_descriptor2(
struct libusb_device *dev,
uint8_t config_index,
unsigned char *buffer,
size_t len,
int *host_endian,
int fd)
{
char filename[PATH_MAX];
int _fd = fd;
int r;
/* Always read from usbfs: sysfs only has the active descriptor
* this will involve waking the device up, but oh well! */
/* FIXME: the above is no longer true, new kernels have all descriptors
* in the descriptors file. but its kinda hard to detect if the kernel
* is sufficiently new. */
// 4ntoine
if (_fd < 0) {
_get_usbfs_path(dev, filename);
_fd = open(filename, O_RDONLY);
if (_fd < 0) {
usbi_err(DEVICE_CTX(dev),
"open '%s' failed, ret=%d errno=%d", filename, _fd, errno);
return LIBUSB_ERROR_IO;
}
}
else {
usbi_dbg("using fd = %i\n", _fd);
}
r = get_config_descriptor(DEVICE_CTX(dev), _fd, config_index, buffer, len);
close(_fd);
return r;
}
现在的问题是找不到使用该fd的USB设备(它通过Unix套接字传递给AVRDUDE,我检查它是肯定的int,所以我相信它是好的):
lseek(fd, DEVICE_DESC_LENGTH, SEEK_SET)
返回负值
输出结果为:
07-30 15:39:08.723: WARN/System.err(30394): [ 07-30 15:39:08.723 30394: 1764 W/System.err ]
libusb: 0.004884 error [get_config_descriptor] seek failed ret=-1 errno=9
如何解决此问题?
答案 0 :(得分:0)
我通过删除close(_fd);
解决了这个问题。第一次调用关闭设备,第二次调用失败,因为它(文件描述符c):
int API_EXPORTED libusb_get_config_descriptor(
libusb_device *dev,
uint8_t config_index,
struct libusb_config_descriptor **config,
int fd)
{
struct libusb_config_descriptor *_config;
unsigned char tmp[8];
unsigned char *buf = NULL;
int host_endian = 0;
int r;
usbi_dbg("index %d\n", config_index);
if (config_index >= dev->num_configurations)
return LIBUSB_ERROR_NOT_FOUND;
_config = malloc(sizeof(*_config));
if (!_config)
return LIBUSB_ERROR_NO_MEM;
usbi_dbg("get_config_descriptor2 1\n"); // 1st invocation
r = usbi_backend->get_config_descriptor2(dev, config_index, tmp, sizeof(tmp), &host_endian, fd);
if (r < 0)
goto err;
usbi_parse_descriptor(tmp, "bbw", _config, host_endian);
usbi_dbg("usbi_parse_descriptor: length=%i\n", _config->wTotalLength);
buf = malloc(_config->wTotalLength);
if (!buf) {
r = LIBUSB_ERROR_NO_MEM;
goto err;
}
host_endian = 0;
usbi_dbg("get_config_descriptor2 2\n"); // 2nd invocation - error here!
r = usbi_backend->get_config_descriptor2(dev, config_index, buf, _config->wTotalLength, &host_endian, fd);
if (r < 0)
goto err;
usbi_dbg("parse_configuration\n");
r = parse_configuration(dev->ctx, _config, buf, host_endian);
if (r < 0) {
usbi_err(dev->ctx, "parse_configuration failed with error %d", r);
goto err;
}
else
if (r > 0) {
usbi_warn(dev->ctx, "descriptor data still left");
}
free(buf);
*config = _config;
return 0;
err:
free(_config);
if (buf)
free(buf);
return r;
}