BLE shield

Fork of X_NUCLEO_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers btle.cpp Source File

btle.cpp

Go to the documentation of this file.
00001 /* mbed Microcontroller Library
00002 * Copyright (c) 2006-2013 ARM Limited
00003 *
00004 * Licensed under the Apache License, Version 2.0 (the "License");
00005 * you may not use this file except in compliance with the License.
00006 * You may obtain a copy of the License at
00007 *
00008 *     http://www.apache.org/licenses/LICENSE-2.0
00009 *
00010 * Unless required by applicable law or agreed to in writing, software
00011 * distributed under the License is distributed on an "AS IS" BASIS,
00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 * See the License for the specific language governing permissions and
00014 * limitations under the License.
00015 */
00016 
00017 
00018 /**
00019   ******************************************************************************
00020   * @file    btle.cpp 
00021   * @author  STMicroelectronics
00022   * @brief   Implementation BlueNRG Init and helper functions.
00023   ******************************************************************************
00024   * @copy
00025   *
00026   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00027   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00028   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
00029   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00030   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00031   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00032   *
00033   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
00034   */ 
00035 
00036 
00037 #include "btle.h"
00038 #include "ble/Gap.h"
00039 #include "ble/GapEvents.h"
00040 #include "BlueNRGGap.h"
00041 #include "BlueNRGGattServer.h"
00042 #include "BlueNRGGattClient.h"
00043 #include "Utils.h"
00044 
00045 #ifdef __cplusplus
00046 extern "C" {
00047 #endif
00048 
00049 
00050 /* C File Includes ------------------------------------------------------------------*/
00051 // ANDREA: Updated includes and changed some types (e.g., tHalUint8 --> uint8_t)
00052 #include <stdio.h>
00053 #include <string.h>
00054 #include "hci.h"
00055 #include "hci_const.h"
00056 #include "bluenrg_aci.h"
00057 #include "bluenrg_hal_aci.h"
00058 #include "bluenrg_gap.h"
00059 #include "bluenrg_utils.h"
00060 
00061 #include "hal_types.h"
00062 #include "hal.h"
00063 #include "gp_timer.h"
00064 #include "osal.h"
00065 #include "sm.h"
00066 #include "debug.h"
00067 
00068 #ifdef __cplusplus
00069 }
00070 #endif
00071 
00072 #define IDB04A1 0
00073 #define IDB05A1 1
00074 
00075 void HCI_Input(tHciDataPacket * hciReadPacket);
00076 
00077 //#define BDADDR_SIZE 6
00078 //tHalUint8 bdaddr[BDADDR_SIZE]= {0xaa, 0x00, 0x00, 0xE1, 0x80, 0x02};
00079 
00080 uint16_t g_gap_service_handle = 0;
00081 uint16_t g_appearance_char_handle = 0;
00082 uint16_t g_device_name_char_handle = 0;
00083 
00084 /* Private variables ---------------------------------------------------------*/
00085 volatile uint8_t set_connectable = 1;
00086 // ANDREA
00087 uint8_t bnrg_expansion_board = IDB04A1; /* at startup, suppose the X-NUCLEO-IDB04A1 is used */
00088 
00089 Gap::Address_t bleAddr;
00090 Gap::AddressType_t addr_type = BLEProtocol::AddressType::PUBLIC;
00091 
00092 /**************************************************************************/
00093 /*!
00094     @brief  Initialises BTLE and the underlying HW/Device
00095     @param  isSetAddress boolean if address has been set
00096     @param  mosi MOSI Pin
00097     @param  miso MISO Pin
00098     @param  sclk clock Pin
00099     @returns void
00100 */
00101 /**************************************************************************/
00102 void btle_init(bool isSetAddress, uint8_t role)
00103 {
00104     PRINTF("btle_init>>\n\r"); 
00105     
00106     int ret;
00107     uint8_t  hwVersion;
00108     uint16_t fwVersion;
00109     uint16_t service_handle, dev_name_char_handle, appearance_char_handle;
00110 
00111     /* Delay needed only to be able to acces the JTAG interface after reset
00112     if it will be disabled later. */
00113     Clock_Wait(500);
00114 
00115     /* Initialize the BlueNRG HCI */
00116     HCI_Init();
00117 
00118     /* Reset BlueNRG SPI interface */
00119     BlueNRG_RST();
00120 
00121     /* get the BlueNRG HW and FW versions */
00122     getBlueNRGVersion(&hwVersion, &fwVersion);
00123 
00124     /* 
00125      * Reset BlueNRG again otherwise we won't
00126      * be able to change its MAC address.
00127      * aci_hal_write_config_data() must be the first
00128      * command after reset otherwise it will fail.
00129      */
00130     BlueNRG_RST();
00131 
00132     if (hwVersion > 0x30) { /* X-NUCLEO-IDB05A1 expansion board is used */
00133         bnrg_expansion_board = IDB05A1;
00134     }
00135 
00136     /* The Nucleo board must be configured as SERVER */
00137     //check if isSetAddress is set than set address.
00138     // ANDREA
00139     if(isSetAddress)
00140     {
00141         BlueNRGGap::getInstance().getAddress(&addr_type, bleAddr);
00142         
00143         Gap::Address_t bdaddr;
00144         Osal_MemCpy(bdaddr, bleAddr, BDADDR_SIZE);
00145 
00146         ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET,
00147                                         CONFIG_DATA_PUBADDR_LEN,
00148                                         bdaddr);
00149     } else {
00150         
00151         const Gap::Address_t BLE_address_BE = {0xFD,0x66,0x05,0x13,0xBE,0xBA};
00152         BlueNRGGap::getInstance().setAddress(BLEProtocol::AddressType::PUBLIC, BLE_address_BE);
00153         
00154         ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET,
00155                                         CONFIG_DATA_PUBADDR_LEN,
00156                                         BLE_address_BE);
00157     }
00158     
00159     ret = aci_gatt_init();
00160     if(ret){
00161         PRINTF("GATT_Init failed.\n");
00162     }
00163     if (bnrg_expansion_board == IDB05A1) {
00164         ret = aci_gap_init_IDB05A1(GAP_PERIPHERAL_ROLE_IDB05A1|GAP_CENTRAL_ROLE_IDB05A1, 0, 0x07, &service_handle, &dev_name_char_handle, &appearance_char_handle);
00165     } else {
00166         ret = aci_gap_init_IDB04A1(role, &service_handle, &dev_name_char_handle, &appearance_char_handle);
00167     }
00168     
00169     if(ret != BLE_STATUS_SUCCESS){
00170         PRINTF("GAP_Init failed.\n");
00171     }
00172 
00173     //ANDREA -- FIXME: Security and passkey set by default    
00174     ret = aci_gap_set_auth_requirement(MITM_PROTECTION_REQUIRED,
00175                                        OOB_AUTH_DATA_ABSENT,
00176                                        NULL,
00177                                        7,
00178                                        16,
00179                                        USE_FIXED_PIN_FOR_PAIRING,
00180                                        123456,
00181                                        BONDING);
00182     if (ret == BLE_STATUS_SUCCESS) {
00183         PRINTF("Auth Req set successfully.\n");
00184     }
00185     
00186     aci_hal_set_tx_power_level(1,4);
00187     
00188     g_gap_service_handle = service_handle;
00189     g_appearance_char_handle = appearance_char_handle;
00190     g_device_name_char_handle = dev_name_char_handle; 
00191     //Device Name is set from Accumulate Adv Data Payload or through setDeviceName API  
00192     /*ret = aci_gatt_update_char_value(service_handle, dev_name_char_handle, 0,
00193                             strlen(name), (tHalUint8 *)name);*/
00194 
00195     // Andrea: mbedOS
00196 #ifdef AST_FOR_MBED_OS
00197     minar::Scheduler::postCallback(btle_handler);
00198 #endif
00199     return;
00200 }
00201 
00202 /**************************************************************************/
00203 /*!
00204     @brief  Andrea: mbedOS
00205 
00206     @param[in]  void
00207     
00208     @returns
00209 */
00210 /**************************************************************************/
00211 #ifdef AST_FOR_MBED_OS
00212 int btle_handler_pending = 0;
00213 
00214 void btle_handler(void)
00215 {
00216     btle_handler_pending = 0;
00217     HCI_Process();
00218 }
00219 #endif
00220 
00221 
00222 /*!
00223     @brief  Not Used
00224 
00225     @param[in]  void
00226     
00227     @returns
00228 */
00229 void SPI_Poll(void)
00230 {
00231     //HAL_GPIO_EXTI_Callback_Poll(BNRG_SPI_EXTI_PIN);
00232     return;
00233 }
00234    
00235 void Attribute_Modified_CB(uint16_t attr_handle, uint8_t data_length, uint8_t *att_data, uint8_t offset)
00236 {        
00237     //Extract the GattCharacteristic from p_characteristics[] and find the properties mask
00238     GattCharacteristic *p_char = BlueNRGGattServer::getInstance().getCharacteristicFromHandle(attr_handle);
00239     if(p_char!=NULL) {
00240         GattAttribute::Handle_t charHandle = p_char->getValueAttribute().getHandle();
00241         BlueNRGGattServer::HandleEnum_t currentHandle = BlueNRGGattServer::CHAR_HANDLE;
00242         PRINTF("CharHandle %d, length: %d, Data: %d\n\r", charHandle, data_length, (uint16_t)att_data[0]);
00243         PRINTF("getProperties 0x%x\n\r",p_char->getProperties());
00244         if(attr_handle == charHandle+CHAR_VALUE_OFFSET) {
00245             currentHandle = BlueNRGGattServer::CHAR_VALUE_HANDLE;
00246         }
00247 
00248         if(attr_handle == charHandle+CHAR_DESC_OFFSET) {
00249             currentHandle = BlueNRGGattServer::CHAR_DESC_HANDLE;
00250         }
00251         PRINTF("currentHandle %d\n\r", currentHandle);
00252         if((p_char->getProperties() & 
00253             (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) &&
00254             currentHandle == BlueNRGGattServer::CHAR_DESC_HANDLE) {
00255 
00256             PRINTF("*****NOTIFICATION CASE\n\r");
00257             //Now Check if data written in Enable or Disable
00258             if((uint16_t)att_data[0]==1) {
00259                 //PRINTF("Notify ENABLED\n\r"); 
00260                 BlueNRGGattServer::getInstance().HCIEvent(GattServerEvents::GATT_EVENT_UPDATES_ENABLED, p_char->getValueAttribute().getHandle());
00261             } else {
00262                 //PRINTF("Notify DISABLED\n\r"); 
00263                 BlueNRGGattServer::getInstance().HCIEvent(GattServerEvents::GATT_EVENT_UPDATES_DISABLED, p_char->getValueAttribute().getHandle());
00264             }
00265         }
00266                     
00267         //Check is attr handle property is WRITEABLE, if yes, generate GATT_EVENT_DATA_WRITTEN Event
00268         if((p_char->getProperties() &
00269             (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE)) &&
00270             currentHandle == BlueNRGGattServer::CHAR_VALUE_HANDLE) {
00271                     
00272             PRINTF("*****WRITE CASE\n\r");
00273                    
00274             GattWriteCallbackParams writeParams;
00275             writeParams.handle = p_char->getValueAttribute().getHandle();
00276             writeParams.writeOp = GattWriteCallbackParams::OP_WRITE_REQ;//Where to find this property in BLUENRG?
00277             writeParams.len = data_length;
00278             writeParams.data = att_data;                                                                                    
00279             if (bnrg_expansion_board == IDB05A1) {
00280                 writeParams.offset = offset;
00281             } else {
00282                 writeParams.offset = 0;
00283             }
00284             BlueNRGGattServer::getInstance().HCIDataWrittenEvent(&writeParams);
00285 
00286             //BlueNRGGattServer::getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_WRITTEN, evt->attr_handle);
00287             //Write the actual Data to the Attr Handle? (uint8_1[])att_data contains the data
00288             if ((p_char->getValueAttribute().getValuePtr() != NULL) && (p_char->getValueAttribute().getLength() > 0)) {
00289                 BlueNRGGattServer::getInstance().write(p_char->getValueAttribute().getHandle(), (uint8_t*)att_data, data_length, false);
00290             }
00291         } 
00292     }
00293 
00294 }
00295 
00296 #ifdef __cplusplus
00297 extern "C" {
00298 #endif
00299 
00300     /**************************************************************************/
00301     /*!
00302     @brief      Handle HCI Stack Event
00303 
00304     @param[in]  pckt
00305                 Event Packet sent by the stack to be decoded
00306     
00307     @returns
00308     */
00309     /**************************************************************************/
00310     extern void HCI_Event_CB(void *pckt) {
00311         hci_uart_pckt *hci_pckt = (hci_uart_pckt*)pckt;
00312         hci_event_pckt *event_pckt = (hci_event_pckt*)hci_pckt->data;
00313         
00314         if(hci_pckt->type != HCI_EVENT_PKT)
00315         return;
00316 
00317         switch(event_pckt->evt){
00318             
00319         case EVT_DISCONN_COMPLETE:
00320             {
00321                 PRINTF("EVT_DISCONN_COMPLETE\n");
00322                 
00323                 evt_disconn_complete *evt = (evt_disconn_complete*)event_pckt;
00324                 
00325                 BlueNRGGap::getInstance().processDisconnectionEvent(evt->handle, BlueNRGGap::REMOTE_USER_TERMINATED_CONNECTION);
00326             }
00327             break;
00328             
00329         case EVT_LE_META_EVENT:
00330             {
00331                 PRINTF("EVT_LE_META_EVENT\n");
00332                 
00333                 evt_le_meta_event *evt = (evt_le_meta_event *)event_pckt->data;
00334                 
00335                 switch(evt->subevent){
00336                 // ANDREA
00337                 case EVT_LE_CONN_COMPLETE:
00338                     {                            
00339                         PRINTF("EVT_LE_CONN_COMPLETE\n");
00340                         Gap::AddressType_t peerAddrType = BLEProtocol::AddressType::PUBLIC;
00341                         Gap::Role_t role;
00342                         
00343                         evt_le_connection_complete *cc = (evt_le_connection_complete *)evt->data;
00344                         
00345                         BlueNRGGap::getInstance().setConnectionHandle(cc->handle);
00346                         BlueNRGGap::ConnectionParams_t connectionParams;
00347                         BlueNRGGap::getInstance().getPreferredConnectionParams(&connectionParams);
00348                         switch (cc->peer_bdaddr_type) {
00349                             case PUBLIC_ADDR:
00350                                 peerAddrType = BLEProtocol::AddressType::PUBLIC;
00351                                 break;
00352                             case STATIC_RANDOM_ADDR:
00353                                 peerAddrType = BLEProtocol::AddressType::RANDOM_STATIC;
00354                                 break;
00355                             case RESOLVABLE_PRIVATE_ADDR:
00356                                 peerAddrType = BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE;
00357                                 break;
00358                             case NON_RESOLVABLE_PRIVATE_ADDR:
00359                                 peerAddrType = BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE;
00360                                 break;
00361                         }                                             
00362                         //PRINTF("EVT_LE_CONN_COMPLETE LL role=%d\n", cc->role);
00363                         switch (cc->role) {
00364             case 0: //master
00365                                 role = Gap::CENTRAL;
00366                                 break;
00367             case 1:
00368                                 role = Gap::PERIPHERAL;
00369                                 break;
00370             default:
00371                                 role = Gap::PERIPHERAL;
00372                 break;
00373                         }
00374                         //PRINTF("EVT_LE_CONN_COMPLETE GAP role=%d\n", role);
00375                         BlueNRGGap::getInstance().processConnectionEvent(cc->handle, role/*Gap::PERIPHERAL*/, peerAddrType, cc->peer_bdaddr, addr_type, bleAddr, (const BlueNRGGap::ConnectionParams_t *)&connectionParams);                            
00376                     }
00377                     break;
00378           
00379         case EVT_LE_ADVERTISING_REPORT:
00380           PRINTF("EVT_LE_ADVERTISING_REPORT\n\r");
00381           /* FIXME: comment this otherwise it will be obscure and error prone if BlueNRG FW will be updated */
00382           // This event is generated only by X-NUCLEO-IDB05A1 version but not by X-NUCLEO-IDB04A1 (which generates DEVICE_FOUND EVT)
00383           // Formally the structure related to both events are identical except that for the ADV REPORT
00384           // there is one more field (number of reports) which is not forwarded to upper layer.
00385           // Thus we need to move one byte over (((uint8_t*)evt->data)+1) before persing the ADV REPORT. 
00386           le_advertising_info *pr = (le_advertising_info*) (((uint8_t*)evt->data)+1);
00387           PRINTF("EVT_LE_ADVERTISING_REPORT evt_type=%d\n\r", pr->evt_type);
00388           
00389           BlueNRGGap::getInstance().Discovery_CB(BlueNRGGap::DEVICE_FOUND,
00390                                                  pr->evt_type,
00391                                                  &pr->bdaddr_type,
00392                                                  pr->bdaddr,
00393                                                  &pr->data_length,
00394                                                  &pr->data_RSSI[0],
00395                                                  &pr->data_RSSI[pr->data_length]);
00396                     break;
00397                 }
00398             }
00399             break;
00400             
00401         case EVT_VENDOR:
00402             {                
00403                 evt_blue_aci *blue_evt = (evt_blue_aci*)event_pckt->data;
00404                 //PRINTF("EVT_VENDOR %d\n", blue_evt->ecode);
00405                 
00406                 switch(blue_evt->ecode){
00407                            
00408                 case EVT_BLUE_GATT_READ_PERMIT_REQ:
00409                     {
00410                         PRINTF("EVT_BLUE_GATT_READ_PERMIT_REQ_OK\n\r");
00411                         evt_gatt_read_permit_req *pr = (evt_gatt_read_permit_req*)blue_evt->data;
00412                         BlueNRGGattServer::getInstance().Read_Request_CB(pr->attr_handle-CHAR_VALUE_OFFSET);                                                
00413                     }
00414                     break;
00415                     
00416                 case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED:         
00417                     {
00418                         PRINTF("EVT_BLUE_GATT_ATTRIBUTE_MODIFIED\n\r");
00419                         /* this callback is invoked when a GATT attribute is modified
00420                             extract callback data and pass to suitable handler function */
00421                         if (bnrg_expansion_board == IDB05A1) {
00422                             evt_gatt_attr_modified_IDB05A1 *evt = (evt_gatt_attr_modified_IDB05A1*)blue_evt->data;
00423                             Attribute_Modified_CB(evt->attr_handle, evt->data_length, evt->att_data, evt->offset);
00424                         } else {
00425                             evt_gatt_attr_modified_IDB04A1 *evt = (evt_gatt_attr_modified_IDB04A1*)blue_evt->data;
00426                             Attribute_Modified_CB(evt->attr_handle, evt->data_length, evt->att_data, 0);
00427                         }                  
00428                     }
00429                     break;  
00430                     
00431                     //Any cases for Data Sent Notifications?
00432                 case EVT_BLUE_GATT_NOTIFICATION:
00433                     //This is only relevant for Client Side Event
00434                     PRINTF("EVT_BLUE_GATT_NOTIFICATION");
00435                     break;
00436                 case EVT_BLUE_GATT_INDICATION:
00437                     //This is only relevant for Client Side Event
00438                     PRINTF("EVT_BLUE_GATT_INDICATION");
00439                     break;   
00440                     
00441         case EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP:
00442           {
00443             PRINTF("EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP\n\r");
00444             evt_att_read_by_group_resp *pr = (evt_att_read_by_group_resp*)blue_evt->data;
00445             BlueNRGGattClient::getInstance().primaryServicesCB(pr->conn_handle,
00446                                                                pr->event_data_length,
00447                                                                pr->attribute_data_length,
00448                                                                pr->attribute_data_list);
00449           }
00450           break;
00451         case EVT_BLUE_ATT_READ_BY_TYPE_RESP:
00452           {
00453             PRINTF("EVT_BLUE_ATT_READ_BY_TYPE_RESP\n\r");
00454             evt_att_read_by_type_resp *pr = (evt_att_read_by_type_resp*)blue_evt->data;
00455             BlueNRGGattClient::getInstance().serviceCharsCB(pr->conn_handle,
00456                                                             pr->event_data_length,
00457                                                             pr->handle_value_pair_length,
00458                                                             pr->handle_value_pair);
00459           }
00460           break;
00461         case EVT_BLUE_ATT_READ_RESP:
00462           {
00463             PRINTF("EVT_BLUE_ATT_READ_RESP\n\r");
00464             evt_att_read_resp *pr = (evt_att_read_resp*)blue_evt->data;
00465             BlueNRGGattClient::getInstance().charReadCB(pr->conn_handle,
00466                                                         pr->event_data_length,
00467                                                         pr->attribute_value);
00468           }
00469           break;
00470         case EVT_BLUE_ATT_EXEC_WRITE_RESP:
00471           {
00472             PRINTF("EVT_BLUE_ATT_EXEC_WRITE_RESP\n\r");
00473             evt_att_prepare_write_resp *pr = (evt_att_prepare_write_resp*)blue_evt->data;
00474             BlueNRGGattClient::getInstance().charWriteExecCB(pr->conn_handle,
00475                                                              pr->event_data_length);
00476           }
00477           break;
00478         case EVT_BLUE_ATT_PREPARE_WRITE_RESP:
00479           {
00480             PRINTF("EVT_BLUE_ATT_PREPARE_WRITE_RESP\n\r");
00481             evt_att_prepare_write_resp *pr = (evt_att_prepare_write_resp*)blue_evt->data;
00482             BlueNRGGattClient::getInstance().charWritePrepareCB(pr->conn_handle,
00483                                                                 pr->event_data_length,
00484                                                                 pr->attribute_handle,
00485                                                                 pr->offset,
00486                                                                 pr->part_attr_value);
00487           }
00488           break;
00489         case EVT_BLUE_GATT_DISC_READ_CHAR_BY_UUID_RESP:
00490           {
00491             PRINTF("EVT_BLUE_GATT_DISC_READ_CHAR_BY_UUID_RESP\n\r");
00492             evt_gatt_disc_read_char_by_uuid_resp *pr = (evt_gatt_disc_read_char_by_uuid_resp*)blue_evt->data;
00493             BlueNRGGattClient::getInstance().serviceCharByUUIDCB(pr->conn_handle,
00494                                                                  pr->event_data_length,
00495                                                                  pr->attr_handle,
00496                                                                  pr->attr_value);
00497           }
00498           break;
00499         case EVT_BLUE_ATT_FIND_BY_TYPE_VAL_RESP:
00500           {
00501             PRINTF("EVT_BLUE_ATT_FIND_BY_TYPE_VAL_RESP\n\r");
00502             evt_att_find_by_type_val_resp *pr = (evt_att_find_by_type_val_resp*)blue_evt->data;
00503             BlueNRGGattClient::getInstance().primaryServiceCB(pr->conn_handle,
00504                                                               pr->event_data_length,
00505                                                               pr->handles_info_list);
00506           }
00507           break;
00508                 case EVT_BLUE_GATT_PROCEDURE_COMPLETE:
00509           {
00510             //PRINTF("EVT_BLUE_GATT_PROCEDURE_COMPLETE\n\r");
00511             evt_gatt_procedure_complete *evt = (evt_gatt_procedure_complete*)blue_evt->data;
00512             PRINTF("EVT_BLUE_GATT_PROCEDURE_COMPLETE error_code=%d\n\r", evt->error_code);
00513             BlueNRGGattClient::getInstance().gattProcedureCompleteCB(evt->conn_handle, evt->error_code);
00514           }
00515           break;
00516           
00517         case EVT_BLUE_GAP_DEVICE_FOUND:
00518           {
00519             PRINTF("EVT_BLUE_GAP_DEVICE_FOUND\n\r");
00520             evt_gap_device_found *pr = (evt_gap_device_found*)blue_evt->data;
00521             PRINTF("EVT_BLUE_GAP_DEVICE_FOUND evt_type=%d\n\r", pr->evt_type);
00522             
00523             BlueNRGGap::getInstance().Discovery_CB(BlueNRGGap::DEVICE_FOUND,
00524                                                    pr->evt_type,
00525                                                    &pr->bdaddr_type,
00526                                                    pr->bdaddr,
00527                                                    &pr->data_length,
00528                                                    &pr->data_RSSI[0],
00529                                                    &pr->data_RSSI[pr->data_length]);
00530           }
00531           break;
00532           
00533         case EVT_BLUE_GAP_PROCEDURE_COMPLETE:
00534           {
00535             evt_gap_procedure_complete *pr = (evt_gap_procedure_complete*)blue_evt->data;
00536             //printf("EVT_BLUE_GAP_PROCEDURE_COMPLETE (code=0x%02X)\n\r", pr->procedure_code);
00537             
00538             switch(pr->procedure_code) {
00539             case GAP_LIMITED_DISCOVERY_PROC:
00540             case GAP_GENERAL_DISCOVERY_PROC:
00541               
00542               BlueNRGGap::getInstance().Discovery_CB(BlueNRGGap::DISCOVERY_COMPLETE, 0, NULL, NULL, NULL, NULL, NULL);
00543               break;
00544             }
00545           }
00546                     break;                                     
00547                 }
00548             }
00549             break;
00550         }    
00551         return ;
00552     }
00553 
00554 
00555 #ifdef __cplusplus
00556 }
00557 #endif