Unverified Commit 323aeda3 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #8322 from mavlink/pr-remove-nxpnfc

Remove reference to NXP NFC Library. Keep only QtNFC.
parents afe86c3e 1d36547d
......@@ -22,7 +22,6 @@ linux {
message("Linux build")
CONFIG += LinuxBuild
DEFINES += __STDC_LIMIT_MACROS
DEFINES += QGC_ENABLE_NFC RW_SUPPORT
DEFINES += QGC_GST_TAISYNC_ENABLED
DEFINES += QGC_GST_MICROHARD_ENABLED
DEFINES += QGC_ENABLE_MAVLINK_INSPECTOR
......
......@@ -147,12 +147,10 @@ contains(DEFINES, QGC_ENABLE_PAIRING) {
} else {
# There is some circular reference settings going on between QGCExternalLibs.pri and gqgroundcontrol.pro.
# So this duplicates some of the enable/disable logic which would normally be in qgroundcontrol.pro.
DEFINES -= QGC_ENABLE_NFC
DEFINES -= QGC_ENABLE_PAIRING
}
} else:WindowsBuild {
#- Pairing is not supported on Windows
DEFINES -= QGC_ENABLE_NFC
DEFINES -= QGC_ENABLE_PAIRING
} else {
LIBS += -lcrypto -lz
......
......@@ -187,18 +187,6 @@ contains (DEFINES, QGC_DISABLE_BLUETOOTH) {
DEFINES += QGC_ENABLE_BLUETOOTH
}
# NFC
contains (DEFINES, QGC_DISABLE_NFC) {
message("Skipping support for NFC (manual override from command line)")
DEFINES -= QGC_ENABLE_NFC
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, QGC_DISABLE_NFC) {
message("Skipping support for NFC (manual override from user_config.pri)")
DEFINES -= QGC_ENABLE_NFC
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, QGC_ENABLE_NFC) {
message("Including support for NFC (manual override from user_config.pri)")
DEFINES += QGC_ENABLE_NFC
}
# QTNFC
contains (DEFINES, QGC_DISABLE_QTNFC) {
message("Skipping support for QTNFC (manual override from command line)")
......@@ -318,14 +306,11 @@ DEFINES+=QGC_DISABLE_PAIRING
# Pairing
contains (DEFINES, QGC_DISABLE_PAIRING) {
message("Skipping support for Pairing")
DEFINES -= QGC_ENABLE_NFC
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, QGC_DISABLE_PAIRING) {
message("Skipping support for Pairing (manual override from user_config.pri)")
DEFINES -= QGC_ENABLE_NFC
} else:AndroidBuild:contains(QT_ARCH, arm64) {
# Haven't figured out how to get 64 bit arm OpenSLL yet which pairing requires
message("Skipping support for Pairing (Missing Android OpenSSL 64 bit support)")
DEFINES -= QGC_ENABLE_NFC
} else {
message("Enabling support for Pairing")
DEFINES += QGC_ENABLE_PAIRING
......@@ -737,37 +722,6 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
}
}
contains (DEFINES, QGC_ENABLE_PAIRING) {
contains(DEFINES, QGC_ENABLE_NFC) {
HEADERS += \
src/PairingManager/PairingNFC.h \
src/PairingManager/NfcLibrary/inc/Nfc.h \
src/PairingManager/NfcLibrary/inc/Nfc_settings.h \
src/PairingManager/NfcLibrary/NdefLibrary/inc/P2P_NDEF.h \
src/PairingManager/NfcLibrary/NdefLibrary/inc/RW_NDEF.h \
src/PairingManager/NfcLibrary/NdefLibrary/inc/RW_NDEF_T1T.h \
src/PairingManager/NfcLibrary/NdefLibrary/inc/RW_NDEF_T2T.h \
src/PairingManager/NfcLibrary/NdefLibrary/inc/RW_NDEF_T3T.h \
src/PairingManager/NfcLibrary/NdefLibrary/inc/RW_NDEF_T4T.h \
src/PairingManager/NfcLibrary/NdefLibrary/inc/T4T_NDEF_emu.h \
src/PairingManager/NfcLibrary/NxpNci/inc/NxpNci.h \
src/PairingManager/NfcTask/inc/ndef_helper.h \
src/PairingManager/TML/inc/framework_Allocator.h \
src/PairingManager/TML/inc/framework_Interface.h \
src/PairingManager/TML/inc/framework_Map.h \
src/PairingManager/TML/inc/framework_Timer.h \
src/PairingManager/TML/inc/lpcusbsio.h \
src/PairingManager/TML/inc/tml.h \
src/PairingManager/TML/inc/tool.h \
src/PairingManager/TML/inc/framework_Container.h \
src/PairingManager/TML/inc/framework_linux.h \
src/PairingManager/TML/inc/framework_Parcel.h \
src/PairingManager/TML/inc/hidapi.h \
src/PairingManager/TML/inc/lpcusbsio_i2c.h \
src/PairingManager/TML/inc/tml_hid.h
}
}
!NoSerialBuild {
HEADERS += \
src/comm/QGCSerialPortInfo.h \
......@@ -966,36 +920,6 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
}
}
contains (DEFINES, QGC_ENABLE_PAIRING) {
contains(DEFINES, QGC_ENABLE_NFC) {
SOURCES += \
src/PairingManager/PairingNFC.cc \
src/PairingManager/NfcLibrary/NxpNci/src/NxpNci.c \
src/PairingManager/NfcLibrary/NdefLibrary/src/RW_NDEF_T4T.c \
src/PairingManager/NfcLibrary/NdefLibrary/src/P2P_NDEF.c \
src/PairingManager/NfcLibrary/NdefLibrary/src/RW_NDEF_T3T.c \
src/PairingManager/NfcLibrary/NdefLibrary/src/RW_NDEF.c \
src/PairingManager/NfcLibrary/NdefLibrary/src/RW_NDEF_T1T.c \
src/PairingManager/NfcLibrary/NdefLibrary/src/RW_NDEF_T2T.c \
src/PairingManager/NfcLibrary/NdefLibrary/src/T4T_NDEF_emu.c \
src/PairingManager/TML/src/framework_Map.c \
src/PairingManager/TML/src/framework_log.c \
src/PairingManager/TML/src/framework_Parcel.c \
src/PairingManager/TML/src/framework_sem.c \
src/PairingManager/TML/src/framework_mutex.c \
src/PairingManager/TML/src/hid.c \
src/PairingManager/TML/src/framework_Allocator.c \
src/PairingManager/TML/src/tml_hid.c \
src/PairingManager/TML/src/framework_Container.c \
src/PairingManager/TML/src/framework_thread.c \
src/PairingManager/TML/src/framework_Timer.c \
src/PairingManager/TML/src/lpcusbsio.c \
src/PairingManager/TML/src/tml.c \
src/PairingManager/NfcTask/src/ndef_helper.c
LIBS += -lrt -ludev
}
}
!MobileBuild {
SOURCES += \
src/GPS/Drivers/src/gps_helper.cpp \
......
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#define P2P_NDEF_MAX_NDEF_MESSAGE_SIZE 240
void P2P_NDEF_Reset(void);
void P2P_NDEF_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#define RW_MAX_NDEF_FILE_SIZE 500
extern unsigned char NdefBuffer[RW_MAX_NDEF_FILE_SIZE];
typedef void RW_NDEF_Callback_t (unsigned char*, unsigned short);
#define RW_NDEF_TYPE_T1T 0x1
#define RW_NDEF_TYPE_T2T 0x2
#define RW_NDEF_TYPE_T3T 0x3
#define RW_NDEF_TYPE_T4T 0x4
extern unsigned char *pRW_NdefMessage;
extern unsigned short RW_NdefMessage_size;
extern RW_NDEF_Callback_t *pRW_NDEF_PullCb;
extern RW_NDEF_Callback_t *pRW_NDEF_PushCb;
void RW_NDEF_Reset(unsigned char type);
void RW_NDEF_Read_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
void RW_NDEF_Write_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
void RW_NDEF_T1T_Reset(void);
void RW_NDEF_T1T_Read_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
void RW_NDEF_T2T_Reset(void);
void RW_NDEF_T2T_Read_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
void RW_NDEF_T2T_Write_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
void RW_NDEF_T3T_Reset(void);
void RW_NDEF_T3T_SetIDm(unsigned char *pIDm);
void RW_NDEF_T3T_Read_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
void RW_NDEF_T4T_Reset(void);
void RW_NDEF_T4T_Read_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
void RW_NDEF_T4T_Write_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
void T4T_NDEF_EMU_Reset(void);
void T4T_NDEF_EMU_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#ifdef P2P_SUPPORT
#include <TML/inc/tool.h>
#include <NfcLibrary/NdefLibrary/inc/P2P_NDEF.h>
/* Well-known LLCP SAP Values */
#define SAP_SDP 1
#define SAP_SNEP 4
/* SNEP codes */
#define SNEP_VER10 0x10
#define SNEP_PUT 0x2
#define SNEP_SUCCESS 0x81
/* LLCP PDU Types */
#define SYMM 0x0
#define PAX 0x1
#define AGF 0x2
#define UI 0x3
#define CONNECT 0x4
#define DISC 0x5
#define CC 0x6
#define DM 0x7
#define FRMR 0x8
#define SNL 0x9
#define reservedA 0xA
#define reservedB 0xB
#define I 0xC
#define RR 0xD
#define RNR 0xE
#define reservedF 0xF
/* LLCP parameters */
#define VERSION 1
#define MIUX 2
#define WKS 3
#define LTO 4
#define RW 5
#define SN 6
const unsigned char SNEP_PUT_SUCCESS[] = {SNEP_VER10, SNEP_SUCCESS, 0x00, 0x00, 0x00, 0x00};
const unsigned char LLCP_CONNECT_SNEP[] = {0x11, 0x20};
const unsigned char LLCP_I_SNEP_PUT_HEADER[] = {SNEP_VER10, SNEP_PUT, 0x00, 0x00, 0x00, 0x00};
const unsigned char LLCP_SYMM[] = {0x00, 0x00};
unsigned char *pNdefMessage;
unsigned short NdefMessage_size = 0;
/* Defines the number of symmetry exchanges is expected before initiating the NDEF push (to allow a remote phone to beam an NDEF message first) */
#define NDEF_PUSH_DELAY_COUNT 2
/* Defines at which frequency the symmetry is exchange (in ms) */
#define SYMM_FREQ 500
typedef enum
{
Idle,
Initial,
DelayingPush,
SnepClientConnecting,
SnepClientConnected,
NdefMsgSent
} P2P_SnepClient_state_t;
typedef struct
{
unsigned char Dsap;
unsigned char Pdu;
unsigned char Ssap;
unsigned char Version;
unsigned short Miux;
unsigned short Wks;
unsigned char Lto;
unsigned char Rw;
unsigned char Sn[30];
} P2P_NDEF_LlcpHeader_t;
typedef void P2P_NDEF_Callback_t (unsigned char*, unsigned short);
static P2P_SnepClient_state_t eP2P_SnepClient_State = Initial;
static P2P_NDEF_Callback_t *pP2P_NDEF_PushCb = NULL;
static P2P_NDEF_Callback_t *pP2P_NDEF_PullCb = NULL;
static unsigned short P2P_SnepClient_DelayCount = NDEF_PUSH_DELAY_COUNT;
static void ParseLlcp(unsigned char *pBuf, unsigned short BufSize, P2P_NDEF_LlcpHeader_t *pLlcpHeader)
{
uint8_t i = 2;
pLlcpHeader->Dsap = pBuf[0] >> 2;
pLlcpHeader->Pdu = ((pBuf[0] & 3) << 2) + (pBuf[1] >> 6);
pLlcpHeader->Ssap = pBuf[1] & 0x3F;
while(i<BufSize)
{
switch (pBuf[i]){
case VERSION:
pLlcpHeader->Version = pBuf[i+2];
break;
case MIUX:
pLlcpHeader->Miux = (pBuf[i+2] << 8) + pBuf[i+3];
break;
case WKS:
pLlcpHeader->Wks = (pBuf[i+2] << 8) + pBuf[i+3];
break;
case LTO:
pLlcpHeader->Lto = pBuf[i+2];
break;
case RW:
pLlcpHeader->Rw = pBuf[i+2];
break;
case SN:
memcpy(pLlcpHeader->Sn, &pBuf[i+2], pBuf[i+1] < sizeof(pLlcpHeader->Sn) ? pBuf[i+1] : sizeof(pLlcpHeader->Sn));
break;
default:
break;
}
i += pBuf[i+1]+2;
}
}
static void FillLlcp(P2P_NDEF_LlcpHeader_t LlcpHeader, unsigned char *pBuf)
{
pBuf[0] = (LlcpHeader.Ssap << 2) + ((LlcpHeader.Pdu >> 2) & 3);
pBuf[1] = (LlcpHeader.Pdu << 6) + LlcpHeader.Dsap;
}
bool P2P_NDEF_SetMessage(unsigned char *pMessage, unsigned short Message_size, void *pCb)
{
if (Message_size <= P2P_NDEF_MAX_NDEF_MESSAGE_SIZE)
{
pNdefMessage = pMessage;
NdefMessage_size = Message_size;
pP2P_NDEF_PushCb = (P2P_NDEF_Callback_t*) pCb;
return true;
}
else
{
NdefMessage_size = 0;
pP2P_NDEF_PushCb = NULL;
return false;
}
}
void P2P_NDEF_RegisterPullCallback(void *pCb)
{
pP2P_NDEF_PullCb = (P2P_NDEF_Callback_t*) pCb;
}
void P2P_NDEF_Reset(void)
{
if (NdefMessage_size != 0)
{
eP2P_SnepClient_State = Initial;
}
else
{
eP2P_SnepClient_State = Idle;
}
}
void P2P_NDEF_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *pRsp, unsigned short *pRsp_size)
{
P2P_NDEF_LlcpHeader_t LlcpHeader;
/* Initialize answer */
*pRsp_size = 0;
ParseLlcp(pCmd, Cmd_size, &LlcpHeader);
switch (LlcpHeader.Pdu)
{
case CONNECT:
/* Is connection from SNEP Client ? */
if ((LlcpHeader.Dsap == SAP_SNEP) || (memcmp(LlcpHeader.Sn, "urn:nfc:sn:snep", 15) == 0))
{
/* Only accept the connection is application is registered for NDEF reception */
if(pP2P_NDEF_PullCb != NULL)
{
LlcpHeader.Pdu = CC;
FillLlcp(LlcpHeader, pRsp);
*pRsp_size = 2;
}
}
else
{
/* Refuse any other connection request */
LlcpHeader.Pdu = DM;
FillLlcp(LlcpHeader, pRsp);
*pRsp_size = 2;
}
break;
case I:
/* Is SNEP PUT ? */
if ((pCmd[3] == SNEP_VER10) && (pCmd[4] == SNEP_PUT))
{
/* Notify application of the NDEF reception */
if(pP2P_NDEF_PullCb != NULL) pP2P_NDEF_PullCb(&pCmd[9], pCmd[8]);
/* Acknowledge the PUT request */
LlcpHeader.Pdu = I;
FillLlcp(LlcpHeader, pRsp);
pRsp[2] = (pCmd[2] >> 4) + 1; // N(R)
memcpy(&pRsp[3], SNEP_PUT_SUCCESS, sizeof(SNEP_PUT_SUCCESS));
*pRsp_size = 9;
}
break;
case CC:
/* Connection to remote SNEP server completed, send NDEF message inside SNEP PUT request */
eP2P_SnepClient_State = SnepClientConnected;
break;
default:
break;
}
/* No answer was set */
if (*pRsp_size == 0)
{
switch(eP2P_SnepClient_State)
{
case Initial:
if((pP2P_NDEF_PullCb == NULL) || (NDEF_PUSH_DELAY_COUNT == 0))
{
memcpy(pRsp, LLCP_CONNECT_SNEP, sizeof(LLCP_CONNECT_SNEP));
*pRsp_size = sizeof(LLCP_CONNECT_SNEP);
eP2P_SnepClient_State = SnepClientConnecting;
}
else
{
P2P_SnepClient_DelayCount = 1;
eP2P_SnepClient_State = DelayingPush;
/* Wait then send a SYMM */
Sleep (SYMM_FREQ);
memcpy(pRsp, LLCP_SYMM, sizeof(LLCP_SYMM));
*pRsp_size = sizeof(LLCP_SYMM);
}
break;
case DelayingPush:
if(P2P_SnepClient_DelayCount == NDEF_PUSH_DELAY_COUNT)
{
memcpy(pRsp, LLCP_CONNECT_SNEP, sizeof(LLCP_CONNECT_SNEP));
*pRsp_size = sizeof(LLCP_CONNECT_SNEP);
eP2P_SnepClient_State = SnepClientConnecting;
}
else
{
P2P_SnepClient_DelayCount++;
/* Wait then send a SYMM */
Sleep (1000);
memcpy(pRsp, LLCP_SYMM, sizeof(LLCP_SYMM));
*pRsp_size = sizeof(LLCP_SYMM);
}
break;
case SnepClientConnected:
LlcpHeader.Pdu = I;
FillLlcp(LlcpHeader, pRsp);
pRsp[2] = 0; // N(R)
pRsp[3] = SNEP_VER10;
pRsp[4] = SNEP_PUT;
pRsp[5] = 0;
pRsp[6] = 0;
pRsp[7] = 0;
pRsp[8] = (unsigned char) NdefMessage_size;
memcpy(&pRsp[9], pNdefMessage, NdefMessage_size);
*pRsp_size = 9 + NdefMessage_size;
eP2P_SnepClient_State = NdefMsgSent;
/* Notify application of the NDEF push */
if(pP2P_NDEF_PushCb != NULL) pP2P_NDEF_PushCb(pNdefMessage, NdefMessage_size);
break;
default:
/* Wait then send a SYMM */
Sleep (SYMM_FREQ);
memcpy(pRsp, LLCP_SYMM, sizeof(LLCP_SYMM));
*pRsp_size = sizeof(LLCP_SYMM);
break;
}
}
}
#endif
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#ifdef RW_SUPPORT
#ifndef NO_NDEF_SUPPORT
#include <TML/inc/tool.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF_T1T.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF_T2T.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF_T3T.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF_T4T.h>
/* Allocate buffer for NDEF operations */
unsigned char NdefBuffer[RW_MAX_NDEF_FILE_SIZE];
typedef void RW_NDEF_Fct_t (unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size);
unsigned char *pRW_NdefMessage;
unsigned short RW_NdefMessage_size;
RW_NDEF_Callback_t *pRW_NDEF_PullCb;
RW_NDEF_Callback_t *pRW_NDEF_PushCb;
static RW_NDEF_Fct_t *pReadFct = NULL;
static RW_NDEF_Fct_t *pWriteFct = NULL;
bool RW_NDEF_SetMessage(unsigned char *pMessage, unsigned short Message_size, void *pCb)
{
if (Message_size <= RW_MAX_NDEF_FILE_SIZE)
{
pRW_NdefMessage = pMessage;
RW_NdefMessage_size = Message_size;
pRW_NDEF_PushCb = (RW_NDEF_Callback_t*) pCb;
return true;
}
else
{
RW_NdefMessage_size = 0;
pRW_NDEF_PushCb = NULL;
return false;
}
}
void RW_NDEF_RegisterPullCallback(void *pCb)
{
pRW_NDEF_PullCb = (RW_NDEF_Callback_t *) pCb;
}
void RW_NDEF_Reset(unsigned char type)
{
pReadFct = NULL;
pWriteFct = NULL;
switch (type)
{
case RW_NDEF_TYPE_T1T:
RW_NDEF_T1T_Reset();
pReadFct = RW_NDEF_T1T_Read_Next;
break;
case RW_NDEF_TYPE_T2T:
RW_NDEF_T2T_Reset();
pReadFct = RW_NDEF_T2T_Read_Next;
pWriteFct = RW_NDEF_T2T_Write_Next;
break;
case RW_NDEF_TYPE_T3T:
RW_NDEF_T3T_Reset();
pReadFct = RW_NDEF_T3T_Read_Next;
break;
case RW_NDEF_TYPE_T4T:
RW_NDEF_T4T_Reset();
pReadFct = RW_NDEF_T4T_Read_Next;
pWriteFct = RW_NDEF_T4T_Write_Next;
break;
default:
break;
}
}
void RW_NDEF_Read_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size)
{
if (pReadFct != NULL) pReadFct(pCmd, Cmd_size, Rsp, pRsp_size);
}
void RW_NDEF_Write_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *Rsp, unsigned short *pRsp_size)
{
if (pWriteFct != NULL) pWriteFct(pCmd, Cmd_size, Rsp, pRsp_size);
}
#endif
#endif
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#ifdef RW_SUPPORT
#ifndef NO_NDEF_SUPPORT
#include <TML/inc/tool.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF.h>
#define T1T_MAGIC_NUMBER 0xE1
#define T1T_NDEF_TLV 0x03
const unsigned char T1T_RID[] = {0x78,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char T1T_RALL[] = {0x00,0x00,0x00};
const unsigned char T1T_READ8[] = {0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
typedef enum
{
Initial,
Getting_ID,
Reading_CardContent,
Reading_NDEF
} RW_NDEF_T1T_state_t;
typedef struct
{
unsigned char HR0;
unsigned char HR1;
unsigned char UID[4];
unsigned char BlkNb;
unsigned short MessagePtr;
unsigned short MessageSize;
unsigned char *pMessage;
} RW_NDEF_T1T_Ndef_t;
static RW_NDEF_T1T_state_t eRW_NDEF_T1T_State = Initial;
static RW_NDEF_T1T_Ndef_t RW_NDEF_T1T_Ndef;
void RW_NDEF_T1T_Reset(void)
{
eRW_NDEF_T1T_State = Initial;
RW_NDEF_T1T_Ndef.pMessage = NdefBuffer;
}
void RW_NDEF_T1T_Read_Next(unsigned char *pRsp, unsigned short Rsp_size, unsigned char *pCmd, unsigned short *pCmd_size)
{
/* By default no further command to be sent */
*pCmd_size = 0;
switch(eRW_NDEF_T1T_State)
{
case Initial:
/* Send T1T_RID */
memcpy (pCmd, T1T_RID, sizeof(T1T_RID));
*pCmd_size = 7;
eRW_NDEF_T1T_State = Getting_ID;
break;
case Getting_ID:
/* Is CC Read and Is Ndef ?*/
if ((Rsp_size == 7) && (pRsp[Rsp_size-1] == 0x00))
{
/* Fill File structure */
RW_NDEF_T1T_Ndef.HR0 = pRsp[0];
RW_NDEF_T1T_Ndef.HR1 = pRsp[1];
memcpy (RW_NDEF_T1T_Ndef.UID, &pRsp[2], sizeof(RW_NDEF_T1T_Ndef.UID));
/* Read full card content */
memcpy (pCmd, T1T_RALL, sizeof(T1T_RALL));
memcpy (&pCmd[3], RW_NDEF_T1T_Ndef.UID, sizeof(RW_NDEF_T1T_Ndef.UID));
*pCmd_size = sizeof(T1T_RALL) + sizeof(RW_NDEF_T1T_Ndef.UID);
eRW_NDEF_T1T_State = Reading_CardContent;
}
break;
case Reading_CardContent:
/* Is Read success ?*/
if ((Rsp_size == 123) && (pRsp[Rsp_size-1] == 0x00))
{
/* Check CC */
if (pRsp[10] == T1T_MAGIC_NUMBER)
{
unsigned char Tmp = 14;
unsigned char data_size;
/* If not NDEF Type skip TLV */
while (pRsp[Tmp] != T1T_NDEF_TLV)
{
Tmp += 2 + pRsp[Tmp+1];
if (Tmp > Rsp_size) return;
}
RW_NDEF_T1T_Ndef.MessageSize = pRsp[Tmp+1];
data_size = (Rsp_size - 1) - 16 - Tmp - 2;
/* If provisioned buffer is not large enough, notify the application and stop reading */
if (RW_NDEF_T1T_Ndef.MessageSize > RW_MAX_NDEF_FILE_SIZE)
{
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(NULL, 0);
break;
}
/* Is NDEF read already completed ? */
if(RW_NDEF_T1T_Ndef.MessageSize <= data_size)
{
memcpy(RW_NDEF_T1T_Ndef.pMessage, &pRsp[Tmp+2], RW_NDEF_T1T_Ndef.MessageSize);
/* Notify application of the NDEF reception */
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(RW_NDEF_T1T_Ndef.pMessage, RW_NDEF_T1T_Ndef.MessageSize);
}
else
{
RW_NDEF_T1T_Ndef.MessagePtr = data_size;
memcpy (RW_NDEF_T1T_Ndef.pMessage, &pRsp[Tmp+2], RW_NDEF_T1T_Ndef.MessagePtr);
RW_NDEF_T1T_Ndef.BlkNb = 0x10;
/* Read NDEF content */
memcpy (pCmd, T1T_READ8, sizeof(T1T_READ8));
pCmd[1] = RW_NDEF_T1T_Ndef.BlkNb;
memcpy (&pCmd[10], RW_NDEF_T1T_Ndef.UID, sizeof(RW_NDEF_T1T_Ndef.UID));
*pCmd_size = sizeof(T1T_READ8) + sizeof(RW_NDEF_T1T_Ndef.UID);
eRW_NDEF_T1T_State = Reading_NDEF;
}
}
}
break;
case Reading_NDEF:
/* Is Read success ?*/
if ((Rsp_size == 10) && (pRsp[Rsp_size-1] == 0x00))
{
/* Is NDEF read already completed ? */
if ((RW_NDEF_T1T_Ndef.MessageSize - RW_NDEF_T1T_Ndef.MessagePtr) < 8)
{
memcpy (&RW_NDEF_T1T_Ndef.pMessage[RW_NDEF_T1T_Ndef.MessagePtr], &pRsp[1], RW_NDEF_T1T_Ndef.MessageSize - RW_NDEF_T1T_Ndef.MessagePtr);
/* Notify application of the NDEF reception */
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(RW_NDEF_T1T_Ndef.pMessage, RW_NDEF_T1T_Ndef.MessageSize);
}
else
{
memcpy (&RW_NDEF_T1T_Ndef.pMessage[RW_NDEF_T1T_Ndef.MessagePtr], &pRsp[1], 8);
RW_NDEF_T1T_Ndef.MessagePtr += 8;
RW_NDEF_T1T_Ndef.BlkNb++;
/* Read NDEF content */
memcpy (pCmd, T1T_READ8, sizeof(T1T_READ8));
pCmd[1] = RW_NDEF_T1T_Ndef.BlkNb;
memcpy (&pCmd[10], RW_NDEF_T1T_Ndef.UID, sizeof(RW_NDEF_T1T_Ndef.UID));
*pCmd_size = sizeof(T1T_READ8) + sizeof(RW_NDEF_T1T_Ndef.UID);
}
}
break;
default:
break;
}
}
#endif
#endif
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#ifdef RW_SUPPORT
#ifndef NO_NDEF_SUPPORT
#include <TML/inc/tool.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF.h>
/* TODO: No support for tag larger than 1024 bytes (requiring SECTOR_SELECT command use) */
#define T2T_MAGIC_NUMBER 0xE1
#define T2T_NDEF_TLV 0x03
typedef enum
{
Initial,
Reading_CC,
Reading_Data,
Reading_NDEF,
Writing_Data
} RW_NDEF_T2T_state_t;
typedef struct
{
unsigned char BlkNb;
unsigned short MessagePtr;
unsigned short MessageSize;
unsigned char *pMessage;
} RW_NDEF_T2T_Ndef_t;
static RW_NDEF_T2T_state_t eRW_NDEF_T2T_State = Initial;
static RW_NDEF_T2T_Ndef_t RW_NDEF_T2T_Ndef;
void RW_NDEF_T2T_Reset(void)
{
eRW_NDEF_T2T_State = Initial;
RW_NDEF_T2T_Ndef.pMessage = NdefBuffer;
}
void RW_NDEF_T2T_Read_Next(unsigned char *pRsp, unsigned short Rsp_size, unsigned char *pCmd, unsigned short *pCmd_size)
{
/* By default no further command to be sent */
*pCmd_size = 0;
switch(eRW_NDEF_T2T_State)
{
case Initial:
/* Read CC */
pCmd[0] = 0x30;
pCmd[1] = 0x03;
*pCmd_size = 2;
eRW_NDEF_T2T_State = Reading_CC;
break;
case Reading_CC:
/* Is CC Read and Is Ndef ?*/
if ((Rsp_size == 17) && (pRsp[Rsp_size-1] == 0x00) && (pRsp[0] == T2T_MAGIC_NUMBER))
{
/* Read First data */
pCmd[0] = 0x30;
pCmd[1] = 0x04;
*pCmd_size = 2;
eRW_NDEF_T2T_State = Reading_Data;
}
break;
case Reading_Data:
/* Is Read success ?*/
if ((Rsp_size == 17) && (pRsp[Rsp_size-1] == 0x00))
{
unsigned char Tmp = 0;
/* If not NDEF Type skip TLV */
while (pRsp[Tmp] != T2T_NDEF_TLV)
{
Tmp += 2 + pRsp[Tmp+1];
if (Tmp > Rsp_size) return;
}
if(pRsp[Tmp+1] == 0xFF)
{
RW_NDEF_T2T_Ndef.MessageSize = (pRsp[Tmp+2] << 8) + pRsp[Tmp+3];
Tmp += 2;
}
else RW_NDEF_T2T_Ndef.MessageSize = pRsp[Tmp+1];
/* If provisioned buffer is not large enough, notify the application and stop reading */
if (RW_NDEF_T2T_Ndef.MessageSize > RW_MAX_NDEF_FILE_SIZE)
{
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(NULL, 0);
break;
}
/* Is NDEF read already completed ? */
if (RW_NDEF_T2T_Ndef.MessageSize <= ((Rsp_size-1) - Tmp - 2))
{
memcpy (RW_NDEF_T2T_Ndef.pMessage, &pRsp[Tmp+2], RW_NDEF_T2T_Ndef.MessageSize);
/* Notify application of the NDEF reception */
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(RW_NDEF_T2T_Ndef.pMessage, RW_NDEF_T2T_Ndef.MessageSize);
}
else
{
RW_NDEF_T2T_Ndef.MessagePtr = (Rsp_size-1) - Tmp - 2;
memcpy (RW_NDEF_T2T_Ndef.pMessage, &pRsp[Tmp+2], RW_NDEF_T2T_Ndef.MessagePtr);
RW_NDEF_T2T_Ndef.BlkNb = 8;
/* Read NDEF content */
pCmd[0] = 0x30;
pCmd[1] = RW_NDEF_T2T_Ndef.BlkNb;
*pCmd_size = 2;
eRW_NDEF_T2T_State = Reading_NDEF;
}
}
break;
case Reading_NDEF:
/* Is Read success ?*/
if ((Rsp_size == 17) && (pRsp[Rsp_size-1] == 0x00))
{
/* Is NDEF read already completed ? */
if ((RW_NDEF_T2T_Ndef.MessageSize - RW_NDEF_T2T_Ndef.MessagePtr) < 16)
{
memcpy (&RW_NDEF_T2T_Ndef.pMessage[RW_NDEF_T2T_Ndef.MessagePtr], pRsp, RW_NDEF_T2T_Ndef.MessageSize - RW_NDEF_T2T_Ndef.MessagePtr);
/* Notify application of the NDEF reception */
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(RW_NDEF_T2T_Ndef.pMessage, RW_NDEF_T2T_Ndef.MessageSize);
}
else
{
memcpy (&RW_NDEF_T2T_Ndef.pMessage[RW_NDEF_T2T_Ndef.MessagePtr], pRsp, 16);
RW_NDEF_T2T_Ndef.MessagePtr += 16;
RW_NDEF_T2T_Ndef.BlkNb += 4;
/* Read NDEF content */
pCmd[0] = 0x30;
pCmd[1] = RW_NDEF_T2T_Ndef.BlkNb;
*pCmd_size = 2;
}
}
break;
default:
break;
}
}
void RW_NDEF_T2T_Write_Next(unsigned char *pRsp, unsigned short Rsp_size, unsigned char *pCmd, unsigned short *pCmd_size)
{
/* By default no further command to be sent */
*pCmd_size = 0;
switch(eRW_NDEF_T2T_State)
{
case Initial:
/* Read CC */
pCmd[0] = 0x30;
pCmd[1] = 0x03;
*pCmd_size = 2;
eRW_NDEF_T2T_State = Reading_CC;
break;
case Reading_CC:
/* Is CC Read, Is Ndef and is R/W ?*/
if ((Rsp_size == 17) && (pRsp[Rsp_size-1] == 0x00) && (pRsp[0] == T2T_MAGIC_NUMBER) && (pRsp[3] == 0x00))
{
/* Is size enough ? */
if (pRsp[2]*8 >= RW_NdefMessage_size)
{
/* Write First data */
pCmd[0] = 0xA2;
pCmd[1] = 0x04;
pCmd[2] = 0x03;
if (RW_NdefMessage_size > 0xFF)
{
pCmd[3] = 0xFF;
pCmd[4] = (RW_NdefMessage_size & 0xFF00) >> 8;
pCmd[5] = RW_NdefMessage_size & 0xFF;
RW_NDEF_T2T_Ndef.MessagePtr = 0;
}
else
{
pCmd[3] = (unsigned char) RW_NdefMessage_size;
memcpy(&pCmd[4], pRW_NdefMessage, 2);
RW_NDEF_T2T_Ndef.MessagePtr = 2;
}
RW_NDEF_T2T_Ndef.BlkNb = 5;
*pCmd_size = 6;
eRW_NDEF_T2T_State = Writing_Data;
}
}
break;
case Writing_Data:
/* Is Write success ?*/
if ((Rsp_size == 2) && (pRsp[Rsp_size-1] == 0x00))
{
/* Is NDEF write already completed ? */
if (RW_NdefMessage_size <= RW_NDEF_T2T_Ndef.MessagePtr)
{
/* Notify application of the NDEF reception */
if(pRW_NDEF_PushCb != NULL) pRW_NDEF_PushCb(pRW_NdefMessage, RW_NdefMessage_size);
}
else
{
/* Write NDEF content */
pCmd[0] = 0xA2;
pCmd[1] = RW_NDEF_T2T_Ndef.BlkNb;
memcpy(&pCmd[2], pRW_NdefMessage+RW_NDEF_T2T_Ndef.MessagePtr, 4);
*pCmd_size = 6;
RW_NDEF_T2T_Ndef.MessagePtr+=4;
RW_NDEF_T2T_Ndef.BlkNb++;
}
}
break;
default:
break;
}
}
#endif
#endif
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#ifdef RW_SUPPORT
#ifndef NO_NDEF_SUPPORT
#include <TML/inc/tool.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF.h>
#define T3T_MAGIC_NUMBER 0xE1
#define T3T_NDEF_TLV 0x03
unsigned char T3T_Check[] = {0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0B,0x00,0x1,0x80,0x00};
typedef enum
{
Initial,
Getting_AttributeInfo,
Reading_CardContent
} RW_NDEF_T3T_state_t;
typedef struct
{
unsigned char IDm[8];
unsigned char BlkNb;
unsigned short Ptr;
unsigned short Size;
unsigned char *p;
} RW_NDEF_T3T_Ndef_t;
static RW_NDEF_T3T_state_t eRW_NDEF_T3T_State = Initial;
static RW_NDEF_T3T_Ndef_t RW_NDEF_T3T_Ndef;
void RW_NDEF_T3T_Reset(void)
{
eRW_NDEF_T3T_State = Initial;
RW_NDEF_T3T_Ndef.p = NdefBuffer;
}
void RW_NDEF_T3T_SetIDm(unsigned char *pIDm)
{
memcpy(RW_NDEF_T3T_Ndef.IDm, pIDm, sizeof(RW_NDEF_T3T_Ndef.IDm));
memcpy(&T3T_Check[2], pIDm, sizeof(RW_NDEF_T3T_Ndef.IDm));
}
void RW_NDEF_T3T_Read_Next(unsigned char *pRsp, unsigned short Rsp_size, unsigned char *pCmd, unsigned short *pCmd_size)
{
/* By default no further command to be sent */
*pCmd_size = 0;
switch(eRW_NDEF_T3T_State)
{
case Initial:
/* Get AttributeInfo */
memcpy (pCmd, T3T_Check, sizeof(T3T_Check));
*pCmd_size = sizeof(T3T_Check);
eRW_NDEF_T3T_State = Getting_AttributeInfo;
break;
case Getting_AttributeInfo:
/* Is Check success ?*/
if ((pRsp[Rsp_size-1] == 0x00) && (pRsp[1] == 0x07) && (pRsp[10] == 0x00) && (pRsp[11] == 0x00))
{
/* Fill File structure */
RW_NDEF_T3T_Ndef.Size = (pRsp[24] << 16) + (pRsp[25] << 16) + pRsp[26];
/* If provisioned buffer is not large enough, notify the application and stop reading */
if (RW_NDEF_T3T_Ndef.Size > RW_MAX_NDEF_FILE_SIZE)
{
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(NULL, 0);
break;
}
RW_NDEF_T3T_Ndef.Ptr = 0;
RW_NDEF_T3T_Ndef.BlkNb = 1;
/* Read first NDEF block */
memcpy (pCmd, T3T_Check, sizeof(T3T_Check));
pCmd[15] = 0x01;
*pCmd_size = sizeof(T3T_Check);
eRW_NDEF_T3T_State = Reading_CardContent;
}
break;
case Reading_CardContent:
/* Is Check success ?*/
if ((pRsp[Rsp_size-1] == 0x00) && (pRsp[1] == 0x07) && (pRsp[10] == 0x00) && (pRsp[11] == 0x00))
{
/* Is NDEF message read completed ?*/
if ((RW_NDEF_T3T_Ndef.Size - RW_NDEF_T3T_Ndef.Ptr) <= 16)
{
memcpy(&RW_NDEF_T3T_Ndef.p[RW_NDEF_T3T_Ndef.Ptr], &pRsp[13], (RW_NDEF_T3T_Ndef.Size - RW_NDEF_T3T_Ndef.Ptr));
/* Notify application of the NDEF reception */
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(RW_NDEF_T3T_Ndef.p, RW_NDEF_T3T_Ndef.Size);
}
else
{
memcpy(&RW_NDEF_T3T_Ndef.p[RW_NDEF_T3T_Ndef.Ptr], &pRsp[13], 16);
RW_NDEF_T3T_Ndef.Ptr += 16;
RW_NDEF_T3T_Ndef.BlkNb++;
/* Read next NDEF block */
memcpy (pCmd, T3T_Check, sizeof(T3T_Check));
pCmd[15] = RW_NDEF_T3T_Ndef.BlkNb;
*pCmd_size = sizeof(T3T_Check);
}
}
break;
default:
break;
}
}
#endif
#endif
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#ifdef RW_SUPPORT
#ifndef NO_NDEF_SUPPORT
#include <TML/inc/tool.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF.h>
const unsigned char RW_NDEF_T4T_APP_Select20[] = {0x00,0xA4,0x04,0x00,0x07,0xD2,0x76,0x00,0x00,0x85,0x01,0x01,0x00};
const unsigned char RW_NDEF_T4T_APP_Select10[] = {0x00,0xA4,0x04,0x00,0x07,0xD2,0x76,0x00,0x00,0x85,0x01,0x00};
const unsigned char RW_NDEF_T4T_CC_Select[] = {0x00,0xA4,0x00,0x0C,0x02,0xE1,0x03};
const unsigned char RW_NDEF_T4T_NDEF_Select[] = {0x00,0xA4,0x00,0x0C,0x02,0xE1,0x04};
const unsigned char RW_NDEF_T4T_Read[] = {0x00,0xB0,0x00,0x00,0x0F};
const unsigned char RW_NDEF_T4T_Write[] = {0x00,0xD6,0x00,0x00,0x00};
const unsigned char RW_NDEF_T4T_OK[] = {0x90, 0x00};
#define WRITE_SZ 54
typedef enum
{
Initial,
Selecting_NDEF_Application20,
Selecting_NDEF_Application10,
Selecting_CC,
Reading_CC,
Selecting_NDEF,
Reading_NDEF_Size,
Reading_NDEF,
Writing_NDEF,
Writing_NDEFsize,
Write_NDEFcomplete
} RW_NDEF_T4T_state_t;
typedef struct
{
unsigned char MappingVersion;
unsigned short MLe;
unsigned short MLc;
unsigned char FileID[2];
unsigned short MaxNdefFileSize;
unsigned char RdAccess;
unsigned char WrAccess;
unsigned short MessagePtr;
unsigned short MessageSize;
unsigned char *pMessage;
} RW_NDEF_T4T_Ndef_t;
static RW_NDEF_T4T_state_t eRW_NDEF_T4T_State = Initial;
static RW_NDEF_T4T_Ndef_t RW_NDEF_T4T_Ndef;
void RW_NDEF_T4T_Reset(void)
{
eRW_NDEF_T4T_State = Initial;
RW_NDEF_T4T_Ndef.pMessage = NdefBuffer;
}
void RW_NDEF_T4T_Read_Next(unsigned char *pRsp, unsigned short Rsp_size, unsigned char *pCmd, unsigned short *pCmd_size)
{
/* By default no further command to be sent */
*pCmd_size = 0;
switch(eRW_NDEF_T4T_State)
{
case Initial:
/* Select NDEF Application in version 2.0 */
memcpy(pCmd, RW_NDEF_T4T_APP_Select20, sizeof(RW_NDEF_T4T_APP_Select20));
*pCmd_size = sizeof(RW_NDEF_T4T_APP_Select20);
eRW_NDEF_T4T_State = Selecting_NDEF_Application20;
break;
case Selecting_NDEF_Application20:
/* Is NDEF Application Selected ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Select CC */
memcpy(pCmd, RW_NDEF_T4T_CC_Select, sizeof(RW_NDEF_T4T_CC_Select));
*pCmd_size = sizeof(RW_NDEF_T4T_CC_Select);
eRW_NDEF_T4T_State = Selecting_CC;
}
else
{
/* Select NDEF Application in version 1.0 */
memcpy(pCmd, RW_NDEF_T4T_APP_Select10, sizeof(RW_NDEF_T4T_APP_Select10));
*pCmd_size = sizeof(RW_NDEF_T4T_APP_Select10);
eRW_NDEF_T4T_State = Selecting_NDEF_Application10;
}
break;
case Selecting_NDEF_Application10:
/* Is NDEF Application Selected ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Select CC */
memcpy(pCmd, RW_NDEF_T4T_CC_Select, sizeof(RW_NDEF_T4T_CC_Select));
pCmd[3] = 0x00;
*pCmd_size = sizeof(RW_NDEF_T4T_CC_Select);
eRW_NDEF_T4T_State = Selecting_CC;
}
break;
case Selecting_CC:
/* Is CC Selected ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Read CC */
memcpy(pCmd, RW_NDEF_T4T_Read, sizeof(RW_NDEF_T4T_Read));
*pCmd_size = sizeof(RW_NDEF_T4T_Read);
eRW_NDEF_T4T_State = Reading_CC;
}
break;
case Reading_CC:
/* Is CC Read ?*/
if ((!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK))) && (Rsp_size == 15 + 2))
{
/* Fill CC structure */
RW_NDEF_T4T_Ndef.MappingVersion = pRsp[2];
RW_NDEF_T4T_Ndef.MLe = (pRsp[3] << 8) + pRsp[4];
RW_NDEF_T4T_Ndef.MLc = (pRsp[5] << 8) + pRsp[6];
RW_NDEF_T4T_Ndef.FileID[0] = pRsp[9];
RW_NDEF_T4T_Ndef.FileID[1] = pRsp[10];
RW_NDEF_T4T_Ndef.MaxNdefFileSize = (pRsp[11] << 8) + pRsp[12];
RW_NDEF_T4T_Ndef.RdAccess = pRsp[13];
RW_NDEF_T4T_Ndef.WrAccess = pRsp[14];
/* Select NDEF */
memcpy(pCmd, RW_NDEF_T4T_NDEF_Select, sizeof(RW_NDEF_T4T_NDEF_Select));
if (RW_NDEF_T4T_Ndef.MappingVersion == 0x10) pCmd[3] = 0x00;
pCmd[5] = RW_NDEF_T4T_Ndef.FileID[0];
pCmd[6] = RW_NDEF_T4T_Ndef.FileID[1];
*pCmd_size = sizeof(RW_NDEF_T4T_NDEF_Select);
eRW_NDEF_T4T_State = Selecting_NDEF;
}
break;
case Selecting_NDEF:
/* Is NDEF Selected ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Get NDEF file size */
memcpy(pCmd, RW_NDEF_T4T_Read, sizeof(RW_NDEF_T4T_Read));
*pCmd_size = sizeof(RW_NDEF_T4T_Read);
pCmd[4] = 2;
eRW_NDEF_T4T_State = Reading_NDEF_Size;
}
break;
case Reading_NDEF_Size:
/* Is Read Success ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
RW_NDEF_T4T_Ndef.MessageSize = (pRsp[0] << 8) + pRsp[1];
/* If provisioned buffer is not large enough, notify the application and stop reading */
if (RW_NDEF_T4T_Ndef.MessageSize > RW_MAX_NDEF_FILE_SIZE)
{
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(NULL, 0);
break;
}
RW_NDEF_T4T_Ndef.MessagePtr = 0;
/* Read NDEF data */
memcpy(pCmd, RW_NDEF_T4T_Read, sizeof(RW_NDEF_T4T_Read));
pCmd[3] = 2;
pCmd[4] = (RW_NDEF_T4T_Ndef.MessageSize > RW_NDEF_T4T_Ndef.MLe-1) ? RW_NDEF_T4T_Ndef.MLe-1 : (unsigned char) RW_NDEF_T4T_Ndef.MessageSize;
*pCmd_size = sizeof(RW_NDEF_T4T_Read);
eRW_NDEF_T4T_State = Reading_NDEF;
}
break;
case Reading_NDEF:
/* Is Read Success ?*/
//if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
memcpy(&RW_NDEF_T4T_Ndef.pMessage[RW_NDEF_T4T_Ndef.MessagePtr], pRsp, Rsp_size - 2);
RW_NDEF_T4T_Ndef.MessagePtr += Rsp_size - 2;
/* Is NDEF message read completed ?*/
if (RW_NDEF_T4T_Ndef.MessagePtr == RW_NDEF_T4T_Ndef.MessageSize)
{
/* Notify application of the NDEF reception */
if(pRW_NDEF_PullCb != NULL) pRW_NDEF_PullCb(RW_NDEF_T4T_Ndef.pMessage, RW_NDEF_T4T_Ndef.MessageSize);
}
else
{
/* Read NDEF data */
memcpy(pCmd, RW_NDEF_T4T_Read, sizeof(RW_NDEF_T4T_Read));
pCmd[3] = RW_NDEF_T4T_Ndef.MessagePtr + 2;
pCmd[4] = ((RW_NDEF_T4T_Ndef.MessageSize - RW_NDEF_T4T_Ndef.MessagePtr) > RW_NDEF_T4T_Ndef.MLe-1) ? RW_NDEF_T4T_Ndef.MLe-1 : (unsigned char) (RW_NDEF_T4T_Ndef.MessageSize - RW_NDEF_T4T_Ndef.MessagePtr);
*pCmd_size = sizeof(RW_NDEF_T4T_Read);
}
}
break;
default:
break;
}
}
void RW_NDEF_T4T_Write_Next(unsigned char *pRsp, unsigned short Rsp_size, unsigned char *pCmd, unsigned short *pCmd_size)
{
/* By default no further command to be sent */
*pCmd_size = 0;
switch(eRW_NDEF_T4T_State)
{
case Initial:
/* Select NDEF Application in version 2.0 */
memcpy(pCmd, RW_NDEF_T4T_APP_Select20, sizeof(RW_NDEF_T4T_APP_Select20));
*pCmd_size = sizeof(RW_NDEF_T4T_APP_Select20);
eRW_NDEF_T4T_State = Selecting_NDEF_Application20;
break;
case Selecting_NDEF_Application20:
/* Is NDEF Application Selected ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Select CC */
memcpy(pCmd, RW_NDEF_T4T_CC_Select, sizeof(RW_NDEF_T4T_CC_Select));
*pCmd_size = sizeof(RW_NDEF_T4T_CC_Select);
eRW_NDEF_T4T_State = Selecting_CC;
}
else
{
/* Select NDEF Application in version 1.0 */
memcpy(pCmd, RW_NDEF_T4T_APP_Select10, sizeof(RW_NDEF_T4T_APP_Select10));
*pCmd_size = sizeof(RW_NDEF_T4T_APP_Select10);
eRW_NDEF_T4T_State = Selecting_NDEF_Application10;
}
break;
case Selecting_NDEF_Application10:
/* Is NDEF Application Selected ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Select CC */
memcpy(pCmd, RW_NDEF_T4T_CC_Select, sizeof(RW_NDEF_T4T_CC_Select));
pCmd[3] = 0x00;
*pCmd_size = sizeof(RW_NDEF_T4T_CC_Select);
eRW_NDEF_T4T_State = Selecting_CC;
}
break;
case Selecting_CC:
/* Is CC Selected ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Read CC */
memcpy(pCmd, RW_NDEF_T4T_Read, sizeof(RW_NDEF_T4T_Read));
*pCmd_size = sizeof(RW_NDEF_T4T_Read);
eRW_NDEF_T4T_State = Reading_CC;
}
break;
case Reading_CC:
/* Is CC Read ?*/
if ((!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK))) && (Rsp_size == 15 + 2))
{
/* Fill CC structure */
RW_NDEF_T4T_Ndef.MappingVersion = pRsp[2];
RW_NDEF_T4T_Ndef.MLe = (pRsp[3] << 8) + pRsp[4];
RW_NDEF_T4T_Ndef.MLc = (pRsp[5] << 8) + pRsp[6];
RW_NDEF_T4T_Ndef.FileID[0] = pRsp[9];
RW_NDEF_T4T_Ndef.FileID[1] = pRsp[10];
RW_NDEF_T4T_Ndef.MaxNdefFileSize = (pRsp[11] << 8) + pRsp[12];
RW_NDEF_T4T_Ndef.RdAccess = pRsp[13];
RW_NDEF_T4T_Ndef.WrAccess = pRsp[14];
/* Select NDEF */
memcpy(pCmd, RW_NDEF_T4T_NDEF_Select, sizeof(RW_NDEF_T4T_NDEF_Select));
if (RW_NDEF_T4T_Ndef.MappingVersion == 0x10) pCmd[3] = 0x00;
pCmd[5] = RW_NDEF_T4T_Ndef.FileID[0];
pCmd[6] = RW_NDEF_T4T_Ndef.FileID[1];
*pCmd_size = sizeof(RW_NDEF_T4T_NDEF_Select);
eRW_NDEF_T4T_State = Selecting_NDEF;
}
break;
case Selecting_NDEF:
/* Is NDEF Selected ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Clearing NDEF message size*/
memcpy(pCmd, RW_NDEF_T4T_Write, sizeof(RW_NDEF_T4T_Write));
pCmd[4] = 2;
pCmd[5] = 0;
pCmd[6] = 0;
*pCmd_size = sizeof(RW_NDEF_T4T_Write) + 2;
RW_NDEF_T4T_Ndef.MessagePtr = 0;
eRW_NDEF_T4T_State = Writing_NDEF;
}
break;
case Writing_NDEF:
/* Is Write Success ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Writing NDEF message */
memcpy(pCmd, RW_NDEF_T4T_Write, sizeof(RW_NDEF_T4T_Write));
pCmd[2] = (RW_NDEF_T4T_Ndef.MessagePtr + 2) >> 8;
pCmd[3] = (RW_NDEF_T4T_Ndef.MessagePtr + 2) & 0xFF;
if((RW_NdefMessage_size - RW_NDEF_T4T_Ndef.MessagePtr) < WRITE_SZ)
{
pCmd[4] = (RW_NdefMessage_size - RW_NDEF_T4T_Ndef.MessagePtr);
memcpy(&pCmd[5], pRW_NdefMessage + RW_NDEF_T4T_Ndef.MessagePtr, (RW_NdefMessage_size - RW_NDEF_T4T_Ndef.MessagePtr));
*pCmd_size = sizeof(RW_NDEF_T4T_Write) + (RW_NdefMessage_size - RW_NDEF_T4T_Ndef.MessagePtr);
eRW_NDEF_T4T_State = Writing_NDEFsize;
}
else
{
pCmd[4] = WRITE_SZ;
memcpy(&pCmd[5], pRW_NdefMessage + RW_NDEF_T4T_Ndef.MessagePtr, WRITE_SZ);
*pCmd_size = sizeof(RW_NDEF_T4T_Write) + WRITE_SZ;
RW_NDEF_T4T_Ndef.MessagePtr += WRITE_SZ;
eRW_NDEF_T4T_State = Writing_NDEF;
}
}
break;
case Writing_NDEFsize:
/* Is Write Success ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
memcpy(pCmd, RW_NDEF_T4T_Write, sizeof(RW_NDEF_T4T_Write));
pCmd[4] = 2;
pCmd[5] = RW_NdefMessage_size >> 8;
pCmd[6] = RW_NdefMessage_size & 0xFF;
*pCmd_size = sizeof(RW_NDEF_T4T_Write) + 2;
eRW_NDEF_T4T_State = Write_NDEFcomplete;
}
break;
case Write_NDEFcomplete:
/* Is Write Success ?*/
if (!memcmp(&pRsp[Rsp_size - 2], RW_NDEF_T4T_OK, sizeof(RW_NDEF_T4T_OK)))
{
/* Notify application of the NDEF reception */
if(pRW_NDEF_PushCb != NULL) pRW_NDEF_PushCb(pRW_NdefMessage, RW_NdefMessage_size);
}
break;
default:
break;
}
}
#endif
#endif
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#ifdef CARDEMU_SUPPORT
#ifndef NO_NDEF_SUPPORT
#include <TML/inc/tool.h>
#include <NfcLibrary/NdefLibrary/inc/T4T_NDEF_emu.h>
const unsigned char T4T_NDEF_EMU_APP_Select[] = {0x00,0xA4,0x04,0x00,0x07,0xD2,0x76,0x00,0x00,0x85,0x01,0x01};
const unsigned char T4T_NDEF_EMU_CC[] = {0x00, 0x0F, 0x20, 0x00, 0xFF, 0x00, 0xFF, 0x04, 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0xFF};
const unsigned char T4T_NDEF_EMU_CC_Select[] = {0x00,0xA4,0x00,0x0C,0x02,0xE1,0x03};
const unsigned char T4T_NDEF_EMU_NDEF_Select[] = {0x00,0xA4,0x00,0x0C,0x02,0xE1,0x04};
const unsigned char T4T_NDEF_EMU_Read[] = {0x00,0xB0};
const unsigned char T4T_NDEF_EMU_OK[] = {0x90, 0x00};
const unsigned char T4T_NDEF_EMU_NOK[] = {0x6A, 0x82};
unsigned char *pT4T_NdefMessage;
unsigned short T4T_NdefMessage_size = 0;
typedef enum
{
Ready,
NDEF_Application_Selected,
CC_Selected,
NDEF_Selected,
} T4T_NDEF_EMU_state_t;
typedef void T4T_NDEF_EMU_Callback_t (unsigned char*, unsigned short);
static T4T_NDEF_EMU_state_t eT4T_NDEF_EMU_State = Ready;
static T4T_NDEF_EMU_Callback_t *pT4T_NDEF_EMU_PushCb = NULL;
static void T4T_NDEF_EMU_FillRsp (unsigned char *pRsp, unsigned short offset, unsigned char length)
{
if (offset == 0)
{
pRsp[0] = (T4T_NdefMessage_size & 0xFF00) >> 8;
pRsp[1] = (T4T_NdefMessage_size & 0x00FF);
memcpy(&pRsp[2], &pT4T_NdefMessage[0], length-2);
}
else if (offset == 1)
{
pRsp[0] = (T4T_NdefMessage_size & 0x00FF);
memcpy(&pRsp[1], &pT4T_NdefMessage[0], length-1);
}
else
{
memcpy(pRsp, &pT4T_NdefMessage[offset-2], length);
}
/* Did we reached the end of NDEF message ?*/
if ((offset + length) >= (T4T_NdefMessage_size + 2))
{
/* Notify application of the NDEF send */
if(pT4T_NDEF_EMU_PushCb != NULL) pT4T_NDEF_EMU_PushCb(pT4T_NdefMessage, T4T_NdefMessage_size);
}
}
bool T4T_NDEF_EMU_SetMessage(unsigned char *pMessage, unsigned short Message_size, void *pCb)
{
pT4T_NdefMessage = pMessage;
T4T_NdefMessage_size = Message_size;
pT4T_NDEF_EMU_PushCb = (T4T_NDEF_EMU_Callback_t*) pCb;
return true;
}
void T4T_NDEF_EMU_Reset(void)
{
eT4T_NDEF_EMU_State = Ready;
}
void T4T_NDEF_EMU_Next(unsigned char *pCmd, unsigned short Cmd_size, unsigned char *pRsp, unsigned short *pRsp_size)
{
bool eStatus = false;
if (!memcmp(pCmd, T4T_NDEF_EMU_APP_Select, sizeof(T4T_NDEF_EMU_APP_Select)))
{
*pRsp_size = 0;
eStatus = true;
eT4T_NDEF_EMU_State = NDEF_Application_Selected;
}
else if (!memcmp(pCmd, T4T_NDEF_EMU_CC_Select, sizeof(T4T_NDEF_EMU_CC_Select)))
{
if(eT4T_NDEF_EMU_State == NDEF_Application_Selected)
{
*pRsp_size = 0;
eStatus = true;
eT4T_NDEF_EMU_State = CC_Selected;
}
}
else if (!memcmp(pCmd, T4T_NDEF_EMU_NDEF_Select, sizeof(T4T_NDEF_EMU_NDEF_Select)))
{
*pRsp_size = 0;
eStatus = true;
eT4T_NDEF_EMU_State = NDEF_Selected;
}
else if (!memcmp(pCmd, T4T_NDEF_EMU_Read, sizeof(T4T_NDEF_EMU_Read)))
{
if(eT4T_NDEF_EMU_State == CC_Selected)
{
memcpy(pRsp, T4T_NDEF_EMU_CC, sizeof(T4T_NDEF_EMU_CC));
*pRsp_size = sizeof(T4T_NDEF_EMU_CC);
eStatus = true;
}
else if (eT4T_NDEF_EMU_State == NDEF_Selected)
{
unsigned short offset = (pCmd[2] << 8) + pCmd[3];
unsigned char length = pCmd[4];
if(length <= (T4T_NdefMessage_size + offset + 2))
{
T4T_NDEF_EMU_FillRsp(pRsp, offset, length);
*pRsp_size = length;
eStatus = true;
}
}
}
if (eStatus == true)
{
memcpy(&pRsp[*pRsp_size], T4T_NDEF_EMU_OK, sizeof(T4T_NDEF_EMU_OK));
*pRsp_size += sizeof(T4T_NDEF_EMU_OK);
} else
{
memcpy(pRsp, T4T_NDEF_EMU_NOK, sizeof(T4T_NDEF_EMU_NOK));
*pRsp_size = sizeof(T4T_NDEF_EMU_NOK);
T4T_NDEF_EMU_Reset();
}
}
#endif
#endif
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#include <NfcLibrary/inc/Nfc.h>
#ifdef CARDEMU_SUPPORT
#include <NfcLibrary/NdefLibrary/inc/T4T_NDEF_emu.h>
#endif
#ifdef P2P_SUPPORT
#include <NfcLibrary/NdefLibrary/inc/P2P_NDEF.h>
#endif
#ifdef RW_SUPPORT
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF.h>
#include <NfcLibrary/NdefLibrary/inc/RW_NDEF_T3T.h>
#endif
#define NXPNCI_SUCCESS NFC_SUCCESS
#define NXPNCI_ERROR NFC_ERROR
#ifdef NCI_DEBUG
#include <stdio.h>
#define NCI_PRINT(...) {printf(__VA_ARGS__);}
unsigned short debug_loop;
#define NCI_PRINT_LOOP(x,y) {for(debug_loop=0; debug_loop<y; debug_loop++) printf("%.2x ", x[debug_loop]);}
#define NCI_PRINT_BUF(x,y,z) {char tmp[200]; int loop; sprintf(tmp, x); \
for(loop=0;loop<(z<30?z:30);loop++) sprintf(tmp+7+(loop*3), "%.2x ", y[loop]); \
if(loop==30) sprintf(tmp+7+(loop*3), "...\n"); \
else sprintf(tmp+7+(loop*3), "\n"); \
printf(tmp);}
#else
#define NCI_PRINT(...)
#define NCI_PRINT_LOOP(x,y)
#define NCI_PRINT_BUF(x,y,z)
#endif
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#include <TML/inc/tool.h>
#include <TML/inc/tml.h>
#include <NfcLibrary/NxpNci/inc/NxpNci.h>
#include <NfcLibrary/inc/Nfc_settings.h>
#define MAX_NCI_FRAME_SIZE 256
#define MAX(x,y) (x > y ? x : y)
static uint8_t gNfcController_generation = 0;
static uint8_t gNextTag_Protocol = PROT_UNDETERMINED;
static bool NxpNci_CheckDevPres(void)
{
uint8_t NCICoreReset[] = {0x20, 0x00, 0x01, 0x01};
uint8_t Answer[6];
uint16_t NbBytes = 0;
tml_Send(NCICoreReset, sizeof(NCICoreReset), &NbBytes);
NCI_PRINT_BUF("NCI >> ", NCICoreReset, NbBytes);
if (NbBytes != sizeof(NCICoreReset)) return NXPNCI_ERROR;
tml_Receive(Answer, sizeof(Answer), &NbBytes, TIMEOUT_100MS);
if ((NbBytes == 0) || (Answer[0] != 0x40) || (Answer[1] != 0x00)) return NXPNCI_ERROR;
NCI_PRINT_BUF("NCI << ", Answer, NbBytes);
return NXPNCI_SUCCESS;
}
static bool NxpNci_WaitForReception(uint8_t *pRBuff, uint16_t RBuffSize, uint16_t *pBytesread, uint16_t timeout)
{
tml_Receive(pRBuff, RBuffSize, pBytesread, timeout);
if (*pBytesread == 0) return NXPNCI_ERROR;
NCI_PRINT_BUF("NCI << ", pRBuff, *pBytesread);
return NXPNCI_SUCCESS;
}
static bool NxpNci_HostTransceive(uint8_t *pTBuff, uint16_t TbuffLen, uint8_t *pRBuff, uint16_t RBuffSize, uint16_t *pBytesread)
{
tml_Send(pTBuff, TbuffLen, pBytesread);
NCI_PRINT_BUF("NCI >> ", pTBuff, TbuffLen);
if (*pBytesread != TbuffLen) return NXPNCI_ERROR;
tml_Receive(pRBuff, RBuffSize, pBytesread, TIMEOUT_1S);
if (*pBytesread == 0) return NXPNCI_ERROR;
NCI_PRINT_BUF("NCI << ", pRBuff, *pBytesread);
return NXPNCI_SUCCESS;
}
static void NxpNci_FillInterfaceInfo(NxpNci_RfIntf_t* pRfIntf, uint8_t* pBuf)
{
uint8_t i;
switch(pRfIntf->ModeTech)
{
case (MODE_POLL | TECH_PASSIVE_NFCA):
memcpy(pRfIntf->Info.NFC_APP.SensRes, &pBuf[0], 2);
pRfIntf->Info.NFC_APP.NfcIdLen = pBuf[2];
memcpy(pRfIntf->Info.NFC_APP.NfcId, &pBuf[3], pRfIntf->Info.NFC_APP.NfcIdLen);
pRfIntf->Info.NFC_APP.SelResLen = pBuf[3+pBuf[2]];
if(pRfIntf->Info.NFC_APP.SelResLen == 1) pRfIntf->Info.NFC_APP.SelRes[0] = pBuf[3+pBuf[2]+1];
break;
case (MODE_POLL | TECH_PASSIVE_NFCB):
pRfIntf->Info.NFC_BPP.SensResLen = pBuf[0];
memcpy(pRfIntf->Info.NFC_BPP.SensRes, &pBuf[1], pRfIntf->Info.NFC_BPP.SensResLen);
break;
case (MODE_POLL | TECH_PASSIVE_NFCF):
pRfIntf->Info.NFC_FPP.BitRate = pBuf[0];
pRfIntf->Info.NFC_FPP.SensResLen = pBuf[1];
memcpy(pRfIntf->Info.NFC_FPP.SensRes, &pBuf[2], pRfIntf->Info.NFC_FPP.SensResLen);
break;
case (MODE_POLL | TECH_PASSIVE_15693):
pRfIntf->Info.NFC_VPP.AFI = pBuf[0];
pRfIntf->Info.NFC_VPP.DSFID = pBuf[1];
for(i=0; i<8; i++) pRfIntf->Info.NFC_VPP.ID[7-i] = pBuf[2+i];
break;
default:
break;
}
}
#ifdef CARDEMU_SUPPORT
void NxpNci_ProcessCardMode(NxpNci_RfIntf_t RfIntf)
{
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
/* Reset Card emulation state */
T4T_NDEF_EMU_Reset();
while(NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_2S) == NXPNCI_SUCCESS)
{
/* is RF_DEACTIVATE_NTF ? */
if((Answer[0] == 0x61) && (Answer[1] == 0x06))
{
/* Come back to discovery state */
break;
}
/* is DATA_PACKET ? */
else if((Answer[0] == 0x00) && (Answer[1] == 0x00))
{
/* DATA_PACKET */
uint8_t Cmd[MAX_NCI_FRAME_SIZE];
uint16_t CmdSize;
T4T_NDEF_EMU_Next(&Answer[3], Answer[2], &Cmd[3], (unsigned short *) &CmdSize);
Cmd[0] = 0x00;
Cmd[1] = (CmdSize & 0xFF00) >> 8;
Cmd[2] = CmdSize & 0x00FF;
NxpNci_HostTransceive(Cmd, CmdSize+3, Answer, sizeof(Answer), &AnswerSize);
}
}
}
bool NxpNci_CardModeReceive (unsigned char *pData, unsigned char *pDataSize)
{
bool status = NXPNCI_ERROR;
uint8_t Ans[MAX_NCI_FRAME_SIZE];
uint16_t AnsSize;
NxpNci_WaitForReception(Ans, sizeof(Ans), &AnsSize, TIMEOUT_2S);
/* Is data packet ? */
if ((Ans[0] == 0x00) && (Ans[1] == 0x00))
{
*pDataSize = Ans[2];
memcpy(pData, &Ans[3], *pDataSize);
status = NXPNCI_SUCCESS;
}
return status;
}
bool NxpNci_CardModeSend (unsigned char *pData, unsigned char DataSize)
{
bool status;
uint8_t Cmd[MAX_NCI_FRAME_SIZE];
uint8_t Ans[MAX_NCI_FRAME_SIZE];
uint16_t AnsSize;
/* Compute and send DATA_PACKET */
Cmd[0] = 0x00;
Cmd[1] = 0x00;
Cmd[2] = DataSize;
memcpy(&Cmd[3], pData, DataSize);
//status = NxpNci_HostSend(Cmd, DataSize+3);
status = NxpNci_HostTransceive(Cmd, DataSize+3, Ans, sizeof(Ans), &AnsSize);
return status;
}
#endif
#ifdef P2P_SUPPORT
void NxpNci_ProcessP2pMode(NxpNci_RfIntf_t RfIntf)
{
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
bool restart;
uint8_t NCILlcpSymm[] = {0x00, 0x00, 0x02, 0x00, 0x00};
uint8_t NCIRestartDiscovery[] = {0x21, 0x06, 0x01, 0x03};
/* Reset P2P_NDEF state */
P2P_NDEF_Reset();
/* Is Initiator mode ? */
if((RfIntf.ModeTech & MODE_LISTEN) != MODE_LISTEN)
{
/* Initiate communication (SYMM PDU) */
NxpNci_HostTransceive(NCILlcpSymm, sizeof(NCILlcpSymm), Answer, sizeof(Answer), &AnswerSize);
}
/* Get frame from remote peer */
while(NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_2S) == NXPNCI_SUCCESS)
{
/* is DATA_PACKET ? */
if((Answer[0] == 0x00) && (Answer[1] == 0x00))
{
uint8_t Cmd[MAX_NCI_FRAME_SIZE];
uint16_t CmdSize;
P2P_NDEF_Next(&Answer[3], Answer[2], &Cmd[3], (unsigned short *) &CmdSize);
/* Compute DATA_PACKET to answer */
Cmd[0] = 0x00;
Cmd[1] = (CmdSize & 0xFF00) >> 8;
Cmd[2] = CmdSize & 0x00FF;
NxpNci_HostTransceive(Cmd, CmdSize+3, Answer, sizeof(Answer), &AnswerSize);
}
/* is CORE_INTERFACE_ERROR_NTF ?*/
else if ((Answer[0] == 0x60) && (Answer[1] == 0x08))
{
break;
}
/* is RF_DEACTIVATE_NTF ? */
else if((Answer[0] == 0x61) && (Answer[1] == 0x06))
{
/* Come back to discovery state */
break;
}
/* is RF_DISCOVERY_NTF ? */
else if((Answer[0] == 0x61) && ((Answer[1] == 0x05) || (Answer[1] == 0x03)))
{
restart = false;
do{
if((Answer[6] & MODE_LISTEN) != MODE_LISTEN) restart = true;
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
}
while (AnswerSize != 0);
if(restart)
{
NxpNci_HostTransceive(NCIRestartDiscovery, sizeof(NCIRestartDiscovery), Answer, sizeof(Answer), &AnswerSize);
}
}
}
/* Is Initiator mode ? */
if((RfIntf.ModeTech & MODE_LISTEN) != MODE_LISTEN)
{
/* Communication ended, restart discovery loop */
NxpNci_HostTransceive(NCIRestartDiscovery, sizeof(NCIRestartDiscovery), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
}
}
#endif
#ifdef RW_SUPPORT
bool NxpNci_ReaderTagCmd (unsigned char *pCommand, unsigned char CommandSize, unsigned char *pAnswer, unsigned char *pAnswerSize)
{
bool status = NXPNCI_ERROR;
uint8_t Cmd[MAX_NCI_FRAME_SIZE];
uint8_t Ans[MAX_NCI_FRAME_SIZE];
uint16_t AnsSize;
/* Compute and send DATA_PACKET */
Cmd[0] = 0x00;
Cmd[1] = 0x00;
Cmd[2] = CommandSize;
memcpy(&Cmd[3], pCommand, CommandSize);
NxpNci_HostTransceive(Cmd, CommandSize+3, Ans, sizeof(Ans), &AnsSize);
/* Wait for Answer */
NxpNci_WaitForReception(Ans, sizeof(Ans), &AnsSize, TIMEOUT_1S);
if ((Ans[0] == 0x0) && (Ans[1] == 0x0))
{
status = NXPNCI_SUCCESS;
}
*pAnswerSize = Ans[2];
memcpy(pAnswer, &Ans[3], *pAnswerSize);
return status;
}
#ifndef NO_NDEF_SUPPORT
static bool NxpNci_T3TretrieveIDm (void)
{
uint8_t NCIPollingCmdT3T[] = {0x21, 0x08, 0x04, 0x12, 0xFC, 0x00, 0x01};
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
NxpNci_HostTransceive(NCIPollingCmdT3T, sizeof(NCIPollingCmdT3T), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
if ((Answer[0] == 0x61) && (Answer[1] == 0x08) && (Answer[3] == 0x00))
{
RW_NDEF_T3T_SetIDm(&Answer[6]);
}
else
{
return NXPNCI_ERROR;
}
return NXPNCI_SUCCESS;
}
static void NxpNci_ReadNdef(NxpNci_RfIntf_t RfIntf)
{
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
uint8_t Cmd[MAX_NCI_FRAME_SIZE];
uint16_t CmdSize = 0;
RW_NDEF_Reset(RfIntf.Protocol);
/* In case of T3T tag, retrieve card IDm for further operation */
if (RfIntf.Protocol == PROT_T3T) NxpNci_T3TretrieveIDm();
while(1)
{
RW_NDEF_Read_Next(&Answer[3], Answer[2], &Cmd[3], (unsigned short *) &CmdSize);
if(CmdSize == 0)
{
/* End of the Read operation */
break;
}
else
{
/* Compute and send DATA_PACKET */
Cmd[0] = 0x00;
Cmd[1] = (CmdSize & 0xFF00) >> 8;
Cmd[2] = CmdSize & 0x00FF;
NxpNci_HostTransceive(Cmd, CmdSize+3, Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
}
}
}
static void NxpNci_WriteNdef(NxpNci_RfIntf_t RfIntf)
{
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
uint8_t Cmd[MAX_NCI_FRAME_SIZE];
uint16_t CmdSize = 0;
RW_NDEF_Reset(RfIntf.Protocol);
/* In case of T3T tag, retrieve card IDm for further operation */
if (RfIntf.Protocol == PROT_T3T) NxpNci_T3TretrieveIDm();
while(1)
{
RW_NDEF_Write_Next(&Answer[3], Answer[2], &Cmd[3], (unsigned short *) &CmdSize);
if(CmdSize == 0)
{
/* End of the Write operation */
break;
}
else
{
/* Compute and send DATA_PACKET */
Cmd[0] = 0x00;
Cmd[1] = (CmdSize & 0xFF00) >> 8;
Cmd[2] = CmdSize & 0x00FF;
NxpNci_HostTransceive(Cmd, CmdSize+3, Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_2S);
}
}
}
#endif
static void NxpNci_PresenceCheck(NxpNci_RfIntf_t RfIntf)
{
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
uint8_t NCIPresCheckT1T[] = {0x00, 0x00, 0x07, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t NCIPresCheckT2T[] = {0x00, 0x00, 0x02, 0x30, 0x00};
uint8_t NCIPresCheckT3T[] = {0x21, 0x08, 0x04, 0xFF, 0xFF, 0x00, 0x01};
uint8_t NCIPresCheckIsoDep[] = {0x2F, 0x11, 0x00};
uint8_t NCIPresCheckIso15693[] = {0x00, 0x00, 0x03, 0x26, 0x01, 0x00};
uint8_t NCIDeactivate[] = {0x21, 0x06, 0x01, 0x01};
uint8_t NCISelectMIFARE[] = {0x21, 0x04, 0x03, 0x01, 0x80, 0x80};
switch (RfIntf.Protocol) {
case PROT_T1T:
do
{
Sleep(500);
NxpNci_HostTransceive(NCIPresCheckT1T, sizeof(NCIPresCheckT1T), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
} while ((Answer[0] == 0x00) && (Answer[1] == 0x00));
break;
case PROT_T2T:
do
{
Sleep(500);
NxpNci_HostTransceive(NCIPresCheckT2T, sizeof(NCIPresCheckT2T), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
} while ((Answer[0] == 0x00) && (Answer[1] == 0x00) && (Answer[2] == 0x11));
break;
case PROT_T3T:
do
{
Sleep(500);
NxpNci_HostTransceive(NCIPresCheckT3T, sizeof(NCIPresCheckT3T), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
} while ((Answer[0] == 0x61) && (Answer[1] == 0x08) && (Answer[3] == 0x00));
break;
case PROT_ISODEP:
do
{
Sleep(500);
NxpNci_HostTransceive(NCIPresCheckIsoDep, sizeof(NCIPresCheckIsoDep), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
} while ((Answer[0] == 0x6F) && (Answer[1] == 0x11) && (Answer[2] == 0x01) && (Answer[3] == 0x01));
break;
case PROT_ISO15693:
do
{
Sleep(500);
NxpNci_HostTransceive(NCIPresCheckIso15693, sizeof(NCIPresCheckIso15693), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
} while ((Answer[0] == 0x00) && (Answer[1] == 0x00));
break;
case PROT_MIFARE:
do
{
Sleep(500);
/* Deactivate target */
NxpNci_HostTransceive(NCIDeactivate, sizeof(NCIDeactivate), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
/* Reactivate target */
NxpNci_HostTransceive(NCISelectMIFARE, sizeof(NCISelectMIFARE), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
} while ((Answer[0] == 0x61) && (Answer[1] == 0x05));
break;
default:
/* Nothing to do */
break;
}
}
void NxpNci_ProcessReaderMode(NxpNci_RfIntf_t RfIntf, NxpNci_RW_Operation_t Operation)
{
switch (Operation)
{
#ifndef NO_NDEF_SUPPORT
case READ_NDEF:
NxpNci_ReadNdef(RfIntf);
break;
case WRITE_NDEF:
NxpNci_WriteNdef(RfIntf);
break;
#endif
case PRESENCE_CHECK:
NxpNci_PresenceCheck(RfIntf);
break;
default:
break;
}
}
bool NxpNci_ReaderActivateNext(NxpNci_RfIntf_t *pRfIntf)
{
uint8_t NCIStopDiscovery[] = {0x21, 0x06, 0x01, 0x01};
uint8_t NCIRfDiscoverSelect[] = {0x21, 0x04, 0x03, 0x02, PROT_ISODEP, INTF_ISODEP};
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
bool status = NXPNCI_ERROR;
pRfIntf->MoreTags = false;
if (gNextTag_Protocol == PROT_UNDETERMINED)
{
pRfIntf->Interface = INTF_UNDETERMINED;
pRfIntf->Protocol = PROT_UNDETERMINED;
return NXPNCI_ERROR;
}
/* First disconnect current tag */
NxpNci_HostTransceive(NCIStopDiscovery, sizeof(NCIStopDiscovery), Answer, sizeof(Answer), &AnswerSize);
if((Answer[0] != 0x41) && (Answer[1] != 0x06) && (Answer[3] != 0x00)) return NXPNCI_ERROR;
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
if((Answer[0] != 0x61) && (Answer[1] != 0x06)) return NXPNCI_ERROR;
NCIRfDiscoverSelect[4] = gNextTag_Protocol;
if (gNextTag_Protocol == PROT_ISODEP) NCIRfDiscoverSelect[5] = INTF_ISODEP;
else if (gNextTag_Protocol == PROT_ISODEP) NCIRfDiscoverSelect[5] = INTF_NFCDEP;
else if (gNextTag_Protocol == PROT_MIFARE) NCIRfDiscoverSelect[5] = INTF_TAGCMD;
else NCIRfDiscoverSelect[5] = INTF_FRAME;
NxpNci_HostTransceive(NCIRfDiscoverSelect, sizeof(NCIRfDiscoverSelect), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] == 0x41) || (Answer[1] == 0x04) || (Answer[3] == 0x00))
{
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
if ((Answer[0] == 0x61) || (Answer[1] == 0x05))
{
pRfIntf->Interface = Answer[4];
pRfIntf->Protocol = Answer[5];
pRfIntf->ModeTech = Answer[6];
NxpNci_FillInterfaceInfo(pRfIntf, &Answer[10]);
status = NXPNCI_SUCCESS;
}
}
return status;
}
bool NxpNci_ReaderReActivate(NxpNci_RfIntf_t *pRfIntf)
{
uint8_t NCIDeactivate[] = {0x21, 0x06, 0x01, 0x01};
uint8_t NCIActivate[] = {0x21, 0x04, 0x03, 0x01, 0x00, 0x00};
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
/* First de-activate the target */
NxpNci_HostTransceive(NCIDeactivate, sizeof(NCIDeactivate), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
/* Then re-activate the target */
NCIActivate[4] = pRfIntf->Protocol;
NCIActivate[5] = pRfIntf->Interface;
NxpNci_HostTransceive(NCIActivate, sizeof(NCIActivate), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
if((Answer[0] != 0x61) || (Answer[1] != 0x05)) return NXPNCI_ERROR;
return NXPNCI_SUCCESS;
}
#endif
bool NxpNci_Connect(void)
{
uint8_t i = 2;
uint8_t NCICoreInit[] = {0x20, 0x01, 0x00};
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
/* Open connection to NXPNCI */
tml_Connect ();
/* Loop until NXPNCI answers */
while(NxpNci_CheckDevPres() != NXPNCI_SUCCESS)
{
if(i-- == 0) return NXPNCI_ERROR;
Sleep(500);
}
NxpNci_HostTransceive(NCICoreInit, sizeof(NCICoreInit), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x01) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
/* Retrieve NXP-NCI NFC Controller generation */
if (Answer[17+Answer[8]] == 0x08) gNfcController_generation = 1;
else if (Answer[17+Answer[8]] == 0x10) gNfcController_generation = 2;
return NXPNCI_SUCCESS;
}
bool NxpNci_Disconnect(void)
{
/* Close connection to NXPNCI */
tml_Disconnect ();
return NXPNCI_SUCCESS;
}
bool NxpNci_ConfigureSettings(void)
{
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
uint8_t NCICoreReset[] = {0x20, 0x00, 0x01, 0x00};
uint8_t NCICoreInit[] = {0x20, 0x01, 0x00};
#if (NXP_TVDD_CONF | NXP_RF_CONF)
uint8_t *NxpNci_CONF;
uint16_t NxpNci_CONF_size = 0;
#endif
bool isResetRequired = false;
/* Apply settings according definition of Nfc_settings.h header file */
#if NXP_CORE_CONF
if (sizeof(NxpNci_CORE_CONF) != 0)
{
isResetRequired = true;
NxpNci_HostTransceive(NxpNci_CORE_CONF, sizeof(NxpNci_CORE_CONF), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x02) || (Answer[3] != 0x00) || (Answer[4] != 0x00)) return NXPNCI_ERROR;
}
#endif
#if NXP_CORE_CONF_EXTN
if (sizeof(NxpNci_CORE_CONF_EXTN) != 0)
{
isResetRequired = true;
NxpNci_HostTransceive(NxpNci_CORE_CONF_EXTN, sizeof(NxpNci_CORE_CONF_EXTN), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x02) || (Answer[3] != 0x00) || (Answer[4] != 0x00)) return NXPNCI_ERROR;
}
#endif
#if NXP_CORE_STANDBY
if (sizeof(NxpNci_CORE_STANDBY) != 0)
{
isResetRequired = true;
NxpNci_HostTransceive(NxpNci_CORE_STANDBY, sizeof(NxpNci_CORE_STANDBY), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x4F) || (Answer[1] != 0x00) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
}
#endif
#if NXP_CLK_CONF
if (sizeof(NxpNci_CLK_CONF) != 0)
{
isResetRequired = true;
NxpNci_HostTransceive(NxpNci_CLK_CONF, sizeof(NxpNci_CLK_CONF), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x02) || (Answer[3] != 0x00) || (Answer[4] != 0x00)) return NXPNCI_ERROR;
}
#endif
#if NXP_TVDD_CONF
if(gNfcController_generation == 1)
{
NxpNci_CONF = NxpNci_TVDD_CONF_1stGen;
NxpNci_CONF_size = sizeof(NxpNci_TVDD_CONF_1stGen);
}
else if(gNfcController_generation == 2)
{
NxpNci_CONF = NxpNci_TVDD_CONF_2ndGen;
NxpNci_CONF_size = sizeof(NxpNci_TVDD_CONF_2ndGen);
}
if (NxpNci_CONF_size != 0)
{
isResetRequired = true;
NxpNci_HostTransceive(NxpNci_CONF, NxpNci_CONF_size, Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x02) || (Answer[3] != 0x00) || (Answer[4] != 0x00)) return NXPNCI_ERROR;
}
#endif
#if NXP_RF_CONF
if(gNfcController_generation == 1)
{
NxpNci_CONF = NxpNci_RF_CONF_1stGen;
NxpNci_CONF_size = sizeof(NxpNci_RF_CONF_1stGen);
}
else if(gNfcController_generation == 2)
{
NxpNci_CONF = NxpNci_RF_CONF_2ndGen;
NxpNci_CONF_size = sizeof(NxpNci_RF_CONF_2ndGen);
}
if (NxpNci_CONF_size != 0)
{
isResetRequired = true;
NxpNci_HostTransceive(NxpNci_CONF, NxpNci_CONF_size, Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x02) || (Answer[3] != 0x00) || (Answer[4] != 0x00)) return NXPNCI_ERROR;
}
#endif
if(isResetRequired)
{
/* Reset the NFC Controller to insure new settings apply */
NxpNci_HostTransceive(NCICoreReset, sizeof(NCICoreReset), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x00) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
NxpNci_HostTransceive(NCICoreInit, sizeof(NCICoreInit), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x01) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
}
return NXPNCI_SUCCESS;
}
bool NxpNci_ConfigureMode(unsigned char mode)
{
uint8_t Command[MAX_NCI_FRAME_SIZE];
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
uint8_t Item = 0;
uint8_t NCIDiscoverMap[] = {0x21, 0x00};
#ifdef CARDEMU_SUPPORT
const uint8_t DM_CARDEMU[] = {0x4, 0x2, 0x2};
const uint8_t R_CARDEMU[] = {0x1, 0x3, 0x0, 0x1, 0x4};
#endif
#ifdef P2P_SUPPORT
const uint8_t DM_P2P[] = {0x5, 0x3, 0x3};
const uint8_t R_P2P[] = {0x1, 0x3, 0x0, 0x1, 0x5};
uint8_t NCISetConfig_NFC[] = {0x20, 0x02, 0x1F, 0x02, 0x29, 0x0D, 0x46, 0x66, 0x6D, 0x01, 0x01, 0x11, 0x03, 0x02, 0x00, 0x01, 0x04, 0x01, 0xFA, 0x61, 0x0D, 0x46, 0x66, 0x6D, 0x01, 0x01, 0x11, 0x03, 0x02, 0x00, 0x01, 0x04, 0x01, 0xFA};
#endif
#ifdef RW_SUPPORT
const uint8_t DM_RW[] = {0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x3, 0x1, 0x1, 0x4, 0x1, 0x2, 0x80, 0x01, 0x80};
uint8_t NCIPropAct[] = {0x2F, 0x02, 0x00};
#endif
#if defined P2P_SUPPORT || defined CARDEMU_SUPPORT
uint8_t NCIRouting[] = {0x21, 0x01, 0x07, 0x00, 0x01};
uint8_t NCISetConfig_NFCA_SELRSP[] = {0x20, 0x02, 0x04, 0x01, 0x32, 0x01, 0x00};
#endif
if(mode == 0) return NXPNCI_SUCCESS;
/* Enable Proprietary interface for T4T card presence check procedure */
#ifdef RW_SUPPORT
if (mode == NXPNCI_MODE_RW)
{
NxpNci_HostTransceive(NCIPropAct, sizeof(NCIPropAct), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x4F) || (Answer[1] != 0x02) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
}
#endif
/* Building Discovery Map command */
Item = 0;
#ifdef CARDEMU_SUPPORT
if (mode & NXPNCI_MODE_CARDEMU)
{
memcpy(&Command[4+(3*Item)], DM_CARDEMU, sizeof(DM_CARDEMU));
Item++;
}
#endif
#ifdef P2P_SUPPORT
if (mode & NXPNCI_MODE_P2P)
{
memcpy(&Command[4+(3*Item)], DM_P2P, sizeof(DM_P2P));
Item++;
}
#endif
#ifdef RW_SUPPORT
if (mode & NXPNCI_MODE_RW)
{
memcpy(&Command[4+(3*Item)], DM_RW, sizeof(DM_RW));
Item+=sizeof(DM_RW)/3;
}
#endif
#if defined P2P_SUPPORT || defined CARDEMU_SUPPORT || defined RW_SUPPORT
if (Item != 0)
{
memcpy(Command, NCIDiscoverMap, sizeof(NCIDiscoverMap));
Command[2] = 1 + (Item*3);
Command[3] = Item;
NxpNci_HostTransceive(Command, 3 + Command[2], Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x41) || (Answer[1] != 0x00) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
}
#endif
/* Configuring routing */
Item = 0;
#ifdef CARDEMU_SUPPORT
if (mode & NXPNCI_MODE_CARDEMU)
{
memcpy(&Command[5+(5*Item)], R_CARDEMU, sizeof(R_CARDEMU));
Item++;
}
#endif
#ifdef P2P_SUPPORT
if (mode & NXPNCI_MODE_P2P)
{
memcpy(&Command[5+(5*Item)], R_P2P, sizeof(R_P2P));
Item++;
}
#endif
#if defined P2P_SUPPORT || defined CARDEMU_SUPPORT
if (Item != 0)
{
memcpy(Command, NCIRouting, sizeof(NCIRouting));
Command[2] = 2 + (Item*5);
Command[4] = Item;
NxpNci_HostTransceive(Command, 3 + Command[2] , Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x41) || (Answer[1] != 0x01) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
}
#endif
/* Setting NFCA SEL_RSP */
#ifdef CARDEMU_SUPPORT
if (mode & NXPNCI_MODE_CARDEMU)
{
NCISetConfig_NFCA_SELRSP[6] += 0x20;
}
#endif
#ifdef P2P_SUPPORT
if (mode & NXPNCI_MODE_P2P)
{
NCISetConfig_NFCA_SELRSP[6] += 0x40;
}
#endif
#if defined P2P_SUPPORT || defined CARDEMU_SUPPORT
if (NCISetConfig_NFCA_SELRSP[6] != 0x00)
{
NxpNci_HostTransceive(NCISetConfig_NFCA_SELRSP, sizeof(NCISetConfig_NFCA_SELRSP), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x02) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
}
#endif
/* Setting LLCP support */
#ifdef P2P_SUPPORT
if (mode & NXPNCI_MODE_P2P)
{
NxpNci_HostTransceive(NCISetConfig_NFC, sizeof(NCISetConfig_NFC), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x40) || (Answer[1] != 0x02) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
}
#endif
return NXPNCI_SUCCESS;
}
bool NxpNci_StartDiscovery(unsigned char *pTechTab, unsigned char TechTabSize)
{
uint8_t Buffer[MAX_NCI_FRAME_SIZE];
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
uint8_t i;
Buffer[0] = 0x21;
Buffer[1] = 0x03;
Buffer[2] = (TechTabSize * 2) + 1;
Buffer[3] = TechTabSize;
for (i=0; i<TechTabSize; i++)
{
Buffer[(i*2)+4] = pTechTab[i];
Buffer[(i*2)+5] = 0x01;
}
NxpNci_HostTransceive(Buffer, (TechTabSize * 2) + 4, Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] != 0x41) || (Answer[1] != 0x03) || (Answer[3] != 0x00)) return NXPNCI_ERROR;
return NXPNCI_SUCCESS;
}
bool NxpNci_StopDiscovery(void)
{
uint8_t NCIStopDiscovery[] = {0x21, 0x06, 0x01, 0x00};
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
NxpNci_HostTransceive(NCIStopDiscovery, sizeof(NCIStopDiscovery), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_1S);
return NXPNCI_SUCCESS;
}
bool NxpNci_WaitForDiscoveryNotification(NxpNci_RfIntf_t *pRfIntf)
{
uint8_t NCIRfDiscoverSelect[] = {0x21, 0x04, 0x03, 0x01, PROT_ISODEP, INTF_ISODEP};
uint8_t Answer[MAX_NCI_FRAME_SIZE];
uint16_t AnswerSize;
#ifdef P2P_SUPPORT
uint8_t NCIRestartDiscovery[] = {0x21, 0x06, 0x01, 0x03};
uint8_t saved_NTF[7];
wait:
#endif
do
{
if(NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_INFINITE) == NXPNCI_ERROR) return NXPNCI_ERROR;
}while ((Answer[0] != 0x61) || ((Answer[1] != 0x05) && (Answer[1] != 0x03)));
gNextTag_Protocol = PROT_UNDETERMINED;
/* Is RF_INTF_ACTIVATED_NTF ? */
if (Answer[1] == 0x05)
{
pRfIntf->Interface = Answer[4];
pRfIntf->Protocol = Answer[5];
pRfIntf->ModeTech = Answer[6];
pRfIntf->MoreTags = false;
NxpNci_FillInterfaceInfo(pRfIntf, &Answer[10]);
#ifdef P2P_SUPPORT
/* Verifying if not a P2P device also presenting T4T emulation */
if ((pRfIntf->Interface == INTF_ISODEP) && (pRfIntf->Protocol == PROT_ISODEP) && ((pRfIntf->ModeTech & MODE_LISTEN) != MODE_LISTEN))
{
memcpy(saved_NTF, Answer, sizeof(saved_NTF));
while(1)
{
/* Restart the discovery loop */
NxpNci_HostTransceive(NCIRestartDiscovery, sizeof(NCIRestartDiscovery), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
/* Wait for discovery */
do NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_1S);
while ((AnswerSize == 4) && (Answer[0] == 0x60) && (Answer[1] == 0x07));
if ((AnswerSize != 0) && (Answer[0] == 0x61) && (Answer[1] == 0x05))
{
/* Is same device detected ? */
if (memcmp(saved_NTF, Answer, sizeof(saved_NTF)) == 0) break;
/* Is P2P detected ? */
if (Answer[5] == PROT_NFCDEP)
{
pRfIntf->Interface = Answer[4];
pRfIntf->Protocol = Answer[5];
pRfIntf->ModeTech = Answer[6];
pRfIntf->MoreTags = false;
NxpNci_FillInterfaceInfo(pRfIntf, &Answer[10]);
break;
}
}
else
{
if (AnswerSize != 0)
{
/* Restart the discovery loop */
NxpNci_HostTransceive(NCIRestartDiscovery, sizeof(NCIRestartDiscovery), Answer, sizeof(Answer), &AnswerSize);
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
}
goto wait;
}
}
}
#endif
}
else /* RF_DISCOVER_NTF */
{
pRfIntf->Interface = INTF_UNDETERMINED;
pRfIntf->Protocol = Answer[4];
pRfIntf->ModeTech = Answer[5];
pRfIntf->MoreTags = true;
/* Get next NTF for further activation */
do {
if(NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS) == NXPNCI_ERROR) return NXPNCI_ERROR;
} while ((Answer[0] != 0x61) || (Answer[1] != 0x03));
gNextTag_Protocol = Answer[4];
/* Remaining NTF ? */
while(Answer[AnswerSize-1] == 0x02) NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
/* In case of multiple cards, select the first one */
NCIRfDiscoverSelect[4] = pRfIntf->Protocol;
if (pRfIntf->Protocol == PROT_ISODEP) NCIRfDiscoverSelect[5] = INTF_ISODEP;
else if (pRfIntf->Protocol == PROT_NFCDEP) NCIRfDiscoverSelect[5] = INTF_NFCDEP;
else if (pRfIntf->Protocol == PROT_MIFARE) NCIRfDiscoverSelect[5] = INTF_TAGCMD;
else NCIRfDiscoverSelect[5] = INTF_FRAME;
NxpNci_HostTransceive(NCIRfDiscoverSelect, sizeof(NCIRfDiscoverSelect), Answer, sizeof(Answer), &AnswerSize);
if ((Answer[0] == 0x41) || (Answer[1] == 0x04) || (Answer[3] == 0x00))
{
NxpNci_WaitForReception(Answer, sizeof(Answer), &AnswerSize, TIMEOUT_100MS);
if ((Answer[0] == 0x61) || (Answer[1] == 0x05))
{
pRfIntf->Interface = Answer[4];
pRfIntf->Protocol = Answer[5];
pRfIntf->ModeTech = Answer[6];
NxpNci_FillInterfaceInfo(pRfIntf, &Answer[10]);
}
}
}
/* In case of unknown target align protocol information */
if (pRfIntf->Interface == INTF_UNDETERMINED) pRfIntf->Protocol = PROT_UNDETERMINED;
return NXPNCI_SUCCESS;
}
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
/***** NFC dedicated interface ****************************************/
/*
* Status code definition used as API returned values
*/
#define NFC_SUCCESS 0
#define NFC_ERROR 1
/*
* Flag definition used as Interface values
*/
#define INTF_UNDETERMINED 0x0
#define INTF_FRAME 0x1
#define INTF_ISODEP 0x2
#define INTF_NFCDEP 0x3
#define INTF_TAGCMD 0x80
/*
* Flag definition used as Protocol values
*/
#define PROT_UNDETERMINED 0x0
#define PROT_T1T 0x1
#define PROT_T2T 0x2
#define PROT_T3T 0x3
#define PROT_ISODEP 0x4
#define PROT_NFCDEP 0x5
#define PROT_ISO15693 0x6
#define PROT_MIFARE 0x80
/*
* Flag definition used as Mode values
*/
#define MODE_POLL 0x00
#define MODE_LISTEN 0x80
#define MODE_MASK 0xF0
/*
* Flag definition used as Technologies values
*/
#define TECH_PASSIVE_NFCA 0
#define TECH_PASSIVE_NFCB 1
#define TECH_PASSIVE_NFCF 2
#define TECH_ACTIVE_NFCA 3
#define TECH_ACTIVE_NFCF 5
#define TECH_PASSIVE_15693 6
/*
* Flag definition used for NFC library configuration
*/
#define NXPNCI_MODE_CARDEMU (1<<0)
#define NXPNCI_MODE_P2P (1<<1)
#define NXPNCI_MODE_RW (1<<2)
/*
* Definition of operations handled when processing Reader mode
*/
typedef enum
{
#ifndef NO_NDEF_SUPPORT
READ_NDEF,
WRITE_NDEF,
#endif
PRESENCE_CHECK
} NxpNci_RW_Operation_t;
/*
* Definition of discovered remote device properties information
*/
/* POLL passive type A */
typedef struct
{
unsigned char SensRes[2];
unsigned char NfcIdLen;
unsigned char NfcId[10];
unsigned char SelResLen;
unsigned char SelRes[1];
} NxpNci_RfIntf_info_APP_t;
/* POLL passive type B */
typedef struct
{
unsigned char SensResLen;
unsigned char SensRes[12];
} NxpNci_RfIntf_info_BPP_t;
/* POLL passive type F */
typedef struct
{
unsigned char BitRate;
unsigned char SensResLen;
unsigned char SensRes[18];
} NxpNci_RfIntf_info_FPP_t;
/* POLL passive type ISO15693 */
typedef struct
{
unsigned char AFI;
unsigned char DSFID;
unsigned char ID[8];
} NxpNci_RfIntf_info_VPP_t;
typedef union
{
NxpNci_RfIntf_info_APP_t NFC_APP;
NxpNci_RfIntf_info_BPP_t NFC_BPP;
NxpNci_RfIntf_info_FPP_t NFC_FPP;
NxpNci_RfIntf_info_VPP_t NFC_VPP;
} NxpNci_RfIntf_Info_t;
/*
* Definition of discovered remote device properties
*/
typedef struct
{
unsigned char Interface;
unsigned char Protocol;
unsigned char ModeTech;
bool MoreTags;
NxpNci_RfIntf_Info_t Info;
} NxpNci_RfIntf_t;
/**********************************************************************/
/***** NFC dedicated API **********************************************/
/*
* Open connection to the NXP-NCI device
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_Connect(void);
/*
* Close connection to the NXP-NCI device
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_Disconnect(void);
/*
* Configure NXP-NCI device settings
* Related settings are defined in Nfc_settings.h header file
* To be called after NxpNci_Connect() and prior to NxpNci_ConfigureMode() APIs
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_ConfigureSettings(void);
/*
* Configure NXP-NCI device mode
* - mode: specifies which modes to be configured (see NXPNCI_MODE_xxx flags)
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_ConfigureMode(unsigned char mode);
/*
* Start NFC Discovery loop for remote NFC device detection
* - pTechTab: list of NFC technologies to look for (see TECH_xxx_xxx flags)
* \param TechTabSize: number of items in the list
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_StartDiscovery(unsigned char *pTechTab, unsigned char TechTabSize);
/*
* Stop NFC Discovery loop
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_StopDiscovery(void);
/*
* Wait until remote NFC device is discovered
* - pRfIntf: filled with discovered NFC remote device properties
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_WaitForDiscoveryNotification(NxpNci_RfIntf_t *pRfIntf);
/**********************************************************************/
/***** Reader/writer dedicated APIs ***********************************/
#ifdef RW_SUPPORT
#ifndef NO_NDEF_SUPPORT
/*
* Register NDEF message to be written to remote NFC Tag
* - pMessage: pointer to the NDEF message
* - Message_size: NDEF message size
* - pCb: pointer to function to be called back when tag has been written
* return NFC_SUCCESS or NFC_ERROR
*/
bool RW_NDEF_SetMessage(unsigned char *pMessage, unsigned short Message_size, void *pCb);
/*
* Register function called when NDEF message is read from remote NFC Tag
* - pCb: pointer to function to be called back when NDEF message has been read
*/
void RW_NDEF_RegisterPullCallback(void *pCb);
#endif
/*
* Process the operation identified as parameter with discovered remote NFC tag (function is blocking until the end of the operation)
* - RfIntf: discovered NFC device properties
* - Operation: select operation to be done with the remote NFC tag
* o READ_NDEF: extract NDEF message from the tag, previously registered callback function will be called whenever complete NDEF message is found.
* o WRITE_NDEF: write previously registered NDEF message to the tag
* o PRESENCE_CHECK: perform presence check until tag has been removed (function is blocking until card is removed)
*/
void NxpNci_ProcessReaderMode(NxpNci_RfIntf_t RfIntf, NxpNci_RW_Operation_t Operation);
/*
* Perform RAW transceive operation (send then receive) with the remote tag
* - pCommand: pointer to the command to send
* - CommandSize: command size
* - pAnswer: pointer to buffer for getting the response
* - pAnswerSize: response size
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_ReaderTagCmd (unsigned char *pCommand, unsigned char CommandSize, unsigned char *pAnswer, unsigned char *pAnswerSize);
/*
* Perform activation of the next tag (in case of multiple tag detection or multi-protocol tag)
* - pRfIntf: filled with discovered NFC remote device properties
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_ReaderActivateNext(NxpNci_RfIntf_t *pRfIntf);
/*
* Perform deactivation then reactivation of the current tag
* - pRfIntf: filled with discovered NFC remote device properties
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_ReaderReActivate(NxpNci_RfIntf_t *pRfIntf);
#endif
/**********************************************************************/
/***** Card Emulation dedicated APIs **********************************/
#ifdef CARDEMU_SUPPORT
#ifndef NO_NDEF_SUPPORT
/*
* Register NDEF message to be exposed to remote NFC reader Device
* - pMessage: pointer to the NDEF message
* - Message_size: NDEF message size
* - pCb: pointer to function to be called back when tag has been written
* return NFC_SUCCESS or NFC_ERROR
*/
bool T4T_NDEF_EMU_SetMessage(unsigned char *pMessage, unsigned short Message_size, void *pCb);
#endif
/*
* Expose the previously registered NDEF message to discovered remote NFC reader (function is blocking until the remote reader is lost):
* - RfIntf: discovered NFC device properties
*/
void NxpNci_ProcessCardMode(NxpNci_RfIntf_t RfIntf);
/*
* Perform RAW reception of data from the remote reader
* - pData: pointer to buffer for getting the data
* - pDataSize: received data size
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_CardModeReceive (unsigned char *pData, unsigned char *pDataSize);
/*
* Perform RAW transmission of data from the remote reader
* - pData: pointer to data to transmit
* - DataSize: size of data to transmit
* return NFC_SUCCESS or NFC_ERROR
*/
bool NxpNci_CardModeSend (unsigned char *pData, unsigned char DataSize);
#endif
/**********************************************************************/
/***** P2P dedicated APIs *********************************************/
#ifdef P2P_SUPPORT
/*
* Register NDEF message to be sent to remote NFC Peer to peer Device
* - pMessage: pointer to the NDEF message
* - Message_size: NDEF message size
* - pCb: pointer to function to be called back when tag has been sent
* return NFC_SUCCESS or NFC_ERROR
*/
bool P2P_NDEF_SetMessage(unsigned char *pMessage, unsigned short Message_size, void *pCb);
/*
* Register function called when NDEF message is received from remote NFC Peer to peer Device
* - pCb: pointer to function to be called back when NDEF message has been received
*/
void P2P_NDEF_RegisterPullCallback(void *pCb);
/* Process P2P operation (function is blocking until the remote peer is lost):
* ¤ SNEP server to allow receiving NDEF message from remote NFC P2P device
* ¤ SNEP client to send previously registered NDEF message
* - RfIntf: discovered NFC device properties
*/
void NxpNci_ProcessP2pMode(NxpNci_RfIntf_t RfIntf);
#endif
/**********************************************************************/
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
/***** NFC dedicated setting ****************************************/
/* Following definitions specifies which settings will apply when NxpNci_ConfigureSettings()
* API is called from the application
*/
#define NXP_CORE_CONF 1
#define NXP_CORE_CONF_EXTN 1
#define NXP_CORE_STANDBY 1
#define NXP_CLK_CONF 1 // 1=Xtal, 2=PLL
#define NXP_TVDD_CONF 1 // 1=CFG1, 2=CFG2
#define NXP_RF_CONF 1
#if NXP_CORE_CONF
/* NCI standard dedicated settings
* Refer to NFC Forum NCI standard for more details
*/
uint8_t NxpNci_CORE_CONF[]={0x20, 0x02, 0x05, 0x01, /* CORE_SET_CONFIG_CMD */
0x00, 0x02, 0x00, 0x01 /* TOTAL_DURATION */
};
#endif
#if NXP_CORE_CONF_EXTN
/* NXP-NCI extension dedicated setting
* Refer to NFC controller User Manual for more details
*/
uint8_t NxpNci_CORE_CONF_EXTN[]={0x20, 0x02, 0x0D, 0x03, /* CORE_SET_CONFIG_CMD */
0xA0, 0x40, 0x01, 0x00, /* TAG_DETECTOR_CFG */
0xA0, 0x41, 0x01, 0x04, /* TAG_DETECTOR_THRESHOLD_CFG */
0xA0, 0x43, 0x01, 0x00 /* TAG_DETECTOR_FALLBACK_CNT_CFG */
};
#endif
#if NXP_CORE_STANDBY
/* NXP-NCI standby enable setting
* Refer to NFC controller User Manual for more details
*/
uint8_t NxpNci_CORE_STANDBY[]={0x2F, 0x00, 0x01, 0x01}; /* last byte indicates enable/disable */
#endif
#if NXP_CLK_CONF
/* NXP-NCI CLOCK configuration
* Refer to NFC controller Hardware Design Guide document for more details
*/
#if (NXP_CLK_CONF == 1)
/* Xtal configuration */
uint8_t NxpNci_CLK_CONF[]={0x20, 0x02, 0x05, 0x01, /* CORE_SET_CONFIG_CMD */
0xA0, 0x03, 0x01, 0x08 /* CLOCK_SEL_CFG */
};
#else
/* PLL configuration */
uint8_t NxpNci_CLK_CONF[]={0x20, 0x02, 0x09, 0x02, /* CORE_SET_CONFIG_CMD */
0xA0, 0x03, 0x01, 0x11, /* CLOCK_SEL_CFG */
0xA0, 0x04, 0x01, 0x01 /* CLOCK_TO_CFG */
};
#endif
#endif
#if NXP_TVDD_CONF
/* NXP-NCI TVDD configuration
* Refer to NFC controller Hardware Design Guide document for more details
*/
/* RF configuration related to 1st generation of NXP-NCI controller (e.g PN7120) */
uint8_t NxpNci_TVDD_CONF_1stGen[]={0x20, 0x02, 0x05, 0x01, 0xA0, 0x13, 0x01, 0x00};
/* RF configuration related to 2nd generation of NXP-NCI controller (e.g PN7150)*/
#if (NXP_TVDD_CONF == 1)
/* CFG1: Vbat is used to generate the VDD(TX) through TXLDO */
uint8_t NxpNci_TVDD_CONF_2ndGen[]={0x20, 0x02, 0x07, 0x01, 0xA0, 0x0E, 0x03, 0x02, 0x09, 0x00};
#else
/* CFG2: external 5V is used to generate the VDD(TX) through TXLDO */
uint8_t NxpNci_TVDD_CONF_2ndGen[]={0x20, 0x02, 0x07, 0x01, 0xA0, 0x0E, 0x03, 0x06, 0x64, 0x00};
#endif
#endif
#if NXP_RF_CONF
/* NXP-NCI RF configuration
* Refer to NFC controller Antenna Design and Tuning Guidelines document for more details
*/
/* RF configuration related to 1st generation of NXP-NCI controller (e.g PN7120) */
/* Following configuration is the default settings of PN7120 NFC Controller */
uint8_t NxpNci_RF_CONF_1stGen[]={0x20, 0x02, 0x38, 0x07,
0xA0, 0x0D, 0x06, 0x06, 0x42, 0x01, 0x00, 0xF1, 0xFF, /* RF_CLIF_CFG_TARGET CLIF_ANA_TX_AMPLITUDE_REG */
0xA0, 0x0D, 0x06, 0x06, 0x44, 0xA3, 0x90, 0x03, 0x00, /* RF_CLIF_CFG_TARGET CLIF_ANA_RX_REG */
0xA0, 0x0D, 0x06, 0x34, 0x2D, 0xDC, 0x50, 0x0C, 0x00, /* RF_CLIF_CFG_BR_106_I_RXA_P CLIF_SIGPRO_RM_CONFIG1_REG */
0xA0, 0x0D, 0x04, 0x06, 0x03, 0x00, 0x70, /* RF_CLIF_CFG_TARGET CLIF_TRANSCEIVE_CONTROL_REG */
0xA0, 0x0D, 0x03, 0x06, 0x16, 0x00, /* RF_CLIF_CFG_TARGET CLIF_TX_UNDERSHOOT_CONFIG_REG */
0xA0, 0x0D, 0x03, 0x06, 0x15, 0x00, /* RF_CLIF_CFG_TARGET CLIF_TX_OVERSHOOT_CONFIG_REG */
0xA0, 0x0D, 0x06, 0x32, 0x4A, 0x53, 0x07, 0x01, 0x1B /* RF_CLIF_CFG_BR_106_I_TXA CLIF_ANA_TX_SHAPE_CONTROL_REG */
};
/* RF configuration related to 2nd generation of NXP-NCI controller (e.g PN7150)*/
/* Following configuration relates to performance optimization of OM5578/PN7150 NFC Controller demo kit */
uint8_t NxpNci_RF_CONF_2ndGen[]={0x20, 0x02, 0xB7, 0x14,
0xA0, 0x0D, 0x06, 0x04, 0x35, 0x90, 0x01, 0xF4, 0x01, /* RF_CLIF_CFG_INITIATOR CLIF_AGC_INPUT_REG */
0xA0, 0x0D, 0x06, 0x06, 0x44, 0x01, 0x90, 0x03, 0x00, /* RF_CLIF_CFG_TARGET CLIF_ANA_RX_REG */
0xA0, 0x0D, 0x06, 0x06, 0x30, 0xB0, 0x01, 0x10, 0x00, /* RF_CLIF_CFG_TARGET CLIF_SIGPRO_ADCBCM_THRESHOLD_REG */
0xA0, 0x0D, 0x06, 0x06, 0x42, 0x02, 0x00, 0xFF, 0xFF, /* RF_CLIF_CFG_TARGET CLIF_ANA_TX_AMPLITUDE_REG */
0xA0, 0x0D, 0x03, 0x06, 0x3F, 0x04, /* RF_CLIF_CFG_TARGET CLIF_TEST_CONTROL_REG */
0xA0, 0x0D, 0x06, 0x20, 0x42, 0x88, 0x00, 0xFF, 0xFF, /* RF_CLIF_CFG_TECHNO_I_TX15693 CLIF_ANA_TX_AMPLITUDE_REG */
0xA0, 0x0D, 0x04, 0x22, 0x44, 0x22, 0x00, /* RF_CLIF_CFG_TECHNO_I_RX15693 CLIF_ANA_RX_REG */
0xA0, 0x0D, 0x06, 0x22, 0x2D, 0x50, 0x34, 0x0C, 0x00, /* RF_CLIF_CFG_TECHNO_I_RX15693 CLIF_SIGPRO_RM_CONFIG1_REG */
0xA0, 0x0D, 0x06, 0x32, 0x42, 0xF8, 0x00, 0xFF, 0xFF, /* RF_CLIF_CFG_BR_106_I_TXA CLIF_ANA_TX_AMPLITUDE_REG */
0xA0, 0x0D, 0x06, 0x34, 0x2D, 0x24, 0x37, 0x0C, 0x00, /* RF_CLIF_CFG_BR_106_I_RXA_P CLIF_SIGPRO_RM_CONFIG1_REG */
0xA0, 0x0D, 0x06, 0x34, 0x33, 0x86, 0x80, 0x00, 0x70, /* RF_CLIF_CFG_BR_106_I_RXA_P CLIF_AGC_CONFIG0_REG */
0xA0, 0x0D, 0x04, 0x34, 0x44, 0x22, 0x00, /* RF_CLIF_CFG_BR_106_I_RXA_P CLIF_ANA_RX_REG */
0xA0, 0x0D, 0x06, 0x42, 0x2D, 0x15, 0x45, 0x0D, 0x00, /* RF_CLIF_CFG_BR_848_I_RXA CLIF_SIGPRO_RM_CONFIG1_REG */
0xA0, 0x0D, 0x04, 0x46, 0x44, 0x22, 0x00, /* RF_CLIF_CFG_BR_106_I_RXB CLIF_ANA_RX_REG */
0xA0, 0x0D, 0x06, 0x46, 0x2D, 0x05, 0x59, 0x0E, 0x00, /* RF_CLIF_CFG_BR_106_I_RXB CLIF_SIGPRO_RM_CONFIG1_REG */
0xA0, 0x0D, 0x06, 0x44, 0x42, 0x88, 0x00, 0xFF, 0xFF, /* RF_CLIF_CFG_BR_106_I_TXB CLIF_ANA_TX_AMPLITUDE_REG */
0xA0, 0x0D, 0x06, 0x56, 0x2D, 0x05, 0x9F, 0x0C, 0x00, /* RF_CLIF_CFG_BR_212_I_RXF_P CLIF_SIGPRO_RM_CONFIG1_REG */
0xA0, 0x0D, 0x06, 0x54, 0x42, 0x88, 0x00, 0xFF, 0xFF, /* RF_CLIF_CFG_BR_212_I_TXF CLIF_ANA_TX_AMPLITUDE_REG */
0xA0, 0x0D, 0x06, 0x0A, 0x33, 0x80, 0x86, 0x00, 0x70, /* RF_CLIF_CFG_I_ACTIVE CLIF_AGC_CONFIG0_REG */
0xA0, 0x1D, 0x11, 0x57, 0x33, 0x14, 0x17, 0x00, 0xAA, 0x85, 0x00, 0x80, 0x55, 0x2A, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00
};
#endif
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#define NDEF_EMPTY 0x00
#define NDEF_WELL_KNOWN 0x01
#define NDEF_MEDIA 0x02
#define NDEF_ABSOLUTE_URI 0x03
#define NDEF_EXTERNAL 0x04
#define NDEF_UNKNOWN 0x05
#define NDEF_UNCHANGED 0x06
#define NDEF_RESERVED 0x07
#define NDEF_RECORD_MB_MASK 0x80
#define NDEF_RECORD_ME_MASK 0x40
#define NDEF_RECORD_CF_MASK 0x20
#define NDEF_RECORD_SR_MASK 0x10
#define NDEF_RECORD_IL_MASK 0x08
#define NDEF_RECORD_TNF_MASK 0x07
typedef enum
{
WELL_KNOWN_SIMPLE_TEXT,
WELL_KNOWN_SIMPLE_URI,
WELL_KNOWN_SMART_POSTER,
WELL_KNOWN_HANDOVER_SELECT,
WELL_KNOWN_HANDOVER_REQUEST,
WELL_KNOWN_ALTERNATIVE_CARRIER,
WELL_KNOWN_COLLISION_RESOLUTION,
MEDIA_VCARD,
MEDIA_HANDOVER_WIFI,
MEDIA_HANDOVER_BT,
MEDIA_HANDOVER_BLE,
MEDIA_HANDOVER_BLE_SECURE,
ABSOLUTE_URI,
UNSUPPORTED_NDEF_RECORD = 0xFF
}NdefRecordType_e;
typedef struct
{
NdefRecordType_e recordType;
unsigned char * recordPayload;
unsigned int recordPayloadSize;
} NdefRecord_t;
const char* ndef_helper_WifiAuth(unsigned char auth);
const char* ndef_helper_WifiEnc(unsigned char enc);
const char* ndef_helper_UriHead(unsigned char head);
NdefRecord_t DetectNdefRecordType(unsigned char *pNdefRecord);
unsigned char* GetNextRecord(unsigned char *pNdefRecord);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
extern "C" {
void task_nfc(void);
}
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <NfcTask/inc/ndef_helper.h>
const char* ndef_helper_WifiAuth(unsigned char auth)
{
switch (auth)
{
case 0x01: return "Open";
case 0x02: return "WPA-Personal";
case 0x04: return "Shared";
case 0x08: return "WPA-Enterprise";
case 0x10: return "WPA2-Enterprise";
case 0x20: return "WPA2-Personal";
default: return "unknown";
}
}
const char* ndef_helper_WifiEnc(unsigned char enc)
{
switch (enc)
{
case 0x01: return "None";
case 0x02: return "WEP";
case 0x04: return "TKIP";
case 0x08: return "AES";
case 0x10: return "AES/TKIP";
default: return "unknown";
}
}
const char* ndef_helper_UriHead(unsigned char head)
{
switch (head) {
case 0: return ("");
case 1: return ("http://www.");
case 2: return ("https://www.");
case 3: return ("http://");
case 4: return ("https://");
case 5: return ("tel:");
case 6: return ("mailto:");
default:return ("!!!unknown!!!");
}
}
NdefRecord_t DetectNdefRecordType(unsigned char *pNdefRecord)
{
NdefRecord_t record;
uint8_t typeField;
/* Short or normal record ?*/
if (pNdefRecord[0] & NDEF_RECORD_SR_MASK)
{
record.recordPayloadSize = pNdefRecord[2];
typeField = 3;
}
else
{
record.recordPayloadSize = (pNdefRecord[2]<<24) + (pNdefRecord[3]<<16) + (pNdefRecord[4]<<8) + pNdefRecord[5];
typeField = 6;
}
/* ID present ?*/
if(pNdefRecord[0] & NDEF_RECORD_IL_MASK)
{
record.recordPayload = pNdefRecord + typeField + pNdefRecord[1] + 1 + pNdefRecord[typeField];
typeField++;
}
else
{
record.recordPayload = pNdefRecord + typeField + pNdefRecord[1];
}
/* Well known Record Type ?*/
if ((pNdefRecord[0] & NDEF_RECORD_TNF_MASK) == NDEF_WELL_KNOWN)
{
if (pNdefRecord[1] == 0x1)
{
switch (pNdefRecord[typeField])
{
case 'T':
record.recordType = WELL_KNOWN_SIMPLE_TEXT;
break;
case 'U':
record.recordType = WELL_KNOWN_SIMPLE_URI;
break;
default:
record.recordType = UNSUPPORTED_NDEF_RECORD;
break;
}
} else if (pNdefRecord[1] == 0x2)
{
if (memcmp(&pNdefRecord[typeField], "Sp", pNdefRecord[1]) == 0x0)
{
record.recordType = WELL_KNOWN_SMART_POSTER;
}
else if (memcmp(&pNdefRecord[typeField], "Hs", pNdefRecord[1]) == 0x0)
{
record.recordType = WELL_KNOWN_HANDOVER_SELECT;
}
else if (memcmp(&pNdefRecord[typeField], "Hr", pNdefRecord[1]) == 0x0)
{
record.recordType = WELL_KNOWN_HANDOVER_REQUEST;
}
else if (memcmp(&pNdefRecord[typeField], "ac", pNdefRecord[1]) == 0x0)
{
record.recordType = WELL_KNOWN_ALTERNATIVE_CARRIER;
}
else if (memcmp(&pNdefRecord[typeField], "cr", pNdefRecord[1]) == 0x0)
{
record.recordType = WELL_KNOWN_COLLISION_RESOLUTION;
}
else
{
record.recordType = UNSUPPORTED_NDEF_RECORD;
}
}
}
/* Media Record Type ?*/
else if ((pNdefRecord[0] & NDEF_RECORD_TNF_MASK) == NDEF_MEDIA)
{
if ((memcmp(&pNdefRecord[typeField], "text/x-vCard", pNdefRecord[1]) == 0x0) ||
(memcmp(&pNdefRecord[typeField], "text/vcard", pNdefRecord[1]) == 0x0))
{
record.recordType = MEDIA_VCARD;
}
else if (memcmp(&pNdefRecord[typeField], "application/vnd.wfa.wsc", pNdefRecord[1]) == 0x0)
{
record.recordType = MEDIA_HANDOVER_WIFI;
}
else if (memcmp(&pNdefRecord[typeField], "application/vnd.bluetooth.ep.oob", pNdefRecord[1]) == 0x0)
{
record.recordType = MEDIA_HANDOVER_BT;
}
else if (memcmp(&pNdefRecord[typeField], "application/vnd.bluetooth.le.oob", pNdefRecord[1]) == 0x0)
{
record.recordType = MEDIA_HANDOVER_BLE;
}
else if (memcmp(&pNdefRecord[typeField], "application/vnd.bluetooth.secure.le.oob", pNdefRecord[1]) == 0x0)
{
record.recordType = MEDIA_HANDOVER_BLE_SECURE;
}
else
{
record.recordType = UNSUPPORTED_NDEF_RECORD;
}
}
/* Absolute URI Record Type ?*/
else if ((pNdefRecord[0] & NDEF_RECORD_TNF_MASK) == NDEF_ABSOLUTE_URI)
{
record.recordType = ABSOLUTE_URI;
}
else
{
record.recordType = UNSUPPORTED_NDEF_RECORD;
}
return record;
}
unsigned char* GetNextRecord(unsigned char *pNdefRecord)
{
unsigned char *temp = NULL;
/* Message End ?*/
if (!(pNdefRecord[0] & NDEF_RECORD_ME_MASK)) {
/* Short or normal record ?*/
if (pNdefRecord[0] & NDEF_RECORD_SR_MASK)
{
/* ID present ?*/
if(pNdefRecord[0] & NDEF_RECORD_IL_MASK)
temp = (pNdefRecord + 4 + pNdefRecord[1] + pNdefRecord[2] + pNdefRecord[3]);
else
temp = (pNdefRecord + 3 + pNdefRecord[1] + pNdefRecord[2]);
}
else
{
/* ID present ?*/
if(pNdefRecord[0] & NDEF_RECORD_IL_MASK)
temp = (pNdefRecord + 7 + pNdefRecord[1] + (pNdefRecord[2]<<24) + (pNdefRecord[3]<<16) + (pNdefRecord[4]<<8) + pNdefRecord[5] + pNdefRecord[6]);
else
temp = (pNdefRecord + 6 + pNdefRecord[1] + (pNdefRecord[2]<<24) + (pNdefRecord[3]<<16) + (pNdefRecord[4]<<8) + pNdefRecord[5]);
}
}
return temp;
}
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <TML/inc/tool.h>
#include <NfcLibrary/inc/Nfc.h>
#include <NfcTask/inc/ndef_helper.h>
//#define RW_NDEF_WRITING
//#define RW_RAW_EXCHANGE
//#define CARDEMU_RAW_EXCHANGE
void print_buf(char *x, char *y, int z)
{
int loop;
char b[256];
char buf[10000];
strcpy(buf, x);
for(loop=0;loop<z;loop++) {
sprintf(b, "%.2x ", y[loop]);
strcat(buf, b);
}
strcat(buf, "\n");
framework_Log(buf);
}
/* Discovery loop configuration according to the targeted modes of operation */
unsigned char DiscoveryTechnologies[] = {
#if defined P2P_SUPPORT || defined RW_SUPPORT
MODE_POLL | TECH_PASSIVE_NFCA,
MODE_POLL | TECH_PASSIVE_NFCF,
#endif // if defined P2P_SUPPORT || defined RW_SUPPORT
#ifdef RW_SUPPORT
MODE_POLL | TECH_PASSIVE_NFCB,
MODE_POLL | TECH_PASSIVE_15693,
#endif // ifdef RW_SUPPORT
#ifdef P2P_SUPPORT
/* Only one POLL ACTIVE mode can be enabled, if both are defined only NFCF applies */
MODE_POLL | TECH_ACTIVE_NFCA,
//MODE_POLL | TECH_ACTIVE_NFCF,
#endif // ifdef P2P_SUPPORT
#if defined P2P_SUPPORT || defined CARDEMU_SUPPORT
MODE_LISTEN | TECH_PASSIVE_NFCA,
#endif // if defined P2P_SUPPORT || defined CARDEMU_SUPPORT
#if defined CARDEMU_SUPPORT
MODE_LISTEN | TECH_PASSIVE_NFCB,
#endif // if defined CARDEMU_SUPPORT
#ifdef P2P_SUPPORT
MODE_LISTEN | TECH_PASSIVE_NFCF,
MODE_LISTEN | TECH_ACTIVE_NFCA,
MODE_LISTEN | TECH_ACTIVE_NFCF,
#endif // ifdef P2P_SUPPORT
};
/* Mode configuration according to the targeted modes of operation */
unsigned mode = 0
#ifdef CARDEMU_SUPPORT
| NXPNCI_MODE_CARDEMU
#endif // ifdef P2P_SUPPORT
#ifdef P2P_SUPPORT
| NXPNCI_MODE_P2P
#endif // ifdef CARDEMU_SUPPORT
#ifdef RW_SUPPORT
| NXPNCI_MODE_RW
#endif // ifdef RW_SUPPORT
;
#if defined P2P_SUPPORT || defined RW_SUPPORT
void NdefPull_Cb(unsigned char *pNdefMessage, unsigned short NdefMessageSize)
{
unsigned char *pNdefRecord = pNdefMessage;
NdefRecord_t NdefRecord;
unsigned char save;
if (pNdefMessage == NULL)
{
framework_Log("--- Issue during NDEF message reception (check provisioned buffer size) \n");
return;
}
while (pNdefRecord != NULL)
{
framework_Log("--- NDEF record received:\n");
NdefRecord = DetectNdefRecordType(pNdefRecord);
switch(NdefRecord.recordType)
{
case MEDIA_VCARD:
{
save = NdefRecord.recordPayload[NdefRecord.recordPayloadSize];
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = '\0';
framework_Log(" vCard:\n%s\n", NdefRecord.recordPayload);
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = save;
}
break;
case WELL_KNOWN_SIMPLE_TEXT:
{
save = NdefRecord.recordPayload[NdefRecord.recordPayloadSize];
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = '\0';
framework_Log(" Text record: %s\n", &NdefRecord.recordPayload[NdefRecord.recordPayload[0]+1]);
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = save;
}
break;
case WELL_KNOWN_SIMPLE_URI:
{
save = NdefRecord.recordPayload[NdefRecord.recordPayloadSize];
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = '\0';
framework_Log(" URI record: %s%s\n", ndef_helper_UriHead(NdefRecord.recordPayload[0]), &NdefRecord.recordPayload[1]);
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = save;
}
break;
case MEDIA_HANDOVER_WIFI:
{
unsigned char index = 0, i;
framework_Log("--- Received WIFI credentials:\n");
if ((NdefRecord.recordPayload[index] == 0x10) && (NdefRecord.recordPayload[index+1] == 0x0e)) index+= 4;
while(index < NdefRecord.recordPayloadSize)
{
if (NdefRecord.recordPayload[index] == 0x10)
{
if (NdefRecord.recordPayload[index+1] == 0x45) {framework_Log("- SSID = "); for(i=0;i<NdefRecord.recordPayload[index+3];i++) framework_Log("%c", NdefRecord.recordPayload[index+4+i]); framework_Log ("\n");}
else if (NdefRecord.recordPayload[index+1] == 0x03) framework_Log("- Authenticate Type = %s\n", ndef_helper_WifiAuth(NdefRecord.recordPayload[index+5]));
else if (NdefRecord.recordPayload[index+1] == 0x0f) framework_Log("- Encryption Type = %s\n", ndef_helper_WifiEnc(NdefRecord.recordPayload[index+5]));
else if (NdefRecord.recordPayload[index+1] == 0x27) {framework_Log("- Network key = "); for(i=0;i<NdefRecord.recordPayload[index+3];i++) framework_Log("#"); framework_Log ("\n");}
index += 4 + NdefRecord.recordPayload[index+3];
}
else continue;
}
}
break;
case WELL_KNOWN_HANDOVER_SELECT:
framework_Log(" Handover select version %d.%d\n", NdefRecord.recordPayload[0] >> 4, NdefRecord.recordPayload[0] & 0xF);
break;
case WELL_KNOWN_HANDOVER_REQUEST:
framework_Log(" Handover request version %d.%d\n", NdefRecord.recordPayload[0] >> 4, NdefRecord.recordPayload[0] & 0xF);
break;
case MEDIA_HANDOVER_BT:
print_buf(" BT Handover payload = ", NdefRecord.recordPayload, NdefRecord.recordPayloadSize);
break;
case MEDIA_HANDOVER_BLE:
print_buf(" BLE Handover payload = ", NdefRecord.recordPayload, NdefRecord.recordPayloadSize);
break;
case MEDIA_HANDOVER_BLE_SECURE:
print_buf(" BLE secure Handover payload = ", NdefRecord.recordPayload, NdefRecord.recordPayloadSize);
break;
default:
framework_Log(" Unsupported NDEF record, cannot parse\n");
break;
}
pNdefRecord = GetNextRecord(pNdefRecord);
}
framework_Log("\n");
}
#endif // if defined P2P_SUPPORT || defined RW_SUPPORT
#if defined P2P_SUPPORT || defined CARDEMU_SUPPORT
const char NDEF_MESSAGE[] = { 0xD1, // MB/ME/CF/1/IL/TNF
0x01, // TYPE LENGTH
0x07, // PAYLOAD LENTGH
'T', // TYPE
0x02, // Status
'e', 'n', // Language
'T', 'e', 's', 't' };
void NdefPush_Cb(unsigned char *pNdefRecord, unsigned short NdefRecordSize) {
framework_Log("--- NDEF Record sent\n\n");
}
#endif // if defined P2P_SUPPORT || defined CARDEMU_SUPPORT
#if defined RW_SUPPORT
#ifdef RW_RAW_EXCHANGE
void PCD_MIFARE_scenario (void)
{
#define BLK_NB_MFC 4
#define KEY_MFC 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
#define DATA_WRITE_MFC 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
bool status;
unsigned char Resp[256];
unsigned char RespSize;
/* Authenticate sector 1 with generic keys */
unsigned char Auth[] = {0x40, BLK_NB_MFC/4, 0x10, KEY_MFC};
/* Read block 4 */
unsigned char Read[] = {0x10, 0x30, BLK_NB_MFC};
/* Write block 4 */
unsigned char WritePart1[] = {0x10, 0xA0, BLK_NB_MFC};
unsigned char WritePart2[] = {0x10, DATA_WRITE_MFC};
/* Authenticate */
status = NxpNci_ReaderTagCmd(Auth, sizeof(Auth), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0))
{
framework_Log(" Authenticate sector %d failed with error 0x%02x\n", Auth[1], Resp[RespSize-1]);
return;
}
framework_Log(" Authenticate sector %d succeed\n", Auth[1]);
/* Read block */
status = NxpNci_ReaderTagCmd(Read, sizeof(Read), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0))
{
framework_Log(" Read block %d failed with error 0x%02x\n", Read[2], Resp[RespSize-1]);
return;
}
framework_Log(" Read block %d:", Read[2]); print_buf(" ", (Resp+1), RespSize-2);
/* Write block */
status = NxpNci_ReaderTagCmd(WritePart1, sizeof(WritePart1), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0))
{
framework_Log(" Write block %d failed with error 0x%02x\n", WritePart1[2], Resp[RespSize-1]);
return;
}
status = NxpNci_ReaderTagCmd(WritePart2, sizeof(WritePart2), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0))
{
framework_Log(" Write block %d failed with error 0x%02x\n", WritePart1[2], Resp[RespSize-1]);
return;
}
framework_Log(" Block %d written\n", WritePart1[2]);
/* Read block */
status = NxpNci_ReaderTagCmd(Read, sizeof(Read), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0))
{
framework_Log(" Read failed with error 0x%02x\n", Resp[RespSize-1]);
return;
}
framework_Log(" Read block %d:", Read[2]); print_buf(" ", (Resp+1), RespSize-2);
}
void PCD_ISO15693_scenario (void)
{
#define BLK_NB_ISO15693 8
#define DATA_WRITE_ISO15693 0x11, 0x22, 0x33, 0x44
bool status;
unsigned char Resp[256];
unsigned char RespSize;
unsigned char ReadBlock[] = {0x02, 0x20, BLK_NB_ISO15693};
unsigned char WriteBlock[] = {0x02, 0x21, BLK_NB_ISO15693, DATA_WRITE_ISO15693};
status = NxpNci_ReaderTagCmd(ReadBlock, sizeof(ReadBlock), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0x00))
{
framework_Log(" Read block %d failed with error 0x%02x\n", ReadBlock[2], Resp[RespSize-1]);
return;
}
framework_Log(" Read block %d:", ReadBlock[2]); print_buf(" ", (Resp+1), RespSize-2);
/* Write */
status = NxpNci_ReaderTagCmd(WriteBlock, sizeof(WriteBlock), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0))
{
framework_Log(" Write block %d failed with error 0x%02x\n", WriteBlock[2], Resp[RespSize-1]);
return;
}
framework_Log(" Block %d written\n", WriteBlock[2]);
/* Read back */
status = NxpNci_ReaderTagCmd(ReadBlock, sizeof(ReadBlock), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0x00))
{
framework_Log(" Read block %d failed with error 0x%02x\n", ReadBlock[2], Resp[RespSize-1]);
return;
}
framework_Log(" Read block %d:", ReadBlock[2]); print_buf(" ", (Resp+1), RespSize-2);
}
void PCD_ISO14443_3A_scenario (void)
{
#define BLK_NB_ISO14443_3A 5
#define DATA_WRITE_ISO14443_3A 0x11, 0x22, 0x33, 0x44
bool status;
unsigned char Resp[256];
unsigned char RespSize;
/* Read block */
unsigned char Read[] = {0x30, BLK_NB_ISO14443_3A};
/* Write block */
unsigned char Write[] = {0xA2, BLK_NB_ISO14443_3A, DATA_WRITE_ISO14443_3A};
/* Read */
status = NxpNci_ReaderTagCmd(Read, sizeof(Read), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0))
{
framework_Log(" Read block %d failed with error 0x%02x\n", Read[1], Resp[RespSize-1]);
return;
}
framework_Log(" Read block %d:", Read[1]); print_buf(" ", Resp, 4);
/* Write */
status = NxpNci_ReaderTagCmd(Write, sizeof(Write), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0))
{
framework_Log(" Write block %d failed with error 0x%02x\n", Write[1], Resp[RespSize-1]);
return;
}
framework_Log(" Block %d written\n", Write[1]);
/* Read back */
status = NxpNci_ReaderTagCmd(Read, sizeof(Read), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-1] != 0))
{
framework_Log(" Read block %d failed with error 0x%02x\n", Read[1], Resp[RespSize-1]);
return;
}
framework_Log(" Read block %d:", Read[1]); print_buf(" ", Resp, 4);
}
void PCD_ISO14443_4_scenario (void)
{
bool status;
unsigned char Resp[256];
unsigned char RespSize;
unsigned char SelectPPSE[] = {0x00, 0xA4, 0x04, 0x00, 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00};
status = NxpNci_ReaderTagCmd(SelectPPSE, sizeof(SelectPPSE), Resp, &RespSize);
if((status == NFC_ERROR) || (Resp[RespSize-2] != 0x90) || (Resp[RespSize-1] != 0x00))
{
framework_Log(" Select PPSE failed with error %02x %02x\n", Resp[RespSize-2], Resp[RespSize-1]);
return;
}
framework_Log(" Select NDEF Application succeed\n");
}
#endif // ifdef RW_RAW_EXCHANGE
void displayCardInfo(NxpNci_RfIntf_t RfIntf)
{
switch(RfIntf.Protocol){
case PROT_T1T:
case PROT_T2T:
case PROT_T3T:
case PROT_ISODEP:
framework_Log(" - POLL MODE: Remote T%dT activated\n", RfIntf.Protocol);
break;
case PROT_ISO15693:
framework_Log(" - POLL MODE: Remote ISO15693 card activated\n");
break;
case PROT_MIFARE:
framework_Log(" - POLL MODE: Remote MIFARE card activated\n");
break;
default:
framework_Log(" - POLL MODE: Undetermined target\n");
return;
}
switch(RfIntf.ModeTech) {
case (MODE_POLL | TECH_PASSIVE_NFCA):
framework_Log("\tSENS_RES = 0x%.2x 0x%.2x\n", RfIntf.Info.NFC_APP.SensRes[0], RfIntf.Info.NFC_APP.SensRes[1]);
print_buf("\tNFCID = ", RfIntf.Info.NFC_APP.NfcId, RfIntf.Info.NFC_APP.NfcIdLen);
if(RfIntf.Info.NFC_APP.SelResLen != 0) framework_Log("\tSEL_RES = 0x%.2x\n", RfIntf.Info.NFC_APP.SelRes[0]);
break;
case (MODE_POLL | TECH_PASSIVE_NFCB):
if(RfIntf.Info.NFC_BPP.SensResLen != 0) print_buf("\tSENS_RES = ", RfIntf.Info.NFC_BPP.SensRes, RfIntf.Info.NFC_BPP.SensResLen);
break;
case (MODE_POLL | TECH_PASSIVE_NFCF):
framework_Log("\tBitrate = %s\n", (RfIntf.Info.NFC_FPP.BitRate==1)?"212":"424");
if(RfIntf.Info.NFC_FPP.SensResLen != 0) print_buf("\tSENS_RES = ", RfIntf.Info.NFC_FPP.SensRes, RfIntf.Info.NFC_FPP.SensResLen);
break;
case (MODE_POLL | TECH_PASSIVE_15693):
print_buf("\tID = ", RfIntf.Info.NFC_VPP.ID, sizeof(RfIntf.Info.NFC_VPP.ID));
framework_Log("\tAFI = 0x%.2x\n", RfIntf.Info.NFC_VPP.AFI);
framework_Log("\tDSFID = 0x%.2x\n", RfIntf.Info.NFC_VPP.DSFID);
break;
default:
break;
}
}
void task_nfc_reader(NxpNci_RfIntf_t RfIntf)
{
/* For each discovered cards */
while(1){
/* Display detected card information */
displayCardInfo(RfIntf);
/* What's the detected card type ? */
switch(RfIntf.Protocol) {
case PROT_T1T:
case PROT_T2T:
case PROT_T3T:
case PROT_ISODEP:
#ifndef RW_RAW_EXCHANGE
/* Process NDEF message read */
NxpNci_ProcessReaderMode(RfIntf, READ_NDEF);
#ifdef RW_NDEF_WRITING
RW_NDEF_SetMessage ((unsigned char *) NDEF_MESSAGE, sizeof(NDEF_MESSAGE), *NdefPush_Cb);
/* Process NDEF message write */
NxpNci_ReaderReActivate(&RfIntf);
NxpNci_ProcessReaderMode(RfIntf, WRITE_NDEF);
#endif // RW_NDEF_WRITING
#else // ifndef RW_RAW_EXCHANGE
if (RfIntf.Protocol == PROT_ISODEP)
{
PCD_ISO14443_4_scenario();
}
else if (RfIntf.Protocol == PROT_T2T)
{
PCD_ISO14443_3A_scenario();
}
#endif // ifndef RW_RAW_EXCHANGE
break;
case PROT_ISO15693:
#ifdef RW_RAW_EXCHANGE
/* Run dedicated scenario to demonstrate ISO15693 card management */
PCD_ISO15693_scenario();
#endif // ifdef RW_RAW_EXCHANGE
break;
case PROT_MIFARE:
#ifdef RW_RAW_EXCHANGE
/* Run dedicated scenario to demonstrate MIFARE card management */
PCD_MIFARE_scenario();
#endif // ifdef RW_RAW_EXCHANGE
break;
default:
break;
}
/* If more cards (or multi-protocol card) were discovered (only same technology are supported) select next one */
if(RfIntf.MoreTags) {
if(NxpNci_ReaderActivateNext(&RfIntf) == NFC_ERROR) break;
}
/* Otherwise leave */
else break;
}
/* Wait for card removal */
NxpNci_ProcessReaderMode(RfIntf, PRESENCE_CHECK);
framework_Log("CARD REMOVED\n");
/* Restart discovery loop */
NxpNci_StopDiscovery();
NxpNci_StartDiscovery(DiscoveryTechnologies,sizeof(DiscoveryTechnologies));
}
#endif // if defined RW_SUPPORT
#if defined CARDEMU_SUPPORT
#ifdef CARDEMU_RAW_EXCHANGE
void PICC_ISO14443_4_scenario (void)
{
unsigned char OK[] = {0x90, 0x00};
unsigned char Cmd[256];
unsigned char CmdSize;
while (1)
{
if(NxpNci_CardModeReceive(Cmd, &CmdSize) == NFC_SUCCESS)
{
if ((CmdSize >= 2) && (Cmd[0] == 0x00))
{
switch (Cmd[1])
{
case 0xA4:
framework_Log("Select File received\n");
break;
case 0xB0:
framework_Log("Read Binary received\n");
break;
case 0xD0:
framework_Log("Write Binary received\n");
break;
default:
break;
}
NxpNci_CardModeSend(OK, sizeof(OK));
}
}
else
{
framework_Log("End of transaction\n");
return;
}
}
}
#endif // if defined CARDEMU_SUPPORT
#endif
void task_nfc(void)
{
NxpNci_RfIntf_t RfInterface;
#ifdef CARDEMU_SUPPORT
/* Register NDEF message to be sent to remote reader */
T4T_NDEF_EMU_SetMessage((unsigned char *) NDEF_MESSAGE, sizeof(NDEF_MESSAGE), *NdefPush_Cb);
#endif // if defined CARDEMU_SUPPORT
#ifdef P2P_SUPPORT
/* Register NDEF message to be sent to remote peer */
P2P_NDEF_SetMessage((unsigned char *) NDEF_MESSAGE, sizeof(NDEF_MESSAGE), *NdefPush_Cb);
/* Register callback for reception of NDEF message from remote peer */
P2P_NDEF_RegisterPullCallback(*NdefPull_Cb);
#endif // if defined P2P_SUPPORT
#ifdef RW_SUPPORT
/* Register callback for reception of NDEF message from remote cards */
RW_NDEF_RegisterPullCallback(*NdefPull_Cb);
#endif // if defined RW_SUPPORT
/* Open connection to NXPNCI device */
if (NxpNci_Connect() == NFC_ERROR) {
framework_Log("Error: cannot connect to NXPNCI device\n");
return;
}
if (NxpNci_ConfigureSettings() == NFC_ERROR) {
framework_Log("Error: cannot configure NXPNCI settings\n");
return;
}
if (NxpNci_ConfigureMode(mode) == NFC_ERROR)
{
framework_Log("Error: cannot configure NXPNCI\n");
return;
}
/* Start Discovery */
if (NxpNci_StartDiscovery(DiscoveryTechnologies,sizeof(DiscoveryTechnologies)) != NFC_SUCCESS)
{
framework_Log("Error: cannot start discovery\n");
return;
}
while(1)
{
framework_Log("\nWAITING FOR DEVICE DISCOVERY\n");
/* Wait until a peer is discovered */
while(NxpNci_WaitForDiscoveryNotification(&RfInterface) != NFC_SUCCESS);
#ifdef CARDEMU_SUPPORT
/* Is activated from remote T4T ? */
if ((RfInterface.Interface == INTF_ISODEP) && ((RfInterface.ModeTech & MODE_MASK) == MODE_LISTEN))
{
framework_Log(" - LISTEN MODE: Activated from remote Reader\n");
#ifndef CARDEMU_RAW_EXCHANGE
NxpNci_ProcessCardMode(RfInterface);
#else
PICC_ISO14443_4_scenario();
#endif
framework_Log("READER DISCONNECTED\n");
}
else
#endif
#ifdef P2P_SUPPORT
/* Is activated from remote T4T ? */
if (RfInterface.Interface == INTF_NFCDEP)
{
if ((RfInterface.ModeTech & MODE_LISTEN) == MODE_LISTEN) framework_Log(" - P2P TARGET MODE: Activated from remote Initiator\n");
else framework_Log(" - P2P INITIATOR MODE: Remote Target activated\n");
/* Process with SNEP for NDEF exchange */
NxpNci_ProcessP2pMode(RfInterface);
framework_Log("PEER LOST\n");
}
else
#endif
#ifdef RW_SUPPORT
if ((RfInterface.ModeTech & MODE_MASK) == MODE_POLL)
{
task_nfc_reader(RfInterface);
}
else
#endif
{
framework_Log("WRONG DISCOVERY\n");
}
}
}
......@@ -457,7 +457,7 @@ PairingManager::pairingLinkTypeStrings()
static QStringList list;
int i = 0;
if (!list.size()) {
#if defined QGC_ENABLE_NFC || defined QGC_ENABLE_QTNFC
#if defined QGC_ENABLE_QTNFC
list += tr("NFC");
_nfcIndex = i++;
#endif
......@@ -501,14 +501,14 @@ PairingManager::startMicrohardPairing()
void
PairingManager::stopPairing()
{
#if defined QGC_ENABLE_NFC || defined QGC_ENABLE_QTNFC
#if defined QGC_ENABLE_QTNFC
pairingNFC.stop();
#endif
_stopUpload();
setPairingStatus(PairingIdle, "");
}
#if defined QGC_ENABLE_NFC || defined QGC_ENABLE_QTNFC
#if defined QGC_ENABLE_QTNFC
//-----------------------------------------------------------------------------
void
PairingManager::startNFCScan()
......
......@@ -20,9 +20,6 @@
#include "QGCToolbox.h"
#include "QGCLoggingCategory.h"
#include "Fact.h"
#if defined QGC_ENABLE_NFC
#include "PairingNFC.h"
#endif
#if defined QGC_ENABLE_QTNFC
#include "QtNFC.h"
#endif
......@@ -79,7 +76,7 @@ public:
Q_INVOKABLE void connectToPairedDevice (QString name);
Q_INVOKABLE void removePairedDevice (QString name);
#if defined QGC_ENABLE_NFC || defined QGC_ENABLE_QTNFC
#if defined defined QGC_ENABLE_QTNFC
Q_INVOKABLE void startNFCScan();
#endif
#if QGC_GST_MICROHARD_ENABLED
......@@ -150,7 +147,7 @@ private:
QString _pairingCacheFile (QString uavName);
void _updatePairedDeviceNameList ();
#if defined QGC_ENABLE_NFC || defined QGC_ENABLE_QTNFC
#if defined QGC_ENABLE_QTNFC
PairingNFC pairingNFC;
#endif
};
/****************************************************************************
*
* (c) 2019 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "PairingManager.h"
#include "PairingNFC.h"
#include "QGCApplication.h"
#include <QSoundEffect>
QGC_LOGGING_CATEGORY(PairingNFCLog, "PairingNFCLog")
extern "C" {
#include <TML/inc/tool.h>
#include <NfcTask/inc/ndef_helper.h>
//-----------------------------------------------------------------------------
void logmsg(char *buf)
{
QString s = buf;
s.replace("\n", "");
qCDebug(PairingNFCLog) << s;
}
//-----------------------------------------------------------------------------
void NdefPull_Cb(unsigned char *pNdefMessage, unsigned short NdefMessageSize)
{
Q_UNUSED(NdefMessageSize);
unsigned char *pNdefRecord = pNdefMessage;
NdefRecord_t NdefRecord;
unsigned char save;
if (!pNdefMessage)
{
qCDebug(PairingNFCLog) << "Issue during NDEF message reception (check provisioned buffer size)";
return;
}
QSoundEffect _nfcSound;
_nfcSound.setSource(QUrl::fromUserInput("qrc:/auterion/wav/beep.wav"));
_nfcSound.setVolume(0.9);
_nfcSound.play();
while (pNdefRecord)
{
qCDebug(PairingNFCLog) << "NDEF record received";
NdefRecord = DetectNdefRecordType(pNdefRecord);
switch(NdefRecord.recordType)
{
case MEDIA_VCARD:
save = NdefRecord.recordPayload[NdefRecord.recordPayloadSize];
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = '\0';
qCDebug(PairingNFCLog) << " vCard: " << reinterpret_cast<char *>(NdefRecord.recordPayload);
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = save;
break;
case WELL_KNOWN_SIMPLE_TEXT:
{
save = NdefRecord.recordPayload[NdefRecord.recordPayloadSize];
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = '\0';
QString text = reinterpret_cast<char *>(&NdefRecord.recordPayload[NdefRecord.recordPayload[0]+1]);
qCDebug(PairingNFCLog) << " Text: " << text;
qgcApp()->toolbox()->pairingManager()->jsonReceived(text);
NdefRecord.recordPayload[NdefRecord.recordPayloadSize] = save;
break;
}
default:
qCDebug(PairingNFCLog) << " Unsupported NDEF record, cannot parse";
break;
}
pNdefRecord = GetNextRecord(pNdefRecord);
}
}
//-----------------------------------------------------------------------------
}
// Discovery loop configuration according to the targeted modes of operation
static unsigned char discoveryTechnologies[] = {
MODE_POLL | TECH_PASSIVE_NFCA,
MODE_POLL | TECH_PASSIVE_NFCF,
MODE_POLL | TECH_PASSIVE_NFCB,
MODE_POLL | TECH_PASSIVE_15693,
};
//-----------------------------------------------------------------------------
PairingNFC::PairingNFC()
{
}
//-----------------------------------------------------------------------------
void PairingNFC::start()
{
if (!isRunning()) {
_exitThread = false;
QThread::start();
}
}
//-----------------------------------------------------------------------------
void PairingNFC::stop()
{
if (isRunning()) {
_exitThread = true;
}
}
//-----------------------------------------------------------------------------
void PairingNFC::run()
{
NxpNci_RfIntf_t RfInterface;
// Register callback for reception of NDEF message from remote cards
RW_NDEF_RegisterPullCallback(reinterpret_cast<void*>(*NdefPull_Cb));
// Open connection to NXPNCI device
if (NxpNci_Connect() == NFC_ERROR) {
qCDebug(PairingNFCLog) << "Error: cannot connect to NXPNCI device";
return;
}
if (NxpNci_ConfigureSettings() == NFC_ERROR) {
qCDebug(PairingNFCLog) << "Error: cannot configure NXPNCI settings";
return;
}
if (NxpNci_ConfigureMode(NXPNCI_MODE_RW) == NFC_ERROR)
{
qCDebug(PairingNFCLog) << "Error: cannot configure NXPNCI";
return;
}
// Start Discovery
if (NxpNci_StartDiscovery(discoveryTechnologies,sizeof(discoveryTechnologies)) != NFC_SUCCESS)
{
qCDebug(PairingNFCLog) << "Error: cannot start discovery";
return;
}
while(!_exitThread)
{
qCDebug(PairingNFCLog) << "Waiting for NFC connection";
qgcApp()->toolbox()->pairingManager()->setStatusMessage(PairingManager::PairingActive, tr("Waiting for NFC connection"));
// Wait until a peer is discovered
while(NxpNci_WaitForDiscoveryNotification(&RfInterface) != NFC_SUCCESS);
if ((RfInterface.ModeTech & MODE_MASK) == MODE_POLL)
{
task_nfc_reader(RfInterface);
}
else
{
qCDebug(PairingNFCLog) << "Wrong discovery";
}
}
qgcApp()->toolbox()->pairingManager()->setStatusMessage(PairingManager::PairingIdle, "");
qCDebug(PairingNFCLog) << "NFC: Stop";
}
//-----------------------------------------------------------------------------
void PairingNFC::task_nfc_reader(NxpNci_RfIntf_t RfIntf)
{
qgcApp()->toolbox()->pairingManager()->setStatusMessage(PairingManager::PairingActive, tr("Device detected"));
qCDebug(PairingNFCLog) << "NFC: Device detected";
// For each discovered cards
while(!_exitThread) {
// What's the detected card type ?
switch(RfIntf.Protocol) {
case PROT_T1T:
case PROT_T2T:
case PROT_T3T:
case PROT_ISODEP:
// Process NDEF message read
NxpNci_ProcessReaderMode(RfIntf, READ_NDEF);
break;
case PROT_ISO15693:
break;
case PROT_MIFARE:
break;
default:
break;
}
// If more cards (or multi-protocol card) were discovered (only same technology are supported) select next one
if (RfIntf.MoreTags) {
if (NxpNci_ReaderActivateNext(&RfIntf) == NFC_ERROR)
break;
}
// Otherwise leave
else
break;
}
// Wait for card removal
NxpNci_ProcessReaderMode(RfIntf, PRESENCE_CHECK);
qgcApp()->toolbox()->pairingManager()->setStatusMessage(PairingManager::PairingActive, tr("Device removed"));
qCDebug(PairingNFCLog) << "NFC device removed";
// Restart discovery loop
NxpNci_StopDiscovery();
NxpNci_StartDiscovery(discoveryTechnologies, sizeof(discoveryTechnologies));
}
//-----------------------------------------------------------------------------
/****************************************************************************
*
* (c) 2019 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include <QObject>
#include <QThread>
#include "QGCLoggingCategory.h"
extern "C" {
#include <NfcLibrary/inc/Nfc.h>
}
Q_DECLARE_LOGGING_CATEGORY(PairingNFCLog)
class PairingNFC : public QThread
{
Q_OBJECT
public:
PairingNFC();
virtual void start();
virtual void stop();
signals:
void parsePairingJson(QString json);
private:
bool _exitThread = false; ///< true: signal thread to exit
// Override from QThread
virtual void run(void);
void task_nfc_reader(NxpNci_RfIntf_t RfIntf);
};
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#ifndef FRAMEWORK_ALLOCATOR_H
#define FRAMEWORK_ALLOCATOR_H
#include <stddef.h>
void* framework_AllocMem(size_t size);
void framework_FreeMem(void *ptr);
#endif //ndef FRAMEWORK_ALLOCATOR_H
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#ifndef FRAMEWORK_CONTAINER_H
#define FRAMEWORK_CONTAINER_H
#include "TML/inc/framework_Interface.h"
typedef enum CONTAINER_STATUS
{
CONTAINER_SUCCESS,
CONTAINER_FAILED,
CONTAINER_INVALID_PARAM,
CONTAINER_INVALID_CONTAINER
}CONTAINER_STATUS;
CONTAINER_STATUS container_create(void** lContainer, uint32_t size);
CONTAINER_STATUS container_delete(void* lContainer);
CONTAINER_STATUS container_add(void* pContainer, void* _ptr);
CONTAINER_STATUS container_set(void* pContainer, uint32_t index,void*_ptr, void** _old);
CONTAINER_STATUS container_remove(void* pContainer, uint32_t index, void** _old);
CONTAINER_STATUS container_get(void* pContainer, uint32_t index, void** _out);
CONTAINER_STATUS container_size(void* pContainer, uint32_t* size);
CONTAINER_STATUS container_clear(void* pContainer);
CONTAINER_STATUS container_flushMallocedContent(void* pContainer);
CONTAINER_STATUS container_removePtr(void* pContainer, void* ref, void** out);
#endif /* FRAMEWORK_CONTAINER_H*/
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#ifndef FRAMEWORK_INTERFACE_H
#define FRAMEWORK_INTERFACE_H
//typedef unsigned long long uint64_t;
#include <stdint.h>
typedef enum _eResult
{
FRAMEWORK_SUCCESS,
FRAMEWORK_FAILED
}eResult;
/**
* Create a thread using the given function in parameters
* @param threadHandle Obfuscated thread handle allocated by this function.
* @param threadedFunc function to start in new thread. ( void* myFunc(void* ctx) )
* @param ctx Parameters given to threadedFunc.
* @return SUCCESS if no error.
*/
eResult framework_CreateThread(void** threadHandle,void *(*threadedFunc)(void*),void *ctx);
/**
* Wait until the given thread finish to run.
* @param threadHandle Obfuscated thread handle allocated by framework_CreateThread()
*/
void framework_JoinThread(void* threadHandle);
/**
* Delete the given thread. NOTE : framework_JoinThread() will be called before this function. So
* the Thread is already stopped.
* @param threadHandle Obfuscated thread handle allocated by framework_CreateThread()
*/
void framework_DeleteThread(void* threadHandle);
/**
* Return the calling thread ID.
* @return thread id.
*/
void* framework_GetCurrentThreadId();
/**
* Get the thread id of the given thread handle.
* @param threadHandle Obfuscated thread handle allocated by framework_CreateThread()
* @return thread id.
*/
void* framework_GetThreadId(void* threadHandle);
/**
* Create a mutex object. To gain performances, do not implement this function using interprocess
* lock mechanism such as Semaphore.
* @param mutexHandle Obfuscated mutex handle allocated by this function.
* @return SUCCESS if no error.
*/
eResult framework_CreateMutex(void** mutexHandle);
/**
* Lock the mutex.
* @param mutexHandle Obfuscated mutex handle allocated by framework_CreateMutex().
*/
void framework_LockMutex(void* mutexHandle);
/**
* Unlock the mutex
* @param mutexHandle Obfuscated mutex handle allocated by framework_CreateMutex().
*/
void framework_UnlockMutex(void* mutexHandle);
/**
* Block the current thread until wake up by framework_NotifyMutex().
* The mutex need to be locked before blocking the thread. (needLock parameter can be used)
* @param mutexHandle Obfuscated mutex handle allocated by framework_CreateMutex().
* @param needLock Indicate if the mutex need to be locked internaly or not. This avoid to call lock();wait();unlock();
*/
void framework_WaitMutex(void* mutexHandle,uint8_t needLock);
/**
* Wake up a thread blocked by the mutex. The mutex must be locked before waking up another thread.
* The mutex need to be locked before waking up a thread. (needLock parameter can be used)
* @param mutexHandle Obfuscated mutex handle allocated by framework_CreateMutex().
* @param needLock Indicate if the mutex need to be locked internaly or not. This avoid to call lock();wait();unlock();
*/
void framework_NotifyMutex(void* mutexHandle,uint8_t needLock);
/**
* Delete the mutex. If the mutex is locked, any locked thread will be unlocked.
* @param mutexHandle Obfuscated mutex handle allocated by framework_CreateMutex().
*/
void framework_DeleteMutex(void* mutexHandle);
/**
* Cause the calling thread to sleep until ms milliseconds elapsed.
* @param ms Milliseconds to wait until wakeup.
*/
void framework_MilliSleep(uint32_t ms);
// **************************************** Generic/Portable function.
/**
* Create a Semaphore. This semaphore have a counter of 1.
* This implementation of Semaphore is supposed to be generic. It uses previous Mutex API.
* There is no need to reimplement it until you have a good reason.
* @param semaphoreHandle Obfuscated semaphore handle allocated by this function.
* @return
*/
eResult framework_CreateSemaphore(void** semaphoreHandle);
/**
* Wait semaphore. Block until a PostSemaphore get called.
* @param semaphoreHandle Obfuscated semaphore handle allocated by framework_CreateSemaphore();
*/
void framework_WaitSemaphore(void* semaphoreHandle);
/**
* Post semaphore. Unblock any waiting semaphore. If nobody wait for this semaphore, the next "waiter"
* will not be blocked.
* @param semaphoreHandle Obfuscated semaphore handle allocated by framework_CreateSemaphore();
*/
void framework_PostSemaphore(void* semaphoreHandle);
/**
* @param semaphoreHandle Obfuscated semaphore handle allocated by framework_CreateSemaphore();
*/
void framework_DeleteSemaphore(void* semaphoreHandle);
#endif // ndef FRAMEWORK_INTERFACE_H
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#ifndef MAP_H
#define MAP_H
typedef enum STATUS
{
SUCCESS,
FAILED,
NOT_FOUND,
INVALID_MAP,
INVALID_PARAM,
ALREADY_EXISTS
}STATUS;
STATUS map_create(void ** map);
STATUS map_destroy(void* map);
STATUS map_add(void * map, void* id, void* object);
STATUS map_remove(void* map, void* id);
STATUS map_get(void* map, void* id, void ** object);
STATUS map_getAll(void* map, void ** elements, int * lenght);
#endif /*MAP_H*/
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#ifndef FRAMEWORK_PARCEL_H
#define FRAMEWORK_PARCEL_H
#include "TML/inc/framework_Interface.h"
void framework_ParcelCreate(void **parcel);
void framework_ParcelDelete(void *parcel);
uint8_t framework_ParcelReadByte(void *parcel);
void framework_ParcelWriteByte(void *parcel,uint8_t i);
uint16_t framework_ParcelReadShort(void *parcel);
void framework_ParcelWriteShort(void *parcel,uint16_t i);
uint32_t framework_ParcelReadInt32(void *parcel);
void framework_ParcelWriteInt32(void *parcel,uint32_t i);
uint64_t framework_ParcelReadInt64(void *parcel);
void framework_ParcelWriteInt64(void *parcel,uint64_t i);
float framework_ParcelReadFloat(void *parcel);
void framework_ParcelWriteFloat(void *parcel,float f);
double framework_ParcelReadDouble(void *parcel);
void framework_ParcelWriteDouble(void *parcel,double d);
const char* framework_ParcelReadString(void *parcel);
void framework_ParcelWriteString(void *parcel,const char* s);
void framework_ParcelReadRaw(void *parcel,void* outBuffer, uint32_t len);
void framework_ParcelWriteRaw(void *parcel,const void* buffer, uint32_t len);
const uint8_t* framework_ParcelDataAtCurrentPosition(void *parcel);
uint32_t framework_ParcelGetRemainingDataSize(void *parcel);
const uint8_t *framework_ParcelGetData(void *parcel);
uint32_t framework_ParcelGetSize(void *parcel);
void framework_ParcelSetData(void *parcel,const uint8_t* data,uint32_t size);
void framework_ParcelRewind(void *parcel);
void framework_ParcelForward(void *parcel,uint32_t nbBytes);
void framework_ParcelClear(void *parcel);
void framework_ParcelSerialize(void *dstParcel,void *srcParcel);
void framework_ParcelDeserialize(void *dstParcel,void *srcParcel);
#endif // ndef FRAMEWORK_PARCEL_H
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#ifndef FRAMEWORK_TIMER_H
#define FRAMEWORK_TIMER_H
#include "TML/inc/framework_Interface.h"
typedef void (framework_TimerCallBack)(void*);
void framework_TimerCreate(void **timer);
void framework_TimerStart(void *timer,uint32_t delay,framework_TimerCallBack *cb,void *usercontext);
void framework_TimerStop(void *timer);
void framework_TimerDelete(void *timer);
#endif // ndef FRAMEWORK_TIMER_H
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include "TML/inc/framework_Interface.h"
#include <stdlib.h>
/**
* Internal function, log a buffer to log output as Hexadecimal + ASCII display.
* @param buffer
* @param size
*/
void HexDump(const void * buffer, uint32_t size);
void framework_Error(const char* format, ...);
/*******************************************************
HIDAPI - Multi-Platform library for
communication with HID devices.
Alan Ott
Signal 11 Software
8/22/2009
Copyright 2009, All Rights Reserved.
At the discretion of the user of this library,
this software may be licensed under the terms of the
GNU Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution.
These files may also be found in the public source
code repository located at:
http://github.com/signal11/hidapi .
********************************************************/
/** @file
* @defgroup API hidapi API
*/
#ifndef HIDAPI_H__
#define HIDAPI_H__
#include <wchar.h>
#ifdef HID_API_EXPORTS
#define HID_API_EXPORT __declspec(dllexport)
#define HID_API_CALL
#else
#define HID_API_EXPORT /**< API export macro */
#define HID_API_CALL /**< API call macro */
#endif
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
#ifdef __cplusplus
extern "C" {
#endif
struct hid_device_;
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
/** hidapi info structure */
struct hid_device_info {
/** Platform-specific device path */
char *path;
/** Device Vendor ID */
unsigned short vendor_id;
/** Device Product ID */
unsigned short product_id;
/** Serial Number */
wchar_t *serial_number;
/** Device Release Number in binary-coded decimal,
also known as Device Version Number */
unsigned short release_number;
/** Manufacturer String */
wchar_t *manufacturer_string;
/** Product string */
wchar_t *product_string;
/** Usage Page for this Device/Interface
(Windows/Mac only). */
unsigned short usage_page;
/** Usage for this Device/Interface
(Windows/Mac only).*/
unsigned short usage;
/** The USB interface which this logical device
represents. Valid on both Linux implementations
in all cases, and valid on the Windows implementation
only if the device contains more than one interface. */
int interface_number;
/** Pointer to the next device */
struct hid_device_info *next;
};
/** @brief Initialize the HIDAPI library.
This function initializes the HIDAPI library. Calling it is not
strictly necessary, as it will be called automatically by
hid_enumerate() and any of the hid_open_*() functions if it is
needed. This function should be called at the beginning of
execution however, if there is a chance of HIDAPI handles
being opened by different threads simultaneously.
@ingroup API
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_init(void);
/** @brief Finalize the HIDAPI library.
This function frees all of the static data associated with
HIDAPI. It should be called at the end of execution to avoid
memory leaks.
@ingroup API
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_exit(void);
/** @brief Enumerate the HID Devices.
This function returns a linked list of all the HID devices
attached to the system which match vendor_id and product_id.
If @p vendor_id and @p product_id are both set to 0, then
all HID devices will be returned.
@ingroup API
@param vendor_id The Vendor ID (VID) of the types of device
to open.
@param product_id The Product ID (PID) of the types of
device to open.
@returns
This function returns a pointer to a linked list of type
struct #hid_device, containing information about the HID devices
attached to the system, or NULL in the case of failure. Free
this linked list by calling hid_free_enumeration().
*/
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
/** @brief Free an enumeration Linked List
This function frees a linked list created by hid_enumerate().
@ingroup API
@param devs Pointer to a list of struct_device returned from
hid_enumerate().
*/
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
/** @brief Open a HID device using a Vendor ID (VID), Product ID
(PID) and optionally a serial number.
If @p serial_number is NULL, the first device with the
specified VID and PID is opened.
@ingroup API
@param vendor_id The Vendor ID (VID) of the device to open.
@param product_id The Product ID (PID) of the device to open.
@param serial_number The Serial Number of the device to open
(Optionally NULL).
@returns
This function returns a pointer to a #hid_device object on
success or NULL on failure.
*/
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, wchar_t *serial_number);
/** @brief Open a HID device by its path name.
The path name be determined by calling hid_enumerate(), or a
platform-specific path name can be used (eg: /dev/hidraw0 on
Linux).
@ingroup API
@param path The path name of the device to open
@returns
This function returns a pointer to a #hid_device object on
success or NULL on failure.
*/
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
/** @brief Write an Output report to a HID device.
The first byte of @p data[] must contain the Report ID. For
devices which only support a single report, this must be set
to 0x0. The remaining bytes contain the report data. Since
the Report ID is mandatory, calls to hid_write() will always
contain one more byte than the report contains. For example,
if a hid report is 16 bytes long, 17 bytes must be passed to
hid_write(), the Report ID (or 0x0, for devices with a
single report), followed by the report data (16 bytes). In
this example, the length passed in would be 17.
hid_write() will send the data on the first OUT endpoint, if
one exists. If it does not, it will send the data through
the Control Endpoint (Endpoint 0).
@ingroup API
@param device A device handle returned from hid_open().
@param data The data to send, including the report number as
the first byte.
@param length The length in bytes of the data to send.
@returns
This function returns the actual number of bytes written and
-1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
/** @brief Read an Input report from a HID device with timeout.
Input reports are returned
to the host through the INTERRUPT IN endpoint. The first byte will
contain the Report number if the device uses numbered reports.
@ingroup API
@param device A device handle returned from hid_open().
@param data A buffer to put the read data into.
@param length The number of bytes to read. For devices with
multiple reports, make sure to read an extra byte for
the report number.
@param milliseconds timeout in milliseconds or -1 for blocking wait.
@returns
This function returns the actual number of bytes read and
-1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
/** @brief Read an Input report from a HID device.
Input reports are returned
to the host through the INTERRUPT IN endpoint. The first byte will
contain the Report number if the device uses numbered reports.
@ingroup API
@param device A device handle returned from hid_open().
@param data A buffer to put the read data into.
@param length The number of bytes to read. For devices with
multiple reports, make sure to read an extra byte for
the report number.
@returns
This function returns the actual number of bytes read and
-1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
/** @brief Set the device handle to be non-blocking.
In non-blocking mode calls to hid_read() will return
immediately with a value of 0 if there is no data to be
read. In blocking mode, hid_read() will wait (block) until
there is data to read before returning.
Nonblocking can be turned on and off at any time.
@ingroup API
@param device A device handle returned from hid_open().
@param nonblock enable or not the nonblocking reads
- 1 to enable nonblocking
- 0 to disable nonblocking.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
/** @brief Send a Feature report to the device.
Feature reports are sent over the Control endpoint as a
Set_Report transfer. The first byte of @p data[] must
contain the Report ID. For devices which only support a
single report, this must be set to 0x0. The remaining bytes
contain the report data. Since the Report ID is mandatory,
calls to hid_send_feature_report() will always contain one
more byte than the report contains. For example, if a hid
report is 16 bytes long, 17 bytes must be passed to
hid_send_feature_report(): the Report ID (or 0x0, for
devices which do not use numbered reports), followed by the
report data (16 bytes). In this example, the length passed
in would be 17.
@ingroup API
@param device A device handle returned from hid_open().
@param data The data to send, including the report number as
the first byte.
@param length The length in bytes of the data to send, including
the report number.
@returns
This function returns the actual number of bytes written and
-1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
/** @brief Get a feature report from a HID device.
Make sure to set the first byte of @p data[] to the Report
ID of the report to be read. Make sure to allow space for
this extra byte in @p data[].
@ingroup API
@param device A device handle returned from hid_open().
@param data A buffer to put the read data into, including
the Report ID. Set the first byte of @p data[] to the
Report ID of the report to be read.
@param length The number of bytes to read, including an
extra byte for the report ID. The buffer can be longer
than the actual report.
@returns
This function returns the number of bytes read and
-1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
/** @brief Close a HID device.
@ingroup API
@param device A device handle returned from hid_open().
*/
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
/** @brief Get The Manufacturer String from a HID device.
@ingroup API
@param device A device handle returned from hid_open().
@param string A wide string buffer to put the data into.
@param maxlen The length of the buffer in multiples of wchar_t.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
/** @brief Get The Product String from a HID device.
@ingroup API
@param device A device handle returned from hid_open().
@param string A wide string buffer to put the data into.
@param maxlen The length of the buffer in multiples of wchar_t.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
/** @brief Get The Serial Number String from a HID device.
@ingroup API
@param device A device handle returned from hid_open().
@param string A wide string buffer to put the data into.
@param maxlen The length of the buffer in multiples of wchar_t.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
/** @brief Get a string from a HID device, based on its string index.
@ingroup API
@param device A device handle returned from hid_open().
@param string_index The index of the string to get.
@param string A wide string buffer to put the data into.
@param maxlen The length of the buffer in multiples of wchar_t.
@returns
This function returns 0 on success and -1 on error.
*/
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
/** @brief Get a string describing the last error which occurred.
@ingroup API
@param device A device handle returned from hid_open().
@returns
This function returns a string containing the last error
which occurred or NULL if none has occurred.
*/
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device);
#ifdef __cplusplus
}
#endif
#endif
/*
* @brief LPC USB serial I/O interface definition
*
* @note
* Copyright(C) NXP Semiconductors, 2013
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#ifndef __LPCUSBSIO_H
#define __LPCUSBSIO_H
#include <stdint.h>
#if defined(LPCUSBSIO_EXPORTS)
#define LPCUSBSIO_API __declspec(dllexport)
#elif defined(LPCUSBSIO_IMPORTS)
#define LPCUSBSIO_API __declspec(dllimport)
#else
#define LPCUSBSIO_API
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup LPCUSBSIO_I2C_API LPC USB serial I/O (LPCUSBSIO) I2C API interface
* <b>API description</b><br>
* The LPCUSBSIO-I2C APIs can be divided into two broad sets. The first set consists of
* five control APIs and the second set consists of two data transferring APIs. On error
* most APIs return an LPCUSBSIO_ERR_T code. Application code can call I2C_Error() routine
* to get user presentable uni-code string corresponding to the last error.
* <br>
* The current version of LPCUSBSIO allows communicating with I2C slave devices only.
*
* @{
*/
#define MAX_WRITE_LENGTH 52 /* Shall be a multiple of 4 */
#define MAX_READ_LENGTH (HID_I2C_PACKET_SZ - sizeof(HID_I2C_IN_REPORT_T))
/** NXP USB-IF vendor ID. */
#define LPCUSBSIO_VID 0x1FC9
/** USB-IF product ID for LPCUSBSIO devices. */
#define LPCUSBSIO_PID 0x0088
/** Read time-out value in milliseconds used by the library. If a response is not received
*
*/
//AL : change default timeout 500 ms to INIFNITE timeout
#define LPCUSBSIO_READ_TMO -1
/** I2C_CFG_OPTIONS Configuration options flags used by I2C_PORTCONFIG_T
* @{
*/
/** Generate start condition before transmitting */
#define I2C_CONFIG_OPTIONS_FORCE_INIT 0x00000001
/** @} */
/** I2C_IO_OPTIONS Options to I2C_DeviceWrite & I2C_DeviceRead routines
* @{
*/
/** Generate start condition before transmitting */
#define I2C_TRANSFER_OPTIONS_START_BIT 0x0001
/** Generate stop condition at the end of transfer */
#define I2C_TRANSFER_OPTIONS_STOP_BIT 0x0002
/** Continue transmitting data in bulk without caring about Ack or nAck from device if this bit is
* not set. If this bit is set then stop transmitting the data in the buffer when the device nAcks
*/
#define I2C_TRANSFER_OPTIONS_BREAK_ON_NACK 0x0004
/** lpcusbsio-I2C generates an ACKs for every byte read. Some I2C slaves require the I2C
master to generate a nACK for the last data byte read. Setting this bit enables working with such
I2C slaves */
#define I2C_TRANSFER_OPTIONS_NACK_LAST_BYTE 0x0008
/* Setting this bit would mean that the address field should be ignored.
* The address is either a part of the data or this is a special I2C
* frame that doesn't require an address. For example when transferring a
* frame greater than the USB_HID packet this option can be used.
*/
#define I2C_TRANSFER_OPTIONS_NO_ADDRESS 0x00000040
/** @} */
/** I2C_FAST_TRANSFER_OPTIONS I2C master faster transfer options
* @{
*/
/** Ignore NACK during data transfer. By default transfer is aborted. */
#define I2C_FAST_XFER_OPTION_IGNORE_NACK 0x01
/** ACK last byte received. By default we NACK last byte we receive per I2C specification. */
#define I2C_FAST_XFER_OPTION_LAST_RX_ACK 0x02
/**
* @}
*/
/******************************************************************************
* Type defines
******************************************************************************/
/** @brief Handle type */
typedef void *LPC_HANDLE;
/** @brief Error types returned by LPCUSBSIO APIs */
typedef enum LPCUSBSIO_ERR_t {
/** All API return positive number for success */
LPCUSBSIO_OK = 0,
/** HID library error. */
LPCUSBSIO_ERR_HID_LIB = -1,
/** Handle passed to the function is invalid. */
LPCUSBSIO_ERR_BAD_HANDLE = -2,
/* Errors from hardware I2C interface*/
/** Fatal error occurred */
LPCUSBSIO_ERR_FATAL = -0x11,
/** Transfer aborted due to NACK */
LPCUSBSIO_ERR_I2C_NAK = -0x12,
/** Transfer aborted due to bus error */
LPCUSBSIO_ERR_I2C_BUS = -0x13,
/** NAK received after SLA+W or SLA+R */
LPCUSBSIO_ERR_I2C_SLAVE_NAK = -0x14,
/** I2C bus arbitration lost to other master */
LPCUSBSIO_ERR_I2C_ARBLOST = -0x15,
/* Errors from firmware's HID-I2C bridge module */
/** Transaction timed out */
LPCUSBSIO_ERR_TIMEOUT = -0x20,
/** Invalid HID_I2C Request or Request not supported in this version. */
LPCUSBSIO_ERR_INVALID_CMD = -0x21,
/** Invalid parameters are provided for the given Request. */
LPCUSBSIO_ERR_INVALID_PARAM = -0x22,
/** Partial transfer completed. */
LPCUSBSIO_ERR_PARTIAL_DATA = -0x23,
/** Request has been canceled*/
LPCUSBSIO_REQ_CANCELED = -0x24,
} LPCUSBSIO_ERR_T;
/** @brief I2C clock rates */
typedef enum I2C_ClockRate_t {
I2C_CLOCK_25KHZ_MODE = 25000, /*!< 25kb/sec */
I2C_CLOCK_50KHZ_MODE = 50000, /*!< 50kb/sec */
I2C_CLOCK_STANDARD_MODE = 100000, /*!< 100kb/sec */
I2C_CLOCK_200KHZ_MODE = 200000, /*!< 200kb/sec */
I2C_CLOCK_FAST_MODE = 400000, /*!< 400kb/sec */
I2C_CLOCK_FAST_MODE_PLUS = 1000000, /*!< 1000kb/sec */
} I2C_CLOCKRATE_T;
/** @brief Port configuration information */
typedef struct PortConfig_t {
I2C_CLOCKRATE_T ClockRate; /*!< I2C Clock speed */
uint32_t Options; /*!< Configuration options */
} I2C_PORTCONFIG_T;
/** @brief Fast transfer parameter structure */
typedef struct FastXferParam_t {
uint8_t txSz; /*!< Number of bytes in transmit array,
if 0 only receive transfer will be carried on */
uint8_t rxSz; /*!< Number of bytes to received,
if 0 only transmission we be carried on */
uint8_t options; /*!< Fast transfer options */
uint8_t slaveAddr; /*!< 7-bit I2C Slave address */
const uint8_t *txBuff; /*!< Pointer to array of bytes to be transmitted */
uint8_t *rxBuff; /*!< Pointer memory where bytes received from I2C be stored */
} I2C_FAST_XFER_T;
//AL : Useless
/** @brief Get version string of the library.
*
* @param handle : A device handle returned from I2C_OpenPort().
*
* @returns
* This function returns a string containing the version of the library.
* If the device handle passed is not NULL then the firmware version of
* the connected device is appended to the string.
*/
//LPCUSBSIO_API const char *I2C_GetVersion(LPC_HANDLE handle);
/** @brief Get number I2C ports available on the LPC controller.
*
* This function gets the number of I2C ports that are available on the LPC controller.
* The number of ports available in each of these chips is different.
*
* @returns
* The number of ports available on the LPC controller.
*
*/
LPCUSBSIO_API int I2C_GetNumPorts(void);
/** @brief Opens the indexed port.
*
* This function opens the indexed port and provides a handle to it. Valid values for
* the index of port can be from 0 to the value obtained using I2C_GetNumPorts
* – 1).
*
* @param index : Index of the port to be opened.
*
* @returns
* This function returns a handle to I2C port object on
* success or NULL on failure.
*/
LPCUSBSIO_API LPC_HANDLE I2C_Open(uint32_t index);
/** @brief Initialize the port.
*
* This function initializes the port and the communication parameters associated
* with it.
*
* @param handle : Handle of the port.
* @param config : Pointer to I2C_PORTCONFIG_T structure. Members of
* I2C_PORTCONFIG_T structure contains the values for I2C
* master clock, latency timer and Options
*
* @returns
* This function returns LPCUSBSIO_OK on success and negative error code on failure.
* Check @ref LPCUSBSIO_ERR_T for more details on error code.
*/
LPCUSBSIO_API int32_t I2C_Init(LPC_HANDLE handle, I2C_PORTCONFIG_T *config);
/** @brief Closes a port.
*
* Closes a port and frees all resources that were used by it.
*
* @param handle : Handle of the port.
*
* @returns
* This function returns LPCUSBSIO_OK on success and negative error code on failure.
* Check @ref LPCUSBSIO_ERR_T for more details on error code.
*
*/
LPCUSBSIO_API int32_t I2C_Close(LPC_HANDLE handle);
/** @brief Reset I2C Controller.
*
* @param handle : A device handle returned from I2C_OpenPort().
*
* @returns
* This function returns LPCUSBSIO_OK on success and negative error code on failure.
* Check @ref LPCUSBSIO_ERR_T for more details on error code.
*
*/
LPCUSBSIO_API int32_t I2C_Reset(LPC_HANDLE handle);
/** @brief Get a string describing the last error which occurred.
*
* @param handle : A device handle returned from I2C_OpenPort().
*
* @returns
* This function returns a string containing the last error
* which occurred or NULL if none has occurred.
*
*/
LPCUSBSIO_API const wchar_t *I2C_Error(LPC_HANDLE handle, int32_t status);
/** @brief Read from an addressed I2C slave.
*
* This function reads the specified number of bytes from an addressed I2C slave.
* The @a options parameter effects the transfers. Some example transfers are shown below :
* - When I2C_TRANSFER_OPTIONS_START_BIT, I2C_TRANSFER_OPTIONS_STOP_BIT and
* I2C_TRANSFER_OPTIONS_NACK_LAST_BYTE are set.
*
* <b> S Addr Rd [A] [rxBuff0] A [rxBuff1] A ...[rxBuffN] NA P </b>
*
* - If I2C_TRANSFER_OPTIONS_NO_ADDRESS is also set.
*
* <b> S [rxBuff0] A [rxBuff1] A ...[rxBuffN] NA P </b>
*
* - if I2C_TRANSFER_OPTIONS_NACK_LAST_BYTE is not set
*
* <b> S Addr Rd [A] [rxBuff0] A [rxBuff1] A ...[rxBuffN] A P </b>
*
* - If I2C_TRANSFER_OPTIONS_STOP_BIT is not set.
*
* <b> S Addr Rd [A] [rxBuff0] A [rxBuff1] A ...[rxBuffN] NA </b>
*
* @param handle : Handle of the port.
* @param deviceAddress : Address of the I2C slave. This is a 7bit value and
* it should not contain the data direction bit, i.e. the decimal
* value passed should be always less than 128
* @param buffer : Pointer to the buffer where data is to be read
* @param sizeToTransfer: Number of bytes to be read
* @param options: This parameter specifies data transfer options. Check I2C_TRANSFER_OPTIONS_ macros.
* @returns
* This function returns number of bytes read on success and negative error code on failure.
* Check @ref LPCUSBSIO_ERR_T for more details on error code.
*/
LPCUSBSIO_API int32_t I2C_DeviceRead(LPC_HANDLE handle,
uint8_t deviceAddress,
uint8_t *buffer,
uint16_t sizeToTransfer,
uint8_t options);
/** @brief Writes to the addressed I2C slave.
*
* This function writes the specified number of bytes to an addressed I2C slave.
* The @a options parameter effects the transfers. Some example transfers are shown below :
* - When I2C_TRANSFER_OPTIONS_START_BIT, I2C_TRANSFER_OPTIONS_STOP_BIT and
* I2C_TRANSFER_OPTIONS_BREAK_ON_NACK are set.
*
* <b> S Addr Wr[A] txBuff0[A] txBuff1[A] ... txBuffN[A] P </b>
*
* - If I2C_TRANSFER_OPTIONS_NO_ADDRESS is also set.
*
* <b> S txBuff0[A ] ... txBuffN[A] P </b>
*
* - if I2C_TRANSFER_OPTIONS_BREAK_ON_NACK is not set
*
* <b> S Addr Wr[A] txBuff0[A or NA] ... txBuffN[A or NA] P </b>
*
* - If I2C_TRANSFER_OPTIONS_STOP_BIT is not set.
*
* <b> S Addr Wr[A] txBuff0[A] txBuff1[A] ... txBuffN[A] </b>
*
* @param handle : Handle of the port.
* @param deviceAddress : Address of the I2C slave. This is a 7bit value and
* it should not contain the data direction bit, i.e. the decimal
* value passed should be always less than 128
* @param sizeToTransfer: Number of bytes to be written
* @param buffer : Pointer to the buffer where data is to be read
* @param options : This parameter specifies data transfer options. Check I2C_TRANSFER_OPTIONS_ macros.
* @returns
* This function returns number of bytes written on success and negative error code on failure.
* Check @ref LPCUSBSIO_ERR_T for more details on error code.
*/
LPCUSBSIO_API int32_t I2C_DeviceWrite(LPC_HANDLE handle,
uint8_t deviceAddress,
uint8_t *buffer,
uint16_t sizeToTransfer,
uint8_t options);
/**@brief Transmit and Receive data in master mode
*
* The parameter @a xfer should have its member @a slaveAddr initialized
* to the 7 - Bit slave address to which the master will do the xfer, Bit0
* to bit6 should have the address and Bit8 is ignored.During the transfer
* no code(like event handler) must change the content of the memory
* pointed to by @a xfer.The member of @a xfer, @a txBuff and @a txSz be
* initialized to the memory from which the I2C must pick the data to be
* transferred to slave and the number of bytes to send respectively, similarly
* @a rxBuff and @a rxSz must have pointer to memory where data received
* from slave be stored and the number of data to get from slave respectively.
*
* Following types of transfers are possible :
* - Write-only transfer : When @a rxSz member of @a xfer is set to 0.
*
* <b> S Addr Wr[A] txBuff0[A] txBuff1[A] ... txBuffN[A] P </b>
*
* - If I2C_FAST_XFER_OPTION_IGNORE_NACK is set in @a options member
*
* <b> S Addr Wr[A] txBuff0[A or NA] ... txBuffN[A or NA] P </b>
*
* - Read-only transfer : When @a txSz member of @a xfer is set to 0.
*
* <b> S Addr Rd[A][rxBuff0] A[rxBuff1] A ...[rxBuffN] NA P </b>
*
* - If I2C_FAST_XFER_OPTION_LAST_RX_ACK is set in @a options member
*
* <b> S Addr Rd[A][rxBuff0] A[rxBuff1] A ...[rxBuffN] A P </b>
*
* - Read-Write transfer : When @a rxSz and @ txSz members of @a xfer are non - zero.
*
* <b> S Addr Wr[A] txBuff0[A] txBuff1[A] ... txBuffN[A] <br>
* S Addr Rd[A][rxBuff0] A[rxBuff1] A ...[rxBuffN] NA P </b>
*
* @param handle : Handle of the port.
* @param xfer : Pointer to a I2C_FAST_XFER_T structure.
* @returns
* This function returns number of bytes read on success and negative error code on failure.
* Check @ref LPCUSBSIO_ERR_T for more details on error code.
*/
LPCUSBSIO_API int32_t I2C_FastXfer(LPC_HANDLE handle, I2C_FAST_XFER_T *xfer);
/** @brief Change the state of VEN GPIO
*
* This function change VEN GPIO State
*
* @param handle : Handle of the port.
* @param newValure : New GPIO State
* @returns
* This function returns number of bytes written on success and negative error code on failure.
* Check @ref LPCUSBSIO_ERR_T for more details on error code.
*/
LPCUSBSIO_API LPCUSBSIO_ERR_T GPIO_SetVENValue(LPC_HANDLE handle, uint8_t newValue);
/** @brief Change the state of Download GPIO
*
* This function change Download GPIO State
*
* @param handle : Handle of the port.
* @param newValure : New GPIO State
* @returns
* This function returns number of bytes written on success and negative error code on failure.
* Check @ref LPCUSBSIO_ERR_T for more details on error code.
*/
LPCUSBSIO_API LPCUSBSIO_ERR_T GPIO_SetDWLValue(LPC_HANDLE handle, uint8_t newValue);
LPCUSBSIO_API LPCUSBSIO_ERR_T I2C_CancelAllRequest(LPC_HANDLE handle);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /*__LPCUSBSIO_H*/
/*
* @brief Protocol definitions for LPCUSBSIO's I2C interface
*
* @note
* Copyright(C) NXP Semiconductors, 2013
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#ifndef __LPCUSBSIO_I2C_H_
#define __LPCUSBSIO_I2C_H_
#ifdef __cplusplus
extern "C"
{
#endif
#pragma pack(1)
/** @defgroup LPCUSBSIO_I2C LPCUSBSIO protocol definitions for I2C interface
* @ingroup LPCUSBSIO
* This package defines the LPCUSBSIO packet structure for I2C interface.
* Both the firmware and PC (host) libraries use this definitions to construct
* the I2C payloads.
* @{
*/
#define HID_I2C_MAX_PACKETS 4 /*!< Maximum packets allowed in processing queue */
#define HID_I2C_PACKET_SZ 64 /*!< Packet size of each I2C command packet */
#define HID_I2C_HEADER_SZ 5 /*!< Size of the header in I2C command packet */
/* HID_I2C Requests */
#define HID_I2C_REQ_RESET 0 /*!< Request to abort and flush all pending requests */
#define HID_I2C_REQ_INIT_PORT 1 /*!< Request to initialize the I2C port */
#define HID_I2C_REQ_DEINIT_PORT 2 /*!< Request to de-initialize the I2C port */
#define HID_I2C_REQ_DEVICE_WRITE 3 /*!< Request to write data to the I2C port */
#define HID_I2C_REQ_DEVICE_READ 4 /*!< Request to read data from the I2C port */
#define HID_I2C_REQ_DEVICE_XFER 5 /*!< Request to write and then read data from the I2C port */
/*AL ! Add GPIO Requests */
#define HID_GPIO_REQ_SET_VEN 6 /*!< Request to set the VEN GPIO State*/
#define HID_GPIO_REQ_SET_DWL 7 /*!< Request to set the DWL GPIO State*/
/**
* @brief HID to I2C bridge Request structure.
* Defines the structure of HID to I2C Request packet. This is same as
* HID OUT report.
*/
typedef struct __HIDI2C_OUT_REPORT {
uint16_t length; /*!< Length of the HID_I2C Request structure including cmd, transId and length fields. */
uint8_t transId; /*!< I2C_HID transaction identifier. Rolls over after 255. */
uint8_t sesId; /*!< I2C_HID session identifier. */
uint8_t req; /*!< I2C_HID Request */
uint8_t data[]; /*!< Data corresponding to the Request */
} HID_I2C_OUT_REPORT_T;
/** HID_I2C responses. The response code below 0x10 should match with I2CM_STATUS codes. */
#define HID_I2C_RES_OK 0x00 /*!< Requested Request was executed successfully. */
#define HID_I2C_RES_ERROR 0x01 /*!< Unknown error condition. */
#define HID_I2C_RES_NAK 0x02 /*!< No device responded for given slave address. */
#define HID_I2C_RES_BUS_ERROR 0x03 /*!< I2C bus error */
#define HID_I2C_RES_SLAVE_NAK 0x04 /*!< NAK received after SLA+W or SLA+R */
#define HID_I2C_RES_ARBLOST 0x05 /*!< Arbitration lost */
#define HID_I2C_RES_TIMEOUT 0x10 /*!< Transaction timed out. */
#define HID_I2C_RES_INVALID_CMD 0x11 /*!< Invalid HID_I2C Request or Request not supported in this version. */
#define HID_I2C_RES_INVALID_PARAM 0x12 /*!< Invalid parameters are provided for the given Request. */
#define HID_I2C_RES_PARTIAL_DATA 0x13 /*!< Partial transfer completed. */
/**
* @brief HID to I2C bridge response structure.
* Defines the structure of HID to I2C Request packet. This is same as
* HID OUT report.
*/
typedef struct __HIDI2C_IN_REPORT {
uint16_t length; /*!< Length of the HID_I2C response structure including resp, transId and length fields.*/
uint8_t transId; /*!< I2C_HID transaction identifier. */
uint8_t sesId; /*!< I2C_HID session identifier. */
uint8_t resp; /*!< I2C_HID reponse */
uint8_t data[]; /*!< Data corresponding to the response */
} HID_I2C_IN_REPORT_T;
/**
* @brief Port configuration information
*/
typedef struct __HIDI2C_PortConfig_t {
uint32_t busSpeed; /*!< I2C bus speed */
uint32_t Options; /*!< Configuration options */
} HID_I2C_PORTCONFIG_T;
/** I2C_IO_OPTIONS Options to I2C_DeviceWrite & I2C_DeviceRead routines
* @{
*/
/** Generate start condition before transmitting */
#define HID_I2C_TRANSFER_OPTIONS_START_BIT 0x0001
/** Generate stop condition at the end of transfer */
#define HID_I2C_TRANSFER_OPTIONS_STOP_BIT 0x0002
/** Continue transmitting data in bulk without caring about Ack or nAck from device if this bit is
not set. If this bit is set then stop transmitting the data in the buffer when the device nAcks*/
#define HID_I2C_TRANSFER_OPTIONS_BREAK_ON_NACK 0x0004
/** lpcusbsio-I2C generates an ACKs for every byte read. Some I2C slaves require the I2C
master to generate a nACK for the last data byte read. Setting this bit enables working with such
I2C slaves */
#define HID_I2C_TRANSFER_OPTIONS_NACK_LAST_BYTE 0x0008
/* Setting this bit would mean that the address field should be ignored.
The address is either a part of the data or this is a special I2C
frame that doesn't require an address. For example when transferring a
frame greater than the USB_HID packet this option can be used. */
#define HID_I2C_TRANSFER_OPTIONS_NO_ADDRESS 0x00000040
/** @} */
/**
* @brief HID to I2C bridge read and write transfer parameters structure.
* Defines the structure of HID to I2C read-write transfer parameters.
*/
typedef struct __HIDI2C_RW_PARAMS {
uint16_t length; /*!< Length of the transfer.*/
uint8_t options; /*!< check @ref I2C_IO_OPTIONS. */
uint8_t slaveAddr; /*!< I2C slave device address. */
uint8_t data[]; /*!< Data corresponding to the response */
} HID_I2C_RW_PARAMS_T;
/** I2C_FAST_XFER_OPTIONS I2C master faster transfer options
* @{
*/
/** Ignore NACK during data transfer. By default transfer is aborted. */
#define I2C_FAST_XFER_OPTION_IGNORE_NACK 0x01
/** ACK last byte received. By default we NACK last byte we receive per I2C spec. */
#define I2C_FAST_XFER_OPTION_LAST_RX_ACK 0x02
/**
* @}
*/
/**
* @brief HID to I2C bridge fast transfer parameters structure.
* Defines the parameters structure for HID_I2C_REQ_DEVICE_XFER command.
*/
typedef struct __HIDI2C_XFER_PARAMS {
uint8_t txLength; /*!< Length of the Tx transfer.*/
uint8_t rxLength; /*!< Length of the Rx transfer. */
uint8_t options; /*!< check @ref I2C_FAST_XFER_OPTIONS. */
uint8_t slaveAddr; /*!< I2C slave device address. */
uint8_t data[]; /*!< Data corresponding to the response */
} HID_I2C_XFER_PARAMS_T;
/**
* @}
*/
#pragma pack()
#ifdef __cplusplus
}
#endif
#endif /* __LPCUSBSIO_I2C_H_ */
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#define TIMEOUT_INFINITE 0
#define TIMEOUT_100MS 100
#define TIMEOUT_1S 1000
#define TIMEOUT_1200MS 1200
#define TIMEOUT_2S 2000
void tml_Connect(void);
void tml_Disconnect(void);
void tml_Send(uint8_t *pBuffer, uint16_t BufferLen, uint16_t *pBytesSent);
void tml_Receive(uint8_t *pBuffer, uint16_t BufferLen, uint16_t *pBytes, uint16_t timeout);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
int tml_hid_Connect(void);
void tml_hid_Disconnect(void);
void tml_hid_Send(uint8_t *pBuffer, uint16_t BufferLen, uint16_t *pBytesSent);
void tml_hid_Receive(uint8_t *pBuffer, uint16_t BufferLen, uint16_t *pBytes, uint16_t timeout);
void tml_hid_Cancel(void);
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <unistd.h>
#define Sleep(x) usleep(1000*x)
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include "TML/inc/framework_Allocator.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef struct sMemInfo
{
uint32_t magic;
size_t size;
} sMemInfo_t;
typedef struct sMemInfoEnd
{
uint32_t magicEnd;
} sMemInfoEnd_t;
void* framework_AllocMem(size_t size)
{
sMemInfo_t *info = NULL;
sMemInfoEnd_t *infoEnd = NULL;
uint8_t * pMem = (uint8_t *) malloc(size+sizeof(sMemInfo_t)+sizeof(sMemInfoEnd_t));
info = (sMemInfo_t*)pMem;
info->magic = 0xDEADC0DE;
info->size = size;
pMem = pMem+sizeof(sMemInfo_t);
memset(pMem,0xAB,size);
infoEnd = (sMemInfoEnd_t*)(pMem+size);
infoEnd->magicEnd = 0xDEADC0DE;
return pMem;
}
void framework_FreeMem(void *ptr)
{
if(NULL != ptr)
{
sMemInfoEnd_t *infoEnd = NULL;
uint8_t *memInfo = (uint8_t*)ptr;
sMemInfo_t *info = (sMemInfo_t*)(memInfo - sizeof(sMemInfo_t));
infoEnd = (sMemInfoEnd_t*)(memInfo+info->size);
if ((info->magic != 0xDEADC0DE)||(infoEnd->magicEnd != 0xDEADC0DE))
{
// Call Debugger
*(int *)(uintptr_t)0xbbadbeef = 0;
}else
{
memset(info,0x14,info->size+sizeof(sMemInfo_t)+sizeof(sMemInfoEnd_t));
}
free(info);
}
}
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include "TML/inc/framework_Container.h"
#include <stdlib.h>
#include <string.h>
#define MEM_ALLOCATOR(x) malloc(x)
#define MEM_DEALLOCATOR(x) free(x)
#define START_OK "valid_start"
#define START_KO "deleted_start"
#define END_OK "valid_end"
#define END_KO "deleted_end"
#define STR_CMP(x, y, z) memcmp(x, y, z)
#define STR_CPY(x, y, z) memcpy(x, y, z)
typedef struct Container
{
char start[14];
void **m_data;
uint32_t m_size_data;
uint32_t m_alloc_size;
char end[12];
}Container_h;
void container_check_size(Container_h* pContainer);
void container_rebuild(Container_h* pContainer, uint32_t index);
CONTAINER_STATUS container_isValid(Container_h* pContainer);
CONTAINER_STATUS container_create(void** pContainer, uint32_t size)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = NULL;
if (NULL == pContainer)
{
lStatus = CONTAINER_INVALID_PARAM;
}
if(CONTAINER_SUCCESS == lStatus)
{
*pContainer = MEM_ALLOCATOR(sizeof(Container_h));
if (NULL == *pContainer)
{
lStatus = CONTAINER_FAILED;
}
else
{
lContainer = (Container_h*)*pContainer;
lContainer->m_data=(void**)MEM_ALLOCATOR(size*sizeof(void*));
memset(lContainer->m_data,0,size*sizeof(void*));
lContainer->m_size_data=0;
lContainer->m_alloc_size=size;
STR_CPY(lContainer->start, START_OK, sizeof(START_OK));
STR_CPY(lContainer->end, END_OK, sizeof(END_OK));
}
}
return lStatus;
}
CONTAINER_STATUS container_delete(void* pContainer)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = (Container_h *) pContainer;
lStatus = container_isValid(lContainer);
if(CONTAINER_SUCCESS == lStatus)
{
if(NULL != lContainer->m_data)
{
MEM_DEALLOCATOR(lContainer->m_data);
lContainer->m_data = NULL;
STR_CPY(lContainer->start, START_KO, sizeof(START_OK));
STR_CPY(lContainer->end, END_KO, sizeof(END_OK));
}
}
return lStatus;
}
CONTAINER_STATUS container_add(void* pContainer, void* _ptr)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = (Container_h *) pContainer;
lStatus = container_isValid(lContainer);
if(CONTAINER_SUCCESS == lStatus)
{
container_check_size(lContainer);
lContainer->m_data[lContainer->m_size_data] = _ptr;
lContainer->m_size_data++;
}
return lStatus;
}
CONTAINER_STATUS container_set(void* pContainer, uint32_t index,void*_ptr, void** _old)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = (Container_h *) pContainer;
lStatus = container_isValid(lContainer);
*_old = NULL;
if(CONTAINER_SUCCESS == lStatus)
{
if (index > lContainer->m_size_data)
{
container_add(pContainer, _ptr);
}
else
{
*_old = lContainer->m_data[index];
lContainer->m_data[index] = _ptr;
}
}
return lStatus;
}
CONTAINER_STATUS container_remove(void* pContainer, uint32_t index, void** _old)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = (Container_h *) pContainer;
lStatus = container_isValid(lContainer);
*_old = NULL;
if(CONTAINER_SUCCESS == lStatus)
{
if (index < lContainer->m_size_data)
{
*_old = lContainer->m_data[index];
lContainer->m_data[index] = NULL;
// this is not the last one
if (index != (lContainer->m_size_data - 1))
{
container_rebuild(lContainer, index);
}
lContainer->m_size_data--;
}
}
return lStatus;
}
CONTAINER_STATUS container_get(void* pContainer, uint32_t index, void** _out)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = (Container_h *) pContainer;
lStatus = container_isValid(lContainer);
*_out = NULL;
if(CONTAINER_SUCCESS == lStatus)
{
if (index < lContainer->m_size_data)
{
*_out = lContainer->m_data[index];
}
}
return lStatus;
}
CONTAINER_STATUS container_size(void* pContainer, uint32_t* size)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = (Container_h *) pContainer;
lStatus = container_isValid(lContainer);
if(CONTAINER_SUCCESS == lStatus)
{
*size = lContainer->m_size_data;
}
return lStatus;
}
void container_check_size(Container_h* pContainer)
{
void** m_new_data;
if (pContainer->m_size_data == pContainer->m_alloc_size)
{
pContainer->m_alloc_size = pContainer->m_alloc_size * 2;
m_new_data = (void**) MEM_ALLOCATOR(sizeof(void*) * pContainer->m_alloc_size);
memmove(m_new_data, pContainer->m_data, pContainer->m_size_data * sizeof(void*));
MEM_DEALLOCATOR(pContainer->m_data);
pContainer->m_data = m_new_data;
}
}
void container_rebuild(Container_h* pContainer, uint32_t index)
{
void** _zero = pContainer->m_data + index;
void** _start_cpy = _zero + 1;
int32_t size = (pContainer->m_size_data - 1) - index;
if (size <= 0) return;
memmove(_zero, _start_cpy, size * sizeof(void*));
}
CONTAINER_STATUS container_clear(void* pContainer)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = (Container_h *) pContainer;
lStatus = container_isValid(lContainer);
if(CONTAINER_SUCCESS == lStatus)
{
memset(lContainer->m_data, 0, lContainer->m_size_data);
lContainer->m_size_data = 0;
}
return lStatus;
}
CONTAINER_STATUS container_flushMallocedContent(void* pContainer)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = (Container_h *) pContainer;
uint32_t sz, i;
void *old;
lStatus = container_isValid(lContainer);
if(CONTAINER_SUCCESS == lStatus)
{
old = NULL;
sz = 0x00;
container_size(pContainer, &sz);
for (i = 0 ; i < sz;i++)
{
container_get(pContainer, i, &old);
MEM_DEALLOCATOR(old);
}
container_clear(pContainer);
}
return lStatus;
}
CONTAINER_STATUS container_removePtr(void* pContainer, void* ref, void** out)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
Container_h *lContainer = (Container_h *) pContainer;
uint32_t sz, i;
void *scan;
lStatus = container_isValid(lContainer);
if(CONTAINER_SUCCESS == lStatus)
{
scan = NULL;
sz = 0x00;
container_size(pContainer, &sz);
*out = NULL;
for (i = 0; i < sz; i++)
{
container_get(pContainer, i, &scan);
if (scan == ref)
{
container_remove(pContainer, i, out);
}
}
}
return lStatus;
}
CONTAINER_STATUS container_isValid(Container_h* pContainer)
{
CONTAINER_STATUS lStatus = CONTAINER_SUCCESS;
if (NULL == pContainer)
{
lStatus = CONTAINER_INVALID_PARAM;
}
if (CONTAINER_SUCCESS == lStatus)
{
if ((0x00 != STR_CMP(START_OK, pContainer->start, sizeof(START_OK))) || (0x00 != STR_CMP(END_OK, pContainer->end, sizeof(END_OK))))
{
lStatus = CONTAINER_INVALID_CONTAINER;
}
}
return lStatus;
}
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include "TML/inc/framework_Map.h"
#include <stdlib.h>
#include <string.h>
#define MEM_ALLOCATOR(x) malloc(x)
#define MEM_DEALLOCATOR(x) free(x)
#define START_OK "valid_start"
#define START_KO "deleted_start"
#define END_OK "valid_end"
#define END_KO "deleted_end"
#define STR_CMP(x, y, z) memcmp(x, y, z)
#define STR_CPY(x, y, z) memcpy(x, y, z)
typedef struct map_element
{
void* id;
void* object;
struct map_element_t* next;
}map_element_t;
typedef struct map
{
char start[14];
map_element_t* elements;
char end[12];
}map_t;
STATUS map_isValid(map_t* map);
STATUS map_create(void ** map)
{
STATUS lStatus = SUCCESS;
map_t* lMap = NULL;
*map = MEM_ALLOCATOR(sizeof(map_t));
if (NULL == *map)
{
lStatus = FAILED;
}
else
{
lMap = (map_t*)*map;
lMap->elements = NULL;
STR_CPY(lMap->start, START_OK, sizeof(START_OK));
STR_CPY(lMap->end, END_OK, sizeof(END_OK));
}
return lStatus;
}
STATUS map_destroy(void* map)
{
STATUS lStatus = SUCCESS;
map_t* lMap = (map_t*)map;
lStatus = map_isValid(lMap);
if (SUCCESS == lStatus)
{
while (NULL != lMap->elements)
{
map_remove(map, lMap->elements->id);
}
STR_CPY(lMap->start, START_KO, sizeof(START_KO));
STR_CPY(lMap->end, END_KO, sizeof(END_KO));
MEM_DEALLOCATOR(lMap);
lMap = NULL;
}
return lStatus;
}
STATUS map_add(void * map, void* id, void* object)
{
STATUS lStatus = SUCCESS;
map_t* lMap = (map_t*)map;
void* lObject = NULL;
map_element_t* lElement = NULL;
map_element_t* lElementTmp = NULL;
lStatus = map_isValid(lMap);
if (SUCCESS == lStatus)
{
lStatus = map_get(map, id, &lObject);
if (SUCCESS == lStatus)
{
lStatus = ALREADY_EXISTS;
}
else
{
lElement = (map_element_t*)MEM_ALLOCATOR(sizeof(map_element_t));
if (NULL == lElement)
{
lStatus = FAILED;
}
else
{
lElement->id = id;
lElement->next = NULL;
lElement->object = object;
lElementTmp = lMap->elements;
if (NULL == lElementTmp)
{
lMap->elements = lElement;
}
else
{
while (NULL != lElementTmp->next)
{
lElementTmp = (map_element_t *) lElementTmp->next;
}
lElementTmp->next = (struct map_element_t *) lElement;
}
lStatus = SUCCESS;
}
}
}
return lStatus;
}
STATUS map_getAll(void* map, void ** elements, int * lenght)
{
STATUS lStatus = SUCCESS;
map_t* lMap = (map_t*)map;
map_element_t* lElement = NULL;
int i;
lStatus = map_isValid(lMap);
if (SUCCESS == lStatus)
{
if (0x00 == *lenght || NULL == elements)
{
*lenght = 0x00;
lElement = lMap->elements;
while (NULL != lElement)
{
(*lenght)++;
lElement = (map_element_t *) lElement->next;
}
}
else
{
lElement = lMap->elements;
for (i = 0x00; i < *lenght; i++)
{
elements[i] = lElement->object;
}
}
}
return lStatus;
}
STATUS map_remove(void* map, void* id)
{
STATUS lStatus = SUCCESS;
map_t* lMap = (map_t*)map;
map_element_t* lElementTmp = NULL;
map_element_t* lElement = NULL;
int lElementFound = 0x00;
lStatus = map_isValid(map);
if (SUCCESS == lStatus)
{
lElement = lMap->elements;
lElementTmp = NULL;
while (NULL != lElement)
{
if (lElement->id == id)
{
lElementFound = 0x01;
if (lMap->elements == lElement)
{
lMap->elements = (map_element_t *) lElement->next;
}
else
{
lElementTmp->next = lElement->next;
}
break;
}
lElementTmp = lElement;
lElement = (map_element_t *) lElement->next;
}
if (0x00 == lElementFound)
{
lStatus = NOT_FOUND;
}
else
{
MEM_DEALLOCATOR(lElement);
}
}
return lStatus;
}
STATUS map_get(void* map, void* id, void ** object)
{
STATUS lStatus = SUCCESS;
map_t* lMap = (map_t*)map;
map_element_t* lElement = NULL;
lStatus = map_isValid(lMap);
if (NULL == object)
{
lStatus = INVALID_PARAM;
}
if (SUCCESS == lStatus)
{
*object = NULL;
if (NULL != lMap->elements)
{
lElement = lMap->elements;
while (NULL != lElement)
{
if (lElement->id == id)
{
*object = lElement->object;
break;
}
lElement = (map_element_t *) lElement->next;
}
if (NULL == *object)
{
lStatus = NOT_FOUND;
}
}
else
{
lStatus = NOT_FOUND;
}
}
return lStatus;
}
STATUS map_isValid(map_t* map)
{
STATUS lStatus = SUCCESS;
if (NULL == map)
{
lStatus = INVALID_PARAM;
}
if (SUCCESS == lStatus)
{
if ((0x00 != STR_CMP(START_OK, map->start, sizeof(START_OK))) || (0x00 != STR_CMP(END_OK, map->end, sizeof(END_OK))))
{
lStatus = INVALID_MAP;
}
}
return lStatus;
}
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include "TML/inc/framework_Parcel.h"
#include "TML/inc/framework_Allocator.h"
#include <stdlib.h>
#include <string.h>
#define INC_COUNTER(p,x) \
{ \
uint8_t seeSomewhereElseCompilator = 0; \
do \
{ \
p->m_curPosition += x; \
if (p->m_curLength < p->m_curPosition) \
{ \
p->m_curLength += x; \
} \
}while (seeSomewhereElseCompilator); \
}
typedef struct _tParcel
{
uint8_t *m_data;
uint32_t m_dataLength;
uint32_t m_curLength;
uint32_t m_curPosition;
}tParcel;
static void growData(tParcel *parcel,uint32_t len)
{
uint32_t newSize;
uint8_t *newBuffer;
if ((parcel->m_curPosition+len) < parcel->m_dataLength)
return;
newSize = parcel->m_dataLength + len;
newBuffer = (uint8_t*)framework_AllocMem(newSize);
memcpy(newBuffer,parcel->m_data, parcel->m_dataLength);
framework_FreeMem(parcel->m_data);
parcel->m_data = newBuffer;
parcel->m_dataLength = newSize;
}
void framework_ParcelCreate(void** parcel)
{
tParcel *p = NULL;
if (parcel == NULL)
{
return;
}
p = (tParcel*)framework_AllocMem(sizeof(tParcel));
p->m_data = (uint8_t*)framework_AllocMem(32);
p->m_dataLength = 32;
p->m_curPosition = 0;
p->m_curLength = 0;
memset(p->m_data, 0, 32);
*parcel = p;
}
void framework_ParcelDelete(void* parcel)
{
tParcel *p = (tParcel*)parcel;
if (parcel)
{
framework_FreeMem(p->m_data);
framework_FreeMem(p);
}
}
void framework_ParcelClear(void* parcel)
{
tParcel *p = (tParcel*)parcel;
p->m_curPosition = 0;
p->m_curLength = 0;
memset(p->m_data, 0, p->m_dataLength);
}
const uint8_t* framework_ParcelDataAtCurrentPosition(void* parcel)
{
tParcel *p = (tParcel*)parcel;
return (p->m_data+p->m_curPosition);
}
void framework_ParcelDeserialize(void* dstParcel, void* srcParcel)
{
tParcel *pDest = (tParcel*)dstParcel;
tParcel *pSrc = (tParcel*)srcParcel;
uint8_t *data = NULL;
uint32_t size = framework_ParcelReadInt32(pSrc);
if (size > 0)
{
data = (uint8_t*)framework_AllocMem(size);
framework_ParcelReadRaw(pSrc,data,size);
framework_ParcelSetData(pDest,data,size);
framework_FreeMem(data);
framework_ParcelRewind(pDest);
}else
{
framework_ParcelClear(pDest);
}
}
void framework_ParcelForward(void* parcel, uint32_t nbBytes)
{
tParcel *p = (tParcel*)parcel;
if (p->m_curPosition+nbBytes <= p->m_curLength)
{
p->m_curPosition+=nbBytes;
}
}
const uint8_t* framework_ParcelGetData(void* parcel)
{
tParcel *p = (tParcel*)parcel;
return p->m_data;
}
uint32_t framework_ParcelGetRemainingDataSize(void* parcel)
{
tParcel *p = (tParcel*)parcel;
return p->m_curLength-p->m_curPosition;
}
uint32_t framework_ParcelGetSize(void* parcel)
{
tParcel *p = (tParcel*)parcel;
return p->m_curLength;
}
uint8_t framework_ParcelReadByte(void* parcel)
{
tParcel *p = (tParcel*)parcel;
if (p->m_curPosition < p->m_curLength)
{
uint8_t result = p->m_data[p->m_curPosition];
p->m_curPosition += sizeof(uint8_t);
return result;
}
return 0;
}
double framework_ParcelReadDouble(void* parcel)
{
tParcel *p = (tParcel*)parcel;
if (p->m_curPosition < p->m_curLength)
{
void* result = p->m_data+p->m_curPosition;
p->m_curPosition += sizeof(double);
return *((double*)result);
}
return 0;
}
float framework_ParcelReadFloat(void* parcel)
{
tParcel *p = (tParcel*)parcel;
if (p->m_curPosition < p->m_curLength)
{
void* result = p->m_data+p->m_curPosition;
p->m_curPosition += sizeof(float);
return *((float*)result);
}
return 0;
}
uint32_t framework_ParcelReadInt32(void* parcel)
{
tParcel *p = (tParcel*)parcel;
if (p->m_curPosition < p->m_curLength)
{
void* result = p->m_data+p->m_curPosition;
p->m_curPosition += sizeof(uint32_t);
return *((uint32_t*)result);
}
return 0;
}
uint64_t framework_ParcelReadInt64(void* parcel)
{
tParcel *p = (tParcel*)parcel;
if (p->m_curPosition < p->m_curLength)
{
void* result = p->m_data+p->m_curPosition;
p->m_curPosition += sizeof(uint64_t);
return *((uint64_t*)result);
}
return 0;
}
void framework_ParcelReadRaw(void* parcel, void* outBuffer, uint32_t len)
{
tParcel *p = (tParcel*)parcel;
if (!outBuffer)
{
return;
}
if (p->m_curPosition < p->m_curLength)
{
uint8_t *start =p->m_data+p->m_curPosition;
memcpy(outBuffer,start,len);
p->m_curPosition += len;
}
}
uint16_t framework_ParcelReadShort(void* parcel)
{
tParcel *p = (tParcel*)parcel;
if (p->m_curPosition < p->m_curLength)
{
void* result = p->m_data+p->m_curPosition;
p->m_curPosition += sizeof(uint16_t);
return *((uint16_t*)result);
}
return 0;
}
const char* framework_ParcelReadString(void* parcel)
{
tParcel *p = (tParcel*)parcel;
if (p->m_curPosition < p->m_curLength)
{
char* result =(char*)(p->m_data+p->m_curPosition);
p->m_curPosition += strlen(result)+1;
return result;
}
return NULL;
}
void framework_ParcelRewind(void* parcel)
{
tParcel *p = (tParcel*)parcel;
p->m_curPosition = 0;
}
void framework_ParcelSerialize(void* dstParcel, void* srcParcel)
{
tParcel *pDest = (tParcel*)dstParcel;
tParcel *pSrc = (tParcel*)srcParcel;
framework_ParcelWriteInt32(pDest,pSrc->m_curLength);
if (pSrc->m_curLength>0)
{
framework_ParcelWriteRaw(dstParcel,pSrc->m_data,pSrc->m_curLength);
}
}
void framework_ParcelSetData(void* parcel, const uint8_t* data, uint32_t size)
{
tParcel *p = (tParcel*)parcel;
framework_FreeMem(p->m_data);
if (size > 0)
{
p->m_data = (uint8_t*)framework_AllocMem(size);
memcpy(p->m_data,data,size);
p->m_dataLength = size;
}else
{
p->m_data = (uint8_t*)framework_AllocMem(32);
memset(p->m_data,0,32);
p->m_dataLength = 32;
}
p->m_curLength = size;
p->m_curPosition = 0;
}
void framework_ParcelWriteByte(void* parcel, uint8_t i)
{
tParcel *p = (tParcel*)parcel;
growData(p,sizeof(uint8_t));
p->m_data[p->m_curPosition] = i;
INC_COUNTER(p,sizeof(uint8_t));
}
void framework_ParcelWriteDouble(void* parcel, double d)
{
tParcel *p = (tParcel*)parcel;
growData(p,sizeof(double));
*((double*)(p->m_data+p->m_curPosition)) = d;
INC_COUNTER(p,sizeof(double));
}
void framework_ParcelWriteFloat(void* parcel, float f)
{
tParcel *p = (tParcel*)parcel;
growData(p,sizeof(float));
*((float*)(p->m_data+p->m_curPosition)) = f;
INC_COUNTER(p,sizeof(float));
}
void framework_ParcelWriteInt32(void* parcel, uint32_t i)
{
tParcel *p = (tParcel*)parcel;
growData(p,sizeof(uint32_t));
*((uint32_t*)(p->m_data+p->m_curPosition)) = i;
INC_COUNTER(p,sizeof(uint32_t));
}
void framework_ParcelWriteInt64(void* parcel, uint64_t i)
{
tParcel *p = (tParcel*)parcel;
growData(p,sizeof(uint64_t));
*((uint64_t*)(p->m_data+p->m_curPosition)) = i;
INC_COUNTER(p,sizeof(uint64_t));
}
void framework_ParcelWriteRaw(void* parcel, const void* buffer, uint32_t len)
{
tParcel *p = (tParcel*)parcel;
growData(p,len);
memcpy((p->m_data+p->m_curPosition),buffer,len);
INC_COUNTER(p,len);
}
void framework_ParcelWriteShort(void* parcel, uint16_t i)
{
tParcel *p = (tParcel*)parcel;
growData(p,sizeof(uint16_t));
*((uint16_t*)(p->m_data+p->m_curPosition)) = i;
INC_COUNTER(p,sizeof(uint16_t));
}
void framework_ParcelWriteString(void* parcel, const char* s)
{
tParcel *p = (tParcel*)parcel;
growData(p,strlen(s)+1); // Trailling 0
strcpy((char*)(p->m_data+p->m_curPosition),s);
INC_COUNTER(p,strlen(s)+1);
}
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include "TML/inc/framework_Timer.h"
#include "TML/inc/framework_Interface.h"
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#define NSECS 1000000
#define MAX_NO_TIMERS 16
struct framework_Timer
{
timer_t handle;
framework_TimerCallBack *callback;
void* pContext;
int nIsStopped;
};
static struct framework_Timer timers[MAX_NO_TIMERS] =
{
{0, NULL, NULL
, 0
},
};
static void framework_TimerExpired(union sigval sv)
{
uint32_t timerid = (uint32_t)(sv.sival_int);
if((timerid < MAX_NO_TIMERS) && (timers[timerid].nIsStopped == 1))
{
return;
}
if(timerid < MAX_NO_TIMERS)
{
framework_TimerStop(&timerid);
if (timers[timerid].callback)
{
timers[timerid].callback(timers[timerid].pContext);
}
}
}
static void framework_TimerDummyCb(void *pContext) {}
void framework_TimerCreate(void** timer)
{
uint32_t timerid;
struct sigevent se;
se.sigev_notify = SIGEV_THREAD;
se.sigev_notify_function = framework_TimerExpired;
se.sigev_notify_attributes = NULL;
/* Look for available timer slot */
for(timerid=0; timerid<MAX_NO_TIMERS; timerid++) {
if(timers[timerid].callback == NULL) break;
}
if(timerid == MAX_NO_TIMERS) {
*timer = NULL;
return;
}
se.sigev_value.sival_int = (int)timerid;
/* Create POSIX timer */
if(timer_create(CLOCK_REALTIME, &se, &(timers[timerid].handle)) == -1) {
*timer = NULL;
return;
}
timers[timerid].callback = framework_TimerDummyCb;
*timer = &timerid;
}
void framework_TimerDelete(void* timer)
{
uint32_t TimerId = *((uint32_t *) timer);
if(TimerId >= MAX_NO_TIMERS)
return;
if(timers[TimerId].callback == NULL)
return;
timer_delete(timers[TimerId].handle);
timers[TimerId].callback = NULL;
timers[TimerId].pContext = NULL;
}
void framework_TimerStart(void* timer,uint32_t delay, framework_TimerCallBack *cb,void *usercontext)
{
struct itimerspec its;
uint32_t TimerId = *((uint32_t *) timer);
if(TimerId >= MAX_NO_TIMERS)
return;
if(cb == NULL)
return;
if(timers[TimerId].callback == NULL)
return;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
its.it_value.tv_sec = delay / 1000;
its.it_value.tv_nsec = 1000000 * (delay % 1000);
if(its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
{
// this would inadvertently stop the timer
its.it_value.tv_nsec = 1;
}
timers[TimerId].callback = cb;
timers[TimerId].pContext = usercontext;
timers[TimerId].nIsStopped = 0;
timer_settime(timers[TimerId].handle, 0, &its, NULL);
}
void framework_TimerStop(void* timer)
{
struct itimerspec its = {{0, 0}, {0, 0}};
uint32_t TimerId = *((uint32_t *) timer);
if(TimerId >= MAX_NO_TIMERS)
return;
if(timers[TimerId].callback == NULL)
return;
if(timers[TimerId].nIsStopped == 1)
return;
timers[TimerId].nIsStopped = 1;
timer_settime(timers[TimerId].handle, 0, &its, NULL);
}
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include "TML/inc/framework_linux.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
// **************************************** Log functions
void framework_Log(const char* format, ...)
{
char buffer[1024];
va_list varg;
va_start(varg, format);
strcpy(buffer, "LOG : ");
vsprintf(&buffer[10], format, varg);
va_end(varg);
logmsg(buffer);
}
void framework_Warn(const char* format, ...)
{
char buffer[1024];
va_list varg;
va_start(varg, format);
strcpy(buffer, "WARNING : ");
vsprintf(&buffer[10], format, varg);
va_end(varg);
logmsg(buffer);
}
void framework_Error(const char* format, ...)
{
char buffer[1024];
va_list varg;
va_start(varg, format);
strcpy(buffer, "ERROR : ");
vsprintf(&buffer[10], format, varg);
va_end(varg);
logmsg(buffer);
}
void framework_HexDump(const void * buffer, uint32_t size)
{
HexDump(buffer,size);
}
// Internal function
void HexDump(const void * buffer, uint32_t size)
{
char tmpBuff[128];
uint8_t *dataBuffer = (uint8_t*)buffer;
uint32_t i = 0;
uint32_t buffIter = 0;
uint32_t tmpI = 0;
while (i < size)
{
buffIter = 0;
tmpI = i;
while ((tmpI < size) && (buffIter < 24))
{
sprintf(tmpBuff + buffIter, "%.2X ", dataBuffer[tmpI]);
buffIter += 3;
tmpI++;
}
tmpI = i;
while ((tmpI < size) && (buffIter < 32))
{
if (dataBuffer[tmpI] == '%')
{
tmpBuff[buffIter++] = '%';
tmpBuff[buffIter++] = '%';
}else if (dataBuffer[tmpI] >= 32)
{
tmpBuff[buffIter++] = dataBuffer[tmpI];
}
else
{
tmpBuff[buffIter++] = '.';
}
tmpI++;
}
i = tmpI;
tmpBuff[buffIter++] = '\n';
tmpBuff[buffIter++] = 0;
framework_Log(tmpBuff);
}
}
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include "TML/inc/framework_linux.h"
#include "TML/inc/framework_Allocator.h"
// **************************************** OS Specific functions
#include <pthread.h>
#include <errno.h>
#include <string.h>
typedef struct tLinuxMutex
{
pthread_mutex_t *lock;
pthread_cond_t *cond;
}tLinuxMutex_t;
eResult framework_CreateMutex(void ** mutexHandle)
{
tLinuxMutex_t *mutex = (tLinuxMutex_t *)framework_AllocMem(sizeof(tLinuxMutex_t));
mutex->lock = (pthread_mutex_t*)framework_AllocMem(sizeof(pthread_mutex_t));
mutex->cond = (pthread_cond_t*)framework_AllocMem(sizeof(pthread_cond_t));
pthread_mutex_init(mutex->lock,NULL);
pthread_cond_init(mutex->cond,NULL);
*mutexHandle = mutex;
return FRAMEWORK_SUCCESS;
}
void framework_LockMutex(void * mutexHandle)
{
tLinuxMutex_t *mutex = (tLinuxMutex_t*)mutexHandle;
int res = pthread_mutex_lock(mutex->lock);
if (res)
{
framework_Error("lock() failed errno %i\n",strerror (errno));
}
}
void framework_UnlockMutex(void * mutexHandle)
{
tLinuxMutex_t *mutex = (tLinuxMutex_t*)mutexHandle;
int res = pthread_mutex_unlock(mutex->lock);
if (res)
{
framework_Error("unlock() failed %s\n",strerror (errno));
}
}
void framework_WaitMutex(void * mutexHandle, uint8_t needLock)
{
tLinuxMutex_t *mutex = (tLinuxMutex_t*)mutexHandle;
if (needLock)
{
framework_LockMutex(mutexHandle);
}
pthread_cond_wait(mutex->cond,mutex->lock);
if (needLock)
{
framework_UnlockMutex(mutexHandle);
}
}
void framework_NotifyMutex(void * mutexHandle, uint8_t needLock)
{
tLinuxMutex_t *mutex = (tLinuxMutex_t*)mutexHandle;
if (needLock)
{
framework_LockMutex(mutexHandle);
}
pthread_cond_broadcast(mutex->cond);
if (needLock)
{
framework_UnlockMutex(mutexHandle);
}
}
void framework_DeleteMutex(void * mutexHandle)
{
tLinuxMutex_t *mutex = (tLinuxMutex_t*)mutexHandle;
pthread_mutex_destroy(mutex->lock);
pthread_cond_destroy(mutex->cond);
framework_FreeMem(mutex);
}
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include <TML/inc/framework_linux.h>
#include <TML/inc/framework_Allocator.h>
// ####################### Semaphore Generic implementation.
typedef struct tGenericSemaphore
{
int8_t counter;
void *mutex;
}tGenericSemaphore_t;
eResult framework_CreateSemaphore(void ** semaphoreHandle)
{
tGenericSemaphore_t *sem = (tGenericSemaphore_t *)framework_AllocMem(sizeof(tGenericSemaphore_t));
sem->counter = 0;
framework_CreateMutex(&(sem->mutex));
*semaphoreHandle = sem;
return FRAMEWORK_SUCCESS;
}
void framework_WaitSemaphore(void * semaphoreHandle)
{
tGenericSemaphore_t *sem = (tGenericSemaphore_t *)semaphoreHandle;
framework_LockMutex(sem->mutex);
sem->counter++;
if (sem->counter > 0)
{
framework_WaitMutex(sem->mutex, 0);
}
framework_UnlockMutex(sem->mutex);
}
void framework_PostSemaphore(void * semaphoreHandle)
{
tGenericSemaphore_t *sem = (tGenericSemaphore_t *)semaphoreHandle;
uint8_t needWakeUp = 0;
framework_LockMutex(sem->mutex);
if (sem->counter > 0)
{
needWakeUp = 1;
}
sem->counter--;
if (needWakeUp)
{
framework_NotifyMutex(sem->mutex, 0);
}
framework_UnlockMutex(sem->mutex);
}
void framework_DeleteSemaphore(void * semaphoreHandle)
{
tGenericSemaphore_t *sem = (tGenericSemaphore_t *)semaphoreHandle;
framework_DeleteMutex(sem->mutex);
framework_FreeMem(sem);
}
/**************************************************************************
* Copyright (C) 2015 Eff'Innov Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Developped by Eff'Innov Technologies : contact@effinnov.com
*
**************************************************************************/
#include "TML/inc/framework_linux.h"
#include "TML/inc/framework_Allocator.h"
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
// **************************************** OS Specific functions
typedef struct tLinuxThread
{
pthread_t thread;
void* ctx;
void* (*threadedFunc)(void *);
void* mutexCanDelete;
}tLinuxThread_t;
void* thread_object_func(void* obj)
{
tLinuxThread_t *linuxThread = (tLinuxThread_t *)obj;
void *res = NULL;
framework_LockMutex(linuxThread->mutexCanDelete);
res = linuxThread->threadedFunc(linuxThread->ctx);
framework_UnlockMutex(linuxThread->mutexCanDelete);
return res;
}
eResult framework_CreateThread(void** threadHandle, void * (* threadedFunc)(void *) , void * ctx)
{
tLinuxThread_t *linuxThread = (tLinuxThread_t *)framework_AllocMem(sizeof(tLinuxThread_t));
linuxThread->ctx = ctx;
linuxThread->threadedFunc = threadedFunc;
framework_CreateMutex(&(linuxThread->mutexCanDelete));
if (pthread_create(&(linuxThread->thread), NULL, thread_object_func, linuxThread))
{
framework_Error("Cannot create Thread\n");
framework_DeleteMutex(linuxThread->mutexCanDelete);
framework_FreeMem(linuxThread);
return FRAMEWORK_FAILED;
}
pthread_detach(linuxThread->thread);
*threadHandle = linuxThread;
return FRAMEWORK_SUCCESS;
}
void framework_JoinThread(void * threadHandle)
{
tLinuxThread_t *linuxThread = (tLinuxThread_t*)threadHandle;
if (pthread_self() != linuxThread->thread)
{
// Will cause block if thread still running !!!
framework_LockMutex(linuxThread->mutexCanDelete);
framework_UnlockMutex(linuxThread->mutexCanDelete);
// Thread now just ends up !
}
}
void framework_DeleteThread(void * threadHandle)
{
tLinuxThread_t *linuxThread = (tLinuxThread_t*)threadHandle;
framework_DeleteMutex(linuxThread->mutexCanDelete);
framework_FreeMem(linuxThread);
}
void * framework_GetCurrentThreadId()
{
return (void*)pthread_self();
}
void * framework_GetThreadId(void * threadHandle)
{
tLinuxThread_t *linuxThread = (tLinuxThread_t*)threadHandle;
return (void*)linuxThread->thread;
}
void framework_MilliSleep(uint32_t ms)
{
usleep(1000*ms);
}
/*******************************************************
HIDAPI - Multi-Platform library for
communication with HID devices.
Alan Ott
Signal 11 Software
8/22/2009
Linux Version - 6/2/2009
Copyright 2009, All Rights Reserved.
At the discretion of the user of this library,
this software may be licensed under the terms of the
GNU Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution.
These files may also be found in the public source
code repository located at:
http://github.com/signal11/hidapi .
********************************************************/
/* C */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#include <errno.h>
/* Unix */
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <fcntl.h>
#include <poll.h>
/* Linux */
#include <linux/hidraw.h>
#include <linux/version.h>
#include <libudev.h>
#include "TML/inc/hidapi.h"
/* Definitions from linux/hidraw.h. Since these are new, some distros
may not have header files which contain them. */
#ifndef HIDIOCSFEATURE
#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
#endif
#ifndef HIDIOCGFEATURE
#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
#endif
struct hid_device_ {
int device_handle;
int blocking;
int uses_numbered_reports;
};
static __u32 kernel_version = 0;
hid_device *new_hid_device()
{
hid_device *dev = calloc(1, sizeof(hid_device));
dev->device_handle = -1;
dev->blocking = 1;
dev->uses_numbered_reports = 0;
return dev;
}
/* Get an attribute value from a udev_device and return it as a whar_t
string. The returned string must be freed with free() when done.*/
static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
{
const char *str;
wchar_t *ret = NULL;
str = udev_device_get_sysattr_value(dev, udev_name);
if (str) {
/* Convert the string from UTF-8 to wchar_t */
size_t wlen = mbstowcs(NULL, str, 0);
ret = calloc(wlen+1, sizeof(wchar_t));
mbstowcs(ret, str, wlen+1);
ret[wlen] = 0x0000;
}
return ret;
}
/* uses_numbered_reports() returns 1 if report_descriptor describes a device
which contains numbered reports. */
static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
int i = 0;
int size_code;
int data_len, key_size;
while (i < size) {
int key = report_descriptor[i];
/* Check for the Report ID key */
if (key == 0x85/*Report ID*/) {
/* This device has a Report ID, which means it uses
numbered reports. */
return 1;
}
//printf("key: %02hhx\n", key);
if ((key & 0xf0) == 0xf0) {
/* This is a Long Item. The next byte contains the
length of the data section (value) for this key.
See the HID specification, version 1.11, section
6.2.2.3, titled "Long Items." */
if (i+1 < size)
data_len = report_descriptor[i+1];
else
data_len = 0; /* malformed report */
key_size = 3;
}
else {
/* This is a Short Item. The bottom two bits of the
key contain the size code for the data section
(value) for this key. Refer to the HID
specification, version 1.11, section 6.2.2.2,
titled "Short Items." */
size_code = key & 0x3;
switch (size_code) {
case 0:
case 1:
case 2:
data_len = size_code;
break;
case 3:
data_len = 4;
break;
default:
/* Can't ever happen since size_code is & 0x3 */
data_len = 0;
break;
};
key_size = 1;
}
/* Skip over this key and it's associated data */
i += data_len + key_size;
}
/* Didn't find a Report ID key. Device doesn't use numbered reports. */
return 0;
}
static int get_device_string(hid_device *dev, const char *key, wchar_t *string, size_t maxlen)
{
struct udev *udev;
struct udev_device *udev_dev, *parent;
struct stat s;
int ret = -1;
setlocale(LC_ALL,"");
/* Create the udev object */
udev = udev_new();
if (!udev) {
//printf("Can't create udev\n");
return -1;
}
/* Get the dev_t (major/minor numbers) from the file handle. */
fstat(dev->device_handle, &s);
/* Open a udev device from the dev_t. 'c' means character device. */
udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev);
if (udev_dev) {
const char *str;
/* Find the parent USB Device */
parent = udev_device_get_parent_with_subsystem_devtype(
udev_dev,
"usb",
"usb_device");
if (parent) {
str = udev_device_get_sysattr_value(parent, key);
if (str) {
/* Convert the string from UTF-8 to wchar_t */
ret = mbstowcs(string, str, maxlen);
goto end;
}
}
}
end:
udev_device_unref(udev_dev);
// parent doesn't need to be (and can't be) unref'd.
// I'm not sure why, but it'll throw double-free() errors.
udev_unref(udev);
return ret;
}
int HID_API_EXPORT hid_init(void)
{
/* Nothing to do for this in the Linux/hidraw implementation. */
return 0;
}
int HID_API_EXPORT hid_exit(void)
{
/* Nothing to do for this in the Linux/hidraw implementation. */
return 0;
}
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
struct udev *udev;
struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *dev_list_entry;
struct hid_device_info *root = NULL; // return object
struct hid_device_info *cur_dev = NULL;
setlocale(LC_ALL,"");
/* Create the udev object */
udev = udev_new();
if (!udev) {
//printf("Can't create udev\n");
return NULL;
}
/* Create a list of the devices in the 'hidraw' subsystem. */
enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "hidraw");
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
/* For each item, see if it matches the vid/pid, and if so
create a udev_device record for it */
udev_list_entry_foreach(dev_list_entry, devices) {
const char *sysfs_path;
const char *dev_path;
const char *str;
struct udev_device *hid_dev; // The device's HID udev node.
struct udev_device *dev; // The actual hardware device.
struct udev_device *intf_dev; // The device's interface (in the USB sense).
unsigned short dev_vid;
unsigned short dev_pid;
/* Get the filename of the /sys entry for the device
and create a udev_device object (dev) representing it */
sysfs_path = udev_list_entry_get_name(dev_list_entry);
hid_dev = udev_device_new_from_syspath(udev, sysfs_path);
dev_path = udev_device_get_devnode(hid_dev);
/* The device pointed to by hid_dev contains information about
the hidraw device. In order to get information about the
USB device, get the parent device with the
subsystem/devtype pair of "usb"/"usb_device". This will
be several levels up the tree, but the function will find
it.*/
dev = udev_device_get_parent_with_subsystem_devtype(
hid_dev,
"usb",
"usb_device");
if (!dev) {
/* Unable to find parent usb device. */
goto next;
}
/* Get the VID/PID of the device */
str = udev_device_get_sysattr_value(dev,"idVendor");
dev_vid = (str)? strtol(str, NULL, 16): 0x0;
str = udev_device_get_sysattr_value(dev, "idProduct");
dev_pid = (str)? strtol(str, NULL, 16): 0x0;
/* Check the VID/PID against the arguments */
if ((vendor_id == 0x0 && product_id == 0x0) ||
(vendor_id == dev_vid && product_id == dev_pid)) {
struct hid_device_info *tmp;
size_t len;
/* VID/PID match. Create the record. */
tmp = malloc(sizeof(struct hid_device_info));
if (cur_dev) {
cur_dev->next = tmp;
}
else {
root = tmp;
}
cur_dev = tmp;
/* Fill out the record */
cur_dev->next = NULL;
str = dev_path;
if (str) {
len = strlen(str);
cur_dev->path = calloc(len+1, sizeof(char));
strncpy(cur_dev->path, str, len+1);
cur_dev->path[len] = '\0';
}
else
cur_dev->path = NULL;
/* Serial Number */
cur_dev->serial_number
= copy_udev_string(dev, "serial");
/* Manufacturer and Product strings */
cur_dev->manufacturer_string
= copy_udev_string(dev, "manufacturer");
cur_dev->product_string
= copy_udev_string(dev, "product");
/* VID/PID */
cur_dev->vendor_id = dev_vid;
cur_dev->product_id = dev_pid;
/* Release Number */
str = udev_device_get_sysattr_value(dev, "bcdDevice");
cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0;
/* Interface Number */
cur_dev->interface_number = -1;
/* Get a handle to the interface's udev node. */
intf_dev = udev_device_get_parent_with_subsystem_devtype(
hid_dev,
"usb",
"usb_interface");
if (intf_dev) {
str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber");
cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1;
}
}
else
goto next;
next:
udev_device_unref(hid_dev);
/* dev and intf_dev don't need to be (and can't be)
unref()d. It will cause a double-free() error. I'm not
sure why. */
}
/* Free the enumerator and udev objects. */
udev_enumerate_unref(enumerate);
udev_unref(udev);
return root;
}
void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
{
struct hid_device_info *d = devs;
while (d) {
struct hid_device_info *next = d->next;
free(d->path);
free(d->serial_number);
free(d->manufacturer_string);
free(d->product_string);
free(d);
d = next;
}
}
hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, wchar_t *serial_number)
{
struct hid_device_info *devs, *cur_dev;
const char *path_to_open = NULL;
hid_device *handle = NULL;
devs = hid_enumerate(vendor_id, product_id);
cur_dev = devs;
while (cur_dev) {
if (cur_dev->vendor_id == vendor_id &&
cur_dev->product_id == product_id) {
if (serial_number) {
if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
path_to_open = cur_dev->path;
break;
}
}
else {
path_to_open = cur_dev->path;
break;
}
}
cur_dev = cur_dev->next;
}
if (path_to_open) {
/* Open the device */
handle = hid_open_path(path_to_open);
}
hid_free_enumeration(devs);
return handle;
}
hid_device * HID_API_EXPORT hid_open_path(const char *path)
{
hid_device *dev = NULL;
dev = new_hid_device();
if (kernel_version == 0) {
struct utsname name;
int major, minor, release;
int ret;
uname(&name);
ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release);
if (ret == 3) {
kernel_version = major << 16 | minor << 8 | release;
//printf("Kernel Version: %d\n", kernel_version);
}
else {
//printf("Couldn't sscanf() version string %s\n", name.release);
}
}
// OPEN HERE //
dev->device_handle = open(path, O_RDWR);
// If we have a good handle, return it.
if (dev->device_handle > 0) {
/* Get the report descriptor */
int res, desc_size = 0;
struct hidraw_report_descriptor rpt_desc;
memset(&rpt_desc, 0x0, sizeof(rpt_desc));
/* Get Report Descriptor Size */
res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
if (res < 0)
perror("HIDIOCGRDESCSIZE");
/* Get Report Descriptor */
rpt_desc.size = desc_size;
res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc);
if (res < 0) {
perror("HIDIOCGRDESC");
} else {
/* Determine if this device uses numbered reports. */
dev->uses_numbered_reports =
uses_numbered_reports(rpt_desc.value,
rpt_desc.size);
}
return dev;
}
else {
// Unable to open any devices.
free(dev);
return NULL;
}
}
int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
{
int bytes_written;
// {int i, len=data[1]; unsigned char *p=data; printf("HID>>"); for(i=0; i<len; i++) printf("%02x", p[i]); printf("\n");}
bytes_written = write(dev->device_handle, data, length);
return bytes_written;
}
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
{
int bytes_read;
if (milliseconds != 0) {
int ret;
struct pollfd fds;
fds.fd = dev->device_handle;
fds.events = POLLIN;
fds.revents = 0;
ret = poll(&fds, 1, milliseconds);
if (ret == -1 || ret == 0)
return ret;
}
bytes_read = read(dev->device_handle, data, length);
if (bytes_read < 0 && errno == EAGAIN)
bytes_read = 0;
// {int i, len=data[0]; unsigned char *p=data; printf("HID<<"); for(i=0; i<len; i++) printf("%02x", p[i]); printf("\n");}
if (bytes_read >= 0 &&
kernel_version < KERNEL_VERSION(2,6,34) &&
dev->uses_numbered_reports) {
/* Work around a kernel bug. Chop off the first byte. */
memmove(data, data+1, bytes_read);
bytes_read--;
}
return bytes_read;
}
int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
{
return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
}
int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
{
int flags, res;
flags = fcntl(dev->device_handle, F_GETFL, 0);
if (flags >= 0) {
if (nonblock)
res = fcntl(dev->device_handle, F_SETFL, flags | O_NONBLOCK);
else
res = fcntl(dev->device_handle, F_SETFL, flags & ~O_NONBLOCK);
}
else
return -1;
if (res < 0) {
return -1;
}
else {
dev->blocking = !nonblock;
return 0; /* Success */
}
}
int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
{
int res;
res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data);
if (res < 0)
perror("ioctl (SFEATURE)");
return res;
}
int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
{
int res;
res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
if (res < 0)
perror("ioctl (GFEATURE)");
return res;
}
void HID_API_EXPORT hid_close(hid_device *dev)
{
if (!dev)
return;
close(dev->device_handle);
free(dev);
}
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
{
return get_device_string(dev, "manufacturer", string, maxlen);
}
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
{
return get_device_string(dev, "product", string, maxlen);
}
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
{
return get_device_string(dev, "serial", string, maxlen);
}
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
{
return -1;
}
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
{
return NULL;
}
/*
* @brief LPC USB serial I/O interface definition
*
* @note
* Copyright(C) NXP Semiconductors, 2013
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include <string.h>
#include <stdlib.h>
#include "TML/inc/hidapi.h"
#include "TML/inc/lpcusbsio.h"
#include "TML/inc/lpcusbsio_i2c.h"
#include "TML/inc/framework_Interface.h"
#include "TML/inc/framework_Map.h"
#include "TML/inc/framework_Container.h"
/* ###############
TODO LIST
----------
- cpu_to _le conversion
- Reset
*/
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
#define NUM_LIB_ERR_STRINGS 3
#define NUM_FW_ERR_STRINGS 6
#define NUM_BRIDGE_ERR_STRINGS 4
#define MAX_XFER_TX_LENGTH (HID_I2C_PACKET_SZ - sizeof(HID_I2C_OUT_REPORT_T) - sizeof(HID_I2C_XFER_PARAMS_T))
#define MAX_XFER_RX_LENGTH (HID_I2C_PACKET_SZ - sizeof(HID_I2C_IN_REPORT_T))
typedef struct LPCUSBSIO_Request
{
uint8_t transId;
int32_t status;
uint8_t *outPacket;
uint32_t outPacketLen;
uint8_t *inPacket;
uint32_t inPacketLen;
void* notifier;
}LPCUSBSIO_Request_t;
typedef struct LPCUSBSIO_I2C_Ctrl {
struct hid_device_info *hidInfo;
hid_device *hidDev;
char fwVersion[60];
uint8_t sesionId;
void* request_map;
void* RequestMapLock;
uint8_t thread_exit;
void* ResponsethreadHandle;
void* SendLock;
void* NotifierContainer;
void* NotifierContainerLock;
struct LPCUSBSIO_I2C_Ctrl *next;
} LPCUSBSIO_I2C_Ctrl_t;
struct LPCUSBSIO_Ctrl {
struct hid_device_info *devInfoList;
LPCUSBSIO_I2C_Ctrl_t *devList;
};
//static const char *g_LibVersion = "LPCUSBSIO v1.00 (" __DATE__ " " __TIME__ ")";
static const char *g_fwInitVer = "FW Ver Unavailable";
static struct LPCUSBSIO_Ctrl g_Ctrl = {0, };
static const wchar_t *g_LibErrMsgs[NUM_LIB_ERR_STRINGS] = {
L"No errors are recorded.",
L"HID library error.", /* LPCUSBSIO_ERR_HID_LIB */
L"Handle passed to the function is invalid.", /* LPCUSBSIO_ERR_BAD_HANDLE */
};
static const wchar_t *g_fwErrMsgs[NUM_FW_ERR_STRINGS] = {
L"Firmware error.", /* catch-all firmware error */
L"Fatal error happened", /* LPCUSBSIO_ERR_FATAL */
L"Transfer aborted due to NAK", /* LPCUSBSIO_ERR_I2C_NAK */
L"Transfer aborted due to bus error", /* LPCUSBSIO_ERR_I2C_BUS */
L"No acknowledgement received from slave address", /* LPCUSBSIO_ERR_I2C_SLAVE_NAK */
L"I2C bus arbitration lost to other master", /* LPCUSBSIO_ERR_I2C_SLAVE_NAK */
};
static const wchar_t *g_BridgeErrMsgs[NUM_BRIDGE_ERR_STRINGS] = {
L"Transaction timed out.", /* LPCUSBSIO_ERR_TIMEOUT */
L"Invalid HID_I2C Request or Request not supported in this version.", /* LPCUSBSIO_ERR_INVALID_CMD */
L"Invalid parameters are provided for the given Request.", /* LPCUSBSIO_ERR_INVALID_PARAM */
L" Partial transfer completed.", /* LPCUSBSIO_ERR_PARTIAL_DATA */
};
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
void* getNotifier(LPCUSBSIO_I2C_Ctrl_t * dev)
{
CONTAINER_STATUS lContainerStatus = CONTAINER_SUCCESS;
uint32_t size = 0x00;
void* Notifier = NULL;
if(NULL != dev)
{
framework_LockMutex(dev->NotifierContainerLock);
if(NULL == dev->NotifierContainer)
{
lContainerStatus = container_create(&dev->NotifierContainer, 2);
}
if (CONTAINER_SUCCESS == lContainerStatus)
{
lContainerStatus = container_size(dev->NotifierContainer, &size);
if(0x00 == size)
{
framework_CreateMutex(&Notifier);
}
else
{
container_remove(dev->NotifierContainer, 0x00, &Notifier);
}
}
framework_UnlockMutex(dev->NotifierContainerLock);
}
return Notifier;
}
void FreeNotifier(LPCUSBSIO_I2C_Ctrl_t * dev, void* Notifier)
{
if(NULL != dev)
{
framework_LockMutex(dev->NotifierContainerLock);
if(NULL != dev->NotifierContainer && NULL != Notifier)
{
container_add(dev->NotifierContainer, Notifier);
}
framework_UnlockMutex(dev->NotifierContainerLock);
}
}
void ReleaseNotifier(LPCUSBSIO_I2C_Ctrl_t * dev)
{
void* Notifier = NULL;
if(NULL != dev)
{
framework_LockMutex(dev->NotifierContainerLock);
if(NULL != dev->NotifierContainer)
{
do
{
container_remove(dev->NotifierContainer, 0x00, &Notifier);
if(NULL != Notifier)
{
framework_DeleteMutex(Notifier);
Notifier = NULL;
}
}while(NULL != Notifier);
container_delete(dev->NotifierContainer);
dev->NotifierContainer = NULL;
}
framework_UnlockMutex(dev->NotifierContainerLock);
}
}
static struct hid_device_info *GetDevAtIndex(uint32_t index) {
struct hid_device_info *cur_dev = g_Ctrl.devInfoList;
uint32_t count = 0;
while (cur_dev) {
if (count++ == index) {
break;
}
cur_dev = cur_dev->next;
}
return cur_dev;
}
static int32_t validHandle(LPCUSBSIO_I2C_Ctrl_t *dev)
{
LPCUSBSIO_I2C_Ctrl_t *curDev = g_Ctrl.devList;
while (dev != curDev) {
curDev = curDev->next;
}
return (curDev == NULL) ? 0 : 1;
}
static void freeDevice(LPCUSBSIO_I2C_Ctrl_t *dev)
{
LPCUSBSIO_I2C_Ctrl_t *curDev = g_Ctrl.devList;
if (curDev == dev) {
g_Ctrl.devList = dev->next;
}
else {
while (curDev) {
if (curDev->next == dev) {
/* update linked list */
curDev->next = dev->next;
break;
}
}
}
free(dev);
/* unload HID library if all devices are closed. */
if (g_Ctrl.devList == NULL) {
hid_free_enumeration(g_Ctrl.devInfoList);
hid_exit();
}
}
static const wchar_t *GetErrorString(int32_t err)
{
const wchar_t *retStr = g_LibErrMsgs[0];
int index;
index = abs(err);
if (index < 0x10) {
retStr = (index < NUM_LIB_ERR_STRINGS) ? g_LibErrMsgs[index] : g_LibErrMsgs[0];
}
else if (index < 0x20) {
index -= 0x10;
retStr = (index < NUM_FW_ERR_STRINGS) ? g_fwErrMsgs[index] : g_fwErrMsgs[0];
}
else if (index < 0x20) {
index -= 0x30;
retStr = (index < NUM_BRIDGE_ERR_STRINGS) ? g_BridgeErrMsgs[index] : g_LibErrMsgs[0];
}
return retStr;
}
static int32_t ConvertResp(int32_t res)
{
int ret;
if (res == HID_I2C_RES_OK) {
ret = LPCUSBSIO_OK;
}
else {
ret = -(res + 0x10);
}
return ret;
}
static void* WaitRequestResponse(void* pContext)
{
LPCUSBSIO_I2C_Ctrl_t * dev = pContext;
HID_I2C_IN_REPORT_T *pIn;
uint8_t inPacket[HID_I2C_PACKET_SZ + 1];
int32_t res = 0;
LPCUSBSIO_Request_t* lRequest;
STATUS lMapStatus = SUCCESS;
void* Notifier = NULL;
uint32_t ReadIndex = 0x00;
uint32_t lenght = 0x00;
while (0x01 != dev->thread_exit)
{
ReadIndex = 0x00;
res = hid_read_timeout(dev->hidDev, inPacket, sizeof(inPacket), LPCUSBSIO_READ_TMO);
if (res > 0)
{
pIn = (HID_I2C_IN_REPORT_T *) &inPacket[0];
framework_LockMutex(dev->RequestMapLock);
lMapStatus = map_get(dev->request_map, (void*) (intptr_t) pIn->transId, (void**) &lRequest);
framework_UnlockMutex(dev->RequestMapLock);
if(SUCCESS == lMapStatus)
{
ReadIndex += HID_I2C_PACKET_SZ;
/* check reponse received from LPC */
lenght = pIn->length;
memcpy(lRequest->inPacket, inPacket, HID_I2C_PACKET_SZ);
while (ReadIndex < lenght)
{
res = hid_read_timeout(dev->hidDev, inPacket, sizeof(inPacket), LPCUSBSIO_READ_TMO);
if (res > 0)
{
memcpy(&lRequest->inPacket[ReadIndex], inPacket, HID_I2C_PACKET_SZ);
ReadIndex += HID_I2C_PACKET_SZ;
}
}
pIn = (HID_I2C_IN_REPORT_T *)&lRequest->inPacket[0];
Notifier = lRequest->notifier;
/* update status */
res = ConvertResp(pIn->resp);
lRequest->status = res;
lRequest->inPacketLen = HID_I2C_PACKET_SZ + 1;
//memcpy(lRequest->inPacket, inPacket, (HID_I2C_PACKET_SZ + 1));
framework_LockMutex(Notifier);
framework_NotifyMutex(Notifier, 0);
framework_UnlockMutex(Notifier);
Notifier = NULL;
}
else
{
/*Transition ID received form the chip not recognized !!!!!! why ??????*/
//TODO : define the behaviour in this case
res = LPCUSBSIO_ERR_HID_LIB;
}
}
else if (res == 0)
{
res = LPCUSBSIO_ERR_TIMEOUT;
}
else
{
}
}
return NULL;
}
static int32_t I2C_SendRequest(LPCUSBSIO_I2C_Ctrl_t *dev, uint8_t req, uint8_t* dataOut, uint32_t dataOutLen, uint8_t* dataIn, uint32_t dataInLen)
{
int32_t res = 0;
static uint32_t ReqIndice = 0x00;
STATUS lMapStatus = SUCCESS;
uint8_t outPacket[HID_I2C_PACKET_SZ + 1];
HID_I2C_OUT_REPORT_T *pOut;
LPCUSBSIO_Request_t lRequest;
uint32_t pos = 0x00;
uint32_t offset = HID_I2C_HEADER_SZ + 1;
lRequest.outPacket = dataOut;
lRequest.outPacketLen = dataOutLen;
lRequest.inPacket = dataIn;
lRequest.inPacketLen = dataInLen;
lRequest.status = LPCUSBSIO_OK;
pOut = (HID_I2C_OUT_REPORT_T *) &outPacket[1];
pOut->sesId = dev->sesionId;
pOut->transId = lRequest.transId = ReqIndice++;
pOut->req = req;
pOut->length = HID_I2C_HEADER_SZ + dataOutLen;
framework_LockMutex(dev->RequestMapLock);
lMapStatus = map_add(dev->request_map, (void*) (intptr_t) lRequest.transId, (void*) &lRequest);
framework_UnlockMutex(dev->RequestMapLock);
if(SUCCESS == lMapStatus)
{
//framework_CreateMutex(&lRequest.notifier);
lRequest.notifier = getNotifier(dev);
framework_LockMutex(lRequest.notifier);
framework_LockMutex(dev->SendLock);
//do
//{
outPacket[0] = 0;
if(lRequest.outPacket != NULL) memcpy(&outPacket[offset], lRequest.outPacket + pos, HID_I2C_PACKET_SZ + 1 - offset);
res = hid_write(dev->hidDev, outPacket, HID_I2C_PACKET_SZ + 1);
// if (HID_I2C_PACKET_SZ + 1 == res)
// {
// pos += HID_I2C_PACKET_SZ - offset + 1;
// offset = 0x01;
// }
//} while (pos < len);
framework_UnlockMutex(dev->SendLock);
if(0x00 < res)
{
framework_WaitMutex(lRequest.notifier, 0);
framework_UnlockMutex(lRequest.notifier);
res = lRequest.status;
}
else
{
framework_UnlockMutex(lRequest.notifier);
res = LPCUSBSIO_ERR_HID_LIB;
}
framework_LockMutex(dev->RequestMapLock);
map_remove(dev->request_map, (void*) (intptr_t) lRequest.transId);
framework_UnlockMutex(dev->RequestMapLock);
FreeNotifier(dev, lRequest.notifier);
//framework_DeleteMutex(lRequest.notifier);
lRequest.notifier = NULL;
}
else
{
res = LPCUSBSIO_ERR_HID_LIB;
}
return res;
}
/*****************************************************************************
* Public functions
****************************************************************************/
LPCUSBSIO_API int32_t I2C_GetNumPorts(void)
{
struct hid_device_info *cur_dev;
int32_t count = 0;
/* free any HID device structures if we were called previously */
if (g_Ctrl.devInfoList != NULL) {
hid_free_enumeration(g_Ctrl.devInfoList);
g_Ctrl.devInfoList = NULL;
}
g_Ctrl.devInfoList = hid_enumerate(LPCUSBSIO_VID, LPCUSBSIO_PID);
cur_dev = g_Ctrl.devInfoList;
while (cur_dev) {
count++;
cur_dev = cur_dev->next;
}
return count;
}
LPCUSBSIO_API LPC_HANDLE I2C_Open(uint32_t index)
{
hid_device *pHid = NULL;
LPCUSBSIO_I2C_Ctrl_t *dev = NULL;
struct hid_device_info *cur_dev;
cur_dev = GetDevAtIndex(index);
if (cur_dev)
{
pHid = hid_open_path(cur_dev->path);
if (pHid)
{
dev = malloc(sizeof(LPCUSBSIO_I2C_Ctrl_t));
memset(dev, 0, sizeof(LPCUSBSIO_I2C_Ctrl_t));
dev->hidDev = pHid;
dev->hidInfo = cur_dev;
dev->sesionId = rand();
map_create(&dev->request_map);
memcpy(&dev->fwVersion[0], g_fwInitVer, strlen(g_fwInitVer));
/* insert at top */
dev->next = g_Ctrl.devList;
g_Ctrl.devList = dev;
/* Set all calls to this hid device as blocking. */
// hid_set_nonblocking(dev->hidDev, 0);
framework_CreateMutex(&dev->SendLock);
framework_CreateMutex(&dev->RequestMapLock);
framework_CreateMutex(&dev->NotifierContainerLock);
dev->thread_exit = 0x00;
framework_CreateThread(&dev->ResponsethreadHandle , WaitRequestResponse, dev);
}
}
return (LPC_HANDLE) dev;
}
LPCUSBSIO_API int32_t I2C_Init(LPC_HANDLE handle, I2C_PORTCONFIG_T *config)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
uint8_t outPacket[HID_I2C_PACKET_SZ + 1];
uint8_t inPacket[HID_I2C_PACKET_SZ + 1];
int32_t res;
HID_I2C_IN_REPORT_T *pIn;
if ((validHandle(handle) == 0) || (config == NULL))
{
return LPCUSBSIO_ERR_BAD_HANDLE;
}
memcpy(outPacket, config, sizeof(I2C_PORTCONFIG_T));
res = I2C_SendRequest(dev, HID_I2C_REQ_INIT_PORT, outPacket, sizeof(I2C_PORTCONFIG_T), inPacket, sizeof(inPacket));
if (res == LPCUSBSIO_OK)
{
/* parse response */
pIn = (HID_I2C_IN_REPORT_T *) &inPacket[0];
res = pIn->length - HID_I2C_HEADER_SZ;
/* copy data back to user buffer */
memcpy(&dev->fwVersion[0], &pIn->data[0], res);
}
return res;
}
LPCUSBSIO_API int32_t I2C_CancelAllRequest(LPC_HANDLE handle)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
uint32_t lMapLenght = 0x00, i;
LPCUSBSIO_Request_t* lRequest = NULL;
void* Notifier = NULL;
framework_LockMutex(dev->RequestMapLock);
//1rst call => we get map lenght
map_getAll(dev->request_map, NULL, (int*)&lMapLenght);
lRequest = malloc(lMapLenght * sizeof(LPCUSBSIO_Request_t));
//2nd call => we get all object in map
map_getAll(dev->request_map, (void **) &lRequest, (int*) &lMapLenght);
for (i = 0x00; i < lMapLenght; i++)
{
//Cancel request
if (NULL != lRequest[i].notifier)
{
lRequest[i].status = LPCUSBSIO_REQ_CANCELED;
Notifier = lRequest[i].notifier;
framework_LockMutex(Notifier);
framework_NotifyMutex(Notifier, 0);
framework_UnlockMutex(Notifier);
Notifier = NULL;
}
}
framework_UnlockMutex(dev->RequestMapLock);
return 0;
}
LPCUSBSIO_API int32_t I2C_Close(LPC_HANDLE handle)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
uint8_t inPacket[HID_I2C_PACKET_SZ + 1];
if (validHandle(handle) == 0)
{
return LPCUSBSIO_ERR_BAD_HANDLE;
}
I2C_SendRequest(dev, HID_I2C_REQ_DEINIT_PORT, NULL, 0, inPacket, sizeof(inPacket));
/*Shutdown reader thread*/
dev->thread_exit = 0x01;
/*Close remote dev handle : all pending request are canceled*/
hid_close(dev->hidDev);
/*Wait End of reader thread & clean up*/
framework_JoinThread(dev->ResponsethreadHandle);
framework_DeleteThread(dev->ResponsethreadHandle);
dev->ResponsethreadHandle = NULL;
/*redaer thread is not running so we notify all pending request*/
I2C_CancelAllRequest(handle);
g_Ctrl.devInfoList = NULL;
ReleaseNotifier(dev);
framework_DeleteMutex(dev->NotifierContainerLock);
dev->NotifierContainerLock = NULL;
framework_LockMutex(dev->RequestMapLock);
map_destroy(dev->request_map);
dev->request_map = NULL;
framework_UnlockMutex(dev->RequestMapLock);
framework_DeleteMutex(dev->RequestMapLock);
dev->RequestMapLock = NULL;
framework_DeleteMutex(dev->SendLock);
dev->SendLock = NULL;
freeDevice(dev);
return LPCUSBSIO_OK;
}
LPCUSBSIO_API int32_t I2C_DeviceRead(LPC_HANDLE handle,
uint8_t deviceAddress,
uint8_t *buffer,
uint16_t sizeToTransfer,
uint8_t options)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
uint8_t outPacket[HID_I2C_PACKET_SZ + 1];
uint8_t inPacket[0xFFFF];
int32_t res;
HID_I2C_RW_PARAMS_T param;
HID_I2C_IN_REPORT_T *pIn;
if (validHandle(handle) == 0)
{
return LPCUSBSIO_ERR_BAD_HANDLE;
}
/* do parameter check */
//if ((sizeToTransfer > MAX_READ_LENGTH) ||
// ((sizeToTransfer > 0) && (buffer == NULL)) ||
// (deviceAddress > 127))
//{
// return LPCUSBSIO_ERR_INVALID_PARAM;
//}
param.length = sizeToTransfer;
param.options = options;
param.slaveAddr = deviceAddress;
memcpy(outPacket, &param, sizeof(HID_I2C_RW_PARAMS_T));
res = I2C_SendRequest(dev, HID_I2C_REQ_DEVICE_READ, outPacket, sizeof(HID_I2C_RW_PARAMS_T), inPacket, sizeof(inPacket));
if (res == LPCUSBSIO_OK)
{
/* parse response */
pIn = (HID_I2C_IN_REPORT_T *) &inPacket[0];
res = pIn->length - HID_I2C_HEADER_SZ;
if (pIn->length <= HID_I2C_PACKET_SZ)
{
/* copy data back to user buffer */
memcpy(buffer, &pIn->data[0], res);
}
else
{
uint8_t ptr = HID_I2C_HEADER_SZ;
uint8_t temp, i=0;
while(res > 0)
{
temp = (res > HID_I2C_PACKET_SZ-HID_I2C_HEADER_SZ) ? (HID_I2C_PACKET_SZ-HID_I2C_HEADER_SZ) : res;
memcpy(&buffer[i], &inPacket[ptr], temp);
i += temp;
res -= temp;
ptr += temp + HID_I2C_HEADER_SZ;
}
res = i;
}
}
return res;
}
LPCUSBSIO_API int32_t I2C_DeviceWrite(LPC_HANDLE handle,
uint8_t deviceAddress,
uint8_t *buffer,
uint16_t sizeToTransfer,
uint8_t options)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
uint8_t outPacket[0xFFFF];
uint8_t inPacket[HID_I2C_PACKET_SZ + 1];
int32_t res;
HID_I2C_RW_PARAMS_T param;
uint8_t *desBuff;
if (validHandle(handle) == 0)
{
return LPCUSBSIO_ERR_BAD_HANDLE;
}
/* do parameter check */
if ((sizeToTransfer > MAX_WRITE_LENGTH) ||
((sizeToTransfer > 0) && (buffer == NULL)) ||
(deviceAddress > 127))
{
return LPCUSBSIO_ERR_INVALID_PARAM;
}
param.length = sizeToTransfer;
param.options = options;
param.slaveAddr = deviceAddress;
desBuff = outPacket;
/* copy params */
memcpy(desBuff, &param, sizeof(HID_I2C_RW_PARAMS_T));
desBuff += sizeof(HID_I2C_RW_PARAMS_T);
/* copy data buffer now */
memcpy(desBuff, buffer, sizeToTransfer);
res = I2C_SendRequest(dev, HID_I2C_REQ_DEVICE_WRITE, outPacket, sizeof(HID_I2C_RW_PARAMS_T) + sizeToTransfer, inPacket, sizeof(inPacket));
if (res == LPCUSBSIO_OK)
{
/* update user on transfered size */
res = sizeToTransfer;
}
return res;
}
LPCUSBSIO_API int32_t I2C_FastXfer(LPC_HANDLE handle, I2C_FAST_XFER_T *xfer)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
uint8_t outPacket[HID_I2C_PACKET_SZ + 1];
uint8_t inPacket[HID_I2C_PACKET_SZ + 1];
int32_t res;
HID_I2C_XFER_PARAMS_T param;
HID_I2C_IN_REPORT_T *pIn;
uint8_t *desBuff;
if (validHandle(handle) == 0)
{
return LPCUSBSIO_ERR_BAD_HANDLE;
}
/* do parameter check */
if ((xfer->txSz > MAX_XFER_TX_LENGTH) || (xfer->rxSz > MAX_XFER_RX_LENGTH) ||
((xfer->txSz > 0) && (xfer->txBuff == NULL)) ||
((xfer->rxSz > 0) && (xfer->rxBuff == NULL)) ||
(xfer->slaveAddr > 127) )
{
return LPCUSBSIO_ERR_INVALID_PARAM;
}
param.txLength = xfer->txSz;
param.rxLength = xfer->rxSz;
param.options = xfer->options;
param.slaveAddr = xfer->slaveAddr;
desBuff = outPacket;
/* copy params */
memcpy(desBuff, &param, sizeof(HID_I2C_XFER_PARAMS_T));
desBuff += sizeof(HID_I2C_XFER_PARAMS_T);
/* copy data buffer now */
memcpy(desBuff, &xfer->txBuff[0], xfer->txSz);
res = I2C_SendRequest(dev, HID_I2C_REQ_DEVICE_XFER, outPacket, sizeof(HID_I2C_XFER_PARAMS_T) + xfer->txSz, inPacket, sizeof(inPacket));
if (res == LPCUSBSIO_OK)
{
/* parse response */
pIn = (HID_I2C_IN_REPORT_T *) &inPacket[0];
res = pIn->length - HID_I2C_HEADER_SZ;
if (res != 0)
{
/* copy data back to user buffer */
memcpy(&xfer->rxBuff[0], &pIn->data[0], res);
}
else
{
/* else it should be Tx only transfer. Update transferred size. */
res = xfer->txSz;
}
}
return res;
}
LPCUSBSIO_API int32_t I2C_Reset(LPC_HANDLE handle)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
uint8_t inPacket[HID_I2C_PACKET_SZ + 1];
int32_t res;
if (validHandle(handle) == 0)
{
return LPCUSBSIO_ERR_BAD_HANDLE;
}
res = I2C_SendRequest(dev, HID_I2C_REQ_RESET, NULL, 0, inPacket, sizeof(inPacket));
return res;
}
LPCUSBSIO_API const wchar_t *I2C_Error(LPC_HANDLE handle, int32_t status)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
const wchar_t *retStr = NULL;
if (validHandle(handle) != 0)
{
if ((status == LPCUSBSIO_OK) || (LPCUSBSIO_ERR_HID_LIB == status))
{
retStr = hid_error(dev->hidDev);
}
else
{
retStr = GetErrorString(status);
}
}
else
{
retStr = hid_error(NULL);
}
return retStr;
}
//AL : Useless
//LPCUSBSIO_API const char *I2C_GetVersion(LPC_HANDLE handle)
//{
// LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
// uint32_t index = 0;
//
// /* copy library version */
// memcpy(&g_Version[index], &g_LibVersion[0], strlen(g_LibVersion));
// index += strlen(g_LibVersion);
//
// /* if handle is good copy firmware version */
// if (validHandle(handle) != 0) {
// g_Version[index] = '/';
// index++;
// /* copy firmware version */
// memcpy(&g_Version[index], &dev->fwVersion[0], strlen(dev->fwVersion));
// index += strlen(dev->fwVersion);
// }
//
// return &g_Version[0];
//}
LPCUSBSIO_API LPCUSBSIO_ERR_T GPIO_SetVENValue(LPC_HANDLE handle, uint8_t newValue)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
LPCUSBSIO_ERR_T res = LPCUSBSIO_OK;
uint8_t outPacket[HID_I2C_PACKET_SZ + 1];
uint8_t inPacket[HID_I2C_PACKET_SZ + 1];
if (validHandle(handle) == 0)
{
return LPCUSBSIO_ERR_BAD_HANDLE;
}
/* do parameter check */
if ( 0 != newValue && 1 != newValue)
{
return LPCUSBSIO_ERR_INVALID_PARAM;
}
outPacket[0] = newValue;
res = I2C_SendRequest(dev, HID_GPIO_REQ_SET_VEN, outPacket, sizeof(uint8_t), inPacket, sizeof(inPacket));
return res;
}
LPCUSBSIO_API LPCUSBSIO_ERR_T GPIO_SetDWLValue(LPC_HANDLE handle, uint8_t newValue)
{
LPCUSBSIO_I2C_Ctrl_t *dev = (LPCUSBSIO_I2C_Ctrl_t *) handle;
LPCUSBSIO_ERR_T res = LPCUSBSIO_OK;
uint8_t outPacket[HID_I2C_PACKET_SZ + 1];
uint8_t inPacket[HID_I2C_PACKET_SZ + 1];
if (validHandle(handle) == 0)
{
return LPCUSBSIO_ERR_BAD_HANDLE;
}
/* do parameter check */
if ( 0 != newValue && 1 != newValue)
{
return LPCUSBSIO_ERR_INVALID_PARAM;
}
outPacket[0] = newValue;
res = I2C_SendRequest(dev, HID_GPIO_REQ_SET_DWL, outPacket, sizeof(uint8_t), inPacket, sizeof(inPacket));
return res;
}
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#include <stdint.h>
#include <TML/inc/tml_hid.h>
void tml_Connect(void) {
tml_hid_Connect();
}
void tml_Disconnect(void) {
tml_hid_Disconnect();
}
void tml_Send(uint8_t *pBuffer, uint16_t BufferLen, uint16_t *pBytesSent) {
tml_hid_Send(pBuffer, BufferLen, pBytesSent);
}
void tml_Receive(uint8_t *pBuffer, uint16_t BufferLen, uint16_t *pBytes,
uint16_t timeout) {
tml_hid_Receive(pBuffer, BufferLen, pBytes, timeout);
}
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#include <TML/inc/tool.h>
#include <TML/inc/tml.h>
#include "TML/inc/lpcusbsio.h"
#include "TML/inc/lpcusbsio_i2c.h"
#include "TML/inc/framework_Interface.h"
#include "TML/inc/framework_Timer.h"
#define I2C_ADD 0x28
static I2C_PORTCONFIG_T lCfgParam;
static LPC_HANDLE mDriverHandle = NULL;
static bool isAborted;
static uint8_t tml_Tx(uint8_t *pBuff, uint16_t buffLen) {
int lRes = 0x00;
int j=0;
do {
lRes = I2C_DeviceWrite(mDriverHandle, I2C_ADD, pBuff+j, (buffLen-j>=MAX_WRITE_LENGTH)?MAX_WRITE_LENGTH:buffLen-j,
I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT);
if(lRes < 0) return 0;
j += MAX_WRITE_LENGTH;
} while (j <= buffLen);
return 1;
}
static void tml_Rx(uint8_t *pBuff, uint16_t buffLen, uint16_t *pBytesRead) {
int lRes = 0x00;
lRes = I2C_DeviceRead( mDriverHandle, I2C_ADD, pBuff, 3, I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT | I2C_TRANSFER_OPTIONS_NACK_LAST_BYTE);
if (lRes > 0) *pBytesRead = pBuff[2] + 3;
else *pBytesRead = 0;
}
static bool tml_Init(void) {
int lRes = 0x00;
if(NULL != mDriverHandle) return true;
lRes = I2C_GetNumPorts();
if (lRes < 0) return false;
mDriverHandle = I2C_Open(0);
if(NULL == mDriverHandle) return false;
memset(&lCfgParam, 0x00, sizeof(I2C_PORTCONFIG_T));
lCfgParam.ClockRate = I2C_CLOCK_FAST_MODE;
lRes = I2C_Init(mDriverHandle, &lCfgParam);
if (lRes < 0){
I2C_Close(mDriverHandle);
mDriverHandle = NULL;
return false;
}
return true;
}
static void tml_Reset(void) {
uint8_t buffer[30];
uint16_t nbBytes;
if (mDriverHandle == NULL) return;
I2C_Reset(mDriverHandle);
GPIO_SetVENValue(mDriverHandle, 0x00);
GPIO_SetDWLValue(mDriverHandle, 0x00);
Sleep(10);
GPIO_SetVENValue(mDriverHandle, 0x01);
/* Insure I2C fragmentation is enabled */
tml_Tx((uint8_t*)"\x20\x00\x01\x01", 4);
tml_Tx((uint8_t*)"\x20\x00\x01\x01", 4);
tml_Rx(buffer, sizeof(buffer), &nbBytes);
tml_Tx((uint8_t*)"\x20\x01\x00", 3);
tml_Rx(buffer, sizeof(buffer), &nbBytes);
tml_Tx((uint8_t*)"\x20\x02\x05\x01\xA0\x05\x01\x10", 8);
tml_Rx(buffer, sizeof(buffer), &nbBytes);
GPIO_SetVENValue(mDriverHandle, 0x00);
Sleep(10);
GPIO_SetVENValue(mDriverHandle, 0x01);
}
int tml_hid_Connect(void) {
if(!tml_Init()) return 1;
tml_Reset();
return 0;
}
void tml_hid_Disconnect(void){
/* I2C_Reset(mDriverHandle);
I2C_CancelAllRequest(mDriverHandle);
I2C_Close(mDriverHandle);
Sleep(2000);*/
}
void tml_hid_Send(uint8_t *pBuffer, uint16_t BufferLen, uint16_t *pBytesSent){
if(tml_Tx(pBuffer, BufferLen) == 0)
{
*pBytesSent = 0;
}
else
{
*pBytesSent = BufferLen;
}
}
static void timeoutCb(void* pContext)
{
uint8_t dummy[] = {0x20, 0x00, 0x00};
I2C_CancelAllRequest(mDriverHandle);
/* Send dummy frame to re-align reception */
tml_Tx(dummy, sizeof(dummy));
isAborted = true;
}
void tml_hid_Receive(uint8_t *pBuffer, uint16_t BufferLen, uint16_t *pBytes, uint16_t timeout){
if (timeout == TIMEOUT_INFINITE) tml_Rx(pBuffer, BufferLen, pBytes);
else {
void *timer;
uint32_t timerId;
framework_TimerCreate(&timer);
timerId = *(uint32_t*)timer;
*pBytes = 0;
isAborted = false;
framework_TimerStart(&timerId, timeout, timeoutCb, NULL);
tml_Rx(pBuffer, BufferLen, pBytes);
if(isAborted) *pBytes = 0;
framework_TimerStop(&timerId);
framework_TimerDelete(&timerId);
}
}
void tml_hid_Cancel(void)
{
I2C_CancelAllRequest(mDriverHandle);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment