diff options
Diffstat (limited to 'decoder/source/c_api')
-rw-r--r-- | decoder/source/c_api/ocsd_c_api.cpp | 632 | ||||
-rw-r--r-- | decoder/source/c_api/ocsd_c_api_custom_obj.cpp | 431 | ||||
-rw-r--r-- | decoder/source/c_api/ocsd_c_api_custom_obj.h | 189 | ||||
-rw-r--r-- | decoder/source/c_api/ocsd_c_api_obj.h | 182 |
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 */ |