Aric Stewart : winebus.sys: Implement udev device enumeration.

Alexandre Julliard julliard at winehq.org
Tue Sep 13 11:33:57 CDT 2016


Module: wine
Branch: master
Commit: 637738f472885dc378545534469e4ba64892d40c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=637738f472885dc378545534469e4ba64892d40c

Author: Aric Stewart <aric at codeweavers.com>
Date:   Tue Sep 13 11:13:26 2016 +0200

winebus.sys: Implement udev device enumeration.

Signed-off-by: Aric Stewart <aric at codeweavers.com>
Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winebus.sys/Makefile.in |   2 +
 dlls/winebus.sys/bus_udev.c  | 113 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 115 insertions(+)

diff --git a/dlls/winebus.sys/Makefile.in b/dlls/winebus.sys/Makefile.in
index 99ff4d2..b24416b 100644
--- a/dlls/winebus.sys/Makefile.in
+++ b/dlls/winebus.sys/Makefile.in
@@ -1,5 +1,7 @@
 MODULE    = winebus.sys
 IMPORTS   = ntoskrnl
+EXTRALIBS = $(UDEV_LIBS)
+EXTRAINCL = $(UDEV_CFLAGS)
 EXTRADLLFLAGS = -Wb,--subsystem,native
 
 C_SRCS = \
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index f040e60..d47a556 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -19,7 +19,16 @@
  */
 
 #include "config.h"
+#include <errno.h>
+#include <fcntl.h>
 #include <stdarg.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_LIBUDEV_H
+# include <libudev.h>
+#endif
 
 #define NONAMELESSUNION
 
@@ -27,6 +36,7 @@
 #define WIN32_NO_STATUS
 #include "windef.h"
 #include "winbase.h"
+#include "winnls.h"
 #include "winternl.h"
 #include "ddk/wdm.h"
 #include "wine/debug.h"
@@ -37,15 +47,118 @@ WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
 
 #ifdef HAVE_UDEV
 
+static struct udev *udev_context = NULL;
 static DRIVER_OBJECT *udev_driver_obj = NULL;
 
+static DWORD get_sysattr_dword(struct udev_device *dev, const char *sysattr, int base)
+{
+    const char *attr = udev_device_get_sysattr_value(dev, sysattr);
+    if (!attr)
+    {
+        WARN("Could not get %s from device\n", sysattr);
+        return 0;
+    }
+    return strtol(attr, NULL, base);
+}
+
+static WCHAR *get_sysattr_string(struct udev_device *dev, const char *sysattr)
+{
+    const char *attr = udev_device_get_sysattr_value(dev, sysattr);
+    WCHAR *dst;
+    DWORD len;
+    if (!attr)
+    {
+        WARN("Could not get %s from device\n", sysattr);
+        return NULL;
+    }
+    len = MultiByteToWideChar(CP_UNIXCP, 0, attr, -1, NULL, 0);
+    if ((dst = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
+        MultiByteToWideChar(CP_UNIXCP, 0, attr, -1, dst, len);
+    return dst;
+}
+
+static void try_add_device(struct udev_device *dev)
+{
+    DWORD vid = 0, pid = 0, version = 0;
+    struct udev_device *usbdev;
+    const char *devnode;
+    WCHAR *serial = NULL;
+    int fd;
+
+    if (!(devnode = udev_device_get_devnode(dev)))
+        return;
+
+    if ((fd = open(devnode, O_RDWR)) == -1)
+    {
+        WARN("Unable to open udev device %s: %s\n", debugstr_a(devnode), strerror(errno));
+        return;
+    }
+    close(fd);
+
+    usbdev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device");
+    if (usbdev)
+    {
+        vid     = get_sysattr_dword(usbdev, "idVendor", 16);
+        pid     = get_sysattr_dword(usbdev, "idProduct", 16);
+        version = get_sysattr_dword(usbdev, "version", 10);
+        serial  = get_sysattr_string(usbdev, "serial");
+    }
+
+    TRACE("Found udev device %s (vid %04x, pid %04x, version %u, serial %s)\n",
+          debugstr_a(devnode), vid, pid, version, debugstr_w(serial));
+
+    HeapFree(GetProcessHeap(), 0, serial);
+}
+
+static void build_initial_deviceset(void)
+{
+    struct udev_enumerate *enumerate;
+    struct udev_list_entry *devices, *dev_list_entry;
+
+    enumerate = udev_enumerate_new(udev_context);
+    if (!enumerate)
+    {
+        WARN("Unable to create udev enumeration object\n");
+        return;
+    }
+
+    if (udev_enumerate_add_match_subsystem(enumerate, "hidraw") < 0)
+        WARN("Failed to add subsystem 'hidraw' to enumeration\n");
+
+    if (udev_enumerate_scan_devices(enumerate) < 0)
+        WARN("Enumeration scan failed\n");
+
+    devices = udev_enumerate_get_list_entry(enumerate);
+    udev_list_entry_foreach(dev_list_entry, devices)
+    {
+        struct udev_device *dev;
+        const char *path;
+
+        path = udev_list_entry_get_name(dev_list_entry);
+        if ((dev = udev_device_new_from_syspath(udev_context, path)))
+        {
+            try_add_device(dev);
+            udev_device_unref(dev);
+        }
+    }
+
+    udev_enumerate_unref(enumerate);
+}
+
 NTSTATUS WINAPI udev_driver_init(DRIVER_OBJECT *driver, UNICODE_STRING *registry_path)
 {
     TRACE("(%p, %s)\n", driver, debugstr_w(registry_path->Buffer));
 
+    if (!(udev_context = udev_new()))
+    {
+        ERR("Can't create udev object\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
     udev_driver_obj = driver;
     driver->MajorFunction[IRP_MJ_PNP] = common_pnp_dispatch;
 
+    build_initial_deviceset();
     return STATUS_SUCCESS;
 }
 




More information about the wine-cvs mailing list