Revise unncessary functions
[framework/connectivity/net-config.git] / src / wifi-power.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Danny JS Seo <S.Seo@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <vconf.h>
25 #include <vconf-keys.h>
26 #include <wifi-direct.h>
27
28 #include "log.h"
29 #include "wifi.h"
30 #include "dbus.h"
31 #include "util.h"
32 #include "neterror.h"
33 #include "netconfig.h"
34 #include "emulator.h"
35 #include "wifi-state.h"
36 #include "wifi-background-scan.h"
37
38 gboolean netconfig_iface_wifi_load_driver(NetconfigWifi *wifi, GError **error);
39 gboolean netconfig_iface_wifi_remove_driver(NetconfigWifi *wifi, GError **error);
40
41 #include "netconfig-iface-wifi-glue.h"
42
43 #define NETCONFIG_WIFI_PATH     "/net/netconfig/wifi"
44
45 #define WLAN_DRIVER_SCRIPT "/usr/bin/wlan.sh"
46
47 #define PROP_DEFAULT            FALSE
48 #define PROP_DEFAULT_STR        NULL
49
50 enum {
51         PROP_O,
52         PROP_WIFI_CONN,
53         PROP_WIFI_PATH,
54 };
55
56 enum {
57         SIG_WIFI_DRIVER,
58         SIG_LAST
59 };
60
61 struct NetconfigWifiClass {
62         GObjectClass parent;
63
64         /* method and signals */
65         void (*driver_loaded) (NetconfigWifi *wifi, gchar *mac);
66 };
67
68 struct NetconfigWifi {
69         GObject parent;
70
71         /* member variable */
72         DBusGConnection *conn;
73         gchar *path;
74 };
75
76 static guint32 signals[SIG_LAST] = { 0, };
77
78 G_DEFINE_TYPE(NetconfigWifi, netconfig_wifi, G_TYPE_OBJECT);
79
80
81 static void __netconfig_wifi_gobject_get_property(GObject *object, guint prop_id,
82                 GValue *value, GParamSpec *pspec)
83 {
84         return;
85 }
86
87 static void __netconfig_wifi_gobject_set_property(GObject *object, guint prop_id,
88                 const GValue *value, GParamSpec *pspec)
89 {
90         NetconfigWifi *wifi = NETCONFIG_WIFI(object);
91
92         switch (prop_id) {
93         case PROP_WIFI_CONN:
94         {
95                 wifi->conn = g_value_get_boxed(value);
96                 INFO("wifi(%p) set conn(%p)", wifi, wifi->conn);
97                 break;
98         }
99
100         case PROP_WIFI_PATH:
101         {
102                 if (wifi->path)
103                         g_free(wifi->path);
104
105                 wifi->path = g_value_dup_string(value);
106                 INFO("wifi(%p) path(%s)", wifi, wifi->path);
107
108                 break;
109         }
110
111         default:
112                 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
113         }
114 }
115
116 static void netconfig_wifi_init(NetconfigWifi *wifi)
117 {
118         DBG("wifi initialize");
119
120         wifi->conn = NULL;
121         wifi->path = g_strdup(PROP_DEFAULT_STR);
122 }
123
124 static void netconfig_wifi_class_init(NetconfigWifiClass *klass)
125 {
126         GObjectClass *object_class = G_OBJECT_CLASS(klass);
127
128         DBG("class initialize");
129
130         object_class->get_property = __netconfig_wifi_gobject_get_property;
131         object_class->set_property = __netconfig_wifi_gobject_set_property;
132
133         /* DBus register */
134         dbus_g_object_type_install_info(NETCONFIG_TYPE_WIFI,
135                         &dbus_glib_netconfig_iface_wifi_object_info);
136
137         /* property */
138         g_object_class_install_property(object_class, PROP_WIFI_CONN,
139                         g_param_spec_boxed("conn", "CONNECTION", "DBus connection",
140                                 DBUS_TYPE_G_CONNECTION,
141                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
142
143         g_object_class_install_property(object_class, PROP_WIFI_PATH,
144                         g_param_spec_string("path", "PATH", "Object Path",
145                                 PROP_DEFAULT_STR,
146                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
147
148         /* signal */
149         signals[SIG_WIFI_DRIVER] = g_signal_new("driver-loaded",
150                         G_OBJECT_CLASS_TYPE(klass),
151                         G_SIGNAL_RUN_LAST,
152                         G_STRUCT_OFFSET(NetconfigWifiClass,
153                                 driver_loaded),
154                         NULL, NULL,
155                         g_cclosure_marshal_VOID__STRING,
156                         G_TYPE_NONE, 1, G_TYPE_STRING);
157 }
158
159
160 static gboolean __netconfig_wifi_enable_technology(void)
161 {
162         DBusMessage *reply = NULL;
163         char path[DBUS_PATH_MAX_BUFLEN] = "/";
164         char request[] = CONNMAN_MANAGER_INTERFACE ".EnableTechnology";
165         char param1[] = "string:wifi";
166         char *param_array[] = {
167                 NULL,
168                 NULL,
169                 NULL,
170                 NULL
171         };
172
173         param_array[0] = path;
174         param_array[1] = request;
175         param_array[2] = param1;
176
177         reply = netconfig_dbus_send_request(CONNMAN_SERVICE, param_array);
178         if (reply == NULL) {
179                 ERR("Error! Request failed");
180
181                 return FALSE;
182         }
183
184         dbus_message_unref(reply);
185
186         return TRUE;
187 }
188
189 static gboolean __netconfig_wifi_disable_technology(void)
190 {
191         DBusMessage *reply = NULL;
192         char path[DBUS_PATH_MAX_BUFLEN] = "/";
193         char request[] = CONNMAN_MANAGER_INTERFACE ".DisableTechnology";
194         char param1[] = "string:wifi";
195         char *param_array[] = {
196                 NULL,
197                 NULL,
198                 NULL,
199                 NULL
200         };
201
202         param_array[0] = path;
203         param_array[1] = request;
204         param_array[2] = param1;
205
206         reply = netconfig_dbus_send_request(CONNMAN_SERVICE, param_array);
207         if (reply == NULL) {
208                 ERR("Error! Request failed");
209
210                 return FALSE;
211         }
212
213         dbus_message_unref(reply);
214
215         return TRUE;
216 }
217
218 static gboolean __netconfig_wifi_load_driver(void)
219 {
220         gboolean rv = FALSE;
221         const char *path = WLAN_DRIVER_SCRIPT;
222         char *const args[] = { "wlan.sh", "start" };
223         char *const envs[] = { NULL };
224
225         if (netconfig_emulator_is_emulated() == TRUE)
226                 return rv;
227
228         rv = netconfig_execute_file(path, args, envs);
229         if (rv != TRUE) {
230                 DBG("failed to load wireless device driver");
231                 return FALSE;
232         }
233
234         DBG("Successfully loaded wireless device drivers");
235         return TRUE;
236 }
237
238 static gboolean __netconfig_wifi_remove_driver(void)
239 {
240         gboolean rv = FALSE;
241         const char *path = WLAN_DRIVER_SCRIPT;
242         char *const args[] = { "wlan.sh", "stop" };
243         char *const env[] = { NULL };
244
245         if (netconfig_emulator_is_emulated() == TRUE)
246                 return rv;
247
248         rv = netconfig_execute_file(path, args, env);
249         if (rv != TRUE) {
250                 DBG("failed to remove(unload) driver for wireless device");
251                 return FALSE;
252         }
253
254         DBG("Successfully removed(unloaded) wireless driver");
255         return TRUE;
256 }
257
258 static gboolean __netconfig_wifi_try_to_load_driver(void);
259 static gboolean __netconfig_wifi_try_to_remove_driver(void);
260
261 static void __netconfig_wifi_direct_state_cb(int error_code,
262                 wifi_direct_device_state_e device_state, void *user_data)
263 {
264         wifi_direct_unset_device_state_changed_cb();
265         wifi_direct_deinitialize();
266
267         if (device_state == WIFI_DIRECT_DEVICE_STATE_DEACTIVATED) {
268                 __netconfig_wifi_try_to_load_driver();
269
270                 return;
271         }
272
273         /* TODO: error report */
274 }
275
276 static gboolean __netconfig_wifi_direct_power_off(void)
277 {
278         DBG("Wi-Fi direct is turning off");
279
280         if (wifi_direct_initialize() < 0)
281                 return FALSE;
282
283         if (wifi_direct_set_device_state_changed_cb(
284                         __netconfig_wifi_direct_state_cb, NULL) < 0)
285                 return FALSE;
286
287         if (wifi_direct_deactivate() < 0)
288                 return FALSE;
289
290         return TRUE;
291 }
292
293 static gboolean __netconfig_wifi_try_to_load_driver(void)
294 {
295         int count = 0;
296         gchar *wifi_tech_state = NULL;
297
298         if (netconfig_is_wifi_tethering_on() == TRUE) {
299                 /* TODO: Wi-Fi tethering turns off here */
300                 /* return TRUE; */
301                 return FALSE;
302         }
303
304         if (netconfig_is_wifi_direct_on() == TRUE) {
305                 if (__netconfig_wifi_direct_power_off() == TRUE)
306                         return TRUE;
307                 else
308                         return FALSE;
309         }
310
311         if (__netconfig_wifi_load_driver() != TRUE) {
312                 __netconfig_wifi_remove_driver();
313
314                 return FALSE;
315         }
316
317         for (count = 0; count < 3; count++) {
318                 __netconfig_wifi_enable_technology();
319
320                 wifi_tech_state = netconfig_wifi_get_technology_state();
321                 INFO("Wi-Fi technology state: %s", wifi_tech_state);
322
323                 if (g_str_equal(wifi_tech_state, "EnabledTechnologies") == TRUE) {
324                         netconfig_wifi_update_power_state(TRUE);
325
326                         netconfig_wifi_device_picker_service_start();
327
328                         return TRUE;
329                 }
330
331                 g_free(wifi_tech_state);
332
333                 wifi_tech_state = NULL;
334         }
335
336         __netconfig_wifi_try_to_remove_driver();
337
338         return FALSE;
339 }
340
341 static gboolean __netconfig_wifi_try_to_remove_driver(void)
342 {
343         int count = 0;
344         gchar *wifi_tech_state = NULL;
345
346         netconfig_wifi_device_picker_service_stop();
347
348         for (count = 0; count < 3; count++) {
349                 __netconfig_wifi_disable_technology();
350
351                 wifi_tech_state = netconfig_wifi_get_technology_state();
352                 INFO("Wi-Fi technology state: %s", wifi_tech_state);
353
354                 if (g_str_equal(wifi_tech_state, "EnabledTechnologies") != TRUE) {
355                         netconfig_wifi_update_power_state(FALSE);
356
357                         return __netconfig_wifi_remove_driver();
358                 }
359
360                 g_free(wifi_tech_state);
361
362                 wifi_tech_state = NULL;
363         }
364
365         return __netconfig_wifi_remove_driver();
366 }
367
368 static void __netconfig_wifi_airplane_mode(keynode_t* node,
369                 void* user_data)
370 {
371         int value = 0;
372         int wifi_state = 0;
373         static gboolean powered_off_by_flightmode = FALSE;
374
375         vconf_get_bool(VCONFKEY_SETAPPL_FLIGHT_MODE_BOOL, &value);
376         vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
377
378         DBG("flight mode %s", value > 0 ? "ON" : "OFF");
379         DBG("Wi-Fi state %d, Wi-Fi was off by flight mode %s",
380                         wifi_state, powered_off_by_flightmode == TRUE ? "Yes" : "No");
381
382         if (value > 0) {
383                 /* flight mode enabled */
384                 if (wifi_state == VCONFKEY_WIFI_OFF)
385                         return;
386
387                 DBG("Turning Wi-Fi off");
388
389                 __netconfig_wifi_try_to_remove_driver();
390
391                 powered_off_by_flightmode = TRUE;
392         } else if (value == 0) {
393                 /* flight mode disabled */
394                 if (wifi_state > VCONFKEY_WIFI_OFF)
395                         return;
396
397                 if (powered_off_by_flightmode != TRUE)
398                         return;
399
400                 __netconfig_wifi_try_to_load_driver();
401
402                 powered_off_by_flightmode = FALSE;
403         } else
404                 DBG("Invalid value (%d)", value);
405 }
406
407 static void __netconfig_wifi_pm_state_mode(keynode_t* node,
408                 void* user_data)
409 {
410         int value = -1;
411         int wifi_state = 0;
412         static int prev_state = VCONFKEY_PM_STATE_NORMAL;
413
414         /*** vconf-keys.h ***
415          *              VCONFKEY_PM_STATE_NORMAL = 1,
416          *              VCONFKEY_PM_STATE_LCDDIM,
417          *              VCONFKEY_PM_STATE_LCDOFF,
418          *              VCONFKEY_PM_STATE_SLEEP
419          */
420
421         if(vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state) == 0) {
422                 DBG("wifi state : %d (0 off / 1 on / 2 connected)", wifi_state);
423                 if(wifi_state <= VCONFKEY_WIFI_OFF)
424                         return;
425         }
426
427         if(vconf_get_int(VCONFKEY_PM_STATE, &value) < 0) {
428                 ERR("VCONFKEY_PM_STATE get failed");
429                 return;
430         }
431
432         DBG("Old state: %d, current: %d", prev_state, value);
433
434         if((value == VCONFKEY_PM_STATE_NORMAL) && (prev_state >= VCONFKEY_PM_STATE_LCDOFF)) {
435                 DBG("PM state : Wake UP!");
436
437                 netconfig_wifi_bgscan_stop();
438                 netconfig_wifi_bgscan_start();
439         }
440
441         prev_state = value;
442 }
443
444 static void __netconfig_wifi_power_configuration(void)
445 {
446         int wifi_last_state = 0;
447
448         vconf_notify_key_changed(VCONFKEY_SETAPPL_FLIGHT_MODE_BOOL,
449                         __netconfig_wifi_airplane_mode, NULL);
450
451         vconf_notify_key_changed(VCONFKEY_PM_STATE,
452                         __netconfig_wifi_pm_state_mode, NULL);
453
454         vconf_get_int(VCONF_WIFI_LAST_POWER_ON_STATE, &wifi_last_state);
455
456         if (wifi_last_state == WIFI_POWER_ON) {
457                 DBG("Turn Wi-Fi on automatically");
458
459                 __netconfig_wifi_try_to_load_driver();
460         }
461 }
462
463 gpointer netconfig_wifi_create_and_init(DBusGConnection *conn)
464 {
465         GObject *object;
466
467         g_return_val_if_fail(conn != NULL, NULL);
468
469         object = g_object_new(NETCONFIG_TYPE_WIFI, "conn", conn, "path",
470                         NETCONFIG_WIFI_PATH, NULL);
471
472         INFO("create wifi(%p)", object);
473
474         dbus_g_connection_register_g_object(conn, NETCONFIG_WIFI_PATH, object);
475
476         INFO("wifi(%p) register DBus path(%s)", object, NETCONFIG_WIFI_PATH);
477
478         __netconfig_wifi_power_configuration();
479
480         return object;
481 }
482
483 gboolean netconfig_iface_wifi_load_driver(NetconfigWifi *wifi, GError **error)
484 {
485         DBG("Wi-Fi turned on");
486
487         g_return_val_if_fail(wifi != NULL, FALSE);
488
489         if (__netconfig_wifi_try_to_load_driver() != TRUE) {
490                 netconfig_error_wifi_driver_failed(error);
491
492                 return FALSE;
493         }
494
495         return TRUE;
496 }
497
498 gboolean netconfig_iface_wifi_remove_driver(NetconfigWifi *wifi, GError **error)
499 {
500         DBG("Wi-Fi turned off");
501
502         g_return_val_if_fail(wifi != NULL, FALSE);
503
504         if (__netconfig_wifi_try_to_remove_driver() != TRUE) {
505                 netconfig_error_wifi_driver_failed(error);
506
507                 return FALSE;
508         }
509
510         return TRUE;
511 }