src/joystick/SDL_joystick.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 06 Jun 2013 18:20:06 -0700
changeset 7294 0923de98a63a
parent 7279 f7805b13b485
child 7297 c43b23f0c000
permissions -rw-r--r--
Fixed crash trying to get the GUID of an invalid joystick index
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 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
*/
slouken@1402
    21
#include "SDL_config.h"
slouken@0
    22
slouken@0
    23
/* This is the joystick API for Simple DirectMedia Layer */
slouken@0
    24
slouken@0
    25
#include "SDL_events.h"
slouken@1361
    26
#include "SDL_sysjoystick.h"
icculus@5861
    27
#include "SDL_assert.h"
jorgen@7279
    28
#include "SDL_hints.h"
icculus@5861
    29
slouken@1361
    30
#if !SDL_EVENTS_DISABLED
slouken@1361
    31
#include "../events/SDL_events_c.h"
slouken@0
    32
#endif
slouken@0
    33
slouken@6712
    34
static SDL_Joystick *SDL_joysticks = NULL;
slouken@6712
    35
static SDL_Joystick *SDL_updating_joystick = NULL;
slouken@0
    36
slouken@1895
    37
int
slouken@1895
    38
SDL_JoystickInit(void)
slouken@0
    39
{
slouken@1895
    40
    int status;
slouken@0
    41
slouken@1895
    42
    status = SDL_SYS_JoystickInit();
slouken@1895
    43
    if (status >= 0) {
slouken@6690
    44
      status = 0;
slouken@1895
    45
    }
slouken@1895
    46
    return (status);
slouken@0
    47
}
slouken@0
    48
slouken@0
    49
/*
slouken@0
    50
 * Count the number of joysticks attached to the system
slouken@0
    51
 */
slouken@1895
    52
int
slouken@1895
    53
SDL_NumJoysticks(void)
slouken@0
    54
{
slouken@6690
    55
    return SDL_SYS_NumJoysticks();
slouken@0
    56
}
slouken@0
    57
slouken@0
    58
/*
slouken@0
    59
 * Get the implementation dependent name of a joystick
slouken@0
    60
 */
slouken@1895
    61
const char *
slouken@6690
    62
SDL_JoystickNameForIndex(int device_index)
slouken@0
    63
{
slouken@6690
    64
    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
slouken@6690
    65
        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
slouken@1895
    66
        return (NULL);
slouken@1895
    67
    }
slouken@6707
    68
    return (SDL_SYS_JoystickNameForDeviceIndex(device_index));
slouken@0
    69
}
slouken@0
    70
slouken@0
    71
/*
slouken@0
    72
 * Open a joystick for use - the index passed as an argument refers to
slouken@0
    73
 * the N'th joystick on the system.  This index is the value which will
slouken@0
    74
 * identify this joystick in future joystick events.
slouken@0
    75
 *
slouken@0
    76
 * This function returns a joystick identifier, or NULL if an error occurred.
slouken@0
    77
 */
slouken@1895
    78
SDL_Joystick *
slouken@1895
    79
SDL_JoystickOpen(int device_index)
slouken@0
    80
{
slouken@1895
    81
    SDL_Joystick *joystick;
slouken@7191
    82
    SDL_Joystick *joysticklist;
slouken@7191
    83
    const char *joystickname = NULL;
slouken@0
    84
slouken@6690
    85
    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
slouken@6690
    86
        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
slouken@1895
    87
        return (NULL);
slouken@1895
    88
    }
slouken@0
    89
slouken@7191
    90
    joysticklist = SDL_joysticks;
slouken@7191
    91
    /* If the joystick is already open, return it
slouken@7191
    92
    * it is important that we have a single joystick * for each instance id
slouken@7191
    93
    */
slouken@7191
    94
    while ( joysticklist )
slouken@7191
    95
    {
slouken@7191
    96
        if ( SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id ) {
slouken@7191
    97
                joystick = joysticklist;
slouken@7191
    98
                ++joystick->ref_count;
slouken@7191
    99
                return (joystick);
slouken@7191
   100
        }
slouken@7191
   101
        joysticklist = joysticklist->next;
slouken@1895
   102
    }
slouken@0
   103
slouken@1895
   104
    /* Create and initialize the joystick */
slouken@1895
   105
    joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
icculus@3608
   106
    if (joystick == NULL) {
icculus@3608
   107
        SDL_OutOfMemory();
icculus@3608
   108
        return NULL;
slouken@1895
   109
    }
icculus@3608
   110
icculus@3608
   111
    SDL_memset(joystick, 0, (sizeof *joystick));
slouken@6690
   112
    if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) {
icculus@3608
   113
        SDL_free(joystick);
icculus@3608
   114
        return NULL;
slouken@1895
   115
    }
slouken@6690
   116
