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