Skip to content

Commit 57cb1b1

Browse files
Andrewpinijhedberg
authored andcommitted
Bluetooth: Mesh: Add missing comp pages to LCD mod
Adds support for all composition data pages to the Large Composition Data model. Signed-off-by: Anders Storrø <[email protected]>
1 parent 0eb027a commit 57cb1b1

File tree

4 files changed

+199
-94
lines changed

4 files changed

+199
-94
lines changed

subsys/bluetooth/mesh/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,16 @@ config BT_MESH_PRIV_BEACON_CLI
13751375

13761376
endif # BT_MESH_PRIV_BEACONS
13771377

1378+
config BT_MESH_COMP_PST_BUF_SIZE
1379+
int "Composition Data Page persistence buffer size"
1380+
default 100
1381+
help
1382+
Stack allocated buffer used to temporarily hold Composition
1383+
Data Pages during flash operations. Should reflect the size
1384+
of the largest Composition Data Page present in the application.
1385+
Note that this buffer should still be large enough to restore previously stored
1386+
pages after a performed device firmware update.
1387+
13781388
config BT_MESH_COMP_PAGE_1
13791389
bool "Support for Composition Data Page 1"
13801390
depends on BT_MESH_MODEL_EXTENSIONS

subsys/bluetooth/mesh/access.c

Lines changed: 144 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,18 @@ static void data_buf_add_le16_offset(struct net_buf_simple *buf,
173173
}
174174
}
175175

176+
static void data_buf_add_mem_offset(struct net_buf_simple *buf, uint8_t *data, size_t len,
177+
size_t *offset)
178+
{
179+
if (*offset >= len) {
180+
*offset -= len;
181+
return;
182+
}
183+
184+
net_buf_simple_add_mem(buf, data + *offset, len - *offset);
185+
*offset = 0;
186+
}
187+
176188
static void comp_add_model(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
177189
bool vnd, void *user_data)
178190
{
@@ -187,20 +199,6 @@ static void comp_add_model(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
187199
}
188200

189201
#if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
190-
static void data_buf_add_mem_offset(struct net_buf_simple *buf,
191-
const void *mem, size_t len,
192-
size_t *offset)
193-
{
194-
if (*offset >= len) {
195-
*offset -= len;
196-
return;
197-
} else if (*offset > 0) {
198-
net_buf_simple_add_mem(buf, ((uint8_t *)mem), (len - *offset));
199-
200-
} else {
201-
net_buf_simple_add_mem(buf, mem, len);
202-
}
203-
}
204202

205203
static size_t metadata_model_size(struct bt_mesh_model *mod,
206204
struct bt_mesh_elem *elem, bool vnd)
@@ -366,23 +364,6 @@ int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset)
366364
}
367365
#endif
368366

369-
size_t bt_mesh_comp_page_0_size(void)
370-
{
371-
const struct bt_mesh_comp *comp;
372-
const struct bt_mesh_elem *elem;
373-
size_t size = 10;
374-
int i;
375-
376-
comp = bt_mesh_comp_get();
377-
378-
for (i = 0; i < comp->elem_count; i++) {
379-
elem = &comp->elem[i];
380-
size += bt_mesh_comp_elem_size(elem);
381-
}
382-
383-
return size;
384-
}
385-
386367
static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem,
387368
size_t *offset)
388369
{
@@ -398,7 +379,7 @@ static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem,
398379
return 0;
399380
}
400381

