ref: a7f8b59bfb1641dea7f30a267c6bf7e882d9edbf
src/libs/mynewt-nimble/nimble/host/mesh/src/nodes.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
/* * Copyright (c) 2019 Tobias Svehagen * * SPDX-License-Identifier: Apache-2.0 */ #include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_PROV_LOG #if MYNEWT_VAL(BLE_MESH_PROVISIONER) #include "mesh/mesh.h" #include "mesh_priv.h" #include "net.h" #include "access.h" #include "settings.h" /* * Check if an address range from addr_start for addr_start + num_elem - 1 is * free for use. When a conflict is found, next will be set to the next address * available after the conflicting range and -EAGAIN will be returned. */ static int addr_is_free(u16_t addr_start, u8_t num_elem, u16_t *next) { const struct bt_mesh_comp *comp = bt_mesh_comp_get(); u16_t addr_end = addr_start + num_elem - 1; u16_t other_start, other_end; int i; if (comp == NULL) { return -EINVAL; } if (!BT_MESH_ADDR_IS_UNICAST(addr_start) || !BT_MESH_ADDR_IS_UNICAST(addr_end) || num_elem == 0 || next == NULL) { return -EINVAL; } other_start = bt_mesh_primary_addr(); other_end = other_start + comp->elem_count - 1; /* Compare with local element addresses */ if (!(addr_end < other_start || addr_start > other_end)) { *next = other_end + 1; return -EAGAIN; } for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) { struct bt_mesh_node *node = &bt_mesh.nodes[i]; if (node->net_idx == BT_MESH_KEY_UNUSED) { continue; } other_start = node->addr; other_end = other_start + node->num_elem - 1; if (!(addr_end < other_start || addr_start > other_end)) { *next = other_end + 1; return -EAGAIN; } } return 0; } /* * Find the lowest possible starting address that can fit num_elem elements. If * a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be * returned. Otherwise the first address in the range is returned. * * NOTE: This is quite an ineffective algorithm as it might need to look * through the array of nodes N+2 times. A more effective algorithm * could be used if the nodes were stored in a sorted list. */ static u16_t find_lowest_free_addr(u8_t num_elem) { u16_t addr = 1, next; int err, i; /* * It takes a maximum of node count + 2 to find a free address if there * is any. +1 for our own address and +1 for making sure that the * address range is valid. */ for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes) + 2; ++i) { err = addr_is_free(addr, num_elem, &next); if (err == 0) { break; } else if (err != -EAGAIN) { addr = BT_MESH_ADDR_UNASSIGNED; break; } addr = next; } return addr; } struct bt_mesh_node *bt_mesh_node_find(u16_t addr) { int i; for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) { struct bt_mesh_node *node = &bt_mesh.nodes[i]; if (addr >= node->addr && addr <= node->addr + node->num_elem - 1) { return node; } } return NULL; } struct bt_mesh_node *bt_mesh_node_alloc(u16_t addr, u8_t num_elem, u16_t net_idx) { int i; BT_DBG(""); if (addr == BT_MESH_ADDR_UNASSIGNED) { addr = find_lowest_free_addr(num_elem); if (addr == BT_MESH_ADDR_UNASSIGNED) { return NULL; } } else if (!addr_is_free(addr, num_elem, NULL)) { return NULL; } for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) { struct bt_mesh_node *node = &bt_mesh.nodes[i]; if (node->addr == BT_MESH_ADDR_UNASSIGNED) { node->addr = addr; node->num_elem = num_elem; node->net_idx = net_idx; return node; } } return NULL; } void bt_mesh_node_del(struct bt_mesh_node *node, bool store) { BT_DBG("Node addr 0x%04x store %u", node->addr, store); if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { bt_mesh_clear_node(node); } node->addr = BT_MESH_ADDR_UNASSIGNED; (void)memset(node->dev_key, 0, sizeof(node->dev_key)); } #endif |