Linux bluetooth development
 help / color / mirror / Atom feed
* [RFC V3 04/12] adapter: Add force dir creation to convert_file()
From: Frédéric Danis @ 2012-11-30 14:46 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354286826-24016-1-git-send-email-frederic.danis@linux.intel.com>

Some device information, like class or device id, should only be
converted if directory for this device has already been created
during previous conversion (from aliases, trusts, blocked, ...
files).
---
 src/adapter.c |   33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 8e3251b..a976793 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -34,6 +34,7 @@
 #include <stdbool.h>
 #include <sys/ioctl.h>
 #include <sys/file.h>
+#include <sys/stat.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/uuid.h>
@@ -2526,6 +2527,7 @@ static void convert_names_entry(char *key, char *value, void *user_data)
 struct device_converter {
 	char *address;
 	void (*cb)(GKeyFile *key_file, void *value);
+	gboolean force;
 };
 
 static void convert_aliases_entry(GKeyFile *key_file, void *value)
@@ -2601,6 +2603,19 @@ static void convert_entry(char *key, char *value, void *user_data)
 	if (bachk(key) != 0)
 		return;
 
+	if (converter->force == FALSE) {
+		struct stat st;
+		int err;
+
+		snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s",
+				converter->address, key);
+		filename[PATH_MAX] = '\0';
+
+		err = stat(filename, &st);
+		if (err || !S_ISDIR(st.st_mode))
+			return;
+	}
+
 	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
 			converter->address, key);
 	filename[PATH_MAX] = '\0';
