2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <stacktrim.h>
26 #include "bt-internal-types.h"
27 #include "bt-service-common.h"
28 #include "bt-service-event.h"
29 #include "bt-service-pbap.h"
33 #define PBAP_OBEX_CLIENT_SERVICE "org.bluez.obex"
34 #define PBAP_OBEX_CLIENT_PATH "/org/bluez/obex"
35 #define PBAP_OBEX_CLIENT_INTERFACE "org.bluez.obex.Client1"
37 #define PBAP_SESSION_SERVICE "org.bluez.obex"
38 #define PBAP_SESSION_INTERFACE "org.bluez.obex.PhonebookAccess1"
39 #define PBAP_VCARDLIST_MAXLENGTH 256
41 #define PBAP_NUM_OF_FIELDS_ENTRY 29
42 #define PBAP_FIELD_ALL (0xFFFFFFFFFFFFFFFFULL)
44 #define PBAP_DEFAULT_DOWNLAOD_PATH "/opt/usr/home/owner/media/Downloads"
45 #define PBAP_DEFAULT_FILE_NAME "pb.vcf"
76 "X-IRMC-CALL-DATETIME", /* 29 */
85 "pb", //Phonebook for the saved contacts
86 "ich", //Incoming call history
87 "och", //Outgoing call history
88 "mch", //Missed call history
89 "cch", //Combined Call History cch = ich + och + mch
93 "vcard21", // vCard Format 2.1 (Default)
94 "vcard30", // vCard Format 3.0
98 "indexed", // Index (default)
99 "alphanumeric", // Alphanumeric
100 "phonetic", // Phonetic
103 char *SEARCH_FIELD[] = {
104 "name", // Search by Name(default)
105 "number", // Search by Phone Number
106 "sound", // Search by phonetic sound
109 static char *g_pbap_session_path = NULL;
110 static char *g_pbap_server_address = NULL;
111 static GDBusProxy *g_pbap_proxy = NULL;
116 } selected_path = { -1, -1};
125 } bt_pbap_operation_e;
128 bt_pbap_operation_e operation;
137 bt_pbap_operation_e operation;
138 } bt_pbap_transfer_info_t;
140 static GSList *transfers;
142 int __bt_pbap_call_get_phonebook_size(GDBusProxy *proxy, bt_pbap_data_t *pbap_data);
143 int __bt_pbap_call_get_phonebook(GDBusProxy *proxy, bt_pbap_data_t *pbap_data);
144 int __bt_pbap_call_get_vcards_list(GDBusProxy *proxy, bt_pbap_data_t *pbap_data);
145 int __bt_pbap_call_get_vcard(GDBusProxy *proxy, bt_pbap_data_t *pbap_data);
146 int __bt_pbap_call_search_phonebook(GDBusProxy *proxy, bt_pbap_data_t *pbap_data);
148 static void __bt_pbap_free_data(bt_pbap_data_t *pbap_data)
150 g_free(pbap_data->app_param);
151 g_free(pbap_data->data);
155 static bt_pbap_transfer_info_t *__bt_find_transfer_by_path(const char *transfer_path)
158 bt_pbap_transfer_info_t *transfer;
160 retv_if(transfer_path == NULL, NULL);
162 for (l = transfers; l != NULL; l = l->next) {
165 if (transfer == NULL)
168 if (g_strcmp0(transfer->path, transfer_path) == 0)
175 static void __bt_free_transfer_info(bt_pbap_transfer_info_t *transfer_info)
177 ret_if(transfer_info == NULL);
179 g_free(transfer_info->path);
180 g_free(transfer_info->filename);
181 g_free(transfer_info->remote_device);
182 g_free(transfer_info);
185 void _bt_pbap_obex_transfer_completed(const char *transfer_path, gboolean transfer_status)
187 bt_pbap_transfer_info_t *transfer_info;
189 int success = transfer_status;
190 GVariant *signal = NULL;
191 BT_DBG("Transfer [%s] Success [%d] \n", transfer_path, success);
193 result = (success == TRUE) ? BLUETOOTH_ERROR_NONE
194 : BLUETOOTH_ERROR_INTERNAL;
196 transfer_info = __bt_find_transfer_by_path(transfer_path);
197 ret_if(transfer_info == NULL);
199 BT_DBG("Remote Device [%s] FileName: [%s] Operation[%d]",
200 transfer_info->remote_device, transfer_info->filename,
201 transfer_info->operation);
203 signal = g_variant_new("(issi)", result,
204 transfer_info->remote_device,
205 transfer_info->filename, success);
206 switch (transfer_info->operation) {
208 _bt_send_event(BT_PBAP_CLIENT_EVENT,
209 BLUETOOTH_PBAP_PHONEBOOK_PULL,
214 _bt_send_event(BT_PBAP_CLIENT_EVENT,
215 BLUETOOTH_PBAP_VCARD_PULL,
220 BT_INFO("Case not handled");
225 transfers = g_slist_remove(transfers, transfer_info);
226 __bt_free_transfer_info(transfer_info);
229 void _bt_obex_pbap_client_disconnect(char *path)
231 if (g_strcmp0(g_pbap_session_path, path) == 0) {
232 int result = BLUETOOTH_ERROR_NONE;
233 GVariant *signal = g_variant_new("(is)", result,
234 g_pbap_server_address);
236 _bt_send_event(BT_PBAP_CLIENT_EVENT,
237 BLUETOOTH_PBAP_DISCONNECTED,
240 g_free(g_pbap_session_path);
241 g_pbap_session_path = NULL;
243 g_free(g_pbap_server_address);
244 g_pbap_server_address = NULL;
246 g_object_unref(g_pbap_proxy);
249 selected_path.folder = -1;
250 selected_path.type = -1;
255 void __bt_pbap_connect_cb(GDBusProxy *proxy,
256 GAsyncResult *res, gpointer user_data)
258 char *session_path = NULL;
259 char *address_string = user_data;
260 GError *error = NULL;
262 GVariant *signal = NULL;
263 int result = BLUETOOTH_ERROR_INTERNAL;
265 value = g_dbus_proxy_call_finish(proxy, res, &error);
266 BT_DBG("Address = %s", address_string);
269 BT_ERR("g_dbus_proxy_call_finish failed");
271 BT_ERR("errCode[%x], message[%s]\n",
272 error->code, error->message);
273 g_clear_error(&error);
275 g_object_unref(g_pbap_proxy);
278 g_variant_get(value, "(&o)", &session_path);
280 g_pbap_session_path = g_strdup(session_path);
281 BT_DBG("Session Path = %s\n", g_pbap_session_path);
282 result = BLUETOOTH_ERROR_NONE;
283 g_pbap_server_address = g_strdup(address_string);
285 g_variant_unref(value);
288 signal = g_variant_new("(is)", result, address_string);
290 _bt_send_event(BT_PBAP_CLIENT_EVENT,
291 BLUETOOTH_PBAP_CONNECTED,
294 g_free(address_string);
298 int _bt_pbap_connect(const bluetooth_device_address_t *address)
301 GDBusConnection *g_conn;
302 GError *error = NULL;
303 char address_string[18] = { 0, };
305 GVariantBuilder builder;
308 BT_CHECK_PARAMETER(address, return);
310 /* check if already connected */
311 if (g_pbap_session_path)
312 return BLUETOOTH_ERROR_ALREADY_CONNECT;
314 BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]",
315 address->addr[0], address->addr[1],
316 address->addr[2], address->addr[3],
317 address->addr[4], address->addr[5]);
319 _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr);
320 BT_DBG("Address String: %s", address_string);
321 g_conn = _bt_get_system_gconn();
322 if (g_conn == NULL) {
323 BT_ERR("Couldn't connect to session bus");
326 g_pbap_proxy = g_dbus_proxy_new_sync(g_conn,
327 G_DBUS_PROXY_FLAGS_NONE, NULL,
328 PBAP_OBEX_CLIENT_SERVICE, PBAP_OBEX_CLIENT_PATH,
329 PBAP_OBEX_CLIENT_INTERFACE, NULL, &error);
331 BT_ERR("Failed to get a proxy for D-Bus\n");
333 ERR("Unable to create proxy: %s", error->message);
334 g_clear_error(&error);
340 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
341 g_variant_builder_add(&builder, "{sv}", "Target",
342 g_variant_new("s", "pbap"));
343 args = g_variant_builder_end(&builder);
345 ptr = g_strdup(address_string);
347 GVariant *temp = g_variant_new("(s@a{sv})", ptr, args);
349 g_dbus_proxy_call(g_pbap_proxy, "CreateSession",
351 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
352 (GAsyncReadyCallback)__bt_pbap_connect_cb, ptr);
358 void __bt_pbap_disconnect_cb(GDBusProxy *proxy,
359 GAsyncResult *res, gpointer user_data)
361 char *address_string = user_data;
362 GError *error = NULL;
364 int result = BLUETOOTH_ERROR_INTERNAL ;
366 BT_DBG("Address = %s", address_string);
368 value = g_dbus_proxy_call_finish(proxy, res, &error);
369 BT_DBG("Address = %s", address_string);
372 BT_ERR("g_dbus_proxy_call_finish failed");
374 BT_ERR("errCode[%x], message[%s]\n",
375 error->code, error->message);
376 g_clear_error(&error);
379 g_object_unref(g_pbap_proxy);
382 g_free(g_pbap_session_path);
383 g_pbap_session_path = NULL;
385 g_free(g_pbap_server_address);
386 g_pbap_server_address = NULL;
388 result = BLUETOOTH_ERROR_NONE;
389 selected_path.folder = -1;
390 selected_path.type = -1;
392 g_variant_unref(value);
395 /* If the result is success, the event reciever will send the disconnect event */
396 if (result != BLUETOOTH_ERROR_NONE) {
397 GVariant *signal = NULL;
399 signal = g_variant_new("(is)", result, address_string);
400 _bt_send_event(BT_PBAP_CLIENT_EVENT,
401 BLUETOOTH_PBAP_DISCONNECTED,
405 g_free(address_string);
409 int _bt_pbap_disconnect(const bluetooth_device_address_t *address)
412 char address_string[18] = { 0, };
414 BT_CHECK_PARAMETER(address, return);
416 /* check if connected */
417 if (g_pbap_session_path == NULL)
418 return BLUETOOTH_ERROR_NOT_CONNECTED;
420 BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]",
421 address->addr[0], address->addr[1],
422 address->addr[2], address->addr[3],
423 address->addr[4], address->addr[5]);
425 _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr);
426 BT_DBG("Address String: %s", address_string);
427 BT_DBG("Session Path: %s", g_pbap_session_path);
429 ptr = g_strdup(address_string);
431 g_dbus_proxy_call(g_pbap_proxy, "RemoveSession",
432 g_variant_new("(o)", g_pbap_session_path),
433 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
434 (GAsyncReadyCallback)__bt_pbap_disconnect_cb, ptr);
439 void __bt_pbap_select_cb(GDBusProxy *proxy,
440 GAsyncResult *res, gpointer user_data)
443 GError *error = NULL;
445 bt_pbap_data_t *pbap_data = user_data;
446 char *address_string = pbap_data->data;
448 BT_DBG("Address = %s", address_string);
450 value = g_dbus_proxy_call_finish(proxy, res, &error);
452 BT_ERR("g_dbus_proxy_call_finish failed");
453 g_object_unref(proxy);
455 BT_ERR("errCode[%x], message[%s]\n",
456 error->code, error->message);
458 if (pbap_data->operation == PULL_ALL ||
459 pbap_data->operation == GET_VCARD) {
460 GVariant *signal = NULL;
461 int result = BLUETOOTH_ERROR_INTERNAL;
464 if (pbap_data->operation == PULL_ALL)
465 event = BLUETOOTH_PBAP_PHONEBOOK_PULL;
467 event = BLUETOOTH_PBAP_VCARD_PULL;
468 if (strstr(error->message, "Not Found") != NULL)
469 result = BLUETOOTH_ERROR_NO_DATA;
470 signal = g_variant_new("(issi)", result,
471 address_string, "", FALSE);
473 _bt_send_event(BT_PBAP_CLIENT_EVENT,
476 g_clear_error(&error);
479 selected_path.folder = -1;
480 selected_path.type = -1;
482 __bt_pbap_free_data(pbap_data);
486 switch (pbap_data->operation) {
488 __bt_pbap_call_get_phonebook_size(proxy, pbap_data);
492 __bt_pbap_call_get_phonebook(proxy, pbap_data);
496 __bt_pbap_call_get_vcards_list(proxy, pbap_data);
500 __bt_pbap_call_get_vcard(proxy, pbap_data);
504 __bt_pbap_call_search_phonebook(proxy, pbap_data);
508 selected_path.folder = -1;
509 selected_path.type = -1;
510 g_object_unref(proxy);
511 __bt_pbap_free_data(pbap_data);
515 g_variant_unref(value);
520 void __bt_pbap_get_phonebook_size_cb(GDBusProxy *proxy,
521 GAsyncResult *res, gpointer user_data)
524 GError *error = NULL;
525 int result = BLUETOOTH_ERROR_INTERNAL;
526 bt_pbap_data_t *pbap_data = user_data;
527 char *address_string = pbap_data->data;
528 unsigned short int size = 0;
530 GVariant *signal = NULL;
532 BT_DBG("Address = %s", address_string);
533 value = g_dbus_proxy_call_finish(proxy, res, &error);
536 BT_ERR("g_dbus_proxy_call_finish failed");
538 BT_ERR("errCode[%x], message[%s]\n",
539 error->code, error->message);
540 g_clear_error(&error);
543 g_variant_get(value, "(q)", &size);
544 result = BLUETOOTH_ERROR_NONE;
547 BT_DBG("Size of Phonebook: %d", size);
549 signal = g_variant_new("(isi)", result, address_string, size);
550 _bt_send_event(BT_PBAP_CLIENT_EVENT,
551 BLUETOOTH_PBAP_PHONEBOOK_SIZE,
554 g_variant_unref(value);
555 g_object_unref(proxy);
556 __bt_pbap_free_data(pbap_data);
560 void __bt_pbap_get_phonebook_cb(GDBusProxy *proxy,
561 GAsyncResult *res, gpointer user_data)
564 GError *error = NULL;
565 bt_pbap_data_t *pbap_data = user_data;
566 char *address_string = pbap_data->data;
567 bt_pbap_transfer_info_t *transfer_info;
568 char *transfer = NULL;
569 const gchar *filename = NULL;
571 GVariant *properties;
573 BT_DBG("Address = %s", address_string);
574 value = g_dbus_proxy_call_finish(proxy, res, &error);
576 BT_ERR("g_dbus_proxy_call_finish failed");
578 BT_ERR("errCode[%x], message[%s]\n",
579 error->code, error->message);
580 g_clear_error(&error);
583 g_variant_get(value, "(o@a{sv})", &transfer, &properties);
585 if (g_variant_lookup(properties, "Filename", "s", &filename) == FALSE)
588 BT_DBG("Transfer Path: %s", transfer);
589 BT_DBG("File Name: %s", filename);
590 transfer_info = g_new0(bt_pbap_transfer_info_t, 1);
591 transfer_info->path = transfer;
592 transfer_info->remote_device = g_strdup(address_string);
593 transfer_info->filename = (char *)filename;
594 transfer_info->operation = PULL_ALL;
595 transfers = g_slist_append(transfers, transfer_info);
597 g_variant_unref(value);
600 g_object_unref(proxy);
601 __bt_pbap_free_data(pbap_data);
605 void __bt_pbap_get_vcard_list_cb(GDBusProxy *proxy,
606 GAsyncResult *res, gpointer user_data)
609 GError *error = NULL;
611 int result = BLUETOOTH_ERROR_INTERNAL;
612 bt_pbap_data_t *pbap_data = user_data;
613 char *address_string = pbap_data->data;
614 char **vcard_list = NULL;
615 char list_entry[PBAP_VCARDLIST_MAXLENGTH] = { 0, };
618 GVariant *signal = NULL;
620 value = g_dbus_proxy_call_finish(proxy, res, &error);
622 BT_ERR("g_dbus_proxy_call_finish failed");
624 BT_ERR("errCode[%x], message[%s]\n",
625 error->code, error->message);
626 g_clear_error(&error);
629 result = BLUETOOTH_ERROR_NONE;
630 gchar *elname, *elval;
633 GVariant *child = NULL;
634 GVariant *value1 = NULL;
636 g_variant_get(value, "(@a(ss))", &value1); /* Format for value1 a(ss)*/
637 gsize items = g_variant_iter_init(&iter, value1);
638 vcard_list = g_new0(char *, items + 1);
640 for (i = 0; (child = g_variant_iter_next_value(&iter)) != NULL; i++) {
641 g_variant_get(child, "(&s&s)", &elname, &elval);
643 memset(list_entry, 0, PBAP_VCARDLIST_MAXLENGTH);
645 g_snprintf(list_entry, PBAP_VCARDLIST_MAXLENGTH - 1,
646 "<card handle = \"%s\" name = \"%s\"/>", elname, elval);
648 g_snprintf(list_entry, PBAP_VCARDLIST_MAXLENGTH - 1,
651 //If possible send as Array of <STRING, STRING>
652 BT_DBG("%s", list_entry);
653 vcard_list[i] = g_strdup(list_entry);
654 g_variant_unref(child);
658 g_variant_unref(value1);
659 g_variant_unref(value);
662 BT_DBG("Address = %s", address_string);
663 GVariant *temp = g_variant_new_strv((const gchar * const *)vcard_list, length);
664 signal = g_variant_new("(isv)", result, address_string, temp);
666 _bt_send_event(BT_PBAP_CLIENT_EVENT,
667 BLUETOOTH_PBAP_VCARD_LIST,
670 for (i = 0; i < length; i++)
671 g_free(vcard_list[i]);
674 g_object_unref(proxy);
675 __bt_pbap_free_data(pbap_data);
679 void __bt_pbap_get_vcard_cb(GDBusProxy *proxy,
680 GAsyncResult *res, gpointer user_data)
683 GError *error = NULL;
684 bt_pbap_data_t *pbap_data = user_data;
685 char *address_string = pbap_data->data;
686 bt_pbap_transfer_info_t *transfer_info;
687 char *transfer = NULL;
688 const gchar *filename = NULL;
690 GVariant *properties;
692 BT_DBG("Address = %s", address_string);
693 value = g_dbus_proxy_call_finish(proxy, res, &error);
695 BT_ERR("g_dbus_proxy_call_finish failed");
697 BT_ERR("errCode[%x], message[%s]\n",
698 error->code, error->message);
699 g_clear_error(&error);
702 g_variant_get(value, "(o@a{sv})", &transfer, &properties);
704 if (g_variant_lookup(properties, "Filename", "s", &filename) == FALSE)
707 BT_DBG("Transfer Path: %s", transfer);
708 BT_DBG("File Name: %s", filename);
709 transfer_info = g_new0(bt_pbap_transfer_info_t, 1);
710 transfer_info->path = transfer;
711 transfer_info->remote_device = g_strdup(address_string);
712 transfer_info->filename = (char *)filename;
713 transfer_info->operation = GET_VCARD;
714 transfers = g_slist_append(transfers, transfer_info);
716 g_variant_unref(properties);
717 g_variant_unref(value);
720 g_object_unref(proxy);
721 __bt_pbap_free_data(pbap_data);
725 void __bt_pbap_search_phonebook_cb(GDBusProxy *proxy,
726 GAsyncResult *res, gpointer user_data)
729 GError *error = NULL;
731 bt_pbap_data_t *pbap_data = user_data;
732 char *address_string = pbap_data->data;
733 char **vcard_list = NULL;
734 char list_entry[PBAP_VCARDLIST_MAXLENGTH] = { 0, };
736 int result = BLUETOOTH_ERROR_INTERNAL;
738 GVariant *signal = NULL;
740 value = g_dbus_proxy_call_finish(proxy, res, &error);
742 BT_ERR("g_dbus_proxy_call_finish failed");
744 BT_ERR("errCode[%x], message[%s]\n",
745 error->code, error->message);
746 g_clear_error(&error);
749 result = BLUETOOTH_ERROR_NONE;
750 gchar *elname, *elval;
753 GVariant *child = NULL;
754 GVariant *value1 = NULL;
756 g_variant_get(value, "(@a(ss))", &value1);
757 gsize items = g_variant_iter_init(&iter, value1);
758 vcard_list = g_new0(char *, items + 1);
760 for (i = 0; (child = g_variant_iter_next_value(&iter)) != NULL; i++) {
761 g_variant_get(child, "(&s&s)", &elname, &elval);
763 memset(list_entry, 0, PBAP_VCARDLIST_MAXLENGTH);
764 g_snprintf(list_entry, PBAP_VCARDLIST_MAXLENGTH - 1,
765 "<card handle = \"%s\" name = \"%s\"/>", elname, elval);
766 //If possible send as Array of <STRING, STRING>
767 BT_DBG("%s", list_entry);
768 vcard_list[i] = g_strdup(list_entry);
770 g_variant_unref(child);
773 g_variant_unref(value1);
774 g_variant_unref(value);
777 BT_DBG("Address = %s", address_string);
779 signal = g_variant_new("(is@as)", result, address_string,
780 g_variant_new_strv((const gchar * const *)vcard_list, length));
782 _bt_send_event(BT_PBAP_CLIENT_EVENT,
783 BLUETOOTH_PBAP_PHONEBOOK_SEARCH,
786 for (i = 0; i < length; i++)
787 g_free(vcard_list[i]);
790 g_object_unref(proxy);
791 __bt_pbap_free_data(pbap_data);
795 int __bt_pbap_call_get_phonebook_size(GDBusProxy *proxy, bt_pbap_data_t *pbap_data)
799 g_dbus_proxy_call(proxy, "GetSize",
800 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
801 (GAsyncReadyCallback)__bt_pbap_get_phonebook_size_cb,
805 return BLUETOOTH_ERROR_NONE;
808 int __bt_pbap_call_get_phonebook(GDBusProxy *proxy, bt_pbap_data_t *pbap_data)
814 char *format_str = NULL;
815 char *fields_str = NULL;
816 char *order_str = NULL;
817 char *download_path = NULL;
818 char *target_file = NULL;
819 bt_pbap_pull_parameters_t *app_param = pbap_data->app_param;
820 GVariantBuilder builder;
821 GVariantBuilder inner_builder;
825 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
826 g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_ARRAY);
828 /* Add MaxlistCount*/
829 g_variant_builder_add(&builder, "{sv}", "MaxCount",
830 g_variant_new("u", app_param->maxlist));
832 /* Add Order Filter only if other than Indexed (default)*/
833 if (app_param->order > 0) {
834 order_str = g_strdup(ORDER[app_param->order]);
835 g_variant_builder_add(&builder, "{sv}", "Order",
836 g_variant_new("s", order_str));
839 /* Add Offset Filter only if other than 0 (default)*/
840 if (app_param->offset > 0) {
841 g_variant_builder_add(&builder, "{sv}", "Offset",
842 g_variant_new("u", app_param->offset));
845 /* Add Format Filter only if other than vCard 2.1 (default)*/
846 if (app_param->format > 0) {
847 format_str = g_strdup(FORMAT[app_param->format]);
848 g_variant_builder_add(&builder, "{sv}", "Format",
849 g_variant_new("s", format_str));
852 /* Add Filter AttributeMask (64bit) */
853 if (app_param->fields > 0) {
854 if (app_param->fields == PBAP_FIELD_ALL) {
855 BT_DBG("** CHECKED ALL **");
856 fields_str = g_strdup("ALL");
857 g_variant_builder_add(&inner_builder, "s", fields_str);
860 for (i = 0; i < PBAP_NUM_OF_FIELDS_ENTRY; i++) {
861 if (app_param->fields & (1ULL << i)) {
862 BT_DBG("** CHECKED[%d]", i);
863 fields_str = g_strdup(FIELDS[i]);
864 g_variant_builder_add(&inner_builder, "s", fields_str);
870 g_variant_builder_add(&builder, "{sv}", "Fields",
871 g_variant_new("as", &inner_builder));
874 filters = g_variant_builder_end(&builder);
876 //****************************
877 // Add code for Fields
879 //****************************
881 ret = storage_get_directory(STORAGE_TYPE_INTERNAL,
882 STORAGE_DIRECTORY_DOWNLOADS, &download_path);
884 if (ret != STORAGE_ERROR_NONE) {
885 target_file = g_strdup_printf("%s/%s", PBAP_DEFAULT_DOWNLAOD_PATH,
886 PBAP_DEFAULT_FILE_NAME);
888 target_file = g_strdup_printf("%s/%s", download_path,
889 PBAP_DEFAULT_FILE_NAME);
895 DBG_SECURE("Target flie: %s", target_file);
897 g_dbus_proxy_call(proxy, "PullAll",
898 g_variant_new("(s@a{sv})", target_file, filters),
899 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
900 (GAsyncReadyCallback)__bt_pbap_get_phonebook_cb,
908 return BLUETOOTH_ERROR_NONE;
911 int __bt_pbap_call_get_vcards_list(GDBusProxy *proxy, bt_pbap_data_t *pbap_data)
914 char *order_str = NULL;
916 GVariantBuilder builder;
919 bt_pbap_list_parameters_t *app_param = pbap_data->app_param;
921 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
923 /* Add MaxlistCount*/
924 g_variant_builder_add(&builder, "{sv}", "MaxCount",
925 g_variant_new("u", app_param->maxlist));
927 /* Add Order Filter only if other than Indexed (default)*/
928 if (app_param->order > 0) {
929 order_str = g_strdup(ORDER[app_param->order]);
930 g_variant_builder_add(&builder, "{sv}", "Order",
931 g_variant_new("s", order_str));
934 /* Add Offset Filter only if other than 0 (default)*/
935 if (app_param->offset > 0) {
936 g_variant_builder_add(&builder, "{sv}", "Offset",
937 g_variant_new("u", app_param->offset));
940 filters = g_variant_builder_end(&builder);
942 folder = g_strdup(TYPE[selected_path.type]);
943 BT_DBG("Folder: %s", folder);
946 g_dbus_proxy_call(proxy, "List",
947 g_variant_new("(s@a{sv})", folder, filters),
948 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
949 (GAsyncReadyCallback)__bt_pbap_get_vcard_list_cb,
954 g_hash_table_unref((GHashTable *)filters);
955 /* In _bt_pbap_get_list(), path(type) is set to "nil", but current type is not null.
956 The path should be reset here */
957 selected_path.type = -1;
960 return BLUETOOTH_ERROR_NONE;
963 int __bt_pbap_call_get_vcard(GDBusProxy *proxy, bt_pbap_data_t *pbap_data)
969 char *format_str = NULL;
970 char *fields_str = NULL;
971 char *target_file = NULL;
972 char *download_path = NULL;
973 char *vcard_handle = NULL;
974 char vcard[20] = { 0, };
975 GVariantBuilder builder;
976 GVariantBuilder inner_builder;
978 bt_pbap_pull_vcard_parameters_t *app_param = pbap_data->app_param;
980 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
981 g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_ARRAY);
983 /* Add Format Filter only if other than vCard 2.1 (default)*/
984 // if (app_param->format > 0) {
985 format_str = g_strdup(FORMAT[app_param->format]);
986 g_variant_builder_add(&builder, "{sv}", "Format",
987 g_variant_new("s", format_str));
990 /* Add Filter AttributeMask (64bit) */
991 if (app_param->fields > 0) {
992 if (app_param->fields == PBAP_FIELD_ALL) {
993 BT_DBG("** CHECKED ALL **");
994 fields_str = g_strdup("ALL");
995 g_variant_builder_add(&inner_builder, "s", fields_str);
998 for (i = 0; i < PBAP_NUM_OF_FIELDS_ENTRY; i++) {
999 if (app_param->fields & (1ULL << i)) {
1000 BT_DBG("** CHECKED[%d]", i);
1001 fields_str = g_strdup(FIELDS[i]);
1002 g_variant_builder_add(&inner_builder, "s", fields_str);
1008 g_variant_builder_add(&builder, "{sv}", "Fields",
1009 g_variant_new("as", &inner_builder));
1012 filters = g_variant_builder_end(&builder);
1014 //****************************
1015 // Add code for Fields
1017 //****************************
1019 snprintf(vcard, 20, "%d.vcf", app_param->index);
1020 BT_DBG("Handle: %s", vcard);
1021 vcard_handle = g_strdup(vcard);
1022 BT_DBG("vcard_handle: %s", vcard_handle);
1024 ret = storage_get_directory(STORAGE_TYPE_INTERNAL,
1025 STORAGE_DIRECTORY_DOWNLOADS, &download_path);
1027 if (ret != STORAGE_ERROR_NONE) {
1028 target_file = g_strdup_printf("%s/%s", PBAP_DEFAULT_DOWNLAOD_PATH,
1029 PBAP_DEFAULT_FILE_NAME);
1032 target_file = g_strdup_printf("%s/%s", download_path,
1035 target_file = g_strdup_printf("%s/%s", download_path,
1036 PBAP_DEFAULT_FILE_NAME);
1039 free(download_path);
1042 DBG_SECURE("Target flie: %s", target_file);
1044 GVariant *temp = g_variant_new("(ss@a{sv})", vcard_handle, target_file, filters);
1046 g_dbus_proxy_call(proxy, "Pull",
1048 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1049 (GAsyncReadyCallback)__bt_pbap_get_vcard_cb,
1053 g_free(vcard_handle);
1054 g_free(target_file);
1057 return BLUETOOTH_ERROR_NONE;
1060 int __bt_pbap_call_search_phonebook(GDBusProxy *proxy, bt_pbap_data_t *pbap_data)
1064 char *order_str = NULL;
1067 bt_pbap_search_parameters_t *app_param = pbap_data->app_param;
1068 GVariantBuilder builder;
1071 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
1073 /* Add MaxlistCount*/
1074 g_variant_builder_add(&builder, "{sv}", "MaxCount",
1075 g_variant_new("u", app_param->maxlist));
1077 /* Add Order Filter only if other than Indexed (default)*/
1078 if (app_param->order > 0) {
1079 order_str = g_strdup(ORDER[app_param->order]);
1080 g_variant_builder_add(&builder, "{sv}", "Order",
1081 g_variant_new("s", order_str));
1084 /* Add Offset Filter only if other than 0 (default)*/
1085 if (app_param->offset > 0) {
1086 g_variant_builder_add(&builder, "{sv}", "Offset",
1087 g_variant_new("u", app_param->offset));
1090 filters = g_variant_builder_end(&builder);
1092 field = g_strdup(SEARCH_FIELD[app_param->search_attribute]);
1093 value = g_strdup(app_param->search_value);
1095 g_dbus_proxy_call(proxy, "Search",
1096 g_variant_new("(ss@a{sv})", field, value, filters),
1097 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1098 (GAsyncReadyCallback)__bt_pbap_search_phonebook_cb,
1106 return BLUETOOTH_ERROR_NONE;
1109 int _bt_pbap_is_connected(bluetooth_device_address_t *device_address,
1110 gboolean *connected)
1112 char address_string[18] = { 0, };
1114 BT_CHECK_PARAMETER(device_address, return);
1115 BT_CHECK_PARAMETER(connected, return);
1117 /* In now, only 1 pbap connection is allowed */
1118 if (g_pbap_server_address == NULL) {
1123 _bt_convert_addr_type_to_string(address_string,
1124 (unsigned char *)device_address->addr);
1125 BT_DBG("Address String: %s", address_string);
1127 if (g_strcmp0(address_string, g_pbap_server_address) == 0)
1135 int _bt_pbap_get_phonebook_size(const bluetooth_device_address_t *address,
1136 int source, int type)
1139 GDBusConnection *g_conn;
1140 GDBusProxy *g_pbap_session_proxy = NULL;
1141 char address_string[18] = { 0, };
1142 char *source_string = NULL;
1143 char *type_string = NULL;
1145 bt_pbap_data_t *pbap_data = NULL;
1147 BT_CHECK_PARAMETER(address, return);
1149 /* check if connected */
1150 if (g_pbap_session_path == NULL) {
1151 BT_ERR("NOT CONNECTED");
1152 return BLUETOOTH_ERROR_NOT_CONNECTED;
1155 BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]",
1156 address->addr[0], address->addr[1],
1157 address->addr[2], address->addr[3],
1158 address->addr[4], address->addr[5]);
1160 _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr);
1161 BT_DBG("Address String: %s", address_string);
1162 source_string = g_strdup(SOURCE[source]);
1163 type_string = g_strdup(TYPE[type]);
1165 BT_DBG("Address[%s] Source[%s] Type[%s]",
1166 address_string, source_string, type_string);
1167 BT_DBG("Session Path = %s\n", g_pbap_session_path);
1169 g_conn = _bt_get_system_gconn();
1170 if (g_conn == NULL) {
1171 BT_ERR("Couldn't connect to session bus");
1172 g_free(source_string);
1173 g_free(type_string);
1176 g_pbap_session_proxy = g_dbus_proxy_new_sync(g_conn,
1177 G_DBUS_PROXY_FLAGS_NONE, NULL,
1178 PBAP_SESSION_SERVICE, g_pbap_session_path,
1179 PBAP_SESSION_INTERFACE, NULL, &err);
1181 if (!g_pbap_session_proxy) {
1182 BT_ERR("Failed to get a proxy for D-Bus\n");
1184 ERR("Unable to create proxy: %s", err->message);
1185 g_clear_error(&err);
1187 g_free(source_string);
1188 g_free(type_string);
1192 BT_DBG("Prepare PBAP data");
1193 pbap_data = g_new0(bt_pbap_data_t, 1);
1194 pbap_data->operation = GET_SIZE;
1195 pbap_data->data = g_strdup(address_string);
1197 if (source == selected_path.folder && type == selected_path.type) {
1198 BT_DBG("Call get_phonebook_size directly");
1199 g_free(source_string);
1200 g_free(type_string);
1201 return __bt_pbap_call_get_phonebook_size(g_pbap_session_proxy, pbap_data);
1204 BT_DBG("Call SELECT");
1205 g_dbus_proxy_call(g_pbap_session_proxy, "Select",
1206 g_variant_new("(ss)", source_string, type_string),
1207 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1208 (GAsyncReadyCallback)__bt_pbap_select_cb,
1211 BT_DBG("Set Folders");
1212 selected_path.folder = source;
1213 selected_path.type = type;
1215 g_free(source_string);
1216 g_free(type_string);
1220 int _bt_pbap_get_phonebook(const bluetooth_device_address_t *address,
1221 int source, int type, bt_pbap_pull_parameters_t *app_param)
1224 GDBusConnection *g_conn;
1225 GDBusProxy *g_pbap_session_proxy = NULL;
1226 char address_string[18] = { 0, };
1227 char *source_string = NULL;
1228 char *type_string = NULL;
1231 bt_pbap_data_t *pbap_data = NULL;
1232 bt_pbap_pull_parameters_t *param = NULL;
1234 BT_CHECK_PARAMETER(address, return);
1236 /* check if connected */
1237 if (g_pbap_session_path == NULL) {
1238 BT_ERR("NOT CONNECTED");
1239 return BLUETOOTH_ERROR_NOT_CONNECTED;
1242 BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]",
1243 address->addr[0], address->addr[1],
1244 address->addr[2], address->addr[3],
1245 address->addr[4], address->addr[5]);
1247 _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr);
1248 BT_DBG("Address String: %s", address_string);
1250 source_string = g_strdup(SOURCE[source]);
1251 type_string = g_strdup(TYPE[type]);
1253 BT_DBG("Address[%s] Source[%s] Type[%s]",
1254 address_string, source_string, type_string);
1256 BT_DBG("Session Path = %s\n", g_pbap_session_path);
1258 g_conn = _bt_get_system_gconn();
1259 if (g_conn == NULL) {
1260 BT_ERR("Couldn't connect to session bus");
1261 g_free(source_string);
1262 g_free(type_string);
1265 g_pbap_session_proxy = g_dbus_proxy_new_sync(g_conn,
1266 G_DBUS_PROXY_FLAGS_NONE, NULL,
1267 PBAP_SESSION_SERVICE, g_pbap_session_path,
1268 PBAP_SESSION_INTERFACE, NULL, &err);
1270 if (!g_pbap_session_proxy) {
1271 BT_ERR("Failed to get a proxy for D-Bus\n");
1273 ERR("Unable to create proxy: %s", err->message);
1274 g_clear_error(&err);
1276 g_free(source_string);
1277 g_free(type_string);
1281 pbap_data = g_new0(bt_pbap_data_t, 1);
1282 pbap_data->operation = PULL_ALL;
1283 pbap_data->data = g_strdup(address_string);
1284 param = g_new0(bt_pbap_pull_parameters_t, 1);
1285 memcpy(param, app_param, sizeof(bt_pbap_pull_parameters_t));
1286 pbap_data->app_param = param;
1288 if (source == selected_path.folder && type == selected_path.type) {
1289 g_free(source_string);
1290 g_free(type_string);
1291 return __bt_pbap_call_get_phonebook(g_pbap_session_proxy, pbap_data);
1294 g_dbus_proxy_call(g_pbap_session_proxy, "Select",
1295 g_variant_new("(ss)", source_string, type_string),
1296 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1297 (GAsyncReadyCallback)__bt_pbap_select_cb,
1300 selected_path.folder = source;
1301 selected_path.type = type;
1302 g_free(source_string);
1303 g_free(type_string);
1308 int _bt_pbap_get_list(const bluetooth_device_address_t *address, int source,
1309 int type, bt_pbap_list_parameters_t *app_param)
1312 GDBusConnection *g_conn;
1313 GDBusProxy *g_pbap_session_proxy = NULL;
1314 char address_string[18] = { 0, };
1315 char *source_string = NULL;
1316 char *type_string = NULL;
1319 bt_pbap_data_t *pbap_data = NULL;
1320 bt_pbap_list_parameters_t *param = NULL;
1322 BT_CHECK_PARAMETER(address, return);
1324 /* check if connected */
1325 if (g_pbap_session_path == NULL) {
1326 BT_ERR("NOT CONNECTED");
1327 return BLUETOOTH_ERROR_NOT_CONNECTED;
1330 BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]",
1331 address->addr[0], address->addr[1],
1332 address->addr[2], address->addr[3],
1333 address->addr[4], address->addr[5]);
1335 _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr);
1336 BT_DBG("Address String: %s", address_string);
1338 source_string = g_strdup(SOURCE[source]);
1339 type_string = g_strdup("nil");
1341 BT_DBG("Address[%s] Source[%s] Type[%s]",
1342 address_string, source_string, type_string);
1344 BT_DBG("Session Path = %s\n", g_pbap_session_path);
1346 g_conn = _bt_get_system_gconn();
1347 if (g_conn == NULL) {
1348 BT_ERR("Couldn't connect to session bus");
1349 g_free(source_string);
1350 g_free(type_string);
1353 g_pbap_session_proxy = g_dbus_proxy_new_sync(g_conn,
1354 G_DBUS_PROXY_FLAGS_NONE, NULL,
1355 PBAP_SESSION_SERVICE, g_pbap_session_path,
1356 PBAP_SESSION_INTERFACE, NULL, &err);
1358 if (!g_pbap_session_proxy) {
1359 BT_ERR("Failed to get a proxy for D-Bus\n");
1361 ERR("Unable to create proxy: %s", err->message);
1362 g_clear_error(&err);
1364 g_free(source_string);
1365 g_free(type_string);
1369 BT_DBG("Set PBAP Data");
1370 pbap_data = g_new0(bt_pbap_data_t, 1);
1371 pbap_data->operation = GET_LIST;
1372 pbap_data->data = g_strdup(address_string);
1373 param = g_new0(bt_pbap_list_parameters_t, 1);
1374 memcpy(param, app_param, sizeof(bt_pbap_list_parameters_t));
1375 pbap_data->app_param = param;
1377 /* Always Call Select for vCardListing
1378 if (source == selected_path.folder && type == selected_path.type) {
1379 BT_DBG("Call Directly");
1380 return __bt_pbap_call_get_vcards_list(g_pbap_session_proxy, pbap_data);
1382 BT_DBG("Call SELECT");
1383 g_dbus_proxy_call(g_pbap_session_proxy, "Select",
1384 g_variant_new("(ss)", source_string, type_string),
1385 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1386 (GAsyncReadyCallback)__bt_pbap_select_cb,
1388 BT_DBG("Set Folders");
1389 selected_path.folder = source;
1390 selected_path.type = type;
1391 g_free(source_string);
1392 g_free(type_string);
1398 int _bt_pbap_pull_vcard(const bluetooth_device_address_t *address,
1399 int source, int type, bt_pbap_pull_vcard_parameters_t *app_param)
1402 GDBusConnection *g_conn;
1403 GDBusProxy *g_pbap_session_proxy = NULL;
1404 char address_string[18] = { 0, };
1405 char *source_string = NULL;
1406 char *type_string = NULL;
1407 bt_pbap_data_t *pbap_data = NULL;
1408 bt_pbap_pull_vcard_parameters_t *param = NULL;
1411 BT_CHECK_PARAMETER(address, return);
1413 /* check if connected */
1414 if (g_pbap_session_path == NULL) {
1415 BT_ERR("NOT CONNECTED");
1416 return BLUETOOTH_ERROR_NOT_CONNECTED;
1419 BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]",
1420 address->addr[0], address->addr[1],
1421 address->addr[2], address->addr[3],
1422 address->addr[4], address->addr[5]);
1424 _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr);
1425 BT_DBG("Address String: %s", address_string);
1427 source_string = g_strdup(SOURCE[source]);
1428 type_string = g_strdup(TYPE[type]);
1430 BT_DBG("Address[%s] Source[%s] Type[%s]",
1431 address_string, source_string, type_string);
1433 BT_DBG("Session Path = %s\n", g_pbap_session_path);
1435 g_conn = _bt_get_system_gconn();
1436 if (g_conn == NULL) {
1437 BT_ERR("Couldn't connect to session bus");
1438 g_free(source_string);
1439 g_free(type_string);
1442 g_pbap_session_proxy = g_dbus_proxy_new_sync(g_conn,
1443 G_DBUS_PROXY_FLAGS_NONE, NULL,
1444 PBAP_SESSION_SERVICE, g_pbap_session_path,
1445 PBAP_SESSION_INTERFACE, NULL, &err);
1447 if (!g_pbap_session_proxy) {
1448 BT_ERR("Failed to get a proxy for D-Bus\n");
1450 ERR("Unable to create proxy: %s", err->message);
1451 g_clear_error(&err);
1453 g_free(source_string);
1454 g_free(type_string);
1458 pbap_data = g_new0(bt_pbap_data_t, 1);
1459 pbap_data->operation = GET_VCARD;
1460 pbap_data->data = g_strdup(address_string);
1461 param = g_new0(bt_pbap_pull_vcard_parameters_t, 1);
1462 memcpy(param, app_param, sizeof(bt_pbap_pull_vcard_parameters_t));
1463 pbap_data->app_param = param;
1465 if (source == selected_path.folder && type == selected_path.type) {
1466 g_free(source_string);
1467 g_free(type_string);
1468 return __bt_pbap_call_get_vcard(g_pbap_session_proxy, pbap_data);
1471 g_dbus_proxy_call(g_pbap_session_proxy, "Select",
1472 g_variant_new("(ss)", source_string, type_string),
1473 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1474 (GAsyncReadyCallback)__bt_pbap_select_cb,
1477 selected_path.folder = source;
1478 selected_path.type = type;
1479 g_free(source_string);
1480 g_free(type_string);
1485 int _bt_pbap_phonebook_search(const bluetooth_device_address_t *address,
1486 int source, int type, bt_pbap_search_parameters_t *app_param)
1489 GDBusConnection *g_conn;
1490 GDBusProxy *g_pbap_session_proxy = NULL;
1491 char address_string[18] = { 0, };
1492 char *source_string = NULL;
1493 char *type_string = NULL;
1494 bt_pbap_data_t *pbap_data = NULL;
1495 bt_pbap_search_parameters_t *param = NULL;
1498 BT_CHECK_PARAMETER(address, return);
1500 /* check if connected */
1501 if (g_pbap_session_path == NULL) {
1502 BT_ERR("NOT CONNECTED");
1503 return BLUETOOTH_ERROR_NOT_CONNECTED;
1506 BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]",
1507 address->addr[0], address->addr[1],
1508 address->addr[2], address->addr[3],
1509 address->addr[4], address->addr[5]);
1511 _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr);
1512 BT_DBG("Address String: %s", address_string);
1514 source_string = g_strdup(SOURCE[source]);
1515 type_string = g_strdup(TYPE[type]);
1517 BT_DBG("Address[%s] Source[%s] Type[%s]",
1518 address_string, source_string, type_string);
1520 BT_DBG("Session Path = %s\n", g_pbap_session_path);
1522 g_conn = _bt_get_system_gconn();
1523 if (g_conn == NULL) {
1524 BT_ERR("Couldn't connect to session bus");
1525 g_free(source_string);
1526 g_free(type_string);
1529 g_pbap_session_proxy = g_dbus_proxy_new_sync(g_conn,
1530 G_DBUS_PROXY_FLAGS_NONE, NULL,
1531 PBAP_SESSION_SERVICE, g_pbap_session_path,
1532 PBAP_SESSION_INTERFACE, NULL, &err);
1534 if (!g_pbap_session_proxy) {
1535 BT_ERR("Failed to get a proxy for D-Bus\n");
1537 ERR("Unable to create proxy: %s", err->message);
1538 g_clear_error(&err);
1540 g_free(source_string);
1541 g_free(type_string);
1545 pbap_data = g_new0(bt_pbap_data_t, 1);
1546 pbap_data->operation = PB_SEARCH;
1547 pbap_data->data = g_strdup(address_string);
1548 param = g_new0(bt_pbap_search_parameters_t, 1);
1549 memcpy(param, app_param, sizeof(bt_pbap_search_parameters_t));
1550 pbap_data->app_param = param;
1552 /* Call Select for vCardListing
1553 if (source == selected_path.folder && type == selected_path.type) {
1554 return __bt_pbap_call_search_phonebook(g_pbap_session_proxy, pbap_data);
1557 g_dbus_proxy_call(g_pbap_session_proxy, "Select",
1558 g_variant_new("(ss)", source_string, type_string),
1559 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1560 (GAsyncReadyCallback)__bt_pbap_select_cb,
1563 selected_path.folder = source;
1564 selected_path.type = type;
1566 g_free(source_string);
1567 g_free(type_string);