PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Embed:
(wiki syntax)
Show/hide line numbers
PokittoCookie.cpp
Go to the documentation of this file.
00001 /**************************************************************************/ 00002 /*! 00003 @file PokittoCookie.cpp 00004 @author Jonne Valola 00005 00006 @section LICENSE 00007 00008 Software License Agreement (BSD License) 00009 00010 Copyright (c) 2018, Jonne Valola 00011 All rights reserved. 00012 00013 Redistribution and use in source and binary forms, with or without 00014 modification, are permitted provided that the following conditions are met: 00015 1. Redistributions of source code must retain the above copyright 00016 notice, this list of conditions and the following disclaimer. 00017 2. Redistributions in binary form must reproduce the above copyright 00018 notice, this list of conditions and the following disclaimer in the 00019 documentation and/or other materials provided with the distribution. 00020 3. Neither the name of the copyright holders nor the 00021 names of its contributors may be used to endorse or promote products 00022 derived from this software without specific prior written permission. 00023 00024 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 00025 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00026 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 00028 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00029 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00031 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00032 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00033 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 */ 00035 /**************************************************************************/ 00036 00037 #include "Pokitto_settings.h " 00038 #include "Pokitto.h " 00039 #include "PokittoCookie.h " 00040 00041 #ifndef POK_SIM 00042 #else 00043 #include "PokittoSimulator.h" 00044 #endif 00045 00046 using namespace Pokitto; 00047 00048 //char Cookie::_key[SBKEYSIZE]; 00049 //char Cookie::_keyorder; 00050 //bool Cookie::_status; 00051 00052 #define HARDCODEDOFFSET 25 //bypasses Cookie parent instance general data (that does not need to be saved in EEPROM) 00053 00054 Cookie::Cookie() { 00055 _status = false; 00056 _keyorder = SBINVALIDSLOT; 00057 } 00058 00059 int Cookie::initialize() { 00060 //initialize is called from begin() and can be called several times during program run 00061 int datasize = _datasize; 00062 // check if key already exists 00063 _keyorder = exists(_key); 00064 if (_keyorder < SBMAXKEYS) { 00065 // key already exists 00066 // check amount of existing storage reserved for cookie 00067 datasize -= getAssignedBlocks()*SBBLOCKSIZE; 00068 if (datasize<=0) { 00069 // the size of data matches the size requested 00070 // therefore retrieve data from storage 00071 _status = true; //were good to go 00072 loadCookie(); 00073 } else { 00074 // if that does not cover the whole size (maybe a newer version of program, who knows) 00075 // then do not load but reserve more blocks and store a new version 00076 while (datasize>0) { 00077 if(reserveBlock()) datasize -= SBBLOCKSIZE; 00078 else return SBNOTENOUGHBLOCKSFREE; //no space to allocate 00079 } 00080 _status = true; //were good to go 00081 eraseKeytableEntry(_keyorder); 00082 writeKeyToKeytable(_key,_keyorder); // write the key in the key table in EEPROM 00083 saveCookie(); 00084 } 00085 } else { 00086 // new key needed 00087 // check if we have free keyslots 00088 _keyorder = getFreeKeytableSlot(); 00089 if (_keyorder>=SBMAXKEYS) return SBNOMOREKEYS; //no space for key 00090 // check if we have free storage blocks 00091 if (getFreeBlocks()*SBBLOCKSIZE<datasize) return SBNOTENOUGHBLOCKSFREE; //no space to allocate 00092 while (datasize>0) { 00093 //reserve enough blocks for the data until all data can fit 00094 if(reserveBlock()) datasize -= SBBLOCKSIZE; 00095 else return SBNOTENOUGHBLOCKSFREE; //no space to allocate 00096 } 00097 } 00098 _status = true; //were good to go 00099 eraseKeytableEntry(_keyorder); 00100 writeKeyToKeytable(_key,_keyorder); // write the key in the key table in EEPROM 00101 return 0; 00102 } 00103 00104 int Cookie::begin(const char* idkey, int datasize, char* ptr) { 00105 _status=false; 00106 _datasize=datasize-HARDCODEDOFFSET;// warning! hardcoded! sizeof(this); //do not include the data of the parent Cookie instance 00107 _pointer = ptr + HARDCODEDOFFSET;// warning! hardcoded! sizeof(this); //point to the beginning of the inherited instance 00108 char _idkey[8]; 00109 // make _idkey exactly 8 readable characters long 00110 for (int t = 0 ; t < 8 ; t++) _idkey[t]=' '; 00111 for (int t = 0 ; t < 8 ; t++) {if (idkey[t]==0) break; _idkey[t]=idkey[t];} 00112 // clean Keytable of keys with no storage 00113 cleanKeytable(); 00114 memcpy(_key, _idkey, SBKEYSIZE); //store name of key 00115 initialize(); 00116 return 0; //success 00117 } 00118 00119 bool Cookie::saveCookie() { 00120 if (!_status || !_pointer) initialize(); //reinitialize if needed 00121 if (!_status || !_pointer) return false; //return if initialize still failed 00122 char* p = _pointer; 00123 _head=0; 00124 _block=0; 00125 _block=findMyNextBlock(); 00126 for (int i=0; i<_datasize; i++) writeQueue(*p++); 00127 return true; 00128 } 00129 00130 bool Cookie::loadCookie() { 00131 if (!_status || !_pointer) return false; 00132 char* p = _pointer; 00133 _head=0; 00134 _block=0; 00135 _block=findMyNextBlock(); 00136 for (int i=0; i<_datasize; i++) *p++ = readQueue(); 00137 return true; 00138 } 00139 00140 void Cookie::deleteCookie() { 00141 if (!_status) return; 00142 // free all blocks held by Cookie 00143 for (int i=0; i<SBMAXBLOCKS; i++) { 00144 if (isMyBlock(i)) freeBlock(i); 00145 } 00146 // erase Cookie entry from keytable 00147 eraseKeytableEntry(_keyorder); 00148 // set status to deleted 00149 _status = false; 00150 } 00151 00152 int Cookie::exists(const char* idkey) { 00153 for (int i=0; i< SBMAXKEYS; i++) { 00154 #ifndef POK_SIM 00155 if(eeprom_read_byte((uint16_t*)(i*SBKEYSIZE))==idkey[0]) { 00156 int total=0; 00157 for (int j=0; j<SBKEYSIZE;j++) { 00158 if(eeprom_read_byte((uint16_t*)(i*SBKEYSIZE+j))==idkey[j]) total++; 00159 } 00160 if (total==SBKEYSIZE) return i; // return the keyslot number where key exists 00161 } 00162 #endif 00163 } 00164 return SBINVALIDSLOT; //not found 00165 } 00166 00167 int Cookie::getFreeKeytableSlot() { 00168 int freeslot=SBINVALIDSLOT; 00169 for (int i=0; i<SBMAXKEYS; i++) { 00170 #ifndef POK_SIM 00171 if (eeprom_read_byte((uint16_t*)(i*SBKEYSIZE))==0) {freeslot=i; break;} 00172 #endif 00173 } 00174 return freeslot; 00175 } 00176 00177 int Cookie::getAssignedBlocks() { 00178 int assignedblocks=0; 00179 for (int i=0;i<SBMAXBLOCKS;i++) { 00180 if (isMyBlock(i)) assignedblocks++; 00181 } 00182 return assignedblocks; 00183 } 00184 00185 int Cookie::getFreeBlocks() { 00186 int freeblocks=0; 00187 for (int i=0;i<SBMAXBLOCKS;i++) { 00188 if (isFreeBlock(i)) freeblocks++; 00189 } 00190 return freeblocks; 00191 } 00192 00193 bool Cookie::isFreeBlock(int n) { 00194 if (n>=SBMAXBLOCKS) return false; 00195 #ifndef POK_SIM 00196 if (!(eeprom_read_byte((uint16_t*)(SBMAXKEYS*SBKEYSIZE+n))&0x80)) return true; //highest bit 0, its free 00197 #endif 00198 return false; //its not free 00199 } 00200 00201 bool Cookie::isMyBlock(int n) { 00202 if (n>=SBMAXBLOCKS) return false; 00203 if (isFreeBlock(n)) return false; //"free" blocks can not be "reserved" at the same time! 00204 #ifndef POK_SIM 00205 char temp; int address; 00206 address = (SBMAXKEYS*SBKEYSIZE+n); 00207 temp = eeprom_read_byte((uint16_t*)address); 00208 if ((temp&0x7F) ==_keyorder) return true; 00209 #endif 00210 return false; //its not your block 00211 } 00212 00213 bool Cookie::blockIsOwnedBy(int n, int k) { 00214 if (n>=SBMAXBLOCKS) return false; 00215 if (k>=SBMAXKEYS) return false; 00216 if (isFreeBlock(n)) return false; //"free" blocks can not be "owned" by anyone 00217 #ifndef POK_SIM 00218 char temp; int address; 00219 address = (SBMAXKEYS*SBKEYSIZE+n); 00220 temp = eeprom_read_byte((uint16_t*)address); 00221 if ((temp&0x7F) == k) return true; 00222 #endif 00223 return false; //its not your block 00224 } 00225 00226 void Cookie::writeKeyToKeytable(const char* key, int slot) { 00227 for (int i=0; i<SBKEYSIZE; i++) { 00228 #ifndef POK_SIM 00229 if (key[i]) eeprom_write_byte((uint16_t*)(slot*SBKEYSIZE+i),key[i]); 00230 else eeprom_write_byte((uint16_t*)(slot*SBKEYSIZE+i),0); 00231 #endif 00232 } 00233 } 00234 00235 void Cookie::readKeytableEntry(int n, char* answer) { 00236 answer[8]=0; 00237 if (n >= SBMAXKEYS) n=SBMAXKEYS-1; 00238 for (int i=0; i<SBKEYSIZE; i++) { 00239 #ifndef POK_SIM 00240 answer[i] = eeprom_read_byte((uint16_t*)(n*SBKEYSIZE+i)); 00241 #endif 00242 } 00243 } 00244 00245 char Cookie::getBlockTableEntry(int n) { 00246 if (n>=SBMAXBLOCKS) return 0x80; // out of bounds will return a reserved block marker 00247 #ifndef POK_SIM 00248 return eeprom_read_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+n)); 00249 #endif 00250 //return 0x80; 00251 } 00252 00253 void Cookie::readBlock(int n, char* data) { 00254 for (int i=0; i<SBBLOCKSIZE; i++) { 00255 data[i]=0; 00256 #ifndef POK_SIM 00257 if (n < SBMAXBLOCKS) data[i] = eeprom_read_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+SBMAXBLOCKS+n*SBBLOCKSIZE+i)); 00258 #endif 00259 } 00260 } 00261 00262 void Cookie::formatKeytable() { 00263 for (int j=0; j<SBMAXKEYS; j++) { 00264 for (int i=0; i<SBKEYSIZE; i++) { 00265 #ifndef POK_SIM 00266 eeprom_write_byte((uint16_t*)(j*SBKEYSIZE+i),0); 00267 #endif 00268 } 00269 } 00270 } 00271 00272 void Cookie::freeBlock(int n) { 00273 if (n >= SBMAXBLOCKS) return; //out of bounds 00274 #ifndef POK_SIM 00275 // delete entry from blocktable 00276 eeprom_write_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+n),0); 00277 #endif 00278 for (int i=0; i<SBBLOCKSIZE;i++) { 00279 #ifndef POK_SIM 00280 // wipe data in the block 00281 eeprom_write_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+SBMAXBLOCKS+n*SBBLOCKSIZE+i),0); 00282 #endif 00283 } 00284 } 00285 00286 bool Cookie::reserveBlock() { 00287 for (int i=0; i<SBMAXBLOCKS;i++) { 00288 #ifndef POK_SIM 00289 // reserve block from blocktable 00290 if (isFreeBlock(i)) { 00291 //free block found, mark it for us in the blocktable 00292 eeprom_write_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+i),_keyorder | 0x80); 00293 return true; 00294 } 00295 #endif 00296 } 00297 return false; // no free block found 00298 } 00299 00300 void Cookie::eraseKeytableEntry(int n) { 00301 if (n >= SBMAXKEYS) n=SBMAXKEYS-1; 00302 for (int i=0; i<SBKEYSIZE; i++) { 00303 #ifndef POK_SIM 00304 eeprom_write_byte((uint16_t*)(n*SBKEYSIZE+i),0); 00305 #endif 00306 } 00307 } 00308 00309 void Cookie::cleanKeytable() { 00310 //Remove any keys without blocks 00311 for (int entry=0; entry<SBMAXKEYS; entry++) { 00312 if (eeprom_read_byte((uint16_t*)(entry*SBKEYSIZE))) { 00313 bool isEmpty=true; 00314 for (int block=0; block<SBMAXBLOCKS; block++) if (blockIsOwnedBy(block,entry)) {isEmpty=false;break;} 00315 //this entry has no blocks reserved, so lets clean it from the keytable 00316 if (isEmpty) eraseKeytableEntry(entry); 00317 } 00318 } 00319 for (int block=0;block<SBMAXBLOCKS;block++) { 00320 int blockentry = eeprom_read_byte((uint16_t*)(SBMAXKEYS*SBKEYSIZE+block)); 00321 if (blockentry&0x80) { 00322 blockentry &= 0x7F; 00323 bool isEmpty=true; 00324 for (int key=0;key<SBMAXKEYS;key++) { 00325 if (eeprom_read_byte((uint16_t*)(key*SBKEYSIZE))) {isEmpty=false;break;} 00326 } 00327 if (isEmpty) eeprom_write_byte((uint16_t*)(SBMAXKEYS*SBKEYSIZE+block),0); 00328 } 00329 } 00330 } 00331 00332 char Cookie::readQueue() { 00333 char data=0; 00334 #ifndef POK_SIM 00335 int address; 00336 address = SBMAXKEYS*SBKEYSIZE+SBMAXBLOCKS+SBBLOCKSIZE*_block+_head%SBBLOCKSIZE; 00337 data=eeprom_read_byte((uint16_t*)address); 00338 #endif 00339 _head++; 00340 if (_head%SBBLOCKSIZE==0 && _head) { 00341 _block++; 00342 _block=findMyNextBlock(); 00343 } 00344 return data; 00345 } 00346 00347 void Cookie::writeQueue(char data) { 00348 #ifndef POK_SIM 00349 eeprom_write_byte((uint16_t*)(SBMAXKEYS*SBKEYSIZE+SBMAXBLOCKS+SBBLOCKSIZE*_block+_head%SBBLOCKSIZE),data); 00350 #endif 00351 _head++; 00352 if (_head%SBBLOCKSIZE==0 && _head) { 00353 _block++; 00354 _block=findMyNextBlock(); 00355 } 00356 } 00357 00358 int Cookie::findMyNextBlock() { 00359 if (!_status) return SBINVALIDBLOCK; 00360 for (int i=_block; i<SBMAXBLOCKS;i++) if (isMyBlock(i)) return i; 00361 return SBINVALIDBLOCK; 00362 } 00363 00364 00365
Generated on Tue Jul 12 2022 21:03:51 by 1.7.2