ack On Mon, Jul 9, 2012 at 2:14 PM, Uri Lublin <uril@xxxxxxxxxx> wrote: > From: Arnon Gilboa <agilboa@xxxxxxxxxx> > > - 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@xxxxxxxxxx> > + Uri Lublin <uril@xxxxxxxxxx> > + > + 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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel