
/**
    \file appl_sample_example_7.c

    Source File for Generic OnOff Client Standalone application without CLI or
    menu based console input interface.
*/

/*
    Copyright (C) 2018. Mindtree Ltd.
    All rights reserved.
*/

#if (MESH_STANDALONE == 7)

/* ----------------------------------------- Header File Inclusion */
#include "MS_common.h"
#include "MS_access_api.h"
#include "MS_config_api.h"
#include "MS_generic_onoff_api.h"
#include "blebrr.h"
#include "nvsto.h"

/* Console Input/Output */
#define CONSOLE_OUT(...)    printf(__VA_ARGS__)
#define CONSOLE_IN(...)     scanf(__VA_ARGS__)

void appl_dump_bytes(UCHAR* buffer, UINT16 length);
void appl_mesh_sample (void);

/* Provisioner */
#define UI_PROV_OUTPUT_OOB_ACTIONS \
    (PROV_MASK_OOOB_ACTION_BLINK | PROV_MASK_OOOB_ACTION_BEEP | \
     PROV_MASK_OOOB_ACTION_VIBRATE | PROV_MASK_OOOB_ACTION_NUMERIC | \
     PROV_MASK_OOOB_ACTION_ALPHANUMERIC)

/** Output OOB Maximum size supported */
#define UI_PROV_OUTPUT_OOB_SIZE               0x08

/** Input OOB Actions supported */
#define UI_PROV_INPUT_OOB_ACTIONS \
    (PROV_MASK_IOOB_ACTION_PUSH | PROV_MASK_IOOB_ACTION_TWIST | \
     PROV_MASK_IOOB_ACTION_NUMERIC | PROV_MASK_IOOB_ACTION_ALPHANUMERIC)

/** Input OOB Maximum size supported */
#define UI_PROV_INPUT_OOB_SIZE                0x08

/** Beacon setup timeout in seconds */
#define UI_PROV_SETUP_TIMEOUT_SECS            30

/** Attention timeout for device in seconds */
#define UI_PROV_DEVICE_ATTENTION_TIMEOUT      30

#define PROV_AUTHVAL_SIZE_PL                  16

/** Authentication values for OOB Display - To be made random */
#define UI_DISPLAY_AUTH_DIGIT                 3
#define UI_DISPLAY_AUTH_NUMERIC               35007
#define UI_DISPLAY_AUTH_STRING                "f00l"

#define UI_DEVICE_UUID      {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}

/* AppKey to be used by the configuration client */
#define UI_APPKEY           {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}

/* ----------------------------------------- External Global Variables */


/* ----------------------------------------- Exported Global Variables */


/* ----------------------------------------- Static Global Variables */
/** Provisioning capabilities of local device */
DECL_STATIC PROV_CAPABILITIES_S UI_prov_capab =
{
    /** Number of Elements */
    0x01,

    /** Supported algorithms */
    PROV_MASK_ALGO_EC_FIPS_P256,

    /** Public key type */
    PROV_MASK_PUBKEY_OOBINFO,

    /** Static OOB type */
    PROV_MASK_STATIC_OOBINFO,

    /** Output OOB information */
    { UI_PROV_OUTPUT_OOB_ACTIONS, UI_PROV_OUTPUT_OOB_SIZE },

    /** Input OOB information */
    { UI_PROV_INPUT_OOB_ACTIONS, UI_PROV_INPUT_OOB_SIZE },
};

/** Data exchanged during Provisiong procedure */
DECL_STATIC PROV_DATA_S UI_prov_data =
{
    /** NetKey */
    { 0x45, 0x74, 0x68, 0x65, 0x72, 0x4d, 0x69, 0x6e, 0x64, 0x4e, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x00 },

    /** Index of the NetKey */
    0x0000,

    /** Flags bitmask */
    0x00,

    /** Current value of the IV index */
    0x00000000,

    /** Unicast address of the primary element */
    0x0002
};

