src/joystick/android/SDL_sysjoystick.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 25 Oct 2018 16:53:14 -0700
changeset 12359 691c32a30fb9
parent 12115 0d9277d27e2d
child 12464 db15b3c90139
permissions -rw-r--r--
Generalized the XInput user index into a player index
gabomdq@7041
     1
/*
gabomdq@7041
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 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
icculus@8093
    22
#include "../../SDL_internal.h"
gabomdq@7041
    23
gabomdq@7041
    24
#ifdef SDL_JOYSTICK_ANDROID
gabomdq@7041
    25
gabomdq@7041
    26
#include <stdio.h>              /* For the definition of NULL */
gabomdq@7041
    27
#include "SDL_error.h"
gabomdq@7041
    28
#include "SDL_events.h"
gabomdq@8057
    29
gabomdq@7041
    30
#include "SDL_joystick.h"
gabomdq@7907
    31
#include "SDL_hints.h"
gabomdq@7944
    32
#include "SDL_assert.h"
gabomdq@8060
    33
#include "SDL_timer.h"
philipp@8074
    34
#include "SDL_log.h"
gabomdq@8057
    35
#include "SDL_sysjoystick_c.h"
gabomdq@7041
    36
#include "../SDL_joystick_c.h"
slouken@11859
    37
#include "../../events/SDL_keyboard_c.h"
gabomdq@7041
    38
#include "../../core/android/SDL_android.h"
slouken@12088
    39
#include "../hidapi/SDL_hidapijoystick_c.h"
philipp@8008
    40
gabomdq@7944
    41
#include "android/keycodes.h"
gabomdq@7944
    42
gabomdq@7944
    43
/* As of platform android-14, android/keycodes.h is missing these defines */
gabomdq@7944
    44
#ifndef AKEYCODE_BUTTON_1
gabomdq@7944
    45
#define AKEYCODE_BUTTON_1 188
gabomdq@7944
    46
#define AKEYCODE_BUTTON_2 189
gabomdq@7944
    47
#define AKEYCODE_BUTTON_3 190
gabomdq@7944
    48
#define AKEYCODE_BUTTON_4 191
gabomdq@7944
    49
#define AKEYCODE_BUTTON_5 192
gabomdq@7944
    50
#define AKEYCODE_BUTTON_6 193
gabomdq@7944
    51
#define AKEYCODE_BUTTON_7 194
gabomdq@7944
    52
#define AKEYCODE_BUTTON_8 195
gabomdq@7944
    53
#define AKEYCODE_BUTTON_9 196
gabomdq@7944
    54
#define AKEYCODE_BUTTON_10 197
gabomdq@7944
    55
#define AKEYCODE_BUTTON_11 198
gabomdq@7944
    56
#define AKEYCODE_BUTTON_12 199
gabomdq@7944
    57
#define AKEYCODE_BUTTON_13 200
gabomdq@7944
    58
#define AKEYCODE_BUTTON_14 201
gabomdq@7944
    59
#define AKEYCODE_BUTTON_15 202
gabomdq@7944
    60
#define AKEYCODE_BUTTON_16 203
gabomdq@7944
    61
#endif
gabomdq@7041
    62
gabomdq@7907
    63
#define ANDROID_ACCELEROMETER_NAME "Android Accelerometer"
gabomdq@8057
    64
#define ANDROID_ACCELEROMETER_DEVICE_ID INT_MIN
gabomdq@7944
    65
#define ANDROID_MAX_NBUTTONS 36
gabomdq@7907
    66
gabomdq@8057
    67
static SDL_joylist_item * JoystickByDeviceId(int device_id);
gabomdq@8057
    68
gabomdq@8057
    69
static SDL_joylist_item *SDL_joylist = NULL;
gabomdq@8057
    70
static SDL_joylist_item *SDL_joylist_tail = NULL;
gabomdq@8057
    71
static int numjoysticks = 0;
gabomdq@8057
    72
gabomdq@7907
    73
slouken@11921
    74
/* Public domain CRC implementation adapted from:
slouken@11921
    75
   http://home.thep.lu.se/~bjorn/crc/crc32_simple.c
slouken@11921
    76
*/
slouken@11921
    77
static Uint32 crc32_for_byte(Uint32 r)
slouken@11921
    78
{
slouken@11921
    79
    int i;
slouken@11921
    80
    for(i = 0; i < 8; ++i) {
slouken@11921
    81
        r = (r & 1? 0: (Uint32)0xEDB88320L) ^ r >> 1;
slouken@11921
    82
    }
slouken@11921
    83
    return r ^ (Uint32)0xFF000000L;
slouken@11921
    84
}
slouken@11921
    85
slouken@11921
    86
static Uint32 crc32(const void *data, int count)
slouken@11921
    87
{
slouken@11921
    88
    Uint32 crc = 0;
slouken@11921
    89
    int i;
slouken@11921
    90
    for(i = 0; i < count; ++i) {
slouken@11921
    91
        crc = crc32_for_byte((Uint8)crc ^ ((const Uint8*)data)[i]) ^ crc >> 8;
slouken@11921
    92
    }
slouken@11921
    93
    return crc;
slouken@11921
    94
}
slouken@11921
    95
gabomdq@7907
    96
