1*c120c564SAndrew Turner /* 2*c120c564SAndrew Turner * \file ocsd_dcd_tree.cpp 3*c120c564SAndrew Turner * \brief OpenCSD : 4*c120c564SAndrew Turner * 5*c120c564SAndrew Turner * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved. 6*c120c564SAndrew Turner */ 7*c120c564SAndrew Turner 8*c120c564SAndrew Turner 9*c120c564SAndrew Turner /* 10*c120c564SAndrew Turner * Redistribution and use in source and binary forms, with or without modification, 11*c120c564SAndrew Turner * are permitted provided that the following conditions are met: 12*c120c564SAndrew Turner * 13*c120c564SAndrew Turner * 1. Redistributions of source code must retain the above copyright notice, 14*c120c564SAndrew Turner * this list of conditions and the following disclaimer. 15*c120c564SAndrew Turner * 16*c120c564SAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright notice, 17*c120c564SAndrew Turner * this list of conditions and the following disclaimer in the documentation 18*c120c564SAndrew Turner * and/or other materials provided with the distribution. 19*c120c564SAndrew Turner * 20*c120c564SAndrew Turner * 3. Neither the name of the copyright holder nor the names of its contributors 21*c120c564SAndrew Turner * may be used to endorse or promote products derived from this software without 22*c120c564SAndrew Turner * specific prior written permission. 23*c120c564SAndrew Turner * 24*c120c564SAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 25*c120c564SAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26*c120c564SAndrew Turner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27*c120c564SAndrew Turner * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28*c120c564SAndrew Turner * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29*c120c564SAndrew Turner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30*c120c564SAndrew Turner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31*c120c564SAndrew Turner * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32*c120c564SAndrew Turner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33*c120c564SAndrew Turner * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34*c120c564SAndrew Turner */ 35*c120c564SAndrew Turner 36*c120c564SAndrew Turner #include "common/ocsd_dcd_tree.h" 37*c120c564SAndrew Turner #include "common/ocsd_lib_dcd_register.h" 38*c120c564SAndrew Turner #include "mem_acc/trc_mem_acc_mapper.h" 39*c120c564SAndrew Turner 40*c120c564SAndrew Turner /***************************************************************/ 41*c120c564SAndrew Turner ITraceErrorLog *DecodeTree::s_i_error_logger = &DecodeTree::s_error_logger; 42*c120c564SAndrew Turner std::list<DecodeTree *> DecodeTree::s_trace_dcd_trees; /**< list of pointers to decode tree objects */ 43*c120c564SAndrew Turner ocsdDefaultErrorLogger DecodeTree::s_error_logger; /**< The library default error logger */ 44*c120c564SAndrew Turner TrcIDecode DecodeTree::s_instruction_decoder; /**< default instruction decode library */ 45*c120c564SAndrew Turner 46*c120c564SAndrew Turner DecodeTree *DecodeTree::CreateDecodeTree(const ocsd_dcd_tree_src_t src_type, uint32_t formatterCfgFlags) 47*c120c564SAndrew Turner { 48*c120c564SAndrew Turner DecodeTree *dcd_tree = new (std::nothrow) DecodeTree(); 49*c120c564SAndrew Turner if(dcd_tree != 0) 50*c120c564SAndrew Turner { 51*c120c564SAndrew Turner if(dcd_tree->initialise(src_type, formatterCfgFlags)) 52*c120c564SAndrew Turner { 53*c120c564SAndrew Turner s_trace_dcd_trees.push_back(dcd_tree); 54*c120c564SAndrew Turner } 55*c120c564SAndrew Turner else 56*c120c564SAndrew Turner { 57*c120c564SAndrew Turner delete dcd_tree; 58*c120c564SAndrew Turner dcd_tree = 0; 59*c120c564SAndrew Turner } 60*c120c564SAndrew Turner } 61*c120c564SAndrew Turner return dcd_tree; 62*c120c564SAndrew Turner } 63*c120c564SAndrew Turner 64*c120c564SAndrew Turner void DecodeTree::DestroyDecodeTree(DecodeTree *p_dcd_tree) 65*c120c564SAndrew Turner { 66*c120c564SAndrew Turner std::list<DecodeTree *>::iterator it; 67*c120c564SAndrew Turner bool bDestroyed = false; 68*c120c564SAndrew Turner it = s_trace_dcd_trees.begin(); 69*c120c564SAndrew Turner while(!bDestroyed && (it != s_trace_dcd_trees.end())) 70*c120c564SAndrew Turner { 71*c120c564SAndrew Turner if(*it == p_dcd_tree) 72*c120c564SAndrew Turner { 73*c120c564SAndrew Turner s_trace_dcd_trees.erase(it); 74*c120c564SAndrew Turner delete p_dcd_tree; 75*c120c564SAndrew Turner bDestroyed = true; 76*c120c564SAndrew Turner } 77*c120c564SAndrew Turner else 78*c120c564SAndrew Turner it++; 79*c120c564SAndrew Turner } 80*c120c564SAndrew Turner } 81*c120c564SAndrew Turner 82*c120c564SAndrew Turner void DecodeTree::setAlternateErrorLogger(ITraceErrorLog *p_error_logger) 83*c120c564SAndrew Turner { 84*c120c564SAndrew Turner if(p_error_logger) 85*c120c564SAndrew Turner s_i_error_logger = p_error_logger; 86*c120c564SAndrew Turner else 87*c120c564SAndrew Turner s_i_error_logger = &s_error_logger; 88*c120c564SAndrew Turner } 89*c120c564SAndrew Turner 90*c120c564SAndrew Turner /***************************************************************/ 91*c120c564SAndrew Turner 92*c120c564SAndrew Turner DecodeTree::DecodeTree() : 93*c120c564SAndrew Turner m_i_instr_decode(&s_instruction_decoder), 94*c120c564SAndrew Turner m_i_mem_access(0), 95*c120c564SAndrew Turner m_i_gen_elem_out(0), 96*c120c564SAndrew Turner m_i_decoder_root(0), 97*c120c564SAndrew Turner m_frame_deformatter_root(0), 98*c120c564SAndrew Turner m_decode_elem_iter(0), 99*c120c564SAndrew Turner m_default_mapper(0), 100*c120c564SAndrew Turner m_created_mapper(false) 101*c120c564SAndrew Turner { 102*c120c564SAndrew Turner for(int i = 0; i < 0x80; i++) 103*c120c564SAndrew Turner m_decode_elements[i] = 0; 104*c120c564SAndrew Turner } 105*c120c564SAndrew Turner 106*c120c564SAndrew Turner DecodeTree::~DecodeTree() 107*c120c564SAndrew Turner { 108*c120c564SAndrew Turner destroyMemAccMapper(); 109*c120c564SAndrew Turner for(uint8_t i = 0; i < 0x80; i++) 110*c120c564SAndrew Turner { 111*c120c564SAndrew Turner destroyDecodeElement(i); 112*c120c564SAndrew Turner } 113*c120c564SAndrew Turner PktPrinterFact::destroyAllPrinters(m_printer_list); 114*c120c564SAndrew Turner } 115*c120c564SAndrew Turner 116*c120c564SAndrew Turner 117*c120c564SAndrew Turner 118*c120c564SAndrew Turner ocsd_datapath_resp_t DecodeTree::TraceDataIn( const ocsd_datapath_op_t op, 119*c120c564SAndrew Turner const ocsd_trc_index_t index, 120*c120c564SAndrew Turner const uint32_t dataBlockSize, 121*c120c564SAndrew Turner const uint8_t *pDataBlock, 122*c120c564SAndrew Turner uint32_t *numBytesProcessed) 123*c120c564SAndrew Turner { 124*c120c564SAndrew Turner if(m_i_decoder_root) 125*c120c564SAndrew Turner return m_i_decoder_root->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed); 126*c120c564SAndrew Turner *numBytesProcessed = 0; 127*c120c564SAndrew Turner return OCSD_RESP_FATAL_NOT_INIT; 128*c120c564SAndrew Turner } 129*c120c564SAndrew Turner 130*c120c564SAndrew Turner /* set key interfaces - attach / replace on any existing tree components */ 131*c120c564SAndrew Turner void DecodeTree::setInstrDecoder(IInstrDecode *i_instr_decode) 132*c120c564SAndrew Turner { 133*c120c564SAndrew Turner uint8_t elemID; 134*c120c564SAndrew Turner DecodeTreeElement *pElem = 0; 135*c120c564SAndrew Turner 136*c120c564SAndrew Turner pElem = getFirstElement(elemID); 137*c120c564SAndrew Turner while(pElem != 0) 138*c120c564SAndrew Turner { 139*c120c564SAndrew Turner pElem->getDecoderMngr()->attachInstrDecoder(pElem->getDecoderHandle(),i_instr_decode); 140*c120c564SAndrew Turner pElem = getNextElement(elemID); 141*c120c564SAndrew Turner } 142*c120c564SAndrew Turner } 143*c120c564SAndrew Turner 144*c120c564SAndrew Turner void DecodeTree::setMemAccessI(ITargetMemAccess *i_mem_access) 145*c120c564SAndrew Turner { 146*c120c564SAndrew Turner uint8_t elemID; 147*c120c564SAndrew Turner DecodeTreeElement *pElem = 0; 148*c120c564SAndrew Turner 149*c120c564SAndrew Turner pElem = getFirstElement(elemID); 150*c120c564SAndrew Turner while(pElem != 0) 151*c120c564SAndrew Turner { 152*c120c564SAndrew Turner pElem->getDecoderMngr()->attachMemAccessor(pElem->getDecoderHandle(),i_mem_access); 153*c120c564SAndrew Turner pElem = getNextElement(elemID); 154*c120c564SAndrew Turner } 155*c120c564SAndrew Turner m_i_mem_access = i_mem_access; 156*c120c564SAndrew Turner } 157*c120c564SAndrew Turner 158*c120c564SAndrew Turner void DecodeTree::setGenTraceElemOutI(ITrcGenElemIn *i_gen_trace_elem) 159*c120c564SAndrew Turner { 160*c120c564SAndrew Turner uint8_t elemID; 161*c120c564SAndrew Turner DecodeTreeElement *pElem = 0; 162*c120c564SAndrew Turner 163*c120c564SAndrew Turner pElem = getFirstElement(elemID); 164*c120c564SAndrew Turner while(pElem != 0) 165*c120c564SAndrew Turner { 166*c120c564SAndrew Turner pElem->getDecoderMngr()->attachOutputSink(pElem->getDecoderHandle(),i_gen_trace_elem); 167*c120c564SAndrew Turner pElem = getNextElement(elemID); 168*c120c564SAndrew Turner } 169*c120c564SAndrew Turner } 170*c120c564SAndrew Turner 171*c120c564SAndrew Turner ocsd_err_t DecodeTree::createMemAccMapper(memacc_mapper_t type /* = MEMACC_MAP_GLOBAL*/ ) 172*c120c564SAndrew Turner { 173*c120c564SAndrew Turner // clean up any old one 174*c120c564SAndrew Turner destroyMemAccMapper(); 175*c120c564SAndrew Turner 176*c120c564SAndrew Turner // make a new one 177*c120c564SAndrew Turner switch(type) 178*c120c564SAndrew Turner { 179*c120c564SAndrew Turner default: 180*c120c564SAndrew Turner case MEMACC_MAP_GLOBAL: 181*c120c564SAndrew Turner m_default_mapper = new (std::nothrow) TrcMemAccMapGlobalSpace(); 182*c120c564SAndrew Turner break; 183*c120c564SAndrew Turner } 184*c120c564SAndrew Turner 185*c120c564SAndrew Turner // set the access interface 186*c120c564SAndrew Turner if(m_default_mapper) 187*c120c564SAndrew Turner { 188*c120c564SAndrew Turner m_created_mapper = true; 189*c120c564SAndrew Turner setMemAccessI(m_default_mapper); 190*c120c564SAndrew Turner m_default_mapper->setErrorLog(s_i_error_logger); 191*c120c564SAndrew Turner } 192*c120c564SAndrew Turner 193*c120c564SAndrew Turner return (m_default_mapper != 0) ? OCSD_OK : OCSD_ERR_MEM; 194*c120c564SAndrew Turner } 195*c120c564SAndrew Turner 196*c120c564SAndrew Turner void DecodeTree::setExternMemAccMapper(TrcMemAccMapper* pMapper) 197*c120c564SAndrew Turner { 198*c120c564SAndrew Turner destroyMemAccMapper(); // destroy any existing mapper - if decode tree created it. 199*c120c564SAndrew Turner m_default_mapper = pMapper; 200*c120c564SAndrew Turner } 201*c120c564SAndrew Turner 202*c120c564SAndrew Turner void DecodeTree::destroyMemAccMapper() 203*c120c564SAndrew Turner { 204*c120c564SAndrew Turner if(m_default_mapper && m_created_mapper) 205*c120c564SAndrew Turner { 206*c120c564SAndrew Turner m_default_mapper->RemoveAllAccessors(); 207*c120c564SAndrew Turner delete m_default_mapper; 208*c120c564SAndrew Turner m_default_mapper = 0; 209*c120c564SAndrew Turner m_created_mapper = false; 210*c120c564SAndrew Turner } 211*c120c564SAndrew Turner } 212*c120c564SAndrew Turner 213*c120c564SAndrew Turner void DecodeTree::logMappedRanges() 214*c120c564SAndrew Turner { 215*c120c564SAndrew Turner if(m_default_mapper) 216*c120c564SAndrew Turner m_default_mapper->logMappedRanges(); 217*c120c564SAndrew Turner } 218*c120c564SAndrew Turner 219*c120c564SAndrew Turner /* Memory accessor creation - all on default mem accessor using the 0 CSID for global core space. */ 220*c120c564SAndrew Turner 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) 221*c120c564SAndrew Turner { 222*c120c564SAndrew Turner if(!hasMemAccMapper()) 223*c120c564SAndrew Turner return OCSD_ERR_NOT_INIT; 224*c120c564SAndrew Turner 225*c120c564SAndrew Turner // need a valid memory buffer, and a least enough bytes for one opcode. 226*c120c564SAndrew Turner if((p_mem_buffer == 0) || (mem_length < 4)) 227*c120c564SAndrew Turner return OCSD_ERR_INVALID_PARAM_VAL; 228*c120c564SAndrew Turner 229*c120c564SAndrew Turner TrcMemAccessorBase *p_accessor; 230*c120c564SAndrew Turner ocsd_err_t err = TrcMemAccFactory::CreateBufferAccessor(&p_accessor, address, p_mem_buffer, mem_length); 231*c120c564SAndrew Turner if(err == OCSD_OK) 232*c120c564SAndrew Turner { 233*c120c564SAndrew Turner TrcMemAccBufPtr *pMBuffAcc = dynamic_cast<TrcMemAccBufPtr *>(p_accessor); 234*c120c564SAndrew Turner if(pMBuffAcc) 235*c120c564SAndrew Turner { 236*c120c564SAndrew Turner pMBuffAcc->setMemSpace(mem_space); 237*c120c564SAndrew Turner err = m_default_mapper->AddAccessor(p_accessor,0); 238*c120c564SAndrew Turner } 239*c120c564SAndrew Turner else 240*c120c564SAndrew Turner err = OCSD_ERR_MEM; // wrong type of object - treat as mem error 241*c120c564SAndrew Turner 242*c120c564SAndrew Turner if(err != OCSD_OK) 243*c120c564SAndrew Turner TrcMemAccFactory::DestroyAccessor(p_accessor); 244*c120c564SAndrew Turner } 245*c120c564SAndrew Turner return err; 246*c120c564SAndrew Turner } 247*c120c564SAndrew Turner 248*c120c564SAndrew Turner ocsd_err_t DecodeTree::addBinFileMemAcc(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const std::string &filepath) 249*c120c564SAndrew Turner { 250*c120c564SAndrew Turner if(!hasMemAccMapper()) 251*c120c564SAndrew Turner return OCSD_ERR_NOT_INIT; 252*c120c564SAndrew Turner 253*c120c564SAndrew Turner if(filepath.length() == 0) 254*c120c564SAndrew Turner return OCSD_ERR_INVALID_PARAM_VAL; 255*c120c564SAndrew Turner 256*c120c564SAndrew Turner TrcMemAccessorBase *p_accessor; 257*c120c564SAndrew Turner ocsd_err_t err = TrcMemAccFactory::CreateFileAccessor(&p_accessor,filepath,address); 258*c120c564SAndrew Turner 259*c120c564SAndrew Turner if(err == OCSD_OK) 260*c120c564SAndrew Turner { 261*c120c564SAndrew Turner TrcMemAccessorFile *pAcc = dynamic_cast<TrcMemAccessorFile *>(p_accessor); 262*c120c564SAndrew Turner if(pAcc) 263*c120c564SAndrew Turner { 264*c120c564SAndrew Turner pAcc->setMemSpace(mem_space); 265*c120c564SAndrew Turner err = m_default_mapper->AddAccessor(pAcc,0); 266*c120c564SAndrew Turner } 267*c120c564SAndrew Turner else 268*c120c564SAndrew Turner err = OCSD_ERR_MEM; // wrong type of object - treat as mem error 269*c120c564SAndrew Turner 270*c120c564SAndrew Turner if(err != OCSD_OK) 271*c120c564SAndrew Turner TrcMemAccFactory::DestroyAccessor(p_accessor); 272*c120c564SAndrew Turner } 273*c120c564SAndrew Turner return err; 274*c120c564SAndrew Turner 275*c120c564SAndrew Turner } 276*c120c564SAndrew Turner 277*c120c564SAndrew Turner 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) 278*c120c564SAndrew Turner { 279*c120c564SAndrew Turner if(!hasMemAccMapper()) 280*c120c564SAndrew Turner return OCSD_ERR_NOT_INIT; 281*c120c564SAndrew Turner 282*c120c564SAndrew Turner if((region_array == 0) || (num_regions == 0) || (filepath.length() == 0)) 283*c120c564SAndrew Turner return OCSD_ERR_INVALID_PARAM_VAL; 284*c120c564SAndrew Turner 285*c120c564SAndrew Turner TrcMemAccessorBase *p_accessor; 286*c120c564SAndrew Turner int curr_region_idx = 0; 287*c120c564SAndrew Turner 288*c120c564SAndrew Turner // add first region during the creation of the file accessor. 289*c120c564SAndrew Turner 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); 290*c120c564SAndrew Turner if(err == OCSD_OK) 291*c120c564SAndrew Turner { 292*c120c564SAndrew Turner TrcMemAccessorFile *pAcc = dynamic_cast<TrcMemAccessorFile *>(p_accessor); 293*c120c564SAndrew Turner if(pAcc) 294*c120c564SAndrew Turner { 295*c120c564SAndrew Turner // add additional regions to the file accessor. 296*c120c564SAndrew Turner curr_region_idx++; 297*c120c564SAndrew Turner while(curr_region_idx < num_regions) 298*c120c564SAndrew Turner { 299*c120c564SAndrew Turner pAcc->AddOffsetRange(region_array[curr_region_idx].start_address, 300*c120c564SAndrew Turner region_array[curr_region_idx].region_size, 301*c120c564SAndrew Turner region_array[curr_region_idx].file_offset); 302*c120c564SAndrew Turner curr_region_idx++; 303*c120c564SAndrew Turner } 304*c120c564SAndrew Turner pAcc->setMemSpace(mem_space); 305*c120c564SAndrew Turner 306*c120c564SAndrew Turner // add the accessor to the map. 307*c120c564SAndrew Turner err = m_default_mapper->AddAccessor(pAcc,0); 308*c120c564SAndrew Turner } 309*c120c564SAndrew Turner else 310*c120c564SAndrew Turner err = OCSD_ERR_MEM; // wrong type of object - treat as mem error 311*c120c564SAndrew Turner 312*c120c564SAndrew Turner if(err != OCSD_OK) 313*c120c564SAndrew Turner TrcMemAccFactory::DestroyAccessor(p_accessor); 314*c120c564SAndrew Turner } 315*c120c564SAndrew Turner return err; 316*c120c564SAndrew Turner } 317*c120c564SAndrew Turner 318*c120c564SAndrew Turner 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) 319*c120c564SAndrew Turner { 320*c120c564SAndrew Turner if (!hasMemAccMapper()) 321*c120c564SAndrew Turner return OCSD_ERR_NOT_INIT; 322*c120c564SAndrew Turner 323*c120c564SAndrew Turner if ((region_array == 0) || (num_regions == 0) || (filepath.length() == 0)) 324*c120c564SAndrew Turner return OCSD_ERR_INVALID_PARAM_VAL; 325*c120c564SAndrew Turner 326*c120c564SAndrew Turner TrcMemAccessorFile *pAcc = TrcMemAccessorFile::getExistingFileAccessor(filepath); 327*c120c564SAndrew Turner if (!pAcc) 328*c120c564SAndrew Turner return OCSD_ERR_INVALID_PARAM_VAL; 329*c120c564SAndrew Turner 330*c120c564SAndrew Turner int curr_region_idx = 0; 331*c120c564SAndrew Turner while (curr_region_idx < num_regions) 332*c120c564SAndrew Turner { 333*c120c564SAndrew Turner // check "new" range 334*c120c564SAndrew Turner if (!pAcc->addrStartOfRange(region_array[curr_region_idx].start_address)) 335*c120c564SAndrew Turner { 336*c120c564SAndrew Turner // ensure adds cleanly 337*c120c564SAndrew Turner if (!pAcc->AddOffsetRange(region_array[curr_region_idx].start_address, 338*c120c564SAndrew Turner region_array[curr_region_idx].region_size, 339*c120c564SAndrew Turner region_array[curr_region_idx].file_offset)) 340*c120c564SAndrew Turner return OCSD_ERR_INVALID_PARAM_VAL; // otherwise bail out 341*c120c564SAndrew Turner } 342*c120c564SAndrew Turner curr_region_idx++; 343*c120c564SAndrew Turner } 344*c120c564SAndrew Turner return OCSD_OK; 345*c120c564SAndrew Turner } 346*c120c564SAndrew Turner ocsd_err_t DecodeTree::initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, 347*c120c564SAndrew Turner const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context) 348*c120c564SAndrew Turner { 349*c120c564SAndrew Turner if(!hasMemAccMapper()) 350*c120c564SAndrew Turner return OCSD_ERR_NOT_INIT; 351*c120c564SAndrew Turner 352*c120c564SAndrew Turner if(p_cb_func == 0) 353*c120c564SAndrew Turner return OCSD_ERR_INVALID_PARAM_VAL; 354*c120c564SAndrew Turner 355*c120c564SAndrew Turner TrcMemAccessorBase *p_accessor; 356*c120c564SAndrew Turner ocsd_err_t err = TrcMemAccFactory::CreateCBAccessor(&p_accessor, st_address, en_address, mem_space); 357*c120c564SAndrew Turner if(err == OCSD_OK) 358*c120c564SAndrew Turner { 359*c120c564SAndrew Turner TrcMemAccCB *pCBAcc = dynamic_cast<TrcMemAccCB *>(p_accessor); 360*c120c564SAndrew Turner if(pCBAcc) 361*c120c564SAndrew Turner { 362*c120c564SAndrew Turner if (IDfn) 363*c120c564SAndrew Turner pCBAcc->setCBIDIfFn((Fn_MemAccID_CB)p_cb_func, p_context); 364*c120c564SAndrew Turner else 365*c120c564SAndrew Turner pCBAcc->setCBIfFn((Fn_MemAcc_CB)p_cb_func, p_context); 366*c120c564SAndrew Turner 367*c120c564SAndrew Turner err = m_default_mapper->AddAccessor(p_accessor,0); 368*c120c564SAndrew Turner } 369*c120c564SAndrew Turner else 370*c120c564SAndrew Turner err = OCSD_ERR_MEM; // wrong type of object - treat as mem error 371*c120c564SAndrew Turner 372*c120c564SAndrew Turner if(err != OCSD_OK) 373*c120c564SAndrew Turner TrcMemAccFactory::DestroyAccessor(p_accessor); 374*c120c564SAndrew Turner } 375*c120c564SAndrew Turner return err; 376*c120c564SAndrew Turner } 377*c120c564SAndrew Turner 378*c120c564SAndrew Turner 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) 379*c120c564SAndrew Turner { 380*c120c564SAndrew Turner return initCallbackMemAcc(st_address, en_address, mem_space, (void *)p_cb_func, false, p_context); 381*c120c564SAndrew Turner } 382*c120c564SAndrew Turner 383*c120c564SAndrew Turner 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) 384*c120c564SAndrew Turner { 385*c120c564SAndrew Turner return initCallbackMemAcc(st_address, en_address, mem_space, (void *)p_cb_func, true, p_context); 386*c120c564SAndrew Turner } 387*c120c564SAndrew Turner 388*c120c564SAndrew Turner ocsd_err_t DecodeTree::removeMemAccByAddress(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space) 389*c120c564SAndrew Turner { 390*c120c564SAndrew Turner if(!hasMemAccMapper()) 391*c120c564SAndrew Turner return OCSD_ERR_NOT_INIT; 392*c120c564SAndrew Turner return m_default_mapper->RemoveAccessorByAddress(address,mem_space,0); 393*c120c564SAndrew Turner } 394*c120c564SAndrew Turner 395*c120c564SAndrew Turner ocsd_err_t DecodeTree::createDecoder(const std::string &decoderName, const int createFlags, const CSConfig *pConfig) 396*c120c564SAndrew Turner { 397*c120c564SAndrew Turner ocsd_err_t err = OCSD_OK; 398*c120c564SAndrew Turner IDecoderMngr *pDecoderMngr = 0; 399*c120c564SAndrew Turner TraceComponent *pTraceComp = 0; 400*c120c564SAndrew Turner int crtFlags = createFlags; 401*c120c564SAndrew Turner 402*c120c564SAndrew Turner uint8_t CSID = 0; // default for single stream decoder (no deformatter) - we ignore the ID 403*c120c564SAndrew Turner if(usingFormatter()) 404*c120c564SAndrew Turner { 405*c120c564SAndrew Turner CSID = pConfig->getTraceID(); 406*c120c564SAndrew Turner crtFlags |= OCSD_CREATE_FLG_INST_ID; 407*c120c564SAndrew Turner } 408*c120c564SAndrew Turner 409*c120c564SAndrew Turner // create the decode element to attach to the channel. 410*c120c564SAndrew Turner if((err = createDecodeElement(CSID)) != OCSD_OK) 411*c120c564SAndrew Turner return err; 412*c120c564SAndrew Turner 413*c120c564SAndrew Turner // get the libary decoder register. 414*c120c564SAndrew Turner OcsdLibDcdRegister * lib_reg = OcsdLibDcdRegister::getDecoderRegister(); 415*c120c564SAndrew Turner if(lib_reg == 0) 416*c120c564SAndrew Turner return OCSD_ERR_NOT_INIT; 417*c120c564SAndrew Turner 418*c120c564SAndrew Turner // find the named decoder 419*c120c564SAndrew Turner if((err = lib_reg->getDecoderMngrByName(decoderName,&pDecoderMngr)) != OCSD_OK) 420*c120c564SAndrew Turner return err; 421*c120c564SAndrew Turner 422*c120c564SAndrew Turner // got the decoder... 423*c120c564SAndrew Turner if((err = pDecoderMngr->createDecoder(crtFlags,(int)CSID,pConfig,&pTraceComp)) != OCSD_OK) 424*c120c564SAndrew Turner return err; 425*c120c564SAndrew Turner 426*c120c564SAndrew Turner m_decode_elements[CSID]->SetDecoderElement(decoderName, pDecoderMngr, pTraceComp, true); 427*c120c564SAndrew Turner 428*c120c564SAndrew Turner // always attach an error logger 429*c120c564SAndrew Turner if(err == OCSD_OK) 430*c120c564SAndrew Turner err = pDecoderMngr->attachErrorLogger(pTraceComp,DecodeTree::s_i_error_logger); 431*c120c564SAndrew Turner 432*c120c564SAndrew Turner // if we created a packet decoder it may need additional components. 433*c120c564SAndrew Turner if(crtFlags & OCSD_CREATE_FLG_FULL_DECODER) 434*c120c564SAndrew Turner { 435*c120c564SAndrew Turner if(m_i_instr_decode && (err == OCSD_OK)) 436*c120c564SAndrew Turner err = pDecoderMngr->attachInstrDecoder(pTraceComp,m_i_instr_decode); 437*c120c564SAndrew Turner 438*c120c564SAndrew Turner if(err == OCSD_ERR_DCD_INTERFACE_UNUSED) // ignore if instruction decoder refused 439*c120c564SAndrew Turner err = OCSD_OK; 440*c120c564SAndrew Turner 441*c120c564SAndrew Turner if(m_i_mem_access && (err == OCSD_OK)) 442*c120c564SAndrew Turner err = pDecoderMngr->attachMemAccessor(pTraceComp,m_i_mem_access); 443*c120c564SAndrew Turner 444*c120c564SAndrew Turner if(err == OCSD_ERR_DCD_INTERFACE_UNUSED) // ignore if mem accessor refused 445*c120c564SAndrew Turner err = OCSD_OK; 446*c120c564SAndrew Turner 447*c120c564SAndrew Turner if( m_i_gen_elem_out && (err == OCSD_OK)) 448*c120c564SAndrew Turner err = pDecoderMngr->attachOutputSink(pTraceComp,m_i_gen_elem_out); 449*c120c564SAndrew Turner } 450*c120c564SAndrew Turner 451*c120c564SAndrew Turner // finally attach the packet processor input to the demux output channel 452*c120c564SAndrew Turner if(err == OCSD_OK) 453*c120c564SAndrew Turner { 454*c120c564SAndrew Turner ITrcDataIn *pDataIn = 0; 455*c120c564SAndrew Turner if((err = pDecoderMngr->getDataInputI(pTraceComp,&pDataIn)) == OCSD_OK) 456*c120c564SAndrew Turner { 457*c120c564SAndrew Turner // got the interface -> attach to demux, or direct to input of decode tree 458*c120c564SAndrew Turner if(usingFormatter()) 459*c120c564SAndrew Turner err = m_frame_deformatter_root->getIDStreamAttachPt(CSID)->attach(pDataIn); 460*c120c564SAndrew Turner else 461*c120c564SAndrew Turner m_i_decoder_root = pDataIn; 462*c120c564SAndrew Turner } 463*c120c564SAndrew Turner } 464*c120c564SAndrew Turner 465*c120c564SAndrew Turner if(err != OCSD_OK) 466*c120c564SAndrew Turner { 467*c120c564SAndrew Turner destroyDecodeElement(CSID); // will destroy decoder as well. 468*c120c564SAndrew Turner } 469*c120c564SAndrew Turner return err; 470*c120c564SAndrew Turner } 471*c120c564SAndrew Turner 472*c120c564SAndrew Turner ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID) 473*c120c564SAndrew Turner { 474*c120c564SAndrew Turner ocsd_err_t err = OCSD_OK; 475*c120c564SAndrew Turner uint8_t localID = CSID; 476*c120c564SAndrew Turner if(!usingFormatter()) 477*c120c564SAndrew Turner localID = 0; 478*c120c564SAndrew Turner 479*c120c564SAndrew Turner if(usingFormatter() && !OCSD_IS_VALID_CS_SRC_ID(CSID)) 480*c120c564SAndrew Turner err = OCSD_ERR_INVALID_ID; 481*c120c564SAndrew Turner else 482*c120c564SAndrew Turner { 483*c120c564SAndrew Turner destroyDecodeElement(localID); 484*c120c564SAndrew Turner } 485*c120c564SAndrew Turner return err; 486*c120c564SAndrew Turner } 487*c120c564SAndrew Turner 488*c120c564SAndrew Turner DecodeTreeElement * DecodeTree::getDecoderElement(const uint8_t CSID) const 489*c120c564SAndrew Turner { 490*c120c564SAndrew Turner DecodeTreeElement *ret_elem = 0; 491*c120c564SAndrew Turner if(usingFormatter() && OCSD_IS_VALID_CS_SRC_ID(CSID)) 492*c120c564SAndrew Turner { 493*c120c564SAndrew Turner ret_elem = m_decode_elements[CSID]; 494*c120c564SAndrew Turner } 495*c120c564SAndrew Turner else 496*c120c564SAndrew Turner ret_elem = m_decode_elements[0]; // ID 0 is used if single leaf tree. 497*c120c564SAndrew Turner return ret_elem; 498*c120c564SAndrew Turner } 499*c120c564SAndrew Turner 500*c120c564SAndrew Turner DecodeTreeElement *DecodeTree::getFirstElement(uint8_t &elemID) 501*c120c564SAndrew Turner { 502*c120c564SAndrew Turner m_decode_elem_iter = 0; 503*c120c564SAndrew Turner return getNextElement(elemID); 504*c120c564SAndrew Turner } 505*c120c564SAndrew Turner 506*c120c564SAndrew Turner DecodeTreeElement *DecodeTree::getNextElement(uint8_t &elemID) 507*c120c564SAndrew Turner { 508*c120c564SAndrew Turner DecodeTreeElement *ret_elem = 0; 509*c120c564SAndrew Turner 510*c120c564SAndrew Turner if(m_decode_elem_iter < 0x80) 511*c120c564SAndrew Turner { 512*c120c564SAndrew Turner // find a none zero entry or end of range 513*c120c564SAndrew Turner while((m_decode_elements[m_decode_elem_iter] == 0) && (m_decode_elem_iter < 0x80)) 514*c120c564SAndrew Turner m_decode_elem_iter++; 515*c120c564SAndrew Turner 516*c120c564SAndrew Turner // return entry unless end of range 517*c120c564SAndrew Turner if(m_decode_elem_iter < 0x80) 518*c120c564SAndrew Turner { 519*c120c564SAndrew Turner ret_elem = m_decode_elements[m_decode_elem_iter]; 520*c120c564SAndrew Turner elemID = m_decode_elem_iter; 521*c120c564SAndrew Turner m_decode_elem_iter++; 522*c120c564SAndrew Turner } 523*c120c564SAndrew Turner } 524*c120c564SAndrew Turner return ret_elem; 525*c120c564SAndrew Turner } 526*c120c564SAndrew Turner 527*c120c564SAndrew Turner bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCfgFlags) 528*c120c564SAndrew Turner { 529*c120c564SAndrew Turner bool initOK = true; 530*c120c564SAndrew Turner m_dcd_tree_type = type; 531*c120c564SAndrew Turner if(type == OCSD_TRC_SRC_FRAME_FORMATTED) 532*c120c564SAndrew Turner { 533*c120c564SAndrew Turner // frame formatted - we want to create the deformatter and hook it up 534*c120c564SAndrew Turner m_frame_deformatter_root = new (std::nothrow) TraceFormatterFrameDecoder(); 535*c120c564SAndrew Turner if(m_frame_deformatter_root) 536*c120c564SAndrew Turner { 537*c120c564SAndrew Turner m_frame_deformatter_root->Configure(formatterCfgFlags); 538*c120c564SAndrew Turner m_frame_deformatter_root->getErrLogAttachPt()->attach(DecodeTree::s_i_error_logger); 539*c120c564SAndrew Turner m_i_decoder_root = dynamic_cast<ITrcDataIn*>(m_frame_deformatter_root); 540*c120c564SAndrew Turner } 541*c120c564SAndrew Turner else 542*c120c564SAndrew Turner initOK = false; 543*c120c564SAndrew Turner } 544*c120c564SAndrew Turner return initOK; 545*c120c564SAndrew Turner } 546*c120c564SAndrew Turner 547*c120c564SAndrew Turner void DecodeTree::setSingleRoot(TrcPktProcI *pComp) 548*c120c564SAndrew Turner { 549*c120c564SAndrew Turner m_i_decoder_root = static_cast<ITrcDataIn*>(pComp); 550*c120c564SAndrew Turner } 551*c120c564SAndrew Turner 552*c120c564SAndrew Turner ocsd_err_t DecodeTree::createDecodeElement(const uint8_t CSID) 553*c120c564SAndrew Turner { 554*c120c564SAndrew Turner ocsd_err_t err = OCSD_ERR_INVALID_ID; 555*c120c564SAndrew Turner if(CSID < 0x80) 556*c120c564SAndrew Turner { 557*c120c564SAndrew Turner if(m_decode_elements[CSID] == 0) 558*c120c564SAndrew Turner { 559*c120c564SAndrew Turner m_decode_elements[CSID] = new (std::nothrow) DecodeTreeElement(); 560*c120c564SAndrew Turner if(m_decode_elements[CSID] == 0) 561*c120c564SAndrew Turner err = OCSD_ERR_MEM; 562*c120c564SAndrew Turner else 563*c120c564SAndrew Turner err = OCSD_OK; 564*c120c564SAndrew Turner } 565*c120c564SAndrew Turner else 566*c120c564SAndrew Turner err = OCSD_ERR_ATTACH_TOO_MANY; 567*c120c564SAndrew Turner } 568*c120c564SAndrew Turner return err; 569*c120c564SAndrew Turner } 570*c120c564SAndrew Turner 571*c120c564SAndrew Turner void DecodeTree::destroyDecodeElement(const uint8_t CSID) 572*c120c564SAndrew Turner { 573*c120c564SAndrew Turner if(CSID < 0x80) 574*c120c564SAndrew Turner { 575*c120c564SAndrew Turner if(m_decode_elements[CSID] != 0) 576*c120c564SAndrew Turner { 577*c120c564SAndrew Turner m_decode_elements[CSID]->DestroyElem(); 578*c120c564SAndrew Turner delete m_decode_elements[CSID]; 579*c120c564SAndrew Turner m_decode_elements[CSID] = 0; 580*c120c564SAndrew Turner } 581*c120c564SAndrew Turner } 582*c120c564SAndrew Turner } 583*c120c564SAndrew Turner 584*c120c564SAndrew Turner ocsd_err_t DecodeTree::setIDFilter(std::vector<uint8_t> &ids) 585*c120c564SAndrew Turner { 586*c120c564SAndrew Turner ocsd_err_t err = OCSD_ERR_DCDT_NO_FORMATTER; 587*c120c564SAndrew Turner if(usingFormatter()) 588*c120c564SAndrew Turner { 589*c120c564SAndrew Turner err = m_frame_deformatter_root->OutputFilterAllIDs(false); 590*c120c564SAndrew Turner if(err == OCSD_OK) 591*c120c564SAndrew Turner err = m_frame_deformatter_root->OutputFilterIDs(ids,true); 592*c120c564SAndrew Turner } 593*c120c564SAndrew Turner return err; 594*c120c564SAndrew Turner } 595*c120c564SAndrew Turner 596*c120c564SAndrew Turner ocsd_err_t DecodeTree::clearIDFilter() 597*c120c564SAndrew Turner { 598*c120c564SAndrew Turner ocsd_err_t err = OCSD_ERR_DCDT_NO_FORMATTER; 599*c120c564SAndrew Turner if(usingFormatter()) 600*c120c564SAndrew Turner { 601*c120c564SAndrew Turner err = m_frame_deformatter_root->OutputFilterAllIDs(true); 602*c120c564SAndrew Turner } 603*c120c564SAndrew Turner return err; 604*c120c564SAndrew Turner } 605*c120c564SAndrew Turner 606*c120c564SAndrew Turner /** add a protocol packet printer */ 607*c120c564SAndrew Turner ocsd_err_t DecodeTree::addPacketPrinter(uint8_t CSID, bool bMonitor, ItemPrinter **ppPrinter) 608*c120c564SAndrew Turner { 609*c120c564SAndrew Turner ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL; 610*c120c564SAndrew Turner DecodeTreeElement *pElement = getDecoderElement(CSID); 611*c120c564SAndrew Turner if (pElement) 612*c120c564SAndrew Turner { 613*c120c564SAndrew Turner ocsd_trace_protocol_t protocol = pElement->getProtocol(); 614*c120c564SAndrew Turner ItemPrinter *pPrinter; 615*c120c564SAndrew Turner 616*c120c564SAndrew Turner pPrinter = PktPrinterFact::createProtocolPrinter(getPrinterList(), protocol, CSID); 617*c120c564SAndrew Turner if (pPrinter) 618*c120c564SAndrew Turner { 619*c120c564SAndrew Turner pPrinter->setMessageLogger(getCurrentErrorLogI()->getOutputLogger()); 620*c120c564SAndrew Turner switch (protocol) 621*c120c564SAndrew Turner { 622*c120c564SAndrew Turner case OCSD_PROTOCOL_ETMV4I: 623*c120c564SAndrew Turner { 624*c120c564SAndrew Turner PacketPrinter<EtmV4ITrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV4ITrcPacket> *>(pPrinter); 625*c120c564SAndrew Turner if (bMonitor) 626*c120c564SAndrew Turner err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<EtmV4ITrcPacket> *)pTPrinter); 627*c120c564SAndrew Turner else 628*c120c564SAndrew Turner err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<EtmV4ITrcPacket> *)pTPrinter); 629*c120c564SAndrew Turner } 630*c120c564SAndrew Turner break; 631*c120c564SAndrew Turner 632*c120c564SAndrew Turner case OCSD_PROTOCOL_ETMV3: 633*c120c564SAndrew Turner { 634*c120c564SAndrew Turner PacketPrinter<EtmV3TrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<EtmV3TrcPacket> *>(pPrinter); 635*c120c564SAndrew Turner if (bMonitor) 636*c120c564SAndrew Turner err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<EtmV3TrcPacket> *)pTPrinter); 637*c120c564SAndrew Turner else 638*c120c564SAndrew Turner err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<EtmV3TrcPacket> *)pTPrinter); 639*c120c564SAndrew Turner } 640*c120c564SAndrew Turner break; 641*c120c564SAndrew Turner 642*c120c564SAndrew Turner case OCSD_PROTOCOL_PTM: 643*c120c564SAndrew Turner { 644*c120c564SAndrew Turner PacketPrinter<PtmTrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<PtmTrcPacket> *>(pPrinter); 645*c120c564SAndrew Turner if (bMonitor) 646*c120c564SAndrew Turner err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<PtmTrcPacket> *)pTPrinter); 647*c120c564SAndrew Turner else 648*c120c564SAndrew Turner err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<PtmTrcPacket> *)pTPrinter); 649*c120c564SAndrew Turner } 650*c120c564SAndrew Turner break; 651*c120c564SAndrew Turner 652*c120c564SAndrew Turner case OCSD_PROTOCOL_STM: 653*c120c564SAndrew Turner { 654*c120c564SAndrew Turner PacketPrinter<StmTrcPacket> *pTPrinter = dynamic_cast<PacketPrinter<StmTrcPacket> *>(pPrinter); 655*c120c564SAndrew Turner if (bMonitor) 656*c120c564SAndrew Turner err = pElement->getDecoderMngr()->attachPktMonitor(pElement->getDecoderHandle(), (IPktRawDataMon<StmTrcPacket> *)pTPrinter); 657*c120c564SAndrew Turner else 658*c120c564SAndrew Turner err = pElement->getDecoderMngr()->attachPktSink(pElement->getDecoderHandle(), (IPktDataIn<StmTrcPacket> *)pTPrinter); 659*c120c564SAndrew Turner } 660*c120c564SAndrew Turner break; 661*c120c564SAndrew Turner 662*c120c564SAndrew Turner default: 663*c120c564SAndrew Turner err = OCSD_ERR_NO_PROTOCOL; 664*c120c564SAndrew Turner break; 665*c120c564SAndrew Turner } 666*c120c564SAndrew Turner 667*c120c564SAndrew Turner if (err == OCSD_OK) 668*c120c564SAndrew Turner { 669*c120c564SAndrew Turner if (ppPrinter) 670*c120c564SAndrew Turner *ppPrinter = pPrinter; 671*c120c564SAndrew Turner } 672*c120c564SAndrew Turner else 673*c120c564SAndrew Turner PktPrinterFact::destroyPrinter(getPrinterList(), pPrinter); 674*c120c564SAndrew Turner } 675*c120c564SAndrew Turner } 676*c120c564SAndrew Turner return err; 677*c120c564SAndrew Turner } 678*c120c564SAndrew Turner 679*c120c564SAndrew Turner /** add a raw frame printer */ 680*c120c564SAndrew Turner ocsd_err_t DecodeTree::addRawFramePrinter(RawFramePrinter **ppPrinter, uint32_t flags) 681*c120c564SAndrew Turner { 682*c120c564SAndrew Turner ocsd_err_t err = OCSD_ERR_MEM; 683*c120c564SAndrew Turner RawFramePrinter *pPrinter = PktPrinterFact::createRawFramePrinter(getPrinterList()); 684*c120c564SAndrew Turner if (pPrinter) 685*c120c564SAndrew Turner { 686*c120c564SAndrew Turner pPrinter->setMessageLogger((DecodeTree::getCurrentErrorLogI()->getOutputLogger())); 687*c120c564SAndrew Turner TraceFormatterFrameDecoder *pFrameDecoder = getFrameDeformatter(); 688*c120c564SAndrew Turner uint32_t cfgFlags = pFrameDecoder->getConfigFlags(); 689*c120c564SAndrew Turner cfgFlags |= ((uint32_t)flags & (OCSD_DFRMTR_PACKED_RAW_OUT | OCSD_DFRMTR_UNPACKED_RAW_OUT)); 690*c120c564SAndrew Turner pFrameDecoder->Configure(cfgFlags); 691*c120c564SAndrew Turner err = pFrameDecoder->getTrcRawFrameAttachPt()->attach(pPrinter); 692*c120c564SAndrew Turner if (ppPrinter && (err==OCSD_OK)) 693*c120c564SAndrew Turner *ppPrinter = pPrinter; 694*c120c564SAndrew Turner } 695*c120c564SAndrew Turner return err; 696*c120c564SAndrew Turner } 697*c120c564SAndrew Turner 698*c120c564SAndrew Turner /** add a generic element output printer */ 699*c120c564SAndrew Turner ocsd_err_t DecodeTree::addGenElemPrinter(TrcGenericElementPrinter **ppPrinter) 700*c120c564SAndrew Turner { 701*c120c564SAndrew Turner ocsd_err_t err = OCSD_ERR_MEM; 702*c120c564SAndrew Turner TrcGenericElementPrinter *pPrinter = PktPrinterFact::createGenElemPrinter(getPrinterList()); 703*c120c564SAndrew Turner if (pPrinter) 704*c120c564SAndrew Turner { 705*c120c564SAndrew Turner pPrinter->setMessageLogger((DecodeTree::getCurrentErrorLogI()->getOutputLogger())); 706*c120c564SAndrew Turner setGenTraceElemOutI(pPrinter); 707*c120c564SAndrew Turner err = OCSD_OK; 708*c120c564SAndrew Turner if (ppPrinter) 709*c120c564SAndrew Turner *ppPrinter = pPrinter; 710*c120c564SAndrew Turner } 711*c120c564SAndrew Turner return err; 712*c120c564SAndrew Turner 713*c120c564SAndrew Turner } 714*c120c564SAndrew Turner 715*c120c564SAndrew Turner /* End of File ocsd_dcd_tree.cpp */ 716