/*! *********************************************************************************
 * \add to group HID Device
 * @{
 ********************************************************************************** */
/*!
 * Copyright (c) 2014, Freescale Semiconductor, Inc.
 * All rights reserved.
 * \file app.c
 * This file is the source file for the HID Device application
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/************************************************************************************
 *************************************************************************************
 * Include
 *************************************************************************************
 ************************************************************************************/
#include <stdlib.h>
#include <string.h>

#include "board.h"
#include "fsl_gpio.h"
#include "fsl_adc16.h"

#include "fsl_debug_console.h"
#include "HAL_I2C_driver.h"
#include "HAL_timer_driver.h"
#include "ntag_bridge.h"

#include "ntag_driver_intern.h"

#include "ntag_defines.h"
#include "ntag_driver.h"
#include "nfc_device.h"

/* NDEF library headers */
#ifdef NDEF_LIBRARY
#include "NDEF_Rec_Text.h"
#include "NDEF_Rec_Uri.h"
#include "NDEF_Rec_BluetoothSsp.h"
#include "NDEF_Rec_Aar.h"
#include "NDEF_Message.h"
#include "NDEF_Rec_GenericPayload.h"
#include "NDEF_Record.h"
#endif // NDEF_LIBRARY

#include "Flash_Adapter.h"
#include "FunctionLib.h"
#include "app_ntag.h"



/************************************************************************************
 *************************************************************************************
 * Private macros
 *************************************************************************************
 ************************************************************************************/


/************************************************************************************
 *************************************************************************************
 * Private type definitions
 *************************************************************************************
 ************************************************************************************/
#define NDEF_DATA_BUFF_LEN      256

#define NO_ERROR        0x00U
#define ERROR_STATE     NO_ERROR + 1

#define AAR_FLAGS_INIT_FLAGS 0x00

typedef enum
{
NDEF_RW_NO_ERROR = 0x00,
NDEF_RW_ERR_NOT_T2T_FORMAT,
NDEF_RW_ERR_TERM_TLV_MISSING,
NDEF_RW_ERR_TOO_LONG_MSG,
NDEF_RW_ERR_READ,
NDEF_RW_ERR_WRITE
} NDEF_RW_STATUS_T;


/************************************************************************************
 *************************************************************************************
 * Private memory declarations
 *************************************************************************************
 ************************************************************************************/

/************************************************************************************
 *************************************************************************************
 * Private functions prototypes
 *************************************************************************************
 ************************************************************************************/


/*******************************************************************************
 * FUNCTION: NFC_MsgWrite
 *
 * Description:
 *
 *******************************************************************************/
