src/joystick/SDL_joystick.c
author Cameron Gutman
Sat, 07 Mar 2020 17:20:04 -0800
changeset 13595 36aabb2051e9
parent 13583 88068887c25d
child 13596 501950e51321
permissions -rw-r--r--
Fix incorrect player index when assigning a joystick the same index twice

Prior to this fix, we would hit the existing_instance >= 0 case and move the joystick
again to a different index than the one requested by the caller. It also breaks the assumption
that a SDL_JoystickID is only present in SDL_joystick_players at one location.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@13422
     3
  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
slouken@0
     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@0
     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@0
    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@0
    20
*/
icculus@8093
    21
#include "../SDL_internal.h"
slouken@0
    22
slouken@0
    23
/* This is the joystick API for Simple DirectMedia Layer */
slouken@0
    24
slouken@7337
    25
#include "SDL.h"
slouken@12088
    26
#include "SDL_atomic.h"
slouken@0
    27
#include "SDL_events.h"
slouken@1361
    28
#include "SDL_sysjoystick.h"
icculus@5861
    29
#include "SDL_assert.h"
jorgen@7279
    30
#include "SDL_hints.h"
icculus@5861
    31
slouken@1361
    32
#if !SDL_EVENTS_DISABLED
slouken@1361
    33
#include "../events/SDL_events_c.h"
slouken@0
    34
#endif
slouken@11255
    35
#include "../video/SDL_sysvideo.h"
slouken@13356
    36
#include "hidapi/SDL_hidapijoystick_c.h"
slouken@0
    37
slouken@12088
    38
/* This is included in only one place because it has a large static list of controllers */
slouken@12088
    39
#include "controller_type.h"
slouken@10855
    40
slouken@12088
    41
#ifdef __WIN32__
slouken@12088
    42
/* Needed for checking for input remapping programs */
slouken@12089
    43
#include "../core/windows/SDL_windows.h"
slouken@12088
    44
slouken@12088
    45
#undef UNICODE          /* We want ASCII functions */
slouken@12088
    46
#include <tlhelp32.h>
slouken@12088
    47
#endif
slouken@12088
    48
slouken@12088
    49
static SDL_JoystickDriver *SDL_joystick_drivers[] = {
slouken@12088
    50
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
slouken@12088
    51
    &SDL_WINDOWS_JoystickDriver,
slouken@12088
    52
#endif
slouken@12088
    53
#ifdef SDL_JOYSTICK_LINUX
slouken@12088
    54
    &SDL_LINUX_JoystickDriver,
slouken@12088
    55
#endif
slouken@12088
    56
#ifdef SDL_JOYSTICK_IOKIT
slouken@12088
    57
    &SDL_DARWIN_JoystickDriver,
slouken@12088
    58
#endif
slouken@12088
    59
#if defined(__IPHONEOS__) || defined(__TVOS__)
slouken@12088
    60
    &SDL_IOS_JoystickDriver,
slouken@12088
    61
#endif
slouken@12088
    62
#ifdef SDL_JOYSTICK_ANDROID
slouken@12088
    63
    &SDL_ANDROID_JoystickDriver,
slouken@12088
    64
#endif
icculus@12104
    65
#ifdef SDL_JOYSTICK_EMSCRIPTEN
icculus@12104
    66
    &SDL_EMSCRIPTEN_JoystickDriver,
icculus@12104
    67
#endif
icculus@12107
    68
#ifdef SDL_JOYSTICK_HAIKU
icculus@12107
    69
    &SDL_HAIKU_JoystickDriver,
icculus@12107
    70
#endif
icculus@12105
    71
#ifdef SDL_JOYSTICK_USBHID  /* !!! FIXME: "USBHID" is a generic name, and doubly-confusing with HIDAPI next to it. This is the *BSD interface, rename this. */
icculus@12105
    72
    &SDL_BSD_JoystickDriver,
icculus@12105
    73
#endif
slouken@12088
    74
#ifdef SDL_JOYSTICK_HIDAPI
slouken@12088
    75
    &SDL_HIDAPI_JoystickDriver,
slouken@12088
    76
#endif
slouken@12088
    77
#if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
slouken@12088
    78
    &SDL_DUMMY_JoystickDriver
slouken@12088
    79
#endif
slouken@12088
    80
};
slouken@7337
    81
static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
slouken@6712
    82
static SDL_Joystick *SDL_joysticks = NULL;
slouken@10704
    83
static SDL_bool SDL_updating_joystick = SDL_FALSE;
slouken@10659
    84
static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
slouken@12088
    85
static SDL_atomic_t SDL_next_joystick_instance_id;
slouken@13369
    86
static int SDL_joystick_player_count = 0;
slouken@13369
    87
static SDL_JoystickID *SDL_joystick_players = NULL;
slouken@10659
    88
slouken@10688
    89
void
slouken@11581
    90
SDL_LockJoysticks(void)
slouken@10659
    91
{
slouken@10659
    92
    if (SDL_joystick_lock) {
slouken@10659
    93
        SDL_LockMutex(SDL_joystick_lock);
slouken@10659
    94
    }
slouken@10659
    95
}
slouken@10659
    96
slouken@10688
    97
void
slouken@11581
    98
SDL_UnlockJoysticks(void)
slouken@10659
    99
{
slouken@10659
   100
    if (SDL_joystick_lock) {
slouken@10659
   101
        SDL_UnlockMutex(SDL_joystick_lock);
slouken@10659
   102
    }
slouken@10659
   103
}
slouken@10659
   104
slouken@13369
   105
static int
slouken@13369
   106
SDL_FindFreePlayerIndex()
slouken@13369
   107
{
slouken@13369
   108
    int player_index;
slouken@13369
   109
slouken@13369
   110
    for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
slouken@13369
   111
        if (SDL_joystick_players[player_index] == -1) {
slouken@13369
   112
            return player_index;
slouken@13369
   113
        }
slouken@13369
   114
    }
slouken@13369
   115
    return player_index;
slouken@13369
   116
}
slouken@13369
   117
slouken@13369
   118
static int
slouken@13369
   119
SDL_GetPlayerIndexForJoystickID(SDL_JoystickID instance_id)
slouken@13369
   120
{
slouken@13369
   121
    int player_index;
slouken@13369
   122
slouken@13369
   123
    for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
slouken@13369
   124
        if (instance_id == SDL_joystick_players[player_index]) {
slouken@13369
   125
            break;
slouken@13369
   126
        }
slouken@13369
   127
    }
slouken@13369
   128
    if (player_index == SDL_joystick_player_count) {
slouken@13369
   129
        player_index = -1;
slouken@13369
   130
    }
slouken@13369
   131
    return player_index;
slouken@13369
   132
}
slouken@13369
   133
slouken@13369
   134
static SDL_JoystickID
slouken@13369
   135
SDL_GetJoystickIDForPlayerIndex(int player_index)
slouken@13369
   136
{
slouken@13369
   137
    if (player_index < 0 || player_index >= SDL_joystick_player_count) {
slouken@13369
   138
        return -1;
slouken@13369
   139
    }
slouken@13369
   140
    return SDL_joystick_players[player_index];
slouken@13369
   141
}
slouken@13369
   142
slouken@13369
   143
static SDL_bool
slouken@13369
   144
SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID instance_id)
slouken@13369
   145
{
slouken@13369
   146
    SDL_JoystickID existing_instance = SDL_GetJoystickIDForPlayerIndex(player_index);
slouken@13369
   147
    SDL_JoystickDriver *driver;
slouken@13369
   148
    int device_index;
slouken@13369
   149
slouken@13369
   150
    if (player_index < 0) {
slouken@13369
   151
        return SDL_FALSE;
slouken@13369
   152
    }
slouken@13369
   153
    if (player_index >= SDL_joystick_player_count) {
slouken@13369
   154
        SDL_JoystickID *new_players = (SDL_JoystickID *)SDL_realloc(SDL_joystick_players, (player_index + 1)*sizeof(*SDL_joystick_players));
slouken@13369
   155
        if (!new_players) {
slouken@13369
   156
            SDL_OutOfMemory();
slouken@13369
   157
            return SDL_FALSE;
slouken@13369
   158
        }
slouken@13369
   159
slouken@13369
   160
        SDL_joystick_players = new_players;
slouken@13412
   161
        SDL_memset(&SDL_joystick_players[SDL_joystick_player_count], 0xFF, (player_index - SDL_joystick_player_count + 1) * sizeof(SDL_joystick_players[0]));
slouken@13412
   162
        SDL_joystick_player_count = player_index + 1;
aicommander@13595
   163
    } else if (SDL_joystick_players[player_index] == instance_id) {
aicommander@13595
   164
        /* Joystick is already assigned the requested player index */
aicommander@13595
   165
        return SDL_TRUE;
slouken@13369
   166
    }
slouken@13369
   167
slouken@13369
   168
    SDL_joystick_players[player_index] = instance_id;
slouken@13369
   169
slouken@13369
   170
    /* Update the driver with the new index */
slouken@13369
   171
    device_index = SDL_JoystickGetDeviceIndexFromInstanceID(instance_id);
slouken@13369
   172
    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
slouken@13369
   173
        driver->SetDevicePlayerIndex(device_index, player_index);
slouken@13369
   174
    }
slouken@13369
   175
slouken@13369
   176
    /* Move any existing joystick to another slot */
slouken@13369
   177
    if (existing_instance >= 0) {
slouken@13369
   178
        SDL_SetJoystickIDForPlayerIndex(SDL_FindFreePlayerIndex(), existing_instance);
slouken@13369
   179
    }
slouken@13369
   180
    return SDL_TRUE;
slouken@13369
   181
}
slouken@0
   182
slouken@11284
   183
static void SDLCALL
slouken@7432
   184
SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
slouken@7432
   185
{
slouken@7432
   186
    if (hint && *hint == '1') {
slouken@7432
   187
        SDL_joystick_allows_background_events = SDL_TRUE;
slouken@7432
   188
    } else {
slouken@7432
   189
        SDL_joystick_allows_background_events = SDL_FALSE;
slouken@7432
   190
    }
slouken@7432
   191
}
slouken@7432
   192
slouken@1895
   193
int
slouken@1895
   194
SDL_JoystickInit(void)
slouken@0
   195
{
slouken@12088
   196
    int i, status;
philipp@7500
   197
slouken@11201
   198
    SDL_GameControllerInitMappings();
slouken@11201
   199
slouken@10659
   200
    /* Create the joystick list lock */
slouken@10659
   201
    if (!SDL_joystick_lock) {
slouken@10659
   202
        SDL_joystick_lock = SDL_CreateMutex();
slouken@10659
   203
    }
slouken@10659
   204
slouken@7432
   205
    /* See if we should allow joystick events while in the background */
slouken@7432
   206
    SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
slouken@7432
   207
                        SDL_JoystickAllowBackgroundEventsChanged, NULL);
slouken@0
   208
slouken@7360
   209
#if !SDL_EVENTS_DISABLED
slouken@7360
   210
    if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
slouken@7360
   211
        return -1;
slouken@7360
   212
    }
slouken@7360
   213
#endif /* !SDL_EVENTS_DISABLED */
slouken@7360
   214
slouken@12088
   215
    status = -1;
slouken@12088
   216
    for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
slouken@12088
   217
        if (SDL_joystick_drivers[i]->Init() >= 0) {
slouken@12088
   218
            status = 0;
slouken@12088
   219
        }
slouken@1895
   220
    }
slouken@12088
   221
    return status;
slouken@0
   222
}
slouken@0
   223
slouken@0
   224
/*
slouken@0
   225
 * Count the number of joysticks attached to the system
slouken@0
   226
 */
slouken@1895
   227
int
slouken@1895
   228
SDL_NumJoysticks(void)
slouken@0
   229
{
slouken@12088
   230
    int i, total_joysticks = 0;
slouken@12088
   231
    SDL_LockJoysticks();
slouken@12088
   232
    for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
slouken@12088
   233
        total_joysticks += SDL_joystick_drivers[i]->GetCount();
slouken@12088
   234
    }
slouken@12088
   235
    SDL_UnlockJoysticks();
slouken@12088
   236
    return total_joysticks;
slouken@12088
   237
}
slouken@12088
   238
slouken@12088
   239
/*
slouken@12088
   240
 * Return the next available joystick instance ID
slouken@12088
   241
 * This may be called by drivers from multiple threads, unprotected by any locks
slouken@12088
   242
 */
slouken@12088
   243
SDL_JoystickID SDL_GetNextJoystickInstanceID()
slouken@12088
   244
{
slouken@12088
   245
    return SDL_AtomicIncRef(&SDL_next_joystick_instance_id);
slouken@12088
   246
}
slouken@12088
   247
slouken@12088
   248
/*
slouken@12088
   249
 * Get the driver and device index for an API device index
slouken@12088
   250
 * This should be called while the joystick lock is held, to prevent another thread from updating the list
slouken@12088
   251
 */
slouken@12088
   252
SDL_bool
slouken@12088
   253
SDL_GetDriverAndJoystickIndex(int device_index, SDL_JoystickDriver **driver, int *driver_index)
slouken@12088
   254
{
slouken@12088
   255
    int i, num_joysticks, total_joysticks = 0;
slouken@12088
   256
slouken@12088
   257
    if (device_index >= 0) {
slouken@12088
   258
        for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
slouken@12088
   259
            num_joysticks = SDL_joystick_drivers[i]->GetCount();
slouken@12088
   260
            if (device_index < num_joysticks) {
slouken@12088
   261
                *driver = SDL_joystick_drivers[i];
slouken@12088
   262
                *driver_index = device_index;
slouken@12088
   263
                return SDL_TRUE;
slouken@12088
   264
            }
slouken@12088
   265
            device_index -= num_joysticks;
slouken@12088
   266
            total_joysticks += num_joysticks;
slouken@12088
   267
        }
slouken@12088
   268
    }