/* Function to convert Android keyCodes into SDL ones.
gabomdq@7907
    97
 * This code manipulation is done to get a sequential list of codes.
gabomdq@7944
    98
 * FIXME: This is only suited for the case where we use a fixed number of buttons determined by ANDROID_MAX_NBUTTONS
gabomdq@7907
    99
 */
philipp@7929
   100
static int
gabomdq@7907
   101
keycode_to_SDL(int keycode)
gabomdq@7907
   102
{
slouken@11778
   103
    /* FIXME: If this function gets too unwieldy in the future, replace with a lookup table */
gabomdq@7944
   104
    int button = 0;
slouken@11845
   105
    switch (keycode) {
gabomdq@8122
   106
        /* Some gamepad buttons (API 9) */
gabomdq@8122
   107
        case AKEYCODE_BUTTON_A:
gabomdq@8122
   108
            button = SDL_CONTROLLER_BUTTON_A;
gabomdq@8122
   109
            break;
gabomdq@8122
   110
        case AKEYCODE_BUTTON_B:
gabomdq@8122
   111
            button = SDL_CONTROLLER_BUTTON_B;
gabomdq@8122
   112
            break;
gabomdq@8122
   113
        case AKEYCODE_BUTTON_X:
gabomdq@8122
   114
            button = SDL_CONTROLLER_BUTTON_X;
gabomdq@8122
   115
            break;
gabomdq@8122
   116
        case AKEYCODE_BUTTON_Y:
gabomdq@8122
   117
            button = SDL_CONTROLLER_BUTTON_Y;
gabomdq@8122
   118
            break;
gabomdq@8122
   119
        case AKEYCODE_BUTTON_L1:
gabomdq@8122
   120
            button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
gabomdq@8122
   121
            break;
gabomdq@8122
   122
        case AKEYCODE_BUTTON_R1:
gabomdq@8122
   123
            button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
gabomdq@8122
   124
            break;
gabomdq@8122
   125
        case AKEYCODE_BUTTON_THUMBL:
gabomdq@8122
   126
            button = SDL_CONTROLLER_BUTTON_LEFTSTICK;
gabomdq@8122
   127
            break;
gabomdq@8122
   128
        case AKEYCODE_BUTTON_THUMBR:
gabomdq@8122
   129
            button = SDL_CONTROLLER_BUTTON_RIGHTSTICK;
gabomdq@8122
   130
            break;
gabomdq@8122
   131
        case AKEYCODE_BUTTON_START:
gabomdq@8122
   132
            button = SDL_CONTROLLER_BUTTON_START;
gabomdq@8122
   133
            break;
slouken@11778
   134
        case AKEYCODE_BACK:
gabomdq@8122
   135
        case AKEYCODE_BUTTON_SELECT:
gabomdq@8122
   136
            button = SDL_CONTROLLER_BUTTON_BACK;
gabomdq@8122
   137
            break;
gabomdq@8122
   138
        case AKEYCODE_BUTTON_MODE:
gabomdq@8122
   139
            button = SDL_CONTROLLER_BUTTON_GUIDE;
gabomdq@8122
   140
            break;
gabomdq@8122
   141
        case AKEYCODE_BUTTON_L2:
gabomdq@8122
   142
            button = SDL_CONTROLLER_BUTTON_MAX; /* Not supported by GameController */
gabomdq@8122
   143
            break;
gabomdq@8122
   144
        case AKEYCODE_BUTTON_R2:
gabomdq@8122
   145
            button = SDL_CONTROLLER_BUTTON_MAX+1; /* Not supported by GameController */
gabomdq@8122
   146
            break;
gabomdq@8122
   147
        case AKEYCODE_BUTTON_C:
gabomdq@8122
   148
            button = SDL_CONTROLLER_BUTTON_MAX+2; /* Not supported by GameController */
gabomdq@8122
   149
            break;
gabomdq@8122
   150
        case AKEYCODE_BUTTON_Z:
gabomdq@8122
   151
            button = SDL_CONTROLLER_BUTTON_MAX+3; /* Not supported by GameController */
gabomdq@8122
   152
            break;
gabomdq@8122
   153
                        
gabomdq@8122
   154
        /* D-Pad key codes (API 1) */
gabomdq@7944
   155
        case AKEYCODE_DPAD_UP:
gabomdq@8122
   156
            button = SDL_CONTROLLER_BUTTON_DPAD_UP;
gabomdq@8122
   157
            break;
gabomdq@7944
   158
        case AKEYCODE_DPAD_DOWN:
gabomdq@8122
   159
            button = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
gabomdq@8122
   160
            break;
gabomdq@7944
   161
        case AKEYCODE_DPAD_LEFT:
gabomdq@8122
   162
            button = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
gabomdq@8122
   163
            break;
gabomdq@7944
   164
        case AKEYCODE_DPAD_RIGHT:
gabomdq@8122
   165
            button = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
gabomdq@8122
   166
            break;
gabomdq@7944
   167
        case AKEYCODE_DPAD_CENTER:
slouken@11663
   168
            /* This is handled better by applications as the A button */
icculus@11833
   169
            /*button = SDL_CONTROLLER_BUTTON_MAX+4;*/ /* Not supported by GameController */
slouken@11663
   170
            button = SDL_CONTROLLER_BUTTON_A;
slouken@11663
   171
            break;
slouken@11663
   172
gabomdq@7944
   173
        /* More gamepad buttons (API 12), these get mapped to 20...35*/
gabomdq@7944
   174
        case AKEYCODE_BUTTON_1:
gabomdq@7944
   175
        case AKEYCODE_BUTTON_2:
gabomdq@7944
   176
        case AKEYCODE_BUTTON_3:
gabomdq@7944
   177
        case AKEYCODE_BUTTON_4:
gabomdq@7944
   178
        case AKEYCODE_BUTTON_5:
gabomdq@7944
   179
        case AKEYCODE_BUTTON_6:
gabomdq@7944
   180
        case AKEYCODE_BUTTON_7:
gabomdq@7944
   181
        case AKEYCODE_BUTTON_8:
gabomdq@7944
   182
        case AKEYCODE_BUTTON_9:
gabomdq@7944
   183
        case AKEYCODE_BUTTON_10:
gabomdq@7944
   184
        case AKEYCODE_BUTTON_11:
gabomdq@7944
   185
        case AKEYCODE_BUTTON_12:
gabomdq@7944
   186
        case AKEYCODE_BUTTON_13:
gabomdq@7944
   187
        case AKEYCODE_BUTTON_14:
gabomdq@7944
   188
        case AKEYCODE_BUTTON_15:
gabomdq@7944
   189
        case AKEYCODE_BUTTON_16:
gabomdq@8122
   190
            button = keycode - AKEYCODE_BUTTON_1 + SDL_CONTROLLER_BUTTON_MAX + 5;
gabomdq@7944
   191
            break;
gabomdq@7944
   192
            
gabomdq@7944
   193
        default:
gabomdq@7944
   194
            return -1;
slouken@10672
   195
            /* break; -Wunreachable-code-break */
gabomdq@7944
   196
    }
gabomdq@7944
   197
    
gabomdq@7944
   198
    /* This is here in case future generations, probably with six fingers per hand, 
gabomdq@7944
   199
     * happily add new cases up above and forget to update the max number of buttons. 
gabomdq@7907
   200
     */
gabomdq@7944
   201
    SDL_assert(button < ANDROID_MAX_NBUTTONS);
gabomdq@7944
   202
    return button;
slouken@11845
   203
}
slouken@11845
   204