NDEF_RW_STATUS_T NFC_MsgWrite(uint8_t * pOutBuff, uint32_t dwOutBuffLen)
    {
    //    bool_t boRetVal; // if problem TRUE
    bool_t boRemainData = TRUE;
    uint8_t aData_Block_1[NTAG_I2C_BLOCK_SIZE];
    uint16_t wOutBuffLenTmp;

    uint8_t bTemp;

    /* check the length of the NDEF message, which will be written */
    if((dwOutBuffLen + 3) > NDEF_MSG_LEN_MAX_2K)
        {
        return NDEF_RW_ERR_TOO_LONG_MSG;
        }

    ntag_handle->status = NTAG_OK;

    /* set the zero data to the buffer for block 1 */
    FLib_MemSet(aData_Block_1, 0, NTAG_I2C_BLOCK_SIZE);
    /* fill the NDEF message control char */
    aData_Block_1[0] = NDEF_MESSAGE_TLV;

    /* calculate the TLV length */
    if((dwOutBuffLen +3) >= NDEF_MSG_LEN_1B_TLV)
        {
        /* retype the length of the message*/
        wOutBuffLenTmp = (uint16_t)dwOutBuffLen;
        /* fill the TLV message length */
        aData_Block_1[1] = (uint8_t)NDEF_MSG_LEN_1B_TLV;
        aData_Block_1[2] = (uint8_t)((wOutBuffLenTmp & 0xFF00) >> 8);
        aData_Block_1[3] = (uint8_t)(wOutBuffLenTmp & 0x00FF);
        /* copy the remain data to the buffer for block 1 */
        FLib_MemCpy(&aData_Block_1[4], pOutBuff, (NTAG_I2C_BLOCK_SIZE-4) );
        /* recalculate the remain length of the NDEF message */
        wOutBuffLenTmp -= (NTAG_I2C_BLOCK_SIZE-4);

        pOutBuff += (NTAG_I2C_BLOCK_SIZE-4);
        }
    else
        {
        /* fill the TLV message length */
        aData_Block_1[1] = (uint8_t)dwOutBuffLen;
        /* copy the remain data to the buffer for block 1 */
        if(aData_Block_1[1]>(NTAG_I2C_BLOCK_SIZE-2))
            {
            FLib_MemCpy(&aData_Block_1[2], pOutBuff, (NTAG_I2C_BLOCK_SIZE-2) );
            /* recalculate the remain length of the NDEF message */
            wOutBuffLenTmp = aData_Block_1[1] - (NTAG_I2C_BLOCK_SIZE-2);

            pOutBuff += (NTAG_I2C_BLOCK_SIZE-2); // 17f74
            }
        else
            {
            FLib_MemCpy(&aData_Block_1[2], pOutBuff, aData_Block_1[1] );
            aData_Block_1[aData_Block_1[1]+2] = TERMINATOR_TLV;
            boRemainData = FALSE;
            /* remain length of the NDEF message is 0 */
            wOutBuffLenTmp = 0;
            /* whole NDEF message + LTV bytes fits into the first user memory block */
            if (NFC_WriteBlock(ntag_handle, 1, aData_Block_1, NTAG_I2C_BLOCK_SIZE))
                {
                return NDEF_RW_ERR_WRITE;
                }

            if (NFC_WriteBlock(ntag_handle, 2, Null_Block, NTAG_I2C_BLOCK_SIZE))
                {
                return NDEF_RW_ERR_WRITE;
                }
            }
        }

    if (boRemainData)
        {
        bTemp = wOutBuffLenTmp / NTAG_I2C_BLOCK_SIZE;

        /* check if longer message then available memory size */
        if (bTemp < 56)
            {
            /* check if length is equal the full user memory range */
            if (bTemp == 55)
                {
                if ((wOutBuffLenTmp % NTAG_I2C_BLOCK_SIZE))
                    {
                    /* length is 55,xx blocks */
                    boRemainData = FALSE;
                    }
                }
            }
        else
            {
            /* message is longer then 55x16 bytes (> 1k version) */
            boRemainData = FALSE;
            }
        }

    if (boRemainData)
        {
        /* fill the terminator char */
        *(pOutBuff+wOutBuffLenTmp)= TERMINATOR_TLV;

        /* Write the default "Empty NDEF" message to the NTAG chip
         * This is from reason some error during the NFC data transmission. The header of the
         * with NDEF message data will be written at the end of the data transmission.
         * */
        if (NFC_WriteBytes( ntag_handle, NTAG_MEM_ADRR_I2C_ADDRESS, Default_Empty_NDEF_msg, NTAG_I2C_BLOCK_SIZE*2))
            {
            return NDEF_RW_ERR_WRITE;
            }

        /* Write remain blocks of the NDEF message. */
        if (NFC_WriteBytes(ntag_handle, NTAG_I2C_BLOCK_SIZE*2, pOutBuff, wOutBuffLenTmp+1))
            {
            return NDEF_RW_ERR_WRITE;
            }

        /* Write the first block of the NDEF message. This consists of the NDEF header */
        if (NFC_WriteBlock(ntag_handle, 1, aData_Block_1, NTAG_I2C_BLOCK_SIZE))
            {
            return NDEF_RW_ERR_WRITE;
            }
        }

    return NDEF_RW_NO_ERROR;
    }


/************************************************************************************
 *************************************************************************************
 * Public functions
 *************************************************************************************
 ************************************************************************************/

/*******************************************************************************
 * FUNCTION: NDEF_Pairing_Write
 *
 * Description:
 *
 *******************************************************************************/
