src/joystick/android/SDL_sysjoystick.c
author Gabriel Jacobo <gabomdq@gmail.com>
Sat, 23 Nov 2013 09:47:25 -0300
changeset 8024 ffbdb99af7bd
parent 8013 109299fe73ad
child 8025 a867f1891d2a
permissions -rw-r--r--
[Android] Fixes #2264, handle joystick open/closed state properly
gabomdq@7041
     1
/*
gabomdq@7041
     2
  Simple DirectMedia Layer
gabomdq@7041
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
gabomdq@7041
     4
gabomdq@7041
     5
  This software is provided 'as-is', without any express or implied
gabomdq@7041
     6
  warranty.  In no event will the authors be held liable for any damages
gabomdq@7041
     7
  arising from the use of this software.
gabomdq@7041
     8
gabomdq@7041
     9
  Permission is granted to anyone to use this software for any purpose,
gabomdq@7041
    10
  including commercial applications, and to alter it and redistribute it
gabomdq@7041
    11
  freely, subject to the following restrictions:
gabomdq@7041
    12
gabomdq@7041
    13
  1. The origin of this software must not be misrepresented; you must not
gabomdq@7041
    14
     claim that you wrote the original software. If you use this software
gabomdq@7041
    15
     in a product, an acknowledgment in the product documentation would be
gabomdq@7041
    16
     appreciated but is not required.
gabomdq@7041
    17
  2. Altered source versions must be plainly marked as such, and must not be
gabomdq@7041
    18
     misrepresented as being the original software.
gabomdq@7041
    19
  3. This notice may not be removed or altered from any source distribution.
gabomdq@7041
    20
*/
gabomdq@7041
    21
gabomdq@7041
    22
#include "SDL_config.h"
gabomdq@7041
    23
gabomdq@7041
    24
#ifdef SDL_JOYSTICK_ANDROID
gabomdq@7041
    25
gabomdq@7041
    26
/* This is the system specific header for the SDL joystick API */
gabomdq@7041
    27
#include <stdio.h>              /* For the definition of NULL */
gabomdq@7041
    28
gabomdq@7041
    29
#include "SDL_error.h"
gabomdq@7041
    30
#include "SDL_events.h"
gabomdq@7041
    31
#include "SDL_joystick.h"
gabomdq@7907
    32
#include "SDL_hints.h"
gabomdq@7944
    33
#include "SDL_assert.h"
philipp@8008
    34
#include "SDL_log.h"
gabomdq@7041
    35
#include "../SDL_sysjoystick.h"
gabomdq@7041
    36
#include "../SDL_joystick_c.h"
gabomdq@7041
    37
#include "../../core/android/SDL_android.h"
philipp@8008
    38
gabomdq@7944
    39
#include "android/keycodes.h"
gabomdq@7944
    40
gabomdq@7944
    41
/* As of platform android-14, android/keycodes.h is missing these defines */
gabomdq@7944
    42
#ifndef AKEYCODE_BUTTON_1
gabomdq@7944
    43
#define AKEYCODE_BUTTON_1 188
gabomdq@7944
    44
#define AKEYCODE_BUTTON_2 189
gabomdq@7944
    45
#define AKEYCODE_BUTTON_3 190
gabomdq@7944
    46
#define AKEYCODE_BUTTON_4 191
gabomdq@7944
    47
#define AKEYCODE_BUTTON_5 192
gabomdq@7944
    48
#define AKEYCODE_BUTTON_6 193
gabomdq@7944
    49
#define AKEYCODE_BUTTON_7 194
gabomdq@7944
    50
#define AKEYCODE_BUTTON_8 195
gabomdq@7944
    51
#define AKEYCODE_BUTTON_9 196
gabomdq@7944
    52
#define AKEYCODE_BUTTON_10 197
gabomdq@7944
    53
#define AKEYCODE_BUTTON_11 198
gabomdq@7944
    54
#define AKEYCODE_BUTTON_12 199
gabomdq@7944
    55
#define AKEYCODE_BUTTON_13 200
gabomdq@7944
    56
#define AKEYCODE_BUTTON_14 201
gabomdq@7944
    57
#define AKEYCODE_BUTTON_15 202
gabomdq@7944
    58
#define AKEYCODE_BUTTON_16 203
gabomdq@7944
    59
#endif
gabomdq@7041
    60
gabomdq@7907
    61
#define ANDROID_ACCELEROMETER_INDEX (SYS_numjoysticks - 1)
gabomdq@7907
    62
#define ANDROID_ACCELEROMETER_NAME "Android Accelerometer"
gabomdq@7944
    63
