a94db5b2fbe8a3e880addb6b89375ecddbe08e5a
[platform/core/telephony/tel-plugin-imc.git] / src / s_phonebook.c
1 /**
2  * tel-plugin-imc
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact: Ankit Jogi <ankit.jogi@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 <glib.h>
25 #include <tcore.h>
26 #include <hal.h>
27 #include <core_object.h>
28 #include <plugin.h>
29 #include <queue.h>
30 #include <co_phonebook.h>
31 #include <co_sim.h>
32 #include <user_request.h>
33 #include <server.h>
34 #include <at.h>
35
36 #include "s_common.h"
37 #include "s_phonebook.h"
38
39 /* Constants */
40 #define VAL_ZERO        0
41 #define VAL_ONE         1
42 #define VAL_TWO         2
43 #define VAL_THREE       3
44 #define VAL_FOUR        4
45 #define VAL_FIVE        5
46 #define VAL_SIX         6
47 #define VAL_SEVEN       7
48 #define VAL_NINE        9
49
50 /* Type Of Number and Number Plan */
51 #define TON_INTERNATIONAL               145
52 #define TON_UNKNOWN                             129
53 #define NUM_PLAN_INTERNATIONAL  0x0070
54 #define NUM_PLAN_UNKNOWN                0x0060
55
56 struct valid_pb_index{
57         int used_count;
58         int total_count;
59         int indexlist_populated;
60         int *indexlist;
61         int current_index;
62 };
63 static struct valid_pb_index __pbindex;
64
65 enum pb_usim_file_type {
66         PB_USIM_NAME = 0x01,            /**< Name */
67         PB_USIM_NUMBER,                         /**< Number */
68         PB_USIM_ANR,                            /**< Another number */
69         PB_USIM_EMAIL,                          /**< Email */
70         PB_USIM_SNE,                            /**< Second name entry */
71         PB_USIM_GRP,                            /**< Group file */
72         PB_USIM_PBC,                            /** <1 byte control info and 1 byte hidden info*/
73         PB_USIM_ANRA,                           /**< Another number a*/
74         PB_USIM_ANRB,                           /**< Another number b*/
75         PB_USIM_ANRC,                           /**< Another number c*/
76         PB_USIM_EMAILA,                         /**< email a*/
77         PB_USIM_EMAILB,                         /**< email b*/
78         PB_USIM_EMAILC,                         /**< email c*/
79 };
80
81 static TReturn _get_support_list(CoreObject *o);
82 static TReturn s_get_count(CoreObject *o, UserRequest *ur);
83 static TReturn s_get_info(CoreObject *o, UserRequest *ur);
84 static TReturn s_get_usim_info(CoreObject *o, UserRequest *ur);
85 static TReturn s_read_record(CoreObject *o, UserRequest *ur);
86 static TReturn s_update_record(CoreObject *o, UserRequest *ur);
87 static TReturn s_delete_record(CoreObject *o, UserRequest *ur);
88
89
90 static void pbindex_reset()
91 {
92         if(__pbindex.indexlist){
93                 free(__pbindex.indexlist);
94         }
95         memset(&__pbindex, 0x00, sizeof(struct valid_pb_index));
96 }
97
98 static enum tcore_response_command _find_resp_command(UserRequest *ur)
99 {
100         switch(tcore_user_request_get_command(ur))
101         {
102                 case TREQ_PHONEBOOK_GETCOUNT:
103                         return TRESP_PHONEBOOK_GETCOUNT;
104                 case TREQ_PHONEBOOK_GETMETAINFO:
105                         return TRESP_PHONEBOOK_GETMETAINFO;
106                 case TREQ_PHONEBOOK_GETUSIMINFO:
107                         return TRESP_PHONEBOOK_GETUSIMINFO;
108                 case TREQ_PHONEBOOK_READRECORD:
109                         return TRESP_PHONEBOOK_READRECORD;
110                 case TREQ_PHONEBOOK_UPDATERECORD:
111                         return TRESP_PHONEBOOK_UPDATERECORD;
112                 case TREQ_PHONEBOOK_DELETERECORD:
113                         return TRESP_PHONEBOOK_DELETERECORD;
114                 default:
115                         return TRESP_UNKNOWN;
116         }
117 }
118
119 static enum tel_phonebook_ton _find_num_plan(int number_plan)
120 {
121         enum tel_phonebook_ton result;
122         dbg("number_plan : 0x%04x", number_plan);
123
124         if(number_plan & NUM_PLAN_INTERNATIONAL) {
125                 result = PB_TON_INTERNATIONAL;
126         }
127         else {
128                 result = PB_TON_UNKNOWN;
129         }
130         dbg("result : %d", result);
131         return result;
132 }
133
134 static char* _get_phonebook_type(enum tel_phonebook_type pb_type)
135 {
136         char *phonebook_type = NULL;
137         dbg(" Function entry ");
138         dbg("pb_type = %d", pb_type);
139
140         phonebook_type = (char*)calloc(sizeof(char), VAL_FIVE);
141         if(NULL == phonebook_type) {
142                 err("Memory allcoation failed");
143                 return phonebook_type;
144         }
145
146         switch(pb_type)
147         {
148                 case PB_TYPE_FDN:
149                         phonebook_type = "FD";
150                         break;
151                 case PB_TYPE_ADN:
152                 case PB_TYPE_AAS:
153                 case PB_TYPE_GAS:
154                         phonebook_type = "SM";
155                         break;
156                 case PB_TYPE_SDN:
157                         phonebook_type = "SN";
158                         break;
159                 case PB_TYPE_USIM:
160                         phonebook_type = "AP";
161                         break;
162                 default:
163                         dbg("Invalid pb_type [%02x]", pb_type);
164                         free(phonebook_type);
165                         phonebook_type = NULL;
166                         break;
167         }
168         dbg(" Function exit");
169         return phonebook_type;
170 }
171
172 static enum tel_phonebook_type _get_phonebook_enum(const char* pb_type)
173 {
174         enum tel_phonebook_type phonebook_type = PB_TYPE_UNKNOWNN;
175         dbg(" Function entry ");
176         dbg("pb_type = %s", pb_type);
177
178         if(strcmp("FD", pb_type) == VAL_ZERO) {
179                 phonebook_type = PB_TYPE_FDN;
180         }
181         else if(strcmp("SM", pb_type) == VAL_ZERO) {
182                 phonebook_type = PB_TYPE_ADN;
183         }
184         else if(strcmp("SN", pb_type) == VAL_ZERO) {
185                 phonebook_type = PB_TYPE_SDN;
186         }
187         else if(strcmp("AP", pb_type) == VAL_ZERO) {
188                 phonebook_type = PB_TYPE_USIM;
189         }
190
191         dbg(" Function exit");
192         return phonebook_type;
193 }
194
195 static gboolean on_event_phonebook_status(CoreObject *o, const void *event_info, void *user_data)
196 {
197         dbg("Phonebook init received from modem");
198
199         _get_support_list(o);
200
201         return TRUE;
202 }
203
204 static void _on_response_select(TcorePending *p, int data_len, const void *data, void *user_data)
205 {
206         const TcoreATResponse *resp = data;
207         UserRequest *ur = NULL;
208         enum tcore_request_command req_cmd = TREQ_UNKNOWN;
209         int *selected_pb = user_data;
210
211         dbg(" Function entry ");
212
213         ur = tcore_pending_ref_user_request(p);
214         if (!ur){
215                 dbg("error - current ur is NULL");
216                 return;
217         }
218
219         req_cmd = tcore_user_request_get_command(ur);
220         dbg("origin treq command [%x]", req_cmd);
221
222         if(resp->success > VAL_ZERO) {
223                 CoreObject *o = NULL;
224                 o = tcore_pending_ref_core_object(p);
225
226                 dbg("RESPONSE OK");
227                 tcore_phonebook_set_selected_type(o, *selected_pb);
228                 switch (req_cmd)
229                 {
230                         case TREQ_PHONEBOOK_GETCOUNT:
231                                 s_get_count(o, ur);
232                                 break;
233                         case TREQ_PHONEBOOK_GETMETAINFO:
234                                 s_get_info(o, ur);
235                                 break;
236                         case TREQ_PHONEBOOK_GETUSIMINFO:
237                                 s_get_usim_info(o, ur);
238                                 break;
239                         case TREQ_PHONEBOOK_READRECORD:
240                                 s_read_record(o, ur);
241                                 break;
242                         case TREQ_PHONEBOOK_UPDATERECORD:
243                                 s_update_record(o, ur);
244                                 break;
245                         case TREQ_PHONEBOOK_DELETERECORD:
246                                 s_delete_record(o, ur);
247                                 break;
248                         default:
249                                 dbg("not handled treq cmd[%d]", req_cmd);
250                                 break;
251                 }
252         }
253         else
254         {
255                 dbg("RESPONSE NOK");
256                 switch (req_cmd)
257                 {
258                         case TREQ_PHONEBOOK_GETCOUNT:
259                         {
260                                 struct tresp_phonebook_get_count resp_getcount;
261                                 dbg("error TREQ_PHONEBOOK_GETCOUNT");
262                                 memset(&resp_getcount, 0x00, sizeof(struct tresp_phonebook_get_count));
263                                 resp_getcount.result = PB_FAIL;
264                                 tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_get_count), &resp_getcount);
265                         }
266                         break;
267                         case TREQ_PHONEBOOK_GETMETAINFO:
268                         {
269                                 dbg("error TREQ_PHONEBOOK_GETMETAINFO");
270                         }
271                         break;
272                         case TREQ_PHONEBOOK_GETUSIMINFO:
273                         {
274                                 dbg("error TREQ_PHONEBOOK_GETUSIMINFO");
275                         }
276                         break;
277                         case TREQ_PHONEBOOK_READRECORD:
278                         {
279                                 struct tresp_phonebook_read_record resp_readrecord;
280                                 dbg("error TREQ_PHONEBOOK_READRECORD");
281                                 pbindex_reset();
282                                 memset(&resp_readrecord, 0x00, sizeof(struct tresp_phonebook_read_record));
283                                 resp_readrecord.result = PB_FAIL;
284                                 resp_readrecord.phonebook_type = *selected_pb;
285                                 tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_read_record), &resp_readrecord);
286                         }
287                         break;
288                         case TREQ_PHONEBOOK_UPDATERECORD:
289                         {
290                                 struct tresp_phonebook_update_record resp_updaterecord;
291                                 dbg("error TREQ_PHONEBOOK_UPDATERECORD");
292                                 memset(&resp_updaterecord, 0x00, sizeof(struct tresp_phonebook_update_record));
293                                 resp_updaterecord.result = PB_FAIL;
294                                 tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_update_record), &resp_updaterecord);
295                         }
296                         break;
297                         case TREQ_PHONEBOOK_DELETERECORD:
298                         {
299                                 struct tresp_phonebook_delete_record resp_deleterecord;
300                                 dbg("error TREQ_PHONEBOOK_DELETERECORD");
301                                 memset(&resp_deleterecord, 0x00, sizeof(struct tresp_phonebook_delete_record));
302                                 resp_deleterecord.result = PB_FAIL;
303                                 tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_delete_record), &resp_deleterecord);
304                         }
305                         break;
306                         default:
307                                 dbg("not handled treq cmd[%d]", req_cmd);
308                         break;
309                 }
310
311         }
312
313         free(selected_pb);
314         selected_pb = NULL;
315         dbg(" Function exit");
316 }
317
318 static void _on_response_getindexlist(TcorePending *p, int data_len, const void *data, void *user_data)
319 {
320         const TcoreATResponse *resp = data;
321         UserRequest *ur = NULL;
322         struct tresp_phonebook_read_record resp_readrecord;
323         int *selected_pb = user_data;
324         int total_lines = 0;
325         int count = 0;
326         GSList *tokens=NULL;
327         const char *line;
328
329         dbg(" Function entry ");
330
331         ur = tcore_pending_ref_user_request(p);
332         if (!ur){
333                 dbg("error - current ur is NULL");
334                 return;
335         }
336         memset(&resp_readrecord, 0x00, sizeof(struct tresp_phonebook_read_record));
337         resp_readrecord.result = PB_FAIL;
338         resp_readrecord.phonebook_type = *selected_pb;
339         
340         if(resp->success > 0)
341         {
342                 CoreObject *o = NULL;
343                 o = tcore_pending_ref_core_object(p);
344
345                 dbg("RESPONSE OK");
346                 tcore_phonebook_set_selected_type(o, *selected_pb);
347                 if (resp->lines) {
348                         total_lines = g_slist_length(resp->lines);
349                         dbg("Total number of PB entry %d\n", total_lines);
350                         if (total_lines < 1) {
351                                 msg("invalid message");
352                                 pbindex_reset();
353                                 goto EXIT;
354                         }
355                         __pbindex.indexlist = (int*)malloc(__pbindex.used_count * sizeof(int));
356                         if(__pbindex.indexlist == NULL){
357                                 dbg("Failed to allocate memory");
358                                 pbindex_reset();
359                                 goto EXIT;
360                         }
361                         resp_readrecord.result = PB_SUCCESS;
362                         for (count = 0; count < total_lines; count++) {
363                                 /* Take each line response at a time & parse it */
364                                 line = tcore_at_tok_nth(resp->lines, count);
365                                 tokens = tcore_at_tok_new(line);
366                                 __pbindex.indexlist[count] = atoi(g_slist_nth_data(tokens, 0));
367                                 dbg("__pbindex.indexlist[%d] = %d", count, __pbindex.indexlist[count]);
368                                 tcore_at_tok_free(tokens);
369                         }
370                 }
371                 __pbindex.indexlist_populated = 1;
372                 s_read_record(o, ur);
373                 free(selected_pb);
374                 selected_pb = NULL;
375                 return;
376         }
377         else{
378                 dbg("RESPONSE NOK");
379         }
380 EXIT:
381         tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_read_record), &resp_readrecord);
382
383         free(selected_pb);
384         selected_pb = NULL;
385         dbg(" Function exit");
386 }
387
388 static void on_response_get_count(TcorePending *p, int data_len, const void *data, void *user_data)
389 {
390         const TcoreATResponse *resp = data;
391         UserRequest *ur = NULL;
392         GSList *tokens=NULL;
393         const char *temp = NULL;
394         struct tresp_phonebook_get_count res;
395         char *pbtype = NULL;
396         dbg(" Function entry ");
397
398         ur = tcore_pending_ref_user_request(p);
399         if (!ur){
400                 dbg("error - current ur is NULL");
401                 return;
402         }
403
404         memset(&res, 0x00, sizeof(struct tresp_phonebook_get_count));
405         res.result = PB_FAIL;
406
407         if(resp->success > VAL_ZERO) {
408                 dbg("RESPONSE OK");
409                 if(resp->lines) {
410                         temp = (const char*)resp->lines->data;
411                         tokens = tcore_at_tok_new(temp);
412                         if (g_slist_length(tokens) < VAL_THREE) {
413                                 //No of tokens must be three. We cannot proceed without used and total count.
414                                 msg("invalid message");
415                                 goto EXIT;
416                         }
417                 }
418                 res.result = PB_SUCCESS;
419
420                 temp = (const char*)g_slist_nth_data(tokens, VAL_ZERO);
421                 pbtype =  util_removeQuotes((void*)temp);
422                 res.type = _get_phonebook_enum(pbtype);
423
424                 if(NULL != g_slist_nth_data(tokens, VAL_ONE)){
425                         res.used_count = atoi(g_slist_nth_data(tokens, VAL_ONE));
426                         __pbindex.used_count = res.used_count;
427                         dbg("used_count %d", __pbindex.used_count);
428                 }
429
430                 if(NULL != g_slist_nth_data(tokens, VAL_TWO)){
431                         res.total_count = atoi(g_slist_nth_data(tokens, VAL_TWO));
432                         __pbindex.total_count = res.total_count;
433                 }
434                 dbg("used count = %d,  total count= %d", res.used_count, res.total_count);
435                 free(pbtype);
436                 pbtype = NULL;
437         }
438         else{
439                 dbg("RESPONSE NOK");
440         }
441 EXIT:
442         tcore_at_tok_free(tokens);
443         tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_get_count), &res);
444         dbg(" Function exit");
445 }
446
447 static void on_response_get_info(TcorePending *p, int data_len, const void *data, void *user_data)
448 {
449         struct tresp_phonebook_get_info res = {0,};
450         const TcoreATResponse *resp = data;
451         UserRequest *ur = NULL;
452         GSList *tokens=NULL;
453         const char *line;
454         int *selected_pb = (int*)user_data;
455
456         dbg(" Function entry ");
457
458         ur = tcore_pending_ref_user_request(p);
459         if (!ur){
460                 dbg("error - current ur is NULL");
461                 return;
462         }
463
464         memset(&res, 0x00, sizeof(struct tresp_phonebook_get_info));
465         res.result = PB_FAIL;
466         res.type = *selected_pb;
467
468         if(resp->success > VAL_ZERO) {
469                 dbg("RESPONSE OK");
470                 if(resp->lines) {
471                         line = (const char*)resp->lines->data;
472                         tokens = tcore_at_tok_new(line);
473                         if (g_slist_length(tokens) < VAL_ONE) {
474                                 msg("invalid message");
475                                 goto EXIT;
476                         }
477                 }
478                 res.result = PB_SUCCESS;
479
480                 res.number_length_max = atoi(g_slist_nth_data(tokens, VAL_ZERO));
481                 res.text_length_max = atoi(g_slist_nth_data(tokens, VAL_ONE));
482                 dbg("number_length_max %d text_length_max %d",res.number_length_max,res.text_length_max);
483         }
484         else{
485                 dbg("RESPONSE NOK");
486         }
487 EXIT:
488         tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_get_info), &res);
489         free(selected_pb);
490         selected_pb = NULL;
491         tcore_at_tok_free(tokens);
492         dbg(" Function exit");
493
494 }
495
496 static void on_response_read_record(TcorePending *p, int data_len, const void *data, void *user_data)
497 {
498         const TcoreATResponse *resp = data;
499         UserRequest *ur = NULL;
500         GSList *tokens=NULL;
501         const char *line;
502         struct tresp_phonebook_read_record res;
503         int num_len = VAL_ZERO;
504         int name_len = VAL_ZERO;
505         int num_plan = VAL_ZERO;
506         char *member = NULL;
507         char *temp = NULL;
508         int *selected_pb = (int*)user_data;
509
510         dbg(" Function entry ");
511
512         ur = tcore_pending_ref_user_request(p);
513         if (!ur){
514                 dbg("error - current ur is NULL");
515                 return;
516         }
517
518         memset(&res, 0x00, sizeof(struct tresp_phonebook_read_record));
519         res.result = PB_FAIL;
520         res.phonebook_type = *selected_pb;
521
522         if(resp->success > VAL_ZERO) {
523                 dbg("RESPONSE OK");
524                 if(resp->lines) {
525                         line = (const char*)resp->lines->data;
526                         tokens = tcore_at_tok_new(line);
527                         if (g_slist_length(tokens) < VAL_ONE) {
528                                 msg("invalid message");
529                                 pbindex_reset();
530                                 goto EXIT;
531                         }
532                 }
533                 res.result = PB_SUCCESS;
534                 res.index = atoi(g_slist_nth_data(tokens, 0));
535                 __pbindex.current_index++;
536                 if(__pbindex.current_index >= __pbindex.used_count){
537                         dbg("RESET");
538                         res.next_index = 0;
539                         pbindex_reset();
540                 }else{
541                         dbg("__pbindex.current_index %d", __pbindex.current_index);
542                         res.next_index = __pbindex.indexlist[__pbindex.current_index];
543                 }
544                 num_plan = atoi(g_slist_nth_data(tokens, 2));
545                 res.ton = _find_num_plan(num_plan);
546
547                 /*Remove the quotes("") from the number string*/
548                 temp = g_slist_nth_data(tokens, 1);
549                 member =  util_removeQuotes((void*)temp);
550                 memcpy(res.number, member, strlen(member));
551                 dbg("number %s - %d", res.number, strlen((const char*)res.number));
552                 free(member);
553                 member = NULL;
554
555                 /*Remove the quotes("") from the name string*/
556                 temp = g_slist_nth_data(tokens, 3);
557                 member =  util_removeQuotes((void*)temp);
558                 memcpy(res.name, member, strlen(member));
559                 dbg("name %s - %d", res.name, strlen((const char*)res.name));
560                 free(member);
561                 member = NULL;
562                 res.dcs = PB_TEXT_ASCII;
563                 res.name_len = strlen((const char*)res.name);
564                 if(NULL != g_slist_nth_data(tokens, VAL_FOUR)) {
565                         if(atoi(g_slist_nth_data(tokens, VAL_FOUR)) == VAL_ZERO) {
566                                 dbg("phonebook entry not hidden");
567                         }
568                         else{
569                                 dbg("phonebook entry hidden");
570                         }
571                 }
572
573                 if(NULL != g_slist_nth_data(tokens, VAL_SIX)){
574                         num_len =  strlen(g_slist_nth_data(tokens, VAL_SIX));
575                         snprintf((char *)res.anr1, num_len+1, "%s", (char*)g_slist_nth_data(tokens, VAL_SIX));
576                 }
577
578                 if(NULL != g_slist_nth_data(tokens, VAL_SEVEN)){
579                         num_plan = atoi(g_slist_nth_data(tokens, VAL_SEVEN));
580                         res.anr1_ton = _find_num_plan(num_plan);
581                 }
582
583                 if(NULL != g_slist_nth_data(tokens, VAL_NINE)){
584                         name_len = strlen(g_slist_nth_data(tokens, VAL_NINE));
585                         memcpy(res.email1, g_slist_nth_data(tokens, VAL_NINE), name_len);
586                 }
587         }
588         else{
589                 dbg("RESPONSE NOK");
590                 pbindex_reset();
591         }
592 EXIT:
593         tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_read_record), &res);
594         free(selected_pb);
595         selected_pb = NULL;
596         tcore_at_tok_free(tokens);
597         dbg(" Function exit");
598
599 }
600
601 static void on_response_update_record(TcorePending *p, int data_len, const void *data, void *user_data)
602 {
603         const TcoreATResponse *resp = data;
604         UserRequest *ur = NULL;
605         struct tresp_phonebook_update_record res;
606         dbg(" Function entry ");
607
608         if(resp->success > VAL_ZERO) {
609                 dbg("RESPONSE OK");
610                 res.result = PB_SUCCESS;
611         }
612         else{
613                 dbg("RESPONSE NOK");
614                 res.result = PB_FAIL;
615         }
616
617         ur = tcore_pending_ref_user_request(p);
618         if (ur){
619                 tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_update_record),
620                                 &res);
621         }
622         else{
623                 dbg("error - current ur is NULL");
624         }
625         dbg(" Function exit");
626 }
627
628 static void on_response_delete_record(TcorePending *p, int data_len, const void *data, void *user_data)
629 {
630         const TcoreATResponse *resp = data;
631         UserRequest *ur = NULL;
632         struct tresp_phonebook_delete_record res;
633
634         dbg(" Function entry ");
635
636         if(resp->success > VAL_ZERO) {
637                 dbg("RESPONSE OK");
638                 res.result = PB_SUCCESS;
639         }
640         else{
641                 dbg("RESPONSE NOK");
642                 res.result = PB_FAIL;
643         }
644
645         ur = tcore_pending_ref_user_request(p);
646         if (ur){
647                 tcore_user_request_send_response(ur, _find_resp_command(ur), sizeof(struct tresp_phonebook_delete_record), &res);
648         }
649         else{
650                 dbg("error - current ur is NULL");
651         }
652         dbg(" Function exit");
653 }
654
655 static void _response_get_support_list(TcorePending *p, int data_len, const void *data, void *user_data)
656 {
657         const TcoreATResponse *resp = data;
658         CoreObject*o = NULL;
659         GSList *tokens=NULL;
660         const char *line;
661         char *temp = NULL;
662         char *pbtype = NULL;
663         struct tnoti_phonebook_status noti_data = {0,};
664
665         dbg(" Function entry ");
666
667         o = tcore_pending_ref_core_object(p);
668         if(!o){
669                 dbg("error -  core object is null");
670                 return;
671         }
672
673         noti_data.b_init = FALSE;
674
675         if(resp->success > VAL_ZERO) {
676                 dbg("RESPONSE OK");
677                 if(resp->lines) {
678                         line = (const char*)resp->lines->data;
679                         tokens = tcore_at_tok_new(line);
680                         if (g_slist_length(tokens) < VAL_ONE) {
681                                 msg("invalid message");
682                                 goto EXIT;
683                         }
684                 }
685
686                 temp = (char*)g_slist_nth_data(tokens, VAL_ZERO);
687                 pbtype = strtok(temp, "(,)");
688                 while(pbtype != NULL) {
689                         temp =  util_removeQuotes((void*)pbtype);
690                         dbg("pbtype %s", temp);
691                         if (VAL_ZERO == strcmp(temp, "FD")) {
692                                 dbg("SIM fixed-dialing phonebook");
693                                 noti_data.support_list.b_fdn = VAL_ONE;
694                         }
695                         else if (VAL_ZERO == strcmp(temp, "SN")) {
696                                 dbg("Service Dialing Number");
697                                 noti_data.support_list.b_sdn = VAL_ONE;
698                         }
699                         else if (VAL_ZERO == strcmp(temp, "SM")) {
700                                 dbg("2G SIM ADN phonebook");
701                                 noti_data.support_list.b_adn = VAL_ONE;
702                         }
703                         else if (VAL_ZERO == strcmp(temp, "LD")) {
704                                 dbg("SIM/UICC last-dialling-phonebook");
705                         }
706                         else if (VAL_ZERO == strcmp(temp, "ON")) {
707                                 dbg("SIM (or MT) own numbers (MSISDNs) list");
708                         }
709                         else if (VAL_ZERO == strcmp(temp, "BL")) {
710                                 dbg("Blacklist phonebook");
711                         }
712                         else if (VAL_ZERO == strcmp(temp, "EC")) {
713                                 dbg("SIM emergency-call-codes phonebook");
714                         }
715                         else if (VAL_ZERO == strcmp(temp, "AP")) {
716                                 dbg("Selected application phonebook");
717                         }
718                         else if (VAL_ZERO == strcmp(temp, "BN")) {
719                                 dbg("SIM barred-dialling-number");
720                         }
721                         pbtype = strtok (NULL, "(,)");
722                         free(temp);
723                 }
724
725                 noti_data.b_init = TRUE;
726                 tcore_phonebook_set_support_list(o, &noti_data.support_list);
727                 tcore_phonebook_set_status(o, noti_data.b_init);
728         }
729         else{
730                 dbg("RESPONSE NOK");
731                 tcore_phonebook_set_status(o, noti_data.b_init);
732         }
733 EXIT:
734         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_PHONEBOOK_STATUS,
735                         sizeof(struct tnoti_phonebook_status), &noti_data);
736         tcore_at_tok_free(tokens);
737         dbg(" Function exit");
738 }
739
740 static  TReturn _get_support_list(CoreObject *o)
741 {
742         TcoreHal *hal = NULL;
743         TcoreATRequest *req = NULL;
744         TcorePending *pending = NULL;
745         char *cmd_str = NULL;
746
747         dbg(" Function entry ");
748
749         if (!o){
750                 return TCORE_RETURN_EINVAL;
751         }
752
753         hal = tcore_object_get_hal(o);
754         pending = tcore_pending_new(o, VAL_ZERO);
755
756         cmd_str = g_strdup_printf("AT+CPBS=?");
757         req = tcore_at_request_new(cmd_str, "+CPBS:", TCORE_AT_SINGLELINE);
758         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
759
760         tcore_pending_set_request_data(pending, VAL_ZERO, req);
761         tcore_pending_set_response_callback(pending, _response_get_support_list, NULL);
762
763         tcore_hal_send_request(hal, pending);
764
765         g_free(cmd_str);
766         dbg(" Function exit");
767         return TCORE_RETURN_SUCCESS;
768 }
769
770 static  TReturn _select(CoreObject *o, UserRequest *ur, enum tel_phonebook_type pbt)
771 {
772         TcoreHal *hal = NULL;
773         TcoreATRequest *req = NULL;
774         TcorePending *pending = NULL;
775         char *cmd_str = NULL;
776         const struct treq_phonebook_get_count *req_data;
777         int *pb_type = NULL;
778         char *phonebook_type = NULL;
779         UserRequest *ur_dup = NULL;
780
781         dbg(" Function entry ");
782
783         if (!o || !ur)
784                 return TCORE_RETURN_EINVAL;
785
786         req_data = tcore_user_request_ref_data(ur, NULL);
787         ur_dup = tcore_user_request_ref(ur);
788
789         phonebook_type = (char*)_get_phonebook_type(req_data->phonebook_type);
790         if(NULL == phonebook_type){
791                 err("phonebook_type is NULL");
792                 return TCORE_RETURN_FAILURE;
793         }
794
795         pb_type = calloc(sizeof(enum tel_phonebook_type),VAL_ONE);
796         if(pb_type == NULL) {
797                 err("Failed to allocate memory");
798                 return TCORE_RETURN_FAILURE;
799         }
800         *pb_type = pbt;
801
802         cmd_str = g_strdup_printf("AT+CPBS=\"%s\"", phonebook_type);
803         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
804         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
805
806         hal = tcore_object_get_hal(o);
807         pending = tcore_pending_new(o, VAL_ZERO);
808         tcore_pending_set_request_data(pending, VAL_ZERO, req);
809         tcore_pending_set_response_callback(pending, _on_response_select, (void*)pb_type);
810         tcore_pending_link_user_request(pending, ur_dup);
811
812         tcore_hal_send_request(hal, pending);
813
814         free(phonebook_type);
815         g_free(cmd_str);
816         dbg(" Function exit");
817         return TCORE_RETURN_SUCCESS;
818 }
819
820 static  TReturn _getindexlist(CoreObject *o, UserRequest *ur, enum tel_phonebook_type pbt)
821 {
822         TcoreHal *hal = NULL;
823         TcoreATRequest *req = NULL;
824         TcorePending *pending = NULL;
825         char *cmd_str = NULL;
826         const struct treq_phonebook_get_count *req_data;
827         int start_index = 1;
828         int *pb_type = NULL;
829         UserRequest *ur_dup = NULL;
830
831         dbg(" Function entry ");
832
833         if (!o || !ur)
834                 return TCORE_RETURN_EINVAL;
835
836         pb_type = calloc(sizeof(enum tel_phonebook_type),1);
837         if(pb_type == NULL) {
838                 err("Failed to allocate memory");
839                 return TCORE_RETURN_FAILURE;
840         }
841         *pb_type = pbt;
842
843         req_data = tcore_user_request_ref_data(ur, NULL);
844         ur_dup = tcore_user_request_ref(ur);
845
846         cmd_str = g_strdup_printf("AT+CPBR=%d,%d", start_index, __pbindex.total_count);
847         req = tcore_at_request_new(cmd_str,  "+CPBR:", TCORE_AT_MULTILINE);
848         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
849
850         hal = tcore_object_get_hal(o);
851         pending = tcore_pending_new(o, 0);
852
853         tcore_pending_set_request_data(pending, 0, req);
854         tcore_pending_set_response_callback(pending, _on_response_getindexlist, (void*)pb_type);
855         tcore_pending_link_user_request(pending, ur_dup);
856         tcore_hal_send_request(hal, pending);
857
858         free(cmd_str);
859         dbg(" Function exit");
860         return TCORE_RETURN_SUCCESS;
861 }
862
863 static  TReturn s_get_count(CoreObject *o, UserRequest *ur)
864 {
865         TcoreHal *hal = NULL;
866         TcoreATRequest *req = NULL;
867         TcorePending *pending = NULL;
868         char *cmd_str = NULL;
869         const struct treq_phonebook_get_count *req_data = NULL;
870         enum tel_phonebook_type pbt = PB_TYPE_UNKNOWNN;
871
872         dbg("Function Entry");
873         if (!o || !ur)
874                 return TCORE_RETURN_EINVAL;
875
876         req_data = tcore_user_request_ref_data(ur, NULL);
877         pbt = tcore_phonebook_get_selected_type(o);
878         if (req_data->phonebook_type != pbt) {
879                 dbg("req pb[%d] is different with tcore pb[%d]", req_data->phonebook_type, pbt);
880                 return _select(o, ur, req_data->phonebook_type);
881         }
882
883         cmd_str = g_strdup_printf("AT+CPBS?");
884         req = tcore_at_request_new(cmd_str, "+CPBS:", TCORE_AT_SINGLELINE);
885         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
886
887         hal = tcore_object_get_hal(o);
888         pending = tcore_pending_new(o, VAL_ZERO);
889
890         tcore_pending_set_request_data(pending, VAL_ZERO, req);
891         tcore_pending_set_response_callback(pending, on_response_get_count, hal);
892         tcore_pending_link_user_request(pending, ur);
893
894         tcore_hal_send_request(hal, pending);
895
896         g_free(cmd_str);
897         dbg("Function exit");
898         return TCORE_RETURN_SUCCESS;
899 }
900
901 static  TReturn s_get_info(CoreObject *o, UserRequest *ur)
902 {
903         TcoreHal *hal = NULL;
904         TcoreATRequest *req = NULL;
905         TcorePending *pending = NULL;
906         char *cmd_str = NULL;
907         const struct treq_phonebook_get_info *req_data = NULL;
908         enum tel_phonebook_type pbt = PB_TYPE_UNKNOWNN;
909         int *pb_type = NULL;
910
911         dbg(" Function entry ");
912
913         if (!o || !ur)
914                 return TCORE_RETURN_EINVAL;
915
916         req_data = tcore_user_request_ref_data(ur, NULL);
917         pbt = tcore_phonebook_get_selected_type(o);
918         if (req_data->phonebook_type != pbt) {
919                 dbg("req pb[%d] is different with tcore pb[%d]", req_data->phonebook_type, pbt);
920                 return _select(o, ur, req_data->phonebook_type);
921         }
922
923         pb_type = calloc(sizeof(enum tel_phonebook_type),VAL_ONE);
924         if(pb_type == NULL) {
925                 err("Failed to allocate memory");
926                 return TCORE_RETURN_FAILURE;
927         }
928         *pb_type = pbt;
929         dbg("pb_type %d", *pb_type);
930
931         cmd_str = g_strdup_printf("AT+CPBF=?");
932         req = tcore_at_request_new(cmd_str, "+CPBF:", TCORE_AT_SINGLELINE);
933         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
934
935         hal = tcore_object_get_hal(o);
936         pending = tcore_pending_new(o, VAL_ZERO);
937
938         tcore_pending_set_request_data(pending, VAL_ZERO, req);
939         tcore_pending_set_response_callback(pending, on_response_get_info, (void*)pb_type);
940         tcore_pending_link_user_request(pending, ur);
941
942         tcore_hal_send_request(hal, pending);
943
944         g_free(cmd_str);
945         dbg(" Function exit");
946         return TCORE_RETURN_SUCCESS;
947
948 }
949
950 static TReturn s_get_usim_info(CoreObject *o, UserRequest *ur)
951 {
952         dbg("NOT IMPLEMENTED");
953
954         return TCORE_RETURN_SUCCESS;
955 }
956
957 static TReturn s_read_record(CoreObject *o, UserRequest *ur)
958 {
959         TcoreHal*hal = NULL;
960         TcoreATRequest *req = NULL;
961         TcorePending *pending = NULL;
962         char *cmd_str = NULL;
963         const struct treq_phonebook_read_record *req_data = NULL;
964         enum tel_phonebook_type pbt = PB_TYPE_UNKNOWNN;
965         int *pb_type = NULL;
966
967         dbg(" Function entry ");
968
969         if (!o || !ur)
970                 return TCORE_RETURN_EINVAL;
971
972         req_data = tcore_user_request_ref_data(ur, NULL);
973         pbt = tcore_phonebook_get_selected_type(o);
974         if (req_data->phonebook_type != pbt) {
975                 dbg("req pb[%d] is different with tcore pb[%d]", req_data->phonebook_type, pbt);
976                 return _select(o, ur, req_data->phonebook_type);
977         }
978         if(!__pbindex.indexlist_populated){
979                 return _getindexlist(o, ur, req_data->phonebook_type);
980         }
981         pb_type = calloc(sizeof(enum tel_phonebook_type),VAL_ONE);
982         if(pb_type == NULL) {
983                 err("Failed to allocate memory");
984                 return TCORE_RETURN_FAILURE;
985         }
986         *pb_type = pbt;
987         dbg("pb_type %d", *pb_type);
988         cmd_str = g_strdup_printf("AT+CPBR=%d", __pbindex.indexlist[__pbindex.current_index]);
989         req = tcore_at_request_new(cmd_str, "+CPBR", TCORE_AT_MULTILINE);
990         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
991
992         hal = tcore_object_get_hal(o);
993         pending = tcore_pending_new(o, VAL_ZERO);
994
995         tcore_pending_set_request_data(pending, VAL_ZERO, req);
996         tcore_pending_set_response_callback(pending, on_response_read_record, (void*)pb_type);
997         tcore_pending_link_user_request(pending, ur);
998
999         tcore_hal_send_request(hal, pending);
1000
1001         g_free(cmd_str);
1002         dbg(" Function exit");
1003         return TCORE_RETURN_SUCCESS;
1004 }
1005
1006 static  TReturn s_update_record(CoreObject *o, UserRequest *ur)
1007 {
1008         TcoreHal *hal = NULL;
1009         TcoreATRequest *req = NULL;
1010         TcorePending *pending = NULL;
1011         char *cmd_str = NULL;
1012         const struct treq_phonebook_update_record *req_data = NULL;
1013         enum tel_phonebook_type pbt = PB_TYPE_UNKNOWNN;
1014
1015         dbg(" Function entry ");
1016
1017         if (!o || !ur)
1018                 return TCORE_RETURN_EINVAL;
1019
1020         req_data = tcore_user_request_ref_data(ur, NULL);
1021         pbt = tcore_phonebook_get_selected_type(o);
1022         if (req_data->phonebook_type != pbt) {
1023                 dbg("req pb[%d] is different with tcore pb[%d]", req_data->phonebook_type, pbt);
1024                 return _select(o, ur, req_data->phonebook_type);
1025         }
1026
1027         cmd_str = g_strdup_printf("AT+CPBW=,\"%s\",%d,\"%s\"", req_data->number, ((PB_TON_INTERNATIONAL == req_data->ton) ? TON_INTERNATIONAL: TON_UNKNOWN), req_data->name);
1028         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_SINGLELINE);
1029         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
1030
1031         hal = tcore_object_get_hal(o);
1032         pending = tcore_pending_new(o, VAL_ZERO);
1033
1034         tcore_pending_set_request_data(pending, VAL_ZERO, req);
1035         tcore_pending_set_response_callback(pending, on_response_update_record, hal);
1036         tcore_pending_link_user_request(pending, ur);
1037
1038         tcore_hal_send_request(hal, pending);
1039
1040         g_free(cmd_str);
1041         dbg(" Function exit");
1042         return TCORE_RETURN_SUCCESS;
1043 }
1044
1045 static  TReturn s_delete_record(CoreObject *o, UserRequest *ur)
1046 {
1047         TcoreHal *hal = NULL;
1048         TcoreATRequest *req = NULL;
1049         TcorePending *pending = NULL;
1050         char *cmd_str = NULL;
1051         const struct treq_phonebook_delete_record *req_data;
1052         enum tel_phonebook_type pbt = PB_TYPE_UNKNOWNN;
1053
1054         dbg(" Function entry ");
1055
1056         if (!o || !ur)
1057                 return TCORE_RETURN_EINVAL;
1058
1059         req_data = tcore_user_request_ref_data(ur, NULL);
1060         pbt = tcore_phonebook_get_selected_type(o);
1061         if (req_data->phonebook_type != pbt) {
1062                 dbg("req pb[%d] is different with tcore pb[%d]", req_data->phonebook_type, pbt);
1063                 return _select(o, ur, req_data->phonebook_type);
1064         }
1065
1066         cmd_str = g_strdup_printf("AT+CPBW=%d", req_data->index);
1067         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_SINGLELINE);
1068         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
1069
1070         hal = tcore_object_get_hal(o);
1071         pending = tcore_pending_new(o, VAL_ZERO);
1072
1073         tcore_pending_set_request_data(pending, VAL_ZERO, req);
1074         tcore_pending_set_response_callback(pending, on_response_delete_record, hal);
1075         tcore_pending_link_user_request(pending, ur);
1076
1077         tcore_hal_send_request(hal, pending);
1078
1079         g_free(cmd_str);
1080         dbg(" Function exit");
1081         return TCORE_RETURN_SUCCESS;
1082 }
1083
1084 static struct tcore_phonebook_operations phonebook_ops = {
1085         .get_count = s_get_count,
1086         .get_info = s_get_info,
1087         .get_usim_info = s_get_usim_info,
1088         .read_record = s_read_record,
1089         .update_record = s_update_record,
1090         .delete_record = s_delete_record,
1091 };
1092
1093 gboolean s_phonebook_init(TcorePlugin *cp, CoreObject *co_phonebook)
1094 {
1095         dbg("Entry");
1096
1097         tcore_phonebook_override_ops(co_phonebook, &phonebook_ops);
1098
1099         tcore_object_override_callback(co_phonebook, "+PBREADY", on_event_phonebook_status, NULL);
1100
1101         dbg("Exit");
1102
1103         return TRUE;
1104 }
1105
1106 void s_phonebook_exit(TcorePlugin *cp, CoreObject *co_phonebook)
1107 {
1108         dbg("Exit");
1109 }