wined3d: Use wined3d_resource_gl_legacy_map_flags() in wined3d_buffer_gl_map().
[wine.git] / dlls / winebus.sys / bus_sdl.c
blob8fcec46d04d6ed42e3c2eeddd5b6381bcff482cc
1 /*
2 * Plug and Play support for hid devices found through SDL2
4 * Copyright 2017 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
21 #include "config.h"
22 #include "wine/port.h"
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #ifdef HAVE_SDL2_SDL_H
31 # include <SDL2/SDL.h>
32 #endif
34 #define NONAMELESSUNION
36 #include "ntstatus.h"
37 #define WIN32_NO_STATUS
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winnls.h"
41 #include "winreg.h"
42 #include "winternl.h"
43 #include "ddk/wdm.h"
44 #include "ddk/hidtypes.h"
45 #include "wine/library.h"
46 #include "wine/debug.h"
47 #include "wine/unicode.h"
48 #include "hidusage.h"
49 #include "controller.h"
51 #ifdef WORDS_BIGENDIAN
52 # define LE_WORD(x) RtlUshortByteSwap(x)
53 #else
54 # define LE_WORD(x) (x)
55 #endif
57 #include "bus.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
61 #ifdef SONAME_LIBSDL2
63 WINE_DECLARE_DEBUG_CHANNEL(hid_report);
65 static const WCHAR sdl_busidW[] = {'S','D','L','J','O','Y',0};
67 static DWORD map_controllers = 0;
69 #include "initguid.h"
70 DEFINE_GUID(GUID_DEVCLASS_SDL, 0x463d60b5,0x802b,0x4bb2,0x8f,0xdb,0x7d,0xa9,0xb9,0x96,0x04,0xd8);
72 static void *sdl_handle = NULL;
74 #ifdef SONAME_LIBSDL2
75 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
76 MAKE_FUNCPTR(SDL_GetError);
77 MAKE_FUNCPTR(SDL_Init);
78 MAKE_FUNCPTR(SDL_JoystickClose);
79 MAKE_FUNCPTR(SDL_JoystickEventState);
80 MAKE_FUNCPTR(SDL_JoystickGetGUID);
81 MAKE_FUNCPTR(SDL_JoystickGetGUIDString);
82 MAKE_FUNCPTR(SDL_JoystickInstanceID);
83 MAKE_FUNCPTR(SDL_JoystickName);
84 MAKE_FUNCPTR(SDL_JoystickNumAxes);
85 MAKE_FUNCPTR(SDL_JoystickOpen);
86 MAKE_FUNCPTR(SDL_WaitEvent);
87 MAKE_FUNCPTR(SDL_JoystickNumButtons);
88 MAKE_FUNCPTR(SDL_JoystickNumBalls);
89 MAKE_FUNCPTR(SDL_JoystickNumHats);
90 MAKE_FUNCPTR(SDL_JoystickGetAxis);
91 MAKE_FUNCPTR(SDL_JoystickGetHat);
92 MAKE_FUNCPTR(SDL_IsGameController);
93 MAKE_FUNCPTR(SDL_GameControllerClose);
94 MAKE_FUNCPTR(SDL_GameControllerGetAxis);
95 MAKE_FUNCPTR(SDL_GameControllerGetButton);
96 MAKE_FUNCPTR(SDL_GameControllerName);
97 MAKE_FUNCPTR(SDL_GameControllerOpen);
98 MAKE_FUNCPTR(SDL_GameControllerEventState);
99 MAKE_FUNCPTR(SDL_HapticClose);
100 MAKE_FUNCPTR(SDL_HapticDestroyEffect);
101 MAKE_FUNCPTR(SDL_HapticNewEffect);
102 MAKE_FUNCPTR(SDL_HapticOpenFromJoystick);
103 MAKE_FUNCPTR(SDL_HapticQuery);
104 MAKE_FUNCPTR(SDL_HapticRumbleInit);
105 MAKE_FUNCPTR(SDL_HapticRumblePlay);
106 MAKE_FUNCPTR(SDL_HapticRumbleSupported);
107 MAKE_FUNCPTR(SDL_HapticRunEffect);
108 MAKE_FUNCPTR(SDL_HapticStopAll);
109 MAKE_FUNCPTR(SDL_JoystickIsHaptic);
110 MAKE_FUNCPTR(SDL_memset);
111 MAKE_FUNCPTR(SDL_GameControllerAddMapping);
112 #endif
113 static Uint16 (*pSDL_JoystickGetProduct)(SDL_Joystick * joystick);
114 static Uint16 (*pSDL_JoystickGetProductVersion)(SDL_Joystick * joystick);
115 static Uint16 (*pSDL_JoystickGetVendor)(SDL_Joystick * joystick);
117 struct platform_private
119 SDL_Joystick *sdl_joystick;
120 SDL_GameController *sdl_controller;
121 SDL_JoystickID id;
123 int button_start;
124 int axis_start;
125 int ball_start;
126 int hat_bit_offs; /* hatswitches are reported in the same bytes as buttons */
128 int report_descriptor_size;
129 BYTE *report_descriptor;
131 int buffer_length;
132 BYTE *report_buffer;
134 SDL_Haptic *sdl_haptic;
135 int haptic_effect_id;
138 static inline struct platform_private *impl_from_DEVICE_OBJECT(DEVICE_OBJECT *device)
140 return (struct platform_private *)get_platform_private(device);
143 static const BYTE REPORT_AXIS_TAIL[] = {
144 0x17, 0x00, 0x00, 0x00, 0x00, /* LOGICAL_MINIMUM (0) */
145 0x27, 0xff, 0xff, 0x00, 0x00, /* LOGICAL_MAXIMUM (65535) */
146 0x37, 0x00, 0x00, 0x00, 0x00, /* PHYSICAL_MINIMUM (0) */
147 0x47, 0xff, 0xff, 0x00, 0x00, /* PHYSICAL_MAXIMUM (65535) */
148 0x75, 0x10, /* REPORT_SIZE (16) */
149 0x95, 0x00, /* REPORT_COUNT (?) */
150 0x81, 0x02, /* INPUT (Data,Var,Abs) */
152 #define IDX_ABS_AXIS_COUNT 23
154 #define CONTROLLER_NUM_BUTTONS 11
156 static const BYTE CONTROLLER_BUTTONS[] = {
157 0x05, 0x09, /* USAGE_PAGE (Button) */
158 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */
159 0x29, CONTROLLER_NUM_BUTTONS, /* USAGE_MAXIMUM (Button 11) */
160 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
161 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
162 0x35, 0x00, /* LOGICAL_MINIMUM (0) */
163 0x45, 0x01, /* LOGICAL_MAXIMUM (1) */
164 0x95, CONTROLLER_NUM_BUTTONS, /* REPORT_COUNT (11) */
165 0x75, 0x01, /* REPORT_SIZE (1) */
166 0x81, 0x02, /* INPUT (Data,Var,Abs) */
169 static const BYTE CONTROLLER_AXIS [] = {
170 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
171 0x09, 0x30, /* USAGE (X) */
172 0x09, 0x31, /* USAGE (Y) */
173 0x09, 0x33, /* USAGE (RX) */
174 0x09, 0x34, /* USAGE (RY) */
175 0x17, 0x00, 0x00, 0x00, 0x00, /* LOGICAL_MINIMUM (0) */
176 0x27, 0xff, 0xff, 0x00, 0x00, /* LOGICAL_MAXIMUM (65535) */
177 0x37, 0x00, 0x00, 0x00, 0x00, /* PHYSICAL_MINIMUM (0) */
178 0x47, 0xff, 0xff, 0x00, 0x00, /* PHYSICAL_MAXIMUM (65535) */
179 0x75, 0x10, /* REPORT_SIZE (16) */
180 0x95, 0x04, /* REPORT_COUNT (4) */
181 0x81, 0x02, /* INPUT (Data,Var,Abs) */
184 static const BYTE CONTROLLER_TRIGGERS [] = {
185 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
186 0x09, 0x32, /* USAGE (Z) */
187 0x09, 0x35, /* USAGE (RZ) */
188 0x16, 0x00, 0x00, /* LOGICAL_MINIMUM (0) */
189 0x26, 0xff, 0x7f, /* LOGICAL_MAXIMUM (32767) */
190 0x36, 0x00, 0x00, /* PHYSICAL_MINIMUM (0) */
191 0x46, 0xff, 0x7f, /* PHYSICAL_MAXIMUM (32767) */
192 0x75, 0x10, /* REPORT_SIZE (16) */
193 0x95, 0x02, /* REPORT_COUNT (2) */
194 0x81, 0x02, /* INPUT (Data,Var,Abs) */
197 #define CONTROLLER_NUM_AXES 6
199 #define CONTROLLER_NUM_HATSWITCHES 1
201 static const BYTE HAPTIC_RUMBLE[] = {
202 0x06, 0x00, 0xff, /* USAGE PAGE (vendor-defined) */
203 0x09, 0x01, /* USAGE (1) */
204 0x85, 0x00, /* REPORT_ID (0) */
205 /* padding */
206 0x95, 0x02, /* REPORT_COUNT (2) */
207 0x75, 0x08, /* REPORT_SIZE (8) */
208 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
209 /* actuators */
210 0x15, 0x00, /* LOGICAL MINIMUM (0) */
211 0x25, 0xff, /* LOGICAL MAXIMUM (255) */
212 0x35, 0x00, /* PHYSICAL MINIMUM (0) */
213 0x45, 0xff, /* PHYSICAL MAXIMUM (255) */
214 0x75, 0x08, /* REPORT_SIZE (8) */
215 0x95, 0x02, /* REPORT_COUNT (2) */
216 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
217 /* padding */
218 0x95, 0x02, /* REPORT_COUNT (3) */
219 0x75, 0x08, /* REPORT_SIZE (8) */
220 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
223 static BYTE *add_axis_block(BYTE *report_ptr, BYTE count, BYTE page, const BYTE *usages, BOOL absolute)
225 int i;
226 memcpy(report_ptr, REPORT_AXIS_HEADER, sizeof(REPORT_AXIS_HEADER));
227 report_ptr[IDX_AXIS_PAGE] = page;
228 report_ptr += sizeof(REPORT_AXIS_HEADER);
229 for (i = 0; i < count; i++)
231 memcpy(report_ptr, REPORT_AXIS_USAGE, sizeof(REPORT_AXIS_USAGE));
232 report_ptr[IDX_AXIS_USAGE] = usages[i];
233 report_ptr += sizeof(REPORT_AXIS_USAGE);
235 if (absolute)
237 memcpy(report_ptr, REPORT_AXIS_TAIL, sizeof(REPORT_AXIS_TAIL));
238 report_ptr[IDX_ABS_AXIS_COUNT] = count;
239 report_ptr += sizeof(REPORT_AXIS_TAIL);
241 else
243 memcpy(report_ptr, REPORT_REL_AXIS_TAIL, sizeof(REPORT_REL_AXIS_TAIL));
244 report_ptr[IDX_REL_AXIS_COUNT] = count;
245 report_ptr += sizeof(REPORT_REL_AXIS_TAIL);
247 return report_ptr;
250 static void set_button_value(struct platform_private *ext, int index, int value)
252 int byte_index = ext->button_start + index / 8;
253 int bit_index = index % 8;
254 BYTE mask = 1 << bit_index;
256 if (value)
258 ext->report_buffer[byte_index] = ext->report_buffer[byte_index] | mask;
260 else
262 mask = ~mask;
263 ext->report_buffer[byte_index] = ext->report_buffer[byte_index] & mask;
267 static void set_axis_value(struct platform_private *ext, int index, short value)
269 int offset;
270 offset = ext->axis_start + index * sizeof(WORD);
272 switch (index)
274 case SDL_CONTROLLER_AXIS_LEFTX:
275 case SDL_CONTROLLER_AXIS_LEFTY:
276 case SDL_CONTROLLER_AXIS_RIGHTX:
277 case SDL_CONTROLLER_AXIS_RIGHTY:
278 *((WORD*)&ext->report_buffer[offset]) = LE_WORD(value) + 32768;
279 break;
280 case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
281 case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
282 *((WORD*)&ext->report_buffer[offset]) = LE_WORD(value);
283 break;
287 static void set_ball_value(struct platform_private *ext, int index, int value1, int value2)
289 int offset;
290 offset = ext->ball_start + (index * sizeof(WORD));
291 if (value1 > 127) value1 = 127;
292 if (value1 < -127) value1 = -127;
293 if (value2 > 127) value2 = 127;
294 if (value2 < -127) value2 = -127;
295 *((WORD*)&ext->report_buffer[offset]) = LE_WORD(value1);
296 *((WORD*)&ext->report_buffer[offset + sizeof(WORD)]) = LE_WORD(value2);
299 static void set_hat_value(struct platform_private *ext, int index, int value)
301 int byte = ext->button_start + (ext->hat_bit_offs + 4 * index) / 8;
302 int bit_offs = (ext->hat_bit_offs + 4 * index) % 8;
303 int num_low_bits, num_high_bits;
304 unsigned char val, low_mask, high_mask;
306 /* 4-bit hatswitch value is packed into button bytes */
307 if (bit_offs <= 4)
309 num_low_bits = 4;
310 num_high_bits = 0;
311 low_mask = 0xf;
312 high_mask = 0;
314 else
316 num_low_bits = 8 - bit_offs;
317 num_high_bits = 4 - num_low_bits;
318 low_mask = (1 << num_low_bits) - 1;
319 high_mask = (1 << num_high_bits) - 1;
322 switch (value)
324 /* 8 1 2
325 * 7 0 3
326 * 6 5 4 */
327 case SDL_HAT_CENTERED: val = 0; break;
328 case SDL_HAT_UP: val = 1; break;
329 case SDL_HAT_RIGHTUP: val = 2; break;
330 case SDL_HAT_RIGHT: val = 3; break;
331 case SDL_HAT_RIGHTDOWN: val = 4; break;
332 case SDL_HAT_DOWN: val = 5; break;
333 case SDL_HAT_LEFTDOWN: val = 6; break;
334 case SDL_HAT_LEFT: val = 7; break;
335 case SDL_HAT_LEFTUP: val = 8; break;
336 default: return;
339 ext->report_buffer[byte] &= ~(low_mask << bit_offs);
340 ext->report_buffer[byte] |= (val & low_mask) << bit_offs;
341 if (high_mask)
343 ext->report_buffer[byte + 1] &= ~high_mask;
344 ext->report_buffer[byte + 1] |= val & high_mask;
348 static int test_haptic(struct platform_private *ext)
350 int rc = 0;
351 if (pSDL_JoystickIsHaptic(ext->sdl_joystick))
353 ext->sdl_haptic = pSDL_HapticOpenFromJoystick(ext->sdl_joystick);
354 if (ext->sdl_haptic &&
355 ((pSDL_HapticQuery(ext->sdl_haptic) & SDL_HAPTIC_LEFTRIGHT) != 0 ||
356 pSDL_HapticRumbleSupported(ext->sdl_haptic)))
358 pSDL_HapticStopAll(ext->sdl_haptic);
359 pSDL_HapticRumbleInit(ext->sdl_haptic);
360 rc = sizeof(HAPTIC_RUMBLE);
361 ext->haptic_effect_id = -1;
363 else
365 pSDL_HapticClose(ext->sdl_haptic);
366 ext->sdl_haptic = NULL;
369 return rc;
372 static int build_haptic(struct platform_private *ext, BYTE *report_ptr)
374 if (ext->sdl_haptic)
376 memcpy(report_ptr, HAPTIC_RUMBLE, sizeof(HAPTIC_RUMBLE));
377 return (sizeof(HAPTIC_RUMBLE));
379 return 0;
382 static BOOL build_report_descriptor(struct platform_private *ext)
384 BYTE *report_ptr;
385 INT i, descript_size;
386 INT report_size;
387 INT button_count, axis_count, ball_count, hat_count;
388 static const BYTE device_usage[2] = {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_GAMEPAD};
389 static const BYTE controller_usages[] = {
390 HID_USAGE_GENERIC_X,
391 HID_USAGE_GENERIC_Y,
392 HID_USAGE_GENERIC_Z,
393 HID_USAGE_GENERIC_RX,
394 HID_USAGE_GENERIC_RY,
395 HID_USAGE_GENERIC_RZ,
396 HID_USAGE_GENERIC_SLIDER,
397 HID_USAGE_GENERIC_DIAL,
398 HID_USAGE_GENERIC_WHEEL};
399 static const BYTE joystick_usages[] = {
400 HID_USAGE_GENERIC_X,
401 HID_USAGE_GENERIC_Y,
402 HID_USAGE_GENERIC_Z,
403 HID_USAGE_GENERIC_RZ,
404 HID_USAGE_GENERIC_RX,
405 HID_USAGE_GENERIC_RY,
406 HID_USAGE_GENERIC_SLIDER,
407 HID_USAGE_GENERIC_DIAL,
408 HID_USAGE_GENERIC_WHEEL};
410 descript_size = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL);
411 report_size = 0;
413 axis_count = pSDL_JoystickNumAxes(ext->sdl_joystick);
414 if (axis_count > 6)
416 FIXME("Clamping joystick to 6 axis\n");
417 axis_count = 6;
420 ext->axis_start = report_size;
421 if (axis_count)
423 descript_size += sizeof(REPORT_AXIS_HEADER);
424 descript_size += (sizeof(REPORT_AXIS_USAGE) * axis_count);
425 descript_size += sizeof(REPORT_AXIS_TAIL);
426 report_size += (sizeof(WORD) * axis_count);
429 ball_count = pSDL_JoystickNumBalls(ext->sdl_joystick);
430 ext->ball_start = report_size;
431 if (ball_count)
433 if ((ball_count*2) + axis_count > 9)
435 FIXME("Capping ball + axis at 9\n");
436 ball_count = (9-axis_count)/2;
438 descript_size += sizeof(REPORT_AXIS_HEADER);
439 descript_size += (sizeof(REPORT_AXIS_USAGE) * ball_count * 2);
440 descript_size += sizeof(REPORT_REL_AXIS_TAIL);
441 report_size += (sizeof(WORD) * 2 * ball_count);
444 /* For now lump all buttons just into incremental usages, Ignore Keys */
445 button_count = pSDL_JoystickNumButtons(ext->sdl_joystick);
446 ext->button_start = report_size;
447 if (button_count)
449 descript_size += sizeof(REPORT_BUTTONS);
452 hat_count = pSDL_JoystickNumHats(ext->sdl_joystick);
453 ext->hat_bit_offs = button_count;
454 if (hat_count)
456 descript_size += sizeof(REPORT_HATSWITCH);
459 report_size += (button_count + hat_count * 4 + 7) / 8;
461 descript_size += test_haptic(ext);
463 TRACE("Report Descriptor will be %i bytes\n", descript_size);
464 TRACE("Report will be %i bytes\n", report_size);
466 ext->report_descriptor = HeapAlloc(GetProcessHeap(), 0, descript_size);
467 if (!ext->report_descriptor)
469 ERR("Failed to alloc report descriptor\n");
470 return FALSE;
472 report_ptr = ext->report_descriptor;
474 memcpy(report_ptr, REPORT_HEADER, sizeof(REPORT_HEADER));
475 report_ptr[IDX_HEADER_PAGE] = device_usage[0];
476 report_ptr[IDX_HEADER_USAGE] = device_usage[1];
477 report_ptr += sizeof(REPORT_HEADER);
478 if (axis_count)
480 if (axis_count == 6 && button_count >= 14)
481 report_ptr = add_axis_block(report_ptr, axis_count, HID_USAGE_PAGE_GENERIC, controller_usages, TRUE);
482 else
483 report_ptr = add_axis_block(report_ptr, axis_count, HID_USAGE_PAGE_GENERIC, joystick_usages, TRUE);
486 if (ball_count)
488 report_ptr = add_axis_block(report_ptr, ball_count * 2, HID_USAGE_PAGE_GENERIC, &joystick_usages[axis_count], FALSE);
490 if (button_count)
492 report_ptr = add_button_block(report_ptr, 1, button_count);
494 if (hat_count)
495 report_ptr = add_hatswitch(report_ptr, hat_count);
497 report_ptr += build_haptic(ext, report_ptr);
498 memcpy(report_ptr, REPORT_TAIL, sizeof(REPORT_TAIL));
500 ext->report_descriptor_size = descript_size;
501 ext->buffer_length = report_size;
502 ext->report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size);
503 if (ext->report_buffer == NULL)
505 ERR("Failed to alloc report buffer\n");
506 HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
507 return FALSE;
510 /* Initialize axis in the report */
511 for (i = 0; i < axis_count; i++)
512 set_axis_value(ext, i, pSDL_JoystickGetAxis(ext->sdl_joystick, i));
513 for (i = 0; i < hat_count; i++)
514 set_hat_value(ext, i, pSDL_JoystickGetHat(ext->sdl_joystick, i));
516 return TRUE;
519 static SHORT compose_dpad_value(SDL_GameController *joystick)
521 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP))
523 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
524 return SDL_HAT_RIGHTUP;
525 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT))
526 return SDL_HAT_LEFTUP;
527 return SDL_HAT_UP;
530 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN))
532 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
533 return SDL_HAT_RIGHTDOWN;
534 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT))
535 return SDL_HAT_LEFTDOWN;
536 return SDL_HAT_DOWN;
539 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
540 return SDL_HAT_RIGHT;
541 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT))
542 return SDL_HAT_LEFT;
543 return SDL_HAT_CENTERED;
546 static BOOL build_mapped_report_descriptor(struct platform_private *ext)
548 BYTE *report_ptr;
549 INT i, descript_size;
551 static const int BUTTON_BIT_COUNT = CONTROLLER_NUM_BUTTONS + CONTROLLER_NUM_HATSWITCHES * 4;
553 descript_size = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL);
554 descript_size += sizeof(CONTROLLER_AXIS);
555 descript_size += sizeof(CONTROLLER_TRIGGERS);
556 descript_size += sizeof(CONTROLLER_BUTTONS);
557 descript_size += sizeof(REPORT_HATSWITCH);
558 descript_size += sizeof(REPORT_PADDING);
559 if (BUTTON_BIT_COUNT % 8 != 0)
560 descript_size += sizeof(REPORT_PADDING);
561 descript_size += test_haptic(ext);
563 ext->axis_start = 0;
564 ext->button_start = CONTROLLER_NUM_AXES * sizeof(WORD);
565 ext->hat_bit_offs = CONTROLLER_NUM_BUTTONS;
567 ext->buffer_length = (BUTTON_BIT_COUNT + 7) / 8
568 + CONTROLLER_NUM_AXES * sizeof(WORD)
569 + 2/* unknown constant*/;
571 TRACE("Report Descriptor will be %i bytes\n", descript_size);
572 TRACE("Report will be %i bytes\n", ext->buffer_length);
574 ext->report_descriptor = HeapAlloc(GetProcessHeap(), 0, descript_size);
575 if (!ext->report_descriptor)
577 ERR("Failed to alloc report descriptor\n");
578 return FALSE;
580 report_ptr = ext->report_descriptor;
582 memcpy(report_ptr, REPORT_HEADER, sizeof(REPORT_HEADER));
583 report_ptr[IDX_HEADER_PAGE] = HID_USAGE_PAGE_GENERIC;
584 report_ptr[IDX_HEADER_USAGE] = HID_USAGE_GENERIC_GAMEPAD;
585 report_ptr += sizeof(REPORT_HEADER);
586 memcpy(report_ptr, CONTROLLER_AXIS, sizeof(CONTROLLER_AXIS));
587 report_ptr += sizeof(CONTROLLER_AXIS);
588 memcpy(report_ptr, CONTROLLER_TRIGGERS, sizeof(CONTROLLER_TRIGGERS));
589 report_ptr += sizeof(CONTROLLER_TRIGGERS);
590 memcpy(report_ptr, CONTROLLER_BUTTONS, sizeof(CONTROLLER_BUTTONS));
591 report_ptr += sizeof(CONTROLLER_BUTTONS);
592 report_ptr = add_hatswitch(report_ptr, 1);
593 if (BUTTON_BIT_COUNT % 8 != 0)
594 report_ptr = add_padding_block(report_ptr, 8 - (BUTTON_BIT_COUNT % 8));/* unused bits between hatswitch and following constant */
595 report_ptr = add_padding_block(report_ptr, 16);/* unknown constant */
596 report_ptr += build_haptic(ext, report_ptr);
597 memcpy(report_ptr, REPORT_TAIL, sizeof(REPORT_TAIL));
599 ext->report_descriptor_size = descript_size;
600 ext->report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ext->buffer_length);
601 if (ext->report_buffer == NULL)
603 ERR("Failed to alloc report buffer\n");
604 HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
605 return FALSE;
608 /* Initialize axis in the report */
609 for (i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++)
610 set_axis_value(ext, i, pSDL_GameControllerGetAxis(ext->sdl_controller, i));
612 set_hat_value(ext, 0, compose_dpad_value(ext->sdl_controller));
614 /* unknown constant */
615 ext->report_buffer[14] = 0x89;
616 ext->report_buffer[15] = 0xc5;
618 return TRUE;
621 static int compare_platform_device(DEVICE_OBJECT *device, void *platform_dev)
623 SDL_JoystickID id1 = impl_from_DEVICE_OBJECT(device)->id;
624 SDL_JoystickID id2 = PtrToUlong(platform_dev);
625 return (id1 != id2);
628 static NTSTATUS get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *out_length)
630 struct platform_private *ext = impl_from_DEVICE_OBJECT(device);
632 *out_length = ext->report_descriptor_size;
634 if (length < ext->report_descriptor_size)
635 return STATUS_BUFFER_TOO_SMALL;
637 memcpy(buffer, ext->report_descriptor, ext->report_descriptor_size);
639 return STATUS_SUCCESS;
642 static NTSTATUS get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length)
644 struct platform_private *ext = impl_from_DEVICE_OBJECT(device);
645 const char* str = NULL;
647 switch (index)
649 case HID_STRING_ID_IPRODUCT:
650 if (ext->sdl_controller)
651 str = pSDL_GameControllerName(ext->sdl_controller);
652 else
653 str = pSDL_JoystickName(ext->sdl_joystick);
654 break;
655 case HID_STRING_ID_IMANUFACTURER:
656 str = "SDL";
657 break;
658 case HID_STRING_ID_ISERIALNUMBER:
659 str = "000000";
660 break;
661 default:
662 ERR("Unhandled string index %i\n", index);
665 if (str && str[0])
666 MultiByteToWideChar(CP_ACP, 0, str, -1, buffer, length);
667 else
668 buffer[0] = 0;
670 return STATUS_SUCCESS;
673 static NTSTATUS begin_report_processing(DEVICE_OBJECT *device)
675 return STATUS_SUCCESS;
678 static NTSTATUS set_output_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *written)
680 struct platform_private *ext = impl_from_DEVICE_OBJECT(device);
682 if (ext->sdl_haptic && id == 0)
684 WORD left = report[2] * 128;
685 WORD right = report[3] * 128;
687 if (ext->haptic_effect_id >= 0)
689 pSDL_HapticDestroyEffect(ext->sdl_haptic, ext->haptic_effect_id);
690 ext->haptic_effect_id = -1;
692 pSDL_HapticStopAll(ext->sdl_haptic);
693 if (left != 0 || right != 0)
695 SDL_HapticEffect effect;
697 pSDL_memset( &effect, 0, sizeof(SDL_HapticEffect) );
698 effect.type = SDL_HAPTIC_LEFTRIGHT;
699 effect.leftright.length = -1;
700 effect.leftright.large_magnitude = left;
701 effect.leftright.small_magnitude = right;
703 ext->haptic_effect_id = pSDL_HapticNewEffect(ext->sdl_haptic, &effect);
704 if (ext->haptic_effect_id >= 0)
706 pSDL_HapticRunEffect(ext->sdl_haptic, ext->haptic_effect_id, 1);
708 else
710 float i = (float)((left + right)/2.0) / 32767.0;
711 pSDL_HapticRumblePlay(ext->sdl_haptic, i, -1);
714 *written = length;
715 return STATUS_SUCCESS;
717 else
719 *written = 0;
720 return STATUS_NOT_IMPLEMENTED;
724 static NTSTATUS get_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *read)
726 *read = 0;
727 return STATUS_NOT_IMPLEMENTED;
730 static NTSTATUS set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *written)
732 *written = 0;
733 return STATUS_NOT_IMPLEMENTED;
736 static const platform_vtbl sdl_vtbl =
738 compare_platform_device,
739 get_reportdescriptor,
740 get_string,
741 begin_report_processing,
742 set_output_report,
743 get_feature_report,
744 set_feature_report,
747 static int compare_joystick_id(DEVICE_OBJECT *device, void* context)
749 return impl_from_DEVICE_OBJECT(device)->id - PtrToUlong(context);
752 static BOOL set_report_from_event(SDL_Event *event)
754 DEVICE_OBJECT *device;
755 struct platform_private *private;
756 /* All the events coming in will have 'which' as a 3rd field */
757 SDL_JoystickID id = ((SDL_JoyButtonEvent*)event)->which;
758 device = bus_enumerate_hid_devices(&sdl_vtbl, compare_joystick_id, ULongToPtr(id));
759 if (!device)
761 ERR("Failed to find device at index %i\n",id);
762 return FALSE;
764 private = impl_from_DEVICE_OBJECT(device);
765 if (private->sdl_controller)
767 /* We want mapped events */
768 return TRUE;
771 switch(event->type)
773 case SDL_JOYBUTTONDOWN:
774 case SDL_JOYBUTTONUP:
776 SDL_JoyButtonEvent *ie = &event->jbutton;
778 set_button_value(private, ie->button, ie->state);
780 process_hid_report(device, private->report_buffer, private->buffer_length);
781 break;
783 case SDL_JOYAXISMOTION:
785 SDL_JoyAxisEvent *ie = &event->jaxis;
787 if (ie->axis < 6)
789 set_axis_value(private, ie->axis, ie->value);
790 process_hid_report(device, private->report_buffer, private->buffer_length);
792 break;
794 case SDL_JOYBALLMOTION:
796 SDL_JoyBallEvent *ie = &event->jball;
798 set_ball_value(private, ie->ball, ie->xrel, ie->yrel);
799 process_hid_report(device, private->report_buffer, private->buffer_length);
800 break;
802 case SDL_JOYHATMOTION:
804 SDL_JoyHatEvent *ie = &event->jhat;
806 set_hat_value(private, ie->hat, ie->value);
807 process_hid_report(device, private->report_buffer, private->buffer_length);
808 break;
810 default:
811 ERR("TODO: Process Report (0x%x)\n",event->type);
813 return FALSE;
816 static BOOL set_mapped_report_from_event(SDL_Event *event)
818 DEVICE_OBJECT *device;
819 struct platform_private *private;
820 /* All the events coming in will have 'which' as a 3rd field */
821 SDL_JoystickID id = ((SDL_ControllerButtonEvent*)event)->which;
822 device = bus_enumerate_hid_devices(&sdl_vtbl, compare_joystick_id, ULongToPtr(id));
823 if (!device)
825 ERR("Failed to find device at index %i\n",id);
826 return FALSE;
828 private = impl_from_DEVICE_OBJECT(device);
830 switch(event->type)
832 case SDL_CONTROLLERBUTTONDOWN:
833 case SDL_CONTROLLERBUTTONUP:
835 int usage = -1;
836 SDL_ControllerButtonEvent *ie = &event->cbutton;
838 switch (ie->button)
840 case SDL_CONTROLLER_BUTTON_A: usage = 0; break;
841 case SDL_CONTROLLER_BUTTON_B: usage = 1; break;
842 case SDL_CONTROLLER_BUTTON_X: usage = 2; break;
843 case SDL_CONTROLLER_BUTTON_Y: usage = 3; break;
844 case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: usage = 4; break;
845 case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: usage = 5; break;
846 case SDL_CONTROLLER_BUTTON_BACK: usage = 6; break;
847 case SDL_CONTROLLER_BUTTON_START: usage = 7; break;
848 case SDL_CONTROLLER_BUTTON_LEFTSTICK: usage = 8; break;
849 case SDL_CONTROLLER_BUTTON_RIGHTSTICK: usage = 9; break;
850 case SDL_CONTROLLER_BUTTON_GUIDE: usage = 10; break;
852 case SDL_CONTROLLER_BUTTON_DPAD_UP:
853 case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
854 case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
855 case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
856 set_hat_value(private, 0, compose_dpad_value(private->sdl_controller));
857 process_hid_report(device, private->report_buffer, private->buffer_length);
858 break;
860 default:
861 ERR("Unknown Button %i\n",ie->button);
864 if (usage >= 0)
866 set_button_value(private, usage, ie->state);
867 process_hid_report(device, private->report_buffer, private->buffer_length);
869 break;
871 case SDL_CONTROLLERAXISMOTION:
873 SDL_ControllerAxisEvent *ie = &event->caxis;
875 set_axis_value(private, ie->axis, ie->value);
876 process_hid_report(device, private->report_buffer, private->buffer_length);
877 break;
879 default:
880 ERR("TODO: Process Report (%x)\n",event->type);
882 return FALSE;
885 static void try_remove_device(SDL_JoystickID id)
887 DEVICE_OBJECT *device = NULL;
888 struct platform_private *private;
889 SDL_Joystick *sdl_joystick;
890 SDL_GameController *sdl_controller;
891 SDL_Haptic *sdl_haptic;
893 device = bus_enumerate_hid_devices(&sdl_vtbl, compare_joystick_id, ULongToPtr(id));
894 if (!device) return;
896 private = impl_from_DEVICE_OBJECT(device);
897 sdl_joystick = private->sdl_joystick;
898 sdl_controller = private->sdl_controller;
899 sdl_haptic = private->sdl_haptic;
901 IoInvalidateDeviceRelations(device, RemovalRelations);
903 bus_remove_hid_device(device);
905 pSDL_JoystickClose(sdl_joystick);
906 if (sdl_controller)
907 pSDL_GameControllerClose(sdl_controller);
908 if (sdl_haptic)
909 pSDL_HapticClose(sdl_haptic);
912 static void try_add_device(unsigned int index)
914 DWORD vid = 0, pid = 0, version = 0;
915 DEVICE_OBJECT *device = NULL;
916 WCHAR serial[34] = {0};
917 char guid_str[34];
918 BOOL is_xbox_gamepad;
919 WORD input = -1;
921 SDL_Joystick* joystick;
922 SDL_JoystickID id;
923 SDL_JoystickGUID guid;
924 SDL_GameController *controller = NULL;
926 if ((joystick = pSDL_JoystickOpen(index)) == NULL)
928 WARN("Unable to open sdl device %i: %s\n", index, pSDL_GetError());
929 return;
932 if (map_controllers && pSDL_IsGameController(index))
933 controller = pSDL_GameControllerOpen(index);
935 id = pSDL_JoystickInstanceID(joystick);
937 if (pSDL_JoystickGetProductVersion != NULL) {
938 vid = pSDL_JoystickGetVendor(joystick);
939 pid = pSDL_JoystickGetProduct(joystick);
940 version = pSDL_JoystickGetProductVersion(joystick);
942 else
944 vid = 0x01;
945 pid = pSDL_JoystickInstanceID(joystick) + 1;
946 version = 0;
949 guid = pSDL_JoystickGetGUID(joystick);
950 pSDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
951 MultiByteToWideChar(CP_ACP, 0, guid_str, -1, serial, sizeof(guid_str));
953 if (controller)
955 TRACE("Found sdl game controller %i (vid %04x, pid %04x, version %u, serial %s)\n",
956 id, vid, pid, version, debugstr_w(serial));
957 is_xbox_gamepad = TRUE;
959 else
961 int button_count, axis_count;
963 TRACE("Found sdl device %i (vid %04x, pid %04x, version %u, serial %s)\n",
964 id, vid, pid, version, debugstr_w(serial));
966 axis_count = pSDL_JoystickNumAxes(joystick);
967 button_count = pSDL_JoystickNumButtons(joystick);
968 is_xbox_gamepad = (axis_count == 6 && button_count >= 14);
970 if (is_xbox_gamepad)
971 input = 0;
973 device = bus_create_hid_device(sdl_busidW, vid, pid,
974 input, version, index, serial, is_xbox_gamepad, &GUID_DEVCLASS_SDL,
975 &sdl_vtbl, sizeof(struct platform_private));
977 if (device)
979 BOOL rc;
980 struct platform_private *private = impl_from_DEVICE_OBJECT(device);
981 private->sdl_joystick = joystick;
982 private->sdl_controller = controller;
983 private->id = id;
984 if (controller)
985 rc = build_mapped_report_descriptor(private);
986 else
987 rc = build_report_descriptor(private);
988 if (!rc)
990 ERR("Building report descriptor failed, removing device\n");
991 bus_remove_hid_device(device);
992 HeapFree(GetProcessHeap(), 0, serial);
993 return;
995 IoInvalidateDeviceRelations(device, BusRelations);
997 else
999 WARN("Ignoring device %i\n", id);
1003 static void process_device_event(SDL_Event *event)
1005 TRACE_(hid_report)("Received action %x\n", event->type);
1007 if (event->type == SDL_JOYDEVICEADDED)
1008 try_add_device(((SDL_JoyDeviceEvent*)event)->which);
1009 else if (event->type == SDL_JOYDEVICEREMOVED)
1010 try_remove_device(((SDL_JoyDeviceEvent*)event)->which);
1011 else if (event->type >= SDL_JOYAXISMOTION && event->type <= SDL_JOYBUTTONUP)
1012 set_report_from_event(event);
1013 else if (event->type >= SDL_CONTROLLERAXISMOTION && event->type <= SDL_CONTROLLERBUTTONUP)
1014 set_mapped_report_from_event(event);
1017 static DWORD CALLBACK deviceloop_thread(void *args)
1019 HANDLE init_done = args;
1020 SDL_Event event;
1022 if (pSDL_Init(SDL_INIT_GAMECONTROLLER|SDL_INIT_HAPTIC) < 0)
1024 ERR("Can't init SDL: %s\n", pSDL_GetError());
1025 return STATUS_UNSUCCESSFUL;
1028 pSDL_JoystickEventState(SDL_ENABLE);
1029 pSDL_GameControllerEventState(SDL_ENABLE);
1031 /* Process mappings */
1032 if (pSDL_GameControllerAddMapping != NULL)
1034 HKEY key;
1035 static const WCHAR szPath[] = {'m','a','p',0};
1037 if (!RegOpenKeyExW(driver_key, szPath, 0, KEY_ENUMERATE_SUB_KEYS, &key))
1039 DWORD index = 0;
1040 CHAR *buffer = NULL;
1041 DWORD buffer_len = 0;
1042 LSTATUS rc;
1044 do {
1045 CHAR name[255];
1046 DWORD name_len;
1047 DWORD type;
1048 DWORD data_len = buffer_len;
1050 name_len = sizeof(name);
1051 rc = RegEnumValueA(key, index, name, &name_len, NULL, &type, (LPBYTE)buffer, &data_len);
1052 if (rc == ERROR_MORE_DATA || buffer == NULL)
1054 if (buffer)
1055 buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, data_len);
1056 else
1057 buffer = HeapAlloc(GetProcessHeap(), 0, data_len);
1058 buffer_len = data_len;
1060 name_len = sizeof(name);
1061 rc = RegEnumValueA(key, index, name, &name_len, NULL, &type, (LPBYTE)buffer, &data_len);
1064 if (rc == STATUS_SUCCESS)
1066 TRACE("Setting mapping %s...\n",debugstr_an(buffer,29));
1067 pSDL_GameControllerAddMapping(buffer);
1068 index ++;
1070 } while (rc == STATUS_SUCCESS);
1071 HeapFree(GetProcessHeap(), 0, buffer);
1072 NtClose(key);
1076 SetEvent(init_done);
1078 while (1)
1079 while (pSDL_WaitEvent(&event) != 0)
1080 process_device_event(&event);
1082 TRACE("Device thread exiting\n");
1083 return 0;
1086 void sdl_driver_unload( void )
1088 TRACE("Unload Driver\n");
1091 NTSTATUS sdl_driver_init(void)
1093 static const WCHAR controller_modeW[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0};
1094 static const UNICODE_STRING controller_mode = {sizeof(controller_modeW) - sizeof(WCHAR), sizeof(controller_modeW), (WCHAR*)controller_modeW};
1096 HANDLE events[2];
1097 DWORD result;
1099 if (sdl_handle == NULL)
1101 sdl_handle = wine_dlopen(SONAME_LIBSDL2, RTLD_NOW, NULL, 0);
1102 if (!sdl_handle) {
1103 WARN("could not load %s\n", SONAME_LIBSDL2);
1104 return STATUS_UNSUCCESSFUL;
1106 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(sdl_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
1107 LOAD_FUNCPTR(SDL_GetError);
1108 LOAD_FUNCPTR(SDL_Init);
1109 LOAD_FUNCPTR(SDL_JoystickClose);
1110 LOAD_FUNCPTR(SDL_JoystickEventState);
1111 LOAD_FUNCPTR(SDL_JoystickGetGUID);
1112 LOAD_FUNCPTR(SDL_JoystickGetGUIDString);
1113 LOAD_FUNCPTR(SDL_JoystickInstanceID);
1114 LOAD_FUNCPTR(SDL_JoystickName);
1115 LOAD_FUNCPTR(SDL_JoystickNumAxes);
1116 LOAD_FUNCPTR(SDL_JoystickOpen);
1117 LOAD_FUNCPTR(SDL_WaitEvent);
1118 LOAD_FUNCPTR(SDL_JoystickNumButtons);
1119 LOAD_FUNCPTR(SDL_JoystickNumBalls);
1120 LOAD_FUNCPTR(SDL_JoystickNumHats);
1121 LOAD_FUNCPTR(SDL_JoystickGetAxis);
1122 LOAD_FUNCPTR(SDL_JoystickGetHat);
1123 LOAD_FUNCPTR(SDL_IsGameController);
1124 LOAD_FUNCPTR(SDL_GameControllerClose);
1125 LOAD_FUNCPTR(SDL_GameControllerGetAxis);
1126 LOAD_FUNCPTR(SDL_GameControllerGetButton);
1127 LOAD_FUNCPTR(SDL_GameControllerName);
1128 LOAD_FUNCPTR(SDL_GameControllerOpen);
1129 LOAD_FUNCPTR(SDL_GameControllerEventState);
1130 LOAD_FUNCPTR(SDL_HapticClose);
1131 LOAD_FUNCPTR(SDL_HapticDestroyEffect);
1132 LOAD_FUNCPTR(SDL_HapticNewEffect);
1133 LOAD_FUNCPTR(SDL_HapticOpenFromJoystick);
1134 LOAD_FUNCPTR(SDL_HapticQuery);
1135 LOAD_FUNCPTR(SDL_HapticRumbleInit);
1136 LOAD_FUNCPTR(SDL_HapticRumblePlay);
1137 LOAD_FUNCPTR(SDL_HapticRumbleSupported);
1138 LOAD_FUNCPTR(SDL_HapticRunEffect);
1139 LOAD_FUNCPTR(SDL_HapticStopAll);
1140 LOAD_FUNCPTR(SDL_JoystickIsHaptic);
1141 LOAD_FUNCPTR(SDL_memset);
1142 LOAD_FUNCPTR(SDL_GameControllerAddMapping);
1143 #undef LOAD_FUNCPTR
1144 pSDL_JoystickGetProduct = wine_dlsym(sdl_handle, "SDL_JoystickGetProduct", NULL, 0);
1145 pSDL_JoystickGetProductVersion = wine_dlsym(sdl_handle, "SDL_JoystickGetProductVersion", NULL, 0);
1146 pSDL_JoystickGetVendor = wine_dlsym(sdl_handle, "SDL_JoystickGetVendor", NULL, 0);
1149 map_controllers = check_bus_option(&controller_mode, 1);
1151 if (!(events[0] = CreateEventW(NULL, TRUE, FALSE, NULL)))
1153 WARN("CreateEvent failed\n");
1154 return STATUS_UNSUCCESSFUL;
1156 if (!(events[1] = CreateThread(NULL, 0, deviceloop_thread, events[0], 0, NULL)))
1158 WARN("CreateThread failed\n");
1159 CloseHandle(events[0]);
1160 return STATUS_UNSUCCESSFUL;
1163 result = WaitForMultipleObjects(2, events, FALSE, INFINITE);
1164 CloseHandle(events[0]);
1165 CloseHandle(events[1]);
1166 if (result == WAIT_OBJECT_0)
1168 TRACE("Initialization successful\n");
1169 return STATUS_SUCCESS;
1172 sym_not_found:
1173 wine_dlclose(sdl_handle, NULL, 0);
1174 sdl_handle = NULL;
1175 return STATUS_UNSUCCESSFUL;
1178 #else
1180 NTSTATUS sdl_driver_init(void)
1182 return STATUS_NOT_IMPLEMENTED;
1185 void sdl_driver_unload( void )
1187 TRACE("Stub: Unload Driver\n");
1190 #endif /* SONAME_LIBSDL2 */