| 541 | */ |
| 542 | |
| 543 | int |
| 544 | ng_l2cap_lp_send(ng_l2cap_con_p con, u_int16_t dcid, struct mbuf *m0) |
| 545 | { |
| 546 | ng_l2cap_p l2cap = con->l2cap; |
| 547 | ng_l2cap_hdr_t *l2cap_hdr = NULL; |
| 548 | ng_hci_acldata_pkt_t *acl_hdr = NULL; |
| 549 | struct mbuf *m_last = NULL, *m = NULL; |
| 550 | int len, flag = (con->linktype == NG_HCI_LINK_ACL) ? NG_HCI_PACKET_START : NG_HCI_LE_PACKET_START; |
| 551 | |
| 552 | KASSERT((con->tx_pkt == NULL), |
| 553 | ("%s: %s - another packet pending?!\n", __func__, NG_NODE_NAME(l2cap->node))); |
| 554 | KASSERT((l2cap->pkt_size > 0), |
| 555 | ("%s: %s - invalid l2cap->pkt_size?!\n", __func__, NG_NODE_NAME(l2cap->node))); |
| 556 | |
| 557 | /* Prepend mbuf with L2CAP header */ |
| 558 | m0 = ng_l2cap_prepend(m0, sizeof(*l2cap_hdr)); |
| 559 | if (m0 == NULL) { |
| 560 | NG_L2CAP_ALERT( |
| 561 | "%s: %s - ng_l2cap_prepend(%zd) failed\n", |
| 562 | __func__, NG_NODE_NAME(l2cap->node), |
| 563 | sizeof(*l2cap_hdr)); |
| 564 | |
| 565 | goto fail; |
| 566 | } |
| 567 | |
| 568 | l2cap_hdr = mtod(m0, ng_l2cap_hdr_t *); |
| 569 | l2cap_hdr->length = htole16(m0->m_pkthdr.len - sizeof(*l2cap_hdr)); |
| 570 | l2cap_hdr->dcid = htole16(dcid); |
| 571 | |
| 572 | /* |
| 573 | * Segment single L2CAP packet according to the HCI layer MTU. Convert |
| 574 | * each segment into ACL data packet and prepend it with ACL data packet |
| 575 | * header. Link all segments together via m_nextpkt link. |
| 576 | * |
| 577 | * XXX BC (Broadcast flag) will always be 0 (zero). |
| 578 | */ |
| 579 | |
| 580 | while (m0 != NULL) { |
| 581 | /* Check length of the packet against HCI MTU */ |
| 582 | len = m0->m_pkthdr.len; |
| 583 | if (len > l2cap->pkt_size) { |
| 584 | m = m_split(m0, l2cap->pkt_size, M_NOWAIT); |
| 585 | if (m == NULL) { |
| 586 | NG_L2CAP_ALERT( |
| 587 | "%s: %s - m_split(%d) failed\n", __func__, NG_NODE_NAME(l2cap->node), |
| 588 | l2cap->pkt_size); |
| 589 | goto fail; |
| 590 | } |
| 591 | |
| 592 | len = l2cap->pkt_size; |
| 593 | } |
| 594 | |
| 595 | /* Convert packet fragment into ACL data packet */ |
| 596 | m0 = ng_l2cap_prepend(m0, sizeof(*acl_hdr)); |
| 597 | if (m0 == NULL) { |
| 598 | NG_L2CAP_ALERT( |
| 599 | "%s: %s - ng_l2cap_prepend(%zd) failed\n", |
| 600 | __func__, NG_NODE_NAME(l2cap->node), |
no test coverage detected