My fork of X_NUCLEO_IDB0XA1

Fork of X_NUCLEO_IDB0XA1 by ST

Files at this revision

API Documentation at this revision

Comitter:
Vincent Coubard
Date:
Thu Sep 15 10:51:21 2016 +0100
Branch:
70f819844d61400a7b6772dcc911a63fc73af09e
Parent:
258:e5ef65120b06
Child:
260:e93cbde933ce
Commit message:
Sync with 70f819844d61400a7b6772dcc911a63fc73af09e

2016-07-08 12:18:26+01:00: Vincent Coubard
Fix ServiceInstantiation_test_xx

Fix the last handle set for characteristics
Fix discovery order.
From a user perspective, the service tree is traversed in deep.

The previous behavior was:

for service in services:
service_callback(callback)

for characteristic in characteristics:
characteristic_callback(characteristic)

The new behavior is:

for service in services:
service_callback(callback)
for characteristic in service.characteristics:
characteristic_callback(characteristic)

Reserve the valid count of attribute records when declaring a service.
Report error when it is not possible to add a service.

Changed in this revision

source/BlueNRGDiscoveredCharacteristic.cpp Show annotated file Show diff for this revision Revisions of this file
source/BlueNRGGap.cpp Show annotated file Show diff for this revision Revisions of this file
source/BlueNRGGattClient.cpp Show annotated file Show diff for this revision Revisions of this file
source/BlueNRGGattServer.cpp Show annotated file Show diff for this revision Revisions of this file
x-nucleo-idb0xa1/BlueNRGDiscoveredCharacteristic.h Show annotated file Show diff for this revision Revisions of this file
x-nucleo-idb0xa1/BlueNRGGattServer.h Show annotated file Show diff for this revision Revisions of this file
--- a/source/BlueNRGDiscoveredCharacteristic.cpp	Thu Sep 15 10:51:20 2016 +0100
+++ b/source/BlueNRGDiscoveredCharacteristic.cpp	Thu Sep 15 10:51:21 2016 +0100
@@ -62,3 +62,7 @@
     props._indicate        = propsIn.indicate();
     props._authSignedWrite = propsIn.authSignedWrite();
 }
+
+ void BlueNRGDiscoveredCharacteristic::setLastHandle(GattAttribute::Handle_t  lastHandleIn) {
+     lastHandle = lastHandleIn;
+ }
\ No newline at end of file
--- a/source/BlueNRGGap.cpp	Thu Sep 15 10:51:20 2016 +0100
+++ b/source/BlueNRGGap.cpp	Thu Sep 15 10:51:21 2016 +0100
@@ -501,9 +501,9 @@
     );
 
     if (err) {
-        printf("impossible to set advertising parameters\n\r");
-        printf("advInterval min: %u, advInterval max: %u\n\r", advInterval, advInterval + 1);
-        printf("advType: %u, advFilterPolicy: %u\n\r", params.getAdvertisingType(), advFilterPolicy);
+        PRINTF("impossible to set advertising parameters\n\r");
+        PRINTF("advInterval min: %u, advInterval max: %u\n\r", advInterval, advInterval + 1);
+        PRINTF("advType: %u, advFilterPolicy: %u\n\r", params.getAdvertisingType(), advFilterPolicy);
         return BLE_ERROR_INVALID_PARAM;
     }
 
@@ -1352,7 +1352,7 @@
     advIntMS = (conn_min_interval*1.25)-GUARD_INT;
     advInterval = _advParams.MSEC_TO_ADVERTISEMENT_DURATION_UNITS(advIntMS);
 
-    printf("conn_min_interval is equal to %u\r\n", conn_min_interval);
+    PRINTF("conn_min_interval is equal to %u\r\n", conn_min_interval);
   } else {
     advInterval = _advParams.getIntervalInADVUnits();
   }