/** Default Provisioning method to start */
DECL_STATIC PROV_METHOD_S UI_prov_method =
{
    /** Algorithm */
    PROV_ALGO_EC_FIPS_P256,

    /** Public Key */
    PROV_PUBKEY_NO_OOB,

    /** Authentication Method */
    PROV_AUTH_OOB_NONE,

    /** OOB Information */
    {0x0000, 0x00}
};

/** Current role of application - Provisioner/Device */
DECL_STATIC UCHAR UI_prov_role;

/** Provisioning Handle */
DECL_STATIC PROV_HANDLE UI_prov_handle;

/** Device UUID Identifier */
DECL_STATIC UCHAR UI_device_uuid[MS_DEVICE_UUID_SIZE] = UI_DEVICE_UUID;

/* Set provision started */
DECL_STATIC UCHAR UI_prov_started;

/* Configuration Client Model Handle */
DECL_STATIC MS_ACCESS_MODEL_HANDLE   UI_config_client_model_handle;

/** Appkey to be used for model binding */
DECL_STATIC UCHAR UI_appkey[MS_ACCESS_APPKEY_SIZE] = UI_APPKEY;

/* Generic ONOFF Client Model Handle */
DECL_STATIC MS_ACCESS_MODEL_HANDLE   UI_generic_onoff_client_model_handle;

/* ----------------------------------------- Functions */
/* Model Client - Configuration Models */
/* Send Config Composition Data Get */
void UI_config_client_get_composition_data(UCHAR page)
{
    API_RESULT retval;
    ACCESS_CONFIG_COMPDATA_GET_PARAM  param;
    CONSOLE_OUT
    ("Send Config Composition Data Get\n");
    param.page = page;
    retval = MS_config_client_composition_data_get(&param);
    CONSOLE_OUT
    ("Retval - 0x%04X\n", retval);
}

/* Send Config Appkey Add */
void UI_config_client_appkey_add(UINT16 netkey_index, UINT16 appkey_index, UCHAR* appkey)
{
    API_RESULT retval;
    ACCESS_CONFIG_APPKEY_ADD_PARAM  param;
    CONSOLE_OUT
    ("Send Config Appkey Add\n");
    param.netkey_index = netkey_index;
    param.appkey_index = appkey_index;
    EM_mem_copy(param.appkey, appkey, MS_ACCESS_APPKEY_SIZE);
    /* Update local database */
    MS_access_cm_add_appkey
    (
        0, /* subnet_handle */
        param.appkey_index, /* appkey_index */
        &param.appkey[0] /* app_key */
    );
    retval = MS_config_client_appkey_add(&param);
    CONSOLE_OUT
    ("Retval - 0x%04X\n", retval);
}

void UI_config_client_model_app_bind(UINT16 addr, UINT16 appkey_index, UCHAR model_type, UINT32 model_id)
{
    API_RESULT retval;
    ACCESS_CONFIG_MODEL_APP_BIND_PARAM  param;
    CONSOLE_OUT
    ("Send Config Model App Bind\n");
    param.element_address = addr;
    param.appkey_index = appkey_index;
    param.model.type = model_type;
    param.model.id = model_id;
    retval = MS_config_client_model_app_bind(&param);
    CONSOLE_OUT
    ("Retval - 0x%04X\n", retval);
}

/* Set Publish Address */
void UI_set_publish_address(UINT16 addr, MS_ACCESS_MODEL_HANDLE model_handle)
{
    API_RESULT retval;
    MS_ACCESS_PUBLISH_INFO  publish_info;
    /* Set Publish Information */
    EM_mem_set(&publish_info, 0, sizeof(publish_info));
    publish_info.addr.use_label = MS_FALSE;
    publish_info.appkey_index = ms_max_apps;
    publish_info.remote = MS_FALSE;
    publish_info.addr.addr = addr;
    retval = MS_access_cm_set_model_publication
             (
                 model_handle,
                 &publish_info
             );

    if (API_SUCCESS == retval)
    {
        CONSOLE_OUT
        ("Publish Address is set Successfully.\n");
    }
    else
    {
        CONSOLE_OUT
        ("Failed to set publish address. Status 0x%04X\n", retval);
    }

    return;
}

