src/sensor/windows/SDL_windowssensor.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 18 Apr 2020 21:41:37 -0700
changeset 13768 5e7c6765ceda
parent 13716 d2647d9e93c7
child 13776 74f7ed12a32b
permissions -rw-r--r--
Added a Windows Gaming Input joystick driver

This driver supports the Razer Atrox Arcade Stick

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