2 * Network Configuration Module
4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <sys/ioctl.h>
24 #include <netinet/in.h>
25 #include <netinet/ip.h>
26 #include <linux/wireless.h>
28 #include <vconf-keys.h>
33 #include "network-statistics.h"
34 #include "netsupplicant.h"
35 #include "wifi-indicator.h"
37 #define VCONFKEY_WIFI_SNR_MIN -89
39 #define NETCONFIG_WIFI_INDICATOR_INTERVAL 1
41 static guint64 netconfig_wifi_tx_bytes = 0;
42 static guint64 netconfig_wifi_rx_bytes = 0;
44 static guint netconfig_wifi_indicator_timer = 0;
47 static int __netconfig_wifi_get_signal(const char *object_path)
49 DBusConnection *connection = NULL;
50 DBusMessage *message = NULL;
55 if (object_path == NULL) {
56 ERR("Error!!! path is NULL");
60 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
61 if (connection == NULL) {
62 ERR("Error!!! Failed to get system DBus");
66 message = netconfig_supplicant_invoke_dbus_method(
67 SUPPLICANT_SERVICE, connection, object_path,
68 SUPPLICANT_INTERFACE ".Interface", "GetLinkSignal",
71 if (message == NULL) {
72 ERR("Error!!! Failed to get service properties");
76 MessageType = dbus_message_get_type(message);
78 if (MessageType == DBUS_MESSAGE_TYPE_ERROR) {
79 const char *err_msg = dbus_message_get_error_name(message);
80 ERR("Error!!! Error message received [%s]", err_msg);
84 dbus_message_iter_init(message, &iter);
86 if ((MessageType = dbus_message_iter_get_arg_type(&iter)) == DBUS_TYPE_INT32)
87 dbus_message_iter_get_basic(&iter, &rssi_dbm);
91 dbus_message_unref(message);
92 dbus_connection_unref(connection);
98 dbus_message_unref(message);
100 if (connection != NULL)
101 dbus_connection_unref(connection);
103 return VCONFKEY_WIFI_SNR_MIN;
106 static int __netconfig_wifi_get_rssi_from_supplicant(void)
110 char object_path[DBUS_PATH_MAX_BUFLEN] = { 0, };
111 char *path_ptr = &object_path[0];
113 if (netconfig_wifi_get_supplicant_interface(&path_ptr) != TRUE) {
114 DBG("Fail to get wpa_supplicant DBus path");
115 return VCONFKEY_WIFI_SNR_MIN;
118 rssi_dbm = __netconfig_wifi_get_signal((const char *)path_ptr);
122 #endif /* #if defined NL80211 */
125 static int __netconfig_wifi_get_rssi_from_system(void)
128 char ifname[16] = { 0, };
129 char *ifname_ptr = &ifname[0];
132 struct iwreq wifi_req;
133 struct iw_statistics stats;
134 unsigned int iw_stats_len = sizeof(struct iw_statistics);
136 if (netconfig_wifi_get_ifname(&ifname_ptr) != TRUE) {
137 DBG("Fail to get Wi-Fi ifname from wpa_supplicant: %s", ifname_ptr);
138 return VCONFKEY_WIFI_SNR_MIN;
141 /* Set device name */
142 memset(wifi_req.ifr_name, 0, sizeof(wifi_req.ifr_name));
143 strncpy(wifi_req.ifr_name, ifname, sizeof(wifi_req.ifr_name) - 1);
144 wifi_req.ifr_name[sizeof(wifi_req.ifr_name) - 1] = '\0';
146 wifi_req.u.data.pointer = (caddr_t) &stats;
147 wifi_req.u.data.length = iw_stats_len;
148 wifi_req.u.data.flags = 1; /* Clear updated flag */
150 if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
151 DBG("Fail to open socket to get rssi");
152 return VCONFKEY_WIFI_SNR_MIN;
155 memset(&stats, 0, iw_stats_len);
157 if (ioctl(fd, SIOCGIWSTATS, &wifi_req) < 0) {
158 DBG("Fail to execute ioctl for SIOCGIWSTATS");
161 return VCONFKEY_WIFI_SNR_MIN;
165 rssi_dbm = stats.qual.level - 255; /** signed integer, so 255 */
169 #endif /* #if !defined NL80211 */
171 int netconfig_wifi_get_rssi(void)
175 /* There are two ways to get Wi-Fi RSSI:
176 * - WEXT interface, get DBus path of wpa_supplicant,
177 * and get Wi-Fi interface name e.g. wlan0 from wpa_supplicant.
178 * IOCTL with ifname will return RSSI dB.
179 * - NL80211 interface, get DBus path of wpa_supplicant,
180 * and get RSSI from wpa_supplicant directly.
181 * However, in this case wpa_supplicant needs some modification
182 * to get RSSI from DBus interface. */
185 rssi_dbm = __netconfig_wifi_get_rssi_from_supplicant();
187 rssi_dbm = __netconfig_wifi_get_rssi_from_system();
193 static void __netconfig_wifi_set_rssi_level(int rssi_dbm)
196 static int last_snr_level = 0;
198 /* Wi-Fi Signal Strength Display
207 else if (rssi_dbm >= -74)
209 else if (rssi_dbm >= -82)
214 if (snr_level != last_snr_level) {
215 INFO("Wi-Fi RSSI: %d dB, %d level", rssi_dbm, snr_level);
217 vconf_set_int(VCONFKEY_WIFI_STRENGTH, snr_level);
219 last_snr_level = snr_level;
223 static gboolean __netconfig_wifi_indicator_monitor(gpointer data)
226 int pm_state = VCONFKEY_PM_STATE_NORMAL;
227 guint64 tx = 0, rx = 0;
229 /* In case of LCD off, we don't need to update Wi-Fi indicator */
230 vconf_get_int(VCONFKEY_PM_STATE, &pm_state);
231 if (pm_state >= VCONFKEY_PM_STATE_LCDOFF)
234 rssi_dbm = netconfig_wifi_get_rssi();
236 if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE) {
237 if (netconfig_wifi_tx_bytes < tx) {
238 if (netconfig_wifi_rx_bytes < rx)
239 vconf_set_int(VCONFKEY_WIFI_TRANSFER_STATE, VCONFKEY_WIFI_TRANSFER_STATE_TXRX);
241 vconf_set_int(VCONFKEY_WIFI_TRANSFER_STATE, VCONFKEY_WIFI_TRANSFER_STATE_TX);
243 if (netconfig_wifi_rx_bytes < rx)
244 vconf_set_int(VCONFKEY_WIFI_TRANSFER_STATE, VCONFKEY_WIFI_TRANSFER_STATE_RX);
246 vconf_set_int(VCONFKEY_WIFI_TRANSFER_STATE, VCONFKEY_WIFI_TRANSFER_STATE_NONE);
249 netconfig_wifi_tx_bytes = tx;
250 netconfig_wifi_rx_bytes = rx;
253 __netconfig_wifi_set_rssi_level(rssi_dbm);
258 void netconfig_wifi_indicator_start(void)
260 guint64 tx = 0, rx = 0;
262 INFO("Start Wi-Fi indicator");
264 vconf_set_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
266 if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE) {
267 netconfig_wifi_tx_bytes = tx;
268 netconfig_wifi_rx_bytes = rx;
270 netconfig_wifi_tx_bytes = 0;
271 netconfig_wifi_rx_bytes = 0;
274 netconfig_start_timer_seconds(
275 NETCONFIG_WIFI_INDICATOR_INTERVAL,
276 __netconfig_wifi_indicator_monitor,
278 &netconfig_wifi_indicator_timer);
281 void netconfig_wifi_indicator_stop(void)
283 INFO("Stop Wi-Fi indicator");
285 vconf_set_int(VCONFKEY_WIFI_STRENGTH, VCONFKEY_WIFI_STRENGTH_MAX);
287 netconfig_stop_timer(&netconfig_wifi_indicator_timer);