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/library.h"
46 #include "wine/debug.h"
47 #include "wine/unicode.h"
49 #include "controller.h"
51 #ifdef WORDS_BIGENDIAN
52 # define LE_WORD(x) RtlUshortByteSwap(x)
54 # define LE_WORD(x) (x)
59 WINE_DEFAULT_DEBUG_CHANNEL(plugplay
);
63 WINE_DECLARE_DEBUG_CHANNEL(hid_report
);
65 static DRIVER_OBJECT
*sdl_driver_obj
= NULL
;
67 static const WCHAR sdl_busidW
[] = {'S','D','L','J','O','Y',0};
69 static DWORD map_controllers
= 0;
72 DEFINE_GUID(GUID_DEVCLASS_SDL
, 0x463d60b5,0x802b,0x4bb2,0x8f,0xdb,0x7d,0xa9,0xb9,0x96,0x04,0xd8);
74 static void *sdl_handle
= NULL
;
77 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
78 MAKE_FUNCPTR(SDL_GetError
);
79 MAKE_FUNCPTR(SDL_Init
);
80 MAKE_FUNCPTR(SDL_JoystickEventState
);
81 MAKE_FUNCPTR(SDL_JoystickGetGUID
);
82 MAKE_FUNCPTR(SDL_JoystickGetGUIDString
);
83 MAKE_FUNCPTR(SDL_JoystickInstanceID
);
84 MAKE_FUNCPTR(SDL_JoystickName
);
85 MAKE_FUNCPTR(SDL_JoystickNumAxes
);
86 MAKE_FUNCPTR(SDL_JoystickOpen
);
87 MAKE_FUNCPTR(SDL_WaitEvent
);
88 MAKE_FUNCPTR(SDL_JoystickNumButtons
);
89 MAKE_FUNCPTR(SDL_JoystickNumBalls
);
90 MAKE_FUNCPTR(SDL_JoystickNumHats
);
91 MAKE_FUNCPTR(SDL_JoystickGetAxis
);
92 MAKE_FUNCPTR(SDL_JoystickGetHat
);
93 MAKE_FUNCPTR(SDL_IsGameController
);
94 MAKE_FUNCPTR(SDL_GameControllerGetAxis
);
95 MAKE_FUNCPTR(SDL_GameControllerGetButton
);
96 MAKE_FUNCPTR(SDL_GameControllerName
);
97 MAKE_FUNCPTR(SDL_GameControllerOpen
);
98 MAKE_FUNCPTR(SDL_GameControllerEventState
);
99 MAKE_FUNCPTR(SDL_HapticClose
);
100 MAKE_FUNCPTR(SDL_HapticDestroyEffect
);
101 MAKE_FUNCPTR(SDL_HapticNewEffect
);
102 MAKE_FUNCPTR(SDL_HapticOpenFromJoystick
);
103 MAKE_FUNCPTR(SDL_HapticQuery
);
104 MAKE_FUNCPTR(SDL_HapticRumbleInit
);
105 MAKE_FUNCPTR(SDL_HapticRumblePlay
);
106 MAKE_FUNCPTR(SDL_HapticRumbleSupported
);
107 MAKE_FUNCPTR(SDL_HapticRunEffect
);
108 MAKE_FUNCPTR(SDL_HapticStopAll
);
109 MAKE_FUNCPTR(SDL_JoystickIsHaptic
);
110 MAKE_FUNCPTR(SDL_memset
);
111 MAKE_FUNCPTR(SDL_GameControllerAddMapping
);
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
)
270 offset
= ext
->axis_start
+ index
* sizeof(WORD
);
274 case SDL_CONTROLLER_AXIS_LEFTX
:
275 case SDL_CONTROLLER_AXIS_LEFTY
:
276 case SDL_CONTROLLER_AXIS_RIGHTX
:
277 case SDL_CONTROLLER_AXIS_RIGHTY
:
278 *((WORD
*)&ext
->report_buffer
[offset
]) = LE_WORD(value
) + 32768;
280 case SDL_CONTROLLER_AXIS_TRIGGERLEFT
:
281 case SDL_CONTROLLER_AXIS_TRIGGERRIGHT
:
282 *((WORD
*)&ext
->report_buffer
[offset
]) = LE_WORD(value
);
287 static void set_ball_value(struct platform_private
*ext
, int index
, int value1
, int value2
)
290 offset
= ext
->ball_start
+ (index
* sizeof(WORD
));
291 if (value1
> 127) value1
= 127;
292 if (value1
< -127) value1
= -127;
293 if (value2
> 127) value2
= 127;
294 if (value2
< -127) value2
= -127;
295 *((WORD
*)&ext
->report_buffer
[offset
]) = LE_WORD(value1
);
296 *((WORD
*)&ext
->report_buffer
[offset
+ sizeof(WORD
)]) = LE_WORD(value2
);
299 static void set_hat_value(struct platform_private
*ext
, int index
, int value
)
301 int byte
= ext
->button_start
+ (ext
->hat_bit_offs
+ 4 * index
) / 8;
302 int bit_offs
= (ext
->hat_bit_offs
+ 4 * index
) % 8;
303 int num_low_bits
, num_high_bits
;
304 unsigned char val
, low_mask
, high_mask
;
306 /* 4-bit hatswitch value is packed into button bytes */
316 num_low_bits
= 8 - bit_offs
;
317 num_high_bits
= 4 - num_low_bits
;
318 low_mask
= (1 << num_low_bits
) - 1;
319 high_mask
= (1 << num_high_bits
) - 1;
327 case SDL_HAT_CENTERED
: val
= 0; break;
328 case SDL_HAT_UP
: val
= 1; break;
329 case SDL_HAT_RIGHTUP
: val
= 2; break;
330 case SDL_HAT_RIGHT
: val
= 3; break;
331 case SDL_HAT_RIGHTDOWN
: val
= 4; break;
332 case SDL_HAT_DOWN
: val
= 5; break;
333 case SDL_HAT_LEFTDOWN
: val
= 6; break;
334 case SDL_HAT_LEFT
: val
= 7; break;
335 case SDL_HAT_LEFTUP
: val
= 8; break;
339 ext
->report_buffer
[byte
] &= ~(low_mask
<< bit_offs
);
340 ext
->report_buffer
[byte
] |= (val
& low_mask
) << bit_offs
;
343 ext
->report_buffer
[byte
+ 1] &= ~high_mask
;
344 ext
->report_buffer
[byte
+ 1] |= val
& high_mask
;
348 static int test_haptic(struct platform_private
*ext
)
351 if (pSDL_JoystickIsHaptic(ext
->sdl_joystick
))
353 ext
->sdl_haptic
= pSDL_HapticOpenFromJoystick(ext
->sdl_joystick
);
354 if (ext
->sdl_haptic
&&
355 ((pSDL_HapticQuery(ext
->sdl_haptic
) & SDL_HAPTIC_LEFTRIGHT
) != 0 ||
356 pSDL_HapticRumbleSupported(ext
->sdl_haptic
)))
358 pSDL_HapticStopAll(ext
->sdl_haptic
);
359 pSDL_HapticRumbleInit(ext
->sdl_haptic
);
360 rc
= sizeof(HAPTIC_RUMBLE
);
361 ext
->haptic_effect_id
= -1;
365 pSDL_HapticClose(ext
->sdl_haptic
);
366 ext
->sdl_haptic
= NULL
;
372 static int build_haptic(struct platform_private
*ext
, BYTE
*report_ptr
)
376 memcpy(report_ptr
, HAPTIC_RUMBLE
, sizeof(HAPTIC_RUMBLE
));
377 return (sizeof(HAPTIC_RUMBLE
));
382 static BOOL
build_report_descriptor(struct platform_private
*ext
)
385 INT i
, descript_size
;
387 INT button_count
, axis_count
, ball_count
, hat_count
;
388 static const BYTE device_usage
[2] = {HID_USAGE_PAGE_GENERIC
, HID_USAGE_GENERIC_GAMEPAD
};
389 static const BYTE controller_usages
[] = {
393 HID_USAGE_GENERIC_RX
,
394 HID_USAGE_GENERIC_RY
,
395 HID_USAGE_GENERIC_RZ
,
396 HID_USAGE_GENERIC_SLIDER
,
397 HID_USAGE_GENERIC_DIAL
,
398 HID_USAGE_GENERIC_WHEEL
};
399 static const BYTE joystick_usages
[] = {
403 HID_USAGE_GENERIC_RZ
,
404 HID_USAGE_GENERIC_RX
,
405 HID_USAGE_GENERIC_RY
,
406 HID_USAGE_GENERIC_SLIDER
,
407 HID_USAGE_GENERIC_DIAL
,
408 HID_USAGE_GENERIC_WHEEL
};
410 descript_size
= sizeof(REPORT_HEADER
) + sizeof(REPORT_TAIL
);
413 axis_count
= pSDL_JoystickNumAxes(ext
->sdl_joystick
);
416 FIXME("Clamping joystick to 6 axis\n");
420 ext
->axis_start
= report_size
;
423 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
424 descript_size
+= (sizeof(REPORT_AXIS_USAGE
) * axis_count
);
425 descript_size
+= sizeof(REPORT_AXIS_TAIL
);
426 report_size
+= (sizeof(WORD
) * axis_count
);
429 ball_count
= pSDL_JoystickNumBalls(ext
->sdl_joystick
);
430 ext
->ball_start
= report_size
;
433 if ((ball_count
*2) + axis_count
> 9)
435 FIXME("Capping ball + axis at 9\n");
436 ball_count
= (9-axis_count
)/2;
438 descript_size
+= sizeof(REPORT_AXIS_HEADER
);
439 descript_size
+= (sizeof(REPORT_AXIS_USAGE
) * ball_count
* 2);
440 descript_size
+= sizeof(REPORT_REL_AXIS_TAIL
);
441 report_size
+= (sizeof(WORD
) * 2 * ball_count
);
444 /* For now lump all buttons just into incremental usages, Ignore Keys */
445 button_count
= pSDL_JoystickNumButtons(ext
->sdl_joystick
);
446 ext
->button_start
= report_size
;
449 descript_size
+= sizeof(REPORT_BUTTONS
);
452 hat_count
= pSDL_JoystickNumHats(ext
->sdl_joystick
);
453 ext
->hat_bit_offs
= button_count
;
456 descript_size
+= sizeof(REPORT_HATSWITCH
);
459 report_size
+= (button_count
+ hat_count
* 4 + 7) / 8;
461 descript_size
+= test_haptic(ext
);
463 TRACE("Report Descriptor will be %i bytes\n", descript_size
);
464 TRACE("Report will be %i bytes\n", report_size
);
466 ext
->report_descriptor
= HeapAlloc(GetProcessHeap(), 0, descript_size
);
467 if (!ext
->report_descriptor
)
469 ERR("Failed to alloc report descriptor\n");
472 report_ptr
= ext
->report_descriptor
;
474 memcpy(report_ptr
, REPORT_HEADER
, sizeof(REPORT_HEADER
));
475 report_ptr
[IDX_HEADER_PAGE
] = device_usage
[0];
476 report_ptr
[IDX_HEADER_USAGE
] = device_usage
[1];
477 report_ptr
+= sizeof(REPORT_HEADER
);
480 if (axis_count
== 6 && button_count
>= 14)
481 report_ptr
= add_axis_block(report_ptr
, axis_count
, HID_USAGE_PAGE_GENERIC
, controller_usages
, TRUE
);
483 report_ptr
= add_axis_block(report_ptr
, axis_count
, HID_USAGE_PAGE_GENERIC
, joystick_usages
, TRUE
);
488 report_ptr
= add_axis_block(report_ptr
, ball_count
* 2, HID_USAGE_PAGE_GENERIC
, &joystick_usages
[axis_count
], FALSE
);
492 report_ptr
= add_button_block(report_ptr
, 1, button_count
);
495 report_ptr
= add_hatswitch(report_ptr
, hat_count
);
497 report_ptr
+= build_haptic(ext
, report_ptr
);
498 memcpy(report_ptr
, REPORT_TAIL
, sizeof(REPORT_TAIL
));
500 ext
->report_descriptor_size
= descript_size
;
501 ext
->buffer_length
= report_size
;
502 ext
->report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, report_size
);
503 if (ext
->report_buffer
== NULL
)
505 ERR("Failed to alloc report buffer\n");
506 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
510 /* Initialize axis in the report */
511 for (i
= 0; i
< axis_count
; i
++)
512 set_axis_value(ext
, i
, pSDL_JoystickGetAxis(ext
->sdl_joystick
, i
));
513 for (i
= 0; i
< hat_count
; i
++)
514 set_hat_value(ext
, i
, pSDL_JoystickGetHat(ext
->sdl_joystick
, i
));
519 static SHORT
compose_dpad_value(SDL_GameController
*joystick
)
521 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_UP
))
523 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_RIGHT
))
524 return SDL_HAT_RIGHTUP
;
525 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_LEFT
))
526 return SDL_HAT_LEFTUP
;
530 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_DOWN
))
532 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_RIGHT
))
533 return SDL_HAT_RIGHTDOWN
;
534 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_LEFT
))
535 return SDL_HAT_LEFTDOWN
;
539 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_RIGHT
))
540 return SDL_HAT_RIGHT
;
541 if (pSDL_GameControllerGetButton(joystick
, SDL_CONTROLLER_BUTTON_DPAD_LEFT
))
543 return SDL_HAT_CENTERED
;
546 static BOOL
build_mapped_report_descriptor(struct platform_private
*ext
)
549 INT i
, descript_size
;
551 static const int BUTTON_BIT_COUNT
= CONTROLLER_NUM_BUTTONS
+ CONTROLLER_NUM_HATSWITCHES
* 4;
553 descript_size
= sizeof(REPORT_HEADER
) + sizeof(REPORT_TAIL
);
554 descript_size
+= sizeof(CONTROLLER_AXIS
);
555 descript_size
+= sizeof(CONTROLLER_TRIGGERS
);
556 descript_size
+= sizeof(CONTROLLER_BUTTONS
);
557 descript_size
+= sizeof(REPORT_HATSWITCH
);
558 descript_size
+= sizeof(REPORT_PADDING
);
559 if (BUTTON_BIT_COUNT
% 8 != 0)
560 descript_size
+= sizeof(REPORT_PADDING
);
561 descript_size
+= test_haptic(ext
);
564 ext
->button_start
= CONTROLLER_NUM_AXES
* sizeof(WORD
);
565 ext
->hat_bit_offs
= CONTROLLER_NUM_BUTTONS
;
567 ext
->buffer_length
= (BUTTON_BIT_COUNT
+ 7) / 8
568 + CONTROLLER_NUM_AXES
* sizeof(WORD
)
569 + 2/* unknown constant*/;
571 TRACE("Report Descriptor will be %i bytes\n", descript_size
);
572 TRACE("Report will be %i bytes\n", ext
->buffer_length
);
574 ext
->report_descriptor
= HeapAlloc(GetProcessHeap(), 0, descript_size
);
575 if (!ext
->report_descriptor
)
577 ERR("Failed to alloc report descriptor\n");
580 report_ptr
= ext
->report_descriptor
;
582 memcpy(report_ptr
, REPORT_HEADER
, sizeof(REPORT_HEADER
));
583 report_ptr
[IDX_HEADER_PAGE
] = HID_USAGE_PAGE_GENERIC
;
584 report_ptr
[IDX_HEADER_USAGE
] = HID_USAGE_GENERIC_GAMEPAD
;
585 report_ptr
+= sizeof(REPORT_HEADER
);
586 memcpy(report_ptr
, CONTROLLER_AXIS
, sizeof(CONTROLLER_AXIS
));
587 report_ptr
+= sizeof(CONTROLLER_AXIS
);
588 memcpy(report_ptr
, CONTROLLER_TRIGGERS
, sizeof(CONTROLLER_TRIGGERS
));
589 report_ptr
+= sizeof(CONTROLLER_TRIGGERS
);
590 memcpy(report_ptr
, CONTROLLER_BUTTONS
, sizeof(CONTROLLER_BUTTONS
));
591 report_ptr
+= sizeof(CONTROLLER_BUTTONS
);
592 report_ptr
= add_hatswitch(report_ptr
, 1);
593 if (BUTTON_BIT_COUNT
% 8 != 0)
594 report_ptr
= add_padding_block(report_ptr
, 8 - (BUTTON_BIT_COUNT
% 8));/* unused bits between hatswitch and following constant */
595 report_ptr
= add_padding_block(report_ptr
, 16);/* unknown constant */
596 report_ptr
+= build_haptic(ext
, report_ptr
);
597 memcpy(report_ptr
, REPORT_TAIL
, sizeof(REPORT_TAIL
));
599 ext
->report_descriptor_size
= descript_size
;
600 ext
->report_buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ext
->buffer_length
);
601 if (ext
->report_buffer
== NULL
)
603 ERR("Failed to alloc report buffer\n");
604 HeapFree(GetProcessHeap(), 0, ext
->report_descriptor
);
608 /* Initialize axis in the report */
609 for (i
= SDL_CONTROLLER_AXIS_LEFTX
; i
< SDL_CONTROLLER_AXIS_MAX
; i
++)
610 set_axis_value(ext
, i
, pSDL_GameControllerGetAxis(ext
->sdl_controller
, i
));
612 set_hat_value(ext
, 0, compose_dpad_value(ext
->sdl_controller
));
614 /* unknown constant */
615 ext
->report_buffer
[14] = 0x89;
616 ext
->report_buffer
[15] = 0xc5;
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
=
738 compare_platform_device
,
739 get_reportdescriptor
,
741 begin_report_processing
,
747 static BOOL
set_report_from_event(SDL_Event
*event
)
749 DEVICE_OBJECT
*device
;
750 struct platform_private
*private;
751 /* All the events coming in will have 'which' as a 3rd field */
752 SDL_JoystickID index
= ((SDL_JoyButtonEvent
*)event
)->which
;
754 device
= bus_find_hid_device(&sdl_vtbl
, ULongToPtr(index
));
757 ERR("Failed to find device at index %i\n",index
);
760 private = impl_from_DEVICE_OBJECT(device
);
761 if (private->sdl_controller
)
763 /* We want mapped events */
769 case SDL_JOYBUTTONDOWN
:
770 case SDL_JOYBUTTONUP
:
772 SDL_JoyButtonEvent
*ie
= &event
->jbutton
;
774 set_button_value(private, ie
->button
, ie
->state
);
776 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
779 case SDL_JOYAXISMOTION
:
781 SDL_JoyAxisEvent
*ie
= &event
->jaxis
;
785 set_axis_value(private, ie
->axis
, ie
->value
);
786 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
790 case SDL_JOYBALLMOTION
:
792 SDL_JoyBallEvent
*ie
= &event
->jball
;
794 set_ball_value(private, ie
->ball
, ie
->xrel
, ie
->yrel
);
795 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
798 case SDL_JOYHATMOTION
:
800 SDL_JoyHatEvent
*ie
= &event
->jhat
;
802 set_hat_value(private, ie
->hat
, ie
->value
);
803 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
807 ERR("TODO: Process Report (0x%x)\n",event
->type
);
812 static BOOL
set_mapped_report_from_event(SDL_Event
*event
)
814 DEVICE_OBJECT
*device
;
815 struct platform_private
*private;
816 /* All the events coming in will have 'which' as a 3rd field */
817 int index
= ((SDL_ControllerButtonEvent
*)event
)->which
;
818 device
= bus_find_hid_device(&sdl_vtbl
, ULongToPtr(index
));
821 ERR("Failed to find device at index %i\n",index
);
824 private = impl_from_DEVICE_OBJECT(device
);
828 case SDL_CONTROLLERBUTTONDOWN
:
829 case SDL_CONTROLLERBUTTONUP
:
832 SDL_ControllerButtonEvent
*ie
= &event
->cbutton
;
836 case SDL_CONTROLLER_BUTTON_A
: usage
= 0; break;
837 case SDL_CONTROLLER_BUTTON_B
: usage
= 1; break;
838 case SDL_CONTROLLER_BUTTON_X
: usage
= 2; break;
839 case SDL_CONTROLLER_BUTTON_Y
: usage
= 3; break;
840 case SDL_CONTROLLER_BUTTON_LEFTSHOULDER
: usage
= 4; break;
841 case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
: usage
= 5; break;
842 case SDL_CONTROLLER_BUTTON_BACK
: usage
= 6; break;
843 case SDL_CONTROLLER_BUTTON_START
: usage
= 7; break;
844 case SDL_CONTROLLER_BUTTON_LEFTSTICK
: usage
= 8; break;
845 case SDL_CONTROLLER_BUTTON_RIGHTSTICK
: usage
= 9; break;
846 case SDL_CONTROLLER_BUTTON_GUIDE
: usage
= 10; break;
848 case SDL_CONTROLLER_BUTTON_DPAD_UP
:
849 case SDL_CONTROLLER_BUTTON_DPAD_DOWN
:
850 case SDL_CONTROLLER_BUTTON_DPAD_LEFT
:
851 case SDL_CONTROLLER_BUTTON_DPAD_RIGHT
:
852 set_hat_value(private, 0, compose_dpad_value(private->sdl_controller
));
853 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
857 ERR("Unknown Button %i\n",ie
->button
);
862 set_button_value(private, usage
, ie
->state
);
863 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
867 case SDL_CONTROLLERAXISMOTION
:
869 SDL_ControllerAxisEvent
*ie
= &event
->caxis
;
871 set_axis_value(private, ie
->axis
, ie
->value
);
872 process_hid_report(device
, private->report_buffer
, private->buffer_length
);
876 ERR("TODO: Process Report (%x)\n",event
->type
);
881 static void try_remove_device(SDL_JoystickID index
)
883 DEVICE_OBJECT
*device
= NULL
;
885 device
= bus_find_hid_device(&sdl_vtbl
, ULongToPtr(index
));
888 IoInvalidateDeviceRelations(device
, RemovalRelations
);
890 bus_remove_hid_device(device
);
893 static void try_add_device(SDL_JoystickID index
)
895 DWORD vid
= 0, pid
= 0, version
= 0;
896 DEVICE_OBJECT
*device
= NULL
;
897 WCHAR serial
[34] = {0};
899 BOOL is_xbox_gamepad
;
902 SDL_Joystick
* joystick
;
904 SDL_JoystickGUID guid
;
905 SDL_GameController
*controller
= NULL
;
907 if ((joystick
= pSDL_JoystickOpen(index
)) == NULL
)
909 WARN("Unable to open sdl device %i: %s\n", index
, pSDL_GetError());
913 if (map_controllers
&& pSDL_IsGameController(index
))
914 controller
= pSDL_GameControllerOpen(index
);
916 id
= pSDL_JoystickInstanceID(joystick
);
918 if (pSDL_JoystickGetProductVersion
!= NULL
) {
919 vid
= pSDL_JoystickGetVendor(joystick
);
920 pid
= pSDL_JoystickGetProduct(joystick
);
921 version
= pSDL_JoystickGetProductVersion(joystick
);
926 pid
= pSDL_JoystickInstanceID(joystick
) + 1;
930 guid
= pSDL_JoystickGetGUID(joystick
);
931 pSDL_JoystickGetGUIDString(guid
, guid_str
, sizeof(guid_str
));
932 MultiByteToWideChar(CP_ACP
, 0, guid_str
, -1, serial
, sizeof(guid_str
));
936 TRACE("Found sdl game controller %i (vid %04x, pid %04x, version %u, serial %s)\n",
937 id
, vid
, pid
, version
, debugstr_w(serial
));
938 is_xbox_gamepad
= TRUE
;
942 int button_count
, axis_count
;
944 TRACE("Found sdl device %i (vid %04x, pid %04x, version %u, serial %s)\n",
945 id
, vid
, pid
, version
, debugstr_w(serial
));
947 axis_count
= pSDL_JoystickNumAxes(joystick
);
948 button_count
= pSDL_JoystickNumButtons(joystick
);
949 is_xbox_gamepad
= (axis_count
== 6 && button_count
>= 14);
954 device
= bus_create_hid_device(sdl_driver_obj
, sdl_busidW
, vid
, pid
,
955 input
, version
, id
, serial
, is_xbox_gamepad
, &GUID_DEVCLASS_SDL
,
956 &sdl_vtbl
, sizeof(struct platform_private
));
961 struct platform_private
*private = impl_from_DEVICE_OBJECT(device
);
962 private->sdl_joystick
= joystick
;
963 private->sdl_controller
= controller
;
966 rc
= build_mapped_report_descriptor(private);
968 rc
= build_report_descriptor(private);
971 ERR("Building report descriptor failed, removing device\n");
972 bus_remove_hid_device(device
);
973 HeapFree(GetProcessHeap(), 0, serial
);
976 IoInvalidateDeviceRelations(device
, BusRelations
);
980 WARN("Ignoring device %i\n", id
);
984 static void process_device_event(SDL_Event
*event
)
986 TRACE_(hid_report
)("Received action %x\n", event
->type
);
988 if (event
->type
== SDL_JOYDEVICEADDED
)
989 try_add_device(((SDL_JoyDeviceEvent
*)event
)->which
);
990 else if (event
->type
== SDL_JOYDEVICEREMOVED
)
991 try_remove_device(((SDL_JoyDeviceEvent
*)event
)->which
);
992 else if (event
->type
>= SDL_JOYAXISMOTION
&& event
->type
<= SDL_JOYBUTTONUP
)
993 set_report_from_event(event
);
994 else if (event
->type
>= SDL_CONTROLLERAXISMOTION
&& event
->type
<= SDL_CONTROLLERBUTTONUP
)
995 set_mapped_report_from_event(event
);
998 typedef struct _thread_args
{
1000 UNICODE_STRING
*registry_path
;
1003 static DWORD CALLBACK
deviceloop_thread(void *args
)
1005 thread_arguments
*thread_args
= args
;
1008 if (pSDL_Init(SDL_INIT_GAMECONTROLLER
|SDL_INIT_HAPTIC
) < 0)
1010 ERR("Can't init SDL: %s\n", pSDL_GetError());
1011 return STATUS_UNSUCCESSFUL
;
1014 pSDL_JoystickEventState(SDL_ENABLE
);
1015 pSDL_GameControllerEventState(SDL_ENABLE
);
1017 /* Process mappings */
1018 if (pSDL_GameControllerAddMapping
!= NULL
)
1021 OBJECT_ATTRIBUTES attr
;
1022 WCHAR buffer
[MAX_PATH
];
1023 UNICODE_STRING regpath
= {0, sizeof(buffer
), buffer
};
1024 static const WCHAR szPath
[] = {'\\','m','a','p',0};
1026 RtlCopyUnicodeString(®path
, thread_args
->registry_path
);
1027 RtlAppendUnicodeToString(®path
, szPath
);
1028 InitializeObjectAttributes(&attr
, ®path
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1029 if (NtOpenKey(&key
, KEY_ALL_ACCESS
, &attr
) == STATUS_SUCCESS
)
1032 CHAR
*buffer
= NULL
;
1033 DWORD buffer_len
= 0;
1040 DWORD data_len
= buffer_len
;
1042 name_len
= sizeof(name
);
1043 rc
= RegEnumValueA(key
, index
, name
, &name_len
, NULL
, &type
, (LPBYTE
)buffer
, &data_len
);
1044 if (rc
== ERROR_MORE_DATA
|| buffer
== NULL
)
1047 buffer
= HeapReAlloc(GetProcessHeap(), 0, buffer
, data_len
);
1049 buffer
= HeapAlloc(GetProcessHeap(), 0, data_len
);
1050 buffer_len
= data_len
;
1052 name_len
= sizeof(name
);
1053 rc
= RegEnumValueA(key
, index
, name
, &name_len
, NULL
, &type
, (LPBYTE
)buffer
, &data_len
);
1056 if (rc
== STATUS_SUCCESS
)
1058 TRACE("Setting mapping %s...\n",debugstr_an(buffer
,29));
1059 pSDL_GameControllerAddMapping(buffer
);
1062 } while (rc
== STATUS_SUCCESS
);
1063 HeapFree(GetProcessHeap(), 0, buffer
);
1068 SetEvent(thread_args
->event
);
1071 while (pSDL_WaitEvent(&event
) != 0)
1072 process_device_event(&event
);
1074 TRACE("Device thread exiting\n");
1078 void sdl_driver_unload( void )
1080 TRACE("Unload Driver\n");
1083 NTSTATUS WINAPI
sdl_driver_init(DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry_path
)
1085 static const WCHAR controller_modeW
[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0};
1086 static const UNICODE_STRING controller_mode
= {sizeof(controller_modeW
) - sizeof(WCHAR
), sizeof(controller_modeW
), (WCHAR
*)controller_modeW
};
1090 thread_arguments args
;
1092 TRACE("(%p, %s)\n", driver
, debugstr_w(registry_path
->Buffer
));
1093 if (sdl_handle
== NULL
)
1095 sdl_handle
= wine_dlopen(SONAME_LIBSDL2
, RTLD_NOW
, NULL
, 0);
1097 WARN("could not load %s\n", SONAME_LIBSDL2
);
1098 sdl_driver_obj
= NULL
;
1099 return STATUS_UNSUCCESSFUL
;
1101 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(sdl_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
1102 LOAD_FUNCPTR(SDL_GetError
);
1103 LOAD_FUNCPTR(SDL_Init
);
1104 LOAD_FUNCPTR(SDL_JoystickEventState
);
1105 LOAD_FUNCPTR(SDL_JoystickGetGUID
);
1106 LOAD_FUNCPTR(SDL_JoystickGetGUIDString
);
1107 LOAD_FUNCPTR(SDL_JoystickInstanceID
);
1108 LOAD_FUNCPTR(SDL_JoystickName
);
1109 LOAD_FUNCPTR(SDL_JoystickNumAxes
);
1110 LOAD_FUNCPTR(SDL_JoystickOpen
);
1111 LOAD_FUNCPTR(SDL_WaitEvent
);
1112 LOAD_FUNCPTR(SDL_JoystickNumButtons
);
1113 LOAD_FUNCPTR(SDL_JoystickNumBalls
);
1114 LOAD_FUNCPTR(SDL_JoystickNumHats
);
1115 LOAD_FUNCPTR(SDL_JoystickGetAxis
);
1116 LOAD_FUNCPTR(SDL_JoystickGetHat
);
1117 LOAD_FUNCPTR(SDL_IsGameController
);
1118 LOAD_FUNCPTR(SDL_GameControllerGetAxis
);
1119 LOAD_FUNCPTR(SDL_GameControllerGetButton
);
1120 LOAD_FUNCPTR(SDL_GameControllerName
);
1121 LOAD_FUNCPTR(SDL_GameControllerOpen
);
1122 LOAD_FUNCPTR(SDL_GameControllerEventState
);
1123 LOAD_FUNCPTR(SDL_HapticClose
);
1124 LOAD_FUNCPTR(SDL_HapticDestroyEffect
);
1125 LOAD_FUNCPTR(SDL_HapticNewEffect
);
1126 LOAD_FUNCPTR(SDL_HapticOpenFromJoystick
);
1127 LOAD_FUNCPTR(SDL_HapticQuery
);
1128 LOAD_FUNCPTR(SDL_HapticRumbleInit
);
1129 LOAD_FUNCPTR(SDL_HapticRumblePlay
);
1130 LOAD_FUNCPTR(SDL_HapticRumbleSupported
);
1131 LOAD_FUNCPTR(SDL_HapticRunEffect
);
1132 LOAD_FUNCPTR(SDL_HapticStopAll
);
1133 LOAD_FUNCPTR(SDL_JoystickIsHaptic
);
1134 LOAD_FUNCPTR(SDL_memset
);
1135 LOAD_FUNCPTR(SDL_GameControllerAddMapping
);
1137 pSDL_JoystickGetProduct
= wine_dlsym(sdl_handle
, "SDL_JoystickGetProduct", NULL
, 0);
1138 pSDL_JoystickGetProductVersion
= wine_dlsym(sdl_handle
, "SDL_JoystickGetProductVersion", NULL
, 0);
1139 pSDL_JoystickGetVendor
= wine_dlsym(sdl_handle
, "SDL_JoystickGetVendor", NULL
, 0);
1142 sdl_driver_obj
= driver
;
1143 driver
->MajorFunction
[IRP_MJ_PNP
] = common_pnp_dispatch
;
1144 driver
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = hid_internal_dispatch
;
1146 map_controllers
= check_bus_option(registry_path
, &controller_mode
, 1);
1148 if (!(events
[0] = CreateEventW(NULL
, TRUE
, FALSE
, NULL
)))
1150 args
.event
= events
[0];
1151 args
.registry_path
= registry_path
;
1152 if (!(events
[1] = CreateThread(NULL
, 0, deviceloop_thread
, &args
, 0, NULL
)))
1154 CloseHandle(events
[0]);
1158 result
= WaitForMultipleObjects(2, events
, FALSE
, INFINITE
);
1159 CloseHandle(events
[0]);
1160 CloseHandle(events
[1]);
1161 if (result
== WAIT_OBJECT_0
)
1163 TRACE("Initialization successful\n");
1164 return STATUS_SUCCESS
;
1168 sdl_driver_obj
= NULL
;
1169 return STATUS_UNSUCCESSFUL
;
1171 wine_dlclose(sdl_handle
, NULL
, 0);
1173 return STATUS_UNSUCCESSFUL
;
1178 NTSTATUS WINAPI
sdl_driver_init(DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry_path
)
1180 WARN("compiled without SDL support\n");
1181 return STATUS_NOT_IMPLEMENTED
;
1184 void sdl_driver_unload( void )
1186 TRACE("Stub: Unload Driver\n");
1189 #endif /* SONAME_LIBSDL2 */