src/joystick/SDL_joystick.c
author Sam Lantinga
Wed, 18 Jan 2017 12:19:57 -0800
changeset 10821 b0b8395f5cf9
parent 10752 c9d3ff50dfcf
child 10823 77ef0962ea62
permissions -rw-r--r--
Removed unused variable
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 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@0
    26
#include "SDL_events.h"
slouken@1361
    27
#include "SDL_sysjoystick.h"
icculus@5861
    28
#include "SDL_assert.h"
jorgen@7279
    29
#include "SDL_hints.h"
icculus@5861
    30
slouken@1361
    31
#if !SDL_EVENTS_DISABLED
slouken@1361
    32
#include "../events/SDL_events_c.h"
slouken@0
    33
#endif
slouken@0
    34
slouken@7337
    35
static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
slouken@6712
    36
static SDL_Joystick *SDL_joysticks = NULL;
slouken@10704
    37
static SDL_bool SDL_updating_joystick = SDL_FALSE;
slouken@10659
    38
static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
slouken@10659
    39
slouken@10688
    40
void
slouken@10688
    41
SDL_LockJoystickList(void)
slouken@10659
    42
{
slouken@10659
    43
    if (SDL_joystick_lock) {
slouken@10659
    44
        SDL_LockMutex(SDL_joystick_lock);
slouken@10659
    45
    }
slouken@10659
    46
}
slouken@10659
    47
slouken@10688
    48
void
slouken@10688
    49
SDL_UnlockJoystickList(void)
slouken@10659
    50
{
slouken@10659
    51
    if (SDL_joystick_lock) {
slouken@10659
    52
        SDL_UnlockMutex(SDL_joystick_lock);
slouken@10659
    53
    }
slouken@10659
    54
}
slouken@10659
    55
slouken@0
    56
slouken@7432
    57
static void
slouken@7432
    58
SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
slouken@7432
    59
{
slouken@7432
    60
    if (hint && *hint == '1') {
slouken@7432
    61
        SDL_joystick_allows_background_events = SDL_TRUE;
slouken@7432
    62
    } else {
slouken@7432
    63
        SDL_joystick_allows_background_events = SDL_FALSE;
slouken@7432
    64
    }
slouken@7432
    65
}
slouken@7432
    66
slouken@1895
    67
int
slouken@1895
    68
SDL_JoystickInit(void)
slouken@0
    69
{
slouken@1895
    70
    int status;
philipp@7500
    71
slouken@10659
    72
    /* Create the joystick list lock */
slouken@10659
    73
    if (!SDL_joystick_lock) {
slouken@10659
    74
        SDL_joystick_lock = SDL_CreateMutex();
slouken@10659
    75
    }
slouken@10659
    76
slouken@7432
    77
    /* See if we should allow joystick events while in the background */
slouken@7432
    78
    SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
slouken@7432
    79
                        SDL_JoystickAllowBackgroundEventsChanged, NULL);
slouken@0
    80
slouken@7360
    81
#if !SDL_EVENTS_DISABLED
slouken@7360
    82
    if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
slouken@7360
    83
        return -1;
slouken@7360
    84
    }
slouken@7360
    85
#endif /* !SDL_EVENTS_DISABLED */
slouken@7360
    86
slouken@1895
    87
    status = SDL_SYS_JoystickInit();
slouken@1895
    88
    if (status >= 0) {
slouken@7337
    89
        status = 0;
slouken@1895
    90
    }
slouken@1895
    91
    return (status);
slouken@0
    92
}
slouken@0
    93
slouken@0
    94
/*
slouken@0
    95
 * Count the number of joysticks attached to the system
slouken@0
    96
 */
slouken@1895
    97
int
slouken@1895
    98
SDL_NumJoysticks(void)
slouken@0
    99
{
slouken@6690
   100
    return SDL_SYS_NumJoysticks();
slouken@0
   101
}
slouken@0
   102
slouken@0
   103
/*
slouken@0
   104
 * Get the implementation dependent name of a joystick
slouken@0
   105
 */
slouken@1895
   106
const char *
slouken@6690
   107
SDL_JoystickNameForIndex(int device_index)
slouken@0
   108
{
slouken@6690
   109
    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
slouken@6690
   110
        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
slouken@1895
   111
        return (NULL);
slouken@1895
   112
    }
slouken@6707
   113
    return (SDL_SYS_JoystickNameForDeviceIndex(device_index));
slouken@0
   114
}
slouken@0
   115
slouken@0
   116
/*
slouken@10745
   117
 * Return true if this joystick is known to have all axes centered at zero
slouken@10745
   118
 * This isn't generally needed unless the joystick never generates an initial axis value near zero,
slouken@10745
   119
 * e.g. it's emulating axes with digital buttons
slouken@10745
   120
 */
slouken@10745
   121
static SDL_bool
slouken@10745
   122
SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick)
slouken@10745
   123
{
slouken@10745
   124
    struct {
slouken@10745
   125
        Uint16 vendor;
slouken@10745
   126
        Uint16 product;
slouken@10745
   127
    } zero_centered_joysticks[] = {
slouken@10749
   128
        { 0x0e8f, 0x3013 }, /* HuiJia SNES USB adapter */
slouken@10745
   129
    };
slouken@10745
   130
slouken@10745
   131
    int i;
slouken@10745
   132
    Uint16 vendor = SDL_JoystickGetVendor(joystick);
slouken@10745
   133
    Uint16 product = SDL_JoystickGetProduct(joystick);
slouken@10745
   134
slouken@10751
   135
    if (joystick->naxes == 2) {
slouken@10751
   136
        /* Assume D-pad or thumbstick style axes are centered at 0 */
slouken@10751
   137
        return SDL_TRUE;
slouken@10751
   138
    }
slouken@10751
   139
slouken@10745
   140
    for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) {
slouken@10745
   141
        if (vendor == zero_centered_joysticks[i].vendor &&
slouken@10745
   142
            product == zero_centered_joysticks[i].product) {
slouken@10745
   143
            return SDL_TRUE;
slouken@10745
   144
        }
slouken@10745
   145
    }
slouken@10745
   146
    return SDL_FALSE;
slouken@10745
   147
}
slouken@10745
   148
slouken@10745
   149
/*
slouken@0
   150
 * Open a joystick for use - the index passed as an argument refers to
slouken@0
   151
 * the N'th joystick on the system.  This index is the value which will
slouken@0
   152
 * identify this joystick in future joystick events.
slouken@0
   153
 *
slouken@0
   154
 * This function returns a joystick identifier, or NULL if an error occurred.
slouken@0
   155
 */
slouken@1895
   156
SDL_Joystick *
slouken@1895
   157
