SDL  2.0
SDL_gamecontroller.c
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 game controller API for Simple DirectMedia Layer */
24 
25 #include "SDL_events.h"
26 #include "SDL_assert.h"
27 #include "SDL_sysjoystick.h"
28 #include "SDL_hints.h"
29 #include "SDL_gamecontrollerdb.h"
30 
31 #if !SDL_EVENTS_DISABLED
32 #include "../events/SDL_events_c.h"
33 #endif
34 #define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
35 
36 #define SDL_CONTROLLER_PLATFORM_FIELD "platform:"
37 
38 /* a list of currently opened game controllers */
39 static SDL_GameController *SDL_gamecontrollers = NULL;
40 
41 /* keep track of the hat and mask value that transforms this hat movement into a button/axis press */
43 {
44  int hat;
46 };
47 
48 /* We need 36 entries for Android (as of SDL v2.0.4) */
49 #define k_nMaxReverseEntries 48
50 
51 /**
52  * We are encoding the "HAT" as 0xhm. where h == hat ID and m == mask
53  * MAX 4 hats supported
54  */
55 #define k_nMaxHatEntries 0x3f + 1
56 
57 /* our in memory mapping db between joystick objects and controller mappings */
59 {
61  const char *name;
62 
63  /* mapping of axis/button id to controller version */
65  int buttonasaxis[SDL_CONTROLLER_AXIS_MAX];
66 
68  int axesasbutton[SDL_CONTROLLER_BUTTON_MAX];
70 
71  /* reverse mapping, joystick indices to buttons */
74 
78 
79 };
80 
81 
82 /* our hard coded list of mapping support */
83 typedef struct _ControllerMapping_t
84 {
86  char *name;
87  char *mapping;
88  struct _ControllerMapping_t *next;
90 
94 
95 /* The SDL game controller structure */
97 {
98  SDL_Joystick *joystick; /* underlying joystick device */
99  int ref_count;
100  Uint8 hatState[4]; /* the current hat state for this controller */
101  struct _SDL_ControllerMapping mapping; /* the mapping object for this controller */
102  struct _SDL_GameController *next; /* pointer to next game controller we have allocated */
103 };
104 
105 
106 int SDL_PrivateGameControllerAxis(SDL_GameController * gamecontroller, SDL_GameControllerAxis axis, Sint16 value);
107 int SDL_PrivateGameControllerButton(SDL_GameController * gamecontroller, SDL_GameControllerButton button, Uint8 state);
108 
109 /*
110  * If there is an existing add event in the queue, it needs to be modified
111  * to have the right value for which, because the number of controllers in
112  * the system is now one less.
113  */
115 {
116  int i, num_events;
117  SDL_Event *events;
118 
120  if (num_events <= 0) {
121  return;
122  }
123 
124  events = SDL_stack_alloc(SDL_Event, num_events);
125  if (!events) {
126  return;
127  }
128 
130  for (i = 0; i < num_events; ++i) {
131  --events[i].cdevice.which;
132  }
133  SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
134 
135  SDL_stack_free(events);
136 }
137 
138 /*
139  * Event filter to fire controller events from joystick ones
140  */
142 {
143  switch(event->type) {
144  case SDL_JOYAXISMOTION:
145  {
146  SDL_GameController *controllerlist;
147 
148  if (event->jaxis.axis >= k_nMaxReverseEntries)
149  {
150  SDL_SetError("SDL_GameControllerEventWatcher: Axis index %d too large, ignoring motion", (int)event->jaxis.axis);
151  break;
152  }
153 
154  controllerlist = SDL_gamecontrollers;
155  while (controllerlist) {
156  if (controllerlist->joystick->instance_id == event->jaxis.which) {
157  if (controllerlist->mapping.raxes[event->jaxis.axis] >= 0) /* simple axis to axis, send it through */ {
158  SDL_GameControllerAxis axis = controllerlist->mapping.raxes[event->jaxis.axis];
159  Sint16 value = event->jaxis.value;
160  switch (axis) {
163  value = value / 2 + 16384;
164  break;
165  default:
166  break;
167  }
168  SDL_PrivateGameControllerAxis(controllerlist, axis, value);
169  } else if (controllerlist->mapping.raxesasbutton[event->jaxis.axis] >= 0) { /* simulate an axis as a button */
170  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.raxesasbutton[event->jaxis.axis], ABS(event->jaxis.value) > 32768/2 ? SDL_PRESSED : SDL_RELEASED);
171  }
172  break;
173  }
174  controllerlist = controllerlist->next;
175  }
176  }
177  break;
178  case SDL_JOYBUTTONDOWN:
179  case SDL_JOYBUTTONUP:
180  {
181  SDL_GameController *controllerlist;
182 
183  if (event->jbutton.button >= k_nMaxReverseEntries)
184  {
185  SDL_SetError("SDL_GameControllerEventWatcher: Button index %d too large, ignoring update", (int)event->jbutton.button);
186  break;
187  }
188 
189  controllerlist = SDL_gamecontrollers;
190  while (controllerlist) {
191  if (controllerlist->joystick->instance_id == event->jbutton.which) {
192  if (controllerlist->mapping.rbuttons[event->jbutton.button] >= 0) { /* simple button as button */
193  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rbuttons[event->jbutton.button], event->jbutton.state);
194  } else if (controllerlist->mapping.rbuttonasaxis[event->jbutton.button] >= 0) { /* an button pretending to be an axis */
195  SDL_PrivateGameControllerAxis(controllerlist, controllerlist->mapping.rbuttonasaxis[event->jbutton.button], event->jbutton.state > 0 ? 32767 : 0);
196  }
197  break;
198  }
199  controllerlist = controllerlist->next;
200  }
201  }
202  break;
203  case SDL_JOYHATMOTION:
204  {
205  SDL_GameController *controllerlist;
206 
207  if (event->jhat.hat >= 4) break;
208 
209  controllerlist = SDL_gamecontrollers;
210  while (controllerlist) {
211  if (controllerlist->joystick->instance_id == event->jhat.which) {
212  Uint8 bSame = controllerlist->hatState[event->jhat.hat] & event->jhat.value;
213  /* Get list of removed bits (button release) */
214  Uint8 bChanged = controllerlist->hatState[event->jhat.hat] ^ bSame;
215  /* the hat idx in the high nibble */
216  int bHighHat = event->jhat.hat << 4;
217 
218  if (bChanged & SDL_HAT_DOWN)
219  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_DOWN], SDL_RELEASED);
220  if (bChanged & SDL_HAT_UP)
221  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_UP], SDL_RELEASED);
222  if (bChanged & SDL_HAT_LEFT)
223  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_LEFT], SDL_RELEASED);
224  if (bChanged & SDL_HAT_RIGHT)
225  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_RIGHT], SDL_RELEASED);
226 
227  /* Get list of added bits (button press) */
228  bChanged = event->jhat.value ^ bSame;
229 
230  if (bChanged & SDL_HAT_DOWN)
231  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_DOWN], SDL_PRESSED);
232  if (bChanged & SDL_HAT_UP)
233  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_UP], SDL_PRESSED);
234  if (bChanged & SDL_HAT_LEFT)
235  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_LEFT], SDL_PRESSED);
236  if (bChanged & SDL_HAT_RIGHT)
237  SDL_PrivateGameControllerButton(controllerlist, controllerlist->mapping.rhatasbutton[bHighHat | SDL_HAT_RIGHT], SDL_PRESSED);
238 
239  /* update our state cache */
240  controllerlist->hatState[event->jhat.hat] = event->jhat.value;
241 
242  break;
243  }
244  controllerlist = controllerlist->next;
245  }
246  }
247  break;
248  case SDL_JOYDEVICEADDED:
249  {
250  if (SDL_IsGameController(event->jdevice.which)) {
251  SDL_Event deviceevent;
252  deviceevent.type = SDL_CONTROLLERDEVICEADDED;
253  deviceevent.cdevice.which = event->jdevice.which;
254  SDL_PushEvent(&deviceevent);
255  }
256  }
257  break;
259  {
260  SDL_GameController *controllerlist = SDL_gamecontrollers;
261  while (controllerlist) {
262  if (controllerlist->joystick->instance_id == event->jdevice.which) {
263  SDL_Event deviceevent;
264 
265  deviceevent.type = SDL_CONTROLLERDEVICEREMOVED;
266  deviceevent.cdevice.which = event->jdevice.which;
267  SDL_PushEvent(&deviceevent);
268 
270  break;
271  }
272  controllerlist = controllerlist->next;
273  }
274  }
275  break;
276  default:
277  break;
278  }
279 
280  return 1;
281 }
282 
283 /*
284  * Helper function to scan the mappings database for a controller with the specified GUID
285  */
287 {
288  ControllerMapping_t *pSupportedController = s_pSupportedControllers;
289  while (pSupportedController) {
290  if (SDL_memcmp(guid, &pSupportedController->guid, sizeof(*guid)) == 0) {
291  return pSupportedController;
292  }
293  pSupportedController = pSupportedController->next;
294  }
295  return NULL;
296 }
297 
298 static const char* map_StringForControllerAxis[] = {
299  "leftx",
300  "lefty",
301  "rightx",
302  "righty",
303  "lefttrigger",
304  "righttrigger",
305  NULL
306 };
307 
308 /*
309  * convert a string to its enum equivalent
310  */
312 {
313  int entry;
314  if (!pchString || !pchString[0])
316 
317  for (entry = 0; map_StringForControllerAxis[entry]; ++entry) {
318  if (!SDL_strcasecmp(pchString, map_StringForControllerAxis[entry]))
319  return entry;
320  }
322 }
323 
324 /*
325  * convert an enum to its string equivalent
326  */
328 {
331  }
332  return NULL;
333 }
334 
335 static const char* map_StringForControllerButton[] = {
336  "a",
337  "b",
338  "x",
339  "y",
340  "back",
341  "guide",
342  "start",
343  "leftstick",
344  "rightstick",
345  "leftshoulder",
346  "rightshoulder",
347  "dpup",
348  "dpdown",
349  "dpleft",
350  "dpright",
351  NULL
352 };
353 
354 /*
355  * convert a string to its enum equivalent
356  */
358 {
359  int entry;
360  if (!pchString || !pchString[0])
362 
363  for (entry = 0; map_StringForControllerButton[entry]; ++entry) {
364  if (SDL_strcasecmp(pchString, map_StringForControllerButton[entry]) == 0)
365  return entry;
366  }
368 }
369 
370 /*
371  * convert an enum to its string equivalent
372  */
374 {
377  }
378  return NULL;
379 }
380 
381 /*
382  * given a controller button name and a joystick name update our mapping structure with it
383  */
384 void SDL_PrivateGameControllerParseButton(const char *szGameButton, const char *szJoystickButton, struct _SDL_ControllerMapping *pMapping)
385 {
386  int iSDLButton = 0;
389  button = SDL_GameControllerGetButtonFromString(szGameButton);
390  axis = SDL_GameControllerGetAxisFromString(szGameButton);
391  iSDLButton = SDL_atoi(&szJoystickButton[1]);
392 
393  if (szJoystickButton[0] == 'a') {
394  if (iSDLButton >= k_nMaxReverseEntries) {
395  SDL_SetError("Axis index too large: %d", iSDLButton);
396  return;
397  }
398  if (axis != SDL_CONTROLLER_AXIS_INVALID) {
399  pMapping->axes[ axis ] = iSDLButton;
400  pMapping->raxes[ iSDLButton ] = axis;
401  } else if (button != SDL_CONTROLLER_BUTTON_INVALID) {
402  pMapping->axesasbutton[ button ] = iSDLButton;
403  pMapping->raxesasbutton[ iSDLButton ] = button;
404  } else {
405  SDL_assert(!"How did we get here?");
406  }
407 
408  } else if (szJoystickButton[0] == 'b') {
409  if (iSDLButton >= k_nMaxReverseEntries) {
410  SDL_SetError("Button index too large: %d", iSDLButton);
411  return;
412  }
413  if (button != SDL_CONTROLLER_BUTTON_INVALID) {
414  pMapping->buttons[ button ] = iSDLButton;
415  pMapping->rbuttons[ iSDLButton ] = button;
416  } else if (axis != SDL_CONTROLLER_AXIS_INVALID) {
417  pMapping->buttonasaxis[ axis ] = iSDLButton;
418  pMapping->rbuttonasaxis[ iSDLButton ] = axis;
419  } else {
420  SDL_assert(!"How did we get here?");
421  }
422  } else if (szJoystickButton[0] == 'h') {
423  int hat = SDL_atoi(&szJoystickButton[1]);
424  int mask = SDL_atoi(&szJoystickButton[3]);
425  if (hat >= 4) {
426  SDL_SetError("Hat index too large: %d", iSDLButton);
427  }
428 
429  if (button != SDL_CONTROLLER_BUTTON_INVALID) {
430  int ridx;
431  pMapping->hatasbutton[ button ].hat = hat;
432  pMapping->hatasbutton[ button ].mask = mask;
433  ridx = (hat << 4) | mask;
434  pMapping->rhatasbutton[ ridx ] = button;
435  } else if (axis != SDL_CONTROLLER_AXIS_INVALID) {
436  SDL_assert(!"Support hat as axis");
437  } else {
438  SDL_assert(!"How did we get here?");
439  }
440  }
441 }
442 
443 
444 /*
445  * given a controller mapping string update our mapping object
446  */
447 static void
449 {
450  char szGameButton[20];
451  char szJoystickButton[20];
452  SDL_bool bGameButton = SDL_TRUE;
453  int i = 0;
454  const char *pchPos = pchString;
455 
456  SDL_memset(szGameButton, 0x0, sizeof(szGameButton));
457  SDL_memset(szJoystickButton, 0x0, sizeof(szJoystickButton));
458 
459  while (pchPos && *pchPos) {
460  if (*pchPos == ':') {
461  i = 0;
462  bGameButton = SDL_FALSE;
463  } else if (*pchPos == ' ') {
464 
465  } else if (*pchPos == ',') {
466  i = 0;
467  bGameButton = SDL_TRUE;
468  SDL_PrivateGameControllerParseButton(szGameButton, szJoystickButton, pMapping);
469  SDL_memset(szGameButton, 0x0, sizeof(szGameButton));
470  SDL_memset(szJoystickButton, 0x0, sizeof(szJoystickButton));
471 
472  } else if (bGameButton) {
473  if (i >= sizeof(szGameButton)) {
474  SDL_SetError("Button name too large: %s", szGameButton);
475  return;
476  }
477  szGameButton[i] = *pchPos;
478  i++;
479  } else {
480  if (i >= sizeof(szJoystickButton)) {
481  SDL_SetError("Joystick button name too large: %s", szJoystickButton);
482  return;
483  }
484  szJoystickButton[i] = *pchPos;
485  i++;
486  }
487  pchPos++;
488  }
489 
490  SDL_PrivateGameControllerParseButton(szGameButton, szJoystickButton, pMapping);
491 
492 }
493 
494 /*
495  * Make a new button mapping struct
496  */
497 void SDL_PrivateLoadButtonMapping(struct _SDL_ControllerMapping *pMapping, SDL_JoystickGUID guid, const char *pchName, const char *pchMapping)
498 {
499  int j;
500 
501  pMapping->guid = guid;
502  pMapping->name = pchName;
503 
504  /* set all the button mappings to non defaults */
505  for (j = 0; j < SDL_CONTROLLER_AXIS_MAX; j++) {
506  pMapping->axes[j] = -1;
507  pMapping->buttonasaxis[j] = -1;
508  }
509  for (j = 0; j < SDL_CONTROLLER_BUTTON_MAX; j++) {
510  pMapping->buttons[j] = -1;
511  pMapping->axesasbutton[j] = -1;
512  pMapping->hatasbutton[j].hat = -1;
513  }
514 
515  for (j = 0; j < k_nMaxReverseEntries; j++) {
516  pMapping->raxes[j] = SDL_CONTROLLER_AXIS_INVALID;
520  }
521 
522  for (j = 0; j < k_nMaxHatEntries; j++) {
524  }
525 
527 }
528 
529 
530 /*
531  * grab the guid string from a mapping string
532  */
534 {
535  const char *pFirstComma = SDL_strchr(pMapping, ',');
536  if (pFirstComma) {
537  char *pchGUID = SDL_malloc(pFirstComma - pMapping + 1);
538  if (!pchGUID) {
539  SDL_OutOfMemory();
540  return NULL;
541  }
542  SDL_memcpy(pchGUID, pMapping, pFirstComma - pMapping);
543  pchGUID[ pFirstComma - pMapping ] = 0;
544  return pchGUID;
545  }
546  return NULL;
547 }
548 
549 
550 /*
551  * grab the name string from a mapping string
552  */
554 {
555  const char *pFirstComma, *pSecondComma;
556  char *pchName;
557 
558  pFirstComma = SDL_strchr(pMapping, ',');
559  if (!pFirstComma)
560  return NULL;
561 
562  pSecondComma = SDL_strchr(pFirstComma + 1, ',');
563  if (!pSecondComma)
564  return NULL;
565 
566  pchName = SDL_malloc(pSecondComma - pFirstComma);
567  if (!pchName) {
568  SDL_OutOfMemory();
569  return NULL;
570  }
571  SDL_memcpy(pchName, pFirstComma + 1, pSecondComma - pFirstComma);
572  pchName[ pSecondComma - pFirstComma - 1 ] = 0;
573  return pchName;
574 }
575 
576 
577 /*
578  * grab the button mapping string from a mapping string
579  */
581 {
582  const char *pFirstComma, *pSecondComma;
583 
584  pFirstComma = SDL_strchr(pMapping, ',');
585  if (!pFirstComma)
586  return NULL;
587 
588  pSecondComma = SDL_strchr(pFirstComma + 1, ',');
589  if (!pSecondComma)
590  return NULL;
591 
592  return SDL_strdup(pSecondComma + 1); /* mapping is everything after the 3rd comma */
593 }
594 
595 /*
596  * Helper function to refresh a mapping
597  */
599 {
600  SDL_GameController *gamecontrollerlist = SDL_gamecontrollers;
601  while (gamecontrollerlist) {
602  if (!SDL_memcmp(&gamecontrollerlist->mapping.guid, &pControllerMapping->guid, sizeof(pControllerMapping->guid))) {
604  event.type = SDL_CONTROLLERDEVICEREMAPPED;
605  event.cdevice.which = gamecontrollerlist->joystick->instance_id;
606  SDL_PushEvent(&event);
607 
608  /* Not really threadsafe. Should this lock access within SDL_GameControllerEventWatcher? */
609  SDL_PrivateLoadButtonMapping(&gamecontrollerlist->mapping, pControllerMapping->guid, pControllerMapping->name, pControllerMapping->mapping);
610  }
611 
612  gamecontrollerlist = gamecontrollerlist->next;
613  }
614 }
615 
616 /*
617  * Helper function to add a mapping for a guid
618  */
619 static ControllerMapping_t *
620 SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, SDL_bool *existing)
621 {
622  char *pchName;
623  char *pchMapping;
624  ControllerMapping_t *pControllerMapping;
625 
626  pchName = SDL_PrivateGetControllerNameFromMappingString(mappingString);
627  if (!pchName) {
628  SDL_SetError("Couldn't parse name from %s", mappingString);
629  return NULL;
630  }
631 
632  pchMapping = SDL_PrivateGetControllerMappingFromMappingString(mappingString);
633  if (!pchMapping) {
634  SDL_free(pchName);
635  SDL_SetError("Couldn't parse %s", mappingString);
636  return NULL;
637  }
638 
639  pControllerMapping = SDL_PrivateGetControllerMappingForGUID(&jGUID);
640  if (pControllerMapping) {
641  /* Update existing mapping */
642  SDL_free(pControllerMapping->name);
643  pControllerMapping->name = pchName;
644  SDL_free(pControllerMapping->mapping);
645  pControllerMapping->mapping = pchMapping;
646  /* refresh open controllers */
647  SDL_PrivateGameControllerRefreshMapping(pControllerMapping);
648  *existing = SDL_TRUE;
649  } else {
650  pControllerMapping = SDL_malloc(sizeof(*pControllerMapping));
651  if (!pControllerMapping) {
652  SDL_free(pchName);
653  SDL_free(pchMapping);
654  SDL_OutOfMemory();
655  return NULL;
656  }
657  pControllerMapping->guid = jGUID;
658  pControllerMapping->name = pchName;
659  pControllerMapping->mapping = pchMapping;
660  pControllerMapping->next = s_pSupportedControllers;
661  s_pSupportedControllers = pControllerMapping;
662  *existing = SDL_FALSE;
663  }
664  return pControllerMapping;
665 }
666 
667 /*
668  * Helper function to determine pre-calculated offset to certain joystick mappings
669  */
671 {
672  SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
674 
675  mapping = SDL_PrivateGetControllerMappingForGUID(&jGUID);
676 #if SDL_JOYSTICK_XINPUT
677  if (!mapping && SDL_SYS_IsXInputGamepad_DeviceIndex(device_index)) {
678  mapping = s_pXInputMapping;
679  }
680 #endif
681 #if defined(SDL_JOYSTICK_EMSCRIPTEN)
682  if (!mapping && s_pEmscriptenMapping) {
683  mapping = s_pEmscriptenMapping;
684  }
685 #endif
686 #ifdef __LINUX__
687  if (!mapping) {
688  const char *name = SDL_JoystickNameForIndex(device_index);
689  if (name) {
690  if (SDL_strstr(name, "Xbox 360 Wireless Receiver")) {
691  /* The Linux driver xpad.c maps the wireless dpad to buttons */
692  SDL_bool existing;
693  mapping = SDL_PrivateAddMappingForGUID(jGUID,
694 "none,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
695  &existing);
696  }
697  }
698  }
699 #endif /* __LINUX__ */
700 
701  if (!mapping) {
702  const char *name = SDL_JoystickNameForIndex(device_index);
703  if (name) {
704  if (SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box")) {
705  mapping = s_pXInputMapping;
706  }
707  }
708  }
709  return mapping;
710 }
711 
712 /*
713  * Add or update an entry into the Mappings Database
714  */
715 int
717 {
718  const char *platform = SDL_GetPlatform();
719  int controllers = 0;
720  char *buf, *line, *line_end, *tmp, *comma, line_platform[64];
721  size_t db_size, platform_len;
722 
723  if (rw == NULL) {
724  return SDL_SetError("Invalid RWops");
725  }
726  db_size = (size_t)SDL_RWsize(rw);
727 
728  buf = (char *)SDL_malloc(db_size + 1);
729  if (buf == NULL) {
730  if (freerw) {
731  SDL_RWclose(rw);
732  }
733  return SDL_SetError("Could not allocate space to read DB into memory");
734  }
735 
736  if (SDL_RWread(rw, buf, db_size, 1) != 1) {
737  if (freerw) {
738  SDL_RWclose(rw);
739  }
740  SDL_free(buf);
741  return SDL_SetError("Could not read DB");
742  }
743 
744  if (freerw) {
745  SDL_RWclose(rw);
746  }
747 
748  buf[db_size] = '\0';
749  line = buf;
750 
751  while (line < buf + db_size) {
752  line_end = SDL_strchr(line, '\n');
753  if (line_end != NULL) {
754  *line_end = '\0';
755  } else {
756  line_end = buf + db_size;
757  }
758 
759  /* Extract and verify the platform */
761  if (tmp != NULL) {
763  comma = SDL_strchr(tmp, ',');
764  if (comma != NULL) {
765  platform_len = comma - tmp + 1;
766  if (platform_len + 1 < SDL_arraysize(line_platform)) {
767  SDL_strlcpy(line_platform, tmp, platform_len);
768  if (SDL_strncasecmp(line_platform, platform, platform_len) == 0 &&
769  SDL_GameControllerAddMapping(line) > 0) {
770  controllers++;
771  }
772  }
773  }
774  }
775 
776  line = line_end + 1;
777  }
778 
779  SDL_free(buf);
780  return controllers;
781 }
782 
783 /*
784  * Add or update an entry into the Mappings Database
785  */
786 int
787 SDL_GameControllerAddMapping(const char *mappingString)
788 {
789  char *pchGUID;
790  SDL_JoystickGUID jGUID;
791  SDL_bool is_xinput_mapping = SDL_FALSE;
792  SDL_bool is_emscripten_mapping = SDL_FALSE;
793  SDL_bool existing = SDL_FALSE;
794  ControllerMapping_t *pControllerMapping;
795 
796  if (!mappingString) {
797  return SDL_InvalidParamError("mappingString");
798  }
799 
800  pchGUID = SDL_PrivateGetControllerGUIDFromMappingString(mappingString);
801  if (!pchGUID) {
802  return SDL_SetError("Couldn't parse GUID from %s", mappingString);
803  }
804  if (!SDL_strcasecmp(pchGUID, "xinput")) {
805  is_xinput_mapping = SDL_TRUE;
806  }
807  if (!SDL_strcasecmp(pchGUID, "emscripten")) {
808  is_emscripten_mapping = SDL_TRUE;
809  }
810  jGUID = SDL_JoystickGetGUIDFromString(pchGUID);
811  SDL_free(pchGUID);
812 
813  pControllerMapping = SDL_PrivateAddMappingForGUID(jGUID, mappingString, &existing);
814  if (!pControllerMapping) {
815  return -1;
816  }
817 
818  if (existing) {
819  return 0;
820  } else {
821  if (is_xinput_mapping) {
822  s_pXInputMapping = pControllerMapping;
823  }
824  if (is_emscripten_mapping) {
825  s_pEmscriptenMapping = pControllerMapping;
826  }
827  return 1;
828  }
829 }
830 
831 /*
832  * Get the mapping string for this GUID
833  */
834 char *
836 {
837  char *pMappingString = NULL;
839  if (mapping) {
840  char pchGUID[33];
841  size_t needed;
842  SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID));
843  /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */
844  needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1;
845  pMappingString = SDL_malloc(needed);
846  if (!pMappingString) {
847  SDL_OutOfMemory();
848  return NULL;
849  }
850  SDL_snprintf(pMappingString, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping);
851  }
852  return pMappingString;
853 }
854 
855 /*
856  * Get the mapping string for this device
857  */
858 char *
859 SDL_GameControllerMapping(SDL_GameController * gamecontroller)
860 {
861  if (!gamecontroller) {
862  return NULL;
863  }
864 
865  return SDL_GameControllerMappingForGUID(gamecontroller->mapping.guid);
866 }
867 
868 static void
870 {
871  const char *hint = SDL_GetHint(SDL_HINT_GAMECONTROLLERCONFIG);
872  if (hint && hint[0]) {
873  size_t nchHints = SDL_strlen(hint);
874  char *pUserMappings = SDL_malloc(nchHints + 1);
875  char *pTempMappings = pUserMappings;
876  SDL_memcpy(pUserMappings, hint, nchHints);
877  pUserMappings[nchHints] = '\0';
878  while (pUserMappings) {
879  char *pchNewLine = NULL;
880 
881  pchNewLine = SDL_strchr(pUserMappings, '\n');
882  if (pchNewLine)
883  *pchNewLine = '\0';
884 
885  SDL_GameControllerAddMapping(pUserMappings);
886 
887  if (pchNewLine) {
888  pUserMappings = pchNewLine + 1;
889  } else {
890  pUserMappings = NULL;
891  }
892  }
893  SDL_free(pTempMappings);
894  }
895 }
896 
897 /*
898  * Initialize the game controller system, mostly load our DB of controller config mappings
899  */
900 int
902 {
903  int i = 0;
904  const char *pMappingString = NULL;
905  pMappingString = s_ControllerMappings[i];
906  while (pMappingString) {
907  SDL_GameControllerAddMapping(pMappingString);
908 
909  i++;
910  pMappingString = s_ControllerMappings[i];
911  }
912 
913  /* load in any user supplied config */
915 
916  /* watch for joy events and fire controller ones if needed */
918 
919  /* Send added events for controllers currently attached */
920  for (i = 0; i < SDL_NumJoysticks(); ++i) {
921  if (SDL_IsGameController(i)) {
922  SDL_Event deviceevent;
923  deviceevent.type = SDL_CONTROLLERDEVICEADDED;
924  deviceevent.cdevice.which = i;
925  SDL_PushEvent(&deviceevent);
926  }
927  }
928 
929  return (0);
930 }
931 
932 
933 /*
934  * Get the implementation dependent name of a controller
935  */
936 const char *
938 {
939  ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(device_index);
940  if (pSupportedController) {
941  return pSupportedController->name;
942  }
943  return NULL;
944 }
945 
946 
947 /*
948  * Return 1 if the joystick at this device index is a supported controller
949  */
950 SDL_bool
951 SDL_IsGameController(int device_index)
952 {
953  ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(device_index);
954  if (pSupportedController) {
955  return SDL_TRUE;
956  }
957 
958  return SDL_FALSE;
959 }
960 
961 /*
962  * Open a controller for use - the index passed as an argument refers to
963  * the N'th controller on the system. This index is the value which will
964  * identify this controller in future controller events.
965  *
966  * This function returns a controller identifier, or NULL if an error occurred.
967  */
968 SDL_GameController *
969 SDL_GameControllerOpen(int device_index)
970 {
971  SDL_GameController *gamecontroller;
972  SDL_GameController *gamecontrollerlist;
973  ControllerMapping_t *pSupportedController = NULL;
974 
975  if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
976  SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
977  return (NULL);
978  }
979 
980  gamecontrollerlist = SDL_gamecontrollers;
981  /* If the controller is already open, return it */
982  while (gamecontrollerlist) {
983  if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == gamecontrollerlist->joystick->instance_id) {
984  gamecontroller = gamecontrollerlist;
985  ++gamecontroller->ref_count;
986  return (gamecontroller);
987  }
988  gamecontrollerlist = gamecontrollerlist->next;
989  }
990 
991  /* Find a controller mapping */
992  pSupportedController = SDL_PrivateGetControllerMapping(device_index);
993  if (!pSupportedController) {
994  SDL_SetError("Couldn't find mapping for device (%d)", device_index);
995  return (NULL);
996  }
997 
998  /* Create and initialize the joystick */
999  gamecontroller = (SDL_GameController *) SDL_malloc((sizeof *gamecontroller));
1000  if (gamecontroller == NULL) {
1001  SDL_OutOfMemory();
1002  return NULL;
1003  }
1004 
1005  SDL_memset(gamecontroller, 0, (sizeof *gamecontroller));
1006  gamecontroller->joystick = SDL_JoystickOpen(device_index);
1007  if (!gamecontroller->joystick) {
1008  SDL_free(gamecontroller);
1009  return NULL;
1010  }
1011 
1012  SDL_PrivateLoadButtonMapping(&gamecontroller->mapping, pSupportedController->guid, pSupportedController->name, pSupportedController->mapping);
1013 
1014  /* The triggers are mapped from -32768 to 32767, where -32768 is the 'unpressed' value */
1015  {
1016  int leftTriggerMapping = gamecontroller->mapping.axes[SDL_CONTROLLER_AXIS_TRIGGERLEFT];
1017  int rightTriggerMapping = gamecontroller->mapping.axes[SDL_CONTROLLER_AXIS_TRIGGERRIGHT];
1018  if (leftTriggerMapping >= 0) {
1019  gamecontroller->joystick->axes[leftTriggerMapping] =
1020  gamecontroller->joystick->axes_zero[leftTriggerMapping] = (Sint16)-32768;
1021  }
1022  if (rightTriggerMapping >= 0) {
1023  gamecontroller->joystick->axes[rightTriggerMapping] =
1024  gamecontroller->joystick->axes_zero[rightTriggerMapping] = (Sint16)-32768;
1025  }
1026  }
1027 
1028  /* Add joystick to list */
1029  ++gamecontroller->ref_count;
1030  /* Link the joystick in the list */
1031  gamecontroller->next = SDL_gamecontrollers;
1032  SDL_gamecontrollers = gamecontroller;
1033 
1034  SDL_SYS_JoystickUpdate(gamecontroller->joystick);
1035 
1036  return (gamecontroller);
1037 }
1038 
1039 /*
1040  * Manually pump for controller updates.
1041  */
1042 void
1044 {
1045  /* Just for API completeness; the joystick API does all the work. */
1047 }
1048 
1049 
1050 /*
1051  * Get the current state of an axis control on a controller
1052  */
1053 Sint16
1054 SDL_GameControllerGetAxis(SDL_GameController * gamecontroller, SDL_GameControllerAxis axis)
1055 {
1056  if (!gamecontroller)
1057  return 0;
1058 
1059  if (gamecontroller->mapping.axes[axis] >= 0) {
1060  Sint16 value = (SDL_JoystickGetAxis(gamecontroller->joystick, gamecontroller->mapping.axes[axis]));
1061  switch (axis) {
1064  /* Shift it to be 0 - 32767 */
1065  value = value / 2 + 16384;
1066  default:
1067  break;
1068  }
1069  return value;
1070  } else if (gamecontroller->mapping.buttonasaxis[axis] >= 0) {
1071  Uint8 value;
1072  value = SDL_JoystickGetButton(gamecontroller->joystick, gamecontroller->mapping.buttonasaxis[axis]);
1073  if (value > 0)
1074  return 32767;
1075  return 0;
1076  }
1077  return 0;
1078 }
1079 
1080 
1081 /*
1082  * Get the current state of a button on a controller
1083  */
1084 Uint8
1085 SDL_GameControllerGetButton(SDL_GameController * gamecontroller, SDL_GameControllerButton button)
1086 {
1087  if (!gamecontroller)
1088  return 0;
1089 
1090  if (gamecontroller->mapping.buttons[button] >= 0) {
1091  return (SDL_JoystickGetButton(gamecontroller->joystick, gamecontroller->mapping.buttons[button]));
1092  } else if (gamecontroller->mapping.axesasbutton[button] >= 0) {
1093  Sint16 value;
1094  value = SDL_JoystickGetAxis(gamecontroller->joystick, gamecontroller->mapping.axesasbutton[button]);
1095  if (ABS(value) > 32768/2)
1096  return 1;
1097  return 0;
1098  } else if (gamecontroller->mapping.hatasbutton[button].hat >= 0) {
1099  Uint8 value;
1100  value = SDL_JoystickGetHat(gamecontroller->joystick, gamecontroller->mapping.hatasbutton[button].hat);
1101 
1102  if (value & gamecontroller->mapping.hatasbutton[button].mask)
1103  return 1;
1104  return 0;
1105  }
1106 
1107  return 0;
1108 }
1109 
1110 /*
1111  * Return if the joystick in question is currently attached to the system,
1112  * \return 0 if not plugged in, 1 if still present.
1113  */
1114 SDL_bool
1115 SDL_GameControllerGetAttached(SDL_GameController * gamecontroller)
1116 {
1117  if (!gamecontroller)
1118  return SDL_FALSE;
1119 
1120  return SDL_JoystickGetAttached(gamecontroller->joystick);
1121 }
1122 
1123 
1124 const char *
1125 SDL_GameControllerName(SDL_GameController * gamecontroller)
1126 {
1127  if (!gamecontroller)
1128  return NULL;
1129 
1130  return (gamecontroller->mapping.name);
1131 }
1132 
1133 
1134 /*
1135  * Get the joystick for this controller
1136  */
1137 SDL_Joystick *SDL_GameControllerGetJoystick(SDL_GameController * gamecontroller)
1138 {
1139  if (!gamecontroller)
1140  return NULL;
1141 
1142  return gamecontroller->joystick;
1143 }
1144 
1145 
1146 /*
1147  * Find the SDL_GameController that owns this instance id
1148  */
1149 SDL_GameController *
1151 {
1152  SDL_GameController *gamecontroller = SDL_gamecontrollers;
1153  while (gamecontroller) {
1154  if (gamecontroller->joystick->instance_id == joyid) {
1155  return gamecontroller;
1156  }
1157  gamecontroller = gamecontroller->next;
1158  }
1159 
1160  return NULL;
1161 }
1162 
1163 
1164 /**
1165  * Get the SDL joystick layer binding for this controller axis mapping
1166  */
1168 {
1170  SDL_memset(&bind, 0x0, sizeof(bind));
1171 
1172  if (!gamecontroller || axis == SDL_CONTROLLER_AXIS_INVALID)
1173  return bind;
1174 
1175  if (gamecontroller->mapping.axes[axis] >= 0) {
1177  bind.value.button = gamecontroller->mapping.axes[axis];
1178  } else if (gamecontroller->mapping.buttonasaxis[axis] >= 0) {
1180  bind.value.button = gamecontroller->mapping.buttonasaxis[axis];
1181  }
1182 
1183  return bind;
1184 }
1185 
1186 
1187 /**
1188  * Get the SDL joystick layer binding for this controller button mapping
1189  */
1191 {
1193  SDL_memset(&bind, 0x0, sizeof(bind));
1194 
1195  if (!gamecontroller || button == SDL_CONTROLLER_BUTTON_INVALID)
1196  return bind;
1197 
1198  if (gamecontroller->mapping.buttons[button] >= 0) {
1200  bind.value.button = gamecontroller->mapping.buttons[button];
1201  } else if (gamecontroller->mapping.axesasbutton[button] >= 0) {
1203  bind.value.axis = gamecontroller->mapping.axesasbutton[button];
1204  } else if (gamecontroller->mapping.hatasbutton[button].hat >= 0) {
1206  bind.value.hat.hat = gamecontroller->mapping.hatasbutton[button].hat;
1207  bind.value.hat.hat_mask = gamecontroller->mapping.hatasbutton[button].mask;
1208  }
1209 
1210  return bind;
1211 }
1212 
1213 
1214 void
1215 SDL_GameControllerClose(SDL_GameController * gamecontroller)
1216 {
1217  SDL_GameController *gamecontrollerlist, *gamecontrollerlistprev;
1218 
1219  if (!gamecontroller)
1220  return;
1221 
1222  /* First decrement ref count */
1223  if (--gamecontroller->ref_count > 0) {
1224  return;
1225  }
1226 
1227  SDL_JoystickClose(gamecontroller->joystick);
1228 
1229  gamecontrollerlist = SDL_gamecontrollers;
1230  gamecontrollerlistprev = NULL;
1231  while (gamecontrollerlist) {
1232  if (gamecontroller == gamecontrollerlist) {
1233  if (gamecontrollerlistprev) {
1234  /* unlink this entry */
1235  gamecontrollerlistprev->next = gamecontrollerlist->next;
1236  } else {
1237  SDL_gamecontrollers = gamecontroller->next;
1238  }
1239 
1240  break;
1241  }
1242  gamecontrollerlistprev = gamecontrollerlist;
1243  gamecontrollerlist = gamecontrollerlist->next;
1244  }
1245 
1246  SDL_free(gamecontroller);
1247 }
1248 
1249 
1250 /*
1251  * Quit the controller subsystem
1252  */
1253 void
1255 {
1256  ControllerMapping_t *pControllerMap;
1257  while (SDL_gamecontrollers) {
1258  SDL_gamecontrollers->ref_count = 1;
1260  }
1261 
1262  while (s_pSupportedControllers) {
1263  pControllerMap = s_pSupportedControllers;
1264  s_pSupportedControllers = s_pSupportedControllers->next;
1265  SDL_free(pControllerMap->name);
1266  SDL_free(pControllerMap->mapping);
1267  SDL_free(pControllerMap);
1268  }
1269 
1271 
1272 }
1273 
1274 /*
1275  * Event filter to transform joystick events into appropriate game controller ones
1276  */
1277 int
1279 {
1280  int posted;
1281 
1282  /* translate the event, if desired */
1283  posted = 0;
1284 #if !SDL_EVENTS_DISABLED
1286  SDL_Event event;
1287  event.type = SDL_CONTROLLERAXISMOTION;
1288  event.caxis.which = gamecontroller->joystick->instance_id;
1289  event.caxis.axis = axis;
1290  event.caxis.value = value;
1291  posted = SDL_PushEvent(&event) == 1;
1292  }
1293 #endif /* !SDL_EVENTS_DISABLED */
1294  return (posted);
1295 }
1296 
1297 
1298 /*
1299  * Event filter to transform joystick events into appropriate game controller ones
1300  */
1301 int
1303 {
1304  int posted;
1305 #if !SDL_EVENTS_DISABLED
1306  SDL_Event event;
1307 
1308  if (button == SDL_CONTROLLER_BUTTON_INVALID)
1309  return (0);
1310 
1311  switch (state) {
1312  case SDL_PRESSED:
1313  event.type = SDL_CONTROLLERBUTTONDOWN;
1314  break;
1315  case SDL_RELEASED:
1316  event.type = SDL_CONTROLLERBUTTONUP;
1317  break;
1318  default:
1319  /* Invalid state -- bail */
1320  return (0);
1321  }
1322 #endif /* !SDL_EVENTS_DISABLED */
1323 
1324  /* translate the event, if desired */
1325  posted = 0;
1326 #if !SDL_EVENTS_DISABLED
1327  if (SDL_GetEventState(event.type) == SDL_ENABLE) {
1328  event.cbutton.which = gamecontroller->joystick->instance_id;
1329  event.cbutton.button = button;
1330  event.cbutton.state = state;
1331  posted = SDL_PushEvent(&event) == 1;
1332  }
1333 #endif /* !SDL_EVENTS_DISABLED */
1334  return (posted);
1335 }
1336 
1337 /*
1338  * Turn off controller events
1339  */
1340 int
1342 {
1343 #if SDL_EVENTS_DISABLED
1344  return SDL_IGNORE;
1345 #else
1346  const Uint32 event_list[] = {
1349  };
1350  unsigned int i;
1351 
1352  switch (state) {
1353  case SDL_QUERY:
1354  state = SDL_IGNORE;
1355  for (i = 0; i < SDL_arraysize(event_list); ++i) {
1356  state = SDL_EventState(event_list[i], SDL_QUERY);
1357  if (state == SDL_ENABLE) {
1358  break;
1359  }
1360  }
1361  break;
1362  default:
1363  for (i = 0; i < SDL_arraysize(event_list); ++i) {
1364  SDL_EventState(event_list[i], state);
1365  }
1366  break;
1367  }
1368  return (state);
1369 #endif /* SDL_EVENTS_DISABLED */
1370 }
1371 
1372 /* vi: set ts=4 sw=4 expandtab: */
static const char * map_StringForControllerAxis[]
#define SDL_strlcpy
char * SDL_GameControllerMapping(SDL_GameController *gamecontroller)
SDL_JoystickID which
Definition: SDL_events.h:335
char * SDL_PrivateGetControllerMappingFromMappingString(const char *pMapping)
#define SDL_DelEventWatch
static ControllerMapping_t * SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, SDL_bool *existing)
#define SDL_CONTROLLER_PLATFORM_FIELD
struct _SDL_HatMapping hatasbutton[SDL_CONTROLLER_BUTTON_MAX]
int buttons[SDL_CONTROLLER_BUTTON_MAX]
#define SDL_JoystickGetButton
SDL_GameControllerButton SDL_GameControllerGetButtonFromString(const char *pchString)
SDL_JoyDeviceEvent jdevice
Definition: SDL_events.h:540
#define SDL_JoystickClose
void SDL_PrivateGameControllerParseButton(const char *szGameButton, const char *szJoystickButton, struct _SDL_ControllerMapping *pMapping)
SDL_Texture * button
SDL_ControllerDeviceEvent cdevice
Definition: SDL_events.h:543
SDL_GameControllerButtonBind SDL_GameControllerGetBindForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button)
#define SDL_RWsize(ctx)
Definition: SDL_rwops.h:184
SDL_JoyButtonEvent jbutton
Definition: SDL_events.h:539
struct _ControllerMapping_t * next
static void UpdateEventsForDeviceRemoval()
Sint16 SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis)
ControllerMapping_t * SDL_PrivateGetControllerMappingForGUID(SDL_JoystickGUID *guid)
SDL_GameControllerAxis SDL_GameControllerGetAxisFromString(const char *pchString)
#define SDL_JoystickNameForIndex
struct xkb_state * state
static SDL_Event events[EVENT_BUF_SIZE]
Definition: testgesture.c:36
SDL_JoystickID which
Definition: SDL_events.h:283
SDL_GameControllerAxis raxes[k_nMaxReverseEntries]
#define SDL_GetHint
SDL_GameControllerButton rbuttons[k_nMaxReverseEntries]
#define SDL_ENABLE
Definition: SDL_events.h:722
#define SDL_JoystickOpen
#define k_nMaxHatEntries
#define SDL_RWread(ctx, ptr, size, n)
Definition: SDL_rwops.h:187
#define SDL_NumJoysticks
int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button, Uint8 state)
#define ABS(_x)
GLuint const GLchar * name
SDL_Texture * axis
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:161
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
SDL_GameControllerButton
#define SDL_strcasecmp
static void SDL_GameControllerLoadHints()
static ControllerMapping_t * s_pEmscriptenMapping
#define SDL_strncasecmp
#define SDL_JoystickGetGUIDString
SDL_GameControllerButton rhatasbutton[k_nMaxHatEntries]
int buttonasaxis[SDL_CONTROLLER_AXIS_MAX]
#define SDL_JoystickGetHat
struct _SDL_GameController * next
#define SDL_JoystickGetDeviceGUID
SDL_GameController * SDL_GameControllerFromInstanceID(SDL_JoystickID joyid)
#define SDL_strchr
int SDL_PrivateGameControllerAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis, Sint16 value)
unsigned int size_t
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:209
void SDL_GameControllerClose(SDL_GameController *gamecontroller)
#define SDL_memcpy
SDL_GameControllerButton raxesasbutton[k_nMaxReverseEntries]
#define SDL_GetEventState(type)
Definition: SDL_events.h:735
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:72
SDL_JoystickGUID guid
#define SDL_PeepEvents
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:211
static SDL_GameController * SDL_gamecontrollers
GLsizei const GLfloat * value
static ControllerMapping_t * s_pSupportedControllers
int SDL_GameControllerEventState(int state)
SDL_JoyAxisEvent jaxis
Definition: SDL_events.h:536
void SDL_GameControllerQuit(void)
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:143
int SDL_GameControllerAddMapping(const char *mappingString)
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:330
struct _cl_event * event
const char * SDL_GameControllerGetStringForAxis(SDL_GameControllerAxis axis)
void SDL_free(void *mem)
SDL_GameControllerBindType bindType
const char * SDL_GameControllerName(SDL_GameController *gamecontroller)
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 int in j)
Definition: SDL_x11sym.h:50
#define SDL_PushEvent
void SDL_PrivateGameControllerRefreshMapping(ControllerMapping_t *pControllerMapping)
#define SDL_memcmp
void SDL_PrivateLoadButtonMapping(struct _SDL_ControllerMapping *pMapping, SDL_JoystickGUID guid, const char *pchName, const char *pchMapping)
ControllerMapping_t * SDL_PrivateGetControllerMapping(int device_index)
#define SDL_JoystickGetAttached
#define SDL_GetPlatform
static const char * map_StringForControllerButton[]
void SDL_GameControllerUpdate(void)
SDL_GameControllerAxis rbuttonasaxis[k_nMaxReverseEntries]
GLenum GLuint GLenum GLsizei const GLchar * buf
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
#define SDL_atoi
GLenum GLint GLuint mask
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_assert(condition)
Definition: SDL_assert.h:167
SDL_GameController * SDL_GameControllerOpen(int device_index)
SDL_bool SDL_IsGameController(int device_index)
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
static const char * s_ControllerMappings[]
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
#define SDL_JoystickUpdate
SDL_Joystick * joystick
#define SDL_SetError
SDL_GameControllerButtonBind SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis)
#define SDL_JoystickGetAxis
char * SDL_PrivateGetControllerNameFromMappingString(const char *pMapping)
union SDL_GameControllerButtonBind::@0 value
#define SDL_AddEventWatch
#define SDL_strlen
#define SDL_strdup
SDL_Joystick * SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller)
#define SDL_EventState
static ControllerMapping_t * s_pXInputMapping
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
GLuint GLfloat x0
#define SDL_snprintf
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:90
GLenum GLenum GLenum GLenum mapping
#define SDL_HINT_GAMECONTROLLERCONFIG
A variable that lets you manually hint extra gamecontroller db entries.
Definition: SDL_hints.h:359
General event structure.
Definition: SDL_events.h:525
#define SDL_malloc
int axes[SDL_CONTROLLER_AXIS_MAX]
int axesasbutton[SDL_CONTROLLER_BUTTON_MAX]
#define SDL_PRESSED
Definition: SDL_events.h:50
#define SDL_QUERY
Definition: SDL_events.h:719
SDL_JoyHatEvent jhat
Definition: SDL_events.h:538
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:331
int SDL_GameControllerAddMappingsFromRW(SDL_RWops *rw, int freerw)
int SDL_GameControllerInit(void)
#define SDL_RELEASED
Definition: SDL_events.h:49
const char * SDL_GameControllerGetStringForButton(SDL_GameControllerButton axis)
char * SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid)
#define SDL_HAT_UP
Definition: SDL_joystick.h:208
#define k_nMaxReverseEntries
Uint8 SDL_GameControllerGetButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button)
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:210
SDL_JoystickID which
Definition: SDL_events.h:315
SDL_GameControllerAxis
int SDL_GameControllerEventWatcher(void *userdata, SDL_Event *event)
static void SDL_PrivateGameControllerParseControllerConfigString(struct _SDL_ControllerMapping *pMapping, const char *pchString)
char * SDL_PrivateGetControllerGUIDFromMappingString(const char *pMapping)
#define SDL_memset
SDL_bool SDL_GameControllerGetAttached(SDL_GameController *gamecontroller)
#define SDL_JoystickGetGUIDFromString
#define SDL_strstr
int16_t Sint16
A signed 16-bit integer type.
Definition: SDL_stdinc.h:147
Uint32 type
Definition: SDL_events.h:527
#define SDL_IGNORE
Definition: SDL_events.h:720
const char * SDL_GameControllerNameForIndex(int device_index)