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;
142 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
144 g_conn = _bt_get_system_gconn();
145 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
147 session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
148 NULL, BT_OBEX_SERVICE_NAME,
150 BT_OBEX_CLIENT_INTERFACE,
153 BT_ERR("Unable to create session_proxy: %s", err->message);
155 return BLUETOOTH_ERROR_INTERNAL;
157 retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
159 GVariant *param = g_variant_new("(o)", session_id);
161 g_dbus_proxy_call_sync(session_proxy, "RemoveSession", param,
162 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
164 BT_ERR("Could not remove session: %s\n", err->message);
166 return BLUETOOTH_ERROR_INTERNAL;
168 BT_DBG("remove session succeed\n");
171 return BLUETOOTH_ERROR_NONE;
174 int _bt_map_client_set_folder(const char* session_id, const char* name)
179 GDBusConnection *g_conn;
180 GDBusProxy *message_proxy;
181 GVariant *ret = NULL;
183 g_conn = _bt_get_system_gconn();
184 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
186 message_proxy = g_dbus_proxy_new_sync(g_conn,
187 G_DBUS_PROXY_FLAGS_NONE, NULL,
188 BT_OBEX_SERVICE_NAME, session_id,
189 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
191 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
193 ret = g_dbus_proxy_call_sync(message_proxy,
194 "SetFolder", g_variant_new("(s)", name),
195 G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT,
200 BT_ERR("SetFolder Error: %s\n", err->message);
204 g_variant_unref(ret);
207 g_object_unref(message_proxy);
211 return BLUETOOTH_ERROR_NONE;
214 static void __bt_list_folders_cb(GDBusProxy *proxy,
215 GAsyncResult *res, gpointer user_data)
219 GError *error = NULL;
220 GVariant *value, *in_param, *param;
222 int result = BLUETOOTH_ERROR_NONE;
225 in_param = (GVariant*) user_data;
226 g_variant_get(in_param, "(i)", &request_id);
228 value = g_dbus_proxy_call_finish(proxy, res, &error);
231 BT_ERR("%s", error->message);
232 g_clear_error(&error);
233 result = BLUETOOTH_ERROR_INTERNAL;
236 param = g_variant_new("(iiv)", result, request_id, value);
237 BT_DBG("RequestID[%d]", request_id);
238 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
239 BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, param);
241 g_variant_unref(value);
242 g_variant_unref(in_param);
247 int _bt_map_client_list_folders(
249 GDBusMethodInvocation *context,
250 const char* session_id,
251 const char* filter_serialized)
253 BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id);
254 GDBusConnection *g_conn;
255 GDBusProxy *message_access_proxy;
256 GError *error = NULL;
257 int result = BLUETOOTH_ERROR_NONE;
259 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
261 g_conn = _bt_get_system_gconn();
262 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
264 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
265 &request_id, sizeof(int),
267 g_dbus_method_invocation_return_value(context,
268 g_variant_new("(iv)", result, out_param1));
270 // create message access proxy
271 g_clear_error(&error);
272 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
273 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
276 BT_ERR("Could not create message access proxy: %s\n", error->message);
277 result = BLUETOOTH_ERROR_INTERNAL;
279 if (!message_access_proxy) {
280 BT_ERR("message proxy handle is null\n");
281 result = BLUETOOTH_ERROR_INTERNAL;
283 BT_DBG("message proxy set");
285 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
287 GVariant *params = g_variant_new("(@a{sv})", filter_variant);
288 GVariant *param = g_variant_new("(i)", request_id);
290 g_dbus_proxy_call(message_access_proxy,
291 "ListFolders", params,
292 G_DBUS_CALL_FLAGS_NONE, -1,
294 (GAsyncReadyCallback)__bt_list_folders_cb,
299 if (message_access_proxy)
300 g_object_unref(message_access_proxy);
306 static void __bt_list_filter_fields_cb(GDBusProxy *proxy,
307 GAsyncResult *res, gpointer user_data)
311 GError *error = NULL;
312 GVariant *value, *in_param, *param;
314 int result = BLUETOOTH_ERROR_NONE;
317 in_param = (GVariant*) user_data;
318 g_variant_get(in_param, "(i)", &request_id);
320 value = g_dbus_proxy_call_finish(proxy, res, &error);
323 BT_ERR("%s", error->message);
324 g_clear_error(&error);
325 result = BLUETOOTH_ERROR_INTERNAL;
328 param = g_variant_new("(ivi)", result, value, request_id);
330 _bt_send_event(BT_MAP_CLIENT_EVENT, BLUETOOTH_EVENT_MAP_LIST_FILTER_FIELD_COMPLETE,
333 g_variant_unref(value);
334 g_variant_unref(in_param);
339 int _bt_map_client_list_filter_fields(int request_id, GDBusMethodInvocation *context, const char* session_id)
344 GDBusConnection *g_conn;
345 GDBusProxy *message_proxy;
346 int result = BLUETOOTH_ERROR_NONE;
348 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
350 g_conn = _bt_get_system_gconn();
351 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
353 GVariant *out_param = g_variant_new_from_data((const GVariantType *)"ay",
354 &request_id, sizeof(int),
357 g_dbus_method_invocation_return_value(context,
358 g_variant_new("(iv)", result, out_param));
361 message_proxy = g_dbus_proxy_new_sync(g_conn,
362 G_DBUS_PROXY_FLAGS_NONE, NULL,
363 BT_OBEX_SERVICE_NAME, session_id,
364 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
366 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
368 GVariant *param = g_variant_new("(i)", request_id);
370 g_dbus_proxy_call(message_proxy,
371 "ListFilterFields", g_variant_new("()"),
372 G_DBUS_CALL_FLAGS_NONE, -1,
374 (GAsyncReadyCallback)__bt_list_filter_fields_cb,
377 g_object_unref(message_proxy);
381 return BLUETOOTH_ERROR_NONE;
384 static void __bt_list_messages_cb(
385 GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
389 GError *error = NULL;
390 GVariant *value, *in_param, *param;
392 int result = BLUETOOTH_ERROR_NONE;
395 in_param = (GVariant*) user_data;
396 g_variant_get(in_param, "(i)", &request_id);
398 value = g_dbus_proxy_call_finish(proxy, res, &error);
401 BT_ERR("%s", error->message);
402 g_clear_error(&error);
403 result = BLUETOOTH_ERROR_INTERNAL;
406 param = g_variant_new("(iiv)", result, request_id, value);
407 BT_DBG("RequestID[%d]", request_id);
408 result = _bt_send_event(BT_MAP_CLIENT_EVENT,
409 BLUETOOTH_EVENT_MAP_LIST_MESSAGES_COMPLETE, param);
411 g_variant_unref(value);
412 g_variant_unref(in_param);
417 int _bt_map_client_list_messages(
419 GDBusMethodInvocation *context,
420 const char* session_id,
422 const char* filter_serialized)
424 BT_DBG("Entered _bt_map_client_list_messages with session id: \"%s\"", session_id);
425 BT_DBG("Entered folder: %s", folder);
426 GDBusConnection *g_conn;
427 GDBusProxy *message_access_proxy;
428 GError *error = NULL;
429 int result = BLUETOOTH_ERROR_NONE;
431 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
433 g_conn = _bt_get_system_gconn();
434 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
436 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
437 &request_id, sizeof(int),
439 g_dbus_method_invocation_return_value(context,
440 g_variant_new("(iv)", result, out_param1));
442 // create message access proxy
443 g_clear_error(&error);
444 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
445 BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1",
448 BT_ERR("Could not create message access proxy: %s\n", error->message);
449 result = BLUETOOTH_ERROR_INTERNAL;
451 if (!message_access_proxy) {
452 BT_ERR("message proxy handle is null\n");
453 result = BLUETOOTH_ERROR_INTERNAL;
455 BT_DBG("message proxy set");
457 GVariant *filter_variant = g_variant_parse(NULL, filter_serialized, NULL, NULL, NULL);
459 GVariant *params = g_variant_new("(s@a{sv})", folder, filter_variant);
460 GVariant *param = g_variant_new("(i)", request_id);
462 g_dbus_proxy_call(message_access_proxy,
463 "ListMessages", params,
464 G_DBUS_CALL_FLAGS_NONE, -1,
466 (GAsyncReadyCallback)__bt_list_messages_cb,
471 if (message_access_proxy)
472 g_object_unref(message_access_proxy);
478 int _bt_map_client_update_inbox(const char* session_id)
483 GDBusConnection *g_conn;
484 GDBusProxy *message_proxy;
485 GVariant *ret = NULL;
487 g_conn = _bt_get_system_gconn();
488 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
490 message_proxy = g_dbus_proxy_new_sync(g_conn,
491 G_DBUS_PROXY_FLAGS_NONE, NULL,
492 BT_OBEX_SERVICE_NAME, session_id,
493 BT_OBEX_MESSAGE_INTERFACE, NULL, &err);
495 retv_if(message_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
497 ret = g_dbus_proxy_call_sync(message_proxy,
498 "UpdateInbox", g_variant_new("()"),
499 G_DBUS_CALL_FLAGS_NONE, -1,
504 BT_ERR("UpdateInbox Error: %s\n", err->message);
508 g_variant_unref(ret);
511 g_object_unref(message_proxy);
515 return BLUETOOTH_ERROR_NONE;
518 void _bt_map_on_transfer_finished(const char *transfer_object_path, const int error)
520 BT_DBG("Entered _bt_map_on_transfer_finished");
521 BT_DBG("Looking for transfer %s id", transfer_object_path);
523 bt_map_callback_data_t *callback_data = NULL;
524 GSList* transfer = NULL;
525 for (transfer = transfer_list; transfer != NULL; transfer = g_slist_next(transfer)) {
526 callback_data = transfer->data;
527 if (NULL == callback_data)
530 if (0 == strcmp(transfer_object_path, callback_data->transfer_path)) {
531 BT_DBG("request id FOUND - triggering event");
533 GVariant *param = g_variant_new("(ii)", error, callback_data->request_id);
536 switch (callback_data->transfer_type) {
537 case BT_MAP_TRANSFER_GET_MESSAGE:
538 event = BLUETOOTH_EVENT_MAP_GET_MESSAGE_COMPLETE;
540 case BT_MAP_TRANSFER_PUSH_MESSAGE:
541 event = BLUETOOTH_EVENT_MAP_PUSH_MESSAGE_COMPLETE;
545 _bt_send_event(BT_MAP_CLIENT_EVENT, event, param);
547 // remove callback data from list
548 transfer_list = g_slist_remove(transfer_list, transfer);
550 //free memory and break loop
551 g_free(callback_data->transfer_path);
552 callback_data->transfer_path = NULL;
553 g_free(callback_data);
560 static void __bt_push_message_cb(GDBusProxy *proxy,
561 GAsyncResult *res, gpointer user_data)
565 GError *error = NULL;
566 GVariant *value, *in_param;
568 char *transfer_object_path = NULL;
569 GVariantIter *iter = NULL;
573 in_param = (GVariant*) user_data;
574 g_variant_get(in_param, "(i)", &request_id);
576 value = g_dbus_proxy_call_finish(proxy, res, &error);
578 BT_ERR("%s", error->message);
579 g_clear_error(&error);
583 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
584 g_variant_unref(value);
587 BT_DBG("transfer object path: [%s]", transfer_object_path);
589 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
590 bt_map_callback_data_t* callback_data = g_malloc0(sizeof(bt_map_callback_data_t));
591 callback_data->transfer_type = BT_MAP_TRANSFER_PUSH_MESSAGE;
592 callback_data->request_id = request_id;
593 callback_data->transfer_path = transfer_object_path;
595 transfer_list = g_slist_append(transfer_list, callback_data);
597 g_variant_unref(value);
598 g_variant_unref(in_param);
603 int _bt_map_client_push_message(
605 GDBusMethodInvocation *context,
606 const char* session_id,
607 const char* source_file,
609 const char* args_serialized)
611 BT_DBG("Entered _bt_map_client_push_message with session id: \"%s\"", session_id);
612 BT_DBG("Entered source_file: %s", source_file);
613 BT_DBG("Entered folder: %s", folder);
615 GDBusConnection *g_conn;
616 GDBusProxy *message_access_proxy;
617 GError *error = NULL;
618 int result = BLUETOOTH_ERROR_NONE;
620 retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
622 // TODO event listeners registration on first call, where should it be unregistered??
623 // _bt_map_client_event_init(); --need to do
625 g_conn = _bt_get_system_gconn();
626 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
628 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
629 &request_id, sizeof(int),
631 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
633 // create message access proxy
634 g_clear_error(&error);
635 message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
636 BT_OBEX_SERVICE_NAME, session_id, BT_OBEX_MESSAGE_INTERFACE,
639 BT_ERR("Could not create message access proxy: %s\n", error->message);
640 result = BLUETOOTH_ERROR_INTERNAL;
642 if (!message_access_proxy) {
643 BT_ERR("message proxy handle is null\n");
644 result = BLUETOOTH_ERROR_INTERNAL;
646 BT_DBG("message proxy set");
648 GVariant *args_variant = g_variant_parse(NULL, args_serialized, NULL, NULL, NULL);
650 GVariant *params = g_variant_new("(ss@a{sv})", source_file, folder, args_variant);
651 GVariant *req_id = g_variant_new("(i)", request_id);
653 g_dbus_proxy_call(message_access_proxy,
654 "PushMessage", params,
655 G_DBUS_CALL_FLAGS_NONE, -1,
656 NULL, (GAsyncReadyCallback)__bt_push_message_cb,
661 g_object_unref(message_access_proxy);
667 static void __bt_get_message_cb(GDBusProxy *proxy,
668 GAsyncResult *res, gpointer user_data)
672 GError *error = NULL;
673 GVariant *value, *in_param;
675 char *transfer_object_path = NULL;
676 GVariantIter *iter = NULL;
680 in_param = (GVariant*) user_data;
681 g_variant_get(in_param, "(i)", &request_id);
683 value = g_dbus_proxy_call_finish(proxy, res, &error);
685 BT_ERR("%s", error->message);
686 g_clear_error(&error);
690 g_variant_get(value, "(oa{sv})", &transfer_object_path, &iter);
691 g_variant_unref(value);
694 BT_DBG("transfer object path: [%s]", transfer_object_path);
696 BT_DBG("Adding request id %d - transfer [%s]", request_id, transfer_object_path);
697 bt_map_callback_data_t* callback_data = g_malloc0(sizeof(bt_map_callback_data_t));
698 callback_data->transfer_type = BT_MAP_TRANSFER_GET_MESSAGE;
699 callback_data->request_id = request_id;
700 callback_data->transfer_path = transfer_object_path;
702 transfer_list = g_slist_append(transfer_list, callback_data);
704 g_variant_unref(value);
705 g_variant_unref(in_param);
710 int _bt_map_client_get_message(
712 GDBusMethodInvocation *context,
713 const char* message_object,
714 const char* target_file,
717 BT_DBG("Entered _bt_map_client_get_message");
719 GDBusConnection *g_conn;
720 GDBusProxy *message_proxy;
721 GError *error = NULL;
722 int result = BLUETOOTH_ERROR_NONE;
724 retv_if(message_object == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
726 // TODO event listeners registration on first call, where should it be unregistered??
727 // _bt_map_client_event_init();
729 g_conn = _bt_get_system_gconn();
730 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
732 GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
733 &request_id, sizeof(int),
735 g_dbus_method_invocation_return_value(context, g_variant_new("(iv)", result, out_param1));
737 // create message proxy
738 g_clear_error(&error);
739 message_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
740 BT_OBEX_SERVICE_NAME, message_object, "org.bluez.obex.Message1",
743 BT_ERR("Could not create message proxy: %s\n", error->message);
744 result = BLUETOOTH_ERROR_INTERNAL;
746 if (!message_proxy) {
747 BT_ERR("message proxy handle is null\n");
748 result = BLUETOOTH_ERROR_INTERNAL;
750 BT_DBG("message proxy set");
751 GVariant *params = g_variant_new("(sb)", target_file, attachment);
752 GVariant *req_id = g_variant_new("(i)", request_id);
754 g_dbus_proxy_call(message_proxy, "Get", params, G_DBUS_CALL_FLAGS_NONE, -1,
755 NULL, (GAsyncReadyCallback)__bt_get_message_cb, (void*)req_id);
759 g_object_unref(message_proxy);