slouken@12088
   269
slouken@12088
   270
    SDL_SetError("There are %d joysticks available", total_joysticks);
slouken@12088
   271
    return SDL_FALSE;
slouken@0
   272
}
slouken@0
   273
slouken@0
   274
/*
slouken@11921
   275
 * Perform any needed fixups for joystick names
slouken@11921
   276
 */
slouken@11921
   277
static const char *
slouken@11921
   278
SDL_FixupJoystickName(const char *name)
slouken@11921
   279
{
slouken@11921
   280
    if (name) {
slouken@11921
   281
        const char *skip_prefix = "NVIDIA Corporation ";
slouken@11921
   282
slouken@11921
   283
        if (SDL_strncmp(name, skip_prefix, SDL_strlen(skip_prefix)) == 0) {
slouken@11921
   284
            name += SDL_strlen(skip_prefix);
slouken@11921
   285
        }
slouken@11921
   286
    }
slouken@11921
   287
    return name;
slouken@11921
   288
}
slouken@11921
   289
slouken@11921
   290
slouken@11921
   291
/*
slouken@0
   292
 * Get the implementation dependent name of a joystick
slouken@0
   293
 */
slouken@1895
   294
const char *
slouken@6690
   295
SDL_JoystickNameForIndex(int device_index)
slouken@0
   296
{
slouken@12088
   297
    SDL_JoystickDriver *driver;
slouken@12088
   298
    const char *name = NULL;
slouken@12088
   299
slouken@12088
   300
    SDL_LockJoysticks();
slouken@12088
   301
    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
slouken@12088
   302
        name = SDL_FixupJoystickName(driver->GetDeviceName(device_index));
slouken@1895
   303
    }
slouken@12088
   304
    SDL_UnlockJoysticks();
slouken@12088
   305
slouken@12088
   306
    /* FIXME: Really we should reference count this name so it doesn't go away after unlock */
slouken@12088
   307
    return name;
slouken@0
   308
}
slouken@0
   309
slouken@13369
   310
/*
slouken@13369
   311
 *  Get the player index of a joystick, or -1 if it's not available
slouken@13369
   312
 */
slouken@12359
   313
int
slouken@12359
   314
SDL_JoystickGetDevicePlayerIndex(int device_index)
slouken@12359
   315
{
slouken@13369
   316
    int player_index;
slouken@12359
   317
slouken@12359
   318
    SDL_LockJoysticks();
slouken@13369
   319
    player_index = SDL_GetPlayerIndexForJoystickID(SDL_JoystickGetDeviceInstanceID(device_index));
slouken@12359
   320
    SDL_UnlockJoysticks();
slouken@12359
   321
slouken@12359
   322
    return player_index;
slouken@12359
   323
}
slouken@12359
   324
slouken@0
   325
/*
slouken@10745
   326
 * Return true if this joystick is known to have all axes centered at zero
slouken@10745
   327
 * This isn't generally needed unless the joystick never generates an initial axis value near zero,
slouken@10745
   328
 * e.g. it's emulating axes with digital buttons
slouken@10745
   329
 */
slouken@10745
   330
static SDL_bool
slouken@10745
   331
SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick)
slouken@10745
   332
{
slouken@10855
   333
    static Uint32 zero_centered_joysticks[] = {
slouken@10855
   334
        MAKE_VIDPID(0x0e8f, 0x3013),    /* HuiJia SNES USB adapter */
slouken@10855
   335
        MAKE_VIDPID(0x05a0, 0x3232),    /* 8Bitdo Zero Gamepad */
slouken@10745
   336
    };
slouken@10745
   337
slouken@10745
   338
    int i;
slouken@10855
   339
    Uint32 id = MAKE_VIDPID(SDL_JoystickGetVendor(joystick),
slouken@10855
   340
                            SDL_JoystickGetProduct(joystick));
slouken@10745
   341
slouken@10823
   342
/*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/
slouken@10823
   343
slouken@10751
   344
    if (joystick->naxes == 2) {
slouken@10751
   345
        /* Assume D-pad or thumbstick style axes are centered at 0 */
slouken@10751
   346
        return SDL_TRUE;
slouken@10751
   347
    }
slouken@10751
   348
slouken@10745
   349
    for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) {
slouken@10855
   350
        if (id == zero_centered_joysticks[i]) {
slouken@10745
   351
            return SDL_TRUE;
slouken@10745
   352
        }
slouken@10745
   353
    }
slouken@10745
   354
    return SDL_FALSE;
slouken@10745
   355
}
slouken@10745
   356
slouken@10745
   357
/*
slouken@0
   358
 * Open a joystick for use - the index passed as an argument refers to
slouken@0
   359
 * the N'th joystick on the system.  This index is the value which will
slouken@0
   360
 * identify this joystick in future joystick events.
slouken@0
   361
 *
slouken@0
   362
 * This function returns a joystick identifier, or NULL if an error occurred.
slouken@0
   363
 */
slouken@1895
   364
SDL_Joystick *
slouken@1895
   365
SDL_JoystickOpen(int device_index)
slouken@0
   366
{
slouken@12088
   367
    SDL_JoystickDriver *driver;
slouken@12088
   368
    SDL_JoystickID instance_id;
slouken@1895
   369
    SDL_Joystick *joystick;
slouken@7191
   370
    SDL_Joystick *joysticklist;
slouken@7191
   371
    const char *joystickname = NULL;
slouken@0
   372
slouken@12088
   373
    SDL_LockJoysticks();
slouken@12088
   374
slouken@12088
   375
    if (!SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
slouken@12088
   376
        SDL_UnlockJoysticks();
slouken@12088
   377
        return NULL;
slouken@1895
   378
    }
slouken@0
   379
slouken@7191
   380
    joysticklist = SDL_joysticks;
slouken@7191
   381
    /* If the joystick is already open, return it
slouken@10934
   382
     * it is important that we have a single joystick * for each instance id
slouken@10934
   383
     */
slouken@12088
   384
    instance_id = driver->GetDeviceInstanceID(device_index);
slouken@8920
   385
    while (joysticklist) {
slouken@12088
   386
        if (instance_id == joysticklist->instance_id) {
slouken@7191
   387
                joystick = joysticklist;
slouken@7191
   388
                ++joystick->ref_count;
slouken@11581
   389
                SDL_UnlockJoysticks();
slouken@12088
   390
                return joystick;
slouken@7191
   391
        }
slouken@7191
   392
        joysticklist = joysticklist->next;
slouken@1895
   393
    }
slouken@0
   394
slouken@1895
   395
    /* Create and initialize the joystick */
slouken@10855
   396
    joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
icculus@3608
   397
    if (joystick == NULL) {
icculus@3608
   398
        SDL_OutOfMemory();
slouken@11581
   399
        SDL_UnlockJoysticks();
icculus@3608
   400
        return NULL;
icculus@3608
   401
    }
slouken@12088
   402
    joystick->driver = driver;
slouken@12088
   403
    joystick->instance_id = instance_id;
slouken@12090
   404
    joystick->attached = SDL_TRUE;
zack@12893
   405
    joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
icculus@3608
   406
slouken@12088
   407
    if (driver->Open(joystick, device_index) < 0) {
icculus@3608
   408
        SDL_free(joystick);
slouken@11581
   409
        SDL_UnlockJoysticks();
icculus@3608
   410
        return NULL;
icculus@3608
   411
    }
slouken@6690
   412
slouken@12088
   413
    joystickname = driver->GetDeviceName(device_index);
slouken@12088
   414
    if (joystickname) {
slouken@8920
   415
        joystick->name = SDL_strdup(joystickname);
slouken@12088
   416
    } else {
slouken@7191
   417
        joystick->name = NULL;
slouken@12088
   418
    }
slouken@12088
   419
slouken@12088
   420
    joystick->guid = driver->GetDeviceGUID(device_index);
slouken@6690
   421
icculus@3608
   422
    if (joystick->naxes > 0) {
slouken@10713
   423
        joystick->axes = (SDL_JoystickAxisInfo *) SDL_calloc(joystick->naxes, sizeof(SDL_JoystickAxisInfo));
icculus@3608
   424
    }
icculus@3608
   425
    if (joystick->nhats > 0) {
slouken@10713
   426
        joystick->hats = (Uint8 *) SDL_calloc(joystick->nhats, sizeof(Uint8));
icculus@3608
   427
    }
icculus@3608
   428
    if (joystick->nballs > 0) {
slouken@10713
   429
        joystick->balls = (struct balldelta *) SDL_calloc(joystick->nballs, sizeof(*joystick->balls));
icculus@3608
   430
    }
icculus@3608
   431
    if (joystick->nbuttons > 0) {
slouken@10713
   432
        joystick->buttons = (Uint8 *) SDL_calloc(joystick->nbuttons, sizeof(Uint8));
slouken@1895
   433
    }
icculus@3608
   434
    if (((joystick->naxes > 0) && !joystick->axes)
icculus@3608
   435
        || ((joystick->nhats > 0) && !joystick->hats)
icculus@3608
   436
        || ((joystick->nballs > 0) && !joystick->balls)
icculus@3608
   437
        || ((joystick->nbuttons > 0) && !joystick->buttons)) {
icculus@3608
   438
        SDL_OutOfMemory();
icculus@3608
   439
        SDL_JoystickClose(joystick);
slouken@11581
   440
        SDL_UnlockJoysticks();
icculus@3608
   441
        return NULL;
icculus@3608
   442
    }
icculus@3608
   443
slouken@10745
   444
    /* If this joystick is known to have all zero centered axes, skip the auto-centering code */
slouken@10745
   445
    if (SDL_JoystickAxesCenteredAtZero(joystick)) {
slouken@10745
   446
        int i;
slouken@10745
   447
slouken@10745
   448
        for (i = 0; i < joystick->naxes; ++i) {
slouken@10745
   449
            joystick->axes[i].has_initial_value = SDL_TRUE;
slouken@10745
   450
        }
slouken@10745
   451
    }
slouken@10745
   452
slouken@10855
   453
    joystick->is_game_controller = SDL_IsGameController(device_index);
slouken@10855
   454
icculus@3608
   455
    /* Add joystick to list */
icculus@3608
   456
    ++joystick->ref_count;
slouken@7191
   457
    /* Link the joystick in the list */
slouken@7191
   458
    joystick->next = SDL_joysticks;
slouken@7191
   459
    SDL_joysticks = joystick;
slouken@6690
   460
slouken@11581
   461
    SDL_UnlockJoysticks();
icculus@3608
   462
slouken@12088
   463
    driver->Update(joystick);
slouken@10659
   464
slouken@12088
   465
    return joystick;
slouken@0
   466
}
slouken@0
   467
slouken@2713
   468
slouken@2713
   469
/*
slouken@2713
   470
 * Checks to make sure the joystick is valid.
slouken@2713
   471
 */
slouken@13369
   472
SDL_bool
slouken@6690
   473
SDL_PrivateJoystickValid(SDL_Joystick * joystick)
slouken@0
   474
{
slouken@13369
   475
    SDL_bool valid;
slouken@0
   476
slouken@8920
   477
    if (joystick == NULL) {
slouken@1895
   478
        SDL_SetError("Joystick hasn't been opened yet");
slouken@13369
   479
        valid = SDL_FALSE;
slouken@1895
   480
    } else {
slouken@13369
   481
        valid = SDL_TRUE;
slouken@1895
   482
    }
slouken@7191
   483
slouken@1895
   484
    return valid;
slouken@0
   485
}
slouken@0
   486
slouken@0
   487
/*
slouken@0
   488
 * Get the number of multi-dimensional axis controls on a joystick
slouken@0
   489
 */
slouken@1895
   490
int
slouken@1895
   491
SDL_JoystickNumAxes(SDL_Joystick * joystick)
slouken@0
   492
{
slouken@6690
   493
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   494
        return -1;
slouken@1895
   495
    }
slouken@12088
   496
    return joystick->naxes;
slouken@0
   497
}
slouken@0
   498
slouken@0
   499
/*
slouken@0
   500
 * Get the number of hats on a joystick
slouken@0
   501
 */
slouken@1895
   502
int
slouken@1895
   503
SDL_JoystickNumHats(SDL_Joystick * joystick)
slouken@0
   504
{
slouken@6690
   505
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   506
        return -1;
slouken@1895
   507
    }
slouken@12088
   508
    return joystick->nhats;
slouken@0
   509
}
slouken@0
   510
slouken@0
   511
/*
slouken@0
   512
 * Get the number of trackballs on a joystick
slouken@0
   513
 */
slouken@1895
   514
int
slouken@1895
   515
SDL_JoystickNumBalls(SDL_Joystick * joystick)
slouken@0
   516
{
slouken@6690
   517
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   518
        return -1;
slouken@1895
   519
    }
slouken@12088
   520
    return joystick->nballs;
slouken@0
   521
}
slouken@0
   522
slouken@0
   523
/*
slouken@0
   524
 * Get the number of buttons on a joystick
slouken@0
   525
 */
slouken@1895
   526
int
slouken@1895
   527
SDL_JoystickNumButtons(SDL_Joystick * joystick)
slouken@0
   528
{
slouken@6690
   529
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   530
        return -1;
slouken@1895
   531
    }
slouken@12088
   532
    return joystick->nbuttons;
slouken@0
   533
}
slouken@0
   534
slouken@0
   535
/*
slouken@0
   536
 * Get the current state of an axis control on a joystick
slouken@0
   537
 */
slouken@1895
   538
Sint16
slouken@1895
   539
SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
slouken@0
   540
{
slouken@1895
   541
    Sint16 state;
slouken@0
   542
slouken@6690
   543
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   544
        return 0;
slouken@1895
   545
    }
slouken@1895
   546
    if (axis < joystick->naxes) {
slouken@10713
   547
        state = joystick->axes[axis].value;
slouken@1895
   548
    } else {
slouken@1895
   549
        SDL_SetError("Joystick only has %d axes", joystick->naxes);
slouken@1895
   550
        state = 0;
slouken@1895
   551
    }
slouken@12088
   552
    return state;
slouken@0
   553
}
slouken@0
   554
slouken@0
   555
/*
slouken@10752
   556
 * Get the initial state of an axis control on a joystick
slouken@10752
   557
 */
slouken@10752
   558
SDL_bool
slouken@10752
   559
SDL_JoystickGetAxisInitialState(SDL_Joystick * joystick, int axis, Sint16 *state)
slouken@10752
   560
{
slouken@10752
   561
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@10752
   562
        return SDL_FALSE;
slouken@10752
   563
    }
slouken@10752
   564
    if (axis >= joystick->naxes) {
slouken@10752
   565
        SDL_SetError("Joystick only has %d axes", joystick->naxes);
slouken@10752
   566
        return SDL_FALSE;
slouken@10752
   567
    }
slouken@10752
   568
    if (state) {
slouken@10752
   569
        *state = joystick->axes[axis].initial_value;
slouken@10752
   570
    }
slouken@10752
   571
    return joystick->axes[axis].has_initial_value;
slouken@10752
   572
}
slouken@10752
   573
slouken@10752
   574
/*
slouken@0
   575
 * Get the current state of a hat on a joystick
slouken@0
   576
 */
slouken@1895
   577
Uint8
slouken@1895
   578
SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
slouken@0
   579
{
slouken@1895
   580
    Uint8 state;
slouken@0
   581
slouken@6690
   582
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   583
        return 0;
slouken@1895
   584
    }
slouken@1895
   585
    if (hat < joystick->nhats) {
slouken@1895
   586
        state = joystick->hats[hat];
slouken@1895
   587
    } else {
slouken@1895
   588
        SDL_SetError("Joystick only has %d hats", joystick->nhats);
slouken@1895
   589
        state = 0;
slouken@1895
   590
    }
slouken@12088
   591
    return state;
slouken@0
   592
}
slouken@0
   593
slouken@0
   594
/*
slouken@0
   595
 * Get the ball axis change since the last poll
slouken@0
   596
 */
slouken@1895
   597
int
slouken@1895
   598
SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
slouken@0
   599
{
slouken@1895
   600
    int retval;
slouken@0
   601
slouken@6690
   602
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   603
        return -1;
slouken@1895
   604
    }
slouken@0
   605
slouken@1895
   606
    retval = 0;
slouken@1895
   607
    if (ball < joystick->nballs) {
slouken@1895
   608
        if (dx) {
slouken@1895
   609
            *dx = joystick->balls[ball].dx;
slouken@1895
   610
        }
slouken@1895
   611
        if (dy) {
slouken@1895
   612
            *dy = joystick->balls[ball].dy;
slouken@1895
   613
        }
slouken@1895
   614
        joystick->balls[ball].dx = 0;
slouken@1895
   615
        joystick->balls[ball].dy = 0;
slouken@1895
   616
    } else {
icculus@7037
   617
        return SDL_SetError("Joystick only has %d balls", joystick->nballs);
slouken@1895
   618
    }
slouken@12088
   619
    return retval;
slouken@0
   620
}
slouken@0
   621
slouken@0
   622
/*
slouken@0
   623
 * Get the current state of a button on a joystick
slouken@0
   624
 */
slouken@1895
   625
Uint8
slouken@1895
   626
SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
slouken@0
   627
{
slouken@1895
   628
    Uint8 state;
slouken@0
   629
slouken@6690
   630
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   631
        return 0;
slouken@1895
   632
    }
slouken@1895
   633
    if (button < joystick->nbuttons) {
slouken@1895
   634
        state = joystick->buttons[button];
slouken@1895
   635
    } else {
slouken@1895
   636
        SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
slouken@1895
   637
        state = 0;
slouken@1895
   638
    }
slouken@12088
   639
    return state;
slouken@0
   640
}
slouken@0
   641
slouken@0
   642
/*
slouken@6690
   643
 * Return if the joystick in question is currently attached to the system,
philipp@7500
   644
 *  \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
slouken@6690
   645
 */
slouken@6707
   646
SDL_bool
slouken@6707
   647
SDL_JoystickGetAttached(SDL_Joystick * joystick)
slouken@6690
   648
{
slouken@7191
   649
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6707
   650
        return SDL_FALSE;
slouken@6690
   651
    }
slouken@6690
   652
slouken@12090
   653
    return joystick->attached;
slouken@6690
   654
}
slouken@6690
   655
slouken@6690
   656
/*
slouken@6690
   657
 * Get the instance id for this opened joystick
slouken@6690
   658
 */
slouken@7191
   659
SDL_JoystickID
slouken@6707
   660
SDL_JoystickInstanceID(SDL_Joystick * joystick)
slouken@6690
   661
{
slouken@7191
   662
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   663
        return -1;
slouken@6690
   664
    }
slouken@6690
   665
slouken@12088
   666
    return joystick->instance_id;
slouken@6690
   667
}
slouken@6690
   668
slouken@6690
   669
/*
slouken@13369
   670
 * Return the SDL_Joystick associated with an instance id.
icculus@9916
   671
 */
icculus@9916
   672
SDL_Joystick *
slouken@13369
   673
SDL_JoystickFromInstanceID(SDL_JoystickID instance_id)
icculus@9916
   674
{
slouken@10659
   675
    SDL_Joystick *joystick;
slouken@10659
   676
slouken@11581
   677
    SDL_LockJoysticks();
slouken@10659
   678
    for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
slouken@13369
   679
        if (joystick->instance_id == instance_id) {
slouken@13369
   680
            break;
slouken@13369
   681
        }
slouken@13369
   682
    }
slouken@13369
   683
    SDL_UnlockJoysticks();
slouken@13369
   684
    return joystick;
slouken@13369
   685
}
slouken@13369
   686
slouken@13369
   687
/**
slouken@13369
   688
 * Return the SDL_Joystick associated with a player index.
slouken@13369
   689
 */
slouken@13369
   690
SDL_Joystick *
slouken@13369
   691
SDL_JoystickFromPlayerIndex(int player_index)
slouken@13369
   692
{
slouken@13369
   693
    SDL_JoystickID instance_id;
slouken@13369
   694
    SDL_Joystick *joystick;
slouken@13369
   695
slouken@13369
   696
    SDL_LockJoysticks();
slouken@13369
   697
    instance_id = SDL_GetJoystickIDForPlayerIndex(player_index);
slouken@13369
   698
    for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
slouken@13369
   699
        if (joystick->instance_id == instance_id) {
slouken@12122
   700
            break;
icculus@9916
   701
        }
icculus@9916
   702
    }
slouken@11581
   703
    SDL_UnlockJoysticks();
slouken@12122
   704
    return joystick;
icculus@9916
   705
}
icculus@9916
   706
icculus@9916
   707
/*
slouken@6690
   708
 * Get the friendly name of this joystick
slouken@6690
   709
 */
slouken@6690
   710
const char *
slouken@6690
   711
SDL_JoystickName(SDL_Joystick * joystick)
slouken@6690
   712
{
slouken@6690
   713
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   714
        return NULL;
slouken@6690
   715
    }
slouken@7191
   716
slouken@11921
   717
    return SDL_FixupJoystickName(joystick->name);
slouken@6690
   718
}
slouken@6690
   719
slouken@13369
   720
/**
slouken@13369
   721
 *  Get the player index of an opened joystick, or -1 if it's not available
slouken@13369
   722
 */
slouken@12088
   723
int
slouken@12359
   724
SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick)
slouken@12359
   725
{
slouken@13369
   726
    int player_index;
slouken@13369
   727
slouken@12359
   728
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12359
   729
        return -1;
slouken@12359
   730
    }
slouken@13369
   731
slouken@13369
   732
    SDL_LockJoysticks();
slouken@13369
   733
    player_index = SDL_GetPlayerIndexForJoystickID(joystick->instance_id);
slouken@13369
   734
    SDL_UnlockJoysticks();
slouken@13369
   735
slouken@13369
   736
    return player_index;
slouken@13369
   737
}
slouken@13369
   738
slouken@13369
   739
/**
slouken@13369
   740
 *  Set the player index of an opened joystick
slouken@13369
   741
 */
slouken@13369
   742
void
slouken@13369
   743
SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index)
slouken@13369
   744
{
slouken@13369
   745
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@13369
   746
        return;
slouken@13369
   747
    }
slouken@13369
   748
slouken@13369
   749
    SDL_LockJoysticks();
slouken@13369
   750
    SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id);
slouken@13369
   751
    SDL_UnlockJoysticks();
slouken@12359
   752
}
slouken@12359
   753
slouken@12359
   754
int
slouken@12088
   755
SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
slouken@12088
   756
{
slouken@13429
   757
    int result;
slouken@13413
   758
slouken@12088
   759
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
   760
        return -1;
slouken@12088
   761
    }
slouken@13413
   762
slouken@13429
   763
    SDL_LockJoysticks();
slouken@13480
   764
    if (low_frequency_rumble == joystick->low_frequency_rumble &&
slouken@13480
   765
        high_frequency_rumble == joystick->high_frequency_rumble) {
slouken@13480
   766
        /* Just update the expiration */
slouken@13480
   767
        result = 0;
slouken@13480
   768
    } else {
slouken@13480
   769
        result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble);
slouken@13480
   770
    }
slouken@13480
   771
slouken@13480
   772
    /* Save the rumble value regardless of success, so we don't spam the driver */
slouken@13480
   773
    joystick->low_frequency_rumble = low_frequency_rumble;
slouken@13480
   774
    joystick->high_frequency_rumble = high_frequency_rumble;
slouken@13480
   775
slouken@13480
   776
    if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
slouken@13480
   777
        joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
slouken@13480
   778
        if (!joystick->rumble_expiration) {
slouken@13480
   779
            joystick->rumble_expiration = 1;
slouken@13480
   780
        }
slouken@13480
   781
    } else {
slouken@13480
   782
        joystick->rumble_expiration = 0;
slouken@13480
   783
    }
slouken@13429
   784
    SDL_UnlockJoysticks();
slouken@13413
   785
slouken@13429
   786
    return result;
slouken@12088
   787
}
slouken@12088
   788
slouken@6690
   789
/*
slouken@0
   790
 * Close a joystick previously opened with SDL_JoystickOpen()
slouken@0
   791
 */
slouken@1895
   792
void
slouken@1895
   793
SDL_JoystickClose(SDL_Joystick * joystick)
slouken@0
   794
{
slouken@7191
   795
    SDL_Joystick *joysticklist;
slouken@7191
   796
    SDL_Joystick *joysticklistprev;
slouken@0
   797
slouken@12088
   798
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   799
        return;
slouken@1895
   800
    }
slouken@0
   801
slouken@11581
   802
    SDL_LockJoysticks();
slouken@10659
   803
slouken@1895
   804
    /* First decrement ref count */
slouken@1895
   805
    if (--joystick->ref_count > 0) {
slouken@11581
   806
        SDL_UnlockJoysticks();
slouken@1895
   807
        return;
slouken@1895
   808
    }
slouken@0
   809
slouken@10704
   810
    if (SDL_updating_joystick) {
slouken@11581
   811
        SDL_UnlockJoysticks();
slouken@6712
   812
        return;
slouken@6712
   813
    }
slouken@6712
   814
slouken@13480
   815
    if (joystick->rumble_expiration) {
slouken@13480
   816
        SDL_JoystickRumble(joystick, 0, 0, 0);
slouken@13480
   817
    }
slouken@13480
   818
slouken@12088
   819
    joystick->driver->Close(joystick);
icculus@9433
   820
    joystick->hwdata = NULL;
slouken@0
   821
slouken@7191
   822
    joysticklist = SDL_joysticks;
slouken@7191
   823
    joysticklistprev = NULL;
slouken@8920
   824
    while (joysticklist) {
slouken@8920
   825
        if (joystick == joysticklist) {
slouken@8920
   826
            if (joysticklistprev) {
slouken@7191
   827
                /* unlink this entry */
slouken@7191
   828
                joysticklistprev->next = joysticklist->next;
slouken@8920
   829
            } else {
slouken@7191
   830
                SDL_joysticks = joystick->next;
slouken@7191
   831
            }
slouken@7191
   832
            break;
slouken@7191
   833
        }
slouken@7191
   834
        joysticklistprev = joysticklist;
slouken@7191
   835
        joysticklist = joysticklist->next;
slouken@7191
   836
    }
slouken@7191
   837
slouken@7719
   838
    SDL_free(joystick->name);
slouken@0
   839
slouken@1895
   840
    /* Free the data associated with this joystick */
slouken@7719
   841
    SDL_free(joystick->axes);
slouken@7719
   842
    SDL_free(joystick->hats);
slouken@7719
   843
    SDL_free(joystick->balls);
slouken@7719
   844
    SDL_free(joystick->buttons);
slouken@1895
   845
    SDL_free(joystick);
slouken@10659
   846
slouken@11581
   847
    SDL_UnlockJoysticks();
slouken@0
   848
}
slouken@0
   849
slouken@1895
   850
void
slouken@1895
   851
