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