Skip to content

Commit 3a0fa86

Browse files
PavelVPVcarlescufi
authored andcommitted
Bluetooth: Mesh: Fix timeout handling on link opening in RPR Client
This commit fixes an issue, where the RPR Client gets stuck forever until reboot if it doesn't receive Link Status or Link Report message when openinig the remote provisioning link. The RPR_CLI_LINK_OPEN flag was used to control the remote provision link and protect against receiving an unexpected message, but it didn't cover a case when neither of messages were received from the RPR Server. cli->link.state only changes by Link Status or Link Report message and is set to BT_MESH_RPR_LINK_IDLE when opening the link. Therefore, when the RPR Client's timer timed out, the client didn't reset its internal states. This commit adds an additional state to cover this intermediate state when the client initiated the link opening but didn't receive any response. Signed-off-by: Pavel Vasilyev <[email protected]>
1 parent 0e6a886 commit 3a0fa86

File tree

1 file changed

+38
-58
lines changed

1 file changed

+38
-58
lines changed

subsys/bluetooth/mesh/rpr_cli.c

Lines changed: 38 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@ BUILD_ASSERT(BT_MESH_MODEL_OP_LEN(RPR_OP_PDU_SEND) == 2, "Assumes PDU send is a
2828
}
2929

3030
enum {
31-
RPR_CLI_LINK_OPEN,
32-
RPR_CLI_NUM_FLAGS,
31+
BEARER_LINK_IDLE,
32+
BEARER_LINK_OPENING,
33+
BEARER_LINK_OPENED,
3334
};
3435