SDL_JoystickOpen(int device_index)
slouken@0
   158
{
slouken@1895
   159
    SDL_Joystick *joystick;
slouken@7191
   160
    SDL_Joystick *joysticklist;
slouken@7191
   161
    const char *joystickname = NULL;
slouken@0
   162
slouken@6690
   163
    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
slouken@6690
   164
        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
slouken@1895
   165
        return (NULL);
slouken@1895
   166
    }
slouken@0
   167
slouken@10659
   168
    SDL_LockJoystickList();
slouken@10659
   169
slouken@7191
   170
    joysticklist = SDL_joysticks;
slouken@7191
   171
    /* If the joystick is already open, return it
slouken@7191
   172
    * it is important that we have a single joystick * for each instance id
slouken@7191
   173
    */
slouken@8920
   174
    while (joysticklist) {
slouken@8920
   175
        if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id) {
slouken@7191
   176
                joystick = joysticklist;
slouken@7191
   177
                ++joystick->ref_count;
slouken@10659
   178
                SDL_UnlockJoystickList();
slouken@7191
   179
                return (joystick);
slouken@7191
   180
        }
slouken@7191
   181
        joysticklist = joysticklist->next;
slouken@1895
   182
    }
slouken@0
   183
slouken@1895
   184
    /* Create and initialize the joystick */
slouken@1895
   185
    joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
icculus@3608
   186
    if (joystick == NULL) {
icculus@3608
   187
        SDL_OutOfMemory();
slouken@10659
   188
        SDL_UnlockJoystickList();
icculus@3608
   189
        return NULL;
icculus@3608
   190
    }
icculus@3608
   191
icculus@3608
   192
    SDL_memset(joystick, 0, (sizeof *joystick));
slouken@6690
   193
    if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) {
icculus@3608
   194
        SDL_free(joystick);
slouken@10659
   195
        SDL_UnlockJoystickList();
icculus@3608
   196
        return NULL;
icculus@3608
   197
    }
slouken@6690
   198
slouken@8920
   199
    joystickname = SDL_SYS_JoystickNameForDeviceIndex(device_index);
slouken@8920
   200
    if (joystickname)
slouken@8920
   201
        joystick->name = SDL_strdup(joystickname);
slouken@7191
   202
    else
slouken@7191
   203
        joystick->name = NULL;
slouken@6690
   204
icculus@3608
   205
    if (joystick->naxes > 0) {
slouken@10713
   206
        joystick->axes = (SDL_JoystickAxisInfo *) SDL_calloc(joystick->naxes, sizeof(SDL_JoystickAxisInfo));
icculus@3608
   207
    }
icculus@3608
   208
    if (joystick->nhats > 0) {
slouken@10713
   209
        joystick->hats = (Uint8 *) SDL_calloc(joystick->nhats, sizeof(Uint8));
icculus@3608
   210
    }
icculus@3608
   211
    if (joystick->nballs > 0) {
slouken@10713
   212
        joystick->balls = (struct balldelta *) SDL_calloc(joystick->nballs, sizeof(*joystick->balls));
icculus@3608
   213
    }
icculus@3608
   214
    if (joystick->nbuttons > 0) {
slouken@10713
   215
        joystick->buttons = (Uint8 *) SDL_calloc(joystick->nbuttons, sizeof(Uint8));
slouken@1895
   216
    }
icculus@3608
   217
    if (((joystick->naxes > 0) && !joystick->axes)
icculus@3608
   218
        || ((joystick->nhats > 0) && !joystick->hats)
icculus@3608
   219
        || ((joystick->nballs > 0) && !joystick->balls)
icculus@3608
   220
        || ((joystick->nbuttons > 0) && !joystick->buttons)) {
icculus@3608
   221
        SDL_OutOfMemory();
icculus@3608
   222
        SDL_JoystickClose(joystick);
slouken@10659
   223
        SDL_UnlockJoystickList();
icculus@3608
   224
        return NULL;
icculus@3608
   225
    }
slouken@9884
   226
    joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
icculus@3608
   227
slouken@10745
   228
    /* If this joystick is known to have all zero centered axes, skip the auto-centering code */
slouken@10745
   229
    if (SDL_JoystickAxesCenteredAtZero(joystick)) {
slouken@10745
   230
        int i;
slouken@10745
   231
slouken@10745
   232
        for (i = 0; i < joystick->naxes; ++i) {
slouken@10745
   233
            joystick->axes[i].has_initial_value = SDL_TRUE;
slouken@10745
   234
        }
slouken@10745
   235
    }
slouken@10745
   236
icculus@3608
   237
    /* Add joystick to list */
icculus@3608
   238
    ++joystick->ref_count;
slouken@7191
   239
    /* Link the joystick in the list */
slouken@7191
   240
    joystick->next = SDL_joysticks;
slouken@7191
   241
    SDL_joysticks = joystick;
slouken@6690
   242
slouken@10688
   243
    SDL_UnlockJoystickList();
icculus@3608
   244
slouken@10688
   245
    SDL_SYS_JoystickUpdate(joystick);
slouken@10659
   246
slouken@1895
   247
    return (joystick);
slouken@0
   248
}
slouken@0
   249
slouken@2713
   250
slouken@2713
   251
/*
slouken@2713
   252
 * Checks to make sure the joystick is valid.
slouken@2713
   253
 */
slouken@2713
   254
int
slouken@6690
   255
SDL_PrivateJoystickValid(SDL_Joystick * joystick)
slouken@0
   256
{
slouken@1895
   257
    int valid;
slouken@0
   258
slouken@8920
   259
    if (joystick == NULL) {
slouken@1895
   260
        SDL_SetError("Joystick hasn't been opened yet");
slouken@1895
   261
        valid = 0;
slouken@1895
   262
    } else {
slouken@1895
   263
        valid = 1;
slouken@1895
   264
    }
slouken@7191
   265
slouken@1895
   266
    return valid;
slouken@0
   267
}
slouken@0
   268
slouken@0
   269
/*
slouken@0
   270
 * Get the number of multi-dimensional axis controls on a joystick
slouken@0
   271
 */
slouken@1895
   272
int
slouken@1895
   273
SDL_JoystickNumAxes(SDL_Joystick * joystick)
slouken@0
   274
{
slouken@6690
   275
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   276
        return (-1);
slouken@1895
   277
    }
slouken@1895
   278
    return (joystick->naxes);
slouken@0
   279
}
slouken@0
   280
slouken@0
   281
/*
slouken@0
   282
 * Get the number of hats on a joystick
slouken@0
   283
 */
slouken@1895
   284
int
slouken@1895
   285
