Bluetooth: AMP: Use HCI cmd to Read AMP Info
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>
Thu, 27 Sep 2012 14:26:08 +0000 (17:26 +0300)
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>
Thu, 27 Sep 2012 20:10:18 +0000 (17:10 -0300)
When receiving A2MP Get Info Request execute Read Local AMP Info HCI
command to AMP controller with function to be executed upon receiving
command complete event. Function will handle A2MP Get Info Response.

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

index 316c1c80367608227357328c69607cf078b822c4..af594685112e64fe134c895da57cdc362b453f4b 100644 (file)
@@ -132,5 +132,7 @@ int amp_mgr_put(struct amp_mgr *mgr);
 struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
                                       struct sk_buff *skb);
 struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
 
 #endif /* __A2MP_H */
index 3f930608ecfa5290a3d4c1ccf1eede9b027d7a96..0e97b3b42ab113b4029efbe3695a5695f58c39e9 100644 (file)
@@ -41,8 +41,7 @@ static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
        return cmd;
 }
 
-static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
-                     void *data)
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
 {
        struct l2cap_chan *chan = mgr->a2mp_chan;
        struct a2mp_cmd *cmd;
@@ -185,7 +184,6 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
                            struct a2mp_cmd *hdr)
 {
        struct a2mp_info_req *req  = (void *) skb->data;
-       struct a2mp_info_rsp rsp;
        struct hci_dev *hdev;
 
        if (le16_to_cpu(hdr->len) < sizeof(*req))
@@ -193,23 +191,23 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
 
        BT_DBG("id %d", req->id);
 
-       rsp.id = req->id;
-       rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
-
        hdev = hci_dev_get(req->id);
-       if (hdev && hdev->amp_type != HCI_BREDR) {
-               rsp.status = 0;
-               rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
-               rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
-               rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
-               rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
-               rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+       if (!hdev) {
+               struct a2mp_info_rsp rsp;
+
+               rsp.id = req->id;
+               rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+               a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp),
+                         &rsp);
        }
 
-       if (hdev)
-               hci_dev_put(hdev);
+       if (hdev->dev_type != HCI_BREDR) {
+               mgr->state = READ_LOC_AMP_INFO;
+               hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
+       }
 
-       a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), &rsp);
+       hci_dev_put(hdev);
 
        skb_pull(skb, sizeof(*req));
        return 0;
@@ -599,3 +597,30 @@ struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
 
        return NULL;
 }
+
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
+{
+       struct amp_mgr *mgr;
+       struct a2mp_info_rsp rsp;
+
+       mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_INFO);
+       if (!mgr)
+               return;
+
+       BT_DBG("%s mgr %p", hdev->name, mgr);
+
+       rsp.id = hdev->id;
+       rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+       if (hdev->amp_type != HCI_BREDR) {
+               rsp.status = 0;
+               rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
+               rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
+               rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
+               rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
+               rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+       }
+
+       a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
+       amp_mgr_put(mgr);
+}
index 2022b43c7353ee98d7546d6c9e0ef67c43811d3f..eb45774165f4ff4bcecec416841eca8b241ff585 100644 (file)
@@ -30,6 +30,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/mgmt.h>
+#include <net/bluetooth/a2mp.h>
 
 /* Handle HCI Event packets */
 
@@ -846,7 +847,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
        BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
        if (rp->status)
-               return;
+               goto a2mp_rsp;
 
        hdev->amp_status = rp->amp_status;
        hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
@@ -860,6 +861,9 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
        hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
 
        hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
+
+a2mp_rsp:
+       a2mp_send_getinfo_rsp(hdev);
 }
 
 static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,