/* Returns the number of bytes received on success, or else the status code returned by the underlying usb_control_msg() call.  */
int usb_get_string(struct usb_host_virt_dev *dev, u16 langid, uint8_t index, void *buf, int32_t size)
/* Returns the number of bytes received on success, or else the status code returned by the underlying usb_control_msg() call.  */
int usb_get_string(struct usb_host_virt_dev *dev, u16 langid, uint8_t index, void *buf, int32_t size)
{
    int i;
    int result;
    for (i = 0; i < 3; ++i)
    {
        result = usb_control_msg(dev,
                                 usb_rcvctrlpipe(dev, 0),
                                 USB_REQ_GET_DESCRIPTOR,
                                 USB_DIR_IN,
                                 (USB_DT_STRING << 8) + index,
                                 langid,
                                 buf,
                                 size,
                                 USB_CTRL_GET_TIMEOUT);
        if (!(result == 0 || result == -EPIPE))
        {
            break;
        }
    }
    return result;
}