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