4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved
6 * Contact: Ankit Jogi <ankit.jogi@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
29 #include <core_object.h>
32 #include <user_request.h>
35 #include <co_phonebook.h>
38 #include "imc_phonebook.h"
52 /* Type Of Number and Number Plan */
53 #define IMC_TON_INTERNATIONAL 145
54 #define IMC_TON_UNKNOWN 129
55 #define IMC_NUM_PLAN_INTERNATIONAL 0x0070
56 #define IMC_NUM_PLAN_UNKNOWN 0x0060
58 #define IMC_PB_INFO_LENGTH 5
61 GSList *used_index_fdn;
62 gboolean used_index_fdn_valid;
64 GSList *used_index_adn;
65 gboolean used_index_adn_valid;
67 GSList *used_index_sdn;
68 gboolean used_index_sdn_valid;
70 GSList *used_index_usim;
71 gboolean used_index_usim_valid;
74 /******************************************************************************
76 *****************************************************************************/
77 static gint __phonebook_compare_index(gconstpointer a, gconstpointer b)
79 guint index1 = (guint)a;
80 guint index2 = (guint)b;
82 return index1 - index2;
85 static enum tel_phonebook_field_type __phonebook_convert_field_type(int field_type)
89 return PB_FIELD_NUMBER;
97 return PB_FIELD_EMAIL1;
103 static enum tel_phonebook_ton __phonebook_find_num_plan(int number_plan)
105 enum tel_phonebook_ton result;
106 dbg("number_plan : 0x%04x", number_plan);
108 if (number_plan & IMC_NUM_PLAN_INTERNATIONAL)
109 result = PB_TON_INTERNATIONAL;
111 result = PB_TON_UNKNOWN;
113 dbg("result : %d", result);
118 static gboolean __phonebook_get_pb_type_str(enum tel_phonebook_type pb_type,
119 gchar **req_type_str)
121 g_assert(req_type_str != NULL);
125 *req_type_str = g_strdup("FD");
129 *req_type_str = g_strdup("SM");
132 *req_type_str = g_strdup("SN");
135 warn("Unsupported Phonebook type");
136 *req_type_str = g_strdup("NS");
143 static gboolean __phonebook_check_and_select_type(CoreObject *co,
144 enum tel_phonebook_type req_pb_type, gchar **set_pb_cmd)
146 struct tel_phonebook_support_list *support_list;
147 enum tel_phonebook_type current_type;
149 /* Check whether pb_type is supported or not */
150 support_list = tcore_phonebook_get_support_list(co);
152 if ((req_pb_type == PB_TYPE_FDN && support_list->b_fdn == FALSE)
153 || (req_pb_type == PB_TYPE_ADN && support_list->b_adn == FALSE)
154 || (req_pb_type == PB_TYPE_SDN && support_list->b_sdn == FALSE)
155 || (req_pb_type == PB_TYPE_USIM && support_list->b_usim == FALSE)) {
156 err("Not supported Phonebook type");
158 g_free(support_list);
161 g_free(support_list);
164 /* Check Current type & Request type */
165 current_type = tcore_phonebook_get_selected_type(co);
166 if (current_type != req_pb_type) {
167 gchar *req_pb_type_str = NULL;
169 __phonebook_get_pb_type_str(req_pb_type, &req_pb_type_str);
170 dbg("Add AT-Command to change [%s] Type", req_pb_type_str);
172 /* Select Phonebook type */
173 *set_pb_cmd = g_strdup_printf("AT+CPBS=\"%s\";", req_pb_type_str);
175 g_free(req_pb_type_str);
177 *set_pb_cmd = g_strdup_printf("AT");
183 static gboolean __phonebook_update_index_list_by_type(CoreObject *co,
184 enum tel_phonebook_type pb_type, guint req_index)
187 PrivateInfo *private_info = tcore_object_ref_user_data(co);
188 g_assert(private_info != NULL);
192 list = private_info->used_index_fdn;
196 list = private_info->used_index_adn;
200 list = private_info->used_index_sdn;
204 list = private_info->used_index_usim;
208 warn("Unsupported Phonebook type: [%d]", pb_type);
213 * Check if 'index' is already available (UPDATE operation).
216 if ((guint)list->data == req_index) {
218 * index 'present', no need to update
220 dbg("Index: [%d] present in Phonebook type: [%d]",
225 list = g_slist_next(list);
229 * 'index' is NOT available (ADD operation),
230 * insert 'index' to corresponding index list.
234 private_info->used_index_fdn = g_slist_insert_sorted(
235 private_info->used_index_fdn,
237 __phonebook_compare_index);
239 /* Update Phonebook list valid */
240 if (private_info->used_index_fdn_valid != TRUE)
241 private_info->used_index_fdn_valid = TRUE;
245 private_info->used_index_adn = g_slist_insert_sorted(
246 private_info->used_index_adn,
248 __phonebook_compare_index);
250 /* Update Phonebook list valid */
251 if (private_info->used_index_adn_valid != TRUE)
252 private_info->used_index_adn_valid = TRUE;
256 private_info->used_index_sdn = g_slist_insert_sorted(
257 private_info->used_index_sdn,
259 __phonebook_compare_index);
261 /* Update Phonebook list valid */
262 if (private_info->used_index_sdn_valid != TRUE)
263 private_info->used_index_sdn_valid = TRUE;
267 private_info->used_index_usim = g_slist_insert_sorted(
268 private_info->used_index_usim,
270 __phonebook_compare_index);
272 /* Update Phonebook list valid */
273 if (private_info->used_index_usim_valid != TRUE)
274 private_info->used_index_usim_valid = TRUE;
278 warn("Unexpected Phonebook type: [%d]", pb_type);
279 g_assert_not_reached();
286 static gboolean __phonebook_get_index_list_by_type(CoreObject *co,
287 enum tel_phonebook_type pb_type, GSList **list)
289 PrivateInfo *private_info = tcore_object_ref_user_data(co);
290 g_assert(private_info != NULL);
294 if (private_info->used_index_fdn_valid != TRUE)
296 *list = private_info->used_index_fdn;
300 if (private_info->used_index_adn_valid != TRUE)
302 *list = private_info->used_index_adn;
306 if (private_info->used_index_sdn_valid != TRUE)
308 *list = private_info->used_index_sdn;
312 if (private_info->used_index_usim_valid != TRUE)
314 *list = private_info->used_index_usim;
318 warn("Unsupported Phonebook type");
326 static void __phonebook_check_used_index(CoreObject *co,
327 enum tel_phonebook_type pb_type, guint req_index, guint *used_index)
331 /* Get used_index list by req_type */
332 if (__phonebook_get_index_list_by_type(co, pb_type, &list) != TRUE) {
333 err("used_index list is NOT valid");
334 *used_index = req_index;
338 /* Use first used_index in case req_index is not used */
339 *used_index = (guint)g_slist_nth_data(list, VAL_ZERO);
341 if ((guint)list->data == req_index) {
343 * req_index is equal to one of used_index
345 *used_index = req_index;
348 list = g_slist_next(list);
352 static void __on_resp_phonebook_get_support_list(TcorePending *p,
353 int data_len, const void *data, void *user_data)
355 const TcoreATResponse *resp = data;
357 CoreObject *co_phonebook = tcore_pending_ref_core_object(p);
358 TcorePlugin *plugin = tcore_object_ref_plugin(co_phonebook);
360 struct tnoti_phonebook_status noti_data = {0, };
364 noti_data.b_init = FALSE;
366 if (resp && resp->success > VAL_ZERO) {
371 GSList *tokens = NULL;
372 char *pb_type = NULL;
376 if (resp->lines == NULL) {
377 warn("Invalid notification");
381 line = (const char *)resp->lines->data;
382 tokens = tcore_at_tok_new(line);
383 if (g_slist_length(tokens) < VAL_ONE) {
384 warn("Invalid notification - 'number' of tokens: [%d]",
385 g_slist_length(tokens));
388 tcore_at_tok_free(tokens);
393 temp = (char *)g_slist_nth_data(tokens, VAL_ZERO);
394 pb_type = strtok_r(temp, "(,)", &ptr);
396 while (pb_type != NULL) {
397 temp = tcore_at_tok_extract(pb_type);
398 dbg("pbtype %s", temp);
400 if (VAL_ZERO == g_strcmp0(temp, "FD")) {
401 dbg("SIM fixed-dialing Phonebook");
402 noti_data.support_list.b_fdn = TRUE;
403 } else if (VAL_ZERO == g_strcmp0(temp, "SN")) {
404 dbg("Service Dialing Number");
405 noti_data.support_list.b_sdn = TRUE;
406 } else if (VAL_ZERO == g_strcmp0(temp, "SM")) {
407 CoreObject *co_sim = NULL;
408 enum tel_sim_type sim_type = SIM_TYPE_UNKNOWN;
411 co_sim = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SIM);
412 if (co_sim == NULL) {
413 err("SIM Core object is NULL");
416 tcore_at_tok_free(tokens);
422 sim_type = tcore_sim_get_type(co_sim);
423 dbg("SIM type: [%d]", sim_type);
424 if (sim_type == SIM_TYPE_USIM) { /* 3G SIM */
425 noti_data.support_list.b_usim = TRUE;
426 dbg("3G SIM - USIM Phonebook");
427 } else { /* 2G SIM */
428 noti_data.support_list.b_adn = TRUE;
429 dbg("2G SIM - ADN Phonebook");
431 } else if (VAL_ZERO == g_strcmp0(temp, "LD")) {
432 dbg("SIM/UICC - last-dialling-phonebook");
433 } else if (VAL_ZERO == g_strcmp0(temp, "ON")) {
434 dbg("SIM (or MT) own numbers (MSISDNs) list");
435 } else if (VAL_ZERO == g_strcmp0(temp, "BL")) {
436 dbg("Blacklist phonebook");
437 } else if (VAL_ZERO == g_strcmp0(temp, "EC")) {
438 dbg("SIM emergency-call-codes phonebook");
439 } else if (VAL_ZERO == g_strcmp0(temp, "AP")) {
440 dbg("Selected application phonebook");
441 } else if (VAL_ZERO == g_strcmp0(temp, "BN")) {
442 dbg("SIM barred-dialling-number");
445 pb_type = strtok_r(NULL, "(,)", &ptr);
451 tcore_at_tok_free(tokens);
453 dbg("FDN: [%s] ADN: [%s] SDN: [%s] USIM: [%s]",
454 noti_data.support_list.b_fdn ? "TRUE" : "FALSE",
455 noti_data.support_list.b_adn ? "TRUE" : "FALSE",
456 noti_data.support_list.b_sdn ? "TRUE" : "FALSE",
457 noti_data.support_list.b_usim ? "TRUE" : "FALSE");
459 /* Phonebook initialized */
460 noti_data.b_init = TRUE;
463 tcore_phonebook_set_support_list(co_phonebook, ¬i_data.support_list);
464 tcore_phonebook_set_status(co_phonebook, noti_data.b_init);
469 tcore_phonebook_set_status(co_phonebook, noti_data.b_init);
476 * Phonebook status (TNOTI_PHONEBOOK_STATUS)
478 tcore_server_send_notification(tcore_plugin_ref_server(plugin),
480 TNOTI_PHONEBOOK_STATUS,
481 sizeof(struct tnoti_phonebook_status), ¬i_data);
487 * Operation - get_support_list
490 * AT-Command: AT+CPBS=?
493 * Success: (Single line)
494 * (list of supported <storage>s)
497 * +CME ERROR: <error>
499 static void __phonebook_get_support_list(CoreObject *co_phonebook)
506 err("Core object is NULL");
510 ret = tcore_prepare_and_send_at_request(co_phonebook,
511 "AT+CPBS=?", "+CPBS",
514 __on_resp_phonebook_get_support_list, NULL,
517 dbg("ret: [0x%x]", ret);
520 static void __on_resp_phonebook_get_used_index(TcorePending *p,
521 int data_len, const void *data, void *user_data)
523 const struct tcore_at_response *at_resp = data;
524 CoreObject *co = tcore_pending_ref_core_object(p);
526 g_assert(at_resp != NULL);
530 if (at_resp->success > VAL_ZERO) {
533 if (at_resp->lines == NULL) {
534 err("at_resp->lines is NULL");
536 GSList *lines = at_resp->lines;
537 enum tel_phonebook_type req_pb_type;
538 GSList **list = NULL;
539 PrivateInfo *private_info = tcore_object_ref_user_data(co);
541 g_assert(private_info != NULL);
543 req_pb_type = (enum tel_phonebook_type)GPOINTER_TO_INT(user_data);
545 /* Select used_index_list by req_type */
546 switch (req_pb_type) {
548 list = &private_info->used_index_fdn;
549 private_info->used_index_fdn_valid = TRUE;
553 list = &private_info->used_index_adn;
554 private_info->used_index_adn_valid = TRUE;
558 list = &private_info->used_index_sdn;
559 private_info->used_index_sdn_valid = TRUE;
563 list = &private_info->used_index_usim;
564 private_info->used_index_usim_valid = TRUE;
568 warn("Unsupported phonebook: [%d]", req_pb_type);
573 const gchar *line = lines->data;
574 GSList *tokens = NULL;
577 dbg("Line: [%s]", line);
579 tokens = tcore_at_tok_new(line);
580 if (tokens == NULL) {
581 err("tokens is NULL");
585 /* Get only used_index */
586 temp = g_slist_nth_data(tokens, VAL_ZERO);
588 /* Insert used_index in PrivateInfo sorted in ascending */
589 *list = g_slist_insert_sorted(*list,
590 (gpointer)atoi(temp),
591 __phonebook_compare_index);
593 tcore_at_tok_free(tokens);
596 lines = g_slist_next(lines);
599 dbg("pb_type: [%d], used_index Length: [%d]",
600 req_pb_type, g_slist_length(*list));
607 static void __phonebook_get_used_index(CoreObject *co,
608 enum tel_phonebook_type pb_type, guint max_index)
616 at_cmd = g_strdup_printf("AT+CPBR=1,%d", max_index);
618 /* Send Request to Modem */
619 ret = tcore_prepare_and_send_at_request(co,
623 __on_resp_phonebook_get_used_index, GINT_TO_POINTER(pb_type),
626 dbg("ret: [0x%x]", ret);
632 /******************************************************************************
633 * Phonebook Response functions
634 *****************************************************************************/
635 static void on_resp_get_count(TcorePending *p,
636 int data_len, const void *data, void *user_data)
638 const struct treq_phonebook_get_count *req_data = NULL;
639 struct tresp_phonebook_get_count resp_get_count;
640 const TcoreATResponse *resp = data;
641 UserRequest *ur = NULL;
645 ur = tcore_pending_ref_user_request(p);
651 req_data = (const struct treq_phonebook_get_count *)tcore_user_request_ref_data(ur, NULL);
653 memset(&resp_get_count, 0x00, sizeof(struct tresp_phonebook_get_count));
654 resp_get_count.result = PB_FAIL;
655 resp_get_count.type = req_data->phonebook_type;
657 if (resp && resp->success > VAL_ZERO) {
658 PrivateInfo *private_info;
659 CoreObject *co = tcore_pending_ref_core_object(p);
660 enum tel_phonebook_type pb_type;
662 GSList *tokens = NULL;
667 if (resp->lines == NULL) {
668 err("invalid message");
672 temp = (char *)resp->lines->data;
673 tokens = tcore_at_tok_new(temp);
674 if (g_slist_length(tokens) < VAL_THREE) {
676 * No of tokens must be three.
677 * We cannot proceed without used and total count.
679 err("Invalid response - 'number' of tokens: [%d]", g_slist_length(tokens));
682 tcore_at_tok_free(tokens);
687 resp_get_count.result = PB_SUCCESS;
690 temp = g_slist_nth_data(tokens, VAL_ONE);
692 resp_get_count.used_count = atoi(temp);
695 temp = g_slist_nth_data(tokens, VAL_TWO);
697 resp_get_count.total_count = atoi(temp);
699 dbg("Used count [%d] Total count: [%d]", resp_get_count.used_count, resp_get_count.total_count);
702 tcore_at_tok_free(tokens);
704 pb_type = resp_get_count.type;
706 /* Updated selected Phonebook type */
707 tcore_phonebook_set_selected_type(co, pb_type);
710 * Cache 'used_index' by req_type if valid used_index is NOT TRUE.
712 private_info = tcore_object_ref_user_data(co);
713 if ((pb_type == PB_TYPE_FDN && private_info->used_index_fdn_valid == FALSE)
714 || (pb_type == PB_TYPE_ADN && private_info->used_index_adn_valid == FALSE)
715 || (pb_type == PB_TYPE_SDN && private_info->used_index_sdn_valid == FALSE)
716 || (pb_type == PB_TYPE_USIM && private_info->used_index_usim_valid == FALSE)) {
717 /* Cache 'used' index list */
718 __phonebook_get_used_index(co, pb_type, resp_get_count.total_count);
725 tcore_user_request_send_response(ur,
726 TRESP_PHONEBOOK_GETCOUNT,
727 sizeof(struct tresp_phonebook_get_count), &resp_get_count);
732 static void on_resp_get_info(TcorePending *p,
733 int data_len, const void *data, void *user_data)
735 const struct treq_phonebook_get_info *req_data = NULL;
736 struct tresp_phonebook_get_info resp_get_info;
737 const TcoreATResponse *resp = data;
738 UserRequest *ur = NULL;
742 ur = tcore_pending_ref_user_request(p);
748 req_data = (const struct treq_phonebook_get_info *)tcore_user_request_ref_data(ur, NULL);
750 memset(&resp_get_info, 0x00, sizeof(struct tresp_phonebook_get_info));
752 resp_get_info.result = PB_FAIL;
753 resp_get_info.type = req_data->phonebook_type;
754 dbg("Phonebook type: [%d]", resp_get_info.type);
756 if (resp && resp->success > VAL_ZERO) {
757 PrivateInfo *private_info;
758 CoreObject *co = tcore_pending_ref_core_object(p);
759 enum tel_phonebook_type pb_type;
761 GSList *tokens = NULL;
763 GSList *lines = resp->lines;
768 if (resp->lines == NULL) {
769 err("invalid message");
774 * +CPBS: <storage>[,<used>][,total]
776 line = g_slist_nth_data(lines, VAL_ZERO);
777 dbg("First Line: [%s]", line);
778 tokens = tcore_at_tok_new(line);
779 if (tokens == NULL) {
780 err("invalid message");
785 temp = g_slist_nth_data(tokens, VAL_ONE);
787 resp_get_info.used_count = atoi(temp);
790 temp = g_slist_nth_data(tokens, VAL_TWO);
792 resp_get_info.index_max = atoi(temp);
794 resp_get_info.index_min = 1;
796 dbg("Used count: [%d] Total count (index_max): [%d] " \
797 "Minimum count (index_min): [%d]",
798 resp_get_info.used_count, resp_get_info.index_max,
799 resp_get_info.index_min);
802 tcore_at_tok_free(tokens);
804 resp_get_info.result = PB_SUCCESS;
807 * +CPBF: [<nlength>],[<tlength>],[<glength>],[<slength>],[<elength>]
809 line = g_slist_nth_data(lines, VAL_ONE);
810 dbg("Second Line: [%s]", line);
811 tokens = tcore_at_tok_new(line);
812 if (tokens == NULL) {
813 err("invalid message");
817 /* Fetch <nlength> */
818 temp = g_slist_nth_data(tokens, VAL_ONE);
820 resp_get_info.number_length_max = atoi(temp);
822 /* Fetch <tlength> */
823 temp = g_slist_nth_data(tokens, VAL_ONE);
825 resp_get_info.text_length_max = atoi(temp);
827 dbg("Number length: [%d] Test length: [%d]",
828 resp_get_info.number_length_max, resp_get_info.text_length_max);
831 tcore_at_tok_free(tokens);
833 pb_type = resp_get_info.type;
835 /* Updated selected Phonebook type */
836 tcore_phonebook_set_selected_type(co, pb_type);
839 * Cache 'used_index' by req_type if valid used_index is NOT TRUE.
841 private_info = tcore_object_ref_user_data(co);
842 if ((pb_type == PB_TYPE_FDN && private_info->used_index_fdn_valid == FALSE)
843 || (pb_type == PB_TYPE_ADN && private_info->used_index_adn_valid == FALSE)
844 || (pb_type == PB_TYPE_SDN && private_info->used_index_sdn_valid == FALSE)
845 || (pb_type == PB_TYPE_USIM && private_info->used_index_usim_valid == FALSE)) {
846 /* Cache 'used' index list */
847 __phonebook_get_used_index(co, pb_type, resp_get_info.index_max);
855 tcore_user_request_send_response(ur,
856 TRESP_PHONEBOOK_GETMETAINFO,
857 sizeof(struct tresp_phonebook_get_info), &resp_get_info);
862 static void on_resp_get_usim_info(TcorePending *p,
863 int data_len, const void *data, void *user_data)
865 struct tresp_phonebook_get_usim_info res_get_usim_info;
866 const TcoreATResponse *resp = data;
867 UserRequest *ur = NULL;
871 ur = tcore_pending_ref_user_request(p);
873 dbg("error - current ur is NULL");
877 memset(&res_get_usim_info, 0x00, sizeof(struct tresp_phonebook_get_usim_info));
878 res_get_usim_info.result = PB_FAIL;
880 if (resp && resp->success > VAL_ZERO) {
881 PrivateInfo *private_info;
882 CoreObject *co = tcore_pending_ref_core_object(p);
884 GSList *tokens = NULL;
886 GSList *lines = resp->lines;
887 int used = 0, total = 0;
888 int nlen = 0, tlen = 0, glen = 0, slen = 0, elen = 0;
889 enum tel_phonebook_field_type phonebook_field_type;
895 if (resp->lines == NULL) {
896 err("invalid message");
901 * +CPBS: <storage>[,<used>][,total]
903 line = g_slist_nth_data(lines, VAL_ZERO);
904 dbg("First Line: [%s]", line);
905 tokens = tcore_at_tok_new(line);
906 if (tokens == NULL) {
907 err("invalid message");
912 temp = g_slist_nth_data(tokens, VAL_ONE);
917 temp = g_slist_nth_data(tokens, VAL_TWO);
921 dbg("used_count %d index_max %d", used, total);
924 tcore_at_tok_free(tokens);
927 * +CPBF: [<nlength>],[<tlength>],[<glength>],[<slength>],[<elength>]
929 line = g_slist_nth_data(lines, VAL_ONE);
930 dbg("Second Line: [%s]", line);
931 tokens = tcore_at_tok_new(line);
932 if (tokens == NULL) {
933 err("invalid message");
937 /* Fetch <nlength> */
938 temp = g_slist_nth_data(tokens, VAL_ZERO);
942 /* Fetch <tlength> */
943 temp = g_slist_nth_data(tokens, VAL_ONE);
947 /* Fetch <glength> */
948 temp = g_slist_nth_data(tokens, VAL_TWO);
952 /* Fetch <slength> */
953 temp = g_slist_nth_data(tokens, VAL_THREE);
957 /* Fetch <elength> */
958 temp = g_slist_nth_data(tokens, VAL_FOUR);
962 dbg("Length - Number: [%d] Test: [%d] Group: [%d] " \
963 "Second name: [%d] e-mail: [%d]",
964 nlen, tlen, glen, slen, elen);
966 for (field_type = 1; field_type <= IMC_PB_INFO_LENGTH; field_type++) {
967 phonebook_field_type = __phonebook_convert_field_type(field_type);
969 res_get_usim_info.field_list[field_type-1].field = phonebook_field_type;
970 res_get_usim_info.field_list[field_type-1].used_count = used;
971 res_get_usim_info.field_list[field_type-1].index_max = total;
973 switch (phonebook_field_type) {
974 case PB_FIELD_NUMBER:
975 res_get_usim_info.field_list[field_type-1].text_max = nlen;
979 res_get_usim_info.field_list[field_type-1].text_max = tlen;
983 res_get_usim_info.field_list[field_type-1].text_max = glen;
987 res_get_usim_info.field_list[field_type-1].text_max = slen;
990 case PB_FIELD_EMAIL1:
991 res_get_usim_info.field_list[field_type-1].text_max = elen;
995 warn("Unsupported Phonebook field type: [%d]", phonebook_field_type);
1000 res_get_usim_info.field_count = IMC_PB_INFO_LENGTH;
1001 res_get_usim_info.result = PB_SUCCESS;
1003 /* Free resources */
1004 tcore_at_tok_free(tokens);
1006 /* Updated selected Phonebook type */
1007 tcore_phonebook_set_selected_type(co, PB_TYPE_USIM);
1010 * Cache 'used_index' for PB_TYPE_USIM if valid used_index is NOT TRUE.
1012 private_info = tcore_object_ref_user_data(co);
1013 if (private_info->used_index_usim_valid == FALSE) {
1014 /* Cache 'used' index list */
1015 __phonebook_get_used_index(co, PB_TYPE_USIM, total);
1021 tcore_user_request_send_response(ur,
1022 TRESP_PHONEBOOK_GETUSIMINFO,
1023 sizeof(struct tresp_phonebook_get_usim_info), &res_get_usim_info);
1027 static void on_resp_read_record(TcorePending *p,
1028 int data_len, const void *data, void *user_data)
1030 const struct treq_phonebook_read_record *req_data = NULL;
1031 struct tresp_phonebook_read_record resp_read_record;
1032 const TcoreATResponse *resp = data;
1033 UserRequest *ur = NULL;
1037 ur = tcore_pending_ref_user_request(p);
1039 dbg("error - current ur is NULL");
1043 req_data = tcore_user_request_ref_data(ur, NULL);
1045 memset(&resp_read_record, 0x00, sizeof(struct tresp_phonebook_read_record));
1047 resp_read_record.result = PB_FAIL;
1048 resp_read_record.phonebook_type = req_data->phonebook_type;
1050 if (resp && resp->success > VAL_ZERO) {
1051 CoreObject *co = tcore_pending_ref_core_object(p);
1052 GSList *list = NULL;
1054 GSList *tokens = NULL;
1057 int num_plan = VAL_ZERO;
1058 char *number = NULL, *name = NULL, *additional_number = NULL;
1059 char *sne = NULL, *email = NULL;
1064 if (resp->lines == NULL) {
1065 err("invalid message");
1070 * +CPBR: <index>,<number>,<type>,<text>[,<hidden>][,<group>]
1071 * [,<adnumber>][,<adtype>][,<secondtext>][,<email>]]
1073 line = (const char *)resp->lines->data;
1074 tokens = tcore_at_tok_new(line);
1075 if (g_slist_length(tokens) < VAL_ONE) {
1076 err("invalid message");
1081 temp = g_slist_nth_data(tokens, VAL_ZERO);
1086 resp_read_record.index = atoi(temp);
1088 /* Fetch <number> */
1089 temp = g_slist_nth_data(tokens, VAL_ONE);
1094 number = tcore_at_tok_extract(temp);
1095 g_strlcpy((char *)resp_read_record.number,
1096 (const gchar *)number, PHONEBOOK_NUMBER_BYTE_MAX+1);
1100 temp = g_slist_nth_data(tokens, VAL_TWO);
1105 num_plan = atoi(temp);
1106 resp_read_record.ton = __phonebook_find_num_plan(num_plan);
1109 temp = g_slist_nth_data(tokens, VAL_THREE);
1114 name = tcore_at_tok_extract(temp);
1116 g_strlcpy((char *)resp_read_record.name,
1117 (const gchar *)name, PHONEBOOK_NAME_BYTE_MAX+1);
1118 resp_read_record.name_len = strlen((const char *)resp_read_record.name);
1119 resp_read_record.dcs = PB_TEXT_ASCII;
1123 /* All 'mandatory' fields are extracted */
1124 resp_read_record.result = PB_SUCCESS;
1126 /* Updated selected Phonebook type */
1127 tcore_phonebook_set_selected_type(co, req_data->phonebook_type);
1129 /* Get used_index list by req_type */
1130 if (__phonebook_get_index_list_by_type(co,
1131 req_data->phonebook_type, &list) == TRUE) {
1133 if ((guint)list->data == resp_read_record.index) {
1134 if ((list = g_slist_next(list)) != NULL) {
1135 /* If exist, set next_index */
1136 resp_read_record.next_index = (guint)list->data;
1137 dbg("next_index is [%u]", resp_read_record.next_index);
1139 /* read_record.index is the end of used_index */
1140 resp_read_record.next_index = 0;
1141 dbg("End of used_index");
1145 list = g_slist_next(list);
1148 /* No PrivateInfo */
1149 resp_read_record.next_index = 0;
1152 /* Fetch <hidden> */
1153 temp = g_slist_nth_data(tokens, VAL_FOUR);
1155 dbg("Phonebook entry is hidden");
1157 /* Fetch <adnumber> */
1158 temp = g_slist_nth_data(tokens, VAL_SIX);
1159 additional_number = tcore_at_tok_extract(temp);
1160 if (additional_number) {
1161 g_strlcpy((char *)resp_read_record.anr1,
1162 (const gchar *)additional_number, PHONEBOOK_NUMBER_BYTE_MAX+1);
1163 g_free(additional_number);
1166 /* Fetch <adtype> */
1167 temp = g_slist_nth_data(tokens, VAL_SEVEN);
1168 name = tcore_at_tok_extract(temp);
1170 num_plan = atoi(temp);
1171 resp_read_record.anr1_ton = __phonebook_find_num_plan(num_plan);
1174 /* Fetch <secondtext> */
1175 temp = g_slist_nth_data(tokens, VAL_EIGHT);
1180 sne = tcore_at_tok_extract(temp);
1182 g_strlcpy((char *)resp_read_record.sne,
1183 (const gchar *)sne, PHONEBOOK_NAME_BYTE_MAX+1);
1184 resp_read_record.sne_len = strlen((const char *)resp_read_record.sne);
1185 resp_read_record.sne_dcs = PB_TEXT_ASCII;
1190 temp = g_slist_nth_data(tokens, VAL_NINE);
1195 email = tcore_at_tok_extract(temp);
1197 g_strlcpy((char *)resp_read_record.email1,
1198 (const gchar *)email, PHONEBOOK_EMAIL_BYTE_MAX+1);
1199 resp_read_record.email1_len = strlen((const char *)resp_read_record.email1);
1204 /* Free resources */
1205 tcore_at_tok_free(tokens);
1207 dbg("RESPONSE NOK");
1211 tcore_user_request_send_response(ur,
1212 TRESP_PHONEBOOK_READRECORD,
1213 sizeof(struct tresp_phonebook_read_record), &resp_read_record);
1218 static void on_resp_update_record(TcorePending *p,
1219 int data_len, const void *data, void *user_data)
1221 const TcoreATResponse *resp = data;
1222 UserRequest *ur = NULL;
1223 struct tresp_phonebook_update_record resp_update_record;
1227 ur = tcore_pending_ref_user_request(p);
1229 if (resp && resp->success > VAL_ZERO) {
1230 const struct treq_phonebook_update_record *req_data = NULL;
1231 CoreObject *co = tcore_pending_ref_core_object(p);
1235 resp_update_record.result = PB_SUCCESS;
1237 req_data = tcore_user_request_ref_data(ur, NULL);
1239 /* Updated selected Phonebook type */
1240 tcore_phonebook_set_selected_type(co, req_data->phonebook_type);
1243 * Need to update the corresponding index list.
1245 * in case 'not available' (ADD operation) - ADD index
1246 * in case 'available' (UPDATE operation) - NO change
1248 __phonebook_update_index_list_by_type(co,
1249 req_data->phonebook_type, req_data->index);
1251 dbg("RESPONSE NOK");
1252 resp_update_record.result = PB_FAIL;
1257 tcore_user_request_send_response(ur,
1258 TRESP_PHONEBOOK_UPDATERECORD,
1259 sizeof(struct tresp_phonebook_update_record), &resp_update_record);
1267 static void on_resp_delete_record(TcorePending *p,
1268 int data_len, const void *data, void *user_data)
1270 const TcoreATResponse *resp = data;
1271 UserRequest *ur = NULL;
1272 struct tresp_phonebook_delete_record resp_delete_record;
1276 ur = tcore_pending_ref_user_request(p);
1278 if (resp && resp->success > VAL_ZERO) {
1279 const struct treq_phonebook_delete_record *req_data = NULL;
1280 CoreObject *co = tcore_pending_ref_core_object(p);
1281 GSList *list = NULL;
1285 resp_delete_record.result = PB_SUCCESS;
1287 req_data = tcore_user_request_ref_data(ur, NULL);
1289 /* Updated selected Phonebook type */
1290 tcore_phonebook_set_selected_type(co, req_data->phonebook_type);
1292 /* Get used_index list by req_type */
1293 if (__phonebook_get_index_list_by_type(co,
1294 req_data->phonebook_type, &list) != TRUE) {
1295 err("used_index list is NOT valid");
1297 const int del_index = (const int)req_data->index;
1298 list = g_slist_remove(list, (gconstpointer)del_index);
1299 dbg("Remove index: [%u] list: [0x%x]", req_data->index, list);
1302 dbg("RESPONSE NOK");
1303 resp_delete_record.result = PB_FAIL;
1307 tcore_user_request_send_response(ur,
1308 TRESP_PHONEBOOK_DELETERECORD,
1309 sizeof(struct tresp_phonebook_delete_record), &resp_delete_record);
1316 /******************************************************************************
1317 * Phonebook Request functions
1318 *****************************************************************************/
1320 * Operation - get_count
1323 * AT-Command: AT+CPBS?
1326 * Success: (Single line)
1327 * +CPBS: <storage>[,<used>][,total]
1330 * <storage> Phonebook storage type
1331 * <used> Number of records 'used'
1332 * <total> 'total' number of records available
1335 * +CME ERROR: <error>
1337 static TReturn imc_get_count(CoreObject *co, UserRequest *ur)
1339 struct treq_phonebook_get_count *req_data = NULL;
1343 TReturn ret = TCORE_RETURN_FAILURE;
1347 req_data = (struct treq_phonebook_get_count *)tcore_user_request_ref_data(ur, NULL);
1349 /* Check whether pb_type is supported or not, and Select pb_type */
1350 if (__phonebook_check_and_select_type(co,
1351 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1352 warn("Requested phonebok type '%d' is NOT supported",
1353 req_data->phonebook_type);
1358 at_cmd = g_strdup_printf("%s+CPBS?", set_pb_cmd);
1360 /* Send Request to Modem */
1361 ret = tcore_prepare_and_send_at_request(co,
1363 TCORE_AT_SINGLELINE,
1365 on_resp_get_count, NULL,
1369 /* Free resources */
1377 * Operation - get_info
1380 * AT-Command: AT+CPBS?;+CPBF=?
1383 * Success: (Multi line)
1384 * +CPBS: <storage>[,<used>][,total]
1385 * +CPBF: [<nlength>],[<tlength>],[<glength>],[<slength>],[<elength>]
1388 * <storage> Phonebook storage type
1389 * <used> Number of records 'used'
1390 * <total> 'total' number of records available
1391 * <nlength> Maximum length of field <number>
1392 * <tlength> Maximum length of field <text>
1393 * <glength> Maximum length of field <group>
1394 * <slength> Maximum length of field <secondtext>
1395 * <elength> Maximum length of field <email>
1398 * +CME ERROR: <error>
1400 static TReturn imc_get_info(CoreObject *co, UserRequest *ur)
1402 struct treq_phonebook_get_info *req_data = NULL;
1406 TReturn ret = TCORE_RETURN_FAILURE;
1410 req_data = (struct treq_phonebook_get_info *)tcore_user_request_ref_data(ur, NULL);
1412 /* Check whether pb_type is supported or not, and Select pb_type */
1413 if (__phonebook_check_and_select_type(co,
1414 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1415 warn("Requested phonebok type '%d' is NOT supported",
1416 req_data->phonebook_type);
1421 at_cmd = g_strdup_printf("%s+CPBS?;+CPBF=?", set_pb_cmd);
1423 /* Send Request to Modem */
1424 ret = tcore_prepare_and_send_at_request(co,
1428 on_resp_get_info, NULL,
1432 /* Free resources */
1440 * Operation - get_usim_info
1443 * AT-Command: AT+CPBS?;+CPBF=?
1446 * Success: (Multi line)
1447 * +CPBS: <storage>[,<used>][,total]
1448 * +CPBF: [<nlength>],[<tlength>],[<glength>],[<slength>],[<elength>]
1451 * <storage> Phonebook storage type
1452 * <used> Number of records 'used'
1453 * <total> 'total' number of records available
1454 * <nlength> Maximum length of field <number>
1455 * <tlength> Maximum length of field <text>
1456 * <glength> Maximum length of field <group>
1457 * <slength> Maximum length of field <secondtext>
1458 * <elength> Maximum length of field <email>
1461 * +CME ERROR: <error>
1463 static TReturn imc_get_usim_info(CoreObject *co, UserRequest *ur)
1468 TReturn ret = TCORE_RETURN_FAILURE;
1472 /* Check whether pb_type is supported or not, and Select pb_type */
1473 if (__phonebook_check_and_select_type(co, PB_TYPE_USIM, &set_pb_cmd) != TRUE) {
1474 warn("Requested phonebok type '%d' is NOT supported", PB_TYPE_USIM);
1479 at_cmd = g_strdup_printf("%s+CPBS?;+CPBF=?", set_pb_cmd);
1481 /* Send Request to Modem */
1482 ret = tcore_prepare_and_send_at_request(co,
1486 on_resp_get_usim_info, NULL,
1490 /* Free resources */
1498 * Operation - read_record
1501 * AT-Command: AT+CPBR=<index>
1504 * 1 Integer type values in range of location numbers of phonebook memory
1508 * Success: (Single line);
1509 * +CPBR: <index>,<number>,<type>,<text>[,<hidden>][,<group>]
1510 * [,<adnumber>][,<adtype>][,<secondtext>][,<email>]]
1513 * <number> String type phone number of format <type>
1514 * <type> Type of address octet in integer format
1515 * <text> String type field of maximum length <tlength>
1516 * <hidden> Indicates if the entry is hidden or not – only available,
1517 * if a UICC with an active USIM application is present
1518 * 0 Phonebook entry not hidden
1519 * 1 Phonebook entry hidden
1520 * <group> String type field of maximum length <glength>
1521 * <adnumber> String type phone number of format <adtype>
1522 * <adtype> Type of address octet in integer format
1523 * <secondtext> String type field of maximum length <slength>
1524 * <email> String type field of maximum length <elength>
1527 * +CME ERROR: <error>
1529 static TReturn imc_read_record(CoreObject *co, UserRequest *ur)
1531 const struct treq_phonebook_read_record *req_data = NULL;
1534 guint used_index = 0;
1536 TReturn ret = TCORE_RETURN_FAILURE;
1540 req_data = tcore_user_request_ref_data(ur, NULL);
1542 /* Check whether pb_type is supported or not, and Select pb_type */
1543 if (__phonebook_check_and_select_type(co,
1544 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1545 warn("Requested phonebok type '%d' is NOT supported",
1546 req_data->phonebook_type);
1550 /* Check whether index is used or not */
1551 __phonebook_check_used_index(co,
1552 req_data->phonebook_type, req_data->index, &used_index);
1555 at_cmd = g_strdup_printf("%s+CPBR=%u", set_pb_cmd, used_index);
1557 /* Send Request to Modem */
1558 ret = tcore_prepare_and_send_at_request(co,
1560 TCORE_AT_SINGLELINE,
1562 on_resp_read_record, NULL,
1566 /* Free resources */
1574 * Operation - update_record
1577 * AT-Command: AT+CPBW=[<index>][,<number>[,<type>[,<text>[,<group>[,<adnumber>
1578 * [,<adtype>[,<secondtext>[,<email>[,<hidden>]]]]]]]]]
1580 * ... same read_record Operation
1583 * Success: (No Result)
1586 * +CME ERROR: <error>
1588 static TReturn imc_update_record(CoreObject *co, UserRequest *ur)
1590 const struct treq_phonebook_update_record *req_data = NULL;
1594 TReturn ret = TCORE_RETURN_FAILURE;
1598 req_data = tcore_user_request_ref_data(ur, NULL);
1600 /* Check whether pb_type is supported or not, and Select pb_type */
1601 if (__phonebook_check_and_select_type(co,
1602 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1603 warn("Requested phonebok type '%d' is NOT supported",
1604 req_data->phonebook_type);
1608 /* Set AT-Command according pb_type */
1609 if (req_data->phonebook_type == PB_TYPE_USIM) {
1610 at_cmd = g_strdup_printf("%s+CPBW=%u,\"%s\",%d,\"%s\",,\"%s\",,\"%s\",\"%s\"",
1611 set_pb_cmd, req_data->index,
1613 ((PB_TON_INTERNATIONAL == req_data->ton) ? IMC_TON_INTERNATIONAL : IMC_TON_UNKNOWN),
1614 req_data->name, req_data->anr1,
1615 req_data->sne, req_data->email1);
1617 at_cmd = g_strdup_printf("%s+CPBW=%u,\"%s\",,\"%s\"",
1618 set_pb_cmd, req_data->index,
1619 req_data->number, req_data->name);
1622 /* Send Request to Modem */
1623 ret = tcore_prepare_and_send_at_request(co,
1627 on_resp_update_record, NULL,
1631 /* Free resources */
1639 * Operation - delete_record
1642 * AT-Command: AT+CPBW=<index>
1645 * 1 Integer type values in range of location numbers of phonebook memory
1649 * Success: (No Result)
1652 * +CME ERROR: <error>
1654 static TReturn imc_delete_record(CoreObject *co, UserRequest *ur)
1656 const struct treq_phonebook_delete_record *req_data;
1660 TReturn ret = TCORE_RETURN_FAILURE;
1664 req_data = tcore_user_request_ref_data(ur, NULL);
1666 /* Check whether pb_type is supported or not, and Select pb_type */
1667 if (__phonebook_check_and_select_type(co,
1668 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1669 warn("Requested phonebok type '%d' is NOT supported",
1670 req_data->phonebook_type);
1675 at_cmd = g_strdup_printf("%s+CPBW=%u", set_pb_cmd, req_data->index);
1677 /* Send Request to Modem */
1678 ret = tcore_prepare_and_send_at_request(co,
1682 on_resp_delete_record, NULL,
1686 /* Free resources */
1693 /******************************************************************************
1694 * Phonebook Notification function(s)
1695 *****************************************************************************/
1696 static gboolean on_noti_phonebook_status(CoreObject *co_phonebook,
1697 const void *event_info, void *user_data)
1699 dbg("Received [+PBREADY]");
1702 * Get supported list of Phonebook types
1704 __phonebook_get_support_list(co_phonebook);
1709 /* Phonebook operations */
1710 static struct tcore_phonebook_operations phonebook_ops = {
1711 .get_count = imc_get_count,
1712 .get_info = imc_get_info,
1713 .get_usim_info = imc_get_usim_info,
1714 .read_record = imc_read_record,
1715 .update_record = imc_update_record,
1716 .delete_record = imc_delete_record,
1719 gboolean imc_phonebook_init(TcorePlugin *cp, CoreObject *co_phonebook)
1721 PrivateInfo *private_info;
1725 /* Set operations */
1726 tcore_phonebook_set_ops(co_phonebook, &phonebook_ops, TCORE_OPS_TYPE_CP);
1728 /* Set PrivateInfo */
1729 private_info = g_malloc0(sizeof(PrivateInfo));
1730 tcore_object_link_user_data(co_phonebook, private_info);
1733 tcore_object_add_callback(co_phonebook,
1735 on_noti_phonebook_status, co_phonebook);
1742 void imc_phonebook_exit(TcorePlugin *cp, CoreObject *co_phonebook)
1744 PrivateInfo *private_info;
1746 private_info = tcore_object_ref_user_data(co_phonebook);
1747 g_assert(private_info != NULL);
1749 /* Free PrivateInfo */
1750 g_slist_free_full(private_info->used_index_fdn, g_free);
1751 g_slist_free_full(private_info->used_index_adn, g_free);
1752 g_slist_free_full(private_info->used_index_sdn, g_free);
1753 g_slist_free_full(private_info->used_index_usim, g_free);
1754 g_free(private_info);
1756 /* Remove Callbacks */
1757 tcore_object_del_callback(co_phonebook,
1758 "+PBREADY", on_noti_phonebook_status);