aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-09-27 10:26:10 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-09-27 16:11:12 -0400
commitaa09537d80bf7e6282103618eb496f03e76f2953 (patch)
treec1b4022bf6f70784fcc39f75b6a93bbda6dedb06 /net
parent903e45411099ae8292f5ce637ad0c72f6fef61db (diff)
Bluetooth: A2MP: Process Discover Response
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> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/a2mp.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 71400612843d..f04c44146663 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)
67 kfree(cmd); 67 kfree(cmd);
68} 68}
69 69
70static u8 __next_ident(struct amp_mgr *mgr)
71{
72 if (++mgr->ident == 0)
73 mgr->ident = 1;
74
75 return mgr->ident;
76}
77
70static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) 78static inline void __a2mp_cl_bredr(struct a2mp_cl *cl)
71{ 79{
72 cl->id = 0; 80 cl->id = 0;
@@ -165,6 +173,55 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
165 return 0; 173 return 0;
166} 174}
167 175
176static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
177 struct a2mp_cmd *hdr)
178{
179 struct a2mp_discov_rsp *rsp = (void *) skb->data;
180 u16 len = le16_to_cpu(hdr->len);
181 struct a2mp_cl *cl;
182 u16 ext_feat;
183
184 if (len < sizeof(*rsp))
185 return -EINVAL;
186
187 len -= sizeof(*rsp);
188 skb_pull(skb, sizeof(*rsp));
189
190 ext_feat = le16_to_cpu(rsp->ext_feat);
191
192 BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(rsp->mtu), ext_feat);
193
194 /* check that packet is not broken for now */
195 while (ext_feat & A2MP_FEAT_EXT) {
196 if (len < sizeof(ext_feat))
197 return -EINVAL;
198
199 ext_feat = get_unaligned_le16(skb->data);
200 BT_DBG("efm 0x%4.4x", ext_feat);
201 len -= sizeof(ext_feat);
202 skb_pull(skb, sizeof(ext_feat));
203 }
204
205 cl = (void *) skb->data;
206 while (len >= sizeof(*cl)) {
207 BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type,
208 cl->status);
209
210 if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) {
211 struct a2mp_info_req req;
212
213 req.id = cl->id;
214 a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
215 sizeof(req), &req);
216 }
217
218 len -= sizeof(*cl);
219 cl = (void *) skb_pull(skb, sizeof(*cl));
220 }
221
222 return 0;
223}
224
168static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb, 225static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb,
169 struct a2mp_cmd *hdr) 226 struct a2mp_cmd *hdr)
170{ 227{
@@ -391,8 +448,11 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
391 err = a2mp_discphyslink_req(mgr, skb, hdr); 448 err = a2mp_discphyslink_req(mgr, skb, hdr);
392 break; 449 break;
393 450
394 case A2MP_CHANGE_RSP:
395 case A2MP_DISCOVER_RSP: 451 case A2MP_DISCOVER_RSP:
452 err = a2mp_discover_rsp(mgr, skb, hdr);
453 break;
454
455 case A2MP_CHANGE_RSP:
396 case A2MP_GETINFO_RSP: 456 case A2MP_GETINFO_RSP:
397 case A2MP_GETAMPASSOC_RSP: 457 case A2MP_GETAMPASSOC_RSP:
398 case A2MP_CREATEPHYSLINK_RSP: 458 case A2MP_CREATEPHYSLINK_RSP: