Modified way of update rssi value
[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         if (iter)
107                 g_variant_iter_free(iter);
108
109         if (value)
110                 g_variant_unref(value);
111
112         netconfig_wifi_rssi = rssi_dbm;
113
114         return rssi_dbm;
115 }
116
117 int netconfig_wifi_rssi_level(const int rssi_dbm)
118 {
119         int snr_level = 0;
120
121         /* Wi-Fi Signal Strength Display
122          *
123          * Excellent :  -63 ~
124          * Good:                -74 ~ -64
125          * Weak:                -82 ~ -75
126          * Very weak:           ~ -83
127          */
128         if (rssi_dbm >= -63)
129                 snr_level = 4;
130         else if (rssi_dbm >= -74)
131                 snr_level = 3;
132         else if (rssi_dbm >= -82)
133                 snr_level = 2;
134         else
135                 snr_level = 1;
136
137         return snr_level;
138 }
139
140 static void __netconfig_wifi_set_rssi_level(const int snr_level)
141 {
142         static int last_snr_level = 0;
143
144         if (snr_level != last_snr_level) {
145                 netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, snr_level);
146                 last_snr_level = snr_level;
147         }
148 }
149
150 static void __netconfig_wifi_data_activity_booster(int level)
151 {
152         gboolean reply = FALSE;
153         GVariant *params = NULL;
154         int level1 = 1;
155         int level2 = 2;
156         int level3 = 3;
157
158         int lock = 2000;
159         int unlock = 0;
160
161         static int old_level = 0;
162
163         if (level < 0)
164                 return;
165
166         if (level > 0) {
167                 /* enable booster */
168                 switch (level) {
169                 case 1:
170                         params = g_variant_new("(ii)", level1, lock);
171                         break;
172                 case 2:
173                         params = g_variant_new("(ii)", level2, lock);
174                         break;
175                 case 3:
176                         params = g_variant_new("(ii)", level3, lock);
177                         break;
178                 default:
179                         ERR("Invalid level");
180                         return;
181                 }
182
183                 reply = netconfig_invoke_dbus_method_nonblock(
184                                 "org.tizen.system.deviced",
185                                 "/Org/Tizen/System/DeviceD/PmQos",
186                                 "org.tizen.system.deviced.PmQos",
187                                 "WifiThroughput",
188                                 params,
189                                 NULL);
190                 if (reply != TRUE)
191                         return;
192         }
193
194         /* disable previous booster */
195         if (old_level == 0 || old_level == level)
196                 return;
197
198         switch (old_level) {
199         case 1:
200                 params = g_variant_new("(ii)", level1, unlock);
201                 break;
202         case 2:
203                 params = g_variant_new("(ii)", level2, unlock);
204                 break;
205         case 3:
206                 params = g_variant_new("(ii)", level3, unlock);
207                 break;
208         default:
209                 ERR("Invalid level");
210                 return;
211         }
212
213         reply = netconfig_invoke_dbus_method_nonblock(
214                         "org.tizen.system.deviced",
215                         "/Org/Tizen/System/DeviceD/PmQos",
216                         "org.tizen.system.deviced.PmQos",
217                         "WifiThroughput",
218                         params,
219                         NULL);
220         if (reply != TRUE)
221                 return;
222
223         old_level = level;
224 }
225
226 static void __netconfig_wifi_update_indicator(void)
227 {
228         static int last_transfer_state = 0;
229         static guint64 netconfig_wifi_tx_bytes = 0;
230         static guint64 netconfig_wifi_rx_bytes = 0;
231         static int booster_tic = 0;
232         static int old_level = 0;
233         int booster_level = 0;
234         guint64 tx, rx, tx_diff, rx_diff;
235         int transfer_state;
236
237         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE) {
238                 tx_diff = tx - netconfig_wifi_tx_bytes;
239                 rx_diff = rx - netconfig_wifi_rx_bytes;
240
241                 if (tx_diff > 0) {
242                         if (rx_diff > 0)
243                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TXRX;
244                         else
245                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_TX;
246                 } else {
247                         if (rx_diff > 0)
248                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_RX;
249                         else
250                                 transfer_state = VCONFKEY_WIFI_TRANSFER_STATE_NONE;
251                 }
252
253                 if (transfer_state != last_transfer_state) {
254                         netconfig_set_vconf_int(VCONFKEY_WIFI_TRANSFER_STATE, transfer_state);
255                         last_transfer_state = transfer_state;
256                 }
257
258                 /* NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER */
259                 if (tx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1 ||
260                         rx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL1)
261                         booster_level = 1;
262                 else if (tx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2 ||
263                                 rx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL2)
264                         booster_level = 2;
265                 else if (tx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3 ||
266                                 rx_diff >= NETCONFIG_WIFI_DATA_ACTIVITY_BOOSTER_LEVEL3)
267                         booster_level = 3;
268
269                 if (old_level == booster_level) {
270                         if (--booster_tic <= 0) {
271                                 __netconfig_wifi_data_activity_booster(booster_level);
272
273                                 booster_tic = 2;
274                         }
275                 } else {
276                         __netconfig_wifi_data_activity_booster(booster_level);
277
278                         if (booster_level > 0)
279                                 booster_tic = 2;
280                         else
281                                 booster_tic = 0;
282                 }
283
284                 old_level = booster_level;
285
286                 netconfig_wifi_tx_bytes = tx;
287                 netconfig_wifi_rx_bytes = rx;
288         }
289 }
290
291 static gboolean __wifi_indicator_monitor(gpointer data)
292 {
293         int rssi_dbm = 0;
294         int snr_level = 0;
295         int pm_state = VCONFKEY_PM_STATE_NORMAL;
296
297         if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED)
298                 return FALSE;
299
300         /* In case of LCD off, we don't need to update Wi-Fi indicator */
301         netconfig_vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
302         if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
303                 return TRUE;
304
305         rssi_dbm = __netconfig_wifi_update_and_get_rssi();
306         /* INFO("%d dbm", rssi_dbm); */
307         snr_level = netconfig_wifi_rssi_level(rssi_dbm);
308         __netconfig_wifi_set_rssi_level(snr_level);
309
310         __netconfig_wifi_update_indicator();
311
312         return TRUE;
313 }
314
315 void netconfig_wifi_indicator_start(void)
316 {
317         INFO("Start Wi-Fi indicator");
318
319         netconfig_set_vconf_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
320         netconfig_start_timer_seconds(WIFI_INDICATOR_INTERVAL, __wifi_indicator_monitor, NULL, &netconfig_wifi_indicator_timer);
321 }
322
323 void netconfig_wifi_indicator_stop(void)
324 {
325         INFO("Stop Wi-Fi indicator");
326
327         netconfig_stop_timer(&netconfig_wifi_indicator_timer);
328
329         netconfig_wifi_rssi = VCONFKEY_WIFI_SNR_MIN;
330 }