xref: /aosp_15_r20/external/OpenCSD/decoder/tests/source/c_api_pkt_print_test.c (revision 02ca8ccacfba7e0df68f3332a95f3180334d6649)
1 /*
2  * \file       c_api_pkt_print_test.c
3  * \brief      OpenCSD : C-API test program
4  *
5  * \copyright  Copyright (c) 2016, ARM Limited. All Rights Reserved.
6  */
7 
8 /*
9  * Redistribution and use in source and binary forms, with or without modification,
10  * are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
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.
18  *
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.
22  *
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.
33  */
34 
35 /*
36  * Example of using the library with the C-API. Used to validate that the C-API
37  * functions work.
38  *
39  * Simple test program to print packets from a single trace ID source stream.
40  * Hard coded configuration based on the Juno r1-1 test snapshot for ETMv4 and
41  * STM, TC2 test snapshot for ETMv3, PTM.
42  *
43  * The test source can be set from the command line, but will default to the
44  * ETMv4 trace for trace ID 0x10 on the juno r1-1 test snapshot.
45  * This example uses the updated C-API functionality from library version 0.4.0 onwards.
46  * Test values are hardcoded from the same values in the snapshots as we do not
47  * explicitly read the snapshot metadata in this example program.
48  */
49 
50 #include <stdio.h>
51 #include <string.h>
52 #include <stdint.h>
53 #include <stdlib.h>
54 
55 /* include the C-API library header */
56 #include "opencsd/c_api/opencsd_c_api.h"
57 
58 /* include the test external decoder factory and decoder types headers
59    - separate from the main library includes by definition as external decoder.
60 */
61 #include "ext_dcd_echo_test_fact.h"
62 #include "ext_dcd_echo_test.h"
63 
64 /* path to test snapshots, relative to tests/bin/<plat>/<dbg|rel> build output dir */
65 #ifdef _WIN32
66 const char *default_base_snapshot_path="..\\..\\..\\snapshots";
67 const char *juno_snapshot = "\\juno_r1_1\\";
68 const char *tc2_snapshot = "\\TC2\\";
69 #else
70 const char *default_base_snapshot_path = "../../snapshots";
71 const char *juno_snapshot = "/juno_r1_1/";
72 const char *tc2_snapshot = "/TC2/";
73 #endif
74 static const char *selected_snapshot;
75 static const char *usr_snapshot_path = 0;
76 #define MAX_TRACE_FILE_PATH_LEN 512
77 
78 /* trace data and memory file dump names and values - taken from snapshot metadata */
79 const char *trace_data_filename = "cstrace.bin";
80 const char *stmtrace_data_filename = "cstraceitm.bin";
81 const char *memory_dump_filename = "kernel_dump.bin";
82 ocsd_vaddr_t mem_dump_address=0xFFFFFFC000081000;
83 const ocsd_vaddr_t mem_dump_address_tc2=0xC0008000;
84 
85 /* test variables - set by command line to feature test API */
86 static int using_mem_acc_cb = 0;    /* test the memory access callback function */
87 static int use_region_file = 0;     /* test multi region memory files */
88 static int using_mem_acc_cb_id = 0; /* test the mem acc callback with trace ID parameter */
89 
90 /* buffer to handle a packet string */
91 #define PACKET_STR_LEN 1024
92 static char packet_str[PACKET_STR_LEN];
93 
94 /* decide if we decode & monitor, decode only or packet print */
95 typedef enum _test_op {
96     TEST_PKT_PRINT,     // process trace input into discrete packets and print.
97     TEST_PKT_DECODE,    // process and decode trace packets, printing discrete packets and generic output.
98     TEST_PKT_DECODEONLY // process and decode trace packets, printing generic output packets only.
99 } test_op_t;
100 
101 // Default test operations
102 static test_op_t op = TEST_PKT_PRINT;   // default operation is to packet print
103 static ocsd_trace_protocol_t test_protocol = OCSD_PROTOCOL_ETMV4I; // ETMV4 protocl
104 static uint8_t test_trc_id_override = 0x00; // no trace ID override.
105 
106 /* external decoder testing */
107 static int test_extern_decoder = 0; /* test the external decoder infrastructure. */
108 static ocsd_extern_dcd_fact_t *p_ext_fact; /* external decoder factory */
109 #define EXT_DCD_NAME "ext_echo"
110 
111 /* raw packet printing test */
112 static int frame_raw_unpacked = 0;
113 static int frame_raw_packed = 0;
114 static int test_printstr = 0;
115 
116 /* test the library printer API */
117 static int test_lib_printers = 0;
118 
119 /* test the last error / error code api */
120 static int test_error_api = 0;
121 
122 /* log statistics */
123 static int stats = 0;
124 
125 /* decoder creation flags */
126 static int add_create_flags = 0;
127 
128 /* output file name */
129 const char* logfile_name = "c_api_test.log";
130 
131 /* Process command line options - choose the operation to use for the test. */
process_cmd_line(int argc,char * argv[])132 static int process_cmd_line(int argc, char *argv[])
133 {
134     int idx = 1;
135     int len = 0;
136 
137     while(idx < argc)
138     {
139         if (strcmp(argv[idx], "-decode_only") == 0)
140         {
141             op = TEST_PKT_DECODEONLY;
142         }
143         else if (strcmp(argv[idx], "-decode") == 0)
144         {
145             op = TEST_PKT_DECODE;
146         }
147         else if (strcmp(argv[idx], "-id") == 0)
148         {
149             idx++;
150             if (idx < argc)
151             {
152                 test_trc_id_override = (uint8_t)(strtoul(argv[idx], 0, 0));
153                 printf("ID override = 0x%02X\n", test_trc_id_override);
154             }
155         }
156         else if (strcmp(argv[idx], "-etmv3") == 0)
157         {
158             test_protocol = OCSD_PROTOCOL_ETMV3;
159             selected_snapshot = tc2_snapshot;
160             mem_dump_address = mem_dump_address_tc2;
161         }
162         else if (strcmp(argv[idx], "-ptm") == 0)
163         {
164             test_protocol = OCSD_PROTOCOL_PTM;
165             selected_snapshot = tc2_snapshot;
166             mem_dump_address = mem_dump_address_tc2;
167         }
168         else if (strcmp(argv[idx], "-stm") == 0)
169         {
170             test_protocol = OCSD_PROTOCOL_STM;
171             trace_data_filename = stmtrace_data_filename;
172         }
173         else if (strcmp(argv[idx], "-test_cb") == 0)
174         {
175             using_mem_acc_cb = 1;
176             use_region_file = 0;
177         }
178         else if (strcmp(argv[idx], "-test_cb_id") == 0)
179         {
180             using_mem_acc_cb = 1;
181             use_region_file = 0;
182             using_mem_acc_cb_id = 1;
183         }
184         else if (strcmp(argv[idx], "-test_region_file") == 0)
185         {
186             use_region_file = 1;
187             using_mem_acc_cb = 0;
188         }
189         else if (strcmp(argv[idx], "-extern") == 0)
190         {
191             test_extern_decoder = 1;
192         }
193         else if (strcmp(argv[idx], "-raw") == 0)
194         {
195             frame_raw_unpacked = 1;
196         }
197         else if (strcmp(argv[idx], "-stats") == 0)
198         {
199             stats = 1;
200         }
201         else if (strcmp(argv[idx], "-raw_packed") == 0)
202         {
203             frame_raw_packed = 1;
204         }
205         else if (strcmp(argv[idx], "-test_printstr") == 0)
206         {
207             test_printstr = 1;
208         }
209         else if (strcmp(argv[idx], "-test_libprint") == 0)
210         {
211             test_lib_printers = 1;
212         }
213         else if (strcmp(argv[idx], "-ss_path") == 0)
214         {
215             idx++;
216             if ((idx >= argc) || (strlen(argv[idx]) == 0))
217             {
218                 printf("-ss_path: Missing path parameter or zero length\n");
219                 return -1;
220             }
221             else
222             {
223                 len = strlen(argv[idx]);
224                 if (len > (MAX_TRACE_FILE_PATH_LEN - 32))
225                 {
226                     printf("-ss_path: path too long\n");
227                     return -1;
228                 }
229                 usr_snapshot_path = argv[idx];
230             }
231 
232         }
233         else if (strcmp(argv[idx], "-test_err_api") == 0)
234         {
235             test_error_api = 1;
236         }
237         else if (strcmp(argv[idx], "-direct_br_cond") == 0)
238         {
239             add_create_flags |= OCSD_OPFLG_N_UNCOND_DIR_BR_CHK;
240         }
241         else if (strcmp(argv[idx], "-strict_br_cond") == 0)
242         {
243             add_create_flags |= OCSD_OPFLG_STRICT_N_UNCOND_BR_CHK;
244         }
245         else if (strcmp(argv[idx], "-range_cont") == 0)
246         {
247             add_create_flags |= OCSD_OPFLG_CHK_RANGE_CONTINUE;
248         }
249         else if (strcmp(argv[idx], "-logfilename") == 0)
250         {
251             idx++;
252             if ((idx >= argc) || (strlen(argv[idx]) == 0))
253             {
254                 printf("-logfilename: Missing filename parameter or zero length\n");
255                 return -1;
256             }
257             logfile_name = argv[idx];
258         }
259         else if (strcmp(argv[idx], "-halt_err") == 0)
260         {
261             add_create_flags |= OCSD_OPFLG_PKTDEC_HALT_BAD_PKTS;
262         }
263         else if(strcmp(argv[idx],"-help") == 0)
264         {
265             return -1;
266         }
267         else
268             printf("Ignored unknown argument %s\n", argv[idx]);
269         idx++;
270     }
271     return 0;
272 }
273 
print_cmd_line_help()274 static void print_cmd_line_help()
275 {
276     printf("Usage:\n-etmv3|-stm|-ptm|-extern  : choose protocol (one only, default etmv4)\n");
277     printf("-id <ID> : decode source for id <ID> (default 0x10)\n");
278     printf("-decode | -decode_only : full decode + trace packets / full decode packets only (default trace packets only)\n");
279     printf("-raw / -raw_packed: print raw unpacked / packed data;\n");
280     printf("-test_printstr | -test_libprint : ttest lib printstr callback | test lib based packet printers\n");
281     printf("-test_region_file | -test_cb | -test_cb_id : mem accessor - test multi region file API | test callback API [with trcid] (default single memory file)\n\n");
282     printf("-ss_path <path> : path from cwd to /snapshots/ directory. Test prog will append required test subdir\n");
283     printf("-direct_br_cond | -strict_br_cond | -range_cont : Decoder checks for inconsistent program images.\n");
284     printf("-logfilename <name> : output to logfile <name>\n");
285     printf("-halt_err : halt on error packets (default is to attempt to resync / recover)\n");
286 }
287 
288 /************************************************************************/
289 /* Memory accessor functionality */
290 /************************************************************************/
291 
292 static FILE *dump_file = NULL;  /* pointer to the file providing the opcode memory */
293 static ocsd_mem_space_acc_t dump_file_mem_space = OCSD_MEM_SPACE_ANY;   /* memory space used by the dump file */
294 static long mem_file_size = 0;                /* size of the memory file */
295 static ocsd_vaddr_t mem_file_en_address = 0;  /* end address last inclusive address in file. */
296 
297 /* log the memacc output */
298 /* #define LOG_MEMACC_CB */
299 
300 /* decode memory access using a CallBack function
301 * tests CB API and add / remove mem acc API.
302 */
do_mem_acc_cb(const void * p_context,const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint8_t trc_id,const uint32_t reqBytes,uint8_t * byteBuffer)303 static uint32_t do_mem_acc_cb(const void *p_context, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t trc_id, const uint32_t reqBytes, uint8_t *byteBuffer)
304 {
305     uint32_t read_bytes = 0;
306     size_t file_read_bytes;
307 
308     if(dump_file == NULL)
309         return 0;
310 
311     /* bitwise & the incoming mem space and supported mem space to confirm coverage */
312     if(((uint8_t)mem_space & (uint8_t)dump_file_mem_space ) == 0)
313         return 0;
314 
315     /* calculate the bytes that can be read */
316     if((address >= mem_dump_address) && (address <= mem_file_en_address))
317     {
318         /* some bytes in our range */
319         read_bytes = reqBytes;
320 
321         if((address + reqBytes - 1) > mem_file_en_address)
322         {
323             /* more than are available - just read the available */
324             read_bytes = (uint32_t)(mem_file_en_address - (address - 1));
325         }
326     }
327 
328     /* read some bytes if more than 0 to read. */
329     if(read_bytes != 0)
330     {
331         fseek(dump_file,(long)(address-mem_dump_address),SEEK_SET);
332         file_read_bytes = fread(byteBuffer,sizeof(uint8_t),read_bytes,dump_file);
333         if(file_read_bytes < read_bytes)
334             read_bytes = file_read_bytes;
335     }
336 #ifdef LOG_MEMACC_CB
337     sprintf(packet_str, "mem_acc_cb(addr 0x%08llX, size %d, trcID 0x%02X)\n", address, reqBytes, trc_id);
338     ocsd_def_errlog_msgout(packet_str);
339 #endif
340     return read_bytes;
341 }
342 
mem_acc_cb(const void * p_context,const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint32_t reqBytes,uint8_t * byteBuffer)343 static uint32_t mem_acc_cb(const void *p_context, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint32_t reqBytes, uint8_t *byteBuffer)
344 {
345     return do_mem_acc_cb(p_context, address, mem_space, 0xff, reqBytes, byteBuffer);
346 }
347 
mem_acc_id_cb(const void * p_context,const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint8_t trc_id,const uint32_t reqBytes,uint8_t * byteBuffer)348 static uint32_t mem_acc_id_cb(const void *p_context, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t trc_id, const uint32_t reqBytes, uint8_t *byteBuffer)
349 {
350     return do_mem_acc_cb(p_context, address, mem_space, trc_id, reqBytes, byteBuffer);
351 }
352 
353 
354 /* Create the memory accessor using the callback function and attach to decode tree */
create_mem_acc_cb(dcd_tree_handle_t dcd_tree_h,const char * mem_file_path)355 static ocsd_err_t create_mem_acc_cb(dcd_tree_handle_t dcd_tree_h, const char *mem_file_path)
356 {
357     ocsd_err_t err = OCSD_OK;
358     dump_file = fopen(mem_file_path,"rb");
359     if(dump_file != NULL)
360     {
361         fseek(dump_file,0,SEEK_END);
362         mem_file_size = ftell(dump_file);
363         mem_file_en_address = mem_dump_address + mem_file_size - 1;
364 
365         if (using_mem_acc_cb_id)
366             err = ocsd_dt_add_callback_trcid_mem_acc(dcd_tree_h, mem_dump_address,
367                 mem_file_en_address, dump_file_mem_space, &mem_acc_id_cb, 0);
368         else
369             err = ocsd_dt_add_callback_mem_acc(dcd_tree_h, mem_dump_address,
370                 mem_file_en_address, dump_file_mem_space, &mem_acc_cb, 0);
371         if(err != OCSD_OK)
372         {
373             fclose(dump_file);
374             dump_file = NULL;
375         }
376     }
377     else
378         err = OCSD_ERR_MEM_ACC_FILE_NOT_FOUND;
379     return err;
380 }
381 
382 /* remove the callback memory accessor from decode tree */
destroy_mem_acc_cb(dcd_tree_handle_t dcd_tree_h)383 static void destroy_mem_acc_cb(dcd_tree_handle_t dcd_tree_h)
384 {
385     if(dump_file != NULL)
386     {
387         ocsd_dt_remove_mem_acc(dcd_tree_h,mem_dump_address,dump_file_mem_space);
388         fclose(dump_file);
389         dump_file = NULL;
390     }
391 }
392 
393 /* create and attach the memory accessor according to required test parameters */
create_test_memory_acc(dcd_tree_handle_t handle)394 static ocsd_err_t create_test_memory_acc(dcd_tree_handle_t handle)
395 {
396     ocsd_err_t ret = OCSD_OK;
397     char mem_file_path[MAX_TRACE_FILE_PATH_LEN];
398     uint32_t i0adjust = 0x100;
399     int i = 0;
400 
401     /* region list to test multi region memory file API */
402     ocsd_file_mem_region_t region_list[4];
403 
404     /* path to the file containing the memory image traced - raw binary data in the snapshot  */
405     if(usr_snapshot_path != 0)
406         strcpy(mem_file_path,usr_snapshot_path);
407     else
408         strcpy(mem_file_path,default_base_snapshot_path);
409     strcat(mem_file_path,selected_snapshot);
410     strcat(mem_file_path,memory_dump_filename);
411 
412     /*
413     * decide how to handle the file - test the normal memory accessor (contiguous binary file),
414     * a callback accessor or a multi-region file (e.g. similar to using the code region in a .so)
415     *
416     * The same memory dump file is used in each case, we just present it differently
417     * to test the API functions.
418     */
419 
420     /* memory access callback */
421     if(using_mem_acc_cb)
422     {
423         ret = create_mem_acc_cb(handle,mem_file_path);
424     }
425     /* multi region file */
426     else if(use_region_file)
427     {
428 
429         dump_file = fopen(mem_file_path,"rb");
430         if(dump_file != NULL)
431         {
432             fseek(dump_file,0,SEEK_END);
433             mem_file_size = ftell(dump_file);
434             fclose(dump_file);
435 
436             /* populate the region list - split existing file into four regions */
437             for(i = 0; i < 4; i++)
438             {
439                 if(i != 0)
440                     i0adjust = 0;
441                 region_list[i].start_address = mem_dump_address + (i *  mem_file_size/4) + i0adjust;
442                 region_list[i].region_size = (mem_file_size/4) - i0adjust;
443                 region_list[i].file_offset = (i * mem_file_size/4) +  i0adjust;
444             }
445 
446             /* create a memory file accessor - full binary file */
447             ret = ocsd_dt_add_binfile_region_mem_acc(handle,&region_list[0],4,OCSD_MEM_SPACE_ANY,mem_file_path);
448         }
449         else
450             ret  = OCSD_ERR_MEM_ACC_FILE_NOT_FOUND;
451     }
452     /* create a memory file accessor - simple contiguous full binary file */
453     else
454     {
455         ret = ocsd_dt_add_binfile_mem_acc(handle,mem_dump_address,OCSD_MEM_SPACE_ANY,mem_file_path);
456     }
457     return ret;
458 }
459 
460 /************************************************************************/
461 /** Packet printers */
462 /************************************************************************/
463 
464 /*
465 * Callback function to process the packets in the packet processor output stream  -
466 * simply print them out in this case to the library message/error logger.
467 */
packet_handler(void * context,const ocsd_datapath_op_t op,const ocsd_trc_index_t index_sop,const void * p_packet_in)468 ocsd_datapath_resp_t packet_handler(void *context, const ocsd_datapath_op_t op, const ocsd_trc_index_t index_sop, const void *p_packet_in)
469 {
470     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
471     int offset = 0;
472 
473     switch(op)
474     {
475     case OCSD_OP_DATA:
476         sprintf(packet_str,"Idx:%"  OCSD_TRC_IDX_STR "; ", index_sop);
477         offset = strlen(packet_str);
478 
479         /*
480         * got a packet - convert to string and use the libraries' message output to print to file and stdoout
481         * Since the test always prints a single ID, we know the protocol type.
482         */
483         if(ocsd_pkt_str(test_protocol,p_packet_in,packet_str+offset,PACKET_STR_LEN-offset) == OCSD_OK)
484         {
485             /* add in <CR> */
486             if(strlen(packet_str) == PACKET_STR_LEN - 1) /* maximum length */
487                 packet_str[PACKET_STR_LEN-2] = '\n';
488             else
489                 strcat(packet_str,"\n");
490 
491             /* print it using the library output logger. */
492             ocsd_def_errlog_msgout(packet_str);
493         }
494         else
495             resp = OCSD_RESP_FATAL_INVALID_PARAM;  /* mark fatal error */
496         break;
497 
498     case OCSD_OP_EOT:
499         sprintf(packet_str,"**** END OF TRACE ****\n");
500         ocsd_def_errlog_msgout(packet_str);
501         break;
502 
503     default: break;
504     }
505 
506     return resp;
507 }
508 
509 /* print an array of hex data - used by the packet monitor to print hex data from packet.*/
print_data_array(const uint8_t * p_array,const int array_size,char * p_buffer,int buf_size)510 static int print_data_array(const uint8_t *p_array, const int array_size, char *p_buffer, int buf_size)
511 {
512     int chars_printed = 0;
513     int bytes_processed;
514     p_buffer[0] = 0;
515 
516     if(buf_size > 9)
517     {
518         /* set up the header */
519         strcat(p_buffer,"[ ");
520         chars_printed+=2;
521 
522         for(bytes_processed = 0; bytes_processed < array_size; bytes_processed++)
523         {
524            sprintf(p_buffer+chars_printed,"0x%02X ", p_array[bytes_processed]);
525            chars_printed += 5;
526            if((chars_printed + 5) > buf_size)
527                break;
528         }
529 
530         strcat(p_buffer,"];");
531         chars_printed+=2;
532     }
533     else if(buf_size >= 4)
534     {
535         sprintf(p_buffer,"[];");
536         chars_printed+=3;
537     }
538     return chars_printed;
539 }
540 
541 /*
542 * Callback function to process packets and packet data from the monitor output of the
543 * packet processor. Again print them to the library error logger.
544 */
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)545 void packet_monitor(    void *context,
546                         const ocsd_datapath_op_t op,
547                         const ocsd_trc_index_t index_sop,
548                         const void *p_packet_in,
549                         const uint32_t size,
550                         const uint8_t *p_data)
551 {
552     int offset = 0;
553 
554     switch(op)
555     {
556     default: break;
557     case OCSD_OP_DATA:
558         sprintf(packet_str,"Idx:%"  OCSD_TRC_IDX_STR ";", index_sop);
559         offset = strlen(packet_str);
560         offset+= print_data_array(p_data,size,packet_str+offset,PACKET_STR_LEN-offset);
561 
562         /* got a packet - convert to string and use the libraries' message output to print to file and stdoout */
563         if(ocsd_pkt_str(test_protocol,p_packet_in,packet_str+offset,PACKET_STR_LEN-offset) == OCSD_OK)
564         {
565             /* add in <CR> */
566             if(strlen(packet_str) == PACKET_STR_LEN - 1) /* maximum length */
567                 packet_str[PACKET_STR_LEN-2] = '\n';
568             else
569                 strcat(packet_str,"\n");
570 
571             /* print it using the library output logger. */
572             ocsd_def_errlog_msgout(packet_str);
573         }
574         break;
575 
576     case OCSD_OP_EOT:
577         sprintf(packet_str,"**** END OF TRACE ****\n");
578         ocsd_def_errlog_msgout(packet_str);
579         break;
580     }
581 }
582 
583 
584 /*
585 * printer for the generic trace elements when decoder output is being processed
586 */
gen_trace_elem_print(const void * p_context,const ocsd_trc_index_t index_sop,const uint8_t trc_chan_id,const ocsd_generic_trace_elem * elem)587 ocsd_datapath_resp_t gen_trace_elem_print(const void *p_context, const ocsd_trc_index_t index_sop, const uint8_t trc_chan_id, const ocsd_generic_trace_elem *elem)
588 {
589     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
590     int offset = 0;
591 
592     sprintf(packet_str,"Idx:%"  OCSD_TRC_IDX_STR "; TrcID:0x%02X; ", index_sop, trc_chan_id);
593     offset = strlen(packet_str);
594 
595     if(ocsd_gen_elem_str(elem, packet_str+offset,PACKET_STR_LEN - offset) == OCSD_OK)
596     {
597         /* add in <CR> */
598         if(strlen(packet_str) == PACKET_STR_LEN - 1) /* maximum length */
599             packet_str[PACKET_STR_LEN-2] = '\n';
600         else
601             strcat(packet_str,"\n");
602     }
603     else
604     {
605         strcat(packet_str,"Unable to create element string\n");
606     }
607 
608     /* print it using the library output logger. */
609     ocsd_def_errlog_msgout(packet_str);
610 
611     return resp;
612 }
613 
614 /************************************************************************/
615 /** decoder creation **/
616 
617 /*** generic ***/
create_generic_decoder(dcd_tree_handle_t handle,const char * p_name,const void * p_cfg,const void * p_context)618 static ocsd_err_t create_generic_decoder(dcd_tree_handle_t handle, const char *p_name, const void *p_cfg, const void *p_context)
619 {
620     ocsd_err_t ret = OCSD_OK;
621     uint8_t CSID = 0;
622 
623     if(op == TEST_PKT_PRINT) /* test operation set to packet printing only */
624     {
625         /*
626          * Create a packet processor on the decode tree for the configuration we have.
627          *  We need to supply the configuration
628          */
629         ret = ocsd_dt_create_decoder(handle,p_name,OCSD_CREATE_FLG_PACKET_PROC,p_cfg,&CSID);
630         if(ret == OCSD_OK)
631         {
632             /* Attach the packet handler to the output of the packet processor - referenced by CSID */
633             if (test_lib_printers)
634                 ret = ocsd_dt_set_pkt_protocol_printer(handle, CSID, 0);
635             else
636                 ret = ocsd_dt_attach_packet_callback(handle,CSID, OCSD_C_API_CB_PKT_SINK,&packet_handler,p_context);
637             if(ret != OCSD_OK)
638                 ocsd_dt_remove_decoder(handle,CSID); /* if the attach failed then destroy the decoder. */
639         }
640     }
641     else
642     {
643         /* Full decode - need decoder, and memory dump */
644 
645         /* create the packet decoder and packet processor pair from the supplied name */
646         ret = ocsd_dt_create_decoder(handle,p_name, add_create_flags | OCSD_CREATE_FLG_FULL_DECODER, p_cfg, &CSID);
647         if(ret == OCSD_OK)
648         {
649             if((op != TEST_PKT_DECODEONLY) && (ret == OCSD_OK))
650             {
651                 /*
652                 * print the packets as well as the decode - use the packet processors monitor
653                 * output this time, as the main output is attached to the packet decoder.
654                 */
655                 if (test_lib_printers)
656                     ret = ocsd_dt_set_pkt_protocol_printer(handle, CSID, 1);
657                 else
658                     ret = ocsd_dt_attach_packet_callback(handle,CSID,OCSD_C_API_CB_PKT_MON,packet_monitor,p_context);
659             }
660 
661             /* attach a memory accessor */
662             if(ret == OCSD_OK)
663                 ret = create_test_memory_acc(handle);
664 
665             /* if the attach failed then destroy the decoder. */
666             if(ret != OCSD_OK)
667                 ocsd_dt_remove_decoder(handle,CSID);
668         }
669     }
670     return ret;
671 }
672 
673 /*** ETMV4 specific settings ***/
create_decoder_etmv4(dcd_tree_handle_t dcd_tree_h)674 static ocsd_err_t create_decoder_etmv4(dcd_tree_handle_t dcd_tree_h)
675 {
676     ocsd_etmv4_cfg trace_config;
677 
678     /*
679     * populate the ETMv4 configuration structure with
680     * hard coded values from snapshot .ini files.
681     */
682 
683     trace_config.arch_ver   = ARCH_V8;
684     trace_config.core_prof  = profile_CortexA;
685 
686     trace_config.reg_configr    = 0x000000C1;
687     trace_config.reg_traceidr   = 0x00000010;   /* this is the trace ID -> 0x10, change this to analyse other streams in snapshot.*/
688 
689     if(test_trc_id_override != 0)
690     {
691         trace_config.reg_traceidr = (uint32_t)test_trc_id_override;
692     }
693     test_trc_id_override = trace_config.reg_traceidr; /* remember what ID we actually used */
694 
695     trace_config.reg_idr0   = 0x28000EA1;
696     trace_config.reg_idr1   = 0x4100F403;
697     trace_config.reg_idr2   = 0x00000488;
698     trace_config.reg_idr8   = 0x0;
699     trace_config.reg_idr9   = 0x0;
700     trace_config.reg_idr10  = 0x0;
701     trace_config.reg_idr11  = 0x0;
702     trace_config.reg_idr12  = 0x0;
703     trace_config.reg_idr13  = 0x0;
704 
705     /* create an ETMV4 decoder - no context needed as we have a single stream to a single handler. */
706     return create_generic_decoder(dcd_tree_h,OCSD_BUILTIN_DCD_ETMV4I,(void *)&trace_config,0);
707 }
708 
709 /*** ETMV3 specific settings ***/
create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h)710 static ocsd_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h)
711 {
712     ocsd_etmv3_cfg trace_config_etmv3;
713 
714     /*
715     * populate the ETMv3 configuration structure with
716     * hard coded values from snapshot .ini files.
717     */
718 
719     trace_config_etmv3.arch_ver = ARCH_V7;
720     trace_config_etmv3.core_prof = profile_CortexA;
721     trace_config_etmv3.reg_ccer  = 0x344008F2;
722     trace_config_etmv3.reg_ctrl  = 0x10001860;
723     trace_config_etmv3.reg_idr  = 0x410CF250;
724     trace_config_etmv3.reg_trc_id  = 0x010;
725     if(test_trc_id_override != 0)
726     {
727         trace_config_etmv3.reg_trc_id = (uint32_t)test_trc_id_override;
728     }
729     test_trc_id_override = trace_config_etmv3.reg_trc_id; /* remember what ID we actually used */
730 
731     /* create an ETMV3 decoder - no context needed as we have a single stream to a single handler. */
732     return create_generic_decoder(dcd_tree_h,OCSD_BUILTIN_DCD_ETMV3,(void *)&trace_config_etmv3,0);
733 }
734 
735 /*** PTM specific settings ***/
create_decoder_ptm(dcd_tree_handle_t dcd_tree_h)736 static ocsd_err_t create_decoder_ptm(dcd_tree_handle_t dcd_tree_h)
737 {
738     ocsd_ptm_cfg trace_config_ptm;
739 
740     /*
741     * populate the PTM configuration structure with
742     * hard coded values from snapshot .ini files.
743     */
744 
745     trace_config_ptm.arch_ver = ARCH_V7;
746     trace_config_ptm.core_prof = profile_CortexA;
747     trace_config_ptm.reg_ccer  = 0x34C01AC2;
748     trace_config_ptm.reg_ctrl  = 0x10001000;
749     trace_config_ptm.reg_idr  = 0x411CF312;
750     trace_config_ptm.reg_trc_id  = 0x013;
751     if(test_trc_id_override != 0)
752     {
753         trace_config_ptm.reg_trc_id = (uint32_t)test_trc_id_override;
754     }
755     test_trc_id_override = trace_config_ptm.reg_trc_id; /* remember what ID we actually used */
756 
757     /* create an PTM decoder - no context needed as we have a single stream to a single handler. */
758     return create_generic_decoder(dcd_tree_h,OCSD_BUILTIN_DCD_PTM,(void *)&trace_config_ptm,0);
759 
760 }
761 
762 /*** STM specific settings ***/
create_decoder_stm(dcd_tree_handle_t dcd_tree_h)763 static ocsd_err_t create_decoder_stm(dcd_tree_handle_t dcd_tree_h)
764 {
765     ocsd_stm_cfg trace_config_stm;
766 
767     /*
768     * populate the STM configuration structure with
769     * hard coded values from snapshot .ini files.
770     */
771     #define STMTCSR_TRC_ID_MASK     0x007F0000
772     #define STMTCSR_TRC_ID_SHIFT    16
773 
774     trace_config_stm.reg_tcsr = 0x00A00005;
775     if(test_trc_id_override != 0)
776     {
777         trace_config_stm.reg_tcsr &= ~STMTCSR_TRC_ID_MASK;
778         trace_config_stm.reg_tcsr |= ((((uint32_t)test_trc_id_override) << STMTCSR_TRC_ID_SHIFT) & STMTCSR_TRC_ID_MASK);
779     }
780     trace_config_stm.reg_feat3r = 0x10000;  /* channel default */
781     trace_config_stm.reg_devid = 0xFF;      /* master default */
782 
783     /* not using hw event trace decode */
784     trace_config_stm.reg_hwev_mast = 0;
785     trace_config_stm.reg_feat1r = 0;
786     trace_config_stm.hw_event = HwEvent_Unknown_Disabled;
787 
788     /* create a STM decoder - no context needed as we have a single stream to a single handler. */
789     return create_generic_decoder(dcd_tree_h, OCSD_BUILTIN_DCD_STM, (void *)&trace_config_stm, 0);
790 }
791 
create_decoder_extern(dcd_tree_handle_t dcd_tree_h)792 static ocsd_err_t create_decoder_extern(dcd_tree_handle_t dcd_tree_h)
793 {
794     echo_dcd_cfg_t trace_cfg_ext;
795 
796     /* setup the custom configuration */
797     trace_cfg_ext.cs_id = 0x010;
798     if (test_trc_id_override != 0)
799     {
800         trace_cfg_ext.cs_id = (uint32_t)test_trc_id_override;
801     }
802     test_trc_id_override = trace_cfg_ext.cs_id;
803 
804     /* create an external decoder - no context needed as we have a single stream to a single handler. */
805     return create_generic_decoder(dcd_tree_h, EXT_DCD_NAME, (void *)&trace_cfg_ext, 0);
806 }
807 
attach_raw_printers(dcd_tree_handle_t dcd_tree_h)808 static ocsd_err_t attach_raw_printers(dcd_tree_handle_t dcd_tree_h)
809 {
810     ocsd_err_t err = OCSD_OK;
811     int flags = 0;
812     if (frame_raw_unpacked)
813         flags |= OCSD_DFRMTR_UNPACKED_RAW_OUT;
814     if (frame_raw_packed)
815         flags |= OCSD_DFRMTR_PACKED_RAW_OUT;
816     if (flags)
817     {
818         err = ocsd_dt_set_raw_frame_printer(dcd_tree_h, flags);
819     }
820     return err;
821 }
822 
print_output_str(const void * p_context,const char * psz_msg_str,const int str_len)823 static void print_output_str(const void *p_context, const char *psz_msg_str, const int str_len)
824 {
825     printf("** CUST_PRNTSTR: %s", psz_msg_str);
826 }
827 
test_printstr_cb(dcd_tree_handle_t dcd_tree_h)828 static ocsd_err_t test_printstr_cb(dcd_tree_handle_t dcd_tree_h)
829 {
830     ocsd_err_t err = OCSD_OK;
831     if (test_printstr)
832         err = ocsd_def_errlog_set_strprint_cb(dcd_tree_h, 0, print_output_str);
833     return err;
834 }
835 /************************************************************************/
836 
register_extern_decoder()837 ocsd_err_t register_extern_decoder()
838 {
839     ocsd_err_t err = OCSD_ERR_NO_PROTOCOL;
840 
841     p_ext_fact = ext_echo_get_dcd_fact();
842     if (p_ext_fact)
843     {
844         err = ocsd_register_custom_decoder(EXT_DCD_NAME, p_ext_fact);
845         if (err == OCSD_OK)
846             test_protocol = p_ext_fact->protocol_id;
847         else
848             printf("External Decoder Registration: Failed to register decoder.");
849     }
850     else
851         printf("External Decoder Registration: Failed to get decoder factory.");
852 
853     return err;
854 }
855 
856 /* create a decoder according to options */
create_decoder(dcd_tree_handle_t dcd_tree_h)857 static ocsd_err_t create_decoder(dcd_tree_handle_t dcd_tree_h)
858 {
859     ocsd_err_t err = OCSD_OK;
860 
861     /* extended for the external decoder testing*/
862     if (test_extern_decoder)
863             err = register_extern_decoder();
864     if (err != OCSD_OK)
865         return err;
866 
867     switch(test_protocol)
868     {
869     case OCSD_PROTOCOL_ETMV4I:
870         err = create_decoder_etmv4(dcd_tree_h);
871         break;
872 
873     case OCSD_PROTOCOL_ETMV3:
874         err = create_decoder_etmv3(dcd_tree_h);
875         break;
876 
877     case OCSD_PROTOCOL_STM:
878         err = create_decoder_stm(dcd_tree_h);
879         break;
880 
881     case OCSD_PROTOCOL_PTM:
882         err = create_decoder_ptm(dcd_tree_h);
883         break;
884 
885         /* we only register a single external decoder in this test,
886         so it will always be assigned the first custom protocol ID */
887     case OCSD_PROTOCOL_CUSTOM_0:
888         err = create_decoder_extern(dcd_tree_h);
889         break;
890 
891     default:
892         err = OCSD_ERR_NO_PROTOCOL;
893         break;
894     }
895     return err;
896 }
897 
898 #define INPUT_BLOCK_SIZE 1024
899 
900 /* process buffer until done or error */
process_data_block(dcd_tree_handle_t dcd_tree_h,int block_index,uint8_t * p_block,const int block_size)901 ocsd_err_t process_data_block(dcd_tree_handle_t dcd_tree_h, int block_index, uint8_t *p_block, const int block_size)
902 {
903     ocsd_err_t ret = OCSD_OK;
904     uint32_t bytes_done = 0;
905     ocsd_datapath_resp_t dp_ret = OCSD_RESP_CONT;
906     uint32_t bytes_this_time = 0;
907 
908     while((bytes_done < (uint32_t)block_size) && (ret == OCSD_OK))
909     {
910         if(OCSD_DATA_RESP_IS_CONT(dp_ret))
911         {
912             dp_ret = ocsd_dt_process_data(dcd_tree_h,
913                                 OCSD_OP_DATA,
914                                 block_index+bytes_done,
915                                 block_size-bytes_done,
916                                 ((uint8_t *)p_block)+bytes_done,
917                                 &bytes_this_time);
918             bytes_done += bytes_this_time;
919         }
920         else if(OCSD_DATA_RESP_IS_WAIT(dp_ret))
921         {
922             dp_ret = ocsd_dt_process_data(dcd_tree_h, OCSD_OP_FLUSH,0,0,NULL,NULL);
923         }
924         else
925             ret = OCSD_ERR_DATA_DECODE_FATAL; /* data path responded with an error - stop processing */
926     }
927     return ret;
928 }
929 
print_statistics(dcd_tree_handle_t dcdtree_handle)930 void print_statistics(dcd_tree_handle_t dcdtree_handle)
931 {
932     ocsd_decode_stats_t *p_stats = 0;
933     ocsd_err_t err;
934 
935     sprintf(packet_str, "\nReading packet decoder statistics for ID:0x%02x...\n", test_trc_id_override);
936     ocsd_def_errlog_msgout(packet_str);
937 
938     err = ocsd_dt_get_decode_stats(dcdtree_handle, test_trc_id_override, &p_stats);
939     if (!err && p_stats)
940     {
941         sprintf(packet_str, "Total Bytes %ld; Unsynced Bytes: %ld\nBad Header Errors: %d; Bad sequence errors: %d\n", (long)p_stats->channel_total,
942             (long)p_stats->channel_unsynced, p_stats->bad_header_errs, p_stats->bad_sequence_errs);
943         ocsd_dt_reset_decode_stats(dcdtree_handle, test_trc_id_override);
944     }
945     else
946     {
947         sprintf(packet_str, "Not available for this ID.\n");
948     }
949     ocsd_def_errlog_msgout(packet_str);
950 }
951 
process_trace_data(FILE * pf)952 int process_trace_data(FILE *pf)
953 {
954     ocsd_err_t ret = OCSD_OK;
955     dcd_tree_handle_t dcdtree_handle = C_API_INVALID_TREE_HANDLE;
956     uint8_t data_buffer[INPUT_BLOCK_SIZE];
957     ocsd_trc_index_t index = 0;
958     size_t data_read;
959 
960 
961     /*  Create a decode tree for this source data.
962         source data is frame formatted, memory aligned from an ETR (no frame syncs) so create tree accordingly
963     */
964     dcdtree_handle = ocsd_create_dcd_tree(OCSD_TRC_SRC_FRAME_FORMATTED, OCSD_DFRMTR_FRAME_MEM_ALIGN);
965 
966     if(dcdtree_handle != C_API_INVALID_TREE_HANDLE)
967     {
968 
969         ret = create_decoder(dcdtree_handle);
970         ocsd_tl_log_mapped_mem_ranges(dcdtree_handle);
971         // check the mem acc caching api - if we are decoding.
972         if (op > TEST_PKT_PRINT)
973             ocsd_dt_set_mem_acc_cacheing(dcdtree_handle, 1, 1024, 8);
974 
975         if (ret == OCSD_OK)
976         {
977             /* attach the generic trace element output callback */
978             if (test_lib_printers)
979                 ret = ocsd_dt_set_gen_elem_printer(dcdtree_handle);
980             else
981                 ret = ocsd_dt_set_gen_elem_outfn(dcdtree_handle, gen_trace_elem_print, 0);
982         }
983 
984 
985         /* raw print and str print cb options tested in their init functions */
986         if (ret == OCSD_OK)
987             ret = test_printstr_cb(dcdtree_handle);
988 
989         if (ret == OCSD_OK)
990             ret = attach_raw_printers(dcdtree_handle);
991 
992 
993         /* now push the trace data through the packet processor */
994         while(!feof(pf) && (ret == OCSD_OK))
995         {
996             /* read from file */
997             data_read = fread(data_buffer,1,INPUT_BLOCK_SIZE,pf);
998             if(data_read > 0)
999             {
1000                 /* process a block of data - any packets from the trace stream
1001                    we have configured will appear at the callback
1002                 */
1003                 ret = process_data_block(dcdtree_handle,
1004                                 index,
1005                                 data_buffer,
1006                                 data_read);
1007                 index += data_read;
1008             }
1009             else if(ferror(pf))
1010                 ret = OCSD_ERR_FILE_ERROR;
1011         }
1012 
1013         /* no errors - let the data path know we are at end of trace */
1014         if(ret == OCSD_OK)
1015             ocsd_dt_process_data(dcdtree_handle, OCSD_OP_EOT, 0,0,NULL,NULL);
1016 
1017         if (stats) {
1018             print_statistics(dcdtree_handle);
1019         }
1020         /* shut down the mem acc CB if in use. */
1021         if(using_mem_acc_cb)
1022         {
1023             destroy_mem_acc_cb(dcdtree_handle);
1024         }
1025 
1026         /* dispose of the decode tree - which will dispose of any packet processors we created
1027         */
1028         ocsd_destroy_dcd_tree(dcdtree_handle);
1029     }
1030     else
1031     {
1032         printf("Failed to create trace decode tree\n");
1033         ret = OCSD_ERR_NOT_INIT;
1034     }
1035     return (int)ret;
1036 }
1037 
1038 #define ERR_BUFFER_SIZE 256
test_err_api()1039 int test_err_api()
1040 {
1041     dcd_tree_handle_t dcdtree_handle = C_API_INVALID_TREE_HANDLE;
1042     ocsd_err_t ret = OCSD_OK, err_test;
1043     ocsd_trc_index_t index = 0, err_index = 0;
1044     uint8_t cs_id;
1045     char err_buffer[ERR_BUFFER_SIZE];
1046 
1047     /*  Create a decode tree for this source data.
1048         source data is frame formatted, memory aligned from an ETR (no frame syncs) so create tree accordingly
1049     */
1050     dcdtree_handle = ocsd_create_dcd_tree(OCSD_TRC_SRC_SINGLE, OCSD_DFRMTR_FRAME_MEM_ALIGN);
1051 
1052     if (dcdtree_handle != C_API_INVALID_TREE_HANDLE)
1053     {
1054 
1055         ret = create_decoder(dcdtree_handle);
1056         if (ret == OCSD_OK)
1057         {
1058             /* attach the generic trace element output callback */
1059             if (test_lib_printers)
1060                 ret = ocsd_dt_set_gen_elem_printer(dcdtree_handle);
1061             else
1062                 ret = ocsd_dt_set_gen_elem_outfn(dcdtree_handle, gen_trace_elem_print, 0);
1063         }
1064 
1065 
1066         /* raw print and str print cb options tested in their init functions */
1067         if (ret == OCSD_OK)
1068             ret = test_printstr_cb(dcdtree_handle);
1069 
1070         if (ret == OCSD_OK)
1071             ret = attach_raw_printers(dcdtree_handle);
1072 
1073         /* feed some duff data into a decoder to provoke an error! */
1074         uint8_t trace_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075                                  0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x60, 0x71 };
1076 
1077         if (ret == OCSD_OK)
1078             ret = process_data_block(dcdtree_handle, index, trace_data, sizeof(trace_data));
1079 
1080         ocsd_err_str(ret, err_buffer, ERR_BUFFER_SIZE);
1081         printf("testing error API for code %d: %s\n", ret, err_buffer);
1082         err_test = ocsd_get_last_err(&err_index, &cs_id, err_buffer, ERR_BUFFER_SIZE);
1083         printf("get last error:\ncode = 0x%02x; trace index %d; cs_id 0x%02x;\nstring: %s\n", err_test, err_index, cs_id, err_buffer);
1084 
1085     }
1086     return ret;
1087 }
1088 
main(int argc,char * argv[])1089 int main(int argc, char *argv[])
1090 {
1091     FILE *trace_data;
1092     char trace_file_path[MAX_TRACE_FILE_PATH_LEN];
1093     int ret = 0, i, len;
1094     char message[512];
1095 
1096     /* default to juno */
1097     selected_snapshot = juno_snapshot;
1098 
1099     /* command line params */
1100     if(process_cmd_line(argc,argv) != 0)
1101     {
1102         print_cmd_line_help();
1103         return -2;
1104     }
1105 
1106     /* trace data file path */
1107     if(usr_snapshot_path != 0)
1108         strcpy(trace_file_path,usr_snapshot_path);
1109     else
1110         strcpy(trace_file_path,default_base_snapshot_path);
1111     strcat(trace_file_path,selected_snapshot);
1112     strcat(trace_file_path,trace_data_filename);
1113     printf("opening %s trace data file\n",trace_file_path);
1114     trace_data = fopen(trace_file_path,"rb");
1115 
1116     if(trace_data != NULL)
1117     {
1118         /* set up the logging in the library - enable the error logger, with an output printer*/
1119         ret = ocsd_def_errlog_init(OCSD_ERR_SEV_INFO,1);
1120 
1121         /* set up the output - to file and stdout, set custom logfile name */
1122         if(ret == 0)
1123             ret = ocsd_def_errlog_config_output(C_API_MSGLOGOUT_FLG_FILE | C_API_MSGLOGOUT_FLG_STDOUT, logfile_name);
1124 
1125         /* print sign-on message in log */
1126         sprintf(message, "C-API packet print test\nLibrary Version %s\n\n",ocsd_get_version_str());
1127         ocsd_def_errlog_msgout(message);
1128 
1129         /* print command line used */
1130         message[0] = 0;
1131         len = 0;
1132         for (i = 0; i < argc; i++)
1133         {
1134             len += strlen(argv[i]) + 1;
1135             if (len < 512)
1136             {
1137                 strcat(message, argv[i]);
1138                 strcat(message, " ");
1139             }
1140         }
1141         if((len + 2) < 512)
1142             strcat(message, "\n\n");
1143         ocsd_def_errlog_msgout(message);
1144 
1145         /* process the trace data */
1146         if (ret == 0) {
1147             if (test_error_api)
1148                 ret = test_err_api();
1149             else
1150                 ret = process_trace_data(trace_data);
1151         }
1152         /* close the data file */
1153         fclose(trace_data);
1154     }
1155     else
1156     {
1157         printf("Unable to open file %s to process trace data\n", trace_file_path);
1158         ret = -1;
1159     }
1160     return ret;
1161 }
1162 /* End of File simple_pkt_c_api.c */
1163