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