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:36 2016 +0100
Branch:
dc54644b61c51990e49672e5bbce3b95124d6364
Parent:
264:1e754a01869e
Parent:
272:4639da7705e1
Child:
274:4826afdae563
Commit message:
Sync with dc54644b61c51990e49672e5bbce3b95124d6364

Merge 83c30f290087a6f5a503812f507492e725a3b717 into e9fb3e390284c3f7ef8e1d21cc55deef7558ca3d
2016-07-20 08:50:37+01:00: Vincent Coubard
Merge branch 'workshop-july' into rtos

Changed in this revision

source/BlueNRGDevice.cpp Show annotated file Show diff for this revision Revisions of this file
source/platform/btle.cpp Show annotated file Show diff for this revision Revisions of this file
x-nucleo-idb0xa1/platform/btle.h Show annotated file Show diff for this revision Revisions of this file
--- a/source/BlueNRGDevice.cpp	Thu Sep 15 10:51:26 2016 +0100
+++ b/source/BlueNRGDevice.cpp	Thu Sep 15 10:51:36 2016 +0100
@@ -181,11 +181,9 @@
         	callback.call(&context);
         	return BLE_ERROR_ALREADY_INITIALIZED;
     	}
-	
-	/* ToDo: Clear memory contents, reset the SD, etc. */
+
 	// Init the BlueNRG/BlueNRG-MS stack
-	// By default, we set the device GAP role to PERIPHERAL
-	btleInit(BlueNRGGap::getInstance().getIsSetAddress(), GAP_PERIPHERAL_ROLE_IDB04A1);
+	btleInit();
 	
 	isInitialized = true;
 	BLE::InitializationCompleteCallbackContext context = {
--- a/source/BlueNRGDiscoveredCharacteristic.cpp	Thu Sep 15 10:51:26 2016 +0100
+++ b/source/BlueNRGDiscoveredCharacteristic.cpp	Thu Sep 15 10:51:36 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:26 2016 +0100
+++ b/source/BlueNRGGap.cpp	Thu Sep 15 10:51:36 2016 +0100
@@ -17,7 +17,7 @@
 
 /**
   ******************************************************************************
-  * @file    BlueNRGGap.cpp 
+  * @file    BlueNRGGap.cpp
   * @author  STMicroelectronics
   * @brief   Implementation of BLE_API Gap Class
   ******************************************************************************
@@ -44,15 +44,11 @@
 #include "Utils.h"
 #include "debug.h"
 
-//Local Variables
-//const char *local_name = NULL;
-//uint8_t local_name_length = 0;
-
 /*
  * Utility to process GAP specific events (e.g., Advertising timeout)
  */
 void BlueNRGGap::Process(void)
-{    
+{
     if(AdvToFlag) {
         stopAdvertising();
     }
@@ -61,7 +57,7 @@
 
 /**************************************************************************/
 /*!
-    @brief  Sets the advertising parameters and payload for the device. 
+    @brief  Sets the advertising parameters and payload for the device.
             Note: Some data types give error when their adv data is updated using aci_gap_update_adv_data() API
 
     @params[in] advData
@@ -95,7 +91,7 @@
 */
 /**************************************************************************/
 ble_error_t BlueNRGGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse)
-{ 
+{
     PRINTF("BlueNRGGap::setAdvertisingData\n\r");
     /* Make sure we don't exceed the advertising payload length */
     if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
@@ -103,18 +99,8 @@
         return BLE_ERROR_BUFFER_OVERFLOW;
     }
 
-    // Reset the length of the ADV payload each time
-    // since we get fields of argument 'advData' iteratively
-    AdvLen = 0;
-
     /* Make sure we have a payload! */
-    if (advData.getPayloadLen() == 0) {
-        PRINTF("advData.getPayloadLen() == 0\n\r");
-        //return BLE_ERROR_PARAM_OUT_OF_RANGE;
-        local_name_length = 0;
-        txPowLevSet = 0;
-        servUuidlength = 0;
-    } else {
+    if (advData.getPayloadLen() != 0) {
         PayloadPtr loadPtr(advData.getPayload(), advData.getPayloadLen());
 
         /* Align the GAP Service Appearance Char value coherently
@@ -125,88 +111,17 @@
         setAppearance((GapAdvertisingData::Appearance)(deviceAppearance[1]<<8|deviceAppearance[0]));
 
 
-        for(uint8_t index=0; index<loadPtr.getPayloadUnitCount(); index++) {                  
+        for(uint8_t index=0; index<loadPtr.getPayloadUnitCount(); index++) {
             loadPtr.getUnitAtIndex(index);
 
             PRINTF("adData[%d].length=%d\n\r", index,(uint8_t)(*loadPtr.getUnitAtIndex(index).getLenPtr()));
-            PRINTF("adData[%d].AdType=0x%x\n\r", index,(uint8_t)(*loadPtr.getUnitAtIndex(index).getAdTypePtr()));                  
-            
+            PRINTF("adData[%d].AdType=0x%x\n\r", index,(uint8_t)(*loadPtr.getUnitAtIndex(index).getAdTypePtr()));
+
             switch(*loadPtr.getUnitAtIndex(index).getAdTypePtr()) {
-            case GapAdvertisingData::FLAGS:                              /* ref *Flags */                     
-                {
-                PRINTF("Advertising type: FLAGS\n\r");
-                //Check if Flags are OK. BlueNRG only supports LE Mode.
-                uint8_t *flags = loadPtr.getUnitAtIndex(index).getDataPtr();
-                if((*flags & GapAdvertisingData::BREDR_NOT_SUPPORTED) != GapAdvertisingData::BREDR_NOT_SUPPORTED) {
-                    PRINTF("BlueNRG does not support BR/EDR Mode");
-                    return BLE_ERROR_PARAM_OUT_OF_RANGE;
-                }
-                
-                break;
-                }
-            case GapAdvertisingData::INCOMPLETE_LIST_16BIT_SERVICE_IDS:  /**< Incomplete list of 16-bit Service IDs */
-            case GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS:    /**< Complete list of 16-bit Service IDs */
-            case GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS: /**< Incomplete list of 128-bit Service IDs */
-            case GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS:   /**< Complete list of 128-bit Service IDs */
+            /**< TX Power Level (in dBm) */
+            case GapAdvertisingData::TX_POWER_LEVEL:
                 {
-                PRINTF("Advertising type: INCOMPLETE_LIST SERVICE_IDS/COMPLETE_LIST SERVICE_IDS\n\r");
-                
-                uint8_t buffSize = *loadPtr.getUnitAtIndex(index).getLenPtr()-1;
-                // The total lenght should include the Data Type Value
-                if(buffSize>UUID_BUFFER_SIZE-1) {
-                    return BLE_ERROR_INVALID_PARAM;
-                }
-                
-                servUuidlength = buffSize+1; // +1 to include the Data Type Value
-                servUuidData[0] = (uint8_t)(*loadPtr.getUnitAtIndex(index).getAdTypePtr()); //Data Type Value
-                
-                PRINTF("servUuidlength=%d servUuidData[0]=%d buffSize=%d\n\r", servUuidlength, servUuidData[0], buffSize);
-                // Save the Service UUID list just after the Data Type Value field
-                memcpy(servUuidData+1, loadPtr.getUnitAtIndex(index).getDataPtr(), buffSize);
-#ifdef DEBUG
-                for(unsigned i=0; i<servUuidlength; i++) {
-                    PRINTF("servUuidData[%d] = 0x%x\n\r", i, servUuidData[i]);
-                }
-                
-                for(unsigned i=0; i<buffSize; i++) {
-                    PRINTF("loadPtr.getUnitAtIndex(index).getDataPtr()[%d] = 0x%x\n\r",
-                            i, loadPtr.getUnitAtIndex(index).getDataPtr()[i]);
-                }
-#endif /* DEBUG */
-                break;
-                }
-            case GapAdvertisingData::INCOMPLETE_LIST_32BIT_SERVICE_IDS:  /**< Incomplete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
-                {
-                PRINTF("Advertising type: INCOMPLETE_LIST_32BIT_SERVICE_IDS\n\r");
-                return BLE_ERROR_NOT_IMPLEMENTED;
-                }
-            case GapAdvertisingData::COMPLETE_LIST_32BIT_SERVICE_IDS:    /**< Complete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
-                {
-                PRINTF("Advertising type: COMPLETE_LIST_32BIT_SERVICE_IDS\n\r");
-                return BLE_ERROR_NOT_IMPLEMENTED;
-                }
-            case GapAdvertisingData::SHORTENED_LOCAL_NAME:               /**< Shortened Local Name */
-                {
-                break;
-                }
-            case GapAdvertisingData::COMPLETE_LOCAL_NAME:                /**< Complete Local Name */
-                {
-                PRINTF("Advertising type: COMPLETE_LOCAL_NAME\n\r");
-                loadPtr.getUnitAtIndex(index).printDataAsString();
-                local_name_length = *loadPtr.getUnitAtIndex(index).getLenPtr()-1;
-                // The total length should include the Data Type Value
-                if(local_name_length>ADV_DATA_MAX_SIZE-1) {
-                    return BLE_ERROR_INVALID_PARAM;
-                }
-                local_name[0] = (uint8_t)(*loadPtr.getUnitAtIndex(index).getAdTypePtr()); //Data Type Value
-                memcpy(local_name+1, (uint8_t*)loadPtr.getUnitAtIndex(index).getDataPtr(), local_name_length-1);
-                PRINTF("Advertising type: COMPLETE_LOCAL_NAME local_name=%s local_name_length=%d\n\r", local_name+1, local_name_length);
-
-                break;
-                }
-            case GapAdvertisingData::TX_POWER_LEVEL:                     /**< TX Power Level (in dBm) */
-                {
-                PRINTF("Advertising type: TX_POWER_LEVEL\n\r");     
+                PRINTF("Advertising type: TX_POWER_LEVEL\n\r");
                 int8_t enHighPower = 0;
                 int8_t paLevel = 0;
 
@@ -218,47 +133,11 @@
 #endif
                 if(ret == BLE_STATUS_SUCCESS) {
                   aci_hal_set_tx_power_level(enHighPower, paLevel);
-                  txPowLevSet = 1;
                 }
                 break;
                 }
-            case GapAdvertisingData::DEVICE_ID:                          /**< Device ID */
-                {
-                break;
-                }
-            case GapAdvertisingData::SLAVE_CONNECTION_INTERVAL_RANGE:    /**< Slave :Connection Interval Range */
-                {
-                PRINTF("Advertising type: SLAVE_CONNECTION_INTERVAL_RANGE\n\r");
-                uint8_t *ptr = loadPtr.getUnitAtIndex(index).getDataPtr();
-                slaveConnIntervMin = ptr[0]|ptr[1]<<8;
-                slaveConnIntervMax = ptr[2]|ptr[3]<<8;
-
-                break;
-                }
-            case GapAdvertisingData::SERVICE_DATA:                       /**< Service Data */
-                {
-                PRINTF("Advertising type: SERVICE_DATA\n\r");
-                uint8_t buffSize = *loadPtr.getUnitAtIndex(index).getLenPtr()-1;
-                PRINTF("Advertising type: SERVICE_DATA (buffSize=%d)\n\r", buffSize);
-                // the total ADV DATA LEN should include two more bytes: the buffer size byte; and the Service Data Type Value byte
-                if(buffSize>ADV_DATA_MAX_SIZE-2) {
-                    return BLE_ERROR_PARAM_OUT_OF_RANGE;
-                }
-#ifdef DEBUG
-                for(int i=0; i<buffSize+1; i++) {
-                    PRINTF("Advertising type: SERVICE_DATA loadPtr.getUnitAtIndex(index).getDataPtr()[%d] = 0x%x\n\r",
-                            i, loadPtr.getUnitAtIndex(index).getDataPtr()[i]);
-                }
-#endif
-                // the total ADV DATA LEN should include two more bytes: the buffer size byte; and the Service Data Type Value byte
-                AdvData[AdvLen++] = buffSize+1; // the fisrt byte is the data buffer size (type+data)
-                AdvData[AdvLen++] = AD_TYPE_SERVICE_DATA;
-                memcpy(&AdvData[AdvLen], loadPtr.getUnitAtIndex(index).getDataPtr(), buffSize);
-                AdvLen += buffSize;
-                break;
-                }
-
-            case GapAdvertisingData::APPEARANCE:			/**< Appearance */
+            /**< Appearance */
+            case GapAdvertisingData::APPEARANCE:
                 {
                 PRINTF("Advertising type: APPEARANCE\n\r");
 
@@ -273,70 +152,15 @@
                 break;
                 }
 
-            case GapAdvertisingData::ADVERTISING_INTERVAL:               /**< Advertising Interval */
-                {
-                printf("Advertising type: ADVERTISING_INTERVAL\n\r");
-                uint8_t buffSize = *loadPtr.getUnitAtIndex(index).getLenPtr()-1;
-                AdvData[AdvLen++] = buffSize+1; // the fisrt byte is the data buffer size (type+data)
-                AdvData[AdvLen++] = AD_TYPE_ADVERTISING_INTERVAL;
-                memcpy(&AdvData[AdvLen], loadPtr.getUnitAtIndex(index).getDataPtr(), buffSize);
-                AdvLen += buffSize;
-                break;
-                }
-            case GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA:        /**< Manufacturer Specific Data */                             
-                {
-                PRINTF("Advertising type: MANUFACTURER_SPECIFIC_DATA\n\r");
-                uint8_t buffSize = *loadPtr.getUnitAtIndex(index).getLenPtr()-1;
-                PRINTF("Advertising type: MANUFACTURER_SPECIFIC_DATA (buffSize=%d)\n\r", buffSize);
-                // the total ADV DATA LEN should include two more bytes:
-		// the buffer size byte;
-		// and the Manufacturer Specific Data Type Value byte
-                if(buffSize>ADV_DATA_MAX_SIZE-2) {
-                    return BLE_ERROR_PARAM_OUT_OF_RANGE;
-                }
-#ifdef DBEUG
-                for(int i=0; i<buffSize+1; i++) {
-                    PRINTF("Advertising type: MANUFACTURER_SPECIFIC_DATA loadPtr.getUnitAtIndex(index).getDataPtr()[%d] = 0x%x\n\r",
-				i, loadPtr.getUnitAtIndex(index).getDataPtr()[i]);
-                }
-#endif
-                // the total ADV DATA LEN should include two more bytes: the buffer size byte; and the Manufacturer Specific Data Type Value byte
-                AdvData[AdvLen++] = buffSize+1; // the fisrt byte is the data buffer size (type+data)
-                AdvData[AdvLen++] = AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
-                memcpy(&AdvData[AdvLen], loadPtr.getUnitAtIndex(index).getDataPtr(), buffSize);
-                AdvLen += buffSize;
-                break;
-                }
             } // end switch
 
         } //end for
 
-        //Set the SCAN_RSP Payload
-        if(scanResponse.getPayloadLen() > 0) {
-          scan_response_payload = scanResponse.getPayload();
-          scan_rsp_length = scanResponse.getPayloadLen();
-        }
+    }
 
-        // Update the ADV data if we are already in ADV mode
-        if(AdvLen > 0 && state.advertising == 1) {
- 
-            tBleStatus ret = aci_gap_update_adv_data(AdvLen, AdvData);
-            if(BLE_STATUS_SUCCESS!=ret) {
-                PRINTF("error occurred while adding adv data (ret=0x%x)\n", ret);
-                switch (ret) {
-                  case BLE_STATUS_TIMEOUT:
-                    return BLE_STACK_BUSY;
-                  case ERR_INVALID_HCI_CMD_PARAMS:
-                  case BLE_STATUS_INVALID_PARAMS:
-                    return BLE_ERROR_INVALID_PARAM;
-                  case BLE_STATUS_FAILED:
-                    return BLE_ERROR_PARAM_OUT_OF_RANGE;
-                  default:
-                    return BLE_ERROR_UNSPECIFIED;
-                }
-            }
-        }
-    }
+    _advData = advData;
+    _scanResponse = scanResponse;
+
     return BLE_ERROR_NONE;
 }
 
