From 231dc651ab1ca082ba6d63559d79ae748b02eb1f Mon Sep 17 00:00:00 2001 From: "Christopher N. Hesse" Date: Wed, 2 Aug 2017 15:21:35 +0200 Subject: [PATCH] wifiloader: Load kernel module if present Samsung does this in the macloader service, but this is the more appropriate place for our platform. Change-Id: I6335fea1d73d48f3c3f9938f33b536c5cda52acb --- wifiloader/Android.mk | 8 +++++ wifiloader/wifiloader.c | 72 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/wifiloader/Android.mk b/wifiloader/Android.mk index 15c9dc2..72c1c49 100644 --- a/wifiloader/Android.mk +++ b/wifiloader/Android.mk @@ -9,6 +9,14 @@ LOCAL_SRC_FILES := \ LOCAL_SHARED_LIBRARIES := \ liblog libutils +ifneq ($(WIFI_DRIVER_MODULE_NAME),) +LOCAL_CFLAGS += -DWIFI_DRIVER_MODULE_NAME=\"$(WIFI_DRIVER_MODULE_NAME)\" +endif + +ifneq ($(WIFI_DRIVER_MODULE_PATH),) +LOCAL_CFLAGS += -DWIFI_DRIVER_MODULE_PATH=\"$(WIFI_DRIVER_MODULE_PATH)\" +endif + LOCAL_MODULE := wifiloader LOCAL_MODULE_TAGS := optional diff --git a/wifiloader/wifiloader.c b/wifiloader/wifiloader.c index 54afdaf..6c29660 100644 --- a/wifiloader/wifiloader.c +++ b/wifiloader/wifiloader.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015 Andreas Schneider + * Copyright (c) 2017 Christopher N. Hesse * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,17 +19,86 @@ #define LOG_NDEBUG 0 #include +#include #include +#include #include #include +#include +#include -#define DEFERRED_INITCALLS "/proc/deferred_initcalls" +#define DEFERRED_INITCALLS "/proc/deferred_initcalls" + +#ifndef WIFI_DRIVER_MODULE_NAME +#define WIFI_DRIVER_MODULE_NAME "wlan" +#endif + +#ifndef WIFI_DRIVER_MODULE_PATH +#define WIFI_DRIVER_MODULE_PATH "/system/lib/modules/" WIFI_DRIVER_MODULE_NAME ".ko" +#endif + +#define finit_module(fd, params, flags) syscall(__NR_finit_module, fd, params, flags) + + +static int check_module_loaded(char const *tag) +{ + FILE *proc; + char line[126]; + + if ((proc = fopen("/proc/modules", "r")) == NULL) { + ALOGW("Could not open %s: %s", "/proc/modules", strerror(errno)); + return -errno; + } + + while ((fgets(line, sizeof(line), proc)) != NULL) { + if (strncmp(line, tag, strlen(tag)) == 0) { + fclose(proc); + return 1; + } + } + + fclose(proc); + return 0; +} + +static int load_module(char const *path) +{ + int fd; + + if (check_module_loaded(WIFI_DRIVER_MODULE_NAME) > 0) { + ALOGE("Driver: %s already loaded", path); + return -1; + } + + fd = open(path, O_RDONLY); + if (fd == -1) { + ALOGE("Failed to open %s - error: %s", path, strerror(errno)); + return -errno; + } + + // load the .ko image + if (finit_module(fd, "", 0) != 0) { + ALOGE("Failed to load module %s - error: %s", path, strerror(errno)); + close(fd); + return -errno; + } + + close(fd); + return 0; +} int main(void) { char buf[8] = { '\0' }; FILE *fp; size_t r; + int fd; + struct stat st; + + if (stat(WIFI_DRIVER_MODULE_PATH, &st) == 0) { + ALOGD("Loading WiFi kernel module: %s", WIFI_DRIVER_MODULE_PATH); + load_module(WIFI_DRIVER_MODULE_PATH); + } ALOGD("Trigger initcall of deferred modules\n"); -- 2.20.1