Atlas - SDL_sysjoystick.c
Home / ext / SDL / src / joystick / android Lines: 1 | Size: 20134 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2026 Sam Lantinga <[email protected]> 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#include "SDL_internal.h" 22 23#ifdef SDL_JOYSTICK_ANDROID 24 25#include <stdio.h> // For the definition of NULL 26 27#include "SDL_sysjoystick_c.h" 28#include "../SDL_joystick_c.h" 29#include "../../events/SDL_keyboard_c.h" 30#include "../../core/android/SDL_android.h" 31#include "../hidapi/SDL_hidapijoystick_c.h" 32 33#include "android/keycodes.h" 34 35// As of platform android-14, android/keycodes.h is missing these defines 36#ifndef AKEYCODE_BUTTON_1 37#define AKEYCODE_BUTTON_1 188 38#define AKEYCODE_BUTTON_2 189 39#define AKEYCODE_BUTTON_3 190 40#define AKEYCODE_BUTTON_4 191 41#define AKEYCODE_BUTTON_5 192 42#define AKEYCODE_BUTTON_6 193 43#define AKEYCODE_BUTTON_7 194 44#define AKEYCODE_BUTTON_8 195 45#define AKEYCODE_BUTTON_9 196 46#define AKEYCODE_BUTTON_10 197 47#define AKEYCODE_BUTTON_11 198 48#define AKEYCODE_BUTTON_12 199 49#define AKEYCODE_BUTTON_13 200 50#define AKEYCODE_BUTTON_14 201 51#define AKEYCODE_BUTTON_15 202 52#define AKEYCODE_BUTTON_16 203 53#endif 54 55#define ANDROID_MAX_NBUTTONS 36 56 57static SDL_joylist_item *JoystickByDeviceId(int device_id); 58 59static SDL_joylist_item *SDL_joylist = NULL; 60static SDL_joylist_item *SDL_joylist_tail = NULL; 61static int numjoysticks = 0; 62 63/* Function to convert Android keyCodes into SDL ones. 64 * This code manipulation is done to get a sequential list of codes. 65 * FIXME: This is only suited for the case where we use a fixed number of buttons determined by ANDROID_MAX_NBUTTONS 66 */ 67static int keycode_to_SDL(int keycode) 68{ 69 // FIXME: If this function gets too unwieldy in the future, replace with a lookup table 70 int button = 0; 71 switch (keycode) { 72 // Some gamepad buttons (API 9) 73 case AKEYCODE_BUTTON_A: 74 button = SDL_GAMEPAD_BUTTON_SOUTH; 75 break; 76 case AKEYCODE_BUTTON_B: 77 button = SDL_GAMEPAD_BUTTON_EAST; 78 break; 79 case AKEYCODE_BUTTON_X: 80 button = SDL_GAMEPAD_BUTTON_WEST; 81 break; 82 case AKEYCODE_BUTTON_Y: 83 button = SDL_GAMEPAD_BUTTON_NORTH; 84 break; 85 case AKEYCODE_BUTTON_L1: 86 button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; 87 break; 88 case AKEYCODE_BUTTON_R1: 89 button = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER; 90 break; 91 case AKEYCODE_BUTTON_THUMBL: 92 button = SDL_GAMEPAD_BUTTON_LEFT_STICK; 93 break; 94 case AKEYCODE_BUTTON_THUMBR: 95 button = SDL_GAMEPAD_BUTTON_RIGHT_STICK; 96 break; 97 case AKEYCODE_MENU: 98 case AKEYCODE_BUTTON_START: 99 button = SDL_GAMEPAD_BUTTON_START; 100 break; 101 case AKEYCODE_BACK: 102 case AKEYCODE_BUTTON_SELECT: 103 button = SDL_GAMEPAD_BUTTON_BACK; 104 break; 105 case AKEYCODE_BUTTON_MODE: 106 button = SDL_GAMEPAD_BUTTON_GUIDE; 107 break; 108 case AKEYCODE_BUTTON_L2: 109 case AKEYCODE_MEDIA_RECORD: 110 button = SDL_GAMEPAD_BUTTON_MISC1; 111 break; 112 case AKEYCODE_BUTTON_R2: 113 button = 16; 114 break; 115 case AKEYCODE_BUTTON_C: 116 button = 17; 117 break; 118 case AKEYCODE_BUTTON_Z: 119 button = 18; 120 break; 121 122 // D-Pad key codes (API 1) 123 case AKEYCODE_DPAD_UP: 124 button = SDL_GAMEPAD_BUTTON_DPAD_UP; 125 break; 126 case AKEYCODE_DPAD_DOWN: 127 button = SDL_GAMEPAD_BUTTON_DPAD_DOWN; 128 break; 129 case AKEYCODE_DPAD_LEFT: 130 button = SDL_GAMEPAD_BUTTON_DPAD_LEFT; 131 break; 132 case AKEYCODE_DPAD_RIGHT: 133 button = SDL_GAMEPAD_BUTTON_DPAD_RIGHT; 134 break; 135 case AKEYCODE_DPAD_CENTER: 136 // This is handled better by applications as the A button 137 // button = 19; 138 button = SDL_GAMEPAD_BUTTON_SOUTH; 139 break; 140 141 // More gamepad buttons (API 12), these get mapped to 20...35 142 case AKEYCODE_BUTTON_1: 143 case AKEYCODE_BUTTON_2: 144 case AKEYCODE_BUTTON_3: 145 case AKEYCODE_BUTTON_4: 146 case AKEYCODE_BUTTON_5: 147 case AKEYCODE_BUTTON_6: 148 case AKEYCODE_BUTTON_7: 149 case AKEYCODE_BUTTON_8: 150 case AKEYCODE_BUTTON_9: 151 case AKEYCODE_BUTTON_10: 152 case AKEYCODE_BUTTON_11: 153 case AKEYCODE_BUTTON_12: 154 case AKEYCODE_BUTTON_13: 155 case AKEYCODE_BUTTON_14: 156 case AKEYCODE_BUTTON_15: 157 case AKEYCODE_BUTTON_16: 158 button = 20 + (keycode - AKEYCODE_BUTTON_1); 159 break; 160 161 default: 162 return -1; 163 // break; -Wunreachable-code-break 164 } 165 166 /* This is here in case future generations, probably with six fingers per hand, 167 * happily add new cases up above and forget to update the max number of buttons. 168 */ 169 SDL_assert(button < ANDROID_MAX_NBUTTONS); 170 return button; 171} 172 173static SDL_Scancode button_to_scancode(int button) 174{ 175 switch (button) { 176 case SDL_GAMEPAD_BUTTON_SOUTH: 177 return SDL_SCANCODE_RETURN; 178 case SDL_GAMEPAD_BUTTON_EAST: 179 return SDL_SCANCODE_ESCAPE; 180 case SDL_GAMEPAD_BUTTON_BACK: 181 return SDL_SCANCODE_ESCAPE; 182 case SDL_GAMEPAD_BUTTON_START: 183 return SDL_SCANCODE_MENU; 184 case SDL_GAMEPAD_BUTTON_DPAD_UP: 185 return SDL_SCANCODE_UP; 186 case SDL_GAMEPAD_BUTTON_DPAD_DOWN: 187 return SDL_SCANCODE_DOWN; 188 case SDL_GAMEPAD_BUTTON_DPAD_LEFT: 189 return SDL_SCANCODE_LEFT; 190 case SDL_GAMEPAD_BUTTON_DPAD_RIGHT: 191 return SDL_SCANCODE_RIGHT; 192 } 193 194 // Unsupported button 195 return SDL_SCANCODE_UNKNOWN; 196} 197 198bool Android_OnPadDown(int device_id, int keycode) 199{ 200 Uint64 timestamp = SDL_GetTicksNS(); 201 SDL_joylist_item *item; 202 int button = keycode_to_SDL(keycode); 203 if (button >= 0) { 204 SDL_LockJoysticks(); 205 item = JoystickByDeviceId(device_id); 206 if (item && item->joystick) { 207 SDL_SendJoystickButton(timestamp, item->joystick, button, true); 208 } else { 209 SDL_SendKeyboardKey(timestamp, SDL_GLOBAL_KEYBOARD_ID, keycode, button_to_scancode(button), true); 210 } 211 SDL_UnlockJoysticks(); 212 return true; 213 } 214 215 return false; 216} 217 218bool Android_OnPadUp(int device_id, int keycode) 219{ 220 Uint64 timestamp = SDL_GetTicksNS(); 221 SDL_joylist_item *item; 222 int button = keycode_to_SDL(keycode); 223 if (button >= 0) { 224 SDL_LockJoysticks(); 225 item = JoystickByDeviceId(device_id); 226 if (item && item->joystick) { 227 SDL_SendJoystickButton(timestamp, item->joystick, button, false); 228 } else { 229 SDL_SendKeyboardKey(timestamp, SDL_GLOBAL_KEYBOARD_ID, keycode, button_to_scancode(button), false); 230 } 231 SDL_UnlockJoysticks(); 232 return true; 233 } 234 235 return false; 236} 237 238bool Android_OnJoy(int device_id, int axis, float value) 239{ 240 Uint64 timestamp = SDL_GetTicksNS(); 241 // Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] 242 SDL_joylist_item *item; 243 244 SDL_LockJoysticks(); 245 item = JoystickByDeviceId(device_id); 246 if (item && item->joystick) { 247 SDL_SendJoystickAxis(timestamp, item->joystick, axis, (Sint16)(32767. * value)); 248 } 249 SDL_UnlockJoysticks(); 250 251 return true; 252} 253 254bool Android_OnHat(int device_id, int hat_id, int x, int y) 255{ 256 Uint64 timestamp = SDL_GetTicksNS(); 257 const int DPAD_UP_MASK = (1 << SDL_GAMEPAD_BUTTON_DPAD_UP); 258 const int DPAD_DOWN_MASK = (1 << SDL_GAMEPAD_BUTTON_DPAD_DOWN); 259 const int DPAD_LEFT_MASK = (1 << SDL_GAMEPAD_BUTTON_DPAD_LEFT); 260 const int DPAD_RIGHT_MASK = (1 << SDL_GAMEPAD_BUTTON_DPAD_RIGHT); 261 262 if (x >= -1 && x <= 1 && y >= -1 && y <= 1) { 263 SDL_joylist_item *item; 264 265 SDL_LockJoysticks(); 266 item = JoystickByDeviceId(device_id); 267 if (item && item->joystick) { 268 int dpad_state = 0; 269 int dpad_delta; 270 if (x < 0) { 271 dpad_state |= DPAD_LEFT_MASK; 272 } else if (x > 0) { 273 dpad_state |= DPAD_RIGHT_MASK; 274 } 275 if (y < 0) { 276 dpad_state |= DPAD_UP_MASK; 277 } else if (y > 0) { 278 dpad_state |= DPAD_DOWN_MASK; 279 } 280 281 dpad_delta = (dpad_state ^ item->dpad_state); 282 if (dpad_delta) { 283 if (dpad_delta & DPAD_UP_MASK) { 284 bool down = ((dpad_state & DPAD_UP_MASK) != 0); 285 SDL_SendJoystickButton(timestamp, item->joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, down); 286 } 287 if (dpad_delta & DPAD_DOWN_MASK) { 288 bool down = ((dpad_state & DPAD_DOWN_MASK) != 0); 289 SDL_SendJoystickButton(timestamp, item->joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, down); 290 } 291 if (dpad_delta & DPAD_LEFT_MASK) { 292 bool down = ((dpad_state & DPAD_LEFT_MASK) != 0); 293 SDL_SendJoystickButton(timestamp, item->joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, down); 294 } 295 if (dpad_delta & DPAD_RIGHT_MASK) { 296 bool down = ((dpad_state & DPAD_RIGHT_MASK) != 0); 297 SDL_SendJoystickButton(timestamp, item->joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, down); 298 } 299 item->dpad_state = dpad_state; 300 } 301 } 302 SDL_UnlockJoysticks(); 303 return true; 304 } 305 306 return false; 307} 308 309void Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats, bool can_rumble, bool has_rgb_led) 310{ 311 SDL_joylist_item *item; 312 SDL_GUID guid; 313 int i; 314 315 SDL_LockJoysticks(); 316 317 if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, true)) { 318 // Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input 319 if (naxes < 2 && nhats < 1) { 320 goto done; 321 } 322 } 323 324 if (JoystickByDeviceId(device_id) != NULL || !name) { 325 goto done; 326 } 327 328 if (SDL_JoystickHandledByAnotherDriver(&SDL_ANDROID_JoystickDriver, vendor_id, product_id, 0, name)) { 329 goto done; 330 } 331 332 if (SDL_ShouldIgnoreJoystick(vendor_id, product_id, 0, name)) { 333 goto done; 334 } 335 336#ifdef DEBUG_JOYSTICK 337 SDL_Log("Joystick: %s, descriptor %s, vendor = 0x%.4x, product = 0x%.4x, %d axes, %d hats", name, desc, vendor_id, product_id, naxes, nhats); 338#endif 339 340 if (nhats > 0) { 341 // Hat is translated into DPAD buttons 342 button_mask |= ((1 << SDL_GAMEPAD_BUTTON_DPAD_UP) | 343 (1 << SDL_GAMEPAD_BUTTON_DPAD_DOWN) | 344 (1 << SDL_GAMEPAD_BUTTON_DPAD_LEFT) | 345 (1 << SDL_GAMEPAD_BUTTON_DPAD_RIGHT)); 346 nhats = 0; 347 } 348 349 guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor_id, product_id, 0, NULL, desc, 0, 0); 350 351 // Update the GUID with capability bits 352 { 353 Uint16 *guid16 = (Uint16 *)guid.data; 354 guid16[6] = SDL_Swap16LE(button_mask); 355 guid16[7] = SDL_Swap16LE(axis_mask); 356 } 357 358 item = (SDL_joylist_item *)SDL_malloc(sizeof(SDL_joylist_item)); 359 if (!item) { 360 goto done; 361 } 362 363 SDL_zerop(item); 364 item->guid = guid; 365 item->device_id = device_id; 366 item->name = SDL_CreateJoystickName(vendor_id, product_id, NULL, name); 367 if (!item->name) { 368 SDL_free(item); 369 goto done; 370 } 371 372 if (button_mask == 0xFFFFFFFF) { 373 item->nbuttons = ANDROID_MAX_NBUTTONS; 374 } else { 375 for (i = 0; i < sizeof(button_mask) * 8; ++i) { 376 if (button_mask & (1 << i)) { 377 item->nbuttons = i + 1; 378 } 379 } 380 } 381 item->naxes = naxes; 382 item->nhats = nhats; 383 item->can_rumble = can_rumble; 384 item->has_rgb_led = has_rgb_led; 385 item->device_instance = SDL_GetNextObjectID(); 386 if (!SDL_joylist_tail) { 387 SDL_joylist = SDL_joylist_tail = item; 388 } else { 389 SDL_joylist_tail->next = item; 390 SDL_joylist_tail = item; 391 } 392 393 // Need to increment the joystick count before we post the event 394 ++numjoysticks; 395 396 SDL_PrivateJoystickAdded(item->device_instance); 397 398#ifdef DEBUG_JOYSTICK 399 SDL_Log("Added joystick %s with device_id %d", item->name, device_id); 400#endif 401 402done: 403 SDL_UnlockJoysticks(); 404} 405 406void Android_RemoveJoystick(int device_id) 407{ 408 SDL_joylist_item *item = SDL_joylist; 409 SDL_joylist_item *prev = NULL; 410 411 SDL_LockJoysticks(); 412 413 // Don't call JoystickByDeviceId here or there'll be an infinite loop! 414 while (item) { 415 if (item->device_id == device_id) { 416 break; 417 } 418 prev = item; 419 item = item->next; 420 } 421 422 if (!item) { 423 goto done; 424 } 425 426 if (item->joystick) { 427 item->joystick->hwdata = NULL; 428 } 429 430 if (prev) { 431 prev->next = item->next; 432 } else { 433 SDL_assert(SDL_joylist == item); 434 SDL_joylist = item->next; 435 } 436 if (item == SDL_joylist_tail) { 437 SDL_joylist_tail = prev; 438 } 439 440 // Need to decrement the joystick count before we post the event 441 --numjoysticks; 442 443 SDL_PrivateJoystickRemoved(item->device_instance); 444 445#ifdef DEBUG_JOYSTICK 446 SDL_Log("Removed joystick with device_id %d", device_id); 447#endif 448 449 SDL_free(item->name); 450 SDL_free(item); 451 452done: 453 SDL_UnlockJoysticks(); 454} 455 456static void ANDROID_JoystickDetect(void); 457 458static bool ANDROID_JoystickInit(void) 459{ 460 ANDROID_JoystickDetect(); 461 return true; 462} 463 464static int ANDROID_JoystickGetCount(void) 465{ 466 return numjoysticks; 467} 468 469static void ANDROID_JoystickDetect(void) 470{ 471 /* Support for device connect/disconnect is API >= 16 only, 472 * so we poll every three seconds 473 * Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html 474 */ 475 static Uint64 timeout = 0; 476 Uint64 now = SDL_GetTicks(); 477 if (!timeout || now >= timeout) { 478 timeout = now + 3000; 479 Android_JNI_PollInputDevices(); 480 } 481} 482 483static bool ANDROID_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) 484{ 485 // We don't override any other drivers 486 return false; 487} 488 489static SDL_joylist_item *GetJoystickByDevIndex(int device_index) 490{ 491 SDL_joylist_item *item = SDL_joylist; 492 493 if ((device_index < 0) || (device_index >= numjoysticks)) { 494 return NULL; 495 } 496 497 while (device_index > 0) { 498 SDL_assert(item != NULL); 499 device_index--; 500 item = item->next; 501 } 502 503 return item; 504} 505 506static SDL_joylist_item *JoystickByDeviceId(int device_id) 507{ 508 SDL_joylist_item *item = SDL_joylist; 509 510 while (item) { 511 if (item->device_id == device_id) { 512 return item; 513 } 514 item = item->next; 515 } 516 517 // Joystick not found, try adding it 518 ANDROID_JoystickDetect(); 519 520 while (item) { 521 if (item->device_id == device_id) { 522 return item; 523 } 524 item = item->next; 525 } 526 527 return NULL; 528} 529 530static const char *ANDROID_JoystickGetDeviceName(int device_index) 531{ 532 return GetJoystickByDevIndex(device_index)->name; 533} 534 535static const char *ANDROID_JoystickGetDevicePath(int device_index) 536{ 537 return NULL; 538} 539 540static int ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) 541{ 542 return -1; 543} 544 545static int ANDROID_JoystickGetDevicePlayerIndex(int device_index) 546{ 547 return -1; 548} 549 550static void ANDROID_JoystickSetDevicePlayerIndex(int device_index, int player_index) 551{ 552} 553 554static SDL_GUID ANDROID_JoystickGetDeviceGUID(int device_index) 555{ 556 return GetJoystickByDevIndex(device_index)->guid; 557} 558 559static SDL_JoystickID ANDROID_JoystickGetDeviceInstanceID(int device_index) 560{ 561 return GetJoystickByDevIndex(device_index)->device_instance; 562} 563 564static bool ANDROID_JoystickOpen(SDL_Joystick *joystick, int device_index) 565{ 566 SDL_joylist_item *item = GetJoystickByDevIndex(device_index); 567 568 if (!item) { 569 return SDL_SetError("No such device"); 570 } 571 572 if (item->joystick) { 573 return SDL_SetError("Joystick already opened"); 574 } 575 576 joystick->hwdata = (struct joystick_hwdata *)item; 577 item->joystick = joystick; 578 joystick->nhats = item->nhats; 579 joystick->nbuttons = item->nbuttons; 580 joystick->naxes = item->naxes; 581 582 if (item->can_rumble) { 583 SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true); 584 } 585 586 if (item->has_rgb_led) { 587 SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, true); 588 } 589 590 return true; 591} 592 593static bool ANDROID_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 594{ 595 SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata; 596 if (!item) { 597 return SDL_SetError("Rumble failed, device disconnected"); 598 } 599 if (!item->can_rumble) { 600 return SDL_Unsupported(); 601 } 602 603 float low_frequency_intensity = (float)low_frequency_rumble / SDL_MAX_UINT16; 604 float high_frequency_intensity = (float)high_frequency_rumble / SDL_MAX_UINT16; 605 Android_JNI_HapticRumble(item->device_id, low_frequency_intensity, high_frequency_intensity, 5000); 606 return true; 607} 608 609static bool ANDROID_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) 610{ 611 return SDL_Unsupported(); 612} 613 614static bool ANDROID_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 615{ 616 SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata; 617 if (!item) { 618 return SDL_SetError("SetLED failed, device disconnected"); 619 } 620 if (!item->has_rgb_led) { 621 return SDL_Unsupported(); 622 } 623 Android_JNI_JoystickSetLED(item->device_id, red, green, blue); 624 return true; 625} 626 627static bool ANDROID_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) 628{ 629 return SDL_Unsupported(); 630} 631 632static bool ANDROID_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled) 633{ 634 return SDL_Unsupported(); 635} 636 637static void ANDROID_JoystickUpdate(SDL_Joystick *joystick) 638{ 639} 640 641static void ANDROID_JoystickClose(SDL_Joystick *joystick) 642{ 643 SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata; 644 if (item) { 645 item->joystick = NULL; 646 } 647} 648 649static void ANDROID_JoystickQuit(void) 650{ 651/* We don't have any way to scan for joysticks at init, so don't wipe the list 652 * of joysticks here in case this is a reinit. 653 */ 654#if 0 655 SDL_joylist_item *item = NULL; 656 SDL_joylist_item *next = NULL; 657 658 for (item = SDL_joylist; item; item = next) { 659 next = item->next; 660 SDL_free(item->name); 661 SDL_free(item); 662 } 663 664 SDL_joylist = SDL_joylist_tail = NULL; 665 666 numjoysticks = 0; 667#endif // 0 668} 669 670static bool ANDROID_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) 671{ 672 return false; 673} 674 675SDL_JoystickDriver SDL_ANDROID_JoystickDriver = { 676 ANDROID_JoystickInit, 677 ANDROID_JoystickGetCount, 678 ANDROID_JoystickDetect, 679 ANDROID_JoystickIsDevicePresent, 680 ANDROID_JoystickGetDeviceName, 681 ANDROID_JoystickGetDevicePath, 682 ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot, 683 ANDROID_JoystickGetDevicePlayerIndex, 684 ANDROID_JoystickSetDevicePlayerIndex, 685 ANDROID_JoystickGetDeviceGUID, 686 ANDROID_JoystickGetDeviceInstanceID, 687 ANDROID_JoystickOpen, 688 ANDROID_JoystickRumble, 689 ANDROID_JoystickRumbleTriggers, 690 ANDROID_JoystickSetLED, 691 ANDROID_JoystickSendEffect, 692 ANDROID_JoystickSetSensorsEnabled, 693 ANDROID_JoystickUpdate, 694 ANDROID_JoystickClose, 695 ANDROID_JoystickQuit, 696 ANDROID_JoystickGetGamepadMapping 697}; 698 699#endif // SDL_JOYSTICK_ANDROID 700[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.