func: USBDevice *usb_host_device_open(const char *devname)
  
  {
  
      int fd = -1, ret;
  
      USBHostDevice *dev = NULL;
  
      struct usbdevfs_connectinfo ci;
  
      char buf[1024];
  
      int bus_num, addr;
  
      char product_name[PRODUCT_NAME_SZ];
  
  
  
      dev = qemu_mallocz(sizeof(USBHostDevice));
  
      if (!dev)
  
          goto fail;
  
  
  
  #ifdef DEBUG_ISOCH
  
      printf("usb_host_device_open %s\n", devname);
  
  #endif
  
      if (usb_host_find_device(&bus_num, &addr,
  
                               product_name, sizeof(product_name),
  
                               devname) < 0)
  
          return NULL;
  
  
  
      snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d",
  
               bus_num, addr);
  
      fd = open(buf, O_RDWR | O_NONBLOCK);
  
      if (fd < 0) {
  
          perror(buf);
  
          return NULL;
  
      }
  
  
  
      /* read the device description */
  
      dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
  
      if (dev->descr_len <= 0) {
  
          perror("usb_host_device_open: reading device data failed");
  
          goto fail;
  
      }
  
  
  
  #ifdef DEBUG
  
      {
  
          int x;
  
          printf("=== begin dumping device descriptor data ===\n");
  
          for (x = 0; x < dev->descr_len; x++)
  
              printf("%02x ", dev->descr[x]);
  
          printf("\n=== end dumping device descriptor data ===\n");
  
      }
  
  #endif
  
  
  
      dev->fd = fd;
  
      dev->configuration = 1;
  
  
  
      /* XXX - do something about initial configuration */
  
      if (!usb_host_update_interfaces(dev, 1))
  
          goto fail;
  
  
  
      ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
  
      if (ret < 0) {
  
          perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
  
          goto fail;
  
      }
  
  
  
  #ifdef DEBUG
  
      printf("host USB device %d.%d grabbed\n", bus_num, addr);
  
  #endif
  
  
  
      ret = usb_linux_update_endp_table(dev);
  
      if (ret)
  
          goto fail;
  
  
  
      if (ci.slow)
  
          dev->dev.speed = USB_SPEED_LOW;
  
      else
  
          dev->dev.speed = USB_SPEED_HIGH;
  
      dev->dev.handle_packet = usb_generic_handle_packet;
  
  
  
      dev->dev.handle_reset = usb_host_handle_reset;
  
      dev->dev.handle_control = usb_host_handle_control;
  
      dev->dev.handle_data = usb_host_handle_data;
  
      dev->dev.handle_destroy = usb_host_handle_destroy;
  
  
  
      if (product_name[0] == '\0')
  
          snprintf(dev->dev.devname, sizeof(dev->dev.devname),
  
                   "host:%s", devname);
  
      else
  
          pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
  
                  product_name);
  
  
  
  #ifdef USE_ASYNCIO
  
      /* set up the signal handlers */
  
      sigemptyset(&sigact.sa_mask);
  
      sigact.sa_sigaction = isoch_done;
  
      sigact.sa_flags = SA_SIGINFO;
  
      sigact.sa_restorer = 0;
  
      ret = sigaction(SIG_ISOCOMPLETE, &sigact, NULL);
  
      if (ret < 0) {
  
          perror("usb_host_device_open: sigaction failed");
  
          goto fail;
  
      }
  
  
  
      if (pipe(dev->pipe_fds) < 0) {
  
          perror("usb_host_device_open: pipe creation failed");
  
          goto fail;
  
      }
  
      fcntl(dev->pipe_fds[0], F_SETFL, O_NONBLOCK | O_ASYNC);
  
      fcntl(dev->pipe_fds[1], F_SETFL, O_NONBLOCK);
  
      qemu_set_fd_handler(dev->pipe_fds[0], urb_completion_pipe_read, NULL, dev);
  
  #endif
  
      dev->urbs_ready = 0;
  
      return (USBDevice *)dev;
  
  fail:
  
      if (dev)
  
          qemu_free(dev);
  
      close(fd);
  
      return NULL;
  
  }
  