This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

HOW to use direct advertising to connect the central successfully?

I use nrf52832 board by fast advertising to connect the central(surface 4 Tablet).Then the board go to sleep.when I push the button the board use direct advertising to connect the central again,but it dont connect. I use the peer manager to get the central address,when the BLE_ADV_EVT_PEER_ADDR_REQUEST event of direct advertising happens.

SDK 14.2  Softdevice 132 .Can you give me some suggestions about direct advertising to connect previous central successfully.

Parents
  • when first time  push button ,the board can connect the central by direct advertising.In connection state, application handles things completely, then the board and central disconnect .The board go to sleep. Next time(push button no matter how many times) the board can use direct advertising ,but cannt connect.I'm confused about this problem,How to solve this problem?

  • Hi, can you make sure that you first delete all bonds on the central and peripheral? 

  • I update my primary content of  main.c .You can see the main code following:

    1.start fast adv in the BSP_EVENT_ADVERTISING_START event of bsp_event_handler() function.

    2.central and peripheral connected, device execute pm_evt_handler(). do BLE_ADV_EVT_PEER_ADDR_REQUEST event in on_adv_evt() function.

    3.delete bond in BLE_GAP_EVT_CONNECTED event of ble_evt_handler() function.

    4.Then everything work completely.the device go to sleep. If button is pushed, it will execute

    directed_valid_peer() function to direct adv.

    /**
     * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    /** @file
     *
     * @defgroup ble_sdk_app_hids_keyboard_main main.c
     * @{
     * @ingroup ble_sdk_app_hids_keyboard
     * @brief HID Keyboard Sample Application main file.
     *
     * This file contains is the source code for a sample application using the HID, Battery and Device
     * Information Services for implementing a simple keyboard functionality.
     * Pressing Button 0 will send text 'hello' to the connected peer. On receiving output report,
     * it toggles the state of LED 2 on the mother board based on whether or not Caps Lock is on.
     * This application uses the @ref app_scheduler.
     *
     * Also it would accept pairing requests from any peer device.
     */
    
    #include <stdint.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include "nrf_assert.h"
    #include "app_error.h"
    #include "ble.h"
    #include "ble_err.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "ble_advertising.h"
    #include "ble_advdata.h"
    #include "ble_hids.h"
    #include "ble_bas.h"
    #include "ble_dis.h"
    #include "ble_conn_params.h"
    #include "sensorsim.h"
    #include "bsp_btn_ble.h"
    #include "app_scheduler.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "app_timer.h"
    #include "peer_manager.h"
    #include "fds.h"
    #include "ble_conn_state.h"
    #include "nrf_ble_gatt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "bsp_config.h"
    #include "nrf_fstorage.h"
    #include "nrf_fstorage_sd.h"
    #include "nrf_drv_saadc.h"
    #include "nrf_power.h"
    
    #define SHIFT_BUTTON_ID                     1                                          /**< Button used as 'SHIFT' Key. */
    #define BTN_ID_ADVERTISING_START            0
    
    
    #define BTN_PIN_NO_WAKEUP             24
    #define BTN_ID_WAKEUP                 0
    
    #define DEVICE_NAME                         "Nordic_Keyboard"                          /**< Name of device. Will be included in the advertising data. */
    #define MANUFACTURER_NAME                   "NordicSemiconductor"                      /**< Manufacturer. Will be passed to Device Information Service. */
    
    #define APP_BLE_OBSERVER_PRIO               3                                          /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    #define APP_BLE_CONN_CFG_TAG                1                                          /**< A tag identifying the SoftDevice BLE configuration. */
    
    #define BATTERY_LEVEL_MEAS_INTERVAL         APP_TIMER_TICKS(10000)                      /**< Battery level measurement interval (ticks). */
    #define MIN_BATTERY_LEVEL                   60                                         /**< Minimum simulated battery level. */
    #define MAX_BATTERY_LEVEL                   100                                        /**< Maximum simulated battery level. */
    #define BATTERY_LEVEL_INCREMENT             1                                          /**< Increment between each simulated battery level measurement. */
    
    #define CONNECTED_TO_SLEEP_INTERVAL         APP_TIMER_TICKS(8000) 
    #define MAIN_TO_SLEEP_INTERVAL							APP_TIMER_TICKS(8000)
    #define RELEASE_TO_SLEEP_INTERVAL           APP_TIMER_TICKS(1000) 
    #define DIRECTED_SLOW_STOP_INTERVAL         APP_TIMER_TICKS(3000)
    
    #define PNP_ID_VENDOR_ID_SOURCE             0x02                                       /**< Vendor ID Source. */
    #define PNP_ID_VENDOR_ID                    0x1915                                     /**< Vendor ID. */
    #define PNP_ID_PRODUCT_ID                   0xEEEE                                     /**< Product ID. */
    #define PNP_ID_PRODUCT_VERSION              0x0001                                     /**< Product Version. */
    
    #define APP_ADV_DIRECTED_SLOW_INTERVAL      0x0028                                        /**< Directed slow advertising interval (in units of 0.625 ms. This value corresponds to 25 ms.). */
    #define APP_ADV_DIRECTED_SLOW_TIMEOUT       30 
    #define APP_ADV_FAST_INTERVAL               0x0028                                     /**< Fast advertising interval (in units of 0.625 ms. This value corresponds to 25 ms.). */
    #define APP_ADV_SLOW_INTERVAL               0x0C80                                     /**< Slow advertising interval (in units of 0.625 ms. This value corrsponds to 2 seconds). */
    #define APP_ADV_FAST_TIMEOUT                30   /**< The duration of the fast advertising period (in seconds). */
    //#define APP_ADV_FAST_WITH_WHITELIST         30
    //#define APP_ADV_SLOW_TIMEOUT                180                                        /**< The duration of the slow advertising period (in seconds). */
    
    /*lint -emacro(524, MIN_CONN_INTERVAL) // Loss of precision */
    #define MIN_CONN_INTERVAL                   MSEC_TO_UNITS(20, UNIT_1_25_MS)           /**< Minimum connection interval (7.5 ms) */
    #define MAX_CONN_INTERVAL                   MSEC_TO_UNITS(100, UNIT_1_25_MS)            /**< Maximum connection interval (30 ms). */
    #define SLAVE_LATENCY                       0                                         /**< Slave latency. */
    #define CONN_SUP_TIMEOUT                    MSEC_TO_UNITS(4000, UNIT_10_MS)             /**< Connection supervisory timeout (430 ms). */
    
    #define FIRST_CONN_PARAMS_UPDATE_DELAY      APP_TIMER_TICKS(5000)                      /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY       APP_TIMER_TICKS(30000)                     /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT        3                                          /**< Number of attempts before giving up the connection parameter negotiation. */
    
    #define SEC_PARAM_BOND                      1                                          /**< Perform bonding. */
    #define SEC_PARAM_MITM                      0                                          /**< Man In The Middle protection not required. */
    #define SEC_PARAM_LESC                      0                                          /**< LE Secure Connections not enabled. */
    #define SEC_PARAM_KEYPRESS                  0                                          /**< Keypress notifications not enabled. */
    #define SEC_PARAM_IO_CAPABILITIES           BLE_GAP_IO_CAPS_NONE                       /**< No I/O capabilities. */
    #define SEC_PARAM_OOB                       0                                          /**< Out Of Band data not available. */
    #define SEC_PARAM_MIN_KEY_SIZE              7                                          /**< Minimum encryption key size. */
    #define SEC_PARAM_MAX_KEY_SIZE              16                                         /**< Maximum encryption key size. */
    
    #define OUTPUT_REPORT_INDEX                 0                                          /**< Index of Output Report. */
    #define OUTPUT_REPORT_MAX_LEN               1     /**< Maximum length of Output Report. */
    //#define INPUT_REPORT_MAX_LEN                1
    #define INPUT_REPORT_KEYS_INDEX             0                                          /**< Index of Input Report. */
    #define OUTPUT_REPORT_BIT_MASK_CAPS_LOCK    0x02                                       /**< CAPS LOCK bit in Output Report (based on 'LED Page (0x08)' of the Universal Serial Bus HID Usage Tables). */
    #define INPUT_REP_REF_ID                    0   /**< Id of reference to Keyboard Input Report. */
    #define INPUT_TEST_REF_ID									  0x10
    #define OUTPUT_REP_REF_ID                   0                                          /**< Id of reference to Keyboard Output Report. */
    
    #define APP_FEATURE_NOT_SUPPORTED           BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2       /**< Reply when unsupported features are requested. */
    
    #define MAX_BUFFER_ENTRIES                  5                                          /**< Number of elements that can be enqueued */
    
    #define BASE_USB_HID_SPEC_VERSION           0x0101                                     /**< Version number of base USB HID Specification implemented by this application. */
    
    #define INPUT_REPORT_KEYS_MAX_LEN           8                                          /**< Maximum length of the Input Report characteristic. */
    #define INPUT_REPORT_MAX_LEN                1
    
    #define DEAD_BEEF                           0xDEADBEEF                                 /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    #define SCHED_MAX_EVENT_DATA_SIZE           APP_TIMER_SCHED_EVENT_DATA_SIZE            /**< Maximum size of scheduler events. */
    #ifdef SVCALL_AS_NORMAL_FUNCTION
    #define SCHED_QUEUE_SIZE                    20                                         /**< Maximum number of events in the scheduler queue. More is needed in case of Serialization. */
    #else
    #define SCHED_QUEUE_SIZE                    10                                         /**< Maximum number of events in the scheduler queue. */
    #endif
    
    #define MODIFIER_KEY_POS                    0                                          /**< Position of the modifier byte in the Input Report. */
    #define SCAN_CODE_POS                       2                                          /**< The start position of the key scan code in a HID Report. */
    #define SHIFT_KEY_CODE                      0x02                                       /**< Key code indicating the press of the Shift Key. */
    
    #define MAX_KEYS_IN_ONE_REPORT              (INPUT_REPORT_KEYS_MAX_LEN - SCAN_CODE_POS)/**< Maximum number of key presses that can be sent in one Input Report. */
    
    #define BOOTLOADER_DFU_START            0xB1        /**< Magic value written to retention register when starting buttonless DFU. */
    
    #define SAMPLES_IN_BUFFER 1
    static bool connection_done = false;
    bool    is_low_battery_alert = false;
    ble_gap_addr_t last_peer_addr;
    
    void sleep_mode_enter(void);
    
    APP_TIMER_DEF(m_battery_timer_id);                                  /**< Battery timer. */
    APP_TIMER_DEF(m_sleep_timer_id);
    APP_TIMER_DEF(m_directed_slow_timer_id);
    BLE_HIDS_DEF(m_hids);                                               /**< Structure used to identify the HID service. */
    BLE_BAS_DEF(m_bas);                                                 /**< Structure used to identify the battery service. */
    NRF_BLE_GATT_DEF(m_gatt);                                           /**< GATT module instance. */
    BLE_ADVERTISING_DEF(m_advertising);                                 /**< Advertising module instance. */
    
    static bsp_event_t queued_event = BSP_EVENT_NOTHING;
    static bool              m_in_boot_mode = false;                    /**< Current protocol mode. */
    uint16_t          m_conn_handle  = BLE_CONN_HANDLE_INVALID;  /**< Handle of the current connection. */
    static pm_peer_id_t      m_peer_id;                                 /**< Device reference handle to the current bonded central. */
    static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
    
    static ble_uuid_t m_adv_uuids[] = {{BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE, BLE_UUID_TYPE_BLE}};
    extern void bsp_button_event_handler(uint8_t pin_no, uint8_t button_action);
    static void keys_send(uint8_t key_pattern_len, uint8_t * p_key_pattern);
    
    uint8_t       m_advertising_mode = BLE_ADV_MODE_IDLE;
    static bool          store_done = false;
    
    static void on_hids_evt(ble_hids_t * p_hids, ble_hids_evt_t * p_evt);
    
    /**@brief Callback function for asserts in the SoftDevice.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and does not fit a final product. You need to analyze
     *          how your product is supposed to react in case of Assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in]   line_num   Line number of the failing ASSERT call.
     * @param[in]   file_name  File name of the failing ASSERT call.
     */
    
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    /**@brief Clear bond information from persistent storage.
     */
    static void delete_bonds(void)
    {
        ret_code_t err_code;
    
        
    	  m_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID);
    		// Only Give peer address if we have a handle to the bonded peer.
        if (m_peer_id != PM_PEER_ID_INVALID)
    		{
    				err_code = pm_peer_delete(m_peer_id);
    				NRF_LOG_INFO("Erase bonds!");
    				APP_ERROR_CHECK(err_code);
    		}
    }
    
    /**@brief Function for handling Peer Manager events.
     *
     * @param[in] p_evt  Peer Manager event.
     */
    static void pm_evt_handler(pm_evt_t const * p_evt)
    {
        ret_code_t        err_code;
        switch (p_evt->evt_id)
        {
            case PM_EVT_BONDED_PEER_CONNECTED:
            {
                NRF_LOG_INFO("Connected to a previously bonded device.");
            } break;
    
            case PM_EVT_CONN_SEC_SUCCEEDED:
            {
                NRF_LOG_INFO("Connection secured: role: %d, conn_handle: 0x%x, procedure: %d.",
                             ble_conn_state_role(p_evt->conn_handle),
                             p_evt->conn_handle,
                             p_evt->params.conn_sec_succeeded.procedure);
    //						m_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID);
    //						if (m_peer_id == PM_PEER_ID_INVALID)
    //						{
    								m_peer_id = p_evt->peer_id;
    //						}
    						NRF_LOG_INFO("1m_peer_id:0x%x,queued_event:%d",m_peer_id,queued_event);
            } break;
    
            case PM_EVT_CONN_SEC_FAILED:
            {
                /* Often, when securing fails, it shouldn't be restarted, for security reasons.
                 * Other times, it can be restarted directly.
                 * Sometimes it can be restarted, but only after changing some Security Parameters.
                 * Sometimes, it cannot be restarted until the link is disconnected and reconnected.
                 * Sometimes it is impossible, to secure the link, or the peer device does not support it.
                 * How to handle this error is highly application dependent. */
            } break;
    
            case PM_EVT_CONN_SEC_CONFIG_REQ:
            {
                // Reject pairing request from an already bonded peer.
                pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false};
                pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
            } break;
    
            case PM_EVT_STORAGE_FULL:
            {
                // Run garbage collection on the flash.
    						NRF_LOG_INFO("fds_gc");
                err_code = fds_gc();
                if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES)
                {
                    // Retry.
                }
                else
                {
                    APP_ERROR_CHECK(err_code);
                }
            } break;
    
            case PM_EVT_PEER_DELETE_SUCCEEDED:
            {
    						NRF_LOG_INFO("PM_EVT_PEERS_DELETE_SUCCEEDED");
            } break;
    
            case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED:
            {
                // The local database has likely changed, send service changed indications.
                pm_local_database_has_changed();
            } break;
    
            case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
    						//APP_ERROR_CHECK(p_evt->params.peer_data_update_failed.error);
            {
                if (     p_evt->params.peer_data_update_succeeded.flash_changed
                     && (p_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_BONDING))
                {
    									NRF_LOG_INFO("new bond");
    									err_code = pm_device_identities_list_set(&m_peer_id, 1);
    									if (err_code != NRF_ERROR_NOT_SUPPORTED)
    									{
    											APP_ERROR_CHECK(err_code);
    									}
    									store_done = true;
                }
    				}
            
    				break;
    
            case PM_EVT_PEER_DATA_UPDATE_FAILED:
            {
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peer_data_update_failed.error);
            } break;
    
            case PM_EVT_PEER_DELETE_FAILED:
            {
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peer_delete_failed.error);
            } break;
    
            case PM_EVT_PEERS_DELETE_FAILED:
            {
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peers_delete_failed_evt.error);
            } break;
    
            case PM_EVT_ERROR_UNEXPECTED:
            {
                // Assert.
                APP_ERROR_CHECK(p_evt->params.error_unexpected.error);
            } break;
    
            case PM_EVT_CONN_SEC_START:
    				//case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
            case PM_EVT_PEERS_DELETE_SUCCEEDED: 
            case PM_EVT_LOCAL_DB_CACHE_APPLIED:
            case PM_EVT_SERVICE_CHANGED_IND_SENT:
            case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED:
            default:
                break;
        }
    }
    
    
    /**@brief Function for handling Service errors.
     *
     * @details A pointer to this function will be passed to each service which may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void service_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /**@brief Function for handling advertising errors.
     *
     * @param[in] nrf_error  Error code containing information about what went wrong.
     */
    static void ble_advertising_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    /**@brief Function for the Timer initialization.
     *
     * @details Initializes the timer module.
     */
    static void timers_init(void)
    {
        ret_code_t err_code;
    
        err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        // Create battery timer.
        err_code = app_timer_create(&m_battery_timer_id,
                                    APP_TIMER_MODE_REPEATED,
                                    battery_level_meas_timeout_handler);
        APP_ERROR_CHECK(err_code);
    		
    
    		err_code = app_timer_create(&m_sleep_timer_id,
    																APP_TIMER_MODE_SINGLE_SHOT,
    																sleep_timer_handler);
    		APP_ERROR_CHECK(err_code);
    		
    		err_code = app_timer_create(&m_directed_slow_timer_id,
    																APP_TIMER_MODE_SINGLE_SHOT,
    																directed_slow_timer_handler);
    		APP_ERROR_CHECK(err_code);
    	
    }
    
    
    /**@brief Function for the GAP initialization.
     *
     * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
     *          device including the device name, appearance, and the preferred connection parameters.
     */
    static void gap_params_init(void)
    {
        ret_code_t              err_code;
        ble_gap_conn_params_t   gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_HID_KEYBOARD); //PEN
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
        gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
        gap_conn_params.slave_latency     = SLAVE_LATENCY;
        gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing the GATT module.
     */
    static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing Device Information Service.
     */
    static void dis_init(void)
    {
        ret_code_t       err_code;
        ble_dis_init_t   dis_init_obj;
        ble_dis_pnp_id_t pnp_id;
    
        pnp_id.vendor_id_source = PNP_ID_VENDOR_ID_SOURCE;
        pnp_id.vendor_id        = PNP_ID_VENDOR_ID;
        pnp_id.product_id       = PNP_ID_PRODUCT_ID;
        pnp_id.product_version  = PNP_ID_PRODUCT_VERSION;
    
        memset(&dis_init_obj, 0, sizeof(dis_init_obj));
    
        ble_srv_ascii_to_utf8(&dis_init_obj.manufact_name_str, MANUFACTURER_NAME);
        dis_init_obj.p_pnp_id = &pnp_id;
    
        BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&dis_init_obj.dis_attr_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init_obj.dis_attr_md.write_perm);
    
        err_code = ble_dis_init(&dis_init_obj);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing Battery Service.
     */
    static void bas_init(void)
    {
        ret_code_t     err_code;
        ble_bas_init_t bas_init_obj;
    
        memset(&bas_init_obj, 0, sizeof(bas_init_obj));
    
        bas_init_obj.evt_handler          = NULL;
        bas_init_obj.support_notification = true;
        bas_init_obj.p_report_ref         = NULL;
        bas_init_obj.initial_batt_level   = 100;
    
        BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&bas_init_obj.battery_level_char_attr_md.cccd_write_perm);
        BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&bas_init_obj.battery_level_char_attr_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init_obj.battery_level_char_attr_md.write_perm);
    
        BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&bas_init_obj.battery_level_report_read_perm);
    
        err_code = ble_bas_init(&m_bas, &bas_init_obj);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing services that will be used by the application.
     */
    static void services_init(void)
    {
        dis_init();  //initializing Device Information Service
        bas_init();  //initializing Battery Service
        hids_init(); //initializing HID Service
    }
    
    /**@brief Function for handling a Connection Parameters error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /**@brief Function for initializing the Connection Parameters module.
     */
    static void conn_params_init(void)
    {
        ret_code_t             err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
        cp_init.disconnect_on_fail             = false;
        cp_init.evt_handler                    = NULL;
        cp_init.error_handler                  = conn_params_error_handler;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for starting timers.
     */
    static void timers_start(void)
    {
        ret_code_t err_code;
    //		bool is_wakeup_mode = false;
    		NRF_LOG_INFO("timer_start.");
        err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
        APP_ERROR_CHECK(err_code);
    
    }
    /**@brief Function for putting the chip into sleep mode.
     *
     * @note This function will not return.
     */
    void sleep_mode_enter(void)
    {
        ret_code_t err_code;
    		m_advertising_mode = BLE_ADV_MODE_IDLE;
        err_code = bsp_indication_set(BSP_INDICATE_IDLE);
        APP_ERROR_CHECK(err_code);
    
        //Prepare wakeup buttons.
        err_code = bsp_btn_ble_sleep_mode_prepare();
        APP_ERROR_CHECK(err_code);
    		//app_button_disable();
    //		err_code = bsp_wakeup_button_disable(BTN_ID_WAKEUP);
    //    APP_ERROR_CHECK(err_code);
        // Go to system-off mode (this function will not return; wakeup will cause a reset).
        err_code = sd_power_system_off();
        APP_ERROR_CHECK(err_code);
    			//nrf_power_system_off();
    }
    
    
    /**@brief Function for handling HID events.
     *
     * @details This function will be called for all HID events which are passed to the application.
     *
     * @param[in]   p_hids  HID service structure.
     * @param[in]   p_evt   Event received from the HID service.
     */
    static void on_hids_evt(ble_hids_t * p_hids, ble_hids_evt_t * p_evt)
    {
        switch (p_evt->evt_type)
        {
            case BLE_HIDS_EVT_BOOT_MODE_ENTERED:
                m_in_boot_mode = true;
                break;
    
            case BLE_HIDS_EVT_REPORT_MODE_ENTERED:
                m_in_boot_mode = false;
                break;
    
            case BLE_HIDS_EVT_REP_CHAR_WRITE:
                //on_hid_rep_char_write(p_evt);
                break;
    
            case BLE_HIDS_EVT_NOTIF_ENABLED:
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief Function for handling advertising events.
     *
     * @details This function will be called for advertising events which are passed to the application.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
    {
        ret_code_t err_code;
    	
        switch (ble_adv_evt)
        {
            case BLE_ADV_EVT_DIRECTED:
                NRF_LOG_INFO("Directed advertising.");
    						m_advertising_mode = BLE_ADV_MODE_DIRECTED;
    						app_timer_stop(m_sleep_timer_id);
                err_code = bsp_indication_set(BSP_INDICATE_IDLE);
                APP_ERROR_CHECK(err_code);
                break;
    
    				case BLE_ADV_EVT_DIRECTED_SLOW:
    						NRF_LOG_INFO("Directed slow advertising.");
    						app_timer_stop(m_sleep_timer_id);
                m_advertising_mode = BLE_ADV_MODE_DIRECTED_SLOW;
                break;
    				
            case BLE_ADV_EVT_FAST:
                NRF_LOG_INFO("Fast advertising.");
    						m_advertising_mode = BLE_ADV_MODE_FAST;
    						//bsp_board_led_off(BSP_BOARD_LED_1);
    						queued_event = BSP_EVENT_NOTHING;
    						app_timer_stop(m_sleep_timer_id);
                err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_ADV_EVT_SLOW:
                NRF_LOG_INFO("Slow advertising.");
                err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_SLOW);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_ADV_EVT_FAST_WHITELIST:
                NRF_LOG_INFO("Fast advertising with whitelist.");
                err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_ADV_EVT_SLOW_WHITELIST:
                NRF_LOG_INFO("Slow advertising with whitelist.");
                err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_ADV_EVT_IDLE:
    						//NRF_LOG_INFO("adv timeout go to sleep.");
    //						err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
    //						APP_ERROR_CHECK(err_code);
    						//sd_power_gpregret_clr(0, 0xff);
                sleep_mode_enter();
                break;
    
            case BLE_ADV_EVT_WHITELIST_REQUEST:
            {
                ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
                ble_gap_irk_t  whitelist_irks[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
                uint32_t       addr_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT;
                uint32_t       irk_cnt  = BLE_GAP_WHITELIST_ADDR_MAX_COUNT;
    
                err_code = pm_whitelist_get(whitelist_addrs, &addr_cnt,
                                            whitelist_irks,  &irk_cnt);
                APP_ERROR_CHECK(err_code);
                NRF_LOG_DEBUG("pm_whitelist_get returns %d addr in whitelist and %d irk whitelist",
                              addr_cnt, irk_cnt);
    
                // Apply the whitelist.
                err_code = ble_advertising_whitelist_reply(&m_advertising,
                                                           whitelist_addrs,
                                                           addr_cnt,
                                                           whitelist_irks,
                                                           irk_cnt);
                APP_ERROR_CHECK(err_code);
            } break; //BLE_ADV_EVT_WHITELIST_REQUEST
    
            case BLE_ADV_EVT_PEER_ADDR_REQUEST:
            {
                pm_peer_data_bonding_t peer_bonding_data;
    			m_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID);
    						// Only Give peer address if we have a handle to the bonded peer.
                if (m_peer_id != PM_PEER_ID_INVALID)
                {
                    err_code = pm_peer_data_bonding_load(m_peer_id, &peer_bonding_data);
                    if (err_code != NRF_ERROR_NOT_FOUND)
                    {
                        APP_ERROR_CHECK(err_code);
                        ble_gap_addr_t * p_peer_addr = &(peer_bonding_data.peer_ble_id.id_addr_info);
    										//NRF_LOG_INFO("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",p_peer_addr->addr[5], p_peer_addr->addr[4], p_peer_addr->addr[3], p_peer_addr->addr[2], p_peer_addr->addr[1], p_peer_addr->addr[0]);
                        err_code = ble_advertising_peer_addr_reply(&m_advertising, p_peer_addr);
    										//NRF_LOG_INFO("reply,err_code:%d",err_code);
                        APP_ERROR_CHECK(err_code);
                    }
                }
    //						else
    //						{		//last_peer_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC ;
    //								err_code = ble_advertising_peer_addr_reply(&m_advertising, &last_peer_addr);
    //								APP_ERROR_CHECK(err_code);
    //								NRF_LOG_INFO("direct.0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",last_peer_addr.addr[5], last_peer_addr.addr[4], last_peer_addr.addr[3], last_peer_addr.addr[2], last_peer_addr.addr[1], last_peer_addr.addr[0]);
    //						}
    						//NRF_LOG_INFO("direct, highest_rank:%d\n", *p_highest_rank);
            } break; //BLE_ADV_EVT_PEER_ADDR_REQUEST
    
            default:
                break;
        }
    }
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
    						app_timer_stop(m_directed_slow_timer_id);
    						app_timer_stop(m_sleep_timer_id);
    						//int i;
    //            memcpy(last_peer_addr.addr, p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr, 6);
    //						NRF_LOG_INFO("PC connected addr:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",last_peer_addr.addr[5], last_peer_addr.addr[4], last_peer_addr.addr[3], last_peer_addr.addr[2], last_peer_addr.addr[1], last_peer_addr.addr[0]);
    //						last_peer_addr.addr_type = p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr_type;
    //						NRF_LOG_INFO("PC addr_type:%d",last_peer_addr.addr_type);
    //						last_peer_addr.addr_id_peer = p_ble_evt->evt.gap_evt.params.connected.peer_addr.addr_id_peer;
    //						NRF_LOG_INFO("addr_id_peer:%d",last_peer_addr.addr_id_peer);
    
    						//bsp_event_t event = *(bsp_event_t*)p_context;
    						if (m_advertising_mode == BLE_ADV_MODE_FAST)
    						{
    								err_code = bsp_indication_set(BSP_INDICATE_IDLE);
    								APP_ERROR_CHECK(err_code);
    								app_timer_start(m_sleep_timer_id, CONNECTED_TO_SLEEP_INTERVAL, NULL);
    								delete_bonds();
    						}
    						else
    						{
    								store_done = true;
    						}
    	
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    						m_advertising_mode = BLE_ADV_MODE_IDLE;
    						NRF_LOG_INFO("Connected");
    					 
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected");
    						connection_done = false;
                // Dequeue all keys without transmission.
                //(void) buffer_dequeue(false);
    					
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                break; // BLE_GAP_EVT_DISCONNECTED
    					
    #ifndef S140
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    #endif
    
            case BLE_GATTS_EVT_HVN_TX_COMPLETE:
                // Send next key event
                //(void) buffer_dequeue(true);
                break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
                NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
                NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_EVT_USER_MEM_REQUEST:
                err_code = sd_ble_user_mem_reply(m_conn_handle, NULL);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
            {
                ble_gatts_evt_rw_authorize_request_t  req;
                ble_gatts_rw_authorize_reply_params_t auth_reply;
    
                req = p_ble_evt->evt.gatts_evt.params.authorize_request;
    
                if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID)
                {
                    if ((req.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ)     ||
                        (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) ||
                        (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL))
                    {
                        if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
                        {
                            auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
                        }
                        else
                        {
                            auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
                        }
                        auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED;
                        err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle,
                                                                   &auth_reply);
                        APP_ERROR_CHECK(err_code);
                    }
                }
            } break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST
    				
    				
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    
    /**@brief Function for the Event Scheduler initialization.
     */
    static void scheduler_init(void)
    {
        APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
    }
    
    static void directed_valid_peer(void)
    {
    		m_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID);
    		//NRF_LOG_INFO("4m_peer_id:0x%x",m_peer_id);
    		if(m_advertising_mode == BLE_ADV_MODE_IDLE)
    		{
    				if (m_peer_id != PM_PEER_ID_INVALID /*&& m_advertising_mode != BLE_ADV_MODE_FAST*/)
    				{
    						ble_advertising_start(&m_advertising, BLE_ADV_MODE_DIRECTED);
    						app_timer_start(m_directed_slow_timer_id, DIRECTED_SLOW_STOP_INTERVAL, NULL);
    				}
    		}
    }
    
    /**@brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated by button press.
     */
    static void bsp_event_handler(bsp_event_t event)
    {
        uint32_t         err_code;
    //    static uint8_t * p_key0 = m_sample_key_press_scan_str;
    //	
    //	  static uint8_t  p_key1 = 0xe3;
    //    static uint8_t   size0  = 0;
    //		static uint8_t   size1  = 0;
    		switch (event)
        {	
    //				case BSP_EVENT_SLEEP:
    //            sleep_mode_enter();
    //            break;
    
            case BSP_EVENT_DISCONNECT:
    							//NRF_LOG_INFO("BSP_EVENT_DISCONNECT.");
                err_code = sd_ble_gap_disconnect(m_conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
    						
    				case BSP_EVENT_WHITELIST_OFF:
                if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
                {
    							//	NRF_LOG_INFO("BSP_EVENT_WHITELIST_OFF.");
                    err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                    if (err_code != NRF_ERROR_INVALID_STATE)
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                }
                break;
    						
    			case	BSP_EVENT_ADVERTISING_START:
    			if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
                {
    								err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    								APP_ERROR_CHECK(err_code);
    								NRF_LOG_INFO("ADVERTISING_START");		
    						}
    						break;
    						
    						case BSP_EVENT_RESET:
    						err_code = sd_power_gpregret_clr(0, 0xff);
    						APP_ERROR_CHECK(err_code);  
    						err_code = sd_power_gpregret_set(0, BOOTLOADER_DFU_START);
    						APP_ERROR_CHECK(err_code);  
    						//nrf_power_gpregret_set(BOOTLOADER_DFU_START);
    						//NVIC_SystemReset();      
    						sd_nvic_SystemReset();  
    						NRF_LOG_INFO("Receive RESET event");
    						break;
    				default:
                break;
        }
    }
    
    
    /**@brief Function for the Peer Manager initialization.
     */
    static void peer_manager_init(void)
    {
        ble_gap_sec_params_t sec_param;
        ret_code_t           err_code;
    
        err_code = pm_init();
        APP_ERROR_CHECK(err_code);
    
        memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
    
        // Security parameters to be used for all security procedures.
        sec_param.bond           = SEC_PARAM_BOND;
        sec_param.mitm           = SEC_PARAM_MITM;
        sec_param.lesc           = SEC_PARAM_LESC;
        sec_param.keypress       = SEC_PARAM_KEYPRESS;
        sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
        sec_param.oob            = SEC_PARAM_OOB;
        sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        sec_param.kdist_own.enc  = 1;
        sec_param.kdist_own.id   = 1;
        sec_param.kdist_peer.enc = 1;
        sec_param.kdist_peer.id  = 1;
    
        err_code = pm_sec_params_set(&sec_param);
        APP_ERROR_CHECK(err_code);
    
        err_code = pm_register(pm_evt_handler);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing the Advertising functionality.
     */
    void advertising_init(void)
    {
        uint32_t               err_code;
        uint8_t                adv_flags;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
        adv_flags                            = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        init.advdata.include_appearance      = true;
        init.advdata.flags                   = adv_flags;
        init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
    
        init.config.ble_adv_whitelist_enabled      = false;
        init.config.ble_adv_directed_enabled       = true;
        init.config.ble_adv_directed_slow_enabled  = true;
        init.config.ble_adv_directed_slow_interval = APP_ADV_DIRECTED_SLOW_INTERVAL;
        init.config.ble_adv_directed_slow_timeout  = APP_ADV_DIRECTED_SLOW_TIMEOUT;
    	
        init.config.ble_adv_fast_enabled           = true;
        init.config.ble_adv_fast_interval          = APP_ADV_FAST_INTERVAL;
        init.config.ble_adv_fast_timeout           = APP_ADV_FAST_TIMEOUT;
        init.config.ble_adv_slow_enabled           = false;
        //init.config.ble_adv_slow_interval          = APP_ADV_SLOW_INTERVAL;
        //init.config.ble_adv_slow_timeout           = APP_ADV_SLOW_TIMEOUT;
    
        init.evt_handler   = on_adv_evt;
        init.error_handler = ble_advertising_error_handler;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    
    /**@brief Function for initializing buttons and leds.
     *
     * @param[out] p_erase_bonds  Will be true if the clear bonding button was pressed to wake the application up.
     */
    static void buttons_leds_init(bool * p_erase_bonds)
    {
        ret_code_t err_code;
        bsp_event_t startup_event;
    
        err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS, bsp_event_handler);
        APP_ERROR_CHECK(err_code);
    		
    	
        err_code = bsp_btn_ble_init(NULL, &startup_event);
        APP_ERROR_CHECK(err_code);
    
        *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
    }
    
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    
    /**@brief Function for the Power manager.
     */
    static void power_manage(void)
    {
        ret_code_t err_code = sd_app_evt_wait();
        APP_ERROR_CHECK(err_code);
    }
    
    int main(void)
    {
    		ret_code_t err_code;
        bool erase_bonds;
    		bool is_wakeup_mode = false;
    		ble_gap_addr_t addr;
        // Initialize.
        log_init();
        timers_init();
        buttons_leds_init(&erase_bonds);
    
    	is_wakeup_mode = bsp_board_button_state_get(BTN_ID_WAKEUP);
        ble_stack_init();
        scheduler_init();
    		services_init();
    		//saadc_init();
    	
        gap_params_init();
        gatt_init();
        advertising_init();
        
        conn_params_init();
        peer_manager_init();
        // Start execution.
        NRF_LOG_INFO("HID Keyboard example started.");
        timers_start();
    	err_code = pm_id_addr_get(&addr);
    	APP_ERROR_CHECK(err_code);
    	NRF_LOG_INFO("pm_id_addr_get local addr:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",addr.addr[5], addr.addr[4], addr.addr[3], addr.addr[2], addr.addr[1], addr.addr[0]);
    	NRF_LOG_INFO("local addr.addr_type = %d",addr.addr_type);
    		//advertising_start(false, BLE_ADV_MODE_DIRECTED);
    	app_timer_start(m_sleep_timer_id, MAIN_TO_SLEEP_INTERVAL, NULL);
    	if(is_wakeup_mode)
    	{
    			directed_valid_peer();
    			bsp_button_event_handler(BTN_PIN_NO_WAKEUP, APP_BUTTON_PUSH);
    	}
    	else
    	{
    			store_done = true;
    	}
        // Enter main loop.
    		//NRF_LOG_INFO("enter main loop.");
        for (;;)
        {
            app_sched_execute();
            if (NRF_LOG_PROCESS() == false)
            {
                power_manage();
            }
        }
    }
    
    
    /**
     * @}
     */
    

    Can you see something unusual.They cannt reconnect with direct adv.

  • Hi,Kenneth . Is it a universal phenomenon that Nrf52 board cannt reconnect surface tablet with direct adv? 

    How can I solve this question?

  • Hi, 

    I'm sorry for the late response. Mr. Kenneth was on vacation. We will continue his investigation and test on the Surface 4. 

    Do you have any other PC (PC not tablet) running Windows 10 that you can test the issue ? 

     

     

  • OK. I test peripheral with tablet(like Lenovo,CINTIQ ) not with PC. Only surface 3 or 4(win 10) has this issue that peripheral and central cant reconnect with direct adv.

    Official example  ble_app_hids_keyboard also has this issue when it connect to Surface 3 or 4.When I push butoon1 long time ,The nrf52 board disconnect the Surface .Then via direct adv, fast and slow adv with whitelist , but cant reconnect again.

    I think they are the similar question.

  • Hi Zhixiang, 

    We are seeing more reports from other customers about the issue. Could you try a test for us to test the board vs Surface 3&4 with the ble_app_hids_keyboard in SDK v11 and SDK v12 as well ? 

     

     

Reply Children
Related