/*
*                    Copyright (c), NXP Semiconductors
*
*                       (C) NXP Semiconductors 2018
*
*         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.
*/

/* ********************************************************************************************
* Includes
* ****************************************************************************************** */

#include <stdio.h>
#include <string.h>
#include "Internal/NDEF_Heap.h"
#include "Internal/NDEF_RecordInternals.h"
#include "Records/NDEF_Rec_BluetoothSsp.h"

/* ********************************************************************************************
* Definitions
* ******************************************************************************************* */



#define AD_LEN_LENGTH	1
#define BTSSP_FLAGS_INIT_FLAGS	0 //the ID number is added within the encoding
#define BTSSP_DEVICE_ADDR_OFFSET 1

#define  ZERO_DATA_BYTE                         0x00
#define  ZERO_DATA_WORD                         0x0000
#define  ZERO_DATA_DWORD                        0x00000000


/* ********************************************************************************************
* Global and Static Variables
* Total Size: NNNbytes
* ******************************************************************************************* */


/* ********************************************************************************************
* Private Functions Prototypes
* ******************************************************************************************* */
static Status_t NDEF_Rec_Btssp_SetOptionalOobData_BrEdr(NDEF_Rec_BtsspBrEdr_t * pRecord, const uint8_t * pOptionalOobData, uint16_t wOobDataLength);
static Status_t NDEF_Rec_Btssp_SetOptionalOobData_Le(NDEF_Rec_BtsspLe_t * pRecord, const uint8_t * pOptionalOobData, uint16_t wOobDataLength);
static Status_t Btssp_SetHeaderBrEdr(NDEF_Rec_BtsspBrEdr_t * pRecord);
static Status_t Btssp_SetHeaderLe(NDEF_Rec_BtsspLe_t * pRecord);

/* ********************************************************************************************
* Public Functions
* ******************************************************************************************* */
NDEF_Rec_BtsspBrEdr_t * NDEF_Rec_Btssp_CreateBrEdr(const uint8_t * pDeviceAdress)
{
	NDEF_Rec_BtsspBrEdr_t * pRecord = NULL;
	Status_t status;
	uint8_t  bErrorFlag = 0;

	/* check input pointer */
	if (pDeviceAdress != NULL)
	{
		/* allocate the memory for the BTSSP record */
		do
		{
			pRecord = (NDEF_Rec_BtsspBrEdr_t *)INT_MALLOC(sizeof(NDEF_Rec_BtsspBrEdr_t));

			BREAK_ON_NULL(pRecord, bErrorFlag);
			memset(pRecord, ZERO_DATA_BYTE, sizeof(NDEF_Rec_BtsspBrEdr_t));

			/* set internal info of the record type */
			pRecord->INT_sRecordInfo.eId = Type_BtsspBrEdr;

			status = Btssp_SetHeaderBrEdr(pRecord);
			BREAK_ON_FAILURE(status);


			/* copy the device address to the record structure */
			memcpy(pRecord->aDeviceAddress, pDeviceAdress, BTSSP_DEVICE_ADDR_LEN);

			pRecord->sHeader.dwPayloadLength = BTSSP_DEVICE_ADDR_LEN + BTSSP_OOB_DATA_LENGTH_LEN;

			status = NDEF_Rec_Btssp_SetOptionalOobData_BrEdr(pRecord, NULL, 0);
			BREAK_ON_FAILURE(status);
		} while (0);

		if ((bErrorFlag || status) != NDEF_STATUS_SUCCESS)
		{
			NDEF_Rec_Destroy((void **)(&pRecord));
			pRecord = NULL;
		}
	}
	return pRecord;
}


