summaryrefslogtreecommitdiffstats
path: root/decoder/tests/ext_dcd_test_eg
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 07:24:57 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 07:24:57 +0000
commit070852d8604cece0c31f28ff3eb8d21d9ba415fb (patch)
tree9097175a6a5b8b7e37af9a96269ac0b61a0189cd /decoder/tests/ext_dcd_test_eg
parentInitial commit. (diff)
downloadlibopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.tar.xz
libopencsd-070852d8604cece0c31f28ff3eb8d21d9ba415fb.zip
Adding upstream version 1.3.3.upstream/1.3.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'decoder/tests/ext_dcd_test_eg')
-rw-r--r--decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test.c451
-rw-r--r--decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test.h93
-rw-r--r--decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test_fact.c104
-rw-r--r--decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test_fact.h48
4 files changed, 696 insertions, 0 deletions
diff --git a/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test.c b/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test.c
new file mode 100644
index 0000000..e2ad045
--- /dev/null
+++ b/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test.c
@@ -0,0 +1,451 @@
+/*
+* \file ext_dcd_echo_test_fact.c
+* \brief OpenCSD : Echo test custom decoder factory
+*
+* \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.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "opencsd/c_api/opencsd_c_api.h"
+#include "opencsd/c_api/ocsd_c_api_types.h"
+#include "opencsd/c_api/ocsd_c_api_cust_impl.h"
+
+#include "ext_dcd_echo_test_fact.h"
+#include "ext_dcd_echo_test.h"
+
+/** The name of the decoder */
+#define DECODER_NAME "ECHO_TEST"
+
+/********* External callback fns passed to library *****/
+/** Declare the trace data input function for the decoder - passed to library as call-back. */
+static ocsd_datapath_resp_t echo_dcd_trace_data_in(const void *decoder_handle,
+ const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index,
+ const uint32_t dataBlockSize,
+ const uint8_t *pDataBlock,
+ uint32_t *numBytesProcessed);
+
+/** Allow library to update the packet monitor / sink in use flags to allow decoder to call CB as appropriate.*/
+static void echo_dcd_update_mon_flags(const void *decoder_handle, const int flags);
+
+/********* Fns called by decoder creation factory *****/
+void echo_dcd_init(echo_decoder_t *decoder,
+ ocsd_extern_dcd_inst_t *p_decoder_inst,
+ const echo_dcd_cfg_t *p_config,
+ const ocsd_extern_dcd_cb_fns *p_lib_callbacks);
+
+void echo_dcd_pkt_tostr(echo_dcd_pkt_t *pkt, char *buffer, const int buflen);
+
+/********* Internal decoder functions *****/
+static void echo_dcd_reset(echo_decoder_t *decoder);
+static ocsd_datapath_resp_t echo_dcd_process_data(echo_decoder_t *decoder,
+ const ocsd_trc_index_t index,
+ const uint32_t dataBlockSize,
+ const uint8_t *pDataBlock,
+ uint32_t *numBytesProcessed);
+
+static ocsd_datapath_resp_t send_gen_packet(echo_decoder_t *decoder);
+static ocsd_datapath_resp_t analyse_packet(echo_decoder_t *decoder);
+static ocsd_datapath_resp_t send_none_data_op(echo_decoder_t *decoder, const ocsd_datapath_op_t op);
+static void print_init_test_message(echo_decoder_t *decoder);
+
+/******Infrastructure testing functionality *********************/
+/* As this is a test decoder we want to check which of the callbacks or call-ins are covered for a given test run
+ (by definition they can't all be - so will need a couple of runs to test all)
+*/
+enum {
+ TEST_COV_ERRORLOG_CB = 0,
+ TEST_COV_MSGLOG_CB,
+ TEST_COV_GEN_ELEM_CB,
+ TEST_COV_IDEC_CB,
+ TEST_COV_MEM_ACC_CB,
+ TEST_COV_PKTMON_CB,
+ TEST_COV_PKTSINK_CB,
+ TEST_COV_INDATA,
+ TEST_COV_INCBFLAGS,
+ /**/
+ TEST_COV_END
+};
+
+typedef enum {
+ TEST_RES_NA, /* not tested */
+ TEST_RES_OK, /* test OK */
+ TEST_RES_FAIL /* test fail */
+} test_result_t;
+
+static test_result_t coverage[TEST_COV_END] = { TEST_RES_NA };
+
+#define UPDATE_COVERAGE(i,r) { if(coverage[i] != TEST_RES_FAIL) coverage[i] = r; }
+
+static void print_test_cov_results(echo_decoder_t *decoder);
+
+/*************************/
+
+
+/** init decoder on creation, along with library instance structure */
+void echo_dcd_init(echo_decoder_t *decoder, ocsd_extern_dcd_inst_t *p_decoder_inst, const echo_dcd_cfg_t *p_config, const ocsd_extern_dcd_cb_fns *p_lib_callbacks)
+{
+ // initialise the decoder instance.
+
+ // zero out the structure
+ memset(decoder, 0, sizeof(echo_decoder_t));
+
+ memcpy(&(decoder->reg_config), p_config, sizeof(echo_dcd_cfg_t)); // copy in the config structure.
+ memcpy(&(decoder->lib_fns), p_lib_callbacks, sizeof(ocsd_extern_dcd_cb_fns)); // copy in the the library callbacks.
+
+ echo_dcd_reset(decoder);
+
+ // fill out the info to pass back to the library.
+
+ // set up the decoder handle, name and CS Trace ID
+ p_decoder_inst->decoder_handle = decoder;
+ p_decoder_inst->p_decoder_name = DECODER_NAME;
+ p_decoder_inst->cs_id = p_config->cs_id;
+
+ // set up the data input callback
+ p_decoder_inst->fn_data_in = echo_dcd_trace_data_in;
+ p_decoder_inst->fn_update_pkt_mon = echo_dcd_update_mon_flags;
+
+}
+
+void echo_dcd_pkt_tostr(echo_dcd_pkt_t *pkt, char *buffer, const int buflen)
+{
+ snprintf(buffer, buflen, "ECHOTP{%d} [0x%02X] (0x%08X)", pkt->header & 0x3, pkt->header, pkt->data);
+}
+
+/**** Main decoder implementation ****/
+ocsd_datapath_resp_t echo_dcd_trace_data_in(const void *decoder_handle,
+ const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index,
+ const uint32_t dataBlockSize,
+ const uint8_t *pDataBlock,
+ uint32_t *numBytesProcessed)
+{
+ ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+ echo_decoder_t *decoder = (echo_decoder_t *)decoder_handle;
+ UPDATE_COVERAGE(TEST_COV_INDATA,TEST_RES_OK)
+
+ /* Deal with each possible datapath operation.
+ */
+ switch (op)
+ {
+ case OCSD_OP_DATA:
+ resp = echo_dcd_process_data(decoder, index, dataBlockSize, pDataBlock, numBytesProcessed);
+ break;
+
+ case OCSD_OP_EOT:
+ if (decoder->data_in_count > 0)
+ lib_cb_LogError(&(decoder->lib_fns), OCSD_ERR_SEV_WARN, OCSD_ERR_PKT_INTERP_FAIL,decoder->curr_pkt_idx,decoder->reg_config.cs_id,"Incomplete packet at end of trace.\n");
+
+ /* if we are in full decoder mode then generate a generic EOT packet. */
+ if (decoder->createFlags & OCSD_CREATE_FLG_FULL_DECODER)
+ {
+ ocsd_gen_elem_init(&(decoder->out_pkt), OCSD_GEN_TRC_ELEM_EO_TRACE);
+ resp = send_gen_packet(decoder);
+ send_none_data_op(decoder, OCSD_OP_EOT); /* send EOT to any packet monitor in use */
+ }
+ else
+ resp = send_none_data_op(decoder, OCSD_OP_EOT); /*send EOT to packet sink and any packet monitor in use */
+ print_test_cov_results(decoder); /* end of test run - need to print out the coverage data */
+ break;
+
+ case OCSD_OP_FLUSH:
+ /* This decoder never saves a list of incoming packets (which some real decoders may have to according to protocol).
+ Additionally this decoder both processes packets and analyses them so there is no second stage to pass the flush request on to.
+ Therefore there is nothing to flush */
+ break;
+
+ case OCSD_OP_RESET:
+ echo_dcd_reset(decoder);
+ break;
+ }
+ return resp;
+}
+
+void echo_dcd_update_mon_flags(const void *decoder_handle, const int flags)
+{
+ lib_cb_updatePktCBFlags(&((echo_decoder_t *)decoder_handle)->lib_fns, flags);
+ UPDATE_COVERAGE(TEST_COV_INCBFLAGS,TEST_RES_OK)
+}
+
+void echo_dcd_reset(echo_decoder_t *decoder)
+{
+ decoder->curr_pkt.header = 0;
+ decoder->data_in_count = 0;
+ decoder->state = DCD_INIT;
+}
+
+ocsd_datapath_resp_t echo_dcd_process_data(echo_decoder_t *decoder,
+ const ocsd_trc_index_t index,
+ const uint32_t dataBlockSize,
+ const uint8_t *pDataBlock,
+ uint32_t *numBytesProcessed)
+{
+ ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+ uint32_t bytesUsed = 0;
+
+ while (OCSD_DATA_RESP_IS_CONT(resp) && (bytesUsed < dataBlockSize))
+ {
+ switch (decoder->state)
+ {
+
+ case DCD_INIT:
+ /* on initialisation / after reset output a not-synced indicator */
+ ocsd_gen_elem_init(&decoder->out_pkt, OCSD_GEN_TRC_ELEM_NO_SYNC);
+ resp = send_gen_packet(decoder);
+ decoder->state = DCD_WAIT_SYNC; /* wait for the first sync point */
+ print_init_test_message(decoder); /* because this is in fact a test decoder - print verification messages */
+ break;
+
+ case DCD_WAIT_SYNC:
+ /* In this 'protocol' sync will be a single 0x00 byte.
+ Some decoders may output "unsynced packets" markers if in packet processing only mode, or on the
+ packet monitor output if in use. We are not bothering here. */
+ if (pDataBlock[bytesUsed] == 0x00)
+ decoder->state = DCD_PROC_PACKETS;
+ bytesUsed++;
+ break;
+
+ case DCD_PROC_PACKETS:
+ /* collect our ECHO_DCD_PKT_SIZE byte packets into the data in buffer */
+ if (decoder->data_in_count < ECHO_DCD_PKT_SIZE)
+ {
+ if (decoder->data_in_count == 0)
+ decoder->curr_pkt_idx = index + bytesUsed; /* record the correct start of packet index in the buffer. */
+ decoder->data_in[decoder->data_in_count++] = pDataBlock[bytesUsed++];
+ }
+
+ /* if we have ECHO_DCD_PKT_SIZE bytes we have a packet */
+ if (decoder->data_in_count == ECHO_DCD_PKT_SIZE)
+ {
+ resp = analyse_packet(decoder);
+ decoder->data_in_count = 0; /* done with the current packet */
+ }
+ break;
+ }
+ }
+ *numBytesProcessed = bytesUsed;
+ return resp;
+}
+
+ocsd_datapath_resp_t send_gen_packet(echo_decoder_t *decoder)
+{
+ ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+ /* Only output generic decode packets if we are in full decode mode. */
+ if (decoder->createFlags & OCSD_CREATE_FLG_FULL_DECODER)
+ {
+ resp = lib_cb_GenElemOp(&decoder->lib_fns, decoder->curr_pkt_idx, decoder->reg_config.cs_id, &decoder->out_pkt);
+ UPDATE_COVERAGE(TEST_COV_GEN_ELEM_CB, (OCSD_DATA_RESP_IS_FATAL(resp) ? TEST_RES_FAIL : TEST_RES_OK))
+ }
+ return resp;
+}
+
+ocsd_datapath_resp_t send_none_data_op(echo_decoder_t *decoder, const ocsd_datapath_op_t op)
+{
+ ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+ ocsd_extern_dcd_cb_fns *p_fns = &(decoder->lib_fns);
+
+ /* send a none data op to the packet monitor or packet sink if in packet processing only mode
+ None data ops have the data parameters all set to 0.
+ */
+
+ /* if the packet monitor callback is in use. */
+ if (lib_cb_usePktMon(p_fns))
+ lib_cb_PktMon(p_fns, op, 0, 0, 0, 0);
+
+ /* if the packet sink is in use then we shouldn't be in full decoder mode.*/
+ if (lib_cb_usePktSink(p_fns))
+ resp = lib_cb_PktDataSink(p_fns, op, 0, 0);
+
+ return resp;
+}
+
+void print_init_test_message(echo_decoder_t * decoder)
+{
+ ocsd_extern_dcd_cb_fns *p_fns = &(decoder->lib_fns);
+ if (lib_cb_LogMsg(p_fns, OCSD_ERR_SEV_ERROR, "Echo_Test_Decoder: Init - LogMsgCB test.\n") == OCSD_OK)
+ UPDATE_COVERAGE(TEST_COV_MSGLOG_CB, TEST_RES_OK)
+ else
+ UPDATE_COVERAGE(TEST_COV_MSGLOG_CB, TEST_RES_FAIL)
+
+ if(lib_cb_LogError(p_fns, OCSD_ERR_SEV_ERROR, OCSD_OK, 0, decoder->reg_config.cs_id, "Echo_Test_Decoder - Init - LogErrorCB test.\n") == OCSD_OK)
+ UPDATE_COVERAGE(TEST_COV_ERRORLOG_CB, TEST_RES_OK)
+ else
+ UPDATE_COVERAGE(TEST_COV_ERRORLOG_CB, TEST_RES_FAIL)
+}
+
+void print_test_cov_results(echo_decoder_t *decoder)
+{
+ int i;
+ ocsd_extern_dcd_cb_fns *p_fns = &(decoder->lib_fns);
+ static char *results[] = {
+ "Not Tested", "Passed", "Failed"
+ };
+ static char *cov_elem_names[] = {
+ "ERRORLOG_CB",
+ "MSGLOG_CB",
+ "GEN_ELEM_CB",
+ "IDEC_CB",
+ "MEM_ACC_CB",
+ "PKTMON_CB",
+ "PKTSINK_CB",
+ "INDATA",
+ "INCBFLAGS"
+ };
+ char coverage_message[256];
+
+ for (i = 0; i < TEST_COV_END; i++)
+ {
+ sprintf(coverage_message, "Element %s : %s\n",cov_elem_names[i],results[coverage[i]]);
+ if (coverage[TEST_COV_MSGLOG_CB] == TEST_RES_OK) /* check we can use the msg logger for outputting the results */
+ lib_cb_LogMsg(p_fns, OCSD_ERR_SEV_ERROR, coverage_message);
+ else
+ printf("%s", coverage_message);
+ }
+}
+
+
+/* This is the packet decode portion of the decoder.
+* incoming protocol packets are analysed to create generic output packets.
+*/
+ocsd_datapath_resp_t analyse_packet(echo_decoder_t * decoder)
+{
+ ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+ ocsd_extern_dcd_cb_fns *p_fns = &(decoder->lib_fns);
+ uint32_t num_mem_bytes = 4;
+ uint8_t mem_buffer[4];
+ ocsd_instr_info instr_info;
+ ocsd_err_t err;
+
+ /* create a packet from the data */
+ decoder->curr_pkt.header = decoder->data_in[0];
+ decoder->curr_pkt.data = *((uint32_t *)&decoder->data_in[1]);
+
+ /* if the packet monitor callback is in use - output the newly created packet. */
+ if (lib_cb_usePktMon(p_fns))
+ {
+ lib_cb_PktMon(p_fns, OCSD_OP_DATA, decoder->curr_pkt_idx, (const void *)(&decoder->curr_pkt), ECHO_DCD_PKT_SIZE, decoder->data_in);
+ UPDATE_COVERAGE(TEST_COV_PKTMON_CB, TEST_RES_OK)
+ }
+
+ /* if the packet sink is in use then we shouldn't be in full decoder mode.*/
+ if (lib_cb_usePktSink(p_fns))
+ {
+ resp = lib_cb_PktDataSink(p_fns, OCSD_OP_DATA, decoder->curr_pkt_idx, (const void *)(&decoder->curr_pkt));
+ UPDATE_COVERAGE(TEST_COV_PKTSINK_CB, (OCSD_DATA_RESP_IS_FATAL(resp) ? TEST_RES_FAIL : TEST_RES_OK))
+ }
+ else if (decoder->createFlags & OCSD_CREATE_FLG_FULL_DECODER) /* no packet sink so are we full decoder? */
+ {
+ /* Full decode - generate generic output packets.
+
+ A real decoder will sometimes require multiple input packets per output packet, or may generate multiple output
+ packets per single input packet. Here we stick at 1:1 for test simplicity.
+
+ This code will also test the infrastructure callbacks to ensure that everything holds together correctly.
+ */
+
+ /* nominally 4 types of packet */
+ switch (decoder->curr_pkt.header & 0x3)
+ {
+ case 0:
+ ocsd_gen_elem_init(&decoder->out_pkt, OCSD_GEN_TRC_ELEM_CUSTOM); /* full custom packet */
+ decoder->out_pkt.extended_data = 1;/* mark the extended ptr in use */
+ decoder->out_pkt.ptr_extended_data = decoder->data_in; /* the custom packet data in this protocol just the packet itself (hence 'echo')*/
+ break;
+
+ case 1:
+ /* custom decoders can re-use existing packet types if they follow the rules for those types. */
+ ocsd_gen_elem_init(&decoder->out_pkt, OCSD_GEN_TRC_ELEM_INSTR_RANGE);
+ /* fake up an address range using the input data */
+ decoder->out_pkt.st_addr = decoder->curr_pkt.data & 0xFFFFFFF0;
+ decoder->out_pkt.en_addr = decoder->curr_pkt.data + 0x10 + (((uint32_t)decoder->curr_pkt.header) << 2);
+ decoder->out_pkt.isa = ocsd_isa_custom;
+ decoder->out_pkt.last_instr_exec = (decoder->curr_pkt.header & 0x4) ? 1 : 0;
+ break;
+
+ case 2:
+ /* test the memory access callback. */
+ err = lib_cb_MemAccess(p_fns, decoder->curr_pkt.data & 0xFFFFFFF0, decoder->reg_config.cs_id, OCSD_MEM_SPACE_ANY, &num_mem_bytes, mem_buffer);
+ if (err != OCSD_OK)
+ lib_cb_LogError(p_fns, OCSD_ERR_SEV_ERROR, err, decoder->curr_pkt_idx, decoder->reg_config.cs_id, "Error accessing memory area\n.");
+ UPDATE_COVERAGE(TEST_COV_MEM_ACC_CB,(err == OCSD_OK ? TEST_RES_OK : TEST_RES_FAIL))
+ if (num_mem_bytes == 0)
+ {
+ /* unable to read the address... */
+ ocsd_gen_elem_init(&decoder->out_pkt, OCSD_GEN_TRC_ELEM_ADDR_NACC);
+ decoder->out_pkt.st_addr = decoder->curr_pkt.data & 0xFFFFFFF0;
+ }
+ else
+ {
+ /* try something different */
+ ocsd_gen_elem_init(&decoder->out_pkt, OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
+ decoder->out_pkt.cycle_count = *((uint32_t *)mem_buffer);
+ decoder->out_pkt.has_cc = 1;
+ }
+ break;
+
+ case 3:
+ /* test the ARM instruction decode callback */
+ instr_info.pe_type.arch = ARCH_V8;
+ instr_info.pe_type.profile = profile_CortexA;
+ instr_info.isa = ocsd_isa_aarch64;
+ instr_info.opcode = decoder->curr_pkt.data;
+ instr_info.instr_addr = decoder->curr_pkt.data & 0xFFFFF000;
+ instr_info.dsb_dmb_waypoints = 0;
+
+ err = lib_cb_DecodeArmInst(p_fns, &instr_info);
+ UPDATE_COVERAGE(TEST_COV_IDEC_CB, (err == OCSD_OK ? TEST_RES_OK : TEST_RES_FAIL))
+ if (err != OCSD_OK)
+ {
+ lib_cb_LogError(p_fns, OCSD_ERR_SEV_ERROR, err, decoder->curr_pkt_idx, decoder->reg_config.cs_id, "Error decoding instruction\n.");
+ ocsd_gen_elem_init(&decoder->out_pkt, OCSD_GEN_TRC_ELEM_CUSTOM);
+ decoder->out_pkt.has_ts = 1;
+ decoder->out_pkt.timestamp = decoder->curr_pkt.data;
+ }
+ else
+ {
+ ocsd_gen_elem_init(&decoder->out_pkt, OCSD_GEN_TRC_ELEM_INSTR_RANGE);
+ /* fake up an address range using the input data */
+ decoder->out_pkt.st_addr = decoder->curr_pkt.data & 0xFFFFFFF0;
+ decoder->out_pkt.en_addr = decoder->curr_pkt.data + 0x10 + (((uint32_t)decoder->curr_pkt.header) << 2);
+ decoder->out_pkt.isa = ocsd_isa_aarch64;
+ decoder->out_pkt.last_instr_exec = (decoder->curr_pkt.header & 0x4) ? 1 : 0;
+ decoder->out_pkt.last_i_type = instr_info.type;
+ decoder->out_pkt.last_i_subtype = instr_info.sub_type;
+ }
+ break;
+ }
+ resp = send_gen_packet(decoder);
+ }
+ return resp;
+}
diff --git a/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test.h b/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test.h
new file mode 100644
index 0000000..b2fdb23
--- /dev/null
+++ b/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test.h
@@ -0,0 +1,93 @@
+/*
+* \file ext_dcd_echo_test_fact.h
+* \brief OpenCSD : Echo test custom decoder
+*
+* \copyright Copyright (c) 2016, ARM Limited. All Rights Reserved.
+*/
+
+/*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* 3. Neither the name of the copyright holder nor the names of its contributors
+* may be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ARM_EXT_DCD_ECHO_TEST_H_INCLUDED
+#define ARM_EXT_DCD_ECHO_TEST_H_INCLUDED
+
+#include <inttypes.h>
+#include "opencsd/c_api/ocsd_c_api_custom.h"
+
+/*
+ Echo test decoder designed to test the external decoder C - API infrastructure.
+ Echo decoders can be attached to any CS byte stream and will mainly echo the data
+ back with a simple "protocol" decoded - not based on real protocol.
+
+ Will test callback infrastructure and provide an implemntation example for a real external decoder.
+
+*/
+
+/*** decoder types ***/
+
+typedef struct _echo_dcd_cfg {
+ unsigned char cs_id;
+} echo_dcd_cfg_t;
+
+typedef struct _echo_dcd_pkt {
+ uint8_t header;
+ uint32_t data;
+} echo_dcd_pkt_t;
+
+typedef enum _echo_dcd_state {
+ DCD_INIT,
+ DCD_WAIT_SYNC,
+ DCD_PROC_PACKETS
+} echo_dcd_stat_t;
+
+/** 'packet' size is 5 bytes - 1 header + 4 data. */
+#define ECHO_DCD_PKT_SIZE 5
+
+/** main decoder structure */
+typedef struct _echo_decoder {
+ uint8_t data_in[ECHO_DCD_PKT_SIZE]; /** input buffer for current incoming packet data bytes */
+ int data_in_count; /** count up to the 5 bytes per packet to know when complete packet RX */
+ echo_dcd_pkt_t curr_pkt; /** current packet */
+ ocsd_trc_index_t curr_pkt_idx; /** buffer index for the current packet */
+ echo_dcd_cfg_t reg_config; /** Decoder config "registers" - in this case just the CSID value */
+ ocsd_extern_dcd_cb_fns lib_fns; /** Library Callback functions */
+ int createFlags; /** creation / operational options -> packet only / full decode */
+ echo_dcd_stat_t state; /** current state of the decoder. */
+ ocsd_generic_trace_elem out_pkt; /** generic output packet */
+} echo_decoder_t;
+
+
+
+/*** internal decoder API ***/
+
+/** decoder will contain packet printing logic */
+void echo_dcd_pkt_tostr(echo_dcd_pkt_t *pkt, char *buffer, const int buflen);
+
+/** init decoder on creation, along with library instance structure */
+void echo_dcd_init(echo_decoder_t *decoder, ocsd_extern_dcd_inst_t *p_decoder_inst, const echo_dcd_cfg_t *p_config, const ocsd_extern_dcd_cb_fns *p_lib_callbacks);
+
+#endif /* ARM_EXT_DCD_ECHO_TEST_H_INCLUDED */
+
diff --git a/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test_fact.c b/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test_fact.c
new file mode 100644
index 0000000..ecf4583
--- /dev/null
+++ b/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test_fact.c
@@ -0,0 +1,104 @@
+/*
+* \file ext_dcd_echo_test_fact.c
+* \brief OpenCSD : Echo test custom decoder factory
+*
+* \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.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ext_dcd_echo_test_fact.h"
+#include "ext_dcd_echo_test.h"
+
+/** Decoder factory implementation.
+ Permits registration of the decoder with the library.
+
+ Provides creation and deletion functionality for decoder instances.
+*/
+
+/*-- functions meeting the ext decode factory structure requirements */
+
+/** Required function to create a decoder instance - fills in the decoder struct supplied. */
+static ocsd_err_t ext_echo_create(const int create_flags, const void *decoder_cfg, const ocsd_extern_dcd_cb_fns *p_lib_callbacks, ocsd_extern_dcd_inst_t *p_decoder_inst);
+
+/** Required Function to destroy a decoder instance - indicated by decoder handle */
+static ocsd_err_t ext_echo_destroy(const void *decoder_handle);
+
+/** Required Function to extract the CoreSight Trace ID from the configuration structure */
+static ocsd_err_t ext_echo_csid_from_cfg(const void *decoder_cfg, unsigned char *p_csid);
+
+/** Optional Function to convert a protocol specific trace packet to human readable string */
+static ocsd_err_t ext_echo_pkt_to_str(const void *trc_pkt, char *buffer, const int buflen);
+
+static ocsd_extern_dcd_fact_t echo_test_decoder_fact;
+
+ocsd_extern_dcd_fact_t *ext_echo_get_dcd_fact()
+{
+ echo_test_decoder_fact.createDecoder = ext_echo_create;
+ echo_test_decoder_fact.destroyDecoder = ext_echo_destroy;
+ echo_test_decoder_fact.csidFromConfig = ext_echo_csid_from_cfg;
+ echo_test_decoder_fact.pktToString = ext_echo_pkt_to_str;
+ echo_test_decoder_fact.protocol_id = OCSD_PROTOCOL_END;
+ return &echo_test_decoder_fact;
+}
+
+ocsd_err_t ext_echo_create(const int create_flags, const void *decoder_cfg, const ocsd_extern_dcd_cb_fns *p_lib_callbacks, ocsd_extern_dcd_inst_t *p_decoder_inst)
+{
+ echo_decoder_t *decoder = NULL;
+
+ if ((decoder = (echo_decoder_t *)malloc(sizeof(echo_decoder_t))) == NULL)
+ return OCSD_ERR_MEM;
+
+ echo_dcd_init(decoder,p_decoder_inst,(echo_dcd_cfg_t *)decoder_cfg, p_lib_callbacks);
+
+ decoder->createFlags = create_flags;
+
+ return OCSD_OK;
+}
+
+ocsd_err_t ext_echo_destroy(const void *decoder_handle)
+{
+ free((echo_decoder_t *)decoder_handle);
+ return OCSD_OK;
+}
+
+ocsd_err_t ext_echo_csid_from_cfg(const void *decoder_cfg, unsigned char *p_csid)
+{
+ *p_csid = ((echo_dcd_cfg_t *)decoder_cfg)->cs_id;
+ return OCSD_OK;
+}
+
+ocsd_err_t ext_echo_pkt_to_str(const void *trc_pkt, char *buffer, const int buflen)
+{
+ echo_dcd_pkt_tostr((echo_dcd_pkt_t*)trc_pkt, buffer, buflen);
+ return OCSD_OK;
+}
diff --git a/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test_fact.h b/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test_fact.h
new file mode 100644
index 0000000..ef382f0
--- /dev/null
+++ b/decoder/tests/ext_dcd_test_eg/c_api_echo_test/ext_dcd_echo_test_fact.h
@@ -0,0 +1,48 @@
+/*
+* \file ext_dcd_echo_test_fact.h
+* \brief OpenCSD : Echo test custom decoder factory
+*
+* \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_EXT_DCD_ECHO_TEST_FACT_H_INCLUDED
+#define ARM_EXT_DCD_ECHO_TEST_FACT_H_INCLUDED
+
+/* Creates echo test decoders to test the external decoder C-API infrastructure.
+ Echo decoders can be attached to any CS byte stream and will mainly echo the data
+ back with a simple "protocol" decoded - not based on real protocol.
+ */
+
+#include "opencsd/c_api/ocsd_c_api_custom.h"
+
+/* return an initialised structure with the factory functions */
+extern ocsd_extern_dcd_fact_t *ext_echo_get_dcd_fact();
+
+
+#endif /*ARM_EXT_DCD_ECHO_TEST_FACT_H_INCLUDED */