--- a/source/BlueNRGGattClient.cpp	Thu Sep 15 10:51:20 2016 +0100
+++ b/source/BlueNRGGattClient.cpp	Thu Sep 15 10:51:21 2016 +0100
@@ -15,7 +15,7 @@
 */
 /**
   ******************************************************************************
-  * @file    BlueNRGGattServer.cpp 
+  * @file    BlueNRGGattServer.cpp
   * @author  STMicroelectronics
   * @brief   Implementation of BlueNRG BLE_API GattServer Class
   ******************************************************************************
@@ -29,13 +29,13 @@
   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
   *
   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
-  */ 
- 
+  */
+
 /** @defgroup BlueNRGGATTClient
  *  @brief BlueNRG BLE_API GattClient Adaptation
  *  @{
  */
- 
+
 #include "BlueNRGGattClient.h"
 #include "mbed-drivers/mbed.h"
 #include "BlueNRGGap.h"
@@ -59,10 +59,10 @@
     _currentState = GATT_IDLE;
     return;
   }
-    
+
   // Service Discovery complete
 /*
-  if(_currentState != GATT_IDLE && 
+  if(_currentState != GATT_IDLE &&
      _currentState != GATT_DISCOVERY_TERMINATED &&
      _currentState != GATT_WRITE_CHAR &&
      _currentState != GATT_READ_CHAR) {
@@ -86,7 +86,7 @@
     _currentState = GATT_IDLE;
   }
 }
-                                                
+
 void BlueNRGGattClient::primaryServicesCB(Gap::Handle_t connectionHandle,
                                           uint8_t event_data_length,
                                           uint8_t attribute_data_length,
@@ -107,13 +107,13 @@
 
     // UUID Type
     if (attribute_data_length == 6) {
-      
+
       PRINTF("UUID_TYPE_16\n\r");
       uuid = attribute_data_list[offset+5]<<8|attribute_data_list[offset+4];
       PRINTF("S UUID-%X attrs[%u %u]\r\n", uuid.getShortUUID(), startHandle, endHandle);
-      
+
     } else {
-      
+
       PRINTF("UUID_TYPE_128\n\r");
       uuid.setupLong(attribute_data_list+offset+4, UUID::LSB);
 
@@ -125,17 +125,12 @@
       }
 #endif
       PRINTF(" attrs[%u %u]\r\n", startHandle, endHandle);
-      
+
     }
-    
+
     PRINTF("Setup serviceIndex = %d\n\r", _numServices);
     discoveredService[_numServices].setup(uuid, startHandle, endHandle);
-    
-    if(serviceDiscoveryCallback) {
-      if(_matchingServiceUUID == BLE_UUID_UNKNOWN || _matchingServiceUUID == discoveredService[_numServices].getUUID()) {
-        serviceDiscoveryCallback(&discoveredService[_numServices]);
-      }
-    }
+
     _numServices++;
 
     offset += attribute_data_length;
@@ -181,12 +176,9 @@
     }
 
     discoveredService[i].setup(uuid, startHandle, endHandle);
-    
-    if(serviceDiscoveryCallback) {
-      serviceDiscoveryCallback(&discoveredService[_numServices]);
-    }
+
     _numServices++;
-    
+
     offset += 4;
   }
 }
@@ -225,10 +217,10 @@
       PRINTF("\r\n");
 #endif
     }
-    
+
     // Properties
     DiscoveredCharacteristic::Properties_t p;
-    
+
     p._broadcast = (props_mask[0] & handle_value_pair[offset+2]);
     p._read = (props_mask[1] & handle_value_pair[offset+2])>>1;
     p._writeWoResp = (props_mask[2] & handle_value_pair[offset+2])>>2;
@@ -263,9 +255,14 @@
                                     valueHandle,
                                     lastHandle);
 
-    if(characteristicDiscoveryCallback) {
-      characteristicDiscoveryCallback(&discoveredChar[_numChars]);
+    if (_numChars != 0) {
+        discoveredChar[_numChars - 1].setLastHandle(declHandle - 1);
+
+        if(characteristicDiscoveryCallback) {
+          characteristicDiscoveryCallback(&discoveredChar[_numChars - 1]);
+        }
     }
+
     _numChars++;
 
     offset += handle_value_pair_length;
@@ -280,9 +277,9 @@
   // Charac Properties(1), Charac Value Handle(2), Charac UUID(2/16)
   GattAttribute::Handle_t declHandle, valueHandle, lastHandle;
   UUID uuid;
-  
+
   PRINTF("serviceCharByUUIDCB\n\r");
-  
+
   // UUID Type
   if (event_data_length == 7) {
     PRINTF("Char UUID_TYPE_16\n\r");
@@ -303,7 +300,7 @@
 
   // Properties
   DiscoveredCharacteristic::Properties_t p;
-  
+
   p._broadcast = (props_mask[0] & attr_value[0]);
   p._read = (props_mask[1] & attr_value[0])>>1;
   p._writeWoResp = (props_mask[2] & attr_value[0])>>2;
@@ -336,7 +333,7 @@
                                   declHandle,
                                   valueHandle,
                                   lastHandle);
-  
+
   if(characteristicDiscoveryCallback) {
     characteristicDiscoveryCallback(&discoveredChar[_numChars]);
   }
@@ -346,24 +343,37 @@
 ble_error_t BlueNRGGattClient::findServiceChars(Gap::Handle_t connectionHandle)
 {
   PRINTF("findServiceChars\n\r");
-  
+
   tBleStatus ret;
   uint8_t uuid_type = UUID_TYPE_16;
   uint8_t short_uuid[2];
   uint8_t *uuid = NULL;
-  
+
   DiscoveredService *service;
-  
+
+  // complete the discovery of the last characteristic of the previous service.
+  // Its last handle wasn't known before this point
+  // update the handle and call the characteristic discovery callback.
+  if (_servIndex != 0 && _numChars != 0) {
+      discoveredChar[_numChars - 1].setLastHandle(discoveredService[_servIndex - 1].getEndHandle());
+
+      if(characteristicDiscoveryCallback) {
+        characteristicDiscoveryCallback(&discoveredChar[_numChars - 1]);
+      }
+  }
+
+  _numChars = 0;
+
   // We finished chars discovery for all services
   if(_servIndex >= _numServices) {
     PRINTF("!!!We finished chars discovery for all services!!!\n\r");
     //_currentState = GATT_CHARS_DISCOVERY_COMPLETE;
-    
+
     terminateServiceDiscovery();
-    
+
     return BLE_ERROR_NONE;
   }
-    
+
   service = &discoveredService[_servIndex];
   /*
   if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
@@ -377,55 +387,59 @@
     PRINTF("\r\n");
   }
   */
