2013-07-30 26 views
0

我正在調試使用libusb-compat和libusb-1.0在Android上打開設備(在Android代碼中授予的權限和從connection.getFileDescriptor()收到的文件描述符),並且出現錯誤:libusb:未能在Android上獲取配置描述符

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找不到errno 13。

初始化代碼(從的libusb-COMPAT)與我的調試輸出(fprintf中的)是:

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; 
} 

現在的問題是,USB設備無法使用FD上找到(它被傳遞給通過Unix套接字AVRDUDE,我檢查它是積極的整型,所以我相信這沒關係): 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

到更詳細地,它在libusb_get_config_descriptor失敗在descriptor.c: R = usbi_backend-> get_config_descriptor(DEV ,config_index,tmp,sizeof(tmp),&host_endian); (r <0) \t if(r <0) \t \t goto err; 這是否意味着它是Android操作系統的問題? – 4ntoine

回答

0

我解決了刪除close(_fd);。第一次調用關閉裝置和所述第二失敗,因爲它(文件descriptor.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; 
}