diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 07:24:57 +0000 |
commit | 070852d8604cece0c31f28ff3eb8d21d9ba415fb (patch) | |
tree | 9097175a6a5b8b7e37af9a96269ac0b61a0189cd /decoder/source/ocsd_dcd_tree.cpp | |
parent | Initial commit. (diff) | |
download | libopencsd-upstream.tar.xz libopencsd-upstream.zip |
Adding upstream version 1.3.3.upstream/1.3.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'decoder/source/ocsd_dcd_tree.cpp')
-rw-r--r-- | decoder/source/ocsd_dcd_tree.cpp | 785 |
1 files changed, 785 insertions, 0 deletions
diff --git a/decoder/source/ocsd_dcd_tree.cpp b/decoder/source/ocsd_dcd_tree.cpp new file mode 100644 index 0000000..8e29269 --- /dev/null +++ b/decoder/source/ocsd_dcd_tree.cpp @@ -0,0 +1,785 @@ +/* + * \file ocsd_dcd_tree.cpp + * \brief OpenCSD : + * + * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. + */ + + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "common/ocsd_dcd_tree.h" +#include "common/ocsd_lib_dcd_register.h" +#include "mem_acc/trc_mem_acc_mapper.h" + +/***************************************************************/ +ITraceErrorLog *DecodeTree::s_i_error_logger = &DecodeTree::s_error_logger; +std::list<DecodeTree *> DecodeTree::s_trace_dcd_trees; /**< list of pointers to decode tree objects */ +ocsdDefaultErrorLogger DecodeTree::s_error_logger; /**< The library default error logger */ +TrcIDecode DecodeTree::s_instruction_decoder; /**< default instruction decode library */ + +DecodeTree *DecodeTree::CreateDecodeTree(const ocsd_dcd_tree_src_t src_type, uint32_t formatterCfgFlags) +{ + DecodeTree *dcd_tree = new (std::nothrow) DecodeTree(); + if(dcd_tree != 0) + { + if(dcd_tree->initialise(src_type, formatterCfgFlags)) + { + s_trace_dcd_trees.push_back(dcd_tree); + } + else + { + delete dcd_tree; + dcd_tree = 0; + } + } + return dcd_tree; +} + +void DecodeTree::DestroyDecodeTree(DecodeTree *p_dcd_tree) +{ + std::list<DecodeTree *>::iterator it; + bool bDestroyed = false; + it = s_trace_dcd_trees.begin(); + while(!bDestroyed && (it != s_trace_dcd_trees.end())) + { + if(*it == p_dcd_tree) + { + s_trace_dcd_trees.erase(it); + delete p_dcd_tree; + bDestroyed = true; + } + else + it++; + } +} + +void DecodeTree::setAlternateErrorLogger(ITraceErrorLog *p_error_logger) +{ + if(p_error_logger) + s_i_error_logger = p_error_logger; + else + s_i_error_logger = &s_error_logger; +} + +/***************************************************************/ + +DecodeTree::DecodeTree() : + m_i_instr_decode(&s_instruction_decoder), + m_i_mem_access(0), + m_i_gen_elem_out(0), + m_i_decoder_root(0), + m_frame_deformatter_root(0), + m_decode_elem_iter(0), + m_default_mapper(0), + m_created_mapper(false) +{ + for(int i = 0; i < 0x80; i++) + m_decode_elements[i] = 0; + + // reset the global demux stats. + m_demux_stats.frame_bytes = 0; + m_demux_stats.no_id_bytes = 0; + m_demux_stats.valid_id_bytes = 0; + m_demux_stats.unknown_id_bytes = 0; + m_demux_stats.reserved_id_bytes = 0; +} + +DecodeTree::~DecodeTree() +{ + destroyMemAccMapper(); + for(uint8_t i = 0; i < 0x80; i++) + { + destroyDecodeElement(i); + } + PktPrinterFact::destroyAllPrinters(m_printer_list); + delete m_frame_deformatter_root; +} + + + +ocsd_datapath_resp_t DecodeTree::TraceDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed) +{ + if(m_i_decoder_root) + return m_i_decoder_root->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed); + *numBytesProcessed = 0; + return OCSD_RESP_FATAL_NOT_INIT; +} + +/* set key interfaces - attach / replace on any existing tree components */ +void DecodeTree::setInstrDecoder(IInstrDecode *i_instr_decode) +{ + uint8_t elemID; + DecodeTreeElement *pElem = 0; + + pElem = getFirstElement(elemID); + while(pElem != 0) + { + pElem->getDecoderMngr()->attachInstrDecoder(pElem->getDecoderHandle(),i_instr_decode); + pElem = getNextElement(elemID); + } +} + +void DecodeTree::setMemAccessI(ITargetMemAccess *i_mem_access) +{ + uint8_t elemID; + DecodeTreeElement *pElem = 0; + + pElem = getFirstElement(elemID); + while(pElem != 0) + { + pElem->getDecoderMngr()->attachMemAccessor(pElem->getDecoderHandle(),i_mem_access); + pElem = getNextElement(elemID); + } + m_i_mem_access = i_mem_access; +} + +void DecodeTree::setGenTraceElemOutI(ITrcGenElemIn *i_gen_trace_elem) +{ + uint8_t elemID; + DecodeTreeElement *pElem = 0; + + pElem = getFirstElement(elemID); + while(pElem != 0) + { + pElem->getDecoderMngr()->attachOutputSink(pElem->getDecoderHandle(),i_gen_trace_elem); + pElem = getNextElement(elemID); + } +} + +ocsd_err_t DecodeTree::createMemAccMapper(memacc_mapper_t type /* = MEMACC_MAP_GLOBAL*/ ) +{ + // clean up any old one + destroyMemAccMapper(); + + // make a new one + switch(type) + { + default: + case MEMACC_MAP_GLOBAL: + m_default_mapper = new (std::nothrow) TrcMemAccMapGlobalSpace(); + break; + } + + // set the access interface + if(m_default_mapper) + { + m_created_mapper = true; + setMemAccessI(m_default_mapper); + m_default_mapper->setErrorLog(s_i_error_logger); + } + + return (m_default_mapper != 0) ? OCSD_OK : OCSD_ERR_MEM; +} + +void DecodeTree::setExternMemAccMapper(TrcMemAccMapper* pMapper) +{ + destroyMemAccMapper(); // destroy any existing mapper - if decode tree created it. + m_default_mapper = pMapper; +} + +void DecodeTree::destroyMemAccMapper() +{ + if(m_default_mapper && m_created_mapper) + { + m_default_mapper->RemoveAllAccessors(); + delete m_default_mapper; + m_default_mapper = 0; + m_created_mapper = false; + } +} + +void DecodeTree::logMappedRanges() +{ + if(m_default_mapper) + m_default_mapper->logMappedRanges(); +} + +/* Memory accessor creation - all on default mem accessor using the 0 CSID for global core space. */ +ocsd_err_t DecodeTree::addBufferMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t *p_mem_buffer, const uint32_t mem_length) +{ + if(!hasMemAccMapper()) + return OCSD_ERR_NOT_INIT; + + // need a valid memory buffer, and a least enough bytes for one opcode. + if((p_mem_buffer == 0) || (mem_length < 4)) + return OCSD_ERR_INVALID_PARAM_VAL; + + TrcMemAccessorBase *p_accessor; + ocsd_err_t err = TrcMemAccFactory::CreateBufferAccessor(&p_accessor, address, p_mem_buffer, mem_length); + if(err == OCSD_OK) + { + TrcMemAccBufPtr *pMBuffAcc = dynamic_cast<TrcMemAccBufPtr *>(p_accessor); + if(pMBuffAcc) + { + pMBuffAcc->setMemSpace(mem_space); + err = m_default_mapper->AddAccessor(p_accessor,0); + } + else + err = OCSD_ERR_MEM; // wrong type of object - treat as mem error + + if(err != OCSD_OK) + TrcMemAccFactory::DestroyAccessor(p_accessor); + } + return err; +} + +ocsd_err_t DecodeTree::addBinFileMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const std::string &filepath) +{ + if(!hasMemAccMapper()) + return OCSD_ERR_NOT_INIT; + + if(filepath.length() == 0) + return OCSD_ERR_INVALID_PARAM_VAL; + + TrcMemAccessorBase *p_accessor; + ocsd_err_t err = TrcMemAccFactory::CreateFileAccessor(&p_accessor,filepath,address); + + if(err == OCSD_OK) + { + TrcMemAccessorFile *pAcc = dynamic_cast<TrcMemAccessorFile *>(p_accessor); + if(pAcc) + { + pAcc->setMemSpace(mem_space); + err = m_default_mapper->AddAccessor(pAcc,0); + } + else + err = OCSD_ERR_MEM; // wrong type of object - treat as mem error + + if(err != OCSD_OK) + TrcMemAccFactory::DestroyAccessor(p_accessor); + } + return err; + +} + +ocsd_err_t DecodeTree::addBinFileRegionMemAcc(const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const std::string &filepath) +{ + if(!hasMemAccMapper()) + return OCSD_ERR_NOT_INIT; + + if((region_array == 0) || (num_regions == 0) || (filepath.length() == 0)) + return OCSD_ERR_INVALID_PARAM_VAL; + + TrcMemAccessorBase *p_accessor; + int curr_region_idx = 0; + + // add first region during the creation of the file accessor. + ocsd_err_t err = TrcMemAccFactory::CreateFileAccessor(&p_accessor,filepath,region_array[curr_region_idx].start_address,region_array[curr_region_idx].file_offset, region_array[curr_region_idx].region_size); + if(err == OCSD_OK) + { + TrcMemAccessorFile *pAcc = dynamic_cast<TrcMemAccessorFile *>(p_accessor); + if(pAcc) + { + // add additional regions to the file accessor. + curr_region_idx++; + while(curr_region_idx < num_regions) + { + pAcc->AddOffsetRange(region_array[curr_region_idx].start_address, + region_array[curr_region_idx].region_size, + region_array[curr_region_idx].file_offset); + curr_region_idx++; + } + pAcc->setMemSpace(mem_space); + + // add the accessor to the map. + err = m_default_mapper->AddAccessor(pAcc,0); + } + else + err = OCSD_ERR_MEM; // wrong type of object - treat as mem error + + if(err != OCSD_OK) + TrcMemAccFactory::DestroyAccessor(p_accessor); + } + return err; +} + +ocsd_err_t DecodeTree::updateBinFileRegionMemAcc(const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const std::string &filepath) +{ + if (!hasMemAccMapper()) + return OCSD_ERR_NOT_INIT; + + if ((region_array == 0) || (num_regions == 0) || (filepath.length() == 0)) + return OCSD_ERR_INVALID_PARAM_VAL; + + TrcMemAccessorFile *pAcc = TrcMemAccessorFile::getExistingFileAccessor(filepath); + if (!pAcc) + return OCSD_ERR_INVALID_PARAM_VAL; + + int curr_region_idx = 0; + while (curr_region_idx < num_regions) + { + // check "new" range + if (!pAcc->addrStartOfRange(region_array[curr_region_idx].start_address)) + { + // ensure adds cleanly + if (!pAcc->AddOffsetRange(region_array[curr_region_idx].start_address, + region_array[curr_region_idx].region_size, + region_array[curr_region_idx].file_offset)) + return OCSD_ERR_INVALID_PARAM_VAL; // otherwise bail out + } + curr_region_idx++; + } + return OCSD_OK; +} +ocsd_err_t DecodeTree::initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, + const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context) +{ + if(!hasMemAccMapper()) + return OCSD_ERR_NOT_INIT; + + if(p_cb_func == 0) + return OCSD_ERR_INVALID_PARAM_VAL; + + TrcMemAccessorBase *p_accessor; + ocsd_err_t err = TrcMemAccFactory::CreateCBAccessor(&p_accessor, st_address, en_address, mem_space); + if(err == OCSD_OK) + { + TrcMemAccCB *pCBAcc = dynamic_cast<TrcMemAccCB *>(p_accessor); + if(pCBAcc) + { + if (IDfn) + pCBAcc->setCBIDIfFn((Fn_MemAccID_CB)p_cb_func, p_context); + else + pCBAcc->setCBIfFn((Fn_MemAcc_CB)p_cb_func, p_context); + + err = m_default_mapper->AddAccessor(p_accessor,0); + } + else + err = OCSD_ERR_MEM; // wrong type of object - treat as mem error + + if(err != OCSD_OK) + TrcMemAccFactory::DestroyAccessor(p_accessor); + } + return err; +} + +ocsd_err_t DecodeTree::addCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, Fn_MemAcc_CB p_cb_func, const void *p_context) +{ + return initCallbackMemAcc(st_address, en_address, mem_space, (void *)p_cb_func, false, p_context); +} + +ocsd_err_t DecodeTree::addCallbackIDMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, Fn_MemAccID_CB p_cb_func, const void *p_context) +{ + return initCallbackMemAcc(st_address, en_address, mem_space, (void *)p_cb_func, true, p_context); +} + +ocsd_err_t DecodeTree::removeMemAccByAddress(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space) +{ + if(!hasMemAccMapper()) + return OCSD_ERR_NOT_INIT; + return m_default_mapper->RemoveAccessorByAddress(address,mem_space,0); +} + +ocsd_err_t DecodeTree::createDecoder(const std::string &decoderName, const int createFlags, const CSConfig *pConfig) +{ + ocsd_err_t err = OCSD_OK; + IDecoderMngr *pDecoderMngr = 0; + TraceComponent *pTraceComp = 0; + int crtFlags = createFlags; + + uint8_t CSID = 0; // default for single stream decoder (no deformatter) - we ignore the ID + if(usingFormatter()) + { + CSID = pConfig->getTraceID(); + crtFlags |= OCSD_CREATE_FLG_INST_ID; + } + + // create the decode element to attach to the channel. + if((err = createDecodeElement(CSID)) != OCSD_OK) + return err; + + // get the libary decoder register. + OcsdLibDcdRegister * lib_reg = OcsdLibDcdRegister::getDecoderRegister(); + if(lib_reg == 0) + return OCSD_ERR_NOT_INIT; + + // find the named decoder + if((err = lib_reg->getDecoderMngrByName(decoderName,&pDecoderMngr)) != OCSD_OK) + return err; + + // got the decoder... + if((err = pDecoderMngr->createDecoder(crtFlags,(int)CSID,pConfig,&pTraceComp)) != OCSD_OK) + return err; + + m_decode_elements[CSID]->SetDecoderElement(decoderName, pDecoderMngr, pTraceComp, true); + + // always attach an error logger + if(err == OCSD_OK) + err = pDecoderMngr->attachErrorLogger(pTraceComp,DecodeTree::s_i_error_logger); + + // if we created a packet decoder it may need additional components. + if(crtFlags & OCSD_CREATE_FLG_FULL_DECODER) + { + if(m_i_instr_decode && (err == OCSD_OK)) + err = pDecoderMngr->attachInstrDecoder(pTraceComp,m_i_instr_decode); + + if(err == OCSD_ERR_DCD_INTERFACE_UNUSED) // ignore if instruction decoder refused + err = OCSD_OK; + + if(m_i_mem_access && (err == OCSD_OK)) + err = pDecoderMngr->attachMemAccessor(pTraceComp,m_i_mem_access); + + if(err == OCSD_ERR_DCD_INTERFACE_UNUSED) // ignore if mem accessor refused + err = OCSD_OK; + + if( m_i_gen_elem_out && (err == OCSD_OK)) + err = pDecoderMngr->attachOutputSink(pTraceComp,m_i_gen_elem_out); + } + + // finally attach the packet processor input to the demux output channel + if(err == OCSD_OK) + { + ITrcDataIn *pDataIn = 0; + if((err = pDecoderMngr->getDataInputI(pTraceComp,&pDataIn)) == OCSD_OK) + { + // got the interface -> attach to demux, or direct to input of decode tree + if(usingFormatter()) + err = m_frame_deformatter_root->getIDStreamAttachPt(CSID)->attach(pDataIn); + else + m_i_decoder_root = pDataIn; + } + } + + if(err != OCSD_OK) + { + destroyDecodeElement(CSID); // will destroy decoder as well. + } + return err; +} + +ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID) +{ + ocsd_err_t err = OCSD_OK; + uint8_t localID = CSID; + if(!usingFormatter()) + localID = 0; + + if(usingFormatter() && !OCSD_IS_VALID_CS_SRC_ID(CSID)) + err = OCSD_ERR_INVALID_ID; + else + { + destroyDecodeElement(localID); + } + return err; +} + +ocsd_err_t DecodeTree::getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block) +{ + ocsd_err_t err = OCSD_OK; + TrcPktProcI *pPktProc = getPktProcI(CSID); + if (!pPktProc) + return OCSD_ERR_INVALID_PARAM_VAL; + err = pPktProc->getStatsBlock(p_stats_block); + if (err == OCSD_OK) { + // copy in the global demux stats. + (*p_stats_block)->demux.frame_bytes = m_demux_stats.frame_bytes; + (*p_stats_block)->demux.no_id_bytes = m_demux_stats.no_id_bytes; + (*p_stats_block)->demux.valid_id_bytes = m_demux_stats.valid_id_bytes; + (*p_stats_block)->demux.unknown_id_bytes = m_demux_stats.unknown_id_bytes; + (*p_stats_block)->demux.reserved_id_bytes = m_demux_stats.reserved_id_bytes; + } + return err; +} + +ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID) +{ + TrcPktProcI *pPktProc = getPktProcI(CSID); + if (!pPktProc) + return OCSD_ERR_INVALID_PARAM_VAL; + pPktProc->resetStats(); + + // reset the global demux stats. + m_demux_stats.frame_bytes = 0; + m_demux_stats.no_id_bytes = 0; + m_demux_stats.valid_id_bytes = 0; + m_demux_stats.unknown_id_bytes = 0; + m_demux_stats.reserved_id_bytes = 0; + return OCSD_OK; +} + +TrcPktProcI *DecodeTree::getPktProcI(const uint8_t CSID) +{ + TrcPktProcI *pPktProc = 0; + TraceComponent *pComp, *pAssoc; + DecodeTreeElement *pElem = getDecoderElement(CSID); + + if (pElem) + { + pComp = pElem->getDecoderHandle(); + if (pComp) + { + /* if this is a full decoder then the associated component is the packet processor */ + pAssoc = pComp->getAssocComponent(); + if (pAssoc) + pPktProc = dynamic_cast<TrcPktProcI *>(pAssoc); + else + pPktProc = dynamic_cast<TrcPktProcI *>(pComp); + } + } + return pPktProc; +} + +DecodeTreeElement * DecodeTree::getDecoderElement(const uint8_t CSID) const +{ + DecodeTreeElement *ret_elem = 0; + if(usingFormatter() && OCSD_IS_VALID_CS_SRC_ID(CSID)) + { + ret_elem = m_decode_elements[CSID]; + } + else + ret_elem = m_decode_elements[0]; // ID 0 is used if single leaf tree. + return ret_elem; +} + +DecodeTreeElement *DecodeTree::getFirstElement(uint8_t &elemID) +{ + m_decode_elem_iter = 0; + return getNextElement(elemID); +} + +DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID) +{ + DecodeTreeElement *ret_elem = 0; + + if(m_decode_elem_iter < 0x80) + { + // find a none zero entry or end of range + while((m_decode_elem_iter < 0x80) && (m_decode_elements[m_decode_elem_iter] == 0)) + m_decode_elem_iter++; + + // return entry unless end of range + if(m_decode_elem_iter < 0x80) + { + ret_elem = m_decode_elements[m_decode_elem_iter]; + elemID = m_decode_elem_iter; + m_decode_elem_iter++; + } + } + return ret_elem; +} + +bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCfgFlags) +{ + ocsd_err_t err; + m_dcd_tree_type = type; + if(type == OCSD_TRC_SRC_FRAME_FORMATTED) + { + // frame formatted - we want to create the deformatter and hook it up + m_frame_deformatter_root = new (std::nothrow) TraceFormatterFrameDecoder(); + if(m_frame_deformatter_root) + { + if (m_frame_deformatter_root->Init() != OCSD_OK) + return false; + m_frame_deformatter_root->getErrLogAttachPt()->attach(DecodeTree::s_i_error_logger); + err = m_frame_deformatter_root->Configure(formatterCfgFlags); + if (err != OCSD_OK) + return false; + m_i_decoder_root = dynamic_cast<ITrcDataIn*>(m_frame_deformatter_root); + m_frame_deformatter_root->SetDemuxStatsBlock(&m_demux_stats); + } + else + return false; + } + return true; +} + +void DecodeTree::setSingleRoot(TrcPktProcI *pComp) +{ + m_i_decoder_root = static_cast<ITrcDataIn*>(pComp); +} + +ocsd_err_t DecodeTree::createDecodeElement(const uint8_t CSID) +{ + ocsd_err_t err = OCSD_ERR_INVALID_ID; + if(CSID < 0x80) + { + if(m_decode_elements[CSID] == 0) + { + m_decode_elements[CSID] = new (std::nothrow) DecodeTreeElement(); + if(m_decode_elements[CSID] == 0) + err = OCSD_ERR_MEM; + else + err = OCSD_OK; + } + else + err = OCSD_ERR_ATTACH_TOO_MANY; + } + return err; +} + +void DecodeTree::destroyDecodeElement(const uint8_t CSID) +{ + if(CSID < 0x80) + { + if(m_decode_elements[CSID] != 0) + { + m_decode_elements[CSID]->DestroyElem(); + delete m_decode_elements[CSID]; + m_decode_elements[CSID] = 0; + } + } +} + +ocsd_err_t DecodeTree::setIDFilter(std::vector<uint8_t> &ids) +{ + ocsd_err_t err = OCSD_ERR_DCDT_NO_FORMATTER; + if(usingFormatter()) + { + err = m_frame_deformatter_root->OutputFilterAllIDs(false); + if(err == OCSD_OK) + err = m_frame_deformatter_root->OutputFilterIDs(ids,true); + } + return err; +} + +ocsd_err_t DecodeTree::clearIDFilter() +{ + ocsd_err_t err = OCSD_ERR_DCDT_NO_FORMATTER; + if(usingFormatter()) + { + err = m_frame_deformatter_root->OutputFilterAllIDs(true); + } + return err; +} + +/** add a protocol packet printer */ +ocsd_err_t DecodeTree::addPacketPrinter(uint8_t CSID, bool bMonitor, ItemPrinter **ppPrinter) +{ + ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL; + DecodeTreeElement *pElement = getDecoderElement(CSID); + if (pElement) + { + ocsd_trace_protocol_t protocol = pElement->getProtocol(); + ItemPrinter *pPrinter; + + pPrinter = PktPrinterFact::createProtocolPrinter(getPrinterList(), protocol, CSID); + if (pPrinter) + { + pPrinter->setMessageLogger(getCurrentErrorLogI()->getOutputLogger()); + switch (protocol) + { + case OCSD_PROTOCOL_ETMV4I: + case OCSD_PROTOCOL_ETE: + { + PacketPrinter<EtmV4ITrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV4ITrcPacket> *>(pPrinter); + if (bMonitor) + err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<EtmV4ITrcPacket> *)pTPrinter); + else + err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<EtmV4ITrcPacket> *)pTPrinter); + } + break; + + case OCSD_PROTOCOL_ETMV3: + { + PacketPrinter<EtmV3TrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV3TrcPacket> *>(pPrinter); + if (bMonitor) + err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<EtmV3TrcPacket> *)pTPrinter); + else + err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<EtmV3TrcPacket> *)pTPrinter); + } + break; + + case OCSD_PROTOCOL_PTM: + { + PacketPrinter<PtmTrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<PtmTrcPacket> *>(pPrinter); + if (bMonitor) + err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<PtmTrcPacket> *)pTPrinter); + else + err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<PtmTrcPacket> *)pTPrinter); + } + break; + + case OCSD_PROTOCOL_STM: + { + PacketPrinter<StmTrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<StmTrcPacket> *>(pPrinter); + if (bMonitor) + err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<StmTrcPacket> *)pTPrinter); + else + err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<StmTrcPacket> *)pTPrinter); + } + break; + + default: + err = OCSD_ERR_NO_PROTOCOL; + break; + } + + if (err == OCSD_OK) + { + if (ppPrinter) + *ppPrinter = pPrinter; + } + else + PktPrinterFact::destroyPrinter(getPrinterList(), pPrinter); + } + } + return err; +} + +/** add a raw frame printer */ +ocsd_err_t DecodeTree::addRawFramePrinter(RawFramePrinter **ppPrinter, uint32_t flags) +{ + ocsd_err_t err = OCSD_ERR_MEM; + RawFramePrinter *pPrinter = PktPrinterFact::createRawFramePrinter(getPrinterList()); + if (pPrinter) + { + pPrinter->setMessageLogger((DecodeTree::getCurrentErrorLogI()->getOutputLogger())); + TraceFormatterFrameDecoder *pFrameDecoder = getFrameDeformatter(); + uint32_t cfgFlags = pFrameDecoder->getConfigFlags(); + cfgFlags |= ((uint32_t)flags & (OCSD_DFRMTR_PACKED_RAW_OUT | OCSD_DFRMTR_UNPACKED_RAW_OUT)); + pFrameDecoder->Configure(cfgFlags); + err = pFrameDecoder->getTrcRawFrameAttachPt()->attach(pPrinter); + if (ppPrinter && (err==OCSD_OK)) + *ppPrinter = pPrinter; + } + return err; +} + +/** add a generic element output printer */ +ocsd_err_t DecodeTree::addGenElemPrinter(TrcGenericElementPrinter **ppPrinter) +{ + ocsd_err_t err = OCSD_ERR_MEM; + TrcGenericElementPrinter *pPrinter = PktPrinterFact::createGenElemPrinter(getPrinterList()); + if (pPrinter) + { + pPrinter->setMessageLogger((DecodeTree::getCurrentErrorLogI()->getOutputLogger())); + setGenTraceElemOutI(pPrinter); + err = OCSD_OK; + if (ppPrinter) + *ppPrinter = pPrinter; + } + return err; + +} + +/* End of File ocsd_dcd_tree.cpp */ |