Bluetooth: A2MP: Add fallback to normal l2cap init sequence
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>
Thu, 27 Sep 2012 14:26:21 +0000 (17:26 +0300)
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>
Thu, 27 Sep 2012 20:31:52 +0000 (17:31 -0300)
When there is no remote AMP controller found fallback to normal
L2CAP sequence.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
include/net/bluetooth/l2cap.h
net/bluetooth/a2mp.c
net/bluetooth/l2cap_core.c

index aba830fc762f5d870440ee8a5aef8c6d3ec7c02b..0967f9e337505eb9a64a43221a408455a8437a29 100644 (file)
@@ -769,5 +769,6 @@ 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);
+void l2cap_send_conn_req(struct l2cap_chan *chan);
 
 #endif /* __L2CAP_H */
index 773e8fc416700681684b2a380a59eee50802def4..28d1246958befbd6e624d0299111081b70daa729 100644 (file)
@@ -180,6 +180,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
        u16 len = le16_to_cpu(hdr->len);
        struct a2mp_cl *cl;
        u16 ext_feat;
+       bool found = false;
 
        if (len < sizeof(*rsp))
                return -EINVAL;
@@ -210,6 +211,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
                if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) {
                        struct a2mp_info_req req;
 
+                       found = true;
                        req.id = cl->id;
                        a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
                                  sizeof(req), &req);
@@ -219,6 +221,32 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
                cl = (void *) skb_pull(skb, sizeof(*cl));
        }
 
+       /* Fall back to L2CAP init sequence */
+       if (!found) {
+               struct l2cap_conn *conn = mgr->l2cap_conn;
+               struct l2cap_chan *chan;
+
+               mutex_lock(&conn->chan_lock);
+
+               list_for_each_entry(chan, &conn->chan_l, list) {
+
+                       BT_DBG("chan %p state %s", chan,
+                              state_to_string(chan->state));
+
+                       if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP)
+                               continue;
+
+                       l2cap_chan_lock(chan);
+
+                       if (chan->state == BT_CONNECT)
+                               l2cap_send_conn_req(chan);
+
+                       l2cap_chan_unlock(chan);
+               }
+
+               mutex_unlock(&conn->chan_lock);
+       }
+
        return 0;
 }
 
index 781a085ae5bc4da76d6c26b29c0547b570ee87cb..a347522b2144d5bc493babfa9477c3658a6e9429 100644 (file)
@@ -958,7 +958,7 @@ static bool __amp_capable(struct l2cap_chan *chan)
                return false;
 }
 
-static void l2cap_send_conn_req(struct l2cap_chan *chan)
+void l2cap_send_conn_req(struct l2cap_chan *chan)
 {
        struct l2cap_conn *conn = chan->conn;
        struct l2cap_conn_req req;