Merge "Refactored "NetlinkScan" DBus method." into tizen
[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
33 #define WLAN_DRIVER_SCRIPT                      "/usr/bin/wlan.sh"
34 #define WLAN_IFACE_NAME                         "wlan0"
35
36 #define WLAN_P2P_IFACE_NAME_TV                  "p2p0"
37 #define WLAN_P2P_IFACE_NAME_COMMON                      "wlan0"
38 #define WLAN_P2P_IFACE_NAME ((TIZEN_TV) ? (WLAN_P2P_IFACE_NAME_TV) : (WLAN_P2P_IFACE_NAME_COMMON))
39
40 static int __netconfig_sta_firmware_start(void)
41 {
42         int rv = 0;
43         const char *path = WLAN_DRIVER_SCRIPT;
44         char *const args[] = { "/usr/bin/wlan.sh", "start", NULL };
45         char *const envs[] = { NULL };
46
47         rv = netconfig_execute_file(path, args, envs);
48         if (rv < 0)
49                 return -EIO;
50
51         rv = netconfig_interface_up(WLAN_IFACE_NAME);
52         if (rv != TRUE)
53                 return -EIO;
54
55         DBG("Successfully loaded wireless device driver");
56         return 0;
57 }
58
59 static int __netconfig_sta_firmware_stop(void)
60 {
61         int rv = 0;
62         const char *path = WLAN_DRIVER_SCRIPT;
63         char *const args[] = { "/usr/bin/wlan.sh", "stop", NULL };
64         char *const envs[] = { NULL };
65
66         /* Update statistics before driver remove */
67         netconfig_wifi_statistics_update_powered_off();
68
69         rv = netconfig_interface_down(WLAN_IFACE_NAME);
70         if (rv != TRUE)
71                 return -EIO;
72
73         rv = netconfig_execute_file(path, args, envs);
74         if (rv < 0)
75                 return -EIO;
76
77         DBG("Successfully removed wireless device driver");
78         return 0;
79 }
80
81 static int __netconfig_p2p_firmware_start(void)
82 {
83         if (!netconfig_check_feature_supported(WIFI_DIRECT_FEATURE))
84                 return -ENODEV;
85
86         int rv = 0;
87         const char *path = WLAN_DRIVER_SCRIPT;
88         char *const args[] = { "/usr/bin/wlan.sh", "p2p", NULL };
89         char *const envs[] = { NULL };
90
91         rv = netconfig_execute_file(path, args, envs);
92         if (rv < 0)
93                 return -EIO;
94
95 #if defined TIZEN_WLAN_USE_P2P_INTERFACE
96         rv = netconfig_interface_up(WLAN_P2P_IFACE_NAME);
97         if (rv != TRUE)
98                 return -EIO;
99 #endif
100
101         DBG("Successfully loaded p2p device driver");
102         return 0;
103 }
104
105 static int __netconfig_p2p_firmware_stop(void)
106 {
107         if (!netconfig_check_feature_supported(WIFI_DIRECT_FEATURE))
108                 return -ENODEV;
109
110         int rv = 0;
111         const char *path = WLAN_DRIVER_SCRIPT;
112         char *const args[] = { "/usr/bin/wlan.sh", "stop", NULL };
113         char *const envs[] = { NULL };
114
115         rv = netconfig_interface_down(WLAN_IFACE_NAME);
116         if (rv != TRUE)
117                 return -EIO;
118
119         rv = netconfig_execute_file(path, args, envs);
120         if (rv < 0)
121                 return -EIO;
122
123         DBG("Successfully removed p2p device driver");
124         return 0;
125 }
126
127 static int __netconfig_softap_firmware_start(void)
128 {
129         if (!netconfig_check_feature_supported(TETHERING_FEATURE))
130                 return -ENODEV;
131
132         int rv = 0;
133         const char *path = WLAN_DRIVER_SCRIPT;
134         char *const args[] = { "/usr/bin/wlan.sh", "softap", NULL };
135         char *const envs[] = { NULL };
136
137         rv = netconfig_execute_file(path, args, envs);
138         if (rv < 0)
139                 return -EIO;
140
141         if (netconfig_interface_up(WLAN_IFACE_NAME) == FALSE)
142                 return -EIO;
143
144         DBG("Successfully loaded softap device driver");
145         return 0;
146 }
147
148 static int __netconfig_softap_firmware_stop(void)
149 {
150         if (!netconfig_check_feature_supported(TETHERING_FEATURE))
151                 return -ENODEV;
152
153         int rv = 0;
154         const char *path = WLAN_DRIVER_SCRIPT;
155         char *const args[] = { "/usr/bin/wlan.sh", "stop", NULL };
156         char *const envs[] = { NULL };
157
158         rv = netconfig_interface_down(WLAN_IFACE_NAME);
159         if (rv != TRUE)
160                 return -EIO;
161
162         rv = netconfig_execute_file(path, args, envs);
163         if (rv < 0)
164                 return -EIO;
165
166         DBG("Successfully removed softap device driver");
167         return 0;
168 }
169
170 static int __netconfig_wifi_firmware_start(enum netconfig_wifi_firmware type)
171 {
172         if (emulator_is_emulated() == TRUE)
173                 return -EIO;
174
175         switch (type) {
176         case NETCONFIG_WIFI_STA:
177                 return __netconfig_sta_firmware_start();
178         case NETCONFIG_WIFI_P2P:
179                 return __netconfig_p2p_firmware_start();
180         case NETCONFIG_WIFI_SOFTAP:
181                 return __netconfig_softap_firmware_start();
182         default:
183                 break;
184         }
185
186         return -ENXIO;
187 }
188
189 static int __netconfig_wifi_firmware_stop(enum netconfig_wifi_firmware type)
190 {
191         if (emulator_is_emulated() == TRUE)
192                 return -EIO;
193
194         switch (type) {
195         case NETCONFIG_WIFI_STA:
196                 return __netconfig_sta_firmware_stop();
197         case NETCONFIG_WIFI_P2P:
198                 return __netconfig_p2p_firmware_stop();
199         case NETCONFIG_WIFI_SOFTAP:
200                 return __netconfig_softap_firmware_stop();
201         default:
202                 break;
203         }
204
205         return -ENXIO;
206 }
207
208 int netconfig_wifi_firmware(enum netconfig_wifi_firmware type, gboolean enable)
209 {
210         int err;
211         static enum netconfig_wifi_firmware current_driver = NETCONFIG_WIFI_OFF;
212         enum netconfig_wifi_firmware alias = type;
213
214 #if defined WLAN_CONCURRENT_MODE
215         int flight_mode = 0;
216
217         if (type == NETCONFIG_WIFI_P2P)
218                 alias = NETCONFIG_WIFI_STA;
219 #endif
220
221         DBG("Wi-Fi current firmware %d (type: %d %s)", current_driver, type,
222                                                         enable == TRUE ? "enable" : "disable");
223
224         if (enable == FALSE) {
225                 if (current_driver == NETCONFIG_WIFI_OFF) {
226                         return -EALREADY;
227                 } else if (current_driver == alias) {
228
229 #if defined WLAN_CONCURRENT_MODE
230                         netconfig_vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &flight_mode);
231                         if (flight_mode == 0 && type == NETCONFIG_WIFI_STA &&
232                                         netconfig_is_wifi_direct_on() == TRUE) {
233                                 netconfig_interface_down(WIFI_IFNAME);
234
235                                 return -EALREADY;
236                         }
237
238                         if (type == NETCONFIG_WIFI_P2P && wifi_state_get_technology_state() > NETCONFIG_WIFI_TECH_OFF) {
239                                 netconfig_interface_down(WLAN_P2P_IFACE_NAME);
240
241                                 return -EALREADY;
242                         }
243 #endif
244                         err = __netconfig_wifi_firmware_stop(type);
245                         if (err < 0 && err != -EALREADY)
246                                 return err;
247
248                         current_driver = NETCONFIG_WIFI_OFF;
249
250                         return err;
251                 }
252
253                 return -EIO;
254         }
255
256         if (current_driver > NETCONFIG_WIFI_OFF) {
257                 if (current_driver == alias) {
258
259 #if defined WLAN_CONCURRENT_MODE
260                         if (type == NETCONFIG_WIFI_STA)
261                                 netconfig_interface_up(WIFI_IFNAME);
262                         else if (netconfig_check_feature_supported(WIFI_DIRECT_FEATURE)
263                                         && type == NETCONFIG_WIFI_P2P)
264                                 netconfig_interface_up(WLAN_P2P_IFACE_NAME);
265 #endif
266                         return -EALREADY;
267                 }
268
269                 return -EIO;
270         }
271
272         err = __netconfig_wifi_firmware_start(type);
273         if (err < 0)
274                 DBG("Failed to execute script file");
275         else
276                 current_driver = alias;
277
278         return err;
279 }
280
281 gboolean handle_start(WifiFirmware *firmware, GDBusMethodInvocation *context, const gchar *device)
282 {
283         int err;
284
285         g_return_val_if_fail(firmware != NULL, FALSE);
286
287         DBG("Wi-Fi firmware start %s", device != NULL ? device : "null");
288
289         if (g_strcmp0("p2p", device) == 0)
290                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, TRUE);
291         else if (g_strcmp0("softap", device) == 0)
292                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, TRUE);
293         else
294                 err = -EINVAL;
295
296         if (err < 0) {
297                 if (err == -EALREADY)
298                         netconfig_error_already_exists(context);
299                 else if (g_strcmp0("softap", device) == 0 && err == -EIO && netconfig_is_wifi_direct_on() == FALSE) {
300                         if (netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, FALSE) == 0 && netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, TRUE) == 0) {
301                                 wifi_firmware_complete_start(firmware, context);
302                                 return TRUE;
303                         } else
304                                 netconfig_error_wifi_driver_failed(context);
305                 } else
306                         netconfig_error_wifi_driver_failed(context);
307
308                 return FALSE;
309         }
310
311         wifi_firmware_complete_start(firmware, context);
312         return TRUE;
313 }
314
315 gboolean handle_stop(WifiFirmware *firmware, GDBusMethodInvocation *context, const gchar *device)
316 {
317         int err;
318
319         g_return_val_if_fail(firmware != NULL, FALSE);
320
321         DBG("Wi-Fi firmware stop %s", device != NULL ? device : "null");
322
323         if (g_strcmp0("p2p", device) == 0)
324                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, FALSE);
325         else if (g_strcmp0("softap", device) == 0)
326                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, FALSE);
327         else
328                 err = -EINVAL;
329
330         if (err < 0) {
331                 if (err == -EALREADY)
332                         netconfig_error_already_exists(context);
333                 else
334                         netconfig_error_wifi_driver_failed(context);
335
336                 return FALSE;
337         }
338
339         wifi_firmware_complete_stop(firmware, context);
340         return TRUE;
341 }