Linux-Bluetooth Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v2 1/6] obexd: Add initial support for MAP conversations
@ 2020-02-11  6:36 Ajay Kishore
  2020-02-11  6:36 ` [PATCH v2 2/6] obexd: Add parsers for conversation filters Ajay Kishore
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Ajay Kishore @ 2020-02-11  6:36 UTC (permalink / raw)
  To: linux-bluetooth

Changes made to add a new method for MAP conversation listing i.e
"ListConversations" to handle conversation listing object
"x-bt/MAP-convo-listing".
---
 obexd/client/map.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index 550c5af..adf62d9 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -1560,6 +1560,69 @@ static DBusMessage *map_list_messages(DBusConnection *connection,
 	return get_message_listing(map, message, folder, apparam);
 }
 
+static GObexApparam *parse_conversation_filters(GObexApparam *apparam,
+							DBusMessageIter *iter)
+{
+	DBusMessageIter array;
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
+		DBG("Not of type array");
+		return NULL;
+	}
+
+	dbus_message_iter_recurse(iter, &array);
+
+	while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
+		const char *key;
+		DBusMessageIter value, entry;
+
+		dbus_message_iter_recurse(&array, &entry);
+		dbus_message_iter_get_basic(&entry, &key);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &value);
+
+		/* TODO: Parse conversation filters */
+
+		dbus_message_iter_next(&array);
+	}
+	return apparam;
+}
+
+static DBusMessage *map_list_conversations(DBusConnection *connection,
+						DBusMessage *message,
+						void *user_data)
+{
+	struct map_data *map = user_data;
+	const char *folder;
+	GObexApparam *apparam;
+	DBusMessageIter args;
+
+	dbus_message_iter_init(message, &args);
+
+	if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING)
+		return g_dbus_create_error(message,
+			ERROR_INTERFACE ".InvalidArguments", NULL);
+
+	dbus_message_iter_get_basic(&args, &folder);
+
+	apparam = g_obex_apparam_set_uint16(NULL, MAP_AP_MAXLISTCOUNT,
+							DEFAULT_COUNT);
+	apparam = g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET,
+							DEFAULT_OFFSET);
+
+	dbus_message_iter_next(&args);
+
+	if (parse_conversation_filters(apparam, &args) == NULL) {
+		g_obex_apparam_free(apparam);
+		return g_dbus_create_error(message,
+			ERROR_INTERFACE ".InvalidArguments", NULL);
+	}
+
+	/*TODO: Return conversation listing */
+	return NULL;
+}
+
 static char **get_filter_strs(uint64_t filter, int *size)
 {
 	char **list, **item;
@@ -1817,6 +1880,10 @@ static const GDBusMethodTable map_methods[] = {
 			GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }),
 			GDBUS_ARGS({ "messages", "a{oa{sv}}" }),
 			map_list_messages) },
+	{ GDBUS_ASYNC_METHOD("ListConversations",
+			GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }),
+			GDBUS_ARGS({ "conversations", "a{oa{sv}}" }),
+			map_list_conversations) },
 	{ GDBUS_METHOD("ListFilterFields",
 			NULL,
 			GDBUS_ARGS({ "fields", "as" }),
-- 
2.7.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 2/6] obexd: Add parsers for conversation filters
  2020-02-11  6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore
@ 2020-02-11  6:36 ` Ajay Kishore
  2020-02-11  6:36 ` [PATCH v2 3/6] obexd: Get conversation listings Ajay Kishore
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Ajay Kishore @ 2020-02-11  6:36 UTC (permalink / raw)
  To: linux-bluetooth

Changes made to add a new method to parse the map conversation filters.
Filters LastActivityBegin and LastActivityEnd is used to filter the
conversations that are returned in the Conversation-Listing object by
LastActivity.
---
 obexd/client/map.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 obexd/src/map_ap.h |  3 +++
 2 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index adf62d9..6e84a73 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -1369,6 +1369,21 @@ static GObexApparam *parse_filter_type(GObexApparam *apparam,
 									types);
 }
 
+static GObexApparam *parse_la_begin(GObexApparam *apparam,
+							DBusMessageIter *iter)
+{
+	const char *string;
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
+		return NULL;
+
+	dbus_message_iter_get_basic(iter, &string);
+
+	return g_obex_apparam_set_string(apparam,
+					MAP_AP_FILTERLASTACTIVITYBEGIN,
+					string);
+}
+
 static GObexApparam *parse_period_begin(GObexApparam *apparam,
 							DBusMessageIter *iter)
 {
@@ -1397,6 +1412,20 @@ static GObexApparam *parse_period_end(GObexApparam *apparam,
 								string);
 }
 
+static GObexApparam *parse_la_end(GObexApparam *apparam,
+						DBusMessageIter *iter)
+{
+	const char *string;
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
+		return NULL;
+
+	dbus_message_iter_get_basic(iter, &string);
+
+	return g_obex_apparam_set_string(apparam, MAP_AP_FILTERLASTACTIVITYEND,
+								string);
+}
+
 static GObexApparam *parse_filter_read(GObexApparam *apparam,
 							DBusMessageIter *iter)
 {
@@ -1560,6 +1589,19 @@ static DBusMessage *map_list_messages(DBusConnection *connection,
 	return get_message_listing(map, message, folder, apparam);
 }
 
+static GObexApparam *parse_filter_conv_id(GObexApparam *apparam,
+							DBusMessageIter *iter)
+{
+	guint8 id;
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BYTE)
+		return NULL;
+
+	dbus_message_iter_get_basic(iter, &id);
+
+	return g_obex_apparam_set_uint8(apparam, MAP_AP_CONVERSATIONID, id);
+}
+
 static GObexApparam *parse_conversation_filters(GObexApparam *apparam,
 							DBusMessageIter *iter)
 {
@@ -1582,8 +1624,28 @@ static GObexApparam *parse_conversation_filters(GObexApparam *apparam,
 		dbus_message_iter_next(&entry);
 		dbus_message_iter_recurse(&entry, &value);
 
-		/* TODO: Parse conversation filters */
-
+		if (strcasecmp(key, "Offset") == 0) {
+			if (parse_offset(apparam, &value) == NULL)
+				return NULL;
+		} else if (strcasecmp(key, "MaxCount") == 0) {
+			if (parse_max_count(apparam, &value) == NULL)
+				return NULL;
+		} else if (strcasecmp(key, "LastActivityBegin") == 0) {
+			if (parse_la_begin(apparam, &value) == NULL)
+				return NULL;
+		} else if (strcasecmp(key, "FilterLastActivityEnd") == 0) {
+			if (parse_la_end(apparam, &value) == NULL)
+				return NULL;
+		} else if (strcasecmp(key, "Read") == 0) {
+			if (parse_filter_read(apparam, &value) == NULL)
+				return NULL;
+		} else if (strcasecmp(key, "Recipient") == 0) {
+			if (parse_filter_recipient(apparam, &value) == NULL)
+				return NULL;
+		} else if (strcasecmp(key, "ConversationId") == 0) {
+			if (parse_filter_conv_id(apparam, &value) == NULL)
+				return NULL;
+		}
 		dbus_message_iter_next(&array);
 	}
 	return apparam;
diff --git a/obexd/src/map_ap.h b/obexd/src/map_ap.h
index da108fe..3773859 100644
--- a/obexd/src/map_ap.h
+++ b/obexd/src/map_ap.h
@@ -31,6 +31,8 @@ enum map_ap_tag {
 	MAP_AP_FILTERREADSTATUS		= 0x06,		/* uint8_t	*/
 	MAP_AP_FILTERRECIPIENT		= 0x07,		/* char *	*/
 	MAP_AP_FILTERORIGINATOR		= 0x08,		/* char *	*/
+	MAP_AP_FILTERLASTACTIVITYBEGIN	= 0x08,		/* char *       */
+	MAP_AP_FILTERLASTACTIVITYEND	= 0x09,		/* char *       */
 	MAP_AP_FILTERPRIORITY		= 0x09,		/* uint8_t	*/
 	MAP_AP_ATTACHMENT		= 0x0A,		/* uint8_t	*/
 	MAP_AP_TRANSPARENT		= 0x0B,		/* uint8_t	*/
@@ -48,4 +50,5 @@ enum map_ap_tag {
 	MAP_AP_STATUSINDICATOR		= 0x17,		/* uint8_t	*/
 	MAP_AP_STATUSVALUE		= 0x18,		/* uint8_t	*/
 	MAP_AP_MSETIME			= 0x19,		/* char *	*/
+	MAP_AP_CONVERSATIONID		= 0x1C,		/* uint32_t     */
 };
-- 
2.7.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 3/6] obexd: Get conversation listings
  2020-02-11  6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore
  2020-02-11  6:36 ` [PATCH v2 2/6] obexd: Add parsers for conversation filters Ajay Kishore
