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