Diff between ebd3eccc79e4020a1d99ca752ab1d0372224c2c0 and 690e25c5a0455e9c70aad338a1e0bd28bc57a557

Changed Files

File Additions Deletions Status
obexd/client/pbap.c +106 -0 modified

Full Patch

diff --git a/obexd/client/pbap.c b/obexd/client/pbap.c
index 6920057..36322b2 100644
--- a/obexd/client/pbap.c
+++ b/obexd/client/pbap.c
@@ -46,6 +46,7 @@
 #define DEFAULT_OFFSET	0
 
 #define PULLPHONEBOOK		0x1
+#define GETPHONEBOOKSIZE	0x2
 
 #define ORDER_TAG		0x01
 #define SEARCHVALUE_TAG		0x02
@@ -67,6 +68,8 @@
 #define PHONEBOOKSIZE_LEN	2
 #define NEWMISSEDCALLS_LEN	1
 
+#define get_be16(val)	GUINT16_FROM_BE(bt_get_unaligned((guint16 *) val))
+
 struct pullphonebook_apparam {
 	uint8_t     filter_tag;
 	uint8_t     filter_len;
@@ -82,6 +85,14 @@ struct pullphonebook_apparam {
 	uint16_t    liststartoffset;
 } __attribute__ ((packed));
 
+struct apparam_hdr {
+	uint8_t		tag;
+	uint8_t		len;
+	uint8_t		val[0];
+} __attribute__ ((packed));
+
+#define APPARAM_HDR_SIZE 2
+
 static gchar *build_phonebook_path(const char *location, const char *item)
 {
 	gchar *path = NULL, *tmp, *tmp1;
@@ -179,6 +190,54 @@ fail:
 	return err;
 }
 
+static void read_return_apparam(struct session_data *session,
+				guint16 *phone_book_size, guint8 *new_missed_calls)
+{
+	GwObexXfer *xfer = session->xfer;
+	unsigned char *buf;
+	size_t size = 0;
+
+	*phone_book_size = 0;
+	*new_missed_calls = 0;
+
+	if (xfer == NULL)
+		return;
+
+	buf = gw_obex_xfer_object_apparam(xfer, &size);
+
+	if (size < APPARAM_HDR_SIZE)
+		return;
+
+	while (size > APPARAM_HDR_SIZE) {
+		struct apparam_hdr *hdr = (struct apparam_hdr *) buf;
+
+		if (hdr->len > size - APPARAM_HDR_SIZE) {
+			fprintf(stderr, "Unexpected PBAP pullphonebook app"
+					" length, tag %d, len %d\n",
+					hdr->tag, hdr->len);
+			return;
+		}
+
+		switch (hdr->tag) {
+		case PHONEBOOKSIZE_TAG:
+			if (hdr->len == PHONEBOOKSIZE_LEN)
+				*phone_book_size = get_be16(hdr->val);
+			break;
+		case NEWMISSEDCALLS_TAG:
+			if (hdr->len == NEWMISSEDCALLS_LEN)
+				*new_missed_calls = hdr->val[0];
+			break;
+		default:
+			fprintf(stderr, "Unexpected PBAP pullphonebook app"
+					" parameter, tag %d, len %d\n",
+					hdr->tag, hdr->len);
+		}
+
+		buf += APPARAM_HDR_SIZE + hdr->len;
+		size -= APPARAM_HDR_SIZE + hdr->len;
+	}
+}
+
 static void pull_phonebook_callback(struct session_data *session,
 					void *user_data)
 {
@@ -200,6 +259,27 @@ static void pull_phonebook_callback(struct session_data *session,
 	session->msg = NULL;
 }
 
+static void phonebook_size_callback(struct session_data *session,
+					void *user_data)
+{
+	DBusMessage *reply;
+	guint16 phone_book_size;
+	guint8 new_missed_calls;
+
+	reply = dbus_message_new_method_return(session->msg);
+
+	read_return_apparam(session, &phone_book_size, &new_missed_calls);
+
+	dbus_message_append_args(reply,
+			DBUS_TYPE_UINT16, &phone_book_size,
+			DBUS_TYPE_INVALID);
+
+	session->filled = 0;
+	g_dbus_send_message(session->conn, reply);
+	dbus_message_unref(session->msg);
+	session->msg = NULL;
+}
+
 static DBusMessage *pull_phonebook(struct session_data *session,
 					DBusMessage *message, guint8 type,
 					const char *name, uint64_t filter,
@@ -231,6 +311,9 @@ static DBusMessage *pull_phonebook(struct session_data *session,
 	case PULLPHONEBOOK:
 		func = pull_phonebook_callback;
 		break;
+	case GETPHONEBOOKSIZE:
+		func = phonebook_size_callback;
+		break;
 	default:
 		fprintf(stderr, "Unexpected type : 0x%2x\n", type);
 	}
@@ -339,6 +422,27 @@ static DBusMessage *pbap_pull_all(DBusConnection *connection,
 	return err;
 }
 
+static DBusMessage *pbap_get_size(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	struct session_data *session = user_data;
+	struct pbap_data *pbapdata = session->pbapdata;
+	DBusMessage * err;
+	char *name;
+
+	if (!pbapdata->path)
+		return g_dbus_create_error(message,
+				ERROR_INF ".Forbidden", "Call Select first of all");
+
+	name = g_strconcat(pbapdata->path, ".vcf", NULL);
+
+	err = pull_phonebook(session, message, GETPHONEBOOKSIZE, name,
+				pbapdata->filter, pbapdata->format,
+				0, DEFAULT_OFFSET);
+	g_free(name);
+	return err;
+}
+
 static DBusMessage *pbap_set_format(DBusConnection *connection,
 					DBusMessage *message, void *user_data)
 {
@@ -381,6 +485,8 @@ static GDBusMethodTable pbap_methods[] = {
 	{ "Select",	"ss",	"",	pbap_select },
 	{ "PullAll",	"",	"s",	pbap_pull_all,
 					G_DBUS_METHOD_FLAG_ASYNC },
+	{ "GetSize",	"",	"q",	pbap_get_size,
+					G_DBUS_METHOD_FLAG_ASYNC },
 	{ "SetFormat",	"s",	"",	pbap_set_format },
 	{ "SetOrder",	"s",	"",	pbap_set_order },
 	{ }