SDL_JoystickQuit(void)
slouken@0
   852
{
slouken@12088
   853
    int i;
slouken@12088
   854
slouken@6712
   855
    /* Make sure we're not getting called in the middle of updating joysticks */
slouken@11581
   856
    SDL_LockJoysticks();
slouken@12672
   857
    while (SDL_updating_joystick) {
slouken@12672
   858
        SDL_UnlockJoysticks();
slouken@12672
   859
        SDL_Delay(1);
slouken@12672
   860
        SDL_LockJoysticks();
slouken@12672
   861
    }
slouken@10659
   862
slouken@1895
   863
    /* Stop the event polling */
slouken@8920
   864
    while (SDL_joysticks) {
slouken@7191
   865
        SDL_joysticks->ref_count = 1;
slouken@6690
   866
        SDL_JoystickClose(SDL_joysticks);
slouken@7191
   867
    }
icculus@5856
   868
slouken@1895
   869
    /* Quit the joystick setup */
slouken@12088
   870
    for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
slouken@12088
   871
       SDL_joystick_drivers[i]->Quit();
slouken@12088
   872
    }
slouken@7360
   873
slouken@13369
   874
    if (SDL_joystick_players) {
slouken@13369
   875
        SDL_free(SDL_joystick_players);
slouken@13369
   876
        SDL_joystick_players = NULL;
slouken@13369
   877
        SDL_joystick_player_count = 0;
slouken@13369
   878
    }
slouken@11581
   879
    SDL_UnlockJoysticks();
slouken@10659
   880
slouken@7360
   881
#if !SDL_EVENTS_DISABLED
slouken@7360
   882
    SDL_QuitSubSystem(SDL_INIT_EVENTS);
slouken@7360
   883
#endif
slouken@10659
   884
slouken@11201
   885
    SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
slouken@11201
   886
                        SDL_JoystickAllowBackgroundEventsChanged, NULL);
slouken@11201
   887
slouken@10659
   888
    if (SDL_joystick_lock) {
slouken@12672
   889
        SDL_mutex *mutex = SDL_joystick_lock;
slouken@10659
   890
        SDL_joystick_lock = NULL;
slouken@12672
   891
        SDL_DestroyMutex(mutex);
slouken@10659
   892
    }
slouken@11201
   893
slouken@11201
   894
    SDL_GameControllerQuitMappings();
slouken@0
   895
}
slouken@0
   896
slouken@0
   897
jorgen@7279
   898
static SDL_bool
jorgen@7279
   899
SDL_PrivateJoystickShouldIgnoreEvent()
jorgen@7279
   900
{
slouken@8920
   901
    if (SDL_joystick_allows_background_events) {
jorgen@7279
   902
        return SDL_FALSE;
jorgen@7279
   903
    }
jorgen@7279
   904
slouken@11255
   905
    if (SDL_HasWindows() && SDL_GetKeyboardFocus() == NULL) {
slouken@11255
   906
        /* We have windows but we don't have focus, ignore the event. */
slouken@11255
   907
        return SDL_TRUE;
jorgen@7279
   908
    }
slouken@7337
   909
    return SDL_FALSE;
jorgen@7279
   910
}
jorgen@7279
   911
slouken@0
   912
/* These are global for SDL_sysjoystick.c and SDL_events.c */
slouken@0
   913
slouken@12088
   914
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
slouken@10226
   915
{
slouken@13369
   916
    SDL_JoystickDriver *driver;
slouken@13369
   917
    int driver_device_index;
slouken@13369
   918
    int player_index = -1;
slouken@13369
   919
    int device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance);
slouken@12088
   920
    if (device_index < 0) {
slouken@12088
   921
        return;
slouken@12088
   922
    }
slouken@10226
   923
slouken@13369
   924
    SDL_LockJoysticks();
slouken@13369
   925
    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
slouken@13369
   926
        player_index = driver->GetDevicePlayerIndex(driver_device_index);
slouken@13369
   927
    }
slouken@13369
   928
    if (player_index < 0 && SDL_IsGameController(device_index)) {
slouken@13369
   929
        player_index = SDL_FindFreePlayerIndex();
slouken@13369
   930
    }
slouken@13369
   931
    if (player_index >= 0) {
slouken@13369
   932
        SDL_SetJoystickIDForPlayerIndex(player_index, device_instance);
slouken@13369
   933
    }
slouken@13369
   934
    SDL_UnlockJoysticks();
slouken@10226
   935
slouken@13369
   936
#if !SDL_EVENTS_DISABLED
slouken@13369
   937
    {
slouken@13369
   938
        SDL_Event event;
slouken@13369
   939
slouken@13369
   940
        event.type = SDL_JOYDEVICEADDED;
slouken@13369
   941
slouken@13369
   942
        if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@13369
   943
            event.jdevice.which = device_index;
slouken@13369
   944
            SDL_PushEvent(&event);
slouken@13369
   945
        }
slouken@10226
   946
    }
slouken@10226
   947
#endif /* !SDL_EVENTS_DISABLED */
slouken@10226
   948
}
slouken@10226
   949
slouken@10226
   950
/*
slouken@10226
   951
 * If there is an existing add event in the queue, it needs to be modified
slouken@10226
   952
 * to have the right value for which, because the number of controllers in
slouken@10226
   953
 * the system is now one less.
slouken@10226
   954
 */
slouken@10226
   955
static void UpdateEventsForDeviceRemoval()
slouken@10226
   956
{
slouken@10226
   957
    int i, num_events;
slouken@10226
   958
    SDL_Event *events;
icculus@12349
   959
    SDL_bool isstack;
slouken@10226
   960
slouken@10226
   961
    num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
slouken@10226
   962
    if (num_events <= 0) {
slouken@10226
   963
        return;
slouken@10226
   964
    }
slouken@10226
   965
icculus@12349
   966
    events = SDL_small_alloc(SDL_Event, num_events, &isstack);
slouken@10226
   967
    if (!events) {
slouken@10226
   968
        return;
slouken@10226
   969
    }
slouken@10226
   970
slouken@10226
   971
    num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
slouken@10226
   972
    for (i = 0; i < num_events; ++i) {
slouken@10226
   973
        --events[i].jdevice.which;
slouken@10226
   974
    }
slouken@10226
   975
    SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
slouken@10226
   976
icculus@12349
   977
    SDL_small_free(events, isstack);
slouken@10226
   978
}
slouken@10226
   979
slouken@10226
   980
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
slouken@10226
   981
{
slouken@12090
   982
    SDL_Joystick *joystick;
slouken@13412
   983
    int player_index;
slouken@12090
   984
slouken@10226
   985
#if !SDL_EVENTS_DISABLED
slouken@10226
   986
    SDL_Event event;
slouken@10226
   987
slouken@10226
   988
    event.type = SDL_JOYDEVICEREMOVED;
slouken@10226
   989
slouken@10226
   990
    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@10226
   991
        event.jdevice.which = device_instance;
slouken@11584
   992
        SDL_PushEvent(&event);
slouken@10226
   993
    }
slouken@10226
   994
slouken@10226
   995
    UpdateEventsForDeviceRemoval();
slouken@10226
   996
#endif /* !SDL_EVENTS_DISABLED */
slouken@12090
   997
slouken@12090
   998
    /* Mark this joystick as no longer attached */
slouken@12090
   999
    for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
slouken@12090
  1000
        if (joystick->instance_id == device_instance) {
slouken@12090
  1001
            joystick->attached = SDL_FALSE;
slouken@12090
  1002
            joystick->force_recentering = SDL_TRUE;
slouken@12090
  1003
            break;
slouken@12090
  1004
        }
slouken@12090
  1005
    }
slouken@13412
  1006
slouken@13412
  1007
    SDL_LockJoysticks();
slouken@13412
  1008
    player_index = SDL_GetPlayerIndexForJoystickID(device_instance);
slouken@13412
  1009
    if (player_index >= 0) {
slouken@13412
  1010
        SDL_joystick_players[player_index] = -1;
slouken@13412
  1011
    }
slouken@13412
  1012
    SDL_UnlockJoysticks();
slouken@10226
  1013
}
slouken@10226
  1014
slouken@1895
  1015
int
slouken@1895
  1016
SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
slouken@0
  1017
{
slouken@1895
  1018
    int posted;
slouken@13302
  1019
    SDL_JoystickAxisInfo *info;
slouken@0
  1020
slouken@8920
  1021
    /* Make sure we're not getting garbage or duplicate events */
slouken@6145
  1022
    if (axis >= joystick->naxes) {
slouken@6145
  1023
        return 0;
slouken@6145
  1024
    }
slouken@13302
  1025
slouken@13302
  1026
    info = &joystick->axes[axis];
slouken@13302
  1027
    if (!info->has_initial_value ||
slouken@13347
  1028
        (!info->has_second_value && (info->initial_value == -32768 || info->initial_value == 32767) && SDL_abs(value) < (SDL_JOYSTICK_AXIS_MAX / 4))) {
slouken@13302
  1029
        info->initial_value = value;
slouken@13302
  1030
        info->value = value;
slouken@13302
  1031
        info->zero = value;
slouken@13302
  1032
        info->has_initial_value = SDL_TRUE;
slouken@13302
  1033
    } else {
slouken@13302
  1034
        info->has_second_value = SDL_TRUE;
slouken@10745
  1035
    }
slouken@13302
  1036
    if (value == info->value) {
slouken@11520
  1037
        return 0;
slouken@11520
  1038
    }
slouken@13302
  1039
    if (!info->sent_initial_value) {
slouken@11512
  1040
        /* Make sure we don't send motion until there's real activity on this axis */
slouken@11512
  1041
        const int MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80;  /* ShanWan PS3 controller needed 96 */
slouken@13302
  1042
        if (SDL_abs(value - info->value) <= MAX_ALLOWED_JITTER) {
slouken@11512
  1043
            return 0;
slouken@11512
  1044
        }
slouken@13302
  1045
        info->sent_initial_value = SDL_TRUE;
slouken@13302
  1046
        info->value = value; /* Just so we pass the check above */
slouken@13302
  1047
        SDL_PrivateJoystickAxis(joystick, axis, info->initial_value);
slouken@10713
  1048
    }
slouken@6145
  1049
slouken@8903
  1050
    /* We ignore events if we don't have keyboard focus, except for centering
slouken@8903
  1051
     * events.
slouken@8903
  1052
     */
slouken@8903
  1053
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
slouken@13302
  1054
        if ((value > info->zero && value >= info->value) ||
slouken@13302
  1055
            (value < info->zero && value <= info->value)) {
slouken@8903
  1056
            return 0;
slouken@8903
  1057
        }
slouken@8903
  1058
    }
slouken@8903
  1059
slouken@1895
  1060
    /* Update internal joystick state */
slouken@13302
  1061
    info->value = value;
slouken@0
  1062
slouken@1895
  1063
    /* Post the event, if desired */
slouken@1895
  1064
    posted = 0;
slouken@1361
  1065
#if !SDL_EVENTS_DISABLED
slouken@4429
  1066
    if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
slouken@1895
  1067
        SDL_Event event;
slouken@1895
  1068
        event.type = SDL_JOYAXISMOTION;
slouken@6690
  1069
        event.jaxis.which = joystick->instance_id;
slouken@1895
  1070
        event.jaxis.axis = axis;
slouken@1895
  1071
        event.jaxis.value = value;
slouken@6690
  1072
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
  1073
    }
slouken@1361
  1074
#endif /* !SDL_EVENTS_DISABLED */
slouken@12088
  1075
    return posted;
slouken@0
  1076
}
slouken@0
  1077
slouken@1895
  1078
int
slouken@1895
  1079
SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
slouken@0
  1080
{
slouken@1895
  1081
    int posted;
slouken@0
  1082
slouken@8920
  1083
    /* Make sure we're not getting garbage or duplicate events */
slouken@6145
  1084
    if (hat >= joystick->nhats) {
slouken@6145
  1085
        return 0;
slouken@6145
  1086
    }
slouken@8920
  1087
    if (value == joystick->hats[hat]) {
slouken@8920
  1088
        return 0;
slouken@8920
  1089
    }
slouken@6145
  1090
jorgen@7279
  1091
    /* We ignore events if we don't have keyboard focus, except for centering
jorgen@7279
  1092
     * events.
jorgen@7279
  1093
     */
jorgen@7279
  1094
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
slouken@8903
  1095
        if (value != SDL_HAT_CENTERED) {
jorgen@7279
  1096
            return 0;
jorgen@7279
  1097
        }
jorgen@7279
  1098
    }
jorgen@7279
  1099
slouken@8903
  1100
    /* Update internal joystick state */
slouken@8903
  1101
    joystick->hats[hat] = value;
jorgen@7279
  1102
slouken@1895
  1103
    /* Post the event, if desired */
slouken@1895
  1104
    posted = 0;
slouken@1361
  1105
#if !SDL_EVENTS_DISABLED
slouken@4429
  1106
    if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
slouken@1895
  1107
        SDL_Event event;
slouken@1895
  1108
        event.jhat.type = SDL_JOYHATMOTION;
slouken@6690
  1109
        event.jhat.which = joystick->instance_id;
slouken@1895
  1110
        event.jhat.hat = hat;
slouken@1895
  1111
        event.jhat.value = value;
slouken@6690
  1112
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
  1113
    }
slouken@1361
  1114
#endif /* !SDL_EVENTS_DISABLED */
slouken@12088
  1115
    return posted;
slouken@0
  1116
}
slouken@0
  1117
slouken@1895
  1118
int
slouken@1895
  1119
SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
slouken@1895
  1120
                        Sint16 xrel, Sint16 yrel)
slouken@0
  1121
{
slouken@1895
  1122
    int posted;
slouken@0
  1123
slouken@6145
  1124
    /* Make sure we're not getting garbage events */
slouken@6145
  1125
    if (ball >= joystick->nballs) {
slouken@6145
  1126
        return 0;
slouken@6145
  1127
    }
slouken@6145
  1128
jorgen@7279
  1129
    /* We ignore events if we don't have keyboard focus. */
jorgen@7279
  1130
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
jorgen@7279
  1131
        return 0;
jorgen@7279
  1132
    }
