// ==========================================================================
// sensor_nfc.c
// (c) 2020, Aurel Dumitru
//
// Description:
// Sensor NFC operations
// =========================================================================

//#include "sensor_nfc.h"
#include <string.h>
#include <stdlib.h>
#include "main.h"
#include "pass.h"
#include "utils.h"
#include "devstatus.h"
#include "calibrations.h"
#include "tagtype5_wrapper.h"
#include "lib_NDEF_URI.h"
#include "lib_NDEF_Text.h"
#include "custom_nfc04a1_nfctag.h"


uint8_t Sensor_Nfc_InitFlag = 0;
uint8_t Sensor_Nfc_FieldDetectedFlag;
char Sensor_Nfc_Link[64];
char Sensor_Nfc_DeviceSn[32];


int32_t Sensor_Nfc_ResetDefault(void)
{
	ST25DV_PASSWD		Password;
	ST25DV_RF_PROT_ZONE RfProtZone;
	sRecordInfo_t		RecordInfo;
	uint8_t FtpPass[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

	uint16_t NdefSize;
	if (NDEF_getNDEFSize(&NdefSize) != NDEF_OK) return -128;
	if (NdefSize == 0) return -128;
	if (NfcTag_ReadNDEF(NDEF_Buffer) != NDEF_OK) return -128;

	NDEF_IdentifyBuffer(&RecordInfo, &NDEF_Buffer[0]);
	uint32_t NextRecordPosition = RecordInfo.PayloadOffset + RecordInfo.PayloadLength;
	NDEF_IdentifyBuffer(&RecordInfo, &NDEF_Buffer[NextRecordPosition]);
	if ((RecordInfo.TypeLength != 1) || (RecordInfo.Type[0] != 'T')) return -128;
	memcpy(Sensor_Nfc_DeviceSn, &NDEF_Buffer[NextRecordPosition + RecordInfo.PayloadOffset + 11 + 3], RecordInfo.PayloadLength - 11 -3);
	Sensor_Nfc_DeviceSn[RecordInfo.PayloadLength-11-3] = '\0';


	Pass_Gen(Sensor_Nfc_DeviceSn, (uint8_t*)(&Password), NULL, 0);
	if (CUSTOM_NFCTAG_PresentI2CPassword(0, Password) != NFCTAG_OK) return -100;
	ST25DV_I2CSSO_STATUS SessionStatus;
	if (CUSTOM_NFCTAG_ReadI2CSecuritySession_Dyn(0, &SessionStatus) != NFCTAG_OK) return -101;
	if (SessionStatus == ST25DV_SESSION_OPEN)
	{
		Password.MsbPasswd = 0;
		Password.LsbPasswd = 0;
		if (CUSTOM_NFCTAG_WriteI2CPassword(0, Password) != NFCTAG_OK)	return -1;
		if (CUSTOM_NFCTAG_WriteLockCFG(0, ST25DV_LOCKED) != NFCTAG_OK) return -4;
		RfProtZone.PasswdCtrl	= ST25DV_NOT_PROTECTED;
		RfProtZone.RWprotection	= ST25DV_NO_PROT;
		if (CUSTOM_NFCTAG_WriteRFZxSS(0, ST25DV_PROT_ZONE1,  RfProtZone) != NFCTAG_OK) return -5;
		RfProtZone.PasswdCtrl	= ST25DV_NOT_PROTECTED;
		RfProtZone.RWprotection	= ST25DV_NO_PROT;
		if (CUSTOM_NFCTAG_WriteRFZxSS(0, ST25DV_PROT_ZONE2,  RfProtZone) != NFCTAG_OK) return -5;
		RfProtZone.PasswdCtrl	= ST25DV_NOT_PROTECTED;
		RfProtZone.RWprotection	= ST25DV_NO_PROT;
		if (CUSTOM_NFCTAG_WriteRFZxSS(0, ST25DV_PROT_ZONE3,  RfProtZone) != NFCTAG_OK) return -5;

		if (CUSTOM_NFCTAG_WriteI2CProtectZonex(0, ST25DV_PROT_ZONE1, ST25DV_NO_PROT) != NFCTAG_OK) return -6;
		if (CUSTOM_NFCTAG_WriteI2CProtectZonex(0, ST25DV_PROT_ZONE2, ST25DV_NO_PROT) != NFCTAG_OK) return -6;
		if (CUSTOM_NFCTAG_WriteI2CProtectZonex(0, ST25DV_PROT_ZONE3, ST25DV_NO_PROT) != NFCTAG_OK) return -6;

		if (CUSTOM_NFCTAG_InitEndZone(0) != NFCTAG_OK)	return -3;
		if (CUSTOM_NFCTAG_WriteData(0, (const uint8_t*)FtpPass, 8176, 16) != NFCTAG_OK) return -7;

		Password.MsbPasswd = 0x0;
		Password.LsbPasswd = 0x1;
		CUSTOM_NFCTAG_PresentI2CPassword(0, Password);
	}
	return 0;
}

void Sensor_Nfc_WriteNdef(uint32_t Diag)
{
	char WebSite[64];
	char Tmp[16];

	uint8_t *PtrNdefMsg = NDEF_Buffer;

	// 1st: WEB address
	strcpy(WebSite, C_HttpAddr);
	strcat(WebSite, "/?sn=");
	strcat(WebSite, Sensor_Nfc_DeviceSn);
	strcat(WebSite, "&diag=");
	strcat(WebSite, itoa(Diag, Tmp, 10));
	*PtrNdefMsg++ = 0x91;	// Set MB,SR
	*PtrNdefMsg++ = URI_TYPE_STRING_LENGTH;
	uint32_t Length = (uint32_t)strlen(WebSite);
    *PtrNdefMsg++ = (uint8_t)(1 + Length);
    memcpy(PtrNdefMsg, URI_TYPE_STRING, URI_TYPE_STRING_LENGTH);
    PtrNdefMsg 	 += URI_TYPE_STRING_LENGTH;
    *PtrNdefMsg++ = URI_ID_0x02;
    memcpy(PtrNdefMsg, WebSite, Length);
    PtrNdefMsg += Length;

    /* 2rd: Device text */
    char TextNDEF[32] = "Device SN: ";
    strcat(TextNDEF, Sensor_Nfc_DeviceSn);
    Length = strlen(TextNDEF);		//1+en+message
    *PtrNdefMsg++ = 0x01|0x10;		// Set SR
    *PtrNdefMsg++ = TEXT_TYPE_STRING_LENGTH;
	*PtrNdefMsg++ = (uint8_t)Length + 3;
    memcpy(PtrNdefMsg, TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH);
    PtrNdefMsg += TEXT_TYPE_STRING_LENGTH;
    /* TEXT payload */
    *PtrNdefMsg++ = ISO_ENGLISH_CODE_STRING_LENGTH;
    memcpy(PtrNdefMsg, ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH);
    PtrNdefMsg += ISO_ENGLISH_CODE_STRING_LENGTH;
    memcpy(PtrNdefMsg, TextNDEF, Length);
    PtrNdefMsg += Length;

    (void)NfcTag_WriteNDEF(PtrNdefMsg-NDEF_Buffer, NDEF_Buffer);
}



int32_t Sensor_Nfc_Init(void)
{
	ST25DV_PASSWD		Password;
	ST25DV_RF_PROT_ZONE RfProtZone;
	sRecordInfo_t		RecordInfo;
	char				FtpPass[16];
	uint32_t			NextRecordPosition;

	NfcTag_SelectProtocol(NFCTAG_TYPE5);
	uint32_t mem_size = CUSTOM_NFCTAG_GetByteSize(CUSTOM_NFCTAG_INSTANCE);
	if(NfcType5_NDEFDetection() != NDEF_OK)
	{
	   	/* Write CC file content */
		CCFileStruct.MagicNumber  = NFCT5_MAGICNUMBER_E1_CCFILE;
		CCFileStruct.Version      = NFCT5_VERSION_V1_0;
		/* Size must be specified by block of 8 bytes */
		if(mem_size > (0xFF*8))
		{
			CCFileStruct.MagicNumber  = NFCT5_MAGICNUMBER_E2_CCFILE;
			CCFileStruct.MemorySize   = NFCT5_EXTENDED_CCFILE;
			CCFileStruct.ExtMemorySize   = (uint16_t)(mem_size / 8);
		}
		else
			CCFileStruct.MemorySize   = (uint8_t)(mem_size / 8);

		/** Type5 Capability Container byte3 value for android compliancy */
		CCFileStruct.TT5Tag = 0x05;
		NfcType5_TT5Init();
	}

//	Sensor_Nfc_ResetDefault();
//	while(1) 	(void)HAL_IWDG_Refresh(&hiwdg1);

	Sensor_Nfc_DeviceSn[0] 	= '\0';
	Sensor_Nfc_Link[0]		= '\0';
	// Check if the access to NFC data is already protected
	Password.MsbPasswd = 0;
	Password.LsbPasswd = 0;
	if (CUSTOM_NFCTAG_PresentI2CPassword(0, Password) != NFCTAG_OK) return -100;
	ST25DV_I2CSSO_STATUS SessionStatus;
	if (CUSTOM_NFCTAG_ReadI2CSecuritySession_Dyn(0, &SessionStatus) != NFCTAG_OK) return -101;
	if (SessionStatus == ST25DV_SESSION_OPEN)
	{
		uint16_t NdefSize = 0;
		if (NDEF_getNDEFSize(&NdefSize) != NDEF_OK) return -128;
		if (NdefSize == 0) return -128;
		if (NfcTag_ReadNDEF(NDEF_Buffer) != NDEF_OK) return -128;
		NDEF_IdentifyBuffer(&RecordInfo, &NDEF_Buffer[0]);
		if ((RecordInfo.TypeLength != 1) || (RecordInfo.Type[0] != 'T')) return -128;
		memcpy(Sensor_Nfc_DeviceSn, &NDEF_Buffer[RecordInfo.PayloadOffset + 3], RecordInfo.PayloadLength-3);
		Sensor_Nfc_DeviceSn[RecordInfo.PayloadLength-3] = '\0';

		NextRecordPosition = RecordInfo.PayloadOffset + RecordInfo.PayloadLength;
		NDEF_IdentifyBuffer(&RecordInfo, &NDEF_Buffer[NextRecordPosition]);
		if ((RecordInfo.TypeLength != 1) || (RecordInfo.Type[0] != 'T') || (RecordInfo.PayloadLength != 15)) return -128;
		memcpy(FtpPass, &NDEF_Buffer[NextRecordPosition + RecordInfo.PayloadOffset + 3], RecordInfo.PayloadLength-3);
		FtpPass[RecordInfo.PayloadLength-3] = '\0';

		Pass_Gen(Sensor_Nfc_DeviceSn, (uint8_t*)(&Password), NULL, 0);
		if (CUSTOM_NFCTAG_WriteI2CPassword(0, Password) != NFCTAG_OK)	return -1;
		if (CUSTOM_NFCTAG_CreateUserZone(0, 1536, 512, 6144, 0) != NFCTAG_OK)	return -3;
		if (CUSTOM_NFCTAG_WriteLockCFG(0, ST25DV_LOCKED) != NFCTAG_OK) return -4;
		RfProtZone.PasswdCtrl	= ST25DV_NOT_PROTECTED;
		RfProtZone.RWprotection	= ST25DV_READWRITE_PROT;
		if (CUSTOM_NFCTAG_WriteRFZxSS(0, ST25DV_PROT_ZONE1,  RfProtZone) != NFCTAG_OK) return -5;
		RfProtZone.PasswdCtrl	= ST25DV_NOT_PROTECTED;
		RfProtZone.RWprotection	= ST25DV_NO_PROT;
		if (CUSTOM_NFCTAG_WriteRFZxSS(0, ST25DV_PROT_ZONE2,  RfProtZone) != NFCTAG_OK) return -5;
		RfProtZone.PasswdCtrl	= ST25DV_NOT_PROTECTED;
		RfProtZone.RWprotection	= ST25DV_READWRITE_PROT;
		if (CUSTOM_NFCTAG_WriteRFZxSS(0, ST25DV_PROT_ZONE3,  RfProtZone) != NFCTAG_OK) return -5;

		if (CUSTOM_NFCTAG_WriteI2CProtectZonex(0, ST25DV_PROT_ZONE1, ST25DV_WRITE_PROT) != NFCTAG_OK) return -6;
		if (CUSTOM_NFCTAG_WriteI2CProtectZonex(0, ST25DV_PROT_ZONE2, ST25DV_NO_PROT) != NFCTAG_OK) return -6;
		if (CUSTOM_NFCTAG_WriteI2CProtectZonex(0, ST25DV_PROT_ZONE3, ST25DV_READWRITE_PROT) != NFCTAG_OK) return -6;

		Pass_Gen(Sensor_Nfc_DeviceSn, (uint8_t*)(&FtpPass), (uint8_t*)(&FtpPass), strlen(FtpPass));
		if (CUSTOM_NFCTAG_WriteData(0, (const uint8_t*)FtpPass, 8176, 12) != NFCTAG_OK) return -7;

		/* URI (smart poster) Record Header */
		/************************************/
		/*  7 |  6 |  5 |  4 |  3 | 2  1  0 */
		/*----------------------------------*/
		/* MB   ME   CF   SR   IL    TNF    */  /* <---- CF=0, IL=0 and SR=1 TNF=1 NFC Forum Well-known type*/
		/*----------------------------------*/
		/*          TYPE LENGTH             */
		/*----------------------------------*/
		/*        PAYLOAD LENGTH 3          */  /* <---- Used only if SR=0 */
		/*----------------------------------*/
		/*        PAYLOAD LENGTH 2          */  /* <---- Used only if SR=0 */
		/*----------------------------------*/
		/*        PAYLOAD LENGTH 1          */  /* <---- Used only if SR=0 */
		/*----------------------------------*/
		/*        PAYLOAD LENGTH 0          */
		/*----------------------------------*/
		/*          ID LENGTH               */  /* <---- Not Used  */
		/*----------------------------------*/
		/*              TYPE                */
		/*----------------------------------*/
		/*               ID                 */  /* <---- Not Used  */
		/************************************/
		Sensor_Nfc_WriteNdef(0);
		Password.LsbPasswd = 0x1;
		Password.MsbPasswd = 0x0;
		CUSTOM_NFCTAG_PresentI2CPassword(0, Password);
	}
	else
	{
		  uint16_t NdefSize;
		  if (NDEF_getNDEFSize(&NdefSize) != NDEF_OK) return -128;
		  if (NdefSize == 0) return -128;
		  if (NfcTag_ReadNDEF(NDEF_Buffer) != NDEF_OK) return -128;

		  NDEF_IdentifyBuffer(&RecordInfo, &NDEF_Buffer[0]);
		  if ((RecordInfo.TypeLength != 1) || (RecordInfo.Type[0] != 'U')) return -128;
		  memcpy(Sensor_Nfc_Link, &NDEF_Buffer[RecordInfo.PayloadOffset + 1], RecordInfo.PayloadLength - 1);
		  Sensor_Nfc_Link[RecordInfo.PayloadLength-1] = '\0';
		  uint32_t NextRecordPosition = RecordInfo.PayloadOffset + RecordInfo.PayloadLength;
		  NDEF_IdentifyBuffer(&RecordInfo, &NDEF_Buffer[NextRecordPosition]);
		  if ((RecordInfo.TypeLength != 1) || (RecordInfo.Type[0] != 'T')) return -128;
		  memcpy(Sensor_Nfc_DeviceSn, &NDEF_Buffer[NextRecordPosition + RecordInfo.PayloadOffset + 11 + 3], RecordInfo.PayloadLength - 11 -3);
		  Sensor_Nfc_DeviceSn[RecordInfo.PayloadLength-11-3] = '\0';
		  Sensor_Nfc_InitFlag = 1;
	}
    return 0;
}


void Sensor_Nfc_FieldDetected(void)
{
	Sensor_Nfc_FieldDetectedFlag = 1;
}

uint8_t Sensor_Nfc_ReadFieldDetectedFlag(void)
{
	uint8_t Flag = Sensor_Nfc_FieldDetectedFlag;
	Sensor_Nfc_FieldDetectedFlag = 0;
	return Flag;
}


void Sensor_Nfc_PowerUp(void)
{
	HAL_GPIO_WritePin(VCC_NFC_GPIO_Port, VCC_NFC_Pin, GPIO_PIN_SET);	// Set VCC_NFC to active level
	Utils_DelayMicroseconds(1000);
}


void Sensor_Nfc_PowerDown(void)
{
	HAL_GPIO_WritePin(VCC_NFC_GPIO_Port, VCC_NFC_Pin, GPIO_PIN_RESET);	// Set VCC_NFC to inactive level
}



char* Sensor_Nfc_GetDevSN(void)
{
	return Sensor_Nfc_DeviceSn;
}

char* Sensor_Nfc_GetDevNumber(void)
{
	uint32_t Length = strlen(Sensor_Nfc_DeviceSn);
	if (Length)
	{
		Length--;
		while((Length) && (Sensor_Nfc_DeviceSn[Length] != '-'))
			Length--;
	}
	return Sensor_Nfc_DeviceSn+Length+1;
}

void Sensor_Nfc_GetFtpPass(char* Ptr)
{
	ST25DV_PASSWD	Password;
	ST25DV_I2CSSO_STATUS SessionStatus;
	uint8_t FtpPass[16] = {0};

	Pass_Gen(Sensor_Nfc_DeviceSn, (uint8_t*)(&Password), NULL, 0);
	if (CUSTOM_NFCTAG_PresentI2CPassword(0, Password) != NFCTAG_OK) return;
	if (CUSTOM_NFCTAG_ReadI2CSecuritySession_Dyn(0, &SessionStatus) != NFCTAG_OK) return;
	if (SessionStatus == ST25DV_SESSION_OPEN)
	{
		if (CUSTOM_NFCTAG_ReadData(0, FtpPass, 8176, 16) != NFCTAG_OK) return;
		Pass_Gen(Sensor_Nfc_DeviceSn, (uint8_t*)Ptr, FtpPass, 12);
		Password.LsbPasswd = 0x0;
		Password.MsbPasswd = 0x0;
		CUSTOM_NFCTAG_PresentI2CPassword(0, Password);
	}
}

void Sensor_Nfc_ReadProtectedData(uint16_t Addr, uint16_t Size, uint8_t* Data)
{
	ST25DV_PASSWD	Password;
	ST25DV_I2CSSO_STATUS SessionStatus;

	Pass_Gen(Sensor_Nfc_DeviceSn, (uint8_t*)(&Password), NULL, 0);
	if (CUSTOM_NFCTAG_PresentI2CPassword(0, Password) != NFCTAG_OK) return;
	if (CUSTOM_NFCTAG_ReadI2CSecuritySession_Dyn(0, &SessionStatus) != NFCTAG_OK) return;
	if (SessionStatus == ST25DV_SESSION_OPEN)
	{
		if (CUSTOM_NFCTAG_ReadData(0, Data, Addr, Size) != NFCTAG_OK) return;
		Password.LsbPasswd = 0x0;
		Password.MsbPasswd = 0x0;
		CUSTOM_NFCTAG_PresentI2CPassword(0, Password);
	}
}

void Sensor_Nfc_WriteProtectedData(uint16_t Addr, uint16_t Size, uint8_t* Data)
{
	ST25DV_PASSWD	Password;
	ST25DV_I2CSSO_STATUS SessionStatus;

	Pass_Gen(Sensor_Nfc_DeviceSn, (uint8_t*)(&Password), NULL, 0);
	if (CUSTOM_NFCTAG_PresentI2CPassword(0, Password) != NFCTAG_OK) return;
	if (CUSTOM_NFCTAG_ReadI2CSecuritySession_Dyn(0, &SessionStatus) != NFCTAG_OK) return;
	if (SessionStatus == ST25DV_SESSION_OPEN)
	{
		if (CUSTOM_NFCTAG_WriteData(0, Data, Addr, Size) != NFCTAG_OK) return;
		Password.LsbPasswd = 0x0;
		Password.MsbPasswd = 0x0;
		CUSTOM_NFCTAG_PresentI2CPassword(0, Password);
	}
}


void Sensor_Nfc_UpdateLinkDiag(void)
{
	ST25DV_PASSWD	Password;
	ST25DV_I2CSSO_STATUS SessionStatus;
	char Link[64];
	char Tmp[16];
	uint32_t Diag=0;

	if (DevStatus[DEVSTATUS_BAT_STATUS_IDX] == DEVSTATUS_BAT_LOW)
		Diag |= 1<<0;
	if (DevStatus[DEVSTATUS_MODEM_STATUS_IDX] == DEVSTATUS_MODEM_UART_FAIL)
		Diag |= 1<<2;
	if (DevStatus[DEVSTATUS_MODEM_STATUS_IDX] == DEVSTATUS_MODEM_SIM_FAIL)
		Diag |= 1<<3;
	if (DevStatus[DEVSTATUS_MODEM_STATUS_IDX] == DEVSTATUS_MODEM_REG_FAIL)
		Diag |= 1<<4;
	if (DevStatus[DEVSTATUS_MODEM_STATUS_IDX] == DEVSTATUS_MODEM_NITZ_FAIL)
		Diag |= 1<<5;
	if (DevStatus[DEVSTATUS_MODEM_STATUS_IDX] == DEVSTATUS_MODEM_FTPS_FAIL)
		Diag |= 1<<6;
	if (DevStatus[DEVSTATUS_MODEM_STATUS_IDX] == DEVSTATUS_MODEM_SIGNAL_FAIL)
		Diag |= 1<<7;
	if (DevStatus[DEVSTATUS_CAMERA_STATUS_IDX] == DEVSTATUS_CAMERA_COM_FAIL)
		Diag |= 1<<8;
	if (DevStatus[DEVSTATUS_CAMERA_STATUS_IDX] == DEVSTATUS_CAMERA_PICTURE_FAIL)
		Diag |= 1<<9;
	if (DevStatus[DEVSTATUS_MOTOR1_STATUS_IDX] == DEVSTATUS_MOTOR_JAMMED)
		Diag |= 1<<10;
	if (DevStatus[DEVSTATUS_MOTOR1_STATUS_IDX] == DEVSTATUS_MOTOR_OPENLOAD)
		Diag |= 1<<11;
	if (DevStatus[DEVSTATUS_MOTOR2_STATUS_IDX] == DEVSTATUS_MOTOR_JAMMED)
		Diag |= 1<<12;
	if (DevStatus[DEVSTATUS_MOTOR2_STATUS_IDX] == DEVSTATUS_MOTOR_OPENLOAD)
		Diag |= 1<<13;
	if (DevStatus[DEVSTATUS_INFRARED_STATUS_IDX] == DEVSTATUS_INFRARED_LOW)
		Diag |= 1<<14;
	if (DevStatus[DEVSTATUS_MICROSD_STATUS_IDX] == DEVSTATUS_MICROSD_FAIL)
		Diag |= 1<<16;
	if (DevStatus[DEVSTATUS_HYPERRAM_STATUS_IDX] == DEVSTATUS_HYPERRAM_FAIL)
		Diag |= 1<<17;
	if (DevStatus[DEVSTATUS_OSC32_STATUS_IDX] == DEVSTATUS_OSC32_FAIL)
		Diag |= 1<<18;
	if (DevStatus[DEVSTATUS_TEMPHUMID_STATUS_IDX] == DEVSTATUS_TEMPHUMID_FAIL)
		Diag |= 1<<19;

	strcpy(Link, C_HttpAddr);
	strcat(Link, "/?sn=");
	strcat(Link, Sensor_Nfc_DeviceSn);
	strcat(Link, "&diag=");
	strcat(Link, itoa(Diag, Tmp, 10));

	if (strcmp(Link, Sensor_Nfc_Link) != 0)
	{
		Pass_Gen(Sensor_Nfc_DeviceSn, (uint8_t*)(&Password), NULL, 0);
		if (CUSTOM_NFCTAG_PresentI2CPassword(0, Password) != NFCTAG_OK) return;
		if (CUSTOM_NFCTAG_ReadI2CSecuritySession_Dyn(0, &SessionStatus) != NFCTAG_OK) return;
		if (SessionStatus == ST25DV_SESSION_OPEN)
		{
			Sensor_Nfc_WriteNdef(Diag);
			Password.LsbPasswd = 0x0;
			Password.MsbPasswd = 0x0;
			CUSTOM_NFCTAG_PresentI2CPassword(0, Password);
		}
	}
}
