* [PATCHv7 13/19] Bluetooth: AMP: Add AMP key calculation
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Function calculates AMP keys using hmac_sha256 helper. Calculated keys
are Generic AMP Link Key (gamp) and Dedicated AMP Link Key with
keyID "802b" for 802.11 PAL.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/amp.h | 2 ++
net/bluetooth/Kconfig | 1 +
net/bluetooth/amp.c | 45 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 48 insertions(+)
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index f57854f..763b463 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -32,6 +32,8 @@ void amp_ctrl_list_flush(struct amp_mgr *mgr);
struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
u8 remote_id);
+int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
+
void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 3537d38..1c11d0d 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -11,6 +11,7 @@ menuconfig BT
select CRYPTO_BLKCIPHER
select CRYPTO_AES
select CRYPTO_ECB
+ select CRYPTO_SHA256
help
Bluetooth is low-cost, low-power, short-range wireless technology.
It was designed as a replacement for cables and other short-range
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index ea4d5ff..67bc2c2f 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -161,6 +161,51 @@ static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
return ret;
}
+int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct link_key *key;
+ u8 keybuf[HCI_AMP_LINK_KEY_SIZE];
+ u8 gamp_key[HCI_AMP_LINK_KEY_SIZE];
+ int err;
+
+ if (!hci_conn_check_link_mode(conn))
+ return -EACCES;
+
+ BT_DBG("conn %p key_type %d", conn, conn->key_type);
+
+ /* Legacy key */
+ if (conn->key_type < 3) {
+ BT_ERR("Legacy key type %d", conn->key_type);
+ return -EACCES;
+ }
+
+ *type = conn->key_type;
+ *len = HCI_AMP_LINK_KEY_SIZE;
+
+ key = hci_find_link_key(hdev, &conn->dst);
+
+ /* BR/EDR Link Key concatenated together with itself */
+ memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE);
+ memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE);
+
+ /* Derive Generic AMP Link Key (gamp) */
+ err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key);
+ if (err) {
+ BT_ERR("Could not derive Generic AMP Key: err %d", err);
+ return err;
+ }
+
+ if (conn->key_type == HCI_LK_DEBUG_COMBINATION) {
+ BT_DBG("Use Generic AMP Key (gamp)");
+ memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE);
+ return err;
+ }
+
+ /* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */
+ return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data);
+}
+
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
{
struct hci_cp_read_local_amp_assoc cp;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 12/19] Bluetooth: Add function to derive AMP key using hmac
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
hmac(sha256) will be used for AMP key generation.
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
net/bluetooth/amp.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 8ef912c..ea4d5ff 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -16,6 +16,7 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/a2mp.h>
#include <net/bluetooth/amp.h>
+#include <crypto/hash.h>
/* Remote AMP Controllers interface */
static void amp_ctrl_get(struct amp_ctrl *ctrl)
@@ -125,6 +126,41 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
return hcon;
}
+/* AMP crypto key generation interface */
+static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
+{
+ int ret = 0;
+ struct crypto_shash *tfm;
+
+ if (!ksize)
+ return -EINVAL;
+
+ tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+ if (IS_ERR(tfm)) {
+ BT_DBG("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm));
+ return PTR_ERR(tfm);
+ }
+
+ ret = crypto_shash_setkey(tfm, key, ksize);
+ if (ret) {
+ BT_DBG("crypto_ahash_setkey failed: err %d", ret);
+ } else {
+ struct {
+ struct shash_desc shash;
+ char ctx[crypto_shash_descsize(tfm)];
+ } desc;
+
+ desc.shash.tfm = tfm;
+ desc.shash.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ ret = crypto_shash_digest(&desc.shash, plaintext, psize,
+ output);
+ }
+
+ crypto_free_shash(tfm);
+ return ret;
+}
+
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
{
struct hci_cp_read_local_amp_assoc cp;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 11/19] Bluetooth: Choose connection based on capabilities
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Choose which L2CAP connection to establish by checking support
for HS and remote side supported features.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/a2mp.h | 2 ++
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/a2mp.c | 34 +++++++++++++++++++++++++++++-----
net/bluetooth/l2cap_core.c | 33 ++++++++++++++++++++++++++++-----
4 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 99c7389..9fda7c9 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -28,6 +28,7 @@ struct amp_mgr {
struct list_head list;
struct l2cap_conn *l2cap_conn;
struct l2cap_chan *a2mp_chan;
+ struct l2cap_chan *bredr_chan;
struct kref kref;
__u8 ident;
__u8 handle;
@@ -137,6 +138,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct sk_buff *skb);
struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
+void a2mp_discover_amp(struct l2cap_chan *chan);
void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7ed8e35..aba830f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -767,6 +767,7 @@ int l2cap_chan_check_security(struct l2cap_chan *chan);
void l2cap_chan_set_defaults(struct l2cap_chan *chan);
int l2cap_ertm_init(struct l2cap_chan *chan);
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void l2cap_chan_del(struct l2cap_chan *chan, int err);
#endif /* __L2CAP_H */
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index d0fde05..93adaad 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -638,7 +638,7 @@ static struct l2cap_ops a2mp_chan_ops = {
.ready = l2cap_chan_no_ready,
};
-static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
+static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
{
struct l2cap_chan *chan;
int err;
@@ -673,7 +673,10 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
chan->conf_state = 0;
- l2cap_chan_add(conn, chan);
+ if (locked)
+ __l2cap_chan_add(conn, chan);
+ else
+ l2cap_chan_add(conn, chan);
chan->remote_mps = chan->omtu;
chan->mps = chan->omtu;
@@ -712,7 +715,7 @@ int amp_mgr_put(struct amp_mgr *mgr)
return kref_put(&mgr->kref, &_mgr_destroy);
}
-static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
+static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked)
{
struct amp_mgr *mgr;
struct l2cap_chan *chan;
@@ -725,7 +728,7 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
mgr->l2cap_conn = conn;
- chan = a2mp_chan_open(conn);
+ chan = a2mp_chan_open(conn, locked);
if (!chan) {
kfree(mgr);
return NULL;
@@ -754,7 +757,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
{
struct amp_mgr *mgr;
- mgr = amp_mgr_create(conn);
+ mgr = amp_mgr_create(conn, false);
if (!mgr) {
BT_ERR("Could not create AMP manager");
return NULL;
@@ -842,3 +845,24 @@ void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
amp_mgr_put(mgr);
kfree(rsp);
}
+
+void a2mp_discover_amp(struct l2cap_chan *chan)
+{
+ struct l2cap_conn *conn = chan->conn;
+ struct amp_mgr *mgr = conn->hcon->amp_mgr;
+ struct a2mp_discov_req req;
+
+ BT_DBG("chan %p conn %p mgr %p", chan, conn, mgr);
+
+ if (!mgr) {
+ mgr = amp_mgr_create(conn, true);
+ if (!mgr)
+ return;
+ }
+
+ mgr->bredr_chan = chan;
+
+ req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
+ req.ext_feat = 0;
+ a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req);
+}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 0873345..0dc3a98 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -455,7 +455,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
}
-static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
+void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
{
BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
__le16_to_cpu(chan->psm), chan->dcid);
@@ -946,6 +946,18 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
}
+static bool __amp_capable(struct l2cap_chan *chan)
+{
+ struct l2cap_conn *conn = chan->conn;
+
+ if (enable_hs &&
+ chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED &&
+ conn->fixed_chan_mask & L2CAP_FC_A2MP)
+ return true;
+ else
+ return false;
+}
+
static void l2cap_send_conn_req(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;
@@ -972,6 +984,16 @@ static void l2cap_chan_ready(struct l2cap_chan *chan)
chan->ops->ready(chan);
}
+static void l2cap_start_connection(struct l2cap_chan *chan)
+{
+ if (__amp_capable(chan)) {
+ BT_DBG("chan %p AMP capable: discover AMPs", chan);
+ a2mp_discover_amp(chan);
+ } else {
+ l2cap_send_conn_req(chan);
+ }
+}
+
static void l2cap_do_start(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;
@@ -986,8 +1008,9 @@ static void l2cap_do_start(struct l2cap_chan *chan)
return;
if (l2cap_chan_check_security(chan) &&
- __l2cap_no_conn_pending(chan))
- l2cap_send_conn_req(chan);
+ __l2cap_no_conn_pending(chan)) {
+ l2cap_start_connection(chan);
+ }
} else {
struct l2cap_info_req req;
req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
@@ -1082,7 +1105,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
continue;
}
- l2cap_send_conn_req(chan);
+ l2cap_start_connection(chan);
} else if (chan->state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
@@ -5462,7 +5485,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (chan->state == BT_CONNECT) {
if (!status) {
- l2cap_send_conn_req(chan);
+ l2cap_start_connection(chan);
} else {
__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 10/19] Bluetooth: A2MP: Process A2MP Get AMP Assoc Rsp
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving A2MP Get AMP Assoc Response save assoc data to remote
AMP controller list and prepare for creating physical link.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
net/bluetooth/a2mp.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 59 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 594df96..d0fde05 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -343,6 +343,61 @@ done:
return 0;
}
+static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_amp_assoc_rsp *rsp = (void *) skb->data;
+ u16 len = le16_to_cpu(hdr->len);
+ struct hci_dev *hdev;
+ struct amp_ctrl *ctrl;
+ struct hci_conn *hcon;
+
+ if (len < sizeof(*rsp))
+ return -EINVAL;
+
+ BT_DBG("id %d status 0x%2.2x assoc len %u", rsp->id, rsp->status,
+ len - sizeof(*rsp));
+
+ if (rsp->status)
+ return -EINVAL;
+
+ /* Save remote ASSOC data */
+ ctrl = amp_ctrl_lookup(mgr, rsp->id);
+ if (ctrl) {
+ u8 *assoc, assoc_len = len - sizeof(*rsp);
+
+ assoc = kzalloc(assoc_len, GFP_KERNEL);
+ if (!assoc) {
+ amp_ctrl_put(ctrl);
+ return -ENOMEM;
+ }
+
+ memcpy(assoc, rsp->amp_assoc, assoc_len);
+ ctrl->assoc = assoc;
+ ctrl->assoc_len = assoc_len;
+ ctrl->assoc_rem_len = assoc_len;
+ ctrl->assoc_len_so_far = 0;
+
+ amp_ctrl_put(ctrl);
+ }
+
+ /* Create Phys Link */
+ hdev = hci_dev_get(rsp->id);
+ if (!hdev)
+ return -EINVAL;
+
+ hcon = phylink_add(hdev, mgr, rsp->id);
+ if (!hcon)
+ goto done;
+
+ BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id);
+
+done:
+ hci_dev_put(hdev);
+ skb_pull(skb, len);
+ return 0;
+}
+
static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
@@ -502,8 +557,11 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
err = a2mp_getinfo_rsp(mgr, skb, hdr);
break;
- case A2MP_CHANGE_RSP:
case A2MP_GETAMPASSOC_RSP:
+ err = a2mp_getampassoc_rsp(mgr, skb, hdr);
+ break;
+
+ case A2MP_CHANGE_RSP:
case A2MP_CREATEPHYSLINK_RSP:
case A2MP_DISCONNPHYSLINK_RSP:
err = a2mp_cmd_rsp(mgr, skb, hdr);
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 09/19] Bluetooth: A2MP: Process A2MP Getinfo Rsp
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Process A2MP Getinfo Response, send Get AMP Assoc Req.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
net/bluetooth/a2mp.c | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 0125417..594df96 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -271,6 +271,35 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
return 0;
}
+static int a2mp_getinfo_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_info_rsp *rsp = (struct a2mp_info_rsp *) skb->data;
+ struct a2mp_amp_assoc_req req;
+ struct amp_ctrl *ctrl;
+
+ if (le16_to_cpu(hdr->len) < sizeof(*rsp))
+ return -EINVAL;
+
+ BT_DBG("id %d status 0x%2.2x", rsp->id, rsp->status);
+
+ if (rsp->status)
+ return -EINVAL;
+
+ ctrl = amp_ctrl_add(mgr);
+ if (!ctrl)
+ return -ENOMEM;
+
+ ctrl->id = rsp->id;
+
+ req.id = rsp->id;
+ a2mp_send(mgr, A2MP_GETAMPASSOC_REQ, __next_ident(mgr), sizeof(req),
+ &req);
+
+ skb_pull(skb, sizeof(*rsp));
+ return 0;
+}
+
static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
@@ -469,8 +498,11 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
err = a2mp_discover_rsp(mgr, skb, hdr);
break;
- case A2MP_CHANGE_RSP:
case A2MP_GETINFO_RSP:
+ err = a2mp_getinfo_rsp(mgr, skb, hdr);
+ break;
+
+ case A2MP_CHANGE_RSP:
case A2MP_GETAMPASSOC_RSP:
case A2MP_CREATEPHYSLINK_RSP:
case A2MP_DISCONNPHYSLINK_RSP:
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 08/19] Bluetooth: AMP: Handle create / disc phylink req
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Use hci_conn structure to keep track about AMP physical connections.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
net/bluetooth/a2mp.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 35e188c..0125417 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -321,6 +321,7 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_physlink_rsp rsp;
struct hci_dev *hdev;
+ struct hci_conn *hcon;
if (le16_to_cpu(hdr->len) < sizeof(*req))
return -EINVAL;
@@ -338,7 +339,14 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
/* TODO process physlink create */
- rsp.status = A2MP_STATUS_SUCCESS;
+ hcon = phylink_add(hdev, mgr, req->local_id);
+ if (hcon) {
+ BT_DBG("hcon %p", hcon);
+
+ rsp.status = A2MP_STATUS_SUCCESS;
+ } else {
+ rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
+ }
send_rsp:
if (hdev)
@@ -357,6 +365,7 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_physlink_req *req = (void *) skb->data;
struct a2mp_physlink_rsp rsp;
struct hci_dev *hdev;
+ struct hci_conn *hcon;
if (le16_to_cpu(hdr->len) < sizeof(*req))
return -EINVAL;
@@ -367,14 +376,22 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
rsp.remote_id = req->local_id;
rsp.status = A2MP_STATUS_SUCCESS;
- hdev = hci_dev_get(req->local_id);
+ hdev = hci_dev_get(req->remote_id);
if (!hdev) {
rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
goto send_rsp;
}
+ hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, mgr->l2cap_conn->dst);
+ if (!hcon) {
+ BT_ERR("No phys link exist");
+ rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS;
+ goto clean;
+ }
+
/* TODO Disconnect Phys Link here */
+clean:
hci_dev_put(hdev);
send_rsp:
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 07/19] Bluetooth: AMP: Remote AMP ctrl definitions
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Create remote AMP controllers structure. It is used to keep information
about discovered remote AMP controllers by A2MP protocol.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/a2mp.h | 3 ++
include/net/bluetooth/amp.h | 15 ++++++++
net/bluetooth/a2mp.c | 5 +++
net/bluetooth/amp.c | 79 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 102 insertions(+)
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index d547671..99c7389 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -33,6 +33,9 @@ struct amp_mgr {
__u8 handle;
enum amp_mgr_state state;
unsigned long flags;
+
+ struct list_head amp_ctrls;
+ struct mutex amp_ctrls_lock;
};
struct a2mp_cmd {
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 3414dfd..f57854f 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -14,6 +14,21 @@
#ifndef __AMP_H
#define __AMP_H
+struct amp_ctrl {
+ struct list_head list;
+ struct kref kref;
+ __u8 id;
+ __u16 assoc_len_so_far;
+ __u16 assoc_rem_len;
+ __u16 assoc_len;
+ __u8 *assoc;
+};
+
+int amp_ctrl_put(struct amp_ctrl *ctrl);
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr);
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
+void amp_ctrl_list_flush(struct amp_mgr *mgr);
+
struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
u8 remote_id);
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index f04c441..35e188c 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -594,6 +594,7 @@ static void amp_mgr_destroy(struct kref *kref)
list_del(&mgr->list);
mutex_unlock(&_mgr_list_lock);
+ amp_ctrl_list_flush(mgr);
kfree(mgr);
}
@@ -630,6 +631,10 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
kref_init(&mgr->kref);
+ /* Remote AMP ctrl list initialization */
+ INIT_LIST_HEAD(&mgr->amp_ctrls);
+ mutex_init(&mgr->amp_ctrls_lock);
+
mutex_lock(&_mgr_list_lock);
list_add(&mgr->list, &_mgr_list);
mutex_unlock(&_mgr_list_lock);
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 50a7b2f..8ef912c 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -17,6 +17,85 @@
#include <net/bluetooth/a2mp.h>
#include <net/bluetooth/amp.h>
+/* Remote AMP Controllers interface */
+static void amp_ctrl_get(struct amp_ctrl *ctrl)
+{
+ BT_DBG("ctrl %p orig refcnt %d", ctrl,
+ atomic_read(&ctrl->kref.refcount));
+
+ kref_get(&ctrl->kref);
+}
+
+static void amp_ctrl_destroy(struct kref *kref)
+{
+ struct amp_ctrl *ctrl = container_of(kref, struct amp_ctrl, kref);
+
+ BT_DBG("ctrl %p", ctrl);
+
+ kfree(ctrl->assoc);
+ kfree(ctrl);
+}
+
+int amp_ctrl_put(struct amp_ctrl *ctrl)
+{
+ BT_DBG("ctrl %p orig refcnt %d", ctrl,
+ atomic_read(&ctrl->kref.refcount));
+
+ return kref_put(&ctrl->kref, &_ctrl_destroy);
+}
+
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr)
+{
+ struct amp_ctrl *ctrl;
+
+ ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return NULL;
+
+ mutex_lock(&mgr->amp_ctrls_lock);
+ list_add(&ctrl->list, &mgr->amp_ctrls);
+ mutex_unlock(&mgr->amp_ctrls_lock);
+
+ kref_init(&ctrl->kref);
+
+ BT_DBG("mgr %p ctrl %p", mgr, ctrl);
+
+ return ctrl;
+}
+
+void amp_ctrl_list_flush(struct amp_mgr *mgr)
+{
+ struct amp_ctrl *ctrl, *n;
+
+ BT_DBG("mgr %p", mgr);
+
+ mutex_lock(&mgr->amp_ctrls_lock);
+ list_for_each_entry_safe(ctrl, n, &mgr->amp_ctrls, list) {
+ list_del(&ctrl->list);
+ amp_ctrl_put(ctrl);
+ }
+ mutex_unlock(&mgr->amp_ctrls_lock);
+}
+
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id)
+{
+ struct amp_ctrl *ctrl;
+
+ BT_DBG("mgr %p id %d", mgr, id);
+
+ mutex_lock(&mgr->amp_ctrls_lock);
+ list_for_each_entry(ctrl, &mgr->amp_ctrls, list) {
+ if (ctrl->id == id) {
+ amp_ctrl_get(ctrl);
+ mutex_unlock(&mgr->amp_ctrls_lock);
+ return ctrl;
+ }
+ }
+ mutex_unlock(&mgr->amp_ctrls_lock);
+
+ return NULL;
+}
+
/* Physical Link interface */
static u8 __next_handle(struct amp_mgr *mgr)
{
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 06/19] Bluetooth: AMP: Physical link struct and heplers
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Define physical link structures. Physical links are represented by
hci_conn structure. For BR/EDR we use type ACL_LINK and for AMP
we use AMP_LINK.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/amp.h | 3 +++
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/amp.c | 29 +++++++++++++++++++++++++++++
4 files changed, 34 insertions(+)
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index e861675..3414dfd 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -14,6 +14,9 @@
#ifndef __AMP_H
#define __AMP_H
+struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+ u8 remote_id);
+
void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index ccc08e5..77b6a19 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -207,6 +207,7 @@ enum {
#define ESCO_LINK 0x02
/* Low Energy links do not have defined link type. Use invented one */
#define LE_LINK 0x80
+#define AMP_LINK 0x81
/* LMP features */
#define LMP_3SLOT 0x01
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index b1c7d06..464eae3 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -318,6 +318,7 @@ struct hci_conn {
__u8 remote_cap;
__u8 remote_auth;
+ __u8 remote_id;
bool flush_key;
unsigned int sent;
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 2d4e79e..50a7b2f 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -17,6 +17,35 @@
#include <net/bluetooth/a2mp.h>
#include <net/bluetooth/amp.h>
+/* Physical Link interface */
+static u8 __next_handle(struct amp_mgr *mgr)
+{
+ if (++mgr->handle == 0)
+ mgr->handle = 1;
+
+ return mgr->handle;
+}
+
+struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+ u8 remote_id)
+{
+ bdaddr_t *dst = mgr->l2cap_conn->dst;
+ struct hci_conn *hcon;
+
+ hcon = hci_conn_add(hdev, AMP_LINK, dst);
+ if (!hcon)
+ return NULL;
+
+ hcon->state = BT_CONNECT;
+ hcon->out = true;
+ hcon->attempt++;
+ hcon->handle = __next_handle(mgr);
+ hcon->remote_id = remote_id;
+ hcon->amp_mgr = mgr;
+
+ return hcon;
+}
+
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
{
struct hci_cp_read_local_amp_assoc cp;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 05/19] Bluetooth: A2MP: Process Discover Response
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving A2MP Discover Response send A2MP Get Info Request
for each AMP controller in the discovery list.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
net/bluetooth/a2mp.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 7140061..f04c441 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -67,6 +67,14 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
kfree(cmd);
}
+static u8 __next_ident(struct amp_mgr *mgr)
+{
+ if (++mgr->ident == 0)
+ mgr->ident = 1;
+
+ return mgr->ident;
+}
+
static inline void __a2mp_cl_bredr(struct a2mp_cl *cl)
{
cl->id = 0;
@@ -165,6 +173,55 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
return 0;
}
+static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_discov_rsp *rsp = (void *) skb->data;
+ u16 len = le16_to_cpu(hdr->len);
+ struct a2mp_cl *cl;
+ u16 ext_feat;
+
+ if (len < sizeof(*rsp))
+ return -EINVAL;
+
+ len -= sizeof(*rsp);
+ skb_pull(skb, sizeof(*rsp));
+
+ ext_feat = le16_to_cpu(rsp->ext_feat);
+
+ BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(rsp->mtu), ext_feat);
+
+ /* check that packet is not broken for now */
+ while (ext_feat & A2MP_FEAT_EXT) {
+ if (len < sizeof(ext_feat))
+ return -EINVAL;
+
+ ext_feat = get_unaligned_le16(skb->data);
+ BT_DBG("efm 0x%4.4x", ext_feat);
+ len -= sizeof(ext_feat);
+ skb_pull(skb, sizeof(ext_feat));
+ }
+
+ cl = (void *) skb->data;
+ while (len >= sizeof(*cl)) {
+ BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type,
+ cl->status);
+
+ if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) {
+ struct a2mp_info_req req;
+
+ req.id = cl->id;
+ a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
+ sizeof(req), &req);
+ }
+
+ len -= sizeof(*cl);
+ cl = (void *) skb_pull(skb, sizeof(*cl));
+ }
+
+ return 0;
+}
+
static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
@@ -391,8 +448,11 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
err = a2mp_discphyslink_req(mgr, skb, hdr);
break;
- case A2MP_CHANGE_RSP:
case A2MP_DISCOVER_RSP:
+ err = a2mp_discover_rsp(mgr, skb, hdr);
+ break;
+
+ case A2MP_CHANGE_RSP:
case A2MP_GETINFO_RSP:
case A2MP_GETAMPASSOC_RSP:
case A2MP_CREATEPHYSLINK_RSP:
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 04/19] Bluetooth: AMP: Use HCI cmd to Read Loc AMP Assoc
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving A2MP Get AMP Assoc Request execute Read Local AMP Assoc
HCI command to AMP controller. If the AMP Assoc data is larger then it
can fit to HCI event only fragment is read. When all fragments are read
send A2MP Get AMP Assoc Response.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/a2mp.h | 2 ++
include/net/bluetooth/amp.h | 21 ++++++++++++++
include/net/bluetooth/hci.h | 2 ++
include/net/bluetooth/hci_core.h | 8 ++++++
net/bluetooth/Makefile | 2 +-
net/bluetooth/a2mp.c | 56 ++++++++++++++++++++++++++++++++++----
net/bluetooth/amp.c | 45 ++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 41 ++++++++++++++++++++++++++++
8 files changed, 171 insertions(+), 6 deletions(-)
create mode 100644 include/net/bluetooth/amp.h
create mode 100644 net/bluetooth/amp.c
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index af59468..d547671 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -21,6 +21,7 @@
enum amp_mgr_state {
READ_LOC_AMP_INFO,
+ READ_LOC_AMP_ASSOC,
};
struct amp_mgr {
@@ -134,5 +135,6 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
#endif /* __A2MP_H */
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
new file mode 100644
index 0000000..e861675
--- /dev/null
+++ b/include/net/bluetooth/amp.h
@@ -0,0 +1,21 @@
+/*
+ Copyright (c) 2011,2012 Intel Corp.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 and
+ only version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#ifndef __AMP_H
+#define __AMP_H
+
+void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+
+#endif /* __AMP_H */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 4be26abf6d..ccc08e5 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -33,6 +33,8 @@
#define HCI_LINK_KEY_SIZE 16
#define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE)
+#define HCI_MAX_AMP_ASSOC_SIZE 672
+
/* HCI dev events */
#define HCI_DEV_REG 1
#define HCI_DEV_UNREG 2
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e7d4546..b1c7d06 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -124,6 +124,12 @@ struct le_scan_params {
#define HCI_MAX_SHORT_NAME_LENGTH 10
+struct amp_assoc {
+ __u16 len;
+ __u16 offset;
+ __u8 data[HCI_MAX_AMP_ASSOC_SIZE];
+};
+
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
@@ -177,6 +183,8 @@ struct hci_dev {
__u32 amp_max_flush_to;
__u32 amp_be_flush_to;
+ struct amp_assoc loc_assoc;
+
__u8 flow_ctl_mode;
unsigned int auto_accept_delay;
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index fa6d94a..dea6a28 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -10,4 +10,4 @@ obj-$(CONFIG_BT_HIDP) += hidp/
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
- a2mp.o
+ a2mp.o amp.o
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 0e97b3b..7140061 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -16,6 +16,7 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
/* Global AMP Manager list */
LIST_HEAD(amp_mgr_list);
@@ -218,26 +219,37 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
{
struct a2mp_amp_assoc_req *req = (void *) skb->data;
struct hci_dev *hdev;
+ struct amp_mgr *tmp;
if (le16_to_cpu(hdr->len) < sizeof(*req))
return -EINVAL;
BT_DBG("id %d", req->id);
+ /* Make sure that other request is not processed */
+ tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+
hdev = hci_dev_get(req->id);
- if (!hdev || hdev->amp_type == HCI_BREDR) {
+ if (!hdev || hdev->amp_type == HCI_BREDR || tmp) {
struct a2mp_amp_assoc_rsp rsp;
rsp.id = req->id;
- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ if (tmp) {
+ rsp.status = A2MP_STATUS_COLLISION_OCCURED;
+ amp_mgr_put(tmp);
+ } else {
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+ }
a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp),
&rsp);
- goto clean;
+
+ goto done;
}
- /* Placeholder for HCI Read AMP Assoc */
+ amp_read_loc_assoc(hdev, mgr);
-clean:
+done:
if (hdev)
hci_dev_put(hdev);
@@ -624,3 +636,37 @@ void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
amp_mgr_put(mgr);
}
+
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
+{
+ struct amp_mgr *mgr;
+ struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+ struct a2mp_amp_assoc_rsp *rsp;
+ size_t len;
+
+ mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+ if (!mgr)
+ return;
+
+ BT_DBG("%s mgr %p", hdev->name, mgr);
+
+ len = sizeof(struct a2mp_amp_assoc_rsp) + loc_assoc->len;
+ rsp = kzalloc(len, GFP_KERNEL);
+ if (!rsp) {
+ amp_mgr_put(mgr);
+ return;
+ }
+
+ rsp->id = hdev->id;
+
+ if (status) {
+ rsp->status = A2MP_STATUS_INVALID_CTRL_ID;
+ } else {
+ rsp->status = A2MP_STATUS_SUCCESS;
+ memcpy(rsp->amp_assoc, loc_assoc->data, loc_assoc->len);
+ }
+
+ a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, mgr->ident, len, rsp);
+ amp_mgr_put(mgr);
+ kfree(rsp);
+}
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
new file mode 100644
index 0000000..2d4e79e
--- /dev/null
+++ b/net/bluetooth/amp.c
@@ -0,0 +1,45 @@
+/*
+ Copyright (c) 2011,2012 Intel Corp.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 and
+ only version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
+
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
+{
+ struct hci_cp_read_local_amp_assoc cp;
+ struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+
+ BT_DBG("%s handle %d", hdev->name, phy_handle);
+
+ cp.phy_handle = phy_handle;
+ cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+ cp.len_so_far = cpu_to_le16(loc_assoc->offset);
+
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
+
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
+{
+ struct hci_cp_read_local_amp_assoc cp;
+
+ memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc));
+ memset(&cp, 0, sizeof(cp));
+
+ cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+
+ mgr->state = READ_LOC_AMP_ASSOC;
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d05b8fe..0a9e720 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -31,6 +31,7 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/mgmt.h>
#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
/* Handle HCI Event packets */
@@ -866,6 +867,42 @@ a2mp_rsp:
a2mp_send_getinfo_rsp(hdev);
}
+static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
+ struct amp_assoc *assoc = &hdev->loc_assoc;
+ size_t rem_len, frag_len;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+ if (rp->status)
+ goto a2mp_rsp;
+
+ frag_len = skb->len - sizeof(*rp);
+ rem_len = __le16_to_cpu(rp->rem_len);
+
+ if (rem_len > frag_len) {
+ BT_DBG("frag_len %d rem_len %d", frag_len, rem_len);
+
+ memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
+ assoc->offset += frag_len;
+
+ /* Read other fragments */
+ amp_read_loc_assoc_frag(hdev, rp->phy_handle);
+
+ return;
+ }
+
+ memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
+ assoc->len = assoc->offset + rem_len;
+ assoc->offset = 0;
+
+a2mp_rsp:
+ /* Send A2MP Rsp when all fragments are received */
+ a2mp_send_getampassoc_rsp(hdev, rp->status);
+}
+
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
struct sk_buff *skb)
{
@@ -2317,6 +2354,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cc_read_local_amp_info(hdev, skb);
break;
+ case HCI_OP_READ_LOCAL_AMP_ASSOC:
+ hci_cc_read_local_amp_assoc(hdev, skb);
+ break;
+
case HCI_OP_DELETE_STORED_LINK_KEY:
hci_cc_delete_stored_link_key(hdev, skb);
break;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 03/19] Bluetooth: AMP: Use HCI cmd to Read AMP Info
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving A2MP Get Info Request execute Read Local AMP Info HCI
command to AMP controller with function to be executed upon receiving
command complete event. Function will handle A2MP Get Info Response.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/a2mp.h | 2 ++
net/bluetooth/a2mp.c | 57 ++++++++++++++++++++++++++++++------------
net/bluetooth/hci_event.c | 6 ++++-
3 files changed, 48 insertions(+), 17 deletions(-)
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 316c1c8..af59468 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -132,5 +132,7 @@ int amp_mgr_put(struct amp_mgr *mgr);
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct sk_buff *skb);
struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
#endif /* __A2MP_H */
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 3f93060..0e97b3b 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -41,8 +41,7 @@ static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
return cmd;
}
-static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
- void *data)
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
{
struct l2cap_chan *chan = mgr->a2mp_chan;
struct a2mp_cmd *cmd;
@@ -185,7 +184,6 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
struct a2mp_info_req *req = (void *) skb->data;
- struct a2mp_info_rsp rsp;
struct hci_dev *hdev;
if (le16_to_cpu(hdr->len) < sizeof(*req))
@@ -193,23 +191,23 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
BT_DBG("id %d", req->id);
- rsp.id = req->id;
- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
-
hdev = hci_dev_get(req->id);
- if (hdev && hdev->amp_type != HCI_BREDR) {
- rsp.status = 0;
- rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
- rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
- rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
- rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
- rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+ if (!hdev) {
+ struct a2mp_info_rsp rsp;
+
+ rsp.id = req->id;
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp),
+ &rsp);
}
- if (hdev)
- hci_dev_put(hdev);
+ if (hdev->dev_type != HCI_BREDR) {
+ mgr->state = READ_LOC_AMP_INFO;
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
+ }
- a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), &rsp);
+ hci_dev_put(hdev);
skb_pull(skb, sizeof(*req));
return 0;
@@ -599,3 +597,30 @@ struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
return NULL;
}
+
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
+{
+ struct amp_mgr *mgr;
+ struct a2mp_info_rsp rsp;
+
+ mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_INFO);
+ if (!mgr)
+ return;
+
+ BT_DBG("%s mgr %p", hdev->name, mgr);
+
+ rsp.id = hdev->id;
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ if (hdev->amp_type != HCI_BREDR) {
+ rsp.status = 0;
+ rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
+ rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
+ rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
+ rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
+ rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+ }
+
+ a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
+ amp_mgr_put(mgr);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6f2b519..d05b8fe 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -30,6 +30,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/mgmt.h>
+#include <net/bluetooth/a2mp.h>
/* Handle HCI Event packets */
@@ -846,7 +847,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (rp->status)
- return;
+ goto a2mp_rsp;
hdev->amp_status = rp->amp_status;
hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
@@ -860,6 +861,9 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
+
+a2mp_rsp:
+ a2mp_send_getinfo_rsp(hdev);
}
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 02/19] Bluetooth: A2MP: Create amp_mgr global list
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Create amp_mgr_list global list which will be used by different
hci devices to find amp_mgr.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/a2mp.h | 10 ++++++++++
net/bluetooth/a2mp.c | 29 +++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 6a76e0a..316c1c8 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -19,12 +19,18 @@
#define A2MP_FEAT_EXT 0x8000
+enum amp_mgr_state {
+ READ_LOC_AMP_INFO,
+};
+
struct amp_mgr {
+ struct list_head list;
struct l2cap_conn *l2cap_conn;
struct l2cap_chan *a2mp_chan;
struct kref kref;
__u8 ident;
__u8 handle;
+ enum amp_mgr_state state;
unsigned long flags;
};
@@ -118,9 +124,13 @@ struct a2mp_physlink_rsp {
#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05
#define A2MP_STATUS_SECURITY_VIOLATION 0x06
+extern struct list_head amp_mgr_list;
+extern struct mutex amp_mgr_list_lock;
+
void amp_mgr_get(struct amp_mgr *mgr);
int amp_mgr_put(struct amp_mgr *mgr);
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct sk_buff *skb);
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
#endif /* __A2MP_H */
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 0760d1f..3f93060 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -17,6 +17,10 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/a2mp.h>
+/* Global AMP Manager list */
+LIST_HEAD(amp_mgr_list);
+DEFINE_MUTEX(amp_mgr_list_lock);
+
/* A2MP build & send command helper functions */
static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
{
@@ -516,6 +520,10 @@ static void amp_mgr_destroy(struct kref *kref)
BT_DBG("mgr %p", mgr);
+ mutex_lock(&_mgr_list_lock);
+ list_del(&mgr->list);
+ mutex_unlock(&_mgr_list_lock);
+
kfree(mgr);
}
@@ -552,6 +560,10 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
kref_init(&mgr->kref);
+ mutex_lock(&_mgr_list_lock);
+ list_add(&mgr->list, &_mgr_list);
+ mutex_unlock(&_mgr_list_lock);
+
return mgr;
}
@@ -570,3 +582,20 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
return mgr->a2mp_chan;
}
+
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
+{
+ struct amp_mgr *mgr;
+
+ mutex_lock(&_mgr_list_lock);
+ list_for_each_entry(mgr, &_mgr_list, list) {
+ if (mgr->state == state) {
+ amp_mgr_get(mgr);
+ mutex_unlock(&_mgr_list_lock);
+ return mgr;
+ }
+ }
+ mutex_unlock(&_mgr_list_lock);
+
+ return NULL;
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 01/19] Bluetooth: Add HCI logical link cmds definitions
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/hci.h | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 76b2b6b..4be26abf6d 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -556,12 +556,46 @@ struct hci_cp_accept_phy_link {
__u8 key[HCI_AMP_LINK_KEY_SIZE];
} __packed;
-#define HCI_OP_DISCONN_PHY_LINK 0x0437
+#define HCI_OP_DISCONN_PHY_LINK 0x0437
struct hci_cp_disconn_phy_link {
__u8 phy_handle;
__u8 reason;
} __packed;
+struct ext_flow_spec {
+ __u8 id;
+ __u8 stype;
+ __le16 msdu;
+ __le32 sdu_itime;
+ __le32 acc_lat;
+ __le32 flush_to;
+} __packed;
+
+#define HCI_OP_CREATE_LOGICAL_LINK 0x0438
+#define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439
+struct hci_cp_create_accept_logical_link {
+ __u8 phy_handle;
+ struct ext_flow_spec tx_flow_spec;
+ struct ext_flow_spec rx_flow_spec;
+} __packed;
+
+#define HCI_OP_DISCONN_LOGICAL_LINK 0x043a
+struct hci_cp_disconn_logical_link {
+ __le16 log_handle;
+} __packed;
+
+#define HCI_OP_LOGICAL_LINK_CANCEL 0x043b
+struct hci_cp_logical_link_cancel {
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
+struct hci_rp_logical_link_cancel {
+ __u8 status;
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
__le16 handle;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 00/19] Bluetooth: Create AMP physical link
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1347437192-24694-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This set of patches enhances A2MP protocol and creates physical
link between AMP controllers. This is further iteration towards
Bluetooth High Speed.
Changes:
* p7: Fix ctrl_lookup, add phylink accept functions.
* p6: Refactoring: moving code from pal.[ch] to amp.[ch]
* p5: Fix issues reported by Mat in mailing list review
* p4: Rebased against recent bluetooth-next, minor fixes
* p3: Use hci_conn for representing physical link(type AMP_LINK) instead of
struct phy_link, refactoring.
* p2: Remove HCI callbacks and use amp_mgr global list, refactor code.
* p1: Fixed locking issues, added basic logical link preparation.
* v3: Remove workqueue from callback processing; change callback functions
names according to reviewers recommendations; create global amp_mgr_list to
have lookup to amp manager, physical and logical links so for those HCI events
which might be identified by __handler__ we have lookup; remove extensive
hexdump from gen_amp_key.
* v2: Fix typos and bugs, add functionality: now physical connection
might be established.
* v1: Fix typos, change debug prints, refactor code for better
splitting functionality.
Andrei Emeltchenko (18):
Bluetooth: Add HCI logical link cmds definitions
Bluetooth: A2MP: Create amp_mgr global list
Bluetooth: AMP: Use HCI cmd to Read AMP Info
Bluetooth: AMP: Use HCI cmd to Read Loc AMP Assoc
Bluetooth: A2MP: Process Discover Response
Bluetooth: AMP: Physical link struct and heplers
Bluetooth: AMP: Remote AMP ctrl definitions
Bluetooth: AMP: Handle create / disc phylink req
Bluetooth: A2MP: Process A2MP Getinfo Rsp
Bluetooth: A2MP: Process A2MP Get AMP Assoc Rsp
Bluetooth: Choose connection based on capabilities
Bluetooth: AMP: Add AMP key calculation
Bluetooth: AMP: Create Physical Link
Bluetooth: AMP: Write remote AMP Assoc
Bluetooth: A2MP: Add fallback to normal l2cap init sequence
Bluetooth: AMP: Process Chan Selected event
Bluetooth: AMP: Accept Physical Link
Bluetooth: AMP: Handle Accept phylink command status evt
Dmitry Kasatkin (1):
Bluetooth: Add function to derive AMP key using hmac
include/net/bluetooth/a2mp.h | 22 ++
include/net/bluetooth/amp.h | 50 +++++
include/net/bluetooth/hci.h | 39 +++-
include/net/bluetooth/hci_core.h | 11 +
include/net/bluetooth/l2cap.h | 4 +
net/bluetooth/Kconfig | 1 +
net/bluetooth/Makefile | 2 +-
net/bluetooth/a2mp.c | 454 +++++++++++++++++++++++++++++++++++---
net/bluetooth/amp.c | 367 ++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 126 ++++++++++-
net/bluetooth/l2cap_core.c | 35 ++-
11 files changed, 1072 insertions(+), 39 deletions(-)
create mode 100644 include/net/bluetooth/amp.h
create mode 100644 net/bluetooth/amp.c
--
1.7.9.5
^ permalink raw reply
* Re: [PATCH 00/14] Thermometer watchers API change + fixes
From: Anderson Lizardo @ 2012-09-27 12:03 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <50642ED8.3090007@tieto.com>
Hi Andrzej,
On Thu, Sep 27, 2012 at 6:47 AM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
>> Maybe we should consider implementing a simple Thermometer role in
>> BlueZ for testing purposes. It is a relatively simple profile.
>
>
> So you mean something like optional org.bluez.ThermometerSensor interface on
> adapter, similar to what is done for reporter role for Proximity?
Yes. There has been some interest on the past on the mailing list from
people willing to implement this role on BlueZ (although I have not
heard anymore from them), so it would become not just a test plugin,
but have an API that allows for BlueZ to expose some external
thermometer measurements over LE. But for now a "dummy" thermometer
which sends dummy measurements in various formats should be enough
(probably enabled only with --enable-test so it is not installed in
production).
Do you have interest/time for working on something like this?
BTW, I definitely plan to test both your HRP implementation and the
HTP changes, but currently I'm working in other things... I'll let you
know once I have these tested (probably with patches if I find any
issues).
Best Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: [PATCH 00/14] Thermometer watchers API change + fixes
From: Andrzej Kaczmarek @ 2012-09-27 10:47 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CAJdJm_N3g2YN32dUo4Af9zBnaVPAcTW5MgF9O-mXz8y_Dt23CQ@mail.gmail.com>
Hi Anderson,
On 09/25/2012 05:21 PM, Anderson Lizardo wrote:
> Hi Andrzej,
>
> On Tue, Sep 25, 2012 at 10:52 AM, Andrzej Kaczmarek
> <andrzej.kaczmarek@tieto.com> wrote:
>> Hi,
>>
>> Here's series of patches to move watchers from per-device to per-adapter
>> interface (basically the same as done for HRP, see other series of patches).
>> This applies to both final and intermediate temperature watchers - once
>> watcher is registered, all connected devices are setup to send measurement
>> notifications and the opposite when last watcher is unregistered.
>>
>> This major change is done in patches 1-6.
>>
>> Patches 7-11 contain some code and documentation refactoring, i.e. to
>> remove duplicated code.
>>
>> Patches 12-14 are trival coding style fixes.
>>
>> Unfortunately, I wasn't able to fully test this code due to lack of proper
>> thermometer device and sample device from CC2540 devkit does not quite
>> work as expected (e.g. I can see CCC is written properly when watcher is
>> registered but remote does not send any indications for unknown reason).
>
> Unfortunately, the thermometer demo app (at least on TI's BLE stack
> v1.1 installation) has several bugs. I haven't tested yet the latest
> release (1.2.1), which version are you using?
1.2 but downloaded 1.2.1 and thermometer demo app didn't change so it
still does not work.
> Do you have access to PTS? You could test with it as well.
I currently don't have BLE dongle for PTS but will test as soon as I
have one.
> Maybe we should consider implementing a simple Thermometer role in
> BlueZ for testing purposes. It is a relatively simple profile.
So you mean something like optional org.bluez.ThermometerSensor
interface on adapter, similar to what is done for reporter role for
Proximity?
BR,
Andrzej
^ permalink raw reply
* Re: [PATCH BlueZ v2 1/2] gdbus: Fix wrong signal handler match
From: Luiz Augusto von Dentz @ 2012-09-27 10:11 UTC (permalink / raw)
To: Lucas De Marchi; +Cc: linux-bluetooth
In-Reply-To: <1348666787-2510-1-git-send-email-lucas.demarchi@profusion.mobi>
Hi Lucas,
On Wed, Sep 26, 2012 at 4:39 PM, Lucas De Marchi
<lucas.demarchi@profusion.mobi> wrote:
> When we add a signal handler with g_dbus_add_signal_watch(), this
> function tries to multiplex the matches added in libdbus by checking
> if there's a previous filter_data with the same fields. However, if the
> field is NULL it accepts as being the same. The result is that the
> following watches will use the same filter data:
>
> watch1 = g_dbus_add_signal_watch(conn, BUS_NAME, NULL, iface, member,
> cb1, data1, NULL);
> watch2 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path2", iface, member,
> cb2, data2, NULL);
> watch3 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path3", iface, member,
> cb3, data3, NULL);
>
> The result is that when a signal arrives with path == "/path2", all 3
> callbacks above will be called, with the same signal delivered to all of
> them.
>
> Another problem is that, if we invert the calls like below, only signals
> to cb1 will never be trigerred, nonetheless it used path == NULL.
>
> watch2 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path2", iface, member,
> cb2, data2, NULL);
> watch1 = g_dbus_add_signal_watch(conn, BUS_NAME, NULL, iface, member,
> cb1, data1, NULL);
> watch3 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path3", iface, member,
> cb3, data3, NULL);
>
> This is fixed by not multiplexing the matchs with filter data if any of
> the fields are different, including being NULL. When a signal arrives,
> if a field is NULL we accept it as a match, but not when adding the
> signal handler.
> ---
> gdbus/watch.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++-----------
> 1 file changed, 94 insertions(+), 21 deletions(-)
>
> diff --git a/gdbus/watch.c b/gdbus/watch.c
> index d749176..2661928 100644
> --- a/gdbus/watch.c
> +++ b/gdbus/watch.c
> @@ -78,6 +78,47 @@ struct filter_data {
> gboolean registered;
> };
>
> +static struct filter_data *filter_data_find_match(DBusConnection *connection,
> + const char *name,
> + const char *owner,
> + const char *path,
> + const char *interface,
> + const char *member,
> + const char *argument)
> +{
> + GSList *current;
> +
> + for (current = listeners;
> + current != NULL; current = current->next) {
> + struct filter_data *data = current->data;
> +
> + if (connection != data->connection)
> + continue;
> +
> + if (g_strcmp0(name, data->name) != 0)
> + continue;
> +
> + if (g_strcmp0(owner, data->owner) != 0)
> + continue;
> +
> + if (g_strcmp0(path, data->path) != 0)
> + continue;
> +
> + if (g_strcmp0(interface, data->interface) != 0)
> + continue;
> +
> + if (g_strcmp0(member, data->member) != 0)
> + continue;
> +
> + if (g_strcmp0(argument, data->argument) != 0)
> + continue;
> +
> + return data;
> + }
> +
> + return NULL;
> +}
> +
> static struct filter_data *filter_data_find(DBusConnection *connection,
> const char *name,
> const char *owner,
> @@ -221,8 +262,8 @@ static struct filter_data *filter_data_get(DBusConnection *connection,
> name = sender;
>
> proceed:
> - data = filter_data_find(connection, name, owner, path, interface,
> - member, argument);
> + data = filter_data_find_match(connection, name, owner, path,
> + interface, member, argument);
> if (data)
> return data;
>
> @@ -501,6 +542,7 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
> {
> struct filter_data *data;
> const char *sender, *path, *iface, *member, *arg = NULL;
> + GSList *current, *delete_listener = NULL;
>
> /* Only filter signals */
> if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
> @@ -512,30 +554,63 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
> member = dbus_message_get_member(message);
> dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
>
> - /* Sender is always bus name */
> - data = filter_data_find(connection, NULL, sender, path, iface, member,
> - arg);
> - if (data == NULL) {
> - error("Got %s.%s signal which has no listeners", iface, member);
> - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
> - }
> + /* Sender is always the owner */
> +
> + for (current = listeners; current != NULL; current = current->next) {
> + data = current->data;
> +
> + if (connection != data->connection)
> + continue;
> +
> + if (data->owner && g_str_equal(sender, data->owner) == FALSE)
> + continue;
>
> - if (data->handle_func) {
> - data->lock = TRUE;
> + if (data->path && g_str_equal(path, data->path) == FALSE)
> + continue;
> +
> + if (data->interface && g_str_equal(iface,
> + data->interface) == FALSE)
> + continue;
>
> - data->handle_func(connection, message, data);
> + if (data->member && g_str_equal(member, data->member) == FALSE)
> + continue;
>
> - data->callbacks = data->processed;
> - data->processed = NULL;
> - data->lock = FALSE;
> + if (data->argument && g_str_equal(arg,
> + data->argument) == FALSE)
> + continue;
> +
> + if (data->handle_func) {
> + data->lock = TRUE;
> +
> + data->handle_func(connection, message, data);
> +
> + data->callbacks = data->processed;
> + data->processed = NULL;
> + data->lock = FALSE;
> + }
> +
> + if (!data->callbacks)
> + delete_listener = g_slist_prepend(delete_listener,
> + current);
> }
>
> - if (data->callbacks)
> - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
> + for (current = delete_listener; current != NULL;
> + current = delete_listener->next) {
> + GSList *l = current->data;
>
> - remove_match(data);
> + data = l->data;
>
> - listeners = g_slist_remove(listeners, data);
> + /* Has any other callback added callbacks back to this data? */
> + if (data->callbacks != NULL)
> + continue;
> +
> + remove_match(data);
> + listeners = g_slist_remove_link(listeners, l);
> +
> + filter_data_free(data);
> + }
> +
> + g_slist_free(delete_listener);
>
> /* Remove filter if there are no listeners left for the connection */
> if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
> @@ -543,8 +618,6 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
> dbus_connection_remove_filter(connection, message_filter,
> NULL);
>
> - filter_data_free(data);
> -
> return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
> }
>
> --
> 1.7.12.1
Patches are now upstream in BlueZ and obexd.
--
Luiz Augusto von Dentz
^ permalink raw reply
* [RFC] Convert storage to use per-remote device directories
From: Frederic Danis @ 2012-09-27 9:59 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 1795 bytes --]
Hi everyone,
Here is my proposal for new storage directory structure using ini-file
format.
Each adapter directory (/var/lib/bluetooth/<adapter address>/) will
contain a config file for the local adapter and one directory per remote
device.
The adapter config file just need to be converted to ini-file format
with only 1 group called [adapter].
Each of remote device directories' name will be based on remote device
address and address type (address#type).
This directory will contain a config file with remote device infos and a
linkkey file.
Remote device config file will include a [device] group with general
device infos (name, alias, profiles or services list, ...), and groups
named by profile uuid (or service uuid) with related infos.
So the directory structure should be:
/var/lib/bluetooth/<adapter address>/
./config
./<remote device address#type>/
./config
./linkkey
./<remote device address#type>/
./config
./linkkey
...
I attached sample of adapter and device config files.
--
Frederic Danis Open Source Technology Center
frederic.danis@intel.com Intel Corporation
---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris,
92196 Meudon Cedex, France
Registration Number: 302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
[-- Attachment #2: adapter-config-sample.txt --]
[-- Type: text/plain, Size: 93 bytes --]
[adapter]
name=desktop-0
class=0x780011
pairable=yes
onmode=discoverable
mode=discoverable
[-- Attachment #3: device-config-sample.txt --]
[-- Type: text/plain, Size: 777 bytes --]
[device]
name=MyPhone
alias=Fred's phone
class=0x180204
device_id=FFFF 0000 0000 0000
eir=040D040218
manufacturer=15
lmp_version=2
lmp_subversion=777
features=FFFE0D0008080000
lastseen=2012-09-26 11:19:40 GMT
lastused=2012-09-26 11:43:42 GMT
trusted=yes
profiles=00001101-0000-1000-8000-00805f9b34fb;00001103-0000-1000-8000-00805f9b34fb
[00001101-0000-1000-8000-00805f9b34fb]
handle=10001
record=35470900000A000100010900013503191101090004350C350319010035051900030802090005350319100209000935083506191101090100090100250C53657269616C20506F727400
[00001103-0000-1000-8000-00805f9b34fb]
handle=10002
record=35530900000A000100020900013503191103090004350C35031901003505190003080309000535031910020900093508350619110309010009010025134469616C2D7570204E6574776F726B696E67000903052800
^ permalink raw reply
* [PATCH v3 5/5] audio: Drop audio-specific authorization mechanism
From: Mikel Astiz @ 2012-09-27 8:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348733272-2117-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Remove the audio-specific service authorization mechanism in favor of
using the conventional one.
The main difference is that audio profiles will be authorized
independently. Therefore a single connection might result in several
profile authorization requests to the agent (i.e. HFP, A2DP and AVRCP).
This removes any internal policy that would skip the authorization
procedure, making it simpler and more convenient for IVI use-cases.
Agents interested in simulating the old behavior are encouraged to
either set the device as trusted or just reply to the additional
authorization requests automatically without user intervention.
---
audio/avctp.c | 30 +++++-------
audio/avdtp.c | 25 +++++++---
audio/device.c | 150 --------------------------------------------------------
audio/device.h | 12 +----
audio/manager.c | 18 ++++---
5 files changed, 41 insertions(+), 194 deletions(-)
diff --git a/audio/avctp.c b/audio/avctp.c
index 6fd5491..690339b 100644
--- a/audio/avctp.c
+++ b/audio/avctp.c
@@ -143,6 +143,7 @@ struct avctp {
GIOChannel *browsing_io;
guint control_io_id;
guint browsing_io_id;
+ int service_auth_id;
uint16_t control_mtu;
uint16_t browsing_mtu;
@@ -360,13 +361,9 @@ static void avctp_disconnected(struct avctp *session)
g_source_remove(session->control_io_id);
session->control_io_id = 0;
- if (session->state == AVCTP_STATE_CONNECTING) {
- struct audio_device *dev;
-
- dev = manager_get_device(&session->server->src,
- &session->dst, FALSE);
- audio_device_cancel_authorization(dev, auth_cb,
- session);
+ if (session->service_auth_id > 0) {
+ btd_cancel_authorization(session->service_auth_id);
+ session->service_auth_id = 0;
}
}
@@ -409,15 +406,7 @@ static void avctp_set_state(struct avctp *session, avctp_state_t new_state)
switch (new_state) {
case AVCTP_STATE_DISCONNECTED:
DBG("AVCTP Disconnected");
-
avctp_disconnected(session);
-
- if (old_state != AVCTP_STATE_CONNECTED)
- break;
-
- if (!audio_device_is_active(dev, NULL))
- audio_device_set_authorized(dev, FALSE);
-
break;
case AVCTP_STATE_CONNECTING:
DBG("AVCTP Connecting");
@@ -769,6 +758,8 @@ static void auth_cb(DBusError *derr, void *user_data)
struct avctp *session = user_data;
GError *err = NULL;
+ session->service_auth_id = 0;
+
if (session->control_io_id) {
g_source_remove(session->control_io_id);
session->control_io_id = 0;
@@ -845,6 +836,8 @@ static struct avctp *avctp_get_internal(const bdaddr_t *src,
static void avctp_control_confirm(struct avctp *session, GIOChannel *chan,
struct audio_device *dev)
{
+ int auth_id;
+
if (session->control_io) {
error("Control: Refusing unexpected connect");
g_io_channel_shutdown(chan, TRUE, NULL);
@@ -854,10 +847,13 @@ static void avctp_control_confirm(struct avctp *session, GIOChannel *chan,
avctp_set_state(session, AVCTP_STATE_CONNECTING);
session->control_io = g_io_channel_ref(chan);
- if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID,
- auth_cb, session) < 0)
+ auth_id = btd_request_authorization(&dev->src, &dev->dst,
+ AVRCP_TARGET_UUID,
+ auth_cb, session);
+ if (auth_id < 0)
goto drop;
+ session->service_auth_id = auth_id;
session->control_io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP |
G_IO_NVAL, session_cb, session);
return;
diff --git a/audio/avdtp.c b/audio/avdtp.c
index d44c504..3137094 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -400,6 +400,8 @@ struct avdtp {
/* True if the entire device is being disconnected */
gboolean device_disconnect;
+ int service_auth_id;
+
GIOChannel *io;
guint io_id;
@@ -1129,16 +1131,21 @@ static void release_stream(struct avdtp_stream *stream, struct avdtp *session)
static int avdtp_cancel_authorization(struct avdtp *session)
{
- struct audio_device *dev;
+ int err;
if (session->state != AVDTP_SESSION_STATE_CONNECTING)
return 0;
- dev = manager_get_device(&session->server->src, &session->dst, FALSE);
- if (dev == NULL)
- return -ENODEV;
+ if (!session->service_auth_id)
+ return 0;
- return audio_device_cancel_authorization(dev, auth_cb, session);
+ err = btd_cancel_authorization(session->service_auth_id);
+ if (err < 0)
+ return err;
+
+ session->service_auth_id = 0;
+
+ return 0;
}
static void connection_lost(struct avdtp *session, int err)
@@ -2507,7 +2514,7 @@ static void avdtp_confirm_cb(GIOChannel *chan, gpointer data)
struct audio_device *dev;
char address[18];
bdaddr_t src, dst;
- int perr;
+ int auth_id;
GError *err = NULL;
bt_io_get(chan, &err,
@@ -2566,15 +2573,17 @@ static void avdtp_confirm_cb(GIOChannel *chan, gpointer data)
session->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
(GIOFunc) session_cb, session);
- perr = audio_device_request_authorization(dev, ADVANCED_AUDIO_UUID,
+ auth_id = btd_request_authorization(&dev->src, &dev->dst,
+ ADVANCED_AUDIO_UUID,
auth_cb, session);
- if (perr < 0) {
+ if (auth_id < 0) {
avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
avdtp_unref(session);
goto drop;
}
dev->auto_connect = auto_connect;
+ session->service_auth_id = auth_id;
return;
diff --git a/audio/device.c b/audio/device.c
index 454bbb9..175e3c0 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -71,19 +71,12 @@ typedef enum {
AUDIO_STATE_CONNECTED,
} audio_state_t;
-struct service_auth {
- service_auth_cb cb;
- void *user_data;
-};
-
struct dev_priv {
audio_state_t state;
headset_state_t hs_state;
sink_state_t sink_state;
avctp_state_t avctp_state;
- GSList *auths;
- int auth_id;
DBusMessage *conn_req;
DBusMessage *dc_req;
@@ -94,8 +87,6 @@ struct dev_priv {
guint dc_id;
gboolean disconnecting;
- gboolean authorized;
- guint auth_idle_id;
};
static unsigned int sink_callback_id = 0;
@@ -110,8 +101,6 @@ static void device_free(struct audio_device *dev)
btd_device_unref(dev->btd_dev);
if (priv) {
- if (priv->auths)
- audio_device_cancel_authorization(dev, NULL, NULL);
if (priv->control_timer)
g_source_remove(priv->control_timer);
if (priv->avdtp_timer)
@@ -238,8 +227,6 @@ static void device_set_state(struct audio_device *dev, audio_state_t new_state)
return;
if (new_state == AUDIO_STATE_DISCONNECTED) {
- priv->authorized = FALSE;
-
if (priv->dc_id) {
device_remove_disconnect_watch(dev->btd_dev,
priv->dc_id);
@@ -732,140 +719,3 @@ void audio_device_unregister(struct audio_device *device)
device_free(device);
}
-
-static void auth_cb(DBusError *derr, void *user_data)
-{
- struct audio_device *dev = user_data;
- struct dev_priv *priv = dev->priv;
-
- priv->auth_id = 0;
-
- if (derr == NULL)
- priv->authorized = TRUE;
-
- while (priv->auths) {
- struct service_auth *auth = priv->auths->data;
-
- auth->cb(derr, auth->user_data);
- priv->auths = g_slist_remove(priv->auths, auth);
- g_free(auth);
- }
-}
-
-static gboolean auth_idle_cb(gpointer user_data)
-{
- struct audio_device *dev = user_data;
- struct dev_priv *priv = dev->priv;
-
- priv->auth_idle_id = 0;
-
- auth_cb(NULL, dev);
-
- return FALSE;
-}
-
-static gboolean audio_device_is_connected(struct audio_device *dev)
-{
- if (dev->headset) {
- headset_state_t state = headset_get_state(dev);
-
- if (state == HEADSET_STATE_CONNECTED ||
- state == HEADSET_STATE_PLAY_IN_PROGRESS ||
- state == HEADSET_STATE_PLAYING)
- return TRUE;
- }
-
- if (dev->sink) {
- sink_state_t state = sink_get_state(dev);
-
- if (state == SINK_STATE_CONNECTED ||
- state == SINK_STATE_PLAYING)
- return TRUE;
- }
-
- if (dev->source) {
- source_state_t state = source_get_state(dev);
-
- if (state == SOURCE_STATE_CONNECTED ||
- state == SOURCE_STATE_PLAYING)
- return TRUE;
- }
-
- return FALSE;
-}
-
-int audio_device_request_authorization(struct audio_device *dev,
- const char *uuid, service_auth_cb cb,
- void *user_data)
-{
- struct dev_priv *priv = dev->priv;
- struct service_auth *auth;
- int err;
-
- auth = g_try_new0(struct service_auth, 1);
- if (!auth)
- return -ENOMEM;
-
- auth->cb = cb;
- auth->user_data = user_data;
-
- priv->auths = g_slist_append(priv->auths, auth);
- if (g_slist_length(priv->auths) > 1)
- return 0;
-
- if (priv->authorized || audio_device_is_connected(dev)) {
- priv->auth_idle_id = g_idle_add(auth_idle_cb, dev);
- return 0;
- }
-
- err = btd_request_authorization(&dev->src, &dev->dst, uuid, auth_cb,
- dev);
- if (err < 0) {
- priv->auths = g_slist_remove(priv->auths, auth);
- g_free(auth);
- } else
- priv->auth_id = err;
-
- return err;
-}
-
-int audio_device_cancel_authorization(struct audio_device *dev,
- authorization_cb cb, void *user_data)
-{
- struct dev_priv *priv = dev->priv;
- GSList *l, *next;
-
- for (l = priv->auths; l != NULL; l = next) {
- struct service_auth *auth = l->data;
-
- next = g_slist_next(l);
-
- if (cb && auth->cb != cb)
- continue;
-
- if (user_data && auth->user_data != user_data)
- continue;
-
- priv->auths = g_slist_remove(priv->auths, auth);
- g_free(auth);
- }
-
- if (g_slist_length(priv->auths) == 0) {
- if (priv->auth_idle_id > 0) {
- g_source_remove(priv->auth_idle_id);
- priv->auth_idle_id = 0;
- } else {
- btd_cancel_authorization(priv->auth_id);
- priv->auth_id = 0;
- }
- }
-
- return 0;
-}
-
-void audio_device_set_authorized(struct audio_device *dev, gboolean auth)
-{
- struct dev_priv *priv = dev->priv;
-
- priv->authorized = auth;
-}
diff --git a/audio/device.h b/audio/device.h
index f9b868f..548462b 100644
--- a/audio/device.h
+++ b/audio/device.h
@@ -47,6 +47,7 @@ struct audio_device {
struct target *target;
guint hs_preauth_id;
+ int hs_service_auth_id;
struct dev_priv *priv;
};
@@ -59,14 +60,3 @@ void audio_device_unregister(struct audio_device *device);
gboolean audio_device_is_active(struct audio_device *dev,
const char *interface);
-
-typedef void (*authorization_cb) (DBusError *derr, void *user_data);
-
-int audio_device_cancel_authorization(struct audio_device *dev,
- authorization_cb cb, void *user_data);
-
-int audio_device_request_authorization(struct audio_device *dev,
- const char *uuid, authorization_cb cb,
- void *user_data);
-
-void audio_device_set_authorized(struct audio_device *dev, gboolean auth);
diff --git a/audio/manager.c b/audio/manager.c
index 70be01b..731b883 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -328,7 +328,7 @@ static gboolean hs_preauth_cb(GIOChannel *chan, GIOCondition cond,
DBG("Headset disconnected during authorization");
- audio_device_cancel_authorization(device, headset_auth_cb, device);
+ btd_cancel_authorization(device->hs_service_auth_id);
headset_set_state(device, HEADSET_STATE_DISCONNECTED);
@@ -343,7 +343,7 @@ static void ag_confirm(GIOChannel *chan, gpointer data)
struct audio_device *device;
gboolean hfp_active;
bdaddr_t src, dst;
- int perr;
+ int auth_id;
GError *err = NULL;
uint8_t ch;
@@ -398,10 +398,11 @@ static void ag_confirm(GIOChannel *chan, gpointer data)
headset_set_state(device, HEADSET_STATE_CONNECTING);
- perr = audio_device_request_authorization(device, server_uuid,
- headset_auth_cb, device);
- if (perr < 0) {
- DBG("Authorization denied: %s", strerror(-perr));
+ auth_id = btd_request_authorization(&device->src, &device->dst,
+ server_uuid, headset_auth_cb,
+ device);
+ if (auth_id < 0) {
+ DBG("Authorization denied: %s", strerror(-auth_id));
headset_set_state(device, HEADSET_STATE_DISCONNECTED);
return;
}
@@ -480,8 +481,9 @@ static void hf_io_cb(GIOChannel *chan, gpointer data)
goto drop;
}
- perr = audio_device_request_authorization(device, server_uuid,
- gateway_auth_cb, device);
+ perr = btd_request_authorization(&device->src, &device->dst,
+ server_uuid, gateway_auth_cb,
+ device);
if (perr < 0) {
DBG("Authorization denied: %s", strerror(-perr));
gateway_set_state(device, GATEWAY_STATE_DISCONNECTED);
--
1.7.11.4
^ permalink raw reply related
* [PATCH v3 4/5] adapter: Queue parallel authorization requests
From: Mikel Astiz @ 2012-09-27 8:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348733272-2117-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Remote device could try to connect several profiles in parallel, or
several devices could be trying to connect services. Instead of
returning EBUSY, this patch adds a queue to each adapter such that the
authorization requests will be queued and processed sequentially.
---
src/adapter.c | 181 +++++++++++++++++++++++++++++++++-------------------------
1 file changed, 103 insertions(+), 78 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index e77d305..b896182 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -101,8 +101,10 @@ struct service_auth {
int id;
service_auth_cb cb;
void *user_data;
+ const char *uuid;
struct btd_device *device;
struct btd_adapter *adapter;
+ struct agent *agent; /* NULL for queued auths */
};
struct btd_adapter {
@@ -129,8 +131,8 @@ struct btd_adapter {
GSList *found_devices;
GSList *oor_devices; /* out of range device list */
struct agent *agent; /* For the new API */
- guint auth_idle_id; /* Ongoing authorization (trusted) */
- struct service_auth *auth; /* Ongoing authorization */
+ guint auth_idle_id; /* Pending authorization dequeue */
+ GQueue *auths; /* Ongoing and pending auths */
GSList *connections; /* Connected devices */
GSList *devices; /* Devices structure pointers */
GSList *mode_sessions; /* Request Mode sessions */
@@ -158,6 +160,8 @@ struct btd_adapter {
GSList *profiles;
};
+static gboolean process_auth_queue(gpointer user_data);
+
static void dev_info_free(void *data)
{
struct remote_dev_info *dev = data;
@@ -951,16 +955,49 @@ static struct btd_device *adapter_create_device(struct btd_adapter *adapter,
return device;
}
+static void service_auth_cancel(struct service_auth *auth)
+{
+ DBusError derr;
+
+ dbus_error_init(&derr);
+ dbus_set_error_const(&derr, "org.bluez.Error.Canceled", NULL);
+
+ auth->cb(&derr, auth->user_data);
+
+ dbus_error_free(&derr);
+
+ if (auth->agent != NULL)
+ agent_cancel(auth->agent);
+
+ g_free(auth);
+}
+
void adapter_remove_device(struct btd_adapter *adapter,
struct btd_device *device,
gboolean remove_storage)
{
const gchar *dev_path = device_get_path(device);
- struct agent *agent;
+ GList *l;
adapter->devices = g_slist_remove(adapter->devices, device);
adapter->connections = g_slist_remove(adapter->connections, device);
+ l = adapter->auths->head;
+ while (l != NULL) {
+ struct service_auth *auth = l->data;
+ GList *next = g_list_next(l);
+
+ if (auth->device != device) {
+ l = next;
+ continue;
+ }
+
+ g_queue_delete_link(adapter->auths, l);
+ l = next;
+
+ service_auth_cancel(auth);
+ }
+
adapter_update_devices(adapter);
g_dbus_emit_signal(btd_get_dbus_connection(), adapter->path,
@@ -968,14 +1005,6 @@ void adapter_remove_device(struct btd_adapter *adapter,
DBUS_TYPE_OBJECT_PATH, &dev_path,
DBUS_TYPE_INVALID);
- agent = device_get_agent(device);
-
- if (agent && adapter->auth && adapter->auth->device == device) {
- g_free(adapter->auth);
- adapter->auth = NULL;
- agent_cancel(agent);
- }
-
device_remove(device, remove_storage);
}
@@ -2426,8 +2455,7 @@ static void adapter_free(gpointer user_data)
if (adapter->auth_idle_id)
g_source_remove(adapter->auth_idle_id);
- if (adapter->auth)
- g_free(adapter->auth);
+ g_queue_free_full(adapter->auths, g_free);
if (adapter->off_timer)
off_timer_remove(adapter);
@@ -2521,6 +2549,7 @@ struct btd_adapter *adapter_create(int id)
}
adapter->dev_id = id;
+ adapter->auths = g_queue_new();
snprintf(path, sizeof(path), "%s/hci%d", base_path, id);
adapter->path = g_strdup(path);
@@ -3164,26 +3193,60 @@ static void agent_auth_cb(struct agent *agent, DBusError *derr,
void *user_data)
{
struct btd_adapter *adapter = user_data;
- struct service_auth *auth = adapter->auth;
+ struct service_auth *auth = adapter->auths->head->data;
- adapter->auth = NULL;
+ g_queue_pop_head(adapter->auths);
auth->cb(derr, auth->user_data);
g_free(auth);
+
+ adapter->auth_idle_id = g_idle_add(process_auth_queue, adapter);
}
-static gboolean auth_idle_cb(gpointer user_data)
+static gboolean process_auth_queue(gpointer user_data)
{
struct btd_adapter *adapter = user_data;
- struct service_auth *auth = adapter->auth;
+ DBusError err;
- adapter->auth = NULL;
adapter->auth_idle_id = 0;
- auth->cb(NULL, auth->user_data);
+ dbus_error_init(&err);
+ dbus_set_error_const(&err, "org.bluez.Error.Rejected", NULL);
- g_free(auth);
+ while (!g_queue_is_empty(adapter->auths)) {
+ struct service_auth *auth = adapter->auths->head->data;
+ struct btd_device *device = auth->device;
+ const gchar *dev_path;
+
+ if (device_is_trusted(device) == TRUE) {
+ auth->cb(NULL, auth->user_data);
+ goto next;
+ }
+
+ auth->agent = device_get_agent(device);
+ if (auth->agent == NULL) {
+ warn("Can't find device agent");
+ auth->cb(&err, auth->user_data);
+ goto next;
+ }
+
+ dev_path = device_get_path(device);
+
+ if (agent_authorize(auth->agent, dev_path, auth->uuid,
+ agent_auth_cb, adapter, NULL) < 0) {
+ auth->cb(&err, auth->user_data);
+ goto next;
+ }
+
+ break;
+
+next:
+ g_free(auth);
+ g_queue_pop_head(adapter->auths);
+ }
+
+ dbus_error_free(&err);
return FALSE;
}
@@ -3194,10 +3257,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
{
struct service_auth *auth;
struct btd_device *device;
- struct agent *agent;
char address[18];
- const gchar *dev_path;
- int err;
ba2str(dst, address);
device = adapter_find_device(adapter, address);
@@ -3208,42 +3268,27 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
if (!g_slist_find(adapter->connections, device))
error("Authorization request for non-connected device!?");
- if (adapter->auth != NULL)
- return -EBUSY;
-
auth = g_try_new0(struct service_auth, 1);
if (!auth)
return -ENOMEM;
auth->cb = cb;
auth->user_data = user_data;
+ auth->uuid = uuid;
auth->device = device;
auth->adapter = adapter;
auth->id = ++service_auth_id;
- if (device_is_trusted(device) == TRUE) {
- adapter->auth_idle_id = g_idle_add(auth_idle_cb, adapter);
- goto done;
- }
+ g_queue_push_tail(adapter->auths, auth);
- agent = device_get_agent(device);
- if (!agent) {
- warn("Can't find device agent");
- g_free(auth);
- return -EPERM;
- }
+ if (adapter->auths->length != 1)
+ return auth->id;
- dev_path = device_get_path(device);
+ if (adapter->auth_idle_id != 0)
+ return auth->id;
- err = agent_authorize(agent, dev_path, uuid, agent_auth_cb, adapter,
- NULL);
- if (err < 0) {
- g_free(auth);
- return err;
- }
+ adapter->auth_idle_id = g_idle_add(process_auth_queue, adapter);
-done:
- adapter->auth = auth;
return auth->id;
}
@@ -3275,18 +3320,20 @@ int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
return -EPERM;
}
-static struct btd_adapter *find_authorization(int id)
+static struct service_auth *find_authorization(int id)
{
GSList *l;
+ GList *l2;
for (l = manager_get_adapters(); l != NULL; l = g_slist_next(l)) {
struct btd_adapter *adapter = l->data;
- if (adapter->auth == NULL)
- continue;
+ for (l2 = adapter->auths->head; l2 != NULL; l2 = l2->next) {
+ struct service_auth *auth = l2->data;
- if (adapter->auth->id == id)
- return adapter;
+ if (auth->id == id)
+ return auth;
+ }
}
return NULL;
@@ -3294,39 +3341,17 @@ static struct btd_adapter *find_authorization(int id)
int btd_cancel_authorization(int id)
{
- struct btd_adapter *adapter;
- struct agent *agent;
- int err;
-
- adapter = find_authorization(id);
- if (adapter == NULL)
- return -EPERM;
-
- if (adapter->auth_idle_id) {
- g_source_remove(adapter->auth_idle_id);
- adapter->auth_idle_id = 0;
- g_free(adapter->auth);
- adapter->auth = NULL;
- return 0;
- }
-
- /*
- * FIXME: Cancel fails if authorization is requested to adapter's
- * agent and in the meanwhile CreatePairedDevice is called.
- */
+ struct service_auth *auth;
- agent = device_get_agent(adapter->auth->device);
- if (!agent)
+ auth = find_authorization(id);
+ if (auth == NULL)
return -EPERM;
- err = agent_cancel(agent);
+ g_queue_remove(auth->adapter->auths, auth);
- if (err == 0) {
- g_free(adapter->auth);
- adapter->auth = NULL;
- }
+ service_auth_cancel(auth);
- return err;
+ return 0;
}
static gchar *adapter_any_path = NULL;
--
1.7.11.4
^ permalink raw reply related
* [PATCH v3 3/5] adapter: Use authorization id for cancelling
From: Mikel Astiz @ 2012-09-27 8:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348733272-2117-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Return a request id in btd_request_authorization() in order to be used
when the request needs to be cancelled. This id alone will be enough to
use btd_cancel_authorization().
---
audio/device.c | 12 +++++++++---
plugins/service.c | 18 ++++++++++-------
profiles/input/server.c | 2 +-
src/adapter.c | 51 +++++++++++++++++++++++++++++++------------------
src/adapter.h | 2 +-
src/profile.c | 24 +++++++++--------------
6 files changed, 63 insertions(+), 46 deletions(-)
diff --git a/audio/device.c b/audio/device.c
index 99d6512..454bbb9 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -83,6 +83,7 @@ struct dev_priv {
sink_state_t sink_state;
avctp_state_t avctp_state;
GSList *auths;
+ int auth_id;
DBusMessage *conn_req;
DBusMessage *dc_req;
@@ -737,6 +738,8 @@ static void auth_cb(DBusError *derr, void *user_data)
struct audio_device *dev = user_data;
struct dev_priv *priv = dev->priv;
+ priv->auth_id = 0;
+
if (derr == NULL)
priv->authorized = TRUE;
@@ -820,7 +823,8 @@ int audio_device_request_authorization(struct audio_device *dev,
if (err < 0) {
priv->auths = g_slist_remove(priv->auths, auth);
g_free(auth);
- }
+ } else
+ priv->auth_id = err;
return err;
}
@@ -850,8 +854,10 @@ int audio_device_cancel_authorization(struct audio_device *dev,
if (priv->auth_idle_id > 0) {
g_source_remove(priv->auth_idle_id);
priv->auth_idle_id = 0;
- } else
- btd_cancel_authorization(&dev->src, &dev->dst);
+ } else {
+ btd_cancel_authorization(priv->auth_id);
+ priv->auth_id = 0;
+ }
}
return 0;
diff --git a/plugins/service.c b/plugins/service.c
index e02a673..fca559d 100644
--- a/plugins/service.c
+++ b/plugins/service.c
@@ -65,6 +65,7 @@ struct pending_auth {
char *sender;
bdaddr_t dst;
char uuid[MAX_LEN_UUID_STR];
+ int id;
};
struct service_adapter {
@@ -557,8 +558,9 @@ done:
else
bacpy(&src, BDADDR_ANY);
- btd_request_authorization(&src, &auth->dst,
- auth->uuid, auth_cb, serv_adapter);
+ auth->id = btd_request_authorization(&src, &auth->dst,
+ auth->uuid, auth_cb,
+ serv_adapter);
}
static DBusMessage *request_authorization(DBusConnection *conn,
@@ -633,8 +635,9 @@ static DBusMessage *request_authorization(DBusConnection *conn,
else
bacpy(&src, BDADDR_ANY);
- if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb,
- serv_adapter) < 0) {
+ auth->id = btd_request_authorization(&src, &auth->dst, auth->uuid,
+ auth_cb, serv_adapter);
+ if (auth->id < 0) {
serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
auth);
g_free(auth);
@@ -664,7 +667,7 @@ static DBusMessage *cancel_authorization(DBusConnection *conn,
else
bacpy(&src, BDADDR_ANY);
- btd_cancel_authorization(&src, &auth->dst);
+ btd_cancel_authorization(auth->id);
reply = btd_error_not_authorized(auth->msg);
dbus_message_unref(auth->msg);
@@ -683,8 +686,9 @@ static DBusMessage *cancel_authorization(DBusConnection *conn,
else
bacpy(&src, BDADDR_ANY);
- btd_request_authorization(&src, &auth->dst,
- auth->uuid, auth_cb, serv_adapter);
+ auth->id = btd_request_authorization(&src, &auth->dst,
+ auth->uuid, auth_cb,
+ serv_adapter);
done:
return dbus_message_new_method_return(msg);
diff --git a/profiles/input/server.c b/profiles/input/server.c
index f71fdc0..773e933 100644
--- a/profiles/input/server.c
+++ b/profiles/input/server.c
@@ -179,7 +179,7 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
ret = btd_request_authorization(&src, &dst, HID_UUID,
auth_callback, server);
- if (ret == 0)
+ if (ret >= 0)
return;
ba2str(&src, addr);
diff --git a/src/adapter.c b/src/adapter.c
index 0664d23..e77d305 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -85,6 +85,7 @@
#define OFF_TIMER 3
static GSList *adapter_drivers = NULL;
+static int service_auth_id = 0;
struct session_req {
struct btd_adapter *adapter;
@@ -97,6 +98,7 @@ struct session_req {
};
struct service_auth {
+ int id;
service_auth_cb cb;
void *user_data;
struct btd_device *device;
@@ -3217,6 +3219,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
auth->user_data = user_data;
auth->device = device;
auth->adapter = adapter;
+ auth->id = ++service_auth_id;
if (device_is_trusted(device) == TRUE) {
adapter->auth_idle_id = g_idle_add(auth_idle_cb, adapter);
@@ -3241,7 +3244,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
done:
adapter->auth = auth;
- return 0;
+ return auth->id;
}
int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
@@ -3260,49 +3263,59 @@ int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
}
for (l = manager_get_adapters(); l != NULL; l = g_slist_next(l)) {
- int err;
+ int id;
adapter = l->data;
- err = adapter_authorize(adapter, dst, uuid, cb, user_data);
- if (err == 0)
- return 0;
+ id = adapter_authorize(adapter, dst, uuid, cb, user_data);
+ if (id >= 0)
+ return id;
}
return -EPERM;
}
-int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
+static struct btd_adapter *find_authorization(int id)
{
- struct btd_adapter *adapter = manager_find_adapter(src);
- struct btd_device *device;
+ GSList *l;
+
+ for (l = manager_get_adapters(); l != NULL; l = g_slist_next(l)) {
+ struct btd_adapter *adapter = l->data;
+
+ if (adapter->auth == NULL)
+ continue;
+
+ if (adapter->auth->id == id)
+ return adapter;
+ }
+
+ return NULL;
+}
+
+int btd_cancel_authorization(int id)
+{
+ struct btd_adapter *adapter;
struct agent *agent;
- char address[18];
int err;
- if (!adapter)
- return -EPERM;
-
- ba2str(dst, address);
- device = adapter_find_device(adapter, address);
- if (!device)
+ adapter = find_authorization(id);
+ if (adapter == NULL)
return -EPERM;
if (adapter->auth_idle_id) {
g_source_remove(adapter->auth_idle_id);
adapter->auth_idle_id = 0;
+ g_free(adapter->auth);
+ adapter->auth = NULL;
return 0;
}
- if (!adapter->auth || adapter->auth->device != device)
- return -EPERM;
-
/*
* FIXME: Cancel fails if authorization is requested to adapter's
* agent and in the meanwhile CreatePairedDevice is called.
*/
- agent = device_get_agent(device);
+ agent = device_get_agent(adapter->auth->device);
if (!agent)
return -EPERM;
diff --git a/src/adapter.h b/src/adapter.h
index 9f840e8..39add98 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -150,7 +150,7 @@ int btd_register_adapter_driver(struct btd_adapter_driver *driver);
void btd_unregister_adapter_driver(struct btd_adapter_driver *driver);
int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
const char *uuid, service_auth_cb cb, void *user_data);
-int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst);
+int btd_cancel_authorization(int id);
const char *adapter_any_get_path(void);
diff --git a/src/profile.c b/src/profile.c
index ad2ad4a..c7fedef 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -72,7 +72,7 @@ struct ext_io {
GIOChannel *io;
guint io_id;
- bool authorizing;
+ int service_auth_id;
DBusPendingCall *new_conn;
};
@@ -151,14 +151,8 @@ static void ext_io_destroy(gpointer p)
g_io_channel_shutdown(ext_io->io, FALSE, NULL);
g_io_channel_unref(ext_io->io);
- if (ext_io->authorizing) {
- bdaddr_t src, dst;
-
- if (bt_io_get(ext_io->io, NULL, BT_IO_OPT_SOURCE_BDADDR, &src,
- BT_IO_OPT_DEST_BDADDR, &dst,
- BT_IO_OPT_INVALID))
- btd_cancel_authorization(&src, &dst);
- }
+ if (ext_io->service_auth_id > 0)
+ btd_cancel_authorization(ext_io->service_auth_id);
if (ext_io->new_conn) {
dbus_pending_call_cancel(ext_io->new_conn);
@@ -318,7 +312,7 @@ static void ext_auth(DBusError *err, void *user_data)
GError *gerr = NULL;
char addr[18];
- conn->authorizing = false;
+ conn->service_auth_id = 0;
bt_io_get(conn->io, &gerr, BT_IO_OPT_DEST, addr, BT_IO_OPT_INVALID);
if (gerr != NULL) {
@@ -372,7 +366,7 @@ static void ext_confirm(GIOChannel *io, gpointer user_data)
GError *gerr = NULL;
bdaddr_t src, dst;
char addr[18];
- int err;
+ int ret;
bt_io_get(io, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &src,
@@ -390,15 +384,15 @@ static void ext_confirm(GIOChannel *io, gpointer user_data)
conn = create_conn(server, io);
- err = btd_request_authorization(&src, &dst, ext->uuid, ext_auth, conn);
- if (err < 0) {
+ ret = btd_request_authorization(&src, &dst, ext->uuid, ext_auth, conn);
+ if (ret < 0) {
error("%s authorization failure: %s", ext->name,
- strerror(-err));
+ strerror(-ret));
ext_io_destroy(conn);
return;
}
- conn->authorizing = true;
+ conn->service_auth_id = ret;
ext->conns = g_slist_append(ext->conns, conn);
--
1.7.11.4
^ permalink raw reply related
* [PATCH v3 2/5] adapter: Replace device authorizing flag
From: Mikel Astiz @ 2012-09-27 8:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348733272-2117-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Refactor code to drop the device authorizing flag by replacing it with a
private authorization pointer in btd_adapter. After all, no more than
one authorization can be ongoing, so the code is easier to follow if
this is made explicit.
---
src/adapter.c | 56 +++++++++++++++++++++++++++++++++++++-------------------
src/device.c | 11 -----------
src/device.h | 2 --
3 files changed, 37 insertions(+), 32 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index b1ea3ea..0664d23 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -127,7 +127,8 @@ struct btd_adapter {
GSList *found_devices;
GSList *oor_devices; /* out of range device list */
struct agent *agent; /* For the new API */
- guint auth_idle_id; /* Ongoing authorization */
+ guint auth_idle_id; /* Ongoing authorization (trusted) */
+ struct service_auth *auth; /* Ongoing authorization */
GSList *connections; /* Connected devices */
GSList *devices; /* Devices structure pointers */
GSList *mode_sessions; /* Request Mode sessions */
@@ -967,8 +968,11 @@ void adapter_remove_device(struct btd_adapter *adapter,
agent = device_get_agent(device);
- if (agent && device_is_authorizing(device))
+ if (agent && adapter->auth && adapter->auth->device == device) {
+ g_free(adapter->auth);
+ adapter->auth = NULL;
agent_cancel(agent);
+ }
device_remove(device, remove_storage);
}
@@ -2420,6 +2424,9 @@ static void adapter_free(gpointer user_data)
if (adapter->auth_idle_id)
g_source_remove(adapter->auth_idle_id);
+ if (adapter->auth)
+ g_free(adapter->auth);
+
if (adapter->off_timer)
off_timer_remove(adapter);
@@ -3154,22 +3161,28 @@ void btd_unregister_adapter_driver(struct btd_adapter_driver *driver)
static void agent_auth_cb(struct agent *agent, DBusError *derr,
void *user_data)
{
- struct service_auth *auth = user_data;
+ struct btd_adapter *adapter = user_data;
+ struct service_auth *auth = adapter->auth;
- device_set_authorizing(auth->device, FALSE);
+ adapter->auth = NULL;
auth->cb(derr, auth->user_data);
+
+ g_free(auth);
}
static gboolean auth_idle_cb(gpointer user_data)
{
- struct service_auth *auth = user_data;
- struct btd_adapter *adapter = auth->adapter;
+ struct btd_adapter *adapter = user_data;
+ struct service_auth *auth = adapter->auth;
+ adapter->auth = NULL;
adapter->auth_idle_id = 0;
auth->cb(NULL, auth->user_data);
+ g_free(auth);
+
return FALSE;
}
@@ -3193,7 +3206,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
if (!g_slist_find(adapter->connections, device))
error("Authorization request for non-connected device!?");
- if (adapter->auth_idle_id)
+ if (adapter->auth != NULL)
return -EBUSY;
auth = g_try_new0(struct service_auth, 1);
@@ -3206,10 +3219,8 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
auth->adapter = adapter;
if (device_is_trusted(device) == TRUE) {
- adapter->auth_idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
- auth_idle_cb, auth,
- g_free);
- return 0;
+ adapter->auth_idle_id = g_idle_add(auth_idle_cb, adapter);
+ goto done;
}
agent = device_get_agent(device);
@@ -3221,14 +3232,16 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
dev_path = device_get_path(device);
- err = agent_authorize(agent, dev_path, uuid, agent_auth_cb, auth,
- g_free);
- if (err < 0)
+ err = agent_authorize(agent, dev_path, uuid, agent_auth_cb, adapter,
+ NULL);
+ if (err < 0) {
g_free(auth);
- else
- device_set_authorizing(device, TRUE);
+ return err;
+ }
- return err;
+done:
+ adapter->auth = auth;
+ return 0;
}
int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
@@ -3281,6 +3294,9 @@ int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
return 0;
}
+ if (!adapter->auth || adapter->auth->device != device)
+ return -EPERM;
+
/*
* FIXME: Cancel fails if authorization is requested to adapter's
* agent and in the meanwhile CreatePairedDevice is called.
@@ -3292,8 +3308,10 @@ int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
err = agent_cancel(agent);
- if (err == 0)
- device_set_authorizing(device, FALSE);
+ if (err == 0) {
+ g_free(adapter->auth);
+ adapter->auth = NULL;
+ }
return err;
}
diff --git a/src/device.c b/src/device.c
index cb25606..adce9ed 100644
--- a/src/device.c
+++ b/src/device.c
@@ -163,7 +163,6 @@ struct btd_device {
gboolean bonded;
gboolean auto_connect;
- gboolean authorizing;
gint ref;
GIOChannel *att_io;
@@ -3027,16 +3026,6 @@ gboolean device_is_authenticating(struct btd_device *device)
return (device->authr != NULL);
}
-gboolean device_is_authorizing(struct btd_device *device)
-{
- return device->authorizing;
-}
-
-void device_set_authorizing(struct btd_device *device, gboolean auth)
-{
- device->authorizing = auth;
-}
-
void device_register_services(struct btd_device *device,
GSList *prim_list, int psm)
{
diff --git a/src/device.h b/src/device.h
index 02c1782..edd3033 100644
--- a/src/device.h
+++ b/src/device.h
@@ -99,8 +99,6 @@ int device_notify_pincode(struct btd_device *device, gboolean secure,
const char *pincode, void *cb);
void device_cancel_authentication(struct btd_device *device, gboolean aborted);
gboolean device_is_authenticating(struct btd_device *device);
-gboolean device_is_authorizing(struct btd_device *device);
-void device_set_authorizing(struct btd_device *device, gboolean auth);
void device_add_connection(struct btd_device *device);
void device_remove_connection(struct btd_device *device);
void device_request_disconnect(struct btd_device *device, DBusMessage *msg);
--
1.7.11.4
^ permalink raw reply related
* [PATCH v3 1/5] build: Update glib dependency to 2.32
From: Mikel Astiz @ 2012-09-27 8:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348733272-2117-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
This version of the library adds several convenient features such as
g_queue_free_full.
---
acinclude.m4 | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/acinclude.m4 b/acinclude.m4
index 39b0a18..02e28bc 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -99,8 +99,8 @@ AC_DEFUN([AC_PATH_DBUS], [
])
AC_DEFUN([AC_PATH_GLIB], [
- PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes,
- AC_MSG_ERROR(GLib >= 2.28 is required))
+ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.32 is required))
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
])
--
1.7.11.4
^ permalink raw reply related
* [PATCH v3 0/5] Audio profile authorization
From: Mikel Astiz @ 2012-09-27 8:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
v3 is similar to v2 but rebased and adapter against the latest upstream
changes.
Patch v2 2/6 has been dropped since it was not intended to be part of this patchet.
>From original cover-letter:
The agent-based profile authorization makes a special consideration for audio profiles: they are processed as if they all belonged to one single profile. This includes several internal policies that are inconvenient for IVI use-cases.
This patchset removes this exception by making use of the conventional authorization mechanism also for audio profiles.
The new approach is not straightforward since devices might send several connection requets in parallel (i.e. HFP, A2DP, AVRCP). This cannot be neither automatically rejected (EBUSY) nor forwarded in parallel to the agent, so a queue was added to store the pending authorization requests. These will be sent to the agent sequentially.
Mikel Astiz (5):
build: Update glib dependency to 2.32
adapter: Replace device authorizing flag
adapter: Use authorization id for cancelling
adapter: Queue parallel authorization requests
audio: Drop audio-specific authorization mechanism
acinclude.m4 | 4 +-
audio/avctp.c | 30 ++++----
audio/avdtp.c | 25 +++++--
audio/device.c | 144 -----------------------------------
audio/device.h | 12 +--
audio/manager.c | 18 +++--
plugins/service.c | 18 +++--
profiles/input/server.c | 2 +-
src/adapter.c | 194 +++++++++++++++++++++++++++++++-----------------
src/adapter.h | 2 +-
src/device.c | 11 ---
src/device.h | 2 -
src/profile.c | 24 +++---
13 files changed, 190 insertions(+), 296 deletions(-)
--
1.7.11.4
^ permalink raw reply
* Re: [PATCH v2 0/6] Audio profile authorization
From: Luiz Augusto von Dentz @ 2012-09-27 8:00 UTC (permalink / raw)
To: Mikel Astiz; +Cc: linux-bluetooth, Mikel Astiz
In-Reply-To: <1348584946-13895-1-git-send-email-mikel.astiz.oss@gmail.com>
Hi Mikel,
On Tue, Sep 25, 2012 at 5:55 PM, Mikel Astiz <mikel.astiz.oss@gmail.com> wrote:
> From: Mikel Astiz <mikel.astiz@bmw-carit.de>
>
> v2 includes the modification suggested by Luiz:
> - Variable renaming from auth_id to id
> - Use of g_queue_free_full, requiring a dependency update to glib 2.32
>
> From original cover-letter:
>
> The agent-based profile authorization makes a special consideration for audio profiles: they are processed as if they all belonged to one single profile. This includes several internal policies that are inconvenient for IVI use-cases.
>
> This patchset removes this exception by making use of the conventional authorization mechanism also for audio profiles.
>
> The new approach is not straightforward since devices might send several connection requets in parallel (i.e. HFP, A2DP, AVRCP). This cannot be neither automatically rejected (EBUSY) nor forwarded in parallel to the agent, so a queue was added to store the pending authorization requests. These will be sent to the agent sequentially.
>
> Mikel Astiz (6):
> build: Update glib dependency to 2.32
> audio: Fix crash on gateway close
> adapter: Replace device authorizing flag
> adapter: Use authorization id for cancelling
> adapter: Queue parallel authorization requests
> audio: Drop audio-specific authorization mechanism
>
> acinclude.m4 | 4 +-
> audio/avctp.c | 29 +++-----
> audio/avdtp.c | 25 +++++--
> audio/device.c | 144 ------------------------------------
> audio/device.h | 12 +--
> audio/gateway.c | 3 +
> audio/manager.c | 18 +++--
> plugins/service.c | 18 +++--
> profiles/input/server.c | 2 +-
> src/adapter.c | 193 +++++++++++++++++++++++++++++++-----------------
> src/adapter.h | 2 +-
> src/device.c | 11 ---
> src/device.h | 2 -
> 13 files changed, 183 insertions(+), 280 deletions(-)
>
> --
> 1.7.11.4
Apparently this patches don't apply anymore, please update them.
--
Luiz Augusto von Dentz
^ permalink raw reply
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