jorgen@7279
  1133
slouken@1895
  1134
    /* Update internal mouse state */
slouken@1895
  1135
    joystick->balls[ball].dx += xrel;
slouken@1895
  1136
    joystick->balls[ball].dy += yrel;
slouken@0
  1137
slouken@1895
  1138
    /* Post the event, if desired */
slouken@1895
  1139
    posted = 0;
slouken@1361
  1140
#if !SDL_EVENTS_DISABLED
slouken@4429
  1141
    if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
slouken@1895
  1142
        SDL_Event event;
slouken@1895
  1143
        event.jball.type = SDL_JOYBALLMOTION;
slouken@6690
  1144
        event.jball.which = joystick->instance_id;
slouken@1895
  1145
        event.jball.ball = ball;
slouken@1895
  1146
        event.jball.xrel = xrel;
slouken@1895
  1147
        event.jball.yrel = yrel;
slouken@6690
  1148
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
  1149
    }
slouken@1361
  1150
#endif /* !SDL_EVENTS_DISABLED */
slouken@12088
  1151
    return posted;
slouken@0
  1152
}
slouken@0
  1153
slouken@1895
  1154
int
slouken@1895
  1155
SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
slouken@0
  1156
{
slouken@1895
  1157
    int posted;
slouken@1361
  1158
#if !SDL_EVENTS_DISABLED
slouken@1895
  1159
    SDL_Event event;
slouken@0
  1160
slouken@1895
  1161
    switch (state) {
slouken@1895
  1162
    case SDL_PRESSED:
slouken@1895
  1163
        event.type = SDL_JOYBUTTONDOWN;
slouken@1895
  1164
        break;
slouken@1895
  1165
    case SDL_RELEASED:
slouken@1895
  1166
        event.type = SDL_JOYBUTTONUP;
slouken@1895
  1167
        break;
slouken@1895
  1168
    default:
slouken@1895
  1169
        /* Invalid state -- bail */
slouken@12088
  1170
        return 0;
slouken@1895
  1171
    }
slouken@1361
  1172
#endif /* !SDL_EVENTS_DISABLED */
slouken@0
  1173
slouken@8920
  1174
    /* Make sure we're not getting garbage or duplicate events */
slouken@6145
  1175
    if (button >= joystick->nbuttons) {
slouken@6145
  1176
        return 0;
slouken@9884
  1177
    }
slouken@9884
  1178
    if (state == joystick->buttons[button]) {
slouken@9884
  1179
        return 0;
slouken@9884
  1180
    }
slouken@6145
  1181
jorgen@7279
  1182
    /* We ignore events if we don't have keyboard focus, except for button
jorgen@7279
  1183
     * release. */
slouken@8903
  1184
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
slouken@8903
  1185
        if (state == SDL_PRESSED) {
slouken@8903
  1186
            return 0;
slouken@8903
  1187
        }
jorgen@7279
  1188
    }
jorgen@7279
  1189
slouken@1895
  1190
    /* Update internal joystick state */
slouken@1895
  1191
    joystick->buttons[button] = state;
slouken@0
  1192
slouken@1895
  1193
    /* Post the event, if desired */
slouken@1895
  1194
    posted = 0;
slouken@1361
  1195
#if !SDL_EVENTS_DISABLED
slouken@4429
  1196
    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@6690
  1197
        event.jbutton.which = joystick->instance_id;
slouken@1895
  1198
        event.jbutton.button = button;
slouken@1895
  1199
        event.jbutton.state = state;
slouken@6690
  1200
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
  1201
    }
slouken@1361
  1202
#endif /* !SDL_EVENTS_DISABLED */
slouken@12088
  1203
    return posted;
slouken@0
  1204
}
slouken@0
  1205
slouken@1895
  1206
void
slouken@1895
  1207
SDL_JoystickUpdate(void)
slouken@0
  1208
{
slouken@12088
  1209
    int i;
sylvain@13163
  1210
    SDL_Joystick *joystick, *next;
slouken@7191
  1211
slouken@12422
  1212
    if (!SDL_WasInit(SDL_INIT_JOYSTICK)) {
slouken@12422
  1213
        return;
slouken@12422
  1214
    }
slouken@12422
  1215
slouken@11581
  1216
    SDL_LockJoysticks();
slouken@10659
  1217
slouken@10688
  1218
    if (SDL_updating_joystick) {
slouken@10688
  1219
        /* The joysticks are already being updated */
slouken@11581
  1220
        SDL_UnlockJoysticks();
slouken@10688
  1221
        return;
slouken@10688
  1222
    }
slouken@10688
  1223
slouken@10704
  1224
    SDL_updating_joystick = SDL_TRUE;
slouken@6690
  1225
slouken@10704
  1226
    /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
slouken@11581
  1227
    SDL_UnlockJoysticks();
slouken@6712
  1228
slouken@13356
  1229
#ifdef SDL_JOYSTICK_HIDAPI
slouken@13356
  1230
    /* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */
slouken@13356
  1231
    HIDAPI_UpdateDevices();
slouken@13356
  1232
#endif /* SDL_JOYSTICK_HIDAPI */
slouken@13356
  1233
slouken@10704
  1234
    for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
slouken@12090
  1235
        if (joystick->attached) {
slouken@12764
  1236
            /* This should always be true, but seeing a crash in the wild...? */
slouken@12764
  1237
            if (joystick->driver) {
slouken@12764
  1238
                joystick->driver->Update(joystick);
slouken@12764
  1239
            }
slouken@0
  1240
slouken@12090
  1241
            if (joystick->delayed_guide_button) {
slouken@12090
  1242
                SDL_GameControllerHandleDelayedGuideButton(joystick);
slouken@12090
  1243
            }
slouken@11934
  1244
        }
slouken@11934
  1245
slouken@13480
  1246
        if (joystick->rumble_expiration) {
slouken@13480
  1247
            SDL_LockJoysticks();
slouken@13480
  1248
            /* Double check now that the lock is held */
slouken@13480
  1249
            if (joystick->rumble_expiration &&
slouken@13480
  1250
                SDL_TICKS_PASSED(SDL_GetTicks(), joystick->rumble_expiration)) {
slouken@13480
  1251
                SDL_JoystickRumble(joystick, 0, 0, 0);
slouken@13480
  1252
            }
slouken@13480
  1253
            SDL_UnlockJoysticks();
slouken@13480
  1254
        }
slouken@13480
  1255
icculus@9433
  1256
        if (joystick->force_recentering) {
slouken@10745
  1257
            /* Tell the app that everything is centered/unpressed... */
slime73@9876
  1258
            for (i = 0; i < joystick->naxes; i++) {
slouken@10745
  1259
                if (joystick->axes[i].has_initial_value) {
slouken@10745
  1260
                    SDL_PrivateJoystickAxis(joystick, i, joystick->axes[i].zero);
slouken@10745
  1261
                }
slime73@9876
  1262
            }
slouken@6690
  1263
slime73@9876
  1264
            for (i = 0; i < joystick->nbuttons; i++) {
slouken@6690
  1265
                SDL_PrivateJoystickButton(joystick, i, 0);
slime73@9876
  1266
            }
slouken@6690
  1267
slime73@9876
  1268
            for (i = 0; i < joystick->nhats; i++) {
slouken@6690
  1269
                SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
slime73@9876
  1270
            }
slouken@6712
  1271
icculus@9433
  1272
            joystick->force_recentering = SDL_FALSE;
slouken@7191
  1273
        }
slouken@10704
  1274
    }
slouken@6690
  1275
slouken@11581
  1276
    SDL_LockJoysticks();
slouken@10688
  1277
slouken@10704
  1278
    SDL_updating_joystick = SDL_FALSE;
slouken@6712
  1279
slouken@10704
  1280
    /* If any joysticks were closed while updating, free them here */
sylvain@13163
  1281
    for (joystick = SDL_joysticks; joystick; joystick = next) {
sylvain@13163
  1282
        next = joystick->next;
slouken@8920
  1283
        if (joystick->ref_count <= 0) {
slouken@6712
  1284
            SDL_JoystickClose(joystick);
slouken@6712
  1285
        }
slouken@7191
  1286
    }
slouken@6690
  1287
slouken@7191
  1288
    /* this needs to happen AFTER walking the joystick list above, so that any
slouken@7191
  1289
       dangling hardware data from removed devices can be free'd
slouken@7191
  1290
     */
slouken@12088
  1291
    for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
slouken@12088
  1292
        SDL_joystick_drivers[i]->Detect();
slouken@12088
  1293
    }
slouken@10659
  1294
slouken@11581
  1295
    SDL_UnlockJoysticks();
slouken@0
  1296
}
slouken@0
  1297
slouken@1895
  1298
int
slouken@1895
  1299
SDL_JoystickEventState(int state)
slouken@0
  1300
{
slouken@1361
  1301
#if SDL_EVENTS_DISABLED
slouken@6753
  1302
    return SDL_DISABLE;
slouken@0
  1303
#else
slouken@4429
  1304
    const Uint32 event_list[] = {
slouken@1895
  1305
        SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
slouken@6690
  1306
        SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
slouken@1895
  1307
    };
slouken@1895
  1308
    unsigned int i;
slouken@0
  1309
slouken@1895
  1310
    switch (state) {
slouken@1895
  1311
    case SDL_QUERY:
slouken@6753
  1312
        state = SDL_DISABLE;
slouken@1895
  1313
        for (i = 0; i < SDL_arraysize(event_list); ++i) {
slouken@1895
  1314
            state = SDL_EventState(event_list[i], SDL_QUERY);
slouken@1895
  1315
            if (state == SDL_ENABLE) {
slouken@1895
  1316
                break;
slouken@1895
  1317
            }
slouken@1895
  1318
        }
slouken@1895
  1319
        break;
slouken@1895
  1320
    default:
slouken@1895
  1321
        for (i = 0; i < SDL_arraysize(event_list); ++i) {
slouken@1895
  1322
            SDL_EventState(event_list[i], state);
slouken@1895
  1323
        }
slouken@1895
  1324
        break;
slouken@1895
  1325
    }
slouken@12088
  1326
    return state;
slouken@1361
  1327
#endif /* SDL_EVENTS_DISABLED */
slouken@0
  1328
}
slouken@1895
  1329
slouken@11201
  1330
void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version)
slouken@10595
  1331
{
slouken@10595
  1332
    Uint16 *guid16 = (Uint16 *)guid.data;
slouken@10595
  1333
slouken@10595
  1334
    /* If the GUID fits the form of BUS 0000 VENDOR 0000 PRODUCT 0000, return the data */
slouken@10595
  1335
    if (/* guid16[0] is device bus type */
slouken@10647
  1336
        guid16[1] == 0x0000 &&
slouken@10595
  1337
        /* guid16[2] is vendor ID */
slouken@10647
  1338
        guid16[3] == 0x0000 &&
slouken@10595
  1339
        /* guid16[4] is product ID */
slouken@10647
  1340
        guid16[5] == 0x0000
slouken@10595
  1341
        /* guid16[6] is product version */
slouken@12088
  1342
   ) {
slouken@10595
  1343
        if (vendor) {
slouken@10595
  1344
            *vendor = guid16[2];
slouken@10595
  1345
        }
slouken@10595
  1346
        if (product) {
slouken@10595
  1347
            *product = guid16[4];
slouken@10595
  1348
        }
slouken@10595
  1349
        if (version) {
slouken@10595
  1350
            *version = guid16[6];
slouken@10595
  1351
        }
slouken@10595
  1352
    } else {
slouken@10595
  1353
        if (vendor) {
slouken@10595
  1354
            *vendor = 0;
slouken@10595
  1355
        }
slouken@10595
  1356
        if (product) {
slouken@10595
  1357
            *product = 0;
slouken@10595
  1358
        }
slouken@10595
  1359
        if (version) {
slouken@10595
  1360
            *version = 0;
slouken@10595
  1361
        }
slouken@10595
  1362
    }
slouken@10595
  1363
}
slouken@10595
  1364
slouken@13333
  1365
const char *
slouken@13341
  1366
SDL_GetCustomJoystickManufacturer(const char *manufacturer)
slouken@13341
  1367
{
slouken@13341
  1368
    if (manufacturer) {
slouken@13341
  1369
        if (SDL_strcmp(manufacturer, "Performance Designed Products") == 0) {
slouken@13341
  1370
            return "PDP";
slouken@13341
  1371
        } else if (SDL_strcmp(manufacturer, "HORI CO.,LTD") == 0) {
slouken@13341
  1372
            return "HORI";
slouken@13341
  1373
        }
slouken@13341
  1374
    }
slouken@13341
  1375
    return manufacturer;
slouken@13341
  1376
}
slouken@13341
  1377
slouken@13341
  1378
const char *
slouken@13333
  1379
SDL_GetCustomJoystickName(Uint16 vendor, Uint16 product)
slouken@13333
  1380
{
slouken@13333
  1381
    return GuessControllerName(vendor, product);
slouken@13333
  1382
}
slouken@13333
  1383
slouken@13275
  1384
SDL_GameControllerType
slouken@13277
  1385
SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name)
slouken@13275
  1386
{
slouken@13275
  1387
    SDL_GameControllerType type;
slouken@13275
  1388
    Uint16 vendor, product;
slouken@13275
  1389
slouken@13275
  1390
    SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
slouken@13429
  1391
    type = SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0);
slouken@13275
  1392
    if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
