
/**
 *  \file blebrr.c
 *
 *  This File contains the BLE Bearer interface for the
 *  Mindtree Mesh stack.
 */

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

/* ------------------------------- Header File Inclusion */
#include "MS_brr_api.h"
#include "MS_prov_api.h"
#include "MS_access_api.h"
#include "blebrr.h"
#include "ll.h"
#include "MS_trn_api.h"
#include "pwrmgr.h"
#include "ll_sleep.h"
#include "led_light.h"



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

/* --------------------------------------------- Global Definitions */
#define BLEBRR_MAX_ADV_FILTER_LIST_COUNT    100
#define BLEBRR_MAX_ADV_DATA_SIZE            31

#define BLEBRR_BCON_ELEMENTS                2
#define BLEBRR_ACTIVEADV_TIMEOUT            1 /* Second */
#define BLEBRR_ADV_TIMEOUT                  6 /* Millisecond */
#define BLEBRR_SCAN_TIMEOUT                 (EM_TIMEOUT_MILLISEC | 30) /* Millisecond */
#define BLEBRR_NCON_ADVTYPE_OFFSET          2
#define BLEBRR_ADVREPEAT_PRO_COUNT          2
#define BLEBRR_ADVREPEAT_NET_COUNT          2
#define BLEBRR_SCAN_ADJ_STEP                30
#define BLEBRR_SCAN_ADJ_THD_MAX             45//90
#define BLEBRR_SCAN_ADJ_THD_MIN             15//90   
#define BLEBRR_TURNOFF_RELAY_THD            32
#define BLEBRR_SKIP_BEACON_QUEUE_DEPTH      0
#define BLEBRR_BCON_READY_TIME              10

/** Bearer Queue defines */
#define BLEBRR_QTYPE_DATA                   0x00
#define BLEBRR_QTYPE_BEACON                 0x01
#define BLEBRR_NUM_QUEUES                   0x02

/** Beacon type defines */
#define BLEBRR_UPROV_ADV_BCON               0x00
#define BLEBRR_UPROV_ADV_URI                0x01
#define BLEBRR_UPROV_GATT_BCON              0x02
#define BLEBRR_UPROV_GATT_URI               0x03
#define BLEBRR_SECNET_BCON                  0x04
#define BLEBRR_NUM_BCONS                    0x05

/** GATT Mode GAP Connectable Advertising Service data offset */
#define BLEBRR_GATT_ADV_SERV_DATA_OFFSET    11
#define BLEBRR_GATT_ADV_SERV_DATALEN_OFFSET 7

/** Advertising data maximum length */
#define BLEBRR_GAP_ADVDATA_LEN              31

/** Advertising data sets MAX */
#define BLEBRR_GAP_MAX_ADVDATA_SETS         2

#ifdef BLEBRR_LP_SUPPORT
UCHAR blebrr_lp_flag = MS_FALSE;
#define BLEBRR_LP_UNPROVISION_TIMEOUT             10*60   //unprovison timeout 10min
#define BLEBRR_LP_PROVISIONED_TIMEOUT             1200   //
#define BLEBRR_LP_PROVISIONED_WKP_TIMEOUT         60      //
#define BLEBRR_LP_PROVISIONED_SLP_TIMEOUT         (BLEBRR_LP_PROVISIONED_TIMEOUT-BLEBRR_LP_PROVISIONED_WKP_TIMEOUT)
#endif




/* --------------------------------------------- Macros */
#define BLEBRR_MUTEX_INIT()                 MS_MUTEX_INIT(blebrr_mutex, BRR);
#define BLEBRR_MUTEX_INIT_VOID()            MS_MUTEX_INIT_VOID(blebrr_mutex, BRR);
#define BLEBRR_LOCK()                       MS_MUTEX_LOCK(blebrr_mutex, BRR);
#define BLEBRR_LOCK_VOID()                  MS_MUTEX_LOCK_VOID(blebrr_mutex, BRR);
#define BLEBRR_UNLOCK()                     MS_MUTEX_UNLOCK(blebrr_mutex, BRR);
#define BLEBRR_UNLOCK_VOID()                MS_MUTEX_UNLOCK_VOID(blebrr_mutex, BRR);

/* --------------------------------------------- Structures/Data Types */
/** BLEBRR Data Queue Element */
typedef struct _BLEBRR_Q_ELEMENT
{
    /* "Allocated" Data Pointer */
    UCHAR *pdata;

    /*
     *  Data Length. If data length is zero, the element is considered
     *  invalid.
     */
    UINT16 pdatalen;

    /* Type of data element */
    UCHAR type;

} BLEBRR_Q_ELEMENT;

/** BLEBRR Data Queue */
typedef struct _BLEBRR_Q
{
    /* List of Bearer Queue elements */
    BLEBRR_Q_ELEMENT element[BLEBRR_QUEUE_SIZE];

    /* Queue start index */
    UINT16 start;

    /* Queue end index */
    UINT16 end;

} BLEBRR_Q;

/** Advertising Data type */
typedef struct _BLEBRR_GAP_ADV_DATA
{
    /** Data */
    UCHAR data[BLEBRR_GAP_ADVDATA_LEN];

    /** Data Length */
    UCHAR datalen;

} BLEBRR_GAP_ADV_DATA;


/* --------------------------------------------- Global Variables */
#ifdef BLEBRR_LP_SUPPORT
EM_timer_handle blebrr_lp_thandle;

#endif
#ifdef BLEBRR_FILTER_DUPLICATE_PACKETS
DECL_STATIC UCHAR blebrr_adv_list[BLEBRR_MAX_ADV_FILTER_LIST_COUNT][BLEBRR_MAX_ADV_DATA_SIZE];
DECL_STATIC UCHAR blebrr_adv_list_inser_index = 0;
#endif /* BLEBRR_FILTER_DUPLICATE_PACKETS */

BRR_BEARER_INFO blebrr_adv;  //HZF

DECL_STATIC BRR_HANDLE blebrr_advhandle;

DECL_STATIC UCHAR blebrr_bconidx;
#ifdef  BLEBRR_LP_SUPPORT 
DECL_STATIC UCHAR blebrr_beacon;
#endif
DECL_STATIC UCHAR blebrr_update_advcount = BLEBRR_BCON_READY_TIME;
DECL_STATIC BLEBRR_Q_ELEMENT blebrr_bcon[BRR_BCON_COUNT];
DECL_STATIC BLEBRR_Q blebrr_queue;