Status_t NDEF_Pairing_Write(void)
    {
#ifdef NDEF_LIBRARY
    uint8_t    i;
    uint32_t   dwOutBuffLen;
    uint8_t    aDeviceAddr[6];
    Status_t   Status = NO_ERROR;
    uint8_t    aOutBuff[NDEF_DATA_BUFF_LEN];
    Status_t   NdefStatus;
    NDEF_RW_STATUS_T       NfcStatus;
    NDEF_Rec_BtsspLe_t     *pRecord;
    NDEF_Message_t         *pMessage = (NDEF_Message_t *)NULL;
    hardwareParameters_t   pHwParams;

    /* Device address is not fixed, it is generated and written to the FLASH.
     * From that reason it has to be read from FLASH and used for NDEF message
     */
    Status = NV_ReadHWParameters(&pHwParams);

    if (Status == NO_ERROR)
        {
        /* copy the Device Address in reverse order */
        for (i=0; i<6; i++)
            {
            aDeviceAddr[5-i] = pHwParams.bluetooth_address[i];
            }

        /* create the record based the OOB data */
        pRecord = NDEF_Rec_Btssp_CreateLe(aDeviceAddr, PublicAddress, PeripheralPrefered);

        /* add created record to the stream at the end, behind the previous record */
        NdefStatus = NDEF_Msg_AppendRecord(&pMessage, pRecord);

        if (NdefStatus == NDEF_STATUS_SUCCESS)
            {
            /* create the NDEF message */
            dwOutBuffLen = NDEF_Msg_EncodeToByteArray(pMessage, aOutBuff, NDEF_DATA_BUFF_LEN);
            /* write NDEF message to the NTAG I2C chip */
            NfcStatus = NFC_MsgWrite(aOutBuff, dwOutBuffLen);
            if (NfcStatus != NDEF_RW_NO_ERROR)
                {
                Status = ERROR_STATE;
                }
            NDEF_Msg_DestroyMsg((void*)&pMessage);
            }
        else
            {
            Status = ERROR_STATE;
            }
        }
#else
    uint8_t    i;
    Status_t   Status = NO_ERROR;
    NDEF_RW_STATUS_T       NfcStatus;
    hardwareParameters_t   pHwParams;

    uint8_t BLE_pairing_NDEF_msg1[] = {
            /* 4  */    0xD2, 0x20, 0x0c,
            /* 32 */    'a','p','p','l','i','c','a','t','i','o','n','/','v','n','d','.','b','l','u','e','t','o','o','t','h','.','l','e','.','o','o','b',
            /* 1  */    0x08,    // LE Bluetooth Device Address length: 8 bytes
            /* 1  */    0x1B,    // LE Bluetooth Device Address data type
            /* 6  */    0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, // Bluetooth Device Address: 6 bytes + 1 (next byte)
            /* 1  */    0x00,    // added at the end of the Device Address
            /* 1  */    0x02,    // LE Role Length: 2 bytes
            /* 1  */    0x1c,    // LE Role data type
            /* 1  */    0x02,    // LE Role:  PeripheralPrefered
    };

    Status = NV_ReadHWParameters(&pHwParams);

    /* copy the device address to the NDEF message field */
    for (i=0; i<6; i++)
        {
        BLE_pairing_NDEF_msg1[37+i] = pHwParams.bluetooth_address[i];
        }

    NfcStatus = NFC_MsgWrite(BLE_pairing_NDEF_msg1, sizeof(BLE_pairing_NDEF_msg1));
    if (NfcStatus != NDEF_RW_NO_ERROR)
        {
        Status = ERROR_STATE;
        }
#endif // NDEF_LIBRARY
    return Status;
    }

/*******************************************************************************
 * FUNCTION: NDEF_Demo_Write
 *
 * Description:
 *
 *******************************************************************************/
