/** * @file smComSCI2c.c * @author NXP Semiconductors * @version 1.0 * @par License * * Copyright 2016,2020 NXP * SPDX-License-Identifier: Apache-2.0 * * @par Description * This file implements the SmCom JRCP-V2 communication layer. * *****************************************************************************/ #include #include #include "smComJRCP.h" #include "sm_printf.h" #include "sm_apdu.h" #include #include "ex_sss_ports.h" #if defined(SSS_USE_FTR_FILE) #include "fsl_sss_ftr.h" #else #include "fsl_sss_ftr_default.h" #endif #ifdef FLOW_VERBOSE # define NX_LOG_ENABLE_SMCOM_DEBUG 1 #endif // #define NX_LOG_ENABLE_SMCOM_DEBUG 1 #if SSS_HAVE_APPLET_SE051_UWB static uint8_t isAlreadyOpen = false; #endif #include #include "nxEnsure.h" #if defined(SMCOM_JRCP_V2) #include static U32 smComJRCP_Transceive(void* conn_ctx, apdu_t * pApdu); static U32 smComJRCP_TransceiveRaw(void* conn_ctx, U8 * pTx, U16 txLen, U8 * pRx, U32 * pRxLen); static jrcplib_tcpclient_ctx_t* gctx = NULL; U16 smComJRCP_Close(void* conn_ctx, U8 mode) { jrcplib_tcpclient_ctx_t* ctx = (conn_ctx == NULL) ? gctx : (jrcplib_tcpclient_ctx_t*)conn_ctx; if (ctx != NULL) { if (gctx == ctx) { gctx = NULL; } jrcplib_tcpclient_disconnect(ctx); jrcplib_tcpclient_free(ctx); ctx = NULL; } #if SSS_HAVE_APPLET_SE051_UWB isAlreadyOpen = false; #endif return SW_OK; } // // smComSCI2C_Init is deprecated, please use smComSCI2C_Open // #ifndef TGT_A71CH void smComJRCP_Init() { smCom_Init(&smComJRCP_Transceive, &smComJRCP_TransceiveRaw); } #endif U16 smComJRCP_Open(void** conn_ctx, const char *hostname_in, unsigned int portnum_in) { int32_t ret = 0; const char *hostname_env; const char *hostname_selected; char szHostname[70] = {0}; unsigned int portnum = 0; const char *hostname_default = EX_SSS_BOOT_SSS_SOCKET_HOSTNAME_DEFAULT; const unsigned int portnum_default = EX_SSS_BOOT_SSS_SOCKET_PORTNUMBER_DEFAULT; jrcplib_tcpclient_ctx_t* ctx = NULL; #if SSS_HAVE_APPLET_SE051_UWB if (isAlreadyOpen) { if(conn_ctx != NULL) { *conn_ctx = gctx; } // TODO disabled check for communication with two simulators return SW_OK; } #endif /* First priority Environment variable */ hostname_env = getenv("JRCP_HOSTNAME"); if (NULL == hostname_env) { /* No ENV */ if (hostname_in == NULL) { /* No value from CLI : use default */ hostname_selected = hostname_default; LOG_I("Hostname taken from default '%s'. Set 'JRCP_HOSTNAME' to override.", hostname_default); } else { /* Take from CLI */ hostname_selected = hostname_in; } } else { strncpy(szHostname, hostname_env, sizeof(szHostname) - 1); hostname_selected = szHostname; } /* First priority Environment variable */ const char *portnum_str_env = getenv("JRCP_PORT"); if (portnum_str_env != NULL) { /* ENV has it, use that*/ portnum = strtol(portnum_str_env, NULL, 10); } if (0 == portnum) { /* No ENV */ if (0 == portnum_in) { /* CLI didn't have it, env didn't have it, use default*/ portnum = portnum_default; LOG_I("Port number taken from default. Set 'JRCP_PORT' to override."); } else { portnum = portnum_in; } } LOG_I("Opening connection to JRCP server on %s:%d", hostname_selected, portnum); ret = jrcplib_tcpclient_init(&ctx); if (ret < 0) { LOG_E("%s", jrcplib_get_error_string(ret)); smComJRCP_Close(ctx, 0); return SMCOM_COM_FAILED; } ret = jrcplib_tcpclient_connect_to_default_node(ctx, hostname_selected, (uint16_t)portnum); if (ret < 0) { LOG_E("%s", jrcplib_get_error_string(ret)); smComJRCP_Close(ctx, 0); return SMCOM_COM_FAILED; } uint32_t nodes_count; jrcplib_nad_t *nodes = NULL; ret = jrcplib_tcpclient_list_nodes(ctx, &nodes_count, &nodes); if (ret < 0) { LOG_E("%s", jrcplib_get_error_string(ret)); smComJRCP_Close(ctx, 0); return SMCOM_COM_FAILED; } /*int i = 0; for (; i < nodes_count; i++) { printf("Node: NAD: %d, Name: %s\n", nodes[i].nad, nodes[i].description); }*/ ret = jrcplib_tcpclient_list_nodes_cleanup(nodes_count, nodes); if (ret < 0) { LOG_E("%s", jrcplib_get_error_string(ret)); smComJRCP_Close(ctx, 0); return SMCOM_COM_FAILED; } ret = jrcplib_tcpclient_reset(ctx, ColdReset); if (ret < 0) { LOG_E("%s", jrcplib_get_error_string(ret)); smComJRCP_Close(ctx, 0); return SMCOM_COM_FAILED; } LOG_D("Opening connection to JRCP successful"); if (conn_ctx == NULL) { gctx = ctx; } else { gctx = ctx; *conn_ctx = ctx; } ret =(U32) smCom_Init(&smComJRCP_Transceive, &smComJRCP_TransceiveRaw); #if SSS_HAVE_APPLET_SE051_UWB isAlreadyOpen = true; #endif return (U16)ret; } U16 smComJRCP_Reset(void* conn_ctx, uint32_t instruction_bytes) { int32_t ret = 0; jrcplib_tcpclient_ctx_t* ctx = (conn_ctx == NULL) ? gctx : (jrcplib_tcpclient_ctx_t*)conn_ctx; ret = jrcplib_tcpclient_prepare_reset(ctx, ColdReset, instruction_bytes); if (ret < 0) { LOG_E("%s", jrcplib_get_error_string(ret)); smComJRCP_Close(ctx, 0); return SMCOM_COM_FAILED; } LOG_D("Resetting JRCP successful"); return SMCOM_OK; } static U32 smComJRCP_Transceive(void* conn_ctx, apdu_t * pApdu) { U32 respLen = MAX_APDU_BUF_LENGTH; U32 retCode = SMCOM_COM_FAILED; jrcplib_tcpclient_ctx_t* ctx = (conn_ctx == NULL) ? gctx : (jrcplib_tcpclient_ctx_t*)conn_ctx; ENSURE_OR_GO_EXIT(pApdu != NULL); retCode = smComJRCP_TransceiveRaw(ctx, (U8 *)pApdu->pBuf, pApdu->buflen, pApdu->pBuf, &respLen); pApdu->rxlen = (U16)respLen; exit: return retCode; } static U32 smComJRCP_TransceiveRaw(void* conn_ctx, U8 * pTx, U16 txLen, U8 * pRx, U32 * pRxLen) { size_t resp_len = *pRxLen; jrcplib_tcpclient_ctx_t* ctx = (conn_ctx == NULL) ? gctx : (jrcplib_tcpclient_ctx_t*)conn_ctx; if (ctx == NULL) { LOG_W("ctx==NULL"); return SMCOM_COM_FAILED; } LOG_MAU8_D("Tx>", pTx, txLen); int32_t ret = jrcplib_tcpclient_dataexchange(ctx, txLen, pTx, *pRxLen, pRx, &resp_len); *pRxLen = (U32)resp_len; if (ret < 0) { LOG_E("%s", jrcplib_get_error_string(ret)); return SMCOM_RCV_FAILED; } LOG_MAU8_D("