@ 2020-02-11  6:36 ` Ajay Kishore
  2020-02-11  6:36 ` [PATCH v2 5/6] obexd: Handle MAP Event Report v1.1 and v1.2 Ajay Kishore
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Ajay Kishore @ 2020-02-11  6:36 UTC (permalink / raw)
  To: linux-bluetooth

Changes made to build get conversation listing command and its
respective callback function to handle response for conversation
listing.
---
 obexd/client/map.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 96 insertions(+), 2 deletions(-)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index 6e84a73..4f3d6c5 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -1221,6 +1221,64 @@ clean:
 	pending_request_free(request);
 }
 
+static void conversation_listing_cb(struct obc_session *session,
+						struct obc_transfer *transfer,
+						GError *err, void *user_data)
+{
+	struct pending_request *request = user_data;
+	struct map_parser *parser;
+	GMarkupParseContext *ctxt;
+	DBusMessage *reply;
+	DBusMessageIter iter, array;
+	char *contents;
+	size_t size;
+	int perr;
+
+	if (err != NULL) {
+		reply = g_dbus_create_error(request->msg,
+						ERROR_INTERFACE ".Failed",
+						"%s", err->message);
+		goto done;
+	}
+
+	perr = obc_transfer_get_contents(transfer, &contents, &size);
+	if (perr < 0) {
+		reply = g_dbus_create_error(request->msg,
+						ERROR_INTERFACE ".Failed",
+						"Error reading contents: %s",
+						strerror(-perr));
+		goto done;
+	}
+
+	reply = dbus_message_new_method_return(request->msg);
+	if (reply == NULL) {
+		g_free(contents);
+		goto clean;
+	}
+
+	dbus_message_iter_init_append(reply, &iter);
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_OBJECT_PATH_AS_STRING
+					DBUS_TYPE_ARRAY_AS_STRING
+					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					DBUS_TYPE_STRING_AS_STRING
+					DBUS_TYPE_VARIANT_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					&array);
+
+	dbus_message_iter_close_container(&iter, &array);
+	g_free(contents);
+
+done:
+	if (convo_element_end)
+		if (g_dbus_send_message(conn, reply))
+			convo_element_end = FALSE;
+clean:
+	pending_request_free(request);
+}
+
 static char *get_absolute_folder(struct map_data *map, const char *subfolder)
 {
 	const char *root = obc_session_get_folder(map->session);
@@ -1269,6 +1327,43 @@ fail:
 	return reply;
 }
 
+static DBusMessage *get_conversations_listing(struct map_data *map,
+							DBusMessage *message,
+							const char *folder,
+							GObexApparam *apparam)
+{
+	struct pending_request *request;
+	struct obc_transfer *transfer;
+	GError *err = NULL;
+	DBusMessage *reply;
+
+	transfer = obc_transfer_get("x-bt/MAP-convo-listing", folder, NULL,
+									&err);
+
+	if (transfer == NULL) {
+		g_obex_apparam_free(apparam);
+		goto fail;
+	}
+	obc_transfer_set_apparam(transfer, apparam);
+
+	request = pending_request_new(map, message);
+	request->folder = get_absolute_folder(map, folder);
+
+	if (!obc_session_queue(map->session, transfer,
+				conversation_listing_cb, request, &err)) {
+		pending_request_free(request);
+		goto fail;
+	}
+
+	return NULL;
+
+fail:
+	reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
+								err->message);
+	g_error_free(err);
+	return reply;
+}
+
 static GObexApparam *parse_subject_length(GObexApparam *apparam,
 							DBusMessageIter *iter)
 {
@@ -1681,8 +1776,7 @@ static DBusMessage *map_list_conversations(DBusConnection *connection,
 			ERROR_INTERFACE ".InvalidArguments", NULL);
 	}
 
-	/*TODO: Return conversation listing */
-	return NULL;
+	return get_conversations_listing(map, message, folder, apparam);
 }
 
 static char **get_filter_strs(uint64_t filter, int *size)
-- 
2.7.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 5/6] obexd: Handle MAP Event Report v1.1 and v1.2
  2020-02-11  6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore
  2020-02-11  6:36 ` [PATCH v2 2/6] obexd: Add parsers for conversation filters Ajay Kishore
  2020-02-11  6:36 ` [PATCH v2 3/6] obexd: Get conversation listings Ajay Kishore
@ 2020-02-11  6:36 ` Ajay Kishore
  2020-02-11  6:36 ` [PATCH v3 4/6] obexd: Add parser for conversation element Ajay Kishore
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Ajay Kishore @ 2020-02-11  6:36 UTC (permalink / raw)
  To: linux-bluetooth

Changes made to add handler function for the corresponding
events mentioned in extended event reports 1.1 and 1.2.
---
 obexd/client/map-event.h |  8 +++++++-
 obexd/client/map.c       | 19 +++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/obexd/client/map-event.h b/obexd/client/map-event.h
index 5414b26..c41bb67 100644
--- a/obexd/client/map-event.h
+++ b/obexd/client/map-event.h
@@ -32,7 +32,13 @@ enum map_event_type {
 	MAP_ET_MEMORY_FULL,
 	MAP_ET_MEMORY_AVAILABLE,
 	MAP_ET_MESSAGE_DELETED,
-	MAP_ET_MESSAGE_SHIFT
+	MAP_ET_MESSAGE_SHIFT,
+	MAP_ET_READ_STATUS_CHANGED,
+	MAP_ET_MESSAGE_REMOVED,
+	MAP_ET_MESSAGE_EXTENDED_DATA_CHANGED,
+	MAP_ET_PARTICIPANT_PRESENCE_CHANGED,
+	MAP_ET_PARTICIPANT_CHAT_STATE_CHANGED,
+	MAP_ET_CONVERSATION_CHANGED
 };
 
 struct map_event {
diff --git a/obexd/client/map.c b/obexd/client/map.c
index 8a059ab..3bcb4a3 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -2550,6 +2550,12 @@ static void map_handle_folder_changed(struct map_data *map,
 								"Folder");
 }
 
+static void map_handle_remove_message(struct map_data *map,
+						struct map_event *event)
+{
+	g_hash_table_remove(map->messages, &event->handle);
+}
+
 static void map_handle_notification(struct map_event *event, void *user_data)
 {
 	struct map_data *map = user_data;
@@ -2582,6 +2588,19 @@ static void map_handle_notification(struct map_event *event, void *user_data)
 	case MAP_ET_MESSAGE_SHIFT:
 		map_handle_folder_changed(map, event, event->folder);
 		break;
+	case MAP_ET_READ_STATUS_CHANGED:
+		map_handle_status_changed(map, event, "read");
+		break;
+	case MAP_ET_MESSAGE_REMOVED:
+		map_handle_remove_message(map, event);
+		break;
+	case MAP_ET_MESSAGE_EXTENDED_DATA_CHANGED:
+		map_handle_status_changed(map, event,
+					"message-extended-data-changed");
+		break;
+	case MAP_ET_PARTICIPANT_PRESENCE_CHANGED:
+	case MAP_ET_PARTICIPANT_CHAT_STATE_CHANGED:
+	case MAP_ET_CONVERSATION_CHANGED:
 	case MAP_ET_MEMORY_FULL:
 	case MAP_ET_MEMORY_AVAILABLE:
 	default:
-- 
2.7.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 4/6] obexd: Add parser for conversation element
  2020-02-11  6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore
                   ` (2 preceding siblings ...)
  2020-02-11  6:36 ` [PATCH v2 5/6] obexd: Handle MAP Event Report v1.1 and v1.2 Ajay Kishore
