SDL  2.0
SDL_sysjoystick.m File Reference
#include "../../SDL_internal.h"
#include "SDL_sysjoystick_c.h"
#include "SDL_config_iphoneos.h"
#include "SDL_assert.h"
#include "SDL_events.h"
#include "SDL_joystick.h"
#include "SDL_hints.h"
#include "SDL_stdinc.h"
#include "../SDL_sysjoystick.h"
#include "../SDL_joystick_c.h"
#include "../../events/SDL_events_c.h"
#import <CoreMotion/CoreMotion.h>
+ Include dependency graph for SDL_sysjoystick.m:

Go to the source code of this file.

Functions

static SDL_JoystickDeviceItemGetDeviceForIndex (int device_index)
 
static void IOS_AddMFIJoystickDevice (SDL_JoystickDeviceItem *device, GCController *controller)
 
static void IOS_AddJoystickDevice (GCController *controller, SDL_bool accelerometer)
 
static SDL_JoystickDeviceItemIOS_RemoveJoystickDevice (SDL_JoystickDeviceItem *device)
 
static int IOS_JoystickInit (void)
 
static int IOS_JoystickGetCount (void)
 
static void IOS_JoystickDetect (void)
 
static const char * IOS_JoystickGetDeviceName (int device_index)
 
static int IOS_JoystickGetDevicePlayerIndex (int device_index)
 
static SDL_JoystickGUID IOS_JoystickGetDeviceGUID (int device_index)
 
static SDL_JoystickID IOS_JoystickGetDeviceInstanceID (int device_index)
 
static int IOS_JoystickOpen (SDL_Joystick *joystick, int device_index)
 
static void IOS_AccelerometerUpdate (SDL_Joystick *joystick)
 
static void IOS_MFIJoystickUpdate (SDL_Joystick *joystick)
 
