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"
35 #define WIN32_NO_STATUS
42 #include "ddk/hidtypes.h"
43 #include "wine/debug.h"
44 #include "wine/unicode.h"
46 #include "controller.h"
48 #ifdef WORDS_BIGENDIAN
49 # define LE_WORD(x) RtlUshortByteSwap(x)
51 # define LE_WORD(x) (x)
56 WINE_DEFAULT_DEBUG_CHANNEL(plugplay
);
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
;
122 int hat_bit_offs
; /* hatswitches are reported in the same bytes as buttons */
124 int report_descriptor_size
;
125 BYTE
*report_descriptor
;
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),
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
),
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
),
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),
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),
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
),
203 REPORT_COUNT(1, 0x02),
204 REPORT_SIZE(1, 0x08),
205 OUTPUT(1, Data
|Var
|Abs
),
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
),
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
)
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
);
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
);
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
);
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
;
257 ext
->report_buffer
[byte_index
] = ext
->report_buffer
[byte_index
] | 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
);
273 report
[index
] = LE_WORD(value
) + 32768;
276 static void set_ball_value(struct platform_private
*ext
, int index
, int value1
, int value2
)
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 */
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;
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;
328 ext
->report_buffer
[byte
] &= ~(low_mask
<< bit_offs
);
329 ext
->report_buffer
[byte
] |= (val
& low_mask
) << bit_offs
;
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
)
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;
354 pSDL_HapticClose(ext
->sdl_haptic
);
355 ext
->sdl_haptic
= NULL
;
361 static int build_haptic(struct platform_private
*ext
, BYTE
*report_ptr
)
365 memcpy(report_ptr
, HAPTIC_RUMBLE
, sizeof(HAPTIC_RUMBLE
));
366 return (sizeof(HAPTIC_RUMBLE
));
371 static BOOL
build_report_descriptor(struct platform_private
*ext
)
374 INT i
, descript_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
[] = {
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
[] = {
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
);
402 axis_count
= pSDL_JoystickNumAxes(ext
->sdl_joystick
);
405 FIXME("Clamping joystick to 6 axis\n");
409 ext
->axis_start
= report_size
;
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
;
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
;
438 descript_size
+= sizeof(REPORT_BUTTONS
);
441 hat_count
= pSDL_JoystickNumHats(ext
->sdl_joystick
);
442 ext
->hat_bit_offs
= button_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");
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
);
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
);
472 report_ptr
= add_axis_block(report_ptr
, axis_count
, HID_USAGE_PAGE_GENERIC
, joystick_usages
, TRUE
);
477 report_ptr
= add_axis_block(report_ptr
, ball_count
* 2, HID_USAGE_PAGE_GENERIC
, &joystick_usages
[axis_count
], FALSE
);
481 report_ptr
= add_button_block(report_ptr
, 1, button_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
);
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
));
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
;
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
;
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
))
532 return SDL_HAT_CENTERED
;
535 static BOOL
build_mapped_report_descriptor(struct platform_private
*ext
)
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
);
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");
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
);
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;
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
);
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
);
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
;
649 case HID_STRING_ID_IPRODUCT
:
650 if (ext
->sdl_controller
)
651 str
= pSDL_GameControllerName(ext
->sdl_controller
);
653 str
= pSDL_JoystickName(ext
->sdl_joystick
);
655 case HID_STRING_ID_IMANUFACTURER
:
658 case HID_STRING_ID_ISERIALNUMBER
:
662 ERR("Unhandled string index %i\n", index
);
666 MultiByteToWideChar(CP_ACP
, 0, str
, -1, buffer
, length
);
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);
710 float i
= (float)((left
+ right
)/2.0) / 32767.0;
711 pSDL_HapticRumblePlay(ext
->sdl_haptic
, i
, -1);
715 return STATUS_SUCCESS
;
720 return STATUS_NOT_IMPLEMENTED
;
724 static NTSTATUS
get_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*read
)
727 return STATUS_NOT_IMPLEMENTED
;
730 static NTSTATUS
set_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
733 return STATUS_NOT_IMPLEMENTED
;
736 static const platform_vtbl sdl_vtbl
=
739 compare_platform_device
,
740 get_reportdescriptor
,
742 begin_report_processing
,
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
));
762 ERR("Failed to find device at index %i\n",id
);
765 private = impl_from_DEVICE_OBJECT(device
);
766 if (private->sdl_controller
)
768 /* We want mapped events */
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
);
784 case SDL_JOYAXISMOTION
:
786 SDL_JoyAxisEvent
*ie
= &event
->jaxis
;
790 set_axis_value(private, ie
->axis
, ie
->value
, FALSE
);
791 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
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
);
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
);
812 ERR("TODO: Process Report (0x%x)\n",event
->type
);
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
));
826 ERR("Failed to find device at index %i\n",id
);
829 private = impl_from_DEVICE_OBJECT(device
);
833 case SDL_CONTROLLERBUTTONDOWN
:
834 case SDL_CONTROLLERBUTTONUP
:
837 SDL_ControllerButtonEvent
*ie
= &event
->cbutton
;
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
);
862 ERR("Unknown Button %i\n",ie
->button
);
867 set_button_value(private, usage
, ie
->state
);
868 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
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
);
881 ERR("TODO: Process Report (%x)\n",event
->type
);
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
));
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};
903 BOOL is_xbox_gamepad
;
906 SDL_Joystick
* joystick
;
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());
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
);
930 pid
= pSDL_JoystickInstanceID(joystick
) + 1;
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
));
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
;
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);
958 device
= bus_create_hid_device(sdl_busidW
, vid
, pid
, input
, version
, index
,
959 serial
, is_xbox_gamepad
, &sdl_vtbl
, sizeof(struct platform_private
));
964 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
965 private->sdl_joystick
= joystick
;
966 private->sdl_controller
= controller
;
969 /* FIXME: We should probably move this to IRP_MN_START_DEVICE. */
971 rc
= build_mapped_report_descriptor(private);
973 rc
= build_report_descriptor(private);
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
);
982 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
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
;
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
)
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
))
1034 CHAR
*buffer
= NULL
;
1035 DWORD buffer_len
= 0;
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
)
1049 buffer
= HeapReAlloc(GetProcessHeap(), 0, buffer
, data_len
);
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());
1065 } while (rc
== STATUS_SUCCESS
);
1066 HeapFree(GetProcessHeap(), 0, buffer
);
1071 SetEvent(init_done
);
1074 while (pSDL_WaitEvent(&event
) != 0) {
1075 if (event
.type
== quit_event
) {
1076 TRACE("Device thread exiting\n");
1079 process_device_event(&event
);
1084 void sdl_driver_unload( void )
1088 TRACE("Unload Driver\n");
1090 if (!deviceloop_handle
)
1093 quit_event
= pSDL_RegisterEvents(1);
1094 if (quit_event
== -1) {
1095 ERR("error registering quit event\n");
1099 event
.type
= quit_event
;
1100 if (pSDL_PushEvent(&event
) != 1) {
1101 ERR("error pushing quit event\n");
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
};
1118 if (sdl_handle
== NULL
)
1120 sdl_handle
= dlopen(SONAME_LIBSDL2
, RTLD_NOW
);
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
);
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]);
1195 dlclose(sdl_handle
);
1197 return STATUS_UNSUCCESSFUL
;
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 */