slouken@11845
   205
static SDL_Scancode
slouken@11845
   206
button_to_scancode(int button)
slouken@11845
   207
{
slouken@11845
   208
    switch (button) {
slouken@11845
   209
    case SDL_CONTROLLER_BUTTON_A:
slouken@11845
   210
        return SDL_SCANCODE_RETURN;
slouken@11845
   211
    case SDL_CONTROLLER_BUTTON_B:
slouken@11845
   212
        return SDL_SCANCODE_ESCAPE;
slouken@11845
   213
    case SDL_CONTROLLER_BUTTON_BACK:
slouken@11845
   214
        return SDL_SCANCODE_ESCAPE;
slouken@11845
   215
    case SDL_CONTROLLER_BUTTON_DPAD_UP:
slouken@11845
   216
        return SDL_SCANCODE_UP;
slouken@11845
   217
    case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
slouken@11845
   218
        return SDL_SCANCODE_DOWN;
slouken@11845
   219
    case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
slouken@11845
   220
        return SDL_SCANCODE_LEFT;
slouken@11845
   221
    case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
slouken@11845
   222
        return SDL_SCANCODE_RIGHT;
slouken@11845
   223
    }
slouken@11845
   224
slouken@11845
   225
    /* Unsupported button */
slouken@11845
   226
    return SDL_SCANCODE_UNKNOWN;
gabomdq@7907
   227
}
gabomdq@7041
   228
gabomdq@8057
   229
int
gabomdq@8057
   230
Android_OnPadDown(int device_id, int keycode)
gabomdq@8057
   231
{
gabomdq@8057
   232
    SDL_joylist_item *item;
gabomdq@8057
   233
    int button = keycode_to_SDL(keycode);
gabomdq@8057
   234
    if (button >= 0) {
gabomdq@8057
   235
        item = JoystickByDeviceId(device_id);
gabomdq@8057
   236
        if (item && item->joystick) {
slouken@11921
   237
            SDL_PrivateJoystickButton(item->joystick, button, SDL_PRESSED);
slouken@11845
   238
        } else {
slouken@11845
   239
            SDL_SendKeyboardKey(SDL_PRESSED, button_to_scancode(button));
gabomdq@8057
   240
        }
slouken@10551
   241
        return 0;
gabomdq@8057
   242
    }
gabomdq@8057
   243
    
gabomdq@8057
   244
    return -1;
gabomdq@8057
   245
}
gabomdq@8057
   246
gabomdq@8057
   247
int
gabomdq@8057
   248
