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