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