slouken@7191
   117
    joystickname = SDL_SYS_JoystickNameForDeviceIndex( device_index );
slouken@7191
   118
    if ( joystickname )
slouken@7191
   119
        joystick->name = SDL_strdup( joystickname );
slouken@7191
   120
    else
slouken@7191
   121
        joystick->name = NULL;
slouken@6690
   122
icculus@3608
   123
    if (joystick->naxes > 0) {
icculus@3608
   124
        joystick->axes = (Sint16 *) SDL_malloc
icculus@3608
   125
            (joystick->naxes * sizeof(Sint16));
icculus@3608
   126
    }
icculus@3608
   127
    if (joystick->nhats > 0) {
icculus@3608
   128
        joystick->hats = (Uint8 *) SDL_malloc
icculus@3608
   129
            (joystick->nhats * sizeof(Uint8));
icculus@3608
   130
    }
icculus@3608
   131
    if (joystick->nballs > 0) {
icculus@3608
   132
        joystick->balls = (struct balldelta *) SDL_malloc
icculus@3608
   133
            (joystick->nballs * sizeof(*joystick->balls));
icculus@3608
   134
    }
icculus@3608
   135
    if (joystick->nbuttons > 0) {
icculus@3608
   136
        joystick->buttons = (Uint8 *) SDL_malloc
icculus@3608
   137
            (joystick->nbuttons * sizeof(Uint8));
icculus@3608
   138
    }
icculus@3608
   139
    if (((joystick->naxes > 0) && !joystick->axes)
icculus@3608
   140
        || ((joystick->nhats > 0) && !joystick->hats)
icculus@3608
   141
        || ((joystick->nballs > 0) && !joystick->balls)
icculus@3608
   142
        || ((joystick->nbuttons > 0) && !joystick->buttons)) {
icculus@3608
   143
        SDL_OutOfMemory();
icculus@3608
   144
        SDL_JoystickClose(joystick);
icculus@3608
   145
        return NULL;
icculus@3608
   146
    }
icculus@3608
   147
    if (joystick->axes) {
icculus@3608
   148
        SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16));
icculus@3608
   149
    }
icculus@3608
   150
    if (joystick->hats) {
icculus@3608
   151
        SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8));
icculus@3608
   152
    }
icculus@3608
   153
    if (joystick->balls) {
icculus@3608
   154
        SDL_memset(joystick->balls, 0,
icculus@3608
   155
            joystick->nballs * sizeof(*joystick->balls));
icculus@3608
   156
    }
icculus@3608
   157
    if (joystick->buttons) {
icculus@3608
   158
        SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
icculus@3608
   159
    }
icculus@3608
   160
icculus@3608
   161
    /* Add joystick to list */
icculus@3608
   162
    ++joystick->ref_count;
slouken@7191
   163
    /* Link the joystick in the list */
slouken@7191
   164
    joystick->next = SDL_joysticks;
slouken@7191
   165
    SDL_joysticks = joystick;
slouken@6690
   166
slouken@7191
   167
    SDL_SYS_JoystickUpdate( joystick );
icculus@3608
   168
slouken@1895
   169
    return (joystick);
slouken@0
   170
}
slouken@0
   171
slouken@2713
   172
slouken@2713
   173
/*
slouken@2713
   174
 * Checks to make sure the joystick is valid.
slouken@2713
   175
 */
slouken@2713
   176
int
slouken@6690
   177
SDL_PrivateJoystickValid(SDL_Joystick * joystick)
slouken@0
   178
{
slouken@1895
   179
    int valid;
slouken@0
   180
slouken@6690
   181
    if ( joystick == NULL ) {
slouken@1895
   182
        SDL_SetError("Joystick hasn't been opened yet");
slouken@1895
   183
        valid = 0;
slouken@1895
   184
    } else {
slouken@1895
   185
        valid = 1;
slouken@1895
   186
    }
slouken@7191
   187
slouken@7191
   188
    if ( joystick && joystick->closed )
slouken@7191
   189
    {
slouken@7191
   190
        valid = 0;
slouken@7191
   191
    }
slouken@7191
   192
slouken@1895
   193
    return valid;
slouken@0
   194
}
slouken@0
   195
slouken@0
   196
/*
slouken@0
   197
 * Get the number of multi-dimensional axis controls on a joystick
slouken@0
   198
 */
slouken@1895
   199
int
slouken@1895
   200
SDL_JoystickNumAxes(SDL_Joystick * joystick)
slouken@0
   201
{
slouken@6690
   202
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   203
        return (-1);
slouken@1895
   204
    }
slouken@1895
   205
    return (joystick->naxes);
slouken@0
   206
}
slouken@0
   207
slouken@0
   208
/*
slouken@0
   209
 * Get the number of hats on a joystick
slouken@0
   210
 */
slouken@1895
   211
