src/joystick/android/SDL_sysjoystick.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Mon, 18 Nov 2013 23:38:59 +0100
changeset 8008 5e5819ca19db
parent 7956 965b7e09c5a8
child 8013 109299fe73ad
permissions -rw-r--r--
Fixed implicit function declaration warning in joystick source for Android.
     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             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);
   132             return -1;
   133             break;
   134     }
   135     
   136     /* This is here in case future generations, probably with six fingers per hand, 
   137      * happily add new cases up above and forget to update the max number of buttons. 
   138      */
   139     SDL_assert(button < ANDROID_MAX_NBUTTONS);
   140     return button;
   141     
   142 }
   143 
   144 /* Function to scan the system for joysticks.
   145  * This function should set SDL_numjoysticks to the number of available
   146  * joysticks.  Joystick 0 should be the system default joystick.
   147  * It should return 0, or -1 on an unrecoverable fatal error.
   148  */
   149 int
   150 SDL_SYS_JoystickInit(void)
   151 {
   152     int i = 0;
   153     const char *env;
   154     
   155     env = SDL_GetHint(SDL_HINT_ACCEL_AS_JOY);
   156     if (env && !SDL_atoi(env))
   157         SYS_accelAsJoy = SDL_FALSE;
   158     else
   159         SYS_accelAsJoy = SDL_TRUE; /* Default behavior */
   160     
   161     SYS_numjoysticks = Android_JNI_GetNumJoysticks();
   162     if (SYS_accelAsJoy) {
   163         SYS_numjoysticks++;
   164     }
   165     SYS_Joysticks = (SDL_Joystick **)SDL_malloc(SYS_numjoysticks*sizeof(SDL_Joystick *));
   166     if (SYS_Joysticks == NULL)
   167     {
   168         return SDL_OutOfMemory();
   169     }
   170     SYS_JoystickNames = (char **)SDL_malloc(SYS_numjoysticks*sizeof(char *));
   171     if (SYS_JoystickNames == NULL)
   172     {
   173         SDL_free(SYS_Joysticks);
   174         SYS_Joysticks = NULL;
   175         return SDL_OutOfMemory();
   176     }
   177     SDL_memset(SYS_JoystickNames, 0, (SYS_numjoysticks*sizeof(char *)));
   178     SDL_memset(SYS_Joysticks, 0, (SYS_numjoysticks*sizeof(SDL_Joystick *)));
   179     
   180     for (i = 0; i < SYS_numjoysticks; i++)
   181     {
   182         if ( SYS_accelAsJoy && i == ANDROID_ACCELEROMETER_INDEX ) {
   183             SYS_JoystickNames[i] = ANDROID_ACCELEROMETER_NAME;
   184         } else {
   185             SYS_JoystickNames[i] = Android_JNI_GetJoystickName(i);
   186         }
   187     }
   188    
   189     return (SYS_numjoysticks);
   190 }
   191 
   192 int SDL_SYS_NumJoysticks()
   193 {
   194     return SYS_numjoysticks;
   195 }
   196 
   197 void SDL_SYS_JoystickDetect()
   198 {
   199 }
   200 
   201 /* TODO: Hotplugging support */
   202 SDL_bool SDL_SYS_JoystickNeedsPolling()
   203 {
   204     return SDL_FALSE;
   205 }
   206 
   207 /* Function to get the device-dependent name of a joystick */
   208 const char *
   209 SDL_SYS_JoystickNameForDeviceIndex(int device_index)
   210 {
   211     return SYS_JoystickNames[device_index];
   212 }
   213 
   214 /* Function to perform the mapping from device index to the instance id for this index */
   215 SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
   216 {
   217     return device_index;
   218 }
   219 
   220 /* Function to open a joystick for use.
   221    The joystick to open is specified by the index field of the joystick.
   222    This should fill the nbuttons and naxes fields of the joystick structure.
   223    It returns 0, or -1 if there is an error.
   224  */
   225 int
   226 SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
   227 {
   228     if (device_index < SYS_numjoysticks) {
   229         joystick->nhats = 0;
   230         joystick->nballs = 0;
   231         if (SYS_accelAsJoy && device_index == ANDROID_ACCELEROMETER_INDEX) {
   232             joystick->nbuttons = 0;
   233             joystick->naxes = 3;
   234         } else {
   235             /* FIXME: Get the real number of buttons in the device? */
   236             joystick->nbuttons = ANDROID_MAX_NBUTTONS;
   237             joystick->naxes = Android_JNI_GetJoystickAxes(device_index);
   238         }
   239         
   240         SYS_Joysticks[device_index] = joystick;
   241         return 0;
   242     } else {
   243         return SDL_SetError("No joystick available with that index");
   244     }
   245 }
   246 
   247 /* Function to determine is this joystick is attached to the system right now */
   248 SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
   249 {
   250     return SDL_TRUE;
   251 }
   252 
   253 /* Function to update the state of a joystick - called as a device poll.
   254  * This function shouldn't update the joystick structure directly,
   255  * but instead should call SDL_PrivateJoystick*() to deliver events
   256  * and update joystick device state.
   257  */
   258 void
   259 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
   260 {
   261     int i;
   262     Sint16 value;
   263     float values[3];
   264 
   265     if (SYS_accelAsJoy && Android_JNI_GetAccelerometerValues(values) &&
   266         joystick->instance_id == ANDROID_ACCELEROMETER_INDEX) {
   267         for ( i = 0; i < 3; i++ ) {
   268             value = (Sint16)(values[i] * 32767.0f);
   269             SDL_PrivateJoystickAxis(joystick, i, value);
   270         }
   271     }
   272 }
   273 
   274 /* Function to close a joystick after use */
   275 void
   276 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
   277 {
   278 }
   279 
   280 /* Function to perform any system-specific joystick related cleanup */
   281 void
   282 SDL_SYS_JoystickQuit(void)
   283 {
   284     SDL_free(SYS_JoystickNames);
   285     SDL_free(SYS_Joysticks);
   286     SYS_JoystickNames = NULL;
   287     SYS_Joysticks = NULL;
   288 }
   289 
   290 SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
   291 {
   292     SDL_JoystickGUID guid;
   293     /* the GUID is just the first 16 chars of the name for now */
   294     const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
   295     SDL_zero( guid );
   296     SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
   297     return guid;
   298 }
   299 
   300 SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
   301 {
   302     SDL_JoystickGUID guid;
   303     /* the GUID is just the first 16 chars of the name for now */
   304     const char *name = joystick->name;
   305     SDL_zero( guid );
   306     SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
   307     return guid;
   308 }
   309 
   310 int
   311 Android_OnPadDown(int padId, int keycode)
   312 {
   313     int button = keycode_to_SDL(keycode);
   314     if (button >= 0) {
   315         SDL_PrivateJoystickButton(SYS_Joysticks[padId], button , SDL_PRESSED);
   316     }
   317     
   318     return 0;
   319 }
   320 
   321 int
   322 Android_OnPadUp(int padId, int keycode)
   323 {
   324     int button = keycode_to_SDL(keycode);
   325     if (button >= 0) {
   326         SDL_PrivateJoystickButton(SYS_Joysticks[padId], button, SDL_RELEASED);
   327     }
   328     
   329     return 0;
   330 }
   331 
   332 int
   333 Android_OnJoy(int joyId, int axis, float value)
   334 {
   335     /* Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] */
   336     /* TODO: Are the reported values right? */
   337     SDL_PrivateJoystickAxis(SYS_Joysticks[joyId], axis, (Sint16) (32767.*value) );
   338     
   339     return 0;
   340 }
   341 
   342 #endif /* SDL_JOYSTICK_ANDROID */
   343 
   344 /* vi: set ts=4 sw=4 expandtab: */