aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/a2mp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/a2mp.c')
-rw-r--r--net/bluetooth/a2mp.c72
1 files changed, 41 insertions, 31 deletions
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 17f33a62f6db..efcd108822c4 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -15,8 +15,9 @@
15#include <net/bluetooth/bluetooth.h> 15#include <net/bluetooth/bluetooth.h>
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
19#include <net/bluetooth/amp.h> 19#include "a2mp.h"
20#include "amp.h"
20 21
21/* Global AMP Manager list */ 22/* Global AMP Manager list */
22LIST_HEAD(amp_mgr_list); 23LIST_HEAD(amp_mgr_list);
@@ -75,33 +76,26 @@ u8 __next_ident(struct amp_mgr *mgr)
75 return mgr->ident; 76 return mgr->ident;
76} 77}
77 78
78static inline void __a2mp_cl_bredr(struct a2mp_cl *cl)
79{
80 cl->id = 0;
81 cl->type = 0;
82 cl->status = 1;
83}
84
85/* hci_dev_list shall be locked */ 79/* hci_dev_list shall be locked */
86static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl, u8 num_ctrl) 80static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl)
87{ 81{
88 int i = 0;
89 struct hci_dev *hdev; 82 struct hci_dev *hdev;
83 int i = 1;
90 84
91 __a2mp_cl_bredr(cl); 85 cl[0].id = AMP_ID_BREDR;
86 cl[0].type = AMP_TYPE_BREDR;
87 cl[0].status = AMP_STATUS_BLUETOOTH_ONLY;
92 88
93 list_for_each_entry(hdev, &hci_dev_list, list) { 89 list_for_each_entry(hdev, &hci_dev_list, list) {
94 /* Iterate through AMP controllers */ 90 if (hdev->dev_type == HCI_AMP) {
95 if (hdev->id == HCI_BREDR_ID) 91 cl[i].id = hdev->id;
96 continue; 92 cl[i].type = hdev->amp_type;
97 93 if (test_bit(HCI_UP, &hdev->flags))
98 /* Starting from second entry */ 94 cl[i].status = hdev->amp_status;
99 if (++i >= num_ctrl) 95 else
100 return; 96 cl[i].status = AMP_STATUS_POWERED_DOWN;
101 97 i++;
102 cl[i].id = hdev->id; 98 }
103 cl[i].type = hdev->amp_type;
104 cl[i].status = hdev->amp_status;
105 } 99 }
106} 100}
107 101
@@ -129,6 +123,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
129 struct a2mp_discov_rsp *rsp; 123 struct a2mp_discov_rsp *rsp;
130 u16 ext_feat; 124 u16 ext_feat;
131 u8 num_ctrl; 125 u8 num_ctrl;
126 struct hci_dev *hdev;
132 127
133 if (len < sizeof(*req)) 128 if (len < sizeof(*req))
134 return -EINVAL; 129 return -EINVAL;
@@ -152,7 +147,14 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
152 147
153 read_lock(&hci_dev_list_lock); 148 read_lock(&hci_dev_list_lock);
154 149
155 num_ctrl = __hci_num_ctrl(); 150 /* at minimum the BR/EDR needs to be listed */
151 num_ctrl = 1;
152
153 list_for_each_entry(hdev, &hci_dev_list, list) {
154 if (hdev->dev_type == HCI_AMP)
155 num_ctrl++;
156 }
157
156 len = num_ctrl * sizeof(struct a2mp_cl) + sizeof(*rsp); 158 len = num_ctrl * sizeof(struct a2mp_cl) + sizeof(*rsp);
157 rsp = kmalloc(len, GFP_ATOMIC); 159 rsp = kmalloc(len, GFP_ATOMIC);
158 if (!rsp) { 160 if (!rsp) {
@@ -163,7 +165,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
163 rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); 165 rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
164 rsp->ext_feat = 0; 166 rsp->ext_feat = 0;
165 167
166 __a2mp_add_cl(mgr, rsp->cl, num_ctrl); 168 __a2mp_add_cl(mgr, rsp->cl);
167 169
168 read_unlock(&hci_dev_list_lock); 170 read_unlock(&hci_dev_list_lock);
169 171
@@ -208,7 +210,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
208 BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type, 210 BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type,
209 cl->status); 211 cl->status);
210 212
211 if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) { 213 if (cl->id != AMP_ID_BREDR && cl->type != AMP_TYPE_BREDR) {
212 struct a2mp_info_req req; 214 struct a2mp_info_req req;
213 215
214 found = true; 216 found = true;
@@ -344,7 +346,7 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
344 tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC); 346 tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
345 347
346 hdev = hci_dev_get(req->id); 348 hdev = hci_dev_get(req->id);
347 if (!hdev || hdev->amp_type == HCI_BREDR || tmp) { 349 if (!hdev || hdev->amp_type == AMP_TYPE_BREDR || tmp) {
348 struct a2mp_amp_assoc_rsp rsp; 350 struct a2mp_amp_assoc_rsp rsp;
349 rsp.id = req->id; 351 rsp.id = req->id;
350 352
@@ -451,7 +453,7 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
451 rsp.remote_id = req->local_id; 453 rsp.remote_id = req->local_id;
452 454
453 hdev = hci_dev_get(req->remote_id); 455 hdev = hci_dev_get(req->remote_id);
454 if (!hdev || hdev->amp_type != HCI_AMP) { 456 if (!hdev || hdev->amp_type == AMP_TYPE_BREDR) {
455 rsp.status = A2MP_STATUS_INVALID_CTRL_ID; 457 rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
456 goto send_rsp; 458 goto send_rsp;
457 } 459 }
@@ -535,7 +537,8 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
535 goto send_rsp; 537 goto send_rsp;
536 } 538 }
537 539
538 hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, mgr->l2cap_conn->dst); 540 hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
541 &mgr->l2cap_conn->hcon->dst);
539 if (!hcon) { 542 if (!hcon) {
540 BT_ERR("No phys link exist"); 543 BT_ERR("No phys link exist");
541 rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS; 544 rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS;
@@ -669,7 +672,8 @@ static void a2mp_chan_close_cb(struct l2cap_chan *chan)
669 l2cap_chan_put(chan); 672 l2cap_chan_put(chan);
670} 673}
671 674
672static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) 675static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state,
676 int err)
673{ 677{
674 struct amp_mgr *mgr = chan->data; 678 struct amp_mgr *mgr = chan->data;
675 679
@@ -706,6 +710,9 @@ static struct l2cap_ops a2mp_chan_ops = {
706 .teardown = l2cap_chan_no_teardown, 710 .teardown = l2cap_chan_no_teardown,
707 .ready = l2cap_chan_no_ready, 711 .ready = l2cap_chan_no_ready,
708 .defer = l2cap_chan_no_defer, 712 .defer = l2cap_chan_no_defer,
713 .resume = l2cap_chan_no_resume,
714 .set_shutdown = l2cap_chan_no_set_shutdown,
715 .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
709}; 716};
710 717
711static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) 718static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
@@ -829,6 +836,9 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
829{ 836{
830 struct amp_mgr *mgr; 837 struct amp_mgr *mgr;
831 838
839 if (conn->hcon->type != ACL_LINK)
840 return NULL;
841
832 mgr = amp_mgr_create(conn, false); 842 mgr = amp_mgr_create(conn, false);
833 if (!mgr) { 843 if (!mgr) {
834 BT_ERR("Could not create AMP manager"); 844 BT_ERR("Could not create AMP manager");
@@ -871,7 +881,7 @@ void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
871 rsp.id = hdev->id; 881 rsp.id = hdev->id;
872 rsp.status = A2MP_STATUS_INVALID_CTRL_ID; 882 rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
873 883
874 if (hdev->amp_type != HCI_BREDR) { 884 if (hdev->amp_type != AMP_TYPE_BREDR) {
875 rsp.status = 0; 885 rsp.status = 0;
876 rsp.total_bw = cpu_to_le32(hdev->amp_total_bw); 886 rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
877 rsp.max_bw = cpu_to_le32(hdev->amp_max_bw); 887 rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);