cb138f206960c3ed37ce2f92960b52d16b374db7
[platform/core/connectivity/net-config.git] / src / wifi-indicator.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 <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/ioctl.h>
25 #include <netinet/in.h>
26 #include <netinet/ip.h>
27 #include <linux/wireless.h>
28 #include <vconf.h>
29 #include <vconf-keys.h>
30
31 #include "log.h"
32 #include "util.h"
33 #include "netdbus.h"
34 #include "wifi-state.h"
35 #include "network-state.h"
36 #include "network-statistics.h"
37 #include "netsupplicant.h"
38 #include "wifi-indicator.h"
39
40 #define VCONFKEY_WIFI_SNR_MIN   -89
41
42 #if !defined TIZEN_WEARABLE
43 #define WIFI_INDICATOR_INTERVAL 1
44 #else
45 #define WIFI_INDICATOR_INTERVAL 10
46 #endif
47
48 #if defined TIZEN_WEARABLE
49 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1     (19200 * 1024)
50 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2     (2560 * 1024)
51 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3     (1536 * 1024)
52 #else
53 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1     (19200 * 1024)
54 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2     (7680 * 1024)
55 #define NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3     (3840 * 1024)
56 #endif
57 #define NETCONFIG_PROCWIRELESS                                  "/proc/net/wireless"
58
59 static int netconfig_wifi_rssi = VCONFKEY_WIFI_SNR_MIN;
60 static guint netconfig_wifi_indicator_timer = 0;
61
62 int netconfig_wifi_get_rssi(void)
63 {
64         return netconfig_wifi_rssi;
65 }
66
67 static int __netconfig_wifi_update_and_get_rssi(void)
68 {
69         const char *if_path = NULL;
70         GVariant *message = NULL;
71         GVariant *value = NULL;
72         gchar *key;
73         GVariantIter *iter;
74         GVariant *variant;
75         gint32 key_value;
76         int rssi_dbm = VCONFKEY_WIFI_SNR_MIN;
77
78         if_path = netconfig_wifi_get_supplicant_interface();
79         if (if_path == NULL) {
80                 ERR("Fail to get wpa_supplicant DBus path");
81                 return 0;
82         }
83
84         message = netconfig_invoke_dbus_method(SUPPLICANT_SERVICE, if_path,
85                                 SUPPLICANT_INTERFACE ".Interface", "SignalPoll", NULL);
86         if (message == NULL) {
87                 ERR("Fail to get SignalPoll from wpa_supplicant");
88                 return 0;
89         }
90
91         g_variant_get(message, "(v)", &value);
92
93         g_variant_get(value, "a{sv}", &iter);
94         while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
95                 key_value = g_variant_get_int32(variant);
96
97                 if (g_strcmp0(key, "rssi") == 0) {
98                         rssi_dbm = (int)key_value;
99                         DBG("Currently signal dbm value [%d]", rssi_dbm);
100                         g_variant_unref(variant);
101                         g_free(key);
102                         break;
103                 }
104         }
105
106         g_variant_iter_free(iter);
107
108         if (value)
109                 g_variant_unref(value);
110
111         netconfig_wifi_rssi = rssi_dbm;
112
113         return rssi_dbm;
114 }
115
116 int netconfig_wifi_rssi_level(const int rssi_dbm)
117 {
118         int snr_level = 0;
119
120         /* Wi-Fi Signal Strength Display
121          *
122          * Excellent :  -63 ~
123          * Good:                -74 ~ -64
124          * Weak:                -82 ~ -75
125          * Very weak:           ~ -83
126          */
127         if (rssi_dbm >= -63)
128                 snr_level = 4;
129         else if (rssi_dbm >= -74)
130                 snr_level = 3;
131         else if (rssi_dbm >= -82)
132                 snr_level = 2;
133         else
134                 snr_level = 1;
135
136         return snr_level;
137 }
138
139 static void __netconfig_wifi_set_rssi_level(const int snr_level)
140 {
141         static int last_snr_level = 0;
142
143         if (snr_level != last_snr_level) {
144                 netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, snr_level);
145                 last_snr_level = snr_level;
146         }
147 }
148
149 static void __netconfig_wifi_data_activity_booster(int level)
150 {
151         gboolean reply = FALSE;
152         GVariant *params = NULL;
153         int level1 = 1;
154         int level2 = 2;
155         int level3 = 3;
156
157         int lock = 2000;
158         int unlock = 0;
159
160         static int old_level = 0;
161
162         if (level < 0)
163                 return;
164
165         if (level > 0) {
166                 /* enable booster */
167                 switch (level) {
168                 case 1:
169                         params = g_variant_new("(ii)", level1, lock);
170                         break;
171                 case 2:
172                         params = g_variant_new("(ii)", level2, lock);
173                         break;
174                 case 3:
175                         params = g_variant_new("(ii)", level3, lock);
176                         break;
177                 default:
178                         ERR("Invalid level");
179                         return;
180                 }
181
182                 reply = netconfig_invoke_dbus_method_nonblock(
183                                 "org.tizen.system.deviced",
184                                 "/Org/Tizen/System/DeviceD/PmQos",
185                                 "org.tizen.system.deviced.PmQos",
186                                 "WifiThroughput",
187                                 params,
188                                 NULL);
189                 if (reply != TRUE)
190                         return;
191         }
192
193         /* disable previous booster */
194         if (old_level == 0 || old_level == level)
195                 return;
196
197         switch (old_level) {
198         case 1:
199                 params = g_variant_new("(ii)", level1, unlock);
200                 break;
201         case 2:
202                 params = g_variant_new("(ii)", level2, unlock);
203                 break;
204         case 3:
205                 params = g_variant_new("(ii)", level3, unlock);
206                 break;
207         default:
208                 ERR("Invalid level");
209                 return;
210         }
211
212         reply = netconfig_invoke_dbus_method_nonblock(
213                         "org.tizen.system.deviced",
214                         "/Org/Tizen/System/DeviceD/PmQos",
215                         "org.tizen.system.deviced.PmQos",
216                         "WifiThroughput",
217                         params,
218                         NULL);
219         if (reply != TRUE)
220                 return;
221
222         old_level = level;
223 }
224
225 static void __netconfig_wifi_update_indicator(void)
226 {
227         static int last_transfer_state = 0;
228         static guint64 netconfig_wifi_tx_bytes = 0;
229         static guint64 netconfig_wifi_rx_bytes = 0;
230         static int booster_tic = 0;
231         static int old_level = 0;
232         int booster_level = 0;
233         guint64 tx, rx, tx_diff, rx_diff;
234         int transfer_state;
235
236         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE) {
237                 tx_diff = tx - netconfig_wifi_tx_bytes;
238                 rx_diff = rx - netconfig_wifi_rx_bytes;
239
240                 if (tx_diff > 0) {
241                         if (rx_diff > 0)
242                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TXRX;
243                         else
244                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TX;
245                 } else {
246                         if (rx_diff > 0)
247                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_RX;
248                         else
249                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_NONE;
250                 }
251
252                 if (transfer_state != last_transfer_state) {
253                         netconfig_set_vconf_int(VCONFKEY_WIFI_TRANSFER_STATE, transfer_state);
254                         last_transfer_state = transfer_state;
255                 }
256
257                 /* NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER */
258                 if (tx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1 ||
259                         rx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1)
260                         booster_level = 1;
261                 else if (tx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2 ||
262                                 rx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2)
263                         booster_level = 2;
264                 else if (tx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3 ||
265                                 rx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3)
266                         booster_level = 3;
267
268                 if (old_level == booster_level) {
269                         if (--booster_tic <= 0) {
270                                 __netconfig_wifi_data_activity_booster(booster_level);
271
272                                 booster_tic = 2;
273                         }
274                 } else {
275                         __netconfig_wifi_data_activity_booster(booster_level);
276
277                         if (booster_level > 0)
278                                 booster_tic = 2;
279                         else
280                                 booster_tic = 0;
281                 }
282
283                 old_level = booster_level;
284
285                 netconfig_wifi_tx_bytes = tx;
286                 netconfig_wifi_rx_bytes = rx;
287         }
288 }
289
290 static gboolean __wifi_indicator_monitor(gpointer data)
291 {
292         int rssi_dbm = 0;
293         int snr_level = 0;
294         int pm_state = VCONFKEY_PM_STATE_NORMAL;
295
296         if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED)
297                 return FALSE;
298
299         /* In case of LCD off, we don't need to update Wi-Fi indicator */
300         netconfig_vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
301         if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
302                 return TRUE;
303
304         rssi_dbm = __netconfig_wifi_update_and_get_rssi();
305         /* INFO("%d dbm", rssi_dbm); */
306         snr_level = netconfig_wifi_rssi_level(rssi_dbm);
307         __netconfig_wifi_set_rssi_level(snr_level);
308
309         __netconfig_wifi_update_indicator();
310
311         return TRUE;
312 }
313
314 void netconfig_wifi_indicator_start(void)
315 {
316         INFO("Start Wi-Fi indicator");
317
318         netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
319         netconfig_start_timer_seconds(WIFI_INDICATOR_INTERVAL, __wifi_indicator_monitor, NULL, &netconfig_wifi_indicator_timer);
320 }
321
322 void netconfig_wifi_indicator_stop(void)
323 {
324         INFO("Stop Wi-Fi indicator");
325
326         netconfig_stop_timer(&netconfig_wifi_indicator_timer);
327
328         netconfig_wifi_rssi = VCONFKEY_WIFI_SNR_MIN;
329 }