#define ANDROID_MAX_NBUTTONS 36
gabomdq@7907
    64
gabomdq@7907
    65
static SDL_Joystick **SYS_Joysticks;
gabomdq@7907
    66
static char **SYS_JoystickNames;
gabomdq@7907
    67
static int SYS_numjoysticks;
gabomdq@7907
    68
static SDL_bool SYS_accelAsJoy;
gabomdq@7907
    69
gabomdq@7907
    70
/* Function to convert Android keyCodes into SDL ones.
gabomdq@7907
    71
 * This code manipulation is done to get a sequential list of codes.
gabomdq@7944
    72
 * FIXME: This is only suited for the case where we use a fixed number of buttons determined by ANDROID_MAX_NBUTTONS
gabomdq@7907
    73
 */
philipp@7929
    74
static int
gabomdq@7907
    75
keycode_to_SDL(int keycode)
gabomdq@7907
    76
{
gabomdq@7944
    77
    /* FIXME: If this function gets too unwiedly in the future, replace with a lookup table */
gabomdq@7944
    78
    int button = 0;
gabomdq@7944
    79
    switch(keycode) 
gabomdq@7944
    80
    {
gabomdq@7944
    81
        /* D-Pad key codes (API 1), these get mapped to 0...4 */
gabomdq@7944
    82
        case AKEYCODE_DPAD_UP:
gabomdq@7944
    83
        case AKEYCODE_DPAD_DOWN:
gabomdq@7944
    84
        case AKEYCODE_DPAD_LEFT:
gabomdq@7944
    85
        case AKEYCODE_DPAD_RIGHT:
gabomdq@7944
    86
        case AKEYCODE_DPAD_CENTER:
gabomdq@7944
    87
            button = keycode - AKEYCODE_DPAD_UP;
gabomdq@7944
    88
            break;
gabomdq@7944
    89
        
gabomdq@7944
    90
        /* Some gamepad buttons (API 9), these get mapped to 5...19*/
gabomdq@7944
    91
        case AKEYCODE_BUTTON_A:
gabomdq@7944
    92
        case AKEYCODE_BUTTON_B:
gabomdq@7944
    93
        case AKEYCODE_BUTTON_C:
gabomdq@7944
    94
        case AKEYCODE_BUTTON_X:
gabomdq@7944
    95
        case AKEYCODE_BUTTON_Y:
gabomdq@7944
    96
        case AKEYCODE_BUTTON_Z:
gabomdq@7944
    97
        case AKEYCODE_BUTTON_L1:
gabomdq@7944
    98
        case AKEYCODE_BUTTON_L2:
gabomdq@7944
    99
        case AKEYCODE_BUTTON_R1:
gabomdq@7944
   100
        case AKEYCODE_BUTTON_R2:
gabomdq@7944
   101
        case AKEYCODE_BUTTON_THUMBL:
gabomdq@7944
   102
        case AKEYCODE_BUTTON_THUMBR:
gabomdq@7944
   103
        case AKEYCODE_BUTTON_START:
gabomdq@7944
   104
        case AKEYCODE_BUTTON_SELECT:
gabomdq@7944
   105
        case AKEYCODE_BUTTON_MODE:
gabomdq@7944
   106
            button = keycode - AKEYCODE_BUTTON_A + 5;
gabomdq@7944
   107
            break;
gabomdq@7944
   108
            
gabomdq@7944
   109
        
gabomdq@7944
   110
        /* More gamepad buttons (API 12), these get mapped to 20...35*/
gabomdq@7944
   111
        case AKEYCODE_BUTTON_1:
gabomdq@7944
   112
        case AKEYCODE_BUTTON_2:
gabomdq@7944
   113
        case AKEYCODE_BUTTON_3:
gabomdq@7944
   114
        case AKEYCODE_BUTTON_4:
gabomdq@7944
   115
        case AKEYCODE_BUTTON_5:
gabomdq@7944
   116
        case AKEYCODE_BUTTON_6:
gabomdq@7944
   117
        case AKEYCODE_BUTTON_7:
gabomdq@7944
   118
        case AKEYCODE_BUTTON_8:
gabomdq@7944
   119
        case AKEYCODE_BUTTON_9:
gabomdq@7944
   120
        case AKEYCODE_BUTTON_10:
gabomdq@7944
   121
        case AKEYCODE_BUTTON_11:
gabomdq@7944
   122
        case AKEYCODE_BUTTON_12:
gabomdq@7944
   123
        case AKEYCODE_BUTTON_13:
gabomdq@7944
   124
        case AKEYCODE_BUTTON_14:
gabomdq@7944
   125
        case AKEYCODE_BUTTON_15:
gabomdq@7944
   126
        case AKEYCODE_BUTTON_16:
gabomdq@7944
   127
            button = keycode - AKEYCODE_BUTTON_1 + 20;
gabomdq@7944
   128
            break;
gabomdq@7944
   129
            
gabomdq@7944
   130
        default:
gabomdq@7944
   131
            return -1;
gabomdq@7944
   132
            break;
gabomdq@7944
   133
    }
gabomdq@7944
   134
    
gabomdq@7944
   135
    /* This is here in case future generations, probably with six fingers per hand, 
gabomdq@7944
   136
     * happily add new cases up above and forget to update the max number of buttons. 
gabomdq@7907
   137
     */
gabomdq@7944
   138
    SDL_assert(button < ANDROID_MAX_NBUTTONS);
gabomdq@7944
   139
    return button;
gabomdq@7944
   140
    
gabomdq@7907
   141
}
gabomdq@7041
   142
