static void usbredir_handle_control(USBDevice *udev, USBPacket *p,
        int request, int value, int index, int length, uint8_t *data)
{
    USBRedirDevice *dev = USB_REDIRECT(udev);
    struct usb_redir_control_packet_header control_packet;

    if (usbredir_already_in_flight(dev, p->id)) {
        p->status = USB_RET_ASYNC;
        return;
    }

    /* Special cases for certain standard device requests */
    switch (request) {
    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
        DPRINTF("set address %d\n", value);
        dev->dev.addr = value;
        return;
    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
        usbredir_set_config(dev, p, value & 0xff);
        return;
    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
        usbredir_get_config(dev, p);
        return;
    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
        usbredir_set_interface(dev, p, index, value);
        return;
    case InterfaceRequest | USB_REQ_GET_INTERFACE:
        usbredir_get_interface(dev, p, index);
        return;
    }

    /* Normal ctrl requests, note request is (bRequestType << 8) | bRequest */
    DPRINTF(
        "ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %"PRIu64"\n",
        request >> 8, request & 0xff, value, index, length, p->id);

    control_packet.request     = request & 0xFF;
    control_packet.requesttype = request >> 8;
    control_packet.endpoint    = control_packet.requesttype & USB_DIR_IN;
    control_packet.value       = value;
    control_packet.index       = index;
    control_packet.length      = length;

    if (control_packet.requesttype & USB_DIR_IN) {
        usbredirparser_send_control_packet(dev->parser, p->id,
                                           &control_packet, NULL, 0);
    } else {
        usbredir_log_data(dev, "ctrl data out:", data, length);
        usbredirparser_send_control_packet(dev->parser, p->id,
                                           &control_packet, data, length);
    }
    usbredirparser_do_write(dev->parser);
    p->status = USB_RET_ASYNC;
}
static void usbredir_handle_control(USBDevice *udev, USBPacket *p,
        int request, int value, int index, int length, uint8_t *data)
{
    USBRedirDevice *dev = USB_REDIRECT(udev);
    struct usb_redir_control_packet_header control_packet;

    if (usbredir_already_in_flight(dev, p->id)) {
        p->status = USB_RET_ASYNC;
        return;
    }

     
    switch (request) {
    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
        DPRINTF("set address %d\n", value);
        dev->dev.addr = value;
        return;
    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
        usbredir_set_config(dev, p, value & 0xff);
        return;
    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
        usbredir_get_config(dev, p);
        return;
    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
        usbredir_set_interface(dev, p, index, value);
        return;
    case InterfaceRequest | USB_REQ_GET_INTERFACE:
        usbredir_get_interface(dev, p, index);
        return;
    }

     
    DPRINTF(
        "ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %"PRIu64"\n",
        request >> 8, request & 0xff, value, index, length, p->id);

    control_packet.request     = request & 0xFF;
    control_packet.requesttype = request >> 8;
    control_packet.endpoint    = control_packet.requesttype & USB_DIR_IN;
    control_packet.value       = value;
    control_packet.index       = index;
    control_packet.length      = length;

    if (control_packet.requesttype & USB_DIR_IN) {
        usbredirparser_send_control_packet(dev->parser, p->id,
                                           &control_packet, NULL, 0);
    } else {
        usbredir_log_data(dev, "ctrl data out:", data, length);
        usbredirparser_send_control_packet(dev->parser, p->id,
                                           &control_packet, data, length);
    }
    usbredirparser_do_write(dev->parser);
    p->status = USB_RET_ASYNC;
}