Diff between b7b2ad11c6c6dc96c8a5ec0ae122eb066de96aef and bac315ca0f4f63a591a324f455de657921ec9ebc

Changed Files

File Additions Deletions Status
obexd/src/bluetooth.c +50 -6 modified
obexd/src/main.c +21 -36 modified
obexd/src/obex.c +25 -14 modified
obexd/src/obex.h +10 -6 modified
obexd/src/pbap.c +92 -0 added

Full Patch

diff --git a/obexd/src/bluetooth.c b/obexd/src/bluetooth.c
index d71de24..a385087 100644
--- a/obexd/src/bluetooth.c
+++ b/obexd/src/bluetooth.c
@@ -133,6 +133,47 @@ const static gchar *ftp_record = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>	\
   </attribute>									\
 </record>";
 
+const static gchar *pbap_record = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>	\
+<record>									\
+  <attribute id=\"0x0001\">							\
+    <sequence>									\
+      <uuid value=\"0x112f\"/>							\
+    </sequence>									\
+  </attribute>									\
+										\
+  <attribute id=\"0x0004\">							\
+    <sequence>									\
+      <sequence>								\
+        <uuid value=\"0x0100\"/>						\
+      </sequence>								\
+      <sequence>								\
+        <uuid value=\"0x0003\"/>						\
+        <uint8 value=\"%u\" name=\"channel\"/>					\
+      </sequence>								\
+      <sequence>								\
+        <uuid value=\"0x0008\"/>						\
+      </sequence>								\
+    </sequence>									\
+  </attribute>									\
+										\
+  <attribute id=\"0x0009\">							\
+    <sequence>									\
+      <sequence>								\
+        <uuid value=\"0x1130\"/>						\
+        <uint16 value=\"0x0100\" name=\"version\"/>				\
+      </sequence>								\
+    </sequence>									\
+  </attribute>									\
+										\
+  <attribute id=\"0x0100\">							\
+    <text value=\"%s\" name=\"name\"/>						\
+  </attribute>									\
+										\
+  <attribute id=\"0x0314\">							\
+    <uint8 value=\"0x01\"/>							\
+  </attribute>									\
+</record>";
+
 static uint32_t register_record(const gchar *name,
 				guint16 service, guint8 channel)
 {
@@ -140,12 +181,15 @@ static uint32_t register_record(const gchar *name,
 	gint handle;
 
 	switch (service) {
-	case OBEX_OPUSH:
+	case OBEX_OPP:
 		record = g_markup_printf_escaped(opp_record, channel, name);
 		break;
 	case OBEX_FTP:
 		record = g_markup_printf_escaped(ftp_record, channel, name);
 		break;
+	case OBEX_PBAP:
+		record = g_markup_printf_escaped(pbap_record, channel, name);
+		break;
 	default:
 		return 0;
 	}
@@ -182,7 +226,7 @@ static gboolean connect_event(GIOChannel *io, GIOCondition cond, gpointer user_d
 	info("New connection from: %s, channel %u, fd %d", address,
 			raddr.rc_channel, nsk);
 
-	if (server->service == OBEX_OPUSH) {
+	if (server->service == OBEX_OPP) {
 		if (obex_session_start(nsk, server) < 0)
 			close(nsk);
 
@@ -292,11 +336,11 @@ failed:
 }
 
 gint bluetooth_init(guint service, const gchar *name, const gchar *folder,
-		guint8 channel, gboolean secure, gboolean auto_accept,
-		const gchar *capability)
+				guint8 channel, gboolean secure,
+				gboolean auto_accept, const gchar *capability)
 {
-	return server_register(service, name, channel,
-			folder, secure, auto_accept, capability);
+	return server_register(service, name, channel, folder,
+					secure, auto_accept, capability);
 }
 
 void bluetooth_exit(void)
diff --git a/obexd/src/main.c b/obexd/src/main.c
index 3a7937c..09d2144 100644
--- a/obexd/src/main.c
+++ b/obexd/src/main.c
@@ -46,12 +46,12 @@
 
 #include "logging.h"
 #include "bluetooth.h"
-#include "phonebook.h"
 #include "obexd.h"
 #include "obex.h"
 
-#define OPUSH_CHANNEL	9
+#define OPP_CHANNEL	9
 #define FTP_CHANNEL	10
+#define PBAP_CHANNEL	15
 
 #define DEFAULT_ROOT_PATH "/tmp"
 
@@ -59,26 +59,8 @@
 
 static GMainLoop *main_loop = NULL;
 
-static void test_phonebook(void)
-{
-	struct phonebook_context *context;
-	struct phonebook_driver *driver;
-
-	driver = phonebook_get_driver(NULL);
-	if (driver == NULL)
-		return;
-
-	context = phonebook_create(driver);
-	if (context == NULL)
-		return;
-
-	phonebook_pullphonebook(context);
-
-	phonebook_unref(context);
-}
-
-static void tty_init(int service, const gchar *root_path, const gchar *capability,
-		const gchar *devnode)
+static void tty_init(int service, const gchar *root_path,
+				const gchar *capability, const gchar *devnode)
 {
 	struct server *server;
 	struct termios options;
@@ -113,26 +95,29 @@ static void tty_init(int service, const gchar *root_path, const gchar *capabilit
 }
 
 static int server_start(int service, const char *root_path,
-		gboolean auto_accept, const gchar *capability,
-		const char *devnode)
+			gboolean auto_accept, const gchar *capability,
+							const char *devnode)
 {
 	switch (service) {
-	case OBEX_OPUSH:
-		bluetooth_init(OBEX_OPUSH, "OBEX OPUSH server",
-				root_path, OPUSH_CHANNEL, FALSE,
-				auto_accept, capability);
+	case OBEX_OPP:
+		bluetooth_init(OBEX_OPP, "Object Push server",
+					root_path, OPP_CHANNEL, FALSE,
+						auto_accept, capability);
 		if (devnode)
-			tty_init(OBEX_OPUSH, root_path, capability,
-					devnode);
+			tty_init(OBEX_OPP, root_path, capability, devnode);
 		break;
 	case OBEX_FTP:
-		bluetooth_init(OBEX_FTP, "OBEX FTP server",
-				root_path, FTP_CHANNEL, TRUE,
-				auto_accept, capability);
-
+		bluetooth_init(OBEX_FTP, "File Transfer server",
+					root_path, FTP_CHANNEL, TRUE,
+						auto_accept, capability);
 		if (devnode)
 			tty_init(OBEX_FTP, root_path, capability, devnode);
 		break;
+	case OBEX_PBAP:
+		bluetooth_init(OBEX_PBAP, "Phonebook Access server",
+					root_path, PBAP_CHANNEL, TRUE,
+						auto_accept, capability);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -257,7 +242,7 @@ int main(int argc, char *argv[])
 		option_capability = g_strdup(DEFAULT_CAP_FILE);
 
 	if (option_opp == TRUE)
-		server_start(OBEX_OPUSH, option_root, option_autoaccept,
+		server_start(OBEX_OPP, option_root, option_autoaccept,
 							NULL, option_devnode);
 
 	if (option_ftp == TRUE)
@@ -265,7 +250,7 @@ int main(int argc, char *argv[])
 					option_capability, option_devnode);
 
 	if (option_pbap == TRUE)
-		test_phonebook();
+		server_start(OBEX_PBAP, NULL, FALSE, NULL, NULL);
 
 	memset(&sa, 0, sizeof(sa));
 	sa.sa_handler = sig_term;
diff --git a/obexd/src/obex.c b/obexd/src/obex.c
index 2ccebd1..de96c8a 100644
--- a/obexd/src/obex.c
+++ b/obexd/src/obex.c
@@ -52,33 +52,40 @@
 #define RX_MTU 32767
 #define TX_MTU 32767
 
-#define TARGET_SIZE	16
-static const guint8 FTP_TARGET[TARGET_SIZE] = { 0xF9, 0xEC, 0x7B, 0xC4,
-					0x95, 0x3C, 0x11, 0xD2,
-					0x98, 0x4E, 0x52, 0x54,
-					0x00, 0xDC, 0x9E, 0x09 };
+#define TARGET_SIZE 16
+
+static const guint8 FTP_TARGET[TARGET_SIZE] = {
+			0xF9, 0xEC, 0x7B, 0xC4,  0x95, 0x3C, 0x11, 0xD2,
+			0x98, 0x4E, 0x52, 0x54,  0x00, 0xDC, 0x9E, 0x09  };
+
+static const guint8 PBAP_TARGET[TARGET_SIZE] = {
+			0x79, 0x61, 0x35, 0xF0,  0xF0, 0xC5, 0x11, 0xD8,
+			0x09, 0x66, 0x08, 0x00,  0x20, 0x0C, 0x9A, 0x66  };
 
 /* Connection ID */
 static guint32 cid = 0x0000;
 
 typedef struct {
-    guint8	version;
-    guint8	flags;
-    guint16	mtu;
+	guint8  version;
+	guint8  flags;
+	guint16 mtu;
 } __attribute__ ((packed)) obex_connect_hdr_t;
 
 struct obex_commands opp = {
 	.get		= opp_get,
-	.chkput		= opp_chkput,
 	.put		= opp_put,
-	.setpath	= NULL,
+	.chkput		= opp_chkput,
 };
 
 struct obex_commands ftp = {
 	.get		= ftp_get,
 	.put		= ftp_put,
-	.setpath	= ftp_setpath,
 	.chkput		= ftp_chkput,
+	.setpath	= ftp_setpath,
+};
+
+struct obex_commands pbap = {
+	.get		= pbap_get,
 };
 
 static void os_reset_session(struct obex_session *os)
@@ -248,7 +255,7 @@ static gboolean chk_cid(obex_t *obex, obex_object_t *obj, guint32 cid)
 
 	os = OBEX_GetUserData(obex);
 
-	/* OPUSH doesn't provide a connection id. */
+	/* Object Push doesn't provide a connection id. */
 	if (os->target == NULL)
 		return TRUE;
 
@@ -728,7 +735,7 @@ static void obex_event(obex_t *obex, obex_object_t *obj, gint mode,
 
 	switch (evt) {
 	case OBEX_EV_PROGRESS:
-		/* Just emit progress for OPUSH */
+		/* Just emit progress for Object Push */
 		if (os->target == NULL)
 			emit_transfer_progress(os->cid, os->size, os->offset);
 		break;
@@ -890,7 +897,7 @@ gint obex_session_start(gint fd, struct server *server)
 
 	os = g_new0(struct obex_session, 1);
 	switch (server->service) {
-	case OBEX_OPUSH:
+	case OBEX_OPP:
 		os->target = NULL;
 		os->cmds = &opp;
 		break;
@@ -898,6 +905,10 @@ gint obex_session_start(gint fd, struct server *server)
 		os->target = FTP_TARGET;
 		os->cmds = &ftp;
 		break;
+	case OBEX_PBAP:
+		os->target = PBAP_TARGET;
+		os->cmds = &pbap;
+		break;
 	default:
 		g_free(os);
 		debug("Invalid OBEX server");
diff --git a/obexd/src/obex.h b/obexd/src/obex.h
index fad8a2d..e1889ec 100644
--- a/obexd/src/obex.h
+++ b/obexd/src/obex.h
@@ -29,16 +29,18 @@
 
 #include <glib.h>
 
-#define OBEX_OPUSH	0x00
-#define OBEX_FTP	0x01
+#define OBEX_OPP	0x01
+#define OBEX_FTP	0x02
+#define OBEX_BIP	0x03
+#define OBEX_PBAP	0x04
 
 #define OBJECT_SIZE_UNKNOWN -1
 #define OBJECT_SIZE_DELETE -2
 
 struct obex_commands {
 	void (*get) (obex_t *obex, obex_object_t *obj);
-	gint (*chkput) (obex_t *obex, obex_object_t *obj);
 	void (*put) (obex_t *obex, obex_object_t *obj);
+	gint (*chkput) (obex_t *obex, obex_object_t *obj);
 	void (*setpath) (obex_t *obex, obex_object_t *obj);
 };
 
@@ -73,14 +75,16 @@ struct obex_session {
 gint obex_session_start(gint fd, struct server *server);
 gint obex_session_stop();
 
-gint opp_chkput(obex_t *obex, obex_object_t *obj);
-void opp_put(obex_t *obex, obex_object_t *obj);
 void opp_get(obex_t *obex, obex_object_t *obj);
+void opp_put(obex_t *obex, obex_object_t *obj);
+gint opp_chkput(obex_t *obex, obex_object_t *obj);
 
 void ftp_get(obex_t *obex, obex_object_t *obj);
 void ftp_put(obex_t *obex, obex_object_t *obj);
-void ftp_setpath(obex_t *obex, obex_object_t *obj);
 gint ftp_chkput(obex_t *obex, obex_object_t *obj);
+void ftp_setpath(obex_t *obex, obex_object_t *obj);
+
+void pbap_get(obex_t *obex, obex_object_t *obj);
 
 gboolean os_prepare_get(struct obex_session *os, gchar *file, guint32 *size);
 gint os_prepare_put(struct obex_session *os);
diff --git a/obexd/src/pbap.c b/obexd/src/pbap.c
new file mode 100644
index 0000000..fa12f12
--- /dev/null
+++ b/obexd/src/pbap.c
@@ -0,0 +1,92 @@
+/*
+ *
+ *  OBEX Server
+ *
+ *  Copyright (C) 2007-2008  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <openobex/obex.h>
+#include <openobex/obex_const.h>
+
+#include <glib.h>
+
+#include "phonebook.h"
+#include "logging.h"
+#include "obex.h"
+
+static void test_phonebook(void)
+{
+	struct phonebook_context *context;
+	struct phonebook_driver *driver;
+
+	driver = phonebook_get_driver(NULL);
+	if (driver == NULL)
+		return;
+
+	context = phonebook_create(driver);
+	if (context == NULL)
+		return;
+
+	phonebook_pullphonebook(context);
+
+	phonebook_unref(context);
+}
+
+void pbap_get(obex_t *obex, obex_object_t *obj)
+{
+	struct obex_session *os;
+	obex_headerdata_t hv;
+	guint32 size;
+
+	os = OBEX_GetUserData(obex);
+	if (os == NULL)
+		return;
+
+	if (os->name)
+		goto fail;
+
+	if (os->type == NULL)
+		goto fail;
+
+	test_phonebook();
+	size = 0;
+
+	hv.bq4 = size;
+	OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_LENGTH, hv, 4, 0);
+
+	/* Add body header */
+	hv.bs = NULL;
+	if (size == 0)
+		OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY,
+						hv, 0, OBEX_FL_FIT_ONE_PACKET);
+	else
+		OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY,
+						hv, 0, OBEX_FL_STREAM_START);
+
+	OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
+
+	return;
+
+fail:
+	OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
+}