summaryrefslogtreecommitdiff
path: root/net/bluetooth/l2cap_core.c
diff options
context:
space:
mode:
authorVinicius Costa Gomes <vinicius.gomes@openbossa.org>2011-01-26 21:42:57 -0300
committerJaikumar Ganesh <jaikumar@google.com>2011-07-11 11:59:22 -0700
commita5474a8d5ad4b2426c41012c63030fd789a047a3 (patch)
tree2b4f8baa9a107ef3d732001b0dabb27e401b0bdf /net/bluetooth/l2cap_core.c
parentc34e25e8e927c6d052c65adbdb4ab6898c184c96 (diff)
Bluetooth: Add support for resuming socket when SMP is finished
This adds support for resuming the user space traffic when SMP negotiation is complete. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r--net/bluetooth/l2cap_core.c61
1 files changed, 31 insertions, 30 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2d7c6b1e4ea..ed8aac7412a 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -891,6 +891,23 @@ clean:
bh_unlock_sock(parent);
}
+static void l2cap_chan_ready(struct sock *sk)
+{
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ struct sock *parent = bt_sk(sk)->parent;
+
+ BT_DBG("sk %p, parent %p", sk, parent);
+
+ chan->conf_state = 0;
+ __clear_chan_timer(chan);
+
+ sk->sk_state = BT_CONNECTED;
+ sk->sk_state_change(sk);
+
+ if (parent)
+ parent->sk_data_ready(parent, 0);
+}
+
static void l2cap_conn_ready(struct l2cap_conn *conn)
{
struct l2cap_chan *chan;
@@ -907,13 +924,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
bh_lock_sock(sk);
- if (conn->hcon->type == LE_LINK) {
- __clear_chan_timer(chan);
- l2cap_state_change(chan, BT_CONNECTED);
- sk->sk_state_change(sk);
+ if (conn->hcon->type == LE_LINK)
if (smp_conn_security(conn, chan->sec_level))
- BT_DBG("Insufficient security");
- }
+ l2cap_chan_ready(sk);
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
__clear_chan_timer(chan);
@@ -1676,30 +1689,6 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
return err;
}
-static void l2cap_chan_ready(struct sock *sk)
-{
- struct sock *parent = bt_sk(sk)->parent;
- struct l2cap_chan *chan = l2cap_pi(sk)->chan;
-
- BT_DBG("sk %p, parent %p", sk, parent);
-
- chan->conf_state = 0;
- __clear_chan_timer(chan);
-
- if (!parent) {
- /* Outgoing channel.
- * Wake up socket sleeping on connect.
- */
- l2cap_state_change(chan, BT_CONNECTED);
- sk->sk_state_change(sk);
- } else {
- /* Incoming channel.
- * Wake up socket sleeping on accept.
- */
- parent->sk_data_ready(parent, 0);
- }
-}
-
/* Copy frame to all raw sockets on that connection */
static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
{
@@ -4189,6 +4178,18 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
bh_lock_sock(sk);
+ BT_DBG("chan->scid %d", chan->scid);
+
+ if (chan->scid == L2CAP_CID_LE_DATA) {
+ if (!status && encrypt) {
+ chan->sec_level = hcon->sec_level;
+ l2cap_chan_ready(sk);
+ }
+
+ bh_unlock_sock(sk);
+ continue;
+ }
+
if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
bh_unlock_sock(sk);
continue;