401-
if (net_buf_simple_tailroom(buf) < (elem_size + BT_MESH_MIC_SHORT)) {
382+
if (net_buf_simple_tailroom(buf) < ((elem_size - *offset) + BT_MESH_MIC_SHORT)) {
402383
if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) {
403384
/* Mesh Profile 1.1 Section 4.4.1.2.2:
404385
* If the complete list of models does not fit in the Data field,
@@ -516,8 +497,8 @@ static bool is_cor_present(struct bt_mesh_model *mod, uint8_t *cor_id)
516497
return false;
517498
}
518499

519-
static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id,
520-
uint8_t *mod_cnt, struct net_buf_simple *buf)
500+
static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id, uint8_t *mod_cnt,
501+
struct net_buf_simple *buf, size_t *offset)
521502
{
522503
uint8_t ext_mod_cnt;
523504
bool cor_present;
@@ -536,41 +517,41 @@ static void prep_model_item_header(struct bt_mesh_model *mod, uint8_t *cor_id,
536517
if (cor_present) {
537518
mod_elem_info |= BIT(0);
538519
}
539-
net_buf_simple_add_u8(buf, mod_elem_info);
520+
data_buf_add_u8_offset(buf, mod_elem_info, offset);
540521

541522
if (cor_present) {
542-
net_buf_simple_add_u8(buf, *cor_id);
523+
data_buf_add_u8_offset(buf, *cor_id, offset);
543524
}
544525
memset(mod_cnt, ext_mod_cnt, sizeof(uint8_t));
545526
}
546527

547528
static void add_items_to_page(struct net_buf_simple *buf, struct bt_mesh_model *mod,
548-
uint8_t ext_mod_cnt)
529+
uint8_t ext_mod_cnt, size_t *offset)
549530
{
550-
int i, offset;
531+
int i, elem_offset;
551532
uint8_t mod_idx;
552533

553534
MOD_REL_LIST_FOR_EACH(i) {
554535
if (IS_MOD_EXTENSION(mod, i)) {
555-
offset = mod->elem_idx - mod_rel_list[i].elem_base;
536+
elem_offset = mod->elem_idx - mod_rel_list[i].elem_base;
556537
mod_idx = mod_rel_list[i].idx_base;
557538
if (ext_mod_cnt < 32 &&
558-
offset < 4 &&
559-
offset > -5) {
539+
elem_offset < 4 &&
540+
elem_offset > -5) {
560541
/* short format */
561-
if (offset < 0) {
562-
offset += 8;
542+
if (elem_offset < 0) {
543+
elem_offset += 8;
563544
}
564545

565-
offset |= mod_idx << 3;
566-
net_buf_simple_add_u8(buf, offset);
546+
elem_offset |= mod_idx << 3;
547+
data_buf_add_u8_offset(buf, elem_offset, offset);
567548
} else {
568549
/* long format */
569-
if (offset < 0) {
570-
offset += 256;
550+
if (elem_offset < 0) {
551+
elem_offset += 256;
571552
}
572-
net_buf_simple_add_u8(buf, offset);
573-
net_buf_simple_add_u8(buf, mod_idx);
553+
data_buf_add_u8_offset(buf, elem_offset, offset);
554+
data_buf_add_u8_offset(buf, mod_idx, offset);
574555
}
575556
}
576557
}
@@ -613,7 +594,7 @@ static size_t page1_elem_size(struct bt_mesh_elem *elem)
613594
return temp_size;
614595
}
615596

616-
static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf)
597+
static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf, size_t offset)
617598
{
618599
const struct bt_mesh_comp *comp;
619600
uint8_t cor_id = 0;
@@ -623,8 +604,14 @@ static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf)
623604
comp = bt_mesh_comp_get();
624605

