So we can stop the device when it's removed from the ntoskrnl.exe device list, and then destroy it only when it's not referenced anymore.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_iohid.c | 8 +++++ dlls/winebus.sys/bus_sdl.c | 16 +++++---- dlls/winebus.sys/bus_udev.c | 64 +++++++++++++++++++-------------- dlls/winebus.sys/unix_private.h | 1 + dlls/winebus.sys/unixlib.c | 19 +++++++--- 5 files changed, 72 insertions(+), 36 deletions(-)
diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index 18e318f7789..d362906637a 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -167,6 +167,13 @@ static NTSTATUS iohid_device_start(struct unix_device *iface, DEVICE_OBJECT *dev return STATUS_SUCCESS; }
+static void iohid_device_stop(struct unix_device *iface) +{ + struct platform_private *private = impl_from_unix_device(iface); + + IOHIDDeviceRegisterInputReportCallback(private->device, NULL, 0, NULL, NULL); +} + static NTSTATUS iohid_device_get_report_descriptor(struct unix_device *iface, BYTE *buffer, DWORD length, DWORD *out_length) { @@ -246,6 +253,7 @@ static const struct unix_device_vtbl iohid_device_vtbl = iohid_device_destroy, iohid_device_compare, iohid_device_start, + iohid_device_stop, iohid_device_get_report_descriptor, iohid_device_set_output_report, iohid_device_get_feature_report, diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 8d6df3e1f13..73562fec14f 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -482,12 +482,6 @@ static void sdl_device_destroy(struct unix_device *iface) { struct platform_private *ext = impl_from_unix_device(iface);
- pSDL_JoystickClose(ext->sdl_joystick); - if (ext->sdl_controller) - pSDL_GameControllerClose(ext->sdl_controller); - if (ext->sdl_haptic) - pSDL_HapticClose(ext->sdl_haptic); - HeapFree(GetProcessHeap(), 0, ext); }
@@ -503,6 +497,15 @@ static NTSTATUS sdl_device_start(struct unix_device *iface, DEVICE_OBJECT *devic return build_report_descriptor(ext); }
+static void sdl_device_stop(struct unix_device *iface) +{ + struct platform_private *private = impl_from_unix_device(iface); + + pSDL_JoystickClose(private->sdl_joystick); + if (private->sdl_controller) pSDL_GameControllerClose(private->sdl_controller); + if (private->sdl_haptic) pSDL_HapticClose(private->sdl_haptic); +} + static NTSTATUS sdl_device_get_reportdescriptor(struct unix_device *iface, BYTE *buffer, DWORD length, DWORD *out_length) { @@ -579,6 +582,7 @@ static const struct unix_device_vtbl sdl_device_vtbl = sdl_device_destroy, sdl_device_compare, sdl_device_start, + sdl_device_stop, sdl_device_get_reportdescriptor, sdl_device_set_output_report, sdl_device_get_feature_report, diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 3010e50ce98..25a408489a4 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -558,19 +558,6 @@ static void hidraw_device_destroy(struct unix_device *iface) { struct platform_private *private = impl_from_unix_device(iface);
- EnterCriticalSection(&udev_cs); - list_remove(&private->unix_device.entry); - LeaveCriticalSection(&udev_cs); - - if (private->report_thread) - { - write(private->control_pipe[1], "q", 1); - WaitForSingleObject(private->report_thread, INFINITE); - close(private->control_pipe[0]); - close(private->control_pipe[1]); - CloseHandle(private->report_thread); - } - close(private->device_fd); udev_device_unref(private->udev_device);
@@ -608,6 +595,24 @@ static NTSTATUS hidraw_device_start(struct unix_device *iface, DEVICE_OBJECT *de return STATUS_SUCCESS; }
+static void hidraw_device_stop(struct unix_device *iface) +{ + struct platform_private *private = impl_from_unix_device(iface); + + EnterCriticalSection(&udev_cs); + list_remove(&private->unix_device.entry); + LeaveCriticalSection(&udev_cs); + + if (private->report_thread) + { + write(private->control_pipe[1], "q", 1); + WaitForSingleObject(private->report_thread, INFINITE); + close(private->control_pipe[0]); + close(private->control_pipe[1]); + CloseHandle(private->report_thread); + } +} + static NTSTATUS hidraw_device_get_report_descriptor(struct unix_device *iface, BYTE *buffer, DWORD length, DWORD *out_length) { @@ -780,6 +785,7 @@ static const struct unix_device_vtbl hidraw_device_vtbl = hidraw_device_destroy, udev_device_compare, hidraw_device_start, + hidraw_device_stop, hidraw_device_get_report_descriptor, hidraw_device_set_output_report, hidraw_device_get_feature_report, @@ -802,19 +808,6 @@ static void lnxev_device_destroy(struct unix_device *iface) { struct wine_input_private *ext = input_impl_from_unix_device(iface);
- EnterCriticalSection(&udev_cs); - list_remove(&ext->base.unix_device.entry); - LeaveCriticalSection(&udev_cs); - - if (ext->base.report_thread) - { - write(ext->base.control_pipe[1], "q", 1); - WaitForSingleObject(ext->base.report_thread, INFINITE); - close(ext->base.control_pipe[0]); - close(ext->base.control_pipe[1]); - CloseHandle(ext->base.report_thread); - } - HeapFree(GetProcessHeap(), 0, ext->current_report_buffer); HeapFree(GetProcessHeap(), 0, ext->last_report_buffer); hid_descriptor_free(&ext->desc); @@ -853,6 +846,24 @@ static NTSTATUS lnxev_device_start(struct unix_device *iface, DEVICE_OBJECT *dev return STATUS_SUCCESS; }
+static void lnxev_device_stop(struct unix_device *iface) +{ + struct wine_input_private *ext = input_impl_from_unix_device(iface); + + EnterCriticalSection(&udev_cs); + list_remove(&ext->base.unix_device.entry); + LeaveCriticalSection(&udev_cs); + + if (ext->base.report_thread) + { + write(ext->base.control_pipe[1], "q", 1); + WaitForSingleObject(ext->base.report_thread, INFINITE); + close(ext->base.control_pipe[0]); + close(ext->base.control_pipe[1]); + CloseHandle(ext->base.report_thread); + } +} + static NTSTATUS lnxev_device_get_report_descriptor(struct unix_device *iface, BYTE *buffer, DWORD length, DWORD *out_length) { @@ -920,6 +931,7 @@ static const struct unix_device_vtbl lnxev_device_vtbl = lnxev_device_destroy, udev_device_compare, lnxev_device_start, + lnxev_device_stop, lnxev_device_get_report_descriptor, lnxev_device_set_output_report, lnxev_device_get_feature_report, diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index 767c9335114..2a878cdb583 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -34,6 +34,7 @@ struct unix_device_vtbl void (*destroy)(struct unix_device *iface); int (*compare)(struct unix_device *iface, void *platform_dev); NTSTATUS (*start)(struct unix_device *iface, DEVICE_OBJECT *device); + void (*stop)(struct unix_device *iface); NTSTATUS (*get_report_descriptor)(struct unix_device *iface, BYTE *buffer, DWORD length, DWORD *out_length); void (*set_output_report)(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io); void (*get_feature_report)(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io); diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c index 67efb794e4f..2407a2af468 100644 --- a/dlls/winebus.sys/unixlib.c +++ b/dlls/winebus.sys/unixlib.c @@ -37,7 +37,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(plugplay); static struct hid_descriptor mouse_desc; static struct hid_descriptor keyboard_desc;
-static void mouse_remove(struct unix_device *iface) +static void mouse_destroy(struct unix_device *iface) { }
@@ -58,6 +58,10 @@ static NTSTATUS mouse_start(struct unix_device *iface, DEVICE_OBJECT *device) return STATUS_SUCCESS; }
+static void mouse_stop(struct unix_device *iface) +{ +} + static NTSTATUS mouse_get_report_descriptor(struct unix_device *iface, BYTE *buffer, DWORD length, DWORD *ret_length) { TRACE("buffer %p, length %u.\n", buffer, length); @@ -92,9 +96,10 @@ static void mouse_set_feature_report(struct unix_device *iface, HID_XFER_PACKET
static const struct unix_device_vtbl mouse_vtbl = { - mouse_remove, + mouse_destroy, mouse_compare, mouse_start, + mouse_stop, mouse_get_report_descriptor, mouse_set_output_report, mouse_get_feature_report, @@ -120,7 +125,7 @@ static NTSTATUS mouse_device_create(void *args) return STATUS_SUCCESS; }
-static void keyboard_remove(struct unix_device *iface) +static void keyboard_destroy(struct unix_device *iface) { }
@@ -141,6 +146,10 @@ static NTSTATUS keyboard_start(struct unix_device *iface, DEVICE_OBJECT *device) return STATUS_SUCCESS; }
+static void keyboard_stop(struct unix_device *iface) +{ +} + static NTSTATUS keyboard_get_report_descriptor(struct unix_device *iface, BYTE *buffer, DWORD length, DWORD *ret_length) { TRACE("buffer %p, length %u.\n", buffer, length); @@ -175,9 +184,10 @@ static void keyboard_set_feature_report(struct unix_device *iface, HID_XFER_PACK
static const struct unix_device_vtbl keyboard_vtbl = { - keyboard_remove, + keyboard_destroy, keyboard_compare, keyboard_start, + keyboard_stop, keyboard_get_report_descriptor, keyboard_set_output_report, keyboard_get_feature_report, @@ -206,6 +216,7 @@ static NTSTATUS keyboard_device_create(void *args) static NTSTATUS unix_device_remove(void *args) { struct unix_device *iface = args; + iface->vtbl->stop(iface); iface->vtbl->destroy(iface); return STATUS_SUCCESS; }