IMC plugin update
[platform/core/telephony/tel-plugin-imc.git] / src / imc_sat.c
1 /*
2  * tel-plugin-imc
3  *
4  * Copyright (c) 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 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <glib.h>
24
25 #include <tcore.h>
26 #include <server.h>
27 #include <plugin.h>
28 #include <core_object.h>
29 #include <hal.h>
30 #include <queue.h>
31 #include <storage.h>
32 #include <at.h>
33
34 #include <co_sat.h>
35
36 #include "imc_sat.h"
37 #include "imc_common.h"
38
39 #define PROACTV_CMD_LEN 256
40
41 static TelSatResult
42 __imc_sim_convert_cme_error_tel_sat_result(const TcoreAtResponse *at_resp)
43 {
44         TelSatResult result = TEL_SAT_RESULT_FAILURE;
45         const gchar *line;
46         GSList *tokens = NULL;
47
48         dbg("Entry");
49
50         if (!at_resp || !at_resp->lines) {
51                 err("Invalid response data");
52                 return result;
53         }
54
55         line = (const gchar *)at_resp->lines->data;
56         tokens = tcore_at_tok_new(line);
57         if (g_slist_length(tokens) > 0) {
58                 gchar *resp_str;
59                 gint cme_err;
60
61                 resp_str = g_slist_nth_data(tokens, 0);
62                 if (!resp_str) {
63                         err("Invalid CME Error data");
64                         tcore_at_tok_free(tokens);
65                         return result;
66                 }
67
68                 cme_err = atoi(resp_str);
69                 dbg("CME error[%d]", cme_err);
70                 switch (cme_err) {
71                 case 3:
72                 case 4:
73                         result = TEL_SAT_RESULT_OPERATION_NOT_SUPPORTED;
74                 break;
75
76                 case 20:
77                 case 23:
78                         result = TEL_SAT_RESULT_MEMORY_FAILURE;
79                 break;
80
81                 case 50:
82                         result =  TEL_SAT_RESULT_INVALID_PARAMETER;
83                 break;
84
85                 case 100:
86                         result =  TEL_SAT_RESULT_UNKNOWN_FAILURE;
87                 break;
88
89                 default:
90                         result = TEL_SAT_RESULT_FAILURE;
91                 }
92         }
93         tcore_at_tok_free(tokens);
94
95         return result;
96 }
97
98 static void on_response_enable_sat(TcorePending *p,
99         guint data_len, const void *data, void *user_data)
100 {
101         const TcoreAtResponse *at_resp = data;
102
103         if (at_resp && at_resp->success) {
104                 dbg("Enable SAT (Proactive command) - [OK]");
105         }
106         else {
107                 err("Enable SAT (Proactive command) - [NOK]");
108         }
109 }
110
111 /* Hook functions */
112 static TcoreHookReturn on_hook_imc_sim_status(TcorePlugin *plugin,
113         TcoreNotification command, guint data_len, void *data, void *user_data)
114 {
115         const TelSimCardStatus *sim_status = (TelSimCardStatus *)data;
116         CoreObject *co = (CoreObject *)user_data;
117
118         tcore_check_return_value(sim_status != NULL, TCORE_HOOK_RETURN_CONTINUE);
119
120         /*
121          * If SIM is initialized -
122          *      * Enable SAT
123          */
124         dbg("SIM Status: [%d]", *sim_status);
125         if (*sim_status == TEL_SIM_STATUS_SIM_INIT_COMPLETED) {
126                 TelReturn ret;
127                 dbg("SIM Initialized!!! Enable SAT");
128
129                 /* Enable SAT - Send AT+CFUN=6 */
130                 ret = tcore_at_prepare_and_send_request(co,
131                         "AT+CFUN=6", NULL,
132                         TCORE_AT_COMMAND_TYPE_NO_RESULT,
133                         NULL,
134                         on_response_enable_sat, NULL,
135                         on_send_imc_request, NULL);
136                 IMC_CHECK_REQUEST_RET(ret, NULL, "Enable SAT");
137         }
138
139         return TCORE_HOOK_RETURN_CONTINUE;
140 }
141
142 static gboolean on_response_imc_sat_terminal_response_confirm
143         (CoreObject *co, const void *event_info, void *user_data)
144 {
145         dbg("Entry");
146         return TRUE;
147 }
148
149 static gboolean on_notification_imc_sat_proactive_command
150         (CoreObject *co, const void *event_info, void *user_data)
151 {
152         TelSatDecodedProactiveData decoded_data;
153         TelSatNotiProactiveData proactive_noti;
154         gint proactive_cmd_len = 0;
155         GSList *lines = NULL;
156         GSList *tokens = NULL;
157         gchar *line = NULL;
158         gchar *hex_data = NULL;
159         gchar *tmp = NULL;
160         gchar *record_data = NULL;
161         guint record_data_len;
162         gint decode_err;
163         gboolean decode_ret = FALSE;
164
165         dbg("Entry");
166
167         tcore_check_return_value_assert(co != NULL, FALSE);
168         memset(&proactive_noti, 0x00, sizeof(TelSatNotiProactiveData));
169         memset(&decoded_data, 0x00, sizeof(TelSatDecodedProactiveData));
170
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);
177                 return TRUE;
178         }
179
180         hex_data = (gchar *)g_slist_nth_data(tokens, 0);
181         dbg("SAT data: [%s] SAT data length: [%d]", hex_data, strlen(hex_data));
182
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);
186         tcore_free(tmp);
187
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);
191
192         decode_ret = tcore_sat_decode_proactive_command((guchar *) record_data,
193                 record_data_len, &decoded_data, &decode_err);
194         if (!decode_ret) {
195                 err("Proactive Command decoding failed");
196                 tcore_at_tok_free(tokens);
197                 return TRUE;
198         }
199
200         tcore_free(record_data);
201
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;
205
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));
212                 break;
213
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));
219                 break;
220
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));
226                 break;
227
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));
233                 break;
234
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));
240                 break;
241
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));
246                 break;
247
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));
253                 break;
254
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));
260                 break;
261
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));
267                 break;
268
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));
274                 break;
275
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));
281                 break;
282
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));
287                 break;
288
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));
294                 break;
295
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);
302                 break;
303
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));
309                 break;
310
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));
316                 break;
317
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));
323                 break;
324
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));
330                 break;
331
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));
337                 break;
338
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));
344                 break;
345
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));
351                 break;
352
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));
358                 break;
359
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));
365                 break;
366
367         default:
368                 dbg("invalid command:[%d]", decoded_data.cmd_type);
369                 break;
370         }
371
372         if (decoded_data.cmd_type == TEL_SAT_PROATV_CMD_REFRESH) {
373                 /*Not supported*/
374                 dbg("Not suported Proactive command");
375                 tcore_at_tok_free(tokens);
376                 return TRUE;
377         }
378
379         /* Send notification */
380         tcore_object_send_notification(co,
381                 TCORE_NOTIFICATION_SAT_PROACTIVE_CMD,
382                 sizeof(TelSatNotiProactiveData), &proactive_noti);
383
384         tcore_at_tok_free(tokens);
385
386         dbg("Exit");
387         return TRUE;
388 }
389
390 /* SAT Responses */
391 static void on_response_imc_sat_send_envelop_cmd(TcorePending *p,
392         guint data_len, const void *data, void *user_data)
393 {
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;
401         gint sw2 = -1;
402
403         dbg("Entry");
404
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);
408
409         if (at_resp && at_resp->success) {
410                 result = TEL_SAT_RESULT_SUCCESS;
411                 dbg("RESPONSE OK");
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");
417                                 goto OUT;
418                         }
419
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);
425                                 if (sw2 == 0) {
426                                         dbg("Response is processed completely " \
427                                                 "and sending session end notification");
428
429                                         /* Send Session End notification */
430                                         tcore_object_send_notification(co,
431                                                 TCORE_NOTIFICATION_SAT_SESSION_END,
432                                                 0, NULL);
433                                 }
434                         }
435                 }
436         } else {
437                 err("RESPONSE NOK");
438
439                 envelop_resp = TEL_SAT_ENVELOPE_FAILED;
440                 result = __imc_sim_convert_cme_error_tel_sat_result(at_resp);
441         }
442
443 OUT:
444         /* Invoke callback */
445         if (resp_cb_data->cb)
446                 resp_cb_data->cb(co, (gint)result, &envelop_resp, resp_cb_data->cb_data);
447
448         imc_destroy_resp_cb_data(resp_cb_data);
449         tcore_at_tok_free(tokens);
450         dbg("Exit");
451 }
452
453 static void on_response_imc_sat_send_terminal_response(TcorePending *p,
454         guint data_len, const void *data, void *user_data)
455 {
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;
460
461         dbg("Entry");
462
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);
466
467         if (at_resp && at_resp->success) {
468                 result = TEL_SAT_RESULT_SUCCESS;
469                 dbg("RESPONSE OK");
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);
473         } else {
474                 err("RESPONSE NOK");
475                 result = __imc_sim_convert_cme_error_tel_sat_result(at_resp);
476         }
477
478         /* Invoke callback */
479         if (resp_cb_data->cb)
480                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
481
482         imc_destroy_resp_cb_data(resp_cb_data);
483         dbg("Exit");
484 }
485
486 static void on_response_imc_sat_send_user_confirmation(TcorePending *p,
487         guint data_len, const void *data, void *user_data)
488 {
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;
493
494         dbg("Entry");
495
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);
499
500         if (at_resp && at_resp->success) {
501                 dbg("RESPONSE OK");
502                 result = TEL_SAT_RESULT_SUCCESS;
503         } else {
504                 err("RESPONSE NOK");
505                 result = __imc_sim_convert_cme_error_tel_sat_result(at_resp);
506         }
507
508         /* Invoke callback */
509         if (resp_cb_data->cb)
510                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
511
512         imc_destroy_resp_cb_data(resp_cb_data);
513         dbg("Exit");
514 }
515
516 /* SAT Requests */
517 /*
518  * Operation - Send Envelop Command
519  *
520  * Request -
521  * AT-Command: AT+SATE
522  *
523  * Response - SW
524  * Success: (Single line)
525  * <sw1>,<sw2>
526  * OK
527  * Failure:
528  * +CME ERROR: <error>
529  */
530 static TelReturn imc_sat_send_envelope(CoreObject *co,
531         const TelSatRequestEnvelopCmdData *envelop_data,
532         TcoreObjectResponseCallback cb, void *cb_data)
533 {
534         gchar *at_cmd;
535         gint envelope_cmd_len = 0;
536         gchar envelope_cmd[PROACTV_CMD_LEN];
537         gint count = 0;
538         gchar hex_string[PROACTV_CMD_LEN * 2];
539         gchar *buffer = NULL;
540         gboolean encode_ret = FALSE;
541
542         ImcRespCbData *resp_cb_data;
543         TelReturn ret;
544
545         dbg("Entry");
546         memset(&hex_string, 0x00, sizeof(hex_string));
547         buffer = hex_string;
548
549         encode_ret = tcore_sat_encode_envelop_cmd(envelop_data,
550                 (gchar *)envelope_cmd, (gint *)&envelope_cmd_len);
551         if (!encode_ret) {
552                 err("Envelope Command encoding failed");
553                 return TEL_RETURN_FAILURE;
554         }
555
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;
560         }
561
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]);
565                 buffer += 2;
566         }
567         dbg("hex_string: %s", hex_string);
568
569         /* AT-Command */
570         at_cmd = g_strdup_printf("AT+SATE=\"%s\"", hex_string);
571
572         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
573                 (void *)&envelop_data->sub_cmd, sizeof(TelSatEnvelopSubCmd));
574
575         /* Send Request to modem */
576         ret = tcore_at_prepare_and_send_request(co,
577                 at_cmd, NULL,
578                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
579                 NULL,
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");
583
584         /* Free resources */
585         tcore_free(at_cmd);
586         dbg("Exit");
587         return ret;
588 }
589
590 /*
591  * Operation - Send Terminal Response
592  *
593  * Request -
594  * AT-Command: AT+SATR
595  *
596  * Response - OK
597  * Success: (NO Result)
598  * OK
599  * Failure:
600  * +CME ERROR: <error>
601  */
602 static TelReturn imc_sat_send_terminal_response(CoreObject *co,
603         const TelSatRequestTerminalResponseData *terminal_rsp_data,
604         TcoreObjectResponseCallback cb, void *cb_data)
605 {
606         gchar *at_cmd;
607         gint terminal_resp_len = 0;
608         gchar terminal_resp[PROACTV_CMD_LEN];
609         gint i = 0;
610         gchar *hex_string = NULL;
611         gboolean encode_ret = FALSE;
612
613         ImcRespCbData *resp_cb_data;
614         TelReturn ret;
615
616         dbg("Entry");
617
618         encode_ret = tcore_sat_encode_terminal_response(terminal_rsp_data,
619                 (gchar *)terminal_resp, (gint *)&terminal_resp_len);
620         if (!encode_ret) {
621                 err("Envelope Command encoding failed");
622                 return TEL_RETURN_FAILURE;
623         }
624
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;
630         }
631         hex_string = calloc((terminal_resp_len * 2) + 1, 1);
632
633         for (i = 0; i < terminal_resp_len * 2; i += 2) {
634                 gchar value = 0;
635                 value = (terminal_resp[i / 2] & 0xf0) >> 4;
636                 if (value < 0xA)
637                         hex_string[i] = ((terminal_resp[i / 2] & 0xf0) >> 4) + '0';
638                 else
639                         hex_string[i] = ((terminal_resp[i / 2] & 0xf0) >> 4) + 'A' - 10;
640
641                 value = terminal_resp[i / 2] & 0x0f;
642                 if (value < 0xA)
643                         hex_string[i + 1] = (terminal_resp[i / 2] & 0x0f) + '0';
644                 else
645                         hex_string[i + 1] = (terminal_resp[i / 2] & 0x0f) + 'A' - 10;
646         }
647         dbg("hex_string: %s", hex_string);
648
649         /* AT-Command */
650         at_cmd = g_strdup_printf("AT+SATR=\"%s\"", hex_string);
651
652         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
653
654         /* Send Request to modem */
655         ret = tcore_at_prepare_and_send_request(co,
656                 at_cmd, NULL,
657                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
658                 NULL,
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");
662
663         /* Free resources */
664         tcore_free(at_cmd);
665         dbg("Exit");
666         return ret;
667 }
668
669 /*
670  * Operation - Send User Confirmation
671  *
672  * Request -
673  * AT-Command: AT+SATD
674  *
675  * Response - OK
676  * Success: (NO Result)
677  * OK
678  * Failure:
679  * +CME ERROR: <error>
680  */
681 static TelReturn imc_sat_send_user_confirmation(CoreObject *co,
682         const TelSatRequestUserConfirmationData *user_conf_data,
683         TcoreObjectResponseCallback cb, void *cb_data)
684 {
685         gchar *at_cmd;
686         guint usr_conf;
687         ImcRespCbData *resp_cb_data;
688         TelReturn ret;
689
690         dbg("Entry");
691
692         usr_conf = (guint)user_conf_data->user_conf;
693         dbg("User confirmation:[%d]", usr_conf);
694
695         /* AT-Command */
696         at_cmd = g_strdup_printf("AT+SATD=%d", usr_conf);
697
698         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
699
700         /* Send Request to modem */
701         ret = tcore_at_prepare_and_send_request(co,
702                 at_cmd, NULL,
703                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
704                 NULL,
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");
708
709         /* Free resources */
710         tcore_free(at_cmd);
711         dbg("Exit");
712         return ret;
713
714 }
715
716 /* SAT Operations */
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
721 };
722
723 /* SAT Init */
724 gboolean imc_sat_init(TcorePlugin *p, CoreObject *co)
725 {
726         dbg("Entry");
727
728         /* Set operations */
729         tcore_sat_set_ops(co, &imc_sat_ops);
730
731         /* Add Callbacks */
732         /*
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.
736          */
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);
743
744         /* Hooks */
745         tcore_plugin_add_notification_hook(p,
746                 TCORE_NOTIFICATION_SIM_STATUS, on_hook_imc_sim_status, co);
747
748         dbg("Exit");
749         return TRUE;
750 }
751
752 /* SAT Exit */
753 void imc_sat_exit(TcorePlugin *p, CoreObject *co)
754 {
755         dbg("Exit");
756 }