All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse
@ 2012-10-28  0:29 Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 02/11] build: Add --enable-fuse for obexfuse Michał Poczwardowski
                   ` (9 more replies)
  0 siblings, 10 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |   54 +++++++++++++++++++++++++
 fuse/helpers.h  |   48 ++++++++++++++++++++++
 fuse/obexfuse.c |  119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 221 insertions(+), 0 deletions(-)
 create mode 100644 fuse/helpers.c
 create mode 100644 fuse/helpers.h
 create mode 100644 fuse/obexfuse.c

diff --git a/fuse/helpers.c b/fuse/helpers.c
new file mode 100644
index 0000000..c36072d
--- /dev/null
+++ b/fuse/helpers.c
@@ -0,0 +1,54 @@
+/*
+ *  OBEX Filesystem in Userspace
+ *
+ *  Copyright (C) 2012  Michał Poczwardowski <dmp0x7c5@gmail.com>
+ *
+ *
+ *  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
+ *
+ */
+
+#include <gobex/gobex.h>
+#include <btio/btio.h>
+
+#include <glib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#define BT_RX_MTU 32767
+#define BT_TX_MTU 32767
+
+#include "helpers.h"
+
+#define OBEX_FTP_UUID \
+	"\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
+#define OBEX_FTP_UUID_LEN 16
+
+#define OBEX_FTP_LS "x-obex/folder-listing"
+
+struct gobexhlp_request {
+	gchar *name;
+	gboolean complete;
+};
+
+struct gobexhlp_location {
+	gchar *dir;
+	gchar *file;
+};
diff --git a/fuse/helpers.h b/fuse/helpers.h
new file mode 100644
index 0000000..142403f
--- /dev/null
+++ b/fuse/helpers.h
@@ -0,0 +1,48 @@
+/*
+ *  OBEX Filesystem in Userspace
+ *
+ *  Copyright (C) 2012  Michał Poczwardowski <dmp0x7c5@gmail.com>
+ *
+ *
+ *  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
+ *
+ */
+
+#include <gobex/gobex.h>
+#include <glib.h>
+
+struct gobexhlp_request;
+
+struct gobexhlp_buffer {
+	void *data;
+	gsize tmpsize;
+	gsize size;
+	gboolean edited;
+};
+
+struct gobexhlp_session {
+	GObex *obex;
+	GList *lsfiles;
+	GIOChannel *io;
+	GHashTable *file_stat;
+	gchar *setpath;
+	struct gobexhlp_request *request;
+	struct gobexhlp_buffer *buffer;
+	gboolean vtouch;
+	gchar *vtouch_path;
+	gboolean rtouch;
+	int status;
+	GError *err;
+};
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
new file mode 100644
index 0000000..fe4f4da
--- /dev/null
+++ b/fuse/obexfuse.c
@@ -0,0 +1,119 @@
+/*
+ *  OBEX Filesystem in Userspace
+ *
+ *  Copyright (C) 2012  Michał Poczwardowski <dmp0x7c5@gmail.com>
+ *
+ *
+ *  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
+ *
+ */
+
+#define FUSE_USE_VERSION 26
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fuse.h>
+#include <fuse/fuse_opt.h>
+
+#include "helpers.h"
+
+struct options {
+	char* dststr;
+	char* srcstr;
+} options;
+
+#define GOBEXFUSE_OPT_KEY(t, p, v) { t, offsetof(struct options, p), v }
+
+enum
+{
+   KEY_VERSION,
+   KEY_HELP,
+};
+
+static struct fuse_opt obexfuse_opts[] =
+{
+	GOBEXFUSE_OPT_KEY("--target=%s",dststr, 0),
+	GOBEXFUSE_OPT_KEY("-t %s",	dststr, 0),
+	GOBEXFUSE_OPT_KEY("--source=%s",srcstr, 0),
+	GOBEXFUSE_OPT_KEY("-s %s",	srcstr, 0),
+
+	FUSE_OPT_KEY("-V",             KEY_VERSION),
+	FUSE_OPT_KEY("--version",      KEY_VERSION),
+	FUSE_OPT_KEY("-h",             KEY_HELP),
+	FUSE_OPT_KEY("--help",         KEY_HELP),
+	FUSE_OPT_END
+};
+
+static struct fuse_operations obexfuse_oper = {
+};
+
+static int obexfuse_opt_proc(void *data, const char *arg, int key,
+					struct fuse_args *outargs)
+{
+	switch (key) {
+	case KEY_HELP:
+		g_printerr("Usage: %s mountpoint [options]\n"
+				"\n"
+				"general options:\n"
+				"    -o opt,[opt...]  mount options\n"
+				"    -h   --help      print help\n"
+				"    -V   --version   print version\n"
+				"\n"
+				"obexfuse options:\n"
+				"    -t   --target    target btaddr "
+				"(mandatory)\n"
+				"    -s   --source    source btaddr\n"
+				"\n"
+				, outargs->argv[0]);
+		fuse_opt_add_arg(outargs, "-ho");
+		fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
+		exit(1);
+	case KEY_VERSION:
+		g_print("obexfuse upon:\n");
+		fuse_opt_add_arg(outargs, "--version");
+		fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
+		exit(0);
+	}
+	return 1;
+}
+
+int main(int argc, char *argv[])
+{
+	int retfuse;
+	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+
+	memset(&options, 0, sizeof(struct options));
+
+	if (fuse_opt_parse(&args, &options, obexfuse_opts,
+				obexfuse_opt_proc) == -1)
+		return -EINVAL;
+
+	if (options.dststr == NULL) {
+		g_printerr("Target not specified\n");
+		return -EINVAL;
+	}
+
+	g_thread_init(NULL);
+
+	fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
+	retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
+
+	fuse_opt_free_args(&args);
+	return retfuse;
+}
-- 
1.7.8.6


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

* [RFC v2 obexd 02/11] build: Add --enable-fuse for obexfuse
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers Michał Poczwardowski
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 Makefile.am  |    9 +++++++++
 configure.ac |   15 +++++++++++++++
 2 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 724dd5d..01441dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -132,6 +132,15 @@ client_obex_client_SOURCES = $(gdbus_sources) $(gobex_sources) \
 client_obex_client_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
 endif
 
+if FUSE
+bin_PROGRAMS = fuse/obexfuse
+
+fuse_obexfuse_SOURCES = $(gobex_sources) $(btio_sources) \
+		fuse/helpers.c fuse/obexfuse.c
+
+fuse_obexfuse_LDADD = @GLIB_LIBS@ @GTHREAD_LIBS@ @BLUEZ_LIBS@ @FUSE_LIBS@
+endif
+
 service_DATA = $(service_in_files:.service.in=.service)
 
 AM_CFLAGS = @BLUEZ_CFLAGS@ @EBOOK_CFLAGS@ @GTHREAD_CFLAGS@ @GLIB_CFLAGS@ \
diff --git a/configure.ac b/configure.ac
index c8e61ac..f380481 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,4 +180,19 @@ AM_CONDITIONAL(CLIENT, test "${enable_client}" != "no")
 
 AM_CONDITIONAL(READLINE, test "${readline_found}" = "yes")
 
+AC_ARG_ENABLE(fuse, AC_HELP_STRING([--enable-fuse],
+			[Build obexfuse]), [
+	PKG_CHECK_MODULES(FUSE, fuse, dummy=yes,
+				      AC_MSG_ERROR(FUSE is required))
+	AC_SUBST(FUSE_CFLAGS)
+	AC_SUBST(FUSE_LIBS)
+	enable_fuse=${enableval}
+
+	PKG_CHECK_MODULES(GTHREAD, gthread-2.0, dummy=yes,
+					AC_MSG_ERROR(libgthread is required))
+	AC_SUBST(GTHREAD_CFLAGS)
+	AC_SUBST(GTHREAD_LIBS)
+])
+AM_CONDITIONAL(FUSE, test "${enable_fuse}" != "no")
+
 AC_OUTPUT(Makefile)
-- 
1.7.8.6


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

* [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 02/11] build: Add --enable-fuse for obexfuse Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  2012-10-30  9:08   ` Luiz Augusto von Dentz
  2012-10-28  0:29 ` [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |  221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h  |    4 +
 fuse/obexfuse.c |   40 ++++++++++
 3 files changed, 265 insertions(+), 0 deletions(-)

diff --git a/fuse/helpers.c b/fuse/helpers.c
index c36072d..856e1d5 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -43,6 +43,9 @@
 
 #define OBEX_FTP_LS "x-obex/folder-listing"
 
+static GCond *gobexhlp_cond;
+static GMutex *gobexhlp_mutex;
+
 struct gobexhlp_request {
 	gchar *name;
 	gboolean complete;
@@ -52,3 +55,221 @@ struct gobexhlp_location {
 	gchar *dir;
 	gchar *file;
 };
+
+static uint16_t find_rfcomm_uuid(void *user_data)
+{
+	sdp_list_t *pds = (sdp_list_t*) user_data;
+	uint16_t channel = 0;
+
+	for (;pds;pds = pds->next) {
+		sdp_data_t *d = (sdp_data_t*)pds->data;
+		int proto = 0;
+		for (; d; d = d->next) {
+			switch(d->dtd) {
+			case SDP_UUID16:
+			case SDP_UUID32:
+			case SDP_UUID128:
+				proto = sdp_uuid_to_proto(&d->val.uuid);
+			break;
+			case SDP_UINT8:
+				if (proto == RFCOMM_UUID)
+					channel = d->val.int8;
+				break;
+			}
+		}
+	}
+	return channel;
+}
+
+static uint16_t get_ftp_channel(bdaddr_t *src, bdaddr_t *dst)
+{
+	sdp_session_t *sdp;
+	sdp_list_t *r, *search_list, *attrid_list;
+	sdp_list_t *response_list = NULL;
+	uuid_t uuid;
+
+	/* FTP_SDP_UUID "00001106-0000-1000-8000-00805f9b34fb" */
+	uint8_t uuid_int[] = {0, 0, 0x11, 0x06, 0, 0, 0x10, 0, 0x80,
+					0, 0, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+	uint32_t range = 0x0000ffff;
+	uint16_t channel = 0;
+
+	sdp = sdp_connect(src, dst, SDP_RETRY_IF_BUSY );
+	if (sdp == NULL)
+		return channel;
+
+	sdp_uuid128_create(&uuid, uuid_int);
+	search_list = sdp_list_append(NULL, &uuid);
+	attrid_list = sdp_list_append(NULL, &range);
+	sdp_service_search_attr_req(sdp, search_list, SDP_ATTR_REQ_RANGE,
+					attrid_list, &response_list);
+	r = response_list;
+
+	for (; r;r = r->next) {
+		sdp_record_t *rec = (sdp_record_t*) r->data;
+		sdp_list_t *proto_list;
+
+		if (sdp_get_access_protos(rec, &proto_list ) == 0) {
+			sdp_list_t *p = proto_list;
+			for (; p; p = p->next) {
+				sdp_list_t *pds = (sdp_list_t*) p->data;
+				channel = find_rfcomm_uuid(pds);
+				sdp_list_free((sdp_list_t*) p->data, 0);
+			}
+			sdp_list_free(proto_list, 0);
+		}
+		sdp_record_free(rec);
+	}
+	sdp_close(sdp);
+
+	g_free(search_list);
+	g_free(attrid_list);
+	g_free(response_list);
+
+	return channel;
+}
+
+/* taken from client/bluetooth.c - bluetooth_getpacketopt */
+static int get_packet_opt(GIOChannel *io, int *tx_mtu, int *rx_mtu)
+{
+	int sk = g_io_channel_unix_get_fd(io);
+	int type;
+	int omtu = -1;
+	int imtu = -1;
+	socklen_t len = sizeof(int);
+
+	if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
+		return -errno;
+
+	if (type != SOCK_SEQPACKET)
+		return -EINVAL;
+
+	if (!bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu,
+						BT_IO_OPT_IMTU, &imtu,
+						BT_IO_OPT_INVALID))
+		return -EINVAL;
+
+	if (tx_mtu)
+		*tx_mtu = omtu;
+
+	if (rx_mtu)
+		*rx_mtu = imtu;
+
+	return 0;
+}
+
+static void obex_callback(GObex *obex, GError *err, GObexPacket *rsp,
+							gpointer user_data)
+{
+	if (err != NULL) {
+		g_debug("Connect failed: %s\n", err->message);
+		g_error_free(err);
+	} else {
+		g_debug("Connect succeeded\n");
+	}
+}
+
+static void bt_io_callback(GIOChannel *io, GError *err, gpointer user_data)
+{
+	struct gobexhlp_session *session = user_data;
+	GObexTransportType type;
+	int tx_mtu = -1;
+	int rx_mtu = -1;
+
+	if (err != NULL) {
+		g_printerr("%s\n", err->message);
+		g_error_free(err);
+		return;
+	}
+
+	g_debug("Bluetooth socket connected\n");
+
+	g_io_channel_set_flags(session->io, G_IO_FLAG_NONBLOCK, NULL);
+	g_io_channel_set_close_on_unref(session->io, TRUE);
+
+	if (get_packet_opt(session->io, &tx_mtu, &rx_mtu) == 0) {
+		type = G_OBEX_TRANSPORT_PACKET;
+		g_debug("PACKET transport tx:%d rx:%d\n", tx_mtu, rx_mtu);
+	} else {
+		type = G_OBEX_TRANSPORT_STREAM;
+		g_debug("STREAM transport\n");
+	}
+
+	session->obex = g_obex_new(io, type, tx_mtu, rx_mtu);
+	g_obex_connect(session->obex, obex_callback, session, NULL,
+				G_OBEX_HDR_TARGET, OBEX_FTP_UUID,
+				OBEX_FTP_UUID_LEN, G_OBEX_HDR_INVALID);
+}
+
+struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
+						const char *dststr)
+{
+	struct gobexhlp_session *session;
+	uint16_t channel;
+	bdaddr_t src, dst;
+
+	session = g_try_malloc0(sizeof(struct gobexhlp_session));
+	if (session == NULL)
+		return NULL;
+
+	if (srcstr == NULL)
+		bacpy(&src, BDADDR_ANY);
+	else
+		str2ba(srcstr, &src);
+
+	str2ba(dststr, &dst);
+	channel = get_ftp_channel(&src, &dst);
+
+	if (channel == 0)
+		return NULL;
+
+	if (channel > 31)
+		session->io = bt_io_connect(BT_IO_L2CAP, bt_io_callback,
+				session, NULL, &session->err,
+				BT_IO_OPT_SOURCE_BDADDR, &src,
+				BT_IO_OPT_DEST_BDADDR, &dst,
+				BT_IO_OPT_PSM, channel,
+				BT_IO_OPT_MODE, BT_IO_MODE_ERTM,
+				BT_IO_OPT_OMTU, BT_TX_MTU,
+				BT_IO_OPT_IMTU, BT_RX_MTU,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+				BT_IO_OPT_INVALID);
+	else
+		session->io = bt_io_connect(BT_IO_RFCOMM, bt_io_callback,
+				session, NULL, &session->err,
+				BT_IO_OPT_SOURCE_BDADDR, &src,
+				BT_IO_OPT_DEST_BDADDR, &dst,
+				BT_IO_OPT_CHANNEL, channel,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+				BT_IO_OPT_INVALID);
+
+	if (session->err != NULL)
+		return NULL;
+
+	session->file_stat = g_hash_table_new_full( g_str_hash, g_str_equal,
+					g_free, g_free);
+	session->setpath = g_strdup("/");
+
+	gobexhlp_mutex = g_mutex_new();
+	gobexhlp_cond = g_cond_new();
+
+	return session;
+}
+
+void gobexhlp_disconnect(struct gobexhlp_session* session)
+{
+	if (session == NULL)
+		return;
+
+	g_obex_unref(session->obex);
+	g_free(session->io);
+
+	g_hash_table_remove_all(session->file_stat);
+	g_list_free_full(session->lsfiles, g_free);
+	g_free(session->setpath);
+
+	g_mutex_free(gobexhlp_mutex);
+	g_cond_free(gobexhlp_cond);
+
+	g_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 142403f..29dc6cf 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -46,3 +46,7 @@ struct gobexhlp_session {
 	int status;
 	GError *err;
 };
+
+struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
+						const char *dstsrc);
+void gobexhlp_disconnect(struct gobexhlp_session* session);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index fe4f4da..79eb990 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -33,6 +33,10 @@
 
 #include "helpers.h"
 
+struct gobexhlp_session* session = NULL;
+static GMainLoop *main_loop;
+static GThread *main_gthread;
+
 struct options {
 	char* dststr;
 	char* srcstr;
@@ -60,7 +64,34 @@ static struct fuse_opt obexfuse_opts[] =
 	FUSE_OPT_END
 };
 
+gpointer main_loop_func(gpointer user_data)
+{
+	main_loop = g_main_loop_new(NULL, FALSE);
+	g_main_loop_run(main_loop);
+
+	return 0;
+}
+
+void* obexfuse_init(struct fuse_conn_info *conn)
+{
+	main_gthread = g_thread_create(main_loop_func, NULL, TRUE, NULL);
+
+	conn->async_read = 0;
+	conn->want &= ~FUSE_CAP_ASYNC_READ;
+
+	return 0;
+}
+
+void obexfuse_destroy()
+{
+	gobexhlp_disconnect(session);
+	g_main_loop_quit(main_loop);
+	g_thread_join(main_gthread);
+}
+
 static struct fuse_operations obexfuse_oper = {
+	.init = obexfuse_init,
+	.destroy = obexfuse_destroy,
 };
 
 static int obexfuse_opt_proc(void *data, const char *arg, int key,
@@ -111,6 +142,15 @@ int main(int argc, char *argv[])
 
 	g_thread_init(NULL);
 
+	session = gobexhlp_connect(options.srcstr, options.dststr);
+	if (session == NULL || session->io == NULL) {
+		g_printerr("Connection to %s failed\n", options.dststr);
+		gobexhlp_disconnect(session);
+		return -EHOSTUNREACH;
+	} else {
+		g_print("Connected\nMounting %s\n", options.dststr);
+	}
+
 	fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
 	retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
 
-- 
1.7.8.6


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

* [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 02/11] build: Add --enable-fuse for obexfuse Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  2012-10-30  9:35   ` Luiz Augusto von Dentz
  2012-10-28  0:29 ` [RFC v2 obexd 05/11] fuse: Add readdir operation Michał Poczwardowski
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 108 insertions(+), 0 deletions(-)

diff --git a/fuse/helpers.c b/fuse/helpers.c
index 856e1d5..1b8082f 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -273,3 +273,111 @@ void gobexhlp_disconnect(struct gobexhlp_session* session)
 
 	g_free(session);
 }
+
+void request_new(struct gobexhlp_session *session,
+					gchar *name)
+{
+	g_print("REQUEST %s\n", name);
+
+	if (session->request != NULL)
+		g_error("Another request (%s) active!\n",
+					session->request->name);
+
+	session->status = 0;
+	session->request = g_malloc0(sizeof(struct gobexhlp_request));
+	session->request->name = name;
+
+	/*
+	 * suspend/resume operations recreates g_io_add_watch(),
+	 * it fixes obex->io freeze during transfer
+	 */
+	g_obex_suspend(session->obex);
+	g_obex_resume(session->obex);
+}
+
+void request_wait_free(struct gobexhlp_session *session)
+{
+	g_print("WAIT for %s\n", session->request->name);
+
+	g_obex_suspend(session->obex);
+	g_obex_resume(session->obex);
+
+	if (session->err != NULL) {
+		g_print("ERROR: %s (%d)\n", session->err->message,
+						session->err->code);
+		g_error_free(session->err);
+		raise(SIGTERM);
+		return;
+	}
+
+	g_mutex_lock(gobexhlp_mutex);
+
+	while (session->request->complete != TRUE)
+		g_cond_wait(gobexhlp_cond, gobexhlp_mutex);
+
+	g_mutex_unlock(gobexhlp_mutex);
+
+	g_free(session->request->name);
+	g_free(session->request);
+	session->request = NULL;
+}
+
+static void complete_func(GObex *obex, GError *err,
+				gpointer user_data)
+{
+	struct gobexhlp_session *session = user_data;
+
+	if (err != NULL) {
+		g_print("ERROR: %s\n", err->message);
+		session->status = -ECANCELED;
+		g_error_free(err);
+	} else {
+		g_print("COMPLETE %s\n", session->request->name);
+	}
+
+	g_mutex_lock(gobexhlp_mutex);
+	session->request->complete = TRUE;
+	g_cond_signal(gobexhlp_cond);
+	g_mutex_unlock(gobexhlp_mutex);
+}
+
+static void response_func(GObex *obex, GError *err, GObexPacket *rsp,
+							gpointer user_data)
+{
+	complete_func(obex, err, user_data);
+}
+
+void gobexhlp_setpath(struct gobexhlp_session *session, const char *path)
+{
+	guint i = 0, split = 0;
+	gchar **path_v;
+	gsize len;
+
+	g_print("gobexhlp_setpath(%s)\n", path);
+
+	if (g_str_has_prefix(path, session->setpath)) {
+		split = strlen(session->setpath);
+	} else {
+		request_new(session, g_strdup_printf("setpath root"));
+		g_obex_setpath(session->obex, "", response_func,
+						session, &session->err);
+		request_wait_free(session);
+	}
+
+	path_v = g_strsplit(path+split, "/", -1);
+	len = g_strv_length(path_v);
+
+	for (i = 0; i < len; i++)
+		if (path_v[i][0] != '\0') {
+			request_new(session,
+				g_strdup_printf("setpath %s", path_v[i]));
+			g_obex_setpath(session->obex, path_v[i],
+					response_func, session, &session->err);
+			request_wait_free(session);
+		}
+
+	g_free(session->setpath);
+	session->setpath = g_strdup(path);
+
+	g_strfreev(path_v);
+}
-- 
1.7.8.6


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

* [RFC v2 obexd 05/11] fuse: Add readdir operation
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (2 preceding siblings ...)
  2012-10-28  0:29 ` [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 06/11] fuse: Add getattr operation Michał Poczwardowski
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |  128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h  |    2 +
 fuse/obexfuse.c |   23 ++++++++++
 3 files changed, 153 insertions(+), 0 deletions(-)

