Initialize Tizen 2.3
[framework/connectivity/net-config.git] / mobile / src / wifi-background-scan.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012-2013 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 <glib.h>
21 #include <vconf.h>
22 #include <vconf-keys.h>
23
24 #include "log.h"
25 #include "util.h"
26 #include "wifi.h"
27 #include "netdbus.h"
28 #include "wifi-state.h"
29 #include "wifi-background-scan.h"
30
31 #define SCAN_PERIODIC_DELAY             10
32 #define SCAN_EXPONENTIAL_MIN    4
33 #define SCAN_EXPONENTIAL_MAX    128
34
35 enum {
36         WIFI_BGSCAN_MODE_EXPONENTIAL = 0x00,
37         WIFI_BGSCAN_MODE_PERIODIC,
38         WIFI_BGSCAN_MODE_MAX,
39 };
40
41 struct bgscan_timer_data {
42         guint time;
43         guint mode;
44         guint timer_id;
45 };
46
47 static gboolean netconfig_wifi_scanning = FALSE;
48
49 static struct bgscan_timer_data *__netconfig_wifi_bgscan_get_bgscan_data(void)
50 {
51         static struct bgscan_timer_data timer_data = {SCAN_EXPONENTIAL_MIN, WIFI_BGSCAN_MODE_EXPONENTIAL, 0};
52
53         return &timer_data;
54 }
55
56 static guint __netconfig_wifi_bgscan_mode(gboolean is_set_mode, guint mode)
57 {
58         static guint bgscan_mode = WIFI_BGSCAN_MODE_EXPONENTIAL;
59
60         if (is_set_mode != TRUE)
61                 return bgscan_mode;
62
63         if (mode < WIFI_BGSCAN_MODE_MAX)
64                 bgscan_mode = mode;
65
66         DBG("Wi-Fi background scan mode set %d", bgscan_mode);
67
68         return bgscan_mode;
69 }
70
71 static void __netconfig_wifi_bgscan_set_mode(guint mode)
72 {
73         __netconfig_wifi_bgscan_mode(TRUE, mode);
74 }
75
76 static guint __netconfig_wifi_bgscan_get_mode(void)
77 {
78         return __netconfig_wifi_bgscan_mode(FALSE, -1);
79 }
80
81 static gboolean __netconfig_wifi_bgscan_request_connman_scan(void)
82 {
83         DBusMessage *reply = NULL;
84
85         if (netconfig_wifi_state_get_service_state() == NETCONFIG_WIFI_CONNECTED)
86                 if (__netconfig_wifi_bgscan_get_mode() == WIFI_BGSCAN_MODE_EXPONENTIAL)
87                         return FALSE;
88
89         if (netconfig_wifi_state_get_service_state() == NETCONFIG_WIFI_CONNECTING)
90                 return FALSE;
91
92         netconfig_wifi_set_scanning(TRUE);
93
94                 reply = netconfig_invoke_dbus_method(CONNMAN_SERVICE, CONNMAN_WIFI_TECHNOLOGY_PREFIX,
95                         CONNMAN_TECHNOLOGY_INTERFACE, "Scan", NULL);
96
97         if (reply == NULL) {
98                 ERR("Error! Request failed");
99                 return FALSE;
100         }
101
102         dbus_message_unref(reply);
103
104         return TRUE;
105 }
106
107 static gboolean __netconfig_wifi_bgscan_request_scan(gpointer data);
108
109 static void __netconfig_wifi_bgscan_start_timer(struct bgscan_timer_data *data)
110 {
111         if (data == NULL)
112                 return;
113
114         netconfig_stop_timer(&(data->timer_id));
115
116         data->mode = __netconfig_wifi_bgscan_get_mode();
117
118         switch (data->mode) {
119         case WIFI_BGSCAN_MODE_EXPONENTIAL:
120                 if (data->time == 0)
121                         data->time = SCAN_EXPONENTIAL_MIN;
122                 else if ((data->time >= SCAN_EXPONENTIAL_MAX) ||
123                                 (data->time > SCAN_EXPONENTIAL_MAX / 2))
124                         data->time = SCAN_EXPONENTIAL_MAX;
125                 else
126                         data->time = data->time * 2;
127
128                 break;
129         case WIFI_BGSCAN_MODE_PERIODIC:
130                 data->time = SCAN_PERIODIC_DELAY;
131
132                 break;
133         default:
134                 DBG("Error! Wi-Fi background scan mode [%d]", data->mode);
135                 return;
136         }
137
138         DBG("Register background scan timer with %d seconds", data->time);
139
140         netconfig_start_timer_seconds(data->time,
141                         __netconfig_wifi_bgscan_request_scan, data, &(data->timer_id));
142 }
143
144 static void __netconfig_wifi_bgscan_stop_timer(struct bgscan_timer_data *data)
145 {
146         if (data == NULL)
147                 return;
148
149         netconfig_stop_timer(&(data->timer_id));
150 }
151
152 static gboolean __netconfig_wifi_bgscan_request_scan(gpointer data)
153 {
154         struct bgscan_timer_data *timer = (struct bgscan_timer_data *)data;
155         int pm_state = VCONFKEY_PM_STATE_NORMAL;
156
157         if (timer == NULL)
158                 return FALSE;
159
160         /* In case of LCD off, we don't need Wi-Fi scan */
161         vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
162         if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
163                 return TRUE;
164
165         __netconfig_wifi_bgscan_stop_timer(timer);
166
167         DBG("Request Wi-Fi scan to ConnMan");
168         __netconfig_wifi_bgscan_request_connman_scan();
169
170         __netconfig_wifi_bgscan_start_timer(timer);
171
172         return FALSE;
173 }
174
175 static void __netconfig_wifi_bgscan_mode_cb(keynode_t* node, void* user_data)
176 {
177         int value;
178         int wifi_state;
179
180         if (vconf_get_int(VCONFKEY_WIFI_BGSCAN_MODE, &value) < 0) {
181                 ERR("VCONFKEY_WIFI_BGSCAN_MODE get failed");
182                 return;
183         }
184
185         DBG("Background scanning mode is changed : %d", value);
186
187         __netconfig_wifi_bgscan_set_mode((guint)value);
188
189         if (vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state) < 0) {
190                 ERR("VCONFKEY_WIFI_STATE get failed");
191                 return;
192         }
193
194         if (wifi_state == VCONFKEY_WIFI_OFF)
195                 return;
196
197         struct bgscan_timer_data *timer_data = __netconfig_wifi_bgscan_get_bgscan_data();
198
199         if (timer_data->timer_id != 0)
200                 netconfig_wifi_bgscan_stop();
201
202         netconfig_wifi_bgscan_start();
203 }
204
205 void netconfig_wifi_bgscan_start(void)
206 {
207         struct bgscan_timer_data *timer_data =
208                         __netconfig_wifi_bgscan_get_bgscan_data();
209
210         if (timer_data == NULL)
211                 return;
212
213         DBG("Wi-Fi background scan start");
214
215         __netconfig_wifi_bgscan_start_timer(timer_data);
216 }
217
218 void netconfig_wifi_bgscan_stop(void)
219 {
220         struct bgscan_timer_data *timer_data =
221                         __netconfig_wifi_bgscan_get_bgscan_data();
222
223         if (timer_data == NULL)
224                 return;
225
226         DBG("Wi-Fi background scan stop");
227
228         timer_data->time = SCAN_EXPONENTIAL_MIN;
229
230         __netconfig_wifi_bgscan_stop_timer(timer_data);
231 }
232
233 gboolean netconfig_wifi_get_bgscan_state(void)
234 {
235         struct bgscan_timer_data *timer_data =
236                         __netconfig_wifi_bgscan_get_bgscan_data();
237
238         return ((timer_data->timer_id > (guint)0) ? TRUE : FALSE);
239 }
240
241 gboolean netconfig_wifi_get_scanning(void)
242 {
243         return netconfig_wifi_scanning;
244 }
245
246 void netconfig_wifi_set_scanning(gboolean scanning)
247 {
248         if (netconfig_wifi_scanning != scanning)
249                 netconfig_wifi_scanning = scanning;
250 }
251
252 gboolean netconfig_iface_wifi_set_bgscan(NetconfigWifi *wifi, guint scan_mode, GError **error)
253 {
254         struct bgscan_timer_data *timer_data = __netconfig_wifi_bgscan_get_bgscan_data();
255
256         __netconfig_wifi_bgscan_set_mode(scan_mode);
257
258         if (timer_data->timer_id != 0)
259                 netconfig_wifi_bgscan_stop();
260
261         netconfig_wifi_bgscan_start();
262
263         return TRUE;
264 }
265
266 void netconfig_wifi_init_bgscan()
267 {
268         guint scan_mode = __netconfig_wifi_bgscan_get_mode();
269
270         if (scan_mode == WIFI_BGSCAN_MODE_PERIODIC)
271                 vconf_set_int(VCONFKEY_WIFI_BGSCAN_MODE, VCONFKEY_WIFI_BGSCAN_MODE_PERIODIC);
272         else
273                 vconf_set_int(VCONFKEY_WIFI_BGSCAN_MODE, VCONFKEY_WIFI_BGSCAN_MODE_EXPONENTIAL);
274
275         if (vconf_notify_key_changed(VCONFKEY_WIFI_BGSCAN_MODE,
276                         __netconfig_wifi_bgscan_mode_cb, NULL))
277                 DBG("Failed to set notify callback");
278 }
279
280 void netconfig_wifi_deinit_bgscan()
281 {
282         if (vconf_ignore_key_changed(VCONFKEY_WIFI_BGSCAN_MODE,
283                         __netconfig_wifi_bgscan_mode_cb))
284                 DBG("Failed to unset notify callback");
285 }
286