Modifited the C-API test program to enable an option to create and use the echo_test external decoder. Validates the external decoder infrastucture.
Addition of error return on packet monitor and packet sink callback wrappers to indicate if has been correctly initialised.
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/include/c_api/ocsd_c_api_cust_impl.h | 18 +++++- decoder/include/c_api/ocsd_c_api_custom.h | 31 +++++++---- decoder/source/c_api/ocsd_c_api.cpp | 11 +++- decoder/tests/source/c_api_pkt_print_test.c | 83 ++++++++++++++++++++++------ 4 files changed, 111 insertions(+), 32 deletions(-)
diff --git a/decoder/include/c_api/ocsd_c_api_cust_impl.h b/decoder/include/c_api/ocsd_c_api_cust_impl.h index 084610f..dfecc78 100644 --- a/decoder/include/c_api/ocsd_c_api_cust_impl.h +++ b/decoder/include/c_api/ocsd_c_api_cust_impl.h @@ -49,7 +49,7 @@ inline ocsd_datapath_resp_t lib_cb_GenElemOp(const ocsd_extern_dcd_cb_fns *callb return OCSD_RESP_FATAL_NOT_INIT; }
-inline void lib_cb_LogError(const ocsd_extern_dcd_cb_fns *callbacks, +inline ocsd_err_t lib_cb_LogError(const ocsd_extern_dcd_cb_fns *callbacks, const ocsd_err_severity_t filter_level, const ocsd_err_t code, const ocsd_trc_index_t idx, @@ -57,15 +57,23 @@ inline void lib_cb_LogError(const ocsd_extern_dcd_cb_fns *callbacks, const char *pMsg) { if (callbacks->fn_log_error) + { callbacks->fn_log_error(callbacks->lib_context, filter_level, code, idx, chan_id, pMsg); + return OCSD_OK; + } + return OCSD_ERR_NOT_INIT; }
-inline void lib_cb_LogMsg(const ocsd_extern_dcd_cb_fns *callbacks, +inline ocsd_err_t lib_cb_LogMsg(const ocsd_extern_dcd_cb_fns *callbacks, const ocsd_err_severity_t filter_level, const char *pMsg) { if (callbacks->fn_log_msg) + { callbacks->fn_log_msg(callbacks->lib_context, filter_level, pMsg); + return OCSD_OK; + } + return OCSD_ERR_NOT_INIT; }
inline ocsd_err_t lib_cb_DecodeArmInst(const ocsd_extern_dcd_cb_fns *callbacks, @@ -107,7 +115,6 @@ inline int lib_cb_usePktMon(const ocsd_extern_dcd_cb_fns *callbacks) return (callbacks->packetCBFlags & OCSD_CUST_DCD_PKT_CB_USE_MON); }
- /* callback function to connect to the packet sink interface, on the main decode data path - used if decoder created as packet processor only */ inline ocsd_datapath_resp_t lib_cb_PktDataSink(const ocsd_extern_dcd_cb_fns *callbacks, @@ -130,4 +137,9 @@ inline int lib_cb_usePktSink(const ocsd_extern_dcd_cb_fns *callbacks) return (callbacks->packetCBFlags & OCSD_CUST_DCD_PKT_CB_USE_SINK); }
+inline void lib_cb_updatePktCBFlags(ocsd_extern_dcd_cb_fns *callbacks, const int newFlags) +{ + callbacks->packetCBFlags = newFlags; +} + #endif /* ARM_OCSD_C_API_CUST_IMPL_H_INCLUDED */ diff --git a/decoder/include/c_api/ocsd_c_api_custom.h b/decoder/include/c_api/ocsd_c_api_custom.h index 7d396ca..ea65fd3 100644 --- a/decoder/include/c_api/ocsd_c_api_custom.h +++ b/decoder/include/c_api/ocsd_c_api_custom.h @@ -57,7 +57,13 @@ typedef ocsd_datapath_resp_t (* fnGenElemOpCB)( const void *lib_context, const ocsd_generic_trace_elem *elem);
/* callback functions to connect into the library error logging mechanism */ -typedef void (* fnLogErrorCB)(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); +typedef void (* fnLogErrorCB)( 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); + typedef void (* fnLogMsgCB)(const void *lib_context, const ocsd_err_severity_t filter_level, const char *msg);
/* callback function to connect an ARM instruction decoder */ @@ -88,18 +94,23 @@ typedef ocsd_datapath_resp_t (* fnPktDataSinkCB)( const void *lib_context,
/** an instance of this is owned by the decoder, filled in by the library - allows the CB fns in the library decode tree to be called. */ typedef struct _ocsd_extern_dcd_cb_fns { - fnGenElemOpCB fn_gen_elem_out; - fnLogErrorCB fn_log_error; - fnLogMsgCB fn_log_msg; - fnDecodeArmInstCB fn_arm_instruction_decode; - fnMemAccessCB fn_memory_access; - fnPktMonCB fn_packet_mon; - fnPktDataSinkCB fn_packet_data_sink; - const void *lib_context; - int packetCBFlags; /**< Flags to indicate if the packet sink / packet monitor callbacks are in use. */ +/* Callback functions */ + fnGenElemOpCB fn_gen_elem_out; /**< Callback to output a generic element. */ + fnLogErrorCB fn_log_error; /**< Callback to output an error. */ + fnLogMsgCB fn_log_msg; /**< Callback to output a message. */ + fnDecodeArmInstCB fn_arm_instruction_decode; /**< Callback to decode an ARM instruction. */ + fnMemAccessCB fn_memory_access; /**< Callback to access memory images related to the trace capture. */ + fnPktMonCB fn_packet_mon; /**< Callback to output trace packet to packet monitor. */ + fnPktDataSinkCB fn_packet_data_sink; /**< Callback to output trace packet to packet sink - if in pack processing only mode. */ +/* CB in use flags. */ + int packetCBFlags; /**< Flags to indicate if the packet sink / packet monitor callbacks are in use. ( OCSD_CUST_DCD_PKT_CB_USE_MON / OCSD_CUST_DCD_PKT_CB_USE_SINK) */ +/* library context */ + const void *lib_context; /** library context pointer - use in callbacks to allow the library to load the correct context data. */ } ocsd_extern_dcd_cb_fns;
+/** Flag to indicate the the packet monitor is in use in the library */ #define OCSD_CUST_DCD_PKT_CB_USE_MON 0x1 +/** Flag to indicate the the packet sink is in use in the library */ #define OCSD_CUST_DCD_PKT_CB_USE_SINK 0x2
/** Owned by the library instance object, this structure is filled in by the ocsd_extern_dcd_fact_t createDecoder() function. */ diff --git a/decoder/source/c_api/ocsd_c_api.cpp b/decoder/source/c_api/ocsd_c_api.cpp index da3e557..e38167f 100644 --- a/decoder/source/c_api/ocsd_c_api.cpp +++ b/decoder/source/c_api/ocsd_c_api.cpp @@ -203,10 +203,14 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h { 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: @@ -215,15 +219,16 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h
if(err == OCSD_OK) { - err = pElem->getDecoderMngr()->attachPktSink(pElem->getDecoderHandle(),pDataInSink); - 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()) + if (it != s_data_map.end()) it->second->cb_objs.push_back(pDataInSink); } + else + delete pDataInSink; } return err; } diff --git a/decoder/tests/source/c_api_pkt_print_test.c b/decoder/tests/source/c_api_pkt_print_test.c index bc1c870..a468556 100644 --- a/decoder/tests/source/c_api_pkt_print_test.c +++ b/decoder/tests/source/c_api_pkt_print_test.c @@ -55,6 +55,12 @@ /* include the C-API library header */ #include "c_api/opencsd_c_api.h"
+/* include the test external decoder factory and decoder types headers + - separate from the main library includes by definition as external decoder. +*/ +#include "ext_dcd_echo_test_fact.h" +#include "ext_dcd_echo_test.h" + /* path to test snapshots, relative to tests/bin/<plat>/<dbg|rel> build output dir */ #ifdef _WIN32 const char *default_path_to_snapshot = "..\..\..\snapshots\juno_r1_1\"; @@ -91,6 +97,10 @@ static test_op_t op = TEST_PKT_PRINT; // default operation is to packet print static ocsd_trace_protocol_t test_protocol = OCSD_PROTOCOL_ETMV4I; // ETMV4 protocl static uint8_t test_trc_id_override = 0x00; // no trace ID override.
+/* external decoder testing */ +static int test_extern_decoder = 0; /* test the external decoder infrastructure. */ +static ocsd_extern_dcd_fact_t *p_ext_fact; /* external decoder factory */ +#define EXT_DCD_NAME "ext_echo"
/* Process command line options - choose the operation to use for the test. */ static int process_cmd_line(int argc, char *argv[]) @@ -143,6 +153,10 @@ static int process_cmd_line(int argc, char *argv[]) use_region_file = 1; using_mem_acc_cb = 0; } + else if (strcmp(argv[idx], "-extern") == 0) + { + test_extern_decoder = 1; + } else if(strcmp(argv[idx],"-help") == 0) { return -1; @@ -396,11 +410,12 @@ static int print_data_array(const uint8_t *p_array, const int array_size, char * * Callback function to process packets and packet data from the monitor output of the * packet processor. Again print them to the library error logger. */ -void packet_monitor(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) +void packet_monitor( void *context, + 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) { int offset = 0;
@@ -630,27 +645,57 @@ static ocsd_err_t create_decoder_stm(dcd_tree_handle_t dcd_tree_h) trace_config_stm.reg_feat1r = 0; trace_config_stm.hw_event = HwEvent_Unknown_Disabled;
- /* STM only has packet processor at present */ - if(op == TEST_PKT_PRINT) /* packet printing only */ - { - ret = create_generic_decoder(dcd_tree_h,OCSD_BUILTIN_DCD_STM,(void *)&trace_config_stm,0); - } - else + /* create a STM decoder - no context needed as we have a single stream to a single handler. */ + return create_generic_decoder(dcd_tree_h, OCSD_BUILTIN_DCD_STM, (void *)&trace_config_stm, 0); +} + +static ocsd_err_t create_decoder_extern(dcd_tree_handle_t dcd_tree_h) +{ + echo_dcd_cfg_t trace_cfg_ext; + + /* setup the custom configuration */ + trace_cfg_ext.cs_id = 0x010; + if (test_trc_id_override != 0) { - /* Full decode */ - /* not supported in library at present */ - printf("STM Full decode not supported in library at present. Packet print only\n"); - ret = OCSD_ERR_RDR_NO_DECODER; + trace_cfg_ext.cs_id = (uint32_t)test_trc_id_override; } - return ret; + + /* create an external decoder - no context needed as we have a single stream to a single handler. */ + return create_generic_decoder(dcd_tree_h, EXT_DCD_NAME, (void *)&trace_cfg_ext, 0); }
/************************************************************************/
+ocsd_err_t register_extern_decoder() +{ + ocsd_err_t err = OCSD_ERR_NO_PROTOCOL; + + p_ext_fact = ext_echo_get_dcd_fact(); + if (p_ext_fact) + { + err = ocsd_register_custom_decoder(EXT_DCD_NAME, p_ext_fact); + if (err == OCSD_OK) + test_protocol = p_ext_fact->protocol_id; + else + printf("External Decoder Registration: Failed to register decoder."); + } + else + printf("External Decoder Registration: Failed to get decoder factory."); + + return err; +} + /* create a decoder according to options */ static ocsd_err_t create_decoder(dcd_tree_handle_t dcd_tree_h) { ocsd_err_t err = OCSD_OK; + + /* extended for the external decoder testing*/ + if (test_extern_decoder) + err = register_extern_decoder(); + if (err != OCSD_OK) + return err; + switch(test_protocol) { case OCSD_PROTOCOL_ETMV4I: @@ -669,6 +714,12 @@ static ocsd_err_t create_decoder(dcd_tree_handle_t dcd_tree_h) err = create_decoder_ptm(dcd_tree_h); break;
+ /* we only register a single external decoder in this test, + so it will always be assigned the first custom protocol ID */ + case OCSD_PROTOCOL_CUSTOM_0: + err = create_decoder_extern(dcd_tree_h); + break; + default: err = OCSD_ERR_NO_PROTOCOL; break;