Thanks for the review.
Great comments which surely help a GObject/Gtk-dummy like myself ;)
See below.

Marc-André Lureau wrote:
Hi

On Mon, May 7, 2012 at 3:15 PM, Uri Lublin <u...@redhat.com> wrote:
From: Arnon Gilboa <agil...@redhat.com>

With this patch usb-device-manager can work with little change
on windows too.

-add uevent signal based on WM_DEVICECHANGE
-add spice_usb_device_manager_set_window for setting winproc
  (which is needed for event registration)

You should document any added public API.
Can't we create a private/hidden window for that?
Right, will be nicer & cleaner. Will do that using Win32 API, seems ok?
+WIN_USB_HDRS =                                         \
+       win-usb-dev.h                                   \
+       $(NULL)
+

Perhaps the header doesn't need to be conditionally excluded from the
list of files.
Also if it's not in the public API, it shouldn't be in the
libspice_client_glibinclude_HEADERS.
ok
+WIN_USB_LIBS = $(GTK_LIBS)

So the spice-glib lib will depend on Gtk? hmm.. I wish we can find
something better.
Right. The hidden window will remove this  too.
@@ -566,6 +586,7 @@ glib_introspection_files =                          \
       channel-usbredir.c                              \
       smartcard-manager.c                             \
       usb-device-manager.c                            \
+       $(WIN_USB_SRCS)                                 \

Does that file need to be introspected? If it doesn't provide a public
API, I guess not.
right
+#ifdef __linux__
 #include <gudev/gudev.h>
+#elif WIN32
+#include "win-usb-dev.h"
+#endif

We generally prefer the glib defines G_OS_WIN32 and G_OS_UNIX.

In this case USE_GUDEV could also be more appropriate.
ok
+void spice_usb_device_manager_set_window(SpiceUsbDeviceManager *manager, 
GdkWindow *win)
+{
+#ifdef WIN32
+    g_udev_client_win_init(manager->priv->udev, manager, win);
+#endif
+}

Please document that API, specify when it should be called, and what
kind of window.
Is it safe to be called multiple time, with NULL argument etc.. It
needs to be annotated for introspection bindings to work correctly.
will be done
+gboolean get_usb_dev_info(libusb_device *dev, GUdevDeviceInfo *usbdev);

Why is this function not static?
sure
+static GObject *g_udev_client_constructor(GType gtype, guint n_properties,
+                                          GObjectConstructParam *properties)
+{
+    GObject *obj = G_OBJECT_CLASS(g_udev_client_parent_class)->constructor(
+        gtype, n_properties, properties);
+    return obj;
+}