MS_DEFINE_MUTEX_TYPE(static, blebrr_mutex)
DECL_STATIC EM_timer_handle blebrr_timer_handle;

UCHAR blebrr_state;    // HZF
//DECL_STATIC UCHAR blebrr_state;

/* Set provision started */
UCHAR blebrr_prov_started;

UCHAR blebrr_adv_restart;


UINT32 blebrr_scanTimeOut = 100;

DECL_STATIC UCHAR blebrr_datacount;

/* DECL_STATIC UCHAR blebrr_scan_type; */
DECL_STATIC UCHAR blebrr_advrepeat_count;
DECL_STATIC UCHAR blebrr_scan_interleave;

BLEBRR_GAP_ADV_DATA blebrr_gap_adv_data[BLEBRR_GAP_MAX_ADVDATA_SETS] =
{
    /* Index 0x00: Mesh Provisioning Service ADV Data */
    {
        {
            /**
             *  Flags:
             *      0x01: LE Limited Discoverable Mode
             *      0x02: LE General Discoverable Mode
             *      0x04: BR/EDR Not Supported
             *      0x08: Simultaneous LE and BR/EDR to Same Device
             *            Capable (Controller)
             *      0x10: Simultaneous LE and BR/EDR to Same Device
             *            Capable (Host)
             */
            0x02, 0x01, 0x06,

            /**
             *  Service UUID List:
             *      Mesh Provisioning Service (0x1827)
             */
            0x03, 0x03, 0x27, 0x18,

            /**
             *  Service Data List:
             *      Mesh Provisioning Service (0x1827)
             *      Mesh UUID (16 Bytes)
             *      Mesh OOB Info (2 Bytes)
             */
             0x15, 0x16,
             0x27, 0x18,
             0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
             0x00, 0x00
        },

        /** Advertising Data length */
        29
    },
    /* Index 0x01: Mesh Proxy Service ADV Data */
    {
        {
            /**
             *  Flags:
             *      0x01: LE Limited Discoverable Mode
             *      0x02: LE General Discoverable Mode
             *      0x04: BR/EDR Not Supported
             *      0x08: Simultaneous LE and BR/EDR to Same Device
             *            Capable (Controller)
             *      0x10: Simultaneous LE and BR/EDR to Same Device
             *            Capable (Host)
             */
            0x02, 0x01, 0x06,

            /**
             *  Service UUID List:
             *      Mesh Proxy Service (0x1828)
             */
            0x03, 0x03, 0x28, 0x18,

            /**
             *  Service Data List:
             *      Mesh Provisioning Service (0x1828)
             *      Type (1 Byte) "0x00 - Network ID; 0x01 - Node Identity"
             *      NetWork ID (8 Bytes)
             */
             0x0C, 0x16,
             0x28, 0x18,
             0x00,
             0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88
        },

        /** Advertising Data length */
        20
    }
};

DECL_STATIC UCHAR pl_advdata_offset;
UCHAR blebrr_sleep;


// ------------ add by HZF
uint32 blebrr_advscan_timeout_count = 0;
extern uint32_t osal_sys_tick;


/* ------------------------------- Functions */
void blebrr_handle_evt_adv_complete (UINT8 enable);
DECL_STATIC void blebrr_timer_start (UINT32 timeout);
DECL_STATIC void blebrr_timer_stop (void);


API_RESULT blebrr_queue_depth_check(void);

/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \return void
 */
void blebrr_scan_enable(void)
{
    BLEBRR_LOCK_VOID();

    if ((BLEBRR_STATE_IDLE == BLEBRR_GET_STATE()) &&
        (MS_TRUE != blebrr_sleep))
    {
        blebrr_scan_pl(MS_TRUE);

        /* Update state */
        BLEBRR_SET_STATE(BLEBRR_STATE_IN_SCAN_ENABLE);
    }

    BLEBRR_UNLOCK_VOID();
}

/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param type
 *  \param bcon
 *
 *  \return void
*/
DECL_STATIC UCHAR blebrr_get_beacon_type (UCHAR type, UCHAR bcon)
{
    return (BRR_BCON_PASSIVE == type)?
           ((BRR_BCON_TYPE_UNPROV_DEVICE == bcon)? BLEBRR_UPROV_ADV_BCON: BLEBRR_SECNET_BCON):
           ((BRR_BCON_TYPE_UNPROV_DEVICE == bcon)? BLEBRR_UPROV_GATT_BCON: BLEBRR_NUM_BCONS);
}

/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param type
 *
 *  \return void
 */
DECL_STATIC BLEBRR_Q_ELEMENT * blebrr_enqueue_alloc (void)
{
    BLEBRR_Q_ELEMENT * elt;
    UINT16 ei;

    /* Get reference to the requested Queue block members */
    elt = blebrr_queue.element;
    ei = blebrr_queue.end;

    /* Check if queue end element is free */
    if (0 != (elt + ei)->pdatalen)
    {
        /* Not free */
        elt = NULL;
    }
    else
    {
        /* Set the element to be returned */
        elt = (elt + ei);

        /* Update the data availability */
//        blebrr_datacount++;

        /* EM_debug_trace (0, "[BLEBRR] Enqueue at Q Index: %d\n", ei); */

        /* Update queue end */
        if(ei == BLEBRR_QUEUE_SIZE - 1)
            ei = 0;
        else
            ei++;
//        ei++;
//        ei &= (BLEBRR_QUEUE_SIZE - 1);
        blebrr_queue.end = ei;
    }

    return elt;
}

DECL_STATIC void blebrr_dequeue_manual (void)
{
    UINT16 ei;

    ei = blebrr_queue.end;

    /* Update the data availability */
//    blebrr_datacount--;

    /* EM_debug_trace (0, "[BLEBRR] Enqueue at Q Index: %d\n", ei); */
//    printf ("[BLEBRR] Dequeue at Q Index: __%d\n", ei);

    /* Update queue end */
    if(ei == 0)
        ei = BLEBRR_QUEUE_SIZE - 1;
    else
        ei--;
    blebrr_queue.end = ei;
}


/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param type
 *
 *  \return void
 */
