blob: b2215bafb19b429d4d8e2cee1f838dceaca6702b [file] [log] [blame]
/*
* \file simple_pkt_c_api.c
* \brief Reference CoreSight Trace Decoder :
*
* \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.
*/
/*
* Example of using the library with the C-API
*
* Simple test program to print packets from a single trace source stream.
* Hard coded configuration based on the Juno r1-1 test snapshot for ETMv4 and
* STM, TC2 test snapshot for ETMv3
*
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
/* include the C-API library header */
#include "c_api/rctdl_c_api.h"
/* path to juno snapshot, relative to tests/bin/<plat>/<dbg|rel> build output dir */
#ifdef _WIN32
const char *default_path_to_snapshot = "..\\..\\..\\snapshots\\juno_r1_1\\";
const char *tc2_snapshot = "..\\..\\..\\snapshots\\TC2\\";
#else
const char *default_path_to_snapshot = "../../../snapshots/juno_r1_1/";
const char *tc2_snapshot = "../../../snapshots/TC2/";
#endif
/* trace data and memory file dump names */
const char *trace_data_filename = "cstrace.bin";
const char *stmtrace_data_filename = "cstraceitm.bin";
const char *memory_dump_filename = "kernel_dump.bin";
const rctdl_vaddr_t mem_dump_address=0xFFFFFFC000081000;
static int using_mem_acc_cb = 0;
static int use_region_file = 0;
/* region list to test region file API */
file_mem_region_t region_list[4];
/* trace configuration structures - contains programmed register values of trace hardware */
static rctdl_etmv4_cfg trace_config;
static rctdl_etmv3_cfg trace_config_etmv3;
static rctdl_stm_cfg trace_config_stm;
/* buffer to handle a packet string */
#define PACKET_STR_LEN 1024
static char packet_str[PACKET_STR_LEN];
/* decide if we decode & monitor, decode only or packet print */
typedef enum _test_op {
TEST_PKT_PRINT,
TEST_PKT_DECODE,
TEST_PKT_DECODEONLY
} test_op_t;
static test_op_t op = TEST_PKT_PRINT;
static rctdl_trace_protocol_t test_protocol = RCTDL_PROTOCOL_ETMV4I;
static uint8_t test_trc_id_override = 0x00;
static int print_data_array(const uint8_t *p_array, const int array_size, char *p_buffer, int buf_size)
{
int chars_printed = 0;
int bytes_processed;
p_buffer[0] = 0;
if(buf_size > 9)
{
/* set up the header */
strcat(p_buffer,"[ ");
chars_printed+=2;
for(bytes_processed = 0; bytes_processed < array_size; bytes_processed++)
{
sprintf(p_buffer+chars_printed,"0x%02X ", p_array[bytes_processed]);
chars_printed += 5;
if((chars_printed + 5) > buf_size)
break;
}
strcat(p_buffer,"];");
chars_printed+=2;
}
else if(buf_size >= 4)
{
sprintf(p_buffer,"[];");
chars_printed+=3;
}
return chars_printed;
}
/* choose the operation to use for the test. */
static void process_cmd_line(int argc, char *argv[])
{
int idx = 1;
while(idx < argc)
{
if(strcmp(argv[idx],"-decode_only") == 0)
{
op = TEST_PKT_DECODEONLY;
}
else if(strcmp(argv[idx],"-decode") == 0)
{
op = TEST_PKT_DECODE;
}
else if(strcmp(argv[idx],"-id") == 0)
{
idx++;
if(idx < argc)
{
test_trc_id_override = (uint8_t)(strtoul(argv[idx],0,0));
printf("ID override = 0x%02X\n",test_trc_id_override);
}
}
else if(strcmp(argv[idx],"-etmv3") == 0)
{
test_protocol = RCTDL_PROTOCOL_ETMV3;
default_path_to_snapshot = tc2_snapshot;
}
else if(strcmp(argv[idx],"-stm") == 0)
{
test_protocol = RCTDL_PROTOCOL_STM;
trace_data_filename = stmtrace_data_filename;
}
else if(strcmp(argv[idx],"-test_cb") == 0)
{
using_mem_acc_cb = 1;
}
else if(strcmp(argv[idx],"-test_region_file") == 0)
{
use_region_file = 1;
}
else
printf("Ignored unknown argument %s\n", argv[idx]);
idx++;
}
}
/* Callback function to process the packets in the stream -
simply print them out in this case
*/
rctdl_datapath_resp_t packet_handler(const rctdl_datapath_op_t op, const rctdl_trc_index_t index_sop, const void *p_packet_in)
{
rctdl_datapath_resp_t resp = RCTDL_RESP_CONT;
int offset = 0;
switch(op)
{
default: break;
case RCTDL_OP_DATA:
sprintf(packet_str,"Idx:%ld; ", index_sop);
offset = strlen(packet_str);
/* got a packet - convert to string and use the libraries' message output to print to file and stdoout */
if(rctdl_pkt_str(test_protocol,p_packet_in,packet_str+offset,PACKET_STR_LEN-offset) == RCTDL_OK)
{
/* add in <CR> */
if(strlen(packet_str) == PACKET_STR_LEN - 1) /* maximum length */
packet_str[PACKET_STR_LEN-2] = '\n';
else
strcat(packet_str,"\n");
/* print it using the library output logger. */
rctdl_def_errlog_msgout(packet_str);
}
else
resp = RCTDL_RESP_FATAL_INVALID_PARAM; /* mark fatal error */
break;
case RCTDL_OP_EOT:
sprintf(packet_str,"**** END OF TRACE ****\n");
rctdl_def_errlog_msgout(packet_str);
break;
}
return resp;
}
/* decode memory access using a CB function
* tests CB API and add / remove mem acc API.
*/
static FILE *dump_file = NULL;
static rctdl_mem_space_acc_t dump_file_mem_space = RCTDL_MEM_SPACE_ANY;
static long mem_file_size = 0;
static rctdl_vaddr_t mem_file_en_address = 0; /* end address last inclusive address in file. */
static uint32_t mem_acc_cb(const void *p_context, const rctdl_vaddr_t address, const rctdl_mem_space_acc_t mem_space, const uint32_t reqBytes, uint8_t *byteBuffer)
{
uint32_t read_bytes = 0;
size_t file_read_bytes;
if(dump_file == NULL)
return 0;
/* bitwise & the incoming mem space and supported mem space to confirm coverage */
if(((uint8_t)mem_space & (uint8_t)dump_file_mem_space ) == 0)
return 0;
/* calculate the bytes that can be read */
if((address >= mem_dump_address) && (address <= mem_file_en_address))
{
/* some bytes in our range */
read_bytes = reqBytes;
if((address + reqBytes - 1) > mem_file_en_address)
{
/* more than are available - just read the available */
read_bytes = (uint32_t)(mem_file_en_address - (address - 1));
}
}
/* read some bytes if more than 0 to read. */
if(read_bytes != 0)
{
fseek(dump_file,(long)(address-mem_dump_address),SEEK_SET);
file_read_bytes = fread(byteBuffer,sizeof(uint8_t),read_bytes,dump_file);
if(file_read_bytes < read_bytes)
read_bytes = file_read_bytes;
}
return read_bytes;
}
static rctdl_err_t create_mem_acc_cb(dcd_tree_handle_t dcd_tree_h, const char *mem_file_path)
{
rctdl_err_t err = RCTDL_OK;
dump_file = fopen(mem_file_path,"rb");
if(dump_file != NULL)
{
fseek(dump_file,0,SEEK_END);
mem_file_size = ftell(dump_file);
mem_file_en_address = mem_dump_address + mem_file_size - 1;
err = rctdl_dt_add_callback_mem_acc(dcd_tree_h,
mem_dump_address,mem_file_en_address,dump_file_mem_space,&mem_acc_cb,0);
if(err != RCTDL_OK)
{
fclose(dump_file);
dump_file = NULL;
}
}
else
err = RCTDL_ERR_MEM_ACC_FILE_NOT_FOUND;
return err;
}
static void destroy_mem_acc_cb(dcd_tree_handle_t dcd_tree_h)
{
if(dump_file != NULL)
{
rctdl_dt_remove_mem_acc(dcd_tree_h,mem_dump_address,dump_file_mem_space);
fclose(dump_file);
dump_file = NULL;
}
}
void packet_monitor(const rctdl_datapath_op_t op,
const rctdl_trc_index_t index_sop,
const void *p_packet_in,
const uint32_t size,
const uint8_t *p_data)
{
int offset = 0;
switch(op)
{
default: break;
case RCTDL_OP_DATA:
sprintf(packet_str,"Idx:%ld;", index_sop);
offset = strlen(packet_str);
offset+= print_data_array(p_data,size,packet_str+offset,PACKET_STR_LEN-offset);
/* got a packet - convert to string and use the libraries' message output to print to file and stdoout */
if(rctdl_pkt_str(test_protocol,p_packet_in,packet_str+offset,PACKET_STR_LEN-offset) == RCTDL_OK)
{
/* add in <CR> */
if(strlen(packet_str) == PACKET_STR_LEN - 1) /* maximum length */
packet_str[PACKET_STR_LEN-2] = '\n';
else
strcat(packet_str,"\n");
/* print it using the library output logger. */
rctdl_def_errlog_msgout(packet_str);
}
break;
case RCTDL_OP_EOT:
sprintf(packet_str,"**** END OF TRACE ****\n");
rctdl_def_errlog_msgout(packet_str);
break;
}
}
rctdl_datapath_resp_t gen_trace_elem_print(const void *p_context, const rctdl_trc_index_t index_sop, const uint8_t trc_chan_id, const rctdl_generic_trace_elem *elem)
{
rctdl_datapath_resp_t resp = RCTDL_RESP_CONT;
int offset = 0;
sprintf(packet_str,"Idx:%ld; TrcID:0x%02X; ", index_sop, trc_chan_id);
offset = strlen(packet_str);
if(rctdl_gen_elem_str(elem, packet_str+offset,PACKET_STR_LEN - offset) == RCTDL_OK)
{
/* add in <CR> */
if(strlen(packet_str) == PACKET_STR_LEN - 1) /* maximum length */
packet_str[PACKET_STR_LEN-2] = '\n';
else
strcat(packet_str,"\n");
}
else
{
strcat(packet_str,"Unable to create element string\n");
}
/* print it using the library output logger. */
rctdl_def_errlog_msgout(packet_str);
return resp;
}
/************************************************************************/
/*** ETMV4 ***/
/************************************************************************/
/* hard coded values from snapshot .ini files */
void set_config_struct_etmv4()
{
trace_config.arch_ver = ARCH_V8;
trace_config.core_prof = profile_CortexA;
trace_config.reg_configr = 0x000000C1;
trace_config.reg_traceidr = 0x00000010; /* this is the trace ID -> 0x10, change this to analyse other streams in snapshot.*/
if(test_trc_id_override != 0)
{
trace_config.reg_traceidr = (uint32_t)test_trc_id_override;
}
trace_config.reg_idr0 = 0x28000EA1;
trace_config.reg_idr1 = 0x4100F403;
trace_config.reg_idr2 = 0x00000488;
trace_config.reg_idr8 = 0x0;
trace_config.reg_idr9 = 0x0;
trace_config.reg_idr10 = 0x0;
trace_config.reg_idr11 = 0x0;
trace_config.reg_idr12 = 0x0;
trace_config.reg_idr13 = 0x0;
}
rctdl_datapath_resp_t etm_v4i_packet_handler(const void *p_context, const rctdl_datapath_op_t op, const rctdl_trc_index_t index_sop, const rctdl_etmv4_i_pkt *p_packet_in)
{
return packet_handler(op,index_sop,(const void *)p_packet_in);
}
void etm_v4i_packet_monitor( const void *p_context,
const rctdl_datapath_op_t op,
const rctdl_trc_index_t index_sop,
const rctdl_etmv4_i_pkt *p_packet_in,
const uint32_t size,
const uint8_t *p_data)
{
packet_monitor(op,index_sop,(void *)p_packet_in,size,p_data);
}
static rctdl_err_t create_decoder_etmv4(dcd_tree_handle_t dcd_tree_h)
{
rctdl_err_t ret = RCTDL_OK;
char mem_file_path[512];
int i;
uint32_t i0adjust = 0x100;
/* populate the ETMv4 configuration structure */
set_config_struct_etmv4();
if(op == TEST_PKT_PRINT) /* packet printing only */
{
/* Create a packet processor on the decode tree for the ETM v4 configuration we have.
We need to supply the configuration, and a packet handling callback.
*/
ret = rctdl_dt_create_etmv4i_pkt_proc(dcd_tree_h,&trace_config,&etm_v4i_packet_handler,0);
}
else
{
/* Full decode - need decoder, and memory dump */
/* create the packet decoder and packet processor pair */
ret = rctdl_dt_create_etmv4i_decoder(dcd_tree_h,&trace_config);
if(ret == RCTDL_OK)
{
if((op != TEST_PKT_DECODEONLY) && (ret == RCTDL_OK))
{
/* print the packets as well as the decode. */
ret = rctdl_dt_attach_etmv4i_pkt_mon(dcd_tree_h, (uint8_t)(trace_config.reg_traceidr & 0xFF), etm_v4i_packet_monitor,0);
}
}
/* trace data file path */
strcpy(mem_file_path,default_path_to_snapshot);
strcat(mem_file_path,memory_dump_filename);
if(ret == RCTDL_OK)
{
if(using_mem_acc_cb)
{
ret = create_mem_acc_cb(dcd_tree_h,mem_file_path);
}
else
{
if(use_region_file)
{
dump_file = fopen(mem_file_path,"rb");
if(dump_file != NULL)
{
fseek(dump_file,0,SEEK_END);
mem_file_size = ftell(dump_file);
fclose(dump_file);
/* populate the region list - split existing file into four regions */
for(i = 0; i < 4; i++)
{
if(i != 0)
i0adjust = 0;
region_list[i].start_address = mem_dump_address + (i * mem_file_size/4) + i0adjust;
region_list[i].region_size = (mem_file_size/4) - i0adjust;
region_list[i].file_offset = (i * mem_file_size/4) + i0adjust;
}
/* create a memory file accessor - full binary file */
ret = rctdl_dt_add_binfile_region_mem_acc(dcd_tree_h,&region_list[0],4,RCTDL_MEM_SPACE_ANY,mem_file_path);
}
else
ret = RCTDL_ERR_MEM_ACC_FILE_NOT_FOUND;
}
else
{
/* create a memory file accessor - full binary file */
ret = rctdl_dt_add_binfile_mem_acc(dcd_tree_h,mem_dump_address,RCTDL_MEM_SPACE_ANY,mem_file_path);
}
}
}
}
return ret;
}
/************************************************************************/
/*** ETMV3 ***/
/************************************************************************/
static void set_config_struct_etmv3()
{
trace_config_etmv3.arch_ver = ARCH_V7;
trace_config_etmv3.core_prof = profile_CortexA;
trace_config_etmv3.reg_ccer = 0x344008F2;
trace_config_etmv3.reg_ctrl = 0x10001860;
trace_config_etmv3.reg_idr = 0x410CF250;
trace_config_etmv3.reg_trc_id = 0x010;
if(test_trc_id_override != 0)
{
trace_config_etmv3.reg_trc_id = (uint32_t)test_trc_id_override;
}
}
rctdl_datapath_resp_t etm_v3_packet_handler(const void *p_context, const rctdl_datapath_op_t op, const rctdl_trc_index_t index_sop, const rctdl_etmv3_pkt *p_packet_in)
{
return packet_handler(op,index_sop,(const void *)p_packet_in);
}
void etm_v3_packet_monitor( const rctdl_datapath_op_t op,
const rctdl_trc_index_t index_sop,
const rctdl_etmv3_pkt *p_packet_in,
const uint32_t size,
const uint8_t *p_data)
{
packet_monitor(op,index_sop,(void *)p_packet_in,size,p_data);
}
static rctdl_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h)
{
rctdl_err_t ret = RCTDL_OK;
/*char mem_file_path[512];*/
/* populate the ETMv3 configuration structure */
set_config_struct_etmv3();
if(op == TEST_PKT_PRINT) /* packet printing only */
{
/* Create a packet processor on the decode tree for the ETM v4 configuration we have.
We need to supply the configuration, and a packet handling callback.
*/
ret = rctdl_dt_create_etmv3_pkt_proc(dcd_tree_h,&trace_config_etmv3,&etm_v3_packet_handler,0);
}
else
{
/* Full decode - need decoder, and memory dump */
/* not supported in library at present */
#if 0
/* create the packet decoder and packet processor pair */
ret = rctdl_dt_create_etmv3_decoder(dcd_tree_h,&trace_config_etmv3);
if(ret == RCTDL_OK)
{
if((op != TEST_PKT_DECODEONLY) && (ret == RCTDL_OK))
{
ret = rctdl_dt_attach_etmv3_pkt_mon(dcd_tree_h, (uint8_t)(trace_config_etmv3.reg_trc_id & 0x7F), etm_v4i_packet_monitor);
}
}
/* trace data file path */
strcpy(mem_file_path,tc2_snapshot);
strcat(mem_file_path,memory_dump_filename);
if(ret == RCTDL_OK)
{
/* create a memory file accessor */
ret = rctdl_dt_add_binfile_mem_acc(dcd_tree_h,mem_dump_address,RCTDL_MEM_SPACE_ANY,mem_file_path);
}
#else
printf("ETMv3 Full decode not supported in library at present. Packet print only\n");
ret = RCTDL_ERR_RDR_NO_DECODER;
#endif
}
return ret;
}
/************************************************************************/
/*** STM ***/
/************************************************************************/
#define STMTCSR_TRC_ID_MASK 0x007F0000
#define STMTCSR_TRC_ID_SHIFT 16
static void set_config_struct_stm()
{
trace_config_stm.reg_tcsr = 0x00A00005;
if(test_trc_id_override != 0)
{
trace_config_stm.reg_tcsr &= ~STMTCSR_TRC_ID_MASK;
trace_config_stm.reg_tcsr |= ((((uint32_t)test_trc_id_override) << STMTCSR_TRC_ID_SHIFT) & STMTCSR_TRC_ID_MASK);
}
trace_config_stm.reg_feat3r = 0x10000; /* channel default */
trace_config_stm.reg_devid = 0xFF; /* master default */
/* not using hw event trace decode */
trace_config_stm.reg_hwev_mast = 0;
trace_config_stm.reg_feat1r = 0;
trace_config_stm.hw_event = HwEvent_Unknown_Disabled;
}
rctdl_datapath_resp_t stm_packet_handler(const void *p_context, const rctdl_datapath_op_t op, const rctdl_trc_index_t index_sop, const rctdl_stm_pkt *p_packet_in)
{
return packet_handler(op,index_sop,(const void *)p_packet_in);
}
void stm_packet_monitor( const rctdl_datapath_op_t op,
const rctdl_trc_index_t index_sop,
const rctdl_stm_pkt *p_packet_in,
const uint32_t size,
const uint8_t *p_data)
{
packet_monitor(op,index_sop,(void *)p_packet_in,size,p_data);
}
static rctdl_err_t create_decoder_stm(dcd_tree_handle_t dcd_tree_h)
{
rctdl_err_t ret = RCTDL_OK;
/*char mem_file_path[512];*/
/* populate the STM configuration structure */
set_config_struct_stm();
if(op == TEST_PKT_PRINT) /* packet printing only */
{
/* Create a packet processor on the decode tree for the ETM v4 configuration we have.
We need to supply the configuration, and a packet handling callback.
*/
ret = rctdl_dt_create_stm_pkt_proc(dcd_tree_h,&trace_config_stm,&stm_packet_handler,0);
}
else
{
/* Full decode */
/* not supported in library at present */
#if 0
/* create the packet decoder and packet processor pair */
ret = rctdl_dt_create_stm_decoder(dcd_tree_h,&trace_config_stm);
if(ret == RCTDL_OK)
{
if((op != TEST_PKT_DECODEONLY) && (ret == RCTDL_OK))
{
ret = rctdl_dt_attach_stm_pkt_mon(dcd_tree_h, (uint8_t)((trace_config_stm.reg_tcsr & STMTCSR_TRC_ID_MASK) >> STMTCSR_TRC_ID_SHIFT), stm_packet_monitor);
}
}
/* trace data file path */
strcpy(mem_file_path,);
strcat(mem_file_path,memory_dump_filename);
if(ret == RCTDL_OK)
{
/* create a memory file accessor */
ret = rctdl_dt_add_binfile_mem_acc(dcd_tree_h,mem_dump_address,RCTDL_MEM_SPACE_ANY,mem_file_path);
}
#else
printf("STM Full decode not supported in library at present. Packet print only\n");
ret = RCTDL_ERR_RDR_NO_DECODER;
#endif
}
return ret;
}
/************************************************************************/
/* create a decoder according to options */
static rctdl_err_t create_decoder(dcd_tree_handle_t dcd_tree_h)
{
rctdl_err_t err = RCTDL_OK;
switch(test_protocol)
{
case RCTDL_PROTOCOL_ETMV4I:
err = create_decoder_etmv4(dcd_tree_h);
break;
case RCTDL_PROTOCOL_ETMV3:
err = create_decoder_etmv3(dcd_tree_h);
break;
case RCTDL_PROTOCOL_STM:
err = create_decoder_stm(dcd_tree_h);
break;
default:
err = RCTDL_ERR_NO_PROTOCOL;
break;
}
return err;
}
#define INPUT_BLOCK_SIZE 1024
/* process buffer until done or error */
rctdl_err_t process_data_block(dcd_tree_handle_t dcd_tree_h, int block_index, uint8_t *p_block, const int block_size)
{
rctdl_err_t ret = RCTDL_OK;
uint32_t bytes_done = 0;
rctdl_datapath_resp_t dp_ret = RCTDL_RESP_CONT;
uint32_t bytes_this_time = 0;
while((bytes_done < (uint32_t)block_size) && (ret == RCTDL_OK))
{
if(RCTDL_DATA_RESP_IS_CONT(dp_ret))
{
dp_ret = rctdl_dt_process_data(dcd_tree_h,
RCTDL_OP_DATA,
block_index+bytes_done,
block_size-bytes_done,
((uint8_t *)p_block)+bytes_done,
&bytes_this_time);
bytes_done += bytes_this_time;
}
else if(RCTDL_DATA_RESP_IS_WAIT(dp_ret))
{
dp_ret = rctdl_dt_process_data(dcd_tree_h, RCTDL_OP_FLUSH,0,0,NULL,NULL);
}
else
ret = RCTDL_ERR_DATA_DECODE_FATAL; /* data path responded with an error - stop processing */
}
return ret;
}
int process_trace_data(FILE *pf)
{
rctdl_err_t ret = RCTDL_OK;
dcd_tree_handle_t dcdtree_handle = C_API_INVALID_TREE_HANDLE;
uint8_t data_buffer[INPUT_BLOCK_SIZE];
rctdl_trc_index_t index = 0;
size_t data_read;
/* Create a decode tree for this source data.
source data is frame formatted, memory aligned from an ETR (no frame syncs) so create tree accordingly
*/
dcdtree_handle = rctdl_create_dcd_tree(RCTDL_TRC_SRC_FRAME_FORMATTED, RCTDL_DFRMTR_FRAME_MEM_ALIGN);
if(dcdtree_handle != C_API_INVALID_TREE_HANDLE)
{
ret = create_decoder(dcdtree_handle);
rctdl_tl_log_mapped_mem_ranges(dcdtree_handle);
if(ret == RCTDL_OK)
/* attach the generic trace element output callback */
ret = rctdl_dt_set_gen_elem_outfn(dcdtree_handle,gen_trace_elem_print,0);
/* now push the trace data through the packet processor */
while(!feof(pf) && (ret == RCTDL_OK))
{
/* read from file */
data_read = fread(data_buffer,1,INPUT_BLOCK_SIZE,pf);
if(data_read > 0)
{
/* process a block of data - any packets from the trace stream
we have configured will appear at the callback
*/
ret = process_data_block(dcdtree_handle,
index,
data_buffer,
data_read);
index += data_read;
}
else if(ferror(pf))
ret = RCTDL_ERR_FILE_ERROR;
}
/* no errors - let the data path know we are at end of trace */
if(ret == RCTDL_OK)
rctdl_dt_process_data(dcdtree_handle, RCTDL_OP_EOT, 0,0,NULL,NULL);
/* shut down the mem acc CB if in use. */
if(using_mem_acc_cb)
{
destroy_mem_acc_cb(dcdtree_handle);
}
/* dispose of the decode tree - which will dispose of any packet processors we created
*/
rctdl_destroy_dcd_tree(dcdtree_handle);
}
else
{
printf("Failed to create trace decode tree\n");
ret = RCTDL_ERR_NOT_INIT;
}
return (int)ret;
}
int main(int argc, char *argv[])
{
FILE *trace_data;
char trace_file_path[512];
int ret = 0;
char message[512];
/* command line params */
process_cmd_line(argc,argv);
/* trace data file path */
strcpy(trace_file_path,default_path_to_snapshot);
strcat(trace_file_path,trace_data_filename);
trace_data = fopen(trace_file_path,"rb");
if(trace_data != NULL)
{
/* set up the logging in the library - enable the error logger, with an output printer*/
ret = rctdl_def_errlog_init(RCTDL_ERR_SEV_INFO,1);
/* set up the output - to file and stdout, set custom logfile name */
if(ret == 0)
ret = rctdl_def_errlog_config_output(C_API_MSGLOGOUT_FLG_FILE | C_API_MSGLOGOUT_FLG_STDOUT, "c_api_test.log");
/* print sign-on message in log */
sprintf(message, "C-API packet print test\nLibrary Version %s\n\n",rctdl_get_version_str());
rctdl_def_errlog_msgout(message);
/* process the trace data */
if(ret == 0)
ret = process_trace_data(trace_data);
/* close the data file */
fclose(trace_data);
}
else
{
printf("Unable to open file %s to process trace data\n", trace_file_path);
ret = -1;
}
return ret;
}
/* End of File simple_pkt_c_api.c */