@@ -2621,7 +2636,8 @@ static void convert_entry(char *key, char *value, void *user_data)
 }
 
 static void convert_file(char *file, char *address,
-				void (*cb)(GKeyFile *key_file, void *value))
+				void (*cb)(GKeyFile *key_file, void *value),
+				gboolean force)
 {
 	char filename[PATH_MAX + 1];
 	struct device_converter converter;
@@ -2636,6 +2652,7 @@ static void convert_file(char *file, char *address,
 	} else {
 		converter.address = address;
 		converter.cb = cb;
+		converter.force = force;
 
 		textfile_foreach(filename, convert_entry, &converter);
 		textfile_put(filename, "converted", "yes");
@@ -2665,19 +2682,19 @@ static void convert_device_storage(struct btd_adapter *adapter)
 	free(str);
 
 	/* Convert aliases */
-	convert_file("aliases", address, convert_aliases_entry);
+	convert_file("aliases", address, convert_aliases_entry, TRUE);
 
 	/* Convert trusts */
-	convert_file("trusts", address, convert_trusts_entry);
-
-	/* Convert classes */
-	convert_file("classes", address, convert_classes_entry);
+	convert_file("trusts", address, convert_trusts_entry, TRUE);
 
 	/* Convert blocked */
-	convert_file("blocked", address, convert_blocked_entry);
+	convert_file("blocked", address, convert_blocked_entry, TRUE);
+
+	/* Convert classes */
+	convert_file("classes", address, convert_classes_entry, FALSE);
 
 	/* Convert device ids */
-	convert_file("did", address, convert_did_entry);
+	convert_file("did", address, convert_did_entry, FALSE);
 }
 
 static void convert_config(struct btd_adapter *adapter, const char *filename,
-- 
1.7.9.5


^ permalink raw reply related

* [RFC V3 05/12] adapter: Convert device type
From: Frédéric Danis @ 2012-11-30 14:46 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354286826-24016-1-git-send-email-frederic.danis@linux.intel.com>

Each time an entry is converted, check device technology and
update device info file
---
 src/adapter.c |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index a976793..c5e856d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2530,6 +2530,44 @@ struct device_converter {
 	gboolean force;
 };
 
+static void set_device_type(GKeyFile *key_file, char type)
+{
+	char *techno;
+	char *addr_type = NULL;
+	char *str;
+
+	switch (type) {
+	case BDADDR_BREDR:
+		techno = "BR/EDR";
+		break;
+	case BDADDR_LE_PUBLIC:
+		techno = "LE";
+		addr_type = "public";
+		break;
+	case BDADDR_LE_RANDOM:
+		techno = "LE";
+		addr_type = "static";
+		break;
+	default:
+		return;
+	}
+
+	str = g_key_file_get_string(key_file, "General",
+					"SupportedTechnologies", NULL);
+	if (!str)
+		g_key_file_set_string(key_file, "General",
+					"SupportedTechnologies", techno);
+	else if (!strstr(str, techno))
+		g_key_file_set_string(key_file, "General",
+					"SupportedTechnologies", "BR/EDR;LE");
+
+	g_free(str);
+
+	if (addr_type)
+		g_key_file_set_string(key_file, "General", "AddressType",
+					addr_type);
+}
+
 static void convert_aliases_entry(GKeyFile *key_file, void *value)
 {
 	g_key_file_set_string(key_file, "General", "Alias", value);
@@ -2592,13 +2630,16 @@ static void convert_did_entry(GKeyFile *key_file, void *value)
 static void convert_entry(char *key, char *value, void *user_data)
 {
 	struct device_converter *converter = user_data;
+	char device_type = -1;
 	char filename[PATH_MAX + 1];
 	GKeyFile *key_file;
 	char *data;
 	gsize length = 0;
 
-	if (key[17] == '#')
+	if (key[17] == '#') {
 		key[17] = '\0';
+		device_type = key[18] - '0';
+	}
 
 	if (bachk(key) != 0)
 		return;
@@ -2622,6 +2663,10 @@ static void convert_entry(char *key, char *value, void *user_data)
 
 	key_file = g_key_file_new();
 	g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+	if (device_type >= 0)
+		set_device_type(key_file, device_type);
+
 	converter->cb(key_file, value);
 
 	data = g_key_file_to_data(key_file, &length, NULL);
-- 
1.7.9.5


^ permalink raw reply related

* [RFC V3 06/12] adapter: Load devices from new storage architecture
From: Frédéric Danis @ 2012-11-30 14:47 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354286826-24016-1-git-send-email-frederic.danis@linux.intel.com>

Parse storage directory and create devices from device sub-directories.

Remove create device from 'blocked' file, this is already converted.
---
 src/adapter.c |   50 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 19 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index c5e856d..f3b1c5d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -35,6 +35,7 @@
 #include <sys/ioctl.h>
 #include <sys/file.h>
 #include <sys/stat.h>
+#include <dirent.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/uuid.h>
@@ -1893,23 +1894,6 @@ static void create_stored_device_from_ltks(char *key, char *value,
 	}
 }
 
-static void create_stored_device_from_blocked(char *key, char *value,
-							void *user_data)
-{
-	struct btd_adapter *adapter = user_data;
-	struct btd_device *device;
-
-	if (g_slist_find_custom(adapter->devices,
-				key, (GCompareFunc) device_address_cmp))
-		return;
-
-	device = device_create(adapter, key, BDADDR_BREDR);
-	if (device) {
-		device_set_temporary(device, FALSE);
-		adapter->devices = g_slist_append(adapter->devices, device);
-	}
-}
-
 static GSList *string_to_primary_list(char *str)
 {
 	GSList *l = NULL;
@@ -1997,6 +1981,8 @@ static void load_devices(struct btd_adapter *adapter)
 	char srcaddr[18];
 	struct adapter_keys keys = { adapter, NULL };
 	int err;
+	DIR *dir;
+	struct dirent *entry;
 
 	ba2str(&adapter->bdaddr, srcaddr);
 
@@ -2030,8 +2016,34 @@ static void load_devices(struct btd_adapter *adapter)
 	g_slist_free_full(keys.keys, smp_key_free);
 	keys.keys = NULL;
 
-	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "blocked");
-	textfile_foreach(filename, create_stored_device_from_blocked, adapter);
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s", srcaddr);
+	filename[PATH_MAX] = '\0';
+
+	dir = opendir(filename);
+	if (!dir) {
+		error("Unable to open adapter storage directory: %s", filename);
+		return;
+	}
+
+	while ((entry = readdir(dir)) != NULL) {
+		struct btd_device *device;
+
+		if (entry->d_type != DT_DIR || bachk(entry->d_name) < 0)
+			continue;
+
+		if (g_slist_find_custom(adapter->devices, entry->d_name,
+					(GCompareFunc) device_address_cmp))
+			continue;
+
+		device = device_create(adapter, entry->d_name, BDADDR_BREDR);
+		if (!device)
+			continue;
+
+		device_set_temporary(device, FALSE);
+		adapter->devices = g_slist_append(adapter->devices, device);
+	}
+
+	closedir(dir);
 }
 
 int btd_adapter_block_address(struct btd_adapter *adapter,
-- 
1.7.9.5


^ permalink raw reply related

* [RFC V3 07/12] adapter: Convert storage linkkeys file
From: Frédéric Danis @ 2012-11-30 14:47 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354286826-24016-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/adapter.c |   31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index f3b1c5d..bf20580 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2639,6 +2639,34 @@ static void convert_did_entry(GKeyFile *key_file, void *value)
 	g_key_file_set_integer(key_file, "DeviceID", "Version", val);
 }
 
+static void convert_linkkey_entry(GKeyFile *key_file, void *value)
+{
+	char *type_str, *length_str, *str;
+	gint val;
+
+	type_str = strchr(value, ' ');
+	if (!type_str)
+		return;
+
+	*(type_str++) = 0;
+
+	length_str = strchr(type_str, ' ');
+	if (!length_str)
+		return;
+
+	*(length_str++) = 0;
+
+	str = g_strconcat("0x", value, NULL);
+	g_key_file_set_string(key_file, "LinkKey", "Key", str);
+	g_free(str);
+
+	val = strtol(type_str, NULL, 16);
+	g_key_file_set_integer(key_file, "LinkKey", "Type", val);
+
+	val = strtol(length_str, NULL, 16);
+	g_key_file_set_integer(key_file, "LinkKey", "PINLength", val);
+}
+
 static void convert_entry(char *key, char *value, void *user_data)
 {
 	struct device_converter *converter = user_data;
@@ -2747,6 +2775,9 @@ static void convert_device_storage(struct btd_adapter *adapter)
 	/* Convert blocked */
 	convert_file("blocked", address, convert_blocked_entry, TRUE);
 
+	/* Convert linkkeys */
+	convert_file("linkkeys", address, convert_linkkey_entry, TRUE);
+
 	/* Convert classes */
 	convert_file("classes", address, convert_classes_entry, FALSE);
 
-- 
1.7.9.5


^ permalink raw reply related

* [RFC V3 08/12] adapter: Upload link keys from new storage
From: Frédéric Danis @ 2012-11-30 14:47 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354286826-24016-1-git-send-email-frederic.danis@linux.intel.com>

Remove read_link_key() from device_create, this moves to load_devices.
---
 src/adapter.c |  110 +++++++++++++++++++++++++--------------------------------
 src/device.c  |    6 ----
 2 files changed, 49 insertions(+), 67 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index bf20580..17f478c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1766,31 +1766,26 @@ static int str2buf(const char *str, uint8_t *buf, size_t blen)
 	return 0;
 }
 
-static struct link_key_info *get_key_info(const char *addr, const char *value)
+static struct link_key_info *get_key_info(GKeyFile *key_file, const char *peer)
 {
-	struct link_key_info *info;
-	char tmp[3];
-	long int l;
+	struct link_key_info *info = NULL;
+	char *str;
 
-	if (strlen(value) < 36) {
-		error("Unexpectedly short (%zu) link key line", strlen(value));
-		return NULL;
-	}
+	str = g_key_file_get_string(key_file, "LinkKey", "Key", NULL);
+	if (!str || strlen(str) != 34)
+		goto failed;
 
 	info = g_new0(struct link_key_info, 1);
 
-	str2ba(addr, &info->bdaddr);
-
-	str2buf(value, info->key, sizeof(info->key));
+	str2ba(peer, &info->bdaddr);
+	str2buf(&str[2], info->key, sizeof(info->key));
 
-	memcpy(tmp, value + 33, 2);
-	info->type = (uint8_t) strtol(tmp, NULL, 10);
+	info->type = g_key_file_get_integer(key_file, "LinkKey", "Type", NULL);
+	info->pin_len = g_key_file_get_integer(key_file, "LinkKey", "PINLength",
+						NULL);
 
-	memcpy(tmp, value + 35, 2);
-	l = strtol(tmp, NULL, 10);
-	if (l < 0)
-		l = 0;
-	info->pin_len = l;
+failed:
+	g_free(str);
 
 	return info;
 }
@@ -1831,34 +1826,6 @@ static struct smp_ltk_info *get_ltk_info(const char *addr, uint8_t bdaddr_type,
 	return ltk;
 }
 
-static void create_stored_device_from_linkkeys(char *key, char *value,
-							void *user_data)
-{
-	char address[18];
-	uint8_t bdaddr_type;
-	struct adapter_keys *keys = user_data;
-	struct btd_adapter *adapter = keys->adapter;
-	struct btd_device *device;
-	struct link_key_info *info;
-
-	if (sscanf(key, "%17s#%hhu", address, &bdaddr_type) < 2)
-		bdaddr_type = BDADDR_BREDR;
-
-	info = get_key_info(address, value);
-	if (info)
-		keys->keys = g_slist_append(keys->keys, info);
-
-	if (g_slist_find_custom(adapter->devices, address,
-					(GCompareFunc) device_address_cmp))
-		return;
-
-	device = device_create(adapter, address, bdaddr_type);
-	if (device) {
-		device_set_temporary(device, FALSE);
-		adapter->devices = g_slist_append(adapter->devices, device);
-	}
-}
-
 static void create_stored_device_from_ltks(char *key, char *value,
 							void *user_data)
 {
@@ -1994,18 +1961,6 @@ static void load_devices(struct btd_adapter *adapter)
 	textfile_foreach(filename, create_stored_device_from_primaries,
 								adapter);
 
-	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "linkkeys");
-	textfile_foreach(filename, create_stored_device_from_linkkeys, &keys);
-
-	err = mgmt_load_link_keys(adapter->dev_id, keys.keys,
-							main_opts.debug_keys);
-	if (err < 0)
-		error("Unable to load link keys: %s (%d)",
-							strerror(-err), -err);
-
-	g_slist_free_full(keys.keys, g_free);
-	keys.keys = NULL;
-
 	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "longtermkeys");
 	textfile_foreach(filename, create_stored_device_from_ltks, &keys);
 
@@ -2027,13 +1982,32 @@ static void load_devices(struct btd_adapter *adapter)
 
 	while ((entry = readdir(dir)) != NULL) {
 		struct btd_device *device;
+		char filename[PATH_MAX + 1];
+		GKeyFile *key_file;
+		struct link_key_info *key_info;
+		GSList *l;
 
 		if (entry->d_type != DT_DIR || bachk(entry->d_name) < 0)
 			continue;
 
-		if (g_slist_find_custom(adapter->devices, entry->d_name,
-					(GCompareFunc) device_address_cmp))
-			continue;
+		snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", srcaddr,
+				entry->d_name);
+
+		key_file = g_key_file_new();
+		g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+		key_info = get_key_info(key_file, entry->d_name);
+		if (key_info)
+			keys.keys = g_slist_append(keys.keys, key_info);
+
+		g_key_file_free(key_file);
+
+		l = g_slist_find_custom(adapter->devices, entry->d_name,
+					(GCompareFunc) device_address_cmp);
+		if (l) {
+			device = l->data;
+			goto device_exist;
+		}
 
 		device = device_create(adapter, entry->d_name, BDADDR_BREDR);
 		if (!device)
@@ -2041,9 +2015,23 @@ static void load_devices(struct btd_adapter *adapter)
 
 		device_set_temporary(device, FALSE);
 		adapter->devices = g_slist_append(adapter->devices, device);
+
+device_exist:
+		if (key_info) {
+			device_set_paired(device, TRUE);
+			device_set_bonded(device, TRUE);
+		}
 	}
 
 	closedir(dir);