DECL_STATIC BLEBRR_Q_ELEMENT * blebrr_dequeue (void)
{
    BLEBRR_Q_ELEMENT * elt;
    UINT16 si;

    /* Get reference to the requested Queue block members */
    elt = blebrr_queue.element;
    si = blebrr_queue.start;

    /* Check if queue start element is valid */
    if (0 == (elt + si)->pdatalen)
    {
        /* Not valid */
        elt = NULL;
    }
    else
    {
        /* Set the element to be returned */
        elt = (elt + si);

        /* EM_debug_trace (0, "[BLEBRR] Dequeue at Q Index: %d\n", si); */

        /* Is Adv data type in element? */
        if (BRR_BCON_COUNT == elt->type)
        {
            /* Update the data availability */
            blebrr_datacount--;
        }

        /* Update the data availability */
//        blebrr_datacount--;

        /* Update queue start */
        if(si == BLEBRR_QUEUE_SIZE - 1)
            si = 0;
        else
            si++;
//        si++;
//        si &= (BLEBRR_QUEUE_SIZE - 1);
        blebrr_queue.start = si;
    }

    return elt;
}

/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param bcon
 *
 *  \return void
 */
DECL_STATIC void blebrr_clear_bcon (UCHAR bconidx)
{
    BLEBRR_Q_ELEMENT * elt;

    /* Get reference to the beacon queue element */
    elt = &blebrr_bcon[bconidx];

    /* Clear the element and the next one for the given type of beacon */
    if (NULL != elt->pdata)
    {
        EM_free_mem (elt->pdata);
        elt->pdata = NULL;
        elt->pdatalen = 0;

        elt->type = BRR_BCON_COUNT;

        if ((BRR_BCON_TYPE_UNPROV_DEVICE == bconidx) &&
            (NULL != (elt + 1)->pdata) &&
            (0 != (elt + 1)->pdatalen))
        {
            EM_free_mem((elt + 1)->pdata);
            (elt + 1)->pdata = NULL;
            (elt + 1)->pdatalen = 0;

            (elt + 1)->type = BRR_BCON_COUNT;
        }

        blebrr_datacount--;
    }
}

UCHAR blebrr_get_queue_depth(void)
{
    UCHAR depth;

    if(blebrr_queue.end>=blebrr_queue.start)
    {
        depth = blebrr_queue.end-blebrr_queue.start;
    }
    else
    {
        depth = BLEBRR_QUEUE_SIZE-(blebrr_queue.start-blebrr_queue.end);
    }
    return depth;
}

API_RESULT blebrr_queue_depth_check(void)
{   
    API_RESULT retval =API_SUCCESS;
    uint8_t randData;
   
    UCHAR depth =blebrr_get_queue_depth();
    
    if(depth>BLEBRR_TURNOFF_RELAY_THD)
    {
        LL_Rand(&randData, 1);
        randData=randData>>1;
        if( depth > randData)
        {
            retval= API_FAILURE;
        }
        BLEBRR_LOG("[Queue DATA CNT] = %d %d %4X\n", depth,randData,retval);
    }

    return retval;
    
}

extern uint8             llState, llSecondaryState;
/**
 *  \brief
 *
 *  \par Description
 *
 * *
 * *  \param void
 *
 *  \return void
 */
DECL_STATIC API_RESULT blebrr_update_advdata(void)
{
    BLEBRR_Q_ELEMENT * elt;
    UCHAR type;
    elt = NULL;
    UCHAR   is_proxy_beacon;

    is_proxy_beacon = 1;

    //ZQY skip bcon adv when queue is not empty
//    printf("blebrr_get_queue_depth:%d\n",blebrr_get_queue_depth());  

    if(blebrr_update_advcount < BLEBRR_BCON_READY_TIME)
    {
        is_proxy_beacon = 0;
        blebrr_update_advcount++;
    }
    else
    {
        blebrr_update_advcount = 0;
    }
    if(blebrr_get_queue_depth()>BLEBRR_SKIP_BEACON_QUEUE_DEPTH)
    {
        is_proxy_beacon = 0;
    }

    if (is_proxy_beacon)
    {
        
        UCHAR bconidx;

        bconidx = blebrr_bconidx;

        do
        {
            if (0 != blebrr_bcon[blebrr_bconidx].pdatalen)
            {
                elt = &blebrr_bcon[blebrr_bconidx];
                is_proxy_beacon = 0;
            }

            if (BRR_BCON_COUNT == ++blebrr_bconidx)
            {
                blebrr_bconidx = 0;
            }
        } while ((blebrr_bconidx != bconidx) && (NULL == elt));        
    }

    if (!is_proxy_beacon && NULL == elt)
    {
        elt = blebrr_dequeue();
        is_proxy_beacon = 1;
    }

    if (NULL == elt)
    {
        return API_FAILURE;
    }

    /* Set the type */
    type = (BRR_BCON_COUNT == elt->type) ? BRR_BCON_PASSIVE : elt->type;

    /* Set the advertising data */
    blebrr_advrepeat_count = 1;
    blebrr_advertise_data_pl(type, elt->pdata, elt->pdatalen); 

    /* Is Adv data type in element? */
    if (BRR_BCON_COUNT == elt->type)
    {
#ifdef  BLEBRR_LP_SUPPORT
        blebrr_beacon = 0;
#endif
        /* Yes, Free the element */
        EM_free_mem(elt->pdata);
        elt->pdatalen = 0;
    }
#ifdef  BLEBRR_LP_SUPPORT    
    else
    {
        blebrr_beacon = 1;
    }
#endif    

    return API_SUCCESS;
}

#if 0
DECL_STATIC void blebrr_timer_restart (UINT32 timeout);
#endif


/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param type
 *  \param pdata
 *  \param datalen
 *  \param elt
 *
 *  \return void
 */
