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 #ifdef HAVE_SYS_POLL_H
34 # include <sys/poll.h>
39 #ifdef HAVE_LINUX_HIDRAW_H
40 # include <linux/hidraw.h>
42 #ifdef HAVE_SYS_IOCTL_H
43 # include <sys/ioctl.h>
46 #ifdef HAVE_LINUX_INPUT_H
47 # include <linux/input.h>
49 # if defined(EVIOCGBIT) && defined(EV_ABS) && defined(BTN_PINKIE)
50 # define HAS_PROPER_INPUT_HEADER
53 # define SYN_DROPPED 3
57 #define NONAMELESSUNION
60 #define WIN32_NO_STATUS
66 #include "ddk/hidtypes.h"
67 #include "wine/debug.h"
68 #include "wine/unicode.h"
70 #ifdef HAS_PROPER_INPUT_HEADER
71 # include "hidusage.h"
74 #ifdef WORDS_BIGENDIAN
75 #define LE_WORD(x) RtlUshortByteSwap(x)
76 #define LE_DWORD(x) RtlUlongByteSwap(x)
78 #define LE_WORD(x) (x)
79 #define LE_DWORD(x) (x)
82 #include "controller.h"
85 WINE_DEFAULT_DEBUG_CHANNEL(plugplay
);
89 WINE_DECLARE_DEBUG_CHANNEL(hid_report
);
91 static struct udev
*udev_context
= NULL
;
92 static DRIVER_OBJECT
*udev_driver_obj
= NULL
;
93 static DWORD disable_hidraw
= 0;
94 static DWORD disable_input
= 0;
96 static const WCHAR hidraw_busidW
[] = {'H','I','D','R','A','W',0};
97 static const WCHAR lnxev_busidW
[] = {'L','N','X','E','V',0};
100 DEFINE_GUID(GUID_DEVCLASS_HIDRAW
, 0x3def44ad,0x242e,0x46e5,0x82,0x6d,0x70,0x72,0x13,0xf3,0xaa,0x81);
101 DEFINE_GUID(GUID_DEVCLASS_LINUXEVENT
, 0x1b932c0d,0xfea7,0x42cd,0x8e,0xaa,0x0e,0x48,0x79,0xb6,0x9e,0xaa);
103 struct platform_private
105 struct udev_device
*udev_device
;
108 HANDLE report_thread
;
112 static inline struct platform_private
*impl_from_DEVICE_OBJECT(DEVICE_OBJECT
*device
)
114 return (struct platform_private
*)get_platform_private(device
);
117 #ifdef HAS_PROPER_INPUT_HEADER
119 static const BYTE REPORT_ABS_AXIS_TAIL
[] = {
120 0x17, 0x00, 0x00, 0x00, 0x00, /* LOGICAL_MINIMUM (0) */
121 0x27, 0xff, 0x00, 0x00, 0x00, /* LOGICAL_MAXIMUM (0xff) */
122 0x37, 0x00, 0x00, 0x00, 0x00, /* PHYSICAL_MINIMUM (0) */
123 0x47, 0xff, 0x00, 0x00, 0x00, /* PHYSICAL_MAXIMUM (256) */
124 0x75, 0x20, /* REPORT_SIZE (32) */
125 0x95, 0x00, /* REPORT_COUNT (2) */
126 0x81, 0x02, /* INPUT (Data,Var,Abs) */
128 #define IDX_ABS_LOG_MINIMUM 1
129 #define IDX_ABS_LOG_MAXIMUM 6
130 #define IDX_ABS_PHY_MINIMUM 11
131 #define IDX_ABS_PHY_MAXIMUM 16
132 #define IDX_ABS_AXIS_COUNT 23
134 static const BYTE ABS_TO_HID_MAP
[][2] = {
135 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_X
}, /*ABS_X*/
136 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Y
}, /*ABS_Y*/
137 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Z
}, /*ABS_Z*/
138 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RX
}, /*ABS_RX*/
139 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RY
}, /*ABS_RY*/
140 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RZ
}, /*ABS_RZ*/
141 {HID_USAGE_PAGE_SIMULATION
, HID_USAGE_SIMULATION_THROTTLE
}, /*ABS_THROTTLE*/
142 {HID_USAGE_PAGE_SIMULATION
, HID_USAGE_SIMULATION_RUDDER
}, /*ABS_RUDDER*/
143 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_WHEEL
}, /*ABS_WHEEL*/
144 {HID_USAGE_PAGE_SIMULATION
, 0xC4}, /*ABS_GAS*/
145 {HID_USAGE_PAGE_SIMULATION
, 0xC5}, /*ABS_BRAKE*/
154 {HID_USAGE_PAGE_DIGITIZER
, 0x30}, /*ABS_PRESSURE*/
155 {0, 0}, /*ABS_DISTANCE*/
156 {HID_USAGE_PAGE_DIGITIZER
, 0x3D}, /*ABS_TILT_X*/
157 {HID_USAGE_PAGE_DIGITIZER
, 0x3F}, /*ABS_TILT_Y*/
158 {0, 0}, /*ABS_TOOL_WIDTH*/
162 {HID_USAGE_PAGE_CONSUMER
, 0xE0} /*ABS_VOLUME*/
164 #define HID_ABS_MAX (ABS_VOLUME+1)
165 #define TOP_ABS_PAGE (HID_USAGE_PAGE_DIGITIZER+1)
167 static const BYTE REL_TO_HID_MAP
[][2] = {
168 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_X
}, /* REL_X */
169 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Y
}, /* REL_Y */
170 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Z
}, /* REL_Z */
171 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RX
}, /* REL_RX */
172 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RY
}, /* REL_RY */
173 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RZ
}, /* REL_RZ */
174 {0, 0}, /* REL_HWHEEL */
175 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_DIAL
}, /* REL_DIAL */
176 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_WHEEL
}, /* REL_WHEEL */
177 {0, 0} /* REL_MISC */
180 #define HID_REL_MAX (REL_MISC+1)
181 #define TOP_REL_PAGE (HID_USAGE_PAGE_CONSUMER+1)
183 struct wine_input_absinfo
{
184 struct input_absinfo info
;
188 struct wine_input_private
{
189 struct platform_private base
;
192 BYTE
*last_report_buffer
;
193 BYTE
*current_report_buffer
;
194 enum { FIRST
, NORMAL
, DROPPED
} report_state
;
196 int report_descriptor_size
;
197 BYTE
*report_descriptor
;
199 BYTE button_map
[KEY_MAX
];
200 BYTE rel_map
[HID_REL_MAX
];
203 struct wine_input_absinfo abs_map
[HID_ABS_MAX
];
206 #define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
208 static BYTE
*add_axis_block(BYTE
*report_ptr
, BYTE count
, BYTE page
, BYTE
*usages
, BOOL absolute
, const struct wine_input_absinfo
*absinfo
)
211 memcpy(report_ptr
, REPORT_AXIS_HEADER
, sizeof(REPORT_AXIS_HEADER
));
212 report_ptr
[IDX_AXIS_PAGE
] = page
;
213 report_ptr
+= sizeof(REPORT_AXIS_HEADER
);
214 for (i
= 0; i
< count
; i
++)
216 memcpy(report_ptr
, REPORT_AXIS_USAGE
, sizeof(REPORT_AXIS_USAGE
));
217 report_ptr
[IDX_AXIS_USAGE
] = usages
[i
];
218 report_ptr
+= sizeof(REPORT_AXIS_USAGE
);
222 memcpy(report_ptr
, REPORT_ABS_AXIS_TAIL
, sizeof(REPORT_ABS_AXIS_TAIL
));
225 *((int*)&report_ptr
[IDX_ABS_LOG_MINIMUM
]) = LE_DWORD(absinfo
->info
.minimum
);
226 *((int*)&report_ptr
[IDX_ABS_LOG_MAXIMUM
]) = LE_DWORD(absinfo
->info
.maximum
);
227 *((int*)&report_ptr
[IDX_ABS_PHY_MINIMUM
]) = LE_DWORD(absinfo
->info
.minimum
);
228 *((int*)&report_ptr
[IDX_ABS_PHY_MAXIMUM
]) = LE_DWORD(absinfo
->info
.maximum
);
230 report_ptr
[IDX_ABS_AXIS_COUNT
] = count
;
231 report_ptr
+= sizeof(REPORT_ABS_AXIS_TAIL
);
235 memcpy(report_ptr
, REPORT_REL_AXIS_TAIL
, sizeof(REPORT_REL_AXIS_TAIL
));
236 report_ptr
[IDX_REL_AXIS_COUNT
] = count
;
237 report_ptr
+= sizeof(REPORT_REL_AXIS_TAIL
);
242 static const BYTE
* what_am_I(struct udev_device
*dev
)
244 static const BYTE Unknown
[2] = {HID_USAGE_PAGE_GENERIC
, 0};
245 static const BYTE Mouse
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_MOUSE
};
246 static const BYTE Keyboard
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_KEYBOARD
};
247 static const BYTE Gamepad
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_GAMEPAD
};
248 static const BYTE Keypad
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_KEYPAD
};
249 static const BYTE Tablet
[2] = {HID_USAGE_PAGE_DIGITIZER
, 0x2};
250 static const BYTE Touchscreen
[2] = {HID_USAGE_PAGE_DIGITIZER
, 0x4};
251 static const BYTE Touchpad
[2] = {HID_USAGE_PAGE_DIGITIZER
, 0x5};
253 struct udev_device
*parent
= dev
;
255 /* Look to the parents until we get a clue */
258 if (udev_device_get_property_value(parent
, "ID_INPUT_MOUSE"))
260 else if (udev_device_get_property_value(parent
, "ID_INPUT_KEYBOARD"))
262 else if (udev_device_get_property_value(parent
, "ID_INPUT_JOYSTICK"))
264 else if (udev_device_get_property_value(parent
, "ID_INPUT_KEY"))
266 else if (udev_device_get_property_value(parent
, "ID_INPUT_TOUCHPAD"))
268 else if (udev_device_get_property_value(parent
, "ID_INPUT_TOUCHSCREEN"))
270 else if (udev_device_get_property_value(parent
, "ID_INPUT_TABLET"))
273 parent
= udev_device_get_parent_with_subsystem_devtype(parent
, "input", NULL
);
278 static void set_abs_axis_value(struct wine_input_private
*ext
, int code
, int value
)
281 /* check for hatswitches */
282 if (code
<= ABS_HAT3Y
&& code
>= ABS_HAT0X
)
284 index
= code
- ABS_HAT0X
;
285 ext
->hat_values
[index
] = value
;
286 if ((code
- ABS_HAT0X
) % 2)
288 if (ext
->hat_values
[index
] == 0)
290 if (ext
->hat_values
[index
+1] == 0)
292 else if (ext
->hat_values
[index
+1] < 0)
297 else if (ext
->hat_values
[index
] > 0)
299 if (ext
->hat_values
[index
+1] == 0)
301 else if (ext
->hat_values
[index
+1] < 0)
308 if (ext
->hat_values
[index
+1] == 0)
310 else if (ext
->hat_values
[index
+1] < 0)
315 ext
->current_report_buffer
[ext
->hat_map
[index
]] = value
;
317 else if (code
< HID_ABS_MAX
&& ABS_TO_HID_MAP
[code
][0] != 0)
319 index
= ext
->abs_map
[code
].report_index
;
320 *((DWORD
*)&ext
->current_report_buffer
[index
]) = LE_DWORD(value
);
324 static void set_rel_axis_value(struct wine_input_private
*ext
, int code
, int value
)
327 if (code
< HID_REL_MAX
&& REL_TO_HID_MAP
[code
][0] != 0)
329 index
= ext
->rel_map
[code
];
330 if (value
> 127) value
= 127;
331 if (value
< -127) value
= -127;
332 ext
->current_report_buffer
[index
] = value
;
336 static INT
count_buttons(int device_fd
, BYTE
*map
)
339 int button_count
= 0;
340 BYTE keybits
[(KEY_MAX
+7)/8];
342 if (ioctl(device_fd
, EVIOCGBIT(EV_KEY
, sizeof(keybits
)), keybits
) == -1)
344 WARN("ioctl(EVIOCGBIT, EV_KEY) failed: %d %s\n", errno
, strerror(errno
));
348 for (i
= BTN_MISC
; i
< KEY_MAX
; i
++)
350 if (test_bit(keybits
, i
))
352 if (map
) map
[i
] = button_count
;
359 static INT
count_abs_axis(int device_fd
)
361 BYTE absbits
[(ABS_MAX
+7)/8];
365 if (ioctl(device_fd
, EVIOCGBIT(EV_ABS
, sizeof(absbits
)), absbits
) == -1)
367 WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno
, strerror(errno
));
371 for (i
= 0; i
< HID_ABS_MAX
; i
++)
372 if (test_bit(absbits
, i
) &&
373 (ABS_TO_HID_MAP
[i
][1] >= HID_USAGE_GENERIC_X
&&
374 ABS_TO_HID_MAP
[i
][1] <= HID_USAGE_GENERIC_WHEEL
))
379 static BOOL
build_report_descriptor(struct wine_input_private
*ext
, struct udev_device
*dev
)
381 int abs_pages
[TOP_ABS_PAGE
][HID_ABS_MAX
+1];
382 int rel_pages
[TOP_REL_PAGE
][HID_REL_MAX
+1];
383 BYTE absbits
[(ABS_MAX
+7)/8];
384 BYTE relbits
[(REL_MAX
+7)/8];
386 INT i
, descript_size
;
388 INT button_count
, abs_count
, rel_count
, hat_count
;
389 const BYTE
*device_usage
= what_am_I(dev
);
391 if (ioctl(ext
->base
.device_fd
, EVIOCGBIT(EV_REL
, sizeof(relbits
)), relbits
) == -1)
393 WARN("ioctl(EVIOCGBIT, EV_REL) failed: %d %s\n", errno
, strerror(errno
));
396 if (ioctl(ext
->base
.device_fd
, EVIOCGBIT(EV_ABS
, sizeof(absbits
)), absbits
) == -1)
398 WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno
, strerror(errno
));
402 descript_size
= sizeof(REPORT_HEADER
) + sizeof(REPORT_TAIL
);
405 /* For now lump all buttons just into incremental usages, Ignore Keys */
406 button_count
= count_buttons(ext
->base
.device_fd
, ext
->button_map
);
409 descript_size
+= sizeof(REPORT_BUTTONS
);
410 if (button_count
% 8)
411 descript_size
+= sizeof(REPORT_PADDING
);
412 report_size
= (button_count
+ 7) / 8;
416 memset(abs_pages
, 0, sizeof(abs_pages
));
417 for (i
= 0; i
< HID_ABS_MAX
; i
++)
418 if (test_bit(absbits
, i
))
420 abs_pages
[ABS_TO_HID_MAP
[i
][0]][0]++;
421 abs_pages
[ABS_TO_HID_MAP
[i
][0]][abs_pages
[ABS_TO_HID_MAP
[i
][0]][0]] = i
;
423 ioctl(ext
->base
.device_fd
, EVIOCGABS(i
), &(ext
->abs_map
[i
]));
424 if (abs_pages
[ABS_TO_HID_MAP
[i
][0]][0] == 1)
426 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
427 descript_size
+= sizeof(REPORT_ABS_AXIS_TAIL
);
430 /* Skip page 0, aka HID_USAGE_PAGE_UNDEFINED */
431 for (i
= 1; i
< TOP_ABS_PAGE
; i
++)
432 if (abs_pages
[i
][0] > 0)
435 descript_size
+= sizeof(REPORT_AXIS_USAGE
) * abs_pages
[i
][0];
436 for (j
= 1; j
<= abs_pages
[i
][0]; j
++)
438 ext
->abs_map
[abs_pages
[i
][j
]].report_index
= report_size
;
445 memset(rel_pages
, 0, sizeof(rel_pages
));
446 for (i
= 0; i
< HID_REL_MAX
; i
++)
447 if (test_bit(relbits
, i
))
449 rel_pages
[REL_TO_HID_MAP
[i
][0]][0]++;
450 rel_pages
[REL_TO_HID_MAP
[i
][0]][rel_pages
[REL_TO_HID_MAP
[i
][0]][0]] = i
;
451 if (rel_pages
[REL_TO_HID_MAP
[i
][0]][0] == 1)
453 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
454 descript_size
+= sizeof(REPORT_REL_AXIS_TAIL
);
457 /* Skip page 0, aka HID_USAGE_PAGE_UNDEFINED */
458 for (i
= 1; i
< TOP_REL_PAGE
; i
++)
459 if (rel_pages
[i
][0] > 0)
462 descript_size
+= sizeof(REPORT_AXIS_USAGE
) * rel_pages
[i
][0];
463 for (j
= 1; j
<= rel_pages
[i
][0]; j
++)
465 ext
->rel_map
[rel_pages
[i
][j
]] = report_size
;
472 for (i
= ABS_HAT0X
; i
<=ABS_HAT3X
; i
+=2)
473 if (test_bit(absbits
, i
))
475 ext
->hat_map
[i
- ABS_HAT0X
] = report_size
;
476 ext
->hat_values
[i
- ABS_HAT0X
] = 0;
477 ext
->hat_values
[i
- ABS_HAT0X
+ 1] = 0;
482 TRACE("Report Descriptor will be %i bytes\n", descript_size
);
483 TRACE("Report will be %i bytes\n", report_size
);
485 ext
->report_descriptor
= HeapAlloc(GetProcessHeap(), 0, descript_size
);
486 if (!ext
->report_descriptor
)
488 ERR("Failed to alloc report descriptor\n");
491 report_ptr
= ext
->report_descriptor
;
493 memcpy(report_ptr
, REPORT_HEADER
, sizeof(REPORT_HEADER
));
494 report_ptr
[IDX_HEADER_PAGE
] = device_usage
[0];
495 report_ptr
[IDX_HEADER_USAGE
] = device_usage
[1];
496 report_ptr
+= sizeof(REPORT_HEADER
);
499 report_ptr
= add_button_block(report_ptr
, 1, button_count
);
500 if (button_count
% 8)
502 BYTE padding
= 8 - (button_count
% 8);
503 report_ptr
= add_padding_block(report_ptr
, padding
);
508 for (i
= 1; i
< TOP_ABS_PAGE
; i
++)
512 BYTE usages
[HID_ABS_MAX
];
514 for (j
= 0; j
< abs_pages
[i
][0]; j
++)
515 usages
[j
] = ABS_TO_HID_MAP
[abs_pages
[i
][j
+1]][1];
516 report_ptr
= add_axis_block(report_ptr
, abs_pages
[i
][0], i
, usages
, TRUE
, &ext
->abs_map
[abs_pages
[i
][1]]);
522 for (i
= 1; i
< TOP_REL_PAGE
; i
++)
526 BYTE usages
[HID_REL_MAX
];
528 for (j
= 0; j
< rel_pages
[i
][0]; j
++)
529 usages
[j
] = REL_TO_HID_MAP
[rel_pages
[i
][j
+1]][1];
530 report_ptr
= add_axis_block(report_ptr
, rel_pages
[i
][0], i
, usages
, FALSE
, NULL
);
535 report_ptr
= add_hatswitch(report_ptr
, hat_count
);
537 memcpy(report_ptr
, REPORT_TAIL
, sizeof(REPORT_TAIL
));
539 ext
->report_descriptor_size
= descript_size
;
540 ext
->buffer_length
= report_size
;
541 ext
->current_report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, report_size
);
542 if (ext
->current_report_buffer
== NULL
)
544 ERR("Failed to alloc report buffer\n");
545 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
548 ext
->last_report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, report_size
);
549 if (ext
->last_report_buffer
== NULL
)
551 ERR("Failed to alloc report buffer\n");
552 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
553 HeapFree(GetProcessHeap(), 0, ext
->current_report_buffer
);
556 ext
->report_state
= FIRST
;
558 /* Initialize axis in the report */
559 for (i
= 0; i
< HID_ABS_MAX
; i
++)
560 if (test_bit(absbits
, i
))
561 set_abs_axis_value(ext
, i
, ext
->abs_map
[i
].info
.value
);
566 static BOOL
set_report_from_event(struct wine_input_private
*ext
, struct input_event
*ie
)
575 if (ext
->report_state
== NORMAL
)
577 memcpy(ext
->last_report_buffer
, ext
->current_report_buffer
, ext
->buffer_length
);
582 if (ext
->report_state
== DROPPED
)
583 memcpy(ext
->current_report_buffer
, ext
->last_report_buffer
, ext
->buffer_length
);
584 ext
->report_state
= NORMAL
;
588 TRACE_(hid_report
)("received SY_DROPPED\n");
589 ext
->report_state
= DROPPED
;
598 set_button_value(ext
->button_map
[ie
->code
], ie
->value
, ext
->current_report_buffer
);
601 set_abs_axis_value(ext
, ie
->code
, ie
->value
);
604 set_rel_axis_value(ext
, ie
->code
, ie
->value
);
607 ERR("TODO: Process Report (%i, %i)\n",ie
->type
, ie
->code
);
613 static inline WCHAR
*strdupAtoW(const char *src
)
617 if (!src
) return NULL
;
618 len
= MultiByteToWideChar(CP_UNIXCP
, 0, src
, -1, NULL
, 0);
619 if ((dst
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
620 MultiByteToWideChar(CP_UNIXCP
, 0, src
, -1, dst
, len
);
624 static WCHAR
*get_sysattr_string(struct udev_device
*dev
, const char *sysattr
)
626 const char *attr
= udev_device_get_sysattr_value(dev
, sysattr
);
629 WARN("Could not get %s from device\n", sysattr
);
632 return strdupAtoW(attr
);
635 static int compare_platform_device(DEVICE_OBJECT
*device
, void *platform_dev
)
637 struct udev_device
*dev1
= impl_from_DEVICE_OBJECT(device
)->udev_device
;
638 struct udev_device
*dev2
= platform_dev
;
639 return strcmp(udev_device_get_syspath(dev1
), udev_device_get_syspath(dev2
));
642 static NTSTATUS
hidraw_get_reportdescriptor(DEVICE_OBJECT
*device
, BYTE
*buffer
, DWORD length
, DWORD
*out_length
)
644 #ifdef HAVE_LINUX_HIDRAW_H
645 struct hidraw_report_descriptor descriptor
;
646 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
648 if (ioctl(private->device_fd
, HIDIOCGRDESCSIZE
, &descriptor
.size
) == -1)
650 WARN("ioctl(HIDIOCGRDESCSIZE) failed: %d %s\n", errno
, strerror(errno
));
651 return STATUS_UNSUCCESSFUL
;
654 *out_length
= descriptor
.size
;
656 if (length
< descriptor
.size
)
657 return STATUS_BUFFER_TOO_SMALL
;
658 if (!descriptor
.size
)
659 return STATUS_SUCCESS
;
661 if (ioctl(private->device_fd
, HIDIOCGRDESC
, &descriptor
) == -1)
663 WARN("ioctl(HIDIOCGRDESC) failed: %d %s\n", errno
, strerror(errno
));
664 return STATUS_UNSUCCESSFUL
;
667 memcpy(buffer
, descriptor
.value
, descriptor
.size
);
668 return STATUS_SUCCESS
;
670 return STATUS_NOT_IMPLEMENTED
;
674 static NTSTATUS
hidraw_get_string(DEVICE_OBJECT
*device
, DWORD index
, WCHAR
*buffer
, DWORD length
)
676 struct udev_device
*hiddev
;
677 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
680 hiddev
= udev_device_get_parent_with_subsystem_devtype(private->udev_device
, "hid", NULL
);
685 case HID_STRING_ID_IPRODUCT
:
686 str
= get_sysattr_string(hiddev
, "product");
688 case HID_STRING_ID_IMANUFACTURER
:
689 str
= get_sysattr_string(hiddev
, "manufacturer");
691 case HID_STRING_ID_ISERIALNUMBER
:
692 str
= get_sysattr_string(hiddev
, "serial");
695 ERR("Unhandled string index %08x\n", index
);
696 return STATUS_NOT_IMPLEMENTED
;
701 #ifdef HAVE_LINUX_HIDRAW_H
704 case HID_STRING_ID_IPRODUCT
:
707 if (ioctl(private->device_fd
, HIDIOCGRAWNAME(MAX_PATH
), buf
) == -1)
708 WARN("ioctl(HIDIOCGRAWNAME) failed: %d %s\n", errno
, strerror(errno
));
710 str
= strdupAtoW(buf
);
713 case HID_STRING_ID_IMANUFACTURER
:
715 case HID_STRING_ID_ISERIALNUMBER
:
718 ERR("Unhandled string index %08x\n", index
);
719 return STATUS_NOT_IMPLEMENTED
;
722 return STATUS_NOT_IMPLEMENTED
;
728 if (!length
) return STATUS_BUFFER_TOO_SMALL
;
730 return STATUS_SUCCESS
;
733 if (length
<= strlenW(str
))
735 HeapFree(GetProcessHeap(), 0, str
);
736 return STATUS_BUFFER_TOO_SMALL
;
739 strcpyW(buffer
, str
);
740 HeapFree(GetProcessHeap(), 0, str
);
741 return STATUS_SUCCESS
;
744 static DWORD CALLBACK
device_report_thread(void *args
)
746 DEVICE_OBJECT
*device
= (DEVICE_OBJECT
*)args
;
747 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
748 struct pollfd plfds
[2];
750 plfds
[0].fd
= private->device_fd
;
751 plfds
[0].events
= POLLIN
;
752 plfds
[0].revents
= 0;
753 plfds
[1].fd
= private->control_pipe
[0];
754 plfds
[1].events
= POLLIN
;
755 plfds
[1].revents
= 0;
760 BYTE report_buffer
[1024];
762 if (poll(plfds
, 2, -1) <= 0) continue;
763 if (plfds
[1].revents
)
765 size
= read(plfds
[0].fd
, report_buffer
, sizeof(report_buffer
));
767 TRACE_(hid_report
)("Read failed. Likely an unplugged device\n");
769 TRACE_(hid_report
)("Failed to read report\n");
771 process_hid_report(device
, report_buffer
, size
);
776 static NTSTATUS
begin_report_processing(DEVICE_OBJECT
*device
)
778 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
780 if (private->report_thread
)
781 return STATUS_SUCCESS
;
783 if (pipe(private->control_pipe
) != 0)
785 ERR("Control pipe creation failed\n");
786 return STATUS_UNSUCCESSFUL
;
789 private->report_thread
= CreateThread(NULL
, 0, device_report_thread
, device
, 0, NULL
);
790 if (!private->report_thread
)
792 ERR("Unable to create device report thread\n");
793 close(private->control_pipe
[0]);
794 close(private->control_pipe
[1]);
795 return STATUS_UNSUCCESSFUL
;
798 return STATUS_SUCCESS
;
801 static NTSTATUS
hidraw_set_output_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
803 struct platform_private
* ext
= impl_from_DEVICE_OBJECT(device
);
807 rc
= write(ext
->device_fd
, report
, length
);
810 BYTE report_buffer
[1024];
812 if (length
+ 1 > sizeof(report_buffer
))
814 ERR("Output report buffer too small\n");
815 return STATUS_UNSUCCESSFUL
;
818 report_buffer
[0] = 0;
819 memcpy(&report_buffer
[1], report
, length
);
820 rc
= write(ext
->device_fd
, report_buffer
, length
+ 1);
825 return STATUS_SUCCESS
;
830 return STATUS_UNSUCCESSFUL
;
834 static NTSTATUS
hidraw_get_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*read
)
836 #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCGFEATURE)
838 struct platform_private
* ext
= impl_from_DEVICE_OBJECT(device
);
840 length
= min(length
, 0x1fff);
841 rc
= ioctl(ext
->device_fd
, HIDIOCGFEATURE(length
), report
);
845 return STATUS_SUCCESS
;
850 return STATUS_UNSUCCESSFUL
;
854 return STATUS_NOT_IMPLEMENTED
;
858 static NTSTATUS
hidraw_set_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
860 #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCSFEATURE)
862 struct platform_private
* ext
= impl_from_DEVICE_OBJECT(device
);
863 BYTE
*feature_buffer
;
868 if (length
+ 1 > sizeof(buffer
))
870 ERR("Output feature buffer too small\n");
871 return STATUS_UNSUCCESSFUL
;
874 memcpy(&buffer
[1], report
, length
);
875 feature_buffer
= buffer
;
879 feature_buffer
= report
;
880 length
= min(length
, 0x1fff);
881 rc
= ioctl(ext
->device_fd
, HIDIOCSFEATURE(length
), feature_buffer
);
885 return STATUS_SUCCESS
;
890 return STATUS_UNSUCCESSFUL
;
894 return STATUS_NOT_IMPLEMENTED
;
898 static const platform_vtbl hidraw_vtbl
=
900 compare_platform_device
,
901 hidraw_get_reportdescriptor
,
903 begin_report_processing
,
904 hidraw_set_output_report
,
905 hidraw_get_feature_report
,
906 hidraw_set_feature_report
,
909 #ifdef HAS_PROPER_INPUT_HEADER
911 static inline struct wine_input_private
*input_impl_from_DEVICE_OBJECT(DEVICE_OBJECT
*device
)
913 return (struct wine_input_private
*)get_platform_private(device
);
916 static NTSTATUS
lnxev_get_reportdescriptor(DEVICE_OBJECT
*device
, BYTE
*buffer
, DWORD length
, DWORD
*out_length
)
918 struct wine_input_private
*ext
= input_impl_from_DEVICE_OBJECT(device
);
920 *out_length
= ext
->report_descriptor_size
;
922 if (length
< ext
->report_descriptor_size
)
923 return STATUS_BUFFER_TOO_SMALL
;
925 memcpy(buffer
, ext
->report_descriptor
, ext
->report_descriptor_size
);
927 return STATUS_SUCCESS
;
930 static NTSTATUS
lnxev_get_string(DEVICE_OBJECT
*device
, DWORD index
, WCHAR
*buffer
, DWORD length
)
932 struct wine_input_private
*ext
= input_impl_from_DEVICE_OBJECT(device
);
938 case HID_STRING_ID_IPRODUCT
:
939 ioctl(ext
->base
.device_fd
, EVIOCGNAME(sizeof(str
)), str
);
941 case HID_STRING_ID_IMANUFACTURER
:
944 case HID_STRING_ID_ISERIALNUMBER
:
945 ioctl(ext
->base
.device_fd
, EVIOCGUNIQ(sizeof(str
)), str
);
948 ERR("Unhandled string index %i\n", index
);
951 MultiByteToWideChar(CP_ACP
, 0, str
, -1, buffer
, length
);
952 return STATUS_SUCCESS
;
955 static DWORD CALLBACK
lnxev_device_report_thread(void *args
)
957 DEVICE_OBJECT
*device
= (DEVICE_OBJECT
*)args
;
958 struct wine_input_private
*private = input_impl_from_DEVICE_OBJECT(device
);
959 struct pollfd plfds
[2];
961 plfds
[0].fd
= private->base
.device_fd
;
962 plfds
[0].events
= POLLIN
;
963 plfds
[0].revents
= 0;
964 plfds
[1].fd
= private->base
.control_pipe
[0];
965 plfds
[1].events
= POLLIN
;
966 plfds
[1].revents
= 0;
971 struct input_event ie
;
973 if (poll(plfds
, 2, -1) <= 0) continue;
974 if (plfds
[1].revents
|| !private->current_report_buffer
|| private->buffer_length
== 0)
976 size
= read(plfds
[0].fd
, &ie
, sizeof(ie
));
978 TRACE_(hid_report
)("Read failed. Likely an unplugged device\n");
980 TRACE_(hid_report
)("Failed to read report\n");
981 else if (set_report_from_event(private, &ie
))
982 process_hid_report(device
, private->current_report_buffer
, private->buffer_length
);
987 static NTSTATUS
lnxev_begin_report_processing(DEVICE_OBJECT
*device
)
989 struct wine_input_private
*private = input_impl_from_DEVICE_OBJECT(device
);
991 if (private->base
.report_thread
)
992 return STATUS_SUCCESS
;
994 if (pipe(private->base
.control_pipe
) != 0)
996 ERR("Control pipe creation failed\n");
997 return STATUS_UNSUCCESSFUL
;
1000 private->base
.report_thread
= CreateThread(NULL
, 0, lnxev_device_report_thread
, device
, 0, NULL
);
1001 if (!private->base
.report_thread
)
1003 ERR("Unable to create device report thread\n");
1004 close(private->base
.control_pipe
[0]);
1005 close(private->base
.control_pipe
[1]);
1006 return STATUS_UNSUCCESSFUL
;
1008 return STATUS_SUCCESS
;
1011 static NTSTATUS
lnxev_set_output_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
1014 return STATUS_NOT_IMPLEMENTED
;
1017 static NTSTATUS
lnxev_get_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*read
)
1020 return STATUS_NOT_IMPLEMENTED
;
1023 static NTSTATUS
lnxev_set_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
1026 return STATUS_NOT_IMPLEMENTED
;
1029 static const platform_vtbl lnxev_vtbl
= {
1030 compare_platform_device
,
1031 lnxev_get_reportdescriptor
,
1033 lnxev_begin_report_processing
,
1034 lnxev_set_output_report
,
1035 lnxev_get_feature_report
,
1036 lnxev_set_feature_report
,
1040 static int check_same_device(DEVICE_OBJECT
*device
, void* context
)
1042 return !compare_platform_device(device
, context
);
1045 static int parse_uevent_info(const char *uevent
, DWORD
*vendor_id
,
1046 DWORD
*product_id
, WCHAR
**serial_number
)
1049 char *tmp
= strdup(uevent
);
1050 char *saveptr
= NULL
;
1056 int found_serial
= 0;
1058 line
= strtok_r(tmp
, "\n", &saveptr
);
1059 while (line
!= NULL
)
1061 /* line: "KEY=value" */
1063 value
= strchr(line
, '=');
1071 if (strcmp(key
, "HID_ID") == 0)
1074 * type vendor product
1075 * HID_ID=0003:000005AC:00008242
1077 int ret
= sscanf(value
, "%x:%x:%x", &bus_type
, vendor_id
, product_id
);
1081 else if (strcmp(key
, "HID_UNIQ") == 0)
1083 /* The caller has to free the serial number */
1086 *serial_number
= (WCHAR
*)strdupAtoW(value
);
1092 line
= strtok_r(NULL
, "\n", &saveptr
);
1096 return (found_id
&& found_serial
);
1099 static void try_add_device(struct udev_device
*dev
)
1101 DWORD vid
= 0, pid
= 0, version
= 0;
1102 struct udev_device
*hiddev
= NULL
;
1103 DEVICE_OBJECT
*device
= NULL
;
1104 const char *subsystem
;
1105 const char *devnode
;
1106 WCHAR
*serial
= NULL
;
1107 BOOL is_gamepad
= FALSE
;
1109 static const CHAR
*base_serial
= "0000";
1111 if (!(devnode
= udev_device_get_devnode(dev
)))
1114 if ((fd
= open(devnode
, O_RDWR
)) == -1)
1116 WARN("Unable to open udev device %s: %s\n", debugstr_a(devnode
), strerror(errno
));
1120 subsystem
= udev_device_get_subsystem(dev
);
1121 hiddev
= udev_device_get_parent_with_subsystem_devtype(dev
, "hid", NULL
);
1124 #ifdef HAS_PROPER_INPUT_HEADER
1125 const platform_vtbl
*other_vtbl
= NULL
;
1126 DEVICE_OBJECT
*dup
= NULL
;
1127 if (strcmp(subsystem
, "hidraw") == 0)
1128 other_vtbl
= &lnxev_vtbl
;
1129 else if (strcmp(subsystem
, "input") == 0)
1130 other_vtbl
= &hidraw_vtbl
;
1133 dup
= bus_enumerate_hid_devices(other_vtbl
, check_same_device
, dev
);
1136 TRACE("Duplicate cross bus device (%p) found, not adding the new one\n", dup
);
1141 parse_uevent_info(udev_device_get_sysattr_value(hiddev
, "uevent"),
1142 &vid
, &pid
, &serial
);
1144 serial
= strdupAtoW(base_serial
);
1146 #ifdef HAS_PROPER_INPUT_HEADER
1149 struct input_id device_id
= {0};
1150 char device_uid
[255];
1152 if (ioctl(fd
, EVIOCGID
, &device_id
) < 0)
1153 WARN("ioctl(EVIOCGID) failed: %d %s\n", errno
, strerror(errno
));
1155 if (ioctl(fd
, EVIOCGUNIQ(254), device_uid
) >= 0 && device_uid
[0])
1156 serial
= strdupAtoW(device_uid
);
1158 vid
= device_id
.vendor
;
1159 pid
= device_id
.product
;
1160 version
= device_id
.version
;
1164 WARN("Could not get device to query VID, PID, Version and Serial\n");
1167 if (is_xbox_gamepad(vid
, pid
))
1169 #ifdef HAS_PROPER_INPUT_HEADER
1172 int axes
=0, buttons
=0;
1173 axes
= count_abs_axis(fd
);
1174 buttons
= count_buttons(fd
, NULL
);
1175 is_gamepad
= (axes
== 6 && buttons
>= 14);
1180 TRACE("Found udev device %s (vid %04x, pid %04x, version %u, serial %s)\n",
1181 debugstr_a(devnode
), vid
, pid
, version
, debugstr_w(serial
));
1183 if (strcmp(subsystem
, "hidraw") == 0)
1185 device
= bus_create_hid_device(udev_driver_obj
, hidraw_busidW
, vid
, pid
, version
, 0, serial
, is_gamepad
,
1186 &GUID_DEVCLASS_HIDRAW
, &hidraw_vtbl
, sizeof(struct platform_private
));
1188 #ifdef HAS_PROPER_INPUT_HEADER
1189 else if (strcmp(subsystem
, "input") == 0)
1191 device
= bus_create_hid_device(udev_driver_obj
, lnxev_busidW
, vid
, pid
, version
, 0, serial
, is_gamepad
,
1192 &GUID_DEVCLASS_LINUXEVENT
, &lnxev_vtbl
, sizeof(struct wine_input_private
));
1198 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
1199 private->udev_device
= udev_device_ref(dev
);
1200 private->device_fd
= fd
;
1201 #ifdef HAS_PROPER_INPUT_HEADER
1202 if (strcmp(subsystem
, "input") == 0)
1203 if (!build_report_descriptor((struct wine_input_private
*)private, dev
))
1205 ERR("Building report descriptor failed, removing device\n");
1207 udev_device_unref(dev
);
1208 bus_remove_hid_device(device
);
1209 HeapFree(GetProcessHeap(), 0, serial
);
1213 IoInvalidateDeviceRelations(device
, BusRelations
);
1217 WARN("Ignoring device %s with subsystem %s\n", debugstr_a(devnode
), subsystem
);
1221 HeapFree(GetProcessHeap(), 0, serial
);
1224 static void try_remove_device(struct udev_device
*dev
)
1226 DEVICE_OBJECT
*device
= NULL
;
1227 struct platform_private
* private;
1228 #ifdef HAS_PROPER_INPUT_HEADER
1229 BOOL is_input
= FALSE
;
1232 device
= bus_find_hid_device(&hidraw_vtbl
, dev
);
1233 #ifdef HAS_PROPER_INPUT_HEADER
1236 device
= bus_find_hid_device(&lnxev_vtbl
, dev
);
1240 if (!device
) return;
1242 IoInvalidateDeviceRelations(device
, RemovalRelations
);
1244 private = impl_from_DEVICE_OBJECT(device
);
1246 if (private->report_thread
)
1248 write(private->control_pipe
[1], "q", 1);
1249 WaitForSingleObject(private->report_thread
, INFINITE
);
1250 close(private->control_pipe
[0]);
1251 close(private->control_pipe
[1]);
1252 CloseHandle(private->report_thread
);
1253 #ifdef HAS_PROPER_INPUT_HEADER
1254 if (strcmp(udev_device_get_subsystem(dev
), "input") == 0)
1256 HeapFree(GetProcessHeap(), 0, ((struct wine_input_private
*)private)->current_report_buffer
);
1257 HeapFree(GetProcessHeap(), 0, ((struct wine_input_private
*)private)->last_report_buffer
);
1262 #ifdef HAS_PROPER_INPUT_HEADER
1265 struct wine_input_private
*ext
= (struct wine_input_private
*)private;
1266 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
1270 dev
= private->udev_device
;
1271 close(private->device_fd
);
1272 bus_remove_hid_device(device
);
1273 udev_device_unref(dev
);
1276 static void build_initial_deviceset(void)
1278 struct udev_enumerate
*enumerate
;
1279 struct udev_list_entry
*devices
, *dev_list_entry
;
1281 enumerate
= udev_enumerate_new(udev_context
);
1284 WARN("Unable to create udev enumeration object\n");
1288 if (!disable_hidraw
)
1289 if (udev_enumerate_add_match_subsystem(enumerate
, "hidraw") < 0)
1290 WARN("Failed to add subsystem 'hidraw' to enumeration\n");
1291 #ifdef HAS_PROPER_INPUT_HEADER
1294 if (udev_enumerate_add_match_subsystem(enumerate
, "input") < 0)
1295 WARN("Failed to add subsystem 'input' to enumeration\n");
1299 if (udev_enumerate_scan_devices(enumerate
) < 0)
1300 WARN("Enumeration scan failed\n");
1302 devices
= udev_enumerate_get_list_entry(enumerate
);
1303 udev_list_entry_foreach(dev_list_entry
, devices
)
1305 struct udev_device
*dev
;
1308 path
= udev_list_entry_get_name(dev_list_entry
);
1309 if ((dev
= udev_device_new_from_syspath(udev_context
, path
)))
1311 try_add_device(dev
);
1312 udev_device_unref(dev
);
1316 udev_enumerate_unref(enumerate
);
1319 static struct udev_monitor
*create_monitor(struct pollfd
*pfd
)
1321 struct udev_monitor
*monitor
;
1324 monitor
= udev_monitor_new_from_netlink(udev_context
, "udev");
1327 WARN("Unable to get udev monitor object\n");
1331 if (!disable_hidraw
)
1333 if (udev_monitor_filter_add_match_subsystem_devtype(monitor
, "hidraw", NULL
) < 0)
1334 WARN("Failed to add 'hidraw' subsystem to monitor\n");
1338 #ifdef HAS_PROPER_INPUT_HEADER
1341 if (udev_monitor_filter_add_match_subsystem_devtype(monitor
, "input", NULL
) < 0)
1342 WARN("Failed to add 'input' subsystem to monitor\n");
1349 WARN("No subsystems added to monitor\n");
1353 if (udev_monitor_enable_receiving(monitor
) < 0)
1356 if ((pfd
->fd
= udev_monitor_get_fd(monitor
)) >= 0)
1358 pfd
->events
= POLLIN
;
1363 WARN("Failed to start monitoring\n");
1364 udev_monitor_unref(monitor
);
1368 static void process_monitor_event(struct udev_monitor
*monitor
)
1370 struct udev_device
*dev
;
1373 dev
= udev_monitor_receive_device(monitor
);
1376 FIXME("Failed to get device that has changed\n");
1380 action
= udev_device_get_action(dev
);
1381 TRACE("Received action %s for udev device %s\n", debugstr_a(action
),
1382 debugstr_a(udev_device_get_devnode(dev
)));
1385 WARN("No action received\n");
1386 else if (strcmp(action
, "add") == 0)
1387 try_add_device(dev
);
1388 else if (strcmp(action
, "remove") == 0)
1389 try_remove_device(dev
);
1391 WARN("Unhandled action %s\n", debugstr_a(action
));
1393 udev_device_unref(dev
);
1396 static DWORD CALLBACK
deviceloop_thread(void *args
)
1398 struct udev_monitor
*monitor
;
1399 HANDLE init_done
= args
;
1402 monitor
= create_monitor(&pfd
);
1403 build_initial_deviceset();
1404 SetEvent(init_done
);
1408 if (poll(&pfd
, 1, -1) <= 0) continue;
1409 process_monitor_event(monitor
);
1412 TRACE("Monitor thread exiting\n");
1414 udev_monitor_unref(monitor
);
1418 NTSTATUS WINAPI
udev_driver_init(DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry_path
)
1422 static const WCHAR hidraw_disabledW
[] = {'D','i','s','a','b','l','e','H','i','d','r','a','w',0};
1423 static const UNICODE_STRING hidraw_disabled
= {sizeof(hidraw_disabledW
) - sizeof(WCHAR
), sizeof(hidraw_disabledW
), (WCHAR
*)hidraw_disabledW
};
1424 static const WCHAR input_disabledW
[] = {'D','i','s','a','b','l','e','I','n','p','u','t',0};
1425 static const UNICODE_STRING input_disabled
= {sizeof(input_disabledW
) - sizeof(WCHAR
), sizeof(input_disabledW
), (WCHAR
*)input_disabledW
};
1427 TRACE("(%p, %s)\n", driver
, debugstr_w(registry_path
->Buffer
));
1429 if (!(udev_context
= udev_new()))
1431 ERR("Can't create udev object\n");
1432 return STATUS_UNSUCCESSFUL
;
1435 udev_driver_obj
= driver
;
1436 driver
->MajorFunction
[IRP_MJ_PNP
] = common_pnp_dispatch
;
1437 driver
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = hid_internal_dispatch
;
1439 disable_hidraw
= check_bus_option(registry_path
, &hidraw_disabled
, 0);
1441 TRACE("UDEV hidraw devices disabled in registry\n");
1443 #ifdef HAS_PROPER_INPUT_HEADER
1444 disable_input
= check_bus_option(registry_path
, &input_disabled
, 0);
1446 TRACE("UDEV input devices disabled in registry\n");
1449 if (!(events
[0] = CreateEventW(NULL
, TRUE
, FALSE
, NULL
)))
1451 if (!(events
[1] = CreateThread(NULL
, 0, deviceloop_thread
, events
[0], 0, NULL
)))
1453 CloseHandle(events
[0]);
1457 result
= WaitForMultipleObjects(2, events
, FALSE
, INFINITE
);
1458 CloseHandle(events
[0]);
1459 CloseHandle(events
[1]);
1460 if (result
== WAIT_OBJECT_0
)
1462 TRACE("Initialization successful\n");
1463 return STATUS_SUCCESS
;
1467 ERR("Failed to initialize udev device thread\n");
1468 udev_unref(udev_context
);
1469 udev_context
= NULL
;
1470 udev_driver_obj
= NULL
;
1471 return STATUS_UNSUCCESSFUL
;
1476 NTSTATUS WINAPI
udev_driver_init(DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry_path
)
1478 WARN("Wine was compiled without UDEV support\n");
1479 return STATUS_NOT_IMPLEMENTED
;
1482 #endif /* HAVE_UDEV */