|
|
@@ -119,3 +119,225 @@ int bt_mesh_model_unsubscribe_group_addr(u16_t elem_addr, u16_t cid,
|
|
|
BT_INFO("Unsubscribe group address 0x%04x", group_addr);
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+#if CONFIG_BLE_MESH_NODE
|
|
|
+
|
|
|
+const u8_t *bt_mesh_node_get_local_net_key(u16_t net_idx)
|
|
|
+{
|
|
|
+ struct bt_mesh_subnet *sub = NULL;
|
|
|
+
|
|
|
+ if (net_idx > 0xFFF) {
|
|
|
+ BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ sub = bt_mesh_subnet_get(net_idx);
|
|
|
+ if (!sub) {
|
|
|
+ BT_ERR("NetKey 0x%04x not exists", net_idx);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return sub->kr_flag ? sub->keys[1].net : sub->keys[0].net;
|
|
|
+}
|
|
|
+
|
|
|
+const u8_t *bt_mesh_node_get_local_app_key(u16_t app_idx)
|
|
|
+{
|
|
|
+ struct bt_mesh_app_key *key = NULL;
|
|
|
+
|
|
|
+ if (app_idx > 0xFFF) {
|
|
|
+ BT_ERR("Invalid AppKeyIndex 0x%04x", app_idx);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ key = bt_mesh_app_key_find(app_idx);
|
|
|
+ if (!key) {
|
|
|
+ BT_ERR("AppKey 0x%04x not exists", app_idx);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return key->updated ? key->keys[1].val : key->keys[0].val;
|
|
|
+}
|
|
|
+
|
|
|
+int bt_mesh_node_local_net_key_add(u16_t net_idx, const u8_t net_key[16])
|
|
|
+{
|
|
|
+ struct bt_mesh_subnet *sub = NULL;
|
|
|
+ int err = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (net_idx > 0xFFF || net_key == NULL) {
|
|
|
+ BT_ERR("%s, Invalid parameter", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!bt_mesh_is_provisioned()) {
|
|
|
+ BT_ERR("Not provisioned, failed to add NetKey");
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ sub = bt_mesh_subnet_get(net_idx);
|
|
|
+ if (sub) {
|
|
|
+ BT_WARN("NetKey 0x%04x already exists", net_idx);
|
|
|
+ return -EEXIST;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
|
|
+ if (bt_mesh.sub[i].net_idx != BLE_MESH_KEY_UNUSED) {
|
|
|
+ if ((bt_mesh.sub[i].kr_flag == false &&
|
|
|
+ memcmp(bt_mesh.sub[i].keys[0].net, net_key, 16) == 0) ||
|
|
|
+ (bt_mesh.sub[i].kr_flag == true &&
|
|
|
+ memcmp(bt_mesh.sub[i].keys[1].net, net_key, 16) == 0)) {
|
|
|
+ BT_WARN("Key value %s already exists", bt_hex(net_key, 16));
|
|
|
+ return -EEXIST;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
|
|
|
+ if (bt_mesh.sub[i].net_idx == BLE_MESH_KEY_UNUSED) {
|
|
|
+ sub = &bt_mesh.sub[i];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sub == NULL) {
|
|
|
+ BT_ERR("NetKey is full!");
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ err = bt_mesh_net_keys_create(&sub->keys[0], net_key);
|
|
|
+ if (err) {
|
|
|
+ BT_ERR("Failed to create keys for NetKey 0x%04x", net_idx);
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ sub->net_idx = net_idx;
|
|
|
+ sub->kr_flag = false;
|
|
|
+ sub->kr_phase = BLE_MESH_KR_NORMAL;
|
|
|
+ if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) {
|
|
|
+ sub->node_id = BLE_MESH_NODE_IDENTITY_STOPPED;
|
|
|
+ } else {
|
|
|
+ sub->node_id = BLE_MESH_NODE_IDENTITY_NOT_SUPPORTED;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
|
|
|
+ BT_DBG("Storing NetKey persistently");
|
|
|
+ bt_mesh_store_subnet(sub);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Make sure we have valid beacon data to be sent */
|
|
|
+ bt_mesh_net_beacon_update(sub);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int bt_mesh_node_local_app_key_add(u16_t net_idx, u16_t app_idx,
|
|
|
+ const u8_t app_key[16])
|
|
|
+{
|
|
|
+ struct bt_mesh_app_key *key = NULL;
|
|
|
+
|
|
|
+ if (net_idx > 0xFFF || app_idx > 0xFFF || app_key == NULL) {
|
|
|
+ BT_ERR("%s, Invalid parameter", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!bt_mesh_is_provisioned()) {
|
|
|
+ BT_ERR("Not provisioned, failed to add AppKey");
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bt_mesh_subnet_get(net_idx) == NULL) {
|
|
|
+ BT_ERR("Subnet 0x%04x not exists", net_idx);
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ key = bt_mesh_app_key_find(app_idx);
|
|
|
+ if (key) {
|
|
|
+ BT_WARN("AppKey 0x%04x already exists", app_idx);
|
|
|
+ return -EEXIST;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
|
|
|
+ if (bt_mesh.app_keys[i].net_idx != BLE_MESH_KEY_UNUSED) {
|
|
|
+ if ((bt_mesh.app_keys[i].updated == false &&
|
|
|
+ memcmp(bt_mesh.app_keys[i].keys[0].val, app_key, 16) == 0) ||
|
|
|
+ (bt_mesh.app_keys[i].updated == true &&
|
|
|
+ memcmp(bt_mesh.app_keys[i].keys[1].val, app_key, 16) == 0)) {
|
|
|
+ BT_WARN("Key value %s already exists", bt_hex(app_key, 16));
|
|
|
+ return -EEXIST;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ key = bt_mesh_app_key_alloc(app_idx);
|
|
|
+ if (key) {
|
|
|
+ struct bt_mesh_app_keys *keys = &key->keys[0];
|
|
|
+
|
|
|
+ if (bt_mesh_app_id(app_key, &keys->id)) {
|
|
|
+ BT_ERR("Failed to generate AID");
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ key->net_idx = net_idx;
|
|
|
+ key->app_idx = app_idx;
|
|
|
+ key->updated = false;
|
|
|
+ memcpy(keys->val, app_key, 16);
|
|
|
+
|
|
|
+ if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
|
|
|
+ BT_DBG("Storing AppKey persistently");
|
|
|
+ bt_mesh_store_app_key(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ BT_INFO("Add AppKey 0x%04x, NetKeyIndex 0x%04x", app_idx, net_idx);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ BT_ERR("AppKey is full!");
|
|
|
+ return -ENOMEM;
|
|
|
+}
|
|
|
+
|
|
|
+int bt_mesh_node_bind_app_key_to_model(u16_t elem_addr, u16_t mod_id,
|
|
|
+ u16_t cid, u16_t app_idx)
|
|
|
+{
|
|
|
+ struct bt_mesh_model *model = NULL;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (!bt_mesh_is_provisioned()) {
|
|
|
+ BT_ERR("Not provisioned, failed to bind AppKey");
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ model = find_model(elem_addr, cid, mod_id);
|
|
|
+ if (model == NULL) {
|
|
|
+ BT_ERR("Bind, model(id 0x%04x, cid 0x%04x) not found", mod_id, cid);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bt_mesh_app_key_find(app_idx) == NULL) {
|
|
|
+ BT_ERR("Bind, AppKey 0x%03x not exists", app_idx);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(model->keys); i++) {
|
|
|
+ if (model->keys[i] == app_idx) {
|
|
|
+ BT_WARN("Already bound to AppKey 0x%04x", app_idx);
|
|
|
+ return -EALREADY;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(model->keys); i++) {
|
|
|
+ if (model->keys[i] == BLE_MESH_KEY_UNUSED) {
|
|
|
+ model->keys[i] = app_idx;
|
|
|
+ if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
|
|
|
+ bt_mesh_store_mod_bind(model);
|
|
|
+ }
|
|
|
+
|
|
|
+ BT_INFO("Model(id 0x%04x, cid 0x%04x) bound to AppKey 0x%04x", mod_id, cid, app_idx);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ BT_ERR("Model bound is full!");
|
|
|
+ return -ENOMEM;
|
|
|
+}
|
|
|
+
|
|
|
+#endif /* CONFIG_BLE_MESH_NODE */
|