int
slouken@1895
   212
SDL_JoystickNumHats(SDL_Joystick * joystick)
slouken@0
   213
{
slouken@6690
   214
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   215
        return (-1);
slouken@1895
   216
    }
slouken@1895
   217
    return (joystick->nhats);
slouken@0
   218
}
slouken@0
   219
slouken@0
   220
/*
slouken@0
   221
 * Get the number of trackballs on a joystick
slouken@0
   222
 */
slouken@1895
   223
int
slouken@1895
   224
SDL_JoystickNumBalls(SDL_Joystick * joystick)
slouken@0
   225
{
slouken@6690
   226
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   227
        return (-1);
slouken@1895
   228
    }
slouken@1895
   229
    return (joystick->nballs);
slouken@0
   230
}
slouken@0
   231
slouken@0
   232
/*
slouken@0
   233
 * Get the number of buttons on a joystick
slouken@0
   234
 */
slouken@1895
   235
int
slouken@1895
   236
SDL_JoystickNumButtons(SDL_Joystick * joystick)
slouken@0
   237
{
slouken@6690
   238
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   239
        return (-1);
slouken@1895
   240
    }
slouken@1895
   241
    return (joystick->nbuttons);
slouken@0
   242
}
slouken@0
   243
slouken@0
   244
/*
slouken@0
   245
 * Get the current state of an axis control on a joystick
slouken@0
   246
 */
slouken@1895
   247
Sint16
slouken@1895
   248
SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
slouken@0
   249
{
slouken@1895
   250
    Sint16 state;
slouken@0
   251
slouken@6690
   252
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   253
        return (0);
slouken@1895
   254
    }
slouken@1895
   255
    if (axis < joystick->naxes) {
slouken@1895
   256
        state = joystick->axes[axis];
slouken@1895
   257
    } else {
slouken@1895
   258
        SDL_SetError("Joystick only has %d axes", joystick->naxes);
slouken@1895
   259
        state = 0;
slouken@1895
   260
    }
slouken@1895
   261
    return (state);
slouken@0
   262
}
slouken@0
   263
slouken@0
   264
/*
slouken@0
   265
 * Get the current state of a hat on a joystick
slouken@0
   266
 */
slouken@1895
   267
Uint8
slouken@1895
   268
SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
slouken@0
   269
{
slouken@1895
   270
    Uint8 state;
slouken@0
   271
slouken@6690
   272
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   273
        return (0);
slouken@1895
   274
    }
slouken@1895
   275
    if (hat < joystick->nhats) {
slouken@1895
   276
        state = joystick->hats[hat];
slouken@1895
   277
    } else {
slouken@1895
   278
        SDL_SetError("Joystick only has %d hats", joystick->nhats);
slouken@1895
   279
        state = 0;
slouken@1895
   280
    }
slouken@1895
   281
    return (state);
slouken@0
   282
}
slouken@0
   283
slouken@0
   284
/*
slouken@0
   285
 * Get the ball axis change since the last poll
slouken@0
   286
 */
slouken@1895
   287
int
slouken@1895
   288
SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
slouken@0
   289
{
slouken@1895
   290
    int retval;
slouken@0
   291
slouken@6690
   292
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   293
        return (-1);
slouken@1895
   294
    }
slouken@0
   295
slouken@1895
   296
    retval = 0;
slouken@1895
   297
    if (ball < joystick->nballs) {
slouken@1895
   298
        if (dx) {
slouken@1895
   299
            *dx = joystick->balls[ball].dx;
slouken@1895
   300
        }
slouken@1895
   301
        if (dy) {
slouken@1895
   302
            *dy = joystick->balls[ball].dy;
slouken@1895
   303
        }
slouken@1895
   304
        joystick->balls[ball].dx = 0;
slouken@1895
   305
        joystick->balls[ball].dy = 0;
slouken@1895
   306
    } else {
icculus@7037
   307
        return SDL_SetError("Joystick only has %d balls", joystick->nballs);
slouken@1895
   308
    }
slouken@1895
   309
    return (retval);
slouken@0
   310
}
slouken@0
   311
slouken@0
   312
/*
slouken@0
   313
 * Get the current state of a button on a joystick
slouken@0
   314
 */
slouken@1895
   315
Uint8
slouken@1895
   316
SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
slouken@0
   317
{
slouken@1895
   318
    Uint8 state;
slouken@0
   319
slouken@6690
   320
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   321
        return (0);
slouken@1895
   322
    }
slouken@1895
   323
    if (button < joystick->nbuttons) {
slouken@1895
   324
        state = joystick->buttons[button];
slouken@1895
   325
    } else {
slouken@1895
   326
        SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
slouken@1895
   327
        state = 0;
slouken@1895
   328
    }
slouken@1895
   329
    return (state);
slouken@0
   330
}
slouken@0
   331
slouken@0
   332
/*
slouken@6690
   333
 * Return if the joystick in question is currently attached to the system,
slouken@6690
   334
 *  \return 0 if not plugged in, 1 if still present.
slouken@6690
   335
 */
slouken@6707
   336
SDL_bool
slouken@6707
   337
SDL_JoystickGetAttached(SDL_Joystick * joystick)
slouken@6690
   338
{
slouken@7191
   339
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6707
   340
        return SDL_FALSE;
slouken@6690
   341
    }
slouken@6690
   342
slouken@7191
   343
    return SDL_SYS_JoystickAttached(joystick);
slouken@6690
   344
}
slouken@6690
   345
slouken@6690
   346
/*
slouken@6690
   347
 * Get the instance id for this opened joystick
slouken@6690
   348
 */
slouken@7191
   349
SDL_JoystickID
slouken@6707
   350
SDL_JoystickInstanceID(SDL_Joystick * joystick)
slouken@6690
   351
{
slouken@7191
   352
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6690
   353
        return (-1);
slouken@6690
   354
    }
slouken@6690
   355
slouken@7191
   356
    return (joystick->instance_id);
slouken@6690
   357
}
slouken@6690
   358
slouken@6690
   359
/*
slouken@6690
   360
 * Get the friendly name of this joystick
slouken@6690
   361
 */
slouken@6690
   362
const char *
slouken@6690
   363
SDL_JoystickName(SDL_Joystick * joystick)
slouken@6690
   364
{
slouken@6690
   365
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6690
   366
        return (NULL);
slouken@6690
   367
    }
slouken@7191
   368
slouken@6690
   369
    return (joystick->name);
slouken@6690
   370
}
slouken@6690
   371
slouken@6690
   372
/*
slouken@0
   373
 * Close a joystick previously opened with SDL_JoystickOpen()
slouken@0
   374
 */
slouken@1895
   375
void
slouken@1895
   376
SDL_JoystickClose(SDL_Joystick * joystick)
slouken@0
   377
{
slouken@7191
   378
    SDL_Joystick *joysticklist;
slouken@7191
   379
    SDL_Joystick *joysticklistprev;
slouken@0
   380
slouken@6690
   381
    if (!joystick) {
slouken@1895
   382
        return;
slouken@1895
   383
    }
slouken@0
   384
slouken@1895
   385
    /* First decrement ref count */
slouken@1895
   386
    if (--joystick->ref_count > 0) {
slouken@1895
   387
        return;
slouken@1895
   388
    }
slouken@0
   389
slouken@6712
   390
    if (joystick == SDL_updating_joystick) {
slouken@6712
   391
        return;
slouken@6712
   392
    }
slouken@6712
   393
slouken@1895
   394
    SDL_SYS_JoystickClose(joystick);
slouken@0
   395
slouken@7191
   396
    joysticklist = SDL_joysticks;
slouken@7191
   397
    joysticklistprev = NULL;
slouken@7191
   398
    while ( joysticklist )
slouken@7191
   399
    {
slouken@7191
   400
        if (joystick == joysticklist)
slouken@7191
   401
        {
slouken@7191
   402
            if ( joysticklistprev )
slouken@7191
   403
            {
slouken@7191
   404
                /* unlink this entry */
slouken@7191
   405
                joysticklistprev->next = joysticklist->next;
slouken@7191
   406
            }
slouken@7191
   407
            else
slouken@7191
   408
            {
slouken@7191
   409
                SDL_joysticks = joystick->next;
slouken@7191
   410
            }
slouken@7191
   411
slouken@7191
   412
            break;
slouken@7191
   413
        }
slouken@7191
   414
        joysticklistprev = joysticklist;
slouken@7191
   415
        joysticklist = joysticklist->next;
slouken@7191
   416
    }
slouken@7191
   417
slouken@7191
   418
    if (joystick->name)
slouken@7191
   419
        SDL_free(joystick->name);
slouken@0
   420
slouken@1895
   421
    /* Free the data associated with this joystick */
slouken@1895
   422
    if (joystick->axes) {
slouken@1895
   423
        SDL_free(joystick->axes);
slouken@1895
   424
    }
slouken@1895
   425
    if (joystick->hats) {
slouken@1895
   426
        SDL_free(joystick->hats);
slouken@1895
   427
    }
slouken@1895
   428
    if (joystick->balls) {
slouken@1895
   429
        SDL_free(joystick->balls);
slouken@1895
   430
    }
slouken@1895
   431
    if (joystick->buttons) {
slouken@1895
   432
        SDL_free(joystick->buttons);
slouken@1895
   433
    }
slouken@1895
   434
    SDL_free(joystick);
slouken@0
   435
}
slouken@0
   436
slouken@1895
   437
void
slouken@1895
   438
SDL_JoystickQuit(void)
slouken@0
   439
{
slouken@6712
   440
    /* Make sure we're not getting called in the middle of updating joysticks */
slouken@6712
   441
    SDL_assert(!SDL_updating_joystick);
slouken@6712
   442
slouken@1895
   443
    /* Stop the event polling */
slouken@7191
   444
    while ( SDL_joysticks )
slouken@7191
   445
    {
slouken@7191
   446
        SDL_joysticks->ref_count = 1;
slouken@6690
   447
        SDL_JoystickClose(SDL_joysticks);
slouken@7191
   448
    }
icculus@5856
   449
slouken@1895
   450
    /* Quit the joystick setup */
slouken@1895
   451
    SDL_SYS_JoystickQuit();
slouken@0
   452
}
slouken@0
   453
slouken@0
   454
jorgen@7279
   455
static SDL_bool
jorgen@7279
   456
SDL_PrivateJoystickShouldIgnoreEvent()
jorgen@7279
   457
{
jorgen@7279
   458
    const char *hint;
jorgen@7279
   459
    if (SDL_GetKeyboardFocus() != NULL) {
jorgen@7279
   460
        return SDL_FALSE;
jorgen@7279
   461
    }
jorgen@7279
   462
jorgen@7279
   463
    hint = SDL_GetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS);
jorgen@7279
   464
    if (hint && *hint == '1') {
jorgen@7279
   465
        return SDL_FALSE;
jorgen@7279
   466
    }
jorgen@7279
   467
jorgen@7279
   468
    return SDL_TRUE;
jorgen@7279
   469
}
jorgen@7279
   470
slouken@0
   471
/* These are global for SDL_sysjoystick.c and SDL_events.c */
slouken@0
   472
slouken@1895
   473
int
slouken@1895
   474
SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
slouken@0
   475
{
slouken@1895
   476
    int posted;
slouken@0
   477
slouken@6145
   478
    /* Make sure we're not getting garbage events */
slouken@6145
   479
    if (axis >= joystick->naxes) {
slouken@6145
   480
        return 0;
slouken@6145
   481
    }
slouken@6145
   482
slouken@1895
   483
    /* Update internal joystick state */
slouken@6735
   484
    if (value == joystick->axes[axis]) {
slouken@6735
   485
        return 0;
slouken@6735
   486
    }
slouken@1895
   487
    joystick->axes[axis] = value;
slouken@0
   488
jorgen@7279
   489
    /* We ignore events if we don't have keyboard focus, except for centering
jorgen@7279
   490
     * events.
jorgen@7279
   491
     */
jorgen@7279
   492
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
jorgen@7279
   493
        if (!(joystick->closed && joystick->uncentered)) {
jorgen@7279
   494
            return 0;
jorgen@7279
   495
        }
jorgen@7279
   496
    }
jorgen@7279
   497
slouken@1895
   498
    /* Post the event, if desired */
slouken@1895
   499
    posted = 0;
slouken@1361
   500
#if !SDL_EVENTS_DISABLED
slouken@4429
   501
    if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
slouken@1895
   502
        SDL_Event event;
slouken@1895
   503
        event.type = SDL_JOYAXISMOTION;
slouken@6690
   504
        event.jaxis.which = joystick->instance_id;
slouken@1895
   505
        event.jaxis.axis = axis;
slouken@1895
   506
        event.jaxis.value = value;
slouken@6690
   507
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   508
    }
slouken@1361
   509
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   510
    return (posted);
slouken@0
   511
}
slouken@0
   512
slouken@1895
   513
int
slouken@1895
   514
SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
slouken@0
   515
{
slouken@1895
   516
    int posted;
slouken@0
   517
slouken@6145
   518
    /* Make sure we're not getting garbage events */
slouken@6145
   519
    if (hat >= joystick->nhats) {
slouken@6145
   520
        return 0;
slouken@6145
   521
    }
slouken@6145
   522
slouken@1895
   523
    /* Update internal joystick state */
slouken@1895
   524
    joystick->hats[hat] = value;
slouken@0
   525
jorgen@7279
   526
    /* We ignore events if we don't have keyboard focus, except for centering
jorgen@7279
   527
     * events.
jorgen@7279
   528
     */
jorgen@7279
   529
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
jorgen@7279
   530
        if (!(joystick->closed && joystick->uncentered)) {
jorgen@7279
   531
            return 0;
jorgen@7279
   532
        }
jorgen@7279
   533
    }
jorgen@7279
   534
jorgen@7279
   535
slouken@1895
   536
    /* Post the event, if desired */
slouken@1895
   537
    posted = 0;
slouken@1361
   538
#if !SDL_EVENTS_DISABLED
slouken@4429
   539
    if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
slouken@1895
   540
        SDL_Event event;
slouken@1895
   541
        event.jhat.type = SDL_JOYHATMOTION;
slouken@6690
   542
        event.jhat.which = joystick->instance_id;
slouken@1895
   543
        event.jhat.hat = hat;
slouken@1895
   544
        event.jhat.value = value;
slouken@6690
   545
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   546
    }
slouken@1361
   547
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   548
    return (posted);
slouken@0
   549
}
slouken@0
   550
slouken@1895
   551
int
slouken@1895
   552
SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
slouken@1895
   553
                        Sint16 xrel, Sint16 yrel)
slouken@0
   554
{
slouken@1895
   555
    int posted;
slouken@0
   556
slouken@6145
   557
    /* Make sure we're not getting garbage events */
slouken@6145
   558
    if (ball >= joystick->nballs) {
slouken@6145
   559
        return 0;
slouken@6145
   560
    }
slouken@6145
   561
jorgen@7279
   562
    /* We ignore events if we don't have keyboard focus. */
jorgen@7279
   563
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
jorgen@7279
   564
        return 0;
jorgen@7279
   565
    }
jorgen@7279
   566
slouken@1895
   567
    /* Update internal mouse state */
slouken@1895
   568
    joystick->balls[ball].dx += xrel;
slouken@1895
   569
    joystick->balls[ball].dy += yrel;
slouken@0
   570
slouken@1895
   571
    /* Post the event, if desired */
slouken@1895
   572
    posted = 0;
slouken@1361
   573
#if !SDL_EVENTS_DISABLED
slouken@4429
   574
    if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
slouken@1895
   575
        SDL_Event event;
slouken@1895
   576
        event.jball.type = SDL_JOYBALLMOTION;
slouken@6690
   577
        event.jball.which = joystick->instance_id;
slouken@1895
   578
        event.jball.ball = ball;
slouken@1895
   579
        event.jball.xrel = xrel;
slouken@1895
   580
        event.jball.yrel = yrel;
slouken@6690
   581
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   582
    }
slouken@1361
   583
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   584
    return (posted);
slouken@0
   585
}
slouken@0
   586
slouken@1895
   587
int
slouken@1895
   588
SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
slouken@0
   589
{
slouken@1895
   590
    int posted;
slouken@1361
   591
#if !SDL_EVENTS_DISABLED
slouken@1895
   592
    SDL_Event event;
slouken@0
   593
slouken@1895
   594
    switch (state) {
slouken@1895
   595
    case SDL_PRESSED:
slouken@1895
   596
        event.type = SDL_JOYBUTTONDOWN;
slouken@1895
   597
        break;
slouken@1895
   598
    case SDL_RELEASED:
slouken@1895
   599
        event.type = SDL_JOYBUTTONUP;
slouken@1895
   600
        break;
slouken@1895
   601
    default:
slouken@1895
   602
        /* Invalid state -- bail */
slouken@1895
   603
        return (0);
slouken@1895
   604
    }
slouken@1361
   605
#endif /* !SDL_EVENTS_DISABLED */
slouken@0
   606
slouken@6145
   607
    /* Make sure we're not getting garbage events */
slouken@6145
   608
    if (button >= joystick->nbuttons) {
slouken@6145
   609
        return 0;
slouken@6145
   610
    }
slouken@6145
   611
jorgen@7279
   612
    /* We ignore events if we don't have keyboard focus, except for button
jorgen@7279
   613
     * release. */
jorgen@7279
   614
    if (SDL_PrivateJoystickShouldIgnoreEvent() && event.type == SDL_JOYBUTTONDOWN) {
jorgen@7279
   615
        return 0;
jorgen@7279
   616
    }
jorgen@7279
   617
slouken@1895
   618
    /* Update internal joystick state */
slouken@1895
   619
    joystick->buttons[button] = state;
slouken@0
   620
slouken@1895
   621
    /* Post the event, if desired */
slouken@1895
   622
    posted = 0;
slouken@1361
   623
#if !SDL_EVENTS_DISABLED
slouken@4429
   624
    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@6690
   625
        event.jbutton.which = joystick->instance_id;
slouken@1895
   626
        event.jbutton.button = button;
slouken@1895
   627
        event.jbutton.state = state;
slouken@6690
   628
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   629
    }
slouken@1361
   630
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   631
    return (posted);
slouken@0
   632
}
slouken@0
   633
slouken@1895
   634
void
slouken@1895
   635