DECL_STATIC API_RESULT blebrr_send
                 (
                     UCHAR type,
                     void * pdata,
                     UINT16 datalen,
                     BLEBRR_Q_ELEMENT * elt
                 )
{
    API_RESULT retval;
    UCHAR * data;
    UINT16 packet_len;
    UCHAR offset;

    data = (UCHAR *)pdata;

    /* BLEBRR_LOG("[ADV-Tx >]: ");
    BLEBRR_dump_bytes(data, datalen); */

    /* Get the offset based on the type */
    offset = (0 != type)? BLEBRR_NCON_ADVTYPE_OFFSET: 0;

    /* Calculate the total length, including Adv Data Type headers */
    packet_len = datalen + offset;

    /* Allocate and save the data */
    elt->pdata = EM_alloc_mem(packet_len);
    if (NULL == elt->pdata)
    {
//        BLEBRR_LOG("Failed to allocate memory!\n");
        return API_FAILURE;
    }

    if (offset >= 1)
    {
        /* Add the Length and Adv type headers */
        elt->pdata[0] = (UCHAR)(datalen + (offset - 1));

        if (offset - 1)
        {
            elt->pdata[1] = type;
        }
    }

    /* Update the data and datalen */
    EM_mem_copy((elt->pdata + offset), data, datalen);
    elt->pdatalen = packet_len;

    /* Is the Adv/Scan timer running? */
    if (EM_TIMER_HANDLE_INIT_VAL != blebrr_timer_handle)
    {
        /* Yes. Do nothing */
        if (BLEBRR_STATE_SCAN_ENABLED == BLEBRR_GET_STATE())
        {
            retval = EM_stop_timer(blebrr_timer_handle);
            blebrr_timer_handle = EM_TIMER_HANDLE_INIT_VAL;
            
            if(retval == EM_SUCCESS)
                blebrr_scan_pl (MS_FALSE);          
        }
    }
    else
    {
        /*
         * No. Scan must be enabled. Disable it to trigger alternating
         * Adv/Scan Procedure
         */
        if (BLEBRR_STATE_SCAN_ENABLED == BLEBRR_GET_STATE())
        {
//            printf ("Trigger Tx...\r\n"); 
            blebrr_scan_pl (MS_FALSE);

            /* Update state */
            BLEBRR_SET_STATE(BLEBRR_STATE_IN_SCAN_DISABLE);
        }
        else if (BLEBRR_STATE_ADV_ENABLED == BLEBRR_GET_STATE())
        {
            blebrr_adv_restart = MS_TRUE;
            blebrr_timer_stop();
                
            /* Disable Advertising */
            blebrr_advertise_pl(MS_FALSE);

            /* Update state */
            BLEBRR_SET_STATE(BLEBRR_STATE_IN_ADV_DISABLE);
        }
        else if (BLEBRR_STATE_IDLE == BLEBRR_GET_STATE())
        {
            /* No, Enable Advertising with Data */
            retval = blebrr_update_advdata();

            if (API_SUCCESS != retval)
            {
                /* Enable Scan */
                blebrr_scan_pl(MS_TRUE);

                /* Update state */
                BLEBRR_SET_STATE(BLEBRR_STATE_IN_SCAN_ENABLE);
            }
            else
            {
                /* Update state */
                BLEBRR_SET_STATE(BLEBRR_STATE_IN_ADV_ENABLE);
            }
        }
    }

    return API_SUCCESS;
}


/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param handle
 *  \param pdata
 *  \param datalen
 *
 *  \return void
 */
DECL_STATIC API_RESULT blebrr_bcon_send(BRR_HANDLE * handle, void * pdata, UINT16 datalen)
{
    BRR_BEACON_INFO * info;
    BLEBRR_Q_ELEMENT * elt;
    UCHAR op, action, type, bcon, bcontype;
    UCHAR bconidx;

    /* Get the beacon information */
    info = (BRR_BEACON_INFO *)pdata;

    /* Get the Operation and Action */
    op = (info->action & 0x0F);
    action = ((info->action & 0xF0) >> 4);

    /* Get the Broadcast/Observe type and Beacon type */
    type = (info->type & 0x0F);
    bcon = ((info->type & 0xF0) >> 4);

    /* Lock */
    BLEBRR_LOCK();

    /* Check the operations */
    switch (op)
    {
        case BRR_OBSERVE:
            /* blebrr_scan_type = type; */
            break;

        case BRR_BROADCAST:
            /* Get the Beacon mapping at the BLEBRR */
            bcontype = blebrr_get_beacon_type (type, bcon);

            /* Set the bcon index */
            bconidx = bcon;

            if (BRR_ENABLE == action)
            {
                /* Update the connectable beacon packet */
                if ((BRR_BCON_ACTIVE == type) && ((NULL != info->bcon_data)))
                {
                    /* Active Beacon (advdata) Source Index */
                    UCHAR abs_index;

                    abs_index = blebrr_gatt_mode_get();

                    if (BLEBRR_GATT_PROV_MODE == abs_index)
                    {
                        /* Copy the incoming UUID and OOB info to global connectable ADV data for PB GATT */
                        /* TODO have a state to decide about provisioned and unprovisioned state */

                        EM_mem_copy
                        (
                            blebrr_gap_adv_data[abs_index].data + BLEBRR_GATT_ADV_SERV_DATA_OFFSET,
                            info->bcon_data + 1,
                            16 + 2
                        );

                        /**
                         * NOTE: It is not need to calculate assign the Service Data Length as
                         *       Service Data length is Fixed for Connectable Provisioning ADV.
                         * This data length is : 1 + 2 + 16 + 2 = 0x15 Bytes, already updated
                         * in the global data strucutre blebrr_gap_adv_data[0].
                         */

                        /* Disable Interleaving */
                        blebrr_scan_interleave = MS_FALSE;
                    }
                    /* Assuming that this Active Beacon is for GATT Proxy*/
                    else
                    {
                        /* Copy the incoming UUID and OOB info to global connectable ADV data for PB GATT */
                        /* TODO have a state to decide about provisioned and unprovisioned state */

                        abs_index = BLEBRR_GATT_PROXY_MODE;

                        /* Copy the incoming Proxy ADV data */
                        EM_mem_copy
                        (
                            blebrr_gap_adv_data[abs_index].data + BLEBRR_GATT_ADV_SERV_DATA_OFFSET,
                            info->bcon_data,
                            info->bcon_datalen
                        );

                        /* Copy the incoming Proxy ADV datalen + the BLEBRR_GATT_ADV_SERV_DATA_OFFSET */
                        blebrr_gap_adv_data[abs_index].datalen = BLEBRR_GATT_ADV_SERV_DATA_OFFSET + info->bcon_datalen;

                        /**
                         * Assign the service data length correctly for Proxy ADVs
                         * Total incoming data + 1 Byte of AD Flags + 2 Bytes of Service UUID
                         */
                        blebrr_gap_adv_data[abs_index].data[BLEBRR_GATT_ADV_SERV_DATALEN_OFFSET] =
                            info->bcon_datalen + 1 + 2;
                    }

                    /* Re-assign updated ADV data to Info Structure */
                    info->bcon_data    = blebrr_gap_adv_data[abs_index].data + pl_advdata_offset;
                    info->bcon_datalen = blebrr_gap_adv_data[abs_index].datalen - pl_advdata_offset;
                }
                else
                {
                    /* Enable Interleaving */
                    blebrr_scan_interleave = MS_TRUE;
                }

                /* Check if beacon element is free */
                if (0 != blebrr_bcon[bconidx].pdatalen)
                {
                    /* Unlock */
                    BLEBRR_UNLOCK();

                    BLEBRR_LOG("Beacon Not Free!\n");
                    return API_FAILURE;
                }

                elt = &blebrr_bcon[bconidx];

                blebrr_datacount++;

                /* Update element type */
                elt->type = type;


                /* Schedule to send */
                blebrr_send
                (
                    ((BRR_BCON_TYPE_UNPROV_DEVICE == bcon) &&
                     (BRR_BCON_ACTIVE != type))? MESH_AD_TYPE_BCON : 0,
                    info->bcon_data,
                    info->bcon_datalen,
                    elt
                );

                /* Check if URI data is present for Unprovisioned device */
                if ((BRR_BCON_TYPE_UNPROV_DEVICE == bconidx) &&
                    (NULL != info->uri) &&
                    (NULL != info->uri->payload) &&
                    (0 != info->uri->length))
                {
                    elt = &blebrr_bcon[bconidx + 1];

                    /* Update element type */
                    elt->type = bcontype + 1;

                    /* Schedule to send */
                    blebrr_send
                    (
                        0,
                        info->uri->payload,
                        info->uri->length,
                        elt
                    );
                }
            }
            else
            {
                /* Remove the beacon with type from the queue */
                blebrr_clear_bcon (bconidx);
            }
            break;

        default:
            break;
    }

    /* Unlock */
    BLEBRR_UNLOCK();

    return API_SUCCESS;
}


