src/joystick/SDL_joystick.c
author Ethan Lee <flibitijibibo@flibitijibibo.com>
Tue, 12 Mar 2019 20:27:54 -0400
changeset 12641 64597a7e8771
parent 12503 806492103856
child 12672 d5b4d374a312
permissions -rw-r--r--
hidapi: Add support for Wii U/Switch USB GameCube controller adapter.

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