changed low freq. clock source to IRC

Dependencies:   BLE_API mbed nRF51822_IRC

Fork of BLE_ANCS_SDAPI by devsar devsar

Revision:
0:1f985a7c0a8b
Child:
1:f0edc06f2d29
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jun 03 04:25:33 2014 +0000
@@ -0,0 +1,773 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "mbed.h"
+#include "nRF51822n.h"
+
+#include "nordic_common.h"
+//#include "nrf.h"
+#include "app_error.h"
+#include "ble_hci.h"
+#include "ble_gap.h"
+#include "ble_advdata.h"
+#include "ble_error_log.h"
+#include "nrf_gpio.h"
+#include "ble_srv_common.h"
+#include "ble_conn_params.h"
+#include "nrf51_bitfields.h"
+#include "ble_bondmngr.h"
+#include "app_timer.h"
+#include "ble_radio_notification.h"
+#include "ble_flash.h"
+#include "ble_debug_assert_handler.h"
+#include "pstorage.h"
+#include "nrf_soc.h"
+#include "softdevice_handler.h"
+
+#include "debug.h"
+
+
+#define DEVICE_NAME                     "ANCC"                                               /**< Name of device. Will be included in the advertising data. */
+#define APP_ADV_INTERVAL                40                                                   /**< The advertising interval (in units of 0.625 ms. This value corresponds to 25 ms). */
+#define APP_ADV_INTERVAL_SLOW           3200                                                 /**< Slow advertising interval (in units of 0.625 ms. This value corresponds to 2 seconds). */
+#define APP_ADV_TIMEOUT_IN_SECONDS      180                                                  /**< The advertising timeout in units of seconds. */
+#define ADV_INTERVAL_FAST_PERIOD        30                                                   /**< The duration of the fast advertising period (in seconds). */
+
+#define APP_TIMER_PRESCALER             0                                                    /**< Value of the RTC1 PRESCALER register. */
+#define APP_TIMER_MAX_TIMERS            2                                                    /**< Maximum number of simultaneously created timers. */
+#define APP_TIMER_OP_QUEUE_SIZE         4                                                    /**< Size of timer operation queues. */
+
+#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(500, UNIT_1_25_MS)                     /**< Minimum acceptable connection interval (0.5 seconds). */
+#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(1000, UNIT_1_25_MS)                    /**< Maximum acceptable connection interval (1 second). */
+#define SLAVE_LATENCY                   0                                                    /**< Slave latency. */
+#define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)                      /**< Connection supervisory timeout (4 seconds). */
+
+#define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(20 * 1000, APP_TIMER_PRESCALER)      /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (20 seconds). */
+#define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(5 * 1000, APP_TIMER_PRESCALER)       /**< Time between each call to sd_ble_gap_conn_param_update after the first (5 seconds). */
+#define MAX_CONN_PARAMS_UPDATE_COUNT    3                                                    /**< Number of attempts before giving up the connection parameter negotiation. */
+
+
+#define SEC_PARAM_TIMEOUT               30                                                   /**< Timeout for Pairing Request or Security Request (in seconds). */
+#define SEC_PARAM_BOND                  0                                                    /**< Perform bonding. */
+#define SEC_PARAM_MITM                  0                                                    /**< Man In The Middle protection not required. */
+#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 BLE_UUID_APPLE_NOTIFICATION_CENTER_SERVICE  0xf431                               /*<< ANCS service UUID. */
+#define BLE_UUID_ANCS_CONTROL_POINT_CHAR            0xd8f3                               /*<< Control point UUID. */
+#define BLE_UUID_ANCS_NOTIFICATION_SOURCE_CHAR      0x120d                               /*<< Notification source UUID. */
+#define BLE_UUID_ANCS_DATA_SOURCE_CHAR              0xc6e9                               /*<< Data source UUID. */
+
+#define BLE_CCCD_NOTIFY_BIT_MASK         0x0001                                            /**< Enable Notification bit. */
+
+
+typedef enum
+{
+    BLE_NO_ADVERTISING,                                                                      /**< No advertising running. */
+    BLE_SLOW_ADVERTISING,                                                                    /**< Slow advertising running. */
+    BLE_FAST_ADVERTISING                                                                     /**< Fast advertising running. */
+} ble_advertising_mode_t;
+
+typedef enum
+{
+    STATE_UNINITIALIZED,                    // Program start.
+    STATE_ADVERTISING,                      // Advertising. See Settings>Bluetooth on iPhone then connect to "ANCC"
+    STATE_CONNECTED,                        // iPhone connected to us.
+    STATE_DISCOVERY_SERVICE,                // Searching for ANCS Service.
+    STATE_DISCOVERY_CHARACTERISTICS,        // Searching for ANCS Characteristics.
+    STATE_PAIRING,                          // Got all we need. Now pair before subscribe. Should see pairing dialog on iPhone
+    STATE_SUBSCRIBING,                      // Subscribe to CCC, for notification.
+    STATE_LISTENING,                        // Listening...
+    STATE_NOTIFIED,                         // Got notification, now retrieve other info and print log out. back to listening.
+    STATE_DISCONNECTED,                     // Disconnected?
+    STATE_ERROR
+} state_t;
+
+
+
+DigitalOut led_adv(LED1);
+DigitalOut led_conn(LED2);
+
+Serial     pc(USBTX, USBRX);
+
+const ble_uuid128_t ble_ancs_base_uuid128 =
+{
+   {
+    // 7905F431-B5CE-4E99-A40F-4B1E122D00D0
+    0xd0, 0x00, 0x2d, 0x12, 0x1e, 0x4b, 0x0f, 0xa4,
+    0x99, 0x4e, 0xce, 0xb5, 0x31, 0xf4, 0x05, 0x79
+   }
+};
+
+
+const ble_uuid128_t ble_ancs_cp_base_uuid128 =
+{
+   {
+    // 69d1d8f3-45e1-49a8-9821-9bbdfdaad9d9
+    0xd9, 0xd9, 0xaa, 0xfd, 0xbd, 0x9b, 0x21, 0x98,
+    0xa8, 0x49, 0xe1, 0x45, 0xf3, 0xd8, 0xd1, 0x69
+
+   }
+};
+
+const ble_uuid128_t ble_ancs_ns_base_uuid128 =
+{
+   {
+    // 9FBF120D-6301-42D9-8C58-25E699A21DBD
+    0xbd, 0x1d, 0xa2, 0x99, 0xe6, 0x25, 0x58, 0x8c,
+    0xd9, 0x42, 0x01, 0x63, 0x0d, 0x12, 0xbf, 0x9f
+
+   }
+};
+
+const ble_uuid128_t ble_ancs_ds_base_uuid128 =
+{
+   {
+    // 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB
+    0xfb, 0x7b, 0x7c, 0xce, 0x6a, 0xb3, 0x44, 0xbe,
+    0xb5, 0x4b, 0xd6, 0x24, 0xe9, 0xc6, 0xea, 0x22
+
+   }
+};
+
+static state_t                          m_state = STATE_UNINITIALIZED;
+
+static ble_gap_adv_params_t             m_adv_params;                                        /**< Parameters to be passed to the stack when starting advertising. */
+static ble_advertising_mode_t           m_advertising_mode;                                  /**< Variable to keep track of when we are advertising. */
+
+static ble_gap_sec_params_t             m_sec_params;                                        /**< Security requirements for this application. */
+
+// ANCS Characteristic...
+static uint16_t m_notification_source_handle = 0;
+static uint16_t m_notification_source_handle_cccd = 0;
+static uint16_t m_control_point_handle = 0;
+static uint16_t m_data_source_handle = 0;
+static uint16_t m_data_source_handle_cccd = 0;
+
+static void err_check(uint32_t error_code, char *method)
+{
+    if(error_code != NRF_SUCCESS) {
+        pc.printf("ERROR: %d (%s) on %s\r\n", error_code, error2string(error_code), method);
+//    } else {
+//        pc.printf("SUCCESS: %s\r\n", method);
+    }
+    APP_ERROR_CHECK(error_code);
+}
+
+
+static void advertising_start(void)
+{
+    uint32_t err_code;
+
+    if (m_advertising_mode == BLE_NO_ADVERTISING)
+    {
+        m_advertising_mode = BLE_FAST_ADVERTISING;
+    }
+    else
+    {
+        m_advertising_mode = BLE_SLOW_ADVERTISING;
+    }
+
+    memset(&m_adv_params, 0, sizeof(m_adv_params));
+    
+    m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
+    m_adv_params.p_peer_addr = NULL;                           // Undirected advertisement.
+    m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
+
+    if (m_advertising_mode == BLE_FAST_ADVERTISING)
+    {
+        m_adv_params.interval = APP_ADV_INTERVAL;
+        m_adv_params.timeout  = ADV_INTERVAL_FAST_PERIOD;
+    }
+    else
+    {
+        m_adv_params.interval = APP_ADV_INTERVAL_SLOW;
+        m_adv_params.timeout  = APP_ADV_TIMEOUT_IN_SECONDS;
+    }
+
+    err_code = sd_ble_gap_adv_start(&m_adv_params);
+    err_check(err_code, "sd_ble_gap_adv_start");
+
+    led_adv = 1;
+    m_state = STATE_ADVERTISING;
+}
+
+
+
+
+static void ble_event_handler(ble_evt_t * p_ble_evt)
+{
+    uint32_t        err_code = NRF_SUCCESS;
+    static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;
+    ble_uuid_t ancs_uuid;
+    static ble_gattc_handle_range_t handle_range;
+
+    pc.printf("Event: %s\r\n", event2string(p_ble_evt));
+//    ble_bondmngr_on_ble_evt(p_ble_evt);
+//    ble_conn_params_on_ble_evt(p_ble_evt);
+    
+    switch (p_ble_evt->header.evt_id)
+    {
+        case BLE_GAP_EVT_CONNECTED:
+        {
+            m_state = STATE_CONNECTED;
+
+            m_advertising_mode = BLE_NO_ADVERTISING;
+            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
+            led_conn = 1;
+            
+            m_state = STATE_DISCOVERY_SERVICE;
+
+            BLE_UUID_BLE_ASSIGN(ancs_uuid, BLE_UUID_APPLE_NOTIFICATION_CENTER_SERVICE);
+            ancs_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
+
+            err_code = sd_ble_gattc_primary_services_discover(m_conn_handle, 0x0001, &ancs_uuid);
+            err_check(err_code, "sd_ble_gattc_primary_services_discover");            
+            
+
+            break;
+        }        
+        case BLE_GAP_EVT_AUTH_STATUS:
+        {                
+            m_state = STATE_SUBSCRIBING;
+
+            // Subscribe to NS
+            uint16_t       cccd_val = true ? BLE_CCCD_NOTIFY_BIT_MASK : 0;
+            static ble_gattc_write_params_t m_write_params;
+            uint8_t gattc_value[2];
+                     
+            gattc_value[0] = LSB(cccd_val);
+            gattc_value[1] = MSB(cccd_val);
+
+            m_write_params.handle = m_notification_source_handle_cccd;
+            m_write_params.len  = 2;
+            m_write_params.p_value = &gattc_value[0];
+            m_write_params.offset = 0;
+            m_write_params.write_op = BLE_GATT_OP_WRITE_REQ;
+                        
+
+            err_code = sd_ble_gattc_write(m_conn_handle, &m_write_params);
+            err_check(err_code, "sd_ble_gattc_write");
+
+            break;
+        }   
+        case BLE_GAP_EVT_DISCONNECTED:
+        {
+            m_conn_handle = BLE_CONN_HANDLE_INVALID;
+
+            advertising_start();
+            led_conn = 0;
+            break;
+        }    
+        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
+        {
+            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, 
+                                                   BLE_GAP_SEC_STATUS_SUCCESS, 
+                                                   &m_sec_params);
+            err_check(err_code, "sd_ble_gap_sec_params_reply");
+            break;
+        }
+        case BLE_GAP_EVT_TIMEOUT:
+        {
+            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
+            { 
+                if (m_advertising_mode == BLE_FAST_ADVERTISING)
+                {
+                    advertising_start();
+                }
+                else
+                {
+                    err_code = sd_power_system_off();
+                }
+            }
+            break;
+        }   
+        case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
+        {
+             if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
+                // Error.
+                pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP");
+            } else {
+                if (p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.count > 0) {
+                    const ble_gattc_service_t * p_service;
+
+                    p_service = &(p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[0]);
+
+                    pc.printf("Found ANCS service, start handle: %d, end handle: %d\r\n", 
+                        p_service->handle_range.start_handle, p_service->handle_range.end_handle);
+
+                    handle_range.start_handle = p_service->handle_range.start_handle;
+                    handle_range.end_handle   = p_service->handle_range.end_handle;
+
+                    err_code = sd_ble_gattc_characteristics_discover(m_conn_handle, &handle_range);
+                    err_check(err_code, "sd_ble_gattc_characteristics_discover");
+                    
+                    m_state = STATE_DISCOVERY_CHARACTERISTICS;
+
+                } else {
+                    pc.printf("Error: discovery failure, no ANCS\r\n");
+                }
+            }
+
+            break;
+        }
+        case BLE_GATTC_EVT_CHAR_DISC_RSP:
+        {    
+            // End of characteristics searching...no more attribute or no more handle.
+            // We got error as response, but this is normal for gatt attribute searching.
+            if (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND ||
+                p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_INVALID_HANDLE) {
+                
+                if(m_notification_source_handle == 0) {
+                    pc.printf("Error: NS not found.\r\n");
+                } else if(m_control_point_handle == 0) {
+                    pc.printf("Error: CP not found.\r\n");
+                } else if(m_data_source_handle == 0) {
+                    pc.printf("Error: DS not found.\r\n");
+                } 
+                // OK, we got all char handles. Next, find CCC.
+                else {
+                    // Start with NS CCC
+                    handle_range.start_handle = m_notification_source_handle + 1;
+                    handle_range.end_handle = m_notification_source_handle + 1;
+                    
+                    err_code = sd_ble_gattc_descriptors_discover(m_conn_handle, &handle_range);
+                    err_check(err_code, "sd_ble_gattc_descriptors_discover");
+                }        
+            
+            } else if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
+                pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_CHAR_DISC_RSP");
+            } else {
+                uint32_t                 i;
+                const ble_gattc_char_t * p_char_resp = NULL;
+
+                // Iterate trough the characteristics and find the correct one.
+                 for (i = 0; i < p_ble_evt->evt.gattc_evt.params.char_disc_rsp.count; i++) {
+                    p_char_resp = &(p_ble_evt->evt.gattc_evt.params.char_disc_rsp.chars[i]);
+                    switch (p_char_resp->uuid.uuid) {
+                        case BLE_UUID_ANCS_CONTROL_POINT_CHAR:
+                            pc.printf("Found char: Control Point");
+                            m_control_point_handle = p_char_resp->handle_value;
+                        break;
+
+                        case BLE_UUID_ANCS_NOTIFICATION_SOURCE_CHAR:
+                            pc.printf("Found char: Notification Source");
+                            m_notification_source_handle = p_char_resp->handle_value;
+                        break;
+
+                        case BLE_UUID_ANCS_DATA_SOURCE_CHAR:
+                            pc.printf("Found char: Data Source");
+                            m_data_source_handle = p_char_resp->handle_value;
+                        break;
+
+                        default:
+                        break;
+                    }
+                }
+                
+                if(p_char_resp!=NULL) {
+
+                    handle_range.start_handle = p_char_resp->handle_value + 1;
+
+                    err_code = sd_ble_gattc_characteristics_discover(m_conn_handle, &handle_range);
+                    err_check(err_code, "sd_ble_gattc_characteristics_discover");
+                    
+                } else {
+                    err_code = sd_ble_gattc_characteristics_discover(m_conn_handle, &handle_range);
+                    err_check(err_code, "sd_ble_gattc_characteristics_discover");
+                }
+        
+            }
+        
+            break;
+        }
+        case BLE_GATTC_EVT_DESC_DISC_RSP:
+        {
+            if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
+                pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_DESC_DISC_RSP");        
+            } else {
+                if (p_ble_evt->evt.gattc_evt.params.desc_disc_rsp.count > 0) {
+                    const ble_gattc_desc_t * p_desc_resp = &(p_ble_evt->evt.gattc_evt.params.desc_disc_rsp.descs[0]);
+                    if (p_desc_resp->uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG) {
+                        if(p_desc_resp->handle == m_notification_source_handle + 1) {
+                                                                          
+                            m_notification_source_handle_cccd = p_desc_resp->handle;
+                            pc.printf("Found NS CCC\r\n");
+                            
+                            // Next, find CCC for data source.
+                            handle_range.start_handle = m_data_source_handle + 1;
+                            handle_range.end_handle = m_data_source_handle + 1;
+                    
+                            err_code = sd_ble_gattc_descriptors_discover(m_conn_handle, &handle_range);
+                            err_check(err_code, "sd_ble_gattc_descriptors_discover");
+
+                        } else if(p_desc_resp->handle == m_data_source_handle + 1) {
+                            
+                            m_data_source_handle_cccd = p_desc_resp->handle;
+                            pc.printf("Found DS CCC\r\n");
+                                                                  
+                            // Got all we need, now before subscribing we'll do pairing.
+                            // request encryption...., we are in peripheral role.
+                            
+                            m_state = STATE_PAIRING;
+                            
+                            err_code = sd_ble_gap_authenticate(m_conn_handle, &m_sec_params);
+                            err_check(err_code, "sd_ble_gap_authenticate");
+                        }
+                    }
+                }
+            }
+            break;
+        }
+        case BLE_GATTC_EVT_WRITE_RSP:
+        {
+            if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
+                pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_WRITE_RSP"); 
+
+                if(p_ble_evt->evt.gattc_evt.params.write_rsp.handle == m_control_point_handle) {
+                    m_state = STATE_LISTENING;
+                }
+            } else {
+                if(p_ble_evt->evt.gattc_evt.params.write_rsp.handle == m_notification_source_handle_cccd) {
+                    pc.printf("NS subscribe success.\r\n");
+
+                    // Next, subscribe to DS.
+                    uint16_t       cccd_val = true ? BLE_CCCD_NOTIFY_BIT_MASK : 0;
+                    static ble_gattc_write_params_t m_write_params;
+                    uint8_t gattc_value[2];
+                     
+                    gattc_value[0] = LSB(cccd_val);
+                    gattc_value[1] = MSB(cccd_val);
+
+                    m_write_params.handle = m_data_source_handle_cccd;
+                    m_write_params.len  = 2;
+                    m_write_params.p_value = &gattc_value[0];
+                    m_write_params.offset = 0;
+                    m_write_params.write_op = BLE_GATT_OP_WRITE_REQ;
+                        
+                    err_code = sd_ble_gattc_write(m_conn_handle, &m_write_params);
+                    err_check(err_code, "sd_ble_gattc_write");
+                }
+                
+                if(p_ble_evt->evt.gattc_evt.params.write_rsp.handle == m_data_source_handle_cccd) {
+                    pc.printf("DS subscribe success.\r\n");
+                    
+                    // Now, we just waiting for NS notification.
+                    m_state = STATE_LISTENING;
+                }
+                
+                if(p_ble_evt->evt.gattc_evt.params.write_rsp.handle == m_control_point_handle) {
+                    pc.printf("CP write success.\r\n");
+                    // We'll receive data from DS notification
+                }
+
+            }
+        
+            break;
+        }
+        case BLE_GATTC_EVT_HVX:
+        {
+            if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
+                pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_HVX");        
+            } else {
+
+                // Got notification...
+                if(p_ble_evt->evt.gattc_evt.params.hvx.handle == m_notification_source_handle) {
+                    ble_gattc_evt_hvx_t *p_hvx = &p_ble_evt->evt.gattc_evt.params.hvx;
+                    if(p_hvx->len == 8) {
+                        pc.printf("Event ID: %x (%s)\r\n", p_hvx->data[0], eventid2string(p_hvx->data[0]));
+                        pc.printf("Event Flags: %x (%s)\r\n", p_hvx->data[1], eventflags2string(p_hvx->data[1]));
+                        pc.printf("Category ID: %x (%s)\r\n", p_hvx->data[2], categoryid2string(p_hvx->data[2]));
+                        pc.printf("Category Count: %x\r\n", p_hvx->data[3]);
+                        pc.printf("Notification ID: %x %x %x %x\r\n", p_hvx->data[4], p_hvx->data[5], p_hvx->data[6], p_hvx->data[7]);
+                        
+                        // if we are still processing, we can not do another write
+                        // with soft device (limitation?). Real implementation should use
+                        // queue to synchronized operation. Since this is a POC... just ignore.
+                        if(m_state == STATE_NOTIFIED) {
+                            pc.printf("Still retrieving data for another notification. ignoring this one.\r\n");
+                        } else if(p_hvx->data[0] == 0) {
+                            // we only retrieved data for added notification.
+                            m_state = STATE_NOTIFIED;
+                            // write control point to get another data.
+                            
+                            // We only retrieve the title, with 16 bytes buffer... see ANCS spec for more
+                            static ble_gattc_write_params_t m_write_params;
+                            uint8_t gattc_value[8];
+                     
+                            gattc_value[0] = 0; // CommandIDGetNotificationAttributes
+                            gattc_value[1] = p_hvx->data[4];
+                            gattc_value[2] = p_hvx->data[5];
+                            gattc_value[3] = p_hvx->data[6];
+                            gattc_value[4] = p_hvx->data[7];
+                            gattc_value[5] = 1; // Title
+                            gattc_value[6] = 16; // Length, 2 bytes, MSB first.
+                            gattc_value[7] = 0;
+
+                            m_write_params.handle = m_control_point_handle;
+                            m_write_params.len  = 8;
+                            m_write_params.p_value = &gattc_value[0];
+                            m_write_params.offset = 0;
+                            m_write_params.write_op = BLE_GATT_OP_WRITE_REQ;
+                        
+                            err_code = sd_ble_gattc_write(m_conn_handle, &m_write_params);
+                            err_check(err_code, "sd_ble_gattc_write");
+                            
+                        }
+                        
+                    } else {
+                        pc.printf("NS data len not 8\r\n");
+                    }
+                }
+                
+                // Got data
+                if(p_ble_evt->evt.gattc_evt.params.hvx.handle == m_data_source_handle) {
+                    ble_gattc_evt_hvx_t *p_hvx = &p_ble_evt->evt.gattc_evt.params.hvx;
+                    pc.printf("Title:");
+                    // we only set size on MSB...
+                    uint16_t len = p_hvx->data[6];
+                    pc.printf("(%d)", len);
+
+                    // the data itself start from index 8 to 8+len;
+                    uint16_t pos;
+                    for(pos=8; pos<=8+len; pos++) {
+                        pc.printf("%c", p_hvx->data[pos]);
+                    }
+                    pc.printf("\r\n");
+                    
+                    // Back to listening...
+                    m_state = STATE_LISTENING;
+                }
+                
+            }
+            break;
+        }
+        case BLE_GATTC_EVT_TIMEOUT:
+        case BLE_GATTS_EVT_TIMEOUT:
+        {
+            // Disconnect on GATT Server and Client timeout events.
+            err_code = sd_ble_gap_disconnect(m_conn_handle, 
+                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+            err_check(err_code, "sd_ble_gap_disconnect");
+            break;
+        }
+        default:
+        {
+            //No implementation needed
+            break;
+        }
+    }
+
+}
+
+
+static void sys_event_handler(uint32_t sys_evt)
+{
+    pc.printf("Event: system event\r\n");
+    pstorage_sys_event_handler(sys_evt);
+}
+
+
+static void timers_init(void)
+{
+    // Initialize timer module.
+    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
+}
+
+
+static void ble_stack_init(void)
+{
+    uint32_t err_code;
+    
+    // Initialize the SoftDevice handler module.
+    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
+    
+
+    // Register with the SoftDevice handler module for BLE events.
+    err_code = softdevice_ble_evt_handler_set(ble_event_handler);
+    err_check(err_code, "softdevice_ble_evt_handler_set");
+    
+    // Register with the SoftDevice handler module for System events.
+    err_code = softdevice_sys_evt_handler_set(sys_event_handler);
+    err_check(err_code, "softdevice_sys_evt_handler_set");
+}
+
+static void set_128_uuid()
+{
+    uint32_t        err_code;
+    uint8_t         temp_type;  // All ANCS is vendor type... so we ignore this.
+
+
+    err_code = sd_ble_uuid_vs_add(&ble_ancs_base_uuid128, &temp_type);
+    err_check(err_code, "sd_ble_uuid_vs_add");
+
+    err_code = sd_ble_uuid_vs_add(&ble_ancs_cp_base_uuid128, &temp_type);
+    err_check(err_code, "sd_ble_uuid_vs_add");
+
+    err_code = sd_ble_uuid_vs_add(&ble_ancs_ns_base_uuid128, &temp_type);
+    err_check(err_code, "sd_ble_uuid_vs_add");
+
+    err_code = sd_ble_uuid_vs_add(&ble_ancs_ds_base_uuid128, &temp_type);
+    err_check(err_code, "sd_ble_uuid_vs_add");
+}
+
+
+static void conn_params_error_handler(uint32_t nrf_error)
+{
+    err_check(nrf_error, "Error: conn params error");
+}
+
+
+static void conn_params_init(void)
+{
+    uint32_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             = true;
+    cp_init.evt_handler                    = NULL;
+    cp_init.error_handler                  = conn_params_error_handler;
+
+    err_code = ble_conn_params_init(&cp_init);
+    err_check(err_code, "ble_conn_params_init");
+}
+
+
+static void sec_params_init(void)
+{
+    m_sec_params.timeout      = SEC_PARAM_TIMEOUT;
+    m_sec_params.bond         = SEC_PARAM_BOND;
+    m_sec_params.mitm         = SEC_PARAM_MITM;
+    m_sec_params.io_caps      = SEC_PARAM_IO_CAPABILITIES;
+    m_sec_params.oob          = SEC_PARAM_OOB;  
+    m_sec_params.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
+    m_sec_params.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
+}
+
+
+static void gap_params_init(void)
+{
+    uint32_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));
+    err_check(err_code, "sd_ble_gap_device_name_set");
+
+    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);
+    err_check(err_code, "sd_ble_gap_ppcp_set");
+}
+
+
+static void advertising_init(void)
+{
+    uint32_t      err_code;
+    ble_advdata_t advdata;
+    uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
+    ble_uuid_t    ancs_uuid;
+    
+//    err_code = sd_ble_uuid_vs_add(&ble_ancs_base_uuid128, &m_ancs_uuid_type);
+//    err_check(err_code, "sd_ble_uuid_vs_add");
+
+//    ancs_uuid.uuid = ((ble_ancs_base_uuid128.uuid128[12]) | (ble_ancs_base_uuid128.uuid128[13] << 8));
+//    ancs_uuid.type = m_ancs_uuid_type;
+    BLE_UUID_BLE_ASSIGN(ancs_uuid, BLE_UUID_APPLE_NOTIFICATION_CENTER_SERVICE);
+    ancs_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
+
+    // Build and set advertising data.
+    memset(&advdata, 0, sizeof(advdata));
+    
+    advdata.name_type               = BLE_ADVDATA_FULL_NAME;
+    advdata.include_appearance      = true;
+    advdata.flags.size              = sizeof(flags);
+    advdata.flags.p_data            = &flags;
+    advdata.uuids_complete.uuid_cnt = 0;
+    advdata.uuids_complete.p_uuids  = NULL;
+    advdata.uuids_solicited.uuid_cnt = 1;
+    advdata.uuids_solicited.p_uuids  = &ancs_uuid;    
+    
+    err_code = ble_advdata_set(&advdata, NULL);
+    err_check(err_code, "ble_advdata_set");
+
+}
+
+
+/**************************************************************************/
+/*!
+    @brief  Program entry point
+*/
+/**************************************************************************/
+int main(void)
+{
+    uint32_t err_code;
+//    uint32_t soc_event;
+//    uint32_t evt_id;
+    
+    pc.printf("Program started\n\r");
+
+    led_adv = 0;
+    led_conn = 0;
+
+
+    pc.printf("timers_init()\r\n");
+    timers_init();
+    
+    pc.printf("ble_stack_init()\r\n");
+    ble_stack_init();    
+
+    pc.printf("gap_params_init()\r\n");
+    gap_params_init();
+
+    pc.printf("set_128_uuid()\r\n");
+    set_128_uuid();
+    
+    pc.printf("advertising_init()\r\n");
+    advertising_init();
+    
+
+    pc.printf("conn_params_init()\r\n");
+    conn_params_init();
+    
+    pc.printf("sec_params_init()\r\n");
+    sec_params_init();
+        
+    pc.printf("advertising_start()\r\n");
+    advertising_start();
+
+
+//    while(1) { wait(1.0); };
+
+    for (;;)
+    {
+        err_code = sd_app_evt_wait();
+        err_check(err_code, "sd_app_evt_wait");
+        
+        /*
+        do {
+            soc_event = sd_evt_get(&evt_id);
+            pc.printf("soc_event: %d\r\n", evt_id);
+        } while(soc_event != NRF_ERROR_NOT_FOUND);
+        */
+    }
+    
+}