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"
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;
72 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
73 MAKE_FUNCPTR(SDL_GetError
);
74 MAKE_FUNCPTR(SDL_Init
);
75 MAKE_FUNCPTR(SDL_JoystickClose
);
76 MAKE_FUNCPTR(SDL_JoystickEventState
);
77 MAKE_FUNCPTR(SDL_JoystickGetGUID
);
78 MAKE_FUNCPTR(SDL_JoystickGetGUIDString
);
79 MAKE_FUNCPTR(SDL_JoystickInstanceID
);
80 MAKE_FUNCPTR(SDL_JoystickName
);
81 MAKE_FUNCPTR(SDL_JoystickNumAxes
);
82 MAKE_FUNCPTR(SDL_JoystickOpen
);
83 MAKE_FUNCPTR(SDL_WaitEvent
);
84 MAKE_FUNCPTR(SDL_JoystickNumButtons
);
85 MAKE_FUNCPTR(SDL_JoystickNumBalls
);
86 MAKE_FUNCPTR(SDL_JoystickNumHats
);
87 MAKE_FUNCPTR(SDL_JoystickGetAxis
);
88 MAKE_FUNCPTR(SDL_JoystickGetHat
);
89 MAKE_FUNCPTR(SDL_IsGameController
);
90 MAKE_FUNCPTR(SDL_GameControllerClose
);
91 MAKE_FUNCPTR(SDL_GameControllerGetAxis
);
92 MAKE_FUNCPTR(SDL_GameControllerGetButton
);
93 MAKE_FUNCPTR(SDL_GameControllerName
);
94 MAKE_FUNCPTR(SDL_GameControllerOpen
);
95 MAKE_FUNCPTR(SDL_GameControllerEventState
);
96 MAKE_FUNCPTR(SDL_HapticClose
);
97 MAKE_FUNCPTR(SDL_HapticDestroyEffect
);
98 MAKE_FUNCPTR(SDL_HapticNewEffect
);
99 MAKE_FUNCPTR(SDL_HapticOpenFromJoystick
);
100 MAKE_FUNCPTR(SDL_HapticQuery
);
101 MAKE_FUNCPTR(SDL_HapticRumbleInit
);
102 MAKE_FUNCPTR(SDL_HapticRumblePlay
);
103 MAKE_FUNCPTR(SDL_HapticRumbleSupported
);
104 MAKE_FUNCPTR(SDL_HapticRunEffect
);
105 MAKE_FUNCPTR(SDL_HapticStopAll
);
106 MAKE_FUNCPTR(SDL_JoystickIsHaptic
);
107 MAKE_FUNCPTR(SDL_memset
);
108 MAKE_FUNCPTR(SDL_GameControllerAddMapping
);
109 MAKE_FUNCPTR(SDL_RegisterEvents
);
110 MAKE_FUNCPTR(SDL_PushEvent
);
111 static Uint16 (*pSDL_JoystickGetProduct
)(SDL_Joystick
* joystick
);
112 static Uint16 (*pSDL_JoystickGetProductVersion
)(SDL_Joystick
* joystick
);
113 static Uint16 (*pSDL_JoystickGetVendor
)(SDL_Joystick
* joystick
);
115 struct platform_private
117 SDL_Joystick
*sdl_joystick
;
118 SDL_GameController
*sdl_controller
;
124 int hat_bit_offs
; /* hatswitches are reported in the same bytes as buttons */
126 int report_descriptor_size
;
127 BYTE
*report_descriptor
;
132 SDL_Haptic
*sdl_haptic
;
133 int haptic_effect_id
;
136 static inline struct platform_private
*impl_from_DEVICE_OBJECT(DEVICE_OBJECT
*device
)
138 return (struct platform_private
*)get_platform_private(device
);
141 static const BYTE REPORT_AXIS_TAIL
[] = {
142 0x17, 0x00, 0x00, 0x00, 0x00, /* LOGICAL_MINIMUM (0) */
143 0x27, 0xff, 0xff, 0x00, 0x00, /* LOGICAL_MAXIMUM (65535) */
144 0x37, 0x00, 0x00, 0x00, 0x00, /* PHYSICAL_MINIMUM (0) */
145 0x47, 0xff, 0xff, 0x00, 0x00, /* PHYSICAL_MAXIMUM (65535) */
146 0x75, 0x10, /* REPORT_SIZE (16) */
147 0x95, 0x00, /* REPORT_COUNT (?) */
148 0x81, 0x02, /* INPUT (Data,Var,Abs) */
150 #define IDX_ABS_AXIS_COUNT 23
152 #define CONTROLLER_NUM_BUTTONS 11
154 static const BYTE CONTROLLER_BUTTONS
[] = {
155 0x05, 0x09, /* USAGE_PAGE (Button) */
156 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */
157 0x29, CONTROLLER_NUM_BUTTONS
, /* USAGE_MAXIMUM (Button 11) */
158 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
159 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
160 0x35, 0x00, /* LOGICAL_MINIMUM (0) */
161 0x45, 0x01, /* LOGICAL_MAXIMUM (1) */
162 0x95, CONTROLLER_NUM_BUTTONS
, /* REPORT_COUNT (11) */
163 0x75, 0x01, /* REPORT_SIZE (1) */
164 0x81, 0x02, /* INPUT (Data,Var,Abs) */
167 static const BYTE CONTROLLER_AXIS
[] = {
168 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
169 0x09, 0x30, /* USAGE (X) */
170 0x09, 0x31, /* USAGE (Y) */
171 0x09, 0x33, /* USAGE (RX) */
172 0x09, 0x34, /* USAGE (RY) */
173 0x17, 0x00, 0x00, 0x00, 0x00, /* LOGICAL_MINIMUM (0) */
174 0x27, 0xff, 0xff, 0x00, 0x00, /* LOGICAL_MAXIMUM (65535) */
175 0x37, 0x00, 0x00, 0x00, 0x00, /* PHYSICAL_MINIMUM (0) */
176 0x47, 0xff, 0xff, 0x00, 0x00, /* PHYSICAL_MAXIMUM (65535) */
177 0x75, 0x10, /* REPORT_SIZE (16) */
178 0x95, 0x04, /* REPORT_COUNT (4) */
179 0x81, 0x02, /* INPUT (Data,Var,Abs) */
182 static const BYTE CONTROLLER_TRIGGERS
[] = {
183 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
184 0x09, 0x32, /* USAGE (Z) */
185 0x09, 0x35, /* USAGE (RZ) */
186 0x16, 0x00, 0x00, /* LOGICAL_MINIMUM (0) */
187 0x26, 0xff, 0x7f, /* LOGICAL_MAXIMUM (32767) */
188 0x36, 0x00, 0x00, /* PHYSICAL_MINIMUM (0) */
189 0x46, 0xff, 0x7f, /* PHYSICAL_MAXIMUM (32767) */
190 0x75, 0x10, /* REPORT_SIZE (16) */
191 0x95, 0x02, /* REPORT_COUNT (2) */
192 0x81, 0x02, /* INPUT (Data,Var,Abs) */
195 #define CONTROLLER_NUM_AXES 6
197 #define CONTROLLER_NUM_HATSWITCHES 1
199 static const BYTE HAPTIC_RUMBLE
[] = {
200 0x06, 0x00, 0xff, /* USAGE PAGE (vendor-defined) */
201 0x09, 0x01, /* USAGE (1) */
203 0x95, 0x02, /* REPORT_COUNT (2) */
204 0x75, 0x08, /* REPORT_SIZE (8) */
205 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
207 0x15, 0x00, /* LOGICAL MINIMUM (0) */
208 0x25, 0xff, /* LOGICAL MAXIMUM (255) */
209 0x35, 0x00, /* PHYSICAL MINIMUM (0) */
210 0x45, 0xff, /* PHYSICAL MAXIMUM (255) */
211 0x75, 0x08, /* REPORT_SIZE (8) */
212 0x95, 0x02, /* REPORT_COUNT (2) */
213 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
215 0x95, 0x02, /* REPORT_COUNT (3) */
216 0x75, 0x08, /* REPORT_SIZE (8) */
217 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
220 static BYTE
*add_axis_block(BYTE
*report_ptr
, BYTE count
, BYTE page
, const BYTE
*usages
, BOOL absolute
)
223 memcpy(report_ptr
, REPORT_AXIS_HEADER
, sizeof(REPORT_AXIS_HEADER
));
224 report_ptr
[IDX_AXIS_PAGE
] = page
;
225 report_ptr
+= sizeof(REPORT_AXIS_HEADER
);
226 for (i
= 0; i
< count
; i
++)
228 memcpy(report_ptr
, REPORT_AXIS_USAGE
, sizeof(REPORT_AXIS_USAGE
));
229 report_ptr
[IDX_AXIS_USAGE
] = usages
[i
];
230 report_ptr
+= sizeof(REPORT_AXIS_USAGE
);
234 memcpy(report_ptr
, REPORT_AXIS_TAIL
, sizeof(REPORT_AXIS_TAIL
));
235 report_ptr
[IDX_ABS_AXIS_COUNT
] = count
;
236 report_ptr
+= sizeof(REPORT_AXIS_TAIL
);
240 memcpy(report_ptr
, REPORT_REL_AXIS_TAIL
, sizeof(REPORT_REL_AXIS_TAIL
));
241 report_ptr
[IDX_REL_AXIS_COUNT
] = count
;
242 report_ptr
+= sizeof(REPORT_REL_AXIS_TAIL
);
247 static void set_button_value(struct platform_private
*ext
, int index
, int value
)
249 int byte_index
= ext
->button_start
+ index
/ 8;
250 int bit_index
= index
% 8;
251 BYTE mask
= 1 << bit_index
;
255 ext
->report_buffer
[byte_index
] = ext
->report_buffer
[byte_index
] | mask
;
260 ext
->report_buffer
[byte_index
] = ext
->report_buffer
[byte_index
] & mask
;
264 static void set_axis_value(struct platform_private
*ext
, int index
, short value
, BOOL controller
)
266 WORD
*report
= (WORD
*)(ext
->report_buffer
+ ext
->axis_start
);
268 if (controller
&& (index
== SDL_CONTROLLER_AXIS_TRIGGERLEFT
|| index
== SDL_CONTROLLER_AXIS_TRIGGERRIGHT
))
269 report
[index
] = LE_WORD(value
);
271 report
[index
] = LE_WORD(value
) + 32768;
274 static void set_ball_value(struct platform_private
*ext
, int index
, int value1
, int value2
)
277 offset
= ext
->ball_start
+ (index
* sizeof(WORD
));
278 if (value1
> 127) value1
= 127;
279 if (value1
< -127) value1
= -127;
280 if (value2
> 127) value2
= 127;
281 if (value2
< -127) value2
= -127;
282 *((WORD
*)&ext
->report_buffer
[offset
]) = LE_WORD(value1
);
283 *((WORD
*)&ext
->report_buffer
[offset
+ sizeof(WORD
)]) = LE_WORD(value2
);
286 static void set_hat_value(struct platform_private
*ext
, int index
, int value
)
288 int byte
= ext
->button_start
+ (ext
->hat_bit_offs
+ 4 * index
) / 8;
289 int bit_offs
= (ext
->hat_bit_offs
+ 4 * index
) % 8;
290 int num_low_bits
, num_high_bits
;
291 unsigned char val
, low_mask
, high_mask
;
293 /* 4-bit hatswitch value is packed into button bytes */
303 num_low_bits
= 8 - bit_offs
;
304 num_high_bits
= 4 - num_low_bits
;
305 low_mask
= (1 << num_low_bits
) - 1;
306 high_mask
= (1 << num_high_bits
) - 1;
314 case SDL_HAT_CENTERED
: val
= 0; break;
315 case SDL_HAT_UP
: val
= 1; break;
316 case SDL_HAT_RIGHTUP
: val
= 2; break;
317 case SDL_HAT_RIGHT
: val
= 3; break;
318 case SDL_HAT_RIGHTDOWN
: val
= 4; break;
319 case SDL_HAT_DOWN
: val
= 5; break;
320 case SDL_HAT_LEFTDOWN
: val
= 6; break;
321 case SDL_HAT_LEFT
: val
= 7; break;
322 case SDL_HAT_LEFTUP
: val
= 8; break;
326 ext
->report_buffer
[byte
] &= ~(low_mask
<< bit_offs
);
327 ext
->report_buffer
[byte
] |= (val
& low_mask
) << bit_offs
;
330 ext
->report_buffer
[byte
+ 1] &= ~high_mask
;
331 ext
->report_buffer
[byte
+ 1] |= val
& high_mask
;
335 static int test_haptic(struct platform_private
*ext
)
338 if (pSDL_JoystickIsHaptic(ext
->sdl_joystick
))
340 ext
->sdl_haptic
= pSDL_HapticOpenFromJoystick(ext
->sdl_joystick
);
341 if (ext
->sdl_haptic
&&
342 ((pSDL_HapticQuery(ext
->sdl_haptic
) & SDL_HAPTIC_LEFTRIGHT
) != 0 ||
343 pSDL_HapticRumbleSupported(ext
->sdl_haptic
)))
345 pSDL_HapticStopAll(ext
->sdl_haptic
);
346 pSDL_HapticRumbleInit(ext
->sdl_haptic
);
347 rc
= sizeof(HAPTIC_RUMBLE
);
348 ext
->haptic_effect_id
= -1;
352 pSDL_HapticClose(ext
->sdl_haptic
);
353 ext
->sdl_haptic
= NULL
;
359 static int build_haptic(struct platform_private
*ext
, BYTE
*report_ptr
)
363 memcpy(report_ptr
, HAPTIC_RUMBLE
, sizeof(HAPTIC_RUMBLE
));
364 return (sizeof(HAPTIC_RUMBLE
));
369 static BOOL
build_report_descriptor(struct platform_private
*ext
)
372 INT i
, descript_size
;
374 INT button_count
, axis_count
, ball_count
, hat_count
;
375 static const BYTE device_usage
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_GAMEPAD
};
376 static const BYTE controller_usages
[] = {
380 HID_USAGE_GENERIC_RX
,
381 HID_USAGE_GENERIC_RY
,
382 HID_USAGE_GENERIC_RZ
,
383 HID_USAGE_GENERIC_SLIDER
,
384 HID_USAGE_GENERIC_DIAL
,
385 HID_USAGE_GENERIC_WHEEL
};
386 static const BYTE joystick_usages
[] = {
390 HID_USAGE_GENERIC_RZ
,
391 HID_USAGE_GENERIC_RX
,
392 HID_USAGE_GENERIC_RY
,
393 HID_USAGE_GENERIC_SLIDER
,
394 HID_USAGE_GENERIC_DIAL
,
395 HID_USAGE_GENERIC_WHEEL
};
397 descript_size
= sizeof(REPORT_HEADER
) + sizeof(REPORT_TAIL
);
400 axis_count
= pSDL_JoystickNumAxes(ext
->sdl_joystick
);
403 FIXME("Clamping joystick to 6 axis\n");
407 ext
->axis_start
= report_size
;
410 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
411 descript_size
+= (sizeof(REPORT_AXIS_USAGE
) * axis_count
);
412 descript_size
+= sizeof(REPORT_AXIS_TAIL
);
413 report_size
+= (sizeof(WORD
) * axis_count
);
416 ball_count
= pSDL_JoystickNumBalls(ext
->sdl_joystick
);
417 ext
->ball_start
= report_size
;
420 if ((ball_count
*2) + axis_count
> 9)
422 FIXME("Capping ball + axis at 9\n");
423 ball_count
= (9-axis_count
)/2;
425 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
426 descript_size
+= (sizeof(REPORT_AXIS_USAGE
) * ball_count
* 2);
427 descript_size
+= sizeof(REPORT_REL_AXIS_TAIL
);
428 report_size
+= (sizeof(WORD
) * 2 * ball_count
);
431 /* For now lump all buttons just into incremental usages, Ignore Keys */
432 button_count
= pSDL_JoystickNumButtons(ext
->sdl_joystick
);
433 ext
->button_start
= report_size
;
436 descript_size
+= sizeof(REPORT_BUTTONS
);
439 hat_count
= pSDL_JoystickNumHats(ext
->sdl_joystick
);
440 ext
->hat_bit_offs
= button_count
;
443 descript_size
+= sizeof(REPORT_HATSWITCH
);
446 report_size
+= (button_count
+ hat_count
* 4 + 7) / 8;
448 descript_size
+= test_haptic(ext
);
450 TRACE("Report Descriptor will be %i bytes\n", descript_size
);
451 TRACE("Report will be %i bytes\n", report_size
);
453 ext
->report_descriptor
= HeapAlloc(GetProcessHeap(), 0, descript_size
);
454 if (!ext
->report_descriptor
)
456 ERR("Failed to alloc report descriptor\n");
459 report_ptr
= ext
->report_descriptor
;
461 memcpy(report_ptr
, REPORT_HEADER
, sizeof(REPORT_HEADER
));
462 report_ptr
[IDX_HEADER_PAGE
] = device_usage
[0];
463 report_ptr
[IDX_HEADER_USAGE
] = device_usage
[1];
464 report_ptr
+= sizeof(REPORT_HEADER
);
467 if (axis_count
== 6 && button_count
>= 14)
468 report_ptr
= add_axis_block(report_ptr
, axis_count
, HID_USAGE_PAGE_GENERIC
, controller_usages
, TRUE
);
470 report_ptr
= add_axis_block(report_ptr
, axis_count
, HID_USAGE_PAGE_GENERIC
, joystick_usages
, TRUE
);
475 report_ptr
= add_axis_block(report_ptr
, ball_count
* 2, HID_USAGE_PAGE_GENERIC
, &joystick_usages
[axis_count
], FALSE
);
479 report_ptr
= add_button_block(report_ptr
, 1, button_count
);
482 report_ptr
= add_hatswitch(report_ptr
, hat_count
);
484 report_ptr
+= build_haptic(ext
, report_ptr
);
485 memcpy(report_ptr
, REPORT_TAIL
, sizeof(REPORT_TAIL
));
487 ext
->report_descriptor_size
= descript_size
;
488 ext
->buffer_length
= report_size
;
489 ext
->report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, report_size
);
490 if (ext
->report_buffer
== NULL
)
492 ERR("Failed to alloc report buffer\n");
493 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
497 /* Initialize axis in the report */
498 for (i
= 0; i
< axis_count
; i
++)
499 set_axis_value(ext
, i
, pSDL_JoystickGetAxis(ext
->sdl_joystick
, i
), FALSE
);
500 for (i
= 0; i
< hat_count
; i
++)
501 set_hat_value(ext
, i
, pSDL_JoystickGetHat(ext
->sdl_joystick
, i
));
506 static SHORT
compose_dpad_value(SDL_GameController
*joystick
)
508 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_UP
))
510 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_RIGHT
))
511 return SDL_HAT_RIGHTUP
;
512 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_LEFT
))
513 return SDL_HAT_LEFTUP
;
517 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_DOWN
))
519 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_RIGHT
))
520 return SDL_HAT_RIGHTDOWN
;
521 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_LEFT
))
522 return SDL_HAT_LEFTDOWN
;
526 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_RIGHT
))
527 return SDL_HAT_RIGHT
;
528 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_LEFT
))
530 return SDL_HAT_CENTERED
;
533 static BOOL
build_mapped_report_descriptor(struct platform_private
*ext
)
536 INT i
, descript_size
;
538 static const int BUTTON_BIT_COUNT
= CONTROLLER_NUM_BUTTONS
+ CONTROLLER_NUM_HATSWITCHES
* 4;
540 descript_size
= sizeof(REPORT_HEADER
) + sizeof(REPORT_TAIL
);
541 descript_size
+= sizeof(CONTROLLER_AXIS
);
542 descript_size
+= sizeof(CONTROLLER_TRIGGERS
);
543 descript_size
+= sizeof(CONTROLLER_BUTTONS
);
544 descript_size
+= sizeof(REPORT_HATSWITCH
);
545 descript_size
+= sizeof(REPORT_PADDING
);
546 if (BUTTON_BIT_COUNT
% 8 != 0)
547 descript_size
+= sizeof(REPORT_PADDING
);
548 descript_size
+= test_haptic(ext
);
551 ext
->button_start
= CONTROLLER_NUM_AXES
* sizeof(WORD
);
552 ext
->hat_bit_offs
= CONTROLLER_NUM_BUTTONS
;
554 ext
->buffer_length
= (BUTTON_BIT_COUNT
+ 7) / 8
555 + CONTROLLER_NUM_AXES
* sizeof(WORD
)
556 + 2/* unknown constant*/;
558 TRACE("Report Descriptor will be %i bytes\n", descript_size
);
559 TRACE("Report will be %i bytes\n", ext
->buffer_length
);
561 ext
->report_descriptor
= HeapAlloc(GetProcessHeap(), 0, descript_size
);
562 if (!ext
->report_descriptor
)
564 ERR("Failed to alloc report descriptor\n");
567 report_ptr
= ext
->report_descriptor
;
569 memcpy(report_ptr
, REPORT_HEADER
, sizeof(REPORT_HEADER
));
570 report_ptr
[IDX_HEADER_PAGE
] = HID_USAGE_PAGE_GENERIC
;
571 report_ptr
[IDX_HEADER_USAGE
] = HID_USAGE_GENERIC_GAMEPAD
;
572 report_ptr
+= sizeof(REPORT_HEADER
);
573 memcpy(report_ptr
, CONTROLLER_AXIS
, sizeof(CONTROLLER_AXIS
));
574 report_ptr
+= sizeof(CONTROLLER_AXIS
);
575 memcpy(report_ptr
, CONTROLLER_TRIGGERS
, sizeof(CONTROLLER_TRIGGERS
));
576 report_ptr
+= sizeof(CONTROLLER_TRIGGERS
);
577 memcpy(report_ptr
, CONTROLLER_BUTTONS
, sizeof(CONTROLLER_BUTTONS
));
578 report_ptr
+= sizeof(CONTROLLER_BUTTONS
);
579 report_ptr
= add_hatswitch(report_ptr
, 1);
580 if (BUTTON_BIT_COUNT
% 8 != 0)
581 report_ptr
= add_padding_block(report_ptr
, 8 - (BUTTON_BIT_COUNT
% 8));/* unused bits between hatswitch and following constant */
582 report_ptr
= add_padding_block(report_ptr
, 16);/* unknown constant */
583 report_ptr
+= build_haptic(ext
, report_ptr
);
584 memcpy(report_ptr
, REPORT_TAIL
, sizeof(REPORT_TAIL
));
586 ext
->report_descriptor_size
= descript_size
;
587 ext
->report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ext
->buffer_length
);
588 if (ext
->report_buffer
== NULL
)
590 ERR("Failed to alloc report buffer\n");
591 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
595 /* Initialize axis in the report */
596 for (i
= SDL_CONTROLLER_AXIS_LEFTX
; i
< SDL_CONTROLLER_AXIS_MAX
; i
++)
597 set_axis_value(ext
, i
, pSDL_GameControllerGetAxis(ext
->sdl_controller
, i
), TRUE
);
599 set_hat_value(ext
, 0, compose_dpad_value(ext
->sdl_controller
));
601 /* unknown constant */
602 ext
->report_buffer
[14] = 0x89;
603 ext
->report_buffer
[15] = 0xc5;
608 static int compare_platform_device(DEVICE_OBJECT
*device
, void *platform_dev
)
610 SDL_JoystickID id1
= impl_from_DEVICE_OBJECT(device
)->id
;
611 SDL_JoystickID id2
= PtrToUlong(platform_dev
);
615 static NTSTATUS
get_reportdescriptor(DEVICE_OBJECT
*device
, BYTE
*buffer
, DWORD length
, DWORD
*out_length
)
617 struct platform_private
*ext
= impl_from_DEVICE_OBJECT(device
);
619 *out_length
= ext
->report_descriptor_size
;
621 if (length
< ext
->report_descriptor_size
)
622 return STATUS_BUFFER_TOO_SMALL
;
624 memcpy(buffer
, ext
->report_descriptor
, ext
->report_descriptor_size
);
626 return STATUS_SUCCESS
;
629 static NTSTATUS
get_string(DEVICE_OBJECT
*device
, DWORD index
, WCHAR
*buffer
, DWORD length
)
631 struct platform_private
*ext
= impl_from_DEVICE_OBJECT(device
);
632 const char* str
= NULL
;
636 case HID_STRING_ID_IPRODUCT
:
637 if (ext
->sdl_controller
)
638 str
= pSDL_GameControllerName(ext
->sdl_controller
);
640 str
= pSDL_JoystickName(ext
->sdl_joystick
);
642 case HID_STRING_ID_IMANUFACTURER
:
645 case HID_STRING_ID_ISERIALNUMBER
:
649 ERR("Unhandled string index %i\n", index
);
653 MultiByteToWideChar(CP_ACP
, 0, str
, -1, buffer
, length
);
657 return STATUS_SUCCESS
;
660 static NTSTATUS
begin_report_processing(DEVICE_OBJECT
*device
)
662 return STATUS_SUCCESS
;
665 static NTSTATUS
set_output_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
667 struct platform_private
*ext
= impl_from_DEVICE_OBJECT(device
);
669 if (ext
->sdl_haptic
&& id
== 0)
671 WORD left
= report
[2] * 128;
672 WORD right
= report
[3] * 128;
674 if (ext
->haptic_effect_id
>= 0)
676 pSDL_HapticDestroyEffect(ext
->sdl_haptic
, ext
->haptic_effect_id
);
677 ext
->haptic_effect_id
= -1;
679 pSDL_HapticStopAll(ext
->sdl_haptic
);
680 if (left
!= 0 || right
!= 0)
682 SDL_HapticEffect effect
;
684 pSDL_memset( &effect
, 0, sizeof(SDL_HapticEffect
) );
685 effect
.type
= SDL_HAPTIC_LEFTRIGHT
;
686 effect
.leftright
.length
= -1;
687 effect
.leftright
.large_magnitude
= left
;
688 effect
.leftright
.small_magnitude
= right
;
690 ext
->haptic_effect_id
= pSDL_HapticNewEffect(ext
->sdl_haptic
, &effect
);
691 if (ext
->haptic_effect_id
>= 0)
693 pSDL_HapticRunEffect(ext
->sdl_haptic
, ext
->haptic_effect_id
, 1);
697 float i
= (float)((left
+ right
)/2.0) / 32767.0;
698 pSDL_HapticRumblePlay(ext
->sdl_haptic
, i
, -1);
702 return STATUS_SUCCESS
;
707 return STATUS_NOT_IMPLEMENTED
;
711 static NTSTATUS
get_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*read
)
714 return STATUS_NOT_IMPLEMENTED
;
717 static NTSTATUS
set_feature_report(DEVICE_OBJECT
*device
, UCHAR id
, BYTE
*report
, DWORD length
, ULONG_PTR
*written
)
720 return STATUS_NOT_IMPLEMENTED
;
723 static const platform_vtbl sdl_vtbl
=
725 compare_platform_device
,
726 get_reportdescriptor
,
728 begin_report_processing
,
734 static int compare_joystick_id(DEVICE_OBJECT
*device
, void* context
)
736 return impl_from_DEVICE_OBJECT(device
)->id
- PtrToUlong(context
);
739 static BOOL
set_report_from_event(SDL_Event
*event
)
741 DEVICE_OBJECT
*device
;
742 struct platform_private
*private;
743 /* All the events coming in will have 'which' as a 3rd field */
744 SDL_JoystickID id
= ((SDL_JoyButtonEvent
*)event
)->which
;
745 device
= bus_enumerate_hid_devices(&sdl_vtbl
, compare_joystick_id
, ULongToPtr(id
));
748 ERR("Failed to find device at index %i\n",id
);
751 private = impl_from_DEVICE_OBJECT(device
);
752 if (private->sdl_controller
)
754 /* We want mapped events */
760 case SDL_JOYBUTTONDOWN
:
761 case SDL_JOYBUTTONUP
:
763 SDL_JoyButtonEvent
*ie
= &event
->jbutton
;
765 set_button_value(private, ie
->button
, ie
->state
);
767 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
770 case SDL_JOYAXISMOTION
:
772 SDL_JoyAxisEvent
*ie
= &event
->jaxis
;
776 set_axis_value(private, ie
->axis
, ie
->value
, FALSE
);
777 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
781 case SDL_JOYBALLMOTION
:
783 SDL_JoyBallEvent
*ie
= &event
->jball
;
785 set_ball_value(private, ie
->ball
, ie
->xrel
, ie
->yrel
);
786 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
789 case SDL_JOYHATMOTION
:
791 SDL_JoyHatEvent
*ie
= &event
->jhat
;
793 set_hat_value(private, ie
->hat
, ie
->value
);
794 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
798 ERR("TODO: Process Report (0x%x)\n",event
->type
);
803 static BOOL
set_mapped_report_from_event(SDL_Event
*event
)
805 DEVICE_OBJECT
*device
;
806 struct platform_private
*private;
807 /* All the events coming in will have 'which' as a 3rd field */
808 SDL_JoystickID id
= ((SDL_ControllerButtonEvent
*)event
)->which
;
809 device
= bus_enumerate_hid_devices(&sdl_vtbl
, compare_joystick_id
, ULongToPtr(id
));
812 ERR("Failed to find device at index %i\n",id
);
815 private = impl_from_DEVICE_OBJECT(device
);
819 case SDL_CONTROLLERBUTTONDOWN
:
820 case SDL_CONTROLLERBUTTONUP
:
823 SDL_ControllerButtonEvent
*ie
= &event
->cbutton
;
827 case SDL_CONTROLLER_BUTTON_A
: usage
= 0; break;
828 case SDL_CONTROLLER_BUTTON_B
: usage
= 1; break;
829 case SDL_CONTROLLER_BUTTON_X
: usage
= 2; break;
830 case SDL_CONTROLLER_BUTTON_Y
: usage
= 3; break;
831 case SDL_CONTROLLER_BUTTON_LEFTSHOULDER
: usage
= 4; break;
832 case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
: usage
= 5; break;
833 case SDL_CONTROLLER_BUTTON_BACK
: usage
= 6; break;
834 case SDL_CONTROLLER_BUTTON_START
: usage
= 7; break;
835 case SDL_CONTROLLER_BUTTON_LEFTSTICK
: usage
= 8; break;
836 case SDL_CONTROLLER_BUTTON_RIGHTSTICK
: usage
= 9; break;
837 case SDL_CONTROLLER_BUTTON_GUIDE
: usage
= 10; break;
839 case SDL_CONTROLLER_BUTTON_DPAD_UP
:
840 case SDL_CONTROLLER_BUTTON_DPAD_DOWN
:
841 case SDL_CONTROLLER_BUTTON_DPAD_LEFT
:
842 case SDL_CONTROLLER_BUTTON_DPAD_RIGHT
:
843 set_hat_value(private, 0, compose_dpad_value(private->sdl_controller
));
844 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
848 ERR("Unknown Button %i\n",ie
->button
);
853 set_button_value(private, usage
, ie
->state
);
854 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
858 case SDL_CONTROLLERAXISMOTION
:
860 SDL_ControllerAxisEvent
*ie
= &event
->caxis
;
862 set_axis_value(private, ie
->axis
, ie
->value
, TRUE
);
863 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
867 ERR("TODO: Process Report (%x)\n",event
->type
);
872 static void try_remove_device(SDL_JoystickID id
)
874 DEVICE_OBJECT
*device
= NULL
;
875 struct platform_private
*private;
876 SDL_Joystick
*sdl_joystick
;
877 SDL_GameController
*sdl_controller
;
878 SDL_Haptic
*sdl_haptic
;
880 device
= bus_enumerate_hid_devices(&sdl_vtbl
, compare_joystick_id
, ULongToPtr(id
));
883 private = impl_from_DEVICE_OBJECT(device
);
884 sdl_joystick
= private->sdl_joystick
;
885 sdl_controller
= private->sdl_controller
;
886 sdl_haptic
= private->sdl_haptic
;
888 bus_unlink_hid_device(device
);
889 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
891 bus_remove_hid_device(device
);
893 pSDL_JoystickClose(sdl_joystick
);
895 pSDL_GameControllerClose(sdl_controller
);
897 pSDL_HapticClose(sdl_haptic
);
900 static void try_add_device(unsigned int index
)
902 DWORD vid
= 0, pid
= 0, version
= 0;
903 DEVICE_OBJECT
*device
= NULL
;
904 WCHAR serial
[34] = {0};
906 BOOL is_xbox_gamepad
;
909 SDL_Joystick
* joystick
;
911 SDL_JoystickGUID guid
;
912 SDL_GameController
*controller
= NULL
;
914 if ((joystick
= pSDL_JoystickOpen(index
)) == NULL
)
916 WARN("Unable to open sdl device %i: %s\n", index
, pSDL_GetError());
920 if (map_controllers
&& pSDL_IsGameController(index
))
921 controller
= pSDL_GameControllerOpen(index
);
923 id
= pSDL_JoystickInstanceID(joystick
);
925 if (pSDL_JoystickGetProductVersion
!= NULL
) {
926 vid
= pSDL_JoystickGetVendor(joystick
);
927 pid
= pSDL_JoystickGetProduct(joystick
);
928 version
= pSDL_JoystickGetProductVersion(joystick
);
933 pid
= pSDL_JoystickInstanceID(joystick
) + 1;
937 guid
= pSDL_JoystickGetGUID(joystick
);
938 pSDL_JoystickGetGUIDString(guid
, guid_str
, sizeof(guid_str
));
939 MultiByteToWideChar(CP_ACP
, 0, guid_str
, -1, serial
, sizeof(guid_str
));
943 TRACE("Found sdl game controller %i (vid %04x, pid %04x, version %u, serial %s)\n",
944 id
, vid
, pid
, version
, debugstr_w(serial
));
945 is_xbox_gamepad
= TRUE
;
949 int button_count
, axis_count
;
951 TRACE("Found sdl device %i (vid %04x, pid %04x, version %u, serial %s)\n",
952 id
, vid
, pid
, version
, debugstr_w(serial
));
954 axis_count
= pSDL_JoystickNumAxes(joystick
);
955 button_count
= pSDL_JoystickNumButtons(joystick
);
956 is_xbox_gamepad
= (axis_count
== 6 && button_count
>= 14);
961 device
= bus_create_hid_device(sdl_busidW
, vid
, pid
, input
, version
, index
,
962 serial
, is_xbox_gamepad
, &sdl_vtbl
, sizeof(struct platform_private
));
967 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
968 private->sdl_joystick
= joystick
;
969 private->sdl_controller
= controller
;
972 rc
= build_mapped_report_descriptor(private);
974 rc
= build_report_descriptor(private);
977 ERR("Building report descriptor failed, removing device\n");
978 bus_unlink_hid_device(device
);
979 bus_remove_hid_device(device
);
980 HeapFree(GetProcessHeap(), 0, serial
);
983 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
987 WARN("Ignoring device %i\n", id
);
991 static void process_device_event(SDL_Event
*event
)
993 TRACE_(hid_report
)("Received action %x\n", event
->type
);
995 if (event
->type
== SDL_JOYDEVICEADDED
)
996 try_add_device(((SDL_JoyDeviceEvent
*)event
)->which
);
997 else if (event
->type
== SDL_JOYDEVICEREMOVED
)
998 try_remove_device(((SDL_JoyDeviceEvent
*)event
)->which
);
999 else if (event
->type
>= SDL_JOYAXISMOTION
&& event
->type
<= SDL_JOYBUTTONUP
)
1000 set_report_from_event(event
);
1001 else if (event
->type
>= SDL_CONTROLLERAXISMOTION
&& event
->type
<= SDL_CONTROLLERBUTTONUP
)
1002 set_mapped_report_from_event(event
);
1005 static DWORD CALLBACK
deviceloop_thread(void *args
)
1007 HANDLE init_done
= args
;
1010 if (pSDL_Init(SDL_INIT_GAMECONTROLLER
|SDL_INIT_HAPTIC
) < 0)
1012 ERR("Can't init SDL: %s\n", pSDL_GetError());
1013 return STATUS_UNSUCCESSFUL
;
1016 pSDL_JoystickEventState(SDL_ENABLE
);
1017 pSDL_GameControllerEventState(SDL_ENABLE
);
1019 /* Process mappings */
1020 if (pSDL_GameControllerAddMapping
!= NULL
)
1023 static const WCHAR szPath
[] = {'m','a','p',0};
1024 const char *mapping
;
1026 if ((mapping
= getenv("SDL_GAMECONTROLLERCONFIG")))
1028 TRACE("Setting environment mapping %s\n", debugstr_a(mapping
));
1029 if (pSDL_GameControllerAddMapping(mapping
) < 0)
1030 WARN("Failed to add environment mapping %s\n", pSDL_GetError());
1032 else if (!RegOpenKeyExW(driver_key
, szPath
, 0, KEY_QUERY_VALUE
, &key
))
1035 CHAR
*buffer
= NULL
;
1036 DWORD buffer_len
= 0;
1043 DWORD data_len
= buffer_len
;
1045 name_len
= sizeof(name
);
1046 rc
= RegEnumValueA(key
, index
, name
, &name_len
, NULL
, &type
, (LPBYTE
)buffer
, &data_len
);
1047 if (rc
== ERROR_MORE_DATA
|| buffer
== NULL
)
1050 buffer
= HeapReAlloc(GetProcessHeap(), 0, buffer
, data_len
);
1052 buffer
= HeapAlloc(GetProcessHeap(), 0, data_len
);
1053 buffer_len
= data_len
;
1055 name_len
= sizeof(name
);
1056 rc
= RegEnumValueA(key
, index
, name
, &name_len
, NULL
, &type
, (LPBYTE
)buffer
, &data_len
);
1059 if (rc
== STATUS_SUCCESS
)
1061 TRACE("Setting registry mapping %s\n", debugstr_a(buffer
));
1062 if (pSDL_GameControllerAddMapping(buffer
) < 0)
1063 WARN("Failed to add registry mapping %s\n", pSDL_GetError());
1066 } while (rc
== STATUS_SUCCESS
);
1067 HeapFree(GetProcessHeap(), 0, buffer
);
1072 SetEvent(init_done
);
1075 while (pSDL_WaitEvent(&event
) != 0) {
1076 if (event
.type
== quit_event
) {
1077 TRACE("Device thread exiting\n");
1080 process_device_event(&event
);
1085 void sdl_driver_unload( void )
1089 TRACE("Unload Driver\n");
1091 if (!deviceloop_handle
)
1094 quit_event
= pSDL_RegisterEvents(1);
1095 if (quit_event
== -1) {
1096 ERR("error registering quit event\n");
1100 event
.type
= quit_event
;
1101 if (pSDL_PushEvent(&event
) != 1) {
1102 ERR("error pushing quit event\n");
1106 WaitForSingleObject(deviceloop_handle
, INFINITE
);
1107 CloseHandle(deviceloop_handle
);
1108 dlclose(sdl_handle
);
1111 NTSTATUS
sdl_driver_init(void)
1113 static const WCHAR controller_modeW
[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0};
1114 static const UNICODE_STRING controller_mode
= {sizeof(controller_modeW
) - sizeof(WCHAR
), sizeof(controller_modeW
), (WCHAR
*)controller_modeW
};
1119 if (sdl_handle
== NULL
)
1121 sdl_handle
= dlopen(SONAME_LIBSDL2
, RTLD_NOW
);
1123 WARN("could not load %s\n", SONAME_LIBSDL2
);
1124 return STATUS_UNSUCCESSFUL
;
1126 #define LOAD_FUNCPTR(f) if((p##f = dlsym(sdl_handle, #f)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
1127 LOAD_FUNCPTR(SDL_GetError
);
1128 LOAD_FUNCPTR(SDL_Init
);
1129 LOAD_FUNCPTR(SDL_JoystickClose
);
1130 LOAD_FUNCPTR(SDL_JoystickEventState
);
1131 LOAD_FUNCPTR(SDL_JoystickGetGUID
);
1132 LOAD_FUNCPTR(SDL_JoystickGetGUIDString
);
1133 LOAD_FUNCPTR(SDL_JoystickInstanceID
);
1134 LOAD_FUNCPTR(SDL_JoystickName
);
1135 LOAD_FUNCPTR(SDL_JoystickNumAxes
);
1136 LOAD_FUNCPTR(SDL_JoystickOpen
);
1137 LOAD_FUNCPTR(SDL_WaitEvent
);
1138 LOAD_FUNCPTR(SDL_JoystickNumButtons
);
1139 LOAD_FUNCPTR(SDL_JoystickNumBalls
);
1140 LOAD_FUNCPTR(SDL_JoystickNumHats
);
1141 LOAD_FUNCPTR(SDL_JoystickGetAxis
);
1142 LOAD_FUNCPTR(SDL_JoystickGetHat
);
1143 LOAD_FUNCPTR(SDL_IsGameController
);
1144 LOAD_FUNCPTR(SDL_GameControllerClose
);
1145 LOAD_FUNCPTR(SDL_GameControllerGetAxis
);
1146 LOAD_FUNCPTR(SDL_GameControllerGetButton
);
1147 LOAD_FUNCPTR(SDL_GameControllerName
);
1148 LOAD_FUNCPTR(SDL_GameControllerOpen
);
1149 LOAD_FUNCPTR(SDL_GameControllerEventState
);
1150 LOAD_FUNCPTR(SDL_HapticClose
);
1151 LOAD_FUNCPTR(SDL_HapticDestroyEffect
);
1152 LOAD_FUNCPTR(SDL_HapticNewEffect
);
1153 LOAD_FUNCPTR(SDL_HapticOpenFromJoystick
);
1154 LOAD_FUNCPTR(SDL_HapticQuery
);
1155 LOAD_FUNCPTR(SDL_HapticRumbleInit
);
1156 LOAD_FUNCPTR(SDL_HapticRumblePlay
);
1157 LOAD_FUNCPTR(SDL_HapticRumbleSupported
);
1158 LOAD_FUNCPTR(SDL_HapticRunEffect
);
1159 LOAD_FUNCPTR(SDL_HapticStopAll
);
1160 LOAD_FUNCPTR(SDL_JoystickIsHaptic
);
1161 LOAD_FUNCPTR(SDL_memset
);
1162 LOAD_FUNCPTR(SDL_GameControllerAddMapping
);
1163 LOAD_FUNCPTR(SDL_RegisterEvents
);
1164 LOAD_FUNCPTR(SDL_PushEvent
);
1166 pSDL_JoystickGetProduct
= dlsym(sdl_handle
, "SDL_JoystickGetProduct");
1167 pSDL_JoystickGetProductVersion
= dlsym(sdl_handle
, "SDL_JoystickGetProductVersion");
1168 pSDL_JoystickGetVendor
= dlsym(sdl_handle
, "SDL_JoystickGetVendor");
1171 map_controllers
= check_bus_option(&controller_mode
, 1);
1173 if (!(events
[0] = CreateEventW(NULL
, TRUE
, FALSE
, NULL
)))
1175 WARN("CreateEvent failed\n");
1176 return STATUS_UNSUCCESSFUL
;
1178 if (!(events
[1] = CreateThread(NULL
, 0, deviceloop_thread
, events
[0], 0, NULL
)))
1180 WARN("CreateThread failed\n");
1181 CloseHandle(events
[0]);
1182 return STATUS_UNSUCCESSFUL
;
1185 result
= WaitForMultipleObjects(2, events
, FALSE
, INFINITE
);
1186 CloseHandle(events
[0]);
1187 if (result
== WAIT_OBJECT_0
)
1189 TRACE("Initialization successful\n");
1190 deviceloop_handle
= events
[1];
1191 return STATUS_SUCCESS
;
1193 CloseHandle(events
[1]);
1196 dlclose(sdl_handle
);
1198 return STATUS_UNSUCCESSFUL
;
1203 NTSTATUS
sdl_driver_init(void)
1205 return STATUS_NOT_IMPLEMENTED
;
1208 void sdl_driver_unload( void )
1210 TRACE("Stub: Unload Driver\n");
1213 #endif /* SONAME_LIBSDL2 */