This doesn't need to be overriden.
ok
+
+static void g_udev_client_init(GUdevClient *self)
+{
+    GUdevClientPrivate *priv;
+
+    self->priv = priv = G_UDEV_CLIENT_GET_PRIVATE(self);
+    priv->usb_dev_mgr = NULL;
+    priv->dev_list = NULL;
+    priv->dev_list_size = 0;
+    priv->udevice_list = NULL;
+    priv->gdk_win = NULL;

fields are already set to NULL after creation, you can get rid of this
init() override.

right
+static void g_udev_client_finalize(GObject *gobject)
+{
+    GUdevClient *self = G_UDEV_CLIENT(gobject);
+    GUdevClientPrivate *priv = self->priv;
+
+    if (priv->usb_dev_mgr || priv->gdk_win) {
+        gdk_window_remove_filter(priv->gdk_win, win_message_cb, 
priv->usb_dev_mgr);
+        g_list_free_full(priv->udevice_list, g_free);
+        libusb_free_device_list(priv->dev_list, 1);
+        libusb_exit(NULL);
+    }

This looks prone to leaks if the finalize is called in an object
intermediate state. Instead, it's recommended to check/free each
pointer individually:

if (priv->ptr)
  free_or_unref(priv->ptr)
...

It's also sometime preferable to do all of this in _dispose() and set
the pointers to NULL. This can solves some cyclic references, although
perhaps not necessary here.

What is the effect of calling libusb_exit(NULL); ? (it's already
called by spice_usb_device_manager_finalize)
ok. Will add context to init/exit. Is it right to use the context from SpiceUsbDeviceManagerPrivate ?
+
+gboolean get_usb_dev_info(libusb_device *dev, GUdevDeviceInfo *usbdev)
+{
+    if (!usbdev) {
+        return FALSE;
+    }

There is a convenient function g_return_val_if_fail(usbdev != NULL,
FALSE) for that. It will log if that condition happen too.
right
+    if (libusb_get_device_descriptor(dev, &usbdev->desc) < 0) {
+        return FALSE;
+    }

It might be worth to add some SPICE_DEBUG?
sure
+    usbdev->dev = libusb_ref_device(dev);
+    sprintf(usbdev->sclass, "%d", usbdev->desc.bDeviceClass);
+    sprintf(usbdev->sbus, "%d", libusb_get_bus_number(dev));
+    sprintf(usbdev->saddr, "%d", libusb_get_device_address(dev));
+    return TRUE;

In general snprintf() is preferred.
right
+    for (dev = (dev_change > 0 ? devs : priv->dev_list); *dev && !changed_dev; 
dev++) {
+        for (d = (dev_change > 0 ? priv->dev_list : devs); *d && *d != *dev; 
d++);

You could break inside the loop instead of having complex conditions.
ok
+        if (!*d) {
+            changed_dev = *dev;
+        }
+    }

+    if (!changed_dev) {
+        goto leave;
+    }

if dev_change != 0, shouldn't it also warn it couldn't find any device?
right
+    if (dev_change > 0) {
+        usbdev = g_new(GUdevDeviceInfo, 1);
+        get_usb_dev_info(changed_dev, usbdev);
+        udevice = g_udev_device_new(usbdev);
+        priv->udevice_list = g_list_append(priv->udevice_list, udevice);
+        SPICE_DEBUG(">>> device inserted: %04x:%04x (bus %s, device %s)\n",
+                    usbdev->desc.idVendor, usbdev->desc.idProduct, usbdev->sbus, 
usbdev->saddr);
+        g_signal_emit(self, signals[UEVENT_SIGNAL], 0, "add", udevice);
+    } else {
+        dev_found = FALSE;
+        for (GList *it = g_list_first(priv->udevice_list); it != NULL && 
!dev_found; it = g_list_next(it)) {
+            udevice = (GUdevDevice*)it->data;
+            usbdev = udevice->priv->usbdev;
+            dev_found = (usbdev->dev == changed_dev);
+        }
+        if (!dev_found) {
+            goto leave;
+        }
+        SPICE_DEBUG("<<< device removed: %04x:%04x (bus %s, device %s)\n",
+                    usbdev->desc.idVendor, usbdev->desc.idProduct, usbdev->sbus, 
usbdev->saddr);
+        g_signal_emit(self, signals[UEVENT_SIGNAL], 0, "remove", udevice);
+        priv->udevice_list = g_list_remove(priv->udevice_list, udevice);
+        g_object_unref(udevice);
+    }

+    if (priv->usb_dev_mgr || priv->gdk_win || !manager || !win) {
+        return FALSE;
+    }

g_return_val_if_fail on each condition (one line for each, so we can
separate failure for each condition if it occurs)
ok

+static GUdevDevice *g_udev_device_new(GUdevDeviceInfo *usbdev)
+{

Could be worth adding g_return_val_if_fail (usbdev != NULL, NULL)
ok
+    GUdevDevice *device =  G_UDEV_DEVICE(g_object_new(G_UDEV_TYPE_DEVICE, 
NULL));
+
+    device->priv->usbdev = usbdev;
+    return device;
+}


+const gchar *g_udev_device_get_property(GUdevDevice *udev, const gchar 
*property)
+{
+    GUdevDeviceInfo* usbdev = udev->priv->usbdev;
+
Checking argument could be worth:
g_return_val_if_fail(G_UDEV_IS_DEVICE(dev)..)
g_return_val_if_fail(property != NULL)
ok
+    if (strcmp(property, "BUSNUM") == 0) {

We generally prefer g_strcmp0() , a bit safer.
ok
+        return usbdev->sbus;
+    } else if (strcmp(property, "DEVNUM") == 0) {
+        return usbdev->saddr;
+    } else if (strcmp(property, "DEVTYPE") == 0) {
+        return "usb_device";
+    }

If the value is different it would be worth to warn with
g_warn_if_reached() for example.
ok
+const gchar *g_udev_device_get_sysfs_attr(GUdevDevice *udev, const gchar *attr)
+{

same comments as previous function


ok & thanks again,
Arnon
_______________________________________________
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel

Reply via email to