BLE test

Fork of X_NUCLEO_IDB0XA1 by ST

Committer:
Vincent Coubard
Date:
Thu Sep 15 10:52:00 2016 +0100
Branch:
8247cc25d48b37d6a78a3e91c728cbbf0fd9ba29
Revision:
293:5a1f577bf92f
Parent:
278:a5209d8cfd61
Child:
302:ed6f74ab78f9
Sync with 8247cc25d48b37d6a78a3e91c728cbbf0fd9ba29

2016-07-28 15:55:49+02:00: Andrea Palmieri
Update include

Signed-off-by: Andrea Palmieri <andrea.palmieri@st.com>

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wolfgang Betz 130:770ce14d3d15 1 /* mbed Microcontroller Library
Wolfgang Betz 130:770ce14d3d15 2 * Copyright (c) 2006-2013 ARM Limited
Wolfgang Betz 130:770ce14d3d15 3 *
Wolfgang Betz 130:770ce14d3d15 4 * Licensed under the Apache License, Version 2.0 (the "License");
Wolfgang Betz 130:770ce14d3d15 5 * you may not use this file except in compliance with the License.
Wolfgang Betz 130:770ce14d3d15 6 * You may obtain a copy of the License at
Wolfgang Betz 130:770ce14d3d15 7 *
Wolfgang Betz 130:770ce14d3d15 8 * http://www.apache.org/licenses/LICENSE-2.0
Wolfgang Betz 130:770ce14d3d15 9 *
Wolfgang Betz 130:770ce14d3d15 10 * Unless required by applicable law or agreed to in writing, software
Wolfgang Betz 130:770ce14d3d15 11 * distributed under the License is distributed on an "AS IS" BASIS,
Wolfgang Betz 130:770ce14d3d15 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Wolfgang Betz 130:770ce14d3d15 13 * See the License for the specific language governing permissions and
Wolfgang Betz 130:770ce14d3d15 14 * limitations under the License.
Wolfgang Betz 130:770ce14d3d15 15 */
Wolfgang Betz 130:770ce14d3d15 16
Wolfgang Betz 130:770ce14d3d15 17
Wolfgang Betz 130:770ce14d3d15 18 /**
Wolfgang Betz 130:770ce14d3d15 19 ******************************************************************************
Vincent Coubard 255:97adb68decd4 20 * @file BlueNRGGap.cpp
Wolfgang Betz 130:770ce14d3d15 21 * @author STMicroelectronics
Wolfgang Betz 130:770ce14d3d15 22 * @brief Implementation of BLE_API Gap Class
Wolfgang Betz 130:770ce14d3d15 23 ******************************************************************************
Wolfgang Betz 130:770ce14d3d15 24 * @copy
Wolfgang Betz 130:770ce14d3d15 25 *
Wolfgang Betz 130:770ce14d3d15 26 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
Wolfgang Betz 130:770ce14d3d15 27 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
Wolfgang Betz 130:770ce14d3d15 28 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
Wolfgang Betz 130:770ce14d3d15 29 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
Wolfgang Betz 130:770ce14d3d15 30 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
Wolfgang Betz 130:770ce14d3d15 31 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
Wolfgang Betz 130:770ce14d3d15 32 *
Wolfgang Betz 130:770ce14d3d15 33 * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
Andrea Palmieri 229:9981f62cdb1a 34 */
Wolfgang Betz 130:770ce14d3d15 35
Wolfgang Betz 130:770ce14d3d15 36 /** @defgroup BlueNRGGap
Wolfgang Betz 130:770ce14d3d15 37 * @brief BlueNRG BLE_API GAP Adaptation
Wolfgang Betz 130:770ce14d3d15 38 * @{
Wolfgang Betz 130:770ce14d3d15 39 */
Wolfgang Betz 130:770ce14d3d15 40
Wolfgang Betz 130:770ce14d3d15 41 #include "BlueNRGDevice.h"
Vincent Coubard 278:a5209d8cfd61 42 #ifdef YOTTA_CFG_MBED_OS
Vincent Coubard 278:a5209d8cfd61 43 #include "mbed-drivers/mbed.h"
Vincent Coubard 278:a5209d8cfd61 44 #else
Vincent Coubard 278:a5209d8cfd61 45 #include "mbed.h"
Vincent Coubard 278:a5209d8cfd61 46 #endif
Vincent Coubard 293:5a1f577bf92f 47 #include "ble_payload.h"
Vincent Coubard 293:5a1f577bf92f 48 #include "ble_utils.h"
Vincent Coubard 293:5a1f577bf92f 49 #include "ble_debug.h"
Wolfgang Betz 130:770ce14d3d15 50
Wolfgang Betz 130:770ce14d3d15 51 /*
Wolfgang Betz 130:770ce14d3d15 52 * Utility to process GAP specific events (e.g., Advertising timeout)
Wolfgang Betz 130:770ce14d3d15 53 */
Wolfgang Betz 130:770ce14d3d15 54 void BlueNRGGap::Process(void)
Vincent Coubard 255:97adb68decd4 55 {
Wolfgang Betz 130:770ce14d3d15 56 if(AdvToFlag) {
Wolfgang Betz 130:770ce14d3d15 57 stopAdvertising();
Wolfgang Betz 130:770ce14d3d15 58 }
Wolfgang Betz 130:770ce14d3d15 59
Wolfgang Betz 130:770ce14d3d15 60 }
Wolfgang Betz 130:770ce14d3d15 61
Wolfgang Betz 130:770ce14d3d15 62 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 63 /*!
Vincent Coubard 255:97adb68decd4 64 @brief Sets the advertising parameters and payload for the device.
Wolfgang Betz 130:770ce14d3d15 65 Note: Some data types give error when their adv data is updated using aci_gap_update_adv_data() API
Wolfgang Betz 130:770ce14d3d15 66
Wolfgang Betz 130:770ce14d3d15 67 @params[in] advData
Wolfgang Betz 130:770ce14d3d15 68 The primary advertising data payload
Wolfgang Betz 130:770ce14d3d15 69 @params[in] scanResponse
Wolfgang Betz 130:770ce14d3d15 70 The optional Scan Response payload if the advertising
Wolfgang Betz 130:770ce14d3d15 71 type is set to \ref GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED
Wolfgang Betz 130:770ce14d3d15 72 in \ref GapAdveritinngParams
Wolfgang Betz 130:770ce14d3d15 73
Wolfgang Betz 130:770ce14d3d15 74 @returns \ref ble_error_t
Wolfgang Betz 130:770ce14d3d15 75
Wolfgang Betz 130:770ce14d3d15 76 @retval BLE_ERROR_NONE
Wolfgang Betz 130:770ce14d3d15 77 Everything executed properly
Wolfgang Betz 130:770ce14d3d15 78
Wolfgang Betz 130:770ce14d3d15 79 @retval BLE_ERROR_BUFFER_OVERFLOW
Wolfgang Betz 130:770ce14d3d15 80 The proposed action would cause a buffer overflow. All
Wolfgang Betz 130:770ce14d3d15 81 advertising payloads must be <= 31 bytes, for example.
Wolfgang Betz 130:770ce14d3d15 82
Wolfgang Betz 130:770ce14d3d15 83 @retval BLE_ERROR_NOT_IMPLEMENTED
Wolfgang Betz 130:770ce14d3d15 84 A feature was requested that is not yet supported in the
Wolfgang Betz 130:770ce14d3d15 85 nRF51 firmware or hardware.
Wolfgang Betz 130:770ce14d3d15 86
Wolfgang Betz 130:770ce14d3d15 87 @retval BLE_ERROR_PARAM_OUT_OF_RANGE
Wolfgang Betz 130:770ce14d3d15 88 One of the proposed values is outside the valid range.
Wolfgang Betz 130:770ce14d3d15 89
Wolfgang Betz 130:770ce14d3d15 90 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 91
Wolfgang Betz 130:770ce14d3d15 92 @code
Wolfgang Betz 130:770ce14d3d15 93
Wolfgang Betz 130:770ce14d3d15 94 @endcode
Wolfgang Betz 130:770ce14d3d15 95 */
Wolfgang Betz 130:770ce14d3d15 96 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 97 ble_error_t BlueNRGGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse)
Vincent Coubard 255:97adb68decd4 98 {
Wolfgang Betz 132:51056160fa4a 99 PRINTF("BlueNRGGap::setAdvertisingData\n\r");
Wolfgang Betz 130:770ce14d3d15 100 /* Make sure we don't exceed the advertising payload length */
Wolfgang Betz 130:770ce14d3d15 101 if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
Andrea Palmieri 237:64c2ddbd9329 102 PRINTF("Exceeded the advertising payload length\n\r");
Wolfgang Betz 130:770ce14d3d15 103 return BLE_ERROR_BUFFER_OVERFLOW;
Wolfgang Betz 130:770ce14d3d15 104 }
Vincent Coubard 254:f4d217cadbde 105
Wolfgang Betz 130:770ce14d3d15 106 /* Make sure we have a payload! */
Vincent Coubard 270:ca649990a830 107 if (advData.getPayloadLen() != 0) {
Andrea Palmieri 236:2a73f3a97452 108 PayloadPtr loadPtr(advData.getPayload(), advData.getPayloadLen());
Andrea Palmieri 236:2a73f3a97452 109
Vincent Coubard 253:9665a6f8bbdb 110 /* Align the GAP Service Appearance Char value coherently
Vincent Coubard 253:9665a6f8bbdb 111 This setting is duplicate (see below GapAdvertisingData::APPEARANCE)
Vincent Coubard 253:9665a6f8bbdb 112 since BLE API has an overloaded function for appearance
Vincent Coubard 253:9665a6f8bbdb 113 */
Vincent Coubard 253:9665a6f8bbdb 114 STORE_LE_16(deviceAppearance, advData.getAppearance());
Vincent Coubard 253:9665a6f8bbdb 115 setAppearance((GapAdvertisingData::Appearance)(deviceAppearance[1]<<8|deviceAppearance[0]));
Vincent Coubard 254:f4d217cadbde 116
Vincent Coubard 254:f4d217cadbde 117
Vincent Coubard 255:97adb68decd4 118 for(uint8_t index=0; index<loadPtr.getPayloadUnitCount(); index++) {
Wolfgang Betz 130:770ce14d3d15 119 loadPtr.getUnitAtIndex(index);
Wolfgang Betz 130:770ce14d3d15 120
Wolfgang Betz 132:51056160fa4a 121 PRINTF("adData[%d].length=%d\n\r", index,(uint8_t)(*loadPtr.getUnitAtIndex(index).getLenPtr()));
Vincent Coubard 255:97adb68decd4 122 PRINTF("adData[%d].AdType=0x%x\n\r", index,(uint8_t)(*loadPtr.getUnitAtIndex(index).getAdTypePtr()));
Vincent Coubard 255:97adb68decd4 123
Wolfgang Betz 130:770ce14d3d15 124 switch(*loadPtr.getUnitAtIndex(index).getAdTypePtr()) {
Vincent Coubard 270:ca649990a830 125 /**< TX Power Level (in dBm) */
Vincent Coubard 270:ca649990a830 126 case GapAdvertisingData::TX_POWER_LEVEL:
Wolfgang Betz 130:770ce14d3d15 127 {
Vincent Coubard 255:97adb68decd4 128 PRINTF("Advertising type: TX_POWER_LEVEL\n\r");
Wolfgang Betz 130:770ce14d3d15 129 int8_t enHighPower = 0;
Wolfgang Betz 130:770ce14d3d15 130 int8_t paLevel = 0;
Andrea Palmieri 251:86df2c289e7c 131
Wolfgang Betz 130:770ce14d3d15 132 int8_t dbm = *loadPtr.getUnitAtIndex(index).getDataPtr();
Andrea Palmieri 251:86df2c289e7c 133 tBleStatus ret = getHighPowerAndPALevelValue(dbm, enHighPower, paLevel);
Andrea Palmieri 251:86df2c289e7c 134 #ifdef DEBUG
Andrea Palmieri 251:86df2c289e7c 135 PRINTF("dbm=%d, ret=%d\n\r", dbm, ret);
Andrea Palmieri 251:86df2c289e7c 136 PRINTF("enHighPower=%d, paLevel=%d\n\r", enHighPower, paLevel);
Wolfgang Betz 130:770ce14d3d15 137 #endif
Andrea Palmieri 251:86df2c289e7c 138 if(ret == BLE_STATUS_SUCCESS) {
Andrea Palmieri 251:86df2c289e7c 139 aci_hal_set_tx_power_level(enHighPower, paLevel);
Andrea Palmieri 251:86df2c289e7c 140 }
Wolfgang Betz 130:770ce14d3d15 141 break;
Wolfgang Betz 130:770ce14d3d15 142 }
Vincent Coubard 270:ca649990a830 143 /**< Appearance */
Vincent Coubard 270:ca649990a830 144 case GapAdvertisingData::APPEARANCE:
Vincent Coubard 253:9665a6f8bbdb 145 {
Vincent Coubard 253:9665a6f8bbdb 146 PRINTF("Advertising type: APPEARANCE\n\r");
Vincent Coubard 253:9665a6f8bbdb 147
Vincent Coubard 253:9665a6f8bbdb 148 GapAdvertisingData::Appearance appearanceP;
Vincent Coubard 253:9665a6f8bbdb 149 memcpy(deviceAppearance, loadPtr.getUnitAtIndex(index).getDataPtr(), 2);
Vincent Coubard 253:9665a6f8bbdb 150
Vincent Coubard 253:9665a6f8bbdb 151 PRINTF("input: deviceAppearance= 0x%x 0x%x\n\r", deviceAppearance[1], deviceAppearance[0]);
Vincent Coubard 253:9665a6f8bbdb 152
Vincent Coubard 253:9665a6f8bbdb 153 appearanceP = (GapAdvertisingData::Appearance)(deviceAppearance[1]<<8|deviceAppearance[0]);
Vincent Coubard 253:9665a6f8bbdb 154 /* Align the GAP Service Appearance Char value coherently */
Vincent Coubard 253:9665a6f8bbdb 155 setAppearance(appearanceP);
Vincent Coubard 253:9665a6f8bbdb 156 break;
Vincent Coubard 253:9665a6f8bbdb 157 }
Vincent Coubard 254:f4d217cadbde 158
Andrea Palmieri 236:2a73f3a97452 159 } // end switch
Andrea Palmieri 236:2a73f3a97452 160
Andrea Palmieri 236:2a73f3a97452 161 } //end for
Andrea Palmieri 236:2a73f3a97452 162
Wolfgang Betz 130:770ce14d3d15 163 }
Vincent Coubard 255:97adb68decd4 164
Vincent Coubard 270:ca649990a830 165 _advData = advData;
Vincent Coubard 270:ca649990a830 166 _scanResponse = scanResponse;
Vincent Coubard 255:97adb68decd4 167
Wolfgang Betz 130:770ce14d3d15 168 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 169 }
Wolfgang Betz 130:770ce14d3d15 170
Wolfgang Betz 130:770ce14d3d15 171 /*
Wolfgang Betz 130:770ce14d3d15 172 * Utility to set ADV timeout flag
Wolfgang Betz 130:770ce14d3d15 173 */
Wolfgang Betz 130:770ce14d3d15 174 void BlueNRGGap::setAdvToFlag(void) {
Wolfgang Betz 130:770ce14d3d15 175 AdvToFlag = true;
Wolfgang Betz 130:770ce14d3d15 176 }
Wolfgang Betz 130:770ce14d3d15 177
Wolfgang Betz 130:770ce14d3d15 178 /*
Wolfgang Betz 130:770ce14d3d15 179 * ADV timeout callback
Andrea Palmieri 229:9981f62cdb1a 180 */
Wolfgang Betz 138:32e3c4ca7a45 181 #ifdef AST_FOR_MBED_OS
Wolfgang Betz 132:51056160fa4a 182 static void advTimeoutCB(void)
Wolfgang Betz 132:51056160fa4a 183 {
Wolfgang Betz 132:51056160fa4a 184 Gap::GapState_t state;
Vincent Coubard 255:97adb68decd4 185
Wolfgang Betz 132:51056160fa4a 186 state = BlueNRGGap::getInstance().getState();
Wolfgang Betz 132:51056160fa4a 187 if (state.advertising == 1) {
Vincent Coubard 255:97adb68decd4 188
Wolfgang Betz 132:51056160fa4a 189 BlueNRGGap::getInstance().stopAdvertising();
Vincent Coubard 255:97adb68decd4 190
Wolfgang Betz 132:51056160fa4a 191 }
Wolfgang Betz 132:51056160fa4a 192 }
Wolfgang Betz 132:51056160fa4a 193 #else
Wolfgang Betz 130:770ce14d3d15 194 static void advTimeoutCB(void)
Wolfgang Betz 130:770ce14d3d15 195 {
Wolfgang Betz 130:770ce14d3d15 196 Gap::GapState_t state;
Vincent Coubard 255:97adb68decd4 197
Wolfgang Betz 130:770ce14d3d15 198 state = BlueNRGGap::getInstance().getState();
Wolfgang Betz 130:770ce14d3d15 199 if (state.advertising == 1) {
Vincent Coubard 255:97adb68decd4 200
Wolfgang Betz 130:770ce14d3d15 201 BlueNRGGap::getInstance().setAdvToFlag();
Vincent Coubard 255:97adb68decd4 202
Wolfgang Betz 130:770ce14d3d15 203 Timeout t = BlueNRGGap::getInstance().getAdvTimeout();
Wolfgang Betz 130:770ce14d3d15 204 t.detach(); /* disable the callback from the timeout */
Wolfgang Betz 130:770ce14d3d15 205
Wolfgang Betz 130:770ce14d3d15 206 }
Wolfgang Betz 130:770ce14d3d15 207 }
Wolfgang Betz 138:32e3c4ca7a45 208 #endif /* AST_FOR_MBED_OS */
Vincent Coubard 255:97adb68decd4 209
Wolfgang Betz 130:770ce14d3d15 210 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 211 /*!
Wolfgang Betz 130:770ce14d3d15 212 @brief Starts the BLE HW, initialising any services that were
Wolfgang Betz 130:770ce14d3d15 213 added before this function was called.
Vincent Coubard 255:97adb68decd4 214
Wolfgang Betz 130:770ce14d3d15 215 @param[in] params
Wolfgang Betz 130:770ce14d3d15 216 Basic advertising details, including the advertising
Wolfgang Betz 130:770ce14d3d15 217 delay, timeout and how the device should be advertised
Vincent Coubard 255:97adb68decd4 218
Wolfgang Betz 130:770ce14d3d15 219 @note All services must be added before calling this function!
Wolfgang Betz 130:770ce14d3d15 220
Wolfgang Betz 130:770ce14d3d15 221 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 222
Wolfgang Betz 130:770ce14d3d15 223 @retval BLE_ERROR_NONE
Wolfgang Betz 130:770ce14d3d15 224 Everything executed properly
Wolfgang Betz 130:770ce14d3d15 225
Wolfgang Betz 130:770ce14d3d15 226 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 227
Wolfgang Betz 130:770ce14d3d15 228 @code
Wolfgang Betz 130:770ce14d3d15 229
Wolfgang Betz 130:770ce14d3d15 230 @endcode
Wolfgang Betz 130:770ce14d3d15 231 */
Wolfgang Betz 130:770ce14d3d15 232 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 233
Wolfgang Betz 130:770ce14d3d15 234 ble_error_t BlueNRGGap::startAdvertising(const GapAdvertisingParams &params)
Andrea Palmieri 187:2e517d3ddd71 235 {
Andrea Palmieri 187:2e517d3ddd71 236 tBleStatus ret;
Vincent Coubard 270:ca649990a830 237 int err;
Andrea Palmieri 187:2e517d3ddd71 238
Wolfgang Betz 130:770ce14d3d15 239 /* Make sure we support the advertising type */
Wolfgang Betz 130:770ce14d3d15 240 if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) {
Andrea Palmieri 220:e02936f0d4c7 241 /* ToDo: This requires a proper security implementation, etc. */
Wolfgang Betz 130:770ce14d3d15 242 return BLE_ERROR_NOT_IMPLEMENTED;
Wolfgang Betz 130:770ce14d3d15 243 }
Wolfgang Betz 130:770ce14d3d15 244
Wolfgang Betz 130:770ce14d3d15 245 /* Check interval range */
Wolfgang Betz 130:770ce14d3d15 246 if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) {
Wolfgang Betz 130:770ce14d3d15 247 /* Min delay is slightly longer for unconnectable devices */
Wolfgang Betz 130:770ce14d3d15 248 if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) ||
Wolfgang Betz 130:770ce14d3d15 249 (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) {
Wolfgang Betz 130:770ce14d3d15 250 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Wolfgang Betz 130:770ce14d3d15 251 }
Wolfgang Betz 130:770ce14d3d15 252 } else {
Wolfgang Betz 130:770ce14d3d15 253 if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) ||
Wolfgang Betz 130:770ce14d3d15 254 (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) {
Wolfgang Betz 130:770ce14d3d15 255 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Wolfgang Betz 130:770ce14d3d15 256 }
Wolfgang Betz 130:770ce14d3d15 257 }
Wolfgang Betz 130:770ce14d3d15 258
Wolfgang Betz 130:770ce14d3d15 259 /* Check timeout is zero for Connectable Directed */
Wolfgang Betz 130:770ce14d3d15 260 if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) {
Wolfgang Betz 130:770ce14d3d15 261 /* Timeout must be 0 with this type, although we'll never get here */
Wolfgang Betz 130:770ce14d3d15 262 /* since this isn't implemented yet anyway */
Wolfgang Betz 130:770ce14d3d15 263 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Wolfgang Betz 130:770ce14d3d15 264 }
Wolfgang Betz 130:770ce14d3d15 265
Wolfgang Betz 130:770ce14d3d15 266 /* Check timeout for other advertising types */
Wolfgang Betz 130:770ce14d3d15 267 if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) &&
Wolfgang Betz 130:770ce14d3d15 268 (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) {
Wolfgang Betz 130:770ce14d3d15 269 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Wolfgang Betz 130:770ce14d3d15 270 }
Wolfgang Betz 130:770ce14d3d15 271
Andrea Palmieri 229:9981f62cdb1a 272 /*
Andrea Palmieri 229:9981f62cdb1a 273 * Advertising filter policy setting
Andrea Palmieri 229:9981f62cdb1a 274 * FIXME: the Security Manager should be implemented
Andrea Palmieri 229:9981f62cdb1a 275 */
Andrea Palmieri 229:9981f62cdb1a 276 AdvertisingPolicyMode_t mode = getAdvertisingPolicyMode();
Andrea Palmieri 229:9981f62cdb1a 277 if(mode != ADV_POLICY_IGNORE_WHITELIST) {
Andrea Palmieri 229:9981f62cdb1a 278 ret = aci_gap_configure_whitelist();
Andrea Palmieri 229:9981f62cdb1a 279 if(ret != BLE_STATUS_SUCCESS) {
Andrea Palmieri 229:9981f62cdb1a 280 PRINTF("aci_gap_configure_whitelist ret=0x%x\n\r", ret);
Andrea Palmieri 229:9981f62cdb1a 281 return BLE_ERROR_OPERATION_NOT_PERMITTED;
Andrea Palmieri 229:9981f62cdb1a 282 }
Andrea Palmieri 229:9981f62cdb1a 283 }
Andrea Palmieri 229:9981f62cdb1a 284
Andrea Palmieri 229:9981f62cdb1a 285 uint8_t advFilterPolicy = NO_WHITE_LIST_USE;
Andrea Palmieri 229:9981f62cdb1a 286 switch(mode) {
Andrea Palmieri 229:9981f62cdb1a 287 case ADV_POLICY_FILTER_SCAN_REQS:
Andrea Palmieri 229:9981f62cdb1a 288 advFilterPolicy = WHITE_LIST_FOR_ONLY_SCAN;
Andrea Palmieri 229:9981f62cdb1a 289 break;
Andrea Palmieri 229:9981f62cdb1a 290 case ADV_POLICY_FILTER_CONN_REQS:
Andrea Palmieri 229:9981f62cdb1a 291 advFilterPolicy = WHITE_LIST_FOR_ONLY_CONN;
Andrea Palmieri 229:9981f62cdb1a 292 break;
Andrea Palmieri 229:9981f62cdb1a 293 case ADV_POLICY_FILTER_ALL_REQS:
Andrea Palmieri 229:9981f62cdb1a 294 advFilterPolicy = WHITE_LIST_FOR_ALL;
Andrea Palmieri 229:9981f62cdb1a 295 break;
Andrea Palmieri 229:9981f62cdb1a 296 default:
Andrea Palmieri 229:9981f62cdb1a 297 advFilterPolicy = NO_WHITE_LIST_USE;
Andrea Palmieri 229:9981f62cdb1a 298 break;
Andrea Palmieri 229:9981f62cdb1a 299 }
Andrea Palmieri 229:9981f62cdb1a 300
Andrea Palmieri 228:25368f053411 301 /* Check the ADV type before setting scan response data */
Andrea Palmieri 228:25368f053411 302 if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED ||
Andrea Palmieri 228:25368f053411 303 params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) {
Andrea Palmieri 228:25368f053411 304
Andrea Palmieri 228:25368f053411 305 /* set scan response data */
Vincent Coubard 270:ca649990a830 306 PRINTF(" setting scan response data (_scanResponseLen=%u)\n", _scanResponse.getPayloadLen());
Vincent Coubard 270:ca649990a830 307 ret = hci_le_set_scan_resp_data(_scanResponse.getPayloadLen(), _scanResponse.getPayload());
Andrea Palmieri 228:25368f053411 308
Andrea Palmieri 228:25368f053411 309 if(BLE_STATUS_SUCCESS!=ret) {
Andrea Palmieri 228:25368f053411 310 PRINTF(" error while setting scan response data (ret=0x%x)\n", ret);
Andrea Palmieri 228:25368f053411 311 switch (ret) {
Andrea Palmieri 228:25368f053411 312 case BLE_STATUS_TIMEOUT:
Andrea Palmieri 228:25368f053411 313 return BLE_STACK_BUSY;
Andrea Palmieri 228:25368f053411 314 default:
Andrea Palmieri 228:25368f053411 315 return BLE_ERROR_UNSPECIFIED;
Andrea Palmieri 228:25368f053411 316 }
Andrea Palmieri 187:2e517d3ddd71 317 }
Andrea Palmieri 228:25368f053411 318 } else {
Andrea Palmieri 228:25368f053411 319 hci_le_set_scan_resp_data(0, NULL);
Andrea Palmieri 187:2e517d3ddd71 320 }
Wolfgang Betz 130:770ce14d3d15 321
Andrea Palmieri 232:aead10288880 322 setAdvParameters();
Andrea Palmieri 232:aead10288880 323 PRINTF("advInterval=%d advType=%d\n\r", advInterval, params.getAdvertisingType());
Wolfgang Betz 130:770ce14d3d15 324
Vincent Coubard 270:ca649990a830 325 err = hci_le_set_advertising_data(_advData.getPayloadLen(), _advData.getPayload());
Vincent Coubard 270:ca649990a830 326
Vincent Coubard 270:ca649990a830 327 if (err) {
Vincent Coubard 270:ca649990a830 328 PRINTF("error while setting the payload\r\n");
Vincent Coubard 270:ca649990a830 329 return BLE_ERROR_UNSPECIFIED;
Vincent Coubard 270:ca649990a830 330 }
Vincent Coubard 270:ca649990a830 331
Vincent Coubard 255:97adb68decd4 332 tBDAddr dummy_addr = { 0 };
Vincent Coubard 255:97adb68decd4 333 uint16_t advIntervalMin = advInterval == GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX ? advInterval - 1 : advInterval;
Vincent Coubard 255:97adb68decd4 334 uint16_t advIntervalMax = advIntervalMin + 1;
Vincent Coubard 255:97adb68decd4 335
Vincent Coubard 270:ca649990a830 336 err = hci_le_set_advertising_parameters(
Vincent Coubard 255:97adb68decd4 337 advIntervalMin,
Vincent Coubard 255:97adb68decd4 338 advIntervalMax,
Vincent Coubard 255:97adb68decd4 339 params.getAdvertisingType(),
Vincent Coubard 255:97adb68decd4 340 addr_type,
Vincent Coubard 255:97adb68decd4 341 0x00,
Vincent Coubard 255:97adb68decd4 342 dummy_addr,
Vincent Coubard 255:97adb68decd4 343 /* all channels */ 7,
Vincent Coubard 255:97adb68decd4 344 advFilterPolicy
Vincent Coubard 255:97adb68decd4 345 );
Vincent Coubard 255:97adb68decd4 346
Vincent Coubard 255:97adb68decd4 347 if (err) {
Vincent Coubard 259:323f588e5f57 348 PRINTF("impossible to set advertising parameters\n\r");
Vincent Coubard 259:323f588e5f57 349 PRINTF("advInterval min: %u, advInterval max: %u\n\r", advInterval, advInterval + 1);
Vincent Coubard 259:323f588e5f57 350 PRINTF("advType: %u, advFilterPolicy: %u\n\r", params.getAdvertisingType(), advFilterPolicy);
Vincent Coubard 255:97adb68decd4 351 return BLE_ERROR_INVALID_PARAM;
Vincent Coubard 255:97adb68decd4 352 }
Vincent Coubard 255:97adb68decd4 353
Vincent Coubard 255:97adb68decd4 354 err = hci_le_set_advertise_enable(0x01);
Vincent Coubard 255:97adb68decd4 355 if (err) {
Vincent Coubard 255:97adb68decd4 356 PRINTF("impossible to start advertising\n\r");
Vincent Coubard 255:97adb68decd4 357 return BLE_ERROR_UNSPECIFIED;
Vincent Coubard 255:97adb68decd4 358 }
Vincent Coubard 255:97adb68decd4 359
Vincent Coubard 255:97adb68decd4 360 state.advertising = 1;
Wolfgang Betz 130:770ce14d3d15 361
Vincent Coubard 255:97adb68decd4 362 AdvToFlag = false;
Vincent Coubard 255:97adb68decd4 363 if(params.getTimeout() != 0) {
Vincent Coubard 255:97adb68decd4 364 PRINTF("!!! attaching to!!!\n");
Vincent Coubard 255:97adb68decd4 365 #ifdef AST_FOR_MBED_OS
Vincent Coubard 255:97adb68decd4 366 minar::Scheduler::postCallback(advTimeoutCB).delay(minar::milliseconds(params.getTimeout() * 1000));
Vincent Coubard 255:97adb68decd4 367 #else
Vincent Coubard 255:97adb68decd4 368 advTimeout.attach(advTimeoutCB, params.getTimeout() * 1000);
Vincent Coubard 255:97adb68decd4 369 #endif
Vincent Coubard 255:97adb68decd4 370 }
Vincent Coubard 255:97adb68decd4 371
Vincent Coubard 255:97adb68decd4 372 return BLE_ERROR_NONE;
Vincent Coubard 255:97adb68decd4 373
Wolfgang Betz 130:770ce14d3d15 374 }
Wolfgang Betz 130:770ce14d3d15 375
Andrea Palmieri 238:b6454c839f42 376
Wolfgang Betz 130:770ce14d3d15 377 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 378 /*!
Wolfgang Betz 130:770ce14d3d15 379 @brief Stops the BLE HW and disconnects from any devices
Wolfgang Betz 130:770ce14d3d15 380
Wolfgang Betz 130:770ce14d3d15 381 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 382
Wolfgang Betz 130:770ce14d3d15 383 @retval BLE_ERROR_NONE
Wolfgang Betz 130:770ce14d3d15 384 Everything executed properly
Wolfgang Betz 130:770ce14d3d15 385
Wolfgang Betz 130:770ce14d3d15 386 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 387
Wolfgang Betz 130:770ce14d3d15 388 @code
Wolfgang Betz 130:770ce14d3d15 389
Wolfgang Betz 130:770ce14d3d15 390 @endcode
Wolfgang Betz 130:770ce14d3d15 391 */
Wolfgang Betz 130:770ce14d3d15 392 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 393 ble_error_t BlueNRGGap::stopAdvertising(void)
Wolfgang Betz 130:770ce14d3d15 394 {
Andrea Palmieri 229:9981f62cdb1a 395
Wolfgang Betz 130:770ce14d3d15 396 if(state.advertising == 1) {
Vincent Coubard 255:97adb68decd4 397
Vincent Coubard 255:97adb68decd4 398 int err = hci_le_set_advertise_enable(0);
Vincent Coubard 255:97adb68decd4 399 if (err) {
Vincent Coubard 255:97adb68decd4 400 return BLE_ERROR_OPERATION_NOT_PERMITTED;
Wolfgang Betz 130:770ce14d3d15 401 }
Vincent Coubard 255:97adb68decd4 402
Wolfgang Betz 132:51056160fa4a 403 PRINTF("Advertisement stopped!!\n\r") ;
Wolfgang Betz 130:770ce14d3d15 404 //Set GapState_t::advertising state
Wolfgang Betz 130:770ce14d3d15 405 state.advertising = 0;
Wolfgang Betz 130:770ce14d3d15 406 }
Vincent Coubard 255:97adb68decd4 407
Wolfgang Betz 130:770ce14d3d15 408 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 409 }
Wolfgang Betz 130:770ce14d3d15 410
Wolfgang Betz 130:770ce14d3d15 411 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 412 /*!
Wolfgang Betz 130:770ce14d3d15 413 @brief Disconnects if we are connected to a central device
Wolfgang Betz 130:770ce14d3d15 414
Wolfgang Betz 130:770ce14d3d15 415 @param[in] reason
Wolfgang Betz 130:770ce14d3d15 416 Disconnection Reason
Vincent Coubard 255:97adb68decd4 417
Wolfgang Betz 130:770ce14d3d15 418 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 419
Wolfgang Betz 130:770ce14d3d15 420 @retval BLE_ERROR_NONE
Wolfgang Betz 130:770ce14d3d15 421 Everything executed properly
Wolfgang Betz 130:770ce14d3d15 422
Wolfgang Betz 130:770ce14d3d15 423 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 424
Wolfgang Betz 130:770ce14d3d15 425 @code
Wolfgang Betz 130:770ce14d3d15 426
Wolfgang Betz 130:770ce14d3d15 427 @endcode
Wolfgang Betz 130:770ce14d3d15 428 */
Wolfgang Betz 130:770ce14d3d15 429 /**************************************************************************/
Andrea Palmieri 239:8e93d6e26c55 430 ble_error_t BlueNRGGap::disconnect(Handle_t connectionHandle, Gap::DisconnectionReason_t reason)
Wolfgang Betz 130:770ce14d3d15 431 {
Andrea Palmieri 239:8e93d6e26c55 432 tBleStatus ret;
Andrea Palmieri 142:adf1567d3900 433
Andrea Palmieri 239:8e93d6e26c55 434 ret = aci_gap_terminate(connectionHandle, reason);
Wolfgang Betz 130:770ce14d3d15 435
Andrea Palmieri 239:8e93d6e26c55 436 if (BLE_STATUS_SUCCESS != ret){
Andrea Palmieri 239:8e93d6e26c55 437 PRINTF("Error in GAP termination (ret=0x%x)!!\n\r", ret) ;
Andrea Palmieri 239:8e93d6e26c55 438 switch (ret) {
Andrea Palmieri 239:8e93d6e26c55 439 case ERR_COMMAND_DISALLOWED:
Andrea Palmieri 239:8e93d6e26c55 440 return BLE_ERROR_OPERATION_NOT_PERMITTED;
Andrea Palmieri 239:8e93d6e26c55 441 case BLE_STATUS_TIMEOUT:
Andrea Palmieri 239:8e93d6e26c55 442 return BLE_STACK_BUSY;
Andrea Palmieri 239:8e93d6e26c55 443 default:
Andrea Palmieri 239:8e93d6e26c55 444 return BLE_ERROR_UNSPECIFIED;
Wolfgang Betz 130:770ce14d3d15 445 }
Wolfgang Betz 130:770ce14d3d15 446 }
Vincent Coubard 255:97adb68decd4 447
Wolfgang Betz 130:770ce14d3d15 448 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 449 }
Wolfgang Betz 130:770ce14d3d15 450
Wolfgang Betz 130:770ce14d3d15 451 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 452 /*!
Wolfgang Betz 130:770ce14d3d15 453 @brief Disconnects if we are connected to a central device
Wolfgang Betz 130:770ce14d3d15 454
Wolfgang Betz 130:770ce14d3d15 455 @param[in] reason
Wolfgang Betz 130:770ce14d3d15 456 Disconnection Reason
Vincent Coubard 255:97adb68decd4 457
Wolfgang Betz 130:770ce14d3d15 458 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 459
Wolfgang Betz 130:770ce14d3d15 460 @retval BLE_ERROR_NONE
Wolfgang Betz 130:770ce14d3d15 461 Everything executed properly
Wolfgang Betz 130:770ce14d3d15 462
Wolfgang Betz 130:770ce14d3d15 463 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 464
Wolfgang Betz 130:770ce14d3d15 465 @code
Wolfgang Betz 130:770ce14d3d15 466
Wolfgang Betz 130:770ce14d3d15 467 @endcode
Wolfgang Betz 130:770ce14d3d15 468 */
Wolfgang Betz 130:770ce14d3d15 469 /**************************************************************************/
Andrea Palmieri 239:8e93d6e26c55 470 ble_error_t BlueNRGGap::disconnect(Gap::DisconnectionReason_t reason)
Wolfgang Betz 130:770ce14d3d15 471 {
Andrea Palmieri 239:8e93d6e26c55 472 return disconnect(m_connectionHandle, reason);
Wolfgang Betz 130:770ce14d3d15 473 }
Wolfgang Betz 130:770ce14d3d15 474
Wolfgang Betz 130:770ce14d3d15 475 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 476 /*!
Wolfgang Betz 130:770ce14d3d15 477 @brief Sets the 16-bit connection handle
Vincent Coubard 255:97adb68decd4 478
Andrea Palmieri 239:8e93d6e26c55 479 @param[in] conn_handle
Wolfgang Betz 130:770ce14d3d15 480 Connection Handle which is set in the Gap Instance
Vincent Coubard 255:97adb68decd4 481
Wolfgang Betz 130:770ce14d3d15 482 @returns void
Wolfgang Betz 130:770ce14d3d15 483 */
Wolfgang Betz 130:770ce14d3d15 484 /**************************************************************************/
Andrea Palmieri 239:8e93d6e26c55 485 void BlueNRGGap::setConnectionHandle(uint16_t conn_handle)
Wolfgang Betz 130:770ce14d3d15 486 {
Andrea Palmieri 239:8e93d6e26c55 487 m_connectionHandle = conn_handle;
Wolfgang Betz 130:770ce14d3d15 488 }
Wolfgang Betz 130:770ce14d3d15 489
Wolfgang Betz 130:770ce14d3d15 490 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 491 /*!
Wolfgang Betz 130:770ce14d3d15 492 @brief Gets the 16-bit connection handle
Vincent Coubard 255:97adb68decd4 493
Wolfgang Betz 130:770ce14d3d15 494 @param[in] void
Vincent Coubard 255:97adb68decd4 495
Wolfgang Betz 130:770ce14d3d15 496 @returns uint16_t
Wolfgang Betz 130:770ce14d3d15 497 Connection Handle of the Gap Instance
Wolfgang Betz 130:770ce14d3d15 498 */
Wolfgang Betz 130:770ce14d3d15 499 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 500 uint16_t BlueNRGGap::getConnectionHandle(void)
Wolfgang Betz 130:770ce14d3d15 501 {
Wolfgang Betz 130:770ce14d3d15 502 return m_connectionHandle;
Wolfgang Betz 130:770ce14d3d15 503 }
Wolfgang Betz 130:770ce14d3d15 504
Wolfgang Betz 130:770ce14d3d15 505 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 506 /*!
Wolfgang Betz 130:770ce14d3d15 507 @brief Sets the BLE device address. SetAddress will reset the BLE
Wolfgang Betz 130:770ce14d3d15 508 device and re-initialize BTLE. Will not start advertising.
Wolfgang Betz 130:770ce14d3d15 509
Wolfgang Betz 130:770ce14d3d15 510 @param[in] type
Wolfgang Betz 130:770ce14d3d15 511 Type of Address
Vincent Coubard 255:97adb68decd4 512
Wolfgang Betz 130:770ce14d3d15 513 @param[in] address[6]
Wolfgang Betz 130:770ce14d3d15 514 Value of the Address to be set
Vincent Coubard 255:97adb68decd4 515
Wolfgang Betz 130:770ce14d3d15 516 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 517
Wolfgang Betz 130:770ce14d3d15 518 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 519
Wolfgang Betz 130:770ce14d3d15 520 @code
Wolfgang Betz 130:770ce14d3d15 521
Wolfgang Betz 130:770ce14d3d15 522 @endcode
Wolfgang Betz 130:770ce14d3d15 523 */
Wolfgang Betz 130:770ce14d3d15 524 /**************************************************************************/
Andrea Palmieri 239:8e93d6e26c55 525 ble_error_t BlueNRGGap::setAddress(AddressType_t type, const BLEProtocol::AddressBytes_t address)
Wolfgang Betz 130:770ce14d3d15 526 {
Andrea Palmieri 210:08c4c85ca679 527 if (type > BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) {
Wolfgang Betz 130:770ce14d3d15 528 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Wolfgang Betz 130:770ce14d3d15 529 }
Vincent Coubard 255:97adb68decd4 530
Vincent Coubard 268:c0a1e03c5736 531 if(type == BLEProtocol::AddressType::PUBLIC){
Vincent Coubard 268:c0a1e03c5736 532 tBleStatus ret = aci_hal_write_config_data(
Vincent Coubard 268:c0a1e03c5736 533 CONFIG_DATA_PUBADDR_OFFSET,
Vincent Coubard 268:c0a1e03c5736 534 CONFIG_DATA_PUBADDR_LEN,
Vincent Coubard 268:c0a1e03c5736 535 address
Vincent Coubard 268:c0a1e03c5736 536 );
Andrea Palmieri 229:9981f62cdb1a 537 if(ret != BLE_STATUS_SUCCESS) {
Andrea Palmieri 239:8e93d6e26c55 538 return BLE_ERROR_OPERATION_NOT_PERMITTED;
Andrea Palmieri 229:9981f62cdb1a 539 }
Vincent Coubard 268:c0a1e03c5736 540 } else if (type == BLEProtocol::AddressType::RANDOM_STATIC) {
Vincent Coubard 268:c0a1e03c5736 541 // ensure that the random static address is well formed
Vincent Coubard 268:c0a1e03c5736 542 if ((address[5] & 0xC0) != 0xC0) {
Vincent Coubard 268:c0a1e03c5736 543 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Vincent Coubard 268:c0a1e03c5736 544 }
Vincent Coubard 268:c0a1e03c5736 545
Vincent Coubard 268:c0a1e03c5736 546 // thanks to const correctness of the API ...
Vincent Coubard 268:c0a1e03c5736 547 tBDAddr random_address = { 0 };
Vincent Coubard 268:c0a1e03c5736 548 memcpy(random_address, address, sizeof(random_address));
Vincent Coubard 268:c0a1e03c5736 549 int err = hci_le_set_random_address(random_address);
Vincent Coubard 268:c0a1e03c5736 550 if (err) {
Vincent Coubard 268:c0a1e03c5736 551 return BLE_ERROR_OPERATION_NOT_PERMITTED;
Vincent Coubard 268:c0a1e03c5736 552 }
Vincent Coubard 268:c0a1e03c5736 553
Vincent Coubard 268:c0a1e03c5736 554 // It is not possible to get the bluetooth address when it is set
Vincent Coubard 268:c0a1e03c5736 555 // store it locally in class data member
Vincent Coubard 268:c0a1e03c5736 556 memcpy(bdaddr, address, sizeof(bdaddr));
Andrea Palmieri 239:8e93d6e26c55 557 } else {
Vincent Coubard 268:c0a1e03c5736 558 // FIXME random addresses are not supported yet
Vincent Coubard 268:c0a1e03c5736 559 // BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE
Vincent Coubard 268:c0a1e03c5736 560 // BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE
Vincent Coubard 268:c0a1e03c5736 561 return BLE_ERROR_NOT_IMPLEMENTED;
Wolfgang Betz 130:770ce14d3d15 562 }
Vincent Coubard 255:97adb68decd4 563
Vincent Coubard 268:c0a1e03c5736 564 // if we're here then the address was correctly set
Vincent Coubard 268:c0a1e03c5736 565 // commit it inside the addr_type
Vincent Coubard 268:c0a1e03c5736 566 addr_type = type;
Vincent Coubard 268:c0a1e03c5736 567 isSetAddress = true;
Wolfgang Betz 130:770ce14d3d15 568 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 569 }
Andrea Palmieri 229:9981f62cdb1a 570
Wolfgang Betz 130:770ce14d3d15 571 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 572 /*!
Wolfgang Betz 130:770ce14d3d15 573 @brief Returns boolean if the address of the device has been set
Wolfgang Betz 130:770ce14d3d15 574 or not
Vincent Coubard 255:97adb68decd4 575
Wolfgang Betz 130:770ce14d3d15 576 @returns bool
Wolfgang Betz 130:770ce14d3d15 577
Wolfgang Betz 130:770ce14d3d15 578 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 579
Wolfgang Betz 130:770ce14d3d15 580 @code
Wolfgang Betz 130:770ce14d3d15 581
Wolfgang Betz 130:770ce14d3d15 582 @endcode
Wolfgang Betz 130:770ce14d3d15 583 */
Wolfgang Betz 130:770ce14d3d15 584 /**************************************************************************/
Vincent Coubard 255:97adb68decd4 585 bool BlueNRGGap::getIsSetAddress()
Wolfgang Betz 130:770ce14d3d15 586 {
Vincent Coubard 255:97adb68decd4 587 return isSetAddress;
Wolfgang Betz 130:770ce14d3d15 588 }
Wolfgang Betz 130:770ce14d3d15 589
Wolfgang Betz 130:770ce14d3d15 590 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 591 /*!
Wolfgang Betz 130:770ce14d3d15 592 @brief Returns the address of the device if set
Wolfgang Betz 130:770ce14d3d15 593
Wolfgang Betz 130:770ce14d3d15 594 @returns Pointer to the address if Address is set else NULL
Wolfgang Betz 130:770ce14d3d15 595
Wolfgang Betz 130:770ce14d3d15 596 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 597
Wolfgang Betz 130:770ce14d3d15 598 @code
Wolfgang Betz 130:770ce14d3d15 599
Wolfgang Betz 130:770ce14d3d15 600 @endcode
Wolfgang Betz 130:770ce14d3d15 601 */
Wolfgang Betz 130:770ce14d3d15 602 /**************************************************************************/
Vincent Coubard 265:46333d70cf81 603 ble_error_t BlueNRGGap::getAddress(BLEProtocol::AddressType_t *typeP, BLEProtocol::AddressBytes_t address)
Wolfgang Betz 130:770ce14d3d15 604 {
Andrea Palmieri 229:9981f62cdb1a 605 uint8_t bdaddr[BDADDR_SIZE];
Andrea Palmieri 229:9981f62cdb1a 606 uint8_t data_len_out;
Andrea Palmieri 229:9981f62cdb1a 607
Vincent Coubard 268:c0a1e03c5736 608 // precondition, check that pointers in input are valid
Vincent Coubard 268:c0a1e03c5736 609 if (typeP == NULL || address == NULL) {
Vincent Coubard 268:c0a1e03c5736 610 return BLE_ERROR_INVALID_PARAM;
Andrea Palmieri 228:25368f053411 611 }
Andrea Palmieri 228:25368f053411 612
Vincent Coubard 268:c0a1e03c5736 613 if (addr_type == BLEProtocol::AddressType::PUBLIC) {
Vincent Coubard 268:c0a1e03c5736 614 tBleStatus ret = aci_hal_read_config_data(CONFIG_DATA_PUBADDR_OFFSET, BDADDR_SIZE, &data_len_out, bdaddr);
Vincent Coubard 268:c0a1e03c5736 615 if(ret != BLE_STATUS_SUCCESS || data_len_out != BDADDR_SIZE) {
Vincent Coubard 268:c0a1e03c5736 616 return BLE_ERROR_UNSPECIFIED;
Vincent Coubard 268:c0a1e03c5736 617 }
Vincent Coubard 268:c0a1e03c5736 618 } else if (addr_type == BLEProtocol::AddressType::RANDOM_STATIC) {
Vincent Coubard 268:c0a1e03c5736 619 // FIXME hci_read_bd_addr and
Vincent Coubard 268:c0a1e03c5736 620 // aci_hal_read_config_data CONFIG_DATA_RANDOM_ADDRESS_IDB05A1
Vincent Coubard 268:c0a1e03c5736 621 // does not work, use the address stored in class data member
Vincent Coubard 268:c0a1e03c5736 622 memcpy(bdaddr, this->bdaddr, sizeof(bdaddr));
Vincent Coubard 268:c0a1e03c5736 623 } else {
Vincent Coubard 268:c0a1e03c5736 624 // FIXME: should be implemented with privacy features
Vincent Coubard 268:c0a1e03c5736 625 // BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE
Vincent Coubard 268:c0a1e03c5736 626 // BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE
Vincent Coubard 268:c0a1e03c5736 627 return BLE_ERROR_NOT_IMPLEMENTED;
Andrea Palmieri 229:9981f62cdb1a 628 }
Andrea Palmieri 229:9981f62cdb1a 629
Vincent Coubard 268:c0a1e03c5736 630 *typeP = addr_type;
Vincent Coubard 268:c0a1e03c5736 631 memcpy(address, bdaddr, BDADDR_SIZE);
Vincent Coubard 255:97adb68decd4 632
Wolfgang Betz 130:770ce14d3d15 633 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 634 }
Wolfgang Betz 130:770ce14d3d15 635
Wolfgang Betz 130:770ce14d3d15 636 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 637 /*!
Wolfgang Betz 130:770ce14d3d15 638 @brief obtains preferred connection params
Wolfgang Betz 130:770ce14d3d15 639
Wolfgang Betz 130:770ce14d3d15 640 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 641
Wolfgang Betz 130:770ce14d3d15 642 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 643
Wolfgang Betz 130:770ce14d3d15 644 @code
Wolfgang Betz 130:770ce14d3d15 645
Wolfgang Betz 130:770ce14d3d15 646 @endcode
Wolfgang Betz 130:770ce14d3d15 647 */
Wolfgang Betz 130:770ce14d3d15 648 /**************************************************************************/
Vincent Coubard 255:97adb68decd4 649 ble_error_t BlueNRGGap::getPreferredConnectionParams(ConnectionParams_t *params)
Wolfgang Betz 130:770ce14d3d15 650 {
Vincent Coubard 266:b49e28134d83 651 static const size_t parameter_size = 2;
Vincent Coubard 266:b49e28134d83 652
Vincent Coubard 266:b49e28134d83 653 if (!g_preferred_connection_parameters_char_handle) {
Vincent Coubard 266:b49e28134d83 654 return BLE_ERROR_OPERATION_NOT_PERMITTED;
Vincent Coubard 266:b49e28134d83 655 }
Vincent Coubard 266:b49e28134d83 656
Vincent Coubard 266:b49e28134d83 657 // Peripheral preferred connection parameters are an array of 4 uint16_t
Vincent Coubard 266:b49e28134d83 658 uint8_t parameters_packed[parameter_size * 4];
Vincent Coubard 266:b49e28134d83 659 uint16_t bytes_read = 0;
Andrea Palmieri 142:adf1567d3900 660
Vincent Coubard 266:b49e28134d83 661 tBleStatus err = aci_gatt_read_handle_value(
Vincent Coubard 266:b49e28134d83 662 g_preferred_connection_parameters_char_handle + BlueNRGGattServer::CHAR_VALUE_HANDLE,
Vincent Coubard 266:b49e28134d83 663 sizeof(parameters_packed),
Vincent Coubard 266:b49e28134d83 664 &bytes_read,
Vincent Coubard 266:b49e28134d83 665 parameters_packed
Vincent Coubard 266:b49e28134d83 666 );
Vincent Coubard 266:b49e28134d83 667
Vincent Coubard 266:b49e28134d83 668 PRINTF("getPreferredConnectionParams err=0x%02x (bytes_read=%u)\n\r", err, bytes_read);
Vincent Coubard 266:b49e28134d83 669
Vincent Coubard 266:b49e28134d83 670 // check that the read succeed and the result have the expected length
Vincent Coubard 266:b49e28134d83 671 if (err || bytes_read != sizeof(parameters_packed)) {
Vincent Coubard 266:b49e28134d83 672 return BLE_ERROR_UNSPECIFIED;
Vincent Coubard 266:b49e28134d83 673 }
Vincent Coubard 266:b49e28134d83 674
Vincent Coubard 266:b49e28134d83 675 // memcpy field by field
Vincent Coubard 266:b49e28134d83 676 memcpy(&params->minConnectionInterval, parameters_packed, parameter_size);
Vincent Coubard 266:b49e28134d83 677 memcpy(&params->maxConnectionInterval, &parameters_packed[parameter_size], parameter_size);
Vincent Coubard 266:b49e28134d83 678 memcpy(&params->slaveLatency, &parameters_packed[2 * parameter_size], parameter_size);
Vincent Coubard 266:b49e28134d83 679 memcpy(&params->connectionSupervisionTimeout, &parameters_packed[3 * parameter_size], parameter_size);
Vincent Coubard 266:b49e28134d83 680
Vincent Coubard 266:b49e28134d83 681 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 682 }
Wolfgang Betz 130:770ce14d3d15 683
Wolfgang Betz 130:770ce14d3d15 684
Wolfgang Betz 130:770ce14d3d15 685 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 686 /*!
Wolfgang Betz 130:770ce14d3d15 687 @brief sets preferred connection params
Wolfgang Betz 130:770ce14d3d15 688
Wolfgang Betz 130:770ce14d3d15 689 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 690
Wolfgang Betz 130:770ce14d3d15 691 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 692
Wolfgang Betz 130:770ce14d3d15 693 @code
Wolfgang Betz 130:770ce14d3d15 694
Wolfgang Betz 130:770ce14d3d15 695 @endcode
Wolfgang Betz 130:770ce14d3d15 696 */
Wolfgang Betz 130:770ce14d3d15 697 /**************************************************************************/
Vincent Coubard 255:97adb68decd4 698 ble_error_t BlueNRGGap::setPreferredConnectionParams(const ConnectionParams_t *params)
Wolfgang Betz 130:770ce14d3d15 699 {
Vincent Coubard 266:b49e28134d83 700 static const size_t parameter_size = 2;
Vincent Coubard 266:b49e28134d83 701 uint8_t parameters_packed[parameter_size * 4];
Vincent Coubard 266:b49e28134d83 702
Vincent Coubard 266:b49e28134d83 703 // ensure that parameters are correct
Vincent Coubard 266:b49e28134d83 704 // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C]
Vincent Coubard 266:b49e28134d83 705 // section 12.3 PERIPHERAL PREFERRED CONNECTION PARAMETERS CHARACTERISTIC
Vincent Coubard 266:b49e28134d83 706 if (((0x0006 > params->minConnectionInterval) || (params->minConnectionInterval > 0x0C80)) &&
Vincent Coubard 266:b49e28134d83 707 params->minConnectionInterval != 0xFFFF) {
Vincent Coubard 266:b49e28134d83 708 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Vincent Coubard 266:b49e28134d83 709 }
Vincent Coubard 266:b49e28134d83 710
Vincent Coubard 266:b49e28134d83 711 if (((params->minConnectionInterval > params->maxConnectionInterval) || (params->maxConnectionInterval > 0x0C80)) &&
Vincent Coubard 266:b49e28134d83 712 params->maxConnectionInterval != 0xFFFF) {
Vincent Coubard 266:b49e28134d83 713 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Vincent Coubard 266:b49e28134d83 714 }
Vincent Coubard 266:b49e28134d83 715
Vincent Coubard 266:b49e28134d83 716 if (params->slaveLatency > 0x01F3) {
Vincent Coubard 266:b49e28134d83 717 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Vincent Coubard 266:b49e28134d83 718 }
Vincent Coubard 266:b49e28134d83 719
Vincent Coubard 266:b49e28134d83 720 if (((0x000A > params->connectionSupervisionTimeout) || (params->connectionSupervisionTimeout > 0x0C80)) &&
Vincent Coubard 266:b49e28134d83 721 params->connectionSupervisionTimeout != 0xFFFF) {
Vincent Coubard 266:b49e28134d83 722 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Vincent Coubard 266:b49e28134d83 723 }
Andrea Palmieri 142:adf1567d3900 724
Vincent Coubard 266:b49e28134d83 725 // copy the parameters inside the byte array
Vincent Coubard 266:b49e28134d83 726 memcpy(parameters_packed, &params->minConnectionInterval, parameter_size);
Vincent Coubard 266:b49e28134d83 727 memcpy(&parameters_packed[parameter_size], &params->maxConnectionInterval, parameter_size);
Vincent Coubard 266:b49e28134d83 728 memcpy(&parameters_packed[2 * parameter_size], &params->slaveLatency, parameter_size);
Vincent Coubard 266:b49e28134d83 729 memcpy(&parameters_packed[3 * parameter_size], &params->connectionSupervisionTimeout, parameter_size);
Vincent Coubard 266:b49e28134d83 730
Vincent Coubard 266:b49e28134d83 731 tBleStatus err = aci_gatt_update_char_value(
Vincent Coubard 266:b49e28134d83 732 g_gap_service_handle,
Vincent Coubard 266:b49e28134d83 733 g_preferred_connection_parameters_char_handle,
Vincent Coubard 266:b49e28134d83 734 /* offset */ 0,
Vincent Coubard 266:b49e28134d83 735 sizeof(parameters_packed),
Vincent Coubard 266:b49e28134d83 736 parameters_packed
Vincent Coubard 266:b49e28134d83 737 );
Vincent Coubard 266:b49e28134d83 738
Vincent Coubard 266:b49e28134d83 739 if (err) {
Vincent Coubard 266:b49e28134d83 740 PRINTF("setPreferredConnectionParams failed (err=0x%x)!!\n\r", err) ;
Vincent Coubard 266:b49e28134d83 741 switch (err) {
Vincent Coubard 266:b49e28134d83 742 case BLE_STATUS_INVALID_HANDLE:
Vincent Coubard 266:b49e28134d83 743 case BLE_STATUS_INVALID_PARAMETER:
Vincent Coubard 266:b49e28134d83 744 return BLE_ERROR_INVALID_PARAM;
Vincent Coubard 266:b49e28134d83 745 case BLE_STATUS_INSUFFICIENT_RESOURCES:
Vincent Coubard 266:b49e28134d83 746 return BLE_ERROR_NO_MEM;
Vincent Coubard 266:b49e28134d83 747 case BLE_STATUS_TIMEOUT:
Vincent Coubard 266:b49e28134d83 748 return BLE_STACK_BUSY;
Vincent Coubard 266:b49e28134d83 749 default:
Vincent Coubard 266:b49e28134d83 750 return BLE_ERROR_UNSPECIFIED;
Vincent Coubard 266:b49e28134d83 751 }
Vincent Coubard 266:b49e28134d83 752 }
Vincent Coubard 266:b49e28134d83 753
Vincent Coubard 266:b49e28134d83 754 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 755 }
Wolfgang Betz 130:770ce14d3d15 756
Wolfgang Betz 130:770ce14d3d15 757 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 758 /*!
Wolfgang Betz 130:770ce14d3d15 759 @brief updates preferred connection params
Wolfgang Betz 130:770ce14d3d15 760
Wolfgang Betz 130:770ce14d3d15 761 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 762
Wolfgang Betz 130:770ce14d3d15 763 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 764
Wolfgang Betz 130:770ce14d3d15 765 @code
Wolfgang Betz 130:770ce14d3d15 766
Wolfgang Betz 130:770ce14d3d15 767 @endcode
Wolfgang Betz 130:770ce14d3d15 768 */
Wolfgang Betz 130:770ce14d3d15 769 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 770 ble_error_t BlueNRGGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *params)
Wolfgang Betz 130:770ce14d3d15 771 {
Vincent Coubard 272:4639da7705e1 772 tBleStatus ret = BLE_STATUS_SUCCESS;
Vincent Coubard 272:4639da7705e1 773
Vincent Coubard 272:4639da7705e1 774 if(gapRole == Gap::CENTRAL) {
Vincent Coubard 272:4639da7705e1 775 ret = aci_gap_start_connection_update(handle,
Vincent Coubard 272:4639da7705e1 776 params->minConnectionInterval,
Vincent Coubard 272:4639da7705e1 777 params->maxConnectionInterval,
Vincent Coubard 272:4639da7705e1 778 params->slaveLatency,
Vincent Coubard 272:4639da7705e1 779 params->connectionSupervisionTimeout,
Vincent Coubard 272:4639da7705e1 780 CONN_L1, CONN_L2);
Vincent Coubard 272:4639da7705e1 781 } else {
Vincent Coubard 272:4639da7705e1 782 ret = aci_l2cap_connection_parameter_update_request(handle,
Vincent Coubard 272:4639da7705e1 783 params->minConnectionInterval,
Vincent Coubard 272:4639da7705e1 784 params->maxConnectionInterval,
Vincent Coubard 272:4639da7705e1 785 params->slaveLatency,
Vincent Coubard 272:4639da7705e1 786 params->connectionSupervisionTimeout);
Vincent Coubard 272:4639da7705e1 787 }
Vincent Coubard 272:4639da7705e1 788
Vincent Coubard 272:4639da7705e1 789 if (BLE_STATUS_SUCCESS != ret){
Vincent Coubard 272:4639da7705e1 790 PRINTF("updateConnectionParams failed (ret=0x%x)!!\n\r", ret) ;
Vincent Coubard 272:4639da7705e1 791 switch (ret) {
Vincent Coubard 272:4639da7705e1 792 case ERR_INVALID_HCI_CMD_PARAMS:
Vincent Coubard 272:4639da7705e1 793 case BLE_STATUS_INVALID_PARAMETER:
Vincent Coubard 272:4639da7705e1 794 return BLE_ERROR_INVALID_PARAM;
Vincent Coubard 272:4639da7705e1 795 case ERR_COMMAND_DISALLOWED:
Vincent Coubard 272:4639da7705e1 796 case BLE_STATUS_NOT_ALLOWED:
Vincent Coubard 272:4639da7705e1 797 return BLE_ERROR_OPERATION_NOT_PERMITTED;
Vincent Coubard 272:4639da7705e1 798 default:
Vincent Coubard 272:4639da7705e1 799 return BLE_ERROR_UNSPECIFIED;
Vincent Coubard 272:4639da7705e1 800 }
Vincent Coubard 272:4639da7705e1 801 }
Andrea Palmieri 142:adf1567d3900 802
Wolfgang Betz 130:770ce14d3d15 803 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 804 }
Wolfgang Betz 130:770ce14d3d15 805
Wolfgang Betz 130:770ce14d3d15 806 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 807 /*!
Vincent Coubard 255:97adb68decd4 808 @brief Sets the Device Name Characteristic
Wolfgang Betz 130:770ce14d3d15 809
Wolfgang Betz 130:770ce14d3d15 810 @param[in] deviceName
Wolfgang Betz 130:770ce14d3d15 811 pointer to device name to be set
Wolfgang Betz 130:770ce14d3d15 812
Wolfgang Betz 130:770ce14d3d15 813 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 814
Wolfgang Betz 130:770ce14d3d15 815 @retval BLE_ERROR_NONE
Wolfgang Betz 130:770ce14d3d15 816 Everything executed properly
Wolfgang Betz 130:770ce14d3d15 817
Wolfgang Betz 130:770ce14d3d15 818 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 819
Wolfgang Betz 130:770ce14d3d15 820 @code
Wolfgang Betz 130:770ce14d3d15 821
Wolfgang Betz 130:770ce14d3d15 822 @endcode
Wolfgang Betz 130:770ce14d3d15 823 */
Wolfgang Betz 130:770ce14d3d15 824 /**************************************************************************/
Vincent Coubard 255:97adb68decd4 825 ble_error_t BlueNRGGap::setDeviceName(const uint8_t *deviceName)
Wolfgang Betz 130:770ce14d3d15 826 {
Andrea Palmieri 187:2e517d3ddd71 827 tBleStatus ret;
Vincent Coubard 255:97adb68decd4 828 uint8_t nameLen = 0;
Vincent Coubard 255:97adb68decd4 829
Andrea Palmieri 228:25368f053411 830 nameLen = strlen((const char*)deviceName);
Andrea Palmieri 228:25368f053411 831 PRINTF("DeviceName Size=%d\n\r", nameLen);
Andrea Palmieri 228:25368f053411 832
Andrea Palmieri 222:37a7e289ee3d 833 ret = aci_gatt_update_char_value(g_gap_service_handle,
Andrea Palmieri 222:37a7e289ee3d 834 g_device_name_char_handle,
Andrea Palmieri 222:37a7e289ee3d 835 0,
Andrea Palmieri 222:37a7e289ee3d 836 nameLen,
Andrea Palmieri 228:25368f053411 837 deviceName);
Andrea Palmieri 187:2e517d3ddd71 838
Andrea Palmieri 187:2e517d3ddd71 839 if (BLE_STATUS_SUCCESS != ret){
Andrea Palmieri 187:2e517d3ddd71 840 PRINTF("device set name failed (ret=0x%x)!!\n\r", ret) ;
Andrea Palmieri 187:2e517d3ddd71 841 switch (ret) {
Andrea Palmieri 187:2e517d3ddd71 842 case BLE_STATUS_INVALID_HANDLE:
Andrea Palmieri 187:2e517d3ddd71 843 case BLE_STATUS_INVALID_PARAMETER:
Andrea Palmieri 187:2e517d3ddd71 844 return BLE_ERROR_INVALID_PARAM;
Andrea Palmieri 187:2e517d3ddd71 845 case BLE_STATUS_INSUFFICIENT_RESOURCES:
Andrea Palmieri 187:2e517d3ddd71 846 return BLE_ERROR_NO_MEM;
Andrea Palmieri 187:2e517d3ddd71 847 case BLE_STATUS_TIMEOUT:
Andrea Palmieri 187:2e517d3ddd71 848 return BLE_STACK_BUSY;
Andrea Palmieri 187:2e517d3ddd71 849 default:
Andrea Palmieri 187:2e517d3ddd71 850 return BLE_ERROR_UNSPECIFIED;
Andrea Palmieri 187:2e517d3ddd71 851 }
Wolfgang Betz 130:770ce14d3d15 852 }
Wolfgang Betz 130:770ce14d3d15 853
Wolfgang Betz 130:770ce14d3d15 854 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 855 }
Wolfgang Betz 130:770ce14d3d15 856
Wolfgang Betz 130:770ce14d3d15 857 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 858 /*!
Vincent Coubard 255:97adb68decd4 859 @brief Gets the Device Name Characteristic
Wolfgang Betz 130:770ce14d3d15 860
Wolfgang Betz 130:770ce14d3d15 861 @param[in] deviceName
Vincent Coubard 255:97adb68decd4 862 pointer to device name
Wolfgang Betz 130:770ce14d3d15 863
Wolfgang Betz 130:770ce14d3d15 864 @param[in] lengthP
Vincent Coubard 255:97adb68decd4 865 pointer to device name length
Wolfgang Betz 130:770ce14d3d15 866
Wolfgang Betz 130:770ce14d3d15 867 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 868
Wolfgang Betz 130:770ce14d3d15 869 @retval BLE_ERROR_NONE
Wolfgang Betz 130:770ce14d3d15 870 Everything executed properly
Wolfgang Betz 130:770ce14d3d15 871
Wolfgang Betz 130:770ce14d3d15 872 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 873
Wolfgang Betz 130:770ce14d3d15 874 @code
Wolfgang Betz 130:770ce14d3d15 875
Wolfgang Betz 130:770ce14d3d15 876 @endcode
Wolfgang Betz 130:770ce14d3d15 877 */
Wolfgang Betz 130:770ce14d3d15 878 /**************************************************************************/
Andrea Palmieri 228:25368f053411 879 ble_error_t BlueNRGGap::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
Andrea Palmieri 228:25368f053411 880 {
Andrea Palmieri 228:25368f053411 881 tBleStatus ret;
Andrea Palmieri 228:25368f053411 882
Andrea Palmieri 229:9981f62cdb1a 883 ret = aci_gatt_read_handle_value(g_device_name_char_handle+BlueNRGGattServer::CHAR_VALUE_HANDLE,
Andrea Palmieri 228:25368f053411 884 *lengthP,
Andrea Palmieri 228:25368f053411 885 (uint16_t *)lengthP,
Andrea Palmieri 228:25368f053411 886 deviceName);
Andrea Palmieri 228:25368f053411 887 PRINTF("getDeviceName ret=0x%02x (lengthP=%d)\n\r", ret, *lengthP);
Andrea Palmieri 228:25368f053411 888 if (ret == BLE_STATUS_SUCCESS) {
Andrea Palmieri 228:25368f053411 889 return BLE_ERROR_NONE;
Andrea Palmieri 228:25368f053411 890 } else {
Andrea Palmieri 228:25368f053411 891 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Andrea Palmieri 228:25368f053411 892 }
Wolfgang Betz 130:770ce14d3d15 893 }
Wolfgang Betz 130:770ce14d3d15 894
Wolfgang Betz 130:770ce14d3d15 895 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 896 /*!
Vincent Coubard 255:97adb68decd4 897 @brief Sets the Device Appearance Characteristic
Wolfgang Betz 130:770ce14d3d15 898
Wolfgang Betz 130:770ce14d3d15 899 @param[in] appearance
Vincent Coubard 255:97adb68decd4 900 device appearance
Wolfgang Betz 130:770ce14d3d15 901
Wolfgang Betz 130:770ce14d3d15 902 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 903
Wolfgang Betz 130:770ce14d3d15 904 @retval BLE_ERROR_NONE
Wolfgang Betz 130:770ce14d3d15 905 Everything executed properly
Wolfgang Betz 130:770ce14d3d15 906
Wolfgang Betz 130:770ce14d3d15 907 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 908
Wolfgang Betz 130:770ce14d3d15 909 @code
Wolfgang Betz 130:770ce14d3d15 910
Wolfgang Betz 130:770ce14d3d15 911 @endcode
Wolfgang Betz 130:770ce14d3d15 912 */
Wolfgang Betz 130:770ce14d3d15 913 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 914 ble_error_t BlueNRGGap::setAppearance(GapAdvertisingData::Appearance appearance)
Wolfgang Betz 130:770ce14d3d15 915 {
Andrea Palmieri 187:2e517d3ddd71 916 tBleStatus ret;
Andrea Palmieri 228:25368f053411 917 uint8_t deviceAppearance[2];
Andrea Palmieri 187:2e517d3ddd71 918
Vincent Coubard 255:97adb68decd4 919 STORE_LE_16(deviceAppearance, appearance);
Vincent Coubard 253:9665a6f8bbdb 920 PRINTF("setAppearance= 0x%x 0x%x\n\r", deviceAppearance[1], deviceAppearance[0]);
Vincent Coubard 255:97adb68decd4 921
Andrea Palmieri 228:25368f053411 922 ret = aci_gatt_update_char_value(g_gap_service_handle,
Andrea Palmieri 228:25368f053411 923 g_appearance_char_handle,
Andrea Palmieri 228:25368f053411 924 0, 2, (uint8_t *)deviceAppearance);
Andrea Palmieri 187:2e517d3ddd71 925 if (BLE_STATUS_SUCCESS == ret){
Andrea Palmieri 187:2e517d3ddd71 926 return BLE_ERROR_NONE;
Andrea Palmieri 187:2e517d3ddd71 927 }
Andrea Palmieri 187:2e517d3ddd71 928
Andrea Palmieri 217:23870c55b07e 929 PRINTF("setAppearance failed (ret=0x%x)!!\n\r", ret);
Andrea Palmieri 187:2e517d3ddd71 930 switch (ret) {
Andrea Palmieri 187:2e517d3ddd71 931 case BLE_STATUS_INVALID_HANDLE:
Andrea Palmieri 187:2e517d3ddd71 932 case BLE_STATUS_INVALID_PARAMETER:
Andrea Palmieri 187:2e517d3ddd71 933 return BLE_ERROR_INVALID_PARAM;
Andrea Palmieri 187:2e517d3ddd71 934 case BLE_STATUS_INSUFFICIENT_RESOURCES:
Andrea Palmieri 187:2e517d3ddd71 935 return BLE_ERROR_NO_MEM;
Andrea Palmieri 187:2e517d3ddd71 936 case BLE_STATUS_TIMEOUT:
Andrea Palmieri 187:2e517d3ddd71 937 return BLE_STACK_BUSY;
Andrea Palmieri 187:2e517d3ddd71 938 default:
Andrea Palmieri 187:2e517d3ddd71 939 return BLE_ERROR_UNSPECIFIED;
Andrea Palmieri 187:2e517d3ddd71 940 }
Wolfgang Betz 130:770ce14d3d15 941 }
Wolfgang Betz 130:770ce14d3d15 942
Wolfgang Betz 130:770ce14d3d15 943 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 944 /*!
Wolfgang Betz 130:770ce14d3d15 945 @brief Gets the Device Appearance Characteristic
Wolfgang Betz 130:770ce14d3d15 946
Wolfgang Betz 130:770ce14d3d15 947 @param[in] appearance
Vincent Coubard 255:97adb68decd4 948 pointer to device appearance value
Wolfgang Betz 130:770ce14d3d15 949
Wolfgang Betz 130:770ce14d3d15 950 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 951
Wolfgang Betz 130:770ce14d3d15 952 @retval BLE_ERROR_NONE
Wolfgang Betz 130:770ce14d3d15 953 Everything executed properly
Wolfgang Betz 130:770ce14d3d15 954
Wolfgang Betz 130:770ce14d3d15 955 @section EXAMPLE
Wolfgang Betz 130:770ce14d3d15 956
Wolfgang Betz 130:770ce14d3d15 957 @code
Wolfgang Betz 130:770ce14d3d15 958
Wolfgang Betz 130:770ce14d3d15 959 @endcode
Wolfgang Betz 130:770ce14d3d15 960 */
Wolfgang Betz 130:770ce14d3d15 961 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 962 ble_error_t BlueNRGGap::getAppearance(GapAdvertisingData::Appearance *appearanceP)
Wolfgang Betz 130:770ce14d3d15 963 {
Andrea Palmieri 228:25368f053411 964 tBleStatus ret;
Andrea Palmieri 228:25368f053411 965 uint16_t lengthP = 2;
Andrea Palmieri 228:25368f053411 966
Andrea Palmieri 229:9981f62cdb1a 967 ret = aci_gatt_read_handle_value(g_appearance_char_handle+BlueNRGGattServer::CHAR_VALUE_HANDLE,
Andrea Palmieri 228:25368f053411 968 lengthP,
Andrea Palmieri 228:25368f053411 969 &lengthP,
Andrea Palmieri 228:25368f053411 970 (uint8_t*)appearanceP);
Andrea Palmieri 228:25368f053411 971 PRINTF("getAppearance ret=0x%02x (lengthP=%d)\n\r", ret, lengthP);
Andrea Palmieri 228:25368f053411 972 if (ret == BLE_STATUS_SUCCESS) {
Andrea Palmieri 228:25368f053411 973 return BLE_ERROR_NONE;
Andrea Palmieri 228:25368f053411 974 } else {
Andrea Palmieri 228:25368f053411 975 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Andrea Palmieri 228:25368f053411 976 }
Andrea Palmieri 228:25368f053411 977
Wolfgang Betz 130:770ce14d3d15 978 }
Wolfgang Betz 130:770ce14d3d15 979
Andrea Palmieri 160:174387d53809 980 GapScanningParams* BlueNRGGap::getScanningParams(void)
Andrea Palmieri 160:174387d53809 981 {
Andrea Palmieri 160:174387d53809 982 return &_scanningParams;
Andrea Palmieri 160:174387d53809 983 }
Andrea Palmieri 160:174387d53809 984
Wolfgang Betz 165:3576598c0889 985 static void makeConnection(void)
Wolfgang Betz 162:667f97a4db7f 986 {
Wolfgang Betz 165:3576598c0889 987 BlueNRGGap::getInstance().createConnection();
Wolfgang Betz 162:667f97a4db7f 988 }
Wolfgang Betz 162:667f97a4db7f 989
Wolfgang Betz 132:51056160fa4a 990 void BlueNRGGap::Discovery_CB(Reason_t reason,
Wolfgang Betz 132:51056160fa4a 991 uint8_t adv_type,
Andrea Palmieri 229:9981f62cdb1a 992 uint8_t addr_type,
Wolfgang Betz 132:51056160fa4a 993 uint8_t *addr,
Wolfgang Betz 132:51056160fa4a 994 uint8_t *data_length,
Wolfgang Betz 132:51056160fa4a 995 uint8_t *data,
Wolfgang Betz 132:51056160fa4a 996 uint8_t *RSSI)
Wolfgang Betz 132:51056160fa4a 997 {
Wolfgang Betz 132:51056160fa4a 998 switch (reason) {
Wolfgang Betz 132:51056160fa4a 999 case DEVICE_FOUND:
Wolfgang Betz 132:51056160fa4a 1000 {
Wolfgang Betz 132:51056160fa4a 1001 GapAdvertisingParams::AdvertisingType_t type;
Wolfgang Betz 132:51056160fa4a 1002 bool isScanResponse = false;
Andrea Palmieri 229:9981f62cdb1a 1003
Andrea Palmieri 229:9981f62cdb1a 1004 /*
Andrea Palmieri 229:9981f62cdb1a 1005 * Whitelisting (scan policy):
Andrea Palmieri 229:9981f62cdb1a 1006 * SCAN_POLICY_FILTER_ALL_ADV (ADV packets only from devs in the White List) &&
Andrea Palmieri 229:9981f62cdb1a 1007 * Private Random Address
Andrea Palmieri 229:9981f62cdb1a 1008 * => scan_results = FALSE
Andrea Palmieri 229:9981f62cdb1a 1009 * FIXME: the Security Manager should be implemented
Andrea Palmieri 229:9981f62cdb1a 1010 */
Andrea Palmieri 229:9981f62cdb1a 1011 ScanningPolicyMode_t mode = getScanningPolicyMode();
Andrea Palmieri 229:9981f62cdb1a 1012 PRINTF("mode=%u addr_type=%u\n\r", mode, addr_type);
Andrea Palmieri 229:9981f62cdb1a 1013 if(mode == Gap::SCAN_POLICY_FILTER_ALL_ADV ||
Andrea Palmieri 229:9981f62cdb1a 1014 (addr_type == RESOLVABLE_PRIVATE_ADDR ||
Andrea Palmieri 229:9981f62cdb1a 1015 addr_type == NON_RESOLVABLE_PRIVATE_ADDR)) {
Andrea Palmieri 229:9981f62cdb1a 1016 return;
Andrea Palmieri 229:9981f62cdb1a 1017 }
Andrea Palmieri 229:9981f62cdb1a 1018
Wolfgang Betz 132:51056160fa4a 1019 switch(adv_type) {
Wolfgang Betz 132:51056160fa4a 1020 case ADV_IND:
Wolfgang Betz 132:51056160fa4a 1021 type = GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED;
Wolfgang Betz 132:51056160fa4a 1022 break;
Wolfgang Betz 132:51056160fa4a 1023 case ADV_DIRECT_IND:
Wolfgang Betz 132:51056160fa4a 1024 type = GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED;
Wolfgang Betz 132:51056160fa4a 1025 break;
Wolfgang Betz 132:51056160fa4a 1026 case ADV_SCAN_IND:
Wolfgang Betz 132:51056160fa4a 1027 case SCAN_RSP:
Wolfgang Betz 132:51056160fa4a 1028 type = GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED;
Wolfgang Betz 132:51056160fa4a 1029 isScanResponse = true;
Wolfgang Betz 132:51056160fa4a 1030 break;
Wolfgang Betz 132:51056160fa4a 1031 case ADV_NONCONN_IND:
Wolfgang Betz 132:51056160fa4a 1032 type = GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED;
Andrea Palmieri 142:adf1567d3900 1033 break;
Andrea Palmieri 142:adf1567d3900 1034 default:
Andrea Palmieri 142:adf1567d3900 1035 type = GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED;
Wolfgang Betz 132:51056160fa4a 1036 }
Vincent Coubard 255:97adb68decd4 1037
Andrea Palmieri 217:23870c55b07e 1038 PRINTF("data_length=%d adv peerAddr[%02x %02x %02x %02x %02x %02x] \r\n",
Andrea Palmieri 217:23870c55b07e 1039 *data_length, addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
Andrea Palmieri 238:b6454c839f42 1040 if(!_connecting) {
Andrea Palmieri 238:b6454c839f42 1041 processAdvertisementReport(addr, *RSSI, isScanResponse, type, *data_length, data);
Andrea Palmieri 238:b6454c839f42 1042 }
Andrea Palmieri 160:174387d53809 1043 PRINTF("!!!After processAdvertisementReport\n\r");
Wolfgang Betz 132:51056160fa4a 1044 }
Wolfgang Betz 132:51056160fa4a 1045 break;
Vincent Coubard 255:97adb68decd4 1046
Wolfgang Betz 132:51056160fa4a 1047 case DISCOVERY_COMPLETE:
Wolfgang Betz 132:51056160fa4a 1048 // The discovery is complete. If this is due to a stop scanning (i.e., the device
Wolfgang Betz 132:51056160fa4a 1049 // we are interested in has been found) and a connection has been requested
Andrea Palmieri 229:9981f62cdb1a 1050 // then we start the device connection.
Andrea Palmieri 145:024a552e4715 1051 PRINTF("DISCOVERY_COMPLETE\n\r");
Wolfgang Betz 132:51056160fa4a 1052 _scanning = false;
Wolfgang Betz 132:51056160fa4a 1053
Wolfgang Betz 165:3576598c0889 1054 // Since the DISCOVERY_COMPLETE event can be received during the scanning interval,
Andrea Palmieri 229:9981f62cdb1a 1055 // we need to delay the starting of connection
Wolfgang Betz 165:3576598c0889 1056 uint16_t delay = 2*(_scanningParams.getInterval());
Wolfgang Betz 165:3576598c0889 1057
Andrea Palmieri 217:23870c55b07e 1058 #ifdef AST_FOR_MBED_OS
Wolfgang Betz 162:667f97a4db7f 1059 if(_connecting) {
Wolfgang Betz 165:3576598c0889 1060 minar::Scheduler::postCallback(makeConnection).delay(minar::milliseconds(delay));
Wolfgang Betz 132:51056160fa4a 1061 }
Andrea Palmieri 217:23870c55b07e 1062 #else
Andrea Palmieri 217:23870c55b07e 1063 Clock_Wait(delay);
Andrea Palmieri 217:23870c55b07e 1064 if(_connecting) {
Andrea Palmieri 217:23870c55b07e 1065 makeConnection();
Andrea Palmieri 217:23870c55b07e 1066 }
Andrea Palmieri 217:23870c55b07e 1067 #endif /* AST_FOR_MBED_OS */
Wolfgang Betz 132:51056160fa4a 1068
Wolfgang Betz 132:51056160fa4a 1069 break;
Wolfgang Betz 132:51056160fa4a 1070 }
Wolfgang Betz 132:51056160fa4a 1071 }
Wolfgang Betz 132:51056160fa4a 1072
Wolfgang Betz 132:51056160fa4a 1073 ble_error_t BlueNRGGap::startRadioScan(const GapScanningParams &scanningParams)
Wolfgang Betz 132:51056160fa4a 1074 {
Vincent Coubard 255:97adb68decd4 1075
Wolfgang Betz 165:3576598c0889 1076 tBleStatus ret = BLE_STATUS_SUCCESS;
Andrea Palmieri 222:37a7e289ee3d 1077
Andrea Palmieri 222:37a7e289ee3d 1078 // Stop ADV before scanning
Andrea Palmieri 223:36df860f7ffc 1079 /*
Andrea Palmieri 222:37a7e289ee3d 1080 if (state.advertising == 1) {
Andrea Palmieri 222:37a7e289ee3d 1081 stopAdvertising();
Andrea Palmieri 222:37a7e289ee3d 1082 }
Andrea Palmieri 223:36df860f7ffc 1083 */
Andrea Palmieri 222:37a7e289ee3d 1084
Andrea Palmieri 229:9981f62cdb1a 1085 /*
Andrea Palmieri 229:9981f62cdb1a 1086 * Whitelisting (scan policy):
Andrea Palmieri 229:9981f62cdb1a 1087 * SCAN_POLICY_FILTER_ALL_ADV (ADV packets only from devs in the White List) &&
Andrea Palmieri 229:9981f62cdb1a 1088 * White List is empty
Andrea Palmieri 229:9981f62cdb1a 1089 * => scan operation = FAILURE
Andrea Palmieri 229:9981f62cdb1a 1090 * FIXME: the Security Manager should be implemented
Andrea Palmieri 229:9981f62cdb1a 1091 */
Andrea Palmieri 229:9981f62cdb1a 1092 ScanningPolicyMode_t mode = getScanningPolicyMode();
Andrea Palmieri 229:9981f62cdb1a 1093 uint8_t whiteListSize = whitelistAddresses.size;
Andrea Palmieri 229:9981f62cdb1a 1094 if(whiteListSize == 0 && mode == Gap::SCAN_POLICY_FILTER_ALL_ADV) {
Andrea Palmieri 229:9981f62cdb1a 1095 return BLE_ERROR_OPERATION_NOT_PERMITTED;
Andrea Palmieri 229:9981f62cdb1a 1096 }
Andrea Palmieri 229:9981f62cdb1a 1097
Andrea Palmieri 217:23870c55b07e 1098 ret = btleStartRadioScan(scanningParams.getActiveScanning(),
Andrea Palmieri 217:23870c55b07e 1099 scanningParams.getInterval(),
Andrea Palmieri 217:23870c55b07e 1100 scanningParams.getWindow(),
Andrea Palmieri 217:23870c55b07e 1101 addr_type);
Andrea Palmieri 217:23870c55b07e 1102
Andrea Palmieri 229:9981f62cdb1a 1103 PRINTF("Scanning...\n\r");
Andrea Palmieri 229:9981f62cdb1a 1104 PRINTF("scanningParams.getInterval()=%u[msec]\r\n",(scanningParams.getInterval()*625)/1000);
Andrea Palmieri 229:9981f62cdb1a 1105 PRINTF("scanningParams.getWindow()=%u[msec]\r\n",(scanningParams.getWindow()*625)/1000);
Andrea Palmieri 229:9981f62cdb1a 1106 //PRINTF("_advParams.getInterval()=%u\r\n",_advParams.getInterval());
Andrea Palmieri 229:9981f62cdb1a 1107 //PRINTF("CONN_P1=%u\r\n",(unsigned)CONN_P1);
Andrea Palmieri 229:9981f62cdb1a 1108 //PRINTF("CONN_P2=%u\r\n",(unsigned)CONN_P2);
Andrea Palmieri 217:23870c55b07e 1109 if (BLE_STATUS_SUCCESS == ret){
Andrea Palmieri 217:23870c55b07e 1110 PRINTF("Observation Procedure Started\n");
Andrea Palmieri 217:23870c55b07e 1111 _scanning = true;
Andrea Palmieri 217:23870c55b07e 1112 return BLE_ERROR_NONE;
Andrea Palmieri 145:024a552e4715 1113 }
Andrea Palmieri 217:23870c55b07e 1114
Andrea Palmieri 217:23870c55b07e 1115 // Observer role is not supported by X-NUCLEO-IDB04A1, return BLE_ERROR_NOT_IMPLEMENTED
Andrea Palmieri 217:23870c55b07e 1116 switch (ret) {
Andrea Palmieri 217:23870c55b07e 1117 case BLE_STATUS_INVALID_CID:
Andrea Palmieri 229:9981f62cdb1a 1118 PRINTF("Observation Procedure not implemented!!!\n\r");
Andrea Palmieri 217:23870c55b07e 1119 return BLE_ERROR_NOT_IMPLEMENTED;
Andrea Palmieri 217:23870c55b07e 1120 default:
Andrea Palmieri 229:9981f62cdb1a 1121 PRINTF("Observation Procedure failed (0x%02X)\n\r", ret);
Andrea Palmieri 217:23870c55b07e 1122 return BLE_ERROR_UNSPECIFIED;
Wolfgang Betz 132:51056160fa4a 1123 }
Andrea Palmieri 217:23870c55b07e 1124
Wolfgang Betz 130:770ce14d3d15 1125 }
Wolfgang Betz 130:770ce14d3d15 1126
Wolfgang Betz 130:770ce14d3d15 1127 ble_error_t BlueNRGGap::stopScan() {
Wolfgang Betz 165:3576598c0889 1128 tBleStatus ret = BLE_STATUS_SUCCESS;
Andrea Palmieri 229:9981f62cdb1a 1129
Andrea Palmieri 229:9981f62cdb1a 1130 PRINTF("stopScan\n\r");
Andrea Palmieri 217:23870c55b07e 1131 ret = aci_gap_terminate_gap_procedure(GAP_OBSERVATION_PROC);
Vincent Coubard 255:97adb68decd4 1132
Wolfgang Betz 132:51056160fa4a 1133 if (ret != BLE_STATUS_SUCCESS) {
Andrea Palmieri 238:b6454c839f42 1134 PRINTF("GAP Terminate Gap Procedure failed(ret=0x%x)\n", ret);
Vincent Coubard 255:97adb68decd4 1135 return BLE_ERROR_UNSPECIFIED;
Wolfgang Betz 132:51056160fa4a 1136 } else {
Wolfgang Betz 132:51056160fa4a 1137 PRINTF("Discovery Procedure Terminated\n");
Vincent Coubard 255:97adb68decd4 1138 return BLE_ERROR_NONE;
Wolfgang Betz 132:51056160fa4a 1139 }
Wolfgang Betz 130:770ce14d3d15 1140 }
Wolfgang Betz 130:770ce14d3d15 1141
Wolfgang Betz 130:770ce14d3d15 1142 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 1143 /*!
Wolfgang Betz 130:770ce14d3d15 1144 @brief set Tx power level
Wolfgang Betz 130:770ce14d3d15 1145 @param[in] txPower Transmission Power level
Wolfgang Betz 130:770ce14d3d15 1146 @returns ble_error_t
Wolfgang Betz 130:770ce14d3d15 1147 */
Wolfgang Betz 130:770ce14d3d15 1148 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 1149 ble_error_t BlueNRGGap::setTxPower(int8_t txPower)
Wolfgang Betz 130:770ce14d3d15 1150 {
Wolfgang Betz 130:770ce14d3d15 1151 tBleStatus ret;
Vincent Coubard 255:97adb68decd4 1152
Wolfgang Betz 130:770ce14d3d15 1153 int8_t enHighPower = 0;
Andrea Palmieri 201:a9bc2e8b01d7 1154 int8_t paLevel = 0;
Andrea Palmieri 201:a9bc2e8b01d7 1155
Andrea Palmieri 228:25368f053411 1156 ret = getHighPowerAndPALevelValue(txPower, enHighPower, paLevel);
Andrea Palmieri 228:25368f053411 1157 if(ret!=BLE_STATUS_SUCCESS) {
Andrea Palmieri 228:25368f053411 1158 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Andrea Palmieri 228:25368f053411 1159 }
Andrea Palmieri 201:a9bc2e8b01d7 1160
Vincent Coubard 255:97adb68decd4 1161 PRINTF("enHighPower=%d, paLevel=%d\n\r", enHighPower, paLevel);
Wolfgang Betz 130:770ce14d3d15 1162 ret = aci_hal_set_tx_power_level(enHighPower, paLevel);
Wolfgang Betz 130:770ce14d3d15 1163 if(ret!=BLE_STATUS_SUCCESS) {
Andrea Palmieri 228:25368f053411 1164 return BLE_ERROR_PARAM_OUT_OF_RANGE;
Wolfgang Betz 130:770ce14d3d15 1165 }
Andrea Palmieri 201:a9bc2e8b01d7 1166
Wolfgang Betz 130:770ce14d3d15 1167 return BLE_ERROR_NONE;
Wolfgang Betz 130:770ce14d3d15 1168 }
Wolfgang Betz 130:770ce14d3d15 1169
Wolfgang Betz 130:770ce14d3d15 1170 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 1171 /*!
Wolfgang Betz 130:770ce14d3d15 1172 @brief get permitted Tx power values
Wolfgang Betz 130:770ce14d3d15 1173 @param[in] values pointer to pointer to permitted power values
Vincent Coubard 255:97adb68decd4 1174 @param[in] num number of values
Wolfgang Betz 130:770ce14d3d15 1175 */
Wolfgang Betz 130:770ce14d3d15 1176 /**************************************************************************/
Wolfgang Betz 130:770ce14d3d15 1177 void BlueNRGGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) {
Wolfgang Betz 130:770ce14d3d15 1178 static const int8_t permittedTxValues[] = {
Andrea Palmieri 229:9981f62cdb1a 1179 -18, -15, -14, -12, -11, -9, -8, -6, -5, -2, 0, 2, 4, 5, 8
Wolfgang Betz 130:770ce14d3d15 1180 };
Wolfgang Betz 130:770ce14d3d15 1181
Wolfgang Betz 130:770ce14d3d15 1182 *valueArrayPP = permittedTxValues;
Wolfgang Betz 130:770ce14d3d15 1183 *countP = sizeof(permittedTxValues) / sizeof(int8_t);
Wolfgang Betz 130:770ce14d3d15 1184 }
Wolfgang Betz 132:51056160fa4a 1185
Andrea Palmieri 229:9981f62cdb1a 1186 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1187 /*!
Andrea Palmieri 232:aead10288880 1188 @brief Set advertising parameters according to the current state
Andrea Palmieri 232:aead10288880 1189 Parameters value is set taking into account guidelines of the BlueNRG
Andrea Palmieri 232:aead10288880 1190 time slots allocation
Andrea Palmieri 232:aead10288880 1191 */
Andrea Palmieri 232:aead10288880 1192 /**************************************************************************/
Andrea Palmieri 232:aead10288880 1193 void BlueNRGGap::setAdvParameters(void)
Andrea Palmieri 232:aead10288880 1194 {
Andrea Palmieri 232:aead10288880 1195 uint32_t advIntMS;
Andrea Palmieri 232:aead10288880 1196
Andrea Palmieri 232:aead10288880 1197 if(state.connected == 1) {
Andrea Palmieri 232:aead10288880 1198 advIntMS = (conn_min_interval*1.25)-GUARD_INT;
Andrea Palmieri 232:aead10288880 1199 advInterval = _advParams.MSEC_TO_ADVERTISEMENT_DURATION_UNITS(advIntMS);
Vincent Coubard 256:146bb175ce80 1200
Vincent Coubard 259:323f588e5f57 1201 PRINTF("conn_min_interval is equal to %u\r\n", conn_min_interval);
Andrea Palmieri 232:aead10288880 1202 } else {
Andrea Palmieri 232:aead10288880 1203 advInterval = _advParams.getIntervalInADVUnits();
Andrea Palmieri 232:aead10288880 1204 }
Andrea Palmieri 232:aead10288880 1205 }
Andrea Palmieri 232:aead10288880 1206
Andrea Palmieri 232:aead10288880 1207 /**************************************************************************/
Andrea Palmieri 232:aead10288880 1208 /*!
Andrea Palmieri 229:9981f62cdb1a 1209 @brief Set connection parameters according to the current state (ADV and/or SCAN)
Andrea Palmieri 229:9981f62cdb1a 1210 Parameters value is set taking into account guidelines of the BlueNRG
Andrea Palmieri 229:9981f62cdb1a 1211 time slots allocation
Andrea Palmieri 229:9981f62cdb1a 1212 */
Andrea Palmieri 229:9981f62cdb1a 1213 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1214 void BlueNRGGap::setConnectionParameters(void)
Andrea Palmieri 229:9981f62cdb1a 1215 {
Andrea Palmieri 229:9981f62cdb1a 1216 if (state.advertising == 1) {
Andrea Palmieri 229:9981f62cdb1a 1217
Andrea Palmieri 232:aead10288880 1218 if (_scanningParams.getInterval() < advInterval) {
Andrea Palmieri 232:aead10288880 1219 PRINTF("state.adv=1 scanInterval<advInterval\r\n");
Andrea Palmieri 232:aead10288880 1220 scanInterval = advInterval;
Andrea Palmieri 232:aead10288880 1221 scanWindow = advInterval;
Andrea Palmieri 229:9981f62cdb1a 1222 } else {
Andrea Palmieri 232:aead10288880 1223 PRINTF("state.adv=1 scanInterval>=advInterval\r\n");
Andrea Palmieri 229:9981f62cdb1a 1224 scanInterval = _scanningParams.getInterval();
Andrea Palmieri 229:9981f62cdb1a 1225 scanWindow = _scanningParams.getWindow();
Andrea Palmieri 229:9981f62cdb1a 1226 }
Andrea Palmieri 234:3f6bba52b307 1227
Andrea Palmieri 234:3f6bba52b307 1228 if(advInterval>(MAX_INT_CONN-(GUARD_INT/1.25))) { //(4000-GUARD_INT)ms
Andrea Palmieri 234:3f6bba52b307 1229 conn_min_interval = MAX_INT_CONN;
Andrea Palmieri 234:3f6bba52b307 1230 conn_max_interval = MAX_INT_CONN;
Andrea Palmieri 234:3f6bba52b307 1231 } else {
Andrea Palmieri 234:3f6bba52b307 1232 conn_min_interval = (_advParams.ADVERTISEMENT_DURATION_UNITS_TO_MS(advInterval)+GUARD_INT)/1.25;
Andrea Palmieri 234:3f6bba52b307 1233 conn_max_interval = (_advParams.ADVERTISEMENT_DURATION_UNITS_TO_MS(advInterval)+GUARD_INT)/1.25;
Andrea Palmieri 234:3f6bba52b307 1234 }
Andrea Palmieri 229:9981f62cdb1a 1235
Andrea Palmieri 229:9981f62cdb1a 1236 } else {
Andrea Palmieri 229:9981f62cdb1a 1237
Andrea Palmieri 232:aead10288880 1238 PRINTF("state.adv = 0\r\n");
Andrea Palmieri 232:aead10288880 1239
Andrea Palmieri 229:9981f62cdb1a 1240 scanInterval = _scanningParams.getInterval();
Andrea Palmieri 229:9981f62cdb1a 1241 scanWindow = _scanningParams.getWindow();
Andrea Palmieri 234:3f6bba52b307 1242 if(SCAN_DURATION_UNITS_TO_MSEC(scanInterval)>(MAX_INT_CONN*1.25) ||
Andrea Palmieri 234:3f6bba52b307 1243 SCAN_DURATION_UNITS_TO_MSEC(scanInterval)<(MIN_INT_CONN*1.25)) { //(4000)ms || (7.5)ms
Andrea Palmieri 234:3f6bba52b307 1244 conn_min_interval = DEF_INT_CONN;
Andrea Palmieri 234:3f6bba52b307 1245 conn_max_interval = DEF_INT_CONN;
Andrea Palmieri 234:3f6bba52b307 1246 } else {
Andrea Palmieri 234:3f6bba52b307 1247 conn_min_interval = SCAN_DURATION_UNITS_TO_MSEC(scanInterval)/1.25;
Andrea Palmieri 234:3f6bba52b307 1248 conn_max_interval = SCAN_DURATION_UNITS_TO_MSEC(scanInterval)/1.25;
Andrea Palmieri 234:3f6bba52b307 1249 }
Andrea Palmieri 229:9981f62cdb1a 1250 }
Andrea Palmieri 229:9981f62cdb1a 1251 PRINTF("scanInterval=%u[msec]\r\n",SCAN_DURATION_UNITS_TO_MSEC(scanInterval));
Andrea Palmieri 229:9981f62cdb1a 1252 PRINTF("scanWindow()=%u[msec]\r\n",SCAN_DURATION_UNITS_TO_MSEC(scanWindow));
Andrea Palmieri 234:3f6bba52b307 1253 PRINTF("conn_min_interval=%u[msec]\r\n",(unsigned)(conn_min_interval*1.25));
Andrea Palmieri 234:3f6bba52b307 1254 PRINTF("conn_max_interval=%u[msec]\r\n",(unsigned)(conn_max_interval*1.25));
Andrea Palmieri 229:9981f62cdb1a 1255
Andrea Palmieri 229:9981f62cdb1a 1256 }
Andrea Palmieri 229:9981f62cdb1a 1257
Andrea Palmieri 181:749071129d2e 1258 ble_error_t BlueNRGGap::createConnection ()
Wolfgang Betz 132:51056160fa4a 1259 {
Wolfgang Betz 132:51056160fa4a 1260 tBleStatus ret;
Andrea Palmieri 229:9981f62cdb1a 1261
Andrea Palmieri 229:9981f62cdb1a 1262 /*
Andrea Palmieri 229:9981f62cdb1a 1263 Before creating connection, set parameters according
Andrea Palmieri 229:9981f62cdb1a 1264 to previous or current procedure (ADV and/or SCAN)
Andrea Palmieri 229:9981f62cdb1a 1265 */
Andrea Palmieri 229:9981f62cdb1a 1266 setConnectionParameters();
Andrea Palmieri 229:9981f62cdb1a 1267
Wolfgang Betz 132:51056160fa4a 1268 /*
Vincent Coubard 255:97adb68decd4 1269 Scan_Interval, Scan_Window, Peer_Address_Type, Peer_Address, Own_Address_Type, Conn_Interval_Min,
Vincent Coubard 255:97adb68decd4 1270 Conn_Interval_Max, Conn_Latency, Supervision_Timeout, Conn_Len_Min, Conn_Len_Max
Wolfgang Betz 132:51056160fa4a 1271 */
Andrea Palmieri 229:9981f62cdb1a 1272 ret = aci_gap_create_connection(scanInterval,
Andrea Palmieri 229:9981f62cdb1a 1273 scanWindow,
Andrea Palmieri 229:9981f62cdb1a 1274 _peerAddrType,
Wolfgang Betz 163:4c008b1089e9 1275 (unsigned char*)_peerAddr,
Andrea Palmieri 229:9981f62cdb1a 1276 addr_type,
Andrea Palmieri 229:9981f62cdb1a 1277 conn_min_interval, conn_max_interval, 0,
Andrea Palmieri 238:b6454c839f42 1278 SUPERV_TIMEOUT, CONN_L1, CONN_L1);
Wolfgang Betz 165:3576598c0889 1279
Andrea Palmieri 238:b6454c839f42 1280 //_connecting = false;
Vincent Coubard 255:97adb68decd4 1281
Wolfgang Betz 163:4c008b1089e9 1282 if (ret != BLE_STATUS_SUCCESS) {
Andrea Palmieri 229:9981f62cdb1a 1283 PRINTF("Error while starting connection (ret=0x%02X).\n\r", ret);
Wolfgang Betz 132:51056160fa4a 1284 return BLE_ERROR_UNSPECIFIED;
Wolfgang Betz 132:51056160fa4a 1285 } else {
Wolfgang Betz 132:51056160fa4a 1286 PRINTF("Connection started.\n");
Andrea Palmieri 238:b6454c839f42 1287 _connecting = false;
Wolfgang Betz 132:51056160fa4a 1288 return BLE_ERROR_NONE;
Wolfgang Betz 132:51056160fa4a 1289 }
Wolfgang Betz 132:51056160fa4a 1290 }
Wolfgang Betz 132:51056160fa4a 1291
Wolfgang Betz 132:51056160fa4a 1292 ble_error_t BlueNRGGap::connect (const Gap::Address_t peerAddr,
Wolfgang Betz 132:51056160fa4a 1293 Gap::AddressType_t peerAddrType,
Wolfgang Betz 132:51056160fa4a 1294 const ConnectionParams_t *connectionParams,
Wolfgang Betz 132:51056160fa4a 1295 const GapScanningParams *scanParams)
Wolfgang Betz 132:51056160fa4a 1296 {
Andrea Palmieri 142:adf1567d3900 1297 /* avoid compiler warnings about unused variables */
Andrea Palmieri 142:adf1567d3900 1298 (void)connectionParams;
Vincent Coubard 272:4639da7705e1 1299
Vincent Coubard 272:4639da7705e1 1300 setScanParams(scanParams->getInterval(),
Vincent Coubard 272:4639da7705e1 1301 scanParams->getWindow(),
Vincent Coubard 272:4639da7705e1 1302 scanParams->getTimeout(),
Vincent Coubard 272:4639da7705e1 1303 scanParams->getActiveScanning()
Vincent Coubard 272:4639da7705e1 1304 );
Andrea Palmieri 142:adf1567d3900 1305
Andrea Palmieri 217:23870c55b07e 1306 // Save the peer address
Wolfgang Betz 132:51056160fa4a 1307 for(int i=0; i<BDADDR_SIZE; i++) {
Wolfgang Betz 132:51056160fa4a 1308 _peerAddr[i] = peerAddr[i];
Wolfgang Betz 132:51056160fa4a 1309 }
Andrea Palmieri 229:9981f62cdb1a 1310 _peerAddrType = peerAddrType;
Wolfgang Betz 132:51056160fa4a 1311
Andrea Palmieri 181:749071129d2e 1312 _connecting = true;
Wolfgang Betz 132:51056160fa4a 1313
Wolfgang Betz 132:51056160fa4a 1314 if(_scanning) {
Wolfgang Betz 132:51056160fa4a 1315 stopScan();
Wolfgang Betz 132:51056160fa4a 1316 } else {
Wolfgang Betz 165:3576598c0889 1317 PRINTF("Calling createConnection from connect()\n\r");
Wolfgang Betz 165:3576598c0889 1318 return createConnection();
Wolfgang Betz 132:51056160fa4a 1319 }
Vincent Coubard 255:97adb68decd4 1320
Wolfgang Betz 132:51056160fa4a 1321 return BLE_ERROR_NONE;
Wolfgang Betz 132:51056160fa4a 1322 }
Andrea Palmieri 229:9981f62cdb1a 1323
Andrea Palmieri 229:9981f62cdb1a 1324 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1325 /*!
Andrea Palmieri 229:9981f62cdb1a 1326 @brief Set the advertising policy filter mode that will be used in
Andrea Palmieri 229:9981f62cdb1a 1327 the next call to startAdvertising().
Andrea Palmieri 229:9981f62cdb1a 1328
Andrea Palmieri 229:9981f62cdb1a 1329 @returns \ref ble_errror_t
Andrea Palmieri 229:9981f62cdb1a 1330
Andrea Palmieri 229:9981f62cdb1a 1331 @retval BLE_ERROR_NONE
Andrea Palmieri 229:9981f62cdb1a 1332 Everything executed properly.
Andrea Palmieri 229:9981f62cdb1a 1333
Andrea Palmieri 229:9981f62cdb1a 1334 BLE_ERROR_NOT_IMPLEMENTED
Andrea Palmieri 229:9981f62cdb1a 1335 This feature is currently note implemented.
Andrea Palmieri 229:9981f62cdb1a 1336 */
Andrea Palmieri 229:9981f62cdb1a 1337 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1338 ble_error_t BlueNRGGap::setAdvertisingPolicyMode(Gap::AdvertisingPolicyMode_t mode)
Andrea Palmieri 229:9981f62cdb1a 1339 {
Andrea Palmieri 229:9981f62cdb1a 1340 advertisingPolicyMode = mode;
Andrea Palmieri 229:9981f62cdb1a 1341
Andrea Palmieri 229:9981f62cdb1a 1342 return BLE_ERROR_NONE;
Andrea Palmieri 229:9981f62cdb1a 1343 }
Andrea Palmieri 229:9981f62cdb1a 1344
Andrea Palmieri 229:9981f62cdb1a 1345 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1346 /*!
Andrea Palmieri 229:9981f62cdb1a 1347 @brief Set the scanning policy filter mode that will be used in
Andrea Palmieri 229:9981f62cdb1a 1348 the next call to startAdvertising().
Andrea Palmieri 229:9981f62cdb1a 1349
Andrea Palmieri 229:9981f62cdb1a 1350 @returns \ref ble_errror_t
Andrea Palmieri 229:9981f62cdb1a 1351
Andrea Palmieri 229:9981f62cdb1a 1352 @retval BLE_ERROR_NONE
Andrea Palmieri 229:9981f62cdb1a 1353 Everything executed properly.
Andrea Palmieri 229:9981f62cdb1a 1354
Andrea Palmieri 229:9981f62cdb1a 1355 BLE_ERROR_NOT_IMPLEMENTED
Andrea Palmieri 229:9981f62cdb1a 1356 This feature is currently note implemented.
Andrea Palmieri 229:9981f62cdb1a 1357 */
Andrea Palmieri 229:9981f62cdb1a 1358 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1359 ble_error_t BlueNRGGap::setScanningPolicyMode(Gap::ScanningPolicyMode_t mode)
Andrea Palmieri 229:9981f62cdb1a 1360 {
Andrea Palmieri 229:9981f62cdb1a 1361 scanningPolicyMode = mode;
Andrea Palmieri 229:9981f62cdb1a 1362
Andrea Palmieri 229:9981f62cdb1a 1363 return BLE_ERROR_NONE;
Andrea Palmieri 229:9981f62cdb1a 1364 }
Andrea Palmieri 229:9981f62cdb1a 1365
Andrea Palmieri 229:9981f62cdb1a 1366 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1367 /*!
Andrea Palmieri 229:9981f62cdb1a 1368 @brief Get the current advertising policy filter mode.
Andrea Palmieri 229:9981f62cdb1a 1369
Andrea Palmieri 229:9981f62cdb1a 1370 @returns The advertising policy filter mode.
Andrea Palmieri 229:9981f62cdb1a 1371 */
Andrea Palmieri 229:9981f62cdb1a 1372 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1373 Gap::AdvertisingPolicyMode_t BlueNRGGap::getAdvertisingPolicyMode(void) const
Andrea Palmieri 229:9981f62cdb1a 1374 {
Andrea Palmieri 229:9981f62cdb1a 1375 return advertisingPolicyMode;
Andrea Palmieri 229:9981f62cdb1a 1376 }
Andrea Palmieri 229:9981f62cdb1a 1377
Andrea Palmieri 229:9981f62cdb1a 1378 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1379 /*!
Andrea Palmieri 229:9981f62cdb1a 1380 @brief Get the current scanning policy filter mode.
Andrea Palmieri 229:9981f62cdb1a 1381
Andrea Palmieri 229:9981f62cdb1a 1382 @returns The scanning policy filter mode.
Andrea Palmieri 229:9981f62cdb1a 1383
Andrea Palmieri 229:9981f62cdb1a 1384 */
Andrea Palmieri 229:9981f62cdb1a 1385 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1386 Gap::ScanningPolicyMode_t BlueNRGGap::getScanningPolicyMode(void) const
Andrea Palmieri 229:9981f62cdb1a 1387 {
Andrea Palmieri 229:9981f62cdb1a 1388 return scanningPolicyMode;
Andrea Palmieri 229:9981f62cdb1a 1389 }
Andrea Palmieri 229:9981f62cdb1a 1390
Andrea Palmieri 229:9981f62cdb1a 1391 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1392 /*!
Andrea Palmieri 229:9981f62cdb1a 1393 @brief Clear BlueNRGGap's state.
Andrea Palmieri 229:9981f62cdb1a 1394
Andrea Palmieri 229:9981f62cdb1a 1395 @returns ble_error_t
Andrea Palmieri 229:9981f62cdb1a 1396
Andrea Palmieri 229:9981f62cdb1a 1397 @retval BLE_ERROR_NONE
Andrea Palmieri 229:9981f62cdb1a 1398 Everything executed properly
Andrea Palmieri 229:9981f62cdb1a 1399 */
Andrea Palmieri 229:9981f62cdb1a 1400 /**************************************************************************/
Andrea Palmieri 229:9981f62cdb1a 1401 ble_error_t BlueNRGGap::reset(void)
Andrea Palmieri 229:9981f62cdb1a 1402 {
Andrea Palmieri 229:9981f62cdb1a 1403 /* Clear all state that is from the parent, including private members */
Andrea Palmieri 229:9981f62cdb1a 1404 if (Gap::reset() != BLE_ERROR_NONE) {
Andrea Palmieri 229:9981f62cdb1a 1405 return BLE_ERROR_INVALID_STATE;
Andrea Palmieri 229:9981f62cdb1a 1406 }
Andrea Palmieri 229:9981f62cdb1a 1407
Andrea Palmieri 229:9981f62cdb1a 1408 /* Clear derived class members */
Andrea Palmieri 229:9981f62cdb1a 1409 m_connectionHandle = BLE_CONN_HANDLE_INVALID;
Andrea Palmieri 229:9981f62cdb1a 1410
Andrea Palmieri 229:9981f62cdb1a 1411 /* Set the whitelist policy filter modes to IGNORE_WHITELIST */
Andrea Palmieri 229:9981f62cdb1a 1412 advertisingPolicyMode = Gap::ADV_POLICY_IGNORE_WHITELIST;
Andrea Palmieri 229:9981f62cdb1a 1413 scanningPolicyMode = Gap::SCAN_POLICY_IGNORE_WHITELIST;
Andrea Palmieri 229:9981f62cdb1a 1414
Andrea Palmieri 229:9981f62cdb1a 1415 return BLE_ERROR_NONE;
Vincent Coubard 256:146bb175ce80 1416 }
Vincent Coubard 256:146bb175ce80 1417
Vincent Coubard 256:146bb175ce80 1418 void BlueNRGGap::setConnectionInterval(uint16_t interval) {
Vincent Coubard 256:146bb175ce80 1419 conn_min_interval = interval;
Vincent Coubard 256:146bb175ce80 1420 conn_max_interval = interval;
Vincent Coubard 272:4639da7705e1 1421 }
Vincent Coubard 272:4639da7705e1 1422
Vincent Coubard 272:4639da7705e1 1423 void BlueNRGGap::setGapRole(Role_t role)
Vincent Coubard 272:4639da7705e1 1424 {
Vincent Coubard 272:4639da7705e1 1425 gapRole = role;
Vincent Coubard 272:4639da7705e1 1426 }