SDL_JoystickNumHats(SDL_Joystick * joystick)
slouken@0
   286
{
slouken@6690
   287
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   288
        return (-1);
slouken@1895
   289
    }
slouken@1895
   290
    return (joystick->nhats);
slouken@0
   291
}
slouken@0
   292
slouken@0
   293
/*
slouken@0
   294
 * Get the number of trackballs on a joystick
slouken@0
   295
 */
slouken@1895
   296
int
slouken@1895
   297
SDL_JoystickNumBalls(SDL_Joystick * joystick)
slouken@0
   298
{
slouken@6690
   299
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   300
        return (-1);
slouken@1895
   301
    }
slouken@1895
   302
    return (joystick->nballs);
slouken@0
   303
}
slouken@0
   304
slouken@0
   305
/*
slouken@0
   306
 * Get the number of buttons on a joystick
slouken@0
   307
 */
slouken@1895
   308
int
slouken@1895
   309
SDL_JoystickNumButtons(SDL_Joystick * joystick)
slouken@0
   310
{
slouken@6690
   311
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   312
        return (-1);
slouken@1895
   313
    }
slouken@1895
   314
    return (joystick->nbuttons);
slouken@0
   315
}
slouken@0
   316
slouken@0
   317
/*
slouken@0
   318
 * Get the current state of an axis control on a joystick
slouken@0
   319
 */
slouken@1895
   320
Sint16
slouken@1895
   321
SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
slouken@0
   322
{
slouken@1895
   323
    Sint16 state;
slouken@0
   324
slouken@6690
   325
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   326
        return (0);
slouken@1895
   327
    }
slouken@1895
   328
    if (axis < joystick->naxes) {
slouken@10713
   329
        state = joystick->axes[axis].value;
slouken@1895
   330
    } else {
slouken@1895
   331
        SDL_SetError("Joystick only has %d axes", joystick->naxes);
slouken@1895
   332
        state = 0;
slouken@1895
   333
    }
slouken@1895
   334
    return (state);
slouken@0
   335
}
slouken@0
   336
slouken@0
   337
/*
slouken@10752
   338
 * Get the initial state of an axis control on a joystick
slouken@10752
   339
 */
slouken@10752
   340
SDL_bool
slouken@10752
   341
SDL_JoystickGetAxisInitialState(SDL_Joystick * joystick, int axis, Sint16 *state)
slouken@10752
   342
{
slouken@10752
   343
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@10752
   344
        return SDL_FALSE;
slouken@10752
   345
    }
slouken@10752
   346
    if (axis >= joystick->naxes) {
slouken@10752
   347
        SDL_SetError("Joystick only has %d axes", joystick->naxes);
slouken@10752
   348
        return SDL_FALSE;
slouken@10752
   349
    }
slouken@10752
   350
    if (state) {
slouken@10752
   351
        *state = joystick->axes[axis].initial_value;
slouken@10752
   352
    }
slouken@10752
   353
    return joystick->axes[axis].has_initial_value;
slouken@10752
   354
}
slouken@10752
   355
slouken@10752
   356
/*
slouken@0
   357
 * Get the current state of a hat on a joystick
slouken@0
   358
 */
slouken@1895
   359
Uint8
slouken@1895
   360
SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
slouken@0
   361
{
slouken@1895
   362
    Uint8 state;
slouken@0
   363
slouken@6690
   364
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   365
        return (0);
slouken@1895
   366
    }
slouken@1895
   367
    if (hat < joystick->nhats) {
slouken@1895
   368
        state = joystick->hats[hat];
slouken@1895
   369
    } else {
slouken@1895
   370
        SDL_SetError("Joystick only has %d hats", joystick->nhats);
slouken@1895
   371
        state = 0;
slouken@1895
   372
    }
slouken@1895
   373
    return (state);
slouken@0
   374
}
slouken@0
   375
slouken@0
   376
/*
slouken@0
   377
 * Get the ball axis change since the last poll
slouken@0
   378
 */
slouken@1895
   379
int
slouken@1895
   380
SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
slouken@0
   381
{
slouken@1895
   382
    int retval;
slouken@0
   383
slouken@6690
   384
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   385
        return (-1);
slouken@1895
   386
    }
slouken@0
   387
slouken@1895
   388
    retval = 0;
slouken@1895
   389
    if (ball < joystick->nballs) {
slouken@1895
   390
        if (dx) {
slouken@1895
   391
            *dx = joystick->balls[ball].dx;
slouken@1895
   392
        }
slouken@1895
   393
        if (dy) {
slouken@1895
   394
            *dy = joystick->balls[ball].dy;
slouken@1895
   395
        }
slouken@1895
   396
        joystick->balls[ball].dx = 0;
slouken@1895
   397
        joystick->balls[ball].dy = 0;
slouken@1895
   398
    } else {
icculus@7037
   399
        return SDL_SetError("Joystick only has %d balls", joystick->nballs);
slouken@1895
   400
    }
slouken@1895
   401
    return (retval);
slouken@0
   402
}
slouken@0
   403
slouken@0
   404
/*
slouken@0
   405
 * Get the current state of a button on a joystick
slouken@0
   406
 */
slouken@1895
   407
Uint8
slouken@1895
   408
SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
slouken@0
   409
{
slouken@1895
   410
    Uint8 state;
slouken@0
   411
slouken@6690
   412
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   413
        return (0);
slouken@1895
   414
    }
slouken@1895
   415
    if (button < joystick->nbuttons) {
slouken@1895
   416
        state = joystick->buttons[button];
slouken@1895
   417
    } else {
slouken@1895
   418
        SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
slouken@1895
   419
        state = 0;
slouken@1895
   420
    }
slouken@1895
   421
    return (state);
slouken@0
   422
}
slouken@0
   423
slouken@0
   424
/*
slouken@6690
   425
 * Return if the joystick in question is currently attached to the system,
philipp@7500
   426
 *  \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
slouken@6690
   427
 */
slouken@6707
   428
SDL_bool
slouken@6707
   429
SDL_JoystickGetAttached(SDL_Joystick * joystick)
slouken@6690
   430
{
slouken@7191
   431
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6707
   432
        return SDL_FALSE;
slouken@6690
   433
    }
slouken@6690
   434
slouken@7191
   435
    return SDL_SYS_JoystickAttached(joystick);
slouken@6690
   436
}
slouken@6690
   437
slouken@6690
   438
/*
slouken@6690
   439
 * Get the instance id for this opened joystick
slouken@6690
   440
 */
slouken@7191
   441
SDL_JoystickID
slouken@6707
   442
SDL_JoystickInstanceID(SDL_Joystick * joystick)
slouken@6690
   443
{
slouken@7191
   444
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6690
   445
        return (-1);
slouken@6690
   446
    }
