4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: DongHoo Park <donghoo.park@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
33 #include <co_context.h>
35 #define INDICATOR_UPDATE_INTERVAL 1
36 #define INDICATOR_PROCFILE "/proc/net/dev"
37 #define INDICATOR_BUFF_SIZE 4096
38 #define DATABASE_PATH "/opt/dbspace/.dnet.db"
39 #define NO_RX_PKT_TIMEOUT 30
42 typedef enum _cellular_state {
44 CELLULAR_NORMAL_CONNECTED = 0x01,
45 CELLULAR_SECURE_CONNECTED = 0x02,
46 CELLULAR_USING = 0x03,
49 typedef enum _indicator_state {
50 INDICATOR_NORMAL = 0x00,
53 INDICATOR_RXTX = 0x03,
56 struct indicator_device_state {
66 static struct indicator_device_state indicator_info = {
71 static gboolean _indicator_update_callback(gpointer user_data);
73 static void _indicator_initialize(Server *s)
75 indicator_info.prev_rx = 0;
76 indicator_info.prev_tx = 0;
77 indicator_info.curr_rx = 0;
78 indicator_info.curr_tx = 0;
81 static gboolean _indicator_start_updater(Server *s)
84 gpointer vconf_handle;
86 dbg("indicator is started");
88 strg_vconf = tcore_server_find_storage(s, "vconf");
89 vconf_handle = tcore_storage_create_handle(strg_vconf, "vconf");
91 err("fail to create vconf db_handle");
93 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_NORMAL_CONNECTED);
94 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_NORMAL);
99 _indicator_initialize(s);
101 src = g_timeout_source_new_seconds(INDICATOR_UPDATE_INTERVAL);
102 g_source_set_callback(src, _indicator_update_callback, s, NULL);
103 g_source_set_priority(src, G_PRIORITY_HIGH);
104 g_source_attach(src, NULL);
110 static gboolean _indicator_stop_updater(Server *s)
113 gpointer vconf_handle;
114 int t_rx = 0, t_tx = 0;
116 dbg("indicator is stopped");
117 strg_vconf = tcore_server_find_storage(s, "vconf");
118 vconf_handle = tcore_storage_create_handle(strg_vconf, "vconf");
120 err("fail to create vconf db_handle");
122 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_OFF);
123 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_NORMAL);
125 t_rx = tcore_storage_get_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV);
126 t_tx = tcore_storage_get_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT);
127 t_rx += (int)indicator_info.curr_rx;
128 t_tx += (int)indicator_info.curr_tx;
130 tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV, t_rx);
131 tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT, t_tx);
132 tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_LAST_RCV, (int)indicator_info.curr_rx);
133 tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_LAST_SNT, (int)indicator_info.curr_tx);
138 g_source_destroy(src);
144 static gint _indicator_get_proc_ver(gchar *buff)
146 if (strstr(buff, "compressed")) return 3;
147 if (strstr(buff, "bytes")) return 2;
151 static gint _indicator_get_pkt(gchar *buff, gint proc_ver, guint64 *rx_pkt, guint64 *tx_pkt)
157 memset(s_rx, 0 , 100);
158 memset(s_tx, 0 , 100);
165 result = sscanf(buff,
166 "%s %*s %*s %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s %*s %*s",
170 result = sscanf(buff,
171 "%s %*s %*s %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s %*s %*s",
175 result = sscanf(buff,
176 "%s %*s %*s %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s %*s %*s",
180 dbg("stats unknown version");
184 *rx_pkt = g_ascii_strtoull(s_rx, NULL, 10);
185 *tx_pkt = g_ascii_strtoull(s_tx, NULL, 10);
190 static gboolean _indicator_get_pktcnt(gpointer user_data)
195 gchar buff[INDICATOR_BUFF_SIZE];
197 pf = fopen(INDICATOR_PROCFILE, "r");
199 err("indicator fail to open file(%s), errno(%d)", INDICATOR_PROCFILE, errno);
203 res = fgets(buff, sizeof(buff), pf);
206 res = fgets(buff, sizeof(buff), pf);
209 proc_ver = _indicator_get_proc_ver(buff);
211 while (fgets(buff, sizeof(buff), pf)) {
215 gchar *ifname, *entry;
218 while (*ifname == ' ')
220 entry = strrchr(ifname, ':');
223 result = _indicator_get_pkt(entry, proc_ver, &rx_pkt, &tx_pkt);
225 err("stats fail to get proc field");
230 if ( g_strcmp0(ifname, indicator_info.devname) == 0 ){
231 indicator_info.prev_rx = indicator_info.curr_rx;
232 indicator_info.prev_tx = indicator_info.curr_tx;
233 indicator_info.curr_rx = rx_pkt;
234 indicator_info.curr_tx = tx_pkt;
243 static gboolean _indicator_update(Server *s)
245 guint64 rx_changes = 0;
246 guint64 tx_changes = 0;
248 gpointer vconf_handle;
250 strg_vconf = tcore_server_find_storage(s, "vconf");
251 vconf_handle = tcore_storage_create_handle(strg_vconf, "vconf");
253 err("fail to create vconf db_handle");
255 if(!indicator_info.active) return FALSE;
257 rx_changes = indicator_info.curr_rx - indicator_info.prev_rx;
258 tx_changes = indicator_info.curr_tx - indicator_info.prev_tx;
260 if (rx_changes != 0 || tx_changes != 0)
261 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_USING);
263 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_NORMAL_CONNECTED);
265 if (rx_changes > 0 && tx_changes > 0)
266 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_RXTX);
267 else if (rx_changes > 0 && tx_changes == 0)
268 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_RX);
269 else if (rx_changes == 0 && tx_changes > 0)
270 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_TX);
272 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_NORMAL);
277 static gboolean _indicator_update_callback(gpointer user_data)
282 s = (Server *)user_data;
284 rv = _indicator_get_pktcnt(NULL);
290 rv = _indicator_update(s);
299 static enum tcore_hook_return __on_hook_powered(Server *s, CoreObject *source,
300 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
302 struct tnoti_modem_power *modem_power = NULL;
304 dbg("powered event called");
305 g_return_val_if_fail(data != NULL, TCORE_HOOK_RETURN_STOP_PROPAGATION);
307 modem_power = (struct tnoti_modem_power *)data;
308 if ( modem_power->state == MODEM_STATE_ERROR ){
309 indicator_info.active = FALSE;
310 g_free(indicator_info.devname);
311 indicator_info.devname = NULL;
312 _indicator_stop_updater(s);
315 return TCORE_HOOK_RETURN_CONTINUE;
318 static enum tcore_hook_return __on_hook_callstatus(Server *s, CoreObject *source,
319 enum tcore_notification_command command, unsigned int data_len, void *data,
322 unsigned int con_id = 0;
323 CoreObject *co_ps = NULL, *co_context = NULL;
324 struct tnoti_ps_call_status *cstatus = NULL;
326 dbg("call status event");
327 g_return_val_if_fail(data != NULL, TCORE_HOOK_RETURN_STOP_PROPAGATION);
330 dbg("ps object(%p)", co_ps);
331 co_context = tcore_ps_ref_context_by_role(co_ps, CONTEXT_ROLE_INTERNET);
332 con_id = tcore_context_get_id(co_context);
333 dbg("context(%p) con_id(%d)", co_context, con_id);
335 cstatus = (struct tnoti_ps_call_status *) data;
336 dbg("call status event cid(%d) state(%d)", cstatus->context_id, cstatus->state);
338 if(con_id != cstatus->context_id)
339 return TCORE_HOOK_RETURN_CONTINUE;
341 if (cstatus->state == PS_DATA_CALL_CTX_DEFINED) {
343 dbg("Just noti for PDP define complete, do nothing.");
344 return TCORE_HOOK_RETURN_CONTINUE;
346 else if (cstatus->state == PS_DATA_CALL_CONNECTED) {
347 indicator_info.active = TRUE;
348 indicator_info.devname = tcore_context_get_ipv4_devname(co_context);
349 _indicator_start_updater(s);
350 return TCORE_HOOK_RETURN_CONTINUE;
353 indicator_info.active = FALSE;
354 g_free(indicator_info.devname);
355 indicator_info.devname = NULL;
356 _indicator_stop_updater(s);
358 return TCORE_HOOK_RETURN_CONTINUE;
361 static gboolean on_load()
363 dbg("Indicator plugin load!");
367 static gboolean on_init(TcorePlugin *p)
370 s = tcore_plugin_ref_server(p);
371 tcore_server_add_notification_hook(s, TNOTI_MODEM_POWER, __on_hook_powered, NULL);
372 tcore_server_add_notification_hook(s, TNOTI_PS_CALL_STATUS, __on_hook_callstatus, NULL);
373 dbg("initialized Indicator plugin!");
377 static void on_unload(TcorePlugin *p)
383 struct tcore_plugin_define_desc plugin_define_desc =
386 .priority = TCORE_PLUGIN_PRIORITY_MID + 2,