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