3 * \brief OpenCSD : "C" API libary implementation.
5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
9 * Redistribution and use in source and binary forms, with or without modification,
10 * are permitted provided that the following conditions are met:
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
19 * 3. Neither the name of the copyright holder nor the names of its contributors
20 * may be used to endorse or promote products derived from this software without
21 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 /* pull in the C++ decode library */
40 /* C-API and wrapper objects */
41 #include "opencsd/c_api/opencsd_c_api.h"
42 #include "ocsd_c_api_obj.h"
44 /** MSVC2010 unwanted export workaround */
46 #if (_MSC_VER == 1600)
48 namespace std { const nothrow_t nothrow = nothrow_t(); }
52 /*******************************************************************************/
53 /* C API internal helper function declarations */
54 /*******************************************************************************/
56 static ocsd_err_t ocsd_create_pkt_sink_cb(ocsd_trace_protocol_t protocol, FnDefPktDataIn pPktInFn, const void *p_context, ITrcTypedBase **ppCBObj );
57 static ocsd_err_t ocsd_create_pkt_mon_cb(ocsd_trace_protocol_t protocol, FnDefPktDataMon pPktInFn, const void *p_context, ITrcTypedBase **ppCBObj );
58 static ocsd_err_t ocsd_check_and_add_mem_acc_mapper(const dcd_tree_handle_t handle, DecodeTree **ppDT);
60 /*******************************************************************************/
61 /* C library data - additional data on top of the C++ library objects */
62 /*******************************************************************************/
64 /* keep a list of interface objects for a decode tree for later disposal */
65 typedef struct _lib_dt_data_list {
66 std::vector<ITrcTypedBase *> cb_objs;
67 DefLogStrCBObj s_def_log_str_cb;
70 /* map lists to handles */
71 static std::map<dcd_tree_handle_t, lib_dt_data_list *> s_data_map;
73 /*******************************************************************************/
75 /*******************************************************************************/
77 /** Get Library version. Return a 32 bit version in form MMMMnnpp - MMMM = major version, nn = minor version, pp = patch version */
78 OCSD_C_API uint32_t ocsd_get_version(void)
80 return ocsdVersion::vers_num();
83 /** Get library version string */
84 OCSD_C_API const char * ocsd_get_version_str(void)
86 return ocsdVersion::vers_str();
90 /*** Decode tree creation etc. */
92 OCSD_C_API dcd_tree_handle_t ocsd_create_dcd_tree(const ocsd_dcd_tree_src_t src_type, const uint32_t deformatterCfgFlags)
94 dcd_tree_handle_t handle = C_API_INVALID_TREE_HANDLE;
95 handle = (dcd_tree_handle_t)DecodeTree::CreateDecodeTree(src_type,deformatterCfgFlags);
96 if(handle != C_API_INVALID_TREE_HANDLE)
98 lib_dt_data_list *pList = new (std::nothrow) lib_dt_data_list;
101 s_data_map.insert(std::pair<dcd_tree_handle_t, lib_dt_data_list *>(handle,pList));
105 ocsd_destroy_dcd_tree(handle);
106 handle = C_API_INVALID_TREE_HANDLE;
112 OCSD_C_API void ocsd_destroy_dcd_tree(const dcd_tree_handle_t handle)
114 if(handle != C_API_INVALID_TREE_HANDLE)
116 GenTraceElemCBObj * pIf = (GenTraceElemCBObj *)(((DecodeTree *)handle)->getGenTraceElemOutI());
120 /* need to clear any associated callback data. */
121 std::map<dcd_tree_handle_t, lib_dt_data_list *>::iterator it;
122 it = s_data_map.find(handle);
123 if(it != s_data_map.end())
125 std::vector<ITrcTypedBase *>::iterator itcb;
126 itcb = it->second->cb_objs.begin();
127 while(itcb != it->second->cb_objs.end())
132 it->second->cb_objs.clear();
134 s_data_map.erase(it);
136 DecodeTree::DestroyDecodeTree((DecodeTree *)handle);
140 /*** Decode tree process data */
142 OCSD_C_API ocsd_datapath_resp_t ocsd_dt_process_data(const dcd_tree_handle_t handle,
143 const ocsd_datapath_op_t op,
144 const ocsd_trc_index_t index,
145 const uint32_t dataBlockSize,
146 const uint8_t *pDataBlock,
147 uint32_t *numBytesProcessed)
149 ocsd_datapath_resp_t resp = OCSD_RESP_FATAL_NOT_INIT;
150 if(handle != C_API_INVALID_TREE_HANDLE)
151 resp = ((DecodeTree *)handle)->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed);
155 /*** Decode tree - decoder management */
157 OCSD_C_API ocsd_err_t ocsd_dt_create_decoder(const dcd_tree_handle_t handle,
158 const char *decoder_name,
159 const int create_flags,
160 const void *decoder_cfg,
164 ocsd_err_t err = OCSD_OK;
165 DecodeTree *dt = (DecodeTree *)handle;
166 std::string dName = decoder_name;
167 IDecoderMngr *pDcdMngr;
168 err = OcsdLibDcdRegister::getDecoderRegister()->getDecoderMngrByName(dName,&pDcdMngr);
172 CSConfig *pConfig = 0;
173 err = pDcdMngr->createConfigFromDataStruct(&pConfig,decoder_cfg);
177 err = dt->createDecoder(dName,create_flags,pConfig);
179 *pCSID = pConfig->getTraceID();
184 OCSD_C_API ocsd_err_t ocsd_dt_remove_decoder( const dcd_tree_handle_t handle,
185 const unsigned char CSID)
187 return ((DecodeTree *)handle)->removeDecoder(CSID);
190 OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t handle,
191 const unsigned char CSID,
192 const ocsd_c_api_cb_types callback_type,
193 void *p_fn_callback_data,
194 const void *p_context)
196 ocsd_err_t err = OCSD_OK;
197 DecodeTree *pDT = static_cast<DecodeTree *>(handle);
198 DecodeTreeElement *pElem = pDT->getDecoderElement(CSID);
200 return OCSD_ERR_INVALID_ID; // cannot find entry for that CSID
202 ITrcTypedBase *pDataInSink = 0; // pointer to a sink callback object
203 switch(callback_type)
205 case OCSD_C_API_CB_PKT_SINK:
206 err = ocsd_create_pkt_sink_cb(pElem->getProtocol(),(FnDefPktDataIn)p_fn_callback_data,p_context,&pDataInSink);
208 err = pElem->getDecoderMngr()->attachPktSink(pElem->getDecoderHandle(), pDataInSink);
211 case OCSD_C_API_CB_PKT_MON:
212 err = ocsd_create_pkt_mon_cb(pElem->getProtocol(),(FnDefPktDataMon)p_fn_callback_data,p_context,&pDataInSink);
214 err = pElem->getDecoderMngr()->attachPktMonitor(pElem->getDecoderHandle(), pDataInSink);
218 err = OCSD_ERR_INVALID_PARAM_VAL;
225 // save object pointer for destruction later.
226 std::map<dcd_tree_handle_t, lib_dt_data_list *>::iterator it;
227 it = s_data_map.find(handle);
228 if (it != s_data_map.end())
229 it->second->cb_objs.push_back(pDataInSink);
237 /*** Decode tree set element output */
239 OCSD_C_API ocsd_err_t ocsd_dt_set_gen_elem_outfn(const dcd_tree_handle_t handle, FnTraceElemIn pFn, const void *p_context)
242 GenTraceElemCBObj * pCBObj = new (std::nothrow)GenTraceElemCBObj(pFn, p_context);
245 ((DecodeTree *)handle)->setGenTraceElemOutI(pCBObj);
252 /*** Default error logging */
254 OCSD_C_API ocsd_err_t ocsd_def_errlog_init(const ocsd_err_severity_t verbosity, const int create_output_logger)
256 if(DecodeTree::getDefaultErrorLogger()->initErrorLogger(verbosity,(bool)(create_output_logger != 0)))
258 return OCSD_ERR_NOT_INIT;
261 OCSD_C_API ocsd_err_t ocsd_def_errlog_config_output(const int output_flags, const char *log_file_name)
263 ocsdMsgLogger *pLogger = DecodeTree::getDefaultErrorLogger()->getOutputLogger();
266 pLogger->setLogOpts(output_flags & C_API_MSGLOGOUT_MASK);
267 if(log_file_name != NULL)
269 pLogger->setLogFileName(log_file_name);
273 return OCSD_ERR_NOT_INIT;
277 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)
279 ocsdMsgLogger *pLogger = DecodeTree::getDefaultErrorLogger()->getOutputLogger();
282 std::map<dcd_tree_handle_t, lib_dt_data_list *>::iterator it;
283 it = s_data_map.find(handle);
284 if (it != s_data_map.end())
286 DefLogStrCBObj *pCBObj = &(it->second->s_def_log_str_cb);
287 pCBObj->setCBFn(p_context, p_str_print_cb);
288 pLogger->setStrOutFn(pCBObj);
289 int logOpts = pLogger->getLogOpts();
290 logOpts |= (int)(ocsdMsgLogger::OUT_STR_CB);
291 pLogger->setLogOpts(logOpts);
295 return OCSD_ERR_NOT_INIT;
298 OCSD_C_API void ocsd_def_errlog_msgout(const char *msg)
300 ocsdMsgLogger *pLogger = DecodeTree::getDefaultErrorLogger()->getOutputLogger();
302 pLogger->LogMsg(msg);
305 /*** Convert packet to string */
307 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)
309 ocsd_err_t err = OCSD_OK;
310 if((buffer == NULL) || (buffer_size < 2))
311 return OCSD_ERR_INVALID_PARAM_VAL;
313 std::string pktStr = "";
318 case OCSD_PROTOCOL_ETMV4I:
319 trcPrintElemToString<EtmV4ITrcPacket,ocsd_etmv4_i_pkt>(p_pkt, pktStr);
322 case OCSD_PROTOCOL_ETMV3:
323 trcPrintElemToString<EtmV3TrcPacket,ocsd_etmv3_pkt>(p_pkt, pktStr);
326 case OCSD_PROTOCOL_STM:
327 trcPrintElemToString<StmTrcPacket,ocsd_stm_pkt>(p_pkt, pktStr);
330 case OCSD_PROTOCOL_PTM:
331 trcPrintElemToString<PtmTrcPacket,ocsd_ptm_pkt>(p_pkt, pktStr);
335 if (OCSD_PROTOCOL_IS_CUSTOM(pkt_protocol))
336 err = ocsd_cust_protocol_to_str(pkt_protocol, p_pkt, buffer, buffer_size);
338 err = OCSD_ERR_NO_PROTOCOL;
342 if(pktStr.size() > 0)
344 strncpy(buffer,pktStr.c_str(),buffer_size-1);
345 buffer[buffer_size-1] = 0;
350 OCSD_C_API ocsd_err_t ocsd_gen_elem_str(const ocsd_generic_trace_elem *p_pkt, char *buffer, const int buffer_size)
352 ocsd_err_t err = OCSD_OK;
353 if((buffer == NULL) || (buffer_size < 2))
354 return OCSD_ERR_INVALID_PARAM_VAL;
356 trcPrintElemToString<OcsdTraceElement,ocsd_generic_trace_elem>(p_pkt,str);
359 strncpy(buffer,str.c_str(),buffer_size -1);
360 buffer[buffer_size-1] = 0;
365 /*** Decode tree -- memory accessor control */
367 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)
369 ocsd_err_t err = OCSD_OK;
371 err = ocsd_check_and_add_mem_acc_mapper(handle,&pDT);
373 err = pDT->addBinFileMemAcc(address,mem_space,filepath);
377 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)
379 ocsd_err_t err = OCSD_OK;
381 err = ocsd_check_and_add_mem_acc_mapper(handle,&pDT);
383 err = pDT->addBinFileRegionMemAcc(region_array,num_regions,mem_space,filepath);
387 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)
389 ocsd_err_t err = OCSD_OK;
391 err = ocsd_check_and_add_mem_acc_mapper(handle,&pDT);
393 err = pDT->addBufferMemAcc(address,mem_space,p_mem_buffer,mem_length);
397 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)
399 ocsd_err_t err = OCSD_OK;
401 err = ocsd_check_and_add_mem_acc_mapper(handle,&pDT);
403 err = pDT->addCallbackMemAcc(st_address,en_address,mem_space,p_cb_func,p_context);
407 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)
409 ocsd_err_t err = OCSD_OK;
411 err = ocsd_check_and_add_mem_acc_mapper(handle, &pDT);
413 err = pDT->addCallbackIDMemAcc(st_address, en_address, mem_space, p_cb_func, p_context);
418 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)
420 ocsd_err_t err = OCSD_OK;
422 if(handle != C_API_INVALID_TREE_HANDLE)
424 DecodeTree *pDT = static_cast<DecodeTree *>(handle);
425 err = pDT->removeMemAccByAddress(st_address,mem_space);
428 err = OCSD_ERR_INVALID_PARAM_VAL;
432 OCSD_C_API void ocsd_tl_log_mapped_mem_ranges(const dcd_tree_handle_t handle)
434 if(handle != C_API_INVALID_TREE_HANDLE)
436 DecodeTree *pDT = static_cast<DecodeTree *>(handle);
437 pDT->logMappedRanges();
441 OCSD_C_API void ocsd_gen_elem_init(ocsd_generic_trace_elem *p_pkt, const ocsd_gen_trc_elem_t elem_type)
443 p_pkt->elem_type = elem_type;
444 p_pkt->flag_bits = 0;
445 p_pkt->ptr_extended_data = 0;
448 OCSD_C_API ocsd_err_t ocsd_dt_set_raw_frame_printer(const dcd_tree_handle_t handle, int flags)
450 if (handle != C_API_INVALID_TREE_HANDLE)
451 return ((DecodeTree *)handle)->addRawFramePrinter(0, (uint32_t)flags);
452 return OCSD_ERR_NOT_INIT;
455 OCSD_C_API ocsd_err_t ocsd_dt_set_gen_elem_printer(const dcd_tree_handle_t handle)
457 if (handle != C_API_INVALID_TREE_HANDLE)
458 return ((DecodeTree *)handle)->addGenElemPrinter(0);
459 return OCSD_ERR_NOT_INIT;
462 OCSD_C_API ocsd_err_t ocsd_dt_set_pkt_protocol_printer(const dcd_tree_handle_t handle, uint8_t cs_id, int monitor)
464 ocsd_err_t err = OCSD_ERR_NOT_INIT;
465 if (handle != C_API_INVALID_TREE_HANDLE)
467 DecodeTree *p_tree = (DecodeTree *)handle;
468 err = p_tree->addPacketPrinter(cs_id, (bool)(monitor != 0), 0);
473 /*******************************************************************************/
474 /* C API local fns */
475 /*******************************************************************************/
476 static ocsd_err_t ocsd_create_pkt_sink_cb(ocsd_trace_protocol_t protocol, FnDefPktDataIn pPktInFn, const void *p_context, ITrcTypedBase **ppCBObj )
478 ocsd_err_t err = OCSD_OK;
483 case OCSD_PROTOCOL_ETMV4I:
484 *ppCBObj = new (std::nothrow) PktCBObj<EtmV4ITrcPacket>(pPktInFn,p_context);
487 case OCSD_PROTOCOL_ETMV3:
488 *ppCBObj = new (std::nothrow) PktCBObj<EtmV3TrcPacket>(pPktInFn,p_context);
491 case OCSD_PROTOCOL_PTM:
492 *ppCBObj = new (std::nothrow) PktCBObj<PtmTrcPacket>(pPktInFn,p_context);
495 case OCSD_PROTOCOL_STM:
496 *ppCBObj = new (std::nothrow) PktCBObj<StmTrcPacket>(pPktInFn,p_context);
500 if ((protocol >= OCSD_PROTOCOL_CUSTOM_0) && (protocol < OCSD_PROTOCOL_END))
502 *ppCBObj = new (std::nothrow) PktCBObj<void>(pPktInFn, p_context);
505 err = OCSD_ERR_NO_PROTOCOL;
509 if((*ppCBObj == 0) && (err == OCSD_OK))
515 static ocsd_err_t ocsd_create_pkt_mon_cb(ocsd_trace_protocol_t protocol, FnDefPktDataMon pPktInFn, const void *p_context, ITrcTypedBase **ppCBObj )
517 ocsd_err_t err = OCSD_OK;
522 case OCSD_PROTOCOL_ETMV4I:
523 *ppCBObj = new (std::nothrow) PktMonCBObj<EtmV4ITrcPacket>(pPktInFn,p_context);
526 case OCSD_PROTOCOL_ETMV3:
527 *ppCBObj = new (std::nothrow) PktMonCBObj<EtmV3TrcPacket>(pPktInFn,p_context);
530 case OCSD_PROTOCOL_PTM:
531 *ppCBObj = new (std::nothrow) PktMonCBObj<PtmTrcPacket>(pPktInFn,p_context);
534 case OCSD_PROTOCOL_STM:
535 *ppCBObj = new (std::nothrow) PktMonCBObj<StmTrcPacket>(pPktInFn,p_context);
539 if ((protocol >= OCSD_PROTOCOL_CUSTOM_0) && (protocol < OCSD_PROTOCOL_END))
541 *ppCBObj = new (std::nothrow) PktMonCBObj<void>(pPktInFn, p_context);
544 err = OCSD_ERR_NO_PROTOCOL;
548 if((*ppCBObj == 0) && (err == OCSD_OK))
554 static ocsd_err_t ocsd_check_and_add_mem_acc_mapper(const dcd_tree_handle_t handle, DecodeTree **ppDT)
557 if(handle == C_API_INVALID_TREE_HANDLE)
558 return OCSD_ERR_INVALID_PARAM_VAL;
559 *ppDT = static_cast<DecodeTree *>(handle);
560 if(!(*ppDT)->hasMemAccMapper())
561 return (*ppDT)->createMemAccMapper();
565 /*******************************************************************************/
566 /* C API Helper objects */
567 /*******************************************************************************/
569 /****************** Generic trace element output callback function ************/
570 GenTraceElemCBObj::GenTraceElemCBObj(FnTraceElemIn pCBFn, const void *p_context) :
571 m_c_api_cb_fn(pCBFn),
572 m_p_cb_context(p_context)
576 ocsd_datapath_resp_t GenTraceElemCBObj::TraceElemIn(const ocsd_trc_index_t index_sop,
577 const uint8_t trc_chan_id,
578 const OcsdTraceElement &elem)
580 return m_c_api_cb_fn(m_p_cb_context, index_sop, trc_chan_id, &elem);
583 /* End of File ocsd_c_api.cpp */