From 9b066a83744f1dca4161e263289ada7ba113773b Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Fri, 28 Oct 2016 14:57:49 +0200 Subject: [PATCH] [bluetooth-frwk] Added listFolders implementation with async result [Feature] added implementation for listFolders method [Verification] function checked with sample C program: - listing folder is possible, - options work correctly and maxcount works fine. - user_data is correctly passed to result callback Change-Id: If81066103306cd1bc4199d5bf2a1396c4d11af7f Signed-off-by: Piotr Kosko --- bt-api/bt-common.c | 1 + bt-api/bt-event-handler.c | 59 +++++++++++++++++++++-- bt-api/bt-map-client.c | 29 ++++++++--- bt-api/bt-request-sender.c | 19 ++++++-- bt-service/bt-request-handler.c | 13 ++++- bt-service/bt-service-event-sender.c | 12 +++++ bt-service/bt-service-map-client.c | 77 ++++++++++++++++++++++++++++-- bt-service/include/bt-service-map-client.h | 3 +- include/bluetooth-api.h | 9 +++- include/bt-internal-types.h | 9 ++++ 10 files changed, 208 insertions(+), 23 deletions(-) diff --git a/bt-api/bt-common.c b/bt-api/bt-common.c index d7a9e49..ce0365e 100644 --- a/bt-api/bt-common.c +++ b/bt-api/bt-common.c @@ -126,6 +126,7 @@ bt_user_info_t *_bt_get_user_data(int type) void _bt_common_event_cb(int event, int result, void *param, void *callback, void *user_data) { + BT_DBG("bt_common_event_cb, event: %d", event); bluetooth_event_param_t bt_event = { 0, }; bt_event.event = event; bt_event.result = result; diff --git a/bt-api/bt-event-handler.c b/bt-api/bt-event-handler.c index 4d0d21a..a2f3913 100644 --- a/bt-api/bt-event-handler.c +++ b/bt-api/bt-event-handler.c @@ -1983,6 +1983,7 @@ void __bt_map_client_event_filter(GDBusConnection *connection, GVariant *parameters, gpointer user_data) { + BT_DBG("Entered __bt_map_client_event_filter"); bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; event_info = (bt_event_info_t *)user_data; @@ -2024,7 +2025,7 @@ void __bt_map_client_event_filter(GDBusConnection *connection, bluetooth_device_address_t dev_address = { {0} }; g_variant_get(parameters, "(i&si)", &result, &address, - &request_id); + &request_id); if (__bt_is_request_id_exist(request_id) == FALSE) { BT_ERR("Different request id!"); @@ -2032,18 +2033,68 @@ void __bt_map_client_event_filter(GDBusConnection *connection, } _bt_convert_addr_string_to_type(dev_address.addr, - address); + address); _bt_common_event_cb(BLUETOOTH_EVENT_MAP_DISCONNECTED, result, &dev_address, event_info->cb, event_info->user_data); __bt_remove_push_request_id(request_id); - } else if (strcasecmp(signal_name, BT_MAP_OP_COMPLETE) == 0) { + } else if (strcasecmp(signal_name, BT_MAP_LIST_FOLDERS_COMPLETE) == 0) { + int request_id = 0; + GVariant* folder_list_var = NULL; + + g_variant_get(parameters, "(iiv)", &result, &request_id, &folder_list_var); + if (__bt_is_request_id_exist(request_id) == FALSE) { + BT_ERR("Different request id!"); + return; + } - /* TODO: MAP, see __bt_opp_client_event_filter above */ + GVariantIter* iter; + bt_map_client_folders_s folders_struct = {0,}; + g_variant_get(folder_list_var, "(aa{sv})", &iter); + + folders_struct.size = g_variant_iter_n_children(iter); + folders_struct.names = (char**) malloc(folders_struct.size * sizeof(*(folders_struct.names))); + BT_DBG("g_variant_iter_n_children: %d", folders_struct.size); + GVariantIter* res = NULL; + int i = 0; + while (g_variant_iter_loop(iter, "a{sv}", &res)) { + char* key = NULL; + GVariant* value = NULL; + while (g_variant_iter_loop(res, "{sv}", &key, &value)) { + char* string_value = NULL; + g_variant_get(value, "s", &string_value); + BT_DBG("got folder name: %s", string_value); + folders_struct.names[i] = strdup(string_value); + } + ++i; + } + _bt_common_event_cb(BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, + result, &folders_struct, + event_info->cb, event_info->user_data); + + __bt_remove_push_request_id(request_id); + + // freeing resources + while (--i >= 0) { + free(folders_struct.names[i]); + folders_struct.names[i] = NULL; + } + free(folders_struct.names); + + g_variant_unref(folder_list_var); } + // TODO MAP place for you else 1 + // TODO MAP place for you else 2 + // TODO MAP place for you else 3 + // TODO MAP place for you else 4 + // TODO MAP place for you else 5 + // TODO MAP place for you else 6 + // TODO MAP place for you else 7 + // TODO MAP place for you else 8 + } void __bt_pbap_client_event_filter(GDBusConnection *connection, diff --git a/bt-api/bt-map-client.c b/bt-api/bt-map-client.c index a476881..eb062c9 100644 --- a/bt-api/bt-map-client.c +++ b/bt-api/bt-map-client.c @@ -134,15 +134,32 @@ BT_EXPORT_API int bluetooth_map_client_set_folder( } BT_EXPORT_API int bluetooth_map_client_list_folders( - bt_map_client_session_info_s *session, - GVariant *filter) + bt_map_client_session_info_s *session, + int offset, + int maxcount) { - BT_DBG("bluetooth_map_client_list_folders"); - int result = BLUETOOTH_ERROR_INTERNAL; + BT_DBG("bluetooth_map_list_folders"); + int result = 0; - /* TODO: MAP */ + BT_CHECK_ENABLED(return); + BT_CHECK_PARAMETER(session->session_path, return); - return result; + bt_user_info_t *user_info = _bt_get_user_data(BT_COMMON); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, session->session_path, strlen(session->session_path)+1); + g_array_append_vals(in_param2, &offset, sizeof(offset)); + g_array_append_vals(in_param3, &maxcount, sizeof(maxcount)); + + result = _bt_send_request_async(BT_OBEX_SERVICE, BT_MAP_LIST_FOLDERS, + in_param1, in_param2, in_param3, in_param4, user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; } BT_EXPORT_API int bluetooth_map_client_list_filter_fields( diff --git a/bt-api/bt-request-sender.c b/bt-api/bt-request-sender.c index be6ab8d..6594580 100644 --- a/bt-api/bt-request-sender.c +++ b/bt-api/bt-request-sender.c @@ -254,6 +254,7 @@ static void __send_request_cb(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { + BT_DBG("Entered __send_request_cb"); bluetooth_event_param_t bt_event; bt_req_info_t *cb_data = user_data; int result = BLUETOOTH_ERROR_NONE; @@ -310,17 +311,25 @@ static void __send_request_cb(GDBusProxy *proxy, &bt_event.event, &event_type, &bt_event.param_data); + BT_DBG("service_function [%d]", cb_data->service_function); if (result == BLUETOOTH_ERROR_NONE && out_param1) { if (cb_data->service_function == BT_OPP_PUSH_FILES) { request_id = g_array_index(out_param1, int, 0); BT_DBG("request_id : %d", request_id); _bt_add_push_request_id(request_id); + } else if (cb_data->service_function == BT_MAP_LIST_FOLDERS) { + request_id = g_array_index(out_param1, int, 0); + BT_DBG("request_id : %d", request_id); + _bt_add_push_request_id(request_id); } - /* TODO: MAP service functions: - else if (cb_data->service_function == BT_MAP_XXX) { - - } - */ + // TODO MAP place for your own if 1 + // TODO MAP place for your own if 2 + // TODO MAP place for your own if 3 + // TODO MAP place for your own if 4 + // TODO MAP place for your own if 5 + // TODO MAP place for your own if 6 + // TODO MAP place for your own if 7 + // TODO MAP place for your own if 8 goto done; } diff --git a/bt-service/bt-request-handler.c b/bt-service/bt-request-handler.c index eb92aa5..401d17e 100644 --- a/bt-service/bt-request-handler.c +++ b/bt-service/bt-request-handler.c @@ -2293,10 +2293,19 @@ int __bt_obexd_request(int function_name, case BT_MAP_LIST_FOLDERS: { BT_DBG("BT_MAP_LIST_FOLDERS"); + // TODO MAP add filter handling + GVariant *filter = g_variant_new("()"); - /* TODO: MAP */ + char* session_id = (char *)g_variant_get_data(in_param1); + int offset = 0; + int maxcount = 0; + __bt_service_get_parameters(in_param2, &offset, sizeof(int)); + __bt_service_get_parameters(in_param3, &maxcount, sizeof(int)); - result = BLUETOOTH_ERROR_NOT_SUPPORT; + result = _bt_map_client_list_folders(request_id, context, session_id, offset, maxcount); + if (result == BLUETOOTH_ERROR_NONE) { + BT_DBG("_bt_map_client_list_folders succeed"); + } break; } diff --git a/bt-service/bt-service-event-sender.c b/bt-service/bt-service-event-sender.c index de9b216..cc13bb8 100644 --- a/bt-service/bt-service-event-sender.c +++ b/bt-service/bt-service-event-sender.c @@ -328,6 +328,18 @@ int _bt_send_event(int event_type, int event, GVariant *param) signal = BT_MAP_DISCONNECTED; BT_INFO_C("Disconnected [MAP]"); break; + case BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE: + signal = BT_MAP_LIST_FOLDERS_COMPLETE; + BT_INFO_C("Completed list folders operation[MAP]"); + break; + // TODO MAP place for your own case 1 + // TODO MAP place for your own case 2 + // TODO MAP place for your own case 3 + // TODO MAP place for your own case 4 + // TODO MAP place for your own case 5 + // TODO MAP place for your own case 6 + // TODO MAP place for your own case 7 + // TODO MAP place for your own case 8 case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_CONNECTED: signal = BT_TRANSFER_CONNECTED; break; diff --git a/bt-service/bt-service-map-client.c b/bt-service/bt-service-map-client.c index 3eac5c5..1ecba34 100644 --- a/bt-service/bt-service-map-client.c +++ b/bt-service/bt-service-map-client.c @@ -366,15 +366,84 @@ int _bt_map_client_set_folder(const char* session_id, const char* name) return BLUETOOTH_ERROR_NONE; } -int _bt_map_client_list_folders(const char* session_id, GVariant *filter) +int _bt_map_client_list_folders(int request_id, GDBusMethodInvocation *context, + const char* session_id, int offset, int maxcount) { - BT_DBG("+"); + BT_DBG("Entered _bt_map_list_folders with session id: \"%s\"", session_id); + BT_DBG("Entered offset: %d maxcount: %d", offset, maxcount); + GDBusConnection *g_conn; + GDBusProxy *message_access_proxy; + GError *error = NULL; + int result = BLUETOOTH_ERROR_NONE; - /* TODO: MAP */ + retv_if(session_id == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + g_conn = _bt_gdbus_get_session_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + GVariant *out_param1 = g_variant_new_from_data((const GVariantType *)"ay", + &request_id, sizeof(int), + TRUE, NULL, NULL); + g_dbus_method_invocation_return_value(context, + g_variant_new("(iv)", result, out_param1)); + + // create message access proxy + g_clear_error(&error); + message_access_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_OBEX_SERVICE_NAME, session_id, "org.bluez.obex.MessageAccess1", + NULL, &error); + if (error != NULL) { + BT_ERR("Could not create message access proxy: %s\n", error->message); + result = BLUETOOTH_ERROR_INTERNAL; + } else { + if (!message_access_proxy) { + BT_ERR("message proxy handle is null\n"); + result = BLUETOOTH_ERROR_INTERNAL; + } else { + BT_DBG("message proxy set"); + + GVariantBuilder* b = g_variant_builder_new (G_VARIANT_TYPE_ARRAY); + + if (offset >= 0) { + g_variant_builder_add(b, "{sv}", "Offset", g_variant_new_uint16(offset)); + } + if (maxcount >= 0) { + g_variant_builder_add(b, "{sv}", "MaxCount", g_variant_new_uint16(maxcount)); + } + GVariant *args = g_variant_builder_end(b); + GVariant *params = g_variant_new("(@a{sv})", args); + g_variant_builder_unref (b); + + int* request_id_p = malloc(sizeof(*request_id_p)); + *request_id_p = request_id; + + GVariant *folder_list_var = g_dbus_proxy_call_sync(message_access_proxy, + "ListFolders", params, G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + if (error != NULL) { + BT_ERR("Could not ListFolders: %s\n", error->message); + // TODO return correct error + result = BLUETOOTH_ERROR_INTERNAL; + } else { + if (!folder_list_var) { + BT_ERR("returned ListFolders is null\n"); + result = BLUETOOTH_ERROR_INTERNAL; + } else { + BT_DBG("ListFolders succeed\n"); + + GVariant *param = g_variant_new("(iiv)", result, request_id, folder_list_var); + BT_DBG("RequestID[%d]", request_id); + result = _bt_send_event(BT_MAP_CLIENT_EVENT, + BLUETOOTH_EVENT_MAP_LIST_FOLDERS_COMPLETE, param); + } + } + } + } + g_object_unref(message_access_proxy); BT_DBG("-"); - return BLUETOOTH_ERROR_NONE; + return result; } int _bt_map_client_list_filter_fields(const char* session_id) diff --git a/bt-service/include/bt-service-map-client.h b/bt-service/include/bt-service-map-client.h index 4f6e133..42eb8d2 100644 --- a/bt-service/include/bt-service-map-client.h +++ b/bt-service/include/bt-service-map-client.h @@ -64,7 +64,8 @@ typedef struct { int _bt_create_session_sync(const char* address, char** session_id); int _bt_destroy_session_sync(const char* session_id); int _bt_map_client_set_folder(const char* session_id, const char* name); -int _bt_map_client_list_folders(const char* session_id, GVariant *filter); +int _bt_map_client_list_folders(int request_id, GDBusMethodInvocation *context, + const char* session_id, int offset, int maxcount); int _bt_map_client_list_filter_fields(const char* session_id); int _bt_map_client_list_messages( const char* session_id, diff --git a/include/bluetooth-api.h b/include/bluetooth-api.h index e7a6951..c81f2b5 100644 --- a/include/bluetooth-api.h +++ b/include/bluetooth-api.h @@ -1796,6 +1796,12 @@ typedef struct { char* remote_address; } bt_map_client_session_info_s; +typedef struct { + char **names; // holding %size null-terminated folder names + int size; +} bt_map_client_folders_s; + + /** * Callback pointer type */ @@ -4859,7 +4865,8 @@ int bluetooth_map_client_set_folder( int bluetooth_map_client_list_folders( bt_map_client_session_info_s *session, - GVariant *filter + int offset, + int maxcount ); int bluetooth_map_client_list_filter_fields( diff --git a/include/bt-internal-types.h b/include/bt-internal-types.h index d9eb63a..0b69dcc 100644 --- a/include/bt-internal-types.h +++ b/include/bt-internal-types.h @@ -501,6 +501,15 @@ typedef struct { #define BT_OPP_DISCONNECTED "OppDisconnected" #define BT_MAP_CONNECTED "MapConnected" #define BT_MAP_DISCONNECTED "MapDisconnected" +#define BT_MAP_LIST_FOLDERS_COMPLETE "ListFoldersComplete" +// TODO MAP place for your define 1 +// TODO MAP place for your define 2 +// TODO MAP place for your define 3 +// TODO MAP place for your define 4 +// TODO MAP place for your define 5 +// TODO MAP place for your define 6 +// TODO MAP place for your define 7 +// TODO MAP place for your define 8 #define BT_MAP_OP_COMPLETE "Complete" #define BT_TRANSFER_CONNECTED "TransferConnected" #define BT_TRANSFER_DISCONNECTED "TransferDisonnected" -- 2.7.4