SDL  2.0
SDL_sysjoystick.m
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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 #include "../../SDL_internal.h"
22 
23 /* This is the iOS implementation of the SDL joystick API */
24 #include "SDL_sysjoystick_c.h"
25 
26 /* needed for SDL_IPHONE_MAX_GFORCE macro */
27 #include "SDL_config_iphoneos.h"
28 
29 #include "SDL_assert.h"
30 #include "SDL_events.h"
31 #include "SDL_joystick.h"
32 #include "SDL_hints.h"
33 #include "SDL_stdinc.h"
34 #include "../SDL_sysjoystick.h"
35 #include "../SDL_joystick_c.h"
36 #include "../steam/SDL_steamcontroller.h"
37 
38 
39 #if !SDL_EVENTS_DISABLED
40 #include "../../events/SDL_events_c.h"
41 #endif
42 
43 #if !TARGET_OS_TV
44 #import <CoreMotion/CoreMotion.h>
45 #endif
46 
47 #ifdef SDL_JOYSTICK_MFI
48 #import <GameController/GameController.h>
49 
50 static id connectObserver = nil;
51 static id disconnectObserver = nil;
52 #endif /* SDL_JOYSTICK_MFI */
53 
54 #if !TARGET_OS_TV
55 static const char *accelerometerName = "iOS Accelerometer";
56 static CMMotionManager *motionManager = nil;
57 #endif /* !TARGET_OS_TV */
58 
60 
61 static int numjoysticks = 0;
64 
66 GetDeviceForIndex(int device_index)
67 {
69  int i = 0;
70 
71  while (i < device_index) {
72  if (device == NULL) {
73  return NULL;
74  }
75  device = device->next;
76  i++;
77  }
78 
79  return device;
80 }
81 
82 static void
84 {
85 #ifdef SDL_JOYSTICK_MFI
86  const char *name = NULL;
87  /* Explicitly retain the controller because SDL_JoystickDeviceItem is a
88  * struct, and ARC doesn't work with structs. */
89  device->controller = (__bridge GCController *) CFBridgingRetain(controller);
90 
91  if (controller.vendorName) {
92  name = controller.vendorName.UTF8String;
93  }
94 
95  if (!name) {
96  name = "MFi Gamepad";
97  }
98 
99  device->name = SDL_strdup(name);
100 
101  device->guid.data[0] = 'M';
102  device->guid.data[1] = 'F';
103  device->guid.data[2] = 'i';
104  device->guid.data[3] = 'G';
105  device->guid.data[4] = 'a';
106  device->guid.data[5] = 'm';
107  device->guid.data[6] = 'e';
108  device->guid.data[7] = 'p';
109  device->guid.data[8] = 'a';
110  device->guid.data[9] = 'd';
111 
112  if (controller.extendedGamepad) {
113  device->guid.data[10] = 1;
114  } else if (controller.gamepad) {
115  device->guid.data[10] = 2;
116  }
117 #if TARGET_OS_TV
118  else if (controller.microGamepad) {
119  device->guid.data[10] = 3;
120  device->remote = SDL_TRUE;
121  }
122 #endif /* TARGET_OS_TV */
123 
124  if (controller.extendedGamepad) {
125  device->naxes = 6; /* 2 thumbsticks and 2 triggers */
126  device->nhats = 1; /* d-pad */
127  device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
128  } else if (controller.gamepad) {
129  device->naxes = 0; /* no traditional analog inputs */
130  device->nhats = 1; /* d-pad */
131  device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
132  }
133 #if TARGET_OS_TV
134  else if (controller.microGamepad) {
135  device->naxes = 2; /* treat the touch surface as two axes */
136  device->nhats = 0; /* apparently the touch surface-as-dpad is buggy */
137  device->nbuttons = 3; /* AX, pause button */
138 
139  controller.microGamepad.allowsRotation = SDL_GetHintBoolean(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_FALSE);
140  }
141 #endif /* TARGET_OS_TV */
142 
143  /* This will be set when the first button press of the controller is
144  * detected. */
145  controller.playerIndex = -1;
146 
147 #endif /* SDL_JOYSTICK_MFI */
148 }
149 
150 static void
152 {
154 
155 #if TARGET_OS_TV
157  /* Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input */
158  if (controller && !controller.extendedGamepad && !controller.gamepad && controller.microGamepad) {
159  return;
160  }
161  }
162 #endif
163 
164  while (device != NULL) {
165  if (device->controller == controller) {
166  return;
167  }
168  device = device->next;
169  }
170 
172  if (device == NULL) {
173  return;
174  }
175 
176  device->accelerometer = accelerometer;
177  device->instance_id = instancecounter++;
178 
179  if (accelerometer) {
180 #if TARGET_OS_TV
181  SDL_free(device);
182  return;
183 #else
184  device->name = SDL_strdup(accelerometerName);
185  device->naxes = 3; /* Device acceleration in the x, y, and z axes. */
186  device->nhats = 0;
187  device->nbuttons = 0;
188 
189  /* Use the accelerometer name as a GUID. */
190  SDL_memcpy(&device->guid.data, device->name, SDL_min(sizeof(SDL_JoystickGUID), SDL_strlen(device->name)));
191 #endif /* TARGET_OS_TV */
192  } else if (controller) {
193  SDL_SYS_AddMFIJoystickDevice(device, controller);
194  }
195 
196  if (deviceList == NULL) {
197  deviceList = device;
198  } else {
199  SDL_JoystickDeviceItem *lastdevice = deviceList;
200  while (lastdevice->next != NULL) {
201  lastdevice = lastdevice->next;
202  }
203  lastdevice->next = device;
204  }
205 
206  ++numjoysticks;
207 
209 }
210 
211 static SDL_JoystickDeviceItem *
213 {
217 
218  if (device == NULL) {
219  return NULL;
220  }
221 
222  next = device->next;
223 
224  while (item != NULL) {
225  if (item == device) {
226  break;
227  }
228  prev = item;
229  item = item->next;
230  }
231 
232  /* Unlink the device item from the device list. */
233  if (prev) {
234  prev->next = device->next;
235  } else if (device == deviceList) {
236  deviceList = device->next;
237  }
238 
239  if (device->joystick) {
240  device->joystick->hwdata = NULL;
241  }
242 
243 #ifdef SDL_JOYSTICK_MFI
244  @autoreleasepool {
245  if (device->controller) {
246  /* The controller was explicitly retained in the struct, so it
247  * should be explicitly released before freeing the struct. */
248  GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(device->controller));
249  controller.controllerPausedHandler = nil;
250  device->controller = nil;
251  }
252  }
253 #endif /* SDL_JOYSTICK_MFI */
254 
255  --numjoysticks;
256 
258 
259  SDL_free(device->name);
260  SDL_free(device);
261 
262  return next;
263 }
264 
265 #if TARGET_OS_TV
266 static void SDLCALL
267 SDL_AppleTVRemoteRotationHintChanged(void *udata, const char *name, const char *oldValue, const char *newValue)
268 {
269  BOOL allowRotation = newValue != NULL && *newValue != '0';
270 
271  @autoreleasepool {
272  for (GCController *controller in [GCController controllers]) {
273  if (controller.microGamepad) {
274  controller.microGamepad.allowsRotation = allowRotation;
275  }
276  }
277  }
278 }
279 #endif /* TARGET_OS_TV */
280 
281 static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
282 {
284  if (device == NULL) {
285  return SDL_FALSE;
286  }
287 
288  *device_instance = device->instance_id = instancecounter++;
289  device->name = SDL_strdup(name);
290  device->guid = guid;
292  &device->naxes,
293  &device->nhats);
294  device->m_bSteamController = SDL_TRUE;
295 
296  if (deviceList == NULL) {
297  deviceList = device;
298  } else {
299  SDL_JoystickDeviceItem *lastdevice = deviceList;
300  while (lastdevice->next != NULL) {
301  lastdevice = lastdevice->next;
302  }
303  lastdevice->next = device;
304  }
305 
306  ++numjoysticks;
307 
309 
310  return SDL_TRUE;
311 }
312 
313 static void SteamControllerDisconnectedCallback(int device_instance)
314 {
316 
317  for (item = deviceList; item; item = item->next) {
318  if (item->instance_id == device_instance) {
320  break;
321  }
322  }
323 }
324 
325 /* Function to scan the system for joysticks.
326  * Joystick 0 should be the system default joystick.
327  * It should return 0, or -1 on an unrecoverable fatal error.
328  */
329 int
331 {
332  @autoreleasepool {
333  NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
334 
337 
338 #if !TARGET_OS_TV
340  /* Default behavior, accelerometer as joystick */
342  }
343 #endif /* !TARGET_OS_TV */
344 
345 #ifdef SDL_JOYSTICK_MFI
346  /* GameController.framework was added in iOS 7. */
347  if (![GCController class]) {
348  return numjoysticks;
349  }
350 
351  for (GCController *controller in [GCController controllers]) {
353  }
354 
355 #if TARGET_OS_TV
357  SDL_AppleTVRemoteRotationHintChanged, NULL);
358 #endif /* TARGET_OS_TV */
359 
360  connectObserver = [center addObserverForName:GCControllerDidConnectNotification
361  object:nil
362  queue:nil
363  usingBlock:^(NSNotification *note) {
364  GCController *controller = note.object;
365  SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
366  }];
367 
368  disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
369  object:nil
370  queue:nil
371  usingBlock:^(NSNotification *note) {
372  GCController *controller = note.object;
373  SDL_JoystickDeviceItem *device = deviceList;
374  while (device != NULL) {
375  if (device->controller == controller) {
376  SDL_SYS_RemoveJoystickDevice(device);
377  break;
378  }
379  device = device->next;
380  }
381  }];
382 #endif /* SDL_JOYSTICK_MFI */
383  }
384 
385  return numjoysticks;
386 }
387 
388 int
390 {
391  return numjoysticks;
392 }
393 
394 void
396 {
398 }
399 
400 /* Function to get the device-dependent name of a joystick */
401 const char *
403 {
405  return device ? device->name : "Unknown";
406 }
407 
408 /* Function to perform the mapping from device index to the instance id for this index */
410 {
412  return device ? device->instance_id : 0;
413 }
414 
415 /* Function to open a joystick for use.
416  The joystick to open is specified by the device index.
417  This should fill the nbuttons and naxes fields of the joystick structure.
418  It returns 0, or -1 if there is an error.
419  */
420 int
421 SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
422 {
424  if (device == NULL) {
425  return SDL_SetError("Could not open Joystick: no hardware device for the specified index");
426  }
427 
428  joystick->hwdata = device;
429  joystick->instance_id = device->instance_id;
430 
431  joystick->naxes = device->naxes;
432  joystick->nhats = device->nhats;
433  joystick->nbuttons = device->nbuttons;
434  joystick->nballs = 0;
435 
436  device->joystick = joystick;
437 
438  @autoreleasepool {
439  if (device->accelerometer) {
440 #if !TARGET_OS_TV
441  if (motionManager == nil) {
442  motionManager = [[CMMotionManager alloc] init];
443  }
444 
445  /* Shorter times between updates can significantly increase CPU usage. */
446  motionManager.accelerometerUpdateInterval = 0.1;
447  [motionManager startAccelerometerUpdates];
448 #endif /* !TARGET_OS_TV */
449  } else {
450 #ifdef SDL_JOYSTICK_MFI
451  GCController *controller = device->controller;
452  controller.controllerPausedHandler = ^(GCController *c) {
453  if (joystick->hwdata) {
454  ++joystick->hwdata->num_pause_presses;
455  }
456  };
457 #endif /* SDL_JOYSTICK_MFI */
458  }
459  }
460  if (device->remote) {
462  }
463 
464  return 0;
465 }
466 
467 /* Function to determine if this joystick is attached to the system right now */
468 SDL_bool
470 {
471  return joystick->hwdata != NULL;
472 }
473 
474 static void
476 {
477 #if !TARGET_OS_TV
478  const float maxgforce = SDL_IPHONE_MAX_GFORCE;
479  const SInt16 maxsint16 = 0x7FFF;
480  CMAcceleration accel;
481 
482  @autoreleasepool {
483  if (!motionManager.isAccelerometerActive) {
484  return;
485  }
486 
487  accel = motionManager.accelerometerData.acceleration;
488  }
489 
490  /*
491  Convert accelerometer data from floating point to Sint16, which is what
492  the joystick system expects.
493 
494  To do the conversion, the data is first clamped onto the interval
495  [-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied
496  by MAX_SINT16 so that it is mapped to the full range of an Sint16.
497 
498  You can customize the clamped range of this function by modifying the
499  SDL_IPHONE_MAX_GFORCE macro in SDL_config_iphoneos.h.
500 
501  Once converted to Sint16, the accelerometer data no longer has coherent
502  units. You can convert the data back to units of g-force by multiplying
503  it in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
504  */
505 
506  /* clamp the data */
507  accel.x = SDL_min(SDL_max(accel.x, -maxgforce), maxgforce);
508  accel.y = SDL_min(SDL_max(accel.y, -maxgforce), maxgforce);
509  accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
510 
511  /* pass in data mapped to range of SInt16 */
512  SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
513  SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
514  SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
515 #endif /* !TARGET_OS_TV */
516 }
517 
518 #ifdef SDL_JOYSTICK_MFI
519 static Uint8
520 SDL_SYS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
521 {
522  Uint8 hat = 0;
523 
524  if (dpad.up.isPressed) {
525  hat |= SDL_HAT_UP;
526  } else if (dpad.down.isPressed) {
527  hat |= SDL_HAT_DOWN;
528  }
529 
530  if (dpad.left.isPressed) {
531  hat |= SDL_HAT_LEFT;
532  } else if (dpad.right.isPressed) {
533  hat |= SDL_HAT_RIGHT;
534  }
535 
536  if (hat == 0) {
537  return SDL_HAT_CENTERED;
538  }
539 
540  return hat;
541 }
542 #endif
543 
544 static void
546 {
547 #if SDL_JOYSTICK_MFI
548  @autoreleasepool {
549  GCController *controller = joystick->hwdata->controller;
550  Uint8 hatstate = SDL_HAT_CENTERED;
551  int i;
552  int updateplayerindex = 0;
553 
554  if (controller.extendedGamepad) {
555  GCExtendedGamepad *gamepad = controller.extendedGamepad;
556 
557  /* Axis order matches the XInput Windows mappings. */
558  Sint16 axes[] = {
559  (Sint16) (gamepad.leftThumbstick.xAxis.value * 32767),
560  (Sint16) (gamepad.leftThumbstick.yAxis.value * -32767),
561  (Sint16) ((gamepad.leftTrigger.value * 65535) - 32768),
562  (Sint16) (gamepad.rightThumbstick.xAxis.value * 32767),
563  (Sint16) (gamepad.rightThumbstick.yAxis.value * -32767),
564  (Sint16) ((gamepad.rightTrigger.value * 65535) - 32768),
565  };
566 
567  /* Button order matches the XInput Windows mappings. */
568  Uint8 buttons[] = {
569  gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
570  gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
571  gamepad.leftShoulder.isPressed,
572  gamepad.rightShoulder.isPressed,
573  };
574 
575  hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
576 
577  for (i = 0; i < SDL_arraysize(axes); i++) {
578  /* The triggers (axes 2 and 5) are resting at -32768 but SDL
579  * initializes its values to 0. We only want to make sure the
580  * player index is up to date if the user actually moves an axis. */
581  if ((i != 2 && i != 5) || axes[i] != -32768) {
582  updateplayerindex |= (joystick->axes[i].value != axes[i]);
583  }
584  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
585  }
586 
587  for (i = 0; i < SDL_arraysize(buttons); i++) {
588  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
589  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
590  }
591  } else if (controller.gamepad) {
592  GCGamepad *gamepad = controller.gamepad;
593 
594  /* Button order matches the XInput Windows mappings. */
595  Uint8 buttons[] = {
596  gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
597  gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
598  gamepad.leftShoulder.isPressed,
599  gamepad.rightShoulder.isPressed,
600  };
601 
602  hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
603 
604  for (i = 0; i < SDL_arraysize(buttons); i++) {
605  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
606  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
607  }
608  }
609 #if TARGET_OS_TV
610  else if (controller.microGamepad) {
611  GCMicroGamepad *gamepad = controller.microGamepad;
612 
613  Sint16 axes[] = {
614  (Sint16) (gamepad.dpad.xAxis.value * 32767),
615  (Sint16) (gamepad.dpad.yAxis.value * -32767),
616  };
617 
618  for (i = 0; i < SDL_arraysize(axes); i++) {
619  updateplayerindex |= (joystick->axes[i].value != axes[i]);
620  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
621  }
622 
623  Uint8 buttons[] = {
624  gamepad.buttonA.isPressed,
625  gamepad.buttonX.isPressed,
626  };
627 
628  for (i = 0; i < SDL_arraysize(buttons); i++) {
629  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
630  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
631  }
632  }
633 #endif /* TARGET_OS_TV */
634 
635  if (joystick->nhats > 0) {
636  updateplayerindex |= (joystick->hats[0] != hatstate);
637  SDL_PrivateJoystickHat(joystick, 0, hatstate);
638  }
639 
640  for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
641  /* The pause button is always last. */
642  Uint8 pausebutton = joystick->nbuttons - 1;
643 
644  SDL_PrivateJoystickButton(joystick, pausebutton, SDL_PRESSED);
645  SDL_PrivateJoystickButton(joystick, pausebutton, SDL_RELEASED);
646 
647  updateplayerindex = YES;
648  }
649 
650  joystick->hwdata->num_pause_presses = 0;
651 
652  if (updateplayerindex && controller.playerIndex == -1) {
653  BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};
654 
655  /* Find the player index of all other connected controllers. */
656  for (GCController *c in [GCController controllers]) {
657  if (c != controller && c.playerIndex >= 0) {
658  usedPlayerIndexSlots[c.playerIndex] = YES;
659  }
660  }
661 
662  /* Set this controller's player index to the first unused index.
663  * FIXME: This logic isn't great... but SDL doesn't expose this
664  * concept in its external API, so we don't have much to go on. */
665  for (i = 0; i < SDL_arraysize(usedPlayerIndexSlots); i++) {
666  if (!usedPlayerIndexSlots[i]) {
667  controller.playerIndex = i;
668  break;
669  }
670  }
671  }
672  }
673 #endif /* SDL_JOYSTICK_MFI */
674 }
675 
676 /* Function to update the state of a joystick - called as a device poll.
677  * This function shouldn't update the joystick structure directly,
678  * but instead should call SDL_PrivateJoystick*() to deliver events
679  * and update joystick device state.
680  */
681 void
683 {
684  SDL_JoystickDeviceItem *device = joystick->hwdata;
685 
686  if (device == NULL) {
687  return;
688  }
689 
690  if (device->m_bSteamController) {
691  SDL_UpdateSteamController(joystick);
692  return;
693  }
694 
695  if (device->accelerometer) {
696  SDL_SYS_AccelerometerUpdate(joystick);
697  } else if (device->controller) {
698  SDL_SYS_MFIJoystickUpdate(joystick);
699  }
700 }
701 
702 /* Function to close a joystick after use */
703 void
705 {
706  SDL_JoystickDeviceItem *device = joystick->hwdata;
707 
708  if (device == NULL) {
709  return;
710  }
711 
712  device->joystick = NULL;
713 
714  @autoreleasepool {
715  if (device->accelerometer) {
716 #if !TARGET_OS_TV
717  [motionManager stopAccelerometerUpdates];
718 #endif /* !TARGET_OS_TV */
719  } else if (device->controller) {
720 #ifdef SDL_JOYSTICK_MFI
721  GCController *controller = device->controller;
722  controller.controllerPausedHandler = nil;
723  controller.playerIndex = -1;
724 #endif
725  }
726  }
727  if (device->remote) {
729  }
730 }
731 
732 /* Function to perform any system-specific joystick related cleanup */
733 void
735 {
736  @autoreleasepool {
737 #ifdef SDL_JOYSTICK_MFI
738  NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
739 
740  if (connectObserver) {
741  [center removeObserver:connectObserver name:GCControllerDidConnectNotification object:nil];
742  connectObserver = nil;
743  }
744 
745  if (disconnectObserver) {
746  [center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
747  disconnectObserver = nil;
748  }
749 
750 #if TARGET_OS_TV
752  SDL_AppleTVRemoteRotationHintChanged, NULL);
753 #endif /* TARGET_OS_TV */
754 #endif /* SDL_JOYSTICK_MFI */
755 
756  while (deviceList != NULL) {
757  SDL_SYS_RemoveJoystickDevice(deviceList);
758  }
759 
760 #if !TARGET_OS_TV
761  motionManager = nil;
762 #endif /* !TARGET_OS_TV */
763  }
764 
766 
767  numjoysticks = 0;
768 }
769 
771 SDL_SYS_JoystickGetDeviceGUID( int device_index )
772 {
775  if (device) {
776  guid = device->guid;
777  } else {
778  SDL_zero(guid);
779  }
780  return guid;
781 }
782 
785 {
787  if (joystick->hwdata) {
788  guid = joystick->hwdata->guid;
789  } else {
790  SDL_zero(guid);
791  }
792  return guid;
793 }
794 
795 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_HINT_TV_REMOTE_AS_JOYSTICK
A variable controlling whether the Android / tvOS remotes should be listed as joystick devices...
Definition: SDL_hints.h:399
void SDL_UpdateSteamControllers(void)
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
Definition: SDL_joystick.c:638
SDL_JoystickGUID guid
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:712
void SDL_InitSteamControllers(SteamControllerConnectedCallback_t connectedCallback, SteamControllerDisconnectedCallback_t disconnectedCallback)
static void SteamControllerDisconnectedCallback(int device_instance)
void SDL_QuitSteamControllers(void)
static SDL_JoystickDeviceItem * deviceList
SDL_Joystick * joystick
static void SDL_SYS_MFIJoystickUpdate(SDL_Joystick *joystick)
#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION
A variable controlling whether the Apple TV remote&#39;s joystick axes will automatically match the rotat...
Definition: SDL_hints.h:368
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:788
static const char * accelerometerName
struct joystick_hwdata * next
void SDL_SYS_JoystickQuit(void)
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
Uint8 data[16]
Definition: SDL_joystick.h:71
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:655
GLuint const GLchar * name
#define SDL_GetHintBoolean
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:318
#define SDL_memcpy
#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK
A variable controlling whether the Android / iOS built-in accelerometer should be listed as a joystic...
Definition: SDL_hints.h:389
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:81
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:320
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
static void SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
const GLubyte * c
void SDL_PrivateJoystickAdded(int device_index)
Definition: SDL_joystick.c:595
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick *joystick)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
int SDL_SYS_JoystickInit(void)
#define SDL_IPHONE_MAX_GFORCE
#define NULL
Definition: begin_code.h:164
void SDL_UpdateSteamController(SDL_Joystick *joystick)
SDL_bool
Definition: SDL_stdinc.h:139
int SDL_SYS_NumJoysticks(void)
#define SDL_SetError
SDL_bool m_bSteamController
#define SDL_calloc
static void SDL_SYS_AccelerometerUpdate(SDL_Joystick *joystick)
static SDL_JoystickID instancecounter
#define SDL_strlen
#define SDL_strdup
int SDL_AppleTVRemoteOpenedAsJoystick
struct SDL_joylist_item * item
#define SDL_AddHintCallback
#define SDL_DelHintCallback
static SDL_JoystickDeviceItem * SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
static int numjoysticks
void SDL_GetSteamControllerInputs(int *nbuttons, int *naxes, int *nhats)
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
#define SDL_PRESSED
Definition: SDL_events.h:50
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:316
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
#define SDL_RELEASED
Definition: SDL_events.h:49
GLuint in
#define SDL_HAT_UP
Definition: SDL_joystick.h:317
static void SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
#define SDLCALL
Definition: SDL_internal.h:45
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:319
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
GCController __unsafe_unretained * controller
int16_t Sint16
Definition: SDL_stdinc.h:163
void SDL_SYS_JoystickDetect(void)
static CMMotionManager * motionManager