void UI_generic_onoff_set(UCHAR state)
{
    API_RESULT retval;
    MS_GENERIC_ONOFF_SET_STRUCT  param;
    CONSOLE_OUT
    ("Send Generic Onoff Set\n");
    param.onoff = state;
    param.tid = 0;
    param.optional_fields_present = 0x00;
    retval = MS_generic_onoff_set(&param);
    CONSOLE_OUT
    ("Retval - 0x%04X\n", retval);
}

/**
    \brief Client Application Asynchronous Notification Callback.

    \par Description
    Configuration client calls the registered callback to indicate events occurred to the application.

    \param [in] handle        Model Handle.
    \param [in] opcode        Opcode.
    \param [in] data_param    Data associated with the event if any or NULL.
    \param [in] data_len      Size of the event data. 0 if event data is NULL.
*/
API_RESULT UI_config_client_cb
(
    /* IN */ MS_ACCESS_MODEL_HANDLE* handle,
    /* IN */ UINT32                   opcode,
    /* IN */ UCHAR*                   data_param,
    /* IN */ UINT16                   data_len
)
{
    API_RESULT retval;
    retval = API_SUCCESS;
    CONSOLE_OUT (
        "[CONFIG_CLIENT] Callback. Opcode 0x%04X\n", opcode);
    appl_dump_bytes(data_param, data_len);

    switch(opcode)
    {
    case MS_ACCESS_CONFIG_GATT_PROXY_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_GATT_PROXY_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_HEARTBEAT_PUBLICATION_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_HEARTBEAT_PUBLICATION_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_SIG_MODEL_APP_LIST_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_SIG_MODEL_APP_LIST_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_COMPOSITION_DATA_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_COMPOSITION_DATA_STATUS_OPCODE\n");
        /* Add Appkey */
        UI_config_client_appkey_add(0, 0, UI_appkey);
    }
    break;

    case MS_ACCESS_CONFIG_MODEL_SUBSCRIPTION_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_MODEL_SUBSCRIPTION_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_NETKEY_LIST_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_NETKEY_LIST_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_LOW_POWER_NODE_POLLTIMEOUT_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_LOW_POWER_NODE_POLLTIMEOUT_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_SIG_MODEL_SUBSCRIPTION_LIST_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_SIG_MODEL_SUBSCRIPTION_LIST_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_VENDOR_MODEL_SUBSCRIPTION_LIST_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_VENDOR_MODEL_SUBSCRIPTION_LIST_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_APPKEY_LIST_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_APPKEY_LIST_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_APPKEY_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_APPKEY_STATUS_OPCODE\n");
        /* Bind the model to Appkey */
        UI_config_client_model_app_bind(UI_prov_data.uaddr, 0, MS_ACCESS_MODEL_TYPE_SIG, MS_MODEL_ID_GENERIC_ONOFF_SERVER);
    }
    break;

    case MS_ACCESS_CONFIG_RELAY_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_RELAY_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_FRIEND_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_FRIEND_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_MODEL_APP_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_MODEL_APP_STATUS_OPCODE\n");
        /* Set the Publish address for Config Client */
        UI_set_publish_address(UI_prov_data.uaddr, UI_generic_onoff_client_model_handle);
        /* Send a Generic ON */
    }
    break;

    case MS_ACCESS_CONFIG_NODE_RESET_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_NODE_RESET_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_DEFAULT_TTL_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_DEFAULT_TTL_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_NODE_IDENTITY_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_NODE_IDENTITY_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_HEARTBEAT_SUBSCRIPTION_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_HEARTBEAT_SUBSCRIPTION_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_KEY_REFRESH_PHASE_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_KEY_REFRESH_PHASE_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_NETWORK_TRANSMIT_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_NETWORK_TRANSMIT_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_BEACON_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_BEACON_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_MODEL_PUBLICATION_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_MODEL_PUBLICATION_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_NETKEY_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_NETKEY_STATUS_OPCODE\n");
    }
    break;

    case MS_ACCESS_CONFIG_VENDOR_MODEL_APP_LIST_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_CONFIG_VENDOR_MODEL_APP_LIST_OPCODE\n");
    }
    break;
    }

    return retval;
}

