static void usbredir_control_packet(void *priv, uint32_t id,

    struct usb_redir_control_packet_header *control_packet,

    uint8_t *data, int data_len)

{

    USBRedirDevice *dev = priv;

    int len = control_packet->length;

    AsyncURB *aurb;



    DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,

            len, id);



    aurb = async_find(dev, id);

    if (!aurb) {

        free(data);

        return;

    }



    aurb->control_packet.status = control_packet->status;

    aurb->control_packet.length = control_packet->length;

    if (memcmp(&aurb->control_packet, control_packet,

               sizeof(*control_packet))) {

        ERROR("return control packet mismatch, please report this!\n");

        len = USB_RET_NAK;

    }



    if (aurb->packet) {

        len = usbredir_handle_status(dev, control_packet->status, len);

        if (len > 0) {

            usbredir_log_data(dev, "ctrl data in:", data, data_len);

            if (data_len <= sizeof(dev->dev.data_buf)) {

                memcpy(dev->dev.data_buf, data, data_len);

            } else {

                ERROR("ctrl buffer too small (%d > %zu)\n",

                      data_len, sizeof(dev->dev.data_buf));

                len = USB_RET_STALL;

            }

        }

        aurb->packet->len = len;

        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);

    }

    async_free(dev, aurb);

    free(data);

}
