version 1.1.1.1, 2018/04/24 18:55:44
|
version 1.1.1.2, 2018/04/24 19:16:47
|
Line 225 static int usbredir_write(void *priv, ui
|
Line 225 static int usbredir_write(void *priv, ui
|
{ |
{ |
USBRedirDevice *dev = priv; |
USBRedirDevice *dev = priv; |
|
|
return qemu_chr_write(dev->cs, data, count); |
if (!dev->cs->opened) { |
|
return 0; |
|
} |
|
|
|
return qemu_chr_fe_write(dev->cs, data, count); |
} |
} |
|
|
/* |
/* |
Line 234 static int usbredir_write(void *priv, ui
|
Line 238 static int usbredir_write(void *priv, ui
|
|
|
static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p) |
static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p) |
{ |
{ |
AsyncURB *aurb = (AsyncURB *) qemu_mallocz(sizeof(AsyncURB)); |
AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB)); |
aurb->dev = dev; |
aurb->dev = dev; |
aurb->packet = p; |
aurb->packet = p; |
aurb->packet_id = dev->packet_id; |
aurb->packet_id = dev->packet_id; |
Line 247 static AsyncURB *async_alloc(USBRedirDev
|
Line 251 static AsyncURB *async_alloc(USBRedirDev
|
static void async_free(USBRedirDevice *dev, AsyncURB *aurb) |
static void async_free(USBRedirDevice *dev, AsyncURB *aurb) |
{ |
{ |
QTAILQ_REMOVE(&dev->asyncq, aurb, next); |
QTAILQ_REMOVE(&dev->asyncq, aurb, next); |
qemu_free(aurb); |
g_free(aurb); |
} |
} |
|
|
static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id) |
static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id) |
Line 286 static void usbredir_cancel_packet(USBDe
|
Line 290 static void usbredir_cancel_packet(USBDe
|
static struct buf_packet *bufp_alloc(USBRedirDevice *dev, |
static struct buf_packet *bufp_alloc(USBRedirDevice *dev, |
uint8_t *data, int len, int status, uint8_t ep) |
uint8_t *data, int len, int status, uint8_t ep) |
{ |
{ |
struct buf_packet *bufp = qemu_malloc(sizeof(struct buf_packet)); |
struct buf_packet *bufp = g_malloc(sizeof(struct buf_packet)); |
bufp->data = data; |
bufp->data = data; |
bufp->len = len; |
bufp->len = len; |
bufp->status = status; |
bufp->status = status; |
Line 299 static void bufp_free(USBRedirDevice *de
|
Line 303 static void bufp_free(USBRedirDevice *de
|
{ |
{ |
QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next); |
QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next); |
free(bufp->data); |
free(bufp->data); |
qemu_free(bufp); |
g_free(bufp); |
} |
} |
|
|
static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep) |
static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep) |
Line 365 static int usbredir_handle_iso_data(USBR
|
Line 369 static int usbredir_handle_iso_data(USBR
|
} |
} |
|
|
len = isop->len; |
len = isop->len; |
if (len > p->len) { |
if (len > p->iov.size) { |
ERROR("received iso data is larger then packet ep %02X\n", ep); |
ERROR("received iso data is larger then packet ep %02X\n", ep); |
bufp_free(dev, isop, ep); |
bufp_free(dev, isop, ep); |
return USB_RET_NAK; |
return USB_RET_NAK; |
} |
} |
memcpy(p->data, isop->data, len); |
usb_packet_copy(p, isop->data, len); |
bufp_free(dev, isop, ep); |
bufp_free(dev, isop, ep); |
return len; |
return len; |
} else { |
} else { |
Line 379 static int usbredir_handle_iso_data(USBR
|
Line 383 static int usbredir_handle_iso_data(USBR
|
if (dev->endpoint[EP2I(ep)].iso_started) { |
if (dev->endpoint[EP2I(ep)].iso_started) { |
struct usb_redir_iso_packet_header iso_packet = { |
struct usb_redir_iso_packet_header iso_packet = { |
.endpoint = ep, |
.endpoint = ep, |
.length = p->len |
.length = p->iov.size |
}; |
}; |
|
uint8_t buf[p->iov.size]; |
/* No id, we look at the ep when receiving a status back */ |
/* No id, we look at the ep when receiving a status back */ |
|
usb_packet_copy(p, buf, p->iov.size); |
usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet, |
usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet, |
p->data, p->len); |
buf, p->iov.size); |
usbredirparser_do_write(dev->parser); |
usbredirparser_do_write(dev->parser); |
} |
} |
status = dev->endpoint[EP2I(ep)].iso_error; |
status = dev->endpoint[EP2I(ep)].iso_error; |
dev->endpoint[EP2I(ep)].iso_error = 0; |
dev->endpoint[EP2I(ep)].iso_error = 0; |
DPRINTF2("iso-token-out ep %02X status %d len %d\n", ep, status, |
DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status, |
p->len); |
p->iov.size); |
return usbredir_handle_status(dev, status, p->len); |
return usbredir_handle_status(dev, status, p->iov.size); |
} |
} |
} |
} |
|
|
Line 413 static int usbredir_handle_bulk_data(USB
|
Line 419 static int usbredir_handle_bulk_data(USB
|
AsyncURB *aurb = async_alloc(dev, p); |
AsyncURB *aurb = async_alloc(dev, p); |
struct usb_redir_bulk_packet_header bulk_packet; |
struct usb_redir_bulk_packet_header bulk_packet; |
|
|
DPRINTF("bulk-out ep %02X len %d id %u\n", ep, p->len, aurb->packet_id); |
DPRINTF("bulk-out ep %02X len %zd id %u\n", ep, |
|
p->iov.size, aurb->packet_id); |
|
|
bulk_packet.endpoint = ep; |
bulk_packet.endpoint = ep; |
bulk_packet.length = p->len; |
bulk_packet.length = p->iov.size; |
bulk_packet.stream_id = 0; |
bulk_packet.stream_id = 0; |
aurb->bulk_packet = bulk_packet; |
aurb->bulk_packet = bulk_packet; |
|
|
Line 424 static int usbredir_handle_bulk_data(USB
|
Line 431 static int usbredir_handle_bulk_data(USB
|
usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id, |
usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id, |
&bulk_packet, NULL, 0); |
&bulk_packet, NULL, 0); |
} else { |
} else { |
usbredir_log_data(dev, "bulk data out:", p->data, p->len); |
uint8_t buf[p->iov.size]; |
|
usb_packet_copy(p, buf, p->iov.size); |
|
usbredir_log_data(dev, "bulk data out:", buf, p->iov.size); |
usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id, |
usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id, |
&bulk_packet, p->data, p->len); |
&bulk_packet, buf, p->iov.size); |
} |
} |
usbredirparser_do_write(dev->parser); |
usbredirparser_do_write(dev->parser); |
return USB_RET_ASYNC; |
return USB_RET_ASYNC; |
Line 471 static int usbredir_handle_interrupt_dat
|
Line 480 static int usbredir_handle_interrupt_dat
|
} |
} |
|
|
len = intp->len; |
len = intp->len; |
if (len > p->len) { |
if (len > p->iov.size) { |
ERROR("received int data is larger then packet ep %02X\n", ep); |
ERROR("received int data is larger then packet ep %02X\n", ep); |
bufp_free(dev, intp, ep); |
bufp_free(dev, intp, ep); |
return USB_RET_NAK; |
return USB_RET_NAK; |
} |
} |
memcpy(p->data, intp->data, len); |
usb_packet_copy(p, intp->data, len); |
bufp_free(dev, intp, ep); |
bufp_free(dev, intp, ep); |
return len; |
return len; |
} else { |
} else { |
/* Output interrupt endpoint, normal async operation */ |
/* Output interrupt endpoint, normal async operation */ |
AsyncURB *aurb = async_alloc(dev, p); |
AsyncURB *aurb = async_alloc(dev, p); |
struct usb_redir_interrupt_packet_header interrupt_packet; |
struct usb_redir_interrupt_packet_header interrupt_packet; |
|
uint8_t buf[p->iov.size]; |
|
|
DPRINTF("interrupt-out ep %02X len %d id %u\n", ep, p->len, |
DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size, |
aurb->packet_id); |
aurb->packet_id); |
|
|
interrupt_packet.endpoint = ep; |
interrupt_packet.endpoint = ep; |
interrupt_packet.length = p->len; |
interrupt_packet.length = p->iov.size; |
aurb->interrupt_packet = interrupt_packet; |
aurb->interrupt_packet = interrupt_packet; |
|
|
usbredir_log_data(dev, "interrupt data out:", p->data, p->len); |
usb_packet_copy(p, buf, p->iov.size); |
|
usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size); |
usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id, |
usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id, |
&interrupt_packet, p->data, p->len); |
&interrupt_packet, buf, p->iov.size); |
usbredirparser_do_write(dev->parser); |
usbredirparser_do_write(dev->parser); |
return USB_RET_ASYNC; |
return USB_RET_ASYNC; |
} |
} |
Line 807 static int usbredir_initfn(USBDevice *ud
|
Line 818 static int usbredir_initfn(USBDevice *ud
|
/* We'll do the attach once we receive the speed from the usb-host */ |
/* We'll do the attach once we receive the speed from the usb-host */ |
udev->auto_attach = 0; |
udev->auto_attach = 0; |
|
|
|
/* Let the backend know we are ready */ |
|
qemu_chr_fe_open(dev->cs); |
qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read, |
qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read, |
usbredir_chardev_read, usbredir_chardev_event, dev); |
usbredir_chardev_read, usbredir_chardev_event, dev); |
|
|
Line 830 static void usbredir_handle_destroy(USBD
|
Line 843 static void usbredir_handle_destroy(USBD
|
{ |
{ |
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); |
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); |
|
|
qemu_chr_close(dev->cs); |
qemu_chr_fe_close(dev->cs); |
|
qemu_chr_delete(dev->cs); |
/* Note must be done after qemu_chr_close, as that causes a close event */ |
/* Note must be done after qemu_chr_close, as that causes a close event */ |
qemu_bh_delete(dev->open_close_bh); |
qemu_bh_delete(dev->open_close_bh); |
|
|
Line 871 static void usbredir_device_connect(void
|
Line 885 static void usbredir_device_connect(void
|
{ |
{ |
USBRedirDevice *dev = priv; |
USBRedirDevice *dev = priv; |
|
|
|
if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) { |
|
ERROR("Received device connect while already connected\n"); |
|
return; |
|
} |
|
|
switch (device_connect->speed) { |
switch (device_connect->speed) { |
case usb_redir_speed_low: |
case usb_redir_speed_low: |
DPRINTF("attaching low speed device\n"); |
DPRINTF("attaching low speed device\n"); |
Line 899 static void usbredir_device_connect(void
|
Line 918 static void usbredir_device_connect(void
|
static void usbredir_device_disconnect(void *priv) |
static void usbredir_device_disconnect(void *priv) |
{ |
{ |
USBRedirDevice *dev = priv; |
USBRedirDevice *dev = priv; |
|
int i; |
|
|
/* Stop any pending attaches */ |
/* Stop any pending attaches */ |
qemu_del_timer(dev->attach_timer); |
qemu_del_timer(dev->attach_timer); |
|
|
if (dev->dev.attached) { |
if (dev->dev.attached) { |
usb_device_detach(&dev->dev); |
usb_device_detach(&dev->dev); |
usbredir_cleanup_device_queues(dev); |
|
/* |
/* |
* Delay next usb device attach to give the guest a chance to see |
* Delay next usb device attach to give the guest a chance to see |
* see the detach / attach in case of quick close / open succession |
* see the detach / attach in case of quick close / open succession |
*/ |
*/ |
dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200; |
dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200; |
} |
} |
|
|
|
/* Reset state so that the next dev connected starts with a clean slate */ |
|
usbredir_cleanup_device_queues(dev); |
|
memset(dev->endpoint, 0, sizeof(dev->endpoint)); |
|
for (i = 0; i < MAX_ENDPOINTS; i++) { |
|
QTAILQ_INIT(&dev->endpoint[i].bufpq); |
|
} |
} |
} |
|
|
static void usbredir_interface_info(void *priv, |
static void usbredir_interface_info(void *priv, |
Line 959 static void usbredir_configuration_statu
|
Line 985 static void usbredir_configuration_statu
|
dev->dev.data_buf[0] = config_status->configuration; |
dev->dev.data_buf[0] = config_status->configuration; |
len = 1; |
len = 1; |
} |
} |
aurb->packet->len = |
aurb->packet->result = |
usbredir_handle_status(dev, config_status->status, len); |
usbredir_handle_status(dev, config_status->status, len); |
usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); |
usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); |
} |
} |
Line 987 static void usbredir_alt_setting_status(
|
Line 1013 static void usbredir_alt_setting_status(
|
dev->dev.data_buf[0] = alt_setting_status->alt; |
dev->dev.data_buf[0] = alt_setting_status->alt; |
len = 1; |
len = 1; |
} |
} |
aurb->packet->len = |
aurb->packet->result = |
usbredir_handle_status(dev, alt_setting_status->status, len); |
usbredir_handle_status(dev, alt_setting_status->status, len); |
usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); |
usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); |
} |
} |
Line 1003 static void usbredir_iso_stream_status(v
|
Line 1029 static void usbredir_iso_stream_status(v
|
DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status, |
DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status, |
ep, id); |
ep, id); |
|
|
|
if (!dev->dev.attached) { |
|
return; |
|
} |
|
|
dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status; |
dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status; |
if (iso_stream_status->status == usb_redir_stall) { |
if (iso_stream_status->status == usb_redir_stall) { |
DPRINTF("iso stream stopped by peer ep %02X\n", ep); |
DPRINTF("iso stream stopped by peer ep %02X\n", ep); |
Line 1020 static void usbredir_interrupt_receiving
|
Line 1050 static void usbredir_interrupt_receiving
|
DPRINTF("interrupt recv status %d ep %02X id %u\n", |
DPRINTF("interrupt recv status %d ep %02X id %u\n", |
interrupt_receiving_status->status, ep, id); |
interrupt_receiving_status->status, ep, id); |
|
|
|
if (!dev->dev.attached) { |
|
return; |
|
} |
|
|
dev->endpoint[EP2I(ep)].interrupt_error = |
dev->endpoint[EP2I(ep)].interrupt_error = |
interrupt_receiving_status->status; |
interrupt_receiving_status->status; |
if (interrupt_receiving_status->status == usb_redir_stall) { |
if (interrupt_receiving_status->status == usb_redir_stall) { |
Line 1070 static void usbredir_control_packet(void
|
Line 1104 static void usbredir_control_packet(void
|
len = USB_RET_STALL; |
len = USB_RET_STALL; |
} |
} |
} |
} |
aurb->packet->len = len; |
aurb->packet->result = len; |
usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); |
usb_generic_async_ctrl_complete(&dev->dev, aurb->packet); |
} |
} |
async_free(dev, aurb); |
async_free(dev, aurb); |
Line 1105 static void usbredir_bulk_packet(void *p
|
Line 1139 static void usbredir_bulk_packet(void *p
|
len = usbredir_handle_status(dev, bulk_packet->status, len); |
len = usbredir_handle_status(dev, bulk_packet->status, len); |
if (len > 0) { |
if (len > 0) { |
usbredir_log_data(dev, "bulk data in:", data, data_len); |
usbredir_log_data(dev, "bulk data in:", data, data_len); |
if (data_len <= aurb->packet->len) { |
if (data_len <= aurb->packet->iov.size) { |
memcpy(aurb->packet->data, data, data_len); |
usb_packet_copy(aurb->packet, data, data_len); |
} else { |
} else { |
ERROR("bulk buffer too small (%d > %d)\n", data_len, |
ERROR("bulk buffer too small (%d > %zd)\n", data_len, |
aurb->packet->len); |
aurb->packet->iov.size); |
len = USB_RET_STALL; |
len = USB_RET_STALL; |
} |
} |
} |
} |
aurb->packet->len = len; |
aurb->packet->result = len; |
usb_packet_complete(&dev->dev, aurb->packet); |
usb_packet_complete(&dev->dev, aurb->packet); |
} |
} |
async_free(dev, aurb); |
async_free(dev, aurb); |
Line 1185 static void usbredir_interrupt_packet(vo
|
Line 1219 static void usbredir_interrupt_packet(vo
|
} |
} |
|
|
if (aurb->packet) { |
if (aurb->packet) { |
aurb->packet->len = usbredir_handle_status(dev, |
aurb->packet->result = usbredir_handle_status(dev, |
interrupt_packet->status, len); |
interrupt_packet->status, len); |
usb_packet_complete(&dev->dev, aurb->packet); |
usb_packet_complete(&dev->dev, aurb->packet); |
} |
} |