diff options
author | Andrei Emeltchenko <andrei.emeltchenko@intel.com> | 2012-09-27 10:26:21 -0400 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2012-09-27 16:31:52 -0400 |
commit | 2766be48a7181d7f2a84831ca7e7be248fb6fdb5 (patch) | |
tree | 9d5554696f17b42a2724b652928450f745cb00a8 /net | |
parent | 93c284ee901f7d7bdd09087e92abefb7496c3777 (diff) |
Bluetooth: A2MP: Add fallback to normal l2cap init sequence
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/a2mp.c | 28 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 2 |
2 files changed, 29 insertions, 1 deletions
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 773e8fc41670..28d1246958be 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -180,6 +180,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
180 | u16 len = le16_to_cpu(hdr->len); | 180 | u16 len = le16_to_cpu(hdr->len); |
181 | struct a2mp_cl *cl; | 181 | struct a2mp_cl *cl; |
182 | u16 ext_feat; | 182 | u16 ext_feat; |
183 | bool found = false; | ||
183 | 184 | ||
184 | if (len < sizeof(*rsp)) | 185 | if (len < sizeof(*rsp)) |
185 | return -EINVAL; | 186 | return -EINVAL; |
@@ -210,6 +211,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
210 | if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) { | 211 | if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) { |
211 | struct a2mp_info_req req; | 212 | struct a2mp_info_req req; |
212 | 213 | ||
214 | found = true; | ||
213 | req.id = cl->id; | 215 | req.id = cl->id; |
214 | a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr), | 216 | a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr), |
215 | sizeof(req), &req); | 217 | sizeof(req), &req); |
@@ -219,6 +221,32 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
219 | cl = (void *) skb_pull(skb, sizeof(*cl)); | 221 | cl = (void *) skb_pull(skb, sizeof(*cl)); |
220 | } | 222 | } |
221 | 223 | ||
224 | /* Fall back to L2CAP init sequence */ | ||
225 | if (!found) { | ||
226 | struct l2cap_conn *conn = mgr->l2cap_conn; | ||
227 | struct l2cap_chan *chan; | ||
228 | |||
229 | mutex_lock(&conn->chan_lock); | ||
230 | |||
231 | list_for_each_entry(chan, &conn->chan_l, list) { | ||
232 | |||
233 | BT_DBG("chan %p state %s", chan, | ||
234 | state_to_string(chan->state)); | ||
235 | |||
236 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) | ||
237 | continue; | ||
238 | |||
239 | l2cap_chan_lock(chan); | ||
240 | |||
241 | if (chan->state == BT_CONNECT) | ||
242 | l2cap_send_conn_req(chan); | ||
243 | |||
244 | l2cap_chan_unlock(chan); | ||
245 | } | ||
246 | |||
247 | mutex_unlock(&conn->chan_lock); | ||
248 | } | ||
249 | |||
222 | return 0; | 250 | return 0; |
223 | } | 251 | } |
224 | 252 | ||
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 781a085ae5bc..a347522b2144 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -958,7 +958,7 @@ static bool __amp_capable(struct l2cap_chan *chan) | |||
958 | return false; | 958 | return false; |
959 | } | 959 | } |
960 | 960 | ||
961 | static void l2cap_send_conn_req(struct l2cap_chan *chan) | 961 | void l2cap_send_conn_req(struct l2cap_chan *chan) |
962 | { | 962 | { |
963 | struct l2cap_conn *conn = chan->conn; | 963 | struct l2cap_conn *conn = chan->conn; |
964 | struct l2cap_conn_req req; | 964 | struct l2cap_conn_req req; |