+
+	err = mgmt_load_link_keys(adapter->dev_id, keys.keys,
+							main_opts.debug_keys);
+	if (err < 0)
+		error("Unable to load link keys: %s (%d)",
+							strerror(-err), -err);
+
+	g_slist_free_full(keys.keys, g_free);
 }
 
 int btd_adapter_block_address(struct btd_adapter *adapter,
diff --git a/src/device.c b/src/device.c
index 1db8a48..bb5689b 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1904,12 +1904,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 
 	load_info(device, srcaddr, address);
 
-	if (read_link_key(src, &device->bdaddr, device->bdaddr_type, NULL,
-								NULL) == 0) {
-		device_set_paired(device, TRUE);
-		device_set_bonded(device, TRUE);
-	}
-
 	if (device_is_le(device) && has_longtermkeys(src, &device->bdaddr,
 							device->bdaddr_type)) {
 		device_set_paired(device, TRUE);
-- 
1.7.9.5


^ permalink raw reply related

* [RFC V3 09/12] event: Store link key infos in device info file
From: Frédéric Danis @ 2012-11-30 14:47 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354286826-24016-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/event.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 47 insertions(+), 12 deletions(-)

diff --git a/src/event.c b/src/event.c
index 7fc8f02..5e83c09 100644
--- a/src/event.c
+++ b/src/event.c
@@ -354,33 +354,68 @@ static int store_longtermkey(bdaddr_t *local, bdaddr_t *peer,
 	return err;
 }
 
+static void store_link_key(struct btd_adapter *adapter,
+				struct btd_device *device, uint8_t *key,
+				uint8_t type, uint8_t pin_length)
+{
+	char adapter_addr[18];
+	char device_addr[18];
+	char filename[PATH_MAX + 1];
+	GKeyFile *key_file;
+	char key_str[35];
+	char *str;
+	int i;
+	gsize length = 0;
+
+	ba2str(adapter_get_address(adapter), adapter_addr);
+	ba2str(device_get_address(device), device_addr);
+
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
+								device_addr);
+	filename[PATH_MAX] = '\0';
+
+	key_file = g_key_file_new();
+	g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+	key_str[0] = '0';
+	key_str[1] = 'x';
+	for (i = 0; i < 16; i++)
+		sprintf(key_str + 2 + (i * 2), "%2.2X", key[i]);
+
+	g_key_file_set_string(key_file, "LinkKey", "Key", key_str);
+
+	g_key_file_set_integer(key_file, "LinkKey", "Type", type);
+	g_key_file_set_integer(key_file, "LinkKey", "PINLength", pin_length);
+
+	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+	str = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(filename, str, length, NULL);
+	g_free(str);
+
+	g_key_file_free(key_file);
+}
+
 int btd_event_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
 				uint8_t *key, uint8_t key_type,
 				uint8_t pin_length)
 {
 	struct btd_adapter *adapter;
 	struct btd_device *device;
-	uint8_t peer_type;
-	int ret;
 
 	if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
 		return -ENODEV;
 
 	DBG("storing link key of type 0x%02x", key_type);
 
-	peer_type = device_get_addr_type(device);
+	store_link_key(adapter, device, key, key_type, pin_length);
 
-	ret = write_link_key(local, peer, peer_type, key, key_type,
-								pin_length);
+	device_set_bonded(device, TRUE);
 
-	if (ret == 0) {
-		device_set_bonded(device, TRUE);
-
-		if (device_is_temporary(device))
-			device_set_temporary(device, FALSE);
-	}
+	if (device_is_temporary(device))
+		device_set_temporary(device, FALSE);
 
-	return ret;
+	return 0;
 }
 
 int btd_event_ltk_notify(bdaddr_t *local, bdaddr_t *peer, uint8_t bdaddr_type,
-- 
1.7.9.5


^ permalink raw reply related

* [RFC V3 10/12] adapter: Convert storage longtermkeys file
From: Frédéric Danis @ 2012-11-30 14:47 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354286826-24016-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/adapter.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 17f478c..ff9d2e7 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2655,6 +2655,46 @@ static void convert_linkkey_entry(GKeyFile *key_file, void *value)
 	g_key_file_set_integer(key_file, "LinkKey", "PINLength", val);
 }
 