@@ -354,40 +178,40 @@
 static void advTimeoutCB(void)
 {
     Gap::GapState_t state;
-    
+
     state = BlueNRGGap::getInstance().getState();
     if (state.advertising == 1) {
-        
+
         BlueNRGGap::getInstance().stopAdvertising();
-        
+
     }
 }
 #else
 static void advTimeoutCB(void)
 {
     Gap::GapState_t state;
-    
+
     state = BlueNRGGap::getInstance().getState();
     if (state.advertising == 1) {
-        
+
         BlueNRGGap::getInstance().setAdvToFlag();
-        
+
         Timeout t = BlueNRGGap::getInstance().getAdvTimeout();
         t.detach(); /* disable the callback from the timeout */
 
     }
 }
 #endif /* AST_FOR_MBED_OS */
-    
+
 /**************************************************************************/
 /*!
     @brief  Starts the BLE HW, initialising any services that were
             added before this function was called.
-    
+
     @param[in]  params
                 Basic advertising details, including the advertising
                 delay, timeout and how the device should be advertised
-                
+
     @note   All services must be added before calling this function!
 
     @returns    ble_error_t
@@ -406,7 +230,7 @@
 ble_error_t BlueNRGGap::startAdvertising(const GapAdvertisingParams &params)
 {
     tBleStatus ret;
-    ble_error_t rc;
+    int err;
 
     /* Make sure we support the advertising type */
     if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) {
@@ -475,8 +299,8 @@
         params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) {
 
         /* set scan response data */
-        PRINTF(" setting scan response data (scan_rsp_length=%u)\n", scan_rsp_length);
-        ret = hci_le_set_scan_resp_data(scan_rsp_length, scan_response_payload);
+        PRINTF(" setting scan response data (_scanResponseLen=%u)\n", _scanResponse.getPayloadLen());
+        ret = hci_le_set_scan_resp_data(_scanResponse.getPayloadLen(), _scanResponse.getPayload());
 
         if(BLE_STATUS_SUCCESS!=ret) {
             PRINTF(" error while setting scan response data (ret=0x%x)\n", ret);
@@ -491,54 +315,42 @@
         hci_le_set_scan_resp_data(0, NULL);
     }
 
-    //advInterval = params.getIntervalInADVUnits();
     setAdvParameters();
     PRINTF("advInterval=%d advType=%d\n\r", advInterval, params.getAdvertisingType());
 
-    /* Setting discoverable mode */
-    ret = aci_gap_set_discoverable(params.getAdvertisingType(), // AdvType
-                                   advInterval,                 // AdvIntervMin
-                                   advInterval,                 // AdvIntervMax
-                                   addr_type,                   // OwnAddrType
-                                   advFilterPolicy,             // AdvFilterPolicy
-                                   local_name_length,           // LocalNameLen
-                                   (const char*)local_name,     // LocalName
-                                   servUuidlength,              // ServiceUUIDLen
-                                   servUuidData,                // ServiceUUIDList
-                                   slaveConnIntervMin,          // SlaveConnIntervMin
-                                   slaveConnIntervMax);         // SlaveConnIntervMax
+    err = hci_le_set_advertising_data(_advData.getPayloadLen(), _advData.getPayload());
 
-    
-    PRINTF("!!!setting discoverable (servUuidlength=0x%x)\n\r", servUuidlength);
-    if(BLE_STATUS_SUCCESS!=ret) {
-       PRINTF("error occurred while setting discoverable (ret=0x%x)\n\r", ret);
-       switch (ret) {
-         case BLE_STATUS_INVALID_PARAMS:
-         case ERR_INVALID_HCI_CMD_PARAMS:
-           return BLE_ERROR_INVALID_PARAM;
-         case ERR_COMMAND_DISALLOWED:
-           return BLE_ERROR_OPERATION_NOT_PERMITTED;
-         case ERR_UNSUPPORTED_FEATURE:
-           return BLE_ERROR_NOT_IMPLEMENTED;
-         case BLE_STATUS_TIMEOUT:
-           return BLE_STACK_BUSY;
-         default:
-           return BLE_ERROR_UNSPECIFIED;
-       }
+    if (err) {
+        PRINTF("error while setting the payload\r\n");
+        return BLE_ERROR_UNSPECIFIED;
     }
 
-    // Since AD_TYPE_TX_POWER_LEVEL has not been set by application, we delete it
-    if(!txPowLevSet) {
-      PRINTF("Deleting TX POW LEV\n");
-      aci_gap_delete_ad_type(AD_TYPE_TX_POWER_LEVEL);
-      txPowLevSet = 0;
+    tBDAddr dummy_addr = { 0 };
+    uint16_t advIntervalMin = advInterval == GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX ? advInterval - 1 : advInterval;
+    uint16_t advIntervalMax = advIntervalMin + 1;
+
+    err = hci_le_set_advertising_parameters(
+        advIntervalMin,
+        advIntervalMax,
+        params.getAdvertisingType(),
+    	addr_type,
+        0x00,
+        dummy_addr,
+        /* all channels */ 7,
+    	advFilterPolicy
+    );
+
+    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);
+        return BLE_ERROR_INVALID_PARAM;
     }
 
-    // Stop Advertising if an error occurs while updating ADV data
-    rc = updateAdvertisingData();
-    if(rc != BLE_ERROR_NONE) {
-      aci_gap_set_non_discoverable();
-      return rc;
+    err = hci_le_set_advertise_enable(0x01);
+    if (err) {
+        PRINTF("impossible to start advertising\n\r");
+        return BLE_ERROR_UNSPECIFIED;
     }
 
     state.advertising = 1;
@@ -554,76 +366,9 @@
     }
 
     return BLE_ERROR_NONE;
+
 }
 
