1721f6112795ec0fb3fbd31a9b6ce516e9f7211a
[platform/core/telephony/tel-plugin-imc.git] / src / imc_sms.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_sms.h>
35
36 #include "imc_sms.h"
37 #include "imc_sim.h"
38 #include "imc_common.h"
39
40 #define CR  '\r'
41 #define CTRL_Z   '\x1A'
42
43 #define AT_MT_UNREAD            0       /* Received and Unread */
44 #define AT_MT_READ              1       /* Received and Read */
45 #define AT_MO_UNSENT            2       /* Unsent */
46 #define AT_MO_SENT              3       /* Sent */
47 #define AT_ALL                  4       /* Unknown */
48
49 #define IMC_NUM_PLAN_ID(sca)    (gchar)(sca & 0x0F)
50 #define IMC_TYPE_OF_NUM(sca)    (gchar)((sca & 0x70) >> 4)
51
52 /* SCA 12 bytes long and TDPU is 164 bytes long */
53 #define PDU_LEN_MAX             176
54 #define HEX_PDU_LEN_MAX         ((PDU_LEN_MAX * 2) + 1)
55
56 #define IMC_SIM_TON_INTERNATIONAL       1
57 #define IMC_SIM_TON_NATIONAL            2
58
59 #define IMC_AT_EF_SMS_RECORD_LEN        176
60
61 typedef struct {
62         guint total_param_count;
63         guint record_count;
64         guint record_length;
65         guint index;
66         TelSmsParamsInfo *params;
67 } ImcSmsParamsCbData;
68 /*
69  * Notification - SMS-DELIVER
70  * +CMT = [<alpha>],<length><CR><LF><pdu> (PDU mode enabled)
71  *
72  * where,
73  * <alpha> alpha_id
74  * <length> length of the PDU
75  * <pdu> Incomming SMS PDU
76  *
77  * Notification - SMS-STATUS-REPORT
78  * +CDS: <length><CR><LF><pdu> (PDU mode enabled)
79  *
80  * where,
81  * <length> length of the PDU
82  * <pdu> Incomming SMS PDU
83  *
84  */
85 static gboolean on_notification_imc_sms_incoming_msg(CoreObject *co,
86         const void *event_info, void *user_data)
87 {
88         GSList *tokens = NULL;
89         GSList *lines = NULL;
90         char *line = NULL;
91         int pdu_len = 0, no_of_tokens = 0;
92
93         TelSmsDatapackageInfo incoming_msg = {{0}, };
94         int sca_length = 0;
95         gchar *byte_pdu;
96         guint byte_pdu_len;
97         dbg("Enter");
98
99         lines = (GSList *)event_info;
100         if (2 != g_slist_length(lines)) {
101                 err("Invalid number of lines for +CMT. Must be 2");
102                 return TRUE;
103         }
104
105         line = (char *)g_slist_nth_data(lines, 0); /* Fetch Line 1 */
106         if (!line) {
107                 err("Line 1 is invalid");
108                 return TRUE;
109         }
110         dbg("Line 1: [%s]", line);
111
112         /* Split Line 1 into tokens */
113         tokens = tcore_at_tok_new(line);
114         no_of_tokens = g_slist_length(tokens);
115
116         /*
117          * Incoming SMS: +CMT
118          *              Number of tokens: 2
119          *
120          * Incoming SMS-STATUS-REPORT: +CDS
121          *              Number of tokens: 1
122          */
123         if (2 == no_of_tokens) {
124                 /* Token 0: Alpha ID */
125                 dbg("Alpha ID: [0x%x]", g_slist_nth_data(tokens, 0));
126
127                 /* Token 1: PDU Length */
128                 pdu_len = atoi((char *)g_slist_nth_data(tokens, 1));
129                 dbg("pdu_len: [%d]", pdu_len);
130         } else if (1 == no_of_tokens) {
131                 /* Token 0: PDU Length */
132                 pdu_len = atoi((char *)g_slist_nth_data(tokens, 0));
133                 dbg("pdu_len: [%d]", pdu_len);
134         }
135         tcore_at_tok_free(tokens);
136
137         /* Fetch Line 2 */
138         line = (char *)g_slist_nth_data(lines, 1);
139         if (!line) {
140                 err("Line 2 is invalid");
141                 return TRUE;
142         }
143         dbg("Line 2: [%s]", line);
144
145         /* Convert to Bytes */
146         tcore_util_hexstring_to_bytes(line, &byte_pdu, &byte_pdu_len);
147
148         sca_length = byte_pdu[0];
149         dbg("SCA length = %d", sca_length);
150         if (sca_length) {
151                 gchar *decoded_sca;
152                 guint encoded_sca_len;
153                 /*
154                  * byte_pdu[1] - sca_address_type
155                  *      Excluding sca_address_type and copy SCA
156                  */
157                 encoded_sca_len = sca_length - 1;
158                 decoded_sca =
159                         tcore_util_convert_bcd_to_ascii(&byte_pdu[2], encoded_sca_len, encoded_sca_len*2);
160                 dbg("Decoded SCA: [%s]", decoded_sca);
161                 g_strlcpy(incoming_msg.sca.number, decoded_sca, strlen(decoded_sca)+1);
162                 tcore_free(decoded_sca);
163
164                 /*SCA Conversion for Address type*/
165                 incoming_msg.sca.ton = IMC_TYPE_OF_NUM(byte_pdu[1]);
166                 incoming_msg.sca.npi = IMC_NUM_PLAN_ID(byte_pdu[1]);
167                 dbg("TON: [%d] NPI: [%d] SCA: [%s]",
168                         incoming_msg.sca.ton, incoming_msg.sca.npi,
169                         incoming_msg.sca.number);
170         }
171         else {
172                 dbg("NO SCA Present");
173         }
174
175         /* TPDU */
176         incoming_msg.tpdu_length = pdu_len;
177         memcpy(incoming_msg.tpdu,
178                 &byte_pdu[sca_length+1], incoming_msg.tpdu_length);
179
180         tcore_util_hex_dump("    ",incoming_msg.tpdu_length, &byte_pdu[sca_length+1]);
181
182         /* Send notification */
183         tcore_object_send_notification(co,
184                 TCORE_NOTIFICATION_SMS_INCOM_MSG,
185                 sizeof(TelSmsDatapackageInfo), &incoming_msg);
186
187         g_free(byte_pdu);
188         return TRUE;
189 }
190
191 /*
192  * Notification
193  * +CBM: <length><CR><LF><pdu> (PDU mode enabled);
194  *
195  * where,
196  * <length> length of the PDU
197  * <pdu> Incomming SMS CB PDU
198  *
199  */
200 static gboolean on_notification_imc_sms_cb_incom_msg(CoreObject *co,
201         const void *event_info, void *user_data)
202 {
203         char * line = NULL, *pdu = NULL, *line_token = NULL;
204         GSList *tokens = NULL;
205         unsigned char *byte_pdu = NULL;
206         guint byte_pdu_len = 0;
207         GSList *lines = NULL;
208
209         TelSmsCbMsgInfo cb_noti = { 0, };
210         dbg("Enter");
211
212         lines = (GSList *)event_info;
213
214         line = (char *)(lines->data);/*Fetch Line 1*/
215         if (line != NULL) {
216                 tokens = tcore_at_tok_new(line); /* Split Line 1 into tokens */
217                 line_token = g_slist_nth_data(tokens, 0);
218                 if (line_token) {
219                         cb_noti.length = atoi(line_token);
220                 } else {
221                         dbg("token 0 is NULL");
222                         tcore_at_tok_free(tokens);
223                         return TRUE;
224                 }
225                 pdu = g_slist_nth_data(lines, 1);
226                 if (pdu != NULL) {
227                         cb_noti.cb_type = TEL_SMS_CB_MSG_GSM;
228
229                         dbg("CB Msg LENGTH [%d]", cb_noti.length);
230
231                         if ((cb_noti.length > 0) && (TEL_SMS_CB_DATA_SIZE_MAX >= cb_noti.length)) {
232                                 tcore_util_hexstring_to_bytes(pdu, (gchar **)&byte_pdu, &byte_pdu_len);
233
234                                 memcpy(cb_noti.cb_data, (char*)byte_pdu, cb_noti.length);
235                         } else {
236                                 err("Invalid Message Length");
237                                 tcore_at_tok_free(tokens);
238                                 return TRUE;
239                         }
240                 } else {
241                         err("NULL PDU Recieved ");
242                         tcore_at_tok_free(tokens);
243                         return TRUE;
244                 }
245                 tcore_object_send_notification(co,
246                                 TCORE_NOTIFICATION_SMS_CB_INCOM_MSG, sizeof(TelSmsCbMsgInfo), &cb_noti);
247                 g_free(byte_pdu);
248         } else {
249                 err("Response NOK");
250         }
251
252         tcore_at_tok_free(tokens);
253         return TRUE;
254 }
255
256 /*
257  * Notification
258  * TODO - AT Command Description Not available
259  *
260  */
261 static gboolean on_notification_imc_sms_memory_status(CoreObject *co,
262         const void *event_info, void *user_data)
263 {
264         gboolean memory_status = TRUE;
265
266         GSList *tokens = NULL;
267         GSList *lines = NULL;
268         char *line = NULL , *line_token = NULL;
269         dbg(" Enter");
270
271         lines = (GSList *)event_info;
272         if (1 != g_slist_length(lines)) {
273                 dbg("Unsolicited msg but multiple line");
274                 return TRUE;
275         }
276
277         line = (char*)(lines->data);
278         if (line) {
279                 tokens = tcore_at_tok_new(line);
280                 line_token = g_slist_nth_data(tokens, 0);
281                 if (line_token) {
282                         /* SIM Full condition */
283                         if (0 == atoi(line_token))
284                                 memory_status = FALSE;
285
286                 /* Send notification */
287                 tcore_object_send_notification(co,
288                                 TCORE_NOTIFICATION_SMS_MEMORY_STATUS,
289                                 sizeof(gboolean), &memory_status);
290                 }
291                 tcore_at_tok_free(tokens);
292         } else {
293                 err("Response NOK");
294         }
295
296         return TRUE;
297 }
298
299 static void on_response_imc_class2_sms_incom_msg(TcorePending *p,
300         guint data_len, const void *data, void *user_data)
301 {
302         const TcoreAtResponse *at_resp = data;
303         CoreObject *co = tcore_pending_ref_core_object(p);
304
305         TelSmsDatapackageInfo incoming_msg = { { 0 }, };
306
307         GSList *tokens=NULL;
308         char *gslist_line = NULL, *line_token = NULL, *byte_pdu = NULL, *hex_pdu = NULL;
309         gint sca_length = 0;
310         guint byte_pdu_len = 0;
311         dbg("Enter");
312
313         if (at_resp && at_resp->success) {
314                 dbg("RESPONSE OK");
315                 if (at_resp->lines) {
316                         /*
317                          * TCORE_AT_PDU:
318                          *      Multi-line output
319                          *
320                          * Fetching First Line
321                          */
322                         gslist_line = (char *)at_resp->lines->data;
323                         dbg("gslist_line: [%s]", gslist_line);
324
325                         /*Tokenize*/
326                         tokens = tcore_at_tok_new(gslist_line);
327                         dbg("Number of tokens: [%d]", g_slist_length(tokens));
328
329                         /* First Token : status
330                          * Second Token: Alpha ID - not needed
331                          */
332                         line_token = g_slist_nth_data(tokens, 2); /* Third Token: PDU Length */
333                         if (line_token != NULL) {
334                                 incoming_msg.tpdu_length = atoi(line_token);
335                                 dbg("Length: [%d]", incoming_msg.tpdu_length);
336                         }
337                         else {
338                                 err("Line Token for PDU Length is NULL");
339                                 return;
340                         }
341
342                         /* Fetching line: Second line is PDU */
343                         hex_pdu = (char *) at_resp->lines->next->data;
344                         dbg("EF-SMS PDU: [%s]", hex_pdu);
345
346                         tcore_at_tok_free(tokens);      /* free the consumed token */
347                         if (NULL != hex_pdu) {
348                                 tcore_util_hexstring_to_bytes(hex_pdu, &byte_pdu, &byte_pdu_len);
349
350                                 sca_length = (int)byte_pdu[0];
351
352                                 dbg("SCA Length [%d], msgLength: [%d]", sca_length, incoming_msg.tpdu_length);
353
354                                 if (ZERO == sca_length) {
355                                         memcpy(incoming_msg.tpdu, &byte_pdu[1], incoming_msg.tpdu_length);
356                                 }
357                                 else {
358                                         char sca_toa;
359
360                                         /*
361                                          * byte_pdu[1] - sca_address_type
362                                          * Excluding sca_address_type and copy SCA
363                                          */
364                                         memcpy(incoming_msg.sca.number, &byte_pdu[2], (sca_length-1));
365
366                                         /*
367                                          * SCA Conversion: Address Type
368                                          * 3GPP TS 23.040 V6.5.0 Section: 9.1.2.5
369                                          */
370                                         sca_toa = byte_pdu[1];
371                                         incoming_msg.sca.npi = IMC_NUM_PLAN_ID(sca_toa);
372                                         incoming_msg.sca.ton = IMC_TYPE_OF_NUM(sca_toa);
373
374                                         memcpy(incoming_msg.tpdu,
375                                                 &byte_pdu[sca_length+1],
376                                                 incoming_msg.tpdu_length);
377                                 }
378                         }
379
380                         tcore_object_send_notification(co,
381                                         TCORE_NOTIFICATION_SMS_INCOM_MSG,
382                                         sizeof(TelSmsDatapackageInfo), &incoming_msg);
383                         tcore_at_tok_free(tokens);
384                         g_free(byte_pdu);
385                 }
386                 else {
387                         err("Invalid Response Received");
388                 }
389         }
390         else {
391                 err("RESPONSE NOK");
392         }
393 }
394
395 /*
396  * Notification
397  * +CMTI: <mem>,<index>
398  *
399  * where,
400  * <mem> memory location
401  * <index> index where msg is stored
402  */
403 static gboolean on_notification_imc_sms_class2_incoming_msg(CoreObject *co, const void *event_info, void *user_data)
404 {
405         gchar *at_cmd;
406         TelReturn ret;
407
408         GSList *tokens = NULL , *lines = NULL;
409         char *line = NULL;
410         gint index, mem_type = 0;
411         dbg("Enter");
412
413         lines = (GSList *)event_info;
414         line = (char *)g_slist_nth_data(lines, 0); /* Fetch Line 1 */
415         if (!line) {
416                 err("Line 1 is invalid");
417                 return TRUE;
418         }
419         dbg("Line 1: [%s]", line);
420
421         tokens = tcore_at_tok_new(line); /* Split Line 1 into tokens */
422         mem_type = atoi(g_slist_nth_data(tokens, 0));/* Type of Memory stored */
423         dbg("mem_type=[%d]", mem_type);
424         index = atoi((char *) g_slist_nth_data(tokens, 1));
425         dbg("index: [%d]", index);
426
427         /*
428          * Operation - read_sms_in_sim
429          *
430          * Request -
431          * AT-Command: At+CMGR=<index>
432          *  where
433          * <index> index of the message to be read.
434          *
435          * Response -
436          * Success: (PDU: Multi-line output)
437          * +CMGR: <stat>,[<alpha>],<length><CR><LF><pdu>
438          *
439          * Failure:
440          *      +CMS ERROR: <error>
441          */
442         /*AT Command*/
443         at_cmd = g_strdup_printf("AT+CMGR=%d", index);
444
445         /* Send Request to modem */
446         ret = tcore_at_prepare_and_send_request(co,
447                 at_cmd, "+CMGR:",
448                 TCORE_AT_COMMAND_TYPE_PDU,
449                 NULL,
450                 on_response_imc_class2_sms_incom_msg, NULL,
451                 on_send_imc_request, NULL);
452         if (ret != TEL_RETURN_SUCCESS) {
453                 err("Failed to Read Class2 Incomming Message");
454         }
455         g_free(at_cmd);
456         return TRUE;
457 }
458
459 static void on_response_imc_sms_send_more_msg(TcorePending *p,
460         guint data_len, const void *data, void *user_data)
461 {
462         const TcoreAtResponse *at_resp = data;
463
464         dbg("Enter");
465
466         if (at_resp && at_resp->success)
467                 dbg("Response OK for AT+CMMS: More msgs to send!!");
468         else
469                 err("Response NOK for AT+CMMS: More msgs to send");
470
471         /* Need not send any response */
472 }
473
474 static void on_response_imc_sms_send_sms(TcorePending *p,
475         guint data_len, const void *data, void *user_data)
476 {
477         const TcoreAtResponse *at_resp = data;
478         CoreObject *co = tcore_pending_ref_core_object(p);
479         ImcRespCbData *resp_cb_data = user_data;
480
481         TelSmsResult result = TEL_SMS_RESULT_FAILURE;/*TODO: CMS error mapping required */
482         dbg("Enter");
483
484         tcore_check_return_assert(co != NULL);
485         tcore_check_return_assert(resp_cb_data != NULL);
486
487         if (at_resp && at_resp->success) {
488                 dbg("Response OK");
489                 if (at_resp->lines) {
490                         const gchar *line;
491                         gchar* line_token;
492                         GSList *tokens = NULL;
493                         gint msg_ref = 0;
494
495                         line = (const gchar *)at_resp->lines->data;
496                         tokens = tcore_at_tok_new(line);
497                         line_token = g_slist_nth_data(tokens, 0);
498                         if (line_token != NULL) {
499                                 /*Response from MODEM for send SMS: +CMGS: <mr>[,<ackpdu>]*/
500                                 /*Message Reference is not used by MSG_SERVER and application.So Filling only result*/
501                                 msg_ref = atoi(line_token);
502
503                                 dbg("Message Reference: [%d]", msg_ref);
504
505                                 result = TEL_SMS_RESULT_SUCCESS;
506                         }
507                         else {
508                                 dbg("No Message Reference received");
509                         }
510                         tcore_at_tok_free(tokens);
511                 }
512         }
513         else {
514                 err("Response NOK");
515         }
516
517         /* Invoke callback */
518         if (resp_cb_data->cb)
519                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
520
521         /* Free callback data */
522         imc_destroy_resp_cb_data(resp_cb_data);
523 }
524
525 static void on_response_imc_sms_write_sms_in_sim(TcorePending *p,
526         guint data_len, const void *data, void *user_data)
527 {
528         const TcoreAtResponse *at_resp = data;
529         CoreObject *co = tcore_pending_ref_core_object(p);
530         ImcRespCbData *resp_cb_data = user_data;
531
532         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
533
534         GSList *tokens = NULL;
535         char *line = NULL, *line_token = NULL;
536         guint index = -1;
537
538         dbg("Enter");
539
540         if (at_resp && at_resp->success) {
541                 dbg("Response OK");
542                 if (at_resp->lines) {
543                 line = (char *)at_resp->lines->data;
544                         tokens = tcore_at_tok_new(line);
545                         line_token = g_slist_nth_data(tokens, 0);
546                         if (line_token) {
547                                 index = (atoi(line_token));
548                                 dbg("SMS written to '%d' index", index);
549                                 result = TEL_SMS_RESULT_SUCCESS;
550                         }
551                         else {
552                                 dbg("No Tokens");
553                                 result = TEL_SMS_RESULT_FAILURE;
554                         }
555                 }
556                 else {
557                         err("Lines NOT present");
558                 }
559         }
560         else {
561                 dbg("Response NOK");
562         }
563
564         /* Invoke callback */
565         if (resp_cb_data->cb)
566                 resp_cb_data->cb(co, (gint)result, &index, resp_cb_data->cb_data);
567
568         /* Free callback data */
569         imc_destroy_resp_cb_data(resp_cb_data);
570 }
571
572 static void on_response_imc_sms_read_sms_in_sim(TcorePending *p,
573         guint data_len, const void *data, void *user_data)
574 {
575         const TcoreAtResponse *at_resp = data;
576         CoreObject *co = tcore_pending_ref_core_object(p);
577         ImcRespCbData *resp_cb_data = user_data;
578         TelSmsSimDataInfo read_resp;
579         GSList *tokens = NULL;
580
581         TelSmsResult result = TEL_SMS_RESULT_FAILURE;/* CMS error mapping required */
582         dbg("Enter");
583
584         memset(&read_resp, 0x0, sizeof(TelSmsSimDataInfo));
585
586         if (at_resp && at_resp->success) {
587                 dbg("RESPONSE OK");
588                 if (at_resp->lines) {
589                         char *gslist_line = NULL,*line_token = NULL,*byte_pdu = NULL,*hex_pdu = NULL;
590                         gint msg_status = 0, pdu_len = 0, alpha_id = 0;
591
592                         /*
593                          * TCORE_AT_PDU:
594                          *      Multi-line output
595                          *
596                          * Fetching First Line
597                          */
598                         gslist_line = (char *)at_resp->lines->data;
599                         dbg("gslist_line: [%s]", gslist_line);
600
601                         /*Tokenize*/
602                         tokens = tcore_at_tok_new(gslist_line);
603                         dbg("Number of tokens: [%d]", g_slist_length(tokens));
604
605                         /*+CMGR: <stat>,[<alpha>],<length><CR><LF><pdu>*/
606                         line_token = g_slist_nth_data(tokens, 0);       /*First Token: Message status*/
607                         if (line_token == NULL) {
608                                 err("Invalid stat");
609                                 goto OUT;
610                         }
611
612                         msg_status = atoi(line_token);
613                         dbg("msg_status is %d",msg_status);
614
615                         switch (msg_status) {
616                         case AT_MT_UNREAD:
617                                 read_resp.status = TEL_SMS_STATUS_MT_UNREAD;
618                         break;
619                         case AT_MT_READ:
620                                 read_resp.status = TEL_SMS_STATUS_MT_READ;
621                         break;
622                         case AT_MO_UNSENT:
623                                 read_resp.status = TEL_SMS_STATUS_MO_NOT_SENT;
624                         break;
625                         case AT_MO_SENT:
626                                 read_resp.status = TEL_SMS_STATUS_MO_SENT;
627                         break;
628                         case AT_ALL:
629                         default:
630                                 read_resp.status = TEL_SMS_STATUS_REPLACED;
631                         break;
632                         }
633
634                          /*Second Token: Alpha ID*/
635                         line_token = g_slist_nth_data(tokens, 1);
636                         if (line_token != NULL) {
637                                 alpha_id = atoi(line_token);
638                                 dbg("alpha_id: [%d]", alpha_id);
639                         }
640
641                         /*Third Token: Length*/
642                         line_token = g_slist_nth_data(tokens, 2);
643                         if (line_token == NULL) {
644                                 err("Invalid PDU length");
645                                 goto OUT;
646                         }
647                         pdu_len = atoi(line_token);
648                         dbg("PDU length: [%d]", pdu_len);
649
650                         /*Fetching line: Second line is PDU*/
651                         hex_pdu = (char *) at_resp->lines->next->data;
652                         dbg("EF-SMS PDU: [%s]", hex_pdu);
653
654                         if (NULL != hex_pdu) {
655                                 gint sca_length = 0;
656                                 guint byte_pdu_len = 0;
657
658                                 tcore_util_hex_dump("    ", sizeof(hex_pdu), (void *)hex_pdu);
659
660                                 tcore_util_hexstring_to_bytes(hex_pdu, &byte_pdu, &byte_pdu_len);
661
662                                 sca_length = byte_pdu[0];
663                                 dbg("SCA length = %d", sca_length);
664                                 if (sca_length) {
665                                         gchar *decoded_sca;
666                                         guint encoded_sca_len;
667
668                                         /*
669                                          * byte_pdu[1] - sca_address_type
670                                          *      Excluding sca_address_type and copy SCA
671                                          */
672                                         encoded_sca_len = sca_length - 1;
673                                         decoded_sca =
674                                                 tcore_util_convert_bcd_to_ascii(&byte_pdu[2],
675                                                         encoded_sca_len, encoded_sca_len*2);
676
677                                         dbg("Decoded SCA: [%s]", decoded_sca);
678                                         memcpy(read_resp.data.sca.number, decoded_sca, TEL_SMS_SCA_LEN_MAX);
679                                         tcore_free(decoded_sca);
680
681                                         /*SCA Conversion for Address type*/
682                                         read_resp.data.sca.ton = IMC_TYPE_OF_NUM(byte_pdu[1]);
683                                         read_resp.data.sca.npi = IMC_NUM_PLAN_ID(byte_pdu[1]);
684                                         dbg("TON: [%d] NPI: [%d] SCA: [%s]",
685                                                 read_resp.data.sca.ton, read_resp.data.sca.npi,
686                                                 read_resp.data.sca.number);
687                                 } else {
688                                         err("NO SCA Present");
689                                 }
690
691                                 /* TPDU */
692                                 read_resp.data.tpdu_length  = pdu_len;
693                                 if ((read_resp.data.tpdu_length > 0)
694                                         && (read_resp.data.tpdu_length <= TEL_SMS_SMDATA_SIZE_MAX)) {
695                                                 memcpy(read_resp.data.tpdu, &byte_pdu[sca_length+1],
696                                                         read_resp.data.tpdu_length);
697                                 } else {
698                                         warn("Invalid TPDU length: [%d]", read_resp.data.tpdu_length);
699                                 }
700
701                                 result = TEL_SMS_RESULT_SUCCESS;
702                                 g_free(byte_pdu);
703                         }
704                 } else {
705                         err("Invalid Response Received");
706                 }
707         }
708         else {
709                 err("RESPONSE NOK");
710         }
711 OUT:
712         /* Invoke callback */
713         if (resp_cb_data->cb)
714                 resp_cb_data->cb(co, (gint)result, &read_resp, resp_cb_data->cb_data);
715
716         /* Free callback data */
717         imc_destroy_resp_cb_data(resp_cb_data);
718
719         /*free the consumed token*/
720         tcore_at_tok_free(tokens);
721 }
722
723 static void on_response_imc_sms_delete_sms_in_sim(TcorePending *p,
724         guint data_len, const void *data, void *user_data)
725 {
726         const TcoreAtResponse *at_resp = data;
727         CoreObject *co = tcore_pending_ref_core_object(p);
728         ImcRespCbData *resp_cb_data = user_data;
729
730         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
731         dbg("Enter");
732
733         tcore_check_return_assert(co != NULL);
734
735         if (at_resp && at_resp->success) {
736                 dbg("Response OK");
737                 result = TEL_SMS_RESULT_SUCCESS;
738         }
739         else {
740                 dbg("Response NOK");
741         }
742
743         /* Invoke callback */
744         if (resp_cb_data->cb)
745                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
746
747         /* Free callback data */
748         imc_destroy_resp_cb_data(resp_cb_data);
749 }
750
751 static void on_response_imc_sms_get_msg_indices(TcorePending *p,
752         guint data_len, const void *data, void *user_data)
753 {
754         TelSmsStoredMsgCountInfo *count_info;/*Response from get_count Request*/
755         TelSmsResult result = TEL_SMS_RESULT_FAILURE;/*TODO: CMS error mapping required */
756
757         const TcoreAtResponse *at_resp = data;
758         CoreObject *co = tcore_pending_ref_core_object(p);
759         ImcRespCbData *resp_cb_data = user_data;
760         dbg("Enter");
761
762         count_info = (TelSmsStoredMsgCountInfo *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
763
764         if (at_resp && at_resp->success) {
765                 dbg("RESPONSE OK");
766                 if (at_resp->lines) {
767                         char *gslist_line = NULL;
768                         gint gslist_line_count = 0, ctr_loop = 0;
769
770                         gslist_line_count = g_slist_length(at_resp->lines);
771
772                         if (gslist_line_count > TEL_SMS_GSM_MSG_NUM_MAX)
773                                 gslist_line_count = TEL_SMS_GSM_MSG_NUM_MAX;
774                         dbg("Number of lines: [%d]", gslist_line_count);
775
776                         for (ctr_loop = 0; ctr_loop < gslist_line_count; ctr_loop++) {
777                                 /* Fetch Line 'ctr_loop' */
778                                 gslist_line = (char *)g_slist_nth_data(at_resp->lines, ctr_loop);
779                                 dbg("gslist_line [%d] is [%s]", ctr_loop, gslist_line);
780
781                                 if (NULL != gslist_line) {
782                                         GSList *tokens = NULL;
783                                         char *line_token = NULL;
784
785                                         tokens = tcore_at_tok_new(gslist_line);
786
787                                         line_token = g_slist_nth_data(tokens, 0);
788                                         if (NULL != line_token) {
789                                                 count_info->index_list[ctr_loop] = atoi(line_token);
790                                         }
791                                         else {
792                                                 dbg("line_token of gslist_line [%d] is NULL", ctr_loop);
793                                         }
794
795                                         tcore_at_tok_free(tokens);
796                                 }
797                                 else {
798                                         err("gslist_line is NULL");
799                                         goto ERROR;
800                                 }
801                         }
802
803                         result = TEL_SMS_RESULT_SUCCESS;
804                 }
805                 else {
806                         err("Invalid Response received. No Lines present in Response");
807
808                         /* Check if used count is zero*/
809                         if (count_info->used_count == 0)
810                                 result = TEL_SMS_RESULT_SUCCESS;
811                 }
812         }
813         else {
814                 err("RESPONSE NOK");
815         }
816
817 ERROR:
818         /* Invoke callback */
819         if (resp_cb_data->cb)
820                 resp_cb_data->cb(co, (gint)result, count_info, resp_cb_data->cb_data);
821
822         /* Free callback data */
823         imc_destroy_resp_cb_data(resp_cb_data);
824 }
825
826 static void on_response_imc_sms_get_sms_count(TcorePending *p,
827         guint data_len, const void *data, void *user_data)
828 {
829         gchar *at_cmd;
830         TelReturn ret;
831
832         TelSmsStoredMsgCountInfo count_info = {0, };
833         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
834         int used_count = 0, total_count = 0;
835
836         const TcoreAtResponse *at_resp = data;
837         CoreObject *co = tcore_pending_ref_core_object(p);
838         ImcRespCbData *resp_cb_data = user_data;
839         ImcRespCbData *getcnt_resp_cb_data;
840         dbg("Enter");
841
842         if (at_resp && at_resp->success) {
843                 dbg("RESPONSE OK");
844                 if (at_resp->lines) {
845                         GSList *tokens = NULL;
846                         char *line = NULL, *line_token = NULL;
847
848                         line = (char *)at_resp->lines->data;
849                         dbg("line: [%s]",line);
850
851                         /*
852                          * Tokenize
853                          *
854                          * +CPMS: <used1>, <total1>, <used2>, <total2>, <used3>, <total3>
855                          */
856                         tokens = tcore_at_tok_new(line);
857
858                         /* <used1> */
859                         line_token = g_slist_nth_data(tokens, 0);
860                         if (line_token) {
861                                 used_count =atoi(line_token);
862                                 dbg("used cnt is %d",used_count);
863                         }
864                         else {
865                                 err("Line Token for used count is NULL");
866                                 tcore_at_tok_free(tokens);
867                                 goto ERROR;
868                         }
869
870                         /* <total1> */
871                         line_token = g_slist_nth_data(tokens, 1);
872                         if (line_token) {
873                                 total_count = atoi(line_token);
874
875                                 count_info.total_count = total_count;
876                                 count_info.used_count = used_count;
877                                 dbg("Count - used: [%d] total: [%d]", used_count, total_count);
878
879                                 /*
880                                 * Operation - get_msg_indices_in_sim
881                                 *
882                                 * Request -
883                                 * AT-Command: AT+CMGL
884                                 *      +CPMS=<mem1>[, <mem2>[,<mem3>]]
885                                 *  where
886                                 * <mem1> memory storage to read.
887                                 *
888                                 * Response -
889                                 * Success: (Multi-line output)
890                                 * +CMGL=<stat>]
891                                 *
892                                 * <stat> status of the message.
893                                 * Failure:
894                                 *      +CMS ERROR: <error>
895                                 */
896
897                                 /* Sending the Second AT Request to fetch msg indices */
898                                 at_cmd = g_strdup_printf("AT+CMGL=4");
899
900                                 /* Response callback data */
901                                 getcnt_resp_cb_data = imc_create_resp_cb_data(resp_cb_data->cb,
902                                                 resp_cb_data->cb_data,
903                                                 &count_info, sizeof(TelSmsStoredMsgCountInfo));
904
905                                 /* Free previous request callback data */
906                                 imc_destroy_resp_cb_data(resp_cb_data);
907
908                                 /* Send Request to modem */
909                                 ret = tcore_at_prepare_and_send_request(co,
910                                         at_cmd, "+CMGL",
911                                         TCORE_AT_COMMAND_TYPE_MULTILINE,
912                                         NULL,
913                                         on_response_imc_sms_get_msg_indices, getcnt_resp_cb_data,
914                                         on_send_imc_request, NULL);
915
916                                 /* free the consumed token */
917                                 tcore_at_tok_free(tokens);
918                                 g_free(at_cmd);
919
920                                 IMC_CHECK_REQUEST_RET(ret, getcnt_resp_cb_data, "Get Indices in SIM");
921                                 if (ret != TEL_RETURN_SUCCESS) {
922                                         err("Failed to Process Get Msg Indices Request");
923                                         goto ERROR;
924                                 }
925
926                                 dbg("Exit");
927                                 return;
928                         }
929                         else {
930                                 err("Line Token for Total count is NULL");
931
932                                 /* free the consumed token */
933                                 tcore_at_tok_free(tokens);
934                                 goto ERROR;
935                         }
936                 }
937                 else {
938                         err("Invalid Response Received: NO Lines Present");
939                 }
940         }
941         else {
942                 err("RESPONSE NOK");
943         }
944
945 ERROR:
946         /* Invoke callback in case of error*/
947         if (resp_cb_data->cb)
948                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
949
950         /* Free callback data */
951         imc_destroy_resp_cb_data(resp_cb_data);
952 }
953
954 static void on_response_imc_sms_set_sca(TcorePending *p,
955         guint data_len, const void *data, void *user_data)
956 {
957         const TcoreAtResponse *at_resp = data;
958         CoreObject *co = tcore_pending_ref_core_object(p);
959         ImcRespCbData *resp_cb_data = user_data;
960
961         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
962         dbg("Enter");
963
964         if (at_resp && at_resp->success) {
965                 dbg("Response OK");
966                 result = TEL_SMS_RESULT_SUCCESS;
967         }
968         else {
969                 err("Response NOK");
970         }
971
972         /* Invoke callback */
973         if (resp_cb_data->cb)
974                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
975
976         /* Free callback data */
977         imc_destroy_resp_cb_data(resp_cb_data);
978 }
979
980 static void on_response_imc_sms_get_sca(TcorePending *p,
981         guint data_len, const void *data, void *user_data)
982 {
983         const TcoreAtResponse *at_resp = data;
984         CoreObject *co = tcore_pending_ref_core_object(p);
985         ImcRespCbData *resp_cb_data = user_data;
986
987         TelSmsSca sca_resp = { 0, };
988         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
989         dbg("Enter");
990
991         if (at_resp && at_resp->success) {
992                 dbg("Response OK");
993                 if (at_resp->lines) {
994                         GSList *tokens = NULL;
995                         const char *sca_tok_addr;
996                         gchar *line = NULL, *sca_addr = NULL, *sca_toa = NULL;
997
998                         line = (char *)at_resp->lines->data;
999                         tokens = tcore_at_tok_new(line);
1000                         sca_tok_addr = g_slist_nth_data(tokens, 0);
1001                         sca_toa = g_slist_nth_data(tokens, 1);
1002
1003                         sca_addr = tcore_at_tok_extract(sca_tok_addr);
1004                         dbg("SCA: [%s] SCA-TOA: [%s]", sca_addr, sca_toa);
1005                         if ((NULL != sca_addr) && (NULL != sca_toa)) {
1006                                 memcpy(sca_resp.number, sca_addr, strlen(sca_addr));
1007
1008                                 /* Type-of-Address */
1009                                 if (145 == atoi(sca_toa)) {
1010                                         sca_resp.ton = IMC_SIM_TON_INTERNATIONAL;
1011                                 }
1012                                 else {
1013                                         sca_resp.ton = IMC_SIM_TON_NATIONAL;
1014                                 }
1015                                 sca_resp.npi = 0;/* TODO */
1016                                 result = TEL_SMS_RESULT_SUCCESS;
1017                         }
1018                         else {
1019                                 err("SCA is NULL");
1020                         }
1021                         tcore_at_tok_free(tokens);
1022                         g_free(sca_addr);
1023                 }
1024                 else {
1025                         err("Invalid Response.No Lines Received");
1026                 }
1027         }
1028         else {
1029                 err("Response NOK");
1030         }
1031
1032         /* Invoke callback */
1033         if (resp_cb_data->cb)
1034                 resp_cb_data->cb(co, (gint)result, &sca_resp, resp_cb_data->cb_data);
1035
1036         /* Free callback data */
1037         imc_destroy_resp_cb_data(resp_cb_data);
1038 }
1039
1040 static void on_response_imc_sms_set_cb_config(TcorePending *p,
1041         guint data_len, const void *data, void *user_data)
1042 {
1043         const TcoreAtResponse *at_resp = data;
1044         CoreObject *co = tcore_pending_ref_core_object(p);
1045         ImcRespCbData *resp_cb_data = user_data;
1046
1047         TelSmsResult result = TEL_SMS_RESULT_FAILURE;/*TODO: CME error mapping required */
1048         dbg("Enter");
1049
1050         if (at_resp && at_resp->success) {
1051                 dbg("Response OK");
1052                 result = TEL_SMS_RESULT_SUCCESS;
1053         }
1054         else {
1055                 err("Response NOK");
1056         }
1057
1058         /* Invoke callback */
1059         if (resp_cb_data->cb)
1060                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1061
1062         /* Free callback data */
1063         imc_destroy_resp_cb_data(resp_cb_data);
1064 }
1065
1066 static void on_response_imc_sms_get_cb_config(TcorePending *p,
1067         guint data_len, const void *data, void *user_data)
1068 {
1069         const TcoreAtResponse *at_resp = data;
1070         CoreObject *co = tcore_pending_ref_core_object(p);
1071         ImcRespCbData *resp_cb_data = user_data;
1072
1073         GSList *cb_tokens = NULL;
1074         char *cb_str_token = NULL;
1075         int num_cb_tokens = 0;
1076         char *mid_tok = NULL;
1077         char *first_tok = NULL, *second_tok = NULL;
1078         gint i = 0, mode = 0;
1079         char delim[] = "-";
1080
1081         TelSmsCbConfigInfo get_cb_conf = {0, };
1082         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
1083         dbg("Enter");
1084
1085         if (at_resp && at_resp->success) {
1086                 dbg("Response OK");
1087                 if (at_resp->lines) {
1088                         GSList *tokens = NULL;
1089                         char *line_token = NULL, *line = NULL;
1090                         line = (char*)at_resp->lines->data;
1091                         if (line != NULL) {
1092                                 tokens = tcore_at_tok_new(line);
1093                                 /*
1094                                  * Response -
1095                                  *      +CSCB: <mode>,<mids>,<dcss>
1096                                  */
1097                                  line_token = g_slist_nth_data(tokens, 0);
1098                                 if (line_token) {
1099                                         mode = atoi(line_token);
1100                                         dbg("mode:[%d]", mode);
1101                                         get_cb_conf.cb_enabled = mode;
1102                                 }
1103                                 else {
1104                                         err("Line Token for Mode is NULL");
1105                                         tcore_at_tok_free(tokens);
1106                                         goto OUT;
1107                                 }
1108                                 line_token = g_slist_nth_data(tokens, 1);
1109                                 if (line_token) {
1110                                         cb_str_token = tcore_at_tok_extract(line_token);
1111                                         cb_tokens = tcore_at_tok_new((const char *)cb_str_token);
1112
1113                                         num_cb_tokens = g_slist_length(cb_tokens);
1114                                         dbg("num_cb_tokens = %d", num_cb_tokens);
1115                                         if (num_cb_tokens == 0) {
1116                                                 if (mode == 1) {        /* All CBS Enabled */
1117                                                         get_cb_conf.msg_id_range_cnt = 1;
1118                                                         get_cb_conf.msg_ids[0].from_msg_id = 0x0000;
1119                                                         get_cb_conf.msg_ids[0].to_msg_id = TEL_SMS_GSM_CBMI_LIST_SIZE_MAX + 1;
1120                                                         get_cb_conf.msg_ids[0].selected = TRUE;
1121                                                 }
1122                                                 else {  /* All CBS Disabled */
1123                                                         get_cb_conf.msg_id_range_cnt = 0;
1124                                                         get_cb_conf.msg_ids[0].selected = FALSE;
1125                                                 }
1126                                         }
1127
1128                                         for(i = 0; i < num_cb_tokens; i++) {
1129                                                 get_cb_conf.msg_ids[i].selected = TRUE;
1130                                                 dbg("msgIdRangeCount:[%d]", get_cb_conf.msg_id_range_cnt);
1131                                                 get_cb_conf.msg_id_range_cnt++;
1132                                                 dbg("Incremented msgIdRangeCount:[%d]", get_cb_conf.msg_id_range_cnt);
1133
1134                                                 mid_tok = tcore_at_tok_nth(cb_tokens, i);
1135                                                 first_tok = strtok(mid_tok, delim);
1136                                                 second_tok = strtok(NULL, delim);
1137
1138                                                 if ((first_tok != NULL) && (second_tok != NULL)) {/* mids in range (320-478) */
1139                                                         get_cb_conf.msg_ids[i].from_msg_id = atoi(first_tok);
1140                                                         get_cb_conf.msg_ids[i].to_msg_id = atoi(second_tok);
1141                                                 }
1142                                                 else {/* single mid value (0,1,5, 922)*/
1143                                                         get_cb_conf.msg_ids[i].from_msg_id = atoi(mid_tok);
1144                                                         get_cb_conf.msg_ids[i].to_msg_id = atoi(mid_tok);
1145                                                 }
1146                                         }
1147                                 }
1148                                 else {
1149                                         err("Line Token for MID is NULL");
1150                                         tcore_at_tok_free(tokens);
1151                                         goto OUT;
1152                                 }
1153                         }
1154                         else {
1155                                 err("Line is NULL");
1156                         }
1157                         result = TEL_SMS_RESULT_SUCCESS;
1158                         tcore_at_tok_free(tokens);
1159                         tcore_at_tok_free(cb_tokens);
1160                         g_free(cb_str_token);
1161                 }
1162                 else {
1163                         err("Invalid Response.No Lines Received");
1164                 }
1165         }
1166         else {
1167                 err("Response NOK");
1168         }
1169
1170 OUT:
1171         /* Invoke callback */
1172         if (resp_cb_data->cb)
1173                 resp_cb_data->cb(co, (gint)result, &get_cb_conf, resp_cb_data->cb_data);
1174
1175         /* Free callback data */
1176         imc_destroy_resp_cb_data(resp_cb_data);
1177 }
1178
1179 static void on_response_imc_sms_set_memory_status(TcorePending *p,
1180         guint data_len, const void *data, void *user_data)
1181 {
1182         const TcoreAtResponse *at_resp = data;
1183         CoreObject *co = tcore_pending_ref_core_object(p);
1184         ImcRespCbData *resp_cb_data = user_data;
1185
1186         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
1187         dbg("Enter");
1188
1189         if (at_resp && at_resp->success) {
1190                 dbg("Response OK");
1191                 result = TEL_SMS_RESULT_SUCCESS;
1192         }
1193         else {
1194                 err("Response NOK");
1195         }
1196
1197         /* Invoke callback */
1198         if (resp_cb_data->cb)
1199                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1200
1201         /* Free callback data */
1202         imc_destroy_resp_cb_data(resp_cb_data);
1203 }
1204
1205 static void on_response_imc_sms_set_message_status(TcorePending *p,
1206         guint data_len, const void *data, void *user_data)
1207 {
1208         const TcoreAtResponse *at_resp = data;
1209         CoreObject *co = tcore_pending_ref_core_object(p);
1210         ImcRespCbData *resp_cb_data = user_data;
1211
1212         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
1213         int response = 0, sw1 = 0, sw2 = 0;
1214         const char *line = NULL;
1215         char *line_token = NULL;
1216         GSList *tokens = NULL;
1217         dbg("Enter");
1218
1219         if (at_resp && at_resp->success) {
1220                 dbg("RESPONSE OK");
1221                 if (at_resp->lines) {
1222                         line = (const char *) at_resp->lines->data;
1223                         tokens = tcore_at_tok_new(line);
1224                         line_token = g_slist_nth_data(tokens, 0);
1225                         if (line_token != NULL) {
1226                                 sw1 = atoi(line_token);
1227                         }
1228                         else {
1229                                 dbg("sw1 is NULL");
1230                         }
1231                         line_token = g_slist_nth_data(tokens, 1);
1232                         if (line_token != NULL) {
1233                                 sw2 = atoi(line_token);
1234                                 if ((sw1 == 0x90) && (sw2 == 0)) {
1235                                         result = TEL_SMS_RESULT_SUCCESS;
1236                                 }
1237                         }
1238                         else {
1239                                 dbg("sw2 is NULL");
1240                         }
1241                         line_token = g_slist_nth_data(tokens, 3);
1242
1243                         if (line_token != NULL) {
1244                                 response = atoi(line_token);
1245                                 dbg("response is %s", response);
1246                         }
1247                         tcore_at_tok_free(tokens);
1248                 }
1249                 else {
1250                         dbg("No lines");
1251                 }
1252         }
1253         else {
1254                         err("RESPONSE NOK");
1255         }
1256
1257         /* Invoke callback */
1258         if (resp_cb_data->cb)
1259                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1260
1261         /* Free callback data */
1262         imc_destroy_resp_cb_data(resp_cb_data);
1263 }
1264
1265 static void _response_get_efsms_data(TcorePending *p,
1266         guint data_len, const void *data, void *user_data)
1267 {
1268         gchar *at_cmd;
1269         const TcoreAtResponse *at_resp = data;
1270         CoreObject *co = tcore_pending_ref_core_object(p);
1271         ImcRespCbData *resp_cb_data = user_data;
1272
1273         TelSmsStatusInfo *status_info;
1274         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
1275         TelReturn ret;
1276
1277         char *encoded_data = NULL;
1278         int encoded_len = 0;
1279         char msg_status = 0;
1280         char *line_token = NULL;
1281         GSList *tokens=NULL;
1282         const char *line = NULL;
1283         int sw1 = 0;
1284         int sw2 = 0;
1285         dbg("Enter");
1286
1287         status_info = (TelSmsStatusInfo *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
1288         if (at_resp && at_resp->success) {
1289                 dbg("RESPONSE OK");
1290                 if (at_resp->lines) {
1291                         dbg("Entry:lines Ok");
1292                         line = (const char *) at_resp->lines->data;
1293                         tokens = tcore_at_tok_new(line);
1294
1295                         sw1 = atoi(g_slist_nth_data(tokens, 0));
1296                         sw2 = atoi(g_slist_nth_data(tokens, 1));
1297                         line_token = g_slist_nth_data(tokens, 2);
1298
1299                         dbg("line_token:[%s], Length of line token:[%d]", line_token, strlen(line_token));
1300
1301                         if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
1302                                 switch (status_info->status) {
1303                                 case TEL_SMS_STATUS_MT_READ:
1304                                         msg_status = 0x01;
1305                                 break;
1306
1307                                 case TEL_SMS_STATUS_MT_UNREAD:
1308                                         msg_status = 0x03;
1309                                 break;
1310
1311                                 case TEL_SMS_STATUS_MO_NOT_SENT:
1312                                         msg_status = 0x07;
1313                                 break;
1314
1315                                 case TEL_SMS_STATUS_MO_SENT:
1316                                         msg_status = 0x05;
1317                                 break;
1318
1319                                 case TEL_SMS_STATUS_MO_DELIVERED:
1320                                         msg_status = 0x1D;
1321                                 break;
1322
1323                                 case TEL_SMS_STATUS_MO_DELIVERY_NOT_CONFIRMED:
1324                                         msg_status = 0xD;
1325                                 break;
1326
1327                                 case TEL_SMS_STATUS_REPLACED:/*Fall Through*/
1328                                 default:
1329                                         msg_status = 0x03;
1330                                 break;
1331                                 }
1332                         }
1333                         encoded_len = strlen(line_token);
1334                         dbg("Encoded data length:[%d]", encoded_len);
1335
1336                         encoded_data = tcore_malloc0(2*encoded_len + 1);
1337
1338                         memcpy(encoded_data, line_token, encoded_len);
1339                         dbg("encoded_data: [%s]", encoded_data);
1340
1341                         /* overwrite Status byte information */
1342                         tcore_util_byte_to_hex((const char *)&msg_status, encoded_data, 1);
1343
1344                         /*
1345                          * Updating EF-SMS File with status byte
1346                          * Rest 175 bytes are same as received in Read Record
1347                          *
1348                          */
1349                         at_cmd = g_strdup_printf("AT+CRSM=220,28476,%d, 4, %d, \"%s\"",
1350                                 (status_info->index), IMC_AT_EF_SMS_RECORD_LEN, encoded_data);
1351
1352                         /* Send Request to modem */
1353                         ret = tcore_at_prepare_and_send_request(co,
1354                                 at_cmd, "+CRSM:",
1355                                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1356                                 NULL,
1357                                 on_response_imc_sms_set_message_status, resp_cb_data,
1358                                 on_send_imc_request, NULL);
1359                         IMC_CHECK_REQUEST_RET(ret, resp_cb_data,
1360                                 "Set Message Status-Updating status in Record");
1361
1362                         g_free(encoded_data);
1363                         g_free(status_info);
1364                         tcore_at_tok_free(tokens);
1365                         return;
1366                 }
1367                 else {
1368                         err("Invalid Response Received");
1369                 }
1370         }
1371         else {
1372                 err("Response NOK");
1373         }
1374
1375         /* Invoke callback */
1376         if (resp_cb_data->cb)
1377                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1378
1379         /* Free callback data */
1380         imc_destroy_resp_cb_data(resp_cb_data);
1381 }
1382
1383 static void on_response_imc_sms_get_sms_params(TcorePending *p,
1384         guint data_len, const void *data, void *user_data)
1385 {
1386         const TcoreAtResponse *at_resp = data;
1387         CoreObject *co = tcore_pending_ref_core_object(p);
1388         ImcRespCbData *resp_cb_data = user_data;
1389         ImcSmsParamsCbData *params_req_data;
1390         gint sw1 = 0, sw2 = 0, decoding_length = 0;
1391         const char *line = NULL;
1392         char *hex_data = NULL, *record_data = NULL;
1393         GSList *tokens = NULL;
1394
1395         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
1396         dbg("Enter");
1397
1398         params_req_data = (ImcSmsParamsCbData *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
1399
1400         if (at_resp && at_resp->success) {
1401                 dbg("RESPONSE OK");
1402                 if (at_resp->lines) {
1403                         line = (const char *) at_resp->lines->data;
1404                         tokens = tcore_at_tok_new(line);
1405
1406                         sw1 = atoi(g_slist_nth_data(tokens, 0));
1407                         sw2 = atoi(g_slist_nth_data(tokens, 1));
1408                         dbg("sw1 [0x%x], sw2[0x%x]", sw1, sw2);
1409
1410                         if (!(sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
1411                                 err("invalid response received");
1412                                 goto OUT;
1413                         }
1414
1415                         hex_data = g_slist_nth_data(tokens, 2);
1416                         if (hex_data == NULL) {
1417                                 err("invalid response received");
1418                                 goto OUT;
1419                         }
1420                         hex_data = tcore_at_tok_extract((const gchar *)hex_data);
1421
1422                         tcore_util_hexstring_to_bytes(hex_data, &record_data, (guint*)&decoding_length);
1423                         tcore_free(hex_data);
1424                         /*
1425                         * Decrementing the Record Count and Filling the ParamsInfo List
1426                         * Final Response will be posted when Record count is ZERO
1427                         */
1428                         params_req_data->params[params_req_data->index].index = params_req_data->index;
1429
1430                         tcore_util_decode_sms_parameters((unsigned char *)record_data,
1431                                 decoding_length,
1432                                 &params_req_data->params[params_req_data->index]);
1433
1434                         params_req_data->total_param_count -= 1;
1435
1436                         if (params_req_data->total_param_count == 0) {
1437                                 dbg("Reading all Records - Complete");
1438                                 result = TEL_SMS_RESULT_SUCCESS;
1439                                 goto OUT;
1440                         } else {
1441                                 gchar *at_cmd;
1442                                 TelReturn ret;
1443
1444                                 dbg("Reading all records incomplete [Pending - %d]",
1445                                         params_req_data->total_param_count);
1446
1447                                 params_req_data->index++;
1448
1449                                 /* AT-Command */
1450                                 at_cmd = g_strdup_printf("AT+CRSM=178,28482,%d,4,%d",
1451                                         params_req_data->index, params_req_data->record_length);
1452
1453                                 /* Send Request to modem */
1454                                 ret = tcore_at_prepare_and_send_request(co,
1455                                                 at_cmd, "+CRSM",
1456                                                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1457                                                 NULL,
1458                                                 on_response_imc_sms_get_sms_params, resp_cb_data,
1459                                                 on_send_imc_request, NULL);
1460                                 g_free(at_cmd);
1461
1462                                 if (ret != TEL_RETURN_SUCCESS) {
1463                                         err("Failed to process request - [%s]", "Get SMS Parameters");
1464                                         goto OUT;
1465                                 }
1466
1467                                 tcore_at_tok_free(tokens);
1468                                 return;
1469                         }
1470                 } else {
1471                         err("Invalid Response Received");
1472                 }
1473         } else {
1474                 err("RESPONSE NOK");
1475         }
1476
1477 OUT:
1478         {
1479                 TelSmsParamsInfoList param_info_list = {0, };
1480
1481                 if (result == TEL_SMS_RESULT_SUCCESS) {
1482                         param_info_list.params = params_req_data->params;
1483                         param_info_list.count = params_req_data->record_count;
1484                 }
1485
1486                 /* Invoke callback */
1487                 if (resp_cb_data->cb)
1488                         resp_cb_data->cb(co, (gint)result, (void *)&param_info_list, resp_cb_data->cb_data);
1489         }
1490
1491         /* Free resource */
1492         tcore_at_tok_free(tokens);
1493
1494         tcore_free(params_req_data->params);
1495         g_free(record_data);
1496
1497         /* Free callback data */
1498         imc_destroy_resp_cb_data(resp_cb_data);
1499 }
1500
1501 static void on_response_imc_sms_set_sms_params(TcorePending *p,
1502         guint data_len, const void *data, void *user_data)
1503 {
1504         const TcoreAtResponse *at_resp = data;
1505         CoreObject *co = tcore_pending_ref_core_object(p);
1506         ImcRespCbData *resp_cb_data = user_data;
1507
1508         TelSmsResult result = TEL_SMS_RESULT_FAILURE;
1509         gint sw1 = 0 , sw2 = 0;
1510         const char *line = NULL;
1511         GSList *tokens=NULL;
1512         dbg("Enter");
1513
1514         if (at_resp && at_resp->success) {
1515                 dbg("Response OK");
1516                 if (at_resp->lines) {
1517                         line = (const char *) at_resp->lines->data;
1518                         tokens = tcore_at_tok_new(line);
1519
1520                         sw1 = atoi(g_slist_nth_data(tokens, 0));
1521                         sw2 = atoi(g_slist_nth_data(tokens, 1));
1522
1523                         if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
1524                                 result = TEL_SMS_RESULT_SUCCESS;
1525                         }
1526                         else {
1527                                 result = TEL_SMS_RESULT_FAILURE;
1528                         }
1529                 }
1530                 tcore_at_tok_free(tokens);
1531         } else {
1532                 err("Response NOK");
1533         }
1534
1535         /* Invoke callback */
1536         if (resp_cb_data->cb)
1537                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1538
1539         /* Free callback data */
1540         imc_destroy_resp_cb_data(resp_cb_data);
1541 }
1542
1543 static gboolean async_callback(gpointer data)
1544 {
1545         ImcRespCbData *resp_cb_data = data;
1546         CoreObject **co;
1547         TelSmsResult result = TEL_SMS_RESULT_SUCCESS;
1548
1549         co = ((CoreObject **)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data));
1550
1551         /* Invoke callback */
1552         if (resp_cb_data->cb)
1553                 resp_cb_data->cb(*co, (gint)result, NULL, resp_cb_data->cb_data);
1554
1555         /* Free callback data */
1556         imc_destroy_resp_cb_data(resp_cb_data);
1557
1558         return FALSE;
1559 }
1560
1561 /* SMS Operations */
1562 /*
1563  * Operation - send_sms
1564  *
1565  * Request -
1566  * AT-Command: AT+CMGS
1567  *      For PDU mode (+CMGF=0):
1568  *      +CMGS=<length><CR>
1569  *      PDU is given<ctrl-Z/ESC>
1570  * where,
1571  * <length> Length of the pdu.
1572  * <PDU>    PDU to send.
1573  *
1574  * Response -
1575  *+CMGS: <mr>[,<ackpdu>]
1576  *      OK
1577  * Failure:
1578  *      +CMS ERROR: <error>
1579  */
1580 static TelReturn imc_sms_send_sms(CoreObject *co,
1581         const TelSmsSendInfo *send_info, TcoreObjectResponseCallback cb, void *cb_data)
1582 {
1583         gchar *at_cmd;
1584
1585         ImcRespCbData *resp_cb_data;
1586         TelReturn ret;
1587
1588         const unsigned char *tpdu_byte_data;
1589         gint tpdu_byte_len, pdu_byte_len;
1590         char buf[HEX_PDU_LEN_MAX];
1591         char pdu[PDU_LEN_MAX];
1592         dbg("Enter");
1593
1594         tpdu_byte_data = send_info->send_data.tpdu;
1595
1596         /* TPDU length is in byte */
1597         tpdu_byte_len = send_info->send_data.tpdu_length;
1598
1599         /* Use same Radio Resource Channel :More Messages to send*/
1600         dbg("More messages: [%d]", send_info->more_msgs);
1601
1602         /* Prepare PDU for hex encoding */
1603         pdu_byte_len = tcore_util_encode_pdu(&(send_info->send_data.sca),
1604                                 tpdu_byte_data, tpdu_byte_len, pdu);
1605         tcore_util_hex_dump("    ", pdu_byte_len, pdu);
1606
1607         tcore_util_encode_hex((unsigned char *)pdu, pdu_byte_len, buf);
1608
1609         /* Response callback data */
1610         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1611
1612         if (send_info->more_msgs == TRUE) {
1613                 /* AT Command: More Msgs to Send */
1614                 ret = tcore_at_prepare_and_send_request(co,
1615                         "AT+CMMS=1", "+CMMS:",
1616                         TCORE_AT_COMMAND_TYPE_SINGLELINE,
1617                         NULL,
1618                         on_response_imc_sms_send_more_msg, NULL,
1619                         on_send_imc_request, NULL);
1620                 IMC_CHECK_REQUEST_RET(ret, NULL, "More Msgs to Send");
1621         }
1622
1623         /* AT-Command : Send SMS*/
1624         at_cmd = g_strdup_printf("AT+CMGS=%d\r%s\x1A", tpdu_byte_len, buf);
1625
1626         /* Send Request to modem */
1627         ret = tcore_at_prepare_and_send_request(co,
1628                 at_cmd, "+CMGS:",
1629                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1630                 NULL,
1631                 on_response_imc_sms_send_sms, resp_cb_data,
1632                 on_send_imc_request, NULL);
1633         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Send SMS");
1634
1635         /* Free resources */
1636         g_free(at_cmd);
1637
1638         return ret;
1639 }
1640
1641 /*
1642  * Operation - write_sms_in_sim
1643  *
1644  * Request -
1645  * AT-Command: AT+CMGW
1646  *      AT+CMGW = <length>[,<stat>]<CR>PDU is given<ctrl-Z/ESC>
1647  * where
1648  *      <length>        length of the tpdu
1649  *      <stat>  status of the message
1650  *      <PDU>   PDu of the message
1651  *
1652  * Response -
1653  *      +CMGW: <index>
1654  * Success: (Single line)
1655  *      OK
1656  * Failure:
1657  *      +CMS ERROR: <error>
1658  */
1659 static TelReturn imc_sms_write_sms_in_sim(CoreObject *co,
1660         const TelSmsSimDataInfo *wdata, TcoreObjectResponseCallback cb, void *cb_data)
1661 {
1662         gchar *at_cmd;
1663
1664         ImcRespCbData *resp_cb_data;
1665         TelReturn ret;
1666
1667         const unsigned char *tpdu_byte_data;
1668         int tpdu_byte_len, pdu_byte_len;
1669         char buf[HEX_PDU_LEN_MAX];
1670         char hex_pdu[PDU_LEN_MAX];
1671         gint status = 0;
1672         dbg("Enter");
1673
1674         switch (wdata->status) {
1675         case TEL_SMS_STATUS_MT_UNREAD:
1676                 status = AT_MT_UNREAD;
1677         break;
1678
1679         case TEL_SMS_STATUS_MT_READ:
1680                 status = AT_MT_READ;
1681         break;
1682
1683         case TEL_SMS_STATUS_MO_NOT_SENT:
1684                 status = AT_MO_UNSENT;
1685         break;
1686
1687         case TEL_SMS_STATUS_MO_SENT:
1688                 status = AT_MO_SENT;
1689         break;
1690
1691         default:
1692                 err("Invalid Message Status");
1693                 return TEL_RETURN_INVALID_PARAMETER;
1694         }
1695         tpdu_byte_data = wdata->data.tpdu;
1696
1697         tpdu_byte_len = wdata->data.tpdu_length;
1698         dbg("TDPU length: [%d]", tpdu_byte_len);
1699
1700         /* Prepare PDU for hex encoding */
1701         pdu_byte_len = tcore_util_encode_pdu(&(wdata->data.sca),
1702                                 tpdu_byte_data, tpdu_byte_len, hex_pdu);
1703         tcore_util_hex_dump("    ", pdu_byte_len, hex_pdu);
1704
1705         tcore_util_encode_hex((unsigned char *)hex_pdu, pdu_byte_len, buf);
1706
1707         /*AT Command*/
1708         at_cmd = g_strdup_printf("AT+CMGW=%d,%d%c%s%c",
1709                         tpdu_byte_len, status, CR, buf, CTRL_Z);
1710
1711         /* Response callback data */
1712         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1713
1714         /* Send Request to modem */
1715         ret = tcore_at_prepare_and_send_request(co,
1716                 at_cmd, "+CMGW:",
1717                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1718                 NULL,
1719                 on_response_imc_sms_write_sms_in_sim, resp_cb_data,
1720                 on_send_imc_request, NULL);
1721         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Write SMS in SIM");
1722
1723         /* Free resources */
1724         g_free(at_cmd);
1725
1726         return ret;
1727 }
1728
1729 /*
1730  * Operation - read_sms_in_sim
1731  *
1732  * Request -
1733  * AT-Command: At+CMGR=<index>
1734  *  where
1735  * <index> index of the message to be read.
1736  *
1737  * Response -
1738  * Success: (PDU: Multi-line output)
1739  * +CMGR: <stat>,[<alpha>],<length><CR><LF><pdu>
1740  *
1741  * Failure:
1742  *      +CMS ERROR: <error>
1743  */
1744 static TelReturn imc_sms_read_sms_in_sim(CoreObject *co,
1745         unsigned int index, TcoreObjectResponseCallback cb, void *cb_data)
1746 {
1747         gchar *at_cmd;
1748
1749         ImcRespCbData *resp_cb_data;
1750         TelReturn ret;
1751         dbg("Enter");
1752
1753         /* AT+Command */
1754         at_cmd = g_strdup_printf("AT+CMGR=%d", index);
1755
1756         /* Response callback data */
1757         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, ZERO);
1758
1759         /* Send Request to modem */
1760         ret = tcore_at_prepare_and_send_request(co,
1761                 at_cmd, "+CMGR:",
1762                 TCORE_AT_COMMAND_TYPE_PDU,
1763                 NULL,
1764                 on_response_imc_sms_read_sms_in_sim, resp_cb_data,
1765                 on_send_imc_request, NULL);
1766         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Read SMS in SIM");
1767
1768         /* Free resources */
1769         g_free(at_cmd);
1770
1771         return ret;
1772 }
1773
1774 /*
1775  * Operation - delete_sms_in_sim
1776  *
1777  * Request -
1778  * AT-Command: AT+CGMD
1779  *      +CMGD=<index>[,<delflag>]
1780  *
1781  * Response -
1782  * Success: (NO RESULT) -
1783  *      OK
1784  * Failure:
1785  *      +CMS ERROR: <error>
1786  */
1787 static TelReturn imc_sms_delete_sms_in_sim(CoreObject *co,
1788         unsigned int index,
1789         TcoreObjectResponseCallback cb, void *cb_data)
1790 {
1791         gchar *at_cmd;
1792
1793         ImcRespCbData *resp_cb_data;
1794         TelReturn ret;
1795         dbg("Enter");
1796
1797         /* Response callback data */
1798         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1799         /*
1800          * TODO: Delete All Messages
1801          *
1802          * at_cmd = g_strdup_printf("AT+CMGD=0,4");
1803          * Need to convey MSG_SERVICE to pass an index of
1804          * guint value to delete all Messages.probably as 0.
1805          */
1806
1807         /* AT-Command */
1808         at_cmd = g_strdup_printf("AT+CMGD=%d,0", index); /*Delete specified index*/
1809
1810         /* Send Request to modem */
1811         ret = tcore_at_prepare_and_send_request(co,
1812                 at_cmd, "+CMGD:",
1813                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1814                 NULL,
1815                 on_response_imc_sms_delete_sms_in_sim, resp_cb_data,
1816                 on_send_imc_request, NULL);
1817         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Delete SMS in SIM");
1818
1819         /* Free resources */
1820         g_free(at_cmd);
1821
1822         return ret;
1823 }
1824
1825 /*
1826  * Operation - get_sms_count_in_sim
1827  *
1828  * Request -
1829  * AT-Command: AT+CPMS
1830  *      +CPMS=<mem1>[, <mem2>[,<mem3>]]
1831  *  where
1832  * <mem1> memory storage to read.
1833  *
1834  * Response -
1835  * Success: (Single-line output)
1836  * +CPMS: <mem1>,<used1>,<total1>,<mem2>,<used2>,<total2>,
1837  * <mem3>,<used3>,<total3>
1838  * OK
1839  *
1840  * Failure:
1841  *      +CMS ERROR: <error>
1842  */
1843 static TelReturn imc_sms_get_msg_count_in_sim(CoreObject *co,
1844         TcoreObjectResponseCallback cb, void *cb_data)
1845 {
1846         gchar *at_cmd;
1847
1848         ImcRespCbData *resp_cb_data;
1849         TelReturn ret;
1850         dbg("Enter");
1851
1852         /*AT Command*/
1853         at_cmd = g_strdup_printf("AT+CPMS=\"SM\"");
1854
1855         /* Response callback data */
1856         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1857
1858         /* Send Request to modem */
1859         ret = tcore_at_prepare_and_send_request(co,
1860                 at_cmd, "+CPMS",
1861                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1862                 NULL,
1863                 on_response_imc_sms_get_sms_count, resp_cb_data,
1864                 on_send_imc_request, NULL);
1865         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get SMS Count");
1866
1867         /* Free resources */
1868         g_free(at_cmd);
1869
1870         return ret;
1871 }
1872
1873 /*
1874  * Operation - set SCA
1875  *
1876  * Request -
1877  * AT-Command: AT+CSCA
1878  *      AT+CSCA=<sca>[,<tosca>]
1879  * where
1880  * <sca> Service center number
1881  * <tosca> address type of SCA
1882  *
1883  * Response -
1884  * Success: No result
1885  *      OK
1886  *
1887  * Failure:
1888  *      +CMS ERROR: <error>
1889  */
1890  static TelReturn imc_sms_set_sca(CoreObject *co,
1891         const TelSmsSca *sca, TcoreObjectResponseCallback cb, void *cb_data)
1892 {
1893         gchar *at_cmd;
1894
1895         ImcRespCbData *resp_cb_data;
1896         TelReturn ret;
1897         gint address_type;
1898
1899         address_type = ((sca->ton << 4) | sca->npi ) | 0x80;
1900
1901         /* AT Command */
1902         at_cmd = g_strdup_printf("AT+CSCA=\"%s\",%d", sca->number, address_type);
1903
1904         /* Response callback data */
1905         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1906
1907         /* Send Request to modem */
1908         ret = tcore_at_prepare_and_send_request(co,
1909                 at_cmd, NULL,
1910                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1911                 NULL,
1912                 on_response_imc_sms_set_sca, resp_cb_data,
1913                 on_send_imc_request, NULL);
1914         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set SCA");
1915
1916         /* Free resources */
1917         g_free(at_cmd);
1918
1919         return ret;
1920 }
1921
1922 /*
1923  * Operation - get SCA
1924  *
1925  * Request -
1926  * AT-Command: AT+CSCA?
1927  *
1928  * Response -
1929  *      Success: Single-Line
1930  *      +CSCA: <sca>,<tosca>
1931  *      OK
1932  * where
1933  * <sca> Service center number
1934  * <tosca> address type of SCA
1935  *
1936  */
1937  static TelReturn imc_sms_get_sca(CoreObject *co,
1938         TcoreObjectResponseCallback cb, void *cb_data)
1939 {
1940         gchar *at_cmd;
1941
1942         ImcRespCbData *resp_cb_data;
1943         TelReturn ret;
1944         dbg("Enter");
1945
1946         /* AT Command */
1947         at_cmd = g_strdup_printf("AT+CSCA?");
1948
1949         /* Response callback data */
1950         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1951
1952         /* Send Request to modem */
1953         ret = tcore_at_prepare_and_send_request(co,
1954                 at_cmd, "+CSCA",
1955                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1956                 NULL,
1957                 on_response_imc_sms_get_sca, resp_cb_data,
1958                 on_send_imc_request, NULL);
1959         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get SCA");
1960
1961         /* Free resources */
1962         g_free(at_cmd);
1963
1964         return ret;
1965 }
1966
1967 /*
1968  * Operation - set_cb_config
1969  *
1970  * Request -
1971  * AT-Command: AT+CSCB
1972  *      +CSCB=[<mode>[,<mids>[,<dcss>]]]
1973  *
1974  * Response -
1975  * Success
1976  * OK
1977  *
1978  * Failure:
1979  *      +CME ERROR: <error>
1980  */
1981 static TelReturn imc_sms_set_cb_config(CoreObject *co,
1982         const TelSmsCbConfigInfo *cb_conf,
1983         TcoreObjectResponseCallback cb, void *cb_data)
1984 {
1985         gchar *at_cmd;
1986
1987         ImcRespCbData *resp_cb_data;
1988         TelReturn ret;
1989
1990         unsigned short ctr1 = 0, ctr2 = 0, msg_id_range = 0;
1991         unsigned short append_msg_id = 0;
1992         dbg("Enter");
1993
1994         if (cb_conf->msg_id_range_cnt != 0) {   /* Enable Specific Msgid's */
1995                 gchar *mids_str = NULL;
1996                 GString *mid_string = NULL;
1997                 at_cmd = NULL;
1998
1999                 mid_string = g_string_new("AT+CSCB=0,\"");
2000                 for(ctr1 = 0; ctr1 < cb_conf->msg_id_range_cnt; ctr1++) {
2001                         if (cb_conf->msg_ids[ctr1].selected == FALSE)
2002                                 continue;
2003                         msg_id_range = ((cb_conf->msg_ids[ctr1].to_msg_id) - (cb_conf->msg_ids[ctr1].from_msg_id));
2004
2005                         if (TEL_SMS_GSM_CBMI_LIST_SIZE_MAX <= msg_id_range) {
2006                                 mid_string = g_string_new("AT+CSCB=1"); /* Enable All CBS */
2007                                 break;
2008                         }
2009                         append_msg_id = cb_conf->msg_ids[ctr1].from_msg_id;
2010                         dbg( "%x", append_msg_id);
2011
2012                         for(ctr2 = 0; ctr2 <= msg_id_range; ctr2++) {
2013                                 mid_string = g_string_append(mid_string, g_strdup_printf("%d", append_msg_id));
2014                                 if (ctr2 == msg_id_range) {
2015                                         mid_string = g_string_append(mid_string, "\""); /*Mids string termination*/
2016                                 }
2017                                 else {
2018                                         mid_string = g_string_append(mid_string, ",");
2019                                 }
2020                                 append_msg_id++;
2021                         }
2022                 }
2023                 mids_str = g_string_free(mid_string, FALSE);
2024                 at_cmd = g_strdup_printf("%s", mids_str);
2025                 g_free(mids_str);
2026         }
2027         else {
2028                 at_cmd = g_strdup_printf("AT+CSCB=%d", cb_conf->cb_enabled);    /* Enable or Disable MsgId's */
2029         }
2030
2031         /* Response callback data */
2032         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
2033
2034         /* Send Request to modem */
2035         ret = tcore_at_prepare_and_send_request(co,
2036                 at_cmd, NULL,
2037                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
2038                 NULL,
2039                 on_response_imc_sms_set_cb_config, resp_cb_data,
2040                 on_send_imc_request, NULL);
2041         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Cb Config");
2042
2043         /* Free resources */
2044         g_free(at_cmd);
2045
2046         return ret;
2047 }
2048
2049 /*
2050  * Operation - get_cb_config
2051  *
2052  * Request -
2053  * AT-Command: AT+CSCB
2054  *      +CSCB?
2055  *
2056  * Response -
2057  * Success - (Single line)
2058  *      +CSCB : <mode>,<mids>,<dcss>
2059  * OK
2060  *
2061  */
2062  static TelReturn imc_sms_get_cb_config(CoreObject *co,
2063         TcoreObjectResponseCallback cb, void *cb_data)
2064 {
2065         gchar *at_cmd;
2066
2067         ImcRespCbData *resp_cb_data;
2068         TelReturn ret;
2069         dbg("Enter");
2070
2071         /* AT Command */
2072         at_cmd = g_strdup_printf("AT+CSCB?");
2073
2074         /* Response callback data */
2075         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
2076
2077         /* Send Request to modem */
2078         ret = tcore_at_prepare_and_send_request(co,
2079                 at_cmd, NULL,
2080                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
2081                 NULL,
2082                 on_response_imc_sms_get_cb_config, resp_cb_data,
2083                 on_send_imc_request, NULL);
2084         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Cb Config");
2085
2086         /* Free resources */
2087         g_free(at_cmd);
2088
2089         return ret;
2090 }
2091
2092 /*
2093  * Operation - send_deliver_report
2094  *
2095  * Request -
2096  *      Modem Takes care of sending the ACK to the network
2097  *
2098  * Response -
2099  * Success: Default response always SUCCESS posted
2100  *
2101  */
2102 static TelReturn imc_sms_send_deliver_report(CoreObject *co,
2103         const TelSmsDeliverReportInfo *dr_info,
2104         TcoreObjectResponseCallback cb, void *cb_data)
2105 {
2106         ImcRespCbData *resp_cb_data;
2107         TelReturn ret = TEL_RETURN_FAILURE;
2108
2109         dbg("CP takes care of sending SMS ack to network for all "
2110                 "classes of SMS. Sending default success.!!!");
2111         ret =  TEL_RETURN_SUCCESS;
2112
2113         /* Response callback data */
2114         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
2115                 (void *)&co, sizeof(CoreObject*));
2116
2117         g_idle_add(async_callback, (gpointer)resp_cb_data);
2118
2119         return ret;
2120 }
2121
2122
2123 /* Operation - set memory status
2124  *
2125  * Request -
2126  * AT-Command: AT+XTESM=<mem_capacity>
2127  *      <mem_capacity> status of the external SMS storage which may be:
2128  * 0: memory capacity free
2129  * 1: memory capacity full
2130  *
2131  * Response -No Result
2132  *      Success
2133  *       OK
2134  *
2135  * Failure:
2136  *      +CME ERROR: <error>
2137  */
2138 static TelReturn imc_sms_set_memory_status(CoreObject *co,
2139         gboolean available, TcoreObjectResponseCallback cb, void *cb_data)
2140 {
2141         gchar *at_cmd;
2142
2143         ImcRespCbData *resp_cb_data;
2144         TelReturn ret;
2145
2146         /*AT+Command*/
2147         at_cmd = g_strdup_printf("AT+XTESM=%d", available? 0: 1);
2148
2149         /* Response callback data */
2150         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
2151
2152         /* Send Request to modem */
2153         ret = tcore_at_prepare_and_send_request(co,
2154                 at_cmd, NULL,
2155                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
2156                 NULL,
2157                 on_response_imc_sms_set_memory_status, resp_cb_data,
2158                 on_send_imc_request, NULL);
2159         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Memory Status");
2160
2161         /* Free resources */
2162         g_free(at_cmd);
2163
2164         return ret;
2165 }
2166
2167 /* Operation - set Message status
2168  *
2169  * Request -
2170  * AT-Command: AT+CRSM= command>[,<fileid>[,<P1>,<P2>,<P3>[,<data>[,<pathid>]]]]
2171  *      p1 Index
2172  *      p3 SMSP record length
2173  *
2174  *
2175  * Response -Single Line
2176  *      Success
2177  *       OK
2178  *
2179  * Failure:
2180  *      +CME ERROR: <error>
2181  */
2182 static TelReturn imc_sms_set_message_status(CoreObject *co,
2183         const TelSmsStatusInfo *status_info,
2184         TcoreObjectResponseCallback cb, void *cb_data)
2185 {
2186         gchar *at_cmd;
2187
2188         ImcRespCbData *resp_cb_data;
2189         TelReturn ret;
2190
2191         /*AT+Command*/
2192         at_cmd = g_strdup_printf("AT+CRSM=178,28476,%d,4,%d",
2193                 (status_info->index), IMC_AT_EF_SMS_RECORD_LEN);
2194
2195         /* Response callback data */
2196         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
2197                 (void *)status_info, sizeof(TelSmsStatusInfo));
2198
2199         /* Send Request to modem */
2200         ret = tcore_at_prepare_and_send_request(co,
2201                 at_cmd, "+CRSM:",
2202                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
2203                 NULL,
2204                 _response_get_efsms_data, resp_cb_data,
2205                 on_send_imc_request, NULL);
2206         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Message Status");
2207
2208         /* Free resources */
2209         g_free(at_cmd);
2210
2211         return ret;
2212 }
2213
2214 /*
2215  * Operation - get_sms_parameters
2216  *
2217  * Request -
2218  * AT-Command: AT+CRSM
2219  *      AT+CRSM= command>[,<fileid>[,<P1>,<P2>,<P3>[,<data>[,<pathid>]]]]
2220  *
2221  * Response -
2222  * Success: (Single-line output)
2223  *      +CRSM:
2224  *      <sw1>,<sw2>[,<response>]
2225  *      OK
2226  *
2227  * Failure:
2228  *      +CME ERROR: <error>
2229  */
2230 static TelReturn imc_sms_get_sms_params(CoreObject *co,
2231         TcoreObjectResponseCallback cb, void *cb_data)
2232 {
2233         TcorePlugin *plugin;
2234         ImcRespCbData *resp_cb_data;
2235         ImcSmsParamsCbData params_req_data = {0, };
2236         gint loop_count, record_count = 0, smsp_record_len = 0;
2237
2238         gchar *at_cmd;
2239
2240         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
2241
2242         dbg("Enter");
2243
2244         plugin = tcore_object_ref_plugin(co);
2245
2246         /* Get Record count and SMSP record length*/
2247         if (FALSE == (imc_sim_get_smsp_info(plugin, &record_count,
2248                                 &smsp_record_len))) {
2249                 err("Failed to get SMSP record Count and Record length");
2250                 return ret;
2251         }
2252
2253         dbg("Record Count: [%d] SMSP Record Length: [%d]",
2254                 record_count, smsp_record_len);
2255
2256         /* Allocate Memory for params list data */
2257         params_req_data.params = tcore_malloc0(sizeof(TelSmsParamsInfo) * record_count);
2258         /* Counter */
2259         params_req_data.total_param_count = record_count;
2260
2261         /* Actual count to be returned */
2262         params_req_data.record_count = record_count;
2263         /* SMSP record length */
2264         params_req_data.record_length = smsp_record_len;
2265
2266         /* Response callback data */
2267         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
2268                                         (void *)&params_req_data,
2269                                         sizeof(ImcSmsParamsCbData));
2270
2271         /* Starting the Index with 1 */
2272         params_req_data.index = 1;
2273
2274         /* AT-Command */
2275         at_cmd = g_strdup_printf("AT+CRSM=178,28482,%d,4,%d",
2276                 params_req_data.index, params_req_data.record_length);
2277
2278         /* Send Request to modem */
2279         ret = tcore_at_prepare_and_send_request(co,
2280                         at_cmd, "+CRSM",
2281                         TCORE_AT_COMMAND_TYPE_SINGLELINE,
2282                         NULL,
2283                         on_response_imc_sms_get_sms_params, resp_cb_data,
2284                         on_send_imc_request, NULL);
2285         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get SMS Parameters");
2286
2287         /* Free resources */
2288         if (ret != TEL_RETURN_SUCCESS)
2289                 tcore_free(params_req_data.params);
2290         g_free(at_cmd);
2291
2292         return ret;
2293 }
2294
2295 /*
2296  * Operation - set_sms_params
2297  *
2298  * Request -
2299  * AT-Command: AT+CRSM
2300  *      AT+CRSM= command>[,<fileid>[,<P1>,<P2>,<P3>[,<data>[,<pathid>]]]]
2301  *
2302  * Response -
2303  * Success: (Single-line output)
2304  *      +CRSM:
2305  *      <sw1>,<sw2>[,<response>]
2306  *      OK
2307  *
2308  * Failure:
2309  *      +CME ERROR: <error>
2310  */
2311 static TelReturn imc_sms_set_sms_params(CoreObject *co,
2312         const TelSmsParamsInfo *params,
2313         TcoreObjectResponseCallback cb, void *cb_data)
2314 {
2315         gchar *at_cmd;
2316         ImcRespCbData *resp_cb_data;
2317         TelReturn ret;
2318
2319         TcorePlugin *plugin;
2320         gint smsp_record_len = 0;
2321         gchar *set_params_data = NULL;
2322         gchar *encoded_data = NULL;
2323         gint record_count;
2324         dbg("Enter");
2325
2326         plugin = tcore_object_ref_plugin(co);
2327
2328         if (FALSE  == imc_sim_get_smsp_info(plugin, &record_count, &smsp_record_len)) {
2329                 err("Failed to get SMSP record Count and Record length");
2330                 return TEL_RETURN_INVALID_PARAMETER;
2331         }
2332
2333         dbg("SMSP Record Length: [%d]", smsp_record_len);
2334
2335         /* Allocate memory for set_params_data */
2336         set_params_data = tcore_malloc0(sizeof(smsp_record_len));
2337
2338         /* Allocate memory for encoded data*/
2339         encoded_data = tcore_malloc0((2 * sizeof(smsp_record_len)+1));
2340
2341         tcore_util_encode_sms_parameters((TelSmsParamsInfo *)params,
2342                 set_params_data, smsp_record_len);
2343         dbg("SCA Address: [%s]", params->sca.number);
2344
2345         tcore_util_byte_to_hex((const char *)set_params_data,
2346                 (char *)encoded_data, smsp_record_len);
2347
2348         /* Response callback data */
2349         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, sizeof(gint));
2350
2351         /* AT+ Command*/
2352         at_cmd = g_strdup_printf("AT+CRSM=220,28482,%d,4,%d,\"%s\"",
2353                 params->index, smsp_record_len, encoded_data);
2354         dbg("at_cmd  - %s", at_cmd);
2355         /* Send Request to modem */
2356         ret = tcore_at_prepare_and_send_request(co,
2357                 at_cmd, "+CRSM",
2358                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
2359                 NULL,
2360                 on_response_imc_sms_set_sms_params, resp_cb_data,
2361                 on_send_imc_request, NULL);
2362         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set SMS Parameters");
2363
2364         /* Free resources */
2365         g_free(at_cmd);
2366         g_free(set_params_data);
2367         g_free(encoded_data);
2368
2369         return ret;
2370 }
2371
2372 /* SMS Operations */
2373 static TcoreSmsOps imc_sms_ops = {
2374         .send_sms = imc_sms_send_sms,
2375         .read_in_sim = imc_sms_read_sms_in_sim,
2376         .write_in_sim = imc_sms_write_sms_in_sim,
2377         .delete_in_sim = imc_sms_delete_sms_in_sim,
2378         .get_count = imc_sms_get_msg_count_in_sim,
2379         .set_cb_config = imc_sms_set_cb_config,
2380         .get_cb_config = imc_sms_get_cb_config,
2381         .get_parameters = imc_sms_get_sms_params,
2382         .set_parameters = imc_sms_set_sms_params,
2383         .send_deliver_report = imc_sms_send_deliver_report,
2384         .set_sca = imc_sms_set_sca,
2385         .get_sca = imc_sms_get_sca,
2386         .set_memory_status = imc_sms_set_memory_status,
2387         .set_message_status = imc_sms_set_message_status
2388 };
2389
2390 gboolean imc_sms_init(TcorePlugin *p, CoreObject *co)
2391 {
2392         dbg("Entry");
2393
2394         /* Set operations */
2395         tcore_sms_set_ops(co, &imc_sms_ops);
2396
2397         /* Add Callbacks */
2398         tcore_object_add_callback(co, "\e+CMT:",
2399                 on_notification_imc_sms_incoming_msg, NULL);
2400         tcore_object_add_callback(co, "\e+CDS",
2401                 on_notification_imc_sms_incoming_msg, NULL);
2402
2403         tcore_object_add_callback(co, "\e+CBM",
2404                 on_notification_imc_sms_cb_incom_msg, NULL);
2405         tcore_object_add_callback(co, "+CMTI",
2406                 on_notification_imc_sms_class2_incoming_msg, NULL);
2407
2408         /*
2409          * Notification
2410          * TODO - AT Command Description Not available
2411          */
2412         tcore_object_add_callback(co, "+XSMSMMSTAT",
2413                 on_notification_imc_sms_memory_status, NULL);
2414
2415         dbg("Exit");
2416         return TRUE;
2417 }
2418
2419 void imc_sms_exit(TcorePlugin *p, CoreObject *co)
2420 {
2421         dbg("Exit");
2422 }