* [bluetooth-next -v2 10/24] Bluetooth: Implement the first SMP commands
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Briglia, Vinicius Costa Gomes
In-Reply-To: <1297388349-14878-10-git-send-email-vinicius.gomes@openbossa.org>
From: Anderson Briglia <anderson.briglia@openbossa.org>
These simple commands will allow the SMP procedure to be started
and terminated with a not supported error. This is the first step
toward something useful.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
---
include/net/bluetooth/smp.h | 26 ++++++++
net/bluetooth/Makefile | 2 +-
net/bluetooth/smp.c | 146 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 173 insertions(+), 1 deletions(-)
create mode 100644 net/bluetooth/smp.c
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 8f2edbf..36bdd6e 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -1,3 +1,25 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
#ifndef __SMP_H
#define __SMP_H
@@ -73,4 +95,8 @@ struct smp_cmd_security_req {
#define SMP_UNSPECIFIED 0x08
#define SMP_REPEATED_ATTEMPTS 0x09
+/* SMP Commands */
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
+
#endif /* __SMP_H */
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index 339b429..cf6183c 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -11,4 +11,4 @@ obj-$(CONFIG_BT_CMTP) += cmtp/
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 lib.o
-l2cap-y := l2cap_core.o l2cap_sock.o
+l2cap-y := l2cap_core.o l2cap_sock.o smp.o
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
new file mode 100644
index 0000000..8b67a56
--- /dev/null
+++ b/net/bluetooth/smp.c
@@ -0,0 +1,146 @@
+/*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ SOFTWARE IS DISCLAIMED.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
+
+static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
+ u16 dlen, void *data)
+{
+ struct sk_buff *skb;
+ struct l2cap_hdr *lh;
+ int len;
+
+ len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
+
+ if (len > conn->mtu)
+ return NULL;
+
+ skb = bt_skb_alloc(len, GFP_ATOMIC);
+ if (!skb)
+ return NULL;
+
+ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+ lh->len = cpu_to_le16(sizeof(code) + dlen);
+ lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+
+ memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
+
+ memcpy(skb_put(skb, dlen), data, dlen);
+
+ return skb;
+}
+
+static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
+{
+ struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
+
+ BT_DBG("code 0x%2.2x", code);
+
+ if (!skb)
+ return;
+
+ hci_send_acl(conn->hcon, skb, 0);
+}
+
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
+{
+ __u8 authreq;
+
+ BT_DBG("conn %p hcon %p level 0x%2.2x", conn, conn->hcon, sec_level);
+
+ switch (sec_level) {
+ case BT_SECURITY_MEDIUM:
+ /* Encrypted, no MITM protection */
+ authreq = HCI_AT_NO_BONDING_MITM;
+ break;
+
+ case BT_SECURITY_HIGH:
+ /* Bonding, MITM protection */
+ authreq = HCI_AT_GENERAL_BONDING_MITM;
+ break;
+
+ case BT_SECURITY_LOW:
+ default:
+ return 1;
+ }
+
+ if (conn->hcon->link_mode & HCI_LM_MASTER) {
+ struct smp_cmd_pairing cp;
+ cp.io_capability = 0x00;
+ cp.oob_flag = 0x00;
+ cp.max_key_size = 16;
+ cp.init_key_dist = 0x00;
+ cp.resp_key_dist = 0x00;
+ cp.auth_req = authreq;
+ smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+ } else {
+ struct smp_cmd_security_req cp;
+ cp.auth_req = authreq;
+ smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
+ }
+
+ return 0;
+}
+
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+ __u8 code = skb->data[0];
+ __u8 reason;
+ int err = 0;
+
+ skb_pull(skb, sizeof(code));
+
+ switch (code) {
+ case SMP_CMD_PAIRING_REQ:
+ reason = SMP_PAIRING_NOTSUPP;
+ smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+ &reason);
+ err = -EOPNOTSUPP;
+ break;
+
+ case SMP_CMD_PAIRING_FAIL:
+ break;
+
+ case SMP_CMD_PAIRING_RSP:
+ case SMP_CMD_PAIRING_CONFIRM:
+ case SMP_CMD_PAIRING_RANDOM:
+ case SMP_CMD_ENCRYPT_INFO:
+ case SMP_CMD_MASTER_IDENT:
+ case SMP_CMD_IDENT_INFO:
+ case SMP_CMD_IDENT_ADDR_INFO:
+ case SMP_CMD_SIGN_INFO:
+ case SMP_CMD_SECURITY_REQ:
+ default:
+ BT_DBG("Unknown command code 0x%2.2x", code);
+
+ reason = SMP_CMD_NOTSUPP;
+ smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+ &reason);
+ err = -EOPNOTSUPP;
+ }
+
+ kfree_skb(skb);
+ return err;
+}
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 09/24] Bluetooth: Add SMP command structures
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ville Tervo
In-Reply-To: <1297388349-14878-9-git-send-email-vinicius.gomes@openbossa.org>
From: Ville Tervo <ville.tervo@nokia.com>
Add command structures for security manager protocol.
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
include/net/bluetooth/smp.h | 76 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 76 insertions(+), 0 deletions(-)
create mode 100644 include/net/bluetooth/smp.h
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
new file mode 100644
index 0000000..8f2edbf
--- /dev/null
+++ b/include/net/bluetooth/smp.h
@@ -0,0 +1,76 @@
+#ifndef __SMP_H
+#define __SMP_H
+
+struct smp_command_hdr {
+ __u8 code;
+} __packed;
+
+#define SMP_CMD_PAIRING_REQ 0x01
+#define SMP_CMD_PAIRING_RSP 0x02
+struct smp_cmd_pairing {
+ __u8 io_capability;
+ __u8 oob_flag;
+ __u8 auth_req;
+ __u8 max_key_size;
+ __u8 init_key_dist;
+ __u8 resp_key_dist;
+} __packed;
+
+#define SMP_CMD_PAIRING_CONFIRM 0x03
+struct smp_cmd_pairing_confirm {
+ __u8 confirm_val[16];
+} __packed;
+
+#define SMP_CMD_PAIRING_RANDOM 0x04
+struct smp_cmd_pairing_random {
+ __u8 rand_val[16];
+} __packed;
+
+#define SMP_CMD_PAIRING_FAIL 0x05
+struct smp_cmd_pairing_fail {
+ __u8 reason;
+} __packed;
+
+#define SMP_CMD_ENCRYPT_INFO 0x06
+struct smp_cmd_encrypt_info {
+ __u8 ltk[16];
+} __packed;
+
+#define SMP_CMD_MASTER_IDENT 0x07
+struct smp_cmd_master_ident {
+ __u16 ediv;
+ __u8 rand[8];
+} __packed;
+
+#define SMP_CMD_IDENT_INFO 0x08
+struct smp_cmd_ident_info {
+ __u8 irk[16];
+} __packed;
+
+#define SMP_CMD_IDENT_ADDR_INFO 0x09
+struct smp_cmd_ident_addr_info {
+ __u8 addr_type;
+ bdaddr_t bdaddr;
+} __packed;
+
+#define SMP_CMD_SIGN_INFO 0x0a
+struct smp_cmd_sign_info {
+ __u8 csrk[16];
+} __packed;
+
+#define SMP_CMD_SECURITY_REQ 0x0b
+struct smp_cmd_security_req {
+ __u8 auth_req;
+} __packed;
+
+#define SMP_PASSKEY_ENTRY_FAILED 0x01
+#define SMP_OOB_NOT_AVAIL 0x02
+#define SMP_AUTH_REQUIREMENTS 0x03
+#define SMP_CONFIRM_FAILED 0x04
+#define SMP_PAIRING_NOTSUPP 0x05
+#define SMP_ENC_KEY_SIZE 0x06
+#define SMP_CMD_NOTSUPP 0x07
+#define SMP_UNSPECIFIED 0x08
+#define SMP_REPEATED_ATTEMPTS 0x09
+
+#endif /* __SMP_H */
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 08/24] Bluetooth: Treat LE and ACL links separately on timeout
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ville Tervo
In-Reply-To: <1297388349-14878-8-git-send-email-vinicius.gomes@openbossa.org>
From: Ville Tervo <ville.tervo@nokia.com>
Separate LE and ACL timeouts. Othervise ACL connections
on non LE hw will time out after 45 secs.
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
net/bluetooth/hci_core.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9296053..173bebd 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1711,19 +1711,19 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
return conn;
}
-static inline void hci_acl_tx_to(struct hci_dev *hdev)
+static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct list_head *p;
struct hci_conn *c;
- BT_ERR("%s ACL tx timeout", hdev->name);
+ BT_ERR("%s link tx timeout", hdev->name);
/* Kill stalled connections */
list_for_each(p, &h->list) {
c = list_entry(p, struct hci_conn, list);
- if (c->type == ACL_LINK && c->sent) {
- BT_ERR("%s killing stalled ACL connection %s",
+ if (c->type == type && c->sent) {
+ BT_ERR("%s killing stalled connection %s",
hdev->name, batostr(&c->dst));
hci_acl_disconn(c, 0x13);
}
@@ -1742,7 +1742,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
/* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if (!hdev->acl_cnt && time_after(jiffies, hdev->acl_last_tx + HZ * 45))
- hci_acl_tx_to(hdev);
+ hci_link_tx_to(hdev, ACL_LINK);
}
while (hdev->acl_cnt && (conn = hci_low_sent(hdev, ACL_LINK, "e))) {
@@ -1812,9 +1812,9 @@ static inline void hci_sched_le(struct hci_dev *hdev)
if (!test_bit(HCI_RAW, &hdev->flags)) {
/* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
- if (!hdev->le_cnt &&
+ if (!hdev->le_cnt && hdev->le_pkts &&
time_after(jiffies, hdev->le_last_tx + HZ * 45))
- hci_acl_tx_to(hdev);
+ hci_link_tx_to(hdev, LE_LINK);
}
cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 07/24] Bluetooth: Fix initiated LE connections
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1297388349-14878-7-git-send-email-vinicius.gomes@openbossa.org>
Fix LE connections not being marked as master.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
net/bluetooth/hci_conn.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index aecd78e..efcd2b5 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -52,6 +52,7 @@ static void hci_le_connect(struct hci_conn *conn)
conn->state = BT_CONNECT;
conn->out = 1;
+ conn->link_mode |= HCI_LM_MASTER;
memset(&cp, 0, sizeof(cp));
cp.scan_interval = cpu_to_le16(0x0004);
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 06/24] Bluetooth: Do not send disconn comand over LE links
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ville Tervo
In-Reply-To: <1297388349-14878-6-git-send-email-vinicius.gomes@openbossa.org>
From: Ville Tervo <ville.tervo@nokia.com>
l2cap over LE links can be disconnected without sending
disconnect command first.
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
net/bluetooth/l2cap_sock.c | 15 ++++++++-------
1 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 0c695be..a7eeacc 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -884,6 +884,8 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
void __l2cap_sock_close(struct sock *sk, int reason)
{
+ struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+
BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
switch (sk->sk_state) {
@@ -893,10 +895,9 @@ void __l2cap_sock_close(struct sock *sk, int reason)
case BT_CONNECTED:
case BT_CONFIG:
- if (sk->sk_type == SOCK_SEQPACKET ||
- sk->sk_type == SOCK_STREAM) {
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-
+ if ((sk->sk_type == SOCK_SEQPACKET ||
+ sk->sk_type == SOCK_STREAM) &&
+ conn->hcon->type == ACL_LINK) {
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
l2cap_send_disconn_req(conn, sk, reason);
} else
@@ -904,9 +905,9 @@ void __l2cap_sock_close(struct sock *sk, int reason)
break;
case BT_CONNECT2:
- if (sk->sk_type == SOCK_SEQPACKET ||
- sk->sk_type == SOCK_STREAM) {
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ if ((sk->sk_type == SOCK_SEQPACKET ||
+ sk->sk_type == SOCK_STREAM) &&
+ conn->hcon->type == ACL_LINK) {
struct l2cap_conn_rsp rsp;
__u16 result;
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 05/24] Bluetooth: Add server socket support for LE connection
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ville Tervo
In-Reply-To: <1297388349-14878-5-git-send-email-vinicius.gomes@openbossa.org>
From: Ville Tervo <ville.tervo@nokia.com>
Add support for LE server sockets.
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/hci_event.c | 10 ++++-
net/bluetooth/l2cap_core.c | 94 +++++++++++++++++++++++++++++++++++++++-
net/bluetooth/l2cap_sock.c | 7 ++-
4 files changed, 105 insertions(+), 7 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 78552a0..031e9cd 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -38,6 +38,7 @@
#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */
#define L2CAP_DEFAULT_ACK_TO 200
#define L2CAP_LOCAL_BUSY_TRIES 12
+#define L2CAP_LE_DEFAULT_MTU 23
#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */
#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3155ad5..74f04a2 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2405,8 +2405,14 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
- if (!conn)
- goto unlock;
+ if (!conn) {
+ conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
+ if (!conn) {
+ BT_ERR("No memory for new connection");
+ hci_dev_unlock(hdev);
+ return;
+ }
+ }
if (ev->status) {
hci_proto_connect_cfm(conn, ev->status);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b322cf5..ec81e2d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -183,8 +183,16 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so
l2cap_pi(sk)->conn = conn;
if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
- /* Alloc CID for connection-oriented socket */
- l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
+ if (conn->hcon->type == LE_LINK) {
+ /* LE connection */
+ l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
+ l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
+ l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
+ } else {
+ /* Alloc CID for connection-oriented socket */
+ l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
+ l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
+ }
} else if (sk->sk_type == SOCK_DGRAM) {
/* Connectionless socket */
l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
@@ -583,6 +591,82 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
}
}
+/* Find socket with cid and source bdaddr.
+ * Returns closest match, locked.
+ */
+static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
+{
+ struct sock *s, *sk = NULL, *sk1 = NULL;
+ struct hlist_node *node;
+
+ read_lock(&l2cap_sk_list.lock);
+
+ sk_for_each(sk, node, &l2cap_sk_list.head) {
+ if (state && sk->sk_state != state)
+ continue;
+
+ if (l2cap_pi(sk)->scid == cid) {
+ /* Exact match. */
+ if (!bacmp(&bt_sk(sk)->src, src))
+ break;
+
+ /* Closest match */
+ if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
+ sk1 = sk;
+ }
+ }
+ s = node ? sk : sk1;
+ if (s)
+ bh_lock_sock(s);
+ read_unlock(&l2cap_sk_list.lock);
+
+ return s;
+}
+
+static void l2cap_le_conn_ready(struct l2cap_conn *conn)
+{
+ struct l2cap_chan_list *list = &conn->chan_list;
+ struct sock *parent, *uninitialized_var(sk);
+
+ BT_DBG("");
+
+ /* Check if we have socket listening on cid */
+ parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
+ conn->src);
+ if (!parent)
+ return;
+
+ /* Check for backlog size */
+ if (sk_acceptq_is_full(parent)) {
+ BT_DBG("backlog full %d", parent->sk_ack_backlog);
+ goto clean;
+ }
+
+ sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
+ if (!sk)
+ goto clean;
+
+ write_lock_bh(&list->lock);
+
+ hci_conn_hold(conn->hcon);
+
+ l2cap_sock_init(sk, parent);
+ bacpy(&bt_sk(sk)->src, conn->src);
+ bacpy(&bt_sk(sk)->dst, conn->dst);
+
+ __l2cap_chan_add(conn, sk, parent);
+
+ l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+
+ sk->sk_state = BT_CONNECTED;
+ parent->sk_data_ready(parent, 0);
+
+ write_unlock_bh(&list->lock);
+
+clean:
+ bh_unlock_sock(parent);
+}
+
static void l2cap_conn_ready(struct l2cap_conn *conn)
{
struct l2cap_chan_list *l = &conn->chan_list;
@@ -590,6 +674,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
BT_DBG("conn %p", conn);
+ if (!conn->hcon->out && conn->hcon->type == LE_LINK)
+ l2cap_le_conn_ready(conn);
+
read_lock(&l->lock);
for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
@@ -672,7 +759,8 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
spin_lock_init(&conn->lock);
rwlock_init(&conn->chan_list.lock);
- setup_timer(&conn->info_timer, l2cap_info_timeout,
+ if (hcon->type != LE_LINK)
+ setup_timer(&conn->info_timer, l2cap_info_timeout,
(unsigned long) conn);
conn->disc_reason = 0x13;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index b435e5f..0c695be 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -103,7 +103,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
len = min_t(unsigned int, sizeof(la), alen);
memcpy(&la, addr, len);
- if (la.l2_cid)
+ if (la.l2_cid && la.l2_psm)
return -EINVAL;
lock_sock(sk);
@@ -145,6 +145,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
}
+ if (la.l2_cid)
+ l2cap_pi(sk)->scid = la.l2_cid;
+
write_unlock_bh(&l2cap_sk_list.lock);
done:
@@ -266,7 +269,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
goto done;
}
- if (!l2cap_pi(sk)->psm) {
+ if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->dcid) {
bdaddr_t *src = &bt_sk(sk)->src;
u16 psm;
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 04/24] Bluetooth: Add LE connection support to L2CAP
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ville Tervo
In-Reply-To: <1297388349-14878-4-git-send-email-vinicius.gomes@openbossa.org>
From: Ville Tervo <ville.tervo@nokia.com>
Add basic LE connection support to L2CAP. LE
connection can be created by specifying cid
in struct sockaddr_l2
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
include/net/bluetooth/l2cap.h | 3 +++
net/bluetooth/l2cap_core.c | 23 +++++++++++++++++++----
net/bluetooth/l2cap_sock.c | 7 ++++---
3 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 75ef0b2..78552a0 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -160,6 +160,9 @@ struct l2cap_conn_rsp {
/* channel indentifier */
#define L2CAP_CID_SIGNALING 0x0001
#define L2CAP_CID_CONN_LESS 0x0002
+#define L2CAP_CID_LE_DATA 0x0004
+#define L2CAP_CID_LE_SIGNALING 0x0005
+#define L2CAP_CID_SMP 0x0006
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ba7f9da..b322cf5 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -595,6 +595,12 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
bh_lock_sock(sk);
+ if (conn->hcon->type == LE_LINK) {
+ l2cap_sock_clear_timer(sk);
+ sk->sk_state = BT_CONNECTED;
+ sk->sk_state_change(sk);
+ }
+
if (sk->sk_type != SOCK_SEQPACKET &&
sk->sk_type != SOCK_STREAM) {
l2cap_sock_clear_timer(sk);
@@ -653,7 +659,11 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
BT_DBG("hcon %p conn %p", hcon, conn);
- conn->mtu = hcon->hdev->acl_mtu;
+ if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
+ conn->mtu = hcon->hdev->le_mtu;
+ else
+ conn->mtu = hcon->hdev->acl_mtu;
+
conn->src = &hcon->hdev->bdaddr;
conn->dst = &hcon->dst;
@@ -760,8 +770,13 @@ int l2cap_do_connect(struct sock *sk)
auth_type = l2cap_get_auth_type(sk);
- hcon = hci_connect(hdev, ACL_LINK, dst,
+ if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
+ hcon = hci_connect(hdev, LE_LINK, dst,
l2cap_pi(sk)->sec_level, auth_type);
+ else
+ hcon = hci_connect(hdev, ACL_LINK, dst,
+ l2cap_pi(sk)->sec_level, auth_type);
+
if (!hcon)
goto done;
@@ -3522,7 +3537,7 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
- if (hcon->type != ACL_LINK)
+ if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
return -EINVAL;
if (!status) {
@@ -3551,7 +3566,7 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
{
BT_DBG("hcon %p reason %d", hcon, reason);
- if (hcon->type != ACL_LINK)
+ if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
return -EINVAL;
l2cap_conn_del(hcon, bt_err(reason));
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index adf4169..b435e5f 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -168,13 +168,13 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
len = min_t(unsigned int, sizeof(la), alen);
memcpy(&la, addr, len);
- if (la.l2_cid)
+ if (la.l2_cid && la.l2_psm)
return -EINVAL;
lock_sock(sk);
if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
- && !la.l2_psm) {
+ && !(la.l2_psm || la.l2_cid)) {
err = -EINVAL;
goto done;
}
@@ -216,7 +216,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
/* PSM must be odd and lsb of upper byte must be 0 */
if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
- sk->sk_type != SOCK_RAW) {
+ sk->sk_type != SOCK_RAW && !la.l2_cid) {
err = -EINVAL;
goto done;
}
@@ -224,6 +224,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
/* Set destination address and psm */
bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
l2cap_pi(sk)->psm = la.l2_psm;
+ l2cap_pi(sk)->dcid = la.l2_cid;
err = l2cap_do_connect(sk);
if (err)
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 03/24] Bluetooth: Use LE buffers for LE traffic
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ville Tervo
In-Reply-To: <1297388349-14878-3-git-send-email-vinicius.gomes@openbossa.org>
From: Ville Tervo <ville.tervo@nokia.com>
Bluetooth chips may have separate buffers for LE traffic.
This patch add support to use LE buffers provided by the chip.
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
include/net/bluetooth/hci_core.h | 5 +++
net/bluetooth/hci_conn.c | 5 +++
net/bluetooth/hci_core.c | 74 +++++++++++++++++++++++++++++++++++--
net/bluetooth/hci_event.c | 33 +++++++++++++++++
4 files changed, 113 insertions(+), 4 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index f434e96..d30b93c 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -123,15 +123,19 @@ struct hci_dev {
atomic_t cmd_cnt;
unsigned int acl_cnt;
unsigned int sco_cnt;
+ unsigned int le_cnt;
unsigned int acl_mtu;
unsigned int sco_mtu;
+ unsigned int le_mtu;
unsigned int acl_pkts;
unsigned int sco_pkts;
+ unsigned int le_pkts;
unsigned long cmd_last_tx;
unsigned long acl_last_tx;
unsigned long sco_last_tx;
+ unsigned long le_last_tx;
struct workqueue_struct *workqueue;
@@ -521,6 +525,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
+#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
/* ----- HCI protocols ----- */
struct hci_proto {
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d0c470c..aecd78e 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -326,6 +326,11 @@ int hci_conn_del(struct hci_conn *conn)
/* Unacked frames */
hdev->acl_cnt += conn->sent;
+ } else if (conn->type == LE_LINK) {
+ if (hdev->le_pkts)
+ hdev->le_cnt += conn->sent;
+ else
+ hdev->acl_cnt += conn->sent;
} else {
struct hci_conn *acl = conn->link;
if (acl) {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 2f00322..9296053 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -263,6 +263,14 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
}
+static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt)
+{
+ BT_DBG("%s", hdev->name);
+
+ /* Read LE buffer size */
+ hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
+}
+
static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
{
__u8 scan = opt;
@@ -529,6 +537,10 @@ int hci_dev_open(__u16 dev)
ret = __hci_request(hdev, hci_init_req, 0,
msecs_to_jiffies(HCI_INIT_TIMEOUT));
+ if (lmp_le_capable(hdev))
+ ret = __hci_request(hdev, hci_le_init_req, 0,
+ msecs_to_jiffies(HCI_INIT_TIMEOUT));
+
clear_bit(HCI_INIT, &hdev->flags);
}
@@ -671,7 +683,7 @@ int hci_dev_reset(__u16 dev)
hdev->flush(hdev);
atomic_set(&hdev->cmd_cnt, 1);
- hdev->acl_cnt = 0; hdev->sco_cnt = 0;
+ hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0;
if (!test_bit(HCI_RAW, &hdev->flags))
ret = __hci_request(hdev, hci_reset_req, 0,
@@ -1672,8 +1684,25 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
}
if (conn) {
- int cnt = (type == ACL_LINK ? hdev->acl_cnt : hdev->sco_cnt);
- int q = cnt / num;
+ int cnt, q;
+
+ switch (conn->type) {
+ case ACL_LINK:
+ cnt = hdev->acl_cnt;
+ break;
+ case SCO_LINK:
+ case ESCO_LINK:
+ cnt = hdev->sco_cnt;
+ break;
+ case LE_LINK:
+ cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
+ break;
+ default:
+ cnt = 0;
+ BT_ERR("Unknown link type");
+ }
+
+ q = cnt / num;
*quote = q ? q : 1;
} else
*quote = 0;
@@ -1772,6 +1801,40 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
}
}
+static inline void hci_sched_le(struct hci_dev *hdev)
+{
+ struct hci_conn *conn;
+ struct sk_buff *skb;
+ int quote, cnt;
+
+ BT_DBG("%s", hdev->name);
+
+ if (!test_bit(HCI_RAW, &hdev->flags)) {
+ /* LE tx timeout must be longer than maximum
+ * link supervision timeout (40.9 seconds) */
+ if (!hdev->le_cnt &&
+ time_after(jiffies, hdev->le_last_tx + HZ * 45))
+ hci_acl_tx_to(hdev);
+ }
+
+ cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
+ while (cnt && (conn = hci_low_sent(hdev, LE_LINK, "e))) {
+ while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
+ BT_DBG("skb %p len %d", skb, skb->len);
+
+ hci_send_frame(skb);
+ hdev->le_last_tx = jiffies;
+
+ cnt--;
+ conn->sent++;
+ }
+ }
+ if (hdev->le_pkts)
+ hdev->le_cnt = cnt;
+ else
+ hdev->acl_cnt = cnt;
+}
+
static void hci_tx_task(unsigned long arg)
{
struct hci_dev *hdev = (struct hci_dev *) arg;
@@ -1779,7 +1842,8 @@ static void hci_tx_task(unsigned long arg)
read_lock(&hci_task_lock);
- BT_DBG("%s acl %d sco %d", hdev->name, hdev->acl_cnt, hdev->sco_cnt);
+ BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
+ hdev->sco_cnt, hdev->le_cnt);
/* Schedule queues and send stuff to HCI driver */
@@ -1789,6 +1853,8 @@ static void hci_tx_task(unsigned long arg)
hci_sched_esco(hdev);
+ hci_sched_le(hdev);
+
/* Send next queued raw (unknown type) packet */
while ((skb = skb_dequeue(&hdev->raw_q)))
hci_send_frame(skb);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 47c6e93..3155ad5 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -776,6 +776,25 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
rp->status);
}
+static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
+ hdev->le_pkts = rp->le_max_pkt;
+
+ hdev->le_cnt = hdev->le_pkts;
+
+ BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
+
+ hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
+}
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
@@ -1704,6 +1723,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_pin_code_neg_reply(hdev, skb);
break;
+ case HCI_OP_LE_READ_BUFFER_SIZE:
+ hci_cc_le_read_buffer_size(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -1849,6 +1872,16 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
hdev->acl_cnt += count;
if (hdev->acl_cnt > hdev->acl_pkts)
hdev->acl_cnt = hdev->acl_pkts;
+ } else if (conn->type == LE_LINK) {
+ if (hdev->le_pkts) {
+ hdev->le_cnt += count;
+ if (hdev->le_cnt > hdev->le_pkts)
+ hdev->le_cnt = hdev->le_pkts;
+ } else {
+ hdev->acl_cnt += count;
+ if (hdev->acl_cnt > hdev->acl_pkts)
+ hdev->acl_cnt = hdev->acl_pkts;
+ }
} else {
hdev->sco_cnt += count;
if (hdev->sco_cnt > hdev->sco_pkts)
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 02/24] Bluetooth: Add LE connect support
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ville Tervo
In-Reply-To: <1297388349-14878-2-git-send-email-vinicius.gomes@openbossa.org>
From: Ville Tervo <ville.tervo@nokia.com>
Bluetooth V4.0 adds support for Low Energy (LE) connections.
Specification introduces new set of hci commands to control LE
connection. This patch adds logic to create, cancel and disconnect
LE connections.
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
include/net/bluetooth/hci.h | 2 +
include/net/bluetooth/hci_core.h | 25 +++++++++--
net/bluetooth/hci_conn.c | 51 +++++++++++++++++++-
net/bluetooth/hci_event.c | 93 ++++++++++++++++++++++++++++++++++++++
4 files changed, 164 insertions(+), 7 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 802d250..e756f82 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -168,6 +168,8 @@ enum {
#define SCO_LINK 0x00
#define ACL_LINK 0x01
#define ESCO_LINK 0x02
+/* Low Energy links do not have defined link type. Use invented one */
+#define LE_LINK 0x80
/* LMP features */
#define LMP_3SLOT 0x01
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6163bff..f434e96 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -60,6 +60,7 @@ struct hci_conn_hash {
spinlock_t lock;
unsigned int acl_num;
unsigned int sco_num;
+ unsigned int le_num;
};
struct bdaddr_list {
@@ -309,20 +310,36 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
{
struct hci_conn_hash *h = &hdev->conn_hash;
list_add(&c->list, &h->list);
- if (c->type == ACL_LINK)
+ switch (c->type) {
+ case ACL_LINK:
h->acl_num++;
- else
+ break;
+ case LE_LINK:
+ h->le_num++;
+ break;
+ case SCO_LINK:
+ case ESCO_LINK:
h->sco_num++;
+ break;
+ }
}
static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
{
struct hci_conn_hash *h = &hdev->conn_hash;
list_del(&c->list);
- if (c->type == ACL_LINK)
+ switch (c->type) {
+ case ACL_LINK:
h->acl_num--;
- else
+ break;
+ case LE_LINK:
+ h->le_num--;
+ break;
+ case SCO_LINK:
+ case ESCO_LINK:
h->sco_num--;
+ break;
+ }
}
static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 42dc39f..d0c470c 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -45,6 +45,32 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+static void hci_le_connect(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_create_conn cp;
+
+ conn->state = BT_CONNECT;
+ conn->out = 1;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.scan_interval = cpu_to_le16(0x0004);
+ cp.scan_window = cpu_to_le16(0x0004);
+ bacpy(&cp.peer_addr, &conn->dst);
+ cp.conn_interval_min = cpu_to_le16(0x0008);
+ cp.conn_interval_max = cpu_to_le16(0x0100);
+ cp.supervision_timeout = cpu_to_le16(0x0064);
+ cp.min_ce_len = cpu_to_le16(0x0001);
+ cp.max_ce_len = cpu_to_le16(0x0001);
+
+ hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
+}
+
+static void hci_le_connect_cancel(struct hci_conn *conn)
+{
+ hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
+}
+
void hci_acl_connect(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
@@ -193,8 +219,12 @@ static void hci_conn_timeout(unsigned long arg)
switch (conn->state) {
case BT_CONNECT:
case BT_CONNECT2:
- if (conn->type == ACL_LINK && conn->out)
- hci_acl_connect_cancel(conn);
+ if (conn->out) {
+ if (conn->type == ACL_LINK)
+ hci_acl_connect_cancel(conn);
+ else if (conn->type == LE_LINK)
+ hci_le_connect_cancel(conn);
+ }
break;
case BT_CONFIG:
case BT_CONNECTED:
@@ -361,15 +391,30 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
}
EXPORT_SYMBOL(hci_get_route);
-/* Create SCO or ACL connection.
+/* Create SCO, ACL or LE connection.
* Device _must_ be locked */
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type)
{
struct hci_conn *acl;
struct hci_conn *sco;
+ struct hci_conn *le;
BT_DBG("%s dst %s", hdev->name, batostr(dst));
+ if (type == LE_LINK) {
+ le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
+ if (!le)
+ le = hci_conn_add(hdev, LE_LINK, dst);
+ if (!le)
+ return NULL;
+ if (le->state == BT_OPEN)
+ hci_le_connect(le);
+
+ hci_conn_hold(le);
+
+ return le;
+ }
+
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
acl = hci_conn_add(hdev, ACL_LINK, dst);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index cee46cb..47c6e93 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1107,6 +1107,43 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
+static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
+{
+ struct hci_cp_le_create_conn *cp;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
+ if (!cp)
+ return;
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
+
+ BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
+ conn);
+
+ if (status) {
+ if (conn && conn->state == BT_CONNECT) {
+ conn->state = BT_CLOSED;
+ hci_proto_connect_cfm(conn, status);
+ hci_conn_del(conn);
+ }
+ } else {
+ if (!conn) {
+ conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
+ if (conn)
+ conn->out = 1;
+ else
+ BT_ERR("No memory for new connection");
+ }
+ }
+
+ hci_dev_unlock(hdev);
+}
+
static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -1738,6 +1775,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
mgmt_disconnect_failed(hdev->id);
break;
+ case HCI_OP_LE_CREATE_CONN:
+ hci_cs_le_create_conn(hdev, ev->status);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -2321,6 +2362,54 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_
hci_dev_unlock(hdev);
}
+static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_le_conn_complete *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status %d", hdev->name, ev->status);
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
+ if (!conn)
+ goto unlock;
+
+ if (ev->status) {
+ hci_proto_connect_cfm(conn, ev->status);
+ conn->state = BT_CLOSED;
+ hci_conn_del(conn);
+ goto unlock;
+ }
+
+ conn->handle = __le16_to_cpu(ev->handle);
+ conn->state = BT_CONNECTED;
+
+ hci_conn_hold_device(conn);
+ hci_conn_add_sysfs(conn);
+
+ hci_proto_connect_cfm(conn, ev->status);
+
+unlock:
+ hci_dev_unlock(hdev);
+}
+
+static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_le_meta *le_ev = (void *) skb->data;
+
+ skb_pull(skb, sizeof(*le_ev));
+
+ switch (le_ev->subevent) {
+ case HCI_EV_LE_CONN_COMPLETE:
+ hci_le_conn_complete_evt(hdev, skb);
+ break;
+
+ default:
+ break;
+ }
+}
+
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *) skb->data;
@@ -2461,6 +2550,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_remote_host_features_evt(hdev, skb);
break;
+ case HCI_EV_LE_META:
+ hci_le_meta_evt(hdev, skb);
+ break;
+
default:
BT_DBG("%s event 0x%x", hdev->name, event);
break;
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 01/24] Bluetooth: Add low energy commands and events
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ville Tervo
In-Reply-To: <1297388349-14878-1-git-send-email-vinicius.gomes@openbossa.org>
From: Ville Tervo <ville.tervo@nokia.com>
Add needed HCI command and event structs to
create LE connections.
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
include/net/bluetooth/hci.h | 49 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 49 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 4bee030..802d250 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -642,6 +642,36 @@ struct hci_rp_read_bd_addr {
bdaddr_t bdaddr;
} __packed;
+#define HCI_OP_LE_SET_EVENT_MASK 0x2001
+struct hci_cp_le_set_event_mask {
+ __u8 mask[8];
+} __packed;
+
+#define HCI_OP_LE_READ_BUFFER_SIZE 0x2002
+struct hci_rp_le_read_buffer_size {
+ __u8 status;
+ __le16 le_mtu;
+ __u8 le_max_pkt;
+} __packed;
+
+#define HCI_OP_LE_CREATE_CONN 0x200d
+struct hci_cp_le_create_conn {
+ __le16 scan_interval;
+ __le16 scan_window;
+ __u8 filter_policy;
+ __u8 peer_addr_type;
+ bdaddr_t peer_addr;
+ __u8 own_address_type;
+ __le16 conn_interval_min;
+ __le16 conn_interval_max;
+ __le16 conn_latency;
+ __le16 supervision_timeout;
+ __le16 min_ce_len;
+ __le16 max_ce_len;
+} __packed;
+
+#define HCI_OP_LE_CREATE_CONN_CANCEL 0x200e
+
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01
@@ -902,6 +932,25 @@ struct hci_ev_remote_host_features {
__u8 features[8];
} __packed;
+#define HCI_EV_LE_META 0x3e
+struct hci_ev_le_meta {
+ __u8 subevent;
+} __packed;
+
+/* Low energy meta events */
+#define HCI_EV_LE_CONN_COMPLETE 0x01
+struct hci_ev_le_conn_complete {
+ __u8 status;
+ __le16 handle;
+ __u8 role;
+ __u8 bdaddr_type;
+ bdaddr_t bdaddr;
+ __le16 interval;
+ __le16 latency;
+ __le16 supervision_timeout;
+ __u8 clk_accurancy;
+} __packed;
+
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
--
1.7.4
^ permalink raw reply related
* [bluetooth-next -v2 00/24] Just Works SMP implementation
From: Vinicius Costa Gomes @ 2011-02-11 1:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Hi,
This patch series adds support for making (and receiving) LE connections
and the simplest SMP pairing method.
Fixed from v1:
- Ville's comments;
- Receiving LE connections (sorry);
What is (should be) working:
- Creating LE connections;
- Receiving LE connections;
- Creating LE connections with higher security levels (MEDIUM and HIGH);
- Changing security level during the connection;
This code is also on my personal repositories:
http://git.infradead.org/users/vcgomes/linux-2.6.git (branch for-next)
http://gitorious.org/bluetooth-next/bluetooth-next (branch for-next)
Cheers,
--
Anderson Briglia (7):
Bluetooth: Implement the first SMP commands
Bluetooth: Start SMP procedure
Bluetooth: simple SMP pairing negotiation
Bluetooth: LE SMP Cryptoolbox functions
Bluetooth: Add SMP confirmation structs
Bluetooth: Add SMP confirmation checks methods
Bluetooth: Minor fix in SMP methods
Ville Tervo (8):
Bluetooth: Add low energy commands and events
Bluetooth: Add LE connect support
Bluetooth: Use LE buffers for LE traffic
Bluetooth: Add LE connection support to L2CAP
Bluetooth: Add server socket support for LE connection
Bluetooth: Do not send disconn comand over LE links
Bluetooth: Treat LE and ACL links separately on timeout
Bluetooth: Add SMP command structures
Vinicius Costa Gomes (9):
Bluetooth: Fix initiated LE connections
Bluetooth: Add support for using the crypto subsystem
Bluetooth: Add support for LE Start Encryption
Bluetooth: Add support for resuming socket when SMP is finished
Bluetooth: Fix initial security level of LE links
Bluetooth: Update the security level when link is encrypted
Bluetooth: Add support for Pairing features exchange
Bluetooth: Add support for SMP timeout
Bluetooth: Add key size checks for SMP
include/net/bluetooth/hci.h | 85 ++++++
include/net/bluetooth/hci_core.h | 40 +++-
include/net/bluetooth/l2cap.h | 13 +
include/net/bluetooth/smp.h | 122 +++++++++
net/bluetooth/Kconfig | 12 +
net/bluetooth/Makefile | 2 +-
net/bluetooth/hci_conn.c | 105 ++++++++-
net/bluetooth/hci_core.c | 101 +++++++-
net/bluetooth/hci_event.c | 201 ++++++++++++++
net/bluetooth/l2cap_core.c | 242 +++++++++++++----
net/bluetooth/l2cap_sock.c | 46 +++-
net/bluetooth/smp.c | 534 ++++++++++++++++++++++++++++++++++++++
12 files changed, 1416 insertions(+), 87 deletions(-)
create mode 100644 include/net/bluetooth/smp.h
create mode 100644 net/bluetooth/smp.c
--
1.7.4
^ permalink raw reply
* [PATCH] Bluetooth: hcitool: add option for LE_Scan_Type parameter
From: Emeltchenko Andrei @ 2011-02-10 21:36 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
The LE_Scan_Type parameter controls the type of scan to perform.
---
tools/hcitool.c | 14 ++++++++++++--
1 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/tools/hcitool.c b/tools/hcitool.c
index c097526..6d17ad5 100644
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2350,23 +2350,33 @@ done:
static struct option lescan_options[] = {
{ "help", 0, 0, 'h' },
{ "privacy", 0, 0, 'p' },
+ { "scantype", 1, 0, 's' },
{ 0, 0, 0, 0 }
};
static const char *lescan_help =
"Usage:\n"
- "\tlescan [--privacy] enable privacy\n";
+ "\tlescan [--privacy] enable privacy\n"
+ "\tlescan [--scantype] set scan type 0 - passive, 1 - active (default)\n";
static void cmd_lescan(int dev_id, int argc, char **argv)
{
int err, opt, dd;
uint8_t own_type = 0x00;
+ uint8_t scan_type = 0x01;
for_each_opt(opt, lescan_options, NULL) {
switch (opt) {
case 'p':
own_type = 0x01; /* Random */
break;
+ case 's':
+ scan_type = atoi(optarg);
+ if (scan_type > 1) {
+ printf("%s", lescan_help);
+ exit(1);
+ }
+ break;
default:
printf("%s", lescan_help);
return;
@@ -2383,7 +2393,7 @@ static void cmd_lescan(int dev_id, int argc, char **argv)
exit(1);
}
- err = hci_le_set_scan_parameters(dd, 0x01, htobs(0x0010),
+ err = hci_le_set_scan_parameters(dd, scan_type, htobs(0x0010),
htobs(0x0010), own_type, 0x00);
if (err < 0) {
perror("Set scan parameters failed");
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] Bluetooth: Use proper timer for hci command timout
From: Gustavo F. Padovan @ 2011-02-10 19:03 UTC (permalink / raw)
To: Ville Tervo; +Cc: linux-bluetooth
In-Reply-To: <1297067207-7735-1-git-send-email-ville.tervo@nokia.com>
Hi Ville,
* Ville Tervo <ville.tervo@nokia.com> [2011-02-07 10:26:47 +0200]:
> Use proper timer instead of hci command flow control to timeout
> failed hci commands. Otherwise stack ends up sending commands
> when flow control is used to block new commands.
>
> 2010-09-01 18:29:41.592132 < HCI Command: Remote Name Request (0x01|0x0019) plen 10
> bdaddr 00:16:CF:E1:C7:D7 mode 2 clkoffset 0x0000
> 2010-09-01 18:29:41.592681 > HCI Event: Command Status (0x0f) plen 4
> Remote Name Request (0x01|0x0019) status 0x00 ncmd 0
> 2010-09-01 18:29:51.022033 < HCI Command: Remote Name Request Cancel (0x01|0x001a) plen 6
> bdaddr 00:16:CF:E1:C7:D7
>
> Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
> ---
> include/net/bluetooth/hci.h | 3 +++
> include/net/bluetooth/hci_core.h | 12 +++++++++++-
> net/bluetooth/hci_core.c | 21 +++++++++++++++------
> net/bluetooth/hci_event.c | 6 ++++++
> 4 files changed, 35 insertions(+), 7 deletions(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 4bee030..e3f0c7d 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -119,6 +119,7 @@ enum {
> #define HCI_PAIRING_TIMEOUT (60000) /* 60 seconds */
> #define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */
> #define HCI_INIT_TIMEOUT (10000) /* 10 seconds */
> +#define HCI_CMD_TIMEOUT (1000) /* 1 secs */
Just to be keep it similar to the other defines change the comment to "1
second"
>
> /* HCI data types */
> #define HCI_COMMAND_PKT 0x01
> @@ -242,6 +243,8 @@ enum {
> #define HCI_AT_GENERAL_BONDING_MITM 0x05
>
> /* ----- HCI Commands ---- */
> +#define HCI_OP_NOP 0x0000
> +
> #define HCI_OP_INQUIRY 0x0401
> struct hci_cp_inquiry {
> __u8 lap[3];
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 6163bff..42105f9 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -128,7 +128,6 @@ struct hci_dev {
> unsigned int acl_pkts;
> unsigned int sco_pkts;
>
> - unsigned long cmd_last_tx;
> unsigned long acl_last_tx;
> unsigned long sco_last_tx;
>
> @@ -138,6 +137,7 @@ struct hci_dev {
> struct work_struct power_off;
> struct timer_list off_timer;
>
> + struct timer_list cmd_timer;
> struct tasklet_struct cmd_task;
> struct tasklet_struct rx_task;
> struct tasklet_struct tx_task;
> @@ -417,6 +417,16 @@ static inline void hci_conn_put(struct hci_conn *conn)
> }
> }
>
> +static inline void hci_start_cmd_timer(struct timer_list *timer)
> +{
> + mod_timer(timer, jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
> +}
> +
> +static inline void hci_stop_cmd_timer(struct timer_list *timer)
> +{
> + del_timer(timer);
> +}
We don't really need this function. Just call del_timer directly.
Otherwise looks good. :-)
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH v5 0/4] Adding HID Feature Report Support to hidraw
From: Gustavo F. Padovan @ 2011-02-10 18:14 UTC (permalink / raw)
To: Jiri Kosina
Cc: Alan Ott, Marcel Holtmann, David S. Miller, Michael Poole,
Eric Dumazet, linux-input, linux-kernel, linux-usb,
linux-bluetooth, netdev
In-Reply-To: <alpine.LNX.2.00.1101191316230.26685@pobox.suse.cz>
Hi Jiri,
* Jiri Kosina <jkosina@suse.cz> [2011-01-19 13:17:00 +0100]:
> On Tue, 18 Jan 2011, Alan Ott wrote:
>
> > This patch adds Feature Report support for USB and Bluetooth HID devices
> > through hidraw.
> >
> > The first two patches prepare the bluetooth side for the change.
> > a. Make sure the hidp_session() thread is started before
> > device's probe() functions are called.
> > b. Wait for ACK/NAK on sent reports, and return proper
> > error codes.
> > The third patch is the hidraw core and USB changes.
> > The fourth patch is the Bluetooth changes.
> >
> > Thanks to Antonio Ospite and Bill Good for providing testing and feedback.
> >
> >
> > Alan Ott (4):
> > bt hidp: Move hid_add_device() call to after hidp_session() has
> > started.
> > bt hidp: Wait for ACK on Sent Reports
> > HID: Add Support for Setting and Getting Feature Reports from hidraw
> > Bluetooth hidp: Add support for hidraw HIDIOCGFEATURE and
> > HIDIOCSFEATURE
> >
> > drivers/hid/hidraw.c | 106 +++++++++++++++++++-
> > drivers/hid/usbhid/hid-core.c | 35 +++++++
> > include/linux/hid.h | 3 +
> > include/linux/hidraw.h | 3 +
> > net/bluetooth/hidp/core.c | 214 ++++++++++++++++++++++++++++++++++++++---
> > net/bluetooth/hidp/hidp.h | 15 +++
>
> Before proceeding with these patches, I'd really like to have comment
> (ideally 'Acked-by') from Marcel on the net/bluetooth/hidp part,
> obviously.
I have tested it and it seems ok to me and to Marcel. For net/bluetooth/
Acked-by: Gustavo F. Padovan <padovan@profusion.mobi>
Regards,
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH] bluetooth: l2cap: fix 1 byte infoleak to userspace
From: Gustavo F. Padovan @ 2011-02-10 18:11 UTC (permalink / raw)
To: Vasiliy Kulikov
Cc: linux-kernel, security, Marcel Holtmann, David S. Miller,
linux-bluetooth, netdev
In-Reply-To: <1297360783-21452-1-git-send-email-segoon@openwall.com>
Hi Vasiliy,
* Vasiliy Kulikov <segoon@openwall.com> [2011-02-10 20:59:42 +0300]:
> Structure l2cap_options has one padding byte between max_tx and
> txwin_size fields. This byte in "opts" is copied to userspace
> uninitialized.
>
> Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
> ---
> Compile tested only.
>
> net/bluetooth/l2cap_sock.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
Patch has been applied, thanks.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* [PATCH] bluetooth: l2cap: fix 1 byte infoleak to userspace
From: Vasiliy Kulikov @ 2011-02-10 17:59 UTC (permalink / raw)
To: linux-kernel
Cc: security, Marcel Holtmann, Gustavo F. Padovan, David S. Miller,
linux-bluetooth, netdev
Structure l2cap_options has one padding byte between max_tx and
txwin_size fields. This byte in "opts" is copied to userspace
uninitialized.
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
---
Compile tested only.
net/bluetooth/l2cap_sock.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index adf4169..21f5385 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -392,6 +392,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
switch (optname) {
case L2CAP_OPTIONS:
+ memset(&opts, 0, sizeof(opts));
opts.imtu = l2cap_pi(sk)->imtu;
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH] Bluetooth: Add firmware support for Atheros 3012
From: Gustavo F. Padovan @ 2011-02-10 17:26 UTC (permalink / raw)
To: Bala Shanmugam; +Cc: linux-bluetooth
In-Reply-To: <1297253715-15142-1-git-send-email-sbalashanmugam@atheros.com>
Hi Bala,
* Bala Shanmugam <sbalashanmugam@atheros.com> [2011-02-09 17:45:15 +0530]:
> Blacklisted AR3012 PID in btusb and added the same
> in ath3k to load patch and sysconfig files.
>
> Signed-off-by: Bala Shanmugam <sbalashanmugam@atheros.com>
> ---
> drivers/bluetooth/ath3k.c | 326 ++++++++++++++++++++++++++++++++++++++++++++-
> drivers/bluetooth/btusb.c | 3 +
> 2 files changed, 325 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
> index 41dadac..37e7cb4 100644
> --- a/drivers/bluetooth/ath3k.c
> +++ b/drivers/bluetooth/ath3k.c
> @@ -31,6 +31,33 @@
>
> #define VERSION "1.0"
>
> +#define ATH3K_DNLOAD 0x01
> +#define ATH3K_GETSTATE 0x05
> +#define ATH3K_SET_NORMAL_MODE 0x07
> +#define ATH3K_SET_PREBOOT_MODE 0x08
> +#define ATH3K_GETVERSION 0x09
> +#define USB_REG_SWITCH_VID_PID 0x0a
> +
> +#define ATH3K_MODE_MASK 0x3F
> +#define ATH3K_NORMAL_MODE 0x0E
> +#define ATH3K_PREBOOT_MODE 0x0D
> +
> +#define ATH3K_UPDATE_MASK 0xC0
> +#define ATH3K_PATCH_UPDATE 0x80
> +#define ATH3K_SYSCFG_UPDATE 0x40
> +
> +#define ATH3K_XTAL_FREQ_26M 0x00
> +#define ATH3K_XTAL_FREQ_40M 0x01
> +#define ATH3K_XTAL_FREQ_19P2 0x02
> +#define ATH3K_NAME_LEN 0xFF
There is some macros here that you are not using in the code.
> +
> +struct ath3k_version {
> + unsigned int rom_version;
> + unsigned int build_version;
> + unsigned int ram_version;
> + unsigned char ref_clock;
> + unsigned char reserved[0x07];
> +};
>
> static struct usb_device_id ath3k_table[] = {
> /* Atheros AR3011 */
> @@ -41,13 +68,29 @@ static struct usb_device_id ath3k_table[] = {
>
> /* Atheros AR9285 Malbec with sflash firmware */
> { USB_DEVICE(0x03F0, 0x311D) },
> +
> + /* Atheros AR3012 with sflash firmware*/
> + { USB_DEVICE(0x0CF3, 0x3004) },
> +
> { } /* Terminating entry */
> };
>
> MODULE_DEVICE_TABLE(usb, ath3k_table);
>
> +#define BTUSB_ATH3012 0x80
> +/* This table is to load patch and sysconfig files
> + * for AR3012 */
> +static struct usb_device_id ath3k_blist_tbl[] = {
> +
> + /* Atheros AR3012 with sflash firmware*/
> + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
> +
> + { } /* Terminating entry */
> +};
> +
> #define USB_REQ_DFU_DNLOAD 1
> #define BULK_SIZE 4096
> +#define FW_HDR_SIZE 20
>
> static int ath3k_load_firmware(struct usb_device *udev,
> const struct firmware *firmware)
> @@ -67,10 +110,10 @@ static int ath3k_load_firmware(struct usb_device *udev,
> }
>
> memcpy(send_buf, firmware->data, 20);
> - if ((err = usb_control_msg(udev, pipe,
> - USB_REQ_DFU_DNLOAD,
> - USB_TYPE_VENDOR, 0, 0,
> - send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) {
> + err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD,
> + USB_TYPE_VENDOR, 0, 0,
> + send_buf, 20, USB_CTRL_SET_TIMEOUT);
> + if (err < 0) {
> BT_ERR("Can't change to loading configuration err");
> goto error;
Please send a separate patch for code styling fixes.
> }
> @@ -103,6 +146,255 @@ error:
> return err;
> }
>
> +static int ath3k_get_state(struct usb_device *udev, unsigned char *state)
> +{
> + int pipe = 0, ret;
> +
> + pipe = usb_rcvctrlpipe(udev, 0);
> + ret = usb_control_msg(udev, pipe, ATH3K_GETSTATE,
> + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
> + state, 0x01, USB_CTRL_SET_TIMEOUT);
> + return ret;
return usb_control_msg(); and get rid of ret.
> +}
> +
> +static int ath3k_get_version(struct usb_device *udev,
> + struct ath3k_version *version)
> +{
> + int pipe = 0, ret;
> +
> + pipe = usb_rcvctrlpipe(udev, 0);
> + ret = usb_control_msg(udev, pipe, ATH3K_GETVERSION,
> + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version,
> + sizeof(struct ath3k_version),
> + USB_CTRL_SET_TIMEOUT);
> + return ret;
Same as above.
> +}
> +
> +static int ath3k_load_fwfile(struct usb_device *udev,
> + const struct firmware *firmware)
> +{
> + u8 *send_buf;
> + int err, pipe, len, size, count, sent = 0;
> + int ret;
> +
> + count = firmware->size;
> +
> + send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
> + if (!send_buf) {
> + BT_ERR("Can't allocate memory chunk for firmware");
> + return -ENOMEM;
> + }
> +
> + size = min_t(uint, count, FW_HDR_SIZE);
> + memcpy(send_buf, firmware->data, size);
> +
> + pipe = usb_sndctrlpipe(udev, 0);
> + ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD,
> + USB_TYPE_VENDOR, 0, 0, send_buf,
> + size, USB_CTRL_SET_TIMEOUT);
> + if (ret < 0) {
> + BT_ERR("Can't change to loading configuration err");
> + kfree(send_buf);
> + return ret;
> + }
> +
> + sent += size;
> + count -= size;
> +
> + while (count) {
> + size = min_t(uint, count, BULK_SIZE);
> + pipe = usb_sndbulkpipe(udev, 0x02);
> +
> + memcpy(send_buf, firmware->data + sent, size);
> +
> + err = usb_bulk_msg(udev, pipe, send_buf, size,
> + &len, 3000);
> + if (err || (len != size)) {
> + BT_ERR("Error in firmware loading err = %d,"
> + "len = %d, size = %d", err, len, size);
> + kfree(send_buf);
> + return err;
> + }
> + sent += size;
> + count -= size;
> + }
> +
> + kfree(send_buf);
> + return 0;
> +}
> +
> +static int ath3k_switch_pid(struct usb_device *udev)
> +{
> + int pipe = 0, ret;
> +
> + pipe = usb_sndctrlpipe(udev, 0);
> + ret = usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID,
> + USB_TYPE_VENDOR, 0, 0,
> + NULL, 0, USB_CTRL_SET_TIMEOUT);
> + return ret;
> +}
> +
> +static int ath3k_set_normal_mode(struct usb_device *udev)
> +{
> + unsigned char fw_state;
> + int pipe = 0, ret;
> +
> + ret = ath3k_get_state(udev, &fw_state);
> + if (ret < 0) {
> + BT_ERR("Can't get state to change to normal mode err");
> + return ret;
> + }
> +
> + if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) {
> + BT_DBG("firmware was already in normal mode");
> + return 0;
> + }
> +
> + pipe = usb_sndctrlpipe(udev, 0);
> + ret = usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE,
> + USB_TYPE_VENDOR, 0, 0,
> + NULL, 0, USB_CTRL_SET_TIMEOUT);
Use return usb_control_msg(); here as well.
> + if (ret < 0)
> + BT_ERR("Can't set normal mode err");
> +
> + return ret;
> +}
> +
> +static int ath3k_load_patch(struct usb_device *udev)
> +{
> + unsigned char fw_state;
> + char filename[ATH3K_NAME_LEN] = {0};
> + const struct firmware *firmware;
> + struct ath3k_version fw_version, pt_version;
> + int delay = 0, ret;
> +
> + ret = ath3k_get_state(udev, &fw_state);
> + if (ret < 0) {
> + BT_ERR("Can't get state to change to load ram patch err");
> + return ret;
> + }
> +
> + if (fw_state & ATH3K_PATCH_UPDATE) {
> + BT_DBG("Patch was already downloaded");
> + return 0;
> + }
> +
> + ret = ath3k_get_version(udev, &fw_version);
> + if (ret < 0) {
> + BT_ERR("Can't get version to change to load ram patch err");
> + return ret;
> + }
> +
> + snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
> + fw_version.rom_version);
> +
> + ret = request_firmware(&firmware, filename, &udev->dev);
> + if (ret < 0) {
> + BT_ERR("Patch file not found %s", filename);
> + return ret;
> + }
> +
> + pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
> + pt_version.build_version = *(int *)
> + (firmware->data + firmware->size - 4);
> +
> + if ((pt_version.rom_version != fw_version.rom_version) ||
> + (pt_version.build_version <= fw_version.build_version)) {
> + BT_ERR("Patch file version did not match with firmware");
> + release_firmware(firmware);
> + return -EINVAL;
> + }
> +
> + ret = ath3k_load_fwfile(udev, firmware);
> + if (ret < 0) {
> + BT_ERR("Patch loading failed - %s", filename);
> + release_firmware(firmware);
> + return ret;
> + }
> +
> + release_firmware(firmware);
> +
> + do {
> + ret = ath3k_get_state(udev, &fw_state);
> + if (ret < 0)
> + continue;
> +
> + if (fw_state & ATH3K_PATCH_UPDATE) {
> + BT_DBG("Patch has been downloaded successfully");
> + break;
> + }
> + delay++;
> + } while (delay < 3);
> +
> + return 0;
> +}
> +
> +static int ath3k_load_syscfg(struct usb_device *udev)
> +{
> + unsigned char fw_state;
> + char filename[ATH3K_NAME_LEN] = {0};
> + const struct firmware *firmware;
> + struct ath3k_version fw_version;
> + int clk_value, delay = 0, ret;
> +
> + if (ath3k_get_state(udev, &fw_state) < 0) {
> + BT_ERR("Can't get state to change to load configration err");
> + return -EBUSY;
> + }
> +
> + ret = ath3k_get_version(udev, &fw_version);
> + if (ret < 0) {
> + BT_ERR("Can't get version to change to load ram patch err");
> + return ret;
> + }
> +
> + switch (fw_version.ref_clock) {
> +
> + case ATH3K_XTAL_FREQ_26M:
> + clk_value = 26;
> + break;
> + case ATH3K_XTAL_FREQ_40M:
> + clk_value = 40;
> + break;
> + case ATH3K_XTAL_FREQ_19P2:
> + clk_value = 19;
> + break;
> + default:
> + clk_value = 0;
> + break;
> + }
> +
> + snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
> + fw_version.rom_version, clk_value, ".dfu");
> +
> + ret = request_firmware(&firmware, filename, &udev->dev);
> + if (ret < 0) {
> + BT_ERR("Configuration file not found %s", filename);
> + return ret;
> + }
> +
> + ret = ath3k_load_fwfile(udev, firmware);
> + if (ret < 0) {
> + BT_ERR("Configuration loading failed - %s", filename);
> + release_firmware(firmware);
> + return ret;
> + }
> +
> + release_firmware(firmware);
ret = ath3k_load_fwfile()
release_firmware()
if (ret < 0)
return ret;
> +
> + do {
> + ret = ath3k_get_state(udev, &fw_state);
> + if (ret < 0)
> + continue;
Can this became a infinite loop? if ath3k_get_state() always return ret < 0.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH 3/5] Add an initial interactive mode to gatttool
From: Johan Hedberg @ 2011-02-10 17:23 UTC (permalink / raw)
To: Sheldon Demario; +Cc: linux-bluetooth
In-Reply-To: <AANLkTin=2-k7F7DUO8rvzLJgf-m7+wUQ7FgtUR5ivuMu@mail.gmail.com>
Hi Sheldon,
On Thu, Feb 10, 2011, Sheldon Demario wrote:
> >> +static void cmd_help(int argcp, char **argvp);
> >> +static void cmd_exit(int argcp, char **argvp);
> >
> > No forward-declarations please. Just reorder the functions so that you
> > don't need to do this.
>
> The problem is the cmd_help() function. It must be declared to be
> known by commands[] array.
> The commands[] array also must be known by cmd_help(), so what do you
> suggest to solve this?
For that one a forward-declaration is fine.
Johan
^ permalink raw reply
* Re: [PATCH 3/5] Add an initial interactive mode to gatttool
From: Sheldon Demario @ 2011-02-10 17:14 UTC (permalink / raw)
To: Sheldon Demario, linux-bluetooth; +Cc: johan.hedberg
In-Reply-To: <20110209212642.GA11368@jh-x301>
Hi Johan,
>> +static void cmd_help(int argcp, char **argvp);
>> +static void cmd_exit(int argcp, char **argvp);
>
> No forward-declarations please. Just reorder the functions so that you
> don't need to do this.
The problem is the cmd_help() function. It must be declared to be
known by commands[] array.
The commands[] array also must be known by cmd_help(), so what do you
suggest to solve this?
Sheldon
>
> Johan
>
^ permalink raw reply
* [PATCH] (NOT FOR UPSTREAM) Do GATT discovery when SDP GATT record is found
From: Elvis Pfützenreuter @ 2011-02-10 13:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: epx
This patch changes BR/EDR behavior. When GATT device driver is probed,
or a SDP search finds a GATT record, a second discovery via GATT is
started.
This patch is for testing purposes only; the GATT spec states that
this is not the correct behavior for dual-mode. Services that are
to be exposed in LE and BR/EDR shall have SDP records of their own,
as well, so GATT discovery is not needed.
---
attrib/gatt.h | 2 -
attrib/manager.c | 8 +++---
lib/sdp.h | 4 +++
src/attrib-server.c | 3 --
src/device.c | 54 +++++++++++++++++++++++++++++++++++---------------
5 files changed, 46 insertions(+), 25 deletions(-)
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 9f69646..a457b62 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -22,8 +22,6 @@
*
*/
-#define GATT_CID 4
-
typedef void (*gatt_cb_t) (GSList *l, guint8 status, gpointer user_data);
guint gatt_discover_primary(GAttrib *attrib, uuid_t *uuid, gatt_cb_t func,
diff --git a/attrib/manager.c b/attrib/manager.c
index f991f8e..0a1964e 100644
--- a/attrib/manager.c
+++ b/attrib/manager.c
@@ -37,8 +37,6 @@
#include "client.h"
#include "example.h"
-#define GATT_UUID "00001801-0000-1000-8000-00805f9b34fb"
-
static DBusConnection *connection;
static int client_probe(struct btd_device *device, GSList *uuids)
@@ -46,7 +44,7 @@ static int client_probe(struct btd_device *device, GSList *uuids)
const sdp_record_t *rec;
int psm = -1;
- rec = btd_device_get_record(device, GATT_UUID);
+ rec = btd_device_get_record(device, GATT_UUID_STR);
if (rec) {
sdp_list_t *list;
if (sdp_get_access_protos(rec, &list) < 0)
@@ -61,6 +59,8 @@ static int client_probe(struct btd_device *device, GSList *uuids)
return -1;
}
+ device_browse_primary(device, NULL, NULL, FALSE);
+
return attrib_client_register(device, psm);
}
@@ -71,7 +71,7 @@ static void client_remove(struct btd_device *device)
static struct btd_device_driver client_driver = {
.name = "gatt-client",
- .uuids = BTD_UUIDS(GATT_UUID),
+ .uuids = BTD_UUIDS(GATT_UUID_STR),
.probe = client_probe,
.remove = client_remove,
};
diff --git a/lib/sdp.h b/lib/sdp.h
index 16b59fc..9abfc1f 100644
--- a/lib/sdp.h
+++ b/lib/sdp.h
@@ -44,6 +44,8 @@ extern "C" {
* of the Bluetooth Specification
*/
#define SDP_PSM 0x0001
+#define GATT_PSM 0x001f
+#define GATT_CID 0x0004
/*
* Protocol UUIDs
@@ -73,6 +75,8 @@ extern "C" {
#define MCAP_DATA_UUID 0x001f
#define L2CAP_UUID 0x0100
#define ATT_UUID 0x1801
+#define GATT_UUID 0x1801
+#define GATT_UUID_STR "00001801-0000-1000-8000-00805f9b34fb"
/*
* Service class identifiers of standard services and service groups
diff --git a/src/attrib-server.c b/src/attrib-server.c
index f03a5b9..bb25d13 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -46,9 +46,6 @@
#include "attrib-server.h"
-#define GATT_PSM 0x1f
-#define GATT_CID 4
-
static GSList *database = NULL;
struct gatt_channel {
diff --git a/src/device.c b/src/device.c
index 0fef71a..bfade65 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1375,6 +1375,9 @@ static void create_device_reply(struct btd_device *device, struct browse_req *re
{
DBusMessage *reply;
+ if (!req->msg)
+ return;
+
reply = dbus_message_new_method_return(req->msg);
if (!reply)
return;
@@ -1460,6 +1463,10 @@ cleanup:
device->browse = NULL;
browse_request_free(req);
+
+ if (g_slist_find_custom(device->uuids, GATT_UUID_STR,
+ (GCompareFunc) strcasecmp) != NULL)
+ device_browse_primary(device, NULL, NULL, FALSE);
}
static void browse_cb(sdp_list_t *recs, int err, gpointer user_data)
@@ -1544,9 +1551,11 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
char *str;
if (status) {
- DBusMessage *reply;
- reply = btd_error_failed(req->msg, att_ecode2str(status));
- g_dbus_send_message(req->conn, reply);
+ if (req->msg) {
+ DBusMessage *reply;
+ reply = btd_error_failed(req->msg, att_ecode2str(status));
+ g_dbus_send_message(req->conn, reply);
+ }
goto done;
}
@@ -1588,8 +1597,10 @@ static void gatt_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
DBG("%s", gerr->message);
- reply = btd_error_failed(req->msg, gerr->message);
- g_dbus_send_message(req->conn, reply);
+ if (req->msg) {
+ reply = btd_error_failed(req->msg, gerr->message);
+ g_dbus_send_message(req->conn, reply);
+ }
device->browse = NULL;
browse_request_free(req);
@@ -1619,22 +1630,33 @@ int device_browse_primary(struct btd_device *device, DBusConnection *conn,
sec_level = secure ? BT_IO_SEC_HIGH : BT_IO_SEC_LOW;
- req->io = bt_io_connect(BT_IO_L2CAP, gatt_connect_cb, req, NULL, NULL,
- BT_IO_OPT_SOURCE_BDADDR, &src,
- BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
- BT_IO_OPT_CID, GATT_CID,
- BT_IO_OPT_SEC_LEVEL, sec_level,
- BT_IO_OPT_INVALID);
-
- if (req->io == NULL ) {
+ if (device_get_type(device) == DEVICE_TYPE_BREDR)
+ req->io = bt_io_connect(BT_IO_L2CAP, gatt_connect_cb, req, NULL, NULL,
+ BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
+ BT_IO_OPT_PSM, GATT_PSM,
+ BT_IO_OPT_SEC_LEVEL, sec_level,
+ BT_IO_OPT_INVALID);
+ else
+ req->io = bt_io_connect(BT_IO_L2CAP, gatt_connect_cb, req, NULL, NULL,
+ BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
+ BT_IO_OPT_CID, GATT_CID,
+ BT_IO_OPT_SEC_LEVEL, sec_level,
+ BT_IO_OPT_INVALID);
+
+ if (req->io == NULL) {
browse_request_free(req);
return -EIO;
}
- if (conn == NULL)
- conn = get_dbus_connection();
+ if (msg) {
+ if (conn == NULL)
+ conn = get_dbus_connection();
+
+ req->conn = dbus_connection_ref(conn);
+ }
- req->conn = dbus_connection_ref(conn);
device->browse = req;
if (msg) {
--
1.7.1
^ permalink raw reply related
* [PATCH] Add check for ACL_START_NO_FLUSH
From: Daniel Örstadius @ 2011-02-10 11:01 UTC (permalink / raw)
To: linux-bluetooth
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: 0001-Add-check-for-ACL_START_NO_FLUSH.patch --]
[-- Type: text/x-patch, Size: 968 bytes --]
From 19bbd9d8236a643ec0674452b143dc451531a862 Mon Sep 17 00:00:00 2001
From: Daniel Orstadius <daniel.orstadius@nokia.com>
Date: Thu, 10 Feb 2011 12:34:01 +0200
Subject: [PATCH] Add check for ACL_START_NO_FLUSH
In addition to ACL_START, hcidump should check for the flag
ACL_START_NO_FLUSH to indicate the start of a frame.
Using '==' instead of '&' for the comparison since
ACL_START_NO_FLUSH is defined to zero.
The flag was introduced in BlueZ commit
2430512c983cad8c20252f1df8f297399993ca3d
---
parser/l2cap.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/parser/l2cap.c b/parser/l2cap.c
index 963468c..e25ce7f 100644
--- a/parser/l2cap.c
+++ b/parser/l2cap.c
@@ -941,7 +941,8 @@ void l2cap_dump(int level, struct frame *frm)
l2cap_hdr *hdr;
uint16_t dlen;
- if (frm->flags & ACL_START) {
+ if (frm->flags & ACL_START ||
+ frm->flags == ACL_START_NO_FLUSH) {
hdr = frm->ptr;
dlen = btohs(hdr->len);
--
1.6.0.4
^ permalink raw reply related
* [RESEND] ID_SERIAL for udev bluetooth joystick events
From: Antonio Ospite @ 2011-02-10 10:42 UTC (permalink / raw)
To: linux-hotplug; +Cc: linux-input, linux-bluetooth
[-- Attachment #1: Type: text/plain, Size: 1830 bytes --]
Hi,
I have a question about udev events generated by a bluetooth joystick:
when udev generates the joystick event for a bt joystick, the ID_SERIAL
property matches the one of the bt adapter not the one of the joystick.
For example (using "udevadm monitor --property"), when connecting the
Sony Sixaxis via usb I get:
ID_SERIAL=Sony_PLAYSTATION_R_3_Controller
in the input and joystick events, but when I connect it via bt, I get:
ID_SERIAL=Broadcom_Corp_ANYCOM_Blue_USB-200_250
which matches my bluetooth adapter.
Is this expected/known, or is it a bug?
I am using kernel 2.6.37, udev 164
For the records, I also get ID_BUS=usb when connecting via bt, but I can
live with that since I can differenciate usb and bt operation using
ID_USB_DRIVER=usbhid
versus
ID_USB_DRIVER=btusb
Some insight of what I am trying to achieve with udev:
1. Monitor new joystick devices.
2. If ID_SERIAL != Sony_PLAYSTATION_R_3_Controller, then STOP.
3. Get the associated hidraw device node navigating the event tree.
4. Set leds using the value from the ID_INPUT_JOYSTICK property.
5. If ID_USB_DRIVER=usbhid do the needed pairing.
And with the current behaviour for ID_SERIAL I cannot enforce 2.
I could listen for the (hid) event and use HID_NAME which seems to be a
little more consistent:
usb -> HID_NAME=Sony PLAYSTATION(R)3 Controller
bt -> HID_NAME=PLAYSTATION(R)3 Controller
and navigate the event hierarchy to get ID_INPUT_JOYSTICK, but that is
slightly more complicated, and I am curious about the ID_SERIAL
behavior anyways :)
Thanks,
Antonio
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* [PATCH] hfp: gateway_suspend_stream should trigger a state change
From: Daniel Wagner @ 2011-02-10 10:41 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Daniel Wagner
From: Daniel Wagner <daniel.wagner@bmw-carit.de>
When gateway_suspend_stream is called it should change the
gateway state machine from PLAYING to CONNECTED.
---
audio/gateway.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/audio/gateway.c b/audio/gateway.c
index 43a4b02..ec0ec5d 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -707,4 +707,5 @@ void gateway_suspend_stream(struct audio_device *dev)
gw->sco = NULL;
gw->sco_start_cb = NULL;
gw->sco_start_cb_data = NULL;
+ change_state(dev, GATEWAY_STATE_CONNECTED);
}
--
1.7.4
^ permalink raw reply related
* Re: [bluetooth-next 00/24] Just Works SMP implementation
From: Ville Tervo @ 2011-02-10 6:57 UTC (permalink / raw)
To: ext Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <1297300704-30006-1-git-send-email-vinicius.gomes@openbossa.org>
Hi Vinicius,
On Wed, Feb 09, 2011 at 10:18:00PM -0300, ext Vinicius Costa Gomes wrote:
> Hi,
>
> This patch series adds support for making (and receiving) LE connections
> and the simplest SMP pairing method.
I found only minor cosmetic suggestions so far. We'll have more knowledge about
the functionality after UPF.
--
Ville
^ permalink raw reply
* Re: [bluetooth-next 16/24] Bluetooth: Add SMP confirmation checks methods
From: Ville Tervo @ 2011-02-10 6:37 UTC (permalink / raw)
To: ext Vinicius Costa Gomes; +Cc: linux-bluetooth, Anderson Briglia
In-Reply-To: <1297300704-30006-17-git-send-email-vinicius.gomes@openbossa.org>
On Wed, Feb 09, 2011 at 10:18:16PM -0300, ext Vinicius Costa Gomes wrote:
> From: Anderson Briglia <anderson.briglia@openbossa.org>
>
> This patch includes support for generating and sending the random value
> used to produce the confirmation value.
>
> Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
> ---
> include/net/bluetooth/l2cap.h | 1 +
> net/bluetooth/smp.c | 93 ++++++++++++++++++++++++++++++++++-------
> 2 files changed, 79 insertions(+), 15 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index ceea46d..359dd1b 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -294,6 +294,7 @@ struct l2cap_conn {
> __u8 pres[7];
> __u8 prnd[16];
> __u8 pcnf[16];
> + __u8 tk[16];
>
> struct l2cap_chan_list chan_list;
> };
> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> index 89e08fe..438226a0 100644
> --- a/net/bluetooth/smp.c
> +++ b/net/bluetooth/smp.c
> @@ -203,6 +203,9 @@ static void smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
> rp->resp_key_dist = 0x00;
> rp->auth_req &= 0x05;
>
> + /* Just works */
> + memset(conn->tk, 0, sizeof(conn->tk));
> +
> conn->pres[0] = SMP_CMD_PAIRING_RSP;
> memcpy(&conn->pres[1], rp, sizeof(*rp));
>
> @@ -213,53 +216,113 @@ static void smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
> {
> struct smp_cmd_pairing *rp = (void *) skb->data;
> struct smp_cmd_pairing_confirm cp;
> + struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
> + int ret;
> + u8 res[16];
>
> BT_DBG("conn %p", conn);
>
> - memset(&cp, 0, sizeof(cp));
> + /* Just works */
> + memset(conn->tk, 0, sizeof(conn->tk));
>
> conn->pres[0] = SMP_CMD_PAIRING_RSP;
> memcpy(&conn->pres[1], rp, sizeof(*rp));
> skb_pull(skb, sizeof(*rp));
>
> + ret = smp_rand(conn->prnd);
> + if (ret)
> + return;
> +
> + ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->pres, 0,
> + conn->src, 0, conn->dst, res);
> + if (ret)
> + return;
> +
> + swap128(res, cp.confirm_val);
> +
> smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
> }
>
> static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
> {
> + struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
> +
> BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
>
> - if (conn->hcon->out) {
> - struct smp_cmd_pairing_random random;
> + memcpy(conn->pcnf, skb->data, 16);
> + skb_pull(skb, 16);
Use sizeof().
>
> - memset(&random, 0, sizeof(random));
> + if (conn->hcon->out) {
> + u8 random[16];
>
> - smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
> - &random);
> + swap128(conn->prnd, random);
> + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, random);
Ditto
> } else {
> - struct smp_cmd_pairing_confirm confirm;
> + struct smp_cmd_pairing_confirm cp;
> + int ret;
> + u8 res[16];
>
> - memset(&confirm, 0, sizeof(confirm));
> + ret = smp_rand(conn->prnd);
> + if (ret)
> + return;
>
> - smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(confirm),
> - &confirm);
> + ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->pres,
> + 0, conn->dst, 0, conn->src, res);
> + if (ret)
> + return;
> +
> + swap128(res, cp.confirm_val);
> +
> + smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
> }
> }
>
> static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
> {
> - struct smp_cmd_pairing_random cp;
> + struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
> + int ret;
> + u8 key[16], res[16], random[16], confirm[16], buf[128];
> +
> + swap128(skb->data, random);
> + skb_pull(skb, 16);
Ditto
>
> +
> + if (conn->hcon->out)
> + ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->pres, 0,
> + conn->src, 0, conn->dst, res);
> + else
> + ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->pres, 0,
> + conn->dst, 0, conn->src, res);
> + if (ret)
> + return;
>
> BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
>
> - skb_pull(skb, sizeof(cp));
> + swap128(res, confirm);
> +
> + if (memcmp(conn->pcnf, confirm, 16) != 0) {
Ditto
> + struct smp_cmd_pairing_fail cp;
> +
> + BT_ERR("Pairing failed (confirmation values mismatch)");
> + cp.reason = SMP_CONFIRM_FAILED;
> + smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(cp), &cp);
> + return;
> + }
>
> if (conn->hcon->out) {
> - /* FIXME: start encryption */
> + smp_s1(tfm, conn->tk, random, conn->prnd, key);
> +
> + hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
> + BT_DBG("key %s", buf);
> } else {
> - memset(&cp, 0, sizeof(cp));
> + u8 r[16];
> +
> + swap128(conn->prnd, r);
> + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, r);
Ditto
> +
> + smp_s1(tfm, conn->tk, conn->prnd, random, key);
>
> - smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(cp), &cp);
> + hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
> + BT_DBG("key %s", buf);
> }
> }
--
Ville
^ 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