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