+static void convert_ltk_entry(GKeyFile *key_file, void *value)
+{
+	char *auth_str, *rand_str, *str;
+	int i, ret;
+	unsigned char auth, master, enc_size;
+	unsigned short ediv;
+
+	auth_str = strchr(value, ' ');
+	if (!auth_str)
+		return;
+
+	*(auth_str++) = 0;
+
+	for (i = 0, rand_str = auth_str; i < 4; i++) {
+		rand_str = strchr(rand_str, ' ');
+		if (!rand_str || rand_str[1] == '\0')
+			return;
+
+		rand_str++;
+	}
+
+	ret = sscanf(auth_str, " %hhd %hhd %hhd %hd", &auth, &master,
+							&enc_size, &ediv);
+	if (ret < 4)
+		return;
+
+	str = g_strconcat("0x", value, NULL);
+	g_key_file_set_string(key_file, "LongTermKey", "Key", str);
+	g_free(str);
+
+	g_key_file_set_integer(key_file, "LongTermKey", "Authenticated", auth);
+	g_key_file_set_integer(key_file, "LongTermKey", "Master", master);
+	g_key_file_set_integer(key_file, "LongTermKey", "EncSize", enc_size);
+	g_key_file_set_integer(key_file, "LongTermKey", "EDiv", ediv);
+
+	str = g_strconcat("0x", rand_str, NULL);
+	g_key_file_set_string(key_file, "LongTermKey", "Rand", str);
+	g_free(str);
+}
+
 static void convert_entry(char *key, char *value, void *user_data)
 {
 	struct device_converter *converter = user_data;
@@ -2766,6 +2806,9 @@ static void convert_device_storage(struct btd_adapter *adapter)
 	/* Convert linkkeys */
 	convert_file("linkkeys", address, convert_linkkey_entry, TRUE);
 
+	/* Convert longtermkeys */
+	convert_file("longtermkeys", address, convert_ltk_entry, TRUE);
+
 	/* Convert classes */
 	convert_file("classes", address, convert_classes_entry, FALSE);
 
-- 
1.7.9.5


^ permalink raw reply related

* [RFC V3 11/12] adapter: Upload long term keys from new storage
From: Frédéric Danis @ 2012-11-30 14:47 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354286826-24016-1-git-send-email-frederic.danis@linux.intel.com>

Remove check of long term keys from device_create,
this moves to load_devices.
---
 src/adapter.c |  127 +++++++++++++++++++++++----------------------------------
 src/device.c  |    6 ---
 2 files changed, 51 insertions(+), 82 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index ff9d2e7..a0ae04c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1790,77 +1790,57 @@ failed:
 	return info;
 }
 
-static struct smp_ltk_info *get_ltk_info(const char *addr, uint8_t bdaddr_type,
-							const char *value)
+static struct smp_ltk_info *get_ltk_info(GKeyFile *key_file, const char *peer)
 {
-	struct smp_ltk_info *ltk;
-	char *ptr;
-	int i, ret;
+	struct smp_ltk_info *ltk = NULL;
+	char *key;
+	char *rand = NULL;
+	char *type = NULL;
+	uint8_t bdaddr_type;
 
-	if (strlen(value) < 60) {
-		error("Unexpectedly short (%zu) LTK", strlen(value));
-		return NULL;
-	}
+	key = g_key_file_get_string(key_file, "LongTermKey", "Key", NULL);
+	if (!key || strlen(key) != 34)
+		goto failed;
 
-	ltk = g_new0(struct smp_ltk_info, 1);
+	rand = g_key_file_get_string(key_file, "LongTermKey", "Rand", NULL);
+	if (!rand || strlen(rand) != 18)
+		goto failed;
 
-	str2ba(addr, &ltk->bdaddr);
+	type = g_key_file_get_string(key_file, "General", "AddressType", NULL);
+	if (!type)
+		goto failed;
 
-	ltk->bdaddr_type = bdaddr_type;
+	if (g_str_equal(type, "public"))
+		bdaddr_type = BDADDR_LE_PUBLIC;
+	else if (g_str_equal(type, "static"))
+		bdaddr_type = BDADDR_LE_RANDOM;
+	else
+		goto failed;
 
-	str2buf(value, ltk->val, sizeof(ltk->val));
+	ltk = g_new0(struct smp_ltk_info, 1);
 
-	ptr = (char *) value + 2 * sizeof(ltk->val) + 1;
+	str2ba(peer, &ltk->bdaddr);
+	ltk->bdaddr_type = bdaddr_type;
+	str2buf(&key[2], ltk->val, sizeof(ltk->val));
+	str2buf(&rand[2], ltk->rand, sizeof(ltk->rand));
 
-	ret = sscanf(ptr, " %hhd %hhd %hhd %hd %n",
-		     &ltk->authenticated, &ltk->master, &ltk->enc_size,
-							&ltk->ediv, &i);
-	if (ret < 2) {
-		g_free(ltk);
-		return NULL;
-	}
-	ptr += i;
+	ltk->authenticated = g_key_file_get_integer(key_file, "LongTermKey",
+							"Authenticated", NULL);
+	ltk->master = g_key_file_get_integer(key_file, "LongTermKey", "Master",
+						NULL);
+	ltk->enc_size = g_key_file_get_integer(key_file, "LongTermKey",
+						"EncSize", NULL);
+	ltk->ediv = g_key_file_get_integer(key_file, "LongTermKey", "EDiv",
+						NULL);
 
-	str2buf(ptr, ltk->rand, sizeof(ltk->rand));
+failed:
+	g_free(key);
+	g_free(rand);
+	g_free(type);
 
 	return ltk;
 }
 
