mbed-os-examples / Mbed OS mbed-os-example-ble-Privacy
Committer:
mbed_official
Date:
Mon Feb 25 17:44:26 2019 +0000
Revision:
0:2a36ad25fd97
Merge pull request #217 from adbridge/master

Updating mbed-os to mbed-os-5.11.4
.
Commit copied from https://github.com/ARMmbed/mbed-os-example-ble

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 0:2a36ad25fd97 1 /* mbed Microcontroller Library
mbed_official 0:2a36ad25fd97 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 0:2a36ad25fd97 3 *
mbed_official 0:2a36ad25fd97 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 0:2a36ad25fd97 5 * you may not use this file except in compliance with the License.
mbed_official 0:2a36ad25fd97 6 * You may obtain a copy of the License at
mbed_official 0:2a36ad25fd97 7 *
mbed_official 0:2a36ad25fd97 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 0:2a36ad25fd97 9 *
mbed_official 0:2a36ad25fd97 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 0:2a36ad25fd97 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 0:2a36ad25fd97 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 0:2a36ad25fd97 13 * See the License for the specific language governing permissions and
mbed_official 0:2a36ad25fd97 14 * limitations under the License.
mbed_official 0:2a36ad25fd97 15 */
mbed_official 0:2a36ad25fd97 16
mbed_official 0:2a36ad25fd97 17 #include <events/mbed_events.h>
mbed_official 0:2a36ad25fd97 18 #include <mbed.h>
mbed_official 0:2a36ad25fd97 19 #include "ble/BLE.h"
mbed_official 0:2a36ad25fd97 20 #include "SecurityManager.h"
mbed_official 0:2a36ad25fd97 21 #include <algorithm>
mbed_official 0:2a36ad25fd97 22 #include "pretty_printer.h"
mbed_official 0:2a36ad25fd97 23 #include "ble/gap/AdvertisingDataParser.h"
mbed_official 0:2a36ad25fd97 24
mbed_official 0:2a36ad25fd97 25 /** This example demonstrates privacy features in Gap. It shows how to use
mbed_official 0:2a36ad25fd97 26 * private addresses when advertising and connecting and how filtering ties
mbed_official 0:2a36ad25fd97 27 * in with these operations.
mbed_official 0:2a36ad25fd97 28 *
mbed_official 0:2a36ad25fd97 29 * The application will start by repeatedly trying to connect to the same
mbed_official 0:2a36ad25fd97 30 * application running on another board. It will do this by advertising and
mbed_official 0:2a36ad25fd97 31 * scanning for random intervals waiting until the difference in intervals
mbed_official 0:2a36ad25fd97 32 * between the boards will make them meet when one is advertising and the
mbed_official 0:2a36ad25fd97 33 * other scanning.
mbed_official 0:2a36ad25fd97 34 *
mbed_official 0:2a36ad25fd97 35 * Two devices will be operating using random resolvable addresses. The
mbed_official 0:2a36ad25fd97 36 * applications will connect to the peer and pair. It will attempt bonding
mbed_official 0:2a36ad25fd97 37 * to store the IRK that resolve the peer. Subsequent connections will
mbed_official 0:2a36ad25fd97 38 * turn on filtering based on stored IRKs.
mbed_official 0:2a36ad25fd97 39 */
mbed_official 0:2a36ad25fd97 40
mbed_official 0:2a36ad25fd97 41 static const char DEVICE_NAME[] = "Privacy";
mbed_official 0:2a36ad25fd97 42
mbed_official 0:2a36ad25fd97 43 /* we have to specify the disconnect call because of ambiguous overloads */
mbed_official 0:2a36ad25fd97 44 typedef ble_error_t (Gap::*disconnect_call_t)(ble::connection_handle_t, ble::local_disconnection_reason_t);
mbed_official 0:2a36ad25fd97 45 const static disconnect_call_t disconnect_call = &Gap::disconnect;
mbed_official 0:2a36ad25fd97 46
mbed_official 0:2a36ad25fd97 47 /** Base class for both peripheral and central. The same class that provides
mbed_official 0:2a36ad25fd97 48 * the logic for the application also implements the SecurityManagerEventHandler
mbed_official 0:2a36ad25fd97 49 * which is the interface used by the Security Manager to communicate events
mbed_official 0:2a36ad25fd97 50 * back to the applications. You can provide overrides for a selection of events
mbed_official 0:2a36ad25fd97 51 * your application is interested in.
mbed_official 0:2a36ad25fd97 52 */
mbed_official 0:2a36ad25fd97 53 class PrivacyDevice : private mbed::NonCopyable<PrivacyDevice>,
mbed_official 0:2a36ad25fd97 54 public SecurityManager::EventHandler,
mbed_official 0:2a36ad25fd97 55 public ble::Gap::EventHandler
mbed_official 0:2a36ad25fd97 56 {
mbed_official 0:2a36ad25fd97 57 public:
mbed_official 0:2a36ad25fd97 58 PrivacyDevice(BLE &ble, events::EventQueue &event_queue) :
mbed_official 0:2a36ad25fd97 59 _ble(ble),
mbed_official 0:2a36ad25fd97 60 _event_queue(event_queue),
mbed_official 0:2a36ad25fd97 61 _handle(0),
mbed_official 0:2a36ad25fd97 62 _bonded(false),
mbed_official 0:2a36ad25fd97 63 _led1(LED1, 0) { };
mbed_official 0:2a36ad25fd97 64
mbed_official 0:2a36ad25fd97 65 virtual ~PrivacyDevice() {
mbed_official 0:2a36ad25fd97 66 _ble.onEventsToProcess(NULL);
mbed_official 0:2a36ad25fd97 67 };
mbed_official 0:2a36ad25fd97 68
mbed_official 0:2a36ad25fd97 69 /** Start BLE interface initialisation */
mbed_official 0:2a36ad25fd97 70 void run()
mbed_official 0:2a36ad25fd97 71 {
mbed_official 0:2a36ad25fd97 72 /* to show we're running we'll blink every 500ms */
mbed_official 0:2a36ad25fd97 73 _event_queue.call_every(500, this, &PrivacyDevice::blink);
mbed_official 0:2a36ad25fd97 74
mbed_official 0:2a36ad25fd97 75 /* this will inform us off all events so we can schedule their handling
mbed_official 0:2a36ad25fd97 76 * using our event queue */
mbed_official 0:2a36ad25fd97 77 _ble.onEventsToProcess(
mbed_official 0:2a36ad25fd97 78 makeFunctionPointer(this, &PrivacyDevice::schedule_ble_events)
mbed_official 0:2a36ad25fd97 79 );
mbed_official 0:2a36ad25fd97 80
mbed_official 0:2a36ad25fd97 81 /* handle gap events */
mbed_official 0:2a36ad25fd97 82 _ble.gap().setEventHandler(this);
mbed_official 0:2a36ad25fd97 83
mbed_official 0:2a36ad25fd97 84 if (_ble.hasInitialized()) {
mbed_official 0:2a36ad25fd97 85 /* ble instance already initialised, skip init and start activity */
mbed_official 0:2a36ad25fd97 86 start();
mbed_official 0:2a36ad25fd97 87 } else {
mbed_official 0:2a36ad25fd97 88 ble_error_t error = _ble.init(this, &PrivacyDevice::on_init_complete);
mbed_official 0:2a36ad25fd97 89
mbed_official 0:2a36ad25fd97 90 if (error) {
mbed_official 0:2a36ad25fd97 91 printf("Error returned by BLE::init.\r\n");
mbed_official 0:2a36ad25fd97 92 return;
mbed_official 0:2a36ad25fd97 93 }
mbed_official 0:2a36ad25fd97 94 }
mbed_official 0:2a36ad25fd97 95
mbed_official 0:2a36ad25fd97 96 /* this will not return until shutdown */
mbed_official 0:2a36ad25fd97 97 _event_queue.dispatch_forever();
mbed_official 0:2a36ad25fd97 98 };
mbed_official 0:2a36ad25fd97 99
mbed_official 0:2a36ad25fd97 100 /** Override to start chosen activity when initialisation completes */
mbed_official 0:2a36ad25fd97 101 virtual void start() = 0;
mbed_official 0:2a36ad25fd97 102
mbed_official 0:2a36ad25fd97 103 /** Override to start chosen activity after initial bonding */
mbed_official 0:2a36ad25fd97 104 virtual void start_after_bonding() = 0;
mbed_official 0:2a36ad25fd97 105
mbed_official 0:2a36ad25fd97 106 /* callbacks */
mbed_official 0:2a36ad25fd97 107
mbed_official 0:2a36ad25fd97 108 /** This is called when BLE interface is initialised and starts the demonstration */
mbed_official 0:2a36ad25fd97 109 void on_init_complete(BLE::InitializationCompleteCallbackContext *event)
mbed_official 0:2a36ad25fd97 110 {
mbed_official 0:2a36ad25fd97 111 ble_error_t error;
mbed_official 0:2a36ad25fd97 112
mbed_official 0:2a36ad25fd97 113 if (event->error) {
mbed_official 0:2a36ad25fd97 114 printf("Error during the initialisation\r\n");
mbed_official 0:2a36ad25fd97 115 _event_queue.break_dispatch();
mbed_official 0:2a36ad25fd97 116 return;
mbed_official 0:2a36ad25fd97 117 }
mbed_official 0:2a36ad25fd97 118
mbed_official 0:2a36ad25fd97 119 /* for use by tools we print out own address and also use it
mbed_official 0:2a36ad25fd97 120 * to seed RNG as the address is unique */
mbed_official 0:2a36ad25fd97 121 print_local_address();
mbed_official 0:2a36ad25fd97 122
mbed_official 0:2a36ad25fd97 123 /* Privacy requires the security manager */
mbed_official 0:2a36ad25fd97 124
mbed_official 0:2a36ad25fd97 125 error = _ble.securityManager().init(
mbed_official 0:2a36ad25fd97 126 /* enableBonding */ true,
mbed_official 0:2a36ad25fd97 127 /* requireMITM */ false,
mbed_official 0:2a36ad25fd97 128 /* iocaps */ SecurityManager::IO_CAPS_NONE,
mbed_official 0:2a36ad25fd97 129 /* passkey */ NULL,
mbed_official 0:2a36ad25fd97 130 /* signing */ false,
mbed_official 0:2a36ad25fd97 131 /* dbFilepath */ NULL
mbed_official 0:2a36ad25fd97 132 );
mbed_official 0:2a36ad25fd97 133
mbed_official 0:2a36ad25fd97 134 if (error) {
mbed_official 0:2a36ad25fd97 135 printf("Error during security manager initialisation\r\n");
mbed_official 0:2a36ad25fd97 136 _event_queue.break_dispatch();
mbed_official 0:2a36ad25fd97 137 return;
mbed_official 0:2a36ad25fd97 138 }
mbed_official 0:2a36ad25fd97 139
mbed_official 0:2a36ad25fd97 140 /* Tell the security manager to use methods in this class to inform us
mbed_official 0:2a36ad25fd97 141 * of any events. Class needs to implement SecurityManagerEventHandler. */
mbed_official 0:2a36ad25fd97 142 _ble.securityManager().setSecurityManagerEventHandler(this);
mbed_official 0:2a36ad25fd97 143
mbed_official 0:2a36ad25fd97 144 /* gap events also handled by this class */
mbed_official 0:2a36ad25fd97 145 _ble.gap().setEventHandler(this);
mbed_official 0:2a36ad25fd97 146
mbed_official 0:2a36ad25fd97 147 /* privacy */
mbed_official 0:2a36ad25fd97 148
mbed_official 0:2a36ad25fd97 149 error = _ble.gap().enablePrivacy(true);
mbed_official 0:2a36ad25fd97 150
mbed_official 0:2a36ad25fd97 151 if (error) {
mbed_official 0:2a36ad25fd97 152 printf("Error enabling privacy.\r\n");
mbed_official 0:2a36ad25fd97 153 _event_queue.break_dispatch();
mbed_official 0:2a36ad25fd97 154 return;
mbed_official 0:2a36ad25fd97 155 }
mbed_official 0:2a36ad25fd97 156
mbed_official 0:2a36ad25fd97 157 start();
mbed_official 0:2a36ad25fd97 158 };
mbed_official 0:2a36ad25fd97 159
mbed_official 0:2a36ad25fd97 160 /** Schedule processing of events from the BLE in the event queue. */
mbed_official 0:2a36ad25fd97 161 void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
mbed_official 0:2a36ad25fd97 162 {
mbed_official 0:2a36ad25fd97 163 _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
mbed_official 0:2a36ad25fd97 164 };
mbed_official 0:2a36ad25fd97 165
mbed_official 0:2a36ad25fd97 166 /** Blink LED to show we're running */
mbed_official 0:2a36ad25fd97 167 void blink(void)
mbed_official 0:2a36ad25fd97 168 {
mbed_official 0:2a36ad25fd97 169 _led1 = !_led1;
mbed_official 0:2a36ad25fd97 170 };
mbed_official 0:2a36ad25fd97 171
mbed_official 0:2a36ad25fd97 172 void print_local_address()
mbed_official 0:2a36ad25fd97 173 {
mbed_official 0:2a36ad25fd97 174 /* show what address we are using now */
mbed_official 0:2a36ad25fd97 175 Gap::AddressType_t addr_type;
mbed_official 0:2a36ad25fd97 176 Gap::Address_t addr;
mbed_official 0:2a36ad25fd97 177 _ble.gap().getAddress(&addr_type, addr);
mbed_official 0:2a36ad25fd97 178 printf("Device address: ");
mbed_official 0:2a36ad25fd97 179 print_address(addr);
mbed_official 0:2a36ad25fd97 180
mbed_official 0:2a36ad25fd97 181 if (!_seeded) {
mbed_official 0:2a36ad25fd97 182 _seeded = true;
mbed_official 0:2a36ad25fd97 183 /* use the address as a seed */
mbed_official 0:2a36ad25fd97 184 uint8_t* random_data = addr;
mbed_official 0:2a36ad25fd97 185 srand(*((unsigned int*)random_data));
mbed_official 0:2a36ad25fd97 186 }
mbed_official 0:2a36ad25fd97 187 }
mbed_official 0:2a36ad25fd97 188
mbed_official 0:2a36ad25fd97 189 private:
mbed_official 0:2a36ad25fd97 190 /* Event handler */
mbed_official 0:2a36ad25fd97 191
mbed_official 0:2a36ad25fd97 192 /** Inform the application of pairing */
mbed_official 0:2a36ad25fd97 193 virtual void pairingResult(
mbed_official 0:2a36ad25fd97 194 ble::connection_handle_t connectionHandle,
mbed_official 0:2a36ad25fd97 195 SecurityManager::SecurityCompletionStatus_t result
mbed_official 0:2a36ad25fd97 196 ) {
mbed_official 0:2a36ad25fd97 197 if (result == SecurityManager::SEC_STATUS_SUCCESS) {
mbed_official 0:2a36ad25fd97 198 printf("Pairing successful\r\n");
mbed_official 0:2a36ad25fd97 199 _bonded = true;
mbed_official 0:2a36ad25fd97 200 } else {
mbed_official 0:2a36ad25fd97 201 printf("Pairing failed\r\n");
mbed_official 0:2a36ad25fd97 202 }
mbed_official 0:2a36ad25fd97 203
mbed_official 0:2a36ad25fd97 204 /* disconnect in 2s */
mbed_official 0:2a36ad25fd97 205 _event_queue.call_in(
mbed_official 0:2a36ad25fd97 206 2000,
mbed_official 0:2a36ad25fd97 207 &_ble.gap(),
mbed_official 0:2a36ad25fd97 208 disconnect_call,
mbed_official 0:2a36ad25fd97 209 connectionHandle,
mbed_official 0:2a36ad25fd97 210 ble::local_disconnection_reason_t(ble::local_disconnection_reason_t::USER_TERMINATION)
mbed_official 0:2a36ad25fd97 211 );
mbed_official 0:2a36ad25fd97 212 }
mbed_official 0:2a36ad25fd97 213
mbed_official 0:2a36ad25fd97 214 /** This is called by Gap to notify the application we connected */
mbed_official 0:2a36ad25fd97 215 virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event)
mbed_official 0:2a36ad25fd97 216 {
mbed_official 0:2a36ad25fd97 217 printf("Connected to peer: ");
mbed_official 0:2a36ad25fd97 218 print_address(event.getPeerAddress().data());
mbed_official 0:2a36ad25fd97 219 printf("Peer random resolvable address: ");
mbed_official 0:2a36ad25fd97 220 print_address(event.getPeerResolvablePrivateAddress().data());
mbed_official 0:2a36ad25fd97 221
mbed_official 0:2a36ad25fd97 222 _handle = event.getConnectionHandle();
mbed_official 0:2a36ad25fd97 223
mbed_official 0:2a36ad25fd97 224 if (_bonded) {
mbed_official 0:2a36ad25fd97 225 /* disconnect in 2s */
mbed_official 0:2a36ad25fd97 226 _event_queue.call_in(
mbed_official 0:2a36ad25fd97 227 2000,
mbed_official 0:2a36ad25fd97 228 &_ble.gap(),
mbed_official 0:2a36ad25fd97 229 disconnect_call,
mbed_official 0:2a36ad25fd97 230 _handle,
mbed_official 0:2a36ad25fd97 231 ble::local_disconnection_reason_t(ble::local_disconnection_reason_t::USER_TERMINATION)
mbed_official 0:2a36ad25fd97 232 );
mbed_official 0:2a36ad25fd97 233 }
mbed_official 0:2a36ad25fd97 234 };
mbed_official 0:2a36ad25fd97 235
mbed_official 0:2a36ad25fd97 236 /** This is called by Gap to notify the application we disconnected */
mbed_official 0:2a36ad25fd97 237 virtual void onDisconnectionComplete(const ble::DisconnectionCompleteEvent &event)
mbed_official 0:2a36ad25fd97 238 {
mbed_official 0:2a36ad25fd97 239 if (_bonded) {
mbed_official 0:2a36ad25fd97 240 /* we have connected to and bonded with the other device, from now
mbed_official 0:2a36ad25fd97 241 * on we will use the second start function and stay in the same role
mbed_official 0:2a36ad25fd97 242 * as peripheral or central */
mbed_official 0:2a36ad25fd97 243 printf("Disconnected.\r\n");
mbed_official 0:2a36ad25fd97 244 _event_queue.call_in(2000, this, &PrivacyDevice::start_after_bonding);
mbed_official 0:2a36ad25fd97 245 } else {
mbed_official 0:2a36ad25fd97 246 printf("Failed to bond.\r\n");
mbed_official 0:2a36ad25fd97 247 _event_queue.break_dispatch();
mbed_official 0:2a36ad25fd97 248 }
mbed_official 0:2a36ad25fd97 249 };
mbed_official 0:2a36ad25fd97 250
mbed_official 0:2a36ad25fd97 251 virtual void onScanTimeout(const ble::ScanTimeoutEvent &)
mbed_official 0:2a36ad25fd97 252 {
mbed_official 0:2a36ad25fd97 253 /* if we failed to find the other device, abort so that we change roles */
mbed_official 0:2a36ad25fd97 254 printf("Haven't seen other device, switch modes.\r\n");
mbed_official 0:2a36ad25fd97 255 _event_queue.break_dispatch();
mbed_official 0:2a36ad25fd97 256 }
mbed_official 0:2a36ad25fd97 257
mbed_official 0:2a36ad25fd97 258 public:
mbed_official 0:2a36ad25fd97 259 static bool _seeded;
mbed_official 0:2a36ad25fd97 260
mbed_official 0:2a36ad25fd97 261 protected:
mbed_official 0:2a36ad25fd97 262 BLE &_ble;
mbed_official 0:2a36ad25fd97 263 events::EventQueue &_event_queue;
mbed_official 0:2a36ad25fd97 264 ble::connection_handle_t _handle;
mbed_official 0:2a36ad25fd97 265 bool _bonded;
mbed_official 0:2a36ad25fd97 266
mbed_official 0:2a36ad25fd97 267 private:
mbed_official 0:2a36ad25fd97 268 DigitalOut _led1;
mbed_official 0:2a36ad25fd97 269 };
mbed_official 0:2a36ad25fd97 270
mbed_official 0:2a36ad25fd97 271 /** A peripheral device will advertise and accept the connections */
mbed_official 0:2a36ad25fd97 272 class PrivacyPeripheral : public PrivacyDevice {
mbed_official 0:2a36ad25fd97 273 public:
mbed_official 0:2a36ad25fd97 274 PrivacyPeripheral(BLE &ble, events::EventQueue &event_queue)
mbed_official 0:2a36ad25fd97 275 : PrivacyDevice(ble, event_queue) { }
mbed_official 0:2a36ad25fd97 276
mbed_official 0:2a36ad25fd97 277 /** Set up and start advertising accepting anyone */
mbed_official 0:2a36ad25fd97 278 virtual void start()
mbed_official 0:2a36ad25fd97 279 {
mbed_official 0:2a36ad25fd97 280 if (!set_advertising_data()) {
mbed_official 0:2a36ad25fd97 281 return;
mbed_official 0:2a36ad25fd97 282 }
mbed_official 0:2a36ad25fd97 283
mbed_official 0:2a36ad25fd97 284 Gap::PeripheralPrivacyConfiguration_t privacy_configuration = {
mbed_official 0:2a36ad25fd97 285 /* use_non_resolvable_random_address */ false,
mbed_official 0:2a36ad25fd97 286 Gap::PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE
mbed_official 0:2a36ad25fd97 287 };
mbed_official 0:2a36ad25fd97 288
mbed_official 0:2a36ad25fd97 289 _ble.gap().setPeripheralPrivacyConfiguration(&privacy_configuration);
mbed_official 0:2a36ad25fd97 290
mbed_official 0:2a36ad25fd97 291 start_advertising();
mbed_official 0:2a36ad25fd97 292 };
mbed_official 0:2a36ad25fd97 293
mbed_official 0:2a36ad25fd97 294 /** advertise and filter based on known devices */
mbed_official 0:2a36ad25fd97 295 virtual void start_after_bonding()
mbed_official 0:2a36ad25fd97 296 {
mbed_official 0:2a36ad25fd97 297 Gap::PeripheralPrivacyConfiguration_t privacy_configuration = {
mbed_official 0:2a36ad25fd97 298 /* use_non_resolvable_random_address */ false,
mbed_official 0:2a36ad25fd97 299 Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS
mbed_official 0:2a36ad25fd97 300 };
mbed_official 0:2a36ad25fd97 301
mbed_official 0:2a36ad25fd97 302 _ble.gap().setPeripheralPrivacyConfiguration(&privacy_configuration);
mbed_official 0:2a36ad25fd97 303
mbed_official 0:2a36ad25fd97 304 start_advertising();
mbed_official 0:2a36ad25fd97 305 }
mbed_official 0:2a36ad25fd97 306
mbed_official 0:2a36ad25fd97 307 /* helper functions */
mbed_official 0:2a36ad25fd97 308
mbed_official 0:2a36ad25fd97 309 private:
mbed_official 0:2a36ad25fd97 310 bool set_advertising_data()
mbed_official 0:2a36ad25fd97 311 {
mbed_official 0:2a36ad25fd97 312 uint8_t adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
mbed_official 0:2a36ad25fd97 313 /* use the helper to build the payload */
mbed_official 0:2a36ad25fd97 314 ble::AdvertisingDataBuilder adv_data_builder(
mbed_official 0:2a36ad25fd97 315 adv_buffer
mbed_official 0:2a36ad25fd97 316 );
mbed_official 0:2a36ad25fd97 317
mbed_official 0:2a36ad25fd97 318 adv_data_builder.setFlags();
mbed_official 0:2a36ad25fd97 319 adv_data_builder.setName(DEVICE_NAME);
mbed_official 0:2a36ad25fd97 320
mbed_official 0:2a36ad25fd97 321 /* Set payload for the set */
mbed_official 0:2a36ad25fd97 322 ble_error_t error = _ble.gap().setAdvertisingPayload(
mbed_official 0:2a36ad25fd97 323 ble::LEGACY_ADVERTISING_HANDLE,
mbed_official 0:2a36ad25fd97 324 adv_data_builder.getAdvertisingData()
mbed_official 0:2a36ad25fd97 325 );
mbed_official 0:2a36ad25fd97 326
mbed_official 0:2a36ad25fd97 327 if (error) {
mbed_official 0:2a36ad25fd97 328 print_error(error, "Gap::setAdvertisingPayload() failed");
mbed_official 0:2a36ad25fd97 329 _event_queue.break_dispatch();
mbed_official 0:2a36ad25fd97 330 return false;
mbed_official 0:2a36ad25fd97 331 }
mbed_official 0:2a36ad25fd97 332
mbed_official 0:2a36ad25fd97 333 return true;
mbed_official 0:2a36ad25fd97 334 }
mbed_official 0:2a36ad25fd97 335
mbed_official 0:2a36ad25fd97 336 bool start_advertising()
mbed_official 0:2a36ad25fd97 337 {
mbed_official 0:2a36ad25fd97 338 ble::AdvertisingParameters adv_parameters(
mbed_official 0:2a36ad25fd97 339 ble::advertising_type_t::CONNECTABLE_UNDIRECTED
mbed_official 0:2a36ad25fd97 340 );
mbed_official 0:2a36ad25fd97 341
mbed_official 0:2a36ad25fd97 342 ble_error_t error = _ble.gap().setAdvertisingParameters(
mbed_official 0:2a36ad25fd97 343 ble::LEGACY_ADVERTISING_HANDLE,
mbed_official 0:2a36ad25fd97 344 adv_parameters
mbed_official 0:2a36ad25fd97 345 );
mbed_official 0:2a36ad25fd97 346
mbed_official 0:2a36ad25fd97 347 if (error) {
mbed_official 0:2a36ad25fd97 348 print_error(error, "Gap::setAdvertisingParameters() failed");
mbed_official 0:2a36ad25fd97 349 return false;
mbed_official 0:2a36ad25fd97 350 }
mbed_official 0:2a36ad25fd97 351
mbed_official 0:2a36ad25fd97 352 if (_bonded) {
mbed_official 0:2a36ad25fd97 353 /* if we bonded it means we have found the other device, from now on
mbed_official 0:2a36ad25fd97 354 * wait at each step until completion */
mbed_official 0:2a36ad25fd97 355 error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
mbed_official 0:2a36ad25fd97 356 } else {
mbed_official 0:2a36ad25fd97 357 /* since we have two boards which might start running this example at the same time
mbed_official 0:2a36ad25fd97 358 * we randomise the interval of advertising to have them meet when one is advertising
mbed_official 0:2a36ad25fd97 359 * and the other one is scanning (we use their random address as source of randomness) */
mbed_official 0:2a36ad25fd97 360 ble::millisecond_t random_duration_ms((1 + rand() % 5) * 1000);
mbed_official 0:2a36ad25fd97 361 ble::adv_duration_t random_duration(random_duration_ms);
mbed_official 0:2a36ad25fd97 362 error = _ble.gap().startAdvertising(
mbed_official 0:2a36ad25fd97 363 ble::LEGACY_ADVERTISING_HANDLE,
mbed_official 0:2a36ad25fd97 364 random_duration
mbed_official 0:2a36ad25fd97 365 );
mbed_official 0:2a36ad25fd97 366 }
mbed_official 0:2a36ad25fd97 367
mbed_official 0:2a36ad25fd97 368 if (error) {
mbed_official 0:2a36ad25fd97 369 print_error(error, "Gap::startAdvertising() failed");
mbed_official 0:2a36ad25fd97 370 _event_queue.break_dispatch();
mbed_official 0:2a36ad25fd97 371 return false;
mbed_official 0:2a36ad25fd97 372 }
mbed_official 0:2a36ad25fd97 373
mbed_official 0:2a36ad25fd97 374 printf("Advertising...\r\n");
mbed_official 0:2a36ad25fd97 375
mbed_official 0:2a36ad25fd97 376 return true;
mbed_official 0:2a36ad25fd97 377 }
mbed_official 0:2a36ad25fd97 378
mbed_official 0:2a36ad25fd97 379 };
mbed_official 0:2a36ad25fd97 380
mbed_official 0:2a36ad25fd97 381 /** A central device will scan and connect to a peer. */
mbed_official 0:2a36ad25fd97 382 class PrivacyCentral : public PrivacyDevice {
mbed_official 0:2a36ad25fd97 383 public:
mbed_official 0:2a36ad25fd97 384 PrivacyCentral(BLE &ble, events::EventQueue &event_queue)
mbed_official 0:2a36ad25fd97 385 : PrivacyDevice(ble, event_queue),
mbed_official 0:2a36ad25fd97 386 _is_connecting(false) { }
mbed_official 0:2a36ad25fd97 387
mbed_official 0:2a36ad25fd97 388 /** start scanning and attach a callback that will handle advertisements
mbed_official 0:2a36ad25fd97 389 * and scan requests responses */
mbed_official 0:2a36ad25fd97 390 virtual void start()
mbed_official 0:2a36ad25fd97 391 {
mbed_official 0:2a36ad25fd97 392 Gap::CentralPrivacyConfiguration_t privacy_configuration = {
mbed_official 0:2a36ad25fd97 393 /* use_non_resolvable_random_address */ false,
mbed_official 0:2a36ad25fd97 394 Gap::CentralPrivacyConfiguration_t::DO_NOT_RESOLVE
mbed_official 0:2a36ad25fd97 395 };
mbed_official 0:2a36ad25fd97 396
mbed_official 0:2a36ad25fd97 397 _ble.gap().setCentralPrivacyConfiguration(&privacy_configuration);
mbed_official 0:2a36ad25fd97 398
mbed_official 0:2a36ad25fd97 399 start_scanning();
mbed_official 0:2a36ad25fd97 400 }
mbed_official 0:2a36ad25fd97 401
mbed_official 0:2a36ad25fd97 402 virtual void start_after_bonding()
mbed_official 0:2a36ad25fd97 403 {
mbed_official 0:2a36ad25fd97 404 Gap::CentralPrivacyConfiguration_t privacy_configuration = {
mbed_official 0:2a36ad25fd97 405 /* use_non_resolvable_random_address */ false,
mbed_official 0:2a36ad25fd97 406 Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER
mbed_official 0:2a36ad25fd97 407 };
mbed_official 0:2a36ad25fd97 408
mbed_official 0:2a36ad25fd97 409 _ble.gap().setCentralPrivacyConfiguration(&privacy_configuration);
mbed_official 0:2a36ad25fd97 410
mbed_official 0:2a36ad25fd97 411 start_scanning();
mbed_official 0:2a36ad25fd97 412 }
mbed_official 0:2a36ad25fd97 413
mbed_official 0:2a36ad25fd97 414 /* helper functions */
mbed_official 0:2a36ad25fd97 415 private:
mbed_official 0:2a36ad25fd97 416 bool start_scanning() {
mbed_official 0:2a36ad25fd97 417 ble_error_t error;
mbed_official 0:2a36ad25fd97 418 ble::ScanParameters scan_params;
mbed_official 0:2a36ad25fd97 419 _ble.gap().setScanParameters(scan_params);
mbed_official 0:2a36ad25fd97 420
mbed_official 0:2a36ad25fd97 421 _is_connecting = false;
mbed_official 0:2a36ad25fd97 422
mbed_official 0:2a36ad25fd97 423 if (_bonded) {
mbed_official 0:2a36ad25fd97 424 /* if we bonded it means we have found the other device, from now on
mbed_official 0:2a36ad25fd97 425 * wait at each step until completion */
mbed_official 0:2a36ad25fd97 426 error = _ble.gap().startScan(ble::scan_duration_t::forever());
mbed_official 0:2a36ad25fd97 427 } else {
mbed_official 0:2a36ad25fd97 428 /* otherwise only scan for a limited time before changing roles again
mbed_official 0:2a36ad25fd97 429 * if we fail to find the other device */
mbed_official 0:2a36ad25fd97 430 error = _ble.gap().startScan(
mbed_official 0:2a36ad25fd97 431 ble::scan_duration_t(ble::millisecond_t(4000))
mbed_official 0:2a36ad25fd97 432 );
mbed_official 0:2a36ad25fd97 433 }
mbed_official 0:2a36ad25fd97 434
mbed_official 0:2a36ad25fd97 435 if (error) {
mbed_official 0:2a36ad25fd97 436 printf("Error during Gap::startScan %d\r\n", error);
mbed_official 0:2a36ad25fd97 437 _event_queue.break_dispatch();
mbed_official 0:2a36ad25fd97 438 return false;
mbed_official 0:2a36ad25fd97 439 }
mbed_official 0:2a36ad25fd97 440
mbed_official 0:2a36ad25fd97 441 printf("Scanning...\r\n");
mbed_official 0:2a36ad25fd97 442
mbed_official 0:2a36ad25fd97 443 return true;
mbed_official 0:2a36ad25fd97 444 }
mbed_official 0:2a36ad25fd97 445
mbed_official 0:2a36ad25fd97 446 private:
mbed_official 0:2a36ad25fd97 447 /* Event handler */
mbed_official 0:2a36ad25fd97 448
mbed_official 0:2a36ad25fd97 449 /** Look at scan payload to find a peer device and connect to it */
mbed_official 0:2a36ad25fd97 450 virtual void onAdvertisingReport(const ble::AdvertisingReportEvent &event)
mbed_official 0:2a36ad25fd97 451 {
mbed_official 0:2a36ad25fd97 452 /* don't bother with analysing scan result if we're already connecting */
mbed_official 0:2a36ad25fd97 453 if (_is_connecting) {
mbed_official 0:2a36ad25fd97 454 return;
mbed_official 0:2a36ad25fd97 455 }
mbed_official 0:2a36ad25fd97 456
mbed_official 0:2a36ad25fd97 457 ble::AdvertisingDataParser adv_data(event.getPayload());
mbed_official 0:2a36ad25fd97 458
mbed_official 0:2a36ad25fd97 459 /* parse the advertising payload, looking for a discoverable device */
mbed_official 0:2a36ad25fd97 460 while (adv_data.hasNext()) {
mbed_official 0:2a36ad25fd97 461 ble::AdvertisingDataParser::element_t field = adv_data.next();
mbed_official 0:2a36ad25fd97 462
mbed_official 0:2a36ad25fd97 463 /* connect to a known device by name */
mbed_official 0:2a36ad25fd97 464 if (field.type == ble::adv_data_type_t::COMPLETE_LOCAL_NAME &&
mbed_official 0:2a36ad25fd97 465 field.value.size() == strlen(DEVICE_NAME) &&
mbed_official 0:2a36ad25fd97 466 (memcmp(field.value.data(), DEVICE_NAME, field.value.size()) == 0)) {
mbed_official 0:2a36ad25fd97 467
mbed_official 0:2a36ad25fd97 468 printf("We found a connectable device\r\n");
mbed_official 0:2a36ad25fd97 469
mbed_official 0:2a36ad25fd97 470 ble_error_t error = _ble.gap().stopScan();
mbed_official 0:2a36ad25fd97 471
mbed_official 0:2a36ad25fd97 472 if (error) {
mbed_official 0:2a36ad25fd97 473 print_error(error, "Error caused by Gap::stopScan");
mbed_official 0:2a36ad25fd97 474 return;
mbed_official 0:2a36ad25fd97 475 }
mbed_official 0:2a36ad25fd97 476
mbed_official 0:2a36ad25fd97 477 const ble::ConnectionParameters connection_params;
mbed_official 0:2a36ad25fd97 478
mbed_official 0:2a36ad25fd97 479 error = _ble.gap().connect(
mbed_official 0:2a36ad25fd97 480 event.getPeerAddressType(),
mbed_official 0:2a36ad25fd97 481 event.getPeerAddress(),
mbed_official 0:2a36ad25fd97 482 connection_params
mbed_official 0:2a36ad25fd97 483 );
mbed_official 0:2a36ad25fd97 484
mbed_official 0:2a36ad25fd97 485 if (error) {
mbed_official 0:2a36ad25fd97 486 print_error(error, "Error caused by Gap::connect");
mbed_official 0:2a36ad25fd97 487 return;
mbed_official 0:2a36ad25fd97 488 }
mbed_official 0:2a36ad25fd97 489
mbed_official 0:2a36ad25fd97 490 /* we may have already scan events waiting
mbed_official 0:2a36ad25fd97 491 * to be processed so we need to remember
mbed_official 0:2a36ad25fd97 492 * that we are already connecting and ignore them */
mbed_official 0:2a36ad25fd97 493 _is_connecting = true;
mbed_official 0:2a36ad25fd97 494
mbed_official 0:2a36ad25fd97 495 return;
mbed_official 0:2a36ad25fd97 496
mbed_official 0:2a36ad25fd97 497 }
mbed_official 0:2a36ad25fd97 498 }
mbed_official 0:2a36ad25fd97 499 }
mbed_official 0:2a36ad25fd97 500
mbed_official 0:2a36ad25fd97 501 private:
mbed_official 0:2a36ad25fd97 502 bool _is_connecting;
mbed_official 0:2a36ad25fd97 503 };
mbed_official 0:2a36ad25fd97 504
mbed_official 0:2a36ad25fd97 505 /* only seed the random number generation once per application run */
mbed_official 0:2a36ad25fd97 506 bool PrivacyDevice::_seeded = false;
mbed_official 0:2a36ad25fd97 507
mbed_official 0:2a36ad25fd97 508 int main()
mbed_official 0:2a36ad25fd97 509 {
mbed_official 0:2a36ad25fd97 510 BLE& ble = BLE::Instance();
mbed_official 0:2a36ad25fd97 511
mbed_official 0:2a36ad25fd97 512 while(1) {
mbed_official 0:2a36ad25fd97 513 {
mbed_official 0:2a36ad25fd97 514 events::EventQueue queue;
mbed_official 0:2a36ad25fd97 515 printf("\r\n * Device is a peripheral *\r\n\r\n");
mbed_official 0:2a36ad25fd97 516 PrivacyPeripheral peripheral(ble, queue);
mbed_official 0:2a36ad25fd97 517 peripheral.run();
mbed_official 0:2a36ad25fd97 518 }
mbed_official 0:2a36ad25fd97 519 {
mbed_official 0:2a36ad25fd97 520 events::EventQueue queue;
mbed_official 0:2a36ad25fd97 521 printf("\r\n * Device is a central *\r\n\r\n");
mbed_official 0:2a36ad25fd97 522 PrivacyCentral central(ble, queue);
mbed_official 0:2a36ad25fd97 523 central.run();
mbed_official 0:2a36ad25fd97 524 }
mbed_official 0:2a36ad25fd97 525 }
mbed_official 0:2a36ad25fd97 526
mbed_official 0:2a36ad25fd97 527 return 0;
mbed_official 0:2a36ad25fd97 528 }