src/joystick/android/SDL_sysjoystick.c
author Gabriel Jacobo <gabomdq@gmail.com>
Tue, 05 Nov 2013 20:07:39 -0300
changeset 7907 24b4e98c6010
parent 7191 75360622e65f
child 7928 8d4d3fdca1aa
permissions -rw-r--r--
Adds Joystick support for Android

This bumps the build SDK level to 12 (up from 10). Runtime requirements remain
the same (at API level < 12 joystick support is disabled).

Also enables building SDL for armv7 and x86.
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@7041
    33
#include "../SDL_sysjoystick.h"
gabomdq@7041
    34
#include "../SDL_joystick_c.h"
gabomdq@7041
    35
#include "../../core/android/SDL_android.h"
gabomdq@7041
    36
gabomdq@7907
    37
#define ANDROID_ACCELEROMETER_INDEX (SYS_numjoysticks - 1)
gabomdq@7907
    38
#define ANDROID_ACCELEROMETER_NAME "Android Accelerometer"
gabomdq@7907
    39
gabomdq@7907
    40
static SDL_Joystick **SYS_Joysticks;
gabomdq@7907
    41
static char **SYS_JoystickNames;
gabomdq@7907
    42
static int SYS_numjoysticks;
gabomdq@7907
    43
static SDL_bool SYS_accelAsJoy;
gabomdq@7907
    44
gabomdq@7907
    45
/* Function to convert Android keyCodes into SDL ones.
gabomdq@7907
    46
 * This code manipulation is done to get a sequential list of codes.
gabomdq@7907
    47
 */
gabomdq@7907
    48
int
gabomdq@7907
    49
keycode_to_SDL(int keycode)
gabomdq@7907
    50
{
gabomdq@7907
    51
    int final = 0;
gabomdq@7907
    52
    /* D-Pad key codes (API 1):
gabomdq@7907
    53
     * KEYCODE_DPAD_UP=19, KEYCODE_DPAD_DOWN
gabomdq@7907
    54
     * KEYCODE_DPAD_LEFT, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_CENTER
gabomdq@7907
    55
     */
gabomdq@7907
    56
    if(keycode < 96)
gabomdq@7907
    57
        return keycode-19;
gabomdq@7907
    58
    /* Some gamepad buttons (API 9):
gabomdq@7907
    59
     * KEYCODE_BUTTON_A=96, KEYCODE_BUTTON_B, KEYCODE_BUTTON_C,
gabomdq@7907
    60
     * KEYCODE_BUTTON_X, KEYCODE_BUTTON_Y, KEYCODE_BUTTON_Z,
gabomdq@7907
    61
     * KEYCODE_BUTTON_L1, KEYCODE_BUTTON_L2,
gabomdq@7907
    62
     * KEYCODE_BUTTON_R1, KEYCODE_BUTTON_R2,
gabomdq@7907
    63
     * KEYCODE_BUTTON_THUMBL, KEYCODE_BUTTON_THUMBR,
gabomdq@7907
    64
     * KEYCODE_BUTTON_START, KEYCODE_BUTTON_SELECT, KEYCODE_BUTTON_MODE
gabomdq@7907
    65
     */
gabomdq@7907
    66
    else if(keycode < 188)
gabomdq@7907
    67
        return keycode-91;
gabomdq@7907
    68
    /* More gamepad buttons (API 12):
gabomdq@7907
    69
     * KEYCODE_BUTTON_1=188 to KEYCODE_BUTTON_16
gabomdq@7907
    70
     */
gabomdq@7907
    71
    else
gabomdq@7907
    72
        return keycode-168;
gabomdq@7907
    73
}
gabomdq@7041
    74
gabomdq@7041
    75
/* Function to scan the system for joysticks.
gabomdq@7041
    76
 * This function should set SDL_numjoysticks to the number of available
gabomdq@7041
    77
 * joysticks.  Joystick 0 should be the system default joystick.
gabomdq@7041
    78
 * It should return 0, or -1 on an unrecoverable fatal error.
gabomdq@7041
    79
 */
gabomdq@7041
    80
int
gabomdq@7041
    81
SDL_SYS_JoystickInit(void)
gabomdq@7041
    82
{
gabomdq@7907
    83
    int i = 0;
gabomdq@7907
    84
    const char *env;
gabomdq@7907
    85
    
gabomdq@7907
    86
    env = SDL_GetHint(SDL_HINT_ACCEL_AS_JOY);
gabomdq@7907
    87
    if (env && !SDL_atoi(env))
gabomdq@7907
    88
        SYS_accelAsJoy = SDL_FALSE;
gabomdq@7907
    89
    else
gabomdq@7907
    90
        SYS_accelAsJoy = SDL_TRUE; /* Default behavior */
gabomdq@7907
    91
    
gabomdq@7907
    92
    SYS_numjoysticks = Android_JNI_GetNumJoysticks();
gabomdq@7907
    93
    if (SYS_accelAsJoy) {
gabomdq@7907
    94
        SYS_numjoysticks++;
gabomdq@7907
    95
    }
gabomdq@7907
    96
    SYS_Joysticks = (SDL_Joystick **)SDL_malloc(SYS_numjoysticks*sizeof(SDL_Joystick *));
gabomdq@7907
    97
    if (SYS_Joysticks == NULL)
gabomdq@7907
    98
    {
gabomdq@7907
    99
        return SDL_OutOfMemory();
gabomdq@7907
   100
    }
gabomdq@7907
   101
    SYS_JoystickNames = (char **)SDL_malloc(SYS_numjoysticks*sizeof(char *));
gabomdq@7907
   102
    if (SYS_JoystickNames == NULL)
gabomdq@7907
   103
    {
gabomdq@7907
   104
        SDL_free(SYS_Joysticks);
gabomdq@7907
   105
        SYS_Joysticks = NULL;
gabomdq@7907
   106
        return SDL_OutOfMemory();
gabomdq@7907
   107
    }
gabomdq@7907
   108
    SDL_memset(SYS_JoystickNames, 0, (SYS_numjoysticks*sizeof(char *)));
gabomdq@7907
   109
    SDL_memset(SYS_Joysticks, 0, (SYS_numjoysticks*sizeof(SDL_Joystick *)));
gabomdq@7907
   110
    
gabomdq@7907
   111
    for (i = 0; i < SYS_numjoysticks; i++)
gabomdq@7907
   112
    {
gabomdq@7907
   113
        if ( SYS_accelAsJoy && i == ANDROID_ACCELEROMETER_INDEX ) {
gabomdq@7907
   114
            SYS_JoystickNames[i] = ANDROID_ACCELEROMETER_NAME;
gabomdq@7907
   115
        } else {
gabomdq@7907
   116
            SYS_JoystickNames[i] = Android_JNI_GetJoystickName(i);
gabomdq@7907
   117
        }
gabomdq@7907
   118
    }
gabomdq@7907
   119
   
gabomdq@7907
   120
    return (SYS_numjoysticks);
gabomdq@7041
   121
}
gabomdq@7041
   122
gabomdq@7041
   123
int SDL_SYS_NumJoysticks()
gabomdq@7041
   124
{
gabomdq@7907
   125
    return SYS_numjoysticks;
gabomdq@7041
   126
}
gabomdq@7041
   127
gabomdq@7041
   128
void SDL_SYS_JoystickDetect()
gabomdq@7041
   129
{
gabomdq@7041
   130
}
gabomdq@7041
   131
gabomdq@7907
   132
/* TODO: Hotplugging support */
gabomdq@7041
   133
SDL_bool SDL_SYS_JoystickNeedsPolling()
gabomdq@7041
   134
{
gabomdq@7041
   135
    return SDL_FALSE;
gabomdq@7041
   136
}
gabomdq@7041
   137
gabomdq@7041
   138
/* Function to get the device-dependent name of a joystick */
gabomdq@7041
   139
const char *
gabomdq@7041
   140
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
gabomdq@7041
   141
{
gabomdq@7907
   142
    return SYS_JoystickNames[device_index];
gabomdq@7041
   143
}
gabomdq@7041
   144
gabomdq@7041
   145
/* Function to perform the mapping from device index to the instance id for this index */
gabomdq@7041
   146
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
gabomdq@7041
   147
{
gabomdq@7041
   148
    return device_index;
gabomdq@7041
   149
}
gabomdq@7041
   150
gabomdq@7041
   151
/* Function to open a joystick for use.
gabomdq@7041
   152
   The joystick to open is specified by the index field of the joystick.
gabomdq@7041
   153
   This should fill the nbuttons and naxes fields of the joystick structure.
gabomdq@7041
   154
   It returns 0, or -1 if there is an error.
gabomdq@7041
   155
 */
gabomdq@7041
   156
int
gabomdq@7041
   157
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
gabomdq@7041
   158
{
gabomdq@7907
   159
    if (device_index < SYS_numjoysticks) {
gabomdq@7041
   160
        joystick->nhats = 0;
gabomdq@7041
   161
        joystick->nballs = 0;
gabomdq@7907
   162
        if (SYS_accelAsJoy && device_index == ANDROID_ACCELEROMETER_INDEX) {
gabomdq@7907
   163
            joystick->nbuttons = 0;
gabomdq@7907
   164
            joystick->naxes = 3;
gabomdq@7907
   165
        } else {
gabomdq@7907
   166
            /* TODO: Get the real number of buttons in the device */
gabomdq@7907
   167
            joystick->nbuttons = 36;
gabomdq@7907
   168
            joystick->naxes = Android_JNI_GetJoystickAxes(device_index);
gabomdq@7907
   169
        }
gabomdq@7907
   170
        
gabomdq@7907
   171
        SYS_Joysticks[device_index] = joystick;
gabomdq@7041
   172
        return 0;
slouken@7191
   173
    } else {
slouken@7191
   174
        SDL_SetError("No joystick available with that index");
slouken@7191
   175
        return (-1);
slouken@7191
   176
    }
gabomdq@7041
   177
}
gabomdq@7041
   178
