[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