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