uint32_t DebugProtocolWriter::writeBool(bool v) { writeItem("{}", v); return 0; }
uint32_t DebugProtocolWriter::writeByte(int8_t v) { writeItem("0x{:x}", uint8_t(v)); return 0; }
void TCollection::write( opstream& os ) { os << count << limit << delta; for( ccIndex idx = 0; idx < count; idx++ ) writeItem( items[idx], os ); }
void MXMLHandler::writeItem(mcore::MObject* object) { // startElement switch (object->typeId()) { case TYPEID_GALLERY: { _writer.writeStartElement(ELEM_GALLERY); mcore::MGallery* gallery = object->toGallery(); // name _writer.writeStartElement(NAMESPACE_GALLERY, ELEM_NAME); _writer.writeCharacters(QString(gallery->name().c_str())); _writer.writeEndElement(); // description _writer.writeStartElement(NAMESPACE_GALLERY, ELEM_DESCRIPTION); _writer.writeCharacters(QString(gallery->description().c_str())); _writer.writeEndElement(); // content _writer.writeStartElement(NAMESPACE_GALLERY, ELEM_CONTENT); std::vector<mcore::MObject*>::iterator it; std::vector<mcore::MObject*> base = gallery->content(); for (it = base.begin(); it != base.end(); ++it) writeItem(*it); _writer.writeEndElement(); _writer.writeEndElement(); // ELEM_GALLERY break; } case TYPEID_PHOTO: { _writer.writeStartElement(ELEM_PHOTO); mcore::MPhoto* photo = object->toPhoto(); // name _writer.writeStartElement(NAMESPACE_PHOTO, ELEM_NAME); _writer.writeCharacters(QString(photo->name().c_str())); _writer.writeEndElement(); // description _writer.writeStartElement(NAMESPACE_PHOTO, ELEM_DESCRIPTION); _writer.writeCharacters(QString(photo->description().c_str())); _writer.writeEndElement(); // path _writer.writeStartElement(NAMESPACE_PHOTO, ELEM_PATH); _writer.writeCharacters(QString(photo->path().c_str())); _writer.writeEndElement(); _writer.writeEndElement(); // ELEM_PHOTO break; } case TYPEID_OBJECT: { // this should be only temporary and never really happen // we need to decide to throw an error here or just let it go through _writer.writeStartElement(ELEM_UNDEFINED); _writer.writeEndElement(); break; } } }
/********************************************************************* * @fn initItem * * @brief An NV item is created and initialized with the data passed to the function, if any. * * @param flag - TRUE if the 'buf' parameter contains data for the call to writeItem(). * (i.e. if invoked from osal_nv_item_init() ). * FALSE if writeItem() should just write the header and the 'buf' parameter * is ok to use as a return value of the page number to be cleaned with * COMPACT_PAGE_CLEANUP(). * (i.e. if invoked from osal_nv_write() ). * @param id - Valid NV item Id. * @param len - Item data length. * @param *buf - Pointer to item initalization data. Set to NULL if none. * * @return The OSAL Nv page number if item write and read back checksums ok; * OSAL_NV_PAGE_NULL otherwise. */ static uint8 initItem( uint8 flag, uint16 id, uint16 len, void *buf ) { uint16 sz = OSAL_NV_ITEM_SIZE( len ); uint8 rtrn = OSAL_NV_PAGE_NULL; uint8 cnt = OSAL_NV_PAGES_USED; uint8 pg = pgRes+1; // Set to 1 after the reserve page to even wear across all available pages. do { if (pg >= OSAL_NV_PAGE_BEG+OSAL_NV_PAGES_USED) { pg = OSAL_NV_PAGE_BEG; } if ( pg != pgRes ) { uint8 idx = pg - OSAL_NV_PAGE_BEG; if ( sz <= (OSAL_NV_PAGE_SIZE - pgOff[idx] + pgLost[idx]) ) { break; } } pg++; } while (--cnt); if (cnt) { // Item fits if an old page is compacted. if ( sz > (OSAL_NV_PAGE_SIZE - pgOff[pg - OSAL_NV_PAGE_BEG]) ) { osalNvPgHdr_t pgHdr; /* Prevent excessive re-writes to page header caused by numerous, rapid, & successive * OSAL_Nv interruptions caused by resets. */ HalFlashRead(pg, OSAL_NV_PAGE_HDR_OFFSET, (uint8 *)(&pgHdr), OSAL_NV_PAGE_HDR_SIZE); if ( pgHdr.xfer == OSAL_NV_ERASED_ID ) { // Mark the old page as being in process of compaction. sz = OSAL_NV_ZEROED_ID; writeWordH( pg, OSAL_NV_PG_XFER, (uint8*)(&sz) ); } /* First the old page is compacted, then the new item will be the last one written to what * had been the reserved page. */ if (compactPage( pg, id )) { if ( writeItem( pgRes, id, len, buf, flag ) ) { rtrn = pgRes; } if ( flag == FALSE ) { /* Overload 'buf' as an OUT parameter to pass back to the calling function * the old page to be cleaned up. */ *(uint8 *)buf = pg; } else { /* Safe to do the compacted page cleanup even if writeItem() above failed because the * item does not yet exist since this call with flag==TRUE is from osal_nv_item_init(). */ COMPACT_PAGE_CLEANUP( pg ); } } } else { if ( writeItem( pg, id, len, buf, flag ) ) { rtrn = pg; } } } return rtrn; }
/********************************************************************* * @fn compactPage * * @brief Compacts the page specified. * * @param srcPg - Valid NV page to erase. * @param skipId - Item Id to not compact. * * @return TRUE if valid items from 'srcPg' are successully compacted onto the 'pgRes'; * FALSE otherwise. * Note that on a failure, this could loop, re-erasing the 'pgRes' and re-compacting with * the risk of infinitely looping on HAL flash failure. * Worst case scenario: HAL flash starts failing in general, perhaps low Vdd? * All page compactions will fail which will cause all osal_nv_write() calls to return * NV_OPER_FAILED. * Eventually, all pages in use may also be in the state of "pending compaction" where * the page header member OSAL_NV_PG_XFER is zeroed out. * During this "HAL flash brown-out", the code will run and OTA should work (until low Vdd * causes an actual chip brown-out, of course.) Although no new NV items will be created * or written, the last value written with a return value of SUCCESS can continue to be * read successfully. * If eventually HAL flash starts working again, all of the pages marked as * "pending compaction" may or may not be eventually compacted. But, initNV() will * deterministically clean-up one page pending compaction per power-cycle * (if HAL flash is working.) Nevertheless, one erased reserve page will be maintained * through such a scenario. */ static uint8 compactPage( uint8 srcPg, uint16 skipId ) { uint16 srcOff; uint8 rtrn; // To minimize code size, only check for a clean page here where it's absolutely required. for (srcOff = 0; srcOff < OSAL_NV_PAGE_SIZE; srcOff++) { HalFlashRead(pgRes, srcOff, &rtrn, 1); if (rtrn != OSAL_NV_ERASED) { erasePage(pgRes); return FALSE; } } srcOff = OSAL_NV_PAGE_HDR_SIZE; rtrn = TRUE; while ( srcOff < (OSAL_NV_PAGE_SIZE - OSAL_NV_HDR_SIZE ) ) { osalNvHdr_t hdr; uint16 sz, dstOff = pgOff[pgRes-OSAL_NV_PAGE_BEG]; HalFlashRead(srcPg, srcOff, (uint8 *)(&hdr), OSAL_NV_HDR_SIZE); if ( hdr.id == OSAL_NV_ERASED_ID ) { break; } // Get the actual size in bytes which is the ceiling(hdr.len) sz = OSAL_NV_DATA_SIZE( hdr.len ); if ( sz > (OSAL_NV_PAGE_SIZE - OSAL_NV_HDR_SIZE - srcOff) ) { break; } if ( sz > (OSAL_NV_PAGE_SIZE - OSAL_NV_HDR_SIZE - dstOff) ) { rtrn = FALSE; break; } srcOff += OSAL_NV_HDR_SIZE; if ( (hdr.id != OSAL_NV_ZEROED_ID) && (hdr.id != skipId) ) { if ( hdr.chk == calcChkF( srcPg, srcOff, hdr.len ) ) { /* Prevent excessive re-writes to item header caused by numerous, rapid, & successive * OSAL_Nv interruptions caused by resets. */ if ( hdr.stat == OSAL_NV_ERASED_ID ) { setItem( srcPg, srcOff, eNvXfer ); } if ( writeItem( pgRes, hdr.id, hdr.len, NULL, FALSE ) ) { dstOff += OSAL_NV_HDR_SIZE; xferBuf( srcPg, srcOff, pgRes, dstOff, sz ); // Calculate and write the new checksum. if (hdr.chk == calcChkF(pgRes, dstOff, hdr.len)) { if ( hdr.chk != setChk( pgRes, dstOff, hdr.chk ) ) { rtrn = FALSE; break; } else { hotItemUpdate(pgRes, dstOff, hdr.id); } } else { rtrn = FALSE; break; } } else { rtrn = FALSE; break; } } } srcOff += sz; } if (rtrn == FALSE) { erasePage(pgRes); } else if (skipId == OSAL_NV_ITEM_NULL) { COMPACT_PAGE_CLEANUP(srcPg); } // else invoking function must cleanup. return rtrn; }
int writeItem(char *sid,int var_id,int instance,unsigned char *value, int value_start,int value_length,int flags) { unsigned char packet[8000]; int packet_len=0; struct response_set responses; struct response *r; unsigned char transaction_id[8]; bzero(&responses,sizeof(responses)); if (debug>1) fprintf(stderr,"Writing %d bytes of var %02x/%02x @ 0x%d flags=%d\n", value_length,var_id,instance,value_start,flags); if (!sid) { printf("ERROR:Must use SID when writing values.\n"); return -1; } /* Split long writes into many short writes. (since each write is acknowledged, we don't have to worry about batch mode) */ if (value_length-value_start>MAX_DATA_BYTES) { int o; if (debug) fprintf(stderr,"Writing large value (%d bytes)\n",value_length-value_start); for(o=value_start;o<value_length;o+=MAX_DATA_BYTES) { int bytes=MAX_DATA_BYTES; if (o+bytes>value_length) bytes=value_length-o; if (debug>1) fprintf(stderr," writing [%d,%d)\n",o,o+bytes-1); if (writeItem(sid,var_id,instance,&value[o-value_start],o,bytes, flags|((o>value_start)?SET_FRAGMENT:0))) { if (debug) fprintf(stderr," - writing installment failed\n"); return setReason("Failure during multi-packet write of long-value"); } } printf("OK:%s\n",sid); return 0; } /* Prepare the request packet */ if (packetMakeHeader(packet,8000,&packet_len,NULL)) return -1; bcopy(&packet[8],transaction_id,8); if (packetSetSid(packet,8000,&packet_len,sid)) return -1; if (packetAddVariableWrite(packet,8000,&packet_len,var_id,instance, value,value_start,value_length,flags)) return -1; if (packetFinalise(packet,8000,&packet_len)) return -1; /* XXX should be able to target to the peer holding the SID, if we have it. In any case, we */ if (packetSendRequest(REQ_FIRSTREPLY,packet,packet_len,NONBATCH,transaction_id,&responses)) return -1; r=responses.responses; while(r) { int slen; char sid[SID_SIZE*2+1]; extractSid(r->sid,&slen,sid); switch(r->code) { case ACTION_ERROR: /* We allocate an extra byte to allow us to do this */ r->response[r->response_len]=0; printf("ERROR:%s\n",(char *)r->response); break; case ACTION_OKAY: printf("ERROR:Unexpected OK response\n"); break; case ACTION_DECLINED: printf("DECLINED:%s\n",sid); break; case ACTION_WROTE: /* Supress success messages when writing fragments */ if (!(flags&SET_FRAGMENT)) printf("WROTE:%s\n",sid); break; case ACTION_DATA: printf("ERROR:DATA reponse not implemented\n"); break; case ACTION_GET: printf("ERROR:You cant respond with GET\n"); break; case ACTION_SET: printf("ERROR:You cant respond with SET\n"); break; case ACTION_DEL: printf("ERROR:You cant respond with DEL\n"); break; case ACTION_CREATEHLR: printf("ERROR:You cant respond with CREATEHLR\n"); break; case ACTION_PAD: /* ignore it */ break; case ACTION_EOT: /* ignore it */ break; default: printf("ERROR:Unexpected response code 0x%02x\n",r->code); } fflush(stdout); r=r->next; } return 0; }