gabomdq@7041
   143
/* Function to scan the system for joysticks.
gabomdq@7041
   144
 * This function should set SDL_numjoysticks to the number of available
gabomdq@7041
   145
 * joysticks.  Joystick 0 should be the system default joystick.
gabomdq@7041
   146
 * It should return 0, or -1 on an unrecoverable fatal error.
gabomdq@7041
   147
 */
gabomdq@7041
   148
int
gabomdq@7041
   149
SDL_SYS_JoystickInit(void)
gabomdq@7041
   150
{
gabomdq@7907
   151
    int i = 0;
gabomdq@7907
   152
    const char *env;
gabomdq@7907
   153
    
gabomdq@7907
   154
    env = SDL_GetHint(SDL_HINT_ACCEL_AS_JOY);
gabomdq@7907
   155
    if (env && !SDL_atoi(env))
gabomdq@7907
   156
        SYS_accelAsJoy = SDL_FALSE;
gabomdq@7907
   157
    else
gabomdq@7907
   158
        SYS_accelAsJoy = SDL_TRUE; /* Default behavior */
gabomdq@7907
   159
    
gabomdq@7907
   160
    SYS_numjoysticks = Android_JNI_GetNumJoysticks();
gabomdq@7907
   161
    if (SYS_accelAsJoy) {
gabomdq@7907
   162
        SYS_numjoysticks++;
gabomdq@7907
   163
    }
gabomdq@8024
   164
    SYS_Joysticks = (SDL_Joystick **)SDL_calloc(1, SYS_numjoysticks*sizeof(SDL_Joystick *));
gabomdq@7907
   165
    if (SYS_Joysticks == NULL)
gabomdq@7907
   166
    {
gabomdq@7907
   167
        return SDL_OutOfMemory();
gabomdq@7907
   168
    }
gabomdq@8024
   169
    SYS_JoystickNames = (char **)SDL_calloc(1, SYS_numjoysticks*sizeof(char *));
gabomdq@7907
   170
    if (SYS_JoystickNames == NULL)
gabomdq@7907
   171
    {
gabomdq@7907
   172
        SDL_free(SYS_Joysticks);
gabomdq@7907
   173
        SYS_Joysticks = NULL;
gabomdq@7907
   174
        return SDL_OutOfMemory();
gabomdq@7907
   175
    }
gabomdq@7907
   176
    
gabomdq@7907
   177
    for (i = 0; i < SYS_numjoysticks; i++)
gabomdq@7907
   178
    {
gabomdq@7907
   179
        if ( SYS_accelAsJoy && i == ANDROID_ACCELEROMETER_INDEX ) {
gabomdq@7907
   180
            SYS_JoystickNames[i] = ANDROID_ACCELEROMETER_NAME;
gabomdq@7907
   181
        } else {
gabomdq@7907
   182
            SYS_JoystickNames[i] = Android_JNI_GetJoystickName(i);
gabomdq@7907
   183
        }
gabomdq@7907
   184
    }
gabomdq@7907
   185
   
gabomdq@7907
   186
    return (SYS_numjoysticks);
gabomdq@7041
   187
}
gabomdq@7041
   188
gabomdq@7041
   189
int SDL_SYS_NumJoysticks()
gabomdq@7041
   190
{
gabomdq@7907
   191
    return SYS_numjoysticks;
gabomdq@7041
   192
}
gabomdq@7041
   193
gabomdq@7041
   194
