Lines Matching full:link
43 #define XACT_SEG_DATA(_seg) (&link.rx.buf->data[XACT_SEG_OFFSET(_seg)])
44 #define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
60 /* Link close retransmits: */
64 ADV_LINK_ACTIVE, /* Link has been opened */
65 ADV_LINK_ACK_RECVD, /* Ack for link has been received */
66 ADV_LINK_CLOSING, /* Link is closing down */
69 ADV_PROVISIONER, /* The link was opened as provisioner */
70 ADV_LINK_ACK_SENDING, /* Link Ack tx was scheduled but not finished. */
77 uint32_t id; /* Link ID */
105 /* Pending outgoing adv(s) (Link Open, Gen Trans Start and Gen Trans Cont) */
118 /* Unacked adv buffers (Link Ack, Link Close and Gen Trans Ack). Array size is
119 * hardcoded to 2 allowing to send Gen Trans Ack and Link Close at the same time.
143 static struct pb_adv link = { .rx = { .buf = &rx_buf } }; variable
159 if (atomic_test_bit(link.flags, ADV_SENDING)) { in tx_schedule()
175 for (int i = 0; i < ARRAY_SIZE(link.tx.unacked); i++) { in send_unacked()
176 if (link.tx.unacked[i].adv != NULL) { in send_unacked()
180 link.tx.unacked[i].adv = adv; in send_unacked()
181 link.tx.unacked[i].cb = cb; in send_unacked()
182 link.tx.unacked[i].cb_data = cb_data; in send_unacked()
196 link.tx.next = 0; in send_reliable()
204 struct unacked_adv_ctx *unacked_adv = &link.tx.unacked[link.tx.last_unacked]; in delayed_adv_send_end()
215 atomic_clear_bit(link.flags, ADV_SENDING); in delayed_adv_send_end()
235 /* Send Link Ack, Link Close and Gen Trans Ack first. */ in tx_work_handler()
236 for (i = 0; i < ARRAY_SIZE(link.tx.unacked); i++) { in tx_work_handler()
237 int idx = (i + link.tx.last_unacked) % ARRAY_SIZE(link.tx.unacked); in tx_work_handler()
238 struct unacked_adv_ctx *unacked = &link.tx.unacked[idx]; in tx_work_handler()
244 atomic_set_bit(link.flags, ADV_SENDING); in tx_work_handler()
247 link.tx.last_unacked = idx; in tx_work_handler()
252 /* Send Trans Start, Trans Cont and Link Open */ in tx_work_handler()
253 if (link.tx.next >= ARRAY_SIZE(link.tx.adv) || link.tx.adv[link.tx.next] == NULL) { in tx_work_handler()
258 atomic_set_bit(link.flags, ADV_SENDING); in tx_work_handler()
259 bt_mesh_adv_send(link.tx.adv[link.tx.next], &delayed_adv_send_cb, (void *)false); in tx_work_handler()
261 link.tx.next++; in tx_work_handler()
263 if (link.tx.next == ARRAY_SIZE(link.tx.adv) || link.tx.adv[link.tx.next] == NULL) { in tx_work_handler()
266 k_work_reschedule(&link.tx.retransmit, RETRANSMIT_TIMEOUT); in tx_work_handler()
286 for (i = 0; i < ARRAY_SIZE(link.tx.adv); i++) { in free_segments()
287 struct bt_mesh_adv *adv = link.tx.adv[i]; in free_segments()
294 link.tx.adv[i] = NULL; in free_segments()
312 atomic_clear_bit(link.flags, ADV_SENDING); in free_segments()
331 (void)k_work_cancel_delayable(&link.tx.retransmit); in prov_clear_tx()
344 (void)k_work_cancel_delayable(&link.prot_timer); in reset_adv_link()
346 if (atomic_test_bit(link.flags, ADV_PROVISIONER)) { in reset_adv_link()
350 (void)memset(&link, 0, offsetof(struct pb_adv, tx.retransmit)); in reset_adv_link()
351 link.rx.id = XACT_ID_NVAL; in reset_adv_link()
353 /* If provisioned, reset the link callback to stop receiving provisioning advs, in reset_adv_link()
357 link.cb = NULL; in reset_adv_link()
360 link.id = 0; in reset_adv_link()
361 atomic_clear(link.flags); in reset_adv_link()
362 link.rx.id = XACT_ID_MAX; in reset_adv_link()
363 link.tx.id = XACT_ID_NVAL; in reset_adv_link()
366 link.tx.pending_ack = XACT_ID_NVAL; in reset_adv_link()
367 link.rx.buf = &rx_buf; in reset_adv_link()
368 net_buf_simple_reset(link.rx.buf); in reset_adv_link()
373 const struct prov_bearer_cb *cb = link.cb; in close_link()
374 void *cb_data = link.cb_data; in close_link()
397 LOG_DBG("xact 0x%x complete", (uint8_t)link.tx.pending_ack); in ack_complete()
398 atomic_clear_bit(link.flags, ADV_ACK_PENDING); in ack_complete()
403 return atomic_test_bit(link.flags, ADV_ACK_PENDING); in ack_pending()
409 link.cb->error(&bt_mesh_pb_adv, link.cb_data, err); in prov_failed()
410 atomic_set_bit(link.flags, ADV_LINK_INVALID); in prov_failed()
415 k_work_reschedule(&link.prot_timer, bt_mesh_prov_protocol_timeout_get()); in prov_msg_recv()
417 if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) { in prov_msg_recv()
422 gen_prov_ack_send(link.rx.id); in prov_msg_recv()
424 if (atomic_test_bit(link.flags, ADV_LINK_INVALID)) { in prov_msg_recv()
425 LOG_WRN("Unexpected msg 0x%02x on invalidated link", link.rx.buf->data[0]); in prov_msg_recv()
430 link.cb->recv(&bt_mesh_pb_adv, link.cb_data, link.rx.buf); in prov_msg_recv()
435 if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { in protocol_timeout()
441 link.rx.seg = 0U; in protocol_timeout()
451 bool pending = atomic_test_and_set_bit(link.flags, ADV_ACK_PENDING); in gen_prov_ack_send()
456 if (pending && link.tx.pending_ack == xact_id) { in gen_prov_ack_send()
463 atomic_clear_bit(link.flags, ADV_ACK_PENDING); in gen_prov_ack_send()
468 link.tx.pending_ack = xact_id; in gen_prov_ack_send()
471 net_buf_simple_add_be32(&adv->b, link.id); in gen_prov_ack_send()
477 atomic_clear_bit(link.flags, ADV_ACK_PENDING); in gen_prov_ack_send()
485 if (link.tx.adv[0]) { in gen_prov_cont()
492 if (!link.rx.seg && link.rx.id == rx->xact_id) { in gen_prov_cont()
501 if (!link.rx.seg && in gen_prov_cont()
502 next_transaction_id(link.rx.id) == rx->xact_id) { in gen_prov_cont()
505 link.rx.id = rx->xact_id; in gen_prov_cont()
507 net_buf_simple_reset(link.rx.buf); in gen_prov_cont()
509 link.rx.seg = SEG_NVAL; in gen_prov_cont()
510 link.rx.last_seg = SEG_NVAL; in gen_prov_cont()
513 } else if (rx->xact_id != link.rx.id) { in gen_prov_cont()
514 LOG_WRN("Data for unknown transaction (0x%x != 0x%x)", rx->xact_id, link.rx.id); in gen_prov_cont()
518 if (seg > link.rx.last_seg) { in gen_prov_cont()
524 if (!(link.rx.seg & BIT(seg))) { in gen_prov_cont()
537 if (seg == link.rx.last_seg && !(link.rx.seg & BIT(0))) { in gen_prov_cont()
540 expect_len = (link.rx.buf->len - 20U - in gen_prov_cont()
541 ((link.rx.last_seg - 1) * 23U)); in gen_prov_cont()
549 if (!link.rx.seg) { in gen_prov_cont()
558 if (!link.tx.adv[0]) { in gen_prov_ack()
562 if (rx->xact_id == link.tx.id) { in gen_prov_ack()
564 if (!atomic_test_bit(link.flags, ADV_LINK_CLOSING)) { in gen_prov_ack()
568 if (link.tx.cb) { in gen_prov_ack()
569 link.tx.cb(0, link.tx.cb_data); in gen_prov_ack()
578 if (link.tx.adv[0]) { in gen_prov_start()
583 if (rx->xact_id == link.rx.id) { in gen_prov_start()
584 if (!link.rx.seg) { in gen_prov_start()
593 if (!(link.rx.seg & BIT(0))) { in gen_prov_start()
597 } else if (rx->xact_id != next_transaction_id(link.rx.id)) { in gen_prov_start()
599 next_transaction_id(link.rx.id)); in gen_prov_start()
603 net_buf_simple_reset(link.rx.buf); in gen_prov_start()
604 link.rx.buf->len = net_buf_simple_pull_be16(buf); in gen_prov_start()
605 link.rx.id = rx->xact_id; in gen_prov_start()
606 link.rx.fcs = net_buf_simple_pull_u8(buf); in gen_prov_start()
609 link.rx.buf->len, link.rx.fcs); in gen_prov_start()
611 if (link.rx.buf->len < 1) { in gen_prov_start()
617 if (link.rx.buf->len > link.rx.buf->size) { in gen_prov_start()
618 LOG_ERR("Too large provisioning PDU (%u bytes)", link.rx.buf->len); in gen_prov_start()
623 if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->len <= 20U) { in gen_prov_start()
629 if (START_LAST_SEG(rx->gpc) != last_seg(link.rx.buf->len)) { in gen_prov_start()
631 last_seg(link.rx.buf->len)); in gen_prov_start()
638 link.rx.last_seg = START_LAST_SEG(rx->gpc); in gen_prov_start()
640 if ((link.rx.seg & BIT(0)) && in gen_prov_start()
641 (find_msb_set((~link.rx.seg) & SEG_NVAL) - 1 > link.rx.last_seg)) { in gen_prov_start()
647 if (link.rx.seg) { in gen_prov_start()
648 seg = link.rx.seg; in gen_prov_start()
651 link.rx.seg = seg & ((1 << (START_LAST_SEG(rx->gpc) + 1)) - 1); in gen_prov_start()
652 memcpy(link.rx.buf->data, buf->data, buf->len); in gen_prov_start()
655 if (!link.rx.seg) { in gen_prov_start()
669 if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { in gen_prov_ctl()
676 if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { in gen_prov_ctl()
711 if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE) && in gen_prov_recv()
713 LOG_DBG("Ignoring message that requires active link"); in gen_prov_recv()
728 if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { in prov_retransmit()
729 LOG_WRN("Link not active"); in prov_retransmit()
733 if (k_uptime_get() - link.tx.start > link.tx.timeout * MSEC_PER_SEC) { in prov_retransmit()
754 net_buf_simple_add_be32(&adv->b, link.id); in ctl_adv_create()
770 k_work_reschedule(&link.prot_timer, bt_mesh_prov_protocol_timeout_get()); in bearer_ctl_send()
772 link.tx.start = k_uptime_get(); in bearer_ctl_send()
773 link.tx.adv[0] = adv; in bearer_ctl_send()
783 atomic_clear_bit(link.flags, ADV_LINK_ACK_SENDING); in buf_sent()
785 if (atomic_test_and_clear_bit(link.flags, ADV_LINK_CLOSING)) { in buf_sent()
800 k_work_reschedule(&link.prot_timer, bt_mesh_prov_protocol_timeout_get()); in bearer_ctl_send_unacked()
817 k_work_reschedule(&link.prot_timer, bt_mesh_prov_protocol_timeout_get()); in prov_send_adv()
824 link.tx.id = next_transaction_id(link.tx.id); in prov_send_adv()
825 net_buf_simple_add_be32(&start->b, link.id); in prov_send_adv()
826 net_buf_simple_add_u8(&start->b, link.tx.id); in prov_send_adv()
832 link.tx.adv[0] = start; in prov_send_adv()
833 link.tx.cb = cb; in prov_send_adv()
834 link.tx.cb_data = cb_data; in prov_send_adv()
835 link.tx.start = k_uptime_get(); in prov_send_adv()
837 LOG_DBG("xact_id: 0x%x len: %u", link.tx.id, msg->len); in prov_send_adv()
846 if (seg_id >= ARRAY_SIZE(link.tx.adv)) { in prov_send_adv()
858 link.tx.adv[seg_id] = adv; in prov_send_adv()
864 net_buf_simple_add_be32(&adv->b, link.id); in prov_send_adv()
865 net_buf_simple_add_u8(&adv->b, link.tx.id); in prov_send_adv()
877 * Link management rx
891 if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { in link_open()
892 /* Send another link ack if the provisioner missed the last */ in link_open()
893 if (link.id != rx->link_id) { in link_open()
894 LOG_DBG("Ignoring bearer open: link already active"); in link_open()
898 if (atomic_test_bit(link.flags, ADV_LINK_ACK_SENDING)) { in link_open()
899 LOG_DBG("Still sending Link Ack"); in link_open()
903 /* Ignore errors, message will be attempted again if we keep receiving link open: */ in link_open()
904 atomic_set_bit(link.flags, ADV_LINK_ACK_SENDING); in link_open()
916 link.id = rx->link_id; in link_open()
917 atomic_set_bit(link.flags, ADV_LINK_ACTIVE); in link_open()
918 net_buf_simple_reset(link.rx.buf); in link_open()
920 atomic_set_bit(link.flags, ADV_LINK_ACK_SENDING); in link_open()
929 link.cb->link_opened(&bt_mesh_pb_adv, link.cb_data); in link_open()
936 if (atomic_test_bit(link.flags, ADV_PROVISIONER)) { in link_ack()
937 if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACK_RECVD)) { in link_ack()
943 link.tx.timeout = TRANSACTION_TIMEOUT; in link_ack()
945 link.cb->link_opened(&bt_mesh_pb_adv, link.cb_data); in link_ack()
968 if (!link.cb) { in bt_mesh_pb_adv_recv()
981 if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE) && link.id != rx.link_id) { in bt_mesh_pb_adv_recv()
1003 if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACTIVE)) { in prov_link_open()
1007 atomic_set_bit(link.flags, ADV_PROVISIONER); in prov_link_open()
1009 bt_rand(&link.id, sizeof(link.id)); in prov_link_open()
1010 link.tx.id = XACT_ID_MAX; in prov_link_open()
1011 link.rx.id = XACT_ID_NVAL; in prov_link_open()
1012 link.cb = cb; in prov_link_open()
1013 link.cb_data = cb_data; in prov_link_open()
1015 /* The link open time is configurable, but this will be changed to TRANSACTION_TIMEOUT once in prov_link_open()
1016 * the link is established. in prov_link_open()
1018 link.tx.timeout = timeout; in prov_link_open()
1020 net_buf_simple_reset(link.rx.buf); in prov_link_open()
1035 if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { in prov_link_accept()
1039 link.rx.id = XACT_ID_MAX; in prov_link_accept()
1040 link.tx.id = XACT_ID_NVAL; in prov_link_accept()
1041 link.cb = cb; in prov_link_accept()
1042 link.cb_data = cb_data; in prov_link_accept()
1043 link.tx.timeout = TRANSACTION_TIMEOUT; in prov_link_accept()
1057 if (atomic_test_and_set_bit(link.flags, ADV_LINK_CLOSING)) { in prov_link_close()
1066 link.tx.timeout = CLOSING_TIMEOUT; in prov_link_close()
1067 /* Ignore errors, the link will time out eventually if this doesn't get sent */ in prov_link_close()
1078 k_work_init_delayable(&link.prot_timer, protocol_timeout); in bt_mesh_pb_adv_init()
1079 k_work_init_delayable(&link.tx.retransmit, prov_retransmit); in bt_mesh_pb_adv_init()