Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
source/main.cpp@0:2a36ad25fd97, 2019-02-25 (annotated)
- 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?
| User | Revision | Line number | New 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 | } |