//------------------------------------------------------------------------------
//! @file WIMOD_SAP_DEVMGMT_ProLink.cpp
//! @ingroup WiMOD_SAP_DEVMGMT_PROLINK
//! <!------------------------------------------------------------------------->
//! @brief Implementation of the commands of the DeviceManagement SericeAccessPoint for LoRaWAN ProLink firmware
//! @version 0.1
//! <!------------------------------------------------------------------------->
//!
//!
//!
//! <!--------------------------------------------------------------------------
//! Copyright (c) 2012
//! IMST GmbH
//! Carl-Friedrich Gauss Str. 2-4
//! 47475 Kamp-Lintfort
//! --------------------------------------------------------------------------->
//! @author (FB), IMST
//! <!--------------------------------------------------------------------------
//! Target OS:    none
//! Target CPU:   tbd
//! Compiler:     tbd
//! --------------------------------------------------------------------------->
//! @internal
//! @par Revision History:
//! <PRE>
//!-----------------------------------------------------------------------------
//! Version | Date       | Author | Comment
//!-----------------------------------------------------------------------------
//!
//! </PRE>
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
// Section Includes Files
//
//------------------------------------------------------------------------------


#include "WiMOD_SAP_DEVMGMT_ProLink.h"

//------------------------------------------------------------------------------
//
// Section public functions
//
//------------------------------------------------------------------------------

//-----------------------------------------------------------------------------
/**
 * @brief Constructor
 *
 * @param hci       Pointer to HCI processor object
 *
 * @param buffer    pointer to storage area for building tx frames; MUST BE VALID
 *
 * @param bufferSize    size of the buffer
 *
 */
WiMOD_SAP_DevMgmt_ProLink::WiMOD_SAP_DevMgmt_ProLink(TWiMODLRHCI* hci, UINT8* buffer, UINT16 bufferSize) :
    WiMOD_SAP_DevMgmt_Lorawan(hci, buffer, bufferSize)
{

}

//-----------------------------------------------------------------------------
/**
 * @brief Destructor
 */
WiMOD_SAP_DevMgmt_ProLink::~WiMOD_SAP_DevMgmt_ProLink(void)
{

}


TWiMODLRResultCodes WiMOD_SAP_DevMgmt_ProLink::SetRadioStack(const TRadioStack_Mode& stackMode, UINT8* statusRsp)
{
    TWiMODLRResultCodes result = WiMODLR_RESULT_TRANMIT_ERROR;
    UINT8              offset = 0;



    if (statusRsp  && (txyPayloadSize >= 0x01)) {
        txPayload[offset++] = (UINT8) stackMode;

        result = HciParser->SendHCIMessage(DEVMGMT_SAP_ID,
                                           PROLINK_DEVMGMT_MSG_SET_RADIO_STACK_REQ,
                                           PROLINK_DEVMGMT_MSG_SET_RADIO_STACK_RSP,
                                           txPayload, offset);

        if (result == WiMODLR_RESULT_OK) {
            const TWiMODLR_HCIMessage& rx = HciParser->GetRxMessage();
            offset = WiMODLR_HCI_RSP_STATUS_POS;
            *statusRsp = rx.Payload[offset++];
        }
    }
    return result;
}


TWiMODLRResultCodes WiMOD_SAP_DevMgmt_ProLink::GetRadioStack(TRadioStack_Mode* stackMode, UINT8* statusRsp)
{
    TWiMODLRResultCodes result = WiMODLR_RESULT_TRANMIT_ERROR;
    UINT8              offset = WiMODLR_HCI_RSP_STATUS_POS;

    if (stackMode && statusRsp) {
        result = HciParser->SendHCIMessage(DEVMGMT_SAP_ID,
                                            PROLINK_DEVMGMT_MSG_GET_RADIO_STACK_REQ,
                                            PROLINK_DEVMGMT_MSG_GET_RADIO_STACK_RSP,
                                           NULL, 0);

        if (result == WiMODLR_RESULT_OK) {
            const TWiMODLR_HCIMessage& rx = HciParser->GetRxMessage();
            offset = WiMODLR_HCI_RSP_CMD_PAYLOAD_POS;

            *stackMode = (TRadioStack_Mode) rx.Payload[offset++];

            *statusRsp = rx.Payload[WiMODLR_HCI_RSP_STATUS_POS];
        }
    }
    return result;
}


TWiMODLRResultCodes WiMOD_SAP_DevMgmt_ProLink::SetDeviceConfig(const TProLinkDeviceConfig& config, UINT8* statusRsp)
{
    TWiMODLRResultCodes result = WiMODLR_RESULT_TRANMIT_ERROR;
    UINT8              offset = 0;



    if (statusRsp  && (txyPayloadSize >= 0x04)) {
        txPayload[offset++] = (UINT8) 0x00; // reserved
        txPayload[offset++] = (UINT8) config.PowerSavingMode;
        txPayload[offset++] = (UINT8) 0x00; // reserved
        txPayload[offset++] = (UINT8) config.MiscOptions;

        result = HciParser->SendHCIMessage(DEVMGMT_SAP_ID,
                                           PROLINK_DEVMGMT_MSG_SET_DEVICE_CONFIG_REQ,
                                           PROLINK_DEVMGMT_MSG_SET_DEVICE_CONFIG_RSP,
                                           txPayload, offset);

        if (result == WiMODLR_RESULT_OK) {
            const TWiMODLR_HCIMessage& rx = HciParser->GetRxMessage();
            offset = WiMODLR_HCI_RSP_STATUS_POS;
            *statusRsp = rx.Payload[offset++];
        }
    }
    return result;
}


