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;
112 result = PB_TON_UNKNOWN;
114 dbg("result : %d", result);
119 static gboolean __phonebook_get_pb_type_str(enum tel_phonebook_type pb_type,
120 gchar **req_type_str)
122 g_assert(req_type_str != NULL);
126 *req_type_str = g_strdup("FD");
130 *req_type_str = g_strdup("SM");
133 *req_type_str = g_strdup("SN");
136 warn("Unsupported Phonebook type");
137 *req_type_str = g_strdup("NS");
144 static gboolean __phonebook_check_and_select_type(CoreObject *co,
145 enum tel_phonebook_type req_pb_type, gchar **set_pb_cmd)
147 struct tel_phonebook_support_list *support_list;
148 enum tel_phonebook_type current_type;
150 /* Check whether pb_type is supported or not */
151 support_list = tcore_phonebook_get_support_list(co);
153 if ((req_pb_type == PB_TYPE_FDN && support_list->b_fdn == FALSE)
154 || (req_pb_type == PB_TYPE_ADN && support_list->b_adn == FALSE)
155 || (req_pb_type == PB_TYPE_SDN && support_list->b_sdn == FALSE)
156 || (req_pb_type == PB_TYPE_USIM && support_list->b_usim == FALSE)) {
157 err("Not supported Phonebook type");
159 g_free(support_list);
162 g_free(support_list);
165 /* Check Current type & Request type */
166 current_type = tcore_phonebook_get_selected_type(co);
167 if (current_type != req_pb_type) {
168 gchar *req_pb_type_str = NULL;
170 __phonebook_get_pb_type_str(req_pb_type, &req_pb_type_str);
171 dbg("Add AT-Command to change [%s] Type", req_pb_type_str);
173 /* Select Phonebook type */
174 *set_pb_cmd = g_strdup_printf("AT+CPBS=\"%s\";", req_pb_type_str);
176 g_free(req_pb_type_str);
178 *set_pb_cmd = g_strdup_printf("AT");
184 static gboolean __phonebook_update_index_list_by_type(CoreObject *co,
185 enum tel_phonebook_type pb_type, guint req_index)
188 PrivateInfo *private_info = tcore_object_ref_user_data(co);
189 g_assert(private_info != NULL);
193 list = private_info->used_index_fdn;
197 list = private_info->used_index_adn;
201 list = private_info->used_index_sdn;
205 list = private_info->used_index_usim;
209 warn("Unsupported Phonebook type: [%d]", pb_type);
214 * Check if 'index' is already available (UPDATE operation).
217 if ((guint)list->data == req_index) {
219 * index 'present', no need to update
221 dbg("Index: [%d] present in Phonebook type: [%d]",
226 list = g_slist_next(list);
230 * 'index' is NOT available (ADD operation),
231 * insert 'index' to corresponding index list.
235 private_info->used_index_fdn = g_slist_insert_sorted(
236 private_info->used_index_fdn,
238 __phonebook_compare_index);
240 /* Update Phonebook list valid */
241 if (private_info->used_index_fdn_valid != TRUE)
242 private_info->used_index_fdn_valid = TRUE;
246 private_info->used_index_adn = g_slist_insert_sorted(
247 private_info->used_index_adn,
249 __phonebook_compare_index);
251 /* Update Phonebook list valid */
252 if (private_info->used_index_adn_valid != TRUE)
253 private_info->used_index_adn_valid = TRUE;
257 private_info->used_index_sdn = g_slist_insert_sorted(
258 private_info->used_index_sdn,
260 __phonebook_compare_index);
262 /* Update Phonebook list valid */
263 if (private_info->used_index_sdn_valid != TRUE)
264 private_info->used_index_sdn_valid = TRUE;
268 private_info->used_index_usim = g_slist_insert_sorted(
269 private_info->used_index_usim,
271 __phonebook_compare_index);
273 /* Update Phonebook list valid */
274 if (private_info->used_index_usim_valid != TRUE)
275 private_info->used_index_usim_valid = TRUE;
279 warn("Unexpected Phonebook type: [%d]", pb_type);
280 g_assert_not_reached();
287 static gboolean __phonebook_get_index_list_by_type(CoreObject *co,
288 enum tel_phonebook_type pb_type, GSList **list)
290 PrivateInfo *private_info = tcore_object_ref_user_data(co);
291 g_assert(private_info != NULL);
295 if (private_info->used_index_fdn_valid != TRUE)
297 *list = private_info->used_index_fdn;
301 if (private_info->used_index_adn_valid != TRUE)
303 *list = private_info->used_index_adn;
307 if (private_info->used_index_sdn_valid != TRUE)
309 *list = private_info->used_index_sdn;
313 if (private_info->used_index_usim_valid != TRUE)
315 *list = private_info->used_index_usim;
319 warn("Unsupported Phonebook type");
327 static void __phonebook_check_used_index(CoreObject *co,
328 enum tel_phonebook_type pb_type, guint req_index, guint *used_index)
332 /* Get used_index list by req_type */
333 if (__phonebook_get_index_list_by_type(co, pb_type, &list) != TRUE) {
334 err("used_index list is NOT valid");
335 *used_index = req_index;
339 /* Use first used_index in case req_index is not used */
340 *used_index = (guint)g_slist_nth_data(list, VAL_ZERO);
342 if ((guint)list->data == req_index) {
344 * req_index is equal to one of used_index
346 *used_index = req_index;
349 list = g_slist_next(list);
353 static void __on_resp_phonebook_get_support_list(TcorePending *p,
354 int data_len, const void *data, void *user_data)
356 const TcoreATResponse *resp = data;
358 CoreObject *co_phonebook = tcore_pending_ref_core_object(p);
359 TcorePlugin *plugin = tcore_object_ref_plugin(co_phonebook);
361 struct tnoti_phonebook_status noti_data = {0, };
365 noti_data.b_init = FALSE;
367 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(temp, "(,)");
395 while (pb_type != NULL) {
396 temp = tcore_at_tok_extract(pb_type);
397 dbg("pbtype %s", temp);
399 if (VAL_ZERO == g_strcmp0(temp, "FD")) {
400 dbg("SIM fixed-dialing Phonebook");
401 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;
407 else if (VAL_ZERO == g_strcmp0(temp, "SM")) {
408 CoreObject *co_sim = NULL;
409 enum tel_sim_type sim_type = SIM_TYPE_UNKNOWN;
412 co_sim = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SIM);
413 if (co_sim == NULL) {
414 err("SIM Core object is NULL");
417 tcore_at_tok_free(tokens);
423 sim_type = tcore_sim_get_type(co_sim);
424 dbg("SIM type: [%d]", sim_type);
425 if (sim_type == SIM_TYPE_USIM) { /* 3G SIM */
426 noti_data.support_list.b_usim = TRUE;
427 dbg("3G SIM - USIM Phonebook");
430 noti_data.support_list.b_adn = TRUE;
431 dbg("2G SIM - ADN Phonebook");
434 else if (VAL_ZERO == g_strcmp0(temp, "LD")) {
435 dbg("SIM/UICC - last-dialling-phonebook");
437 else if (VAL_ZERO == g_strcmp0(temp, "ON")) {
438 dbg("SIM (or MT) own numbers (MSISDNs) list");
440 else if (VAL_ZERO == g_strcmp0(temp, "BL")) {
441 dbg("Blacklist phonebook");
443 else if (VAL_ZERO == g_strcmp0(temp, "EC")) {
444 dbg("SIM emergency-call-codes phonebook");
446 else if (VAL_ZERO == g_strcmp0(temp, "AP")) {
447 dbg("Selected application phonebook");
449 else if (VAL_ZERO == g_strcmp0(temp, "BN")) {
450 dbg("SIM barred-dialling-number");
453 pb_type = strtok (NULL, "(,)");
458 tcore_at_tok_free(tokens);
460 dbg("FDN: [%s] ADN: [%s] SDN: [%s] USIM: [%s]",
461 noti_data.support_list.b_fdn ? "TRUE" : "FALSE",
462 noti_data.support_list.b_adn ? "TRUE" : "FALSE",
463 noti_data.support_list.b_sdn ? "TRUE" : "FALSE",
464 noti_data.support_list.b_usim ? "TRUE" : "FALSE");
466 /* Phonebook initialized */
467 noti_data.b_init = TRUE;
470 tcore_phonebook_set_support_list(co_phonebook, ¬i_data.support_list);
471 tcore_phonebook_set_status(co_phonebook, noti_data.b_init);
477 tcore_phonebook_set_status(co_phonebook, noti_data.b_init);
484 * Phonebook status (TNOTI_PHONEBOOK_STATUS)
486 tcore_server_send_notification(tcore_plugin_ref_server(plugin),
488 TNOTI_PHONEBOOK_STATUS,
489 sizeof(struct tnoti_phonebook_status), ¬i_data);
495 * Operation - get_support_list
498 * AT-Command: AT+CPBS=?
501 * Success: (Single line)
502 * (list of supported <storage>s)
505 * +CME ERROR: <error>
507 static void __phonebook_get_support_list(CoreObject *co_phonebook)
514 err("Core object is NULL");
518 ret = tcore_prepare_and_send_at_request(co_phonebook,
519 "AT+CPBS=?", "+CPBS",
522 __on_resp_phonebook_get_support_list, NULL,
525 dbg("ret: [0x%x]", ret);
528 static void __on_resp_phonebook_get_used_index(TcorePending *p,
529 int data_len, const void *data, void *user_data)
531 const struct tcore_at_response *at_resp = data;
532 CoreObject *co = tcore_pending_ref_core_object(p);
534 g_assert(at_resp != NULL);
538 if (at_resp->success > VAL_ZERO) {
541 if (at_resp->lines == NULL) {
542 err("at_resp->lines is NULL");
544 GSList *lines = at_resp->lines;
545 enum tel_phonebook_type req_pb_type;
546 GSList **list = NULL;
547 PrivateInfo *private_info = tcore_object_ref_user_data(co);
549 g_assert(private_info != NULL);
551 req_pb_type = (enum tel_phonebook_type)GPOINTER_TO_INT(user_data);
553 /* Select used_index_list by req_type */
554 switch (req_pb_type) {
556 list = &private_info->used_index_fdn;
557 private_info->used_index_fdn_valid = TRUE;
561 list = &private_info->used_index_adn;
562 private_info->used_index_adn_valid = TRUE;
566 list = &private_info->used_index_sdn;
567 private_info->used_index_sdn_valid = TRUE;
571 list = &private_info->used_index_usim;
572 private_info->used_index_usim_valid = TRUE;
576 warn("Unsupported phonebook: [%d]", req_pb_type);
581 const gchar *line = lines->data;
582 GSList *tokens = NULL;
585 dbg("Line: [%s]", line);
587 tokens = tcore_at_tok_new(line);
588 if (tokens == NULL) {
589 err("tokens is NULL");
593 /* Get only used_index */
594 temp = g_slist_nth_data(tokens, VAL_ZERO);
596 /* Insert used_index in PrivateInfo sorted in ascending */
597 *list = g_slist_insert_sorted(*list,
598 (gpointer)atoi(temp),
599 __phonebook_compare_index);
601 tcore_at_tok_free(tokens);
604 lines = g_slist_next(lines);
607 dbg("pb_type: [%d], used_index Length: [%d]",
608 req_pb_type, g_slist_length(*list));
616 static void __phonebook_get_used_index(CoreObject *co,
617 enum tel_phonebook_type pb_type, guint max_index)
625 at_cmd = g_strdup_printf("AT+CPBR=1,%d", max_index);
627 /* Send Request to Modem */
628 ret = tcore_prepare_and_send_at_request(co,
632 __on_resp_phonebook_get_used_index, GINT_TO_POINTER(pb_type),
635 dbg("ret: [0x%x]", ret);
641 /******************************************************************************
642 * Phonebook Response functions
643 *****************************************************************************/
644 static void on_resp_get_count(TcorePending *p,
645 int data_len, const void *data, void *user_data)
647 const struct treq_phonebook_get_count *req_data = NULL;
648 struct tresp_phonebook_get_count resp_get_count;
649 const TcoreATResponse *resp = data;
650 UserRequest *ur = NULL;
654 ur = tcore_pending_ref_user_request(p);
660 req_data = (const struct treq_phonebook_get_count *)tcore_user_request_ref_data(ur, NULL);
662 memset(&resp_get_count, 0x00, sizeof(struct tresp_phonebook_get_count));
663 resp_get_count.result = PB_FAIL;
664 resp_get_count.type = req_data->phonebook_type;
666 if (resp && resp->success > VAL_ZERO) {
667 PrivateInfo *private_info;
668 CoreObject *co = tcore_pending_ref_core_object(p);
669 enum tel_phonebook_type pb_type;
676 if (resp->lines == NULL) {
677 err("invalid message");
681 temp = (char *)resp->lines->data;
682 tokens = tcore_at_tok_new(temp);
683 if (g_slist_length(tokens) < VAL_THREE) {
685 * No of tokens must be three.
686 * We cannot proceed without used and total count.
688 err("Invalid response - 'number' of tokens: [%d]", g_slist_length(tokens));
691 tcore_at_tok_free(tokens);
696 resp_get_count.result = PB_SUCCESS;
699 temp = g_slist_nth_data(tokens, VAL_ONE);
701 resp_get_count.used_count = atoi(temp);
704 temp = g_slist_nth_data(tokens, VAL_TWO);
706 resp_get_count.total_count = atoi(temp);
708 dbg("Used count [%d] Total count: [%d]", resp_get_count.used_count, resp_get_count.total_count);
711 tcore_at_tok_free(tokens);
713 pb_type = resp_get_count.type;
715 /* Updated selected Phonebook type */
716 tcore_phonebook_set_selected_type(co, pb_type);
719 * Cache 'used_index' by req_type if valid used_index is NOT TRUE.
721 private_info = tcore_object_ref_user_data(co);
722 if ((pb_type == PB_TYPE_FDN && private_info->used_index_fdn_valid == FALSE)
723 || (pb_type == PB_TYPE_ADN && private_info->used_index_adn_valid == FALSE)
724 || (pb_type == PB_TYPE_SDN && private_info->used_index_sdn_valid == FALSE)
725 || (pb_type == PB_TYPE_USIM && private_info->used_index_usim_valid == FALSE)) {
726 /* Cache 'used' index list */
727 __phonebook_get_used_index(co, pb_type, resp_get_count.total_count);
735 tcore_user_request_send_response(ur,
736 TRESP_PHONEBOOK_GETCOUNT,
737 sizeof(struct tresp_phonebook_get_count), &resp_get_count);
742 static void on_resp_get_info(TcorePending *p,
743 int data_len, const void *data, void *user_data)
745 const struct treq_phonebook_get_info *req_data = NULL;
746 struct tresp_phonebook_get_info resp_get_info;
747 const TcoreATResponse *resp = data;
748 UserRequest *ur = NULL;
752 ur = tcore_pending_ref_user_request(p);
758 req_data = (const struct treq_phonebook_get_info *)tcore_user_request_ref_data(ur, NULL);
760 memset(&resp_get_info, 0x00, sizeof(struct tresp_phonebook_get_info));
762 resp_get_info.result = PB_FAIL;
763 resp_get_info.type = req_data->phonebook_type;
764 dbg("Phonebook type: [%d]", resp_get_info.type);
766 if (resp && resp->success > VAL_ZERO) {
767 PrivateInfo *private_info;
768 CoreObject *co = tcore_pending_ref_core_object(p);
769 enum tel_phonebook_type pb_type;
771 GSList *tokens = NULL;
773 GSList *lines = resp->lines;
778 if (resp->lines == NULL) {
779 err("invalid message");
784 * +CPBS: <storage>[,<used>][,total]
786 line = g_slist_nth_data(lines, VAL_ZERO);
787 dbg("First Line: [%s]", line);
788 tokens = tcore_at_tok_new(line);
789 if (tokens == NULL) {
790 err("invalid message");
795 temp = g_slist_nth_data(tokens, VAL_ONE);
797 resp_get_info.used_count = atoi(temp);
800 temp = g_slist_nth_data(tokens, VAL_TWO);
802 resp_get_info.index_max = atoi(temp);
804 resp_get_info.index_min = 1;
806 dbg("Used count: [%d] Total count (index_max): [%d] " \
807 "Minimum count (index_min): [%d]",
808 resp_get_info.used_count, resp_get_info.index_max,
809 resp_get_info.index_min);
812 tcore_at_tok_free(tokens);
814 resp_get_info.result = PB_SUCCESS;
817 * +CPBF: [<nlength>],[<tlength>],[<glength>],[<slength>],[<elength>]
819 line = g_slist_nth_data(lines, VAL_ONE);
820 dbg("Second Line: [%s]", line);
821 tokens = tcore_at_tok_new(line);
822 if (tokens == NULL) {
823 err("invalid message");
827 /* Fetch <nlength> */
828 temp = g_slist_nth_data(tokens, VAL_ONE);
830 resp_get_info.number_length_max = atoi(temp);
832 /* Fetch <tlength> */
833 temp = g_slist_nth_data(tokens, VAL_ONE);
835 resp_get_info.text_length_max = atoi(temp);
837 dbg("Number length: [%d] Test length: [%d]",
838 resp_get_info.number_length_max, resp_get_info.text_length_max);
841 tcore_at_tok_free(tokens);
843 pb_type = resp_get_info.type;
845 /* Updated selected Phonebook type */
846 tcore_phonebook_set_selected_type(co, pb_type);
849 * Cache 'used_index' by req_type if valid used_index is NOT TRUE.
851 private_info = tcore_object_ref_user_data(co);
852 if ((pb_type == PB_TYPE_FDN && private_info->used_index_fdn_valid == FALSE)
853 || (pb_type == PB_TYPE_ADN && private_info->used_index_adn_valid == FALSE)
854 || (pb_type == PB_TYPE_SDN && private_info->used_index_sdn_valid == FALSE)
855 || (pb_type == PB_TYPE_USIM && private_info->used_index_usim_valid == FALSE)) {
856 /* Cache 'used' index list */
857 __phonebook_get_used_index(co, pb_type, resp_get_info.index_max);
866 tcore_user_request_send_response(ur,
867 TRESP_PHONEBOOK_GETMETAINFO,
868 sizeof(struct tresp_phonebook_get_info), &resp_get_info);
873 static void on_resp_get_usim_info(TcorePending *p,
874 int data_len, const void *data, void *user_data)
876 struct tresp_phonebook_get_usim_info res_get_usim_info;
877 const TcoreATResponse *resp = data;
878 UserRequest *ur = NULL;
882 ur = tcore_pending_ref_user_request(p);
884 dbg("error - current ur is NULL");
888 memset(&res_get_usim_info, 0x00, sizeof(struct tresp_phonebook_get_usim_info));
889 res_get_usim_info.result = PB_FAIL;
891 if (resp && resp->success > VAL_ZERO) {
892 PrivateInfo *private_info;
893 CoreObject *co = tcore_pending_ref_core_object(p);
895 GSList *tokens = NULL;
897 GSList *lines = resp->lines;
898 int used = 0, total = 0;
899 int nlen = 0, tlen = 0, glen = 0, slen = 0, elen = 0;
900 enum tel_phonebook_field_type phonebook_field_type;
906 if (resp->lines == NULL) {
907 err("invalid message");
912 * +CPBS: <storage>[,<used>][,total]
914 line = g_slist_nth_data(lines, VAL_ZERO);
915 dbg("First Line: [%s]", line);
916 tokens = tcore_at_tok_new(line);
917 if (tokens == NULL) {
918 err("invalid message");
923 temp = g_slist_nth_data(tokens, VAL_ONE);
928 temp = g_slist_nth_data(tokens, VAL_TWO);
932 dbg("used_count %d index_max %d", used, total);
935 tcore_at_tok_free(tokens);
938 * +CPBF: [<nlength>],[<tlength>],[<glength>],[<slength>],[<elength>]
940 line = g_slist_nth_data(lines, VAL_ONE);
941 dbg("Second Line: [%s]", line);
942 tokens = tcore_at_tok_new(line);
943 if (tokens == NULL) {
944 err("invalid message");
948 /* Fetch <nlength> */
949 temp = g_slist_nth_data(tokens, VAL_ZERO);
953 /* Fetch <tlength> */
954 temp = g_slist_nth_data(tokens, VAL_ONE);
958 /* Fetch <glength> */
959 temp = g_slist_nth_data(tokens, VAL_TWO);
963 /* Fetch <slength> */
964 temp = g_slist_nth_data(tokens, VAL_THREE);
968 /* Fetch <elength> */
969 temp = g_slist_nth_data(tokens, VAL_FOUR);
973 dbg("Length - Number: [%d] Test: [%d] Group: [%d] " \
974 "Second name: [%d] e-mail: [%d]",
975 nlen, tlen, glen, slen, elen);
977 for (field_type = 1; field_type <= IMC_PB_INFO_LENGTH; field_type++) {
978 phonebook_field_type = __phonebook_convert_field_type(field_type);
980 res_get_usim_info.field_list[field_type-1].field = phonebook_field_type;
981 res_get_usim_info.field_list[field_type-1].used_count = used;
982 res_get_usim_info.field_list[field_type-1].index_max = total;
984 switch (phonebook_field_type) {
985 case PB_FIELD_NUMBER:
986 res_get_usim_info.field_list[field_type-1].text_max = nlen;
990 res_get_usim_info.field_list[field_type-1].text_max = tlen;
994 res_get_usim_info.field_list[field_type-1].text_max = glen;
998 res_get_usim_info.field_list[field_type-1].text_max = slen;
1001 case PB_FIELD_EMAIL1:
1002 res_get_usim_info.field_list[field_type-1].text_max = elen;
1006 warn("Unsupported Phonebook field type: [%d]", phonebook_field_type);
1011 res_get_usim_info.field_count = IMC_PB_INFO_LENGTH;
1012 res_get_usim_info.result = PB_SUCCESS;
1014 /* Free resources */
1015 tcore_at_tok_free(tokens);
1017 /* Updated selected Phonebook type */
1018 tcore_phonebook_set_selected_type(co, PB_TYPE_USIM);
1021 * Cache 'used_index' for PB_TYPE_USIM if valid used_index is NOT TRUE.
1023 private_info = tcore_object_ref_user_data(co);
1024 if (private_info->used_index_usim_valid == FALSE) {
1025 /* Cache 'used' index list */
1026 __phonebook_get_used_index(co, PB_TYPE_USIM, total);
1032 tcore_user_request_send_response(ur,
1033 TRESP_PHONEBOOK_GETUSIMINFO,
1034 sizeof(struct tresp_phonebook_get_usim_info), &res_get_usim_info);
1038 static void on_resp_read_record(TcorePending *p,
1039 int data_len, const void *data, void *user_data)
1041 const struct treq_phonebook_read_record *req_data = NULL;
1042 struct tresp_phonebook_read_record resp_read_record;
1043 const TcoreATResponse *resp = data;
1044 UserRequest *ur = NULL;
1048 ur = tcore_pending_ref_user_request(p);
1050 dbg("error - current ur is NULL");
1054 req_data = tcore_user_request_ref_data(ur, NULL);
1056 memset(&resp_read_record, 0x00, sizeof(struct tresp_phonebook_read_record));
1058 resp_read_record.result = PB_FAIL;
1059 resp_read_record.phonebook_type = req_data->phonebook_type;
1061 if (resp && resp->success > VAL_ZERO) {
1062 CoreObject *co = tcore_pending_ref_core_object(p);
1063 GSList *list = NULL;
1065 GSList *tokens = NULL;
1068 int num_plan = VAL_ZERO;
1069 char *number = NULL, *name = NULL, *additional_number = NULL;
1070 char *sne = NULL, *email = NULL;
1075 if (resp->lines == NULL) {
1076 err("invalid message");
1081 * +CPBR: <index>,<number>,<type>,<text>[,<hidden>][,<group>]
1082 * [,<adnumber>][,<adtype>][,<secondtext>][,<email>]]
1084 line = (const char*)resp->lines->data;
1085 tokens = tcore_at_tok_new(line);
1086 if (g_slist_length(tokens) < VAL_ONE) {
1087 err("invalid message");
1092 temp = g_slist_nth_data(tokens, VAL_ZERO);
1097 resp_read_record.index = atoi(temp);
1099 /* Fetch <number> */
1100 temp = g_slist_nth_data(tokens, VAL_ONE);
1105 number = tcore_at_tok_extract(temp);
1106 g_strlcpy((char *)resp_read_record.number,
1107 (const gchar *)number, PHONEBOOK_NUMBER_BYTE_MAX+1);
1111 temp = g_slist_nth_data(tokens, VAL_TWO);
1116 num_plan = atoi(temp);
1117 resp_read_record.ton = __phonebook_find_num_plan(num_plan);
1120 temp = g_slist_nth_data(tokens, VAL_THREE);
1125 name = tcore_at_tok_extract(temp);
1127 g_strlcpy((char *)resp_read_record.name,
1128 (const gchar *)name, PHONEBOOK_NAME_BYTE_MAX+1);
1129 resp_read_record.name_len = strlen((const char*)resp_read_record.name);
1130 resp_read_record.dcs = PB_TEXT_ASCII;
1134 /* All 'mandatory' fields are extracted */
1135 resp_read_record.result = PB_SUCCESS;
1137 /* Updated selected Phonebook type */
1138 tcore_phonebook_set_selected_type(co, req_data->phonebook_type);
1140 /* Get used_index list by req_type */
1141 if (__phonebook_get_index_list_by_type(co,
1142 req_data->phonebook_type, &list) == TRUE) {
1144 if ((guint)list->data == resp_read_record.index) {
1145 if ((list = g_slist_next(list)) != NULL) {
1146 /* If exist, set next_index */
1147 resp_read_record.next_index = (guint)list->data;
1148 dbg("next_index is [%u]", resp_read_record.next_index);
1150 /* read_record.index is the end of used_index */
1151 resp_read_record.next_index = 0;
1152 dbg("End of used_index");
1156 list = g_slist_next(list);
1159 /* No PrivateInfo */
1160 resp_read_record.next_index = 0;
1163 /* Fetch <hidden> */
1164 temp = g_slist_nth_data(tokens, VAL_FOUR);
1166 dbg("Phonebook entry is hidden");
1169 /* Fetch <adnumber> */
1170 temp = g_slist_nth_data(tokens, VAL_SIX);
1171 additional_number = tcore_at_tok_extract(temp);
1172 if (additional_number) {
1173 g_strlcpy((char *)resp_read_record.anr1,
1174 (const gchar *)additional_number, PHONEBOOK_NUMBER_BYTE_MAX+1);
1175 g_free(additional_number);
1178 /* Fetch <adtype> */
1179 temp = g_slist_nth_data(tokens, VAL_SEVEN);
1180 name = tcore_at_tok_extract(temp);
1182 num_plan = atoi(temp);
1183 resp_read_record.anr1_ton = __phonebook_find_num_plan(num_plan);
1186 /* Fetch <secondtext> */
1187 temp = g_slist_nth_data(tokens, VAL_EIGHT);
1192 sne = tcore_at_tok_extract(temp);
1194 g_strlcpy((char *)resp_read_record.sne,
1195 (const gchar *)sne, PHONEBOOK_NAME_BYTE_MAX+1);
1196 resp_read_record.sne_len = strlen((const char*)resp_read_record.sne);
1197 resp_read_record.sne_dcs = PB_TEXT_ASCII;
1202 temp = g_slist_nth_data(tokens, VAL_NINE);
1207 email = tcore_at_tok_extract(temp);
1209 g_strlcpy((char *)resp_read_record.email1,
1210 (const gchar *)email, PHONEBOOK_EMAIL_BYTE_MAX+1);
1211 resp_read_record.email1_len = strlen((const char*)resp_read_record.email1);
1216 /* Free resources */
1217 tcore_at_tok_free(tokens);
1220 dbg("RESPONSE NOK");
1224 tcore_user_request_send_response(ur,
1225 TRESP_PHONEBOOK_READRECORD,
1226 sizeof(struct tresp_phonebook_read_record), &resp_read_record);
1231 static void on_resp_update_record(TcorePending *p,
1232 int data_len, const void *data, void *user_data)
1234 const TcoreATResponse *resp = data;
1235 UserRequest *ur = NULL;
1236 struct tresp_phonebook_update_record resp_update_record;
1240 ur = tcore_pending_ref_user_request(p);
1242 if (resp && resp->success > VAL_ZERO) {
1243 const struct treq_phonebook_update_record *req_data = NULL;
1244 CoreObject *co = tcore_pending_ref_core_object(p);
1248 resp_update_record.result = PB_SUCCESS;
1250 req_data = tcore_user_request_ref_data(ur, NULL);
1252 /* Updated selected Phonebook type */
1253 tcore_phonebook_set_selected_type(co, req_data->phonebook_type);
1256 * Need to update the corresponding index list.
1258 * in case 'not available' (ADD operation) - ADD index
1259 * in case 'available' (UPDATE operation) - NO change
1261 __phonebook_update_index_list_by_type(co,
1262 req_data->phonebook_type, req_data->index);
1265 dbg("RESPONSE NOK");
1266 resp_update_record.result = PB_FAIL;
1271 tcore_user_request_send_response(ur,
1272 TRESP_PHONEBOOK_UPDATERECORD,
1273 sizeof(struct tresp_phonebook_update_record), &resp_update_record);
1282 static void on_resp_delete_record(TcorePending *p,
1283 int data_len, const void *data, void *user_data)
1285 const TcoreATResponse *resp = data;
1286 UserRequest *ur = NULL;
1287 struct tresp_phonebook_delete_record resp_delete_record;
1291 ur = tcore_pending_ref_user_request(p);
1293 if (resp && resp->success > VAL_ZERO) {
1294 const struct treq_phonebook_delete_record *req_data = NULL;
1295 CoreObject *co = tcore_pending_ref_core_object(p);
1296 GSList *list = NULL;
1300 resp_delete_record.result = PB_SUCCESS;
1302 req_data = tcore_user_request_ref_data(ur, NULL);
1304 /* Updated selected Phonebook type */
1305 tcore_phonebook_set_selected_type(co, req_data->phonebook_type);
1307 /* Get used_index list by req_type */
1308 if (__phonebook_get_index_list_by_type(co,
1309 req_data->phonebook_type, &list) != TRUE) {
1310 err("used_index list is NOT valid");
1313 const int del_index = (const int)req_data->index;
1314 list = g_slist_remove(list, (gconstpointer)del_index);
1315 dbg("Remove index: [%u] list: [0x%x]", req_data->index, list);
1319 dbg("RESPONSE NOK");
1320 resp_delete_record.result = PB_FAIL;
1324 tcore_user_request_send_response(ur,
1325 TRESP_PHONEBOOK_DELETERECORD,
1326 sizeof(struct tresp_phonebook_delete_record), &resp_delete_record);
1335 /******************************************************************************
1336 * Phonebook Request functions
1337 *****************************************************************************/
1339 * Operation - get_count
1342 * AT-Command: AT+CPBS?
1345 * Success: (Single line)
1346 * +CPBS: <storage>[,<used>][,total]
1349 * <storage> Phonebook storage type
1350 * <used> Number of records 'used'
1351 * <total> 'total' number of records available
1354 * +CME ERROR: <error>
1356 static TReturn imc_get_count(CoreObject *co, UserRequest *ur)
1358 struct treq_phonebook_get_count *req_data = NULL;
1362 TReturn ret = TCORE_RETURN_FAILURE;
1366 req_data = (struct treq_phonebook_get_count *)tcore_user_request_ref_data(ur, NULL);
1368 /* Check whether pb_type is supported or not, and Select pb_type */
1369 if (__phonebook_check_and_select_type(co,
1370 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1371 warn("Requested phonebok type '%d' is NOT supported",
1372 req_data->phonebook_type);
1377 at_cmd = g_strdup_printf("%s+CPBS?", set_pb_cmd);
1379 /* Send Request to Modem */
1380 ret = tcore_prepare_and_send_at_request(co,
1382 TCORE_AT_SINGLELINE,
1384 on_resp_get_count, NULL,
1388 /* Free resources */
1396 * Operation - get_info
1399 * AT-Command: AT+CPBS?;+CPBF=?
1402 * Success: (Multi line)
1403 * +CPBS: <storage>[,<used>][,total]
1404 * +CPBF: [<nlength>],[<tlength>],[<glength>],[<slength>],[<elength>]
1407 * <storage> Phonebook storage type
1408 * <used> Number of records 'used'
1409 * <total> 'total' number of records available
1410 * <nlength> Maximum length of field <number>
1411 * <tlength> Maximum length of field <text>
1412 * <glength> Maximum length of field <group>
1413 * <slength> Maximum length of field <secondtext>
1414 * <elength> Maximum length of field <email>
1417 * +CME ERROR: <error>
1419 static TReturn imc_get_info(CoreObject *co, UserRequest *ur)
1421 struct treq_phonebook_get_info *req_data = NULL;
1425 TReturn ret = TCORE_RETURN_FAILURE;
1429 req_data = (struct treq_phonebook_get_info *)tcore_user_request_ref_data(ur, NULL);
1431 /* Check whether pb_type is supported or not, and Select pb_type */
1432 if (__phonebook_check_and_select_type(co,
1433 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1434 warn("Requested phonebok type '%d' is NOT supported",
1435 req_data->phonebook_type);
1440 at_cmd = g_strdup_printf("%s+CPBS?;+CPBF=?", set_pb_cmd);
1442 /* Send Request to Modem */
1443 ret = tcore_prepare_and_send_at_request(co,
1447 on_resp_get_info, NULL,
1451 /* Free resources */
1459 * Operation - get_usim_info
1462 * AT-Command: AT+CPBS?;+CPBF=?
1465 * Success: (Multi line)
1466 * +CPBS: <storage>[,<used>][,total]
1467 * +CPBF: [<nlength>],[<tlength>],[<glength>],[<slength>],[<elength>]
1470 * <storage> Phonebook storage type
1471 * <used> Number of records 'used'
1472 * <total> 'total' number of records available
1473 * <nlength> Maximum length of field <number>
1474 * <tlength> Maximum length of field <text>
1475 * <glength> Maximum length of field <group>
1476 * <slength> Maximum length of field <secondtext>
1477 * <elength> Maximum length of field <email>
1480 * +CME ERROR: <error>
1482 static TReturn imc_get_usim_info(CoreObject *co, UserRequest *ur)
1487 TReturn ret = TCORE_RETURN_FAILURE;
1491 /* Check whether pb_type is supported or not, and Select pb_type */
1492 if (__phonebook_check_and_select_type(co, PB_TYPE_USIM, &set_pb_cmd) != TRUE) {
1493 warn("Requested phonebok type '%d' is NOT supported", PB_TYPE_USIM);
1498 at_cmd = g_strdup_printf("%s+CPBS?;+CPBF=?", set_pb_cmd);
1500 /* Send Request to Modem */
1501 ret = tcore_prepare_and_send_at_request(co,
1505 on_resp_get_usim_info, NULL,
1509 /* Free resources */
1517 * Operation - read_record
1520 * AT-Command: AT+CPBR=<index>
1523 * 1 Integer type values in range of location numbers of phonebook memory
1527 * Success: (Single line);
1528 * +CPBR: <index>,<number>,<type>,<text>[,<hidden>][,<group>]
1529 * [,<adnumber>][,<adtype>][,<secondtext>][,<email>]]
1532 * <number> String type phone number of format <type>
1533 * <type> Type of address octet in integer format
1534 * <text> String type field of maximum length <tlength>
1535 * <hidden> Indicates if the entry is hidden or not – only available,
1536 * if a UICC with an active USIM application is present
1537 * 0 Phonebook entry not hidden
1538 * 1 Phonebook entry hidden
1539 * <group> String type field of maximum length <glength>
1540 * <adnumber> String type phone number of format <adtype>
1541 * <adtype> Type of address octet in integer format
1542 * <secondtext> String type field of maximum length <slength>
1543 * <email> String type field of maximum length <elength>
1546 * +CME ERROR: <error>
1548 static TReturn imc_read_record(CoreObject *co, UserRequest *ur)
1550 const struct treq_phonebook_read_record *req_data = NULL;
1553 guint used_index = 0;
1555 TReturn ret = TCORE_RETURN_FAILURE;
1559 req_data = tcore_user_request_ref_data(ur, NULL);
1561 /* Check whether pb_type is supported or not, and Select pb_type */
1562 if (__phonebook_check_and_select_type(co,
1563 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1564 warn("Requested phonebok type '%d' is NOT supported",
1565 req_data->phonebook_type);
1569 /* Check whether index is used or not */
1570 __phonebook_check_used_index(co,
1571 req_data->phonebook_type, req_data->index, &used_index);
1574 at_cmd = g_strdup_printf("%s+CPBR=%u", set_pb_cmd, used_index);
1576 /* Send Request to Modem */
1577 ret = tcore_prepare_and_send_at_request(co,
1579 TCORE_AT_SINGLELINE,
1581 on_resp_read_record, NULL,
1585 /* Free resources */
1593 * Operation - update_record
1596 * AT-Command: AT+CPBW=[<index>][,<number>[,<type>[,<text>[,<group>[,<adnumber>
1597 * [,<adtype>[,<secondtext>[,<email>[,<hidden>]]]]]]]]]
1599 * ... same read_record Operation
1602 * Success: (No Result)
1605 * +CME ERROR: <error>
1607 static TReturn imc_update_record(CoreObject *co, UserRequest *ur)
1609 const struct treq_phonebook_update_record *req_data = NULL;
1613 TReturn ret = TCORE_RETURN_FAILURE;
1617 req_data = tcore_user_request_ref_data(ur, NULL);
1619 /* Check whether pb_type is supported or not, and Select pb_type */
1620 if (__phonebook_check_and_select_type(co,
1621 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1622 warn("Requested phonebok type '%d' is NOT supported",
1623 req_data->phonebook_type);
1627 /* Set AT-Command according pb_type */
1628 if (req_data->phonebook_type == PB_TYPE_USIM) {
1629 at_cmd = g_strdup_printf("%s+CPBW=%u,\"%s\",%d,\"%s\",,\"%s\",,\"%s\",\"%s\"",
1630 set_pb_cmd, req_data->index,
1632 ((PB_TON_INTERNATIONAL == req_data->ton) ? IMC_TON_INTERNATIONAL: IMC_TON_UNKNOWN),
1633 req_data->name, req_data->anr1,
1634 req_data->sne, req_data->email1);
1636 at_cmd = g_strdup_printf("%s+CPBW=%u,\"%s\",,\"%s\"",
1637 set_pb_cmd, req_data->index,
1638 req_data->number, req_data->name);
1641 /* Send Request to Modem */
1642 ret = tcore_prepare_and_send_at_request(co,
1646 on_resp_update_record, NULL,
1650 /* Free resources */
1658 * Operation - delete_record
1661 * AT-Command: AT+CPBW=<index>
1664 * 1 Integer type values in range of location numbers of phonebook memory
1668 * Success: (No Result)
1671 * +CME ERROR: <error>
1673 static TReturn imc_delete_record(CoreObject *co, UserRequest *ur)
1675 const struct treq_phonebook_delete_record *req_data;
1679 TReturn ret = TCORE_RETURN_FAILURE;
1683 req_data = tcore_user_request_ref_data(ur, NULL);
1685 /* Check whether pb_type is supported or not, and Select pb_type */
1686 if (__phonebook_check_and_select_type(co,
1687 req_data->phonebook_type, &set_pb_cmd) != TRUE) {
1688 warn("Requested phonebok type '%d' is NOT supported",
1689 req_data->phonebook_type);
1694 at_cmd = g_strdup_printf("%s+CPBW=%u", set_pb_cmd, req_data->index);
1696 /* Send Request to Modem */
1697 ret = tcore_prepare_and_send_at_request(co,
1701 on_resp_delete_record, NULL,
1705 /* Free resources */
1712 /******************************************************************************
1713 * Phonebook Notification function(s)
1714 *****************************************************************************/
1715 static gboolean on_noti_phonebook_status(CoreObject *co_phonebook,
1716 const void *event_info, void *user_data)
1718 dbg("Received [+PBREADY]");
1721 * Get supported list of Phonebook types
1723 __phonebook_get_support_list(co_phonebook);
1728 /* Phonebook operations */
1729 static struct tcore_phonebook_operations phonebook_ops = {
1730 .get_count = imc_get_count,
1731 .get_info = imc_get_info,
1732 .get_usim_info = imc_get_usim_info,
1733 .read_record = imc_read_record,
1734 .update_record = imc_update_record,
1735 .delete_record = imc_delete_record,
1738 gboolean imc_phonebook_init(TcorePlugin *cp, CoreObject *co_phonebook)
1740 PrivateInfo *private_info;
1744 /* Set operations */
1745 tcore_phonebook_set_ops(co_phonebook, &phonebook_ops);
1747 /* Set PrivateInfo */
1748 private_info = g_malloc0(sizeof(PrivateInfo));
1749 tcore_object_link_user_data(co_phonebook, private_info);
1752 tcore_object_add_callback(co_phonebook,
1754 on_noti_phonebook_status, co_phonebook);
1761 void imc_phonebook_exit(TcorePlugin *cp, CoreObject *co_phonebook)
1763 PrivateInfo *private_info;
1765 private_info = tcore_object_ref_user_data(co_phonebook);
1766 g_assert(private_info != NULL);
1768 /* Free PrivateInfo */
1769 g_slist_free_full(private_info->used_index_fdn, g_free);
1770 g_slist_free_full(private_info->used_index_adn, g_free);
1771 g_slist_free_full(private_info->used_index_sdn, g_free);
1772 g_slist_free_full(private_info->used_index_usim, g_free);
1773 g_free(private_info);
1775 /* Remove Callbacks */
1776 tcore_object_del_callback(co_phonebook,
1777 "+PBREADY", on_noti_phonebook_status);