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 /***************************************************************/
41 ITraceErrorLog *DecodeTree::s_i_error_logger = &DecodeTree::s_error_logger;
42 std::list<DecodeTree *> DecodeTree::s_trace_dcd_trees;  /**< list of pointers to decode tree objects */
43 ocsdDefaultErrorLogger DecodeTree::s_error_logger;     /**< The library default error logger */
44 TrcIDecode DecodeTree::s_instruction_decoder;           /**< default instruction decode library */
45 
46 DecodeTree *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 
64 void 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 
82 void 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 
92 DecodeTree::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 
106 DecodeTree::~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 
117 ocsd_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 */
130 void 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 
143 void 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 
157 void 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 
170 ocsd_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 
195 void DecodeTree::setExternMemAccMapper(TrcMemAccMapper* pMapper)
196 {
197     destroyMemAccMapper();  // destroy any existing mapper - if decode tree created it.
198     m_default_mapper = pMapper;
199 }
200 
201 void 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 
212 void 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. */
219 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)
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 
247 ocsd_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 
276 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)
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 
317 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)
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 
344 ocsd_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 
351 ocsd_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 
428 ocsd_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 
444 DecodeTreeElement * 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 
456 DecodeTreeElement *DecodeTree::getFirstElement(uint8_t &elemID)
457 {
458     m_decode_elem_iter = 0;
459     return getNextElement(elemID);
460 }
461 
462 DecodeTreeElement *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 
483 bool 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 
503 void DecodeTree::setSingleRoot(TrcPktProcI *pComp)
504 {
505     m_i_decoder_root = static_cast<ITrcDataIn*>(pComp);
506 }
507 
508 ocsd_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 
527 void 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 
540 ocsd_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 
552 ocsd_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 */
563 ocsd_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 */
636 ocsd_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 */
655 ocsd_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