Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
thread_nvm_store.c
00001 /* 00002 * Copyright (c) 2017-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: BSD-3-Clause 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holder nor the 00014 * names of its contributors may be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 /* 00030 * \file thread_nvm_store.c 00031 * 00032 */ 00033 00034 #include "nsconfig.h" 00035 00036 #include <string.h> 00037 #include <stdio.h> 00038 #include "Core/include/ns_address_internal.h" 00039 #include "ns_file_system.h" 00040 #include "thread_config.h" 00041 #include "thread_common.h" 00042 #include "thread_nvm_store.h" 00043 #include "ns_trace.h" 00044 00045 #define TRACE_GROUP "tnvm" 00046 const char *FAST_DATA_FILE = "f_d"; 00047 #define FAST_DATA_VERSION 1 00048 #define LINK_INFO_WRITE_DELAY 2 00049 #define LINK_INFO_SHORT_ADDR_NOT_SET 0xffff 00050 #define LINK_INFO_WRITE_DONE 0xffff 00051 00052 const char *LINK_INFO_FILE = "l_i"; 00053 #define LINK_INFO_DATA_VERSION 1 00054 00055 const char *LEADER_INFO_FILE = "ld_i"; 00056 #define LEADER_INFO_DATA_VERSION 1 00057 00058 typedef struct { 00059 uint8_t mac[8]; 00060 uint16_t short_addr; 00061 } nvm_link_info_t; 00062 00063 typedef struct { 00064 nvm_link_info_t nvm_link_info; 00065 uint16_t write_delay; 00066 bool loaded; 00067 } thread_nvm_store_link_info_t; 00068 00069 const char *THREAD_NVM_ACTIVE_CONF_FILE = "a_c"; 00070 #define ACTIVE_CONF_DATA_VERSION 1 00071 00072 const char *DEVICE_CONF_FILE = "s_d"; 00073 #define DEVICE_CONF_VERSION 1 00074 00075 const char *THREAD_NVM_PENDING_CONF_FILE = "p_c"; 00076 #define PENDING_CONF_DATA_VERSION 1 00077 00078 static const char *thread_nvm_store_get_root_path(void); 00079 static int root_path_valid(void); 00080 static int thread_nvm_store_read(const char *file_name, void *data, uint32_t data_size, uint32_t *version); 00081 static int thread_nvm_store_write(const char *file_name, void *data, uint32_t data_size, uint32_t version); 00082 static void thread_nvm_store_create_path(char *fast_data_path, const char *file_name); 00083 static int thread_nvm_store_fast_data_save(thread_nvm_fast_data_t *fast_data_to_set); 00084 static int thread_nvm_store_all_counters_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t seq_counter); 00085 static void thread_nvm_store_link_info_delayed_write(uint32_t seconds); 00086 00087 #define MAX_ROOT_PATH_LEN 200 00088 00089 #define FAST_DATA_STRING_LEN (strlen(FAST_DATA_FILE)+strlen(thread_nvm_store_get_root_path())+1) 00090 #define ACTIVE_CONF_STRING_LEN (strlen(THREAD_NVM_ACTIVE_CONF_FILE)+strlen(thread_nvm_store_get_root_path())+1) 00091 #define DEVICE_CONF_STRING_LEN (strlen(DEVICE_CONF_FILE)+strlen(thread_nvm_store_get_root_path())+1) 00092 #define PENDING_CONF_STRING_LEN (strlen(THREAD_NVM_PENDING_CONF_FILE)+strlen(thread_nvm_store_get_root_path())+1) 00093 #define LINK_INFO_STRING_LEN (strlen(LINK_INFO_FILE)+strlen(thread_nvm_store_get_root_path())+1) 00094 #define LEADER_INFO_STRING_LEN (strlen(LEADER_INFO_FILE)+strlen(thread_nvm_store_get_root_path())+1) 00095 00096 00097 thread_nvm_fast_data_t cached_fast_data; 00098 thread_nvm_store_link_info_t cached_link_info = { 00099 .nvm_link_info.short_addr = LINK_INFO_SHORT_ADDR_NOT_SET, 00100 .nvm_link_info.mac = {0, 0, 0, 0, 0, 0, 0, 0}, 00101 .write_delay = LINK_INFO_WRITE_DELAY, 00102 .loaded = false 00103 }; 00104 00105 static const char *thread_nvm_store_get_root_path(void) 00106 { 00107 char *path = ns_file_system_get_root_path(); 00108 if (NULL == path) { 00109 return ""; 00110 } 00111 return path; 00112 } 00113 00114 static int root_path_valid(void) 00115 { 00116 if (NULL == ns_file_system_get_root_path()) { 00117 return 0; 00118 } 00119 int path_len = strlen(thread_nvm_store_get_root_path()); 00120 if (path_len == 0 || path_len > MAX_ROOT_PATH_LEN) { 00121 return 0; 00122 } 00123 return 1; 00124 } 00125 00126 int thread_nvm_store_mleid_rloc_map_write(thread_nvm_mleid_rloc_map *mleid_rloc_map) 00127 { 00128 char lc_data_path[LEADER_INFO_STRING_LEN]; 00129 if (!root_path_valid()) { 00130 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00131 } 00132 thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE); 00133 tr_debug("writing to store rloc mapping info"); 00134 return thread_nvm_store_write(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map), LEADER_INFO_DATA_VERSION); 00135 } 00136 00137 int thread_nvm_store_mleid_rloc_map_read(thread_nvm_mleid_rloc_map *mleid_rloc_map) 00138 { 00139 char lc_data_path[LEADER_INFO_STRING_LEN]; 00140 uint32_t version; 00141 if (NULL == mleid_rloc_map) { 00142 return THREAD_NVM_FILE_PARAMETER_INVALID; 00143 } 00144 if (!root_path_valid()) { 00145 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00146 } 00147 thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE); 00148 00149 int ret = thread_nvm_store_read(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map), &version); 00150 00151 if (THREAD_NVM_FILE_SUCCESS != ret) { 00152 tr_info("Leader data map read failed"); 00153 thread_nvm_store_mleid_rloc_map_remove(); 00154 return ret; 00155 } 00156 00157 if (LEADER_INFO_DATA_VERSION != version) { 00158 tr_info("Leader data map version mismatch %"PRIu32, version); 00159 thread_nvm_store_mleid_rloc_map_remove(); 00160 return THREAD_NVM_FILE_VERSION_WRONG; 00161 } 00162 00163 return ret; 00164 } 00165 00166 int thread_nvm_store_mleid_rloc_map_remove(void) 00167 { 00168 int status; 00169 tr_info("thread_nvm_store_leader_info_remove"); 00170 00171 if (!ns_file_system_get_root_path()) { 00172 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00173 } 00174 00175 char lc_data_path[LEADER_INFO_STRING_LEN]; 00176 thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE); 00177 status = remove(lc_data_path); 00178 if (status != 0) { 00179 return THREAD_NVM_FILE_REMOVE_ERROR; 00180 } 00181 return THREAD_NVM_FILE_SUCCESS; 00182 } 00183 00184 int thread_nvm_store_device_configuration_write(uint8_t *mac_ptr, uint8_t *mleid_ptr) 00185 { 00186 thread_nvm_device_conf_t d_c; 00187 if (!root_path_valid()) { 00188 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00189 } 00190 memcpy(d_c.mac, mac_ptr, sizeof(d_c.mac)); 00191 memcpy(d_c.mle_id, mleid_ptr, sizeof(d_c.mle_id)); 00192 char device_conf_path[DEVICE_CONF_STRING_LEN]; 00193 thread_nvm_store_create_path(device_conf_path, DEVICE_CONF_FILE); 00194 return thread_nvm_store_write(device_conf_path, &d_c, sizeof(thread_nvm_device_conf_t), DEVICE_CONF_VERSION); 00195 } 00196 00197 int thread_nvm_store_device_configuration_read(uint8_t *mac_ptr, uint8_t *mleid_ptr) 00198 { 00199 int ret = THREAD_NVM_FILE_READ_ERROR; 00200 if (!root_path_valid()) { 00201 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00202 } 00203 char device_conf_path[DEVICE_CONF_STRING_LEN]; 00204 thread_nvm_store_create_path(device_conf_path, DEVICE_CONF_FILE); 00205 uint32_t version; 00206 thread_nvm_device_conf_t d_c; 00207 00208 ret = thread_nvm_store_read(device_conf_path, &d_c, sizeof(thread_nvm_device_conf_t), &version); 00209 if (THREAD_NVM_FILE_SUCCESS == ret) { 00210 if (THREAD_NVM_FILE_SUCCESS == ret && DEVICE_CONF_VERSION != version) { 00211 tr_info("fast data version mismatch %"PRIu32, version); 00212 ret = THREAD_NVM_FILE_VERSION_WRONG; 00213 } else { 00214 memcpy(mac_ptr, d_c.mac, sizeof(d_c.mac)); 00215 memcpy(mleid_ptr, d_c.mle_id, sizeof(d_c.mle_id)); 00216 } 00217 } 00218 return ret; 00219 } 00220 00221 int thread_nvm_store_pending_configuration_write(void *data, uint16_t size) 00222 { 00223 char pc_data_path[PENDING_CONF_STRING_LEN]; 00224 if (NULL == data) { 00225 return THREAD_NVM_FILE_PARAMETER_INVALID; 00226 } 00227 if (!root_path_valid()) { 00228 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00229 } 00230 thread_nvm_store_create_path(pc_data_path, THREAD_NVM_PENDING_CONF_FILE); 00231 return thread_nvm_store_write(pc_data_path, data, size, PENDING_CONF_DATA_VERSION); 00232 } 00233 00234 int thread_nvm_store_pending_configuration_read(void *data, uint16_t size) 00235 { 00236 char pc_data_path[PENDING_CONF_STRING_LEN]; 00237 uint32_t version; 00238 if (NULL == data) { 00239 return THREAD_NVM_FILE_PARAMETER_INVALID; 00240 } 00241 if (!root_path_valid()) { 00242 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00243 } 00244 thread_nvm_store_create_path(pc_data_path, THREAD_NVM_PENDING_CONF_FILE); 00245 00246 int ret = thread_nvm_store_read(pc_data_path, data, size, &version); 00247 if (THREAD_NVM_FILE_SUCCESS == ret && PENDING_CONF_DATA_VERSION != version) { 00248 tr_info("Pending configuration version mismatch %"PRIu32, version); 00249 return THREAD_NVM_FILE_VERSION_WRONG; 00250 } 00251 return ret; 00252 } 00253 00254 int thread_nvm_store_active_configuration_write(void *data, uint16_t data_size) 00255 { 00256 char ac_data_path[ACTIVE_CONF_STRING_LEN]; 00257 if (NULL == data) { 00258 return THREAD_NVM_FILE_PARAMETER_INVALID; 00259 } 00260 if (!root_path_valid()) { 00261 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00262 } 00263 00264 thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE); 00265 return thread_nvm_store_write(ac_data_path, data, data_size, ACTIVE_CONF_DATA_VERSION); 00266 } 00267 00268 int thread_nvm_store_active_configuration_read(void *data, uint16_t data_size) 00269 { 00270 char ac_data_path[ACTIVE_CONF_STRING_LEN]; 00271 uint32_t version; 00272 if (NULL == data) { 00273 return THREAD_NVM_FILE_PARAMETER_INVALID; 00274 } 00275 if (!root_path_valid()) { 00276 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00277 } 00278 thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE); 00279 00280 int ret = thread_nvm_store_read(ac_data_path, data, data_size, &version); 00281 if (THREAD_NVM_FILE_SUCCESS == ret && ACTIVE_CONF_DATA_VERSION != version) { 00282 tr_info("active configuration version mismatch %"PRIu32, version); 00283 return THREAD_NVM_FILE_VERSION_WRONG; 00284 } 00285 return ret; 00286 } 00287 00288 int thread_nvm_store_active_configuration_remove(void) 00289 { 00290 if (!root_path_valid()) { 00291 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00292 } 00293 char ac_data_path[ACTIVE_CONF_STRING_LEN]; 00294 thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE); 00295 int status = remove(ac_data_path); 00296 if (status != 0) { 00297 return THREAD_NVM_FILE_REMOVE_ERROR; 00298 } 00299 return THREAD_NVM_FILE_SUCCESS; 00300 } 00301 00302 int thread_nvm_store_pending_configuration_remove(void) 00303 { 00304 if (!root_path_valid()) { 00305 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00306 } 00307 char ac_data_path[PENDING_CONF_STRING_LEN]; 00308 thread_nvm_store_create_path(ac_data_path, THREAD_NVM_PENDING_CONF_FILE); 00309 int status = remove(ac_data_path); 00310 if (status != 0) { 00311 return THREAD_NVM_FILE_REMOVE_ERROR; 00312 } 00313 return THREAD_NVM_FILE_SUCCESS; 00314 } 00315 00316 00317 int thread_nvm_store_seq_counter_write(uint32_t network_seq_counter) 00318 { 00319 int ret = THREAD_NVM_FILE_SUCCESS; 00320 if (cached_fast_data.seq_counter != network_seq_counter) { 00321 ret = thread_nvm_store_all_counters_store(cached_fast_data.mac_frame_counter, cached_fast_data.mle_frame_counter, network_seq_counter); 00322 cached_fast_data.seq_counter = network_seq_counter; 00323 } 00324 return ret; 00325 } 00326 00327 int thread_nvm_store_fast_data_check_and_write(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter) 00328 { 00329 int ret = THREAD_NVM_FILE_SUCCESS; 00330 if (((int)(mac_frame_counter - cached_fast_data.mac_frame_counter) > MAC_FRAME_COUNTER_LIMIT) || 00331 ((int)(mle_frame_counter - cached_fast_data.mle_frame_counter) > MLE_FRAME_COUNTER_LIMIT) || 00332 cached_fast_data.seq_counter != network_seq_counter) { 00333 ret = thread_nvm_store_all_counters_store(mac_frame_counter, mle_frame_counter, network_seq_counter); 00334 cached_fast_data.mac_frame_counter = mac_frame_counter; 00335 cached_fast_data.mle_frame_counter = mle_frame_counter; 00336 cached_fast_data.seq_counter = network_seq_counter; 00337 } 00338 return ret; 00339 } 00340 00341 int thread_nvm_store_fast_data_write_all(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter) 00342 { 00343 int ret; 00344 ret = thread_nvm_store_all_counters_store(mac_frame_counter, mle_frame_counter, network_seq_counter); 00345 cached_fast_data.mac_frame_counter = mac_frame_counter; 00346 cached_fast_data.mle_frame_counter = mle_frame_counter; 00347 cached_fast_data.seq_counter = network_seq_counter; 00348 return ret; 00349 } 00350 00351 int thread_nvm_store_frame_counters_check_and_write(uint32_t mac_frame_counter, uint32_t mle_frame_counter) 00352 { 00353 int ret = THREAD_NVM_FILE_SUCCESS; 00354 if (((int)(mac_frame_counter - cached_fast_data.mac_frame_counter) > MAC_FRAME_COUNTER_LIMIT) || 00355 ((int)(mle_frame_counter - cached_fast_data.mle_frame_counter) > MLE_FRAME_COUNTER_LIMIT)) { 00356 ret = thread_nvm_store_all_counters_store(mac_frame_counter, mle_frame_counter, cached_fast_data.seq_counter); 00357 cached_fast_data.mac_frame_counter = mac_frame_counter; 00358 cached_fast_data.mle_frame_counter = mle_frame_counter; 00359 } 00360 return ret; 00361 } 00362 00363 static int thread_nvm_store_all_counters_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter) 00364 { 00365 thread_nvm_fast_data_t fast_data; 00366 fast_data.mac_frame_counter = mac_frame_counter; 00367 fast_data.mle_frame_counter = mle_frame_counter; 00368 fast_data.seq_counter = network_seq_counter; 00369 if (root_path_valid()) { 00370 return thread_nvm_store_fast_data_save(&fast_data); 00371 } else { 00372 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00373 } 00374 } 00375 00376 int thread_nvm_store_fast_data_write(thread_nvm_fast_data_t *fast_data) 00377 { 00378 cached_fast_data.mac_frame_counter = fast_data->mac_frame_counter; 00379 cached_fast_data.mle_frame_counter = fast_data->mle_frame_counter; 00380 cached_fast_data.seq_counter = fast_data->seq_counter; 00381 00382 if (root_path_valid()) { 00383 return thread_nvm_store_fast_data_save(fast_data); 00384 } else { 00385 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00386 } 00387 } 00388 00389 static void thread_nvm_store_create_path(char *fast_data_path, const char *file_name) 00390 { 00391 strcpy(fast_data_path, thread_nvm_store_get_root_path()); 00392 strcat(fast_data_path, file_name); 00393 } 00394 00395 int thread_nvm_store_fast_data_read(thread_nvm_fast_data_t *fast_data) 00396 { 00397 int ret = THREAD_NVM_FILE_SUCCESS; 00398 00399 if (root_path_valid()) { 00400 char fast_data_path[FAST_DATA_STRING_LEN]; 00401 thread_nvm_store_create_path(fast_data_path, FAST_DATA_FILE); 00402 uint32_t version; 00403 ret = thread_nvm_store_read(fast_data_path, fast_data, sizeof(thread_nvm_fast_data_t), &version); 00404 if (THREAD_NVM_FILE_SUCCESS == ret && FAST_DATA_VERSION != version) { 00405 tr_info("fast data version mismatch %"PRIu32, version); 00406 return THREAD_NVM_FILE_VERSION_WRONG; 00407 } 00408 } else { 00409 fast_data->mac_frame_counter = cached_fast_data.mac_frame_counter; 00410 fast_data->mle_frame_counter = cached_fast_data.mle_frame_counter; 00411 fast_data->seq_counter = cached_fast_data.seq_counter; 00412 } 00413 return ret; 00414 } 00415 00416 static int thread_nvm_store_fast_data_save(thread_nvm_fast_data_t *fast_data_to_set) 00417 { 00418 char fast_data_path[FAST_DATA_STRING_LEN]; 00419 thread_nvm_store_create_path(fast_data_path, FAST_DATA_FILE); 00420 return thread_nvm_store_write(fast_data_path, fast_data_to_set, sizeof(thread_nvm_fast_data_t), FAST_DATA_VERSION); 00421 } 00422 00423 static int thread_nvm_store_write(const char *file_name, void *data, uint32_t data_size, uint32_t version) 00424 { 00425 FILE *fp = fopen(file_name, "w"); 00426 if (fp == NULL) { 00427 tr_error("NVM open error: %s", file_name); 00428 return THREAD_NVM_FILE_CANNOT_OPEN; 00429 } 00430 00431 size_t n_bytes = fwrite(&version, 1, sizeof(uint32_t), fp); 00432 if (n_bytes != sizeof(uint32_t)) { 00433 tr_warning("NVM version write error"); 00434 fclose(fp); 00435 return THREAD_NVM_FILE_WRITE_ERROR; 00436 } 00437 00438 n_bytes = fwrite(data, 1, data_size, fp); 00439 fclose(fp); 00440 if (n_bytes != data_size) { 00441 tr_error("NVM write error %s", file_name); 00442 return THREAD_NVM_FILE_WRITE_ERROR; 00443 } else { 00444 return THREAD_NVM_FILE_SUCCESS; 00445 } 00446 } 00447 00448 // returns 0 when ok 00449 static int thread_nvm_store_read(const char *file_name, void *data, uint32_t data_size, uint32_t *version) 00450 { 00451 FILE *fp = fopen(file_name, "r"); 00452 if (fp == NULL) { 00453 tr_warning("File not found: %s", file_name); 00454 return THREAD_NVM_FILE_CANNOT_OPEN; 00455 } 00456 00457 size_t n_bytes = fread(version, 1, sizeof(uint32_t), fp); 00458 if (n_bytes != sizeof(uint32_t)) { 00459 tr_warning("NVM version read error %s", file_name); 00460 fclose(fp); 00461 return THREAD_NVM_FILE_READ_ERROR; 00462 } 00463 00464 n_bytes = fread(data, 1, data_size, fp); 00465 fclose(fp); 00466 if (n_bytes != data_size) { 00467 tr_error("NVM read error %s", file_name); 00468 return THREAD_NVM_FILE_READ_ERROR; 00469 } else { 00470 return THREAD_NVM_FILE_SUCCESS; // return how many bytes was written. 00471 } 00472 } 00473 00474 int thread_nvm_store_link_info_read(void) 00475 { 00476 nvm_link_info_t nvm_link_info_tmp; 00477 int status; 00478 00479 if (!ns_file_system_get_root_path()) { 00480 if (!memcmp(cached_link_info.nvm_link_info.mac, ADDR_UNSPECIFIED, 8) && 00481 cached_link_info.nvm_link_info.short_addr == LINK_INFO_SHORT_ADDR_NOT_SET) { 00482 tr_info("link info not cached"); 00483 return THREAD_NVM_FILE_READ_ERROR; 00484 } 00485 } 00486 cached_link_info.loaded = true; 00487 char link_info_path[LINK_INFO_STRING_LEN]; 00488 strcpy(link_info_path, thread_nvm_store_get_root_path()); 00489 strcat(link_info_path, LINK_INFO_FILE); 00490 00491 uint32_t version = 0; 00492 status = thread_nvm_store_read(link_info_path, &nvm_link_info_tmp, sizeof(nvm_link_info_t), &version); 00493 00494 if (status != THREAD_NVM_FILE_SUCCESS) { 00495 if (!memcmp(cached_link_info.nvm_link_info.mac, ADDR_UNSPECIFIED, 8) && 00496 cached_link_info.nvm_link_info.short_addr == LINK_INFO_SHORT_ADDR_NOT_SET) { 00497 tr_info("link info not cached and read error %d", status); 00498 cached_link_info.loaded = false; 00499 return THREAD_NVM_FILE_READ_ERROR; 00500 } 00501 return status; 00502 } else if (ACTIVE_CONF_DATA_VERSION != version) { 00503 tr_info("link info version mismatch %"PRIu32, version); 00504 return THREAD_NVM_FILE_VERSION_WRONG; 00505 } 00506 memcpy(cached_link_info.nvm_link_info.mac, nvm_link_info_tmp.mac, 8); 00507 cached_link_info.nvm_link_info.short_addr = nvm_link_info_tmp.short_addr; 00508 tr_info("info read: %s parent short addr: %"PRIu16, trace_array(cached_link_info.nvm_link_info.mac, 8), cached_link_info.nvm_link_info.short_addr); 00509 return THREAD_NVM_FILE_SUCCESS; 00510 } 00511 00512 int thread_nvm_store_link_info_get(uint8_t *parent_mac64, uint16_t *my_short_address) 00513 { 00514 if (!memcmp(cached_link_info.nvm_link_info.mac, ADDR_UNSPECIFIED, 8) && 00515 cached_link_info.nvm_link_info.short_addr == LINK_INFO_SHORT_ADDR_NOT_SET) { 00516 tr_info("thread_nvm_store_link_info_get addr zeros"); 00517 return THREAD_NVM_FILE_READ_ERROR; 00518 } 00519 00520 if (!cached_link_info.loaded) { 00521 return THREAD_NVM_FILE_READ_ERROR; 00522 } 00523 // read data from cache if cached data is available 00524 if (parent_mac64) { 00525 memcpy(parent_mac64, cached_link_info.nvm_link_info.mac, 8); 00526 } 00527 if (my_short_address) { 00528 *my_short_address = cached_link_info.nvm_link_info.short_addr; 00529 } 00530 return THREAD_NVM_FILE_SUCCESS; 00531 } 00532 00533 int thread_nvm_store_link_info_clear(void) 00534 { 00535 int status; 00536 tr_info("thread_nvm_store_link_info_clear"); 00537 memset(cached_link_info.nvm_link_info.mac, 0, 8); 00538 cached_link_info.nvm_link_info.short_addr = LINK_INFO_SHORT_ADDR_NOT_SET; 00539 00540 cached_link_info.loaded = false; 00541 00542 if (!ns_file_system_get_root_path()) { 00543 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00544 } 00545 00546 char link_info_path[LINK_INFO_STRING_LEN]; 00547 strcpy(link_info_path, thread_nvm_store_get_root_path()); 00548 strcat(link_info_path, LINK_INFO_FILE); 00549 00550 status = remove(link_info_path); 00551 00552 if (status != 0) { 00553 return THREAD_NVM_FILE_REMOVE_ERROR; 00554 } 00555 00556 return THREAD_NVM_FILE_SUCCESS; 00557 } 00558 00559 int thread_nvm_store_link_info_write(uint8_t *parent_mac, uint16_t short_addr) 00560 { 00561 //tr_info("write mac: %s parent short addr: %"PRIu16, trace_array(parent_mac, 8), short_addr); 00562 if (parent_mac) { 00563 memcpy(cached_link_info.nvm_link_info.mac, parent_mac, 8); 00564 } else { 00565 memset(cached_link_info.nvm_link_info.mac, 0, 8); 00566 tr_info("setting to zero"); 00567 } 00568 // when router parent is zeros, but my short address is the actual routing address. 00569 cached_link_info.nvm_link_info.short_addr = short_addr; 00570 00571 if (cached_link_info.write_delay == LINK_INFO_WRITE_DONE) { 00572 cached_link_info.write_delay = LINK_INFO_WRITE_DELAY; // delay writing some seconds 00573 } 00574 00575 if (!ns_file_system_get_root_path()) { 00576 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00577 } 00578 00579 return THREAD_NVM_FILE_SUCCESS; 00580 } 00581 00582 static void thread_nvm_store_link_info_delayed_write(uint32_t seconds) 00583 { 00584 if (cached_link_info.write_delay == LINK_INFO_WRITE_DONE) { 00585 return; 00586 } else if (cached_link_info.write_delay > seconds) { 00587 cached_link_info.write_delay -= seconds; 00588 return; 00589 } 00590 cached_link_info.write_delay = LINK_INFO_WRITE_DONE; 00591 00592 if (!ns_file_system_get_root_path()) { 00593 return; 00594 } 00595 00596 char link_info_path[LINK_INFO_STRING_LEN]; 00597 strcpy(link_info_path, thread_nvm_store_get_root_path()); 00598 strcat(link_info_path, LINK_INFO_FILE); 00599 tr_info("link info write parent mac: %s parent short addr: %"PRIu16, trace_array(cached_link_info.nvm_link_info.mac, 8), cached_link_info.nvm_link_info.short_addr); 00600 thread_nvm_store_write(link_info_path, &cached_link_info.nvm_link_info, sizeof(nvm_link_info_t), LINK_INFO_DATA_VERSION); 00601 } 00602 00603 void thread_nvm_store_seconds_timer(uint32_t seconds) 00604 { 00605 thread_nvm_store_link_info_delayed_write(seconds); 00606 }
Generated on Tue Jul 12 2022 13:54:59 by
