aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r--net/bluetooth/l2cap_core.c63
1 files changed, 43 insertions, 20 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index bdffc4c207b5..2f0e165eef4d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4237,7 +4237,9 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
4237 u16 cmd_len, void *data) 4237 u16 cmd_len, void *data)
4238{ 4238{
4239 struct l2cap_create_chan_req *req = data; 4239 struct l2cap_create_chan_req *req = data;
4240 struct l2cap_create_chan_rsp rsp;
4240 struct l2cap_chan *chan; 4241 struct l2cap_chan *chan;
4242 struct hci_dev *hdev;
4241 u16 psm, scid; 4243 u16 psm, scid;
4242 4244
4243 if (cmd_len != sizeof(*req)) 4245 if (cmd_len != sizeof(*req))
@@ -4251,36 +4253,57 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
4251 4253
4252 BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); 4254 BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4253 4255
4254 if (req->amp_id) { 4256 /* For controller id 0 make BR/EDR connection */
4255 struct hci_dev *hdev; 4257 if (req->amp_id == HCI_BREDR_ID) {
4256 4258 l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
4257 /* Validate AMP controller id */ 4259 req->amp_id);
4258 hdev = hci_dev_get(req->amp_id); 4260 return 0;
4259 if (!hdev || hdev->dev_type != HCI_AMP || 4261 }
4260 !test_bit(HCI_UP, &hdev->flags)) {
4261 struct l2cap_create_chan_rsp rsp;
4262 4262
4263 rsp.dcid = 0; 4263 /* Validate AMP controller id */
4264 rsp.scid = cpu_to_le16(scid); 4264 hdev = hci_dev_get(req->amp_id);
4265 rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); 4265 if (!hdev)
4266 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 4266 goto error;
4267 4267
4268 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, 4268 if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
4269 sizeof(rsp), &rsp); 4269 hci_dev_put(hdev);
4270 goto error;
4271 }
4270 4272
4271 if (hdev) 4273 chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
4272 hci_dev_put(hdev); 4274 req->amp_id);
4275 if (chan) {
4276 struct amp_mgr *mgr = conn->hcon->amp_mgr;
4277 struct hci_conn *hs_hcon;
4273 4278
4274 return 0; 4279 hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, conn->dst);
4280 if (!hs_hcon) {
4281 hci_dev_put(hdev);
4282 return -EFAULT;
4275 } 4283 }
4276 4284
4277 hci_dev_put(hdev); 4285 BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
4286
4287 chan->local_amp_id = req->amp_id;
4288 mgr->bredr_chan = chan;
4289 chan->hs_hcon = hs_hcon;
4290 conn->mtu = hdev->block_mtu;
4278 } 4291 }
4279 4292
4280 chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, 4293 hci_dev_put(hdev);
4281 req->amp_id);
4282 4294
4283 return 0; 4295 return 0;
4296
4297error:
4298 rsp.dcid = 0;
4299 rsp.scid = cpu_to_le16(scid);
4300 rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
4301 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
4302
4303 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4304 sizeof(rsp), &rsp);
4305
4306 return -EFAULT;
4284} 4307}
4285 4308
4286static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) 4309static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)