NDEF_Rec_BtsspLe_t * NDEF_Rec_Btssp_CreateLe(const uint8_t * pDeviceAdress, AddressType_t eAddressType, DeviceRole_t eRole)
{
	NDEF_Rec_BtsspLe_t * pRecord = NULL;
	Status_t status;
	uint8_t  bErrorFlag = 0;

	/* check input pointer */
	if (pDeviceAdress != NULL)
	{
		/* allocate the memory for the BTSSP record */
		do
		{
			pRecord = (NDEF_Rec_BtsspLe_t *)INT_MALLOC(sizeof(NDEF_Rec_BtsspLe_t));

			BREAK_ON_NULL(pRecord, bErrorFlag);
			memset(pRecord, ZERO_DATA_BYTE, sizeof(NDEF_Rec_BtsspLe_t));

			status = Btssp_SetHeaderLe(pRecord);
			BREAK_ON_FAILURE(status);

			/* set internal info of the record type */
			pRecord->INT_sRecordInfo.eId = Type_BtsspLe;
			/* this is the Bluetooth LE role type */
			pRecord->eLeRole = eRole;
			/* address type is copied at the beginning of the device address */
			pRecord->aDeviceAddress[0] = (uint8_t)eAddressType;
			/* copy the device address to the record structure */
			memcpy((pRecord->aDeviceAddress + BTSSP_DEVICE_ADDR_OFFSET), pDeviceAdress, BTSSP_DEVICE_ADDR_LEN);

			pRecord->sHeader.dwPayloadLength = BTSSP_LE_ROLE_TOTAL_LEN + BTSSP_LE_DEVICE_ADDR_TOTAL_LEN;

		} while (0);

		if (bErrorFlag || status != NDEF_STATUS_SUCCESS)
		{
			NDEF_Rec_Destroy((void **)(&pRecord));
			pRecord = NULL;
		}
	}
	return pRecord;

}

Status_t NDEF_Rec_Btssp_SetOptionalOobData(void * pRecord, const uint8_t * pOptionalOobData, uint16_t wOobDataLength)
{
	Status_t sRetVal = NDEF_STATUS_SUCCESS;
	RETURN_ON_NULL_PARAM(pRecord);
	RETURN_ON_NULL_PARAM(pOptionalOobData);

	if (((NDEF_Rec_BtsspBrEdr_t *)pRecord)->INT_sRecordInfo.eId == Type_BtsspBrEdr)
	{
		sRetVal = NDEF_Rec_Btssp_SetOptionalOobData_BrEdr((NDEF_Rec_BtsspBrEdr_t *)pRecord, pOptionalOobData, wOobDataLength);
	}
	else if (((NDEF_Rec_BtsspLe_t *)pRecord)->INT_sRecordInfo.eId == Type_BtsspLe)
	{
		sRetVal = NDEF_Rec_Btssp_SetOptionalOobData_Le((NDEF_Rec_BtsspLe_t *)pRecord, pOptionalOobData, wOobDataLength);
	}
	else
	{
		sRetVal = NDEF_STATUS_ERROR_INVALID_PARAM;
	}

	return sRetVal;
}


Status_t NDEF_Rec_Btssp_GetOptionalOobData(const void * pRecord, uint8_t * pOptionalOobData, uint16_t wLength)
{
	uint16_t wOobDataFieldLen;

	/* check the input pointers */
	RETURN_ON_NULL_PARAM(pRecord);
	RETURN_ON_NULL_PARAM(pOptionalOobData);

	if (((NDEF_Rec_BtsspBrEdr_t *)pRecord)->INT_sRecordInfo.eId == Type_BtsspBrEdr)
	{
		/* check the input pointers */
		RETURN_ON_NULL_MEMBER(((NDEF_Rec_BtsspBrEdr_t *)pRecord)->pOptionalOobData);

		/* take the length of the OOB data from payload of the BR/EDR record */
		wOobDataFieldLen = (uint16_t)(((NDEF_Rec_BtsspBrEdr_t *)pRecord)->sHeader.dwPayloadLength - BTSSP_DEVICE_ADDR_LEN - BTSSP_OOB_DATA_LENGTH_LEN);
		/* return error if required length is more then existing */
		if (wOobDataFieldLen > wLength)
		{
			return NDEF_STATUS_ERROR_BUFF_OVF;
		}
		/* copy the get the data */
		memcpy(pOptionalOobData, ((NDEF_Rec_BtsspBrEdr_t *)pRecord)->pOptionalOobData, wOobDataFieldLen);
	}
	else if (((NDEF_Rec_BtsspLe_t *)pRecord)->INT_sRecordInfo.eId == Type_BtsspLe)
	{
		/* check the input pointers */
		RETURN_ON_NULL_MEMBER(((NDEF_Rec_BtsspLe_t *)pRecord)->pOptionalOobData);

		/* take the length of the OOB data from payload of the LE record */
		wOobDataFieldLen = (uint16_t)(((NDEF_Rec_BtsspLe_t *)pRecord)->sHeader.dwPayloadLength - BTSSP_LE_DEVICE_ADDR_TOTAL_LEN - BTSSP_LE_ROLE_TOTAL_LEN);
		/* return error if required length is more then existing */
		if (wOobDataFieldLen > wLength)
		{
			return NDEF_STATUS_ERROR_BUFF_OVF;
		}
		/* copy the get the data */
		memcpy(pOptionalOobData, ((NDEF_Rec_BtsspLe_t *)pRecord)->pOptionalOobData, wOobDataFieldLen);
	}

	return NDEF_STATUS_SUCCESS;
}


