@@ -998,6 +998,134 @@ static void le_disconn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
998998 bt_l2cap_chan_del (& chan -> chan );
999999}
10001000
1001+ static struct net_buf * l2cap_chan_create_seg (struct bt_l2cap_le_chan * ch ,
1002+ struct net_buf * buf ,
1003+ size_t sdu_hdr_len )
1004+ {
1005+ struct net_buf * seg ;
1006+ uint16_t headroom ;
1007+ uint16_t len ;
1008+
1009+ /* Segment if data (+ data headroom) is bigger than MPS */
1010+ if (buf -> len + sdu_hdr_len > ch -> tx .mps ) {
1011+ goto segment ;
1012+ }
1013+
1014+ /* Segment if there is no space in the user_data */
1015+ if (buf -> pool -> user_data_size < BT_BUF_USER_DATA_MIN ) {
1016+ BT_WARN ("Too small buffer user_data_size %u" ,
1017+ buf -> pool -> user_data_size );
1018+ goto segment ;
1019+ }
1020+
1021+ headroom = sizeof (struct bt_hci_acl_hdr ) +
1022+ sizeof (struct bt_l2cap_hdr ) + sdu_hdr_len ;
1023+
1024+ /* Check if original buffer has enough headroom and don't have any
1025+ * fragments.
1026+ */
1027+ if (net_buf_headroom (buf ) >= headroom && !buf -> frags ) {
1028+ if (sdu_hdr_len ) {
1029+ /* Push SDU length if set */
1030+ net_buf_push_le16 (buf , net_buf_frags_len (buf ));
1031+ }
1032+ return net_buf_ref (buf );
1033+ }
1034+
1035+ segment :
1036+ seg = bt_l2cap_create_pdu (& le_data_pool , 0 );
1037+
1038+ if (sdu_hdr_len ) {
1039+ net_buf_add_le16 (seg , net_buf_frags_len (buf ));
1040+ }
1041+
1042+ /* Don't send more that TX MPS including SDU length */
1043+ len = min (net_buf_tailroom (seg ), ch -> tx .mps - sdu_hdr_len );
1044+ /* Limit if original buffer is smaller than the segment */
1045+ len = min (buf -> len , len );
1046+ net_buf_add_mem (seg , buf -> data , len );
1047+ net_buf_pull (buf , len );
1048+
1049+ BT_DBG ("ch %p seg %p len %u" , ch , seg , seg -> len );
1050+
1051+ return seg ;
1052+ }
1053+
1054+ static int l2cap_chan_le_send (struct bt_l2cap_le_chan * ch , struct net_buf * buf ,
1055+ uint16_t sdu_hdr_len )
1056+ {
1057+ int len ;
1058+
1059+ /* Wait for credits */
1060+ if (k_sem_take (& ch -> tx .credits , K_NO_WAIT )) {
1061+ BT_DBG ("No credits to transmit packet" );
1062+ return - EAGAIN ;
1063+ }
1064+
1065+ buf = l2cap_chan_create_seg (ch , buf , sdu_hdr_len );
1066+ if (!buf ) {
1067+ return - ENOMEM ;
1068+ }
1069+
1070+ /* Channel may have been disconnected while waiting for credits */
1071+ if (!ch -> chan .conn ) {
1072+ net_buf_unref (buf );
1073+ return - ECONNRESET ;
1074+ }
1075+
1076+ BT_DBG ("ch %p cid 0x%04x len %u credits %u" , ch , ch -> tx .cid ,
1077+ buf -> len , k_sem_count_get (& ch -> tx .credits ));
1078+
1079+ len = buf -> len ;
1080+
1081+ bt_l2cap_send (ch -> chan .conn , ch -> tx .cid , buf );
1082+
1083+ return len ;
1084+ }
1085+
1086+ static int l2cap_chan_le_send_sdu (struct bt_l2cap_le_chan * ch ,
1087+ struct net_buf * buf )
1088+ {
1089+ int ret , sent , total_len ;
1090+ struct net_buf * frag ;
1091+
1092+ total_len = net_buf_frags_len (buf );
1093+
1094+ if (total_len > ch -> tx .mtu ) {
1095+ return - EMSGSIZE ;
1096+ }
1097+
1098+ frag = buf ;
1099+ if (!frag -> len && frag -> frags ) {
1100+ frag = frag -> frags ;
1101+ }
1102+
1103+ /* Add SDU length for the first segment */
1104+ ret = l2cap_chan_le_send (ch , frag , BT_L2CAP_SDU_HDR_LEN );
1105+ if (ret < 0 ) {
1106+ return ret ;
1107+ }
1108+
1109+ /* Send remaining segments */
1110+ for (sent = ret ; sent < total_len ; sent += ret ) {
1111+ /* Proceed to next fragment */
1112+ if (!frag -> len ) {
1113+ frag = net_buf_frag_del (buf , frag );
1114+ }
1115+
1116+ ret = l2cap_chan_le_send (ch , frag , 0 );
1117+ if (ret < 0 ) {
1118+ return ret ;
1119+ }
1120+ }
1121+
1122+ BT_DBG ("ch %p cid 0x%04x sent %u" , ch , ch -> tx .cid , sent );
1123+
1124+ net_buf_unref (buf );
1125+
1126+ return ret ;
1127+ }
1128+
10011129static void le_credits (struct bt_l2cap * l2cap , uint8_t ident ,
10021130 struct net_buf * buf )
10031131{
@@ -1499,131 +1627,6 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
14991627 return 0 ;
15001628}
15011629
1502- static struct net_buf * l2cap_chan_create_seg (struct bt_l2cap_le_chan * ch ,
1503- struct net_buf * buf ,
1504- size_t sdu_hdr_len )
1505- {
1506- struct net_buf * seg ;
1507- uint16_t headroom ;
1508- uint16_t len ;
1509-
1510- /* Segment if data (+ data headroom) is bigger than MPS */
1511- if (buf -> len + sdu_hdr_len > ch -> tx .mps ) {
1512- goto segment ;
1513- }
1514-
1515- /* Segment if there is no space in the user_data */
1516- if (buf -> pool -> user_data_size < BT_BUF_USER_DATA_MIN ) {
1517- BT_WARN ("Too small buffer user_data_size %u" ,
1518- buf -> pool -> user_data_size );
1519- goto segment ;
1520- }
1521-
1522- headroom = sizeof (struct bt_hci_acl_hdr ) +
1523- sizeof (struct bt_l2cap_hdr ) + sdu_hdr_len ;
1524-
1525- /* Check if original buffer has enough headroom and don't have any
1526- * fragments.
1527- */
1528- if (net_buf_headroom (buf ) >= headroom && !buf -> frags ) {
1529- if (sdu_hdr_len ) {
1530- /* Push SDU length if set */
1531- net_buf_push_le16 (buf , net_buf_frags_len (buf ));
1532- }
1533- return net_buf_ref (buf );
1534- }
1535-
1536- segment :
1537- seg = bt_l2cap_create_pdu (& le_data_pool , 0 );
1538-
1539- if (sdu_hdr_len ) {
1540- net_buf_add_le16 (seg , net_buf_frags_len (buf ));
1541- }
1542-
1543- /* Don't send more that TX MPS including SDU length */
1544- len = min (net_buf_tailroom (seg ), ch -> tx .mps - sdu_hdr_len );
1545- /* Limit if original buffer is smaller than the segment */
1546- len = min (buf -> len , len );
1547- net_buf_add_mem (seg , buf -> data , len );
1548- net_buf_pull (buf , len );
1549-
1550- BT_DBG ("ch %p seg %p len %u" , ch , seg , seg -> len );
1551-
1552- return seg ;
1553- }
1554-
1555- static int l2cap_chan_le_send (struct bt_l2cap_le_chan * ch , struct net_buf * buf ,
1556- uint16_t sdu_hdr_len )
1557- {
1558- int len ;
1559-
1560- /* Wait for credits */
1561- k_sem_take (& ch -> tx .credits , K_FOREVER );
1562-
1563- buf = l2cap_chan_create_seg (ch , buf , sdu_hdr_len );
1564- if (!buf ) {
1565- return - ENOMEM ;
1566- }
1567-
1568- /* Channel may have been disconnected while waiting for credits */
1569- if (!ch -> chan .conn ) {
1570- net_buf_unref (buf );
1571- return - ECONNRESET ;
1572- }
1573-
1574- BT_DBG ("ch %p cid 0x%04x len %u credits %u" , ch , ch -> tx .cid ,
1575- buf -> len , k_sem_count_get (& ch -> tx .credits ));
1576-
1577- len = buf -> len ;
1578-
1579- bt_l2cap_send (ch -> chan .conn , ch -> tx .cid , buf );
1580-
1581- return len ;
1582- }
1583-
1584- static int l2cap_chan_le_send_sdu (struct bt_l2cap_le_chan * ch ,
1585- struct net_buf * buf )
1586- {
1587- int ret , sent , total_len ;
1588- struct net_buf * frag ;
1589-
1590- total_len = net_buf_frags_len (buf );
1591-
1592- if (total_len > ch -> tx .mtu ) {
1593- return - EMSGSIZE ;
1594- }
1595-
1596- frag = buf ;
1597- if (!frag -> len && frag -> frags ) {
1598- frag = frag -> frags ;
1599- }
1600-
1601- /* Add SDU length for the first segment */
1602- ret = l2cap_chan_le_send (ch , frag , BT_L2CAP_SDU_HDR_LEN );
1603- if (ret < 0 ) {
1604- return ret ;
1605- }
1606-
1607- /* Send remaining segments */
1608- for (sent = ret ; sent < total_len ; sent += ret ) {
1609- /* Proceed to next fragment */
1610- if (!frag -> len ) {
1611- frag = net_buf_frag_del (buf , frag );
1612- }
1613-
1614- ret = l2cap_chan_le_send (ch , frag , 0 );
1615- if (ret < 0 ) {
1616- return ret ;
1617- }
1618- }
1619-
1620- BT_DBG ("ch %p cid 0x%04x sent %u" , ch , ch -> tx .cid , sent );
1621-
1622- net_buf_unref (buf );
1623-
1624- return sent ;
1625- }
1626-
16271630int bt_l2cap_chan_send (struct bt_l2cap_chan * chan , struct net_buf * buf )
16281631{
16291632 int err ;
0 commit comments