简体   繁体   English

libusb:无法在Android上获取配置描述符

[英]libusb: failed to get configuration descriptor on Android

I'm debugging opening a device on Android (permission granted in Android code and file descriptor received from connection.getFileDescriptor() ) using libusb-compat and libusb-1.0, and I'm getting an error: 我正在调试使用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

I can't find errno 13 in libusb.h . 我在libusb.h找不到errno 13。

The init code (from libusb-compat) with my debug output (fprintf's) is: 我的调试输出(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;
}

UPDATE: I'm getting closer to fix my problem. 更新:我正在接近解决我的问题。 I found that op_get_config_descriptor (linux_usbfs.c) uses the device path to get fd using open(), but it was already received from the Android connection and should be used. 我发现op_get_config_descriptor(linux_usbfs.c)使用设备路径通过open()获取fd,但是已经从Android连接中收到了它,应该使用它。 So I had to change the code to pass fd to op_get_config_descriptor() and rename it to op_get_config_descriptor2(): 因此,我不得不更改代码以将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;
}

Now the problem is that a USB device can't be found using that fd (it is passed to AVRDUDE via Unix socket, and I check it to be positive int, so I believe it's okay): lseek(fd, DEVICE_DESC_LENGTH, SEEK_SET) returns negative value 现在的问题是,无法使用该fd找到USB设备(它是通过Unix套接字传递给AVRDUDE的 ,我检查它是否为正int,所以我认为还可以): lseek(fd, DEVICE_DESC_LENGTH, SEEK_SET)返回负值

The output is: 输出为:

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

How can I fix this problem? 我该如何解决这个问题?

I solved by removing close(_fd); 我通过删除close(_fd);解决了 . The first invocation closes the device and the second fails because of it (file descriptor.c): 第一次调用会关闭设备,第二次调用会因此而失败(文件描述符.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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM