Antonio Vilei / X_NUCLEO_IDB0XA1

Fork of X_NUCLEO_IDB0XA1 by ST Expansion SW Team

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BlueNRGGattClient.cpp Source File

BlueNRGGattClient.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   * @file    BlueNRGGattServer.cpp 
00019   * @author  STMicroelectronics
00020   * @brief   Implementation of BlueNRG BLE_API GattServer Class
00021   ******************************************************************************
00022   * @copy
00023   *
00024   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00025   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00026   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
00027   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00028   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00029   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00030   *
00031   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
00032   */ 
00033  
00034 /** @defgroup BlueNRGGATTClient
00035  *  @brief BlueNRG BLE_API GattClient Adaptation
00036  *  @{
00037  */
00038  
00039 #include "BlueNRGGattClient.h"
00040 #include "mbed.h"
00041 #include "BlueNRGGap.h"
00042 #include "Utils.h"
00043 #include "debug.h"
00044 
00045 static uint8_t props_mask[] = {
00046   0x01,
00047   0x02,
00048   0x04,
00049   0x08,
00050   0x10,
00051   0x20,
00052   0x40,
00053   0x80
00054   };
00055 
00056 void BlueNRGGattClient::gattProcedureCompleteCB(Gap::Handle_t connectionHandle, uint8_t error_code)
00057 {
00058   if(error_code != BLE_STATUS_SUCCESS) {
00059     _currentState = GATT_IDLE;
00060     return;
00061   }
00062     
00063   // Service Discovery complete
00064 /*
00065   if(_currentState != GATT_IDLE && 
00066      _currentState != GATT_DISCOVERY_TERMINATED &&
00067      _currentState != GATT_WRITE_CHAR &&
00068      _currentState != GATT_READ_CHAR) {
00069 */
00070   if(_currentState == GATT_SERVICE_DISCOVERY) {
00071     findServiceChars(connectionHandle);
00072   }
00073 
00074   if(_currentState == GATT_CHAR_DESC_DISCOVERY) {
00075     _currentState = GATT_IDLE;
00076   }
00077 
00078   // Read complete
00079   if(_currentState == GATT_READ_CHAR) {
00080     _currentState = GATT_IDLE;
00081   }
00082 
00083   // Write complete
00084   if(_currentState == GATT_WRITE_CHAR) {
00085     BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
00086     _currentState = GATT_IDLE;
00087   }
00088 }
00089                                                 
00090 void BlueNRGGattClient::primaryServicesCB(Gap::Handle_t connectionHandle,
00091                                           uint8_t event_data_length,
00092                                           uint8_t attribute_data_length,
00093                                           uint8_t *attribute_data_list)
00094 {
00095   GattAttribute::Handle_t startHandle, endHandle;
00096   UUID uuid;
00097   uint8_t i, offset, numAttr;
00098   /* avoid compiler warnings about unused variables */
00099   (void)connectionHandle;
00100 
00101   numAttr = (event_data_length - 1) / attribute_data_length;
00102 
00103   offset = 0;
00104   for (i=0; i<numAttr; i++) {
00105     startHandle = attribute_data_list[offset];
00106     endHandle = attribute_data_list[offset+2];
00107 
00108     // UUID Type
00109     if (attribute_data_length == 6) {
00110       
00111       PRINTF("UUID_TYPE_16\n\r");
00112       uuid = attribute_data_list[offset+5]<<8|attribute_data_list[offset+4];
00113       PRINTF("S UUID-%X attrs[%u %u]\r\n", uuid.getShortUUID(), startHandle, endHandle);
00114       
00115     } else {
00116       
00117       PRINTF("UUID_TYPE_128\n\r");
00118       uuid.setupLong(attribute_data_list+offset+4, UUID::LSB);
00119 
00120 #ifdef DEBUG
00121       PRINTF("S UUID-");
00122       const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00123       for (unsigned j = 0; j < UUID::LENGTH_OF_LONG_UUID; j++) {
00124         PRINTF("%02x", longUUIDBytes[j]);
00125       }
00126 #endif
00127       PRINTF(" attrs[%u %u]\r\n", startHandle, endHandle);
00128       
00129     }
00130     
00131     PRINTF("Setup serviceIndex = %d\n\r", _numServices);
00132     discoveredService[_numServices].setup(uuid, startHandle, endHandle);
00133     
00134     if(serviceDiscoveryCallback) {
00135       if(_matchingServiceUUID == BLE_UUID_UNKNOWN || _matchingServiceUUID == discoveredService[_numServices].getUUID()) {
00136         serviceDiscoveryCallback(&discoveredService[_numServices]);
00137       }
00138     }
00139     _numServices++;
00140 
00141     offset += attribute_data_length;
00142   }
00143 
00144   PRINTF("!!!Service Discovery complete (numAttr=%u)!!!\n\r", numAttr);
00145 
00146 }
00147 
00148 void BlueNRGGattClient::primaryServiceCB(Gap::Handle_t connectionHandle,
00149                                          uint8_t event_data_length,
00150                                          uint8_t *handles_info_list)
00151 {
00152   GattAttribute::Handle_t startHandle, endHandle;
00153   UUID uuid;
00154   uint8_t i, offset, numHandlePairs;
00155   /* avoid compiler warnings about unused variables */
00156   (void)connectionHandle;
00157 
00158   numHandlePairs = (event_data_length - 1) / 2;
00159 
00160   offset = 0;
00161   for (i=0; i<numHandlePairs; i++) {
00162     startHandle = handles_info_list[offset];
00163     endHandle = handles_info_list[offset+2];
00164 
00165     PRINTF("primaryServiceCB attrs[%u %u]\r\n", startHandle, endHandle);
00166 
00167 
00168     if (_matchingServiceUUID.shortOrLong() == UUID::UUID_TYPE_SHORT) {
00169         PRINTF("S UUID-%x attrs[%u %u]\r\n", _matchingServiceUUID.getShortUUID(), startHandle, endHandle);
00170         uuid = _matchingServiceUUID.getShortUUID();
00171     } else {
00172 #ifdef DEBUG
00173         PRINTF("S UUID-");
00174         const uint8_t *longUUIDBytes = _matchingServiceUUID.getBaseUUID();
00175         for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00176             PRINTF("%02x", longUUIDBytes[i]);
00177         }
00178 #endif
00179         PRINTF(" attrs[%u %u]\r\n", startHandle, endHandle);
00180         uuid.setupLong(_matchingServiceUUID.getBaseUUID(), UUID::MSB);
00181     }
00182 
00183     discoveredService[i].setup(uuid, startHandle, endHandle);
00184     
00185     if(serviceDiscoveryCallback) {
00186       serviceDiscoveryCallback(&discoveredService[_numServices]);
00187     }
00188     _numServices++;
00189     
00190     offset += 4;
00191   }
00192 }
00193 
00194 void BlueNRGGattClient::serviceCharsCB(Gap::Handle_t connectionHandle,
00195                                        uint8_t event_data_length,
00196                                        uint8_t handle_value_pair_length,
00197                                        uint8_t *handle_value_pair)
00198 {
00199   // Charac Handle (2), Charac Properties(1), Charac Value Handle(2), Charac UUID(2/16)
00200 
00201   GattAttribute::Handle_t declHandle, valueHandle, lastHandle;
00202   UUID uuid;
00203   uint8_t i, numChar, offset;
00204 
00205   numChar = (event_data_length - 1) / handle_value_pair_length;
00206 
00207   PRINTF("event_data_length=%d handle_value_pair_length=%d numChar=%d\n\r", event_data_length, handle_value_pair_length, numChar);
00208 
00209   offset = 0;
00210   for (i=0; i<numChar; i++) {
00211     // UUID Type
00212     if (handle_value_pair_length == 7) {
00213       PRINTF("Char UUID_TYPE_16\n\r");
00214       uuid = handle_value_pair[offset+6]<<8|handle_value_pair[offset+5];
00215       PRINTF("C UUID-%X\r\n", uuid.getShortUUID());
00216     } else {
00217       PRINTF("Char UUID_TYPE_128\n\r");
00218       uuid.setupLong(handle_value_pair+offset+5, UUID::LSB);
00219 #ifdef DEBUG
00220       PRINTF("C UUID-");
00221       const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00222       for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00223         PRINTF("%02X", longUUIDBytes[i]);
00224       }
00225       PRINTF("\r\n");
00226 #endif
00227     }
00228     
00229     // Properties
00230     DiscoveredCharacteristic::Properties_t p;
00231     
00232     p._broadcast = (props_mask[0] & handle_value_pair[offset+2]);
00233     p._read = (props_mask[1] & handle_value_pair[offset+2])>>1;
00234     p._writeWoResp = (props_mask[2] & handle_value_pair[offset+2])>>2;
00235     p._write = (props_mask[3] & handle_value_pair[offset+2])>>3;
00236     p._notify = (props_mask[4] & handle_value_pair[offset+2])>>4;
00237     p._indicate = (props_mask[5] & handle_value_pair[offset+2])>>5;
00238     p._authSignedWrite = (props_mask[6] & handle_value_pair[offset+2])>>6;
00239     PRINTF("p._broadcast=%d\n\r", p._broadcast);
00240     PRINTF("p._read=%d\n\r", p._read);
00241     PRINTF("p._writeWoResp=%d\n\r", p._writeWoResp);
00242     PRINTF("p._write=%d\n\r", p._write);
00243     PRINTF("p._notify=%d\n\r", p._notify);
00244     PRINTF("p._indicate=%d\n\r", p._indicate);
00245     PRINTF("p._authSignedWrite=%d\n\r", p._authSignedWrite);
00246 
00247     /*
00248     uint8_t props = handle_value_pair[offset+2];
00249     PRINTF("CHAR PROPS: %d\n\r", props);
00250     */
00251 
00252     // Handles
00253     declHandle = handle_value_pair[offset];
00254     valueHandle = handle_value_pair[offset+3];
00255     lastHandle = valueHandle+1;
00256     PRINTF("declHandle: %u valueHandle=%u lastHandle=%u\n\r", declHandle, valueHandle, lastHandle);
00257 
00258     discoveredChar[_numChars].setup(this,
00259                                     connectionHandle,
00260                                     uuid,
00261                                     p,
00262                                     declHandle,
00263                                     valueHandle,
00264                                     lastHandle);
00265 
00266     if(characteristicDiscoveryCallback) {
00267       characteristicDiscoveryCallback(&discoveredChar[_numChars]);
00268     }
00269     _numChars++;
00270 
00271     offset += handle_value_pair_length;
00272   }
00273 }
00274 
00275 void BlueNRGGattClient::serviceCharByUUIDCB(Gap::Handle_t connectionHandle,
00276                                             uint8_t event_data_length,
00277                                             uint16_t attr_handle,
00278                                             uint8_t *attr_value)
00279 {
00280   // Charac Properties(1), Charac Value Handle(2), Charac UUID(2/16)
00281   GattAttribute::Handle_t declHandle, valueHandle, lastHandle;
00282   UUID uuid;
00283   
00284   PRINTF("serviceCharByUUIDCB\n\r");
00285   
00286   // UUID Type
00287   if (event_data_length == 7) {
00288     PRINTF("Char UUID_TYPE_16\n\r");
00289     uuid = attr_value[4]<<8|attr_value[3];
00290     PRINTF("C UUID-%X\r\n", uuid.getShortUUID());
00291   } else {
00292     PRINTF("Char UUID_TYPE_128\n\r");
00293     uuid.setupLong(attr_value+3, UUID::LSB);
00294 #ifdef DEBUG
00295     PRINTF("C UUID-");
00296     const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00297     for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00298       PRINTF("%02X", longUUIDBytes[i]);
00299     }
00300     PRINTF("\r\n");
00301 #endif
00302   }
00303 
00304   // Properties
00305   DiscoveredCharacteristic::Properties_t p;
00306   
00307   p._broadcast = (props_mask[0] & attr_value[0]);
00308   p._read = (props_mask[1] & attr_value[0])>>1;
00309   p._writeWoResp = (props_mask[2] & attr_value[0])>>2;
00310   p._write = (props_mask[3] & attr_value[0])>>3;
00311   p._notify = (props_mask[4] & attr_value[0])>>4;
00312   p._indicate = (props_mask[5] & attr_value[0])>>5;
00313   p._authSignedWrite = (props_mask[6] & attr_value[0])>>6;
00314   PRINTF("p._broadcast=%d\n\r", p._broadcast);
00315   PRINTF("p._read=%d\n\r", p._read);
00316   PRINTF("p._writeWoResp=%d\n\r", p._writeWoResp);
00317   PRINTF("p._write=%d\n\r", p._write);
00318   PRINTF("p._notify=%d\n\r", p._notify);
00319   PRINTF("p._indicate=%d\n\r", p._indicate);
00320   PRINTF("p._authSignedWrite=%d\n\r", p._authSignedWrite);
00321 
00322   /*
00323   uint8_t props = attr_value[0];
00324   PRINTF("CHAR PROPS: %d\n\r", props);
00325   */
00326 
00327   // Handles
00328   declHandle = attr_handle;
00329   valueHandle = attr_value[1];
00330   lastHandle = valueHandle+1;
00331 
00332   discoveredChar[_numChars].setup(this,
00333                                   connectionHandle,
00334                                   uuid,
00335                                   p,
00336                                   declHandle,
00337                                   valueHandle,
00338                                   lastHandle);
00339   
00340   if(characteristicDiscoveryCallback) {
00341     characteristicDiscoveryCallback(&discoveredChar[_numChars]);
00342   }
00343   _numChars++;
00344 }
00345 
00346 ble_error_t BlueNRGGattClient::findServiceChars(Gap::Handle_t connectionHandle)
00347 {
00348   PRINTF("findServiceChars\n\r");
00349   
00350   tBleStatus ret;
00351   uint8_t uuid_type = UUID_TYPE_16;
00352   uint8_t short_uuid[2];
00353   uint8_t *uuid = NULL;
00354   
00355   DiscoveredService *service;
00356   
00357   // We finished chars discovery for all services
00358   if(_servIndex >= _numServices) {
00359     PRINTF("!!!We finished chars discovery for all services!!!\n\r");
00360     //_currentState = GATT_CHARS_DISCOVERY_COMPLETE;
00361     
00362     terminateServiceDiscovery();
00363     
00364     return BLE_ERROR_NONE;
00365   }
00366     
00367   service = &discoveredService[_servIndex];
00368   /*
00369   if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
00370     PRINTF("S UUID-%X\r\n", service->getUUID().getShortUUID());
00371   } else {
00372     PRINTF("S UUID-");
00373     const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
00374     for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00375       PRINTF("%02X", longUUIDBytes[i]);
00376     }
00377     PRINTF("\r\n");
00378   }
00379   */
00380   
00381   PRINTF("findServiceChars (_servIndex=%d)\n\r", _servIndex);
00382   //ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle());
00383 
00384   if(_matchingCharacteristicUUIDIn == BLE_UUID_UNKNOWN) {
00385     PRINTF("findServiceChars (BLE_UUID_UNKNOWN)\n\r");
00386     ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle());
00387   } else {
00388     
00389     uint8_t type = _matchingCharacteristicUUIDIn.shortOrLong();
00390     
00391     if(type == UUID::UUID_TYPE_SHORT) {
00392       STORE_LE_16(short_uuid, _matchingCharacteristicUUIDIn.getShortUUID());
00393       
00394       uuid_type = UUID_TYPE_16;
00395       uuid = short_uuid;
00396 #ifdef DEBUG
00397       PRINTF("findServiceChars C UUID-");
00398       for(unsigned i = 0; i < 2; i++) {
00399         PRINTF("%02X", short_uuid[i]);
00400       }
00401       PRINTF("\n\r");
00402 #endif
00403     } else if(type==UUID::UUID_TYPE_LONG) {
00404       
00405       uuid_type = UUID_TYPE_128;
00406       uuid = (unsigned char*)_matchingCharacteristicUUIDIn.getBaseUUID();
00407 #ifdef DEBUG
00408       PRINTF("(findServiceChars) C UUID-");
00409       for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00410         PRINTF("%02X", uuid[i]);
00411       }
00412       PRINTF("\r\n");
00413 #endif
00414     }
00415 
00416     ret = aci_gatt_disc_charac_by_uuid(connectionHandle,
00417                                        service->getStartHandle(),
00418                                        service->getEndHandle(),
00419                                        uuid_type,
00420                                        uuid);
00421   }
00422   
00423   if(ret == BLE_STATUS_SUCCESS) {
00424     _servIndex++;
00425   }
00426   
00427   PRINTF("findServiceChars ret=%d\n\r", ret);
00428   
00429   return BLE_ERROR_NONE;
00430 }
00431 
00432 ble_error_t BlueNRGGattClient::launchServiceDiscovery(Gap::Handle_t                               connectionHandle,
00433                                                       ServiceDiscovery::ServiceCallback_t         sc,
00434                                                       ServiceDiscovery::CharacteristicCallback_t  cc,
00435                                                       const UUID                                 &matchingServiceUUID,
00436                                                       const UUID                                 &matchingCharacteristicUUIDIn)
00437 {
00438   PRINTF("launchServiceDiscovery\n\r");
00439   
00440   tBleStatus ret;
00441   uint8_t uuid_type = UUID_TYPE_16;
00442   uint8_t short_uuid[2];
00443   uint8_t *uuid = NULL;
00444   unsigned j;
00445 
00446   if(isServiceDiscoveryActive()) {
00447     return BLE_ERROR_OPERATION_NOT_PERMITTED;
00448   }
00449 
00450   if(!sc && !cc) {
00451     // nothing to do
00452     PRINTF("launchServiceDiscovery: nothing to do\n\r");
00453     return BLE_ERROR_NONE;
00454   }
00455 
00456   _connectionHandle = connectionHandle;
00457   serviceDiscoveryCallback = sc;
00458   characteristicDiscoveryCallback = cc;
00459   _matchingServiceUUID = matchingServiceUUID;
00460   _matchingCharacteristicUUIDIn = matchingCharacteristicUUIDIn;
00461 
00462   //reset services
00463   _numServices = 0;
00464   _numChars = 0;
00465   _servIndex = 0;
00466   for(j = 0; j < BLE_TOTAL_DISCOVERED_SERVICES; j++) {
00467     discoveredService[j].setup(BLE_UUID_UNKNOWN, GattAttribute::INVALID_HANDLE, GattAttribute::INVALID_HANDLE);
00468   }
00469   
00470   if(matchingServiceUUID == BLE_UUID_UNKNOWN) {
00471     
00472     // Wildcard: search for all services
00473     ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle);
00474     
00475   } else {
00476   
00477     uint8_t type = matchingServiceUUID.shortOrLong();
00478     //PRINTF("AddService(): Type:%d\n\r", type);
00479     
00480     if(type == UUID::UUID_TYPE_SHORT) {
00481       STORE_LE_16(short_uuid, matchingServiceUUID.getShortUUID());
00482 #ifdef DEBUG
00483       PRINTF("launchServiceDiscovery short_uuid=0x");
00484       for(j = 0; j < 2; j++) {
00485         PRINTF("%02X", short_uuid[j]);
00486       }
00487       PRINTF("\n\r");
00488 #endif
00489       
00490       uuid_type = UUID_TYPE_16;
00491       uuid = short_uuid;
00492       
00493     } else if(type==UUID::UUID_TYPE_LONG) {
00494 
00495       uuid_type = UUID_TYPE_128;
00496       uuid = (unsigned char*)matchingServiceUUID.getBaseUUID();
00497 
00498 #ifdef DEBUG
00499       PRINTF("launchServiceDiscovery base_uuid=0x");
00500       for(j = 0; j < 16; j++) {
00501         PRINTF("%02X", uuid[j]);
00502       }
00503       PRINTF("\n\r");
00504 #endif
00505     }
00506     
00507     // search for specific service by UUID
00508     ret = aci_gatt_disc_prim_service_by_uuid((uint16_t)connectionHandle, uuid_type, uuid);
00509     //ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle);
00510   }
00511     
00512   if(ret == BLE_STATUS_SUCCESS) {
00513     _currentState = GATT_SERVICE_DISCOVERY;
00514   }
00515   
00516   PRINTF("launchServiceDiscovery ret=%d\n\r", ret);
00517   
00518   return BLE_ERROR_NONE;
00519 }
00520 
00521 ble_error_t BlueNRGGattClient::discoverServices(Gap::Handle_t                        connectionHandle,
00522                                                 ServiceDiscovery::ServiceCallback_t  callback,
00523                                                 const UUID                          &matchingServiceUUID)
00524 {
00525   /* avoid compiler warnings about unused variables */
00526   (void)connectionHandle;
00527   (void)callback;
00528   (void)matchingServiceUUID;
00529 
00530   return BLE_ERROR_NOT_IMPLEMENTED;
00531 }
00532 
00533 ble_error_t BlueNRGGattClient::discoverServices(Gap::Handle_t                        connectionHandle,
00534                                                 ServiceDiscovery::ServiceCallback_t  callback,
00535                                                 GattAttribute::Handle_t              startHandle,
00536                                                 GattAttribute::Handle_t              endHandle)
00537 {
00538   /* avoid compiler warnings about unused variables */
00539   (void)connectionHandle;
00540   (void)callback;
00541   (void)startHandle;
00542   (void)endHandle;
00543 
00544   return BLE_ERROR_NOT_IMPLEMENTED;
00545 }
00546 
00547 bool BlueNRGGattClient::isServiceDiscoveryActive(void) const
00548 {
00549   if(_currentState == GATT_SERVICE_DISCOVERY) {
00550     return true;
00551   }
00552 
00553   return false;
00554 /*
00555   if(_currentState == GATT_IDLE ||
00556      _currentState == GATT_DISCOVERY_TERMINATED ||
00557        _currentState == GATT_READ_CHAR ||
00558          _currentState == GATT_WRITE_CHAR ) {
00559     return false;
00560   }
00561   
00562   return true;
00563 */
00564 }
00565 
00566 void BlueNRGGattClient::terminateServiceDiscovery(void)
00567 {
00568   _currentState = GATT_IDLE;//GATT_DISCOVERY_TERMINATED;
00569   
00570   if (terminationCallback) {
00571     terminationCallback(_connectionHandle);
00572   }
00573 }
00574 
00575 void BlueNRGGattClient::charReadCB(Gap::Handle_t connHandle,
00576                                    uint8_t event_data_length,
00577                                    uint8_t* attribute_value)
00578 {
00579   readCBParams.connHandle = connHandle;
00580   readCBParams.offset = 0;
00581   readCBParams.len = event_data_length;
00582   readCBParams.data = attribute_value;
00583 
00584   BlueNRGGattClient::getInstance().processReadResponse(&readCBParams);
00585 }
00586 
00587 ble_error_t BlueNRGGattClient::read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const
00588 {
00589   /* avoid compiler warnings about unused variables */
00590   (void)offset;
00591 
00592   tBleStatus ret;
00593   
00594   BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this);
00595   
00596   // Save the attribute_handle not provided by evt_att_read_resp    
00597   gattc->readCBParams.handle = attributeHandle;
00598   
00599   // FIXME: We need to wait for a while before starting a read
00600   // due to BlueNRG process queue handling
00601   Clock_Wait(100);
00602 
00603   ret = aci_gatt_read_charac_val(connHandle, attributeHandle);
00604   
00605   if(ret == BLE_STATUS_SUCCESS) {
00606     gattc->_currentState = GATT_READ_CHAR;
00607     return BLE_ERROR_NONE;
00608   }
00609   switch (ret) {
00610   case BLE_STATUS_BUSY:
00611     return BLE_STACK_BUSY;
00612   default:
00613     return BLE_ERROR_INVALID_STATE;
00614   }
00615 }
00616 
00617 void BlueNRGGattClient::charWritePrepareCB(Gap::Handle_t connHandle,
00618                                            uint8_t event_data_length,
00619                                            uint16_t attribute_handle,
00620                                            uint16_t offset,
00621                                            uint8_t *part_attr_value)
00622 {
00623   /* avoid compiler warnings about unused variables */
00624   (void)connHandle;
00625 
00626   // Update the write response params
00627   writeCBParams.handle = attribute_handle;
00628   writeCBParams.offset = offset;
00629   writeCBParams.len = event_data_length-4; //(?)
00630   writeCBParams.data = part_attr_value;
00631 
00632   BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
00633 }
00634 
00635 void BlueNRGGattClient::charWriteExecCB(Gap::Handle_t connHandle,
00636                                         uint8_t event_data_length)
00637 {
00638   /* avoid compiler warnings about unused variables */
00639   (void)event_data_length;
00640 
00641   writeCBParams.connHandle = connHandle;
00642   
00643   BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
00644 }
00645 
00646 ble_error_t BlueNRGGattClient::write(GattClient::WriteOp_t    cmd,
00647                                      Gap::Handle_t            connHandle,
00648                                      GattAttribute::Handle_t  attributeHandle,
00649                                      size_t                   length,
00650                                      const uint8_t           *value) const
00651 {
00652   /* avoid compiler warnings about unused variables */
00653   (void)cmd;
00654 
00655   tBleStatus ret;
00656   
00657   BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this);
00658   
00659   // We save the write response params (used by the callback) because
00660   // when the aci_gatt_write_charac_value() is used the only event received is the EVT_BLUE_GATT_PROCEDURE_COMPLETE
00661   gattc->writeCBParams.connHandle = connHandle;
00662   gattc->writeCBParams.writeOp = GattWriteCallbackParams::OP_WRITE_CMD;
00663   gattc->writeCBParams.handle = attributeHandle;
00664   gattc->writeCBParams.offset = 0;
00665   gattc->writeCBParams.len = length;
00666   gattc->writeCBParams.data = value;
00667   
00668   ret = aci_gatt_write_charac_value(connHandle, attributeHandle, length, const_cast<uint8_t *>(value));
00669   //ret = aci_gatt_write_charac_reliable(connHandle, attributeHandle, 0, length, const_cast<uint8_t *>(value));
00670   
00671   if (ret == BLE_STATUS_SUCCESS) {
00672     gattc->_currentState = GATT_WRITE_CHAR;
00673     return BLE_ERROR_NONE;
00674   }
00675   switch (ret) {
00676   case BLE_STATUS_BUSY:
00677     return BLE_STACK_BUSY;
00678   default:
00679     return BLE_ERROR_INVALID_STATE;
00680   }
00681 
00682 }
00683 
00684 void BlueNRGGattClient::discAllCharacDescCB(Gap::Handle_t connHandle,
00685                                             uint8_t event_data_length,
00686                                             uint8_t format,
00687                                             uint8_t *handle_uuid_pair) {
00688   GattAttribute::Handle_t attHandle;
00689   UUID uuid;
00690   uint8_t i, numCharacDesc, offset, handle_uuid_length;
00691 
00692   handle_uuid_length = 4; //Handle + UUID_16
00693   if (format == 2)
00694     handle_uuid_length = 18; //Handle + UUID_128
00695 
00696   numCharacDesc = (event_data_length - 1) / handle_uuid_length;
00697   
00698   offset = 0;
00699 
00700   for (i=0; i<numCharacDesc; i++) {
00701     attHandle = handle_uuid_pair[offset];
00702 
00703     // UUID Type
00704     if (handle_uuid_length == 4) {
00705       
00706       PRINTF("UUID_TYPE_16\n\r");
00707       uuid = handle_uuid_pair[offset+3]<<8|handle_uuid_pair[offset+2];
00708       PRINTF("D UUID-%X attHandle=%u\r\n", uuid.getShortUUID(), attHandle);
00709       
00710     } else {
00711       
00712       PRINTF("UUID_TYPE_128\n\r");
00713       uuid.setupLong(handle_uuid_pair+offset+2, UUID::LSB);
00714 #ifdef DEBUG
00715       PRINTF("D UUID-");
00716       const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00717       for (unsigned j = 0; j < UUID::LENGTH_OF_LONG_UUID; j++) {
00718         PRINTF("%02x", longUUIDBytes[j]);
00719       }
00720 #endif
00721      }
00722 
00723      if(charDescDiscoveryCallback != NULL) {
00724        CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
00725                                  _characteristic,
00726                                  DiscoveredCharacteristicDescriptor(
00727                                    _characteristic.getGattClient(),
00728                                    connHandle,
00729                                    attHandle,
00730                                    uuid
00731                                  )
00732        };
00733        charDescDiscoveryCallback(&params);
00734      }
00735 
00736     _numCharDesc++;
00737 
00738     offset += handle_uuid_length;
00739   }
00740 
00741   if(charDescTerminationCallback != NULL) {
00742      CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
00743                                _characteristic,
00744                                BLE_ERROR_NONE
00745      };
00746      charDescTerminationCallback(&params);
00747    }
00748 
00749 }
00750 
00751 ble_error_t BlueNRGGattClient::discoverCharacteristicDescriptors(
00752         const DiscoveredCharacteristic& characteristic,
00753         const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
00754         const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback) {
00755 
00756   tBleStatus ret;
00757 
00758   if(_currentState != GATT_IDLE) {
00759     return BLE_ERROR_OPERATION_NOT_PERMITTED;
00760   }
00761 
00762   charDescDiscoveryCallback = discoveryCallback;
00763   charDescTerminationCallback = terminationCallback;
00764 
00765   Gap::Handle_t connHandle = characteristic.getConnectionHandle();
00766   GattAttribute::Handle_t valueHandle = characteristic.getValueHandle();
00767   GattAttribute::Handle_t lastHandle = characteristic.getLastHandle();
00768 
00769   PRINTF("Starting aci_gatt_disc_all_charac_descriptors...\n\r");
00770   ret = aci_gatt_disc_all_charac_descriptors(connHandle, valueHandle, lastHandle);
00771 
00772   if (ret == BLE_STATUS_SUCCESS) {
00773     _currentState = GATT_CHAR_DESC_DISCOVERY;
00774     _characteristic = characteristic;
00775     return BLE_ERROR_NONE;
00776   }
00777   switch (ret) {
00778   case BLE_STATUS_INVALID_PARAMS:
00779     return BLE_ERROR_INVALID_PARAM;
00780   default:
00781     return BLE_ERROR_OPERATION_NOT_PERMITTED;
00782   }
00783 }
00784 
00785 /**************************************************************************/
00786 /*!
00787     @brief  Clear BlueNRGGattServer's state.
00788 
00789     @returns    ble_error_t
00790 
00791     @retval     BLE_ERROR_NONE
00792                 Everything executed properly
00793 */
00794 /**************************************************************************/
00795 ble_error_t BlueNRGGattClient::reset(void) {
00796   /* Clear all state that is from the parent, including private members */
00797   if (GattClient::reset() != BLE_ERROR_NONE) {
00798     return BLE_ERROR_INVALID_STATE;
00799   }
00800 
00801   _currentState = GATT_IDLE;
00802   _matchingServiceUUID = BLE_UUID_UNKNOWN;
00803   _matchingCharacteristicUUIDIn = BLE_UUID_UNKNOWN;
00804 
00805   _numServices = 0;
00806   _servIndex = 0;
00807   _numChars = 0;
00808   _numCharDesc = 0;
00809 
00810   /* Clear class members */
00811   memset(discoveredService, 0, sizeof(discoveredService));
00812   memset(discoveredChar, 0, sizeof(discoveredChar));
00813 
00814   return BLE_ERROR_NONE;
00815 }
00816