API_RESULT UI_register_config_model_client
(
    MS_ACCESS_ELEMENT_HANDLE element_handle
)
{
    /* Configuration Client */
    API_RESULT retval;
    CONSOLE_OUT("In Model Client - Configuration Models\n");
    retval = MS_config_client_init
             (
                 element_handle,
                 &UI_config_client_model_handle,
                 UI_config_client_cb
             );
    CONSOLE_OUT("Config Model Client Registration Status: 0x%04X\n", retval);
    return retval;
}


/* ---- Generic OnOff Handlers */

/* Generic OnOff Model Client */
/**
    \brief Client Application Asynchronous Notification Callback.

    \par Description
    Generic_Onoff client calls the registered callback to indicate events occurred to the application.

    \param [in] handle        Model Handle.
    \param [in] opcode        Opcode.
    \param [in] data_param    Data associated with the event if any or NULL.
    \param [in] data_len      Size of the event data. 0 if event data is NULL.
*/
API_RESULT UI_generic_onoff_client_cb
(
    /* IN */ MS_ACCESS_MODEL_HANDLE* handle,
    /* IN */ UINT32                   opcode,
    /* IN */ UCHAR*                   data_param,
    /* IN */ UINT16                   data_len
)
{
    API_RESULT retval;
    retval = API_SUCCESS;
    CONSOLE_OUT (
        "[GENERIC_ONOFF_CLIENT] Callback. Opcode 0x%04X\n", opcode);
    appl_dump_bytes(data_param, data_len);

    switch(opcode)
    {
    case MS_ACCESS_GENERIC_ONOFF_STATUS_OPCODE:
    {
        CONSOLE_OUT(
            "MS_ACCESS_GENERIC_ONOFF_STATUS_OPCODE\n");
    }
    break;
    }

    return retval;
}


API_RESULT UI_register_generic_onoff_model_client
(
    MS_ACCESS_ELEMENT_HANDLE element_handle
)
{
    /* Generic OnOff Client */
    API_RESULT retval;
    CONSOLE_OUT("In Generic OnOff Model Client\n");
    retval = MS_generic_onoff_client_init
             (
                 element_handle,
                 &UI_generic_onoff_client_model_handle,
                 UI_generic_onoff_client_cb
             );

    if (API_SUCCESS == retval)
    {
        CONSOLE_OUT(
            "Generic Onoff Client Initialized. Model Handle: 0x%04X\n",
            UI_generic_onoff_client_model_handle);
    }
    else
    {
        CONSOLE_OUT(
            "[ERR] Generic Onoff Client Initialization Failed. Result: 0x%04X\n",
            retval);
    }

    return retval;
}

