SDL_windowssensor.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "../../SDL_internal.h"
  19. #include "SDL_config.h"
  20. #if defined(SDL_SENSOR_WINDOWS)
  21. #include "SDL_error.h"
  22. #include "SDL_mutex.h"
  23. #include "SDL_sensor.h"
  24. #include "SDL_windowssensor.h"
  25. #include "../SDL_syssensor.h"
  26. #include "../../core/windows/SDL_windows.h"
  27. #define COBJMACROS
  28. #include <InitGuid.h>
  29. #include <SensorsApi.h>
  30. #include <Sensors.h>
  31. DEFINE_GUID(CLSID_SensorManager, 0x77A1C827, 0xFCD2, 0x4689, 0x89, 0x15, 0x9D, 0x61, 0x3C, 0xC5, 0xFA, 0x3E);
  32. DEFINE_GUID(IID_SensorManager, 0xBD77DB67, 0x45A8, 0x42DC, 0x8D, 0x00, 0x6D, 0xCF, 0x15, 0xF8, 0x37, 0x7A);
  33. DEFINE_GUID(IID_SensorManagerEvents, 0x9B3B0B86, 0x266A, 0x4AAD, 0xB2, 0x1F, 0xFD, 0xE5, 0x50, 0x10, 0x01, 0xB7);
  34. DEFINE_GUID(IID_SensorEvents, 0x5D8DCC91, 0x4641, 0x47E7, 0xB7, 0xC3, 0xB7, 0x4F, 0x48, 0xA6, 0xC3, 0x91);
  35. 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]
  36. 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]
  37. 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]
  38. typedef struct
  39. {
  40. SDL_SensorID id;
  41. ISensor *sensor;
  42. SENSOR_ID sensor_id;
  43. char *name;
  44. SDL_SensorType type;
  45. SDL_Sensor *sensor_opened;
  46. } SDL_Windows_Sensor;
  47. static SDL_bool SDL_windowscoinit;
  48. static ISensorManager *SDL_sensor_manager;
  49. static int SDL_num_sensors;
  50. static SDL_Windows_Sensor *SDL_sensors;
  51. static int ConnectSensor(ISensor *sensor);
  52. static int DisconnectSensor(ISensor *sensor);
  53. static HRESULT STDMETHODCALLTYPE ISensorManagerEventsVtbl_QueryInterface(ISensorManagerEvents * This, REFIID riid, void **ppvObject)
  54. {
  55. if (!ppvObject) {
  56. return E_INVALIDARG;
  57. }
  58. *ppvObject = NULL;
  59. if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_SensorManagerEvents)) {
  60. *ppvObject = This;
  61. return S_OK;
  62. }
  63. return E_NOINTERFACE;
  64. }
  65. static ULONG STDMETHODCALLTYPE ISensorManagerEventsVtbl_AddRef(ISensorManagerEvents * This)
  66. {
  67. return 1;
  68. }
  69. static ULONG STDMETHODCALLTYPE ISensorManagerEventsVtbl_Release(ISensorManagerEvents * This)
  70. {
  71. return 1;
  72. }
  73. static HRESULT STDMETHODCALLTYPE ISensorManagerEventsVtbl_OnSensorEnter(ISensorManagerEvents * This, ISensor *pSensor, SensorState state)
  74. {
  75. ConnectSensor(pSensor);
  76. return S_OK;
  77. }
  78. static ISensorManagerEventsVtbl sensor_manager_events_vtbl = {
  79. ISensorManagerEventsVtbl_QueryInterface,
  80. ISensorManagerEventsVtbl_AddRef,
  81. ISensorManagerEventsVtbl_Release,
  82. ISensorManagerEventsVtbl_OnSensorEnter
  83. };
  84. static ISensorManagerEvents sensor_manager_events = {
  85. &sensor_manager_events_vtbl
  86. };
  87. static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_QueryInterface(ISensorEvents * This, REFIID riid, void **ppvObject)
  88. {
  89. if (!ppvObject) {
  90. return E_INVALIDARG;
  91. }
  92. *ppvObject = NULL;
  93. if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_SensorEvents)) {
  94. *ppvObject = This;
  95. return S_OK;
  96. }
  97. return E_NOINTERFACE;
  98. }
  99. static ULONG STDMETHODCALLTYPE ISensorEventsVtbl_AddRef(ISensorEvents * This)
  100. {
  101. return 1;
  102. }
  103. static ULONG STDMETHODCALLTYPE ISensorEventsVtbl_Release(ISensorEvents * This)
  104. {
  105. return 1;
  106. }
  107. static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnStateChanged(ISensorEvents * This, ISensor *pSensor, SensorState state)
  108. {
  109. #ifdef DEBUG_SENSORS
  110. int i;
  111. SDL_LockSensors();
  112. for (i = 0; i < SDL_num_sensors; ++i) {
  113. if (pSensor == SDL_sensors[i].sensor) {
  114. SDL_Log("Sensor %s state changed to %d\n", SDL_sensors[i].name, state);
  115. }
  116. }
  117. SDL_UnlockSensors();
  118. #endif
  119. return S_OK;
  120. }
  121. static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnDataUpdated(ISensorEvents * This, ISensor *pSensor, ISensorDataReport *pNewData)
  122. {
  123. int i;
  124. SDL_LockSensors();
  125. for (i = 0; i < SDL_num_sensors; ++i) {
  126. if (pSensor == SDL_sensors[i].sensor) {
  127. if (SDL_sensors[i].sensor_opened) {
  128. HRESULT hrX, hrY, hrZ;
  129. PROPVARIANT valueX, valueY, valueZ;
  130. #ifdef DEBUG_SENSORS
  131. SDL_Log("Sensor %s data updated\n", SDL_sensors[i].name);
  132. #endif
  133. switch (SDL_sensors[i].type) {
  134. case SDL_SENSOR_ACCEL:
  135. hrX = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ACCELERATION_X_G, &valueX);
  136. hrY = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ACCELERATION_Y_G, &valueY);
  137. hrZ = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ACCELERATION_Z_G, &valueZ);
  138. if (SUCCEEDED(hrX) && SUCCEEDED(hrY) && SUCCEEDED(hrZ) &&
  139. valueX.vt == VT_R8 && valueY.vt == VT_R8 && valueZ.vt == VT_R8) {
  140. float values[3];
  141. values[0] = (float)valueX.dblVal;
  142. values[1] = (float)valueY.dblVal;
  143. values[2] = (float)valueZ.dblVal;
  144. SDL_PrivateSensorUpdate(SDL_sensors[i].sensor_opened, values, 3);
  145. }
  146. break;
  147. case SDL_SENSOR_GYRO:
  148. hrX = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND, &valueX);
  149. hrY = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND, &valueY);
  150. hrZ = ISensorDataReport_GetSensorValue(pNewData, &SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND, &valueZ);
  151. if (SUCCEEDED(hrX) && SUCCEEDED(hrY) && SUCCEEDED(hrZ) &&
  152. valueX.vt == VT_R8 && valueY.vt == VT_R8 && valueZ.vt == VT_R8) {
  153. float values[3];
  154. values[0] = (float)(valueX.dblVal * (M_PI / 180.0));
  155. values[1] = (float)(valueY.dblVal * (M_PI / 180.0));
  156. values[2] = (float)(valueZ.dblVal * (M_PI / 180.0));
  157. SDL_PrivateSensorUpdate(SDL_sensors[i].sensor_opened, values, 3);
  158. }
  159. break;
  160. default:
  161. /* FIXME: Need to know how to interpret the data for this sensor */
  162. break;
  163. }
  164. }
  165. break;
  166. }
  167. }
  168. SDL_UnlockSensors();
  169. return S_OK;
  170. }
  171. static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnEvent(ISensorEvents * This, ISensor *pSensor, REFGUID eventID, IPortableDeviceValues *pEventData)
  172. {
  173. #ifdef DEBUG_SENSORS
  174. int i;
  175. SDL_LockSensors();
  176. for (i = 0; i < SDL_num_sensors; ++i) {
  177. if (pSensor == SDL_sensors[i].sensor) {
  178. SDL_Log("Sensor %s event occurred\n", SDL_sensors[i].name);
  179. }
  180. }
  181. SDL_UnlockSensors();
  182. #endif
  183. return S_OK;
  184. }
  185. static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnLeave(ISensorEvents * This, REFSENSOR_ID ID)
  186. {
  187. int i;
  188. SDL_LockSensors();
  189. for (i = 0; i < SDL_num_sensors; ++i) {
  190. if (WIN_IsEqualIID(ID, &SDL_sensors[i].sensor_id)) {
  191. #ifdef DEBUG_SENSORS
  192. SDL_Log("Sensor %s disconnected\n", SDL_sensors[i].name);
  193. #endif
  194. DisconnectSensor(SDL_sensors[i].sensor);
  195. }
  196. }
  197. SDL_UnlockSensors();
  198. return S_OK;
  199. }
  200. static ISensorEventsVtbl sensor_events_vtbl = {
  201. ISensorEventsVtbl_QueryInterface,
  202. ISensorEventsVtbl_AddRef,
  203. ISensorEventsVtbl_Release,
  204. ISensorEventsVtbl_OnStateChanged,
  205. ISensorEventsVtbl_OnDataUpdated,
  206. ISensorEventsVtbl_OnEvent,
  207. ISensorEventsVtbl_OnLeave
  208. };
  209. static ISensorEvents sensor_events = {
  210. &sensor_events_vtbl
  211. };
  212. static int ConnectSensor(ISensor *sensor)
  213. {
  214. SDL_Windows_Sensor *new_sensor, *new_sensors;
  215. HRESULT hr;
  216. SENSOR_ID sensor_id;
  217. SENSOR_TYPE_ID type_id;
  218. SDL_SensorType type;
  219. BSTR bstr_name = NULL;
  220. char *name;
  221. hr = ISensor_GetID(sensor, &sensor_id);
  222. if (FAILED(hr)) {
  223. return SDL_SetError("Couldn't get sensor ID: 0x%.4x", hr);
  224. }
  225. hr = ISensor_GetType(sensor, &type_id);
  226. if (FAILED(hr)) {
  227. return SDL_SetError("Couldn't get sensor type: 0x%.4x", hr);
  228. }
  229. if (WIN_IsEqualIID(&type_id, &SENSOR_TYPE_ACCELEROMETER_3D)) {
  230. type = SDL_SENSOR_ACCEL;
  231. } else if (WIN_IsEqualIID(&type_id, &SENSOR_TYPE_GYROMETER_3D)) {
  232. type = SDL_SENSOR_GYRO;
  233. } else {
  234. return SDL_SetError("Unknown sensor type");
  235. }
  236. hr = ISensor_GetFriendlyName(sensor, &bstr_name);
  237. if (SUCCEEDED(hr) && bstr_name) {
  238. name = WIN_StringToUTF8(bstr_name);
  239. } else {
  240. name = SDL_strdup("Unknown Sensor");
  241. }
  242. if (!name) {
  243. return SDL_OutOfMemory();
  244. }
  245. SDL_LockSensors();
  246. new_sensors = (SDL_Windows_Sensor *)SDL_realloc(SDL_sensors, (SDL_num_sensors + 1) * sizeof(SDL_Windows_Sensor));
  247. if (new_sensors == NULL) {
  248. SDL_UnlockSensors();
  249. return SDL_OutOfMemory();
  250. }
  251. ISensor_AddRef(sensor);
  252. ISensor_SetEventSink(sensor, &sensor_events);
  253. SDL_sensors = new_sensors;
  254. new_sensor = &SDL_sensors[SDL_num_sensors];
  255. ++SDL_num_sensors;
  256. new_sensor->id = SDL_GetNextSensorInstanceID();
  257. new_sensor->sensor = sensor;
  258. new_sensor->type = type;
  259. new_sensor->name = name;
  260. SDL_UnlockSensors();
  261. return 0;
  262. }
  263. static int DisconnectSensor(ISensor *sensor)
  264. {
  265. SDL_Windows_Sensor *old_sensor;
  266. int i;
  267. SDL_LockSensors();
  268. for (i = 0; i < SDL_num_sensors; ++i) {
  269. old_sensor = &SDL_sensors[i];
  270. if (sensor == old_sensor->sensor) {
  271. ISensor_SetEventSink(sensor, NULL);
  272. ISensor_Release(sensor);
  273. SDL_free(old_sensor->name);
  274. --SDL_num_sensors;
  275. if (i < SDL_num_sensors) {
  276. SDL_memmove(&SDL_sensors[i], &SDL_sensors[i + 1], (SDL_num_sensors - i) * sizeof(SDL_sensors[i]));
  277. }
  278. break;
  279. }
  280. }
  281. SDL_UnlockSensors();
  282. return 0;
  283. }
  284. static int
  285. SDL_WINDOWS_SensorInit(void)
  286. {
  287. HRESULT hr;
  288. ISensorCollection *sensor_collection = NULL;
  289. while (!IsDebuggerPresent()) Sleep(100);
  290. if (WIN_CoInitialize() == S_OK) {
  291. SDL_windowscoinit = SDL_TRUE;
  292. }
  293. hr = CoCreateInstance(&CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, &IID_SensorManager, &SDL_sensor_manager);
  294. if (FAILED(hr)) {
  295. return SDL_SetError("Couldn't create the sensor manager: 0x%.4x", hr);
  296. }
  297. hr = ISensorManager_SetEventSink(SDL_sensor_manager, &sensor_manager_events);
  298. if (FAILED(hr)) {
  299. ISensorManager_Release(SDL_sensor_manager);
  300. return SDL_SetError("Couldn't set the sensor manager event sink: 0x%.4x", hr);
  301. }
  302. hr = ISensorManager_GetSensorsByCategory(SDL_sensor_manager, &SENSOR_CATEGORY_ALL, &sensor_collection);
  303. if (SUCCEEDED(hr)) {
  304. ULONG i, count;
  305. hr = ISensorCollection_GetCount(sensor_collection, &count);
  306. if (SUCCEEDED(hr)) {
  307. for (i = 0; i < count; ++i) {
  308. ISensor *sensor;
  309. hr = ISensorCollection_GetAt(sensor_collection, i, &sensor);
  310. if (SUCCEEDED(hr)) {
  311. SensorState state;
  312. hr = ISensor_GetState(sensor, &state);
  313. if (SUCCEEDED(hr)) {
  314. ISensorManagerEventsVtbl_OnSensorEnter(&sensor_manager_events, sensor, state);
  315. }
  316. ISensorManager_Release(sensor);
  317. }
  318. }
  319. }
  320. ISensorCollection_Release(sensor_collection);
  321. }
  322. return 0;
  323. }
  324. static int
  325. SDL_WINDOWS_SensorGetCount(void)
  326. {
  327. return SDL_num_sensors;
  328. }
  329. static void
  330. SDL_WINDOWS_SensorDetect(void)
  331. {
  332. }
  333. static const char *
  334. SDL_WINDOWS_SensorGetDeviceName(int device_index)
  335. {
  336. return SDL_sensors[device_index].name;
  337. }
  338. static SDL_SensorType
  339. SDL_WINDOWS_SensorGetDeviceType(int device_index)
  340. {
  341. return SDL_sensors[device_index].type;
  342. }
  343. static int
  344. SDL_WINDOWS_SensorGetDeviceNonPortableType(int device_index)
  345. {
  346. return -1;
  347. }
  348. static SDL_SensorID
  349. SDL_WINDOWS_SensorGetDeviceInstanceID(int device_index)
  350. {
  351. return SDL_sensors[device_index].id;
  352. }
  353. static int
  354. SDL_WINDOWS_SensorOpen(SDL_Sensor *sensor, int device_index)
  355. {
  356. SDL_sensors[device_index].sensor_opened = sensor;
  357. return 0;
  358. }
  359. static void
  360. SDL_WINDOWS_SensorUpdate(SDL_Sensor *sensor)
  361. {
  362. }
  363. static void
  364. SDL_WINDOWS_SensorClose(SDL_Sensor *sensor)
  365. {
  366. int i;
  367. for (i = 0; i < SDL_num_sensors; ++i) {
  368. if (sensor == SDL_sensors[i].sensor_opened) {
  369. SDL_sensors[i].sensor_opened = NULL;
  370. break;
  371. }
  372. }
  373. }
  374. static void
  375. SDL_WINDOWS_SensorQuit(void)
  376. {
  377. while (SDL_num_sensors > 0) {
  378. DisconnectSensor(SDL_sensors[0].sensor);
  379. }
  380. if (SDL_sensor_manager) {
  381. ISensorManager_SetEventSink(SDL_sensor_manager, NULL);
  382. ISensorManager_Release(SDL_sensor_manager);
  383. SDL_sensor_manager = NULL;
  384. }
  385. if (SDL_windowscoinit) {
  386. WIN_CoUninitialize();
  387. }
  388. }
  389. SDL_SensorDriver SDL_WINDOWS_SensorDriver =
  390. {
  391. SDL_WINDOWS_SensorInit,
  392. SDL_WINDOWS_SensorGetCount,
  393. SDL_WINDOWS_SensorDetect,
  394. SDL_WINDOWS_SensorGetDeviceName,
  395. SDL_WINDOWS_SensorGetDeviceType,
  396. SDL_WINDOWS_SensorGetDeviceNonPortableType,
  397. SDL_WINDOWS_SensorGetDeviceInstanceID,
  398. SDL_WINDOWS_SensorOpen,
  399. SDL_WINDOWS_SensorUpdate,
  400. SDL_WINDOWS_SensorClose,
  401. SDL_WINDOWS_SensorQuit,
  402. };
  403. #endif /* SDL_SENSOR_WINDOWS */
  404. /* vi: set ts=4 sw=4 expandtab: */