slouken@6690
   447
slouken@7191
   448
    return (joystick->instance_id);
slouken@6690
   449
}
slouken@6690
   450
slouken@6690
   451
/*
icculus@9916
   452
 * Find the SDL_Joystick that owns this instance id
icculus@9916
   453
 */
icculus@9916
   454
SDL_Joystick *
icculus@9916
   455
SDL_JoystickFromInstanceID(SDL_JoystickID joyid)
icculus@9916
   456
{
slouken@10659
   457
    SDL_Joystick *joystick;
slouken@10659
   458
slouken@10659
   459
    SDL_LockJoystickList();
slouken@10659
   460
    for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
icculus@9916
   461
        if (joystick->instance_id == joyid) {
slouken@10659
   462
            SDL_UnlockJoystickList();
icculus@9916
   463
            return joystick;
icculus@9916
   464
        }
icculus@9916
   465
    }
slouken@10659
   466
    SDL_UnlockJoystickList();
icculus@9916
   467
    return NULL;
icculus@9916
   468
}
icculus@9916
   469
icculus@9916
   470
/*
slouken@6690
   471
 * Get the friendly name of this joystick
slouken@6690
   472
 */
slouken@6690
   473
const char *
slouken@6690
   474
SDL_JoystickName(SDL_Joystick * joystick)
slouken@6690
   475
{
slouken@6690
   476
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6690
   477
        return (NULL);
slouken@6690
   478
    }
slouken@7191
   479
slouken@6690
   480
    return (joystick->name);
slouken@6690
   481
}
slouken@6690
   482
slouken@6690
   483
/*
slouken@0
   484
 * Close a joystick previously opened with SDL_JoystickOpen()
slouken@0
   485
 */
slouken@1895
   486
void
slouken@1895
   487
SDL_JoystickClose(SDL_Joystick * joystick)
slouken@0
   488
{
slouken@7191
   489
    SDL_Joystick *joysticklist;
slouken@7191
   490
    SDL_Joystick *joysticklistprev;
slouken@0
   491
slouken@6690
   492
    if (!joystick) {
slouken@1895
   493
        return;
slouken@1895
   494
    }
slouken@0
   495
slouken@10659
   496
    SDL_LockJoystickList();
slouken@10659
   497
slouken@1895
   498
    /* First decrement ref count */
slouken@1895
   499
    if (--joystick->ref_count > 0) {
slouken@10659
   500
        SDL_UnlockJoystickList();
slouken@1895
   501
        return;
slouken@1895
   502
    }
slouken@0
   503
slouken@10704
   504
    if (SDL_updating_joystick) {
slouken@10659
   505
        SDL_UnlockJoystickList();
slouken@6712
   506
        return;
slouken@6712
   507
    }
slouken@6712
   508
slouken@1895
   509
    SDL_SYS_JoystickClose(joystick);
icculus@9433
   510
    joystick->hwdata = NULL;
slouken@0
   511
slouken@7191
   512
    joysticklist = SDL_joysticks;
slouken@7191
   513
    joysticklistprev = NULL;
slouken@8920
   514
    while (joysticklist) {
slouken@8920
   515
        if (joystick == joysticklist) {
slouken@8920
   516
            if (joysticklistprev) {
slouken@7191
   517
                /* unlink this entry */
slouken@7191
   518
                joysticklistprev->next = joysticklist->next;
slouken@8920
   519
            } else {
slouken@7191
   520
                SDL_joysticks = joystick->next;
slouken@7191
   521
            }
slouken@7191
   522
            break;
slouken@7191
   523
        }
slouken@7191
   524
        joysticklistprev = joysticklist;
slouken@7191
   525
        joysticklist = joysticklist->next;
slouken@7191
   526
    }
slouken@7191
   527
slouken@7719
   528
    SDL_free(joystick->name);
slouken@0
   529
slouken@1895
   530
    /* Free the data associated with this joystick */
slouken@7719
   531
    SDL_free(joystick->axes);
slouken@7719
   532
    SDL_free(joystick->hats);
slouken@7719
   533
    SDL_free(joystick->balls);
slouken@7719
   534
    SDL_free(joystick->buttons);
slouken@1895
   535
    SDL_free(joystick);
slouken@10659
   536
slouken@10659
   537
    SDL_UnlockJoystickList();
slouken@0
   538
}
slouken@0
   539
slouken@1895
   540
void
slouken@1895
   541
SDL_JoystickQuit(void)
slouken@0
   542
{
slouken@6712
   543
    /* Make sure we're not getting called in the middle of updating joysticks */
slouken@6712
   544
    SDL_assert(!SDL_updating_joystick);
slouken@6712
   545
slouken@10659
   546
    SDL_LockJoystickList();
slouken@10659
   547
slouken@1895
   548
    /* Stop the event polling */
slouken@8920
   549
    while (SDL_joysticks) {
slouken@7191
   550
        SDL_joysticks->ref_count = 1;
slouken@6690
   551
        SDL_JoystickClose(SDL_joysticks);
slouken@7191
   552
    }
icculus@5856
   553
slouken@1895
   554
    /* Quit the joystick setup */
slouken@1895
   555
    SDL_SYS_JoystickQuit();
slouken@7360
   556
slouken@10659
   557
    SDL_UnlockJoystickList();
slouken@10659
   558
slouken@7360
   559
#if !SDL_EVENTS_DISABLED
slouken@7360
   560
    SDL_QuitSubSystem(SDL_INIT_EVENTS);
slouken@7360
   561
#endif
slouken@10659
   562
slouken@10659
   563
    if (SDL_joystick_lock) {
slouken@10659
   564
        SDL_DestroyMutex(SDL_joystick_lock);
slouken@10659
   565
        SDL_joystick_lock = NULL;
slouken@10659
   566
    }
slouken@0
   567
}
slouken@0
   568
slouken@0
   569
jorgen@7279
   570
static SDL_bool
jorgen@7279
   571
SDL_PrivateJoystickShouldIgnoreEvent()
jorgen@7279
   572
{
slouken@8920
   573
    if (SDL_joystick_allows_background_events) {
jorgen@7279
   574
        return SDL_FALSE;
jorgen@7279
   575
    }
jorgen@7279
   576
slouken@7337
   577
    if (SDL_WasInit(SDL_INIT_VIDEO)) {
slouken@7337
   578
        if (SDL_GetKeyboardFocus() == NULL) {
gabomdq@7677
   579
            /* Video is initialized and we don't have focus, ignore the event. */
slouken@7337
   580
            return SDL_TRUE;
slouken@7337
   581
        } else {
slouken@7337
   582
            return SDL_FALSE;
slouken@7337
   583
        }
jorgen@7279
   584
    }
jorgen@7279
   585
gabomdq@7677
   586
    /* Video subsystem wasn't initialized, always allow the event */
slouken@7337
   587
    return SDL_FALSE;
jorgen@7279
   588
}
jorgen@7279
   589
