#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
#include "qemu/iov.h"
-#include "char/char.h"
+#include "sysemu/char.h"
#include <dirent.h>
#include <sys/ioctl.h>
/* Data passed from chardev the fd_read cb to the usbredirparser read cb */
const uint8_t *read_buf;
int read_buf_size;
+ /* Active chardev-watch-tag */
+ guint watch;
/* For async handling of close */
QEMUBH *chardev_close_bh;
/* To delay the usb attach in case of quick chardev close + open */
return count;
}
+static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond,
+ void *opaque)
+{
+ USBRedirDevice *dev = opaque;
+
+ dev->watch = 0;
+ usbredirparser_do_write(dev->parser);
+
+ return FALSE;
+}
+
static int usbredir_write(void *priv, uint8_t *data, int count)
{
USBRedirDevice *dev = priv;
+ int r;
- if (!dev->cs->opened) {
+ if (!dev->cs->be_open) {
return 0;
}
return 0;
}
- return qemu_chr_fe_write(dev->cs, data, count);
+ r = qemu_chr_fe_write(dev->cs, data, count);
+ if (r < count) {
+ if (!dev->watch) {
+ dev->watch = qemu_chr_fe_add_watch(dev->cs, G_IO_OUT,
+ usbredir_write_unblocked, dev);
+ }
+ if (r < 0) {
+ r = 0;
+ }
+ }
+ return r;
}
/*
uint8_t ep)
{
struct usb_redir_bulk_packet_header bulk_packet;
- size_t size = (p->combined) ? p->combined->iov.size : p->iov.size;
+ size_t size = usb_packet_size(p);
const int maxp = dev->endpoint[EP2I(ep)].max_packet_size;
if (usbredir_already_in_flight(dev, p->id)) {
&bulk_packet, NULL, 0);
} else {
uint8_t buf[size];
- if (p->combined) {
- iov_to_buf(p->combined->iov.iov, p->combined->iov.niov,
- 0, buf, size);
- } else {
- usb_packet_copy(p, buf, size);
- }
+ usb_packet_copy(p, buf, size);
usbredir_log_data(dev, "bulk data out:", buf, size);
usbredirparser_send_bulk_packet(dev->parser, p->id,
&bulk_packet, buf, size);
usbredirparser_destroy(dev->parser);
dev->parser = NULL;
}
+ if (dev->watch) {
+ g_source_remove(dev->watch);
+ dev->watch = 0;
+ }
}
static void usbredir_create_parser(USBRedirDevice *dev)
dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH;
/* Let the backend know we are ready */
- qemu_chr_fe_open(dev->cs);
qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
usbredir_chardev_read, usbredir_chardev_event, dev);
{
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
- qemu_chr_fe_close(dev->cs);
qemu_chr_delete(dev->cs);
+ dev->cs = NULL;
/* Note must be done after qemu_chr_close, as that causes a close event */
qemu_bh_delete(dev->chardev_close_bh);
if (dev->parser) {
usbredirparser_destroy(dev->parser);
}
+ if (dev->watch) {
+ g_source_remove(dev->watch);
+ }
free(dev->filter_rules);
}
USBRedirDevice *dev = priv;
const char *speed;
- if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
+ if (timer_pending(dev->attach_timer) || dev->dev.attached) {
ERROR("Received device connect while already connected\n");
return;
}
* If we receive interface info after the device has already been
* connected (ie on a set_config), re-check interface dependent things.
*/
- if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
+ if (timer_pending(dev->attach_timer) || dev->dev.attached) {
usbredir_check_bulk_receiving(dev);
if (usbredir_check_filter(dev)) {
ERROR("Device no longer matches filter after interface info "
p = usbredir_find_packet_by_id(dev, ep, id);
if (p) {
- size_t size = (p->combined) ? p->combined->iov.size : p->iov.size;
+ size_t size = usb_packet_size(p);
usbredir_handle_status(dev, p, bulk_packet->status);
if (data_len > 0) {
usbredir_log_data(dev, "bulk data in:", data, data_len);
p->status = USB_RET_BABBLE;
data_len = len = size;
}
- if (p->combined) {
- iov_from_buf(p->combined->iov.iov, p->combined->iov.niov,
- 0, data, data_len);
- } else {
- usb_packet_copy(p, data, data_len);
- }
+ usb_packet_copy(p, data, data_len);
}
p->actual_length = len;
if (p->pid == USB_TOKEN_IN && p->ep->pipeline) {
}
if (QTAILQ_EMPTY(&dev->endpoint[EP2I(ep)].bufpq)) {
- usb_wakeup(usb_ep_get(&dev->dev, USB_TOKEN_IN, ep & 0x0f));
+ usb_wakeup(usb_ep_get(&dev->dev, USB_TOKEN_IN, ep & 0x0f), 0);
}
/* bufp_alloc also adds the packet to the ep queue */
{
USBRedirDevice *dev = priv;
+ if (dev->parser == NULL) {
+ return 0;
+ }
+
switch (dev->device_info.speed) {
case usb_redir_speed_low:
dev->dev.speed = USB_SPEED_LOW;
uc->ep_stopped = usbredir_ep_stopped;
dc->vmsd = &usbredir_vmstate;
dc->props = usbredir_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo usbredir_dev_info = {