-ble_error_t BlueNRGGap::updateAdvertisingData(void)
-{
-    tBleStatus ret;
-
-    // Before updating the ADV data, delete COMPLETE_LOCAL_NAME field
-    if(AdvLen > 0) {
-      if(local_name_length > 0) {
-        ret = aci_gap_delete_ad_type(AD_TYPE_COMPLETE_LOCAL_NAME);
-        if (BLE_STATUS_SUCCESS!=ret){
-          PRINTF("aci_gap_delete_ad_type failed return=%d\n", ret);
-          switch (ret) {
-            case BLE_STATUS_TIMEOUT:
-              return BLE_STACK_BUSY;
-            case ERR_COMMAND_DISALLOWED:
-              return BLE_ERROR_OPERATION_NOT_PERMITTED;
-            case ERR_INVALID_HCI_CMD_PARAMS:
-              return BLE_ERROR_INVALID_PARAM;
-            default:
-              return BLE_ERROR_UNSPECIFIED;
-          }
-        }
-      }
-
-      // ...and TX_POWER_LEVEL field to make the needed room in ADV payload
-      if(txPowLevSet) {
-        ret = aci_gap_delete_ad_type(AD_TYPE_TX_POWER_LEVEL);
-        if (BLE_STATUS_SUCCESS!=ret){
-          PRINTF("aci_gap_delete_ad_type failed return=%d\n", ret);
-          switch (ret) {
-            case BLE_STATUS_TIMEOUT:
-              return BLE_STACK_BUSY;
-            case ERR_COMMAND_DISALLOWED:
-              return BLE_ERROR_OPERATION_NOT_PERMITTED;
-            case ERR_INVALID_HCI_CMD_PARAMS:
-              return BLE_ERROR_INVALID_PARAM;
-            default:
-              return BLE_ERROR_UNSPECIFIED;
-          }
-        }
-      }
-
-      ret = aci_gap_update_adv_data(AdvLen, AdvData);
-      if(BLE_STATUS_SUCCESS!=ret) {
-          PRINTF("error occurred while adding adv data (ret=0x%x)\n\r", ret);
-          switch (ret) {
-            case BLE_STATUS_TIMEOUT:
-              return BLE_STACK_BUSY;
-            case ERR_INVALID_HCI_CMD_PARAMS:
-            case BLE_STATUS_INVALID_PARAMS:
-              return BLE_ERROR_INVALID_PARAM;
-            case BLE_STATUS_FAILED:
-              return BLE_ERROR_PARAM_OUT_OF_RANGE;
-            default:
-              return BLE_ERROR_UNSPECIFIED;
-          }
-      }
-
-    } // AdvLen>0
-
-    if(deviceAppearance != 0) {
-      uint8_t appearance[] = {3, AD_TYPE_APPEARANCE, deviceAppearance[0], deviceAppearance[1]};
-      // just ignore error code while setting appearance
-      aci_gap_update_adv_data(4, appearance);
-    }
-
-    return BLE_ERROR_NONE;
-
-}
 
 /**************************************************************************/
 /*!
@@ -643,28 +388,19 @@
 /**************************************************************************/
 ble_error_t BlueNRGGap::stopAdvertising(void)
 {
-    tBleStatus ret;
 
     if(state.advertising == 1) {
-        //Set non-discoverable to stop advertising
-        ret = aci_gap_set_non_discoverable();
-        
-        if (BLE_STATUS_SUCCESS!=ret){
-            PRINTF("Error in stopping advertisement (ret=0x%x)!!\n\r", ret) ;
-            switch (ret) {
-              case ERR_COMMAND_DISALLOWED:
-                return BLE_ERROR_OPERATION_NOT_PERMITTED;
-              case BLE_STATUS_TIMEOUT:
-                return BLE_STACK_BUSY;
-              default:
-                return BLE_ERROR_UNSPECIFIED;
-            }
+
+        int err = hci_le_set_advertise_enable(0);
+        if (err) {
+            return BLE_ERROR_OPERATION_NOT_PERMITTED;
         }
+
         PRINTF("Advertisement stopped!!\n\r") ;
         //Set GapState_t::advertising state
         state.advertising = 0;
     }
-    
+
     return BLE_ERROR_NONE;
 }
 
@@ -674,7 +410,7 @@
 
     @param[in]  reason
                 Disconnection Reason
-                
+
     @returns    ble_error_t
 
     @retval     BLE_ERROR_NONE
@@ -704,7 +440,7 @@
             return BLE_ERROR_UNSPECIFIED;
         }
     }
-    
+
     return BLE_ERROR_NONE;
 }
 
@@ -714,7 +450,7 @@
 
     @param[in]  reason
                 Disconnection Reason
-                
+
     @returns    ble_error_t
 
     @retval     BLE_ERROR_NONE
@@ -735,10 +471,10 @@
 /**************************************************************************/
 /*!
     @brief  Sets the 16-bit connection handle
-    
+
     @param[in]  conn_handle
                 Connection Handle which is set in the Gap Instance
-                
+
     @returns    void
 */
 /**************************************************************************/
@@ -750,9 +486,9 @@
 /**************************************************************************/
 /*!
     @brief  Gets the 16-bit connection handle
-    
+
     @param[in]  void
-                
+
     @returns    uint16_t
                 Connection Handle of the Gap Instance
 */
@@ -769,10 +505,10 @@
 
     @param[in]  type
                 Type of Address
-    
+
     @param[in]  address[6]
                 Value of the Address to be set
-                
+
     @returns    ble_error_t
 
     @section EXAMPLE
@@ -784,26 +520,47 @@
 /**************************************************************************/
 ble_error_t BlueNRGGap::setAddress(AddressType_t type, const BLEProtocol::AddressBytes_t address)
 {
-    tBleStatus ret;
-
     if (type > BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) {
         return BLE_ERROR_PARAM_OUT_OF_RANGE;
     }
-    
-    addr_type = type;
 
-    // If Address Type is other than PUBLIC, the given Address is ignored
-    if(addr_type == BLEProtocol::AddressType::PUBLIC){
-        ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET,
-                                        CONFIG_DATA_PUBADDR_LEN,
-                                        address);
+    if(type == BLEProtocol::AddressType::PUBLIC){
+        tBleStatus ret = aci_hal_write_config_data(
+            CONFIG_DATA_PUBADDR_OFFSET,
+            CONFIG_DATA_PUBADDR_LEN,
+            address
+        );
         if(ret != BLE_STATUS_SUCCESS) {
             return BLE_ERROR_OPERATION_NOT_PERMITTED;
         }
+    } else if  (type == BLEProtocol::AddressType::RANDOM_STATIC) {
+        // ensure that the random static address is well formed
+        if ((address[5] & 0xC0) != 0xC0) {
+            return BLE_ERROR_PARAM_OUT_OF_RANGE;
+        }
+
+        // thanks to const correctness of the API ...
+        tBDAddr random_address = { 0 };
+        memcpy(random_address, address, sizeof(random_address));
+        int err = hci_le_set_random_address(random_address);
+        if (err) {
+            return BLE_ERROR_OPERATION_NOT_PERMITTED;
+        }
+
+        // It is not possible to get the bluetooth address when it is set
+        // store it locally in class data member
+        memcpy(bdaddr, address, sizeof(bdaddr));
     } else {
-        return BLE_ERROR_OPERATION_NOT_PERMITTED;
+        // FIXME random addresses are not supported yet
+        // BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE
+        // BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE
+        return BLE_ERROR_NOT_IMPLEMENTED;
     }
-    
+
+    // if we're here then the address was correctly set
+    // commit it inside the addr_type
+    addr_type = type;
+    isSetAddress = true;
     return BLE_ERROR_NONE;
 }
 
@@ -811,7 +568,7 @@
 /*!
     @brief      Returns boolean if the address of the device has been set
                 or not
-                
+
     @returns    bool
 
     @section EXAMPLE
@@ -821,9 +578,9 @@
     @endcode
 */
 /**************************************************************************/
-bool BlueNRGGap::getIsSetAddress() 
+bool BlueNRGGap::getIsSetAddress()
 {
-    return isSetAddress;   
+    return isSetAddress;
 }
 
 /**************************************************************************/
@@ -839,29 +596,36 @@
     @endcode
 */
 /**************************************************************************/
-ble_error_t BlueNRGGap::getAddress(AddressType_t *typeP, Address_t address) 
+ble_error_t BlueNRGGap::getAddress(AddressType_t *typeP, Address_t address)
 {
     uint8_t bdaddr[BDADDR_SIZE];
     uint8_t data_len_out;
 
-    if (addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE ||
-        addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) {
-        return BLE_ERROR_OPERATION_NOT_PERMITTED;
-    }
-
-    if(typeP != NULL) {
-        *typeP = addr_type;
+    // precondition, check that pointers in input are valid
+    if (typeP == NULL || address == NULL) {
+        return BLE_ERROR_INVALID_PARAM;
     }
 
-    tBleStatus ret = aci_hal_read_config_data(CONFIG_DATA_RANDOM_ADDRESS_IDB05A1, BDADDR_SIZE, &data_len_out, bdaddr);
-    if(ret != BLE_STATUS_SUCCESS) {
-        return BLE_ERROR_UNSPECIFIED;
+    if (addr_type == BLEProtocol::AddressType::PUBLIC) {
+        tBleStatus ret = aci_hal_read_config_data(CONFIG_DATA_PUBADDR_OFFSET, BDADDR_SIZE, &data_len_out, bdaddr);
+        if(ret != BLE_STATUS_SUCCESS || data_len_out != BDADDR_SIZE) {
+            return BLE_ERROR_UNSPECIFIED;
+        }
+    } else if (addr_type == BLEProtocol::AddressType::RANDOM_STATIC) {
+        // FIXME hci_read_bd_addr and
+        // aci_hal_read_config_data CONFIG_DATA_RANDOM_ADDRESS_IDB05A1
+        // does not work, use the address stored in class data member
+        memcpy(bdaddr, this->bdaddr, sizeof(bdaddr));
+    } else {
+        // FIXME: should be implemented with privacy features
+        // BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE
+        // BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE
+        return BLE_ERROR_NOT_IMPLEMENTED;
     }
 
-    if(address != NULL) {
-        memcpy(address, bdaddr, BDADDR_SIZE);
-    }
-        
+    *typeP = addr_type;
+    memcpy(address, bdaddr, BDADDR_SIZE);
+
     return BLE_ERROR_NONE;
 }
 
@@ -878,12 +642,39 @@
     @endcode
 */
 /**************************************************************************/
-ble_error_t BlueNRGGap::getPreferredConnectionParams(ConnectionParams_t *params) 
+ble_error_t BlueNRGGap::getPreferredConnectionParams(ConnectionParams_t *params)
 {
-    /* avoid compiler warnings about unused variables */
-    (void)params;
+    static const size_t parameter_size = 2;
+
+    if (!g_preferred_connection_parameters_char_handle) {
+        return BLE_ERROR_OPERATION_NOT_PERMITTED;
+    }
+
+    // Peripheral preferred connection parameters are an array of 4 uint16_t
+    uint8_t parameters_packed[parameter_size * 4];
+    uint16_t bytes_read = 0;
 
-    return BLE_ERROR_NOT_IMPLEMENTED;
+    tBleStatus err = aci_gatt_read_handle_value(
+        g_preferred_connection_parameters_char_handle + BlueNRGGattServer::CHAR_VALUE_HANDLE,
+        sizeof(parameters_packed),
+        &bytes_read,
+        parameters_packed
+    );
+
+    PRINTF("getPreferredConnectionParams err=0x%02x (bytes_read=%u)\n\r", err, bytes_read);
+
+    // check that the read succeed and the result have the expected length
+    if (err || bytes_read != sizeof(parameters_packed)) {
+        return BLE_ERROR_UNSPECIFIED;
+    }
+
+    // memcpy field by field
+    memcpy(&params->minConnectionInterval, parameters_packed, parameter_size);
+    memcpy(&params->maxConnectionInterval, &parameters_packed[parameter_size], parameter_size);
+    memcpy(&params->slaveLatency, &parameters_packed[2 * parameter_size], parameter_size);
+    memcpy(&params->connectionSupervisionTimeout, &parameters_packed[3 * parameter_size], parameter_size);
+
+    return BLE_ERROR_NONE;
 }
 
 
@@ -900,12 +691,63 @@
     @endcode
 */
 /**************************************************************************/
-ble_error_t BlueNRGGap::setPreferredConnectionParams(const ConnectionParams_t *params) 
+ble_error_t BlueNRGGap::setPreferredConnectionParams(const ConnectionParams_t *params)
 {
-    /* avoid compiler warnings about unused variables */
-    (void)params;
+    static const size_t parameter_size = 2;
+    uint8_t parameters_packed[parameter_size * 4];
+
+    // ensure that parameters are correct
+    // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C]
+    // section 12.3 PERIPHERAL PREFERRED CONNECTION PARAMETERS CHARACTERISTIC
+    if (((0x0006 > params->minConnectionInterval) || (params->minConnectionInterval > 0x0C80)) &&
+        params->minConnectionInterval != 0xFFFF) {
+        return BLE_ERROR_PARAM_OUT_OF_RANGE;
+    }
+
+    if (((params->minConnectionInterval > params->maxConnectionInterval) || (params->maxConnectionInterval > 0x0C80)) &&
+        params->maxConnectionInterval != 0xFFFF) {
+        return BLE_ERROR_PARAM_OUT_OF_RANGE;
+    }
+
+    if (params->slaveLatency > 0x01F3) {
+        return BLE_ERROR_PARAM_OUT_OF_RANGE;
+    }
+
+    if (((0x000A > params->connectionSupervisionTimeout) || (params->connectionSupervisionTimeout > 0x0C80)) &&
+        params->connectionSupervisionTimeout != 0xFFFF) {
+        return BLE_ERROR_PARAM_OUT_OF_RANGE;
+    }
 
-    return BLE_ERROR_NOT_IMPLEMENTED;
+    // copy the parameters inside the byte array
+    memcpy(parameters_packed, &params->minConnectionInterval, parameter_size);
+    memcpy(&parameters_packed[parameter_size], &params->maxConnectionInterval, parameter_size);
+    memcpy(&parameters_packed[2 * parameter_size], &params->slaveLatency, parameter_size);
+    memcpy(&parameters_packed[3 * parameter_size], &params->connectionSupervisionTimeout, parameter_size);
+
+    tBleStatus err = aci_gatt_update_char_value(
+        g_gap_service_handle,
+        g_preferred_connection_parameters_char_handle,
+        /* offset */ 0,
+        sizeof(parameters_packed),
+        parameters_packed
+    );
+
+    if (err) {
+        PRINTF("setPreferredConnectionParams failed (err=0x%x)!!\n\r", err) ;
+        switch (err) {
+          case BLE_STATUS_INVALID_HANDLE:
+          case BLE_STATUS_INVALID_PARAMETER:
+            return BLE_ERROR_INVALID_PARAM;
+          case BLE_STATUS_INSUFFICIENT_RESOURCES:
+            return BLE_ERROR_NO_MEM;
+          case BLE_STATUS_TIMEOUT:
+            return BLE_STACK_BUSY;
+          default:
+            return BLE_ERROR_UNSPECIFIED;
+        }
+    }
+
+    return BLE_ERROR_NONE;
 }
 
 /**************************************************************************/
@@ -923,16 +765,43 @@
 /**************************************************************************/
 ble_error_t BlueNRGGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *params)
 {
-    /* avoid compiler warnings about unused variables */
-    (void) handle;
-    (void)params;
+    tBleStatus ret = BLE_STATUS_SUCCESS;
+
+    if(gapRole == Gap::CENTRAL) {
+        ret = aci_gap_start_connection_update(handle,
+                                              params->minConnectionInterval,
+                                              params->maxConnectionInterval,
+                                              params->slaveLatency,
+                                              params->connectionSupervisionTimeout,
+                                              CONN_L1, CONN_L2);
+    } else {
+        ret = aci_l2cap_connection_parameter_update_request(handle,
+                                                            params->minConnectionInterval,
+                                                            params->maxConnectionInterval,
+                                                            params->slaveLatency,
+                                                            params->connectionSupervisionTimeout);
+    }
+
+    if (BLE_STATUS_SUCCESS != ret){
+        PRINTF("updateConnectionParams failed (ret=0x%x)!!\n\r", ret) ;
+        switch (ret) {
+          case ERR_INVALID_HCI_CMD_PARAMS:
+          case BLE_STATUS_INVALID_PARAMETER:
+            return BLE_ERROR_INVALID_PARAM;
+          case ERR_COMMAND_DISALLOWED:
+          case BLE_STATUS_NOT_ALLOWED:
+            return BLE_ERROR_OPERATION_NOT_PERMITTED;
+          default:
+            return BLE_ERROR_UNSPECIFIED;
+        }
+    }
 
     return BLE_ERROR_NONE;
 }
 
 /**************************************************************************/
 /*!
-    @brief  Sets the Device Name Characteristic 
+    @brief  Sets the Device Name Characteristic
 
     @param[in]  deviceName
                 pointer to device name to be set
@@ -949,11 +818,11 @@
     @endcode
 */
 /**************************************************************************/
-ble_error_t BlueNRGGap::setDeviceName(const uint8_t *deviceName) 
+ble_error_t BlueNRGGap::setDeviceName(const uint8_t *deviceName)
 {
     tBleStatus ret;
-    uint8_t nameLen = 0;     
-    
+    uint8_t nameLen = 0;
+
     nameLen = strlen((const char*)deviceName);
     PRINTF("DeviceName Size=%d\n\r", nameLen);
 
@@ -983,13 +852,13 @@
 
 /**************************************************************************/
 /*!
-    @brief  Gets the Device Name Characteristic 
+    @brief  Gets the Device Name Characteristic
 
     @param[in]  deviceName
-                pointer to device name                 
+                pointer to device name
 
     @param[in]  lengthP
-                pointer to device name length                
+                pointer to device name length
 
     @returns    ble_error_t
 
@@ -1021,10 +890,10 @@
 
 /**************************************************************************/
 /*!
-    @brief  Sets the Device Appearance Characteristic 
+    @brief  Sets the Device Appearance Characteristic
 
     @param[in]  appearance
-                device appearance      
+                device appearance
 
     @returns    ble_error_t
 
@@ -1043,9 +912,9 @@
     tBleStatus ret;
     uint8_t deviceAppearance[2];
 
-    STORE_LE_16(deviceAppearance, appearance);                 
+    STORE_LE_16(deviceAppearance, appearance);
     PRINTF("setAppearance= 0x%x 0x%x\n\r", deviceAppearance[1], deviceAppearance[0]);
-    
+
     ret = aci_gatt_update_char_value(g_gap_service_handle,
                                      g_appearance_char_handle,
                                      0, 2, (uint8_t *)deviceAppearance);
@@ -1072,7 +941,7 @@
     @brief  Gets the Device Appearance Characteristic
 
     @param[in]  appearance
-                pointer to device appearance value      
+                pointer to device appearance value
 
     @returns    ble_error_t
 
@@ -1161,7 +1030,7 @@
       default:
         type = GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED;
       }
-    
+
       PRINTF("data_length=%d adv peerAddr[%02x %02x %02x %02x %02x %02x] \r\n",
              *data_length, addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
       if(!_connecting) {
@@ -1170,7 +1039,7 @@
       PRINTF("!!!After processAdvertisementReport\n\r");
     }
     break;
-    
+
   case DISCOVERY_COMPLETE:
     // The discovery is complete. If this is due to a stop scanning (i.e., the device
     // we are interested in has been found) and a connection has been requested
@@ -1199,7 +1068,7 @@
 
 ble_error_t BlueNRGGap::startRadioScan(const GapScanningParams &scanningParams)
 {
-  
+
   tBleStatus ret = BLE_STATUS_SUCCESS;
 
   // Stop ADV before scanning
@@ -1256,13 +1125,13 @@
 
   PRINTF("stopScan\n\r");
   ret = aci_gap_terminate_gap_procedure(GAP_OBSERVATION_PROC);
-  
+
   if (ret != BLE_STATUS_SUCCESS) {
     PRINTF("GAP Terminate Gap Procedure failed(ret=0x%x)\n", ret);
-    return BLE_ERROR_UNSPECIFIED; 
+    return BLE_ERROR_UNSPECIFIED;
   } else {
     PRINTF("Discovery Procedure Terminated\n");
-    return BLE_ERROR_NONE; 
+    return BLE_ERROR_NONE;
   }
 }
 
@@ -1276,7 +1145,7 @@
 ble_error_t BlueNRGGap::setTxPower(int8_t txPower)
 {
     tBleStatus ret;
-    
+
     int8_t enHighPower = 0;
     int8_t paLevel = 0;
 
@@ -1285,7 +1154,7 @@
         return BLE_ERROR_PARAM_OUT_OF_RANGE;
     }
 
-    PRINTF("enHighPower=%d, paLevel=%d\n\r", enHighPower, paLevel);                    
+    PRINTF("enHighPower=%d, paLevel=%d\n\r", enHighPower, paLevel);
     ret = aci_hal_set_tx_power_level(enHighPower, paLevel);
     if(ret!=BLE_STATUS_SUCCESS) {
       return BLE_ERROR_PARAM_OUT_OF_RANGE;
@@ -1298,7 +1167,7 @@
 /*!
     @brief  get permitted Tx power values
     @param[in] values pointer to pointer to permitted power values
-    @param[in] num number of values   
+    @param[in] num number of values
 */
 /**************************************************************************/
 void BlueNRGGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) {
@@ -1324,6 +1193,8 @@
   if(state.connected == 1) {
     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);
   } else {
     advInterval = _advParams.getIntervalInADVUnits();
   }
@@ -1391,8 +1262,8 @@
   setConnectionParameters();
 
   /*
-    Scan_Interval, Scan_Window, Peer_Address_Type, Peer_Address, Own_Address_Type, Conn_Interval_Min, 
-    Conn_Interval_Max, Conn_Latency, Supervision_Timeout, Conn_Len_Min, Conn_Len_Max    
+    Scan_Interval, Scan_Window, Peer_Address_Type, Peer_Address, Own_Address_Type, Conn_Interval_Min,
+    Conn_Interval_Max, Conn_Latency, Supervision_Timeout, Conn_Len_Min, Conn_Len_Max
   */
   ret = aci_gap_create_connection(scanInterval,
 				  scanWindow,
@@ -1403,7 +1274,7 @@
 				  SUPERV_TIMEOUT, CONN_L1, CONN_L1);
 
   //_connecting = false;
-  
+
   if (ret != BLE_STATUS_SUCCESS) {
     PRINTF("Error while starting connection (ret=0x%02X).\n\r", ret);
     return BLE_ERROR_UNSPECIFIED;
@@ -1421,7 +1292,12 @@
 {
   /* avoid compiler warnings about unused variables */
   (void)connectionParams;
-  (void)scanParams;
+
+  setScanParams(scanParams->getInterval(),
+                scanParams->getWindow(),
+                scanParams->getTimeout(),
+                scanParams->getActiveScanning()
+               );
 
   // Save the peer address
   for(int i=0; i<BDADDR_SIZE; i++) {
@@ -1437,7 +1313,7 @@
     PRINTF("Calling createConnection from connect()\n\r");
     return createConnection();
   }
-  
+
   return BLE_ERROR_NONE;
 }
 
@@ -1528,14 +1404,19 @@
     /* Clear derived class members */
     m_connectionHandle = BLE_CONN_HANDLE_INVALID;
 
-    memset(deviceAppearance, 0, sizeof(deviceAppearance));
-    memset(local_name, 0, LOCAL_NAME_MAX_SIZE);
-    memset(local_name, 0, UUID_BUFFER_SIZE);
-    memset(AdvData, 0, ADV_DATA_MAX_SIZE);
-
     /* Set the whitelist policy filter modes to IGNORE_WHITELIST */
     advertisingPolicyMode = Gap::ADV_POLICY_IGNORE_WHITELIST;
     scanningPolicyMode    = Gap::SCAN_POLICY_IGNORE_WHITELIST;
 
     return BLE_ERROR_NONE;
 }
+
+void BlueNRGGap::setConnectionInterval(uint16_t interval) {
+    conn_min_interval = interval;
+    conn_max_interval = interval;
+}
+
+void BlueNRGGap::setGapRole(Role_t role)
+{
+    gapRole = role;
+}
--- a/source/BlueNRGGattClient.cpp	Thu Sep 15 10:51:26 2016 +0100
+++ b/source/BlueNRGGattClient.cpp	Thu Sep 15 10:51:36 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) {
@@ -72,6 +72,13 @@
   }
 
   if(_currentState == GATT_CHAR_DESC_DISCOVERY) {
+      if(charDescTerminationCallback != NULL) {
+         CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
+                                   _characteristic,
+                                   BLE_ERROR_NONE
+         };
+         charDescTerminationCallback(&params);
+       }
     _currentState = GATT_IDLE;
   }
 
