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