static int IOS_JoystickRumble (SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
 
static void IOS_JoystickUpdate (SDL_Joystick *joystick)
 
static void IOS_JoystickClose (SDL_Joystick *joystick)
 
static void IOS_JoystickQuit (void)
 

Variables

static const char * accelerometerName = "iOS Accelerometer"
 
static CMMotionManager * motionManager = nil
 
static SDL_JoystickDeviceItemdeviceList = NULL
 
static int numjoysticks = 0
 
int SDL_AppleTVRemoteOpenedAsJoystick = 0
 
SDL_JoystickDriver SDL_IOS_JoystickDriver
 

Function Documentation

◆ GetDeviceForIndex()

static SDL_JoystickDeviceItem* GetDeviceForIndex ( int  device_index)
static

Definition at line 87 of file SDL_sysjoystick.m.

References device, deviceList, i, recDevice::next, and NULL.

Referenced by IOS_JoystickGetDeviceGUID(), IOS_JoystickGetDeviceInstanceID(), IOS_JoystickGetDeviceName(), IOS_JoystickGetDevicePlayerIndex(), and IOS_JoystickOpen().

88 {
90  int i = 0;
91 
92  while (i < device_index) {
93  if (device == NULL) {
94  return NULL;
95  }
96  device = device->next;
97  i++;
98  }
99 
100  return device;
101 }
static SDL_JoystickDeviceItem * deviceList
struct joystick_hwdata * next
static SDL_AudioDeviceID device
Definition: loopwave.c:37
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
#define NULL
Definition: begin_code.h:167

◆ IOS_AccelerometerUpdate()

static void IOS_AccelerometerUpdate ( SDL_Joystick *  joystick)
static

Definition at line 540 of file SDL_sysjoystick.m.

References motionManager, SDL_HAT_CENTERED, SDL_HAT_DOWN, SDL_HAT_LEFT, SDL_HAT_RIGHT, SDL_HAT_UP, SDL_IPHONE_MAX_GFORCE, SDL_max, SDL_min, and SDL_PrivateJoystickAxis().

Referenced by IOS_JoystickUpdate().

541 {
542 #if !TARGET_OS_TV
543  const float maxgforce = SDL_IPHONE_MAX_GFORCE;
544  const SInt16 maxsint16 = 0x7FFF;
545  CMAcceleration accel;
546 
547  @autoreleasepool {
548  if (!motionManager.isAccelerometerActive) {
549  return;
550  }
551 
552  accel = motionManager.accelerometerData.acceleration;
553  }
554 
555  /*
556  Convert accelerometer data from floating point to Sint16, which is what
557  the joystick system expects.
558 
559  To do the conversion, the data is first clamped onto the interval
560  [-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied
561  by MAX_SINT16 so that it is mapped to the full range of an Sint16.
562 
563  You can customize the clamped range of this function by modifying the
564  SDL_IPHONE_MAX_GFORCE macro in SDL_config_iphoneos.h.
565 
566  Once converted to Sint16, the accelerometer data no longer has coherent
567  units. You can convert the data back to units of g-force by multiplying
568  it in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
569  */
570 
571  /* clamp the data */
572  accel.x = SDL_min(SDL_max(accel.x, -maxgforce), maxgforce);
573  accel.y = SDL_min(SDL_max(accel.y, -maxgforce), maxgforce);
574  accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
575 
576  /* pass in data mapped to range of SInt16 */
577  SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
578  SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
579  SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
580 #endif /* !TARGET_OS_TV */
581 }
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:833
#define SDL_IPHONE_MAX_GFORCE
static CMMotionManager * motionManager

◆ IOS_AddJoystickDevice()

static void IOS_AddJoystickDevice ( GCController *  controller,
SDL_bool  accelerometer 
)
static

Definition at line 259 of file SDL_sysjoystick.m.

References recDevice::accelerometer, accelerometerName, recDevice::controller, SDL_JoystickGUID::data, device, deviceList, recDevice::guid, recDevice::instance_id, IOS_AddMFIJoystickDevice(), recDevice::name, recDevice::naxes, recDevice::nbuttons, recDevice::next, recDevice::nhats, NULL, numjoysticks, SDL_calloc, SDL_free, SDL_GetHintBoolean, SDL_GetNextJoystickInstanceID(), SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_memcpy, SDL_min, SDL_PrivateJoystickAdded(), SDL_strdup, SDL_strlen, and SDL_TRUE.

Referenced by IOS_JoystickInit().

260 {
262 
263 #if TARGET_OS_TV
265  /* Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input */
266  if (controller && !controller.extendedGamepad && !controller.gamepad && controller.microGamepad) {
267  return;
268  }
269  }
270 #endif
271 
272  while (device != NULL) {
273  if (device->controller == controller) {
274  return;
275  }
276  device = device->next;
277  }
278 
280  if (device == NULL) {
281  return;
282  }
283 
284  device->accelerometer = accelerometer;
286 
287  if (accelerometer) {
288 #if TARGET_OS_TV
289  SDL_free(device);
290  return;
291 #else
292  device->name = SDL_strdup(accelerometerName);
293  device->naxes = 3; /* Device acceleration in the x, y, and z axes. */
294  device->nhats = 0;
295  device->nbuttons = 0;
296 
297  /* Use the accelerometer name as a GUID. */
298  SDL_memcpy(&device->guid.data, device->name, SDL_min(sizeof(SDL_JoystickGUID), SDL_strlen(device->name)));
299 #endif /* TARGET_OS_TV */
300  } else if (controller) {
301  IOS_AddMFIJoystickDevice(device, controller);
302  }
303 
304  if (deviceList == NULL) {
305  deviceList = device;
306  } else {
307  SDL_JoystickDeviceItem *lastdevice = deviceList;
308  while (lastdevice->next != NULL) {
309  lastdevice = lastdevice->next;
310  }
311  lastdevice->next = device;
312  }
313 
314  ++numjoysticks;
315 
317 }
#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:419
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
SDL_JoystickGUID guid
static SDL_JoystickDeviceItem * deviceList
static const char * accelerometerName
struct joystick_hwdata * next
Uint8 data[16]
Definition: SDL_joystick.h:71
#define SDL_GetHintBoolean
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define SDL_memcpy
#define SDL_free
static void IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
Definition: SDL_joystick.c:755
#define NULL
Definition: begin_code.h:167
#define SDL_calloc
SDL_JoystickID SDL_GetNextJoystickInstanceID()
Definition: SDL_joystick.c:163
#define SDL_strlen
#define SDL_strdup
static int numjoysticks
GCController __unsafe_unretained * controller

◆ IOS_AddMFIJoystickDevice()

static void IOS_AddMFIJoystickDevice ( SDL_JoystickDeviceItem device,
GCController *  controller 
)
static

Definition at line 104 of file SDL_sysjoystick.m.

References recDevice::button_mask, recDevice::controller, SDL_JoystickGUID::data, recDevice::guid, recDevice::name, recDevice::naxes, recDevice::nbuttons, recDevice::nhats, NULL, SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_BUTTON_BACK, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_BUTTON_LEFTSTICK, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_BUTTON_RIGHTSTICK, SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_BUTTON_Y, SDL_FALSE, SDL_GetHintBoolean, SDL_HARDWARE_BUS_BLUETOOTH, SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_strdup, SDL_SwapLE16, SDL_TRUE, and recDevice::uses_pause_handler.

Referenced by IOS_AddJoystickDevice().