625606
for (i = 0; i < comp->elem_count; i++) {
626-
if (net_buf_simple_tailroom(buf) <
627-
(page1_elem_size(&comp->elem[i]) + BT_MESH_MIC_SHORT)) {
607+
size_t elem_size = page1_elem_size(&comp->elem[i]);
608+
609+
if (offset >= elem_size) {
610+
offset -= elem_size;
611+
continue;
612+
}
613+
614+
if (net_buf_simple_tailroom(buf) < ((elem_size - offset) + BT_MESH_MIC_SHORT)) {
628615
if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) {
629616
/* Mesh Profile 1.1 Section 4.4.1.2.2:
630617
* If the complete list of models does not fit in the Data field,
@@ -639,70 +626,74 @@ static int bt_mesh_comp_data_get_page_1(struct net_buf_simple *buf)
639626
return -E2BIG;
640627
}
641628

642-
net_buf_simple_add_u8(buf, comp->elem[i].model_count);
643-
net_buf_simple_add_u8(buf, comp->elem[i].vnd_model_count);
629+
data_buf_add_u8_offset(buf, comp->elem[i].model_count, &offset);
630+
data_buf_add_u8_offset(buf, comp->elem[i].vnd_model_count, &offset);
644631
for (j = 0; j < comp->elem[i].model_count; j++) {
645-
prep_model_item_header(&comp->elem[i].models[j],
646-
&cor_id, &ext_mod_cnt, buf);
632+
prep_model_item_header(&comp->elem[i].models[j], &cor_id, &ext_mod_cnt, buf,
633+
&offset);
647634
if (ext_mod_cnt != 0) {
648-
add_items_to_page(buf,
649-
&comp->elem[i].models[j],
650-
ext_mod_cnt);
635+
add_items_to_page(buf, &comp->elem[i].models[j], ext_mod_cnt,
636+
&offset);
651637
}
652638
}
653639

654640
for (j = 0; j < comp->elem[i].vnd_model_count; j++) {
655-
prep_model_item_header(&comp->elem[i].vnd_models[j],
656-
&cor_id, &ext_mod_cnt, buf);
641+
prep_model_item_header(&comp->elem[i].vnd_models[j], &cor_id, &ext_mod_cnt,
642+
buf, &offset);
657643
if (ext_mod_cnt != 0) {
658-
add_items_to_page(buf,
659-
&comp->elem[i].vnd_models[j],
660-
ext_mod_cnt);
644+
add_items_to_page(buf, &comp->elem[i].vnd_models[j], ext_mod_cnt,
645+
&offset);
661646
}
662647
}
663648
}
664649
return 0;
665650
}
666651

667-
static int bt_mesh_comp_data_get_page_2(struct net_buf_simple *buf)
652+
static int bt_mesh_comp_data_get_page_2(struct net_buf_simple *buf, size_t offset)
668653
{
669654
if (!dev_comp2) {
670655
LOG_ERR("Composition data P2 not registered");
671656
return -ENODEV;
672657
}
673658

659+
size_t elem_size;
660+
674661
for (int i = 0; i < dev_comp2->record_cnt; i++) {
675-
if (net_buf_simple_tailroom(buf) <
676-
(8 + dev_comp2->record[i].elem_offset_cnt + dev_comp2->record[i].data_len +
677-
BT_MESH_MIC_SHORT)) {
662+
elem_size =
663+
8 + dev_comp2->record[i].elem_offset_cnt + dev_comp2->record[i].data_len;
664+
if (offset >= elem_size) {
665+
offset -= elem_size;
666+
continue;
667+
}
668+
669+
if (net_buf_simple_tailroom(buf) < ((elem_size - offset) + BT_MESH_MIC_SHORT)) {
678670
if (IS_ENABLED(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)) {
679671
/* Mesh Profile 1.1 Section 4.4.1.2.2:
680672
* If the complete list of models does not fit in the Data field,
681673
* the element shall not be reported.
682674
*/
683-
LOG_DBG("Record 0x%04x didn't fit in the Data field",
684-
i);
675+
LOG_DBG("Record 0x%04x didn't fit in the Data field", i);
685676
return 0;
686677
}
687678

688679
LOG_ERR("Too large device composition");
689680
return -E2BIG;
690681
}
691682

692-
net_buf_simple_add_le16(buf, dev_comp2->record[i].id);
693-
net_buf_simple_add_u8(buf, dev_comp2->record[i].version.x);
694-
net_buf_simple_add_u8(buf, dev_comp2->record[i].version.y);
695-
net_buf_simple_add_u8(buf, dev_comp2->record[i].version.z);
696-
net_buf_simple_add_u8(buf, dev_comp2->record[i].elem_offset_cnt);
683+
data_buf_add_le16_offset(buf, dev_comp2->record[i].id, &offset);
684+
data_buf_add_u8_offset(buf, dev_comp2->record[i].version.x, &offset);
685+
data_buf_add_u8_offset(buf, dev_comp2->record[i].version.y, &offset);
686+
data_buf_add_u8_offset(buf, dev_comp2->record[i].version.z, &offset);
687+
data_buf_add_u8_offset(buf, dev_comp2->record[i].elem_offset_cnt, &offset);
697688
if (dev_comp2->record[i].elem_offset_cnt) {
698-
net_buf_simple_add_mem(buf, dev_comp2->record[i].elem_offset,
699-
dev_comp2->record[i].elem_offset_cnt);
689+
data_buf_add_mem_offset(buf, (uint8_t *)dev_comp2->record[i].elem_offset,
690+
dev_comp2->record[i].elem_offset_cnt, &offset);
700691
}
701692

702-
net_buf_simple_add_le16(buf, dev_comp2->record[i].data_len);
693+
data_buf_add_le16_offset(buf, dev_comp2->record[i].data_len, &offset);
703694
if (dev_comp2->record[i].data_len) {
704-
net_buf_simple_add_mem(buf, dev_comp2->record[i].data,
705-
dev_comp2->record[i].data_len);
695+
data_buf_add_mem_offset(buf, (uint8_t *)dev_comp2->record[i].data,
696+
dev_comp2->record[i].data_len, &offset);
706697
}
707698
}
708699

