Added support to set private-key password.
[platform/core/connectivity/net-config.git] / src / wifi-firmware.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 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 <errno.h>
21 #include <vconf.h>
22 #include <vconf-keys.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25
26 #include "log.h"
27 #include "util.h"
28 #include "netdbus.h"
29 #include "emulator.h"
30 #include "neterror.h"
31 #include "netsupplicant.h"
32 #include "wifi-firmware.h"
33 #include "network-statistics.h"
34
35 #define WLAN_DRIVER_SCRIPT                      "/usr/bin/wlan.sh"
36 #define WLAN_IFACE_NAME                         "wlan0"
37
38 #define WLAN_P2P_IFACE_NAME_TV                  "p2p0"
39 #define WLAN_P2P_IFACE_NAME_COMMON                      "wlan0"
40 #define WLAN_P2P_IFACE_NAME ((TIZEN_TV) ? (WLAN_P2P_IFACE_NAME_TV) : (WLAN_P2P_IFACE_NAME_COMMON))
41 #define QUAD_CPUS_COUNT                 4
42 #define TEMP_BUFFER_LEN                 100
43 #define WIFI_MAC_ADD_PATH               "/sys/class/net/wlan0/address"
44
45 static int __netconfig_sta_firmware_start(void)
46 {
47         int rv = 0;
48         const char *path = WLAN_DRIVER_SCRIPT;
49         char *const args[] = { "/usr/bin/wlan.sh", "start", NULL };
50         char *const envs[] = { NULL };
51
52         rv = netconfig_execute_file(path, args, envs);
53         if (rv < 0)
54                 return -EIO;
55
56         rv = netconfig_interface_up(WLAN_IFACE_NAME);
57         if (rv != TRUE)
58                 return -EIO;
59
60         DBG("Successfully loaded wireless device driver");
61         return 0;
62 }
63
64 static int __netconfig_sta_firmware_stop(void)
65 {
66         int rv = 0;
67         const char *path = WLAN_DRIVER_SCRIPT;
68         char *const args[] = { "/usr/bin/wlan.sh", "stop", NULL };
69         char *const envs[] = { NULL };
70
71         /* Update statistics before driver remove */
72         netconfig_wifi_statistics_update_powered_off();
73
74         rv = netconfig_interface_down(WLAN_IFACE_NAME);
75         if (rv != TRUE)
76                 return -EIO;
77
78         rv = netconfig_execute_file(path, args, envs);
79         if (rv < 0)
80                 return -EIO;
81
82         DBG("Successfully removed wireless device driver");
83         return 0;
84 }
85
86 static int __netconfig_p2p_firmware_start(void)
87 {
88         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT))
89                 return -ENODEV;
90
91         int rv = 0;
92         const char *path = WLAN_DRIVER_SCRIPT;
93         char *const args[] = { "/usr/bin/wlan.sh", "p2p", NULL };
94         char *const envs[] = { NULL };
95
96         rv = netconfig_execute_file(path, args, envs);
97         if (rv < 0)
98                 return -EIO;
99
100 #if defined TIZEN_WLAN_USE_P2P_INTERFACE
101         rv = netconfig_interface_up(WLAN_P2P_IFACE_NAME);
102         if (rv != TRUE)
103                 return -EIO;
104 #endif
105
106         DBG("Successfully loaded p2p device driver");
107         return 0;
108 }
109
110 static int __netconfig_p2p_firmware_stop(void)
111 {
112         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT))
113                 return -ENODEV;
114
115         int rv = 0;
116         const char *path = WLAN_DRIVER_SCRIPT;
117         char *const args[] = { "/usr/bin/wlan.sh", "stop", NULL };
118         char *const envs[] = { NULL };
119
120         rv = netconfig_interface_down(WLAN_IFACE_NAME);
121         if (rv != TRUE)
122                 return -EIO;
123
124         rv = netconfig_execute_file(path, args, envs);
125         if (rv < 0)
126                 return -EIO;
127
128         DBG("Successfully removed p2p device driver");
129         return 0;
130 }
131
132 static int __netconfig_softap_firmware_start(void)
133 {
134         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING))
135                 return -ENODEV;
136
137         int rv = 0;
138         const char *path = WLAN_DRIVER_SCRIPT;
139         char *const args[] = { "/usr/bin/wlan.sh", "softap", NULL };
140         char *const envs[] = { NULL };
141
142         rv = netconfig_execute_file(path, args, envs);
143         if (rv < 0)
144                 return -EIO;
145
146         if (netconfig_interface_up(WLAN_IFACE_NAME) == FALSE)
147                 return -EIO;
148
149         DBG("Successfully loaded softap device driver");
150         return 0;
151 }
152
153 static int __netconfig_softap_firmware_stop(void)
154 {
155         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING))
156                 return -ENODEV;
157
158         int rv = 0;
159         const char *path = WLAN_DRIVER_SCRIPT;
160         char *const args[] = { "/usr/bin/wlan.sh", "stop", NULL };
161         char *const envs[] = { NULL };
162
163         rv = netconfig_interface_down(WLAN_IFACE_NAME);
164         if (rv != TRUE)
165                 return -EIO;
166
167         rv = netconfig_execute_file(path, args, envs);
168         if (rv < 0)
169                 return -EIO;
170
171         DBG("Successfully removed softap device driver");
172         return 0;
173 }
174
175 static int __netconfig_wifi_firmware_start(enum netconfig_wifi_firmware type)
176 {
177         if (emulator_is_emulated() == TRUE)
178                 return -EIO;
179
180         switch (type) {
181         case NETCONFIG_WIFI_STA:
182                 return __netconfig_sta_firmware_start();
183         case NETCONFIG_WIFI_P2P:
184                 return __netconfig_p2p_firmware_start();
185         case NETCONFIG_WIFI_SOFTAP:
186                 return __netconfig_softap_firmware_start();
187         default:
188                 break;
189         }
190
191         return -ENXIO;
192 }
193
194 static int __netconfig_wifi_firmware_stop(enum netconfig_wifi_firmware type)
195 {
196         if (emulator_is_emulated() == TRUE)
197                 return -EIO;
198
199         switch (type) {
200         case NETCONFIG_WIFI_STA:
201                 return __netconfig_sta_firmware_stop();
202         case NETCONFIG_WIFI_P2P:
203                 return __netconfig_p2p_firmware_stop();
204         case NETCONFIG_WIFI_SOFTAP:
205                 return __netconfig_softap_firmware_stop();
206         default:
207                 break;
208         }
209
210         return -ENXIO;
211 }
212
213 static int __netconfig_set_rps_cpus(void)
214 {
215         int fd, curr;
216         ssize_t count;
217         char t_buf[TEMP_BUFFER_LEN];
218         char r_buf[TEMP_BUFFER_LEN];
219
220         if (access(WIFI_MAC_ADD_PATH, F_OK) != 0) {
221                 DBG("WiFi driver is not loaded... ");
222                 return -1;
223         } else {
224                 DBG("WiFi driver loaded... ");
225         }
226
227         snprintf(t_buf, TEMP_BUFFER_LEN, "/sys/class/net/wlan0/queues/rx-0/rps_cpus");
228         DBG("Command : [%s]", t_buf);
229         curr = 0;
230
231         while ((fd = open(t_buf, O_RDWR | O_CLOEXEC)) >= 0) {
232                 curr++;
233                 count = read(fd, r_buf, 1);
234
235                 if (count < 0) {
236                         DBG("read failed");
237                         close(fd);
238                         return -1;
239                 } else {
240                         DBG("read size = %d", count);
241                 }
242
243                 if (r_buf[0] == 'e') {
244                         close(fd);
245                         DBG("e is already written");
246                         snprintf(t_buf, TEMP_BUFFER_LEN, "/sys/class/net/wlan0/queues/rx-%d/rps_cpus", curr);
247                         DBG("Command : [%s]", t_buf);
248                         continue;
249                 } else {
250                         DBG("writing e");
251                 }
252
253                 if (lseek(fd, 0, SEEK_SET) < 0) {
254                         DBG("lseek failed");
255                         close(fd);
256                         return -1;
257                 }
258
259                 count = write(fd, "e", 1);
260
261                 if (count < 0) {
262                         DBG("write failed");
263                         close(fd);
264                         return -1;
265                 } else {
266                         DBG("write size = %d", count);
267                 }
268
269                 close(fd);
270                 snprintf(t_buf, TEMP_BUFFER_LEN, "/sys/class/net/wlan0/queues/rx-%d/rps_cpus", curr);
271                 DBG("Command : [%s]", t_buf);
272         }
273
274         return 0;
275 }
276
277 int netconfig_wifi_firmware(enum netconfig_wifi_firmware type, gboolean enable)
278 {
279         int err;
280         static enum netconfig_wifi_firmware current_driver = NETCONFIG_WIFI_OFF;
281         enum netconfig_wifi_firmware alias = type;
282
283         DBG("Wi-Fi current firmware %d (type: %d %s)", current_driver, type,
284                                                         enable == TRUE ? "enable" : "disable");
285
286         if (enable == FALSE) {
287                 if (current_driver == NETCONFIG_WIFI_OFF) {
288                         return -EALREADY;
289                 } else if (current_driver == alias) {
290
291                         err = __netconfig_wifi_firmware_stop(type);
292                         if (err < 0 && err != -EALREADY)
293                                 return err;
294
295                         current_driver = NETCONFIG_WIFI_OFF;
296
297                         return err;
298                 }
299
300                 return -EIO;
301         }
302
303         if (current_driver > NETCONFIG_WIFI_OFF) {
304                 if (current_driver == alias)
305                         return -EALREADY;
306
307                 return -EIO;
308         }
309
310         err = __netconfig_wifi_firmware_start(type);
311         if (err < 0)
312                 DBG("Failed to execute script file");
313         else
314                 current_driver = alias;
315
316         if (__netconfig_set_rps_cpus() < 0)
317                 DBG("Failed to set rps_cpus");
318
319         return err;
320 }
321
322 gboolean handle_start(WifiFirmware *firmware, GDBusMethodInvocation *context, const gchar *device)
323 {
324         int err;
325
326         g_return_val_if_fail(firmware != NULL, TRUE);
327
328         DBG("Wi-Fi firmware start %s", device != NULL ? device : "null");
329
330         if (g_strcmp0("p2p", device) == 0)
331                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, TRUE);
332         else if (g_strcmp0("softap", device) == 0)
333                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, TRUE);
334         else
335                 err = -EINVAL;
336
337         if (err < 0) {
338                 if (err == -EALREADY)
339                         netconfig_error_already_exists(context);
340                 else if (g_strcmp0("softap", device) == 0 && err == -EIO && netconfig_is_wifi_direct_on() == FALSE) {
341                         if (netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, FALSE) == 0 && netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, TRUE) == 0) {
342                                 wifi_firmware_complete_start(firmware, context);
343                                 return TRUE;
344                         } else
345                                 netconfig_error_wifi_driver_failed(context);
346                 } else
347                         netconfig_error_wifi_driver_failed(context);
348
349                 return TRUE;
350         }
351
352         wifi_firmware_complete_start(firmware, context);
353         return TRUE;
354 }
355
356 gboolean handle_stop(WifiFirmware *firmware, GDBusMethodInvocation *context, const gchar *device)
357 {
358         int err;
359
360         g_return_val_if_fail(firmware != NULL, TRUE);
361
362         DBG("Wi-Fi firmware stop %s", device != NULL ? device : "null");
363
364         if (g_strcmp0("p2p", device) == 0)
365                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, FALSE);
366         else if (g_strcmp0("softap", device) == 0)
367                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, FALSE);
368         else
369                 err = -EINVAL;
370
371         if (err < 0) {
372                 if (err == -EALREADY)
373                         netconfig_error_already_exists(context);
374                 else
375                         netconfig_error_wifi_driver_failed(context);
376
377                 return TRUE;
378         }
379
380         wifi_firmware_complete_stop(firmware, context);
381         return TRUE;
382 }