105 {
106 #ifdef SDL_JOYSTICK_MFI
107  const Uint16 VENDOR_APPLE = 0x05AC;
108  const Uint16 VENDOR_MICROSOFT = 0x045e;
109  const Uint16 VENDOR_SONY = 0x054C;
110  Uint16 *guid16 = (Uint16 *)device->guid.data;
111  Uint16 vendor = 0;
112  Uint16 product = 0;
113  Uint8 subtype = 0;
114 
115  const char *name = NULL;
116  /* Explicitly retain the controller because SDL_JoystickDeviceItem is a
117  * struct, and ARC doesn't work with structs. */
118  device->controller = (__bridge GCController *) CFBridgingRetain(controller);
119 
120  if (controller.vendorName) {
121  name = controller.vendorName.UTF8String;
122  }
123 
124  if (!name) {
125  name = "MFi Gamepad";
126  }
127 
128  device->name = SDL_strdup(name);
129 
130  if (controller.extendedGamepad) {
131  GCExtendedGamepad *gamepad = controller.extendedGamepad;
132  int nbuttons = 0;
133 
134  /* These buttons are part of the original MFi spec */
135  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_A);
136  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_B);
137  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_X);
138  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_Y);
141  nbuttons += 6;
142 
143  /* These buttons are available on some newer controllers */
144 #pragma clang diagnostic push
145 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
146  if ([gamepad respondsToSelector:@selector(leftThumbstickButton)] && gamepad.leftThumbstickButton) {
148  ++nbuttons;
149  }
150  if ([gamepad respondsToSelector:@selector(rightThumbstickButton)] && gamepad.rightThumbstickButton) {
152  ++nbuttons;
153  }
154  if ([gamepad respondsToSelector:@selector(buttonOptions)] && gamepad.buttonOptions) {
155  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_BACK);
156  ++nbuttons;
157  }
158  if ([gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu) {
159  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_START);
160  ++nbuttons;
161  } else {
162  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_START);
163  ++nbuttons;
164  device->uses_pause_handler = SDL_TRUE;
165  }
166 #pragma clang diagnostic pop
167 
168  if ([controller.vendorName containsString: @"Xbox"]) {
169  vendor = VENDOR_MICROSOFT;
170  product = 0x02E0; /* Assume Xbox One S BLE Controller unless/until GCController flows VID/PID */
171  } else if ([controller.vendorName containsString: @"DUALSHOCK"]) {
172  vendor = VENDOR_SONY;
173  product = 0x09CC; /* Assume DS4 Slim unless/until GCController flows VID/PID */
174  } else {
175  vendor = VENDOR_APPLE;
176  product = 1;
177  subtype = 1;
178  }
179 
180  device->naxes = 6; /* 2 thumbsticks and 2 triggers */
181  device->nhats = 1; /* d-pad */
182  device->nbuttons = nbuttons;
183 
184  } else if (controller.gamepad) {
185  int nbuttons = 0;
186 
187  /* These buttons are part of the original MFi spec */
188  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_A);
189  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_B);
190  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_X);
191  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_Y);
194  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_START);
195  nbuttons += 7;
196  device->uses_pause_handler = SDL_TRUE;
197 
198  vendor = VENDOR_APPLE;
199  product = 2;
200  subtype = 2;
201  device->naxes = 0; /* no traditional analog inputs */
202  device->nhats = 1; /* d-pad */
203  device->nbuttons = nbuttons;
204  }
205 #if TARGET_OS_TV
206  else if (controller.microGamepad) {
207  GCMicroGamepad *gamepad = controller.microGamepad;
208  int nbuttons = 0;
209 
210  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_A);
211  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_B); /* Button X on microGamepad */
212  nbuttons += 2;
213 
214  if ([gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu) {
215  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_START);
216  ++nbuttons;
217  } else {
218  device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_START);
219  ++nbuttons;
220  device->uses_pause_handler = SDL_TRUE;
221  }
222 
223  vendor = VENDOR_APPLE;
224  product = 3;
225  subtype = 3;
226  device->naxes = 2; /* treat the touch surface as two axes */
227  device->nhats = 0; /* apparently the touch surface-as-dpad is buggy */
228  device->nbuttons = nbuttons;
229 
230  controller.microGamepad.allowsRotation = SDL_GetHintBoolean(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_FALSE);
231  }
232 #endif /* TARGET_OS_TV */
233 
234  /* We only need 16 bits for each of these; space them out to fill 128. */
235  /* Byteswap so devices get same GUID on little/big endian platforms. */
237  *guid16++ = 0;
238  *guid16++ = SDL_SwapLE16(vendor);
239  *guid16++ = 0;
240  *guid16++ = SDL_SwapLE16(product);
241  *guid16++ = 0;
242 
243  *guid16++ = SDL_SwapLE16(device->button_mask);
244 
245  if (subtype != 0) {
246  /* Note that this is an MFI controller and what subtype it is */
247  device->guid.data[14] = 'm';
248  device->guid.data[15] = subtype;
249  }
250 
251  /* This will be set when the first button press of the controller is
252  * detected. */
253  controller.playerIndex = -1;
254 
255 #endif /* SDL_JOYSTICK_MFI */
256 }
SDL_JoystickGUID guid
#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:388
uint16_t Uint16
Definition: SDL_stdinc.h:191
Uint8 data[16]
Definition: SDL_joystick.h:71
GLuint const GLchar * name
#define SDL_GetHintBoolean
#define SDL_HARDWARE_BUS_BLUETOOTH
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define NULL
Definition: begin_code.h:167
#define SDL_strdup
SDL_bool uses_pause_handler
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
GCController __unsafe_unretained * controller

