Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/core/windows/SDL_hid.c
9905 views
1
/*
2
Simple DirectMedia Layer
3
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
4
5
This software is provided 'as-is', without any express or implied
6
warranty. In no event will the authors be held liable for any damages
7
arising from the use of this software.
8
9
Permission is granted to anyone to use this software for any purpose,
10
including commercial applications, and to alter it and redistribute it
11
freely, subject to the following restrictions:
12
13
1. The origin of this software must not be misrepresented; you must not
14
claim that you wrote the original software. If you use this software
15
in a product, an acknowledgment in the product documentation would be
16
appreciated but is not required.
17
2. Altered source versions must be plainly marked as such, and must not be
18
misrepresented as being the original software.
19
3. This notice may not be removed or altered from any source distribution.
20
*/
21
#include "SDL_internal.h"
22
23
#include "SDL_hid.h"
24
25
HidD_GetAttributes_t SDL_HidD_GetAttributes;
26
HidD_GetString_t SDL_HidD_GetManufacturerString;
27
HidD_GetString_t SDL_HidD_GetProductString;
28
HidP_GetCaps_t SDL_HidP_GetCaps;
29
HidP_GetButtonCaps_t SDL_HidP_GetButtonCaps;
30
HidP_GetValueCaps_t SDL_HidP_GetValueCaps;
31
HidP_MaxDataListLength_t SDL_HidP_MaxDataListLength;
32
HidP_GetData_t SDL_HidP_GetData;
33
34
static HMODULE s_pHIDDLL = 0;
35
static int s_HIDDLLRefCount = 0;
36
37
38
bool WIN_LoadHIDDLL(void)
39
{
40
if (s_pHIDDLL) {
41
SDL_assert(s_HIDDLLRefCount > 0);
42
s_HIDDLLRefCount++;
43
return true; // already loaded
44
}
45
46
s_pHIDDLL = LoadLibrary(TEXT("hid.dll"));
47
if (!s_pHIDDLL) {
48
return false;
49
}
50
51
SDL_assert(s_HIDDLLRefCount == 0);
52
s_HIDDLLRefCount = 1;
53
54
SDL_HidD_GetAttributes = (HidD_GetAttributes_t)GetProcAddress(s_pHIDDLL, "HidD_GetAttributes");
55
SDL_HidD_GetManufacturerString = (HidD_GetString_t)GetProcAddress(s_pHIDDLL, "HidD_GetManufacturerString");
56
SDL_HidD_GetProductString = (HidD_GetString_t)GetProcAddress(s_pHIDDLL, "HidD_GetProductString");
57
SDL_HidP_GetCaps = (HidP_GetCaps_t)GetProcAddress(s_pHIDDLL, "HidP_GetCaps");
58
SDL_HidP_GetButtonCaps = (HidP_GetButtonCaps_t)GetProcAddress(s_pHIDDLL, "HidP_GetButtonCaps");
59
SDL_HidP_GetValueCaps = (HidP_GetValueCaps_t)GetProcAddress(s_pHIDDLL, "HidP_GetValueCaps");
60
SDL_HidP_MaxDataListLength = (HidP_MaxDataListLength_t)GetProcAddress(s_pHIDDLL, "HidP_MaxDataListLength");
61
SDL_HidP_GetData = (HidP_GetData_t)GetProcAddress(s_pHIDDLL, "HidP_GetData");
62
if (!SDL_HidD_GetManufacturerString || !SDL_HidD_GetProductString ||
63
!SDL_HidP_GetCaps || !SDL_HidP_GetButtonCaps ||
64
!SDL_HidP_GetValueCaps || !SDL_HidP_MaxDataListLength || !SDL_HidP_GetData) {
65
WIN_UnloadHIDDLL();
66
return false;
67
}
68
69
return true;
70
}
71
72
void WIN_UnloadHIDDLL(void)
73
{
74
if (s_pHIDDLL) {
75
SDL_assert(s_HIDDLLRefCount > 0);
76
if (--s_HIDDLLRefCount == 0) {
77
FreeLibrary(s_pHIDDLL);
78
s_pHIDDLL = NULL;
79
}
80
} else {
81
SDL_assert(s_HIDDLLRefCount == 0);
82
}
83
}
84
85
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
86
87
// CM_Register_Notification definitions
88
89
#define CR_SUCCESS 0
90
91
DECLARE_HANDLE(HCMNOTIFICATION);
92
typedef HCMNOTIFICATION *PHCMNOTIFICATION;
93
94
typedef enum _CM_NOTIFY_FILTER_TYPE
95
{
96
CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE = 0,
97
CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE,
98
CM_NOTIFY_FILTER_TYPE_DEVICEINSTANCE,
99
CM_NOTIFY_FILTER_TYPE_MAX
100
} CM_NOTIFY_FILTER_TYPE, *PCM_NOTIFY_FILTER_TYPE;
101
102
typedef struct _CM_NOTIFY_FILTER
103
{
104
DWORD cbSize;
105
DWORD Flags;
106
CM_NOTIFY_FILTER_TYPE FilterType;
107
DWORD Reserved;
108
union
109
{
110
struct
111
{
112
GUID ClassGuid;
113
} DeviceInterface;
114
struct
115
{
116
HANDLE hTarget;
117
} DeviceHandle;
118
struct
119
{
120
WCHAR InstanceId[200];
121
} DeviceInstance;
122
} u;
123
} CM_NOTIFY_FILTER, *PCM_NOTIFY_FILTER;
124
125
typedef enum _CM_NOTIFY_ACTION
126
{
127
CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL = 0,
128
CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL,
129
CM_NOTIFY_ACTION_DEVICEQUERYREMOVE,
130
CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED,
131
CM_NOTIFY_ACTION_DEVICEREMOVEPENDING,
132
CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE,
133
CM_NOTIFY_ACTION_DEVICECUSTOMEVENT,
134
CM_NOTIFY_ACTION_DEVICEINSTANCEENUMERATED,
135
CM_NOTIFY_ACTION_DEVICEINSTANCESTARTED,
136
CM_NOTIFY_ACTION_DEVICEINSTANCEREMOVED,
137
CM_NOTIFY_ACTION_MAX
138
} CM_NOTIFY_ACTION, *PCM_NOTIFY_ACTION;
139
140
typedef struct _CM_NOTIFY_EVENT_DATA
141
{
142
CM_NOTIFY_FILTER_TYPE FilterType;
143
DWORD Reserved;
144
union
145
{
146
struct
147
{
148
GUID ClassGuid;
149
WCHAR SymbolicLink[ANYSIZE_ARRAY];
150
} DeviceInterface;
151
struct
152
{
153
GUID EventGuid;
154
LONG NameOffset;
155
DWORD DataSize;
156
BYTE Data[ANYSIZE_ARRAY];
157
} DeviceHandle;
158
struct
159
{
160
WCHAR InstanceId[ANYSIZE_ARRAY];
161
} DeviceInstance;
162
} u;
163
} CM_NOTIFY_EVENT_DATA, *PCM_NOTIFY_EVENT_DATA;
164
165
typedef DWORD (CALLBACK *PCM_NOTIFY_CALLBACK)(HCMNOTIFICATION hNotify, PVOID Context, CM_NOTIFY_ACTION Action, PCM_NOTIFY_EVENT_DATA EventData, DWORD EventDataSize);
166
167
typedef DWORD (WINAPI *CM_Register_NotificationFunc)(PCM_NOTIFY_FILTER pFilter, PVOID pContext, PCM_NOTIFY_CALLBACK pCallback, PHCMNOTIFICATION pNotifyContext);
168
typedef DWORD (WINAPI *CM_Unregister_NotificationFunc)(HCMNOTIFICATION NotifyContext);
169
170
static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
171
172
static int s_DeviceNotificationsRequested;
173
static HMODULE cfgmgr32_lib_handle;
174
static CM_Register_NotificationFunc CM_Register_Notification;
175
static CM_Unregister_NotificationFunc CM_Unregister_Notification;
176
static HCMNOTIFICATION s_DeviceNotificationFuncHandle;
177
static Uint64 s_LastDeviceNotification = 1;
178
179
static DWORD CALLBACK SDL_DeviceNotificationFunc(HCMNOTIFICATION hNotify, PVOID context, CM_NOTIFY_ACTION action, PCM_NOTIFY_EVENT_DATA eventData, DWORD event_data_size)
180
{
181
if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL ||
182
action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) {
183
s_LastDeviceNotification = SDL_GetTicksNS();
184
}
185
return ERROR_SUCCESS;
186
}
187
188
void WIN_InitDeviceNotification(void)
189
{
190
++s_DeviceNotificationsRequested;
191
if (s_DeviceNotificationsRequested > 1) {
192
return;
193
}
194
195
cfgmgr32_lib_handle = LoadLibraryA("cfgmgr32.dll");
196
if (cfgmgr32_lib_handle) {
197
CM_Register_Notification = (CM_Register_NotificationFunc)GetProcAddress(cfgmgr32_lib_handle, "CM_Register_Notification");
198
CM_Unregister_Notification = (CM_Unregister_NotificationFunc)GetProcAddress(cfgmgr32_lib_handle, "CM_Unregister_Notification");
199
if (CM_Register_Notification && CM_Unregister_Notification) {
200
CM_NOTIFY_FILTER notify_filter;
201
202
SDL_zero(notify_filter);
203
notify_filter.cbSize = sizeof(notify_filter);
204
notify_filter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
205
notify_filter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_HID;
206
if (CM_Register_Notification(&notify_filter, NULL, SDL_DeviceNotificationFunc, &s_DeviceNotificationFuncHandle) == CR_SUCCESS) {
207
return;
208
}
209
}
210
}
211
212
// FIXME: Should we log errors?
213
}
214
215
Uint64 WIN_GetLastDeviceNotification(void)
216
{
217
return s_LastDeviceNotification;
218
}
219
220
void WIN_QuitDeviceNotification(void)
221
{
222
if (--s_DeviceNotificationsRequested > 0) {
223
return;
224
}
225
// Make sure we have balanced calls to init/quit
226
SDL_assert(s_DeviceNotificationsRequested == 0);
227
228
if (cfgmgr32_lib_handle) {
229
if (s_DeviceNotificationFuncHandle && CM_Unregister_Notification) {
230
CM_Unregister_Notification(s_DeviceNotificationFuncHandle);
231
s_DeviceNotificationFuncHandle = NULL;
232
}
233
234
FreeLibrary(cfgmgr32_lib_handle);
235
cfgmgr32_lib_handle = NULL;
236
}
237
}
238
239
#else
240
241
void WIN_InitDeviceNotification(void)
242
{
243
}
244
245
Uint64 WIN_GetLastDeviceNotification( void )
246
{
247
return 0;
248
}
249
250
void WIN_QuitDeviceNotification(void)
251
{
252
}
253
254
#endif // !SDL_PLATFORM_XBOXONE && !SDL_PLATFORM_XBOXSERIES
255
256