5d7d03ab01f71aa4e3d9fd4867e6c610975d459e
[platform/core/connectivity/net-config.git] / src / wifi-indicator.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 <string.h>
21 #include <unistd.h>
22 #include <sys/ioctl.h>
23 #include <netinet/in.h>
24 #include <netinet/ip.h>
25 #include <linux/wireless.h>
26 #include <vconf.h>
27 #include <vconf-keys.h>
28
29 #include "log.h"
30 #include "util.h"
31 #include "netdbus.h"
32 #include "netsupplicant.h"
33 #include "wifi-indicator.h"
34
35 #define VCONFKEY_WIFI_SNR_MIN   -89
36
37 #define NETCONFIG_WIFI_INDICATOR_INTERVAL       3
38
39 static guint netconfig_wifi_indicator_timer = 0;
40
41 #if defined NL80211
42 static int __netconfig_wifi_get_signal(const char *object_path)
43 {
44         DBusConnection *connection = NULL;
45         DBusMessage *message = NULL;
46         DBusMessageIter iter;
47         int rssi_dbm = 0;
48         int MessageType = 0;
49
50         if (object_path == NULL) {
51                 ERR("Error!!! path is NULL");
52                 goto error;
53         }
54
55         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
56         if (connection == NULL) {
57                 ERR("Error!!! Failed to get system DBus");
58                 goto error;
59         }
60
61         message = netconfig_supplicant_invoke_dbus_method(
62                         SUPPLICANT_SERVICE, connection, object_path,
63                         SUPPLICANT_INTERFACE ".Interface", "GetLinkSignal",
64                         NULL);
65
66         if (message == NULL) {
67                 ERR("Error!!! Failed to get service properties");
68                 goto error;
69         }
70
71         MessageType = dbus_message_get_type(message);
72
73         if (MessageType == DBUS_MESSAGE_TYPE_ERROR) {
74                 const char *err_msg = dbus_message_get_error_name(message);
75                 ERR("Error!!! Error message received [%s]", err_msg);
76                 goto error;
77         }
78
79         dbus_message_iter_init(message, &iter);
80
81         if ((MessageType = dbus_message_iter_get_arg_type(&iter)) == DBUS_TYPE_INT32)
82                 dbus_message_iter_get_basic(&iter, &rssi_dbm);
83         else
84                 goto error;
85
86         dbus_message_unref(message);
87         dbus_connection_unref(connection);
88
89         return rssi_dbm;
90
91 error:
92         if (message != NULL)
93                 dbus_message_unref(message);
94
95         if (connection != NULL)
96                 dbus_connection_unref(connection);
97
98         return VCONFKEY_WIFI_SNR_MIN;
99 }
100
101 static int __netconfig_wifi_get_rssi_from_supplicant(void)
102 {
103         int rssi_dbm =0;
104
105         char object_path[DBUS_PATH_MAX_BUFLEN] = { 0, };
106         char *path_ptr = &object_path[0];
107
108         if (netconfig_wifi_get_supplicant_interface(&path_ptr) != TRUE) {
109                 DBG("Fail to get wpa_supplicant DBus path");
110                 return VCONFKEY_WIFI_SNR_MIN;
111         }
112
113         rssi_dbm = __netconfig_wifi_get_signal((const char *)path_ptr);
114
115         return rssi_dbm;
116 }
117 #endif /* #if defined NL80211 */
118
119 #if !defined NL80211
120 static int __netconfig_wifi_get_rssi_from_system(void)
121 {
122         int rssi_dbm = 0;
123         char ifname[16] = { 0, };
124         char *ifname_ptr = &ifname[0];
125
126         int fd = -1;
127         struct iwreq wifi_req;
128         struct iw_statistics stats;
129         unsigned int iw_stats_len = sizeof(struct iw_statistics);
130
131         if (netconfig_wifi_get_ifname(&ifname_ptr) != TRUE) {
132                 DBG("Fail to get Wi-Fi ifname from wpa_supplicant: %s", ifname_ptr);
133                 return VCONFKEY_WIFI_SNR_MIN;
134         }
135
136         /* Set device name */
137         memset(wifi_req.ifr_name, 0, sizeof(wifi_req.ifr_name));
138         strncpy(wifi_req.ifr_name, ifname, sizeof(wifi_req.ifr_name) - 1);
139         wifi_req.ifr_name[sizeof(wifi_req.ifr_name) - 1] = '\0';
140
141         wifi_req.u.data.pointer = (caddr_t) &stats;
142         wifi_req.u.data.length = iw_stats_len;
143         wifi_req.u.data.flags = 1;      /* Clear updated flag */
144
145         if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
146                 DBG("Fail to open socket to get rssi");
147                 return VCONFKEY_WIFI_SNR_MIN;
148         }
149
150         memset(&stats, 0, iw_stats_len);
151
152         if (ioctl(fd, SIOCGIWSTATS, &wifi_req) < 0) {
153                 DBG("Fail to execute ioctl for SIOCGIWSTATS");
154                 close(fd);
155
156                 return VCONFKEY_WIFI_SNR_MIN;
157         }
158         close(fd);
159
160         rssi_dbm = stats.qual.level - 255; /** signed integer, so 255 */
161
162         return rssi_dbm;
163 }
164 #endif /* #if !defined NL80211 */
165
166 int netconfig_wifi_get_rssi(void)
167 {
168         int rssi_dbm = 0;
169
170         /* There are two ways to get Wi-Fi RSSI:
171          *  - WEXT interface, get DBus path of wpa_supplicant,
172          *  and get Wi-Fi interface name e.g. wlan0 from wpa_supplicant.
173          *  IOCTL with ifname will return RSSI dB.
174          *  - NL80211 interface, get DBus path of wpa_supplicant,
175          *  and get RSSI from wpa_supplicant directly.
176          *  However, in this case wpa_supplicant needs some modification
177          *  to get RSSI from DBus interface. */
178
179 #if defined NL80211
180         rssi_dbm = __netconfig_wifi_get_rssi_from_supplicant();
181 #else
182         rssi_dbm = __netconfig_wifi_get_rssi_from_system();
183 #endif
184
185         return rssi_dbm;
186 }
187
188 static void __netconfig_wifi_set_rssi_level(int rssi_dbm)
189 {
190         int snr_level = 0;
191         static int last_snr_level = 0;
192
193         /* Wi-Fi Signal Strength Display
194          *
195          * Excellent :  -63 ~
196          * Good:                -74 ~ -64
197          * Weak:                -82 ~ -75
198          * Very weak:           ~ -83
199          */
200         if (rssi_dbm >= -63)
201                 snr_level = 4;
202         else if (rssi_dbm >= -74)
203                 snr_level = 3;
204         else if (rssi_dbm >= -82)
205                 snr_level = 2;
206         else
207                 snr_level = 1;
208
209         if (snr_level != last_snr_level) {
210                 INFO("Wi-Fi RSSI: %d dB, %d level", rssi_dbm, snr_level);
211
212                 vconf_set_int(VCONFKEY_WIFI_STRENGTH, snr_level);
213
214                 last_snr_level = snr_level;
215         }
216 }
217
218 static gboolean __netconfig_wifi_indicator_monitor(gpointer data)
219 {
220         int rssi_dbm = 0;
221         int pm_state = VCONFKEY_PM_STATE_NORMAL;
222
223         /* In case of LCD off, we don't need to update Wi-Fi indicator */
224         vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
225         if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
226                 return TRUE;
227
228         rssi_dbm = netconfig_wifi_get_rssi();
229
230         __netconfig_wifi_set_rssi_level(rssi_dbm);
231
232         return TRUE;
233 }
234
235 void netconfig_wifi_indicator_start(void)
236 {
237         INFO("Start Wi-Fi indicator");
238
239         vconf_set_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
240
241         netconfig_start_timer_seconds(
242                         NETCONFIG_WIFI_INDICATOR_INTERVAL,
243                         __netconfig_wifi_indicator_monitor,
244                         NULL,
245                         &netconfig_wifi_indicator_timer);
246 }
247
248 void netconfig_wifi_indicator_stop(void)
249 {
250         INFO("Stop Wi-Fi indicator");
251
252         vconf_set_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
253
254         netconfig_stop_timer(&netconfig_wifi_indicator_timer);
255 }