2 * Plug and Play support for hid devices found through udev
4 * Copyright 2016 CodeWeavers, Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #define NONAMELESSUNION
36 #define WIN32_NO_STATUS
42 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(plugplay
);
50 static struct udev
*udev_context
= NULL
;
51 static DRIVER_OBJECT
*udev_driver_obj
= NULL
;
53 static const WCHAR hidraw_busidW
[] = {'H','I','D','R','A','W',0};
56 DEFINE_GUID(GUID_DEVCLASS_HIDRAW
, 0x3def44ad,0x242e,0x46e5,0x82,0x6d,0x70,0x72,0x13,0xf3,0xaa,0x81);
58 static DWORD
get_sysattr_dword(struct udev_device
*dev
, const char *sysattr
, int base
)
60 const char *attr
= udev_device_get_sysattr_value(dev
, sysattr
);
63 WARN("Could not get %s from device\n", sysattr
);
66 return strtol(attr
, NULL
, base
);
69 static WCHAR
*get_sysattr_string(struct udev_device
*dev
, const char *sysattr
)
71 const char *attr
= udev_device_get_sysattr_value(dev
, sysattr
);
76 WARN("Could not get %s from device\n", sysattr
);
79 len
= MultiByteToWideChar(CP_UNIXCP
, 0, attr
, -1, NULL
, 0);
80 if ((dst
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
81 MultiByteToWideChar(CP_UNIXCP
, 0, attr
, -1, dst
, len
);
85 static void try_add_device(struct udev_device
*dev
)
87 DWORD vid
= 0, pid
= 0, version
= 0;
88 struct udev_device
*usbdev
;
89 DEVICE_OBJECT
*device
= NULL
;
90 const char *subsystem
;
95 if (!(devnode
= udev_device_get_devnode(dev
)))
98 if ((fd
= open(devnode
, O_RDWR
)) == -1)
100 WARN("Unable to open udev device %s: %s\n", debugstr_a(devnode
), strerror(errno
));
105 usbdev
= udev_device_get_parent_with_subsystem_devtype(dev
, "usb", "usb_device");
108 vid
= get_sysattr_dword(usbdev
, "idVendor", 16);
109 pid
= get_sysattr_dword(usbdev
, "idProduct", 16);
110 version
= get_sysattr_dword(usbdev
, "version", 10);
111 serial
= get_sysattr_string(usbdev
, "serial");
114 TRACE("Found udev device %s (vid %04x, pid %04x, version %u, serial %s)\n",
115 debugstr_a(devnode
), vid
, pid
, version
, debugstr_w(serial
));
117 subsystem
= udev_device_get_subsystem(dev
);
118 if (strcmp(subsystem
, "hidraw") == 0)
120 device
= bus_create_hid_device(udev_driver_obj
, hidraw_busidW
, dev
, vid
, pid
,
121 version
, 0, serial
, FALSE
, &GUID_DEVCLASS_HIDRAW
);
125 udev_device_ref(dev
);
127 WARN("Ignoring device %s with subsystem %s\n", debugstr_a(devnode
), subsystem
);
129 HeapFree(GetProcessHeap(), 0, serial
);
132 static void build_initial_deviceset(void)
134 struct udev_enumerate
*enumerate
;
135 struct udev_list_entry
*devices
, *dev_list_entry
;
137 enumerate
= udev_enumerate_new(udev_context
);
140 WARN("Unable to create udev enumeration object\n");
144 if (udev_enumerate_add_match_subsystem(enumerate
, "hidraw") < 0)
145 WARN("Failed to add subsystem 'hidraw' to enumeration\n");
147 if (udev_enumerate_scan_devices(enumerate
) < 0)
148 WARN("Enumeration scan failed\n");
150 devices
= udev_enumerate_get_list_entry(enumerate
);
151 udev_list_entry_foreach(dev_list_entry
, devices
)
153 struct udev_device
*dev
;
156 path
= udev_list_entry_get_name(dev_list_entry
);
157 if ((dev
= udev_device_new_from_syspath(udev_context
, path
)))
160 udev_device_unref(dev
);
164 udev_enumerate_unref(enumerate
);
167 NTSTATUS WINAPI
udev_driver_init(DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry_path
)
169 TRACE("(%p, %s)\n", driver
, debugstr_w(registry_path
->Buffer
));
171 if (!(udev_context
= udev_new()))
173 ERR("Can't create udev object\n");
174 return STATUS_UNSUCCESSFUL
;
177 udev_driver_obj
= driver
;
178 driver
->MajorFunction
[IRP_MJ_PNP
] = common_pnp_dispatch
;
180 build_initial_deviceset();
181 return STATUS_SUCCESS
;
186 NTSTATUS WINAPI
udev_driver_init(DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry_path
)
188 WARN("Wine was compiled without UDEV support\n");
189 return STATUS_NOT_IMPLEMENTED
;
192 #endif /* HAVE_UDEV */