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