aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-09-27 10:26:24 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-09-27 16:35:09 -0400
commit0b26ab9dce74f8ac77d7eef0d683ab1d527e45b1 (patch)
tree201cc46c4bf0189d649988deb4ad3366f8d30d34
parentdffa387110025801862d7ad09f4e850d06ff55a9 (diff)
Bluetooth: AMP: Handle Accept phylink command status evt
When receiving HCI Command Status event for Accept Physical Link execute HCI Write Remote AMP Assoc with data saved from A2MP Create Physical Link Request. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r--include/net/bluetooth/amp.h1
-rw-r--r--net/bluetooth/a2mp.c32
-rw-r--r--net/bluetooth/amp.c2
-rw-r--r--net/bluetooth/hci_event.c20
4 files changed, 54 insertions, 1 deletions
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 1b06d7b01359..b1e54903dd42 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -25,6 +25,7 @@ struct amp_ctrl {
25}; 25};
26 26
27int amp_ctrl_put(struct amp_ctrl *ctrl); 27int amp_ctrl_put(struct amp_ctrl *ctrl);
28void amp_ctrl_get(struct amp_ctrl *ctrl);
28struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr); 29struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr);
29struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id); 30struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
30void amp_ctrl_list_flush(struct amp_mgr *mgr); 31void amp_ctrl_list_flush(struct amp_mgr *mgr);
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index dbfdbbb9707c..47565d28b27f 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -438,6 +438,7 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
438 struct a2mp_physlink_rsp rsp; 438 struct a2mp_physlink_rsp rsp;
439 struct hci_dev *hdev; 439 struct hci_dev *hdev;
440 struct hci_conn *hcon; 440 struct hci_conn *hcon;
441 struct amp_ctrl *ctrl;
441 442
442 if (le16_to_cpu(hdr->len) < sizeof(*req)) 443 if (le16_to_cpu(hdr->len) < sizeof(*req))
443 return -EINVAL; 444 return -EINVAL;
@@ -453,6 +454,37 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
453 goto send_rsp; 454 goto send_rsp;
454 } 455 }
455 456
457 ctrl = amp_ctrl_lookup(mgr, rsp.remote_id);
458 if (!ctrl) {
459 ctrl = amp_ctrl_add(mgr);
460 if (ctrl) {
461 amp_ctrl_get(ctrl);
462 } else {
463 rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
464 goto send_rsp;
465 }
466 }
467
468 if (ctrl) {
469 u8 *assoc, assoc_len = le16_to_cpu(hdr->len) - sizeof(*req);
470
471 ctrl->id = rsp.remote_id;
472
473 assoc = kzalloc(assoc_len, GFP_KERNEL);
474 if (!assoc) {
475 amp_ctrl_put(ctrl);
476 return -ENOMEM;
477 }
478
479 memcpy(assoc, req->amp_assoc, assoc_len);
480 ctrl->assoc = assoc;
481 ctrl->assoc_len = assoc_len;
482 ctrl->assoc_rem_len = assoc_len;
483 ctrl->assoc_len_so_far = 0;
484
485 amp_ctrl_put(ctrl);
486 }
487
456 hcon = phylink_add(hdev, mgr, req->local_id); 488 hcon = phylink_add(hdev, mgr, req->local_id);
457 if (hcon) { 489 if (hcon) {
458 amp_accept_phylink(hdev, mgr, hcon); 490 amp_accept_phylink(hdev, mgr, hcon);
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 845e43073c40..5dab2d1c7c82 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -19,7 +19,7 @@
19#include <crypto/hash.h> 19#include <crypto/hash.h>
20 20
21/* Remote AMP Controllers interface */ 21/* Remote AMP Controllers interface */
22static void amp_ctrl_get(struct amp_ctrl *ctrl) 22void amp_ctrl_get(struct amp_ctrl *ctrl)
23{ 23{
24 BT_DBG("ctrl %p orig refcnt %d", ctrl, 24 BT_DBG("ctrl %p orig refcnt %d", ctrl,
25 atomic_read(&ctrl->kref.refcount)); 25 atomic_read(&ctrl->kref.refcount));
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d702ba1c171c..7e716698fe64 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1729,6 +1729,22 @@ static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
1729 amp_write_remote_assoc(hdev, cp->phy_handle); 1729 amp_write_remote_assoc(hdev, cp->phy_handle);
1730} 1730}
1731 1731
1732static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
1733{
1734 struct hci_cp_accept_phy_link *cp;
1735
1736 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1737
1738 if (status)
1739 return;
1740
1741 cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
1742 if (!cp)
1743 return;
1744
1745 amp_write_remote_assoc(hdev, cp->phy_handle);
1746}
1747
1732static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1748static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1733{ 1749{
1734 __u8 status = *((__u8 *) skb->data); 1750 __u8 status = *((__u8 *) skb->data);
@@ -2551,6 +2567,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2551 hci_cs_create_phylink(hdev, ev->status); 2567 hci_cs_create_phylink(hdev, ev->status);
2552 break; 2568 break;
2553 2569
2570 case HCI_OP_ACCEPT_PHY_LINK:
2571 hci_cs_accept_phylink(hdev, ev->status);
2572 break;
2573
2554 default: 2574 default:
2555 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2575 BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
2556 break; 2576 break;