slouken@13275
  1393
        if (SDL_IsJoystickXInput(guid)) {
slouken@13275
  1394
            /* This is probably an Xbox One controller */
slouken@13275
  1395
            return SDL_CONTROLLER_TYPE_XBOXONE;
slouken@13275
  1396
        }
slouken@13275
  1397
    }
slouken@13275
  1398
    return type;
slouken@13275
  1399
}
slouken@13275
  1400
slouken@13275
  1401
SDL_GameControllerType
slouken@13429
  1402
SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
slouken@13275
  1403
{
slouken@13540
  1404
    static const int LIBUSB_CLASS_VENDOR_SPEC = 0xFF;
slouken@13540
  1405
    static const int XB360_IFACE_SUBCLASS = 93;
slouken@13540
  1406
    static const int XB360_IFACE_PROTOCOL = 1; /* Wired */
slouken@13540
  1407
    static const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
slouken@13540
  1408
    static const int XBONE_IFACE_SUBCLASS = 71;
slouken@13540
  1409
    static const int XBONE_IFACE_PROTOCOL = 208;
slouken@13540
  1410
slouken@13429
  1411
    SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN;
slouken@13429
  1412
slouken@13540
  1413
    /* This code should match the checks in libusb/hid.c and HIDDeviceManager.java */
slouken@13540
  1414
    if (interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
slouken@13540
  1415
        interface_subclass == XB360_IFACE_SUBCLASS &&
slouken@13540
  1416
        (interface_protocol == XB360_IFACE_PROTOCOL ||
slouken@13540
  1417
         interface_protocol == XB360W_IFACE_PROTOCOL)) {
slouken@13429
  1418
slouken@13540
  1419
        static const int SUPPORTED_VENDORS[] = {
slouken@13540
  1420
            0x0079, /* GPD Win 2 */
slouken@13540
  1421
            0x044f, /* Thrustmaster */
slouken@13540
  1422
            0x045e, /* Microsoft */
slouken@13540
  1423
            0x046d, /* Logitech */
slouken@13540
  1424
            0x056e, /* Elecom */
slouken@13540
  1425
            0x06a3, /* Saitek */
slouken@13540
  1426
            0x0738, /* Mad Catz */
slouken@13540
  1427
            0x07ff, /* Mad Catz */
slouken@13540
  1428
            0x0e6f, /* PDP */
slouken@13540
  1429
            0x0f0d, /* Hori */
slouken@13540
  1430
            0x1038, /* SteelSeries */
slouken@13540
  1431
            0x11c9, /* Nacon */
slouken@13540
  1432
            0x12ab, /* Unknown */
slouken@13540
  1433
            0x1430, /* RedOctane */
slouken@13540
  1434
            0x146b, /* BigBen */
slouken@13540
  1435
            0x1532, /* Razer Sabertooth */
slouken@13540
  1436
            0x15e4, /* Numark */
slouken@13540
  1437
            0x162e, /* Joytech */
slouken@13540
  1438
            0x1689, /* Razer Onza */
slouken@13540
  1439
            0x1bad, /* Harmonix */
slouken@13540
  1440
            0x24c6, /* PowerA */
slouken@13540
  1441
        };
slouken@13429
  1442
slouken@13540
  1443
        int i;
slouken@13540
  1444
        for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
slouken@13540
  1445
            if (vendor == SUPPORTED_VENDORS[i]) {
slouken@13540
  1446
                type = SDL_CONTROLLER_TYPE_XBOX360;
slouken@13540
  1447
                break;
slouken@13540
  1448
            }
slouken@13540
  1449
        }
slouken@13540
  1450
    }
slouken@13540
  1451
slouken@13540
  1452
    if (interface_number == 0 &&
slouken@13540
  1453
        interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
slouken@13540
  1454
        interface_subclass == XBONE_IFACE_SUBCLASS &&
slouken@13540
  1455
        interface_protocol == XBONE_IFACE_PROTOCOL) {
slouken@13540
  1456
slouken@13540
  1457
        static const int SUPPORTED_VENDORS[] = {
slouken@13540
  1458
            0x045e, /* Microsoft */
slouken@13540
  1459
            0x0738, /* Mad Catz */
slouken@13540
  1460
            0x0e6f, /* PDP */
slouken@13540
  1461
            0x0f0d, /* Hori */
slouken@13540
  1462
            0x1532, /* Razer Wildcat */
slouken@13540
  1463
            0x24c6, /* PowerA */
slouken@13540
  1464
            0x2e24, /* Hyperkin */
slouken@13540
  1465
        };
slouken@13540
  1466
slouken@13540
  1467
        int i;
slouken@13540
  1468
        for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
slouken@13540
  1469
            if (vendor == SUPPORTED_VENDORS[i]) {
slouken@13540
  1470
                type = SDL_CONTROLLER_TYPE_XBOXONE;
slouken@13540
  1471
                break;
slouken@13540
  1472
            }
slouken@13429
  1473
        }
slouken@13275
  1474
    }
slouken@13275
  1475
slouken@13429
  1476
    if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
slouken@13540
  1477
        if (vendor == 0x0000 && product == 0x0000) {
slouken@13540
  1478
            /* Some devices are only identifiable by their name */
slouken@13540
  1479
            if (SDL_strcmp(name, "Lic Pro Controller") == 0 ||
slouken@13540
  1480
                SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 ||
slouken@13540
  1481
                SDL_strcmp(name, "Wireless Gamepad") == 0) {
slouken@13540
  1482
                /* HORI or PowerA Switch Pro Controller clone */
slouken@13540
  1483
                type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
slouken@13540
  1484
            } else {
slouken@13540
  1485
                type = SDL_CONTROLLER_TYPE_UNKNOWN;
slouken@13540
  1486
            }
slouken@13429
  1487
slouken@13540
  1488
        } else if (vendor == 0x0001 && product == 0x0001) {
slouken@13540
  1489
            type = SDL_CONTROLLER_TYPE_UNKNOWN;
slouken@13429
  1490
slouken@13540
  1491
        } else {
slouken@13540
  1492
            switch (GuessControllerType(vendor, product)) {
slouken@13540
  1493
            case k_eControllerType_XBox360Controller:
slouken@13540
  1494
                type = SDL_CONTROLLER_TYPE_XBOX360;
slouken@13540
  1495
                break;
slouken@13540
  1496
            case k_eControllerType_XBoxOneController:
slouken@13540
  1497
                type = SDL_CONTROLLER_TYPE_XBOXONE;
slouken@13540
  1498
                break;
slouken@13540
  1499
            case k_eControllerType_PS3Controller:
slouken@13540
  1500
                type = SDL_CONTROLLER_TYPE_PS3;
slouken@13540
  1501
                break;
slouken@13540
  1502
            case k_eControllerType_PS4Controller:
slouken@13540
  1503
                type = SDL_CONTROLLER_TYPE_PS4;
slouken@13540
  1504
                break;
slouken@13540
  1505
            case k_eControllerType_SwitchProController:
slouken@13540
  1506
            case k_eControllerType_SwitchInputOnlyController:
slouken@13540
  1507
                type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
slouken@13540
  1508
                break;
slouken@13540
  1509
            default:
slouken@13540
  1510
                type = SDL_CONTROLLER_TYPE_UNKNOWN;
slouken@13540
  1511
                break;
slouken@13429
  1512
            }
slouken@13429
  1513
        }
slouken@13275
  1514
    }
slouken@13429
  1515
    return type;
slouken@13275
  1516
}
slouken@13275
  1517
slouken@12088
  1518
SDL_bool
slouken@13135
  1519
SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor, Uint16 product)
slouken@13135
  1520
{
slouken@13135
  1521
    EControllerType eType = GuessControllerType(vendor, product);
slouken@13135
  1522
    return (eType == k_eControllerType_SwitchInputOnlyController);
slouken@13135
  1523
}
slouken@13135
  1524
slouken@13135
  1525
SDL_bool
slouken@12088
  1526
SDL_IsJoystickSteamController(Uint16 vendor, Uint16 product)
slouken@12088
  1527
{
slouken@12947
  1528
    EControllerType eType = GuessControllerType(vendor, product);
slouken@12947
  1529
    return (eType == k_eControllerType_SteamController ||
slouken@12947
  1530
            eType == k_eControllerType_SteamControllerV2);
slouken@12088
  1531
}
slouken@12088
  1532
slouken@12088
  1533
SDL_bool
slouken@12192
  1534
SDL_IsJoystickXInput(SDL_JoystickGUID guid)
slouken@12192
  1535
{
slouken@12192
  1536
    return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE;
slouken@12192
  1537
}
slouken@12192
  1538
slouken@12192
  1539
SDL_bool
slouken@12192
  1540
SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid)
slouken@12192
  1541
{
slouken@12192
  1542
    return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE;
slouken@12192
  1543
}
slouken@12192
  1544
slouken@10868
  1545
static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
slouken@10855
  1546
{
slouken@10855
  1547
    static Uint32 wheel_joysticks[] = {
slouken@10855
  1548
        MAKE_VIDPID(0x046d, 0xc294),    /* Logitech generic wheel */
slouken@10855
  1549
        MAKE_VIDPID(0x046d, 0xc295),    /* Logitech Momo Force */
slouken@10855
  1550
        MAKE_VIDPID(0x046d, 0xc298),    /* Logitech Driving Force Pro */
slouken@10855
  1551
        MAKE_VIDPID(0x046d, 0xc299),    /* Logitech G25 */
slouken@10855
  1552
        MAKE_VIDPID(0x046d, 0xc29a),    /* Logitech Driving Force GT */
slouken@10855
  1553
        MAKE_VIDPID(0x046d, 0xc29b),    /* Logitech G27 */
slouken@10855
  1554
        MAKE_VIDPID(0x046d, 0xc261),    /* Logitech G920 (initial mode) */
slouken@10855
  1555
        MAKE_VIDPID(0x046d, 0xc262),    /* Logitech G920 (active mode) */
slouken@10855
  1556
        MAKE_VIDPID(0x044f, 0xb65d),    /* Thrustmaster Wheel FFB */
slouken@10856
  1557
        MAKE_VIDPID(0x044f, 0xb66d),    /* Thrustmaster Wheel FFB */
slouken@10855
  1558
        MAKE_VIDPID(0x044f, 0xb677),    /* Thrustmaster T150 */
slouken@10855
  1559
        MAKE_VIDPID(0x044f, 0xb664),    /* Thrustmaster TX (initial mode) */
slouken@10855
  1560
        MAKE_VIDPID(0x044f, 0xb669),    /* Thrustmaster TX (active mode) */
slouken@10855
  1561
    };
slouken@10855
  1562
    int i;
slouken@10855
  1563
slouken@10867
  1564
    for (i = 0; i < SDL_arraysize(wheel_joysticks); ++i) {
slouken@10867
  1565
        if (vidpid == wheel_joysticks[i]) {
slouken@10867
  1566
            return SDL_TRUE;
slouken@10867
  1567
        }
slouken@10867
  1568
    }
slouken@10867
  1569
    return SDL_FALSE;
slouken@10867
  1570
}
slouken@10855
  1571
slouken@10868
  1572
static SDL_bool SDL_IsJoystickProductFlightStick(Uint32 vidpid)
slouken@10867
  1573
{
slouken@10867
  1574
    static Uint32 flightstick_joysticks[] = {
slouken@10869
  1575
        MAKE_VIDPID(0x044f, 0x0402),    /* HOTAS Warthog Joystick */
slouken@10869
  1576
        MAKE_VIDPID(0x0738, 0x2221),    /* Saitek Pro Flight X-56 Rhino Stick */
slouken@10867
  1577
    };
slouken@10867
  1578
    int i;
slouken@10867
  1579
slouken@10867
  1580
    for (i = 0; i < SDL_arraysize(flightstick_joysticks); ++i) {
slouken@10867
  1581
        if (vidpid == flightstick_joysticks[i]) {
slouken@10855
  1582
            return SDL_TRUE;
slouken@10855
  1583
        }
slouken@10855
  1584
    }
slouken@10855
  1585
    return SDL_FALSE;
slouken@10855
  1586
}
slouken@10855
  1587
slouken@10868
  1588
static SDL_bool SDL_IsJoystickProductThrottle(Uint32 vidpid)
slouken@10868
  1589
{
slouken@10868
  1590
    static Uint32 throttle_joysticks[] = {
slouken@10869
  1591
        MAKE_VIDPID(0x044f, 0x0404),    /* HOTAS Warthog Throttle */
slouken@10869
  1592
        MAKE_VIDPID(0x0738, 0xa221),    /* Saitek Pro Flight X-56 Rhino Throttle */
slouken@10868
  1593
    };
slouken@10868
  1594
    int i;
slouken@10868
  1595
slouken@10868
  1596
    for (i = 0; i < SDL_arraysize(throttle_joysticks); ++i) {
slouken@10868
  1597
        if (vidpid == throttle_joysticks[i]) {
slouken@10868
  1598
            return SDL_TRUE;
slouken@10868
  1599
        }
slouken@10868
  1600
    }
slouken@10868
  1601
    return SDL_FALSE;
slouken@10868
  1602
}
slouken@10868
  1603
slouken@10855
  1604
