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