Atlas - SDL_hid.c

Home / ext / SDL / src / core / windows Lines: 1 | Size: 8258 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
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 25HidD_GetAttributes_t SDL_HidD_GetAttributes; 26HidD_GetString_t SDL_HidD_GetManufacturerString; 27HidD_GetString_t SDL_HidD_GetProductString; 28HidP_GetCaps_t SDL_HidP_GetCaps; 29HidP_GetButtonCaps_t SDL_HidP_GetButtonCaps; 30HidP_GetValueCaps_t SDL_HidP_GetValueCaps; 31HidP_MaxDataListLength_t SDL_HidP_MaxDataListLength; 32HidP_GetData_t SDL_HidP_GetData; 33 34static HMODULE s_pHIDDLL = 0; 35static int s_HIDDLLRefCount = 0; 36 37 38bool 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 72void 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 91DECLARE_HANDLE(HCMNOTIFICATION); 92typedef HCMNOTIFICATION *PHCMNOTIFICATION; 93 94typedef 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 102typedef 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 125typedef 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 140typedef 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 165typedef DWORD (CALLBACK *PCM_NOTIFY_CALLBACK)(HCMNOTIFICATION hNotify, PVOID Context, CM_NOTIFY_ACTION Action, PCM_NOTIFY_EVENT_DATA EventData, DWORD EventDataSize); 166 167typedef DWORD (WINAPI *CM_Register_NotificationFunc)(PCM_NOTIFY_FILTER pFilter, PVOID pContext, PCM_NOTIFY_CALLBACK pCallback, PHCMNOTIFICATION pNotifyContext); 168typedef DWORD (WINAPI *CM_Unregister_NotificationFunc)(HCMNOTIFICATION NotifyContext); 169 170static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } }; 171 172static int s_DeviceNotificationsRequested; 173static HMODULE cfgmgr32_lib_handle; 174static CM_Register_NotificationFunc CM_Register_Notification; 175static CM_Unregister_NotificationFunc CM_Unregister_Notification; 176static HCMNOTIFICATION s_DeviceNotificationFuncHandle; 177static Uint64 s_LastDeviceNotification = 1; 178 179static 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 188void 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 215Uint64 WIN_GetLastDeviceNotification(void) 216{ 217 return s_LastDeviceNotification; 218} 219 220void 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 241void WIN_InitDeviceNotification(void) 242{ 243} 244 245Uint64 WIN_GetLastDeviceNotification( void ) 246{ 247 return 0; 248} 249 250void WIN_QuitDeviceNotification(void) 251{ 252} 253 254#endif // !SDL_PLATFORM_XBOXONE && !SDL_PLATFORM_XBOXSERIES 255
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.