-static void create_stored_device_from_ltks(char *key, char *value,
-							void *user_data)
-{
-	struct adapter_keys *keys = user_data;
-	struct btd_adapter *adapter = keys->adapter;
-	struct btd_device *device;
-	struct smp_ltk_info *info;
-	char address[18], srcaddr[18];
-	uint8_t bdaddr_type;
-
-	if (sscanf(key, "%17s#%hhu", address, &bdaddr_type) < 2)
-		return;
-
-	info = get_ltk_info(address, bdaddr_type, value);
-	if (info == NULL)
-		return;
-
-	keys->keys = g_slist_append(keys->keys, info);
-
-	if (g_slist_find_custom(adapter->devices, address,
-					(GCompareFunc) device_address_cmp))
-		return;
-
-	ba2str(&adapter->bdaddr, srcaddr);
-
-	if (g_strcmp0(srcaddr, address) == 0)
-		return;
-
-	device = device_create(adapter, address, bdaddr_type);
-	if (device) {
-		device_set_temporary(device, FALSE);
-		adapter->devices = g_slist_append(adapter->devices, device);
-	}
-}
-
 static GSList *string_to_primary_list(char *str)
 {
 	GSList *l = NULL;
@@ -1935,18 +1915,12 @@ static void create_stored_device_from_primaries(char *key, char *value,
 	g_slist_free(uuids);
 }
 
-static void smp_key_free(void *data)
-{
-	struct smp_ltk_info *info = data;
-
-	g_free(info);
-}
-
 static void load_devices(struct btd_adapter *adapter)
 {
 	char filename[PATH_MAX + 1];
 	char srcaddr[18];
 	struct adapter_keys keys = { adapter, NULL };
+	struct adapter_keys ltks = { adapter, NULL };
 	int err;
 	DIR *dir;
 	struct dirent *entry;
@@ -1961,16 +1935,6 @@ static void load_devices(struct btd_adapter *adapter)
 	textfile_foreach(filename, create_stored_device_from_primaries,
 								adapter);
 
-	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "longtermkeys");
-	textfile_foreach(filename, create_stored_device_from_ltks, &keys);
-
-	err = mgmt_load_ltks(adapter->dev_id, keys.keys);
-	if (err < 0)
-		error("Unable to load ltks: %s (%d)", strerror(-err), -err);
-
-	g_slist_free_full(keys.keys, smp_key_free);
-	keys.keys = NULL;
-
 	snprintf(filename, PATH_MAX, STORAGEDIR "/%s", srcaddr);
 	filename[PATH_MAX] = '\0';
 
@@ -1985,6 +1949,7 @@ static void load_devices(struct btd_adapter *adapter)
 		char filename[PATH_MAX + 1];
 		GKeyFile *key_file;
 		struct link_key_info *key_info;
+		struct smp_ltk_info *ltk_info;
 		GSList *l;
 
 		if (entry->d_type != DT_DIR || bachk(entry->d_name) < 0)
@@ -2000,6 +1965,10 @@ static void load_devices(struct btd_adapter *adapter)
 		if (key_info)
 			keys.keys = g_slist_append(keys.keys, key_info);
 
+		ltk_info = get_ltk_info(key_file, entry->d_name);
+		if (ltk_info)
+			ltks.keys = g_slist_append(ltks.keys, ltk_info);
+
 		g_key_file_free(key_file);
 
 		l = g_slist_find_custom(adapter->devices, entry->d_name,
@@ -2017,7 +1986,7 @@ static void load_devices(struct btd_adapter *adapter)
 		adapter->devices = g_slist_append(adapter->devices, device);
 
 device_exist:
-		if (key_info) {
+		if (key_info || ltk_info) {
 			device_set_paired(device, TRUE);
 			device_set_bonded(device, TRUE);
 		}
@@ -2032,6 +2001,12 @@ device_exist:
 							strerror(-err), -err);
 
 	g_slist_free_full(keys.keys, g_free);
+
+	err = mgmt_load_ltks(adapter->dev_id, ltks.keys);
+	if (err < 0)
+		error("Unable to load ltks: %s (%d)", strerror(-err), -err);
+
+	g_slist_free_full(ltks.keys, g_free);
 }
 
 int btd_adapter_block_address(struct btd_adapter *adapter,
diff --git a/src/device.c b/src/device.c
index bb5689b..a5bdf4c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1904,12 +1904,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 
 	load_info(device, srcaddr, address);
 
-	if (device_is_le(device) && has_longtermkeys(src, &device->bdaddr,
-							device->bdaddr_type)) {
-		device_set_paired(device, TRUE);
-		device_set_bonded(device, TRUE);
-	}
-
 	return btd_device_ref(device);
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [RFC V3 12/12] event: Store long term key infos in device info file
From: Frédéric Danis @ 2012-11-30 14:47 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354286826-24016-1-git-send-email-frederic.danis@linux.intel.com>

---
 src/event.c |   89 ++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 46 insertions(+), 43 deletions(-)

diff --git a/src/event.c b/src/event.c
index 5e83c09..61fa0f4 100644
--- a/src/event.c
+++ b/src/event.c
@@ -304,54 +304,59 @@ void btd_event_remote_name(const bdaddr_t *local, bdaddr_t *peer,
 		device_set_name(device, name);
 }
 
-static char *buf2str(uint8_t *data, int datalen)
+static void store_longtermkey(bdaddr_t *local, bdaddr_t *peer,
+				uint8_t bdaddr_type, unsigned char *key,
+				uint8_t master, uint8_t authenticated,
+				uint8_t enc_size, uint16_t ediv,
+				uint8_t rand[8])
 {
-	char *buf;
+	char adapter_addr[18];
+	char device_addr[18];
+	char filename[PATH_MAX + 1];
+	GKeyFile *key_file;
+	char key_str[35];
+	char rand_str[19];
+	char *str;
 	int i;
+	gsize length = 0;
 
-	buf = g_try_new0(char, (datalen * 2) + 1);
-	if (buf == NULL)
-		return NULL;
-
-	for (i = 0; i < datalen; i++)
-		sprintf(buf + (i * 2), "%2.2x", data[i]);
+	ba2str(local, adapter_addr);
+	ba2str(peer, device_addr);
 
-	return buf;
-}
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
+								device_addr);
+	filename[PATH_MAX] = '\0';
 
-static int store_longtermkey(bdaddr_t *local, bdaddr_t *peer,
-				uint8_t bdaddr_type, unsigned char *key,
-				uint8_t master, uint8_t authenticated,
-				uint8_t enc_size, uint16_t ediv, uint8_t rand[8])
-{
-	GString *newkey;
-	char *val, *str;
-	int err;
+	key_file = g_key_file_new();
+	g_key_file_load_from_file(key_file, filename, 0, NULL);
 
-	val = buf2str(key, 16);
-	if (val == NULL)
-		return -ENOMEM;
+	key_str[0] = '0';
+	key_str[1] = 'x';
+	for (i = 0; i < 16; i++)
+		sprintf(key_str + 2 + (i * 2), "%2.2X", key[i]);
 
-	newkey = g_string_new(val);
-	g_free(val);
+	g_key_file_set_string(key_file, "LongTermKey", "Key", key_str);
 
-	g_string_append_printf(newkey, " %d %d %d %d ", authenticated, master,
-								enc_size, ediv);
+	g_key_file_set_integer(key_file, "LongTermKey", "Authenticated",
+				authenticated);
+	g_key_file_set_integer(key_file, "LongTermKey", "Master", master);
+	g_key_file_set_integer(key_file, "LongTermKey", "EncSize", enc_size);
+	g_key_file_set_integer(key_file, "LongTermKey", "EDiv", ediv);
 
-	str = buf2str(rand, 8);
-	if (str == NULL) {
-		g_string_free(newkey, TRUE);
-		return -ENOMEM;
-	}
+	rand_str[0] = '0';
+	rand_str[1] = 'x';
+	for (i = 0; i < 8; i++)
+		sprintf(rand_str + 2 + (i * 2), "%2.2X", rand[i]);
 
-	newkey = g_string_append(newkey, str);
-	g_free(str);
+	g_key_file_set_string(key_file, "LongTermKey", "Rand", rand_str);
 
-	err = write_longtermkeys(local, peer, bdaddr_type, newkey->str);
+	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 
-	g_string_free(newkey, TRUE);
+	str = g_key_file_to_data(key_file, &length, NULL);
+	g_file_set_contents(filename, str, length, NULL);
+	g_free(str);
 
-	return err;
+	g_key_file_free(key_file);
 }
 
 static void store_link_key(struct btd_adapter *adapter,
@@ -425,21 +430,19 @@ int btd_event_ltk_notify(bdaddr_t *local, bdaddr_t *peer, uint8_t bdaddr_type,
 {
 	struct btd_adapter *adapter;
 	struct btd_device *device;
-	int ret;
 
 	if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
 		return -ENODEV;
 
-	ret = store_longtermkey(local, peer, bdaddr_type, key, master,
+	store_longtermkey(local, peer, bdaddr_type, key, master,
 					authenticated, enc_size, ediv, rand);
-	if (ret == 0) {
-		device_set_bonded(device, TRUE);
 
-		if (device_is_temporary(device))
-			device_set_temporary(device, FALSE);
-	}
+	device_set_bonded(device, TRUE);
 
-	return ret;
+	if (device_is_temporary(device))
+		device_set_temporary(device, FALSE);
+
+	return 0;
 }
 
 void btd_event_conn_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t bdaddr_type,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH] Bluetooth: Fix using locked state_change for A2MP chan
From: Andrei Emeltchenko @ 2012-11-30 14:51 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

A2MP channel do not have sk associated so use unlocked version
of state_change. chan is already locked.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2414cff..6de4287 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1276,7 +1276,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
 	}
 
 	if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
-		l2cap_state_change(chan, BT_DISCONN);
+		__l2cap_state_change(chan, BT_DISCONN);
 		return;
 	}
 
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCHv2 4/4] Bluetooth: trivial: Change NO_FCS_RECV to RECV_NO_FCS
From: Gustavo Padovan @ 2012-11-30 17:50 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1354203968-1335-4-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

