@@ -40,7 +40,6 @@ LOG_MODULE_REGISTER(bt_l2cap, CONFIG_BT_L2CAP_LOG_LEVEL);
4040#define CHAN_RX (_w ) CONTAINER_OF(_w, struct bt_l2cap_le_chan, rx_work)
4141
4242#define L2CAP_LE_MIN_MTU 23
43- #define L2CAP_ECRED_MIN_MTU 64
4443
4544#define L2CAP_LE_MAX_CREDITS (CONFIG_BT_BUF_ACL_RX_COUNT - 1)
4645
@@ -58,6 +57,10 @@ LOG_MODULE_REGISTER(bt_l2cap, CONFIG_BT_L2CAP_LOG_LEVEL);
5857
5958#define L2CAP_CONN_TIMEOUT K_SECONDS(40)
6059#define L2CAP_DISC_TIMEOUT K_SECONDS(2)
60+ /** @brief Local L2CAP RTX (Response Timeout eXpired)
61+ *
62+ * Specification-allowed range for the value of RTX is 1 to 60 seconds.
63+ */
6164#define L2CAP_RTX_TIMEOUT K_SECONDS(2)
6265
6366#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL )
@@ -613,15 +616,15 @@ static void l2cap_le_encrypt_change(struct bt_l2cap_chan *chan, uint8_t status)
613616
614617#if defined(CONFIG_BT_L2CAP_ECRED )
615618 if (le -> ident ) {
616- struct bt_l2cap_chan * echan [L2CAP_ECRED_CHAN_MAX_PER_REQ ];
619+ struct bt_l2cap_chan * echan [BT_L2CAP_ECRED_CHAN_MAX_PER_REQ ];
617620 struct bt_l2cap_chan * ch ;
618621 int i = 0 ;
619622
620623 SYS_SLIST_FOR_EACH_CONTAINER (& chan -> conn -> channels , ch , node ) {
621624 if (le -> ident == BT_L2CAP_LE_CHAN (ch )-> ident ) {
622- __ASSERT (i < L2CAP_ECRED_CHAN_MAX_PER_REQ ,
623- "There can only be L2CAP_ECRED_CHAN_MAX_PER_REQ channels "
624- "from the same request." );
625+ __ASSERT (i < BT_L2CAP_ECRED_CHAN_MAX_PER_REQ ,
626+ "There can only be BT_L2CAP_ECRED_CHAN_MAX_PER_REQ "
627+ "channels from the same request." );
625628 atomic_clear_bit (ch -> status , BT_L2CAP_STATUS_ENCRYPT_PENDING );
626629 echan [i ++ ] = ch ;
627630 }
@@ -1518,14 +1521,14 @@ static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
15181521 struct net_buf * buf )
15191522{
15201523 struct bt_conn * conn = l2cap -> chan .chan .conn ;
1521- struct bt_l2cap_chan * chan [L2CAP_ECRED_CHAN_MAX_PER_REQ ];
1524+ struct bt_l2cap_chan * chan [BT_L2CAP_ECRED_CHAN_MAX_PER_REQ ];
15221525 struct bt_l2cap_le_chan * ch = NULL ;
15231526 struct bt_l2cap_server * server ;
15241527 struct bt_l2cap_ecred_conn_req * req ;
15251528 struct bt_l2cap_ecred_conn_rsp * rsp ;
15261529 uint16_t mtu , mps , credits , result = BT_L2CAP_LE_SUCCESS ;
15271530 uint16_t psm = 0x0000 ;
1528- uint16_t scid , dcid [L2CAP_ECRED_CHAN_MAX_PER_REQ ];
1531+ uint16_t scid , dcid [BT_L2CAP_ECRED_CHAN_MAX_PER_REQ ];
15291532 int i = 0 ;
15301533 uint8_t req_cid_count ;
15311534 bool rsp_queued = false;
@@ -1544,7 +1547,7 @@ static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
15441547
15451548 if (buf -> len > sizeof (dcid )) {
15461549 LOG_ERR ("Too large LE conn req packet size" );
1547- req_cid_count = L2CAP_ECRED_CHAN_MAX_PER_REQ ;
1550+ req_cid_count = BT_L2CAP_ECRED_CHAN_MAX_PER_REQ ;
15481551 result = BT_L2CAP_LE_ERR_INVALID_PARAMS ;
15491552 goto response ;
15501553 }
@@ -1556,7 +1559,7 @@ static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
15561559
15571560 LOG_DBG ("psm 0x%02x mtu %u mps %u credits %u" , psm , mtu , mps , credits );
15581561
1559- if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MTU ) {
1562+ if (mtu < BT_L2CAP_ECRED_MIN_MTU || mps < BT_L2CAP_ECRED_MIN_MTU ) {
15601563 LOG_ERR ("Invalid ecred conn req params. mtu %u mps %u" , mtu , mps );
15611564 result = BT_L2CAP_LE_ERR_INVALID_PARAMS ;
15621565 goto response ;
@@ -1646,7 +1649,7 @@ static void le_ecred_reconf_req(struct bt_l2cap *l2cap, uint8_t ident,
16461649 struct net_buf * buf )
16471650{
16481651 struct bt_conn * conn = l2cap -> chan .chan .conn ;
1649- struct bt_l2cap_chan * chans [L2CAP_ECRED_CHAN_MAX_PER_REQ ];
1652+ struct bt_l2cap_chan * chans [BT_L2CAP_ECRED_CHAN_MAX_PER_REQ ];
16501653 struct bt_l2cap_ecred_reconf_req * req ;
16511654 struct bt_l2cap_ecred_reconf_rsp * rsp ;
16521655 uint16_t mtu , mps ;
@@ -1664,18 +1667,18 @@ static void le_ecred_reconf_req(struct bt_l2cap *l2cap, uint8_t ident,
16641667 mtu = sys_le16_to_cpu (req -> mtu );
16651668 mps = sys_le16_to_cpu (req -> mps );
16661669
1667- if (mps < L2CAP_ECRED_MIN_MTU ) {
1670+ if (mps < BT_L2CAP_ECRED_MIN_MTU ) {
16681671 result = BT_L2CAP_RECONF_OTHER_UNACCEPT ;
16691672 goto response ;
16701673 }
16711674
1672- if (mtu < L2CAP_ECRED_MIN_MTU ) {
1675+ if (mtu < BT_L2CAP_ECRED_MIN_MTU ) {
16731676 result = BT_L2CAP_RECONF_INVALID_MTU ;
16741677 goto response ;
16751678 }
16761679
16771680 /* The specification only allows up to 5 CIDs in this packet */
1678- if (buf -> len > (L2CAP_ECRED_CHAN_MAX_PER_REQ * sizeof (scid ))) {
1681+ if (buf -> len > (BT_L2CAP_ECRED_CHAN_MAX_PER_REQ * sizeof (scid ))) {
16791682 result = BT_L2CAP_RECONF_OTHER_UNACCEPT ;
16801683 goto response ;
16811684 }
@@ -2908,7 +2911,7 @@ int bt_l2cap_ecred_chan_connect(struct bt_conn *conn,
29082911 }
29092912
29102913 /* Init non-null channels */
2911- for (i = 0 ; i < L2CAP_ECRED_CHAN_MAX_PER_REQ ; i ++ ) {
2914+ for (i = 0 ; i < BT_L2CAP_ECRED_CHAN_MAX_PER_REQ ; i ++ ) {
29122915 if (!chan [i ]) {
29132916 break ;
29142917 }
@@ -2962,7 +2965,7 @@ int bt_l2cap_ecred_chan_reconfigure(struct bt_l2cap_chan **chans, uint16_t mtu)
29622965 return - EINVAL ;
29632966 }
29642967
2965- for (i = 0 ; i < L2CAP_ECRED_CHAN_MAX_PER_REQ ; i ++ ) {
2968+ for (i = 0 ; i < BT_L2CAP_ECRED_CHAN_MAX_PER_REQ ; i ++ ) {
29662969 if (!chans [i ]) {
29672970 break ;
29682971 }
@@ -3035,6 +3038,94 @@ int bt_l2cap_ecred_chan_reconfigure(struct bt_l2cap_chan **chans, uint16_t mtu)
30353038 return 0 ;
30363039}
30373040
3041+ #if defined(CONFIG_BT_L2CAP_RECONFIGURE_EXPLICIT )
3042+ int bt_l2cap_ecred_chan_reconfigure_explicit (struct bt_l2cap_chan * * chans , size_t chan_count ,
3043+ uint16_t mtu , uint16_t mps )
3044+ {
3045+ struct bt_l2cap_ecred_reconf_req * req ;
3046+ struct bt_conn * conn = NULL ;
3047+ struct net_buf * buf ;
3048+ uint8_t ident ;
3049+
3050+ LOG_DBG ("chans %p chan_count %u mtu 0x%04x mps 0x%04x" , chans , chan_count , mtu , mps );
3051+
3052+ if (!chans || !IN_RANGE (chan_count , 1 , BT_L2CAP_ECRED_CHAN_MAX_PER_REQ )) {
3053+ return - EINVAL ;
3054+ }
3055+
3056+ if (!IN_RANGE (mps , BT_L2CAP_ECRED_MIN_MPS , BT_L2CAP_RX_MTU )) {
3057+ return - EINVAL ;
3058+ }
3059+
3060+ for (size_t i = 0 ; i < chan_count ; i ++ ) {
3061+ /* validate that all channels are from same connection */
3062+ if (conn ) {
3063+ if (conn != chans [i ]-> conn ) {
3064+ return - EINVAL ;
3065+ }
3066+ } else {
3067+ conn = chans [i ]-> conn ;
3068+ }
3069+
3070+ /* validate MTU is not decreased */
3071+ if (mtu < BT_L2CAP_LE_CHAN (chans [i ])-> rx .mtu ) {
3072+ return - EINVAL ;
3073+ }
3074+
3075+ /* MPS is not allowed to decrease when reconfiguring multiple channels.
3076+ * Core Specification 3.A.4.27 v6.0
3077+ */
3078+ if (chan_count > 1 && mps < BT_L2CAP_LE_CHAN (chans [i ])-> rx .mps ) {
3079+ return - EINVAL ;
3080+ }
3081+ }
3082+
3083+ if (!conn ) {
3084+ return - ENOTCONN ;
3085+ }
3086+
3087+ if (conn -> type != BT_CONN_TYPE_LE ) {
3088+ return - EINVAL ;
3089+ }
3090+
3091+ /* allow only 1 request at time */
3092+ if (l2cap_find_pending_reconf (conn )) {
3093+ return - EBUSY ;
3094+ }
3095+
3096+ ident = get_ident ();
3097+
3098+ buf = l2cap_create_le_sig_pdu (BT_L2CAP_ECRED_RECONF_REQ , ident ,
3099+ sizeof (* req ) + (chan_count * sizeof (uint16_t )));
3100+ if (!buf ) {
3101+ return - ENOMEM ;
3102+ }
3103+
3104+ req = net_buf_add (buf , sizeof (* req ));
3105+ req -> mtu = sys_cpu_to_le16 (mtu );
3106+ req -> mps = sys_cpu_to_le16 (mps );
3107+
3108+ for (size_t i = 0 ; i < chan_count ; i ++ ) {
3109+ struct bt_l2cap_le_chan * ch ;
3110+
3111+ ch = BT_L2CAP_LE_CHAN (chans [i ]);
3112+
3113+ ch -> ident = ident ;
3114+ ch -> pending_rx_mtu = mtu ;
3115+
3116+ net_buf_add_le16 (buf , ch -> rx .cid );
3117+ };
3118+
3119+ /* We set the RTX timer on one of the supplied channels, but when the
3120+ * request resolves or times out we will act on all the channels in the
3121+ * supplied array, using the ident field to find them.
3122+ */
3123+ l2cap_chan_send_req (chans [0 ], buf , L2CAP_CONN_TIMEOUT );
3124+
3125+ return 0 ;
3126+ }
3127+ #endif /* defined(CONFIG_BT_L2CAP_RECONFIGURE_EXPLICIT) */
3128+
30383129#endif /* defined(CONFIG_BT_L2CAP_ECRED) */
30393130
30403131int bt_l2cap_chan_connect (struct bt_conn * conn , struct bt_l2cap_chan * chan ,
0 commit comments