From 3180ba81af4357b72845558e45620532863d3d17 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Apr 2020 08:34:27 -0700 Subject: [PATCH] First pass at Windows sensor implementation --- CMakeLists.txt | 7 + VisualC/SDL.sln | 11 + VisualC/SDL/SDL.vcxproj | 2 + VisualC/SDL/SDL.vcxproj.filters | 2 + VisualC/tests/testsensor/testsensor.vcxproj | 199 ++++++++ configure | 10 + configure.ac | 8 + include/SDL_config_windows.h | 4 +- include/SDL_sensor.h | 13 + src/dynapi/SDL_dynapi_overrides.h | 2 + src/dynapi/SDL_dynapi_procs.h | 2 + src/sensor/SDL_sensor.c | 7 +- src/sensor/SDL_syssensor.h | 3 +- src/sensor/android/SDL_androidsensor.c | 1 + src/sensor/dummy/SDL_dummysensor.c | 1 + src/sensor/windows/SDL_windowssensor.c | 480 ++++++++++++++++++++ src/sensor/windows/SDL_windowssensor.h | 23 + 17 files changed, 770 insertions(+), 5 deletions(-) create mode 100644 VisualC/tests/testsensor/testsensor.vcxproj create mode 100644 src/sensor/windows/SDL_windowssensor.c create mode 100644 src/sensor/windows/SDL_windowssensor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 35f331171..93603de2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1417,6 +1417,13 @@ elseif(WINDOWS) set(HAVE_SDL_THREADS TRUE) endif() + if(SDL_SENSOR) + set(SDL_SENSOR_WINDOWS 1) + set(HAVE_SDL_SENSORS TRUE) + file(GLOB WINDOWS_SENSOR_SOURCES ${SDL2_SOURCE_DIR}/src/sensor/windows/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${WINDOWS_SENSOR_SOURCES}) + endif() + if(SDL_POWER) set(SDL_POWER_WINDOWS 1) set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/power/windows/SDL_syspower.c) diff --git a/VisualC/SDL.sln b/VisualC/SDL.sln index b30d4eb54..0b5650cc4 100644 --- a/VisualC/SDL.sln +++ b/VisualC/SDL.sln @@ -52,6 +52,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testvulkan", "tests\testvul EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testyuv", "tests\testyuv\testyuv.vcxproj", "{40FB7794-D3C3-4CFE-BCF4-A80C97635682}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsensor", "tests\testsensor\testsensor.vcxproj", "{C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -260,6 +262,14 @@ Global {40FB7794-D3C3-4CFE-BCF4-A80C97635682}.Release|Win32.Build.0 = Release|Win32 {40FB7794-D3C3-4CFE-BCF4-A80C97635682}.Release|x64.ActiveCfg = Release|x64 {40FB7794-D3C3-4CFE-BCF4-A80C97635682}.Release|x64.Build.0 = Release|x64 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4}.Debug|Win32.ActiveCfg = Debug|Win32 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4}.Debug|Win32.Build.0 = Debug|Win32 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4}.Debug|x64.ActiveCfg = Debug|x64 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4}.Debug|x64.Build.0 = Debug|x64 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4}.Release|Win32.ActiveCfg = Release|Win32 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4}.Release|Win32.Build.0 = Release|Win32 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4}.Release|x64.ActiveCfg = Release|x64 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -287,5 +297,6 @@ Global {55812185-D13C-4022-9C81-32E0F4A08306} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} {0D604DFD-AAB6-442C-9368-F91A344146AB} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} {40FB7794-D3C3-4CFE-BCF4-A80C97635682} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} EndGlobalSection EndGlobal diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 1c99a6c2d..1c968094f 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -352,6 +352,7 @@ + @@ -487,6 +488,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 79ed8305f..cbf6db581 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -326,6 +326,7 @@ + @@ -482,6 +483,7 @@ + diff --git a/VisualC/tests/testsensor/testsensor.vcxproj b/VisualC/tests/testsensor/testsensor.vcxproj new file mode 100644 index 000000000..8e35ff881 --- /dev/null +++ b/VisualC/tests/testsensor/testsensor.vcxproj @@ -0,0 +1,199 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A4} + testsensor + + + + Application + + + Application + + + Application + + + Application + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/testsensor.tlb + + + Disabled + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + OldStyle + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + Windows + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Debug/testsensor.tlb + + + Disabled + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + OldStyle + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + Windows + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/testsensor.tlb + + + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Windows + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Release/testsensor.tlb + + + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Windows + + + + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} + false + false + true + + + {da956fd3-e142-46f2-9dd5-c78bebb56b7a} + false + false + true + + + + + + + + + diff --git a/configure b/configure index d1fb9c634..60d536246 100755 --- a/configure +++ b/configure @@ -25018,6 +25018,15 @@ $as_echo "#define SDL_HAPTIC_DINPUT 1" >>confdefs.h have_haptic=yes fi fi + # Set up files for the sensor library + if test x$enable_sensor = xyes; then + +$as_echo "#define SDL_SENSOR_WINDOWS 1" >>confdefs.h + + SOURCES="$SOURCES $srcdir/src/sensor/windows/*.c" + have_sensor=yes + fi + # Set up files for the power library if test x$enable_power = xyes; then $as_echo "#define SDL_POWER_WINDOWS 1" >>confdefs.h @@ -25025,6 +25034,7 @@ $as_echo "#define SDL_POWER_WINDOWS 1" >>confdefs.h SOURCES="$SOURCES $srcdir/src/power/windows/SDL_syspower.c" have_power=yes fi + # Set up files for the filesystem library if test x$enable_filesystem = xyes; then $as_echo "#define SDL_FILESYSTEM_WINDOWS 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index 7c8eee6d0..3ada39bc1 100644 --- a/configure.ac +++ b/configure.ac @@ -3739,11 +3739,19 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau have_haptic=yes fi fi + # Set up files for the sensor library + if test x$enable_sensor = xyes; then + AC_DEFINE(SDL_SENSOR_WINDOWS, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/sensor/windows/*.c" + have_sensor=yes + fi + # Set up files for the power library if test x$enable_power = xyes; then AC_DEFINE(SDL_POWER_WINDOWS, 1, [ ]) SOURCES="$SOURCES $srcdir/src/power/windows/SDL_syspower.c" have_power=yes fi + # Set up files for the filesystem library if test x$enable_filesystem = xyes; then AC_DEFINE(SDL_FILESYSTEM_WINDOWS, 1, [ ]) SOURCES="$SOURCES $srcdir/src/filesystem/windows/SDL_sysfilesystem.c" diff --git a/include/SDL_config_windows.h b/include/SDL_config_windows.h index 16fa06f72..c3097bb5c 100644 --- a/include/SDL_config_windows.h +++ b/include/SDL_config_windows.h @@ -201,8 +201,8 @@ typedef unsigned int uintptr_t; #define SDL_HAPTIC_DINPUT 1 #define SDL_HAPTIC_XINPUT 1 -/* Enable the dummy sensor driver */ -#define SDL_SENSOR_DUMMY 1 +/* Enable the sensor driver */ +#define SDL_SENSOR_WINDOWS 1 /* Enable various shared object loading systems */ #define SDL_LOADSO_WINDOWS 1 diff --git a/include/SDL_sensor.h b/include/SDL_sensor.h index 5122ee153..83abf1ee4 100644 --- a/include/SDL_sensor.h +++ b/include/SDL_sensor.h @@ -121,6 +121,19 @@ typedef enum /* Function prototypes */ +/** + * Locking for multi-threaded access to the sensor API + * + * If you are using the sensor API or handling events from multiple threads + * you should use these locking functions to protect access to the sensors. + * + * In particular, you are guaranteed that the sensor list won't change, so + * the API functions that take a sensor index will be valid, and sensor + * events will not be delivered. + */ +extern DECLSPEC void SDLCALL SDL_LockSensors(void); +extern DECLSPEC void SDLCALL SDL_UnlockSensors(void); + /** * \brief Count the number of sensors attached to the system right now */ diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index e2a44b0be..28c800b96 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -757,3 +757,5 @@ #define SDL_JoystickSetVirtualButton SDL_JoystickSetVirtualButton_REAL #define SDL_JoystickSetVirtualHat SDL_JoystickSetVirtualHat_REAL #define SDL_GetErrorMsg SDL_GetErrorMsg_REAL +#define SDL_LockSensors SDL_LockSensors_REAL +#define SDL_UnlockSensors SDL_UnlockSensors_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 48e18044d..b08fe74b7 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -816,3 +816,5 @@ SDL_DYNAPI_PROC(int,SDL_JoystickSetVirtualAxis,(SDL_Joystick *a, int b, Sint16 c SDL_DYNAPI_PROC(int,SDL_JoystickSetVirtualButton,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_JoystickSetVirtualHat,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return) SDL_DYNAPI_PROC(char*,SDL_GetErrorMsg,(char *a, int b),(a,b),return) +SDL_DYNAPI_PROC(void,SDL_LockSensors,(void),(),) +SDL_DYNAPI_PROC(void,SDL_UnlockSensors,(void),(),) diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 68c3b1fc7..b0c5238f0 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -39,6 +39,9 @@ static SDL_SensorDriver *SDL_sensor_drivers[] = { #ifdef SDL_SENSOR_COREMOTION &SDL_COREMOTION_SensorDriver, #endif +#ifdef SDL_SENSOR_WINDOWS + &SDL_WINDOWS_SensorDriver, +#endif #if defined(SDL_SENSOR_DUMMY) || defined(SDL_SENSOR_DISABLED) &SDL_DUMMY_SensorDriver #endif @@ -48,7 +51,7 @@ static SDL_bool SDL_updating_sensor = SDL_FALSE; static SDL_mutex *SDL_sensor_lock = NULL; /* This needs to support recursive locks */ static SDL_atomic_t SDL_next_sensor_instance_id; -static void +void SDL_LockSensors(void) { if (SDL_sensor_lock) { @@ -56,7 +59,7 @@ SDL_LockSensors(void) } } -static void +void SDL_UnlockSensors(void) { if (SDL_sensor_lock) { diff --git a/src/sensor/SDL_syssensor.h b/src/sensor/SDL_syssensor.h index 394c68b56..d4d5c874e 100644 --- a/src/sensor/SDL_syssensor.h +++ b/src/sensor/SDL_syssensor.h @@ -98,8 +98,9 @@ typedef struct _SDL_SensorDriver /* The available sensor drivers */ extern SDL_SensorDriver SDL_ANDROID_SensorDriver; extern SDL_SensorDriver SDL_COREMOTION_SensorDriver; +extern SDL_SensorDriver SDL_WINDOWS_SensorDriver; extern SDL_SensorDriver SDL_DUMMY_SensorDriver; -#endif /* SDL_syssensor_c_h_ */ +#endif /* SDL_syssensor_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/sensor/android/SDL_androidsensor.c b/src/sensor/android/SDL_androidsensor.c index 165eb9b68..778fc262e 100644 --- a/src/sensor/android/SDL_androidsensor.c +++ b/src/sensor/android/SDL_androidsensor.c @@ -18,6 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "../../SDL_internal.h" #include "SDL_config.h" diff --git a/src/sensor/dummy/SDL_dummysensor.c b/src/sensor/dummy/SDL_dummysensor.c index aa55e1bf7..8d2db39a1 100644 --- a/src/sensor/dummy/SDL_dummysensor.c +++ b/src/sensor/dummy/SDL_dummysensor.c @@ -18,6 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "../../SDL_internal.h" #include "SDL_config.h" diff --git a/src/sensor/windows/SDL_windowssensor.c b/src/sensor/windows/SDL_windowssensor.c new file mode 100644 index 000000000..6ec80e1ed --- /dev/null +++ b/src/sensor/windows/SDL_windowssensor.c @@ -0,0 +1,480 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#include "SDL_config.h" + +#if defined(SDL_SENSOR_WINDOWS) + +#include "SDL_error.h" +#include "SDL_mutex.h" +#include "SDL_sensor.h" +#include "SDL_windowssensor.h" +#include "../SDL_syssensor.h" +#include "../../core/windows/SDL_windows.h" + +#define COBJMACROS +#include +#include +#include + +DEFINE_GUID(CLSID_SensorManager, 0x77A1C827, 0xFCD2, 0x4689, 0x89, 0x15, 0x9D, 0x61, 0x3C, 0xC5, 0xFA, 0x3E); +DEFINE_GUID(IID_SensorManager, 0xBD77DB67, 0x45A8, 0x42DC, 0x8D, 0x00, 0x6D, 0xCF, 0x15, 0xF8, 0x37, 0x7A); +DEFINE_GUID(IID_SensorManagerEvents, 0x9B3B0B86, 0x266A, 0x4AAD, 0xB2, 0x1F, 0xFD, 0xE5, 0x50, 0x10, 0x01, 0xB7); +DEFINE_GUID(IID_SensorEvents, 0x5D8DCC91, 0x4641, 0x47E7, 0xB7, 0xC3, 0xB7, 0x4F, 0x48, 0xA6, 0xC3, 0x91); + +DEFINE_PROPERTYKEY(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND, 0X3F8A69A2, 0X7C5, 0X4E48, 0XA9, 0X65, 0XCD, 0X79, 0X7A, 0XAB, 0X56, 0XD5, 10); //[VT_R8] +DEFINE_PROPERTYKEY(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND, 0X3F8A69A2, 0X7C5, 0X4E48, 0XA9, 0X65, 0XCD, 0X79, 0X7A, 0XAB, 0X56, 0XD5, 11); //[VT_R8] +DEFINE_PROPERTYKEY(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND, 0X3F8A69A2, 0X7C5, 0X4E48, 0XA9, 0X65, 0XCD, 0X79, 0X7A, 0XAB, 0X56, 0XD5, 12); //[VT_R8] + +typedef struct +{ + SDL_SensorID id; + ISensor *sensor; + SENSOR_ID sensor_id; + char *name; + SDL_SensorType type; + SDL_Sensor *sensor_opened; + +} SDL_Windows_Sensor; + +static SDL_bool SDL_windowscoinit; +static ISensorManager *SDL_sensor_manager; +static int SDL_num_sensors; +static SDL_Windows_Sensor *SDL_sensors; + +static int ConnectSensor(ISensor *sensor); +static int DisconnectSensor(ISensor *sensor); + +static HRESULT STDMETHODCALLTYPE ISensorManagerEventsVtbl_QueryInterface(ISensorManagerEvents * This, REFIID riid, void **ppvObject) +{ + if (!ppvObject) { + return E_INVALIDARG; + } + + *ppvObject = NULL; + if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_SensorManagerEvents)) { + *ppvObject = This; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE ISensorManagerEventsVtbl_AddRef(ISensorManagerEvents * This) +{ + return 1; +} + +static ULONG STDMETHODCALLTYPE ISensorManagerEventsVtbl_Release(ISensorManagerEvents * This) +{ + return 1; +} + +static HRESULT STDMETHODCALLTYPE ISensorManagerEventsVtbl_OnSensorEnter(ISensorManagerEvents * This, ISensor *pSensor, SensorState state) +{ + ConnectSensor(pSensor); + return S_OK; +} + +static ISensorManagerEventsVtbl sensor_manager_events_vtbl = { + ISensorManagerEventsVtbl_QueryInterface, + ISensorManagerEventsVtbl_AddRef, + ISensorManagerEventsVtbl_Release, + ISensorManagerEventsVtbl_OnSensorEnter +}; +static ISensorManagerEvents sensor_manager_events = { + &sensor_manager_events_vtbl +}; + +static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_QueryInterface(ISensorEvents * This, REFIID riid, void **ppvObject) +{ + if (!ppvObject) { + return E_INVALIDARG; + } + + *ppvObject = NULL; + if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_SensorEvents)) { + *ppvObject = This; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE ISensorEventsVtbl_AddRef(ISensorEvents * This) +{ + return 1; +} + +static ULONG STDMETHODCALLTYPE ISensorEventsVtbl_Release(ISensorEvents * This) +{ + return 1; +} + +static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnStateChanged(ISensorEvents * This, ISensor *pSensor, SensorState state) +{ +#ifdef DEBUG_SENSORS + int i; + + SDL_LockSensors(); + for (i = 0; i < SDL_num_sensors; ++i) { + if (pSensor == SDL_sensors[i].sensor) { + SDL_Log("Sensor %s state changed to %d\n", SDL_sensors[i].name, state); + } + } + SDL_UnlockSensors(); +#endif + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnDataUpdated(ISensorEvents * This, ISensor *pSensor, ISensorDataReport *pNewData) +{ + int i; + + SDL_LockSensors(); + for (i = 0; i < SDL_num_sensors; ++i) { + if (pSensor == SDL_sensors[i].sensor) { + if (SDL_sensors[i].sensor_opened) { + HRESULT hrX, hrY, hrZ; + PROPVARIANT valueX, valueY, valueZ; + +#ifdef DEBUG_SENSORS + SDL_Log("Sensor %s data updated\n", SDL_sensors[i].name); +#endif + switch (SDL_sensors[i].type) { + case SDL_SENSOR_ACCEL: + hrX = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ACCELERATION_X_G, &valueX); + hrY = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ACCELERATION_Y_G, &valueY); + hrZ = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ACCELERATION_Z_G, &valueZ); + if (SUCCEEDED(hrX) && SUCCEEDED(hrY) && SUCCEEDED(hrZ) && + valueX.vt == VT_R8 && valueY.vt == VT_R8 && valueZ.vt == VT_R8) { + float values[3]; + + values[0] = (float)valueX.dblVal; + values[1] = (float)valueY.dblVal; + values[2] = (float)valueZ.dblVal; + SDL_PrivateSensorUpdate(SDL_sensors[i].sensor_opened, values, 3); + } + break; + case SDL_SENSOR_GYRO: + hrX = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND, &valueX); + hrY = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND, &valueY); + hrZ = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND, &valueZ); + if (SUCCEEDED(hrX) && SUCCEEDED(hrY) && SUCCEEDED(hrZ) && + valueX.vt == VT_R8 && valueY.vt == VT_R8 && valueZ.vt == VT_R8) { + float values[3]; + + values[0] = (float)(valueX.dblVal * (M_PI / 180.0)); + values[1] = (float)(valueY.dblVal * (M_PI / 180.0)); + values[2] = (float)(valueZ.dblVal * (M_PI / 180.0)); + SDL_PrivateSensorUpdate(SDL_sensors[i].sensor_opened, values, 3); + } + break; + default: + /* FIXME: Need to know how to interpret the data for this sensor */ + break; + } + } + break; + } + } + SDL_UnlockSensors(); + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnEvent(ISensorEvents * This, ISensor *pSensor, REFGUID eventID, IPortableDeviceValues *pEventData) +{ +#ifdef DEBUG_SENSORS + int i; + + SDL_LockSensors(); + for (i = 0; i < SDL_num_sensors; ++i) { + if (pSensor == SDL_sensors[i].sensor) { + SDL_Log("Sensor %s event occurred\n", SDL_sensors[i].name); + } + } + SDL_UnlockSensors(); +#endif + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnLeave(ISensorEvents * This, REFSENSOR_ID ID) +{ + int i; + + SDL_LockSensors(); + for (i = 0; i < SDL_num_sensors; ++i) { + if (WIN_IsEqualIID(ID, &SDL_sensors[i].sensor_id)) { +#ifdef DEBUG_SENSORS + SDL_Log("Sensor %s disconnected\n", SDL_sensors[i].name); +#endif + DisconnectSensor(SDL_sensors[i].sensor); + } + } + SDL_UnlockSensors(); + + return S_OK; +} + +static ISensorEventsVtbl sensor_events_vtbl = { + ISensorEventsVtbl_QueryInterface, + ISensorEventsVtbl_AddRef, + ISensorEventsVtbl_Release, + ISensorEventsVtbl_OnStateChanged, + ISensorEventsVtbl_OnDataUpdated, + ISensorEventsVtbl_OnEvent, + ISensorEventsVtbl_OnLeave +}; +static ISensorEvents sensor_events = { + &sensor_events_vtbl +}; + +static int ConnectSensor(ISensor *sensor) +{ + SDL_Windows_Sensor *new_sensor, *new_sensors; + HRESULT hr; + SENSOR_ID sensor_id; + SENSOR_TYPE_ID type_id; + SDL_SensorType type; + BSTR bstr_name = NULL; + char *name; + + hr = ISensor_GetID(sensor, &sensor_id); + if (FAILED(hr)) { + return SDL_SetError("Couldn't get sensor ID: 0x%.4x", hr); + } + + hr = ISensor_GetType(sensor, &type_id); + if (FAILED(hr)) { + return SDL_SetError("Couldn't get sensor type: 0x%.4x", hr); + } + + if (WIN_IsEqualIID(&type_id, &SENSOR_TYPE_ACCELEROMETER_3D)) { + type = SDL_SENSOR_ACCEL; + } else if (WIN_IsEqualIID(&type_id, &SENSOR_TYPE_GYROMETER_3D)) { + type = SDL_SENSOR_GYRO; + } else { + return SDL_SetError("Unknown sensor type"); + } + + hr = ISensor_GetFriendlyName(sensor, &bstr_name); + if (SUCCEEDED(hr) && bstr_name) { + name = WIN_StringToUTF8(bstr_name); + } else { + name = SDL_strdup("Unknown Sensor"); + } + if (!name) { + return SDL_OutOfMemory(); + } + + SDL_LockSensors(); + new_sensors = (SDL_Windows_Sensor *)SDL_realloc(SDL_sensors, (SDL_num_sensors + 1) * sizeof(SDL_Windows_Sensor)); + if (new_sensors == NULL) { + SDL_UnlockSensors(); + return SDL_OutOfMemory(); + } + + ISensor_AddRef(sensor); + ISensor_SetEventSink(sensor, &sensor_events); + + SDL_sensors = new_sensors; + new_sensor = &SDL_sensors[SDL_num_sensors]; + ++SDL_num_sensors; + + new_sensor->id = SDL_GetNextSensorInstanceID(); + new_sensor->sensor = sensor; + new_sensor->type = type; + new_sensor->name = name; + + SDL_UnlockSensors(); + + return 0; +} + +static int DisconnectSensor(ISensor *sensor) +{ + SDL_Windows_Sensor *old_sensor; + int i; + + SDL_LockSensors(); + for (i = 0; i < SDL_num_sensors; ++i) { + old_sensor = &SDL_sensors[i]; + if (sensor == old_sensor->sensor) { + ISensor_SetEventSink(sensor, NULL); + ISensor_Release(sensor); + SDL_free(old_sensor->name); + --SDL_num_sensors; + if (i < SDL_num_sensors) { + SDL_memmove(&SDL_sensors[i], &SDL_sensors[i + 1], (SDL_num_sensors - i) * sizeof(SDL_sensors[i])); + } + break; + } + } + SDL_UnlockSensors(); + + return 0; +} + +static int +SDL_WINDOWS_SensorInit(void) +{ + HRESULT hr; + ISensorCollection *sensor_collection = NULL; + + while (!IsDebuggerPresent()) Sleep(100); + + if (WIN_CoInitialize() == S_OK) { + SDL_windowscoinit = SDL_TRUE; + } + + hr = CoCreateInstance(&CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, &IID_SensorManager, &SDL_sensor_manager); + if (FAILED(hr)) { + return SDL_SetError("Couldn't create the sensor manager: 0x%.4x", hr); + } + + hr = ISensorManager_SetEventSink(SDL_sensor_manager, &sensor_manager_events); + if (FAILED(hr)) { + ISensorManager_Release(SDL_sensor_manager); + return SDL_SetError("Couldn't set the sensor manager event sink: 0x%.4x", hr); + } + + hr = ISensorManager_GetSensorsByCategory(SDL_sensor_manager, &SENSOR_CATEGORY_ALL, &sensor_collection); + if (SUCCEEDED(hr)) { + ULONG i, count; + + hr = ISensorCollection_GetCount(sensor_collection, &count); + if (SUCCEEDED(hr)) { + for (i = 0; i < count; ++i) { + ISensor *sensor; + + hr = ISensorCollection_GetAt(sensor_collection, i, &sensor); + if (SUCCEEDED(hr)) { + SensorState state; + + hr = ISensor_GetState(sensor, &state); + if (SUCCEEDED(hr)) { + ISensorManagerEventsVtbl_OnSensorEnter(&sensor_manager_events, sensor, state); + } + ISensorManager_Release(sensor); + } + } + } + ISensorCollection_Release(sensor_collection); + } + return 0; +} + +static int +SDL_WINDOWS_SensorGetCount(void) +{ + return SDL_num_sensors; +} + +static void +SDL_WINDOWS_SensorDetect(void) +{ +} + +static const char * +SDL_WINDOWS_SensorGetDeviceName(int device_index) +{ + return SDL_sensors[device_index].name; +} + +static SDL_SensorType +SDL_WINDOWS_SensorGetDeviceType(int device_index) +{ + return SDL_sensors[device_index].type; +} + +static int +SDL_WINDOWS_SensorGetDeviceNonPortableType(int device_index) +{ + return -1; +} + +static SDL_SensorID +SDL_WINDOWS_SensorGetDeviceInstanceID(int device_index) +{ + return SDL_sensors[device_index].id; +} + +static int +SDL_WINDOWS_SensorOpen(SDL_Sensor *sensor, int device_index) +{ + SDL_sensors[device_index].sensor_opened = sensor; + return 0; +} + +static void +SDL_WINDOWS_SensorUpdate(SDL_Sensor *sensor) +{ +} + +static void +SDL_WINDOWS_SensorClose(SDL_Sensor *sensor) +{ + int i; + + for (i = 0; i < SDL_num_sensors; ++i) { + if (sensor == SDL_sensors[i].sensor_opened) { + SDL_sensors[i].sensor_opened = NULL; + break; + } + } +} + +static void +SDL_WINDOWS_SensorQuit(void) +{ + while (SDL_num_sensors > 0) { + DisconnectSensor(SDL_sensors[0].sensor); + } + + if (SDL_sensor_manager) { + ISensorManager_SetEventSink(SDL_sensor_manager, NULL); + ISensorManager_Release(SDL_sensor_manager); + SDL_sensor_manager = NULL; + } + + if (SDL_windowscoinit) { + WIN_CoUninitialize(); + } +} + +SDL_SensorDriver SDL_WINDOWS_SensorDriver = +{ + SDL_WINDOWS_SensorInit, + SDL_WINDOWS_SensorGetCount, + SDL_WINDOWS_SensorDetect, + SDL_WINDOWS_SensorGetDeviceName, + SDL_WINDOWS_SensorGetDeviceType, + SDL_WINDOWS_SensorGetDeviceNonPortableType, + SDL_WINDOWS_SensorGetDeviceInstanceID, + SDL_WINDOWS_SensorOpen, + SDL_WINDOWS_SensorUpdate, + SDL_WINDOWS_SensorClose, + SDL_WINDOWS_SensorQuit, +}; + +#endif /* SDL_SENSOR_WINDOWS */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/sensor/windows/SDL_windowssensor.h b/src/sensor/windows/SDL_windowssensor.h new file mode 100644 index 000000000..ee66f2fe0 --- /dev/null +++ b/src/sensor/windows/SDL_windowssensor.h @@ -0,0 +1,23 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +/* vi: set ts=4 sw=4 expandtab: */