Creates C API interface for custom decoders. Creates C++ wrapper for custom decoder. Updates registration code to allow registration and deletion of custom decoders. Addition of doc file to explain use of custom decoder setAPIDcdFact
Signed-off-by: Mike Leach mike.leach@linaro.org --- .../win/rctdl_c_api_lib/rctdl_c_api_lib.vcxproj | 3 + .../rctdl_c_api_lib.vcxproj.filters | 9 + .../ref_trace_decode_lib.vcxproj | 1 + .../ref_trace_decode_lib.vcxproj.filters | 3 + decoder/docs/doxygen_config.dox | 3 +- decoder/docs/external_custom.md | 80 ++++++ decoder/include/c_api/ocsd_c_api_custom.h | 143 +++++++++++ decoder/include/c_api/opencsd_c_api.h | 7 + decoder/include/common/ocsd_lib_dcd_register.h | 4 + decoder/include/ocsd_if_types.h | 1 + decoder/source/c_api/ocsd_c_api_custom_obj.cpp | 271 +++++++++++++++++++++ decoder/source/c_api/ocsd_c_api_custom_obj.h | 144 +++++++++++ decoder/source/ocsd_lib_dcd_register.cpp | 45 +++- 13 files changed, 708 insertions(+), 6 deletions(-) create mode 100644 decoder/docs/external_custom.md create mode 100644 decoder/include/c_api/ocsd_c_api_custom.h create mode 100644 decoder/source/c_api/ocsd_c_api_custom_obj.cpp create mode 100644 decoder/source/c_api/ocsd_c_api_custom_obj.h
diff --git a/decoder/build/win/rctdl_c_api_lib/rctdl_c_api_lib.vcxproj b/decoder/build/win/rctdl_c_api_lib/rctdl_c_api_lib.vcxproj index f1019c1..8e8a7a1 100644 --- a/decoder/build/win/rctdl_c_api_lib/rctdl_c_api_lib.vcxproj +++ b/decoder/build/win/rctdl_c_api_lib/rctdl_c_api_lib.vcxproj @@ -296,9 +296,11 @@ </Link> </ItemDefinitionGroup> <ItemGroup> + <ClInclude Include="..\..\..\include\c_api\ocsd_c_api_custom.h" /> <ClInclude Include="..\..\..\include\c_api\ocsd_c_api_deprc_fn.h" /> <ClInclude Include="..\..\..\include\c_api\ocsd_c_api_types.h" /> <ClInclude Include="..\..\..\include\c_api\opencsd_c_api.h" /> + <ClInclude Include="..\..\..\source\c_api\ocsd_c_api_custom_obj.h" /> <ClInclude Include="..\..\..\source\c_api\ocsd_c_api_obj.h" /> </ItemGroup> <ItemGroup> @@ -308,6 +310,7 @@ </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\source\c_api\ocsd_c_api.cpp" /> + <ClCompile Include="..\..\..\source\c_api\ocsd_c_api_custom_obj.cpp" /> <ClCompile Include="..\..\..\source\c_api\ocsd_c_api_deprc_fn.cpp" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> diff --git a/decoder/build/win/rctdl_c_api_lib/rctdl_c_api_lib.vcxproj.filters b/decoder/build/win/rctdl_c_api_lib/rctdl_c_api_lib.vcxproj.filters index 6b0484c..27d0f11 100644 --- a/decoder/build/win/rctdl_c_api_lib/rctdl_c_api_lib.vcxproj.filters +++ b/decoder/build/win/rctdl_c_api_lib/rctdl_c_api_lib.vcxproj.filters @@ -27,6 +27,12 @@ <ClInclude Include="..\..\..\include\c_api\ocsd_c_api_deprc_fn.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\..\..\include\c_api\ocsd_c_api_custom.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\c_api\ocsd_c_api_custom_obj.h"> + <Filter>Source Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\source\c_api\ocsd_c_api.cpp"> @@ -35,5 +41,8 @@ <ClCompile Include="..\..\..\source\c_api\ocsd_c_api_deprc_fn.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\..\..\source\c_api\ocsd_c_api_custom_obj.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> </Project> \ No newline at end of file diff --git a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj index 65e066c..1b68ed7 100644 --- a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj +++ b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj @@ -299,6 +299,7 @@ <None Include="..\..\..\..\README.md" /> <None Include="..\..\..\..\TODO" /> <None Include="..\..\..\docs\build_libs.md" /> + <None Include="..\..\..\docs\external_custom.md" /> <None Include="..\..\..\docs\test_progs.md" /> </ItemGroup> <ItemGroup> diff --git a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters index e95490f..bbd98f2 100644 --- a/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters +++ b/decoder/build/win/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters @@ -78,6 +78,9 @@ <None Include="..\..\..\..\HOWTO.md"> <Filter>docs-files</Filter> </None> + <None Include="..\..\..\docs\external_custom.md"> + <Filter>docs-files</Filter> + </None> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\..\source\trc_frame_deformatter_impl.h"> diff --git a/decoder/docs/doxygen_config.dox b/decoder/docs/doxygen_config.dox index 72eeaa9..7054396 100644 --- a/decoder/docs/doxygen_config.dox +++ b/decoder/docs/doxygen_config.dox @@ -774,7 +774,8 @@ INPUT = ../include \ ../../README.md \ . \ ../../HOWTO.md \ - ../include/common + ../include/common \ + ../include
# This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/decoder/docs/external_custom.md b/decoder/docs/external_custom.md new file mode 100644 index 0000000..7efd65d --- /dev/null +++ b/decoder/docs/external_custom.md @@ -0,0 +1,80 @@ +Attaching External Custom Decoders {#custom_decoders} +================================== + +@brief A description of the C API external decoder interface. + +Introduction +------------ + +An external custom decoder is one which decodes a CoreSight trace byte stream from a source other +than an ARM core which cannot be decoded by the standard builtin decoders within the library. + +An example of this may be a trace stream from a DSP device. + +The external decoder API allows a suitable decoder to be attached to the library and used in the +same way as the built-in decoders. This means that the external decoder can be created and destroyed +using the decode tree API, and will integrate seamlessly with any ARM processor decoders that are part +of the same tree. + +An external decoder will be required to provide two standard structures:- + +- `ocsd_extern_dcd_fact_t` : this is a decoder "factory" that allows the creation of the custom decoders. +- `ocsd_extern_dcd_inst_t` : one of these structures exists for each instance of the custom decoder that is created. + +These structures consist of data and function pointers to allow integration with the library infrastructure. + +Registering A Decoder +--------------------- + +A single API function is provided to allow a decoder to be registered with the library by name. + + ocsd_err_t ocsd_register_custom_decoder(const char *name, ocsd_extern_dcd_fact_t *p_dcd_fact); + +This registers the custom decoder with the libary using the supplied name and factory structure. +Once registered, the standard API functions used with the built-in decoders will work with the custom decoder. + +The Factory Structure +--------------------- +This structure contains the interface that is registered with the library to allow the creation of custom decoder instances. + +The mandatory functions that must be provided include: +- `fnCreateCustomDecoder` : Creates a decoder. This function will fill in a `ocsd_extern_dcd_inst_t` structure for the decoder instance. +- `fnDestroyCustomDecoder` : Destroys the decoder. Takes the `decoder_handle` attribute of the instance structure. +- `fnGetCSIDFromConfig` : Extracts the CoreSight Trace ID from the decoder configuration structure. + May be called before the create function. The CSID is used as part of the creation process to + attach the decoder to the correct trace byte stream. + +`fnPacketToString` : This optional function will provide a human readable string from a protocol specific packet structure. + +`protocol_id` : This is filled in when the decoder type is registered with the library. Used in some API + calls to specify the decoder protocol type. + + + +The Decoder Instance Structure +------------------------------ + +This structure must be filled in by the `fnCreateCustomDecoder` function implmentation. + +There is a single mandatory function in this structure: + + `fnTraceDataIn` : the decoder must provide this as this is called by the library to provide the + raw trace data to the decoder. + +There are a number of optional callback functions. These allow the custom decoder to call into the library +and use the same infrastructure as the builting decoders. The callbacks are registed with the custom decoder +as the libary performs initialisation of connections. + +For example, the library will connect the error logging interface to all the decoders. The instance structure +contains the `fnRegisterErrLogCB` function pointer which will register two error logging callbacks with the custom +decoder, `fnLogErrorCB` and `fnLogMsgCB`. These can then be called by the custom decoder, and the errors and +messages will appear in the same place as for the built-in decoders. + +Where a custom decoder does not require or support the optional callbacks, then the registration function is set to +0 in the structure. + + + + + + diff --git a/decoder/include/c_api/ocsd_c_api_custom.h b/decoder/include/c_api/ocsd_c_api_custom.h new file mode 100644 index 0000000..607e023 --- /dev/null +++ b/decoder/include/c_api/ocsd_c_api_custom.h @@ -0,0 +1,143 @@ +/* + * \file ocsd_c_api_custom.h + * \brief Reference CoreSight Trace Decoder : + * + * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ARM_OCSD_C_API_CUSTOM_H_INCLUDED +#define ARM_OCSD_C_API_CUSTOM_H_INCLUDED + +#include "ocsd_c_api_types.h" + +/* Custom decoder C-API interface types. */ + +/* Raw trace data input function - a decoder must have one of these */ +typedef ocsd_datapath_resp_t (* fnTraceDataIn)( const void *decoder_handle, + const ocsd_datapath_op_t op, + const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed); + + +/* callback and registration function to connect a generic element output point */ +typedef ocsd_datapath_resp_t (* fnGenElemOpCB)( const void *cb_context, + const ocsd_trc_index_t index_sop, + const uint8_t trc_chan_id, + const ocsd_generic_trace_elem *elem); +typedef ocsd_err_t (* fnRegisterGenElemOpCB)(const void *decoder_handle, const void *cb_context, const fnGenElemOpCB pFnGenElemOut); + +/* callback and registration function to connect into the library error logging mechanism */ +typedef void (* fnLogErrorCB)(const void *cb_context, const ocsd_err_severity_t filter_level, const ocsd_err_t code, const ocsd_trc_index_t idx, const uint8_t chan_id, const char *pMsg); +typedef void (* fnLogMsgCB)(const void *cb_context, const ocsd_err_severity_t filter_level, const char *msg); +typedef void (* fnRegisterErrLogCB)(const void *decoder_handle, const void *cb_context, const fnLogErrorCB pFnErrLog, const fnLogMsgCB pFnMsgLog); + +/* callback and registration function to connect an ARM instruction decoder */ +typedef ocsd_err_t (* fnDecodeArmInstCB)(const void *cb_context, ocsd_instr_info *instr_info); +typedef ocsd_err_t (* fnRegisterDecodeArmInstCB)(const void *decoder_handle, const void *cb_context, const fnDecodeArmInstCB pFnDecodeArmInstr); + +/* callback and registration function to connect the memory accessor interface */ +typedef ocsd_err_t (* fnMemAccessCB)(const void *cb_context, + const ocsd_vaddr_t address, + const uint8_t cs_trace_id, + const ocsd_mem_space_acc_t mem_space, + uint32_t *num_bytes, + uint8_t *p_buffer); +typedef ocsd_err_t (* fnRegisterMemAccessCB)(const void *decoder_handle, const void *cb_context, const fnMemAccessCB pFnmemAcc); + +/* callback and registration function to connect to the packet monitor interface of the packet processor */ +typedef void (* fnPktMonCB)( const void *cb_context, + const ocsd_datapath_op_t op, + const ocsd_trc_index_t index_sop, + const void *pkt, + const uint32_t size, + const uint8_t *p_data); +typedef ocsd_err_t (* fnRegisterPktMonCB)(const void *decoder_handle, const void *cb_context, fnPktMonCB pFnPktMon); + +/* callback and registration function to connect to the packet sink interface, on the main decode + data path - use if decoder created as packet processor only */ +typedef ocsd_datapath_resp_t (* fnPktDataSinkCB)( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index_sop, + const void *p_packet_in); +typedef ocsd_err_t (* fnRegisterPktDataSinkCB)(const void *decoder_handle, const void *cb_context, fnPktDataSinkCB pFnPktData); + +/** This structure is filled in by the ocsd_extern_dcd_fact_t creation function with the exception of the + library context value. */ +typedef struct _ocsd_extern_dcd_inst { + /* Mandatory decoder functions - library initialisation will fail without these. */ + fnTraceDataIn fn_data_in; /**< raw trace data input function to decoder */ + + /* Optional decoder functions - set to 0 if the decoder class does not require / support this functionality */ + fnRegisterGenElemOpCB fn_reg_gen_out_cb; /**< connect callback to get the generic element output of the decoder */ + fnRegisterErrLogCB fn_reg_error_log_cb; /**< connect callbacks for error logging */ + fnRegisterDecodeArmInstCB fn_reg_instr_dcd_cb; /**< connect callback to decode an arm instruction */ + fnRegisterMemAccessCB fn_reg_mem_acc_cb; /**< connect callback to access trace memory images */ + fnRegisterPktMonCB fn_reg_pkt_mon_cb; /**< connect to the packet monitor of the packet processing stage */ + fnRegisterPktDataSinkCB fn_reg_pkt_sink_cb; /**< connect to packet sink on main datapath if decoder in packe processing mode only */ + + /* Decoder instance data */ + void *decoder_handle; /**< Instance handle for the decoder */ + unsigned char cs_id; /**< CS ID of the trace stream this decoder should be attached to */ + char *p_decoder_name; /**< type name of the decoder - may be used in logging */ + + /* opaque library context value */ + void *library_context; /**< Context information for this decoder used by the library */ +} ocsd_extern_dcd_inst_t; + + +/** function to create a decoder instance - fills in the decoder struct supplied. */ +typedef ocsd_err_t (* fnCreateCustomDecoder)(const int create_flags, const void *decoder_cfg, ocsd_extern_dcd_inst_t *p_decoder_inst); +/** Function to destroy a decoder instance - indicated by decoder handle */ +typedef ocsd_err_t (* fnDestroyCustomDecoder)(const void *decoder_handle); +/** Function to extract the CoreSight Trace ID from the configuration structure */ +typedef ocsd_err_t (* fnGetCSIDFromConfig)(const void *decoder_cfg, unsigned char *p_csid); +/** Function to convert a protocol specific trace packet to human readable string */ +typedef ocsd_err_t (* fnPacketToString)(const void *trc_pkt, char *buffer, const int buflen); + + +/** set of functions and callbacks to create an extern custom decoder in the library + via the C API interface. This structure is registered with the library by name and + then decoders of the type can be created on the decode tree. +*/ +typedef struct _ocsd_extern_dcd_fact { + /* mandatory functions */ + fnCreateCustomDecoder createDecoder; /**< [required] Function pointer to create a decoder instance. */ + fnDestroyCustomDecoder destroyDecoder; /**< [required] Function pointer to destroy a decoder instance. */ + fnGetCSIDFromConfig csidFromConfig; /**< [required] Function pointer to extract the CSID from a config structure */ + + /* optional functions */ + fnPacketToString pktToString; /**< [optional] function pointer to print a trace packet in this decoder */ + + ocsd_trace_protocol_t protocol_id; /**< protocol ID assigned during registration. */ +} ocsd_extern_dcd_fact_t; + +#endif // ARM_OCSD_C_API_CUSTOM_H_INCLUDED + +/* End of File ocsd_c_api_custom.h */ diff --git a/decoder/include/c_api/opencsd_c_api.h b/decoder/include/c_api/opencsd_c_api.h index a6daef9..66927a7 100644 --- a/decoder/include/c_api/opencsd_c_api.h +++ b/decoder/include/c_api/opencsd_c_api.h @@ -79,6 +79,7 @@ #endif
#include "ocsd_c_api_types.h" +#include "ocsd_c_api_custom.h"
/** @name Library Version API
@@ -379,6 +380,12 @@ OCSD_C_API ocsd_err_t ocsd_gen_elem_str(const ocsd_generic_trace_elem *p_pkt, ch
/** @}*/
+/** register a custom decoder with the library */ +OCSD_C_API ocsd_err_t ocsd_register_custom_decoder(const char *name, ocsd_extern_dcd_fact_t *p_dcd_fact); +/** clear all registered decoders - library cleanup */ +OCSD_C_API ocsd_err_t ocsd_deregister_decoders(); + + /** @}*/
#ifdef OPENCSD_INC_DEPRECATED_API diff --git a/decoder/include/common/ocsd_lib_dcd_register.h b/decoder/include/common/ocsd_lib_dcd_register.h index c954adf..15dfc03 100644 --- a/decoder/include/common/ocsd_lib_dcd_register.h +++ b/decoder/include/common/ocsd_lib_dcd_register.h @@ -57,6 +57,8 @@ public: static OcsdLibDcdRegister *getDecoderRegister();
static void deregisterAllDecoders(); //!< library cleanup - deregisters decoder managers and destroys the register object. + static const ocsd_trace_protocol_t getNextCustomProtocolID(); + static void releaseLastCustomProtocolID();
const ocsd_err_t registerDecoderTypeByName(const std::string &name, IDecoderMngr *p_decoder_fact); //!< register a decoder manager interface const ocsd_err_t getDecoderMngrByName(const std::string &name, IDecoderMngr **p_decoder_mngr); @@ -70,6 +72,7 @@ public:
private: void registerBuiltInDecoders(); //!< register the list of build in decoder managers on first access of getDecoderMngrByName. + void deRegisterCustomDecoders(); //!< delete all custom decoders registered with the library.
std::map<const std::string, IDecoderMngr *> m_decoder_mngrs; //!< map linking names to decoder manager interfaces. std::map<const std::string, IDecoderMngr *>::const_iterator m_iter; //!< iterator for name search. @@ -84,6 +87,7 @@ private:
static OcsdLibDcdRegister *m_p_libMngr; static bool m_b_registeredBuiltins; + static ocsd_trace_protocol_t m_nextCustomProtocolID; };
/*! diff --git a/decoder/include/ocsd_if_types.h b/decoder/include/ocsd_if_types.h index 0cf65f5..b28382b 100644 --- a/decoder/include/ocsd_if_types.h +++ b/decoder/include/ocsd_if_types.h @@ -148,6 +148,7 @@ typedef enum _ocsd_err_t { /* decoder registration */ OCSD_ERR_DCDREG_NAME_REPEAT, /**< attempted to register a decoder with the same name as another one */ OCSD_ERR_DCDREG_NAME_UNKNOWN, /**< attempted to find a decoder with a name that is not known in the library */ + OCSD_ERR_DCDREG_TOOMANY, /**< attempted to register too many custom decoders */ /* decoder config */ OCSD_ERR_DCD_INTERFACE_UNUSED, /**< Attempt to connect or use and inteface not supported by this decoder. */ /* end marker*/ diff --git a/decoder/source/c_api/ocsd_c_api_custom_obj.cpp b/decoder/source/c_api/ocsd_c_api_custom_obj.cpp new file mode 100644 index 0000000..36db747 --- /dev/null +++ b/decoder/source/c_api/ocsd_c_api_custom_obj.cpp @@ -0,0 +1,271 @@ +/* + * \file ocsd_c_api_custom_obj.cpp + * \brief OpenCSD : + * + * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* pull in the C++ decode library */ +#include "opencsd.h" + +#include "c_api/opencsd_c_api.h" +#include "ocsd_c_api_custom_obj.h" +#include "common/ocsd_lib_dcd_register.h" + +/***************** C-API functions ********************************/ + +/** register a custom decoder with the library */ +OCSD_C_API ocsd_err_t ocsd_register_custom_decoder(const char *name, ocsd_extern_dcd_fact_t *p_dcd_fact) +{ + ocsd_err_t err = OCSD_OK; + OcsdLibDcdRegister *pRegister = OcsdLibDcdRegister::getDecoderRegister(); + + // check not already registered + if(pRegister->isRegisteredDecoder(name)) + return OCSD_ERR_DCDREG_NAME_REPEAT; + + // validate the factory interface structure + if((p_dcd_fact->createDecoder == 0) || + (p_dcd_fact->destroyDecoder == 0) || + (p_dcd_fact->csidFromConfig == 0) + ) + return OCSD_ERR_INVALID_PARAM_VAL; + + // create a wrapper. + CustomDcdMngrWrapper *pWrapper = new (std::nothrow) CustomDcdMngrWrapper(); + if(pRegister == 0) + return OCSD_ERR_MEM; + + p_dcd_fact->protocol_id = OcsdLibDcdRegister::getNextCustomProtocolID(); + if(p_dcd_fact->protocol_id < OCSD_PROTOCOL_END) + { + // fill out the wrapper and register it + pWrapper->setAPIDcdFact(p_dcd_fact); + err = pRegister->registerDecoderTypeByName(name,pWrapper); + if(err != OCSD_OK) + OcsdLibDcdRegister::releaseLastCustomProtocolID(); + } + else + err = OCSD_ERR_DCDREG_TOOMANY; // too many decoders + + if(err != OCSD_OK) + delete pWrapper; + + return err; +} + +OCSD_C_API ocsd_err_t ocsd_deregister_decoders() +{ + // destroys all builtin and custom decoders & library registration object. + OcsdLibDcdRegister::deregisterAllDecoders(); + return OCSD_OK; +} + +/***************** Decode Manager Wrapper *****************************/ + +CustomDcdMngrWrapper::CustomDcdMngrWrapper() +{ + m_dcd_fact.protocol_id = OCSD_PROTOCOL_END; +} + + + // set the C-API decoder factory interface +void CustomDcdMngrWrapper::setAPIDcdFact(ocsd_extern_dcd_fact_t *p_dcd_fact) +{ + m_dcd_fact = *p_dcd_fact; +} + +// create and destroy decoders +ocsd_err_t CustomDcdMngrWrapper::createDecoder(const int create_flags, const int instID, const CSConfig *p_config, TraceComponent **ppComponent) +{ + ocsd_err_t err = OCSD_OK; + if(m_dcd_fact.protocol_id == OCSD_PROTOCOL_END) + return OCSD_ERR_NOT_INIT; + + ocsd_extern_dcd_inst_t dcd_inst; + err = m_dcd_fact.createDecoder( create_flags, + ((CustomConfigWrapper *)p_config)->getConfig(), + &dcd_inst); + if(err == OCSD_OK) + { + CustomDecoderWrapper *pComp = new (std::nothrow) CustomDecoderWrapper(dcd_inst,dcd_inst.p_decoder_name,dcd_inst.cs_id); + *ppComponent = pComp; + if(pComp == 0) + err = OCSD_ERR_MEM; + } + return err; +} + +ocsd_err_t CustomDcdMngrWrapper::destroyDecoder(TraceComponent *pComponent) +{ + CustomDecoderWrapper *pCustWrap = dynamic_cast<CustomDecoderWrapper *>(pComponent); + if(m_dcd_fact.protocol_id != OCSD_PROTOCOL_END) + m_dcd_fact.destroyDecoder(pCustWrap->getDecoderInstInfo()->decoder_handle); + return OCSD_OK; +} + +const ocsd_trace_protocol_t CustomDcdMngrWrapper::getProtocolType() const +{ + return m_dcd_fact.protocol_id; +} + +ocsd_err_t CustomDcdMngrWrapper::createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct) +{ + ocsd_err_t err = OCSD_OK; + CustomConfigWrapper *pConfig = new (std::nothrow) CustomConfigWrapper(pDataStruct); + if(!pConfig) + return OCSD_ERR_MEM; + + if(m_dcd_fact.csidFromConfig == 0) + return OCSD_ERR_NOT_INIT; + + unsigned char csid; + err = m_dcd_fact.csidFromConfig(pDataStruct,&csid); + if(err == OCSD_OK) + { + pConfig->setCSID(csid); + *pConfigBase = pConfig; + } + return err; +} + +ocsd_err_t CustomDcdMngrWrapper::getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn) +{ + CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent); + if(pDecoder == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + *ppDataIn = pDecoder; + return OCSD_OK; +} + +// component connections +// all +ocsd_err_t CustomDcdMngrWrapper::attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog) +{ + CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent); + if(pDecoder == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; +} + +// full decoder +ocsd_err_t CustomDcdMngrWrapper::attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec) +{ + CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent); + if(pDecoder == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; + + return OCSD_OK; +} + +ocsd_err_t CustomDcdMngrWrapper::attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor) +{ + CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent); + if(pDecoder == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; +} + +ocsd_err_t CustomDcdMngrWrapper::attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink) +{ + CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent); + if(pDecoder == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; +} + +// pkt processor only +ocsd_err_t CustomDcdMngrWrapper::attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon) +{ + CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent); + if(pDecoder == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; +} + +ocsd_err_t CustomDcdMngrWrapper::attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer) +{ + // indexers for external custom will also be external and custom. + return OCSD_ERR_DCD_INTERFACE_UNUSED; +} + +ocsd_err_t CustomDcdMngrWrapper::attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink) +{ + CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent); + if(pDecoder == 0) + return OCSD_ERR_INVALID_PARAM_TYPE; +} + +void CustomDcdMngrWrapper::pktToString(void *pkt, char *pStrBuffer, int bufSize) +{ + if(m_dcd_fact.pktToString) + m_dcd_fact.pktToString(pkt,pStrBuffer,bufSize); +} + + +/************************** Decoder instance wrapper **************************************/ + +ocsd_datapath_resp_t GenElemOpCB( const void *cb_context, + const ocsd_trc_index_t index_sop, + const uint8_t trc_chan_id, + const ocsd_generic_trace_elem *elem) +{ + if(cb_context && ((CustomDecoderWrapper *)cb_context)->m_pGenElemIn) + return ((CustomDecoderWrapper *)cb_context)->m_pGenElemIn->TraceElemIn(index_sop,trc_chan_id,*(OcsdTraceElement *)elem); + return OCSD_RESP_FATAL_NOT_INIT; +} + +CustomDecoderWrapper::CustomDecoderWrapper( const ocsd_extern_dcd_inst_t &dcd_inst, + const std::string &name, + const int instID) + : TraceComponent(name,instID) +{ + m_pGenElemIn = 0; + m_decoder_inst = dcd_inst; +} + +CustomDecoderWrapper::~CustomDecoderWrapper() +{ +} + +ocsd_datapath_resp_t CustomDecoderWrapper::TraceDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed) +{ + if(m_decoder_inst.fn_data_in) + return m_decoder_inst.fn_data_in( m_decoder_inst.decoder_handle, + op, + index, + dataBlockSize, + pDataBlock, + numBytesProcessed); + return OCSD_RESP_FATAL_NOT_INIT; +} + +/* End of File ocsd_c_api_custom_obj.cpp */ diff --git a/decoder/source/c_api/ocsd_c_api_custom_obj.h b/decoder/source/c_api/ocsd_c_api_custom_obj.h new file mode 100644 index 0000000..ec8cc03 --- /dev/null +++ b/decoder/source/c_api/ocsd_c_api_custom_obj.h @@ -0,0 +1,144 @@ +/* + * \file ocsd_c_api_custom_obj.h + * \brief OpenCSD : + * + * \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef ARM_OCSD_C_API_CUSTOM_OBJ_H_INCLUDED +#define ARM_OCSD_C_API_CUSTOM_OBJ_H_INCLUDED + +#include "c_api/ocsd_c_api_custom.h" +#include "common/ocsd_dcd_mngr_i.h" + +/***** Decoder manager interface ******************************/ +class CustomDcdMngrWrapper : public IDecoderMngr +{ +public: + CustomDcdMngrWrapper(); + virtual ~CustomDcdMngrWrapper() {}; + + // set the C-API decoder factory interface. + void setAPIDcdFact(ocsd_extern_dcd_fact_t *p_dcd_fact); + +// create and destroy decoders + virtual ocsd_err_t createDecoder(const int create_flags, const int instID, const CSConfig *p_config, TraceComponent **ppComponent); + virtual ocsd_err_t destroyDecoder(TraceComponent *pComponent); + + //! Get the built in protocol type ID managed by this instance - extern for custom decoders + virtual const ocsd_trace_protocol_t getProtocolType() const; + +// connect decoders to other components - (replace current / 0 pointer value to detach ); +// compatible with all decoders + //!attach error logger to ptk-processor, or both of pkt processor and pkt decoder pair + virtual ocsd_err_t attachErrorLogger(TraceComponent *pComponent, ITraceErrorLog *pIErrorLog); + +// pkt decoder only + //! attach instruction decoder to pkt decoder + virtual ocsd_err_t attachInstrDecoder(TraceComponent *pComponent, IInstrDecode *pIInstrDec); + + //! attach memory accessor to pkt decoder + virtual ocsd_err_t attachMemAccessor(TraceComponent *pComponent, ITargetMemAccess *pMemAccessor); + + //! attach generic output interface to pkt decoder + virtual ocsd_err_t attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink); + +// pkt processor only + //! attach a raw packet monitor to pkt processor (solo pkt processor, or pkt processor part of pair) + virtual ocsd_err_t attachPktMonitor(TraceComponent *pComponent, ITrcTypedBase *pPktRawDataMon); + + //! attach a packet indexer to pkt processor (solo pkt processor, or pkt processor part of pair) + virtual ocsd_err_t attachPktIndexer(TraceComponent *pComponent, ITrcTypedBase *pPktIndexer); + + //! attach a packet data sink to pkt processor output (solo pkt processor only - instead of decoder when pkt processor only created.) + virtual ocsd_err_t attachPktSink(TraceComponent *pComponent, ITrcTypedBase *pPktDataInSink); + +// data input connection interface + //! get raw data input interface from packet processor + virtual ocsd_err_t getDataInputI(TraceComponent *pComponent, ITrcDataIn **ppDataIn); + +// create configuration from data structure + virtual ocsd_err_t createConfigFromDataStruct(CSConfig **pConfigBase, const void *pDataStruct); + + void pktToString(void *pkt, char *pStrBuffer, int bufSize); + +private: + + ocsd_extern_dcd_fact_t m_dcd_fact; +}; + +/**** Decoder instance wrapper */ +class CustomDecoderWrapper : public TraceComponent, public ITrcDataIn +{ +public: + CustomDecoderWrapper(const ocsd_extern_dcd_inst_t &dcd_inst, const std::string &name, const int instID); + virtual ~CustomDecoderWrapper(); + const ocsd_extern_dcd_inst_t *getDecoderInstInfo() const { return &m_decoder_inst; } + + virtual ocsd_datapath_resp_t TraceDataIn( const ocsd_datapath_op_t op, + const ocsd_trc_index_t index, + const uint32_t dataBlockSize, + const uint8_t *pDataBlock, + uint32_t *numBytesProcessed); + + // declare the callback functions as friend functions. + friend ocsd_datapath_resp_t GenElemOpCB( const void *cb_context, + const ocsd_trc_index_t index_sop, + const uint8_t trc_chan_id, + const ocsd_generic_trace_elem *elem); + +private: + ITrcGenElemIn *m_pGenElemIn; //!< generic element sink interface - output from decdoer. + ITraceErrorLog *m_pErrorLog; //!< error log interface + IInstrDecode *m_pIInstrDec; //!< arm instruction decode interface. + ITargetMemAccess *m_pMemAccessor; + +private: + ocsd_extern_dcd_inst_t m_decoder_inst; +}; + +/**** Decoder configuration wrapper - implements CSConfig base class interface ***/ +class CustomConfigWrapper : public CSConfig +{ +public: + CustomConfigWrapper(const void *p_config) : m_p_config(p_config), m_CSID(0) {}; + virtual ~CustomConfigWrapper() {}; + virtual const uint8_t getTraceID() const { return m_CSID; }; + void setCSID(const uint8_t CSID) { m_CSID = CSID; }; + const void *getConfig() { return m_p_config; }; +private: + const void *m_p_config; + uint8_t m_CSID; +}; + +#endif // ARM_OCSD_C_API_CUSTOM_OBJ_H_INCLUDED + +/* End of File ocsd_c_api_custom_obj.h */ diff --git a/decoder/source/ocsd_lib_dcd_register.cpp b/decoder/source/ocsd_lib_dcd_register.cpp index 0fd11fa..bc562cc 100644 --- a/decoder/source/ocsd_lib_dcd_register.cpp +++ b/decoder/source/ocsd_lib_dcd_register.cpp @@ -54,6 +54,7 @@ static built_in_decoder_info_t sBuiltInArray[] = {
OcsdLibDcdRegister *OcsdLibDcdRegister::m_p_libMngr = 0; bool OcsdLibDcdRegister::m_b_registeredBuiltins = false; +ocsd_trace_protocol_t OcsdLibDcdRegister::m_nextCustomProtocolID = OCSD_PROTOCOL_CUSTOM_0;
OcsdLibDcdRegister *OcsdLibDcdRegister::getDecoderRegister() { @@ -62,6 +63,20 @@ OcsdLibDcdRegister *OcsdLibDcdRegister::getDecoderRegister() return m_p_libMngr; }
+const ocsd_trace_protocol_t OcsdLibDcdRegister::getNextCustomProtocolID() +{ + ocsd_trace_protocol_t ret = m_nextCustomProtocolID; + if(m_nextCustomProtocolID < OCSD_PROTOCOL_END) + m_nextCustomProtocolID = (ocsd_trace_protocol_t)(((int)m_nextCustomProtocolID)+1); + return ret; +} + +void OcsdLibDcdRegister::releaseLastCustomProtocolID() +{ + if(m_nextCustomProtocolID > OCSD_PROTOCOL_CUSTOM_0) + m_nextCustomProtocolID = (ocsd_trace_protocol_t)(((int)m_nextCustomProtocolID)-1); +} + OcsdLibDcdRegister::OcsdLibDcdRegister() { m_iter = m_decoder_mngrs.begin(); @@ -100,11 +115,31 @@ void OcsdLibDcdRegister::registerBuiltInDecoders()
void OcsdLibDcdRegister::deregisterAllDecoders() { - for(unsigned i = 0; i < NUM_BUILTINS; i++) - delete sBuiltInArray[i].pMngr; - m_b_registeredBuiltins = false; - delete m_p_libMngr; - m_p_libMngr = 0; + if(m_b_registeredBuiltins) + { + for(unsigned i = 0; i < NUM_BUILTINS; i++) + delete sBuiltInArray[i].pMngr; + m_b_registeredBuiltins = false; + } + + if(m_p_libMngr) + { + m_p_libMngr->deRegisterCustomDecoders(); + delete m_p_libMngr; + m_p_libMngr = 0; + } +} + +void OcsdLibDcdRegister::deRegisterCustomDecoders() +{ + std::map<const ocsd_trace_protocol_t, IDecoderMngr *>::const_iterator iter = m_typed_decoder_mngrs.begin(); + while(iter != m_typed_decoder_mngrs.end()) + { + IDecoderMngr *pMngr = iter->second; + if(pMngr->getProtocolType() >= OCSD_PROTOCOL_CUSTOM_0) + delete pMngr; + iter++; + } }
const ocsd_err_t OcsdLibDcdRegister::getDecoderMngrByName(const std::string &name, IDecoderMngr **p_decoder_mngr)