Status_t NDEF_Demo_Write(void)
    {
#ifdef NDEF_LIBRARY

    void       *pTemp;
    void       *pRecord;
    uint8_t    bErrorFlag;
    Status_t   NdefStatus;
    uint32_t   dwOutBuffLen;
    Status_t   Status = NO_ERROR;
    uint8_t    aOutBuff[NDEF_DATA_BUFF_LEN];
    NDEF_RW_STATUS_T    NfcStatus;
    NDEF_Rec_Aar_t      *pRecordAAR;
    uint32_t            dwPackageLen;
    const char          cPackage[] = "com.nxp.ntagi2cdemo";
    NDEF_Message_t      *pMultiRecMsg = (NDEF_Message_t *)NULL;

    /* create the text record */
    pRecord = NDEF_Rec_Text_CreateByStr("en", "NTAG I2C EXPLORER");
    /* add it to the multi-record field */
    NdefStatus = NDEF_Msg_AppendRecord(&pMultiRecMsg, pRecord);
    if (NdefStatus != NDEF_STATUS_SUCCESS)
        {
        Status = NDEF_STATUS_ERROR;
        }

    /* create the URL record */
    pRecord = NDEF_Rec_Uri_CreateByStr(0x01, "nxp.com/demoboard/OM5569");
    /* add it to the multi-record field */
    NdefStatus = NDEF_Msg_AppendRecord(&pMultiRecMsg, pRecord);
    if (NdefStatus != NDEF_STATUS_SUCCESS)
        {
        Status = NDEF_STATUS_ERROR;
        }

    /* there is not direct function to create AAR record, from that reason is necessary to
     * perform via the generic part of the NDEF library
     */
    /* create the record pointer for AAR */
    pRecordAAR = malloc(sizeof(NDEF_Rec_Aar_t));
    if (pRecordAAR == NULL)
        {
        Status = NDEF_STATUS_ERROR;
        }
    else
        {
        memset(pRecordAAR, 0, sizeof(NDEF_Rec_Aar_t));
        }

    /* set the type */
    pRecordAAR->INT_sRecordInfo.eId = Type_Generic;
    /* set the TNF */
    if (NDEF_Rec_SetTnf(pRecordAAR, ExternalRecord ))
        {
        Status = NDEF_STATUS_ERROR;
        }
    /* fill the type */
    if (NDEF_Rec_SetType(pRecordAAR, "android.com:pkg"))
        {
        Status = NDEF_STATUS_ERROR;
        }
    /* set the flags ....  typically is zero "0" */
    if (NDEF_Rec_SetFlags(pRecordAAR, AAR_FLAGS_INIT_FLAGS))
        {
        Status = NDEF_STATUS_ERROR;
        }

    /* package consists of the code name of the application which could be launched */
    dwPackageLen = strlen(cPackage);
    pTemp = realloc(pRecordAAR->pPackage, dwPackageLen);
    pRecordAAR->pPackage = (uint8_t *)pTemp;
    /* necessary to fill in the header structure */
    pRecordAAR->sHeader.dwPayloadLength = dwPackageLen;
    memcpy(pRecordAAR->pPackage, cPackage, dwPackageLen);
    pRecordAAR->INT_sRecordInfo.dwHeapUsedByPayload = dwPackageLen;

    /* add it to the multi-record field */
    NdefStatus = NDEF_Msg_AppendRecord(&pMultiRecMsg, pRecordAAR);

    if (NdefStatus == NDEF_STATUS_SUCCESS)
        {
        /* create the NDEF message */
        dwOutBuffLen = NDEF_Msg_EncodeToByteArray(pMultiRecMsg, aOutBuff, NDEF_DATA_BUFF_LEN);
        /* write NDEF message to the NTAG I2C chip */
        NfcStatus = NFC_MsgWrite(aOutBuff, dwOutBuffLen);

        if (NfcStatus != NDEF_RW_NO_ERROR)
            {
            Status = ERROR_STATE;
            }
        NDEF_Msg_DestroyMsg((void*)&pMultiRecMsg);

        /* factory reset pages 56,57,58 - default procedure - not exactly required */
        if (NFC_WriteBlock(ntag_handle, 56, Default_Page_56, NTAG_I2C_BLOCK_SIZE))
            {
            Status = NDEF_STATUS_ERROR;
            }
        if (NFC_WriteBlock(ntag_handle, 57, Default_Page_57, NTAG_I2C_BLOCK_SIZE))
            {
            Status = NDEF_STATUS_ERROR;
            }
        if (NFC_WriteBlock(ntag_handle, 58, Default_Page_58, NTAG_I2C_BLOCK_SIZE))
            {
            Status = NDEF_STATUS_ERROR;
            }
        }
    else
        {
        Status = NDEF_STATUS_ERROR;
        }

#else
    Status_t         Status = NO_ERROR;
    NDEF_RW_STATUS_T NfcStatus;

    /*Default NDEF message: SmartPoster
     * Title: NTAG I2C Explorer
     * Link: http://www.nxp.com/demoboard/OM5569
     */
    uint8_t Default_SmartPoster[] = {
            0x91, 0x02, 0x35, 0x53, 0x70, 0x91, 0x01, 0x14, 0x54, 0x02, 0x65, 0x6E, 0x4E, 0x54,
            0x41, 0x47, 0x20, 0x49, 0x32, 0x43, 0x20, 0x45, 0x58, 0x50, 0x4C, 0x4F, 0x52, 0x45, 0x52, 0x51,
            0x01, 0x19, 0x55, 0x01, 0x6E, 0x78, 0x70, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x64, 0x65, 0x6D, 0x6F,
            0x62, 0x6F, 0x61, 0x72, 0x64, 0x2F, 0x4F, 0x4D, 0x35, 0x35, 0x36, 0x39, 0x54, 0x0F, 0x13, 0x61,
            0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x2E, 0x63, 0x6F, 0x6D, 0x3A, 0x70, 0x6B, 0x67, 0x63, 0x6F,
            0x6D, 0x2E, 0x6E, 0x78, 0x70, 0x2E, 0x6E, 0x74, 0x61, 0x67, 0x69, 0x32, 0x63, 0x64, 0x65, 0x6D,
            0x6F
    };

    NfcStatus = NFC_MsgWrite(Default_SmartPoster, sizeof(Default_SmartPoster));
    if (NfcStatus != NDEF_RW_NO_ERROR)
        {
        Status = ERROR_STATE;
        }

#endif // NDEF_LIBRARY

    return Status;
    }


/*! *********************************************************************************
 * @}   end of file
 ********************************************************************************** */



