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
32 #ifdef HAVE_SYS_POLL_H
33 # include <sys/poll.h>
38 #ifdef HAVE_LINUX_HIDRAW_H
39 # include <linux/hidraw.h>
41 #ifdef HAVE_SYS_IOCTL_H
42 # include <sys/ioctl.h>
45 #ifdef HAVE_LINUX_INPUT_H
46 # include <linux/input.h>
48 # if defined(EVIOCGBIT) && defined(EV_ABS) && defined(BTN_PINKIE)
49 # define HAS_PROPER_INPUT_HEADER
53 #define NONAMELESSUNION
56 #define WIN32_NO_STATUS
62 #include "ddk/hidtypes.h"
63 #include "wine/debug.h"
64 #include "wine/unicode.h"
66 #ifdef HAS_PROPER_INPUT_HEADER
67 # include "hidusage.h"
70 #ifdef WORDS_BIGENDIAN
71 #define LE_WORD(x) RtlUshortByteSwap(x)
72 #define LE_DWORD(x) RtlUlongByteSwap(x)
74 #define LE_WORD(x) (x)
75 #define LE_DWORD(x) (x)
80 WINE_DEFAULT_DEBUG_CHANNEL(plugplay
);
84 WINE_DECLARE_DEBUG_CHANNEL(hid_report
);
86 static struct udev
*udev_context
= NULL
;
87 static DRIVER_OBJECT
*udev_driver_obj
= NULL
;
88 static DWORD disable_hidraw
= 0;
89 static DWORD disable_input
= 0;
91 static const WCHAR hidraw_busidW
[] = {'H','I','D','R','A','W',0};
92 static const WCHAR lnxev_busidW
[] = {'L','N','X','E','V',0};
95 DEFINE_GUID(GUID_DEVCLASS_HIDRAW
, 0x3def44ad,0x242e,0x46e5,0x82,0x6d,0x70,0x72,0x13,0xf3,0xaa,0x81);
96 DEFINE_GUID(GUID_DEVCLASS_LINUXEVENT
, 0x1b932c0d,0xfea7,0x42cd,0x8e,0xaa,0x0e,0x48,0x79,0xb6,0x9e,0xaa);
98 struct platform_private
100 struct udev_device
*udev_device
;
103 HANDLE report_thread
;
107 static inline struct platform_private
*impl_from_DEVICE_OBJECT(DEVICE_OBJECT
*device
)
109 return (struct platform_private
*)get_platform_private(device
);
112 #ifdef HAS_PROPER_INPUT_HEADER
113 static const BYTE REPORT_HEADER
[] = {
114 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
115 0x09, 0x00, /* USAGE (??) */
116 0xa1, 0x01, /* COLLECTION (Application) */
117 0x09, 0x01, /* USAGE () */
118 0xa1, 0x00, /* COLLECTION (Physical) */
121 #define IDX_HEADER_PAGE 1
122 #define IDX_HEADER_USAGE 3
124 static const BYTE REPORT_BUTTONS
[] = {
125 0x05, 0x09, /* USAGE_PAGE (Button) */
126 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */
127 0x29, 0x03, /* USAGE_MAXIMUM (Button 3) */
128 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
129 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
130 0x35, 0x00, /* LOGICAL_MINIMUM (0) */
131 0x45, 0x01, /* LOGICAL_MAXIMUM (1) */
132 0x95, 0x03, /* REPORT_COUNT (3) */
133 0x75, 0x01, /* REPORT_SIZE (1) */
134 0x81, 0x02, /* INPUT (Data,Var,Abs) */
136 #define IDX_BUTTON_MIN_USAGE 3
137 #define IDX_BUTTON_MAX_USAGE 5
138 #define IDX_BUTTON_COUNT 11
140 static const BYTE REPORT_PADDING
[] = {
141 0x95, 0x03, /* REPORT_COUNT (3) */
142 0x75, 0x01, /* REPORT_SIZE (1) */
143 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
145 #define IDX_PADDING_BIT_COUNT 1
147 static const BYTE REPORT_AXIS_HEADER
[] = {
148 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
150 #define IDX_AXIS_PAGE 1
153 static const BYTE REPORT_AXIS_USAGE
[] = {
154 0x09, 0x30, /* USAGE (X) */
156 #define IDX_AXIS_USAGE 1
158 static const BYTE REPORT_ABS_AXIS_TAIL
[] = {
159 0x17, 0x00, 0x00, 0x00, 0x00, /* LOGICAL_MINIMUM (0) */
160 0x27, 0xff, 0x00, 0x00, 0x00, /* LOGICAL_MAXIMUM (0xff) */
161 0x37, 0x00, 0x00, 0x00, 0x00, /* PHYSICAL_MINIMUM (0) */
162 0x47, 0xff, 0x00, 0x00, 0x00, /* PHYSICAL_MAXIMUM (256) */
163 0x75, 0x20, /* REPORT_SIZE (32) */
164 0x95, 0x00, /* REPORT_COUNT (2) */
165 0x81, 0x02, /* INPUT (Data,Var,Abs) */
167 #define IDX_ABS_LOG_MINIMUM 1
168 #define IDX_ABS_LOG_MAXIMUM 6
169 #define IDX_ABS_PHY_MINIMUM 11
170 #define IDX_ABS_PHY_MAXIMUM 16
171 #define IDX_ABS_AXIS_COUNT 23
173 static const BYTE REPORT_REL_AXIS_TAIL
[] = {
174 0x15, 0x81, /* LOGICAL_MINIMUM (0) */
175 0x25, 0x7f, /* LOGICAL_MAXIMUM (0xffff) */
176 0x75, 0x08, /* REPORT_SIZE (16) */
177 0x95, 0x02, /* REPORT_COUNT (2) */
178 0x81, 0x06, /* INPUT (Data,Var,Rel) */
180 #define IDX_REL_AXIS_COUNT 7
182 static const BYTE REPORT_HATSWITCH
[] = {
183 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
184 0x09, 0x39, /* USAGE (Hatswitch) */
185 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
186 0x25, 0x08, /* LOGICAL_MAXIMUM (0x08) */
187 0x35, 0x00, /* PHYSICAL_MINIMUM (0) */
188 0x45, 0x08, /* PHYSICAL_MAXIMUM (8) */
189 0x75, 0x08, /* REPORT_SIZE (8) */
190 0x95, 0x01, /* REPORT_COUNT (1) */
191 0x81, 0x02, /* INPUT (Data,Var,Abs) */
193 #define IDX_HATSWITCH_COUNT 15
195 static const BYTE REPORT_TAIL
[] = {
196 0xc0, /* END_COLLECTION */
197 0xc0 /* END_COLLECTION */
200 static const BYTE ABS_TO_HID_MAP
[][2] = {
201 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_X
}, /*ABS_X*/
202 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Y
}, /*ABS_Y*/
203 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Z
}, /*ABS_Z*/
204 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RX
}, /*ABS_RX*/
205 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RY
}, /*ABS_RY*/
206 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RZ
}, /*ABS_RZ*/
207 {HID_USAGE_PAGE_SIMULATION
, HID_USAGE_SIMULATION_THROTTLE
}, /*ABS_THROTTLE*/
208 {HID_USAGE_PAGE_SIMULATION
, HID_USAGE_SIMULATION_RUDDER
}, /*ABS_RUDDER*/
209 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_WHEEL
}, /*ABS_WHEEL*/
210 {HID_USAGE_PAGE_SIMULATION
, 0xC4}, /*ABS_GAS*/
211 {HID_USAGE_PAGE_SIMULATION
, 0xC5}, /*ABS_BRAKE*/
220 {HID_USAGE_PAGE_DIGITIZER
, 0x30}, /*ABS_PRESSURE*/
221 {0, 0}, /*ABS_DISTANCE*/
222 {HID_USAGE_PAGE_DIGITIZER
, 0x3D}, /*ABS_TILT_X*/
223 {HID_USAGE_PAGE_DIGITIZER
, 0x3F}, /*ABS_TILT_Y*/
224 {0, 0}, /*ABS_TOOL_WIDTH*/
228 {HID_USAGE_PAGE_CONSUMER
, 0xE0} /*ABS_VOLUME*/
230 #define HID_ABS_MAX (ABS_VOLUME+1)
231 #define TOP_ABS_PAGE (HID_USAGE_PAGE_DIGITIZER+1)
233 static const BYTE REL_TO_HID_MAP
[][2] = {
234 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_X
}, /* REL_X */
235 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Y
}, /* REL_Y */
236 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Z
}, /* REL_Z */
237 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RX
}, /* REL_RX */
238 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RY
}, /* REL_RY */
239 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RZ
}, /* REL_RZ */
240 {0, 0}, /* REL_HWHEEL */
241 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_DIAL
}, /* REL_DIAL */
242 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_WHEEL
}, /* REL_WHEEL */
243 {0, 0} /* REL_MISC */
246 #define HID_REL_MAX (REL_MISC+1)
247 #define TOP_REL_PAGE (HID_USAGE_PAGE_CONSUMER+1)
249 struct wine_input_absinfo
{
250 struct input_absinfo info
;
254 struct wine_input_private
{
255 struct platform_private base
;
257 int report_descriptor_size
;
258 BYTE
*report_descriptor
;
260 BYTE button_map
[KEY_MAX
];
261 BYTE rel_map
[HID_REL_MAX
];
264 struct wine_input_absinfo abs_map
[HID_ABS_MAX
];
267 #define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
269 static BYTE
*add_button_block(BYTE
* report_ptr
, BYTE usage_min
, BYTE usage_max
)
271 memcpy(report_ptr
, REPORT_BUTTONS
, sizeof(REPORT_BUTTONS
));
272 report_ptr
[IDX_BUTTON_MIN_USAGE
] = usage_min
;
273 report_ptr
[IDX_BUTTON_MAX_USAGE
] = usage_max
;
274 report_ptr
[IDX_BUTTON_COUNT
] = (usage_max
- usage_min
) + 1;
275 return report_ptr
+ sizeof(REPORT_BUTTONS
);
278 static BYTE
*add_axis_block(BYTE
*report_ptr
, BYTE count
, BYTE page
, BYTE
*usages
, BOOL absolute
, const struct wine_input_absinfo
*absinfo
)
281 memcpy(report_ptr
, REPORT_AXIS_HEADER
, sizeof(REPORT_AXIS_HEADER
));
282 report_ptr
[IDX_AXIS_PAGE
] = page
;
283 report_ptr
+= sizeof(REPORT_AXIS_HEADER
);
284 for (i
= 0; i
< count
; i
++)
286 memcpy(report_ptr
, REPORT_AXIS_USAGE
, sizeof(REPORT_AXIS_USAGE
));
287 report_ptr
[IDX_AXIS_USAGE
] = usages
[i
];
288 report_ptr
+= sizeof(REPORT_AXIS_USAGE
);
292 memcpy(report_ptr
, REPORT_ABS_AXIS_TAIL
, sizeof(REPORT_ABS_AXIS_TAIL
));
295 *((int*)&report_ptr
[IDX_ABS_LOG_MINIMUM
]) = LE_DWORD(absinfo
->info
.minimum
);
296 *((int*)&report_ptr
[IDX_ABS_LOG_MAXIMUM
]) = LE_DWORD(absinfo
->info
.maximum
);
297 *((int*)&report_ptr
[IDX_ABS_PHY_MINIMUM
]) = LE_DWORD(absinfo
->info
.minimum
);
298 *((int*)&report_ptr
[IDX_ABS_PHY_MAXIMUM
]) = LE_DWORD(absinfo
->info
.maximum
);
300 report_ptr
[IDX_ABS_AXIS_COUNT
] = count
;
301 report_ptr
+= sizeof(REPORT_ABS_AXIS_TAIL
);
305 memcpy(report_ptr
, REPORT_REL_AXIS_TAIL
, sizeof(REPORT_REL_AXIS_TAIL
));
306 report_ptr
[IDX_REL_AXIS_COUNT
] = count
;
307 report_ptr
+= sizeof(REPORT_REL_AXIS_TAIL
);
312 static BYTE
*add_padding_block(BYTE
*report_ptr
, BYTE bitcount
)
314 memcpy(report_ptr
, REPORT_PADDING
, sizeof(REPORT_PADDING
));
315 report_ptr
[IDX_PADDING_BIT_COUNT
] = bitcount
;
316 return report_ptr
+ sizeof(REPORT_PADDING
);
319 static BYTE
*add_hatswitch(BYTE
*report_ptr
, INT count
)
321 memcpy(report_ptr
, REPORT_HATSWITCH
, sizeof(REPORT_HATSWITCH
));
322 report_ptr
[IDX_HATSWITCH_COUNT
] = count
;
323 return report_ptr
+ sizeof(REPORT_HATSWITCH
);
326 static const BYTE
* what_am_I(struct udev_device
*dev
)
328 static const BYTE Unknown
[2] = {HID_USAGE_PAGE_GENERIC
, 0};
329 static const BYTE Mouse
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_MOUSE
};
330 static const BYTE Keyboard
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_KEYBOARD
};
331 static const BYTE Gamepad
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_GAMEPAD
};
332 static const BYTE Keypad
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_KEYPAD
};
333 static const BYTE Tablet
[2] = {HID_USAGE_PAGE_DIGITIZER
, 0x2};
334 static const BYTE Touchscreen
[2] = {HID_USAGE_PAGE_DIGITIZER
, 0x4};
335 static const BYTE Touchpad
[2] = {HID_USAGE_PAGE_DIGITIZER
, 0x5};
337 struct udev_device
*parent
= dev
;
339 /* Look to the parents until we get a clue */
342 if (udev_device_get_property_value(parent
, "ID_INPUT_MOUSE"))
344 else if (udev_device_get_property_value(parent
, "ID_INPUT_KEYBOARD"))
346 else if (udev_device_get_property_value(parent
, "ID_INPUT_JOYSTICK"))
348 else if (udev_device_get_property_value(parent
, "ID_INPUT_KEY"))
350 else if (udev_device_get_property_value(parent
, "ID_INPUT_TOUCHPAD"))
352 else if (udev_device_get_property_value(parent
, "ID_INPUT_TOUCHSCREEN"))
354 else if (udev_device_get_property_value(parent
, "ID_INPUT_TABLET"))
357 parent
= udev_device_get_parent_with_subsystem_devtype(parent
, "input", NULL
);
362 static VOID
build_report_descriptor(struct wine_input_private
*ext
, struct udev_device
*dev
)
364 int abs_pages
[TOP_ABS_PAGE
][HID_ABS_MAX
+1];
365 int rel_pages
[TOP_REL_PAGE
][HID_REL_MAX
+1];
366 BYTE absbits
[(ABS_MAX
+7)/8];
367 BYTE relbits
[(REL_MAX
+7)/8];
368 BYTE keybits
[(KEY_MAX
+7)/8];
370 INT i
, descript_size
;
372 INT button_count
, abs_count
, rel_count
, hat_count
;
373 const BYTE
*device_usage
= what_am_I(dev
);
375 if (ioctl(ext
->base
.device_fd
, EVIOCGBIT(EV_REL
, sizeof(relbits
)), relbits
) == -1)
377 WARN("ioctl(EVIOCGBIT, EV_REL) failed: %d %s\n", errno
, strerror(errno
));
380 if (ioctl(ext
->base
.device_fd
, EVIOCGBIT(EV_ABS
, sizeof(absbits
)), absbits
) == -1)
382 WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno
, strerror(errno
));
385 if (ioctl(ext
->base
.device_fd
, EVIOCGBIT(EV_KEY
, sizeof(keybits
)), keybits
) == -1)
387 WARN("ioctl(EVIOCGBIT, EV_KEY) failed: %d %s\n", errno
, strerror(errno
));
391 descript_size
= sizeof(REPORT_HEADER
) + sizeof(REPORT_TAIL
);
394 /* For now lump all buttons just into incremental usages, Ignore Keys */
396 for (i
= BTN_MISC
; i
< KEY_MAX
; i
++)
398 if (test_bit(keybits
, i
))
400 ext
->button_map
[i
] = button_count
;
406 descript_size
+= sizeof(REPORT_BUTTONS
);
407 if (button_count
% 8)
408 descript_size
+= sizeof(REPORT_PADDING
);
409 report_size
= (button_count
+ 7) / 8;
413 memset(abs_pages
, 0, sizeof(abs_pages
));
414 for (i
= 0; i
< HID_ABS_MAX
; i
++)
415 if (test_bit(absbits
, i
))
417 abs_pages
[ABS_TO_HID_MAP
[i
][0]][0]++;
418 abs_pages
[ABS_TO_HID_MAP
[i
][0]][abs_pages
[ABS_TO_HID_MAP
[i
][0]][0]] = i
;
420 ioctl(ext
->base
.device_fd
, EVIOCGABS(i
), &(ext
->abs_map
[i
]));
421 if (abs_pages
[ABS_TO_HID_MAP
[i
][0]][0] == 1)
423 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
424 descript_size
+= sizeof(REPORT_ABS_AXIS_TAIL
);
427 /* Skip page 0, aka HID_USAGE_PAGE_UNDEFINED */
428 for (i
= 1; i
< TOP_ABS_PAGE
; i
++)
429 if (abs_pages
[i
][0] > 0)
432 descript_size
+= sizeof(REPORT_AXIS_USAGE
) * abs_pages
[i
][0];
433 for (j
= 1; j
<= abs_pages
[i
][0]; j
++)
435 ext
->abs_map
[abs_pages
[i
][j
]].report_index
= report_size
;
442 memset(rel_pages
, 0, sizeof(rel_pages
));
443 for (i
= 0; i
< HID_REL_MAX
; i
++)
444 if (test_bit(relbits
, i
))
446 rel_pages
[REL_TO_HID_MAP
[i
][0]][0]++;
447 rel_pages
[REL_TO_HID_MAP
[i
][0]][rel_pages
[REL_TO_HID_MAP
[i
][0]][0]] = i
;
448 if (rel_pages
[REL_TO_HID_MAP
[i
][0]][0] == 1)
450 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
451 descript_size
+= sizeof(REPORT_REL_AXIS_TAIL
);
454 /* Skip page 0, aka HID_USAGE_PAGE_UNDEFINED */
455 for (i
= 1; i
< TOP_REL_PAGE
; i
++)
456 if (rel_pages
[i
][0] > 0)
459 descript_size
+= sizeof(REPORT_AXIS_USAGE
) * rel_pages
[i
][0];
460 for (j
= 1; j
<= rel_pages
[i
][0]; j
++)
462 ext
->rel_map
[rel_pages
[i
][j
]] = report_size
;
469 for (i
= ABS_HAT0X
; i
<=ABS_HAT3X
; i
+=2)
470 if (test_bit(absbits
, i
))
472 ext
->hat_map
[i
- ABS_HAT0X
] = report_size
;
473 ext
->hat_values
[i
- ABS_HAT0X
] = 0;
474 ext
->hat_values
[i
- ABS_HAT0X
+ 1] = 0;
479 TRACE("Report Descriptor will be %i bytes\n", descript_size
);
480 TRACE("Report will be %i bytes\n", report_size
);
482 ext
->report_descriptor
= HeapAlloc(GetProcessHeap(), 0, descript_size
);
483 report_ptr
= ext
->report_descriptor
;
485 memcpy(report_ptr
, REPORT_HEADER
, sizeof(REPORT_HEADER
));
486 report_ptr
[IDX_HEADER_PAGE
] = device_usage
[0];
487 report_ptr
[IDX_HEADER_USAGE
] = device_usage
[1];
488 report_ptr
+= sizeof(REPORT_HEADER
);
491 report_ptr
= add_button_block(report_ptr
, 1, button_count
);
492 if (button_count
% 8)
494 BYTE padding
= 8 - (button_count
% 8);
495 report_ptr
= add_padding_block(report_ptr
, padding
);
500 for (i
= 1; i
< TOP_ABS_PAGE
; i
++)
504 BYTE usages
[HID_ABS_MAX
];
506 for (j
= 0; j
< abs_pages
[i
][0]; j
++)
507 usages
[j
] = ABS_TO_HID_MAP
[abs_pages
[i
][j
+1]][1];
508 report_ptr
= add_axis_block(report_ptr
, abs_pages
[i
][0], i
, usages
, TRUE
, &ext
->abs_map
[abs_pages
[i
][1]]);
514 for (i
= 1; i
< TOP_REL_PAGE
; i
++)
518 BYTE usages
[HID_REL_MAX
];
520 for (j
= 0; j
< rel_pages
[i
][0]; j
++)
521 usages
[j
] = REL_TO_HID_MAP
[rel_pages
[i
][j
+1]][1];
522 report_ptr
= add_axis_block(report_ptr
, rel_pages
[i
][0], i
, usages
, FALSE
, NULL
);
527 report_ptr
= add_hatswitch(report_ptr
, hat_count
);
529 memcpy(report_ptr
, REPORT_TAIL
, sizeof(REPORT_TAIL
));
531 ext
->report_descriptor_size
= descript_size
;
535 static inline WCHAR
*strdupAtoW(const char *src
)
539 if (!src
) return NULL
;
540 len
= MultiByteToWideChar(CP_UNIXCP
, 0, src
, -1, NULL
, 0);
541 if ((dst
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
542 MultiByteToWideChar(CP_UNIXCP
, 0, src
, -1, dst
, len
);
546 static DWORD
get_sysattr_dword(struct udev_device
*dev
, const char *sysattr
, int base
)
548 const char *attr
= udev_device_get_sysattr_value(dev
, sysattr
);
551 WARN("Could not get %s from device\n", sysattr
);
554 return strtol(attr
, NULL
, base
);
557 static WCHAR
*get_sysattr_string(struct udev_device
*dev
, const char *sysattr
)
559 const char *attr
= udev_device_get_sysattr_value(dev
, sysattr
);
562 WARN("Could not get %s from device\n", sysattr
);
565 return strdupAtoW(attr
);
568 static int compare_platform_device(DEVICE_OBJECT
*device
, void *platform_dev
)
570 struct udev_device
*dev1
= impl_from_DEVICE_OBJECT(device
)->udev_device
;
571 struct udev_device
*dev2
= platform_dev
;
572 return strcmp(udev_device_get_syspath(dev1
), udev_device_get_syspath(dev2
));
575 static NTSTATUS
hidraw_get_reportdescriptor(DEVICE_OBJECT
*device
, BYTE
*buffer
, DWORD length
, DWORD
*out_length
)
577 #ifdef HAVE_LINUX_HIDRAW_H
578 struct hidraw_report_descriptor descriptor
;
579 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
581 if (ioctl(private->device_fd
, HIDIOCGRDESCSIZE
, &descriptor
.size
) == -1)
583 WARN("ioctl(HIDIOCGRDESCSIZE) failed: %d %s\n", errno
, strerror(errno
));
584 return STATUS_UNSUCCESSFUL
;
587 *out_length
= descriptor
.size
;
589 if (length
< descriptor
.size
)
590 return STATUS_BUFFER_TOO_SMALL
;
591 if (!descriptor
.size
)
592 return STATUS_SUCCESS
;
594 if (ioctl(private->device_fd
, HIDIOCGRDESC
, &descriptor
) == -1)
596 WARN("ioctl(HIDIOCGRDESC) failed: %d %s\n", errno
, strerror(errno
));
597 return STATUS_UNSUCCESSFUL
;
600 memcpy(buffer
, descriptor
.value
, descriptor
.size
);
601 return STATUS_SUCCESS
;
603 return STATUS_NOT_IMPLEMENTED
;
607 static NTSTATUS
hidraw_get_string(DEVICE_OBJECT
*device
, DWORD index
, WCHAR
*buffer
, DWORD length
)
609 struct udev_device
*usbdev
;
610 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
613 usbdev
= udev_device_get_parent_with_subsystem_devtype(private->udev_device
, "usb", "usb_device");
618 case HID_STRING_ID_IPRODUCT
:
619 str
= get_sysattr_string(usbdev
, "product");
621 case HID_STRING_ID_IMANUFACTURER
:
622 str
= get_sysattr_string(usbdev
, "manufacturer");
624 case HID_STRING_ID_ISERIALNUMBER
:
625 str
= get_sysattr_string(usbdev
, "serial");
628 ERR("Unhandled string index %08x\n", index
);
629 return STATUS_NOT_IMPLEMENTED
;
634 #ifdef HAVE_LINUX_HIDRAW_H
637 case HID_STRING_ID_IPRODUCT
:
640 if (ioctl(private->device_fd
, HIDIOCGRAWNAME(MAX_PATH
), buf
) == -1)
641 WARN("ioctl(HIDIOCGRAWNAME) failed: %d %s\n", errno
, strerror(errno
));
643 str
= strdupAtoW(buf
);
646 case HID_STRING_ID_IMANUFACTURER
:
648 case HID_STRING_ID_ISERIALNUMBER
:
651 ERR("Unhandled string index %08x\n", index
);
652 return STATUS_NOT_IMPLEMENTED
;
655 return STATUS_NOT_IMPLEMENTED
;
661 if (!length
) return STATUS_BUFFER_TOO_SMALL
;
663 return STATUS_SUCCESS
;
666 if (length
<= strlenW(str
))
668 HeapFree(GetProcessHeap(), 0, str
);
669 return STATUS_BUFFER_TOO_SMALL
;
672 strcpyW(buffer
, str
);
673 HeapFree(GetProcessHeap(), 0, str
);
674 return STATUS_SUCCESS
;
677 static DWORD CALLBACK
device_report_thread(void *args
)
679 DEVICE_OBJECT
*device
= (DEVICE_OBJECT
*)args
;
680 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
681 struct pollfd plfds
[2];
683 plfds
[0].fd
= private->device_fd
;
684 plfds
[0].events
= POLLIN
;
685 plfds
[0].revents
= 0;
686 plfds
[1].fd
= private->control_pipe
[0];
687 plfds
[1].events
= POLLIN
;
688 plfds
[1].revents
= 0;
693 BYTE report_buffer
[1024];
695 if (poll(plfds
, 2, -1) <= 0) continue;
696 if (plfds
[1].revents
)
698 size
= read(plfds
[0].fd
, report_buffer
, sizeof(report_buffer
));
700 TRACE_(hid_report
)("Read failed. Likely an unplugged device\n");
702 TRACE_(hid_report
)("Failed to read report\n");
704 process_hid_report(device
, report_buffer
, size
);
709 static NTSTATUS
begin_report_processing(DEVICE_OBJECT
*device
)
711 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
713 if (private->report_thread
)
714 return STATUS_SUCCESS
;
716 if (pipe(private->control_pipe
) != 0)
718 ERR("Control pipe creation failed\n");
719 return STATUS_UNSUCCESSFUL
;
722 private->report_thread
= CreateThread(NULL
, 0, device_report_thread
, device
, 0, NULL
);
723 if (!private->report_thread
)
725 ERR("Unable to create device report thread\n");
726 close(private->control_pipe
[0]);
727 close(private->control_pipe
[1]);
728 return STATUS_UNSUCCESSFUL
;
731 return STATUS_SUCCESS
;
734 static NTSTATUS
hidraw_set_output_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
736 struct platform_private
* ext
= impl_from_DEVICE_OBJECT(device
);
740 rc
= write(ext
->device_fd
, report
, length
);
743 BYTE report_buffer
[1024];
745 if (length
+ 1 > sizeof(report_buffer
))
747 ERR("Output report buffer too small\n");
748 return STATUS_UNSUCCESSFUL
;
751 report_buffer
[0] = 0;
752 memcpy(&report_buffer
[1], report
, length
);
753 rc
= write(ext
->device_fd
, report_buffer
, length
+ 1);
758 return STATUS_SUCCESS
;
763 return STATUS_UNSUCCESSFUL
;
767 static NTSTATUS
hidraw_get_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*read
)
769 #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCGFEATURE)
771 struct platform_private
* ext
= impl_from_DEVICE_OBJECT(device
);
773 length
= min(length
, 0x1fff);
774 rc
= ioctl(ext
->device_fd
, HIDIOCGFEATURE(length
), report
);
778 return STATUS_SUCCESS
;
783 return STATUS_UNSUCCESSFUL
;
787 return STATUS_NOT_IMPLEMENTED
;
791 static NTSTATUS
hidraw_set_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
793 #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCSFEATURE)
795 struct platform_private
* ext
= impl_from_DEVICE_OBJECT(device
);
796 BYTE
*feature_buffer
;
801 if (length
+ 1 > sizeof(buffer
))
803 ERR("Output feature buffer too small\n");
804 return STATUS_UNSUCCESSFUL
;
807 memcpy(&buffer
[1], report
, length
);
808 feature_buffer
= buffer
;
812 feature_buffer
= report
;
813 length
= min(length
, 0x1fff);
814 rc
= ioctl(ext
->device_fd
, HIDIOCSFEATURE(length
), feature_buffer
);
818 return STATUS_SUCCESS
;
823 return STATUS_UNSUCCESSFUL
;
827 return STATUS_NOT_IMPLEMENTED
;
831 static const platform_vtbl hidraw_vtbl
=
833 compare_platform_device
,
834 hidraw_get_reportdescriptor
,
836 begin_report_processing
,
837 hidraw_set_output_report
,
838 hidraw_get_feature_report
,
839 hidraw_set_feature_report
,
842 #ifdef HAS_PROPER_INPUT_HEADER
844 static inline struct wine_input_private
*input_impl_from_DEVICE_OBJECT(DEVICE_OBJECT
*device
)
846 return (struct wine_input_private
*)get_platform_private(device
);
849 static NTSTATUS
lnxev_get_reportdescriptor(DEVICE_OBJECT
*device
, BYTE
*buffer
, DWORD length
, DWORD
*out_length
)
851 struct wine_input_private
*ext
= input_impl_from_DEVICE_OBJECT(device
);
853 *out_length
= ext
->report_descriptor_size
;
855 if (length
< ext
->report_descriptor_size
)
856 return STATUS_BUFFER_TOO_SMALL
;
858 memcpy(buffer
, ext
->report_descriptor
, ext
->report_descriptor_size
);
860 return STATUS_SUCCESS
;
863 static NTSTATUS
lnxev_get_string(DEVICE_OBJECT
*device
, DWORD index
, WCHAR
*buffer
, DWORD length
)
865 return STATUS_NOT_IMPLEMENTED
;
868 static NTSTATUS
lnxev_begin_report_processing(DEVICE_OBJECT
*device
)
870 return STATUS_NOT_IMPLEMENTED
;
873 static NTSTATUS
lnxev_set_output_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
876 return STATUS_NOT_IMPLEMENTED
;
879 static NTSTATUS
lnxev_get_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*read
)
882 return STATUS_NOT_IMPLEMENTED
;
885 static NTSTATUS
lnxev_set_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
888 return STATUS_NOT_IMPLEMENTED
;
891 static const platform_vtbl lnxev_vtbl
= {
892 compare_platform_device
,
893 lnxev_get_reportdescriptor
,
895 lnxev_begin_report_processing
,
896 lnxev_set_output_report
,
897 lnxev_get_feature_report
,
898 lnxev_set_feature_report
,
902 static int check_same_device(DEVICE_OBJECT
*device
, void* context
)
904 return !compare_platform_device(device
, context
);
907 static void try_add_device(struct udev_device
*dev
)
909 DWORD vid
= 0, pid
= 0, version
= 0;
910 struct udev_device
*usbdev
= NULL
;
911 DEVICE_OBJECT
*device
= NULL
;
912 const char *subsystem
;
914 WCHAR
*serial
= NULL
;
915 const char* gamepad
= NULL
;
918 if (!(devnode
= udev_device_get_devnode(dev
)))
921 if ((fd
= open(devnode
, O_RDWR
)) == -1)
923 WARN("Unable to open udev device %s: %s\n", debugstr_a(devnode
), strerror(errno
));
927 subsystem
= udev_device_get_subsystem(dev
);
928 usbdev
= udev_device_get_parent_with_subsystem_devtype(dev
, "usb", "usb_device");
931 #ifdef HAS_PROPER_INPUT_HEADER
932 const platform_vtbl
*other_vtbl
= NULL
;
933 DEVICE_OBJECT
*dup
= NULL
;
934 if (strcmp(subsystem
, "hidraw") == 0)
935 other_vtbl
= &lnxev_vtbl
;
936 else if (strcmp(subsystem
, "input") == 0)
937 other_vtbl
= &hidraw_vtbl
;
940 dup
= bus_enumerate_hid_devices(other_vtbl
, check_same_device
, dev
);
943 TRACE("Duplicate cross bus device (%p) found, not adding the new one\n", dup
);
948 vid
= get_sysattr_dword(usbdev
, "idVendor", 16);
949 pid
= get_sysattr_dword(usbdev
, "idProduct", 16);
950 version
= get_sysattr_dword(usbdev
, "version", 10);
951 serial
= get_sysattr_string(usbdev
, "serial");
953 #ifdef HAS_PROPER_INPUT_HEADER
956 struct input_id device_id
= {0};
957 char device_uid
[255];
959 if (ioctl(fd
, EVIOCGID
, &device_id
) < 0)
960 WARN("ioctl(EVIOCGID) failed: %d %s\n", errno
, strerror(errno
));
962 if (ioctl(fd
, EVIOCGUNIQ(254), device_uid
) >= 0 && device_uid
[0])
963 serial
= strdupAtoW(device_uid
);
965 gamepad
= udev_device_get_property_value(dev
, "ID_INPUT_JOYSTICK");
966 vid
= device_id
.vendor
;
967 pid
= device_id
.product
;
968 version
= device_id
.version
;
972 WARN("Could not get device to query VID, PID, Version and Serial\n");
975 TRACE("Found udev device %s (vid %04x, pid %04x, version %u, serial %s)\n",
976 debugstr_a(devnode
), vid
, pid
, version
, debugstr_w(serial
));
978 if (strcmp(subsystem
, "hidraw") == 0)
980 device
= bus_create_hid_device(udev_driver_obj
, hidraw_busidW
, vid
, pid
, version
, 0, serial
, FALSE
,
981 &GUID_DEVCLASS_HIDRAW
, &hidraw_vtbl
, sizeof(struct platform_private
));
983 #ifdef HAS_PROPER_INPUT_HEADER
984 else if (strcmp(subsystem
, "input") == 0)
986 device
= bus_create_hid_device(udev_driver_obj
, lnxev_busidW
, vid
, pid
, version
, 0, serial
, (gamepad
!= NULL
),
987 &GUID_DEVCLASS_LINUXEVENT
, &lnxev_vtbl
, sizeof(struct wine_input_private
));
993 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
994 private->udev_device
= udev_device_ref(dev
);
995 private->device_fd
= fd
;
996 #ifdef HAS_PROPER_INPUT_HEADER
997 if (strcmp(subsystem
, "input") == 0)
998 build_report_descriptor((struct wine_input_private
*)private, dev
);
1000 IoInvalidateDeviceRelations(device
, BusRelations
);
1004 WARN("Ignoring device %s with subsystem %s\n", debugstr_a(devnode
), subsystem
);
1008 HeapFree(GetProcessHeap(), 0, serial
);
1011 static void try_remove_device(struct udev_device
*dev
)
1013 DEVICE_OBJECT
*device
= NULL
;
1014 struct platform_private
* private;
1015 #ifdef HAS_PROPER_INPUT_HEADER
1016 BOOL is_input
= FALSE
;
1019 device
= bus_find_hid_device(&hidraw_vtbl
, dev
);
1020 #ifdef HAS_PROPER_INPUT_HEADER
1023 device
= bus_find_hid_device(&lnxev_vtbl
, dev
);
1027 if (!device
) return;
1029 IoInvalidateDeviceRelations(device
, RemovalRelations
);
1031 private = impl_from_DEVICE_OBJECT(device
);
1033 if (private->report_thread
)
1035 write(private->control_pipe
[1], "q", 1);
1036 WaitForSingleObject(private->report_thread
, INFINITE
);
1037 close(private->control_pipe
[0]);
1038 close(private->control_pipe
[1]);
1039 CloseHandle(private->report_thread
);
1042 #ifdef HAS_PROPER_INPUT_HEADER
1045 struct wine_input_private
*ext
= (struct wine_input_private
*)private;
1046 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
1050 dev
= private->udev_device
;
1051 close(private->device_fd
);
1052 bus_remove_hid_device(device
);
1053 udev_device_unref(dev
);
1056 static void build_initial_deviceset(void)
1058 struct udev_enumerate
*enumerate
;
1059 struct udev_list_entry
*devices
, *dev_list_entry
;
1061 enumerate
= udev_enumerate_new(udev_context
);
1064 WARN("Unable to create udev enumeration object\n");
1068 if (!disable_hidraw
)
1069 if (udev_enumerate_add_match_subsystem(enumerate
, "hidraw") < 0)
1070 WARN("Failed to add subsystem 'hidraw' to enumeration\n");
1071 #ifdef HAS_PROPER_INPUT_HEADER
1074 if (udev_enumerate_add_match_subsystem(enumerate
, "input") < 0)
1075 WARN("Failed to add subsystem 'input' to enumeration\n");
1079 if (udev_enumerate_scan_devices(enumerate
) < 0)
1080 WARN("Enumeration scan failed\n");
1082 devices
= udev_enumerate_get_list_entry(enumerate
);
1083 udev_list_entry_foreach(dev_list_entry
, devices
)
1085 struct udev_device
*dev
;
1088 path
= udev_list_entry_get_name(dev_list_entry
);
1089 if ((dev
= udev_device_new_from_syspath(udev_context
, path
)))
1091 try_add_device(dev
);
1092 udev_device_unref(dev
);
1096 udev_enumerate_unref(enumerate
);
1099 static struct udev_monitor
*create_monitor(struct pollfd
*pfd
)
1101 struct udev_monitor
*monitor
;
1104 monitor
= udev_monitor_new_from_netlink(udev_context
, "udev");
1107 WARN("Unable to get udev monitor object\n");
1111 if (!disable_hidraw
)
1113 if (udev_monitor_filter_add_match_subsystem_devtype(monitor
, "hidraw", NULL
) < 0)
1114 WARN("Failed to add 'hidraw' subsystem to monitor\n");
1118 #ifdef HAS_PROPER_INPUT_HEADER
1121 if (udev_monitor_filter_add_match_subsystem_devtype(monitor
, "input", NULL
) < 0)
1122 WARN("Failed to add 'input' subsystem to monitor\n");
1129 WARN("No subsystems added to monitor\n");
1133 if (udev_monitor_enable_receiving(monitor
) < 0)
1136 if ((pfd
->fd
= udev_monitor_get_fd(monitor
)) >= 0)
1138 pfd
->events
= POLLIN
;
1143 WARN("Failed to start monitoring\n");
1144 udev_monitor_unref(monitor
);
1148 static void process_monitor_event(struct udev_monitor
*monitor
)
1150 struct udev_device
*dev
;
1153 dev
= udev_monitor_receive_device(monitor
);
1156 FIXME("Failed to get device that has changed\n");
1160 action
= udev_device_get_action(dev
);
1161 TRACE("Received action %s for udev device %s\n", debugstr_a(action
),
1162 debugstr_a(udev_device_get_devnode(dev
)));
1165 WARN("No action received\n");
1166 else if (strcmp(action
, "add") == 0)
1167 try_add_device(dev
);
1168 else if (strcmp(action
, "remove") == 0)
1169 try_remove_device(dev
);
1171 WARN("Unhandled action %s\n", debugstr_a(action
));
1173 udev_device_unref(dev
);
1176 static DWORD CALLBACK
deviceloop_thread(void *args
)
1178 struct udev_monitor
*monitor
;
1179 HANDLE init_done
= args
;
1182 monitor
= create_monitor(&pfd
);
1183 build_initial_deviceset();
1184 SetEvent(init_done
);
1188 if (poll(&pfd
, 1, -1) <= 0) continue;
1189 process_monitor_event(monitor
);
1192 TRACE("Monitor thread exiting\n");
1194 udev_monitor_unref(monitor
);
1198 NTSTATUS WINAPI
udev_driver_init(DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry_path
)
1202 static const WCHAR hidraw_disabledW
[] = {'D','i','s','a','b','l','e','H','i','d','r','a','w',0};
1203 static const UNICODE_STRING hidraw_disabled
= {sizeof(hidraw_disabledW
) - sizeof(WCHAR
), sizeof(hidraw_disabledW
), (WCHAR
*)hidraw_disabledW
};
1204 static const WCHAR input_disabledW
[] = {'D','i','s','a','b','l','e','I','n','p','u','t',0};
1205 static const UNICODE_STRING input_disabled
= {sizeof(input_disabledW
) - sizeof(WCHAR
), sizeof(input_disabledW
), (WCHAR
*)input_disabledW
};
1207 TRACE("(%p, %s)\n", driver
, debugstr_w(registry_path
->Buffer
));
1209 if (!(udev_context
= udev_new()))
1211 ERR("Can't create udev object\n");
1212 return STATUS_UNSUCCESSFUL
;
1215 udev_driver_obj
= driver
;
1216 driver
->MajorFunction
[IRP_MJ_PNP
] = common_pnp_dispatch
;
1217 driver
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = hid_internal_dispatch
;
1219 disable_hidraw
= check_bus_option(registry_path
, &hidraw_disabled
, 0);
1221 TRACE("UDEV hidraw devices disabled in registry\n");
1223 #ifdef HAS_PROPER_INPUT_HEADER
1224 disable_input
= check_bus_option(registry_path
, &input_disabled
, 0);
1226 TRACE("UDEV input devices disabled in registry\n");
1229 if (!(events
[0] = CreateEventW(NULL
, TRUE
, FALSE
, NULL
)))
1231 if (!(events
[1] = CreateThread(NULL
, 0, deviceloop_thread
, events
[0], 0, NULL
)))
1233 CloseHandle(events
[0]);
1237 result
= WaitForMultipleObjects(2, events
, FALSE
, INFINITE
);
1238 CloseHandle(events
[0]);
1239 CloseHandle(events
[1]);
1240 if (result
== WAIT_OBJECT_0
)
1242 TRACE("Initialization successful\n");
1243 return STATUS_SUCCESS
;
1247 ERR("Failed to initialize udev device thread\n");
1248 udev_unref(udev_context
);
1249 udev_context
= NULL
;
1250 udev_driver_obj
= NULL
;
1251 return STATUS_UNSUCCESSFUL
;
1256 NTSTATUS WINAPI
udev_driver_init(DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry_path
)
1258 WARN("Wine was compiled without UDEV support\n");
1259 return STATUS_NOT_IMPLEMENTED
;
1262 #endif /* HAVE_UDEV */