static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid)
slouken@10855
  1605
{
slouken@10867
  1606
    Uint16 vendor;
slouken@10867
  1607
    Uint16 product;
slouken@10867
  1608
    Uint32 vidpid;
slouken@10867
  1609
slouken@12192
  1610
    if (SDL_IsJoystickXInput(guid)) {
slouken@10855
  1611
        /* XInput GUID, get the type based on the XInput device subtype */
slouken@10855
  1612
        switch (guid.data[15]) {
slouken@10855
  1613
        case 0x01:  /* XINPUT_DEVSUBTYPE_GAMEPAD */
slouken@10855
  1614
            return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
slouken@10855
  1615
        case 0x02:  /* XINPUT_DEVSUBTYPE_WHEEL */
slouken@10855
  1616
            return SDL_JOYSTICK_TYPE_WHEEL;
slouken@10855
  1617
        case 0x03:  /* XINPUT_DEVSUBTYPE_ARCADE_STICK */
slouken@10855
  1618
            return SDL_JOYSTICK_TYPE_ARCADE_STICK;
slouken@10855
  1619
        case 0x04:  /* XINPUT_DEVSUBTYPE_FLIGHT_STICK */
slouken@10855
  1620
            return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
slouken@10855
  1621
        case 0x05:  /* XINPUT_DEVSUBTYPE_DANCE_PAD */
slouken@10855
  1622
            return SDL_JOYSTICK_TYPE_DANCE_PAD;
slouken@10855
  1623
        case 0x06:  /* XINPUT_DEVSUBTYPE_GUITAR */
slouken@10855
  1624
        case 0x07:  /* XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE */
slouken@10855
  1625
        case 0x0B:  /* XINPUT_DEVSUBTYPE_GUITAR_BASS */
slouken@10855
  1626
            return SDL_JOYSTICK_TYPE_GUITAR;
slouken@10855
  1627
        case 0x08:  /* XINPUT_DEVSUBTYPE_DRUM_KIT */
slouken@10855
  1628
            return SDL_JOYSTICK_TYPE_DRUM_KIT;
slouken@10855
  1629
        case 0x13:  /* XINPUT_DEVSUBTYPE_ARCADE_PAD */
slouken@10855
  1630
            return SDL_JOYSTICK_TYPE_ARCADE_PAD;
slouken@10855
  1631
        default:
slouken@10855
  1632
            return SDL_JOYSTICK_TYPE_UNKNOWN;
slouken@10855
  1633
        }
slouken@10855
  1634
    }
slouken@10855
  1635
slouken@10867
  1636
    SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
slouken@10867
  1637
    vidpid = MAKE_VIDPID(vendor, product);
slouken@10867
  1638
slouken@10868
  1639
    if (SDL_IsJoystickProductWheel(vidpid)) {
slouken@10855
  1640
        return SDL_JOYSTICK_TYPE_WHEEL;
slouken@10855
  1641
    }
slouken@10855
  1642
slouken@10868
  1643
    if (SDL_IsJoystickProductFlightStick(vidpid)) {
slouken@10867
  1644
        return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
slouken@10867
  1645
    }
slouken@10867
  1646
slouken@10868
  1647
    if (SDL_IsJoystickProductThrottle(vidpid)) {
slouken@10868
  1648
        return SDL_JOYSTICK_TYPE_THROTTLE;
slouken@10868
  1649
    }
slouken@10868
  1650
slouken@12088
  1651
    if (GuessControllerType(vendor, product) != k_eControllerType_UnknownNonSteamController) {
slouken@12088
  1652
        return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
slouken@12088
  1653
    }
slouken@12088
  1654
slouken@10855
  1655
    return SDL_JOYSTICK_TYPE_UNKNOWN;
slouken@10855
  1656
}
slouken@10855
  1657
slouken@12088
  1658
static SDL_bool SDL_IsPS4RemapperRunning(void)
slouken@12088
  1659
{
slouken@12088
  1660
#ifdef __WIN32__
slouken@12088
  1661
    const char *mapper_processes[] = {
slouken@12088
  1662
        "DS4Windows.exe",
slouken@12088
  1663
        "InputMapper.exe",
slouken@12088
  1664
    };
slouken@12088
  1665
    int i;
slouken@12088
  1666
    PROCESSENTRY32 pe32;
slouken@12088
  1667
    SDL_bool found = SDL_FALSE;
slouken@12088
  1668
slouken@12088
  1669
    /* Take a snapshot of all processes in the system */
slouken@12088
  1670
    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
slouken@12088
  1671
    if (hProcessSnap != INVALID_HANDLE_VALUE) {
slouken@12088
  1672
        pe32.dwSize = sizeof(PROCESSENTRY32);
slouken@12088
  1673
        if (Process32First(hProcessSnap, &pe32)) {
slouken@12088
  1674
            do
slouken@12088
  1675
            {
slouken@12088
  1676
                for (i = 0; i < SDL_arraysize(mapper_processes); ++i) {
slouken@12088
  1677
                    if (SDL_strcasecmp(pe32.szExeFile, mapper_processes[i]) == 0) {
slouken@12088
  1678
                        found = SDL_TRUE;
slouken@12088
  1679
                    }
slouken@12088
  1680
                }
slouken@12088
  1681
            } while (Process32Next(hProcessSnap, &pe32) && !found);
slouken@12088
  1682
        }
slouken@12088
  1683
        CloseHandle(hProcessSnap);
slouken@12088
  1684
    }
slouken@12088
  1685
    return found;
slouken@12088
  1686
#else
slouken@12088
  1687
    return SDL_FALSE;
slouken@12088
  1688
#endif
slouken@12088
  1689
}
slouken@12088
  1690
slouken@12088
  1691
SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
slouken@12088
  1692
{
slouken@13583
  1693
    /* This list is taken from:
slouken@12459
  1694
       https://raw.githubusercontent.com/denilsonsa/udev-joystick-blacklist/master/generate_rules.py
slouken@12459
  1695
     */
slouken@12459
  1696
    static Uint32 joystick_blacklist[] = {
slouken@12459
  1697
        /* Microsoft Microsoft Wireless Optical Desktop® 2.10 */
slouken@12459
  1698
        /* Microsoft Wireless Desktop - Comfort Edition */
slouken@12459
  1699
        MAKE_VIDPID(0x045e, 0x009d),
slouken@12459
  1700
slouken@12459
  1701
        /* Microsoft Microsoft® Digital Media Pro Keyboard */
slouken@12459
  1702
        /* Microsoft Corp. Digital Media Pro Keyboard */
slouken@12459
  1703
        MAKE_VIDPID(0x045e, 0x00b0),
slouken@12459
  1704
slouken@12459
  1705
        /* Microsoft Microsoft® Digital Media Keyboard */
slouken@12459
  1706
        /* Microsoft Corp. Digital Media Keyboard 1.0A */
slouken@12459
  1707
        MAKE_VIDPID(0x045e, 0x00b4),
slouken@12459
  1708
slouken@12459
  1709
        /* Microsoft Microsoft® Digital Media Keyboard 3000 */
slouken@12459
  1710
        MAKE_VIDPID(0x045e, 0x0730),
slouken@12459
  1711
slouken@12459
  1712
        /* Microsoft Microsoft® 2.4GHz Transceiver v6.0 */
slouken@12459
  1713
        /* Microsoft Microsoft® 2.4GHz Transceiver v8.0 */
slouken@12459
  1714
        /* Microsoft Corp. Nano Transceiver v1.0 for Bluetooth */
slouken@12459
  1715
        /* Microsoft Wireless Mobile Mouse 1000 */
slouken@12459
  1716
        /* Microsoft Wireless Desktop 3000 */
slouken@12459
  1717
        MAKE_VIDPID(0x045e, 0x0745),
slouken@12459
  1718
slouken@12459
  1719
        /* Microsoft® SideWinder(TM) 2.4GHz Transceiver */
slouken@12459
  1720
        MAKE_VIDPID(0x045e, 0x0748),
slouken@12459
  1721
slouken@12459
  1722
        /* Microsoft Corp. Wired Keyboard 600 */
slouken@12459
  1723
        MAKE_VIDPID(0x045e, 0x0750),
slouken@12459
  1724
slouken@12459
  1725
        /* Microsoft Corp. Sidewinder X4 keyboard */
slouken@12459
  1726
        MAKE_VIDPID(0x045e, 0x0768),
slouken@12459
  1727
slouken@12459
  1728
        /* Microsoft Corp. Arc Touch Mouse Transceiver */
slouken@12459
  1729
        MAKE_VIDPID(0x045e, 0x0773),
slouken@12459
  1730
slouken@12459
  1731
        /* Microsoft® 2.4GHz Transceiver v9.0 */
slouken@12459
  1732
        /* Microsoft® Nano Transceiver v2.1 */
slouken@12459
  1733
        /* Microsoft Sculpt Ergonomic Keyboard (5KV-00001) */
slouken@12459
  1734
        MAKE_VIDPID(0x045e, 0x07a5),
slouken@12459
  1735
slouken@12459
  1736
        /* Microsoft® Nano Transceiver v1.0 */
slouken@12459
  1737
        /* Microsoft Wireless Keyboard 800 */
slouken@12459
  1738
        MAKE_VIDPID(0x045e, 0x07b2),
slouken@12459
  1739
slouken@12459
  1740
        /* Microsoft® Nano Transceiver v2.0 */
slouken@12459
  1741
        MAKE_VIDPID(0x045e, 0x0800),
slouken@12459
  1742
slouken@12459
  1743
        MAKE_VIDPID(0x046d, 0xc30a),  /* Logitech, Inc. iTouch Composite keboard */
slouken@12459
  1744
slouken@12459
  1745
        MAKE_VIDPID(0x04d9, 0xa0df),  /* Tek Syndicate Mouse (E-Signal USB Gaming Mouse) */
slouken@12459
  1746
slouken@12459
  1747
        /* List of Wacom devices at: http://linuxwacom.sourceforge.net/wiki/index.php/Device_IDs */
slouken@12459
  1748
        MAKE_VIDPID(0x056a, 0x0010),  /* Wacom ET-0405 Graphire */
slouken@12459
  1749
        MAKE_VIDPID(0x056a, 0x0011),  /* Wacom ET-0405A Graphire2 (4x5) */
slouken@12459
  1750
        MAKE_VIDPID(0x056a, 0x0012),  /* Wacom ET-0507A Graphire2 (5x7) */
slouken@12459
  1751
        MAKE_VIDPID(0x056a, 0x0013),  /* Wacom CTE-430 Graphire3 (4x5) */
slouken@12459
  1752
        MAKE_VIDPID(0x056a, 0x0014),  /* Wacom CTE-630 Graphire3 (6x8) */
slouken@12459
  1753
        MAKE_VIDPID(0x056a, 0x0015),  /* Wacom CTE-440 Graphire4 (4x5) */
slouken@12459
  1754
        MAKE_VIDPID(0x056a, 0x0016),  /* Wacom CTE-640 Graphire4 (6x8) */
slouken@12459
  1755
        MAKE_VIDPID(0x056a, 0x0017),  /* Wacom CTE-450 Bamboo Fun (4x5) */
slouken@12459
  1756
        MAKE_VIDPID(0x056a, 0x0018),  /* Wacom CTE-650 Bamboo Fun 6x8 */
slouken@12459
  1757
        MAKE_VIDPID(0x056a, 0x0019),  /* Wacom CTE-631 Bamboo One */
slouken@12459
  1758
        MAKE_VIDPID(0x056a, 0x00d1),  /* Wacom Bamboo Pen and Touch CTH-460 */
slouken@12459
  1759
        MAKE_VIDPID(0x056a, 0x030e),  /* Wacom Intuos Pen (S) CTL-480 */
slouken@12459
  1760
slouken@12459
  1761
        MAKE_VIDPID(0x09da, 0x054f),  /* A4 Tech Co., G7 750 mouse */
slouken@12459
  1762
        MAKE_VIDPID(0x09da, 0x1410),  /* A4 Tech Co., Ltd Bloody AL9 mouse */
slouken@12459
  1763
        MAKE_VIDPID(0x09da, 0x3043),  /* A4 Tech Co., Ltd Bloody R8A Gaming Mouse */
slouken@12459
  1764
        MAKE_VIDPID(0x09da, 0x31b5),  /* A4 Tech Co., Ltd Bloody TL80 Terminator Laser Gaming Mouse */
slouken@12459
  1765
        MAKE_VIDPID(0x09da, 0x3997),  /* A4 Tech Co., Ltd Bloody RT7 Terminator Wireless */
slouken@12459
  1766
        MAKE_VIDPID(0x09da, 0x3f8b),  /* A4 Tech Co., Ltd Bloody V8 mouse */
slouken@12459
  1767
        MAKE_VIDPID(0x09da, 0x51f4),  /* Modecom MC-5006 Keyboard */
slouken@12459
  1768
        MAKE_VIDPID(0x09da, 0x5589),  /* A4 Tech Co., Ltd Terminator TL9 Laser Gaming Mouse */
slouken@12459
  1769
        MAKE_VIDPID(0x09da, 0x7b22),  /* A4 Tech Co., Ltd Bloody V5 */
slouken@12459
  1770
        MAKE_VIDPID(0x09da, 0x7f2d),  /* A4 Tech Co., Ltd Bloody R3 mouse */
slouken@12459
  1771
        MAKE_VIDPID(0x09da, 0x8090),  /* A4 Tech Co., Ltd X-718BK Oscar Optical Gaming Mouse */
slouken@12459
  1772
        MAKE_VIDPID(0x09da, 0x9033),  /* A4 Tech Co., X7 X-705K */
slouken@12459
  1773
        MAKE_VIDPID(0x09da, 0x9066),  /* A4 Tech Co., Sharkoon Fireglider Optical */
slouken@12459
  1774
        MAKE_VIDPID(0x09da, 0x9090),  /* A4 Tech Co., Ltd XL-730K / XL-750BK / XL-755BK Laser Mouse */
slouken@12459
  1775
        MAKE_VIDPID(0x09da, 0x90c0),  /* A4 Tech Co., Ltd X7 G800V keyboard */
slouken@12459
  1776
        MAKE_VIDPID(0x09da, 0xf012),  /* A4 Tech Co., Ltd Bloody V7 mouse */
slouken@12459
  1777
        MAKE_VIDPID(0x09da, 0xf32a),  /* A4 Tech Co., Ltd Bloody B540 keyboard */
slouken@12459
  1778
        MAKE_VIDPID(0x09da, 0xf613),  /* A4 Tech Co., Ltd Bloody V2 mouse */
slouken@12459
  1779
        MAKE_VIDPID(0x09da, 0xf624),  /* A4 Tech Co., Ltd Bloody B120 Keyboard */
slouken@12459
  1780
slouken@12459
  1781
        MAKE_VIDPID(0x1b1c, 0x1b3c),  /* Corsair Harpoon RGB gaming mouse */
slouken@12459
  1782
slouken@12459
  1783
        MAKE_VIDPID(0x1d57, 0xad03),  /* [T3] 2.4GHz and IR Air Mouse Remote Control */
slouken@12459
  1784
slouken@12459
  1785
        MAKE_VIDPID(0x1e7d, 0x2e4a),  /* Roccat Tyon Mouse */
slouken@12459
  1786
slouken@12459
  1787
        MAKE_VIDPID(0x20a0, 0x422d),  /* Winkeyless.kr Keyboards */
slouken@12459
  1788
slouken@12459
  1789
        MAKE_VIDPID(0x2516, 0x001f),  /* Cooler Master Storm Mizar Mouse */
slouken@12459
  1790
        MAKE_VIDPID(0x2516, 0x0028),  /* Cooler Master Storm Alcor Mouse */
slouken@12459
  1791
    };
slouken@12459
  1792
slouken@12459
  1793
    unsigned int i;
slouken@12459
  1794
    Uint32 id;
slouken@12088
  1795
    Uint16 vendor;
slouken@12088
  1796
    Uint16 product;
slouken@12088
  1797
slouken@12088
  1798
    SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
slouken@12088
  1799
slouken@12459
  1800
    /* Check the joystick blacklist */
slouken@12459
  1801
    id = MAKE_VIDPID(vendor, product);
slouken@12459
  1802
    for (i = 0; i < SDL_arraysize(joystick_blacklist); ++i) {
slouken@12459
  1803
        if (id == joystick_blacklist[i]) {
slouken@12459
  1804
            return SDL_TRUE;
slouken@12459
  1805
        }
slouken@12459
  1806
    }
slouken@12459
  1807
slouken@13429
  1808
    if (SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0) == SDL_CONTROLLER_TYPE_PS4 && SDL_IsPS4RemapperRunning()) {
slouken@12088
  1809
        return SDL_TRUE;
slouken@12088
  1810
    }