-  
+
+  if(serviceDiscoveryCallback) {
+    serviceDiscoveryCallback(service);
+  }
+
   PRINTF("findServiceChars (_servIndex=%d)\n\r", _servIndex);
   //ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle());
 
-  if(_matchingCharacteristicUUIDIn == BLE_UUID_UNKNOWN) {
-    PRINTF("findServiceChars (BLE_UUID_UNKNOWN)\n\r");
-    ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle());
-  } else {
-    
-    uint8_t type = _matchingCharacteristicUUIDIn.shortOrLong();
-    
-    if(type == UUID::UUID_TYPE_SHORT) {
-      STORE_LE_16(short_uuid, _matchingCharacteristicUUIDIn.getShortUUID());
-      
-      uuid_type = UUID_TYPE_16;
-      uuid = short_uuid;
+    if(_matchingCharacteristicUUIDIn == BLE_UUID_UNKNOWN) {
+        PRINTF("findServiceChars (BLE_UUID_UNKNOWN)\n\r");
+        ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle());
+    } else {
+
+        uint8_t type = _matchingCharacteristicUUIDIn.shortOrLong();
+
+        if(type == UUID::UUID_TYPE_SHORT) {
+            STORE_LE_16(short_uuid, _matchingCharacteristicUUIDIn.getShortUUID());
+
+            uuid_type = UUID_TYPE_16;
+            uuid = short_uuid;
 #ifdef DEBUG
-      PRINTF("findServiceChars C UUID-");
-      for(unsigned i = 0; i < 2; i++) {
-        PRINTF("%02X", short_uuid[i]);
-      }
-      PRINTF("\n\r");
+            PRINTF("findServiceChars C UUID-");
+            for(unsigned i = 0; i < 2; i++) {
+                PRINTF("%02X", short_uuid[i]);
+            }
+            PRINTF("\n\r");
 #endif
-    } else if(type==UUID::UUID_TYPE_LONG) {
-      
-      uuid_type = UUID_TYPE_128;
-      uuid = (unsigned char*)_matchingCharacteristicUUIDIn.getBaseUUID();
+        } else if(type==UUID::UUID_TYPE_LONG) {
+
+            uuid_type = UUID_TYPE_128;
+            uuid = (unsigned char*)_matchingCharacteristicUUIDIn.getBaseUUID();
 #ifdef DEBUG
-      PRINTF("(findServiceChars) C UUID-");
-      for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
-        PRINTF("%02X", uuid[i]);
-      }
-      PRINTF("\r\n");
+            PRINTF("(findServiceChars) C UUID-");
+            for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
+                PRINTF("%02X", uuid[i]);
+            }
+            PRINTF("\r\n");
 #endif
+        }
+
+        ret = aci_gatt_disc_charac_by_uuid(connectionHandle,
+                                           service->getStartHandle(),
+                                           service->getEndHandle(),
+                                           uuid_type,
+                                           uuid);
     }
 
-    ret = aci_gatt_disc_charac_by_uuid(connectionHandle,
-                                       service->getStartHandle(),
-                                       service->getEndHandle(),
-                                       uuid_type,
-                                       uuid);
-  }
-  
   if(ret == BLE_STATUS_SUCCESS) {
     _servIndex++;
   }
-  
+
   PRINTF("findServiceChars ret=%d\n\r", ret);
-  
+
   return BLE_ERROR_NONE;
 }
 
@@ -436,7 +450,7 @@
                                                       const UUID                                 &matchingCharacteristicUUIDIn)
 {
   PRINTF("launchServiceDiscovery\n\r");
-  
+
   tBleStatus ret;
   uint8_t uuid_type = UUID_TYPE_16;
   uint8_t short_uuid[2];
@@ -466,17 +480,17 @@
   for(j = 0; j < BLE_TOTAL_DISCOVERED_SERVICES; j++) {
     discoveredService[j].setup(BLE_UUID_UNKNOWN, GattAttribute::INVALID_HANDLE, GattAttribute::INVALID_HANDLE);
   }
-  
+
   if(matchingServiceUUID == BLE_UUID_UNKNOWN) {
-    
+
     // Wildcard: search for all services
     ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle);
-    
+
   } else {
-  
+
     uint8_t type = matchingServiceUUID.shortOrLong();
     //PRINTF("AddService(): Type:%d\n\r", type);
-    
+
     if(type == UUID::UUID_TYPE_SHORT) {
       STORE_LE_16(short_uuid, matchingServiceUUID.getShortUUID());
 #ifdef DEBUG
@@ -486,10 +500,10 @@
       }
       PRINTF("\n\r");
 #endif
-      
+
       uuid_type = UUID_TYPE_16;
       uuid = short_uuid;
-      
+
     } else if(type==UUID::UUID_TYPE_LONG) {
 
       uuid_type = UUID_TYPE_128;
@@ -503,18 +517,18 @@
       PRINTF("\n\r");
 #endif
     }
-    
+
     // search for specific service by UUID
     ret = aci_gatt_disc_prim_service_by_uuid((uint16_t)connectionHandle, uuid_type, uuid);
     //ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle);
   }
-    
+
   if(ret == BLE_STATUS_SUCCESS) {
     _currentState = GATT_SERVICE_DISCOVERY;
   }
-  
+
   PRINTF("launchServiceDiscovery ret=%d\n\r", ret);
-  
+
   return BLE_ERROR_NONE;
 }
 
@@ -558,7 +572,7 @@
          _currentState == GATT_WRITE_CHAR ) {
     return false;
   }
-  
+
   return true;
 */
 }
@@ -566,7 +580,7 @@
 void BlueNRGGattClient::terminateServiceDiscovery(void)
 {
   _currentState = GATT_IDLE;//GATT_DISCOVERY_TERMINATED;
-  
+
   if (terminationCallback) {
     terminationCallback(_connectionHandle);
   }
@@ -590,18 +604,18 @@
   (void)offset;
 
   tBleStatus ret;
-  
+
   BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this);
-  
-  // Save the attribute_handle not provided by evt_att_read_resp    
+
+  // Save the attribute_handle not provided by evt_att_read_resp
   gattc->readCBParams.handle = attributeHandle;
-  
+
   // FIXME: We need to wait for a while before starting a read
   // due to BlueNRG process queue handling
   Clock_Wait(100);
 
   ret = aci_gatt_read_charac_val(connHandle, attributeHandle);
-  
+
   if(ret == BLE_STATUS_SUCCESS) {
     gattc->_currentState = GATT_READ_CHAR;
     return BLE_ERROR_NONE;
@@ -639,7 +653,7 @@
   (void)event_data_length;
 
   writeCBParams.connHandle = connHandle;
-  
+
   BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
 }
 
@@ -653,9 +667,9 @@
   (void)cmd;
 
   tBleStatus ret;
-  
+
   BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this);
-  
+
   // We save the write response params (used by the callback) because
   // when the aci_gatt_write_charac_value() is used the only event received is the EVT_BLUE_GATT_PROCEDURE_COMPLETE
   gattc->writeCBParams.connHandle = connHandle;
@@ -664,10 +678,10 @@
   gattc->writeCBParams.offset = 0;
   gattc->writeCBParams.len = length;
   gattc->writeCBParams.data = value;
-  
+
   ret = aci_gatt_write_charac_value(connHandle, attributeHandle, length, const_cast<uint8_t *>(value));
   //ret = aci_gatt_write_charac_reliable(connHandle, attributeHandle, 0, length, const_cast<uint8_t *>(value));
-  
+
   if (ret == BLE_STATUS_SUCCESS) {
     gattc->_currentState = GATT_WRITE_CHAR;
     return BLE_ERROR_NONE;
@@ -694,7 +708,7 @@
     handle_uuid_length = 18; //Handle + UUID_128
 
   numCharacDesc = (event_data_length - 1) / handle_uuid_length;
-  
+
   offset = 0;
 
   for (i=0; i<numCharacDesc; i++) {
@@ -702,13 +716,13 @@
 
     // UUID Type
     if (handle_uuid_length == 4) {
-      
+
       PRINTF("UUID_TYPE_16\n\r");
       uuid = handle_uuid_pair[offset+3]<<8|handle_uuid_pair[offset+2];
       PRINTF("D UUID-%X attHandle=%u\r\n", uuid.getShortUUID(), attHandle);
-      
+
     } else {
-      
+
       PRINTF("UUID_TYPE_128\n\r");
       uuid.setupLong(handle_uuid_pair+offset+2, UUID::LSB);
 #ifdef DEBUG
@@ -812,5 +826,4 @@
   memset(discoveredChar, 0, sizeof(discoveredChar));
 
   return BLE_ERROR_NONE;
-}
-
+}
\ No newline at end of file
--- a/source/BlueNRGGattServer.cpp	Thu Sep 15 10:51:20 2016 +0100
+++ b/source/BlueNRGGattServer.cpp	Thu Sep 15 10:51:21 2016 +0100
@@ -76,8 +76,17 @@
     const uint8_t *base_uuid;
     const uint8_t *base_char_uuid;
 
-    uint8_t charsCount = 0;
-    uint8_t maxAttrRecords = 0;
+    uint8_t charsCount = service.getCharacteristicCount();
+    const uint8_t available_characteristics = BLE_TOTAL_CHARACTERISTICS - characteristicCount;
+
+    // check that there is enough characteristics left in the
+    // characteristic array.
+    if (charsCount > available_characteristics) {
+        PRINTF("charCount = %u and characteristicCount = %u\r\n", charsCount, available_characteristics);
+        return BLE_ERROR_NO_MEM;
+    }
+
+    const uint16_t maxAttrRecords = computeAttributesRecord(service);
 
     type = (service.getUUID()).shortOrLong();
     PRINTF("AddService(): Type:%d\n\r", type);
@@ -92,17 +101,14 @@
         COPY_UUID_128(primary_base_uuid, base_uuid[15],base_uuid[14],primary_short_uuid[1],primary_short_uuid[0],base_uuid[11],base_uuid[10],base_uuid[9],base_uuid[8],base_uuid[7],base_uuid[6],base_uuid[5],base_uuid[4],base_uuid[3],base_uuid[2],base_uuid[1],base_uuid[0]);
     }
 
-    charsCount = service.getCharacteristicCount();
-    //1(service record)+2records*char+1record*char_desc
-    maxAttrRecords = 1+3*charsCount;
-
     if(type==UUID::UUID_TYPE_SHORT) {
         ret = aci_gatt_add_serv(UUID_TYPE_16,
                                 primary_short_uuid,
                                 PRIMARY_SERVICE,
                                 maxAttrRecords/*7*/,
                                 &servHandle);
-        PRINTF("aci_gatt_add_serv UUID_TYPE_LONG ret=%d\n\r", ret);
+        PRINTF("aci_gatt_add_serv UUID_TYPE_SHORT ret=%d\n\r", ret);
+
     }
     else if(type==UUID::UUID_TYPE_LONG) {
         ret = aci_gatt_add_serv(UUID_TYPE_128,
@@ -113,6 +119,25 @@
         PRINTF("aci_gatt_add_serv UUID_TYPE_LONG ret=%d\n\r", ret);
     }
 
+    switch (ret) {
+        case BLE_STATUS_SUCCESS:
+            break;
+
+        case BLE_STATUS_INVALID_PARAMETER:
+            return BLE_ERROR_INVALID_PARAM;
+
+        case BLE_STATUS_OUT_OF_HANDLE:
+        case BLE_STATUS_INSUFFICIENT_RESOURCES:
+        case ERR_UNSPECIFIED_ERROR:
+            return BLE_ERROR_NO_MEM;
+
+        case BLE_STATUS_ERROR:
+        default:
+            return BLE_ERROR_INTERNAL_STACK_FAILURE;
+    }
+
+
+
     service.setHandle(servHandle);
     //serviceHandleVector.push_back(servHandle);
     PRINTF("added servHandle handle =%u\n\r", servHandle);
@@ -191,6 +216,40 @@
                     p_char->getProperties(), p_char->getValueAttribute().getMaxLength(), ret);
         }
 
+        switch (ret) {
+            case BLE_STATUS_SUCCESS:
+                break;
+
+            case ERR_UNSPECIFIED_ERROR:
+            case BLE_STATUS_INSUFFICIENT_RESOURCES:
+            case BLE_STATUS_OUT_OF_HANDLE:
+                // TODO remove characteristics and the service previously added.
+                // remove service in the stack by using: Aci_Gatt_Del_Service
+                // remove characteristics in the stack by using: Aci_Gatt_Del_Char
+                // update service counter
+                // destroy registered characteristic and updat echaracteristic counter
+                return BLE_ERROR_NO_MEM;
+
+            case BLE_STATUS_INVALID_HANDLE:
+            case BLE_STATUS_INVALID_PARAMETER:
+            case BLE_STATUS_CHARAC_ALREADY_EXISTS:
+            // TODO remove characteristics and the service previously added.
+            // remove service in the stack by using: Aci_Gatt_Del_Service
+            // remove characteristics in the stack by using: Aci_Gatt_Del_Char
+            // update service counter
+            // destroy registered characteristic and updat echaracteristic counter
+                return BLE_ERROR_INVALID_PARAM;
+
+            case BLE_STATUS_ERROR:
+            default:
+            // TODO remove characteristics and the service previously added.
+            // remove service in the stack by using: Aci_Gatt_Del_Service
+            // remove characteristics in the stack by using: Aci_Gatt_Del_Char
+            // update service counter
+            // destroy registered characteristic and updat echaracteristic counter
+                return BLE_ERROR_INTERNAL_STACK_FAILURE;
+        }
+
         bleCharHandleMap.insert(std::pair<uint16_t, uint16_t>(bleCharacteristic, servHandle));
 
         p_characteristics[characteristicCount++] = p_char;
@@ -199,9 +258,13 @@
         PRINTF("added bleCharacteristic (value handle =%u)\n\r", p_char->getValueAttribute().getHandle());
 
         if ((p_char->getValueAttribute().getValuePtr() != NULL) && (p_char->getValueAttribute().getLength() > 0)) {
-            write(p_char->getValueAttribute().getHandle(),
+            ble_error_t err = write(p_char->getValueAttribute().getHandle(),
                   p_char->getValueAttribute().getValuePtr(),
                   p_char->getValueAttribute().getLength(), false /* localOnly */);
+            if (err) {
+                PRINTF("ERROR HERE !!!!\r\n");
+                return err;
+            }
         }
 
         // add descriptors now
@@ -226,12 +289,45 @@
                                          CHAR_ATTRIBUTE_LEN_IS_FIXED,
                                          &descHandle);
             PRINTF("Adding Descriptor descriptor handle=%d ret=%d\n\r", descHandle, ret);
-            if(ret==(tBleStatus)0) {
-                PRINTF("Descriptor added successfully, descriptor handle=%d\n\r", descHandle);
-                descriptor->setHandle(descHandle);
+
+            switch (ret) {
+                case BLE_STATUS_SUCCESS:
+                    PRINTF("Descriptor added successfully, descriptor handle=%d\n\r", descHandle);
+                    descriptor->setHandle(descHandle);
+                    break;
+
+                case ERR_UNSPECIFIED_ERROR:
+                case BLE_STATUS_INSUFFICIENT_RESOURCES:
+                case BLE_STATUS_OUT_OF_HANDLE:
+                    // TODO remove characteristics and the service previously added.
+                    // remove service in the stack by using: Aci_Gatt_Del_Service
+                    // remove characteristics in the stack by using: Aci_Gatt_Del_Char
+                    // update service counter
+                    // destroy registered characteristic and updat echaracteristic counter
+                    return BLE_ERROR_NO_MEM;
+
+                case BLE_STATUS_INVALID_HANDLE:
+                case BLE_STATUS_INVALID_PARAMETER:
+                // TODO remove characteristics and the service previously added.
+                // remove service in the stack by using: Aci_Gatt_Del_Service
+                // remove characteristics in the stack by using: Aci_Gatt_Del_Char
+                // update service counter
+                // destroy registered characteristic and updat echaracteristic counter
+                    return BLE_ERROR_INVALID_PARAM;
+
+                case BLE_STATUS_INVALID_OPERATION:
+                    return BLE_ERROR_OPERATION_NOT_PERMITTED;
+
+                case BLE_STATUS_ERROR:
+                default:
+                // TODO remove characteristics and the service previously added.
+                // remove service in the stack by using: Aci_Gatt_Del_Service
+                // remove characteristics in the stack by using: Aci_Gatt_Del_Char
+                // update service counter
+                // destroy registered characteristic and updat echaracteristic counter
+                    return BLE_ERROR_INTERNAL_STACK_FAILURE;
             }
         }
-
     }
 
     serviceCount++;
@@ -528,4 +624,45 @@
     characteristicCount = 0;
 
     return BLE_ERROR_NONE;
+}
+
+
+/// compute the number of attributes needed by this service.
+uint16_t BlueNRGGattServer::computeAttributesRecord(GattService& service) {
+    uint16_t attribute_records = 1;
+
+    for (uint8_t characteristic_index = 0; characteristic_index < service.getCharacteristicCount(); ++characteristic_index) {
+        // add two attributes, one for the characteristic declaration
+        // and the other for the characteristic value.
+        attribute_records += 2;
+
+        const GattCharacteristic* characteristic = service.getCharacteristic(characteristic_index);
+        const uint8_t properties = characteristic->getProperties();
+        // if notify or indicate are present, two attributes are
+        // needed
+        if ((properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ||
+            (properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) {
+            attribute_records += 2;
+        }
+
+        // if broadcast is set, two attributes are needed
+        if (properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_BROADCAST) {
+            attribute_records += 2;
+        }
+
+        // if extended properties flag is set, two attributes are needed
+        if (properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES) {
+            attribute_records += 2;
+        }
+
+        attribute_records += characteristic->getDescriptorCount();
+    }
+
+    // for some reason, if there is just a service, this value should
+    // be equal to 5
+    if (attribute_records == 1) {
+        attribute_records = 5;
+    }
+
+    return attribute_records;
 }
\ No newline at end of file
--- a/x-nucleo-idb0xa1/BlueNRGDiscoveredCharacteristic.h	Thu Sep 15 10:51:20 2016 +0100
+++ b/x-nucleo-idb0xa1/BlueNRGDiscoveredCharacteristic.h	Thu Sep 15 10:51:21 2016 +0100
@@ -30,7 +30,7 @@
              GattAttribute::Handle_t  declHandleIn,
              GattAttribute::Handle_t  valueHandleIn,
              GattAttribute::Handle_t  lastHandleIn);
-  
+
   void setup(BlueNRGGattClient         *gattcIn,
              Gap::Handle_t            connectionHandleIn,
              UUID   uuidIn,
@@ -38,6 +38,9 @@
              GattAttribute::Handle_t  declHandleIn,
              GattAttribute::Handle_t  valueHandleIn,
              GattAttribute::Handle_t  lastHandleIn);
+
+
+  void setLastHandle(GattAttribute::Handle_t  lastHandleIn);
 };
 
