winebus.sys: Use nameless unions.
[wine.git] / dlls / winebus.sys / bus_sdl.c
blob1580ba5ef9282267bde2171d2f857f9758e508f3
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_SDL_H
31 # include <SDL.h>
32 #endif
34 #include "ntstatus.h"
35 #define WIN32_NO_STATUS
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winnls.h"
39 #include "winreg.h"
40 #include "winternl.h"
41 #include "ddk/wdm.h"
42 #include "ddk/hidtypes.h"
43 #include "wine/debug.h"
44 #include "wine/unicode.h"
45 #include "hidusage.h"
46 #include "controller.h"
48 #ifdef WORDS_BIGENDIAN
49 # define LE_WORD(x) RtlUshortByteSwap(x)
50 #else
51 # define LE_WORD(x) (x)
52 #endif
54 #include "bus.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
58 #ifdef SONAME_LIBSDL2
60 WINE_DECLARE_DEBUG_CHANNEL(hid_report);
62 static const WCHAR sdl_busidW[] = {'S','D','L','J','O','Y',0};
64 static DWORD map_controllers = 0;
66 static void *sdl_handle = NULL;
67 static HANDLE deviceloop_handle;
68 static UINT quit_event = -1;
70 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
71 MAKE_FUNCPTR(SDL_GetError);
72 MAKE_FUNCPTR(SDL_Init);
73 MAKE_FUNCPTR(SDL_JoystickClose);
74 MAKE_FUNCPTR(SDL_JoystickEventState);
75 MAKE_FUNCPTR(SDL_JoystickGetGUID);
76 MAKE_FUNCPTR(SDL_JoystickGetGUIDString);
77 MAKE_FUNCPTR(SDL_JoystickInstanceID);
78 MAKE_FUNCPTR(SDL_JoystickName);
79 MAKE_FUNCPTR(SDL_JoystickNumAxes);
80 MAKE_FUNCPTR(SDL_JoystickOpen);
81 MAKE_FUNCPTR(SDL_WaitEvent);
82 MAKE_FUNCPTR(SDL_JoystickNumButtons);
83 MAKE_FUNCPTR(SDL_JoystickNumBalls);
84 MAKE_FUNCPTR(SDL_JoystickNumHats);
85 MAKE_FUNCPTR(SDL_JoystickGetAxis);
86 MAKE_FUNCPTR(SDL_JoystickGetHat);
87 MAKE_FUNCPTR(SDL_IsGameController);
88 MAKE_FUNCPTR(SDL_GameControllerClose);
89 MAKE_FUNCPTR(SDL_GameControllerGetAxis);
90 MAKE_FUNCPTR(SDL_GameControllerGetButton);
91 MAKE_FUNCPTR(SDL_GameControllerName);
92 MAKE_FUNCPTR(SDL_GameControllerOpen);
93 MAKE_FUNCPTR(SDL_GameControllerEventState);
94 MAKE_FUNCPTR(SDL_HapticClose);
95 MAKE_FUNCPTR(SDL_HapticDestroyEffect);
96 MAKE_FUNCPTR(SDL_HapticNewEffect);
97 MAKE_FUNCPTR(SDL_HapticOpenFromJoystick);
98 MAKE_FUNCPTR(SDL_HapticQuery);
99 MAKE_FUNCPTR(SDL_HapticRumbleInit);
100 MAKE_FUNCPTR(SDL_HapticRumblePlay);
101 MAKE_FUNCPTR(SDL_HapticRumbleSupported);
102 MAKE_FUNCPTR(SDL_HapticRunEffect);
103 MAKE_FUNCPTR(SDL_HapticStopAll);
104 MAKE_FUNCPTR(SDL_JoystickIsHaptic);
105 MAKE_FUNCPTR(SDL_memset);
106 MAKE_FUNCPTR(SDL_GameControllerAddMapping);
107 MAKE_FUNCPTR(SDL_RegisterEvents);
108 MAKE_FUNCPTR(SDL_PushEvent);
109 static Uint16 (*pSDL_JoystickGetProduct)(SDL_Joystick * joystick);
110 static Uint16 (*pSDL_JoystickGetProductVersion)(SDL_Joystick * joystick);
111 static Uint16 (*pSDL_JoystickGetVendor)(SDL_Joystick * joystick);
113 struct platform_private
115 SDL_Joystick *sdl_joystick;
116 SDL_GameController *sdl_controller;
117 SDL_JoystickID id;
119 int button_start;
120 int axis_start;
121 int ball_start;
122 int hat_bit_offs; /* hatswitches are reported in the same bytes as buttons */
124 int report_descriptor_size;
125 BYTE *report_descriptor;
127 int buffer_length;
128 BYTE *report_buffer;
130 SDL_Haptic *sdl_haptic;
131 int haptic_effect_id;
134 static inline struct platform_private *impl_from_DEVICE_OBJECT(DEVICE_OBJECT *device)
136 return (struct platform_private *)get_platform_private(device);
139 #include "psh_hid_macros.h"
141 static const BYTE REPORT_AXIS_TAIL[] = {
142 LOGICAL_MINIMUM(4, 0x00000000),
143 LOGICAL_MAXIMUM(4, 0x0000ffff),
144 PHYSICAL_MINIMUM(4, 0x00000000),
145 PHYSICAL_MAXIMUM(4, 0x0000ffff),
146 REPORT_SIZE(1, 16),
147 REPORT_COUNT(1, /* placeholder */ 0),
148 INPUT(1, Data|Var|Abs),
150 #define IDX_ABS_AXIS_COUNT 23
152 #define CONTROLLER_NUM_BUTTONS 11
154 static const BYTE CONTROLLER_BUTTONS[] = {
155 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
156 USAGE_MINIMUM(1, 1),
157 USAGE_MAXIMUM(1, CONTROLLER_NUM_BUTTONS),
158 LOGICAL_MINIMUM(1, 0),
159 LOGICAL_MAXIMUM(1, 1),
160 PHYSICAL_MINIMUM(1, 0),
161 PHYSICAL_MAXIMUM(1, 1),
162 REPORT_COUNT(1, CONTROLLER_NUM_BUTTONS),
163 REPORT_SIZE(1, 1),
164 INPUT(1, Data|Var|Abs),
167 static const BYTE CONTROLLER_AXIS [] = {
168 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
169 USAGE(1, HID_USAGE_GENERIC_X),
170 USAGE(1, HID_USAGE_GENERIC_Y),
171 USAGE(1, HID_USAGE_GENERIC_RX),
172 USAGE(1, HID_USAGE_GENERIC_RY),
173 LOGICAL_MINIMUM(4, 0x00000000),
174 LOGICAL_MAXIMUM(4, 0x0000ffff),
175 PHYSICAL_MINIMUM(4, 0x00000000),
176 PHYSICAL_MAXIMUM(4, 0x0000ffff),
177 REPORT_SIZE(1, 16),
178 REPORT_COUNT(1, 4),
179 INPUT(1, Data|Var|Abs),
182 static const BYTE CONTROLLER_TRIGGERS [] = {
183 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
184 USAGE(1, HID_USAGE_GENERIC_Z),
185 USAGE(1, HID_USAGE_GENERIC_RZ),
186 LOGICAL_MINIMUM(2, 0x0000),
187 LOGICAL_MAXIMUM(2, 0x7fff),
188 PHYSICAL_MINIMUM(2, 0x0000),
189 PHYSICAL_MAXIMUM(2, 0x7fff),
190 REPORT_SIZE(1, 16),
191 REPORT_COUNT(1, 2),
192 INPUT(1, Data|Var|Abs),
195 #define CONTROLLER_NUM_AXES 6
197 #define CONTROLLER_NUM_HATSWITCHES 1
199 static const BYTE HAPTIC_RUMBLE[] = {
200 USAGE_PAGE(2, HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN),
201 USAGE(1, 0x01),
202 /* padding */
203 REPORT_COUNT(1, 0x02),
204 REPORT_SIZE(1, 0x08),
205 OUTPUT(1, Data|Var|Abs),
206 /* actuators */
207 LOGICAL_MINIMUM(1, 0x00),
208 LOGICAL_MAXIMUM(1, 0xff),
209 PHYSICAL_MINIMUM(1, 0x00),
210 PHYSICAL_MAXIMUM(1, 0xff),
211 REPORT_SIZE(1, 0x08),
212 REPORT_COUNT(1, 0x02),
213 OUTPUT(1, Data|Var|Abs),
214 /* padding */
215 REPORT_COUNT(1, 0x02),
216 REPORT_SIZE(1, 0x08),
217 OUTPUT(1, Data|Var|Abs),
220 #include "pop_hid_macros.h"
222 static BYTE *add_axis_block(BYTE *report_ptr, BYTE count, BYTE page, const BYTE *usages, BOOL absolute)
224 int i;
225 memcpy(report_ptr, REPORT_AXIS_HEADER, sizeof(REPORT_AXIS_HEADER));
226 report_ptr[IDX_AXIS_PAGE] = page;
227 report_ptr += sizeof(REPORT_AXIS_HEADER);
228 for (i = 0; i < count; i++)
230 memcpy(report_ptr, REPORT_AXIS_USAGE, sizeof(REPORT_AXIS_USAGE));
231 report_ptr[IDX_AXIS_USAGE] = usages[i];
232 report_ptr += sizeof(REPORT_AXIS_USAGE);
234 if (absolute)
236 memcpy(report_ptr, REPORT_AXIS_TAIL, sizeof(REPORT_AXIS_TAIL));
237 report_ptr[IDX_ABS_AXIS_COUNT] = count;
238 report_ptr += sizeof(REPORT_AXIS_TAIL);
240 else
242 memcpy(report_ptr, REPORT_REL_AXIS_TAIL, sizeof(REPORT_REL_AXIS_TAIL));
243 report_ptr[IDX_REL_AXIS_COUNT] = count;
244 report_ptr += sizeof(REPORT_REL_AXIS_TAIL);
246 return report_ptr;
249 static void set_button_value(struct platform_private *ext, int index, int value)
251 int byte_index = ext->button_start + index / 8;
252 int bit_index = index % 8;
253 BYTE mask = 1 << bit_index;
255 if (value)
257 ext->report_buffer[byte_index] = ext->report_buffer[byte_index] | mask;
259 else
261 mask = ~mask;
262 ext->report_buffer[byte_index] = ext->report_buffer[byte_index] & mask;
266 static void set_axis_value(struct platform_private *ext, int index, short value, BOOL controller)
268 WORD *report = (WORD *)(ext->report_buffer + ext->axis_start);
270 if (controller && (index == SDL_CONTROLLER_AXIS_TRIGGERLEFT || index == SDL_CONTROLLER_AXIS_TRIGGERRIGHT))
271 report[index] = LE_WORD(value);
272 else
273 report[index] = LE_WORD(value) + 32768;
276 static void set_ball_value(struct platform_private *ext, int index, int value1, int value2)
278 int offset;
279 offset = ext->ball_start + (index * sizeof(WORD));
280 if (value1 > 127) value1 = 127;
281 if (value1 < -127) value1 = -127;
282 if (value2 > 127) value2 = 127;
283 if (value2 < -127) value2 = -127;
284 *((WORD*)&ext->report_buffer[offset]) = LE_WORD(value1);
285 *((WORD*)&ext->report_buffer[offset + sizeof(WORD)]) = LE_WORD(value2);
288 static void set_hat_value(struct platform_private *ext, int index, int value)
290 int byte = ext->button_start + (ext->hat_bit_offs + 4 * index) / 8;
291 int bit_offs = (ext->hat_bit_offs + 4 * index) % 8;
292 int num_low_bits, num_high_bits;
293 unsigned char val, low_mask, high_mask;
295 /* 4-bit hatswitch value is packed into button bytes */
296 if (bit_offs <= 4)
298 num_low_bits = 4;
299 num_high_bits = 0;
300 low_mask = 0xf;
301 high_mask = 0;
303 else
305 num_low_bits = 8 - bit_offs;
306 num_high_bits = 4 - num_low_bits;
307 low_mask = (1 << num_low_bits) - 1;
308 high_mask = (1 << num_high_bits) - 1;
311 switch (value)
313 /* 8 1 2
314 * 7 0 3
315 * 6 5 4 */
316 case SDL_HAT_CENTERED: val = 0; break;
317 case SDL_HAT_UP: val = 1; break;
318 case SDL_HAT_RIGHTUP: val = 2; break;
319 case SDL_HAT_RIGHT: val = 3; break;
320 case SDL_HAT_RIGHTDOWN: val = 4; break;
321 case SDL_HAT_DOWN: val = 5; break;
322 case SDL_HAT_LEFTDOWN: val = 6; break;
323 case SDL_HAT_LEFT: val = 7; break;
324 case SDL_HAT_LEFTUP: val = 8; break;
325 default: return;
328 ext->report_buffer[byte] &= ~(low_mask << bit_offs);
329 ext->report_buffer[byte] |= (val & low_mask) << bit_offs;
330 if (high_mask)
332 ext->report_buffer[byte + 1] &= ~high_mask;
333 ext->report_buffer[byte + 1] |= val & high_mask;
337 static int test_haptic(struct platform_private *ext)
339 int rc = 0;
340 if (pSDL_JoystickIsHaptic(ext->sdl_joystick))
342 ext->sdl_haptic = pSDL_HapticOpenFromJoystick(ext->sdl_joystick);
343 if (ext->sdl_haptic &&
344 ((pSDL_HapticQuery(ext->sdl_haptic) & SDL_HAPTIC_LEFTRIGHT) != 0 ||
345 pSDL_HapticRumbleSupported(ext->sdl_haptic)))
347 pSDL_HapticStopAll(ext->sdl_haptic);
348 pSDL_HapticRumbleInit(ext->sdl_haptic);
349 rc = sizeof(HAPTIC_RUMBLE);
350 ext->haptic_effect_id = -1;
352 else
354 pSDL_HapticClose(ext->sdl_haptic);
355 ext->sdl_haptic = NULL;
358 return rc;
361 static int build_haptic(struct platform_private *ext, BYTE *report_ptr)
363 if (ext->sdl_haptic)
365 memcpy(report_ptr, HAPTIC_RUMBLE, sizeof(HAPTIC_RUMBLE));
366 return (sizeof(HAPTIC_RUMBLE));
368 return 0;
371 static BOOL build_report_descriptor(struct platform_private *ext)
373 BYTE *report_ptr;
374 INT i, descript_size;
375 INT report_size;
376 INT button_count, axis_count, ball_count, hat_count;
377 static const BYTE device_usage[2] = {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_GAMEPAD};
378 static const BYTE controller_usages[] = {
379 HID_USAGE_GENERIC_X,
380 HID_USAGE_GENERIC_Y,
381 HID_USAGE_GENERIC_Z,
382 HID_USAGE_GENERIC_RX,
383 HID_USAGE_GENERIC_RY,
384 HID_USAGE_GENERIC_RZ,
385 HID_USAGE_GENERIC_SLIDER,
386 HID_USAGE_GENERIC_DIAL,
387 HID_USAGE_GENERIC_WHEEL};
388 static const BYTE joystick_usages[] = {
389 HID_USAGE_GENERIC_X,
390 HID_USAGE_GENERIC_Y,
391 HID_USAGE_GENERIC_Z,
392 HID_USAGE_GENERIC_RZ,
393 HID_USAGE_GENERIC_RX,
394 HID_USAGE_GENERIC_RY,
395 HID_USAGE_GENERIC_SLIDER,
396 HID_USAGE_GENERIC_DIAL,
397 HID_USAGE_GENERIC_WHEEL};
399 descript_size = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL);
400 report_size = 0;
402 axis_count = pSDL_JoystickNumAxes(ext->sdl_joystick);
403 if (axis_count > 6)
405 FIXME("Clamping joystick to 6 axis\n");
406 axis_count = 6;
409 ext->axis_start = report_size;
410 if (axis_count)
412 descript_size += sizeof(REPORT_AXIS_HEADER);
413 descript_size += (sizeof(REPORT_AXIS_USAGE) * axis_count);
414 descript_size += sizeof(REPORT_AXIS_TAIL);
415 report_size += (sizeof(WORD) * axis_count);
418 ball_count = pSDL_JoystickNumBalls(ext->sdl_joystick);
419 ext->ball_start = report_size;
420 if (ball_count)
422 if ((ball_count*2) + axis_count > 9)
424 FIXME("Capping ball + axis at 9\n");
425 ball_count = (9-axis_count)/2;
427 descript_size += sizeof(REPORT_AXIS_HEADER);
428 descript_size += (sizeof(REPORT_AXIS_USAGE) * ball_count * 2);
429 descript_size += sizeof(REPORT_REL_AXIS_TAIL);
430 report_size += (sizeof(WORD) * 2 * ball_count);
433 /* For now lump all buttons just into incremental usages, Ignore Keys */
434 button_count = pSDL_JoystickNumButtons(ext->sdl_joystick);
435 ext->button_start = report_size;
436 if (button_count)
438 descript_size += sizeof(REPORT_BUTTONS);
441 hat_count = pSDL_JoystickNumHats(ext->sdl_joystick);
442 ext->hat_bit_offs = button_count;
443 if (hat_count)
445 descript_size += sizeof(REPORT_HATSWITCH);
448 report_size += (button_count + hat_count * 4 + 7) / 8;
450 descript_size += test_haptic(ext);
452 TRACE("Report Descriptor will be %i bytes\n", descript_size);
453 TRACE("Report will be %i bytes\n", report_size);
455 ext->report_descriptor = HeapAlloc(GetProcessHeap(), 0, descript_size);
456 if (!ext->report_descriptor)
458 ERR("Failed to alloc report descriptor\n");
459 return FALSE;
461 report_ptr = ext->report_descriptor;
463 memcpy(report_ptr, REPORT_HEADER, sizeof(REPORT_HEADER));
464 report_ptr[IDX_HEADER_PAGE] = device_usage[0];
465 report_ptr[IDX_HEADER_USAGE] = device_usage[1];
466 report_ptr += sizeof(REPORT_HEADER);
467 if (axis_count)
469 if (axis_count == 6 && button_count >= 14)
470 report_ptr = add_axis_block(report_ptr, axis_count, HID_USAGE_PAGE_GENERIC, controller_usages, TRUE);
471 else
472 report_ptr = add_axis_block(report_ptr, axis_count, HID_USAGE_PAGE_GENERIC, joystick_usages, TRUE);
475 if (ball_count)
477 report_ptr = add_axis_block(report_ptr, ball_count * 2, HID_USAGE_PAGE_GENERIC, &joystick_usages[axis_count], FALSE);
479 if (button_count)
481 report_ptr = add_button_block(report_ptr, 1, button_count);
483 if (hat_count)
484 report_ptr = add_hatswitch(report_ptr, hat_count);
486 report_ptr += build_haptic(ext, report_ptr);
487 memcpy(report_ptr, REPORT_TAIL, sizeof(REPORT_TAIL));
489 ext->report_descriptor_size = descript_size;
490 ext->buffer_length = report_size;
491 ext->report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size);
492 if (ext->report_buffer == NULL)
494 ERR("Failed to alloc report buffer\n");
495 HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
496 return FALSE;
499 /* Initialize axis in the report */
500 for (i = 0; i < axis_count; i++)
501 set_axis_value(ext, i, pSDL_JoystickGetAxis(ext->sdl_joystick, i), FALSE);
502 for (i = 0; i < hat_count; i++)
503 set_hat_value(ext, i, pSDL_JoystickGetHat(ext->sdl_joystick, i));
505 return TRUE;
508 static SHORT compose_dpad_value(SDL_GameController *joystick)
510 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP))
512 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
513 return SDL_HAT_RIGHTUP;
514 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT))
515 return SDL_HAT_LEFTUP;
516 return SDL_HAT_UP;
519 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN))
521 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
522 return SDL_HAT_RIGHTDOWN;
523 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT))
524 return SDL_HAT_LEFTDOWN;
525 return SDL_HAT_DOWN;
528 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
529 return SDL_HAT_RIGHT;
530 if (pSDL_GameControllerGetButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT))
531 return SDL_HAT_LEFT;
532 return SDL_HAT_CENTERED;
535 static BOOL build_mapped_report_descriptor(struct platform_private *ext)
537 BYTE *report_ptr;
538 INT i, descript_size;
540 static const int BUTTON_BIT_COUNT = CONTROLLER_NUM_BUTTONS + CONTROLLER_NUM_HATSWITCHES * 4;
542 descript_size = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL);
543 descript_size += sizeof(CONTROLLER_AXIS);
544 descript_size += sizeof(CONTROLLER_TRIGGERS);
545 descript_size += sizeof(CONTROLLER_BUTTONS);
546 descript_size += sizeof(REPORT_HATSWITCH);
547 descript_size += sizeof(REPORT_PADDING);
548 if (BUTTON_BIT_COUNT % 8 != 0)
549 descript_size += sizeof(REPORT_PADDING);
550 descript_size += test_haptic(ext);
552 ext->axis_start = 0;
553 ext->button_start = CONTROLLER_NUM_AXES * sizeof(WORD);
554 ext->hat_bit_offs = CONTROLLER_NUM_BUTTONS;
556 ext->buffer_length = (BUTTON_BIT_COUNT + 7) / 8
557 + CONTROLLER_NUM_AXES * sizeof(WORD)
558 + 2/* unknown constant*/;
560 TRACE("Report Descriptor will be %i bytes\n", descript_size);
561 TRACE("Report will be %i bytes\n", ext->buffer_length);
563 ext->report_descriptor = HeapAlloc(GetProcessHeap(), 0, descript_size);
564 if (!ext->report_descriptor)
566 ERR("Failed to alloc report descriptor\n");
567 return FALSE;
569 report_ptr = ext->report_descriptor;
571 memcpy(report_ptr, REPORT_HEADER, sizeof(REPORT_HEADER));
572 report_ptr[IDX_HEADER_PAGE] = HID_USAGE_PAGE_GENERIC;
573 report_ptr[IDX_HEADER_USAGE] = HID_USAGE_GENERIC_GAMEPAD;
574 report_ptr += sizeof(REPORT_HEADER);
575 memcpy(report_ptr, CONTROLLER_AXIS, sizeof(CONTROLLER_AXIS));
576 report_ptr += sizeof(CONTROLLER_AXIS);
577 memcpy(report_ptr, CONTROLLER_TRIGGERS, sizeof(CONTROLLER_TRIGGERS));
578 report_ptr += sizeof(CONTROLLER_TRIGGERS);
579 memcpy(report_ptr, CONTROLLER_BUTTONS, sizeof(CONTROLLER_BUTTONS));
580 report_ptr += sizeof(CONTROLLER_BUTTONS);
581 report_ptr = add_hatswitch(report_ptr, 1);
582 if (BUTTON_BIT_COUNT % 8 != 0)
583 report_ptr = add_padding_block(report_ptr, 8 - (BUTTON_BIT_COUNT % 8));/* unused bits between hatswitch and following constant */
584 report_ptr = add_padding_block(report_ptr, 16);/* unknown constant */
585 report_ptr += build_haptic(ext, report_ptr);
586 memcpy(report_ptr, REPORT_TAIL, sizeof(REPORT_TAIL));
588 ext->report_descriptor_size = descript_size;
589 ext->report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ext->buffer_length);
590 if (ext->report_buffer == NULL)
592 ERR("Failed to alloc report buffer\n");
593 HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
594 return FALSE;
597 /* Initialize axis in the report */
598 for (i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++)
599 set_axis_value(ext, i, pSDL_GameControllerGetAxis(ext->sdl_controller, i), TRUE);
601 set_hat_value(ext, 0, compose_dpad_value(ext->sdl_controller));
603 /* unknown constant */
604 ext->report_buffer[14] = 0x89;
605 ext->report_buffer[15] = 0xc5;
607 return TRUE;
610 static void free_device(DEVICE_OBJECT *device)
612 struct platform_private *ext = impl_from_DEVICE_OBJECT(device);
614 pSDL_JoystickClose(ext->sdl_joystick);
615 if (ext->sdl_controller)
616 pSDL_GameControllerClose(ext->sdl_controller);
617 if (ext->sdl_haptic)
618 pSDL_HapticClose(ext->sdl_haptic);
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 free_device,
739 compare_platform_device,
740 get_reportdescriptor,
741 get_string,
742 begin_report_processing,
743 set_output_report,
744 get_feature_report,
745 set_feature_report,
748 static int compare_joystick_id(DEVICE_OBJECT *device, void* context)
750 return impl_from_DEVICE_OBJECT(device)->id - PtrToUlong(context);
753 static BOOL set_report_from_event(SDL_Event *event)
755 DEVICE_OBJECT *device;
756 struct platform_private *private;
757 /* All the events coming in will have 'which' as a 3rd field */
758 SDL_JoystickID id = ((SDL_JoyButtonEvent*)event)->which;
759 device = bus_enumerate_hid_devices(&sdl_vtbl, compare_joystick_id, ULongToPtr(id));
760 if (!device)
762 ERR("Failed to find device at index %i\n",id);
763 return FALSE;
765 private = impl_from_DEVICE_OBJECT(device);
766 if (private->sdl_controller)
768 /* We want mapped events */
769 return TRUE;
772 switch(event->type)
774 case SDL_JOYBUTTONDOWN:
775 case SDL_JOYBUTTONUP:
777 SDL_JoyButtonEvent *ie = &event->jbutton;
779 set_button_value(private, ie->button, ie->state);
781 process_hid_report(device, private->report_buffer, private->buffer_length);
782 break;
784 case SDL_JOYAXISMOTION:
786 SDL_JoyAxisEvent *ie = &event->jaxis;
788 if (ie->axis < 6)
790 set_axis_value(private, ie->axis, ie->value, FALSE);
791 process_hid_report(device, private->report_buffer, private->buffer_length);
793 break;
795 case SDL_JOYBALLMOTION:
797 SDL_JoyBallEvent *ie = &event->jball;
799 set_ball_value(private, ie->ball, ie->xrel, ie->yrel);
800 process_hid_report(device, private->report_buffer, private->buffer_length);
801 break;
803 case SDL_JOYHATMOTION:
805 SDL_JoyHatEvent *ie = &event->jhat;
807 set_hat_value(private, ie->hat, ie->value);
808 process_hid_report(device, private->report_buffer, private->buffer_length);
809 break;
811 default:
812 ERR("TODO: Process Report (0x%x)\n",event->type);
814 return FALSE;
817 static BOOL set_mapped_report_from_event(SDL_Event *event)
819 DEVICE_OBJECT *device;
820 struct platform_private *private;
821 /* All the events coming in will have 'which' as a 3rd field */
822 SDL_JoystickID id = ((SDL_ControllerButtonEvent*)event)->which;
823 device = bus_enumerate_hid_devices(&sdl_vtbl, compare_joystick_id, ULongToPtr(id));
824 if (!device)
826 ERR("Failed to find device at index %i\n",id);
827 return FALSE;
829 private = impl_from_DEVICE_OBJECT(device);
831 switch(event->type)
833 case SDL_CONTROLLERBUTTONDOWN:
834 case SDL_CONTROLLERBUTTONUP:
836 int usage = -1;
837 SDL_ControllerButtonEvent *ie = &event->cbutton;
839 switch (ie->button)
841 case SDL_CONTROLLER_BUTTON_A: usage = 0; break;
842 case SDL_CONTROLLER_BUTTON_B: usage = 1; break;
843 case SDL_CONTROLLER_BUTTON_X: usage = 2; break;
844 case SDL_CONTROLLER_BUTTON_Y: usage = 3; break;
845 case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: usage = 4; break;
846 case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: usage = 5; break;
847 case SDL_CONTROLLER_BUTTON_BACK: usage = 6; break;
848 case SDL_CONTROLLER_BUTTON_START: usage = 7; break;
849 case SDL_CONTROLLER_BUTTON_LEFTSTICK: usage = 8; break;
850 case SDL_CONTROLLER_BUTTON_RIGHTSTICK: usage = 9; break;
851 case SDL_CONTROLLER_BUTTON_GUIDE: usage = 10; break;
853 case SDL_CONTROLLER_BUTTON_DPAD_UP:
854 case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
855 case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
856 case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
857 set_hat_value(private, 0, compose_dpad_value(private->sdl_controller));
858 process_hid_report(device, private->report_buffer, private->buffer_length);
859 break;
861 default:
862 ERR("Unknown Button %i\n",ie->button);
865 if (usage >= 0)
867 set_button_value(private, usage, ie->state);
868 process_hid_report(device, private->report_buffer, private->buffer_length);
870 break;
872 case SDL_CONTROLLERAXISMOTION:
874 SDL_ControllerAxisEvent *ie = &event->caxis;
876 set_axis_value(private, ie->axis, ie->value, TRUE);
877 process_hid_report(device, private->report_buffer, private->buffer_length);
878 break;
880 default:
881 ERR("TODO: Process Report (%x)\n",event->type);
883 return FALSE;
886 static void try_remove_device(SDL_JoystickID id)
888 DEVICE_OBJECT *device = NULL;
890 device = bus_enumerate_hid_devices(&sdl_vtbl, compare_joystick_id, ULongToPtr(id));
891 if (!device) return;
893 bus_unlink_hid_device(device);
894 IoInvalidateDeviceRelations(bus_pdo, BusRelations);
897 static void try_add_device(unsigned int index)
899 DWORD vid = 0, pid = 0, version = 0;
900 DEVICE_OBJECT *device = NULL;
901 WCHAR serial[34] = {0};
902 char guid_str[34];
903 BOOL is_xbox_gamepad;
904 WORD input = -1;
906 SDL_Joystick* joystick;
907 SDL_JoystickID id;
908 SDL_JoystickGUID guid;
909 SDL_GameController *controller = NULL;
911 if ((joystick = pSDL_JoystickOpen(index)) == NULL)
913 WARN("Unable to open sdl device %i: %s\n", index, pSDL_GetError());
914 return;
917 if (map_controllers && pSDL_IsGameController(index))
918 controller = pSDL_GameControllerOpen(index);
920 id = pSDL_JoystickInstanceID(joystick);
922 if (pSDL_JoystickGetProductVersion != NULL) {
923 vid = pSDL_JoystickGetVendor(joystick);
924 pid = pSDL_JoystickGetProduct(joystick);
925 version = pSDL_JoystickGetProductVersion(joystick);
927 else
929 vid = 0x01;
930 pid = pSDL_JoystickInstanceID(joystick) + 1;
931 version = 0;
934 guid = pSDL_JoystickGetGUID(joystick);
935 pSDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
936 MultiByteToWideChar(CP_ACP, 0, guid_str, -1, serial, sizeof(guid_str));
938 if (controller)
940 TRACE("Found sdl game controller %i (vid %04x, pid %04x, version %u, serial %s)\n",
941 id, vid, pid, version, debugstr_w(serial));
942 is_xbox_gamepad = TRUE;
944 else
946 int button_count, axis_count;
948 TRACE("Found sdl device %i (vid %04x, pid %04x, version %u, serial %s)\n",
949 id, vid, pid, version, debugstr_w(serial));
951 axis_count = pSDL_JoystickNumAxes(joystick);
952 button_count = pSDL_JoystickNumButtons(joystick);
953 is_xbox_gamepad = (axis_count == 6 && button_count >= 14);
955 if (is_xbox_gamepad)
956 input = 0;
958 device = bus_create_hid_device(sdl_busidW, vid, pid, input, version, index,
959 serial, is_xbox_gamepad, &sdl_vtbl, sizeof(struct platform_private));
961 if (device)
963 BOOL rc;
964 struct platform_private *private = impl_from_DEVICE_OBJECT(device);
965 private->sdl_joystick = joystick;
966 private->sdl_controller = controller;
967 private->id = id;
969 /* FIXME: We should probably move this to IRP_MN_START_DEVICE. */
970 if (controller)
971 rc = build_mapped_report_descriptor(private);
972 else
973 rc = build_report_descriptor(private);
974 if (!rc)
976 ERR("Building report descriptor failed, removing device\n");
977 bus_unlink_hid_device(device);
978 bus_remove_hid_device(device);
979 HeapFree(GetProcessHeap(), 0, serial);
980 return;
982 IoInvalidateDeviceRelations(bus_pdo, BusRelations);
984 else
986 WARN("Ignoring device %i\n", id);
990 static void process_device_event(SDL_Event *event)
992 TRACE_(hid_report)("Received action %x\n", event->type);
994 if (event->type == SDL_JOYDEVICEADDED)
995 try_add_device(((SDL_JoyDeviceEvent*)event)->which);
996 else if (event->type == SDL_JOYDEVICEREMOVED)
997 try_remove_device(((SDL_JoyDeviceEvent*)event)->which);
998 else if (event->type >= SDL_JOYAXISMOTION && event->type <= SDL_JOYBUTTONUP)
999 set_report_from_event(event);
1000 else if (event->type >= SDL_CONTROLLERAXISMOTION && event->type <= SDL_CONTROLLERBUTTONUP)
1001 set_mapped_report_from_event(event);
1004 static DWORD CALLBACK deviceloop_thread(void *args)
1006 HANDLE init_done = args;
1007 SDL_Event event;
1009 if (pSDL_Init(SDL_INIT_GAMECONTROLLER|SDL_INIT_HAPTIC) < 0)
1011 ERR("Can't init SDL: %s\n", pSDL_GetError());
1012 return STATUS_UNSUCCESSFUL;
1015 pSDL_JoystickEventState(SDL_ENABLE);
1016 pSDL_GameControllerEventState(SDL_ENABLE);
1018 /* Process mappings */
1019 if (pSDL_GameControllerAddMapping != NULL)
1021 HKEY key;
1022 static const WCHAR szPath[] = {'m','a','p',0};
1023 const char *mapping;
1025 if ((mapping = getenv("SDL_GAMECONTROLLERCONFIG")))
1027 TRACE("Setting environment mapping %s\n", debugstr_a(mapping));
1028 if (pSDL_GameControllerAddMapping(mapping) < 0)
1029 WARN("Failed to add environment mapping %s\n", pSDL_GetError());
1031 else if (!RegOpenKeyExW(driver_key, szPath, 0, KEY_QUERY_VALUE, &key))
1033 DWORD index = 0;
1034 CHAR *buffer = NULL;
1035 DWORD buffer_len = 0;
1036 LSTATUS rc;
1038 do {
1039 CHAR name[255];
1040 DWORD name_len;
1041 DWORD type;
1042 DWORD data_len = buffer_len;
1044 name_len = sizeof(name);
1045 rc = RegEnumValueA(key, index, name, &name_len, NULL, &type, (LPBYTE)buffer, &data_len);
1046 if (rc == ERROR_MORE_DATA || buffer == NULL)
1048 if (buffer)
1049 buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, data_len);
1050 else
1051 buffer = HeapAlloc(GetProcessHeap(), 0, data_len);
1052 buffer_len = data_len;
1054 name_len = sizeof(name);
1055 rc = RegEnumValueA(key, index, name, &name_len, NULL, &type, (LPBYTE)buffer, &data_len);
1058 if (rc == STATUS_SUCCESS)
1060 TRACE("Setting registry mapping %s\n", debugstr_a(buffer));
1061 if (pSDL_GameControllerAddMapping(buffer) < 0)
1062 WARN("Failed to add registry mapping %s\n", pSDL_GetError());
1063 index ++;
1065 } while (rc == STATUS_SUCCESS);
1066 HeapFree(GetProcessHeap(), 0, buffer);
1067 NtClose(key);
1071 SetEvent(init_done);
1073 while (1) {
1074 while (pSDL_WaitEvent(&event) != 0) {
1075 if (event.type == quit_event) {
1076 TRACE("Device thread exiting\n");
1077 return 0;
1079 process_device_event(&event);
1084 void sdl_driver_unload( void )
1086 SDL_Event event;
1088 TRACE("Unload Driver\n");
1090 if (!deviceloop_handle)
1091 return;
1093 quit_event = pSDL_RegisterEvents(1);
1094 if (quit_event == -1) {
1095 ERR("error registering quit event\n");
1096 return;
1099 event.type = quit_event;
1100 if (pSDL_PushEvent(&event) != 1) {
1101 ERR("error pushing quit event\n");
1102 return;
1105 WaitForSingleObject(deviceloop_handle, INFINITE);
1106 CloseHandle(deviceloop_handle);
1107 dlclose(sdl_handle);
1110 NTSTATUS sdl_driver_init(void)
1112 static const WCHAR controller_modeW[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0};
1113 static const UNICODE_STRING controller_mode = {sizeof(controller_modeW) - sizeof(WCHAR), sizeof(controller_modeW), (WCHAR*)controller_modeW};
1115 HANDLE events[2];
1116 DWORD result;
1118 if (sdl_handle == NULL)
1120 sdl_handle = dlopen(SONAME_LIBSDL2, RTLD_NOW);
1121 if (!sdl_handle) {
1122 WARN("could not load %s\n", SONAME_LIBSDL2);
1123 return STATUS_UNSUCCESSFUL;
1125 #define LOAD_FUNCPTR(f) if((p##f = dlsym(sdl_handle, #f)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
1126 LOAD_FUNCPTR(SDL_GetError);
1127 LOAD_FUNCPTR(SDL_Init);
1128 LOAD_FUNCPTR(SDL_JoystickClose);
1129 LOAD_FUNCPTR(SDL_JoystickEventState);
1130 LOAD_FUNCPTR(SDL_JoystickGetGUID);
1131 LOAD_FUNCPTR(SDL_JoystickGetGUIDString);
1132 LOAD_FUNCPTR(SDL_JoystickInstanceID);
1133 LOAD_FUNCPTR(SDL_JoystickName);
1134 LOAD_FUNCPTR(SDL_JoystickNumAxes);
1135 LOAD_FUNCPTR(SDL_JoystickOpen);
1136 LOAD_FUNCPTR(SDL_WaitEvent);
1137 LOAD_FUNCPTR(SDL_JoystickNumButtons);
1138 LOAD_FUNCPTR(SDL_JoystickNumBalls);
1139 LOAD_FUNCPTR(SDL_JoystickNumHats);
1140 LOAD_FUNCPTR(SDL_JoystickGetAxis);
1141 LOAD_FUNCPTR(SDL_JoystickGetHat);
1142 LOAD_FUNCPTR(SDL_IsGameController);
1143 LOAD_FUNCPTR(SDL_GameControllerClose);
1144 LOAD_FUNCPTR(SDL_GameControllerGetAxis);
1145 LOAD_FUNCPTR(SDL_GameControllerGetButton);
1146 LOAD_FUNCPTR(SDL_GameControllerName);
1147 LOAD_FUNCPTR(SDL_GameControllerOpen);
1148 LOAD_FUNCPTR(SDL_GameControllerEventState);
1149 LOAD_FUNCPTR(SDL_HapticClose);
1150 LOAD_FUNCPTR(SDL_HapticDestroyEffect);
1151 LOAD_FUNCPTR(SDL_HapticNewEffect);
1152 LOAD_FUNCPTR(SDL_HapticOpenFromJoystick);
1153 LOAD_FUNCPTR(SDL_HapticQuery);
1154 LOAD_FUNCPTR(SDL_HapticRumbleInit);
1155 LOAD_FUNCPTR(SDL_HapticRumblePlay);
1156 LOAD_FUNCPTR(SDL_HapticRumbleSupported);
1157 LOAD_FUNCPTR(SDL_HapticRunEffect);
1158 LOAD_FUNCPTR(SDL_HapticStopAll);
1159 LOAD_FUNCPTR(SDL_JoystickIsHaptic);
1160 LOAD_FUNCPTR(SDL_memset);
1161 LOAD_FUNCPTR(SDL_GameControllerAddMapping);
1162 LOAD_FUNCPTR(SDL_RegisterEvents);
1163 LOAD_FUNCPTR(SDL_PushEvent);
1164 #undef LOAD_FUNCPTR
1165 pSDL_JoystickGetProduct = dlsym(sdl_handle, "SDL_JoystickGetProduct");
1166 pSDL_JoystickGetProductVersion = dlsym(sdl_handle, "SDL_JoystickGetProductVersion");
1167 pSDL_JoystickGetVendor = dlsym(sdl_handle, "SDL_JoystickGetVendor");
1170 map_controllers = check_bus_option(&controller_mode, 1);
1172 if (!(events[0] = CreateEventW(NULL, TRUE, FALSE, NULL)))
1174 WARN("CreateEvent failed\n");
1175 return STATUS_UNSUCCESSFUL;
1177 if (!(events[1] = CreateThread(NULL, 0, deviceloop_thread, events[0], 0, NULL)))
1179 WARN("CreateThread failed\n");
1180 CloseHandle(events[0]);
1181 return STATUS_UNSUCCESSFUL;
1184 result = WaitForMultipleObjects(2, events, FALSE, INFINITE);
1185 CloseHandle(events[0]);
1186 if (result == WAIT_OBJECT_0)
1188 TRACE("Initialization successful\n");
1189 deviceloop_handle = events[1];
1190 return STATUS_SUCCESS;
1192 CloseHandle(events[1]);
1194 sym_not_found:
1195 dlclose(sdl_handle);
1196 sdl_handle = NULL;
1197 return STATUS_UNSUCCESSFUL;
1200 #else
1202 NTSTATUS sdl_driver_init(void)
1204 return STATUS_NOT_IMPLEMENTED;
1207 void sdl_driver_unload( void )
1209 TRACE("Stub: Unload Driver\n");
1212 #endif /* SONAME_LIBSDL2 */