@@ -86,7 +93,7 @@
     _currentState = GATT_IDLE;
   }
 }
-                                                
+
 void BlueNRGGattClient::primaryServicesCB(Gap::Handle_t connectionHandle,
                                           uint8_t event_data_length,
                                           uint8_t attribute_data_length,
@@ -107,13 +114,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 +132,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 +183,9 @@
     }
 
     discoveredService[i].setup(uuid, startHandle, endHandle);
-    
-    if(serviceDiscoveryCallback) {
-      serviceDiscoveryCallback(&discoveredService[_numServices]);
-    }
+
     _numServices++;
-    
+
     offset += 4;
   }
 }
@@ -225,10 +224,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 +262,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 +284,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 +307,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 +340,7 @@
                                   declHandle,
                                   valueHandle,
                                   lastHandle);
-  
+
   if(characteristicDiscoveryCallback) {
     characteristicDiscoveryCallback(&discoveredChar[_numChars]);
   }
@@ -346,24 +350,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 +394,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 +457,7 @@
                                                       const UUID                                 &matchingCharacteristicUUIDIn)
 {
   PRINTF("launchServiceDiscovery\n\r");
-  
+
   tBleStatus ret;
   uint8_t uuid_type = UUID_TYPE_16;
   uint8_t short_uuid[2];
@@ -466,17 +487,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 +507,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 +524,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 +579,7 @@
          _currentState == GATT_WRITE_CHAR ) {
     return false;
   }
-  
+
   return true;
 */
 }
@@ -566,7 +587,7 @@
 void BlueNRGGattClient::terminateServiceDiscovery(void)
 {
   _currentState = GATT_IDLE;//GATT_DISCOVERY_TERMINATED;
-  
+
   if (terminationCallback) {
     terminationCallback(_connectionHandle);
   }
@@ -590,18 +611,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 +660,7 @@
   (void)event_data_length;
 
   writeCBParams.connHandle = connHandle;
-  
+
   BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
 }
 
@@ -653,9 +674,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 +685,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,21 +715,25 @@
     handle_uuid_length = 18; //Handle + UUID_128
 
   numCharacDesc = (event_data_length - 1) / handle_uuid_length;
-  
+
   offset = 0;
 
+  PRINTF("\r\ncharacteristic descriptor discovered: data length %u, format %u\r\n",
+    event_data_length, format);
+
+
   for (i=0; i<numCharacDesc; i++) {
-    attHandle = handle_uuid_pair[offset];
+    memcpy(&attHandle, handle_uuid_pair + offset, sizeof(attHandle));
 
     // 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
@@ -737,15 +762,6 @@
 
     offset += handle_uuid_length;
   }
-
-  if(charDescTerminationCallback != NULL) {
-     CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
-                               _characteristic,
-                               BLE_ERROR_NONE
-     };
-     charDescTerminationCallback(&params);
-   }
-
 }
 
 ble_error_t BlueNRGGattClient::discoverCharacteristicDescriptors(
@@ -766,7 +782,7 @@
   GattAttribute::Handle_t valueHandle = characteristic.getValueHandle();
   GattAttribute::Handle_t lastHandle = characteristic.getLastHandle();
 
-  PRINTF("Starting aci_gatt_disc_all_charac_descriptors...\n\r");
+  PRINTF("Starting aci_gatt_disc_all_charac_descriptors... [%u : %u]\n\r", valueHandle, lastHandle);
   ret = aci_gatt_disc_all_charac_descriptors(connHandle, valueHandle, lastHandle);
 
   if (ret == BLE_STATUS_SUCCESS) {
@@ -812,5 +828,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:26 2016 +0100
+++ b/source/BlueNRGGattServer.cpp	Thu Sep 15 10:51:36 2016 +0100
@@ -15,7 +15,7 @@
 */
 /**
   ******************************************************************************
-  * @file    BlueNRGGattServer.cpp 
+  * @file    BlueNRGGattServer.cpp
   * @author  STMicroelectronics
   * @brief   Implementation of BlueNRG BLE_API GattServer Class
   ******************************************************************************
@@ -30,12 +30,12 @@
   *
   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
   */
- 
+
 /** @defgroup BlueNRGGATTSERVER
  *  @brief BlueNRG BLE_API GattServer Adaptation
  *  @{
  */
- 
+
 #include "BlueNRGGattServer.h"
 #include "mbed-drivers/mbed.h"
 #include "BlueNRGGap.h"
@@ -48,7 +48,7 @@
 
     @params[in] service
                 Pointer to instance of the Gatt Server to add
-                
+
     @returns    ble_error_t
 
     @retval     BLE_ERROR_NONE
@@ -66,7 +66,7 @@
     /* ToDo: Make sure we don't overflow the array, etc. */
     /* ToDo: Make sure this service UUID doesn't already exist (?) */
     /* ToDo: Basic validation */
-    
+
     tBleStatus ret;
     uint8_t type;
     uint16_t short_uuid;
@@ -75,26 +75,33 @@
     uint8_t char_base_uuid[16];
     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);
-    
+
     /* Add the service to the BlueNRG */
     short_uuid = (service.getUUID()).getShortUUID();
     STORE_LE_16(primary_short_uuid, short_uuid);
-    
+
     if(type==UUID::UUID_TYPE_LONG) {
-        base_uuid = (service.getUUID()).getBaseUUID();   
-        
+        base_uuid = (service.getUUID()).getBaseUUID();
+
         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;
+    ret = BLE_STATUS_SUCCESS;
 
     if(type==UUID::UUID_TYPE_SHORT) {
         ret = aci_gatt_add_serv(UUID_TYPE_16,
@@ -102,9 +109,9 @@
                                 PRIMARY_SERVICE,
                                 maxAttrRecords/*7*/,
                                 &servHandle);
-        PRINTF("aci_gatt_add_serv UUID_TYPE_LONG ret=%d\n\r", ret);
-    }
-    else if(type==UUID::UUID_TYPE_LONG) {
+        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,
                                 primary_base_uuid,
                                 PRIMARY_SERVICE,
@@ -112,12 +119,31 @@
                                 &servHandle);
         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);
     uint16_t bleCharacteristic;
-    
+
     //iterate to include all characteristics
     for (uint8_t i = 0; i < charsCount; i++) {
         GattCharacteristic *p_char = service.getCharacteristic(i);
@@ -138,7 +164,7 @@
 #endif
             COPY_UUID_128(char_base_uuid,base_char_uuid[15],base_char_uuid[14],int_8_uuid[1],int_8_uuid[0],base_char_uuid[11],base_char_uuid[10],base_char_uuid[9],base_char_uuid[8],base_char_uuid[7],base_char_uuid[6],base_char_uuid[5],base_char_uuid[4],base_char_uuid[3],base_char_uuid[2],base_char_uuid[1],base_char_uuid[0]);
         }
-        
+
         PRINTF("Char Properties 0x%x\n\r", p_char->getProperties());
         /*
         * Gatt_Evt_Mask -> HardCoded (0)
@@ -151,13 +177,13 @@
                     (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE|
                         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE))) {
             PRINTF("Setting up Gatt GATT_NOTIFY_ATTRIBUTE_WRITE Mask\n\r");
-            Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_ATTRIBUTE_WRITE;
+            Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_ATTRIBUTE_WRITE  | GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP;
         }
         if((p_char->getProperties() &
                     (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ|
                         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE))) {
             PRINTF("Setting up Gatt GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP Mask\n\r");
-            Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP; 
+            Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP;
         }    //This will support also GATT_SERVER_ATTR_READ_WRITE since it will be covered by previous if() check.
 
         if(type==UUID::UUID_TYPE_SHORT) {
@@ -171,7 +197,7 @@
                                      16 /*Encryption_Key_Size*/,
                                      1 /*isVariable*/,
                                      &bleCharacteristic);
-            
+
             PRINTF("aci_gatt_add_char UUID_TYPE_16 props=%d MaxLength=%d ret=%d\n\r",
                     p_char->getProperties(), p_char->getValueAttribute().getMaxLength(), ret);
 
@@ -186,36 +212,85 @@
                                      16 /*Encryption_Key_Size*/,
                                      1 /*isVariable*/,
                                      &bleCharacteristic);
-            
+
             PRINTF("aci_gatt_add_char UUID_TYPE_128 props=%d MaxLength=%d ret=%d\n\r",
                     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;
         /* Set the characteristic value handle */
         p_char->getValueAttribute().setHandle(bleCharacteristic+BlueNRGGattServer::CHAR_VALUE_HANDLE);
         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
         uint16_t descHandle = 0;
         PRINTF("p_char->getDescriptorCount()=%d\n\r", p_char->getDescriptorCount());
-        
+
         for(uint8_t descIndex=0; descIndex<p_char->getDescriptorCount(); descIndex++) {
             GattAttribute *descriptor = p_char->getDescriptor(descIndex);
-            uint16_t shortUUID = descriptor->getUUID().getShortUUID();
-            const uint8_t uuidArray[] = {(uint8_t)((shortUUID>>8)&0xFF), (uint8_t)((shortUUID&0xFF))};
+            uint8_t desc_uuid[16] = { 0 };
+
+
+            uint8_t desc_uuid_type = CHAR_DESC_TYPE_16_BIT;
+            STORE_LE_16(desc_uuid, descriptor->getUUID().getShortUUID());
+
+            if((descriptor->getUUID()).shortOrLong() == UUID::UUID_TYPE_LONG) {
+                desc_uuid_type = CHAR_DESC_TYPE_128_BIT;
+                const uint8_t* base_desc_uuid  = descriptor->getUUID().getBaseUUID();
+
+                COPY_UUID_128(desc_uuid, base_desc_uuid[15], base_desc_uuid[14],base_desc_uuid[13],base_desc_uuid[12], base_desc_uuid[11], base_desc_uuid[10], base_desc_uuid[9], base_desc_uuid[8], base_desc_uuid[7], base_desc_uuid[6], base_desc_uuid[5], base_desc_uuid[4], base_desc_uuid[3], base_desc_uuid[2], base_desc_uuid[1], base_desc_uuid[0]);
+            }
+
             ret = aci_gatt_add_char_desc(service.getHandle(),
                                          bleCharacteristic,
-                                         CHAR_DESC_TYPE_16_BIT,
-                                         uuidArray,
+                                         desc_uuid_type,
+                                         desc_uuid,
                                          descriptor->getMaxLength(),
                                          descriptor->getLength(),
                                          descriptor->getValuePtr(),
@@ -226,19 +301,52 @@
                                          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++;
-    
-    //FIXME: There is no GattService pointer array in GattServer. 
+
+    //FIXME: There is no GattService pointer array in GattServer.
     //        There should be one? (Only the user is aware of GattServices!) Report to forum.
-    
+
     return BLE_ERROR_NONE;
 }
 
@@ -269,7 +377,7 @@
 ble_error_t BlueNRGGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
 {
   tBleStatus ret;
-  uint16_t charHandle = attributeHandle-BlueNRGGattServer::CHAR_VALUE_HANDLE;
+  uint16_t charHandle = attributeHandle;
 
   ret = aci_gatt_read_handle_value(charHandle, *lengthP, lengthP, buffer);
 
@@ -335,38 +443,91 @@
 
   return BLE_ERROR_NONE;
 }
-    
+
 ble_error_t BlueNRGGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
 {
     /* avoid compiler warnings about unused variables */
     (void)localOnly;
 
-    tBleStatus ret;
-
-    uint16_t charHandle = attributeHandle-BlueNRGGattServer::CHAR_VALUE_HANDLE;
-
-    PRINTF("updating bleCharacteristic valueHandle=%u,\
-            corresponding serviceHandle=%u len=%d\n\r",
-            attributeHandle, bleCharHandleMap.find(charHandle)->second, len);
-
-    /*
-     * If notifications (or indications) are enabled on that characteristic, a notification (or indication)
-     * will be sent to the client after sending this command to the BlueNRG.
-     */
-    ret = aci_gatt_update_char_value(bleCharHandleMap.find(charHandle)->second, charHandle, 0, len, buffer);
-
-    if (ret != BLE_STATUS_SUCCESS){
-      PRINTF("Error while updating characteristic (ret=0x%x).\n\r", ret);
-      switch (ret) {
-        case BLE_STATUS_INVALID_HANDLE:
-        case BLE_STATUS_INVALID_PARAMETER:
-          return BLE_ERROR_INVALID_PARAM;
-        default:
-          return BLE_STACK_BUSY;
-      }
+    // check that the len of the data to write are compatible with the characteristic
+    GattCharacteristic* characteristic = getCharacteristicFromHandle(attributeHandle);
+    if (!characteristic) {
+        PRINTF("characteristic not found\r\n");
+        return BLE_ERROR_INVALID_PARAM;
     }
 
-    return BLE_ERROR_NONE;
+    // if the attribute handle is the attribute handle of the characteristic value then
+    // write the value
+    if (attributeHandle == characteristic->getValueHandle()) {
+        // assert the len in input is correct for this characteristic
+        const GattAttribute& value_attribute = characteristic->getValueAttribute();
+
+        // reject write if the lenght exceed the maximum lenght of this attribute
+        if (value_attribute.getMaxLength() < len) {
+            PRINTF("invalid variable length: %u, max length is: %u\r\n", len, value_attribute.getMaxLength());
+            return BLE_ERROR_INVALID_PARAM;
+        }
+
+        // reject write if the attribute size is fixed and the lenght in input is different than the
+        // length of the attribute.
+        if (value_attribute.hasVariableLength() == false && value_attribute.getMaxLength() != len) {
+            PRINTF("invalid fixed length: %u, len should be %u\r\n", len, value_attribute.getMaxLength());
+            return BLE_ERROR_INVALID_PARAM;
+        }
+
+        tBleStatus ret;
+
+        uint16_t charHandle = characteristic->getValueHandle() - BlueNRGGattServer::CHAR_VALUE_HANDLE;
+
+        PRINTF("updating bleCharacteristic valueHandle=%u,\
+                corresponding serviceHandle=%u len=%d\n\r",
+                attributeHandle, bleCharHandleMap.find(charHandle)->second, len);
+
+        /*
+         * If notifications (or indications) are enabled on that characteristic, a notification (or indication)
+         * will be sent to the client after sending this command to the BlueNRG.
+         */
+        ret = aci_gatt_update_char_value(bleCharHandleMap.find(charHandle)->second, charHandle, 0, len, buffer);
+
+        if (ret != BLE_STATUS_SUCCESS){
+          PRINTF("Error while updating characteristic (ret=0x%x).\n\r", ret);
+          switch (ret) {
+            case BLE_STATUS_INVALID_HANDLE:
+            case BLE_STATUS_INVALID_PARAMETER:
+              return BLE_ERROR_INVALID_PARAM;
+            default:
+              return BLE_STACK_BUSY;
+          }
+        }
+
+        return BLE_ERROR_NONE;
+    } else {
+        // write this handle has a descriptor handle
+        uint16_t charHandle = characteristic->getValueHandle() - BlueNRGGattServer::CHAR_VALUE_HANDLE;
+        uint16_t service_handle = bleCharHandleMap.find(charHandle)->second;
+
+        tBleStatus ret = aci_gatt_set_desc_value(
+            service_handle,
+            charHandle,
+            attributeHandle,
+            0,
+        	len,
+        	buffer
+        );
+
+        if (ret != BLE_STATUS_SUCCESS){
+          PRINTF("Error while updating characteristic descriptor (ret=0x%x).\n\r", ret);
+          switch (ret) {
+            case BLE_STATUS_INVALID_HANDLE:
+            case BLE_STATUS_INVALID_PARAMETER:
+              return BLE_ERROR_INVALID_PARAM;
+            default:
+              return BLE_STACK_BUSY;
+          }
+        }
+
+        return BLE_ERROR_NONE;
+    }
 }
 
 /**************************************************************************/
@@ -391,22 +552,58 @@
 ble_error_t BlueNRGGattServer::Read_Request_CB(uint16_t attributeHandle)
 {
     uint16_t gapConnectionHandle = BlueNRGGap::getInstance().getConnectionHandle();
-    
+
     GattReadCallbackParams readParams;
     readParams.handle = attributeHandle;
 
     //PRINTF("readParams.handle = %d\n\r", readParams.handle);
     HCIDataReadEvent(&readParams);
-    
+
     //EXIT:
     if(gapConnectionHandle != 0){
         //PRINTF("Calling aci_gatt_allow_read\n\r");
         aci_gatt_allow_read(gapConnectionHandle);
     }
-    
+
     return BLE_ERROR_NONE;
 }
 
+// ask if the write request should be accepted of rejected
+// return 0 in case of success or an ATT error response in
+// case of faillure
+uint8_t BlueNRGGattServer::Write_Request_CB(
+    uint16_t connection_handle, uint16_t attr_handle, uint8_t data_length,
+    const uint8_t* data) {
+
+    GattCharacteristic* characteristic = getCharacteristicFromHandle(attr_handle);
+    if(!characteristic) {
+        return AUTH_CALLBACK_REPLY_ATTERR_INVALID_HANDLE & 0xFF;
+    }
+
+    // check if the data length is in range
+    if (characteristic->getValueAttribute().getMaxLength() < data_length) {
+        return AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH & 0xFF;
+    }
+
+    // if the length of the characteristic value is fixed
+    // then the data in input should be of that length
+    if (characteristic->getValueAttribute().hasVariableLength() == false &&
+        characteristic->getValueAttribute().getMaxLength() != data_length) {
+        return AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH & 0xFF;
+    }
+
+    GattWriteAuthCallbackParams params = {
+        connection_handle,
+        attr_handle,
+        /* offset */ 0,
+        data_length,
+        data,
+        /* authorizationReply */ AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED
+    };
+
+    return characteristic->authorizeWrite(&params) & 0xFF;
+}
+
 /**************************************************************************/
 /*!
     @brief  Returns the GattCharacteristic according to the handle provided
@@ -444,7 +641,7 @@
                 p_char = p_characteristics[i];
                 PRINTF("Found Characteristic Properties 0x%x (handle=%d)\n\r",p_char->getProperties(), handle);
                 break;
-            }            
+            }
         }
         else {
             handle_1 = p_characteristics[i+1]->getValueAttribute().getHandle()-BlueNRGGattServer::CHAR_VALUE_HANDLE;
@@ -464,7 +661,7 @@
 void BlueNRGGattServer::HCIDataWrittenEvent(const GattWriteCallbackParams *params) {
     this->handleDataWrittenEvent(params);
 }
-    
+
 void BlueNRGGattServer::HCIDataReadEvent(const GattReadCallbackParams *params) {
     PRINTF("Called HCIDataReadEvent\n\r");
     this->handleDataReadEvent(params);
@@ -478,10 +675,10 @@
     this->handleDataSentEvent(count);
 }
 
-    
+
 ble_error_t BlueNRGGattServer::initializeGATTDatabase(void)   {
-    // <TODO>    
-    return (ble_error_t)0;       
+    // <TODO>
+    return (ble_error_t)0;
 }
 
 /**************************************************************************/
@@ -509,3 +706,44 @@
 
     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/source/platform/btle.cpp	Thu Sep 15 10:51:26 2016 +0100
+++ b/source/platform/btle.cpp	Thu Sep 15 10:51:36 2016 +0100
@@ -17,7 +17,7 @@
 
 /**
   ******************************************************************************
-  * @file    btle.cpp 
+  * @file    btle.cpp
   * @author  STMicroelectronics
   * @brief   Implementation BlueNRG Init and helper functions.
   ******************************************************************************
@@ -31,7 +31,7 @@
   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
   *
   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
-  */ 
+  */
 
 
 #include "btle.h"
@@ -81,6 +81,7 @@
 uint16_t g_gap_service_handle = 0;
 uint16_t g_appearance_char_handle = 0;
 uint16_t g_device_name_char_handle = 0;
+uint16_t g_preferred_connection_parameters_char_handle = 0;
 
 /* Private variables ---------------------------------------------------------*/
 volatile uint8_t set_connectable = 1;
@@ -91,17 +92,13 @@
 /**************************************************************************/
 /*!
     @brief  Init the BTLE stack with the specified role
-    @param  isSetAddress boolean if address has been set
-    @param  role The device role
     @returns void
 */
 /**************************************************************************/
-void btleInit(bool isSetAddress, uint8_t role)
+void btleInit(void)
 {
     PRINTF("btleInit>>\n\r");
-    /* Avoid compiler warnings about unused variables. */
-    (void)isSetAddress;
-    
+
     int ret;
     uint8_t  hwVersion;
     uint16_t fwVersion;
@@ -113,7 +110,7 @@
     /* get the BlueNRG HW and FW versions */
     getBlueNRGVersion(&hwVersion, &fwVersion);
 
-    /* 
+    /*
      * Reset BlueNRG again otherwise we won't
      * be able to change its MAC address.
      * aci_hal_write_config_data() must be the first
@@ -135,33 +132,6 @@
                                         &stackMode);
     }
 
-    /* The Nucleo board must be configured as SERVER */
-    //check if isSetAddress is set then set address.
-#if 0
-    if(isSetAddress)
-    {
-        Gap::Address_t bleAddr;
-        Gap::AddressType_t addr_type;
-
-        BlueNRGGap::getInstance().getAddress(&addr_type, bleAddr);
-
-        ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET,
-                                        CONFIG_DATA_PUBADDR_LEN,
-                                        bleAddr);
-    } else {
-        
-        const Gap::Address_t BLE_address_BE = {0xFD,0x66,0x05,0x13,0xBE,0xBA};
-        BlueNRGGap::getInstance().setAddress(BLEProtocol::AddressType::RANDOM_STATIC, BLE_address_BE);
-        
-        ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET,
-                                        CONFIG_DATA_PUBADDR_LEN,
-                                        BLE_address_BE);
-    }
-#endif
-
-    const Gap::Address_t BLE_address_BE = {0xFD,0x66,0x05,0x13,0xBE,0xBA};
-    BlueNRGGap::getInstance().setAddress(BLEProtocol::AddressType::RANDOM_STATIC, BLE_address_BE);
-    
     ret = aci_gatt_init();
     if(ret != BLE_STATUS_SUCCESS){
         PRINTF("GATT_Init failed.\n");
@@ -174,9 +144,19 @@
                                    &dev_name_char_handle,
                                    &appearance_char_handle);
     } else {
-        ret = aci_gap_init_IDB04A1(role, &service_handle, &dev_name_char_handle, &appearance_char_handle);
+        // IDB04A1 is configured as peripheral by default
+        ret = aci_gap_init_IDB04A1(GAP_PERIPHERAL_ROLE_IDB04A1, &service_handle, &dev_name_char_handle, &appearance_char_handle);
     }
-    
+
+    // read the default static address and inject it into the GAP object
+    {
+        Gap::Address_t BLE_address_BE = { 0 };
+        uint8_t data_len_out;
+        aci_hal_read_config_data(CONFIG_DATA_RANDOM_ADDRESS_IDB05A1, BDADDR_SIZE, &data_len_out, BLE_address_BE);
+        // FIXME error handling of this function
+        BlueNRGGap::getInstance().setAddress(BLEProtocol::AddressType::RANDOM_STATIC, BLE_address_BE);
+    }
+
     if(ret != BLE_STATUS_SUCCESS){
         PRINTF("GAP_Init failed.\n");
     }
@@ -193,17 +173,21 @@
     if (ret != BLE_STATUS_SUCCESS) {
         PRINTF("Auth Req set failed.\n");
     }
-    
+
     aci_hal_set_tx_power_level(1,4);
-    
+
     g_gap_service_handle = service_handle;
     g_appearance_char_handle = appearance_char_handle;
-    g_device_name_char_handle = dev_name_char_handle; 
-    //Device Name is set from Accumulate Adv Data Payload or through setDeviceName API  
+    g_device_name_char_handle = dev_name_char_handle;
+    //Device Name is set from Accumulate Adv Data Payload or through setDeviceName API
     /*ret = aci_gatt_update_char_value(service_handle, dev_name_char_handle, 0,
                             strlen(name), (tHalUint8 *)name);*/
 
     signalEventsToProcess();
+    // update the peripheral preferred conenction parameters handle
+    // This value is hardcoded at the moment.
+    g_preferred_connection_parameters_char_handle = 10;
+
     return;
 }
 
