* [RFC v2 14/15] Bluetooth: Mgmt command for adding connection parameters
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch introduces a new Mgmt command (MGMT_OP_ADD_CONN_PARAMS)
to specify the connection parameters the kernel should use when
establishing connections to a certain device. Moreover, this command
also specifies the auto connection option the device requires.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/mgmt.h | 9 +++++++++
net/bluetooth/mgmt.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 518c5c8..a16924f 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -369,6 +369,15 @@ struct mgmt_cp_set_scan_params {
} __packed;
#define MGMT_SET_SCAN_PARAMS_SIZE 4
+#define MGMT_OP_ADD_CONN_PARAMS 0x002D
+struct mgmt_cp_add_conn_params {
+ struct mgmt_addr_info addr;
+ __u8 auto_connect;
+ __le16 min_conn_interval;
+ __le16 max_conn_interval;
+} __packed;
+#define MGMT_ADD_CONN_PARAMS_SIZE (MGMT_ADDR_INFO_SIZE + 5)
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d396e47..b8e0f12 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -79,6 +79,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_SET_BREDR,
MGMT_OP_SET_STATIC_ADDRESS,
MGMT_OP_SET_SCAN_PARAMS,
+ MGMT_OP_ADD_CONN_PARAMS,
};
static const u16 mgmt_events[] = {
@@ -4080,6 +4081,52 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
return err;
}
+static int add_conn_params(struct sock *sk, struct hci_dev *hdev, void *cp_data,
+ u16 len)
+{
+ struct mgmt_cp_add_conn_params *cp = cp_data;
+ u8 status;
+ u8 addr_type;
+ int err;
+
+ if (!bdaddr_type_is_le(cp->addr.type))
+ return cmd_complete(sk, hdev->id, MGMT_OP_ADD_CONN_PARAMS,
+ MGMT_STATUS_NOT_SUPPORTED, NULL, 0);
+
+ status = mgmt_le_support(hdev);
+ if (status)
+ return cmd_complete(sk, hdev->id, MGMT_OP_ADD_CONN_PARAMS,
+ status, NULL, 0);
+
+ if (cp->addr.type == BDADDR_LE_PUBLIC)
+ addr_type = ADDR_LE_DEV_PUBLIC;
+ else
+ addr_type = ADDR_LE_DEV_RANDOM;
+
+ err = hci_add_conn_params(hdev, &cp->addr.bdaddr, addr_type,
+ cp->auto_connect,
+ __le16_to_cpu(cp->min_conn_interval),
+ __le16_to_cpu(cp->max_conn_interval));
+ if (err)
+ return cmd_complete(sk, hdev->id, MGMT_OP_ADD_CONN_PARAMS,
+ MGMT_STATUS_FAILED, NULL, 0);
+
+ if (cp->auto_connect == HCI_AUTO_CONN_ALWAYS) {
+ err = hci_add_pending_auto_conn(hdev, &cp->addr.bdaddr,
+ addr_type);
+ if (err) {
+ hci_remove_conn_params(hdev, &cp->addr.bdaddr,
+ addr_type);
+ return cmd_complete(sk, hdev->id,
+ MGMT_OP_ADD_CONN_PARAMS,
+ MGMT_STATUS_FAILED, NULL, 0);
+ }
+ }
+
+ return cmd_complete(sk, hdev->id, MGMT_OP_ADD_CONN_PARAMS,
+ MGMT_STATUS_SUCCESS, NULL, 0);
+}
+
static const struct mgmt_handler {
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len);
@@ -4131,6 +4178,7 @@ static const struct mgmt_handler {
{ set_bredr, false, MGMT_SETTING_SIZE },
{ set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
{ set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
+ { add_conn_params, false, MGMT_ADD_CONN_PARAMS_SIZE },
};
--
1.8.4
^ permalink raw reply related
* [RFC v2 13/15] Bluetooth: Add thread-safe version of helpers
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch adds the thread-safe version of helper functions to add
and remove pending auto connections. These helpers will be used in
next patches to implementing the Mgmt add/remove connection
parameters commands.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 4 ++++
net/bluetooth/hci_core.c | 20 ++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 379bb36..2659123 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -779,8 +779,12 @@ bool hci_has_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
u8 addr_type);
int __hci_add_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
u8 addr_type);
+int hci_add_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type);
void __hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
u8 addr_type);
+void hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type);
bool hci_is_scan_and_conn_supported(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 63a56f5..5d7fd3d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3029,6 +3029,18 @@ int __hci_add_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
return 0;
}
+int hci_add_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type)
+{
+ int err;
+
+ hci_dev_lock(hdev);
+ err = __hci_add_pending_auto_conn(hdev, addr, addr_type);
+ hci_dev_unlock(hdev);
+
+ return err;
+}
+
/* This function requires the caller holds hdev->lock */
void __hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
u8 addr_type)
@@ -3051,6 +3063,14 @@ void __hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
}
}
+void hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type)
+{
+ hci_dev_lock(hdev);
+ __hci_remove_pending_auto_conn(hdev, addr, addr_type);
+ hci_dev_unlock(hdev);
+}
+
/* This function requires the caller holds hdev->lock */
static void __clear_pending_auto_conn(struct hci_dev *hdev)
{
--
1.8.4
^ permalink raw reply related
* [RFC v2 12/15] Bleutooth: Add support for auto connect options
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch adds support for the HCI_AUTO_CONN_ALWAYS and HCI_AUTO_
CONN_LINK_LOSS options from struct hci_conn_params.
The HCI_AUTO_CONN_ALWAYS option configures the kernel to always re-
establish the connection, no matter the reason the connection was
terminated. This feature is required by some LE profiles such as
HID over GATT, Health Thermometer and Blood Pressure. These profiles
require the host autonomously connect to the device as soon as it
enters in connectable mode (start advertising) so the device is able
to delivery a notification or indication.
The BT_AUTO_CONN_LINK_LOSS option configures the kernel to re-
establish the connection in case the connection was terminated due
to a link loss. This feature is required by the majority of LE
profiles such as Proximity, Find Me, Cycling Speed and Cadence and
Time.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_event.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index e48601d..b2d8aee 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1785,6 +1785,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
struct hci_conn *conn;
u8 type;
bool send_mgmt_event = false;
+ struct hci_conn_params *params;
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
@@ -1817,6 +1818,31 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn->type == ACL_LINK && conn->flush_key)
hci_remove_link_key(hdev, &conn->dst);
+ params = hci_find_conn_params(hdev, &conn->dst, conn->dst_type);
+ if (params) {
+ int err;
+
+ switch (params->auto_connect) {
+ case HCI_AUTO_CONN_LINK_LOSS:
+ if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
+ break;
+ /* Fall through */
+
+ case HCI_AUTO_CONN_ALWAYS:
+ err = __hci_add_pending_auto_conn(hdev, &conn->dst,
+ conn->dst_type);
+ if (err)
+ BT_ERR("Failed to add pending auto connection "
+ " %d", err);
+ break;
+
+ default:
+ break;
+ }
+
+ hci_conn_params_put(params);
+ }
+
type = conn->type;
hci_proto_disconn_cfm(conn, ev->reason);
hci_conn_del(conn);
--
1.8.4
^ permalink raw reply related
* [RFC v2 11/15] Bluetooth: Auto connection and power on
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch implements a fixup required by auto connection mechanism
in order to work properly after a power on.
When hdev is closed (e.g. Mgmt power off command, RFKILL or controller
is reset), the ongoing active connections are silently dropped by the
controller (no Disconnection Complete Event is sent to host). For that
reason, the devices that require HCI_AUTO_CONN_ALWAYS are not added to
hdev->pending_auto_conn list and they won't auto connect. So to fix
this issue, after adapter is powered on, we should add all HCI_AUTO_
CONN_ALWAYS address to hdev->pending_auto_conn list. Besides that, we
always have to check if there are pending auto connections and start
the background scanning if it is the case.
This way, the auto connection mechanism works propely after a power
off and power on sequence as well as RFKILL block/unblock.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 2 ++
net/bluetooth/hci_core.c | 49 ++++++++++++++++++++++++++++++++++++++++
net/bluetooth/mgmt.c | 2 ++
3 files changed, 53 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 322918f..379bb36 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -786,6 +786,8 @@ bool hci_is_scan_and_conn_supported(struct hci_dev *hdev);
void hci_check_background_scan(struct hci_dev *hdev);
+void __hci_fixup_auto_conn(struct hci_dev *hdev);
+
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 44d3f99..63a56f5 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3090,6 +3090,55 @@ void hci_check_background_scan(struct hci_dev *hdev)
BT_ERR("Failed to start background scanning: err %d", err);
}
+/* This functions implements a fixup required by auto connection mechanism
+ * in order to work properly after a power on.
+ *
+ * When hdev is closed (e.g. Mgmt power off command, RFKILL or controller is
+ * reset), the ongoing active connections are silently dropped by the
+ * by the controller (no Disconnection Complete Event is sent to host). For
+ * that reason, the devices that require HCI_AUTO_CONN_ALWAYS are not add to
+ * hdev->pending_auto_conn list and they won't auto connect. So to fix this
+ * issue, after adapter is powered on, we should add all HCI_AUTO_CONN_ALWAYS
+ * address to hdev->pending_auto_conn list. Besides that, we always have to
+ * check if there are pending auto connections and start the background
+ * scanning if it is the case.
+ *
+ * This function requires the caller holds hdev->lock.
+ */
+void __hci_fixup_auto_conn(struct hci_dev *hdev)
+{
+ struct hci_conn_params *p;
+ struct bdaddr_list *entry;
+
+ list_for_each_entry(p, &hdev->conn_params, list) {
+ if (p->auto_connect != HCI_AUTO_CONN_ALWAYS)
+ continue;
+
+ entry = __find_pending_auto_conn(hdev, &p->addr, p->addr_type);
+ if (entry)
+ continue;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ BT_ERR("Out of memory of auto connection");
+ return;
+ }
+
+ bacpy(&entry->bdaddr, &p->addr);
+ entry->bdaddr_type = p->addr_type;
+ list_add(&entry->list, &hdev->pending_auto_conn);
+ }
+
+ if (!list_empty(&hdev->pending_auto_conn)) {
+ int err;
+
+ err = start_background_scan(hdev);
+ if (err)
+ BT_ERR("Failed to start background scanning: err %d",
+ err);
+ }
+}
+
static void inquiry_complete(struct hci_dev *hdev, u8 status)
{
if (status) {
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 0e329e5..d396e47 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4255,6 +4255,8 @@ static void powered_complete(struct hci_dev *hdev, u8 status)
hci_dev_lock(hdev);
+ __hci_fixup_auto_conn(hdev);
+
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
new_settings(hdev, match.sk);
--
1.8.4
^ permalink raw reply related
* [RFC v2 10/15] Bluetooth: Temporarily stop background scanning on discovery
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
If the user send a mgmt start discovery command while the background
scanning is running, we should temporarily stop it. Once the discovery
finishes, we start the background scanning again.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_core.c | 5 +++++
net/bluetooth/mgmt.c | 12 ++++++++----
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 79debc3..44d3f99 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1496,6 +1496,11 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
switch (state) {
case DISCOVERY_STOPPED:
+ /* Check the background scanning since it may have been
+ * temporarily stopped by the start discovery command.
+ */
+ hci_check_background_scan(hdev);
+
if (hdev->discovery.state != DISCOVERY_STARTING)
mgmt_discovering(hdev, 0);
break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 22cf547..0e329e5 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3280,11 +3280,15 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}
+ /* If controller is scanning, it means the background scanning
+ * is running. Thus, we should temporarily stop it in order to
+ * set the discovery scanning parameters.
+ */
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
- err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
- MGMT_STATUS_BUSY);
- mgmt_pending_remove(cmd);
- goto failed;
+ memset(&enable_cp, 0, sizeof(enable_cp));
+ enable_cp.enable = LE_SCAN_DISABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE,
+ sizeof(enable_cp), &enable_cp);
}
memset(¶m_cp, 0, sizeof(param_cp));
--
1.8.4
^ permalink raw reply related
* [RFC v2 09/15] Bluetooth: Introduce LE auto connection infrastructure
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch introduces the LE auto connection infrastructure.
This infrastructure will be used to implement the auto_connect
options from hci_conn_params.
The auto connection mechanism works as follows: When the first
device address is inserted into hdev->pending_auto_con list, we
start the background scanning. Once the target device is found
in range, the kernel creates the connection. If connection is
established successfully, the device address is removed from
hdev->pending_auto_conn list. Finally, when the last device
address is removed, the background scanning is stopped.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 2 +
net/bluetooth/hci_conn.c | 6 ++
net/bluetooth/hci_core.c | 115 +++++++++++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 43 +++++++++++++++
4 files changed, 166 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 0049036..322918f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -784,6 +784,8 @@ void __hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
bool hci_is_scan_and_conn_supported(struct hci_dev *hdev);
+void hci_check_background_scan(struct hci_dev *hdev);
+
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b52bcb2..bbe3cab 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -544,6 +544,12 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
done:
hci_dev_unlock(hdev);
+
+ /* Check the background scanning since it may have been temporarily
+ * stopped if the controller doesn't support scanning and creating
+ * connection at the same time.
+ */
+ hci_check_background_scan(hdev);
}
static int hci_create_le_conn(struct hci_conn *conn)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 19624d1..79debc3 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2923,6 +2923,72 @@ bool hci_has_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
return res;
}
+static void start_background_scan_complete(struct hci_dev *hdev, u8 status)
+{
+ if (status)
+ BT_DBG("HCI request failed to start background scanning: "
+ "status 0x%2.2x", status);
+}
+
+static int start_background_scan(struct hci_dev *hdev)
+{
+ struct hci_cp_le_set_scan_param param_cp;
+ struct hci_cp_le_set_scan_enable enable_cp;
+ struct hci_request req;
+
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ return 0;
+
+ BT_DBG("%s", hdev->name);
+
+ hci_req_init(&req, hdev);
+
+ memset(¶m_cp, 0, sizeof(param_cp));
+ param_cp.type = LE_SCAN_PASSIVE;
+ param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
+ param_cp.window = cpu_to_le16(hdev->le_scan_window);
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+ ¶m_cp);
+
+ memset(&enable_cp, 0, sizeof(enable_cp));
+ enable_cp.enable = LE_SCAN_ENABLE;
+ enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+ &enable_cp);
+
+ return hci_req_run(&req, start_background_scan_complete);
+}
+
+static void stop_background_scan_complete(struct hci_dev *hdev, u8 status)
+{
+ if (status)
+ BT_DBG("HCI request failed to stop background scanning: "
+ "status 0x%2.2x", status);
+}
+
+static int stop_background_scan(struct hci_dev *hdev)
+{
+ struct hci_cp_le_set_scan_enable cp;
+ struct hci_request req;
+
+ if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ return 0;
+
+ /* If device discovery is running, background scanning is stopped so
+ * we return sucess.
+ */
+ if (hdev->discovery.state == DISCOVERY_FINDING)
+ return 0;
+
+ hci_req_init(&req, hdev);
+
+ memset(&cp, 0, sizeof(cp));
+ cp.enable = LE_SCAN_DISABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+
+ return hci_req_run(&req, stop_background_scan_complete);
+}
+
/* This function requires the caller holds hdev->lock */
int __hci_add_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
u8 addr_type)
@@ -2940,6 +3006,19 @@ int __hci_add_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
bacpy(&entry->bdaddr, addr);
entry->bdaddr_type = addr_type;
+ /* If there is no pending auto connection, the background scanning
+ * is not runnning. So we should start it.
+ */
+ if (list_empty(&hdev->pending_auto_conn)) {
+ int err;
+
+ err = start_background_scan(hdev);
+ if (err) {
+ kfree(entry);
+ return err;
+ }
+ }
+
list_add(&entry->list, &hdev->pending_auto_conn);
return 0;
@@ -2957,6 +3036,14 @@ void __hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
list_del(&entry->list);
kfree(entry);
+
+ if (list_empty(&hdev->pending_auto_conn)) {
+ int err;
+
+ err = stop_background_scan(hdev);
+ if (err)
+ BT_ERR("Failed to run HCI request: err %d", err);
+ }
}
/* This function requires the caller holds hdev->lock */
@@ -2970,6 +3057,34 @@ static void __clear_pending_auto_conn(struct hci_dev *hdev)
}
}
+/* This function starts the background scanning in case there is still
+ * pending auto connections.
+ */
+void hci_check_background_scan(struct hci_dev *hdev)
+{
+ struct hci_conn *conn;
+ int err;
+
+ if (list_empty(&hdev->pending_auto_conn))
+ return;
+
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ return;
+
+ /* If the controller is connecting but it doesn't support scanning
+ * scanning and connecting at the same time we don't start the
+ * background scanning now. It will be started once the connection
+ * is established.
+ */
+ conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+ if (conn && !hci_is_scan_and_conn_supported(hdev))
+ return;
+
+ err = start_background_scan(hdev);
+ if (err)
+ BT_ERR("Failed to start background scanning: err %d", err);
+}
+
static void inquiry_complete(struct hci_dev *hdev, u8 status)
{
if (status) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8b7cd37..e48601d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3547,8 +3547,49 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_proto_connect_cfm(conn, ev->status);
+ __hci_remove_pending_auto_conn(hdev, &ev->bdaddr, ev->bdaddr_type);
+
unlock:
hci_dev_unlock(hdev);
+
+ /* Check the background scanning since it may have been temporarily
+ * stopped if the controller doesn't support scanning and creating
+ * connection at the same time.
+ */
+ hci_check_background_scan(hdev);
+}
+
+static void check_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type)
+{
+ struct hci_conn *conn;
+ u8 bdaddr_type;
+
+ if (!hci_has_pending_auto_conn(hdev, addr, addr_type))
+ return;
+
+ if (addr_type == ADDR_LE_DEV_PUBLIC)
+ bdaddr_type = BDADDR_LE_PUBLIC;
+ else
+ bdaddr_type = BDADDR_LE_RANDOM;
+
+ conn = hci_connect(hdev, LE_LINK, addr, bdaddr_type, BT_SECURITY_LOW,
+ HCI_AT_NO_BONDING);
+ if (IS_ERR(conn)) {
+ switch (PTR_ERR(conn)) {
+ case -EBUSY:
+ /* When hci_connect() returns EBUSY it means there is
+ * already an LE connection attempt going on. Since the
+ * controller supports only one connection attempt at
+ * the time, we simply return.
+ */
+ return;
+ default:
+ BT_ERR("Failed to auto connect: err %ld",
+ PTR_ERR(conn));
+ return;
+ }
+ }
}
static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -3560,6 +3601,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
while (num_reports--) {
struct hci_ev_le_advertising_info *ev = ptr;
+ check_pending_auto_conn(hdev, &ev->bdaddr, ev->bdaddr_type);
+
rssi = ev->data[ev->length];
mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
NULL, rssi, 0, 1, ev->data, ev->length);
--
1.8.4
^ permalink raw reply related
* [RFC v2 08/15] Bluetooth: Move is_scan_and_conn_supported() to hci_core
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch adds the "hci_" prefix and moves the is_scan_and_conn_
supported() helper to hci_core so it can be reused in hci_core by
the next patch.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 2 ++
net/bluetooth/hci_conn.c | 13 +------------
net/bluetooth/hci_core.c | 11 +++++++++++
3 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e85b37e..0049036 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -782,6 +782,8 @@ int __hci_add_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
void __hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
u8 addr_type);
+bool hci_is_scan_and_conn_supported(struct hci_dev *hdev);
+
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 075d070..b52bcb2 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -546,17 +546,6 @@ done:
hci_dev_unlock(hdev);
}
-/* Check if controller supports creating a connection while scanning is
- * runnning.
- */
-static bool is_scan_and_conn_supported(struct hci_dev *hdev)
-{
- u8 mask = BIT(6) | BIT(7);
-
- /* Return true if both bits are set */
- return (hdev->le_states[2] & mask) == mask;
-}
-
static int hci_create_le_conn(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
@@ -571,7 +560,7 @@ static int hci_create_le_conn(struct hci_conn *conn)
* Otherwise, LE Create Connection command fails.
*/
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
- !is_scan_and_conn_supported(hdev)) {
+ !hci_is_scan_and_conn_supported(hdev)) {
struct hci_cp_le_set_scan_enable enable_cp;
memset(&enable_cp, 0, sizeof(enable_cp));
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 94c390b..19624d1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -4496,3 +4496,14 @@ static void hci_cmd_work(struct work_struct *work)
}
}
}
+
+/* Check if controller supports creating a connection while scanning is
+ * runnning.
+ */
+bool hci_is_scan_and_conn_supported(struct hci_dev *hdev)
+{
+ u8 mask = BIT(6) | BIT(7);
+
+ /* Return true if both bits are set */
+ return (hdev->le_states[2] & mask) == mask;
+}
--
1.8.4
^ permalink raw reply related
* [RFC v2 07/15] Bluetooth: Introduce hdev->pending_auto_conn list
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch introduces the hdev->pending_auto_conn list which holds
the device addresses the kernel should autonomously connect. It also
introduces some helper functions to manipulate the list.
The list and helper functions will be used by the next patch which
implements the LE auto connection infrastructure.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 9 +++++
net/bluetooth/hci_core.c | 84 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 93 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 64911aa..e85b37e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -273,6 +273,8 @@ struct hci_dev {
struct list_head conn_params;
+ struct list_head pending_auto_conn;
+
struct hci_dev_stats stat;
atomic_t promisc;
@@ -773,6 +775,13 @@ struct hci_conn_params *hci_find_conn_params(struct hci_dev *hdev,
bdaddr_t *addr, u8 addr_type);
void hci_conn_params_put(struct hci_conn_params *params);
+bool hci_has_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type);
+int __hci_add_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type);
+void __hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type);
+
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 0a278da..94c390b 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2888,6 +2888,88 @@ static void __clear_conn_params(struct hci_dev *hdev)
__remove_conn_params(params);
}
+static struct bdaddr_list *__find_pending_auto_conn(struct hci_dev *hdev,
+ bdaddr_t *addr,
+ u8 addr_type)
+{
+ struct bdaddr_list *entry;
+
+ list_for_each_entry(entry, &hdev->pending_auto_conn, list) {
+ if (bacmp(&entry->bdaddr, addr))
+ continue;
+ if (entry->bdaddr_type != addr_type)
+ continue;
+
+ return entry;
+ }
+
+ return NULL;
+}
+
+bool hci_has_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type)
+{
+ bool res;
+
+ hci_dev_lock(hdev);
+
+ if (__find_pending_auto_conn(hdev, addr, addr_type))
+ res = true;
+ else
+ res = false;
+
+ hci_dev_unlock(hdev);
+
+ return res;
+}
+
+/* This function requires the caller holds hdev->lock */
+int __hci_add_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type)
+{
+ struct bdaddr_list *entry;
+
+ entry = __find_pending_auto_conn(hdev, addr, addr_type);
+ if (entry)
+ return 0;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ bacpy(&entry->bdaddr, addr);
+ entry->bdaddr_type = addr_type;
+
+ list_add(&entry->list, &hdev->pending_auto_conn);
+
+ return 0;
+}
+
+/* This function requires the caller holds hdev->lock */
+void __hci_remove_pending_auto_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type)
+{
+ struct bdaddr_list *entry;
+
+ entry = __find_pending_auto_conn(hdev, addr, addr_type);
+ if (!entry)
+ return;
+
+ list_del(&entry->list);
+ kfree(entry);
+}
+
+/* This function requires the caller holds hdev->lock */
+static void __clear_pending_auto_conn(struct hci_dev *hdev)
+{
+ struct bdaddr_list *entry, *tmp;
+
+ list_for_each_entry_safe(entry, tmp, &hdev->pending_auto_conn, list) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
+}
+
static void inquiry_complete(struct hci_dev *hdev, u8 status)
{
if (status) {
@@ -2999,6 +3081,7 @@ struct hci_dev *hci_alloc_dev(void)
INIT_LIST_HEAD(&hdev->long_term_keys);
INIT_LIST_HEAD(&hdev->remote_oob_data);
INIT_LIST_HEAD(&hdev->conn_params);
+ INIT_LIST_HEAD(&hdev->pending_auto_conn);
INIT_LIST_HEAD(&hdev->conn_hash.list);
INIT_WORK(&hdev->rx_work, hci_rx_work);
@@ -3185,6 +3268,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_smp_ltks_clear(hdev);
hci_remote_oob_data_clear(hdev);
__clear_conn_params(hdev);
+ __clear_pending_auto_conn(hdev);
hci_dev_unlock(hdev);
hci_dev_put(hdev);
--
1.8.4
^ permalink raw reply related
* [RFC v2 06/15] Bluetooth: Use connection parameters if any
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch changes hci_connect_le() so it uses the connection
parameters specified for the certain device. If no parameters
were configured, we use the default values.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_conn.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 195b78f..075d070 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -608,6 +608,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
{
struct hci_conn *conn;
int err;
+ struct hci_conn_params *params;
if (test_bit(HCI_ADVERTISING, &hdev->flags))
return ERR_PTR(-ENOTSUPP);
@@ -652,8 +653,16 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
conn->sec_level = BT_SECURITY_LOW;
conn->pending_sec_level = sec_level;
conn->auth_type = auth_type;
- conn->conn_interval_min = hdev->le_conn_min_interval;
- conn->conn_interval_max = hdev->le_conn_max_interval;
+
+ params = hci_find_conn_params(hdev, &conn->dst, conn->dst_type);
+ if (params) {
+ conn->conn_interval_min = params->conn_interval_min;
+ conn->conn_interval_max = params->conn_interval_max;
+ hci_conn_params_put(params);
+ } else {
+ conn->conn_interval_min = hdev->le_conn_min_interval;
+ conn->conn_interval_max = hdev->le_conn_max_interval;
+ }
err = hci_create_le_conn(conn);
if (err)
--
1.8.4
^ permalink raw reply related
* [RFC v2 05/15] Bluetooth: Make find_conn_param() helper non-local
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch makes the find_conn_param() helper non-local by adding the
hci_ prefix and declaring it in hci_core.h. This helper will be used
in hci_conn.c to get the connection parameters when establishing
connections.
Since hci_find_conn_param() returns a reference to the hci_conn_param
object, it was added a refcount to hci_conn_param to control its
lifetime. This way, we avoid bugs such as use-after-free.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 5 +++++
net/bluetooth/hci_core.c | 45 ++++++++++++++++++++++++++++++++++------
2 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 22d16d9..64911aa 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -378,6 +378,8 @@ struct hci_chan {
};
struct hci_conn_params {
+ struct kref refcount;
+
struct list_head list;
bdaddr_t addr;
@@ -767,6 +769,9 @@ int hci_add_conn_params(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
u16 conn_interval_max);
void hci_remove_conn_params(struct hci_dev *hdev, bdaddr_t *addr,
u8 addr_type);
+struct hci_conn_params *hci_find_conn_params(struct hci_dev *hdev,
+ bdaddr_t *addr, u8 addr_type);
+void hci_conn_params_put(struct hci_conn_params *params);
int hci_uuids_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index fa41a58..0a278da 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2771,8 +2771,33 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
return mgmt_device_unblocked(hdev, bdaddr, type);
}
-static struct hci_conn_params *find_conn_params(struct hci_dev *hdev,
- bdaddr_t *addr, u8 addr_type)
+static void hci_conn_params_get(struct hci_conn_params *params)
+{
+ kref_get(¶ms->refcount);
+}
+
+static void release_hci_conn_params(struct kref *kref)
+{
+ struct hci_conn_params *params = container_of(kref,
+ struct hci_conn_params,
+ refcount);
+
+ kfree(params);
+}
+
+void hci_conn_params_put(struct hci_conn_params *params)
+{
+ kref_put(¶ms->refcount, release_hci_conn_params);
+}
+
+/* Lookup hci_conn_params in hdev->conn_params list.
+ *
+ * Return a reference to hci_conn_params object with refcount incremented.
+ * The caller should drop its reference by using hci_conn_params_put(). If
+ * hci_conn_params is not found, NULL is returned.
+ */
+struct hci_conn_params *hci_find_conn_params(struct hci_dev *hdev,
+ bdaddr_t *addr, u8 addr_type)
{
struct hci_conn_params *params;
@@ -2784,6 +2809,8 @@ static struct hci_conn_params *find_conn_params(struct hci_dev *hdev,
if (params->addr_type != addr_type)
continue;
+ hci_conn_params_get(params);
+
rcu_read_unlock();
return params;
}
@@ -2798,14 +2825,18 @@ int hci_add_conn_params(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
{
struct hci_conn_params *params;
- params = find_conn_params(hdev, addr, addr_type);
- if (params)
+ params = hci_find_conn_params(hdev, addr, addr_type);
+ if (params) {
+ hci_conn_params_put(params);
return -EEXIST;
+ }
params = kmalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
+ kref_init(¶ms->refcount);
+
bacpy(¶ms->addr, addr);
params->addr_type = addr_type;
params->auto_connect = auto_connect;
@@ -2827,20 +2858,22 @@ static void __remove_conn_params(struct hci_conn_params *params)
list_del_rcu(¶ms->list);
synchronize_rcu();
- kfree(params);
+ hci_conn_params_put(params);
}
void hci_remove_conn_params(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
{
struct hci_conn_params *params;
- params = find_conn_params(hdev, addr, addr_type);
+ params = hci_find_conn_params(hdev, addr, addr_type);
if (!params)
return;
hci_dev_lock(hdev);
__remove_conn_params(params);
hci_dev_unlock(hdev);
+
+ hci_conn_params_put(params);
}
/* Remove all elements from hdev->conn_params list.
--
1.8.4
^ permalink raw reply related
* [RFC v2 04/15] Bluetooth: Introduce connection parameters list
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch adds to hdev the connection parameters list (hdev->
conn_params). The elements from this list (struct hci_conn_params)
contains the connection parameters (for now, minimum and maximum
connection interval) that should be used during the connection
establishment.
The struct hci_conn_params also defines the 'auto_connect' field
which will be used to implement the auto connection mechanism.
Moreover, this patch adds helper functions to manipulate hdev->conn_
params list. Some of these functions are also declared in hci_core.h
since they will be used outside hci_core.c in upcoming patches.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 24 +++++++++++
net/bluetooth/hci_core.c | 86 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 037a7b5..22d16d9 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -271,6 +271,8 @@ struct hci_dev {
struct list_head remote_oob_data;
+ struct list_head conn_params;
+
struct hci_dev_stats stat;
atomic_t promisc;
@@ -375,6 +377,22 @@ struct hci_chan {
__u8 state;
};
+struct hci_conn_params {
+ struct list_head list;
+
+ bdaddr_t addr;
+ u8 addr_type;
+
+ enum {
+ HCI_AUTO_CONN_DISABLED,
+ HCI_AUTO_CONN_ALWAYS,
+ HCI_AUTO_CONN_LINK_LOSS,
+ } auto_connect;
+
+ u16 conn_interval_min;
+ u16 conn_interval_max;
+};
+
extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock;
@@ -744,6 +762,12 @@ int hci_blacklist_clear(struct hci_dev *hdev);
int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
+int hci_add_conn_params(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
+ u8 auto_connect, u16 conn_interval_min,
+ u16 conn_interval_max);
+void hci_remove_conn_params(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type);
+
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 6ccc4eb..fa41a58 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2771,6 +2771,90 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
return mgmt_device_unblocked(hdev, bdaddr, type);
}
+static struct hci_conn_params *find_conn_params(struct hci_dev *hdev,
+ bdaddr_t *addr, u8 addr_type)
+{
+ struct hci_conn_params *params;
+
+ rcu_read_lock();
+
+ list_for_each_entry(params, &hdev->conn_params, list) {
+ if (bacmp(¶ms->addr, addr))
+ continue;
+ if (params->addr_type != addr_type)
+ continue;
+
+ rcu_read_unlock();
+ return params;
+ }
+
+ rcu_read_unlock();
+ return NULL;
+}
+
+int hci_add_conn_params(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
+ u8 auto_connect, u16 conn_interval_min,
+ u16 conn_interval_max)
+{
+ struct hci_conn_params *params;
+
+ params = find_conn_params(hdev, addr, addr_type);
+ if (params)
+ return -EEXIST;
+
+ params = kmalloc(sizeof(*params), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+
+ bacpy(¶ms->addr, addr);
+ params->addr_type = addr_type;
+ params->auto_connect = auto_connect;
+ params->conn_interval_min = conn_interval_min;
+ params->conn_interval_max = conn_interval_max;
+
+ hci_dev_lock(hdev);
+ list_add_rcu(¶ms->list, &hdev->conn_params);
+ hci_dev_unlock(hdev);
+ return 0;
+}
+
+/* Remove from hdev->conn_params and free hci_conn_params.
+ *
+ * This function requires the caller holds hdev->lock.
+ */
+static void __remove_conn_params(struct hci_conn_params *params)
+{
+ list_del_rcu(¶ms->list);
+ synchronize_rcu();
+
+ kfree(params);
+}
+
+void hci_remove_conn_params(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+ struct hci_conn_params *params;
+
+ params = find_conn_params(hdev, addr, addr_type);
+ if (!params)
+ return;
+
+ hci_dev_lock(hdev);
+ __remove_conn_params(params);
+ hci_dev_unlock(hdev);
+}
+
+/* Remove all elements from hdev->conn_params list.
+ *
+ * This function requires the caller holds hdev->lock.
+ */
+static void __clear_conn_params(struct hci_dev *hdev)
+{
+ struct hci_conn_params *params, *tmp;
+
+ list_for_each_entry_safe(params, tmp, &hdev->conn_params, list)
+ __remove_conn_params(params);
+}
+
static void inquiry_complete(struct hci_dev *hdev, u8 status)
{
if (status) {
@@ -2881,6 +2965,7 @@ struct hci_dev *hci_alloc_dev(void)
INIT_LIST_HEAD(&hdev->link_keys);
INIT_LIST_HEAD(&hdev->long_term_keys);
INIT_LIST_HEAD(&hdev->remote_oob_data);
+ INIT_LIST_HEAD(&hdev->conn_params);
INIT_LIST_HEAD(&hdev->conn_hash.list);
INIT_WORK(&hdev->rx_work, hci_rx_work);
@@ -3066,6 +3151,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_link_keys_clear(hdev);
hci_smp_ltks_clear(hdev);
hci_remote_oob_data_clear(hdev);
+ __clear_conn_params(hdev);
hci_dev_unlock(hdev);
hci_dev_put(hdev);
--
1.8.4
^ permalink raw reply related
* [RFC v2 03/15] Bluetooth: Stop scanning on connection
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
Some LE controllers don't support scanning and creating a connection
at the same time. So, for those controllers, we should stop scanning
in order to establish the connection.
Since we may prematurely stop the discovery procedure in favor of
the connection establishment, we should also cancel hdev->le_scan_
disable delayed work and set the discovery state to DISCOVERY_STOPPED.
This change does a small improvement since it is not mandatory user
stops scanning before connecting anymore. Moreover, this change is
required by upcoming LE auto connection mechanism in order to work
properly with controllers that don't support background scanning and
connection establishment at the same time.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_conn.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 9fb7b44..195b78f 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -518,8 +518,11 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
{
struct hci_conn *conn;
- if (status == 0)
+ if (status == 0) {
+ cancel_delayed_work(&hdev->le_scan_disable);
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
return;
+ }
BT_ERR("HCI request failed to create LE connection: status 0x%2.2x",
status);
@@ -543,6 +546,17 @@ done:
hci_dev_unlock(hdev);
}
+/* Check if controller supports creating a connection while scanning is
+ * runnning.
+ */
+static bool is_scan_and_conn_supported(struct hci_dev *hdev)
+{
+ u8 mask = BIT(6) | BIT(7);
+
+ /* Return true if both bits are set */
+ return (hdev->le_states[2] & mask) == mask;
+}
+
static int hci_create_le_conn(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
@@ -552,6 +566,20 @@ static int hci_create_le_conn(struct hci_conn *conn)
hci_req_init(&req, hdev);
+ /* If controller is scanning but it doesn't support scanning and
+ * creating a connection at the same time, we stop scanning.
+ * Otherwise, LE Create Connection command fails.
+ */
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
+ !is_scan_and_conn_supported(hdev)) {
+ struct hci_cp_le_set_scan_enable enable_cp;
+
+ memset(&enable_cp, 0, sizeof(enable_cp));
+ enable_cp.enable = LE_SCAN_DISABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+ &enable_cp);
+ }
+
memset(&cp, 0, sizeof(cp));
cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
cp.scan_window = cpu_to_le16(hdev->le_scan_window);
--
1.8.4
^ permalink raw reply related
* [RFC v2 02/15] Bluetooth: Save connection interval parameters in hci_conn
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
This patch creates two new fields in struct hci_conn to save the
minimum and maximum connection interval values used to establish
the connection this object represents.
This change is required in order to know what parameters the
connection is currently using.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 3 +++
net/bluetooth/hci_conn.c | 6 ++++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8c0ab3d..037a7b5 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -341,6 +341,9 @@ struct hci_conn {
unsigned int sent;
+ __u16 conn_interval_min;
+ __u16 conn_interval_max;
+
struct sk_buff_head data_q;
struct list_head chan_list;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index ba5366c..9fb7b44 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -558,8 +558,8 @@ static int hci_create_le_conn(struct hci_conn *conn)
bacpy(&cp.peer_addr, &conn->dst);
cp.peer_addr_type = conn->dst_type;
cp.own_address_type = conn->src_type;
- cp.conn_interval_min = cpu_to_le16(hdev->le_conn_min_interval);
- cp.conn_interval_max = cpu_to_le16(hdev->le_conn_max_interval);
+ cp.conn_interval_min = cpu_to_le16(conn->conn_interval_min);
+ cp.conn_interval_max = cpu_to_le16(conn->conn_interval_max);
cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
cp.min_ce_len = __constant_cpu_to_le16(0x0000);
cp.max_ce_len = __constant_cpu_to_le16(0x0000);
@@ -624,6 +624,8 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
conn->sec_level = BT_SECURITY_LOW;
conn->pending_sec_level = sec_level;
conn->auth_type = auth_type;
+ conn->conn_interval_min = hdev->le_conn_min_interval;
+ conn->conn_interval_max = hdev->le_conn_max_interval;
err = hci_create_le_conn(conn);
if (err)
--
1.8.4
^ permalink raw reply related
* [RFC v2 01/15] Bluetooth: Refactor hci_disconn_complete_evt
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383053160-10175-1-git-send-email-andre.guedes@openbossa.org>
hci_disconn_complete_evt() logic is more complicated than what it
should be, making it hard to follow and add new features.
So this patch does some code refactoring by handling the error cases
in the beginning of the function and by moving the main flow into the
first level of function scope. No change is done in the event handling
logic itself.
Besides organizing this messy code, this patch makes easier to add
code for handling LE auto connection (which will be added in a further
patch).
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
net/bluetooth/hci_event.c | 62 +++++++++++++++++++++++++----------------------
1 file changed, 33 insertions(+), 29 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 5935f74..8b7cd37 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1783,6 +1783,8 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_disconn_complete *ev = (void *) skb->data;
struct hci_conn *conn;
+ u8 type;
+ bool send_mgmt_event = false;
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
@@ -1792,44 +1794,46 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (!conn)
goto unlock;
- if (ev->status == 0)
- conn->state = BT_CLOSED;
-
if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
- (conn->type == ACL_LINK || conn->type == LE_LINK)) {
- if (ev->status) {
+ (conn->type == ACL_LINK || conn->type == LE_LINK))
+ send_mgmt_event = true;
+
+ if (ev->status) {
+ if (send_mgmt_event)
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
conn->dst_type, ev->status);
- } else {
- u8 reason = hci_to_mgmt_reason(ev->reason);
-
- mgmt_device_disconnected(hdev, &conn->dst, conn->type,
- conn->dst_type, reason);
- }
+ return;
}
- if (ev->status == 0) {
- u8 type = conn->type;
+ conn->state = BT_CLOSED;
- if (type == ACL_LINK && conn->flush_key)
- hci_remove_link_key(hdev, &conn->dst);
- hci_proto_disconn_cfm(conn, ev->reason);
- hci_conn_del(conn);
+ if (send_mgmt_event) {
+ u8 reason = hci_to_mgmt_reason(ev->reason);
- /* Re-enable advertising if necessary, since it might
- * have been disabled by the connection. From the
- * HCI_LE_Set_Advertise_Enable command description in
- * the core specification (v4.0):
- * "The Controller shall continue advertising until the Host
- * issues an LE_Set_Advertise_Enable command with
- * Advertising_Enable set to 0x00 (Advertising is disabled)
- * or until a connection is created or until the Advertising
- * is timed out due to Directed Advertising."
- */
- if (type == LE_LINK)
- mgmt_reenable_advertising(hdev);
+ mgmt_device_disconnected(hdev, &conn->dst, conn->type,
+ conn->dst_type, reason);
}
+ if (conn->type == ACL_LINK && conn->flush_key)
+ hci_remove_link_key(hdev, &conn->dst);
+
+ type = conn->type;
+ hci_proto_disconn_cfm(conn, ev->reason);
+ hci_conn_del(conn);
+
+ /* Re-enable advertising if necessary, since it might
+ * have been disabled by the connection. From the
+ * HCI_LE_Set_Advertise_Enable command description in
+ * the core specification (v4.0):
+ * "The Controller shall continue advertising until the Host
+ * issues an LE_Set_Advertise_Enable command with
+ * Advertising_Enable set to 0x00 (Advertising is disabled)
+ * or until a connection is created or until the Advertising
+ * is timed out due to Directed Advertising."
+ */
+ if (type == LE_LINK)
+ mgmt_reenable_advertising(hdev);
+
unlock:
hci_dev_unlock(hdev);
}
--
1.8.4
^ permalink raw reply related
* [RFC v2 00/15] LE auto connection and connection parameters
From: Andre Guedes @ 2013-10-29 13:25 UTC (permalink / raw)
To: linux-bluetooth
Hi all,
Sorry about the delay of this patch set.
This v2 patch set implements Marcel's comments from the previous one. The main
changes are:
* The patch set was reorganized, all refactoring and improving was placed at
the beginning of the set.
* Minimum and maximum connection interval are saved in hci_conn so we are able
to know the connection parameters that are currently being used.
* The trigger/untrigger background scanning mechanism was replaced by a list
of pending auto connection. We keep background scan running as long as we
have elements in the list.
* New mgmt commands patches were moved to the end of the set.
It was suggested we change connect() behavior to use LE auto connection
infrastructure. To achieve that, we would have to change hci_connect_le() to
add a pending auto connection and hci_conn_timeout() to remove that pending
auto connection. However, this change is more complicated than what it seems.
The trick part is handling connection timeout. To properly handle connection
timeout, we have to delete the hci_conn object inside hci_conn_timeout() but
we cannot do it since since we get a dead lock. The problem is: a delayed work
thread executes hci_conn_timeout() which calls hci_conn_del(). hci_conn_del()
calls cancel_delayed_work_sync() which waits for itself.
Thus, since this change is not required to support LE auto connection and it
would delay even more this v2 patch set, connect() behavior was not changed.
If this change is really worth, we can do it in a separate patch set.
This patch set has been extensively tested with dongles that don't support
scanning and connection at the same time (e.g. PTS dongle) as well as with
dongles that support it. For testing purposes, patched btmgmt tool to support
the new mgmt commands (you can find patches in [1]).
Finally, this patch set is organized as follows:
* Patch 1-3: Refactoring and improvements.
* Patch 4-6: Use connection parameters specified by user.
* Patch 7-11: Add support for LE auto connection infrastructure
* Patch 12: Add support for auto connection options
* Patch 13-15: Add mgmt commands
Regards,
Andre
[1] - https://github.com/aguedes/bluez/commits/auto-connect
Andre Guedes (15):
Bluetooth: Refactor hci_disconn_complete_evt
Bluetooth: Save connection interval parameters in hci_conn
Bluetooth: Stop scanning on connection
Bluetooth: Introduce connection parameters list
Bluetooth: Make find_conn_param() helper non-local
Bluetooth: Use connection parameters if any
Bluetooth: Introduce hdev->pending_auto_conn list
Bluetooth: Move is_scan_and_conn_supported() to hci_core
Bluetooth: Introduce LE auto connection infrastructure
Bluetooth: Temporarily stop background scanning on discovery
Bluetooth: Auto connection and power on
Bleutooth: Add support for auto connect options
Bluetooth: Add thread-safe version of helpers
Bluetooth: Mgmt command for adding connection parameters
Bluetooth: Mgmt command for removing connection parameters
include/net/bluetooth/hci_core.h | 51 +++++
include/net/bluetooth/mgmt.h | 15 ++
net/bluetooth/hci_conn.c | 40 +++-
net/bluetooth/hci_core.c | 403 +++++++++++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 129 ++++++++++---
net/bluetooth/mgmt.c | 93 ++++++++-
6 files changed, 696 insertions(+), 35 deletions(-)
--
1.8.4
^ permalink raw reply
* Re: [PATCH 5/6] android/hal: Add device state changed event handler
From: Jakub Tyszkowski @ 2013-10-29 13:18 UTC (permalink / raw)
To: Andrei Emeltchenko, Jakub Tyszkowski, linux-bluetooth
In-Reply-To: <20131029123622.GF27517@aemeltch-MOBL1>
Hi Andrei,
I think the props packing part can be extracted and reused. Not sure
if other events will benefit from this.. probably just adapter props
event?
Thanks, I'll fix those.
On 29 October 2013 13:36, Andrei Emeltchenko
<andrei.emeltchenko.news@gmail.com> wrote:
> Hi Jakub,
>
> On Tue, Oct 29, 2013 at 01:16:55PM +0100, Jakub Tyszkowski wrote:
>> This is used to report property change of already reported remote
>> device.
>>
>> ---
>> android/hal-bluetooth.c | 26 ++++++++++++++++++++++++++
>> 1 file changed, 26 insertions(+)
>>
>> diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
>> index 261ae85..0fef680 100644
>> --- a/android/hal-bluetooth.c
>> +++ b/android/hal-bluetooth.c
>> @@ -114,6 +114,29 @@ static void handle_device_found(void *buf)
>> bt_hal_cbacks->device_found_cb(ev->num_props, send_props);
>> }
>>
>> +static void handle_device_state_changed(void *buf)
>> +{
>> + uint8_t i;
>
> I've got comment myself that first we put variables with assignments.
>
>> + struct hal_ev_remote_device_props *ev = buf;
>> + bt_property_t send_props[ev->num_props];
>> + struct hal_property *prop = ev->props;
>> +
>> + if (!bt_hal_cbacks->remote_device_properties_cb)
>> + return;
>> +
>> + /* repack props */
>> + for (i = 0; i < ev->num_props; ++i) {
>> + send_props[i].type = prop->type;
>> + send_props[i].len = prop->len;
>> + send_props[i].val = prop->val;
>> +
>> + prop = (void *) prop + (sizeof(*prop) + prop->len);
>> + }
>
> I would put empty line here. This looks a bit more readable then
> handle_adapter_props_changed. Do you think those 2 might have reused code?
>
> Best regards
> Andrei Emeltchenko
>
>
>> + bt_hal_cbacks->remote_device_properties_cb(ev->status,
>> + (bt_bdaddr_t *)ev->bdaddr,
>> + ev->num_props, send_props);
>> +}
>> +
>> /* will be called from notification thread context */
>> void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
>> {
>> @@ -133,6 +156,9 @@ void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
>> case HAL_EV_DEVICE_FOUND:
>> handle_device_found(buf);
>> break;
>> + case HAL_EV_REMOTE_DEVICE_PROPS:
>> + handle_device_state_changed(buf);
>> + break;
>> default:
>> DBG("Unhandled callback opcode=0x%x", opcode);
>> break;
>> --
>> 1.8.4.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2] android: Add README file with instructions
From: Andrei Emeltchenko @ 2013-10-29 13:07 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1383051302-9754-1-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Tue, Oct 29, 2013 at 01:55:02PM +0100, Szymon Janc wrote:
> This file cotains help on how BlueZ for Android should be build, run
> and test. Some hints and examples on how BlueZ can be intergrated into
> Android are present as well.
> ---
> V2:
> - rebased against master
> - clarify requirements on Android init system
>
> android/Makefile.am | 2 +-
> android/README | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 88 insertions(+), 1 deletion(-)
> create mode 100644 android/README
>
> diff --git a/android/Makefile.am b/android/Makefile.am
> index 22002be..5690e93 100644
> --- a/android/Makefile.am
> +++ b/android/Makefile.am
> @@ -96,7 +96,7 @@ EXTRA_DIST += android/client/terminal.c \
> android/client/history.h \
> android/client/terminal.h
>
> -EXTRA_DIST += android/hal-ipc-api.txt
> +EXTRA_DIST += android/hal-ipc-api.txt android/README
>
> EXTRA_DIST += android/hardware/bluetooth.h \
> android/hardware/bt_av.h \
> diff --git a/android/README b/android/README
> new file mode 100644
> index 0000000..ada2c2f
> --- /dev/null
> +++ b/android/README
> @@ -0,0 +1,87 @@
> +BlueZ for Android
> +*****************
> +
> +Since Android 4.2 there exists a well standardized HAL interface that the
> +Bluetooth stack is expected to provide and which enables the easy replacement
> +of the stack of choice on Android. Android BlueZ is intended as a drop-in
> +replacement to Android provided Bluetooth stack.
> +
> +More details about BlueZ for Android architecture and components can be found
> +in android/hal-apc-api.txt file.
> +
> +===============================
> +Building and running on Android
> +===============================
> +
> +Build requirements
> +==================
> +
> +- GLib - Android 4.2 or later don't provide GLib and one must provide it in
> +'external/bluetooth/glib' folder of Android tree. Sample Android GLib port
> +is available at https://code.google.com/p/android-bluez.glib/
> +
> +- Bionic support - BlueZ requires signalfd and timerfd APIs to be provided
> +by libc library. Currently only 'master' branch available at
> +https://android.googlesource.com/platform/bionic provides all required
> +functionality and running BlueZ on older branch requires backporting missing
> +features. Sample Bionic for Android on Intel Architecture (Android-IA) with all
> +required features backported is available at
> +https://code.google.com/p/android-bluez.bionic/
> +
> +Runtime requirements
> +====================
> +
> +BlueZ HAL library requires 'bluetoothd' service to be available on Android
> +system. This can be done by defining service in init.rc file of targeted board:
> +
> +service bluetoothd logwrapper /system/bin/bluetoothd
logwrapper cannot be found without the full path:
service bluetoothd /system/bin/logwrapper /system/bin/bluetoothd
> + class main
> + group bluetooth net_bt_stack
net_bt_stack seems to be bluedroid specific, currently we use
group bluetooth net_admin
otherwise looks good
Best regards
Andrei Emeltchenko
> + disabled
> + oneshot
> +
> +It is required that bluetooth user could start and stop bluetoothd service by
> +setting 'ctl.start' or 'ctl.stop' property.
> +
> +Required Android init system modifications can be found at
> +https://code.google.com/p/android-bluez.system-core/
> +
> +Downloading and building
> +========================
> +
> +Building for Android requires full Android AOSP source tree. Sample Android-IA
> +tree with all required components present is available at
> +http://code.google.com/p/android-bluez/
> +
> +Downloading:
> +repo init -u https://code.google.com/p/android-bluez.manifest/ -m topics/bluez
> +repo sync
> +
> +Build for Intel ultrabook:
> +'source build/envsetup.sh'
> +'lunch core_mesa-eng'
> +'make allimages -j8'
> +
> +After full build is done it is possible to rebuild only BlueZ:
> +'cd external/bluetooth/bluez/android/'
> +'mm' (or 'mm -B' to force rebuilding of all files)
> +'adb sync' to update target device.
> +
> +=============================
> +Building and running on Linux
> +=============================
> +It is possible to build and test BlueZ for Android daemon on Linux (eg. PC).
> +Simply follow instructions available at README file in BlueZ top directory.
> +Android daemon binary is located at android/bluetoothd.
> +
> +=======
> +Testing
> +=======
> +
> +BT HAL test tools located in android/haltest is provided for HAL level testing
> +of both Android daemon and HAL library. Start it and type 'adapter init' in
> +prompt to initialize HAL library. On Android required bluetoothd service will
> +be started automatically. On Linux it is required to start android/bluetoothd
> +manually before init command timeout. To deinitialize HAL library and stop
> +daemon type 'adapter cleanup'. Type 'help' for more information. Tab completion
> +is also supported.
> \ No newline at end of file
> --
> 1.8.4.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v4 1/2] android/hal: Add support for handling pin request event
From: Johan Hedberg @ 2013-10-29 13:06 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1383050945-7984-1-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Tue, Oct 29, 2013, Szymon Janc wrote:
> ---
> v4: Added comment clarifying that pointer casting is safe here
>
> android/hal-bluetooth.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
Both patches have been applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH] android: Fix build errors
From: Johan Hedberg @ 2013-10-29 13:05 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1383050922-27758-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Tue, Oct 29, 2013, Andrei Emeltchenko wrote:
> The patch fixes following issues when building:
>
> Make links to sco.h and rfcomm.h needed for Android sockets.
> ...
> btio.c:39:30: fatal error: bluetooth/rfcomm.h: No such file or directory
> compilation terminated.
> ...
> btio.c:40:27: fatal error: bluetooth/sco.h: No such file or directory
> compilation terminated.
> ...
> ---
> android/Android.mk | 2 ++
> 1 file changed, 2 insertions(+)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 1/6] android: Remove reduntant structure
From: Jakub Tyszkowski @ 2013-10-29 13:01 UTC (permalink / raw)
To: Jakub Tyszkowski, linux-bluetooth
In-Reply-To: <20131029122827.GA12345@x220.p-661hnu-f1>
Hi Johan,
Please ignore this patch then. I'll fix this or Szymon will.
On 29 October 2013 13:28, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Jakub,
>
> On Tue, Oct 29, 2013, Jakub Tyszkowski wrote:
>> ---
>> android/adapter.c | 3 +--
>> 1 file changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/android/adapter.c b/android/adapter.c
>> index 15b65e5..7e5c1a1 100644
>> --- a/android/adapter.c
>> +++ b/android/adapter.c
>> @@ -234,12 +234,11 @@ static void load_link_keys(GSList *keys)
>> {
>> struct mgmt_cp_load_link_keys *cp;
>> size_t key_len = g_slist_length(keys);
>> - struct mgmt_link_key_info *key;
>> size_t len;
>>
>> DBG("");
>>
>> - len = sizeof(*cp) + key_len * sizeof(*key);
>> + len = sizeof(*cp) + key_len * sizeof(struct mgmt_link_key_info);
>> cp = g_malloc0(len);
>>
>> cp->debug_keys = 0;
>
> If the point of the keys list is to contain struct mgmt_link_key_info
> entries I'd rather fix this function to properly fill in the mgmt
> command with those since right now it's broken if the list contains any
> entries at all.
>
> Johan
^ permalink raw reply
* [PATCHv3 9/9] android: Fix build errors
From: Andrei Emeltchenko @ 2013-10-29 12:57 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383051459-29495-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
The patch fixes following issues when building:
Make links to sco.h and rfcomm.h needed for Android sockets.
...
btio.c:39:30: fatal error: bluetooth/rfcomm.h: No such file or directory
compilation terminated.
...
btio.c:40:27: fatal error: bluetooth/sco.h: No such file or directory
compilation terminated.
...
---
android/Android.mk | 2 ++
1 file changed, 2 insertions(+)
diff --git a/android/Android.mk b/android/Android.mk
index 28ec465..d8f9d0d 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -52,6 +52,8 @@ lib_headers := \
l2cap.h \
sdp_lib.h \
sdp.h \
+ rfcomm.h \
+ sco.h \
$(shell mkdir -p $(LOCAL_PATH)/../lib/bluetooth)
--
1.7.10.4
^ permalink raw reply related
* [PATCHv3 8/9] android: Use thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-29 12:57 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383051459-29495-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Make use of thread-safe helpers.
---
android/client/textconv.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/android/client/textconv.c b/android/client/textconv.c
index 1dc6ad0..effd1b3 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -19,6 +19,8 @@
#include <stdio.h>
#include <hardware/bluetooth.h>
+#include "../pthread-local.h"
+
#include "textconv.h"
/*
@@ -227,11 +229,12 @@ const char *enum_one_string(void *v, int i)
return (i == 0) && (m[0] != 0) ? m : NULL;
}
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(bdaddr);
char *bdaddr2str(const bt_bdaddr_t *bd_addr)
{
- static char buf[MAX_ADDR_STR_LEN];
+ LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, bdaddr, MAX_ADDR_STR_LEN);
- return bt_bdaddr_t2str(bd_addr, buf);
+ return bt_bdaddr_t2str(bd_addr, bdaddr_tls_buffer);
}
static char *btuuid2str(const bt_uuid_t *uuid)
@@ -241,12 +244,14 @@ static char *btuuid2str(const bt_uuid_t *uuid)
return bt_uuid_t2str(uuid, buf);
}
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(property);
char *btproperty2str(const bt_property_t *property)
{
- static char buf[4096];
char *p;
+ LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, property, 4096);
- p = buf + sprintf(buf, "type=%s len=%d val=",
+ p = property_tls_buffer + sprintf(property_tls_buffer,
+ "type=%s len=%d val=",
bt_property_type_t2str(property->type),
property->len);
@@ -334,5 +339,5 @@ char *btproperty2str(const bt_property_t *property)
sprintf(p, "%p", property->val);
}
- return buf;
+ return property_tls_buffer;
}
--
1.7.10.4
^ permalink raw reply related
* [PATCHv3 7/9] android: Add thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-29 12:57 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383051459-29495-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add thread safe helpers to make HAL debug printing thread-safe. The code
is inherited from Android bionic and it is used for strerror, strsignal,
etc.
---
android/pthread-local.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 android/pthread-local.h
diff --git a/android/pthread-local.h b/android/pthread-local.h
new file mode 100644
index 0000000..bc3c0b3
--- /dev/null
+++ b/android/pthread-local.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 Intel Corp.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <pthread.h>
+#include <stdlib.h>
+
+#define GLOBAL_INIT_THREAD_LOCAL_BUFFER(name) \
+ static pthread_key_t __tls_ ## name ## _key; \
+ static void __tls_ ## name ## _key_destroy(void *buffer) \
+ { \
+ free(buffer); \
+ } \
+ static void __attribute__((constructor)) __tls_ ## name ## _key_init() \
+ { \
+ pthread_key_create(&__tls_ ## name ## _key, \
+ __tls_ ## name ## _key_destroy); \
+ }
+
+/*
+ * Leaves "name_tls_buffer" and "name_tls_buffer_size" defined and initialized.
+ */
+#define LOCAL_INIT_THREAD_LOCAL_BUFFER(type, name, byte_count) \
+ const size_t name ## _tls_buffer_size \
+ __attribute__((unused)) = byte_count; \
+ type name ## _tls_buffer = \
+ (pthread_getspecific(__tls_ ## name ## _key)); \
+ if (name ## _tls_buffer == NULL) { \
+ name ## _tls_buffer = (calloc(1, byte_count)); \
+ pthread_setspecific(__tls_ ## name ## _key, \
+ name ## _tls_buffer); \
+ }
--
1.7.10.4
^ permalink raw reply related
* [PATCHv3 6/9] android/hal: Print adapter property in callback
From: Andrei Emeltchenko @ 2013-10-29 12:57 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383051459-29495-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/hal-bluetooth.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 4d467ee..cc63bd9 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -65,6 +65,8 @@ static void handle_adapter_props_changed(void *buf, uint16_t len)
p += sizeof(*hal_prop) + hal_prop->len;
hal_prop = p;
+
+ DBG("prop[%d]: %s", i, btproperty2str(&props[i]));
}
bt_hal_cbacks->adapter_properties_cb(ev->status, ev->num_props, props);
--
1.7.10.4
^ permalink raw reply related
* [PATCHv3 5/9] android/hal: Print adapter state
From: Andrei Emeltchenko @ 2013-10-29 12:57 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1383051459-29495-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/hal-bluetooth.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 85ccded..4d467ee 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -33,6 +33,8 @@ static void handle_adapter_state_changed(void *buf)
{
struct hal_ev_adapter_state_changed *ev = buf;
+ DBG("state: %s", bt_state_t2str(ev->state));
+
if (bt_hal_cbacks->adapter_state_changed_cb)
bt_hal_cbacks->adapter_state_changed_cb(ev->state);
}
--
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