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