Android_OnPadUp(int device_id, int keycode)
gabomdq@8057
   249
{
gabomdq@8057
   250
    SDL_joylist_item *item;
gabomdq@8057
   251
    int button = keycode_to_SDL(keycode);
gabomdq@8057
   252
    if (button >= 0) {
gabomdq@8057
   253
        item = JoystickByDeviceId(device_id);
gabomdq@8057
   254
        if (item && item->joystick) {
gabomdq@8057
   255
            SDL_PrivateJoystickButton(item->joystick, button, SDL_RELEASED);
slouken@11845
   256
        } else {
slouken@11845
   257
            SDL_SendKeyboardKey(SDL_RELEASED, button_to_scancode(button));
gabomdq@8057
   258
        }
slouken@10551
   259
        return 0;
gabomdq@8057
   260
    }
gabomdq@8057
   261
    
gabomdq@8057
   262
    return -1;
gabomdq@8057
   263
}
gabomdq@8057
   264
gabomdq@8057
   265
int
gabomdq@8057
   266
Android_OnJoy(int device_id, int axis, float value)
gabomdq@8057
   267
{
gabomdq@8057
   268
    /* Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] */
gabomdq@8057
   269
    SDL_joylist_item *item = JoystickByDeviceId(device_id);
gabomdq@8057
   270
    if (item && item->joystick) {
slouken@11532
   271
        SDL_PrivateJoystickAxis(item->joystick, axis, (Sint16) (32767.*value));
gabomdq@8057
   272
    }
gabomdq@8057
   273
    
gabomdq@8057
   274
    return 0;
gabomdq@8057
   275
}
gabomdq@8057
   276
dbrady@8140
   277
int
dbrady@8140
   278
Android_OnHat(int device_id, int hat_id, int x, int y)
dbrady@8140
   279
{
slouken@11921
   280
    const int DPAD_UP_MASK = (1 << SDL_CONTROLLER_BUTTON_DPAD_UP);
slouken@11921
   281
    const int DPAD_DOWN_MASK = (1 << SDL_CONTROLLER_BUTTON_DPAD_DOWN);
slouken@11921
   282
    const int DPAD_LEFT_MASK = (1 << SDL_CONTROLLER_BUTTON_DPAD_LEFT);
slouken@11921
   283
    const int DPAD_RIGHT_MASK = (1 << SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
dbrady@8140
   284
slouken@11921
   285
    if (x >= -1 && x <= 1 && y >= -1 && y <= 1) {
dbrady@8140
   286
        SDL_joylist_item *item = JoystickByDeviceId(device_id);
dbrady@8140
   287
        if (item && item->joystick) {
slouken@11921
   288
            int dpad_state = 0;
slouken@11921
   289
            int dpad_delta;
slouken@11921
   290
            if (x < 0) {
slouken@11921
   291
                dpad_state |= DPAD_LEFT_MASK;
slouken@11921
   292
            } else if (x > 0) {
slouken@11921
   293
                dpad_state |= DPAD_RIGHT_MASK;
slouken@11921
   294
            }
slouken@11921
   295
            if (y < 0) {
slouken@11921
   296
                dpad_state |= DPAD_UP_MASK;
slouken@11921
   297
            } else if (y > 0) {
slouken@11921
   298
                dpad_state |= DPAD_DOWN_MASK;
slouken@11921
   299
            }
slouken@11921
   300
slouken@11921
   301
            dpad_delta = (dpad_state ^ item->dpad_state);
slouken@11921
   302
            if (dpad_delta) {
slouken@11921
   303
                if (dpad_delta & DPAD_UP_MASK) {
slouken@11921
   304
                    SDL_PrivateJoystickButton(item->joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (dpad_state & DPAD_UP_MASK) ? SDL_PRESSED : SDL_RELEASED);
slouken@11921
   305
                }
slouken@11921
   306
                if (dpad_delta & DPAD_DOWN_MASK) {
slouken@11921
   307
                    SDL_PrivateJoystickButton(item->joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, (dpad_state & DPAD_DOWN_MASK) ? SDL_PRESSED : SDL_RELEASED);
slouken@11921
   308
                }
slouken@11921
   309
                if (dpad_delta & DPAD_LEFT_MASK) {
slouken@11921
   310
                    SDL_PrivateJoystickButton(item->joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (dpad_state & DPAD_LEFT_MASK) ? SDL_PRESSED : SDL_RELEASED);
slouken@11921
   311
                }
slouken@11921
   312
                if (dpad_delta & DPAD_RIGHT_MASK) {
slouken@11921
   313
                    SDL_PrivateJoystickButton(item->joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (dpad_state & DPAD_RIGHT_MASK) ? SDL_PRESSED : SDL_RELEASED);
slouken@11921
   314
                }
slouken@11921
   315
                item->dpad_state = dpad_state;
slouken@11921
   316
            }
dbrady@8140
   317
        }
dbrady@8140
   318
        return 0;
dbrady@8140
   319
    }
dbrady@8140
   320
dbrady@8140
   321
    return -1;
dbrady@8140
   322
}
dbrady@8140
   323
gabomdq@8057
   324
gabomdq@8057
   325
int
slouken@11921
   326
Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, SDL_bool is_accelerometer, int button_mask, int naxes, int nhats, int nballs)
gabomdq@8057
   327
{
slouken@11921
   328
    SDL_joylist_item *item;
gabomdq@8057
   329
    SDL_JoystickGUID guid;
slouken@11921
   330
    Uint16 *guid16 = (Uint16 *)guid.data;
slouken@11921
   331
    int i;
slouken@11921
   332
    int axis_mask;
slouken@11921
   333
slouken@11845
   334
slouken@11845
   335
    if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) {
slouken@11845
   336
        /* Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input */
slouken@11845
   337
        if (naxes < 2 && nhats < 1) {
slouken@11845
   338
            return -1;
slouken@11845
   339
        }
slouken@11845
   340
    }
