/** | |
* @file tst_sm_util.c | |
* @author NXP Semiconductors | |
* @version 1.0 | |
* @par LICENSE | |
* | |
* Copyright 2016 NXP | |
* SPDX-License-Identifier: Apache-2.0 | |
* | |
* @par Description | |
* This file implements utility functions for the example programs, not for | |
* the Host Library. | |
* @par HISTORY | |
* 1.0 06-aug-2013 : Initial version | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <assert.h> | |
#include "tst_sm_util.h" | |
#include "nxLog_App.h" | |
#ifdef TGT_EDEV | |
#include "sm_debug.h" | |
#endif | |
/** | |
* Utility function to pretty print a byte array | |
* @param[in] pName Name associated with the byte array to be printed out | |
* @param[in] pData Byte array to be printed out | |
* @param[in] dataLength length in byte of byte array A | |
* @param[in] style Style of byte array decoration (e.g. ::AX_COLON_32) | |
* @return Always returns ::AX_UTIL_OK | |
*/ | |
int axPrintByteArray(const char *pName, const U8 *pData, U16 dataLength, U16 style) | |
{ | |
#if (defined(DEBUG) || defined(FLOW_VERBOSE) || defined(AX_CONSOLE_LOG)) && !(AX_EMBEDDED) | |
U16 i = 0; | |
int nBreak = 0; | |
char preDeco[32]; | |
char postDeco[32]; | |
assert(pName != NULL); | |
assert(pData != NULL); | |
switch (style) | |
{ | |
case AX_COMPACT_16: | |
nBreak = 16; | |
strcpy(preDeco, ""); | |
strcpy(postDeco, ""); | |
break; | |
case AX_COMPACT_32: | |
nBreak = 32; | |
strcpy(preDeco, ""); | |
strcpy(postDeco, ""); | |
break; | |
case AX_COMPACT_LINE: | |
nBreak = -1; | |
strcpy(preDeco, ""); | |
strcpy(postDeco, ""); | |
break; | |
case AX_HEX_16: | |
nBreak = 16; | |
strcpy(preDeco, "0x"); | |
strcpy(postDeco, " "); | |
break; | |
case AX_HEX_32: | |
nBreak = 32; | |
strcpy(preDeco, "0x"); | |
strcpy(postDeco, " "); | |
break; | |
case AX_COLON_16: | |
nBreak = 16; | |
strcpy(preDeco, ""); | |
strcpy(postDeco, ":"); | |
break; | |
case AX_COLON_32: | |
nBreak = 32; | |
strcpy(preDeco, ""); | |
strcpy(postDeco, ":"); | |
break; | |
case AX_CARRAY_16: | |
nBreak = 16; | |
strcpy(preDeco, "0x"); | |
strcpy(postDeco, ", "); | |
break; | |
case AX_CARRAY_32: | |
nBreak = 32; | |
strcpy(preDeco, "0x"); | |
strcpy(postDeco, ", "); | |
break; | |
default: | |
nBreak = 32; | |
strcpy(preDeco, ""); | |
strcpy(postDeco, ""); | |
break; | |
} | |
printf("%s (LEN=%d):%c", pName, dataLength, (nBreak > 0) ? '\n' : ' '); | |
for (i = 0; i < dataLength ; i++) | |
{ | |
if (i == (dataLength-1)) | |
{ | |
// The last byte to print doesn't get postDeco appended | |
printf("%s%02X", preDeco, pData[i]); | |
} | |
else | |
{ | |
printf("%s%02X%s", preDeco, pData[i], postDeco); | |
} | |
if (nBreak > 0 ) | |
{ | |
if ((i+1) % nBreak == 0) {printf("\r\n");} | |
} | |
} | |
printf("\r\n"); | |
#endif | |
return AX_UTIL_OK; | |
} | |
/** | |
* Convert a Byte array into an ASCII string representation of an Hexadecimal value. | |
* | |
* Example invocation: axConvertHexString2ByteArray(byteArray, "02AA0B", 0, 3) | |
* | |
* @param[in,out] string Target (byte array as ASCII string) | |
* @param[in] stringBufSize size of string buffer (including storage required for closing '\0') | |
* @param[in] byteArray Source byte array | |
* @param[in] nByte Length to be converted (length as amount of byte; Note: 1 byte equals 2 ASCII characters) | |
* @param[in] style Style of byte array decoration (only one style supported: ::AX_COMPACT_LINE) | |
* | |
* @retval ::AX_UTIL_OK upon successfull conversion | |
* @retval ::AX_UTIL_ERROR upon failure | |
*/ | |
int axConvertByteArray2HexString(char *string, int stringBufSize, const U8 *byteArray, int nByte, U16 style) | |
{ | |
int i = 0; | |
// We only support one style at the moment | |
if (style != AX_COMPACT_LINE) | |
{ | |
return AX_UTIL_ERROR; | |
} | |
// Check whether provided stringbuffer can contain converted | |
if (stringBufSize < ((nByte << 1) + 1)) | |
{ | |
return AX_UTIL_ERROR; | |
} | |
for (i = 0; i < nByte; i++) | |
{ | |
sprintf(&string[i<<1], "%02X", byteArray[i]); | |
} | |
return AX_UTIL_OK; | |
} | |
/** | |
* Convert an ASCII string representation of an Hexadecimal value into a bytearray. | |
* | |
* Example invocation: axConvertHexString2ByteArray(byteArray, "02AA0B", 0, 3) | |
* | |
* @param[in,out] byteArray Target byte array, caller needs to ensure buffer is of sufficient size (> \p nByte) | |
* @param[in] string Source (byte array as ASCII string) | |
* @param[in] nOffset offset in string (ASCII string offset) | |
* @param[in] nByte Length to be converted (length as amount of byte; note: 2 ASCII characters equals 1 byte) | |
* | |
* @retval ::AX_UTIL_OK upon successfull conversion | |
* @retval ::AX_UTIL_ERROR upon failure | |
*/ | |
int axConvertHexString2ByteArray(U8 *byteArray, const char *string, int nOffset, int nByte) | |
{ | |
char szDummy[] = "szDummy"; | |
char *pastConverted = szDummy; // Catch number conversion issues | |
int j; | |
for (j=0; j<nByte; j++) { | |
char byteAsString[3]; | |
byteAsString[0] = string[nOffset+2*j]; | |
byteAsString[1] = string[nOffset+2*j + 1]; | |
byteAsString[2] = '\0'; | |
byteArray[j] = (U8)(strtoul(byteAsString, &pastConverted, 16)); | |
if (pastConverted == byteAsString) { | |
// Conversion failed | |
printf("(%s/%d) %s can not be converted to HEX value.\r\n", __FILE__, __LINE__, byteAsString); | |
return AX_UTIL_ERROR; | |
} | |
} | |
return AX_UTIL_OK; | |
} | |
#if defined(TGT_A71CH) || defined (TGT_A71CL) | |
/** | |
* Utility function to compare two byte arrays. Print out arrays in case they are different | |
* | |
* Use the macro ::AX_COMPARE_BYTE_ARRAY to invoke this function | |
* | |
* @param[in] aName String associated with byte array A | |
* @param[in] pA Byte array A | |
* @param[in] aLen length in byte of byte array A | |
* @param[in] bName String associated with byte array B | |
* @param[in] pB Byte array B | |
* @param[in] bLen length in byte of byte array B | |
* @param[in] style Style of byte array decoration (e.g. ::AX_COLON_32) | |
* @param[in] szFilename Filename of source file from which this function was invoked | |
* @param[in] lineNr Linenumber in source file from which the function was invoked | |
* @retval 0 Upon failed execution or wrong comparison | |
* @retval 1 Upon successfull comparison | |
* | |
*/ | |
U8 axCompareByteArray(const char *aName, const U8 *pA, U16 aLen, const char *bName, const U8 *pB, U16 bLen, U16 style, char *szFilename, int lineNr) | |
#else | |
/** | |
* Utility function to compare two byte arrays. Print out arrays in case they are different | |
* @param[in] aName String associated with byte array A | |
* @param[in] pA Byte array A | |
* @param[in] aLen length in byte of byte array A | |
* @param[in] bName String associated with byte array B | |
* @param[in] pB Byte array B | |
* @param[in] bLen length in byte of byte array B | |
* @param[in] style Style of byte array decoration (e.g. ::AX_COLON_32) | |
* @retval 0 Upon failed execution or wrong comparison | |
* @retval 1 Upon successfull comparison | |
* | |
*/ | |
U8 axCompareByteArray(const char *aName, const U8 *pA, U16 aLen, const char *bName, const U8 *pB, U16 bLen, U16 style) | |
#endif | |
{ | |
U8 uRet = 0; | |
if (aName == NULL) {return 0;} | |
if (pA == NULL) {return 0;} | |
if (bName == NULL) {return 0;} | |
if (pB == NULL) {return 0;} | |
if (aLen == bLen) | |
{ | |
if (memcmp(pA, pB, aLen) == 0) | |
{ | |
uRet = 1; | |
} | |
} | |
if (uRet != 1) | |
{ | |
printf("\r\n***** ERROR (%s != %s)\r\n", aName, bName); | |
#if defined(TGT_A71CH) || defined (TGT_A71CL) | |
printf("%s: line=%d\r\n", szFilename, lineNr); | |
#endif | |
axPrintByteArray(aName, pA, aLen, style); | |
axPrintByteArray(bName, pB, bLen, style); | |
printf("*****\r\n"); | |
} | |
return uRet; | |
} | |
/** | |
* Utility function to compare a status word (of type U16) with a reference value. | |
* | |
* Use the macro ::AX_CHECK_SW to invoke this function | |
* | |
* @param[in] sw Status word to evaluate | |
* @param[in] expectedSw Reference status word | |
* @param[in] msg Message to print in case value \p err does not equal \p expectedErr | |
* @param[in] szFilename Filename of source file from which this function was invoked | |
* @param[in] lineNr Linenumber in source file from which the function was invoked | |
* @retval 0 Upon failed execution or wrong comparison | |
* @retval 1 Upon successfull comparison | |
* | |
*/ | |
U8 axCheckSw(U16 sw, U16 expectedSw, char *msg, char *szFilename, int lineNr) | |
{ | |
if (sw != expectedSw) | |
{ | |
LOG_E("\r\n***** ERROR (%s)\r\n", msg); | |
LOG_E("%s: line=%d\r\n", szFilename, lineNr); | |
LOG_E("***** Expected SW 0x%04x, but got 0x%04X\r\n", expectedSw, sw); | |
return 0; | |
} | |
else | |
{ | |
return 1; | |
} | |
} | |
/** | |
* Utility function to compare a value of type U8 with a reference value. | |
* | |
* Use the macro ::AX_CHECK_U8 to invoke this function | |
* | |
* @param[in] in U8 variable to evaluate | |
* @param[in] expected Reference value | |
* @param[in] msg Message to print in case value \p in does not equal \p expected | |
* @param[in] szFilename Filename of source file from which this function was invoked | |
* @param[in] lineNr Linenumber in source file from which the function was invoked | |
* @retval 0 Upon failed execution or wrong comparison | |
* @retval 1 Upon successfull comparison | |
* | |
*/ | |
U8 axCheckU8(U8 in, U8 expected, char *msg, char *szFilename, int lineNr) | |
{ | |
if (in != expected) | |
{ | |
LOG_E("\r\n***** ERROR (%s)\r\n", msg); | |
LOG_E("%s: line=%d\r\n", szFilename, lineNr); | |
LOG_E("***** Expected 0x%02x, but got 0x%02x\r\n", expected, in); | |
return 0; | |
} | |
else | |
{ | |
return 1; | |
} | |
} | |
/** | |
* Utility function to compare a value of type U16 with a reference value. | |
* | |
* Use the macro ::AX_CHECK_U16 to invoke this function | |
* | |
* @param[in] in U16 variable to evaluate | |
* @param[in] expected Reference value | |
* @param[in] msg Message to print in case value \p in does not equal \p expected | |
* @param[in] szFilename Filename of source file from which this function was invoked | |
* @param[in] lineNr Linenumber in source file from which the function was invoked | |
* @retval 0 Upon failed execution or wrong comparison | |
* @retval 1 Upon successfull comparison | |
* | |
*/ | |
U8 axCheckU16(U16 in, U16 expected, char *msg, char *szFilename, int lineNr) | |
{ | |
if (in != expected) | |
{ | |
LOG_E("\r\n***** ERROR (%s)\r\n", msg); | |
LOG_E("%s: line=%d\r\n", szFilename, lineNr); | |
LOG_E("***** Expected 0x%02x, but got 0x%02x\r\n", expected, in); | |
return 0; | |
} | |
else | |
{ | |
return 1; | |
} | |
} | |
/** | |
* Extend the byte array \p pStore with 0x00 byte(s). This is typically required when | |
* a big integer has - previously - been stripped from its (superfluous) sign bits. | |
* The caller must ensure \p expectedLength is bigger than \p actualLength | |
* @param[in,out] pStore Array representation of big number, to be zero sign extended. | |
* Size of corresponding buffer must be at least \p expectedLength | |
* @param[in] actualLength Length of incoming array \p pStore | |
* @param[in] expectedLength Zero sign extend until this length. | |
* | |
* @retval SW_OK In case of successfull execution | |
* @retval ERR_API_ERROR Requested adjustment would result in truncation | |
*/ | |
U16 axZeroSignExtend(U8* pStore, U16 actualLength, U16 expectedLength) | |
{ | |
U16 sw = SW_OK; | |
int numExtraByte = (int)expectedLength - (int)actualLength; | |
if (numExtraByte == 0) { | |
// Do nothing | |
} | |
else if (numExtraByte < 0) { | |
// Flag an API error | |
sw = ERR_API_ERROR; | |
} | |
else { | |
memmove(pStore + numExtraByte, pStore, actualLength); | |
memset(pStore, 0x00, numExtraByte); | |
} | |
return sw; | |
} | |
#if !defined(TGT_A71CH) && !defined(TGT_A71CL) | |
// Utility functions | |
void printBytestring(const char *pName, const U8 *pData, U16 dataLength) | |
{ | |
U16 i = 0; | |
assert(pName != NULL); | |
assert(pData != NULL); | |
printf("%s (LEN=%d):\r\n", pName, dataLength); | |
for (i = 0; i < dataLength ; i++) | |
{ | |
printf("%02X ", pData[i]); | |
} | |
printf("\r\n"); | |
} | |
U8 checkBytestring(U8 *pA, U16 aLength, U8 * pB, U16 bLength, char *msg) | |
{ | |
if (compareBytestrings(pA, aLength,pB, bLength) != 0) | |
{ | |
printf("\r\n***** ERROR (%s)\r\n", msg); | |
printf("Bytestring are different:\r\n"); | |
axPrintByteArray ("A", pA, aLength, AX_COLON_32); | |
axPrintByteArray ("B", pB, bLength, AX_COLON_32); | |
// assert(0); | |
return 0; | |
} | |
else | |
{ | |
return 1; | |
} | |
} | |
// U8 *byteArray : Target byte array, caller needs to ensure buffer is of sufficient size (>nByte) | |
// const char *string : Source (byte array as ASCII string) | |
// int nOffset : offset in string (ASCII string offset) | |
// int nByte : length to be converted (length as amount of byte; note: 2 ASCII characters equals 1 byte) | |
// | |
// Obsolete function, please use axConvertHexString2ByteArray | |
int convertString2ByteArray(U8 *byteArray, const char *string, int nOffset, int nByte) | |
{ | |
int j; | |
for (j=0; j<nByte; j++) { | |
char byteAsString[3]; | |
byteAsString[0] = string[nOffset+2*j]; | |
byteAsString[1] = string[nOffset+2*j + 1]; | |
byteAsString[2] = '\0'; | |
byteArray[j] = (U8)(strtoul(byteAsString, (char **)NULL, 16)); | |
} | |
return 0; | |
} | |
int compareBytestrings(U8 *pA, U16 aLength, U8 *pB, U16 bLength) | |
{ | |
assert (pA != NULL); | |
assert (pB != NULL); | |
if (aLength < bLength) { | |
return (-1); | |
} | |
else if (aLength > bLength) { | |
return (+1); | |
} | |
else { | |
return memcmp(pA, pB, aLength); | |
} | |
} | |
/** | |
* Utility function to compare a status word (of type U16) with a reference value. | |
* @param[in] err Status word to evaluate | |
* @param[in] expectedErr Reference status word | |
* @param[in] msg Message to print in case value \p err does not equal \p expectedErr | |
* @retval 0 Upon failed execution or wrong comparison | |
* @retval 1 Upon successfull comparison | |
* | |
*/ | |
U8 checkErr(U16 err, U16 expectedErr, char *msg) | |
{ | |
if (err != expectedErr) | |
{ | |
printf("\r\n***** ERROR (%s)\r\n", msg); | |
printf("***** Expected ERR 0x%04x, but got 0x%04X\r\n", expectedErr, err); | |
// assert(0); | |
return 0; | |
} | |
else | |
{ | |
return 1; | |
} | |
} | |
/** | |
* Utility function to compare a value of type U8 with a reference value. | |
* @param[in] in U8 variable to evaluate | |
* @param[in] expected Reference value | |
* @param[in] msg Message to print in case value \p in does not equal \p expected | |
* @retval 0 Upon failed execution or wrong comparison | |
* @retval 1 Upon successfull comparison | |
* | |
*/ | |
U8 checkU8(U8 in, U8 expected, char *msg) | |
{ | |
if (in != expected) | |
{ | |
printf("\r\n***** ERROR (%s)\r\n", msg); | |
printf("***** Expected 0x%02x, but got 0x%02x\r\n", expected, in); | |
// assert(0); | |
return 0; | |
} | |
else | |
{ | |
return 1; | |
} | |
} | |
/** | |
* Utility function to compare a value of type U16 with a reference value. | |
* @param[in] in U8 variable to evaluate | |
* @param[in] expected Reference value | |
* @param[in] msg Message to print in case value \p in does not equal \p expected | |
* @retval 0 Upon failed execution or wrong comparison | |
* @retval 1 Upon successfull comparison | |
* | |
*/ | |
U8 checkU16(U16 in, U16 expected, char *msg) | |
{ | |
if (in != expected) | |
{ | |
printf("\r\n***** ERROR (%s)\r\n", msg); | |
printf("***** Expected 0x%04x, but got 0x%04x\r\n", expected, in); | |
// assert(0); | |
return 0; | |
} | |
else | |
{ | |
return 1; | |
} | |
} | |
#endif // TGT_A71CH | |
#ifdef TGT_A70CI | |
char* getLifecycleStateName(U16 state) | |
{ | |
switch(state) | |
{ | |
case SM_FACTORY: | |
return "SM_FACTORY"; | |
case SM_CONFIGURE_INITIAL: | |
return "SM_CONFIGURE_INITIAL"; | |
case SM_CONFIGURE: | |
return "SM_CONFIGURE"; | |
case SM_OPERATE: | |
return "SM_OPERATE"; | |
case SM_DEAD: | |
return "SM_DEAD"; | |
case SM_UNKNOWN: | |
return "SM_UNKNOWN"; | |
default: | |
// this should not happen | |
assert(0); | |
return ""; | |
} | |
} | |
#elif defined(TGT_A70CM) | |
char* getLifecycleStateName(U16 state) | |
{ | |
switch(state) { | |
case SM_FACTORY: | |
return "SM_FACTORY"; | |
case SM_CONFIGURE_INITIAL: | |
return "SM_CONFIGURE_INITIAL"; | |
case SM_CONFIGURE: | |
return "SM_CONFIGURE"; | |
case SM_OPERATE: | |
return "SM_OPERATE"; | |
case SM_RE_CONFIGURE: | |
return "SM_RE_CONFIGURE"; | |
case SM_DEAD: | |
return "SM_DEAD"; | |
case SM_UNKNOWN: | |
return "SM_UNKNOWN"; | |
default: | |
// this should not happen | |
assert(0); | |
return ""; | |
} | |
} | |
#elif defined(TGT_A71CH) | |
#elif defined(TGT_A71CL) | |
#else | |
char* getLifecycleStateName(U8 state) | |
{ | |
//switch(state) | |
//{ | |
// case SM_FACTORY: | |
// return "SM_FACTORY"; | |
// case SM_LOCKED: | |
// return "SM_LOCKED"; | |
// case SM_CONFIGURE_INITIAL: | |
// return "SM_CONFIGURE_INITIAL"; | |
// case SM_CONFIGURE: | |
// return "SM_CONFIGURE"; | |
// case SM_OPERATE: | |
// return "SM_OPERATE"; | |
// case SM_DIAGNOSTIC: | |
// return "SM_DIAGNOSTIC"; | |
// case SM_DEACTIVATED: | |
// return "SM_DEACTIVATED"; | |
// case SM_DEAD: | |
// return "SM_DEAD"; | |
// default: | |
// // this should not happen | |
// assert(0); | |
// return ""; | |
//} | |
} | |
char *getUserName(U8 user) | |
{ | |
switch (user) | |
{ | |
/* case P2_USER_UNAUTH: | |
return "unauth"; | |
case P2_USER_ADMIN: | |
return "admin"; | |
case P2_USER_HOST: | |
return "host"; | |
default: | |
assert(0); | |
return "";*/ | |
} | |
} | |
#ifdef TGT_EDEV | |
U8 setUser(U8 targetUser) | |
{ | |
U8 result = 1; | |
U16 err = 0; | |
sm_printf(CONSOLE, "DBG_SetUser(%s)\r\n", getUserName(targetUser)); | |
err = DBG_SetUser(targetUser); | |
result &= checkErr(err, SW_OK, "err"); | |
return result; | |
} | |
#endif | |
#endif // TGT_A70CI |