void SDL_SYS_JoystickDetect()
gabomdq@7041
   195
{
gabomdq@7041
   196
}
gabomdq@7041
   197
gabomdq@7907
   198
/* TODO: Hotplugging support */
gabomdq@7041
   199
SDL_bool SDL_SYS_JoystickNeedsPolling()
gabomdq@7041
   200
{
gabomdq@7041
   201
    return SDL_FALSE;
gabomdq@7041
   202
}
gabomdq@7041
   203
gabomdq@7041
   204
/* Function to get the device-dependent name of a joystick */
gabomdq@7041
   205
const char *
gabomdq@7041
   206
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
gabomdq@7041
   207
{
gabomdq@7907
   208
    return SYS_JoystickNames[device_index];
gabomdq@7041
   209
}
gabomdq@7041
   210
gabomdq@7041
   211
/* Function to perform the mapping from device index to the instance id for this index */
gabomdq@7041
   212
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
gabomdq@7041
   213
{
gabomdq@7041
   214
    return device_index;
gabomdq@7041
   215
}
gabomdq@7041
   216
gabomdq@7041
   217
/* Function to open a joystick for use.
gabomdq@7041
   218
   The joystick to open is specified by the index field of the joystick.
gabomdq@7041
   219
   This should fill the nbuttons and naxes fields of the joystick structure.
gabomdq@7041
   220
   It returns 0, or -1 if there is an error.
gabomdq@7041
   221
 */
gabomdq@7041
   222
int
gabomdq@7041
   223
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
gabomdq@7041
   224
{
gabomdq@7907
   225
    if (device_index < SYS_numjoysticks) {
gabomdq@7041
   226
        joystick->nhats = 0;
gabomdq@7041
   227
        joystick->nballs = 0;
gabomdq@7907
   228
        if (SYS_accelAsJoy && device_index == ANDROID_ACCELEROMETER_INDEX) {
gabomdq@7907
   229
            joystick->nbuttons = 0;
gabomdq@7907
   230
            joystick->naxes = 3;
gabomdq@7907
   231
        } else {
gabomdq@7944
   232
            /* FIXME: Get the real number of buttons in the device? */
gabomdq@7944
   233
            joystick->nbuttons = ANDROID_MAX_NBUTTONS;
gabomdq@7907
   234
            joystick->naxes = Android_JNI_GetJoystickAxes(device_index);
gabomdq@7907
   235
        }
gabomdq@7907
   236
        
gabomdq@7907
   237
        SYS_Joysticks[device_index] = joystick;
gabomdq@7041
   238
        return 0;
slouken@7191
   239
    } else {
philipp@7930
   240
        return SDL_SetError("No joystick available with that index");
slouken@7191
   241
    }
gabomdq@7041
   242
}
gabomdq@7041
   243
gabomdq@7041
   244
/* Function to determine is this joystick is attached to the system right now */
gabomdq@7041
   245
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
gabomdq@7041
   246
{
gabomdq@7041
   247
    return SDL_TRUE;
gabomdq@7041
   248
}
gabomdq@7041
   249
gabomdq@7041
   250
/* Function to update the state of a joystick - called as a device poll.
gabomdq@7041
   251
 * This function shouldn't update the joystick structure directly,
gabomdq@7041
   252
 * but instead should call SDL_PrivateJoystick*() to deliver events
gabomdq@7041
   253
 * and update joystick device state.
gabomdq@7041
   254
 */
gabomdq@7041
   255
void
gabomdq@7041
   256
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
gabomdq@7041
   257
{
gabomdq@7041
   258
    int i;
gabomdq@7041
   259
    Sint16 value;
gabomdq@7041
   260
    float values[3];
gabomdq@7041
   261
gabomdq@7907
   262
    if (SYS_accelAsJoy && Android_JNI_GetAccelerometerValues(values) &&
gabomdq@7907
   263
        joystick->instance_id == ANDROID_ACCELEROMETER_INDEX) {
gabomdq@7041
   264
        for ( i = 0; i < 3; i++ ) {
gabomdq@7041
   265
            value = (Sint16)(values[i] * 32767.0f);
gabomdq@7041
   266
            SDL_PrivateJoystickAxis(joystick, i, value);
gabomdq@7041
   267
        }
gabomdq@7041
   268
    }
gabomdq@7041
   269
}
gabomdq@7041
   270
gabomdq@7041
   271
/* Function to close a joystick after use */
gabomdq@7041
   272