gabomdq@8057
   341
    
slouken@11845
   342
    if (JoystickByDeviceId(device_id) != NULL || name == NULL) {
gabomdq@8057
   343
        return -1;
gabomdq@8057
   344
    }
slouken@12088
   345
slouken@12088
   346
#ifdef SDL_JOYSTICK_HIDAPI
slouken@12115
   347
    if (HIDAPI_IsDevicePresent(vendor_id, product_id, 0)) {
slouken@12088
   348
        /* The HIDAPI driver is taking care of this device */
slouken@12088
   349
        return -1;
slouken@12088
   350
    }
slouken@12088
   351
#endif
slouken@12088
   352
slouken@11921
   353
#ifdef DEBUG_JOYSTICK
slouken@11921
   354
    SDL_Log("Joystick: %s, descriptor %s, vendor = 0x%.4x, product = 0x%.4x, %d axes, %d hats\n", name, desc, vendor_id, product_id, naxes, nhats);
slouken@11921
   355
#endif
slouken@11921
   356
slouken@11921
   357
    /* Add the available buttons and axes
slouken@11921
   358
       The axis mask should probably come from Java where there is more information about the axes...
slouken@11921
   359
     */
slouken@11921
   360
    axis_mask = 0;
slouken@11921
   361
    if (!is_accelerometer) {
slouken@11921
   362
        if (naxes >= 2) {
slouken@11921
   363
            axis_mask |= ((1 << SDL_CONTROLLER_AXIS_LEFTX) | (1 << SDL_CONTROLLER_AXIS_LEFTY));
slouken@11921
   364
        }
slouken@11921
   365
        if (naxes >= 4) {
slouken@11921
   366
            axis_mask |= ((1 << SDL_CONTROLLER_AXIS_RIGHTX) | (1 << SDL_CONTROLLER_AXIS_RIGHTY));
slouken@11921
   367
        }
slouken@11921
   368
        if (naxes >= 6) {
slouken@11921
   369
            axis_mask |= ((1 << SDL_CONTROLLER_AXIS_TRIGGERLEFT) | (1 << SDL_CONTROLLER_AXIS_TRIGGERRIGHT));
slouken@11921
   370
        }
slouken@11921
   371
    }
slouken@11921
   372
slouken@11921
   373
    if (nhats > 0) {
slouken@11921
   374
        /* Hat is translated into DPAD buttons */
slouken@11921
   375
        button_mask |= ((1 << SDL_CONTROLLER_BUTTON_DPAD_UP) |
slouken@11921
   376
                        (1 << SDL_CONTROLLER_BUTTON_DPAD_DOWN) |
slouken@11921
   377
                        (1 << SDL_CONTROLLER_BUTTON_DPAD_LEFT) |
slouken@11921
   378
                        (1 << SDL_CONTROLLER_BUTTON_DPAD_RIGHT));
slouken@11921
   379
        nhats = 0;
slouken@11921
   380
    }
slouken@11921
   381
slouken@11921
   382
    SDL_memset(guid.data, 0, sizeof(guid.data));
slouken@11921
   383
slouken@11921
   384
    /* We only need 16 bits for each of these; space them out to fill 128. */
slouken@11921
   385
    /* Byteswap so devices get same GUID on little/big endian platforms. */
slouken@12088
   386
    *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH);
slouken@11921
   387
    *guid16++ = 0;
slouken@11921
   388
slouken@11921
   389
    if (vendor_id && product_id) {
slouken@11921
   390
        *guid16++ = SDL_SwapLE16(vendor_id);
slouken@11921
   391
        *guid16++ = 0;
slouken@11921
   392
        *guid16++ = SDL_SwapLE16(product_id);
slouken@11921
   393
        *guid16++ = 0;
slouken@11921
   394
    } else {
slouken@11921
   395
        Uint32 crc = crc32(desc, SDL_strlen(desc));
slouken@11921
   396
        SDL_memcpy(guid16, desc, SDL_min(2*sizeof(*guid16), SDL_strlen(desc)));
slouken@11921
   397
        guid16 += 2;
slouken@11921
   398
        *(Uint32 *)guid16 = SDL_SwapLE32(crc);
slouken@11921
   399
        guid16 += 2;
slouken@11921
   400
    }
slouken@11921
   401
slouken@11921
   402
    *guid16++ = SDL_SwapLE16(button_mask);
slouken@11921
   403
    *guid16++ = SDL_SwapLE16(axis_mask);
gabomdq@8057
   404
gabomdq@8057
   405
    item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
gabomdq@8057
   406
    if (item == NULL) {
gabomdq@8057
   407
        return -1;
gabomdq@8057
   408
    }
gabomdq@8057
   409
gabomdq@8057
   410
    SDL_zerop(item);
gabomdq@8057
   411
    item->guid = guid;
gabomdq@8057
   412
    item->device_id = device_id;
gabomdq@8057
   413
    item->name = SDL_strdup(name);
