Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of X_NUCLEO_IDB0XA1 by
BlueNRGGattServer.cpp
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>© 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 }
Generated on Tue Jul 12 2022 16:31:45 by
1.7.2
