My fork of X_NUCLEO_IDB0XA1

Fork of X_NUCLEO_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BlueNRGGattServer.cpp Source File

BlueNRGGattServer.cpp

Go to the documentation of this file.
00001 /* mbed Microcontroller Library
00002 * Copyright (c) 2006-2013 ARM Limited
00003 *
00004 * Licensed under the Apache License, Version 2.0 (the "License");
00005 * you may not use this file except in compliance with the License.
00006 * You may obtain a copy of the License at
00007 *
00008 *     http://www.apache.org/licenses/LICENSE-2.0
00009 *
00010 * Unless required by applicable law or agreed to in writing, software
00011 * distributed under the License is distributed on an "AS IS" BASIS,
00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 * See the License for the specific language governing permissions and
00014 * limitations under the License.
00015 */
00016 /**
00017   ******************************************************************************
00018   * @file    BlueNRGGattServer.cpp
00019   * @author  STMicroelectronics
00020   * @brief   Implementation of BlueNRG BLE_API GattServer Class
00021   ******************************************************************************
00022   * @copy
00023   *
00024   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00025   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00026   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
00027   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00028   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00029   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00030   *
00031   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
00032   */
00033 
00034 /** @defgroup BlueNRGGATTSERVER
00035  *  @brief BlueNRG BLE_API GattServer Adaptation
00036  *  @{
00037  */
00038 
00039 #include "BlueNRGGattServer.h"
00040 #ifdef YOTTA_CFG_MBED_OS
00041     #include "mbed-drivers/mbed.h"
00042 #else
00043     #include "mbed.h"
00044 #endif 
00045 #include "BlueNRGGap.h"
00046 #include "ble_utils.h"
00047 #include "ble_debug.h"
00048 
00049 /**************************************************************************/
00050 /*!
00051     @brief  Adds a new service to the GATT table on the peripheral
00052 
00053     @params[in] service
00054                 Pointer to instance of the Gatt Server to add
00055 
00056     @returns    ble_error_t
00057 
00058     @retval     BLE_ERROR_NONE
00059                 Everything executed properly
00060 
00061     @section EXAMPLE
00062 
00063     @code
00064 
00065     @endcode
00066 */
00067 /**************************************************************************/
00068 ble_error_t BlueNRGGattServer::addService(GattService &service)
00069 {
00070     /* ToDo: Make sure we don't overflow the array, etc. */
00071     /* ToDo: Make sure this service UUID doesn't already exist (?) */
00072     /* ToDo: Basic validation */
00073 
00074     tBleStatus ret;
00075     uint8_t type;
00076     uint16_t short_uuid;
00077     uint8_t primary_short_uuid[2];
00078     uint8_t primary_base_uuid[16];
00079     uint8_t char_base_uuid[16];
00080     const uint8_t *base_uuid;
00081     const uint8_t *base_char_uuid;
00082 
00083     uint8_t charsCount = service.getCharacteristicCount();
00084     const uint8_t available_characteristics = BLE_TOTAL_CHARACTERISTICS - characteristicCount;
00085 
00086     // check that there is enough characteristics left in the
00087     // characteristic array.
00088     if (charsCount > available_characteristics) {
00089         PRINTF("charCount = %u and characteristicCount = %u\r\n", charsCount, available_characteristics);
00090         return BLE_ERROR_NO_MEM;
00091     }
00092 
00093     const uint16_t maxAttrRecords = computeAttributesRecord(service);
00094 
00095     type = (service.getUUID()).shortOrLong();
00096     PRINTF("AddService(): Type:%d\n\r", type);
00097 
00098     /* Add the service to the BlueNRG */
00099     short_uuid = (service.getUUID()).getShortUUID();
00100     STORE_LE_16(primary_short_uuid, short_uuid);
00101 
00102     if(type==UUID::UUID_TYPE_LONG) {
00103         base_uuid = (service.getUUID()).getBaseUUID();
00104 
00105         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]);
00106     }
00107 
00108     ret = BLE_STATUS_SUCCESS;
00109 
00110     if(type==UUID::UUID_TYPE_SHORT) {
00111         ret = aci_gatt_add_serv(UUID_TYPE_16,
00112                                 primary_short_uuid,
00113                                 PRIMARY_SERVICE,
00114                                 maxAttrRecords/*7*/,
00115                                 &servHandle);
00116         PRINTF("aci_gatt_add_serv UUID_TYPE_SHORT ret=%d\n\r", ret);
00117 
00118     } else if(type==UUID::UUID_TYPE_LONG) {
00119         ret = aci_gatt_add_serv(UUID_TYPE_128,
00120                                 primary_base_uuid,
00121                                 PRIMARY_SERVICE,
00122                                 maxAttrRecords/*7*/,
00123                                 &servHandle);
00124         PRINTF("aci_gatt_add_serv UUID_TYPE_LONG ret=%d\n\r", ret);
00125     }
00126 
00127     switch (ret) {
00128         case BLE_STATUS_SUCCESS:
00129             break;
00130 
00131         case BLE_STATUS_INVALID_PARAMETER:
00132             return BLE_ERROR_INVALID_PARAM;
00133 
00134         case BLE_STATUS_OUT_OF_HANDLE:
00135         case BLE_STATUS_INSUFFICIENT_RESOURCES:
00136         case ERR_UNSPECIFIED_ERROR:
00137             return BLE_ERROR_NO_MEM;
00138 
00139         case BLE_STATUS_ERROR:
00140         default:
00141             return BLE_ERROR_INTERNAL_STACK_FAILURE;
00142     }
00143 
00144 
00145 
00146     service.setHandle(servHandle);
00147     //serviceHandleVector.push_back(servHandle);
00148     PRINTF("added servHandle handle =%u\n\r", servHandle);
00149     uint16_t bleCharacteristic;
00150 
00151     //iterate to include all characteristics
00152     for (uint8_t i = 0; i < charsCount; i++) {
00153         GattCharacteristic *p_char = service.getCharacteristic(i);
00154         uint16_t char_uuid = (p_char->getValueAttribute().getUUID()).getShortUUID();
00155 
00156         uint8_t int_8_uuid[2];
00157         STORE_LE_16(int_8_uuid, char_uuid);
00158 
00159         type = (p_char->getValueAttribute().getUUID()).shortOrLong();
00160 
00161         if(type==UUID::UUID_TYPE_LONG) {
00162             base_char_uuid = (p_char->getValueAttribute().getUUID()).getBaseUUID();
00163 #ifdef DEBUG
00164             for(uint8_t j=0; j<16; j++) {
00165                 PRINTF("base_char_uuid[%d] 0x%02x ", j, base_char_uuid[j]);
00166             }
00167             PRINTF("\n\r");
00168 #endif
00169             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]);
00170         }
00171 
00172         PRINTF("Char Properties 0x%x\n\r", p_char->getProperties());
00173         /*
00174         * Gatt_Evt_Mask -> HardCoded (0)
00175         * Encryption_Key_Size -> Hardcoded (16)
00176         * isVariable (variable length value field) -> Hardcoded (1)
00177         */
00178         uint8_t Gatt_Evt_Mask = 0x0;
00179 
00180         if((p_char->getProperties() &
00181                     (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE|
00182                         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE))) {
00183             PRINTF("Setting up Gatt GATT_NOTIFY_ATTRIBUTE_WRITE Mask\n\r");
00184             Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_ATTRIBUTE_WRITE  | GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP;
00185         }
00186         if((p_char->getProperties() &
00187                     (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ|
00188                         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE))) {
00189             PRINTF("Setting up Gatt GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP Mask\n\r");
00190             Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP;
00191         }    //This will support also GATT_SERVER_ATTR_READ_WRITE since it will be covered by previous if() check.
00192 
00193         if(type==UUID::UUID_TYPE_SHORT) {
00194             ret =  aci_gatt_add_char(service.getHandle(),
00195                                      UUID_TYPE_16,
00196                                      int_8_uuid,
00197                                      p_char->getValueAttribute().getMaxLength() /*2*/ /*Value Length*/,
00198                                      p_char->getProperties(),
00199                                      ATTR_PERMISSION_NONE,
00200                                      Gatt_Evt_Mask /*Gatt_Evt_Mask*/,
00201                                      16 /*Encryption_Key_Size*/,
00202                                      1 /*isVariable*/,
00203                                      &bleCharacteristic);
00204 
00205             PRINTF("aci_gatt_add_char UUID_TYPE_16 props=%d MaxLength=%d ret=%d\n\r",
00206                     p_char->getProperties(), p_char->getValueAttribute().getMaxLength(), ret);
00207 
00208         } else if(type==UUID::UUID_TYPE_LONG) {
00209             ret =  aci_gatt_add_char(service.getHandle(),
00210                                      UUID_TYPE_128,
00211                                      char_base_uuid,
00212                                      p_char->getValueAttribute().getMaxLength() /*2*/ /*Value Length*/,
00213                                      p_char->getProperties(),
00214                                      ATTR_PERMISSION_NONE,
00215                                      Gatt_Evt_Mask /*Gatt_Evt_Mask*/,
00216                                      16 /*Encryption_Key_Size*/,
00217                                      1 /*isVariable*/,
00218                                      &bleCharacteristic);
00219 
00220             PRINTF("aci_gatt_add_char UUID_TYPE_128 props=%d MaxLength=%d ret=%d\n\r",
00221                     p_char->getProperties(), p_char->getValueAttribute().getMaxLength(), ret);
00222         }
00223 
00224         switch (ret) {
00225             case BLE_STATUS_SUCCESS:
00226                 break;
00227 
00228             case ERR_UNSPECIFIED_ERROR:
00229             case BLE_STATUS_INSUFFICIENT_RESOURCES:
00230             case BLE_STATUS_OUT_OF_HANDLE:
00231                 // TODO remove characteristics and the service previously added.
00232                 // remove service in the stack by using: Aci_Gatt_Del_Service
00233                 // remove characteristics in the stack by using: Aci_Gatt_Del_Char
00234                 // update service counter
00235                 // destroy registered characteristic and updat echaracteristic counter
00236                 return BLE_ERROR_NO_MEM;
00237 
00238             case BLE_STATUS_INVALID_HANDLE:
00239             case BLE_STATUS_INVALID_PARAMETER:
00240             case BLE_STATUS_CHARAC_ALREADY_EXISTS:
00241             // TODO remove characteristics and the service previously added.
00242             // remove service in the stack by using: Aci_Gatt_Del_Service
00243             // remove characteristics in the stack by using: Aci_Gatt_Del_Char
00244             // update service counter
00245             // destroy registered characteristic and updat echaracteristic counter
00246                 return BLE_ERROR_INVALID_PARAM;
00247 
00248             case BLE_STATUS_ERROR:
00249             default:
00250             // TODO remove characteristics and the service previously added.
00251             // remove service in the stack by using: Aci_Gatt_Del_Service
00252             // remove characteristics in the stack by using: Aci_Gatt_Del_Char
00253             // update service counter
00254             // destroy registered characteristic and updat echaracteristic counter
00255                 return BLE_ERROR_INTERNAL_STACK_FAILURE;
00256         }
00257 
00258         bleCharHandleMap.insert(std::pair<uint16_t, uint16_t>(bleCharacteristic, servHandle));
00259 
00260         p_characteristics[characteristicCount++] = p_char;
00261         /* Set the characteristic value handle */
00262         p_char->getValueAttribute().setHandle(bleCharacteristic+BlueNRGGattServer::CHAR_VALUE_HANDLE);
00263         PRINTF("added bleCharacteristic (value handle =%u)\n\r", p_char->getValueAttribute().getHandle());
00264 
00265         if ((p_char->getValueAttribute().getValuePtr() != NULL) && (p_char->getValueAttribute().getLength() > 0)) {
00266             ble_error_t err = write(p_char->getValueAttribute().getHandle(),
00267                   p_char->getValueAttribute().getValuePtr(),
00268                   p_char->getValueAttribute().getLength(), false /* localOnly */);
00269             if (err) {
00270                 PRINTF("ERROR HERE !!!!\r\n");
00271                 return err;
00272             }
00273         }
00274 
00275         // add descriptors now
00276         uint16_t descHandle = 0;
00277         PRINTF("p_char->getDescriptorCount()=%d\n\r", p_char->getDescriptorCount());
00278 
00279         for(uint8_t descIndex=0; descIndex<p_char->getDescriptorCount(); descIndex++) {
00280             GattAttribute *descriptor = p_char->getDescriptor(descIndex);
00281             uint8_t desc_uuid[16] = { 0 };
00282 
00283 
00284             uint8_t desc_uuid_type = CHAR_DESC_TYPE_16_BIT;
00285             STORE_LE_16(desc_uuid, descriptor->getUUID().getShortUUID());
00286 
00287             if((descriptor->getUUID()).shortOrLong() == UUID::UUID_TYPE_LONG) {
00288                 desc_uuid_type = CHAR_DESC_TYPE_128_BIT;
00289                 const uint8_t* base_desc_uuid  = descriptor->getUUID().getBaseUUID();
00290 
00291                 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]);
00292             }
00293 
00294             ret = aci_gatt_add_char_desc(service.getHandle(),
00295                                          bleCharacteristic,
00296                                          desc_uuid_type,
00297                                          desc_uuid,
00298                                          descriptor->getMaxLength(),
00299                                          descriptor->getLength(),
00300                                          descriptor->getValuePtr(),
00301                                          CHAR_DESC_SECURITY_PERMISSION,
00302                                          CHAR_DESC_ACCESS_PERMISSION,
00303                                          GATT_NOTIFY_ATTRIBUTE_WRITE,
00304                                          MIN_ENCRY_KEY_SIZE,
00305                                          CHAR_ATTRIBUTE_LEN_IS_FIXED,
00306                                          &descHandle);
00307             PRINTF("Adding Descriptor descriptor handle=%d ret=%d\n\r", descHandle, ret);
00308 
00309             switch (ret) {
00310                 case BLE_STATUS_SUCCESS:
00311                     PRINTF("Descriptor added successfully, descriptor handle=%d\n\r", descHandle);
00312                     descriptor->setHandle(descHandle);
00313                     break;
00314 
00315                 case ERR_UNSPECIFIED_ERROR:
00316                 case BLE_STATUS_INSUFFICIENT_RESOURCES:
00317                 case BLE_STATUS_OUT_OF_HANDLE:
00318                     // TODO remove characteristics and the service previously added.
00319                     // remove service in the stack by using: Aci_Gatt_Del_Service
00320                     // remove characteristics in the stack by using: Aci_Gatt_Del_Char
00321                     // update service counter
00322                     // destroy registered characteristic and updat echaracteristic counter
00323                     return BLE_ERROR_NO_MEM;
00324 
00325                 case BLE_STATUS_INVALID_HANDLE:
00326                 case BLE_STATUS_INVALID_PARAMETER:
00327                 // TODO remove characteristics and the service previously added.
00328                 // remove service in the stack by using: Aci_Gatt_Del_Service
00329                 // remove characteristics in the stack by using: Aci_Gatt_Del_Char
00330                 // update service counter
00331                 // destroy registered characteristic and updat echaracteristic counter
00332                     return BLE_ERROR_INVALID_PARAM;
00333 
00334                 case BLE_STATUS_INVALID_OPERATION:
00335                     return BLE_ERROR_OPERATION_NOT_PERMITTED;
00336 
00337                 case BLE_STATUS_ERROR:
00338                 default:
00339                 // TODO remove characteristics and the service previously added.
00340                 // remove service in the stack by using: Aci_Gatt_Del_Service
00341                 // remove characteristics in the stack by using: Aci_Gatt_Del_Char
00342                 // update service counter
00343                 // destroy registered characteristic and updat echaracteristic counter
00344                     return BLE_ERROR_INTERNAL_STACK_FAILURE;
00345             }
00346         }
00347     }
00348 
00349     serviceCount++;
00350 
00351     //FIXME: There is no GattService pointer array in GattServer.
00352     //        There should be one? (Only the user is aware of GattServices!) Report to forum.
00353 
00354     return BLE_ERROR_NONE;
00355 }
00356 
00357 /**************************************************************************/
00358 /*!
00359     @brief  Reads the value of a characteristic, based on char handle
00360 
00361     @param[in]  attributeHandle
00362                 The handle of the GattCharacteristic to read from
00363     @param[in]  buffer
00364                 Buffer to hold the the characteristic's value
00365                 (raw byte array in LSB format)
00366     @param[in]  lengthP
00367                 The number of bytes read into the buffer
00368 
00369     @returns    ble_error_t
00370 
00371     @retval     BLE_ERROR_NONE
00372                 Everything executed properly
00373 
00374     @section EXAMPLE
00375 
00376     @code
00377 
00378     @endcode
00379 */
00380 /**************************************************************************/
00381 ble_error_t BlueNRGGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
00382 {
00383   tBleStatus ret;
00384   uint16_t charHandle = attributeHandle;
00385 
00386   ret = aci_gatt_read_handle_value(charHandle, *lengthP, lengthP, buffer);
00387 
00388   if(ret == BLE_STATUS_SUCCESS) {
00389     return BLE_ERROR_NONE;
00390   }
00391   switch (ret) {
00392   case ERR_INVALID_HCI_CMD_PARAMS:
00393     return BLE_ERROR_INVALID_PARAM;
00394   default:
00395     return BLE_ERROR_UNSPECIFIED;
00396   }
00397 }
00398 
00399 /**************************************************************************/
00400 /*!
00401     @brief  Reads the value of a characteristic, based on the connection
00402             and char handle
00403 
00404     @param[in]  connectionHandle
00405                 The handle of the connection
00406     @param[in]  attributeHandle
00407                 The handle of the GattCharacteristic to write to
00408     @param[in]  buffer
00409                 Data to use when updating the characteristic's value
00410                 (raw byte array in LSB format)
00411     @param[in]  lengthP
00412                 The number of bytes in buffer
00413 
00414     @returns    ble_error_t
00415 
00416     @retval     BLE_ERROR_NONE
00417                 Everything executed properly
00418 
00419     @section EXAMPLE
00420 
00421     @code
00422 
00423     @endcode
00424 */
00425 /**************************************************************************/
00426 ble_error_t BlueNRGGattServer::read(Gap::Handle_t connectionHandle,
00427                                     GattAttribute::Handle_t attributeHandle,
00428                                     uint8_t buffer[],
00429                                     uint16_t *lengthP) {
00430 
00431   /* avoid compiler warnings about unused variables */
00432   (void)connectionHandle;
00433   (void)attributeHandle;
00434   (void)buffer;
00435   (void)lengthP;
00436 
00437   return BLE_ERROR_NONE;
00438 }
00439 
00440 ble_error_t BlueNRGGattServer::write(Gap::Handle_t connectionHandle,
00441                                      GattAttribute::Handle_t,
00442                                      const uint8_t[],
00443                                      uint16_t, bool localOnly) {
00444   /* avoid compiler warnings about unused variables */
00445   (void)connectionHandle;
00446   (void)localOnly;
00447 
00448   return BLE_ERROR_NONE;
00449 }
00450 
00451 ble_error_t BlueNRGGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
00452 {
00453     /* avoid compiler warnings about unused variables */
00454     (void)localOnly;
00455 
00456     // check that the len of the data to write are compatible with the characteristic
00457     GattCharacteristic* characteristic = getCharacteristicFromHandle(attributeHandle);
00458     if (!characteristic) {
00459         PRINTF("characteristic not found\r\n");
00460         return BLE_ERROR_INVALID_PARAM;
00461     }
00462 
00463     // if the attribute handle is the attribute handle of the characteristic value then
00464     // write the value
00465     if (attributeHandle == characteristic->getValueHandle()) {
00466         // assert the len in input is correct for this characteristic
00467         const GattAttribute& value_attribute = characteristic->getValueAttribute();
00468 
00469         // reject write if the lenght exceed the maximum lenght of this attribute
00470         if (value_attribute.getMaxLength() < len) {
00471             PRINTF("invalid variable length: %u, max length is: %u\r\n", len, value_attribute.getMaxLength());
00472             return BLE_ERROR_INVALID_PARAM;
00473         }
00474 
00475         // reject write if the attribute size is fixed and the lenght in input is different than the
00476         // length of the attribute.
00477         if (value_attribute.hasVariableLength() == false && value_attribute.getMaxLength() != len) {
00478             PRINTF("invalid fixed length: %u, len should be %u\r\n", len, value_attribute.getMaxLength());
00479             return BLE_ERROR_INVALID_PARAM;
00480         }
00481 
00482         tBleStatus ret;
00483 
00484         uint16_t charHandle = characteristic->getValueHandle() - BlueNRGGattServer::CHAR_VALUE_HANDLE;
00485 
00486         PRINTF("updating bleCharacteristic valueHandle=%u,\
00487                 corresponding serviceHandle=%u len=%d\n\r",
00488                 attributeHandle, bleCharHandleMap.find(charHandle)->second, len);
00489 
00490         /*
00491          * If notifications (or indications) are enabled on that characteristic, a notification (or indication)
00492          * will be sent to the client after sending this command to the BlueNRG.
00493          */
00494         ret = aci_gatt_update_char_value(bleCharHandleMap.find(charHandle)->second, charHandle, 0, len, buffer);
00495 
00496         if (ret != BLE_STATUS_SUCCESS){
00497           PRINTF("Error while updating characteristic (ret=0x%x).\n\r", ret);
00498           switch (ret) {
00499             case BLE_STATUS_INVALID_HANDLE:
00500             case BLE_STATUS_INVALID_PARAMETER:
00501               return BLE_ERROR_INVALID_PARAM;
00502             default:
00503               return BLE_STACK_BUSY;
00504           }
00505         }
00506 
00507         return BLE_ERROR_NONE;
00508     } else {
00509         // write this handle has a descriptor handle
00510         uint16_t charHandle = characteristic->getValueHandle() - BlueNRGGattServer::CHAR_VALUE_HANDLE;
00511         uint16_t service_handle = bleCharHandleMap.find(charHandle)->second;
00512 
00513         tBleStatus ret = aci_gatt_set_desc_value(
00514             service_handle,
00515             charHandle,
00516             attributeHandle,
00517             0,
00518             len,
00519             buffer
00520         );
00521 
00522         if (ret != BLE_STATUS_SUCCESS){
00523           PRINTF("Error while updating characteristic descriptor (ret=0x%x).\n\r", ret);
00524           switch (ret) {
00525             case BLE_STATUS_INVALID_HANDLE:
00526             case BLE_STATUS_INVALID_PARAMETER:
00527               return BLE_ERROR_INVALID_PARAM;
00528             default:
00529               return BLE_STACK_BUSY;
00530           }
00531         }
00532 
00533         return BLE_ERROR_NONE;
00534     }
00535 }
00536 
00537 /**************************************************************************/
00538 /*!
00539     @brief  Reads a value according to the handle provided
00540 
00541     @param[in]  attributeHandle
00542                 The handle of the attribute to read from
00543 
00544     @returns    ble_error_t
00545 
00546     @retval     BLE_ERROR_NONE
00547                 Everything executed properly
00548 
00549     @section EXAMPLE
00550 
00551     @code
00552 
00553     @endcode
00554 */
00555 /**************************************************************************/
00556 ble_error_t BlueNRGGattServer::Read_Request_CB(uint16_t attributeHandle)
00557 {
00558     uint16_t gapConnectionHandle = BlueNRGGap::getInstance().getConnectionHandle();
00559 
00560     GattReadCallbackParams readParams;
00561     readParams.handle = attributeHandle;
00562 
00563     //PRINTF("readParams.handle = %d\n\r", readParams.handle);
00564     HCIDataReadEvent(&readParams);
00565 
00566     //EXIT:
00567     if(gapConnectionHandle != 0){
00568         //PRINTF("Calling aci_gatt_allow_read\n\r");
00569         aci_gatt_allow_read(gapConnectionHandle);
00570     }
00571 
00572     return BLE_ERROR_NONE;
00573 }
00574 
00575 // ask if the write request should be accepted of rejected
00576 // return 0 in case of success or an ATT error response in
00577 // case of faillure
00578 uint8_t BlueNRGGattServer::Write_Request_CB(
00579     uint16_t connection_handle, uint16_t attr_handle, uint8_t data_length,
00580     const uint8_t* data) {
00581 
00582     GattCharacteristic* characteristic = getCharacteristicFromHandle(attr_handle);
00583     if(!characteristic) {
00584         return AUTH_CALLBACK_REPLY_ATTERR_INVALID_HANDLE & 0xFF;
00585     }
00586 
00587     // check if the data length is in range
00588     if (characteristic->getValueAttribute().getMaxLength() < data_length) {
00589         return AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH & 0xFF;
00590     }
00591 
00592     // if the length of the characteristic value is fixed
00593     // then the data in input should be of that length
00594     if (characteristic->getValueAttribute().hasVariableLength() == false &&
00595         characteristic->getValueAttribute().getMaxLength() != data_length) {
00596         return AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH & 0xFF;
00597     }
00598 
00599     GattWriteAuthCallbackParams params = {
00600         connection_handle,
00601         attr_handle,
00602         /* offset */ 0,
00603         data_length,
00604         data,
00605         /* authorizationReply */ AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED
00606     };
00607 
00608     return characteristic->authorizeWrite(&params) & 0xFF;
00609 }
00610 
00611 /**************************************************************************/
00612 /*!
00613     @brief  Returns the GattCharacteristic according to the handle provided
00614 
00615     @param[in]  attrHandle
00616                 The handle of the attribute
00617 
00618     @returns    ble_error_t
00619 
00620     @retval     BLE_ERROR_NONE
00621                 Everything executed properly
00622 
00623     @section EXAMPLE
00624 
00625     @code
00626 
00627     @endcode
00628 */
00629 /**************************************************************************/
00630 GattCharacteristic* BlueNRGGattServer::getCharacteristicFromHandle(uint16_t attrHandle)
00631 {
00632     GattCharacteristic *p_char = NULL;
00633     int i;
00634     uint16_t handle, handle_1;
00635 
00636     PRINTF("BlueNRGGattServer::getCharacteristicFromHandle()>>Attr Handle received %d\n\r",attrHandle);
00637     for(i=0; i<characteristicCount; i++)
00638     {
00639         handle = p_characteristics[i]->getValueAttribute().getHandle()-BlueNRGGattServer::CHAR_VALUE_HANDLE;
00640         PRINTF("handle(%d)=%d\n\r", i, handle);
00641         if(i==characteristicCount-1)//Last Characteristic check
00642         {
00643             if(attrHandle>=handle)
00644             {
00645                 p_char = p_characteristics[i];
00646                 PRINTF("Found Characteristic Properties 0x%x (handle=%d)\n\r",p_char->getProperties(), handle);
00647                 break;
00648             }
00649         }
00650         else {
00651             handle_1 = p_characteristics[i+1]->getValueAttribute().getHandle()-BlueNRGGattServer::CHAR_VALUE_HANDLE;
00652             //Testing if attribute handle is between two Characteristic Handles
00653             if(attrHandle>=handle && attrHandle<handle_1)
00654             {
00655                 p_char = p_characteristics[i];
00656                 PRINTF("Found Characteristic Properties 0x%x (handle=%d handle_1=%d)\n\r",p_char->getProperties(), handle, handle_1);
00657                 break;
00658             } else continue;
00659         }
00660     }
00661 
00662     return p_char;
00663 }
00664 
00665 void BlueNRGGattServer::HCIDataWrittenEvent(const GattWriteCallbackParams *params) {
00666     this->handleDataWrittenEvent(params);
00667 }
00668 
00669 void BlueNRGGattServer::HCIDataReadEvent(const GattReadCallbackParams *params) {
00670     PRINTF("Called HCIDataReadEvent\n\r");
00671     this->handleDataReadEvent(params);
00672 }
00673 
00674 void BlueNRGGattServer::HCIEvent(GattServerEvents::gattEvent_e type, uint16_t charHandle) {
00675     this->handleEvent(type, charHandle);
00676 }
00677 
00678 void BlueNRGGattServer::HCIDataSentEvent(unsigned count) {
00679     this->handleDataSentEvent(count);
00680 }
00681 
00682 
00683 ble_error_t BlueNRGGattServer::initializeGATTDatabase(void)   {
00684     // <TODO>
00685     return (ble_error_t)0;
00686 }
00687 
00688 /**************************************************************************/
00689 /*!
00690     @brief  Clear BlueNRGGattServer's state.
00691 
00692     @returns    ble_error_t
00693 
00694     @retval     BLE_ERROR_NONE
00695                 Everything executed properly
00696 */
00697 /**************************************************************************/
00698 ble_error_t BlueNRGGattServer::reset(void)
00699 {
00700     /* Clear all state that is from the parent, including private members */
00701     if (GattServer::reset() != BLE_ERROR_NONE) {
00702         return BLE_ERROR_INVALID_STATE;
00703     }
00704 
00705     /* Clear class members */
00706     memset(p_characteristics,        0, sizeof(p_characteristics));
00707     memset(bleCharacteristicHandles, 0, sizeof(bleCharacteristicHandles));
00708     serviceCount = 0;
00709     characteristicCount = 0;
00710 
00711     return BLE_ERROR_NONE;
00712 }
00713 
00714 
00715 /// compute the number of attributes needed by this service.
00716 uint16_t BlueNRGGattServer::computeAttributesRecord(GattService& service) {
00717     uint16_t attribute_records = 1;
00718 
00719     for (uint8_t characteristic_index = 0; characteristic_index < service.getCharacteristicCount(); ++characteristic_index) {
00720         // add two attributes, one for the characteristic declaration
00721         // and the other for the characteristic value.
00722         attribute_records += 2;
00723 
00724         const GattCharacteristic* characteristic = service.getCharacteristic(characteristic_index);
00725         const uint8_t properties = characteristic->getProperties();
00726         // if notify or indicate are present, two attributes are
00727         // needed
00728         if ((properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ||
00729             (properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) {
00730             attribute_records += 2;
00731         }
00732 
00733         // if broadcast is set, two attributes are needed
00734         if (properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_BROADCAST) {
00735             attribute_records += 2;
00736         }
00737 
00738         // if extended properties flag is set, two attributes are needed
00739         if (properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES) {
00740             attribute_records += 2;
00741         }
00742 
00743         attribute_records += characteristic->getDescriptorCount();
00744     }
00745 
00746     // for some reason, if there is just a service, this value should
00747     // be equal to 5
00748     if (attribute_records == 1) {
00749         attribute_records = 5;
00750     }
00751 
00752     return attribute_records;
00753 }