@@ -998,6 +998,134 @@ static void le_disconn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
998
998
bt_l2cap_chan_del (& chan -> chan );
999
999
}
1000
1000
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
+
1001
1129
static void le_credits (struct bt_l2cap * l2cap , uint8_t ident ,
1002
1130
struct net_buf * buf )
1003
1131
{
@@ -1499,131 +1627,6 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
1499
1627
return 0 ;
1500
1628
}
1501
1629
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
-
1627
1630
int bt_l2cap_chan_send (struct bt_l2cap_chan * chan , struct net_buf * buf )
1628
1631
{
1629
1632
int err ;
0 commit comments