* [PATCH v3 3/7] Bluetooth: Refactor LE connection into its own function
From: Vinicius Costa Gomes @ 2012-07-27 22:32 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1343428380-32705-1-git-send-email-vinicius.gomes@openbossa.org>
The code that handles LE connection is already quite separated from
the rest of the connection procedure, so we can easily put it into
its own.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
net/bluetooth/hci_conn.c | 53 +++++++++++++++++++++++++---------------------
1 file changed, 29 insertions(+), 24 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index c30c507..0a74399 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -470,6 +470,33 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
}
EXPORT_SYMBOL(hci_get_route);
+static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
+ u8 dst_type, u8 sec_level, u8 auth_type)
+{
+ struct hci_conn *le;
+
+ le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
+ if (!le) {
+ le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+ if (le)
+ return ERR_PTR(-EBUSY);
+
+ le = hci_conn_add(hdev, LE_LINK, dst);
+ if (!le)
+ return ERR_PTR(-ENOMEM);
+
+ le->dst_type = bdaddr_to_le(dst_type);
+ hci_le_create_connection(le);
+ }
+
+ le->pending_sec_level = sec_level;
+ le->auth_type = auth_type;
+
+ hci_conn_hold(le);
+
+ return le;
+}
+
/* Create SCO, ACL or LE connection.
* Device _must_ be locked */
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
@@ -477,33 +504,11 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
{
struct hci_conn *acl;
struct hci_conn *sco;
- struct hci_conn *le;
BT_DBG("%s dst %s", hdev->name, batostr(dst));
- if (type == LE_LINK) {
- le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
- if (!le) {
- le = hci_conn_hash_lookup_state(hdev, LE_LINK,
- BT_CONNECT);
- if (le)
- return ERR_PTR(-EBUSY);
-
- le = hci_conn_add(hdev, LE_LINK, dst);
- if (!le)
- return ERR_PTR(-ENOMEM);
-
- le->dst_type = bdaddr_to_le(dst_type);
- hci_le_create_connection(le);
- }
-
- le->pending_sec_level = sec_level;
- le->auth_type = auth_type;
-
- hci_conn_hold(le);
-
- return le;
- }
+ if (type == LE_LINK)
+ return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type);
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3 2/7] Bluetooth: Rename LE and ACL connection functions
From: Vinicius Costa Gomes @ 2012-07-27 22:32 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1343428380-32705-1-git-send-email-vinicius.gomes@openbossa.org>
These names were causing much confusion, so we rename these functions
that send HCI commands to be more similar in naming to the actual HCI
commands that will be sent.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
net/bluetooth/hci_conn.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 724eea9..c30c507 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -30,7 +30,7 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/a2mp.h>
-static void hci_le_connect(struct hci_conn *conn)
+static void hci_le_create_connection(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct hci_cp_le_create_conn cp;
@@ -54,12 +54,12 @@ static void hci_le_connect(struct hci_conn *conn)
hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
}
-static void hci_le_connect_cancel(struct hci_conn *conn)
+static void hci_le_create_connection_cancel(struct hci_conn *conn)
{
hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
}
-static void hci_acl_connect(struct hci_conn *conn)
+static void hci_acl_create_connection(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct inquiry_entry *ie;
@@ -103,7 +103,7 @@ static void hci_acl_connect(struct hci_conn *conn)
hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
}
-static void hci_acl_connect_cancel(struct hci_conn *conn)
+static void hci_acl_create_connection_cancel(struct hci_conn *conn)
{
struct hci_cp_create_conn_cancel cp;
@@ -245,9 +245,9 @@ static void hci_conn_timeout(struct work_struct *work)
case BT_CONNECT2:
if (conn->out) {
if (conn->type == ACL_LINK)
- hci_acl_connect_cancel(conn);
+ hci_acl_create_connection_cancel(conn);
else if (conn->type == LE_LINK)
- hci_le_connect_cancel(conn);
+ hci_le_create_connection_cancel(conn);
}
break;
case BT_CONFIG:
@@ -494,7 +494,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
return ERR_PTR(-ENOMEM);
le->dst_type = bdaddr_to_le(dst_type);
- hci_le_connect(le);
+ hci_le_create_connection(le);
}
le->pending_sec_level = sec_level;
@@ -518,7 +518,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
acl->sec_level = BT_SECURITY_LOW;
acl->pending_sec_level = sec_level;
acl->auth_type = auth_type;
- hci_acl_connect(acl);
+ hci_acl_create_connection(acl);
}
if (type == ACL_LINK)
@@ -771,7 +771,7 @@ void hci_conn_check_pending(struct hci_dev *hdev)
conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
if (conn)
- hci_acl_connect(conn);
+ hci_acl_create_connection(conn);
hci_dev_unlock(hdev);
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3 1/7] Bluetooth: Remove some functions from being exported
From: Vinicius Costa Gomes @ 2012-07-27 22:32 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1343428380-32705-1-git-send-email-vinicius.gomes@openbossa.org>
Some connection related functions are only used inside hci_conn.c
so no need to have them exported.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 2 --
net/bluetooth/hci_conn.c | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 41d9439..7267daf 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -551,9 +551,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
return NULL;
}
-void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
-void hci_add_sco(struct hci_conn *conn, __u16 handle);
void hci_setup_sync(struct hci_conn *conn, __u16 handle);
void hci_sco_setup(struct hci_conn *conn, __u8 status);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 5ad7da2..724eea9 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -59,7 +59,7 @@ static void hci_le_connect_cancel(struct hci_conn *conn)
hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
}
-void hci_acl_connect(struct hci_conn *conn)
+static void hci_acl_connect(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct inquiry_entry *ie;
@@ -129,7 +129,7 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
}
-void hci_add_sco(struct hci_conn *conn, __u16 handle)
+static void hci_add_sco(struct hci_conn *conn, __u16 handle)
{
struct hci_dev *hdev = conn->hdev;
struct hci_cp_add_sco cp;
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3 0/7] Bluetooth: Refactoring hci_connect()
From: Vinicius Costa Gomes @ 2012-07-27 22:32 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Hi,
Changes from last version:
* Changed the names of the functions that send HCI Commands to avoid confusion;
* There was no need for exporting some functions related to connections;
Cheers,
Vinicius Costa Gomes (7):
Bluetooth: Remove some functions from being exported
Bluetooth: Rename LE and ACL connection functions
Bluetooth: Refactor LE connection into its own function
Bluetooth: Refactor ACL connection into its own function
Bluetooth: Refactor SCO connection into its own function
Bluetooth: Simplify a the connection type handling
Bluetooth: Add type information to the hci_connect() debug statement
include/net/bluetooth/hci_core.h | 2 -
net/bluetooth/hci_conn.c | 99 ++++++++++++++++++++++++--------------
2 files changed, 62 insertions(+), 39 deletions(-)
--
1.7.10.4
^ permalink raw reply
* [PATCH BlueZ 14/14] core: Re-connect for ECONNRESET or ECONNABORTED
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
From: Claudio Takahasi <claudio.takahasi@openbossa.org>
This patch keeps scanning and re-connections active if the disconnection
reason is ECONNRESET(Remote Initiated Disconnection).
Re-connection is a behaviour determined by Profiles or by the upper
layer(user actions). For instance, HoG requires re-connection always
active, no matter if the previous disconnection reason was page timeout
or remote initiated disconnection (ECONNRESET). Some devices disconnects
after some idle time, connectable advertises are sent by the peripheral
when commanded by the user(eg: key pressed). Disconnection can be also
triggered by the local host (ECONNABORTED) using command line tools or
Disconnect method in the Device interface.
The peripheral dictates the re-connection controlling the connectable
advertises, BlueZ(central) needs to keep the scanning always active to
able to detect the advertises and trigger the connection.
---
src/device.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/device.c b/src/device.c
index d9c6708..1b01a8c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1810,10 +1810,18 @@ static gboolean attrib_disconnected_cb(GIOChannel *io, GIOCondition cond,
g_slist_foreach(device->attios, attio_disconnected, NULL);
- if (device->auto_connect == FALSE || err != ETIMEDOUT)
+ if (device->auto_connect == FALSE) {
+ DBG("Automatic connection disabled");
goto done;
+ }
- adapter_connect_list_add(device_get_adapter(device), device);
+ /*
+ * Keep scanning/re-connection active if disconnection reason
+ * is page timeout, remote user terminated connection or local
+ * initiated disconnection.
+ */
+ if (err == ETIMEDOUT || err == ECONNRESET || err == ECONNABORTED)
+ adapter_connect_list_add(device_get_adapter(device), device);
done:
attio_cleanup(device);
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 13/14] core: Disable unnecessary auto connections
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Paulo Alcantara
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
From: Paulo Alcantara <paulo.alcantara@openbossa.org>
BlueZ host disconnects the link when encryption fails. ECONNABORTED
error is returned by the kernel when the connection is terminated by the
local host. This scenario commonly happens when authentication fails due
PIN or Key Missing.
---
src/device.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/device.c b/src/device.c
index d81976e..d9c6708 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1954,6 +1954,9 @@ static void att_error_cb(const GError *gerr, gpointer user_data)
struct att_callbacks *attcb = user_data;
struct btd_device *device = attcb->user_data;
+ if (gerr->code == ECONNABORTED)
+ return;
+
if (device->auto_connect == FALSE)
return;
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 12/14] test: Fix exiting the bus when a discovery session ends
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
From: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
This way we are able to test more complex scenarios.
---
test/test-discovery | 8 --------
1 file changed, 8 deletions(-)
diff --git a/test/test-discovery b/test/test-discovery
index 269c51c..08dfd0b 100755
--- a/test/test-discovery
+++ b/test/test-discovery
@@ -22,10 +22,6 @@ def device_found(address, properties):
print()
-def property_changed(name, value):
- if (name == "Discovering" and not value):
- mainloop.quit()
-
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@@ -53,10 +49,6 @@ if __name__ == '__main__':
dbus_interface = "org.bluez.Adapter",
signal_name = "DeviceFound")
- bus.add_signal_receiver(property_changed,
- dbus_interface = "org.bluez.Adapter",
- signal_name = "PropertyChanged")
-
adapter.StartDiscovery()
mainloop = GObject.MainLoop()
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 11/14] core: Queue discovery if scanning is active
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
From: Claudio Takahasi <claudio.takahasi@openbossa.org>
This patch manages BR/EDR inquiry and BLE scanning discovery sessions.
A scanning session is added in the discovery session list when there is
a bonded device which requires re-connection.
bluetoothd decides if interleaved or scanning needs to be executed based
on the queued discovery sessions. Interleaved discovery has higher
priority, scanning only is executed when there is only a scanning
session active.
---
src/adapter.c | 68 +++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 47 insertions(+), 21 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 3bc2d0e..f27af24 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -132,6 +132,7 @@ struct btd_adapter {
GSList *devices; /* Devices structure pointers */
GSList *mode_sessions; /* Request Mode sessions */
GSList *disc_sessions; /* Discovery sessions */
+ struct session_req *scanning_session;
GSList *connect_list; /* Devices to connect when found */
GSList *connecting_list; /* Pending connects */
guint discov_id; /* Discovery timer */
@@ -220,18 +221,19 @@ static struct session_req *create_session(struct btd_adapter *adapter,
DBusConnection *conn, DBusMessage *msg,
uint8_t mode, GDBusWatchFunction cb)
{
- const char *sender = dbus_message_get_sender(msg);
+ const char *sender;
struct session_req *req;
req = g_new0(struct session_req, 1);
req->adapter = adapter;
- req->conn = dbus_connection_ref(conn);
- req->msg = dbus_message_ref(msg);
req->mode = mode;
- if (cb == NULL)
+ if (conn == NULL || cb == NULL || msg == NULL)
return session_ref(req);
+ req->conn = dbus_connection_ref(conn);
+ req->msg = dbus_message_ref(msg);
+ sender = dbus_message_get_sender(msg);
req->owner = g_strdup(sender);
req->id = g_dbus_add_disconnect_watch(conn, sender, cb, req, NULL);
@@ -443,7 +445,9 @@ static struct session_req *find_session(GSList *list, const char *sender)
for (; list; list = list->next) {
struct session_req *req = list->data;
- if (g_str_equal(req->owner, sender))
+ /* req->owner may be NULL if the session has been added by the
+ * daemon itself, so we use g_strcmp0 instead of g_str_equal */
+ if (g_strcmp0(req->owner, sender) == 0)
return req;
}
@@ -518,7 +522,7 @@ static void session_remove(struct session_req *req)
struct btd_adapter *adapter = req->adapter;
/* Ignore set_mode session */
- if (req->owner == NULL)
+ if (req->owner == NULL && adapter->pending_mode)
return;
DBG("%s session %p with %s deactivated",
@@ -1002,7 +1006,12 @@ static gboolean discovery_cb(gpointer user_data)
struct btd_adapter *adapter = user_data;
adapter->discov_id = 0;
- mgmt_start_discovery(adapter->dev_id);
+
+ if (adapter->scanning_session &&
+ (g_slist_length(adapter->disc_sessions) == 1))
+ mgmt_start_scanning(adapter->dev_id);
+ else
+ mgmt_start_discovery(adapter->dev_id);
return FALSE;
}
@@ -2172,6 +2181,7 @@ const char *btd_adapter_get_name(struct btd_adapter *adapter)
void adapter_connect_list_add(struct btd_adapter *adapter,
struct btd_device *device)
{
+ struct session_req *req;
bdaddr_t bdaddr;
device_get_address(device, &bdaddr, NULL);
@@ -2186,10 +2196,21 @@ void adapter_connect_list_add(struct btd_adapter *adapter,
DBG("%s added to %s's connect_list", device_get_path(device),
adapter->name);
- if (adapter->disc_sessions)
+ if (!adapter->up)
return;
- mgmt_start_scanning(adapter->dev_id);
+ if (adapter->off_requested)
+ return;
+
+ if (adapter->scanning_session)
+ return;
+
+ if (adapter->disc_sessions == NULL)
+ adapter->discov_id = g_idle_add(discovery_cb, adapter);
+
+ req = create_session(adapter, NULL, NULL, 0, NULL);
+ adapter->disc_sessions = g_slist_append(adapter->disc_sessions, req);
+ adapter->scanning_session = req;
}
void adapter_connect_list_remove(struct btd_adapter *adapter,
@@ -2202,6 +2223,7 @@ void adapter_connect_list_remove(struct btd_adapter *adapter,
void btd_adapter_start(struct btd_adapter *adapter)
{
+ struct session_req *req;
char address[18];
gboolean powered;
@@ -2228,8 +2250,15 @@ void btd_adapter_start(struct btd_adapter *adapter)
info("Adapter %s has been enabled", adapter->path);
- if (g_slist_length(adapter->connect_list))
- mgmt_start_scanning(adapter->dev_id);
+ if (g_slist_length(adapter->connect_list) == 0 ||
+ adapter->disc_sessions)
+ return;
+
+ req = create_session(adapter, NULL, NULL, 0, NULL);
+ adapter->disc_sessions = g_slist_append(adapter->disc_sessions, req);
+ adapter->scanning_session = req;
+
+ adapter->discov_id = g_idle_add(discovery_cb, adapter);
}
static void reply_pending_requests(struct btd_adapter *adapter)
@@ -2563,6 +2592,11 @@ void adapter_set_discovering(struct btd_adapter *adapter,
connect_list_size = g_slist_length(adapter->connect_list);
+ if (connect_list_size == 0 && adapter->scanning_session) {
+ session_unref(adapter->scanning_session);
+ adapter->scanning_session = NULL;
+ }
+
if (adapter_has_discov_sessions(adapter)) {
adapter->discov_id = g_idle_add(discovery_cb, adapter);
@@ -2571,14 +2605,6 @@ void adapter_set_discovering(struct btd_adapter *adapter,
g_slist_length(adapter->disc_sessions));
return;
}
-
- if (connect_list_size) {
- mgmt_start_scanning(adapter->dev_id);
-
- DBG("hci%u restarting scanning connect_list size %u",
- adapter->dev_id, connect_list_size);
- return;
- }
}
static void suspend_discovery(struct btd_adapter *adapter)
@@ -2877,7 +2903,6 @@ static gboolean clean_connecting_state(GIOChannel *io, GIOCondition cond, gpoint
struct btd_device *device = user_data;
struct btd_adapter *adapter = device_get_adapter(device);
- adapter_connect_list_remove(adapter, device);
adapter->connecting_list = g_slist_remove(adapter->connecting_list,
device);
@@ -2885,7 +2910,7 @@ static gboolean clean_connecting_state(GIOChannel *io, GIOCondition cond, gpoint
if (!g_slist_length(adapter->connecting_list) &&
g_slist_length(adapter->connect_list))
- mgmt_start_scanning(adapter->dev_id);
+ adapter->discov_id = g_idle_add(discovery_cb, adapter);
btd_device_unref(device);
@@ -3009,6 +3034,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
goto done;
device = l->data;
+ adapter_connect_list_remove(adapter, device);
l = g_slist_find(adapter->connecting_list, device);
if (l)
goto done;
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 10/14] core: Remove leftover define
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
From: Claudio Takahasi <claudio.takahasi@openbossa.org>
---
src/device.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/device.c b/src/device.c
index a0dc5a0..d81976e 100644
--- a/src/device.c
+++ b/src/device.c
@@ -67,8 +67,6 @@
#define DISCONNECT_TIMER 2
#define DISCOVERY_TIMER 2
-#define AUTO_CONNECTION_INTERVAL 5 /* Next connection attempt */
-
/* When all services should trust a remote device */
#define GLOBAL_TRUST "[all]"
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 09/14] core: Start LE scanning when a device requests
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
From: Claudio Takahasi <claudio.takahasi@openbossa.org>
This patch enables the LE scanning when a device requires connection and
there isn't discovery sessions, triggering the General Connection
Establishment Procedure.
---
src/adapter.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/adapter.c b/src/adapter.c
index 46b32d7..3bc2d0e 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2185,6 +2185,11 @@ void adapter_connect_list_add(struct btd_adapter *adapter,
adapter->connect_list = g_slist_append(adapter->connect_list, device);
DBG("%s added to %s's connect_list", device_get_path(device),
adapter->name);
+
+ if (adapter->disc_sessions)
+ return;
+
+ mgmt_start_scanning(adapter->dev_id);
}
void adapter_connect_list_remove(struct btd_adapter *adapter,
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 08/14] core: Replace interleaved by LE scanning
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
From: Claudio Takahasi <claudio.takahasi@openbossa.org>
This patches replaces the interleaved discovery by LE scanning when LE
re-connection is required.
---
src/adapter.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 4c2505a..46b32d7 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2224,7 +2224,7 @@ void btd_adapter_start(struct btd_adapter *adapter)
info("Adapter %s has been enabled", adapter->path);
if (g_slist_length(adapter->connect_list))
- mgmt_start_discovery(adapter->dev_id);
+ mgmt_start_scanning(adapter->dev_id);
}
static void reply_pending_requests(struct btd_adapter *adapter)
@@ -2558,14 +2558,22 @@ void adapter_set_discovering(struct btd_adapter *adapter,
connect_list_size = g_slist_length(adapter->connect_list);
- if (!adapter_has_discov_sessions(adapter) && !connect_list_size)
+ if (adapter_has_discov_sessions(adapter)) {
+ adapter->discov_id = g_idle_add(discovery_cb, adapter);
+
+ DBG("hci%u restarting discovery: disc_sessions %u",
+ adapter->dev_id,
+ g_slist_length(adapter->disc_sessions));
return;
+ }
- DBG("hci%u restarting discovery: disc_sessions %u, connect_list size "
- "%u", adapter->dev_id, g_slist_length(adapter->disc_sessions),
- connect_list_size);
+ if (connect_list_size) {
+ mgmt_start_scanning(adapter->dev_id);
- adapter->discov_id = g_idle_add(discovery_cb, adapter);
+ DBG("hci%u restarting scanning connect_list size %u",
+ adapter->dev_id, connect_list_size);
+ return;
+ }
}
static void suspend_discovery(struct btd_adapter *adapter)
@@ -2872,7 +2880,7 @@ static gboolean clean_connecting_state(GIOChannel *io, GIOCondition cond, gpoint
if (!g_slist_length(adapter->connecting_list) &&
g_slist_length(adapter->connect_list))
- mgmt_start_discovery(adapter->dev_id);
+ mgmt_start_scanning(adapter->dev_id);
btd_device_unref(device);
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 07/14] mgmt: Add LE scanning callback
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
From: Claudio Takahasi <claudio.takahasi@openbossa.org>
This patch adds a new callback to allow the adapter to control LE
scanning. The current approach uses the active scanning with default
windows and intervals defined by the core spec without any filtering.
---
src/mgmt.c | 32 ++++++++++++++++++++++++++++++++
src/mgmt.h | 1 +
2 files changed, 33 insertions(+)
diff --git a/src/mgmt.c b/src/mgmt.c
index d73cf2a..b013aeb 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -1970,6 +1970,38 @@ int mgmt_start_discovery(int index)
return 0;
}
+int mgmt_start_scanning(int index)
+{
+ char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_start_discovery)];
+ struct mgmt_hdr *hdr = (void *) buf;
+ struct mgmt_cp_start_discovery *cp = (void *) &buf[sizeof(*hdr)];
+ struct controller_info *info = &controllers[index];
+
+ DBG("index %d", index);
+
+ info->discov_type = 0;
+
+ if (mgmt_low_energy(info->current_settings)) {
+ hci_set_bit(BDADDR_LE_PUBLIC, &info->discov_type);
+ hci_set_bit(BDADDR_LE_RANDOM, &info->discov_type);
+ }
+
+ memset(buf, 0, sizeof(buf));
+ hdr->opcode = htobs(MGMT_OP_START_DISCOVERY);
+ hdr->len = htobs(sizeof(*cp));
+ hdr->index = htobs(index);
+
+ cp->type = info->discov_type;
+
+ if (write(mgmt_sock, buf, sizeof(buf)) < 0) {
+ int err = errno;
+ error("failed to write to MGMT socket: %s", strerror(err));
+ return -err;
+ }
+
+ return 0;
+}
+
int mgmt_stop_discovery(int index)
{
char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_start_discovery)];
diff --git a/src/mgmt.h b/src/mgmt.h
index 0658198..ed47b40 100644
--- a/src/mgmt.h
+++ b/src/mgmt.h
@@ -33,6 +33,7 @@ int mgmt_set_dev_class(int index, uint8_t major, uint8_t minor);
int mgmt_set_fast_connectable(int index, gboolean enable);
int mgmt_start_discovery(int index);
+int mgmt_start_scanning(int index);
int mgmt_stop_discovery(int index);
int mgmt_read_clock(int index, bdaddr_t *bdaddr, int which, int timeout,
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 06/14] core: mutually exclude concurrent connections
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: João Paulo Rechi Vita
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
Since controllers don't support more than one ongoing connection
procedure at the same time, new connection attempts needs to yield if
there is an ongoing connection procedure already.
---
src/adapter.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
src/device.c | 4 ++--
src/device.h | 2 +-
3 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index b48dd0a..4c2505a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -133,8 +133,10 @@ struct btd_adapter {
GSList *mode_sessions; /* Request Mode sessions */
GSList *disc_sessions; /* Discovery sessions */
GSList *connect_list; /* Devices to connect when found */
+ GSList *connecting_list; /* Pending connects */
guint discov_id; /* Discovery timer */
gboolean discovering; /* Discovery active */
+ gboolean connecting; /* Connect active */
gboolean discov_suspended; /* Discovery suspended */
guint auto_timeout_id; /* Automatic connections timeout */
sdp_list_t *services; /* Services associated to adapter */
@@ -2220,6 +2222,9 @@ void btd_adapter_start(struct btd_adapter *adapter)
call_adapter_powered_callbacks(adapter, TRUE);
info("Adapter %s has been enabled", adapter->path);
+
+ if (g_slist_length(adapter->connect_list))
+ mgmt_start_discovery(adapter->dev_id);
}
static void reply_pending_requests(struct btd_adapter *adapter)
@@ -2533,6 +2538,7 @@ void adapter_set_discovering(struct btd_adapter *adapter,
gboolean discovering)
{
const char *path = adapter->path;
+ guint connect_list_size;
adapter->discovering = discovering;
@@ -2547,11 +2553,17 @@ void adapter_set_discovering(struct btd_adapter *adapter,
g_slist_free_full(adapter->oor_devices, dev_info_free);
adapter->oor_devices = g_slist_copy(adapter->found_devices);
- if (!adapter_has_discov_sessions(adapter) || adapter->discov_suspended)
+ if (adapter->discov_suspended)
return;
- DBG("hci%u restarting discovery, disc_sessions %u", adapter->dev_id,
- g_slist_length(adapter->disc_sessions));
+ connect_list_size = g_slist_length(adapter->connect_list);
+
+ if (!adapter_has_discov_sessions(adapter) && !connect_list_size)
+ return;
+
+ DBG("hci%u restarting discovery: disc_sessions %u, connect_list size "
+ "%u", adapter->dev_id, g_slist_length(adapter->disc_sessions),
+ connect_list_size);
adapter->discov_id = g_idle_add(discovery_cb, adapter);
}
@@ -2847,17 +2859,44 @@ static char *read_stored_data(bdaddr_t *local, bdaddr_t *peer, const char *file)
return textfile_get(filename, peer_addr);
}
+static gboolean clean_connecting_state(GIOChannel *io, GIOCondition cond, gpointer user_data)
+{
+ struct btd_device *device = user_data;
+ struct btd_adapter *adapter = device_get_adapter(device);
+
+ adapter_connect_list_remove(adapter, device);
+ adapter->connecting_list = g_slist_remove(adapter->connecting_list,
+ device);
+
+ adapter->connecting = FALSE;
+
+ if (!g_slist_length(adapter->connecting_list) &&
+ g_slist_length(adapter->connect_list))
+ mgmt_start_discovery(adapter->dev_id);
+
+ btd_device_unref(device);
+
+ return FALSE;
+}
+
static gboolean connect_pending_cb(gpointer user_data)
{
struct btd_device *device = user_data;
struct btd_adapter *adapter = device_get_adapter(device);
+ GIOChannel *io;
/* in the future we may want to check here if the controller supports
* scanning and connecting at the same time */
if (adapter->discovering)
return TRUE;
- device_att_connect(device);
+ if (adapter->connecting)
+ return TRUE;
+
+ adapter->connecting = TRUE;
+ io = device_att_connect(device);
+ g_io_add_watch(io, G_IO_OUT | G_IO_ERR, clean_connecting_state,
+ btd_device_ref(device));
return FALSE;
}
@@ -2949,12 +2988,22 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
if (bdaddr_type == BDADDR_LE_PUBLIC ||
bdaddr_type == BDADDR_LE_RANDOM) {
+ struct btd_device *device;
+
l = g_slist_find_custom(adapter->connect_list, bdaddr,
(GCompareFunc) device_bdaddr_cmp);
- if (l) {
- g_idle_add(connect_pending_cb, l->data);
- stop_discovery(adapter);
- }
+ if (!l)
+ goto done;
+
+ device = l->data;
+ l = g_slist_find(adapter->connecting_list, device);
+ if (l)
+ goto done;
+
+ g_idle_add(connect_pending_cb, device);
+ adapter->connecting_list = g_slist_append(
+ adapter->connecting_list, device);
+ stop_discovery(adapter);
}
done:
diff --git a/src/device.c b/src/device.c
index 2cd694d..a0dc5a0 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1974,7 +1974,7 @@ static void att_success_cb(gpointer user_data)
g_slist_foreach(device->attios, attio_connected, device->attrib);
}
-gboolean device_att_connect(gpointer user_data)
+GIOChannel *device_att_connect(gpointer user_data)
{
struct btd_device *device = user_data;
struct btd_adapter *adapter = device->adapter;
@@ -2022,7 +2022,7 @@ gboolean device_att_connect(gpointer user_data)
device->att_io = io;
- return FALSE;
+ return io;
}
static void att_browse_error_cb(const GError *gerr, gpointer user_data)
diff --git a/src/device.h b/src/device.h
index 9b7df1c..5f51745 100644
--- a/src/device.h
+++ b/src/device.h
@@ -127,4 +127,4 @@ int device_unblock(DBusConnection *conn, struct btd_device *device,
void device_set_pnpid(struct btd_device *device, uint8_t vendor_id_src,
uint16_t vendor_id, uint16_t product_id,
uint16_t product_ver);
-gboolean device_att_connect(gpointer user_data);
+GIOChannel *device_att_connect(gpointer user_data);
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 05/14] core: use adapter connect list for LE connections
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: João Paulo Rechi Vita
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
When a connection is needed for a LE device it is added to the adapter
connect list instead of directly connecting the ATT io channel.
---
src/adapter.c | 2 +-
src/device.c | 43 +++++++++++--------------------------------
src/device.h | 1 +
3 files changed, 13 insertions(+), 33 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index d0f8d6b..b48dd0a 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2857,7 +2857,7 @@ static gboolean connect_pending_cb(gpointer user_data)
if (adapter->discovering)
return TRUE;
- /* TODO: call device connect callback */
+ device_att_connect(device);
return FALSE;
}
diff --git a/src/device.c b/src/device.c
index 7ec98dd..2cd694d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1796,15 +1796,6 @@ static void attio_disconnected(gpointer data, gpointer user_data)
attio->dcfunc(attio->user_data);
}
-static void att_connect_dispatched(gpointer user_data)
-{
- struct btd_device *device = user_data;
-
- device->auto_id = 0;
-}
-
-static gboolean att_connect(gpointer user_data);
-
static gboolean attrib_disconnected_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
@@ -1824,10 +1815,7 @@ static gboolean attrib_disconnected_cb(GIOChannel *io, GIOCondition cond,
if (device->auto_connect == FALSE || err != ETIMEDOUT)
goto done;
- device->auto_id = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT_IDLE,
- AUTO_CONNECTION_INTERVAL,
- att_connect, device,
- att_connect_dispatched);
+ adapter_connect_list_add(device_get_adapter(device), device);
done:
attio_cleanup(device);
@@ -1971,11 +1959,7 @@ static void att_error_cb(const GError *gerr, gpointer user_data)
if (device->auto_connect == FALSE)
return;
- device->auto_id = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT_IDLE,
- AUTO_CONNECTION_INTERVAL,
- att_connect, device,
- att_connect_dispatched);
-
+ adapter_connect_list_add(device_get_adapter(device), device);
DBG("Enabling automatic connections");
}
@@ -1990,7 +1974,7 @@ static void att_success_cb(gpointer user_data)
g_slist_foreach(device->attios, attio_connected, device->attrib);
}
-static gboolean att_connect(gpointer user_data)
+gboolean device_att_connect(gpointer user_data)
{
struct btd_device *device = user_data;
struct btd_adapter *adapter = device->adapter;
@@ -2260,6 +2244,9 @@ void device_set_temporary(struct btd_device *device, gboolean temporary)
DBG("temporary %d", temporary);
+ if (temporary)
+ adapter_connect_list_remove(device_get_adapter(device), device);
+
device->temporary = temporary;
}
@@ -2275,6 +2262,7 @@ void device_set_bonded(struct btd_device *device, gboolean bonded)
void device_set_auto_connect(struct btd_device *device, gboolean enable)
{
+ struct btd_adapter *adapter = device_get_adapter(device);
char addr[18];
if (!device)
@@ -2288,15 +2276,10 @@ void device_set_auto_connect(struct btd_device *device, gboolean enable)
/* Disabling auto connect */
if (enable == FALSE) {
- if (device->auto_id)
- g_source_remove(device->auto_id);
+ adapter_connect_list_remove(adapter, device);
return;
}
- /* Enabling auto connect */
- if (device->auto_id != 0)
- return;
-
if (device->attrib) {
DBG("Already connected");
return;
@@ -2305,9 +2288,8 @@ void device_set_auto_connect(struct btd_device *device, gboolean enable)
if (device->attios == NULL && device->attios_offline == NULL)
return;
- device->auto_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
- att_connect, device,
- att_connect_dispatched);
+ /* Enabling auto connect */
+ adapter_connect_list_add(adapter, device);
}
static gboolean start_discovery(gpointer user_data)
@@ -3085,10 +3067,7 @@ guint btd_device_add_attio_callback(struct btd_device *device,
device->attios = g_slist_append(device->attios, attio);
- if (device->auto_id == 0)
- device->auto_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
- att_connect, device,
- att_connect_dispatched);
+ adapter_connect_list_add(device_get_adapter(device), device);
return attio->id;
}
diff --git a/src/device.h b/src/device.h
index 2b2e6d8..9b7df1c 100644
--- a/src/device.h
+++ b/src/device.h
@@ -127,3 +127,4 @@ int device_unblock(DBusConnection *conn, struct btd_device *device,
void device_set_pnpid(struct btd_device *device, uint8_t vendor_id_src,
uint16_t vendor_id, uint16_t product_id,
uint16_t product_ver);
+gboolean device_att_connect(gpointer user_data);
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 04/14] core: Add a list of LE devices to connect
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: João Paulo Rechi Vita
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
This commit creates a per-adapter list of LE devices to connect when a
advertising from them is seen during a scan.
---
src/adapter.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/adapter.h | 2 ++
2 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/src/adapter.c b/src/adapter.c
index 5dd9821..d0f8d6b 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -132,6 +132,7 @@ struct btd_adapter {
GSList *devices; /* Devices structure pointers */
GSList *mode_sessions; /* Request Mode sessions */
GSList *disc_sessions; /* Discovery sessions */
+ GSList *connect_list; /* Devices to connect when found */
guint discov_id; /* Discovery timer */
gboolean discovering; /* Discovery active */
gboolean discov_suspended; /* Discovery suspended */
@@ -2166,6 +2167,32 @@ const char *btd_adapter_get_name(struct btd_adapter *adapter)
return adapter->name;
}
+void adapter_connect_list_add(struct btd_adapter *adapter,
+ struct btd_device *device)
+{
+ bdaddr_t bdaddr;
+
+ device_get_address(device, &bdaddr, NULL);
+ if (g_slist_find_custom(adapter->connect_list, &bdaddr,
+ (GCompareFunc) device_bdaddr_cmp)) {
+ DBG("trying to add device %s which is already in the connect "
+ "list, ignoring", device_get_path(device));
+ return;
+ }
+
+ adapter->connect_list = g_slist_append(adapter->connect_list, device);
+ DBG("%s added to %s's connect_list", device_get_path(device),
+ adapter->name);
+}
+
+void adapter_connect_list_remove(struct btd_adapter *adapter,
+ struct btd_device *device)
+{
+ adapter->connect_list = g_slist_remove(adapter->connect_list, device);
+ DBG("%s removed from %s's connect_list", device_get_path(device),
+ adapter->name);
+}
+
void btd_adapter_start(struct btd_adapter *adapter)
{
char address[18];
@@ -2820,6 +2847,21 @@ static char *read_stored_data(bdaddr_t *local, bdaddr_t *peer, const char *file)
return textfile_get(filename, peer_addr);
}
+static gboolean connect_pending_cb(gpointer user_data)
+{
+ struct btd_device *device = user_data;
+ struct btd_adapter *adapter = device_get_adapter(device);
+
+ /* in the future we may want to check here if the controller supports
+ * scanning and connecting at the same time */
+ if (adapter->discovering)
+ return TRUE;
+
+ /* TODO: call device connect callback */
+
+ return FALSE;
+}
+
void adapter_update_found_devices(struct btd_adapter *adapter,
bdaddr_t *bdaddr, uint8_t bdaddr_type,
int8_t rssi, uint8_t confirm_name,
@@ -2831,6 +2873,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
gboolean legacy, name_known;
uint32_t dev_class;
int err;
+ GSList *l;
memset(&eir_data, 0, sizeof(eir_data));
err = eir_parse(&eir_data, data, data_len);
@@ -2853,7 +2896,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
eir_data.name);
dev = adapter_search_found_devices(adapter, bdaddr);
- if (dev) {
+ if (dev && dev->bdaddr_type == BDADDR_BREDR) {
adapter->oor_devices = g_slist_remove(adapter->oor_devices,
dev);
@@ -2904,6 +2947,16 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
adapter->found_devices = g_slist_prepend(adapter->found_devices, dev);
+ if (bdaddr_type == BDADDR_LE_PUBLIC ||
+ bdaddr_type == BDADDR_LE_RANDOM) {
+ l = g_slist_find_custom(adapter->connect_list, bdaddr,
+ (GCompareFunc) device_bdaddr_cmp);
+ if (l) {
+ g_idle_add(connect_pending_cb, l->data);
+ stop_discovery(adapter);
+ }
+ }
+
done:
dev->rssi = rssi;
diff --git a/src/adapter.h b/src/adapter.h
index 602bb6f..e31f355 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -230,3 +230,5 @@ int btd_adapter_remove_remote_oob_data(struct btd_adapter *adapter,
int btd_adapter_gatt_server_start(struct btd_adapter *adapter);
void btd_adapter_gatt_server_stop(struct btd_adapter *adapter);
+void adapter_connect_list_add(struct btd_adapter *adapter, struct btd_device *device);
+void adapter_connect_list_remove(struct btd_adapter *adapter, struct btd_device *device);
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 03/14] core: add compare function for bdaddr in a struct btd_device
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: João Paulo Rechi Vita
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
This is a utility function similar to device_address_cmp but comparing
bdaddr instead of the string representing the address. This way is
possible to avoid allocating two buffers to temporarily hold the
strings, two sprintf() calls to generate the strings from the bdaddr
arrays, and a string comparison, substituting all of it for one memcmp()
call.
---
src/device.c | 5 +++++
src/device.h | 1 +
2 files changed, 6 insertions(+)
diff --git a/src/device.c b/src/device.c
index cd571f7..7ec98dd 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1232,6 +1232,11 @@ gint device_address_cmp(struct btd_device *device, const gchar *address)
return strcasecmp(addr, address);
}
+gint device_bdaddr_cmp(struct btd_device *device, bdaddr_t *bdaddr)
+{
+ return bacmp(&device->bdaddr, bdaddr);
+}
+
static gboolean record_has_uuid(const sdp_record_t *rec,
const char *profile_uuid)
{
diff --git a/src/device.h b/src/device.h
index 26e17f7..2b2e6d8 100644
--- a/src/device.h
+++ b/src/device.h
@@ -45,6 +45,7 @@ uint16_t btd_device_get_product(struct btd_device *device);
uint16_t btd_device_get_version(struct btd_device *device);
void device_remove(struct btd_device *device, gboolean remove_stored);
gint device_address_cmp(struct btd_device *device, const gchar *address);
+gint device_bdaddr_cmp(struct btd_device *device, bdaddr_t *bdaddr);
int device_browse_primary(struct btd_device *device, DBusConnection *conn,
DBusMessage *msg, gboolean secure);
int device_browse_sdp(struct btd_device *device, DBusConnection *conn,
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 02/14] mgmt: print error message when start_discovery fails
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: João Paulo Rechi Vita
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
If we fail to communicate with the MGMT socket is better to print the
error message on the mgmtops plugin, where it really happened, instead
of leaving this job to its users.
---
src/adapter.c | 6 +-----
src/mgmt.c | 7 +++++--
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index c9c82e3..5dd9821 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -997,13 +997,9 @@ struct btd_device *adapter_get_device(DBusConnection *conn,
static gboolean discovery_cb(gpointer user_data)
{
struct btd_adapter *adapter = user_data;
- int err;
adapter->discov_id = 0;
-
- err = mgmt_start_discovery(adapter->dev_id);
- if (err < 0)
- error("start_discovery: %s (%d)", strerror(-err), -err);
+ mgmt_start_discovery(adapter->dev_id);
return FALSE;
}
diff --git a/src/mgmt.c b/src/mgmt.c
index c55b1a8..d73cf2a 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -1961,8 +1961,11 @@ int mgmt_start_discovery(int index)
cp->type = info->discov_type;
- if (write(mgmt_sock, buf, sizeof(buf)) < 0)
- return -errno;
+ if (write(mgmt_sock, buf, sizeof(buf)) < 0) {
+ int err = -errno;
+ error("failed to write to MGMT socket: %s", strerror(err));
+ return err;
+ }
return 0;
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 01/14] core: Control connections based on adapter state
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1343428198-23621-1-git-send-email-jprvita@openbossa.org>
From: Claudio Takahasi <claudio.takahasi@openbossa.org>
This patch disable automatic ATTIO connections when the adapter is
powered down and enable automatic connection when the adapter is powered
on.
---
src/adapter.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 8820e27..c9c82e3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2083,6 +2083,14 @@ static int get_pairable_timeout(const char *src)
return main_opts.pairto;
}
+static void set_auto_connect(gpointer data, gpointer user_data)
+{
+ struct btd_device *device = data;
+ gboolean enable = GPOINTER_TO_INT(user_data);
+
+ device_set_auto_connect(device, enable);
+}
+
static void call_adapter_powered_callbacks(struct btd_adapter *adapter,
gboolean powered)
{
@@ -2092,7 +2100,10 @@ static void call_adapter_powered_callbacks(struct btd_adapter *adapter,
btd_adapter_powered_cb cb = l->data;
cb(adapter, powered);
- }
+ }
+
+ g_slist_foreach(adapter->devices, set_auto_connect,
+ GINT_TO_POINTER(powered));
}
static void emit_device_disappeared(gpointer data, gpointer user_data)
@@ -3292,15 +3303,10 @@ static gboolean disable_auto(gpointer user_data)
return FALSE;
}
-static void set_auto_connect(gpointer data, gpointer user_data)
-{
- struct btd_device *device = data;
-
- device_set_auto_connect(device, TRUE);
-}
-
void btd_adapter_enable_auto_connect(struct btd_adapter *adapter)
{
+ gboolean enable = TRUE;
+
if (!adapter->up)
return;
@@ -3309,7 +3315,8 @@ void btd_adapter_enable_auto_connect(struct btd_adapter *adapter)
if (adapter->auto_timeout_id)
return;
- g_slist_foreach(adapter->devices, set_auto_connect, NULL);
+ g_slist_foreach(adapter->devices, set_auto_connect,
+ GINT_TO_POINTER(enable));
adapter->auto_timeout_id = g_timeout_add_seconds(main_opts.autoto,
disable_auto, adapter);
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 00/14] LE General Connection Establishment procedure
From: João Paulo Rechi Vita @ 2012-07-27 22:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: João Paulo Rechi Vita
This series implement the LE General Connection Establishment procedure
for LE connections.
If there are LE bonded devices marked for auto connection they are added
to a connect_list on the adapter. When there is any device on this list
scan is performed continuously. When a device is found the connect_list
is checked. If that device is on the list scan is stopped and a
connection attempt is made to that device.
If any client tries to perform discovery and the scan for the General
Connection Establishment procedure is active, the discovery request is
queued and performed right after the GCEP scan session finishes.
This series changes quite a lot the LE connection logic, but we've been
testing and using this code at INdT for about 4 weeks. Any comments and
more testing are appreciated.
Claudio Takahasi (7):
core: Control connections based on adapter state
mgmt: Add LE scanning callback
core: Replace interleaved by LE scanning
core: Start LE scanning when a device requests
core: Remove leftover define
core: Queue discovery if scanning is active
core: Re-connect for ECONNRESET or ECONNABORTED
João Paulo Rechi Vita (5):
mgmt: print error message when start_discovery fails
core: add compare function for bdaddr in a struct btd_device
core: Add a list of LE devices to connect
core: use adapter connect list for LE connections
core: mutually exclude concurrent connections
Paulo Alcantara (1):
core: Disable unnecessary auto connections
Vinicius Costa Gomes (1):
test: Fix exiting the bus when a discovery session ends
src/adapter.c | 192 ++++++++++++++++++++++++++++++++++++++++++++-------
src/adapter.h | 2 +
src/device.c | 65 ++++++++---------
src/device.h | 2 +
src/mgmt.c | 39 ++++++++++-
src/mgmt.h | 1 +
test/test-discovery | 8 ---
7 files changed, 239 insertions(+), 70 deletions(-)
--
1.7.10.4
^ permalink raw reply
* [PATCH] Bluetooth: Another vendor specific ID for BCM20702A0 [0a5c:21f1]
From: Michal Marek @ 2012-07-27 21:21 UTC (permalink / raw)
To: linux-bluetooth; +Cc: linux-kernel
Bus 002 Device 003: ID 0a5c:21f1 Broadcom Corp.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 255 Vendor Specific Class
bDeviceSubClass 1
bDeviceProtocol 1
bMaxPacketSize0 64
idVendor 0x0a5c Broadcom Corp.
idProduct 0x21f1
bcdDevice 1.12
iManufacturer 1 Broadcom Corp
iProduct 2 BCM20702A0
iSerial 3 9CB70DCFF833
bNumConfigurations 1
Signed-off-by: Michal Marek <mmarek@suse.cz>
---
drivers/bluetooth/btusb.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index e272214..5748b15 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -97,6 +97,7 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x0a5c, 0x21e3) },
{ USB_DEVICE(0x0a5c, 0x21e6) },
{ USB_DEVICE(0x0a5c, 0x21e8) },
+ { USB_DEVICE(0x0a5c, 0x21f1) },
{ USB_DEVICE(0x0a5c, 0x21f3) },
{ USB_DEVICE(0x413c, 0x8197) },
--
1.7.3.1
^ permalink raw reply related
* [PATCH BlueZ 3/3] gatt: Add support to GATT Write Long Characteristic
From: Eder Ruiz Maria @ 2012-07-27 20:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Eder Ruiz Maria
In-Reply-To: <1343420976-19921-1-git-send-email-eder.ruiz@openbossa.org>
Extending the function gatt_write_char for support GATT Write Long
Characteristics. MTU is checked and if the payload does not fit,
the prepare and execute write are used to do the transaction.
---
attrib/att.h | 4 ++
attrib/gatt.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++---
attrib/gatttool.c | 2 +-
attrib/interactive.c | 2 +-
4 files changed, 110 insertions(+), 7 deletions(-)
diff --git a/attrib/att.h b/attrib/att.h
index 64d22ca..e7a29cb 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -92,6 +92,10 @@
#define ATT_CID 4
#define ATT_PSM 31
+/* Flags for Execute Write Request Operation */
+#define ATT_CANCEL_ALL_PREP_WRITES 0x00
+#define ATT_WRITE_ALL_PREP_WRITES 0x01
+
struct att_data_list {
uint16_t num;
uint16_t len;
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 6f9a11d..b7eb736 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -520,21 +520,120 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, uint16_t offset,
return id;
}
+struct write_long_data {
+ GAttrib *attrib;
+ GAttribResultFunc func;
+ gpointer user_data;
+ guint16 handle;
+ uint16_t offset;
+ uint8_t *value;
+ int vlen;
+};
+
+static guint execute_write(GAttrib *attrib, uint8_t flags,
+ GAttribResultFunc func, gpointer user_data)
+{
+ uint8_t *buf;
+ int buflen;
+ guint16 plen;
+
+ buf = g_attrib_get_buffer(attrib, &buflen);
+ plen = enc_exec_write_req(flags, buf, buflen);
+ if (plen == 0)
+ return 0;
+
+ return g_attrib_send(attrib, 0, buf[0], buf, plen, func, user_data,
+ NULL);
+}
+
+static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
+ uint8_t *value, int vlen, GAttribResultFunc func,
+ gpointer user_data);
+
+static void prepare_write_cb(guint8 status, const guint8 *rpdu,
+ guint16 rlen, gpointer user_data)
+{
+ struct write_long_data *long_write = user_data;
+
+ if (status != 0) {
+ long_write->func(status, rpdu, rlen, long_write->user_data);
+ return;
+ }
+
+ /* Skip Prepare Write Response PDU header (5 bytes) */
+ long_write->offset += rlen - 5;
+
+ if (long_write->offset == long_write->vlen){
+ execute_write(long_write->attrib, ATT_WRITE_ALL_PREP_WRITES,
+ long_write->func, long_write->user_data);
+ g_free(long_write->value);
+ g_free(long_write);
+
+ return;
+ }
+
+ prepare_write(long_write->attrib, long_write->handle,
+ long_write->offset, long_write->value, long_write->vlen,
+ long_write->func, long_write);
+}
+
+static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
+ uint8_t *value, int vlen, GAttribResultFunc func,
+ gpointer user_data)
+{
+ guint16 plen;
+ int buflen;
+ uint8_t *buf;
+
+ buf = g_attrib_get_buffer(attrib, &buflen);
+
+ plen = enc_prep_write_req(handle, offset, &value[offset], vlen - offset,
+ buf, buflen);
+ if (plen == 0)
+ return 0;
+
+ return g_attrib_send(attrib, 0, buf[0], buf, plen, prepare_write_cb,
+ user_data, NULL);
+}
+
guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
int vlen, GAttribResultFunc func, gpointer user_data)
{
uint8_t *buf;
int buflen;
guint16 plen;
+ struct write_long_data *long_write;
buf = g_attrib_get_buffer(attrib, &buflen);
- if (func)
- plen = enc_write_req(handle, value, vlen, buf, buflen);
- else
- plen = enc_write_cmd(handle, value, vlen, buf, buflen);
- return g_attrib_send(attrib, 0, buf[0], buf, plen, func,
+ /* Only use Write Request/Command if payload fits on a single transfer,
+ * including 3 bytes for the header. */
+ if (vlen <= buflen - 3) {
+ if (func)
+ plen = enc_write_req(handle, value, vlen, buf,
+ buflen);
+ else
+ plen = enc_write_cmd(handle, value, vlen, buf,
+ buflen);
+
+ return g_attrib_send(attrib, 0, buf[0], buf, plen, func,
user_data, NULL);
+ }
+
+ /* Write Long Characteristic Values */
+ long_write = g_try_new0(struct write_long_data, 1);
+ if (long_write == NULL)
+ return 0;
+
+ long_write->attrib = attrib;
+ long_write->func = func;
+ long_write->user_data = user_data;
+ long_write->handle = handle;
+ long_write->value = g_memdup(value,vlen);
+ long_write->vlen = vlen;
+
+ return prepare_write(attrib, handle, long_write->offset, value, vlen,
+ func, long_write);
}
guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 1f23522..a11ca9f 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -371,7 +371,7 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
goto done;
}
- if (!dec_write_resp(pdu, plen)) {
+ if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
g_printerr("Protocol error\n");
goto done;
}
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 3657798..6cd8bd5 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -588,7 +588,7 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
return;
}
- if (!dec_write_resp(pdu, plen)) {
+ if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
printf("Protocol error\n");
return;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 2/3] att: Add encode/decode execute write support
From: Eder Ruiz Maria @ 2012-07-27 20:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Eder Ruiz Maria
In-Reply-To: <1343420976-19921-1-git-send-email-eder.ruiz@openbossa.org>
Add functions for encoding/decoding Execute Write Request and
Response PDUs.
---
attrib/att.c | 34 ++++++++++++++++++++++++++++++++++
attrib/att.h | 2 ++
2 files changed, 36 insertions(+)
diff --git a/attrib/att.c b/attrib/att.c
index acfb4e0..20a8efa 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -1029,3 +1029,37 @@ uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
return len;
}
+uint16_t enc_exec_write_req(uint8_t flags, uint8_t *pdu, int len)
+{
+ const uint16_t min_len = sizeof(pdu[0]) + sizeof(flags);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (flags > 1)
+ return 0;
+
+ pdu[0] = ATT_OP_EXEC_WRITE_REQ;
+ pdu[1] = flags;
+
+ return min_len;
+}
+
+uint16_t dec_exec_write_resp(const uint8_t *pdu, int len)
+{
+ const uint16_t min_len = sizeof(pdu[0]);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (pdu[0] != ATT_OP_EXEC_WRITE_RESP)
+ return 0;
+
+ return len;
+}
diff --git a/attrib/att.h b/attrib/att.h
index ec03be9..64d22ca 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -261,3 +261,5 @@ uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
const uint8_t *value, int vlen, uint8_t *pdu, int len);
uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
uint16_t *offset, uint8_t *value, int *vlen);
+uint16_t enc_exec_write_req(uint8_t flags, uint8_t *pdu, int len);
+uint16_t dec_exec_write_resp(const uint8_t *pdu, int len);
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 1/3] att: Add prepare write support
From: Eder Ruiz Maria @ 2012-07-27 20:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Eder Ruiz Maria
Add functions for encoding/decoding Prepare Write Request and
Response PDUs.
---
attrib/att.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
attrib/att.h | 5 +++++
2 files changed, 60 insertions(+)
diff --git a/attrib/att.c b/attrib/att.c
index 0550ac1..acfb4e0 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -974,3 +974,58 @@ uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu)
return min_len;
}
+
+uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
+ const uint8_t *value, int vlen, uint8_t *pdu, int len)
+{
+ const uint16_t min_len = sizeof(pdu[0]) + sizeof(handle) +
+ sizeof(offset);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (vlen > len - min_len)
+ vlen = len - min_len;
+
+ pdu[0] = ATT_OP_PREP_WRITE_REQ;
+ att_put_u16(handle, &pdu[1]);
+ att_put_u16(offset, &pdu[3]);
+
+ if (vlen > 0) {
+ memcpy(&pdu[5], value, vlen);
+ return min_len + vlen;
+ }
+
+ return min_len;
+}
+
+uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
+ uint16_t *offset, uint8_t *value, int *vlen)
+{
+ const uint16_t min_len = sizeof(pdu[0]) + sizeof(*handle) +
+ sizeof(*offset);
+
+ if (pdu == NULL)
+ return 0;
+
+ if (handle == NULL || offset == NULL || value == NULL || vlen == NULL)
+ return 0;
+
+ if (len < min_len)
+ return 0;
+
+ if (pdu[0] != ATT_OP_PREP_WRITE_REQ)
+ return 0;
+
+ *handle = att_get_u16(&pdu[1]);
+ *offset = att_get_u16(&pdu[3]);
+ *vlen = len - min_len;
+ if (*vlen > 0)
+ memcpy(value, pdu + min_len, *vlen);
+
+ return len;
+}
+
diff --git a/attrib/att.h b/attrib/att.h
index 1c1102a..ec03be9 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -256,3 +256,8 @@ uint16_t enc_mtu_req(uint16_t mtu, uint8_t *pdu, int len);
uint16_t dec_mtu_req(const uint8_t *pdu, int len, uint16_t *mtu);
uint16_t enc_mtu_resp(uint16_t mtu, uint8_t *pdu, int len);
uint16_t dec_mtu_resp(const uint8_t *pdu, int len, uint16_t *mtu);
+
+uint16_t enc_prep_write_req(uint16_t handle, uint16_t offset,
+ const uint8_t *value, int vlen, uint8_t *pdu, int len);
+uint16_t dec_prep_write_resp(const uint8_t *pdu, int len, uint16_t *handle,
+ uint16_t *offset, uint8_t *value, int *vlen);
--
1.7.9.5
^ permalink raw reply related
* [RFC BlueZ] storage: Remove support for trusted services
From: Vinicius Costa Gomes @ 2012-07-27 20:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Since a long time, it is impossible to set individual services as
trusted using our API, so there's no need to have support for storing
this kind of information.
---
Hi,
Do you think it is useful to still maintain support for reading that kind of
information? That "feature" was removed in the 3 -> 4 transition as deprecated.
Cheers,
src/device.c | 9 +----
src/storage.c | 119 +++++++--------------------------------------------------
src/storage.h | 6 +--
3 files changed, 19 insertions(+), 115 deletions(-)
diff --git a/src/device.c b/src/device.c
index 1718726..73df561 100644
--- a/src/device.c
+++ b/src/device.c
@@ -69,9 +69,6 @@
#define AUTO_CONNECTION_INTERVAL 5 /* Next connection attempt */
-/* When all services should trust a remote device */
-#define GLOBAL_TRUST "[all]"
-
#define APPEARANCE_CHR_UUID 0x2a01
struct btd_disconnect_data {
@@ -488,8 +485,7 @@ static DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,
ba2str(&src, srcaddr);
ba2str(&device->bdaddr, dstaddr);
- err = write_trust(srcaddr, dstaddr, device->bdaddr_type, GLOBAL_TRUST,
- value);
+ err = write_trust(srcaddr, dstaddr, device->bdaddr_type, value);
if (err < 0)
return btd_error_failed(msg, strerror(-err));
@@ -1080,8 +1076,7 @@ struct btd_device *device_create(DBusConnection *conn,
if (read_device_alias(srcaddr, address, bdaddr_type, alias,
sizeof(alias)) == 0)
device->alias = g_strdup(alias);
- device->trusted = read_trust(&src, address, device->bdaddr_type,
- GLOBAL_TRUST);
+ device->trusted = read_trust(&src, address, device->bdaddr_type);
if (read_blocked(&src, &device->bdaddr, device->bdaddr_type))
device_block(conn, device, FALSE);
diff --git a/src/storage.c b/src/storage.c
index c50e920..3db1754 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -47,6 +47,9 @@
#include "glib-helper.h"
#include "storage.h"
+/* When all services should trust a remote device */
+#define GLOBAL_TRUST "[all]"
+
struct match {
GSList *keys;
char *pattern;
@@ -714,59 +717,10 @@ ssize_t read_pin_code(bdaddr_t *local, bdaddr_t *peer, char *pin)
return len;
}
-static GSList *service_string_to_list(char *services)
-{
- GSList *l = NULL;
- char *start = services;
- int i, finished = 0;
-
- for (i = 0; !finished; i++) {
- if (services[i] == '\0')
- finished = 1;
-
- if (services[i] == ' ' || services[i] == '\0') {
- services[i] = '\0';
- l = g_slist_append(l, start);
- start = services + i + 1;
- }
- }
-
- return l;
-}
-
-static char *service_list_to_string(GSList *services)
-{
- char str[1024];
- int len = 0;
-
- if (!services)
- return g_strdup("");
-
- memset(str, 0, sizeof(str));
-
- while (services) {
- int ret;
- char *ident = services->data;
-
- ret = snprintf(str + len, sizeof(str) - len - 1, "%s%s",
- ident, services->next ? " " : "");
-
- if (ret > 0)
- len += ret;
-
- services = services->next;
- }
-
- return g_strdup(str);
-}
-
int write_trust(const char *src, const char *addr, uint8_t addr_type,
- const char *service, gboolean trust)
+ gboolean trust)
{
- char filename[PATH_MAX + 1], key[20], *str;
- GSList *services = NULL, *match;
- gboolean trusted;
- int ret;
+ char filename[PATH_MAX + 1], key[20];
create_name(filename, PATH_MAX, STORAGEDIR, src, "trusts");
@@ -774,54 +728,15 @@ int write_trust(const char *src, const char *addr, uint8_t addr_type,
snprintf(key, sizeof(key), "%17s#%hhu", addr, addr_type);
- str = textfile_caseget(filename, key);
- if (str == NULL) {
- /* Try old format (address only) */
- str = textfile_caseget(filename, addr);
- if (str)
- services = service_string_to_list(str);
- } else
- services = service_string_to_list(str);
-
- match = g_slist_find_custom(services, service, (GCompareFunc) strcmp);
- trusted = match ? TRUE : FALSE;
-
- /* If the old setting is the same as the requested one, we're done */
- if (trusted == trust) {
- g_slist_free(services);
- free(str);
- return 0;
- }
-
- if (trust)
- services = g_slist_append(services, (void *) service);
- else
- services = g_slist_remove(services, match->data);
-
- /* Remove the entry if the last trusted service was removed */
- if (!trust && !services) {
- ret = textfile_casedel(filename, key);
- if (ret < 0)
- /* Try old format (address only) */
- ret = textfile_casedel(filename, addr);
- } else {
- char *new_str = service_list_to_string(services);
- ret = textfile_caseput(filename, key, new_str);
- g_free(new_str);
- }
-
- g_slist_free(services);
-
- free(str);
+ if (trust == FALSE)
+ return textfile_casedel(filename, key);
- return ret;
+ return textfile_caseput(filename, key, GLOBAL_TRUST);
}
-gboolean read_trust(const bdaddr_t *local, const char *addr, uint8_t addr_type,
- const char *service)
+gboolean read_trust(const bdaddr_t *local, const char *addr, uint8_t addr_type)
{
char filename[PATH_MAX + 1], key[20], *str;
- GSList *services;
gboolean ret;
create_filename(filename, PATH_MAX, local, "trusts");
@@ -829,25 +744,19 @@ gboolean read_trust(const bdaddr_t *local, const char *addr, uint8_t addr_type,
snprintf(key, sizeof(key), "%17s#%hhu", addr, addr_type);
str = textfile_caseget(filename, key);
- if (str != NULL)
- goto done;
+ if (str == NULL)
+ /* Try old format (address only) */
+ str = textfile_caseget(filename, addr);
- /* Try old format (address only) */
- str = textfile_caseget(filename, addr);
- if (!str)
+ if (str == NULL)
return FALSE;
-done:
- services = service_string_to_list(str);
-
- if (g_slist_find_custom(services, service, (GCompareFunc) strcmp))
+ if (strcmp(str, GLOBAL_TRUST) == 0)
ret = TRUE;
else
ret = FALSE;
- g_slist_free(services);
free(str);
-
return ret;
}
diff --git a/src/storage.h b/src/storage.h
index c4f13dd..6e2766d 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -64,10 +64,10 @@ int write_link_key(bdaddr_t *local, bdaddr_t *peer, uint8_t peer_type,
int read_link_key(bdaddr_t *local, bdaddr_t *peer, uint8_t peer_type,
unsigned char *key, uint8_t *type);
ssize_t read_pin_code(bdaddr_t *local, bdaddr_t *peer, char *pin);
-gboolean read_trust(const bdaddr_t *local, const char *addr, uint8_t addr_type,
- const char *service);
+gboolean read_trust(const bdaddr_t *local, const char *addr,
+ uint8_t addr_type);
int write_trust(const char *src, const char *addr, uint8_t addr_type,
- const char *service, gboolean trust);
+ gboolean trust);
int write_device_profiles(bdaddr_t *src, bdaddr_t *dst, uint8_t dst_type,
const char *profiles);
int delete_entry(bdaddr_t *src, const char *storage, bdaddr_t *dst,
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3 BlueZ 12/12] storage: Store address type in "sdp" file
From: Vinicius Costa Gomes @ 2012-07-27 19:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Paulo Alcantara
In-Reply-To: <1343418203-15335-1-git-send-email-vinicius.gomes@openbossa.org>
From: Paulo Alcantara <paulo.alcantara@openbossa.org>
---
profiles/input/device.c | 5 ++++-
src/device.c | 12 ++++++++----
src/storage.c | 49 ++++++++++++++++++++++++++++++++++-------------
src/storage.h | 12 ++++++++----
4 files changed, 56 insertions(+), 22 deletions(-)
diff --git a/profiles/input/device.c b/profiles/input/device.c
index 829ca03..ed178b4 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -599,6 +599,7 @@ static int hidp_add_connection(const struct input_device *idev,
struct hidp_connadd_req *req;
struct fake_hid *fake_hid;
struct fake_input *fake;
+ uint8_t dst_type;
sdp_record_t *rec;
char src_addr[18], dst_addr[18];
GError *gerr = NULL;
@@ -613,7 +614,9 @@ static int hidp_add_connection(const struct input_device *idev,
ba2str(&idev->src, src_addr);
ba2str(&idev->dst, dst_addr);
- rec = fetch_record(src_addr, dst_addr, idev->handle);
+ dst_type = device_get_addr_type(idev->device);
+
+ rec = fetch_record(src_addr, dst_addr, dst_type, idev->handle);
if (!rec) {
error("Rejected connection from unknown device %s", dst_addr);
err = -EPERM;
diff --git a/src/device.c b/src/device.c
index 4ff37e6..1718726 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1176,8 +1176,8 @@ static void device_remove_stored(struct btd_device *device)
btd_adapter_remove_bonding(device->adapter, &dst, dst_type);
}
- delete_all_records(&src, &device->bdaddr);
- delete_device_service(&src, &device->bdaddr, device->bdaddr_type);
+ delete_all_records(&src, &dst, dst_type);
+ delete_device_service(&src, &dst, dst_type);
if (device->blocked)
device_unblock(conn, device, TRUE, FALSE);
@@ -1401,7 +1401,8 @@ static void device_remove_drivers(struct btd_device *device, GSList *uuids)
if (!rec)
continue;
- delete_record(srcaddr, dstaddr, rec->handle);
+ delete_record(srcaddr, dstaddr, device->bdaddr_type,
+ rec->handle);
records = sdp_list_remove(records, rec);
sdp_record_free(rec);
@@ -1443,6 +1444,7 @@ static void update_services(struct browse_req *req, sdp_list_t *recs)
struct btd_adapter *adapter = device_get_adapter(device);
sdp_list_t *seq;
char srcaddr[18], dstaddr[18];
+ uint8_t dst_type;
bdaddr_t src;
adapter_get_address(adapter, &src);
@@ -1509,7 +1511,9 @@ static void update_services(struct browse_req *req, sdp_list_t *recs)
continue;
}
- store_record(srcaddr, dstaddr, rec);
+ dst_type = device_get_addr_type(device);
+
+ store_record(srcaddr, dstaddr, dst_type, rec);
/* Copy record */
req->records = sdp_list_append(req->records,
diff --git a/src/storage.c b/src/storage.c
index 9e0ea12..c50e920 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -894,9 +894,10 @@ int delete_entry(bdaddr_t *src, const char *storage, bdaddr_t *dst,
return err;
}
-int store_record(const gchar *src, const gchar *dst, sdp_record_t *rec)
+int store_record(const gchar *src, const gchar *dst, uint8_t dst_type,
+ sdp_record_t *rec)
{
- char filename[PATH_MAX + 1], key[28];
+ char filename[PATH_MAX + 1], key[30];
sdp_buf_t buf;
int err, size, i;
char *str;
@@ -905,7 +906,8 @@ int store_record(const gchar *src, const gchar *dst, sdp_record_t *rec)
create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- snprintf(key, sizeof(key), "%17s#%08X", dst, rec->handle);
+ snprintf(key, sizeof(key), "%17s#%hhu#%08X", dst, dst_type,
+ rec->handle);
if (sdp_gen_record_pdu(rec, &buf) < 0)
return -1;
@@ -949,34 +951,54 @@ sdp_record_t *record_from_string(const gchar *str)
sdp_record_t *fetch_record(const gchar *src, const gchar *dst,
- const uint32_t handle)
+ uint8_t dst_type, const uint32_t handle)
{
- char filename[PATH_MAX + 1], key[28], *str;
+ char filename[PATH_MAX + 1], old_key[28], key[30], *str;
sdp_record_t *rec;
create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
- snprintf(key, sizeof(key), "%17s#%08X", dst, handle);
+ snprintf(key, sizeof(key), "%17s#%hhu#%08X", dst, dst_type, handle);
+ snprintf(old_key, sizeof(old_key), "%17s#%08X", dst, handle);
str = textfile_get(filename, key);
- if (!str)
+ if (str != NULL)
+ goto done;
+
+ /* Try old format (address#handle) */
+ str = textfile_get(filename, old_key);
+ if (str == NULL)
return NULL;
+done:
rec = record_from_string(str);
free(str);
return rec;
}
-int delete_record(const gchar *src, const gchar *dst, const uint32_t handle)
+int delete_record(const gchar *src, const gchar *dst, uint8_t dst_type,
+ const uint32_t handle)
{
- char filename[PATH_MAX + 1], key[28];
+ char filename[PATH_MAX + 1], old_key[28], key[30];
+ int err, ret;
create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
- snprintf(key, sizeof(key), "%17s#%08X", dst, handle);
+ snprintf(key, sizeof(key), "%17s#%hhu#%08X", dst, dst_type, handle);
+ snprintf(old_key, sizeof(old_key), "%17s#%08X", dst, handle);
- return textfile_del(filename, key);
+ err = 0;
+ ret = textfile_del(filename, key);
+ if (ret)
+ err = ret;
+
+ /* Try old format (address#handle) */
+ ret = textfile_del(filename, old_key);
+ if (ret)
+ err = ret;
+
+ return err;
}
struct record_list {
@@ -999,7 +1021,8 @@ static void create_stored_records_from_keys(char *key, char *value,
rec_list->recs = sdp_list_append(rec_list->recs, rec);
}
-void delete_all_records(const bdaddr_t *src, const bdaddr_t *dst)
+void delete_all_records(const bdaddr_t *src, const bdaddr_t *dst,
+ uint8_t dst_type)
{
sdp_list_t *records, *seq;
char srcaddr[18], dstaddr[18];
@@ -1011,7 +1034,7 @@ void delete_all_records(const bdaddr_t *src, const bdaddr_t *dst)
for (seq = records; seq; seq = seq->next) {
sdp_record_t *rec = seq->data;
- delete_record(srcaddr, dstaddr, rec->handle);
+ delete_record(srcaddr, dstaddr, dst_type, rec->handle);
}
if (records)
diff --git a/src/storage.h b/src/storage.h
index b8cdb3c..c4f13dd 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -72,11 +72,15 @@ int write_device_profiles(bdaddr_t *src, bdaddr_t *dst, uint8_t dst_type,
const char *profiles);
int delete_entry(bdaddr_t *src, const char *storage, bdaddr_t *dst,
uint8_t dst_type);
-int store_record(const gchar *src, const gchar *dst, sdp_record_t *rec);
+int store_record(const gchar *src, const gchar *dst, uint8_t dst_type,
+ sdp_record_t *rec);
sdp_record_t *record_from_string(const gchar *str);
-sdp_record_t *fetch_record(const gchar *src, const gchar *dst, const uint32_t handle);
-int delete_record(const gchar *src, const gchar *dst, const uint32_t handle);
-void delete_all_records(const bdaddr_t *src, const bdaddr_t *dst);
+sdp_record_t *fetch_record(const gchar *src, const gchar *dst,
+ uint8_t dst_type, const uint32_t handle);
+int delete_record(const gchar *src, const gchar *dst, uint8_t dst_type,
+ const uint32_t handle);
+void delete_all_records(const bdaddr_t *src, const bdaddr_t *dst,
+ uint8_t dst_type);
sdp_list_t *read_records(const bdaddr_t *src, const bdaddr_t *dst);
sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid);
int store_device_id(const gchar *src, const gchar *dst, uint8_t dst_type,
--
1.7.10.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox