diff --git a/configuration.c b/configuration.c index a58a35f62e..2365d7b503 100644 --- a/configuration.c +++ b/configuration.c @@ -3834,18 +3834,18 @@ static void video_driver_save_settings(config_file_t *conf) /** * config_save_autoconf_profile: - * @path : Path that shall be written to. + * @device_name : Input device name * @user : Controller number to save * Writes a controller autoconf file to disk. **/ -bool config_save_autoconf_profile(const char *path, unsigned user) +bool config_save_autoconf_profile(const char *device_name, unsigned user) { static const char* invalid_filename_chars[] = { /* https://support.microsoft.com/en-us/help/905231/information-about-the-characters-that-you-cannot-use-in-site-names--fo */ "~", "#", "%", "&", "*", "{", "}", "\\", ":", "[", "]", "?", "/", "|", "\'", "\"", NULL }; - unsigned i; + size_t i; config_file_t *conf = NULL; size_t path_size = PATH_MAX_LENGTH * sizeof(char); int32_t pid_user = 0; @@ -3853,19 +3853,49 @@ bool config_save_autoconf_profile(const char *path, unsigned user) bool ret = false; settings_t *settings = config_get_ptr(); const char *autoconf_dir = settings->paths.directory_autoconfig; - const char *joypad_ident = settings->arrays.input_joypad_driver; + const char *joypad_driver_fallback = settings->arrays.input_joypad_driver; + const char *joypad_driver = NULL; + char *sanitised_name = NULL; char *buf = (char*) malloc(PATH_MAX_LENGTH * sizeof(char)); char *autoconf_file = (char*) malloc(PATH_MAX_LENGTH * sizeof(char)); - char *path_new = strdup(path); - buf[0] = autoconf_file[0] = '\0'; + + if (!buf || !autoconf_file) + goto end; + + buf[0] = '\0'; + autoconf_file[0] = '\0'; + + if (string_is_empty(device_name)) + goto end; + + /* Get currently set joypad driver */ + joypad_driver = input_config_get_device_joypad_driver(user); + if (string_is_empty(joypad_driver)) + { + /* This cannot happen, but if we reach this + * point without a driver being set for the + * current input device then use the value + * from the settings struct as a fallback */ + joypad_driver = joypad_driver_fallback; + + if (string_is_empty(joypad_driver)) + goto end; + } + + /* Remove invalid filename characters from + * input device name */ + sanitised_name = strdup(device_name); + + if (string_is_empty(sanitised_name)) + goto end; for (i = 0; invalid_filename_chars[i]; i++) { for (;;) { - char *tmp = strstr(path_new, invalid_filename_chars[i]); + char *tmp = strstr(sanitised_name, invalid_filename_chars[i]); if (tmp) *tmp = '_'; @@ -3874,50 +3904,47 @@ bool config_save_autoconf_profile(const char *path, unsigned user) } } - path = path_new; - - fill_pathname_join(buf, autoconf_dir, joypad_ident, path_size); + /* Generate autconfig file path */ + fill_pathname_join(buf, autoconf_dir, joypad_driver, path_size); if (path_is_directory(buf)) { char *buf_new = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); - buf_new[0] = '\0'; + if (!buf_new) + goto end; + + buf_new[0] = '\0'; fill_pathname_join(buf_new, buf, - path, path_size); - fill_pathname_noext(autoconf_file, buf_new, - ".cfg", - path_size); + sanitised_name, path_size); + fill_pathname_noext(autoconf_file, + buf_new, ".cfg", path_size); free(buf_new); } else { fill_pathname_join(buf, autoconf_dir, - path, path_size); - fill_pathname_noext(autoconf_file, buf, - ".cfg", - path_size); + sanitised_name, path_size); + fill_pathname_noext(autoconf_file, + buf, ".cfg", path_size); } - free(buf); - free(path_new); - + /* Open config file */ conf = config_file_new_from_path_to_string(autoconf_file); if (!conf) { conf = config_file_new_alloc(); + if (!conf) - { - free(autoconf_file); - return false; - } + goto end; } + /* Update config file */ config_set_string(conf, "input_driver", - joypad_ident); + joypad_driver); config_set_string(conf, "input_device", input_config_get_device_name(user)); @@ -3943,8 +3970,19 @@ bool config_save_autoconf_profile(const char *path, unsigned user) ret = config_file_write(conf, autoconf_file, false); - config_file_free(conf); - free(autoconf_file); +end: + if (sanitised_name) + free(sanitised_name); + + if (buf) + free(buf); + + if (autoconf_file) + free(autoconf_file); + + if (conf) + config_file_free(conf); + return ret; } diff --git a/configuration.h b/configuration.h index 8b36ac56c9..f2ba7dad07 100644 --- a/configuration.h +++ b/configuration.h @@ -904,11 +904,11 @@ bool config_load_remap(const char *directory_input_remapping, /** * config_save_autoconf_profile: - * @path : Path that shall be written to. + * @device_name : Input device name * @user : Controller number to save * Writes a controller autoconf file to disk. **/ -bool config_save_autoconf_profile(const char *path, unsigned user); +bool config_save_autoconf_profile(const char *device_name, unsigned user); /** * config_save_file: diff --git a/input/input_driver.h b/input/input_driver.h index 45af484140..135869b544 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -157,6 +157,7 @@ typedef struct char display_name[256]; char config_path[PATH_MAX_LENGTH]; char config_name[PATH_MAX_LENGTH]; + char joypad_driver[32]; uint16_t vid; uint16_t pid; bool autoconfigured; @@ -493,6 +494,7 @@ void input_config_set_device_name(unsigned port, const char *name); void input_config_set_device_display_name(unsigned port, const char *name); void input_config_set_device_config_path(unsigned port, const char *path); void input_config_set_device_config_name(unsigned port, const char *name); +void input_config_set_device_joypad_driver(unsigned port, const char *driver); void input_config_set_device_vid(unsigned port, uint16_t vid); void input_config_set_device_pid(unsigned port, uint16_t pid); void input_config_set_device_autoconfigured(unsigned port, bool autoconfigured); @@ -503,6 +505,7 @@ void input_config_clear_device_name(unsigned port); void input_config_clear_device_display_name(unsigned port); void input_config_clear_device_config_path(unsigned port); void input_config_clear_device_config_name(unsigned port); +void input_config_clear_device_joypad_driver(unsigned port); unsigned input_config_get_device_count(void); @@ -517,6 +520,7 @@ const char *input_config_get_device_name(unsigned port); const char *input_config_get_device_display_name(unsigned port); const char *input_config_get_device_config_path(unsigned port); const char *input_config_get_device_config_name(unsigned port); +const char *input_config_get_device_joypad_driver(unsigned port); uint16_t input_config_get_device_vid(unsigned port); uint16_t input_config_get_device_pid(unsigned port); bool input_config_get_device_autoconfigured(unsigned port); diff --git a/retroarch.c b/retroarch.c index f20a336b32..1e8381055c 100644 --- a/retroarch.c +++ b/retroarch.c @@ -27787,6 +27787,14 @@ const char *input_config_get_device_config_name(unsigned port) return p_rarch->input_device_info[port].config_name; } +const char *input_config_get_device_joypad_driver(unsigned port) +{ + struct rarch_state *p_rarch = &rarch_st; + if (string_is_empty(p_rarch->input_device_info[port].joypad_driver)) + return NULL; + return p_rarch->input_device_info[port].joypad_driver; +} + uint16_t input_config_get_device_vid(unsigned port) { struct rarch_state *p_rarch = &rarch_st; @@ -27875,6 +27883,14 @@ void input_config_set_device_config_name(unsigned port, const char *name) sizeof(p_rarch->input_device_info[port].config_name)); } +void input_config_set_device_joypad_driver(unsigned port, const char *driver) +{ + struct rarch_state *p_rarch = &rarch_st; + if (!string_is_empty(driver)) + strlcpy(p_rarch->input_device_info[port].joypad_driver, driver, + sizeof(p_rarch->input_device_info[port].joypad_driver)); +} + void input_config_set_device_vid(unsigned port, uint16_t vid) { struct rarch_state *p_rarch = &rarch_st; @@ -27926,6 +27942,12 @@ void input_config_clear_device_config_name(unsigned port) p_rarch->input_device_info[port].config_name[0] = '\0'; } +void input_config_clear_device_joypad_driver(unsigned port) +{ + struct rarch_state *p_rarch = &rarch_st; + p_rarch->input_device_info[port].joypad_driver[0] = '\0'; +} + /* input_device_info wrappers END */ unsigned *input_config_get_device_ptr(unsigned port) @@ -28014,6 +28036,7 @@ void input_config_reset(void) input_config_clear_device_display_name(i); input_config_clear_device_config_path(i); input_config_clear_device_config_name(i); + input_config_clear_device_joypad_driver(i); input_config_set_device_vid(i, 0); input_config_set_device_pid(i, 0); input_config_set_device_autoconfigured(i, false); diff --git a/tasks/task_autodetect.c b/tasks/task_autodetect.c index 292f89cba7..bb1dfc72f0 100644 --- a/tasks/task_autodetect.c +++ b/tasks/task_autodetect.c @@ -42,7 +42,6 @@ typedef struct input_device_info_t device_info; bool autoconfig_enabled; bool suppress_notifcations; - char *driver; char *dir_autoconfig; char *dir_driver_autoconfig; config_file_t *autoconfig_file; @@ -57,12 +56,6 @@ static void free_autoconfig_handle(autoconfig_handle_t *autoconfig_handle) if (!autoconfig_handle) return; - if (autoconfig_handle->driver) - { - free(autoconfig_handle->driver); - autoconfig_handle->driver = NULL; - } - if (autoconfig_handle->dir_autoconfig) { free(autoconfig_handle->dir_autoconfig); @@ -415,6 +408,13 @@ static void cb_input_autoconfigure_connect( else input_config_clear_device_display_name(port); + /* > Driver */ + if (!string_is_empty(autoconfig_handle->device_info.joypad_driver)) + input_config_set_device_joypad_driver(port, + autoconfig_handle->device_info.joypad_driver); + else + input_config_clear_device_joypad_driver(port); + /* > VID/PID */ input_config_set_device_vid(port, autoconfig_handle->device_info.vid); input_config_set_device_pid(port, autoconfig_handle->device_info.pid); @@ -493,11 +493,14 @@ static void input_autoconfigure_connect_handler(retro_task_t *task) /* Preset fallback device names - must match * those set in 'input_autodetect_builtin.c' */ - if (string_is_equal(autoconfig_handle->driver, "android")) + if (string_is_equal(autoconfig_handle->device_info.joypad_driver, + "android")) fallback_device_name = "Android Gamepad"; - else if (string_is_equal(autoconfig_handle->driver, "xinput")) + else if (string_is_equal(autoconfig_handle->device_info.joypad_driver, + "xinput")) fallback_device_name = "XInput Controller"; - else if (string_is_equal(autoconfig_handle->driver, "sdl2")) + else if (string_is_equal(autoconfig_handle->device_info.joypad_driver, + "sdl2")) fallback_device_name = "Standard Gamepad"; if (!string_is_empty(fallback_device_name) && @@ -604,6 +607,7 @@ void input_autoconfigure_connect( { retro_task_t *task = NULL; autoconfig_handle_t *autoconfig_handle = NULL; + bool driver_valid = false; settings_t *settings = config_get_ptr(); bool autoconfig_enabled = settings ? settings->bools.input_autodetect_enable : false; @@ -630,21 +634,21 @@ void input_autoconfigure_connect( if (!autoconfig_handle) goto error; - autoconfig_handle->port = port; - autoconfig_handle->device_info.vid = vid; - autoconfig_handle->device_info.pid = pid; - autoconfig_handle->device_info.name[0] = '\0'; - autoconfig_handle->device_info.display_name[0] = '\0'; - autoconfig_handle->device_info.config_path[0] = '\0'; - autoconfig_handle->device_info.config_name[0] = '\0'; - autoconfig_handle->device_info.autoconfigured = false; - autoconfig_handle->device_info.name_index = 0; - autoconfig_handle->autoconfig_enabled = autoconfig_enabled; - autoconfig_handle->suppress_notifcations = !notification_show_autoconfig; - autoconfig_handle->driver = NULL; - autoconfig_handle->dir_autoconfig = NULL; - autoconfig_handle->dir_driver_autoconfig = NULL; - autoconfig_handle->autoconfig_file = NULL; + autoconfig_handle->port = port; + autoconfig_handle->device_info.vid = vid; + autoconfig_handle->device_info.pid = pid; + autoconfig_handle->device_info.name[0] = '\0'; + autoconfig_handle->device_info.display_name[0] = '\0'; + autoconfig_handle->device_info.config_path[0] = '\0'; + autoconfig_handle->device_info.config_name[0] = '\0'; + autoconfig_handle->device_info.joypad_driver[0] = '\0'; + autoconfig_handle->device_info.autoconfigured = false; + autoconfig_handle->device_info.name_index = 0; + autoconfig_handle->autoconfig_enabled = autoconfig_enabled; + autoconfig_handle->suppress_notifcations = !notification_show_autoconfig; + autoconfig_handle->dir_autoconfig = NULL; + autoconfig_handle->dir_driver_autoconfig = NULL; + autoconfig_handle->autoconfig_file = NULL; if (!string_is_empty(name)) strlcpy(autoconfig_handle->device_info.name, name, @@ -654,8 +658,10 @@ void input_autoconfigure_connect( strlcpy(autoconfig_handle->device_info.display_name, display_name, sizeof(autoconfig_handle->device_info.display_name)); - if (!string_is_empty(driver)) - autoconfig_handle->driver = strdup(driver); + driver_valid = !string_is_empty(driver); + if (driver_valid) + strlcpy(autoconfig_handle->device_info.joypad_driver, + driver, sizeof(autoconfig_handle->device_info.joypad_driver)); /* > Have to cache both the base autoconfig directory * and the driver-specific autoconfig directory @@ -668,16 +674,14 @@ void input_autoconfigure_connect( { autoconfig_handle->dir_autoconfig = strdup(dir_autoconfig); - /* 'autoconfig_handle->driver' will only be - * non-NULL if 'driver' is a non-empty string */ - if (autoconfig_handle->driver) + if (driver_valid) { char dir_driver_autoconfig[PATH_MAX_LENGTH]; dir_driver_autoconfig[0] = '\0'; /* Generate driver-specific autoconfig directory */ - fill_pathname_join(dir_driver_autoconfig, - dir_autoconfig, autoconfig_handle->driver, + fill_pathname_join(dir_driver_autoconfig, dir_autoconfig, + autoconfig_handle->device_info.joypad_driver, sizeof(dir_driver_autoconfig)); if (!string_is_empty(dir_driver_autoconfig)) @@ -778,6 +782,7 @@ static void cb_input_autoconfigure_disconnect( input_config_clear_device_display_name(port); input_config_clear_device_config_path(port); input_config_clear_device_config_name(port); + input_config_clear_device_joypad_driver(port); input_config_set_device_vid(port, 0); input_config_set_device_pid(port, 0); input_config_set_device_autoconfigured(port, false);