aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/a2mp.c
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-09-27 10:26:09 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-09-27 16:10:32 -0400
commit903e45411099ae8292f5ce637ad0c72f6fef61db (patch)
tree7e04801dc8623c17c415d1c14221682867be6389 /net/bluetooth/a2mp.c
parent8e2a0d92c56ec6955526a8b60838c9b00f70540d (diff)
Bluetooth: AMP: Use HCI cmd to Read Loc AMP Assoc
When receiving A2MP Get AMP Assoc Request execute Read Local AMP Assoc HCI command to AMP controller. If the AMP Assoc data is larger than it can fit to HCI event only fragment is read. When all fragments are read send A2MP Get AMP Assoc Response. 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.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 0e97b3b42ab1..71400612843d 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -16,6 +16,7 @@
16#include <net/bluetooth/hci_core.h> 16#include <net/bluetooth/hci_core.h>
17#include <net/bluetooth/l2cap.h> 17#include <net/bluetooth/l2cap.h>
18#include <net/bluetooth/a2mp.h> 18#include <net/bluetooth/a2mp.h>
19#include <net/bluetooth/amp.h>
19 20
20/* Global AMP Manager list */ 21/* Global AMP Manager list */
21LIST_HEAD(amp_mgr_list); 22LIST_HEAD(amp_mgr_list);
@@ -218,26 +219,37 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
218{ 219{
219 struct a2mp_amp_assoc_req *req = (void *) skb->data; 220 struct a2mp_amp_assoc_req *req = (void *) skb->data;
220 struct hci_dev *hdev; 221 struct hci_dev *hdev;
222 struct amp_mgr *tmp;
221 223
222 if (le16_to_cpu(hdr->len) < sizeof(*req)) 224 if (le16_to_cpu(hdr->len) < sizeof(*req))
223 return -EINVAL; 225 return -EINVAL;
224 226
225 BT_DBG("id %d", req->id); 227 BT_DBG("id %d", req->id);
226 228
229 /* Make sure that other request is not processed */
230 tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
231
227 hdev = hci_dev_get(req->id); 232 hdev = hci_dev_get(req->id);
228 if (!hdev || hdev->amp_type == HCI_BREDR) { 233 if (!hdev || hdev->amp_type == HCI_BREDR || tmp) {
229 struct a2mp_amp_assoc_rsp rsp; 234 struct a2mp_amp_assoc_rsp rsp;
230 rsp.id = req->id; 235 rsp.id = req->id;
231 rsp.status = A2MP_STATUS_INVALID_CTRL_ID; 236
237 if (tmp) {
238 rsp.status = A2MP_STATUS_COLLISION_OCCURED;
239 amp_mgr_put(tmp);
240 } else {
241 rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
242 }
232 243
233 a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp), 244 a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp),
234 &rsp); 245 &rsp);
235 goto clean; 246
247 goto done;
236 } 248 }
237 249
238 /* Placeholder for HCI Read AMP Assoc */ 250 amp_read_loc_assoc(hdev, mgr);
239 251
240clean: 252done:
241 if (hdev) 253 if (hdev)
242 hci_dev_put(hdev); 254 hci_dev_put(hdev);
243 255
@@ -624,3 +636,37 @@ void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
624 a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp); 636 a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
625 amp_mgr_put(mgr); 637 amp_mgr_put(mgr);
626} 638}
639
640void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
641{
642 struct amp_mgr *mgr;
643 struct amp_assoc *loc_assoc = &hdev->loc_assoc;
644 struct a2mp_amp_assoc_rsp *rsp;
645 size_t len;
646
647 mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
648 if (!mgr)
649 return;
650
651 BT_DBG("%s mgr %p", hdev->name, mgr);
652
653 len = sizeof(struct a2mp_amp_assoc_rsp) + loc_assoc->len;
654 rsp = kzalloc(len, GFP_KERNEL);
655 if (!rsp) {
656 amp_mgr_put(mgr);
657 return;
658 }
659
660 rsp->id = hdev->id;
661
662 if (status) {
663 rsp->status = A2MP_STATUS_INVALID_CTRL_ID;
664 } else {
665 rsp->status = A2MP_STATUS_SUCCESS;
666 memcpy(rsp->amp_assoc, loc_assoc->data, loc_assoc->len);
667 }
668
669 a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, mgr->ident, len, rsp);
670 amp_mgr_put(mgr);
671 kfree(rsp);
672}