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