uint16_t NDEF_Rec_Btssp_GetOptionalOobDataLen(const void * pRecord)
{
	uint16_t wRetVal = ZERO_DATA_WORD;

	if (pRecord != NULL)
	{
		if (((NDEF_Rec_BtsspBrEdr_t *)pRecord)->INT_sRecordInfo.eId == Type_BtsspBrEdr)
		{
			/* take the length of the OOB data from payload of the BR/EDR record */
			wRetVal = (uint16_t)(((NDEF_Rec_BtsspBrEdr_t *)pRecord)->wOobDataLen - BTSSP_DEVICE_ADDR_LEN - BTSSP_OOB_DATA_LENGTH_LEN);
		}
		else if (((NDEF_Rec_BtsspLe_t *)pRecord)->INT_sRecordInfo.eId == Type_BtsspLe)
		{
			/* take the length of the OOB data from payload of the LE record */
			wRetVal = (uint16_t)(((NDEF_Rec_BtsspLe_t *)pRecord)->sHeader.dwPayloadLength - BTSSP_LE_DEVICE_ADDR_TOTAL_LEN - BTSSP_LE_ROLE_TOTAL_LEN);
		}
	}

	return wRetVal;
}


Status_t NDEF_Rec_Btssp_GetDeviceAddress(const void * pRecord, uint8_t * pDeviceAdress)
{
	/* check the input pointers */
	RETURN_ON_NULL_PARAM(pRecord);
	RETURN_ON_NULL_PARAM(pDeviceAdress);

	if (((NDEF_Rec_BtsspBrEdr_t *)pRecord)->INT_sRecordInfo.eId == Type_BtsspBrEdr)
	{
		/* copy the device address from the record structure */
		memcpy(pDeviceAdress, ((NDEF_Rec_BtsspBrEdr_t *)pRecord)->aDeviceAddress, BTSSP_DEVICE_ADDR_LEN);
	}

	else if (((NDEF_Rec_BtsspLe_t *)pRecord)->INT_sRecordInfo.eId == Type_BtsspLe)
	{
		/* copy the device address from the record structure */
		memcpy(pDeviceAdress, (((NDEF_Rec_BtsspLe_t *)pRecord)->aDeviceAddress) + BTSSP_LE_DEVICE_ADDR_DATA_TYPE_LEN, BTSSP_DEVICE_ADDR_LEN);
	}

	return NDEF_STATUS_SUCCESS;
}


AddressType_t NDEF_Rec_Btssp_GetLeAddressType(NDEF_Rec_BtsspLe_t * pRecord)
{
	AddressType_t eRetVal;

	/* check the input pointers */
	if (pRecord != NULL)
	{
		eRetVal = (AddressType_t)pRecord->aDeviceAddress[0];
	}
	else
	{
		eRetVal = ErrorAddressType;
	}

	return eRetVal;
}


DeviceRole_t NDEF_Rec_Btssp_GetLeRole(NDEF_Rec_BtsspLe_t * pRecord)
{
	DeviceRole_t eRetVal;

	/* check the input pointers */
	if (pRecord != NULL)
	{
		eRetVal = pRecord->eLeRole;
	}
	else
	{
		eRetVal = ErrorRole;
	}

	return eRetVal;
}



/* ********************************************************************************************
* Private Functions
* ******************************************************************************************* */
static Status_t NDEF_Rec_Btssp_SetOptionalOobData_BrEdr(NDEF_Rec_BtsspBrEdr_t * pRecord, const uint8_t * pOptionalOobData, uint16_t wOobDataLength)
{
	void * pTemp;

	if (wOobDataLength)
	{
		pTemp = INT_REALLOC(pRecord->pOptionalOobData, wOobDataLength);
		RETURN_ON_NULL_MEMBER(pTemp);
		pRecord->pOptionalOobData = (uint8_t *)pTemp;

		/* payload length consists of the DEVICE ADDRESS + OOB data length + OOB data */
		pRecord->sHeader.dwPayloadLength = wOobDataLength + BTSSP_DEVICE_ADDR_LEN + BTSSP_OOB_DATA_LENGTH_LEN;
		pRecord->wOobDataLen = (uint16_t)pRecord->sHeader.dwPayloadLength;
		memcpy(pRecord->pOptionalOobData, pOptionalOobData, wOobDataLength);
	}
	else
	{
		/* if nothing OOB data the OOB data length takes 2 bytes more and the value is "0" */
		pRecord->sHeader.dwPayloadLength = BTSSP_DEVICE_ADDR_LEN + BTSSP_OOB_DATA_LENGTH_LEN;
		pRecord->wOobDataLen = (uint16_t)pRecord->sHeader.dwPayloadLength;
		INT_FREE(pRecord->pOptionalOobData);
		pRecord->pOptionalOobData = NULL;
	}
	return NDEF_STATUS_SUCCESS;
}