API_RESULT UI_prov_callback
(
    PROV_HANDLE* phandle,
    UCHAR         event_type,
    API_RESULT    event_result,
    void*         event_data,
    UINT16        event_datalen
)
{
    PROV_DEVICE_S* rdev;
    PROV_CAPABILITIES_S* rcap;
    PROV_DATA_S* rdata;
    PROV_OOB_TYPE_S* oob_info;
    API_RESULT retval;
    UCHAR i;
    UCHAR authstr[PROV_AUTHVAL_SIZE_PL << 1];
    UINT32 authnum;
    UCHAR authtype;
    UCHAR* pauth;
    UINT16 authsize;
    UCHAR  pdata[(MS_DEVICE_UUID_SIZE * 2) + 1];
    UCHAR*   t_data;

    switch (event_type)
    {
    case PROV_EVT_UNPROVISIONED_BEACON:
        /* Reference the beacon pointer */
        rdev = (PROV_DEVICE_S*)event_data;
        retval = API_SUCCESS;

        if (0 != EM_mem_cmp(rdev->uuid, UI_device_uuid, 16))
        {
            /* Beacon not from device of interest. Do no process */
            break;
        }

        CONSOLE_OUT ("Recvd PROV_EVT_UNPROVISIONED_BEACON\n");
        CONSOLE_OUT ("Status - 0x%04X\n", event_result);
        CONSOLE_OUT("\nUUID : [");
        EM_mem_set(pdata, 0x0, sizeof(pdata));
        t_data = pdata;

        for (i = 0; i < (MS_DEVICE_UUID_SIZE); i++)
        {
            sprintf(t_data,"%02X", rdev->uuid[i]);
            t_data += 2;
        }

        CONSOLE_OUT(" %s ", pdata);
        CONSOLE_OUT("]");
        CONSOLE_OUT("\nOOB  : 0x%04X", rdev->oob);
        CONSOLE_OUT("\nURI  : 0x%08X", rdev->uri);
        CONSOLE_OUT("\n\n");
        /* Bind to the device */
        retval = MS_prov_bind(PROV_BRR_ADV, rdev, UI_PROV_DEVICE_ATTENTION_TIMEOUT, phandle);
        CONSOLE_OUT("Retval - 0x%04X\n", retval);
        /* Set provision started */
        UI_prov_started = MS_TRUE;
        break;

    case PROV_EVT_PROVISIONING_SETUP:
        CONSOLE_OUT("Recvd PROV_EVT_PROVISIONING_SETUP\n");
        CONSOLE_OUT("Status - 0x%04X\n", event_result);

        /* Decipher the data based on the role */
        if (PROV_ROLE_PROVISIONER == UI_prov_role)
        {
            /* Display the capabilities */
            rcap = (PROV_CAPABILITIES_S*)event_data;
            CONSOLE_OUT ("Remote Device Capabilities:\n");
            CONSOLE_OUT ("\tNum Elements     - %d\n", rcap->num_elements);
            CONSOLE_OUT ("\tSupp Algorithms  - 0x%04X\n", rcap->supp_algorithms);
            CONSOLE_OUT ("\tSupp PublicKey   - 0x%02X\n", rcap->supp_pubkey);
            CONSOLE_OUT ("\tSupp Static OOB  - 0x%02X\n", rcap->supp_soob);
            CONSOLE_OUT ("\tOutput OOB Size  - %d\n", rcap->ooob.size);
            CONSOLE_OUT ("\tOutput OOB Action- 0x%04X\n", rcap->ooob.action);
            CONSOLE_OUT ("\tInput OOB Size   - %d\n", rcap->ioob.size);
            CONSOLE_OUT ("\tInput OOB Action - 0x%04X\n", rcap->ioob.action);
            /* Start with default method */
            CONSOLE_OUT ("Start Provisioning with default method...\n");
            retval = MS_prov_start (phandle, &UI_prov_method);
            CONSOLE_OUT ("Retval - 0x%04X\n", retval);
        }
        else
        {
            /* Display the attention timeout */
            CONSOLE_OUT("Attention TImeout - %d\n", *((UCHAR*)event_data));
        }

        break;

    case PROV_EVT_OOB_DISPLAY:
        CONSOLE_OUT("Recvd PROV_EVT_OOB_DISPLAY\n");
        CONSOLE_OUT("Status - 0x%04X\n", event_result);
        /* Reference the Authenticatio Type information */
        oob_info = (PROV_OOB_TYPE_S*)event_data;
        CONSOLE_OUT("Authenticaion Action - 0x%02X\n", oob_info->action);
        CONSOLE_OUT("Authenticaion Size - 0x%02X\n", oob_info->size);

        /* If role is Device, the action is of Output OOB, else Input OOB */
        if (PROV_ROLE_DEVICE == UI_prov_role)
        {
            if (PROV_OOOB_ACTION_ALPHANUMERIC == oob_info->action)
            {
                authtype = 1;
            }
            else if (PROV_OOOB_ACTION_NUMERIC == oob_info->action)
            {
                authtype = 2;
            }
            else
            {
                authtype = 0;
            }
        }
        else
        {
            if (PROV_IOOB_ACTION_ALPHANUMERIC == oob_info->action)
            {
                authtype = 1;
            }
            else if (PROV_IOOB_ACTION_NUMERIC == oob_info->action)
            {
                authtype = 2;
            }
            else
            {
                authtype = 0;
            }
        }

        if (1 == authtype)
        {
            EM_str_copy (authstr, UI_DISPLAY_AUTH_STRING);
            CONSOLE_OUT("\n\n>>> AuthVal - %s <<<\n\n", authstr);
            pauth = authstr;
            authsize = EM_str_len(authstr);
        }
        else if (2 == authtype)
        {
            authnum = (UINT32)UI_DISPLAY_AUTH_NUMERIC;
            CONSOLE_OUT("\n\n>>> AuthVal - %d <<<\n\n", authnum);
            pauth = (UCHAR*)&authnum;
            authsize = sizeof(UINT32);
        }
        else
        {
            authnum = (UINT32)UI_DISPLAY_AUTH_DIGIT;
            CONSOLE_OUT("\n\n>>> AuthVal - %d <<<\n\n", authnum);
            pauth = (UCHAR*)&authnum;
            authsize = sizeof(UINT32);
        }

        /* Call to input the oob */
        CONSOLE_OUT("Setting the Authval...\n");
        retval = MS_prov_set_authval(phandle, pauth, authsize);
        CONSOLE_OUT("Retval - 0x%04X\n", retval);
        break;

    case PROV_EVT_OOB_ENTRY:
        CONSOLE_OUT("Recvd PROV_EVT_OOB_ENTRY\n");
        CONSOLE_OUT("Status - 0x%04X\n", event_result);
        /* Reference the Authenticatio Type information */
        oob_info = (PROV_OOB_TYPE_S*)event_data;
        CONSOLE_OUT("Authenticaion Action - 0x%02X\n", oob_info->action);
        CONSOLE_OUT("Authenticaion Size - 0x%02X\n", oob_info->size);
        break;

    case PROV_EVT_DEVINPUT_COMPLETE:
        CONSOLE_OUT("Recvd PROV_EVT_DEVINPUT_COMPLETE\n");
        CONSOLE_OUT("Status - 0x%04X\n", event_result);
        break;

    case PROV_EVT_PROVDATA_INFO_REQ:
        CONSOLE_OUT ("Recvd PROV_EVT_PROVDATA_INFO_REQ\n");
        CONSOLE_OUT ("Status - 0x%04X\n", event_result);
        /* Send Provisioning Data */
        CONSOLE_OUT ("Send Provisioning Data...\n");
        retval = MS_prov_data (phandle, &UI_prov_data);
        CONSOLE_OUT ("Retval - 0x%04X\n", retval);
        break;

    case PROV_EVT_PROVISIONING_COMPLETE:
        CONSOLE_OUT("Recvd PROV_EVT_PROVISIONING_COMPLETE\n");
        CONSOLE_OUT("Status - 0x%04X\n", event_result);

        if (API_SUCCESS == event_result)
        {
            if (PROV_ROLE_PROVISIONER == UI_prov_role)
            {
                /* Set provision started */
                UI_prov_started = MS_FALSE;

                if (0x0002 == UI_prov_data.uaddr)
                {
                    /* Holding a temporary structure for local prov data */
                    PROV_DATA_S temp_ps_prov_data;
                    EM_mem_copy
                    (
                        &temp_ps_prov_data,
                        &UI_prov_data,
                        sizeof(UI_prov_data)
                    );
                    /**
                        Assigning the Local Unicast Address of the Provisioner
                        to the Access Layer along with other related keys.
                    */
                    temp_ps_prov_data.uaddr = 0x0001;
                    /* Provide Provisioning Data to Access Layer */
                    MS_access_cm_set_prov_data
                    (
                        &temp_ps_prov_data
                    );
                    /**
                        NOTE:
                        Increment the appl_prov_data.uaddr for the next
                        set of device which is getting provisioned based on
                        the address and number of elements present in the last
                        provisioned device.
                    */
                }

                /* Set the Publish address for Config Client */
                UI_set_publish_address(UI_prov_data.uaddr, UI_config_client_model_handle);
                /* Get the Composition data */
                UI_config_client_get_composition_data(0x00);
            }
        }

        break;

    default:
        CONSOLE_OUT("Unknown Event - 0x%02X\n", event_type);
    }

    return API_SUCCESS;
}

