Subdirectory provided by Embedded Artists

Dependencies:   DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos mbed-src

Dependents:   lpc4088_displaymodule_hello_world_Sept_2018

Fork of DMSupport by Embedded Artists

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Registry.cpp Source File

Registry.cpp

00001 /*
00002  *  Copyright 2014 Embedded Artists AB
00003  *
00004  *  Licensed under the Apache License, Version 2.0 (the "License");
00005  *  you may not use this file except in compliance with the License.
00006  *  You may obtain a copy of the License at
00007  *
00008  *    http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  *  Unless required by applicable law or agreed to in writing, software
00011  *  distributed under the License is distributed on an "AS IS" BASIS,
00012  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *  See the License for the specific language governing permissions and
00014  *  limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "DMBoard.h"
00019 #include "InternalEEPROM.h"
00020 #include "Registry.h"
00021 
00022 
00023 /******************************************************************************
00024  * Defines and typedefs
00025  *****************************************************************************/
00026 
00027 //Registry::Entry::Entry(const char* key, const char* value, bool free) :
00028 //    _key(key),_value(value),_freeKey(free),_freeValue(free)
00029 //{
00030 //}
00031 //
00032 //Registry::Entry::~Entry()
00033 //{
00034 //  if (_freeKey && _key != NULL) {
00035 //    free((void*)_key);
00036 //    _key = NULL;
00037 //  }
00038 //}
00039 //
00040 //void Registry::Entry::modify(const char* newValue)
00041 //{
00042 //  if (_freeValue && _value != NULL) {
00043 //    free((void*)_value);
00044 //    _value = NULL;
00045 //  }
00046 //  _freeValue = true;
00047 //  _value = newValue;
00048 //}
00049 
00050 /******************************************************************************
00051  * Local variables
00052  *****************************************************************************/
00053 
00054 /******************************************************************************
00055  * Private Class
00056  *****************************************************************************/
00057 
00058 /******************************************************************************
00059  * Private Functions
00060  *****************************************************************************/
00061 
00062 Registry::Registry() : _numEntries(0), _entries(NULL)
00063 {
00064 }
00065 
00066 Registry::~Registry()
00067 {
00068   if (_data != NULL) {
00069     free(_data);
00070     _data = NULL;
00071   }
00072   _numEntries = 0;
00073   _entries = NULL;
00074 }
00075 
00076 Registry::RegistryError Registry::fromEEPROM()
00077 {
00078   // Registry is stored as a header followed by a nuber of key-value
00079   // pairs. Each key and value is a maximum of 31 characters + null
00080   // termination. The header looks like this:
00081   //
00082   // key = 'e','a','r','e','g','\0'
00083   // val = X
00084   // 
00085   // where X is the number of key-value pairs used (one byte).
00086   // The list is compacted so that there are no unused entries in
00087   // the list.
00088   //
00089   _entries = (reg_entry_t*)_data;
00090   _numEntries = _entries[0].val[0];
00091   for (int i = 0; i < NumEntries; i++) {
00092     _modified[i] = false;
00093   }
00094     
00095   // Check header entry
00096   if (strcmp(_entries[0].key, "eareg") == 0) {
00097     
00098     // Check num entries
00099     if (_numEntries < NumEntries) {
00100         
00101       // list is valid, but make sure null termination is ok
00102       // just in case
00103       for (int i = 1; i <= _numEntries; i++) {
00104         _entries[i].key[EntryLen-1] = '\0';
00105         _entries[i].val[EntryLen-1] = '\0';
00106       }
00107       
00108       return Ok;
00109     }
00110   }
00111   
00112   // The list is either corrupt or doesn't exist, create one
00113   memset(_data, 0, NumEntries*sizeof(reg_entry_t));
00114   sprintf(_entries[0].key, "eareg");
00115   _entries[0].val[0] = _numEntries = 0;
00116   _modified[0] = true;
00117   
00118   return Ok;
00119 }
00120 
00121 Registry::RegistryError Registry::toEEPROM()
00122 {
00123   if (_entries[0].val[0] != _numEntries) {
00124     _entries[0].val[0] = _numEntries;
00125     _modified[0] = true;
00126   }
00127   return Ok;
00128 }
00129 
00130 int Registry::find(const char* key)
00131 {
00132   for (int i = 1; i <= _numEntries; i++) {
00133     if (strcmp(key, _entries[i].key) == 0) {
00134       return i;
00135     }
00136   }
00137   return -1;
00138 }
00139 
00140 /******************************************************************************
00141  * Public Functions
00142  *****************************************************************************/
00143 
00144 Registry::RegistryError Registry::load()
00145 {
00146   InternalEEPROM eeprom;
00147   RegistryError err = Ok;
00148 
00149   _mutex.lock();
00150   if (_data != NULL) {
00151     free(_data);
00152     _data = NULL;
00153   }
00154   _numEntries = 0;
00155   _entries = NULL;
00156 
00157   do {
00158     eeprom.init();
00159 
00160     _data = (uint8_t*)malloc(eeprom.memorySize());
00161     if (_data == NULL) {
00162       err = MemoryError;
00163       break;
00164     }
00165     
00166     uint32_t read = eeprom.read(0,_data,eeprom.memorySize());
00167     if (read != eeprom.memorySize()) {
00168       err = EEPROMReadError;
00169       break;
00170     }
00171     
00172     eeprom.powerDown();
00173     
00174     // decode the data
00175     err = fromEEPROM();
00176     if (err != Ok) {
00177       free(_data);
00178       _data = NULL;
00179     }
00180     
00181   } while(0);
00182     
00183   _mutex.unlock();
00184   return err;
00185 }
00186 
00187 Registry::RegistryError Registry::setValue(const char* key, const char* val)
00188 {
00189   RegistryError err = Ok;
00190   _mutex.lock();
00191   int existingIdx = find(key);
00192   if (existingIdx == -1) {
00193     // new value
00194     if (_numEntries < (NumEntries-1)) {
00195       // room for more
00196      if (strlen(key) < EntryLen) {
00197        if (strlen(val) < EntryLen) {
00198          _numEntries++;
00199          strncpy(_entries[_numEntries].key, key, EntryLen-1);
00200          strncpy(_entries[_numEntries].val, val, EntryLen-1);
00201          _modified[_numEntries] = true;
00202        } else {
00203          err = ValueLenError;
00204        }
00205      } else {
00206        err = KeyLenError;
00207      }
00208     } else {
00209       err = RegistryFullError;
00210     }
00211   } else {
00212     // already have value, modify it
00213     if (strlen(val) < EntryLen) {
00214       strncpy(_entries[existingIdx].val, val, EntryLen-1);
00215       _modified[existingIdx] = true;
00216     } else {
00217       err = ValueLenError;
00218     }
00219   }
00220   _mutex.unlock();
00221   return err;
00222 }
00223 
00224 Registry::RegistryError Registry::getValue(const char* key, char** pVal)
00225 {
00226   RegistryError err = Ok;
00227   _mutex.lock();
00228   int existingIdx = find(key);
00229   if (existingIdx == -1) {
00230     *pVal = NULL;
00231     err = NoSuchKeyError;
00232   } else {
00233     *pVal = (char*)malloc(EntryLen);
00234     if (*pVal == NULL) {
00235       err = MemoryError;
00236     } else {
00237       strncpy(*pVal, _entries[existingIdx].val, EntryLen);
00238     }
00239   }
00240   _mutex.unlock();
00241   return err;
00242 }
00243 
00244 Registry::RegistryError Registry::entryAt(int pos, char** pKey, char** pVal)
00245 {
00246   RegistryError err = Ok;
00247   _mutex.lock();
00248   if (pos < 0 || pos >= NumEntries) {
00249     err = InvalidPositionError;
00250   } else {
00251     *pKey = (char*)malloc(EntryLen);
00252     if (*pKey == NULL) {
00253       err = MemoryError;
00254     } else {
00255       strncpy(*pKey, _entries[pos+1].key, EntryLen);
00256       *pVal = (char*)malloc(EntryLen);
00257       if (*pVal == NULL) {
00258         err = MemoryError;
00259         free(*pKey);
00260         *pKey = NULL;
00261       } else {
00262         strncpy(*pVal, _entries[pos+1].val, EntryLen);
00263       }
00264     }
00265   }
00266   _mutex.unlock();
00267   return err;
00268 }
00269 
00270 
00271 Registry::RegistryError Registry::registerListener()
00272 {
00273     return Ok;
00274 }
00275 
00276 Registry::RegistryError Registry::store()
00277 {
00278   InternalEEPROM eeprom;
00279   RegistryError err = Ok;
00280 
00281   _mutex.lock();
00282     
00283   do {
00284     err = toEEPROM();
00285     if (err != Ok) {
00286       break;
00287     }
00288     
00289     eeprom.init();  
00290 
00291     for (int i = 0; i <= _numEntries; i++) {
00292       if (_modified[i]) {
00293         if (eeprom.write(i*EntrySize, (uint8_t*)&_entries[i], EntrySize) != EntrySize) {
00294           err = EEPROMWriteError;
00295           break;
00296         }
00297         _modified[i] = false;
00298       }
00299     }
00300     
00301     eeprom.powerDown();
00302     
00303   } while(0);
00304   
00305   _mutex.unlock();  
00306   
00307   return err;
00308 }