◆ IOS_JoystickClose()

static void IOS_JoystickClose ( SDL_Joystick *  joystick)
static

Definition at line 805 of file SDL_sysjoystick.m.

References recDevice::accelerometer, recDevice::controller, device, recDevice::joystick, NULL, recDevice::remote, and SDL_AppleTVRemoteOpenedAsJoystick.

806 {
807  SDL_JoystickDeviceItem *device = joystick->hwdata;
808 
809  if (device == NULL) {
810  return;
811  }
812 
813  device->joystick = NULL;
814 
815  @autoreleasepool {
816  if (device->accelerometer) {
817 #if !TARGET_OS_TV
818  [motionManager stopAccelerometerUpdates];
819 #endif /* !TARGET_OS_TV */
820  } else if (device->controller) {
821 #ifdef SDL_JOYSTICK_MFI
822  GCController *controller = device->controller;
823  controller.controllerPausedHandler = nil;
824  controller.playerIndex = -1;
825 #endif
826  }
827  }
828  if (device->remote) {
830  }
831 }
SDL_Joystick * joystick
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define NULL
Definition: begin_code.h:167
int SDL_AppleTVRemoteOpenedAsJoystick
GCController __unsafe_unretained * controller

◆ IOS_JoystickDetect()

static void IOS_JoystickDetect ( void  )
static

Definition at line 452 of file SDL_sysjoystick.m.

453 {
454 }

◆ IOS_JoystickGetCount()

static int IOS_JoystickGetCount ( void  )
static

Definition at line 446 of file SDL_sysjoystick.m.

References numjoysticks.

447 {
448  return numjoysticks;
449 }
static int numjoysticks

◆ IOS_JoystickGetDeviceGUID()

static SDL_JoystickGUID IOS_JoystickGetDeviceGUID ( int  device_index)
static

Definition at line 471 of file SDL_sysjoystick.m.

References device, GetDeviceForIndex(), recDevice::guid, and SDL_zero.

472 {
474  SDL_JoystickGUID guid;
475  if (device) {
476  guid = device->guid;
477  } else {
478  SDL_zero(guid);
479  }
480  return guid;
481 }
SDL_JoystickGUID guid
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define SDL_zero(x)
Definition: SDL_stdinc.h:416

◆ IOS_JoystickGetDeviceInstanceID()

static SDL_JoystickID IOS_JoystickGetDeviceInstanceID ( int  device_index)
static

Definition at line 484 of file SDL_sysjoystick.m.

References device, GetDeviceForIndex(), and recDevice::instance_id.

485 {
487  return device ? device->instance_id : -1;
488 }
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_AudioDeviceID device
Definition: loopwave.c:37

◆ IOS_JoystickGetDeviceName()

static const char* IOS_JoystickGetDeviceName ( int  device_index)
static

Definition at line 457 of file SDL_sysjoystick.m.

References device, GetDeviceForIndex(), and recDevice::name.

458 {
460  return device ? device->name : "Unknown";
461 }
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_AudioDeviceID device
Definition: loopwave.c:37

◆ IOS_JoystickGetDevicePlayerIndex()

static int IOS_JoystickGetDevicePlayerIndex ( int  device_index)
static

Definition at line 464 of file SDL_sysjoystick.m.

References recDevice::controller, device, and GetDeviceForIndex().

465 {
467  return device ? (int)device->controller.playerIndex : -1;
468 }
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_AudioDeviceID device
Definition: loopwave.c:37
GCController __unsafe_unretained * controller

◆ IOS_JoystickInit()

static int IOS_JoystickInit ( void  )
static

Definition at line 390 of file SDL_sysjoystick.m.

