/* $License: Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved. See included License.txt for License information. $ */ /** * @defgroup Storage_Manager storage_manager * @brief Motion Library - Stores Data for functions. * * * @{ * @file storage_manager.c * @brief Load and Store Manager. */ #include "storage_manager.h" #include "log.h" #include "ml_math_func.h" #include "mlmath.h" /* Must be changed if the format of storage changes */ #define DEFAULT_KEY 29681 typedef inv_error_t (*load_func_t)(const unsigned char *data); typedef inv_error_t (*save_func_t)(unsigned char *data); /** Max number of entites that can be stored */ #define NUM_STORAGE_BOXES 20 struct data_header_t { long size; uint32_t checksum; unsigned int key; }; struct data_storage_t { int num; /**< Number of differnt save entities */ size_t total_size; /**< Size in bytes to store non volatile data */ load_func_t load[NUM_STORAGE_BOXES]; /**< Callback to load data */ save_func_t save[NUM_STORAGE_BOXES]; /**< Callback to save data */ struct data_header_t hd[NUM_STORAGE_BOXES]; /**< Header info for each entity */ }; static struct data_storage_t ds; /** Should be called once before using any of the storage methods. Typically * called first by inv_init_mpl().*/ void inv_init_storage_manager() { memset(&ds, 0, sizeof(ds)); ds.total_size = sizeof(struct data_header_t); } /** Used to register your mechanism to load and store non-volative data. This should typical be * called during the enable function for your feature. * @param[in] load_func function pointer you will use to receive data that was stored for you. * @param[in] save_func function pointer you will use to save any data you want saved to * non-volatile memory between runs. * @param[in] size The size in bytes of the amount of data you want loaded and saved. * @param[in] key The key associated with your data type should be unique across MPL. * The key should change when your type of data for storage changes. * @return Returns INV_SUCCESS if successful or an error code if not. */ inv_error_t inv_register_load_store(inv_error_t (*load_func)(const unsigned char *data), inv_error_t (*save_func)(unsigned char *data), size_t size, unsigned int key) { int kk; // Check if this has been registered already for (kk=0; kk= NUM_STORAGE_BOXES) { return INV_ERROR_INVALID_PARAMETER; } // Add to list ds.hd[ds.num].key = key; ds.hd[ds.num].size = size; ds.load[ds.num] = load_func; ds.save[ds.num] = save_func; ds.total_size += size + sizeof(struct data_header_t); ds.num++; return INV_SUCCESS; } /** Returns the memory size needed to perform a store * @param[out] size Size in bytes of memory needed to store. * @return Returns INV_SUCCESS if successful or an error code if not. */ inv_error_t inv_get_mpl_state_size(size_t *size) { *size = ds.total_size; return INV_SUCCESS; } /** @internal * Finds key in ds.hd[] array and returns location * @return location where key exists in array, -1 if not found. */ static int inv_find_entry(unsigned int key) { int kk; for (kk=0; kkkey != DEFAULT_KEY) return INV_ERROR_CALIBRATION_LOAD; // Key changed or data corruption len = MIN(hd->size, len); len = hd->size; len -= sizeof(struct data_header_t); data += sizeof(struct data_header_t); checksum = inv_checksum(data, len); if (checksum != hd->checksum) return INV_ERROR_CALIBRATION_LOAD; // Data corruption while (len > (long)sizeof(struct data_header_t)) { hd = (struct data_header_t *)data; entry = inv_find_entry(hd->key); data += sizeof(struct data_header_t); len -= sizeof(struct data_header_t); if (entry >= 0 && len >= hd->size) { if (hd->size == ds.hd[entry].size) { checksum = inv_checksum(data, hd->size); if (checksum == hd->checksum) { ds.load[entry](data); } else { return INV_ERROR_CALIBRATION_LOAD; } } } len -= hd->size; if (len >= 0) data = data + hd->size; } return INV_SUCCESS; } /** This function fills up a block of memory to be stored in non-volatile memory. * @param[out] data Place to store data, size of sz, must be at least size * returned by inv_get_mpl_state_size() * @param[in] sz Size of data. * @return Returns INV_SUCCESS if successful or an error code if not. */ inv_error_t inv_save_mpl_states(unsigned char *data, size_t sz) { unsigned char *cur; int kk; struct data_header_t *hd; if (sz >= ds.total_size) { cur = data + sizeof(struct data_header_t); for (kk = 0; kk < ds.num; ++kk) { hd = (struct data_header_t *)cur; cur += sizeof(struct data_header_t); ds.save[kk](cur); hd->checksum = inv_checksum(cur, ds.hd[kk].size); hd->size = ds.hd[kk].size; hd->key = ds.hd[kk].key; cur += ds.hd[kk].size; } } else { return INV_ERROR_CALIBRATION_LOAD; } hd = (struct data_header_t *)data; hd->checksum = inv_checksum(data + sizeof(struct data_header_t), ds.total_size - sizeof(struct data_header_t)); hd->key = DEFAULT_KEY; hd->size = ds.total_size; return INV_SUCCESS; } /** * @} */