/*******************************************************************************
* Project:      Amped'RF Bluetooth
* File name:    App_Ex2.c
* Description:  Example for intercepting the host UART messages using
*               the SIG_AT_RX_DONE signal.
*
* Copyright (c) 2016 Amped'RF Technology Inc, All rights reserved.
*******************************************************************************/
#ifdef SDK
#include "SDK_Common.h"
#include "App_Ex.h"
#if APP_EXAMPLE == 2


/*******************************************************************************
* Used for debugging
*******************************************************************************/
#define DPRINT(x)   TM_printlf(x); TM_printflush()


/*******************************************************************************
* Structures & Defines
*******************************************************************************/
#define STRMAX 128
typedef struct {
    bool    Connected;
    uint16  PortHandle;
    uint8   portname[AMP_PORT_NAME_LENGTH];
    tBdAddr BdAddr;
    uint8   Role;
} tRemoteDevice;


/*******************************************************************************
*   Globals
*******************************************************************************/
tRemoteDevice   Remote={0};
uint64 Connect_BD_ADDR=0x00043e083613;



/*******************************************************************************
* Function Name  : SppConnect
* Description    : Make a connection
*******************************************************************************/
void SppConnect(tBdAddr RemoteAddress)
{
    tOS_Signal                *pSignal;
    tSIG_AMPSppConnectRequest *pConnectReq;

    pSignal = BP_AllocSignal(SIG_AMP_SPP_CONNECT_REQ, sizeof(tSIG_AMPSppConnectRequest));
    pConnectReq = (tSIG_AMPSppConnectRequest *)OS_GetSignalDataPtr(pSignal);

    memset(pConnectReq, 0, sizeof(tSIG_AMPSppConnectRequest));      // zero structure
    memcpy(&pConnectReq->BdAddr, &RemoteAddress, 6);                // set bd addr
    strcpy((char *)pConnectReq->PortName, "Port");
    pConnectReq->ServiceId = BTM_SEC_SERVICE_SERIAL_PORT;

    TM_print("Connecting to ");
    for (int i=0; i<6; i++) {
        TM_print("%02x", pConnectReq->BdAddr.Byte[5-i]);
    }
    TM_printlf("");
    TM_printflush();

    uuid = eUUID_SPP;
    OS_Send(OS_AMP, pSignal);
}


/*******************************************************************************
* Function Name  : SppDisconnect
* Description    : Disconnect a connection
*******************************************************************************/
void SppDisconnect(uint8 *portname, uint8 role)
{
    tOS_Signal                   *pSignal;
    tSIG_AMPSppDisconnectRequest *pDisconReq;

    pSignal= BP_AllocSignal(SIG_BTI_SPP_DISCONNECT_REQ, sizeof(tSIG_AMPSppDisconnectRequest));
    pDisconReq = (tSIG_AMPSppDisconnectRequest*)OS_GetSignalDataPtr(pSignal);
    memset(pDisconReq, 0, sizeof(tSIG_AMPSppDisconnectRequest));
    memcpy(pDisconReq->PortName, portname, AMP_PORT_NAME_LENGTH);
    pDisconReq->SppRole = role;
    OS_Send(OS_AMP, pSignal);
}



/*******************************************************************************
* SDK_ReceiveSignal
* This handles signals for AT and the SDK application. All AT signals are first
* sent here. If they are ignored the signals are passed to the AT layer. If
* RetCode is zero, the signal will be handled by AT. If it is non-zero, further
* processing will be ignored by AT.
********************************************************************************/
int SDK_ReceiveSignal(tOS_Signal *pSignal)
{
    int  RetCode=SIGNAL_UNHANDLED;
    uint16 SigNo = OS_GetSignalNo(pSignal);
    tSIG_AMPSppConnectCon   * pSppConnection;
    char msg[STRMAX+16];
    static int ConnectionCount=0;

    switch (SigNo)
    {
    case SIG_AT_DEVICE_UP:
        TM_printlf("Amped RF DevKit Version %s %s [App_Ex%d.c]",
                SDK_VERSION, SDK_BUILD, APP_EXAMPLE);
        TM_printflush();
        APP_InitTask();
        break;

    case SIG_CONNECT:
        SppConnect(Remote.BdAddr);
        RetCode = SIGNAL_HANDLED;
        break;

    case SIG_DISCONNECT:
        SppDisconnect(Remote.portname, Remote.Role);
        RetCode = SIGNAL_HANDLED;
        break;

    case SIG_AMP_SPP_LISTEN_CON:
    case SIG_AMP_SPP_CONNECT_CON:
        pSppConnection = (tSIG_AMPSppListenCon*)OS_GetSignalDataPtr(pSignal);
        if (pSppConnection->Status == AMP_RESULT_CONNECTION_UP) {
            Remote.Role = (SigNo==SIG_AMP_SPP_LISTEN_CON) ? 1 : 0;
            pSppConnection = (tSIG_AMPSppListenCon*)OS_GetSignalDataPtr(pSignal);
            Remote.Connected = true;
            Remote.PortHandle = pSppConnection->Handle;
            memcpy(Remote.portname, pSppConnection->PortName, AMP_PORT_NAME_LENGTH);
            Remote.BdAddr = pSppConnection->BdAddr;

            sprintf(msg, "Connect # %d\r\n", ++ConnectionCount);
            OS_SendDataToHandle(Remote.PortHandle, (u8 *)msg, strlen(msg));
            TM_print(msg);
            TM_printflush();

            // Disconnect in two seconds
            OS_TimerRegisterRequest(0, APP_TMRID_DISCONNECT, 2000, SIG_DISCONNECT);
        }
        RetCode = SIGNAL_HANDLED;
        break;

    case SIG_AMP_SPP_DISCONNECT_IND:
    case SIG_AMP_SPP_DISCONNECT_CON:
        if (Remote.Connected) {
            Remote.Connected = false;
            // Connect in three seconds
            OS_TimerRegisterRequest(0, APP_TMRID_CONNECT, 3000, SIG_CONNECT);
        }
        RetCode = SIGNAL_HANDLED;
        break;
    }

    //---------------------------------------------------------------
    // RetCode == 0 Unhandled Signal
    // RetCode == 1 Signal was handled in this function
    //---------------------------------------------------------------
    if (RetCode==SIGNAL_HANDLED) {
        OS_ReleaseSignal(pSignal);
    }
    return RetCode;
}



/*******************************************************************************
* Function Name  : APP_InitTask
* Description    : Initialize App layer
********************************************************************************/
void APP_InitTask(void)
{
    // Initialize your variables here
    memset(&Remote, 0, sizeof(Remote));
    memcpy(&Remote.BdAddr, &Connect_BD_ADDR, 6);
}


#endif // APP_EXAMPLE
#endif // SDK
