summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2013-11-11 22:25:48 +0100
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2017-06-13 14:26:14 +0200
commit0a29b8547b892115003c46ae17eae4b609aa9a87 (patch)
tree9ef9379d560afe5034688e417e42d03229a91b9c
parent1f27ca88dc332eecf1dda3a6dc1afcdef6591e78 (diff)
downloadhardware_libhardware_legacy-0a29b8547b892115003c46ae17eae4b609aa9a87.zip
hardware_libhardware_legacy-0a29b8547b892115003c46ae17eae4b609aa9a87.tar.gz
hardware_libhardware_legacy-0a29b8547b892115003c46ae17eae4b609aa9a87.tar.bz2
Properly handle missing firmwaresHEADreplicant-6.0
Change-Id: I33e9f2fd201834ebe5a0cd0255913aaf463e01d4 Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
-rw-r--r--wifi/wifi.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/wifi/wifi.c b/wifi/wifi.c
index 6f7e105..27b18af 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 <sys/stat.h>
#include <unistd.h>
@@ -318,8 +319,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 */