diff --git a/fuse/helpers.c b/fuse/helpers.c
index 1b8082f..cb0b51d 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -381,3 +381,131 @@ void gobexhlp_setpath(struct gobexhlp_session *session, const char *path)
 
 	g_strfreev(path_v);
 }
+
+static void listfolder_xml_element(GMarkupParseContext *ctxt,
+			const gchar *element, const gchar **names,
+			const gchar **values, gpointer user_data,
+			GError **gerr)
+{
+	gchar *key, *pathname, *name = NULL;
+	struct gobexhlp_session *session = user_data;
+	struct stat *stbuf;
+	gint i = 0;
+
+	stbuf = g_malloc0(sizeof(struct stat));
+
+	if ((strcasecmp("file", element) == 0)) {
+		stbuf->st_mode = S_IFREG;
+	} else if ((strcasecmp("folder", element)) == 0) {
+		stbuf->st_mode = S_IFDIR;
+		stbuf->st_mtime = time(NULL);
+	} else {
+		g_free(stbuf);
+		return;
+	}
+
+	for (key = (gchar *) names[i]; key; key = (gchar *) names[++i]) {
+		if (g_str_equal("name", key) == TRUE) {
+			session->lsfiles = g_list_append(session->lsfiles,
+						g_strdup(values[i]));
+			name = g_strdup(values[i]);
+
+		} else if (g_str_equal("size", key) == TRUE) {
+			guint64 size;
+			size = g_ascii_strtoll(values[i], NULL, 10);
+			stbuf->st_size = size;
+
+		} else if (g_str_equal("created", key) == TRUE) {
+			GTimeVal time;
+			GDateTime *datetime;
+			g_time_val_from_iso8601(values[i], &time);
+			datetime = g_date_time_new_from_timeval_utc(&time);
+			stbuf->st_mtime = g_date_time_to_unix(datetime);
+		}
+	}
+
+	if (g_str_equal("/", session->setpath) == TRUE)
+		pathname = g_strdup_printf("/%s", name);
+	else
+		pathname = g_strdup_printf("%s/%s", session->setpath, name);
+
+	g_hash_table_replace(session->file_stat, pathname, stbuf);
+	g_free(name);
+}
+
+static const GMarkupParser parser = {
+	listfolder_xml_element,
+	NULL, NULL, NULL, NULL
+};
+
+static void complete_listfolder_func(GObex *obex, GError *err,
+				gpointer user_data)
+{
+	GMarkupParseContext *ctxt;
+	struct gobexhlp_session *session = user_data;
+	struct gobexhlp_buffer *buffer = session->buffer;
+
+	if (err == NULL) {
+		ctxt = g_markup_parse_context_new(&parser, 0, session, NULL);
+		g_markup_parse_context_parse(ctxt, buffer->data, buffer->size,
+							NULL);
+		g_markup_parse_context_free(ctxt);
+	}
+
+	complete_func(obex, err, user_data);
+}
+
+static gboolean async_get_consumer(const void *buf, gsize len,
+							gpointer user_data)
+{
+	struct gobexhlp_session *session = user_data;
+	struct gobexhlp_buffer *buffer = session->buffer;
+
+	if (buffer->size == 0)
+		buffer->data = g_malloc0(sizeof(char) * len);
+	else
+		buffer->data = g_realloc(buffer->data, buffer->size + len);
+
+	memcpy(buffer->data + buffer->size, buf, len);
+	buffer->size += len;
+
+	g_obex_suspend(session->obex);
+	g_obex_resume(session->obex);
+
+	return TRUE;
+}
+
+GList *gobexhlp_listfolder(struct gobexhlp_session* session,
+					const char *path)
+{
+	struct gobexhlp_buffer *buffer;
+	GObexPacket *req;
+	guint reqpkt;
+
+	gobexhlp_setpath(session, path);
+
+	g_print("gobexhlp_listfolder(%s)\n", path);
+
+	if (session->lsfiles != NULL) {
+		g_list_free_full(session->lsfiles, g_free);
+		session->lsfiles = NULL;
+	}
+
+	session->lsfiles = g_list_alloc();
+	buffer = g_malloc0(sizeof(struct gobexhlp_buffer));
+	session->buffer = buffer;
+
+	request_new(session, g_strdup_printf("listfolder %s", path));
+	req = g_obex_packet_new(G_OBEX_OP_GET, TRUE, G_OBEX_HDR_INVALID);
+	g_obex_packet_add_bytes(req, G_OBEX_HDR_TYPE, OBEX_FTP_LS,
+						strlen(OBEX_FTP_LS) + 1);
+	reqpkt = g_obex_get_req_pkt(session->obex, req,
+				async_get_consumer,
+				complete_listfolder_func,
+				session, &session->err);
+	request_wait_free(session);
+	g_free(buffer->data);
+	g_free(buffer);
+
+	return session->lsfiles;
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 29dc6cf..546d79c 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -50,3 +50,5 @@ struct gobexhlp_session {
 struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
 						const char *dstsrc);
 void gobexhlp_disconnect(struct gobexhlp_session* session);
+
+GList *gobexhlp_listfolder(struct gobexhlp_session* session, const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 79eb990..5de82ec 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -89,7 +89,30 @@ void obexfuse_destroy()
 	g_thread_join(main_gthread);
 }
 
+static int obexfuse_readdir(const char *path, void *buf,
+			fuse_fill_dir_t filler, off_t offset,
+				struct fuse_file_info *fi)
+{
+	int len, i;
+	gchar *string;
+	GList *files;
+
+	filler(buf, ".", NULL, 0);
+	filler(buf, "..", NULL, 0);
+
+	files = gobexhlp_listfolder(session, path);
+	len = g_list_length(files);
+
+	for (i = 1; i < len; i++) { /* element for i==0 is NULL */
+		string = g_list_nth_data(files, i);
+		filler(buf, string, NULL, 0);
+	}
+
+	return session->status;
+}
+
 static struct fuse_operations obexfuse_oper = {
+	.readdir = obexfuse_readdir,
 	.init = obexfuse_init,
 	.destroy = obexfuse_destroy,
 };
-- 
1.7.8.6


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

* [RFC v2 obexd 06/11] fuse: Add getattr operation
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (3 preceding siblings ...)
  2012-10-28  0:29 ` [RFC v2 obexd 05/11] fuse: Add readdir operation Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 07/11] fuse: Add open and read operations plus location helpers Michał Poczwardowski
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |    6 ++++++
 fuse/helpers.h  |    2 ++
 fuse/obexfuse.c |   34 ++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/fuse/helpers.c b/fuse/helpers.c
index cb0b51d..a10b706 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -509,3 +509,9 @@ GList *gobexhlp_listfolder(struct gobexhlp_session* session,
 
 	return session->lsfiles;
 }
+
+struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
+					const char *path)
+{
+	return g_hash_table_lookup(session->file_stat, path);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 546d79c..047abae 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -52,3 +52,5 @@ struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
 void gobexhlp_disconnect(struct gobexhlp_session* session);
 
 GList *gobexhlp_listfolder(struct gobexhlp_session* session, const char *path);
+struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
+					const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 5de82ec..f4e85fa 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -111,8 +111,42 @@ static int obexfuse_readdir(const char *path, void *buf,
 	return session->status;
 }
 
+static int obexfuse_getattr(const char *path, struct stat *stbuf)
+{
+	int res = 0;
+	struct stat *stfile;
+
+	memset(stbuf, 0, sizeof(struct stat));
+
+	if (strcmp(path, "/") == 0) {
+		stbuf->st_mode = S_IFDIR | 0755;
+		stbuf->st_nlink = 2;
+	} else {
+		stfile = gobexhlp_getattr(session, path);
+
+		if (stfile == NULL)
+			return -ENOENT;
+
+		if (stfile->st_mode == S_IFREG)
+			stbuf->st_mode = stfile->st_mode | 0666;
+		else /* S_IFDIR */
+			stbuf->st_mode = stfile->st_mode | 0755;
+
+		stbuf->st_nlink = 1;
+		stbuf->st_size = stfile->st_size;
+		stbuf->st_mtime = stbuf->st_atime = stbuf->st_ctime =
+						stfile->st_mtime;
+		stbuf->st_blksize = 512;
+		stbuf->st_blocks = (stbuf->st_size + stbuf->st_blksize)
+						/ stbuf->st_blksize;
+	}
+
+	return res;
+}
+
 static struct fuse_operations obexfuse_oper = {
 	.readdir = obexfuse_readdir,
+	.getattr = obexfuse_getattr,
 	.init = obexfuse_init,
 	.destroy = obexfuse_destroy,
 };
-- 
1.7.8.6


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

* [RFC v2 obexd 07/11] fuse: Add open and read operations plus location helpers
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (4 preceding siblings ...)
  2012-10-28  0:29 ` [RFC v2 obexd 06/11] fuse: Add getattr operation Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 08/11] fuse: Add write operation Michał Poczwardowski
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h  |    2 +
 fuse/obexfuse.c |   32 ++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/fuse/helpers.c b/fuse/helpers.c
