I am puzzled by some functions calling in the function : "spice_usb_device_manager_initable_init"
At this block:
/* 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");
...
...
libusb_free_device_list(priv->coldplug_list, 1);
priv->coldplug_list = NULL;
My questions are as follows:
1. Well, it seems that there are two routines to gather information of the already connected devices :
"libusb_get_device_list" and "
g_udev_client_query_by_subsystem " , which is the really for wok one ?
"g_udev_client_query_by_subsystem" seems to be , am I right ?
2. So, the second question is, why we gather info to "priv->coldplug_list", as the codes above, it just be freed, and has never been used!
list :
I type the descriptions of these two lists, as you can see that the ids of them are very different, Why???
desc Linux 3.2.0-23-generic-pae ehci_hcd EHCI Host Controller [1d6b:0002] at 1-1
desc Linux 3.2.0-23-generic-pae uhci_hcd UHCI Host Controller [1d6b:0001] at 2-1
desc Linux 3.2.0-23-generic-pae uhci_hcd UHCI Host Controller [1d6b:0001] at 3-1
desc Linux 3.2.0-23-generic-pae uhci_hcd UHCI Host Controller [1d6b:0001] at 4-1
desc Linux 3.2.0-23-generic-pae uhci_hcd UHCI Host Controller [1d6b:0001] at 5-1
desc NEC Corp. HighSpeed Hub [0409:005a] at 1-4
desc Alcor Micro Corp. USB Hub [058f:6254] at 1-5
desc USB Keykoard [1a2c:0021] at 3-2
desc Logitech USB-PS/2 Optical Mouse [046d:c045] at 3-3
desc USB 2.0 Peripheral Switch USB 2.0 Peripheral Switch [0557:2407] at 1-6
priv->coldplug_list :
name usb2
name 2-0:1.0
name usb3
name 3-0:1.0
name 3-1
name 3-1:1.0
name 3-1:1.1
name 3-2
name 3-2:1.0
name usb4
name 4-0:1.0
name usb5
name 5-0:1.0
name usb1
name 1-0:1.0
name 1-5
name 1-5.2
name 1-5.2:1.0
name 1-5.2:1.1
name hiddev0
name 1-5:1.0
name 1-8
name 1-8:1.0
and the codes I get the log above are attached.
Thanks a lot! Looking forward to you !!!
2012/6/14 Hans de Goede <hdegoede@xxxxxxxxxx>
Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
---
doc/reference/spice-gtk-sections.txt | 2 +
gtk/map-file | 2 +
gtk/usb-device-manager.c | 130 ++++++++++++++++++++++++++++++++--
gtk/usb-device-manager.h | 5 ++
4 files changed, 132 insertions(+), 7 deletions(-)
diff --git a/doc/reference/spice-gtk-sections.txt b/doc/reference/spice-gtk-sections.txt
index a339d32..7eea1fb 100644
--- a/doc/reference/spice-gtk-sections.txt
+++ b/doc/reference/spice-gtk-sections.txt
@@ -293,6 +293,8 @@ spice_usb_device_manager_disconnect_device
spice_usb_device_manager_can_redirect_device
spice_usb_device_manager_connect_device_async
spice_usb_device_manager_connect_device_finish
+spice_usb_device_manager_disable_automounting
+spice_usb_device_manager_restore_automounting
<SUBSECTION>
SpiceUsbDevice
spice_usb_device_get_description
diff --git a/gtk/map-file b/gtk/map-file
index 32ead37..dd3495c 100644
--- a/gtk/map-file
+++ b/gtk/map-file
@@ -89,11 +89,13 @@ spice_usb_device_get_type;
spice_usb_device_manager_can_redirect_device;
spice_usb_device_manager_connect_device_async;
spice_usb_device_manager_connect_device_finish;
+spice_usb_device_manager_disable_automounting;
spice_usb_device_manager_disconnect_device;
spice_usb_device_manager_get;
spice_usb_device_manager_get_devices;
spice_usb_device_manager_get_type;
spice_usb_device_manager_is_device_connected;
+spice_usb_device_manager_restore_automounting;
spice_usb_device_widget_get_type;
spice_usb_device_widget_new;
spice_usbredir_channel_get_type;
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index 25cb14a..bf08b95 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -34,6 +34,7 @@
#include "usbutil.h"
#endif
+#include "desktop-integration.h"
#include "spice-session-priv.h"
#include "spice-client.h"
#include "spice-marshal.h"
@@ -96,6 +97,8 @@ struct _SpiceUsbDeviceManagerPrivate {
libusb_device **coldplug_list; /* Avoid needless reprobing during init */
struct usbredirfilter_rule *auto_conn_filter_rules;
int auto_conn_filter_rules_count;
+ int disable_automount;
+ guint update_automount_id;
#endif
GPtrArray *devices;
GPtrArray *channels;
@@ -284,9 +287,17 @@ static void spice_usb_device_manager_set_property(GObject *gobject,
case PROP_SESSION:
priv->session = g_value_get_object(value);
break;
- case PROP_AUTO_CONNECT:
- priv->auto_connect = g_value_get_boolean(value);
+ case PROP_AUTO_CONNECT: {
+ gboolean new_val = g_value_get_boolean(value);
+ if (priv->auto_connect != new_val) {
+ priv->auto_connect = new_val;
+ if (priv->auto_connect)
+ spice_usb_device_manager_disable_automounting(self);
+ else
+ spice_usb_device_manager_restore_automounting(self);
+ }
break;
+ }
case PROP_AUTO_CONNECT_FILTER: {
const gchar *filter = g_value_get_string(value);
#ifdef USE_USBREDIR
@@ -341,6 +352,15 @@ static void spice_usb_device_manager_class_init(SpiceUsbDeviceManagerClass *klas
/**
* SpiceUsbDeviceManager:auto-connect:
+ *
+ * Set this to TRUE to automatically redirect newly plugged in device.
+ *
+ * When this property changes from FALSE to TRUE, #SpiceUsbDeviceManager
+ * calls spice_usb_device_manager_disable_automounting() once, and on TRUE
+ * to FALSE it calls spice_usb_device_manager_restore_automounting().
+ *
+ * Note when #SpiceGtkSession's auto-usbredir property is TRUE, this
+ * property is controlled by #SpiceGtkSession.
*/
pspec = g_param_spec_boolean("auto-connect", "Auto Connect",
"Auto connect plugged in USB devices",
@@ -642,19 +662,33 @@ static void spice_usb_device_manager_uevent_cb(GUdevClient *client,
spice_usb_device_manager_remove_dev(self, udevice);
}
+struct channel_connect_cb_data {
+ GSimpleAsyncResult *result;
+ gboolean restore_automount;
+};
+
static void spice_usb_device_manager_channel_connect_cb(
GObject *gobject, GAsyncResult *channel_res, gpointer user_data)
{
SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(gobject);
- GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(user_data);
+ struct channel_connect_cb_data *data = ""> + SpiceUsbDeviceManager *self;
GError *err = NULL;
spice_usbredir_channel_connect_device_finish(channel, channel_res, &err);
if (err) {
- g_simple_async_result_take_error(result, err);
+ g_simple_async_result_take_error(data->result, err);
}
- g_simple_async_result_complete(result);
- g_object_unref(result);
+
+ if (data->restore_automount) {
+ self = SPICE_USB_DEVICE_MANAGER(g_async_result_get_source_object(
+ G_ASYNC_RESULT(data->result)));
+ spice_usb_device_manager_restore_automounting(self);
+ }
+
+ g_simple_async_result_complete(data->result);
+ g_object_unref(data->result);
+ g_free(data);
}
/* ------------------------------------------------------------------ */
@@ -848,6 +882,7 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
#ifdef USE_USBREDIR
SpiceUsbDeviceManagerPrivate *priv = self->priv;
+ struct channel_connect_cb_data *data;
guint i;
if (spice_usb_device_manager_is_device_connected(self, device)) {
@@ -863,11 +898,18 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
if (spice_usbredir_channel_get_device(channel))
continue; /* Skip already used channels */
+ data = "" channel_connect_cb_data, 1);
+ data->result = result;
+ /* If automount is disabled, ensure it stays disabled while we run */
+ if (priv->disable_automount) {
+ spice_usb_device_manager_disable_automounting(self);
+ data->restore_automount = TRUE;
+ }
spice_usbredir_channel_connect_device_async(channel,
(libusb_device *)device,
cancellable,
spice_usb_device_manager_channel_connect_cb,
- result);
+ data);
return;
}
#endif
@@ -1047,3 +1089,77 @@ gchar *spice_usb_device_get_description(SpiceUsbDevice *_device, const gchar *fo
return NULL;
#endif
}
+
+/* ------------------------------------------------------------------ */
+/* Automount disable helper functions */
+
+static gboolean spice_usb_device_manager_update_automount(gpointer user_data)
+{
+ SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(user_data);
+ SpiceUsbDeviceManagerPrivate *priv = self->priv;
+ SpiceDesktopIntegration *di = spice_desktop_integration_get(priv->session);
+
+ if (priv->disable_automount == 0)
+ spice_desktop_integration_restore_automount(di);
+
+ priv->update_automount_id = 0;
+ return FALSE;
+}
+
+/**
+ * spice_usb_device_manager_disable_automounting:
+ * @manager: the #SpiceUsbDeviceManager manager
+ *
+ * Disables automounting of newly plugged in devices by the client OS, to avoid
+ * newly plugged in devices getting mounted by the client OS, before they can
+ * be redirected.
+ *
+ * When this function gets called multiple times,
+ * spice_usb_device_manager_restore_automounting() must be called the same
+ * amount of times, before automounting gets restored.
+ */
+void spice_usb_device_manager_disable_automounting(SpiceUsbDeviceManager *self)
+{
+#ifdef USE_USBREDIR
+ SpiceUsbDeviceManagerPrivate *priv = self->priv;
+ SpiceDesktopIntegration *di = spice_desktop_integration_get(priv->session);
+
+ priv->disable_automount++;
+ if (priv->disable_automount == 1)
+ spice_desktop_integration_disable_automount(di);
+#endif
+}
+
+/**
+ * spice_usb_device_manager_restore_automounting:
+ * @manager: the #SpiceUsbDeviceManager manager
+ *
+ * Restores automounting of newly plugged in devices by the client OS, to its
+ * original state. If it was disabled already before calling
+ * spice_usb_device_manager_disable_automounting() this is a no-op.
+ *
+ * If spice_usb_device_manager_disable_automounting() has been called multiple
+ * times, this function will not restore automounting until it has been called
+ * the same amount of times.
+ */
+void spice_usb_device_manager_restore_automounting(SpiceUsbDeviceManager *self)
+{
+#ifdef USE_USBREDIR
+ SpiceUsbDeviceManagerPrivate *priv = self->priv;
+
+ g_return_if_fail(priv->disable_automount > 0);
+
+ priv->disable_automount--;
+ if (priv->disable_automount)
+ return;
+
+ /*
+ * Re-enable automount from a timer, to avoid unnecessary ping-ponging
+ * automount when switching between the windows of a multi monitor vm.
+ */
+ if (priv->update_automount_id)
+ g_source_remove(priv->update_automount_id);
+ priv->update_automount_id =
+ g_timeout_add(50, spice_usb_device_manager_update_automount, self);
+#endif
+}
diff --git a/gtk/usb-device-manager.h b/gtk/usb-device-manager.h
index df138ee..b01fe98 100644
--- a/gtk/usb-device-manager.h
+++ b/gtk/usb-device-manager.h
@@ -114,6 +114,11 @@ spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self,
SpiceUsbDevice *device,
GError **err);
+void spice_usb_device_manager_disable_automounting(
+ SpiceUsbDeviceManager *manager);
+void spice_usb_device_manager_restore_automounting(
+ SpiceUsbDeviceManager *manager);
+
G_END_DECLS
#endif /* __SPICE_USB_DEVICE_MANAGER_H__ */
--
1.7.10.2
_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/spice-devel
/* Do coldplug (detection of already connected devices) */ int cnt = 0; cnt = libusb_get_device_list(priv->context, &priv->coldplug_list); if(cnt > 0) { size_t i = 0; struct libusb_device *dev = NULL; while((dev = priv->coldplug_list[i++]) != NULL) { gchar *desc = spice_usb_device_get_description((SpiceUsbDevice *)dev, NULL); g_print(" desc %s \n", desc); } } list = g_udev_client_query_by_subsystem(priv->udev, "usb"); for (it = g_list_first(list); it; it = g_list_next(it)) { spice_usb_device_manager_add_dev(self, it->data); g_print(" name %s \n", g_udev_device_get_name(it->data)); g_object_unref(it->data); } g_list_free(list); libusb_free_device_list(priv->coldplug_list, 1); priv->coldplug_list = NULL;
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel