mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-gtk
synced 2026-02-03 20:30:35 +00:00
Windows mingw: usb: Dynamically install a libusb driver for USB devices
- Added win-usb-driver-install.[ch] - Added win-usb-clerk.h Operation (on Windows, spice-gtk point of view): - After some sanity checks, just before redir'ing a USB device a libusb driver needs to be installed (before libusb can open the device) - A connection (NamedPipe) is established with usb-clerk, a libusb driver installation service, and a request for driver installation is sent. - Installation status is asynchronously read from the pipe, and spice_usb_drv_install_finished() is called. - Upon a successful intallation, usbredir continues. Linux operation is not changed.
This commit is contained in:
parent
5525ce9734
commit
714def3df0
@ -316,6 +316,9 @@ endif
|
||||
WIN_USB_FILES= \
|
||||
win-usb-dev.h \
|
||||
win-usb-dev.c \
|
||||
win-usb-clerk.h \
|
||||
win-usb-driver-install.h \
|
||||
win-usb-driver-install.c \
|
||||
$(NULL)
|
||||
|
||||
if OS_WIN32
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <gudev/gudev.h>
|
||||
#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"
|
||||
#endif
|
||||
@ -144,6 +145,13 @@ static libusb_device *
|
||||
spice_usb_device_manager_device_to_libdev(SpiceUsbDeviceManager *self,
|
||||
SpiceUsbDevice *device);
|
||||
|
||||
static void
|
||||
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
|
||||
SpiceUsbDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device,
|
||||
(GBoxedCopyFunc)spice_usb_device_ref,
|
||||
(GBoxedFreeFunc)spice_usb_device_unref)
|
||||
@ -154,6 +162,12 @@ G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device, g_object_ref, g_object_unr
|
||||
|
||||
static void spice_usb_device_manager_initable_iface_init(GInitableIface *iface);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
static void spice_usb_device_manager_drv_install_cb(GObject *gobject,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data);
|
||||
#endif
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE(SpiceUsbDeviceManager, spice_usb_device_manager, G_TYPE_OBJECT,
|
||||
@ -723,6 +737,87 @@ static void spice_usb_device_manager_channel_connect_cb(
|
||||
g_object_unref(result);
|
||||
}
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
typedef struct _UsbInstallCbInfo {
|
||||
SpiceUsbDeviceManager *manager;
|
||||
SpiceUsbDevice *device;
|
||||
SpiceWinUsbDriver *installer;
|
||||
GCancellable *cancellable;
|
||||
GAsyncReadyCallback callback;
|
||||
gpointer user_data;
|
||||
} UsbInstallCbInfo;
|
||||
|
||||
/**
|
||||
* spice_usb_device_manager_drv_install_cb:
|
||||
* @gobject: #SpiceWinUsbDriver in charge of installing the driver
|
||||
* @res: #GAsyncResult of async win usb driver installation
|
||||
* @user_data: #SpiceUsbDeviceManager requested the installation
|
||||
*
|
||||
* Called when an Windows libusb driver installation completed.
|
||||
*
|
||||
* If the driver installation was successful, continue with USB
|
||||
* device redirection
|
||||
*
|
||||
* Always call _spice_usb_device_manager_connect_device_async.
|
||||
* When installation fails, libusb_open fails too, but cleanup would be better.
|
||||
*/
|
||||
static void spice_usb_device_manager_drv_install_cb(GObject *gobject,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
SpiceUsbDeviceManager *self;
|
||||
SpiceWinUsbDriver *installer;
|
||||
gint status;
|
||||
GError *err = NULL;
|
||||
SpiceUsbDevice *device;
|
||||
UsbInstallCbInfo *cbinfo;
|
||||
GCancellable *cancellable;
|
||||
GAsyncReadyCallback callback;
|
||||
|
||||
SPICE_DEBUG("Win USB driver Installation finished");
|
||||
|
||||
g_return_if_fail(user_data != NULL);
|
||||
|
||||
cbinfo = user_data;
|
||||
self = cbinfo->manager;
|
||||
device = cbinfo->device;
|
||||
installer = cbinfo->installer;
|
||||
cancellable = cbinfo->cancellable;
|
||||
callback = cbinfo->callback;
|
||||
user_data = cbinfo->user_data;
|
||||
|
||||
g_free(cbinfo);
|
||||
|
||||
g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
|
||||
g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(installer));
|
||||
g_return_if_fail(device!= NULL);
|
||||
|
||||
status = spice_win_usb_driver_install_finish(installer, res, &err);
|
||||
|
||||
g_object_unref(installer);
|
||||
spice_usb_device_unref(device);
|
||||
|
||||
if (err) {
|
||||
g_warning("win usb driver installation failed -- %s",
|
||||
err->message);
|
||||
g_error_free(err);
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
g_warning("failed to install win usb driver (status=0)");
|
||||
}
|
||||
|
||||
/* device is already ref'ed */
|
||||
_spice_usb_device_manager_connect_device_async(self,
|
||||
device,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* private api */
|
||||
|
||||
@ -903,11 +998,12 @@ gboolean spice_usb_device_manager_is_device_connected(SpiceUsbDeviceManager *sel
|
||||
* @callback: a #GAsyncReadyCallback to call when the request is satisfied
|
||||
* @user_data: data to pass to callback
|
||||
*/
|
||||
void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
|
||||
SpiceUsbDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
static void
|
||||
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
|
||||
SpiceUsbDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GSimpleAsyncResult *result;
|
||||
|
||||
@ -958,6 +1054,38 @@ done:
|
||||
g_object_unref(result);
|
||||
}
|
||||
|
||||
|
||||
void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
|
||||
SpiceUsbDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
||||
#if defined(USE_USBREDIR) && defined(G_OS_WIN32)
|
||||
SpiceWinUsbDriver *installer;
|
||||
UsbInstallCbInfo *cbinfo;
|
||||
|
||||
installer = spice_win_usb_driver_new();
|
||||
cbinfo = g_new0(UsbInstallCbInfo, 1);
|
||||
cbinfo->manager = self;
|
||||
cbinfo->device = spice_usb_device_ref(device);
|
||||
cbinfo->installer = installer;
|
||||
cbinfo->cancellable = cancellable;
|
||||
cbinfo->callback = callback;
|
||||
cbinfo->user_data = user_data;
|
||||
spice_win_usb_driver_install(installer, device, cancellable,
|
||||
spice_usb_device_manager_drv_install_cb,
|
||||
cbinfo);
|
||||
#else
|
||||
_spice_usb_device_manager_connect_device_async(self,
|
||||
device,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean spice_usb_device_manager_connect_device_finish(
|
||||
SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err)
|
||||
{
|
||||
|
||||
35
gtk/win-usb-clerk.h
Normal file
35
gtk/win-usb-clerk.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef _H_USBCLERK
|
||||
#define _H_USBCLERK
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define USB_CLERK_PIPE_NAME TEXT("\\\\.\\pipe\\usbclerkpipe")
|
||||
#define USB_CLERK_MAGIC 0xDADA
|
||||
#define USB_CLERK_VERSION 0x0002
|
||||
|
||||
typedef struct USBClerkHeader {
|
||||
UINT16 magic;
|
||||
UINT16 version;
|
||||
UINT16 type;
|
||||
UINT16 size;
|
||||
} USBClerkHeader;
|
||||
|
||||
enum {
|
||||
USB_CLERK_DRIVER_INSTALL = 1,
|
||||
USB_CLERK_DRIVER_REMOVE,
|
||||
USB_CLERK_REPLY,
|
||||
USB_CLERK_END_MESSAGE,
|
||||
};
|
||||
|
||||
typedef struct USBClerkDriverOp {
|
||||
USBClerkHeader hdr;
|
||||
UINT16 vid;
|
||||
UINT16 pid;
|
||||
} USBClerkDriverOp;
|
||||
|
||||
typedef struct USBClerkReply {
|
||||
USBClerkHeader hdr;
|
||||
UINT32 status;
|
||||
} USBClerkReply;
|
||||
|
||||
#endif
|
||||
357
gtk/win-usb-driver-install.c
Normal file
357
gtk/win-usb-driver-install.c
Normal file
@ -0,0 +1,357 @@
|
||||
/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
/*
|
||||
Copyright (C) 2011 Red Hat, Inc.
|
||||
|
||||
Red Hat Authors:
|
||||
Uri Lublin <uril@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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some notes:
|
||||
* Each installer (instance) opens a named-pipe to talk with win-usb-clerk.
|
||||
* Each installer (instance) requests driver installation for a single device.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gwin32inputstream.h>
|
||||
#include <gio/gwin32outputstream.h>
|
||||
#include "spice-util.h"
|
||||
#include "win-usb-clerk.h"
|
||||
#include "win-usb-driver-install.h"
|
||||
#include "usb-device-manager-priv.h"
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* gobject glue */
|
||||
|
||||
#define SPICE_WIN_USB_DRIVER_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_WIN_USB_DRIVER, SpiceWinUsbDriverPrivate))
|
||||
|
||||
struct _SpiceWinUsbDriverPrivate {
|
||||
USBClerkReply reply;
|
||||
GSimpleAsyncResult *result;
|
||||
GCancellable *cancellable;
|
||||
HANDLE handle;
|
||||
SpiceUsbDevice *device;
|
||||
};
|
||||
|
||||
|
||||
|
||||
G_DEFINE_TYPE(SpiceWinUsbDriver, spice_win_usb_driver, G_TYPE_OBJECT);
|
||||
|
||||
static void spice_win_usb_driver_init(SpiceWinUsbDriver *self)
|
||||
{
|
||||
self->priv = SPICE_WIN_USB_DRIVER_GET_PRIVATE(self);
|
||||
}
|
||||
|
||||
static void spice_win_usb_driver_close(SpiceWinUsbDriver *self)
|
||||
{
|
||||
if (self->priv->handle) {
|
||||
CloseHandle(self->priv->handle);
|
||||
self->priv->handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void spice_win_usb_driver_finalize(GObject *gobject)
|
||||
{
|
||||
SpiceWinUsbDriver *self = SPICE_WIN_USB_DRIVER(gobject);
|
||||
SpiceWinUsbDriverPrivate *priv = self->priv;
|
||||
|
||||
spice_win_usb_driver_close(self);
|
||||
g_clear_object(&priv->result);
|
||||
}
|
||||
|
||||
static void spice_win_usb_driver_class_init(SpiceWinUsbDriverClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = spice_win_usb_driver_finalize;
|
||||
|
||||
g_type_class_add_private(klass, sizeof(SpiceWinUsbDriverPrivate));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* callbacks */
|
||||
|
||||
void win_usb_driver_handle_reply_cb(GObject *gobject,
|
||||
GAsyncResult *read_res,
|
||||
gpointer user_data)
|
||||
{
|
||||
SpiceWinUsbDriver *self;
|
||||
SpiceWinUsbDriverPrivate *priv;
|
||||
|
||||
GInputStream *istream;
|
||||
GError *err = NULL;
|
||||
gssize bytes;
|
||||
|
||||
g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(user_data));
|
||||
self = SPICE_WIN_USB_DRIVER(user_data);
|
||||
priv = self->priv;
|
||||
istream = G_INPUT_STREAM(gobject);
|
||||
|
||||
bytes = g_input_stream_read_finish(istream, read_res, &err);
|
||||
|
||||
SPICE_DEBUG("Finished reading reply-msg from usbclerk: bytes=%ld "
|
||||
"err_exist?=%d", (long)bytes, err!=NULL);
|
||||
|
||||
g_warn_if_fail(g_input_stream_close(istream, NULL, NULL));
|
||||
g_clear_object(&istream);
|
||||
spice_win_usb_driver_close(self);
|
||||
|
||||
if (err) {
|
||||
g_warning("failed to read reply from usbclerk (%s)", err->message);
|
||||
g_simple_async_result_take_error(priv->result, err);
|
||||
goto failed_reply;
|
||||
}
|
||||
|
||||
if (bytes == 0) {
|
||||
g_warning("unexpected EOF from usbclerk");
|
||||
g_simple_async_result_set_error(priv->result,
|
||||
SPICE_WIN_USB_DRIVER_ERROR,
|
||||
SPICE_WIN_USB_DRIVER_ERROR_FAILED,
|
||||
"unexpected EOF from usbclerk");
|
||||
goto failed_reply;
|
||||
}
|
||||
|
||||
if (bytes != sizeof(priv->reply)) {
|
||||
g_warning("usbclerk size mismatch: read %d bytes, expected %d (header %d, size in header %d)",
|
||||
bytes, sizeof(priv->reply), sizeof(priv->reply.hdr), priv->reply.hdr.size);
|
||||
/* For now just warn, do not fail */
|
||||
}
|
||||
|
||||
if (priv->reply.hdr.magic != USB_CLERK_MAGIC) {
|
||||
g_warning("usbclerk magic mismatch: mine=0x%04x server=0x%04x",
|
||||
USB_CLERK_MAGIC, priv->reply.hdr.magic);
|
||||
g_simple_async_result_set_error(priv->result,
|
||||
SPICE_WIN_USB_DRIVER_ERROR,
|
||||
SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
|
||||
"usbclerk magic mismatch");
|
||||
goto failed_reply;
|
||||
}
|
||||
|
||||
if (priv->reply.hdr.version != USB_CLERK_VERSION) {
|
||||
g_warning("usbclerk version mismatch: mine=0x%04x server=0x%04x",
|
||||
USB_CLERK_VERSION, priv->reply.hdr.version);
|
||||
/* For now just warn, do not fail */
|
||||
}
|
||||
|
||||
if (priv->reply.hdr.type != USB_CLERK_REPLY) {
|
||||
g_warning("usbclerk message with unexpected type %d",
|
||||
priv->reply.hdr.type);
|
||||
g_simple_async_result_set_error(priv->result,
|
||||
SPICE_WIN_USB_DRIVER_ERROR,
|
||||
SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
|
||||
"usbclerk message with unexpected type");
|
||||
goto failed_reply;
|
||||
}
|
||||
|
||||
if (priv->reply.hdr.size != bytes) {
|
||||
g_warning("usbclerk message size mismatch: read %d bytes hdr.size=%d",
|
||||
bytes, priv->reply.hdr.size);
|
||||
g_simple_async_result_set_error(priv->result,
|
||||
SPICE_WIN_USB_DRIVER_ERROR,
|
||||
SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
|
||||
"usbclerk message with unexpected size");
|
||||
goto failed_reply;
|
||||
}
|
||||
|
||||
failed_reply:
|
||||
g_simple_async_result_complete_in_idle(priv->result);
|
||||
g_clear_object(&priv->result);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* helper functions */
|
||||
|
||||
static
|
||||
gboolean spice_win_usb_driver_send_request(SpiceWinUsbDriver *self, guint16 op,
|
||||
guint16 vid, guint16 pid, GError **err)
|
||||
{
|
||||
USBClerkDriverOp req = {0,};
|
||||
GOutputStream *ostream;
|
||||
SpiceWinUsbDriverPrivate *priv;
|
||||
gsize bytes;
|
||||
gboolean ret;
|
||||
|
||||
SPICE_DEBUG("sending a request to usbclerk service (op=%d vid=0x%04x pid=0x%04x",
|
||||
op, vid, pid);
|
||||
|
||||
g_return_val_if_fail(SPICE_IS_WIN_USB_DRIVER(self), FALSE);
|
||||
priv = self->priv;
|
||||
|
||||
req.hdr.magic = USB_CLERK_MAGIC;
|
||||
req.hdr.version = USB_CLERK_VERSION;
|
||||
req.hdr.type = op;
|
||||
req.hdr.size = sizeof(req);
|
||||
req.vid = vid;
|
||||
req.pid = pid;
|
||||
|
||||
ostream = g_win32_output_stream_new(priv->handle, FALSE);
|
||||
|
||||
ret = g_output_stream_write_all(ostream, &req, sizeof(req), &bytes, NULL, err);
|
||||
g_warn_if_fail(g_output_stream_close(ostream, NULL, NULL));
|
||||
g_object_unref(ostream);
|
||||
SPICE_DEBUG("write_all request returned %d written bytes %u expecting %u",
|
||||
ret, bytes, sizeof(req));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
void spice_win_usb_driver_read_reply_async(SpiceWinUsbDriver *self)
|
||||
{
|
||||
SpiceWinUsbDriverPrivate *priv;
|
||||
GInputStream *istream;
|
||||
|
||||
g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(self));
|
||||
priv = self->priv;
|
||||
|
||||
SPICE_DEBUG("waiting for a reply from usbclerk");
|
||||
|
||||
istream = g_win32_input_stream_new(priv->handle, FALSE);
|
||||
|
||||
g_input_stream_read_async(istream, &priv->reply, sizeof(priv->reply),
|
||||
G_PRIORITY_DEFAULT, priv->cancellable,
|
||||
win_usb_driver_handle_reply_cb, self);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* private api */
|
||||
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
SpiceWinUsbDriver *spice_win_usb_driver_new(void)
|
||||
{
|
||||
GObject *obj;
|
||||
|
||||
obj = g_object_new(SPICE_TYPE_WIN_USB_DRIVER, NULL);
|
||||
|
||||
return SPICE_WIN_USB_DRIVER(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* spice_win_usb_driver_install:
|
||||
* Start libusb driver installation for @device
|
||||
*
|
||||
* A new NamedPipe is created for each request.
|
||||
*
|
||||
* Returns: TRUE if a request was sent to usbclerk
|
||||
* FALSE upon failure to send a request.
|
||||
*/
|
||||
G_GNUC_INTERNAL
|
||||
void spice_win_usb_driver_install(SpiceWinUsbDriver *self,
|
||||
SpiceUsbDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
guint16 vid, pid;
|
||||
GError *err = NULL;
|
||||
GSimpleAsyncResult *result;
|
||||
SpiceWinUsbDriverPrivate *priv;
|
||||
|
||||
SPICE_DEBUG("Win usb driver installation started");
|
||||
|
||||
g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(self));
|
||||
g_return_if_fail(device != NULL);
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
g_return_if_fail(priv->result == NULL);
|
||||
|
||||
result = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
|
||||
spice_win_usb_driver_install);
|
||||
|
||||
vid = spice_usb_device_get_vid(device);
|
||||
pid = spice_usb_device_get_pid(device);
|
||||
|
||||
SPICE_DEBUG("win-usb-driver-install: connecting to usbclerk named pipe");
|
||||
priv->handle = CreateFile(USB_CLERK_PIPE_NAME,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
if (priv->handle == INVALID_HANDLE_VALUE) {
|
||||
DWORD errval = GetLastError();
|
||||
gchar *errstr = g_win32_error_message(errval);
|
||||
g_warning("failed to create a named pipe to usbclerk (%ld) %s",
|
||||
errval,errstr);
|
||||
g_simple_async_result_set_error(result,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to create named pipe (%ld) %s", errval, errstr);
|
||||
goto failed_request;
|
||||
}
|
||||
|
||||
if (!spice_win_usb_driver_send_request(self, USB_CLERK_DRIVER_INSTALL,
|
||||
vid, pid, &err)) {
|
||||
g_warning("failed to send a request to usbclerk %s", err->message);
|
||||
g_simple_async_result_take_error(result, err);
|
||||
goto failed_request;
|
||||
}
|
||||
|
||||
/* set up for async read */
|
||||
priv->result = result;
|
||||
priv->device = device;
|
||||
priv->cancellable = cancellable;
|
||||
|
||||
spice_win_usb_driver_read_reply_async(self);
|
||||
|
||||
return;
|
||||
|
||||
failed_request:
|
||||
spice_win_usb_driver_close(self);
|
||||
g_simple_async_result_complete_in_idle(result);
|
||||
g_clear_object(&result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns: currently returns 0 (failure) and 1 (success)
|
||||
* possibly later we'll add error-codes
|
||||
*/
|
||||
G_GNUC_INTERNAL
|
||||
gint spice_win_usb_driver_install_finish(SpiceWinUsbDriver *self,
|
||||
GAsyncResult *res, GError **err)
|
||||
{
|
||||
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(res);
|
||||
|
||||
g_return_val_if_fail(SPICE_IS_WIN_USB_DRIVER(self), 0);
|
||||
g_return_val_if_fail(g_simple_async_result_is_valid(res, G_OBJECT(self),
|
||||
spice_win_usb_driver_install),
|
||||
FALSE);
|
||||
if (g_simple_async_result_propagate_error(result, err))
|
||||
return 0;
|
||||
|
||||
return self->priv->reply.status;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
SpiceUsbDevice *spice_win_usb_driver_get_device(SpiceWinUsbDriver *self)
|
||||
{
|
||||
g_return_val_if_fail(SPICE_IS_WIN_USB_DRIVER(self), 0);
|
||||
|
||||
return self->priv->device;
|
||||
}
|
||||
|
||||
GQuark spice_win_usb_driver_error_quark(void)
|
||||
{
|
||||
return g_quark_from_static_string("spice-win-usb-driver-error-quark");
|
||||
}
|
||||
98
gtk/win-usb-driver-install.h
Normal file
98
gtk/win-usb-driver-install.h
Normal file
@ -0,0 +1,98 @@
|
||||
/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
/*
|
||||
Copyright (C) 2011 Red Hat, Inc.
|
||||
|
||||
Red Hat Authors:
|
||||
Uri Lublin <uril@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/>.
|
||||
*/
|
||||
|
||||
#ifndef SPICE_WIN_USB_DRIVER_H
|
||||
#define SPICE_WIN_USB_DRIVER_H
|
||||
|
||||
#include "usb-device-manager.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GQuark win_usb_driver_error_quark(void);
|
||||
|
||||
|
||||
#define SPICE_TYPE_WIN_USB_DRIVER (spice_win_usb_driver_get_type ())
|
||||
#define SPICE_WIN_USB_DRIVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
SPICE_TYPE_WIN_USB_DRIVER, SpiceWinUsbDriver))
|
||||
#define SPICE_IS_WIN_USB_DRIVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
SPICE_TYPE_WIN_USB_DRIVER))
|
||||
#define SPICE_WIN_USB_DRIVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
SPICE_TYPE_WIN_USB_DRIVER, SpiceWinUsbDriverClass))
|
||||
#define SPICE_IS_WIN_USB_DRIVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
|
||||
SPICE_TYPE_WIN_USB_DRIVER))
|
||||
#define SPICE_WIN_USB_DRIVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
|
||||
SPICE_TYPE_WIN_USB_DRIVER, SpiceWinUsbDriverClass))
|
||||
|
||||
typedef struct _SpiceWinUsbDriver SpiceWinUsbDriver;
|
||||
typedef struct _SpiceWinUsbDriverClass SpiceWinUsbDriverClass;
|
||||
typedef struct _SpiceWinUsbDriverPrivate SpiceWinUsbDriverPrivate;
|
||||
|
||||
struct _SpiceWinUsbDriver
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
/*< private >*/
|
||||
SpiceWinUsbDriverPrivate *priv;
|
||||
/* Do not add fields to this struct */
|
||||
};
|
||||
|
||||
struct _SpiceWinUsbDriverClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType spice_win_usb_driver_get_type(void);
|
||||
|
||||
SpiceWinUsbDriver *spice_win_usb_driver_new(void);
|
||||
|
||||
|
||||
void spice_win_usb_driver_install(SpiceWinUsbDriver *self,
|
||||
SpiceUsbDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gint spice_win_usb_driver_install_finish(SpiceWinUsbDriver *self,
|
||||
GAsyncResult *res, GError **err);
|
||||
|
||||
|
||||
SpiceUsbDevice *spice_win_usb_driver_get_device(SpiceWinUsbDriver *self);
|
||||
|
||||
#define SPICE_WIN_USB_DRIVER_ERROR spice_win_usb_driver_error_quark()
|
||||
|
||||
/**
|
||||
* SpiceWinUsbDriverError:
|
||||
* @SPICE_WIN_USB_DRIVER_ERROR_FAILED: generic error code
|
||||
* @SPICE_WIN_USB_DRIVER_ERROR_MESSAGE: bad message read from clerk
|
||||
*
|
||||
* Error codes returned by spice-client API.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SPICE_WIN_USB_DRIVER_ERROR_FAILED,
|
||||
SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
|
||||
} SpiceWinUsbDriverError;
|
||||
|
||||
GQuark spice_win_usb_driver_error_quark(void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* SPICE_WIN_USB_DRIVER_H */
|
||||
Loading…
Reference in New Issue
Block a user