Use key-manager API instead of secure-storage
[platform/core/telephony/tel-plugin-imc.git] / src / imc_sms.c
1 /*
2  * tel-plugin-imc
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Madhavi Akella <madhavi.a@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdint.h>
25
26 #include <glib.h>
27
28 #include <tcore.h>
29 #include <hal.h>
30 #include <core_object.h>
31 #include <plugin.h>
32 #include <queue.h>
33 #include <co_sms.h>
34 #include <co_sim.h>
35 #include <user_request.h>
36 #include <storage.h>
37 #include <server.h>
38 #include <at.h>
39 #include <plugin.h>
40
41 #include <util.h>
42
43 #include "common/imc_tel_err.h"
44 #include "imc_common.h"
45 #include "imc_sms.h"
46
47 /*=============================================================
48                         GSM-SMS Size
49 ==============================================================*/
50 #define MAX_GSM_SMS_TPDU_SIZE           244
51 #define MAX_GSM_SMS_MSG_NUM                     255
52 #define MAX_GSM_SMS_SERVICE_CENTER_ADDR 12      /* Maximum number of bytes of service center address */
53 #define MAX_GSM_SMS_CBMI_LIST_SIZE              100     /* Maximum number of CBMI list size for CBS 30*2=60  */
54 #define MAX_GSM_SMS_PARAM_RECORD_SIZE   156     /* Maximum number of bytes SMSP Record size (Y + 28), y : 0 ~ 128 */
55 #define MAX_GSM_SMS_STATUS_FILE_SIZE            2       /* Last Used TP-MR + SMS "Memory Cap. Exceeded" Noti Flag */
56 #define TAPI_SIM_SMSP_ADDRESS_LEN               20
57
58 /*=============================================================
59                         Device Ready
60 ==============================================================*/
61 #define SMS_DEVICE_READY                        1       /* Telephony device ready */
62 #define SMS_DEVICE_NOT_READY                    0       /* Telephony device not ready */
63
64 /*=============================================================
65                                                         CBMI Selection
66 ==============================================================*/
67 #define SMS_CBMI_SELECTED_SOME          0x02    /* Some CBMIs are selected */
68 #define SMS_CBMI_SELECTED_ALL                   0x01    /* All CBMIs are selected */
69
70 /*=============================================================
71                         Message Status
72 ==============================================================*/
73 #define AT_REC_UNREAD                           0       /* Received and Unread */
74 #define AT_REC_READ                             1       /* Received and Read */
75 #define AT_STO_UNSENT                           2       /* Unsent */
76 #define AT_STO_SENT                             3       /* Sent */
77 #define AT_ALL                                  4       /* Unknown */
78
79 /*=============================================================
80                                                         Memory Status
81 ==============================================================*/
82 #define AT_MEMORY_AVAILABLE                     0       /* Memory Available */
83 #define AT_MEMORY_FULL                          1       /* Memory Full */
84
85 /*=============================================================
86                 SIM CRSM SW1 and Sw2 Error definitions */
87
88 #define AT_SW1_SUCCESS                          0x90
89 #define AT_SW2_SUCCESS                          0
90 #define AT_SW1_LEN_RESP                 0x9F
91
92 #define AT_MAX_RECORD_LEN                       256
93  /* SCA 12 bytes long and TDPU is 164 bytes long */
94 #define PDU_LEN_MAX                             176
95 #define HEX_PDU_LEN_MAX                 ((PDU_LEN_MAX * 2) + 1)
96
97 /*=============================================================
98                         String Preprocessor
99 ==============================================================*/
100 #define CR              '\r'            /* Carriage Return */
101
102 /*=============================================================
103                                                         Developer
104 ==============================================================*/
105 #define SMS_SWAPBYTES16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
106 #define SMS_ENCODED_SCA_LEN_MAX                 12
107 #define CONVERT_TO_HEX(in, out) (in <= 9) ? \
108         (out = '0' + in) : (out = 'A' + in - 10)
109
110 void print_glib_list_elem(gpointer data, gpointer user_data);
111
112 static void on_response_class2_read_msg(TcorePending *pending, int data_len, const void *data, void *user_data);
113
114
115 gboolean util_byte_to_hex(const char *byte_pdu, char *hex_pdu, int num_bytes);
116
117 void print_glib_list_elem(gpointer data, gpointer user_data)
118 {
119         char *item = (char *)data;
120
121         dbg("item: [%s]", item);
122 }
123
124 /*=============================================================
125                                                         Send Callback
126 ==============================================================*/
127 static void on_confirmation_sms_message_send(TcorePending *p, gboolean result, void *user_data)
128 {
129         dbg("Entered Function. Request message out from queue");
130
131         dbg("TcorePending: [%p]", p);
132         dbg("result: [%02x]", result);
133         dbg("user_data: [%p]", user_data);
134
135         if (result == TRUE) {
136                 dbg("SEND OK");
137         } else { /* Failed */
138                 dbg("SEND NOK");
139         }
140
141         dbg("Exiting Function. Nothing to return");
142 }
143
144 /*=============================================================
145                                                         Utilities
146 ==============================================================*/
147 static void util_sms_free_memory(void *sms_ptr)
148 {
149         dbg("Entry");
150
151         if (NULL != sms_ptr) {
152                 dbg("Freeing memory location: [%p]", sms_ptr);
153                 free(sms_ptr);
154                 sms_ptr = NULL;
155         } else {
156                 err("Invalid memory location. Nothing to do.");
157         }
158
159         dbg("Exit");
160 }
161
162
163 static guint __util_sms_encode_pdu(const guchar *sca,
164         const guchar *tpdu, guint tpdu_len, gchar *pdu)
165 {
166         guint sca_len = 0;
167         unsigned char converted_sca[SMS_ENCODED_SCA_LEN_MAX];
168
169         if (sca[0] == 0) {
170                 converted_sca[0] = 0;
171                 sca_len = 0;
172         } else {
173                 unsigned int i;
174                 /*
175                  * For PDU, the SC Address length is the number of packed BCD bytes
176                  * + 1 byte for SC Address type whereas the length given in
177                  * 3GPP 23.040 Address encoding is the number of digits without 1 byte
178                  * for address type.
179                  */
180                 sca_len = ((sca[0] + 1) / 2) + 1;
181
182                 converted_sca[0] = (unsigned char)sca_len;
183
184                 for (i = 1; i <= sca_len; i++)
185                         converted_sca[i] = sca[i];
186         }
187
188         memcpy(pdu, converted_sca, sca_len + 1);
189         memcpy(pdu + sca_len + 1, tpdu, tpdu_len);
190
191         return sca_len + 1 + tpdu_len;
192
193 }
194
195 static long __util_sms_encode_hex(const guchar *src, long num_bytes, gchar *buf)
196 {
197         long i, j;
198
199         if (num_bytes <= 0)
200         return -1;
201
202         for (i = 0, j = 0; i < num_bytes; i++, j++) {
203                 CONVERT_TO_HEX(((src[i] >> 4) & 0xf), buf[j++]);
204                 CONVERT_TO_HEX((src[i] & 0xf), buf[j]);
205         }
206
207         buf[j] = '\0';
208
209         return j;
210 }
211
212 static int util_sms_decode_smsParameters(unsigned char *incoming,
213         unsigned int length, struct telephony_sms_Params *params)
214 {
215         int alpha_id_len = 0;
216         int i = 0;
217         int nOffset = 0;
218
219         dbg(" RecordLen = %d", length);
220
221         if (incoming == NULL || params == NULL)
222                 return FALSE;
223
224         alpha_id_len = length - SMS_SMSP_PARAMS_MAX_LEN;
225
226         if (alpha_id_len > 0) {
227                 if (alpha_id_len > SMS_SMSP_ALPHA_ID_LEN_MAX)
228                         alpha_id_len = SMS_SMSP_ALPHA_ID_LEN_MAX;
229
230                 for (i = 0; i < alpha_id_len; i++) {
231                         if (0xff == incoming[i]) {
232                                 dbg(" found");
233                                 break;
234                         }
235                 }
236
237                 memcpy(params->szAlphaId, incoming, i);
238
239                 params->alphaIdLen = i;
240
241                 dbg(" Alpha id length = %d", i);
242         } else {
243                 params->alphaIdLen = 0;
244                 dbg(" Alpha id length is zero");
245         }
246
247         params->paramIndicator = incoming[alpha_id_len];
248
249         dbg(" Param Indicator = %02x", params->paramIndicator);
250
251         if ((params->paramIndicator & SMSPValidDestAddr) == 0) {
252                 nOffset = nDestAddrOffset;
253
254                 if (0x00 == incoming[alpha_id_len + nOffset] || 0xff == incoming[alpha_id_len + nOffset]) {
255                         params->tpDestAddr.dialNumLen = 0;
256
257                         dbg("DestAddr Length is 0");
258                 } else {
259                         if (0 < (int) incoming[alpha_id_len + nOffset]) {
260                                 params->tpDestAddr.dialNumLen = (int) (incoming[alpha_id_len + nOffset] - 1);
261
262                                 if (params->tpDestAddr.dialNumLen > SMS_SMSP_ADDRESS_LEN)
263                                         params->tpDestAddr.dialNumLen = SMS_SMSP_ADDRESS_LEN;
264                         } else {
265                                 params->tpDestAddr.dialNumLen = 0;
266                         }
267
268                         params->tpDestAddr.numPlanId = incoming[alpha_id_len + (++nOffset)] & 0x0f;
269                         params->tpDestAddr.typeOfNum = (incoming[alpha_id_len + nOffset] & 0x70) >> 4;
270
271                         memcpy(params->tpDestAddr.diallingNum, &incoming[alpha_id_len + (++nOffset)], (params->tpDestAddr.dialNumLen));
272
273                         dbg("Dest TON is %d", params->tpDestAddr.typeOfNum);
274                         dbg("Dest NPI is %d", params->tpDestAddr.numPlanId);
275                         dbg("Dest Length = %d", params->tpDestAddr.dialNumLen);
276                         dbg("Dest Addr = %s", params->tpDestAddr.diallingNum);
277                 }
278         } else {
279                 params->tpDestAddr.dialNumLen = 0;
280         }
281
282         if ((params->paramIndicator & SMSPValidSvcAddr) == 0) {
283                 nOffset = nSCAAddrOffset;
284
285                 if (0x00 == (int) incoming[alpha_id_len + nOffset] || 0xff == (int) incoming[alpha_id_len + nOffset]) {
286                         params->tpSvcCntrAddr.dialNumLen = 0;
287
288                         dbg(" SCAddr Length is 0");
289                 } else {
290                         if (0 < (int) incoming[alpha_id_len + nOffset]) {
291                                 params->tpSvcCntrAddr.dialNumLen = (int) (incoming[alpha_id_len + nOffset] - 1);
292
293                                 if (params->tpSvcCntrAddr.dialNumLen > SMS_SMSP_ADDRESS_LEN)
294                                         params->tpSvcCntrAddr.dialNumLen = SMS_SMSP_ADDRESS_LEN;
295
296                                 params->tpSvcCntrAddr.numPlanId = incoming[alpha_id_len + (++nOffset)] & 0x0f;
297                                 params->tpSvcCntrAddr.typeOfNum = (incoming[alpha_id_len + nOffset] & 0x70) >> 4;
298
299                                 memcpy(params->tpSvcCntrAddr.diallingNum, &incoming[alpha_id_len + (++nOffset)], (params->tpSvcCntrAddr.dialNumLen));
300
301                                 dbg("SCAddr Length = %d ", params->tpSvcCntrAddr.dialNumLen);
302                                 dbg("SCAddr TON is %d", params->tpSvcCntrAddr.typeOfNum);
303                                 dbg("SCAddr NPI is %d", params->tpSvcCntrAddr.numPlanId);
304
305                                 for (i = 0; i < (int) params->tpSvcCntrAddr.dialNumLen; i++)
306                                         dbg("SCAddr = %d [%02x]", i, params->tpSvcCntrAddr.diallingNum[i]);
307                         } else {
308                                 params->tpSvcCntrAddr.dialNumLen = 0;
309                         }
310                 }
311         } else if ((0x00 < (int) incoming[alpha_id_len + nSCAAddrOffset] && (int) incoming[alpha_id_len + nSCAAddrOffset] <= 12)
312                            || 0xff != (int) incoming[alpha_id_len + nSCAAddrOffset]) {
313                 nOffset = nSCAAddrOffset;
314
315                 if (0x00 == (int) incoming[alpha_id_len + nOffset] || 0xff == (int) incoming[alpha_id_len + nOffset]) {
316                         params->tpSvcCntrAddr.dialNumLen = 0;
317                         dbg("SCAddr Length is 0");
318                 } else {
319                         if (0 < (int) incoming[alpha_id_len + nOffset]) {
320                                 params->tpSvcCntrAddr.dialNumLen = (int) (incoming[alpha_id_len + nOffset] - 1);
321
322                                 params->tpSvcCntrAddr.dialNumLen = incoming[alpha_id_len + nOffset] - 1;
323
324                                 if (params->tpSvcCntrAddr.dialNumLen > SMS_SMSP_ADDRESS_LEN)
325                                         params->tpSvcCntrAddr.dialNumLen = SMS_SMSP_ADDRESS_LEN;
326
327                                 params->tpSvcCntrAddr.numPlanId = incoming[alpha_id_len + (++nOffset)] & 0x0f;
328                                 params->tpSvcCntrAddr.typeOfNum = (incoming[alpha_id_len + nOffset] & 0x70) >> 4;
329
330                                 memcpy(params->tpSvcCntrAddr.diallingNum, &incoming[alpha_id_len + (++nOffset)],
331                                            (params->tpSvcCntrAddr.dialNumLen));
332
333                                 dbg("SCAddr Length = %d ", params->tpSvcCntrAddr.dialNumLen);
334                                 dbg("SCAddr TON is %d", params->tpSvcCntrAddr.typeOfNum);
335                                 dbg("SCAddr NPI is %d", params->tpSvcCntrAddr.numPlanId);
336
337                                 for (i = 0; i < (int) params->tpSvcCntrAddr.dialNumLen; i++)
338                                         dbg("SCAddr = %d [%02x]", i, params->tpSvcCntrAddr.diallingNum[i]);
339                         } else {
340                                 params->tpSvcCntrAddr.dialNumLen = 0;
341                         }
342                 }
343         } else {
344                         params->tpSvcCntrAddr.dialNumLen = 0;
345         }
346
347         if ((params->paramIndicator & SMSPValidPID) == 0
348                         && (alpha_id_len + nPIDOffset) < MAX_GSM_SMS_PARAM_RECORD_SIZE)
349                 params->tpProtocolId = incoming[alpha_id_len + nPIDOffset];
350
351         if ((params->paramIndicator & SMSPValidDCS) == 0
352                         && (alpha_id_len + nDCSOffset) < MAX_GSM_SMS_PARAM_RECORD_SIZE)
353                 params->tpDataCodingScheme = incoming[alpha_id_len + nDCSOffset];
354
355         if ((params->paramIndicator & SMSPValidVP) == 0
356                         && (alpha_id_len + nVPOffset) < MAX_GSM_SMS_PARAM_RECORD_SIZE)
357                 params->tpValidityPeriod = incoming[alpha_id_len + nVPOffset];
358
359         dbg(" Alpha Id(Len) = %d", (int) params->alphaIdLen);
360
361         for (i = 0; i < (int) params->alphaIdLen; i++)
362                 dbg(" Alpha Id = [%d] [%c]", i, params->szAlphaId[i]);
363
364         dbg(" PID = %d", params->tpProtocolId);
365         dbg(" DCS = %d", params->tpDataCodingScheme);
366         dbg(" VP = %d", params->tpValidityPeriod);
367
368         return TRUE;
369 }
370
371 /*
372  * Notifications
373  */
374 static gboolean on_event_class2_sms_incom_msg(CoreObject *obj,
375         const void *event_info, void *user_data)
376 {
377         /* +CMTI: <mem>, <index> */
378         GSList *tokens = NULL, *lines = NULL;
379         char *line = NULL, *cmd_str = NULL;
380         int index = 0, mem_type = 0;
381         TcoreHal *hal = NULL;
382         TcoreATRequest *atreq = NULL;
383         TcorePending *pending = NULL;
384
385         dbg("Entered Function");
386
387         lines = (GSList *)event_info;
388         line = (char *)g_slist_nth_data(lines, 0); /* Fetch Line 1 */
389
390         dbg("Line 1: [%s]", line);
391
392         if (!line) {
393                 err("Line 1 is invalid");
394                 return FALSE;
395         }
396
397         tokens = tcore_at_tok_new(line); /* Split Line 1 into tokens */
398         mem_type = atoi(g_slist_nth_data(tokens, 0));       /* Type of Memory stored */
399         if (mem_type == 0)
400                 err("Token 0 not present");
401
402         index = atoi((char *)g_slist_nth_data(tokens, 1));
403
404         hal = tcore_object_get_hal(obj);
405         if (NULL == hal) {
406                 err("NULL input. Unable to proceed");
407                 dbg("readMsg: hal: [%p]", hal);
408
409                 dbg("Exit");
410                 return TCORE_RETURN_EINVAL;
411         }
412
413         dbg("index: [%d]", index);
414
415         cmd_str = g_strdup_printf("AT+CMGR=%d", index);
416         atreq = tcore_at_request_new((const char *)cmd_str, "+CMGR", TCORE_AT_PDU);
417         pending = tcore_pending_new(obj, 0);
418
419         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
420                 err("Out of memory. Unable to proceed");
421                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
422
423                 g_free(cmd_str);
424                 util_sms_free_memory(atreq);
425                 util_sms_free_memory(pending);
426
427                 dbg("Exit");
428                 return TCORE_RETURN_ENOMEM;
429         }
430
431         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
432
433         tcore_pending_set_request_data(pending, 0, atreq);
434         tcore_pending_set_response_callback(pending, on_response_class2_read_msg, (void *)(uintptr_t)index); /* storing index as user data for response */
435         tcore_pending_link_user_request(pending, NULL);
436         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
437         tcore_hal_send_request(hal, pending);
438         g_free(cmd_str);
439
440         if (tokens)
441                 tcore_at_tok_free(tokens);
442
443         return TRUE;
444 }
445
446 static gboolean on_event_sms_incom_msg(CoreObject *o, const void *event_info, void *user_data)
447 {
448         /* +CMT: [<alpha>], <length><CR><LF><pdu> (PDU mode enabled); */
449         TReturn ret;
450         GSList *tokens = NULL;
451         GSList *lines = NULL;
452         char *line = NULL;
453         int pdu_len = 0, no_of_tokens = 0;
454         unsigned char *bytePDU = NULL;
455         struct tnoti_sms_incoming_msg gsmMsgInfo;
456         int sca_length = 0;
457
458         dbg("Entered Function");
459
460         lines = (GSList *)event_info;
461         memset(&gsmMsgInfo, 0x00, sizeof(struct tnoti_sms_incoming_msg));
462
463         if (2 != g_slist_length(lines)) {
464                 err("Invalid number of lines for +CMT. Must be 2");
465                 return FALSE;
466         }
467
468         line = (char *)g_slist_nth_data(lines, 0); /* Fetch Line 1 */
469
470         dbg("Line 1: [%s]", line);
471
472         if (!line) {
473                 err("Line 1 is invalid");
474                 return FALSE;
475         }
476
477         tokens = tcore_at_tok_new(line); /* Split Line 1 into tokens */
478
479         no_of_tokens = g_slist_length(tokens);
480
481         if (no_of_tokens == 2) { /* in case of incoming SMS +CMT */
482                 dbg("Alpha ID: [%02x]", g_slist_nth_data(tokens, 0)); /* 0: Alpha ID */
483                 pdu_len = atoi((char *)g_slist_nth_data(tokens, 1));
484                 dbg("pdu_len: [%d]", pdu_len);  /* 1: PDU Length */
485         } else if (no_of_tokens == 1) { /* in case of incoming status report +CDS */
486                 pdu_len = atoi((char *)g_slist_nth_data(tokens, 0));
487                 dbg("pdu_len: [%d]", pdu_len);  /* 1: PDU Length */
488         }
489
490         line = (char *)g_slist_nth_data(lines, 1); /* Fetch Line 2 */
491
492         dbg("Line 2: [%s]", line);
493
494         if (!line) {
495                 err("Line 2 is invalid");
496                 return FALSE;
497         }
498
499         /* Convert to Bytes */
500         bytePDU = (unsigned char *)util_hexStringToBytes(line);
501         if (!bytePDU) {
502                 err("NULL data received[%p]", bytePDU);
503                 tcore_at_tok_free(tokens);
504                 return FALSE;
505         }
506         sca_length = bytePDU[0];
507
508         dbg("SCA length = %d", sca_length);
509
510         gsmMsgInfo.msgInfo.format = SMS_NETTYPE_3GPP;
511         gsmMsgInfo.msgInfo.msgLength = pdu_len;
512
513         if (sca_length == 0) {
514                 memcpy(gsmMsgInfo.msgInfo.tpduData, &bytePDU[1], gsmMsgInfo.msgInfo.msgLength);
515         } else {
516                 gsmMsgInfo.msgInfo.sca[0] = sca_length;
517                 memcpy(&(gsmMsgInfo.msgInfo.sca[1]), &bytePDU[1], sca_length);
518                 memcpy(gsmMsgInfo.msgInfo.tpduData, &bytePDU[sca_length + 1], gsmMsgInfo.msgInfo.msgLength);
519         }
520
521         tcore_util_hex_dump("      ", strlen(line) / 2, bytePDU);
522         tcore_util_hex_dump("      ", sca_length, gsmMsgInfo.msgInfo.sca);
523         tcore_util_hex_dump("      ", gsmMsgInfo.msgInfo.msgLength, gsmMsgInfo.msgInfo.tpduData);
524
525         ret = tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),
526                 o,
527                 TNOTI_SMS_INCOM_MSG,
528                 sizeof(struct tnoti_sms_incoming_msg), &gsmMsgInfo);
529         dbg("ret: %x", ret);
530
531         if (tokens)
532                 tcore_at_tok_free(tokens);
533
534         g_free(bytePDU);
535
536         return TRUE;
537 }
538
539
540
541 static gboolean on_event_sms_memory_status(CoreObject *o, const void *event_info, void *user_data)
542 {
543         struct tnoti_sms_memory_status memStatusInfo = {0, };
544
545         int memoryStatus = -1;
546         GSList *tokens = NULL;
547         GSList *lines = NULL;
548         char *line = NULL, *pResp = NULL;
549         TReturn ret;
550
551         dbg(" Entry");
552
553         lines = (GSList *)event_info;
554         if (1 != g_slist_length(lines))
555                 dbg("unsolicited msg but multiple line");
556
557         line = (char *)(lines->data);
558
559         if (line) {
560                 dbg("Response OK");
561                 tokens = tcore_at_tok_new(line);
562                 pResp = g_slist_nth_data(tokens, 0);
563
564                 if (pResp) {
565                         memoryStatus = atoi(pResp);
566                         dbg("memoryStatus is %d", memoryStatus);
567                         if (memoryStatus == 0) /* SIM Full condition */
568                                 memStatusInfo.status = SMS_PHONE_MEMORY_STATUS_FULL;
569
570                         ret = tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),
571                                 o,
572                                 TNOTI_SMS_MEMORY_STATUS,
573                                 sizeof(struct tnoti_sms_memory_status), &memStatusInfo);
574                         dbg("ret: %x", ret);
575                 }
576                 tcore_at_tok_free(tokens);
577         } else {
578                 dbg("Response NOK");
579         }
580
581         dbg(" Exit ");
582         return TRUE;
583 }
584
585 static gboolean on_event_sms_cb_incom_msg(CoreObject *o, const void *event_info, void *user_data)
586 {
587         /* +CBM: <length><CR><LF><pdu> */
588         struct tnoti_sms_cellBroadcast_msg cbMsgInfo;
589
590         int rtn = -1, length = 0;
591         char *line = NULL, *pdu = NULL, *pResp = NULL;
592         GSList *tokens = NULL;
593         GSList *lines = NULL;
594
595         dbg(" Func Entrance");
596
597         lines = (GSList *)event_info;
598
599         memset(&cbMsgInfo, 0, sizeof(struct tnoti_sms_cellBroadcast_msg));
600
601         line = (char *)(lines->data);
602
603         if (line != NULL) {
604                 dbg("Response OK");
605                 dbg("Noti line is %s", line);
606                 tokens = tcore_at_tok_new(line); /* Split Line 1 into tokens */
607
608                 pResp = g_slist_nth_data(tokens, 0);
609                 if (pResp)
610                         length = atoi(pResp);
611                 else
612                         dbg("token 0 is null");
613
614                 pdu = g_slist_nth_data(lines, 1);
615                 if (pdu != NULL) {
616                         cbMsgInfo.cbMsg.length = length;
617                         cbMsgInfo.cbMsg.cbMsgType = SMS_CB_MSG_GSM;
618
619                         dbg("CB Msg LENGTH [%2x]", length);
620
621                         if ((cbMsgInfo.cbMsg.length > 0)
622                                         && (SMS_CB_SIZE_MAX >= cbMsgInfo.cbMsg.length)) {
623                                 unsigned char *byte_pdu = NULL;
624
625                                 byte_pdu = (unsigned char *)util_hexStringToBytes(pdu);
626                                 if (byte_pdu) {
627                                         memcpy(cbMsgInfo.cbMsg.msgData, (char *)byte_pdu, cbMsgInfo.cbMsg.length);
628                                         rtn = tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),
629                                                 o,
630                                                 TNOTI_SMS_CB_INCOM_MSG,
631                                                 sizeof(struct tnoti_sms_cellBroadcast_msg), &cbMsgInfo);
632                                         g_free(byte_pdu);
633                                 } else {
634                                         err("util_hexStringToBytes Failed!!");
635                                 }
636                         } else {
637                                 dbg("Invalid Message Length");
638                         }
639                 } else {
640                         dbg("Recieved NULL pdu");
641                 }
642         } else {
643                 dbg("Response NOK");
644         }
645
646         dbg(" Return value [%d]", rtn);
647
648         if (tokens)
649                 tcore_at_tok_free(tokens);
650
651         return TRUE;
652 }
653
654
655 /*
656  * Responses
657  */
658 static void on_response_sms_delete_msg(TcorePending *p,
659 int data_len, const void *data, void *user_data)
660 {
661         struct tresp_sms_delete_msg delMsgInfo = {0, };
662         UserRequest *ur = NULL;
663         const TcoreATResponse *atResp = data;
664         int index = GPOINTER_TO_INT(user_data);
665
666         dbg(" Func Entrance");
667
668         ur = tcore_pending_ref_user_request(p);
669         if (atResp->success) {
670                 dbg("Response OK");
671                 delMsgInfo.index = index;
672                 delMsgInfo.result = SMS_SENDSMS_SUCCESS;
673         } else {
674                 dbg("Response NOK");
675                 delMsgInfo.index = index;
676                 delMsgInfo.result = SMS_DEVICE_FAILURE;
677         }
678
679         tcore_user_request_send_response(ur,
680                 TRESP_SMS_DELETE_MSG,
681                 sizeof(struct tresp_sms_delete_msg), &delMsgInfo);
682
683         return;
684 }
685
686 static void on_response_sms_save_msg(TcorePending *p,
687         int data_len, const void *data, void *user_data)
688 {
689         struct tresp_sms_save_msg saveMsgInfo = {0, };
690         UserRequest *ur = NULL;
691         const TcoreATResponse *atResp = data;
692         GSList *tokens = NULL;
693         char *line = NULL;
694         char *pResp = NULL;
695         int rtn = -1;
696
697         ur = tcore_pending_ref_user_request(p);
698         if (atResp->success) {
699                 dbg("Response OK");
700                 if (atResp->lines) {
701                         line = (char *)atResp->lines->data;
702                         tokens = tcore_at_tok_new(line);
703                         pResp = g_slist_nth_data(tokens, 0);
704                         if (pResp) {
705                                 dbg("0: %s", pResp);
706                                 saveMsgInfo.index = (atoi(pResp) - 1); /* IMC index starts from 1 */
707                                 saveMsgInfo.result = SMS_SENDSMS_SUCCESS;
708                         } else {
709                                 dbg("No Tokens");
710                                 saveMsgInfo.index = -1;
711                                 saveMsgInfo.result = SMS_DEVICE_FAILURE;
712                         }
713                         tcore_at_tok_free(tokens);
714                 }
715         } else {
716                 dbg("Response NOK");
717                 saveMsgInfo.index = -1;
718                 saveMsgInfo.result = SMS_DEVICE_FAILURE;
719         }
720
721         rtn = tcore_user_request_send_response(ur,
722                 TRESP_SMS_SAVE_MSG,
723                 sizeof(struct tresp_sms_save_msg), &saveMsgInfo);
724         dbg("Return value [%d]", rtn);
725         return;
726 }
727
728 static void on_response_send_umts_msg(TcorePending *pending,
729         int data_len, const void *data, void *user_data)
730 {
731         const TcoreATResponse *at_response = data;
732         struct tresp_sms_send_msg resp_umts;
733         UserRequest *user_req = NULL;
734
735         int msg_ref = 0;
736         GSList *tokens = NULL;
737         char *gslist_line = NULL, *line_token = NULL;
738
739         dbg("Entry");
740
741         user_req = tcore_pending_ref_user_request(pending);
742
743         if (NULL == user_req) {
744                 err("No user request");
745
746                 dbg("Exit");
747                 return;
748         }
749
750         memset(&resp_umts, 0x00, sizeof(resp_umts));
751         resp_umts.result = SMS_DEVICE_FAILURE;
752
753         if (at_response->success > 0) { /* SUCCESS */
754                 dbg("Response OK");
755                 if (at_response->lines) { /* lines present in at_response */
756                         gslist_line = (char *)at_response->lines->data;
757                         dbg("gslist_line: [%s]", gslist_line);
758
759                         tokens = tcore_at_tok_new(gslist_line); /* extract tokens */
760
761                         line_token = g_slist_nth_data(tokens, 0);
762                         if (line_token != NULL) {
763                                 msg_ref = atoi(line_token);
764                                 dbg("Message Reference: [%d]", msg_ref);
765
766                                 resp_umts.result = SMS_SENDSMS_SUCCESS;
767                         } else {
768                                 dbg("No Message Reference received");
769                         }
770                         tcore_at_tok_free(tokens);
771                 } else { /* no lines in at_response */
772                         dbg("No lines");
773                 }
774         } else { /*  failure */
775                 dbg("Response NOK");
776         }
777
778         tcore_user_request_send_response(user_req,
779                 TRESP_SMS_SEND_UMTS_MSG,
780                 sizeof(resp_umts), &resp_umts);
781
782         dbg("Exit");
783         return;
784 }
785
786 static void on_response_class2_read_msg(TcorePending *pending,
787         int data_len, const void *data, void *user_data)
788 {
789         const TcoreATResponse *at_response = data;
790         GSList *tokens = NULL;
791         char *gslist_line = NULL, *line_token = NULL, *hex_pdu = NULL;
792         int  pdu_len = 0, rtn = 0;
793         unsigned char *bytePDU = NULL;
794         struct tnoti_sms_incoming_msg gsmMsgInfo;
795         int sca_length = 0;
796
797         dbg("Entry");
798         dbg("lines: [%p]", at_response->lines);
799         g_slist_foreach(at_response->lines, print_glib_list_elem, NULL);
800
801         if (at_response->success > 0) {
802                 dbg("Response OK");
803                 if (at_response->lines) {
804                         /* fetch first line */
805                         gslist_line = (char *)at_response->lines->data;
806
807                         dbg("gslist_line: [%s]", gslist_line);
808
809                         tokens = tcore_at_tok_new(gslist_line);
810                         dbg("Number of tokens: [%d]", g_slist_length(tokens));
811                         g_slist_foreach(tokens, print_glib_list_elem, NULL);
812
813                         line_token = g_slist_nth_data(tokens, 2); /* Third Token: Length */
814                         if (line_token != NULL) {
815                                 pdu_len = atoi(line_token);
816                                 dbg("Length: [%d]", pdu_len);
817                         }
818
819                         /* fetch second line */
820                         gslist_line = (char *)at_response->lines->next->data;
821
822                         dbg("gslist_line: [%s]", gslist_line);
823
824                         /* free the consumed token */
825                         tcore_at_tok_free(tokens);
826
827                         tokens = tcore_at_tok_new(gslist_line);
828                         dbg("Number of tokens: [%d]", g_slist_length(tokens));
829                         g_slist_foreach(tokens, print_glib_list_elem, NULL);
830
831                         hex_pdu = g_slist_nth_data(tokens, 0); /* Fetch SMS PDU */
832
833                         /* free the consumed token */
834                         tcore_at_tok_free(tokens);
835                 } else {
836                         dbg("No lines");
837                 }
838         } else {
839                 err("Response NOK");
840         }
841
842         /* Convert to Bytes */
843         bytePDU = (unsigned char *)util_hexStringToBytes(hex_pdu);
844         if (!bytePDU) {
845                 err("util_hexStringToBytes Failed!!");
846                 return;
847         }
848         sca_length = bytePDU[0];
849
850         dbg("SCA length = %d", sca_length);
851
852         gsmMsgInfo.msgInfo.msgLength = pdu_len;
853
854         if (sca_length == 0) {
855                 memcpy(gsmMsgInfo.msgInfo.tpduData, &bytePDU[1], gsmMsgInfo.msgInfo.msgLength);
856         } else {
857                 memcpy(gsmMsgInfo.msgInfo.sca, bytePDU, sca_length);
858                 memcpy(gsmMsgInfo.msgInfo.tpduData, &bytePDU[sca_length+1], gsmMsgInfo.msgInfo.msgLength);
859         }
860
861         tcore_util_hex_dump("      ", strlen(hex_pdu)/2, bytePDU);
862         tcore_util_hex_dump("      ", sca_length, gsmMsgInfo.msgInfo.sca);
863         tcore_util_hex_dump("      ", gsmMsgInfo.msgInfo.msgLength, gsmMsgInfo.msgInfo.tpduData);
864
865         rtn = tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(tcore_pending_ref_core_object(pending))),
866                 tcore_pending_ref_core_object(pending),
867                 TNOTI_SMS_INCOM_MSG,
868                 sizeof(struct tnoti_sms_incoming_msg), &gsmMsgInfo);
869         dbg("rtn: [%d]", rtn);
870
871         g_free(bytePDU);
872
873         dbg("Exit");
874         return;
875 }
876
877 static void on_response_read_msg(TcorePending *pending,
878         int data_len, const void *data, void *user_data)
879 {
880         const TcoreATResponse *at_response = data;
881         struct tresp_sms_read_msg resp_read_msg;
882         UserRequest *user_req = NULL;
883
884         GSList *tokens = NULL;
885         char *gslist_line = NULL, *line_token = NULL, *byte_pdu = NULL, *hex_pdu = NULL;
886         int sca_length = 0;
887         int msg_status = 0, alpha_id = 0, pdu_len = 0;
888         int index = (int)(uintptr_t)user_data;
889
890         dbg("Entry");
891         dbg("index: [%d]", index);
892         g_slist_foreach(at_response->lines, print_glib_list_elem, NULL);
893
894         user_req = tcore_pending_ref_user_request(pending);
895         if (NULL == user_req) {
896                 err("No user request");
897
898                 dbg("Exit");
899                 return;
900         }
901
902         memset(&resp_read_msg, 0x00, sizeof(resp_read_msg));
903         resp_read_msg.result = SMS_PHONE_FAILURE;
904
905         if (at_response->success > 0) {
906                 dbg("Response OK");
907                 if (at_response->lines) {
908                         if (g_slist_length(at_response->lines) != 2) {
909                                 err("2 lines are required");
910                                 goto OUT;
911                         }
912                         /* fetch first line */
913                         gslist_line = (char *)at_response->lines->data;
914
915                         dbg("gslist_line: [%s]", gslist_line);
916
917                         tokens = tcore_at_tok_new(gslist_line);
918                         dbg("Number of tokens: [%d]", g_slist_length(tokens));
919                         g_slist_foreach(tokens, print_glib_list_elem, NULL);
920
921                         line_token = g_slist_nth_data(tokens, 0); /* First Token: Message Status */
922                         if (line_token != NULL) {
923                                 msg_status = atoi(line_token);
924                                 dbg("msg_status is %d", msg_status);
925                                 switch (msg_status) {
926                                 case AT_REC_UNREAD:
927                                         resp_read_msg.dataInfo.msgStatus = SMS_STATUS_UNREAD;
928                                 break;
929
930                                 case AT_REC_READ:
931                                         resp_read_msg.dataInfo.msgStatus = SMS_STATUS_READ;
932                                 break;
933
934                                 case AT_STO_UNSENT:
935                                         resp_read_msg.dataInfo.msgStatus = SMS_STATUS_UNSENT;
936                                 break;
937
938                                 case AT_STO_SENT:
939                                         resp_read_msg.dataInfo.msgStatus = SMS_STATUS_SENT;
940                                 break;
941
942                                 case AT_ALL: /* Fall Through */
943                                 default: /* Fall Through */
944                                         resp_read_msg.dataInfo.msgStatus = SMS_STATUS_RESERVED;
945                                 break;
946                                 }
947                         }
948
949                         line_token = g_slist_nth_data(tokens, 1); /* Second Token: AlphaID */
950                         if (line_token != NULL) {
951                                 alpha_id = atoi(line_token);
952                                 dbg("AlphaID: [%d]", alpha_id);
953                         }
954
955                         line_token = g_slist_nth_data(tokens, 2); /* Third Token: Length */
956                         if (line_token != NULL) {
957                                 pdu_len = atoi(line_token);
958                                 dbg("Length: [%d]", pdu_len);
959                         }
960
961                         /* fetch second line */
962                         hex_pdu = (char *)at_response->lines->next->data;
963
964                         dbg("EF-SMS PDU: [%s]", hex_pdu);
965
966                         /* free the consumed token */
967                         tcore_at_tok_free(tokens);
968
969                         if (NULL != hex_pdu) {
970                                 tcore_util_hex_dump("    ", strlen(hex_pdu), (void *)hex_pdu);
971
972                                 byte_pdu = util_hexStringToBytes(hex_pdu);
973                                 if (!byte_pdu) {
974                                         err("util_hexStringToBytes Failed!!");
975                                         goto OUT;
976                                 }
977                                 sca_length = (int)byte_pdu[0];
978
979                                 resp_read_msg.dataInfo.simIndex = index; /* Retrieving index stored as user_data */
980
981                                 dbg("SCA Length : %d", sca_length);
982
983                                 resp_read_msg.dataInfo.smsData.msgLength = pdu_len;
984                                 dbg("msgLength: [%d]", resp_read_msg.dataInfo.smsData.msgLength);
985
986                                 if (0 == sca_length) {
987                                         if ((resp_read_msg.dataInfo.smsData.msgLength > 0)
988                                                         && (resp_read_msg.dataInfo.smsData.msgLength <= SMS_SMDATA_SIZE_MAX)) {
989                                                 memset(resp_read_msg.dataInfo.smsData.sca, 0, TAPI_SIM_SMSP_ADDRESS_LEN);
990                                                 memcpy(resp_read_msg.dataInfo.smsData.tpduData, &byte_pdu[1], resp_read_msg.dataInfo.smsData.msgLength);
991
992                                                 resp_read_msg.result = SMS_SUCCESS;
993                                         } else {
994                                                 dbg("Invalid Message Length");
995                                                 resp_read_msg.result = SMS_INVALID_PARAMETER_FORMAT;
996                                         }
997                                 } else if (sca_length > SMS_ENCODED_SCA_LEN_MAX) {
998                                         dbg("Invalid Message Length");
999                                         resp_read_msg.result = SMS_INVALID_PARAMETER_FORMAT;
1000                                 } else {
1001                                         if ((resp_read_msg.dataInfo.smsData.msgLength > 0)
1002                                                 && (resp_read_msg.dataInfo.smsData.msgLength <= SMS_SMDATA_SIZE_MAX)) {
1003                                                 memcpy(resp_read_msg.dataInfo.smsData.sca, (char *)byte_pdu, (sca_length+1));
1004                                                 memcpy(resp_read_msg.dataInfo.smsData.tpduData, &byte_pdu[sca_length+1], resp_read_msg.dataInfo.smsData.msgLength);
1005
1006                                                 tcore_util_hex_dump("    ", SMS_SMSP_ADDRESS_LEN, (void *)resp_read_msg.dataInfo.smsData.sca);
1007                                                 tcore_util_hex_dump("    ", (SMS_SMDATA_SIZE_MAX + 1), (void *)resp_read_msg.dataInfo.smsData.tpduData);
1008                                                 tcore_util_hex_dump("    ", strlen(hex_pdu) / 2 + 1, (void *)byte_pdu);
1009
1010                                                 resp_read_msg.result = SMS_SUCCESS;
1011                                         } else {
1012                                                 dbg("Invalid Message Length");
1013                                                 resp_read_msg.result = SMS_INVALID_PARAMETER_FORMAT;
1014                                         }
1015                                 }
1016                                 g_free(byte_pdu);
1017                         } else {
1018                                 dbg("NULL PDU");
1019                         }
1020                 } else {
1021                         dbg("No lines");
1022                 }
1023         } else {
1024                 err("Response NOK");
1025         }
1026
1027 OUT:
1028         tcore_user_request_send_response(user_req,
1029                 TRESP_SMS_READ_MSG,
1030                 sizeof(resp_read_msg), &resp_read_msg);
1031
1032         dbg("Exit");
1033         return;
1034 }
1035
1036 static void on_response_get_msg_indices(TcorePending *pending,
1037         int data_len, const void *data, void *user_data)
1038 {
1039         const TcoreATResponse *at_response = data;
1040         struct tresp_sms_get_storedMsgCnt resp_stored_msg_cnt;
1041         UserRequest *user_req = NULL;
1042         struct tresp_sms_get_storedMsgCnt *resp_stored_msg_cnt_prev = NULL;
1043
1044         GSList *tokens = NULL;
1045         char *gslist_line = NULL, *line_token = NULL;
1046         int gslist_line_count = 0, ctr_loop = 0;
1047
1048         dbg("Entry");
1049
1050         resp_stored_msg_cnt_prev = (struct tresp_sms_get_storedMsgCnt *)user_data;
1051         user_req = tcore_pending_ref_user_request(pending);
1052
1053         memset(&resp_stored_msg_cnt, 0x00, sizeof(resp_stored_msg_cnt));
1054         resp_stored_msg_cnt.result = SMS_DEVICE_FAILURE;
1055
1056         if (at_response->success) {
1057                 dbg("Response OK");
1058                 if (at_response->lines) {
1059                         gslist_line_count = g_slist_length(at_response->lines);
1060
1061                         if (gslist_line_count > SMS_GSM_SMS_MSG_NUM_MAX)
1062                                 gslist_line_count = SMS_GSM_SMS_MSG_NUM_MAX;
1063
1064                         dbg("Number of lines: [%d]", gslist_line_count);
1065                         g_slist_foreach(at_response->lines, print_glib_list_elem, NULL);
1066
1067                         for (ctr_loop = 0; ctr_loop < gslist_line_count; ctr_loop++) {
1068                                 gslist_line = (char *)g_slist_nth_data(at_response->lines, ctr_loop); /* Fetch Line i */
1069
1070                                 dbg("gslist_line [%d] is [%s]", ctr_loop, gslist_line);
1071
1072                                 if (NULL != gslist_line) {
1073                                         tokens = tcore_at_tok_new(gslist_line);
1074
1075                                         g_slist_foreach(tokens, print_glib_list_elem, NULL);
1076
1077                                         line_token = g_slist_nth_data(tokens, 0);
1078                                         if (NULL != line_token) {
1079                                                 resp_stored_msg_cnt.storedMsgCnt.indexList[ctr_loop] = atoi(line_token);
1080                                                 resp_stored_msg_cnt.result = SMS_SENDSMS_SUCCESS;
1081                                         } else {
1082                                                 dbg("line_token of gslist_line [%d] is NULL", ctr_loop);
1083                                                 continue;
1084                                         }
1085                                         tcore_at_tok_free(tokens);
1086                                 } else {
1087                                         dbg("gslist_line [%d] is NULL", ctr_loop);
1088                                         continue;
1089                                 }
1090                         }
1091                 } else {
1092                         dbg("No lines.");
1093                         if (resp_stored_msg_cnt_prev->storedMsgCnt.usedCount == 0) /* Check if used count is zero */
1094                                 resp_stored_msg_cnt.result = SMS_SENDSMS_SUCCESS;
1095                 }
1096         } else {
1097                 dbg("Respnose NOK");
1098         }
1099
1100         resp_stored_msg_cnt.storedMsgCnt.totalCount = resp_stored_msg_cnt_prev->storedMsgCnt.totalCount;
1101         resp_stored_msg_cnt.storedMsgCnt.usedCount = resp_stored_msg_cnt_prev->storedMsgCnt.usedCount;
1102
1103         util_sms_free_memory(resp_stored_msg_cnt_prev);
1104
1105         dbg("total: [%d], used: [%d], result: [%d]",
1106                 resp_stored_msg_cnt.storedMsgCnt.totalCount,
1107                 resp_stored_msg_cnt.storedMsgCnt.usedCount,
1108                 resp_stored_msg_cnt.result);
1109         for (ctr_loop = 0; ctr_loop < gslist_line_count; ctr_loop++)
1110                 dbg("index: [%d]", resp_stored_msg_cnt.storedMsgCnt.indexList[ctr_loop]);
1111
1112         tcore_user_request_send_response(user_req,
1113                 TRESP_SMS_GET_STORED_MSG_COUNT,
1114                 sizeof(resp_stored_msg_cnt), &resp_stored_msg_cnt);
1115
1116         dbg("Exit");
1117         return;
1118 }
1119
1120 static void on_response_get_stored_msg_cnt(TcorePending *pending,
1121         int data_len, const void *data, void *user_data)
1122 {
1123         UserRequest *ur = NULL, *ur_dup = NULL;
1124         struct tresp_sms_get_storedMsgCnt *respStoredMsgCnt = NULL;
1125         const TcoreATResponse *atResp = data;
1126         GSList *tokens = NULL;
1127         char *line = NULL, *pResp = NULL, *cmd_str = NULL;
1128         TcoreATRequest *atReq = NULL;
1129         int usedCnt = 0, totalCnt = 0, result = 0;
1130
1131         TcorePending *pending_new = NULL;
1132         CoreObject *o = NULL;
1133
1134         dbg("Entered");
1135
1136         respStoredMsgCnt = malloc(sizeof(struct tresp_sms_get_storedMsgCnt));
1137         if (!respStoredMsgCnt)
1138                 return;
1139
1140         result = SMS_DEVICE_FAILURE;
1141
1142         ur = tcore_pending_ref_user_request(pending);
1143         ur_dup = tcore_user_request_ref(ur);
1144         o = tcore_pending_ref_core_object(pending);
1145
1146         if (atResp->success > 0) {
1147                 dbg("Response OK");
1148                 if (NULL != atResp->lines) {
1149                         line = (char *)atResp->lines->data;
1150                         dbg("line is %s", line);
1151
1152                         tokens = tcore_at_tok_new(line);
1153                         pResp = g_slist_nth_data(tokens, 0);
1154
1155                         if (pResp) {
1156                                 usedCnt = atoi(pResp);
1157                                 dbg("used cnt is %d", usedCnt);
1158                         }
1159
1160                         pResp = g_slist_nth_data(tokens, 1);
1161                         if (pResp) {
1162                                 totalCnt = atoi(pResp);
1163                                 result = SMS_SENDSMS_SUCCESS;
1164
1165                                 respStoredMsgCnt->storedMsgCnt.usedCount = usedCnt;
1166                                 respStoredMsgCnt->storedMsgCnt.totalCount = totalCnt;
1167                                 respStoredMsgCnt->result = result;
1168
1169                                 dbg("used %d, total %d, result %d", usedCnt, totalCnt, result);
1170
1171                                 pending_new = tcore_pending_new(o, 0);
1172                                 /* Get all messages information */
1173                                 cmd_str = g_strdup_printf("AT+CMGL=4");
1174                                 atReq = tcore_at_request_new((const char *)cmd_str, "+CMGL", TCORE_AT_MULTILINE);
1175
1176                                 dbg("cmd str is %s", cmd_str);
1177
1178                                 tcore_pending_set_request_data(pending_new, 0, atReq);
1179                                 tcore_pending_set_response_callback(pending_new, on_response_get_msg_indices, (void *)respStoredMsgCnt);
1180                                 tcore_pending_link_user_request(pending_new, ur_dup);
1181                                 tcore_pending_set_send_callback(pending_new, on_confirmation_sms_message_send, NULL);
1182                                 tcore_hal_send_request(tcore_object_get_hal(o), pending_new);
1183
1184                                 /* free the consumed token */
1185                                 tcore_at_tok_free(tokens);
1186
1187                                 g_free(cmd_str);
1188
1189                                 dbg("Exit");
1190                                 return;
1191                         }
1192                         /* free the consumed token */
1193                         if (tokens)
1194                         tcore_at_tok_free(tokens);
1195                 } else {
1196                         dbg("No data");
1197                 }
1198         } else {
1199                 err("Response NOK");
1200         }
1201
1202         respStoredMsgCnt->result = result;
1203         tcore_user_request_send_response(ur,
1204                 TRESP_SMS_GET_STORED_MSG_COUNT,
1205                 sizeof(struct tresp_sms_get_storedMsgCnt), &respStoredMsgCnt);
1206
1207
1208         dbg("Exit");
1209         return;
1210 }
1211
1212 static void on_response_get_sca(TcorePending *pending,
1213         int data_len, const void *data, void *user_data)
1214 {
1215         const TcoreATResponse *at_response = data;
1216         struct tresp_sms_get_sca respGetSca;
1217         UserRequest *user_req = NULL;
1218
1219         GSList *tokens = NULL;
1220         const char *sca_tok_addr;
1221         char *gslist_line = NULL, *sca_addr = NULL, *sca_toa = NULL;
1222
1223         dbg("Entry");
1224
1225         memset(&respGetSca, 0, sizeof(respGetSca));
1226         respGetSca.result = SMS_DEVICE_FAILURE;
1227
1228         user_req = tcore_pending_ref_user_request(pending);
1229
1230         if (at_response->success) {
1231                 dbg("Response OK");
1232                 if (at_response->lines) {
1233                         gslist_line = (char *)at_response->lines->data;
1234
1235                         tokens = tcore_at_tok_new(gslist_line);
1236                         sca_tok_addr = g_slist_nth_data(tokens, 0);
1237                         sca_toa = g_slist_nth_data(tokens, 1);
1238
1239                         sca_addr = tcore_at_tok_extract(sca_tok_addr);
1240                         if ((NULL != sca_addr)
1241                                 && (NULL != sca_toa)) {
1242                                 dbg("sca_addr: [%s]. sca_toa: [%s]", sca_addr, sca_toa);
1243
1244                                 respGetSca.scaAddress.dialNumLen = strlen(sca_addr);
1245
1246                                 if (145 == atoi(sca_toa))
1247                                         respGetSca.scaAddress.typeOfNum = SIM_TON_INTERNATIONAL;
1248                                 else
1249                                         respGetSca.scaAddress.typeOfNum = SIM_TON_NATIONAL;
1250
1251                                 respGetSca.scaAddress.numPlanId = 0;
1252
1253                                 memcpy(respGetSca.scaAddress.diallingNum, sca_addr, strlen(sca_addr));
1254
1255                                 dbg("len [%d], sca_addr [%s], TON [%d], NPI [%d]",
1256                                         respGetSca.scaAddress.dialNumLen,
1257                                         respGetSca.scaAddress.diallingNum,
1258                                         respGetSca.scaAddress.typeOfNum,
1259                                         respGetSca.scaAddress.numPlanId);
1260
1261                                 respGetSca.result = SMS_SENDSMS_SUCCESS;
1262                         } else {
1263                                 err("sca_addr OR sca_toa NULL");
1264                         }
1265                 } else {
1266                         dbg("NO Lines");
1267                 }
1268         } else {
1269                 dbg("Response NOK");
1270         }
1271
1272         tcore_user_request_send_response(user_req,
1273                 TRESP_SMS_GET_SCA,
1274                 sizeof(respGetSca), &respGetSca);
1275
1276         tcore_at_tok_free(tokens);
1277         g_free(sca_addr);
1278
1279         dbg("Exit");
1280 }
1281
1282 static void on_response_set_sca(TcorePending *pending,
1283         int data_len, const void *data, void *user_data)
1284 {
1285         /*
1286          * Response is expected in this format
1287          *      OK
1288          * or
1289          *      +CMS ERROR: <err>
1290          */
1291         UserRequest *ur;
1292         const TcoreATResponse *atResp = data;
1293         struct tresp_sms_set_sca respSetSca;
1294
1295         memset(&respSetSca, 0, sizeof(struct tresp_sms_set_sca));
1296
1297         ur = tcore_pending_ref_user_request(pending);
1298         if (!ur) {
1299                 dbg("no user_request");
1300                 return;
1301         }
1302
1303         if (atResp->success > 0) {
1304                 dbg("RESPONSE OK");
1305                 respSetSca.result = SMS_SUCCESS;
1306         } else {
1307                 dbg("RESPONSE NOK");
1308                 respSetSca.result = SMS_DEVICE_FAILURE;
1309         }
1310
1311         tcore_user_request_send_response(ur,
1312                 TRESP_SMS_SET_SCA,
1313                 sizeof(struct tresp_sms_set_sca), &respSetSca);
1314 }
1315
1316 static void on_response_get_cb_config(TcorePending *p,
1317         int data_len, const void *data, void *user_data)
1318 {
1319         UserRequest *ur;
1320         struct tresp_sms_get_cb_config respGetCbConfig;
1321         const TcoreATResponse *atResp = data;
1322         GSList *tokens = NULL;
1323         int i = 0, mode = 0;
1324         char *pResp = NULL, *line = NULL;
1325
1326         memset(&respGetCbConfig, 0, sizeof(struct tresp_sms_get_cb_config));
1327         respGetCbConfig.result = SMS_DEVICE_FAILURE;
1328
1329         ur = tcore_pending_ref_user_request(p);
1330         if (!ur) {
1331                 dbg("no user_request");
1332                 return;
1333         }
1334
1335         respGetCbConfig.cbConfig.net3gppType = SMS_NETTYPE_3GPP;
1336         respGetCbConfig.cbConfig.msgIdMaxCount = SMS_GSM_SMS_CBMI_LIST_SIZE_MAX;
1337
1338         if (atResp->success) {
1339                 dbg("Response OK");
1340                 if (atResp->lines) {
1341                         line = (char *)atResp->lines->data;
1342                         if (line != NULL) {
1343                                 dbg("line is %s", line);
1344                                 tokens = tcore_at_tok_new(line);
1345                                 pResp = g_slist_nth_data(tokens, 0);
1346                                 if (pResp) {
1347                                         mode = atoi(pResp);
1348                                         respGetCbConfig.cbConfig.cbEnabled = mode;
1349
1350                                         pResp = g_slist_nth_data(tokens, 1);
1351                                         if (pResp) {
1352                                                 GSList *cb_tokens = NULL;
1353                                                 char *cb_mid_str = NULL;
1354                                                 int num_cb_tokens = 0;
1355                                                 char *mid_tok = NULL;
1356                                                 char *first_tok = NULL, *second_tok = NULL;
1357                                                 char *ptr = NULL;
1358
1359                                                 /* 0, 1, 5, 320-478, 922 */
1360                                                 cb_mid_str = tcore_at_tok_extract(pResp);
1361                                                 cb_tokens = tcore_at_tok_new((const char *)cb_mid_str);
1362
1363                                                 g_free(cb_mid_str);
1364
1365                                                 num_cb_tokens = g_slist_length(cb_tokens);
1366                                                 dbg("num_cb_tokens = %d", num_cb_tokens);
1367
1368                                                 if (num_cb_tokens == 0) {
1369                                                         if (mode == 1) { /* Enable all CBs */
1370                                                                 respGetCbConfig.cbConfig.msgIdRangeCount = 1;
1371                                                                 respGetCbConfig.cbConfig.msgIDs[0].net3gpp.fromMsgId = 0x0000;
1372                                                                 respGetCbConfig.cbConfig.msgIDs[0].net3gpp.toMsgId = SMS_GSM_SMS_CBMI_LIST_SIZE_MAX + 1;
1373                                                                 respGetCbConfig.cbConfig.msgIDs[0].net3gpp.selected = TRUE;
1374                                                                         respGetCbConfig.result = SMS_SENDSMS_SUCCESS;
1375                                                         } else { /* all CBs disabled */
1376                                                                 respGetCbConfig.cbConfig.msgIdRangeCount = 0;
1377                                                                 respGetCbConfig.cbConfig.msgIDs[0].net3gpp.selected = FALSE;
1378                                                                 respGetCbConfig.result = SMS_SENDSMS_SUCCESS;
1379                                                         }
1380                                                 } else {
1381                                                         respGetCbConfig.cbConfig.msgIdRangeCount = 0;
1382                                                         respGetCbConfig.cbConfig.msgIDs[0].net3gpp.selected = FALSE;
1383                                                         respGetCbConfig.result = SMS_SENDSMS_SUCCESS;
1384                                                 }
1385
1386                                                 for (i = 0; i < num_cb_tokens; i++) {
1387                                                         respGetCbConfig.cbConfig.msgIDs[i].net3gpp.selected = TRUE;
1388                                                         respGetCbConfig.cbConfig.msgIdRangeCount++;
1389
1390                                                         mid_tok = tcore_at_tok_nth(cb_tokens, i);
1391                                                         first_tok = strtok_r(mid_tok, "-", &ptr);
1392                                                         second_tok = strtok_r(NULL, "-", &ptr);
1393
1394                                                         if ((first_tok != NULL) && (second_tok != NULL)) {
1395                                                                 /* mids in range (320-478) */
1396                                                                 dbg("inside if mid_range");
1397                                                                 respGetCbConfig.cbConfig.msgIDs[i].net3gpp.fromMsgId = atoi(first_tok);
1398                                                                 respGetCbConfig.cbConfig.msgIDs[i].net3gpp.toMsgId = atoi(second_tok);
1399                                                         }  else {
1400                                                                 /* single mid value (0, 1, 5, 922) */
1401                                                                 respGetCbConfig.cbConfig.msgIDs[i].net3gpp.fromMsgId = atoi(mid_tok);
1402                                                                 respGetCbConfig.cbConfig.msgIDs[i].net3gpp.toMsgId = atoi(mid_tok);
1403                                                         }
1404                                                 }
1405                                         }
1406                                 }
1407                         } else {
1408                                 dbg("line is NULL");
1409                         }
1410                 } else {
1411                         dbg("atresp->lines is NULL");
1412                 }
1413         } else {
1414                 dbg("RESPONSE NOK");
1415         }
1416
1417         tcore_user_request_send_response(ur,
1418                 TRESP_SMS_GET_CB_CONFIG,
1419                 sizeof(struct tresp_sms_get_cb_config), &respGetCbConfig);
1420
1421         if (tokens)
1422                 tcore_at_tok_free(tokens);
1423 }
1424
1425 static void on_response_set_cb_config(TcorePending *pending,
1426         int data_len, const void *data, void *user_data)
1427 {
1428         /*
1429          * Response is expected in this format
1430          *      OK
1431          * or
1432          *      +CMS ERROR: <err>
1433          */
1434         UserRequest *ur;
1435         const TcoreATResponse *resp = data;
1436         int response = 0;
1437         const char *line = NULL;
1438         GSList *tokens = NULL;
1439
1440         struct tresp_sms_set_cb_config respSetCbConfig = {0, };
1441
1442         memset(&respSetCbConfig, 0, sizeof(struct tresp_sms_set_cb_config));
1443
1444         ur = tcore_pending_ref_user_request(pending);
1445         respSetCbConfig.result = SMS_SENDSMS_SUCCESS;
1446
1447         if (resp->success > 0) {
1448                 dbg("RESPONSE OK");
1449         } else {
1450                 dbg("RESPONSE NOK");
1451                 line = (const char *)resp->final_response;
1452                 tokens = tcore_at_tok_new(line);
1453
1454                 if (g_slist_length(tokens) < 1) {
1455                         dbg("err cause not specified or string corrupted");
1456                         respSetCbConfig.result = SMS_DEVICE_FAILURE;
1457                 } else {
1458                         response = atoi(g_slist_nth_data(tokens, 0));
1459                         dbg("response is %d", response);
1460                         /* TODO: CMEE error mapping is required. */
1461                         respSetCbConfig.result = SMS_DEVICE_FAILURE;
1462                 }
1463         }
1464
1465         if (!ur) {
1466                 dbg("no user_request");
1467                 return;
1468         }
1469
1470         tcore_user_request_send_response(ur,
1471                 TRESP_SMS_SET_CB_CONFIG,
1472                 sizeof(struct tresp_sms_set_cb_config), &respSetCbConfig);
1473
1474         if (tokens)
1475                 tcore_at_tok_free(tokens);
1476 }
1477
1478 static void on_response_set_mem_status(TcorePending *p,
1479         int data_len, const void *data, void *user_data)
1480 {
1481         UserRequest *ur;
1482         struct tresp_sms_set_mem_status respSetMemStatus = {0, };
1483         const TcoreATResponse *resp = data;
1484
1485         memset(&respSetMemStatus, 0, sizeof(struct tresp_sms_set_mem_status));
1486
1487         if (resp->success > 0) {
1488                 dbg("RESPONSE OK");
1489                 respSetMemStatus.result = SMS_SENDSMS_SUCCESS;
1490         } else {
1491                 dbg("RESPONSE NOK");
1492                 respSetMemStatus.result = SMS_DEVICE_FAILURE;
1493         }
1494
1495         ur = tcore_pending_ref_user_request(p);
1496         if (!ur) {
1497                 dbg("no user_request");
1498                 return;
1499         }
1500
1501         tcore_user_request_send_response(ur,
1502                 TRESP_SMS_SET_MEM_STATUS,
1503                 sizeof(struct tresp_sms_set_mem_status), &respSetMemStatus);
1504 }
1505
1506 static void on_response_set_msg_status(TcorePending *pending,
1507         int data_len, const void *data, void *user_data)
1508 {
1509         UserRequest *ur;
1510         struct tresp_sms_set_msg_status respMsgStatus = {0, };
1511         const TcoreATResponse *atResp = data;
1512         int response = 0, sw1 = 0, sw2 = 0;
1513         const char *line = NULL;
1514         char *pResp = NULL;
1515         GSList *tokens = NULL;
1516
1517         dbg("Entry");
1518
1519         memset(&respMsgStatus, 0, sizeof(struct tresp_sms_set_msg_status));
1520         respMsgStatus.result = SMS_DEVICE_FAILURE;
1521
1522         ur = tcore_pending_ref_user_request(pending);
1523
1524         if (atResp->success > 0) {
1525                 dbg("RESPONSE OK");
1526
1527                 if (atResp->lines) {
1528                         line = (const char *)atResp->lines->data;
1529                         tokens = tcore_at_tok_new(line);
1530                         pResp = g_slist_nth_data(tokens, 0);
1531                         if (pResp != NULL)
1532                                 sw1 = atoi(pResp);
1533                         else
1534                                 dbg("sw1 is NULL");
1535
1536                         pResp = g_slist_nth_data(tokens, 1);
1537                         if (pResp != NULL) {
1538                                 sw2 = atoi(pResp);
1539                                 if ((sw1 == AT_SW1_SUCCESS) && (sw2 == 0))
1540                                         respMsgStatus.result = SMS_SENDSMS_SUCCESS;
1541                         } else {
1542                                 dbg("sw2 is NULL");
1543                         }
1544                         pResp = g_slist_nth_data(tokens, 3);
1545
1546                         if (pResp != NULL) {
1547                                 response = atoi(pResp);
1548                                 dbg("response is %d", response);
1549                         }
1550                 } else {
1551                         dbg("No lines");
1552                 }
1553         } else {
1554                 dbg("RESPONSE NOK");
1555         }
1556
1557         tcore_user_request_send_response(ur,
1558                 TRESP_SMS_SET_MSG_STATUS,
1559                 sizeof(struct tresp_sms_set_msg_status), &respMsgStatus);
1560
1561         if (tokens)
1562                 tcore_at_tok_free(tokens);
1563
1564         dbg("Exit");
1565 }
1566
1567 static void on_response_get_sms_params(TcorePending *pending,
1568         int data_len, const void *data, void *user_data)
1569 {
1570         UserRequest *ur;
1571         struct tresp_sms_get_params respGetParams ;
1572         const TcoreATResponse *atResp = data;
1573         int sw1 = 0, sw2 = 0;
1574         const char *line = NULL;
1575         char *pResp = NULL;
1576         GSList *tokens = NULL;
1577         char *hexData = NULL;
1578         char *recordData = NULL;
1579         int i = 0;
1580
1581         memset(&respGetParams, 0, sizeof(struct tresp_sms_get_params));
1582         respGetParams.result = SMS_DEVICE_FAILURE;
1583
1584         ur = tcore_pending_ref_user_request(pending);
1585
1586         if (atResp->success > 0) {
1587                 dbg("RESPONSE OK");
1588
1589                 if (atResp->lines) {
1590                         line = (const char *)atResp->lines->data;
1591                         tokens = tcore_at_tok_new(line);
1592                         pResp = g_slist_nth_data(tokens, 0);
1593                         if (pResp != NULL) {
1594                                 sw1 = atoi(pResp);
1595                                 dbg("sw1 is %d", sw1);
1596                         } else {
1597                                 dbg("sw1 is NULL");
1598                         }
1599                         pResp = g_slist_nth_data(tokens, 1);
1600                         if (pResp != NULL) {
1601                                 sw2 = atoi(pResp);
1602                                 dbg("sw2 is %d", sw2);
1603                                 if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91)
1604                                         respGetParams.result = SMS_SENDSMS_SUCCESS;
1605                         } else {
1606                                 dbg("sw2 is NULL");
1607                         }
1608                         pResp = g_slist_nth_data(tokens, 2);
1609                         if (pResp != NULL) {
1610                                 hexData = tcore_at_tok_extract(pResp);
1611                                 if (hexData) {
1612                                         recordData = util_hexStringToBytes(hexData);
1613                                         tcore_util_hex_dump("    ", strlen(hexData) / 2, recordData);
1614
1615                                         respGetParams.paramsInfo.recordLen = strlen(hexData) / 2;
1616
1617                                         util_sms_decode_smsParameters((unsigned char *)recordData, strlen(hexData) / 2, &(respGetParams.paramsInfo));
1618                                         respGetParams.result = SMS_SENDSMS_SUCCESS;
1619
1620                                         for (i = 0; i < (int) respGetParams.paramsInfo.tpSvcCntrAddr.dialNumLen; i++)
1621                                                 dbg("SCAddr = %d [%02x]", i, respGetParams.paramsInfo.tpSvcCntrAddr.diallingNum[i]);
1622
1623                                         g_free(recordData);
1624                                         g_free(hexData);
1625                                 }
1626                         } else {
1627                                 dbg("No response");
1628                         }
1629                         tcore_at_tok_free(tokens);
1630                 }
1631         } else {
1632                 dbg("RESPONSE NOK");
1633         }
1634
1635         tcore_user_request_send_response(ur,
1636                 TRESP_SMS_GET_PARAMS,
1637                 sizeof(struct tresp_sms_get_params), &respGetParams);
1638
1639         dbg("Exit");
1640 }
1641
1642 static void on_response_set_sms_params(TcorePending *pending,
1643         int data_len, const void *data, void *user_data)
1644 {
1645         UserRequest *ur;
1646         struct tresp_sms_set_params respSetParams = {0, };
1647         const TcoreATResponse *atResp = data;
1648         int sw1 = 0, sw2 = 0;
1649         const char *line = NULL;
1650         char *pResp = NULL;
1651         GSList *tokens = NULL;
1652
1653
1654         memset(&respSetParams, 0, sizeof(struct tresp_sms_set_params));
1655         ur = tcore_pending_ref_user_request(pending);
1656
1657         respSetParams.result = SMS_DEVICE_FAILURE;
1658
1659         if (atResp->success > 0) {
1660                 dbg("RESPONSE OK");
1661
1662                 if (atResp->lines) {
1663                         line = (const char *)atResp->lines->data;
1664                         tokens = tcore_at_tok_new(line);
1665                         pResp = g_slist_nth_data(tokens, 0);
1666                         if (pResp != NULL)
1667                                 sw1 = atoi(pResp);
1668                         else
1669                                 dbg("sw1 is NULL");
1670
1671                         pResp = g_slist_nth_data(tokens, 1);
1672                         if (pResp != NULL) {
1673                                 sw2 = atoi(pResp);
1674                                 if (((sw1 == AT_SW1_SUCCESS) && (sw2 == AT_SW2_SUCCESS)) || (sw1 == 0x91))
1675                                         respSetParams.result = SMS_SENDSMS_SUCCESS;
1676                         } else {
1677                                 dbg("sw2 is NULL");
1678                         }
1679                 } else {
1680                         dbg("No lines");
1681                 }
1682         } else {
1683                 dbg("RESPONSE NOK");
1684         }
1685
1686         tcore_user_request_send_response(ur,
1687                 TRESP_SMS_SET_PARAMS,
1688                 sizeof(struct tresp_sms_set_params), &respSetParams);
1689
1690         if (tokens)
1691                 tcore_at_tok_free(tokens);
1692
1693         dbg("Exit");
1694 }
1695
1696 static void on_response_get_paramcnt(TcorePending *p,
1697         int data_len, const void *data, void *user_data)
1698 {
1699         UserRequest *ur = NULL;
1700         struct tresp_sms_get_paramcnt respGetParamCnt = {0, };
1701         const TcoreATResponse *atResp = data;
1702         char *line = NULL, *pResp = NULL;
1703         int sw1 = 0, sw2 = 0, *smsp_record_len = NULL;
1704         int sim_type = 0;
1705         GSList *tokens = NULL;
1706         CoreObject *co_sim = NULL;  /* need this to get the sim type GSM/USIM */
1707         TcorePlugin *plugin = NULL;
1708
1709         dbg("Entry");
1710
1711         ur = tcore_pending_ref_user_request(p);
1712         respGetParamCnt.result = SMS_DEVICE_FAILURE;
1713
1714         if (atResp->success > 0) {
1715                 dbg("RESPONSE OK");
1716
1717                 if (atResp->lines) {
1718                         line = (char *)atResp->lines->data;
1719
1720                         dbg("line is %s", line);
1721
1722                         tokens = tcore_at_tok_new(line);
1723                         pResp = g_slist_nth_data(tokens, 0);
1724                         if (pResp != NULL)
1725                                 sw1 = atoi(pResp);
1726                         else
1727                                 dbg("sw1 is NULL");
1728
1729                         pResp = g_slist_nth_data(tokens, 1);
1730                         if (pResp != NULL) {
1731                                 sw2 = atoi(pResp);
1732                                 if ((sw1 == 144) && (sw2 == 0))
1733                                         respGetParamCnt.result = SMS_SENDSMS_SUCCESS;
1734                         } else {
1735                                 dbg("sw2 is NULL");
1736                         }
1737                         pResp = g_slist_nth_data(tokens, 2);
1738                         if (pResp != NULL) {
1739                                 char *hexData = NULL;
1740                                 char *recordData = NULL;
1741                                 hexData = tcore_at_tok_extract(pResp);
1742
1743                                 /*1. SIM access success case*/
1744                                 if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
1745                                         unsigned char tag_len = 0; /* 1 or 2 bytes ??? */
1746                                         int record_len = 0;
1747                                         char num_of_records = 0;
1748                                         unsigned char file_id_len = 0;
1749                                         unsigned short file_id = 0;
1750                                         unsigned short file_size = 0;
1751                                         unsigned short file_type = 0;
1752                                         unsigned short arr_file_id = 0;
1753                                         int arr_file_id_rec_num = 0;
1754
1755                                         /* handling only last 3 bits */
1756                                         unsigned char file_type_tag = 0x07;
1757                                         unsigned char *ptr_data;
1758
1759                                         recordData = util_hexStringToBytes(hexData);
1760                                         if (!recordData) {
1761                                                 err("util_hexStringToBytes Failed!!");
1762                                                 tcore_at_tok_free(tokens);
1763                                                 return;
1764                                         }
1765                                         tcore_util_hex_dump("    ", strlen(hexData)/2, recordData);
1766
1767                                         ptr_data = (unsigned char *)recordData;
1768
1769                                         co_sim = tcore_plugin_ref_core_object(tcore_pending_ref_plugin(p), CORE_OBJECT_TYPE_SIM);
1770                                         sim_type = tcore_sim_get_type(co_sim);
1771                                         dbg("sim type is %d", sim_type);
1772
1773                                         if (sim_type ==  SIM_TYPE_USIM) {
1774                                                 /*
1775                                                  * ETSI TS 102 221 v7.9.0
1776                                                  * - Response Data
1777                                                  * '62' FCP template tag
1778                                                  * - Response for an EF
1779                                                  * '82' M       File Descriptor
1780                                                  * '83' M       File Identifier
1781                                                  * 'A5' O       Proprietary information
1782                                                  * '8A' M       Life Cycle Status Integer
1783                                                  * '8B', '8C' or 'AB'   C1      Security attributes
1784                                                  * '80' M       File size
1785                                                  * '81' O       Total file size
1786                                                  * '88' O       Short File Identifier (SFI)
1787                                                  */
1788
1789                                                 /* rsim.res_len  has complete data length received  */
1790
1791                                                 /* FCP template tag - File Control Parameters tag*/
1792                                                 if (*ptr_data == 0x62) {
1793                                                         /* parse complete FCP tag*/
1794                                                         /* increment to next byte */
1795                                                         ptr_data++;
1796                                                         tag_len = *ptr_data++;
1797                                                         dbg("tag_len: [%d]", tag_len);
1798
1799                                                         /* FCP file descriptor - file type, accessibility, DF, ADF etc*/
1800                                                         if (*ptr_data == 0x82) {
1801                                                                 /* increment to next byte */
1802                                                                 ptr_data++;
1803
1804                                                                 /*2 or 5 value*/
1805                                                                 ptr_data++;
1806
1807                                                                 /* unsigned char file_desc_len = *ptr_data++;*/
1808                                                                 /* dbg("file descriptor length: [%d]", file_desc_len);*/
1809                                                                 /* TBD:  currently capture only file type : ignore sharable, non sharable, working, internal etc*/
1810                                                                 /* consider only last 3 bits*/
1811                                                                 file_type_tag = file_type_tag & (*ptr_data);
1812
1813                                                                 switch (file_type_tag) {
1814                                                                 /* increment to next byte */
1815                                                                 ptr_data++;
1816
1817                                                                 case 0x1:
1818                                                                         dbg("Getting FileType: [Transparent file type]");
1819                                                                         /* increment to next byte */
1820                                                                         ptr_data++;
1821                                                                         file_type = 0x01; /* SIM_FTYPE_TRANSPARENT */
1822
1823                                                                         /* data coding byte - value 21 */
1824                                                                         ptr_data++;
1825                                                                 break;
1826
1827                                                                 case 0x2:
1828                                                                         dbg("Getting FileType: [Linear fixed file type]");
1829                                                                         /* increment to next byte */
1830                                                                         ptr_data++;
1831
1832                                                                         /* data coding byte - value 21 */
1833                                                                         ptr_data++;
1834
1835                                                                         /* 2bytes */
1836                                                                         memcpy(&record_len, ptr_data, 2);
1837
1838                                                                         /* swap bytes */
1839                                                                         record_len = SMS_SWAPBYTES16(record_len);
1840                                                                         ptr_data = ptr_data + 2;
1841                                                                         num_of_records = *ptr_data++;
1842
1843                                                                         /* Data lossy conversation from enum (int) to unsigned char */
1844                                                                         file_type = 0x02;       /* SIM_FTYPE_LINEAR_FIXED */
1845                                                                 break;
1846
1847                                                                 case 0x6:
1848                                                                         dbg(" Cyclic fixed file type");
1849                                                                         /* increment to next byte */
1850                                                                         ptr_data++;
1851
1852                                                                         /* data coding byte - value 21 */
1853                                                                         ptr_data++;
1854
1855                                                                         /* 2bytes */
1856                                                                         memcpy(&record_len, ptr_data, 2);
1857
1858                                                                         /* swap bytes  */
1859                                                                         record_len = SMS_SWAPBYTES16(record_len);
1860                                                                         ptr_data = ptr_data + 2;
1861                                                                         num_of_records = *ptr_data++;
1862                                                                         file_type = 0x04;       /* SIM_FTYPE_CYCLIC */
1863                                                                 break;
1864
1865                                                                 default:
1866                                                                         dbg("not handled file type [0x%x]", *ptr_data);
1867                                                                 break;
1868                                                                 }
1869                                                         } else {
1870                                                                 dbg("INVALID FCP received - DEbug!");
1871                                                                 g_free(hexData);
1872                                                                 g_free(recordData);
1873                                                                 tcore_at_tok_free(tokens);
1874                                                                 return;
1875                                                         }
1876
1877                                                         /*
1878                                                          * File identifier - file id??
1879                                                          *
1880                                                          * 0x84, 0x85, 0x86 etc are currently ignored and not handled
1881                                                          */
1882                                                         if (*ptr_data == 0x83) {
1883                                                                 /* increment to next byte */
1884                                                                 ptr_data++;
1885                                                                 file_id_len = *ptr_data++;
1886                                                                 memcpy(&file_id, ptr_data, file_id_len);
1887
1888                                                                 /* swap bytes */
1889                                                                 file_id = SMS_SWAPBYTES16(file_id);
1890                                                                 ptr_data = ptr_data + 2;
1891                                                                 dbg("Getting FileID=[0x%x]", file_id);
1892                                                         } else {
1893                                                                 dbg("INVALID FCP received - DEbug!");
1894                                                                 g_free(hexData);
1895                                                                 g_free(recordData);
1896                                                                 tcore_at_tok_free(tokens);
1897                                                                 return;
1898                                                         }
1899
1900                                                         /* proprietary information  */
1901                                                         if (*ptr_data == 0xA5) {
1902                                                                 unsigned short prop_len;
1903                                                                 /* increment to next byte */
1904                                                                 ptr_data++;
1905
1906                                                                 /* length */
1907                                                                 prop_len = *ptr_data;
1908
1909                                                                 /* skip data */
1910                                                                 ptr_data = ptr_data + prop_len + 1;
1911                                                         } else {
1912                                                                 dbg("INVALID FCP received - DEbug!");
1913                                                         }
1914
1915                                                         /* life cycle status integer [8A][length:0x01][status]*/
1916                                                         /*
1917                                                          * status info b8~b1
1918                                                          * 00000000 : No information given
1919                                                          * 00000001 : creation state
1920                                                          * 00000011 : initialization state
1921                                                          * 000001-1 : operation state -activated
1922                                                          * 000001-0 : operation state -deactivated
1923                                                          * 000011-- : Termination state
1924                                                          * b8~b5 !=0, b4~b1=X : Proprietary
1925                                                          * Any other value : RFU
1926                                                          */
1927                                                         if (*ptr_data == 0x8A) {
1928                                                                 /* increment to next byte */
1929                                                                 ptr_data++;
1930                                                                 /* length - value 1 */
1931                                                                 ptr_data++;
1932
1933                                                                 switch (*ptr_data) {
1934                                                                 case 0x04:
1935                                                                 case 0x06:
1936                                                                         dbg("[RX] Operation State: DEACTIVATED");
1937                                                                         ptr_data++;
1938                                                                 break;
1939
1940                                                                 case 0x05:
1941                                                                 case 0x07:
1942                                                                         dbg("[RX] Operation State: ACTIVATED");
1943                                                                         ptr_data++;
1944                                                                 break;
1945
1946                                                                 default:
1947                                                                         dbg("[RX] DEBUG! LIFE CYCLE STATUS: [0x%x]", *ptr_data);
1948                                                                         ptr_data++;
1949                                                                 break;
1950                                                                 }
1951                                                         }
1952
1953                                                         /* related to security attributes : currently not handled*/
1954                                                         if (*ptr_data == 0x86 || *ptr_data == 0x8B || *ptr_data == 0x8C || *ptr_data == 0xAB) {
1955                                                                 /* increment to next byte */
1956                                                                 ptr_data++;
1957
1958                                                                 /* if tag length is 3 */
1959                                                                 if (*ptr_data == 0x03) {
1960                                                                         /* increment to next byte */
1961                                                                         ptr_data++;
1962
1963                                                                         /* EFARR file id */
1964                                                                         memcpy(&arr_file_id, ptr_data, 2);
1965
1966                                                                         /* swap byes */
1967                                                                         arr_file_id = SMS_SWAPBYTES16(arr_file_id);
1968                                                                         ptr_data = ptr_data + 2;
1969                                                                         arr_file_id_rec_num = *ptr_data++;
1970                                                                         dbg("arr_file_id_rec_num: [%d]", arr_file_id_rec_num);
1971                                                                 } else {
1972                                                                         /* if tag length is not 3 */
1973                                                                         /* ignoring bytes       */
1974                                                                         dbg("Useless security attributes, so jump to next tag");
1975                                                                         ptr_data = ptr_data + (*ptr_data + 1);
1976                                                                 }
1977                                                         } else {
1978                                                                 dbg("INVALID FCP received[0x%x] - DEbug!", *ptr_data);
1979                                                                 g_free(hexData);
1980                                                                 g_free(recordData);
1981                                                                 tcore_at_tok_free(tokens);
1982                                                                 return;
1983                                                         }
1984
1985                                                         dbg("Current ptr_data value is [%x]", *ptr_data);
1986
1987                                                         /* file size excluding structural info*/
1988                                                         if (*ptr_data == 0x80) {
1989                                                                 /*
1990                                                                  * for EF file size is body of file and for Linear or cyclic it is
1991                                                                  * number of recXsizeof(one record)
1992                                                                  */
1993                                                                 /* increment to next byte */
1994                                                                 ptr_data++;
1995
1996                                                                 /* length is 1 byte - value is 2 bytes or more */
1997                                                                 ptr_data++;
1998                                                                 memcpy(&file_size, ptr_data, 2);
1999
2000                                                                 /* swap bytes */
2001                                                                 file_size = SMS_SWAPBYTES16(file_size);
2002                                                                 ptr_data = ptr_data + 2;
2003                                                         } else {
2004                                                                 dbg("INVALID FCP received - DEbug!");
2005                                                                 g_free(hexData);
2006                                                                 g_free(recordData);
2007                                                                 tcore_at_tok_free(tokens);
2008                                                                 return;
2009                                                         }
2010
2011                                                         /* total file size including structural info*/
2012                                                         if (*ptr_data == 0x81) {
2013                                                                 int len;
2014                                                                 /* increment to next byte */
2015                                                                 ptr_data++;
2016
2017                                                                 /* length */
2018                                                                 len = *ptr_data;
2019                                                                 dbg("len: [%d]", len);
2020
2021                                                                 /* ignored bytes */
2022                                                                 ptr_data = ptr_data + 3;
2023                                                         } else {
2024                                                                 dbg("INVALID FCP received - DEbug!");
2025                                                                 /* 0x81 is optional tag?? check out! so do not return -1 from here! */
2026                                                                 /* return -1; */
2027                                                         }
2028                                                         /*short file identifier ignored*/
2029                                                         if (*ptr_data == 0x88) {
2030                                                                 dbg("0x88: Do Nothing");
2031                                                                 /*DO NOTHING*/
2032                                                         }
2033                                                 } else {
2034                                                         dbg("INVALID FCP received - DEbug!");
2035                                                         g_free(hexData);
2036                                                         g_free(recordData);
2037                                                         tcore_at_tok_free(tokens);
2038                                                         return;
2039                                                 }
2040                                         } else if (sim_type == SIM_TYPE_GSM) {
2041                                                 unsigned char gsm_specific_file_data_len = 0;
2042                                                 /* ignore RFU byte1 and byte2 */
2043                                                 ptr_data++;
2044                                                 ptr_data++;
2045
2046                                                 /* file size */
2047                                                 memcpy(&file_size, ptr_data, 2);
2048
2049                                                 /* swap bytes */
2050                                                 file_size = SMS_SWAPBYTES16(file_size);
2051
2052                                                 /* parsed file size */
2053                                                 ptr_data = ptr_data + 2;
2054
2055                                                 /*  file id  */
2056                                                 memcpy(&file_id, ptr_data, 2);
2057                                                 file_id = SMS_SWAPBYTES16(file_id);
2058                                                 dbg(" FILE id --> [%x]", file_id);
2059                                                 ptr_data = ptr_data + 2;
2060
2061                                                 /* save file type - transparent, linear fixed or cyclic */
2062                                                 file_type_tag = (*(ptr_data + 7));
2063
2064                                                 switch (*ptr_data) {
2065                                                 case 0x0:
2066                                                         /* RFU file type */
2067                                                         dbg(" RFU file type- not handled - Debug!");
2068                                                 break;
2069
2070                                                 case 0x1:
2071                                                         /* MF file type */
2072                                                         dbg(" MF file type - not handled - Debug!");
2073                                                 break;
2074
2075                                                 case 0x2:
2076                                                         /* DF file type */
2077                                                         dbg(" DF file type - not handled - Debug!");
2078                                                 break;
2079
2080                                                 case 0x4:
2081                                                         /* EF file type */
2082                                                         dbg(" EF file type [%d] ", file_type_tag);
2083                                                         /* increment to next byte */
2084                                                         ptr_data++;
2085
2086                                                         if (file_type_tag == 0x00 || file_type_tag == 0x01) {
2087                                                                 /* increament to next byte as this byte is RFU */
2088                                                                 ptr_data++;
2089                                                                 file_type = (file_type_tag == 0x00) ? 0x01 : 0x02; /* SIM_FTYPE_TRANSPARENT:SIM_FTYPE_LINEAR_FIXED; */
2090                                                         } else {
2091                                                                 /* increment to next byte */
2092                                                                 ptr_data++;
2093
2094                                                                 /* For a cyclic EF all bits except bit 7 are RFU; b7=1 indicates that */
2095                                                                 /* the INCREASE command is allowed on the selected cyclic file. */
2096                                                                 file_type = 0x04;       /* SIM_FTYPE_CYCLIC; */
2097                                                         }
2098
2099                                                         /* bytes 9 to 11 give SIM file access conditions */
2100                                                         ptr_data++;
2101
2102                                                         /* byte 10 has one nibble that is RF U and another for INCREASE which is not used currently */
2103                                                         ptr_data++;
2104
2105                                                         /* byte 11 is invalidate and rehabilate nibbles */
2106                                                         ptr_data++;
2107
2108                                                         /* byte 12 - file status */
2109                                                         ptr_data++;
2110
2111                                                         /* byte 13 - GSM specific data */
2112                                                         gsm_specific_file_data_len = *ptr_data;
2113                                                         dbg("gsm_specific_file_data_len: [%d]", gsm_specific_file_data_len);
2114                                                         ptr_data++;
2115
2116                                                         /* byte 14 - structure of EF - transparent or linear or cyclic, already saved above */
2117                                                         ptr_data++;
2118
2119                                                         /* byte 15 - length of record for linear and cyclic, for transparent it is set to 0x00. */
2120                                                         record_len = *ptr_data;
2121                                                         dbg("record length[%d], file size[%d]", record_len, file_size);
2122
2123                                                         if (record_len != 0)
2124                                                                 num_of_records = (file_size / record_len);
2125
2126                                                         dbg("Number of records [%d]", num_of_records);
2127                                                 break;
2128
2129                                                 default:
2130                                                         dbg(" not handled file type");
2131                                                 break;
2132                                                 }
2133                                         } else {
2134                                                 dbg(" Card Type - UNKNOWN  [%d]", sim_type);
2135                                         }
2136
2137                                         dbg("EF[0x%x] size[%ld] Type[0x%x] NumOfRecords[%ld] RecordLen[%ld]",
2138                                                 file_id, file_size, file_type, num_of_records, record_len);
2139
2140                                         respGetParamCnt.recordCount = num_of_records;
2141                                         respGetParamCnt.result = SMS_SUCCESS;
2142
2143                                         /* TO Store smsp record length in the property */
2144                                         plugin = tcore_pending_ref_plugin(p);
2145                                         smsp_record_len = tcore_plugin_ref_property(plugin, "SMSPRECORDLEN");
2146                                         memcpy(smsp_record_len, &record_len, sizeof(int));
2147
2148                                         g_free(recordData);
2149                                         g_free(hexData);
2150                                 } else {
2151                                         /*2. SIM access fail case*/
2152                                         dbg("SIM access fail");
2153                                         respGetParamCnt.result = SMS_UNKNOWN;
2154                                 }
2155                         } else {
2156                                 dbg("presp is NULL");
2157                         }
2158                 } else {
2159                         dbg("line is blank");
2160                 }
2161         } else {
2162                 dbg("RESPONSE NOK");
2163         }
2164
2165         tcore_user_request_send_response(ur,
2166                 TRESP_SMS_GET_PARAMCNT,
2167                 sizeof(struct tresp_sms_get_paramcnt), &respGetParamCnt);
2168
2169         if (tokens)
2170                 tcore_at_tok_free(tokens);
2171
2172         dbg("Exit");
2173         return;
2174 }
2175
2176 static void _response_get_efsms_data(TcorePending *p, int data_len, const void *data, void *user_data)
2177 {
2178         UserRequest *ur = NULL;
2179         UserRequest *dup_ur = NULL;
2180         struct tresp_sms_set_msg_status resp_msg_status = {0, };
2181         const struct treq_sms_set_msg_status *req_msg_status = NULL ;
2182
2183         const TcoreATResponse *resp = data;
2184         char *encoded_data = NULL;
2185         char msg_status = 0;
2186         char *pResp = NULL;
2187         GSList *tokens = NULL;
2188         const char *line = NULL;
2189         int sw1 = 0;
2190         int sw2 = 0;
2191
2192         TcoreHal *hal = NULL;
2193         TcoreATRequest *atreq = NULL;
2194         TcorePending *pending = NULL;
2195         gchar *cmd_str = NULL;
2196
2197         ur = tcore_pending_ref_user_request(p);
2198
2199         req_msg_status = tcore_user_request_ref_data(ur, NULL);
2200
2201         resp_msg_status.result = SMS_DEVICE_FAILURE;
2202
2203         hal = tcore_object_get_hal(tcore_pending_ref_core_object(pending));
2204         dbg("msgStatus: [%x], index [%x]", req_msg_status->msgStatus, req_msg_status->index);
2205
2206         if (resp->success <= 0)
2207                 goto OUT;
2208
2209         dbg("RESPONSE OK");
2210         if (resp->lines) {
2211                 line = (const char *)resp->lines->data;
2212                 tokens = tcore_at_tok_new(line);
2213                 if (g_slist_length(tokens) != 3) {
2214                         msg("invalid message");
2215                         goto OUT;
2216                 }
2217         }
2218         sw1 = atoi(g_slist_nth_data(tokens, 0));
2219         sw2 = atoi(g_slist_nth_data(tokens, 1));
2220         pResp = g_slist_nth_data(tokens, 2);
2221
2222         if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
2223                 switch (req_msg_status->msgStatus) {
2224                 case SMS_STATUS_READ:
2225                         msg_status = 0x01;
2226                 break;
2227
2228                 case SMS_STATUS_UNREAD:
2229                         msg_status = 0x03;
2230                 break;
2231
2232                 case SMS_STATUS_UNSENT:
2233                         msg_status = 0x07;
2234                 break;
2235
2236                 case SMS_STATUS_SENT:
2237                         msg_status = 0x05;
2238                 break;
2239
2240                 case SMS_STATUS_DELIVERED:
2241                         msg_status = 0x1D;
2242                 break;
2243
2244                 case SMS_STATUS_DELIVERY_UNCONFIRMED:
2245                         msg_status = 0xD;
2246                 break;
2247
2248                 case SMS_STATUS_MESSAGE_REPLACED:
2249                 case SMS_STATUS_RESERVED:
2250                 default:
2251                         msg_status = 0x03;
2252                 break;
2253                 }
2254
2255                 encoded_data = tcore_at_tok_extract(pResp);
2256                 if (!encoded_data) {
2257                         err("Encoded data is NULL");
2258                         goto OUT;
2259                 }
2260
2261                 /* Overwrite Status byte information */
2262                 util_byte_to_hex((const char *)&msg_status, (char *)encoded_data, 1);
2263
2264                 /* Update EF-SMS with just status byte overwritten, rest 175 bytes are same as received in read information */
2265                 cmd_str = g_strdup_printf("AT+CRSM=220, 28476, %d, 4, %d, \"%s\"", (req_msg_status->index+1), PDU_LEN_MAX, encoded_data);
2266                 atreq = tcore_at_request_new((const char *)cmd_str, "+CRSM", TCORE_AT_SINGLELINE);
2267                 pending = tcore_pending_new(tcore_pending_ref_core_object(pending), 0);
2268                 if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2269                         err("Out of memory. Unable to proceed");
2270                         dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2271
2272                         g_free(cmd_str);
2273                         g_free(encoded_data);
2274                         util_sms_free_memory(atreq);
2275                         util_sms_free_memory(pending);
2276
2277                         goto OUT;
2278                 }
2279
2280                 tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
2281
2282                 dup_ur = tcore_user_request_ref(ur);
2283
2284                 tcore_pending_set_request_data(pending, 0, atreq);
2285                 tcore_pending_set_response_callback(pending, on_response_set_msg_status, NULL);
2286                 tcore_pending_link_user_request(pending, dup_ur);
2287                 tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
2288                 tcore_hal_send_request(hal, pending);
2289
2290                 g_free(cmd_str);
2291                 g_free(encoded_data);
2292
2293                 resp_msg_status.result = SMS_SENDSMS_SUCCESS;
2294         }
2295
2296 OUT:
2297         if (tokens)
2298                 tcore_at_tok_free(tokens);
2299
2300         tcore_user_request_send_response(ur,
2301                 TRESP_SMS_SET_MSG_STATUS,
2302                 sizeof(struct tresp_sms_set_msg_status), &resp_msg_status);
2303
2304         dbg("Exit");
2305
2306         return;
2307 }
2308
2309 /*
2310  * Requests
2311  */
2312 static TReturn send_umts_msg(CoreObject *co_sms, UserRequest *ur)
2313 {
2314         const struct treq_sms_send_msg *send_msg;
2315         const unsigned char *tpdu_byte_data;
2316         const unsigned char *sca_byte_data;
2317         int tpdu_byte_len;
2318         int pdu_byte_len;
2319         int pdu_hex_len = 0;
2320         char buf[HEX_PDU_LEN_MAX];
2321         char pdu[PDU_LEN_MAX];
2322         char *cmd_str;
2323         int mms = 0;
2324         TReturn ret;
2325
2326         dbg("Enter");
2327
2328         send_msg = tcore_user_request_ref_data(ur, NULL);
2329
2330         /* Validating the Message Format */
2331         if (SMS_NETTYPE_3GPP == send_msg->msgDataPackage.format) {
2332                 info("3gpp format received");
2333         } else {
2334                 info("invalid format received");
2335                 return TCORE_RETURN_EINVAL;
2336         }
2337
2338         tpdu_byte_data = send_msg->msgDataPackage.tpduData;
2339         sca_byte_data = send_msg->msgDataPackage.sca;
2340
2341
2342         /* TPDU length is in byte */
2343         tpdu_byte_len = send_msg->msgDataPackage.msgLength;
2344         dbg("TDPU length: [%d]", tpdu_byte_len);
2345         dbg("SCA semi-octet length: [%d]", sca_byte_data[0]);
2346
2347         /* Use same Radio Resource Channel */
2348         mms = send_msg->more;
2349
2350         /* Prepare PDU for hex encoding */
2351         pdu_byte_len = __util_sms_encode_pdu(sca_byte_data, tpdu_byte_data,
2352                                                 tpdu_byte_len, pdu);
2353
2354         pdu_hex_len = (int) __util_sms_encode_hex((unsigned char *)pdu,
2355                                                 pdu_byte_len, buf);
2356
2357         dbg("PDU hexadecimal length: [%d]", pdu_hex_len);
2358
2359         if (mms > 0) {
2360                 cmd_str = g_strdup_printf("AT+CMMS=%d", mms);
2361
2362                 ret = tcore_prepare_and_send_at_request(co_sms, cmd_str, NULL,
2363                                         TCORE_AT_NO_RESULT, NULL, NULL, NULL,
2364                                         on_confirmation_sms_message_send,
2365                                         NULL, 0, NULL, NULL);
2366                 if (ret != TCORE_RETURN_SUCCESS) {
2367                         err("Failed to prepare and send AT request");
2368                         goto error;
2369                 }
2370
2371                 g_free(cmd_str);
2372         }
2373
2374         cmd_str = g_strdup_printf("AT+CMGS=%d\r%s\x1A", tpdu_byte_len, buf);
2375
2376         ret = tcore_prepare_and_send_at_request(co_sms, cmd_str, "+CMGS:",
2377                                 TCORE_AT_SINGLELINE, ur,
2378                                 on_response_send_umts_msg, NULL,
2379                                 on_confirmation_sms_message_send, NULL,
2380                                 0, NULL, NULL);
2381         if (ret != TCORE_RETURN_SUCCESS)
2382                 err("Failed to prepare and send AT request");
2383
2384 error:
2385         g_free(cmd_str);
2386
2387         dbg("Exit");
2388
2389         return ret;
2390 }
2391
2392 static TReturn read_msg(CoreObject *obj, UserRequest *ur)
2393 {
2394         gchar *cmd_str = NULL;
2395         TcoreHal *hal = NULL;
2396         TcoreATRequest *atreq = NULL;
2397         TcorePending *pending = NULL;
2398         const struct treq_sms_read_msg *readMsg = NULL;
2399
2400         dbg("Entry");
2401
2402         readMsg = tcore_user_request_ref_data(ur, NULL);
2403         hal = tcore_object_get_hal(obj);
2404         if (NULL == readMsg || NULL == hal) {
2405                 err("NULL input. Unable to proceed");
2406                 dbg("readMsg: [%p], hal: [%p]", readMsg, hal);
2407
2408                 dbg("Exit");
2409                 return TCORE_RETURN_EINVAL;
2410         }
2411
2412         if (FALSE == tcore_hal_get_power_state(hal)) {
2413                 dbg("cp not ready/n");
2414                 return TCORE_RETURN_ENOSYS;
2415         }
2416         dbg("index: [%d]", readMsg->index);
2417
2418         cmd_str = g_strdup_printf("AT+CMGR=%d", readMsg->index);
2419         atreq = tcore_at_request_new((const char *)cmd_str, "+CMGR", TCORE_AT_PDU);
2420         pending = tcore_pending_new(obj, 0);
2421
2422         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2423                 err("Out of memory. Unable to proceed");
2424                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2425
2426                 g_free(cmd_str);
2427                 util_sms_free_memory(atreq);
2428                 util_sms_free_memory(pending);
2429
2430                 dbg("Exit");
2431                 return TCORE_RETURN_ENOMEM;
2432         }
2433
2434         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
2435
2436         tcore_pending_set_request_data(pending, 0, atreq);
2437         tcore_pending_set_response_callback(pending, on_response_read_msg, (void *)(uintptr_t)(readMsg->index)); /* storing index as user data for response */
2438         tcore_pending_link_user_request(pending, ur);
2439         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
2440         tcore_hal_send_request(hal, pending);
2441
2442         g_free(cmd_str);
2443
2444         dbg("Exit");
2445         return TCORE_RETURN_SUCCESS;
2446 }
2447
2448 static TReturn save_msg(CoreObject *obj, UserRequest *ur)
2449 {
2450         gchar *cmd_str = NULL;
2451         TcoreHal *hal = NULL;
2452         TcoreATRequest *atreq = NULL;
2453         TcorePending *pending = NULL;
2454         const struct treq_sms_save_msg *saveMsg = NULL;
2455         int ScLength = 0, pdu_len = 0, stat = 0;
2456         char buf[2 * (SMS_SMSP_ADDRESS_LEN + SMS_SMDATA_SIZE_MAX) + 1] = {0};
2457         char *hex_pdu = NULL;
2458
2459         dbg("Entry");
2460
2461         saveMsg = tcore_user_request_ref_data(ur, NULL);
2462         hal = tcore_object_get_hal(obj);
2463         if (NULL == saveMsg || NULL == hal) {
2464                 err("NULL input. Unable to proceed");
2465                 dbg("saveMsg: [%p], hal: [%p]", saveMsg, hal);
2466
2467                 dbg("Exit");
2468                 return TCORE_RETURN_EINVAL;
2469         }
2470         if (FALSE == tcore_hal_get_power_state(hal)) {
2471                 dbg("cp not ready/n");
2472                 return TCORE_RETURN_ENOSYS;
2473         }
2474
2475         dbg("msgStatus: %x, msgLength: [%d]", saveMsg->msgStatus, saveMsg->msgDataPackage.msgLength);
2476         tcore_util_hex_dump("    ", (SMS_SMDATA_SIZE_MAX+1), (void *)saveMsg->msgDataPackage.tpduData);
2477         tcore_util_hex_dump("    ", SMS_SMSP_ADDRESS_LEN, (void *)saveMsg->msgDataPackage.sca);
2478
2479         switch (saveMsg->msgStatus) {
2480         case SMS_STATUS_READ:
2481                 stat = AT_REC_READ;
2482         break;
2483
2484         case SMS_STATUS_UNREAD:
2485                 stat = AT_REC_UNREAD;
2486         break;
2487
2488         case SMS_STATUS_SENT:
2489                 stat = AT_STO_SENT;
2490         break;
2491
2492         case SMS_STATUS_UNSENT:
2493                 stat = AT_STO_UNSENT;
2494         break;
2495
2496         default:
2497                 err("Invalid msgStatus");
2498                 dbg("Exit");
2499                 return TCORE_RETURN_EINVAL;
2500         }
2501
2502         if ((saveMsg->msgDataPackage.msgLength > 0)
2503                 && (saveMsg->msgDataPackage.msgLength <= SMS_SMDATA_SIZE_MAX)) {
2504                 ScLength = (int)saveMsg->msgDataPackage.sca[0];
2505
2506                 buf[0] = ScLength;
2507                 dbg("ScLength = %d", ScLength);
2508
2509                 if (ScLength == 0)
2510                         buf[0] = 0;
2511                 else
2512                         memcpy(&buf[1],  saveMsg->msgDataPackage.sca, ScLength);
2513
2514                 memcpy(&buf[ScLength + 1], saveMsg->msgDataPackage.tpduData, saveMsg->msgDataPackage.msgLength);
2515
2516                 pdu_len = saveMsg->msgDataPackage.msgLength + ScLength + 1;
2517                 dbg("pdu_len: [%d]", pdu_len);
2518
2519                 hex_pdu = g_malloc0(pdu_len * 2 + 1);
2520                 tcore_util_hex_dump("    ", sizeof(buf), (void *)buf);
2521
2522                 memset(hex_pdu, 0x00, pdu_len * 2 + 1);
2523
2524                 util_byte_to_hex((const char *)buf, (char *)hex_pdu, pdu_len);
2525
2526                 /* AT+CMGW=<length>[, <stat>]<CR>PDU is given<ctrl-Z/ESC> */
2527                 cmd_str = g_strdup_printf("AT+CMGW=%d, %d%s%s\x1A", saveMsg->msgDataPackage.msgLength, stat, "\r", hex_pdu);
2528                 pending = tcore_pending_new(obj, 0);
2529                 atreq = tcore_at_request_new((const char *)cmd_str, "+CMGW", TCORE_AT_SINGLELINE);
2530
2531                 if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2532                         err("Out of memory. Unable to proceed");
2533                         dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2534
2535                         g_free(cmd_str);
2536                         util_sms_free_memory(atreq);
2537                         util_sms_free_memory(pending);
2538                         util_sms_free_memory(hex_pdu);
2539
2540                         dbg("Exit");
2541                         return TCORE_RETURN_ENOMEM;
2542                 }
2543
2544                 tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
2545
2546                 tcore_pending_set_request_data(pending, 0, atreq);
2547                 tcore_pending_set_response_callback(pending, on_response_sms_save_msg, NULL);
2548                 tcore_pending_link_user_request(pending, ur);
2549                 tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
2550                 tcore_hal_send_request(hal, pending);
2551
2552                 g_free(cmd_str);
2553                 free(hex_pdu);
2554
2555                 dbg("Exit");
2556                 return TCORE_RETURN_SUCCESS;
2557         }
2558
2559         err("Invalid Data len");
2560         dbg("Exit");
2561         return TCORE_RETURN_SMS_INVALID_DATA_LEN;
2562 }
2563
2564 static TReturn delete_msg(CoreObject *obj, UserRequest *ur)
2565 {
2566         gchar *cmd_str = NULL;
2567         TcoreHal *hal = NULL;
2568         TcoreATRequest *atreq = NULL;
2569         TcorePending *pending = NULL;
2570         const struct treq_sms_delete_msg *delete_msg = NULL;
2571
2572         dbg("Entry");
2573
2574         delete_msg = tcore_user_request_ref_data(ur, NULL);
2575         hal = tcore_object_get_hal(obj);
2576         if (NULL == delete_msg || NULL == hal) {
2577                 err("NULL input. Unable to proceed");
2578                 dbg("deleteMsg: [%p], hal: [%p]", delete_msg, hal);
2579
2580                 dbg("Exit");
2581                 return TCORE_RETURN_EINVAL;
2582         }
2583
2584         if (FALSE == tcore_hal_get_power_state(hal)) {
2585                 dbg("cp not ready/n");
2586                 return TCORE_RETURN_ENOSYS;
2587         }
2588
2589         dbg("index: %d", delete_msg->index);
2590
2591         if (delete_msg->index == -1)
2592                 cmd_str = g_strdup_printf("AT+CMGD=0, 4"); /* Delete All Messages */
2593         else
2594                 cmd_str = g_strdup_printf("AT+CMGD=%d, 0", delete_msg->index + 1); /* Delete specified index */
2595
2596         pending = tcore_pending_new(obj, 0);
2597         atreq = tcore_at_request_new((const char *)cmd_str, NULL, TCORE_AT_NO_RESULT);
2598         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2599                 err("Out of memory. Unable to proceed");
2600                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2601
2602                 g_free(cmd_str);
2603                 util_sms_free_memory(atreq);
2604                 util_sms_free_memory(pending);
2605
2606                 dbg("Exit");
2607                 return TCORE_RETURN_ENOMEM;
2608         }
2609
2610         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
2611
2612         tcore_pending_set_request_data(pending, 0, atreq);
2613         tcore_pending_set_response_callback(pending, on_response_sms_delete_msg, (void *) (uintptr_t) (delete_msg->index)); /* storing index as user data for response */
2614         tcore_pending_link_user_request(pending, ur);
2615         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
2616         tcore_hal_send_request(hal, pending);
2617
2618         g_free(cmd_str);
2619
2620         dbg("Exit");
2621         return TCORE_RETURN_SUCCESS;
2622 }
2623
2624 static TReturn get_stored_msg_cnt(CoreObject *obj, UserRequest *ur)
2625 {
2626         gchar *cmd_str = NULL;
2627         TcoreHal *hal = NULL;
2628         TcoreATRequest *atreq = NULL;
2629         TcorePending *pending = NULL;
2630
2631         dbg("Entry");
2632
2633         hal = tcore_object_get_hal(obj);
2634         if (NULL == hal) {
2635                 err("NULL HAL. Unable to proceed");
2636
2637                 dbg("Exit");
2638                 return TCORE_RETURN_EINVAL;
2639         }
2640
2641         if (FALSE == tcore_hal_get_power_state(hal)) {
2642                 dbg("cp not ready/n");
2643                 return TCORE_RETURN_ENOSYS;
2644         }
2645
2646         cmd_str = g_strdup_printf("AT+CPMS=\"SM\"");
2647         pending = tcore_pending_new(obj, 0);
2648         atreq = tcore_at_request_new((const char *)cmd_str, "+CPMS", TCORE_AT_SINGLELINE);
2649
2650         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2651                 err("Out of memory. Unable to proceed");
2652                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2653
2654                 g_free(cmd_str);
2655                 util_sms_free_memory(atreq);
2656                 util_sms_free_memory(pending);
2657
2658                 dbg("Exit");
2659                 return TCORE_RETURN_ENOMEM;
2660         }
2661
2662         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
2663
2664         tcore_pending_set_request_data(pending, 0, atreq);
2665         tcore_pending_set_response_callback(pending, on_response_get_stored_msg_cnt, NULL);
2666         tcore_pending_link_user_request(pending, ur);
2667         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
2668         tcore_hal_send_request(hal, pending);
2669
2670         g_free(cmd_str);
2671
2672         dbg("Exit");
2673         return TCORE_RETURN_SUCCESS;
2674 }
2675
2676 static TReturn get_sca(CoreObject *obj, UserRequest *ur)
2677 {
2678         gchar *cmd_str = NULL;
2679         TcoreHal *hal = NULL;
2680         TcoreATRequest *atreq = NULL;
2681         TcorePending *pending = NULL;
2682
2683         dbg("Entry");
2684
2685         hal = tcore_object_get_hal(obj);
2686         if (NULL == hal) {
2687                 err("HAL NULL. Unable to proceed");
2688
2689                 dbg("Exit");
2690                 return TCORE_RETURN_EINVAL;
2691         }
2692         if (FALSE == tcore_hal_get_power_state(hal)) {
2693                 dbg("cp not ready/n");
2694                 return TCORE_RETURN_ENOSYS;
2695         }
2696
2697         cmd_str = g_strdup_printf("AT+CSCA?");
2698         pending = tcore_pending_new(obj, 0);
2699         atreq = tcore_at_request_new((const char *)cmd_str, "+CSCA", TCORE_AT_SINGLELINE);
2700
2701         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2702                 err("Out of memory. Unable to proceed");
2703                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2704
2705                 g_free(cmd_str);
2706                 util_sms_free_memory(atreq);
2707                 util_sms_free_memory(pending);
2708
2709                 dbg("Exit");
2710                 return TCORE_RETURN_ENOMEM;
2711         }
2712
2713         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
2714
2715         tcore_pending_set_request_data(pending, 0, atreq);
2716         tcore_pending_set_response_callback(pending, on_response_get_sca, NULL);
2717         tcore_pending_link_user_request(pending, ur);
2718         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
2719         tcore_hal_send_request(hal, pending);
2720
2721         g_free(cmd_str);
2722
2723         dbg("Exit");
2724         return TCORE_RETURN_SUCCESS;
2725 }
2726
2727 static TReturn set_sca(CoreObject *obj, UserRequest *ur)
2728 {
2729         gchar *cmd_str = NULL;
2730         TcoreHal *hal = NULL;
2731         TcoreATRequest *atreq = NULL;
2732         TcorePending *pending = NULL;
2733         const struct treq_sms_set_sca *setSca = NULL;
2734         int addrType = 0;
2735
2736         dbg("Entry");
2737
2738         setSca = tcore_user_request_ref_data(ur, NULL);
2739         hal = tcore_object_get_hal(obj);
2740         if (NULL == setSca || NULL == hal) {
2741                 err("NULL input. Unable to proceed");
2742                 dbg("setSca: [%p], hal: [%p]", setSca, hal);
2743
2744                 dbg("Exit");
2745                 return TCORE_RETURN_EINVAL;
2746         }
2747         if (FALSE == tcore_hal_get_power_state(hal)) {
2748                 dbg("cp not ready/n");
2749                 return TCORE_RETURN_ENOSYS;
2750         }
2751
2752         dbg("dialNumLen: %u, typeOfNum: %d, numPlanId: %d, ", setSca->scaInfo.dialNumLen, setSca->scaInfo.typeOfNum, setSca->scaInfo.numPlanId);
2753
2754         tcore_util_hex_dump("    ", (SMS_SMSP_ADDRESS_LEN+1), (void *)setSca->scaInfo.diallingNum);
2755
2756         addrType = ((setSca->scaInfo.typeOfNum << 4) | setSca->scaInfo.numPlanId) | 0x80;
2757
2758         cmd_str = g_strdup_printf("AT+CSCA=\"%s\", %d", setSca->scaInfo.diallingNum, addrType);
2759         pending = tcore_pending_new(obj, 0);
2760         atreq = tcore_at_request_new((const char *)cmd_str, NULL, TCORE_AT_NO_RESULT);
2761
2762         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2763                 err("Out of memory. Unable to proceed");
2764                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2765
2766                 g_free(cmd_str);
2767                 util_sms_free_memory(atreq);
2768                 util_sms_free_memory(pending);
2769
2770                 dbg("Exit");
2771                 return TCORE_RETURN_ENOMEM;
2772         }
2773
2774         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
2775
2776         tcore_pending_set_request_data(pending, 0, atreq);
2777         tcore_pending_set_response_callback(pending, on_response_set_sca, NULL);
2778         tcore_pending_link_user_request(pending, ur);
2779         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
2780         tcore_hal_send_request(hal, pending);
2781
2782         g_free(cmd_str);
2783
2784         dbg("Exit");
2785         return TCORE_RETURN_SUCCESS;
2786 }
2787
2788 static TReturn get_cb_config(CoreObject *obj, UserRequest *ur)
2789 {
2790         gchar *cmd_str = NULL;
2791         TcoreHal *hal = NULL;
2792         TcoreATRequest *atreq = NULL;
2793         TcorePending *pending = NULL;
2794
2795         dbg("Entry");
2796
2797         hal = tcore_object_get_hal(obj);
2798         if (NULL == hal) {
2799                 err("NULL HAL. Unable to proceed");
2800
2801                 dbg("Exit");
2802                 return TCORE_RETURN_EINVAL;
2803         }
2804
2805         if (FALSE == tcore_hal_get_power_state(hal)) {
2806                 dbg("cp not ready/n");
2807                 return TCORE_RETURN_ENOSYS;
2808         }
2809
2810         cmd_str = g_strdup_printf("AT+CSCB?");
2811         pending = tcore_pending_new(obj, 0);
2812         atreq = tcore_at_request_new((const char *)cmd_str, "+CSCB", TCORE_AT_SINGLELINE);
2813         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2814                 err("Out of memory. Unable to proceed");
2815                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2816
2817                 g_free(cmd_str);
2818                 util_sms_free_memory(atreq);
2819                 util_sms_free_memory(pending);
2820
2821                 dbg("Exit");
2822                 return TCORE_RETURN_ENOMEM;
2823         }
2824
2825         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
2826
2827         tcore_pending_set_request_data(pending, 0, atreq);
2828         tcore_pending_set_response_callback(pending, on_response_get_cb_config, NULL);
2829         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
2830         tcore_pending_link_user_request(pending, ur);
2831         tcore_hal_send_request(hal, pending);
2832
2833         g_free(cmd_str);
2834
2835         dbg("Exit");
2836         return TCORE_RETURN_SUCCESS;
2837 }
2838
2839 static TReturn set_cb_config(CoreObject *obj, UserRequest *ur)
2840 {
2841         gchar *cmd_str = NULL;
2842         gchar *mids_str = NULL;
2843         GString *mids_GString = NULL;
2844
2845         TcoreHal *hal = NULL;
2846         TcoreATRequest *atreq = NULL;
2847         TcorePending *pending = NULL;
2848         const struct treq_sms_set_cb_config *setCbConfig = NULL;
2849         int ctr1 = 0, ctr2 = 0;
2850         unsigned short appendMsgId = 0;
2851
2852         dbg("Entry");
2853
2854         setCbConfig = tcore_user_request_ref_data(ur, NULL);
2855         hal = tcore_object_get_hal(obj);
2856         if (NULL == setCbConfig || NULL == hal) {
2857                 err("NULL input. Unable to proceed");
2858                 dbg("setCbConfig: [%p], hal: [%p]", setCbConfig, hal);
2859
2860                 dbg("Exit");
2861                 return TCORE_RETURN_EINVAL;
2862         }
2863
2864         if (FALSE == tcore_hal_get_power_state(hal)) {
2865                 dbg("cp not ready/n");
2866                 return TCORE_RETURN_ENOSYS;
2867         }
2868
2869         dbg("bCBEnabled: %d,  msgIdCount: %d", setCbConfig->cbEnabled, setCbConfig->msgIdRangeCount);
2870
2871         if (setCbConfig->cbEnabled == 2) { /* Enable all CBS */
2872                 cmd_str = g_strdup_printf("AT+CSCB=1");
2873         } else if ((setCbConfig->cbEnabled == 1) && (setCbConfig->msgIdRangeCount == 0)) { /* Special case: Enable all CBS */
2874                 cmd_str = g_strdup_printf("AT+CSCB=1");
2875         } else if (setCbConfig->cbEnabled == 0) {/* AT+CSCB=0: Disable CBS */
2876                 cmd_str = g_strdup_printf("AT+CSCB=0");
2877         } else {
2878                 mids_GString = g_string_new("AT+CSCB=0, \"");
2879
2880                 for (ctr1 = 0; ctr1 < setCbConfig->msgIdRangeCount; ctr1++) {
2881                         if (setCbConfig->msgIDs[ctr1].net3gpp.selected == FALSE)
2882                                 continue;
2883
2884                         if (SMS_GSM_SMS_CBMI_LIST_SIZE_MAX <= (setCbConfig->msgIDs[ctr1].net3gpp.toMsgId - setCbConfig->msgIDs[ctr1].net3gpp.fromMsgId)) {
2885                                 g_string_free(mids_GString, TRUE);
2886                                 mids_GString = g_string_new("AT+CSCB=1");
2887                                 break;
2888                         }
2889
2890                         appendMsgId = setCbConfig->msgIDs[ctr1].net3gpp.fromMsgId;
2891
2892                         for (ctr2 = 0; (ctr2 <= ((setCbConfig->msgIDs[ctr1].net3gpp.toMsgId) - (setCbConfig->msgIDs[ctr1].net3gpp.fromMsgId))); ctr2++) {
2893                                 gchar *append_str = NULL;
2894                                 dbg("%x", appendMsgId);
2895                                 append_str = g_strdup_printf("%d", appendMsgId);
2896                                 g_string_append(mids_GString, append_str);
2897                                 g_free(append_str);
2898
2899                                 if (ctr2 == ((setCbConfig->msgIDs[ctr1].net3gpp.toMsgId) - (setCbConfig->msgIDs[ctr1].net3gpp.fromMsgId)))
2900                                         g_string_append(mids_GString, "\""); /* Mids string termination */
2901                                 else
2902                                         g_string_append(mids_GString, ", ");
2903
2904                                 appendMsgId++;
2905                         }
2906                 }
2907                 mids_str = g_string_free(mids_GString, FALSE);
2908                 cmd_str = g_strdup_printf("%s", mids_str);
2909                 g_free(mids_str);
2910         }
2911
2912         pending = tcore_pending_new(obj, 0);
2913         atreq = tcore_at_request_new((const char *)cmd_str, NULL, TCORE_AT_NO_RESULT);
2914         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2915                 err("Out of memory. Unable to proceed");
2916                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2917
2918                 g_free(cmd_str);
2919                 util_sms_free_memory(atreq);
2920                 util_sms_free_memory(pending);
2921
2922                 dbg("Exit");
2923                 return TCORE_RETURN_ENOMEM;
2924         }
2925
2926         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
2927
2928         tcore_pending_set_request_data(pending, 0, atreq);
2929         tcore_pending_set_response_callback(pending, on_response_set_cb_config, NULL);
2930         tcore_pending_link_user_request(pending, ur);
2931         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
2932         tcore_hal_send_request(hal, pending);
2933
2934         g_free(cmd_str);
2935
2936         dbg("Exit");
2937         return TCORE_RETURN_SUCCESS;
2938 }
2939
2940 static TReturn set_mem_status(CoreObject *obj, UserRequest *ur)
2941 {
2942         gchar *cmd_str = NULL;
2943         TcoreHal *hal = NULL;
2944         TcoreATRequest *atreq = NULL;
2945         TcorePending *pending = NULL;
2946         const struct treq_sms_set_mem_status *setMemStatus = NULL;
2947         int memoryStatus = 0;
2948
2949         dbg("Entry");
2950
2951         setMemStatus = tcore_user_request_ref_data(ur, NULL);
2952         hal = tcore_object_get_hal(obj);
2953         if (NULL == setMemStatus || NULL == hal) {
2954                 err("NULL input. Unable to proceed");
2955                 dbg("setMemStatus: [%p], hal: [%p]", setMemStatus, hal);
2956
2957                 dbg("Exit");
2958                 return TCORE_RETURN_EINVAL;
2959         }
2960         if (FALSE == tcore_hal_get_power_state(hal)) {
2961                 dbg("cp not ready/n");
2962                 return TCORE_RETURN_ENOSYS;
2963         }
2964
2965         dbg("memory_status: %d", setMemStatus->memory_status);
2966
2967         if (setMemStatus->memory_status < SMS_PDA_MEMORY_STATUS_AVAILABLE
2968                         || setMemStatus->memory_status > SMS_PDA_MEMORY_STATUS_FULL) {
2969                 err("Invalid memory_status");
2970
2971                 dbg("Exit");
2972                 return TCORE_RETURN_EINVAL;
2973         }
2974
2975         switch (setMemStatus->memory_status) {
2976         case SMS_PDA_MEMORY_STATUS_AVAILABLE:
2977                 memoryStatus = AT_MEMORY_AVAILABLE;
2978         break;
2979
2980         case SMS_PDA_MEMORY_STATUS_FULL:
2981                 memoryStatus = AT_MEMORY_FULL;
2982         break;
2983
2984         default:
2985                 err("Invalid memory_status");
2986                 dbg("Exit");
2987                 return TCORE_RETURN_EINVAL;
2988         }
2989
2990         cmd_str = g_strdup_printf("AT+XTESM=%d", memoryStatus);
2991         pending = tcore_pending_new(obj, 0);
2992         atreq = tcore_at_request_new((const char *)cmd_str, NULL, TCORE_AT_NO_RESULT);
2993
2994         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
2995                 err("Out of memory. Unable to proceed");
2996                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
2997
2998                 g_free(cmd_str);
2999                 util_sms_free_memory(atreq);
3000                 util_sms_free_memory(pending);
3001
3002                 dbg("Exit");
3003                 return TCORE_RETURN_ENOMEM;
3004         }
3005
3006         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
3007
3008         tcore_pending_set_request_data(pending, 0, atreq);
3009         tcore_pending_set_response_callback(pending, on_response_set_mem_status, NULL);
3010         tcore_pending_link_user_request(pending, ur);
3011         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
3012         tcore_hal_send_request(hal, pending);
3013
3014         g_free(cmd_str);
3015
3016         dbg("Exit");
3017         return TCORE_RETURN_SUCCESS;
3018 }
3019
3020 static TReturn set_delivery_report(CoreObject *obj, UserRequest *ur)
3021 {
3022         struct tresp_sms_set_delivery_report respSetDeliveryReport = {0, };
3023
3024         respSetDeliveryReport.result = SMS_SUCCESS;
3025
3026         dbg("Entry");
3027         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(obj))) {
3028                 dbg("cp not ready/n");
3029                 return TCORE_RETURN_ENOSYS;
3030         }
3031
3032         dbg("CP takes care of sending SMS ack to network for all classes of SMS. Sending default success.");
3033
3034         tcore_user_request_send_response(ur, TRESP_SMS_SET_DELIVERY_REPORT, sizeof(struct tresp_sms_set_delivery_report), &respSetDeliveryReport);
3035
3036         dbg("Exit");
3037         return TCORE_RETURN_SUCCESS;
3038 }
3039
3040 static TReturn set_msg_status(CoreObject *obj, UserRequest *ur)
3041 {
3042         gchar *cmd_str = NULL;
3043         TcoreHal *hal = NULL;
3044         TcoreATRequest *atreq = NULL;
3045         TcorePending *pending = NULL;
3046         const struct treq_sms_set_msg_status *msg_status = NULL;
3047
3048         dbg("Entry");
3049         hal = tcore_object_get_hal(obj);
3050         if (FALSE == tcore_hal_get_power_state(hal)) {
3051                 dbg("cp not ready/n");
3052                 return TCORE_RETURN_ENOSYS;
3053         }
3054         msg_status = tcore_user_request_ref_data(ur, NULL);
3055
3056         cmd_str = g_strdup_printf("AT+CRSM=178, 28476, %d, 4, %d", (msg_status->index+1), PDU_LEN_MAX);
3057         atreq = tcore_at_request_new((const char *)cmd_str, "+CRSM", TCORE_AT_SINGLELINE);
3058         pending = tcore_pending_new(obj, 0);
3059         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
3060                 err("Out of memory. Unable to proceed");
3061                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
3062
3063                 g_free(cmd_str);
3064                 util_sms_free_memory(atreq);
3065                 util_sms_free_memory(pending);
3066
3067                 dbg("Exit");
3068                 return TCORE_RETURN_ENOMEM;
3069         }
3070
3071         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
3072
3073         tcore_pending_set_request_data(pending, 0, atreq);
3074         tcore_pending_set_response_callback(pending, _response_get_efsms_data, NULL);
3075         tcore_pending_link_user_request(pending, ur);
3076         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
3077         tcore_hal_send_request(hal, pending);
3078
3079         g_free(cmd_str);
3080
3081         dbg("Exit");
3082         return TCORE_RETURN_SUCCESS;
3083 }
3084
3085 static TReturn get_sms_params(CoreObject *obj, UserRequest *ur)
3086 {
3087         gchar *cmd_str = NULL;
3088         TcoreHal *hal = NULL;
3089         TcoreATRequest *atreq = NULL;
3090         TcorePending *pending = NULL;
3091         const struct treq_sms_get_params *getSmsParams = NULL;
3092         int record_len = 0, *smsp_record_len = NULL;
3093
3094         dbg("Entry");
3095
3096         getSmsParams = tcore_user_request_ref_data(ur, NULL);
3097         hal = tcore_object_get_hal(obj);
3098         if (NULL == getSmsParams || NULL == hal) {
3099                 err("NULL input. Unable to proceed");
3100                 dbg("getSmsParams: [%p], hal: [%p]", getSmsParams, hal);
3101
3102                 dbg("Exit");
3103                 return TCORE_RETURN_EINVAL;
3104         }
3105
3106         if (FALSE == tcore_hal_get_power_state(hal)) {
3107                 dbg("cp not ready/n");
3108                 return TCORE_RETURN_ENOSYS;
3109         }
3110
3111         smsp_record_len = tcore_plugin_ref_property(tcore_object_ref_plugin(obj), "SMSPRECORDLEN");
3112         record_len = *smsp_record_len;
3113         dbg("record len from property %d", record_len);
3114
3115         /* AT+CRSM=command>[, <fileid>[, <P1>, <P2>, <P3>[, <data>[, <pathid>]]]] */
3116         cmd_str = g_strdup_printf("AT+CRSM=178, 28482, %d, 4, %d", (getSmsParams->index + 1), record_len);
3117
3118         dbg("cmd_str is %s", cmd_str);
3119
3120         atreq = tcore_at_request_new((const char *)cmd_str, "+CRSM", TCORE_AT_SINGLELINE);
3121         pending = tcore_pending_new(obj, 0);
3122         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
3123                 err("Out of memory. Unable to proceed");
3124                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
3125
3126                 g_free(cmd_str);
3127                 util_sms_free_memory(atreq);
3128                 util_sms_free_memory(pending);
3129
3130                 dbg("Exit");
3131                 return TCORE_RETURN_ENOMEM;
3132         }
3133
3134         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
3135
3136         tcore_pending_set_request_data(pending, 0, atreq);
3137         tcore_pending_set_response_callback(pending, on_response_get_sms_params, NULL);
3138         tcore_pending_link_user_request(pending, ur);
3139         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
3140         tcore_hal_send_request(hal, pending);
3141
3142         g_free(cmd_str);
3143
3144         dbg("Exit");
3145         return TCORE_RETURN_SUCCESS;
3146 }
3147
3148 static TReturn set_sms_params(CoreObject *obj, UserRequest *ur)
3149 {
3150         gchar *cmd_str = NULL;
3151         char *encoded_data = NULL;
3152         unsigned char *temp_data = NULL;
3153         int SMSPRecordLen = 0;
3154         int *smsp_record_len;
3155
3156         TcoreHal *hal = NULL;
3157         TcoreATRequest *atreq = NULL;
3158         TcorePending *pending = NULL;
3159         const struct treq_sms_set_params *setSmsParams = NULL;
3160         int encoded_data_len = 0;
3161
3162         dbg("Entry");
3163
3164         setSmsParams = tcore_user_request_ref_data(ur, NULL);
3165         hal = tcore_object_get_hal(obj);
3166         if (NULL == setSmsParams || NULL == hal) {
3167                 err("NULL input. Unable to proceed");
3168                 dbg("setSmsParams: [%p], hal: [%p]", setSmsParams, hal);
3169                 return FALSE;
3170         }
3171         if (FALSE == tcore_hal_get_power_state(hal)) {
3172                 dbg("cp not ready/n");
3173                 return TCORE_RETURN_ENOSYS;
3174         }
3175
3176         /* EFsmsp file size is 28 +Y bytes (Y is alpha id size) */
3177         smsp_record_len = tcore_plugin_ref_property(tcore_object_ref_plugin(obj), "SMSPRECORDLEN");
3178         if (NULL == smsp_record_len) {
3179                 err("SMSP record is NULL");
3180                 return TCORE_RETURN_FAILURE;
3181         }
3182         SMSPRecordLen = *smsp_record_len;
3183         if (SMSPRecordLen < nDefaultSMSPWithoutAlphaId)
3184                 return FALSE;
3185
3186         temp_data = g_malloc0(SMSPRecordLen);
3187         encoded_data = g_malloc0(SMSPRecordLen*2 + 1);
3188
3189         _tcore_util_sms_encode_smsParameters(&(setSmsParams->params), temp_data, SMSPRecordLen);
3190
3191         util_byte_to_hex((const char *)temp_data, (char *)encoded_data, SMSPRecordLen);
3192
3193         encoded_data_len = ((SMSPRecordLen) * 2);
3194
3195         hal = tcore_object_get_hal(obj);
3196         pending = tcore_pending_new(obj, 0);
3197
3198         dbg("alpha id len %d encoded data %s. Encoded data len %d", setSmsParams->params.alphaIdLen, encoded_data, encoded_data_len);
3199         cmd_str = g_strdup_printf("AT+CRSM=220, 28482, %d, 4, %d, \"%s\"", (setSmsParams->params.recordIndex+1), SMSPRecordLen, encoded_data);
3200
3201         dbg("cmd str is %s", cmd_str);
3202         atreq = tcore_at_request_new(cmd_str, "+CRSM:", TCORE_AT_SINGLELINE);
3203
3204         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
3205                 err("Out of memory. Unable to proceed");
3206                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
3207
3208                 g_free(cmd_str);
3209                 util_sms_free_memory(atreq);
3210                 util_sms_free_memory(pending);
3211
3212                 util_sms_free_memory(temp_data);
3213                 util_sms_free_memory(encoded_data);
3214
3215                 dbg("Exit");
3216                 return TCORE_RETURN_ENOMEM;
3217         }
3218
3219         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
3220
3221         tcore_pending_set_request_data(pending, 0, atreq);
3222         tcore_pending_set_response_callback(pending, on_response_set_sms_params, NULL);
3223         tcore_pending_link_user_request(pending, ur);
3224         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
3225         tcore_hal_send_request(hal, pending);
3226
3227         g_free(cmd_str);
3228         util_sms_free_memory(temp_data);
3229         util_sms_free_memory(encoded_data);
3230
3231         return TCORE_RETURN_SUCCESS;
3232 }
3233
3234 static TReturn get_paramcnt(CoreObject *obj, UserRequest *ur)
3235 {
3236         gchar *cmd_str = NULL;
3237         TcoreHal *hal = NULL;
3238         TcoreATRequest *atreq = NULL;
3239         TcorePending *pending = NULL;
3240
3241         dbg("Entry");
3242
3243         hal = tcore_object_get_hal(obj);
3244         if (NULL == hal) {
3245                 err("NULL HAL. Unable to proceed");
3246
3247                 dbg("Exit");
3248                 return TCORE_RETURN_EINVAL;
3249         }
3250         if (FALSE == tcore_hal_get_power_state(hal)) {
3251                 dbg("cp not ready/n");
3252                 return TCORE_RETURN_ENOSYS;
3253         }
3254
3255         /* AT+CRSM=command>[, <fileid>[, <P1>, <P2>, <P3>[, <data>[, <pathid>]]]] */
3256         cmd_str = g_strdup_printf("AT+CRSM=192, 28482");
3257         atreq = tcore_at_request_new((const char *)cmd_str, "+CRSM", TCORE_AT_SINGLELINE);
3258         pending = tcore_pending_new(obj, 0);
3259
3260         if (NULL == cmd_str || NULL == atreq || NULL == pending) {
3261                 err("NULL pointer. Unable to proceed");
3262                 dbg("cmd_str: [%p], atreq: [%p], pending: [%p]", cmd_str, atreq, pending);
3263
3264                 g_free(cmd_str);
3265                 util_sms_free_memory(atreq);
3266                 util_sms_free_memory(pending);
3267
3268                 dbg("Exit");
3269                 return TCORE_RETURN_FAILURE;
3270         }
3271
3272         tcore_util_hex_dump("    ", strlen(cmd_str), (void *)cmd_str);
3273
3274         tcore_pending_set_request_data(pending, 0, atreq);
3275         tcore_pending_set_response_callback(pending, on_response_get_paramcnt, NULL);
3276         tcore_pending_link_user_request(pending, ur);
3277         tcore_pending_set_send_callback(pending, on_confirmation_sms_message_send, NULL);
3278         tcore_hal_send_request(hal, pending);
3279
3280         g_free(cmd_str);
3281
3282         dbg("Exit");
3283         return TCORE_RETURN_SUCCESS;
3284 }
3285
3286 static struct tcore_sms_operations sms_ops = {
3287         .send_umts_msg = send_umts_msg,
3288         .read_msg = read_msg,
3289         .save_msg = save_msg,
3290         .delete_msg = delete_msg,
3291         .get_storedMsgCnt = get_stored_msg_cnt,
3292         .get_sca = get_sca,
3293         .set_sca = set_sca,
3294         .get_cb_config = get_cb_config,
3295         .set_cb_config = set_cb_config,
3296         .set_mem_status = set_mem_status,
3297         .get_pref_brearer = NULL,
3298         .set_pref_brearer = NULL,
3299         .set_delivery_report = set_delivery_report,
3300         .set_msg_status = set_msg_status,
3301         .get_sms_params = get_sms_params,
3302         .set_sms_params = set_sms_params,
3303         .get_paramcnt = get_paramcnt,
3304 };
3305
3306 gboolean imc_sms_init(TcorePlugin *cp, CoreObject *co_sms)
3307 {
3308         int *smsp_record_len;
3309         dbg("Entry");
3310
3311         /* Set operations */
3312         tcore_sms_set_ops(co_sms, &sms_ops, TCORE_OPS_TYPE_CP);
3313
3314         /* Registering for SMS notifications */
3315         tcore_object_add_callback(co_sms, "+CMTI:", on_event_class2_sms_incom_msg, NULL);
3316         tcore_object_add_callback(co_sms, "\e+CMT:", on_event_sms_incom_msg, NULL);
3317
3318         tcore_object_add_callback(co_sms, "\e+CDS", on_event_sms_incom_msg, NULL);
3319         tcore_object_add_callback(co_sms, "+XSMSMMSTAT", on_event_sms_memory_status, NULL);
3320         tcore_object_add_callback(co_sms, "+CMS", on_event_sms_memory_status, NULL);
3321
3322         tcore_object_add_callback(co_sms, "+CBMI:", on_event_sms_cb_incom_msg, NULL);
3323         tcore_object_add_callback(co_sms, "\e+CBM:", on_event_sms_cb_incom_msg, NULL);
3324
3325         /* Storing SMSP record length */
3326         smsp_record_len = g_new0(int, 1);
3327         tcore_plugin_link_property(cp, "SMSPRECORDLEN", smsp_record_len);
3328
3329         dbg("Exit");
3330         return TRUE;
3331 }
3332
3333 void imc_sms_exit(TcorePlugin *cp, CoreObject *co_sms)
3334 {
3335         int *smsp_record_len;
3336
3337         smsp_record_len = tcore_plugin_ref_property(cp, "SMSPRECORDLEN");
3338         g_free(smsp_record_len);
3339
3340         dbg("Exit");
3341 }