@@ -2212,20 +2203,89 @@ int bt_mesh_comp_data_get_page(struct net_buf_simple *buf, size_t page, size_t o
22122203
if (page == 0 || page == 128) {
22132204
return bt_mesh_comp_data_get_page_0(buf, offset);
22142205
} else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && (page == 1 || page == 129)) {
2215-
return bt_mesh_comp_data_get_page_1(buf);
2206+
return bt_mesh_comp_data_get_page_1(buf, offset);
22162207
} else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && (page == 2 || page == 130)) {
2217-
return bt_mesh_comp_data_get_page_2(buf);
2208+
return bt_mesh_comp_data_get_page_2(buf, offset);
22182209
}
22192210

22202211
return -EINVAL;
22212212
}
22222213

2214+
size_t comp_page_0_size(void)
2215+
{
2216+
const struct bt_mesh_comp *comp;
2217+
const struct bt_mesh_elem *elem;
2218+
size_t size = 10; /* Non-variable length params of comp page 0. */
2219+
2220+
comp = bt_mesh_comp_get();
2221+
2222+
for (int i = 0; i < comp->elem_count; i++) {
2223+
elem = &comp->elem[i];
2224+
size += bt_mesh_comp_elem_size(elem);
2225+
}
2226+
2227+
return size;
2228+
}
2229+
2230+
size_t comp_page_1_size(void)
2231+
{
2232+
const struct bt_mesh_comp *comp;
2233+
size_t size = 0;
2234+
2235+
comp = bt_mesh_comp_get();
2236+
2237+
for (int i = 0; i < comp->elem_count; i++) {
2238+
2239+
size += page1_elem_size(&comp->elem[i]);
2240+
}
2241+
2242+
return size;
2243+
}
2244+
2245+
size_t comp_page_2_size(void)
2246+
{
2247+
size_t size = 0;
2248+
2249+
if (!dev_comp2) {
2250+
LOG_ERR("Composition data P2 not registered");
2251+
return size;
2252+
}
2253+
2254+
for (int i = 0; i < dev_comp2->record_cnt; i++) {
2255+
size += 8 + dev_comp2->record[i].elem_offset_cnt + dev_comp2->record[i].data_len;
2256+
}
2257+
return size;
2258+
}
2259+
2260+
size_t bt_mesh_comp_page_size(uint8_t page)
2261+
{
2262+
if (page == 0 || page == 128) {
2263+
return comp_page_0_size();
2264+
} else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && (page == 1 || page == 129)) {
2265+
return comp_page_1_size();
2266+
} else if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && (page == 2 || page == 130)) {
2267+
return comp_page_2_size();
2268+
}
2269+
2270+
return 0;
2271+
}
2272+
22232273
int bt_mesh_comp_store(void)
22242274
{
2225-
NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_TX_SDU_MAX);
2275+
#if IS_ENABLED(CONFIG_BT_MESH_V1d1)
2276+
NET_BUF_SIMPLE_DEFINE(buf, CONFIG_BT_MESH_COMP_PST_BUF_SIZE);
22262277
int err;
22272278

22282279
for (int i = 0; i < ARRAY_SIZE(comp_data_pages); i++) {
2280+
size_t page_size = bt_mesh_comp_page_size(i);
2281+
2282+
if (page_size > CONFIG_BT_MESH_COMP_PST_BUF_SIZE) {
2283+
LOG_WRN("CDP%d is larger than the CDP persistence buffer. "
2284+
"Please increase the CDP persistence buffer size "
2285+
"to the required size (%d bytes)",
2286+
i, page_size);
2287+
}
2288+
22292289
net_buf_simple_reset(&buf);
22302290

22312291
err = bt_mesh_comp_data_get_page(&buf, comp_data_pages[i].page, 0);
@@ -2242,7 +2302,7 @@ int bt_mesh_comp_store(void)
22422302

22432303
LOG_DBG("Stored CDP%d", comp_data_pages[i].page);
22442304
}
2245-
2305+
#endif
22462306
return 0;
22472307
}
22482308

subsys/bluetooth/mesh/access.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ enum {
2323
void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count);
2424

2525
uint8_t bt_mesh_elem_count(void);
26-
size_t bt_mesh_comp_page_0_size(void);
26+
size_t bt_mesh_comp_page_size(uint8_t page);
2727
int bt_mesh_comp_data_get_page_0(struct net_buf_simple *buf, size_t offset);
2828
size_t bt_mesh_metadata_page_0_size(void);
2929
int bt_mesh_metadata_get_page_0(struct net_buf_simple *buf, size_t offset);

0 commit comments

Comments
 (0)