slouken@0
   590
/* These are global for SDL_sysjoystick.c and SDL_events.c */
slouken@0
   591
slouken@10226
   592
void SDL_PrivateJoystickAdded(int device_index)
slouken@10226
   593
{
slouken@10226
   594
#if !SDL_EVENTS_DISABLED
slouken@10226
   595
    SDL_Event event;
slouken@10226
   596
slouken@10226
   597
    event.type = SDL_JOYDEVICEADDED;
slouken@10226
   598
slouken@10226
   599
    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@10226
   600
        event.jdevice.which = device_index;
slouken@10601
   601
        if ((SDL_EventOK == NULL) ||
slouken@10601
   602
             (*SDL_EventOK) (SDL_EventOKParam, &event)) {
slouken@10226
   603
            SDL_PushEvent(&event);
slouken@10226
   604
        }
slouken@10226
   605
    }
slouken@10226
   606
#endif /* !SDL_EVENTS_DISABLED */
slouken@10226
   607
}
slouken@10226
   608
slouken@10226
   609
/*
slouken@10226
   610
 * If there is an existing add event in the queue, it needs to be modified
slouken@10226
   611
 * to have the right value for which, because the number of controllers in
slouken@10226
   612
 * the system is now one less.
slouken@10226
   613
 */
slouken@10226
   614
static void UpdateEventsForDeviceRemoval()
slouken@10226
   615
{
slouken@10226
   616
    int i, num_events;
slouken@10226
   617
    SDL_Event *events;
slouken@10226
   618
slouken@10226
   619
    num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
slouken@10226
   620
    if (num_events <= 0) {
slouken@10226
   621
        return;
slouken@10226
   622
    }
slouken@10226
   623
slouken@10226
   624
    events = SDL_stack_alloc(SDL_Event, num_events);
slouken@10226
   625
    if (!events) {
slouken@10226
   626
        return;
slouken@10226
   627
    }
slouken@10226
   628
slouken@10226
   629
    num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
slouken@10226
   630
    for (i = 0; i < num_events; ++i) {
slouken@10226
   631
        --events[i].jdevice.which;
slouken@10226
   632
    }
slouken@10226
   633
    SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
slouken@10226
   634
slouken@10226
   635
    SDL_stack_free(events);
slouken@10226
   636
}
slouken@10226
   637
slouken@10226
   638
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
slouken@10226
   639
{
slouken@10226
   640
#if !SDL_EVENTS_DISABLED
slouken@10226
   641
    SDL_Event event;
slouken@10226
   642
slouken@10226
   643
    event.type = SDL_JOYDEVICEREMOVED;
slouken@10226
   644
slouken@10226
   645
    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@10226
   646
        event.jdevice.which = device_instance;
slouken@10601
   647
        if ((SDL_EventOK == NULL) ||
slouken@10601
   648
             (*SDL_EventOK) (SDL_EventOKParam, &event)) {
slouken@10226
   649
            SDL_PushEvent(&event);
slouken@10226
   650
        }
slouken@10226
   651
    }
slouken@10226
   652
slouken@10226
   653
    UpdateEventsForDeviceRemoval();
slouken@10226
   654
#endif /* !SDL_EVENTS_DISABLED */
slouken@10226
   655
}
slouken@10226
   656
slouken@1895
   657
int
slouken@1895
   658
SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
slouken@0
   659
{
slouken@1895
   660
    int posted;
slouken@10748
   661
    const int MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80;  /* ShanWan PS3 controller needed 96 */
slouken@0
   662
slouken@8920
   663
    /* Make sure we're not getting garbage or duplicate events */
slouken@6145
   664
    if (axis >= joystick->naxes) {
slouken@6145
   665
        return 0;
slouken@6145
   666
    }
slouken@10745
   667
    if (!joystick->axes[axis].has_initial_value) {
slouken@10752
   668
        joystick->axes[axis].initial_value = value;
slouken@10745
   669
        joystick->axes[axis].value = value;
slouken@10745
   670
        joystick->axes[axis].zero = value;
slouken@10745
   671
        joystick->axes[axis].has_initial_value = SDL_TRUE;
slouken@10745
   672
    }
slouken@10745
   673
    if (SDL_abs(value - joystick->axes[axis].value) <= MAX_ALLOWED_JITTER) {
slouken@8920
   674
        return 0;
slouken@8920
   675
    }
slouken@10745
   676
    if (!joystick->axes[axis].sent_initial_value) {
slouken@10745
   677
        joystick->axes[axis].sent_initial_value = SDL_TRUE;
slouken@10745
   678
        joystick->axes[axis].value = value; /* Just so we pass the check above */
slouken@10752
   679
        SDL_PrivateJoystickAxis(joystick, axis, joystick->axes[axis].initial_value);
slouken@10713
   680
    }
slouken@6145
   681
slouken@8903
   682
    /* We ignore events if we don't have keyboard focus, except for centering
slouken@8903
   683
     * events.
slouken@8903
   684
     */
slouken@8903
   685
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
slouken@10713
   686
        if ((value > joystick->axes[axis].zero && value >= joystick->axes[axis].value) ||
slouken@10713
   687
            (value < joystick->axes[axis].zero && value <= joystick->axes[axis].value)) {
slouken@8903
   688
            return 0;
slouken@8903
   689
        }
slouken@8903
   690
    }
slouken@8903
   691
slouken@1895
   692
    /* Update internal joystick state */
slouken@10713
   693
    joystick->axes[axis].value = value;
slouken@0
   694
slouken@1895
   695
    /* Post the event, if desired */
slouken@1895
   696
    posted = 0;
slouken@1361
   697
#if !SDL_EVENTS_DISABLED
slouken@4429
   698
    if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
slouken@1895
   699
        SDL_Event event;
slouken@1895
   700
        event.type = SDL_JOYAXISMOTION;
slouken@6690
   701
        event.jaxis.which = joystick->instance_id;
slouken@1895
   702
        event.jaxis.axis = axis;
slouken@1895
   703
        event.jaxis.value = value;
slouken@6690
   704
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   705
    }
slouken@1361
   706
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   707
    return (posted);
slouken@0
   708
}
slouken@0
   709
slouken@1895
   710
int
slouken@1895
   711
SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
slouken@0
   712
{
slouken@1895
   713
    int posted;
slouken@0
   714
slouken@8920
   715
    /* Make sure we're not getting garbage or duplicate events */
slouken@6145
   716
    if (hat >= joystick->nhats) {
slouken@6145
   717
        return 0;
slouken@6145
   718
    }
slouken@8920
   719
    if (value == joystick->hats[hat]) {
slouken@8920
   720
        return 0;
slouken@8920
   721
    }
slouken@6145
   722
jorgen@7279
   723
    /* We ignore events if we don't have keyboard focus, except for centering
jorgen@7279
   724
     * events.
jorgen@7279
   725
     */
jorgen@7279
   726
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
slouken@8903
   727
        if (value != SDL_HAT_CENTERED) {
jorgen@7279
   728
            return 0;
jorgen@7279
   729
        }
jorgen@7279
   730
    }
jorgen@7279
   731
slouken@8903
   732
    /* Update internal joystick state */
slouken@8903
   733
    joystick->hats[hat] = value;
jorgen@7279
   734
slouken@1895
   735
    /* Post the event, if desired */
slouken@1895
   736
    posted = 0;
slouken@1361
   737
#if !SDL_EVENTS_DISABLED
slouken@4429
   738
    if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
slouken@1895
   739
        SDL_Event event;
slouken@1895
   740
        event.jhat.type = SDL_JOYHATMOTION;
slouken@6690
   741
        event.jhat.which = joystick->instance_id;
slouken@1895
   742
        event.jhat.hat = hat;
slouken@1895
   743
        event.jhat.value = value;
slouken@6690
   744
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   745
    }
slouken@1361
   746
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   747
    return (posted);
slouken@0
   748
}
slouken@0
   749
slouken@1895
   750
int
slouken@1895
   751
SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
slouken@1895
   752
                        Sint16 xrel, Sint16 yrel)
slouken@0
   753
{
slouken@1895
   754
    int posted;
slouken@0
   755
slouken@6145
   756
    /* Make sure we're not getting garbage events */
slouken@6145
   757
    if (ball >= joystick->nballs) {
slouken@6145
   758
        return 0;
slouken@6145
   759
    }
slouken@6145
   760
jorgen@7279
   761
    /* We ignore events if we don't have keyboard focus. */
jorgen@7279
   762
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
jorgen@7279
   763
        return 0;
jorgen@7279
   764
    }
jorgen@7279
   765
slouken@1895
   766
    /* Update internal mouse state */
slouken@1895
   767
    joystick->balls[ball].dx += xrel;
slouken@1895
   768
    joystick->balls[ball].dy += yrel;
slouken@0
   769
slouken@1895
   770
    /* Post the event, if desired */
slouken@1895
   771
    posted = 0;
slouken@1361
   772
#if !SDL_EVENTS_DISABLED
slouken@4429
   773
    if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
slouken@1895
   774
        SDL_Event event;
slouken@1895
   775
        event.jball.type = SDL_JOYBALLMOTION;
slouken@6690
   776
        event.jball.which = joystick->instance_id;
slouken@1895
   777
        event.jball.ball = ball;
slouken@1895
   778
        event.jball.xrel = xrel;
slouken@1895
   779
        event.jball.yrel = yrel;
slouken@6690
   780
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   781
    }
slouken@1361
   782
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   783
    return (posted);
slouken@0
   784
}
slouken@0
   785
slouken@1895
   786
int
slouken@1895
   787
SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
slouken@0
   788
{
slouken@1895
   789
    int posted;
slouken@1361
   790
#if !SDL_EVENTS_DISABLED
slouken@1895
   791
    SDL_Event event;
slouken@0
   792
slouken@1895
   793
    switch (state) {
slouken@1895
   794
    case SDL_PRESSED:
slouken@1895
   795
        event.type = SDL_JOYBUTTONDOWN;
slouken@1895
   796
        break;
slouken@1895
   797
    case SDL_RELEASED:
slouken@1895
   798
        event.type = SDL_JOYBUTTONUP;
slouken@1895
   799
        break;
slouken@1895
   800
    default:
slouken@1895
   801
        /* Invalid state -- bail */
slouken@1895
   802
        return (0);
slouken@1895
   803
    }
slouken@1361
   804
#endif /* !SDL_EVENTS_DISABLED */
slouken@0
   805
slouken@8920
   806
    /* Make sure we're not getting garbage or duplicate events */
slouken@6145
   807
    if (button >= joystick->nbuttons) {
slouken@6145
   808
        return 0;
slouken@9884
   809
    }
slouken@9884
   810
    if (state == joystick->buttons[button]) {
slouken@9884
   811
        return 0;
slouken@9884
   812
    }
slouken@6145
   813
jorgen@7279
   814
    /* We ignore events if we don't have keyboard focus, except for button
jorgen@7279
   815
     * release. */
slouken@8903
   816
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
slouken@8903
   817
        if (state == SDL_PRESSED) {
slouken@8903
   818
            return 0;
slouken@8903
   819
        }
jorgen@7279
   820
    }
jorgen@7279
   821
slouken@1895
   822
    /* Update internal joystick state */
slouken@1895
   823
    joystick->buttons[button] = state;
slouken@0
   824
slouken@1895
   825
    /* Post the event, if desired */
slouken@1895
   826
    posted = 0;
slouken@1361
   827
#if !SDL_EVENTS_DISABLED
slouken@4429
   828
    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@6690
   829
        event.jbutton.which = joystick->instance_id;
slouken@1895
   830
        event.jbutton.button = button;
slouken@1895
   831
        event.jbutton.state = state;
slouken@6690
   832
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   833
    }
slouken@1361
   834
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   835
    return (posted);
slouken@0
   836
}
slouken@0
   837
slouken@1895
   838
void
slouken@1895
   839
SDL_JoystickUpdate(void)
slouken@0
   840
{
slouken@10704
   841
    SDL_Joystick *joystick;
slouken@7191
   842
slouken@10659
   843
    SDL_LockJoystickList();
slouken@10659
   844
slouken@10688
   845
    if (SDL_updating_joystick) {
slouken@10688
   846
        /* The joysticks are already being updated */
slouken@10688
   847
        SDL_UnlockJoystickList();
slouken@10688
   848
        return;
slouken@10688
   849
    }
slouken@10688
   850
slouken@10704
   851
    SDL_updating_joystick = SDL_TRUE;
slouken@6690
   852
slouken@10704
   853
    /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
slouken@10704
   854
    SDL_UnlockJoystickList();
slouken@6712
   855
slouken@10704
   856
    for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
slouken@8920
   857
        SDL_SYS_JoystickUpdate(joystick);
slouken@0
   858
icculus@9433
   859
        if (joystick->force_recentering) {
slouken@7191
   860
            int i;
slouken@6690
   861
slouken@10745
   862
            /* Tell the app that everything is centered/unpressed... */
slime73@9876
   863
            for (i = 0; i < joystick->naxes; i++) {
slouken@10745
   864
                if (joystick->axes[i].has_initial_value) {
slouken@10745
   865
                    SDL_PrivateJoystickAxis(joystick, i, joystick->axes[i].zero);
slouken@10745
   866
                }
slime73@9876
   867
            }
slouken@6690
   868
slime73@9876
   869
            for (i = 0; i < joystick->nbuttons; i++) {
slouken@6690
   870
                SDL_PrivateJoystickButton(joystick, i, 0);
slime73@9876
   871
            }
slouken@6690
   872
slime73@9876
   873
            for (i = 0; i < joystick->nhats; i++) {
slouken@6690
   874
                SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
slime73@9876
   875
            }
slouken@6712
   876
icculus@9433
   877
            joystick->force_recentering = SDL_FALSE;
slouken@7191
   878
        }
slouken@10704
   879
    }
