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.
24 #include "bluetooth-api.h"
25 #include "bt-internal-types.h"
27 #include "bt-service-common.h"
28 #include "bt-service-event.h"
29 #include "bt-service-util.h"
30 #include "bt-service-map-client.h"
31 #include "bt-service-obex-agent.h"
32 #include "bt-service-core-adapter.h"
34 #define DBUS_TIMEOUT 20 * 1000 /* 20 Seconds */
36 enum bt_map_transfer_type {
37 BT_MAP_TRANSFER_GET_MESSAGE = 0,
38 BT_MAP_TRANSFER_PUSH_MESSAGE
42 enum bt_map_transfer_type transfer_type;
45 } bt_map_callback_data_t;
47 static GSList *transfer_list = NULL;
49 bt_session_info_t *session_info;
51 static void __bt_free_session_info(bt_session_info_t *info)
54 g_free(info->address);
58 void _bt_map_disconnected(const char *session_path)
61 GVariant *param = NULL;
62 ret_if(session_info == NULL);
64 if (g_strcmp0(session_info->session_path,
66 BT_INFO("Path mismatch, previous transfer failed! Returning");
70 param = g_variant_new("(isi)", session_info->result,
71 session_info->address,
72 session_info->request_id);
73 _bt_send_event(BT_MAP_CLIENT_EVENT,
74 BLUETOOTH_EVENT_MAP_DISCONNECTED,
77 __bt_free_session_info(session_info);
83 int _bt_create_session_sync(const char* address, char** session_id)
85 BT_DBG("Entered SERVICE create session");
86 GDBusConnection *g_conn;
87 GDBusProxy *session_proxy;
90 retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
92 g_conn = _bt_get_system_gconn();
93 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
95 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
96 NULL, BT_OBEX_SERVICE_NAME,
98 BT_OBEX_CLIENT_INTERFACE,
101 BT_ERR("Unable to create session_proxy: %s", err->message);
103 return BLUETOOTH_ERROR_INTERNAL;
105 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
107 GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
108 g_variant_builder_add(builder, "{sv}", "Target",
109 g_variant_new("s", "map"));
110 GVariant *args = g_variant_builder_end(builder);
111 g_variant_builder_unref(builder);
112 GVariant *param = g_variant_new("(s@a{sv})", address, args);
114 GVariant *value = g_dbus_proxy_call_sync(session_proxy, "CreateSession", param,
115 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
117 BT_ERR("Could not create session: %s\n", err->message);
119 return BLUETOOTH_ERROR_INTERNAL;
122 BT_ERR("create session returned value is null\n");
123 return BLUETOOTH_ERROR_INTERNAL;
125 BT_DBG("create session succeed\n");
129 g_variant_get(value, "(&o)", session_id);
130 BT_DBG("session_id = \"%s\"\n", *session_id);
132 return BLUETOOTH_ERROR_NONE;
135 int _bt_destroy_session_sync(const char* session_id)
137 BT_DBG("Entered SERVICE destroy session with id: \"%s\"", session_id);
138 GDBusConnection *g_conn;
139 GDBusProxy *session_proxy;
143 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
145 g_conn = _bt_get_system_gconn();
146 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
148 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
149 NULL, BT_OBEX_SERVICE_NAME,
151 BT_OBEX_CLIENT_INTERFACE,
154 BT_ERR("Unable to create session_proxy: %s", err->message);
156 return BLUETOOTH_ERROR_INTERNAL;
158 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
160 GVariant *param = g_variant_new("(o)", session_id);
162 result = g_dbus_proxy_call_sync(session_proxy, "RemoveSession", param,
163 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
166 BT_ERR("Could not remove session: %s\n", err->message);
168 return BLUETOOTH_ERROR_INTERNAL;
171 g_variant_unref(result);
172 BT_DBG("remove session succeed\n");
175 return BLUETOOTH_ERROR_NONE;
178 int _bt_map_client_set_folder(const char* session_id, const char* name)
183 GDBusConnection *g_conn;
184 GDBusProxy *message_proxy;
185 GVariant *ret = NULL;
187 g_conn = _bt_get_system_gconn();
188 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
190 message_proxy = g_dbus_proxy_new_sync(g_conn,
191 G_DBUS_PROXY_FLAGS_NONE, NULL,
192 BT_OBEX_SERVICE_NAME, session_id,
193 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
195 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
197 ret = g_dbus_proxy_call_sync(message_proxy,
198 "SetFolder", g_variant_new("(s)", name),
199 G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT,
204 BT_ERR("SetFolder Error: %s\n", err->message);
208 g_variant_unref(ret);
211 g_object_unref(message_proxy);
215 return BLUETOOTH_ERROR_NONE;
218 static void __bt_list_folders_cb(GDBusProxy *proxy,
219 GAsyncResult *res, gpointer user_data)
223 GError *error = NULL;
224 GVariant *value, *in_param, *param;
226 int result = BLUETOOTH_ERROR_NONE;
229 in_param = (GVariant*) user_data;
230 g_variant_get(in_param, "(i)", &request_id);
232 value = g_dbus_proxy_call_finish(proxy, res, &error);
235 BT_ERR("%s", error->message);
236 g_clear_error(&error);
237 result = BLUETOOTH_ERROR_INTERNAL;
240 param = g_variant_new("(iiv)", result, request_id, value);
241 BT_DBG("RequestID[%d]", request_id);
242 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
243 BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, param);
245 g_variant_unref(value);
246 g_variant_unref(in_param);
251 int _bt_map_client_list_folders(
253 GDBusMethodInvocation *context,
254 const char* session_id,
255 const char* filter_serialized)
257 BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id);
258 GDBusConnection *g_conn;
259 GDBusProxy *message_access_proxy;
260 GError *error = NULL;
261 int result = BLUETOOTH_ERROR_NONE;
263 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
265 g_conn = _bt_get_system_gconn();
266 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
268 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
269 &request_id, sizeof(int),
271 g_dbus_method_invocation_return_value(context,
272 g_variant_new("(iv)", result, out_param1));
274 // create message access proxy
275 g_clear_error(&error);
276 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
277 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
280 BT_ERR("Could not create message access proxy: %s\n", error->message);
281 result = BLUETOOTH_ERROR_INTERNAL;
283 if (!message_access_proxy) {
284 BT_ERR("message proxy handle is null\n");
285 result = BLUETOOTH_ERROR_INTERNAL;
287 BT_DBG("message proxy set");
289 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
291 GVariant *params = g_variant_new("(@a{sv})", filter_variant);
292 GVariant *param = g_variant_new("(i)", request_id);
294 g_dbus_proxy_call(message_access_proxy,
295 "ListFolders", params,
296 G_DBUS_CALL_FLAGS_NONE, -1,
298 (GAsyncReadyCallback)__bt_list_folders_cb,
303 if (message_access_proxy)
304 g_object_unref(message_access_proxy);
310 static void __bt_list_filter_fields_cb(GDBusProxy *proxy,
311 GAsyncResult *res, gpointer user_data)
315 GError *error = NULL;
316 GVariant *value, *in_param, *param;
318 int result = BLUETOOTH_ERROR_NONE;
321 in_param = (GVariant*) user_data;
322 g_variant_get(in_param, "(i)", &request_id);
324 value = g_dbus_proxy_call_finish(proxy, res, &error);
327 BT_ERR("%s", error->message);
328 g_clear_error(&error);
329 result = BLUETOOTH_ERROR_INTERNAL;
332 param = g_variant_new("(ivi)", result, value, request_id);
334 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_LIST_FILTER_FIELD_COMPLETE,
337 g_variant_unref(value);
338 g_variant_unref(in_param);
343 int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id)
348 GDBusConnection *g_conn;
349 GDBusProxy *message_proxy;
350 int result = BLUETOOTH_ERROR_NONE;
352 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
354 g_conn = _bt_get_system_gconn();
355 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
357 GVariant *out_param = g_variant_new_from_data((const GVariantType *)"ay",
358 &request_id, sizeof(int),
361 g_dbus_method_invocation_return_value(context,
362 g_variant_new("(iv)", result, out_param));
365 message_proxy = g_dbus_proxy_new_sync(g_conn,
366 G_DBUS_PROXY_FLAGS_NONE, NULL,
367 BT_OBEX_SERVICE_NAME, session_id,
368 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
370 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
372 GVariant *param = g_variant_new("(i)", request_id);
374 g_dbus_proxy_call(message_proxy,
375 "ListFilterFields", g_variant_new("()"),
376 G_DBUS_CALL_FLAGS_NONE, -1,
378 (GAsyncReadyCallback)__bt_list_filter_fields_cb,
381 g_object_unref(message_proxy);
385 return BLUETOOTH_ERROR_NONE;
388 static void __bt_list_messages_cb(
389 GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
393 GError *error = NULL;
394 GVariant *value, *in_param, *param;
396 int result = BLUETOOTH_ERROR_NONE;
399 in_param = (GVariant*) user_data;
400 g_variant_get(in_param, "(i)", &request_id);
402 value = g_dbus_proxy_call_finish(proxy, res, &error);
405 BT_ERR("%s", error->message);
406 g_clear_error(&error);
407 result = BLUETOOTH_ERROR_INTERNAL;
410 param = g_variant_new("(iiv)", result, request_id, value);
411 BT_DBG("RequestID[%d]", request_id);
412 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
413 BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param);
415 g_variant_unref(value);
416 g_variant_unref(in_param);
421 int _bt_map_client_list_messages(
423 GDBusMethodInvocation *context,
424 const char* session_id,
426 const char* filter_serialized)
428 BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id);
429 BT_DBG("Entered folder: %s", folder);
430 GDBusConnection *g_conn;
431 GDBusProxy *message_access_proxy;
432 GError *error = NULL;
433 int result = BLUETOOTH_ERROR_NONE;
435 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
437 g_conn = _bt_get_system_gconn();
438 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
440 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
441 &request_id, sizeof(int),
443 g_dbus_method_invocation_return_value(context,
444 g_variant_new("(iv)", result, out_param1));
446 // create message access proxy
447 g_clear_error(&error);
448 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
449 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
452 BT_ERR("Could not create message access proxy: %s\n", error->message);
453 result = BLUETOOTH_ERROR_INTERNAL;
455 if (!message_access_proxy) {
456 BT_ERR("message proxy handle is null\n");
457 result = BLUETOOTH_ERROR_INTERNAL;
459 BT_DBG("message proxy set");
461 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
463 GVariant *params = g_variant_new("(s@a{sv})", folder, filter_variant);
464 GVariant *param = g_variant_new("(i)", request_id);
466 g_dbus_proxy_call(message_access_proxy,
467 "ListMessages", params,
468 G_DBUS_CALL_FLAGS_NONE, -1,
470 (GAsyncReadyCallback)__bt_list_messages_cb,
475 if (message_access_proxy)
476 g_object_unref(message_access_proxy);
482 int _bt_map_client_update_inbox(const char* session_id)
487 GDBusConnection *g_conn;
488 GDBusProxy *message_proxy;
489 GVariant *ret = NULL;
491 g_conn = _bt_get_system_gconn();
492 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
494 message_proxy = g_dbus_proxy_new_sync(g_conn,
495 G_DBUS_PROXY_FLAGS_NONE, NULL,
496 BT_OBEX_SERVICE_NAME, session_id,
497 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
499 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
501 ret = g_dbus_proxy_call_sync(message_proxy,
502 "UpdateInbox", g_variant_new("()"),
503 G_DBUS_CALL_FLAGS_NONE, -1,
508 BT_ERR("UpdateInbox Error: %s\n", err->message);
512 g_variant_unref(ret);
515 g_object_unref(message_proxy);
519 return BLUETOOTH_ERROR_NONE;
522 void _bt_map_on_transfer_finished(const char *transfer_object_path, const int error)
524 BT_DBG("Entered _bt_map_on_transfer_finished");
525 BT_DBG("Looking for transfer %s id", transfer_object_path);
527 bt_map_callback_data_t *callback_data = NULL;
528 GSList* transfer = NULL;
529 for (transfer = transfer_list; transfer != NULL; transfer = g_slist_next(transfer)) {
530 callback_data = transfer->data;
531 if (NULL == callback_data)
534 if (0 == strcmp(transfer_object_path, callback_data->transfer_path)) {
535 BT_DBG("request id FOUND - triggering event");
537 GVariant *param = g_variant_new("(ii)", error, callback_data->request_id);
540 switch (callback_data->transfer_type) {
541 case BT_MAP_TRANSFER_GET_MESSAGE:
542 event = BLUETOOTH_EVENT_MAP_GET_MESSAGE_COMPLETE;
544 case BT_MAP_TRANSFER_PUSH_MESSAGE:
545 event = BLUETOOTH_EVENT_MAP_PUSH_MESSAGE_COMPLETE;
549 _bt_send_event(BT_MAP_CLIENT_EVENT, event, param);
551 // remove callback data from list
552 transfer_list = g_slist_remove(transfer_list, transfer);
554 //free memory and break loop
555 g_free(callback_data->transfer_path);
556 callback_data->transfer_path = NULL;
557 g_free(callback_data);
564 static void __bt_push_message_cb(GDBusProxy *proxy,
565 GAsyncResult *res, gpointer user_data)
569 GError *error = NULL;
570 GVariant *value, *in_param;
572 char *transfer_object_path = NULL;
573 GVariantIter *iter = NULL;
577 in_param = (GVariant*) user_data;
578 g_variant_get(in_param, "(i)", &request_id);
580 value = g_dbus_proxy_call_finish(proxy, res, &error);
582 BT_ERR("%s", error->message);
583 g_clear_error(&error);
587 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
588 g_variant_unref(value);
591 BT_DBG("transfer object path: [%s]", transfer_object_path);
593 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
594 bt_map_callback_data_t* callback_data = g_malloc0(sizeof(bt_map_callback_data_t));
595 callback_data->transfer_type = BT_MAP_TRANSFER_PUSH_MESSAGE;
596 callback_data->request_id = request_id;
597 callback_data->transfer_path = transfer_object_path;
599 transfer_list = g_slist_append(transfer_list, callback_data);
601 g_variant_unref(value);
602 g_variant_unref(in_param);
607 int _bt_map_client_push_message(
609 GDBusMethodInvocation *context,
610 const char* session_id,
611 const char* source_file,
613 const char* args_serialized)
615 BT_DBG("Entered _bt_map_client_push_message with session id: \"%s\"", session_id);
616 BT_DBG("Entered source_file: %s", source_file);
617 BT_DBG("Entered folder: %s", folder);
619 GDBusConnection *g_conn;
620 GDBusProxy *message_access_proxy;
621 GError *error = NULL;
622 int result = BLUETOOTH_ERROR_NONE;
624 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
626 // TODO event listeners registration on first call, where should it be unregistered??
627 // _bt_map_client_event_init(); --need to do
629 g_conn = _bt_get_system_gconn();
630 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
632 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
633 &request_id, sizeof(int),
635 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
637 // create message access proxy
638 g_clear_error(&error);
639 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
640 BT_OBEX_SERVICE_NAME, session_id, BT_OBEX_MESSAGE_INTERFACE,
643 BT_ERR("Could not create message access proxy: %s\n", error->message);
644 result = BLUETOOTH_ERROR_INTERNAL;
646 if (!message_access_proxy) {
647 BT_ERR("message proxy handle is null\n");
648 result = BLUETOOTH_ERROR_INTERNAL;
650 BT_DBG("message proxy set");
652 GVariant *args_variant = g_variant_parse(NULL, args_serialized, NULL, NULL, NULL);
654 GVariant *params = g_variant_new("(ss@a{sv})", source_file, folder, args_variant);
655 GVariant *req_id = g_variant_new("(i)", request_id);
657 g_dbus_proxy_call(message_access_proxy,
658 "PushMessage", params,
659 G_DBUS_CALL_FLAGS_NONE, -1,
660 NULL, (GAsyncReadyCallback)__bt_push_message_cb,
665 if (message_access_proxy)
666 g_object_unref(message_access_proxy);
672 static void __bt_get_message_cb(GDBusProxy *proxy,
673 GAsyncResult *res, gpointer user_data)
677 GError *error = NULL;
678 GVariant *value, *in_param;
680 char *transfer_object_path = NULL;
681 GVariantIter *iter = NULL;
685 in_param = (GVariant*) user_data;
686 g_variant_get(in_param, "(i)", &request_id);
688 value = g_dbus_proxy_call_finish(proxy, res, &error);
690 BT_ERR("%s", error->message);
691 g_clear_error(&error);
695 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
696 g_variant_unref(value);
699 BT_DBG("transfer object path: [%s]", transfer_object_path);
701 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
702 bt_map_callback_data_t* callback_data = g_malloc0(sizeof(bt_map_callback_data_t));
703 callback_data->transfer_type = BT_MAP_TRANSFER_GET_MESSAGE;
704 callback_data->request_id = request_id;
705 callback_data->transfer_path = transfer_object_path;
707 transfer_list = g_slist_append(transfer_list, callback_data);
709 g_variant_unref(value);
710 g_variant_unref(in_param);
715 int _bt_map_client_get_message(
717 GDBusMethodInvocation *context,
718 const char* message_object,
719 const char* target_file,
722 BT_DBG("Entered _bt_map_client_get_message");
724 GDBusConnection *g_conn;
725 GDBusProxy *message_proxy;
726 GError *error = NULL;
727 int result = BLUETOOTH_ERROR_NONE;
729 retv_if(message_object == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
731 // TODO event listeners registration on first call, where should it be unregistered??
732 // _bt_map_client_event_init();
734 g_conn = _bt_get_system_gconn();
735 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
737 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
738 &request_id, sizeof(int),
740 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
742 // create message proxy
743 g_clear_error(&error);
744 message_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
745 BT_OBEX_SERVICE_NAME, message_object, "org.bluez.obex.Message1",
748 BT_ERR("Could not create message proxy: %s\n", error->message);
749 result = BLUETOOTH_ERROR_INTERNAL;
751 if (!message_proxy) {
752 BT_ERR("message proxy handle is null\n");
753 result = BLUETOOTH_ERROR_INTERNAL;
755 BT_DBG("message proxy set");
756 GVariant *params = g_variant_new("(sb)", target_file, attachment);
757 GVariant *req_id = g_variant_new("(i)", request_id);
759 g_dbus_proxy_call(message_proxy, "Get", params, G_DBUS_CALL_FLAGS_NONE, -1,
760 NULL, (GAsyncReadyCallback)__bt_get_message_cb, (void*)req_id);
765 g_object_unref(message_proxy);