TWiMODLRResultCodes WiMOD_SAP_DevMgmt_ProLink::GetDeviceConfig(TProLinkDeviceConfig* config, UINT8* statusRsp)
{
    TWiMODLRResultCodes result = WiMODLR_RESULT_TRANMIT_ERROR;
    UINT8              offset = WiMODLR_HCI_RSP_STATUS_POS;

    if (config && statusRsp) {
        result = HciParser->SendHCIMessage(DEVMGMT_SAP_ID,
                                            PROLINK_DEVMGMT_MSG_GET_DEVICE_CONFIG_REQ,
                                            PROLINK_DEVMGMT_MSG_GET_DEVICE_CONFIG_RSP,
                                           NULL, 0);

        if (result == WiMODLR_RESULT_OK) {
            const TWiMODLR_HCIMessage& rx = HciParser->GetRxMessage();
            offset++; // ingore status
            offset++; // reserved
            config->PowerSavingMode = rx.Payload[offset++];
            offset++; // reserved
            config->MiscOptions     = rx.Payload[offset++];

            *statusRsp = rx.Payload[WiMODLR_HCI_RSP_STATUS_POS];
        }
    }
    return result;
}

TWiMODLRResultCodes WiMOD_SAP_DevMgmt_ProLink::ResetDeviceConfig(UINT8* statusRsp)
{
    TWiMODLRResultCodes result = WiMODLR_RESULT_TRANMIT_ERROR;
    UINT8              offset = 0;



    if (statusRsp  && (txyPayloadSize >= 0x04)) {

        result = HciParser->SendHCIMessage(DEVMGMT_SAP_ID,
                                           PROLINK_DEVMGMT_MSG_RESET_DEVICE_CONFIG_REQ,
                                           PROLINK_DEVMGMT_MSG_RESET_DEVICE_CONFIG_RSP,
                                           txPayload, offset);

        if (result == WiMODLR_RESULT_OK) {
            const TWiMODLR_HCIMessage& rx = HciParser->GetRxMessage();
            offset = WiMODLR_HCI_RSP_STATUS_POS;
            *statusRsp = rx.Payload[offset++];
        }
    }
    return result;
}

TWiMODLRResultCodes WiMOD_SAP_DevMgmt_ProLink::GetSystemStatus(TWiMODLR_DevMgmt_SystemStatus* info, UINT8* statusRsp) {
    (void) info;
    // not supported in this firmware
    return unsupportedCmd(statusRsp);
}

TWiMODLRResultCodes WiMOD_SAP_DevMgmt_ProLink::GetDeviceStatus(TProLinkDeviceStatus* devStatus, UINT8* statusRsp)
{
    TWiMODLRResultCodes result = WiMODLR_RESULT_TRANMIT_ERROR;
    UINT8              offset = WiMODLR_HCI_RSP_STATUS_POS;

    if (devStatus && statusRsp) {
        result = HciParser->SendHCIMessage(DEVMGMT_SAP_ID,
                                            PROLINK_DEVMGMT_MSG_GET_DEVICE_STATUS_REQ,
                                            PROLINK_DEVMGMT_MSG_GET_DEVICE_STATUS_RSP,
                                           NULL, 0);

        if (result == WiMODLR_RESULT_OK) {
            const TWiMODLR_HCIMessage& rx = HciParser->GetRxMessage();

            /* common part*/
            devStatus->Status                   = rx.Payload[offset++];
            devStatus->SysTickResolution        = rx.Payload[offset++];
            devStatus->SysTickCounter           = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->RtcTime                  = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->NvmStatus                = NTOH16(&rx.Payload[offset]);
            offset += 0x02;
            devStatus->BatteryStatus            = NTOH16(&rx.Payload[offset]);
            offset += 0x02;
            devStatus->ExtraStatus              = NTOH16(&rx.Payload[offset]);
            offset += 0x02;

            /*LoRaWAN part*/
            devStatus->LoRaWAN_TxUDataPackets   = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_TxCDataPackets   = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_TxError          = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_Rx1UDataPackets  = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_Rx1CDataPackets  = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_Rx1MicError      = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_Rx2UDataPackets  = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_Rx2CDataPackets  = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_Rx2MicError      = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_TxJoin           = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LoRaWAN_RxAccept         = NTOH32(&rx.Payload[offset]);
            offset += 0x04;

            /*proprietary part (LR-BASE)*/
            devStatus->LRBASE_RxPackets         = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LRBASE_RxAddressMatch    = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LRBASE_RxCRCError        = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LRBASE_TxPackets         = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LRBASE_TxError           = NTOH32(&rx.Payload[offset]);
            offset += 0x04;
            devStatus->LRBASE_TxMediaBusyEvents = NTOH32(&rx.Payload[offset]);
            offset += 0x04;

            *statusRsp = rx.Payload[WiMODLR_HCI_RSP_STATUS_POS];
        }
    }
    return result;
}

//------------------------------------------------------------------------------
//
// Section protected functions
//
//------------------------------------------------------------------------------
/**
 * @internal
 * @brief default cmd handler for unknown / unsupported commands
 * @params statusRsp    pointer to HCI status response code to set
 * @endinternal
 */
TWiMODLRResultCodes WiMOD_SAP_DevMgmt_ProLink::unsupportedCmd(UINT8* statusRsp) {
    if (statusRsp) {
        *statusRsp = DEVMGMT_STATUS_CMD_NOT_SUPPORTED;
    }
    return WiMODLR_RESULT_TRANMIT_ERROR;
}

