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.
28 #include <core_object.h>
37 #include "imc_common.h"
39 #define PROACTV_CMD_LEN 256
42 __imc_sim_convert_cme_error_tel_sat_result(const TcoreAtResponse *at_resp)
44 TelSatResult result = TEL_SAT_RESULT_FAILURE;
46 GSList *tokens = NULL;
50 if (!at_resp || !at_resp->lines) {
51 err("Invalid response data");
55 line = (const gchar *)at_resp->lines->data;
56 tokens = tcore_at_tok_new(line);
57 if (g_slist_length(tokens) > 0) {
61 resp_str = g_slist_nth_data(tokens, 0);
63 err("Invalid CME Error data");
64 tcore_at_tok_free(tokens);
68 cme_err = atoi(resp_str);
69 dbg("CME error[%d]", cme_err);
73 result = TEL_SAT_RESULT_OPERATION_NOT_SUPPORTED;
78 result = TEL_SAT_RESULT_MEMORY_FAILURE;
82 result = TEL_SAT_RESULT_INVALID_PARAMETER;
86 result = TEL_SAT_RESULT_UNKNOWN_FAILURE;
90 result = TEL_SAT_RESULT_FAILURE;
93 tcore_at_tok_free(tokens);
98 static void on_response_enable_sat(TcorePending *p,
99 guint data_len, const void *data, void *user_data)
101 const TcoreAtResponse *at_resp = data;
103 if (at_resp && at_resp->success) {
104 dbg("Enable SAT (Proactive command) - [OK]");
107 err("Enable SAT (Proactive command) - [NOK]");
112 static TcoreHookReturn on_hook_imc_sim_status(TcorePlugin *plugin,
113 TcoreNotification command, guint data_len, void *data, void *user_data)
115 const TelSimCardStatus *sim_status = (TelSimCardStatus *)data;
116 CoreObject *co = (CoreObject *)user_data;
118 tcore_check_return_value(sim_status != NULL, TCORE_HOOK_RETURN_CONTINUE);
121 * If SIM is initialized -
124 dbg("SIM Status: [%d]", *sim_status);
125 if (*sim_status == TEL_SIM_STATUS_SIM_INIT_COMPLETED) {
127 dbg("SIM Initialized!!! Enable SAT");
129 /* Enable SAT - Send AT+CFUN=6 */
130 ret = tcore_at_prepare_and_send_request(co,
132 TCORE_AT_COMMAND_TYPE_NO_RESULT,
134 on_response_enable_sat, NULL,
135 on_send_imc_request, NULL);
136 IMC_CHECK_REQUEST_RET(ret, NULL, "Enable SAT");
139 return TCORE_HOOK_RETURN_CONTINUE;
142 static gboolean on_response_imc_sat_terminal_response_confirm
143 (CoreObject *co, const void *event_info, void *user_data)
149 static gboolean on_notification_imc_sat_proactive_command
150 (CoreObject *co, const void *event_info, void *user_data)
152 TelSatDecodedProactiveData decoded_data;
153 TelSatNotiProactiveData proactive_noti;
154 gint proactive_cmd_len = 0;
155 GSList *lines = NULL;
156 GSList *tokens = NULL;
158 gchar *hex_data = NULL;
160 gchar *record_data = NULL;
161 guint record_data_len;
163 gboolean decode_ret = FALSE;
167 tcore_check_return_value_assert(co != NULL, FALSE);
168 memset(&proactive_noti, 0x00, sizeof(TelSatNotiProactiveData));
169 memset(&decoded_data, 0x00, sizeof(TelSatDecodedProactiveData));
171 lines = (GSList *) event_info;
172 line = (gchar *) lines->data;
173 tokens = tcore_at_tok_new(line);
174 if (g_slist_length(tokens) != 1) {
175 err("Invalid message");
176 tcore_at_tok_free(tokens);
180 hex_data = (gchar *)g_slist_nth_data(tokens, 0);
181 dbg("SAT data: [%s] SAT data length: [%d]", hex_data, strlen(hex_data));
183 tmp = (gchar *)tcore_at_tok_extract((gchar *)hex_data);
184 tcore_util_hexstring_to_bytes(tmp, &record_data, &record_data_len);
185 dbg("record_data: %x", record_data);
188 tcore_util_hex_dump(" ", strlen(hex_data) / 2, record_data);
189 proactive_cmd_len = strlen(record_data);
190 dbg("proactive_cmd_len = %d", proactive_cmd_len);
192 decode_ret = tcore_sat_decode_proactive_command((guchar *) record_data,
193 record_data_len, &decoded_data, &decode_err);
195 err("Proactive Command decoding failed");
196 tcore_at_tok_free(tokens);
200 tcore_free(record_data);
202 proactive_noti.cmd_number = decoded_data.cmd_num;
203 proactive_noti.cmd_type = decoded_data.cmd_type;
204 proactive_noti.decode_err_code = decode_err;
206 switch (decoded_data.cmd_type) {
207 case TEL_SAT_PROATV_CMD_DISPLAY_TEXT:
208 dbg("decoded command is display text!!");
209 memcpy(&proactive_noti.proactive_ind_data.display_text,
210 &decoded_data.data.display_text,
211 sizeof(TelSatDisplayTextTlv));
214 case TEL_SAT_PROATV_CMD_GET_INKEY:
215 dbg("decoded command is get inkey!!");
216 memcpy(&proactive_noti.proactive_ind_data.get_inkey,
217 &decoded_data.data.get_inkey,
218 sizeof(TelSatGetInkeyTlv));
221 case TEL_SAT_PROATV_CMD_GET_INPUT:
222 dbg("decoded command is get input!!");
223 memcpy(&proactive_noti.proactive_ind_data.get_input,
224 &decoded_data.data.get_input,
225 sizeof(TelSatGetInputTlv));
228 case TEL_SAT_PROATV_CMD_MORE_TIME:
229 dbg("decoded command is more time!!");
230 memcpy(&proactive_noti.proactive_ind_data.more_time,
231 &decoded_data.data.more_time,
232 sizeof(TelSatMoreTimeTlv));
235 case TEL_SAT_PROATV_CMD_PLAY_TONE:
236 dbg("decoded command is play tone!!");
237 memcpy(&proactive_noti.proactive_ind_data.play_tone,
238 &decoded_data.data.play_tone,
239 sizeof(TelSatPlayToneTlv));
242 case TEL_SAT_PROATV_CMD_SETUP_MENU:
243 dbg("decoded command is SETUP MENU!!");
244 memcpy(&proactive_noti.proactive_ind_data.setup_menu,
245 &decoded_data.data.setup_menu, sizeof(TelSatSetupMenuTlv));
248 case TEL_SAT_PROATV_CMD_SELECT_ITEM:
249 dbg("decoded command is select item!!");
250 memcpy(&proactive_noti.proactive_ind_data.select_item,
251 &decoded_data.data.select_item,
252 sizeof(TelSatSelectItemTlv));
255 case TEL_SAT_PROATV_CMD_SEND_SMS:
256 dbg("decoded command is send sms!!");
257 memcpy(&proactive_noti.proactive_ind_data.send_sms,
258 &decoded_data.data.send_sms,
259 sizeof(TelSatSendSmsTlv));
262 case TEL_SAT_PROATV_CMD_SEND_SS:
263 dbg("decoded command is send ss!!");
264 memcpy(&proactive_noti.proactive_ind_data.send_ss,
265 &decoded_data.data.send_ss,
266 sizeof(TelSatSendSsTlv));
269 case TEL_SAT_PROATV_CMD_SEND_USSD:
270 dbg("decoded command is send ussd!!");
271 memcpy(&proactive_noti.proactive_ind_data.send_ussd,
272 &decoded_data.data.send_ussd,
273 sizeof(TelSatSendUssdTlv));
276 case TEL_SAT_PROATV_CMD_SETUP_CALL:
277 dbg("decoded command is setup call!!");
278 memcpy(&proactive_noti.proactive_ind_data.setup_call,
279 &decoded_data.data.setup_call,
280 sizeof(TelSatSetupCallTlv));
283 case TEL_SAT_PROATV_CMD_REFRESH:
284 dbg("decoded command is refresh");
285 memcpy(&proactive_noti.proactive_ind_data.refresh,
286 &decoded_data.data.refresh, sizeof(TelSatRefreshTlv));
289 case TEL_SAT_PROATV_CMD_PROVIDE_LOCAL_INFO:
290 dbg("decoded command is provide local info");
291 memcpy(&proactive_noti.proactive_ind_data.provide_local_info,
292 &decoded_data.data.provide_local_info,
293 sizeof(TelSatProvideLocalInfoTlv));
296 case TEL_SAT_PROATV_CMD_SETUP_EVENT_LIST:
297 dbg("decoded command is setup event list!!");
298 memcpy(&proactive_noti.proactive_ind_data.setup_event_list,
299 &decoded_data.data.setup_event_list,
300 sizeof(TelSatSetupEventListTlv));
301 // setup_event_rsp_get(o, &decoded_data.data.setup_event_list);
304 case TEL_SAT_PROATV_CMD_SETUP_IDLE_MODE_TEXT:
305 dbg("decoded command is setup idle mode text");
306 memcpy(&proactive_noti.proactive_ind_data.setup_idle_mode_text,
307 &decoded_data.data.setup_idle_mode_text,
308 sizeof(TelSatSetupIdleModeTextTlv));
311 case TEL_SAT_PROATV_CMD_SEND_DTMF:
312 dbg("decoded command is send dtmf");
313 memcpy(&proactive_noti.proactive_ind_data.send_dtmf,
314 &decoded_data.data.send_dtmf,
315 sizeof(TelSatSendDtmfTlv));
318 case TEL_SAT_PROATV_CMD_LANGUAGE_NOTIFICATION:
319 dbg("decoded command is language notification");
320 memcpy(&proactive_noti.proactive_ind_data.language_notification,
321 &decoded_data.data.language_notification,
322 sizeof(TelSatLanguageNotificationTlv));
325 case TEL_SAT_PROATV_CMD_LAUNCH_BROWSER:
326 dbg("decoded command is launch browser");
327 memcpy(&proactive_noti.proactive_ind_data.launch_browser,
328 &decoded_data.data.launch_browser,
329 sizeof(TelSatLaunchBrowserTlv));
332 case TEL_SAT_PROATV_CMD_OPEN_CHANNEL:
333 dbg("decoded command is open channel!!");
334 memcpy(&proactive_noti.proactive_ind_data.open_channel,
335 &decoded_data.data.open_channel,
336 sizeof(TelSatOpenChannelTlv));
339 case TEL_SAT_PROATV_CMD_CLOSE_CHANNEL:
340 dbg("decoded command is close channel!!");
341 memcpy(&proactive_noti.proactive_ind_data.close_channel,
342 &decoded_data.data.close_channel,
343 sizeof(TelSatCloseChannelTlv));
346 case TEL_SAT_PROATV_CMD_RECEIVE_DATA:
347 dbg("decoded command is receive data!!");
348 memcpy(&proactive_noti.proactive_ind_data.receive_data,
349 &decoded_data.data.receive_data,
350 sizeof(TelSatReceiveChannelTlv));
353 case TEL_SAT_PROATV_CMD_SEND_DATA:
354 dbg("decoded command is send data!!");
355 memcpy(&proactive_noti.proactive_ind_data.send_data,
356 &decoded_data.data.send_data,
357 sizeof(TelSatSendChannelTlv));
360 case TEL_SAT_PROATV_CMD_GET_CHANNEL_STATUS:
361 dbg("decoded command is get channel status!!");
362 memcpy(&proactive_noti.proactive_ind_data.get_channel_status,
363 &decoded_data.data.get_channel_status,
364 sizeof(TelSatGetChannelStatusTlv));
368 dbg("invalid command:[%d]", decoded_data.cmd_type);
372 if (decoded_data.cmd_type == TEL_SAT_PROATV_CMD_REFRESH) {
374 dbg("Not suported Proactive command");
375 tcore_at_tok_free(tokens);
379 /* Send notification */
380 tcore_object_send_notification(co,
381 TCORE_NOTIFICATION_SAT_PROACTIVE_CMD,
382 sizeof(TelSatNotiProactiveData), &proactive_noti);
384 tcore_at_tok_free(tokens);
391 static void on_response_imc_sat_send_envelop_cmd(TcorePending *p,
392 guint data_len, const void *data, void *user_data)
394 const TcoreAtResponse *at_resp = data;
395 CoreObject *co = tcore_pending_ref_core_object(p);
396 ImcRespCbData *resp_cb_data = user_data;
397 TelSatEnvelopeResp envelop_resp;
398 TelSatResult result = TEL_SAT_RESULT_FAILURE;
399 GSList *tokens = NULL;
400 const gchar *line = NULL;
405 tcore_check_return_assert(co != NULL);
406 tcore_check_return_assert(resp_cb_data != NULL);
407 tcore_check_return_assert(resp_cb_data->cb != NULL);
409 if (at_resp && at_resp->success) {
410 result = TEL_SAT_RESULT_SUCCESS;
412 if (at_resp->lines) {
413 line = (const gchar *) at_resp->lines->data;
414 tokens = tcore_at_tok_new(line);
415 if (g_slist_length(tokens) < 1) {
416 err("invalid message");
420 envelop_resp = TEL_SAT_ENVELOPE_SUCCESS;
421 dbg("RESPONSE tokens present");
422 if (NULL != g_slist_nth_data(tokens, 1)) {
423 sw2 = atoi(g_slist_nth_data(tokens, 1));
424 dbg("status word SW2:[%d]", sw2);
426 dbg("Response is processed completely " \
427 "and sending session end notification");
429 /* Send Session End notification */
430 tcore_object_send_notification(co,
431 TCORE_NOTIFICATION_SAT_SESSION_END,
439 envelop_resp = TEL_SAT_ENVELOPE_FAILED;
440 result = __imc_sim_convert_cme_error_tel_sat_result(at_resp);
444 /* Invoke callback */
445 if (resp_cb_data->cb)
446 resp_cb_data->cb(co, (gint)result, &envelop_resp, resp_cb_data->cb_data);
448 imc_destroy_resp_cb_data(resp_cb_data);
449 tcore_at_tok_free(tokens);
453 static void on_response_imc_sat_send_terminal_response(TcorePending *p,
454 guint data_len, const void *data, void *user_data)
456 const TcoreAtResponse *at_resp = data;
457 CoreObject *co = tcore_pending_ref_core_object(p);
458 ImcRespCbData *resp_cb_data = user_data;
459 TelSatResult result = TEL_SAT_RESULT_FAILURE;
463 tcore_check_return_assert(co != NULL);
464 tcore_check_return_assert(resp_cb_data != NULL);
465 tcore_check_return_assert(resp_cb_data->cb != NULL);
467 if (at_resp && at_resp->success) {
468 result = TEL_SAT_RESULT_SUCCESS;
470 dbg(" at_resp->success = %d", at_resp->success);
471 /* Send Session End notification */
472 tcore_object_send_notification(co, TCORE_NOTIFICATION_SAT_SESSION_END, 0, NULL);
475 result = __imc_sim_convert_cme_error_tel_sat_result(at_resp);
478 /* Invoke callback */
479 if (resp_cb_data->cb)
480 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
482 imc_destroy_resp_cb_data(resp_cb_data);
486 static void on_response_imc_sat_send_user_confirmation(TcorePending *p,
487 guint data_len, const void *data, void *user_data)
489 const TcoreAtResponse *at_resp = data;
490 CoreObject *co = tcore_pending_ref_core_object(p);
491 ImcRespCbData *resp_cb_data = user_data;
492 TelSatResult result = TEL_SAT_RESULT_FAILURE;
496 tcore_check_return_assert(co != NULL);
497 tcore_check_return_assert(resp_cb_data != NULL);
498 tcore_check_return_assert(resp_cb_data->cb != NULL);
500 if (at_resp && at_resp->success) {
502 result = TEL_SAT_RESULT_SUCCESS;
505 result = __imc_sim_convert_cme_error_tel_sat_result(at_resp);
508 /* Invoke callback */
509 if (resp_cb_data->cb)
510 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
512 imc_destroy_resp_cb_data(resp_cb_data);
518 * Operation - Send Envelop Command
521 * AT-Command: AT+SATE
524 * Success: (Single line)
528 * +CME ERROR: <error>
530 static TelReturn imc_sat_send_envelope(CoreObject *co,
531 const TelSatRequestEnvelopCmdData *envelop_data,
532 TcoreObjectResponseCallback cb, void *cb_data)
535 gint envelope_cmd_len = 0;
536 gchar envelope_cmd[PROACTV_CMD_LEN];
538 gchar hex_string[PROACTV_CMD_LEN * 2];
539 gchar *buffer = NULL;
540 gboolean encode_ret = FALSE;
542 ImcRespCbData *resp_cb_data;
546 memset(&hex_string, 0x00, sizeof(hex_string));
549 encode_ret = tcore_sat_encode_envelop_cmd(envelop_data,
550 (gchar *)envelope_cmd, (gint *)&envelope_cmd_len);
552 err("Envelope Command encoding failed");
553 return TEL_RETURN_FAILURE;
556 dbg("envelope_cmd_len after encoding :[%d]", envelope_cmd_len);
557 if (envelope_cmd_len == 0) {
558 err("Envelope command length after encoding is NULL");
559 return TEL_RETURN_INVALID_PARAMETER;
562 for (count = 0; count < envelope_cmd_len; count++) {
563 dbg("envelope_cmd: %02x", (guchar)envelope_cmd[count]);
564 sprintf(buffer, "%02x", (guchar)envelope_cmd[count]);
567 dbg("hex_string: %s", hex_string);
570 at_cmd = g_strdup_printf("AT+SATE=\"%s\"", hex_string);
572 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
573 (void *)&envelop_data->sub_cmd, sizeof(TelSatEnvelopSubCmd));
575 /* Send Request to modem */
576 ret = tcore_at_prepare_and_send_request(co,
578 TCORE_AT_COMMAND_TYPE_SINGLELINE,
580 on_response_imc_sat_send_envelop_cmd, resp_cb_data,
581 on_send_imc_request, NULL);
582 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Send Envelop Command");
591 * Operation - Send Terminal Response
594 * AT-Command: AT+SATR
597 * Success: (NO Result)
600 * +CME ERROR: <error>
602 static TelReturn imc_sat_send_terminal_response(CoreObject *co,
603 const TelSatRequestTerminalResponseData *terminal_rsp_data,
604 TcoreObjectResponseCallback cb, void *cb_data)
607 gint terminal_resp_len = 0;
608 gchar terminal_resp[PROACTV_CMD_LEN];
610 gchar *hex_string = NULL;
611 gboolean encode_ret = FALSE;
613 ImcRespCbData *resp_cb_data;
618 encode_ret = tcore_sat_encode_terminal_response(terminal_rsp_data,
619 (gchar *)terminal_resp, (gint *)&terminal_resp_len);
621 err("Envelope Command encoding failed");
622 return TEL_RETURN_FAILURE;
625 dbg("terminal_resp after encoding: %s", terminal_resp);
626 dbg("terminal_resp length after encoding:[%d]", strlen(terminal_resp));
627 if (terminal_resp_len == 0) {
628 err("Terminal Response length after encoding is NULL");
629 return TEL_RETURN_INVALID_PARAMETER;
631 hex_string = calloc((terminal_resp_len * 2) + 1, 1);
633 for (i = 0; i < terminal_resp_len * 2; i += 2) {
635 value = (terminal_resp[i / 2] & 0xf0) >> 4;
637 hex_string[i] = ((terminal_resp[i / 2] & 0xf0) >> 4) + '0';
639 hex_string[i] = ((terminal_resp[i / 2] & 0xf0) >> 4) + 'A' - 10;
641 value = terminal_resp[i / 2] & 0x0f;
643 hex_string[i + 1] = (terminal_resp[i / 2] & 0x0f) + '0';
645 hex_string[i + 1] = (terminal_resp[i / 2] & 0x0f) + 'A' - 10;
647 dbg("hex_string: %s", hex_string);
650 at_cmd = g_strdup_printf("AT+SATR=\"%s\"", hex_string);
652 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
654 /* Send Request to modem */
655 ret = tcore_at_prepare_and_send_request(co,
657 TCORE_AT_COMMAND_TYPE_NO_RESULT,
659 on_response_imc_sat_send_terminal_response, resp_cb_data,
660 on_send_imc_request, NULL);
661 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Send Terminal Response");
670 * Operation - Send User Confirmation
673 * AT-Command: AT+SATD
676 * Success: (NO Result)
679 * +CME ERROR: <error>
681 static TelReturn imc_sat_send_user_confirmation(CoreObject *co,
682 const TelSatRequestUserConfirmationData *user_conf_data,
683 TcoreObjectResponseCallback cb, void *cb_data)
687 ImcRespCbData *resp_cb_data;
692 usr_conf = (guint)user_conf_data->user_conf;
693 dbg("User confirmation:[%d]", usr_conf);
696 at_cmd = g_strdup_printf("AT+SATD=%d", usr_conf);
698 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
700 /* Send Request to modem */
701 ret = tcore_at_prepare_and_send_request(co,
703 TCORE_AT_COMMAND_TYPE_NO_RESULT,
705 on_response_imc_sat_send_user_confirmation, resp_cb_data,
706 on_send_imc_request, NULL);
707 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Send User Confirmation");
717 static TcoreSatOps imc_sat_ops = {
718 .send_envelope = imc_sat_send_envelope,
719 .send_terminal_response = imc_sat_send_terminal_response,
720 .send_user_confirmation = imc_sat_send_user_confirmation
724 gboolean imc_sat_init(TcorePlugin *p, CoreObject *co)
729 tcore_sat_set_ops(co, &imc_sat_ops);
733 * At present keeping the same notification processing for
734 * both SATI and SATN command. But in future notification processing
735 * will be seperated for both command depending on SAT re-architecure.
737 tcore_object_add_callback(co, "+SATI",
738 on_notification_imc_sat_proactive_command, NULL);
739 tcore_object_add_callback(co, "+SATN",
740 on_notification_imc_sat_proactive_command, NULL);
741 tcore_object_add_callback(co, "+SATF",
742 on_response_imc_sat_terminal_response_confirm, NULL);
745 tcore_plugin_add_notification_hook(p,
746 TCORE_NOTIFICATION_SIM_STATUS, on_hook_imc_sim_status, co);
753 void imc_sat_exit(TcorePlugin *p, CoreObject *co)