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