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