* Andrei Emeltchenko <Andrei.Emeltchenko.news@gmail.com> [2012-11-29 17:46:08 +0200]:

> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> Make code more readable by changing CONF_NO_FCS_RECV which is read
> as "No L2CAP FCS option received" to CONF_RECV_NO_FCS which means
> "Received L2CAP option NO_FCS". This flag really means that we have
> received L2CAP FRAME CHECK SEQUENCE (FCS) OPTION with value "No FCS".
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  include/net/bluetooth/l2cap.h |    2 +-
>  net/bluetooth/l2cap_core.c    |   10 +++++-----
>  2 files changed, 6 insertions(+), 6 deletions(-)

All patches have been applied to bluetooth-next. Thanks.

	Gustavo

^ permalink raw reply

* [PATCH 1/4] gas: Fix memory leak at gas struct removal
From: Paulo Borges @ 2012-11-30 18:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Paulo Borges

---
 profiles/gatt/gas.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index 0e82097..e6cddad 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -64,6 +64,7 @@ static void gas_free(struct gas *gas)
 	if (gas->attioid)
 		btd_device_remove_attio_callback(gas->device, gas->attioid);
 
+	g_attrib_unref(gas->attrib);
 	btd_device_unref(gas->device);
 	g_free(gas);
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 2/4] input: Fix memory leak at hogdev struct removal
From: Paulo Borges @ 2012-11-30 18:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Paulo Borges
In-Reply-To: <1354300294-9105-1-git-send-email-paulo.borges@openbossa.org>

---
 profiles/input/hog_device.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 0a5fb58..a873eac 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -705,6 +705,7 @@ static void hog_device_free(struct hog_device *hogdev)
 {
 	btd_device_unref(hogdev->device);
 	g_slist_free_full(hogdev->reports, report_free);
+	g_attrib_unref(hogdev->attrib);
 	g_free(hogdev->hog_primary);
 	g_free(hogdev);
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 3/4] gatt: Fix memory leak in characteristic discovery
From: Paulo Borges @ 2012-11-30 18:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Paulo Borges
In-Reply-To: <1354300294-9105-1-git-send-email-paulo.borges@openbossa.org>

If the Discover Characteristics by UUID sub-procedure has been
executed and the first characteristic is not the target, a memory
leak occurs.

This commit fixes this leak by postponing the allocation to after
the UUID verification.
---
 attrib/gatt.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/attrib/gatt.c b/attrib/gatt.c
index 963fa20..b834b13 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -475,15 +475,15 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
 		} else
 			uuid = att_get_uuid128(&value[5]);
 
+		if (dc->uuid && bt_uuid_cmp(dc->uuid, &uuid))
+			break;
+
 		chars = g_try_new0(struct gatt_char, 1);
 		if (!chars) {
 			err = ATT_ECODE_INSUFF_RESOURCES;
 			goto done;
 		}
 
-		if (dc->uuid && bt_uuid_cmp(dc->uuid, &uuid))
-			break;
-
 		chars->handle = last;
 		chars->properties = value[2];
 		chars->value_handle = att_get_u16(&value[3]);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 4/4] gatt: Improve characteristics discovery
From: Paulo Borges @ 2012-11-30 18:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Paulo Borges
In-Reply-To: <1354300294-9105-1-git-send-email-paulo.borges@openbossa.org>

In the Discover Characteristics by UUID sub-procedure, if a fetched
characteristic doesn't matches with the target UUID, all others
characteristics in that response were discarded.

Because of this, the procedure will make a new request to possibly
rediscover the characteristics in the range beyond this last
characteristic.

At present, this procedure works because the gatt library will send a
Read by Type Request starting at the first attribute after the non
matching characteristic.

This commit makes the rest of the characteristics to be checked for a
matching type, which should reduce the number of requests sent during
the discovery of characteristics.
---
 attrib/gatt.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/attrib/gatt.c b/attrib/gatt.c
index b834b13..38c050e 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -476,7 +476,7 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
 			uuid = att_get_uuid128(&value[5]);
 
 		if (dc->uuid && bt_uuid_cmp(dc->uuid, &uuid))
-			break;
+			continue;
 
 		chars = g_try_new0(struct gatt_char, 1);
 		if (!chars) {
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ] input: Fix emitting a signal for a non-existant interface
From: Vinicius Costa Gomes @ 2012-11-30 23:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

When the 'org.bluez.Input' interface was removed, this should have been
removed as well, now it is causing a segmentation fault.
---
 profiles/input/device.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/profiles/input/device.c b/profiles/input/device.c
index 2871cc3..421af64 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -503,9 +503,6 @@ static int input_device_connected(struct input_device *idev)
 	if (err < 0)
 		return err;
 
-	g_dbus_emit_property_changed(idev->conn, idev->path,
-					INPUT_DEVICE_INTERFACE, "Connected");
-
 	idev->dc_id = device_add_disconnect_watch(idev->device, disconnect_cb,
 							idev, NULL);
 
-- 
1.8.0


^ permalink raw reply related

* Re: [PATCH BlueZ] input: Fix emitting a signal for a non-existant interface
From: Vinicius Gomes @ 2012-11-30 23:45 UTC (permalink / raw)
  To: BlueZ development; +Cc: Vinicius Costa Gomes
In-Reply-To: <1354318625-15066-1-git-send-email-vinicius.gomes@openbossa.org>

Hi,

On Fri, Nov 30, 2012 at 8:37 PM, Vinicius Costa Gomes
<vinicius.gomes@openbossa.org> wrote:
> When the 'org.bluez.Input' interface was removed, this should have been
> removed as well, now it is causing a segmentation fault.
> ---

Please ignore this patch. I didn't notice that the signal is emitted
in another place too. Updated version coming soon.


Cheers,
--
Vinicius

^ permalink raw reply

* [PATCH BlueZ v2 1/2] input: Fix emitting a signal for a non-existant interface
From: Vinicius Costa Gomes @ 2012-12-01  0:36 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

When the 'org.bluez.Input' interface was removed, this should have been
removed as well, now it is causing a segmentation fault.
---
 profiles/input/device.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/profiles/input/device.c b/profiles/input/device.c