-#endif /* __BLUENRG_DISCOVERED_CHARACTERISTIC_H__ */
+#endif /* __BLUENRG_DISCOVERED_CHARACTERISTIC_H__ */
\ No newline at end of file
--- a/x-nucleo-idb0xa1/BlueNRGGattServer.h	Thu Sep 15 10:51:20 2016 +0100
+++ b/x-nucleo-idb0xa1/BlueNRGGattServer.h	Thu Sep 15 10:51:21 2016 +0100
@@ -15,7 +15,7 @@
 */
 /**
   ******************************************************************************
-  * @file    BlueNRGGattServer.cpp 
+  * @file    BlueNRGGattServer.cpp
   * @author  STMicroelectronics
   * @brief   Header file for BLE_API GattServer Class
   ******************************************************************************
@@ -30,7 +30,7 @@
   *
   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
   */
- 
+
 #ifndef __BLUENRG_GATT_SERVER_H__
 #define __BLUENRG_GATT_SERVER_H__
 
@@ -53,13 +53,13 @@
         static BlueNRGGattServer m_instance;
         return m_instance;
     }
-    
+
     enum HandleEnum_t {
         CHAR_HANDLE = 0,
         CHAR_VALUE_HANDLE,
         CHAR_DESC_HANDLE
     };
-    
+
     /* Functions that must be implemented from GattServer */
     virtual ble_error_t addService(GattService &);
     virtual ble_error_t read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP);
@@ -67,13 +67,13 @@
     virtual ble_error_t write(GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false);
     virtual ble_error_t write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false);
     virtual ble_error_t initializeGATTDatabase(void);
-    
+
     virtual bool isOnDataReadAvailable() const {
         return true;
     }
 
     virtual ble_error_t reset(void);
-    
+
     /* BlueNRG Functions */
     void eventCallback(void);
     //void hwCallback(void *pckt);
@@ -83,8 +83,13 @@
     void HCIDataReadEvent(const GattReadCallbackParams *params);
     void HCIEvent(GattServerEvents::gattEvent_e type, uint16_t charHandle);
     void HCIDataSentEvent(unsigned count);
-    
+
 private:
+
+    // compute the number of attribute record needed by a service
+    static uint16_t computeAttributesRecord(GattService& service);
+
+
     static const int MAX_SERVICE_COUNT = 10;
     uint8_t serviceCount;
     uint8_t characteristicCount;
@@ -101,12 +106,12 @@
 
     BlueNRGGattServer(BlueNRGGattServer const &);
     void operator=(BlueNRGGattServer const &);
-    
-    static const int CHAR_DESC_TYPE_16_BIT=0x01; 
-    static const int CHAR_DESC_TYPE_128_BIT=0x02;    
+
+    static const int CHAR_DESC_TYPE_16_BIT=0x01;
+    static const int CHAR_DESC_TYPE_128_BIT=0x02;
     static const int CHAR_DESC_SECURITY_PERMISSION=0x00;
-    static const int CHAR_DESC_ACCESS_PERMISSION=0x03;  
-    static const int CHAR_ATTRIBUTE_LEN_IS_FIXED=0x00;        
+    static const int CHAR_DESC_ACCESS_PERMISSION=0x03;
+    static const int CHAR_ATTRIBUTE_LEN_IS_FIXED=0x00;
 };
 
-#endif
+#endif
\ No newline at end of file