title: libusb: failed to get configuration descriptor on Android
body: <p>I'm debugging opening a device on Android (permission granted in Android code and file descriptor received from <code>connection.getFileDescriptor()</code>) using libusb-compat and libusb-1.0, and I'm getting an error:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>I can't find errno 13 in <code>libusb.h</code>.</p>
  
  <p>The init code (from libusb-compat) with my debug output (fprintf's) is:</p>
  
  <pre><code>static int initialize_device(struct usb_device *dev)
  {
      libusb_device *newlib_dev = dev-&gt;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 *) &amp;dev-&gt;descriptor); // Error here!
      if (r &lt; 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-&gt;descriptor.idProduct, dev-&gt;descriptor.idVendor, dev-&gt;descriptor.iSerialNumber);
      }
  
      num_configurations = dev-&gt;descriptor.bNumConfigurations;
      alloc_size = sizeof(struct usb_config_descriptor) * num_configurations;
      dev-&gt;config = malloc(alloc_size);
      if (!dev-&gt;config)
          return -ENOMEM;
      memset(dev-&gt;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 &lt; num_configurations; i++) {
          struct libusb_config_descriptor *newlib_config;
          r = libusb_get_config_descriptor(newlib_dev, i, &amp;newlib_config);
  
          if (r &lt; 0) {
              // 4ntoine
              fprintf(stderr, "failed to libusb_get_config_descriptor: %i\n", r);
  
              clear_device(dev);
              free(dev-&gt;config);
              return compat_err(r);
          }
  
          // 4ntoine - print information
          fprintf(stderr, "Interfaces: %i\n", (int)config-&gt;bNumInterfaces);
          const libusb_interface *inter;
          const libusb_interface_descriptor *interdesc;
          const libusb_endpoint_descriptor *epdesc;
          for(int i=0; i&lt;(int)config-&gt;bNumInterfaces; i++) {
              inter = &amp;config-&gt;interface[i];
              fprintf(stderr, "Number of alternate settings: %i\n", inter-&gt;num_altsetting;
              for(int j=0; j&lt;inter-&gt;num_altsetting; j++) {
                  interdesc = &amp;inter-&gt;altsetting[j];
                  fprintf(stderr, "Interface Number: %i\n", (int)interdesc-&gt;bInterfaceNumber);
                  fprintf(stderr, "Number of endpoints: %i\n", (int)interdesc-&gt;bNumEndpoints);
                  for(int k=0; k&lt;(int)interdesc-&gt;bNumEndpoints; k++) {
                      epdesc = &amp;interdesc-&gt;endpoint[k];
                      fprintf(stderr, "Descriptor Type: %i\n", (int)epdesc-&gt;bDescriptorType);
                      fprintf(stderr, "EP Address: %i\n", (int)epdesc-&gt;bEndpointAddress);
                  }
              }
          }
  
          r = copy_config_descriptor(dev-&gt;config + i, newlib_config);
          libusb_free_config_descriptor(newlib_config);
          if (r &lt; 0) {
              // 4ntoine
              fprintf(stderr, "failed to copy_config_descriptor: %i\n", r);
  
              clear_device(dev);
              free(dev-&gt;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-&gt;num_children = 0;
      dev-&gt;children = NULL;
  
      libusb_ref_device(newlib_dev);
      return 0;
  }
  </code></pre>
  
  <p>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. So I had to change the code to pass fd to op_get_config_descriptor() and rename it to op_get_config_descriptor2():</p>
  
  <pre><code>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 &lt; 0) {
          _get_usbfs_path(dev, filename);
          _fd = open(filename, O_RDONLY);
          if (_fd &lt; 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;
  }
  </code></pre>
  
  <p>Now the problem is that a <a href="http://en.wikipedia.org/wiki/USB" rel="nofollow">USB</a> device can't be found using that fd (it is passed to <a href="http://www.nongnu.org/avrdude/" rel="nofollow">AVRDUDE</a> via Unix socket, and I check it to be positive int, so I believe it's okay):
  <code>lseek(fd, DEVICE_DESC_LENGTH, SEEK_SET)</code> returns negative value</p>
  
  <p>The output is:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>How can I fix this problem?</p>