References sort_controllers::controllers, IOS_AddJoystickDevice(), NULL, SDL_AddHintCallback, SDL_FALSE, SDL_GetHintBoolean, SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, and SDL_TRUE.

391 {
392  @autoreleasepool {
393  NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
394 
395 #if !TARGET_OS_TV
397  /* Default behavior, accelerometer as joystick */
399  }
400 #endif /* !TARGET_OS_TV */
401 
402 #ifdef SDL_JOYSTICK_MFI
403  /* GameController.framework was added in iOS 7. */
404  if (![GCController class]) {
405  return 0;
406  }
407 
408  for (GCController *controller in [GCController controllers]) {
409  IOS_AddJoystickDevice(controller, SDL_FALSE);
410  }
411 
412 #if TARGET_OS_TV
414  SDL_AppleTVRemoteRotationHintChanged, NULL);
415 #endif /* TARGET_OS_TV */
416 
417  connectObserver = [center addObserverForName:GCControllerDidConnectNotification
418  object:nil
419  queue:nil
420  usingBlock:^(NSNotification *note) {
421  GCController *controller = note.object;
422  IOS_AddJoystickDevice(controller, SDL_FALSE);
423  }];
424 
425  disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
426  object:nil
427  queue:nil
428  usingBlock:^(NSNotification *note) {
429  GCController *controller = note.object;
430  SDL_JoystickDeviceItem *device = deviceList;
431  while (device != NULL) {
432  if (device->controller == controller) {
433  IOS_RemoveJoystickDevice(device);
434  break;
435  }
436  device = device->next;
437  }
438  }];
439 #endif /* SDL_JOYSTICK_MFI */
440  }
441 
442  return 0;
443 }
#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:388
#define SDL_GetHintBoolean
#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:409
#define NULL
Definition: begin_code.h:167
#define SDL_AddHintCallback
static void IOS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
GLuint in

◆ IOS_JoystickOpen()

static int IOS_JoystickOpen ( SDL_Joystick *  joystick,
int  device_index 
)
static

Definition at line 491 of file SDL_sysjoystick.m.

References recDevice::accelerometer, recDevice::controller, device, GetDeviceForIndex(), recDevice::instance_id, recDevice::joystick, motionManager, recDevice::naxes, recDevice::nbuttons, recDevice::nhats, NULL, recDevice::remote, SDL_AppleTVRemoteOpenedAsJoystick, SDL_SetError, and recDevice::uses_pause_handler.

492 {
494  if (device == NULL) {
495  return SDL_SetError("Could not open Joystick: no hardware device for the specified index");
496  }
497 
498  joystick->hwdata = device;
499  joystick->instance_id = device->instance_id;
500 
501  joystick->naxes = device->naxes;
502  joystick->nhats = device->nhats;
503  joystick->nbuttons = device->nbuttons;
504  joystick->nballs = 0;
505 
506  device->joystick = joystick;
507 
508  @autoreleasepool {
509  if (device->accelerometer) {
510 #if !TARGET_OS_TV
511  if (motionManager == nil) {
512  motionManager = [[CMMotionManager alloc] init];
513  }
514 
515  /* Shorter times between updates can significantly increase CPU usage. */
516  motionManager.accelerometerUpdateInterval = 0.1;
517  [motionManager startAccelerometerUpdates];
518 #endif /* !TARGET_OS_TV */
519  } else {
520 #ifdef SDL_JOYSTICK_MFI
521  if (device->uses_pause_handler) {
522  GCController *controller = device->controller;
523  controller.controllerPausedHandler = ^(GCController *c) {
524  if (joystick->hwdata) {
525  ++joystick->hwdata->num_pause_presses;
526  }
527  };
528  }
529 #endif /* SDL_JOYSTICK_MFI */
530  }
531  }
532  if (device->remote) {
534  }
535 
536  return 0;
537 }
SDL_Joystick * joystick
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_AudioDeviceID device
Definition: loopwave.c:37
const GLubyte * c
#define NULL
Definition: begin_code.h:167
#define SDL_SetError
int SDL_AppleTVRemoteOpenedAsJoystick
SDL_bool uses_pause_handler
GCController __unsafe_unretained * controller
static CMMotionManager * motionManager

◆ IOS_JoystickQuit()

static void IOS_JoystickQuit ( void  )
static

Definition at line 834 of file SDL_sysjoystick.m.

References IOS_RemoveJoystickDevice(), motionManager, NULL, numjoysticks, SDL_DelHintCallback, and SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION.