@@ -212,7 +196,7 @@
     @brief  mbedOS
 
     @param[in]  void
-    
+
     @returns
 */
 /**************************************************************************/
@@ -271,7 +255,7 @@
     @brief  Not Used
 
     @param[in]  void
-    
+
     @returns
 */
 void SPI_Poll(void)
@@ -279,7 +263,7 @@
     //HAL_GPIO_EXTI_Callback_Poll(BNRG_SPI_EXTI_PIN);
     return;
 }
-   
+
 void Attribute_Modified_CB(evt_blue_aci *blue_evt)
 {
     uint16_t conn_handle;
@@ -320,7 +304,7 @@
             currentHandle = BlueNRGGattServer::CHAR_DESC_HANDLE;
         }
         PRINTF("currentHandle %d\n\r", currentHandle);
-        if((p_char->getProperties() & 
+        if((p_char->getProperties() &
             (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) &&
             currentHandle == BlueNRGGattServer::CHAR_DESC_HANDLE) {
 
@@ -329,21 +313,22 @@
             PRINTF("*****NOTIFICATION CASE\n\r");
             //Now Check if data written in Enable or Disable
             if((uint16_t)att_data[0]==1) {
-                //PRINTF("Notify ENABLED\n\r"); 
+                //PRINTF("Notify ENABLED\n\r");
                 BlueNRGGattServer::getInstance().HCIEvent(GattServerEvents::GATT_EVENT_UPDATES_ENABLED, charDescHandle);
             } else {
-                //PRINTF("Notify DISABLED\n\r"); 
+                //PRINTF("Notify DISABLED\n\r");
                 BlueNRGGattServer::getInstance().HCIEvent(GattServerEvents::GATT_EVENT_UPDATES_DISABLED, charDescHandle);
             }
+            return;
         }
-                    
+
         //Check if attr handle property is WRITEABLE, in the case generate GATT_EVENT_DATA_WRITTEN Event
         if((p_char->getProperties() &
             (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE)) &&
             currentHandle == BlueNRGGattServer::CHAR_VALUE_HANDLE) {
-                    
+
             PRINTF("*****WRITE CASE\n\r");
-                   
+
             GattWriteCallbackParams writeParams;
             writeParams.connHandle = conn_handle;
             writeParams.handle = p_char->getValueAttribute().getHandle();
@@ -352,17 +337,31 @@
             writeParams.data = att_data;
             writeParams.offset = offset;
 
-            BlueNRGGattServer::getInstance().HCIDataWrittenEvent(&writeParams);
-
             //BlueNRGGattServer::getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_WRITTEN, attr_handle);
             //Write the actual Data to the Attr Handle? (uint8_1[])att_data contains the data
             if ((p_char->getValueAttribute().getValuePtr() != NULL) && (p_char->getValueAttribute().getLength() > 0)) {
-                BlueNRGGattServer::getInstance().write(p_char->getValueAttribute().getHandle(),
-                                                       (uint8_t*)att_data,
-                                                       data_length,
-                                                       false);
+                BlueNRGGattServer::getInstance().write(
+                    p_char->getValueAttribute().getHandle(),
+                    (uint8_t*)att_data,
+                    data_length,
+                    false
+                );
             }
-        } 
+
+            BlueNRGGattServer::getInstance().HCIDataWrittenEvent(&writeParams);
+        } else {
+            PRINTF("*****WRITE DESCRIPTOR CASE\n\r");
+
+            GattWriteCallbackParams writeParams;
+            writeParams.connHandle = conn_handle;
+            writeParams.handle = attr_handle;
+            writeParams.writeOp = GattWriteCallbackParams::OP_WRITE_REQ;//Where to find this property in BLUENRG?
+            writeParams.len = data_length;
+            writeParams.data = att_data;
+            writeParams.offset = offset;
+
+            BlueNRGGattServer::getInstance().HCIDataWrittenEvent(&writeParams);
+        }
     }
 
 }
@@ -377,39 +376,39 @@
 
     @param[in]  pckt
                 Event Packet sent by the stack to be decoded
