Or we may have a race condition where a pending IRP may be completed after we left the CS but before we read its status.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 001f775e230..b7230cf2e33 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -982,9 +982,9 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) break; }
+ status = irp->IoStatus.Status; LeaveCriticalSection(&ext->cs);
- status = irp->IoStatus.Status; if (status != STATUS_PENDING) IoCompleteRequest(irp, IO_NO_INCREMENT); return status; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_udev.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index c411e9e3929..4a494abac09 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -166,11 +166,6 @@ static const BYTE REL_TO_HID_MAP[][2] = { #define HID_REL_MAX (REL_MISC+1) #define TOP_REL_PAGE (HID_USAGE_PAGE_CONSUMER+1)
-struct wine_input_absinfo { - struct input_absinfo info; - BYTE report_index; -}; - struct wine_input_private { struct platform_private base;
@@ -186,7 +181,7 @@ struct wine_input_private { BYTE rel_map[HID_REL_MAX]; BYTE hat_map[8]; int hat_values[8]; - struct wine_input_absinfo abs_map[HID_ABS_MAX]; + int abs_map[HID_ABS_MAX]; };
#define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7))) @@ -287,7 +282,7 @@ static void set_abs_axis_value(struct wine_input_private *ext, int code, int val } else if (code < HID_ABS_MAX && ABS_TO_HID_MAP[code][0] != 0) { - index = ext->abs_map[code].report_index; + index = ext->abs_map[code]; *((DWORD*)&ext->current_report_buffer[index]) = LE_DWORD(value); } } @@ -349,6 +344,7 @@ static INT count_abs_axis(int device_fd)
static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_device *dev) { + struct input_absinfo abs_info[HID_ABS_MAX]; int abs_pages[TOP_ABS_PAGE][HID_ABS_MAX+1]; int rel_pages[TOP_REL_PAGE][HID_REL_MAX+1]; BYTE absbits[(ABS_MAX+7)/8]; @@ -379,7 +375,7 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_ abs_pages[ABS_TO_HID_MAP[i][0]][0]++; abs_pages[ABS_TO_HID_MAP[i][0]][abs_pages[ABS_TO_HID_MAP[i][0]][0]] = i;
- ioctl(ext->base.device_fd, EVIOCGABS(i), &(ext->abs_map[i])); + ioctl(ext->base.device_fd, EVIOCGABS(i), abs_info + i); } /* Skip page 0, aka HID_USAGE_PAGE_UNDEFINED */ for (i = 1; i < TOP_ABS_PAGE; i++) @@ -388,7 +384,7 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_ int j; for (j = 1; j <= abs_pages[i][0]; j++) { - ext->abs_map[abs_pages[i][j]].report_index = report_size; + ext->abs_map[abs_pages[i][j]] = report_size; report_size+=4; } abs_count++; @@ -450,8 +446,8 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_ for (j = 0; j < abs_pages[i][0]; j++) usages[j] = ABS_TO_HID_MAP[abs_pages[i][j+1]][1]; if (!hid_descriptor_add_axes(&ext->desc, abs_pages[i][0], i, usages, FALSE, 32, - LE_DWORD(ext->abs_map[abs_pages[i][1]].info.minimum), - LE_DWORD(ext->abs_map[abs_pages[i][1]].info.maximum))) + LE_DWORD(abs_info[abs_pages[i][1]].minimum), + LE_DWORD(abs_info[abs_pages[i][1]].maximum))) return FALSE; } } @@ -502,7 +498,7 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_ /* Initialize axis in the report */ for (i = 0; i < HID_ABS_MAX; i++) if (test_bit(absbits, i)) - set_abs_axis_value(ext, i, ext->abs_map[i].info.value); + set_abs_axis_value(ext, i, abs_info[i].value);
return TRUE;
Fixing invalid axis range when they differ between two axis of the same usage page.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_udev.c | 140 +++++++++++++----------------------- 1 file changed, 48 insertions(+), 92 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 4a494abac09..816adcc6539 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -62,6 +62,7 @@ #include "winternl.h" #include "ddk/wdm.h" #include "ddk/hidtypes.h" +#include "ddk/hidsdi.h" #include "wine/debug.h" #include "wine/heap.h" #include "wine/unicode.h" @@ -345,10 +346,9 @@ static INT count_abs_axis(int device_fd) static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_device *dev) { struct input_absinfo abs_info[HID_ABS_MAX]; - int abs_pages[TOP_ABS_PAGE][HID_ABS_MAX+1]; - int rel_pages[TOP_REL_PAGE][HID_REL_MAX+1]; BYTE absbits[(ABS_MAX+7)/8]; BYTE relbits[(REL_MAX+7)/8]; + USAGE_AND_PAGE usage; INT i; INT report_size; INT button_count, abs_count, rel_count, hat_count; @@ -367,106 +367,46 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
report_size = 0;
+ if (!hid_descriptor_begin(&ext->desc, device_usage[0], device_usage[1])) + return FALSE; + abs_count = 0; - memset(abs_pages, 0, sizeof(abs_pages)); for (i = 0; i < HID_ABS_MAX; i++) - if (test_bit(absbits, i)) - { - abs_pages[ABS_TO_HID_MAP[i][0]][0]++; - abs_pages[ABS_TO_HID_MAP[i][0]][abs_pages[ABS_TO_HID_MAP[i][0]][0]] = i; + { + if (!test_bit(absbits, i)) continue; + ioctl(ext->base.device_fd, EVIOCGABS(i), abs_info + i);
- ioctl(ext->base.device_fd, EVIOCGABS(i), abs_info + i); - } - /* Skip page 0, aka HID_USAGE_PAGE_UNDEFINED */ - for (i = 1; i < TOP_ABS_PAGE; i++) - if (abs_pages[i][0] > 0) - { - int j; - for (j = 1; j <= abs_pages[i][0]; j++) - { - ext->abs_map[abs_pages[i][j]] = report_size; - report_size+=4; - } - abs_count++; - } + if (!(usage.UsagePage = ABS_TO_HID_MAP[i][0])) continue; + if (!(usage.Usage = ABS_TO_HID_MAP[i][1])) continue;
- rel_count = 0; - memset(rel_pages, 0, sizeof(rel_pages)); - for (i = 0; i < HID_REL_MAX; i++) - if (test_bit(relbits, i)) - { - rel_pages[REL_TO_HID_MAP[i][0]][0]++; - rel_pages[REL_TO_HID_MAP[i][0]][rel_pages[REL_TO_HID_MAP[i][0]][0]] = i; - } - /* Skip page 0, aka HID_USAGE_PAGE_UNDEFINED */ - for (i = 1; i < TOP_REL_PAGE; i++) - if (rel_pages[i][0] > 0) - { - int j; - for (j = 1; j <= rel_pages[i][0]; j++) - { - ext->rel_map[rel_pages[i][j]] = report_size; - report_size++; - } - rel_count++; - } + if (!hid_descriptor_add_axes(&ext->desc, 1, usage.UsagePage, &usage.Usage, FALSE, 32, + LE_DWORD(abs_info[i].minimum), LE_DWORD(abs_info[i].maximum))) + return FALSE;
- /* For now lump all buttons just into incremental usages, Ignore Keys */ - ext->button_start = report_size; - button_count = count_buttons(ext->base.device_fd, ext->button_map); - if (button_count) - { - report_size += (button_count + 7) / 8; + ext->abs_map[i] = report_size; + report_size += 4; + abs_count++; }
- hat_count = 0; - for (i = ABS_HAT0X; i <=ABS_HAT3X; i+=2) - if (test_bit(absbits, i)) - { - ext->hat_map[i - ABS_HAT0X] = report_size; - ext->hat_values[i - ABS_HAT0X] = 0; - ext->hat_values[i - ABS_HAT0X + 1] = 0; - report_size++; - hat_count++; - } - - TRACE("Report will be %i bytes\n", report_size); + rel_count = 0; + for (i = 0; i < HID_REL_MAX; i++) + { + if (!test_bit(relbits, i)) continue; + if (!(usage.UsagePage = REL_TO_HID_MAP[i][0])) continue; + if (!(usage.Usage = REL_TO_HID_MAP[i][1])) continue;
- if (!hid_descriptor_begin(&ext->desc, device_usage[0], device_usage[1])) - return FALSE; + if (!hid_descriptor_add_axes(&ext->desc, 1, usage.UsagePage, &usage.Usage, TRUE, 8, + 0x81, 0x7f)) + return FALSE;
- if (abs_count) - { - for (i = 1; i < TOP_ABS_PAGE; i++) - { - if (abs_pages[i][0]) - { - USAGE usages[HID_ABS_MAX]; - int j; - for (j = 0; j < abs_pages[i][0]; j++) - usages[j] = ABS_TO_HID_MAP[abs_pages[i][j+1]][1]; - if (!hid_descriptor_add_axes(&ext->desc, abs_pages[i][0], i, usages, FALSE, 32, - LE_DWORD(abs_info[abs_pages[i][1]].minimum), - LE_DWORD(abs_info[abs_pages[i][1]].maximum))) - return FALSE; - } - } - } - if (rel_count) - { - for (i = 1; i < TOP_REL_PAGE; i++) - { - if (rel_pages[i][0]) - { - USAGE usages[HID_REL_MAX]; - int j; - for (j = 0; j < rel_pages[i][0]; j++) - usages[j] = REL_TO_HID_MAP[rel_pages[i][j+1]][1]; - if (!hid_descriptor_add_axes(&ext->desc, rel_pages[i][0], i, usages, TRUE, 8, 0x81, 0x7f)) - return FALSE; - } - } + ext->rel_map[i] = report_size; + report_size++; + rel_count++; } + + /* For now lump all buttons just into incremental usages, Ignore Keys */ + ext->button_start = report_size; + button_count = count_buttons(ext->base.device_fd, ext->button_map); if (button_count) { if (!hid_descriptor_add_buttons(&ext->desc, HID_USAGE_PAGE_BUTTON, 1, button_count)) @@ -478,7 +418,21 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_ if (!hid_descriptor_add_padding(&ext->desc, padding)) return FALSE; } + + report_size += (button_count + 7) / 8; } + + hat_count = 0; + for (i = ABS_HAT0X; i <=ABS_HAT3X; i+=2) + { + if (!test_bit(absbits, i)) continue; + ext->hat_map[i - ABS_HAT0X] = report_size; + ext->hat_values[i - ABS_HAT0X] = 0; + ext->hat_values[i - ABS_HAT0X + 1] = 0; + report_size++; + hat_count++; + } + if (hat_count) { if (!hid_descriptor_add_hatswitch(&ext->desc, hat_count)) @@ -488,6 +442,8 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_ if (!hid_descriptor_end(&ext->desc)) return FALSE;
+ TRACE("Report will be %i bytes\n", report_size); + ext->buffer_length = report_size; if (!(ext->current_report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size))) goto failed;
This was inconsistently forcing the first report byte to the report id.
The report ids are stripped when they aren't used, in the packet hidclass.sys provides, but hidraw API wants them all the time, so we need to use an intermediate buffer.
Also ioctl length argument have a lower size capacity, so we have to check for it as well.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_udev.c | 83 ++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 43 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 816adcc6539..b9466b0178b 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -720,32 +720,27 @@ static NTSTATUS begin_report_processing(DEVICE_OBJECT *device) static NTSTATUS hidraw_set_output_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *written) { struct platform_private* ext = impl_from_DEVICE_OBJECT(device); - int rc; + BYTE buffer[8192]; + int count = 0;
- if (id != 0) - rc = write(ext->device_fd, report, length); + if ((buffer[0] = id)) + count = write(ext->device_fd, report, length); + else if (length > sizeof(buffer) - 1) + ERR_(hid_report)("id %d length %u >= 8192, cannot write\n", id, length); else { - BYTE report_buffer[1024]; - - if (length + 1 > sizeof(report_buffer)) - { - ERR("Output report buffer too small\n"); - return STATUS_UNSUCCESSFUL; - } - - report_buffer[0] = 0; - memcpy(&report_buffer[1], report, length); - rc = write(ext->device_fd, report_buffer, length + 1); + memcpy(buffer + 1, report, length); + count = write(ext->device_fd, buffer, length + 1); } - if (rc > 0) + + if (count > 0) { - *written = rc; + *written = count; return STATUS_SUCCESS; } else { - TRACE("write failed: %d %d %s\n", rc, errno, strerror(errno)); + ERR_(hid_report)("id %d write failed error: %d %s\n", id, errno, strerror(errno)); *written = 0; return STATUS_UNSUCCESSFUL; } @@ -754,19 +749,28 @@ static NTSTATUS hidraw_set_output_report(DEVICE_OBJECT *device, UCHAR id, BYTE * static NTSTATUS hidraw_get_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *read) { #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCGFEATURE) - int rc; struct platform_private* ext = impl_from_DEVICE_OBJECT(device); - report[0] = id; - length = min(length, 0x1fff); - rc = ioctl(ext->device_fd, HIDIOCGFEATURE(length), report); - if (rc >= 0) + BYTE buffer[8192]; + int count = 0; + + if ((buffer[0] = id) && length <= 0x1fff) + count = ioctl(ext->device_fd, HIDIOCGFEATURE(length), report); + else if (length > sizeof(buffer) - 1) + ERR_(hid_report)("id %d length %u >= 8192, cannot read\n", id, length); + else { - *read = rc; + count = ioctl(ext->device_fd, HIDIOCGFEATURE(length + 1), buffer); + memcpy(report, buffer + 1, length); + } + + if (count > 0) + { + *read = count; return STATUS_SUCCESS; } else { - TRACE_(hid_report)("ioctl(HIDIOCGFEATURE(%d)) failed: %d %s\n", length, errno, strerror(errno)); + ERR_(hid_report)("id %d read failed, error: %d %s\n", id, errno, strerror(errno)); *read = 0; return STATUS_UNSUCCESSFUL; } @@ -779,35 +783,28 @@ static NTSTATUS hidraw_get_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE static NTSTATUS hidraw_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *written) { #if defined(HAVE_LINUX_HIDRAW_H) && defined(HIDIOCSFEATURE) - int rc; struct platform_private* ext = impl_from_DEVICE_OBJECT(device); - BYTE *feature_buffer; BYTE buffer[8192]; + int count = 0;
- if (id == 0) + if ((buffer[0] = id) && length <= 0x1fff) + count = ioctl(ext->device_fd, HIDIOCSFEATURE(length), report); + else if (length > sizeof(buffer) - 1) + ERR_(hid_report)("id %d length %u >= 8192, cannot write\n", id, length); + else { - if (length + 1 > sizeof(buffer)) - { - ERR("Output feature buffer too small\n"); - return STATUS_UNSUCCESSFUL; - } - buffer[0] = 0; - memcpy(&buffer[1], report, length); - feature_buffer = buffer; - length = length + 1; + memcpy(buffer + 1, report, length); + count = ioctl(ext->device_fd, HIDIOCSFEATURE(length + 1), buffer); } - else - feature_buffer = report; - length = min(length, 0x1fff); - rc = ioctl(ext->device_fd, HIDIOCSFEATURE(length), feature_buffer); - if (rc >= 0) + + if (count > 0) { - *written = rc; + *written = count; return STATUS_SUCCESS; } else { - TRACE_(hid_report)("ioctl(HIDIOCSFEATURE(%d)) failed: %d %s\n", length, errno, strerror(errno)); + ERR_(hid_report)("id %d write failed, error: %d %s\n", id, errno, strerror(errno)); *written = 0; return STATUS_UNSUCCESSFUL; }
The comparison result was wrong, and the device syspath always differs anyway between two different subsystems. We need to compare the parent device syspath.
The input subsystem devices also needs to be deduplicated between eventX devices and jsX devices.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
We could keep the syspath on the device instead of requesting it every time, but it should not be too bad and I intend to rewrite the code later anyway with the unixlib conversion.
dlls/winebus.sys/bus_udev.c | 48 ++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 19 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index b9466b0178b..887996daf49 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -976,9 +976,23 @@ static const platform_vtbl lnxev_vtbl = { }; #endif
-static int check_same_device(DEVICE_OBJECT *device, void* context) +static const char *get_device_syspath(struct udev_device *dev) { - return !compare_platform_device(device, context); + struct udev_device *parent; + + if ((parent = udev_device_get_parent_with_subsystem_devtype(dev, "hid", NULL))) + return udev_device_get_syspath(parent); + + if ((parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device"))) + return udev_device_get_syspath(parent); + + return ""; +} + +static int check_device_syspath(DEVICE_OBJECT *device, void* context) +{ + struct platform_private *private = impl_from_DEVICE_OBJECT(device); + return strcmp(get_device_syspath(private->udev_device), context); }
static int parse_uevent_info(const char *uevent, DWORD *vendor_id, @@ -1078,28 +1092,24 @@ static void try_add_device(struct udev_device *dev) return; }
+ TRACE("udev %s syspath %s\n", debugstr_a(devnode), udev_device_get_syspath(dev)); + +#ifdef HAS_PROPER_INPUT_HEADER + device = bus_enumerate_hid_devices(&lnxev_vtbl, check_device_syspath, (void *)get_device_syspath(dev)); + if (!device) device = bus_enumerate_hid_devices(&hidraw_vtbl, check_device_syspath, (void *)get_device_syspath(dev)); + if (device) + { + TRACE("duplicate device found, not adding the new one\n"); + close(fd); + return; + } +#endif + subsystem = udev_device_get_subsystem(dev); hiddev = udev_device_get_parent_with_subsystem_devtype(dev, "hid", NULL); if (hiddev) { const char *bcdDevice = NULL; -#ifdef HAS_PROPER_INPUT_HEADER - const platform_vtbl *other_vtbl = NULL; - DEVICE_OBJECT *dup = NULL; - if (strcmp(subsystem, "hidraw") == 0) - other_vtbl = &lnxev_vtbl; - else if (strcmp(subsystem, "input") == 0) - other_vtbl = &hidraw_vtbl; - - if (other_vtbl) - dup = bus_enumerate_hid_devices(other_vtbl, check_same_device, dev); - if (dup) - { - TRACE("Duplicate cross bus device (%p) found, not adding the new one\n", dup); - close(fd); - return; - } -#endif parse_uevent_info(udev_device_get_sysattr_value(hiddev, "uevent"), &vid, &pid, &input, &serial); if (serial == NULL)
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 116 ++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 52 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 572b46b4114..d866fb0d8bb 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -968,6 +968,69 @@ void sdl_driver_unload( void ) dlclose(sdl_handle); }
+static BOOL sdl_initialize(void) +{ + if (!(sdl_handle = dlopen(SONAME_LIBSDL2, RTLD_NOW))) + { + WARN("could not load %s\n", SONAME_LIBSDL2); + return FALSE; + } +#define LOAD_FUNCPTR(f) \ + if ((p##f = dlsym(sdl_handle, #f)) == NULL) \ + { \ + WARN("could not find symbol %s\n", #f); \ + goto failed; \ + } + LOAD_FUNCPTR(SDL_GetError); + LOAD_FUNCPTR(SDL_Init); + LOAD_FUNCPTR(SDL_JoystickClose); + LOAD_FUNCPTR(SDL_JoystickEventState); + LOAD_FUNCPTR(SDL_JoystickGetGUID); + LOAD_FUNCPTR(SDL_JoystickGetGUIDString); + LOAD_FUNCPTR(SDL_JoystickInstanceID); + LOAD_FUNCPTR(SDL_JoystickName); + LOAD_FUNCPTR(SDL_JoystickNumAxes); + LOAD_FUNCPTR(SDL_JoystickOpen); + LOAD_FUNCPTR(SDL_WaitEvent); + LOAD_FUNCPTR(SDL_JoystickNumButtons); + LOAD_FUNCPTR(SDL_JoystickNumBalls); + LOAD_FUNCPTR(SDL_JoystickNumHats); + LOAD_FUNCPTR(SDL_JoystickGetAxis); + LOAD_FUNCPTR(SDL_JoystickGetHat); + LOAD_FUNCPTR(SDL_IsGameController); + LOAD_FUNCPTR(SDL_GameControllerClose); + LOAD_FUNCPTR(SDL_GameControllerGetAxis); + LOAD_FUNCPTR(SDL_GameControllerGetButton); + LOAD_FUNCPTR(SDL_GameControllerName); + LOAD_FUNCPTR(SDL_GameControllerOpen); + LOAD_FUNCPTR(SDL_GameControllerEventState); + LOAD_FUNCPTR(SDL_HapticClose); + LOAD_FUNCPTR(SDL_HapticDestroyEffect); + LOAD_FUNCPTR(SDL_HapticNewEffect); + LOAD_FUNCPTR(SDL_HapticOpenFromJoystick); + LOAD_FUNCPTR(SDL_HapticQuery); + LOAD_FUNCPTR(SDL_HapticRumbleInit); + LOAD_FUNCPTR(SDL_HapticRumblePlay); + LOAD_FUNCPTR(SDL_HapticRumbleSupported); + LOAD_FUNCPTR(SDL_HapticRunEffect); + LOAD_FUNCPTR(SDL_HapticStopAll); + LOAD_FUNCPTR(SDL_JoystickIsHaptic); + LOAD_FUNCPTR(SDL_memset); + LOAD_FUNCPTR(SDL_GameControllerAddMapping); + LOAD_FUNCPTR(SDL_RegisterEvents); + LOAD_FUNCPTR(SDL_PushEvent); +#undef LOAD_FUNCPTR + pSDL_JoystickGetProduct = dlsym(sdl_handle, "SDL_JoystickGetProduct"); + pSDL_JoystickGetProductVersion = dlsym(sdl_handle, "SDL_JoystickGetProductVersion"); + pSDL_JoystickGetVendor = dlsym(sdl_handle, "SDL_JoystickGetVendor"); + return TRUE; + +failed: + dlclose(sdl_handle); + sdl_handle = NULL; + return FALSE; +} + NTSTATUS sdl_driver_init(void) { static const WCHAR controller_modeW[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0}; @@ -976,57 +1039,7 @@ NTSTATUS sdl_driver_init(void) HANDLE events[2]; DWORD result;
- if (sdl_handle == NULL) - { - sdl_handle = dlopen(SONAME_LIBSDL2, RTLD_NOW); - if (!sdl_handle) { - WARN("could not load %s\n", SONAME_LIBSDL2); - return STATUS_UNSUCCESSFUL; - } -#define LOAD_FUNCPTR(f) if((p##f = dlsym(sdl_handle, #f)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;} - LOAD_FUNCPTR(SDL_GetError); - LOAD_FUNCPTR(SDL_Init); - LOAD_FUNCPTR(SDL_JoystickClose); - LOAD_FUNCPTR(SDL_JoystickEventState); - LOAD_FUNCPTR(SDL_JoystickGetGUID); - LOAD_FUNCPTR(SDL_JoystickGetGUIDString); - LOAD_FUNCPTR(SDL_JoystickInstanceID); - LOAD_FUNCPTR(SDL_JoystickName); - LOAD_FUNCPTR(SDL_JoystickNumAxes); - LOAD_FUNCPTR(SDL_JoystickOpen); - LOAD_FUNCPTR(SDL_WaitEvent); - LOAD_FUNCPTR(SDL_JoystickNumButtons); - LOAD_FUNCPTR(SDL_JoystickNumBalls); - LOAD_FUNCPTR(SDL_JoystickNumHats); - LOAD_FUNCPTR(SDL_JoystickGetAxis); - LOAD_FUNCPTR(SDL_JoystickGetHat); - LOAD_FUNCPTR(SDL_IsGameController); - LOAD_FUNCPTR(SDL_GameControllerClose); - LOAD_FUNCPTR(SDL_GameControllerGetAxis); - LOAD_FUNCPTR(SDL_GameControllerGetButton); - LOAD_FUNCPTR(SDL_GameControllerName); - LOAD_FUNCPTR(SDL_GameControllerOpen); - LOAD_FUNCPTR(SDL_GameControllerEventState); - LOAD_FUNCPTR(SDL_HapticClose); - LOAD_FUNCPTR(SDL_HapticDestroyEffect); - LOAD_FUNCPTR(SDL_HapticNewEffect); - LOAD_FUNCPTR(SDL_HapticOpenFromJoystick); - LOAD_FUNCPTR(SDL_HapticQuery); - LOAD_FUNCPTR(SDL_HapticRumbleInit); - LOAD_FUNCPTR(SDL_HapticRumblePlay); - LOAD_FUNCPTR(SDL_HapticRumbleSupported); - LOAD_FUNCPTR(SDL_HapticRunEffect); - LOAD_FUNCPTR(SDL_HapticStopAll); - LOAD_FUNCPTR(SDL_JoystickIsHaptic); - LOAD_FUNCPTR(SDL_memset); - LOAD_FUNCPTR(SDL_GameControllerAddMapping); - LOAD_FUNCPTR(SDL_RegisterEvents); - LOAD_FUNCPTR(SDL_PushEvent); -#undef LOAD_FUNCPTR - pSDL_JoystickGetProduct = dlsym(sdl_handle, "SDL_JoystickGetProduct"); - pSDL_JoystickGetProductVersion = dlsym(sdl_handle, "SDL_JoystickGetProductVersion"); - pSDL_JoystickGetVendor = dlsym(sdl_handle, "SDL_JoystickGetVendor"); - } + if (!sdl_handle && !sdl_initialize()) return STATUS_UNSUCCESSFUL;
map_controllers = check_bus_option(&controller_mode, 1);
@@ -1052,7 +1065,6 @@ NTSTATUS sdl_driver_init(void) } CloseHandle(events[1]);
-sym_not_found: dlclose(sdl_handle); sdl_handle = NULL; return STATUS_UNSUCCESSFUL;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 103 +++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 51 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index d866fb0d8bb..8c9886c7d3c 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -862,6 +862,57 @@ static void process_device_event(SDL_Event *event) set_mapped_report_from_event(event); }
+static void sdl_load_mappings(void) +{ + HKEY key; + static const WCHAR szPath[] = {'m','a','p',0}; + const char *mapping; + + if ((mapping = getenv("SDL_GAMECONTROLLERCONFIG"))) + { + TRACE("Setting environment mapping %s\n", debugstr_a(mapping)); + if (pSDL_GameControllerAddMapping(mapping) < 0) + WARN("Failed to add environment mapping %s\n", pSDL_GetError()); + } + else if (!RegOpenKeyExW(driver_key, szPath, 0, KEY_QUERY_VALUE, &key)) + { + DWORD index = 0; + CHAR *buffer = NULL; + DWORD buffer_len = 0; + LSTATUS rc; + + do + { + CHAR name[255]; + DWORD name_len; + DWORD type; + DWORD data_len = buffer_len; + + name_len = sizeof(name); + rc = RegEnumValueA(key, index, name, &name_len, NULL, &type, (LPBYTE)buffer, &data_len); + if (rc == ERROR_MORE_DATA || buffer == NULL) + { + if (buffer) buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, data_len); + else buffer = HeapAlloc(GetProcessHeap(), 0, data_len); + buffer_len = data_len; + + name_len = sizeof(name); + rc = RegEnumValueA(key, index, name, &name_len, NULL, &type, (LPBYTE)buffer, &data_len); + } + + if (rc == STATUS_SUCCESS) + { + TRACE("Setting registry mapping %s\n", debugstr_a(buffer)); + if (pSDL_GameControllerAddMapping(buffer) < 0) + WARN("Failed to add registry mapping %s\n", pSDL_GetError()); + index++; + } + } while (rc == STATUS_SUCCESS); + HeapFree(GetProcessHeap(), 0, buffer); + NtClose(key); + } +} + static DWORD CALLBACK deviceloop_thread(void *args) { HANDLE init_done = args; @@ -877,57 +928,7 @@ static DWORD CALLBACK deviceloop_thread(void *args) pSDL_GameControllerEventState(SDL_ENABLE);
/* Process mappings */ - if (pSDL_GameControllerAddMapping != NULL) - { - HKEY key; - static const WCHAR szPath[] = {'m','a','p',0}; - const char *mapping; - - if ((mapping = getenv("SDL_GAMECONTROLLERCONFIG"))) - { - TRACE("Setting environment mapping %s\n", debugstr_a(mapping)); - if (pSDL_GameControllerAddMapping(mapping) < 0) - WARN("Failed to add environment mapping %s\n", pSDL_GetError()); - } - else if (!RegOpenKeyExW(driver_key, szPath, 0, KEY_QUERY_VALUE, &key)) - { - DWORD index = 0; - CHAR *buffer = NULL; - DWORD buffer_len = 0; - LSTATUS rc; - - do { - CHAR name[255]; - DWORD name_len; - DWORD type; - DWORD data_len = buffer_len; - - name_len = sizeof(name); - rc = RegEnumValueA(key, index, name, &name_len, NULL, &type, (LPBYTE)buffer, &data_len); - if (rc == ERROR_MORE_DATA || buffer == NULL) - { - if (buffer) - buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, data_len); - else - buffer = HeapAlloc(GetProcessHeap(), 0, data_len); - buffer_len = data_len; - - name_len = sizeof(name); - rc = RegEnumValueA(key, index, name, &name_len, NULL, &type, (LPBYTE)buffer, &data_len); - } - - if (rc == STATUS_SUCCESS) - { - TRACE("Setting registry mapping %s\n", debugstr_a(buffer)); - if (pSDL_GameControllerAddMapping(buffer) < 0) - WARN("Failed to add registry mapping %s\n", pSDL_GetError()); - index ++; - } - } while (rc == STATUS_SUCCESS); - HeapFree(GetProcessHeap(), 0, buffer); - NtClose(key); - } - } + if (pSDL_GameControllerAddMapping != NULL) sdl_load_mappings();
SetEvent(init_done);