slouken@11532
   414
    if (item->name == NULL) {
gabomdq@8057
   415
         SDL_free(item);
gabomdq@8057
   416
         return -1;
gabomdq@8057
   417
    }
gabomdq@8057
   418
    
gabomdq@8057
   419
    item->is_accelerometer = is_accelerometer;
slouken@11921
   420
    if (button_mask == 0xFFFFFFFF) {
gabomdq@8057
   421
        item->nbuttons = ANDROID_MAX_NBUTTONS;
slouken@11921
   422
    } else {
slouken@11921
   423
        for (i = 0; i < sizeof(button_mask)*8; ++i) {
slouken@11921
   424
            if (button_mask & (1 << i)) {
slouken@11921
   425
                item->nbuttons = i+1;
slouken@11921
   426
            }
slouken@11921
   427
        }
gabomdq@8057
   428
    }
gabomdq@8057
   429
    item->naxes = naxes;
gabomdq@8057
   430
    item->nhats = nhats;
gabomdq@8057
   431
    item->nballs = nballs;
slouken@12088
   432
    item->device_instance = SDL_GetNextJoystickInstanceID();
gabomdq@8057
   433
    if (SDL_joylist_tail == NULL) {
gabomdq@8057
   434
        SDL_joylist = SDL_joylist_tail = item;
gabomdq@8057
   435
    } else {
gabomdq@8057
   436
        SDL_joylist_tail->next = item;
gabomdq@8057
   437
        SDL_joylist_tail = item;
gabomdq@8057
   438
    }
gabomdq@8057
   439
gabomdq@8057
   440
    /* Need to increment the joystick count before we post the event */
gabomdq@8057
   441
    ++numjoysticks;
gabomdq@8057
   442
slouken@12088
   443
    SDL_PrivateJoystickAdded(item->device_instance);
gabomdq@8057
   444
philipp@9579
   445
#ifdef DEBUG_JOYSTICK
gabomdq@8057
   446
    SDL_Log("Added joystick %s with device_id %d", name, device_id);
philipp@9579
   447
#endif
gabomdq@8057
   448
gabomdq@8057
   449
    return numjoysticks;
gabomdq@8057
   450
}
gabomdq@8057
   451
gabomdq@8057
   452
int 
gabomdq@8057
   453
Android_RemoveJoystick(int device_id)
gabomdq@8057
   454
{
gabomdq@8057
   455
    SDL_joylist_item *item = SDL_joylist;
gabomdq@8057
   456
    SDL_joylist_item *prev = NULL;
gabomdq@8057
   457
    
gabomdq@8057
   458
    /* Don't call JoystickByDeviceId here or there'll be an infinite loop! */
gabomdq@8057
   459
    while (item != NULL) {
gabomdq@8057
   460
        if (item->device_id == device_id) {
gabomdq@8057
   461
            break;
gabomdq@8057
   462
        }
gabomdq@8057
   463
        prev = item;
gabomdq@8057
   464
        item = item->next;
gabomdq@8057
   465
    }
gabomdq@8057
   466
    
gabomdq@8057
   467
    if (item == NULL) {
gabomdq@8057
   468
        return -1;
gabomdq@8057
   469
    }
gabomdq@8057
   470
gabomdq@8119
   471
    if (item->joystick) {
gabomdq@8119
   472
        item->joystick->hwdata = NULL;
gabomdq@8119
   473
    }
gabomdq@8119
   474
        
gabomdq@8057
   475
    if (prev != NULL) {
gabomdq@8057
   476
        prev->next = item->next;
gabomdq@8057
   477
    } else {
gabomdq@8057
   478
        SDL_assert(SDL_joylist == item);
gabomdq@8057
   479
        SDL_joylist = item->next;
gabomdq@8057
   480
    }
gabomdq@8057
   481
    if (item == SDL_joylist_tail) {
gabomdq@8057
   482
        SDL_joylist_tail = prev;
gabomdq@8057
   483
    }
gabomdq@8057
   484
gabomdq@8057
   485
    /* Need to decrement the joystick count before we post the event */
gabomdq@8057
   486
    --numjoysticks;
gabomdq@8057
   487
slouken@10226
   488
    SDL_PrivateJoystickRemoved(item->device_instance);
gabomdq@8057
   489
philipp@9579
   490
#ifdef DEBUG_JOYSTICK
gabomdq@8057
   491
    SDL_Log("Removed joystick with device_id %d", device_id);
philipp@9579
   492
#endif
gabomdq@8057
   493
    
gabomdq@8057
   494
    SDL_free(item->name);
gabomdq@8057
   495
    SDL_free(item);
philipp@10073
   496
    return numjoysticks;
gabomdq@8057
   497
}
gabomdq@8057
   498
gabomdq@8057
   499
slouken@12088
   500
static void ANDROID_JoystickDetect();
slouken@12088
   501
slouken@12088
   502
static int
slouken@12088
   503
ANDROID_JoystickInit(void)
slouken@11532
   504
{
slouken@12088
   505
    ANDROID_JoystickDetect();
gabomdq@7907
   506
    
slouken@10499
   507
    if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
gabomdq@8057
   508
        /* Default behavior, accelerometer as joystick */
slouken@11921
   509
        Android_AddJoystick(ANDROID_ACCELEROMETER_DEVICE_ID, ANDROID_ACCELEROMETER_NAME, ANDROID_ACCELEROMETER_NAME, 0, 0, SDL_TRUE, 0, 3, 0, 0);
gabomdq@7907
   510
    }
