mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-10-26 12:27:44 +00:00 
			
		
		
		
	Use SDL_HINT_GAMECONTROLLER_SENSOR_FUSION as a list of controllers to enable sensor fusion
There are too many wraparound style controllers out there to enumerate them all, so instead make this a user option in applications that support it.
This commit is contained in:
		| @@ -620,11 +620,18 @@ extern "C" { | |||||||
|  *  \brief  Controls whether the device's built-in accelerometer and gyro should be used as sensors for gamepads. |  *  \brief  Controls whether the device's built-in accelerometer and gyro should be used as sensors for gamepads. | ||||||
|  * |  * | ||||||
|  *  The variable can be set to the following values: |  *  The variable can be set to the following values: | ||||||
|  *    "auto"    - Sensor fusion is enabled for known wraparound controllers like the Razer Kishi and Backbone One |  | ||||||
|  *    "0"       - Sensor fusion is disabled |  *    "0"       - Sensor fusion is disabled | ||||||
|  *    "1"       - Sensor fusion is enabled for all controllers that lack sensors |  *    "1"       - Sensor fusion is enabled for all controllers that lack sensors | ||||||
|  * |  * | ||||||
|  *  The default value is "auto". This hint is checked when a gamepad is opened. |  *  Or the variable can be a comma separated list of USB VID/PID pairs | ||||||
|  |  *  in hexadecimal form, e.g. | ||||||
|  |  * | ||||||
|  |  *      0xAAAA/0xBBBB,0xCCCC/0xDDDD | ||||||
|  |  * | ||||||
|  |  *  The variable can also take the form of @file, in which case the named | ||||||
|  |  *  file will be loaded and interpreted as the value of the variable. | ||||||
|  |  * | ||||||
|  |  *  This hint is checked when a gamepad is opened. | ||||||
|  */ |  */ | ||||||
| #define SDL_HINT_GAMECONTROLLER_SENSOR_FUSION "SDL_GAMECONTROLLER_SENSOR_FUSION" | #define SDL_HINT_GAMECONTROLLER_SENSOR_FUSION "SDL_GAMECONTROLLER_SENSOR_FUSION" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -150,61 +150,9 @@ struct SDL_Gamepad | |||||||
|         return retval;                                                       \ |         return retval;                                                       \ | ||||||
|     } |     } | ||||||
|  |  | ||||||
| typedef struct |  | ||||||
| { |  | ||||||
|     int num_entries; |  | ||||||
|     int max_entries; |  | ||||||
|     Uint32 *entries; |  | ||||||
| } SDL_vidpid_list; |  | ||||||
|  |  | ||||||
| static SDL_vidpid_list SDL_allowed_gamepads; | static SDL_vidpid_list SDL_allowed_gamepads; | ||||||
| static SDL_vidpid_list SDL_ignored_gamepads; | static SDL_vidpid_list SDL_ignored_gamepads; | ||||||
|  |  | ||||||
| static void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list) |  | ||||||
| { |  | ||||||
|     Uint32 entry; |  | ||||||
|     char *spot; |  | ||||||
|     char *file = NULL; |  | ||||||
|  |  | ||||||
|     list->num_entries = 0; |  | ||||||
|  |  | ||||||
|     if (hint && *hint == '@') { |  | ||||||
|         spot = file = (char *)SDL_LoadFile(hint + 1, NULL); |  | ||||||
|     } else { |  | ||||||
|         spot = (char *)hint; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (spot == NULL) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     while ((spot = SDL_strstr(spot, "0x")) != NULL) { |  | ||||||
|         entry = (Uint16)SDL_strtol(spot, &spot, 0); |  | ||||||
|         entry <<= 16; |  | ||||||
|         spot = SDL_strstr(spot, "0x"); |  | ||||||
|         if (spot == NULL) { |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         entry |= (Uint16)SDL_strtol(spot, &spot, 0); |  | ||||||
|  |  | ||||||
|         if (list->num_entries == list->max_entries) { |  | ||||||
|             int max_entries = list->max_entries + 16; |  | ||||||
|             Uint32 *entries = (Uint32 *)SDL_realloc(list->entries, max_entries * sizeof(*list->entries)); |  | ||||||
|             if (entries == NULL) { |  | ||||||
|                 /* Out of memory, go with what we have already */ |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|             list->entries = entries; |  | ||||||
|             list->max_entries = max_entries; |  | ||||||
|         } |  | ||||||
|         list->entries[list->num_entries++] = entry; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (file) { |  | ||||||
|         SDL_free(file); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void SDLCALL SDL_GamepadIgnoreDevicesChanged(void *userdata, const char *name, const char *oldValue, const char *hint) | static void SDLCALL SDL_GamepadIgnoreDevicesChanged(void *userdata, const char *name, const char *oldValue, const char *hint) | ||||||
| { | { | ||||||
|     SDL_LoadVIDPIDListFromHint(hint, &SDL_ignored_gamepads); |     SDL_LoadVIDPIDListFromHint(hint, &SDL_ignored_gamepads); | ||||||
| @@ -2112,11 +2060,9 @@ static SDL_bool SDL_endswith(const char *string, const char *suffix) | |||||||
|  */ |  */ | ||||||
| SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid) | SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid) | ||||||
| { | { | ||||||
|     int i; |  | ||||||
|     Uint16 vendor; |     Uint16 vendor; | ||||||
|     Uint16 product; |     Uint16 product; | ||||||
|     Uint16 version; |     Uint16 version; | ||||||
|     Uint32 vidpid; |  | ||||||
|  |  | ||||||
| #ifdef __LINUX__ | #ifdef __LINUX__ | ||||||
|     if (SDL_endswith(name, " Motion Sensors")) { |     if (SDL_endswith(name, " Motion Sensors")) { | ||||||
| @@ -2165,21 +2111,15 @@ SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     vidpid = MAKE_VIDPID(vendor, product); |  | ||||||
|  |  | ||||||
|     if (SDL_allowed_gamepads.num_entries > 0) { |     if (SDL_allowed_gamepads.num_entries > 0) { | ||||||
|         for (i = 0; i < SDL_allowed_gamepads.num_entries; ++i) { |         if (SDL_VIDPIDInList(vendor, product, &SDL_allowed_gamepads)) { | ||||||
|             if (vidpid == SDL_allowed_gamepads.entries[i]) { |  | ||||||
|             return SDL_FALSE; |             return SDL_FALSE; | ||||||
|         } |         } | ||||||
|         } |  | ||||||
|         return SDL_TRUE; |         return SDL_TRUE; | ||||||
|     } else { |     } else { | ||||||
|         for (i = 0; i < SDL_ignored_gamepads.num_entries; ++i) { |         if (SDL_VIDPIDInList(vendor, product, &SDL_ignored_gamepads)) { | ||||||
|             if (vidpid == SDL_ignored_gamepads.entries[i]) { |  | ||||||
|             return SDL_TRUE; |             return SDL_TRUE; | ||||||
|         } |         } | ||||||
|         } |  | ||||||
|         return SDL_FALSE; |         return SDL_FALSE; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -3100,14 +3040,8 @@ void SDL_QuitGamepadMappings(void) | |||||||
|     SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT, |     SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT, | ||||||
|                         SDL_GamepadIgnoreDevicesExceptChanged, NULL); |                         SDL_GamepadIgnoreDevicesExceptChanged, NULL); | ||||||
|  |  | ||||||
|     if (SDL_allowed_gamepads.entries) { |     SDL_FreeVIDPIDList(&SDL_allowed_gamepads); | ||||||
|         SDL_free(SDL_allowed_gamepads.entries); |     SDL_FreeVIDPIDList(&SDL_ignored_gamepads); | ||||||
|         SDL_zero(SDL_allowed_gamepads); |  | ||||||
|     } |  | ||||||
|     if (SDL_ignored_gamepads.entries) { |  | ||||||
|         SDL_free(SDL_ignored_gamepads.entries); |  | ||||||
|         SDL_zero(SDL_ignored_gamepads); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   | |||||||
| @@ -564,19 +564,8 @@ static SDL_bool IsROGAlly(SDL_Joystick *joystick) | |||||||
|  |  | ||||||
| static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, SDL_bool *invert_sensors) | static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, SDL_bool *invert_sensors) | ||||||
| { | { | ||||||
|     static Uint32 wraparound_gamepads[] = { |     const char *hint; | ||||||
|         MAKE_VIDPID(0x1532, 0x0709),    /* Razer Junglecat (L) */ |     int hint_value; | ||||||
|         MAKE_VIDPID(0x1532, 0x070a),    /* Razer Junglecat (R) */ |  | ||||||
|         MAKE_VIDPID(0x1532, 0x0717),    /* Razer Edge controller */ |  | ||||||
|         MAKE_VIDPID(0x1949, 0x0402),    /* Ipega PG-9083S */ |  | ||||||
|         MAKE_VIDPID(0x27f8, 0x0bbc),    /* Gamevice */ |  | ||||||
|         MAKE_VIDPID(0x27f8, 0x0bbf),    /* Razer Kishi */ |  | ||||||
|     }; |  | ||||||
|     SDL_JoystickGUID guid; |  | ||||||
|     Uint16 vendor, product; |  | ||||||
|     Uint32 vidpid; |  | ||||||
|     int i; |  | ||||||
|     int hint; |  | ||||||
|  |  | ||||||
|     *invert_sensors = SDL_FALSE; |     *invert_sensors = SDL_FALSE; | ||||||
|  |  | ||||||
| @@ -590,20 +579,28 @@ static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, SDL_bool *inve | |||||||
|         return SDL_FALSE; |         return SDL_FALSE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     hint = SDL_GetStringInteger(SDL_GetHint(SDL_HINT_GAMECONTROLLER_SENSOR_FUSION), -1); |     hint = SDL_GetHint(SDL_HINT_GAMECONTROLLER_SENSOR_FUSION); | ||||||
|     if (hint > 0) { |     hint_value = SDL_GetStringInteger(hint, -1); | ||||||
|  |     if (hint_value > 0) { | ||||||
|         return SDL_TRUE; |         return SDL_TRUE; | ||||||
|     } |     } | ||||||
|     if (hint == 0) { |     if (hint_value == 0) { | ||||||
|         return SDL_FALSE; |         return SDL_FALSE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* See if the controller is in our list of wraparound gamepads */ |     if (hint) { | ||||||
|  |         SDL_vidpid_list gamepads; | ||||||
|  |         SDL_JoystickGUID guid; | ||||||
|  |         Uint16 vendor, product; | ||||||
|  |         SDL_bool enabled; | ||||||
|  |  | ||||||
|  |         /* See if the gamepad is in our list of devices to enable */ | ||||||
|         guid = SDL_GetJoystickGUID(joystick); |         guid = SDL_GetJoystickGUID(joystick); | ||||||
|         SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); |         SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); | ||||||
|     vidpid = MAKE_VIDPID(vendor, product); |         SDL_LoadVIDPIDListFromHint(hint, &gamepads); | ||||||
|     for (i = 0; i < SDL_arraysize(wraparound_gamepads); ++i) { |         enabled = SDL_VIDPIDInList(vendor, product, &gamepads); | ||||||
|         if (vidpid == wraparound_gamepads[i]) { |         SDL_FreeVIDPIDList(&gamepads); | ||||||
|  |         if (enabled) { | ||||||
|             return SDL_TRUE; |             return SDL_TRUE; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -3263,3 +3260,69 @@ int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_SensorT | |||||||
|     } |     } | ||||||
|     return posted; |     return posted; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list) | ||||||
|  | { | ||||||
|  |     Uint32 entry; | ||||||
|  |     char *spot; | ||||||
|  |     char *file = NULL; | ||||||
|  |  | ||||||
|  |     list->num_entries = 0; | ||||||
|  |  | ||||||
|  |     if (hint && *hint == '@') { | ||||||
|  |         spot = file = (char *)SDL_LoadFile(hint + 1, NULL); | ||||||
|  |     } else { | ||||||
|  |         spot = (char *)hint; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (spot == NULL) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     while ((spot = SDL_strstr(spot, "0x")) != NULL) { | ||||||
|  |         entry = (Uint16)SDL_strtol(spot, &spot, 0); | ||||||
|  |         entry <<= 16; | ||||||
|  |         spot = SDL_strstr(spot, "0x"); | ||||||
|  |         if (spot == NULL) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         entry |= (Uint16)SDL_strtol(spot, &spot, 0); | ||||||
|  |  | ||||||
|  |         if (list->num_entries == list->max_entries) { | ||||||
|  |             int max_entries = list->max_entries + 16; | ||||||
|  |             Uint32 *entries = (Uint32 *)SDL_realloc(list->entries, max_entries * sizeof(*list->entries)); | ||||||
|  |             if (entries == NULL) { | ||||||
|  |                 /* Out of memory, go with what we have already */ | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             list->entries = entries; | ||||||
|  |             list->max_entries = max_entries; | ||||||
|  |         } | ||||||
|  |         list->entries[list->num_entries++] = entry; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (file) { | ||||||
|  |         SDL_free(file); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SDL_bool SDL_VIDPIDInList(Uint16 vendor_id, Uint16 product_id, const SDL_vidpid_list *list) | ||||||
|  | { | ||||||
|  |     int i; | ||||||
|  |     Uint32 vidpid = MAKE_VIDPID(vendor_id, product_id); | ||||||
|  |  | ||||||
|  |     for (i = 0; i < list->num_entries; ++i) { | ||||||
|  |         if (vidpid == list->entries[i]) { | ||||||
|  |             return SDL_TRUE; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return SDL_FALSE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SDL_FreeVIDPIDList(SDL_vidpid_list *list) | ||||||
|  | { | ||||||
|  |     if (list->entries) { | ||||||
|  |         SDL_free(list->entries); | ||||||
|  |         SDL_zerop(list); | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -202,6 +202,18 @@ typedef struct SDL_GamepadMapping | |||||||
| extern SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(SDL_JoystickID instance_id, | extern SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(SDL_JoystickID instance_id, | ||||||
|                                                          SDL_GamepadMapping *out); |                                                          SDL_GamepadMapping *out); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |     int num_entries; | ||||||
|  |     int max_entries; | ||||||
|  |     Uint32 *entries; | ||||||
|  | } SDL_vidpid_list; | ||||||
|  |  | ||||||
|  | extern void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list); | ||||||
|  | extern SDL_bool SDL_VIDPIDInList(Uint16 vendor_id, Uint16 product_id, const SDL_vidpid_list *list); | ||||||
|  | extern void SDL_FreeVIDPIDList(SDL_vidpid_list *list); | ||||||
|  |  | ||||||
| /* Ends C function definitions when using C++ */ | /* Ends C function definitions when using C++ */ | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Sam Lantinga
					Sam Lantinga