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 #include <sys/types.h>
36 #include <sys/ioctl.h>
40 #ifdef HAVE_LINUX_HIDRAW_H
41 # include <linux/hidraw.h>
43 #ifdef HAVE_SYS_INOTIFY_H
44 # include <sys/inotify.h>
48 #ifdef HAVE_LINUX_INPUT_H
49 # include <linux/input.h>
51 # if defined(EVIOCGBIT) && defined(EV_ABS) && defined(BTN_PINKIE)
52 # define HAS_PROPER_INPUT_HEADER
55 # define SYN_DROPPED 3
60 # define BUS_BLUETOOTH 5
66 #define WIN32_NO_STATUS
72 #include "ddk/hidtypes.h"
73 #include "ddk/hidsdi.h"
75 #include "wine/debug.h"
77 #include "wine/unixlib.h"
79 #ifdef HAS_PROPER_INPUT_HEADER
80 # include "hidusage.h"
83 #ifdef WORDS_BIGENDIAN
84 #define LE_DWORD(x) RtlUlongByteSwap(x)
86 #define LE_DWORD(x) (x)
89 #include "unix_private.h"
91 WINE_DEFAULT_DEBUG_CHANNEL(hid
);
95 static pthread_mutex_t udev_cs
= PTHREAD_MUTEX_INITIALIZER
;
97 static struct udev
*udev_context
= NULL
;
98 static struct udev_monitor
*udev_monitor
;
99 static int deviceloop_control
[2];
100 static struct list event_queue
= LIST_INIT(event_queue
);
101 static struct list device_list
= LIST_INIT(device_list
);
102 static struct udev_bus_options options
;
106 struct unix_device unix_device
;
107 void (*read_report
)(struct unix_device
*iface
);
109 struct udev_device
*udev_device
;
110 char devnode
[MAX_PATH
];
114 static inline struct base_device
*impl_from_unix_device(struct unix_device
*iface
)
116 return CONTAINING_RECORD(iface
, struct base_device
, unix_device
);
119 #define QUIRK_DS4_BT 0x1
120 #define QUIRK_DUALSENSE_BT 0x2
124 struct base_device base
;
128 static inline struct hidraw_device
*hidraw_impl_from_unix_device(struct unix_device
*iface
)
130 return CONTAINING_RECORD(impl_from_unix_device(iface
), struct hidraw_device
, base
);
133 #ifdef HAS_PROPER_INPUT_HEADER
135 static const USAGE_AND_PAGE absolute_usages
[] =
137 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_X
}, /* ABS_X */
138 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_Y
}, /* ABS_Y */
139 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_Z
}, /* ABS_Z */
140 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_RX
}, /* ABS_RX */
141 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_RY
}, /* ABS_RY */
142 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_RZ
}, /* ABS_RZ */
143 {.UsagePage
= HID_USAGE_PAGE_SIMULATION
, .Usage
= HID_USAGE_SIMULATION_THROTTLE
}, /* ABS_THROTTLE */
144 {.UsagePage
= HID_USAGE_PAGE_SIMULATION
, .Usage
= HID_USAGE_SIMULATION_RUDDER
}, /* ABS_RUDDER */
145 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_WHEEL
}, /* ABS_WHEEL */
146 {.UsagePage
= HID_USAGE_PAGE_SIMULATION
, .Usage
= HID_USAGE_SIMULATION_ACCELERATOR
}, /* ABS_GAS */
147 {.UsagePage
= HID_USAGE_PAGE_SIMULATION
, .Usage
= HID_USAGE_SIMULATION_BRAKE
}, /* ABS_BRAKE */
161 {.UsagePage
= HID_USAGE_PAGE_DIGITIZER
, .Usage
= HID_USAGE_DIGITIZER_TIP_PRESSURE
}, /* ABS_PRESSURE */
162 {0}, /* ABS_DISTANCE */
163 {.UsagePage
= HID_USAGE_PAGE_DIGITIZER
, .Usage
= HID_USAGE_DIGITIZER_X_TILT
}, /* ABS_TILT_X */
164 {.UsagePage
= HID_USAGE_PAGE_DIGITIZER
, .Usage
= HID_USAGE_DIGITIZER_Y_TILT
}, /* ABS_TILT_Y */
165 {0}, /* ABS_TOOL_WIDTH */
169 {.UsagePage
= HID_USAGE_PAGE_CONSUMER
, .Usage
= HID_USAGE_CONSUMER_VOLUME
}, /* ABS_VOLUME */
172 static const USAGE_AND_PAGE relative_usages
[] =
174 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_X
}, /* REL_X */
175 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_Y
}, /* REL_Y */
176 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_Z
}, /* REL_Z */
177 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_RX
}, /* REL_RX */
178 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_RY
}, /* REL_RY */
179 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_RZ
}, /* REL_RZ */
180 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_SLIDER
},/* REL_HWHEEL */
181 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_DIAL
}, /* REL_DIAL */
182 {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_WHEEL
}, /* REL_WHEEL */
188 struct base_device base
;
190 BYTE abs_map
[ARRAY_SIZE(absolute_usages
)];
191 BYTE rel_map
[ARRAY_SIZE(relative_usages
)];
193 BYTE button_map
[KEY_MAX
];
195 int haptic_effect_id
;
200 static inline struct lnxev_device
*lnxev_impl_from_unix_device(struct unix_device
*iface
)
202 return CONTAINING_RECORD(impl_from_unix_device(iface
), struct lnxev_device
, base
);
205 #endif /* HAS_PROPER_INPUT_HEADER */
207 #define MAX_DEVICES 128
208 static int close_fds
[MAX_DEVICES
];
209 static struct pollfd poll_fds
[MAX_DEVICES
];
210 static struct base_device
*poll_devs
[MAX_DEVICES
];
211 static int close_count
, poll_count
;
213 static void stop_polling_device(struct unix_device
*iface
)
215 struct base_device
*impl
= impl_from_unix_device(iface
);
218 if (impl
->device_fd
== -1) return; /* already removed */
220 for (i
= 2; i
< poll_count
; ++i
)
221 if (poll_fds
[i
].fd
== impl
->device_fd
) break;
224 ERR("could not find poll entry matching device %p fd\n", iface
);
228 poll_fds
[i
] = poll_fds
[poll_count
];
229 poll_devs
[i
] = poll_devs
[poll_count
];
230 close_fds
[close_count
++] = impl
->device_fd
;
231 impl
->device_fd
= -1;
235 static void start_polling_device(struct unix_device
*iface
)
237 struct base_device
*impl
= impl_from_unix_device(iface
);
239 if (poll_count
>= ARRAY_SIZE(poll_fds
))
240 ERR("could not start polling device %p, too many fds\n", iface
);
243 poll_devs
[poll_count
] = impl
;
244 poll_fds
[poll_count
].fd
= impl
->device_fd
;
245 poll_fds
[poll_count
].events
= POLLIN
;
246 poll_fds
[poll_count
].revents
= 0;
249 write(deviceloop_control
[1], "u", 1);
253 static struct base_device
*find_device_from_fd(int fd
)
257 for (i
= 2; i
< poll_count
; ++i
) if (poll_fds
[i
].fd
== fd
) break;
258 if (i
< poll_count
) return poll_devs
[i
];
263 static struct base_device
*find_device_from_devnode(const char *path
)
265 struct base_device
*impl
;
267 LIST_FOR_EACH_ENTRY(impl
, &device_list
, struct base_device
, unix_device
.entry
)
268 if (!strcmp(impl
->devnode
, path
)) return impl
;
273 static void hidraw_device_destroy(struct unix_device
*iface
)
275 struct hidraw_device
*impl
= hidraw_impl_from_unix_device(iface
);
277 udev_device_unref(impl
->base
.udev_device
);
280 static NTSTATUS
hidraw_device_start(struct unix_device
*iface
)
282 pthread_mutex_lock(&udev_cs
);
283 start_polling_device(iface
);
284 pthread_mutex_unlock(&udev_cs
);
285 return STATUS_SUCCESS
;
288 static void hidraw_device_stop(struct unix_device
*iface
)
290 struct hidraw_device
*impl
= hidraw_impl_from_unix_device(iface
);
292 pthread_mutex_lock(&udev_cs
);
293 stop_polling_device(iface
);
294 list_remove(&impl
->base
.unix_device
.entry
);
295 pthread_mutex_unlock(&udev_cs
);
298 static NTSTATUS
hidraw_device_get_report_descriptor(struct unix_device
*iface
, BYTE
*buffer
,
299 UINT length
, UINT
*out_length
)
301 #ifdef HAVE_LINUX_HIDRAW_H
302 struct hidraw_report_descriptor descriptor
;
303 struct hidraw_device
*impl
= hidraw_impl_from_unix_device(iface
);
305 if (ioctl(impl
->base
.device_fd
, HIDIOCGRDESCSIZE
, &descriptor
.size
) == -1)
307 WARN("ioctl(HIDIOCGRDESCSIZE) failed: %d %s\n", errno
, strerror(errno
));
308 return STATUS_UNSUCCESSFUL
;
311 *out_length
= descriptor
.size
;
313 if (length
< descriptor
.size
)
314 return STATUS_BUFFER_TOO_SMALL
;
315 if (!descriptor
.size
)
316 return STATUS_SUCCESS
;
318 if (ioctl(impl
->base
.device_fd
, HIDIOCGRDESC
, &descriptor
) == -1)
320 WARN("ioctl(HIDIOCGRDESC) failed: %d %s\n", errno
, strerror(errno
));
321 return STATUS_UNSUCCESSFUL
;
324 memcpy(buffer
, descriptor
.value
, descriptor
.size
);
325 return STATUS_SUCCESS
;
327 return STATUS_NOT_IMPLEMENTED
;
331 static void hidraw_device_read_report(struct unix_device
*iface
)
333 struct hidraw_device
*impl
= hidraw_impl_from_unix_device(iface
);
334 BYTE report_buffer
[1024], *buff
= report_buffer
;
336 int size
= read(impl
->base
.device_fd
, report_buffer
, sizeof(report_buffer
));
338 TRACE("Read failed. Likely an unplugged device %d %s\n", errno
, strerror(errno
));
340 TRACE("Failed to read report\n");
343 /* As described in the Linux kernel driver, when connected over bluetooth, DS4 controllers
344 * start sending input through report #17 as soon as they receive a feature report #2, which
345 * the kernel sends anyway for calibration.
347 * Input report #17 is the same as the default input report #1, with additional gyro data and
348 * two additional bytes in front, but is only described as vendor specific in the report descriptor,
349 * and applications aren't expecting it.
351 * We have to translate it to input report #1, like native driver does.
353 if ((impl
->quirks
& QUIRK_DS4_BT
) && report_buffer
[0] == 0x11 && size
>= 12)
360 /* The behavior of DualSense is very similar to DS4 described above with a few exceptions.
362 * The report number #41 is used for the extended bluetooth input report. The report comes
363 * with only one extra byte in front and the format is not exactly the same as the one used
364 * for the report #1 so we need to shuffle a few bytes around.
367 * X Y Z RZ Buttons[3] TriggerLeft TriggerRight
369 * Extended #41 report:
370 * Prefix X Y Z Rz TriggerLeft TriggerRight Counter Buttons[3] ...
372 if ((impl
->quirks
& QUIRK_DUALSENSE_BT
) && report_buffer
[0] == 0x31 && size
>= 11)
378 buff
[0] = 1; /* fake report #1 */
380 trigger
[0] = buff
[5]; /* TriggerLeft*/
381 trigger
[1] = buff
[6]; /* TriggerRight */
383 buff
[5] = buff
[8]; /* Buttons[0] */
384 buff
[6] = buff
[9]; /* Buttons[1] */
385 buff
[7] = buff
[10]; /* Buttons[2] */
386 buff
[8] = trigger
[0]; /* TriggerLeft */
387 buff
[9] = trigger
[1]; /* TirggerRight */
390 bus_event_queue_input_report(&event_queue
, iface
, buff
, size
);
394 static void hidraw_disable_sony_quirks(struct unix_device
*iface
)
396 struct hidraw_device
*impl
= hidraw_impl_from_unix_device(iface
);
398 /* FIXME: we may want to validate CRC at the end of the outbound HID reports,
399 * as controllers do not switch modes if it is incorrect.
402 if ((impl
->quirks
& QUIRK_DS4_BT
))
404 TRACE("Disabling report quirk for Bluetooth DualShock4 controller iface %p\n", iface
);
405 impl
->quirks
&= ~QUIRK_DS4_BT
;
408 if ((impl
->quirks
& QUIRK_DUALSENSE_BT
))
410 TRACE("Disabling report quirk for Bluetooth DualSense controller iface %p\n", iface
);
411 impl
->quirks
&= ~QUIRK_DUALSENSE_BT
;
415 static void hidraw_device_set_output_report(struct unix_device
*iface
, HID_XFER_PACKET
*packet
, IO_STATUS_BLOCK
*io
)
417 struct hidraw_device
*impl
= hidraw_impl_from_unix_device(iface
);
418 unsigned int length
= packet
->reportBufferLen
;
422 if ((buffer
[0] = packet
->reportId
))
423 count
= write(impl
->base
.device_fd
, packet
->reportBuffer
, length
);
424 else if (length
> sizeof(buffer
) - 1)
425 ERR("id %d length %u >= 8192, cannot write\n", packet
->reportId
, length
);
428 memcpy(buffer
+ 1, packet
->reportBuffer
, length
);
429 count
= write(impl
->base
.device_fd
, buffer
, length
+ 1);
434 hidraw_disable_sony_quirks(iface
);
435 io
->Information
= count
;
436 io
->Status
= STATUS_SUCCESS
;
440 ERR("id %d write failed error: %d %s\n", packet
->reportId
, errno
, strerror(errno
));
442 io
->Status
= STATUS_UNSUCCESSFUL
;
446 static void hidraw_device_get_feature_report(struct unix_device
*iface
, HID_XFER_PACKET
*packet
,
449 #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCGFEATURE)
450 struct hidraw_device
*impl
= hidraw_impl_from_unix_device(iface
);
451 unsigned int length
= packet
->reportBufferLen
;
455 if ((buffer
[0] = packet
->reportId
) && length
<= 0x1fff)
456 count
= ioctl(impl
->base
.device_fd
, HIDIOCGFEATURE(length
), packet
->reportBuffer
);
457 else if (length
> sizeof(buffer
) - 1)
458 ERR("id %d length %u >= 8192, cannot read\n", packet
->reportId
, length
);
461 count
= ioctl(impl
->base
.device_fd
, HIDIOCGFEATURE(length
+ 1), buffer
);
462 memcpy(packet
->reportBuffer
, buffer
+ 1, length
);
467 hidraw_disable_sony_quirks(iface
);
468 io
->Information
= count
;
469 io
->Status
= STATUS_SUCCESS
;
473 ERR("id %d read failed, error: %d %s\n", packet
->reportId
, errno
, strerror(errno
));
475 io
->Status
= STATUS_UNSUCCESSFUL
;
479 io
->Status
= STATUS_NOT_IMPLEMENTED
;
483 static void hidraw_device_set_feature_report(struct unix_device
*iface
, HID_XFER_PACKET
*packet
,
486 #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCSFEATURE)
487 struct hidraw_device
*impl
= hidraw_impl_from_unix_device(iface
);
488 unsigned int length
= packet
->reportBufferLen
;
492 if ((buffer
[0] = packet
->reportId
) && length
<= 0x1fff)
493 count
= ioctl(impl
->base
.device_fd
, HIDIOCSFEATURE(length
), packet
->reportBuffer
);
494 else if (length
> sizeof(buffer
) - 1)
495 ERR("id %d length %u >= 8192, cannot write\n", packet
->reportId
, length
);
498 memcpy(buffer
+ 1, packet
->reportBuffer
, length
);
499 count
= ioctl(impl
->base
.device_fd
, HIDIOCSFEATURE(length
+ 1), buffer
);
504 hidraw_disable_sony_quirks(iface
);
505 io
->Information
= count
;
506 io
->Status
= STATUS_SUCCESS
;
510 ERR("id %d write failed, error: %d %s\n", packet
->reportId
, errno
, strerror(errno
));
512 io
->Status
= STATUS_UNSUCCESSFUL
;
516 io
->Status
= STATUS_NOT_IMPLEMENTED
;
520 static const struct raw_device_vtbl hidraw_device_vtbl
=
522 hidraw_device_destroy
,
525 hidraw_device_get_report_descriptor
,
526 hidraw_device_set_output_report
,
527 hidraw_device_get_feature_report
,
528 hidraw_device_set_feature_report
,
531 #ifdef HAS_PROPER_INPUT_HEADER
533 static const char *get_device_syspath(struct udev_device
*dev
)
535 struct udev_device
*parent
;
537 if ((parent
= udev_device_get_parent_with_subsystem_devtype(dev
, "hid", NULL
)))
538 return udev_device_get_syspath(parent
);
540 if ((parent
= udev_device_get_parent_with_subsystem_devtype(dev
, "usb", "usb_device")))
541 return udev_device_get_syspath(parent
);
546 static struct base_device
*find_device_from_syspath(const char *path
)
548 struct base_device
*impl
;
550 LIST_FOR_EACH_ENTRY(impl
, &device_list
, struct base_device
, unix_device
.entry
)
551 if (!strcmp(get_device_syspath(impl
->udev_device
), path
)) return impl
;
556 #define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
558 static const USAGE_AND_PAGE
*what_am_I(struct udev_device
*dev
, int fd
)
560 static const USAGE_AND_PAGE Unknown
= {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= 0};
561 static const USAGE_AND_PAGE Mouse
= {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_MOUSE
};
562 static const USAGE_AND_PAGE Keyboard
= {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_KEYBOARD
};
563 static const USAGE_AND_PAGE Gamepad
= {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_GAMEPAD
};
564 static const USAGE_AND_PAGE Keypad
= {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_KEYPAD
};
565 static const USAGE_AND_PAGE Tablet
= {.UsagePage
= HID_USAGE_PAGE_DIGITIZER
, .Usage
= HID_USAGE_DIGITIZER_PEN
};
566 static const USAGE_AND_PAGE Touchscreen
= {.UsagePage
= HID_USAGE_PAGE_DIGITIZER
, .Usage
= HID_USAGE_DIGITIZER_TOUCH_SCREEN
};
567 static const USAGE_AND_PAGE Touchpad
= {.UsagePage
= HID_USAGE_PAGE_DIGITIZER
, .Usage
= HID_USAGE_DIGITIZER_TOUCH_PAD
};
569 struct udev_device
*parent
= dev
;
571 /* Look to the parents until we get a clue */
574 if (udev_device_get_property_value(parent
, "ID_INPUT_MOUSE"))
576 else if (udev_device_get_property_value(parent
, "ID_INPUT_KEYBOARD"))
578 else if (udev_device_get_property_value(parent
, "ID_INPUT_JOYSTICK"))
580 else if (udev_device_get_property_value(parent
, "ID_INPUT_KEY"))
582 else if (udev_device_get_property_value(parent
, "ID_INPUT_TOUCHPAD"))
584 else if (udev_device_get_property_value(parent
, "ID_INPUT_TOUCHSCREEN"))
586 else if (udev_device_get_property_value(parent
, "ID_INPUT_TABLET"))
589 parent
= udev_device_get_parent_with_subsystem_devtype(parent
, "input", NULL
);
595 static INT
count_buttons(int device_fd
, BYTE
*map
)
598 int button_count
= 0;
599 BYTE keybits
[(KEY_MAX
+7)/8];
601 if (ioctl(device_fd
, EVIOCGBIT(EV_KEY
, sizeof(keybits
)), keybits
) == -1)
603 WARN("ioctl(EVIOCGBIT, EV_KEY) failed: %d %s\n", errno
, strerror(errno
));
607 for (i
= BTN_MISC
; i
< KEY_MAX
; i
++)
609 if (test_bit(keybits
, i
))
611 if (map
) map
[i
] = button_count
;
618 static INT
count_abs_axis(int device_fd
)
620 BYTE absbits
[(ABS_MAX
+7)/8];
624 if (ioctl(device_fd
, EVIOCGBIT(EV_ABS
, sizeof(absbits
)), absbits
) == -1)
626 WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno
, strerror(errno
));
630 for (i
= 0; i
< ARRAY_SIZE(absolute_usages
); i
++)
631 if (test_bit(absbits
, i
)) abs_count
++;
635 static NTSTATUS
build_report_descriptor(struct unix_device
*iface
, struct udev_device
*dev
)
637 struct input_absinfo abs_info
[ARRAY_SIZE(absolute_usages
)];
638 BYTE absbits
[(ABS_MAX
+7)/8];
639 BYTE relbits
[(REL_MAX
+7)/8];
640 BYTE ffbits
[(FF_MAX
+7)/8];
641 struct ff_effect effect
;
642 USAGE_AND_PAGE usage
;
645 INT i
, button_count
, abs_count
, rel_count
, hat_count
;
646 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
647 const USAGE_AND_PAGE device_usage
= *what_am_I(dev
, impl
->base
.device_fd
);
649 if (ioctl(impl
->base
.device_fd
, EVIOCGBIT(EV_REL
, sizeof(relbits
)), relbits
) == -1)
651 WARN("ioctl(EVIOCGBIT, EV_REL) failed: %d %s\n", errno
, strerror(errno
));
652 memset(relbits
, 0, sizeof(relbits
));
654 if (ioctl(impl
->base
.device_fd
, EVIOCGBIT(EV_ABS
, sizeof(absbits
)), absbits
) == -1)
656 WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno
, strerror(errno
));
657 memset(absbits
, 0, sizeof(absbits
));
659 if (ioctl(impl
->base
.device_fd
, EVIOCGBIT(EV_FF
, sizeof(ffbits
)), ffbits
) == -1)
661 WARN("ioctl(EVIOCGBIT, EV_FF) failed: %d %s\n", errno
, strerror(errno
));
662 memset(ffbits
, 0, sizeof(ffbits
));
665 if (!hid_device_begin_report_descriptor(iface
, &device_usage
))
666 return STATUS_NO_MEMORY
;
668 if (!hid_device_begin_input_report(iface
, &device_usage
))
669 return STATUS_NO_MEMORY
;
672 for (i
= 0; i
< ARRAY_SIZE(absolute_usages
); i
++)
674 usage
= absolute_usages
[i
];
675 if (!test_bit(absbits
, i
)) continue;
676 ioctl(impl
->base
.device_fd
, EVIOCGABS(i
), abs_info
+ i
);
677 if (!usage
.UsagePage
|| !usage
.Usage
) continue;
678 if (!hid_device_add_axes(iface
, 1, usage
.UsagePage
, &usage
.Usage
, FALSE
,
679 LE_DWORD(abs_info
[i
].minimum
), LE_DWORD(abs_info
[i
].maximum
)))
680 return STATUS_NO_MEMORY
;
682 impl
->abs_map
[i
] = abs_count
++;
686 for (i
= 0; i
< ARRAY_SIZE(relative_usages
); i
++)
688 usage
= relative_usages
[i
];
689 if (!test_bit(relbits
, i
)) continue;
690 if (!usage
.UsagePage
|| !usage
.Usage
) continue;
691 if (!hid_device_add_axes(iface
, 1, usage
.UsagePage
, &usage
.Usage
, TRUE
,
692 INT32_MIN
, INT32_MAX
))
693 return STATUS_NO_MEMORY
;
695 impl
->rel_map
[i
] = rel_count
++;
699 for (i
= ABS_HAT0X
; i
<= ABS_HAT3X
; i
+= 2)
701 if (!test_bit(absbits
, i
)) continue;
702 impl
->hat_map
[i
- ABS_HAT0X
] = hat_count
;
703 impl
->hat_map
[i
- ABS_HAT0X
+ 1] = hat_count
++;
706 if (hat_count
&& !hid_device_add_hatswitch(iface
, hat_count
))
707 return STATUS_NO_MEMORY
;
709 /* For now lump all buttons just into incremental usages, Ignore Keys */
710 button_count
= count_buttons(impl
->base
.device_fd
, impl
->button_map
);
711 if (button_count
&& !hid_device_add_buttons(iface
, HID_USAGE_PAGE_BUTTON
, 1, button_count
))
712 return STATUS_NO_MEMORY
;
714 if (!hid_device_end_input_report(iface
))
715 return STATUS_NO_MEMORY
;
717 impl
->haptic_effect_id
= -1;
718 for (i
= 0; i
< ARRAY_SIZE(impl
->effect_ids
); ++i
) impl
->effect_ids
[i
] = -1;
720 if (test_bit(ffbits
, FF_RUMBLE
))
723 effect
.type
= FF_RUMBLE
;
724 effect
.replay
.length
= 0;
725 effect
.u
.rumble
.strong_magnitude
= 0;
726 effect
.u
.rumble
.weak_magnitude
= 0;
728 if (ioctl(impl
->base
.device_fd
, EVIOCSFF
, &effect
) == -1)
729 WARN("couldn't allocate rumble effect for haptics: %d %s\n", errno
, strerror(errno
));
730 else if (!hid_device_add_haptics(iface
))
733 impl
->haptic_effect_id
= effect
.id
;
736 for (i
= 0; i
< FF_MAX
; ++i
) if (test_bit(ffbits
, i
)) break;
739 if (test_bit(ffbits
, FF_SINE
)) usages
[count
++] = PID_USAGE_ET_SINE
;
740 if (test_bit(ffbits
, FF_SQUARE
)) usages
[count
++] = PID_USAGE_ET_SQUARE
;
741 if (test_bit(ffbits
, FF_TRIANGLE
)) usages
[count
++] = PID_USAGE_ET_TRIANGLE
;
742 if (test_bit(ffbits
, FF_SAW_UP
)) usages
[count
++] = PID_USAGE_ET_SAWTOOTH_UP
;
743 if (test_bit(ffbits
, FF_SAW_DOWN
)) usages
[count
++] = PID_USAGE_ET_SAWTOOTH_DOWN
;
744 if (test_bit(ffbits
, FF_SPRING
)) usages
[count
++] = PID_USAGE_ET_SPRING
;
745 if (test_bit(ffbits
, FF_DAMPER
)) usages
[count
++] = PID_USAGE_ET_DAMPER
;
746 if (test_bit(ffbits
, FF_INERTIA
)) usages
[count
++] = PID_USAGE_ET_INERTIA
;
747 if (test_bit(ffbits
, FF_FRICTION
)) usages
[count
++] = PID_USAGE_ET_FRICTION
;
748 if (test_bit(ffbits
, FF_CONSTANT
)) usages
[count
++] = PID_USAGE_ET_CONSTANT_FORCE
;
749 if (test_bit(ffbits
, FF_RAMP
)) usages
[count
++] = PID_USAGE_ET_RAMP
;
751 if (!hid_device_add_physical(iface
, usages
, count
))
752 return STATUS_NO_MEMORY
;
755 if (!hid_device_end_report_descriptor(iface
))
756 return STATUS_NO_MEMORY
;
758 /* Initialize axis in the report */
759 for (i
= 0; i
< ARRAY_SIZE(absolute_usages
); i
++)
761 if (!test_bit(absbits
, i
)) continue;
762 if (i
< ABS_HAT0X
|| i
> ABS_HAT3Y
)
763 hid_device_set_abs_axis(iface
, impl
->abs_map
[i
], abs_info
[i
].value
);
764 else if ((i
- ABS_HAT0X
) % 2)
765 hid_device_set_hatswitch_y(iface
, impl
->hat_map
[i
- ABS_HAT0X
], abs_info
[i
].value
);
767 hid_device_set_hatswitch_x(iface
, impl
->hat_map
[i
- ABS_HAT0X
], abs_info
[i
].value
);
770 return STATUS_SUCCESS
;
773 static BOOL
set_report_from_event(struct unix_device
*iface
, struct input_event
*ie
)
775 struct hid_effect_state
*effect_state
= &iface
->hid_physical
.effect_state
;
776 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
777 ULONG effect_flags
= InterlockedOr(&impl
->effect_flags
, 0);
786 case SYN_REPORT
: return hid_device_sync_report(iface
);
787 case SYN_DROPPED
: hid_device_drop_report(iface
); break;
796 hid_device_set_button(iface
, impl
->button_map
[ie
->code
], ie
->value
);
799 if (ie
->code
< ABS_HAT0X
|| ie
->code
> ABS_HAT3Y
)
800 hid_device_set_abs_axis(iface
, impl
->abs_map
[ie
->code
], ie
->value
);
801 else if ((ie
->code
- ABS_HAT0X
) % 2)
802 hid_device_set_hatswitch_y(iface
, impl
->hat_map
[ie
->code
- ABS_HAT0X
], ie
->value
);
804 hid_device_set_hatswitch_x(iface
, impl
->hat_map
[ie
->code
- ABS_HAT0X
], ie
->value
);
807 hid_device_set_rel_axis(iface
, impl
->rel_map
[ie
->code
], ie
->value
);
810 for (i
= 0; i
< ARRAY_SIZE(impl
->effect_ids
); ++i
) if (impl
->effect_ids
[i
] == ie
->code
) break;
811 if (i
== ARRAY_SIZE(impl
->effect_ids
)) return FALSE
;
813 if (ie
->value
== FF_STATUS_PLAYING
) effect_flags
|= EFFECT_STATE_EFFECT_PLAYING
;
814 hid_device_set_effect_state(iface
, i
, effect_flags
);
815 bus_event_queue_input_report(&event_queue
, iface
, effect_state
->report_buf
, effect_state
->report_len
);
818 ERR("TODO: Process Report (%i, %i)\n",ie
->type
, ie
->code
);
823 static void lnxev_device_destroy(struct unix_device
*iface
)
825 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
826 udev_device_unref(impl
->base
.udev_device
);
829 static NTSTATUS
lnxev_device_start(struct unix_device
*iface
)
831 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
834 if ((status
= build_report_descriptor(iface
, impl
->base
.udev_device
)))
837 pthread_mutex_lock(&udev_cs
);
838 start_polling_device(iface
);
839 pthread_mutex_unlock(&udev_cs
);
840 return STATUS_SUCCESS
;
843 static void lnxev_device_stop(struct unix_device
*iface
)
845 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
847 pthread_mutex_lock(&udev_cs
);
848 stop_polling_device(iface
);
849 list_remove(&impl
->base
.unix_device
.entry
);
850 pthread_mutex_unlock(&udev_cs
);
853 static void lnxev_device_read_report(struct unix_device
*iface
)
855 struct hid_device_state
*state
= &iface
->hid_device_state
;
856 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
857 struct input_event ie
;
860 size
= read(impl
->base
.device_fd
, &ie
, sizeof(ie
));
862 TRACE("Read failed. Likely an unplugged device\n");
864 TRACE("Failed to read report\n");
865 else if (set_report_from_event(iface
, &ie
))
866 bus_event_queue_input_report(&event_queue
, iface
, state
->report_buf
, state
->report_len
);
869 static NTSTATUS
lnxev_device_haptics_start(struct unix_device
*iface
, UINT duration_ms
,
870 USHORT rumble_intensity
, USHORT buzz_intensity
,
871 USHORT left_intensity
, USHORT right_intensity
)
873 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
874 struct ff_effect effect
=
876 .id
= impl
->haptic_effect_id
,
879 struct input_event event
;
881 TRACE("iface %p, duration_ms %u, rumble_intensity %u, buzz_intensity %u, left_intensity %u, right_intensity %u.\n",
882 iface
, duration_ms
, rumble_intensity
, buzz_intensity
, left_intensity
, right_intensity
);
884 effect
.replay
.length
= duration_ms
;
885 effect
.u
.rumble
.strong_magnitude
= rumble_intensity
;
886 effect
.u
.rumble
.weak_magnitude
= buzz_intensity
;
888 if (ioctl(impl
->base
.device_fd
, EVIOCSFF
, &effect
) == -1)
891 if (ioctl(impl
->base
.device_fd
, EVIOCSFF
, &effect
) == 1)
893 WARN("couldn't re-allocate rumble effect for haptics: %d %s\n", errno
, strerror(errno
));
894 return STATUS_UNSUCCESSFUL
;
896 impl
->haptic_effect_id
= effect
.id
;
900 event
.code
= effect
.id
;
902 if (write(impl
->base
.device_fd
, &event
, sizeof(event
)) == -1)
904 WARN("couldn't start haptics rumble effect: %d %s\n", errno
, strerror(errno
));
905 return STATUS_UNSUCCESSFUL
;
908 return STATUS_SUCCESS
;
911 static NTSTATUS
lnxev_device_haptics_stop(struct unix_device
*iface
)
913 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
914 struct ff_effect effect
=
916 .id
= impl
->haptic_effect_id
,
919 struct input_event event
;
921 TRACE("iface %p.\n", iface
);
923 if (effect
.id
== -1) return STATUS_SUCCESS
;
926 event
.code
= effect
.id
;
928 if (write(impl
->base
.device_fd
, &event
, sizeof(event
)) == -1)
929 WARN("couldn't stop haptics rumble effect: %d %s\n", errno
, strerror(errno
));
931 return STATUS_SUCCESS
;
934 static NTSTATUS
lnxev_device_physical_effect_run(struct lnxev_device
*impl
, BYTE index
,
937 struct input_event ie
=
943 if (impl
->effect_ids
[index
] < 0) return STATUS_UNSUCCESSFUL
;
944 ie
.code
= impl
->effect_ids
[index
];
946 if (write(impl
->base
.device_fd
, &ie
, sizeof(ie
)) == -1)
948 WARN("couldn't stop effect, write failed %d %s\n", errno
, strerror(errno
));
949 return STATUS_UNSUCCESSFUL
;
952 return STATUS_SUCCESS
;
955 static NTSTATUS
lnxev_device_physical_device_control(struct unix_device
*iface
, USAGE control
)
957 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
960 TRACE("iface %p, control %#04x.\n", iface
, control
);
964 case PID_USAGE_DC_ENABLE_ACTUATORS
:
966 struct input_event ie
=
972 if (write(impl
->base
.device_fd
, &ie
, sizeof(ie
)) == -1)
973 WARN("write failed %d %s\n", errno
, strerror(errno
));
975 InterlockedOr(&impl
->effect_flags
, EFFECT_STATE_ACTUATORS_ENABLED
);
976 return STATUS_SUCCESS
;
978 case PID_USAGE_DC_DISABLE_ACTUATORS
:
980 struct input_event ie
=
986 if (write(impl
->base
.device_fd
, &ie
, sizeof(ie
)) == -1)
987 WARN("write failed %d %s\n", errno
, strerror(errno
));
989 InterlockedAnd(&impl
->effect_flags
, ~EFFECT_STATE_ACTUATORS_ENABLED
);
990 return STATUS_SUCCESS
;
992 case PID_USAGE_DC_STOP_ALL_EFFECTS
:
993 for (i
= 0; i
< ARRAY_SIZE(impl
->effect_ids
); ++i
)
995 if (impl
->effect_ids
[i
] < 0) continue;
996 lnxev_device_physical_effect_run(impl
, i
, 0);
998 return STATUS_SUCCESS
;
999 case PID_USAGE_DC_DEVICE_RESET
:
1000 for (i
= 0; i
< ARRAY_SIZE(impl
->effect_ids
); ++i
)
1002 if (impl
->effect_ids
[i
] < 0) continue;
1003 if (ioctl(impl
->base
.device_fd
, EVIOCRMFF
, impl
->effect_ids
[i
]) == -1)
1004 WARN("couldn't free effect, EVIOCRMFF ioctl failed: %d %s\n", errno
, strerror(errno
));
1005 impl
->effect_ids
[i
] = -1;
1007 return STATUS_SUCCESS
;
1008 case PID_USAGE_DC_DEVICE_PAUSE
:
1009 WARN("device pause not supported\n");
1010 InterlockedOr(&impl
->effect_flags
, EFFECT_STATE_DEVICE_PAUSED
);
1011 return STATUS_NOT_SUPPORTED
;
1012 case PID_USAGE_DC_DEVICE_CONTINUE
:
1013 WARN("device continue not supported\n");
1014 InterlockedAnd(&impl
->effect_flags
, ~EFFECT_STATE_DEVICE_PAUSED
);
1015 return STATUS_NOT_SUPPORTED
;
1018 return STATUS_NOT_SUPPORTED
;
1021 static NTSTATUS
lnxev_device_physical_device_set_gain(struct unix_device
*iface
, BYTE percent
)
1023 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
1024 struct input_event ie
=
1028 .value
= 0xffff * percent
/ 100,
1031 TRACE("iface %p, percent %#x.\n", iface
, percent
);
1033 if (write(impl
->base
.device_fd
, &ie
, sizeof(ie
)) == -1)
1034 WARN("write failed %d %s\n", errno
, strerror(errno
));
1036 return STATUS_SUCCESS
;
1039 static NTSTATUS
lnxev_device_physical_effect_control(struct unix_device
*iface
, BYTE index
,
1040 USAGE control
, BYTE iterations
)
1042 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
1045 TRACE("iface %p, index %u, control %04x, iterations %u.\n", iface
, index
, control
, iterations
);
1049 case PID_USAGE_OP_EFFECT_START_SOLO
:
1050 if ((status
= lnxev_device_physical_device_control(iface
, PID_USAGE_DC_STOP_ALL_EFFECTS
)))
1053 case PID_USAGE_OP_EFFECT_START
:
1054 return lnxev_device_physical_effect_run(impl
, index
, iterations
);
1055 case PID_USAGE_OP_EFFECT_STOP
:
1056 return lnxev_device_physical_effect_run(impl
, index
, 0);
1059 return STATUS_SUCCESS
;
1062 static NTSTATUS
set_effect_type_from_usage(struct ff_effect
*effect
, USAGE type
)
1066 case PID_USAGE_ET_SINE
:
1067 effect
->type
= FF_PERIODIC
;
1068 effect
->u
.periodic
.waveform
= FF_SINE
;
1069 return STATUS_SUCCESS
;
1070 case PID_USAGE_ET_SQUARE
:
1071 effect
->type
= FF_PERIODIC
;
1072 effect
->u
.periodic
.waveform
= FF_SQUARE
;
1073 return STATUS_SUCCESS
;
1074 case PID_USAGE_ET_TRIANGLE
:
1075 effect
->type
= FF_PERIODIC
;
1076 effect
->u
.periodic
.waveform
= FF_TRIANGLE
;
1077 return STATUS_SUCCESS
;
1078 case PID_USAGE_ET_SAWTOOTH_UP
:
1079 effect
->type
= FF_PERIODIC
;
1080 effect
->u
.periodic
.waveform
= FF_SAW_UP
;
1081 return STATUS_SUCCESS
;
1082 case PID_USAGE_ET_SAWTOOTH_DOWN
:
1083 effect
->type
= FF_PERIODIC
;
1084 effect
->u
.periodic
.waveform
= FF_SAW_DOWN
;
1085 return STATUS_SUCCESS
;
1086 case PID_USAGE_ET_SPRING
:
1087 effect
->type
= FF_SPRING
;
1088 return STATUS_SUCCESS
;
1089 case PID_USAGE_ET_DAMPER
:
1090 effect
->type
= FF_DAMPER
;
1091 return STATUS_SUCCESS
;
1092 case PID_USAGE_ET_INERTIA
:
1093 effect
->type
= FF_INERTIA
;
1094 return STATUS_SUCCESS
;
1095 case PID_USAGE_ET_FRICTION
:
1096 effect
->type
= FF_FRICTION
;
1097 return STATUS_SUCCESS
;
1098 case PID_USAGE_ET_CONSTANT_FORCE
:
1099 effect
->type
= FF_CONSTANT
;
1100 return STATUS_SUCCESS
;
1101 case PID_USAGE_ET_RAMP
:
1102 effect
->type
= FF_RAMP
;
1103 return STATUS_SUCCESS
;
1104 case PID_USAGE_ET_CUSTOM_FORCE_DATA
:
1105 effect
->type
= FF_CUSTOM
;
1106 return STATUS_SUCCESS
;
1108 return STATUS_NOT_SUPPORTED
;
1112 static NTSTATUS
lnxev_device_physical_effect_update(struct unix_device
*iface
, BYTE index
,
1113 struct effect_params
*params
)
1115 struct lnxev_device
*impl
= lnxev_impl_from_unix_device(iface
);
1116 struct ff_effect effect
= {.id
= impl
->effect_ids
[index
]};
1119 TRACE("iface %p, index %u, params %p.\n", iface
, index
, params
);
1121 if (params
->effect_type
== PID_USAGE_UNDEFINED
) return STATUS_SUCCESS
;
1122 if ((status
= set_effect_type_from_usage(&effect
, params
->effect_type
))) return status
;
1124 effect
.replay
.length
= (params
->duration
== 0xffff ? 0 : params
->duration
);
1125 effect
.replay
.delay
= params
->start_delay
;
1126 effect
.trigger
.button
= params
->trigger_button
;
1127 effect
.trigger
.interval
= params
->trigger_repeat_interval
;
1129 /* Linux FF only supports polar direction, and the first direction we get from PID
1130 * is in polar coordinate space already. */
1131 effect
.direction
= params
->direction
[0] * 0x800 / 1125;
1133 switch (params
->effect_type
)
1135 case PID_USAGE_ET_SINE
:
1136 case PID_USAGE_ET_SQUARE
:
1137 case PID_USAGE_ET_TRIANGLE
:
1138 case PID_USAGE_ET_SAWTOOTH_UP
:
1139 case PID_USAGE_ET_SAWTOOTH_DOWN
:
1140 effect
.u
.periodic
.period
= params
->periodic
.period
;
1141 effect
.u
.periodic
.magnitude
= (params
->periodic
.magnitude
* params
->gain_percent
) / 100;
1142 effect
.u
.periodic
.offset
= params
->periodic
.offset
;
1143 effect
.u
.periodic
.phase
= params
->periodic
.phase
* 0x800 / 1125;
1144 effect
.u
.periodic
.envelope
.attack_length
= params
->envelope
.attack_time
;
1145 effect
.u
.periodic
.envelope
.attack_level
= params
->envelope
.attack_level
;
1146 effect
.u
.periodic
.envelope
.fade_length
= params
->envelope
.fade_time
;
1147 effect
.u
.periodic
.envelope
.fade_level
= params
->envelope
.fade_level
;
1150 case PID_USAGE_ET_SPRING
:
1151 case PID_USAGE_ET_DAMPER
:
1152 case PID_USAGE_ET_INERTIA
:
1153 case PID_USAGE_ET_FRICTION
:
1154 if (params
->condition_count
>= 1)
1156 effect
.u
.condition
[0].right_saturation
= params
->condition
[0].positive_saturation
;
1157 effect
.u
.condition
[0].left_saturation
= params
->condition
[0].negative_saturation
;
1158 effect
.u
.condition
[0].right_coeff
= params
->condition
[0].positive_coefficient
;
1159 effect
.u
.condition
[0].left_coeff
= params
->condition
[0].negative_coefficient
;
1160 effect
.u
.condition
[0].deadband
= params
->condition
[0].dead_band
;
1161 effect
.u
.condition
[0].center
= params
->condition
[0].center_point_offset
;
1163 if (params
->condition_count
>= 2)
1165 effect
.u
.condition
[1].right_saturation
= params
->condition
[1].positive_saturation
;
1166 effect
.u
.condition
[1].left_saturation
= params
->condition
[1].negative_saturation
;
1167 effect
.u
.condition
[1].right_coeff
= params
->condition
[1].positive_coefficient
;
1168 effect
.u
.condition
[1].left_coeff
= params
->condition
[1].negative_coefficient
;
1169 effect
.u
.condition
[1].deadband
= params
->condition
[1].dead_band
;
1170 effect
.u
.condition
[1].center
= params
->condition
[1].center_point_offset
;
1174 case PID_USAGE_ET_CONSTANT_FORCE
:
1175 effect
.u
.constant
.level
= (params
->constant_force
.magnitude
* params
->gain_percent
) / 100;
1176 effect
.u
.constant
.envelope
.attack_length
= params
->envelope
.attack_time
;
1177 effect
.u
.constant
.envelope
.attack_level
= params
->envelope
.attack_level
;
1178 effect
.u
.constant
.envelope
.fade_length
= params
->envelope
.fade_time
;
1179 effect
.u
.constant
.envelope
.fade_level
= params
->envelope
.fade_level
;
1182 case PID_USAGE_ET_RAMP
:
1183 effect
.u
.ramp
.start_level
= (params
->ramp_force
.ramp_start
* params
->gain_percent
) / 100;
1184 effect
.u
.ramp
.end_level
= (params
->ramp_force
.ramp_end
* params
->gain_percent
) / 100;
1185 effect
.u
.ramp
.envelope
.attack_length
= params
->envelope
.attack_time
;
1186 effect
.u
.ramp
.envelope
.attack_level
= params
->envelope
.attack_level
;
1187 effect
.u
.ramp
.envelope
.fade_length
= params
->envelope
.fade_time
;
1188 effect
.u
.ramp
.envelope
.fade_level
= params
->envelope
.fade_level
;
1191 case PID_USAGE_ET_CUSTOM_FORCE_DATA
:
1192 FIXME("not implemented!\n");
1196 if (ioctl(impl
->base
.device_fd
, EVIOCSFF
, &effect
) != -1)
1197 impl
->effect_ids
[index
] = effect
.id
;
1200 WARN("couldn't create effect, EVIOCSFF ioctl failed: %d %s\n", errno
, strerror(errno
));
1201 return STATUS_UNSUCCESSFUL
;
1204 return STATUS_SUCCESS
;
1207 static const struct hid_device_vtbl lnxev_device_vtbl
=
1209 lnxev_device_destroy
,
1212 lnxev_device_haptics_start
,
1213 lnxev_device_haptics_stop
,
1214 lnxev_device_physical_device_control
,
1215 lnxev_device_physical_device_set_gain
,
1216 lnxev_device_physical_effect_control
,
1217 lnxev_device_physical_effect_update
,
1219 #endif /* HAS_PROPER_INPUT_HEADER */
1221 static void get_device_subsystem_info(struct udev_device
*dev
, char const *subsystem
, struct device_desc
*desc
,
1224 struct udev_device
*parent
= NULL
;
1225 const char *ptr
, *next
, *tmp
;
1226 char buffer
[MAX_PATH
];
1228 if (!(parent
= udev_device_get_parent_with_subsystem_devtype(dev
, subsystem
, NULL
))) return;
1230 if ((next
= udev_device_get_sysattr_value(parent
, "uevent")))
1232 while ((ptr
= next
) && *ptr
)
1234 if ((next
= strchr(next
, '\n'))) next
+= 1;
1235 else next
= ptr
+ strlen(ptr
);
1236 TRACE("%s uevent %s\n", subsystem
, debugstr_an(ptr
, next
- ptr
- 1));
1238 if (!strncmp(ptr
, "HID_UNIQ=", 9))
1240 if (desc
->serialnumber
[0]) continue;
1241 if (sscanf(ptr
, "HID_UNIQ=%256[^\n]", buffer
) == 1)
1242 ntdll_umbstowcs(buffer
, strlen(buffer
) + 1, desc
->serialnumber
, ARRAY_SIZE(desc
->serialnumber
));
1244 if (!strncmp(ptr
, "HID_NAME=", 9))
1246 if (desc
->product
[0]) continue;
1247 if (sscanf(ptr
, "HID_NAME=%256[^\n]", buffer
) == 1)
1248 ntdll_umbstowcs(buffer
, strlen(buffer
) + 1, desc
->product
, ARRAY_SIZE(desc
->product
));
1250 if (!strncmp(ptr
, "HID_PHYS=", 9) || !strncmp(ptr
, "PHYS=\"", 6))
1252 if (!(tmp
= strstr(ptr
, "/input")) || tmp
>= next
) continue;
1253 if (desc
->input
== -1) sscanf(tmp
, "/input%d\n", &desc
->input
);
1255 if (!strncmp(ptr
, "HID_ID=", 7))
1257 if (*bus
|| desc
->vid
|| desc
->pid
) continue;
1258 sscanf(ptr
, "HID_ID=%x:%x:%x\n", bus
, &desc
->vid
, &desc
->pid
);
1260 if (!strncmp(ptr
, "PRODUCT=", 8) && *bus
!= BUS_BLUETOOTH
)
1262 if (desc
->version
) continue;
1263 if (!strcmp(subsystem
, "usb"))
1264 sscanf(ptr
, "PRODUCT=%x/%x/%x\n", &desc
->vid
, &desc
->pid
, &desc
->version
);
1266 sscanf(ptr
, "PRODUCT=%x/%x/%x/%x\n", bus
, &desc
->vid
, &desc
->pid
, &desc
->version
);
1271 if (!desc
->manufacturer
[0] && (tmp
= udev_device_get_sysattr_value(dev
, "manufacturer")))
1272 ntdll_umbstowcs(tmp
, strlen(tmp
) + 1, desc
->manufacturer
, ARRAY_SIZE(desc
->manufacturer
));
1274 if (!desc
->product
[0] && (tmp
= udev_device_get_sysattr_value(dev
, "product")))
1275 ntdll_umbstowcs(tmp
, strlen(tmp
) + 1, desc
->product
, ARRAY_SIZE(desc
->product
));
1277 if (!desc
->serialnumber
[0] && (tmp
= udev_device_get_sysattr_value(dev
, "serial")))
1278 ntdll_umbstowcs(tmp
, strlen(tmp
) + 1, desc
->serialnumber
, ARRAY_SIZE(desc
->serialnumber
));
1281 static void hidraw_set_quirks(struct hidraw_device
*impl
, DWORD bus_type
, WORD vid
, WORD pid
)
1283 if (bus_type
== BUS_BLUETOOTH
&& is_dualshock4_gamepad(vid
, pid
))
1284 impl
->quirks
|= QUIRK_DS4_BT
;
1286 if (bus_type
== BUS_BLUETOOTH
&& is_dualsense_gamepad(vid
, pid
))
1287 impl
->quirks
|= QUIRK_DUALSENSE_BT
;
1290 static void udev_add_device(struct udev_device
*dev
, int fd
)
1292 struct device_desc desc
=
1296 struct base_device
*impl
;
1297 const char *subsystem
;
1298 const char *devnode
;
1301 if (!(devnode
= udev_device_get_devnode(dev
)))
1303 if (fd
>= 0) close(fd
);
1307 if (fd
< 0 && (fd
= open(devnode
, O_RDWR
)) == -1)
1309 WARN("Unable to open udev device %s: %s\n", debugstr_a(devnode
), strerror(errno
));
1313 TRACE("udev %s syspath %s\n", debugstr_a(devnode
), udev_device_get_syspath(dev
));
1315 #ifdef HAS_PROPER_INPUT_HEADER
1316 if ((impl
= find_device_from_syspath(get_device_syspath(dev
))))
1318 TRACE("duplicate device found, not adding the new one\n");
1324 get_device_subsystem_info(dev
, "hid", &desc
, &bus
);
1325 get_device_subsystem_info(dev
, "input", &desc
, &bus
);
1326 get_device_subsystem_info(dev
, "usb", &desc
, &bus
);
1328 subsystem
= udev_device_get_subsystem(dev
);
1329 if (!strcmp(subsystem
, "hidraw"))
1331 static const WCHAR hidraw
[] = {'h','i','d','r','a','w',0};
1332 #ifdef HAVE_LINUX_HIDRAW_H
1333 char product
[MAX_PATH
];
1336 if (!desc
.manufacturer
[0]) memcpy(desc
.manufacturer
, hidraw
, sizeof(hidraw
));
1338 #ifdef HAVE_LINUX_HIDRAW_H
1339 if (!desc
.product
[0] && ioctl(fd
, HIDIOCGRAWNAME(sizeof(product
) - 1), product
) >= 0)
1340 ntdll_umbstowcs(product
, strlen(product
) + 1, desc
.product
, ARRAY_SIZE(desc
.product
));
1343 #ifdef HAS_PROPER_INPUT_HEADER
1344 else if (!strcmp(subsystem
, "input"))
1346 static const WCHAR evdev
[] = {'e','v','d','e','v',0};
1347 struct input_id device_id
= {0};
1348 char buffer
[MAX_PATH
];
1350 if (ioctl(fd
, EVIOCGID
, &device_id
) < 0)
1351 WARN("ioctl(EVIOCGID) failed: %d %s\n", errno
, strerror(errno
));
1354 desc
.vid
= device_id
.vendor
;
1355 desc
.pid
= device_id
.product
;
1356 desc
.version
= device_id
.version
;
1359 if (!desc
.manufacturer
[0]) memcpy(desc
.manufacturer
, evdev
, sizeof(evdev
));
1361 if (!desc
.product
[0] && ioctl(fd
, EVIOCGNAME(sizeof(buffer
) - 1), buffer
) > 0)
1362 ntdll_umbstowcs(buffer
, strlen(buffer
) + 1, desc
.product
, ARRAY_SIZE(desc
.product
));
1364 if (!desc
.serialnumber
[0] && ioctl(fd
, EVIOCGUNIQ(sizeof(buffer
)), buffer
) >= 0)
1365 ntdll_umbstowcs(buffer
, strlen(buffer
) + 1, desc
.serialnumber
, ARRAY_SIZE(desc
.serialnumber
));
1369 if (!desc
.serialnumber
[0])
1371 static const WCHAR zeros
[] = {'0','0','0','0',0};
1372 memcpy(desc
.serialnumber
, zeros
, sizeof(zeros
));
1375 if (is_xbox_gamepad(desc
.vid
, desc
.pid
))
1376 desc
.is_gamepad
= TRUE
;
1377 #ifdef HAS_PROPER_INPUT_HEADER
1380 int axes
=0, buttons
=0;
1381 axes
= count_abs_axis(fd
);
1382 buttons
= count_buttons(fd
, NULL
);
1383 desc
.is_gamepad
= (axes
== 6 && buttons
>= 14);
1387 TRACE("dev %p, node %s, desc %s.\n", dev
, debugstr_a(devnode
), debugstr_device_desc(&desc
));
1389 if (strcmp(subsystem
, "hidraw") == 0)
1391 if (!(impl
= raw_device_create(&hidraw_device_vtbl
, sizeof(struct hidraw_device
)))) return;
1392 list_add_tail(&device_list
, &impl
->unix_device
.entry
);
1393 impl
->read_report
= hidraw_device_read_report
;
1394 impl
->udev_device
= udev_device_ref(dev
);
1395 strcpy(impl
->devnode
, devnode
);
1396 impl
->device_fd
= fd
;
1397 hidraw_set_quirks((struct hidraw_device
*)impl
, bus
, desc
.vid
, desc
.pid
);
1399 bus_event_queue_device_created(&event_queue
, &impl
->unix_device
, &desc
);
1401 #ifdef HAS_PROPER_INPUT_HEADER
1402 else if (strcmp(subsystem
, "input") == 0)
1404 if (!(impl
= hid_device_create(&lnxev_device_vtbl
, sizeof(struct lnxev_device
)))) return;
1405 list_add_tail(&device_list
, &impl
->unix_device
.entry
);
1406 impl
->read_report
= lnxev_device_read_report
;
1407 impl
->udev_device
= udev_device_ref(dev
);
1408 strcpy(impl
->devnode
, devnode
);
1409 impl
->device_fd
= fd
;
1411 bus_event_queue_device_created(&event_queue
, &impl
->unix_device
, &desc
);
1416 #ifdef HAVE_SYS_INOTIFY_H
1417 static int dev_watch
= -1;
1418 #ifdef HAS_PROPER_INPUT_HEADER
1419 static int devinput_watch
= -1;
1422 static void maybe_add_devnode(const char *base
, const char *dir
, const char *subsystem
)
1424 char *syspath
= NULL
, devnode
[MAX_PATH
], syslink
[MAX_PATH
];
1425 struct udev_device
*dev
= NULL
;
1426 const char *udev_devnode
;
1429 TRACE("Considering %s/%s...\n", dir
, base
);
1431 snprintf(devnode
, sizeof(devnode
), "%s/%s", dir
, base
);
1432 if ((fd
= open(devnode
, O_RDWR
)) < 0)
1434 /* When using inotify monitoring, quietly ignore device nodes that we cannot read,
1435 * without emitting a warning.
1437 * We can expect that a significant number of device nodes will be permanently
1438 * unreadable, such as the device nodes for keyboards and mice. We can also expect
1439 * that joysticks and game controllers will be temporarily unreadable until udevd
1440 * chmods them; we'll get another chance to open them when their attributes change. */
1441 TRACE("Unable to open %s, ignoring: %s\n", debugstr_a(devnode
), strerror(errno
));
1445 snprintf(syslink
, sizeof(syslink
), "/sys/class/%s/%s", subsystem
, base
);
1446 TRACE("Resolving real path to %s\n", debugstr_a(syslink
));
1448 if (!(syspath
= realpath(syslink
, NULL
)))
1450 WARN("Unable to resolve path \"%s\" for \"%s/%s\": %s\n",
1451 debugstr_a(syslink
), dir
, base
, strerror(errno
));
1455 TRACE("Creating udev_device for %s\n", syspath
);
1456 if (!(dev
= udev_device_new_from_syspath(udev_context
, syspath
)))
1458 WARN("failed to create udev device from syspath %s\n", syspath
);
1462 if (!(udev_devnode
= udev_device_get_devnode(dev
)) || strcmp(devnode
, udev_devnode
) != 0)
1464 WARN("Tried to get udev device for \"%s\" but device node of \"%s\" -> \"%s\" is \"%s\"\n",
1465 debugstr_a(devnode
), debugstr_a(syslink
), debugstr_a(syspath
), debugstr_a(udev_devnode
));
1469 TRACE("Adding device for %s\n", syspath
);
1470 udev_add_device(dev
, fd
);
1471 udev_device_unref(dev
);
1475 if (dev
) udev_device_unref(dev
);
1480 static void build_initial_deviceset_direct(void)
1482 struct dirent
*dent
;
1486 if (!options
.disable_hidraw
)
1488 TRACE("Initial enumeration of /dev/hidraw*\n");
1489 if (!(dir
= opendir("/dev"))) WARN("Unable to open /dev: %s\n", strerror(errno
));
1492 for (dent
= readdir(dir
); dent
; dent
= readdir(dir
))
1494 if (sscanf(dent
->d_name
, "hidraw%u%n", &n
, &len
) != 1 || len
!= strlen(dent
->d_name
))
1495 WARN("ignoring %s, name doesn't match hidraw%%u\n", debugstr_a(dent
->d_name
));
1497 maybe_add_devnode(dent
->d_name
, "/dev", "hidraw");
1502 #ifdef HAS_PROPER_INPUT_HEADER
1503 if (!options
.disable_input
)
1505 TRACE("Initial enumeration of /dev/input/event*\n");
1506 if (!(dir
= opendir("/dev/input"))) WARN("Unable to open /dev/input: %s\n", strerror(errno
));
1509 for (dent
= readdir(dir
); dent
; dent
= readdir(dir
))
1511 if (sscanf(dent
->d_name
, "event%u%n", &n
, &len
) != 1 || len
!= strlen(dent
->d_name
))
1512 WARN("ignoring %s, name doesn't match event%%u\n", debugstr_a(dent
->d_name
));
1514 maybe_add_devnode(dent
->d_name
, "/dev/input", "input");
1522 static int create_inotify(void)
1524 int systems
= 0, fd
, flags
= IN_CREATE
| IN_DELETE
| IN_MOVE
| IN_ATTRIB
;
1526 if ((fd
= inotify_init1(IN_NONBLOCK
| IN_CLOEXEC
)) < 0)
1528 WARN("Unable to get inotify fd\n");
1532 if (!options
.disable_hidraw
)
1534 /* We need to watch for attribute changes in addition to
1535 * creation, because when a device is first created, it has
1536 * permissions that we can't read. When udev chmods it to
1537 * something that we maybe *can* read, we'll get an
1538 * IN_ATTRIB event to tell us. */
1539 dev_watch
= inotify_add_watch(fd
, "/dev", flags
);
1540 if (dev_watch
< 0) WARN("Unable to initialize inotify for /dev: %s\n", strerror(errno
));
1543 #ifdef HAS_PROPER_INPUT_HEADER
1544 if (!options
.disable_input
)
1546 devinput_watch
= inotify_add_watch(fd
, "/dev/input", flags
);
1547 if (devinput_watch
< 0) WARN("Unable to initialize inotify for /dev/input: %s\n", strerror(errno
));
1553 WARN("No subsystems added to monitor\n");
1561 static void maybe_remove_devnode(const char *base
, const char *dir
)
1563 struct base_device
*impl
;
1564 char devnode
[MAX_PATH
];
1566 snprintf(devnode
, sizeof(devnode
), "%s/%s", dir
, base
);
1567 impl
= find_device_from_devnode(devnode
);
1568 if (impl
) bus_event_queue_device_removed(&event_queue
, &impl
->unix_device
);
1569 else WARN("failed to find device for path %s\n", devnode
);
1572 static void process_inotify_event(int fd
)
1576 struct inotify_event event
;
1578 char enough_for_inotify
[sizeof(struct inotify_event
) + NAME_MAX
+ 1];
1583 if ((bytes
= read(fd
, &buf
, sizeof(buf
))) < 0)
1584 WARN("read failed: %u %s\n", errno
, strerror(errno
));
1585 else while (bytes
> 0)
1587 if (buf
.event
.len
> 0)
1589 if (buf
.event
.wd
== dev_watch
)
1591 if (sscanf(buf
.event
.name
, "hidraw%u%n", &n
, &len
) != 1 || len
!= strlen(buf
.event
.name
))
1592 WARN("ignoring %s, name doesn't match hidraw%%u\n", debugstr_a(buf
.event
.name
));
1593 else if (buf
.event
.mask
& (IN_DELETE
| IN_MOVED_FROM
))
1594 maybe_remove_devnode(buf
.event
.name
, "/dev");
1595 else if (buf
.event
.mask
& (IN_CREATE
| IN_MOVED_TO
))
1596 maybe_add_devnode(buf
.event
.name
, "/dev", "hidraw");
1597 else if (buf
.event
.mask
& IN_ATTRIB
)
1599 maybe_remove_devnode(buf
.event
.name
, "/dev");
1600 maybe_add_devnode(buf
.event
.name
, "/dev", "hidraw");
1603 #ifdef HAS_PROPER_INPUT_HEADER
1604 else if (buf
.event
.wd
== devinput_watch
)
1606 if (sscanf(buf
.event
.name
, "event%u%n", &n
, &len
) != 1 || len
!= strlen(buf
.event
.name
))
1607 WARN("ignoring %s, name doesn't match event%%u\n", debugstr_a(buf
.event
.name
));
1608 else if (buf
.event
.mask
& (IN_DELETE
| IN_MOVED_FROM
))
1609 maybe_remove_devnode(buf
.event
.name
, "/dev/input");
1610 else if (buf
.event
.mask
& (IN_CREATE
| IN_MOVED_TO
))
1611 maybe_add_devnode(buf
.event
.name
, "/dev/input", "input");
1612 else if (buf
.event
.mask
& IN_ATTRIB
)
1614 maybe_remove_devnode(buf
.event
.name
, "/dev/input");
1615 maybe_add_devnode(buf
.event
.name
, "/dev/input", "input");
1621 len
= sizeof(struct inotify_event
) + buf
.event
.len
;
1623 if (bytes
> 0) memmove(&buf
.storage
[0], &buf
.storage
[len
], bytes
);
1626 #endif /* HAVE_SYS_INOTIFY_H */
1628 static void build_initial_deviceset_udevd(void)
1630 struct udev_enumerate
*enumerate
;
1631 struct udev_list_entry
*devices
, *dev_list_entry
;
1633 enumerate
= udev_enumerate_new(udev_context
);
1636 WARN("Unable to create udev enumeration object\n");
1640 if (!options
.disable_hidraw
)
1641 if (udev_enumerate_add_match_subsystem(enumerate
, "hidraw") < 0)
1642 WARN("Failed to add subsystem 'hidraw' to enumeration\n");
1643 #ifdef HAS_PROPER_INPUT_HEADER
1644 if (!options
.disable_input
)
1646 if (udev_enumerate_add_match_subsystem(enumerate
, "input") < 0)
1647 WARN("Failed to add subsystem 'input' to enumeration\n");
1651 if (udev_enumerate_scan_devices(enumerate
) < 0)
1652 WARN("Enumeration scan failed\n");
1654 devices
= udev_enumerate_get_list_entry(enumerate
);
1655 udev_list_entry_foreach(dev_list_entry
, devices
)
1657 struct udev_device
*dev
;
1660 path
= udev_list_entry_get_name(dev_list_entry
);
1661 if ((dev
= udev_device_new_from_syspath(udev_context
, path
)))
1663 udev_add_device(dev
, -1);
1664 udev_device_unref(dev
);
1668 udev_enumerate_unref(enumerate
);
1671 static struct udev_monitor
*create_monitor(int *fd
)
1673 struct udev_monitor
*monitor
;
1676 monitor
= udev_monitor_new_from_netlink(udev_context
, "udev");
1679 WARN("Unable to get udev monitor object\n");
1683 if (!options
.disable_hidraw
)
1685 if (udev_monitor_filter_add_match_subsystem_devtype(monitor
, "hidraw", NULL
) < 0)
1686 WARN("Failed to add 'hidraw' subsystem to monitor\n");
1690 #ifdef HAS_PROPER_INPUT_HEADER
1691 if (!options
.disable_input
)
1693 if (udev_monitor_filter_add_match_subsystem_devtype(monitor
, "input", NULL
) < 0)
1694 WARN("Failed to add 'input' subsystem to monitor\n");
1701 WARN("No subsystems added to monitor\n");
1705 if (udev_monitor_enable_receiving(monitor
) < 0)
1708 if ((*fd
= udev_monitor_get_fd(monitor
)) >= 0)
1712 WARN("Failed to start monitoring\n");
1713 udev_monitor_unref(monitor
);
1717 static void process_monitor_event(struct udev_monitor
*monitor
)
1719 struct base_device
*impl
;
1720 struct udev_device
*dev
;
1723 dev
= udev_monitor_receive_device(monitor
);
1726 FIXME("Failed to get device that has changed\n");
1730 action
= udev_device_get_action(dev
);
1731 TRACE("Received action %s for udev device %s\n", debugstr_a(action
),
1732 debugstr_a(udev_device_get_devnode(dev
)));
1735 WARN("No action received\n");
1736 else if (strcmp(action
, "remove"))
1737 udev_add_device(dev
, -1);
1740 impl
= find_device_from_devnode(udev_device_get_devnode(dev
));
1741 if (impl
) bus_event_queue_device_removed(&event_queue
, &impl
->unix_device
);
1742 else WARN("failed to find device for udev device %p\n", dev
);
1745 udev_device_unref(dev
);
1748 NTSTATUS
udev_bus_init(void *args
)
1750 int monitor_fd
= -1;
1752 TRACE("args %p\n", args
);
1754 options
= *(struct udev_bus_options
*)args
;
1756 if (pipe(deviceloop_control
) != 0)
1758 ERR("UDEV control pipe creation failed\n");
1759 return STATUS_UNSUCCESSFUL
;
1762 if (!(udev_context
= udev_new()))
1764 ERR("UDEV object creation failed\n");
1768 #ifdef HAVE_SYS_INOTIFY_H
1769 if (options
.disable_udevd
) monitor_fd
= create_inotify();
1770 if (monitor_fd
< 0) options
.disable_udevd
= FALSE
;
1772 if (options
.disable_udevd
) ERR("inotify support not compiled in!\n");
1773 options
.disable_udevd
= FALSE
;
1776 if (monitor_fd
< 0 && !(udev_monitor
= create_monitor(&monitor_fd
)))
1778 ERR("UDEV monitor creation failed\n");
1782 if (monitor_fd
< 0) goto error
;
1784 poll_fds
[0].fd
= monitor_fd
;
1785 poll_fds
[0].events
= POLLIN
;
1786 poll_fds
[0].revents
= 0;
1787 poll_fds
[1].fd
= deviceloop_control
[0];
1788 poll_fds
[1].events
= POLLIN
;
1789 poll_fds
[1].revents
= 0;
1792 if (!options
.disable_udevd
) build_initial_deviceset_udevd();
1793 #ifdef HAVE_SYS_INOTIFY_H
1794 else build_initial_deviceset_direct();
1797 return STATUS_SUCCESS
;
1800 if (udev_monitor
) udev_monitor_unref(udev_monitor
);
1801 if (udev_context
) udev_unref(udev_context
);
1802 udev_context
= NULL
;
1803 close(deviceloop_control
[0]);
1804 close(deviceloop_control
[1]);
1805 return STATUS_UNSUCCESSFUL
;
1808 NTSTATUS
udev_bus_wait(void *args
)
1810 struct bus_event
*result
= args
;
1811 struct pollfd pfd
[MAX_DEVICES
];
1812 struct base_device
*impl
;
1816 /* cleanup previously returned event */
1817 bus_event_cleanup(result
);
1821 if (bus_event_queue_pop(&event_queue
, result
)) return STATUS_PENDING
;
1823 pthread_mutex_lock(&udev_cs
);
1824 while (close_count
--) close(close_fds
[close_count
]);
1825 memcpy(pfd
, poll_fds
, poll_count
* sizeof(*pfd
));
1828 pthread_mutex_unlock(&udev_cs
);
1830 while (poll(pfd
, count
, -1) <= 0) {}
1832 pthread_mutex_lock(&udev_cs
);
1835 if (udev_monitor
) process_monitor_event(udev_monitor
);
1836 #ifdef HAVE_SYS_INOTIFY_H
1837 else process_inotify_event(pfd
[0].fd
);
1840 if (pfd
[1].revents
) read(deviceloop_control
[0], &ctrl
, 1);
1841 for (i
= 2; i
< count
; ++i
)
1843 if (!pfd
[i
].revents
) continue;
1844 impl
= find_device_from_fd(pfd
[i
].fd
);
1845 if (impl
) impl
->read_report(&impl
->unix_device
);
1847 pthread_mutex_unlock(&udev_cs
);
1850 TRACE("UDEV main loop exiting\n");
1851 bus_event_queue_destroy(&event_queue
);
1852 if (udev_monitor
) udev_monitor_unref(udev_monitor
);
1853 udev_unref(udev_context
);
1854 udev_context
= NULL
;
1855 close(deviceloop_control
[0]);
1856 close(deviceloop_control
[1]);
1857 return STATUS_SUCCESS
;
1860 NTSTATUS
udev_bus_stop(void *args
)
1862 if (!udev_context
) return STATUS_SUCCESS
;
1863 write(deviceloop_control
[1], "q", 1);
1864 return STATUS_SUCCESS
;
1869 NTSTATUS
udev_bus_init(void *args
)
1871 WARN("UDEV support not compiled in!\n");
1872 return STATUS_NOT_IMPLEMENTED
;
1875 NTSTATUS
udev_bus_wait(void *args
)
1877 WARN("UDEV support not compiled in!\n");
1878 return STATUS_NOT_IMPLEMENTED
;
1881 NTSTATUS
udev_bus_stop(void *args
)
1883 WARN("UDEV support not compiled in!\n");
1884 return STATUS_NOT_IMPLEMENTED
;
1887 #endif /* HAVE_UDEV */