blob: 6c296601dde92d0e22379dbed361ee71853c2054 [file] [log] [blame]
Andreas Schneider2140f1f2015-12-19 14:29:21 +01001/*
2 * Copyright (c) 2015 Andreas Schneider <asn@cryptomilk.org>
Christopher N. Hesse231dc652017-08-02 15:21:35 +02003 * Copyright (c) 2017 Christopher N. Hesse <raymanfx@gmail.com>
Andreas Schneider2140f1f2015-12-19 14:29:21 +01004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_TAG "wifiloader"
19#define LOG_NDEBUG 0
20
21#include <errno.h>
Christopher N. Hesse231dc652017-08-02 15:21:35 +020022#include <fcntl.h>
Andreas Schneider2140f1f2015-12-19 14:29:21 +010023#include <stdio.h>
Christopher N. Hesse231dc652017-08-02 15:21:35 +020024#include <stdlib.h>
Andreas Schneider2140f1f2015-12-19 14:29:21 +010025#include <string.h>
26#include <cutils/log.h>
Christopher N. Hesse231dc652017-08-02 15:21:35 +020027#include <sys/stat.h>
28#include <sys/syscall.h>
Andreas Schneider2140f1f2015-12-19 14:29:21 +010029
Christopher N. Hesse231dc652017-08-02 15:21:35 +020030#define DEFERRED_INITCALLS "/proc/deferred_initcalls"
31
32#ifndef WIFI_DRIVER_MODULE_NAME
33#define WIFI_DRIVER_MODULE_NAME "wlan"
34#endif
35
36#ifndef WIFI_DRIVER_MODULE_PATH
37#define WIFI_DRIVER_MODULE_PATH "/system/lib/modules/" WIFI_DRIVER_MODULE_NAME ".ko"
38#endif
39
40#define finit_module(fd, params, flags) syscall(__NR_finit_module, fd, params, flags)
41
42
43static int check_module_loaded(char const *tag)
44{
45 FILE *proc;
46 char line[126];
47
48 if ((proc = fopen("/proc/modules", "r")) == NULL) {
49 ALOGW("Could not open %s: %s", "/proc/modules", strerror(errno));
50 return -errno;
51 }
52
53 while ((fgets(line, sizeof(line), proc)) != NULL) {
54 if (strncmp(line, tag, strlen(tag)) == 0) {
55 fclose(proc);
56 return 1;
57 }
58 }
59
60 fclose(proc);
61 return 0;
62}
63
64static int load_module(char const *path)
65{
66 int fd;
67
68 if (check_module_loaded(WIFI_DRIVER_MODULE_NAME) > 0) {
69 ALOGE("Driver: %s already loaded", path);
70 return -1;
71 }
72
73 fd = open(path, O_RDONLY);
74 if (fd == -1) {
75 ALOGE("Failed to open %s - error: %s", path, strerror(errno));
76 return -errno;
77 }
78
79 // load the .ko image
80 if (finit_module(fd, "", 0) != 0) {
81 ALOGE("Failed to load module %s - error: %s", path, strerror(errno));
82 close(fd);
83 return -errno;
84 }
85
86 close(fd);
87 return 0;
88}
Andreas Schneider2140f1f2015-12-19 14:29:21 +010089
90int main(void)
91{
92 char buf[8] = { '\0' };
93 FILE *fp;
94 size_t r;
Christopher N. Hesse231dc652017-08-02 15:21:35 +020095 int fd;
96 struct stat st;
97
98 if (stat(WIFI_DRIVER_MODULE_PATH, &st) == 0) {
99 ALOGD("Loading WiFi kernel module: %s", WIFI_DRIVER_MODULE_PATH);
100 load_module(WIFI_DRIVER_MODULE_PATH);
101 }
Andreas Schneider2140f1f2015-12-19 14:29:21 +0100102
103 ALOGD("Trigger initcall of deferred modules\n");
104
105 fp = fopen(DEFERRED_INITCALLS, "r");
106 if (fp == NULL) {
107 ALOGE("Failed to open %s - error: %s\n",
108 DEFERRED_INITCALLS,
109 strerror(errno));
110 return -errno;
111 }
112
113 r = fread(buf, sizeof(buf), 1, fp);
114 fclose(fp);
115
116 ALOGV("%s=%s\n", DEFERRED_INITCALLS, buf);
117
118 return 0;
119}