winebus.sys: Improve unloading the winebus driver.
[wine.git] / dlls / winebus.sys / bus_sdl.c
blob6b2b28e8c90f0118d6b656cb08e0d4d2bb489ef3
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 "winternl.h"
42 #include "ddk/wdm.h"
43 #include "ddk/hidtypes.h"
44 #include "wine/library.h"
45 #include "wine/debug.h"
46 #include "wine/unicode.h"
47 #include "hidusage.h"
48 #include "controller.h"
50 #ifdef WORDS_BIGENDIAN
51 # define LE_WORD(x) RtlUshortByteSwap(x)
52 #else
53 # define LE_WORD(x) (x)
54 #endif
56 #include "bus.h"
58 WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
60 #ifdef SONAME_LIBSDL2
62 #define VID_MICROSOFT 0x045e
64 static const WORD PID_XBOX_CONTROLLERS[] = {
65 0x0202, /* Xbox Controller */
66 0x0285, /* Xbox Controller S */
67 0x0289, /* Xbox Controller S */
68 0x028e, /* Xbox360 Controller */
69 0x028f, /* Xbox360 Wireless Controller */
70 0x02d1, /* Xbox One Controller */
71 0x02dd, /* Xbox One Controller (Covert Forces/Firmware 2015) */
72 0x02e0, /* Xbox One X Controller */
73 0x02e3, /* Xbox One Elite Controller */
74 0x02e6, /* Wireless XBox Controller Dongle */
75 0x02ea, /* Xbox One S Controller */
76 0x02fd, /* Xbox One S Controller (Firmware 2017) */
77 0x0719, /* Xbox 360 Wireless Adapter */
80 WINE_DECLARE_DEBUG_CHANNEL(hid_report);
82 static DRIVER_OBJECT *sdl_driver_obj = NULL;
84 static const WCHAR sdl_busidW[] = {'S','D','L','J','O','Y',0};
86 static DWORD map_controllers = 0;
88 #include "initguid.h"
89 DEFINE_GUID(GUID_DEVCLASS_SDL, 0x463d60b5,0x802b,0x4bb2,0x8f,0xdb,0x7d,0xa9,0xb9,0x96,0x04,0xd8);
91 static void *sdl_handle = NULL;
93 #ifdef SONAME_LIBSDL2
94 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
95 MAKE_FUNCPTR(SDL_GetError);
96 MAKE_FUNCPTR(SDL_Init);
97 MAKE_FUNCPTR(SDL_JoystickEventState);
98 MAKE_FUNCPTR(SDL_JoystickGetGUID);
99 MAKE_FUNCPTR(SDL_JoystickGetGUIDString);
100 MAKE_FUNCPTR(SDL_JoystickInstanceID);
101 MAKE_FUNCPTR(SDL_JoystickName);
102 MAKE_FUNCPTR(SDL_JoystickNumAxes);
103 MAKE_FUNCPTR(SDL_JoystickOpen);
104 MAKE_FUNCPTR(SDL_WaitEvent);
105 MAKE_FUNCPTR(SDL_JoystickNumButtons);
106 MAKE_FUNCPTR(SDL_JoystickNumBalls);
107 MAKE_FUNCPTR(SDL_JoystickNumHats);
108 MAKE_FUNCPTR(SDL_JoystickGetAxis);
109 MAKE_FUNCPTR(SDL_JoystickGetHat);
110 MAKE_FUNCPTR(SDL_IsGameController);
111 MAKE_FUNCPTR(SDL_GameControllerGetAxis);
112 MAKE_FUNCPTR(SDL_GameControllerName);
113 MAKE_FUNCPTR(SDL_GameControllerOpen);
114 MAKE_FUNCPTR(SDL_GameControllerEventState);
115 MAKE_FUNCPTR(SDL_HapticClose);
116 MAKE_FUNCPTR(SDL_HapticDestroyEffect);
117 MAKE_FUNCPTR(SDL_HapticNewEffect);
118 MAKE_FUNCPTR(SDL_HapticOpenFromJoystick);
119 MAKE_FUNCPTR(SDL_HapticQuery);
120 MAKE_FUNCPTR(SDL_HapticRumbleInit);
121 MAKE_FUNCPTR(SDL_HapticRumblePlay);
122 MAKE_FUNCPTR(SDL_HapticRumbleSupported);
123 MAKE_FUNCPTR(SDL_HapticRunEffect);
124 MAKE_FUNCPTR(SDL_HapticStopAll);
125 MAKE_FUNCPTR(SDL_JoystickIsHaptic);
126 MAKE_FUNCPTR(SDL_memset);
127 #endif
128 static Uint16 (*pSDL_JoystickGetProduct)(SDL_Joystick * joystick);
129 static Uint16 (*pSDL_JoystickGetProductVersion)(SDL_Joystick * joystick);
130 static Uint16 (*pSDL_JoystickGetVendor)(SDL_Joystick * joystick);
132 struct platform_private
134 SDL_Joystick *sdl_joystick;
135 SDL_GameController *sdl_controller;
136 SDL_JoystickID id;
138 int axis_start;
139 int ball_start;
140 int hat_start;
142 int report_descriptor_size;
143 BYTE *report_descriptor;
145 int buffer_length;
146 BYTE *report_buffer;
148 SDL_Haptic *sdl_haptic;
149 int haptic_effect_id;
152 static inline struct platform_private *impl_from_DEVICE_OBJECT(DEVICE_OBJECT *device)
154 return (struct platform_private *)get_platform_private(device);
157 static const BYTE REPORT_AXIS_TAIL[] = {
158 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */
159 0x26, 0xff, 0x7f, /* LOGICAL_MAXIMUM (32767) */
160 0x36, 0x00, 0x80, /* PHYSICAL_MINIMUM (-32768) */
161 0x46, 0xff, 0x7f, /* PHYSICAL_MAXIMUM (32767) */
162 0x75, 0x10, /* REPORT_SIZE (16) */
163 0x95, 0x00, /* REPORT_COUNT (?) */
164 0x81, 0x02, /* INPUT (Data,Var,Abs) */
166 #define IDX_ABS_AXIS_COUNT 15
168 static const BYTE CONTROLLER_BUTTONS[] = {
169 0x05, 0x09, /* USAGE_PAGE (Button) */
170 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */
171 0x29, 0x0f, /* USAGE_MAXIMUM (Button 15) */
172 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
173 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
174 0x35, 0x00, /* LOGICAL_MINIMUM (0) */
175 0x45, 0x01, /* LOGICAL_MAXIMUM (1) */
176 0x95, 0x0f, /* REPORT_COUNT (15) */
177 0x75, 0x01, /* REPORT_SIZE (1) */
178 0x81, 0x02, /* INPUT (Data,Var,Abs) */
179 /* padding */
180 0x95, 0x01, /* REPORT_COUNT (1) */
181 0x75, 0x01, /* REPORT_SIZE (1) */
182 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
185 static const BYTE CONTROLLER_AXIS [] = {
186 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
187 0x09, 0x30, /* USAGE (X) */
188 0x09, 0x31, /* USAGE (Y) */
189 0x09, 0x33, /* USAGE (RX) */
190 0x09, 0x34, /* USAGE (RY) */
191 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */
192 0x26, 0xff, 0x7f, /* LOGICAL_MAXIMUM (32767) */
193 0x36, 0x00, 0x80, /* PHYSICAL_MINIMUM (-32768) */
194 0x46, 0xff, 0x7f, /* PHYSICAL_MAXIMUM (32767) */
195 0x75, 0x10, /* REPORT_SIZE (16) */
196 0x95, 0x04, /* REPORT_COUNT (4) */
197 0x81, 0x02, /* INPUT (Data,Var,Abs) */
200 static const BYTE CONTROLLER_TRIGGERS [] = {
201 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
202 0x09, 0x32, /* USAGE (Z) */
203 0x09, 0x35, /* USAGE (RZ) */
204 0x16, 0x00, 0x00, /* LOGICAL_MINIMUM (0) */
205 0x26, 0xff, 0x7f, /* LOGICAL_MAXIMUM (32767) */
206 0x36, 0x00, 0x00, /* PHYSICAL_MINIMUM (0) */
207 0x46, 0xff, 0x7f, /* PHYSICAL_MAXIMUM (32767) */
208 0x75, 0x10, /* REPORT_SIZE (16) */
209 0x95, 0x02, /* REPORT_COUNT (2) */
210 0x81, 0x02, /* INPUT (Data,Var,Abs) */
213 static const BYTE HAPTIC_RUMBLE[] = {
214 0x06, 0x00, 0xff, /* USAGE PAGE (vendor-defined) */
215 0x09, 0x01, /* USAGE (1) */
216 0x85, 0x00, /* REPORT_ID (0) */
217 /* padding */
218 0x95, 0x02, /* REPORT_COUNT (2) */
219 0x75, 0x08, /* REPORT_SIZE (8) */
220 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
221 /* actuators */
222 0x15, 0x00, /* LOGICAL MINIMUM (0) */
223 0x25, 0xff, /* LOGICAL MAXIMUM (255) */
224 0x35, 0x00, /* PHYSICAL MINIMUM (0) */
225 0x45, 0xff, /* PHYSICAL MAXIMUM (255) */
226 0x75, 0x08, /* REPORT_SIZE (8) */
227 0x95, 0x02, /* REPORT_COUNT (2) */
228 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
229 /* padding */
230 0x95, 0x02, /* REPORT_COUNT (3) */
231 0x75, 0x08, /* REPORT_SIZE (8) */
232 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
235 static BYTE *add_axis_block(BYTE *report_ptr, BYTE count, BYTE page, const BYTE *usages, BOOL absolute)
237 int i;
238 memcpy(report_ptr, REPORT_AXIS_HEADER, sizeof(REPORT_AXIS_HEADER));
239 report_ptr[IDX_AXIS_PAGE] = page;
240 report_ptr += sizeof(REPORT_AXIS_HEADER);
241 for (i = 0; i < count; i++)
243 memcpy(report_ptr, REPORT_AXIS_USAGE, sizeof(REPORT_AXIS_USAGE));
244 report_ptr[IDX_AXIS_USAGE] = usages[i];
245 report_ptr += sizeof(REPORT_AXIS_USAGE);
247 if (absolute)
249 memcpy(report_ptr, REPORT_AXIS_TAIL, sizeof(REPORT_AXIS_TAIL));
250 report_ptr[IDX_ABS_AXIS_COUNT] = count;
251 report_ptr += sizeof(REPORT_AXIS_TAIL);
253 else
255 memcpy(report_ptr, REPORT_REL_AXIS_TAIL, sizeof(REPORT_REL_AXIS_TAIL));
256 report_ptr[IDX_REL_AXIS_COUNT] = count;
257 report_ptr += sizeof(REPORT_REL_AXIS_TAIL);
259 return report_ptr;
262 static void set_axis_value(struct platform_private *ext, int index, short value)
264 int offset;
265 offset = ext->axis_start + index * 2;
266 *((WORD*)&ext->report_buffer[offset]) = LE_WORD(value);
269 static void set_ball_value(struct platform_private *ext, int index, int value1, int value2)
271 int offset;
272 offset = ext->ball_start + (index * 2);
273 if (value1 > 127) value1 = 127;
274 if (value1 < -127) value1 = -127;
275 if (value2 > 127) value2 = 127;
276 if (value2 < -127) value2 = -127;
277 ext->report_buffer[offset] = value1;
278 ext->report_buffer[offset + 1] = value2;
281 static void set_hat_value(struct platform_private *ext, int index, int value)
283 int offset;
284 offset = ext->hat_start + index;
285 switch (value)
287 case SDL_HAT_CENTERED: ext->report_buffer[offset] = 8; break;
288 case SDL_HAT_UP: ext->report_buffer[offset] = 0; break;
289 case SDL_HAT_RIGHTUP: ext->report_buffer[offset] = 1; break;
290 case SDL_HAT_RIGHT: ext->report_buffer[offset] = 2; break;
291 case SDL_HAT_RIGHTDOWN: ext->report_buffer[offset] = 3; break;
292 case SDL_HAT_DOWN: ext->report_buffer[offset] = 4; break;
293 case SDL_HAT_LEFTDOWN: ext->report_buffer[offset] = 5; break;
294 case SDL_HAT_LEFT: ext->report_buffer[offset] = 6; break;
295 case SDL_HAT_LEFTUP: ext->report_buffer[offset] = 7; break;
299 static int test_haptic(struct platform_private *ext)
301 int rc = 0;
302 if (pSDL_JoystickIsHaptic(ext->sdl_joystick))
304 ext->sdl_haptic = pSDL_HapticOpenFromJoystick(ext->sdl_joystick);
305 if (ext->sdl_haptic &&
306 ((pSDL_HapticQuery(ext->sdl_haptic) & SDL_HAPTIC_LEFTRIGHT) != 0 ||
307 pSDL_HapticRumbleSupported(ext->sdl_haptic)))
309 pSDL_HapticStopAll(ext->sdl_haptic);
310 pSDL_HapticRumbleInit(ext->sdl_haptic);
311 rc = sizeof(HAPTIC_RUMBLE);
312 ext->haptic_effect_id = -1;
314 else
316 pSDL_HapticClose(ext->sdl_haptic);
317 ext->sdl_haptic = NULL;
320 return rc;
323 static int build_haptic(struct platform_private *ext, BYTE *report_ptr)
325 if (ext->sdl_haptic)
327 memcpy(report_ptr, HAPTIC_RUMBLE, sizeof(HAPTIC_RUMBLE));
328 return (sizeof(HAPTIC_RUMBLE));
330 return 0;
333 static BOOL build_report_descriptor(struct platform_private *ext)
335 BYTE *report_ptr;
336 INT i, descript_size;
337 INT report_size;
338 INT button_count, axis_count, ball_count, hat_count;
339 static const BYTE device_usage[2] = {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_GAMEPAD};
340 static const BYTE controller_usages[] = {
341 HID_USAGE_GENERIC_X,
342 HID_USAGE_GENERIC_Y,
343 HID_USAGE_GENERIC_Z,
344 HID_USAGE_GENERIC_RX,
345 HID_USAGE_GENERIC_RY,
346 HID_USAGE_GENERIC_RZ,
347 HID_USAGE_GENERIC_SLIDER,
348 HID_USAGE_GENERIC_DIAL,
349 HID_USAGE_GENERIC_WHEEL};
350 static const BYTE joystick_usages[] = {
351 HID_USAGE_GENERIC_X,
352 HID_USAGE_GENERIC_Y,
353 HID_USAGE_GENERIC_Z,
354 HID_USAGE_GENERIC_RZ,
355 HID_USAGE_GENERIC_RX,
356 HID_USAGE_GENERIC_RY,
357 HID_USAGE_GENERIC_SLIDER,
358 HID_USAGE_GENERIC_DIAL,
359 HID_USAGE_GENERIC_WHEEL};
361 descript_size = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL);
362 report_size = 0;
364 /* For now lump all buttons just into incremental usages, Ignore Keys */
365 button_count = pSDL_JoystickNumButtons(ext->sdl_joystick);
366 if (button_count)
368 descript_size += sizeof(REPORT_BUTTONS);
369 if (button_count % 8)
370 descript_size += sizeof(REPORT_PADDING);
371 report_size = (button_count + 7) / 8;
374 axis_count = pSDL_JoystickNumAxes(ext->sdl_joystick);
375 if (axis_count > 6)
377 FIXME("Clamping joystick to 6 axis\n");
378 axis_count = 6;
381 ext->axis_start = report_size;
382 if (axis_count)
384 descript_size += sizeof(REPORT_AXIS_HEADER);
385 descript_size += (sizeof(REPORT_AXIS_USAGE) * axis_count);
386 descript_size += sizeof(REPORT_AXIS_TAIL);
387 report_size += (2 * axis_count);
390 ball_count = pSDL_JoystickNumBalls(ext->sdl_joystick);
391 ext->ball_start = report_size;
392 if (ball_count)
394 if ((ball_count*2) + axis_count > 9)
396 FIXME("Capping ball + axis at 9\n");
397 ball_count = (9-axis_count)/2;
399 descript_size += sizeof(REPORT_AXIS_HEADER);
400 descript_size += (sizeof(REPORT_AXIS_USAGE) * ball_count * 2);
401 descript_size += sizeof(REPORT_REL_AXIS_TAIL);
402 report_size += (2*ball_count);
405 hat_count = pSDL_JoystickNumHats(ext->sdl_joystick);
406 ext->hat_start = report_size;
407 if (hat_count)
409 descript_size += sizeof(REPORT_HATSWITCH);
410 for (i = 0; i < hat_count; i++)
411 report_size++;
414 descript_size += test_haptic(ext);
416 TRACE("Report Descriptor will be %i bytes\n", descript_size);
417 TRACE("Report will be %i bytes\n", report_size);
419 ext->report_descriptor = HeapAlloc(GetProcessHeap(), 0, descript_size);
420 if (!ext->report_descriptor)
422 ERR("Failed to alloc report descriptor\n");
423 return FALSE;
425 report_ptr = ext->report_descriptor;
427 memcpy(report_ptr, REPORT_HEADER, sizeof(REPORT_HEADER));
428 report_ptr[IDX_HEADER_PAGE] = device_usage[0];
429 report_ptr[IDX_HEADER_USAGE] = device_usage[1];
430 report_ptr += sizeof(REPORT_HEADER);
431 if (button_count)
433 report_ptr = add_button_block(report_ptr, 1, button_count);
434 if (button_count % 8)
436 BYTE padding = 8 - (button_count % 8);
437 report_ptr = add_padding_block(report_ptr, padding);
440 if (axis_count)
442 if (axis_count == 6 && button_count >= 14)
443 report_ptr = add_axis_block(report_ptr, axis_count, HID_USAGE_PAGE_GENERIC, controller_usages, TRUE);
444 else
445 report_ptr = add_axis_block(report_ptr, axis_count, HID_USAGE_PAGE_GENERIC, joystick_usages, TRUE);
448 if (ball_count)
450 report_ptr = add_axis_block(report_ptr, ball_count * 2, HID_USAGE_PAGE_GENERIC, &joystick_usages[axis_count], FALSE);
452 if (hat_count)
453 report_ptr = add_hatswitch(report_ptr, hat_count);
455 report_ptr += build_haptic(ext, report_ptr);
456 memcpy(report_ptr, REPORT_TAIL, sizeof(REPORT_TAIL));
458 ext->report_descriptor_size = descript_size;
459 ext->buffer_length = report_size;
460 ext->report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size);
461 if (ext->report_buffer == NULL)
463 ERR("Failed to alloc report buffer\n");
464 HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
465 return FALSE;
468 /* Initialize axis in the report */
469 for (i = 0; i < axis_count; i++)
470 set_axis_value(ext, i, pSDL_JoystickGetAxis(ext->sdl_joystick, i));
471 for (i = 0; i < hat_count; i++)
472 set_hat_value(ext, i, pSDL_JoystickGetHat(ext->sdl_joystick, i));
474 return TRUE;
477 static BOOL build_mapped_report_descriptor(struct platform_private *ext)
479 BYTE *report_ptr;
480 INT i, descript_size;
482 descript_size = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL);
483 descript_size += sizeof(CONTROLLER_BUTTONS);
484 descript_size += sizeof(CONTROLLER_AXIS);
485 descript_size += sizeof(CONTROLLER_TRIGGERS);
486 descript_size += test_haptic(ext);
488 ext->axis_start = 2;
489 ext->buffer_length = 14;
491 TRACE("Report Descriptor will be %i bytes\n", descript_size);
492 TRACE("Report will be %i bytes\n", ext->buffer_length);
494 ext->report_descriptor = HeapAlloc(GetProcessHeap(), 0, descript_size);
495 if (!ext->report_descriptor)
497 ERR("Failed to alloc report descriptor\n");
498 return FALSE;
500 report_ptr = ext->report_descriptor;
502 memcpy(report_ptr, REPORT_HEADER, sizeof(REPORT_HEADER));
503 report_ptr[IDX_HEADER_PAGE] = HID_USAGE_PAGE_GENERIC;
504 report_ptr[IDX_HEADER_USAGE] = HID_USAGE_GENERIC_GAMEPAD;
505 report_ptr += sizeof(REPORT_HEADER);
506 memcpy(report_ptr, CONTROLLER_BUTTONS, sizeof(CONTROLLER_BUTTONS));
507 report_ptr += sizeof(CONTROLLER_BUTTONS);
508 memcpy(report_ptr, CONTROLLER_AXIS, sizeof(CONTROLLER_AXIS));
509 report_ptr += sizeof(CONTROLLER_AXIS);
510 memcpy(report_ptr, CONTROLLER_TRIGGERS, sizeof(CONTROLLER_TRIGGERS));
511 report_ptr += sizeof(CONTROLLER_TRIGGERS);
512 report_ptr += build_haptic(ext, report_ptr);
513 memcpy(report_ptr, REPORT_TAIL, sizeof(REPORT_TAIL));
515 ext->report_descriptor_size = descript_size;
516 ext->report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ext->buffer_length);
517 if (ext->report_buffer == NULL)
519 ERR("Failed to alloc report buffer\n");
520 HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
521 return FALSE;
524 /* Initialize axis in the report */
525 for (i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++)
526 set_axis_value(ext, i, pSDL_GameControllerGetAxis(ext->sdl_controller, i));
528 return TRUE;
531 static int compare_platform_device(DEVICE_OBJECT *device, void *platform_dev)
533 SDL_JoystickID id1 = impl_from_DEVICE_OBJECT(device)->id;
534 SDL_JoystickID id2 = PtrToUlong(platform_dev);
535 return (id1 != id2);
538 static NTSTATUS get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *out_length)
540 struct platform_private *ext = impl_from_DEVICE_OBJECT(device);
542 *out_length = ext->report_descriptor_size;
544 if (length < ext->report_descriptor_size)
545 return STATUS_BUFFER_TOO_SMALL;
547 memcpy(buffer, ext->report_descriptor, ext->report_descriptor_size);
549 return STATUS_SUCCESS;
552 static NTSTATUS get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length)
554 struct platform_private *ext = impl_from_DEVICE_OBJECT(device);
555 const char* str = NULL;
557 switch (index)
559 case HID_STRING_ID_IPRODUCT:
560 if (ext->sdl_controller)
561 str = pSDL_GameControllerName(ext->sdl_controller);
562 else
563 str = pSDL_JoystickName(ext->sdl_joystick);
564 break;
565 case HID_STRING_ID_IMANUFACTURER:
566 str = "SDL";
567 break;
568 case HID_STRING_ID_ISERIALNUMBER:
569 str = "000000";
570 break;
571 default:
572 ERR("Unhandled string index %i\n", index);
575 if (str && str[0])
576 MultiByteToWideChar(CP_ACP, 0, str, -1, buffer, length);
577 else
578 buffer[0] = 0;
580 return STATUS_SUCCESS;
583 static NTSTATUS begin_report_processing(DEVICE_OBJECT *device)
585 return STATUS_SUCCESS;
588 static NTSTATUS set_output_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *written)
590 struct platform_private *ext = impl_from_DEVICE_OBJECT(device);
592 if (ext->sdl_haptic && id == 0)
594 WORD left = report[2] * 128;
595 WORD right = report[3] * 128;
597 if (ext->haptic_effect_id >= 0)
599 pSDL_HapticDestroyEffect(ext->sdl_haptic, ext->haptic_effect_id);
600 ext->haptic_effect_id = -1;
602 pSDL_HapticStopAll(ext->sdl_haptic);
603 if (left != 0 || right != 0)
605 SDL_HapticEffect effect;
607 pSDL_memset( &effect, 0, sizeof(SDL_HapticEffect) );
608 effect.type = SDL_HAPTIC_LEFTRIGHT;
609 effect.leftright.length = -1;
610 effect.leftright.large_magnitude = left;
611 effect.leftright.small_magnitude = right;
613 ext->haptic_effect_id = pSDL_HapticNewEffect(ext->sdl_haptic, &effect);
614 if (ext->haptic_effect_id >= 0)
616 pSDL_HapticRunEffect(ext->sdl_haptic, ext->haptic_effect_id, 1);
618 else
620 float i = (float)((left + right)/2.0) / 32767.0;
621 pSDL_HapticRumblePlay(ext->sdl_haptic, i, -1);
624 *written = length;
625 return STATUS_SUCCESS;
627 else
629 *written = 0;
630 return STATUS_NOT_IMPLEMENTED;
634 static NTSTATUS get_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *read)
636 *read = 0;
637 return STATUS_NOT_IMPLEMENTED;
640 static NTSTATUS set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE *report, DWORD length, ULONG_PTR *written)
642 *written = 0;
643 return STATUS_NOT_IMPLEMENTED;
646 static const platform_vtbl sdl_vtbl =
648 compare_platform_device,
649 get_reportdescriptor,
650 get_string,
651 begin_report_processing,
652 set_output_report,
653 get_feature_report,
654 set_feature_report,
657 static BOOL set_report_from_event(SDL_Event *event)
659 DEVICE_OBJECT *device;
660 struct platform_private *private;
661 /* All the events coming in will have 'which' as a 3rd field */
662 SDL_JoystickID index = ((SDL_JoyButtonEvent*)event)->which;
664 device = bus_find_hid_device(&sdl_vtbl, ULongToPtr(index));
665 if (!device)
667 ERR("Failed to find device at index %i\n",index);
668 return FALSE;
670 private = impl_from_DEVICE_OBJECT(device);
671 if (private->sdl_controller)
673 /* We want mapped events */
674 return TRUE;
677 switch(event->type)
679 case SDL_JOYBUTTONDOWN:
680 case SDL_JOYBUTTONUP:
682 SDL_JoyButtonEvent *ie = &event->jbutton;
684 set_button_value(ie->button, ie->state, private->report_buffer);
686 process_hid_report(device, private->report_buffer, private->buffer_length);
687 break;
689 case SDL_JOYAXISMOTION:
691 SDL_JoyAxisEvent *ie = &event->jaxis;
693 if (ie->axis < 6)
695 set_axis_value(private, ie->axis, ie->value);
696 process_hid_report(device, private->report_buffer, private->buffer_length);
698 break;
700 case SDL_JOYBALLMOTION:
702 SDL_JoyBallEvent *ie = &event->jball;
704 set_ball_value(private, ie->ball, ie->xrel, ie->yrel);
705 process_hid_report(device, private->report_buffer, private->buffer_length);
706 break;
708 case SDL_JOYHATMOTION:
710 SDL_JoyHatEvent *ie = &event->jhat;
712 set_hat_value(private, ie->hat, ie->value);
713 process_hid_report(device, private->report_buffer, private->buffer_length);
714 break;
716 default:
717 ERR("TODO: Process Report (0x%x)\n",event->type);
719 return FALSE;
722 static BOOL set_mapped_report_from_event(SDL_Event *event)
724 DEVICE_OBJECT *device;
725 struct platform_private *private;
726 /* All the events coming in will have 'which' as a 3rd field */
727 int index = ((SDL_ControllerButtonEvent*)event)->which;
728 device = bus_find_hid_device(&sdl_vtbl, ULongToPtr(index));
729 if (!device)
731 ERR("Failed to find device at index %i\n",index);
732 return FALSE;
734 private = impl_from_DEVICE_OBJECT(device);
736 switch(event->type)
738 case SDL_CONTROLLERBUTTONDOWN:
739 case SDL_CONTROLLERBUTTONUP:
741 int usage = -1;
742 SDL_ControllerButtonEvent *ie = &event->cbutton;
744 switch (ie->button)
746 case SDL_CONTROLLER_BUTTON_A: usage = 0; break;
747 case SDL_CONTROLLER_BUTTON_B: usage = 1; break;
748 case SDL_CONTROLLER_BUTTON_X: usage = 2; break;
749 case SDL_CONTROLLER_BUTTON_Y: usage = 3; break;
750 case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: usage = 4; break;
751 case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: usage = 5; break;
752 case SDL_CONTROLLER_BUTTON_LEFTSTICK: usage = 6; break;
753 case SDL_CONTROLLER_BUTTON_RIGHTSTICK: usage = 7; break;
754 case SDL_CONTROLLER_BUTTON_START: usage = 8; break;
755 case SDL_CONTROLLER_BUTTON_BACK: usage = 9; break;
756 case SDL_CONTROLLER_BUTTON_GUIDE: usage = 10; break;
757 case SDL_CONTROLLER_BUTTON_DPAD_UP: usage = 11; break;
758 case SDL_CONTROLLER_BUTTON_DPAD_DOWN: usage = 12; break;
759 case SDL_CONTROLLER_BUTTON_DPAD_LEFT: usage = 13; break;
760 case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: usage = 14; break;
761 default:
762 ERR("Unknown Button %i\n",ie->button);
765 if (usage >= 0)
767 set_button_value(usage, ie->state, private->report_buffer);
768 process_hid_report(device, private->report_buffer, private->buffer_length);
770 break;
772 case SDL_CONTROLLERAXISMOTION:
774 SDL_ControllerAxisEvent *ie = &event->caxis;
776 set_axis_value(private, ie->axis, ie->value);
777 process_hid_report(device, private->report_buffer, private->buffer_length);
778 break;
780 default:
781 ERR("TODO: Process Report (%x)\n",event->type);
783 return FALSE;
786 static void try_remove_device(SDL_JoystickID index)
788 DEVICE_OBJECT *device = NULL;
790 device = bus_find_hid_device(&sdl_vtbl, ULongToPtr(index));
791 if (!device) return;
793 IoInvalidateDeviceRelations(device, RemovalRelations);
795 bus_remove_hid_device(device);
798 static void try_add_device(SDL_JoystickID index)
800 DWORD vid = 0, pid = 0, version = 0;
801 DEVICE_OBJECT *device = NULL;
802 WCHAR serial[34] = {0};
803 char guid_str[34];
804 BOOL is_xbox_gamepad;
806 SDL_Joystick* joystick;
807 SDL_JoystickID id;
808 SDL_JoystickGUID guid;
809 SDL_GameController *controller = NULL;
811 if ((joystick = pSDL_JoystickOpen(index)) == NULL)
813 WARN("Unable to open sdl device %i: %s\n", index, pSDL_GetError());
814 return;
817 if (map_controllers && pSDL_IsGameController(index))
818 controller = pSDL_GameControllerOpen(index);
820 id = pSDL_JoystickInstanceID(joystick);
821 if (controller)
823 vid = VID_MICROSOFT;
824 pid = PID_XBOX_CONTROLLERS[3];
825 version = 0x01;
827 else
829 if (pSDL_JoystickGetProductVersion != NULL) {
830 vid = pSDL_JoystickGetVendor(joystick);
831 pid = pSDL_JoystickGetProduct(joystick);
832 version = pSDL_JoystickGetProductVersion(joystick);
834 else
836 vid = 0x01;
837 pid = pSDL_JoystickInstanceID(joystick) + 1;
838 version = 0;
842 guid = pSDL_JoystickGetGUID(joystick);
843 pSDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
844 MultiByteToWideChar(CP_ACP, 0, guid_str, -1, serial, sizeof(guid_str));
846 if (controller)
848 TRACE("Found sdl game controller %i (vid %04x, pid %04x, version %u, serial %s)\n",
849 id, vid, pid, version, debugstr_w(serial));
850 is_xbox_gamepad = TRUE;
852 else
854 int button_count, axis_count;
856 TRACE("Found sdl device %i (vid %04x, pid %04x, version %u, serial %s)\n",
857 id, vid, pid, version, debugstr_w(serial));
859 axis_count = pSDL_JoystickNumAxes(joystick);
860 button_count = pSDL_JoystickNumAxes(joystick);
861 is_xbox_gamepad = (axis_count == 6 && button_count >= 14);
864 device = bus_create_hid_device(sdl_driver_obj, sdl_busidW, vid, pid, version, id, serial, is_xbox_gamepad, &GUID_DEVCLASS_SDL, &sdl_vtbl, sizeof(struct platform_private));
866 if (device)
868 BOOL rc;
869 struct platform_private *private = impl_from_DEVICE_OBJECT(device);
870 private->sdl_joystick = joystick;
871 private->sdl_controller = controller;
872 private->id = id;
873 if (controller)
874 rc = build_mapped_report_descriptor(private);
875 else
876 rc = build_report_descriptor(private);
877 if (!rc)
879 ERR("Building report descriptor failed, removing device\n");
880 bus_remove_hid_device(device);
881 HeapFree(GetProcessHeap(), 0, serial);
882 return;
884 IoInvalidateDeviceRelations(device, BusRelations);
886 else
888 WARN("Ignoring device %i\n", id);
892 static void process_device_event(SDL_Event *event)
894 TRACE_(hid_report)("Received action %x\n", event->type);
896 if (event->type == SDL_JOYDEVICEADDED)
897 try_add_device(((SDL_JoyDeviceEvent*)event)->which);
898 else if (event->type == SDL_JOYDEVICEREMOVED)
899 try_remove_device(((SDL_JoyDeviceEvent*)event)->which);
900 else if (event->type >= SDL_JOYAXISMOTION && event->type <= SDL_JOYBUTTONUP)
901 set_report_from_event(event);
902 else if (event->type >= SDL_CONTROLLERAXISMOTION && event->type <= SDL_CONTROLLERBUTTONUP)
903 set_mapped_report_from_event(event);
906 static DWORD CALLBACK deviceloop_thread(void *args)
908 HANDLE init_done = args;
909 SDL_Event event;
911 if (pSDL_Init(SDL_INIT_GAMECONTROLLER|SDL_INIT_HAPTIC) < 0)
913 ERR("Can't init SDL: %s\n", pSDL_GetError());
914 return STATUS_UNSUCCESSFUL;
917 pSDL_JoystickEventState(SDL_ENABLE);
918 pSDL_GameControllerEventState(SDL_ENABLE);
920 SetEvent(init_done);
922 while (1)
923 while (pSDL_WaitEvent(&event) != 0)
924 process_device_event(&event);
926 TRACE("Device thread exiting\n");
927 return 0;
930 void sdl_driver_unload( void )
932 TRACE("Unload Driver\n");
935 NTSTATUS WINAPI sdl_driver_init(DRIVER_OBJECT *driver, UNICODE_STRING *registry_path)
937 static const WCHAR controller_modeW[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0};
938 static const UNICODE_STRING controller_mode = {sizeof(controller_modeW) - sizeof(WCHAR), sizeof(controller_modeW), (WCHAR*)controller_modeW};
940 HANDLE events[2];
941 DWORD result;
943 TRACE("(%p, %s)\n", driver, debugstr_w(registry_path->Buffer));
944 if (sdl_handle == NULL)
946 sdl_handle = wine_dlopen(SONAME_LIBSDL2, RTLD_NOW, NULL, 0);
947 if (!sdl_handle) {
948 WARN("could not load %s\n", SONAME_LIBSDL2);
949 sdl_driver_obj = NULL;
950 return STATUS_UNSUCCESSFUL;
952 #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;}
953 LOAD_FUNCPTR(SDL_GetError);
954 LOAD_FUNCPTR(SDL_Init);
955 LOAD_FUNCPTR(SDL_JoystickEventState);
956 LOAD_FUNCPTR(SDL_JoystickGetGUID);
957 LOAD_FUNCPTR(SDL_JoystickGetGUIDString);
958 LOAD_FUNCPTR(SDL_JoystickInstanceID);
959 LOAD_FUNCPTR(SDL_JoystickName);
960 LOAD_FUNCPTR(SDL_JoystickNumAxes);
961 LOAD_FUNCPTR(SDL_JoystickOpen);
962 LOAD_FUNCPTR(SDL_WaitEvent);
963 LOAD_FUNCPTR(SDL_JoystickNumButtons);
964 LOAD_FUNCPTR(SDL_JoystickNumBalls);
965 LOAD_FUNCPTR(SDL_JoystickNumHats);
966 LOAD_FUNCPTR(SDL_JoystickGetAxis);
967 LOAD_FUNCPTR(SDL_JoystickGetHat);
968 LOAD_FUNCPTR(SDL_IsGameController);
969 LOAD_FUNCPTR(SDL_GameControllerGetAxis);
970 LOAD_FUNCPTR(SDL_GameControllerName);
971 LOAD_FUNCPTR(SDL_GameControllerOpen);
972 LOAD_FUNCPTR(SDL_GameControllerEventState);
973 LOAD_FUNCPTR(SDL_HapticClose);
974 LOAD_FUNCPTR(SDL_HapticDestroyEffect);
975 LOAD_FUNCPTR(SDL_HapticNewEffect);
976 LOAD_FUNCPTR(SDL_HapticOpenFromJoystick);
977 LOAD_FUNCPTR(SDL_HapticQuery);
978 LOAD_FUNCPTR(SDL_HapticRumbleInit);
979 LOAD_FUNCPTR(SDL_HapticRumblePlay);
980 LOAD_FUNCPTR(SDL_HapticRumbleSupported);
981 LOAD_FUNCPTR(SDL_HapticRunEffect);
982 LOAD_FUNCPTR(SDL_HapticStopAll);
983 LOAD_FUNCPTR(SDL_JoystickIsHaptic);
984 LOAD_FUNCPTR(SDL_memset);
985 #undef LOAD_FUNCPTR
986 pSDL_JoystickGetProduct = wine_dlsym(sdl_handle, "SDL_JoystickGetProduct", NULL, 0);
987 pSDL_JoystickGetProductVersion = wine_dlsym(sdl_handle, "SDL_JoystickGetProductVersion", NULL, 0);
988 pSDL_JoystickGetVendor = wine_dlsym(sdl_handle, "SDL_JoystickGetVendor", NULL, 0);
991 sdl_driver_obj = driver;
992 driver->MajorFunction[IRP_MJ_PNP] = common_pnp_dispatch;
993 driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = hid_internal_dispatch;
995 map_controllers = check_bus_option(registry_path, &controller_mode, 1);
997 if (!(events[0] = CreateEventW(NULL, TRUE, FALSE, NULL)))
998 goto error;
999 if (!(events[1] = CreateThread(NULL, 0, deviceloop_thread, events[0], 0, NULL)))
1001 CloseHandle(events[0]);
1002 goto error;
1005 result = WaitForMultipleObjects(2, events, FALSE, INFINITE);
1006 CloseHandle(events[0]);
1007 CloseHandle(events[1]);
1008 if (result == WAIT_OBJECT_0)
1010 TRACE("Initialization successful\n");
1011 return STATUS_SUCCESS;
1014 error:
1015 sdl_driver_obj = NULL;
1016 return STATUS_UNSUCCESSFUL;
1017 sym_not_found:
1018 wine_dlclose(sdl_handle, NULL, 0);
1019 sdl_handle = NULL;
1020 return STATUS_UNSUCCESSFUL;
1023 #else
1025 NTSTATUS WINAPI sdl_driver_init(DRIVER_OBJECT *driver, UNICODE_STRING *registry_path)
1027 WARN("compiled without SDL support\n");
1028 return STATUS_NOT_IMPLEMENTED;
1031 void sdl_driver_unload( void )
1033 TRACE("Stub: Unload Driver\n");
1036 #endif /* SONAME_LIBSDL2 */