/* ********************************************************************************************* * @Title: Sample program to execute TRACE32 commands from a system shell. * @Description: * This application creates a connection to a TRACE32 PowerView instance and sends a * TRACE32 command to that PowerView instance for execution. * * By default the port on which TRACE32 PowerView listens for API connections is 20000. * Optionally the port can be send with the port= parameter. * The port number must match with the definition in config.t32 of the PowerView instance you * want to receive the command *. * The optional parameter wait= will cause t32rem to wait (after sending its command) until * no more PRACTICE scripts are running in TRACE32 - or the given timeout elapses. Without the * parameter wait=, t32rem will not wait until all PRACTICE scripts stop running. * * A binary of this sample can be found in /bin//t32rem[.exe] * * Syntax: t32rem [port=] [protocol=NETASSIST|NETTCP] * [timeout=] [wait=] * * Example1: Set a breakpoint on main(): * t32rem localhost port=20000 Break.Set main * * Example2: Open the Break.List window: * t32rem localhost port=20000 Break.List * * Example3: Start a PRACTICE script and waits up to 5000.ms until it stops: * t32rem localhost port=20000 wait=5000 DO ~~/demo/practice/pcmd.cmm * * Return values: * 0 OK * 1 Error accessing TRACE32. * 2 Failed to connect to TRACE32. (No TRACE32 with an open API port at that socket) * 3 Invalid input. (Invalid ip-address/hostname/port or too long command) * 4 Timeout while waiting for PRACTICE scripts to stop running. * * $Id: t32rem.c 168156 2024-03-30 11:49:30Z fsirl $ * $LastChangedRevision: 168156 $ * $LastChangedBy: fsirl $ * * @Copyright: (C) 1989-2020 Lauterbach GmbH, licensed for use with TRACE32(R) only * ********************************************************************************************* * $Id: t32rem.c 168156 2024-03-30 11:49:30Z fsirl $ */ #if defined(_MSC_VER) # pragma warning( push ) # pragma warning( disable : 4255 4005) # include # include # include # include # include # include # pragma warning( pop ) # define strncasecmp(S1,S2,N) _strnicmp((S1), (S2), (N)) #else # ifdef __linux__ /* for usleep() declaration */ # define _BSD_SOURCE # endif # include # include # include # include # include # include # include # include # define Sleep(t) usleep((t)*1000) #endif #include "t32.h" #if !defined(_MSC_VER) static uint32_t GetTickCount(void) { struct timeval now; if ( gettimeofday( &now, NULL ) == -1 ) return 0; return (now.tv_sec*1000 + now.tv_usec/1000) & UINT32_MAX; } #endif int main(int argc, char **argp) { typedef enum { RESULT_OK = 0, RESULT_NOACCESS, RESULT_NOCONNECTION, RESULT_INVALIDINPUT, RESULT_TIMEOUT} result_t; char cmd[2048]; char * port = NULL; char * api_timeout = NULL; uint16_t msgMode, msgLen; unsigned long int wait = 0; uint8_t is_nettcp = false; result_t result = RESULT_OK; if (argc < 2) { printf( "Usage: t32rem [port=] [protocol=NETASSIST|NETTCP] [timeout=] [wait=] \n" ); printf( "Send a TRACE32 command to a running TRACE32 PowerView instance.\n"); printf( "The receiving TRACE32 instance needs to have an enabled API port.\n\n"); printf( " IP address or hostname of the machine running the receiving TRACE32.\n"); printf( " port= API port opened on the receiving TRACE32 (Default is 20000)\n"); printf( " protocol=NETASSIST|NETTCP Communication protocol used for the communication with TRACE32 (Default is NETASSIST)\n"); printf( " timeout= Communication timeout for the execution of API functions (Default is 5 seconds)\n"); printf( " wait= Wait up to the given milliseconds until all PRACTICE scripts on the\n" " receiving TRACE32 stop, after sending the command. This is useful in\n" " combination with a command starting a PRACTICE script like \"run\" or\n" " \"do\". Without this option t32rem will not wait for scripts to end.\n"); exit(RESULT_INVALIDINPUT); } /* * The executable path is at argp[0] and the position of * are fixed. The positions of port=, wait=, timeout= and * protocol=NETASSIST|NETTCP can be flexible. */ int idx_last_option_flag = 0; for (int idx = 2; idx < argc; idx++) { char * arg = argp[idx]; if (strncasecmp(arg, "port=", 5) == 0) { if (T32_Config("PORT=", &arg[5]) == -1) { printf( "port number %s not accepted\n", arg); exit(RESULT_INVALIDINPUT); } port = &arg[5]; idx_last_option_flag = idx; } else if (strncasecmp(arg, "protocol=", 9) == 0) { if (strcmp(&arg[9], "NETASSIST") == 0) { is_nettcp = false; } else if (strcmp(&arg[9], "NETTCP") == 0) { is_nettcp = true; } else { printf( "communication protocol \"%s\" not supported\n", arg); exit(RESULT_INVALIDINPUT); } idx_last_option_flag = idx; } else if (strncasecmp(arg, "timeout=", 8) == 0) { api_timeout = &arg[8]; idx_last_option_flag = idx; } else if (strncasecmp(arg, "wait=", 5) == 0) { wait = strtoul(&arg[5], NULL, 10); idx_last_option_flag = idx; } else { /* Abort on first positional/unknown flag */ break; } } int idx_command = 2; if (idx_last_option_flag > 0) { /* Command line has optional parameters */ idx_command = idx_last_option_flag + 1u; } strcpy(cmd, ""); while (idx_command < argc) { if ( (strlen(cmd) + strlen(argp[idx_command]) + 1) > (sizeof(cmd) - 1) ) { printf( "actual command line exceeds maximum internal bufferlength of %d\n", (int) sizeof(cmd) - 1 ); exit(RESULT_INVALIDINPUT); } strcat( cmd, argp[idx_command] ); strcat( cmd, " " ); idx_command++; } /* NETASSIST is the default protocol */ void * channel = NULL; if (is_nettcp) { T32_RequestChannelNetTcp(&channel); T32_SetChannel(channel); } char default_port[] = "20000"; if (port == NULL) { port = default_port; } if (T32_Config( "NODE=", argp[1]) == -1 ) { printf( "hostname %s not accepted\n", argp[1] ); exit(RESULT_INVALIDINPUT); } if (T32_Config("PORT=", port) == -1) { printf("error initializing TRACE32\n"); exit(RESULT_NOCONNECTION); } if (api_timeout != NULL) { if (T32_Config("TIMEOUT=", api_timeout) == -1) { printf("error initializing TRACE32\n"); exit(RESULT_NOCONNECTION); } } if ( T32_Init() != T32_OK ) { printf( "error initializing TRACE32\n" ); exit(RESULT_NOCONNECTION); } if (T32_Attach(1) != T32_OK) { printf("error no device\n"); exit(RESULT_NOCONNECTION); } int rc = T32_Nop(); if ( rc != T32_OK ) { goto error; } rc = T32_Stop(); if (T32_Errno != T32_OK && T32_Errno != 1) { goto error; } rc = T32_Cmd( cmd ); if ( rc != T32_OK ) { goto error; } if (wait) { uint32_t start, now; start = GetTickCount(); int pstate = -1; rc = T32_OK; while ((rc == T32_OK) && (pstate != 0)) { rc = T32_GetPracticeState(&pstate); now = GetTickCount(); // handle GetTickCount() overflow if (now < start) { wait = UINT32_MAX - start; start = 0; } if ((now - start) >= wait) { result = RESULT_TIMEOUT; break; } Sleep(1); } if (rc != T32_OK) { goto error; } } rc = T32_GetMessageString( cmd, (uint16_t)sizeof(cmd), &msgMode, &msgLen); if ( rc != T32_OK ) { goto error; } printf( "command returned "); if (msgMode & 1) printf ("General Information, "); if (msgMode & 2) printf ("Error, "); if (msgMode & 8) printf ("Status Information, "); if (msgMode & 16) printf ("Error Information, "); if (msgMode & 32) printf ("Temporary Display, "); if (msgMode & 64) printf ("Temporary Information, "); if (msgMode & 128) printf ("Empty, "); printf ("message: %s\n", cmd); T32_Exit(); return result; error: printf( "error accessing TRACE32 [#%x]\n", rc); T32_Exit(); return RESULT_NOACCESS; }