21 #include "../SDL_internal.h"
33 #if !SDL_EVENTS_DISABLED
34 #include "../events/SDL_events_c.h"
37 #if defined(__ANDROID__)
43 #define SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS 250
45 #define SDL_CONTROLLER_PLATFORM_FIELD "platform:"
46 #define SDL_CONTROLLER_SDKGE_FIELD "sdk>=:"
47 #define SDL_CONTROLLER_SDKLE_FIELD "sdk<=:"
95 typedef struct _ControllerMapping_t
101 struct _ControllerMapping_t *
next;
146 if (hint && *hint ==
'@') {
168 if (entries ==
NULL) {
210 if (num_events <= 0) {
220 for (
i = 0;
i < num_events; ++
i) {
230 if (
a->outputType !=
b->outputType) {
235 return (
a->output.axis.axis ==
b->output.axis.axis);
237 return (
a->output.button ==
b->output.button);
256 for (
i = 0;
i < gamecontroller->num_bindings; ++
i) {
276 if (last_match && (!match || !
HasSameOutput(last_match, match))) {
299 gamecontroller->last_match_axis[
axis] = match;
306 for (
i = 0;
i < gamecontroller->num_bindings; ++
i) {
324 Uint8 last_mask = gamecontroller->last_hat_mask[hat];
327 for (
i = 0;
i < gamecontroller->num_bindings; ++
i) {
330 if ((changed_mask & binding->
input.
hat.hat_mask) != 0) {
343 gamecontroller->last_hat_mask[hat] =
value;
351 switch(
event->type) {
355 while (controllerlist) {
356 if (controllerlist->joystick->instance_id ==
event->jaxis.which) {
360 controllerlist = controllerlist->next;
368 while (controllerlist) {
369 if (controllerlist->joystick->instance_id ==
event->jbutton.which) {
373 controllerlist = controllerlist->next;
380 while (controllerlist) {
381 if (controllerlist->joystick->instance_id ==
event->jhat.which) {
385 controllerlist = controllerlist->next;
402 while (controllerlist) {
403 if (controllerlist->joystick->instance_id ==
event->jdevice.which) {
413 controllerlist = controllerlist->next;
430 while (pSupportedController) {
431 if (
SDL_memcmp(guid, &pSupportedController->
guid,
sizeof(*guid)) == 0) {
432 return pSupportedController;
434 pSupportedController = pSupportedController->
next;
441 #if SDL_JOYSTICK_XINPUT
468 if (pchString && (*pchString ==
'+' || *pchString ==
'-')) {
472 if (!pchString || !pchString[0]) {
519 if (!pchString || !pchString[0])
549 char half_axis_input = 0;
550 char half_axis_output = 0;
552 if (*szGameButton ==
'+' || *szGameButton ==
'-') {
553 half_axis_output = *szGameButton++;
565 if (half_axis_output ==
'+') {
568 }
else if (half_axis_output ==
'-') {
580 SDL_SetError(
"Unexpected controller element %s", szGameButton);
584 if (*szJoystickButton ==
'+' || *szJoystickButton ==
'-') {
585 half_axis_input = *szJoystickButton++;
587 if (szJoystickButton[
SDL_strlen(szJoystickButton) - 1] ==
'~') {
591 if (szJoystickButton[0] ==
'a' &&
SDL_isdigit(szJoystickButton[1])) {
594 if (half_axis_input ==
'+') {
597 }
else if (half_axis_input ==
'-') {
609 }
else if (szJoystickButton[0] ==
'b' &&
SDL_isdigit(szJoystickButton[1])) {
612 }
else if (szJoystickButton[0] ==
'h' &&
SDL_isdigit(szJoystickButton[1]) &&
613 szJoystickButton[2] ==
'.' &&
SDL_isdigit(szJoystickButton[3])) {
614 int hat =
SDL_atoi(&szJoystickButton[1]);
620 SDL_SetError(
"Unexpected joystick element: %s", szJoystickButton);
624 ++gamecontroller->num_bindings;
626 if (!gamecontroller->bindings) {
627 gamecontroller->num_bindings = 0;
631 gamecontroller->bindings[gamecontroller->num_bindings - 1] = bind;
641 char szGameButton[20];
642 char szJoystickButton[20];
645 const char *pchPos = pchString;
650 while (pchPos && *pchPos) {
651 if (*pchPos ==
':') {
654 }
else if (*pchPos ==
' ') {
656 }
else if (*pchPos ==
',') {
663 }
else if (bGameButton) {
664 if (
i >=
sizeof(szGameButton)) {
665 SDL_SetError(
"Button name too large: %s", szGameButton);
668 szGameButton[
i] = *pchPos;
671 if (
i >=
sizeof(szJoystickButton)) {
672 SDL_SetError(
"Joystick button name too large: %s", szJoystickButton);
675 szJoystickButton[
i] = *pchPos;
682 if (szGameButton[0] !=
'\0' || szJoystickButton[0] !=
'\0') {
694 gamecontroller->name = pchName;
695 gamecontroller->num_bindings = 0;
696 if (gamecontroller->joystick->naxes) {
697 SDL_memset(gamecontroller->last_match_axis, 0, gamecontroller->joystick->naxes *
sizeof(*gamecontroller->last_match_axis));
703 for (
i = 0;
i < gamecontroller->num_bindings; ++
i) {
709 if (binding->
input.
axis.axis < gamecontroller->joystick->naxes) {
710 gamecontroller->joystick->axes[binding->
input.
axis.axis].value =
723 const char *pFirstComma =
SDL_strchr(pMapping,
',');
725 char *pchGUID =
SDL_malloc(pFirstComma - pMapping + 1);
730 SDL_memcpy(pchGUID, pMapping, pFirstComma - pMapping);
731 pchGUID[pFirstComma - pMapping] =
'\0';
736 SDL_memcmp(&pchGUID[20],
"504944564944", 12) == 0) {
744 SDL_memcmp(&pchGUID[4],
"000000000000", 12) == 0 &&
745 SDL_memcmp(&pchGUID[20],
"000000000000", 12) == 0) {
762 const char *pFirstComma, *pSecondComma;
769 pSecondComma =
SDL_strchr(pFirstComma + 1,
',');
773 pchName =
SDL_malloc(pSecondComma - pFirstComma);
778 SDL_memcpy(pchName, pFirstComma + 1, pSecondComma - pFirstComma);
779 pchName[pSecondComma - pFirstComma - 1] = 0;
789 const char *pFirstComma, *pSecondComma;
795 pSecondComma =
SDL_strchr(pFirstComma + 1,
',');
808 while (gamecontrollerlist) {
809 if (!
SDL_memcmp(&gamecontrollerlist->joystick->guid, &pControllerMapping->
guid,
sizeof(pControllerMapping->
guid))) {
816 event.cdevice.which = gamecontrollerlist->joystick->instance_id;
821 gamecontrollerlist = gamecontrollerlist->next;
837 SDL_SetError(
"Couldn't parse name from %s", mappingString);
849 if (pControllerMapping) {
851 if (pControllerMapping->
priority <= priority) {
854 pControllerMapping->
name = pchName;
856 pControllerMapping->
mapping = pchMapping;
857 pControllerMapping->
priority = priority;
866 pControllerMapping =
SDL_malloc(
sizeof(*pControllerMapping));
867 if (!pControllerMapping) {
873 pControllerMapping->
guid = jGUID;
874 pControllerMapping->
name = pchName;
875 pControllerMapping->
mapping = pchMapping;
877 pControllerMapping->
priority = priority;
885 pPrevMapping = pCurrMapping, pCurrMapping = pCurrMapping->
next ) {
888 pPrevMapping->
next = pControllerMapping;
894 return pControllerMapping;
904 char name_string[128];
905 char mapping_string[1024];
911 if (!button_mask && !axis_mask) {
920 for (spot = name_string; *spot; ++spot) {
926 SDL_snprintf(mapping_string,
sizeof(mapping_string),
"none,%s,", name_string);
928 SDL_strlcat(mapping_string,
"a:b0,",
sizeof(mapping_string));
931 SDL_strlcat(mapping_string,
"b:b1,",
sizeof(mapping_string));
934 SDL_strlcat(mapping_string,
"b:b4,",
sizeof(mapping_string));
938 SDL_strlcat(mapping_string,
"x:b2,",
sizeof(mapping_string));
941 SDL_strlcat(mapping_string,
"y:b3,",
sizeof(mapping_string));
944 SDL_strlcat(mapping_string,
"back:b4,",
sizeof(mapping_string));
948 SDL_strlcat(mapping_string,
"guide:b5,",
sizeof(mapping_string));
954 SDL_strlcat(mapping_string,
"guide:b6,",
sizeof(mapping_string));
960 SDL_strlcat(mapping_string,
"start:b6,",
sizeof(mapping_string));
963 SDL_strlcat(mapping_string,
"leftstick:b7,",
sizeof(mapping_string));
966 SDL_strlcat(mapping_string,
"rightstick:b8,",
sizeof(mapping_string));
969 SDL_strlcat(mapping_string,
"leftshoulder:b9,",
sizeof(mapping_string));
972 SDL_strlcat(mapping_string,
"rightshoulder:b10,",
sizeof(mapping_string));
975 SDL_strlcat(mapping_string,
"dpup:b11,",
sizeof(mapping_string));
978 SDL_strlcat(mapping_string,
"dpdown:b12,",
sizeof(mapping_string));
981 SDL_strlcat(mapping_string,
"dpleft:b13,",
sizeof(mapping_string));
984 SDL_strlcat(mapping_string,
"dpright:b14,",
sizeof(mapping_string));
987 SDL_strlcat(mapping_string,
"leftx:a0,",
sizeof(mapping_string));
990 SDL_strlcat(mapping_string,
"lefty:a1,",
sizeof(mapping_string));
993 SDL_strlcat(mapping_string,
"rightx:a2,",
sizeof(mapping_string));
996 SDL_strlcat(mapping_string,
"righty:a3,",
sizeof(mapping_string));
999 SDL_strlcat(mapping_string,
"lefttrigger:a4,",
sizeof(mapping_string));
1002 SDL_strlcat(mapping_string,
"righttrigger:a5,",
sizeof(mapping_string));
1007 int pos = (int)
SDL_strlen(mapping_string) - 1;
1009 if (mapping_string[pos] ==
',') {
1010 mapping_string[pos] =
'\0';
1035 "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",
1048 mapping = SDL_CreateMappingForAndroidController(
name, guid);
1086 char *
buf, *line, *line_end, *tmp, *comma, line_platform[64];
1087 size_t db_size, platform_len;
1099 return SDL_SetError(
"Could not allocate space to read DB into memory");
1114 buf[db_size] =
'\0';
1117 while (line <
buf + db_size) {
1119 if (line_end !=
NULL) {
1122 line_end =
buf + db_size;
1130 if (comma !=
NULL) {
1131 platform_len = comma - tmp + 1;
1142 line = line_end + 1;
1163 if (!mappingString) {
1190 return SDL_SetError(
"Couldn't parse GUID from %s", mappingString);
1203 if (!pControllerMapping) {
1210 if (is_default_mapping) {
1212 }
else if (is_hidapi_mapping) {
1214 }
else if (is_xinput_mapping) {
1236 int num_mappings = 0;
1245 return num_mappings;
1260 if (mapping_index == 0) {
1261 char *pMappingString;
1269 if (!pMappingString) {
1274 return pMappingString;
1287 char *pMappingString =
NULL;
1296 if (!pMappingString) {
1302 return pMappingString;
1311 if (!gamecontroller) {
1322 if (hint && hint[0]) {
1324 char *pUserMappings =
SDL_malloc(nchHints + 1);
1325 char *pTempMappings = pUserMappings;
1327 pUserMappings[nchHints] =
'\0';
1328 while (pUserMappings) {
1329 char *pchNewLine =
NULL;
1331 pchNewLine =
SDL_strchr(pUserMappings,
'\n');
1338 pUserMappings = pchNewLine + 1;
1340 pUserMappings =
NULL;
1355 if (hint && *hint) {
1359 #if defined(__ANDROID__)
1372 char szControllerMapPath[1024];
1374 const char *pMappingString =
NULL;
1376 while (pMappingString) {
1427 if (pSupportedController) {
1431 return pSupportedController->
name;
1456 char *pMappingString =
NULL;
1470 if (!pMappingString) {
1478 return pMappingString;
1489 if (pSupportedController) {
1502 if (pSupportedController) {
1519 #if defined(__LINUX__)
1536 #if defined(__LINUX__)
1537 bSteamVirtualGamepad = (vendor == 0x28DE && product == 0x11FF);
1538 #elif defined(__MACOSX__)
1539 bSteamVirtualGamepad = (vendor == 0x045E && product == 0x028E && version == 1);
1540 #elif defined(__WIN32__)
1544 if (bSteamVirtualGamepad) {
1575 SDL_GameController *
1579 SDL_GameController *gamecontroller;
1580 SDL_GameController *gamecontrollerlist;
1588 while (gamecontrollerlist) {
1589 if (instance_id == gamecontrollerlist->joystick->instance_id) {
1590 gamecontroller = gamecontrollerlist;
1591 ++gamecontroller->ref_count;
1593 return (gamecontroller);
1595 gamecontrollerlist = gamecontrollerlist->next;
1600 if (!pSupportedController) {
1601 SDL_SetError(
"Couldn't find mapping for device (%d)", device_index);
1607 gamecontroller = (SDL_GameController *)
SDL_calloc(1,
sizeof(*gamecontroller));
1608 if (gamecontroller ==
NULL) {
1615 if (!gamecontroller->joystick) {
1621 if (gamecontroller->joystick->naxes) {
1623 if (!gamecontroller->last_match_axis) {
1631 if (gamecontroller->joystick->nhats) {
1632 gamecontroller->last_hat_mask = (
Uint8 *)
SDL_calloc(gamecontroller->joystick->nhats,
sizeof(*gamecontroller->last_hat_mask));
1633 if (!gamecontroller->last_hat_mask) {
1636 SDL_free(gamecontroller->last_match_axis);
1646 ++gamecontroller->ref_count;
1653 return (gamecontroller);
1674 if (!gamecontroller)
1677 for (
i = 0;
i < gamecontroller->num_bindings; ++
i) {
1691 if (valid_input_range) {
1706 if (hat_mask & binding->
input.
hat.hat_mask) {
1717 if (
value != 0 && valid_output_range) {
1733 if (!gamecontroller)
1736 for (
i = 0;
i < gamecontroller->num_bindings; ++
i) {
1746 if (valid_input_range) {
1751 if (valid_input_range) {
1769 if (!gamecontroller)
1772 if (
SDL_strcmp(gamecontroller->name,
"*") == 0) {
1775 return gamecontroller->name;
1825 if (!gamecontroller)
1836 if (!gamecontroller)
1839 return gamecontroller->joystick;
1846 SDL_GameController *
1849 SDL_GameController *gamecontroller;
1853 while (gamecontroller) {
1854 if (gamecontroller->joystick->instance_id == joyid) {
1856 return gamecontroller;
1858 gamecontroller = gamecontroller->next;
1890 for (
i = 0;
i < gamecontroller->num_bindings; ++
i) {
1922 for (
i = 0;
i < gamecontroller->num_bindings; ++
i) {
1950 SDL_GameController *gamecontrollerlist, *gamecontrollerlistprev;
1952 if (!gamecontroller)
1958 if (--gamecontroller->ref_count > 0) {
1966 gamecontrollerlistprev =
NULL;
1967 while (gamecontrollerlist) {
1968 if (gamecontroller == gamecontrollerlist) {
1969 if (gamecontrollerlistprev) {
1971 gamecontrollerlistprev->next = gamecontrollerlist->next;
1977 gamecontrollerlistprev = gamecontrollerlist;
1978 gamecontrollerlist = gamecontrollerlist->next;
1981 SDL_free(gamecontroller->bindings);
1982 SDL_free(gamecontroller->last_match_axis);
1983 SDL_free(gamecontroller->last_hat_mask);
2044 #if !SDL_EVENTS_DISABLED
2048 event.caxis.which = gamecontroller->joystick->instance_id;
2049 event.caxis.axis =
axis;
2050 event.caxis.value =
value;
2065 #if !SDL_EVENTS_DISABLED
2087 gamecontroller->guide_button_down = now;
2089 if (gamecontroller->joystick->delayed_guide_button) {
2095 gamecontroller->joystick->delayed_guide_button =
SDL_TRUE;
2098 gamecontroller->joystick->delayed_guide_button =
SDL_FALSE;
2104 #if !SDL_EVENTS_DISABLED
2106 event.cbutton.which = gamecontroller->joystick->instance_id;
2107 event.cbutton.button =
button;
2108 event.cbutton.state =
state;
2121 #if SDL_EVENTS_DISABLED
2124 const Uint32 event_list[] = {
2154 while (controllerlist) {
2155 if (controllerlist->joystick ==
joystick) {
2159 controllerlist = controllerlist->next;