[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v8 13/18] hw/usb/redirect-server: Announce the exported device



> Send device_connect when a device is attached and the host has greeted
> us, device_disconnect when it goes away, and handle the bus reset the
> host sends before enumerating.
> 
> device_connect carries no identity. The peer asks the device itself with
> GET_DESCRIPTOR as soon as it enumerates, so anything we put there would
> be made up. The speed is real: it comes from the device on our port.
> 
> Signed-off-by: Jamin Lin <jamin_lin@xxxxxxxxxxxxxx>
> Message-ID: <20261102092201.1729245-14-jamin_lin@xxxxxxxxxxxxxx>
> ---
>  hw/usb/redirect-server.c | 150 ++++++++++++++++++++++++++++++++++++++-
>  hw/usb/trace-events      |   7 ++
>  2 files changed, 156 insertions(+), 1 deletion(-)
>
> diff --git a/hw/usb/redirect-server.c b/hw/usb/redirect-server.c
> index f78351bde919..e207f5a7eb56 100644
> --- a/hw/usb/redirect-server.c
> +++ b/hw/usb/redirect-server.c
> @@ -56,6 +56,7 @@
>  #include "qemu/main-loop.h"
>  #include "qemu/module.h"
>  #include "migration/vmstate.h"
> +#include "qemu/cutils.h"
>  #include "hw/core/sysbus.h"
>  #include "hw/usb/usb.h"
>  #include "chardev/char-fe.h"
> @@ -85,17 +86,105 @@ struct USBRedirServer {
>      /* usbredir over the chardev */
>      struct usbredirparser *parser;
>      QEMUBH *chardev_close_bh;
> +    QEMUBH *announce_bh;
>      const uint8_t *read_buf;
>      int read_buf_size;
>      bool in_write;
>      guint watch;
>      bool host_connected;
> +    bool device_announced;
>  };
>  
> +/*
> + * The device is whatever USBDevice the user plugged into our port with
> + * "-device <device>,bus=<id>.0". NULL until then.
> + */
> +static USBDevice *usbredir_server_device(USBRedirServer *s)
> +{
> +    return s->port.dev;
> +}
> +
> +/*
> + * Device announcement
> + */
> +
> +static uint8_t usbredir_server_speed(USBDevice *device)
> +{
> +    switch (device->speed) {
> +    case USB_SPEED_LOW:
> +        return usb_redir_speed_low;
> +    case USB_SPEED_FULL:
> +        return usb_redir_speed_full;
> +    default:
> +        return usb_redir_speed_high;
> +    }
> +}
> +
> +static void usbredir_server_announce_device(void *opaque)
> +{
> +    USBRedirServer *s = opaque;
> +    USBDevice *device = usbredir_server_device(s);
> +    struct usb_redir_interface_info_header iface_info = {
> +        .interface_count = 0,
> +    };
> +    struct usb_redir_device_connect_header conn = {};
> +
> +    if (!s->host_connected || s->device_announced ||
> +        !device || !device->attached) {
> +        return;
> +    }
> +    s->device_announced = true;
> +    conn.speed = usbredir_server_speed(device);
> +
> +    /*
> +     * The device has to be in DEFAULT state before it can answer
> +     * anything, so reset it here.
> +     */
> +    usb_device_reset(device);
> +
> +    /* Send this before device_connect. The peer needs it to accept us. */
> +    usbredirparser_send_interface_info(s->parser, &iface_info);

The peer's usb-redir client evaluates its "filter" property against
device_connect and this interface_info. With interface_count == 0 and
the all-zero connect header above, any non-empty filter (vendor/product,
class or interface rule) rejects the exported device. Fill
interface_info from the saved configuration descriptor (interface
number, class/subclass/ protocol) and device_connect from the local
USBDevice?

-- 
Marc-André Lureau <marcandre.lureau@xxxxxxxxxx>




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.