static Status_t NDEF_Rec_Btssp_SetOptionalOobData_Le(NDEF_Rec_BtsspLe_t * pRecord, const uint8_t * pOptionalOobData, uint16_t wOobDataLength)
{
	void * pTemp;

	if (wOobDataLength)
	{
		pTemp = INT_REALLOC(pRecord->pOptionalOobData, wOobDataLength);
		RETURN_ON_NULL_MEMBER(pTemp);
		pRecord->pOptionalOobData = (uint8_t *)pTemp;

		/* payload length consists of the following data:
		 *  DEVICE ADDRESS + OOB data length + OOB data */
		pRecord->sHeader.dwPayloadLength = wOobDataLength + BTSSP_LE_DEVICE_ADDR_TOTAL_LEN + BTSSP_LE_ROLE_TOTAL_LEN;
		memcpy(pRecord->pOptionalOobData, pOptionalOobData, wOobDataLength);
	}
	else
	{
		/* if nothing OOB data the OOB data length takes 2 bytes more and the value is "0" */
		pRecord->sHeader.dwPayloadLength = BTSSP_LE_DEVICE_ADDR_TOTAL_LEN + BTSSP_LE_ROLE_TOTAL_LEN;
		INT_FREE(pRecord->pOptionalOobData);
		pRecord->pOptionalOobData = NULL;
	}

	return NDEF_STATUS_SUCCESS;
}


static Status_t Btssp_SetHeaderBrEdr(NDEF_Rec_BtsspBrEdr_t * pRecord)
{
	Status_t status;
	do
	{
		status = NDEF_Rec_SetTnf(pRecord, MimeRecord);
		BREAK_ON_FAILURE(status);
		status = NDEF_Rec_SetType(pRecord, BTSSP_TYPE_BREDR);
		BREAK_ON_FAILURE(status);
		status = NDEF_Rec_SetFlags(pRecord, BTSSP_FLAGS_INIT_FLAGS);
		BREAK_ON_FAILURE(status);
	} while (0);
	return status;
}


static Status_t Btssp_SetHeaderLe(NDEF_Rec_BtsspLe_t * pRecord)
{
	Status_t status;
	do
	{
		status = NDEF_Rec_SetTnf(pRecord, MimeRecord);
		BREAK_ON_FAILURE(status);
		status = NDEF_Rec_SetType(pRecord, BTSSP_TYPE_LE);
		BREAK_ON_FAILURE(status);
		status = NDEF_Rec_SetFlags(pRecord, BTSSP_FLAGS_INIT_FLAGS);
		BREAK_ON_FAILURE(status);
	} while (0);
	return status;
}

/* ********************************************************************************************
* Internal functions - not part of API
* ******************************************************************************************* */
Status_t INT_Btssp_Free(void *pRecord)
{
	NDEF_Rec_BtsspBrEdr_t * pRec;
	pRec = (NDEF_Rec_BtsspBrEdr_t *)pRecord;
	if (pRec->INT_sRecordInfo.dwHeapUsedByPayload != 0)
	{
		INT_FREE(pRec->pOptionalOobData);
		pRec->INT_sRecordInfo.dwHeapUsedByPayload = 0;
		pRec->pOptionalOobData = NULL;
	}
	return NDEF_STATUS_SUCCESS;
}

Status_t INT_BtsspLe_Free(void *pRecord)
{
	NDEF_Rec_BtsspLe_t * pRec;
	pRec = (NDEF_Rec_BtsspLe_t *)pRecord;
	if (pRec->INT_sRecordInfo.dwHeapUsedByPayload != 0)
	{
		INT_FREE(pRec->pOptionalOobData);
		pRec->INT_sRecordInfo.dwHeapUsedByPayload = 0;
		pRec->pOptionalOobData = NULL;
	}
	return NDEF_STATUS_SUCCESS;
}