-    
+
     @returns
     */
     /**************************************************************************/
     extern void HCI_Event_CB(void *pckt) {
         hci_uart_pckt *hci_pckt = (hci_uart_pckt*)pckt;
         hci_event_pckt *event_pckt = (hci_event_pckt*)hci_pckt->data;
-        
+
         if(hci_pckt->type != HCI_EVENT_PKT)
           return;
 
         switch(event_pckt->evt){
-            
+
         case EVT_DISCONN_COMPLETE:
             {
                 PRINTF("EVT_DISCONN_COMPLETE\n");
-                
+
                 evt_disconn_complete *evt = (evt_disconn_complete*)event_pckt->data;
-                
+
                 BlueNRGGap::getInstance().processDisconnectionEvent(evt->handle, (Gap::DisconnectionReason_t)evt->reason);
             }
             break;
-            
+
         case EVT_LE_META_EVENT:
             {
                 PRINTF("EVT_LE_META_EVENT\n");
-                
+
                 evt_le_meta_event *evt = (evt_le_meta_event *)event_pckt->data;
-                
+
                 switch(evt->subevent){
 
                 case EVT_LE_CONN_COMPLETE:
-                    {                            
+                    {
                         PRINTF("EVT_LE_CONN_COMPLETE\n");
                         Gap::Address_t ownAddr;
                         Gap::AddressType_t ownAddrType;
@@ -417,12 +416,19 @@
 
                         Gap::AddressType_t peerAddrType = BLEProtocol::AddressType::RANDOM_STATIC;
                         Gap::Role_t role;
-                        
+
                         evt_le_connection_complete *cc = (evt_le_connection_complete *)evt->data;
-                        
+
                         BlueNRGGap::getInstance().setConnectionHandle(cc->handle);
-                        BlueNRGGap::ConnectionParams_t connectionParams;
-                        BlueNRGGap::getInstance().getPreferredConnectionParams(&connectionParams);
+                        BlueNRGGap::ConnectionParams_t connectionParams = {
+                            /* minConnectionInterval = */ cc->interval,
+                            /* maxConnectionInterval = */ cc->interval,
+                            /* slaveLatency = */ cc->latency,
+                            /* connectionSupervisionTimeout = */ cc->supervision_timeout
+                        };
+
+                        BlueNRGGap::getInstance().setConnectionInterval(cc->interval);
+
                         switch (cc->peer_bdaddr_type) {
                             case PUBLIC_ADDR:
                                 peerAddrType = BLEProtocol::AddressType::PUBLIC;
@@ -436,7 +442,7 @@
                             case NON_RESOLVABLE_PRIVATE_ADDR:
                                 peerAddrType = BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE;
                                 break;
-                        }                                             
+                        }
                         //PRINTF("EVT_LE_CONN_COMPLETE LL role=%d\n", cc->role);
                         switch (cc->role) {
 			case 0: //master
@@ -449,7 +455,9 @@
                                 role = Gap::PERIPHERAL;
 				break;
                         }
-                        //PRINTF("EVT_LE_CONN_COMPLETE GAP role=%d\n", role);
+
+                        BlueNRGGap::getInstance().setGapRole(role);
+
                         BlueNRGGap::getInstance().processConnectionEvent(cc->handle,
                                                                          role,
                                                                          peerAddrType,
@@ -459,17 +467,17 @@
                                                                          &connectionParams);
                     }
                     break;
-          
+
         case EVT_LE_ADVERTISING_REPORT:
           PRINTF("EVT_LE_ADVERTISING_REPORT\n\r");
           /* FIXME: comment this otherwise it will be obscure and error prone if BlueNRG FW will be updated */
           // This event is generated only by X-NUCLEO-IDB05A1 version but not by X-NUCLEO-IDB04A1 (which generates DEVICE_FOUND EVT)
           // Formally the structure related to both events are identical except that for the ADV REPORT
           // there is one more field (number of reports) which is not forwarded to upper layer.
-          // Thus we need to move one byte over (((uint8_t*)evt->data)+1) before persing the ADV REPORT. 
+          // Thus we need to move one byte over (((uint8_t*)evt->data)+1) before persing the ADV REPORT.
           le_advertising_info *pr = (le_advertising_info*) (((uint8_t*)evt->data)+1);
           PRINTF("EVT_LE_ADVERTISING_REPORT evt_type=%d\n\r", pr->evt_type);
-          
+
           BlueNRGGap::getInstance().Discovery_CB(BlueNRGGap::DEVICE_FOUND,
                                                  pr->evt_type,
                                                  pr->bdaddr_type,
@@ -481,14 +489,40 @@
                 }
             }
             break;
-            
+
         case EVT_VENDOR:
-            {                
+            {
                 evt_blue_aci *blue_evt = (evt_blue_aci*)event_pckt->data;
                 //PRINTF("EVT_VENDOR %d\n", blue_evt->ecode);
-                
+
                 switch(blue_evt->ecode){
-                           
+
+                case EVT_BLUE_GATT_WRITE_PERMIT_REQ:
+                    {
+                        PRINTF("EVT_BLUE_GATT_WRITE_PERMIT_REQ\r\n");
+                        evt_gatt_write_permit_req* write_req = (evt_gatt_write_permit_req*)blue_evt->data;
+
+                        // ask the local server if the write operation is authorized
+                        uint8_t err_code = BlueNRGGattServer::getInstance().Write_Request_CB(
+                            write_req->conn_handle,
+                            write_req->attr_handle,
+                            write_req->data_length,
+                            write_req->data
+                        );
+                        uint8_t write_status = err_code == 0 ? 0 : 1;
+
+                        // reply to the shield
+                        aci_gatt_write_response(
+                            write_req->conn_handle,
+                            write_req->attr_handle,
+                            write_status,
+                            err_code,
+                            write_req->data_length,
+                            write_req->data
+                        );
+                    }
+                    break;
+
                 case EVT_BLUE_GATT_READ_PERMIT_REQ:
                     {
                         PRINTF("EVT_BLUE_GATT_READ_PERMIT_REQ_OK\n\r");
@@ -497,16 +531,16 @@
                         BlueNRGGattServer::getInstance().Read_Request_CB(pr->attr_handle);
                     }
                     break;
-                    
-                case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED:         
+
+                case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED:
                     {
                         PRINTF("EVT_BLUE_GATT_ATTRIBUTE_MODIFIED\n\r");
                         /* this callback is invoked when a GATT attribute is modified
                             extract callback data and pass to suitable handler function */
                         Attribute_Modified_CB(blue_evt);
                     }
-                    break;  
-                    
+                    break;
+
                     //Any cases for Data Sent Notifications?
                 case EVT_BLUE_GATT_NOTIFICATION:
                     //This is only relevant for Client Side Event
@@ -515,8 +549,8 @@
                 case EVT_BLUE_GATT_INDICATION:
                     //This is only relevant for Client Side Event
                     PRINTF("EVT_BLUE_GATT_INDICATION");
-                    break;   
-                    
+                    break;
+
         case EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP:
           {
             PRINTF("EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP\n\r");
@@ -601,12 +635,42 @@
             BlueNRGGattClient::getInstance().gattProcedureCompleteCB(evt->conn_handle, evt->error_code);
           }
           break;
-          
+
+        case EVT_BLUE_L2CAP_CONN_UPD_REQ:
+          {
+            PRINTF("EVT_BLUE_L2CAP_CONN_UPD_REQ\r\n");
+            evt_l2cap_conn_upd_req *evt = (evt_l2cap_conn_upd_req*)blue_evt->data;
+            if(bnrg_expansion_board == IDB05A1) {
+              // we assume the application accepts the request from the slave
+              aci_l2cap_connection_parameter_update_response_IDB05A1(evt->conn_handle,
+                                                                     evt->interval_min,
+                                                                     evt->interval_max,
+                                                                     evt->slave_latency,
+                                                                     evt->timeout_mult,
+                                                                     CONN_L1, CONN_L2,
+                                                                     evt->identifier,
+                                                                     0x0000);
+            }
+          }
+          break;
+
+        case EVT_BLUE_L2CAP_CONN_UPD_RESP:
+          {
+            PRINTF("EVT_BLUE_L2CAP_CONN_UPD_RESP\r\n");
+          }
+          break;
+
+        case EVT_LE_CONN_UPDATE_COMPLETE:
+          {
+            PRINTF("EVT_LE_CONN_UPDATE_COMPLETE\r\n");
+          }
+          break;
+
         case EVT_BLUE_GAP_DEVICE_FOUND:
           {
             evt_gap_device_found *pr = (evt_gap_device_found*)blue_evt->data;
             PRINTF("EVT_BLUE_GAP_DEVICE_FOUND evt_type=%d\n\r", pr->evt_type);
-            
+
             BlueNRGGap::getInstance().Discovery_CB(BlueNRGGap::DEVICE_FOUND,
                                                    pr->evt_type,
                                                    pr->bdaddr_type,
@@ -616,24 +680,24 @@
                                                    &pr->data_RSSI[pr->data_length]);
           }
           break;
-          
+
         case EVT_BLUE_GAP_PROCEDURE_COMPLETE:
           {
             evt_gap_procedure_complete *pr = (evt_gap_procedure_complete*)blue_evt->data;
             //PRINTF("EVT_BLUE_GAP_PROCEDURE_COMPLETE (code=0x%02X)\n\r", pr->procedure_code);
-            
+
             switch(pr->procedure_code) {
             case GAP_OBSERVATION_PROC_IDB05A1:
-              
+
               BlueNRGGap::getInstance().Discovery_CB(BlueNRGGap::DISCOVERY_COMPLETE, 0, 0, NULL, NULL, NULL, NULL);
               break;
             }
           }
-                    break;                                     
+                    break;
                 }
             }
             break;
-        }    
+        }
         return ;
     }
 
--- a/x-nucleo-idb0xa1/BlueNRGDiscoveredCharacteristic.h	Thu Sep 15 10:51:26 2016 +0100
+++ b/x-nucleo-idb0xa1/BlueNRGDiscoveredCharacteristic.h	Thu Sep 15 10:51:36 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/BlueNRGGap.h	Thu Sep 15 10:51:26 2016 +0100
+++ b/x-nucleo-idb0xa1/BlueNRGGap.h	Thu Sep 15 10:51:36 2016 +0100
@@ -16,7 +16,7 @@
 
 /**
   ******************************************************************************
-  * @file    BlueNRGGap.h 
+  * @file    BlueNRGGap.h
   * @author  STMicroelectronics
   * @brief   Header file for BlueNRG BLE_API Gap Class
   ******************************************************************************
@@ -30,8 +30,8 @@
   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
   *
   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
-  */ 
-  
+  */
+
 #ifndef __BLUENRG_GAP_H__
 #define __BLUENRG_GAP_H__
 
@@ -66,10 +66,6 @@
 #define MAX_INT_CONN   0x0C80 //=>4000msec
 #define DEF_INT_CONN   0x0140 //=>400msec (default value for connection interval)
 
-#define LOCAL_NAME_MAX_SIZE 9 //8 + 1(AD_DATA_TYPE)
-#define UUID_BUFFER_SIZE 17 //Either 8*2(16-bit UUIDs) or 4*4(32-bit UUIDs) or 1*16(128-bit UUIDs) +1(AD_DATA_TYPE)
-#define ADV_DATA_MAX_SIZE 31
-
 /**************************************************************************/
 /*!
     \brief
@@ -88,7 +84,7 @@
         DEVICE_FOUND,
         DISCOVERY_COMPLETE
     };
-    
+
     /* Functions that must be implemented from Gap */
     virtual ble_error_t setAddress(addr_type_t type,   const Address_t address);
     virtual ble_error_t getAddress(addr_type_t *typeP, Address_t address);
@@ -136,9 +132,9 @@
 
     void     setConnectionHandle(uint16_t con_handle);
     uint16_t getConnectionHandle(void);
-    
+
     bool getIsSetAddress();
-    
+
     Timeout getAdvTimeout(void) const {
         return advTimeout;
     }
@@ -146,15 +142,19 @@
         return AdvToFlag;
     }
     void setAdvToFlag(void);
-    
+
     void Process(void);
 
     GapScanningParams* getScanningParams(void);
 
     virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams);
 
+    void setConnectionInterval(uint16_t interval);
+    void setGapRole(Role_t role);
+
 private:
     uint16_t m_connectionHandle;
+    Role_t gapRole;
     AddressType_t addr_type;
     Address_t _peerAddr;
     AddressType_t _peerAddrType;
@@ -164,23 +164,9 @@
     bool isSetAddress;
     uint8_t deviceAppearance[2];
 
-    uint8_t local_name_length;
-    uint8_t local_name[ADV_DATA_MAX_SIZE];//LOCAL_NAME_MAX_SIZE];
-
-    uint8_t servUuidlength;
-    uint8_t servUuidData[UUID_BUFFER_SIZE];
-
-    uint8_t AdvLen;
-    uint8_t AdvData[ADV_DATA_MAX_SIZE];
-
-    uint8_t txPowLevSet;
-    
     Timeout advTimeout;
     bool AdvToFlag;
 
-    const uint8_t *scan_response_payload;
-    uint8_t scan_rsp_length;
-
     static uint16_t SCAN_DURATION_UNITS_TO_MSEC(uint16_t duration) {
         return (duration * 625) / 1000;
     }
@@ -202,7 +188,7 @@
 
     ble_error_t updateAdvertisingData(void);
 
-    BlueNRGGap(): txPowLevSet(0) {
+    BlueNRGGap() {
         m_connectionHandle = BLE_CONN_HANDLE_INVALID;
         addr_type = BLEProtocol::AddressType::RANDOM_STATIC;
 
@@ -216,6 +202,9 @@
 
     BlueNRGGap(BlueNRGGap const &);
     void operator=(BlueNRGGap const &);
+
+    GapAdvertisingData _advData;
+    GapAdvertisingData _scanResponse;
 };
 
-#endif // ifndef __BLUENRG_GAP_H__
+#endif // ifndef __BLUENRG_GAP_H__
\ No newline at end of file
--- a/x-nucleo-idb0xa1/BlueNRGGattServer.h	Thu Sep 15 10:51:26 2016 +0100
+++ b/x-nucleo-idb0xa1/BlueNRGGattServer.h	Thu Sep 15 10:51:36 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,24 +67,33 @@
     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);
     ble_error_t Read_Request_CB(uint16_t attributeHandle);
+    uint8_t Write_Request_CB(
+        uint16_t connection_handle, uint16_t attr_handle,
+        uint8_t data_length, const uint8_t* data
+    );
     GattCharacteristic* getCharacteristicFromHandle(uint16_t charHandle);
     void HCIDataWrittenEvent(const GattWriteCallbackParams *params);
     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 +110,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
--- a/x-nucleo-idb0xa1/bluenrg-hci/debug.h	Thu Sep 15 10:51:26 2016 +0100
+++ b/x-nucleo-idb0xa1/bluenrg-hci/debug.h	Thu Sep 15 10:51:36 2016 +0100
@@ -1,6 +1,6 @@
 /**
   ******************************************************************************
-  * @file    debug.h 
+  * @file    debug.h
   * @author  CL
   * @version V1.0.0
   * @date    04-July-2014
@@ -41,7 +41,7 @@
 
 #ifdef __cplusplus
  extern "C" {
-#endif 
+#endif
 
 /* Includes ------------------------------------------------------------------*/
 #include <string.h>
@@ -56,7 +56,7 @@
 #endif
 
 /* Print the data travelling over the SPI in the .csv format for the GUI*/
-//#define PRINT_CSV_FORMAT 
+//#define PRINT_CSV_FORMAT
 #ifdef PRINT_CSV_FORMAT
 #include <stdio.h>
 #define PRINT_CSV(...) printf(__VA_ARGS__)
@@ -70,4 +70,4 @@
 
 #endif /* __DEBUG_H */
 
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\ No newline at end of file
--- a/x-nucleo-idb0xa1/platform/btle.h	Thu Sep 15 10:51:26 2016 +0100
+++ b/x-nucleo-idb0xa1/platform/btle.h	Thu Sep 15 10:51:36 2016 +0100
@@ -25,20 +25,21 @@
 
 #include <stdio.h>
 #include <string.h>
-	
+
 #include "hci.h"
-#include "bluenrg_aci.h"	
-#include "hci_const.h"	
+#include "bluenrg_aci.h"
+#include "hci_const.h"
 #include "bluenrg_hal_aci.h"
-#include "stm32_bluenrg_ble.h"	
+#include "stm32_bluenrg_ble.h"
 #include "bluenrg_gap.h"
 #include "bluenrg_gatt_server.h"
 
 extern uint16_t g_gap_service_handle;
 extern uint16_t g_appearance_char_handle;
 extern uint16_t g_device_name_char_handle;
-	
-void btleInit(bool isSetAddress, uint8_t role);
+extern uint16_t g_preferred_connection_parameters_char_handle;
+
+void btleInit(void);
 void SPI_Poll(void);
 void User_Process(void);
 void setConnectable(void);