[Spice-devel] [spice-gtk Win32 v5 15/22] Windows mingw: usb: implement GUdevDevice & GUdevClient for windows

Marc-André Lureau marcandre.lureau at gmail.com
Mon Jul 9 08:37:16 PDT 2012


ack

On Mon, Jul 9, 2012 at 2:14 PM, Uri Lublin <uril at redhat.com> wrote:
> From: Arnon Gilboa <agilboa at redhat.com>
>
> - Added win-usb-dev.[ch]
> - Added GUdevDevice and GUdevClient like classes
> - Added uevent signal based on WM_DEVICECHANGE
> ---
>  gtk/Makefile.am          |   13 ++
>  gtk/usb-device-manager.c |    8 +
>  gtk/win-usb-dev.c        |  510 ++++++++++++++++++++++++++++++++++++++++++++++
>  gtk/win-usb-dev.h        |  110 ++++++++++
>  4 files changed, 641 insertions(+), 0 deletions(-)
>  create mode 100644 gtk/win-usb-dev.c
>  create mode 100644 gtk/win-usb-dev.h
>
> diff --git a/gtk/Makefile.am b/gtk/Makefile.am
> index 10fa9cd..8edea9a 100644
> --- a/gtk/Makefile.am
> +++ b/gtk/Makefile.am
> @@ -312,6 +312,19 @@ libspice_client_glib_2_0_la_SOURCES += coroutine_gthread.c
>  libspice_client_glib_2_0_la_LIBADD += $(GTHREAD_LIBS)
>  endif
>
> +
> +WIN_USB_FILES= \
> +       win-usb-dev.h                   \
> +       win-usb-dev.c                   \
> +       $(NULL)
> +
> +if OS_WIN32
> +if WITH_USBREDIR
> +libspice_client_glib_2_0_la_SOURCES += \
> +       $(WIN_USB_FILES)
> +endif
> +endif
> +
>  displaysrc =                                   \
>         glib-compat.h                           \
>         display/edid.h                          \
> diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
> index 753ffc2..c323ca9 100644
> --- a/gtk/usb-device-manager.c
> +++ b/gtk/usb-device-manager.c
> @@ -28,7 +28,15 @@
>  #ifdef USE_USBREDIR
>  #include <errno.h>
>  #include <libusb.h>
> +
> +#if defined(USE_GUDEV)
>  #include <gudev/gudev.h>
> +#elif defined(G_OS_WIN32)
> +#include "win-usb-dev.h"
> +#else
> +#warning "Expecting one of G_OS_WIN32 and USE_GUDEV to be defined"
> +#endif
> +
>  #include "channel-usbredir-priv.h"
>  #include "usbredirhost.h"
>  #include "usbutil.h"
> diff --git a/gtk/win-usb-dev.c b/gtk/win-usb-dev.c
> new file mode 100644
> index 0000000..bc21e08
> --- /dev/null
> +++ b/gtk/win-usb-dev.c
> @@ -0,0 +1,510 @@
> +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> +/*
> +   Copyright (C) 2012 Red Hat, Inc.
> +
> +   Red Hat Authors:
> +   Arnon Gilboa <agilboa at redhat.com>
> +   Uri Lublin   <uril at redhat.com>
> +
> +   This library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   This library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with this library; if not, see <http://www.gnu.org/licenses/>.
> +*/
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include <windows.h>
> +#include <libusb.h>
> +#include "win-usb-dev.h"
> +#include "spice-marshal.h"
> +#include "spice-util.h"
> +#include "usbutil.h"
> +
> +#define G_UDEV_CLIENT_GET_PRIVATE(obj) \
> +    (G_TYPE_INSTANCE_GET_PRIVATE((obj), G_UDEV_TYPE_CLIENT, GUdevClientPrivate))
> +
> +struct _GUdevClientPrivate {
> +    libusb_context *ctx;
> +    gssize udev_list_size;
> +    GList *udev_list;
> +    HWND hwnd;
> +};
> +
> +#define G_UDEV_CLIENT_WINCLASS_NAME  TEXT("G_UDEV_CLIENT")
> +
> +static void g_udev_client_initable_iface_init(GInitableIface  *iface);
> +
> +G_DEFINE_TYPE_WITH_CODE(GUdevClient, g_udev_client, G_TYPE_OBJECT,
> +                        G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, g_udev_client_initable_iface_init));
> +
> +
> +typedef struct _GUdevDeviceInfo GUdevDeviceInfo;
> +
> +struct _GUdevDeviceInfo {
> +    guint16 bus;
> +    guint16 addr;
> +    guint16 vid;
> +    guint16 pid;
> +    guint16 class;
> +    gchar sclass[4];
> +    gchar sbus[4];
> +    gchar saddr[4];
> +};
> +
> +struct _GUdevDevicePrivate
> +{
> +    /* FixMe: move above fields to this structure and access them directly */
> +    GUdevDeviceInfo *udevinfo;
> +};
> +
> +G_DEFINE_TYPE(GUdevDevice, g_udev_device, G_TYPE_OBJECT)
> +
> +
> +enum
> +{
> +    UEVENT_SIGNAL,
> +    LAST_SIGNAL,
> +};
> +
> +static guint signals[LAST_SIGNAL] = { 0, };
> +static GUdevClient *singleton = NULL;
> +
> +static GUdevDevice *g_udev_device_new(GUdevDeviceInfo *udevinfo);
> +static LRESULT CALLBACK wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
> +static gboolean get_usb_dev_info(libusb_device *dev, GUdevDeviceInfo *udevinfo);
> +
> +//uncomment to debug gudev device lists.
> +//#define DEBUG_GUDEV_DEVICE_LISTS
> +
> +#ifdef DEBUG_GUDEV_DEVICE_LISTS
> +static void g_udev_device_print_list(GList *l, const gchar *msg);
> +#else
> +static void g_udev_device_print_list(GList *l, const gchar *msg) {}
> +#endif
> +static void g_udev_device_print(GUdevDevice *udev, const gchar *msg);
> +
> +GQuark g_udev_client_error_quark(void)
> +{
> +    return g_quark_from_static_string("win-gudev-client-error-quark");
> +}
> +
> +GUdevClient *g_udev_client_new(const gchar* const *subsystems)
> +{
> +    if (!singleton) {
> +        singleton = g_initable_new(G_UDEV_TYPE_CLIENT, NULL, NULL, NULL);
> +        return singleton;
> +    } else {
> +        return g_object_ref(singleton);
> +    }
> +}
> +
> +
> +/*
> + * devs [in,out] an empty devs list in, full devs list out
> + * Returns: number-of-devices, or a negative value on error.
> + */
> +static ssize_t
> +g_udev_client_list_devices(GUdevClient *self, GList **devs,
> +                           GError **err, const gchar *name)
> +{
> +    gssize rc;
> +    libusb_device **lusb_list, **dev;
> +    GUdevClientPrivate *priv;
> +    GUdevDeviceInfo *udevinfo;
> +    GUdevDevice *udevice;
> +    ssize_t n;
> +
> +    g_return_val_if_fail(G_UDEV_IS_CLIENT(self), -1);
> +    g_return_val_if_fail(devs != NULL, -2);
> +
> +    priv = self->priv;
> +
> +    g_return_val_if_fail(self->priv->ctx != NULL, -3);
> +
> +    rc = libusb_get_device_list(priv->ctx, &lusb_list);
> +    if (rc < 0) {
> +        const char *errstr = spice_usbutil_libusb_strerror(rc);
> +        g_warning("%s: libusb_get_device_list failed", name);
> +        g_set_error(err, G_UDEV_CLIENT_ERROR, G_UDEV_CLIENT_LIBUSB_FAILED,
> +                    "%s: Error getting device list from libusb: %s [%i]",
> +                    name, errstr, rc);
> +        return -4;
> +    }
> +
> +    n = rc;
> +
> +    for (dev = lusb_list; *dev; dev++) {
> +        udevinfo = g_new0(GUdevDeviceInfo, 1);
> +        get_usb_dev_info(*dev, udevinfo);
> +        udevice = g_udev_device_new(udevinfo);
> +        *devs = g_list_prepend(*devs, udevice);
> +    }
> +    libusb_free_device_list(lusb_list, 1);
> +
> +    return n;
> +}
> +
> +static void g_udev_client_free_device_list(GList **devs)
> +{
> +    g_return_if_fail(devs != NULL);
> +    if (*devs) {
> +        g_list_free_full(*devs, g_object_unref);
> +        *devs = NULL;
> +    }
> +}

This is not conventionnal to to use  pointer to pointer (**ptr) for
free() functions. But ok.




-- 
Marc-André Lureau


More information about the Spice-devel mailing list