21 #include "../../SDL_internal.h"
23 #if SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT
41 #include "../SDL_sysjoystick.h"
42 #include "../../thread/SDL_systhread.h"
43 #include "../../core/windows/SDL_windows.h"
44 #if !defined(__WINRT__)
53 #include "../../haptic/windows/SDL_dinputhaptic_c.h"
54 #include "../../haptic/windows/SDL_xinputhaptic_c.h"
57 #ifndef DEVICE_NOTIFY_WINDOW_HANDLE
58 #define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000
78 } SDL_DeviceNotificationData;
81 SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *
data)
86 SDL_CreateDeviceNotification(SDL_DeviceNotificationData *
data)
101 HRESULT coinitialized;
105 } SDL_DeviceNotificationData;
107 #define IDT_SDL_DEVICE_CHANGE_TIMER_1 1200
108 #define IDT_SDL_DEVICE_CHANGE_TIMER_2 1201
111 static LRESULT CALLBACK
112 SDL_PrivateJoystickDetectProc(HWND hwnd, UINT
message, WPARAM wParam, LPARAM lParam)
115 case WM_DEVICECHANGE:
117 case DBT_DEVICEARRIVAL:
118 case DBT_DEVICEREMOVECOMPLETE:
119 if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
121 SetTimer(hwnd, IDT_SDL_DEVICE_CHANGE_TIMER_1, 300,
NULL);
122 SetTimer(hwnd, IDT_SDL_DEVICE_CHANGE_TIMER_2, 2000,
NULL);
128 KillTimer(hwnd, wParam);
133 return DefWindowProc (hwnd,
message, wParam, lParam);
137 SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *
data)
140 UnregisterDeviceNotification(
data->hNotify);
142 if (
data->messageWindow)
143 DestroyWindow(
data->messageWindow);
145 UnregisterClass(
data->wincl.lpszClassName,
data->wincl.hInstance);
153 SDL_CreateDeviceNotification(SDL_DeviceNotificationData *
data)
155 DEV_BROADCAST_DEVICEINTERFACE dbh;
156 GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
162 data->wincl.hInstance = GetModuleHandle(
NULL);
163 data->wincl.lpszClassName = L
"Message";
164 data->wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc;
165 data->wincl.cbSize =
sizeof (WNDCLASSEX);
167 if (!RegisterClassEx(&
data->wincl)) {
168 WIN_SetError(
"Failed to create register class for joystick autodetect");
169 SDL_CleanupDeviceNotification(
data);
173 data->messageWindow = (HWND)CreateWindowEx(0, L
"Message",
NULL, 0, 0, 0, 0, 0, HWND_MESSAGE,
NULL,
NULL,
NULL);
174 if (!
data->messageWindow) {
175 WIN_SetError(
"Failed to create message window for joystick autodetect");
176 SDL_CleanupDeviceNotification(
data);
181 dbh.dbcc_size =
sizeof(dbh);
182 dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
183 dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
185 data->hNotify = RegisterDeviceNotification(
data->messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
186 if (!
data->hNotify) {
187 WIN_SetError(
"Failed to create notify device for joystick autodetect");
188 SDL_CleanupDeviceNotification(
data);
200 if (!
data->messageWindow) {
205 while (lastret > 0 && s_bWindowsDeviceChanged ==
SDL_FALSE) {
206 lastret = GetMessage(&msg,
NULL, 0, 0);
208 TranslateMessage(&msg);
209 DispatchMessage(&msg);
220 SDL_JoystickThread(
void *_data)
222 SDL_DeviceNotificationData notification_data;
224 #if SDL_JOYSTICK_XINPUT
225 SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
229 if (SDL_CreateDeviceNotification(¬ification_data) < 0) {
234 while (s_bJoystickThreadQuit ==
SDL_FALSE) {
237 if (SDL_WaitForDeviceNotification(¬ification_data, s_mutexJoyStickEnum) ==
SDL_FALSE) {
238 #if SDL_JOYSTICK_XINPUT
244 for (userId = 0; userId < XUSER_MAX_COUNT; userId++) {
245 XINPUT_CAPABILITIES capabilities;
246 const DWORD
result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
248 if (bOpenedXInputDevices[userId] !=
available) {
250 bOpenedXInputDevices[userId] =
available;
260 if (s_bWindowsDeviceChanged || bXInputChanged) {
268 SDL_CleanupDeviceNotification(¬ification_data);
283 static void WINDOWS_JoystickDetect(
void);
284 static void WINDOWS_JoystickQuit(
void);
291 WINDOWS_JoystickInit(
void)
294 WINDOWS_JoystickQuit();
299 WINDOWS_JoystickQuit();
307 WINDOWS_JoystickDetect();
309 if (!s_threadJoystick) {
319 WINDOWS_JoystickGetCount(
void)
333 WINDOWS_JoystickDetect(
void)
338 if (!s_bDeviceAdded && !s_bDeviceRemoved) {
369 pListNext = pCurList->
pNext;
372 pCurList = pListNext;
375 if (s_bDeviceAdded) {
377 int device_index = 0;
380 while (pNewJoystick) {
393 pNewJoystick = pNewJoystick->
pNext;
400 WINDOWS_JoystickGetDeviceName(
int device_index)
404 for (; device_index > 0; device_index--)
407 return device->joystickname;
411 WINDOWS_JoystickGetDevicePlayerIndex(
int device_index)
419 return device->bXInputDevice ? (
int)
device->XInputUserId : -1;
424 WINDOWS_JoystickGetDeviceGUID(
int device_index)
437 WINDOWS_JoystickGetDeviceInstanceID(
int device_index)
445 return device->nInstanceID;
454 WINDOWS_JoystickOpen(SDL_Joystick * joystick,
int device_index)
458 for (; device_index > 0; device_index--)
459 joystickdevice = joystickdevice->
pNext;
462 joystick->instance_id = joystickdevice->
nInstanceID;
465 if (joystick->hwdata ==
NULL) {
469 joystick->hwdata->guid = joystickdevice->
guid;
479 WINDOWS_JoystickRumble(SDL_Joystick * joystick,
Uint16 low_frequency_rumble,
Uint16 high_frequency_rumble,
Uint32 duration_ms)
481 if (joystick->hwdata->bXInputDevice) {
489 WINDOWS_JoystickUpdate(SDL_Joystick * joystick)
491 if (!joystick->hwdata) {
495 if (joystick->hwdata->bXInputDevice) {
504 WINDOWS_JoystickClose(SDL_Joystick * joystick)
506 if (joystick->hwdata->bXInputDevice) {
517 WINDOWS_JoystickQuit(
void)
529 if (s_threadJoystick) {
541 s_condJoystickThread=
NULL;
542 s_mutexJoyStickEnum =
NULL;
543 s_threadJoystick =
NULL;
555 WINDOWS_JoystickInit,
556 WINDOWS_JoystickGetCount,
557 WINDOWS_JoystickDetect,
558 WINDOWS_JoystickGetDeviceName,
559 WINDOWS_JoystickGetDevicePlayerIndex,
560 WINDOWS_JoystickGetDeviceGUID,
561 WINDOWS_JoystickGetDeviceInstanceID,
562 WINDOWS_JoystickOpen,
563 WINDOWS_JoystickRumble,
564 WINDOWS_JoystickUpdate,
565 WINDOWS_JoystickClose,
566 WINDOWS_JoystickQuit,