/**
*  \brief
*
*  \par Description
*
*
*  \param handle
*  \param pdata
*  \param datalen
*
*  \return void
*/
DECL_STATIC API_RESULT blebrr_adv_send(BRR_HANDLE * handle, UCHAR type, void * pdata, UINT16 datalen)
{
    API_RESULT retval;
    BLEBRR_Q_ELEMENT * elt;

    /* Validate handle */
    if (*handle != blebrr_advhandle)
    {
        return API_FAILURE;
    }

    if ((NULL == pdata) ||
        (0 == datalen))
    {
        return API_FAILURE;
    }

    /* Enable interleaving */
    blebrr_scan_interleave = MS_TRUE;
    blebrr_update_advcount = BLEBRR_BCON_READY_TIME;    //send beacon immediately

    /* If beacon type, pass to the handler */
    if (MESH_AD_TYPE_BCON == type)
    {
        BRR_BEACON_INFO * info;

        /* Get reference to the beacon info */
        info = (BRR_BEACON_INFO *)pdata;

        if (BRR_BCON_TYPE_SECURE_NET != (info->type >> 4))
        {
            return blebrr_bcon_send(handle, pdata, datalen);
        }
        else
        {
            /* Update the data and length reference */
            pdata = info->bcon_data;
            datalen = info->bcon_datalen;
        }
    }

    /* Lock */
    BLEBRR_LOCK();

    /* Allocate the next free element in the data queue */
    elt = blebrr_enqueue_alloc();

    /* Is any element free? */
    if (NULL == elt)
    {
        /* Unlock */
        BLEBRR_UNLOCK();

        BLEBRR_LOG("Queue Full! blebrr_advscan_timeout_count = %d, ble state = %d\r\n", blebrr_advscan_timeout_count, BLEBRR_GET_STATE());

        blebrr_scan_pl(FALSE);    // HZF
        return API_FAILURE;
    }

    /* Update element type */
    elt->type = BRR_BCON_COUNT;

    /* Schedule to send */
    retval = blebrr_send
    (
        type,
        pdata,
        datalen,
        elt
    );

    if(retval == API_FAILURE)
        blebrr_dequeue_manual();
    else
        blebrr_datacount++;
    
    /* Unlock */
    BLEBRR_UNLOCK();

    return API_SUCCESS;
}

#ifdef BLEBRR_LP_SUPPORT
DECL_STATIC void blebrr_adv_sleep(BRR_HANDLE * handle)
{
    BLEBRR_LOCK_VOID();

    /* Set bearer sleep state */
    blebrr_sleep = MS_TRUE;

    MS_prov_stop_interleave_timer();

    MS_proxy_server_stop_timer();

    if (BLEBRR_STATE_SCAN_ENABLED == BLEBRR_GET_STATE() ||
        BLEBRR_STATE_IDLE == BLEBRR_GET_STATE())
    {
        /* Disable Scan */
        blebrr_scan_pl(MS_FALSE);

        /* Update state */
        BLEBRR_SET_STATE(BLEBRR_STATE_IDLE);
    }
    else if(BLEBRR_STATE_ADV_ENABLED == BLEBRR_GET_STATE())
    {
        /* Disable Advertising */
        blebrr_advertise_pl(MS_FALSE);
    }

    /* Enter platform sleep */
    EM_enter_sleep_pl();

    BLEBRR_UNLOCK_VOID();
}

DECL_STATIC void blebrr_adv_wakeup(BRR_HANDLE * handle, UINT8 mode)
{
    BLEBRR_LOCK_VOID();

    /* Exit platform sleep */
    EM_exit_sleep_pl();

    /* Reset bearer sleep state */
    blebrr_sleep = MS_FALSE;

    if (BRR_TX & mode)
    {
        if (BLEBRR_STATE_IDLE == BLEBRR_GET_STATE())
        {
            blebrr_update_advcount = BLEBRR_BCON_READY_TIME; //send beacon immediately
            /* Enable Advertise */
            blebrr_lp_flag = MS_TRUE;
            blebrr_update_advdata();

            /* Update state */
            BLEBRR_SET_STATE(BLEBRR_STATE_IN_ADV_ENABLE);
        }
    }
    else if (BRR_RX & mode)
    {
        if (BLEBRR_STATE_IDLE == BLEBRR_GET_STATE())
        {
            /* Enable Scan */
            blebrr_scan_pl(MS_TRUE);

            /* Update state */
            BLEBRR_SET_STATE(BLEBRR_STATE_IN_SCAN_ENABLE);
        }
    }

    BLEBRR_UNLOCK_VOID();
}

