e416baa5f9493beff1d3261a3ff8dc44222fc75f
[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
24 #include "log.h"
25 #include "util.h"
26 #include "netdbus.h"
27 #include "emulator.h"
28 #include "neterror.h"
29 #include "netsupplicant.h"
30 #include "wifi-firmware.h"
31 #include "network-statistics.h"
32 #if defined WLAN_CHECK_POWERSAVE
33 #include "wifi-powersave.h"
34 #endif
35
36 #define WLAN_DRIVER_SCRIPT                      "/usr/bin/wlan.sh"
37 #define WLAN_IFACE_NAME                         "wlan0"
38
39 #if defined(TIZEN_TV)
40 #define WLAN_P2P_IFACE_NAME                     "p2p0"
41 #else /* defined(TIZEN_TV) */
42 #define WLAN_P2P_IFACE_NAME                     "wlan0"
43 #endif /* defined(TIZEN_TV) */
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 defined TIZEN_P2P_ENABLE
89         int rv = 0;
90         const char *path = WLAN_DRIVER_SCRIPT;
91         char *const args[] = { "/usr/bin/wlan.sh", "p2p", NULL };
92         char *const envs[] = { NULL };
93
94         rv = netconfig_execute_file(path, args, envs);
95         if (rv < 0)
96                 return -EIO;
97
98 #if defined TIZEN_WLAN_USE_P2P_INTERFACE
99         rv = netconfig_interface_up(WLAN_P2P_IFACE_NAME);
100         if (rv != TRUE)
101                 return -EIO;
102 #endif
103
104         DBG("Successfully loaded p2p device driver");
105         return 0;
106 #else
107         return -ENODEV;
108 #endif
109 }
110
111 static int __netconfig_p2p_firmware_stop(void)
112 {
113 #if defined TIZEN_P2P_ENABLE
114         int rv = 0;
115         const char *path = WLAN_DRIVER_SCRIPT;
116         char *const args[] = { "/usr/bin/wlan.sh", "stop", NULL };
117         char *const envs[] = { NULL };
118
119         rv = netconfig_interface_down(WLAN_IFACE_NAME);
120         if (rv != TRUE)
121                 return -EIO;
122
123         rv = netconfig_execute_file(path, args, envs);
124         if (rv < 0)
125                 return -EIO;
126
127         DBG("Successfully removed p2p device driver");
128         return 0;
129 #else
130         return -ENODEV;
131 #endif
132 }
133
134 static int __netconfig_softap_firmware_start(void)
135 {
136 #if defined TIZEN_TETHERING_ENABLE
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 #else
152         return -ENODEV;
153 #endif
154 }
155
156 static int __netconfig_softap_firmware_stop(void)
157 {
158 #if defined TIZEN_TETHERING_ENABLE
159         int rv = 0;
160         const char *path = WLAN_DRIVER_SCRIPT;
161         char *const args[] = { "/usr/bin/wlan.sh", "stop", NULL };
162         char *const envs[] = { NULL };
163
164         rv = netconfig_interface_down(WLAN_IFACE_NAME);
165         if (rv != TRUE)
166                 return -EIO;
167
168         rv = netconfig_execute_file(path, args, envs);
169         if (rv < 0)
170                 return -EIO;
171
172         DBG("Successfully removed softap device driver");
173         return 0;
174 #else
175         return -ENODEV;
176 #endif
177 }
178
179 static int __netconfig_wifi_firmware_start(enum netconfig_wifi_firmware type)
180 {
181         if (emulator_is_emulated() == TRUE)
182                 return -EIO;
183
184         switch (type) {
185         case NETCONFIG_WIFI_STA:
186                 return __netconfig_sta_firmware_start();
187         case NETCONFIG_WIFI_P2P:
188                 return __netconfig_p2p_firmware_start();
189         case NETCONFIG_WIFI_SOFTAP:
190                 return __netconfig_softap_firmware_start();
191         default:
192                 break;
193         }
194
195         return -ENXIO;
196 }
197
198 static int __netconfig_wifi_firmware_stop(enum netconfig_wifi_firmware type)
199 {
200         if (emulator_is_emulated() == TRUE)
201                 return -EIO;
202
203         switch (type) {
204         case NETCONFIG_WIFI_STA:
205                 return __netconfig_sta_firmware_stop();
206         case NETCONFIG_WIFI_P2P:
207                 return __netconfig_p2p_firmware_stop();
208         case NETCONFIG_WIFI_SOFTAP:
209                 return __netconfig_softap_firmware_stop();
210         default:
211                 break;
212         }
213
214         return -ENXIO;
215 }
216
217 int netconfig_wifi_firmware(enum netconfig_wifi_firmware type, gboolean enable)
218 {
219         int err;
220         static enum netconfig_wifi_firmware current_driver = NETCONFIG_WIFI_OFF;
221         enum netconfig_wifi_firmware alias = type;
222
223 #if defined WLAN_CONCURRENT_MODE
224         int flight_mode = 0;
225
226         if (type == NETCONFIG_WIFI_P2P)
227                 alias = NETCONFIG_WIFI_STA;
228 #endif
229
230         DBG("Wi-Fi current firmware %d (type: %d %s)", current_driver, type,
231                                                         enable == TRUE ? "enable" : "disable");
232
233         if (enable == FALSE) {
234                 if (current_driver == NETCONFIG_WIFI_OFF) {
235                         return -EALREADY;
236                 } else if (current_driver == alias) {
237 #if defined WLAN_CHECK_POWERSAVE
238                         if (type == NETCONFIG_WIFI_STA && netconfig_wifi_is_powersave_mode() == TRUE) {
239                                 netconfig_interface_down(WIFI_IFNAME);
240                                 return -EALREADY;
241                         }
242 #endif
243
244 #if defined WLAN_CONCURRENT_MODE
245                         netconfig_vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &flight_mode);
246                         if (flight_mode == 0 && type == NETCONFIG_WIFI_STA &&
247                                         netconfig_is_wifi_direct_on() == TRUE) {
248                                 netconfig_interface_down(WIFI_IFNAME);
249
250                                 return -EALREADY;
251                         }
252
253                         if (type == NETCONFIG_WIFI_P2P && wifi_state_get_technology_state() > NETCONFIG_WIFI_TECH_OFF) {
254                                 netconfig_interface_down(WLAN_P2P_IFACE_NAME);
255
256                                 return -EALREADY;
257                         }
258 #endif
259                         err = __netconfig_wifi_firmware_stop(type);
260                         if (err < 0 && err != -EALREADY)
261                                 return err;
262
263                         current_driver = NETCONFIG_WIFI_OFF;
264
265                         return err;
266                 }
267
268                 return -EIO;
269         }
270
271         if (current_driver > NETCONFIG_WIFI_OFF) {
272                 if (current_driver == alias) {
273 #if defined WLAN_CHECK_POWERSAVE
274                         if (type == NETCONFIG_WIFI_STA && netconfig_wifi_is_powersave_mode() == TRUE) {
275                                 netconfig_interface_up(WIFI_IFNAME);
276
277                                 return -EALREADY;
278                         }
279 #endif
280
281 #if defined WLAN_CONCURRENT_MODE
282                         if (type == NETCONFIG_WIFI_STA)
283                                 netconfig_interface_up(WIFI_IFNAME);
284 #if defined TIZEN_P2P_ENABLE
285                         else if (type == NETCONFIG_WIFI_P2P)
286                                 netconfig_interface_up(WLAN_P2P_IFACE_NAME);
287 #endif
288 #endif
289                         return -EALREADY;
290                 }
291
292                 return -EIO;
293         }
294
295         err = __netconfig_wifi_firmware_start(type);
296         if (err < 0)
297                 DBG("Failed to execute script file");
298         else
299                 current_driver = alias;
300
301         return err;
302 }
303
304 gboolean handle_start(WifiFirmware *firmware, GDBusMethodInvocation *context, const gchar *device)
305 {
306         int err;
307
308         g_return_val_if_fail(firmware != NULL, FALSE);
309
310         DBG("Wi-Fi firmware start %s", device != NULL ? device : "null");
311
312         if (g_strcmp0("p2p", device) == 0)
313                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, TRUE);
314         else if (g_strcmp0("softap", device) == 0)
315                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, TRUE);
316         else
317                 err = -EINVAL;
318
319         if (err < 0) {
320                 if (err == -EALREADY)
321                         netconfig_error_already_exists(context);
322                 else if (g_strcmp0("softap", device) == 0 && err == -EIO && netconfig_is_wifi_direct_on() == FALSE) {
323                         if (netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, FALSE) == 0 && netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, TRUE) == 0) {
324                                 wifi_firmware_complete_start(firmware, context);
325                                 return TRUE;
326                         } else
327                                 netconfig_error_wifi_driver_failed(context);
328                 } else
329                         netconfig_error_wifi_driver_failed(context);
330
331                 return FALSE;
332         }
333
334         wifi_firmware_complete_start(firmware, context);
335         return TRUE;
336 }
337
338 gboolean handle_stop(WifiFirmware *firmware, GDBusMethodInvocation *context, const gchar *device)
339 {
340         int err;
341
342         g_return_val_if_fail(firmware != NULL, FALSE);
343
344         DBG("Wi-Fi firmware stop %s", device != NULL ? device : "null");
345
346         if (g_strcmp0("p2p", device) == 0)
347                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, FALSE);
348         else if (g_strcmp0("softap", device) == 0)
349                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, FALSE);
350         else
351                 err = -EINVAL;
352
353         if (err < 0) {
354                 if (err == -EALREADY)
355                         netconfig_error_already_exists(context);
356                 else
357                         netconfig_error_wifi_driver_failed(context);
358
359                 return FALSE;
360         }
361
362         wifi_firmware_complete_stop(firmware, context);
363         return TRUE;
364 }