tizen 2.4 release
[adaptation/devices/wlandrv-plugin-sprd.git] / src / wifi-loader.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <sys/utsname.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23
24 #include <stddef.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28
29 #include "wifi-log.h"
30
31 #define WIFI_MAC_INFO_PATH "/opt/etc/.mac.info"
32
33 #define WIFI_MODULE_NAME "sprdwl.ko"
34 #define WIFI_MODULE_PATH_PREFIX "/lib/modules/"
35 #define WIFI_MODULE_PATH_POSTFIX "/kernel/drivers/net/wireless/sc2331/"WIFI_MODULE_NAME
36
37 #ifndef TEMP_FAILURE_RETRY
38 /* Used to retry syscalls that can return EINTR. */
39 #define TEMP_FAILURE_RETRY(exp) ({         \
40         typeof (exp) _rc;                      \
41         do {                                   \
42                 _rc = (exp);                       \
43         } while (_rc == -1 && errno == EINTR); \
44         _rc; })
45 #endif
46
47 #define WCND_SOCKET_NAME        "/tmp/wcnd"
48 #define WCND_CMD_STR_START_CP2  "wcn WIFI-OPEN"
49 #define WCND_CMD_STR_STOP_CP2  "wcn WIFI-CLOSE"
50 #define WCND_RESP_STR_WIFI_OK   "WCNBTWIFI-CMD OK"
51
52 static int wcnd_socket = -1;
53
54 static int socket_local_client(const char *path, int type)
55 {
56         int s;
57         struct sockaddr_un addr;
58         socklen_t alen;
59         size_t pathlen;
60
61         s = socket(AF_LOCAL, type, 0);
62         if (s < 0) return -1;
63
64         memset(&addr, 0, sizeof(addr));
65
66         addr.sun_family = AF_LOCAL;
67
68         pathlen = strlen(path);
69         if (pathlen > sizeof(addr)
70                 - offsetof(struct sockaddr_un, sun_path) - 1) {
71                         close(s);
72                         return -1;
73                 }
74
75         addr.sun_path[0] = 0;
76         memcpy(addr.sun_path + 1, path, pathlen);
77
78         alen = pathlen + offsetof(struct sockaddr_un, sun_path) + 1;
79
80         if (connect(s, (struct sockaddr *)&addr, alen) < 0) {
81                 close(s);
82                 return -1;
83         }
84
85         return s;
86 }
87
88 static int connect_wcnd(void)
89 {
90         int client_fd = -1;
91
92         client_fd = socket_local_client(WCND_SOCKET_NAME, SOCK_STREAM);
93
94         while (client_fd < 0)
95         {
96                 WIFI_LOGE("%s: Unable bind server %s, waiting...", __func__, WCND_SOCKET_NAME);
97                 usleep(100*1000);
98                 client_fd = socket_local_client(WCND_SOCKET_NAME, SOCK_STREAM);
99         }
100
101         return client_fd;
102 }
103
104 static int start_cp2(void)
105 {
106         char buffer[128];
107         int n = 0;
108         int ret = 0;
109
110         WIFI_LOGE("%s: send %s to %s",__func__, WCND_CMD_STR_START_CP2, WCND_SOCKET_NAME);
111
112         memset(buffer, 0, 128);
113
114         n = strlen(WCND_CMD_STR_START_CP2) + 1;
115
116         TEMP_FAILURE_RETRY(write(wcnd_socket, WCND_CMD_STR_START_CP2, n));
117
118         memset(buffer, 0, 128);
119
120         WIFI_LOGE("%s: waiting for server %s",__func__, WCND_SOCKET_NAME);
121         n = read(wcnd_socket, buffer, sizeof(buffer) - 1);
122
123         WIFI_LOGE("%s: get %d bytes %s", __func__, n, buffer);
124
125         if (!strstr(buffer, WCND_RESP_STR_WIFI_OK)) ret = -1;
126
127         return ret;
128 }
129
130 static int stop_cp2(void)
131 {
132         char buffer[128];
133         int n = 0;
134         int ret = 0;
135
136         WIFI_LOGE("%s: send %s to %s",__func__, WCND_CMD_STR_STOP_CP2, WCND_SOCKET_NAME);
137
138         memset(buffer, 0, 128);
139
140         n = strlen(WCND_CMD_STR_STOP_CP2) + 1;
141
142         TEMP_FAILURE_RETRY(write(wcnd_socket, WCND_CMD_STR_STOP_CP2, n));
143
144         memset(buffer, 0, 128);
145
146         WIFI_LOGE("%s: waiting for server %s",__func__, WCND_SOCKET_NAME);
147         n = read(wcnd_socket, buffer, sizeof(buffer) - 1);
148
149         WIFI_LOGE("%s: get %d bytes %s", __func__, n, buffer);
150
151         if (!strstr(buffer, WCND_RESP_STR_WIFI_OK)) ret = -1;
152
153         return ret;
154 }
155
156 static int wifi_find_module_path(char *path)
157 {
158         struct utsname buf;
159
160         uname(&buf);
161
162         strcat(path, buf.release);
163         strcat(path, WIFI_MODULE_PATH_POSTFIX);
164
165         WIFI_LOGE("path = %s", path);
166         return 0;
167 }
168
169 static void *wifi_load_module(const char *path, int *len)
170 {
171         char *buf = NULL;
172         int fd, size;
173
174         fd = open(path, O_RDONLY);
175         if (fd < 0)
176                 return 0;
177
178         size = lseek(fd, 0, SEEK_END);
179         if (size < 0)
180                 goto error;
181
182         if (lseek(fd, 0, SEEK_SET) != 0)
183                 goto error;
184
185         buf = (char *) malloc(size+1);
186         if (buf == NULL)
187                 goto error;
188
189         if (read(fd, buf, size) != size)
190                 goto error;
191
192         close(fd);
193         buf[size] = 0;
194
195         if(len)
196                 *len = size;
197
198         return buf;
199
200 error:
201         close(fd);
202         if (buf != 0)
203                 free(buf);
204
205         return 0;
206 }
207
208 static int insmod(const char *path, const char *args)
209 {
210         void *module;
211         int len, ret;
212
213         module = wifi_load_module(path, &len);
214         if (!module)
215                 return -1;
216
217         ret = init_module(module, len, args);
218
219         if (ret != 0) {
220                 WIFI_LOGE("insmod failed ret = %d, %s", ret, strerror(errno));
221                 if (errno == EEXIST)
222                         ret = 0;
223         }
224
225         free(module);
226
227         return ret;
228 }
229
230 static int rmmod(char *modname)
231 {
232         int ret = -1;
233         int len;
234
235         len = strlen(modname);
236         modname[len-3] = 0;
237
238         WIFI_LOGE("modname = %s", modname);
239
240         ret = delete_module(modname, O_NONBLOCK | O_EXCL);
241         if (ret < 0)
242                 WIFI_LOGE("rmmmod failed %s: ret = %d, %s", modname, ret, strerror(errno));
243
244         return ret;
245 }
246
247 static int wifi_check_mac_info()
248 {
249         FILE *file = NULL;
250         char buf[20];
251         int ret = 0;
252
253         file = fopen(WIFI_MAC_INFO_PATH, "r");
254         if (file == NULL) {
255                 WIFI_LOGE("Failed to open %s", WIFI_MAC_INFO_PATH);
256                 return -1;
257         }
258
259         if(!fgets(buf, sizeof(buf), file)) {
260                 WIFI_LOGE("Failed to read %s. Remove file", WIFI_MAC_INFO_PATH);
261                 fclose(file);
262                 ret = remove(WIFI_MAC_INFO_PATH);
263                 if (ret < 0)
264                         WIFI_LOGE("%s file remove failed", WIFI_MAC_INFO_PATH);
265                 return -1;
266         }
267         fclose(file);
268
269         WIFI_LOGE("Successfully read %s. MAC : ", WIFI_MAC_INFO_PATH, buf);
270
271         return 0;
272 }
273
274 static int __wifi_start(int mode)
275 {
276         char wifi_module_path[100] = WIFI_MODULE_PATH_PREFIX;
277         int i, ret = 0;
278
279         WIFI_LOGE("mode = %d", mode);
280
281         ret = wifi_find_module_path(wifi_module_path);
282         if (ret < 0) {
283                 WIFI_LOGE("wifi_find_module_path failed");
284                 return -1;
285         }
286
287         if (wcnd_socket < 0)
288                 wcnd_socket = connect_wcnd();
289
290         if (wcnd_socket > 0 && (start_cp2() < 0))
291                 WIFI_LOGE("start CP2 FAIL");
292
293 /*      if (mode == 3)
294                 ret = insmod(wifi_module_path, "con_mode=5");
295         else */
296                 ret = insmod(wifi_module_path, "");
297
298         return ret;
299 }
300
301 static int wifi_start()
302 {
303         int ret = 0;
304
305         ret = __wifi_start(1);
306         if (ret < 0) {
307                 WIFI_LOGE("__wifi_start(1) failed");
308                 return -1;
309         }
310
311         return 0;
312 }
313
314 static int wifi_softap()
315 {
316         int ret = 0;
317
318         ret = __wifi_start(2);
319         if (ret < 0) {
320                 WIFI_LOGE("__wifi_start(2) failed");
321                 return -1;
322         }
323
324         return 0;
325 }
326
327 static int wifi_rftest()
328 {
329         int ret = 0;
330
331         ret = __wifi_start(3);
332         if (ret < 0) {
333                 WIFI_LOGE("__wifi_start(3) failed");
334                 return -1;
335         }
336
337         return 0;
338 }
339
340 static int wifi_stop()
341 {
342         char wifi_module_name[20] = WIFI_MODULE_NAME;
343         int ret = 0;
344
345         WIFI_LOGE("wifi_stop called");
346
347         ret = rmmod(wifi_module_name);
348         if (ret < 0) {
349                 WIFI_LOGE("rmmod failed");
350                 return -1;
351         }
352
353         if (wcnd_socket < 0)
354                 wcnd_socket = connect_wcnd();
355
356         if (wcnd_socket > 0 && (stop_cp2() < 0))
357                 WIFI_LOGE("stop CP2 FAIL");
358
359         return 0;
360 }
361
362 static int wifi_check_hw()
363 {
364         int ret = 0;
365
366         ret = wifi_check_mac_info();
367         if (ret < 0) {
368                 WIFI_LOGE("There is no %s file", WIFI_MAC_INFO_PATH);
369
370                 ret = __wifi_start(4);
371                 if (ret < 0) {
372                         WIFI_LOGE("__wifi_start(4) failed");
373                         return -1;
374                 }
375
376                 usleep(200000);
377
378                 ret = wifi_stop();
379                 if (ret < 0) {
380                         WIFI_LOGE("wifi_stop() failed");
381                         return -1;
382                 }
383         }
384
385         return 0;
386 }
387
388 int main(int argc, char *argv[])
389 {
390         int ret = 0;
391
392         if (argc != 2) {
393                 WIFI_LOGE("Usage: wifi <mode>");
394                 return -1;
395         }
396
397         ret = wifi_check_hw();
398         if (ret < 0)
399                 return ret;
400
401         if (strcmp(argv[1], "start") == 0 || strcmp(argv[1], "p2p") == 0)
402                 ret = wifi_start();
403         else if (strcmp(argv[1], "softap") == 0)
404                 ret = wifi_softap();
405         else if (strcmp(argv[1], "rftest") == 0)
406                 ret = wifi_rftest();
407         else if (strcmp(argv[1], "check_hw") == 0);
408         else if (strcmp(argv[1], "stop") == 0)
409                 ret = wifi_stop();
410
411         return ret;
412 }