void
gabomdq@7041
   273
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
gabomdq@7041
   274
{
gabomdq@8024
   275
    int device_index;
gabomdq@8024
   276
    
gabomdq@8024
   277
    for (device_index = 0; device_index < SYS_numjoysticks; device_index++) {
gabomdq@8024
   278
        if ( SYS_Joysticks[device_index] == joystick ) {
gabomdq@8024
   279
            SYS_Joysticks[device_index] = NULL;
gabomdq@8024
   280
        }
gabomdq@8024
   281
    }
gabomdq@8024
   282
    
gabomdq@8024
   283
    joystick->closed = 1;
gabomdq@7041
   284
}
gabomdq@7041
   285
gabomdq@7041
   286
/* Function to perform any system-specific joystick related cleanup */
gabomdq@7041
   287
void
gabomdq@7041
   288
SDL_SYS_JoystickQuit(void)
gabomdq@7041
   289
{
gabomdq@7907
   290
    SDL_free(SYS_JoystickNames);
gabomdq@7907
   291
    SDL_free(SYS_Joysticks);
gabomdq@7907
   292
    SYS_JoystickNames = NULL;
gabomdq@7907
   293
    SYS_Joysticks = NULL;
gabomdq@7041
   294
}
gabomdq@7041
   295
gabomdq@7041
   296
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
gabomdq@7041
   297
{
gabomdq@7041
   298
    SDL_JoystickGUID guid;
slouken@7191
   299
    /* the GUID is just the first 16 chars of the name for now */
gabomdq@7041
   300
    const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
gabomdq@7041
   301
    SDL_zero( guid );
gabomdq@7041
   302
    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
gabomdq@7041
   303
    return guid;
gabomdq@7041
   304
}
gabomdq@7041
   305
gabomdq@7041
   306
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
gabomdq@7041
   307
{
gabomdq@7041
   308
    SDL_JoystickGUID guid;
slouken@7191
   309
    /* the GUID is just the first 16 chars of the name for now */
gabomdq@7041
   310
    const char *name = joystick->name;
gabomdq@7041
   311
    SDL_zero( guid );
gabomdq@7041
   312
    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
gabomdq@7041
   313
    return guid;
gabomdq@7041
   314
}
gabomdq@7041
   315
gabomdq@7907
   316
int
gabomdq@7907
   317
Android_OnPadDown(int padId, int keycode)
gabomdq@7907
   318
{
gabomdq@7956
   319
    int button = keycode_to_SDL(keycode);
gabomdq@7956
   320
    if (button >= 0) {
gabomdq@8024
   321
        if (SYS_Joysticks[padId]) {
gabomdq@8024
   322
            SDL_PrivateJoystickButton(SYS_Joysticks[padId], button , SDL_PRESSED);
gabomdq@8024
   323
        }
gabomdq@8013
   324
        return 0;
gabomdq@7956
   325
    }
gabomdq@7907
   326
    
gabomdq@8013
   327
    return -1;
gabomdq@7907
   328
}
gabomdq@7907
   329
gabomdq@7907
   330
int
gabomdq@7907
   331
Android_OnPadUp(int padId, int keycode)
gabomdq@7907
   332
{
gabomdq@7956
   333
    int button = keycode_to_SDL(keycode);
gabomdq@7956
   334
    if (button >= 0) {
gabomdq@8024
   335
        if (SYS_Joysticks[padId]) {
gabomdq@8024
   336
            SDL_PrivateJoystickButton(SYS_Joysticks[padId], button, SDL_RELEASED);
gabomdq@8024
   337
        }
gabomdq@8013
   338
        return 0;
gabomdq@7956
   339
    }
gabomdq@7907
   340
    
gabomdq@8013
   341
    return -1;
gabomdq@7907
   342
}
gabomdq@7907
   343
gabomdq@7907
   344
int
gabomdq@7907
   345
Android_OnJoy(int joyId, int axis, float value)
gabomdq@7907
   346
{
gabomdq@7907
   347
    /* Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] */
gabomdq@7907
   348
    /* TODO: Are the reported values right? */
gabomdq@8024
   349
    if (SYS_Joysticks[joyId]) {
gabomdq@8024
   350
        SDL_PrivateJoystickAxis(SYS_Joysticks[joyId], axis, (Sint16) (32767.*value) );
gabomdq@8024
   351
    }
gabomdq@7907
   352
    
gabomdq@7907
   353
    return 0;
gabomdq@7907
   354
}
gabomdq@7907
   355
gabomdq@7041
   356
#endif /* SDL_JOYSTICK_ANDROID */
gabomdq@7041
   357
gabomdq@7041
   358
/* vi: set ts=4 sw=4 expandtab: */