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