index a10b706..9b453e0 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -515,3 +515,65 @@ struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
 {
 	return g_hash_table_lookup(session->file_stat, path);
 }
+
+static struct gobexhlp_location *get_location(const char *path)
+{
+	struct gobexhlp_location *location;
+	gchar **directories;
+	guint i, len, fid = 0;
+
+	location = g_malloc0(sizeof(*location));
+	directories = g_strsplit(path, "/", -1);
+	len = g_strv_length(directories);
+
+	for (i = 0; i < len; i++)
+		if (directories[i][0] != '\0') /* protect multi slashes */
+			fid = i; /* last nonempty is a file */
+
+	location->file = g_strdup(directories[fid]);
+	directories[fid][0] = '\0'; /* remove file */
+	location->dir = g_strjoinv("/", directories);
+
+	g_strfreev(directories);
+
+	return location;
+}
+
+void free_location(struct gobexhlp_location *location)
+{
+	g_free(location->file);
+	g_free(location->dir);
+	g_free(location);
+}
+
+struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
+						const char *path)
+{
+	struct gobexhlp_location *l;
+	struct gobexhlp_buffer *buffer;
+	struct stat *stfile;
+	l = get_location(path);
+
+	g_print("gobexhlp_get(%s%s)\n", l->dir, l->file);
+
+	stfile = gobexhlp_getattr(session, path);
+	if (stfile == NULL)
+		return NULL;
+
+	buffer = g_malloc0(sizeof(*buffer));
+
+	if (stfile->st_size == 0)
+		return buffer;
+
+	gobexhlp_setpath(session, l->dir);
+	request_new(session, g_strdup_printf("get %s", path));
+	session->buffer = buffer;
+	g_obex_get_req(session->obex, async_get_consumer,
+					complete_func, session, &session->err,
+					G_OBEX_HDR_NAME, l->file,
+					G_OBEX_HDR_INVALID);
+	free_location(l);
+	request_wait_free(session);
+
+	return buffer;
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 047abae..aa2a194 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -54,3 +54,5 @@ void gobexhlp_disconnect(struct gobexhlp_session* session);
 GList *gobexhlp_listfolder(struct gobexhlp_session* session, const char *path);
 struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
 					const char *path);
+struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
+					const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index f4e85fa..9fe2dea 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -144,9 +144,41 @@ static int obexfuse_getattr(const char *path, struct stat *stbuf)
 	return res;
 }
 
+static int obexfuse_open(const char *path, struct fuse_file_info *fi)
+{
+	struct gobexhlp_buffer *file_buffer;
+
+	file_buffer = gobexhlp_get(session, path);
+
+	if (file_buffer == NULL)
+		return -ENOENT;
+
+	fi->fh = (uint64_t)file_buffer;
+
+	return session->status;
+}
+
+static int obexfuse_read(const char *path, char *buf, size_t size,
+			off_t offset, struct fuse_file_info *fi)
+{
+	gsize asize;
+	struct gobexhlp_buffer *file_buffer = (struct gobexhlp_buffer*)fi->fh;
+
+	asize = file_buffer->size - offset;
+
+	if (asize > size)
+		asize = size;
+
+	memcpy(buf, file_buffer->data + offset, asize);
+
+	return asize;
+}
+
 static struct fuse_operations obexfuse_oper = {
 	.readdir = obexfuse_readdir,
 	.getattr = obexfuse_getattr,
+	.open = obexfuse_open,
+	.read = obexfuse_read,
 	.init = obexfuse_init,
 	.destroy = obexfuse_destroy,
 };
-- 
1.7.8.6


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

* [RFC v2 obexd 08/11] fuse: Add write operation
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (5 preceding siblings ...)
  2012-10-28  0:29 ` [RFC v2 obexd 07/11] fuse: Add open and read operations plus location helpers Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 09/11] fuse: Add touch operation Michał Poczwardowski
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |   44 ++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h  |    3 +++
 fuse/obexfuse.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/fuse/helpers.c b/fuse/helpers.c
index 9b453e0..796c4a3 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -577,3 +577,47 @@ struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
 
 	return buffer;
 }
+
+static gssize async_put_producer(void *buf, gsize len, gpointer user_data)
+{
+	gssize size;
+	struct gobexhlp_session *session = user_data;
+	struct gobexhlp_buffer *buffer = session->buffer;
+
+	size = buffer->size - buffer->tmpsize;
+
+	if (size > len)
+		size = len;
+
+	g_obex_suspend(session->obex);
+	g_obex_resume(session->obex);
+
+	if (size == 0)
+		return 0;
+
+	memcpy(buf, buffer->data + buffer->tmpsize, size);
+	buffer->tmpsize += size;
+
+	return size;
+}
+
+void gobexhlp_put(struct gobexhlp_session* session,
+				struct gobexhlp_buffer *buffer,
+				const char *path)
+{
+	struct gobexhlp_location *l;
+	l = get_location(path);
+
+	g_print("gobexhlp_put(%s%s)\n", l->dir, l->file);
+
+	gobexhlp_setpath(session, l->dir);
+	buffer->tmpsize = 0;
+	session->buffer = buffer;
+	request_new(session, g_strdup_printf("put %s", path));
+	g_obex_put_req(session->obex, async_put_producer,
+					complete_func, session, &session->err,
+					G_OBEX_HDR_NAME, l->file,
+					G_OBEX_HDR_INVALID);
+	free_location(l);
+	request_wait_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index aa2a194..1eca29d 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -56,3 +56,6 @@ struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
 					const char *path);
 struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
 					const char *path);
+void gobexhlp_put(struct gobexhlp_session* session,
+					struct gobexhlp_buffer *buffer,
+					const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 9fe2dea..900e6d7 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -174,11 +174,55 @@ static int obexfuse_read(const char *path, char *buf, size_t size,
 	return asize;
 }
 
+static int obexfuse_write(const char *path, const char *buf, size_t size,
+				off_t offset, struct fuse_file_info *fi)
+{
+	gsize nsize;
+	struct gobexhlp_buffer *file_buffer = (struct gobexhlp_buffer*)fi->fh;
+
+	if (file_buffer->size < offset + size) {
+		nsize = offset + size;
+		file_buffer->data = g_realloc(file_buffer->data, nsize);
+		file_buffer->size = nsize;
+	} else {
+		nsize = file_buffer->size;
+	}
+
+	file_buffer->edited = TRUE;
+	memcpy(file_buffer->data + offset, buf, size);
+
+	return size;
+}
+
+static int obexfuse_truncate(const char *path, off_t offset)
+{
+	/*
+	 *  Allow to change the size of a file.
+	 */
+	return 0;
+}
+
+static int obexfuse_release(const char *path, struct fuse_file_info *fi)
+{
+	struct gobexhlp_buffer *file_buffer = (struct gobexhlp_buffer*)fi->fh;
+
+	if (file_buffer->edited == TRUE)
+		gobexhlp_put(session, file_buffer, path); /* send to device */
+
+	g_free(file_buffer->data);
+	g_free(file_buffer);
+
+	return session->status;
+}
+
 static struct fuse_operations obexfuse_oper = {
 	.readdir = obexfuse_readdir,
 	.getattr = obexfuse_getattr,
 	.open = obexfuse_open,
 	.read = obexfuse_read,
+	.write = obexfuse_write,
+	.truncate = obexfuse_truncate,
+	.release = obexfuse_release,
 	.init = obexfuse_init,
 	.destroy = obexfuse_destroy,
 };
-- 
1.7.8.6


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

* [RFC v2 obexd 09/11] fuse: Add touch operation
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (6 preceding siblings ...)
  2012-10-28  0:29 ` [RFC v2 obexd 08/11] fuse: Add write operation Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 10/11] fuse: Add unlink/rmdir operation Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 11/11] fuse: Add rename operation Michał Poczwardowski
  9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |   40 ++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h  |    1 +
 fuse/obexfuse.c |   17 +++++++++++++++++
 3 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/fuse/helpers.c b/fuse/helpers.c
index 796c4a3..cabf8f7 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -56,6 +56,8 @@ struct gobexhlp_location {
 	gchar *file;
 };
 
