root/net/bluetooth/a2mp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __a2mp_build
  2. a2mp_send
  3. __next_ident
  4. amp_mgr_lookup_by_state
  5. __a2mp_add_cl
  6. a2mp_command_rej
  7. a2mp_discover_req
  8. a2mp_discover_rsp
  9. a2mp_change_notify
  10. read_local_amp_info_complete
  11. a2mp_getinfo_req
  12. a2mp_getinfo_rsp
  13. a2mp_getampassoc_req
  14. a2mp_getampassoc_rsp
  15. a2mp_createphyslink_req
  16. a2mp_discphyslink_req
  17. a2mp_cmd_rsp
  18. a2mp_chan_recv_cb
  19. a2mp_chan_close_cb
  20. a2mp_chan_state_change_cb
  21. a2mp_chan_alloc_skb_cb
  22. a2mp_chan_open
  23. amp_mgr_get
  24. amp_mgr_destroy
  25. amp_mgr_put
  26. amp_mgr_create
  27. a2mp_channel_create
  28. a2mp_send_getinfo_rsp
  29. a2mp_send_getampassoc_rsp
  30. a2mp_send_create_phy_link_req
  31. a2mp_send_create_phy_link_rsp
  32. a2mp_discover_amp

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3    Copyright (c) 2010,2011 Code Aurora Forum.  All rights reserved.
   4    Copyright (c) 2011,2012 Intel Corp.
   5 
   6 */
   7 
   8 #include <net/bluetooth/bluetooth.h>
   9 #include <net/bluetooth/hci_core.h>
  10 #include <net/bluetooth/l2cap.h>
  11 
  12 #include "hci_request.h"
  13 #include "a2mp.h"
  14 #include "amp.h"
  15 
  16 #define A2MP_FEAT_EXT   0x8000
  17 
  18 /* Global AMP Manager list */
  19 static LIST_HEAD(amp_mgr_list);
  20 static DEFINE_MUTEX(amp_mgr_list_lock);
  21 
  22 /* A2MP build & send command helper functions */
  23 static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
  24 {
  25         struct a2mp_cmd *cmd;
  26         int plen;
  27 
  28         plen = sizeof(*cmd) + len;
  29         cmd = kzalloc(plen, GFP_KERNEL);
  30         if (!cmd)
  31                 return NULL;
  32 
  33         cmd->code = code;
  34         cmd->ident = ident;
  35         cmd->len = cpu_to_le16(len);
  36 
  37         memcpy(cmd->data, data, len);
  38 
  39         return cmd;
  40 }
  41 
  42 static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
  43 {
  44         struct l2cap_chan *chan = mgr->a2mp_chan;
  45         struct a2mp_cmd *cmd;
  46         u16 total_len = len + sizeof(*cmd);
  47         struct kvec iv;
  48         struct msghdr msg;
  49 
  50         cmd = __a2mp_build(code, ident, len, data);
  51         if (!cmd)
  52                 return;
  53 
  54         iv.iov_base = cmd;
  55         iv.iov_len = total_len;
  56 
  57         memset(&msg, 0, sizeof(msg));
  58 
  59         iov_iter_kvec(&msg.msg_iter, WRITE, &iv, 1, total_len);
  60 
  61         l2cap_chan_send(chan, &msg, total_len);
  62 
  63         kfree(cmd);
  64 }
  65 
  66 static u8 __next_ident(struct amp_mgr *mgr)
  67 {
  68         if (++mgr->ident == 0)
  69                 mgr->ident = 1;
  70 
  71         return mgr->ident;
  72 }
  73 
  74 static struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
  75 {
  76         struct amp_mgr *mgr;
  77 
  78         mutex_lock(&amp_mgr_list_lock);
  79         list_for_each_entry(mgr, &amp_mgr_list, list) {
  80                 if (test_and_clear_bit(state, &mgr->state)) {
  81                         amp_mgr_get(mgr);
  82                         mutex_unlock(&amp_mgr_list_lock);
  83                         return mgr;
  84                 }
  85         }
  86         mutex_unlock(&amp_mgr_list_lock);
  87 
  88         return NULL;
  89 }
  90 
  91 /* hci_dev_list shall be locked */
  92 static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl)
  93 {
  94         struct hci_dev *hdev;
  95         int i = 1;
  96 
  97         cl[0].id = AMP_ID_BREDR;
  98         cl[0].type = AMP_TYPE_BREDR;
  99         cl[0].status = AMP_STATUS_BLUETOOTH_ONLY;
 100 
 101         list_for_each_entry(hdev, &hci_dev_list, list) {
 102                 if (hdev->dev_type == HCI_AMP) {
 103                         cl[i].id = hdev->id;
 104                         cl[i].type = hdev->amp_type;
 105                         if (test_bit(HCI_UP, &hdev->flags))
 106                                 cl[i].status = hdev->amp_status;
 107                         else
 108                                 cl[i].status = AMP_STATUS_POWERED_DOWN;
 109                         i++;
 110                 }
 111         }
 112 }
 113 
 114 /* Processing A2MP messages */
 115 static int a2mp_command_rej(struct amp_mgr *mgr, struct sk_buff *skb,
 116                             struct a2mp_cmd *hdr)
 117 {
 118         struct a2mp_cmd_rej *rej = (void *) skb->data;
 119 
 120         if (le16_to_cpu(hdr->len) < sizeof(*rej))
 121                 return -EINVAL;
 122 
 123         BT_DBG("ident %d reason %d", hdr->ident, le16_to_cpu(rej->reason));
 124 
 125         skb_pull(skb, sizeof(*rej));
 126 
 127         return 0;
 128 }
 129 
 130 static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
 131                              struct a2mp_cmd *hdr)
 132 {
 133         struct a2mp_discov_req *req = (void *) skb->data;
 134         u16 len = le16_to_cpu(hdr->len);
 135         struct a2mp_discov_rsp *rsp;
 136         u16 ext_feat;
 137         u8 num_ctrl;
 138         struct hci_dev *hdev;
 139 
 140         if (len < sizeof(*req))
 141                 return -EINVAL;
 142 
 143         skb_pull(skb, sizeof(*req));
 144 
 145         ext_feat = le16_to_cpu(req->ext_feat);
 146 
 147         BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(req->mtu), ext_feat);
 148 
 149         /* check that packet is not broken for now */
 150         while (ext_feat & A2MP_FEAT_EXT) {
 151                 if (len < sizeof(ext_feat))
 152                         return -EINVAL;
 153 
 154                 ext_feat = get_unaligned_le16(skb->data);
 155                 BT_DBG("efm 0x%4.4x", ext_feat);
 156                 len -= sizeof(ext_feat);
 157                 skb_pull(skb, sizeof(ext_feat));
 158         }
 159 
 160         read_lock(&hci_dev_list_lock);
 161 
 162         /* at minimum the BR/EDR needs to be listed */
 163         num_ctrl = 1;
 164 
 165         list_for_each_entry(hdev, &hci_dev_list, list) {
 166                 if (hdev->dev_type == HCI_AMP)
 167                         num_ctrl++;
 168         }
 169 
 170         len = struct_size(rsp, cl, num_ctrl);
 171         rsp = kmalloc(len, GFP_ATOMIC);
 172         if (!rsp) {
 173                 read_unlock(&hci_dev_list_lock);
 174                 return -ENOMEM;
 175         }
 176 
 177         rsp->mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
 178         rsp->ext_feat = 0;
 179 
 180         __a2mp_add_cl(mgr, rsp->cl);
 181 
 182         read_unlock(&hci_dev_list_lock);
 183 
 184         a2mp_send(mgr, A2MP_DISCOVER_RSP, hdr->ident, len, rsp);
 185 
 186         kfree(rsp);
 187         return 0;
 188 }
 189 
 190 static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
 191                              struct a2mp_cmd *hdr)
 192 {
 193         struct a2mp_discov_rsp *rsp = (void *) skb->data;
 194         u16 len = le16_to_cpu(hdr->len);
 195         struct a2mp_cl *cl;
 196         u16 ext_feat;
 197         bool found = false;
 198 
 199         if (len < sizeof(*rsp))
 200                 return -EINVAL;
 201 
 202         len -= sizeof(*rsp);
 203         skb_pull(skb, sizeof(*rsp));
 204 
 205         ext_feat = le16_to_cpu(rsp->ext_feat);
 206 
 207         BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(rsp->mtu), ext_feat);
 208 
 209         /* check that packet is not broken for now */
 210         while (ext_feat & A2MP_FEAT_EXT) {
 211                 if (len < sizeof(ext_feat))
 212                         return -EINVAL;
 213 
 214                 ext_feat = get_unaligned_le16(skb->data);
 215                 BT_DBG("efm 0x%4.4x", ext_feat);
 216                 len -= sizeof(ext_feat);
 217                 skb_pull(skb, sizeof(ext_feat));
 218         }
 219 
 220         cl = (void *) skb->data;
 221         while (len >= sizeof(*cl)) {
 222                 BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type,
 223                        cl->status);
 224 
 225                 if (cl->id != AMP_ID_BREDR && cl->type != AMP_TYPE_BREDR) {
 226                         struct a2mp_info_req req;
 227 
 228                         found = true;
 229                         req.id = cl->id;
 230                         a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
 231                                   sizeof(req), &req);
 232                 }
 233 
 234                 len -= sizeof(*cl);
 235                 cl = skb_pull(skb, sizeof(*cl));
 236         }
 237 
 238         /* Fall back to L2CAP init sequence */
 239         if (!found) {
 240                 struct l2cap_conn *conn = mgr->l2cap_conn;
 241                 struct l2cap_chan *chan;
 242 
 243                 mutex_lock(&conn->chan_lock);
 244 
 245                 list_for_each_entry(chan, &conn->chan_l, list) {
 246 
 247                         BT_DBG("chan %p state %s", chan,
 248                                state_to_string(chan->state));
 249 
 250                         if (chan->scid == L2CAP_CID_A2MP)
 251                                 continue;
 252 
 253                         l2cap_chan_lock(chan);
 254 
 255                         if (chan->state == BT_CONNECT)
 256                                 l2cap_send_conn_req(chan);
 257 
 258                         l2cap_chan_unlock(chan);
 259                 }
 260 
 261                 mutex_unlock(&conn->chan_lock);
 262         }
 263 
 264         return 0;
 265 }
 266 
 267 static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb,
 268                               struct a2mp_cmd *hdr)
 269 {
 270         struct a2mp_cl *cl = (void *) skb->data;
 271 
 272         while (skb->len >= sizeof(*cl)) {
 273                 BT_DBG("Controller id %d type %d status %d", cl->id, cl->type,
 274                        cl->status);
 275                 cl = skb_pull(skb, sizeof(*cl));
 276         }
 277 
 278         /* TODO send A2MP_CHANGE_RSP */
 279 
 280         return 0;
 281 }
 282 
 283 static void read_local_amp_info_complete(struct hci_dev *hdev, u8 status,
 284                                          u16 opcode)
 285 {
 286         BT_DBG("%s status 0x%2.2x", hdev->name, status);
 287 
 288         a2mp_send_getinfo_rsp(hdev);
 289 }
 290 
 291 static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
 292                             struct a2mp_cmd *hdr)
 293 {
 294         struct a2mp_info_req *req  = (void *) skb->data;
 295         struct hci_dev *hdev;
 296         struct hci_request hreq;
 297         int err = 0;
 298 
 299         if (le16_to_cpu(hdr->len) < sizeof(*req))
 300                 return -EINVAL;
 301 
 302         BT_DBG("id %d", req->id);
 303 
 304         hdev = hci_dev_get(req->id);
 305         if (!hdev || hdev->dev_type != HCI_AMP) {
 306                 struct a2mp_info_rsp rsp;
 307 
 308                 rsp.id = req->id;
 309                 rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
 310 
 311                 a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp),
 312                           &rsp);
 313 
 314                 goto done;
 315         }
 316 
 317         set_bit(READ_LOC_AMP_INFO, &mgr->state);
 318         hci_req_init(&hreq, hdev);
 319         hci_req_add(&hreq, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
 320         err = hci_req_run(&hreq, read_local_amp_info_complete);
 321         if (err < 0)
 322                 a2mp_send_getinfo_rsp(hdev);
 323 
 324 done:
 325         if (hdev)
 326                 hci_dev_put(hdev);
 327 
 328         skb_pull(skb, sizeof(*req));
 329         return 0;
 330 }
 331 
 332 static int a2mp_getinfo_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
 333                             struct a2mp_cmd *hdr)
 334 {
 335         struct a2mp_info_rsp *rsp = (struct a2mp_info_rsp *) skb->data;
 336         struct a2mp_amp_assoc_req req;
 337         struct amp_ctrl *ctrl;
 338 
 339         if (le16_to_cpu(hdr->len) < sizeof(*rsp))
 340                 return -EINVAL;
 341 
 342         BT_DBG("id %d status 0x%2.2x", rsp->id, rsp->status);
 343 
 344         if (rsp->status)
 345                 return -EINVAL;
 346 
 347         ctrl = amp_ctrl_add(mgr, rsp->id);
 348         if (!ctrl)
 349                 return -ENOMEM;
 350 
 351         req.id = rsp->id;
 352         a2mp_send(mgr, A2MP_GETAMPASSOC_REQ, __next_ident(mgr), sizeof(req),
 353                   &req);
 354 
 355         skb_pull(skb, sizeof(*rsp));
 356         return 0;
 357 }
 358 
 359 static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
 360                                 struct a2mp_cmd *hdr)
 361 {
 362         struct a2mp_amp_assoc_req *req = (void *) skb->data;
 363         struct hci_dev *hdev;
 364         struct amp_mgr *tmp;
 365 
 366         if (le16_to_cpu(hdr->len) < sizeof(*req))
 367                 return -EINVAL;
 368 
 369         BT_DBG("id %d", req->id);
 370 
 371         /* Make sure that other request is not processed */
 372         tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
 373 
 374         hdev = hci_dev_get(req->id);
 375         if (!hdev || hdev->amp_type == AMP_TYPE_BREDR || tmp) {
 376                 struct a2mp_amp_assoc_rsp rsp;
 377                 rsp.id = req->id;
 378 
 379                 if (tmp) {
 380                         rsp.status = A2MP_STATUS_COLLISION_OCCURED;
 381                         amp_mgr_put(tmp);
 382                 } else {
 383                         rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
 384                 }
 385 
 386                 a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp),
 387                           &rsp);
 388 
 389                 goto done;
 390         }
 391 
 392         amp_read_loc_assoc(hdev, mgr);
 393 
 394 done:
 395         if (hdev)
 396                 hci_dev_put(hdev);
 397 
 398         skb_pull(skb, sizeof(*req));
 399         return 0;
 400 }
 401 
 402 static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
 403                                 struct a2mp_cmd *hdr)
 404 {
 405         struct a2mp_amp_assoc_rsp *rsp = (void *) skb->data;
 406         u16 len = le16_to_cpu(hdr->len);
 407         struct hci_dev *hdev;
 408         struct amp_ctrl *ctrl;
 409         struct hci_conn *hcon;
 410         size_t assoc_len;
 411 
 412         if (len < sizeof(*rsp))
 413                 return -EINVAL;
 414 
 415         assoc_len = len - sizeof(*rsp);
 416 
 417         BT_DBG("id %d status 0x%2.2x assoc len %zu", rsp->id, rsp->status,
 418                assoc_len);
 419 
 420         if (rsp->status)
 421                 return -EINVAL;
 422 
 423         /* Save remote ASSOC data */
 424         ctrl = amp_ctrl_lookup(mgr, rsp->id);
 425         if (ctrl) {
 426                 u8 *assoc;
 427 
 428                 assoc = kmemdup(rsp->amp_assoc, assoc_len, GFP_KERNEL);
 429                 if (!assoc) {
 430                         amp_ctrl_put(ctrl);
 431                         return -ENOMEM;
 432                 }
 433 
 434                 ctrl->assoc = assoc;
 435                 ctrl->assoc_len = assoc_len;
 436                 ctrl->assoc_rem_len = assoc_len;
 437                 ctrl->assoc_len_so_far = 0;
 438 
 439                 amp_ctrl_put(ctrl);
 440         }
 441 
 442         /* Create Phys Link */
 443         hdev = hci_dev_get(rsp->id);
 444         if (!hdev)
 445                 return -EINVAL;
 446 
 447         hcon = phylink_add(hdev, mgr, rsp->id, true);
 448         if (!hcon)
 449                 goto done;
 450 
 451         BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id);
 452 
 453         mgr->bredr_chan->remote_amp_id = rsp->id;
 454 
 455         amp_create_phylink(hdev, mgr, hcon);
 456 
 457 done:
 458         hci_dev_put(hdev);
 459         skb_pull(skb, len);
 460         return 0;
 461 }
 462 
 463 static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
 464                                    struct a2mp_cmd *hdr)
 465 {
 466         struct a2mp_physlink_req *req = (void *) skb->data;
 467 
 468         struct a2mp_physlink_rsp rsp;
 469         struct hci_dev *hdev;
 470         struct hci_conn *hcon;
 471         struct amp_ctrl *ctrl;
 472 
 473         if (le16_to_cpu(hdr->len) < sizeof(*req))
 474                 return -EINVAL;
 475 
 476         BT_DBG("local_id %d, remote_id %d", req->local_id, req->remote_id);
 477 
 478         rsp.local_id = req->remote_id;
 479         rsp.remote_id = req->local_id;
 480 
 481         hdev = hci_dev_get(req->remote_id);
 482         if (!hdev || hdev->amp_type == AMP_TYPE_BREDR) {
 483                 rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
 484                 goto send_rsp;
 485         }
 486 
 487         ctrl = amp_ctrl_lookup(mgr, rsp.remote_id);
 488         if (!ctrl) {
 489                 ctrl = amp_ctrl_add(mgr, rsp.remote_id);
 490                 if (ctrl) {
 491                         amp_ctrl_get(ctrl);
 492                 } else {
 493                         rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
 494                         goto send_rsp;
 495                 }
 496         }
 497 
 498         if (ctrl) {
 499                 size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req);
 500                 u8 *assoc;
 501 
 502                 assoc = kmemdup(req->amp_assoc, assoc_len, GFP_KERNEL);
 503                 if (!assoc) {
 504                         amp_ctrl_put(ctrl);
 505                         return -ENOMEM;
 506                 }
 507 
 508                 ctrl->assoc = assoc;
 509                 ctrl->assoc_len = assoc_len;
 510                 ctrl->assoc_rem_len = assoc_len;
 511                 ctrl->assoc_len_so_far = 0;
 512 
 513                 amp_ctrl_put(ctrl);
 514         }
 515 
 516         hcon = phylink_add(hdev, mgr, req->local_id, false);
 517         if (hcon) {
 518                 amp_accept_phylink(hdev, mgr, hcon);
 519                 rsp.status = A2MP_STATUS_SUCCESS;
 520         } else {
 521                 rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
 522         }
 523 
 524 send_rsp:
 525         if (hdev)
 526                 hci_dev_put(hdev);
 527 
 528         /* Reply error now and success after HCI Write Remote AMP Assoc
 529            command complete with success status
 530          */
 531         if (rsp.status != A2MP_STATUS_SUCCESS) {
 532                 a2mp_send(mgr, A2MP_CREATEPHYSLINK_RSP, hdr->ident,
 533                           sizeof(rsp), &rsp);
 534         } else {
 535                 set_bit(WRITE_REMOTE_AMP_ASSOC, &mgr->state);
 536                 mgr->ident = hdr->ident;
 537         }
 538 
 539         skb_pull(skb, le16_to_cpu(hdr->len));
 540         return 0;
 541 }
 542 
 543 static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
 544                                  struct a2mp_cmd *hdr)
 545 {
 546         struct a2mp_physlink_req *req = (void *) skb->data;
 547         struct a2mp_physlink_rsp rsp;
 548         struct hci_dev *hdev;
 549         struct hci_conn *hcon;
 550 
 551         if (le16_to_cpu(hdr->len) < sizeof(*req))
 552                 return -EINVAL;
 553 
 554         BT_DBG("local_id %d remote_id %d", req->local_id, req->remote_id);
 555 
 556         rsp.local_id = req->remote_id;
 557         rsp.remote_id = req->local_id;
 558         rsp.status = A2MP_STATUS_SUCCESS;
 559 
 560         hdev = hci_dev_get(req->remote_id);
 561         if (!hdev) {
 562                 rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
 563                 goto send_rsp;
 564         }
 565 
 566         hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
 567                                        &mgr->l2cap_conn->hcon->dst);
 568         if (!hcon) {
 569                 bt_dev_err(hdev, "no phys link exist");
 570                 rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS;
 571                 goto clean;
 572         }
 573 
 574         /* TODO Disconnect Phys Link here */
 575 
 576 clean:
 577         hci_dev_put(hdev);
 578 
 579 send_rsp:
 580         a2mp_send(mgr, A2MP_DISCONNPHYSLINK_RSP, hdr->ident, sizeof(rsp), &rsp);
 581 
 582         skb_pull(skb, sizeof(*req));
 583         return 0;
 584 }
 585 
 586 static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
 587                                struct a2mp_cmd *hdr)
 588 {
 589         BT_DBG("ident %d code 0x%2.2x", hdr->ident, hdr->code);
 590 
 591         skb_pull(skb, le16_to_cpu(hdr->len));
 592         return 0;
 593 }
 594 
 595 /* Handle A2MP signalling */
 596 static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
 597 {
 598         struct a2mp_cmd *hdr;
 599         struct amp_mgr *mgr = chan->data;
 600         int err = 0;
 601 
 602         amp_mgr_get(mgr);
 603 
 604         while (skb->len >= sizeof(*hdr)) {
 605                 u16 len;
 606 
 607                 hdr = (void *) skb->data;
 608                 len = le16_to_cpu(hdr->len);
 609 
 610                 BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len);
 611 
 612                 skb_pull(skb, sizeof(*hdr));
 613 
 614                 if (len > skb->len || !hdr->ident) {
 615                         err = -EINVAL;
 616                         break;
 617                 }
 618 
 619                 mgr->ident = hdr->ident;
 620 
 621                 switch (hdr->code) {
 622                 case A2MP_COMMAND_REJ:
 623                         a2mp_command_rej(mgr, skb, hdr);
 624                         break;
 625 
 626                 case A2MP_DISCOVER_REQ:
 627                         err = a2mp_discover_req(mgr, skb, hdr);
 628                         break;
 629 
 630                 case A2MP_CHANGE_NOTIFY:
 631                         err = a2mp_change_notify(mgr, skb, hdr);
 632                         break;
 633 
 634                 case A2MP_GETINFO_REQ:
 635                         err = a2mp_getinfo_req(mgr, skb, hdr);
 636                         break;
 637 
 638                 case A2MP_GETAMPASSOC_REQ:
 639                         err = a2mp_getampassoc_req(mgr, skb, hdr);
 640                         break;
 641 
 642                 case A2MP_CREATEPHYSLINK_REQ:
 643                         err = a2mp_createphyslink_req(mgr, skb, hdr);
 644                         break;
 645 
 646                 case A2MP_DISCONNPHYSLINK_REQ:
 647                         err = a2mp_discphyslink_req(mgr, skb, hdr);
 648                         break;
 649 
 650                 case A2MP_DISCOVER_RSP:
 651                         err = a2mp_discover_rsp(mgr, skb, hdr);
 652                         break;
 653 
 654                 case A2MP_GETINFO_RSP:
 655                         err = a2mp_getinfo_rsp(mgr, skb, hdr);
 656                         break;
 657 
 658                 case A2MP_GETAMPASSOC_RSP:
 659                         err = a2mp_getampassoc_rsp(mgr, skb, hdr);
 660                         break;
 661 
 662                 case A2MP_CHANGE_RSP:
 663                 case A2MP_CREATEPHYSLINK_RSP:
 664                 case A2MP_DISCONNPHYSLINK_RSP:
 665                         err = a2mp_cmd_rsp(mgr, skb, hdr);
 666                         break;
 667 
 668                 default:
 669                         BT_ERR("Unknown A2MP sig cmd 0x%2.2x", hdr->code);
 670                         err = -EINVAL;
 671                         break;
 672                 }
 673         }
 674 
 675         if (err) {
 676                 struct a2mp_cmd_rej rej;
 677 
 678                 rej.reason = cpu_to_le16(0);
 679                 hdr = (void *) skb->data;
 680 
 681                 BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err);
 682 
 683                 a2mp_send(mgr, A2MP_COMMAND_REJ, hdr->ident, sizeof(rej),
 684                           &rej);
 685         }
 686 
 687         /* Always free skb and return success error code to prevent
 688            from sending L2CAP Disconnect over A2MP channel */
 689         kfree_skb(skb);
 690 
 691         amp_mgr_put(mgr);
 692 
 693         return 0;
 694 }
 695 
 696 static void a2mp_chan_close_cb(struct l2cap_chan *chan)
 697 {
 698         l2cap_chan_put(chan);
 699 }
 700 
 701 static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state,
 702                                       int err)
 703 {
 704         struct amp_mgr *mgr = chan->data;
 705 
 706         if (!mgr)
 707                 return;
 708 
 709         BT_DBG("chan %p state %s", chan, state_to_string(state));
 710 
 711         chan->state = state;
 712 
 713         switch (state) {
 714         case BT_CLOSED:
 715                 if (mgr)
 716                         amp_mgr_put(mgr);
 717                 break;
 718         }
 719 }
 720 
 721 static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan,
 722                                               unsigned long hdr_len,
 723                                               unsigned long len, int nb)
 724 {
 725         struct sk_buff *skb;
 726 
 727         skb = bt_skb_alloc(hdr_len + len, GFP_KERNEL);
 728         if (!skb)
 729                 return ERR_PTR(-ENOMEM);
 730 
 731         return skb;
 732 }
 733 
 734 static const struct l2cap_ops a2mp_chan_ops = {
 735         .name = "L2CAP A2MP channel",
 736         .recv = a2mp_chan_recv_cb,
 737         .close = a2mp_chan_close_cb,
 738         .state_change = a2mp_chan_state_change_cb,
 739         .alloc_skb = a2mp_chan_alloc_skb_cb,
 740 
 741         /* Not implemented for A2MP */
 742         .new_connection = l2cap_chan_no_new_connection,
 743         .teardown = l2cap_chan_no_teardown,
 744         .ready = l2cap_chan_no_ready,
 745         .defer = l2cap_chan_no_defer,
 746         .resume = l2cap_chan_no_resume,
 747         .set_shutdown = l2cap_chan_no_set_shutdown,
 748         .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
 749 };
 750 
 751 static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
 752 {
 753         struct l2cap_chan *chan;
 754         int err;
 755 
 756         chan = l2cap_chan_create();
 757         if (!chan)
 758                 return NULL;
 759 
 760         BT_DBG("chan %p", chan);
 761 
 762         chan->chan_type = L2CAP_CHAN_FIXED;
 763         chan->scid = L2CAP_CID_A2MP;
 764         chan->dcid = L2CAP_CID_A2MP;
 765         chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
 766         chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
 767         chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
 768 
 769         chan->ops = &a2mp_chan_ops;
 770 
 771         l2cap_chan_set_defaults(chan);
 772         chan->remote_max_tx = chan->max_tx;
 773         chan->remote_tx_win = chan->tx_win;
 774 
 775         chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
 776         chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
 777 
 778         skb_queue_head_init(&chan->tx_q);
 779 
 780         chan->mode = L2CAP_MODE_ERTM;
 781 
 782         err = l2cap_ertm_init(chan);
 783         if (err < 0) {
 784                 l2cap_chan_del(chan, 0);
 785                 return NULL;
 786         }
 787 
 788         chan->conf_state = 0;
 789 
 790         if (locked)
 791                 __l2cap_chan_add(conn, chan);
 792         else
 793                 l2cap_chan_add(conn, chan);
 794 
 795         chan->remote_mps = chan->omtu;
 796         chan->mps = chan->omtu;
 797 
 798         chan->state = BT_CONNECTED;
 799 
 800         return chan;
 801 }
 802 
 803 /* AMP Manager functions */
 804 struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr)
 805 {
 806         BT_DBG("mgr %p orig refcnt %d", mgr, kref_read(&mgr->kref));
 807 
 808         kref_get(&mgr->kref);
 809 
 810         return mgr;
 811 }
 812 
 813 static void amp_mgr_destroy(struct kref *kref)
 814 {
 815         struct amp_mgr *mgr = container_of(kref, struct amp_mgr, kref);
 816 
 817         BT_DBG("mgr %p", mgr);
 818 
 819         mutex_lock(&amp_mgr_list_lock);
 820         list_del(&mgr->list);
 821         mutex_unlock(&amp_mgr_list_lock);
 822 
 823         amp_ctrl_list_flush(mgr);
 824         kfree(mgr);
 825 }
 826 
 827 int amp_mgr_put(struct amp_mgr *mgr)
 828 {
 829         BT_DBG("mgr %p orig refcnt %d", mgr, kref_read(&mgr->kref));
 830 
 831         return kref_put(&mgr->kref, &amp_mgr_destroy);
 832 }
 833 
 834 static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked)
 835 {
 836         struct amp_mgr *mgr;
 837         struct l2cap_chan *chan;
 838 
 839         mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
 840         if (!mgr)
 841                 return NULL;
 842 
 843         BT_DBG("conn %p mgr %p", conn, mgr);
 844 
 845         mgr->l2cap_conn = conn;
 846 
 847         chan = a2mp_chan_open(conn, locked);
 848         if (!chan) {
 849                 kfree(mgr);
 850                 return NULL;
 851         }
 852 
 853         mgr->a2mp_chan = chan;
 854         chan->data = mgr;
 855 
 856         conn->hcon->amp_mgr = mgr;
 857 
 858         kref_init(&mgr->kref);
 859 
 860         /* Remote AMP ctrl list initialization */
 861         INIT_LIST_HEAD(&mgr->amp_ctrls);
 862         mutex_init(&mgr->amp_ctrls_lock);
 863 
 864         mutex_lock(&amp_mgr_list_lock);
 865         list_add(&mgr->list, &amp_mgr_list);
 866         mutex_unlock(&amp_mgr_list_lock);
 867 
 868         return mgr;
 869 }
 870 
 871 struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
 872                                        struct sk_buff *skb)
 873 {
 874         struct amp_mgr *mgr;
 875 
 876         if (conn->hcon->type != ACL_LINK)
 877                 return NULL;
 878 
 879         mgr = amp_mgr_create(conn, false);
 880         if (!mgr) {
 881                 BT_ERR("Could not create AMP manager");
 882                 return NULL;
 883         }
 884 
 885         BT_DBG("mgr: %p chan %p", mgr, mgr->a2mp_chan);
 886 
 887         return mgr->a2mp_chan;
 888 }
 889 
 890 void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
 891 {
 892         struct amp_mgr *mgr;
 893         struct a2mp_info_rsp rsp;
 894 
 895         mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_INFO);
 896         if (!mgr)
 897                 return;
 898 
 899         BT_DBG("%s mgr %p", hdev->name, mgr);
 900 
 901         rsp.id = hdev->id;
 902         rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
 903 
 904         if (hdev->amp_type != AMP_TYPE_BREDR) {
 905                 rsp.status = 0;
 906                 rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
 907                 rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
 908                 rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
 909                 rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
 910                 rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
 911         }
 912 
 913         a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
 914         amp_mgr_put(mgr);
 915 }
 916 
 917 void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
 918 {
 919         struct amp_mgr *mgr;
 920         struct amp_assoc *loc_assoc = &hdev->loc_assoc;
 921         struct a2mp_amp_assoc_rsp *rsp;
 922         size_t len;
 923 
 924         mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
 925         if (!mgr)
 926                 return;
 927 
 928         BT_DBG("%s mgr %p", hdev->name, mgr);
 929 
 930         len = sizeof(struct a2mp_amp_assoc_rsp) + loc_assoc->len;
 931         rsp = kzalloc(len, GFP_KERNEL);
 932         if (!rsp) {
 933                 amp_mgr_put(mgr);
 934                 return;
 935         }
 936 
 937         rsp->id = hdev->id;
 938 
 939         if (status) {
 940                 rsp->status = A2MP_STATUS_INVALID_CTRL_ID;
 941         } else {
 942                 rsp->status = A2MP_STATUS_SUCCESS;
 943                 memcpy(rsp->amp_assoc, loc_assoc->data, loc_assoc->len);
 944         }
 945 
 946         a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, mgr->ident, len, rsp);
 947         amp_mgr_put(mgr);
 948         kfree(rsp);
 949 }
 950 
 951 void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status)
 952 {
 953         struct amp_mgr *mgr;
 954         struct amp_assoc *loc_assoc = &hdev->loc_assoc;
 955         struct a2mp_physlink_req *req;
 956         struct l2cap_chan *bredr_chan;
 957         size_t len;
 958 
 959         mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC_FINAL);
 960         if (!mgr)
 961                 return;
 962 
 963         len = sizeof(*req) + loc_assoc->len;
 964 
 965         BT_DBG("%s mgr %p assoc_len %zu", hdev->name, mgr, len);
 966 
 967         req = kzalloc(len, GFP_KERNEL);
 968         if (!req) {
 969                 amp_mgr_put(mgr);
 970                 return;
 971         }
 972 
 973         bredr_chan = mgr->bredr_chan;
 974         if (!bredr_chan)
 975                 goto clean;
 976 
 977         req->local_id = hdev->id;
 978         req->remote_id = bredr_chan->remote_amp_id;
 979         memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len);
 980 
 981         a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req);
 982 
 983 clean:
 984         amp_mgr_put(mgr);
 985         kfree(req);
 986 }
 987 
 988 void a2mp_send_create_phy_link_rsp(struct hci_dev *hdev, u8 status)
 989 {
 990         struct amp_mgr *mgr;
 991         struct a2mp_physlink_rsp rsp;
 992         struct hci_conn *hs_hcon;
 993 
 994         mgr = amp_mgr_lookup_by_state(WRITE_REMOTE_AMP_ASSOC);
 995         if (!mgr)
 996                 return;
 997 
 998         hs_hcon = hci_conn_hash_lookup_state(hdev, AMP_LINK, BT_CONNECT);
 999         if (!hs_hcon) {
1000                 rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
1001         } else {
1002                 rsp.remote_id = hs_hcon->remote_id;
1003                 rsp.status = A2MP_STATUS_SUCCESS;
1004         }
1005 
1006         BT_DBG("%s mgr %p hs_hcon %p status %u", hdev->name, mgr, hs_hcon,
1007                status);
1008 
1009         rsp.local_id = hdev->id;
1010         a2mp_send(mgr, A2MP_CREATEPHYSLINK_RSP, mgr->ident, sizeof(rsp), &rsp);
1011         amp_mgr_put(mgr);
1012 }
1013 
1014 void a2mp_discover_amp(struct l2cap_chan *chan)
1015 {
1016         struct l2cap_conn *conn = chan->conn;
1017         struct amp_mgr *mgr = conn->hcon->amp_mgr;
1018         struct a2mp_discov_req req;
1019 
1020         BT_DBG("chan %p conn %p mgr %p", chan, conn, mgr);
1021 
1022         if (!mgr) {
1023                 mgr = amp_mgr_create(conn, true);
1024                 if (!mgr)
1025                         return;
1026         }
1027 
1028         mgr->bredr_chan = chan;
1029 
1030         req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
1031         req.ext_feat = 0;
1032         a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req);
1033 }

/* [<][>][^][v][top][bottom][index][help] */