835 {
836  @autoreleasepool {
837 #ifdef SDL_JOYSTICK_MFI
838  NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
839 
840  if (connectObserver) {
841  [center removeObserver:connectObserver name:GCControllerDidConnectNotification object:nil];
842  connectObserver = nil;
843  }
844 
845  if (disconnectObserver) {
846  [center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
847  disconnectObserver = nil;
848  }
849 
850 #if TARGET_OS_TV
852  SDL_AppleTVRemoteRotationHintChanged, NULL);
853 #endif /* TARGET_OS_TV */
854 #endif /* SDL_JOYSTICK_MFI */
855 
856  while (deviceList != NULL) {
858  }
859 
860 #if !TARGET_OS_TV
861  motionManager = nil;
862 #endif /* !TARGET_OS_TV */
863  }
864 
865  numjoysticks = 0;
866 }
static SDL_JoystickDeviceItem * IOS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
static SDL_JoystickDeviceItem * deviceList
#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:388
#define NULL
Definition: begin_code.h:167
#define SDL_DelHintCallback
static int numjoysticks
static CMMotionManager * motionManager

◆ IOS_JoystickRumble()

static int IOS_JoystickRumble ( SDL_Joystick *  joystick,
Uint16  low_frequency_rumble,
Uint16  high_frequency_rumble,
Uint32  duration_ms 
)
static

Definition at line 783 of file SDL_sysjoystick.m.

References SDL_Unsupported.

784 {
785  return SDL_Unsupported();
786 }
#define SDL_Unsupported()
Definition: SDL_error.h:53

◆ IOS_JoystickUpdate()

static void IOS_JoystickUpdate ( SDL_Joystick *  joystick)
static

Definition at line 789 of file SDL_sysjoystick.m.

References recDevice::accelerometer, recDevice::controller, device, IOS_AccelerometerUpdate(), IOS_MFIJoystickUpdate(), and NULL.

790 {
791  SDL_JoystickDeviceItem *device = joystick->hwdata;
792 
793  if (device == NULL) {
794  return;
795  }
796 
797  if (device->accelerometer) {
798  IOS_AccelerometerUpdate(joystick);
799  } else if (device->controller) {
800  IOS_MFIJoystickUpdate(joystick);
801  }
802 }
static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
static SDL_AudioDeviceID device
Definition: loopwave.c:37
static void IOS_AccelerometerUpdate(SDL_Joystick *joystick)
#define NULL
Definition: begin_code.h:167
GCController __unsafe_unretained * controller

◆ IOS_MFIJoystickUpdate()

static void IOS_MFIJoystickUpdate ( SDL_Joystick *  joystick)
static

Definition at line 610 of file SDL_sysjoystick.m.

References sort_controllers::controllers, i, SDL_arraysize, SDL_CONTROLLER_BUTTON_BACK, SDL_CONTROLLER_BUTTON_LEFTSTICK, SDL_CONTROLLER_BUTTON_RIGHTSTICK, SDL_CONTROLLER_BUTTON_START, SDL_HAT_CENTERED, SDL_PRESSED, SDL_PrivateJoystickAxis(), SDL_PrivateJoystickButton(), SDL_PrivateJoystickHat(), and SDL_RELEASED.

Referenced by IOS_JoystickUpdate().

