Add "USB device reset" option to File menu

Adds a "USB device reset" option to the File menu. When selected, "USB
device reset" will disconnect and reconnect all currently connected USB
devices.

Signed-off-by: Shawn M. Chapla <schapla@codeweavers.com>
This commit is contained in:
Shawn M. Chapla 2020-09-23 22:09:38 -04:00 committed by Shawn M. Chapla
parent 1573a790da
commit 1608dabd9f
7 changed files with 140 additions and 3 deletions

View File

@ -54,6 +54,17 @@
<signal name="activate" handler="virt_viewer_window_menu_file_usb_device_selection" swapped="no"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu-file-usb-device-reset">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="accel_path">&lt;virt-viewer&gt;/file/usb-device-reset</property>
<property name="label" translatable="yes">USB device _reset</property>
<property name="use_underline">True</property>
<signal name="activate" handler="virt_viewer_window_menu_file_usb_device_reset" swapped="no"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu-file-smartcard-insert">
<property name="can_focus">False</property>

View File

@ -998,6 +998,20 @@ virt_viewer_app_set_usb_options_sensitive(VirtViewerApp *self, gboolean sensitiv
GINT_TO_POINTER(sensitive));
}
static void set_usb_reset_sensitive(gpointer value,
gpointer user_data)
{
virt_viewer_window_set_usb_reset_sensitive(VIRT_VIEWER_WINDOW(value),
GPOINTER_TO_INT(user_data));
}
static void
virt_viewer_app_set_usb_reset_sensitive(VirtViewerApp *self, gboolean sensitive)
{
g_list_foreach(self->priv->windows, set_usb_reset_sensitive,
GINT_TO_POINTER(sensitive));
}
static void
set_menus_sensitive(gpointer value, gpointer user_data)
{
@ -1048,6 +1062,7 @@ virt_viewer_app_window_new(VirtViewerApp *self, gint nth)
{
VirtViewerWindow* window;
GtkWindow *w;
gboolean has_usbredir;
window = virt_viewer_app_get_nth_window(self, nth);
if (window)
@ -1061,7 +1076,10 @@ virt_viewer_app_window_new(VirtViewerApp *self, gint nth)
self->priv->windows = g_list_append(self->priv->windows, window);
virt_viewer_app_set_window_subtitle(self, window, nth);
virt_viewer_app_update_menu_displays(self);
virt_viewer_window_set_usb_options_sensitive(window, virt_viewer_app_has_usbredir(self));
has_usbredir = virt_viewer_app_has_usbredir(self);
virt_viewer_window_set_usb_options_sensitive(window, has_usbredir);
virt_viewer_window_set_usb_reset_sensitive(window, has_usbredir);
w = virt_viewer_window_get_window(window);
g_object_set_data(G_OBJECT(w), "virt-viewer-window", window);
@ -1249,8 +1267,10 @@ virt_viewer_app_has_usbredir_updated(VirtViewerSession *session,
GParamSpec *pspec G_GNUC_UNUSED,
VirtViewerApp *self)
{
virt_viewer_app_set_usb_options_sensitive(self,
virt_viewer_session_get_has_usbredir(session));
gboolean has_usbredir = virt_viewer_session_get_has_usbredir(session);
virt_viewer_app_set_usb_options_sensitive(self, has_usbredir);
virt_viewer_app_set_usb_reset_sensitive(self, has_usbredir);
}
static void notify_software_reader_cb(GObject *gobject G_GNUC_UNUSED,
@ -1691,6 +1711,7 @@ virt_viewer_app_disconnected(VirtViewerSession *session G_GNUC_UNUSED, const gch
gtk_widget_destroy(dialog);
}
virt_viewer_app_set_usb_options_sensitive(self, FALSE);
virt_viewer_app_set_usb_reset_sensitive(self, FALSE);
virt_viewer_app_deactivate(self, connect_error);
}

View File

@ -83,6 +83,7 @@ static void virt_viewer_session_spice_channel_destroyed(SpiceSession *s,
VirtViewerSession *session);
static void virt_viewer_session_spice_session_disconnected(SpiceSession *s,
VirtViewerSessionSpice *session);
static void virt_viewer_session_spice_usb_device_reset(VirtViewerSession *session);
static void virt_viewer_session_spice_smartcard_insert(VirtViewerSession *session);
static void virt_viewer_session_spice_smartcard_remove(VirtViewerSession *session);
static gboolean virt_viewer_session_spice_fullscreen_auto_conf(VirtViewerSessionSpice *self);
@ -262,6 +263,7 @@ virt_viewer_session_spice_class_init(VirtViewerSessionSpiceClass *klass)
dclass->open_uri = virt_viewer_session_spice_open_uri;
dclass->channel_open_fd = virt_viewer_session_spice_channel_open_fd;
dclass->usb_device_selection = virt_viewer_session_spice_usb_device_selection;
dclass->usb_device_reset = virt_viewer_session_spice_usb_device_reset;
dclass->smartcard_insert = virt_viewer_session_spice_smartcard_insert;
dclass->smartcard_remove = virt_viewer_session_spice_smartcard_remove;
dclass->mime_type = virt_viewer_session_spice_mime_type;
@ -1412,6 +1414,70 @@ virt_viewer_session_spice_get_main_channel(VirtViewerSessionSpice *self)
return self->priv->main_channel;
}
static void
usb_device_reset_connect_cb(GObject *gobject, GAsyncResult *res, gpointer user_data)
{
SpiceUsbDeviceManager *usb_manager = SPICE_USB_DEVICE_MANAGER(gobject);
SpiceUsbDevice *device = (SpiceUsbDevice *)user_data;
GError *err = NULL;
spice_usb_device_manager_connect_device_finish(usb_manager, res, &err);
if (err) {
g_critical("USB device reset failed; could not connect %p", device);
return;
}
g_debug("USB device reset success; did reset %p", device);
}
static void
usb_device_reset_disconnect_cb(GObject *gobject, GAsyncResult *res, gpointer user_data)
{
SpiceUsbDeviceManager *usb_manager = SPICE_USB_DEVICE_MANAGER(gobject);
SpiceUsbDevice *device = (SpiceUsbDevice *)user_data;
GError *err = NULL;
spice_usb_device_manager_disconnect_device_finish(usb_manager, res, &err);
if (err) {
g_critical("USB device reset failed; could not disconnect %p", device);
return;
}
spice_usb_device_manager_connect_device_async(usb_manager, device, NULL,
usb_device_reset_connect_cb, device);
}
static void
virt_viewer_session_spice_usb_device_reset(VirtViewerSession *session)
{
VirtViewerSessionSpice *self = VIRT_VIEWER_SESSION_SPICE(session);
SpiceUsbDeviceManager *usb_manager;
g_return_if_fail(self != NULL);
usb_manager = spice_usb_device_manager_get(self->priv->session, NULL);
if (usb_manager) {
int i;
GPtrArray *devices = spice_usb_device_manager_get_devices(usb_manager);
if (devices == NULL) {
g_warning("Couldn't get USB device list");
return;
}
for (i = 0; i < devices->len; ++i) {
SpiceUsbDevice *device = g_ptr_array_index(devices, i);
if (spice_usb_device_manager_is_device_connected(usb_manager, device)) {
g_debug("Attempting to reset USB device connection: %p", device);
spice_usb_device_manager_disconnect_device_async(usb_manager, device, NULL,
usb_device_reset_disconnect_cb, device);
}
}
g_ptr_array_unref(devices);
}
}
static void
virt_viewer_session_spice_smartcard_insert(VirtViewerSession *session G_GNUC_UNUSED)
{

View File

@ -613,6 +613,21 @@ void virt_viewer_session_usb_device_selection(VirtViewerSession *self,
klass->usb_device_selection(self, parent);
}
void virt_viewer_session_usb_device_reset(VirtViewerSession *self)
{
VirtViewerSessionClass *klass;
g_return_if_fail(VIRT_VIEWER_IS_SESSION(self));
klass = VIRT_VIEWER_SESSION_GET_CLASS(self);
if (klass->usb_device_reset == NULL) {
g_debug("No session usbredir support");
return;
}
klass->usb_device_reset(self);
}
void virt_viewer_session_smartcard_insert(VirtViewerSession *self)
{
VirtViewerSessionClass *klass;

View File

@ -79,6 +79,7 @@ struct _VirtViewerSessionClass {
gboolean (* open_uri) (VirtViewerSession* session, const gchar *uri, GError **error);
gboolean (* channel_open_fd) (VirtViewerSession* session, VirtViewerSessionChannel *channel, int fd);
void (* usb_device_selection) (VirtViewerSession* session, GtkWindow *parent);
void (* usb_device_reset) (VirtViewerSession* session);
void (* smartcard_insert) (VirtViewerSession* session);
void (* smartcard_remove) (VirtViewerSession* session);
const gchar* (* mime_type) (VirtViewerSession* session);
@ -116,6 +117,7 @@ void virt_viewer_session_set_has_usbredir(VirtViewerSession* session, gboolean h
gboolean virt_viewer_session_get_has_usbredir(VirtViewerSession *self);
void virt_viewer_session_usb_device_selection(VirtViewerSession *self, GtkWindow *parent);
void virt_viewer_session_usb_device_reset(VirtViewerSession *self);
void virt_viewer_session_smartcard_insert(VirtViewerSession *self);
void virt_viewer_session_smartcard_remove(VirtViewerSession *self);
VirtViewerApp* virt_viewer_session_get_app(VirtViewerSession *self);

View File

@ -64,6 +64,7 @@ void virt_viewer_window_menu_view_fullscreen(GtkWidget *menu, VirtViewerWindow *
void virt_viewer_window_menu_send(GtkWidget *menu, VirtViewerWindow *self);
void virt_viewer_window_menu_file_screenshot(GtkWidget *menu, VirtViewerWindow *self);
void virt_viewer_window_menu_file_usb_device_selection(GtkWidget *menu, VirtViewerWindow *self);
void virt_viewer_window_menu_file_usb_device_reset(GtkWidget *menu, VirtViewerWindow *self);
void virt_viewer_window_menu_file_smartcard_insert(GtkWidget *menu, VirtViewerWindow *self);
void virt_viewer_window_menu_file_smartcard_remove(GtkWidget *menu, VirtViewerWindow *self);
void virt_viewer_window_menu_view_release_cursor(GtkWidget *menu, VirtViewerWindow *self);
@ -1130,6 +1131,13 @@ virt_viewer_window_menu_file_usb_device_selection(GtkWidget *menu G_GNUC_UNUSED,
GTK_WINDOW(self->priv->window));
}
G_MODULE_EXPORT void
virt_viewer_window_menu_file_usb_device_reset(GtkWidget *menu G_GNUC_UNUSED,
VirtViewerWindow *self)
{
virt_viewer_session_usb_device_reset(virt_viewer_app_get_session(self->priv->app));
}
G_MODULE_EXPORT void
virt_viewer_window_menu_file_smartcard_insert(GtkWidget *menu G_GNUC_UNUSED,
VirtViewerWindow *self)
@ -1469,6 +1477,19 @@ virt_viewer_window_set_usb_options_sensitive(VirtViewerWindow *self, gboolean se
gtk_widget_set_visible(priv->toolbar_usb_device_selection, sensitive);
}
void
virt_viewer_window_set_usb_reset_sensitive(VirtViewerWindow *self, gboolean sensitive)
{
VirtViewerWindowPrivate *priv;
GtkWidget *menu;
g_return_if_fail(VIRT_VIEWER_IS_WINDOW(self));
priv = self->priv;
menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-file-usb-device-reset"));
gtk_widget_set_sensitive(menu, sensitive);
}
void
virt_viewer_window_set_menus_sensitive(VirtViewerWindow *self, gboolean sensitive)
{

View File

@ -70,6 +70,7 @@ void virt_viewer_window_set_display(VirtViewerWindow *self, VirtViewerDisplay *d
VirtViewerDisplay* virt_viewer_window_get_display(VirtViewerWindow *self);
void virt_viewer_window_set_menu_displays_sensitive(VirtViewerWindow *self, gboolean sensitive);
void virt_viewer_window_set_usb_options_sensitive(VirtViewerWindow *self, gboolean sensitive);
void virt_viewer_window_set_usb_reset_sensitive(VirtViewerWindow *self, gboolean sensitive);
void virt_viewer_window_set_menus_sensitive(VirtViewerWindow *self, gboolean sensitive);
void virt_viewer_window_update_title(VirtViewerWindow *self);
void virt_viewer_window_show(VirtViewerWindow *self);