index 2871cc3..7538297 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -160,9 +160,6 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data
 	if ((cond & (G_IO_HUP | G_IO_ERR)) && idev->ctrl_watch)
 		g_io_channel_shutdown(chan, TRUE, NULL);
 
-	g_dbus_emit_property_changed(idev->conn, idev->path,
-					INPUT_DEVICE_INTERFACE, "Connected");
-
 	device_remove_disconnect_watch(idev->device, idev->dc_id);
 	idev->dc_id = 0;
 
@@ -503,9 +500,6 @@ static int input_device_connected(struct input_device *idev)
 	if (err < 0)
 		return err;
 
-	g_dbus_emit_property_changed(idev->conn, idev->path,
-					INPUT_DEVICE_INTERFACE, "Connected");
-
 	idev->dc_id = device_add_disconnect_watch(idev->device, disconnect_cb,
 							idev, NULL);
 
-- 
1.8.0


^ permalink raw reply related

* [PATCH BlueZ v2 2/2] input: Remove leftovers from the Input iface removal
From: Vinicius Costa Gomes @ 2012-12-01  0:36 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1354322217-11219-1-git-send-email-vinicius.gomes@openbossa.org>

Now that the Input interface is removed, the only way to connect is
via the Profile interface, so no need to separate the way that
connection is made.
---
 profiles/input/device.c | 37 ++++++-------------------------------
 1 file changed, 6 insertions(+), 31 deletions(-)

diff --git a/profiles/input/device.c b/profiles/input/device.c
index 7538297..8464062 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -64,14 +64,8 @@
 #define FI_FLAG_CONNECTED	1
 
 struct pending_connect {
-	bool local;
-	union {
-		struct {
-			struct btd_profile *profile;
-			btd_profile_cb cb;
-		} p;
-		DBusMessage *msg;
-	};
+	struct btd_profile *profile;
+	btd_profile_cb cb;
 };
 
 struct input_device {
@@ -119,11 +113,8 @@ static void input_device_free(struct input_device *idev)
 	g_free(idev->name);
 	g_free(idev->path);
 
-	if (idev->pending) {
-		if (idev->pending->local)
-			dbus_message_unref(idev->pending->msg);
+	if (idev->pending)
 		g_free(idev->pending);
-	}
 
 	if (idev->ctrl_watch > 0)
 		g_source_remove(idev->ctrl_watch);
@@ -510,8 +501,6 @@ static void connect_reply(struct input_device *idev, int err,
 							const char *err_msg)
 {
 	struct pending_connect *pending = idev->pending;
-	DBusConnection *conn = btd_get_dbus_connection();
-	DBusMessage *reply;
 
 	if (!pending)
 		return;
@@ -521,20 +510,7 @@ static void connect_reply(struct input_device *idev, int err,
 	if (err_msg)
 		error("%s", err_msg);
 
-	if (!pending->local) {
-		pending->p.cb(pending->p.profile, idev->device, err);
-		g_free(pending);
-		return;
-	}
-
-	if (err_msg) {
-		reply = btd_error_failed(idev->pending->msg, err_msg);
-		g_dbus_send_message(conn, reply);
-	} else {
-		g_dbus_send_reply(conn, pending->msg, DBUS_TYPE_INVALID);
-	}
-
-	dbus_message_unref(pending->msg);
+	pending->cb(pending->profile, idev->device, err);
 	g_free(pending);
 }
 
@@ -667,9 +643,8 @@ int input_device_connect(struct btd_device *dev, struct btd_profile *profile,
 		return -EALREADY;
 
 	idev->pending = g_new0(struct pending_connect, 1);
-	idev->pending->local = false;
-	idev->pending->p.profile = profile;
-	idev->pending->p.cb = cb;
+	idev->pending->profile = profile;
+	idev->pending->cb = cb;
 
 	return dev_connect(idev);
 }
-- 
1.8.0


^ permalink raw reply related

* Re: [PATCH 1/4] gas: Fix memory leak at gas struct removal
From: Johan Hedberg @ 2012-12-01  9:11 UTC (permalink / raw)
  To: Paulo Borges; +Cc: linux-bluetooth
In-Reply-To: <1354300294-9105-1-git-send-email-paulo.borges@openbossa.org>

Hi Paulo,

On Fri, Nov 30, 2012, Paulo Borges wrote:
> ---
>  profiles/gatt/gas.c |    1 +
>  1 file changed, 1 insertion(+)

All four patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH BlueZ v2 1/2] input: Fix emitting a signal for a non-existant interface
From: Johan Hedberg @ 2012-12-01  9:13 UTC (permalink / raw)
  To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1354322217-11219-1-git-send-email-vinicius.gomes@openbossa.org>

Hi Vinicius,

On Fri, Nov 30, 2012, Vinicius Costa Gomes wrote:
> When the 'org.bluez.Input' interface was removed, this should have been
> removed as well, now it is causing a segmentation fault.
> ---
>  profiles/input/device.c | 6 ------
>  1 file changed, 6 deletions(-)

Both patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH BlueZ] control: Add methods FastForward and Rewind
From: Johan Hedberg @ 2012-12-01  9:25 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1354279699-1245-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Fri, Nov 30, 2012, Luiz Augusto von Dentz wrote:
> These method can be used to fast-forward and rewind the playback, their
> action will keep active until another method is called.
> 
> The commands are reapeated every 2 seconds to conform with AVC spec.
> ---
>  doc/control-api.txt      |  10 ++++
>  profiles/audio/avctp.c   | 148 ++++++++++++++++++++++++++++++++++++++++++-----
>  profiles/audio/control.c |  14 +++++
>  3 files changed, 157 insertions(+), 15 deletions(-)


Applied. Thanks.

Johan

^ permalink raw reply

* [RFC v3 obexd 01/10] fuse: Add initial obexfuse files, fuse main and options parse
From: Michał Poczwardowski @ 2012-12-01 23:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/helpers.c  |   54 +++++++++++++++++++++++++
 fuse/helpers.h  |   49 ++++++++++++++++++++++
 fuse/obexfuse.c |  119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 222 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..2dc309a
