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
22 #include "wine/port.h"
30 #ifdef HAVE_SDL2_SDL_H
31 # include <SDL2/SDL.h>
34 #define NONAMELESSUNION
37 #define WIN32_NO_STATUS
44 #include "ddk/hidtypes.h"
45 #include "wine/debug.h"
46 #include "wine/unicode.h"
48 #include "controller.h"
50 #ifdef WORDS_BIGENDIAN
51 # define LE_WORD(x) RtlUshortByteSwap(x)
53 # define LE_WORD(x) (x)
58 WINE_DEFAULT_DEBUG_CHANNEL(plugplay
);
62 WINE_DECLARE_DEBUG_CHANNEL(hid_report
);
64 static const WCHAR sdl_busidW
[] = {'S','D','L','J','O','Y',0};
66 static DWORD map_controllers
= 0;
68 static void *sdl_handle
= NULL
;
69 static HANDLE deviceloop_handle
;
70 static UINT quit_event
= -1;
73 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
74 MAKE_FUNCPTR(SDL_GetError
);
75 MAKE_FUNCPTR(SDL_Init
);
76 MAKE_FUNCPTR(SDL_JoystickClose
);
77 MAKE_FUNCPTR(SDL_JoystickEventState
);
78 MAKE_FUNCPTR(SDL_JoystickGetGUID
);
79 MAKE_FUNCPTR(SDL_JoystickGetGUIDString
);
80 MAKE_FUNCPTR(SDL_JoystickInstanceID
);
81 MAKE_FUNCPTR(SDL_JoystickName
);
82 MAKE_FUNCPTR(SDL_JoystickNumAxes
);
83 MAKE_FUNCPTR(SDL_JoystickOpen
);
84 MAKE_FUNCPTR(SDL_WaitEvent
);
85 MAKE_FUNCPTR(SDL_JoystickNumButtons
);
86 MAKE_FUNCPTR(SDL_JoystickNumBalls
);
87 MAKE_FUNCPTR(SDL_JoystickNumHats
);
88 MAKE_FUNCPTR(SDL_JoystickGetAxis
);
89 MAKE_FUNCPTR(SDL_JoystickGetHat
);
90 MAKE_FUNCPTR(SDL_IsGameController
);
91 MAKE_FUNCPTR(SDL_GameControllerClose
);
92 MAKE_FUNCPTR(SDL_GameControllerGetAxis
);
93 MAKE_FUNCPTR(SDL_GameControllerGetButton
);
94 MAKE_FUNCPTR(SDL_GameControllerName
);
95 MAKE_FUNCPTR(SDL_GameControllerOpen
);
96 MAKE_FUNCPTR(SDL_GameControllerEventState
);
97 MAKE_FUNCPTR(SDL_HapticClose
);
98 MAKE_FUNCPTR(SDL_HapticDestroyEffect
);
99 MAKE_FUNCPTR(SDL_HapticNewEffect
);
100 MAKE_FUNCPTR(SDL_HapticOpenFromJoystick
);
101 MAKE_FUNCPTR(SDL_HapticQuery
);
102 MAKE_FUNCPTR(SDL_HapticRumbleInit
);
103 MAKE_FUNCPTR(SDL_HapticRumblePlay
);
104 MAKE_FUNCPTR(SDL_HapticRumbleSupported
);
105 MAKE_FUNCPTR(SDL_HapticRunEffect
);
106 MAKE_FUNCPTR(SDL_HapticStopAll
);
107 MAKE_FUNCPTR(SDL_JoystickIsHaptic
);
108 MAKE_FUNCPTR(SDL_memset
);
109 MAKE_FUNCPTR(SDL_GameControllerAddMapping
);
110 MAKE_FUNCPTR(SDL_RegisterEvents
);
111 MAKE_FUNCPTR(SDL_PushEvent
);
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
;
126 int hat_bit_offs
; /* hatswitches are reported in the same bytes as buttons */
128 int report_descriptor_size
;
129 BYTE
*report_descriptor
;
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) */
206 0x95, 0x02, /* REPORT_COUNT (2) */
207 0x75, 0x08, /* REPORT_SIZE (8) */
208 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
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) */
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
)
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
);
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
);
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
);
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
;
258 ext
->report_buffer
[byte_index
] = ext
->report_buffer
[byte_index
] | 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
, BOOL controller
)
269 WORD
*report
= (WORD
*)(ext
->report_buffer
+ ext
->axis_start
);
271 if (controller
&& (index
== SDL_CONTROLLER_AXIS_TRIGGERLEFT
|| index
== SDL_CONTROLLER_AXIS_TRIGGERRIGHT
))
272 report
[index
] = LE_WORD(value
);
274 report
[index
] = LE_WORD(value
) + 32768;
277 static void set_ball_value(struct platform_private
*ext
, int index
, int value1
, int value2
)
280 offset
= ext
->ball_start
+ (index
* sizeof(WORD
));
281 if (value1
> 127) value1
= 127;
282 if (value1
< -127) value1
= -127;
283 if (value2
> 127) value2
= 127;
284 if (value2
< -127) value2
= -127;
285 *((WORD
*)&ext
->report_buffer
[offset
]) = LE_WORD(value1
);
286 *((WORD
*)&ext
->report_buffer
[offset
+ sizeof(WORD
)]) = LE_WORD(value2
);
289 static void set_hat_value(struct platform_private
*ext
, int index
, int value
)
291 int byte
= ext
->button_start
+ (ext
->hat_bit_offs
+ 4 * index
) / 8;
292 int bit_offs
= (ext
->hat_bit_offs
+ 4 * index
) % 8;
293 int num_low_bits
, num_high_bits
;
294 unsigned char val
, low_mask
, high_mask
;
296 /* 4-bit hatswitch value is packed into button bytes */
306 num_low_bits
= 8 - bit_offs
;
307 num_high_bits
= 4 - num_low_bits
;
308 low_mask
= (1 << num_low_bits
) - 1;
309 high_mask
= (1 << num_high_bits
) - 1;
317 case SDL_HAT_CENTERED
: val
= 0; break;
318 case SDL_HAT_UP
: val
= 1; break;
319 case SDL_HAT_RIGHTUP
: val
= 2; break;
320 case SDL_HAT_RIGHT
: val
= 3; break;
321 case SDL_HAT_RIGHTDOWN
: val
= 4; break;
322 case SDL_HAT_DOWN
: val
= 5; break;
323 case SDL_HAT_LEFTDOWN
: val
= 6; break;
324 case SDL_HAT_LEFT
: val
= 7; break;
325 case SDL_HAT_LEFTUP
: val
= 8; break;
329 ext
->report_buffer
[byte
] &= ~(low_mask
<< bit_offs
);
330 ext
->report_buffer
[byte
] |= (val
& low_mask
) << bit_offs
;
333 ext
->report_buffer
[byte
+ 1] &= ~high_mask
;
334 ext
->report_buffer
[byte
+ 1] |= val
& high_mask
;
338 static int test_haptic(struct platform_private
*ext
)
341 if (pSDL_JoystickIsHaptic(ext
->sdl_joystick
))
343 ext
->sdl_haptic
= pSDL_HapticOpenFromJoystick(ext
->sdl_joystick
);
344 if (ext
->sdl_haptic
&&
345 ((pSDL_HapticQuery(ext
->sdl_haptic
) & SDL_HAPTIC_LEFTRIGHT
) != 0 ||
346 pSDL_HapticRumbleSupported(ext
->sdl_haptic
)))
348 pSDL_HapticStopAll(ext
->sdl_haptic
);
349 pSDL_HapticRumbleInit(ext
->sdl_haptic
);
350 rc
= sizeof(HAPTIC_RUMBLE
);
351 ext
->haptic_effect_id
= -1;
355 pSDL_HapticClose(ext
->sdl_haptic
);
356 ext
->sdl_haptic
= NULL
;
362 static int build_haptic(struct platform_private
*ext
, BYTE
*report_ptr
)
366 memcpy(report_ptr
, HAPTIC_RUMBLE
, sizeof(HAPTIC_RUMBLE
));
367 return (sizeof(HAPTIC_RUMBLE
));
372 static BOOL
build_report_descriptor(struct platform_private
*ext
)
375 INT i
, descript_size
;
377 INT button_count
, axis_count
, ball_count
, hat_count
;
378 static const BYTE device_usage
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_GAMEPAD
};
379 static const BYTE controller_usages
[] = {
383 HID_USAGE_GENERIC_RX
,
384 HID_USAGE_GENERIC_RY
,
385 HID_USAGE_GENERIC_RZ
,
386 HID_USAGE_GENERIC_SLIDER
,
387 HID_USAGE_GENERIC_DIAL
,
388 HID_USAGE_GENERIC_WHEEL
};
389 static const BYTE joystick_usages
[] = {
393 HID_USAGE_GENERIC_RZ
,
394 HID_USAGE_GENERIC_RX
,
395 HID_USAGE_GENERIC_RY
,
396 HID_USAGE_GENERIC_SLIDER
,
397 HID_USAGE_GENERIC_DIAL
,
398 HID_USAGE_GENERIC_WHEEL
};
400 descript_size
= sizeof(REPORT_HEADER
) + sizeof(REPORT_TAIL
);
403 axis_count
= pSDL_JoystickNumAxes(ext
->sdl_joystick
);
406 FIXME("Clamping joystick to 6 axis\n");
410 ext
->axis_start
= report_size
;
413 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
414 descript_size
+= (sizeof(REPORT_AXIS_USAGE
) * axis_count
);
415 descript_size
+= sizeof(REPORT_AXIS_TAIL
);
416 report_size
+= (sizeof(WORD
) * axis_count
);
419 ball_count
= pSDL_JoystickNumBalls(ext
->sdl_joystick
);
420 ext
->ball_start
= report_size
;
423 if ((ball_count
*2) + axis_count
> 9)
425 FIXME("Capping ball + axis at 9\n");
426 ball_count
= (9-axis_count
)/2;
428 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
429 descript_size
+= (sizeof(REPORT_AXIS_USAGE
) * ball_count
* 2);
430 descript_size
+= sizeof(REPORT_REL_AXIS_TAIL
);
431 report_size
+= (sizeof(WORD
) * 2 * ball_count
);
434 /* For now lump all buttons just into incremental usages, Ignore Keys */
435 button_count
= pSDL_JoystickNumButtons(ext
->sdl_joystick
);
436 ext
->button_start
= report_size
;
439 descript_size
+= sizeof(REPORT_BUTTONS
);
442 hat_count
= pSDL_JoystickNumHats(ext
->sdl_joystick
);
443 ext
->hat_bit_offs
= button_count
;
446 descript_size
+= sizeof(REPORT_HATSWITCH
);
449 report_size
+= (button_count
+ hat_count
* 4 + 7) / 8;
451 descript_size
+= test_haptic(ext
);
453 TRACE("Report Descriptor will be %i bytes\n", descript_size
);
454 TRACE("Report will be %i bytes\n", report_size
);
456 ext
->report_descriptor
= HeapAlloc(GetProcessHeap(), 0, descript_size
);
457 if (!ext
->report_descriptor
)
459 ERR("Failed to alloc report descriptor\n");
462 report_ptr
= ext
->report_descriptor
;
464 memcpy(report_ptr
, REPORT_HEADER
, sizeof(REPORT_HEADER
));
465 report_ptr
[IDX_HEADER_PAGE
] = device_usage
[0];
466 report_ptr
[IDX_HEADER_USAGE
] = device_usage
[1];
467 report_ptr
+= sizeof(REPORT_HEADER
);
470 if (axis_count
== 6 && button_count
>= 14)
471 report_ptr
= add_axis_block(report_ptr
, axis_count
, HID_USAGE_PAGE_GENERIC
, controller_usages
, TRUE
);
473 report_ptr
= add_axis_block(report_ptr
, axis_count
, HID_USAGE_PAGE_GENERIC
, joystick_usages
, TRUE
);
478 report_ptr
= add_axis_block(report_ptr
, ball_count
* 2, HID_USAGE_PAGE_GENERIC
, &joystick_usages
[axis_count
], FALSE
);
482 report_ptr
= add_button_block(report_ptr
, 1, button_count
);
485 report_ptr
= add_hatswitch(report_ptr
, hat_count
);
487 report_ptr
+= build_haptic(ext
, report_ptr
);
488 memcpy(report_ptr
, REPORT_TAIL
, sizeof(REPORT_TAIL
));
490 ext
->report_descriptor_size
= descript_size
;
491 ext
->buffer_length
= report_size
;
492 ext
->report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, report_size
);
493 if (ext
->report_buffer
== NULL
)
495 ERR("Failed to alloc report buffer\n");
496 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
500 /* Initialize axis in the report */
501 for (i
= 0; i
< axis_count
; i
++)
502 set_axis_value(ext
, i
, pSDL_JoystickGetAxis(ext
->sdl_joystick
, i
), FALSE
);
503 for (i
= 0; i
< hat_count
; i
++)
504 set_hat_value(ext
, i
, pSDL_JoystickGetHat(ext
->sdl_joystick
, i
));
509 static SHORT
compose_dpad_value(SDL_GameController
*joystick
)
511 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_UP
))
513 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_RIGHT
))
514 return SDL_HAT_RIGHTUP
;
515 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_LEFT
))
516 return SDL_HAT_LEFTUP
;
520 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_DOWN
))
522 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_RIGHT
))
523 return SDL_HAT_RIGHTDOWN
;
524 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_LEFT
))
525 return SDL_HAT_LEFTDOWN
;
529 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_RIGHT
))
530 return SDL_HAT_RIGHT
;
531 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_LEFT
))
533 return SDL_HAT_CENTERED
;
536 static BOOL
build_mapped_report_descriptor(struct platform_private
*ext
)
539 INT i
, descript_size
;
541 static const int BUTTON_BIT_COUNT
= CONTROLLER_NUM_BUTTONS
+ CONTROLLER_NUM_HATSWITCHES
* 4;
543 descript_size
= sizeof(REPORT_HEADER
) + sizeof(REPORT_TAIL
);
544 descript_size
+= sizeof(CONTROLLER_AXIS
);
545 descript_size
+= sizeof(CONTROLLER_TRIGGERS
);
546 descript_size
+= sizeof(CONTROLLER_BUTTONS
);
547 descript_size
+= sizeof(REPORT_HATSWITCH
);
548 descript_size
+= sizeof(REPORT_PADDING
);
549 if (BUTTON_BIT_COUNT
% 8 != 0)
550 descript_size
+= sizeof(REPORT_PADDING
);
551 descript_size
+= test_haptic(ext
);
554 ext
->button_start
= CONTROLLER_NUM_AXES
* sizeof(WORD
);
555 ext
->hat_bit_offs
= CONTROLLER_NUM_BUTTONS
;
557 ext
->buffer_length
= (BUTTON_BIT_COUNT
+ 7) / 8
558 + CONTROLLER_NUM_AXES
* sizeof(WORD
)
559 + 2/* unknown constant*/;
561 TRACE("Report Descriptor will be %i bytes\n", descript_size
);
562 TRACE("Report will be %i bytes\n", ext
->buffer_length
);
564 ext
->report_descriptor
= HeapAlloc(GetProcessHeap(), 0, descript_size
);
565 if (!ext
->report_descriptor
)
567 ERR("Failed to alloc report descriptor\n");
570 report_ptr
= ext
->report_descriptor
;
572 memcpy(report_ptr
, REPORT_HEADER
, sizeof(REPORT_HEADER
));
573 report_ptr
[IDX_HEADER_PAGE
] = HID_USAGE_PAGE_GENERIC
;
574 report_ptr
[IDX_HEADER_USAGE
] = HID_USAGE_GENERIC_GAMEPAD
;
575 report_ptr
+= sizeof(REPORT_HEADER
);
576 memcpy(report_ptr
, CONTROLLER_AXIS
, sizeof(CONTROLLER_AXIS
));
577 report_ptr
+= sizeof(CONTROLLER_AXIS
);
578 memcpy(report_ptr
, CONTROLLER_TRIGGERS
, sizeof(CONTROLLER_TRIGGERS
));
579 report_ptr
+= sizeof(CONTROLLER_TRIGGERS
);
580 memcpy(report_ptr
, CONTROLLER_BUTTONS
, sizeof(CONTROLLER_BUTTONS
));
581 report_ptr
+= sizeof(CONTROLLER_BUTTONS
);
582 report_ptr
= add_hatswitch(report_ptr
, 1);
583 if (BUTTON_BIT_COUNT
% 8 != 0)
584 report_ptr
= add_padding_block(report_ptr
, 8 - (BUTTON_BIT_COUNT
% 8));/* unused bits between hatswitch and following constant */
585 report_ptr
= add_padding_block(report_ptr
, 16);/* unknown constant */
586 report_ptr
+= build_haptic(ext
, report_ptr
);
587 memcpy(report_ptr
, REPORT_TAIL
, sizeof(REPORT_TAIL
));
589 ext
->report_descriptor_size
= descript_size
;
590 ext
->report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ext
->buffer_length
);
591 if (ext
->report_buffer
== NULL
)
593 ERR("Failed to alloc report buffer\n");
594 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
598 /* Initialize axis in the report */
599 for (i
= SDL_CONTROLLER_AXIS_LEFTX
; i
< SDL_CONTROLLER_AXIS_MAX
; i
++)
600 set_axis_value(ext
, i
, pSDL_GameControllerGetAxis(ext
->sdl_controller
, i
), TRUE
);
602 set_hat_value(ext
, 0, compose_dpad_value(ext
->sdl_controller
));
604 /* unknown constant */
605 ext
->report_buffer
[14] = 0x89;
606 ext
->report_buffer
[15] = 0xc5;
611 static int compare_platform_device(DEVICE_OBJECT
*device
, void *platform_dev
)
613 SDL_JoystickID id1
= impl_from_DEVICE_OBJECT(device
)->id
;
614 SDL_JoystickID id2
= PtrToUlong(platform_dev
);
618 static NTSTATUS
get_reportdescriptor(DEVICE_OBJECT
*device
, BYTE
*buffer
, DWORD length
, DWORD
*out_length
)
620 struct platform_private
*ext
= impl_from_DEVICE_OBJECT(device
);
622 *out_length
= ext
->report_descriptor_size
;
624 if (length
< ext
->report_descriptor_size
)
625 return STATUS_BUFFER_TOO_SMALL
;
627 memcpy(buffer
, ext
->report_descriptor
, ext
->report_descriptor_size
);
629 return STATUS_SUCCESS
;
632 static NTSTATUS
get_string(DEVICE_OBJECT
*device
, DWORD index
, WCHAR
*buffer
, DWORD length
)
634 struct platform_private
*ext
= impl_from_DEVICE_OBJECT(device
);
635 const char* str
= NULL
;
639 case HID_STRING_ID_IPRODUCT
:
640 if (ext
->sdl_controller
)
641 str
= pSDL_GameControllerName(ext
->sdl_controller
);
643 str
= pSDL_JoystickName(ext
->sdl_joystick
);
645 case HID_STRING_ID_IMANUFACTURER
:
648 case HID_STRING_ID_ISERIALNUMBER
:
652 ERR("Unhandled string index %i\n", index
);
656 MultiByteToWideChar(CP_ACP
, 0, str
, -1, buffer
, length
);
660 return STATUS_SUCCESS
;
663 static NTSTATUS
begin_report_processing(DEVICE_OBJECT
*device
)
665 return STATUS_SUCCESS
;
668 static NTSTATUS
set_output_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
670 struct platform_private
*ext
= impl_from_DEVICE_OBJECT(device
);
672 if (ext
->sdl_haptic
&& id
== 0)
674 WORD left
= report
[2] * 128;
675 WORD right
= report
[3] * 128;
677 if (ext
->haptic_effect_id
>= 0)
679 pSDL_HapticDestroyEffect(ext
->sdl_haptic
, ext
->haptic_effect_id
);
680 ext
->haptic_effect_id
= -1;
682 pSDL_HapticStopAll(ext
->sdl_haptic
);
683 if (left
!= 0 || right
!= 0)
685 SDL_HapticEffect effect
;
687 pSDL_memset( &effect
, 0, sizeof(SDL_HapticEffect
) );
688 effect
.type
= SDL_HAPTIC_LEFTRIGHT
;
689 effect
.leftright
.length
= -1;
690 effect
.leftright
.large_magnitude
= left
;
691 effect
.leftright
.small_magnitude
= right
;
693 ext
->haptic_effect_id
= pSDL_HapticNewEffect(ext
->sdl_haptic
, &effect
);
694 if (ext
->haptic_effect_id
>= 0)
696 pSDL_HapticRunEffect(ext
->sdl_haptic
, ext
->haptic_effect_id
, 1);
700 float i
= (float)((left
+ right
)/2.0) / 32767.0;
701 pSDL_HapticRumblePlay(ext
->sdl_haptic
, i
, -1);
705 return STATUS_SUCCESS
;
710 return STATUS_NOT_IMPLEMENTED
;
714 static NTSTATUS
get_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*read
)
717 return STATUS_NOT_IMPLEMENTED
;
720 static NTSTATUS
set_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
723 return STATUS_NOT_IMPLEMENTED
;
726 static const platform_vtbl sdl_vtbl
=
728 compare_platform_device
,
729 get_reportdescriptor
,
731 begin_report_processing
,
737 static int compare_joystick_id(DEVICE_OBJECT
*device
, void* context
)
739 return impl_from_DEVICE_OBJECT(device
)->id
- PtrToUlong(context
);
742 static BOOL
set_report_from_event(SDL_Event
*event
)
744 DEVICE_OBJECT
*device
;
745 struct platform_private
*private;
746 /* All the events coming in will have 'which' as a 3rd field */
747 SDL_JoystickID id
= ((SDL_JoyButtonEvent
*)event
)->which
;
748 device
= bus_enumerate_hid_devices(&sdl_vtbl
, compare_joystick_id
, ULongToPtr(id
));
751 ERR("Failed to find device at index %i\n",id
);
754 private = impl_from_DEVICE_OBJECT(device
);
755 if (private->sdl_controller
)
757 /* We want mapped events */
763 case SDL_JOYBUTTONDOWN
:
764 case SDL_JOYBUTTONUP
:
766 SDL_JoyButtonEvent
*ie
= &event
->jbutton
;
768 set_button_value(private, ie
->button
, ie
->state
);
770 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
773 case SDL_JOYAXISMOTION
:
775 SDL_JoyAxisEvent
*ie
= &event
->jaxis
;
779 set_axis_value(private, ie
->axis
, ie
->value
, FALSE
);
780 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
784 case SDL_JOYBALLMOTION
:
786 SDL_JoyBallEvent
*ie
= &event
->jball
;
788 set_ball_value(private, ie
->ball
, ie
->xrel
, ie
->yrel
);
789 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
792 case SDL_JOYHATMOTION
:
794 SDL_JoyHatEvent
*ie
= &event
->jhat
;
796 set_hat_value(private, ie
->hat
, ie
->value
);
797 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
801 ERR("TODO: Process Report (0x%x)\n",event
->type
);
806 static BOOL
set_mapped_report_from_event(SDL_Event
*event
)
808 DEVICE_OBJECT
*device
;
809 struct platform_private
*private;
810 /* All the events coming in will have 'which' as a 3rd field */
811 SDL_JoystickID id
= ((SDL_ControllerButtonEvent
*)event
)->which
;
812 device
= bus_enumerate_hid_devices(&sdl_vtbl
, compare_joystick_id
, ULongToPtr(id
));
815 ERR("Failed to find device at index %i\n",id
);
818 private = impl_from_DEVICE_OBJECT(device
);
822 case SDL_CONTROLLERBUTTONDOWN
:
823 case SDL_CONTROLLERBUTTONUP
:
826 SDL_ControllerButtonEvent
*ie
= &event
->cbutton
;
830 case SDL_CONTROLLER_BUTTON_A
: usage
= 0; break;
831 case SDL_CONTROLLER_BUTTON_B
: usage
= 1; break;
832 case SDL_CONTROLLER_BUTTON_X
: usage
= 2; break;
833 case SDL_CONTROLLER_BUTTON_Y
: usage
= 3; break;
834 case SDL_CONTROLLER_BUTTON_LEFTSHOULDER
: usage
= 4; break;
835 case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
: usage
= 5; break;
836 case SDL_CONTROLLER_BUTTON_BACK
: usage
= 6; break;
837 case SDL_CONTROLLER_BUTTON_START
: usage
= 7; break;
838 case SDL_CONTROLLER_BUTTON_LEFTSTICK
: usage
= 8; break;
839 case SDL_CONTROLLER_BUTTON_RIGHTSTICK
: usage
= 9; break;
840 case SDL_CONTROLLER_BUTTON_GUIDE
: usage
= 10; break;
842 case SDL_CONTROLLER_BUTTON_DPAD_UP
:
843 case SDL_CONTROLLER_BUTTON_DPAD_DOWN
:
844 case SDL_CONTROLLER_BUTTON_DPAD_LEFT
:
845 case SDL_CONTROLLER_BUTTON_DPAD_RIGHT
:
846 set_hat_value(private, 0, compose_dpad_value(private->sdl_controller
));
847 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
851 ERR("Unknown Button %i\n",ie
->button
);
856 set_button_value(private, usage
, ie
->state
);
857 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
861 case SDL_CONTROLLERAXISMOTION
:
863 SDL_ControllerAxisEvent
*ie
= &event
->caxis
;
865 set_axis_value(private, ie
->axis
, ie
->value
, TRUE
);
866 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
870 ERR("TODO: Process Report (%x)\n",event
->type
);
875 static void try_remove_device(SDL_JoystickID id
)
877 DEVICE_OBJECT
*device
= NULL
;
878 struct platform_private
*private;
879 SDL_Joystick
*sdl_joystick
;
880 SDL_GameController
*sdl_controller
;
881 SDL_Haptic
*sdl_haptic
;
883 device
= bus_enumerate_hid_devices(&sdl_vtbl
, compare_joystick_id
, ULongToPtr(id
));
886 private = impl_from_DEVICE_OBJECT(device
);
887 sdl_joystick
= private->sdl_joystick
;
888 sdl_controller
= private->sdl_controller
;
889 sdl_haptic
= private->sdl_haptic
;
891 bus_unlink_hid_device(device
);
892 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
894 bus_remove_hid_device(device
);
896 pSDL_JoystickClose(sdl_joystick
);
898 pSDL_GameControllerClose(sdl_controller
);
900 pSDL_HapticClose(sdl_haptic
);
903 static void try_add_device(unsigned int index
)
905 DWORD vid
= 0, pid
= 0, version
= 0;
906 DEVICE_OBJECT
*device
= NULL
;
907 WCHAR serial
[34] = {0};
909 BOOL is_xbox_gamepad
;
912 SDL_Joystick
* joystick
;
914 SDL_JoystickGUID guid
;
915 SDL_GameController
*controller
= NULL
;
917 if ((joystick
= pSDL_JoystickOpen(index
)) == NULL
)
919 WARN("Unable to open sdl device %i: %s\n", index
, pSDL_GetError());
923 if (map_controllers
&& pSDL_IsGameController(index
))
924 controller
= pSDL_GameControllerOpen(index
);
926 id
= pSDL_JoystickInstanceID(joystick
);
928 if (pSDL_JoystickGetProductVersion
!= NULL
) {
929 vid
= pSDL_JoystickGetVendor(joystick
);
930 pid
= pSDL_JoystickGetProduct(joystick
);
931 version
= pSDL_JoystickGetProductVersion(joystick
);
936 pid
= pSDL_JoystickInstanceID(joystick
) + 1;
940 guid
= pSDL_JoystickGetGUID(joystick
);
941 pSDL_JoystickGetGUIDString(guid
, guid_str
, sizeof(guid_str
));
942 MultiByteToWideChar(CP_ACP
, 0, guid_str
, -1, serial
, sizeof(guid_str
));
946 TRACE("Found sdl game controller %i (vid %04x, pid %04x, version %u, serial %s)\n",
947 id
, vid
, pid
, version
, debugstr_w(serial
));
948 is_xbox_gamepad
= TRUE
;
952 int button_count
, axis_count
;
954 TRACE("Found sdl device %i (vid %04x, pid %04x, version %u, serial %s)\n",
955 id
, vid
, pid
, version
, debugstr_w(serial
));
957 axis_count
= pSDL_JoystickNumAxes(joystick
);
958 button_count
= pSDL_JoystickNumButtons(joystick
);
959 is_xbox_gamepad
= (axis_count
== 6 && button_count
>= 14);
964 device
= bus_create_hid_device(sdl_busidW
, vid
, pid
, input
, version
, index
,
965 serial
, is_xbox_gamepad
, &sdl_vtbl
, sizeof(struct platform_private
));
970 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
971 private->sdl_joystick
= joystick
;
972 private->sdl_controller
= controller
;
975 rc
= build_mapped_report_descriptor(private);
977 rc
= build_report_descriptor(private);
980 ERR("Building report descriptor failed, removing device\n");
981 bus_unlink_hid_device(device
);
982 bus_remove_hid_device(device
);
983 HeapFree(GetProcessHeap(), 0, serial
);
986 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
990 WARN("Ignoring device %i\n", id
);
994 static void process_device_event(SDL_Event
*event
)
996 TRACE_(hid_report
)("Received action %x\n", event
->type
);
998 if (event
->type
== SDL_JOYDEVICEADDED
)
999 try_add_device(((SDL_JoyDeviceEvent
*)event
)->which
);
1000 else if (event
->type
== SDL_JOYDEVICEREMOVED
)
1001 try_remove_device(((SDL_JoyDeviceEvent
*)event
)->which
);
1002 else if (event
->type
>= SDL_JOYAXISMOTION
&& event
->type
<= SDL_JOYBUTTONUP
)
1003 set_report_from_event(event
);
1004 else if (event
->type
>= SDL_CONTROLLERAXISMOTION
&& event
->type
<= SDL_CONTROLLERBUTTONUP
)
1005 set_mapped_report_from_event(event
);
1008 static DWORD CALLBACK
deviceloop_thread(void *args
)
1010 HANDLE init_done
= args
;
1013 if (pSDL_Init(SDL_INIT_GAMECONTROLLER
|SDL_INIT_HAPTIC
) < 0)
1015 ERR("Can't init SDL: %s\n", pSDL_GetError());
1016 return STATUS_UNSUCCESSFUL
;
1019 pSDL_JoystickEventState(SDL_ENABLE
);
1020 pSDL_GameControllerEventState(SDL_ENABLE
);
1022 /* Process mappings */
1023 if (pSDL_GameControllerAddMapping
!= NULL
)
1026 static const WCHAR szPath
[] = {'m','a','p',0};
1027 const char *mapping
;
1029 if ((mapping
= getenv("SDL_GAMECONTROLLERCONFIG")))
1031 TRACE("Setting environment mapping %s\n", debugstr_a(mapping
));
1032 if (pSDL_GameControllerAddMapping(mapping
) < 0)
1033 WARN("Failed to add environment mapping %s\n", pSDL_GetError());
1035 else if (!RegOpenKeyExW(driver_key
, szPath
, 0, KEY_QUERY_VALUE
, &key
))
1038 CHAR
*buffer
= NULL
;
1039 DWORD buffer_len
= 0;
1046 DWORD data_len
= buffer_len
;
1048 name_len
= sizeof(name
);
1049 rc
= RegEnumValueA(key
, index
, name
, &name_len
, NULL
, &type
, (LPBYTE
)buffer
, &data_len
);
1050 if (rc
== ERROR_MORE_DATA
|| buffer
== NULL
)
1053 buffer
= HeapReAlloc(GetProcessHeap(), 0, buffer
, data_len
);
1055 buffer
= HeapAlloc(GetProcessHeap(), 0, data_len
);
1056 buffer_len
= data_len
;
1058 name_len
= sizeof(name
);
1059 rc
= RegEnumValueA(key
, index
, name
, &name_len
, NULL
, &type
, (LPBYTE
)buffer
, &data_len
);
1062 if (rc
== STATUS_SUCCESS
)
1064 TRACE("Setting registry mapping %s\n", debugstr_a(buffer
));
1065 if (pSDL_GameControllerAddMapping(buffer
) < 0)
1066 WARN("Failed to add registry mapping %s\n", pSDL_GetError());
1069 } while (rc
== STATUS_SUCCESS
);
1070 HeapFree(GetProcessHeap(), 0, buffer
);
1075 SetEvent(init_done
);
1078 while (pSDL_WaitEvent(&event
) != 0) {
1079 if (event
.type
== quit_event
) {
1080 TRACE("Device thread exiting\n");
1083 process_device_event(&event
);
1088 void sdl_driver_unload( void )
1092 TRACE("Unload Driver\n");
1094 if (!deviceloop_handle
)
1097 quit_event
= pSDL_RegisterEvents(1);
1098 if (quit_event
== -1) {
1099 ERR("error registering quit event\n");
1103 event
.type
= quit_event
;
1104 if (pSDL_PushEvent(&event
) != 1) {
1105 ERR("error pushing quit event\n");
1109 WaitForSingleObject(deviceloop_handle
, INFINITE
);
1110 CloseHandle(deviceloop_handle
);
1111 dlclose(sdl_handle
);
1114 NTSTATUS
sdl_driver_init(void)
1116 static const WCHAR controller_modeW
[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0};
1117 static const UNICODE_STRING controller_mode
= {sizeof(controller_modeW
) - sizeof(WCHAR
), sizeof(controller_modeW
), (WCHAR
*)controller_modeW
};
1122 if (sdl_handle
== NULL
)
1124 sdl_handle
= dlopen(SONAME_LIBSDL2
, RTLD_NOW
);
1126 WARN("could not load %s\n", SONAME_LIBSDL2
);
1127 return STATUS_UNSUCCESSFUL
;
1129 #define LOAD_FUNCPTR(f) if((p##f = dlsym(sdl_handle, #f)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
1130 LOAD_FUNCPTR(SDL_GetError
);
1131 LOAD_FUNCPTR(SDL_Init
);
1132 LOAD_FUNCPTR(SDL_JoystickClose
);
1133 LOAD_FUNCPTR(SDL_JoystickEventState
);
1134 LOAD_FUNCPTR(SDL_JoystickGetGUID
);
1135 LOAD_FUNCPTR(SDL_JoystickGetGUIDString
);
1136 LOAD_FUNCPTR(SDL_JoystickInstanceID
);
1137 LOAD_FUNCPTR(SDL_JoystickName
);
1138 LOAD_FUNCPTR(SDL_JoystickNumAxes
);
1139 LOAD_FUNCPTR(SDL_JoystickOpen
);
1140 LOAD_FUNCPTR(SDL_WaitEvent
);
1141 LOAD_FUNCPTR(SDL_JoystickNumButtons
);
1142 LOAD_FUNCPTR(SDL_JoystickNumBalls
);
1143 LOAD_FUNCPTR(SDL_JoystickNumHats
);
1144 LOAD_FUNCPTR(SDL_JoystickGetAxis
);
1145 LOAD_FUNCPTR(SDL_JoystickGetHat
);
1146 LOAD_FUNCPTR(SDL_IsGameController
);
1147 LOAD_FUNCPTR(SDL_GameControllerClose
);
1148 LOAD_FUNCPTR(SDL_GameControllerGetAxis
);
1149 LOAD_FUNCPTR(SDL_GameControllerGetButton
);
1150 LOAD_FUNCPTR(SDL_GameControllerName
);
1151 LOAD_FUNCPTR(SDL_GameControllerOpen
);
1152 LOAD_FUNCPTR(SDL_GameControllerEventState
);
1153 LOAD_FUNCPTR(SDL_HapticClose
);
1154 LOAD_FUNCPTR(SDL_HapticDestroyEffect
);
1155 LOAD_FUNCPTR(SDL_HapticNewEffect
);
1156 LOAD_FUNCPTR(SDL_HapticOpenFromJoystick
);
1157 LOAD_FUNCPTR(SDL_HapticQuery
);
1158 LOAD_FUNCPTR(SDL_HapticRumbleInit
);
1159 LOAD_FUNCPTR(SDL_HapticRumblePlay
);
1160 LOAD_FUNCPTR(SDL_HapticRumbleSupported
);
1161 LOAD_FUNCPTR(SDL_HapticRunEffect
);
1162 LOAD_FUNCPTR(SDL_HapticStopAll
);
1163 LOAD_FUNCPTR(SDL_JoystickIsHaptic
);
1164 LOAD_FUNCPTR(SDL_memset
);
1165 LOAD_FUNCPTR(SDL_GameControllerAddMapping
);
1166 LOAD_FUNCPTR(SDL_RegisterEvents
);
1167 LOAD_FUNCPTR(SDL_PushEvent
);
1169 pSDL_JoystickGetProduct
= dlsym(sdl_handle
, "SDL_JoystickGetProduct");
1170 pSDL_JoystickGetProductVersion
= dlsym(sdl_handle
, "SDL_JoystickGetProductVersion");
1171 pSDL_JoystickGetVendor
= dlsym(sdl_handle
, "SDL_JoystickGetVendor");
1174 map_controllers
= check_bus_option(&controller_mode
, 1);
1176 if (!(events
[0] = CreateEventW(NULL
, TRUE
, FALSE
, NULL
)))
1178 WARN("CreateEvent failed\n");
1179 return STATUS_UNSUCCESSFUL
;
1181 if (!(events
[1] = CreateThread(NULL
, 0, deviceloop_thread
, events
[0], 0, NULL
)))
1183 WARN("CreateThread failed\n");
1184 CloseHandle(events
[0]);
1185 return STATUS_UNSUCCESSFUL
;
1188 result
= WaitForMultipleObjects(2, events
, FALSE
, INFINITE
);
1189 CloseHandle(events
[0]);
1190 if (result
== WAIT_OBJECT_0
)
1192 TRACE("Initialization successful\n");
1193 deviceloop_handle
= events
[1];
1194 return STATUS_SUCCESS
;
1196 CloseHandle(events
[1]);
1199 dlclose(sdl_handle
);
1201 return STATUS_UNSUCCESSFUL
;
1206 NTSTATUS
sdl_driver_init(void)
1208 return STATUS_NOT_IMPLEMENTED
;
1211 void sdl_driver_unload( void )
1213 TRACE("Stub: Unload Driver\n");
1216 #endif /* SONAME_LIBSDL2 */