611 {
612 #if SDL_JOYSTICK_MFI
613  @autoreleasepool {
614  GCController *controller = joystick->hwdata->controller;
615  Uint8 hatstate = SDL_HAT_CENTERED;
616  int i;
617  int updateplayerindex = 0;
618  int pause_button_index = 0;
619 
620  if (controller.extendedGamepad) {
621  GCExtendedGamepad *gamepad = controller.extendedGamepad;
622 
623  /* Axis order matches the XInput Windows mappings. */
624  Sint16 axes[] = {
625  (Sint16) (gamepad.leftThumbstick.xAxis.value * 32767),
626  (Sint16) (gamepad.leftThumbstick.yAxis.value * -32767),
627  (Sint16) ((gamepad.leftTrigger.value * 65535) - 32768),
628  (Sint16) (gamepad.rightThumbstick.xAxis.value * 32767),
629  (Sint16) (gamepad.rightThumbstick.yAxis.value * -32767),
630  (Sint16) ((gamepad.rightTrigger.value * 65535) - 32768),
631  };
632 
633  /* Button order matches the XInput Windows mappings. */
634  Uint8 buttons[joystick->nbuttons];
635  int button_count = 0;
636 
637  /* These buttons are part of the original MFi spec */
638  buttons[button_count++] = gamepad.buttonA.isPressed;
639  buttons[button_count++] = gamepad.buttonB.isPressed;
640  buttons[button_count++] = gamepad.buttonX.isPressed;
641  buttons[button_count++] = gamepad.buttonY.isPressed;
642  buttons[button_count++] = gamepad.leftShoulder.isPressed;
643  buttons[button_count++] = gamepad.rightShoulder.isPressed;
644 
645  /* These buttons are available on some newer controllers */
646 #pragma clang diagnostic push
647 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
648  if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_LEFTSTICK)) {
649  buttons[button_count++] = gamepad.leftThumbstickButton.isPressed;
650  }
651  if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_RIGHTSTICK)) {
652  buttons[button_count++] = gamepad.rightThumbstickButton.isPressed;
653  }
654  if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_BACK)) {
655  buttons[button_count++] = gamepad.buttonOptions.isPressed;
656  }
657  /* This must be the last button, so we can optionally handle it with pause_button_index below */
658  if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_START)) {
659  if (joystick->hwdata->uses_pause_handler) {
660  pause_button_index = button_count;
661  buttons[button_count++] = joystick->delayed_guide_button;
662  } else {
663  buttons[button_count++] = gamepad.buttonMenu.isPressed;
664  }
665  }
666 #pragma clang diagnostic pop
667 
668  hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
669 
670  for (i = 0; i < SDL_arraysize(axes); i++) {
671  /* The triggers (axes 2 and 5) are resting at -32768 but SDL
672  * initializes its values to 0. We only want to make sure the
673  * player index is up to date if the user actually moves an axis. */
674  if ((i != 2 && i != 5) || axes[i] != -32768) {
675  updateplayerindex |= (joystick->axes[i].value != axes[i]);
676  }
677  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
678  }
679 
680  for (i = 0; i < button_count; i++) {
681  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
682  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
683  }
684  } else if (controller.gamepad) {
685  GCGamepad *gamepad = controller.gamepad;
686 
687  /* Button order matches the XInput Windows mappings. */
688  Uint8 buttons[joystick->nbuttons];
689  int button_count = 0;
690  buttons[button_count++] = gamepad.buttonA.isPressed;
691  buttons[button_count++] = gamepad.buttonB.isPressed;
692  buttons[button_count++] = gamepad.buttonX.isPressed;
693  buttons[button_count++] = gamepad.buttonY.isPressed;
694  buttons[button_count++] = gamepad.leftShoulder.isPressed;
695  buttons[button_count++] = gamepad.rightShoulder.isPressed;
696  pause_button_index = button_count;
697  buttons[button_count++] = joystick->delayed_guide_button;
698 
699  hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
700 
701  for (i = 0; i < button_count; i++) {
702  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
703  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
704  }
705  }
706 #if TARGET_OS_TV
707  else if (controller.microGamepad) {
708  GCMicroGamepad *gamepad = controller.microGamepad;
709 
710  Sint16 axes[] = {
711  (Sint16) (gamepad.dpad.xAxis.value * 32767),
712  (Sint16) (gamepad.dpad.yAxis.value * -32767),
713  };
714 
715  for (i = 0; i < SDL_arraysize(axes); i++) {
716  updateplayerindex |= (joystick->axes[i].value != axes[i]);
717  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
718  }
719 
720  Uint8 buttons[joystick->nbuttons];
721  int button_count = 0;
722  buttons[button_count++] = gamepad.buttonA.isPressed;
723  buttons[button_count++] = gamepad.buttonX.isPressed;
724 #pragma clang diagnostic push
725 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
726  /* This must be the last button, so we can optionally handle it with pause_button_index below */
727  if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_START)) {
728  if (joystick->hwdata->uses_pause_handler) {
729  pause_button_index = button_count;
730  buttons[button_count++] = joystick->delayed_guide_button;
731  } else {
732  buttons[button_count++] = gamepad.buttonMenu.isPressed;
733  }
734  }
735 #pragma clang diagnostic pop
736 
737  for (i = 0; i < button_count; i++) {
738  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
739  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
740  }
741  }
742 #endif /* TARGET_OS_TV */
743 
744  if (joystick->nhats > 0) {
745  updateplayerindex |= (joystick->hats[0] != hatstate);
746  SDL_PrivateJoystickHat(joystick, 0, hatstate);
747  }
748 
749  if (joystick->hwdata->uses_pause_handler) {
750  for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
751  SDL_PrivateJoystickButton(joystick, pause_button_index, SDL_PRESSED);
752  SDL_PrivateJoystickButton(joystick, pause_button_index, SDL_RELEASED);
753  updateplayerindex = YES;
754  }
755  joystick->hwdata->num_pause_presses = 0;
756  }
757 
758  if (updateplayerindex && controller.playerIndex == -1) {
759  BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};
760 
761  /* Find the player index of all other connected controllers. */
762  for (GCController *c in [GCController controllers]) {
763  if (c != controller && c.playerIndex >= 0) {
764  usedPlayerIndexSlots[c.playerIndex] = YES;
765  }
766  }
767 
768  /* Set this controller's player index to the first unused index.
769  * FIXME: This logic isn't great... but SDL doesn't expose this
770  * concept in its external API, so we don't have much to go on. */
771  for (i = 0; i < SDL_arraysize(usedPlayerIndexSlots); i++) {
772  if (!usedPlayerIndexSlots[i]) {
773  controller.playerIndex = i;
774  break;
775  }
776  }
777  }
778  }
779 #endif /* SDL_JOYSTICK_MFI */
780 }
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:890
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:966
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:833
uint8_t Uint8
Definition: SDL_stdinc.h:179
const GLubyte * c
GLsizei const GLfloat * value
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
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
#define SDL_PRESSED
Definition: SDL_events.h:50
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:329
#define SDL_RELEASED
Definition: SDL_events.h:49
GLuint in
int16_t Sint16
Definition: SDL_stdinc.h:185

