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