slouken@12088
   511
    return 0;
gabomdq@8057
   512
gabomdq@7041
   513
}
gabomdq@7041
   514
slouken@12088
   515
static int
slouken@12088
   516
ANDROID_JoystickGetCount(void)
gabomdq@7041
   517
{
gabomdq@8057
   518
    return numjoysticks;
gabomdq@7041
   519
}
gabomdq@7041
   520
slouken@12088
   521
static void
slouken@12088
   522
ANDROID_JoystickDetect(void)
gabomdq@7041
   523
{
gabomdq@8057
   524
    /* Support for device connect/disconnect is API >= 16 only,
gabomdq@8060
   525
     * so we poll every three seconds
gabomdq@8057
   526
     * Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html
gabomdq@8057
   527
     */
gabomdq@8060
   528
    static Uint32 timeout = 0;
slouken@11671
   529
    if (!timeout || SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
gabomdq@8060
   530
        timeout = SDL_GetTicks() + 3000;
gabomdq@8060
   531
        Android_JNI_PollInputDevices();
gabomdq@8060
   532
    }
gabomdq@7041
   533
}
gabomdq@7041
   534
gabomdq@8057
   535
static SDL_joylist_item *
gabomdq@8057
   536
JoystickByDevIndex(int device_index)
gabomdq@8057
   537
{
gabomdq@8057
   538
    SDL_joylist_item *item = SDL_joylist;
gabomdq@8057
   539
gabomdq@8057
   540
    if ((device_index < 0) || (device_index >= numjoysticks)) {
gabomdq@8057
   541
        return NULL;
gabomdq@8057
   542
    }
gabomdq@8057
   543
gabomdq@8057
   544
    while (device_index > 0) {
gabomdq@8057
   545
        SDL_assert(item != NULL);
gabomdq@8057
   546
        device_index--;
gabomdq@8057
   547
        item = item->next;
gabomdq@8057
   548
    }
gabomdq@8057
   549
gabomdq@8057
   550
    return item;
gabomdq@8057
   551
}
gabomdq@8057
   552
gabomdq@8057
   553
static SDL_joylist_item *
gabomdq@8057
   554
JoystickByDeviceId(int device_id)
gabomdq@8057
   555
{
gabomdq@8057
   556
    SDL_joylist_item *item = SDL_joylist;
gabomdq@8057
   557
gabomdq@8057
   558
    while (item != NULL) {
gabomdq@8057
   559
        if (item->device_id == device_id) {
gabomdq@8057
   560
            return item;
gabomdq@8057
   561
        }
gabomdq@8057
   562
        item = item->next;
gabomdq@8057
   563
    }
gabomdq@8057
   564
    
gabomdq@8057
   565
    /* Joystick not found, try adding it */
slouken@12088
   566
    ANDROID_JoystickDetect();
gabomdq@8057
   567
    
gabomdq@8057
   568
    while (item != NULL) {
gabomdq@8057
   569
        if (item->device_id == device_id) {
gabomdq@8057
   570
            return item;
gabomdq@8057
   571
        }
gabomdq@8057
   572
        item = item->next;
gabomdq@8057
   573
    }
gabomdq@8057
   574
gabomdq@8057
   575
    return NULL;
gabomdq@7041
   576
}
gabomdq@7041
   577
slouken@12088
   578
static const char *
slouken@12088
   579
ANDROID_JoystickGetDeviceName(int device_index)
gabomdq@7041
   580
{
gabomdq@8057
   581
    return JoystickByDevIndex(device_index)->name;
gabomdq@7041
   582
}
gabomdq@7041
   583
slouken@12359
   584
static int
slouken@12359
   585
ANDROID_JoystickGetDevicePlayerIndex(int device_index)
slouken@12359
   586
{
slouken@12359
   587
    return -1;
slouken@12359
   588
}
slouken@12359
   589
slouken@12088
   590
static SDL_JoystickGUID
slouken@12088
   591
ANDROID_JoystickGetDeviceGUID(int device_index)
slouken@12088
   592
{
slouken@12088
   593
    return JoystickByDevIndex(device_index)->guid;
slouken@12088
   594
}
slouken@12088
   595
slouken@12088
   596
static SDL_JoystickID
slouken@12088
   597
ANDROID_JoystickGetDeviceInstanceID(int device_index)
gabomdq@7041
   598
{
gabomdq@8057
   599
    return JoystickByDevIndex(device_index)->device_instance;
gabomdq@7041
   600
}
gabomdq@7041
   601
slouken@12088
   602
static int
slouken@12088
   603
