diff --git a/CMakeLists.txt b/CMakeLists.txt
index 35f331171f..93603de2cd 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 b30d4eb543..0b5650cc4b 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 1c99a6c2d9..1c968094ff 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 79ed8305fd..cbf6db5818 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 0000000000..8e35ff8818
--- /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 d1fb9c634d..60d536246b 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 7c8eee6d09..3ada39bc13 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 16fa06f727..c3097bb5c1 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 5122ee153c..83abf1ee45 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 e2a44b0be7..28c800b96e 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 48e18044d1..b08fe74b74 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 68c3b1fc78..b0c5238f00 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 394c68b56e..d4d5c874e2 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 165eb9b685..778fc262e7 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 aa55e1bf78..8d2db39a15 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 0000000000..6ec80e1edd
--- /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 0000000000..ee66f2fe0b
--- /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: */