Status_t INT_BtsspBrEdr_Serialize(void *pRecord, uint8_t * pOutput, uint32_t * pOffset)
{
	Status_t status;
	uint32_t dwOobDataLen;
	uint32_t dwOffset;
	uint8_t bCounter;
	NDEF_Rec_BtsspBrEdr_t * pRec;

	pRec = (NDEF_Rec_BtsspBrEdr_t *)pRecord;
	dwOffset = *pOffset;

	status = INT_Header_Serialize(pRecord, pOutput, &dwOffset);

	/* Length of OOB data is little endian*/
	pOutput[dwOffset++] = (uint8_t)(pRec->wOobDataLen & 0x00FFUL);
	pOutput[dwOffset++] = (uint8_t)((pRec->wOobDataLen & 0xFF00UL) >> 8);

	/* Address byte order is reversed*/
	for (bCounter = BTSSP_DEVICE_ADDR_LEN; bCounter > 0; bCounter--)
	{
		pOutput[dwOffset++] = pRec->aDeviceAddress[bCounter - 1];
	}



	if (pRec->pOptionalOobData != NULL)
	{
		dwOobDataLen = NDEF_Rec_Btssp_GetOptionalOobDataLen(pRec);
		memcpy(&pOutput[dwOffset], pRec->pOptionalOobData, dwOobDataLen);
		dwOffset += dwOobDataLen;
	}

	*pOffset = dwOffset;
	return status;
}


Status_t INT_BtsspLe_Serialize(void *pRecord, uint8_t * pOutput, uint32_t * pOffset)
{
	Status_t status;
	uint32_t dwOobDataLen;
	uint32_t dwOffset;
	uint8_t bCounter;
	NDEF_Rec_BtsspLe_t * pRec;

	pRec = (NDEF_Rec_BtsspLe_t *)pRecord;
	dwOffset = *pOffset;

	status = INT_Header_Serialize(pRecord, pOutput, &dwOffset);

	/* Address field in Advertising and Scan Response Data format*/
	pOutput[dwOffset] = (uint8_t)(BTSSP_LE_DEVICE_ADDR_DATA_TYPE_LEN + BTSSP_LE_DEVICE_ADDR_LEN);
	dwOffset += BTSSP_LE_DEVICE_ADDR_LENGTH_LEN;
	pOutput[dwOffset] = BTSSP_LE_DEVICE_ADDR_DATA_TYPE;
	dwOffset += BTSSP_LE_DEVICE_ADDR_DATA_TYPE_LEN;
	/* Address byte order is reversed*/
	for (bCounter = BTSSP_LE_DEVICE_ADDR_LEN; bCounter > 0; bCounter--)
	{
		pOutput[dwOffset++] = pRec->aDeviceAddress[bCounter - 1];
	}


	/* LE Role field in Advertising and Scan Response Data format*/
	pOutput[dwOffset] = (uint8_t)(BTSSP_LE_ROLE_DATA_TYE_LEN + BTSSP_LE_ROLE_LEN);
	dwOffset += BTSSP_LE_ROLE_LENGTH_LEN;
	pOutput[dwOffset] = BTSSP_LE_ROLE_DATA_TYPE;
	dwOffset += BTSSP_LE_ROLE_DATA_TYE_LEN;
	pOutput[dwOffset] = (uint8_t)pRec->eLeRole;
	dwOffset += BTSSP_LE_ROLE_LEN;

	/*Optional OOB data*/
	if (pRec->pOptionalOobData != NULL)
	{
		dwOobDataLen = NDEF_Rec_Btssp_GetOptionalOobDataLen(pRec);
		memcpy(&pOutput[dwOffset], pRec->pOptionalOobData, dwOobDataLen);
		dwOffset += dwOobDataLen;
	}

	*pOffset = dwOffset;
	return status;
}