◆ IOS_RemoveJoystickDevice()

static SDL_JoystickDeviceItem* IOS_RemoveJoystickDevice ( SDL_JoystickDeviceItem device)
static

Definition at line 320 of file SDL_sysjoystick.m.

References recDevice::controller, sort_controllers::controllers, deviceList, recDevice::instance_id, recDevice::joystick, recDevice::name, recDevice::next, NULL, numjoysticks, SDL_free, SDL_PrivateJoystickRemoved(), and SDLCALL.

Referenced by IOS_JoystickQuit().

321 {
325 
326  if (device == NULL) {
327  return NULL;
328  }
329 
330  next = device->next;
331 
332  while (item != NULL) {
333  if (item == device) {
334  break;
335  }
336  prev = item;
337  item = item->next;
338  }
339 
340  /* Unlink the device item from the device list. */
341  if (prev) {
342  prev->next = device->next;
343  } else if (device == deviceList) {
344  deviceList = device->next;
345  }
346 
347  if (device->joystick) {
348  device->joystick->hwdata = NULL;
349  }
350 
351 #ifdef SDL_JOYSTICK_MFI
352  @autoreleasepool {
353  if (device->controller) {
354  /* The controller was explicitly retained in the struct, so it
355  * should be explicitly released before freeing the struct. */
356  GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(device->controller));
357  controller.controllerPausedHandler = nil;
358  device->controller = nil;
359  }
360  }
361 #endif /* SDL_JOYSTICK_MFI */
362 
363  --numjoysticks;
364 
366 
367  SDL_free(device->name);
368  SDL_free(device);
369 
370  return next;
371 }
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
Definition: SDL_joystick.c:805
static SDL_JoystickDeviceItem * deviceList
SDL_Joystick * joystick
struct joystick_hwdata * next
struct hid_device_info * next
Definition: hidapi.h:82
#define SDL_free
#define NULL
Definition: begin_code.h:167
static int numjoysticks
GCController __unsafe_unretained * controller

Variable Documentation

◆ accelerometerName

const char* accelerometerName = "iOS Accelerometer"
static

Definition at line 77 of file SDL_sysjoystick.m.

Referenced by IOS_AddJoystickDevice().

◆ deviceList

SDL_JoystickDeviceItem* deviceList = NULL
static

◆ motionManager

CMMotionManager* motionManager = nil
static

Definition at line 78 of file SDL_sysjoystick.m.

Referenced by IOS_AccelerometerUpdate(), IOS_JoystickOpen(), and IOS_JoystickQuit().

◆ numjoysticks

int numjoysticks = 0
static

◆ SDL_AppleTVRemoteOpenedAsJoystick

int SDL_AppleTVRemoteOpenedAsJoystick = 0

Definition at line 84 of file SDL_sysjoystick.m.

Referenced by IOS_JoystickClose(), and IOS_JoystickOpen().

◆ SDL_IOS_JoystickDriver

SDL_JoystickDriver SDL_IOS_JoystickDriver
Initial value:
=
{
}
static int IOS_JoystickGetCount(void)
static void IOS_JoystickUpdate(SDL_Joystick *joystick)
static int IOS_JoystickInit(void)
static void IOS_JoystickDetect(void)
static SDL_JoystickID IOS_JoystickGetDeviceInstanceID(int device_index)
static const char * IOS_JoystickGetDeviceName(int device_index)
static void IOS_JoystickQuit(void)
static int IOS_JoystickOpen(SDL_Joystick *joystick, int device_index)
static SDL_JoystickGUID IOS_JoystickGetDeviceGUID(int device_index)
static int IOS_JoystickGetDevicePlayerIndex(int device_index)
static int IOS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
static void IOS_JoystickClose(SDL_Joystick *joystick)

Definition at line 868 of file SDL_sysjoystick.m.