SDL_JoystickUpdate(void)
slouken@0
   636
{
slouken@7191
   637
    SDL_Joystick *joystick;
slouken@7191
   638
slouken@7191
   639
    joystick = SDL_joysticks;
slouken@7191
   640
    while ( joystick )
slouken@7191
   641
    {
slouken@7191
   642
        SDL_Joystick *joysticknext;
slouken@7191
   643
        /* save off the next pointer, the Update call may cause a joystick removed event
slouken@7191
   644
         * and cause our joystick pointer to be freed
slouken@7191
   645
         */
slouken@7191
   646
        joysticknext = joystick->next;
slouken@0
   647
slouken@6712
   648
        SDL_updating_joystick = joystick;
slouken@6712
   649
slouken@6690
   650
        SDL_SYS_JoystickUpdate( joystick );
slouken@6690
   651
slouken@7191
   652
        if ( joystick->closed && joystick->uncentered )
slouken@7191
   653
        {
slouken@7191
   654
            int i;
slouken@6690
   655
slouken@6712
   656
            /* Tell the app that everything is centered/unpressed...  */
slouken@6690
   657
            for (i = 0; i < joystick->naxes; i++)
slouken@6690
   658
                SDL_PrivateJoystickAxis(joystick, i, 0);
slouken@6690
   659
slouken@6690
   660
            for (i = 0; i < joystick->nbuttons; i++)
slouken@6690
   661
                SDL_PrivateJoystickButton(joystick, i, 0);
slouken@6690
   662
slouken@6690
   663
            for (i = 0; i < joystick->nhats; i++)
slouken@6690
   664
                SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
slouken@6712
   665
jorgen@7279
   666
            joystick->uncentered = 0;
slouken@7191
   667
        }
slouken@6690
   668
slouken@6712
   669
        SDL_updating_joystick = NULL;
slouken@6712
   670
slouken@6712
   671
        /* If the joystick was closed while updating, free it here */
slouken@6712
   672
        if ( joystick->ref_count <= 0 ) {
slouken@6712
   673
            SDL_JoystickClose(joystick);
slouken@6712
   674
        }
slouken@6712
   675
slouken@7191
   676
        joystick = joysticknext;
slouken@7191
   677
    }
slouken@6690
   678
slouken@7191
   679
    /* this needs to happen AFTER walking the joystick list above, so that any
slouken@7191
   680
       dangling hardware data from removed devices can be free'd
slouken@7191
   681
     */
slouken@7191
   682
    SDL_SYS_JoystickDetect();
slouken@0
   683
}
slouken@0
   684
slouken@1895
   685
int
slouken@1895
   686
SDL_JoystickEventState(int state)
slouken@0
   687
{
slouken@1361
   688
#if SDL_EVENTS_DISABLED
slouken@6753
   689
    return SDL_DISABLE;
slouken@0
   690
#else
slouken@4429
   691
    const Uint32 event_list[] = {
slouken@1895
   692
        SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
slouken@6690
   693
        SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
slouken@1895
   694
    };
slouken@1895
   695
    unsigned int i;
slouken@0
   696
slouken@1895
   697
    switch (state) {
slouken@1895
   698
    case SDL_QUERY:
slouken@6753
   699
        state = SDL_DISABLE;
slouken@1895
   700
        for (i = 0; i < SDL_arraysize(event_list); ++i) {
slouken@1895
   701
            state = SDL_EventState(event_list[i], SDL_QUERY);
slouken@1895
   702
            if (state == SDL_ENABLE) {
slouken@1895
   703
                break;
slouken@1895
   704
            }
slouken@1895
   705
        }
slouken@1895
   706
        break;
slouken@1895
   707
    default:
slouken@1895
   708
        for (i = 0; i < SDL_arraysize(event_list); ++i) {
slouken@1895
   709
            SDL_EventState(event_list[i], state);
slouken@1895
   710
        }
slouken@1895
   711
        break;
slouken@1895
   712
    }
slouken@1895
   713
    return (state);
slouken@1361
   714
#endif /* SDL_EVENTS_DISABLED */
slouken@0
   715
}
slouken@1895
   716
slouken@6690
   717
/* return 1 if you want to run the joystick update loop this frame, used by hotplug support */
slouken@7191
   718
SDL_bool
slouken@6690
   719
SDL_PrivateJoystickNeedsPolling()
slouken@6690
   720
{
slouken@7191
   721
    if (SDL_joysticks != NULL) {
slouken@7191
   722
        return SDL_TRUE;
slouken@7191
   723
    } else {
slouken@7191
   724
        return SDL_SYS_JoystickNeedsPolling();
slouken@7191
   725
    }
slouken@6690
   726
}
slouken@6690
   727
slouken@6690
   728
slouken@6693
   729
/* return the guid for this index */
slouken@6738
   730
SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
slouken@6690
   731
{
slouken@7294
   732
    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
slouken@7294
   733
        SDL_JoystickGUID emptyGUID;
slouken@7294
   734
        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
slouken@7294
   735
        SDL_zero( emptyGUID );
slouken@7294
   736
        return emptyGUID;
slouken@7294
   737
    }
slouken@7191
   738
    return SDL_SYS_JoystickGetDeviceGUID( device_index );
