Commit 0017b5eb authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

winebus.sys: Load SDL bus mappings before calling bus_init.

parent 7032b417
/*
* Copyright 2016 Aric Stewart
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <windef.h>
#include <winbase.h>
#include <winternl.h>
#include <ddk/wdm.h>
#include <ddk/hidclass.h>
#include <hidusage.h>
#include "unixlib.h"
extern HANDLE driver_key DECLSPEC_HIDDEN;
......@@ -89,7 +89,6 @@
#include "ddk/hidtypes.h"
#include "wine/debug.h"
#include "bus.h"
#include "unix_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
......
......@@ -50,7 +50,6 @@
# define LE_WORD(x) (x)
#endif
#include "bus.h"
#include "unix_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
......@@ -815,59 +814,11 @@ static void process_device_event(SDL_Event *event)
LeaveCriticalSection(&sdl_cs);
}
static void sdl_load_mappings(void)
NTSTATUS sdl_bus_init(void *args)
{
HKEY key;
static const WCHAR szPath[] = {'m','a','p',0};
const char *mapping;
int i;
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);
}
}
NTSTATUS sdl_bus_init(void *args)
{
TRACE("args %p\n", args);
options = *(struct sdl_bus_options *)args;
......@@ -942,7 +893,21 @@ NTSTATUS sdl_bus_init(void *args)
pSDL_GameControllerEventState(SDL_ENABLE);
/* Process mappings */
if (pSDL_GameControllerAddMapping != NULL) sdl_load_mappings();
if (pSDL_GameControllerAddMapping)
{
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 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)
WARN("Failed to add registry mapping %s\n", pSDL_GetError());
}
}
return STATUS_SUCCESS;
......
......@@ -79,7 +79,6 @@
#define LE_DWORD(x) (x)
#endif
#include "bus.h"
#include "unix_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
......
......@@ -34,7 +34,6 @@
#include "wine/list.h"
#include "wine/unixlib.h"
#include "bus.h"
#include "unixlib.h"
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
......@@ -66,7 +65,7 @@ static DEVICE_OBJECT *keyboard_obj;
static DEVICE_OBJECT *bus_pdo;
static DEVICE_OBJECT *bus_fdo;
HANDLE driver_key;
static HANDLE driver_key;
enum device_state
{
......@@ -630,6 +629,85 @@ static NTSTATUS bus_main_thread_start(struct bus_main_params *bus)
return STATUS_SUCCESS;
}
static void sdl_bus_free_mappings(struct sdl_bus_options *options)
{
DWORD count = options->mappings_count;
char **mappings = options->mappings;
while (count) HeapFree(GetProcessHeap(), 0, mappings[--count]);
HeapFree(GetProcessHeap(), 0, mappings);
}
static void sdl_bus_load_mappings(struct sdl_bus_options *options)
{
static const WCHAR szPath[] = {'m','a','p',0};
ULONG idx = 0, len, count = 0, capacity, info_size, info_max_size;
KEY_VALUE_FULL_INFORMATION *info;
OBJECT_ATTRIBUTES attr = {0};
char **mappings = NULL;
UNICODE_STRING path;
NTSTATUS status;
HANDLE key;
options->mappings_count = 0;
options->mappings = NULL;
RtlInitUnicodeString(&path, szPath);
InitializeObjectAttributes(&attr, &path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, driver_key, NULL);
status = NtOpenKey(&key, KEY_ALL_ACCESS, &attr);
if (status) return;
capacity = 1024;
mappings = HeapAlloc(GetProcessHeap(), 0, capacity * sizeof(*mappings));
info_max_size = offsetof(KEY_VALUE_FULL_INFORMATION, Name) + 512;
info = HeapAlloc(GetProcessHeap(), 0, info_max_size);
while (!status && info && mappings)
{
status = NtEnumerateValueKey(key, idx, KeyValueFullInformation, info, info_max_size, &info_size);
while (status == STATUS_BUFFER_OVERFLOW)
{
info_max_size = info_size;
if (!(info = HeapReAlloc(GetProcessHeap(), 0, info, info_max_size))) break;
status = NtEnumerateValueKey(key, idx, KeyValueFullInformation, info, info_max_size, &info_size);
}
if (status == STATUS_NO_MORE_ENTRIES)
{
options->mappings_count = count;
options->mappings = mappings;
goto done;
}
idx++;
if (status) break;
if (info->Type != REG_SZ) continue;
RtlUnicodeToMultiByteSize(&len, (WCHAR *)((char *)info + info->DataOffset), info_size - info->DataOffset);
if (!len) continue;
if (!(mappings[count++] = HeapAlloc(GetProcessHeap(), 0, len + 1))) break;
if (count > capacity)
{
capacity = capacity * 3 / 2;
if (!(mappings = HeapReAlloc(GetProcessHeap(), 0, mappings, capacity * sizeof(*mappings))))
break;
}
RtlUnicodeToMultiByteN(mappings[count], len, NULL, (WCHAR *)((char *)info + info->DataOffset),
info_size - info->DataOffset);
if (mappings[len - 1]) mappings[len] = 0;
}
if (mappings) while (count) HeapFree(GetProcessHeap(), 0, mappings[--count]);
HeapFree(GetProcessHeap(), 0, mappings);
done:
HeapFree(GetProcessHeap(), 0, info);
NtClose(key);
}
static NTSTATUS sdl_driver_init(void)
{
static const WCHAR bus_name[] = {'S','D','L',0};
......@@ -643,11 +721,15 @@ static NTSTATUS sdl_driver_init(void)
.init_code = sdl_init,
.wait_code = sdl_wait,
};
NTSTATUS status;
bus_options.map_controllers = check_bus_option(&controller_mode, 1);
if (!bus_options.map_controllers) TRACE("SDL controller to XInput HID gamepad mapping disabled\n");
sdl_bus_load_mappings(&bus_options);
return bus_main_thread_start(&bus);
status = bus_main_thread_start(&bus);
sdl_bus_free_mappings(&bus_options);
return status;
}
static NTSTATUS udev_driver_init(void)
......
......@@ -49,6 +49,9 @@ struct device_desc
struct sdl_bus_options
{
BOOL map_controllers;
/* freed after bus_init */
DWORD mappings_count;
char **mappings;
};
struct udev_bus_options
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment