src/joystick/windows/SDL_dinputjoystick.c
author Ryan C. Gordon
Tue, 24 Jan 2017 16:18:25 -0500
changeset 10850 c9dc0068b0e7
parent 10821 b0b8395f5cf9
child 11201 813a8510bd0c
permissions -rw-r--r--
configure: report libsamplerate support status.
slouken@1895
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@1895
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1895
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1895
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1895
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@1895
    22
icculus@9659
    23
#include "../SDL_sysjoystick.h"
icculus@9659
    24
icculus@9658
    25
#if SDL_JOYSTICK_DINPUT
icculus@9658
    26
slouken@8972
    27
#include "SDL_windowsjoystick_c.h"
slouken@8972
    28
#include "SDL_dinputjoystick_c.h"
slouken@8972
    29
#include "SDL_xinputjoystick_c.h"
slouken@1895
    30
slouken@2761
    31
#ifndef DIDFT_OPTIONAL
slouken@7191
    32
#define DIDFT_OPTIONAL      0x80000000
slouken@2761
    33
#endif
slouken@2761
    34
slouken@7191
    35
#define INPUT_QSIZE 32      /* Buffer up to 32 input messages */
slouken@10724
    36
#define JOY_AXIS_THRESHOLD  (((SDL_JOYSTICK_AXIS_MAX)-(SDL_JOYSTICK_AXIS_MIN))/100)   /* 1% motion */
slouken@1895
    37
slouken@2198
    38
/* external variables referenced. */
slouken@2713
    39
extern HWND SDL_HelperWindow;
slouken@2198
    40
slouken@2198
    41
/* local variables */
icculus@5591
    42
static SDL_bool coinitialized = SDL_FALSE;
icculus@6716
    43
static LPDIRECTINPUT8 dinput = NULL;
slouken@8972
    44
static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
slouken@8972
    45
static UINT SDL_RawDevListCount = 0;
slouken@2198
    46
slouken@7191
    47
/* Taken from Wine - Thanks! */
slouken@8972
    48
static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
slouken@8972
    49
        { &GUID_XAxis, DIJOFS_X, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    50
        { &GUID_YAxis, DIJOFS_Y, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    51
        { &GUID_ZAxis, DIJOFS_Z, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    52
        { &GUID_RxAxis, DIJOFS_RX, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    53
        { &GUID_RyAxis, DIJOFS_RY, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    54
        { &GUID_RzAxis, DIJOFS_RZ, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    55
        { &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    56
        { &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    57
        { &GUID_POV, DIJOFS_POV(0), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    58
        { &GUID_POV, DIJOFS_POV(1), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    59
        { &GUID_POV, DIJOFS_POV(2), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    60
        { &GUID_POV, DIJOFS_POV(3), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    61
        { NULL, DIJOFS_BUTTON(0), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    62
        { NULL, DIJOFS_BUTTON(1), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    63
        { NULL, DIJOFS_BUTTON(2), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    64
        { NULL, DIJOFS_BUTTON(3), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    65
        { NULL, DIJOFS_BUTTON(4), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    66
        { NULL, DIJOFS_BUTTON(5), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    67
        { NULL, DIJOFS_BUTTON(6), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    68
        { NULL, DIJOFS_BUTTON(7), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    69
        { NULL, DIJOFS_BUTTON(8), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    70
        { NULL, DIJOFS_BUTTON(9), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    71
        { NULL, DIJOFS_BUTTON(10), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    72
        { NULL, DIJOFS_BUTTON(11), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    73
        { NULL, DIJOFS_BUTTON(12), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    74
        { NULL, DIJOFS_BUTTON(13), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    75
        { NULL, DIJOFS_BUTTON(14), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    76
        { NULL, DIJOFS_BUTTON(15), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    77
        { NULL, DIJOFS_BUTTON(16), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    78
        { NULL, DIJOFS_BUTTON(17), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    79
        { NULL, DIJOFS_BUTTON(18), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    80
        { NULL, DIJOFS_BUTTON(19), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    81
        { NULL, DIJOFS_BUTTON(20), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    82
        { NULL, DIJOFS_BUTTON(21), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    83
        { NULL, DIJOFS_BUTTON(22), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    84
        { NULL, DIJOFS_BUTTON(23), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    85
        { NULL, DIJOFS_BUTTON(24), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    86
        { NULL, DIJOFS_BUTTON(25), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    87
        { NULL, DIJOFS_BUTTON(26), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    88
        { NULL, DIJOFS_BUTTON(27), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    89
        { NULL, DIJOFS_BUTTON(28), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    90
        { NULL, DIJOFS_BUTTON(29), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    91
        { NULL, DIJOFS_BUTTON(30), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    92
        { NULL, DIJOFS_BUTTON(31), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    93
        { NULL, DIJOFS_BUTTON(32), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    94
        { NULL, DIJOFS_BUTTON(33), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    95
        { NULL, DIJOFS_BUTTON(34), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    96
        { NULL, DIJOFS_BUTTON(35), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    97
        { NULL, DIJOFS_BUTTON(36), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    98
        { NULL, DIJOFS_BUTTON(37), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
    99
        { NULL, DIJOFS_BUTTON(38), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   100
        { NULL, DIJOFS_BUTTON(39), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   101
        { NULL, DIJOFS_BUTTON(40), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   102
        { NULL, DIJOFS_BUTTON(41), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   103
        { NULL, DIJOFS_BUTTON(42), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   104
        { NULL, DIJOFS_BUTTON(43), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   105
        { NULL, DIJOFS_BUTTON(44), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   106
        { NULL, DIJOFS_BUTTON(45), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   107
        { NULL, DIJOFS_BUTTON(46), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   108
        { NULL, DIJOFS_BUTTON(47), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   109
        { NULL, DIJOFS_BUTTON(48), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   110
        { NULL, DIJOFS_BUTTON(49), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   111
        { NULL, DIJOFS_BUTTON(50), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   112
        { NULL, DIJOFS_BUTTON(51), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   113
        { NULL, DIJOFS_BUTTON(52), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   114
        { NULL, DIJOFS_BUTTON(53), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   115
        { NULL, DIJOFS_BUTTON(54), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   116
        { NULL, DIJOFS_BUTTON(55), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   117
        { NULL, DIJOFS_BUTTON(56), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   118
        { NULL, DIJOFS_BUTTON(57), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   119
        { NULL, DIJOFS_BUTTON(58), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   120
        { NULL, DIJOFS_BUTTON(59), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   121
        { NULL, DIJOFS_BUTTON(60), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   122
        { NULL, DIJOFS_BUTTON(61), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   123
        { NULL, DIJOFS_BUTTON(62), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   124
        { NULL, DIJOFS_BUTTON(63), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   125
        { NULL, DIJOFS_BUTTON(64), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   126
        { NULL, DIJOFS_BUTTON(65), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   127
        { NULL, DIJOFS_BUTTON(66), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   128
        { NULL, DIJOFS_BUTTON(67), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   129
        { NULL, DIJOFS_BUTTON(68), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   130
        { NULL, DIJOFS_BUTTON(69), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   131
        { NULL, DIJOFS_BUTTON(70), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   132
        { NULL, DIJOFS_BUTTON(71), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   133
        { NULL, DIJOFS_BUTTON(72), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   134
        { NULL, DIJOFS_BUTTON(73), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   135
        { NULL, DIJOFS_BUTTON(74), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   136
        { NULL, DIJOFS_BUTTON(75), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   137
        { NULL, DIJOFS_BUTTON(76), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   138
        { NULL, DIJOFS_BUTTON(77), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   139
        { NULL, DIJOFS_BUTTON(78), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   140
        { NULL, DIJOFS_BUTTON(79), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   141
        { NULL, DIJOFS_BUTTON(80), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   142
        { NULL, DIJOFS_BUTTON(81), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   143
        { NULL, DIJOFS_BUTTON(82), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   144
        { NULL, DIJOFS_BUTTON(83), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   145
        { NULL, DIJOFS_BUTTON(84), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   146
        { NULL, DIJOFS_BUTTON(85), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   147
        { NULL, DIJOFS_BUTTON(86), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   148
        { NULL, DIJOFS_BUTTON(87), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   149
        { NULL, DIJOFS_BUTTON(88), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   150
        { NULL, DIJOFS_BUTTON(89), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   151
        { NULL, DIJOFS_BUTTON(90), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   152
        { NULL, DIJOFS_BUTTON(91), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   153
        { NULL, DIJOFS_BUTTON(92), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   154
        { NULL, DIJOFS_BUTTON(93), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   155
        { NULL, DIJOFS_BUTTON(94), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   156
        { NULL, DIJOFS_BUTTON(95), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   157
        { NULL, DIJOFS_BUTTON(96), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   158
        { NULL, DIJOFS_BUTTON(97), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   159
        { NULL, DIJOFS_BUTTON(98), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   160
        { NULL, DIJOFS_BUTTON(99), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   161
        { NULL, DIJOFS_BUTTON(100), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   162
        { NULL, DIJOFS_BUTTON(101), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   163
        { NULL, DIJOFS_BUTTON(102), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   164
        { NULL, DIJOFS_BUTTON(103), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   165
        { NULL, DIJOFS_BUTTON(104), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   166
        { NULL, DIJOFS_BUTTON(105), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   167
        { NULL, DIJOFS_BUTTON(106), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   168
        { NULL, DIJOFS_BUTTON(107), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   169
        { NULL, DIJOFS_BUTTON(108), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   170
        { NULL, DIJOFS_BUTTON(109), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   171
        { NULL, DIJOFS_BUTTON(110), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   172
        { NULL, DIJOFS_BUTTON(111), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   173
        { NULL, DIJOFS_BUTTON(112), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   174
        { NULL, DIJOFS_BUTTON(113), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   175
        { NULL, DIJOFS_BUTTON(114), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   176
        { NULL, DIJOFS_BUTTON(115), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   177
        { NULL, DIJOFS_BUTTON(116), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   178
        { NULL, DIJOFS_BUTTON(117), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   179
        { NULL, DIJOFS_BUTTON(118), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   180
        { NULL, DIJOFS_BUTTON(119), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   181
        { NULL, DIJOFS_BUTTON(120), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   182
        { NULL, DIJOFS_BUTTON(121), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   183
        { NULL, DIJOFS_BUTTON(122), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   184
        { NULL, DIJOFS_BUTTON(123), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   185
        { NULL, DIJOFS_BUTTON(124), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   186
        { NULL, DIJOFS_BUTTON(125), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   187
        { NULL, DIJOFS_BUTTON(126), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   188
        { NULL, DIJOFS_BUTTON(127), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   189
        { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lVX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   190
        { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lVY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   191
        { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lVZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   192
        { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lVRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   193
        { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lVRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   194
        { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lVRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   195
        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   196
        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   197
        { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lAX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   198
        { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lAY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   199
        { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lAZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   200
        { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lARx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   201
        { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lARy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   202
        { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lARz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   203
        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   204
        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   205
        { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lFX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   206
        { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lFY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   207
        { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lFZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   208
        { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lFRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   209
        { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lFRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   210
        { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lFRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   211
        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@8972
   212
        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
slouken@2760
   213
};
slouken@2760
   214
slouken@10442
   215
const DIDATAFORMAT SDL_c_dfDIJoystick2 = {
slouken@2760
   216
    sizeof(DIDATAFORMAT),
slouken@2760
   217
    sizeof(DIOBJECTDATAFORMAT),
slouken@2760
   218
    DIDF_ABSAXIS,
slouken@2760
   219
    sizeof(DIJOYSTATE2),
slouken@2760
   220
    SDL_arraysize(dfDIJoystick2),
slouken@2760
   221
    dfDIJoystick2
slouken@2760
   222
};
slouken@2760
   223
slouken@1895
   224
/* Convert a DirectInput return code to a text message */
icculus@7037
   225
static int
slouken@2198
   226
SetDIerror(const char *function, HRESULT code)
slouken@1895
   227
{
slouken@2760
   228
    /*
icculus@7037
   229
    return SDL_SetError("%s() [%s]: %s", function,
slouken@8972
   230
    DXGetErrorString9A(code), DXGetErrorDescription9A(code));
slouken@8972
   231
    */
slouken@8976
   232
    return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code);
slouken@1895
   233
}
slouken@1895
   234
slouken@8920
   235
static SDL_bool
slouken@8920
   236
SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
slouken@6690
   237
{
slouken@8972
   238
    static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
slouken@8972
   239
    static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
slouken@8972
   240
    static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
mikkel@10217
   241
    static GUID IID_XOneWiredGamepad = { MAKELONG(0x045E, 0x02FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
mikkel@10217
   242
    static GUID IID_XOneWirelessGamepad = { MAKELONG(0x045E, 0x02DD), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
mikkel@10217
   243
    static GUID IID_XOneNewWirelessGamepad = { MAKELONG(0x045E, 0x02D1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
mikkel@10217
   244
    static GUID IID_XOneSWirelessGamepad = { MAKELONG(0x045E, 0x02EA), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
mikkel@10217
   245
    static GUID IID_XOneSBluetoothGamepad = { MAKELONG(0x045E, 0x02E0), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
mikkel@10217
   246
    static GUID IID_XOneEliteWirelessGamepad = { MAKELONG(0x045E, 0x02E3), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
slouken@8972
   247
slouken@7299
   248
    static const GUID *s_XInputProductGUID[] = {
icculus@7706
   249
        &IID_ValveStreamingGamepad,
mikkel@10217
   250
        &IID_X360WiredGamepad,         /* Microsoft's wired X360 controller for Windows. */
mikkel@10217
   251
        &IID_X360WirelessGamepad,      /* Microsoft's wireless X360 controller for Windows. */
mikkel@10217
   252
        &IID_XOneWiredGamepad,         /* Microsoft's wired Xbox One controller for Windows. */
mikkel@10217
   253
        &IID_XOneWirelessGamepad,      /* Microsoft's wireless Xbox One controller for Windows. */
mikkel@10217
   254
        &IID_XOneNewWirelessGamepad,   /* Microsoft's updated wireless Xbox One controller (w/ 3.5 mm jack) for Windows. */
mikkel@10217
   255
        &IID_XOneSWirelessGamepad,     /* Microsoft's wireless Xbox One S controller for Windows. */
mikkel@10217
   256
        &IID_XOneSBluetoothGamepad,    /* Microsoft's Bluetooth Xbox One S controller for Windows. */
mikkel@10217
   257
        &IID_XOneEliteWirelessGamepad  /* Microsoft's wireless Xbox One Elite controller for Windows. */
slouken@7299
   258
    };
slouken@6690
   259
icculus@7706
   260
    size_t iDevice;
icculus@7706
   261
    UINT i;
icculus@7706
   262
slouken@8972
   263
    if (!SDL_XINPUT_Enabled()) {
urkle@6965
   264
        return SDL_FALSE;
urkle@6965
   265
    }
urkle@6965
   266
gabomdq@7663
   267
    /* Check for well known XInput device GUIDs */
icculus@7706
   268
    /* This lets us skip RAWINPUT for popular devices. Also, we need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list. */
slouken@8920
   269
    for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) {
slouken@7299
   270
        if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
slouken@7299
   271
            return SDL_TRUE;
slouken@7299
   272
        }
slouken@7299
   273
    }
slouken@7299
   274
icculus@7706
   275
    /* Go through RAWINPUT (WinXP and later) to find HID devices. */
icculus@7706
   276
    /* Cache this if we end up using it. */
icculus@7706
   277
    if (SDL_RawDevList == NULL) {
slouken@8972
   278
        if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
icculus@7706
   279
            return SDL_FALSE;  /* oh well. */
icculus@7706
   280
        }
slouken@6690
   281
slouken@8972
   282
        SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount);
icculus@7706
   283
        if (SDL_RawDevList == NULL) {
icculus@7706
   284
            SDL_OutOfMemory();
icculus@7706
   285
            return SDL_FALSE;
icculus@7706
   286
        }
slouken@6690
   287
slouken@8972
   288
        if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) {
slouken@8972
   289
            SDL_free(SDL_RawDevList);
slouken@8972
   290
            SDL_RawDevList = NULL;
slouken@8972
   291
            return SDL_FALSE;  /* oh well. */
slouken@7191
   292
        }
slouken@7191
   293
    }
slouken@7191
   294
icculus@7706
   295
    for (i = 0; i < SDL_RawDevListCount; i++) {
icculus@7706
   296
        RID_DEVICE_INFO rdi;
icculus@7706
   297
        char devName[128];
slouken@8972
   298
        UINT rdiSize = sizeof(rdi);
icculus@7706
   299
        UINT nameSize = SDL_arraysize(devName);
slouken@6690
   300
slouken@8972
   301
        rdi.cbSize = sizeof(rdi);
slouken@8920
   302
        if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
slouken@8972
   303
            (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
slouken@8972
   304
            (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
slouken@8972
   305
            (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
slouken@8972
   306
            (SDL_strstr(devName, "IG_") != NULL)) {
slouken@8972
   307
            return SDL_TRUE;
icculus@7706
   308
        }
icculus@7706
   309
    }
slouken@6690
   310
icculus@7706
   311
    return SDL_FALSE;
slouken@6690
   312
}
slouken@6690
   313
slouken@1895
   314
int
slouken@8972
   315
SDL_DINPUT_JoystickInit(void)
slouken@1895
   316
{
slouken@1895
   317
    HRESULT result;
slouken@2713
   318
    HINSTANCE instance;
slouken@1895
   319
icculus@5591
   320
    result = WIN_CoInitialize();
slouken@2198
   321
    if (FAILED(result)) {
icculus@7037
   322
        return SetDIerror("CoInitialize", result);
slouken@1895
   323
    }
slouken@1895
   324
icculus@5591
   325
    coinitialized = SDL_TRUE;
icculus@5591
   326
slouken@6690
   327
    result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
slouken@8972
   328
        &IID_IDirectInput8, (LPVOID)&dinput);
slouken@2198
   329
slouken@2198
   330
    if (FAILED(result)) {
icculus@7037
   331
        return SetDIerror("CoCreateInstance", result);
slouken@2198
   332
    }
slouken@2198
   333
slouken@2198
   334
    /* Because we used CoCreateInstance, we need to Initialize it, first. */
slouken@2713
   335
    instance = GetModuleHandle(NULL);
slouken@2713
   336
    if (instance == NULL) {
slouken@8976
   337
        return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError());
slouken@2713
   338
    }
slouken@6690
   339
    result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
slouken@2198
   340
slouken@2198
   341
    if (FAILED(result)) {
icculus@7037
   342
        return SetDIerror("IDirectInput::Initialize", result);
slouken@2198
   343
    }
slouken@8972
   344
    return 0;
slouken@6707
   345
}
slouken@6707
   346
slouken@6707
   347
/* helper function for direct input, gets called for each connected joystick */
slouken@6707
   348
static BOOL CALLBACK
slouken@8920
   349
EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
slouken@6707
   350
{
slouken@10595
   351
    const Uint16 BUS_USB = 0x03;
slouken@10595
   352
    const Uint16 BUS_BLUETOOTH = 0x05;
slouken@7191
   353
    JoyStick_DeviceData *pNewJoystick;
slouken@7191
   354
    JoyStick_DeviceData *pPrevJoystick = NULL;
icculus@9477
   355
    const DWORD devtype = (pdidInstance->dwDevType & 0xFF);
slouken@10595
   356
    Uint16 *guid16;
icculus@9477
   357
slouken@9728
   358
    if (devtype == DI8DEVTYPE_SUPPLEMENTAL) {
slouken@10820
   359
        /* Add any supplemental devices that should be ignored here */
slouken@10820
   360
#define MAKE_TABLE_ENTRY(VID, PID)	((((DWORD)PID)<<16)|VID)
slouken@10820
   361
		static DWORD ignored_devices[] = {
slouken@10820
   362
			MAKE_TABLE_ENTRY(0, 0)
slouken@10820
   363
		};
slouken@10820
   364
#undef MAKE_TABLE_ENTRY
slouken@10820
   365
		unsigned int i;
slouken@10820
   366
slouken@10820
   367
		for (i = 0; i < SDL_arraysize(ignored_devices); ++i) {
slouken@10820
   368
			if (pdidInstance->guidProduct.Data1 == ignored_devices[i]) {
slouken@10820
   369
				return DIENUM_CONTINUE;
slouken@10820
   370
			}
slouken@10820
   371
		}
icculus@9477
   372
    }
icculus@7707
   373
slouken@8920
   374
    if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
icculus@7707
   375
        return DIENUM_CONTINUE;  /* ignore XInput devices here, keep going. */
icculus@7707
   376
    }
icculus@7707
   377
slouken@7191
   378
    pNewJoystick = *(JoyStick_DeviceData **)pContext;
slouken@8920
   379
    while (pNewJoystick) {
slouken@8920
   380
        if (!SDL_memcmp(&pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance))) {
slouken@7191
   381
            /* if we are replacing the front of the list then update it */
slouken@8920
   382
            if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
slouken@7191
   383
                *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
slouken@8920
   384
            } else if (pPrevJoystick) {
slouken@7191
   385
                pPrevJoystick->pNext = pNewJoystick->pNext;
slouken@7191
   386
            }
slouken@6712
   387
slouken@7191
   388
            pNewJoystick->pNext = SYS_Joystick;
slouken@7191
   389
            SYS_Joystick = pNewJoystick;
slouken@6707
   390
icculus@7707
   391
            return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
slouken@7191
   392
        }
slouken@6707
   393
slouken@7191
   394
        pPrevJoystick = pNewJoystick;
slouken@7191
   395
        pNewJoystick = pNewJoystick->pNext;
slouken@7191
   396
    }
slouken@6707
   397
slouken@8920
   398
    pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
icculus@7707
   399
    if (!pNewJoystick) {
icculus@7707
   400
        return DIENUM_CONTINUE; /* better luck next time? */
icculus@7707
   401
    }
slouken@6707
   402
icculus@7707
   403
    SDL_zerop(pNewJoystick);
icculus@7707
   404
    pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
icculus@7707
   405
    if (!pNewJoystick->joystickname) {
icculus@7707
   406
        SDL_free(pNewJoystick);
icculus@7707
   407
        return DIENUM_CONTINUE; /* better luck next time? */
slouken@7191
   408
    }
slouken@7191
   409
slouken@7191
   410
    SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
slouken@7191
   411
        sizeof(DIDEVICEINSTANCE));
slouken@6712
   412
slouken@10595
   413
    SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data));
slouken@10595
   414
slouken@10595
   415
    guid16 = (Uint16 *)pNewJoystick->guid.data;
slouken@10600
   416
    if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
slouken@10595
   417
        *guid16++ = SDL_SwapLE16(BUS_USB);
slouken@10595
   418
        *guid16++ = 0;
slouken@10595
   419
        *guid16++ = SDL_SwapLE16((Uint16)LOWORD(pdidInstance->guidProduct.Data1)); /* vendor */
slouken@10595
   420
        *guid16++ = 0;
slouken@10595
   421
        *guid16++ = SDL_SwapLE16((Uint16)HIWORD(pdidInstance->guidProduct.Data1)); /* product */
slouken@10595
   422
        *guid16++ = 0;
slouken@10595
   423
        *guid16++ = 0; /* version */
slouken@10595
   424
        *guid16++ = 0;
slouken@10595
   425
    } else {
slouken@10595
   426
        *guid16++ = SDL_SwapLE16(BUS_BLUETOOTH);
slouken@10595
   427
        *guid16++ = 0;
slouken@10595
   428
        SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4);
slouken@10595
   429
    }
slouken@10595
   430
slouken@8972
   431
    SDL_SYS_AddJoystickDevice(pNewJoystick);
icculus@7707
   432
icculus@7707
   433
    return DIENUM_CONTINUE; /* get next device, please */
icculus@7707
   434
}
icculus@7707
   435
slouken@8972
   436
void
slouken@8972
   437
SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
slouken@8920
   438
{
slouken@8972
   439
    IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY);
slouken@6707
   440
slouken@8972
   441
    if (SDL_RawDevList) {
slouken@8972
   442
        SDL_free(SDL_RawDevList);  /* in case we used this in DirectInput detection */
slouken@8972
   443
        SDL_RawDevList = NULL;
icculus@7707
   444
    }
icculus@8860
   445
    SDL_RawDevListCount = 0;
slouken@6707
   446
}
slouken@6707
   447
slouken@8972
   448
static BOOL CALLBACK
slouken@8972
   449
EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
slouken@6707
   450
{
slouken@8972
   451
    SDL_Joystick *joystick = (SDL_Joystick *)pvRef;
slouken@1895
   452
    HRESULT result;
slouken@8972
   453
    input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
slouken@2198
   454
slouken@8972
   455
    if (dev->dwType & DIDFT_BUTTON) {
slouken@8972
   456
        in->type = BUTTON;
slouken@8972
   457
        in->num = joystick->nbuttons;
slouken@8972
   458
        in->ofs = DIJOFS_BUTTON(in->num);
slouken@8972
   459
        joystick->nbuttons++;
slouken@8972
   460
    } else if (dev->dwType & DIDFT_POV) {
slouken@8972
   461
        in->type = HAT;
slouken@8972
   462
        in->num = joystick->nhats;
slouken@8972
   463
        in->ofs = DIJOFS_POV(in->num);
slouken@8972
   464
        joystick->nhats++;
slouken@8972
   465
    } else if (dev->dwType & DIDFT_AXIS) {
slouken@8972
   466
        DIPROPRANGE diprg;
slouken@8972
   467
        DIPROPDWORD dilong;
slouken@7684
   468
slouken@8972
   469
        in->type = AXIS;
slouken@8972
   470
        in->num = joystick->naxes;
slouken@8972
   471
        if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
slouken@8972
   472
            in->ofs = DIJOFS_X;
slouken@8972
   473
        else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
slouken@8972
   474
            in->ofs = DIJOFS_Y;
slouken@8972
   475
        else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
slouken@8972
   476
            in->ofs = DIJOFS_Z;
slouken@8972
   477
        else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
slouken@8972
   478
            in->ofs = DIJOFS_RX;
slouken@8972
   479
        else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
slouken@8972
   480
            in->ofs = DIJOFS_RY;
slouken@8972
   481
        else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
slouken@8972
   482
            in->ofs = DIJOFS_RZ;
slouken@8972
   483
        else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
slouken@8972
   484
            in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
slouken@8972
   485
            ++joystick->hwdata->NumSliders;
slouken@8972
   486
        } else {
slouken@8972
   487
            return DIENUM_CONTINUE; /* not an axis we can grok */
slouken@7191
   488
        }
slouken@2198
   489
slouken@8972
   490
        diprg.diph.dwSize = sizeof(diprg);
slouken@8972
   491
        diprg.diph.dwHeaderSize = sizeof(diprg.diph);
slouken@8972
   492
        diprg.diph.dwObj = dev->dwType;
slouken@8972
   493
        diprg.diph.dwHow = DIPH_BYID;
slouken@10724
   494
        diprg.lMin = SDL_JOYSTICK_AXIS_MIN;
slouken@10724
   495
        diprg.lMax = SDL_JOYSTICK_AXIS_MAX;
slouken@2198
   496
slouken@7191
   497
        result =
slouken@8972
   498
            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
slouken@8972
   499
            DIPROP_RANGE, &diprg.diph);
slouken@7191
   500
        if (FAILED(result)) {
slouken@8972
   501
            return DIENUM_CONTINUE;     /* don't use this axis */
slouken@7191
   502
        }
slouken@6690
   503
slouken@8972
   504
        /* Set dead zone to 0. */
slouken@8972
   505
        dilong.diph.dwSize = sizeof(dilong);
slouken@8972
   506
        dilong.diph.dwHeaderSize = sizeof(dilong.diph);
slouken@8972
   507
        dilong.diph.dwObj = dev->dwType;
slouken@8972
   508
        dilong.diph.dwHow = DIPH_BYID;
slouken@8972
   509
        dilong.dwData = 0;
slouken@8972
   510
        result =
slouken@8972
   511
            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
slouken@8972
   512
            DIPROP_DEADZONE, &dilong.diph);
slouken@8972
   513
        if (FAILED(result)) {
slouken@8972
   514
            return DIENUM_CONTINUE;     /* don't use this axis */
slouken@7191
   515
        }
slouken@6220
   516
slouken@8972
   517
        joystick->naxes++;
slouken@8972
   518
    } else {
slouken@8972
   519
        /* not supported at this time */
slouken@8972
   520
        return DIENUM_CONTINUE;
slouken@8972
   521
    }
slouken@2198
   522
slouken@8972
   523
    joystick->hwdata->NumInputs++;
slouken@2198
   524
slouken@8972
   525
    if (joystick->hwdata->NumInputs == MAX_INPUTS) {
slouken@8972
   526
        return DIENUM_STOP;     /* too many */
slouken@7191
   527
    }
slouken@8972
   528
slouken@8972
   529
    return DIENUM_CONTINUE;
slouken@1895
   530
}
slouken@1895
   531
slouken@6220
   532
/* Sort using the data offset into the DInput struct.
slouken@8972
   533
 * This gives a reasonable ordering for the inputs.
slouken@8972
   534
 */
slouken@6220
   535
static int
slouken@6220
   536
SortDevFunc(const void *a, const void *b)
slouken@6220
   537
{
slouken@7191
   538
    const input_t *inputA = (const input_t*)a;
slouken@7191
   539
    const input_t *inputB = (const input_t*)b;
slouken@6220
   540
slouken@7191
   541
    if (inputA->ofs < inputB->ofs)
slouken@7191
   542
        return -1;
slouken@7191
   543
    if (inputA->ofs > inputB->ofs)
slouken@7191
   544
        return 1;
slouken@7191
   545
    return 0;
slouken@6220
   546
}
slouken@6220
   547
slouken@6220
   548
/* Sort the input objects and recalculate the indices for each input. */
slouken@6220
   549
static void
slouken@6220
   550
SortDevObjects(SDL_Joystick *joystick)
slouken@6220
   551
{
slouken@7191
   552
    input_t *inputs = joystick->hwdata->Inputs;
slouken@7191
   553
    int nButtons = 0;
slouken@7191
   554
    int nHats = 0;
slouken@7191
   555
    int nAxis = 0;
slouken@7191
   556
    int n;
slouken@6220
   557
slouken@7191
   558
    SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
slouken@6220
   559
slouken@8920
   560
    for (n = 0; n < joystick->hwdata->NumInputs; n++) {
slouken@8920
   561
        switch (inputs[n].type) {
slouken@7191
   562
        case BUTTON:
slouken@7191
   563
            inputs[n].num = nButtons;
slouken@7191
   564
            nButtons++;
slouken@7191
   565
            break;
slouken@6220
   566
slouken@7191
   567
        case HAT:
slouken@7191
   568
            inputs[n].num = nHats;
slouken@7191
   569
            nHats++;
slouken@7191
   570
            break;
slouken@6220
   571
slouken@7191
   572
        case AXIS:
slouken@7191
   573
            inputs[n].num = nAxis;
slouken@7191
   574
            nAxis++;
slouken@7191
   575
            break;
slouken@7191
   576
        }
slouken@7191
   577
    }
slouken@6220
   578
}
slouken@6220
   579
slouken@8972
   580
int
slouken@8972
   581
SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
slouken@2198
   582
{
slouken@2198
   583
    HRESULT result;
slouken@8972
   584
    LPDIRECTINPUTDEVICE8 device;
slouken@8972
   585
    DIPROPDWORD dipdw;
slouken@8972
   586
slouken@8972
   587
    joystick->hwdata->buffered = SDL_TRUE;
slouken@8972
   588
    joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
slouken@8972
   589
slouken@8972
   590
    SDL_zero(dipdw);
slouken@8972
   591
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
slouken@8972
   592
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
slouken@8972
   593
slouken@8972
   594
    result =
slouken@8972
   595
        IDirectInput8_CreateDevice(dinput,
slouken@8972
   596
        &(joystickdevice->dxdevice.guidInstance), &device, NULL);
slouken@8972
   597
    if (FAILED(result)) {
slouken@8972
   598
        return SetDIerror("IDirectInput::CreateDevice", result);
slouken@8972
   599
    }
slouken@8972
   600
slouken@8972
   601
    /* Now get the IDirectInputDevice8 interface, instead. */
slouken@8972
   602
    result = IDirectInputDevice8_QueryInterface(device,
slouken@8972
   603
        &IID_IDirectInputDevice8,
slouken@8972
   604
        (LPVOID *)& joystick->
slouken@8972
   605
        hwdata->InputDevice);
slouken@8972
   606
    /* We are done with this object.  Use the stored one from now on. */
slouken@8972
   607
    IDirectInputDevice8_Release(device);
slouken@8972
   608
slouken@8972
   609
    if (FAILED(result)) {
slouken@8972
   610
        return SetDIerror("IDirectInputDevice8::QueryInterface", result);
slouken@8972
   611
    }
slouken@2198
   612
slouken@8972
   613
    /* Acquire shared access. Exclusive access is required for forces,
slouken@8972
   614
    * though. */
slouken@8972
   615
    result =
slouken@8972
   616
        IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
slouken@8972
   617
        InputDevice, SDL_HelperWindow,
slouken@8972
   618
        DISCL_EXCLUSIVE |
slouken@8972
   619
        DISCL_BACKGROUND);
slouken@8972
   620
    if (FAILED(result)) {
slouken@8972
   621
        return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
slouken@8972
   622
    }
slouken@2198
   623
slouken@8972
   624
    /* Use the extended data structure: DIJOYSTATE2. */
slouken@8972
   625
    result =
slouken@8972
   626
        IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
slouken@10442
   627
        &SDL_c_dfDIJoystick2);
slouken@8972
   628
    if (FAILED(result)) {
slouken@8972
   629
        return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
slouken@8972
   630
    }
slouken@8972
   631
slouken@8972
   632
    /* Get device capabilities */
slouken@8972
   633
    result =
slouken@8972
   634
        IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
slouken@8972
   635
        &joystick->hwdata->Capabilities);
slouken@8972
   636
    if (FAILED(result)) {
slouken@8972
   637
        return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
slouken@8972
   638
    }
slouken@8972
   639
slouken@8972
   640
    /* Force capable? */
slouken@8972
   641
    if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
slouken@8972
   642
slouken@8972
   643
        result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
slouken@8972
   644
        if (FAILED(result)) {
slouken@8972
   645
            return SetDIerror("IDirectInputDevice8::Acquire", result);
slouken@7191
   646
        }
slouken@2198
   647
slouken@8972
   648
        /* reset all actuators. */
slouken@8972
   649
        result =
slouken@8972
   650
            IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
slouken@8972
   651
            InputDevice,
slouken@8972
   652
            DISFFC_RESET);
slouken@8972
   653
slouken@8972
   654
        /* Not necessarily supported, ignore if not supported.
slouken@8972
   655
        if (FAILED(result)) {
slouken@8972
   656
        return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
slouken@8972
   657
        }
slouken@8972
   658
        */
slouken@8972
   659
slouken@8972
   660
        result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
slouken@8972
   661
slouken@8972
   662
        if (FAILED(result)) {
slouken@8972
   663
            return SetDIerror("IDirectInputDevice8::Unacquire", result);
slouken@8972
   664
        }
slouken@8972
   665
slouken@8972
   666
        /* Turn on auto-centering for a ForceFeedback device (until told
slouken@8972
   667
        * otherwise). */
slouken@8972
   668
        dipdw.diph.dwObj = 0;
slouken@8972
   669
        dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
   670
        dipdw.dwData = DIPROPAUTOCENTER_ON;
slouken@2198
   671
slouken@2198
   672
        result =
slouken@6690
   673
            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
slouken@8972
   674
            DIPROP_AUTOCENTER, &dipdw.diph);
slouken@2198
   675
slouken@8972
   676
        /* Not necessarily supported, ignore if not supported.
slouken@8972
   677
        if (FAILED(result)) {
slouken@8972
   678
        return SetDIerror("IDirectInputDevice8::SetProperty", result);
slouken@8972
   679
        }
slouken@8972
   680
        */
slouken@7191
   681
    }
slouken@6690
   682
slouken@8972
   683
    /* What buttons and axes does it have? */
slouken@8972
   684
    IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
slouken@8972
   685
        EnumDevObjectsCallback, joystick,
slouken@8972
   686
        DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
slouken@2198
   687
slouken@8972
   688
    /* Reorder the input objects. Some devices do not report the X axis as
slouken@8972
   689
    * the first axis, for example. */
slouken@8972
   690
    SortDevObjects(joystick);
slouken@2198
   691
slouken@8972
   692
    dipdw.diph.dwObj = 0;
slouken@8972
   693
    dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
   694
    dipdw.dwData = INPUT_QSIZE;
slouken@2198
   695
slouken@8972
   696
    /* Set the buffer size */
slouken@8972
   697
    result =
slouken@8972
   698
        IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
slouken@8972
   699
        DIPROP_BUFFERSIZE, &dipdw.diph);
slouken@8920
   700
slouken@8972
   701
    if (result == DI_POLLEDDEVICE) {
slouken@8972
   702
        /* This device doesn't support buffering, so we're forced
slouken@8972
   703
         * to use less reliable polling. */
slouken@8972
   704
        joystick->hwdata->buffered = SDL_FALSE;
slouken@8972
   705
    } else if (FAILED(result)) {
slouken@8972
   706
        return SetDIerror("IDirectInputDevice8::SetProperty", result);
slouken@7191
   707
    }
slouken@8972
   708
    return 0;
slouken@6690
   709
}
slouken@6690
   710
slouken@1895
   711
static Uint8
slouken@1895
   712
TranslatePOV(DWORD value)
slouken@1895
   713
{
slouken@1895
   714
    const int HAT_VALS[] = {
slouken@1895
   715
        SDL_HAT_UP,
slouken@1895
   716
        SDL_HAT_UP | SDL_HAT_RIGHT,
slouken@1895
   717
        SDL_HAT_RIGHT,
slouken@1895
   718
        SDL_HAT_DOWN | SDL_HAT_RIGHT,
slouken@1895
   719
        SDL_HAT_DOWN,
slouken@1895
   720
        SDL_HAT_DOWN | SDL_HAT_LEFT,
slouken@1895
   721
        SDL_HAT_LEFT,
slouken@1895
   722
        SDL_HAT_UP | SDL_HAT_LEFT
slouken@1895
   723
    };
slouken@1895
   724
slouken@1895
   725
    if (LOWORD(value) == 0xFFFF)
slouken@1895
   726
        return SDL_HAT_CENTERED;
slouken@1895
   727
slouken@1895
   728
    /* Round the value up: */
slouken@1895
   729
    value += 4500 / 2;
slouken@1895
   730
    value %= 36000;
slouken@1895
   731
    value /= 4500;
slouken@1895
   732
slouken@1895
   733
    if (value >= 8)
slouken@1895
   734
        return SDL_HAT_CENTERED;        /* shouldn't happen */
slouken@1895
   735
slouken@1895
   736
    return HAT_VALS[value];
slouken@1895
   737
}
slouken@1895
   738
slouken@8972
   739
static void
slouken@8972
   740
UpdateDINPUTJoystickState_Buffered(SDL_Joystick * joystick)
slouken@1895
   741
{
slouken@8972
   742
    int i;
slouken@1895
   743
    HRESULT result;
slouken@8972
   744
    DWORD numevents;
slouken@8972
   745
    DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
slouken@1895
   746
slouken@8972
   747
    numevents = INPUT_QSIZE;
slouken@8972
   748
    result =
slouken@8972
   749
        IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
slouken@8972
   750
        sizeof(DIDEVICEOBJECTDATA), evtbuf,
slouken@8972
   751
        &numevents, 0);
slouken@8972
   752
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
slouken@8972
   753
        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
slouken@8972
   754
        result =
slouken@8972
   755
            IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
slouken@8972
   756
            sizeof(DIDEVICEOBJECTDATA),
slouken@8972
   757
            evtbuf, &numevents, 0);
slouken@7191
   758
    }
slouken@6690
   759
slouken@8972
   760
    /* Handle the events or punt */
slouken@8972
   761
    if (FAILED(result)) {
slouken@8972
   762
        joystick->hwdata->send_remove_event = SDL_TRUE;
slouken@8972
   763
        joystick->hwdata->removed = SDL_TRUE;
slouken@8972
   764
        return;
slouken@8972
   765
    }
slouken@8972
   766
slouken@8972
   767
    for (i = 0; i < (int)numevents; ++i) {
slouken@8972
   768
        int j;
slouken@8972
   769
slouken@8972
   770
        for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
slouken@8972
   771
            const input_t *in = &joystick->hwdata->Inputs[j];
slouken@8972
   772
slouken@8972
   773
            if (evtbuf[i].dwOfs != in->ofs)
slouken@8972
   774
                continue;
slouken@8972
   775
slouken@8972
   776
            switch (in->type) {
slouken@8972
   777
            case AXIS:
slouken@8972
   778
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData);
slouken@8972
   779
                break;
slouken@8972
   780
            case BUTTON:
slouken@8972
   781
                SDL_PrivateJoystickButton(joystick, in->num,
slouken@8972
   782
                    (Uint8)(evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
slouken@8972
   783
                break;
slouken@8972
   784
            case HAT:
slouken@8972
   785
                {
slouken@8972
   786
                    Uint8 pos = TranslatePOV(evtbuf[i].dwData);
slouken@8972
   787
                    SDL_PrivateJoystickHat(joystick, in->num, pos);
slouken@8972
   788
                }
slouken@8972
   789
                break;
slouken@8972
   790
            }
slouken@8972
   791
        }
slouken@7191
   792
    }
slouken@1895
   793
}
slouken@1895
   794
slouken@8972
   795
/* Function to update the state of a joystick - called as a device poll.
slouken@8972
   796
 * This function shouldn't update the joystick structure directly,
slouken@8972
   797
 * but instead should call SDL_PrivateJoystick*() to deliver events
slouken@8972
   798
 * and update joystick device state.
slouken@8972
   799
 */
slouken@8972
   800
static void
slouken@8972
   801
UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
slouken@1895
   802
{
slouken@8972
   803
    DIJOYSTATE2 state;
slouken@8972
   804
    HRESULT result;
slouken@8972
   805
    int i;
slouken@8972
   806
slouken@8972
   807
    result =
slouken@8972
   808
        IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
slouken@8972
   809
        sizeof(DIJOYSTATE2), &state);
slouken@8972
   810
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
slouken@8972
   811
        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
slouken@8972
   812
        result =
slouken@8972
   813
            IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
slouken@8972
   814
            sizeof(DIJOYSTATE2), &state);
slouken@8972
   815
    }
slouken@8972
   816
slouken@8972
   817
    if (result != DI_OK) {
slouken@8972
   818
        joystick->hwdata->send_remove_event = SDL_TRUE;
slouken@8972
   819
        joystick->hwdata->removed = SDL_TRUE;
slouken@8972
   820
        return;
slouken@7191
   821
    }
slouken@1895
   822
slouken@8972
   823
    /* Set each known axis, button and POV. */
slouken@8972
   824
    for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
slouken@8972
   825
        const input_t *in = &joystick->hwdata->Inputs[i];
slouken@6690
   826
slouken@8972
   827
        switch (in->type) {
slouken@8972
   828
        case AXIS:
slouken@8972
   829
            switch (in->ofs) {
slouken@8972
   830
            case DIJOFS_X:
slouken@8972
   831
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX);
slouken@8972
   832
                break;
slouken@8972
   833
            case DIJOFS_Y:
slouken@8972
   834
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY);
slouken@8972
   835
                break;
slouken@8972
   836
            case DIJOFS_Z:
slouken@8972
   837
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ);
slouken@8972
   838
                break;
slouken@8972
   839
            case DIJOFS_RX:
slouken@8972
   840
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx);
slouken@8972
   841
                break;
slouken@8972
   842
            case DIJOFS_RY:
slouken@8972
   843
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy);
slouken@8972
   844
                break;
slouken@8972
   845
            case DIJOFS_RZ:
slouken@8972
   846
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz);
slouken@8972
   847
                break;
slouken@8972
   848
            case DIJOFS_SLIDER(0):
slouken@8972
   849
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]);
slouken@8972
   850
                break;
slouken@8972
   851
            case DIJOFS_SLIDER(1):
slouken@8972
   852
                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]);
slouken@8972
   853
                break;
slouken@8972
   854
            }
slouken@8972
   855
            break;
slouken@8972
   856
slouken@8972
   857
        case BUTTON:
slouken@8972
   858
            SDL_PrivateJoystickButton(joystick, in->num,
slouken@8972
   859
                (Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
slouken@8972
   860
            break;
slouken@8972
   861
        case HAT:
slouken@8972
   862
        {
slouken@8972
   863
            Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
slouken@8972
   864
            SDL_PrivateJoystickHat(joystick, in->num, pos);
slouken@8972
   865
            break;
slouken@8972
   866
        }
slouken@8972
   867
        }
slouken@8972
   868
    }
slouken@1895
   869
}
slouken@1895
   870
slouken@1895
   871
void
slouken@8972
   872
SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
slouken@1895
   873
{
slouken@8972
   874
    HRESULT result;
slouken@6690
   875
slouken@8972
   876
    result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
slouken@8972
   877
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
slouken@8972
   878
        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
slouken@8972
   879
        IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
slouken@7191
   880
    }
slouken@5090
   881
slouken@8972
   882
    if (joystick->hwdata->buffered) {
slouken@8972
   883
        UpdateDINPUTJoystickState_Buffered(joystick);
slouken@8972
   884
    } else {
slouken@8972
   885
        UpdateDINPUTJoystickState_Polled(joystick);
slouken@8972
   886
    }
slouken@8972
   887
}
slouken@8972
   888
slouken@8972
   889
void
slouken@8972
   890
SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
slouken@8972
   891
{
slouken@8972
   892
    IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
slouken@8972
   893
    IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
slouken@8972
   894
}
slouken@8972
   895
slouken@8972
   896
void
slouken@8972
   897
SDL_DINPUT_JoystickQuit(void)
slouken@8972
   898
{
icculus@5591
   899
    if (dinput != NULL) {
slouken@6690
   900
        IDirectInput8_Release(dinput);
icculus@5591
   901
        dinput = NULL;
icculus@5591
   902
    }
icculus@5591
   903
icculus@5591
   904
    if (coinitialized) {
icculus@5591
   905
        WIN_CoUninitialize();
icculus@5591
   906
        coinitialized = SDL_FALSE;
icculus@5591
   907
    }
slouken@8972
   908
}
slouken@6690
   909
slouken@8972
   910
#else /* !SDL_JOYSTICK_DINPUT */
slouken@8972
   911
icculus@9660
   912
typedef struct JoyStick_DeviceData JoyStick_DeviceData;
slouken@8972
   913
slouken@8972
   914
int
slouken@8972
   915
SDL_DINPUT_JoystickInit(void)
slouken@8972
   916
{
slouken@8972
   917
    return 0;
slouken@8972
   918
}
slouken@8972
   919
slouken@8972
   920
void
slouken@8972
   921
SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
slouken@8972
   922
{
slouken@6690
   923
}
slouken@6690
   924
slouken@8972
   925
int
slouken@8972
   926
SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
slouken@6690
   927
{
slouken@8972
   928
    return SDL_Unsupported();
slouken@6690
   929
}
slouken@6690
   930
slouken@8972
   931
void
slouken@8972
   932
SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
slouken@6707
   933
{
slouken@6707
   934
}
slouken@6707
   935
slouken@8972
   936
void
slouken@8972
   937
SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
slouken@6690
   938
{
slouken@8972
   939
}
slouken@6690
   940
slouken@8972
   941
void
slouken@8972
   942
SDL_DINPUT_JoystickQuit(void)
slouken@8972
   943
{
slouken@7685
   944
}
slouken@7685
   945
slouken@1895
   946
#endif /* SDL_JOYSTICK_DINPUT */
slouken@3575
   947
slouken@1895
   948
/* vi: set ts=4 sw=4 expandtab: */