void UI_register_prov(void)
{
    API_RESULT retval;
    CONSOLE_OUT("Registering with Provisioning layer...\n");
    retval = MS_prov_register(&UI_prov_capab, UI_prov_callback);
    CONSOLE_OUT("Retval - 0x%04X\n", retval);
}

void UI_setup_prov(UCHAR role, UCHAR brr)
{
    API_RESULT retval;

    if (PROV_ROLE_PROVISIONER == role)
    {
        CONSOLE_OUT("Setting up Provisioner for Provisioning ...\n");
        retval = MS_prov_setup
                 (
                     brr,
                     role,
                     NULL,
                     UI_PROV_SETUP_TIMEOUT_SECS
                 );
        UI_prov_role = PROV_ROLE_PROVISIONER;
    }

    CONSOLE_OUT("Retval - 0x%04X\n", retval);
}

void appl_mesh_sample (void)
{
    MS_ACCESS_NODE_ID node_id;
    MS_ACCESS_ELEMENT_DESC   element;
    MS_ACCESS_ELEMENT_HANDLE element_handle;
    API_RESULT retval;
    UCHAR role, brr;
    MS_CONFIG* config_ptr;
    #ifdef MS_HAVE_DYNAMIC_CONFIG
    MS_CONFIG  config;
    /* Initialize dynamic configuration */
    MS_INIT_CONFIG(config);
    config_ptr = &config;
    #else
    config_ptr = NULL;
    #endif /* MS_HAVE_DYNAMIC_CONFIG */
    /* Initialize OSAL */
    EM_os_init();
    /* Initialize Debug Module */
    EM_debug_init();
    /* Initialize Timer Module */
    EM_timer_init();
    timer_em_init();
    /* Initialize utilities */
    nvsto_init();
    /* Initialize Mesh Stack */
    MS_init(config_ptr);
    /* Register with underlying BLE stack */
    blebrr_register();
    /* Create Node */
    retval = MS_access_create_node(&node_id);
    /* Register Element */
    /**
        TBD: Define GATT Namespace Descriptions from
        https://www.bluetooth.com/specifications/assigned-numbers/gatt-namespace-descriptors

        Using 'main' (0x0106) as Location temporarily.
    */
    element.loc = 0x0106;
    retval = MS_access_register_element
             (
                 node_id,
                 &element,
                 &element_handle
             );

    if (API_SUCCESS == retval)
    {
        /* Register Configuration model client */
        retval = UI_register_config_model_client(element_handle);
    }

    if (API_SUCCESS == retval)
    {
        /* Register Generic OnOff model client */
        retval = UI_register_generic_onoff_model_client(element_handle);
    }

    /* Configure as provisioner */
    UI_register_prov();
    /**
        setup <role:[1 - Device, 2 - Provisioner]> <bearer:[1 - Adv, 2 - GATT]
    */
    role = PROV_ROLE_PROVISIONER;
    brr = PROV_BRR_ADV;
    UI_setup_prov(role, brr);
    return;
}

#endif /* (MESH_STANDALONE == 7) */

