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