slouken@6690
   880
slouken@10704
   881
    SDL_LockJoystickList();
slouken@10688
   882
slouken@10704
   883
    SDL_updating_joystick = SDL_FALSE;
slouken@6712
   884
slouken@10704
   885
    /* If any joysticks were closed while updating, free them here */
slouken@10704
   886
    for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
slouken@8920
   887
        if (joystick->ref_count <= 0) {
slouken@6712
   888
            SDL_JoystickClose(joystick);
slouken@6712
   889
        }
slouken@7191
   890
    }
slouken@6690
   891
slouken@7191
   892
    /* this needs to happen AFTER walking the joystick list above, so that any
slouken@7191
   893
       dangling hardware data from removed devices can be free'd
slouken@7191
   894
     */
slouken@7191
   895
    SDL_SYS_JoystickDetect();
slouken@10659
   896
slouken@10659
   897
    SDL_UnlockJoystickList();
slouken@0
   898
}
slouken@0
   899
slouken@1895
   900
int
slouken@1895
   901
SDL_JoystickEventState(int state)
slouken@0
   902
{
slouken@1361
   903
#if SDL_EVENTS_DISABLED
slouken@6753
   904
    return SDL_DISABLE;
slouken@0
   905
#else
slouken@4429
   906
    const Uint32 event_list[] = {
slouken@1895
   907
        SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
slouken@6690
   908
        SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
slouken@1895
   909
    };
slouken@1895
   910
    unsigned int i;
slouken@0
   911
slouken@1895
   912
    switch (state) {
slouken@1895
   913
    case SDL_QUERY:
slouken@6753
   914
        state = SDL_DISABLE;
slouken@1895
   915
        for (i = 0; i < SDL_arraysize(event_list); ++i) {
slouken@1895
   916
            state = SDL_EventState(event_list[i], SDL_QUERY);
slouken@1895
   917
            if (state == SDL_ENABLE) {
slouken@1895
   918
                break;
slouken@1895
   919
            }
slouken@1895
   920
        }
slouken@1895
   921
        break;
slouken@1895
   922
    default:
slouken@1895
   923
        for (i = 0; i < SDL_arraysize(event_list); ++i) {
slouken@1895
   924
            SDL_EventState(event_list[i], state);
slouken@1895
   925
        }
slouken@1895
   926
        break;
slouken@1895
   927
    }
slouken@1895
   928
    return (state);
slouken@1361
   929
#endif /* SDL_EVENTS_DISABLED */
slouken@0
   930
}
slouken@1895
   931
slouken@10595
   932
static void GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version)
slouken@10595
   933
{
slouken@10595
   934
    Uint16 *guid16 = (Uint16 *)guid.data;
slouken@10595
   935
slouken@10595
   936
    /* If the GUID fits the form of BUS 0000 VENDOR 0000 PRODUCT 0000, return the data */
slouken@10595
   937
    if (/* guid16[0] is device bus type */
slouken@10647
   938
        guid16[1] == 0x0000 &&
slouken@10595
   939
        /* guid16[2] is vendor ID */
slouken@10647
   940
        guid16[3] == 0x0000 &&
slouken@10595
   941
        /* guid16[4] is product ID */
slouken@10647
   942
        guid16[5] == 0x0000
slouken@10595
   943
        /* guid16[6] is product version */
slouken@10595
   944
    ) {
slouken@10595
   945
        if (vendor) {
slouken@10595
   946
            *vendor = guid16[2];
slouken@10595
   947
        }
slouken@10595
   948
        if (product) {
slouken@10595
   949
            *product = guid16[4];
slouken@10595
   950
        }
slouken@10595
   951
        if (version) {
slouken@10595
   952
            *version = guid16[6];
slouken@10595
   953
        }
slouken@10595
   954
    } else {
slouken@10595
   955
        if (vendor) {
slouken@10595
   956
            *vendor = 0;
slouken@10595
   957
        }
slouken@10595
   958
        if (product) {
slouken@10595
   959
            *product = 0;
slouken@10595
   960
        }
slouken@10595
   961
        if (version) {
slouken@10595
   962
            *version = 0;
slouken@10595
   963
        }
slouken@10595
   964
    }
slouken@10595
   965
}
slouken@10595
   966
slouken@6693
   967
/* return the guid for this index */
slouken@6738
   968
SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
slouken@6690
   969
{
slouken@7294
   970
    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
slouken@7294
   971
        SDL_JoystickGUID emptyGUID;
slouken@7294
   972
        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
slouken@8920
   973
        SDL_zero(emptyGUID);
slouken@7294
   974
        return emptyGUID;
slouken@7294
   975
    }
slouken@8920
   976
    return SDL_SYS_JoystickGetDeviceGUID(device_index);
slouken@6690
   977
}
slouken@6690
   978
slouken@10595
   979
Uint16 SDL_JoystickGetDeviceVendor(int device_index)
slouken@10595
   980
{
slouken@10595
   981
    Uint16 vendor;
slouken@10595
   982
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
slouken@10595
   983
slouken@10595
   984
    GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
slouken@10595
   985
    return vendor;
slouken@10595
   986
}
slouken@10595
   987
slouken@10595
   988
Uint16 SDL_JoystickGetDeviceProduct(int device_index)
slouken@10595
   989
{
slouken@10595
   990
    Uint16 product;
slouken@10595
   991
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
slouken@10595
   992
slouken@10595
   993
    GetJoystickGUIDInfo(guid, NULL, &product, NULL);
slouken@10595
   994
    return product;
slouken@10595
   995
}
slouken@10595
   996
slouken@10595
   997