ANDROID_JoystickOpen(SDL_Joystick * joystick, int device_index)
gabomdq@7041
   604
{
gabomdq@8057
   605
    SDL_joylist_item *item = JoystickByDevIndex(device_index);
gabomdq@8057
   606
slouken@11532
   607
    if (item == NULL) {
gabomdq@8057
   608
        return SDL_SetError("No such device");
slouken@7191
   609
    }
gabomdq@8057
   610
    
gabomdq@8057
   611
    if (item->joystick != NULL) {
gabomdq@8057
   612
        return SDL_SetError("Joystick already opened");
gabomdq@8057
   613
    }
gabomdq@8057
   614
gabomdq@8057
   615
    joystick->instance_id = item->device_instance;
gabomdq@8057
   616
    joystick->hwdata = (struct joystick_hwdata *) item;
gabomdq@8057
   617
    item->joystick = joystick;
gabomdq@8057
   618
    joystick->nhats = item->nhats;
gabomdq@8057
   619
    joystick->nballs = item->nballs;
gabomdq@8057
   620
    joystick->nbuttons = item->nbuttons;
gabomdq@8057
   621
    joystick->naxes = item->naxes;
gabomdq@8057
   622
gabomdq@8057
   623
    return (0);
gabomdq@7041
   624
}
gabomdq@7041
   625
slouken@12088
   626
static int
slouken@12088
   627
ANDROID_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
slouken@12088
   628
{
slouken@12088
   629
    return SDL_Unsupported();
slouken@12088
   630
}
slouken@12088
   631
slouken@12088
   632
static void
slouken@12088
   633
ANDROID_JoystickUpdate(SDL_Joystick * joystick)
gabomdq@7041
   634
{
slouken@11532
   635
    SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
gabomdq@7041
   636
slouken@11532
   637
    if (item == NULL) {
slouken@11532
   638
        return;
slouken@11532
   639
    }
slouken@11532
   640
 
slouken@11532
   641
    if (item->is_accelerometer) {
slouken@11532
   642
        int i;
slouken@11532
   643
        Sint16 value;
slouken@11532
   644
        float values[3];
slouken@11532
   645
slouken@11532
   646
        if (Android_JNI_GetAccelerometerValues(values)) {
slouken@11532
   647
            for (i = 0; i < 3; i++) {
slouken@11532
   648
                if (values[i] > 1.0f) {
slouken@11532
   649
                    values[i] = 1.0f;
slouken@11532
   650
                } else if (values[i] < -1.0f) {
slouken@11532
   651
                    values[i] = -1.0f;
gabomdq@8057
   652
                }
slouken@11532
   653
slouken@11532
   654
                value = (Sint16)(values[i] * 32767.0f);
slouken@11532
   655
                SDL_PrivateJoystickAxis(item->joystick, i, value);
gabomdq@8057
   656
            }
gabomdq@7041
   657
        }
gabomdq@7041
   658
    }
gabomdq@7041
   659
}
gabomdq@7041
   660
slouken@12088
   661
static void
slouken@12088
   662
ANDROID_JoystickClose(SDL_Joystick * joystick)
gabomdq@7041
   663
{
philipp@10219
   664
    SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
philipp@10223
   665
    if (item) {
philipp@10223
   666
        item->joystick = NULL;
philipp@10223
   667
    }
gabomdq@7041
   668
}
gabomdq@7041
   669
slouken@12088
   670
static void
slouken@12088
   671
ANDROID_JoystickQuit(void)
gabomdq@7041
   672
{
slouken@11532
   673
/* We don't have any way to scan for joysticks at init, so don't wipe the list
slouken@11532
   674
 * of joysticks here in case this is a reinit.
slouken@11532
   675
 */
slouken@11532
   676
#if 0
gabomdq@8057
   677
    SDL_joylist_item *item = NULL;
gabomdq@8057
   678
    SDL_joylist_item *next = NULL;
gabomdq@8057
   679
gabomdq@8057
   680
    for (item = SDL_joylist; item; item = next) {
gabomdq@8057
   681
        next = item->next;
gabomdq@8057
   682
        SDL_free(item->name);
gabomdq@8057
   683
        SDL_free(item);
gabomdq@8057
   684
    }
gabomdq@8057
   685
gabomdq@8057
   686
    SDL_joylist = SDL_joylist_tail = NULL;
gabomdq@8057
   687
gabomdq@8057
   688
    numjoysticks = 0;
slouken@11532
   689
#endif /* 0 */
gabomdq@7041
   690
}
gabomdq@7041
   691
slouken@12088
   692
SDL_JoystickDriver SDL_ANDROID_JoystickDriver =
gabomdq@7041
   693
{
slouken@12088
   694
    ANDROID_JoystickInit,
slouken@12088
   695
    ANDROID_JoystickGetCount,
slouken@12088
   696
    ANDROID_JoystickDetect,
slouken@12088
   697
    ANDROID_JoystickGetDeviceName,
slouken@12359
   698
    ANDROID_JoystickGetDevicePlayerIndex,
slouken@12088
   699
    ANDROID_JoystickGetDeviceGUID,
slouken@12088
   700
    ANDROID_JoystickGetDeviceInstanceID,
slouken@12088
   701
    ANDROID_JoystickOpen,
slouken@12088
   702
    ANDROID_JoystickRumble,
slouken@12088
   703
    ANDROID_JoystickUpdate,
slouken@12088
   704
    ANDROID_JoystickClose,
slouken@12088
   705
    ANDROID_JoystickQuit,
slouken@12088
   706
};
gabomdq@7907
   707
gabomdq@7041
   708
#endif /* SDL_JOYSTICK_ANDROID */
gabomdq@7041
   709
gabomdq@7041
   710
/* vi: set ts=4 sw=4 expandtab: */