+void gobexhlp_touch_real(struct gobexhlp_session* session, gchar *path);
+
 static uint16_t find_rfcomm_uuid(void *user_data)
 {
 	sdp_list_t *pds = (sdp_list_t*) user_data;
@@ -279,6 +281,12 @@ void request_new(struct gobexhlp_session *session,
 {
 	g_print("REQUEST %s\n", name);
 
+	if (session->vtouch == TRUE) {
+		session->vtouch = FALSE;
+		gobexhlp_touch_real(session, session->vtouch_path);
+		g_free(session->vtouch_path);
+	}
+
 	if (session->request != NULL)
 		g_error("Another request (%s) active!\n",
 					session->request->name);
@@ -621,3 +629,35 @@ void gobexhlp_put(struct gobexhlp_session* session,
 	free_location(l);
 	request_wait_free(session);
 }
+
+/* virtual file creation */
+void gobexhlp_touch(struct gobexhlp_session* session, const char *path)
+{
+	struct stat *stbuf;
+
+	g_print("gobexhlp_touch(%s)\n", path);
+
+	stbuf = g_malloc0(sizeof(struct stat));
+	stbuf->st_mode = S_IFREG;
+	g_hash_table_replace(session->file_stat, g_strdup(path), stbuf);
+
+	session->vtouch = TRUE;
+	session->vtouch_path = g_strdup(path);
+}
+
+void gobexhlp_touch_real(struct gobexhlp_session* session, gchar *path)
+{
+	struct gobexhlp_buffer *buffer, *tmpbuf;
+
+	g_print("gobexhlp_touch_real(%s)\n", path);
+
+	tmpbuf = session->buffer; /* save buffer state */
+
+	buffer = g_malloc0(sizeof(struct gobexhlp_buffer));
+	session->rtouch = TRUE;
+	gobexhlp_put(session, buffer, path);
+	session->rtouch = FALSE;
+	g_free(buffer);
+
+	session->buffer = tmpbuf;
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 1eca29d..c2b28ca 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -59,3 +59,4 @@ struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
 void gobexhlp_put(struct gobexhlp_session* session,
 					struct gobexhlp_buffer *buffer,
 					const char *path);
+void gobexhlp_touch(struct gobexhlp_session* session, const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 900e6d7..b4599d8 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -215,6 +215,21 @@ static int obexfuse_release(const char *path, struct fuse_file_info *fi)
 	return session->status;
 }
 
+static int obexfuse_utimens(const char *path, const struct timespec tv[2])
+{
+	/*
+	 * Important for mknod (touch) operation
+	 */
+	return 0;
+}
+
+static int obexfuse_mknod(const char *path, mode_t mode, dev_t dev)
+{
+	gobexhlp_touch(session, path);
+
+	return 0;
+}
+
 static struct fuse_operations obexfuse_oper = {
 	.readdir = obexfuse_readdir,
 	.getattr = obexfuse_getattr,
@@ -223,6 +238,8 @@ static struct fuse_operations obexfuse_oper = {
 	.write = obexfuse_write,
 	.truncate = obexfuse_truncate,
 	.release = obexfuse_release,
+	.utimens = obexfuse_utimens,
+	.mknod = obexfuse_mknod,
 	.init = obexfuse_init,
 	.destroy = obexfuse_destroy,
 };
-- 
1.7.8.6


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

* [RFC v2 obexd 10/11] fuse: Add unlink/rmdir operation
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (7 preceding siblings ...)
  2012-10-28  0:29 ` [RFC v2 obexd 09/11] fuse: Add touch operation Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  2012-10-28  0:29 ` [RFC v2 obexd 11/11] fuse: Add rename operation Michał Poczwardowski
  9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |   28 ++++++++++++++++++++++++++++
 fuse/helpers.h  |    1 +
 fuse/obexfuse.c |    9 +++++++++
 3 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/fuse/helpers.c b/fuse/helpers.c
index cabf8f7..d0580c2 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -618,6 +618,16 @@ void gobexhlp_put(struct gobexhlp_session* session,
 
 	g_print("gobexhlp_put(%s%s)\n", l->dir, l->file);
 
+	if (g_strcmp0(path, session->vtouch_path) == 0 &&
+				session->vtouch == TRUE) {
+		session->vtouch = FALSE;
+		g_free(session->vtouch_path);
+	} else {
+		/* delete existing file */
+		if (session->rtouch == FALSE)
+			gobexhlp_delete(session, path);
+	}
+
 	gobexhlp_setpath(session, l->dir);
 	buffer->tmpsize = 0;
 	session->buffer = buffer;
@@ -661,3 +671,21 @@ void gobexhlp_touch_real(struct gobexhlp_session* session, gchar *path)
 
 	session->buffer = tmpbuf;
 }
+
+void gobexhlp_delete(struct gobexhlp_session* session, const char *path)
+{
+	struct gobexhlp_location *l;
+	l = get_location(path);
+
+	g_print("gobexhlp_delete(%s)\n", l->file);
+
+	gobexhlp_setpath(session, l->dir);
+	request_new(session, g_strdup_printf("delete %s", path));
+	g_obex_delete(session->obex, l->file, response_func, session,
+							&session->err);
+
+	g_hash_table_remove(session->file_stat, path);
+
+	free_location(l);
+	request_wait_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index c2b28ca..803cb59 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -60,3 +60,4 @@ void gobexhlp_put(struct gobexhlp_session* session,
 					struct gobexhlp_buffer *buffer,
 					const char *path);
 void gobexhlp_touch(struct gobexhlp_session* session, const char *path);
+void gobexhlp_delete(struct gobexhlp_session* session, const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index b4599d8..2a6ee11 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -230,6 +230,13 @@ static int obexfuse_mknod(const char *path, mode_t mode, dev_t dev)
 	return 0;
 }
 
+static int obexfuse_unlink(const char *path)
+{
+	gobexhlp_delete(session, path);
+
+	return session->status;
+}
+
 static struct fuse_operations obexfuse_oper = {
 	.readdir = obexfuse_readdir,
 	.getattr = obexfuse_getattr,
@@ -240,6 +247,8 @@ static struct fuse_operations obexfuse_oper = {
 	.release = obexfuse_release,
 	.utimens = obexfuse_utimens,
 	.mknod = obexfuse_mknod,
+	.unlink = obexfuse_unlink,
+	.rmdir = obexfuse_unlink,
 	.init = obexfuse_init,
 	.destroy = obexfuse_destroy,
 };
-- 
1.7.8.6


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

* [RFC v2 obexd 11/11] fuse: Add rename operation
  2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (8 preceding siblings ...)
  2012-10-28  0:29 ` [RFC v2 obexd 10/11] fuse: Add unlink/rmdir operation Michał Poczwardowski
@ 2012-10-28  0:29 ` Michał Poczwardowski
  9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28  0:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h  |    3 +++
 fuse/obexfuse.c |   16 ++++++++++++++++
 3 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/fuse/helpers.c b/fuse/helpers.c
index d0580c2..2487d09 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -689,3 +689,49 @@ void gobexhlp_delete(struct gobexhlp_session* session, const char *path)
 	free_location(l);
 	request_wait_free(session);
 }
+
+void gobexhlp_mkdir(struct gobexhlp_session* session, const char *path)
+{
+	struct gobexhlp_location *l;
+	struct stat *stbuf;
+
+	g_print("gobexhlp_mkdir(%s)\n", path);
+
+	l = get_location(path);
+	gobexhlp_setpath(session, l->dir);
+
+	request_new(session, g_strdup_printf("mkdir %s", path));
+	/* g_obex_mkdir also sets path, to new folder */
+	g_obex_mkdir(session->obex, l->file, response_func, session,
+							&session->err);
+	g_free(session->setpath);
+	session->setpath = g_strdup(path);
+
+	stbuf = g_malloc0(sizeof(struct stat));
+	stbuf->st_mode = S_IFDIR;
+	stbuf->st_mtime = time(NULL);
+	g_hash_table_replace(session->file_stat, g_strdup(path), stbuf);
+
+	free_location(l);
+	request_wait_free(session);
+}
+
+void gobexhlp_move(struct gobexhlp_session* session, const char *oldpath,
+						const char* newpath)
+{
+	struct gobexhlp_location *l_from, *l_to;
+
+	l_to = get_location(newpath);
+	l_from = get_location(oldpath);
+	gobexhlp_setpath(session, l_from->dir);
+
+	g_print("gobexhlp_move(%s to %s)\n", l_from->file, l_to->file);
+
+	request_new(session, g_strdup_printf("move %s:%s",
+					oldpath, newpath));
+	g_obex_move(session->obex, l_from->file, l_to->file, response_func,
+						session, &session->err);
+	free_location(l_to);
+	free_location(l_from);
+	request_wait_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 803cb59..80e3aa8 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -61,3 +61,6 @@ void gobexhlp_put(struct gobexhlp_session* session,
 					const char *path);
 void gobexhlp_touch(struct gobexhlp_session* session, const char *path);
 void gobexhlp_delete(struct gobexhlp_session* session, const char *path);
+void gobexhlp_mkdir(struct gobexhlp_session* session, const char *path);
+void gobexhlp_move(struct gobexhlp_session* session, const char *oldpath,
+					const char* newpath);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 2a6ee11..f9f9d0e 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -237,6 +237,20 @@ static int obexfuse_unlink(const char *path)
 	return session->status;
 }
 
+static int obexfuse_mkdir(const char *path, mode_t mode)
+{
+	gobexhlp_mkdir(session, path);
+
+	return session->status;
+}
+
+static int obexfuse_rename(const char *from, const char *to)
+{
+	gobexhlp_move(session, from, to);
+
+	return session->status;
+}
+
 static struct fuse_operations obexfuse_oper = {
 	.readdir = obexfuse_readdir,
 	.getattr = obexfuse_getattr,
@@ -249,6 +263,8 @@ static struct fuse_operations obexfuse_oper = {
 	.mknod = obexfuse_mknod,
 	.unlink = obexfuse_unlink,
 	.rmdir = obexfuse_unlink,
+	.mkdir = obexfuse_mkdir,
+	.rename = obexfuse_rename,
 	.init = obexfuse_init,
 	.destroy = obexfuse_destroy,
 };
-- 
1.7.8.6


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

* Re: [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers
  2012-10-28  0:29 ` [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers Michał Poczwardowski
@ 2012-10-30  9:08   ` Luiz Augusto von Dentz
  2012-11-01 22:33     ` Michał Poczwardowski
  0 siblings, 1 reply; 16+ messages in thread
From: Luiz Augusto von Dentz @ 2012-10-30  9:08 UTC (permalink / raw)
  To: Michał Poczwardowski; +Cc: linux-bluetooth

Hi Michal,

On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
<dmp0x7c5@gmail.com> wrote:
> ---
>  fuse/helpers.c  |  221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  fuse/helpers.h  |    4 +
>  fuse/obexfuse.c |   40 ++++++++++
>  3 files changed, 265 insertions(+), 0 deletions(-)
>
> diff --git a/fuse/helpers.c b/fuse/helpers.c
> index c36072d..856e1d5 100644
> --- a/fuse/helpers.c
> +++ b/fuse/helpers.c
> @@ -43,6 +43,9 @@
>
>  #define OBEX_FTP_LS "x-obex/folder-listing"
>
> +static GCond *gobexhlp_cond;
> +static GMutex *gobexhlp_mutex;
> +
>  struct gobexhlp_request {
>         gchar *name;
>         gboolean complete;
> @@ -52,3 +55,221 @@ struct gobexhlp_location {
>         gchar *dir;
>         gchar *file;
>  };
> +
> +static uint16_t find_rfcomm_uuid(void *user_data)
> +{
> +       sdp_list_t *pds = (sdp_list_t*) user_data;
> +       uint16_t channel = 0;
> +
> +       for (;pds;pds = pds->next) {
> +               sdp_data_t *d = (sdp_data_t*)pds->data;
> +               int proto = 0;
> +               for (; d; d = d->next) {
> +                       switch(d->dtd) {
> +                       case SDP_UUID16:
> +                       case SDP_UUID32:
> +                       case SDP_UUID128:
> +                               proto = sdp_uuid_to_proto(&d->val.uuid);
> +                       break;
> +                       case SDP_UINT8:
> +                               if (proto == RFCOMM_UUID)
> +                                       channel = d->val.int8;
> +                               break;
> +                       }
> +               }
> +       }
> +       return channel;
> +}
> +
> +static uint16_t get_ftp_channel(bdaddr_t *src, bdaddr_t *dst)
> +{
> +       sdp_session_t *sdp;
> +       sdp_list_t *r, *search_list, *attrid_list;
> +       sdp_list_t *response_list = NULL;
> +       uuid_t uuid;
> +
> +       /* FTP_SDP_UUID "00001106-0000-1000-8000-00805f9b34fb" */
> +       uint8_t uuid_int[] = {0, 0, 0x11, 0x06, 0, 0, 0x10, 0, 0x80,
> +                                       0, 0, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
> +       uint32_t range = 0x0000ffff;
> +       uint16_t channel = 0;
> +
> +       sdp = sdp_connect(src, dst, SDP_RETRY_IF_BUSY );
> +       if (sdp == NULL)
> +               return channel;
> +
> +       sdp_uuid128_create(&uuid, uuid_int);
> +       search_list = sdp_list_append(NULL, &uuid);
> +       attrid_list = sdp_list_append(NULL, &range);
> +       sdp_service_search_attr_req(sdp, search_list, SDP_ATTR_REQ_RANGE,
> +                                       attrid_list, &response_list);
> +       r = response_list;
> +
> +       for (; r;r = r->next) {
> +               sdp_record_t *rec = (sdp_record_t*) r->data;
> +               sdp_list_t *proto_list;
> +
> +               if (sdp_get_access_protos(rec, &proto_list ) == 0) {
> +                       sdp_list_t *p = proto_list;
> +                       for (; p; p = p->next) {
> +                               sdp_list_t *pds = (sdp_list_t*) p->data;
> +                               channel = find_rfcomm_uuid(pds);
> +                               sdp_list_free((sdp_list_t*) p->data, 0);

You dont really need to iterate in the list of protos there exist a
function that does that for you take a look at sdp_get_proto_port, btw
there exist a similar code in client/bluetooth.c

> +                       }
> +                       sdp_list_free(proto_list, 0);
> +               }
> +               sdp_record_free(rec);
> +       }
> +       sdp_close(sdp);
> +
> +       g_free(search_list);
> +       g_free(attrid_list);
> +       g_free(response_list);
> +
> +       return channel;
> +}
> +
> +/* taken from client/bluetooth.c - bluetooth_getpacketopt */
> +static int get_packet_opt(GIOChannel *io, int *tx_mtu, int *rx_mtu)
> +{
> +       int sk = g_io_channel_unix_get_fd(io);
> +       int type;
> +       int omtu = -1;
> +       int imtu = -1;
> +       socklen_t len = sizeof(int);
> +
> +       if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
> +               return -errno;
> +
> +       if (type != SOCK_SEQPACKET)
> +               return -EINVAL;
> +
> +       if (!bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu,
> +                                               BT_IO_OPT_IMTU, &imtu,
> +                                               BT_IO_OPT_INVALID))
> +               return -EINVAL;
> +
> +       if (tx_mtu)
> +               *tx_mtu = omtu;
> +
> +       if (rx_mtu)
> +               *rx_mtu = imtu;
> +
> +       return 0;
> +}
> +
> +static void obex_callback(GObex *obex, GError *err, GObexPacket *rsp,
> +                                                       gpointer user_data)
> +{
> +       if (err != NULL) {
> +               g_debug("Connect failed: %s\n", err->message);
> +               g_error_free(err);
> +       } else {
> +               g_debug("Connect succeeded\n");
> +       }
> +}
> +
> +static void bt_io_callback(GIOChannel *io, GError *err, gpointer user_data)
> +{
> +       struct gobexhlp_session *session = user_data;
> +       GObexTransportType type;
> +       int tx_mtu = -1;
> +       int rx_mtu = -1;
> +
> +       if (err != NULL) {
> +               g_printerr("%s\n", err->message);
> +               g_error_free(err);
> +               return;
> +       }
> +
> +       g_debug("Bluetooth socket connected\n");
> +
> +       g_io_channel_set_flags(session->io, G_IO_FLAG_NONBLOCK, NULL);
> +       g_io_channel_set_close_on_unref(session->io, TRUE);
> +
> +       if (get_packet_opt(session->io, &tx_mtu, &rx_mtu) == 0) {
> +               type = G_OBEX_TRANSPORT_PACKET;
> +               g_debug("PACKET transport tx:%d rx:%d\n", tx_mtu, rx_mtu);
> +       } else {
> +               type = G_OBEX_TRANSPORT_STREAM;
> +               g_debug("STREAM transport\n");
> +       }
> +
> +       session->obex = g_obex_new(io, type, tx_mtu, rx_mtu);
> +       g_obex_connect(session->obex, obex_callback, session, NULL,
> +                               G_OBEX_HDR_TARGET, OBEX_FTP_UUID,
> +                               OBEX_FTP_UUID_LEN, G_OBEX_HDR_INVALID);
> +}
> +
> +struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
> +                                               const char *dststr)
> +{
> +       struct gobexhlp_session *session;
> +       uint16_t channel;
> +       bdaddr_t src, dst;
> +
> +       session = g_try_malloc0(sizeof(struct gobexhlp_session));
> +       if (session == NULL)
> +               return NULL;
> +
> +       if (srcstr == NULL)
> +               bacpy(&src, BDADDR_ANY);
> +       else
> +               str2ba(srcstr, &src);
> +
> +       str2ba(dststr, &dst);
> +       channel = get_ftp_channel(&src, &dst);
> +
> +       if (channel == 0)
> +               return NULL;

Currently you are not checking for L2CAP psm just RFCOMM channel so
the code bellow would never be used.

> +       if (channel > 31)
> +               session->io = bt_io_connect(BT_IO_L2CAP, bt_io_callback,
> +                               session, NULL, &session->err,
> +                               BT_IO_OPT_SOURCE_BDADDR, &src,
> +                               BT_IO_OPT_DEST_BDADDR, &dst,
> +                               BT_IO_OPT_PSM, channel,
> +                               BT_IO_OPT_MODE, BT_IO_MODE_ERTM,
> +                               BT_IO_OPT_OMTU, BT_TX_MTU,
> +                               BT_IO_OPT_IMTU, BT_RX_MTU,
> +                               BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
> +                               BT_IO_OPT_INVALID);
> +       else
> +               session->io = bt_io_connect(BT_IO_RFCOMM, bt_io_callback,
> +                               session, NULL, &session->err,
> +                               BT_IO_OPT_SOURCE_BDADDR, &src,
> +                               BT_IO_OPT_DEST_BDADDR, &dst,
> +                               BT_IO_OPT_CHANNEL, channel,
> +                               BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
> +                               BT_IO_OPT_INVALID);
> +
> +       if (session->err != NULL)
> +               return NULL;
> +
> +       session->file_stat = g_hash_table_new_full( g_str_hash, g_str_equal,
> +                                       g_free, g_free);
> +       session->setpath = g_strdup("/");
> +
> +       gobexhlp_mutex = g_mutex_new();
> +       gobexhlp_cond = g_cond_new();
> +
> +       return session;
> +}
> +
> +void gobexhlp_disconnect(struct gobexhlp_session* session)
> +{
> +       if (session == NULL)
> +               return;
> +
> +       g_obex_unref(session->obex);
> +       g_free(session->io);
> +
> +       g_hash_table_remove_all(session->file_stat);
> +       g_list_free_full(session->lsfiles, g_free);
> +       g_free(session->setpath);
> +
> +       g_mutex_free(gobexhlp_mutex);
> +       g_cond_free(gobexhlp_cond);
> +
> +       g_free(session);
> +}
> diff --git a/fuse/helpers.h b/fuse/helpers.h
> index 142403f..29dc6cf 100644
> --- a/fuse/helpers.h
> +++ b/fuse/helpers.h
> @@ -46,3 +46,7 @@ struct gobexhlp_session {
>         int status;
>         GError *err;
>  };
> +
> +struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
> +                                               const char *dstsrc);
> +void gobexhlp_disconnect(struct gobexhlp_session* session);
> diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
> index fe4f4da..79eb990 100644
> --- a/fuse/obexfuse.c
> +++ b/fuse/obexfuse.c
> @@ -33,6 +33,10 @@
>
>  #include "helpers.h"
>
> +struct gobexhlp_session* session = NULL;
> +static GMainLoop *main_loop;
> +static GThread *main_gthread;
> +
>  struct options {
>         char* dststr;
>         char* srcstr;
> @@ -60,7 +64,34 @@ static struct fuse_opt obexfuse_opts[] =
>         FUSE_OPT_END
>  };
>
> +gpointer main_loop_func(gpointer user_data)
> +{
> +       main_loop = g_main_loop_new(NULL, FALSE);
> +       g_main_loop_run(main_loop);
> +
> +       return 0;
> +}
> +
> +void* obexfuse_init(struct fuse_conn_info *conn)
> +{
> +       main_gthread = g_thread_create(main_loop_func, NULL, TRUE, NULL);
> +
> +       conn->async_read = 0;
> +       conn->want &= ~FUSE_CAP_ASYNC_READ;
> +
> +       return 0;
> +}
> +
> +void obexfuse_destroy()
> +{
> +       gobexhlp_disconnect(session);
> +       g_main_loop_quit(main_loop);
> +       g_thread_join(main_gthread);
> +}
> +
>  static struct fuse_operations obexfuse_oper = {
> +       .init = obexfuse_init,
> +       .destroy = obexfuse_destroy,
>  };
>
>  static int obexfuse_opt_proc(void *data, const char *arg, int key,
> @@ -111,6 +142,15 @@ int main(int argc, char *argv[])
>
>         g_thread_init(NULL);
>

I would suggest not mixing gobex prefix with your helper functions, in
fact it is probably fine to just use obexfuse e.g. obexfuse_connect.

> +       session = gobexhlp_connect(options.srcstr, options.dststr);
> +       if (session == NULL || session->io == NULL) {
> +               g_printerr("Connection to %s failed\n", options.dststr);
> +               gobexhlp_disconnect(session);
> +               return -EHOSTUNREACH;
> +       } else {
> +               g_print("Connected\nMounting %s\n", options.dststr);
> +       }
> +
>         fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
>         retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
>
> --
> 1.7.8.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Luiz Augusto von Dentz

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

* Re: [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation
  2012-10-28  0:29 ` [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
@ 2012-10-30  9:35   ` Luiz Augusto von Dentz
  2012-11-01 21:59     ` Michał Poczwardowski
  0 siblings, 1 reply; 16+ messages in thread
From: Luiz Augusto von Dentz @ 2012-10-30  9:35 UTC (permalink / raw)
  To: Michał Poczwardowski; +Cc: linux-bluetooth

Hi Michal,

On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
<dmp0x7c5@gmail.com> wrote:
> ---
>  fuse/helpers.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 108 insertions(+), 0 deletions(-)
>
> diff --git a/fuse/helpers.c b/fuse/helpers.c
> index 856e1d5..1b8082f 100644
> --- a/fuse/helpers.c
> +++ b/fuse/helpers.c
> @@ -273,3 +273,111 @@ void gobexhlp_disconnect(struct gobexhlp_session* session)
>
>         g_free(session);
>  }
> +
> +void request_new(struct gobexhlp_session *session,
> +                                       gchar *name)
> +{
> +       g_print("REQUEST %s\n", name);
> +
> +       if (session->request != NULL)
> +               g_error("Another request (%s) active!\n",
> +                                       session->request->name);
> +
> +       session->status = 0;
> +       session->request = g_malloc0(sizeof(struct gobexhlp_request));
> +       session->request->name = name;
> +
> +       /*
> +        * suspend/resume operations recreates g_io_add_watch(),
> +        * it fixes obex->io freeze during transfer
> +        */
> +       g_obex_suspend(session->obex);
> +       g_obex_resume(session->obex);

It seems the issue here is that the mainloop is blocked then you have
to force the io checking by doing g_io_add_watch in a different
thread, we have dealt with this kind of problem before using
g_main_context_iteration. I would have been better if fuse supported
async io, but apparently all operations are blocking.

-- 
Luiz Augusto von Dentz

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

* Re: [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation
  2012-10-30  9:35   ` Luiz Augusto von Dentz
@ 2012-11-01 21:59     ` Michał Poczwardowski
  2012-11-20 17:52       ` Michał Poczwardowski
  0 siblings, 1 reply; 16+ messages in thread
From: Michał Poczwardowski @ 2012-11-01 21:59 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

On 30 October 2012 10:35, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
> Hi Michal,
>
> On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
> <dmp0x7c5@gmail.com> wrote:
>> ---
>>  fuse/helpers.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 files changed, 108 insertions(+), 0 deletions(-)
>>
>> diff --git a/fuse/helpers.c b/fuse/helpers.c
>> index 856e1d5..1b8082f 100644
>> --- a/fuse/helpers.c
>> +++ b/fuse/helpers.c
>> @@ -273,3 +273,111 @@ void gobexhlp_disconnect(struct gobexhlp_session* session)
>>
>>         g_free(session);
>>  }
>> +
>> +void request_new(struct gobexhlp_session *session,
>> +                                       gchar *name)
>> +{
>> +       g_print("REQUEST %s\n", name);
>> +
>> +       if (session->request != NULL)
>> +               g_error("Another request (%s) active!\n",
>> +                                       session->request->name);
>> +
>> +       session->status = 0;
>> +       session->request = g_malloc0(sizeof(struct gobexhlp_request));
>> +       session->request->name = name;
>> +
>> +       /*
>> +        * suspend/resume operations recreates g_io_add_watch(),
>> +        * it fixes obex->io freeze during transfer
>> +        */
>> +       g_obex_suspend(session->obex);
>> +       g_obex_resume(session->obex);
>
> It seems the issue here is that the mainloop is blocked then you have
> to force the io checking by doing g_io_add_watch in a different
> thread, we have dealt with this kind of problem before using
> g_main_context_iteration. I would have been better if fuse supported
> async io, but apparently all operations are blocking.
>
> --
> Luiz Augusto von Dentz

I'll try g_main_context_iteration way to avoid the io freeze.
Unfortunately fuse with obex should use blocking operations.

Thanks,
Michal

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

* Re: [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers
  2012-10-30  9:08   ` Luiz Augusto von Dentz
@ 2012-11-01 22:33     ` Michał Poczwardowski
  0 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-11-01 22:33 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

On 30 October 2012 10:08, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
> Hi Michal,
>
> On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
> <dmp0x7c5@gmail.com> wrote:
>> ---
>>  fuse/helpers.c  |  221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  fuse/helpers.h  |    4 +
>>  fuse/obexfuse.c |   40 ++++++++++
>>  3 files changed, 265 insertions(+), 0 deletions(-)
>>
>> diff --git a/fuse/helpers.c b/fuse/helpers.c
>> index c36072d..856e1d5 100644
>> --- a/fuse/helpers.c
>> +++ b/fuse/helpers.c
>> @@ -43,6 +43,9 @@
>>
>>  #define OBEX_FTP_LS "x-obex/folder-listing"
>>
>> +static GCond *gobexhlp_cond;
>> +static GMutex *gobexhlp_mutex;
>> +
>>  struct gobexhlp_request {
>>         gchar *name;
>>         gboolean complete;
>> @@ -52,3 +55,221 @@ struct gobexhlp_location {
>>         gchar *dir;
>>         gchar *file;
>>  };
>> +
>> +static uint16_t find_rfcomm_uuid(void *user_data)
>> +{
>> +       sdp_list_t *pds = (sdp_list_t*) user_data;
>> +       uint16_t channel = 0;
>> +
>> +       for (;pds;pds = pds->next) {
>> +               sdp_data_t *d = (sdp_data_t*)pds->data;
>> +               int proto = 0;
>> +               for (; d; d = d->next) {
>> +                       switch(d->dtd) {
>> +                       case SDP_UUID16:
>> +                       case SDP_UUID32:
>> +                       case SDP_UUID128:
>> +                               proto = sdp_uuid_to_proto(&d->val.uuid);
>> +                       break;
>> +                       case SDP_UINT8:
>> +                               if (proto == RFCOMM_UUID)
>> +                                       channel = d->val.int8;
>> +                               break;
>> +                       }
>> +               }
>> +       }
>> +       return channel;
>> +}
>> +
>> +static uint16_t get_ftp_channel(bdaddr_t *src, bdaddr_t *dst)
>> +{
>> +       sdp_session_t *sdp;
>> +       sdp_list_t *r, *search_list, *attrid_list;
>> +       sdp_list_t *response_list = NULL;
>> +       uuid_t uuid;
>> +
>> +       /* FTP_SDP_UUID "00001106-0000-1000-8000-00805f9b34fb" */
>> +       uint8_t uuid_int[] = {0, 0, 0x11, 0x06, 0, 0, 0x10, 0, 0x80,
>> +                                       0, 0, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
>> +       uint32_t range = 0x0000ffff;
>> +       uint16_t channel = 0;
>> +
>> +       sdp = sdp_connect(src, dst, SDP_RETRY_IF_BUSY );
>> +       if (sdp == NULL)
>> +               return channel;
>> +
>> +       sdp_uuid128_create(&uuid, uuid_int);
>> +       search_list = sdp_list_append(NULL, &uuid);
>> +       attrid_list = sdp_list_append(NULL, &range);
>> +       sdp_service_search_attr_req(sdp, search_list, SDP_ATTR_REQ_RANGE,
>> +                                       attrid_list, &response_list);
>> +       r = response_list;
>> +
>> +       for (; r;r = r->next) {
>> +               sdp_record_t *rec = (sdp_record_t*) r->data;
>> +               sdp_list_t *proto_list;
>> +
>> +               if (sdp_get_access_protos(rec, &proto_list ) == 0) {
>> +                       sdp_list_t *p = proto_list;
>> +                       for (; p; p = p->next) {
>> +                               sdp_list_t *pds = (sdp_list_t*) p->data;
>> +                               channel = find_rfcomm_uuid(pds);
>> +                               sdp_list_free((sdp_list_t*) p->data, 0);
>
> You dont really need to iterate in the list of protos there exist a
> function that does that for you take a look at sdp_get_proto_port, btw
> there exist a similar code in client/bluetooth.c
>

I didn't notice sdp_get_proto_port when I was reading client/bluetooth.c code :)

>> +                       }
>> +                       sdp_list_free(proto_list, 0);
>> +               }
>> +               sdp_record_free(rec);
>> +       }
>> +       sdp_close(sdp);
>> +
>> +       g_free(search_list);
>> +       g_free(attrid_list);
>> +       g_free(response_list);
>> +
>> +       return channel;
>> +}
>> +
>> +/* taken from client/bluetooth.c - bluetooth_getpacketopt */
>> +static int get_packet_opt(GIOChannel *io, int *tx_mtu, int *rx_mtu)
>> +{
>> +       int sk = g_io_channel_unix_get_fd(io);
>> +       int type;
>> +       int omtu = -1;
>> +       int imtu = -1;
>> +       socklen_t len = sizeof(int);
>> +
>> +       if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
>> +               return -errno;
>> +
>> +       if (type != SOCK_SEQPACKET)
>> +               return -EINVAL;
>> +
>> +       if (!bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu,
>> +                                               BT_IO_OPT_IMTU, &imtu,
>> +                                               BT_IO_OPT_INVALID))
>> +               return -EINVAL;
>> +
>> +       if (tx_mtu)
>> +               *tx_mtu = omtu;
>> +
>> +       if (rx_mtu)
>> +               *rx_mtu = imtu;
>> +
>> +       return 0;
>> +}
>> +
>> +static void obex_callback(GObex *obex, GError *err, GObexPacket *rsp,
>> +                                                       gpointer user_data)
>> +{
>> +       if (err != NULL) {
>> +               g_debug("Connect failed: %s\n", err->message);
>> +               g_error_free(err);
>> +       } else {
>> +               g_debug("Connect succeeded\n");
>> +       }
>> +}
>> +
>> +static void bt_io_callback(GIOChannel *io, GError *err, gpointer user_data)
>> +{
>> +       struct gobexhlp_session *session = user_data;
>> +       GObexTransportType type;
>> +       int tx_mtu = -1;
>> +       int rx_mtu = -1;
>> +
>> +       if (err != NULL) {
>> +               g_printerr("%s\n", err->message);
>> +               g_error_free(err);
>> +               return;
>> +       }
>> +
>> +       g_debug("Bluetooth socket connected\n");
>> +
>> +       g_io_channel_set_flags(session->io, G_IO_FLAG_NONBLOCK, NULL);
>> +       g_io_channel_set_close_on_unref(session->io, TRUE);
>> +
>> +       if (get_packet_opt(session->io, &tx_mtu, &rx_mtu) == 0) {
>> +               type = G_OBEX_TRANSPORT_PACKET;
>> +               g_debug("PACKET transport tx:%d rx:%d\n", tx_mtu, rx_mtu);
>> +       } else {
>> +               type = G_OBEX_TRANSPORT_STREAM;
>> +               g_debug("STREAM transport\n");
>> +       }
>> +
>> +       session->obex = g_obex_new(io, type, tx_mtu, rx_mtu);
>> +       g_obex_connect(session->obex, obex_callback, session, NULL,
>> +                               G_OBEX_HDR_TARGET, OBEX_FTP_UUID,
>> +                               OBEX_FTP_UUID_LEN, G_OBEX_HDR_INVALID);
>> +}
>> +
>> +struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
>> +                                               const char *dststr)
>> +{
>> +       struct gobexhlp_session *session;
>> +       uint16_t channel;
>> +       bdaddr_t src, dst;
>> +
>> +       session = g_try_malloc0(sizeof(struct gobexhlp_session));
>> +       if (session == NULL)
>> +               return NULL;
>> +
>> +       if (srcstr == NULL)
>> +               bacpy(&src, BDADDR_ANY);
>> +       else
>> +               str2ba(srcstr, &src);
>> +
>> +       str2ba(dststr, &dst);
>> +       channel = get_ftp_channel(&src, &dst);
>> +
>> +       if (channel == 0)
>> +               return NULL;
>
> Currently you are not checking for L2CAP psm just RFCOMM channel so
> the code bellow would never be used.
>

In client/bluetooth.c these lines (in search_callback):

		data = sdp_data_get(rec, 0x0200);
		/* PSM must be odd and lsb of upper byte must be 0 */
		if (data != NULL && (data->val.uint16 & 0x0101) == 0x0001)
			ch = data->val.uint16;

Are responsible for L2CAP psm, right?

>> +       if (channel > 31)
>> +               session->io = bt_io_connect(BT_IO_L2CAP, bt_io_callback,
>> +                               session, NULL, &session->err,
>> +                               BT_IO_OPT_SOURCE_BDADDR, &src,
>> +                               BT_IO_OPT_DEST_BDADDR, &dst,
>> +                               BT_IO_OPT_PSM, channel,
>> +                               BT_IO_OPT_MODE, BT_IO_MODE_ERTM,
>> +                               BT_IO_OPT_OMTU, BT_TX_MTU,
>> +                               BT_IO_OPT_IMTU, BT_RX_MTU,
>> +                               BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
>> +                               BT_IO_OPT_INVALID);
>> +       else
>> +               session->io = bt_io_connect(BT_IO_RFCOMM, bt_io_callback,
>> +                               session, NULL, &session->err,
>> +                               BT_IO_OPT_SOURCE_BDADDR, &src,
>> +                               BT_IO_OPT_DEST_BDADDR, &dst,
>> +                               BT_IO_OPT_CHANNEL, channel,
>> +                               BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
>> +                               BT_IO_OPT_INVALID);
>> +
>> +       if (session->err != NULL)
>> +               return NULL;
>> +
>> +       session->file_stat = g_hash_table_new_full( g_str_hash, g_str_equal,
>> +                                       g_free, g_free);
>> +       session->setpath = g_strdup("/");
>> +
>> +       gobexhlp_mutex = g_mutex_new();
>> +       gobexhlp_cond = g_cond_new();
>> +
>> +       return session;
>> +}
>> +
>> +void gobexhlp_disconnect(struct gobexhlp_session* session)
>> +{
>> +       if (session == NULL)
>> +               return;
>> +
>> +       g_obex_unref(session->obex);
>> +       g_free(session->io);
>> +
>> +       g_hash_table_remove_all(session->file_stat);
>> +       g_list_free_full(session->lsfiles, g_free);
>> +       g_free(session->setpath);
>> +
>> +       g_mutex_free(gobexhlp_mutex);
>> +       g_cond_free(gobexhlp_cond);
>> +
>> +       g_free(session);
>> +}
>> diff --git a/fuse/helpers.h b/fuse/helpers.h
>> index 142403f..29dc6cf 100644
>> --- a/fuse/helpers.h
>> +++ b/fuse/helpers.h
>> @@ -46,3 +46,7 @@ struct gobexhlp_session {
>>         int status;
>>         GError *err;
>>  };
>> +
>> +struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
>> +                                               const char *dstsrc);
>> +void gobexhlp_disconnect(struct gobexhlp_session* session);
>> diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
>> index fe4f4da..79eb990 100644
>> --- a/fuse/obexfuse.c
>> +++ b/fuse/obexfuse.c
>> @@ -33,6 +33,10 @@
>>
>>  #include "helpers.h"
>>
>> +struct gobexhlp_session* session = NULL;
>> +static GMainLoop *main_loop;
>> +static GThread *main_gthread;
>> +
>>  struct options {
>>         char* dststr;
>>         char* srcstr;
>> @@ -60,7 +64,34 @@ static struct fuse_opt obexfuse_opts[] =
>>         FUSE_OPT_END
>>  };
>>
>> +gpointer main_loop_func(gpointer user_data)
>> +{
>> +       main_loop = g_main_loop_new(NULL, FALSE);
>> +       g_main_loop_run(main_loop);
>> +
>> +       return 0;
>> +}
>> +
>> +void* obexfuse_init(struct fuse_conn_info *conn)
>> +{
>> +       main_gthread = g_thread_create(main_loop_func, NULL, TRUE, NULL);
>> +
>> +       conn->async_read = 0;
>> +       conn->want &= ~FUSE_CAP_ASYNC_READ;
>> +
>> +       return 0;
>> +}
>> +
>> +void obexfuse_destroy()
>> +{
>> +       gobexhlp_disconnect(session);
>> +       g_main_loop_quit(main_loop);
>> +       g_thread_join(main_gthread);
>> +}
>> +
>>  static struct fuse_operations obexfuse_oper = {
>> +       .init = obexfuse_init,
>> +       .destroy = obexfuse_destroy,
>>  };
>>
>>  static int obexfuse_opt_proc(void *data, const char *arg, int key,
>> @@ -111,6 +142,15 @@ int main(int argc, char *argv[])
>>
>>         g_thread_init(NULL);
>>
>
> I would suggest not mixing gobex prefix with your helper functions, in
> fact it is probably fine to just use obexfuse e.g. obexfuse_connect.
>

Right, when I was removing 'g' from gobexfuse I forgot to change
gobexhlp to obexhlp.

I'll send RFC v3 after LinuxCon :)

>> +       session = gobexhlp_connect(options.srcstr, options.dststr);
>> +       if (session == NULL || session->io == NULL) {
>> +               g_printerr("Connection to %s failed\n", options.dststr);
>> +               gobexhlp_disconnect(session);
>> +               return -EHOSTUNREACH;
>> +       } else {
>> +               g_print("Connected\nMounting %s\n", options.dststr);
>> +       }
>> +
>>         fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
>>         retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
>>
>> --
>> 1.7.8.6
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>
> --
> Luiz Augusto von Dentz

Thanks,
Michal

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

* Re: [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation
  2012-11-01 21:59     ` Michał Poczwardowski
@ 2012-11-20 17:52       ` Michał Poczwardowski
  0 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-11-20 17:52 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

Sorry for delay - I was a little overwhelmed by university stuff. I've
just replaced suspend/resume with g_main_context_iteration() but
unfortunately it doesn't work in this case.

Regarding requests queue - fuse handles it, also in single threaded mode :)


On 1 November 2012 22:59, Michał Poczwardowski <dmp0x7c5@gmail.com> wrote:
> Hi Luiz,
>
> On 30 October 2012 10:35, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
>> Hi Michal,
>>
>> On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
>> <dmp0x7c5@gmail.com> wrote:
>>> ---
>>>  fuse/helpers.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  1 files changed, 108 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/fuse/helpers.c b/fuse/helpers.c
>>> index 856e1d5..1b8082f 100644
>>> --- a/fuse/helpers.c
>>> +++ b/fuse/helpers.c
>>> @@ -273,3 +273,111 @@ void gobexhlp_disconnect(struct gobexhlp_session* session)
>>>
>>>         g_free(session);
>>>  }
>>> +
>>> +void request_new(struct gobexhlp_session *session,
>>> +                                       gchar *name)
>>> +{
>>> +       g_print("REQUEST %s\n", name);
>>> +
>>> +       if (session->request != NULL)
>>> +               g_error("Another request (%s) active!\n",
>>> +                                       session->request->name);
>>> +
>>> +       session->status = 0;
>>> +       session->request = g_malloc0(sizeof(struct gobexhlp_request));
>>> +       session->request->name = name;
>>> +
>>> +       /*
>>> +        * suspend/resume operations recreates g_io_add_watch(),
>>> +        * it fixes obex->io freeze during transfer
>>> +        */
>>> +       g_obex_suspend(session->obex);
>>> +       g_obex_resume(session->obex);
>>
>> It seems the issue here is that the mainloop is blocked then you have
>> to force the io checking by doing g_io_add_watch in a different
>> thread, we have dealt with this kind of problem before using
>> g_main_context_iteration. I would have been better if fuse supported
>> async io, but apparently all operations are blocking.
>>
>> --
>> Luiz Augusto von Dentz
>
> I'll try g_main_context_iteration way to avoid the io freeze.
> Unfortunately fuse with obex should use blocking operations.
>
> Thanks,
> Michal

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

end of thread, other threads:[~2012-11-20 17:52 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-28  0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 02/11] build: Add --enable-fuse for obexfuse Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers Michał Poczwardowski
2012-10-30  9:08   ` Luiz Augusto von Dentz
2012-11-01 22:33     ` Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
2012-10-30  9:35   ` Luiz Augusto von Dentz
2012-11-01 21:59     ` Michał Poczwardowski
2012-11-20 17:52       ` Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 05/11] fuse: Add readdir operation Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 06/11] fuse: Add getattr operation Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 07/11] fuse: Add open and read operations plus location helpers Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 08/11] fuse: Add write operation Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 09/11] fuse: Add touch operation Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 10/11] fuse: Add unlink/rmdir operation Michał Poczwardowski
2012-10-28  0:29 ` [RFC v2 obexd 11/11] fuse: Add rename operation Michał Poczwardowski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.