4 * Copyright (c) 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.
30 #include <co_context.h>
32 #define INDICATOR_UPDATE_INTERVAL 1
33 #define INDICATOR_PROCFILE "/proc/net/dev"
34 #define INDICATOR_BUFF_SIZE 4096
35 #define NO_RX_PKT_TIMEOUT 30
38 typedef enum _cellular_state {
40 CELLULAR_NORMAL_CONNECTED = 0x01,
41 CELLULAR_SECURE_CONNECTED = 0x02,
42 CELLULAR_USING = 0x03,
45 typedef enum _indicator_state {
46 INDICATOR_NORMAL = 0x00,
49 INDICATOR_RXTX = 0x03,
52 typedef struct _indicator_device_state {
59 }indicator_device_state;
61 typedef struct _indicator_data {
62 indicator_device_state indicator_info;
66 static gboolean _indicator_update_callback(gpointer user_data);
68 static void _indicator_initialize(indicator_data *data)
71 data->indicator_info.prev_rx = 0;
72 data->indicator_info.prev_tx = 0;
73 data->indicator_info.curr_rx = 0;
74 data->indicator_info.curr_tx = 0;
76 err("user data is NULL");
81 static gboolean _indicator_start_updater(Server *s, TcorePlugin *plugin)
83 TcoreStorage *strg_vconf;
84 indicator_data *data = NULL;
86 dbg("indicator is started");
87 strg_vconf = tcore_server_find_storage(s, "vconf");
89 data = tcore_plugin_ref_user_data(plugin);
91 err("user data is NULL");
95 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_NORMAL_CONNECTED);
96 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_NORMAL);
102 _indicator_initialize(data);
104 data->src = g_timeout_source_new_seconds(INDICATOR_UPDATE_INTERVAL);
105 g_source_set_callback(data->src, _indicator_update_callback, plugin, NULL);
106 g_source_set_priority(data->src, G_PRIORITY_HIGH);
107 g_source_attach(data->src, NULL);
108 g_source_unref(data->src);
113 static gboolean _indicator_stop_updater(Server *s, TcorePlugin *plugin)
115 TcoreStorage *strg_vconf;
116 int t_rx = 0, t_tx = 0;
117 indicator_data *data = NULL;
119 dbg("indicator is stopped");
120 data = tcore_plugin_ref_user_data(plugin);
122 err("user data is NULL");
125 strg_vconf = tcore_server_find_storage(s, "vconf");
127 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_OFF);
128 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_NORMAL);
130 t_rx = tcore_storage_get_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV);
131 t_tx = tcore_storage_get_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT);
132 t_rx += (int)data->indicator_info.curr_rx;
133 t_tx += (int)data->indicator_info.curr_tx;
135 tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV, t_rx);
136 tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT, t_tx);
137 tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_LAST_RCV, (int)data->indicator_info.curr_rx);
138 tcore_storage_set_int(strg_vconf, STORAGE_KEY_CELLULAR_PKT_LAST_SNT, (int)data->indicator_info.curr_tx);
144 g_source_destroy(data->src);
150 static gint _indicator_get_proc_ver(gchar *buff)
152 if (strstr(buff, "compressed")) return 3;
153 if (strstr(buff, "bytes")) return 2;
157 static gint _indicator_get_pkt(gchar *buff, gint proc_ver, guint64 *rx_pkt, guint64 *tx_pkt)
163 memset(s_rx, 0 , 100);
164 memset(s_tx, 0 , 100);
171 result = sscanf(buff,
172 "%s %*s %*s %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s %*s %*s",
176 result = sscanf(buff,
177 "%s %*s %*s %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s %*s %*s",
181 result = sscanf(buff,
182 "%s %*s %*s %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s %*s %*s",
186 dbg("stats unknown version");
190 *rx_pkt = g_ascii_strtoull(s_rx, NULL, 10);
191 *tx_pkt = g_ascii_strtoull(s_tx, NULL, 10);
196 static gboolean _indicator_get_pktcnt(indicator_data *data)
201 gchar buff[INDICATOR_BUFF_SIZE];
204 err("user data is NULL");
208 pf = fopen(INDICATOR_PROCFILE, "r");
210 err("indicator fail to open file(%s), errno(%d)", INDICATOR_PROCFILE, errno);
214 res = fgets(buff, sizeof(buff), pf);
217 res = fgets(buff, sizeof(buff), pf);
220 proc_ver = _indicator_get_proc_ver(buff);
222 while (fgets(buff, sizeof(buff), pf)) {
226 gchar *ifname, *entry;
229 while (*ifname == ' ')
231 entry = strrchr(ifname, ':');
234 result = _indicator_get_pkt(entry, proc_ver, &rx_pkt, &tx_pkt);
236 err("stats fail to get proc field");
241 if ( g_strcmp0(ifname, data->indicator_info.devname) == 0 ){
242 data->indicator_info.prev_rx = data->indicator_info.curr_rx;
243 data->indicator_info.prev_tx = data->indicator_info.curr_tx;
244 data->indicator_info.curr_rx = rx_pkt;
245 data->indicator_info.curr_tx = tx_pkt;
254 static gboolean _indicator_update(Server *s, indicator_data *data)
256 guint64 rx_changes = 0;
257 guint64 tx_changes = 0;
258 TcoreStorage *strg_vconf;
260 strg_vconf = tcore_server_find_storage(s, "vconf");
261 if(!data) return FALSE;
262 if(!data->indicator_info.active) return FALSE;
264 rx_changes = data->indicator_info.curr_rx - data->indicator_info.prev_rx;
265 tx_changes = data->indicator_info.curr_tx - data->indicator_info.prev_tx;
267 if (rx_changes != 0 || tx_changes != 0)
268 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_USING);
270 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_SERVICE_STATE, CELLULAR_NORMAL_CONNECTED);
272 if (rx_changes > 0 && tx_changes > 0)
273 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_RXTX);
274 else if (rx_changes > 0 && tx_changes == 0)
275 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_RX);
276 else if (rx_changes == 0 && tx_changes > 0)
277 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_TX);
279 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, INDICATOR_NORMAL);
284 static gboolean _indicator_update_callback(gpointer user_data)
287 TcorePlugin *indicator_plugin = NULL;
289 indicator_data *data = NULL;
291 indicator_plugin = (TcorePlugin *)user_data;
292 s = tcore_plugin_ref_server(indicator_plugin);
293 data = tcore_plugin_ref_user_data(indicator_plugin);
295 err("user data is NULL");
299 rv = _indicator_get_pktcnt(data);
305 rv = _indicator_update(s, data);
314 static TcoreHookReturn __on_hook_modem_powered(TcorePlugin *source,
315 TcoreNotification command, guint data_len, void *data, void *user_data)
317 TelModemPowerStatus *power_status = NULL;
319 dbg("powered event called");
320 tcore_check_return_value(data != NULL, TCORE_HOOK_RETURN_STOP_PROPAGATION);
322 power_status = (TelModemPowerStatus *)data;
323 if (*power_status == TEL_MODEM_POWER_ERROR) {
325 indicator_data *data = NULL;
326 TcorePlugin *plugin = (TcorePlugin *)user_data;
328 data = tcore_plugin_ref_user_data(plugin);
330 data->indicator_info.active = FALSE;
331 g_free(data->indicator_info.devname);
332 data->indicator_info.devname = NULL;
333 s = tcore_plugin_ref_server(source);
335 _indicator_stop_updater(s, plugin);
338 err("user data is NULL");
342 return TCORE_HOOK_RETURN_CONTINUE;
345 static TcoreHookReturn __on_hook_ps_callstatus(TcorePlugin *source,
346 TcoreNotification command, guint data_len, void *data, void *user_data)
348 unsigned int con_id = 0;
349 CoreObject *co_ps = NULL, *co_context = NULL;
350 TcorePsCallStatusInfo *cstatus = NULL;
351 TcorePlugin *plugin = NULL;
352 indicator_data *indata = NULL;
354 gboolean res = FALSE;
356 dbg("call status event");
357 tcore_check_return_value((data != NULL) || (user_data != NULL), TCORE_HOOK_RETURN_STOP_PROPAGATION);
359 plugin = (TcorePlugin *)user_data;
360 indata = tcore_plugin_ref_user_data(plugin);
361 tcore_check_return_value((indata != NULL) , TCORE_HOOK_RETURN_STOP_PROPAGATION);
363 s = tcore_plugin_ref_server(source);
364 co_ps = tcore_plugin_ref_core_object(source, CORE_OBJECT_TYPE_PS);
365 dbg("ps object(%p)", co_ps);
366 co_context = tcore_ps_ref_context_by_role(co_ps, TCORE_CONTEXT_ROLE_INTERNET);
367 res = tcore_context_get_id(co_context, &con_id);
369 err("get context id failed");
370 return TCORE_HOOK_RETURN_CONTINUE;
372 dbg("context(%p) con_id(%d)", co_context, con_id);
374 cstatus = (TcorePsCallStatusInfo *) data;
376 err("PS status is NULL");
377 return TCORE_HOOK_RETURN_CONTINUE;
379 dbg("call status event cid(%d) state(%d)", cstatus->context_id, cstatus->state);
381 if(con_id != cstatus->context_id)
382 return TCORE_HOOK_RETURN_CONTINUE;
384 if (cstatus->state == TCORE_PS_CALL_STATE_CTX_DEFINED) {
386 dbg("Just noti for PDP define complete, do nothing.");
387 return TCORE_HOOK_RETURN_CONTINUE;
389 else if (cstatus->state == TCORE_PS_CALL_STATE_CONNECTED) {
390 indata->indicator_info.active = TRUE;
391 res = tcore_context_get_ipv4_devname(co_context, &indata->indicator_info.devname);
393 err("get context ipv4 failed");
394 return TCORE_HOOK_RETURN_CONTINUE;
396 _indicator_start_updater(s, plugin);
397 return TCORE_HOOK_RETURN_CONTINUE;
400 indata->indicator_info.active = FALSE;
401 g_free(indata->indicator_info.devname);
402 indata->indicator_info.devname = NULL;
403 _indicator_stop_updater(s, plugin);
404 return TCORE_HOOK_RETURN_CONTINUE;
407 static TcoreHookReturn __on_hook_modem_plugin_added(Server *s,
408 TcoreServerNotification command,
409 guint data_len, void *data, void *user_data)
411 TcorePlugin *modem_plugin;
412 TcorePlugin *indicator_plugin = (TcorePlugin *)user_data;
414 modem_plugin = (TcorePlugin *)data;
415 tcore_check_return_value_assert(NULL != modem_plugin, TCORE_HOOK_RETURN_STOP_PROPAGATION);
417 tcore_plugin_add_notification_hook(modem_plugin, TCORE_NOTIFICATION_MODEM_POWER,
418 __on_hook_modem_powered, indicator_plugin);
419 tcore_plugin_add_notification_hook(modem_plugin, TCORE_NOTIFICATION_PS_CALL_STATUS,
420 __on_hook_ps_callstatus, indicator_plugin);
422 return TCORE_HOOK_RETURN_CONTINUE;
425 static TcoreHookReturn __on_hook_modem_plugin_removed(Server *s,
426 TcoreServerNotification command,
427 guint data_len, void *data, void *user_data)
429 TcorePlugin *modem_plugin;
431 modem_plugin = (TcorePlugin *)data;
432 tcore_check_return_value_assert(NULL != modem_plugin, TCORE_HOOK_RETURN_STOP_PROPAGATION);
434 tcore_plugin_remove_notification_hook(modem_plugin, TCORE_NOTIFICATION_MODEM_POWER,
435 __on_hook_modem_powered);
436 tcore_plugin_remove_notification_hook(modem_plugin, TCORE_NOTIFICATION_PS_CALL_STATUS,
437 __on_hook_ps_callstatus);
439 return TCORE_HOOK_RETURN_CONTINUE;
442 static gboolean on_load()
444 dbg("Indicator plugin load!");
448 static gboolean on_init(TcorePlugin *p)
452 indicator_data *data = NULL;
453 TelReturn ret = TEL_RETURN_FAILURE;
455 data = tcore_malloc0(sizeof(indicator_data));
457 err("Failed to allocate memory");
460 ret = tcore_plugin_link_user_data(p, data);
461 if (ret != TEL_RETURN_SUCCESS) {
462 err("Unable to link user data");
467 s = tcore_plugin_ref_server(p);
468 list = tcore_server_get_modem_plugin_list(s);
469 while (list) { /* Process for pre-loaded Modem Plug-in */
470 TcorePlugin *modem_plugin;
472 modem_plugin = list->data;
473 if ( NULL != modem_plugin) {
474 tcore_plugin_add_notification_hook(modem_plugin, TCORE_NOTIFICATION_MODEM_POWER,
475 __on_hook_modem_powered, p);
476 tcore_plugin_add_notification_hook(modem_plugin, TCORE_NOTIFICATION_PS_CALL_STATUS,
477 __on_hook_ps_callstatus, p);
479 list = g_slist_next(list);
483 /* Register for post-loaded Modem Plug-ins */
484 tcore_server_add_notification_hook(s, TCORE_SERVER_NOTIFICATION_ADDED_MODEM_PLUGIN,
485 __on_hook_modem_plugin_added, p);
486 tcore_server_add_notification_hook(s, TCORE_SERVER_NOTIFICATION_REMOVED_MODEM_PLUGIN,
487 __on_hook_modem_plugin_removed, p);
488 dbg("initialized Indicator plugin!");
492 static void on_unload(TcorePlugin *p)
494 indicator_data *data = NULL;
497 data = tcore_plugin_ref_user_data(p);
499 g_source_destroy(data->src);
507 struct tcore_plugin_define_desc plugin_define_desc =
510 .priority = TCORE_PLUGIN_PRIORITY_MID + 2,