API_RESULT blebrr_sleep_handler(void)
{
    API_RESULT retval;
    retval=MS_brr_sleep();
    return retval;
}

API_RESULT blebrr_wakeup_handler(void)
{
    API_RESULT retval;
    UCHAR state;

    /* Fetch PROXY feature state */
    MS_access_cm_get_features_field(&state, MS_FEATURE_PROXY);

    if(state == MS_TRUE)
    {
        retval = MS_brr_wakeup(BRR_TX|BRR_RX);
    }
    else
    {
        retval = MS_brr_wakeup(BRR_RX);
    }
    
    return retval;
}

static void enter_lp_sleep_mode (void)
{
    light_timeout_handle();
    hal_pwrmgr_unlock(MOD_USR1);        
    blebrr_sleep_handler();
    printf("sleep mode:%d\n", isSleepAllow());
}


void blebrr_lp_mode (void * args, UINT16 size)
{
    UCHAR       mode;
    UCHAR       glp_mode;
    blebrr_lp_thandle = EM_TIMER_HANDLE_INIT_VAL;

    UCHAR state;

    /* Fetch PROXY feature state */
    MS_access_cm_get_features_field(&state, MS_FEATURE_PROXY);

    MS_IGNORE_UNUSED_PARAM(size);

    mode = (*((UCHAR *)args));
    if(mode == BLEBRR_LP_OFF)
    {
        pwroff_cfg_t pwr_wkp_cfg[]={{P14,NEGEDGE}};
        hal_pwrmgr_poweroff( pwr_wkp_cfg, sizeof(pwr_wkp_cfg)/sizeof(pwr_wkp_cfg[0]) );
    }
    else if(mode == BLEBRR_LP_SLEEP)
    {
        blebrr_wakeup_handler();
        if(state != MS_TRUE)
        {
            glp_mode = BLEBRR_LP_WKP;
            EM_start_timer 
            (
                &blebrr_lp_thandle, 
                EM_TIMEOUT_MILLISEC | BLEBRR_LP_PROVISIONED_WKP_TIMEOUT, 
                blebrr_lp_mode, 
                (void *)&glp_mode, 
                sizeof(glp_mode)
            );
        }
        
    }
    else
    {
        glp_mode = BLEBRR_LP_SLEEP;
        EM_start_timer 
        (
            &blebrr_lp_thandle, 
            EM_TIMEOUT_MILLISEC | BLEBRR_LP_PROVISIONED_SLP_TIMEOUT, 
            blebrr_lp_mode, 
            (void *)&glp_mode, 
            sizeof(glp_mode)
        );
        enter_lp_sleep_mode();
    }
}


API_RESULT blebrr_lp_start(UCHAR mode)
{
    API_RESULT retval;
    UCHAR state;
    UINT32 timeout;

    /* Fetch PROXY feature state */
    MS_access_cm_get_features_field(&state, MS_FEATURE_PROXY);

    switch(mode)
    {
        case BLEBRR_LP_OFF:
        {
            timeout = BLEBRR_LP_UNPROVISION_TIMEOUT;
        }
        break;
        case BLEBRR_LP_SLEEP:
        {
            timeout = EM_TIMEOUT_MILLISEC | BLEBRR_LP_PROVISIONED_SLP_TIMEOUT;
        }
        break;
        case BLEBRR_LP_WKP:
        {
            timeout = EM_TIMEOUT_MILLISEC | BLEBRR_LP_PROVISIONED_WKP_TIMEOUT;
        }
        break;
        default:
        break;
        
    }

    retval = EM_start_timer 
            (
                &blebrr_lp_thandle, 
                timeout, 
                blebrr_lp_mode, 
                (void *)&mode, 
                sizeof(mode)
            );

    if(mode == BLEBRR_LP_SLEEP)
        enter_lp_sleep_mode();

    return retval;
    
}

void blebrr_lp_stop(void)
{
    EM_stop_timer (blebrr_lp_thandle);
    blebrr_lp_thandle = EM_TIMER_HANDLE_INIT_VAL;
}


#endif /* BLEBRR_LP_SUPPORT */

/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param args
 *  \param size
 *
 *  \return void
 */
DECL_STATIC void blebrr_advscan_timeout_handler (void * args, UINT16 size)
{
    MS_IGNORE_UNUSED_PARAM(args);
    MS_IGNORE_UNUSED_PARAM(size);

    BLEBRR_LOCK_VOID();

	blebrr_advscan_timeout_count ++;

    /* Reset Timer Handler */
    blebrr_timer_handle = EM_TIMER_HANDLE_INIT_VAL;

    /* Check the state of AdvScan procedure */
    switch (BLEBRR_GET_STATE())
    {
        case BLEBRR_STATE_ADV_ENABLED:
            /* Disable Adv */
            if (!blebrr_advertise_pl (MS_FALSE))        // HZF
                /* Update state */
                BLEBRR_SET_STATE(BLEBRR_STATE_IN_ADV_DISABLE);
            break;

        case BLEBRR_STATE_SCAN_ENABLED:
            /* Disable Scan */
            blebrr_scan_pl (MS_FALSE);

            /* Update state */
            BLEBRR_SET_STATE(BLEBRR_STATE_IN_SCAN_DISABLE);
            break;

        default:
            /* Should not reach here */
		//BLEBRR_LOG("=======blebrr_advscan_timeout_handler error: state = %2X, state will not change\r\n", BLEBRR_GET_STATE());
            break;
    }

    BLEBRR_UNLOCK_VOID();
}


/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param timeout
 *
 *  \return void
 */
DECL_STATIC void blebrr_timer_start (UINT32 timeout)
{
    EM_RESULT retval;
    blebrr_timer_handle = EM_TIMER_HANDLE_INIT_VAL;
    retval = EM_start_timer
             (
                 &blebrr_timer_handle,
                 timeout,
                 blebrr_advscan_timeout_handler,
                 NULL,
                 0
             );

    if (EM_SUCCESS != retval)
    {
        /* TODO: Log */
    }
}


