/* Don't use this function from within an interrupt context, like a bottom half handler. If you need an asynchronous message, or need to send a message from within interrupt context, use usb_submit_urb() If a thread in your driver uses this call, make sure your disconnect() method can wait for it to complete. Since you don't have a handle on the URB used, you can't cancel the request.  */
int usb_control_msg(struct usb_host_virt_dev *dev, u32 pipe, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size, s32 timeout)
/* Don't use this function from within an interrupt context, like a bottom half handler. If you need an asynchronous message, or need to send a message from within interrupt context, use usb_submit_urb() If a thread in your driver uses this call, make sure your disconnect() method can wait for it to complete. Since you don't have a handle on the URB used, you can't cancel the request.  */
int usb_control_msg(struct usb_host_virt_dev *dev, u32 pipe, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size, s32 timeout)
{
    int ret  = 0;
    struct usb_ctrlrequest *dr = NULL;
    dr = malloc(sizeof(struct usb_ctrlrequest));
    if (!dr)
    {
        hal_log_err("ERR: malloc failed");
        return -ENOMEM;
    }
    memset(dr, 0, sizeof(struct usb_ctrlrequest));
    dr->bRequestType    = requesttype;
    dr->bRequest        = request;
    dr->wValue          = value;
    dr->wIndex          = index;
    dr->wLength         = size;
    ret = _usb_internal_ctrll_msg(dev, pipe, dr, data, size, timeout);
    if (dr)
    {
        free((void *)dr);
        dr = NULL;
    }
    else
    {
       hal_log_err("ERR: parameter is NULL, can't free");
    }
    return ret;
}