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.
thread_nvm_store.c
00001 /* 00002 * Copyright (c) 2017-2018, 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/address.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 int path_len = strlen(thread_nvm_store_get_root_path()); 00119 if(path_len==0 || path_len>MAX_ROOT_PATH_LEN) { 00120 return 0; 00121 } 00122 return 1; 00123 } 00124 00125 int thread_nvm_store_mleid_rloc_map_write(thread_nvm_mleid_rloc_map *mleid_rloc_map) 00126 { 00127 char lc_data_path[LEADER_INFO_STRING_LEN]; 00128 if (!root_path_valid()) { 00129 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00130 } 00131 thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE); 00132 tr_debug("writing to store rloc mapping info"); 00133 return thread_nvm_store_write(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map), LEADER_INFO_DATA_VERSION); 00134 } 00135 00136 int thread_nvm_store_mleid_rloc_map_read(thread_nvm_mleid_rloc_map *mleid_rloc_map) 00137 { 00138 char lc_data_path[LEADER_INFO_STRING_LEN]; 00139 uint32_t version; 00140 if (NULL==mleid_rloc_map) { 00141 return THREAD_NVM_FILE_PARAMETER_INVALID; 00142 } 00143 if (!root_path_valid()) { 00144 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00145 } 00146 thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE); 00147 00148 int ret = thread_nvm_store_read(lc_data_path, mleid_rloc_map, sizeof(thread_nvm_mleid_rloc_map), &version); 00149 00150 if (THREAD_NVM_FILE_SUCCESS!=ret) { 00151 tr_info("Leader data map read failed"); 00152 thread_nvm_store_mleid_rloc_map_remove(); 00153 return ret; 00154 } 00155 00156 if (LEADER_INFO_DATA_VERSION!=version) { 00157 tr_info("Leader data map version mismatch %"PRIu32, version); 00158 thread_nvm_store_mleid_rloc_map_remove(); 00159 return THREAD_NVM_FILE_VERSION_WRONG; 00160 } 00161 00162 return ret; 00163 } 00164 00165 int thread_nvm_store_mleid_rloc_map_remove(void) 00166 { 00167 int status; 00168 tr_info("thread_nvm_store_leader_info_remove"); 00169 00170 if (!ns_file_system_get_root_path()) { 00171 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00172 } 00173 00174 char lc_data_path[LEADER_INFO_STRING_LEN]; 00175 thread_nvm_store_create_path(lc_data_path, LEADER_INFO_FILE); 00176 status = remove(lc_data_path); 00177 if (status != 0) { 00178 return THREAD_NVM_FILE_REMOVE_ERROR; 00179 } 00180 return THREAD_NVM_FILE_SUCCESS; 00181 } 00182 00183 int thread_nvm_store_device_configuration_write(uint8_t *mac_ptr, uint8_t *mleid_ptr) 00184 { 00185 thread_nvm_device_conf_t d_c; 00186 if (!root_path_valid()) { 00187 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00188 } 00189 memcpy(d_c.mac, mac_ptr, sizeof(d_c.mac)); 00190 memcpy(d_c.mle_id, mleid_ptr, sizeof(d_c.mle_id)); 00191 char device_conf_path[DEVICE_CONF_STRING_LEN]; 00192 thread_nvm_store_create_path(device_conf_path, DEVICE_CONF_FILE); 00193 return thread_nvm_store_write(device_conf_path, &d_c, sizeof(thread_nvm_device_conf_t), DEVICE_CONF_VERSION); 00194 } 00195 00196 int thread_nvm_store_device_configuration_read(uint8_t *mac_ptr, uint8_t *mleid_ptr) 00197 { 00198 int ret = THREAD_NVM_FILE_READ_ERROR; 00199 if (!root_path_valid()) { 00200 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00201 } 00202 char device_conf_path[DEVICE_CONF_STRING_LEN]; 00203 thread_nvm_store_create_path(device_conf_path, DEVICE_CONF_FILE); 00204 uint32_t version; 00205 thread_nvm_device_conf_t d_c; 00206 00207 ret = thread_nvm_store_read(device_conf_path, &d_c, sizeof(thread_nvm_device_conf_t), &version); 00208 if(THREAD_NVM_FILE_SUCCESS==ret) { 00209 if (THREAD_NVM_FILE_SUCCESS==ret && DEVICE_CONF_VERSION!=version) { 00210 tr_info("fast data version mismatch %"PRIu32, version); 00211 ret = THREAD_NVM_FILE_VERSION_WRONG; 00212 } 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 return remove(ac_data_path); 00296 } 00297 00298 int thread_nvm_store_pending_configuration_remove(void) 00299 { 00300 if (!root_path_valid()) { 00301 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00302 } 00303 char ac_data_path[PENDING_CONF_STRING_LEN]; 00304 thread_nvm_store_create_path(ac_data_path, THREAD_NVM_PENDING_CONF_FILE); 00305 return remove(ac_data_path); 00306 } 00307 00308 00309 int thread_nvm_store_seq_counter_write(uint32_t network_seq_counter) 00310 { 00311 int ret = THREAD_NVM_FILE_SUCCESS; 00312 if (cached_fast_data.seq_counter!=network_seq_counter) { 00313 ret = thread_nvm_store_all_counters_store(cached_fast_data.mac_frame_counter, cached_fast_data.mle_frame_counter, network_seq_counter); 00314 cached_fast_data.seq_counter=network_seq_counter; 00315 } 00316 return ret; 00317 } 00318 00319 int thread_nvm_store_fast_data_check_and_write(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter) 00320 { 00321 int ret = THREAD_NVM_FILE_SUCCESS; 00322 if( ((int)(mac_frame_counter - cached_fast_data.mac_frame_counter) > MAC_FRAME_COUNTER_LIMIT) || 00323 ((int)(mle_frame_counter - cached_fast_data.mle_frame_counter) > MLE_FRAME_COUNTER_LIMIT) || 00324 cached_fast_data.seq_counter!=network_seq_counter) { 00325 ret = thread_nvm_store_all_counters_store(mac_frame_counter, mle_frame_counter, network_seq_counter); 00326 cached_fast_data.mac_frame_counter = mac_frame_counter; 00327 cached_fast_data.mle_frame_counter = mle_frame_counter; 00328 cached_fast_data.seq_counter=network_seq_counter; 00329 } 00330 return ret; 00331 } 00332 00333 int thread_nvm_store_fast_data_write_all(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter) 00334 { 00335 int ret; 00336 ret = thread_nvm_store_all_counters_store(mac_frame_counter, mle_frame_counter, network_seq_counter); 00337 cached_fast_data.mac_frame_counter = mac_frame_counter; 00338 cached_fast_data.mle_frame_counter = mle_frame_counter; 00339 cached_fast_data.seq_counter=network_seq_counter; 00340 return ret; 00341 } 00342 00343 int thread_nvm_store_frame_counters_check_and_write(uint32_t mac_frame_counter, uint32_t mle_frame_counter) 00344 { 00345 int ret = THREAD_NVM_FILE_SUCCESS; 00346 if( ((int)(mac_frame_counter - cached_fast_data.mac_frame_counter) > MAC_FRAME_COUNTER_LIMIT) || 00347 ((int)(mle_frame_counter - cached_fast_data.mle_frame_counter) > MLE_FRAME_COUNTER_LIMIT)) { 00348 ret = thread_nvm_store_all_counters_store(mac_frame_counter, mle_frame_counter, cached_fast_data.seq_counter); 00349 cached_fast_data.mac_frame_counter = mac_frame_counter; 00350 cached_fast_data.mle_frame_counter = mle_frame_counter; 00351 } 00352 return ret; 00353 } 00354 00355 static int thread_nvm_store_all_counters_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter) 00356 { 00357 thread_nvm_fast_data_t fast_data; 00358 fast_data.mac_frame_counter = mac_frame_counter; 00359 fast_data.mle_frame_counter = mle_frame_counter; 00360 fast_data.seq_counter = network_seq_counter; 00361 if (root_path_valid()) { 00362 return thread_nvm_store_fast_data_save(&fast_data); 00363 } 00364 else{ 00365 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00366 } 00367 } 00368 00369 int thread_nvm_store_fast_data_write(thread_nvm_fast_data_t* fast_data) 00370 { 00371 cached_fast_data.mac_frame_counter = fast_data->mac_frame_counter; 00372 cached_fast_data.mle_frame_counter = fast_data->mle_frame_counter; 00373 cached_fast_data.seq_counter = fast_data->seq_counter; 00374 00375 if (root_path_valid()) { 00376 return thread_nvm_store_fast_data_save(fast_data); 00377 } 00378 else { 00379 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00380 } 00381 } 00382 00383 static void thread_nvm_store_create_path(char* fast_data_path, const char* file_name) 00384 { 00385 strcpy(fast_data_path, thread_nvm_store_get_root_path()); 00386 strcat(fast_data_path, file_name); 00387 } 00388 00389 int thread_nvm_store_fast_data_read(thread_nvm_fast_data_t* fast_data) 00390 { 00391 int ret = THREAD_NVM_FILE_SUCCESS; 00392 00393 if (root_path_valid()) { 00394 char fast_data_path[FAST_DATA_STRING_LEN]; 00395 thread_nvm_store_create_path(fast_data_path, FAST_DATA_FILE); 00396 uint32_t version; 00397 ret = thread_nvm_store_read(fast_data_path, fast_data, sizeof(thread_nvm_fast_data_t), &version); 00398 if (THREAD_NVM_FILE_SUCCESS==ret && FAST_DATA_VERSION!=version) { 00399 tr_info("fast data version mismatch %"PRIu32, version); 00400 return THREAD_NVM_FILE_VERSION_WRONG; 00401 } 00402 } 00403 else { 00404 fast_data->mac_frame_counter = cached_fast_data.mac_frame_counter; 00405 fast_data->mle_frame_counter = cached_fast_data.mle_frame_counter; 00406 fast_data->seq_counter = cached_fast_data.seq_counter; 00407 } 00408 return ret; 00409 } 00410 00411 static int thread_nvm_store_fast_data_save(thread_nvm_fast_data_t* fast_data_to_set) 00412 { 00413 char fast_data_path[FAST_DATA_STRING_LEN]; 00414 thread_nvm_store_create_path(fast_data_path, FAST_DATA_FILE); 00415 return thread_nvm_store_write(fast_data_path, fast_data_to_set, sizeof(thread_nvm_fast_data_t), FAST_DATA_VERSION); 00416 } 00417 00418 static int thread_nvm_store_write(const char *file_name, void *data, uint32_t data_size, uint32_t version) 00419 { 00420 FILE *fp = fopen(file_name, "w"); 00421 if(fp == NULL) { 00422 tr_error("NVM open error: %s", file_name); 00423 return THREAD_NVM_FILE_CANNOT_OPEN; 00424 } 00425 00426 size_t n_bytes = fwrite(&version, 1, sizeof(uint32_t), fp); 00427 if (n_bytes!=sizeof(uint32_t)) { 00428 tr_warning("NVM version write error"); 00429 fclose(fp); 00430 return THREAD_NVM_FILE_WRITE_ERROR; 00431 } 00432 00433 n_bytes = fwrite(data, 1, data_size, fp); 00434 fclose(fp); 00435 if (n_bytes!=data_size) { 00436 tr_error("NVM write error %s", file_name); 00437 return THREAD_NVM_FILE_WRITE_ERROR; 00438 } 00439 else { 00440 return THREAD_NVM_FILE_SUCCESS; 00441 } 00442 } 00443 00444 // returns 0 when ok 00445 static int thread_nvm_store_read(const char *file_name, void *data, uint32_t data_size, uint32_t *version) 00446 { 00447 FILE *fp = fopen(file_name, "r"); 00448 if(fp == NULL) { 00449 tr_warning("File not found: %s", file_name); 00450 return THREAD_NVM_FILE_CANNOT_OPEN; 00451 } 00452 00453 size_t n_bytes = fread(version, 1, sizeof(uint32_t), fp); 00454 if (n_bytes!=sizeof(uint32_t)) { 00455 tr_warning("NVM version read error %s", file_name); 00456 fclose(fp); 00457 return THREAD_NVM_FILE_READ_ERROR; 00458 } 00459 00460 n_bytes = fread(data, 1, data_size, fp); 00461 fclose(fp); 00462 if (n_bytes!=data_size) { 00463 tr_error("NVM read error %s", file_name); 00464 return THREAD_NVM_FILE_READ_ERROR; 00465 } 00466 else { 00467 return THREAD_NVM_FILE_SUCCESS; // return how many bytes was written. 00468 } 00469 } 00470 00471 int thread_nvm_store_link_info_read(void) 00472 { 00473 nvm_link_info_t nvm_link_info_tmp; 00474 int status; 00475 00476 if (!ns_file_system_get_root_path()) { 00477 if (!memcmp(cached_link_info.nvm_link_info.mac, ADDR_UNSPECIFIED, 8) && 00478 cached_link_info.nvm_link_info.short_addr == LINK_INFO_SHORT_ADDR_NOT_SET) { 00479 tr_info("link info not cached"); 00480 return THREAD_NVM_FILE_READ_ERROR; 00481 } 00482 } 00483 cached_link_info.loaded = true; 00484 char link_info_path[LINK_INFO_STRING_LEN]; 00485 strcpy(link_info_path, thread_nvm_store_get_root_path()); 00486 strcat(link_info_path, LINK_INFO_FILE); 00487 00488 uint32_t version=0; 00489 status = thread_nvm_store_read(link_info_path, &nvm_link_info_tmp, sizeof(nvm_link_info_t), &version); 00490 00491 if (status != THREAD_NVM_FILE_SUCCESS) { 00492 if (!memcmp(cached_link_info.nvm_link_info.mac, ADDR_UNSPECIFIED, 8) && 00493 cached_link_info.nvm_link_info.short_addr == LINK_INFO_SHORT_ADDR_NOT_SET) { 00494 tr_info("link info not cached and read error %d", status); 00495 cached_link_info.loaded = false; 00496 return THREAD_NVM_FILE_READ_ERROR; 00497 } 00498 return status; 00499 } 00500 else if (ACTIVE_CONF_DATA_VERSION != version) { 00501 tr_info("link info version mismatch %"PRIu32, version); 00502 return THREAD_NVM_FILE_VERSION_WRONG; 00503 } 00504 memcpy(cached_link_info.nvm_link_info.mac, nvm_link_info_tmp.mac, 8); 00505 cached_link_info.nvm_link_info.short_addr = nvm_link_info_tmp.short_addr; 00506 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); 00507 return THREAD_NVM_FILE_SUCCESS; 00508 } 00509 00510 int thread_nvm_store_link_info_get(uint8_t *parent_mac64, uint16_t *my_short_address) 00511 { 00512 if (!memcmp(cached_link_info.nvm_link_info.mac, ADDR_UNSPECIFIED, 8) && 00513 cached_link_info.nvm_link_info.short_addr == LINK_INFO_SHORT_ADDR_NOT_SET) { 00514 tr_info("thread_nvm_store_link_info_get addr zeros"); 00515 return THREAD_NVM_FILE_READ_ERROR; 00516 } 00517 00518 if (!cached_link_info.loaded) { 00519 return THREAD_NVM_FILE_READ_ERROR; 00520 } 00521 // read data from cache if cached data is available 00522 if (parent_mac64) { 00523 memcpy(parent_mac64, cached_link_info.nvm_link_info.mac, 8); 00524 } 00525 if (my_short_address) { 00526 *my_short_address = cached_link_info.nvm_link_info.short_addr; 00527 } 00528 return THREAD_NVM_FILE_SUCCESS; 00529 } 00530 00531 int thread_nvm_store_link_info_clear(void) 00532 { 00533 int status; 00534 tr_info("thread_nvm_store_link_info_clear"); 00535 memset(cached_link_info.nvm_link_info.mac, 0, 8); 00536 cached_link_info.nvm_link_info.short_addr = LINK_INFO_SHORT_ADDR_NOT_SET; 00537 00538 cached_link_info.loaded = false; 00539 00540 if (!ns_file_system_get_root_path()) { 00541 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00542 } 00543 00544 char link_info_path[LINK_INFO_STRING_LEN]; 00545 strcpy(link_info_path, thread_nvm_store_get_root_path()); 00546 strcat(link_info_path, LINK_INFO_FILE); 00547 00548 status = remove(link_info_path); 00549 00550 if (status != 0) { 00551 return THREAD_NVM_FILE_REMOVE_ERROR; 00552 } 00553 00554 return THREAD_NVM_FILE_SUCCESS; 00555 } 00556 00557 int thread_nvm_store_link_info_write(uint8_t *parent_mac, uint16_t short_addr) 00558 { 00559 //tr_info("write mac: %s parent short addr: %"PRIu16, trace_array(parent_mac, 8), short_addr); 00560 if (parent_mac) { 00561 memcpy(cached_link_info.nvm_link_info.mac, parent_mac, 8); 00562 } else { 00563 memset(cached_link_info.nvm_link_info.mac, 0, 8); 00564 tr_info("setting to zero"); 00565 } 00566 // when router parent is zeros, but my short address is the actual routing address. 00567 cached_link_info.nvm_link_info.short_addr = short_addr; 00568 00569 if (cached_link_info.write_delay == LINK_INFO_WRITE_DONE) { 00570 cached_link_info.write_delay = LINK_INFO_WRITE_DELAY; // delay writing some seconds 00571 } 00572 00573 if (!ns_file_system_get_root_path()) { 00574 return THREAD_NVM_FILE_ROOT_PATH_INVALID; 00575 } 00576 00577 return THREAD_NVM_FILE_SUCCESS; 00578 } 00579 00580 static void thread_nvm_store_link_info_delayed_write(uint32_t seconds) 00581 { 00582 if (cached_link_info.write_delay == LINK_INFO_WRITE_DONE) { 00583 return; 00584 } 00585 else if (cached_link_info.write_delay > seconds) { 00586 cached_link_info.write_delay -= seconds; 00587 return; 00588 } 00589 cached_link_info.write_delay = LINK_INFO_WRITE_DONE; 00590 00591 if (!ns_file_system_get_root_path()) { 00592 return; 00593 } 00594 00595 char link_info_path[LINK_INFO_STRING_LEN]; 00596 strcpy(link_info_path, thread_nvm_store_get_root_path()); 00597 strcat(link_info_path, LINK_INFO_FILE); 00598 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); 00599 thread_nvm_store_write(link_info_path, &cached_link_info.nvm_link_info, sizeof(nvm_link_info_t), LINK_INFO_DATA_VERSION); 00600 } 00601 00602 void thread_nvm_store_seconds_timer(uint32_t seconds) 00603 { 00604 thread_nvm_store_link_info_delayed_write(seconds); 00605 }
Generated on Tue Aug 9 2022 00:37:23 by
 1.7.2
 1.7.2