void * INT_BtsspBrEdr_Parse(INT_FetchedHeader_t * pFetchedHeader, const uint8_t * pInput)
{
	NDEF_Rec_BtsspBrEdr_t * pRecord;
	uint32_t dwOffset;
	uint16_t wOobDataLen = 0;
	uint8_t bCounter;
	uint8_t bErrorFlag = 0;
	dwOffset = pFetchedHeader->dwOffsetToPayload;
	pRecord = INT_MALLOC(sizeof(NDEF_Rec_BtsspBrEdr_t));
	RETURN_NULL_ON_NULL(pRecord);
	memset(pRecord, 0, sizeof(NDEF_Rec_BtsspBrEdr_t));
	pRecord->INT_sRecordInfo.eId = Type_BtsspBrEdr;
	memcpy(&pRecord->sHeader, &pFetchedHeader->sHeader, sizeof(NDEF_Record_Header_t));

	if (pFetchedHeader->sHeader.dwPayloadLength)
	{
		do
		{
			/* OobDataLen is little endian*/
			wOobDataLen |= ((uint16_t)(pInput[dwOffset++]));
			wOobDataLen |= ((uint16_t)(pInput[dwOffset++]) << 8);
			pRecord->wOobDataLen = wOobDataLen;


			/*Device Address*/
			for (bCounter = BTSSP_DEVICE_ADDR_LEN; bCounter > 0; bCounter--)
			{
				pRecord->aDeviceAddress[bCounter - 1] = pInput[dwOffset++];
			}


			/* Optional OobData*/
			/* substract 8 bytes to get optional oob data len*/
			wOobDataLen = wOobDataLen - BTSSP_DEVICE_ADDR_LEN - BTSSP_OOB_DATA_LENGTH_LEN;
			if (wOobDataLen)
			{
				pRecord->pOptionalOobData = INT_MALLOC(sizeof(uint8_t)*wOobDataLen);
				BREAK_ON_NULL(pRecord->pOptionalOobData, bErrorFlag);
				memcpy(pRecord->pOptionalOobData, &pInput[dwOffset], wOobDataLen);
			}
			else
			{
				pRecord->pOptionalOobData = NULL;
			}

		} while (0);
	}
	if (bErrorFlag)
	{
		INT_FREE(pRecord);
		pRecord = NULL;
	}
	return pRecord;
}

void * INT_BtsspLe_Parse(INT_FetchedHeader_t * pFetchedHeader, const uint8_t * pInput)
{
	NDEF_Rec_BtsspLe_t * pRecord;
	void * pTempPtr;
	uint32_t dwOffset;
	uint16_t wOobDataLen = 0;
	uint8_t bCounter;
	uint8_t bAdType;
	uint8_t bAdLength;
	uint8_t bErrorFlag = 0;

	dwOffset = pFetchedHeader->dwOffsetToPayload;
	pRecord = INT_MALLOC(sizeof(NDEF_Rec_BtsspLe_t));
	RETURN_NULL_ON_NULL(pRecord);
	memset(pRecord, 0, sizeof(NDEF_Rec_BtsspLe_t));
	pRecord->INT_sRecordInfo.eId = Type_BtsspLe;
	memcpy(&pRecord->sHeader, &pFetchedHeader->sHeader, sizeof(NDEF_Record_Header_t));
	/* Iterate trough AD formated OOB data */
	while (pFetchedHeader->sHeader.dwPayloadLength > dwOffset - pFetchedHeader->dwOffsetToPayload)
	{

		bAdType = pInput[dwOffset + 1];
		if (bAdType == (uint8_t)BTSSP_LE_DEVICE_ADDR_DATA_TYPE)
		{
			/*Parse device address*/
			dwOffset += BTSSP_LE_DEVICE_ADDR_LENGTH_LEN + BTSSP_LE_DEVICE_ADDR_DATA_TYPE_LEN;
			for (bCounter = BTSSP_LE_DEVICE_ADDR_LEN; bCounter > 0; bCounter--)
			{
				pRecord->aDeviceAddress[bCounter - 1] = pInput[dwOffset++];

			}

		}
		else if (bAdType == (uint8_t)BTSSP_LE_ROLE_DATA_TYPE)
		{
			/* Parse device role*/
			dwOffset += BTSSP_LE_ROLE_LENGTH_LEN + BTSSP_LE_DEVICE_ADDR_DATA_TYPE_LEN;
			pRecord->eLeRole = (DeviceRole_t)(pInput[dwOffset++]);
		}
		else
		{
			/* Parse optional OOB data*/
			bAdLength = pInput[dwOffset] + AD_LEN_LENGTH;
			wOobDataLen += bAdLength;
			pTempPtr = INT_REALLOC(pRecord->pOptionalOobData, sizeof(uint8_t)*wOobDataLen);
			BREAK_ON_NULL(pTempPtr, bErrorFlag);
			pRecord->pOptionalOobData = pTempPtr;
			memcpy((pRecord->pOptionalOobData + wOobDataLen - bAdLength), &pInput[dwOffset], bAdLength);
			dwOffset += bAdLength;

		}
	}
	if (bErrorFlag)
	{
		INT_FREE(pRecord->pOptionalOobData);
		INT_FREE(pRecord);
		pRecord = NULL;
	}
	return pRecord;
}