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