WILLIAN MATTOS / X_NUCLEO_IDB0XA1

Dependents:   BLE_HeartRate_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 #include "mbed.h"
00041 #include "BlueNRGGap.h"
00042 #include "Utils.h"
00043 #include "debug.h"
00044 
00045 /**************************************************************************/
00046 /*!
00047     @brief  Adds a new service to the GATT table on the peripheral
00048 
00049     @params[in] service
00050                 Pointer to instance of the Gatt Server to add
00051                 
00052     @returns    ble_error_t
00053 
00054     @retval     BLE_ERROR_NONE
00055                 Everything executed properly
00056 
00057     @section EXAMPLE
00058 
00059     @code
00060 
00061     @endcode
00062 */
00063 /**************************************************************************/
00064 ble_error_t BlueNRGGattServer::addService(GattService &service)
00065 {
00066     /* ToDo: Make sure we don't overflow the array, etc. */
00067     /* ToDo: Make sure this service UUID doesn't already exist (?) */
00068     /* ToDo: Basic validation */
00069     
00070     tBleStatus ret;
00071     uint8_t type;
00072     uint16_t short_uuid;
00073     uint8_t primary_short_uuid[2];
00074     uint8_t primary_base_uuid[16];
00075     uint8_t char_base_uuid[16];
00076     const uint8_t *base_uuid;
00077     const uint8_t *base_char_uuid;
00078     
00079     uint8_t charsCount = 0;
00080     uint8_t maxAttrRecords = 0;
00081 
00082     type = (service.getUUID()).shortOrLong();
00083     PRINTF("AddService(): Type:%d\n\r", type);
00084     
00085     /* Add the service to the BlueNRG */
00086     short_uuid = (service.getUUID()).getShortUUID();
00087     STORE_LE_16(primary_short_uuid, short_uuid);
00088     
00089     if(type==UUID::UUID_TYPE_LONG) {
00090         base_uuid = (service.getUUID()).getBaseUUID();   
00091         
00092         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]);
00093     }
00094 
00095     charsCount = service.getCharacteristicCount();
00096     //1(service record)+2records*char+1record*char_desc
00097     maxAttrRecords = 1+3*charsCount;
00098 
00099     if(type==UUID::UUID_TYPE_SHORT) {
00100         ret = aci_gatt_add_serv(UUID_TYPE_16,
00101                                 primary_short_uuid,
00102                                 PRIMARY_SERVICE,
00103                                 maxAttrRecords/*7*/,
00104                                 &servHandle);
00105         PRINTF("aci_gatt_add_serv UUID_TYPE_LONG ret=%d\n\r", ret);
00106     }
00107     else if(type==UUID::UUID_TYPE_LONG) {
00108         ret = aci_gatt_add_serv(UUID_TYPE_128,
00109                                 primary_base_uuid,
00110                                 PRIMARY_SERVICE,
00111                                 maxAttrRecords/*7*/,
00112                                 &servHandle);
00113         PRINTF("aci_gatt_add_serv UUID_TYPE_LONG ret=%d\n\r", ret);
00114     }
00115     
00116     service.setHandle(servHandle);
00117     //serviceHandleVector.push_back(servHandle);
00118     PRINTF("added servHandle handle =%u\n\r", servHandle);
00119     uint16_t bleCharacteristic;
00120     
00121     //iterate to include all characteristics
00122     for (uint8_t i = 0; i < charsCount; i++) {
00123         GattCharacteristic *p_char = service.getCharacteristic(i);
00124         uint16_t char_uuid = (p_char->getValueAttribute().getUUID()).getShortUUID();
00125 
00126         uint8_t int_8_uuid[2];
00127         STORE_LE_16(int_8_uuid, char_uuid);
00128 
00129         type = (p_char->getValueAttribute().getUUID()).shortOrLong();
00130 
00131         if(type==UUID::UUID_TYPE_LONG) {
00132             base_char_uuid = (p_char->getValueAttribute().getUUID()).getBaseUUID();
00133 #ifdef DEBUG
00134             for(uint8_t j=0; j<16; j++) {
00135                 PRINTF("base_char_uuid[%d] 0x%02x ", j, base_char_uuid[j]);
00136             }
00137             PRINTF("\n\r");
00138 #endif
00139             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]);
00140         }
00141         
00142         PRINTF("Char Properties 0x%x\n\r", p_char->getProperties());
00143         /*
00144         * Gatt_Evt_Mask -> HardCoded (0)
00145         * Encryption_Key_Size -> Hardcoded (16)
00146         * isVariable (variable length value field) -> Hardcoded (1)
00147         */
00148         uint8_t Gatt_Evt_Mask = 0x0;
00149 
00150         if((p_char->getProperties() &
00151                     (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE|
00152                         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE))) {
00153             PRINTF("Setting up Gatt GATT_NOTIFY_ATTRIBUTE_WRITE Mask\n\r");
00154             Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_ATTRIBUTE_WRITE;
00155         }
00156         if((p_char->getProperties() &
00157                     (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ|
00158                         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE))) {
00159             PRINTF("Setting up Gatt GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP Mask\n\r");
00160             Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP; 
00161         }    //This will support also GATT_SERVER_ATTR_READ_WRITE since it will be covered by previous if() check.
00162 
00163         if(type==UUID::UUID_TYPE_SHORT) {
00164             ret =  aci_gatt_add_char(service.getHandle(),
00165                                      UUID_TYPE_16,
00166                                      int_8_uuid,
00167                                      p_char->getValueAttribute().getMaxLength() /*2*/ /*Value Length*/,
00168                                      p_char->getProperties(),
00169                                      ATTR_PERMISSION_NONE,
00170                                      Gatt_Evt_Mask /*Gatt_Evt_Mask*/,
00171                                      16 /*Encryption_Key_Size*/,
00172                                      1 /*isVariable*/,
00173                                      &bleCharacteristic);
00174             
00175             PRINTF("aci_gatt_add_char UUID_TYPE_16 props=%d MaxLength=%d ret=%d\n\r",
00176                     p_char->getProperties(), p_char->getValueAttribute().getMaxLength(), ret);
00177 
00178         } else if(type==UUID::UUID_TYPE_LONG) {
00179             ret =  aci_gatt_add_char(service.getHandle(),
00180                                      UUID_TYPE_128,
00181                                      char_base_uuid,
00182                                      p_char->getValueAttribute().getMaxLength() /*2*/ /*Value Length*/,
00183                                      p_char->getProperties(),
00184                                      ATTR_PERMISSION_NONE,
00185                                      Gatt_Evt_Mask /*Gatt_Evt_Mask*/,
00186                                      16 /*Encryption_Key_Size*/,
00187                                      1 /*isVariable*/,
00188                                      &bleCharacteristic);
00189             
00190             PRINTF("aci_gatt_add_char UUID_TYPE_128 props=%d MaxLength=%d ret=%d\n\r",
00191                     p_char->getProperties(), p_char->getValueAttribute().getMaxLength(), ret);
00192         }
00193         
00194         bleCharHandleMap.insert(std::pair<uint16_t, uint16_t>(bleCharacteristic, servHandle));
00195         
00196         p_characteristics[characteristicCount++] = p_char;
00197         /* Set the characteristic value handle */
00198         p_char->getValueAttribute().setHandle(bleCharacteristic+BlueNRGGattServer::CHAR_VALUE_HANDLE);
00199         PRINTF("added bleCharacteristic (value handle =%u)\n\r", p_char->getValueAttribute().getHandle());
00200 
00201         if ((p_char->getValueAttribute().getValuePtr() != NULL) && (p_char->getValueAttribute().getLength() > 0)) {
00202             write(p_char->getValueAttribute().getHandle(),
00203                   p_char->getValueAttribute().getValuePtr(),
00204                   p_char->getValueAttribute().getLength(), false /* localOnly */);
00205         }
00206 
00207         // add descriptors now
00208         uint16_t descHandle = 0;
00209         PRINTF("p_char->getDescriptorCount()=%d\n\r", p_char->getDescriptorCount());
00210         
00211         for(uint8_t descIndex=0; descIndex<p_char->getDescriptorCount(); descIndex++) {
00212             GattAttribute *descriptor = p_char->getDescriptor(descIndex);
00213             uint16_t shortUUID = descriptor->getUUID().getShortUUID();
00214             const uint8_t uuidArray[] = {(uint8_t)((shortUUID>>8)&0xFF), (uint8_t)((shortUUID&0xFF))};
00215             ret = aci_gatt_add_char_desc(service.getHandle(),
00216                                          bleCharacteristic,
00217                                          CHAR_DESC_TYPE_16_BIT,
00218                                          uuidArray,
00219                                          descriptor->getMaxLength(),
00220                                          descriptor->getLength(),
00221                                          descriptor->getValuePtr(),
00222                                          CHAR_DESC_SECURITY_PERMISSION,
00223                                          CHAR_DESC_ACCESS_PERMISSION,
00224                                          GATT_NOTIFY_ATTRIBUTE_WRITE,
00225                                          MIN_ENCRY_KEY_SIZE,
00226                                          CHAR_ATTRIBUTE_LEN_IS_FIXED,
00227                                          &descHandle);
00228             PRINTF("Adding Descriptor descriptor handle=%d ret=%d\n\r", descHandle, ret);
00229             if(ret==(tBleStatus)0) {
00230                 PRINTF("Descriptor added successfully, descriptor handle=%d\n\r", descHandle);
00231                 descriptor->setHandle(descHandle);
00232             }
00233         }
00234 
00235     }    
00236     
00237     serviceCount++;
00238     
00239     //FIXME: There is no GattService pointer array in GattServer. 
00240     //        There should be one? (Only the user is aware of GattServices!) Report to forum.
00241     
00242     return BLE_ERROR_NONE;
00243 }
00244 
00245 /**************************************************************************/
00246 /*!
00247     @brief  Reads the value of a characteristic, based on char handle
00248 
00249     @param[in]  attributeHandle
00250                 The handle of the GattCharacteristic to read from
00251     @param[in]  buffer
00252                 Buffer to hold the the characteristic's value
00253                 (raw byte array in LSB format)
00254     @param[in]  lengthP
00255                 The number of bytes read into the buffer
00256 
00257     @returns    ble_error_t
00258 
00259     @retval     BLE_ERROR_NONE
00260                 Everything executed properly
00261 
00262     @section EXAMPLE
00263 
00264     @code
00265 
00266     @endcode
00267 */
00268 /**************************************************************************/
00269 ble_error_t BlueNRGGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
00270 {
00271   tBleStatus ret;
00272   uint16_t charHandle = attributeHandle-BlueNRGGattServer::CHAR_VALUE_HANDLE;
00273 
00274   ret = aci_gatt_read_handle_value(charHandle, *lengthP, lengthP, buffer);
00275 
00276   if(ret == BLE_STATUS_SUCCESS) {
00277     return BLE_ERROR_NONE;
00278   }
00279   switch (ret) {
00280   case ERR_INVALID_HCI_CMD_PARAMS:
00281     return BLE_ERROR_INVALID_PARAM;
00282   default:
00283     return BLE_ERROR_UNSPECIFIED;
00284   }
00285 }
00286 
00287 /**************************************************************************/
00288 /*!
00289     @brief  Reads the value of a characteristic, based on the connection
00290             and char handle
00291 
00292     @param[in]  connectionHandle
00293                 The handle of the connection
00294     @param[in]  attributeHandle
00295                 The handle of the GattCharacteristic to write to
00296     @param[in]  buffer
00297                 Data to use when updating the characteristic's value
00298                 (raw byte array in LSB format)
00299     @param[in]  lengthP
00300                 The number of bytes in buffer
00301 
00302     @returns    ble_error_t
00303 
00304     @retval     BLE_ERROR_NONE
00305                 Everything executed properly
00306 
00307     @section EXAMPLE
00308 
00309     @code
00310 
00311     @endcode
00312 */
00313 /**************************************************************************/
00314 ble_error_t BlueNRGGattServer::read(Gap::Handle_t connectionHandle,
00315                                     GattAttribute::Handle_t attributeHandle,
00316                                     uint8_t buffer[],
00317                                     uint16_t *lengthP) {
00318 
00319   /* avoid compiler warnings about unused variables */
00320   (void)connectionHandle;
00321   (void)attributeHandle;
00322   (void)buffer;
00323   (void)lengthP;
00324 
00325   return BLE_ERROR_NONE;
00326 }
00327 
00328 ble_error_t BlueNRGGattServer::write(Gap::Handle_t connectionHandle,
00329                                      GattAttribute::Handle_t,
00330                                      const uint8_t[],
00331                                      uint16_t, bool localOnly) {
00332   /* avoid compiler warnings about unused variables */
00333   (void)connectionHandle;
00334   (void)localOnly;
00335 
00336   return BLE_ERROR_NONE;
00337 }
00338     
00339 ble_error_t BlueNRGGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
00340 {
00341     /* avoid compiler warnings about unused variables */
00342     (void)localOnly;
00343 
00344     tBleStatus ret;
00345 
00346     uint16_t charHandle = attributeHandle-BlueNRGGattServer::CHAR_VALUE_HANDLE;
00347 
00348     PRINTF("updating bleCharacteristic valueHandle=%u,\
00349             corresponding serviceHandle=%u len=%d\n\r",
00350             attributeHandle, bleCharHandleMap.find(charHandle)->second, len);
00351 
00352     /*
00353      * If notifications (or indications) are enabled on that characteristic, a notification (or indication)
00354      * will be sent to the client after sending this command to the BlueNRG.
00355      */
00356     ret = aci_gatt_update_char_value(bleCharHandleMap.find(charHandle)->second, charHandle, 0, len, buffer);
00357 
00358     if (ret != BLE_STATUS_SUCCESS){
00359       PRINTF("Error while updating characteristic (ret=0x%x).\n\r", ret);
00360       switch (ret) {
00361         case BLE_STATUS_INVALID_HANDLE:
00362         case BLE_STATUS_INVALID_PARAMETER:
00363           return BLE_ERROR_INVALID_PARAM;
00364         default:
00365           return BLE_STACK_BUSY;
00366       }
00367     }
00368 
00369     return BLE_ERROR_NONE;
00370 }
00371 
00372 /**************************************************************************/
00373 /*!
00374     @brief  Reads a value according to the handle provided
00375 
00376     @param[in]  attributeHandle
00377                 The handle of the attribute to read from
00378 
00379     @returns    ble_error_t
00380 
00381     @retval     BLE_ERROR_NONE
00382                 Everything executed properly
00383 
00384     @section EXAMPLE
00385 
00386     @code
00387 
00388     @endcode
00389 */
00390 /**************************************************************************/
00391 ble_error_t BlueNRGGattServer::Read_Request_CB(uint16_t attributeHandle)
00392 {
00393     uint16_t gapConnectionHandle = BlueNRGGap::getInstance().getConnectionHandle();
00394     
00395     GattReadCallbackParams readParams;
00396     readParams.handle = attributeHandle;
00397 
00398     //PRINTF("readParams.handle = %d\n\r", readParams.handle);
00399     HCIDataReadEvent(&readParams);
00400     
00401     //EXIT:
00402     if(gapConnectionHandle != 0){
00403         //PRINTF("Calling aci_gatt_allow_read\n\r");
00404         aci_gatt_allow_read(gapConnectionHandle);
00405     }
00406     
00407     return BLE_ERROR_NONE;
00408 }
00409 
00410 /**************************************************************************/
00411 /*!
00412     @brief  Returns the GattCharacteristic according to the handle provided
00413 
00414     @param[in]  attrHandle
00415                 The handle of the attribute
00416 
00417     @returns    ble_error_t
00418 
00419     @retval     BLE_ERROR_NONE
00420                 Everything executed properly
00421 
00422     @section EXAMPLE
00423 
00424     @code
00425 
00426     @endcode
00427 */
00428 /**************************************************************************/
00429 GattCharacteristic* BlueNRGGattServer::getCharacteristicFromHandle(uint16_t attrHandle)
00430 {
00431     GattCharacteristic *p_char = NULL;
00432     int i;
00433     uint16_t handle, handle_1;
00434 
00435     PRINTF("BlueNRGGattServer::getCharacteristicFromHandle()>>Attr Handle received %d\n\r",attrHandle);
00436     for(i=0; i<characteristicCount; i++)
00437     {
00438         handle = p_characteristics[i]->getValueAttribute().getHandle()-BlueNRGGattServer::CHAR_VALUE_HANDLE;
00439         PRINTF("handle(%d)=%d\n\r", i, handle);
00440         if(i==characteristicCount-1)//Last Characteristic check
00441         {
00442             if(attrHandle>=handle)
00443             {
00444                 p_char = p_characteristics[i];
00445                 PRINTF("Found Characteristic Properties 0x%x (handle=%d)\n\r",p_char->getProperties(), handle);
00446                 break;
00447             }            
00448         }
00449         else {
00450             handle_1 = p_characteristics[i+1]->getValueAttribute().getHandle()-BlueNRGGattServer::CHAR_VALUE_HANDLE;
00451             //Testing if attribute handle is between two Characteristic Handles
00452             if(attrHandle>=handle && attrHandle<handle_1)
00453             {
00454                 p_char = p_characteristics[i];
00455                 PRINTF("Found Characteristic Properties 0x%x (handle=%d handle_1=%d)\n\r",p_char->getProperties(), handle, handle_1);
00456                 break;
00457             } else continue;
00458         }
00459     }
00460 
00461     return p_char;
00462 }
00463 
00464 void BlueNRGGattServer::HCIDataWrittenEvent(const GattWriteCallbackParams *params) {
00465     this->handleDataWrittenEvent(params);
00466 }
00467     
00468 void BlueNRGGattServer::HCIDataReadEvent(const GattReadCallbackParams *params) {
00469     PRINTF("Called HCIDataReadEvent\n\r");
00470     this->handleDataReadEvent(params);
00471 }
00472 
00473 void BlueNRGGattServer::HCIEvent(GattServerEvents::gattEvent_e type, uint16_t charHandle) {
00474     this->handleEvent(type, charHandle);
00475 }
00476 
00477 void BlueNRGGattServer::HCIDataSentEvent(unsigned count) {
00478     this->handleDataSentEvent(count);
00479 }
00480 
00481     
00482 ble_error_t BlueNRGGattServer::initializeGATTDatabase(void)   {
00483     // <TODO>    
00484     return (ble_error_t)0;       
00485 }
00486 
00487 /**************************************************************************/
00488 /*!
00489     @brief  Clear BlueNRGGattServer's state.
00490 
00491     @returns    ble_error_t
00492 
00493     @retval     BLE_ERROR_NONE
00494                 Everything executed properly
00495 */
00496 /**************************************************************************/
00497 ble_error_t BlueNRGGattServer::reset(void)
00498 {
00499     /* Clear all state that is from the parent, including private members */
00500     if (GattServer::reset() != BLE_ERROR_NONE) {
00501         return BLE_ERROR_INVALID_STATE;
00502     }
00503 
00504     /* Clear class members */
00505     memset(p_characteristics,        0, sizeof(p_characteristics));
00506     memset(bleCharacteristicHandles, 0, sizeof(bleCharacteristicHandles));
00507     serviceCount = 0;
00508     characteristicCount = 0;
00509 
00510     return BLE_ERROR_NONE;
00511 }