summaryrefslogtreecommitdiffstats
path: root/decoder/source/c_api
diff options
context:
space:
mode:
Diffstat (limited to 'decoder/source/c_api')
-rw-r--r--decoder/source/c_api/ocsd_c_api.cpp632
-rw-r--r--decoder/source/c_api/ocsd_c_api_custom_obj.cpp431
-rw-r--r--decoder/source/c_api/ocsd_c_api_custom_obj.h189
-rw-r--r--decoder/source/c_api/ocsd_c_api_obj.h182
4 files changed, 1434 insertions, 0 deletions
diff --git a/decoder/source/c_api/ocsd_c_api.cpp b/decoder/source/c_api/ocsd_c_api.cpp
new file mode 100644
index 0000000..750c847
--- /dev/null
+++ b/decoder/source/c_api/ocsd_c_api.cpp
@@ -0,0 +1,632 @@
+/*
+ * \file ocsd_c_api.cpp
+ * \brief OpenCSD : "C" API libary implementation.
+ *
+ * \copyright Copyright (c) 2015, 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.
+ */
+
+#include <cstring>
+
+/* pull in the C++ decode library */
+#include "opencsd.h"
+
+/* C-API and wrapper objects */
+#include "opencsd/c_api/opencsd_c_api.h"
+#include "ocsd_c_api_obj.h"
+
+/** MSVC2010 unwanted export workaround */
+#ifdef WIN32
+#if (_MSC_VER == 1600)
+#include <new>
+namespace std { const nothrow_t nothrow = nothrow_t(); }
+#endif
+#endif
+
+/*******************************************************************************/
+/* C API internal helper function declarations */
+/*******************************************************************************/
+
+static ocsd_err_t ocsd_create_pkt_sink_cb(ocsd_trace_protocol_t protocol, FnDefPktDataIn pPktInFn, const void *p_context, ITrcTypedBase **ppCBObj );
+static ocsd_err_t ocsd_create_pkt_mon_cb(ocsd_trace_protocol_t protocol, FnDefPktDataMon pPktInFn, const void *p_context, ITrcTypedBase **ppCBObj );
+static ocsd_err_t ocsd_check_and_add_mem_acc_mapper(const dcd_tree_handle_t handle, DecodeTree **ppDT);
+
+/*******************************************************************************/
+/* C library data - additional data on top of the C++ library objects */
+/*******************************************************************************/
+
+/* keep a list of interface objects for a decode tree for later disposal */
+typedef struct _lib_dt_data_list {
+ std::vector<ITrcTypedBase *> cb_objs;
+ DefLogStrCBObj s_def_log_str_cb;
+} lib_dt_data_list;
+
+/* map lists to handles */
+static std::map<dcd_tree_handle_t, lib_dt_data_list *> s_data_map;
+
+/*******************************************************************************/
+/* C API functions */
+/*******************************************************************************/
+
+/** Get Library version. Return a 32 bit version in form MMMMnnpp - MMMM = major version, nn = minor version, pp = patch version */
+OCSD_C_API uint32_t ocsd_get_version(void)
+{
+ return ocsdVersion::vers_num();
+}
+
+/** Get library version string */
+OCSD_C_API const char * ocsd_get_version_str(void)
+{
+ return ocsdVersion::vers_str();
+}
+
+
+/*** Decode tree creation etc. */
+
+OCSD_C_API dcd_tree_handle_t ocsd_create_dcd_tree(const ocsd_dcd_tree_src_t src_type, const uint32_t deformatterCfgFlags)
+{
+ dcd_tree_handle_t handle = C_API_INVALID_TREE_HANDLE;
+ handle = (dcd_tree_handle_t)DecodeTree::CreateDecodeTree(src_type,deformatterCfgFlags);
+ if(handle != C_API_INVALID_TREE_HANDLE)
+ {
+ lib_dt_data_list *pList = new (std::nothrow) lib_dt_data_list;
+ if(pList != 0)
+ {
+ s_data_map.insert(std::pair<dcd_tree_handle_t, lib_dt_data_list *>(handle,pList));
+ }
+ else
+ {
+ ocsd_destroy_dcd_tree(handle);
+ handle = C_API_INVALID_TREE_HANDLE;
+ }
+ }
+ return handle;
+}
+
+OCSD_C_API void ocsd_destroy_dcd_tree(const dcd_tree_handle_t handle)
+{
+ if(handle != C_API_INVALID_TREE_HANDLE)
+ {
+ GenTraceElemCBObj * pIf = (GenTraceElemCBObj *)(((DecodeTree *)handle)->getGenTraceElemOutI());
+ if(pIf != 0)
+ delete pIf;
+
+ /* need to clear any associated callback data. */
+ std::map<dcd_tree_handle_t, lib_dt_data_list *>::iterator it;
+ it = s_data_map.find(handle);
+ if(it != s_data_map.end())
+ {
+ std::vector<ITrcTypedBase *>::iterator itcb;
+ itcb = it->second->cb_objs.begin();
+ while(itcb != it->second->cb_objs.end())
+ {
+ delete *itcb;
+ itcb++;
+ }
+ it->second->cb_objs.clear();
+ delete it->second;
+ s_data_map.erase(it);
+ }
+ DecodeTree::DestroyDecodeTree((DecodeTree *)handle);
+ }
+}
+
+/*** Decode tree process data */
+
+OCSD_C_API ocsd_datapath_resp_t ocsd_dt_process_data(const dcd_tree_handle_t handle,
+ const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index,
+ const uint32_t dataBlockSize,
+ const uint8_t *pDataBlock,
+ uint32_t *numBytesProcessed)
+{
+ ocsd_datapath_resp_t resp = OCSD_RESP_FATAL_NOT_INIT;
+ if(handle != C_API_INVALID_TREE_HANDLE)
+ resp = ((DecodeTree *)handle)->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed);
+ return resp;
+}
+
+/*** Decode tree - decoder management */
+
+OCSD_C_API ocsd_err_t ocsd_dt_create_decoder(const dcd_tree_handle_t handle,
+ const char *decoder_name,
+ const int create_flags,
+ const void *decoder_cfg,
+ unsigned char *pCSID
+ )
+{
+ ocsd_err_t err = OCSD_OK;
+ DecodeTree *dt = (DecodeTree *)handle;
+ std::string dName = decoder_name;
+ IDecoderMngr *pDcdMngr;
+ err = OcsdLibDcdRegister::getDecoderRegister()->getDecoderMngrByName(dName,&pDcdMngr);
+ if(err != OCSD_OK)
+ return err;
+
+ CSConfig *pConfig = 0;
+ err = pDcdMngr->createConfigFromDataStruct(&pConfig,decoder_cfg);
+ if(err != OCSD_OK)
+ return err;
+
+ err = dt->createDecoder(dName,create_flags,pConfig);
+ if(err == OCSD_OK)
+ *pCSID = pConfig->getTraceID();
+ delete pConfig;
+ return err;
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_remove_decoder( const dcd_tree_handle_t handle,
+ const unsigned char CSID)
+{
+ return ((DecodeTree *)handle)->removeDecoder(CSID);
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t handle,
+ const unsigned char CSID,
+ const ocsd_c_api_cb_types callback_type,
+ void *p_fn_callback_data,
+ const void *p_context)
+{
+ ocsd_err_t err = OCSD_OK;
+ DecodeTree *pDT = static_cast<DecodeTree *>(handle);
+ DecodeTreeElement *pElem = pDT->getDecoderElement(CSID);
+ if(pElem == 0)
+ return OCSD_ERR_INVALID_ID; // cannot find entry for that CSID
+
+ ITrcTypedBase *pDataInSink = 0; // pointer to a sink callback object
+ switch(callback_type)
+ {
+ case OCSD_C_API_CB_PKT_SINK:
+ err = ocsd_create_pkt_sink_cb(pElem->getProtocol(),(FnDefPktDataIn)p_fn_callback_data,p_context,&pDataInSink);
+ if(err == OCSD_OK)
+ err = pElem->getDecoderMngr()->attachPktSink(pElem->getDecoderHandle(), pDataInSink);
+ break;
+
+ case OCSD_C_API_CB_PKT_MON:
+ err = ocsd_create_pkt_mon_cb(pElem->getProtocol(),(FnDefPktDataMon)p_fn_callback_data,p_context,&pDataInSink);
+ if (err == OCSD_OK)
+ err = pElem->getDecoderMngr()->attachPktMonitor(pElem->getDecoderHandle(), pDataInSink);
+ break;
+
+ default:
+ err = OCSD_ERR_INVALID_PARAM_VAL;
+ }
+
+ if(err == OCSD_OK)
+ {
+ if (err == OCSD_OK)
+ {
+ // save object pointer for destruction later.
+ std::map<dcd_tree_handle_t, lib_dt_data_list *>::iterator it;
+ it = s_data_map.find(handle);
+ if (it != s_data_map.end())
+ it->second->cb_objs.push_back(pDataInSink);
+ }
+ else
+ delete pDataInSink;
+ }
+ return err;
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats(const dcd_tree_handle_t handle,
+ const unsigned char CSID,
+ ocsd_decode_stats_t **p_stats_block)
+{
+ DecodeTree *pDT = static_cast<DecodeTree *>(handle);
+
+ return pDT->getDecoderStats(CSID, p_stats_block);
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats(const dcd_tree_handle_t handle,
+ const unsigned char CSID)
+{
+ DecodeTree *pDT = static_cast<DecodeTree *>(handle);
+
+ return pDT->resetDecoderStats(CSID);
+}
+
+/*** Decode tree set element output */
+OCSD_C_API ocsd_err_t ocsd_dt_set_gen_elem_outfn(const dcd_tree_handle_t handle, FnTraceElemIn pFn, const void *p_context)
+{
+
+ GenTraceElemCBObj * pCBObj = new (std::nothrow)GenTraceElemCBObj(pFn, p_context);
+ if(pCBObj)
+ {
+ ((DecodeTree *)handle)->setGenTraceElemOutI(pCBObj);
+ return OCSD_OK;
+ }
+ return OCSD_ERR_MEM;
+}
+
+
+/*** Default error logging */
+
+OCSD_C_API ocsd_err_t ocsd_def_errlog_init(const ocsd_err_severity_t verbosity, const int create_output_logger)
+{
+ if(DecodeTree::getDefaultErrorLogger()->initErrorLogger(verbosity,(bool)(create_output_logger != 0)))
+ return OCSD_OK;
+ return OCSD_ERR_NOT_INIT;
+}
+
+OCSD_C_API ocsd_err_t ocsd_def_errlog_config_output(const int output_flags, const char *log_file_name)
+{
+ ocsdMsgLogger *pLogger = DecodeTree::getDefaultErrorLogger()->getOutputLogger();
+ if(pLogger)
+ {
+ pLogger->setLogOpts(output_flags & C_API_MSGLOGOUT_MASK);
+ if(log_file_name != NULL)
+ {
+ pLogger->setLogFileName(log_file_name);
+ }
+ return OCSD_OK;
+ }
+ return OCSD_ERR_NOT_INIT;
+}
+
+
+OCSD_C_API ocsd_err_t ocsd_def_errlog_set_strprint_cb(const dcd_tree_handle_t handle, void *p_context, FnDefLoggerPrintStrCB p_str_print_cb)
+{
+ ocsdMsgLogger *pLogger = DecodeTree::getDefaultErrorLogger()->getOutputLogger();
+ if (pLogger)
+ {
+ std::map<dcd_tree_handle_t, lib_dt_data_list *>::iterator it;
+ it = s_data_map.find(handle);
+ if (it != s_data_map.end())
+ {
+ DefLogStrCBObj *pCBObj = &(it->second->s_def_log_str_cb);
+ pCBObj->setCBFn(p_context, p_str_print_cb);
+ pLogger->setStrOutFn(pCBObj);
+ int logOpts = pLogger->getLogOpts();
+ logOpts |= (int)(ocsdMsgLogger::OUT_STR_CB);
+ pLogger->setLogOpts(logOpts);
+ return OCSD_OK;
+ }
+ }
+ return OCSD_ERR_NOT_INIT;
+}
+
+OCSD_C_API void ocsd_def_errlog_msgout(const char *msg)
+{
+ ocsdMsgLogger *pLogger = DecodeTree::getDefaultErrorLogger()->getOutputLogger();
+ if(pLogger)
+ pLogger->LogMsg(msg);
+}
+
+/*** Convert packet to string */
+
+OCSD_C_API ocsd_err_t ocsd_pkt_str(const ocsd_trace_protocol_t pkt_protocol, const void *p_pkt, char *buffer, const int buffer_size)
+{
+ ocsd_err_t err = OCSD_OK;
+ if((buffer == NULL) || (buffer_size < 2))
+ return OCSD_ERR_INVALID_PARAM_VAL;
+
+ std::string pktStr = "";
+ buffer[0] = 0;
+
+ switch(pkt_protocol)
+ {
+ case OCSD_PROTOCOL_ETMV4I:
+ trcPrintElemToString<EtmV4ITrcPacket,ocsd_etmv4_i_pkt>(p_pkt, pktStr);
+ break;
+
+ case OCSD_PROTOCOL_ETMV3:
+ trcPrintElemToString<EtmV3TrcPacket,ocsd_etmv3_pkt>(p_pkt, pktStr);
+ break;
+
+ case OCSD_PROTOCOL_STM:
+ trcPrintElemToString<StmTrcPacket,ocsd_stm_pkt>(p_pkt, pktStr);
+ break;
+
+ case OCSD_PROTOCOL_PTM:
+ trcPrintElemToString<PtmTrcPacket,ocsd_ptm_pkt>(p_pkt, pktStr);
+ break;
+
+ default:
+ if (OCSD_PROTOCOL_IS_CUSTOM(pkt_protocol))
+ err = ocsd_cust_protocol_to_str(pkt_protocol, p_pkt, buffer, buffer_size);
+ else
+ err = OCSD_ERR_NO_PROTOCOL;
+ break;
+ }
+
+ if(pktStr.size() > 0)
+ {
+ strncpy(buffer,pktStr.c_str(),buffer_size-1);
+ buffer[buffer_size-1] = 0;
+ }
+ return err;
+}
+
+OCSD_C_API ocsd_err_t ocsd_gen_elem_str(const ocsd_generic_trace_elem *p_pkt, char *buffer, const int buffer_size)
+{
+ ocsd_err_t err = OCSD_OK;
+ if((buffer == NULL) || (buffer_size < 2))
+ return OCSD_ERR_INVALID_PARAM_VAL;
+ std::string str;
+ trcPrintElemToString<OcsdTraceElement,ocsd_generic_trace_elem>(p_pkt,str);
+ if(str.size() > 0)
+ {
+ strncpy(buffer,str.c_str(),buffer_size -1);
+ buffer[buffer_size-1] = 0;
+ }
+ return err;
+}
+
+/*** Decode tree -- memory accessor control */
+
+OCSD_C_API ocsd_err_t ocsd_dt_add_binfile_mem_acc(const dcd_tree_handle_t handle, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const char *filepath)
+{
+ ocsd_err_t err = OCSD_OK;
+ DecodeTree *pDT;
+ err = ocsd_check_and_add_mem_acc_mapper(handle,&pDT);
+ if(err == OCSD_OK)
+ err = pDT->addBinFileMemAcc(address,mem_space,filepath);
+ return err;
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_add_binfile_region_mem_acc(const dcd_tree_handle_t handle, const ocsd_file_mem_region_t *region_array, const int num_regions, const ocsd_mem_space_acc_t mem_space, const char *filepath)
+{
+ ocsd_err_t err = OCSD_OK;
+ DecodeTree *pDT;
+ err = ocsd_check_and_add_mem_acc_mapper(handle,&pDT);
+ if(err == OCSD_OK)
+ err = pDT->addBinFileRegionMemAcc(region_array,num_regions,mem_space,filepath);
+ return err;
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_add_buffer_mem_acc(const dcd_tree_handle_t handle, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t *p_mem_buffer, const uint32_t mem_length)
+{
+ ocsd_err_t err = OCSD_OK;
+ DecodeTree *pDT;
+ err = ocsd_check_and_add_mem_acc_mapper(handle,&pDT);
+ if(err == OCSD_OK)
+ err = pDT->addBufferMemAcc(address,mem_space,p_mem_buffer,mem_length);
+ return err;
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_add_callback_mem_acc(const dcd_tree_handle_t handle, 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)
+{
+ ocsd_err_t err = OCSD_OK;
+ DecodeTree *pDT;
+ err = ocsd_check_and_add_mem_acc_mapper(handle,&pDT);
+ if(err == OCSD_OK)
+ err = pDT->addCallbackMemAcc(st_address,en_address,mem_space,p_cb_func,p_context);
+ return err;
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_add_callback_trcid_mem_acc(const dcd_tree_handle_t handle, 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)
+{
+ ocsd_err_t err = OCSD_OK;
+ DecodeTree *pDT;
+ err = ocsd_check_and_add_mem_acc_mapper(handle, &pDT);
+ if (err == OCSD_OK)
+ err = pDT->addCallbackIDMemAcc(st_address, en_address, mem_space, p_cb_func, p_context);
+ return err;
+}
+
+
+OCSD_C_API ocsd_err_t ocsd_dt_remove_mem_acc(const dcd_tree_handle_t handle, const ocsd_vaddr_t st_address, const ocsd_mem_space_acc_t mem_space)
+{
+ ocsd_err_t err = OCSD_OK;
+
+ if(handle != C_API_INVALID_TREE_HANDLE)
+ {
+ DecodeTree *pDT = static_cast<DecodeTree *>(handle);
+ err = pDT->removeMemAccByAddress(st_address,mem_space);
+ }
+ else
+ err = OCSD_ERR_INVALID_PARAM_VAL;
+ return err;
+}
+
+OCSD_C_API void ocsd_tl_log_mapped_mem_ranges(const dcd_tree_handle_t handle)
+{
+ if(handle != C_API_INVALID_TREE_HANDLE)
+ {
+ DecodeTree *pDT = static_cast<DecodeTree *>(handle);
+ pDT->logMappedRanges();
+ }
+}
+
+OCSD_C_API void ocsd_gen_elem_init(ocsd_generic_trace_elem *p_pkt, const ocsd_gen_trc_elem_t elem_type)
+{
+ p_pkt->elem_type = elem_type;
+ p_pkt->flag_bits = 0;
+ p_pkt->ptr_extended_data = 0;
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_set_raw_frame_printer(const dcd_tree_handle_t handle, int flags)
+{
+ if (handle != C_API_INVALID_TREE_HANDLE)
+ return ((DecodeTree *)handle)->addRawFramePrinter(0, (uint32_t)flags);
+ return OCSD_ERR_NOT_INIT;
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_set_gen_elem_printer(const dcd_tree_handle_t handle)
+{
+ if (handle != C_API_INVALID_TREE_HANDLE)
+ return ((DecodeTree *)handle)->addGenElemPrinter(0);
+ return OCSD_ERR_NOT_INIT;
+}
+
+OCSD_C_API ocsd_err_t ocsd_dt_set_pkt_protocol_printer(const dcd_tree_handle_t handle, uint8_t cs_id, int monitor)
+{
+ ocsd_err_t err = OCSD_ERR_NOT_INIT;
+ if (handle != C_API_INVALID_TREE_HANDLE)
+ {
+ DecodeTree *p_tree = (DecodeTree *)handle;
+ err = p_tree->addPacketPrinter(cs_id, (bool)(monitor != 0), 0);
+ }
+ return err;
+}
+
+OCSD_C_API void ocsd_err_str(const ocsd_err_t err, char *buffer, const int buffer_size)
+{
+ std::string err_str;
+ err_str = ocsdError::getErrorString(ocsdError(OCSD_ERR_SEV_ERROR, err));
+ strncpy(buffer, err_str.c_str(), buffer_size - 1);
+ buffer[buffer_size - 1] = 0;
+}
+
+OCSD_C_API ocsd_err_t ocsd_get_last_err(ocsd_trc_index_t *index, uint8_t *chan_id, char *message, const int message_len)
+{
+ ocsdError *p_err;
+ ocsd_err_t err = OCSD_OK;
+ std::string err_str;
+
+ p_err = DecodeTree::getDefaultErrorLogger()->GetLastError();
+ if (p_err)
+ {
+ *index = p_err->getErrorIndex();
+ *chan_id = p_err->getErrorChanID();
+ err_str = p_err->getErrorString(ocsdError(p_err));
+ strncpy(message, err_str.c_str(), message_len - 1);
+ message[message_len - 1] = 0;
+ err = p_err->getErrorCode();
+ }
+ else
+ {
+ message[0] = 0;
+ *index = OCSD_BAD_TRC_INDEX;
+ *chan_id = OCSD_BAD_CS_SRC_ID;
+ }
+ return err;
+}
+
+/*******************************************************************************/
+/* C API local fns */
+/*******************************************************************************/
+static ocsd_err_t ocsd_create_pkt_sink_cb(ocsd_trace_protocol_t protocol, FnDefPktDataIn pPktInFn, const void *p_context, ITrcTypedBase **ppCBObj )
+{
+ ocsd_err_t err = OCSD_OK;
+ *ppCBObj = 0;
+
+ switch(protocol)
+ {
+ case OCSD_PROTOCOL_ETMV4I:
+ *ppCBObj = new (std::nothrow) PktCBObj<EtmV4ITrcPacket>(pPktInFn,p_context);
+ break;
+
+ case OCSD_PROTOCOL_ETMV3:
+ *ppCBObj = new (std::nothrow) PktCBObj<EtmV3TrcPacket>(pPktInFn,p_context);
+ break;
+
+ case OCSD_PROTOCOL_PTM:
+ *ppCBObj = new (std::nothrow) PktCBObj<PtmTrcPacket>(pPktInFn,p_context);
+ break;
+
+ case OCSD_PROTOCOL_STM:
+ *ppCBObj = new (std::nothrow) PktCBObj<StmTrcPacket>(pPktInFn,p_context);
+ break;
+
+ default:
+ if ((protocol >= OCSD_PROTOCOL_CUSTOM_0) && (protocol < OCSD_PROTOCOL_END))
+ {
+ *ppCBObj = new (std::nothrow) PktCBObj<void>(pPktInFn, p_context);
+ }
+ else
+ err = OCSD_ERR_NO_PROTOCOL;
+ break;
+ }
+
+ if((*ppCBObj == 0) && (err == OCSD_OK))
+ err = OCSD_ERR_MEM;
+
+ return err;
+}
+
+static ocsd_err_t ocsd_create_pkt_mon_cb(ocsd_trace_protocol_t protocol, FnDefPktDataMon pPktInFn, const void *p_context, ITrcTypedBase **ppCBObj )
+{
+ ocsd_err_t err = OCSD_OK;
+ *ppCBObj = 0;
+
+ switch(protocol)
+ {
+ case OCSD_PROTOCOL_ETMV4I:
+ *ppCBObj = new (std::nothrow) PktMonCBObj<EtmV4ITrcPacket>(pPktInFn,p_context);
+ break;
+
+ case OCSD_PROTOCOL_ETMV3:
+ *ppCBObj = new (std::nothrow) PktMonCBObj<EtmV3TrcPacket>(pPktInFn,p_context);
+ break;
+
+ case OCSD_PROTOCOL_PTM:
+ *ppCBObj = new (std::nothrow) PktMonCBObj<PtmTrcPacket>(pPktInFn,p_context);
+ break;
+
+ case OCSD_PROTOCOL_STM:
+ *ppCBObj = new (std::nothrow) PktMonCBObj<StmTrcPacket>(pPktInFn,p_context);
+ break;
+
+ default:
+ if ((protocol >= OCSD_PROTOCOL_CUSTOM_0) && (protocol < OCSD_PROTOCOL_END))
+ {
+ *ppCBObj = new (std::nothrow) PktMonCBObj<void>(pPktInFn, p_context);
+ }
+ else
+ err = OCSD_ERR_NO_PROTOCOL;
+ break;
+ }
+
+ if((*ppCBObj == 0) && (err == OCSD_OK))
+ err = OCSD_ERR_MEM;
+
+ return err;
+}
+
+static ocsd_err_t ocsd_check_and_add_mem_acc_mapper(const dcd_tree_handle_t handle, DecodeTree **ppDT)
+{
+ *ppDT = 0;
+ if(handle == C_API_INVALID_TREE_HANDLE)
+ return OCSD_ERR_INVALID_PARAM_VAL;
+ *ppDT = static_cast<DecodeTree *>(handle);
+ if(!(*ppDT)->hasMemAccMapper())
+ return (*ppDT)->createMemAccMapper();
+ return OCSD_OK;
+}
+
+/*******************************************************************************/
+/* C API Helper objects */
+/*******************************************************************************/
+
+/****************** Generic trace element output callback function ************/
+GenTraceElemCBObj::GenTraceElemCBObj(FnTraceElemIn pCBFn, const void *p_context) :
+ m_c_api_cb_fn(pCBFn),
+ m_p_cb_context(p_context)
+{
+}
+
+ocsd_datapath_resp_t GenTraceElemCBObj::TraceElemIn(const ocsd_trc_index_t index_sop,
+ const uint8_t trc_chan_id,
+ const OcsdTraceElement &elem)
+{
+ return m_c_api_cb_fn(m_p_cb_context, index_sop, trc_chan_id, &elem);
+}
+
+/* End of File ocsd_c_api.cpp */
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..dbd0bd1
--- /dev/null
+++ b/decoder/source/c_api/ocsd_c_api_custom_obj.cpp
@@ -0,0 +1,431 @@
+/*
+ * \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 "opencsd/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;
+}
+
+OCSD_C_API ocsd_err_t ocsd_cust_protocol_to_str(const ocsd_trace_protocol_t pkt_protocol, const void *trc_pkt, char *buffer, const int buflen)
+{
+ OcsdLibDcdRegister *pRegister = OcsdLibDcdRegister::getDecoderRegister();
+ IDecoderMngr *p_mngr = 0;
+ if (OCSD_PROTOCOL_IS_CUSTOM(pkt_protocol) && (pRegister->getDecoderMngrByType(pkt_protocol, &p_mngr) == OCSD_OK))
+ {
+ CustomDcdMngrWrapper *pWrapper = static_cast<CustomDcdMngrWrapper *>(p_mngr);
+ pWrapper->pktToString(trc_pkt, buffer, buflen);
+ return OCSD_OK;
+ }
+ return OCSD_ERR_NO_PROTOCOL;
+}
+
+/***************** 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;
+
+ CustomDecoderWrapper *pComp = new (std::nothrow) CustomDecoderWrapper();
+ *ppComponent = pComp;
+ if (pComp == 0)
+ return OCSD_ERR_MEM;
+
+ ocsd_extern_dcd_cb_fns lib_callbacks;
+ CustomDecoderWrapper::SetCallbacks(lib_callbacks);
+ lib_callbacks.lib_context = pComp;
+ lib_callbacks.packetCBFlags = 0;
+
+ ocsd_extern_dcd_inst_t *pDecodeInst = pComp->getDecoderInstInfo();
+
+ err = m_dcd_fact.createDecoder( create_flags,
+ ((CustomConfigWrapper *)p_config)->getConfig(),
+ &lib_callbacks,
+ pDecodeInst);
+
+ if (err == OCSD_OK)
+ {
+ // validate the decoder
+ if ((pDecodeInst->fn_data_in == 0) ||
+ (pDecodeInst->fn_update_pkt_mon == 0) ||
+ (pDecodeInst->cs_id == 0) ||
+ (pDecodeInst->decoder_handle == 0) ||
+ (pDecodeInst->p_decoder_name == 0)
+ )
+ {
+ err = OCSD_ERR_INVALID_PARAM_VAL;
+ }
+ }
+
+ if (err != OCSD_OK)
+ delete pComp;
+ else
+ pComp->updateNameFromDcdInst();
+ 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);
+ delete pCustWrap;
+ 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;
+ pDecoder->getErrorLogAttachPt()->replace_first(pIErrorLog);
+ return OCSD_OK;
+}
+
+// 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;
+ pDecoder->attachInstrDecI(pIInstrDec);
+ 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;
+ pDecoder->attachMemAccI(pMemAccessor);
+ return OCSD_OK;
+}
+
+ocsd_err_t CustomDcdMngrWrapper::attachOutputSink(TraceComponent *pComponent, ITrcGenElemIn *pOutSink)
+{
+ CustomDecoderWrapper *pDecoder = dynamic_cast<CustomDecoderWrapper *>(pComponent);
+ if(pDecoder == 0)
+ return OCSD_ERR_INVALID_PARAM_TYPE;
+ pDecoder->attachGenElemI(pOutSink);
+ return OCSD_OK;
+}
+
+// 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;
+ IPktRawDataMon<void> *pIF = 0;
+ if (pPktRawDataMon)
+ {
+ pIF = dynamic_cast<IPktRawDataMon<void> *>(pPktRawDataMon);
+ if (!pIF)
+ return OCSD_ERR_INVALID_PARAM_TYPE;
+ }
+ pDecoder->attachPtkMonI(pIF);
+ return OCSD_OK;
+}
+
+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;
+ IPktDataIn<void> *pIF = 0;
+ if (pPktDataInSink)
+ {
+ pIF = dynamic_cast<IPktDataIn<void> *>(pPktDataInSink);
+ if(!pIF)
+ return OCSD_ERR_INVALID_PARAM_TYPE;
+ }
+ pDecoder->attachPtkSinkI(pIF);
+ return OCSD_OK;
+}
+
+void CustomDcdMngrWrapper::pktToString(const void *pkt, char *pStrBuffer, int bufSize)
+{
+ if (m_dcd_fact.pktToString)
+ m_dcd_fact.pktToString(pkt, pStrBuffer, bufSize);
+ else
+ snprintf(pStrBuffer, bufSize, "CUSTOM_PKT[]: print unsupported; protocol(%d).",m_dcd_fact.protocol_id);
+}
+
+/************************** Decoder instance wrapper **************************************/
+
+/* callback functions */
+ocsd_datapath_resp_t GenElemOpCB( const void *lib_context,
+ const ocsd_trc_index_t index_sop,
+ const uint8_t trc_chan_id,
+ const ocsd_generic_trace_elem *elem)
+{
+ if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pGenElemIn)
+ return ((CustomDecoderWrapper *)lib_context)->m_pGenElemIn->TraceElemIn(index_sop,trc_chan_id,*(OcsdTraceElement *)elem);
+ return OCSD_RESP_FATAL_NOT_INIT;
+}
+
+void LogErrorCB(const void *lib_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)
+{
+ if (lib_context)
+ {
+ if(pMsg)
+ ((CustomDecoderWrapper *)lib_context)->LogError(ocsdError(filter_level, code, idx, chan_id, std::string(pMsg)));
+ else
+ ((CustomDecoderWrapper *)lib_context)->LogError(ocsdError(filter_level, code, idx, chan_id));
+ }
+}
+
+void LogMsgCB(const void *lib_context, const ocsd_err_severity_t filter_level, const char *msg)
+{
+ if (lib_context && msg)
+ ((CustomDecoderWrapper *)lib_context)->LogMessage(filter_level, std::string(msg));
+}
+
+ocsd_err_t DecodeArmInstCB(const void *lib_context, ocsd_instr_info *instr_info)
+{
+ if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pIInstrDec)
+ return ((CustomDecoderWrapper *)lib_context)->m_pIInstrDec->DecodeInstruction(instr_info);
+ return OCSD_ERR_ATTACH_INVALID_PARAM;
+}
+
+ocsd_err_t MemAccessCB(const void *lib_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)
+{
+ if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pMemAccessor)
+ return ((CustomDecoderWrapper *)lib_context)->m_pMemAccessor->ReadTargetMemory(address, cs_trace_id, mem_space, num_bytes, p_buffer);
+ return OCSD_ERR_INVALID_PARAM_VAL;
+}
+
+void PktMonCB(const void *lib_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)
+{
+ if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pPktMon)
+ ((CustomDecoderWrapper *)lib_context)->m_pPktMon->RawPacketDataMon(op, index_sop, pkt, size, p_data);
+}
+
+ocsd_datapath_resp_t PktDataSinkCB(const void *lib_context,
+ const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index_sop,
+ const void *pkt)
+{
+ ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+ if (lib_context && ((CustomDecoderWrapper *)lib_context)->m_pPktIn)
+ resp = ((CustomDecoderWrapper *)lib_context)->m_pPktIn->PacketDataIn(op, index_sop, pkt);
+ return resp;
+}
+
+
+
+/** decoder instance object */
+CustomDecoderWrapper::CustomDecoderWrapper() : TraceComponent("extern_wrapper"),
+ m_pGenElemIn(0),
+ m_pIInstrDec(0),
+ m_pMemAccessor(0),
+ m_pPktMon(0),
+ m_pPktIn(0)
+{
+}
+
+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;
+}
+
+void CustomDecoderWrapper::attachPtkMonI(IPktRawDataMon<void>* pIF)
+{
+ m_pPktMon = pIF;
+ int flags = (m_pPktMon ? OCSD_CUST_DCD_PKT_CB_USE_MON : 0) | (m_pPktIn ? OCSD_CUST_DCD_PKT_CB_USE_SINK : 0);
+ m_decoder_inst.fn_update_pkt_mon(m_decoder_inst.decoder_handle, flags);
+}
+
+void CustomDecoderWrapper::attachPtkSinkI(IPktDataIn<void>* pIF)
+{
+ m_pPktIn = pIF;
+ int flags = (m_pPktMon ? OCSD_CUST_DCD_PKT_CB_USE_MON : 0) | (m_pPktIn ? OCSD_CUST_DCD_PKT_CB_USE_SINK : 0);
+ m_decoder_inst.fn_update_pkt_mon(m_decoder_inst.decoder_handle, flags);
+}
+
+void CustomDecoderWrapper::updateNameFromDcdInst()
+{
+ // create a unique component name from the decoder name + cs-id.
+ std::string name_combined = m_decoder_inst.p_decoder_name;
+ char num_buffer[32];
+ sprintf(num_buffer, "_%04d", m_decoder_inst.cs_id);
+ name_combined += (std::string)num_buffer;
+ setComponentName(name_combined);
+}
+
+void CustomDecoderWrapper::SetCallbacks(ocsd_extern_dcd_cb_fns & callbacks)
+{
+ callbacks.fn_arm_instruction_decode = DecodeArmInstCB;
+ callbacks.fn_gen_elem_out = GenElemOpCB;
+ callbacks.fn_log_error = LogErrorCB;
+ callbacks.fn_log_msg = LogMsgCB;
+ callbacks.fn_memory_access = MemAccessCB;
+ callbacks.fn_packet_data_sink = PktDataSinkCB;
+ callbacks.fn_packet_mon = PktMonCB;
+}
+
+/* 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..d4845bd
--- /dev/null
+++ b/decoder/source/c_api/ocsd_c_api_custom_obj.h
@@ -0,0 +1,189 @@
+/*
+ * \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 "opencsd/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);
+
+// custom packet to string interface.
+ void pktToString(const 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();
+ virtual ~CustomDecoderWrapper();
+ ocsd_extern_dcd_inst_t *getDecoderInstInfo() { 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);
+
+ void attachGenElemI(ITrcGenElemIn *pIF) { m_pGenElemIn = pIF; };
+ void attachInstrDecI(IInstrDecode *pIF) { m_pIInstrDec = pIF; };
+ void attachMemAccI(ITargetMemAccess *pIF) { m_pMemAccessor = pIF; };
+
+ void attachPtkMonI(IPktRawDataMon<void> *pIF);
+ void attachPtkSinkI(IPktDataIn<void> *pIF);
+
+ void updateNameFromDcdInst();
+
+ static void SetCallbacks(ocsd_extern_dcd_cb_fns &callbacks);
+
+private:
+ // declare the callback functions as friend functions.
+ friend ocsd_datapath_resp_t GenElemOpCB( const void *lib_context,
+ const ocsd_trc_index_t index_sop,
+ const uint8_t trc_chan_id,
+ const ocsd_generic_trace_elem *elem);
+
+ friend void LogErrorCB( const void *lib_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);
+
+ friend void LogMsgCB(const void *lib_context,
+ const ocsd_err_severity_t filter_level,
+ const char *msg);
+
+ friend ocsd_err_t DecodeArmInstCB(const void *lib_context, ocsd_instr_info *instr_info);
+
+ friend ocsd_err_t MemAccessCB(const void *lib_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);
+
+ friend void PktMonCB(const void *lib_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);
+
+ friend ocsd_datapath_resp_t PktDataSinkCB(const void *lib_context,
+ const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index_sop,
+ const void *pkt);
+
+private:
+ ITrcGenElemIn *m_pGenElemIn; //!< generic element sink interface - output from decoder fed to common sink.
+ IInstrDecode *m_pIInstrDec; //!< arm instruction decode interface - decoder may want to use this.
+ ITargetMemAccess *m_pMemAccessor; //!< system memory accessor insterface - decoder may want to use this.
+ IPktRawDataMon<void> *m_pPktMon; //!< interface to packet monitor (full or packet only decode).
+ IPktDataIn<void> *m_pPktIn; //!< interface to packet sink (decode packets only).
+
+ 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/c_api/ocsd_c_api_obj.h b/decoder/source/c_api/ocsd_c_api_obj.h
new file mode 100644
index 0000000..0476ac6
--- /dev/null
+++ b/decoder/source/c_api/ocsd_c_api_obj.h
@@ -0,0 +1,182 @@
+/*
+ * \file ocsd_c_api_obj.h
+ * \brief OpenCSD : C API callback objects.
+ *
+ * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
+ */
+
+#ifndef ARM_OCSD_C_API_OBJ_H_INCLUDED
+#define ARM_OCSD_C_API_OBJ_H_INCLUDED
+
+#include "opencsd/c_api/ocsd_c_api_types.h"
+#include "interfaces/trc_gen_elem_in_i.h"
+#include "common/ocsd_msg_logger.h"
+
+class TraceElemCBBase
+{
+public:
+ TraceElemCBBase() {};
+ virtual ~TraceElemCBBase() {};
+};
+
+class GenTraceElemCBObj : public ITrcGenElemIn, public TraceElemCBBase
+{
+public:
+ GenTraceElemCBObj(FnTraceElemIn pCBFn, const void *p_context);
+ virtual ~GenTraceElemCBObj() {};
+
+ virtual ocsd_datapath_resp_t TraceElemIn(const ocsd_trc_index_t index_sop,
+ const uint8_t trc_chan_id,
+ const OcsdTraceElement &elem);
+
+private:
+ FnTraceElemIn m_c_api_cb_fn;
+ const void *m_p_cb_context;
+};
+
+
+
+template<class TrcPkt>
+class PktCBObj : public IPktDataIn<TrcPkt>
+{
+public:
+ PktCBObj( FnDefPktDataIn pCBFunc, const void *p_context)
+ {
+ m_c_api_cb_fn = pCBFunc;
+ m_p_context = p_context;
+ };
+
+ virtual ~PktCBObj() {};
+
+ virtual ocsd_datapath_resp_t PacketDataIn( const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index_sop,
+ const TrcPkt *p_packet_in)
+ {
+ const void *c_pkt_struct = 0;
+ if(op == OCSD_OP_DATA)
+ c_pkt_struct = p_packet_in->c_pkt(); // always output the c struct packet
+ return m_c_api_cb_fn(m_p_context,op,index_sop,c_pkt_struct);
+ };
+
+private:
+ FnDefPktDataIn m_c_api_cb_fn;
+ const void *m_p_context;
+};
+
+// void specialisation for custom decoders that pass packets as const void * pointers
+template<>
+class PktCBObj<void> : public IPktDataIn<void>
+{
+public:
+ PktCBObj(FnDefPktDataIn pCBFunc, const void *p_context)
+ {
+ m_c_api_cb_fn = pCBFunc;
+ m_p_context = p_context;
+ };
+
+ virtual ~PktCBObj() {};
+
+ virtual ocsd_datapath_resp_t PacketDataIn(const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index_sop,
+ const void *p_packet_in)
+ {
+ return m_c_api_cb_fn(m_p_context, op, index_sop, p_packet_in);
+ };
+
+private:
+ FnDefPktDataIn m_c_api_cb_fn;
+ const void *m_p_context;
+};
+
+
+template<class TrcPkt>
+class PktMonCBObj : public IPktRawDataMon<TrcPkt>
+{
+public:
+ PktMonCBObj( FnDefPktDataMon pCBFunc, const void *p_context)
+ {
+ m_c_api_cb_fn = pCBFunc;
+ m_p_context = p_context;
+ };
+
+ virtual ~PktMonCBObj() {};
+
+ virtual void RawPacketDataMon( const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index_sop,
+ const TrcPkt *p_packet_in,
+ const uint32_t size,
+ const uint8_t *p_data)
+ {
+ const void *c_pkt_struct = 0;
+ if(op == OCSD_OP_DATA)
+ c_pkt_struct = p_packet_in->c_pkt(); // always output the c struct packet
+ m_c_api_cb_fn(m_p_context,op,index_sop,c_pkt_struct,size,p_data);
+ };
+
+private:
+ FnDefPktDataMon m_c_api_cb_fn;
+ const void *m_p_context;
+};
+
+// void specialisation for custom decoders that pass packets as const void * pointers
+template<>
+class PktMonCBObj<void> : public IPktRawDataMon<void>
+{
+public:
+ PktMonCBObj(FnDefPktDataMon pCBFunc, const void *p_context)
+ {
+ m_c_api_cb_fn = pCBFunc;
+ m_p_context = p_context;
+ };
+
+ virtual ~PktMonCBObj() {};
+ virtual void RawPacketDataMon(const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index_sop,
+ const void *p_packet_in,
+ const uint32_t size,
+ const uint8_t *p_data)
+ {
+ m_c_api_cb_fn(m_p_context, op, index_sop, p_packet_in, size, p_data);
+ };
+
+private:
+ FnDefPktDataMon m_c_api_cb_fn;
+ const void *m_p_context;
+};
+
+/* handler for default string print CB object */
+class DefLogStrCBObj : public ocsdMsgLogStrOutI
+{
+public:
+ DefLogStrCBObj()
+ {
+ m_c_api_cb_fn = 0;
+ m_p_context = 0;
+ };
+
+ virtual ~DefLogStrCBObj()
+ {
+ m_c_api_cb_fn = 0;
+ m_p_context = 0;
+ };
+
+ void setCBFn(const void *p_context, FnDefLoggerPrintStrCB pCBFn)
+ {
+ m_c_api_cb_fn = pCBFn;
+ m_p_context = p_context;
+ };
+
+ virtual void printOutStr(const std::string &outStr)
+ {
+ if(m_c_api_cb_fn)
+ m_c_api_cb_fn(m_p_context, outStr.c_str(), outStr.length());
+ }
+
+private:
+ FnDefLoggerPrintStrCB m_c_api_cb_fn;
+ const void *m_p_context;
+};
+
+#endif // ARM_OCSD_C_API_OBJ_H_INCLUDED
+
+/* End of File ocsd_c_api_obj.h */