DECL_STATIC void blebrr_timer_stop (void)
{    
    
    EM_stop_timer(blebrr_timer_handle);
    blebrr_timer_handle = EM_TIMER_HANDLE_INIT_VAL;
}



#if 0
/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param timeout
 *
 *  \return void
 */
DECL_STATIC void blebrr_timer_restart (UINT32 timeout)
{
    EM_RESULT retval;
//    printf("before blebrr_timer_handle:%d\n",blebrr_timer_handle);
    retval = EM_restart_timer
             (
                 blebrr_timer_handle,
                 timeout
             );
//    printf("after blebrr_timer_handle:%d\n",blebrr_timer_handle);

    if (EM_SUCCESS != retval)
    {
        /* TODO: Log */
    }
}
#endif



/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param enable
 *
 *  \return void
 */
void blebrr_pl_scan_setup (UCHAR enable)
{
    API_RESULT retval;
    BLEBRR_LOCK_VOID();

#ifdef BLEBRR_ENABLE_SCAN_TRACE
    BLEBRR_LOG ("Scan Setup - %d", enable);
#endif /* BLEBRR_ENABLE_SCAN_TRACE */

    /* Is scan enabled? */
    if (MS_TRUE == enable)
    {
        /* Yes, Update state */
        BLEBRR_SET_STATE(BLEBRR_STATE_SCAN_ENABLED);

        /* Is data available in queue to be sent? */
        if (0 != blebrr_datacount)
        {
            UCHAR depth=blebrr_get_queue_depth();

            if(depth>0)
                blebrr_scanTimeOut = BLEBRR_SCAN_ADJ_THD_MIN;
            else
                blebrr_scanTimeOut = BLEBRR_SCAN_ADJ_THD_MAX;
  
             /* Yes, Start bearer timer for Scan Timeout */
            blebrr_timer_start ((EM_TIMEOUT_MILLISEC | blebrr_scanTimeOut));
        }
    }
    else
    {
        /* No, Enable Advertising with Data */
        retval = blebrr_update_advdata();

        if (API_SUCCESS != retval)
        {
            if (MS_TRUE != blebrr_sleep)
            {
                /* Enale Scan */
                blebrr_scan_pl(MS_TRUE);

                /* Update state */
                BLEBRR_SET_STATE(BLEBRR_STATE_IN_SCAN_ENABLE);
            }
            else
            {
                /* Update state */
                BLEBRR_SET_STATE(BLEBRR_STATE_IDLE);
            }
        }
        else
        {
            /* Update state */
            BLEBRR_SET_STATE(BLEBRR_STATE_IN_ADV_ENABLE);
        }
    }

    BLEBRR_UNLOCK_VOID();
}

/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param type
 *  \param enable
 *
 *  \return void
 */
void blebrr_pl_advertise_setup (UCHAR enable)
{
    BLEBRR_LOCK_VOID();
    UCHAR adv_repeat_count;
    API_RESULT retval;

#ifdef BLEBRR_ENABLE_ADV_TRACE
    BLEBRR_LOG ("Adv Setup - %d", enable);
#endif /* BLEBRR_ENABLE_ADV_TRACE */

    /* Is advertise enabled? */
    if (MS_TRUE == enable)
    {
        /* Yes, Update state */
        BLEBRR_SET_STATE(BLEBRR_STATE_ADV_ENABLED);

        /* Start bearer timer for Adv Timeout */
        if (blebrr_scan_interleave == MS_TRUE)
        {
            blebrr_timer_start (EM_TIMEOUT_MILLISEC | BLEBRR_ADV_TIMEOUT);
        }
        
    }
    else
    {
        if (MS_TRUE == blebrr_sleep)
        {
            /* Update state */
            blebrr_adv_restart = MS_FALSE;
            BLEBRR_SET_STATE(BLEBRR_STATE_IDLE);
            return;
        }
        
        if(blebrr_adv_restart == MS_TRUE)
        {
            blebrr_adv_restart = MS_FALSE;
            blebrr_update_advcount = BLEBRR_BCON_READY_TIME;
            retval = blebrr_update_advdata();

            if (API_SUCCESS != retval)
            {
                /* Enale Scan */
                blebrr_scan_pl(MS_TRUE);

                /* Update state */
                BLEBRR_SET_STATE(BLEBRR_STATE_IN_SCAN_ENABLE);
            }
            else
            {
                /* Update state */
                BLEBRR_SET_STATE(BLEBRR_STATE_IN_ADV_ENABLE);
            }
            
        }
        else
        {       
            adv_repeat_count = (blebrr_prov_started == MS_TRUE)?BLEBRR_ADVREPEAT_PRO_COUNT:BLEBRR_ADVREPEAT_NET_COUNT;
            if (/*blebrr_beacon && */(adv_repeat_count > blebrr_advrepeat_count))
            {
                blebrr_advrepeat_count++;
                blebrr_advertise_pl(MS_TRUE);

                /* Update state */
                BLEBRR_SET_STATE(BLEBRR_STATE_IN_ADV_ENABLE);
            }
            else
            {
        	    /* No, Enable Scanning */
                blebrr_scan_pl(MS_TRUE);

#ifdef  BLEBRR_LP_SUPPORT 
                
                UCHAR glp_mode;
                if((blebrr_lp_flag == MS_TRUE) &&(blebrr_beacon == 1))
                {
                    blebrr_beacon =0;
                    blebrr_lp_flag = MS_FALSE;
                    glp_mode = BLEBRR_LP_WKP;
                    blebrr_lp_start(glp_mode);
                }
#endif

                /* Update state */
                BLEBRR_SET_STATE(BLEBRR_STATE_IN_SCAN_ENABLE);
            }
        }
        
    }

    BLEBRR_UNLOCK_VOID();
}

/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param None
 *
 *  \return void
 */
void blebrr_pl_advertise_end (void)
{
    BLEBRR_LOCK_VOID();

    BLEBRR_SET_STATE(BLEBRR_STATE_IDLE);
    blebrr_advrepeat_count = 0;

    BLEBRR_UNLOCK_VOID();
}

#ifdef BLEBRR_FILTER_DUPLICATE_PACKETS
/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param p_adv_data_with_bd_addr
 *
 *  \return void
 */
DECL_STATIC API_RESULT blebrr_adv_duplicate_filter(/* IN */ UCHAR * p_adv_data_with_bd_addr)
{
    UCHAR length, index;

    /* Get the ADV data packet length */
    length = p_adv_data_with_bd_addr[1 + BT_BD_ADDR_SIZE];

    for (index = 0; index < BLEBRR_MAX_ADV_FILTER_LIST_COUNT; index++)
    {
        /* First Match BD Addr */
        if (0 == EM_mem_cmp
                 (
                     &blebrr_adv_list[index][0],
                     p_adv_data_with_bd_addr,
                     1 + BT_BD_ADDR_SIZE
                 ))
        {
            /* Check Data Length */
            if (blebrr_adv_list[index][1 + BT_BD_ADDR_SIZE] == p_adv_data_with_bd_addr[1 + BT_BD_ADDR_SIZE])
            {
                if (0 == EM_mem_cmp
                         (
                             &blebrr_adv_list[index][1 + BT_BD_ADDR_SIZE + 1],
                             &p_adv_data_with_bd_addr[1 + BT_BD_ADDR_SIZE + 1],
                             length
                         ))
                {
                    return API_SUCCESS;
                }
            }

            /* Update Adv data */
            EM_mem_copy
            (
                &blebrr_adv_list[index][1 + BT_BD_ADDR_SIZE],
                &p_adv_data_with_bd_addr[1 + BT_BD_ADDR_SIZE],
                length + 1
            );

            return API_FAILURE;
        }
    }

    /* Find out the suitable location to save the most recent ADV packet */
    /* New peer device. Add */
    EM_mem_copy
    (
        &blebrr_adv_list[blebrr_adv_list_inser_index][0],
        p_adv_data_with_bd_addr,
        length + 1 + BT_BD_ADDR_SIZE + 1
    );

    /* Increment and Wrap (if required) */
    blebrr_adv_list_inser_index++;

    if (BLEBRR_MAX_ADV_FILTER_LIST_COUNT <= blebrr_adv_list_inser_index)
    {
        blebrr_adv_list_inser_index = 0;
    }

    return API_FAILURE;
}
#endif /* BLEBRR_FILTER_DUPLICATE_PACKETS */


extern uint8  osal_memory_audit(void *ptr);
/**
 *  \brief
 *
 *  \par Description
 *
 *
 *  \param type
 *  \param pdata
 *  \param pdatalen
 *  \param rssi
 *
 *  \return void
 */
void blebrr_pl_recv_advpacket (UCHAR type, UCHAR * pdata, UINT16 pdatalen, UCHAR rssi)
{
    MS_BUFFER info;

#ifdef BLEBRR_FILTER_DUPLICATE_PACKETS
    /* Duplicate Filtering */
    retval = blebrr_adv_duplicate_filter(p_adv_data_with_bd_addr);

    /* If found the ADV packet as duplicate, drop the ADV packet */
    if (API_SUCCESS == retval)
    {
        return API_FAILURE;
    }
#endif /* BLEBRR_FILTER_DUPLICATE_PACKETS */

    /* Handle only if Non-Connectable (Passive) Advertising */
    if (BRR_BCON_PASSIVE != type)
    {
        return;
    }

    /* Pack the RSSI as metadata */
    info.payload = &rssi;
    info.length = sizeof(UCHAR);

    /* Deliver the packet to the bearer */
    if (NULL != blebrr_adv.bearer_recv)
    {
        /* BLEBRR_LOG("[ADV-Rx <]: ");
        BLEBRR_dump_bytes(pdata, pdatalen); */

        blebrr_adv.bearer_recv(&blebrr_advhandle, pdata, pdatalen, &info);
    }
    else
    {
        BLEBRR_LOG("BEARER RECV Callback Currently NULL !!\n");
    }
}

/**
 *  \brief
 *
 *  \par Description
 *
 * *
 * *  \param void
 *
 *  \return void
 */
void blebrr_register(void)
{
    /* Initialize locals */
    BLEBRR_MUTEX_INIT_VOID();

    /* Initialize Timer Handler */
    blebrr_timer_handle = EM_TIMER_HANDLE_INIT_VAL;

    /* Initialize the transport */
    blebrr_init_pl();

    /* Get the platform Advdata initial offset if any */
    pl_advdata_offset = blebrr_get_advdata_offset_pl ();

    /* Reset the bearer sleep */
    blebrr_sleep = MS_FALSE;

    /* Add the Adv Bearer */
    blebrr_adv.bearer_send = blebrr_adv_send;

#ifdef BLEBRR_LP_SUPPORT
    blebrr_adv.bearer_sleep = blebrr_adv_sleep;
    blebrr_adv.bearer_wakeup = blebrr_adv_wakeup;
    blebrr_lp_thandle = EM_TIMER_HANDLE_INIT_VAL;
#endif /* BLEBRR_LP_SUPPORT */

    MS_brr_add_bearer(BRR_TYPE_ADV, &blebrr_adv, &blebrr_advhandle);

    /* Enable all Mesh related Module Debugging */
    EM_enable_module_debug_flag
    (
        MS_MODULE_ID_APP    |
        MS_MODULE_ID_ACCESS |
        MS_MODULE_ID_TRN    |
        MS_MODULE_ID_LTRN   |
        MS_MODULE_ID_NET    |
        MS_MODULE_ID_COMMON |
        MS_MODULE_ID_BRR    |
        MS_MODULE_ID_STBX   |
        MS_MODULE_ID_PROV
    );

    /* Set Debug Level Trace as default. Enable Information only if required */
    EM_set_debug_level(EM_DEBUG_LEVEL_TRC);

    /* Allow the tasks to start and be ready */
    EM_sleep (1);

#if 0
    /* Start Observing */
    BLEBRR_LOG ("Start Observing...\n");
    blebrr_scan_pl (MS_TRUE);

    /* Update state */
    BLEBRR_SET_STATE(BLEBRR_STATE_IN_SCAN_ENABLE);
#else /* 0 */
    BLEBRR_SET_STATE(BLEBRR_STATE_IDLE);
#endif /* 0 */
}

