changed low freq. clock source to IRC

Dependencies:   BLE_API mbed nRF51822_IRC

Fork of BLE_ANCS_SDAPI by devsar devsar

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include <stdbool.h>
00002 #include <stdint.h>
00003 #include <string.h>
00004 
00005 #include "mbed.h"
00006 #include "nRF51822n.h"
00007 
00008 #include "nordic_common.h"
00009 //#include "nrf.h"
00010 #include "app_error.h"
00011 #include "ble_hci.h"
00012 #include "ble_gap.h"
00013 #include "ble_advdata.h"
00014 #include "ble_error_log.h"
00015 #include "nrf_gpio.h"
00016 #include "ble_srv_common.h"
00017 #include "ble_conn_params.h"
00018 #include "nrf51_bitfields.h"
00019 #include "ble_bondmngr.h"
00020 #include "app_timer.h"
00021 #include "ble_radio_notification.h"
00022 #include "ble_flash.h"
00023 #include "ble_debug_assert_handler.h"
00024 #include "pstorage.h"
00025 #include "nrf_soc.h"
00026 #include "softdevice_handler.h"
00027 
00028 #include "debug.h"
00029 
00030 
00031 #define DEVICE_NAME                     "ANCC"                                               /**< Name of device. Will be included in the advertising data. */
00032 #define APP_ADV_INTERVAL                40                                                   /**< The advertising interval (in units of 0.625 ms. This value corresponds to 25 ms). */
00033 #define APP_ADV_INTERVAL_SLOW           3200                                                 /**< Slow advertising interval (in units of 0.625 ms. This value corresponds to 2 seconds). */
00034 #define APP_ADV_TIMEOUT_IN_SECONDS      180                                                  /**< The advertising timeout in units of seconds. */
00035 #define ADV_INTERVAL_FAST_PERIOD        30                                                   /**< The duration of the fast advertising period (in seconds). */
00036 
00037 #define APP_TIMER_PRESCALER             0                                                    /**< Value of the RTC1 PRESCALER register. */
00038 #define APP_TIMER_MAX_TIMERS            2                                                    /**< Maximum number of simultaneously created timers. */
00039 #define APP_TIMER_OP_QUEUE_SIZE         4                                                    /**< Size of timer operation queues. */
00040 
00041 #define MIN_CONN_INTERVAL               MSEC_TO_UNITS(500, UNIT_1_25_MS)                     /**< Minimum acceptable connection interval (0.5 seconds). */
00042 #define MAX_CONN_INTERVAL               MSEC_TO_UNITS(1000, UNIT_1_25_MS)                    /**< Maximum acceptable connection interval (1 second). */
00043 #define SLAVE_LATENCY                   0                                                    /**< Slave latency. */
00044 #define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)                      /**< Connection supervisory timeout (4 seconds). */
00045 
00046 #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). */
00047 #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). */
00048 #define MAX_CONN_PARAMS_UPDATE_COUNT    3                                                    /**< Number of attempts before giving up the connection parameter negotiation. */
00049 
00050 
00051 #define SEC_PARAM_TIMEOUT               30                                                   /**< Timeout for Pairing Request or Security Request (in seconds). */
00052 #define SEC_PARAM_BOND                  0                                                    /**< Perform bonding. */
00053 #define SEC_PARAM_MITM                  0                                                    /**< Man In The Middle protection not required. */
00054 #define SEC_PARAM_IO_CAPABILITIES       BLE_GAP_IO_CAPS_NONE                                 /**< No I/O capabilities. */
00055 #define SEC_PARAM_OOB                   0                                                    /**< Out Of Band data not available. */
00056 #define SEC_PARAM_MIN_KEY_SIZE          7                                                    /**< Minimum encryption key size. */
00057 #define SEC_PARAM_MAX_KEY_SIZE          16                                                   /**< Maximum encryption key size. */
00058 
00059 #define BLE_UUID_APPLE_NOTIFICATION_CENTER_SERVICE  0xf431                               /*<< ANCS service UUID. */
00060 #define BLE_UUID_ANCS_CONTROL_POINT_CHAR            0xd8f3                               /*<< Control point UUID. */
00061 #define BLE_UUID_ANCS_NOTIFICATION_SOURCE_CHAR      0x120d                               /*<< Notification source UUID. */
00062 #define BLE_UUID_ANCS_DATA_SOURCE_CHAR              0xc6e9                               /*<< Data source UUID. */
00063 
00064 #define BLE_CCCD_NOTIFY_BIT_MASK         0x0001                                            /**< Enable Notification bit. */
00065 
00066 
00067 typedef enum
00068 {
00069     BLE_NO_ADVERTISING,                                                                      /**< No advertising running. */
00070     BLE_SLOW_ADVERTISING,                                                                    /**< Slow advertising running. */
00071     BLE_FAST_ADVERTISING                                                                     /**< Fast advertising running. */
00072 } ble_advertising_mode_t;
00073 
00074 typedef enum
00075 {
00076     STATE_UNINITIALIZED,                    // Program start.
00077     STATE_ADVERTISING,                      // Advertising. See Settings>Bluetooth on iPhone then connect to "ANCC"
00078     STATE_CONNECTED,                        // iPhone connected to us.
00079     STATE_DISCOVERY_SERVICE,                // Searching for ANCS Service.
00080     STATE_DISCOVERY_CHARACTERISTICS,        // Searching for ANCS Characteristics.
00081     STATE_PAIRING,                          // Got all we need. Now pair before subscribe. Should see pairing dialog on iPhone
00082     STATE_SUBSCRIBING,                      // Subscribe to CCC, for notification.
00083     STATE_LISTENING,                        // Listening...
00084     STATE_NOTIFIED,                         // Got notification, now retrieve other info and print log out. back to listening.
00085     STATE_DISCONNECTED,                     // Disconnected?
00086     STATE_ERROR
00087 } state_t;
00088 
00089 
00090 
00091 DigitalOut led_adv(LED1);
00092 DigitalOut led_conn(LED2);
00093 
00094 Serial     pc(USBTX, USBRX);
00095 
00096 const ble_uuid128_t ble_ancs_base_uuid128 =
00097 {
00098    {
00099     // 7905F431-B5CE-4E99-A40F-4B1E122D00D0
00100     0xd0, 0x00, 0x2d, 0x12, 0x1e, 0x4b, 0x0f, 0xa4,
00101     0x99, 0x4e, 0xce, 0xb5, 0x31, 0xf4, 0x05, 0x79
00102    }
00103 };
00104 
00105 
00106 const ble_uuid128_t ble_ancs_cp_base_uuid128 =
00107 {
00108    {
00109     // 69d1d8f3-45e1-49a8-9821-9bbdfdaad9d9
00110     0xd9, 0xd9, 0xaa, 0xfd, 0xbd, 0x9b, 0x21, 0x98,
00111     0xa8, 0x49, 0xe1, 0x45, 0xf3, 0xd8, 0xd1, 0x69
00112 
00113    }
00114 };
00115 
00116 const ble_uuid128_t ble_ancs_ns_base_uuid128 =
00117 {
00118    {
00119     // 9FBF120D-6301-42D9-8C58-25E699A21DBD
00120     0xbd, 0x1d, 0xa2, 0x99, 0xe6, 0x25, 0x58, 0x8c,
00121     0xd9, 0x42, 0x01, 0x63, 0x0d, 0x12, 0xbf, 0x9f
00122 
00123    }
00124 };
00125 
00126 const ble_uuid128_t ble_ancs_ds_base_uuid128 =
00127 {
00128    {
00129     // 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB
00130     0xfb, 0x7b, 0x7c, 0xce, 0x6a, 0xb3, 0x44, 0xbe,
00131     0xb5, 0x4b, 0xd6, 0x24, 0xe9, 0xc6, 0xea, 0x22
00132 
00133    }
00134 };
00135 
00136 static state_t                          m_state = STATE_UNINITIALIZED;
00137 
00138 static ble_gap_adv_params_t             m_adv_params;                                        /**< Parameters to be passed to the stack when starting advertising. */
00139 static ble_advertising_mode_t           m_advertising_mode;                                  /**< Variable to keep track of when we are advertising. */
00140 
00141 static ble_gap_sec_params_t             m_sec_params;                                        /**< Security requirements for this application. */
00142 
00143 // ANCS Characteristic...
00144 static uint16_t m_notification_source_handle = 0;
00145 static uint16_t m_notification_source_handle_cccd = 0;
00146 static uint16_t m_control_point_handle = 0;
00147 static uint16_t m_data_source_handle = 0;
00148 static uint16_t m_data_source_handle_cccd = 0;
00149 
00150 static void err_check(uint32_t error_code, char *method)
00151 {
00152     if(error_code != NRF_SUCCESS) {
00153         pc.printf("ERROR: %d (%s) on %s\r\n", error_code, error2string(error_code), method);
00154 //    } else {
00155 //        pc.printf("SUCCESS: %s\r\n", method);
00156     }
00157     APP_ERROR_CHECK(error_code);
00158 }
00159 
00160 
00161 static void advertising_start(void)
00162 {
00163     uint32_t err_code;
00164 
00165     if (m_advertising_mode == BLE_NO_ADVERTISING)
00166     {
00167         m_advertising_mode = BLE_FAST_ADVERTISING;
00168     }
00169     else
00170     {
00171         m_advertising_mode = BLE_SLOW_ADVERTISING;
00172     }
00173 
00174     memset(&m_adv_params, 0, sizeof(m_adv_params));
00175     
00176     m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
00177     m_adv_params.p_peer_addr = NULL;                           // Undirected advertisement.
00178     m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
00179 
00180     if (m_advertising_mode == BLE_FAST_ADVERTISING)
00181     {
00182         m_adv_params.interval = APP_ADV_INTERVAL;
00183         m_adv_params.timeout  = ADV_INTERVAL_FAST_PERIOD;
00184     }
00185     else
00186     {
00187         m_adv_params.interval = APP_ADV_INTERVAL_SLOW;
00188         m_adv_params.timeout  = APP_ADV_TIMEOUT_IN_SECONDS;
00189     }
00190 
00191     err_code = sd_ble_gap_adv_start(&m_adv_params);
00192     err_check(err_code, "sd_ble_gap_adv_start");
00193 
00194     led_adv = 1;
00195     m_state = STATE_ADVERTISING;
00196 }
00197 
00198 
00199 
00200 
00201 static void ble_event_handler(ble_evt_t * p_ble_evt)
00202 {
00203     uint32_t        err_code = NRF_SUCCESS;
00204     static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;
00205     ble_uuid_t ancs_uuid;
00206     static ble_gattc_handle_range_t handle_range;
00207 
00208     pc.printf("Event: %s\r\n", event2string(p_ble_evt));
00209 //    ble_bondmngr_on_ble_evt(p_ble_evt);
00210 //    ble_conn_params_on_ble_evt(p_ble_evt);
00211     
00212     switch (p_ble_evt->header.evt_id)
00213     {
00214         case BLE_GAP_EVT_CONNECTED:
00215         {
00216             m_state = STATE_CONNECTED;
00217 
00218             m_advertising_mode = BLE_NO_ADVERTISING;
00219             m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
00220             led_conn = 1;
00221             
00222             m_state = STATE_DISCOVERY_SERVICE;
00223 
00224             BLE_UUID_BLE_ASSIGN(ancs_uuid, BLE_UUID_APPLE_NOTIFICATION_CENTER_SERVICE);
00225             ancs_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
00226 
00227             err_code = sd_ble_gattc_primary_services_discover(m_conn_handle, 0x0001, &ancs_uuid);
00228             err_check(err_code, "sd_ble_gattc_primary_services_discover");            
00229             
00230 
00231             break;
00232         }        
00233         case BLE_GAP_EVT_AUTH_STATUS:
00234         {                
00235             m_state = STATE_SUBSCRIBING;
00236 
00237             // Subscribe to NS
00238             uint16_t       cccd_val = true ? BLE_CCCD_NOTIFY_BIT_MASK : 0;
00239             static ble_gattc_write_params_t m_write_params;
00240             uint8_t gattc_value[2];
00241                      
00242             gattc_value[0] = LSB(cccd_val);
00243             gattc_value[1] = MSB(cccd_val);
00244 
00245             m_write_params.handle = m_notification_source_handle_cccd;
00246             m_write_params.len  = 2;
00247             m_write_params.p_value = &gattc_value[0];
00248             m_write_params.offset = 0;
00249             m_write_params.write_op = BLE_GATT_OP_WRITE_REQ;
00250                         
00251 
00252             err_code = sd_ble_gattc_write(m_conn_handle, &m_write_params);
00253             err_check(err_code, "sd_ble_gattc_write");
00254 
00255             break;
00256         }   
00257         case BLE_GAP_EVT_DISCONNECTED:
00258         {
00259             m_conn_handle = BLE_CONN_HANDLE_INVALID;
00260 
00261             advertising_start();
00262             led_conn = 0;
00263             break;
00264         }    
00265         case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
00266         {
00267             err_code = sd_ble_gap_sec_params_reply(m_conn_handle, 
00268                                                    BLE_GAP_SEC_STATUS_SUCCESS, 
00269                                                    &m_sec_params);
00270             err_check(err_code, "sd_ble_gap_sec_params_reply");
00271             break;
00272         }
00273         case BLE_GAP_EVT_TIMEOUT:
00274         {
00275             if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
00276             { 
00277                 if (m_advertising_mode == BLE_FAST_ADVERTISING)
00278                 {
00279                     advertising_start();
00280                 }
00281                 else
00282                 {
00283                     err_code = sd_power_system_off();
00284                 }
00285             }
00286             break;
00287         }   
00288         case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
00289         {
00290              if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
00291                 // Error.
00292                 pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP");
00293             } else {
00294                 if (p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.count > 0) {
00295                     const ble_gattc_service_t * p_service;
00296 
00297                     p_service = &(p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[0]);
00298 
00299                     pc.printf("Found ANCS service, start handle: %d, end handle: %d\r\n", 
00300                         p_service->handle_range.start_handle, p_service->handle_range.end_handle);
00301 
00302                     handle_range.start_handle = p_service->handle_range.start_handle;
00303                     handle_range.end_handle   = p_service->handle_range.end_handle;
00304 
00305                     err_code = sd_ble_gattc_characteristics_discover(m_conn_handle, &handle_range);
00306                     err_check(err_code, "sd_ble_gattc_characteristics_discover");
00307                     
00308                     m_state = STATE_DISCOVERY_CHARACTERISTICS;
00309 
00310                 } else {
00311                     pc.printf("Error: discovery failure, no ANCS\r\n");
00312                 }
00313             }
00314 
00315             break;
00316         }
00317         case BLE_GATTC_EVT_CHAR_DISC_RSP:
00318         {    
00319             // End of characteristics searching...no more attribute or no more handle.
00320             // We got error as response, but this is normal for gatt attribute searching.
00321             if (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND ||
00322                 p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_INVALID_HANDLE) {
00323                 
00324                 if(m_notification_source_handle == 0) {
00325                     pc.printf("Error: NS not found.\r\n");
00326                 } else if(m_control_point_handle == 0) {
00327                     pc.printf("Error: CP not found.\r\n");
00328                 } else if(m_data_source_handle == 0) {
00329                     pc.printf("Error: DS not found.\r\n");
00330                 } 
00331                 // OK, we got all char handles. Next, find CCC.
00332                 else {
00333                     // Start with NS CCC
00334                     handle_range.start_handle = m_notification_source_handle + 1;
00335                     handle_range.end_handle = m_notification_source_handle + 1;
00336                     
00337                     err_code = sd_ble_gattc_descriptors_discover(m_conn_handle, &handle_range);
00338                     err_check(err_code, "sd_ble_gattc_descriptors_discover");
00339                 }        
00340             
00341             } else if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
00342                 pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_CHAR_DISC_RSP");
00343             } else {
00344                 uint32_t                 i;
00345                 const ble_gattc_char_t * p_char_resp = NULL;
00346 
00347                 // Iterate trough the characteristics and find the correct one.
00348                  for (i = 0; i < p_ble_evt->evt.gattc_evt.params.char_disc_rsp.count; i++) {
00349                     p_char_resp = &(p_ble_evt->evt.gattc_evt.params.char_disc_rsp.chars[i]);
00350                     switch (p_char_resp->uuid.uuid) {
00351                         case BLE_UUID_ANCS_CONTROL_POINT_CHAR:
00352                             pc.printf("Found char: Control Point");
00353                             m_control_point_handle = p_char_resp->handle_value;
00354                         break;
00355 
00356                         case BLE_UUID_ANCS_NOTIFICATION_SOURCE_CHAR:
00357                             pc.printf("Found char: Notification Source");
00358                             m_notification_source_handle = p_char_resp->handle_value;
00359                         break;
00360 
00361                         case BLE_UUID_ANCS_DATA_SOURCE_CHAR:
00362                             pc.printf("Found char: Data Source");
00363                             m_data_source_handle = p_char_resp->handle_value;
00364                         break;
00365 
00366                         default:
00367                         break;
00368                     }
00369                 }
00370                 
00371                 if(p_char_resp!=NULL) {
00372 
00373                     handle_range.start_handle = p_char_resp->handle_value + 1;
00374 
00375                     err_code = sd_ble_gattc_characteristics_discover(m_conn_handle, &handle_range);
00376                     err_check(err_code, "sd_ble_gattc_characteristics_discover");
00377                     
00378                 } else {
00379                     err_code = sd_ble_gattc_characteristics_discover(m_conn_handle, &handle_range);
00380                     err_check(err_code, "sd_ble_gattc_characteristics_discover");
00381                 }
00382         
00383             }
00384         
00385             break;
00386         }
00387         case BLE_GATTC_EVT_DESC_DISC_RSP:
00388         {
00389             if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
00390                 pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_DESC_DISC_RSP");        
00391             } else {
00392                 if (p_ble_evt->evt.gattc_evt.params.desc_disc_rsp.count > 0) {
00393                     const ble_gattc_desc_t * p_desc_resp = &(p_ble_evt->evt.gattc_evt.params.desc_disc_rsp.descs[0]);
00394                     if (p_desc_resp->uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG) {
00395                         if(p_desc_resp->handle == m_notification_source_handle + 1) {
00396                                                                           
00397                             m_notification_source_handle_cccd = p_desc_resp->handle;
00398                             pc.printf("Found NS CCC\r\n");
00399                             
00400                             // Next, find CCC for data source.
00401                             handle_range.start_handle = m_data_source_handle + 1;
00402                             handle_range.end_handle = m_data_source_handle + 1;
00403                     
00404                             err_code = sd_ble_gattc_descriptors_discover(m_conn_handle, &handle_range);
00405                             err_check(err_code, "sd_ble_gattc_descriptors_discover");
00406 
00407                         } else if(p_desc_resp->handle == m_data_source_handle + 1) {
00408                             
00409                             m_data_source_handle_cccd = p_desc_resp->handle;
00410                             pc.printf("Found DS CCC\r\n");
00411                                                                   
00412                             // Got all we need, now before subscribing we'll do pairing.
00413                             // request encryption...., we are in peripheral role.
00414                             
00415                             m_state = STATE_PAIRING;
00416                             
00417                             err_code = sd_ble_gap_authenticate(m_conn_handle, &m_sec_params);
00418                             err_check(err_code, "sd_ble_gap_authenticate");
00419                         }
00420                     }
00421                 }
00422             }
00423             break;
00424         }
00425         case BLE_GATTC_EVT_WRITE_RSP:
00426         {
00427             if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
00428                 pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_WRITE_RSP"); 
00429 
00430                 if(p_ble_evt->evt.gattc_evt.params.write_rsp.handle == m_control_point_handle) {
00431                     m_state = STATE_LISTENING;
00432                 }
00433             } else {
00434                 if(p_ble_evt->evt.gattc_evt.params.write_rsp.handle == m_notification_source_handle_cccd) {
00435                     pc.printf("NS subscribe success.\r\n");
00436 
00437                     // Next, subscribe to DS.
00438                     uint16_t       cccd_val = true ? BLE_CCCD_NOTIFY_BIT_MASK : 0;
00439                     static ble_gattc_write_params_t m_write_params;
00440                     uint8_t gattc_value[2];
00441                      
00442                     gattc_value[0] = LSB(cccd_val);
00443                     gattc_value[1] = MSB(cccd_val);
00444 
00445                     m_write_params.handle = m_data_source_handle_cccd;
00446                     m_write_params.len  = 2;
00447                     m_write_params.p_value = &gattc_value[0];
00448                     m_write_params.offset = 0;
00449                     m_write_params.write_op = BLE_GATT_OP_WRITE_REQ;
00450                         
00451                     err_code = sd_ble_gattc_write(m_conn_handle, &m_write_params);
00452                     err_check(err_code, "sd_ble_gattc_write");
00453                 }
00454                 
00455                 if(p_ble_evt->evt.gattc_evt.params.write_rsp.handle == m_data_source_handle_cccd) {
00456                     pc.printf("DS subscribe success.\r\n");
00457                     
00458                     // Now, we just waiting for NS notification.
00459                     m_state = STATE_LISTENING;
00460                 }
00461                 
00462                 if(p_ble_evt->evt.gattc_evt.params.write_rsp.handle == m_control_point_handle) {
00463                     pc.printf("CP write success.\r\n");
00464                     // We'll receive data from DS notification
00465                 }
00466 
00467             }
00468         
00469             break;
00470         }
00471         case BLE_GATTC_EVT_HVX:
00472         {
00473             if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) {
00474                 pc.printf("Error: %s\r\n", "BLE_GATTC_EVT_HVX");        
00475             } else {
00476 
00477                 // Got notification...
00478                 if(p_ble_evt->evt.gattc_evt.params.hvx.handle == m_notification_source_handle) {
00479                     ble_gattc_evt_hvx_t *p_hvx = &p_ble_evt->evt.gattc_evt.params.hvx;
00480                     if(p_hvx->len == 8) {
00481                         pc.printf("Event ID: %x (%s)\r\n", p_hvx->data[0], eventid2string(p_hvx->data[0]));
00482                         pc.printf("Event Flags: %x (%s)\r\n", p_hvx->data[1], eventflags2string(p_hvx->data[1]));
00483                         pc.printf("Category ID: %x (%s)\r\n", p_hvx->data[2], categoryid2string(p_hvx->data[2]));
00484                         pc.printf("Category Count: %x\r\n", p_hvx->data[3]);
00485                         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]);
00486                         
00487                         // if we are still processing, we can not do another write
00488                         // with soft device (limitation?). Real implementation should use
00489                         // queue to synchronized operation. Since this is a POC... just ignore.
00490                         if(m_state == STATE_NOTIFIED) {
00491                             pc.printf("Still retrieving data for another notification. ignoring this one.\r\n");
00492                         } else if(p_hvx->data[0] == 0) {
00493                             // we only retrieved data for added notification.
00494                             m_state = STATE_NOTIFIED;
00495                             // write control point to get another data.
00496                             
00497                             // We only retrieve the title, with 16 bytes buffer... see ANCS spec for more
00498                             static ble_gattc_write_params_t m_write_params;
00499                             uint8_t gattc_value[8];
00500                      
00501                             gattc_value[0] = 0; // CommandIDGetNotificationAttributes
00502                             gattc_value[1] = p_hvx->data[4];
00503                             gattc_value[2] = p_hvx->data[5];
00504                             gattc_value[3] = p_hvx->data[6];
00505                             gattc_value[4] = p_hvx->data[7];
00506                             gattc_value[5] = 1; // Title
00507                             gattc_value[6] = 16; // Length, 2 bytes, MSB first.
00508                             gattc_value[7] = 0;
00509 
00510                             m_write_params.handle = m_control_point_handle;
00511                             m_write_params.len  = 8;
00512                             m_write_params.p_value = &gattc_value[0];
00513                             m_write_params.offset = 0;
00514                             m_write_params.write_op = BLE_GATT_OP_WRITE_REQ;
00515                         
00516                             err_code = sd_ble_gattc_write(m_conn_handle, &m_write_params);
00517                             err_check(err_code, "sd_ble_gattc_write");
00518                             
00519                         }
00520                         
00521                     } else {
00522                         pc.printf("NS data len not 8\r\n");
00523                     }
00524                 }
00525                 
00526                 // Got data
00527                 if(p_ble_evt->evt.gattc_evt.params.hvx.handle == m_data_source_handle) {
00528                     ble_gattc_evt_hvx_t *p_hvx = &p_ble_evt->evt.gattc_evt.params.hvx;
00529                     pc.printf("Title:");
00530                     // we only set size on MSB...
00531                     uint16_t len = p_hvx->data[6];
00532                     pc.printf("(%d)", len);
00533 
00534                     // the data itself start from index 8 to 8+len;
00535                     uint16_t pos;
00536                     for(pos=8; pos<=8+len; pos++) {
00537                         pc.printf("%c", p_hvx->data[pos]);
00538                     }
00539                     pc.printf("\r\n");
00540                     
00541                     // Back to listening...
00542                     m_state = STATE_LISTENING;
00543                 }
00544                 
00545             }
00546             break;
00547         }
00548         case BLE_GATTC_EVT_TIMEOUT:
00549         case BLE_GATTS_EVT_TIMEOUT:
00550         {
00551             // Disconnect on GATT Server and Client timeout events.
00552             err_code = sd_ble_gap_disconnect(m_conn_handle, 
00553                                              BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
00554             err_check(err_code, "sd_ble_gap_disconnect");
00555             break;
00556         }
00557         default:
00558         {
00559             //No implementation needed
00560             break;
00561         }
00562     }
00563 
00564 }
00565 
00566 
00567 static void sys_event_handler(uint32_t sys_evt)
00568 {
00569     pc.printf("Event: system event\r\n");
00570     pstorage_sys_event_handler(sys_evt);
00571 }
00572 
00573 
00574 static void timers_init(void)
00575 {
00576     // Initialize timer module.
00577     APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
00578 }
00579 
00580 
00581 static void ble_stack_init(void)
00582 {
00583     uint32_t err_code;
00584     
00585     // Initialize the SoftDevice handler module.
00586 //    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
00587     SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION, false);
00588     
00589 
00590     // Register with the SoftDevice handler module for BLE events.
00591     err_code = softdevice_ble_evt_handler_set(ble_event_handler);
00592     err_check(err_code, "softdevice_ble_evt_handler_set");
00593     
00594     // Register with the SoftDevice handler module for System events.
00595     err_code = softdevice_sys_evt_handler_set(sys_event_handler);
00596     err_check(err_code, "softdevice_sys_evt_handler_set");
00597 }
00598 
00599 static void set_128_uuid()
00600 {
00601     uint32_t        err_code;
00602     uint8_t         temp_type;  // All ANCS is vendor type... so we ignore this.
00603 
00604 
00605     err_code = sd_ble_uuid_vs_add(&ble_ancs_base_uuid128, &temp_type);
00606     err_check(err_code, "sd_ble_uuid_vs_add");
00607 
00608     err_code = sd_ble_uuid_vs_add(&ble_ancs_cp_base_uuid128, &temp_type);
00609     err_check(err_code, "sd_ble_uuid_vs_add");
00610 
00611     err_code = sd_ble_uuid_vs_add(&ble_ancs_ns_base_uuid128, &temp_type);
00612     err_check(err_code, "sd_ble_uuid_vs_add");
00613 
00614     err_code = sd_ble_uuid_vs_add(&ble_ancs_ds_base_uuid128, &temp_type);
00615     err_check(err_code, "sd_ble_uuid_vs_add");
00616 }
00617 
00618 
00619 static void conn_params_error_handler(uint32_t nrf_error)
00620 {
00621     err_check(nrf_error, "Error: conn params error");
00622 }
00623 
00624 
00625 static void conn_params_init(void)
00626 {
00627     uint32_t               err_code;
00628     ble_conn_params_init_t cp_init;
00629 
00630     memset(&cp_init, 0, sizeof(cp_init));
00631 
00632     cp_init.p_conn_params                  = NULL;
00633     cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
00634     cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
00635     cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
00636     cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
00637     cp_init.disconnect_on_fail             = true;
00638     cp_init.evt_handler                    = NULL;
00639     cp_init.error_handler                  = conn_params_error_handler;
00640 
00641     err_code = ble_conn_params_init(&cp_init);
00642     err_check(err_code, "ble_conn_params_init");
00643 }
00644 
00645 
00646 static void sec_params_init(void)
00647 {
00648     m_sec_params.timeout      = SEC_PARAM_TIMEOUT;
00649     m_sec_params.bond         = SEC_PARAM_BOND;
00650     m_sec_params.mitm         = SEC_PARAM_MITM;
00651     m_sec_params.io_caps      = SEC_PARAM_IO_CAPABILITIES;
00652     m_sec_params.oob          = SEC_PARAM_OOB;  
00653     m_sec_params.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
00654     m_sec_params.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
00655 }
00656 
00657 
00658 static void gap_params_init(void)
00659 {
00660     uint32_t                err_code;
00661     ble_gap_conn_params_t   gap_conn_params;
00662     ble_gap_conn_sec_mode_t sec_mode;
00663 
00664     BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
00665     
00666     err_code = sd_ble_gap_device_name_set(&sec_mode, 
00667                                           (const uint8_t *)DEVICE_NAME, 
00668                                           strlen(DEVICE_NAME));
00669     err_check(err_code, "sd_ble_gap_device_name_set");
00670 
00671     memset(&gap_conn_params, 0, sizeof(gap_conn_params));
00672 
00673     gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
00674     gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
00675     gap_conn_params.slave_latency     = SLAVE_LATENCY;
00676     gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
00677 
00678     err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
00679     err_check(err_code, "sd_ble_gap_ppcp_set");
00680 }
00681 
00682 
00683 static void advertising_init(void)
00684 {
00685     uint32_t      err_code;
00686     ble_advdata_t advdata;
00687     uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
00688     ble_uuid_t    ancs_uuid;
00689     
00690 //    err_code = sd_ble_uuid_vs_add(&ble_ancs_base_uuid128, &m_ancs_uuid_type);
00691 //    err_check(err_code, "sd_ble_uuid_vs_add");
00692 
00693 //    ancs_uuid.uuid = ((ble_ancs_base_uuid128.uuid128[12]) | (ble_ancs_base_uuid128.uuid128[13] << 8));
00694 //    ancs_uuid.type = m_ancs_uuid_type;
00695     BLE_UUID_BLE_ASSIGN(ancs_uuid, BLE_UUID_APPLE_NOTIFICATION_CENTER_SERVICE);
00696     ancs_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
00697 
00698     // Build and set advertising data.
00699     memset(&advdata, 0, sizeof(advdata));
00700     
00701     advdata.name_type               = BLE_ADVDATA_FULL_NAME;
00702     advdata.include_appearance      = true;
00703     advdata.flags.size              = sizeof(flags);
00704     advdata.flags.p_data            = &flags;
00705     advdata.uuids_complete.uuid_cnt = 0;
00706     advdata.uuids_complete.p_uuids  = NULL;
00707     advdata.uuids_solicited.uuid_cnt = 1;
00708     advdata.uuids_solicited.p_uuids  = &ancs_uuid;    
00709     
00710     err_code = ble_advdata_set(&advdata, NULL);
00711     err_check(err_code, "ble_advdata_set");
00712 
00713 }
00714 
00715 
00716 /**************************************************************************/
00717 /*!
00718     @brief  Program entry point
00719 */
00720 /**************************************************************************/
00721 int main(void)
00722 {
00723     uint32_t err_code;
00724 //    uint32_t soc_event;
00725 //    uint32_t evt_id;
00726     
00727     pc.printf("Program started\n\r");
00728         
00729     led_adv = 0;
00730     led_conn = 0;
00731 
00732 
00733     pc.printf("timers_init()\r\n");
00734     timers_init();
00735     
00736     pc.printf("ble_stack_init()\r\n");
00737     ble_stack_init();    
00738 
00739     /* Make sure we get a clean start */
00740     wait(0.5);
00741     wait(1);
00742 
00743     pc.printf("gap_params_init()\r\n");
00744     gap_params_init();
00745 
00746     pc.printf("set_128_uuid()\r\n");
00747     set_128_uuid();
00748     
00749     pc.printf("advertising_init()\r\n");
00750     advertising_init();
00751     
00752 
00753     pc.printf("conn_params_init()\r\n");
00754     conn_params_init();
00755     
00756     pc.printf("sec_params_init()\r\n");
00757     sec_params_init();
00758         
00759     pc.printf("advertising_start()\r\n");
00760     advertising_start();
00761 
00762 
00763 //    while(1) { wait(1.0); };
00764 
00765     for (;;)
00766     {
00767         err_code = sd_app_evt_wait();
00768         err_check(err_code, "sd_app_evt_wait");
00769         
00770         /*
00771         do {
00772             soc_event = sd_evt_get(&evt_id);
00773             pc.printf("soc_event: %d\r\n", evt_id);
00774         } while(soc_event != NRF_ERROR_NOT_FOUND);
00775         */
00776     }
00777     
00778 }