slouken@6690
   739
}
slouken@6690
   740
slouken@6693
   741
/* return the guid for this opened device */
slouken@6738
   742
SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
slouken@6690
   743
{
slouken@7191
   744
    return SDL_SYS_JoystickGetGUID( joystick );
slouken@6690
   745
}
slouken@6690
   746
slouken@6690
   747
/* convert the guid to a printable string */
slouken@6738
   748
void SDL_JoystickGetGUIDString( SDL_JoystickGUID guid, char *pszGUID, int cbGUID )
slouken@6690
   749
{
slouken@7191
   750
    static const char k_rgchHexToASCII[] = "0123456789abcdef";
slouken@7191
   751
    int i;
slouken@6690
   752
icculus@6748
   753
    if ((pszGUID == NULL) || (cbGUID <= 0)) {
icculus@6748
   754
        return;
icculus@6748
   755
    }
icculus@6748
   756
slouken@7191
   757
    for ( i = 0; i < sizeof(guid.data) && i < (cbGUID-1); i++ )
slouken@7191
   758
    {
slouken@7191
   759
        /* each input byte writes 2 ascii chars, and might write a null byte. */
slouken@7191
   760
        /* If we don't have room for next input byte, stop */
slouken@7191
   761
        unsigned char c = guid.data[i];
slouken@6690
   762
slouken@7191
   763
        *pszGUID++ = k_rgchHexToASCII[ c >> 4 ];
slouken@7191
   764
        *pszGUID++ = k_rgchHexToASCII[ c & 0x0F ];
slouken@7191
   765
    }
slouken@7191
   766
    *pszGUID = '\0';
slouken@6690
   767
}
slouken@6690
   768
slouken@6690
   769
slouken@7191
   770
/*-----------------------------------------------------------------------------
slouken@7191
   771
 * Purpose: Returns the 4 bit nibble for a hex character
slouken@7191
   772
 * Input  : c -
slouken@7191
   773
 * Output : unsigned char
slouken@7191
   774
 *-----------------------------------------------------------------------------*/
slouken@6690
   775
static unsigned char nibble( char c )
slouken@6690
   776
{
slouken@7191
   777
    if ( ( c >= '0' ) &&
slouken@7191
   778
        ( c <= '9' ) )
slouken@7191
   779
    {
slouken@7191
   780
        return (unsigned char)(c - '0');
slouken@7191
   781
    }
slouken@6690
   782
slouken@7191
   783
    if ( ( c >= 'A' ) &&
slouken@7191
   784
        ( c <= 'F' ) )
slouken@7191
   785
    {
slouken@7191
   786
        return (unsigned char)(c - 'A' + 0x0a);
slouken@7191
   787
    }
slouken@6690
   788
slouken@7191
   789
    if ( ( c >= 'a' ) &&
slouken@7191
   790
        ( c <= 'f' ) )
slouken@7191
   791
    {
slouken@7191
   792
        return (unsigned char)(c - 'a' + 0x0a);
slouken@7191
   793
    }
slouken@6690
   794
slouken@7191
   795
    /* received an invalid character, and no real way to return an error */
slouken@7191
   796
    /* AssertMsg1( false, "Q_nibble invalid hex character '%c' ", c ); */
slouken@7191
   797
    return 0;
slouken@6690
   798
}
slouken@6690
   799
slouken@6690
   800
slouken@6690
   801
/* convert the string version of a joystick guid to the struct */
slouken@6738
   802
SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
slouken@6690
   803
{
slouken@7191
   804
    SDL_JoystickGUID guid;
slouken@7191
   805
    int maxoutputbytes= sizeof(guid);
slouken@7191
   806
    int len = SDL_strlen( pchGUID );
slouken@7191
   807
    Uint8 *p;
slouken@7191
   808
    int i;
slouken@6690
   809
slouken@7191
   810
    /* Make sure it's even */
slouken@7191
   811
    len = ( len ) & ~0x1;
slouken@6690
   812
slouken@7191
   813
    SDL_memset( &guid, 0x00, sizeof(guid) );
slouken@6690
   814
slouken@7191
   815
    p = (Uint8 *)&guid;
slouken@7191
   816
    for ( i = 0;
slouken@7191
   817
        ( i < len ) && ( ( p - (Uint8 *)&guid ) < maxoutputbytes );
slouken@7191
   818
        i+=2, p++ )
slouken@7191
   819
    {
slouken@7191
   820
        *p = ( nibble( pchGUID[i] ) << 4 ) | nibble( pchGUID[i+1] );
slouken@7191
   821
    }
slouken@6690
   822
slouken@7191
   823
    return guid;
slouken@6690
   824
}
slouken@6690
   825
slouken@6690
   826
slouken@1895
   827
/* vi: set ts=4 sw=4 expandtab: */