diff options
Diffstat (limited to 'wifi/wifi.c')
-rw-r--r-- | wifi/wifi.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/wifi/wifi.c b/wifi/wifi.c index 90b7632..58d4572 100644 --- a/wifi/wifi.c +++ b/wifi/wifi.c @@ -19,6 +19,7 @@ #include <errno.h> #include <string.h> #include <dirent.h> +#include <libgen.h> #include <sys/socket.h> #include <unistd.h> #include <poll.h> @@ -283,8 +284,143 @@ int is_wifi_driver_loaded() { #endif } +int wifi_check_fw_path(const char *fw_path) +{ + char *fw_path_string = NULL; + char *fw_dirname; + char *fw_basename; + size_t fw_basename_length; + size_t length; + int rc; + + DIR *fw_dir = NULL; + struct dirent *entry; + + if (fw_path == NULL) + return -1; + + fw_path_string = strdup(fw_path); + fw_basename = basename(fw_path_string); + fw_dirname = dirname(fw_path_string); + + fw_basename_length = strlen(fw_basename); + if (fw_basename_length == 0) + goto error; + + fw_dir = opendir(fw_dirname); + if (fw_dir == NULL) + goto error; + + while ((entry = readdir(fw_dir)) != NULL) { + length = strlen(entry->d_name); + if (length >= fw_basename_length && strncmp(fw_basename, entry->d_name, fw_basename_length) == 0) { + rc = 1; + goto complete; + } + } + + rc = 0; + goto complete; + +error: + rc = 0; + +complete: + if (fw_path_string != NULL) + free(fw_path_string); + + if (fw_dir != NULL) + closedir(fw_dir); + + return rc; +} + +int wifi_check_fw_args(const char *args, const char **keys, unsigned int keys_count) +{ + char format[256] = { 0 }; + char fw_path[PATH_MAX] = { 0 }; + size_t args_length; + size_t key_length; + unsigned int i, j; + int rc; + + if (args == NULL || keys == NULL || keys_count == 0) + return 0; + + args_length = strlen(args); + + for (i = 0; i < keys_count; i++) { + key_length = strlen(keys[i]); + + for (j = 0; j < args_length; j++) { + if (strncmp(&args[j], keys[i], key_length) == 0) { + snprintf((char *) &format, sizeof(format), "%s=%256[^ ]", keys[i]); + + rc = sscanf(&args[j], format, &fw_path); + if (rc == 1) { + rc = wifi_check_fw_path(fw_path); + if (!rc) + return rc; + else + break; + } + } + } + } + + return 1; +} + +int wifi_check_fw_paths(void) +{ + const char *keys[] = { + "firmware_path", + "nvram_path" + }; + unsigned int keys_count = sizeof(keys) / sizeof(const char *); + int rc; + + if (WIFI_DRIVER_FW_PATH_STA != NULL && wifi_mode != 1) { + rc = wifi_check_fw_path(WIFI_DRIVER_FW_PATH_STA); + if (!rc) + return rc; + } else if (WIFI_DRIVER_FW_PATH_AP && wifi_mode == 1) { + rc = wifi_check_fw_path(WIFI_DRIVER_FW_PATH_AP); + if (!rc) + return rc; + } + + if (WIFI_DRIVER_FW_PATH_P2P != NULL) { + rc = wifi_check_fw_path(WIFI_DRIVER_FW_PATH_P2P); + if (!rc) + return rc; + } + + if (WIFI_DRIVER_MODULE_ARG != NULL) { + rc = wifi_check_fw_args(WIFI_DRIVER_MODULE_ARG, (const char **) &keys, keys_count); + if (!rc) + return rc; + } + + if (WIFI_DRIVER_MODULE_AP_ARG != NULL && wifi_mode == 1) { + rc = wifi_check_fw_args(WIFI_DRIVER_MODULE_AP_ARG, (const char **) &keys, keys_count); + if (!rc) + return rc; + } + + return 1; +} + int wifi_load_driver() { + int rc; + + rc = wifi_check_fw_paths(); + if (!rc) { + property_set(DRIVER_PROP_NAME, "unloaded"); + return -1; + } + #ifdef WIFI_DRIVER_MODULE_PATH char driver_status[PROPERTY_VALUE_MAX]; int count = 100; /* wait at most 20 seconds for completion */ |