Tizen 2.1 base
[platform/core/connectivity/net-config.git] / 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 void netconfig_wifi_bgscan_start(void)
176 {
177         struct bgscan_timer_data *timer_data =
178                         __netconfig_wifi_bgscan_get_bgscan_data();
179
180         if (timer_data == NULL)
181                 return;
182
183         DBG("Wi-Fi background scan start");
184
185         __netconfig_wifi_bgscan_start_timer(timer_data);
186 }
187
188 void netconfig_wifi_bgscan_stop(void)
189 {
190         struct bgscan_timer_data *timer_data =
191                         __netconfig_wifi_bgscan_get_bgscan_data();
192
193         if (timer_data == NULL)
194                 return;
195
196         DBG("Wi-Fi background scan stop");
197
198         timer_data->time = SCAN_EXPONENTIAL_MIN;
199
200         __netconfig_wifi_bgscan_stop_timer(timer_data);
201 }
202
203 gboolean netconfig_wifi_get_bgscan_state(void)
204 {
205         struct bgscan_timer_data *timer_data =
206                         __netconfig_wifi_bgscan_get_bgscan_data();
207
208         return ((timer_data->timer_id > (guint)0) ? TRUE : FALSE);
209 }
210
211 gboolean netconfig_wifi_get_scanning(void)
212 {
213         return netconfig_wifi_scanning;
214 }
215
216 void netconfig_wifi_set_scanning(gboolean scanning)
217 {
218         if (netconfig_wifi_scanning != scanning)
219                 netconfig_wifi_scanning = scanning;
220 }
221
222 gboolean netconfig_iface_wifi_set_bgscan(NetconfigWifi *wifi, guint scan_mode, GError **error)
223 {
224         struct bgscan_timer_data *timer_data = __netconfig_wifi_bgscan_get_bgscan_data();
225
226         __netconfig_wifi_bgscan_set_mode(scan_mode);
227
228         if (timer_data->timer_id != 0)
229                 netconfig_wifi_bgscan_stop();
230
231         netconfig_wifi_bgscan_start();
232
233         return TRUE;
234 }