slouken@12088
  1811
slouken@12088
  1812
    if (SDL_IsGameControllerNameAndGUID(name, guid) &&
slouken@12088
  1813
        SDL_ShouldIgnoreGameController(name, guid)) {
slouken@12088
  1814
        return SDL_TRUE;
slouken@12088
  1815
    }
slouken@12088
  1816
slouken@12088
  1817
    return SDL_FALSE;
slouken@12088
  1818
}
slouken@12088
  1819
slouken@6693
  1820
/* return the guid for this index */
slouken@6738
  1821
SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
slouken@6690
  1822
{
slouken@12088
  1823
    SDL_JoystickDriver *driver;
slouken@12088
  1824
    SDL_JoystickGUID guid;
slouken@12088
  1825
slouken@12088
  1826
    SDL_LockJoysticks();
slouken@12088
  1827
    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
slouken@12088
  1828
        guid = driver->GetDeviceGUID(device_index);
slouken@12088
  1829
    } else {
slouken@12088
  1830
        SDL_zero(guid);
slouken@7294
  1831
    }
slouken@12088
  1832
    SDL_UnlockJoysticks();
slouken@12088
  1833
slouken@12088
  1834
    return guid;
slouken@6690
  1835
}
slouken@6690
  1836
slouken@10595
  1837
Uint16 SDL_JoystickGetDeviceVendor(int device_index)
slouken@10595
  1838
{
slouken@10595
  1839
    Uint16 vendor;
slouken@10595
  1840
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
slouken@10595
  1841
slouken@10855
  1842
    SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
slouken@10595
  1843
    return vendor;
slouken@10595
  1844
}
slouken@10595
  1845
slouken@10595
  1846
Uint16 SDL_JoystickGetDeviceProduct(int device_index)
slouken@10595
  1847
{
slouken@10595
  1848
    Uint16 product;
slouken@10595
  1849
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
slouken@10595
  1850
slouken@10855
  1851
    SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
slouken@10595
  1852
    return product;
slouken@10595
  1853
}
slouken@10595
  1854
slouken@10595
  1855
Uint16 SDL_JoystickGetDeviceProductVersion(int device_index)
slouken@10595
  1856
{
slouken@10595
  1857
    Uint16 version;
slouken@10595
  1858
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
slouken@10595
  1859
slouken@10855
  1860
    SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
slouken@10595
  1861
    return version;
slouken@10595
  1862
}
slouken@10595
  1863
slouken@10855
  1864
SDL_JoystickType SDL_JoystickGetDeviceType(int device_index)
slouken@10855
  1865
{
slouken@10855
  1866
    SDL_JoystickType type;
slouken@10855
  1867
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
slouken@10855
  1868
slouken@10855
  1869
    type = SDL_GetJoystickGUIDType(guid);
slouken@10855
  1870
    if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
slouken@10855
  1871
        if (SDL_IsGameController(device_index)) {
slouken@10855
  1872
            type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
slouken@10855
  1873
        }
slouken@10855
  1874
    }
slouken@10855
  1875
    return type;
slouken@10855
  1876
}
slouken@10855
  1877
slouken@10934
  1878
SDL_JoystickID SDL_JoystickGetDeviceInstanceID(int device_index)
slouken@10934
  1879
{
slouken@12088
  1880
    SDL_JoystickDriver *driver;
slouken@12088
  1881
    SDL_JoystickID instance_id = -1;
slouken@12088
  1882
slouken@12088
  1883
    SDL_LockJoysticks();
slouken@12088
  1884
    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
slouken@12088
  1885
        instance_id = driver->GetDeviceInstanceID(device_index);
slouken@10934
  1886
    }
slouken@12088
  1887
    SDL_UnlockJoysticks();
slouken@12088
  1888
slouken@12088
  1889
    return instance_id;
slouken@12088
  1890
}
slouken@12088
  1891
slouken@12088
  1892
int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id)
slouken@12088
  1893
{
slouken@12088
  1894
    int i, num_joysticks, device_index = -1;
slouken@12088
  1895
slouken@12088
  1896
    SDL_LockJoysticks();
slouken@12088
  1897
    num_joysticks = SDL_NumJoysticks();
slouken@12088
  1898
    for (i = 0; i < num_joysticks; ++i) {
slouken@12088
  1899
        if (SDL_JoystickGetDeviceInstanceID(i) == instance_id) {
slouken@12088
  1900
            device_index = i;
slouken@12088
  1901
            break;
slouken@12088
  1902
        }
slouken@12088
  1903
    }
slouken@12088
  1904
    SDL_UnlockJoysticks();
slouken@12088
  1905
slouken@12088
  1906
    return device_index;
slouken@10934
  1907
}
slouken@10934
  1908
slouken@6738
  1909
SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
slouken@6690
  1910
{
slouken@7789
  1911
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@7789
  1912
        SDL_JoystickGUID emptyGUID;
slouken@8920
  1913
        SDL_zero(emptyGUID);
slouken@7789
  1914
        return emptyGUID;
slouken@7789
  1915
    }
slouken@12088
  1916
    return joystick->guid;
slouken@6690
  1917
}
slouken@6690
  1918
slouken@10595
  1919
Uint16 SDL_JoystickGetVendor(SDL_Joystick * joystick)
slouken@10595
  1920
{
slouken@10595
  1921
    Uint16 vendor;
slouken@10595
  1922
    SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
slouken@10595
  1923
slouken@10855
  1924
    SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
slouken@10595
  1925
    return vendor;
slouken@10595
  1926
}
slouken@10595
  1927
slouken@10595
  1928
Uint16 SDL_JoystickGetProduct(SDL_Joystick * joystick)
slouken@10595
  1929
{
slouken@10595
  1930
    Uint16 product;
slouken@10595
  1931
    SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
slouken@10595
  1932
slouken@10855
  1933
    SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
slouken@10595
  1934
    return product;
slouken@10595
  1935
}
slouken@10595
  1936
slouken@10595
  1937
Uint16 SDL_JoystickGetProductVersion(SDL_Joystick * joystick)
slouken@10595
  1938
{
slouken@10595
  1939
    Uint16 version;
slouken@10595
  1940
    SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
slouken@10595
  1941
slouken@10855
  1942
    SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
slouken@10595
  1943
    return version;
slouken@10595
  1944
}
slouken@10595
  1945
slouken@10855
  1946
SDL_JoystickType SDL_JoystickGetType(SDL_Joystick * joystick)
slouken@10855
  1947
{
slouken@10855
  1948
    SDL_JoystickType type;
slouken@10855
  1949
    SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
slouken@10855
  1950
slouken@10855
  1951
    type = SDL_GetJoystickGUIDType(guid);
slouken@10855
  1952
    if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
slouken@10855
  1953
        if (joystick && joystick->is_game_controller) {
slouken@10855
  1954
            type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
slouken@10855
  1955
        }
slouken@10855
  1956
    }
slouken@10855
  1957
    return type;
slouken@10855
  1958
}
slouken@10855
  1959
slouken@6690
  1960
/* convert the guid to a printable string */
slouken@8920
  1961
void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID)
slouken@6690
  1962
{
slouken@7191
  1963
    static const char k_rgchHexToASCII[] = "0123456789abcdef";
slouken@7191
  1964
    int i;
slouken@6690
  1965
icculus@6748
  1966
    if ((pszGUID == NULL) || (cbGUID <= 0)) {
icculus@6748
  1967
        return;
icculus@6748
  1968
    }
icculus@6748
  1969
slouken@8920
  1970
    for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) {
slouken@7191
  1971
        /* each input byte writes 2 ascii chars, and might write a null byte. */
slouken@7191
  1972
        /* If we don't have room for next input byte, stop */
slouken@7191
  1973
        unsigned char c = guid.data[i];
slouken@6690
  1974
slouken@8920
  1975
        *pszGUID++ = k_rgchHexToASCII[c >> 4];
slouken@8920
  1976
        *pszGUID++ = k_rgchHexToASCII[c & 0x0F];
slouken@7191
  1977
    }
slouken@7191
  1978
    *pszGUID = '\0';
slouken@6690
  1979
}
slouken@6690
  1980
slouken@7191
  1981
/*-----------------------------------------------------------------------------
slouken@7191
  1982
 * Purpose: Returns the 4 bit nibble for a hex character
slouken@7191
  1983
 * Input  : c -
slouken@7191
  1984
 * Output : unsigned char
slouken@7191
  1985
 *-----------------------------------------------------------------------------*/
slouken@8920
  1986
static unsigned char nibble(char c)
slouken@6690
  1987
{
slouken@8920
  1988
    if ((c >= '0') && (c <= '9')) {
slouken@7191
  1989
        return (unsigned char)(c - '0');
slouken@7191
  1990
    }
slouken@6690
  1991
slouken@8920
  1992
    if ((c >= 'A') && (c <= 'F')) {
slouken@7191
  1993
        return (unsigned char)(c - 'A' + 0x0a);
slouken@7191
  1994
    }
slouken@6690
  1995
slouken@8920
  1996
    if ((c >= 'a') && (c <= 'f')) {
slouken@7191
  1997
        return (unsigned char)(c - 'a' + 0x0a);
slouken@7191
  1998
    }
slouken@6690
  1999
slouken@7191
  2000
    /* received an invalid character, and no real way to return an error */
slouken@8920
  2001
    /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
slouken@7191
  2002
    return 0;
slouken@6690
  2003
}
slouken@6690
  2004
slouken@6690
  2005
/* convert the string version of a joystick guid to the struct */
slouken@6738
  2006
SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
slouken@6690
  2007
{
slouken@7191
  2008
    SDL_JoystickGUID guid;
slouken@7191
  2009
    int maxoutputbytes= sizeof(guid);
slouken@8920
  2010
    size_t len = SDL_strlen(pchGUID);
slouken@7191
  2011
    Uint8 *p;
slouken@7922
  2012
    size_t i;
slouken@6690
  2013
slouken@7191
  2014
    /* Make sure it's even */
slouken@8920
  2015
    len = (len) & ~0x1;
slouken@6690
  2016
slouken@8920
  2017
    SDL_memset(&guid, 0x00, sizeof(guid));
slouken@6690
  2018
slouken@7191
  2019
    p = (Uint8 *)&guid;
slouken@8920
  2020
    for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) {
slouken@8920
  2021
        *p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]);
slouken@7191
  2022
    }
slouken@6690
  2023
slouken@7191
  2024
    return guid;
slouken@6690
  2025
}
slouken@6690
  2026
slouken@9884
  2027
/* update the power level for this joystick */
slouken@9884
  2028
void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel)
slouken@9884
  2029
{
slouken@9884
  2030
    joystick->epowerlevel = ePowerLevel;
slouken@9884
  2031
}
slouken@9884
  2032
slouken@9884
  2033
/* return its power level */
slouken@9884
  2034
SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick)
slouken@9884
  2035
{
slouken@9884
  2036
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@12088
  2037
        return SDL_JOYSTICK_POWER_UNKNOWN;
slouken@9884
  2038
    }
slouken@9884
  2039
    return joystick->epowerlevel;
slouken@9884
  2040
}
slouken@9884
  2041
slouken@1895
  2042
/* vi: set ts=4 sw=4 expandtab: */