@ 2020-02-11  6:36 ` Ajay Kishore
  2020-02-11  6:36 ` [PATCH v3 6/6] doc/obex-api: Update documentation Ajay Kishore
  2020-02-11 19:27 ` [PATCH v2 1/6] obexd: Add initial support for MAP conversations Luiz Augusto von Dentz
  5 siblings, 0 replies; 7+ messages in thread
From: Ajay Kishore @ 2020-02-11  6:36 UTC (permalink / raw)
  To: linux-bluetooth

Changes made to define convo parser function to iterate through
all supported conversation elements and parse their values.
---
 obexd/client/map.c | 428 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 obexd/src/map_ap.h |  40 ++---
 2 files changed, 447 insertions(+), 21 deletions(-)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index 4f3d6c5..8a059ab 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -138,12 +138,35 @@ struct map_msg {
 	GDBusPendingPropertySet pending;
 };
 
+struct map_convo {
+	struct map_data *data;
+	char *path;
+	uint64_t id;
+	char *convo_name;
+	char *convo_last_activity;
+	char *read_status;
+	char *summary;
+	char *uci;
+	char *display_name;
+	uint8_t chat_state;
+	char *last_activity;
+	char *x_bt_uid;
+	char *name;
+	uint8_t presence_availability;
+	char *presence_text;
+	int8_t priority;
+	char *folder;
+};
+
 struct map_parser {
 	struct pending_request *request;
 	DBusMessageIter *iter;
 };
 
 static DBusConnection *conn = NULL;
+DBusMessageIter convo_entry, *convo_iter;
+struct map_convo *conversation;
+static bool convo_element_end = FALSE;
 
 static struct pending_request *pending_request_new(struct map_data *map,
 							DBusMessage *message)
@@ -836,6 +859,8 @@ static void parse_type(struct map_msg *msg, const char *value)
 		type = "email";
 	else if (strcasecmp(value, "MMS") == 0)
 		type = "mms";
+	else if (strcasecmp(value, "IM") == 0)
+		type = "IM";
 
 	if (g_strcmp0(msg->type, type) == 0)
 		return;
@@ -1073,6 +1098,285 @@ static void parse_protected(struct map_msg *msg, const char *value)
 						MAP_MSG_INTERFACE, "Protected");
 }
 
+static void map_convo_free(void *data)
+{
+	struct map_convo *convo = data;
+
+	g_free(convo->path);
+	g_free(convo->convo_name);
+	g_free(convo->folder);
+	g_free(convo->convo_last_activity);
+	g_free(convo->read_status);
+	g_free(convo->summary);
+	g_free(convo->uci);
+	g_free(convo->display_name);
+	g_free(convo->last_activity);
+	g_free(convo->x_bt_uid);
+	g_free(convo->name);
+	g_free(convo->presence_text);
+	g_free(convo);
+}
+
+static gboolean convo_name_exists(const GDBusPropertyTable *property,
+								void *data)
+{
+	struct map_convo *convo = data;
+
+	return convo->convo_name != NULL;
+}
+
+static gboolean get_convo_name(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_convo *convo = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+						&convo->convo_name);
+
+	return TRUE;
+}
+
+static gboolean summary_exists(const GDBusPropertyTable *property,
+								void *data)
+{
+	struct map_convo *convo = data;
+
+	return convo->summary != NULL;
+}
+
+static gboolean get_summary(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_convo *convo = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+							&convo->summary);
+
+	return TRUE;
+}
+
+static gboolean uci_exists(const GDBusPropertyTable *property, void *data)
+{
+	struct map_convo *convo = data;
+
+	return convo->uci != NULL;
+}
+
+static gboolean get_uci(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_convo *convo = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+							&convo->uci);
+
+	return TRUE;
+}
+
+static gboolean display_name_exists(const GDBusPropertyTable *property,
+								void *data)
+{
+	struct map_convo *convo = data;
+
+	return convo->display_name != NULL;
+}
+
+static gboolean get_display_name(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_convo *convo = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+						&convo->display_name);
+
+	return TRUE;
+}
+
+static gboolean x_bt_uid_exists(const GDBusPropertyTable *property, void *data)
+{
+	struct map_convo *convo = data;
+
+	return convo->x_bt_uid != NULL;
+}
+
+static gboolean get_x_bt_uid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct map_convo *convo = data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64,
+							&convo->x_bt_uid);
+
+	return TRUE;
+}
+
+static const GDBusPropertyTable map_convo_properties[] = {
+	{ "ConvoName", "s", get_convo_name, NULL, convo_name_exists },
+	{ "Summary", "s", get_summary, NULL, summary_exists },
+	{ "Uci", "s", get_uci, NULL, uci_exists },
+	{ "DisplayName", "s", get_display_name, NULL, display_name_exists },
+	{ "XBtUid", "s", get_x_bt_uid, NULL, x_bt_uid_exists},
+	{ }
+};
+
+static void parse_convo_name(struct map_convo *convo, const char *value)
+{
+	if (g_strcmp0(convo->convo_name, value) == 0)
+		return;
+	g_free(convo->convo_name);
+	convo->convo_name = g_strdup(value);
+
+	g_dbus_emit_property_changed(conn, convo->path,
+				MAP_MSG_INTERFACE, "ConvoName");
+}
+
+static void parse_convo_last_activity(struct map_convo *convo,
+							const char *value)
+{
+	if (g_strcmp0(convo->convo_last_activity, value) == 0)
+		return;
+
+	g_free(convo->convo_last_activity);
+	convo->convo_last_activity = g_strdup(value);
+
+	g_dbus_emit_property_changed(conn, convo->path,
+				MAP_MSG_INTERFACE, "ConvoLastActivity");
+}
+
+static void parse_read_status(struct map_convo *convo, const char *value)
+{
+	if (g_strcmp0(convo->read_status, value) == 0)
+		return;
+
+	g_free(convo->read_status);
+	convo->read_status = g_strdup(value);
+
+	g_dbus_emit_property_changed(conn, convo->path,
+				MAP_MSG_INTERFACE, "ReadStatus");
+}
+
+static void parse_summary(struct map_convo *convo, const char *value)
+{
+	if (g_strcmp0(convo->summary, value) == 0)
+		return;
+
+	g_free(convo->summary);
+	convo->summary = g_strdup(value);
+
+	g_dbus_emit_property_changed(conn, convo->path,
+					MAP_MSG_INTERFACE, "Summary");
+}
+
+static void parse_uci(struct map_convo *convo, const char *value)
+{
+	if (g_strcmp0(convo->uci, value) == 0)
+		return;
+
+	g_free(convo->uci);
+	convo->uci = g_strdup(value);
+
+	g_dbus_emit_property_changed(conn, convo->path,
+					MAP_MSG_INTERFACE, "Uci");
+}
+
+static void parse_display_name(struct map_convo *convo, const char *value)
+{
+	if (g_strcmp0(convo->display_name, value) == 0)
+		return;
+
+	g_free(convo->display_name);
+	convo->display_name = g_strdup(value);
+
+	g_dbus_emit_property_changed(conn, convo->path,
+					MAP_MSG_INTERFACE, "DisplayName");
+}
+
+static void parse_chat_state(struct map_convo *convo, const char *value)
+{
+	uint8_t chat_state = g_ascii_strtoll(value, NULL, 10);
+
+	if (convo->chat_state == chat_state)
+		return;
+
+	convo->chat_state = chat_state;
+
+	g_dbus_emit_property_changed(conn, convo->path,
+					MAP_MSG_INTERFACE, "ChatState");
+}
+
+static void parse_last_activity(struct map_convo *convo, const char *value)
+{
+	if (g_strcmp0(convo->last_activity, value) == 0)
+		return;
+
+	g_free(convo->last_activity);
+	convo->last_activity = g_strdup(value);
+
+	g_dbus_emit_property_changed(conn, convo->path,
+					MAP_MSG_INTERFACE, "LastActivity");
+}
+
+static void parse_x_bt_uid(struct map_convo *convo, const char *value)
+{
+	if (g_strcmp0(convo->x_bt_uid, value) == 0)
+		return;
+
+	g_free(convo->x_bt_uid);
+	convo->x_bt_uid = g_strdup(value);
+	g_dbus_emit_property_changed(conn, convo->path,
+					MAP_MSG_INTERFACE, "X_BT_UID");
+}
+
+static void parse_name(struct map_convo *convo, const char *value)
+{
+	if (g_strcmp0(convo->name, value) == 0)
+		return;
+
+	g_free(convo->name);
+	convo->name = g_strdup(value);
+
+	g_dbus_emit_property_changed(conn, convo->path,
+					MAP_MSG_INTERFACE, "Name");
+}
+
+static void parse_presence_availability(struct map_convo *convo,
+							const char *value)
+{
+	uint8_t presence_availability = g_ascii_strtoll(value, NULL, 10);
+
+	if (convo->presence_availability == presence_availability)
+		return;
+
+	convo->presence_availability = presence_availability;
+	g_dbus_emit_property_changed(conn, convo->path,
+					MAP_MSG_INTERFACE,
+					"PresenceAvailability");
+}
+
+static void parse_presence_text(struct map_convo *convo, const char *value)
+{
+	if (g_strcmp0(convo->presence_text, value) == 0)
+		return;
+
+	g_free(convo->presence_text);
+	convo->presence_text = g_strdup(value);
+
+	g_dbus_emit_property_changed(conn, convo->path,
+					MAP_MSG_INTERFACE, "PresenceText");
+}
+
+static void parse_convo_priority(struct map_convo *convo, const char *value)
+{
+	int8_t priority = g_ascii_strtoll(value, NULL, 10);
+
+	if (convo->priority == priority)
+		return;
+
+	convo->priority = priority;
+	g_dbus_emit_property_changed(conn, convo->path,
+				MAP_MSG_INTERFACE, "Priority");
+}
+
 static struct map_msg_parser {
 	const char *name;
 	void (*func) (struct map_msg *msg, const char *value);
@@ -1096,6 +1400,55 @@ static struct map_msg_parser {
 		{ }
 };
 
+static struct map_convo_parser {
+	const char *name;
+	void (*func)(struct map_convo *convo, const char *value);
+} convo_parsers[] = {
+		{ "name", parse_convo_name },
+		{ "last_activity", parse_convo_last_activity },
+		{ "read_status", parse_read_status },
+		{ "summary", parse_summary },
+		{ "x_bt_uci", parse_uci },
+		{ "display_name", parse_display_name },
+		{ "chat_state", parse_chat_state },
+		{ "last_activity", parse_last_activity },
+		{ "x_bt_uid", parse_x_bt_uid },
+		{ "name", parse_name },
+		{ "presence_availability", parse_presence_availability },
+		{ "presence_text", parse_presence_text },
+		{ "priority", parse_convo_priority },
+		{ }
+};
+
+static struct map_convo *map_convo_create(struct map_data *data,
+						uint64_t id,
+						const char *folder,
+						const char *type)
+{
+	struct map_convo *convo;
+
+	convo = g_new0(struct map_convo, 1);
+	convo->data = data;
+	convo->id = id;
+
+	convo->path = g_strdup_printf("%s/message%" PRIu64,
+					obc_session_get_path(data->session),
+					convo->id);
+
+	convo->folder = g_strdup(folder);
+
+	if (!g_dbus_register_interface(conn, convo->path, MAP_MSG_INTERFACE,
+						map_msg_methods, NULL,
+						map_convo_properties,
+						convo, map_convo_free)) {
+		map_convo_free(convo);
+		return NULL;
+	}
+	g_hash_table_insert(data->messages, &convo->id, convo);
+
+	return convo;
+}
+
 static void msg_element(GMarkupParseContext *ctxt, const char *element,
 				const char **names, const char **values,
 				gpointer user_data, GError **gerr)
@@ -1149,6 +1502,73 @@ static void msg_element(GMarkupParseContext *ctxt, const char *element,
 	dbus_message_iter_close_container(iter, &entry);
 }
 
+static void start_convo_element(GMarkupParseContext *ctxt, const char *element,
+				const char **names, const char **values,
+				gpointer user_data, GError **gerr)
+{
+	struct map_parser *parser = user_data;
+	struct map_data *data = parser->request->map;
+	uint32_t id = 0;
+	const char *key;
+	int i;
+	DBusMessageIter *iter = parser->iter;
+
+	for (i = 0, key = names[i]; key; key = names[++i]) {
+		if (strcasecmp(key, "id") == 0) {
+			id = strtoull(values[i], NULL, 32);
+			break;
+		}
+	}
+
+	if (id == 0)
+		return;
+
+	conversation = g_hash_table_lookup(data->messages, &id);
+	if (conversation == NULL) {
+		conversation = map_convo_create(data, id,
+					parser->request->folder, NULL);
+		if (conversation == NULL)
+			return;
+	}
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL,
+								&convo_entry);
+	dbus_message_iter_append_basic(&convo_entry, DBUS_TYPE_OBJECT_PATH,
+							&conversation->path);
+
+	for (i = 0, key = names[i]; key; key = names[++i]) {
+		struct map_convo_parser *parser;
+
+		for (parser = convo_parsers; parser && parser->name; parser++) {
+			if (strcasecmp(key, parser->name) == 0) {
+				if (values[i]) {
+					parser->func(conversation, values[i]);
+					break;
+				}
+			}
+		}
+	}
+
+	g_dbus_get_properties(conn, conversation->path, MAP_MSG_INTERFACE,
+								&convo_entry);
+	dbus_message_iter_close_container(iter, &convo_entry);
+}
+
+static void end_convo_element(GMarkupParseContext *ctxt, const char *element,
+					gpointer user_data, GError **gerr)
+{
+	if (strcasecmp("MAP-convo-listing", element) == 0)
+		convo_element_end = TRUE;
+}
+
+static const GMarkupParser convo_parser = {
+	start_convo_element,
+	end_convo_element,
+	NULL,
+	NULL,
+	NULL
+};
+
 static const GMarkupParser msg_parser = {
 	msg_element,
 	NULL,
@@ -1267,9 +1687,15 @@ static void conversation_listing_cb(struct obc_session *session,
 					DBUS_DICT_ENTRY_END_CHAR_AS_STRING
 					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
 					&array);
-
+	parser = g_new(struct map_parser, 1);
+	parser->request = request;
+	parser->iter = &array;
+	ctxt = g_markup_parse_context_new(&convo_parser, 0, parser, NULL);
+	g_markup_parse_context_parse(ctxt, contents, size, NULL);
+	g_markup_parse_context_free(ctxt);
 	dbus_message_iter_close_container(&iter, &array);
 	g_free(contents);
+	g_free(parser);
 
 done:
 	if (convo_element_end)
diff --git a/obexd/src/map_ap.h b/obexd/src/map_ap.h
index 3773859..d6577fd 100644
--- a/obexd/src/map_ap.h
+++ b/obexd/src/map_ap.h
@@ -30,25 +30,25 @@ enum map_ap_tag {
 	MAP_AP_FILTERPERIODEND		= 0x05,		/* char *	*/
 	MAP_AP_FILTERREADSTATUS		= 0x06,		/* uint8_t	*/
 	MAP_AP_FILTERRECIPIENT		= 0x07,		/* char *	*/
-	MAP_AP_FILTERORIGINATOR		= 0x08,		/* char *	*/
-	MAP_AP_FILTERLASTACTIVITYBEGIN	= 0x08,		/* char *       */
-	MAP_AP_FILTERLASTACTIVITYEND	= 0x09,		/* char *       */
-	MAP_AP_FILTERPRIORITY		= 0x09,		/* uint8_t	*/
-	MAP_AP_ATTACHMENT		= 0x0A,		/* uint8_t	*/
-	MAP_AP_TRANSPARENT		= 0x0B,		/* uint8_t	*/
-	MAP_AP_RETRY			= 0x0C,		/* uint8_t	*/
-	MAP_AP_NEWMESSAGE		= 0x0D,		/* uint8_t	*/
-	MAP_AP_NOTIFICATIONSTATUS	= 0x0E,		/* uint8_t	*/
-	MAP_AP_MASINSTANCEID		= 0x0F,		/* uint8_t	*/
-	MAP_AP_PARAMETERMASK		= 0x10,		/* uint32_t	*/
-	MAP_AP_FOLDERLISTINGSIZE	= 0x11,		/* uint16_t	*/
-	MAP_AP_MESSAGESLISTINGSIZE	= 0x12,		/* uint16_t	*/
-	MAP_AP_SUBJECTLENGTH		= 0x13,		/* uint8_t	*/
-	MAP_AP_CHARSET			= 0x14,		/* uint8_t	*/
-	MAP_AP_FRACTIONREQUEST		= 0x15,		/* uint8_t	*/
-	MAP_AP_FRACTIONDELIVER		= 0x16,		/* uint8_t	*/
-	MAP_AP_STATUSINDICATOR		= 0x17,		/* uint8_t	*/
-	MAP_AP_STATUSVALUE		= 0x18,		/* uint8_t	*/
-	MAP_AP_MSETIME			= 0x19,		/* char *	*/
+	MAP_AP_FILTERLASTACTIVITYBEGIN	= 0x08,         /* char *       */
+	MAP_AP_FILTERLASTACTIVITYEND	= 0x09,         /* char *       */
+	MAP_AP_FILTERORIGINATOR		= 0x0A,		/* char *	*/
+	MAP_AP_FILTERPRIORITY		= 0x0B,		/* uint8_t	*/
+	MAP_AP_ATTACHMENT		= 0x0C,		/* uint8_t	*/
+	MAP_AP_TRANSPARENT		= 0x0D,		/* uint8_t	*/
+	MAP_AP_RETRY			= 0x0E,		/* uint8_t	*/
+	MAP_AP_NEWMESSAGE		= 0x0F,		/* uint8_t	*/
+	MAP_AP_NOTIFICATIONSTATUS	= 0x10,		/* uint8_t	*/
+	MAP_AP_MASINSTANCEID		= 0x11,		/* uint8_t	*/
+	MAP_AP_PARAMETERMASK		= 0x12,		/* uint32_t	*/
+	MAP_AP_FOLDERLISTINGSIZE	= 0x13,		/* uint16_t	*/
+	MAP_AP_MESSAGESLISTINGSIZE	= 0x14,		/* uint16_t	*/
+	MAP_AP_SUBJECTLENGTH		= 0x15,		/* uint8_t	*/
+	MAP_AP_CHARSET			= 0x16,		/* uint8_t	*/
+	MAP_AP_FRACTIONREQUEST		= 0x17,		/* uint8_t	*/
+	MAP_AP_FRACTIONDELIVER		= 0x18,		/* uint8_t	*/
+	MAP_AP_STATUSINDICATOR		= 0x19,		/* uint8_t	*/
+	MAP_AP_STATUSVALUE		= 0x1A,		/* uint8_t	*/
+	MAP_AP_MSETIME			= 0x1B,		/* char *	*/
 	MAP_AP_CONVERSATIONID		= 0x1C,		/* uint32_t     */
 };
-- 
2.7.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 6/6] doc/obex-api: Update documentation
  2020-02-11  6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore
                   ` (3 preceding siblings ...)
  2020-02-11  6:36 ` [PATCH v3 4/6] obexd: Add parser for conversation element Ajay Kishore
@ 2020-02-11  6:36 ` Ajay Kishore
  2020-02-11 19:27 ` [PATCH v2 1/6] obexd: Add initial support for MAP conversations Luiz Augusto von Dentz
  5 siblings, 0 replies; 7+ messages in thread
From: Ajay Kishore @ 2020-02-11  6:36 UTC (permalink / raw)
  To: linux-bluetooth

This adds documentation with the conversation listing feature
---
 doc/obex-api.txt | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/doc/obex-api.txt b/doc/obex-api.txt
index f39355a..ef81460 100644
--- a/doc/obex-api.txt
+++ b/doc/obex-api.txt
@@ -712,6 +712,44 @@ Methods		void SetFolder(string name)
 			Possible errors: org.bluez.obex.Error.InvalidArguments
 					 org.bluez.obex.Error.Failed
 
+		array{object, dict} ListConversations(string folder, dict filter)
+
+			Returns an array containing the conversations found in the
+			given subfolder of the current folder, or in the current
+			folder if folder is empty.
+
+			Possible Filters: MaxListCount, LastActivityBegin, LastActivityEnd,
+			ReadStatus, Recipient
+
+			Each message is represented by an object path followed
+			by a dictionary of the properties.
+
+			Properties:
+
+				string id:
+
+					Conversation unique identification
+
+				string last_activity:
+
+					Conversation timestamp for the last activity
+
+				string chat_state:
+
+					Conversation current chat state of the participants
+
+				string presence_availability:
+
+					Conversation  participants availability
+
+				string presence_text:
+
+					User defined status of the conversation
+
+			Possible errors: org.bluez.obex.Error.InvalidArguments
+					 org.bluez.obex.Error.Failed
+
+
 		void UpdateInbox(void)
 
 			Request remote to update its inbox.
@@ -799,6 +837,18 @@ Filter:		uint16 Offset:
 			Possible values: True for high priority or False for
 			non-high priority
 
+		string LastActivityBegin:
+
+			Filter conversations by starting period.
+
+			Possible values: Date in "YYYYMMDDTHHMMSS" format.
+
+		string LastActivityEnd:
+
+			Filter conversations by ending period.
+
+			Possible values: Date in "YYYYMMDDTHHMMSS" format.
+
 Message hierarchy
 =================
 
-- 
2.7.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/6] obexd: Add initial support for MAP conversations
  2020-02-11  6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore
                   ` (4 preceding siblings ...)
  2020-02-11  6:36 ` [PATCH v3 6/6] doc/obex-api: Update documentation Ajay Kishore
@ 2020-02-11 19:27 ` Luiz Augusto von Dentz
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2020-02-11 19:27 UTC (permalink / raw)
  To: Ajay Kishore; +Cc: linux-bluetooth

