static int usb_host_open(USBHostDevice *dev, int bus_num,

                         int addr, const char *port,

                         const char *prod_name, int speed)

{

    int fd = -1, ret;



    trace_usb_host_open_started(bus_num, addr);



    if (dev->fd != -1) {

        goto fail;

    }



    fd = usb_host_open_device(bus_num, addr);

    if (fd < 0) {

        goto fail;

    }

    DPRINTF("husb: opened %s\n", buf);



    dev->bus_num = bus_num;

    dev->addr = addr;

    strcpy(dev->port, port);

    dev->fd = fd;



    /* read the device description */

    dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));

    if (dev->descr_len <= 0) {

        perror("husb: 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





    /* start unconfigured -- we'll wait for the guest to set a configuration */

    if (!usb_host_claim_interfaces(dev, 0)) {

        goto fail;

    }



    usb_ep_init(&dev->dev);

    ret = usb_linux_update_endp_table(dev);

    if (ret) {

        goto fail;

    }



    if (speed == -1) {

        struct usbdevfs_connectinfo ci;



        ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);

        if (ret < 0) {

            perror("usb_host_device_open: USBDEVFS_CONNECTINFO");

            goto fail;

        }



        if (ci.slow) {

            speed = USB_SPEED_LOW;

        } else {

            speed = USB_SPEED_HIGH;

        }

    }

    dev->dev.speed = speed;

    dev->dev.speedmask = (1 << speed);

    if (dev->dev.speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) {

        dev->dev.speedmask |= USB_SPEED_MASK_FULL;

    }



    trace_usb_host_open_success(bus_num, addr);



    if (!prod_name || prod_name[0] == '\0') {

        snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),

                 "host:%d.%d", bus_num, addr);

    } else {

        pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),

                prod_name);

    }



    ret = usb_device_attach(&dev->dev);

    if (ret) {

        goto fail;

    }



    /* USB devio uses 'write' flag to check for async completions */

    qemu_set_fd_handler(dev->fd, NULL, async_complete, dev);



    return 0;



fail:

    trace_usb_host_open_failure(bus_num, addr);

    if (dev->fd != -1) {

        close(dev->fd);

        dev->fd = -1;

    }

    return -1;

}
