@@ -50,7 +50,7 @@ LOG_MODULE_REGISTER(bt_mesh_pb_adv);
50
50
51
51
#define RETRANSMIT_TIMEOUT K_MSEC(CONFIG_BT_MESH_PB_ADV_RETRANS_TIMEOUT)
52
52
#define BUF_TIMEOUT K_MSEC(400)
53
- #define CLOSING_TIMEOUT 3
53
+ #define CLOSING_TIMEOUT 2
54
54
#define TRANSACTION_TIMEOUT 30
55
55
56
56
/* Acked messages, will do retransmissions manually, taking acks into account:
@@ -112,6 +112,15 @@ struct pb_adv {
112
112
struct k_work_delayable retransmit ;
113
113
} tx ;
114
114
115
+ struct {
116
+ /* Start timestamp of link close */
117
+ int64_t start ;
118
+
119
+ /* Close reason */
120
+ enum prov_bearer_link_status reason ;
121
+ } close_link ;
122
+
123
+
115
124
/* Protocol timeout */
116
125
struct k_work_delayable prot_timer ;
117
126
};
@@ -133,11 +142,18 @@ static void link_close(struct prov_rx *rx, struct net_buf_simple *buf);
133
142
static void prov_link_close (enum prov_bearer_link_status status );
134
143
static void close_link (enum prov_bearer_link_status status );
135
144
145
+ static inline bool close_timer_elapsed (void )
146
+ {
147
+ return k_uptime_get () - link .close_link .start > CLOSING_TIMEOUT * MSEC_PER_SEC ;
148
+ }
149
+
136
150
static void buf_sent (int err , void * user_data )
137
151
{
138
152
enum prov_bearer_link_status reason = (enum prov_bearer_link_status )(int )user_data ;
139
153
140
- if (atomic_test_and_clear_bit (link .flags , ADV_LINK_CLOSING )) {
154
+ if (atomic_test_bit (link .flags , ADV_LINK_CLOSING ) && close_timer_elapsed ()) {
155
+ LOG_DBG ("Close link timer elapsed - Closing link." );
156
+ atomic_clear_bit (link .flags , ADV_LINK_CLOSING );
141
157
close_link (reason );
142
158
return ;
143
159
}
@@ -608,24 +624,6 @@ static void send_reliable(void)
608
624
k_work_reschedule (& link .tx .retransmit , RETRANSMIT_TIMEOUT );
609
625
}
610
626
611
- static void prov_retransmit (struct k_work * work )
612
- {
613
- LOG_DBG ("" );
614
-
615
- if (!atomic_test_bit (link .flags , ADV_LINK_ACTIVE )) {
616
- LOG_WRN ("Link not active" );
617
- return ;
618
- }
619
-
620
- if (k_uptime_get () - link .tx .start > link .tx .timeout * MSEC_PER_SEC ) {
621
- LOG_WRN ("Giving up transaction" );
622
- prov_link_close (PROV_BEARER_LINK_STATUS_TIMEOUT );
623
- return ;
624
- }
625
-
626
- send_reliable ();
627
- }
628
-
629
627
static struct net_buf * ctl_buf_create (uint8_t op , const void * data , uint8_t data_len ,
630
628
uint8_t retransmits )
631
629
{
@@ -663,7 +661,7 @@ static int bearer_ctl_send(struct net_buf *buf)
663
661
return 0 ;
664
662
}
665
663
666
- static int bearer_ctl_send_unacked (struct net_buf * buf , void * user_data )
664
+ static int bearer_ctl_send_unacked (struct net_buf * buf )
667
665
{
668
666
if (!buf ) {
669
667
return - ENOMEM ;
@@ -672,12 +670,57 @@ static int bearer_ctl_send_unacked(struct net_buf *buf, void *user_data)
672
670
prov_clear_tx ();
673
671
k_work_reschedule (& link .prot_timer , PROTOCOL_TIMEOUT );
674
672
675
- bt_mesh_adv_send (buf , & buf_sent_cb , user_data );
673
+ bt_mesh_adv_send (buf , NULL , NULL );
676
674
net_buf_unref (buf );
677
675
678
676
return 0 ;
679
677
}
680
678
679
+ static void bearer_ctl_send_link_close (void )
680
+ { /*
681
+ * According to mesh profile spec (5.3.1.4.3), the close message should
682
+ * be restransmitted at least three times.
683
+ */
684
+ struct net_buf * buf =
685
+ ctl_buf_create (LINK_CLOSE , & link .close_link .reason , 1 , RETRANSMITS_LINK_CLOSE );
686
+
687
+ if (!buf ) {
688
+ LOG_ERR ("Failed to create link close buffer" );
689
+ return ;
690
+ }
691
+
692
+ prov_clear_tx ();
693
+ k_work_reschedule (& link .prot_timer , PROTOCOL_TIMEOUT );
694
+
695
+ bt_mesh_adv_send (buf , & buf_sent_cb , (void * )link .close_link .reason );
696
+ net_buf_unref (buf );
697
+ }
698
+
699
+ static void prov_retransmit (struct k_work * work )
700
+ {
701
+ LOG_DBG ("" );
702
+
703
+ if (atomic_test_bit (link .flags , ADV_LINK_CLOSING )) {
704
+ if (close_timer_elapsed ()) {
705
+ LOG_DBG ("Close link timer elapsed - Closing link." );
706
+ atomic_clear_bit (link .flags , ADV_LINK_CLOSING );
707
+ close_link (link .close_link .reason );
708
+ return ;
709
+ }
710
+
711
+ bearer_ctl_send_link_close ();
712
+ k_work_reschedule (& link .tx .retransmit , RETRANSMIT_TIMEOUT );
713
+ } else if (atomic_test_bit (link .flags , ADV_LINK_ACTIVE )) {
714
+ if (k_uptime_get () - link .tx .start > link .tx .timeout * MSEC_PER_SEC ) {
715
+ LOG_WRN ("Giving up transaction" );
716
+ prov_link_close (PROV_BEARER_LINK_STATUS_TIMEOUT );
717
+ return ;
718
+ }
719
+
720
+ send_reliable ();
721
+ }
722
+ }
723
+
681
724
static int prov_send_adv (struct net_buf_simple * msg ,
682
725
prov_bearer_send_complete_t cb , void * cb_data )
683
726
{
@@ -769,8 +812,7 @@ static void link_open(struct prov_rx *rx, struct net_buf_simple *buf)
769
812
LOG_DBG ("Resending link ack" );
770
813
/* Ignore errors, message will be attempted again if we keep receiving link open: */
771
814
(void )bearer_ctl_send_unacked (
772
- ctl_buf_create (LINK_ACK , NULL , 0 , RETRANSMITS_ACK ),
773
- (void * )PROV_BEARER_LINK_STATUS_SUCCESS );
815
+ ctl_buf_create (LINK_ACK , NULL , 0 , RETRANSMITS_ACK ));
774
816
return ;
775
817
}
776
818
@@ -784,8 +826,7 @@ static void link_open(struct prov_rx *rx, struct net_buf_simple *buf)
784
826
net_buf_simple_reset (link .rx .buf );
785
827
786
828
err = bearer_ctl_send_unacked (
787
- ctl_buf_create (LINK_ACK , NULL , 0 , RETRANSMITS_ACK ),
788
- (void * )PROV_BEARER_LINK_STATUS_SUCCESS );
829
+ ctl_buf_create (LINK_ACK , NULL , 0 , RETRANSMITS_ACK ));
789
830
if (err ) {
790
831
reset_adv_link ();
791
832
return ;
@@ -926,11 +967,11 @@ static void prov_link_close(enum prov_bearer_link_status status)
926
967
* be restransmitted at least three times. Retransmit the LINK_CLOSE
927
968
* message until CLOSING_TIMEOUT has elapsed.
928
969
*/
929
- link .tx . timeout = CLOSING_TIMEOUT ;
930
- /* Ignore errors, the link will time out eventually if this doesn't get sent */
931
- bearer_ctl_send_unacked (
932
- ctl_buf_create ( LINK_CLOSE , & status , 1 , RETRANSMITS_LINK_CLOSE ),
933
- ( void * ) status );
970
+ link .close_link . reason = status ;
971
+ link . close_link . start = k_uptime_get ();
972
+
973
+ bearer_ctl_send_link_close ();
974
+ k_work_reschedule ( & link . tx . retransmit , RETRANSMIT_TIMEOUT );
934
975
}
935
976
936
977
void bt_mesh_pb_adv_init (void )
0 commit comments