ack ----- Mensaje original ----- > For now this makes the usb-code even more of a #ifdef party (albeit only > slightly so). But it does give us (theoretical, untested) usb support on > Mac OS X, and once the libusb Windows backend also gets hotplug support, we > can bump the required libusb version to a new enough one, and drop both the > windows gudev emulation as well as the gudev code-paths. > > Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> > --- > configure.ac | 41 ++++++++++------ > gtk/usb-device-manager.c | 119 > ++++++++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 139 insertions(+), 21 deletions(-) > > diff --git a/configure.ac b/configure.ac > index bd59ccf..11f11fc 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -367,21 +367,34 @@ else > if test "x$have_usbredir" = "xno" && test "x$enable_usbredir" = "xyes"; > then > AC_MSG_ERROR([usbredir support explicitly requested, but some required > packages are not available]) > fi > - if test "x$have_usbredir" = "xyes"; then > - AC_DEFINE(USE_USBREDIR, [1], [Define if supporting usbredir proxying]) > - fi > > - # Require gudev for non-windows > - if test "x$os_win32" = "xno"; then > - PKG_CHECK_MODULES([GUDEV], > - [gudev-1.0], > - [have_gudev=yes], > - [have_gudev=no]) > - > - if test "x$have_usbredir" = "xyes" && test "x$have_gudev" = "xno"; then > - AC_MSG_ERROR([usbredir requested but required gudev is not available]) > + # On non windows we need either libusb hotplug support or gudev > + if test "x$have_usbredir" = "xyes" && test "x$os_win32" = "xno"; then > + PKG_CHECK_MODULES([LIBUSB_HOTPLUG], [libusb-1.0 >= 1.0.16], > + [have_libusb_hotplug=yes], [have_libusb_hotplug=no]) > + if test "x$have_libusb_hotplug" = "xyes"; then > + AC_DEFINE(USE_LIBUSB_HOTPLUG, [1], [Define if libusb has hotplug > support]) > + with_usbredir_hotplug="with libusb hotplug" > + else > + PKG_CHECK_MODULES([GUDEV], > + [gudev-1.0], > + [have_gudev=yes], > + [have_gudev=no]) > + > + if test "x$have_gudev" = "xno" && test "x$enable_usbredir" = "xyes"; > then > + AC_MSG_ERROR([usbredir requested but required gudev is not > available]) > + fi > + if test "x$have_gudev" = "xyes"; then > + AC_DEFINE(USE_GUDEV, [1], [Define if supporting gudev]) > + with_usbredir_hotplug="with gudev hotplug" > + else > + have_usbredir=no > + fi > fi > - AC_DEFINE(USE_GUDEV, [1], [Define if supporting gudev]) > + fi > + > + if test "x$have_usbredir" = "xyes"; then > + AC_DEFINE(USE_USBREDIR, [1], [Define if supporting usbredir proxying]) > fi > fi > AM_CONDITIONAL([WITH_USBREDIR], [test "x$have_usbredir" = "xyes"]) > @@ -686,7 +699,7 @@ AC_MSG_NOTICE([ > Target: ${red_target} > SASL support: ${enable_sasl} > Smartcard support: ${have_smartcard} > - USB redirection support: ${have_usbredir} > + USB redirection support: ${have_usbredir} ${with_usbredir_hotplug} > Gtk: $GTK_API_VERSION > > Now type 'make' to build $PACKAGE > diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c > index 8b8bb8b..bdcfd13 100644 > --- a/gtk/usb-device-manager.c > +++ b/gtk/usb-device-manager.c > @@ -34,8 +34,9 @@ > #elif defined(G_OS_WIN32) > #include "win-usb-dev.h" > #include "win-usb-driver-install.h" > -#else > -#warning "Expecting one of G_OS_WIN32 and USE_GUDEV to be defined" > +#define USE_GUDEV /* win-usb-dev.h provides a fake gudev interface */ > +#elif !defined USE_LIBUSB_HOTPLUG > +#error "Expecting one of USE_GUDEV or USE_LIBUSB_HOTPLUG to be defined" > #endif > > #include "channel-usbredir-priv.h" > @@ -106,15 +107,19 @@ struct _SpiceUsbDeviceManagerPrivate { > gchar *redirect_on_connect; > #ifdef USE_USBREDIR > libusb_context *context; > - GUdevClient *udev; > int event_listeners; > GThread *event_thread; > gboolean event_thread_run; > - libusb_device **coldplug_list; /* Avoid needless reprobing during init > */ > struct usbredirfilter_rule *auto_conn_filter_rules; > struct usbredirfilter_rule *redirect_on_connect_rules; > int auto_conn_filter_rules_count; > int redirect_on_connect_rules_count; > +#ifdef USE_GUDEV > + GUdevClient *udev; > + libusb_device **coldplug_list; /* Avoid needless reprobing during init > */ > +#else > + libusb_hotplug_callback_handle hp_handle; > +#endif > #ifdef G_OS_WIN32 > SpiceWinUsbDriver *installer; > #endif > @@ -153,12 +158,19 @@ static void channel_new(SpiceSession *session, > SpiceChannel *channel, > gpointer user_data); > static void channel_destroy(SpiceSession *session, SpiceChannel *channel, > gpointer user_data); > +#ifdef USE_GUDEV > static void spice_usb_device_manager_uevent_cb(GUdevClient *client, > const gchar *action, > GUdevDevice *udevice, > gpointer user_data); > static void spice_usb_device_manager_add_udev(SpiceUsbDeviceManager *self, > GUdevDevice *udev); > +#else > +static int spice_usb_device_manager_hotplug_cb(libusb_context *ctx, > + libusb_device *device, > + libusb_hotplug_event event, > + void *data); > +#endif > static void spice_usb_device_manager_check_redir_on_connect( > SpiceUsbDeviceManager *self, SpiceChannel *channel); > > @@ -231,8 +243,10 @@ static gboolean > spice_usb_device_manager_initable_init(GInitable *initable, > GList *list; > GList *it; > int rc; > +#ifdef USE_GUDEV > const gchar *const subsystems[] = {"usb", NULL}; > #endif > +#endif > > g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(initable), FALSE); > g_return_val_if_fail(err == NULL || *err == NULL, FALSE); > @@ -264,10 +278,10 @@ static gboolean > spice_usb_device_manager_initable_init(GInitable *initable, > } > > /* Start listening for usb devices plug / unplug */ > +#ifdef USE_GUDEV > priv->udev = g_udev_client_new(subsystems); > g_signal_connect(G_OBJECT(priv->udev), "uevent", > G_CALLBACK(spice_usb_device_manager_uevent_cb), self); > - > /* Do coldplug (detection of already connected devices) */ > libusb_get_device_list(priv->context, &priv->coldplug_list); > list = g_udev_client_query_by_subsystem(priv->udev, "usb"); > @@ -278,6 +292,21 @@ static gboolean > spice_usb_device_manager_initable_init(GInitable *initable, > g_list_free(list); > libusb_free_device_list(priv->coldplug_list, 1); > priv->coldplug_list = NULL; > +#else > + rc = libusb_hotplug_register_callback(priv->context, > + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | > LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, > + LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, > + LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, > + spice_usb_device_manager_hotplug_cb, self, &priv->hp_handle); > + if (rc < 0) { > + const char *desc = spice_usbutil_libusb_strerror(rc); > + g_warning("Error initializing USB hotplug support: %s [%i]", desc, > rc); > + g_set_error(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, > + "Error initializing USB hotplug support: %s [%i]", desc, > rc); > + return FALSE; > + } > + spice_usb_device_manager_start_event_listening(self, NULL); > +#endif > > /* Start listening for usb channels connect/disconnect */ > g_signal_connect(priv->session, "channel-new", > @@ -298,6 +327,31 @@ static gboolean > spice_usb_device_manager_initable_init(GInitable *initable, > #endif > } > > +static void spice_usb_device_manager_dispose(GObject *gobject) > +{ > + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject); > + SpiceUsbDeviceManagerPrivate *priv = self->priv; > + > +#ifdef USE_USBREDIR > +#ifdef USE_LIBUSB_HOTPLUG > + if (priv->hp_handle) { > + spice_usb_device_manager_stop_event_listening(self); > + /* This also wakes up the libusb_handle_events() in the event_thread > */ > + libusb_hotplug_deregister_callback(priv->context, priv->hp_handle); > + priv->hp_handle = 0; > + } > +#endif > + if (priv->event_thread && !priv->event_thread_run) { > + g_thread_join(priv->event_thread); > + priv->event_thread = NULL; > + } > +#endif > + > + /* Chain up to the parent class */ > + if (G_OBJECT_CLASS(spice_usb_device_manager_parent_class)->dispose) > + > G_OBJECT_CLASS(spice_usb_device_manager_parent_class)->dispose(gobject); > +} > + > static void spice_usb_device_manager_finalize(GObject *gobject) > { > SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject); > @@ -308,11 +362,12 @@ static void spice_usb_device_manager_finalize(GObject > *gobject) > g_ptr_array_unref(priv->devices); > > #ifdef USE_USBREDIR > +#ifdef USE_GUDEV > g_clear_object(&priv->udev); > +#endif > + g_return_if_fail(priv->event_thread == NULL); > if (priv->context) > libusb_exit(priv->context); > - if (priv->event_thread) > - g_thread_join(priv->event_thread); > free(priv->auto_conn_filter_rules); > free(priv->redirect_on_connect_rules); > #ifdef G_OS_WIN32 > @@ -433,6 +488,7 @@ static void > spice_usb_device_manager_class_init(SpiceUsbDeviceManagerClass *klas > GObjectClass *gobject_class = G_OBJECT_CLASS (klass); > GParamSpec *pspec; > > + gobject_class->dispose = spice_usb_device_manager_dispose; > gobject_class->finalize = spice_usb_device_manager_finalize; > gobject_class->get_property = spice_usb_device_manager_get_property; > gobject_class->set_property = spice_usb_device_manager_set_property; > @@ -601,6 +657,7 @@ static void > spice_usb_device_manager_class_init(SpiceUsbDeviceManagerClass *klas > /* ------------------------------------------------------------------ */ > /* gudev / libusb Helper functions */ > > +#ifdef USE_GUDEV > static gboolean spice_usb_device_manager_get_udev_bus_n_address( > GUdevDevice *udev, int *bus, int *address) > { > @@ -622,6 +679,7 @@ static gboolean > spice_usb_device_manager_get_udev_bus_n_address( > > return *bus && *address; > } > +#endif > > static gboolean spice_usb_device_manager_get_device_descriptor( > libusb_device *libdev, > @@ -724,6 +782,7 @@ spice_usb_device_manager_device_match(SpiceUsbDevice > *device, > spice_usb_device_get_devaddr(device) == address); > } > > +#ifdef USE_GUDEV > static gboolean > spice_usb_device_manager_libdev_match(libusb_device *libdev, > const int bus, const int address) > @@ -731,6 +790,7 @@ spice_usb_device_manager_libdev_match(libusb_device > *libdev, > return (libusb_get_bus_number(libdev) == bus && > libusb_get_device_address(libdev) == address); > } > +#endif > > #else /* Win32 -- match functions for Windows -- match by vid:pid */ > static gboolean > @@ -846,6 +906,7 @@ static void > spice_usb_device_manager_remove_dev(SpiceUsbDeviceManager *self, > spice_usb_device_unref(device); > } > > +#ifdef USE_GUDEV > static void spice_usb_device_manager_add_udev(SpiceUsbDeviceManager *self, > GUdevDevice *udev) > { > @@ -920,6 +981,50 @@ static void > spice_usb_device_manager_uevent_cb(GUdevClient *client, > else if (g_str_equal (action, "remove")) > spice_usb_device_manager_remove_udev(self, udevice); > } > +#else > +struct hotplug_idle_cb_args { > + SpiceUsbDeviceManager *self; > + libusb_device *device; > + libusb_hotplug_event event; > +}; > + > +static gboolean spice_usb_device_manager_hotplug_idle_cb(gpointer user_data) > +{ > + struct hotplug_idle_cb_args *args = user_data; > + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(args->self); > + > + switch (args->event) { > + case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: > + spice_usb_device_manager_add_dev(self, args->device); > + break; > + case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: > + spice_usb_device_manager_remove_dev(self, > + libusb_get_bus_number(args->device), > + > libusb_get_device_address(args->device)); > + break; > + } > + libusb_unref_device(args->device); > + g_object_unref(self); > + g_free(args); > + return FALSE; > +} > + > +/* Can be called from both the main-thread as well as the event_thread */ > +static int spice_usb_device_manager_hotplug_cb(libusb_context *ctx, > + libusb_device *device, > + libusb_hotplug_event event, > + void > *user_data) > +{ > + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(user_data); > + struct hotplug_idle_cb_args *args = g_malloc(sizeof(*args)); > + > + args->self = g_object_ref(self); > + args->device = libusb_ref_device(device); > + args->event = event; > + g_idle_add(spice_usb_device_manager_hotplug_idle_cb, args); > + return 0; > +} > +#endif > > static void spice_usb_device_manager_channel_connect_cb( > GObject *gobject, GAsyncResult *channel_res, gpointer user_data) > -- > 1.8.3.1 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel > _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel