aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/a2mp.c
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-09-27 10:26:15 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-09-27 16:14:03 -0400
commit9a5e94dbb4aa306742a47cbbcb0a44d4fc77a9e4 (patch)
treedf4fc293e1411287fbbadc083c50ea85d956196b /net/bluetooth/a2mp.c
parent0d868de9d8760c76f6d4c6c777935c05ef272caa (diff)
Bluetooth: A2MP: Process A2MP Get AMP Assoc Rsp
When receiving A2MP Get AMP Assoc Response save assoc data to remote AMP controller list and prepare for creating physical link. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth/a2mp.c')
-rw-r--r--net/bluetooth/a2mp.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 594df9643365..d0fde05e8b17 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -343,6 +343,61 @@ done:
343 return 0; 343 return 0;
344} 344}
345 345
346static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
347 struct a2mp_cmd *hdr)
348{
349 struct a2mp_amp_assoc_rsp *rsp = (void *) skb->data;
350 u16 len = le16_to_cpu(hdr->len);
351 struct hci_dev *hdev;
352 struct amp_ctrl *ctrl;
353 struct hci_conn *hcon;
354
355 if (len < sizeof(*rsp))
356 return -EINVAL;
357
358 BT_DBG("id %d status 0x%2.2x assoc len %u", rsp->id, rsp->status,
359 len - sizeof(*rsp));
360
361 if (rsp->status)
362 return -EINVAL;
363
364 /* Save remote ASSOC data */
365 ctrl = amp_ctrl_lookup(mgr, rsp->id);
366 if (ctrl) {
367 u8 *assoc, assoc_len = len - sizeof(*rsp);
368
369 assoc = kzalloc(assoc_len, GFP_KERNEL);
370 if (!assoc) {
371 amp_ctrl_put(ctrl);
372 return -ENOMEM;
373 }
374
375 memcpy(assoc, rsp->amp_assoc, assoc_len);
376 ctrl->assoc = assoc;
377 ctrl->assoc_len = assoc_len;
378 ctrl->assoc_rem_len = assoc_len;
379 ctrl->assoc_len_so_far = 0;
380
381 amp_ctrl_put(ctrl);
382 }
383
384 /* Create Phys Link */
385 hdev = hci_dev_get(rsp->id);
386 if (!hdev)
387 return -EINVAL;
388
389 hcon = phylink_add(hdev, mgr, rsp->id);
390 if (!hcon)
391 goto done;
392
393 BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id);
394
395done:
396 hci_dev_put(hdev);
397 skb_pull(skb, len);
398 return 0;
399}
400
346static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, 401static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
347 struct a2mp_cmd *hdr) 402 struct a2mp_cmd *hdr)
348{ 403{
@@ -502,8 +557,11 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
502 err = a2mp_getinfo_rsp(mgr, skb, hdr); 557 err = a2mp_getinfo_rsp(mgr, skb, hdr);
503 break; 558 break;
504 559
505 case A2MP_CHANGE_RSP:
506 case A2MP_GETAMPASSOC_RSP: 560 case A2MP_GETAMPASSOC_RSP:
561 err = a2mp_getampassoc_rsp(mgr, skb, hdr);
562 break;
563
564 case A2MP_CHANGE_RSP:
507 case A2MP_CREATEPHYSLINK_RSP: 565 case A2MP_CREATEPHYSLINK_RSP:
508 case A2MP_DISCONNPHYSLINK_RSP: 566 case A2MP_DISCONNPHYSLINK_RSP:
509 err = a2mp_cmd_rsp(mgr, skb, hdr); 567 err = a2mp_cmd_rsp(mgr, skb, hdr);