3536
static struct {
36-
ATOMIC_DEFINE(flags, RPR_CLI_NUM_FLAGS);
37+
int link;
3738
const struct prov_bearer_cb *cb;
3839
struct bt_mesh_rpr_cli *cli;
3940
struct {
@@ -54,22 +55,23 @@ static void link_report(struct bt_mesh_rpr_cli *cli,
5455
struct pb_remote_ctx ctx = { cli, srv };
5556

5657
if (link->state == BT_MESH_RPR_LINK_ACTIVE &&
57-
!atomic_test_and_set_bit(bearer.flags, RPR_CLI_LINK_OPEN)) {
58+
bearer.link == BEARER_LINK_OPENING) {
59+
bearer.link = BEARER_LINK_OPENED;
5860
LOG_DBG("Opened");
5961
bearer.cb->link_opened(&pb_remote_cli, &ctx);
6062
return;
6163
}
6264

63-
if (link->state != BT_MESH_RPR_LINK_IDLE ||
64-
!atomic_test_and_clear_bit(bearer.flags, RPR_CLI_LINK_OPEN)) {
65-
return;
66-
}
65+
if (link->state == BT_MESH_RPR_LINK_IDLE &&
66+
bearer.link != BEARER_LINK_IDLE) {
67+
bearer.link = BEARER_LINK_IDLE;
6768

68-
LOG_DBG("Closed (%u)", link->status);
69-
bearer.cb->link_closed(&pb_remote_cli, &ctx,
70-
((link->status == BT_MESH_RPR_SUCCESS) ?
71-
PROV_BEARER_LINK_STATUS_SUCCESS :
72-
PROV_BEARER_LINK_STATUS_FAIL));
69+
LOG_DBG("Closed (%u)", link->status);
70+
bearer.cb->link_closed(&pb_remote_cli, &ctx,
71+
((link->status == BT_MESH_RPR_SUCCESS) ?
72+
PROV_BEARER_LINK_STATUS_SUCCESS :
73+
PROV_BEARER_LINK_STATUS_FAIL));
74+
}
7375
}
7476

7577
static void tx_complete(struct bt_mesh_rpr_cli *cli, int err, void *cb_data)
@@ -142,13 +144,13 @@ static int handle_link_report(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx
142144
tx_complete(cli, -ECANCELED, cb_data);
143145
}
144146

145-
k_work_reschedule(&cli->link.timeout, K_SECONDS(cli->link.time));
146-
147147
if (cli->link.srv.addr != srv.addr) {
148148
LOG_DBG("Link report from unknown server 0x%04x", srv.addr);
149149
return 0;
150150
}
151151

152+
k_work_reschedule(&cli->link.timeout, K_SECONDS(cli->link.time));
153+
152154
cli->link.state = link.state;
153155

154156
LOG_DBG("0x%04x: status: %u state: %u", srv.addr, link.status,
@@ -205,8 +207,6 @@ static int handle_pdu_outbound_report(struct bt_mesh_model *mod, struct bt_mesh_
205207
void *cb_data;
206208
uint8_t num;
207209

208-
k_work_reschedule(&cli->link.timeout, K_SECONDS(cli->link.time));
209-
210210
if (srv.addr != cli->link.srv.addr) {
211211
LOG_WRN("Outbound report from unknown server 0x%04x", srv.addr);
212212
return 0;
@@ -216,6 +216,7 @@ static int handle_pdu_outbound_report(struct bt_mesh_model *mod, struct bt_mesh_
216216

217217
LOG_DBG("0x%04x: %u", srv.addr, num);
218218

219+
k_work_reschedule(&cli->link.timeout, K_SECONDS(cli->link.time));
219220

220221
if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, RPR_OP_PDU_OUTBOUND_REPORT,
221222
srv.addr, &cb_data) ||
@@ -358,7 +359,7 @@ static void link_timeout(struct k_work *work)
358359
struct bt_mesh_rpr_cli *cli = CONTAINER_OF(k_work_delayable_from_work(work),
359360
struct bt_mesh_rpr_cli, link.timeout);
360361

361-
if (cli->link.state != BT_MESH_RPR_LINK_IDLE) {
362+
if (bearer.link != BEARER_LINK_IDLE) {
362363
LOG_DBG("");
363364
link_closed(cli, BT_MESH_RPR_ERR_LINK_CLOSED_BY_CLIENT);
364365
}
@@ -578,65 +579,31 @@ static int link_open_prov(struct bt_mesh_rpr_cli *cli,
578579
uint8_t timeout)
579580
{
580581
struct bt_mesh_msg_ctx ctx = LINK_CTX(srv, false);
581-
int err;
582-
583-
if (cli->link.srv.addr != BT_MESH_ADDR_UNASSIGNED) {
584-
return -EBUSY;
585-
}
586582

587583
BT_MESH_MODEL_BUF_DEFINE(buf, RPR_OP_LINK_OPEN, 17);
588584
bt_mesh_model_msg_init(&buf, RPR_OP_LINK_OPEN);
589585

590586
net_buf_simple_add_mem(&buf, uuid, 16);
591587

592-
if (timeout) {
593-
cli->link.time = timeout;
594-
}
595-
596588
if (cli->link.time != LINK_TIMEOUT_SECONDS_DEFAULT) {
597589
net_buf_simple_add_u8(&buf, cli->link.time);
598590
}
599591

600-
link_init(cli, srv);
601-
602-
LOG_DBG("");
603-
604-
err = bt_mesh_model_send(cli->mod, &ctx, &buf, NULL, NULL);
605-
if (err) {
606-
link_reset(cli);
607-
}
608-
609-
return err;
592+
return bt_mesh_model_send(cli->mod, &ctx, &buf, NULL, NULL);
610593
}
611594

612595
static int link_open_node(struct bt_mesh_rpr_cli *cli,
613596
const struct bt_mesh_rpr_node *srv,
614597
enum bt_mesh_rpr_node_refresh type)
615598
{
616599
struct bt_mesh_msg_ctx ctx = LINK_CTX(srv, false);
617-
int err;
618-
619-
if (cli->link.srv.addr != BT_MESH_ADDR_UNASSIGNED) {
620-
return -EBUSY;
621-
}
622600

623601
BT_MESH_MODEL_BUF_DEFINE(buf, RPR_OP_LINK_OPEN, 1);
624602
bt_mesh_model_msg_init(&buf, RPR_OP_LINK_OPEN);
625603

626604
net_buf_simple_add_u8(&buf, type);
627605

628-
cli->link.time = LINK_TIMEOUT_SECONDS_DEFAULT;
629-
630-
link_init(cli, srv);
631-
632-
LOG_DBG("");
633-
634-
err = bt_mesh_model_send(cli->mod, &ctx, &buf, NULL, NULL);
635-
if (err) {
636-
link_reset(cli);
637-
}
638-
639-
return err;
606+
return bt_mesh_model_send(cli->mod, &ctx, &buf, NULL, NULL);
640607
}
641608

642609
static int link_close(struct bt_mesh_rpr_cli *cli,
@@ -732,24 +699,37 @@ static int pb_link_open(const uint8_t uuid[16], uint8_t timeout,
732699
const struct prov_bearer_cb *cb, void *cb_data)
733700
{
734701
struct pb_remote_ctx *ctx = cb_data;
702+
struct bt_mesh_rpr_cli *cli = ctx->cli;
703+
const struct bt_mesh_rpr_node *srv = ctx->srv;
735704
int err;
736705

706+
if (cli->link.srv.addr != BT_MESH_ADDR_UNASSIGNED) {
707+
return -EBUSY;
708+
}
709+
737710
bearer.cli = ctx->cli;
738711
bearer.cb = cb;
739712

713+
cli->link.time = timeout ? timeout : LINK_TIMEOUT_SECONDS_DEFAULT;
714+
715+
LOG_DBG("timeout: %d", cli->link.time);
716+
717+
link_init(cli, srv);
718+
740719
if (uuid) {
741-
err = link_open_prov(ctx->cli, ctx->srv, uuid, timeout);
720+
err = link_open_prov(cli, srv, uuid, timeout);
742721
} else {
743-
err = link_open_node(ctx->cli, ctx->srv, ctx->refresh);
722+
err = link_open_node(cli, srv, ctx->refresh);
744723
}
745724

746725
if (err) {
726+
link_reset(cli);
747727
return err;
748728
}
749729

750-
atomic_clear(bearer.flags);
730+
bearer.link = BEARER_LINK_OPENING;
751731

752-
return err;
732+
return 0;
753733
}
754734

755735
static void pb_link_close(enum prov_bearer_link_status status)

0 commit comments

Comments
 (0)