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/heap.h"
69 #include "wine/unicode.h"
71 #ifdef HAS_PROPER_INPUT_HEADER
72 # include "hidusage.h"
75 #ifdef WORDS_BIGENDIAN
76 #define LE_WORD(x) RtlUshortByteSwap(x)
77 #define LE_DWORD(x) RtlUlongByteSwap(x)
79 #define LE_WORD(x) (x)
80 #define LE_DWORD(x) (x)
83 #include "controller.h"
86 WINE_DEFAULT_DEBUG_CHANNEL(plugplay
);
90 WINE_DECLARE_DEBUG_CHANNEL(hid_report
);
92 static struct udev
*udev_context
= NULL
;
93 static DWORD disable_hidraw
= 0;
94 static DWORD disable_input
= 0;
95 static HANDLE deviceloop_handle
;
96 static int deviceloop_control
[2];
98 static const WCHAR hidraw_busidW
[] = {'H','I','D','R','A','W',0};
99 static const WCHAR lnxev_busidW
[] = {'L','N','X','E','V',0};
101 struct platform_private
103 struct udev_device
*udev_device
;
106 HANDLE report_thread
;
110 static inline struct platform_private
*impl_from_DEVICE_OBJECT(DEVICE_OBJECT
*device
)
112 return (struct platform_private
*)get_platform_private(device
);
115 #ifdef HAS_PROPER_INPUT_HEADER
117 #include "psh_hid_macros.h"
119 static const BYTE REPORT_ABS_AXIS_TAIL
[] = {
120 LOGICAL_MINIMUM(4, /* placeholder */ 0x00000000),
121 LOGICAL_MAXIMUM(4, /* placeholder */ 0x000000ff),
122 PHYSICAL_MINIMUM(4, /* placeholder */ 0x00000000),
123 PHYSICAL_MAXIMUM(4, /* placeholder */ 0x000000ff),
125 REPORT_COUNT(1, /* placeholder */ 0),
126 INPUT(1, 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 #include "pop_hid_macros.h"
136 static const BYTE ABS_TO_HID_MAP
[][2] = {
137 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_X
}, /*ABS_X*/
138 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Y
}, /*ABS_Y*/
139 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Z
}, /*ABS_Z*/
140 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RX
}, /*ABS_RX*/
141 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RY
}, /*ABS_RY*/
142 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RZ
}, /*ABS_RZ*/
143 {HID_USAGE_PAGE_SIMULATION
, HID_USAGE_SIMULATION_THROTTLE
}, /*ABS_THROTTLE*/
144 {HID_USAGE_PAGE_SIMULATION
, HID_USAGE_SIMULATION_RUDDER
}, /*ABS_RUDDER*/
145 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_WHEEL
}, /*ABS_WHEEL*/
146 {HID_USAGE_PAGE_SIMULATION
, HID_USAGE_SIMULATION_ACCELERATOR
}, /*ABS_GAS*/
147 {HID_USAGE_PAGE_SIMULATION
, HID_USAGE_SIMULATION_BRAKE
}, /*ABS_BRAKE*/
161 {HID_USAGE_PAGE_DIGITIZER
, HID_USAGE_DIGITIZER_TIP_PRESSURE
}, /*ABS_PRESSURE*/
162 {0, 0}, /*ABS_DISTANCE*/
163 {HID_USAGE_PAGE_DIGITIZER
, HID_USAGE_DIGITIZER_X_TILT
}, /*ABS_TILT_X*/
164 {HID_USAGE_PAGE_DIGITIZER
, HID_USAGE_DIGITIZER_Y_TILT
}, /*ABS_TILT_Y*/
165 {0, 0}, /*ABS_TOOL_WIDTH*/
169 {HID_USAGE_PAGE_CONSUMER
, HID_USAGE_CONSUMER_VOLUME
} /*ABS_VOLUME*/
171 #define HID_ABS_MAX (ABS_VOLUME+1)
172 C_ASSERT(ARRAY_SIZE(ABS_TO_HID_MAP
) == HID_ABS_MAX
);
173 #define TOP_ABS_PAGE (HID_USAGE_PAGE_DIGITIZER+1)
175 static const BYTE REL_TO_HID_MAP
[][2] = {
176 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_X
}, /* REL_X */
177 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Y
}, /* REL_Y */
178 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_Z
}, /* REL_Z */
179 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RX
}, /* REL_RX */
180 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RY
}, /* REL_RY */
181 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_RZ
}, /* REL_RZ */
182 {0, 0}, /* REL_HWHEEL */
183 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_DIAL
}, /* REL_DIAL */
184 {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_WHEEL
}, /* REL_WHEEL */
185 {0, 0} /* REL_MISC */
188 #define HID_REL_MAX (REL_MISC+1)
189 #define TOP_REL_PAGE (HID_USAGE_PAGE_CONSUMER+1)
191 struct wine_input_absinfo
{
192 struct input_absinfo info
;
196 struct wine_input_private
{
197 struct platform_private base
;
200 BYTE
*last_report_buffer
;
201 BYTE
*current_report_buffer
;
202 enum { FIRST
, NORMAL
, DROPPED
} report_state
;
204 int report_descriptor_size
;
205 BYTE
*report_descriptor
;
208 BYTE button_map
[KEY_MAX
];
209 BYTE rel_map
[HID_REL_MAX
];
212 struct wine_input_absinfo abs_map
[HID_ABS_MAX
];
215 #define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
217 static BYTE
*add_axis_block(BYTE
*report_ptr
, BYTE count
, BYTE page
, BYTE
*usages
, BOOL absolute
, const struct wine_input_absinfo
*absinfo
)
220 memcpy(report_ptr
, REPORT_AXIS_HEADER
, sizeof(REPORT_AXIS_HEADER
));
221 report_ptr
[IDX_AXIS_PAGE
] = page
;
222 report_ptr
+= sizeof(REPORT_AXIS_HEADER
);
223 for (i
= 0; i
< count
; i
++)
225 memcpy(report_ptr
, REPORT_AXIS_USAGE
, sizeof(REPORT_AXIS_USAGE
));
226 report_ptr
[IDX_AXIS_USAGE
] = usages
[i
];
227 report_ptr
+= sizeof(REPORT_AXIS_USAGE
);
231 memcpy(report_ptr
, REPORT_ABS_AXIS_TAIL
, sizeof(REPORT_ABS_AXIS_TAIL
));
234 *((int*)&report_ptr
[IDX_ABS_LOG_MINIMUM
]) = LE_DWORD(absinfo
->info
.minimum
);
235 *((int*)&report_ptr
[IDX_ABS_LOG_MAXIMUM
]) = LE_DWORD(absinfo
->info
.maximum
);
236 *((int*)&report_ptr
[IDX_ABS_PHY_MINIMUM
]) = LE_DWORD(absinfo
->info
.minimum
);
237 *((int*)&report_ptr
[IDX_ABS_PHY_MAXIMUM
]) = LE_DWORD(absinfo
->info
.maximum
);
239 report_ptr
[IDX_ABS_AXIS_COUNT
] = count
;
240 report_ptr
+= sizeof(REPORT_ABS_AXIS_TAIL
);
244 memcpy(report_ptr
, REPORT_REL_AXIS_TAIL
, sizeof(REPORT_REL_AXIS_TAIL
));
245 report_ptr
[IDX_REL_AXIS_COUNT
] = count
;
246 report_ptr
+= sizeof(REPORT_REL_AXIS_TAIL
);
251 static const BYTE
* what_am_I(struct udev_device
*dev
)
253 static const BYTE Unknown
[2] = {HID_USAGE_PAGE_GENERIC
, 0};
254 static const BYTE Mouse
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_MOUSE
};
255 static const BYTE Keyboard
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_KEYBOARD
};
256 static const BYTE Gamepad
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_GAMEPAD
};
257 static const BYTE Keypad
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_KEYPAD
};
258 static const BYTE Tablet
[2] = {HID_USAGE_PAGE_DIGITIZER
, HID_USAGE_DIGITIZER_PEN
};
259 static const BYTE Touchscreen
[2] = {HID_USAGE_PAGE_DIGITIZER
, HID_USAGE_DIGITIZER_TOUCH_SCREEN
};
260 static const BYTE Touchpad
[2] = {HID_USAGE_PAGE_DIGITIZER
, HID_USAGE_DIGITIZER_TOUCH_PAD
};
262 struct udev_device
*parent
= dev
;
264 /* Look to the parents until we get a clue */
267 if (udev_device_get_property_value(parent
, "ID_INPUT_MOUSE"))
269 else if (udev_device_get_property_value(parent
, "ID_INPUT_KEYBOARD"))
271 else if (udev_device_get_property_value(parent
, "ID_INPUT_JOYSTICK"))
273 else if (udev_device_get_property_value(parent
, "ID_INPUT_KEY"))
275 else if (udev_device_get_property_value(parent
, "ID_INPUT_TOUCHPAD"))
277 else if (udev_device_get_property_value(parent
, "ID_INPUT_TOUCHSCREEN"))
279 else if (udev_device_get_property_value(parent
, "ID_INPUT_TABLET"))
282 parent
= udev_device_get_parent_with_subsystem_devtype(parent
, "input", NULL
);
287 static void set_button_value(int index
, int value
, BYTE
* buffer
)
289 int bindex
= index
/ 8;
295 buffer
[bindex
] = buffer
[bindex
] | mask
;
299 buffer
[bindex
] = buffer
[bindex
] & mask
;
303 static void set_abs_axis_value(struct wine_input_private
*ext
, int code
, int value
)
306 /* check for hatswitches */
307 if (code
<= ABS_HAT3Y
&& code
>= ABS_HAT0X
)
309 index
= code
- ABS_HAT0X
;
310 ext
->hat_values
[index
] = value
;
311 if ((code
- ABS_HAT0X
) % 2)
316 if (ext
->hat_values
[index
] == 0)
318 if (ext
->hat_values
[index
+1] == 0)
320 else if (ext
->hat_values
[index
+1] < 0)
325 else if (ext
->hat_values
[index
] > 0)
327 if (ext
->hat_values
[index
+1] == 0)
329 else if (ext
->hat_values
[index
+1] < 0)
336 if (ext
->hat_values
[index
+1] == 0)
338 else if (ext
->hat_values
[index
+1] < 0)
343 ext
->current_report_buffer
[ext
->hat_map
[index
]] = value
;
345 else if (code
< HID_ABS_MAX
&& ABS_TO_HID_MAP
[code
][0] != 0)
347 index
= ext
->abs_map
[code
].report_index
;
348 *((DWORD
*)&ext
->current_report_buffer
[index
]) = LE_DWORD(value
);
352 static void set_rel_axis_value(struct wine_input_private
*ext
, int code
, int value
)
355 if (code
< HID_REL_MAX
&& REL_TO_HID_MAP
[code
][0] != 0)
357 index
= ext
->rel_map
[code
];
358 if (value
> 127) value
= 127;
359 if (value
< -127) value
= -127;
360 ext
->current_report_buffer
[index
] = value
;
364 static INT
count_buttons(int device_fd
, BYTE
*map
)
367 int button_count
= 0;
368 BYTE keybits
[(KEY_MAX
+7)/8];
370 if (ioctl(device_fd
, EVIOCGBIT(EV_KEY
, sizeof(keybits
)), keybits
) == -1)
372 WARN("ioctl(EVIOCGBIT, EV_KEY) failed: %d %s\n", errno
, strerror(errno
));
376 for (i
= BTN_MISC
; i
< KEY_MAX
; i
++)
378 if (test_bit(keybits
, i
))
380 if (map
) map
[i
] = button_count
;
387 static INT
count_abs_axis(int device_fd
)
389 BYTE absbits
[(ABS_MAX
+7)/8];
393 if (ioctl(device_fd
, EVIOCGBIT(EV_ABS
, sizeof(absbits
)), absbits
) == -1)
395 WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno
, strerror(errno
));
399 for (i
= 0; i
< HID_ABS_MAX
; i
++)
400 if (test_bit(absbits
, i
) &&
401 (ABS_TO_HID_MAP
[i
][1] >= HID_USAGE_GENERIC_X
&&
402 ABS_TO_HID_MAP
[i
][1] <= HID_USAGE_GENERIC_WHEEL
))
407 static BOOL
build_report_descriptor(struct wine_input_private
*ext
, struct udev_device
*dev
)
409 int abs_pages
[TOP_ABS_PAGE
][HID_ABS_MAX
+1];
410 int rel_pages
[TOP_REL_PAGE
][HID_REL_MAX
+1];
411 BYTE absbits
[(ABS_MAX
+7)/8];
412 BYTE relbits
[(REL_MAX
+7)/8];
414 INT i
, descript_size
;
416 INT button_count
, abs_count
, rel_count
, hat_count
;
417 const BYTE
*device_usage
= what_am_I(dev
);
419 if (ioctl(ext
->base
.device_fd
, EVIOCGBIT(EV_REL
, sizeof(relbits
)), relbits
) == -1)
421 WARN("ioctl(EVIOCGBIT, EV_REL) failed: %d %s\n", errno
, strerror(errno
));
424 if (ioctl(ext
->base
.device_fd
, EVIOCGBIT(EV_ABS
, sizeof(absbits
)), absbits
) == -1)
426 WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno
, strerror(errno
));
430 descript_size
= sizeof(REPORT_HEADER
) + sizeof(REPORT_TAIL
);
434 memset(abs_pages
, 0, sizeof(abs_pages
));
435 for (i
= 0; i
< HID_ABS_MAX
; i
++)
436 if (test_bit(absbits
, i
))
438 abs_pages
[ABS_TO_HID_MAP
[i
][0]][0]++;
439 abs_pages
[ABS_TO_HID_MAP
[i
][0]][abs_pages
[ABS_TO_HID_MAP
[i
][0]][0]] = i
;
441 ioctl(ext
->base
.device_fd
, EVIOCGABS(i
), &(ext
->abs_map
[i
]));
443 /* Skip page 0, aka HID_USAGE_PAGE_UNDEFINED */
444 for (i
= 1; i
< TOP_ABS_PAGE
; i
++)
445 if (abs_pages
[i
][0] > 0)
448 descript_size
+= sizeof(REPORT_AXIS_USAGE
) * abs_pages
[i
][0];
449 for (j
= 1; j
<= abs_pages
[i
][0]; j
++)
451 ext
->abs_map
[abs_pages
[i
][j
]].report_index
= report_size
;
456 descript_size
+= sizeof(REPORT_AXIS_HEADER
) * abs_count
;
457 descript_size
+= sizeof(REPORT_ABS_AXIS_TAIL
) * abs_count
;
460 memset(rel_pages
, 0, sizeof(rel_pages
));
461 for (i
= 0; i
< HID_REL_MAX
; i
++)
462 if (test_bit(relbits
, i
))
464 rel_pages
[REL_TO_HID_MAP
[i
][0]][0]++;
465 rel_pages
[REL_TO_HID_MAP
[i
][0]][rel_pages
[REL_TO_HID_MAP
[i
][0]][0]] = i
;
467 /* Skip page 0, aka HID_USAGE_PAGE_UNDEFINED */
468 for (i
= 1; i
< TOP_REL_PAGE
; i
++)
469 if (rel_pages
[i
][0] > 0)
472 descript_size
+= sizeof(REPORT_AXIS_USAGE
) * rel_pages
[i
][0];
473 for (j
= 1; j
<= rel_pages
[i
][0]; j
++)
475 ext
->rel_map
[rel_pages
[i
][j
]] = report_size
;
480 descript_size
+= sizeof(REPORT_AXIS_HEADER
) * rel_count
;
481 descript_size
+= sizeof(REPORT_REL_AXIS_TAIL
) * rel_count
;
483 /* For now lump all buttons just into incremental usages, Ignore Keys */
484 ext
->button_start
= report_size
;
485 button_count
= count_buttons(ext
->base
.device_fd
, ext
->button_map
);
488 descript_size
+= sizeof(REPORT_BUTTONS
);
489 if (button_count
% 8)
490 descript_size
+= sizeof(REPORT_PADDING
);
491 report_size
+= (button_count
+ 7) / 8;
495 for (i
= ABS_HAT0X
; i
<=ABS_HAT3X
; i
+=2)
496 if (test_bit(absbits
, i
))
498 ext
->hat_map
[i
- ABS_HAT0X
] = report_size
;
499 ext
->hat_values
[i
- ABS_HAT0X
] = 0;
500 ext
->hat_values
[i
- ABS_HAT0X
+ 1] = 0;
505 descript_size
+= sizeof(REPORT_HATSWITCH
);
507 TRACE("Report Descriptor will be %i bytes\n", descript_size
);
508 TRACE("Report will be %i bytes\n", report_size
);
510 ext
->report_descriptor
= HeapAlloc(GetProcessHeap(), 0, descript_size
);
511 if (!ext
->report_descriptor
)
513 ERR("Failed to alloc report descriptor\n");
516 report_ptr
= ext
->report_descriptor
;
518 memcpy(report_ptr
, REPORT_HEADER
, sizeof(REPORT_HEADER
));
519 report_ptr
[IDX_HEADER_PAGE
] = device_usage
[0];
520 report_ptr
[IDX_HEADER_USAGE
] = device_usage
[1];
521 report_ptr
+= sizeof(REPORT_HEADER
);
524 for (i
= 1; i
< TOP_ABS_PAGE
; i
++)
528 BYTE usages
[HID_ABS_MAX
];
530 for (j
= 0; j
< abs_pages
[i
][0]; j
++)
531 usages
[j
] = ABS_TO_HID_MAP
[abs_pages
[i
][j
+1]][1];
532 report_ptr
= add_axis_block(report_ptr
, abs_pages
[i
][0], i
, usages
, TRUE
, &ext
->abs_map
[abs_pages
[i
][1]]);
538 for (i
= 1; i
< TOP_REL_PAGE
; i
++)
542 BYTE usages
[HID_REL_MAX
];
544 for (j
= 0; j
< rel_pages
[i
][0]; j
++)
545 usages
[j
] = REL_TO_HID_MAP
[rel_pages
[i
][j
+1]][1];
546 report_ptr
= add_axis_block(report_ptr
, rel_pages
[i
][0], i
, usages
, FALSE
, NULL
);
552 report_ptr
= add_button_block(report_ptr
, 1, button_count
);
553 if (button_count
% 8)
555 BYTE padding
= 8 - (button_count
% 8);
556 report_ptr
= add_padding_block(report_ptr
, padding
);
560 report_ptr
= add_hatswitch(report_ptr
, hat_count
);
562 memcpy(report_ptr
, REPORT_TAIL
, sizeof(REPORT_TAIL
));
564 ext
->report_descriptor_size
= descript_size
;
565 ext
->buffer_length
= report_size
;
566 ext
->current_report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, report_size
);
567 if (ext
->current_report_buffer
== NULL
)
569 ERR("Failed to alloc report buffer\n");
570 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
573 ext
->last_report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, report_size
);
574 if (ext
->last_report_buffer
== NULL
)
576 ERR("Failed to alloc report buffer\n");
577 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
578 HeapFree(GetProcessHeap(), 0, ext
->current_report_buffer
);
581 ext
->report_state
= FIRST
;
583 /* Initialize axis in the report */
584 for (i
= 0; i
< HID_ABS_MAX
; i
++)
585 if (test_bit(absbits
, i
))
586 set_abs_axis_value(ext
, i
, ext
->abs_map
[i
].info
.value
);
591 static BOOL
set_report_from_event(struct wine_input_private
*ext
, struct input_event
*ie
)
600 if (ext
->report_state
== NORMAL
)
602 memcpy(ext
->last_report_buffer
, ext
->current_report_buffer
, ext
->buffer_length
);
607 if (ext
->report_state
== DROPPED
)
608 memcpy(ext
->current_report_buffer
, ext
->last_report_buffer
, ext
->buffer_length
);
609 ext
->report_state
= NORMAL
;
613 TRACE_(hid_report
)("received SY_DROPPED\n");
614 ext
->report_state
= DROPPED
;
623 set_button_value(ext
->button_start
+ ext
->button_map
[ie
->code
], ie
->value
, ext
->current_report_buffer
);
626 set_abs_axis_value(ext
, ie
->code
, ie
->value
);
629 set_rel_axis_value(ext
, ie
->code
, ie
->value
);
632 ERR("TODO: Process Report (%i, %i)\n",ie
->type
, ie
->code
);
638 static inline WCHAR
*strdupAtoW(const char *src
)
642 if (!src
) return NULL
;
643 len
= MultiByteToWideChar(CP_UNIXCP
, 0, src
, -1, NULL
, 0);
644 if ((dst
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
645 MultiByteToWideChar(CP_UNIXCP
, 0, src
, -1, dst
, len
);
649 static WCHAR
*get_sysattr_string(struct udev_device
*dev
, const char *sysattr
)
651 const char *attr
= udev_device_get_sysattr_value(dev
, sysattr
);
654 WARN("Could not get %s from device\n", sysattr
);
657 return strdupAtoW(attr
);
660 static void hidraw_free_device(DEVICE_OBJECT
*device
)
662 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
664 if (private->report_thread
)
666 write(private->control_pipe
[1], "q", 1);
667 WaitForSingleObject(private->report_thread
, INFINITE
);
668 close(private->control_pipe
[0]);
669 close(private->control_pipe
[1]);
670 CloseHandle(private->report_thread
);
673 close(private->device_fd
);
674 udev_device_unref(private->udev_device
);
677 static int compare_platform_device(DEVICE_OBJECT
*device
, void *platform_dev
)
679 struct udev_device
*dev1
= impl_from_DEVICE_OBJECT(device
)->udev_device
;
680 struct udev_device
*dev2
= platform_dev
;
681 return strcmp(udev_device_get_syspath(dev1
), udev_device_get_syspath(dev2
));
684 static NTSTATUS
hidraw_get_reportdescriptor(DEVICE_OBJECT
*device
, BYTE
*buffer
, DWORD length
, DWORD
*out_length
)
686 #ifdef HAVE_LINUX_HIDRAW_H
687 struct hidraw_report_descriptor descriptor
;
688 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
690 if (ioctl(private->device_fd
, HIDIOCGRDESCSIZE
, &descriptor
.size
) == -1)
692 WARN("ioctl(HIDIOCGRDESCSIZE) failed: %d %s\n", errno
, strerror(errno
));
693 return STATUS_UNSUCCESSFUL
;
696 *out_length
= descriptor
.size
;
698 if (length
< descriptor
.size
)
699 return STATUS_BUFFER_TOO_SMALL
;
700 if (!descriptor
.size
)
701 return STATUS_SUCCESS
;
703 if (ioctl(private->device_fd
, HIDIOCGRDESC
, &descriptor
) == -1)
705 WARN("ioctl(HIDIOCGRDESC) failed: %d %s\n", errno
, strerror(errno
));
706 return STATUS_UNSUCCESSFUL
;
709 memcpy(buffer
, descriptor
.value
, descriptor
.size
);
710 return STATUS_SUCCESS
;
712 return STATUS_NOT_IMPLEMENTED
;
716 static NTSTATUS
hidraw_get_string(DEVICE_OBJECT
*device
, DWORD index
, WCHAR
*buffer
, DWORD length
)
718 struct udev_device
*usbdev
;
719 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
722 usbdev
= udev_device_get_parent_with_subsystem_devtype(private->udev_device
, "usb", "usb_device");
727 case HID_STRING_ID_IPRODUCT
:
728 str
= get_sysattr_string(usbdev
, "product");
730 case HID_STRING_ID_IMANUFACTURER
:
731 str
= get_sysattr_string(usbdev
, "manufacturer");
733 case HID_STRING_ID_ISERIALNUMBER
:
734 str
= get_sysattr_string(usbdev
, "serial");
737 ERR("Unhandled string index %08x\n", index
);
738 return STATUS_NOT_IMPLEMENTED
;
743 #ifdef HAVE_LINUX_HIDRAW_H
746 case HID_STRING_ID_IPRODUCT
:
749 if (ioctl(private->device_fd
, HIDIOCGRAWNAME(MAX_PATH
), buf
) == -1)
750 WARN("ioctl(HIDIOCGRAWNAME) failed: %d %s\n", errno
, strerror(errno
));
752 str
= strdupAtoW(buf
);
755 case HID_STRING_ID_IMANUFACTURER
:
757 case HID_STRING_ID_ISERIALNUMBER
:
760 ERR("Unhandled string index %08x\n", index
);
761 return STATUS_NOT_IMPLEMENTED
;
764 return STATUS_NOT_IMPLEMENTED
;
770 if (!length
) return STATUS_BUFFER_TOO_SMALL
;
772 return STATUS_SUCCESS
;
775 if (length
<= strlenW(str
))
777 HeapFree(GetProcessHeap(), 0, str
);
778 return STATUS_BUFFER_TOO_SMALL
;
781 strcpyW(buffer
, str
);
782 HeapFree(GetProcessHeap(), 0, str
);
783 return STATUS_SUCCESS
;
786 static DWORD CALLBACK
device_report_thread(void *args
)
788 DEVICE_OBJECT
*device
= (DEVICE_OBJECT
*)args
;
789 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
790 struct pollfd plfds
[2];
792 plfds
[0].fd
= private->device_fd
;
793 plfds
[0].events
= POLLIN
;
794 plfds
[0].revents
= 0;
795 plfds
[1].fd
= private->control_pipe
[0];
796 plfds
[1].events
= POLLIN
;
797 plfds
[1].revents
= 0;
802 BYTE report_buffer
[1024];
804 if (poll(plfds
, 2, -1) <= 0) continue;
805 if (plfds
[1].revents
)
807 size
= read(plfds
[0].fd
, report_buffer
, sizeof(report_buffer
));
809 TRACE_(hid_report
)("Read failed. Likely an unplugged device %d %s\n", errno
, strerror(errno
));
811 TRACE_(hid_report
)("Failed to read report\n");
813 process_hid_report(device
, report_buffer
, size
);
818 static NTSTATUS
begin_report_processing(DEVICE_OBJECT
*device
)
820 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
822 if (private->report_thread
)
823 return STATUS_SUCCESS
;
825 if (pipe(private->control_pipe
) != 0)
827 ERR("Control pipe creation failed\n");
828 return STATUS_UNSUCCESSFUL
;
831 private->report_thread
= CreateThread(NULL
, 0, device_report_thread
, device
, 0, NULL
);
832 if (!private->report_thread
)
834 ERR("Unable to create device report thread\n");
835 close(private->control_pipe
[0]);
836 close(private->control_pipe
[1]);
837 return STATUS_UNSUCCESSFUL
;
840 return STATUS_SUCCESS
;
843 static NTSTATUS
hidraw_set_output_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
845 struct platform_private
* ext
= impl_from_DEVICE_OBJECT(device
);
849 rc
= write(ext
->device_fd
, report
, length
);
852 BYTE report_buffer
[1024];
854 if (length
+ 1 > sizeof(report_buffer
))
856 ERR("Output report buffer too small\n");
857 return STATUS_UNSUCCESSFUL
;
860 report_buffer
[0] = 0;
861 memcpy(&report_buffer
[1], report
, length
);
862 rc
= write(ext
->device_fd
, report_buffer
, length
+ 1);
867 return STATUS_SUCCESS
;
871 TRACE("write failed: %d %d %s\n", rc
, errno
, strerror(errno
));
873 return STATUS_UNSUCCESSFUL
;
877 static NTSTATUS
hidraw_get_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*read
)
879 #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCGFEATURE)
881 struct platform_private
* ext
= impl_from_DEVICE_OBJECT(device
);
883 length
= min(length
, 0x1fff);
884 rc
= ioctl(ext
->device_fd
, HIDIOCGFEATURE(length
), report
);
888 return STATUS_SUCCESS
;
892 TRACE_(hid_report
)("ioctl(HIDIOCGFEATURE(%d)) failed: %d %s\n", length
, errno
, strerror(errno
));
894 return STATUS_UNSUCCESSFUL
;
898 return STATUS_NOT_IMPLEMENTED
;
902 static NTSTATUS
hidraw_set_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
904 #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCSFEATURE)
906 struct platform_private
* ext
= impl_from_DEVICE_OBJECT(device
);
907 BYTE
*feature_buffer
;
912 if (length
+ 1 > sizeof(buffer
))
914 ERR("Output feature buffer too small\n");
915 return STATUS_UNSUCCESSFUL
;
918 memcpy(&buffer
[1], report
, length
);
919 feature_buffer
= buffer
;
923 feature_buffer
= report
;
924 length
= min(length
, 0x1fff);
925 rc
= ioctl(ext
->device_fd
, HIDIOCSFEATURE(length
), feature_buffer
);
929 return STATUS_SUCCESS
;
933 TRACE_(hid_report
)("ioctl(HIDIOCSFEATURE(%d)) failed: %d %s\n", length
, errno
, strerror(errno
));
935 return STATUS_UNSUCCESSFUL
;
939 return STATUS_NOT_IMPLEMENTED
;
943 static const platform_vtbl hidraw_vtbl
=
946 compare_platform_device
,
947 hidraw_get_reportdescriptor
,
949 begin_report_processing
,
950 hidraw_set_output_report
,
951 hidraw_get_feature_report
,
952 hidraw_set_feature_report
,
955 #ifdef HAS_PROPER_INPUT_HEADER
957 static inline struct wine_input_private
*input_impl_from_DEVICE_OBJECT(DEVICE_OBJECT
*device
)
959 return (struct wine_input_private
*)get_platform_private(device
);
962 static void lnxev_free_device(DEVICE_OBJECT
*device
)
964 struct wine_input_private
*ext
= input_impl_from_DEVICE_OBJECT(device
);
966 if (ext
->base
.report_thread
)
968 write(ext
->base
.control_pipe
[1], "q", 1);
969 WaitForSingleObject(ext
->base
.report_thread
, INFINITE
);
970 close(ext
->base
.control_pipe
[0]);
971 close(ext
->base
.control_pipe
[1]);
972 CloseHandle(ext
->base
.report_thread
);
975 HeapFree(GetProcessHeap(), 0, ext
->current_report_buffer
);
976 HeapFree(GetProcessHeap(), 0, ext
->last_report_buffer
);
977 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
979 close(ext
->base
.device_fd
);
980 udev_device_unref(ext
->base
.udev_device
);
983 static NTSTATUS
lnxev_get_reportdescriptor(DEVICE_OBJECT
*device
, BYTE
*buffer
, DWORD length
, DWORD
*out_length
)
985 struct wine_input_private
*ext
= input_impl_from_DEVICE_OBJECT(device
);
987 *out_length
= ext
->report_descriptor_size
;
989 if (length
< ext
->report_descriptor_size
)
990 return STATUS_BUFFER_TOO_SMALL
;
992 memcpy(buffer
, ext
->report_descriptor
, ext
->report_descriptor_size
);
994 return STATUS_SUCCESS
;
997 static NTSTATUS
lnxev_get_string(DEVICE_OBJECT
*device
, DWORD index
, WCHAR
*buffer
, DWORD length
)
999 struct wine_input_private
*ext
= input_impl_from_DEVICE_OBJECT(device
);
1005 case HID_STRING_ID_IPRODUCT
:
1006 ioctl(ext
->base
.device_fd
, EVIOCGNAME(sizeof(str
)), str
);
1008 case HID_STRING_ID_IMANUFACTURER
:
1009 strcpy(str
,"evdev");
1011 case HID_STRING_ID_ISERIALNUMBER
:
1012 ioctl(ext
->base
.device_fd
, EVIOCGUNIQ(sizeof(str
)), str
);
1015 ERR("Unhandled string index %i\n", index
);
1018 MultiByteToWideChar(CP_ACP
, 0, str
, -1, buffer
, length
);
1019 return STATUS_SUCCESS
;
1022 static DWORD CALLBACK
lnxev_device_report_thread(void *args
)
1024 DEVICE_OBJECT
*device
= (DEVICE_OBJECT
*)args
;
1025 struct wine_input_private
*private = input_impl_from_DEVICE_OBJECT(device
);
1026 struct pollfd plfds
[2];
1028 plfds
[0].fd
= private->base
.device_fd
;
1029 plfds
[0].events
= POLLIN
;
1030 plfds
[0].revents
= 0;
1031 plfds
[1].fd
= private->base
.control_pipe
[0];
1032 plfds
[1].events
= POLLIN
;
1033 plfds
[1].revents
= 0;
1038 struct input_event ie
;
1040 if (poll(plfds
, 2, -1) <= 0) continue;
1041 if (plfds
[1].revents
|| !private->current_report_buffer
|| private->buffer_length
== 0)
1043 size
= read(plfds
[0].fd
, &ie
, sizeof(ie
));
1045 TRACE_(hid_report
)("Read failed. Likely an unplugged device\n");
1047 TRACE_(hid_report
)("Failed to read report\n");
1048 else if (set_report_from_event(private, &ie
))
1049 process_hid_report(device
, private->current_report_buffer
, private->buffer_length
);
1054 static NTSTATUS
lnxev_begin_report_processing(DEVICE_OBJECT
*device
)
1056 struct wine_input_private
*private = input_impl_from_DEVICE_OBJECT(device
);
1058 if (private->base
.report_thread
)
1059 return STATUS_SUCCESS
;
1061 if (pipe(private->base
.control_pipe
) != 0)
1063 ERR("Control pipe creation failed\n");
1064 return STATUS_UNSUCCESSFUL
;
1067 private->base
.report_thread
= CreateThread(NULL
, 0, lnxev_device_report_thread
, device
, 0, NULL
);
1068 if (!private->base
.report_thread
)
1070 ERR("Unable to create device report thread\n");
1071 close(private->base
.control_pipe
[0]);
1072 close(private->base
.control_pipe
[1]);
1073 return STATUS_UNSUCCESSFUL
;
1075 return STATUS_SUCCESS
;
1078 static NTSTATUS
lnxev_set_output_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
1081 return STATUS_NOT_IMPLEMENTED
;
1084 static NTSTATUS
lnxev_get_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*read
)
1087 return STATUS_NOT_IMPLEMENTED
;
1090 static NTSTATUS
lnxev_set_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
1093 return STATUS_NOT_IMPLEMENTED
;
1096 static const platform_vtbl lnxev_vtbl
= {
1098 compare_platform_device
,
1099 lnxev_get_reportdescriptor
,
1101 lnxev_begin_report_processing
,
1102 lnxev_set_output_report
,
1103 lnxev_get_feature_report
,
1104 lnxev_set_feature_report
,
1108 static int check_same_device(DEVICE_OBJECT
*device
, void* context
)
1110 return !compare_platform_device(device
, context
);
1113 static int parse_uevent_info(const char *uevent
, DWORD
*vendor_id
,
1114 DWORD
*product_id
, WORD
*input
, WCHAR
**serial_number
)
1118 char *saveptr
= NULL
;
1124 int found_serial
= 0;
1126 tmp
= heap_alloc(strlen(uevent
) + 1);
1127 strcpy(tmp
, uevent
);
1128 line
= strtok_r(tmp
, "\n", &saveptr
);
1129 while (line
!= NULL
)
1131 /* line: "KEY=value" */
1133 value
= strchr(line
, '=');
1141 if (strcmp(key
, "HID_ID") == 0)
1144 * type vendor product
1145 * HID_ID=0003:000005AC:00008242
1147 int ret
= sscanf(value
, "%x:%x:%x", &bus_type
, vendor_id
, product_id
);
1151 else if (strcmp(key
, "HID_UNIQ") == 0)
1153 /* The caller has to free the serial number */
1156 *serial_number
= strdupAtoW(value
);
1160 else if (strcmp(key
, "HID_PHYS") == 0)
1162 const char *input_no
= strstr(value
, "input");
1164 *input
= atoi(input_no
+5 );
1168 line
= strtok_r(NULL
, "\n", &saveptr
);
1172 return (found_id
&& found_serial
);
1175 static DWORD
a_to_bcd(const char *s
)
1179 int shift
= strlen(s
) - 1;
1180 for (c
= s
; *c
; ++c
)
1182 r
|= (*c
- '0') << (shift
* 4);
1188 static void try_add_device(struct udev_device
*dev
)
1190 DWORD vid
= 0, pid
= 0, version
= 0;
1191 struct udev_device
*hiddev
= NULL
, *walk_device
;
1192 DEVICE_OBJECT
*device
= NULL
;
1193 const char *subsystem
;
1194 const char *devnode
;
1195 WCHAR
*serial
= NULL
;
1196 BOOL is_gamepad
= FALSE
;
1199 static const CHAR
*base_serial
= "0000";
1201 if (!(devnode
= udev_device_get_devnode(dev
)))
1204 if ((fd
= open(devnode
, O_RDWR
)) == -1)
1206 WARN("Unable to open udev device %s: %s\n", debugstr_a(devnode
), strerror(errno
));
1210 subsystem
= udev_device_get_subsystem(dev
);
1211 hiddev
= udev_device_get_parent_with_subsystem_devtype(dev
, "hid", NULL
);
1214 const char *bcdDevice
= NULL
;
1215 #ifdef HAS_PROPER_INPUT_HEADER
1216 const platform_vtbl
*other_vtbl
= NULL
;
1217 DEVICE_OBJECT
*dup
= NULL
;
1218 if (strcmp(subsystem
, "hidraw") == 0)
1219 other_vtbl
= &lnxev_vtbl
;
1220 else if (strcmp(subsystem
, "input") == 0)
1221 other_vtbl
= &hidraw_vtbl
;
1224 dup
= bus_enumerate_hid_devices(other_vtbl
, check_same_device
, dev
);
1227 TRACE("Duplicate cross bus device (%p) found, not adding the new one\n", dup
);
1232 parse_uevent_info(udev_device_get_sysattr_value(hiddev
, "uevent"),
1233 &vid
, &pid
, &input
, &serial
);
1235 serial
= strdupAtoW(base_serial
);
1238 while (walk_device
&& !bcdDevice
)
1240 bcdDevice
= udev_device_get_sysattr_value(walk_device
, "bcdDevice");
1241 walk_device
= udev_device_get_parent(walk_device
);
1245 version
= a_to_bcd(bcdDevice
);
1248 #ifdef HAS_PROPER_INPUT_HEADER
1251 struct input_id device_id
= {0};
1252 char device_uid
[255];
1254 if (ioctl(fd
, EVIOCGID
, &device_id
) < 0)
1255 WARN("ioctl(EVIOCGID) failed: %d %s\n", errno
, strerror(errno
));
1257 if (ioctl(fd
, EVIOCGUNIQ(254), device_uid
) >= 0 && device_uid
[0])
1258 serial
= strdupAtoW(device_uid
);
1260 vid
= device_id
.vendor
;
1261 pid
= device_id
.product
;
1262 version
= device_id
.version
;
1266 WARN("Could not get device to query VID, PID, Version and Serial\n");
1269 if (is_xbox_gamepad(vid
, pid
))
1271 #ifdef HAS_PROPER_INPUT_HEADER
1274 int axes
=0, buttons
=0;
1275 axes
= count_abs_axis(fd
);
1276 buttons
= count_buttons(fd
, NULL
);
1277 is_gamepad
= (axes
== 6 && buttons
>= 14);
1280 if (input
== (WORD
)-1 && is_gamepad
)
1284 TRACE("Found udev device %s (vid %04x, pid %04x, version %u, serial %s)\n",
1285 debugstr_a(devnode
), vid
, pid
, version
, debugstr_w(serial
));
1287 if (strcmp(subsystem
, "hidraw") == 0)
1289 device
= bus_create_hid_device(hidraw_busidW
, vid
, pid
, input
, version
, 0, serial
, is_gamepad
,
1290 &hidraw_vtbl
, sizeof(struct platform_private
));
1292 #ifdef HAS_PROPER_INPUT_HEADER
1293 else if (strcmp(subsystem
, "input") == 0)
1295 device
= bus_create_hid_device(lnxev_busidW
, vid
, pid
, input
, version
, 0, serial
, is_gamepad
,
1296 &lnxev_vtbl
, sizeof(struct wine_input_private
));
1302 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
1303 private->udev_device
= udev_device_ref(dev
);
1304 private->device_fd
= fd
;
1305 #ifdef HAS_PROPER_INPUT_HEADER
1306 if (strcmp(subsystem
, "input") == 0)
1307 /* FIXME: We should probably move this to IRP_MN_START_DEVICE. */
1308 if (!build_report_descriptor((struct wine_input_private
*)private, dev
))
1310 ERR("Building report descriptor failed, removing device\n");
1312 udev_device_unref(dev
);
1313 bus_unlink_hid_device(device
);
1314 bus_remove_hid_device(device
);
1315 HeapFree(GetProcessHeap(), 0, serial
);
1319 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
1323 WARN("Ignoring device %s with subsystem %s\n", debugstr_a(devnode
), subsystem
);
1327 HeapFree(GetProcessHeap(), 0, serial
);
1330 static void try_remove_device(struct udev_device
*dev
)
1332 DEVICE_OBJECT
*device
= NULL
;
1334 device
= bus_find_hid_device(&hidraw_vtbl
, dev
);
1335 #ifdef HAS_PROPER_INPUT_HEADER
1337 device
= bus_find_hid_device(&lnxev_vtbl
, dev
);
1339 if (!device
) return;
1341 bus_unlink_hid_device(device
);
1342 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
1345 static void build_initial_deviceset(void)
1347 struct udev_enumerate
*enumerate
;
1348 struct udev_list_entry
*devices
, *dev_list_entry
;
1350 enumerate
= udev_enumerate_new(udev_context
);
1353 WARN("Unable to create udev enumeration object\n");
1357 if (!disable_hidraw
)
1358 if (udev_enumerate_add_match_subsystem(enumerate
, "hidraw") < 0)
1359 WARN("Failed to add subsystem 'hidraw' to enumeration\n");
1360 #ifdef HAS_PROPER_INPUT_HEADER
1363 if (udev_enumerate_add_match_subsystem(enumerate
, "input") < 0)
1364 WARN("Failed to add subsystem 'input' to enumeration\n");
1368 if (udev_enumerate_scan_devices(enumerate
) < 0)
1369 WARN("Enumeration scan failed\n");
1371 devices
= udev_enumerate_get_list_entry(enumerate
);
1372 udev_list_entry_foreach(dev_list_entry
, devices
)
1374 struct udev_device
*dev
;
1377 path
= udev_list_entry_get_name(dev_list_entry
);
1378 if ((dev
= udev_device_new_from_syspath(udev_context
, path
)))
1380 try_add_device(dev
);
1381 udev_device_unref(dev
);
1385 udev_enumerate_unref(enumerate
);
1388 static struct udev_monitor
*create_monitor(struct pollfd
*pfd
)
1390 struct udev_monitor
*monitor
;
1393 monitor
= udev_monitor_new_from_netlink(udev_context
, "udev");
1396 WARN("Unable to get udev monitor object\n");
1400 if (!disable_hidraw
)
1402 if (udev_monitor_filter_add_match_subsystem_devtype(monitor
, "hidraw", NULL
) < 0)
1403 WARN("Failed to add 'hidraw' subsystem to monitor\n");
1407 #ifdef HAS_PROPER_INPUT_HEADER
1410 if (udev_monitor_filter_add_match_subsystem_devtype(monitor
, "input", NULL
) < 0)
1411 WARN("Failed to add 'input' subsystem to monitor\n");
1418 WARN("No subsystems added to monitor\n");
1422 if (udev_monitor_enable_receiving(monitor
) < 0)
1425 if ((pfd
->fd
= udev_monitor_get_fd(monitor
)) >= 0)
1427 pfd
->events
= POLLIN
;
1432 WARN("Failed to start monitoring\n");
1433 udev_monitor_unref(monitor
);
1437 static void process_monitor_event(struct udev_monitor
*monitor
)
1439 struct udev_device
*dev
;
1442 dev
= udev_monitor_receive_device(monitor
);
1445 FIXME("Failed to get device that has changed\n");
1449 action
= udev_device_get_action(dev
);
1450 TRACE("Received action %s for udev device %s\n", debugstr_a(action
),
1451 debugstr_a(udev_device_get_devnode(dev
)));
1454 WARN("No action received\n");
1455 else if (strcmp(action
, "add") == 0)
1456 try_add_device(dev
);
1457 else if (strcmp(action
, "remove") == 0)
1458 try_remove_device(dev
);
1460 WARN("Unhandled action %s\n", debugstr_a(action
));
1462 udev_device_unref(dev
);
1465 static DWORD CALLBACK
deviceloop_thread(void *args
)
1467 struct udev_monitor
*monitor
;
1468 HANDLE init_done
= args
;
1469 struct pollfd pfd
[2];
1471 pfd
[1].fd
= deviceloop_control
[0];
1472 pfd
[1].events
= POLLIN
;
1475 monitor
= create_monitor(&pfd
[0]);
1476 build_initial_deviceset();
1477 SetEvent(init_done
);
1481 if (poll(pfd
, 2, -1) <= 0) continue;
1482 if (pfd
[1].revents
) break;
1483 process_monitor_event(monitor
);
1486 TRACE("Monitor thread exiting\n");
1488 udev_monitor_unref(monitor
);
1492 void udev_driver_unload( void )
1494 TRACE("Unload Driver\n");
1496 if (!deviceloop_handle
)
1499 write(deviceloop_control
[1], "q", 1);
1500 WaitForSingleObject(deviceloop_handle
, INFINITE
);
1501 close(deviceloop_control
[0]);
1502 close(deviceloop_control
[1]);
1503 CloseHandle(deviceloop_handle
);
1506 NTSTATUS
udev_driver_init(void)
1510 static const WCHAR hidraw_disabledW
[] = {'D','i','s','a','b','l','e','H','i','d','r','a','w',0};
1511 static const UNICODE_STRING hidraw_disabled
= {sizeof(hidraw_disabledW
) - sizeof(WCHAR
), sizeof(hidraw_disabledW
), (WCHAR
*)hidraw_disabledW
};
1512 static const WCHAR input_disabledW
[] = {'D','i','s','a','b','l','e','I','n','p','u','t',0};
1513 static const UNICODE_STRING input_disabled
= {sizeof(input_disabledW
) - sizeof(WCHAR
), sizeof(input_disabledW
), (WCHAR
*)input_disabledW
};
1515 if (pipe(deviceloop_control
) != 0)
1517 ERR("Control pipe creation failed\n");
1518 return STATUS_UNSUCCESSFUL
;
1521 if (!(udev_context
= udev_new()))
1523 ERR("Can't create udev object\n");
1527 disable_hidraw
= check_bus_option(&hidraw_disabled
, 0);
1529 TRACE("UDEV hidraw devices disabled in registry\n");
1531 #ifdef HAS_PROPER_INPUT_HEADER
1532 disable_input
= check_bus_option(&input_disabled
, 0);
1534 TRACE("UDEV input devices disabled in registry\n");
1537 if (!(events
[0] = CreateEventW(NULL
, TRUE
, FALSE
, NULL
)))
1539 if (!(events
[1] = CreateThread(NULL
, 0, deviceloop_thread
, events
[0], 0, NULL
)))
1541 CloseHandle(events
[0]);
1545 result
= WaitForMultipleObjects(2, events
, FALSE
, INFINITE
);
1546 CloseHandle(events
[0]);
1547 if (result
== WAIT_OBJECT_0
)
1549 deviceloop_handle
= events
[1];
1550 TRACE("Initialization successful\n");
1551 return STATUS_SUCCESS
;
1553 CloseHandle(events
[1]);
1556 ERR("Failed to initialize udev device thread\n");
1557 close(deviceloop_control
[0]);
1558 close(deviceloop_control
[1]);
1561 udev_unref(udev_context
);
1562 udev_context
= NULL
;
1564 return STATUS_UNSUCCESSFUL
;
1569 NTSTATUS
udev_driver_init(void)
1571 return STATUS_NOT_IMPLEMENTED
;
1574 void udev_driver_unload( void )
1576 TRACE("Stub: Unload Driver\n");
1579 #endif /* HAVE_UDEV */