The per-device/vendor option list is allocated on the PE side and shared with the unix, it should be alright to access linked list from both side as winebus should not need and doesn't implement WOW64.
-- v2: winebus: Support per-device/vendor hidraw registry option. winebus: Use a single global structure for bus options.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winebus.sys/bus_iohid.c | 4 +- dlls/winebus.sys/bus_sdl.c | 18 ++++---- dlls/winebus.sys/bus_udev.c | 32 +++++++------ dlls/winebus.sys/main.c | 88 ++++++++++++++++++------------------ dlls/winebus.sys/unixlib.h | 18 ++------ 5 files changed, 78 insertions(+), 82 deletions(-)
diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index 5a210fc6bbd..67276a26c48 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -106,7 +106,7 @@ static IOHIDManagerRef hid_manager; static CFRunLoopRef run_loop; static struct list event_queue = LIST_INIT(event_queue); static struct list device_list = LIST_INIT(device_list); -static struct iohid_bus_options options; +static const struct bus_options *options;
struct iohid_device { @@ -352,7 +352,7 @@ NTSTATUS iohid_bus_init(void *args) { TRACE("args %p\n", args);
- options = *(struct iohid_bus_options *)args; + options = args;
if (!(hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, 0L))) { diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 5cec049a845..2c49f0f408b 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -61,7 +61,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(hid); #ifdef SONAME_LIBSDL2
static pthread_mutex_t sdl_cs = PTHREAD_MUTEX_INITIALIZER; -static struct sdl_bus_options options; +static const struct bus_options *options;
static void *sdl_handle = NULL; static UINT quit_event = -1; @@ -283,7 +283,7 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface) USAGE_AND_PAGE physical_usage;
axis_count = pSDL_JoystickNumAxes(impl->sdl_joystick); - if (options.split_controllers) axis_count = min(6, axis_count - impl->axis_offset); + if (options->split_controllers) axis_count = min(6, axis_count - impl->axis_offset); if (axis_count > ARRAY_SIZE(absolute_axis_usages)) { FIXME("More than %zu absolute axes found, ignoring.\n", ARRAY_SIZE(absolute_axis_usages)); @@ -952,7 +952,7 @@ static void sdl_add_device(unsigned int index) return; }
- if (options.map_controllers && pSDL_IsGameController(index)) + if (options->map_controllers && pSDL_IsGameController(index)) controller = pSDL_GameControllerOpen(index);
if (controller) product = pSDL_GameControllerName(controller); @@ -1027,7 +1027,7 @@ static void sdl_add_device(unsigned int index) }
bus_event_queue_device_created(&event_queue, &impl->unix_device, &desc); - axis_offset += (options.split_controllers ? 6 : axis_count); + axis_offset += (options->split_controllers ? 6 : axis_count); } while (axis_offset < axis_count); } @@ -1050,7 +1050,7 @@ static void process_device_event(SDL_Event *event) if (impl) bus_event_queue_device_removed(&event_queue, &impl->unix_device); else WARN("Failed to find device with id %d\n", id); } - else if (event->type == SDL_JOYAXISMOTION && options.split_controllers) + else if (event->type == SDL_JOYAXISMOTION && options->split_controllers) { id = event->jaxis.which; impl = find_device_from_id_and_axis(id, event->jaxis.axis); @@ -1089,7 +1089,7 @@ NTSTATUS sdl_bus_init(void *args)
TRACE("args %p\n", args);
- options = *(struct sdl_bus_options *)args; + options = (struct bus_options *)args;
if (!(sdl_handle = dlopen(SONAME_LIBSDL2, RTLD_NOW))) { @@ -1182,10 +1182,10 @@ NTSTATUS sdl_bus_init(void *args) if (pSDL_GameControllerAddMapping(mapping) < 0) WARN("Failed to add environment mapping %s\n", pSDL_GetError()); } - else for (i = 0; i < options.mappings_count; ++i) + else for (i = 0; i < options->mappings_count; ++i) { - TRACE("Setting registry mapping %s\n", debugstr_a(options.mappings[i])); - if (pSDL_GameControllerAddMapping(options.mappings[i]) < 0) + TRACE("Setting registry mapping %s\n", debugstr_a(options->mappings[i])); + if (pSDL_GameControllerAddMapping(options->mappings[i]) < 0) WARN("Failed to add registry mapping %s\n", pSDL_GetError()); } } diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 39b810b7588..3f9a4fe43b9 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -99,7 +99,7 @@ static struct udev_monitor *udev_monitor; static int deviceloop_control[2]; static struct list event_queue = LIST_INIT(event_queue); static struct list device_list = LIST_INIT(device_list); -static struct udev_bus_options options; +static const struct bus_options *options;
struct base_device { @@ -1408,7 +1408,7 @@ static void build_initial_deviceset_direct(void) int n, len; DIR *dir;
- if (!options.disable_hidraw) + if (!options->disable_hidraw) { TRACE("Initial enumeration of /dev/hidraw*\n"); if (!(dir = opendir("/dev"))) WARN("Unable to open /dev: %s\n", strerror(errno)); @@ -1425,7 +1425,7 @@ static void build_initial_deviceset_direct(void) } } #ifdef HAS_PROPER_INPUT_HEADER - if (!options.disable_input) + if (!options->disable_input) { TRACE("Initial enumeration of /dev/input/event*\n"); if (!(dir = opendir("/dev/input"))) WARN("Unable to open /dev/input: %s\n", strerror(errno)); @@ -1454,7 +1454,7 @@ static int create_inotify(void) return fd; }
- if (!options.disable_hidraw) + if (!options->disable_hidraw) { /* We need to watch for attribute changes in addition to * creation, because when a device is first created, it has @@ -1466,7 +1466,7 @@ static int create_inotify(void) else systems++; } #ifdef HAS_PROPER_INPUT_HEADER - if (!options.disable_input) + if (!options->disable_input) { devinput_watch = inotify_add_watch(fd, "/dev/input", flags); if (devinput_watch < 0) WARN("Unable to initialize inotify for /dev/input: %s\n", strerror(errno)); @@ -1562,11 +1562,11 @@ static void build_initial_deviceset_udevd(void) return; }
- if (!options.disable_hidraw) + if (!options->disable_hidraw) if (udev_enumerate_add_match_subsystem(enumerate, "hidraw") < 0) WARN("Failed to add subsystem 'hidraw' to enumeration\n"); #ifdef HAS_PROPER_INPUT_HEADER - if (!options.disable_input) + if (!options->disable_input) { if (udev_enumerate_add_match_subsystem(enumerate, "input") < 0) WARN("Failed to add subsystem 'input' to enumeration\n"); @@ -1605,7 +1605,7 @@ static struct udev_monitor *create_monitor(int *fd) return NULL; }
- if (!options.disable_hidraw) + if (!options->disable_hidraw) { if (udev_monitor_filter_add_match_subsystem_devtype(monitor, "hidraw", NULL) < 0) WARN("Failed to add 'hidraw' subsystem to monitor\n"); @@ -1613,7 +1613,7 @@ static struct udev_monitor *create_monitor(int *fd) systems++; } #ifdef HAS_PROPER_INPUT_HEADER - if (!options.disable_input) + if (!options->disable_input) { if (udev_monitor_filter_add_match_subsystem_devtype(monitor, "input", NULL) < 0) WARN("Failed to add 'input' subsystem to monitor\n"); @@ -1685,10 +1685,12 @@ static void process_monitor_event(struct udev_monitor *monitor) NTSTATUS udev_bus_init(void *args) { int monitor_fd = -1; + BOOL disable_udevd;
TRACE("args %p\n", args);
- options = *(struct udev_bus_options *)args; + options = (struct bus_options *)args; + disable_udevd = options->disable_udevd;
if (pipe(deviceloop_control) != 0) { @@ -1703,11 +1705,11 @@ NTSTATUS udev_bus_init(void *args) }
#ifdef HAVE_SYS_INOTIFY_H - if (options.disable_udevd) monitor_fd = create_inotify(); - if (monitor_fd < 0) options.disable_udevd = FALSE; + if (disable_udevd) monitor_fd = create_inotify(); + if (monitor_fd < 0) disable_udevd = FALSE; #else - if (options.disable_udevd) ERR("inotify support not compiled in!\n"); - options.disable_udevd = FALSE; + if (disable_udevd) ERR("inotify support not compiled in!\n"); + disable_udevd = FALSE; #endif
if (monitor_fd < 0 && !(udev_monitor = create_monitor(&monitor_fd))) @@ -1726,7 +1728,7 @@ NTSTATUS udev_bus_init(void *args) poll_fds[1].revents = 0; poll_count = 2;
- if (!options.disable_udevd) build_initial_deviceset_udevd(); + if (!disable_udevd) build_initial_deviceset_udevd(); #ifdef HAVE_SYS_INOTIFY_H else build_initial_deviceset_direct(); #endif diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index e7f16d26a92..fec0c20ed68 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -51,6 +51,7 @@ static DEVICE_OBJECT *keyboard_obj; static DEVICE_OBJECT *bus_pdo; static DEVICE_OBJECT *bus_fdo;
+static struct bus_options options; static HANDLE driver_key;
struct hid_report @@ -426,7 +427,7 @@ static BOOL is_hidraw_enabled(WORD vid, WORD pid, const USAGE_AND_PAGE *usages, UNICODE_STRING str; DWORD size;
- if (check_bus_option(L"DisableHidraw", FALSE)) return FALSE; + if (options.disable_hidraw) return FALSE;
if (usages->UsagePage == HID_USAGE_PAGE_DIGITIZER) { @@ -441,9 +442,7 @@ static BOOL is_hidraw_enabled(WORD vid, WORD pid, const USAGE_AND_PAGE *usages, } if (usages->Usage != HID_USAGE_GENERIC_GAMEPAD && usages->Usage != HID_USAGE_GENERIC_JOYSTICK) return TRUE;
- if (!check_bus_option(L"Enable SDL", 1) && check_bus_option(L"DisableInput", 0)) - prefer_hidraw = TRUE; - + if (options.disable_sdl && options.disable_input) prefer_hidraw = TRUE; if (is_dualshock4_gamepad(vid, pid)) prefer_hidraw = TRUE; if (is_dualsense_gamepad(vid, pid)) prefer_hidraw = TRUE;
@@ -911,7 +910,7 @@ static NTSTATUS bus_main_thread_start(struct bus_main_params *bus) return status; }
-static void sdl_bus_free_mappings(struct sdl_bus_options *options) +static void sdl_bus_free_mappings(struct bus_options *options) { DWORD count = options->mappings_count; char **mappings = options->mappings; @@ -920,7 +919,7 @@ static void sdl_bus_free_mappings(struct sdl_bus_options *options) RtlFreeHeap(GetProcessHeap(), 0, mappings); }
-static void sdl_bus_load_mappings(struct sdl_bus_options *options) +static void sdl_bus_load_mappings(struct bus_options *options) { ULONG idx = 0, len, count = 0, capacity, info_size, info_max_size; UNICODE_STRING path = RTL_CONSTANT_STRING(L"map"); @@ -987,74 +986,74 @@ done: NtClose(key); }
+static void bus_options_init(void) +{ + options.disable_sdl = !check_bus_option(L"Enable SDL", 1); + if (options.disable_sdl) TRACE("SDL devices disabled in registry\n"); + options.disable_hidraw = check_bus_option(L"DisableHidraw", 0); + if (options.disable_hidraw) TRACE("UDEV hidraw devices disabled in registry\n"); + options.disable_input = check_bus_option(L"DisableInput", 0); + if (options.disable_input) TRACE("UDEV input devices disabled in registry\n"); + options.disable_udevd = check_bus_option(L"DisableUdevd", 0); + if (options.disable_udevd) TRACE("UDEV udevd use disabled in registry\n"); + + if (!options.disable_sdl) + { + options.split_controllers = check_bus_option(L"Split Controllers", 0); + if (options.split_controllers) TRACE("SDL controller splitting enabled\n"); + options.map_controllers = check_bus_option(L"Map Controllers", 1); + if (!options.map_controllers) TRACE("SDL controller to XInput HID gamepad mapping disabled\n"); + sdl_bus_load_mappings(&options); + } +} + +static void bus_options_cleanup(void) +{ + if (!options.disable_sdl) sdl_bus_free_mappings(&options); + memset(&options, 0, sizeof(options)); +} + static NTSTATUS sdl_driver_init(void) { - struct sdl_bus_options bus_options; struct bus_main_params bus = { .name = L"SDL", - .init_args = &bus_options, + .init_args = &options, .init_code = sdl_init, .wait_code = sdl_wait, }; - NTSTATUS status; - - bus_options.split_controllers = check_bus_option(L"Split Controllers", 0); - if (bus_options.split_controllers) TRACE("SDL controller splitting enabled\n"); - bus_options.map_controllers = check_bus_option(L"Map Controllers", 1); - if (!bus_options.map_controllers) TRACE("SDL controller to XInput HID gamepad mapping disabled\n"); - sdl_bus_load_mappings(&bus_options); - - status = bus_main_thread_start(&bus); - sdl_bus_free_mappings(&bus_options); - return status; + if (options.disable_sdl) return STATUS_SUCCESS; + return bus_main_thread_start(&bus); }
-static NTSTATUS udev_driver_init(BOOL enable_sdl) +static NTSTATUS udev_driver_init(void) { - struct udev_bus_options bus_options; struct bus_main_params bus = { .name = L"UDEV", - .init_args = &bus_options, + .init_args = &options, .init_code = udev_init, .wait_code = udev_wait, }; - - bus_options.disable_hidraw = check_bus_option(L"DisableHidraw", 0); - if (bus_options.disable_hidraw) TRACE("UDEV hidraw devices disabled in registry\n"); - bus_options.disable_input = check_bus_option(L"DisableInput", 0) || enable_sdl; - if (bus_options.disable_input) TRACE("UDEV input devices disabled in registry\n"); - bus_options.disable_udevd = check_bus_option(L"DisableUdevd", 0); - if (bus_options.disable_udevd) TRACE("UDEV udevd use disabled in registry\n"); - return bus_main_thread_start(&bus); }
static NTSTATUS iohid_driver_init(void) { - struct iohid_bus_options bus_options; struct bus_main_params bus = { .name = L"IOHID", - .init_args = &bus_options, + .init_args = &options, .init_code = iohid_init, .wait_code = iohid_wait, }; - - if (check_bus_option(L"DisableHidraw", FALSE)) - { - TRACE("IOHID hidraw devices disabled in registry\n"); - return STATUS_SUCCESS; - } - + if (options.disable_hidraw) return STATUS_SUCCESS; return bus_main_thread_start(&bus); }
static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); - BOOL enable_sdl; NTSTATUS ret;
switch (irpsp->MinorFunction) @@ -1063,12 +1062,13 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) irp->IoStatus.Status = handle_IRP_MN_QUERY_DEVICE_RELATIONS(irp); break; case IRP_MN_START_DEVICE: + bus_options_init(); + mouse_device_create(); keyboard_device_create();
- if ((enable_sdl = check_bus_option(L"Enable SDL", 1))) - enable_sdl = !sdl_driver_init(); - udev_driver_init(enable_sdl); + if (!sdl_driver_init()) options.disable_input = TRUE; + udev_driver_init(); iohid_driver_init();
irp->IoStatus.Status = STATUS_SUCCESS; @@ -1089,6 +1089,8 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) ret = IoCallDriver(bus_pdo, irp); IoDetachDevice(bus_pdo); IoDeleteDevice(device); + + bus_options_cleanup(); return ret; default: FIXME("Unhandled minor function %#x.\n", irpsp->MinorFunction); diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h index 02e7a1c6953..8064cfe6ffa 100644 --- a/dlls/winebus.sys/unixlib.h +++ b/dlls/winebus.sys/unixlib.h @@ -47,26 +47,18 @@ struct device_desc WCHAR serialnumber[MAX_PATH]; };
-struct sdl_bus_options +struct bus_options { + BOOL disable_sdl; + BOOL disable_hidraw; + BOOL disable_input; + BOOL disable_udevd; BOOL split_controllers; BOOL map_controllers; - /* freed after bus_init */ UINT mappings_count; char **mappings; };
-struct udev_bus_options -{ - BOOL disable_hidraw; - BOOL disable_input; - BOOL disable_udevd; -}; - -struct iohid_bus_options -{ -}; - enum bus_event_type { BUS_EVENT_TYPE_NONE,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winebus.sys/main.c | 111 ++++++++++++++++++++++++++++++++++++- dlls/winebus.sys/unixlib.h | 9 +++ 2 files changed, 118 insertions(+), 2 deletions(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index fec0c20ed68..a9f634a8e42 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -19,6 +19,7 @@ */
#include <stdarg.h> +#include <stdlib.h> #include <assert.h>
#include "ntstatus.h" @@ -51,7 +52,7 @@ static DEVICE_OBJECT *keyboard_obj; static DEVICE_OBJECT *bus_pdo; static DEVICE_OBJECT *bus_fdo;
-static struct bus_options options; +static struct bus_options options = {.devices = LIST_INIT(options.devices)}; static HANDLE driver_key;
struct hid_report @@ -408,8 +409,8 @@ static DWORD check_bus_option(const WCHAR *option, DWORD default_value) UNICODE_STRING str; DWORD size;
+ /* @@ Wine registry key: HKLM\System\CurrentControlSet\Services\WineBus */ RtlInitUnicodeString(&str, option); - if (NtQueryValueKey(driver_key, &str, KeyValuePartialInformation, info, sizeof(buffer), &size) == STATUS_SUCCESS) { if (info->Type == REG_DWORD) return *(DWORD *)info->Data; @@ -422,6 +423,7 @@ static BOOL is_hidraw_enabled(WORD vid, WORD pid, const USAGE_AND_PAGE *usages, { char buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[1024])]; KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + struct device_options *device; WCHAR vidpid[MAX_PATH], *tmp; BOOL prefer_hidraw = FALSE; UNICODE_STRING str; @@ -429,6 +431,14 @@ static BOOL is_hidraw_enabled(WORD vid, WORD pid, const USAGE_AND_PAGE *usages,
if (options.disable_hidraw) return FALSE;
+ LIST_FOR_EACH_ENTRY(device, &options.devices, struct device_options, entry) + { + if (device->vid != vid) continue; + if (device->pid != -1 && device->pid != pid) continue; + if (device->hidraw == -1) continue; + return !!device->hidraw; + } + if (usages->UsagePage == HID_USAGE_PAGE_DIGITIZER) { WARN("Ignoring unsupported %04X:%04X hidraw touchscreen\n", vid, pid); @@ -986,6 +996,91 @@ done: NtClose(key); }
+static struct device_options *add_device_options(UINT vid, UINT pid) +{ + struct device_options *device, *next; + + LIST_FOR_EACH_ENTRY(device, &options.devices, struct device_options, entry) + if (device->vid == vid && device->pid == pid) return device; + + if (!(device = calloc(1, sizeof(*device)))) return NULL; + device->vid = vid; + device->pid = pid; + device->hidraw = -1; + + LIST_FOR_EACH_ENTRY(next, &options.devices, struct device_options, entry) + if (next->vid > vid || (next->vid == vid && next->pid > pid)) break; + list_add_before(&next->entry, &device->entry); + + return device; +} + +static void load_device_options(void) +{ + char buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[1024])]; + KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + UNICODE_STRING path = RTL_CONSTANT_STRING(L"Devices"); + ULONG idx = 0, size, name_max_size; + OBJECT_ATTRIBUTES attr = {0}; + KEY_NAME_INFORMATION *name; + WCHAR name_buffer[32]; + HANDLE key, subkey; + NTSTATUS status; + + /* @@ Wine registry key: HKLM\System\CurrentControlSet\Services\WineBus\Devices */ + InitializeObjectAttributes(&attr, &path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, driver_key, NULL); + status = NtOpenKey(&key, KEY_ALL_ACCESS, &attr); + if (status) return; + + name_max_size = offsetof(KEY_NAME_INFORMATION, Name) + 512; + name = RtlAllocateHeap(GetProcessHeap(), 0, name_max_size); + + while (!status && name) + { + static const UNICODE_STRING hidraw = RTL_CONSTANT_STRING(L"Hidraw"); + static const UNICODE_STRING backslash = RTL_CONSTANT_STRING(L"\"); + struct device_options *device; + UNICODE_STRING name_str; + UINT vid, pid; + USHORT pos; + int ret; + + status = NtEnumerateKey(key, idx, KeyNameInformation, name, name_max_size, &size); + while (status == STATUS_BUFFER_OVERFLOW) + { + name_max_size = size; + if (!(name = RtlReAllocateHeap(GetProcessHeap(), 0, name, name_max_size))) break; + status = NtEnumerateKey(key, idx, KeyNameInformation, name, name_max_size, &size); + } + if (status == STATUS_NO_MORE_ENTRIES) break; + idx++; + + /* @@ Wine registry key: HKLM\System\CurrentControlSet\Services\WineBus\Devices<VID[/PID]> */ + name_str.Buffer = name->Name; + name_str.Length = name->NameLength; + InitializeObjectAttributes(&attr, &name_str, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL); + if (NtOpenKey(&subkey, KEY_ALL_ACCESS, &attr)) continue; + + if (!RtlFindCharInUnicodeString(1, &name_str, &backslash, &pos)) pos += sizeof(WCHAR); + if (name->NameLength - pos >= sizeof(name_buffer)) continue; + + memcpy(name_buffer, name->Name + pos / sizeof(WCHAR), name->NameLength - pos); + name_buffer[(name->NameLength - pos) / sizeof(WCHAR)] = 0; + + if ((ret = swscanf(name_buffer, L"%04x/%04x", &vid, &pid)) < 1) continue; + if (!(device = add_device_options(vid, ret == 1 ? -1 : pid))) continue; + + if (!NtQueryValueKey(subkey, &hidraw, KeyValuePartialInformation, info, sizeof(buffer), &size) && info->Type == REG_DWORD) + device->hidraw = *(DWORD *)info->Data; + if (device->hidraw != -1) TRACE("- %04x/%04x: %sabling hidraw\n", device->vid, device->pid, device->hidraw ? "en" : "dis"); + + NtClose(subkey); + } + + RtlFreeHeap(GetProcessHeap(), 0, name); + NtClose(key); +} + static void bus_options_init(void) { options.disable_sdl = !check_bus_option(L"Enable SDL", 1); @@ -1005,12 +1100,24 @@ static void bus_options_init(void) if (!options.map_controllers) TRACE("SDL controller to XInput HID gamepad mapping disabled\n"); sdl_bus_load_mappings(&options); } + + load_device_options(); }
static void bus_options_cleanup(void) { + struct device_options *device, *next; + if (!options.disable_sdl) sdl_bus_free_mappings(&options); + + LIST_FOR_EACH_ENTRY_SAFE(device, next, &options.devices, struct device_options, entry) + { + list_remove(&device->entry); + free(device); + } + memset(&options, 0, sizeof(options)); + list_init(&options.devices); }
static NTSTATUS sdl_driver_init(void) diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h index 8064cfe6ffa..8dab8af0d57 100644 --- a/dlls/winebus.sys/unixlib.h +++ b/dlls/winebus.sys/unixlib.h @@ -47,6 +47,14 @@ struct device_desc WCHAR serialnumber[MAX_PATH]; };
+struct device_options +{ + struct list entry; + UINT vid; + UINT pid; + INT hidraw; +}; + struct bus_options { BOOL disable_sdl; @@ -56,6 +64,7 @@ struct bus_options BOOL split_controllers; BOOL map_controllers; UINT mappings_count; + struct list devices; char **mappings; };
v2: Only implement the hidraw preference option for now.