Uint16 SDL_JoystickGetDeviceProductVersion(int device_index)
slouken@10595
   998
{
slouken@10595
   999
    Uint16 version;
slouken@10595
  1000
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
slouken@10595
  1001
slouken@10595
  1002
    GetJoystickGUIDInfo(guid, NULL, NULL, &version);
slouken@10595
  1003
    return version;
slouken@10595
  1004
}
slouken@10595
  1005
slouken@6693
  1006
/* return the guid for this opened device */
slouken@6738
  1007
SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
slouken@6690
  1008
{
slouken@7789
  1009
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@7789
  1010
        SDL_JoystickGUID emptyGUID;
slouken@8920
  1011
        SDL_zero(emptyGUID);
slouken@7789
  1012
        return emptyGUID;
slouken@7789
  1013
    }
slouken@8920
  1014
    return SDL_SYS_JoystickGetGUID(joystick);
slouken@6690
  1015
}
slouken@6690
  1016
slouken@10595
  1017
Uint16 SDL_JoystickGetVendor(SDL_Joystick * joystick)
slouken@10595
  1018
{
slouken@10595
  1019
    Uint16 vendor;
slouken@10595
  1020
    SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
slouken@10595
  1021
slouken@10595
  1022
    GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
slouken@10595
  1023
    return vendor;
slouken@10595
  1024
}
slouken@10595
  1025
slouken@10595
  1026
Uint16 SDL_JoystickGetProduct(SDL_Joystick * joystick)
slouken@10595
  1027
{
slouken@10595
  1028
    Uint16 product;
slouken@10595
  1029
    SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
slouken@10595
  1030
slouken@10595
  1031
    GetJoystickGUIDInfo(guid, NULL, &product, NULL);
slouken@10595
  1032
    return product;
slouken@10595
  1033
}
slouken@10595
  1034
slouken@10595
  1035
Uint16 SDL_JoystickGetProductVersion(SDL_Joystick * joystick)
slouken@10595
  1036
{
slouken@10595
  1037
    Uint16 version;
slouken@10595
  1038
    SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
slouken@10595
  1039
slouken@10595
  1040
    GetJoystickGUIDInfo(guid, NULL, NULL, &version);
slouken@10595
  1041
    return version;
slouken@10595
  1042
}
slouken@10595
  1043
slouken@6690
  1044
/* convert the guid to a printable string */
slouken@8920
  1045
void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID)
slouken@6690
  1046
{
slouken@7191
  1047
    static const char k_rgchHexToASCII[] = "0123456789abcdef";
slouken@7191
  1048
    int i;
slouken@6690
  1049
icculus@6748
  1050
    if ((pszGUID == NULL) || (cbGUID <= 0)) {
icculus@6748
  1051
        return;
icculus@6748
  1052
    }
icculus@6748
  1053
slouken@8920
  1054
    for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) {
slouken@7191
  1055
        /* each input byte writes 2 ascii chars, and might write a null byte. */
slouken@7191
  1056
        /* If we don't have room for next input byte, stop */
slouken@7191
  1057
        unsigned char c = guid.data[i];
slouken@6690
  1058
slouken@8920
  1059
        *pszGUID++ = k_rgchHexToASCII[c >> 4];
slouken@8920
  1060
        *pszGUID++ = k_rgchHexToASCII[c & 0x0F];
slouken@7191
  1061
    }
slouken@7191
  1062
    *pszGUID = '\0';
slouken@6690
  1063
}
slouken@6690
  1064
slouken@6690
  1065
slouken@7191
  1066
/*-----------------------------------------------------------------------------
slouken@7191
  1067
 * Purpose: Returns the 4 bit nibble for a hex character
slouken@7191
  1068
 * Input  : c -
slouken@7191
  1069
 * Output : unsigned char
slouken@7191
  1070
 *-----------------------------------------------------------------------------*/
slouken@8920
  1071
static unsigned char nibble(char c)
slouken@6690
  1072
{
slouken@8920
  1073
    if ((c >= '0') && (c <= '9')) {
slouken@7191
  1074
        return (unsigned char)(c - '0');
slouken@7191
  1075
    }
slouken@6690
  1076
slouken@8920
  1077
    if ((c >= 'A') && (c <= 'F')) {
slouken@7191
  1078
        return (unsigned char)(c - 'A' + 0x0a);
slouken@7191
  1079
    }
slouken@6690
  1080
slouken@8920
  1081
    if ((c >= 'a') && (c <= 'f')) {
slouken@7191
  1082
        return (unsigned char)(c - 'a' + 0x0a);
slouken@7191
  1083
    }
slouken@6690
  1084
slouken@7191
  1085
    /* received an invalid character, and no real way to return an error */
slouken@8920
  1086
    /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
slouken@7191
  1087
    return 0;
slouken@6690
  1088
}
slouken@6690
  1089
slouken@6690
  1090
slouken@6690
  1091
/* convert the string version of a joystick guid to the struct */
slouken@6738
  1092
SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
slouken@6690
  1093
{
slouken@7191
  1094
    SDL_JoystickGUID guid;
slouken@7191
  1095
    int maxoutputbytes= sizeof(guid);
slouken@8920
  1096
    size_t len = SDL_strlen(pchGUID);
slouken@7191
  1097
    Uint8 *p;
slouken@7922
  1098
    size_t i;
slouken@6690
  1099
slouken@7191
  1100
    /* Make sure it's even */
slouken@8920
  1101
    len = (len) & ~0x1;
slouken@6690
  1102
slouken@8920
  1103
    SDL_memset(&guid, 0x00, sizeof(guid));
slouken@6690
  1104
slouken@7191
  1105
    p = (Uint8 *)&guid;
slouken@8920
  1106
    for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) {
slouken@8920
  1107
        *p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]);
slouken@7191
  1108
    }
slouken@6690
  1109
slouken@7191
  1110
    return guid;
slouken@6690
  1111
}
slouken@6690
  1112
slouken@6690
  1113
slouken@9884
  1114
/* update the power level for this joystick */
slouken@9884
  1115
void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel)
slouken@9884
  1116
{
slouken@9884
  1117
    joystick->epowerlevel = ePowerLevel;
slouken@9884
  1118
}
slouken@9884
  1119
slouken@9884
  1120
slouken@9884
  1121
/* return its power level */
slouken@9884
  1122
SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick)
slouken@9884
  1123
{
slouken@9884
  1124
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@9884
  1125
        return (SDL_JOYSTICK_POWER_UNKNOWN);
slouken@9884
  1126
    }
slouken@9884
  1127
    return joystick->epowerlevel;
slouken@9884
  1128
}
slouken@9884
  1129
slouken@9884
  1130
slouken@1895
  1131
/* vi: set ts=4 sw=4 expandtab: */