gabomdq@7041
   179
/* Function to determine is this joystick is attached to the system right now */
gabomdq@7041
   180
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
gabomdq@7041
   181
{
gabomdq@7041
   182
    return SDL_TRUE;
gabomdq@7041
   183
}
gabomdq@7041
   184
gabomdq@7041
   185
/* Function to update the state of a joystick - called as a device poll.
gabomdq@7041
   186
 * This function shouldn't update the joystick structure directly,
gabomdq@7041
   187
 * but instead should call SDL_PrivateJoystick*() to deliver events
gabomdq@7041
   188
 * and update joystick device state.
gabomdq@7041
   189
 */
gabomdq@7041
   190
void
gabomdq@7041
   191
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
gabomdq@7041
   192
{
gabomdq@7041
   193
    int i;
gabomdq@7041
   194
    Sint16 value;
gabomdq@7041
   195
    float values[3];
gabomdq@7041
   196
gabomdq@7907
   197
    if (SYS_accelAsJoy && Android_JNI_GetAccelerometerValues(values) &&
gabomdq@7907
   198
        joystick->instance_id == ANDROID_ACCELEROMETER_INDEX) {
gabomdq@7041
   199
        for ( i = 0; i < 3; i++ ) {
gabomdq@7041
   200
            value = (Sint16)(values[i] * 32767.0f);
gabomdq@7041
   201
            SDL_PrivateJoystickAxis(joystick, i, value);
gabomdq@7041
   202
        }
gabomdq@7041
   203
    }
gabomdq@7041
   204
}
gabomdq@7041
   205
gabomdq@7041
   206
/* Function to close a joystick after use */
gabomdq@7041
   207
void
gabomdq@7041
   208
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
gabomdq@7041
   209
{
gabomdq@7041
   210
}
gabomdq@7041
   211
gabomdq@7041
   212
/* Function to perform any system-specific joystick related cleanup */
gabomdq@7041
   213
void
gabomdq@7041
   214
SDL_SYS_JoystickQuit(void)
gabomdq@7041
   215
{
gabomdq@7907
   216
    SDL_free(SYS_JoystickNames);
gabomdq@7907
   217
    SDL_free(SYS_Joysticks);
gabomdq@7907
   218
    SYS_JoystickNames = NULL;
gabomdq@7907
   219
    SYS_Joysticks = NULL;
gabomdq@7041
   220
}
gabomdq@7041
   221
gabomdq@7041
   222
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
gabomdq@7041
   223
{
gabomdq@7041
   224
    SDL_JoystickGUID guid;
slouken@7191
   225
    /* the GUID is just the first 16 chars of the name for now */
gabomdq@7041
   226
    const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
gabomdq@7041
   227
    SDL_zero( guid );
gabomdq@7041
   228
    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
gabomdq@7041
   229
    return guid;
gabomdq@7041
   230
}
gabomdq@7041
   231
gabomdq@7041
   232
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
gabomdq@7041
   233
{
gabomdq@7041
   234
    SDL_JoystickGUID guid;
slouken@7191
   235
    /* the GUID is just the first 16 chars of the name for now */
gabomdq@7041
   236
    const char *name = joystick->name;
gabomdq@7041
   237
    SDL_zero( guid );
gabomdq@7041
   238
    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
gabomdq@7041
   239
    return guid;
gabomdq@7041
   240
}
gabomdq@7041
   241
gabomdq@7907
   242
int
gabomdq@7907
   243
Android_OnPadDown(int padId, int keycode)
gabomdq@7907
   244
{
gabomdq@7907
   245
    SDL_PrivateJoystickButton(SYS_Joysticks[padId], keycode_to_SDL(keycode), SDL_PRESSED);
gabomdq@7907
   246
    
gabomdq@7907
   247
    return 0;
gabomdq@7907
   248
}
gabomdq@7907
   249
gabomdq@7907
   250
int
gabomdq@7907
   251
Android_OnPadUp(int padId, int keycode)
gabomdq@7907
   252
{
gabomdq@7907
   253
    SDL_PrivateJoystickButton(SYS_Joysticks[padId], keycode_to_SDL(keycode), SDL_RELEASED);
gabomdq@7907
   254
    
gabomdq@7907
   255
    return 0;
gabomdq@7907
   256
}
gabomdq@7907
   257
gabomdq@7907
   258
int
gabomdq@7907
   259
Android_OnJoy(int joyId, int axis, float value)
gabomdq@7907
   260
{
gabomdq@7907
   261
    /* Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] */
gabomdq@7907
   262
    /* TODO: Are the reported values right? */
gabomdq@7907
   263
    SDL_PrivateJoystickAxis(SYS_Joysticks[joyId], axis, (Sint16) (32767.*value) );
gabomdq@7907
   264
    
gabomdq@7907
   265
    return 0;
gabomdq@7907
   266
}
gabomdq@7907
   267
gabomdq@7041
   268
#endif /* SDL_JOYSTICK_ANDROID */
gabomdq@7041
   269
gabomdq@7041
   270
/* vi: set ts=4 sw=4 expandtab: */