--- /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 obexhlp_request {
+	gchar *name;
+	gboolean complete;
+};
+
+struct obexhlp_location {
+	gchar *dir;
+	gchar *file;
+};
diff --git a/fuse/helpers.h b/fuse/helpers.h
new file mode 100644
index 0000000..abbdd70
--- /dev/null
+++ b/fuse/helpers.h
@@ -0,0 +1,49 @@
+/*
+ *  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 obexhlp_request;
+
+struct obexhlp_buffer {
+	void *data;
+	gsize tmpsize;
+	gsize size;
+	gboolean edited;
+};
+
+struct obexhlp_session {
+	GObex *obex;
+	uint16_t channel;
+	GList *lsfiles;
+	GIOChannel *io;
+	GHashTable *file_stat;
+	gchar *setpath;
+	struct obexhlp_request *request;
+	struct obexhlp_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

* [RFC v3 obexd 02/10] build: Add --enable-fuse for obexfuse
From: Michał Poczwardowski @ 2012-12-01 23:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1354403695-18985-1-git-send-email-dmp0x7c5@gmail.com>

---
 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 69d636f..7d0a904 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

* [RFC v3 obexd 03/10] fuse: Add obexhlp_connect/disconnect functions with helpers
From: Michał Poczwardowski @ 2012-12-01 23:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1354403695-18985-1-git-send-email-dmp0x7c5@gmail.com>

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

diff --git a/fuse/helpers.c b/fuse/helpers.c
index 2dc309a..82797d9 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -43,6 +43,9 @@
 
 #define OBEX_FTP_LS "x-obex/folder-listing"
 
+static GCond *obexhlp_cond;
+static GMutex *obexhlp_mutex;
+
 struct obexhlp_request {
 	gchar *name;
 	gboolean complete;
@@ -52,3 +55,268 @@ struct obexhlp_location {
 	gchar *dir;
 	gchar *file;
 };
+
+static volatile sig_atomic_t __sdp_io_finished = 0;
+
+/* adopted from client/bluetooth.c - search_callback() */
+static void search_callback(uint8_t type, uint16_t status,
+			uint8_t *rsp, size_t size, void *user_data)
+{
+	struct obexhlp_session *session = user_data;
+	unsigned int scanned, bytesleft = size;
+	int seqlen = 0;
+	uint8_t dataType;
+	uint16_t port = 0;
+
+	if (status || type != SDP_SVC_SEARCH_ATTR_RSP)
+		goto done;
+
+	scanned = sdp_extract_seqtype(rsp, bytesleft, &dataType, &seqlen);
+	if (!scanned || !seqlen)
+		goto done;
+
+	rsp += scanned;
+	bytesleft -= scanned;
+	do {
+		sdp_record_t *rec;
+		sdp_list_t *protos;
+		sdp_data_t *data;
+		int recsize, ch = -1;
+
+		recsize = 0;
+		rec = sdp_extract_pdu(rsp, bytesleft, &recsize);
+		if (!rec)
+			break;
+
+		if (!recsize) {
+			sdp_record_free(rec);
+			break;
+		}
+
+		if (!sdp_get_access_protos(rec, &protos)) {
+			port = sdp_get_proto_port(protos, RFCOMM_UUID);
+			sdp_list_foreach(protos,
+					(sdp_list_func_t) sdp_list_free, NULL);
+			sdp_list_free(protos, NULL);
+			protos = NULL;
+			goto done;
+		}
+
+		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;
+
+		sdp_record_free(rec);
+
+		if (ch > 0) {
+			port = ch;
+			break;
+		}
+
+		scanned += recsize;
+		rsp += recsize;
+		bytesleft -= recsize;
+	} while (scanned < size && bytesleft > 0);
+
+done:
+	session->channel = port;
+	__sdp_io_finished = 1;
+}
+
+static uint16_t get_ftp_channel(struct obexhlp_session* session,
+					bdaddr_t *src, bdaddr_t *dst)
+{
+	sdp_list_t *search, *attrid;
+	uint32_t range = 0x0000ffff;
+	sdp_session_t *sdp;
+	uuid_t uuid;
+
+	sdp = sdp_connect(src, dst, SDP_RETRY_IF_BUSY);
+	if (sdp == NULL)
+		return 0;
+
+	/* 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};
+	sdp_uuid128_create(&uuid, uuid_int);
+
+	if (sdp_set_notify(sdp, search_callback, session) < 0)
+		goto done;
+
+	search = sdp_list_append(NULL, &uuid);
+	attrid = sdp_list_append(NULL, &range);
+
+	if (sdp_service_search_attr_async(sdp,
+				search, SDP_ATTR_REQ_RANGE, attrid) < 0) {
+		sdp_list_free(attrid, NULL);
+		sdp_list_free(search, NULL);
+		goto done;
+	}
+
+	sdp_list_free(attrid, NULL);
+	sdp_list_free(search, NULL);
+
+	while (!__sdp_io_finished)
+		sdp_process(sdp);
+
+done:
+	return session->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, 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_print("OBEX Connect failed: %s\n", err->message);
+		g_error_free(err);
+	} else {
+		g_print("OBEX Connect succeeded\n");
+	}
+}
+
+static void bt_io_callback(GIOChannel *io, GError *err, gpointer user_data)
+{
+	struct obexhlp_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_print("Bluetooth socket connected\n");
+
+	g_io_channel_set_close_on_unref(io, FALSE);
+
+	if (get_packet_opt(io, &tx_mtu, &rx_mtu) == 0) {
+		type = G_OBEX_TRANSPORT_PACKET;
+		g_print("PACKET transport tx:%d rx:%d\n", tx_mtu, rx_mtu);
+	} else {
+		type = G_OBEX_TRANSPORT_STREAM;
+		g_print("STREAM transport\n");
+	}
+
+	session->obex = g_obex_new(io, type, tx_mtu, rx_mtu);
+	if (session->obex == NULL) {
+		g_print("ERROR: obex is NULL");
+		raise(SIGTERM);
+	}
+
+	g_io_channel_set_close_on_unref(io, TRUE);
+
+	g_obex_connect(session->obex, obex_callback, session, &err,
+				G_OBEX_HDR_TARGET, OBEX_FTP_UUID,
+				OBEX_FTP_UUID_LEN, G_OBEX_HDR_INVALID);
+
+	if (err != NULL) {
+		g_print("ERROR: %s\n", err->message);
+		g_obex_unref(session->obex);
+		raise(SIGTERM);
+	}
+}
+
+struct obexhlp_session* obexhlp_connect(const char *srcstr,
+						const char *dststr)
+{
+	struct obexhlp_session *session;
+	uint16_t channel;
+	bdaddr_t src, dst;
+
+	session = g_try_malloc0(sizeof(struct obexhlp_session));
+	if (session == NULL)
+		return NULL;
+
+	if (srcstr == NULL)
+		bacpy(&src, BDADDR_ANY);
+	else
+		str2ba(srcstr, &src);
+
+	str2ba(dststr, &dst);
+	channel = get_ftp_channel(session, &src, &dst);
+
+	if (channel == 0)
+		return NULL;
+
+	if (channel > 31)
+		session->io = bt_io_connect(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_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("/");
+
+	obexhlp_mutex = g_mutex_new();
+	obexhlp_cond = g_cond_new();
+
+	return session;
+}
+
+void obexhlp_disconnect(struct obexhlp_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(obexhlp_mutex);
+	g_cond_free(obexhlp_cond);
+
+	g_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index abbdd70..3ef924e 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -47,3 +47,7 @@ struct obexhlp_session {
 	int status;
 	GError *err;
 };
+
+struct obexhlp_session* obexhlp_connect(const char *srcstr,
+						const char *dstsrc);
+void obexhlp_disconnect(struct obexhlp_session* session);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index fe4f4da..d6a87f3 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -33,6 +33,10 @@
 
 #include "helpers.h"
 
+struct obexhlp_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()
+{
+	obexhlp_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 = obexhlp_connect(options.srcstr, options.dststr);
+	if (session == NULL || session->io == NULL) {
+		g_printerr("Connection to %s failed\n", options.dststr);
+		obexhlp_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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox