1/*
2 * \file       ocsd_lib_dcd_register.cpp
3 * \brief      OpenCSD : Library decoder register object
4 *
5 * \copyright  Copyright (c) 2016, ARM Limited. All Rights Reserved.
6 */
7
8/*
9 * Redistribution and use in source and binary forms, with or without modification,
10 * are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the copyright holder nor the names of its contributors
20 * may be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include "common/ocsd_lib_dcd_register.h"
36
37// include built-in decode manager headers
38#include "opencsd/etmv4/trc_dcd_mngr_etmv4i.h"
39#include "opencsd/etmv3/trc_dcd_mngr_etmv3.h"
40#include "opencsd/ptm/trc_dcd_mngr_ptm.h"
41#include "opencsd/stm/trc_dcd_mngr_stm.h"
42#include "opencsd/ete/trc_dcd_mngr_ete.h"
43
44// create array of built-in decoders to register with library
45static built_in_decoder_info_t sBuiltInArray[] = {
46    CREATE_BUILTIN_ENTRY(DecoderMngrEtmV4I,OCSD_BUILTIN_DCD_ETMV4I),
47    CREATE_BUILTIN_ENTRY(DecoderMngrEtmV3, OCSD_BUILTIN_DCD_ETMV3),
48    CREATE_BUILTIN_ENTRY(DecoderMngrPtm, OCSD_BUILTIN_DCD_PTM),
49    CREATE_BUILTIN_ENTRY(DecoderMngrStm, OCSD_BUILTIN_DCD_STM),
50    CREATE_BUILTIN_ENTRY(DecoderMngrETE, OCSD_BUILTIN_DCD_ETE)
51    //{ 0, 0, 0}
52};
53
54#define NUM_BUILTINS sizeof(sBuiltInArray) / sizeof(built_in_decoder_info_t)
55
56
57OcsdLibDcdRegister *OcsdLibDcdRegister::m_p_libMngr = 0;
58bool OcsdLibDcdRegister::m_b_registeredBuiltins = false;
59ocsd_trace_protocol_t OcsdLibDcdRegister::m_nextCustomProtocolID = OCSD_PROTOCOL_CUSTOM_0;
60
61OcsdLibDcdRegister *OcsdLibDcdRegister::getDecoderRegister()
62{
63    if(m_p_libMngr == 0)
64        m_p_libMngr = new (std::nothrow) OcsdLibDcdRegister();
65    return m_p_libMngr;
66}
67
68const ocsd_trace_protocol_t OcsdLibDcdRegister::getNextCustomProtocolID()
69{
70    ocsd_trace_protocol_t ret = m_nextCustomProtocolID;
71    if(m_nextCustomProtocolID < OCSD_PROTOCOL_END)
72        m_nextCustomProtocolID = (ocsd_trace_protocol_t)(((int)m_nextCustomProtocolID)+1);
73    return ret;
74}
75
76void OcsdLibDcdRegister::releaseLastCustomProtocolID()
77{
78    if(m_nextCustomProtocolID > OCSD_PROTOCOL_CUSTOM_0)
79        m_nextCustomProtocolID = (ocsd_trace_protocol_t)(((int)m_nextCustomProtocolID)-1);
80}
81
82OcsdLibDcdRegister::OcsdLibDcdRegister()
83{
84    m_iter = m_decoder_mngrs.begin();
85    m_pLastTypedDecoderMngr = 0;
86}
87
88OcsdLibDcdRegister::~OcsdLibDcdRegister()
89{
90    m_decoder_mngrs.clear();
91    m_typed_decoder_mngrs.clear();
92    m_pLastTypedDecoderMngr = 0;
93}
94
95const ocsd_err_t OcsdLibDcdRegister::registerDecoderTypeByName(const std::string &name, IDecoderMngr *p_decoder_fact)
96{
97    if(isRegisteredDecoder(name))
98        return OCSD_ERR_DCDREG_NAME_REPEAT;
99    m_decoder_mngrs.emplace(std::pair<const std::string, IDecoderMngr *>(name,p_decoder_fact));
100    m_typed_decoder_mngrs.emplace(std::pair<const ocsd_trace_protocol_t, IDecoderMngr *>(p_decoder_fact->getProtocolType(),p_decoder_fact));
101    return OCSD_OK;
102}
103
104void OcsdLibDcdRegister::registerBuiltInDecoders()
105{
106    bool memFail = false;
107    for(unsigned i = 0; i < NUM_BUILTINS; i++)
108    {
109        if(sBuiltInArray[i].PFn)
110        {
111            sBuiltInArray[i].pMngr = sBuiltInArray[i].PFn( sBuiltInArray[i].name);
112            if(!sBuiltInArray[i].pMngr)
113                memFail=true;
114        }
115    }
116    m_b_registeredBuiltins = !memFail;
117}
118
119void OcsdLibDcdRegister::deregisterAllDecoders()
120{
121    if(m_b_registeredBuiltins)
122    {
123        for(unsigned i = 0; i < NUM_BUILTINS; i++)
124            delete sBuiltInArray[i].pMngr;
125        m_b_registeredBuiltins = false;
126    }
127
128    if(m_p_libMngr)
129    {
130        m_p_libMngr->deRegisterCustomDecoders();
131        delete m_p_libMngr;
132        m_p_libMngr = 0;
133    }
134}
135
136void OcsdLibDcdRegister::deRegisterCustomDecoders()
137{
138    std::map<const ocsd_trace_protocol_t, IDecoderMngr *>::const_iterator iter = m_typed_decoder_mngrs.begin();
139    while(iter != m_typed_decoder_mngrs.end())
140    {
141        IDecoderMngr *pMngr = iter->second;
142        if(pMngr->getProtocolType() >= OCSD_PROTOCOL_CUSTOM_0)
143            delete pMngr;
144        iter++;
145    }
146}
147
148const ocsd_err_t OcsdLibDcdRegister::getDecoderMngrByName(const std::string &name, IDecoderMngr **p_decoder_mngr)
149{
150    if(!m_b_registeredBuiltins)
151    {
152        registerBuiltInDecoders();
153        if(!m_b_registeredBuiltins)
154            return OCSD_ERR_MEM;
155    }
156
157    std::map<const std::string,  IDecoderMngr *>::const_iterator iter = m_decoder_mngrs.find(name);
158    if(iter == m_decoder_mngrs.end())
159        return OCSD_ERR_DCDREG_NAME_UNKNOWN;
160    *p_decoder_mngr = iter->second;
161    return OCSD_OK;
162}
163
164const ocsd_err_t OcsdLibDcdRegister::getDecoderMngrByType(const ocsd_trace_protocol_t decoderType, IDecoderMngr **p_decoder_mngr)
165{
166    if(!m_b_registeredBuiltins)
167    {
168        registerBuiltInDecoders();
169        if(!m_b_registeredBuiltins)
170            return OCSD_ERR_MEM;
171    }
172
173    if (m_pLastTypedDecoderMngr && (m_pLastTypedDecoderMngr->getProtocolType() == decoderType))
174        *p_decoder_mngr = m_pLastTypedDecoderMngr;
175    else
176    {
177        std::map<const ocsd_trace_protocol_t, IDecoderMngr *>::const_iterator iter = m_typed_decoder_mngrs.find(decoderType);
178        if (iter == m_typed_decoder_mngrs.end())
179            return OCSD_ERR_DCDREG_TYPE_UNKNOWN;
180        *p_decoder_mngr = m_pLastTypedDecoderMngr = iter->second;
181    }
182    return OCSD_OK;
183}
184
185const bool OcsdLibDcdRegister::isRegisteredDecoder(const std::string &name)
186{
187    std::map<const std::string,  IDecoderMngr *>::const_iterator iter = m_decoder_mngrs.find(name);
188    if(iter != m_decoder_mngrs.end())
189        return true;
190    return false;
191}
192
193const bool OcsdLibDcdRegister::isRegisteredDecoderType(const ocsd_trace_protocol_t decoderType)
194{
195    std::map<const ocsd_trace_protocol_t, IDecoderMngr *>::const_iterator iter = m_typed_decoder_mngrs.find(decoderType);
196    if(iter !=  m_typed_decoder_mngrs.end())
197        return true;
198    return false;
199}
200
201const bool OcsdLibDcdRegister::getFirstNamedDecoder(std::string &name)
202{
203    m_iter = m_decoder_mngrs.begin();
204    return getNextNamedDecoder(name);
205}
206
207const bool OcsdLibDcdRegister::getNextNamedDecoder(std::string &name)
208{
209    if(m_iter == m_decoder_mngrs.end())
210        return false;
211    name = m_iter->first;
212    m_iter++;
213    return true;
214}
215
216/* End of File ocsd_lib_dcd_register.cpp */
217