Hi Ajay,

On Mon, Feb 10, 2020 at 11:32 PM Ajay Kishore <ajay.kishore@intel.com> wrote:
>
> Changes made to add a new method for MAP conversation listing i.e
> "ListConversations" to handle conversation listing object
> "x-bt/MAP-convo-listing".
> ---
>  obexd/client/map.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 67 insertions(+)
>
> diff --git a/obexd/client/map.c b/obexd/client/map.c
> index 550c5af..adf62d9 100644
> --- a/obexd/client/map.c
> +++ b/obexd/client/map.c
> @@ -1560,6 +1560,69 @@ static DBusMessage *map_list_messages(DBusConnection *connection,
>         return get_message_listing(map, message, folder, apparam);
>  }
>
> +static GObexApparam *parse_conversation_filters(GObexApparam *apparam,
> +                                                       DBusMessageIter *iter)
> +{
> +       DBusMessageIter array;
> +
> +       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
> +               DBG("Not of type array");
> +               return NULL;
> +       }
> +
> +       dbus_message_iter_recurse(iter, &array);
> +
> +       while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
> +               const char *key;
> +               DBusMessageIter value, entry;
> +
> +               dbus_message_iter_recurse(&array, &entry);
> +               dbus_message_iter_get_basic(&entry, &key);
> +
> +               dbus_message_iter_next(&entry);
> +               dbus_message_iter_recurse(&entry, &value);
> +
> +               /* TODO: Parse conversation filters */
> +
> +               dbus_message_iter_next(&array);
> +       }
> +       return apparam;
> +}
> +
> +static DBusMessage *map_list_conversations(DBusConnection *connection,
> +                                               DBusMessage *message,
> +                                               void *user_data)
> +{
> +       struct map_data *map = user_data;
> +       const char *folder;
> +       GObexApparam *apparam;
> +       DBusMessageIter args;
> +
> +       dbus_message_iter_init(message, &args);
> +
> +       if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING)
> +               return g_dbus_create_error(message,
> +                       ERROR_INTERFACE ".InvalidArguments", NULL);
> +
> +       dbus_message_iter_get_basic(&args, &folder);
> +
> +       apparam = g_obex_apparam_set_uint16(NULL, MAP_AP_MAXLISTCOUNT,
> +                                                       DEFAULT_COUNT);
> +       apparam = g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET,
> +                                                       DEFAULT_OFFSET);
> +
> +       dbus_message_iter_next(&args);
> +
> +       if (parse_conversation_filters(apparam, &args) == NULL) {
> +               g_obex_apparam_free(apparam);
> +               return g_dbus_create_error(message,
> +                       ERROR_INTERFACE ".InvalidArguments", NULL);
> +       }
> +
> +       /*TODO: Return conversation listing */
> +       return NULL;
> +}
> +
>  static char **get_filter_strs(uint64_t filter, int *size)
>  {
>         char **list, **item;
> @@ -1817,6 +1880,10 @@ static const GDBusMethodTable map_methods[] = {
>                         GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }),
>                         GDBUS_ARGS({ "messages", "a{oa{sv}}" }),
>                         map_list_messages) },
> +       { GDBUS_ASYNC_METHOD("ListConversations",
> +                       GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }),
> +                       GDBUS_ARGS({ "conversations", "a{oa{sv}}" }),
> +                       map_list_conversations) },
>         { GDBUS_METHOD("ListFilterFields",
>                         NULL,
>                         GDBUS_ARGS({ "fields", "as" }),
> --
> 2.7.4

I see some mix of v2 and v3 patches, I recommend updating the whole
set to v3 to make easier to review.


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, back to index

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-11  6:36 [PATCH v2 1/6] obexd: Add initial support for MAP conversations Ajay Kishore
2020-02-11  6:36 ` [PATCH v2 2/6] obexd: Add parsers for conversation filters Ajay Kishore
2020-02-11  6:36 ` [PATCH v2 3/6] obexd: Get conversation listings Ajay Kishore
2020-02-11  6:36 ` [PATCH v2 5/6] obexd: Handle MAP Event Report v1.1 and v1.2 Ajay Kishore
2020-02-11  6:36 ` [PATCH v3 4/6] obexd: Add parser for conversation element Ajay Kishore
2020-02-11  6:36 ` [PATCH v3 6/6] doc/obex-api: Update documentation Ajay Kishore
2020-02-11 19:27 ` [PATCH v2 1/6] obexd: Add initial support for MAP conversations Luiz Augusto von Dentz

Linux-Bluetooth Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-bluetooth/0 linux-bluetooth/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-bluetooth linux-bluetooth/ https://lore.kernel.org/linux-bluetooth \
		linux-bluetooth@vger.kernel.org
	public-inbox-index linux-bluetooth

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-bluetooth


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git