Demonstration of possible usage of the Security Manager. Security Manager deals with pairing, authentication and encryption.

SM - example usage of the Security Manager to pair and encrypt

Demonstration of possible usage of the Security Manager. Security Manager deals with pairing, authentication and encryption.

The application demonstrates usage as a central and a peripheral. The central will connect to any connectable device present. Please have one ready and advertising. Application will attempt pairing. Please authorise your peer device to pair.

Upon success it will disconnect and start advertising to demonstrate usage as a peripheral. Please scan and connect using your peer device. Upon connection grant pairing if prompted. Upon success the application will disconnect. Observe the terminal to keep track of the sequence.

Running the application

Requirements

The sample application can be seen on any BLE scanner on a smartphone. If you don't have a scanner on your phone, please install :

- nRF Master Control Panel for Android.

- LightBlue for iPhone.

Information about activity is printed over the serial connection - please have a client open. You may use:

- Tera Term

Hardware requirements are in the main readme.

Building instructions

Building instructions for all samples are in the main readme.

Committer:
mbed_official
Date:
Thu Aug 15 17:02:31 2019 +0100
Revision:
23:03723224d5e7
Parent:
17:6bf7972c4d0e
Merge pull request #252 from donatieng/mbed_os_update

Update Master branch to use Mbed OS 5.13.1
.
Commit copied from https://github.com/ARMmbed/mbed-os-example-ble

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Donatien Garnier 1:916188eae2bb 1 /* mbed Microcontroller Library
Donatien Garnier 1:916188eae2bb 2 * Copyright (c) 2006-2013 ARM Limited
Donatien Garnier 1:916188eae2bb 3 *
Donatien Garnier 1:916188eae2bb 4 * Licensed under the Apache License, Version 2.0 (the "License");
Donatien Garnier 1:916188eae2bb 5 * you may not use this file except in compliance with the License.
Donatien Garnier 1:916188eae2bb 6 * You may obtain a copy of the License at
Donatien Garnier 1:916188eae2bb 7 *
Donatien Garnier 1:916188eae2bb 8 * http://www.apache.org/licenses/LICENSE-2.0
Donatien Garnier 1:916188eae2bb 9 *
Donatien Garnier 1:916188eae2bb 10 * Unless required by applicable law or agreed to in writing, software
Donatien Garnier 1:916188eae2bb 11 * distributed under the License is distributed on an "AS IS" BASIS,
Donatien Garnier 1:916188eae2bb 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Donatien Garnier 1:916188eae2bb 13 * See the License for the specific language governing permissions and
Donatien Garnier 1:916188eae2bb 14 * limitations under the License.
Donatien Garnier 1:916188eae2bb 15 */
Donatien Garnier 1:916188eae2bb 16
Donatien Garnier 1:916188eae2bb 17 #include <events/mbed_events.h>
Donatien Garnier 1:916188eae2bb 18 #include <mbed.h>
Donatien Garnier 1:916188eae2bb 19 #include "ble/BLE.h"
Donatien Garnier 1:916188eae2bb 20 #include "SecurityManager.h"
mbed_official 17:6bf7972c4d0e 21 #include "pretty_printer.h"
Donatien Garnier 1:916188eae2bb 22
mbed_official 9:674ab70e0f36 23 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 24 #include "LittleFileSystem.h"
mbed_official 9:674ab70e0f36 25 #include "HeapBlockDevice.h"
mbed_official 9:674ab70e0f36 26 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 27
Donatien Garnier 1:916188eae2bb 28 /** This example demonstrates all the basic setup required
Donatien Garnier 1:916188eae2bb 29 * for pairing and setting up link security both as a central and peripheral
Donatien Garnier 1:916188eae2bb 30 *
Donatien Garnier 1:916188eae2bb 31 * The example is implemented as two classes, one for the peripheral and one
Donatien Garnier 1:916188eae2bb 32 * for central inheriting from a common base. They are run in sequence and
Donatien Garnier 1:916188eae2bb 33 * require a peer device to connect to. During the peripheral device demonstration
Donatien Garnier 1:916188eae2bb 34 * a peer device is required to connect. In the central device demonstration
Donatien Garnier 1:916188eae2bb 35 * this peer device will be scanned for and connected to - therefore it should
Donatien Garnier 1:916188eae2bb 36 * be advertising with the same address as when it connected.
Donatien Garnier 1:916188eae2bb 37 *
Donatien Garnier 1:916188eae2bb 38 * During the test output is written on the serial connection to monitor its
Donatien Garnier 1:916188eae2bb 39 * progress.
Donatien Garnier 1:916188eae2bb 40 */
Donatien Garnier 1:916188eae2bb 41
mbed_official 17:6bf7972c4d0e 42 static const char DEVICE_NAME[] = "SM_device";
mbed_official 17:6bf7972c4d0e 43
mbed_official 17:6bf7972c4d0e 44 /* we have to specify the disconnect call because of ambiguous overloads */
mbed_official 17:6bf7972c4d0e 45 typedef ble_error_t (Gap::*disconnect_call_t)(ble::connection_handle_t, ble::local_disconnection_reason_t);
mbed_official 17:6bf7972c4d0e 46 const static disconnect_call_t disconnect_call = &Gap::disconnect;
Donatien Garnier 1:916188eae2bb 47
Donatien Garnier 1:916188eae2bb 48 /* for demonstration purposes we will store the peer device address
Donatien Garnier 1:916188eae2bb 49 * of the device that connects to us in the first demonstration
Donatien Garnier 1:916188eae2bb 50 * so we can use its address to reconnect to it later */
Donatien Garnier 1:916188eae2bb 51 static BLEProtocol::AddressBytes_t peer_address;
Donatien Garnier 1:916188eae2bb 52
Donatien Garnier 1:916188eae2bb 53 /** Base class for both peripheral and central. The same class that provides
Donatien Garnier 1:916188eae2bb 54 * the logic for the application also implements the SecurityManagerEventHandler
Donatien Garnier 1:916188eae2bb 55 * which is the interface used by the Security Manager to communicate events
Donatien Garnier 1:916188eae2bb 56 * back to the applications. You can provide overrides for a selection of events
Donatien Garnier 1:916188eae2bb 57 * your application is interested in.
Donatien Garnier 1:916188eae2bb 58 */
Donatien Garnier 1:916188eae2bb 59 class SMDevice : private mbed::NonCopyable<SMDevice>,
mbed_official 17:6bf7972c4d0e 60 public SecurityManager::EventHandler,
mbed_official 17:6bf7972c4d0e 61 public ble::Gap::EventHandler
Donatien Garnier 1:916188eae2bb 62 {
Donatien Garnier 1:916188eae2bb 63 public:
Donatien Garnier 1:916188eae2bb 64 SMDevice(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) :
Donatien Garnier 1:916188eae2bb 65 _led1(LED1, 0),
Donatien Garnier 1:916188eae2bb 66 _ble(ble),
Donatien Garnier 1:916188eae2bb 67 _event_queue(event_queue),
Donatien Garnier 1:916188eae2bb 68 _peer_address(peer_address),
Donatien Garnier 1:916188eae2bb 69 _handle(0),
Donatien Garnier 1:916188eae2bb 70 _is_connecting(false) { };
Donatien Garnier 1:916188eae2bb 71
Donatien Garnier 1:916188eae2bb 72 virtual ~SMDevice()
Donatien Garnier 1:916188eae2bb 73 {
Donatien Garnier 1:916188eae2bb 74 if (_ble.hasInitialized()) {
Donatien Garnier 1:916188eae2bb 75 _ble.shutdown();
Donatien Garnier 1:916188eae2bb 76 }
Donatien Garnier 1:916188eae2bb 77 };
Donatien Garnier 1:916188eae2bb 78
Donatien Garnier 1:916188eae2bb 79 /** Start BLE interface initialisation */
Donatien Garnier 1:916188eae2bb 80 void run()
Donatien Garnier 1:916188eae2bb 81 {
Donatien Garnier 1:916188eae2bb 82 ble_error_t error;
Donatien Garnier 1:916188eae2bb 83
Donatien Garnier 1:916188eae2bb 84 /* to show we're running we'll blink every 500ms */
Donatien Garnier 1:916188eae2bb 85 _event_queue.call_every(500, this, &SMDevice::blink);
Donatien Garnier 1:916188eae2bb 86
Donatien Garnier 1:916188eae2bb 87 if (_ble.hasInitialized()) {
Donatien Garnier 1:916188eae2bb 88 printf("Ble instance already initialised.\r\n");
Donatien Garnier 1:916188eae2bb 89 return;
Donatien Garnier 1:916188eae2bb 90 }
Donatien Garnier 1:916188eae2bb 91
Donatien Garnier 1:916188eae2bb 92 /* this will inform us off all events so we can schedule their handling
Donatien Garnier 1:916188eae2bb 93 * using our event queue */
Donatien Garnier 1:916188eae2bb 94 _ble.onEventsToProcess(
Donatien Garnier 1:916188eae2bb 95 makeFunctionPointer(this, &SMDevice::schedule_ble_events)
Donatien Garnier 1:916188eae2bb 96 );
Donatien Garnier 1:916188eae2bb 97
mbed_official 17:6bf7972c4d0e 98 /* handle gap events */
mbed_official 17:6bf7972c4d0e 99 _ble.gap().setEventHandler(this);
Donatien Garnier 1:916188eae2bb 100
Donatien Garnier 1:916188eae2bb 101 error = _ble.init(this, &SMDevice::on_init_complete);
Donatien Garnier 1:916188eae2bb 102
Donatien Garnier 1:916188eae2bb 103 if (error) {
Donatien Garnier 1:916188eae2bb 104 printf("Error returned by BLE::init.\r\n");
Donatien Garnier 1:916188eae2bb 105 return;
Donatien Garnier 1:916188eae2bb 106 }
Donatien Garnier 1:916188eae2bb 107
Donatien Garnier 1:916188eae2bb 108 /* this will not return until shutdown */
Donatien Garnier 1:916188eae2bb 109 _event_queue.dispatch_forever();
Donatien Garnier 1:916188eae2bb 110 };
Donatien Garnier 1:916188eae2bb 111
Donatien Garnier 1:916188eae2bb 112 private:
Donatien Garnier 1:916188eae2bb 113 /** Override to start chosen activity when initialisation completes */
Donatien Garnier 1:916188eae2bb 114 virtual void start() = 0;
Donatien Garnier 1:916188eae2bb 115
Donatien Garnier 1:916188eae2bb 116 /** This is called when BLE interface is initialised and starts the demonstration */
Donatien Garnier 1:916188eae2bb 117 void on_init_complete(BLE::InitializationCompleteCallbackContext *event)
Donatien Garnier 1:916188eae2bb 118 {
Donatien Garnier 1:916188eae2bb 119 ble_error_t error;
Donatien Garnier 1:916188eae2bb 120
Donatien Garnier 1:916188eae2bb 121 if (event->error) {
Donatien Garnier 1:916188eae2bb 122 printf("Error during the initialisation\r\n");
Donatien Garnier 1:916188eae2bb 123 return;
Donatien Garnier 1:916188eae2bb 124 }
Donatien Garnier 1:916188eae2bb 125
mbed_official 9:674ab70e0f36 126 /* This path will be used to store bonding information but will fallback
mbed_official 9:674ab70e0f36 127 * to storing in memory if file access fails (for example due to lack of a filesystem) */
mbed_official 9:674ab70e0f36 128 const char* db_path = "/fs/bt_sec_db";
Donatien Garnier 1:916188eae2bb 129 /* If the security manager is required this needs to be called before any
Donatien Garnier 1:916188eae2bb 130 * calls to the Security manager happen. */
mbed_official 9:674ab70e0f36 131 error = _ble.securityManager().init(
mbed_official 9:674ab70e0f36 132 true,
mbed_official 9:674ab70e0f36 133 false,
mbed_official 9:674ab70e0f36 134 SecurityManager::IO_CAPS_NONE,
mbed_official 9:674ab70e0f36 135 NULL,
mbed_official 9:674ab70e0f36 136 false,
mbed_official 9:674ab70e0f36 137 db_path
mbed_official 9:674ab70e0f36 138 );
Donatien Garnier 1:916188eae2bb 139
Donatien Garnier 1:916188eae2bb 140 if (error) {
Donatien Garnier 1:916188eae2bb 141 printf("Error during init %d\r\n", error);
Donatien Garnier 1:916188eae2bb 142 return;
Donatien Garnier 1:916188eae2bb 143 }
Donatien Garnier 1:916188eae2bb 144
mbed_official 9:674ab70e0f36 145 error = _ble.securityManager().preserveBondingStateOnReset(true);
mbed_official 9:674ab70e0f36 146
mbed_official 9:674ab70e0f36 147 if (error) {
mbed_official 9:674ab70e0f36 148 printf("Error during preserveBondingStateOnReset %d\r\n", error);
mbed_official 9:674ab70e0f36 149 }
mbed_official 9:674ab70e0f36 150
mbed_official 9:674ab70e0f36 151 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 152 /* Enable privacy so we can find the keys */
mbed_official 9:674ab70e0f36 153 error = _ble.gap().enablePrivacy(true);
mbed_official 9:674ab70e0f36 154
mbed_official 9:674ab70e0f36 155 if (error) {
mbed_official 9:674ab70e0f36 156 printf("Error enabling privacy\r\n");
mbed_official 9:674ab70e0f36 157 }
mbed_official 9:674ab70e0f36 158
mbed_official 9:674ab70e0f36 159 Gap::PeripheralPrivacyConfiguration_t configuration_p = {
mbed_official 9:674ab70e0f36 160 /* use_non_resolvable_random_address */ false,
mbed_official 9:674ab70e0f36 161 Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS
mbed_official 9:674ab70e0f36 162 };
mbed_official 9:674ab70e0f36 163 _ble.gap().setPeripheralPrivacyConfiguration(&configuration_p);
mbed_official 9:674ab70e0f36 164
mbed_official 9:674ab70e0f36 165 Gap::CentralPrivacyConfiguration_t configuration_c = {
mbed_official 9:674ab70e0f36 166 /* use_non_resolvable_random_address */ false,
mbed_official 9:674ab70e0f36 167 Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD
mbed_official 9:674ab70e0f36 168 };
mbed_official 9:674ab70e0f36 169 _ble.gap().setCentralPrivacyConfiguration(&configuration_c);
mbed_official 9:674ab70e0f36 170
mbed_official 9:674ab70e0f36 171 /* this demo switches between being master and slave */
mbed_official 9:674ab70e0f36 172 _ble.securityManager().setHintFutureRoleReversal(true);
mbed_official 9:674ab70e0f36 173 #endif
mbed_official 9:674ab70e0f36 174
Donatien Garnier 1:916188eae2bb 175 /* Tell the security manager to use methods in this class to inform us
Donatien Garnier 1:916188eae2bb 176 * of any events. Class needs to implement SecurityManagerEventHandler. */
Donatien Garnier 1:916188eae2bb 177 _ble.securityManager().setSecurityManagerEventHandler(this);
Donatien Garnier 1:916188eae2bb 178
mbed_official 17:6bf7972c4d0e 179 /* gap events also handled by this class */
mbed_official 17:6bf7972c4d0e 180 _ble.gap().setEventHandler(this);
mbed_official 17:6bf7972c4d0e 181
Donatien Garnier 1:916188eae2bb 182 /* print device address */
Donatien Garnier 1:916188eae2bb 183 Gap::AddressType_t addr_type;
Donatien Garnier 1:916188eae2bb 184 Gap::Address_t addr;
Donatien Garnier 1:916188eae2bb 185 _ble.gap().getAddress(&addr_type, addr);
mbed_official 17:6bf7972c4d0e 186 print_address(addr);
Donatien Garnier 1:916188eae2bb 187
Donatien Garnier 1:916188eae2bb 188 /* start test in 500 ms */
Donatien Garnier 1:916188eae2bb 189 _event_queue.call_in(500, this, &SMDevice::start);
Donatien Garnier 1:916188eae2bb 190 };
Donatien Garnier 1:916188eae2bb 191
Donatien Garnier 1:916188eae2bb 192 /** Schedule processing of events from the BLE in the event queue. */
Donatien Garnier 1:916188eae2bb 193 void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
Donatien Garnier 1:916188eae2bb 194 {
Donatien Garnier 1:916188eae2bb 195 _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
Donatien Garnier 1:916188eae2bb 196 };
Donatien Garnier 1:916188eae2bb 197
Donatien Garnier 1:916188eae2bb 198 /** Blink LED to show we're running */
Donatien Garnier 1:916188eae2bb 199 void blink(void)
Donatien Garnier 1:916188eae2bb 200 {
Donatien Garnier 1:916188eae2bb 201 _led1 = !_led1;
Donatien Garnier 1:916188eae2bb 202 };
Donatien Garnier 1:916188eae2bb 203
Donatien Garnier 1:916188eae2bb 204 private:
mbed_official 17:6bf7972c4d0e 205 /* Event handler */
mbed_official 17:6bf7972c4d0e 206
mbed_official 17:6bf7972c4d0e 207 /** Respond to a pairing request. This will be called by the stack
mbed_official 17:6bf7972c4d0e 208 * when a pairing request arrives and expects the application to
mbed_official 17:6bf7972c4d0e 209 * call acceptPairingRequest or cancelPairingRequest */
mbed_official 17:6bf7972c4d0e 210 virtual void pairingRequest(
mbed_official 17:6bf7972c4d0e 211 ble::connection_handle_t connectionHandle
mbed_official 17:6bf7972c4d0e 212 ) {
mbed_official 17:6bf7972c4d0e 213 printf("Pairing requested - authorising\r\n");
mbed_official 17:6bf7972c4d0e 214 _ble.securityManager().acceptPairingRequest(connectionHandle);
mbed_official 17:6bf7972c4d0e 215 }
mbed_official 17:6bf7972c4d0e 216
mbed_official 17:6bf7972c4d0e 217 /** Inform the application of a successful pairing. Terminate the demonstration. */
mbed_official 17:6bf7972c4d0e 218 virtual void pairingResult(
mbed_official 17:6bf7972c4d0e 219 ble::connection_handle_t connectionHandle,
mbed_official 17:6bf7972c4d0e 220 SecurityManager::SecurityCompletionStatus_t result
mbed_official 17:6bf7972c4d0e 221 ) {
mbed_official 17:6bf7972c4d0e 222 if (result == SecurityManager::SEC_STATUS_SUCCESS) {
mbed_official 17:6bf7972c4d0e 223 printf("Pairing successful\r\n");
mbed_official 17:6bf7972c4d0e 224 } else {
mbed_official 17:6bf7972c4d0e 225 printf("Pairing failed\r\n");
mbed_official 17:6bf7972c4d0e 226 }
mbed_official 17:6bf7972c4d0e 227 }
mbed_official 17:6bf7972c4d0e 228
mbed_official 17:6bf7972c4d0e 229 /** Inform the application of change in encryption status. This will be
mbed_official 17:6bf7972c4d0e 230 * communicated through the serial port */
mbed_official 17:6bf7972c4d0e 231 virtual void linkEncryptionResult(
mbed_official 17:6bf7972c4d0e 232 ble::connection_handle_t connectionHandle,
mbed_official 17:6bf7972c4d0e 233 ble::link_encryption_t result
mbed_official 17:6bf7972c4d0e 234 ) {
mbed_official 17:6bf7972c4d0e 235 if (result == ble::link_encryption_t::ENCRYPTED) {
mbed_official 17:6bf7972c4d0e 236 printf("Link ENCRYPTED\r\n");
mbed_official 17:6bf7972c4d0e 237 } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) {
mbed_official 17:6bf7972c4d0e 238 printf("Link ENCRYPTED_WITH_MITM\r\n");
mbed_official 17:6bf7972c4d0e 239 } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) {
mbed_official 17:6bf7972c4d0e 240 printf("Link NOT_ENCRYPTED\r\n");
mbed_official 17:6bf7972c4d0e 241 }
mbed_official 17:6bf7972c4d0e 242
mbed_official 17:6bf7972c4d0e 243 /* disconnect in 2 s */
mbed_official 17:6bf7972c4d0e 244 _event_queue.call_in(
mbed_official 17:6bf7972c4d0e 245 2000,
mbed_official 17:6bf7972c4d0e 246 &_ble.gap(),
mbed_official 17:6bf7972c4d0e 247 disconnect_call,
mbed_official 17:6bf7972c4d0e 248 _handle,
mbed_official 17:6bf7972c4d0e 249 ble::local_disconnection_reason_t(ble::local_disconnection_reason_t::USER_TERMINATION)
mbed_official 17:6bf7972c4d0e 250 );
mbed_official 17:6bf7972c4d0e 251 }
mbed_official 17:6bf7972c4d0e 252
mbed_official 17:6bf7972c4d0e 253 /** This is called by Gap to notify the application we disconnected,
mbed_official 17:6bf7972c4d0e 254 * in our case it ends the demonstration. */
mbed_official 17:6bf7972c4d0e 255 virtual void onDisconnectionComplete(const ble::DisconnectionCompleteEvent &)
mbed_official 17:6bf7972c4d0e 256 {
mbed_official 17:6bf7972c4d0e 257 printf("Diconnected\r\n");
mbed_official 17:6bf7972c4d0e 258 _event_queue.break_dispatch();
mbed_official 17:6bf7972c4d0e 259 };
mbed_official 17:6bf7972c4d0e 260
mbed_official 17:6bf7972c4d0e 261 virtual void onAdvertisingEnd(const ble::AdvertisingEndEvent &)
mbed_official 17:6bf7972c4d0e 262 {
mbed_official 17:6bf7972c4d0e 263 printf("Advertising timed out - aborting\r\n");
mbed_official 17:6bf7972c4d0e 264 _event_queue.break_dispatch();
mbed_official 17:6bf7972c4d0e 265 }
mbed_official 17:6bf7972c4d0e 266
mbed_official 17:6bf7972c4d0e 267 virtual void onScanTimeout(const ble::ScanTimeoutEvent &)
mbed_official 17:6bf7972c4d0e 268 {
mbed_official 17:6bf7972c4d0e 269 printf("Scan timed out - aborting\r\n");
mbed_official 17:6bf7972c4d0e 270 _event_queue.break_dispatch();
mbed_official 17:6bf7972c4d0e 271 }
mbed_official 17:6bf7972c4d0e 272
mbed_official 17:6bf7972c4d0e 273 private:
Donatien Garnier 1:916188eae2bb 274 DigitalOut _led1;
Donatien Garnier 1:916188eae2bb 275
Donatien Garnier 1:916188eae2bb 276 protected:
Donatien Garnier 1:916188eae2bb 277 BLE &_ble;
Donatien Garnier 1:916188eae2bb 278 events::EventQueue &_event_queue;
Donatien Garnier 1:916188eae2bb 279 BLEProtocol::AddressBytes_t &_peer_address;
Donatien Garnier 1:916188eae2bb 280 ble::connection_handle_t _handle;
Donatien Garnier 1:916188eae2bb 281 bool _is_connecting;
Donatien Garnier 1:916188eae2bb 282 };
Donatien Garnier 1:916188eae2bb 283
Donatien Garnier 1:916188eae2bb 284 /** A peripheral device will advertise, accept the connection and request
Donatien Garnier 1:916188eae2bb 285 * a change in link security. */
Donatien Garnier 1:916188eae2bb 286 class SMDevicePeripheral : public SMDevice {
Donatien Garnier 1:916188eae2bb 287 public:
Donatien Garnier 1:916188eae2bb 288 SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
Donatien Garnier 1:916188eae2bb 289 : SMDevice(ble, event_queue, peer_address) { }
Donatien Garnier 1:916188eae2bb 290
Donatien Garnier 1:916188eae2bb 291 virtual void start()
Donatien Garnier 1:916188eae2bb 292 {
Donatien Garnier 1:916188eae2bb 293 /* Set up and start advertising */
mbed_official 17:6bf7972c4d0e 294 uint8_t adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
mbed_official 17:6bf7972c4d0e 295 /* use the helper to build the payload */
mbed_official 17:6bf7972c4d0e 296 ble::AdvertisingDataBuilder adv_data_builder(
mbed_official 17:6bf7972c4d0e 297 adv_buffer
Donatien Garnier 1:916188eae2bb 298 );
Donatien Garnier 1:916188eae2bb 299
mbed_official 17:6bf7972c4d0e 300 adv_data_builder.setFlags();
mbed_official 17:6bf7972c4d0e 301 adv_data_builder.setName(DEVICE_NAME);
mbed_official 17:6bf7972c4d0e 302
mbed_official 17:6bf7972c4d0e 303 /* Set payload for the set */
mbed_official 17:6bf7972c4d0e 304 ble_error_t error = _ble.gap().setAdvertisingPayload(
mbed_official 17:6bf7972c4d0e 305 ble::LEGACY_ADVERTISING_HANDLE,
mbed_official 17:6bf7972c4d0e 306 adv_data_builder.getAdvertisingData()
mbed_official 17:6bf7972c4d0e 307 );
Donatien Garnier 1:916188eae2bb 308
Donatien Garnier 1:916188eae2bb 309 if (error) {
mbed_official 17:6bf7972c4d0e 310 print_error(error, "Gap::setAdvertisingPayload() failed");
mbed_official 17:6bf7972c4d0e 311 _event_queue.break_dispatch();
Donatien Garnier 1:916188eae2bb 312 return;
Donatien Garnier 1:916188eae2bb 313 }
Donatien Garnier 1:916188eae2bb 314
mbed_official 17:6bf7972c4d0e 315 ble::AdvertisingParameters adv_parameters(
mbed_official 17:6bf7972c4d0e 316 ble::advertising_type_t::CONNECTABLE_UNDIRECTED
mbed_official 17:6bf7972c4d0e 317 );
Donatien Garnier 1:916188eae2bb 318
mbed_official 17:6bf7972c4d0e 319 error = _ble.gap().setAdvertisingParameters(
mbed_official 17:6bf7972c4d0e 320 ble::LEGACY_ADVERTISING_HANDLE,
mbed_official 17:6bf7972c4d0e 321 adv_parameters
mbed_official 17:6bf7972c4d0e 322 );
Donatien Garnier 1:916188eae2bb 323
Donatien Garnier 1:916188eae2bb 324 if (error) {
mbed_official 17:6bf7972c4d0e 325 print_error(error, "Gap::setAdvertisingParameters() failed");
mbed_official 17:6bf7972c4d0e 326 return;
mbed_official 17:6bf7972c4d0e 327 }
mbed_official 17:6bf7972c4d0e 328
mbed_official 17:6bf7972c4d0e 329 error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
mbed_official 17:6bf7972c4d0e 330
mbed_official 17:6bf7972c4d0e 331 if (error) {
mbed_official 17:6bf7972c4d0e 332 print_error(error, "Gap::startAdvertising() failed");
Donatien Garnier 1:916188eae2bb 333 return;
Donatien Garnier 1:916188eae2bb 334 }
Donatien Garnier 1:916188eae2bb 335
mbed_official 9:674ab70e0f36 336 printf("Please connect to device\r\n");
mbed_official 9:674ab70e0f36 337
Donatien Garnier 1:916188eae2bb 338 /** This tells the stack to generate a pairingRequest event
Donatien Garnier 1:916188eae2bb 339 * which will require this application to respond before pairing
Donatien Garnier 1:916188eae2bb 340 * can proceed. Setting it to false will automatically accept
Donatien Garnier 1:916188eae2bb 341 * pairing. */
Donatien Garnier 1:916188eae2bb 342 _ble.securityManager().setPairingRequestAuthorisation(true);
Donatien Garnier 1:916188eae2bb 343 };
Donatien Garnier 1:916188eae2bb 344
Donatien Garnier 1:916188eae2bb 345 /** This is called by Gap to notify the application we connected,
Donatien Garnier 1:916188eae2bb 346 * in our case it immediately requests a change in link security */
mbed_official 17:6bf7972c4d0e 347 virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event)
Donatien Garnier 1:916188eae2bb 348 {
Donatien Garnier 1:916188eae2bb 349 ble_error_t error;
Donatien Garnier 1:916188eae2bb 350
Donatien Garnier 1:916188eae2bb 351 /* remember the device that connects to us now so we can connect to it
Donatien Garnier 1:916188eae2bb 352 * during the next demonstration */
mbed_official 17:6bf7972c4d0e 353 memcpy(_peer_address, event.getPeerAddress().data(), sizeof(_peer_address));
Donatien Garnier 1:916188eae2bb 354
mbed_official 17:6bf7972c4d0e 355 printf("Connected to peer: ");
mbed_official 17:6bf7972c4d0e 356 print_address(event.getPeerAddress().data());
mbed_official 9:674ab70e0f36 357
mbed_official 17:6bf7972c4d0e 358 _handle = event.getConnectionHandle();
Donatien Garnier 1:916188eae2bb 359
Donatien Garnier 1:916188eae2bb 360 /* Request a change in link security. This will be done
Donatien Garnier 1:916188eae2bb 361 * indirectly by asking the master of the connection to
Donatien Garnier 1:916188eae2bb 362 * change it. Depending on circumstances different actions
Donatien Garnier 1:916188eae2bb 363 * may be taken by the master which will trigger events
Donatien Garnier 1:916188eae2bb 364 * which the applications should deal with. */
Donatien Garnier 1:916188eae2bb 365 error = _ble.securityManager().setLinkSecurity(
Donatien Garnier 1:916188eae2bb 366 _handle,
Donatien Garnier 1:916188eae2bb 367 SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM
Donatien Garnier 1:916188eae2bb 368 );
Donatien Garnier 1:916188eae2bb 369
Donatien Garnier 1:916188eae2bb 370 if (error) {
Donatien Garnier 1:916188eae2bb 371 printf("Error during SM::setLinkSecurity %d\r\n", error);
Donatien Garnier 1:916188eae2bb 372 return;
Donatien Garnier 1:916188eae2bb 373 }
Donatien Garnier 1:916188eae2bb 374 };
Donatien Garnier 1:916188eae2bb 375 };
Donatien Garnier 1:916188eae2bb 376
Donatien Garnier 1:916188eae2bb 377 /** A central device will scan, connect to a peer and request pairing. */
Donatien Garnier 1:916188eae2bb 378 class SMDeviceCentral : public SMDevice {
Donatien Garnier 1:916188eae2bb 379 public:
Donatien Garnier 1:916188eae2bb 380 SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
Donatien Garnier 1:916188eae2bb 381 : SMDevice(ble, event_queue, peer_address) { }
Donatien Garnier 1:916188eae2bb 382
Donatien Garnier 1:916188eae2bb 383 virtual void start()
Donatien Garnier 1:916188eae2bb 384 {
mbed_official 17:6bf7972c4d0e 385 ble::ScanParameters params;
mbed_official 17:6bf7972c4d0e 386 ble_error_t error = _ble.gap().setScanParameters(params);
mbed_official 17:6bf7972c4d0e 387
mbed_official 17:6bf7972c4d0e 388 if (error) {
mbed_official 17:6bf7972c4d0e 389 print_error(error, "Error in Gap::startScan %d\r\n");
mbed_official 17:6bf7972c4d0e 390 return;
mbed_official 17:6bf7972c4d0e 391 }
mbed_official 17:6bf7972c4d0e 392
mbed_official 17:6bf7972c4d0e 393 /* start scanning, results will be handled by onAdvertisingReport */
mbed_official 17:6bf7972c4d0e 394 error = _ble.gap().startScan();
mbed_official 17:6bf7972c4d0e 395
mbed_official 17:6bf7972c4d0e 396 if (error) {
mbed_official 17:6bf7972c4d0e 397 print_error(error, "Error in Gap::startScan %d\r\n");
mbed_official 17:6bf7972c4d0e 398 return;
mbed_official 17:6bf7972c4d0e 399 }
Donatien Garnier 1:916188eae2bb 400
mbed_official 9:674ab70e0f36 401 printf("Please advertise\r\n");
mbed_official 9:674ab70e0f36 402
mbed_official 17:6bf7972c4d0e 403 printf("Scanning for: ");
mbed_official 17:6bf7972c4d0e 404 print_address(_peer_address);
Donatien Garnier 1:916188eae2bb 405 }
Donatien Garnier 1:916188eae2bb 406
mbed_official 17:6bf7972c4d0e 407 private:
mbed_official 17:6bf7972c4d0e 408 /* Gap::EventHandler */
mbed_official 17:6bf7972c4d0e 409
Donatien Garnier 1:916188eae2bb 410 /** Look at scan payload to find a peer device and connect to it */
mbed_official 17:6bf7972c4d0e 411 virtual void onAdvertisingReport(const ble::AdvertisingReportEvent &event)
Donatien Garnier 1:916188eae2bb 412 {
Donatien Garnier 1:916188eae2bb 413 /* don't bother with analysing scan result if we're already connecting */
Donatien Garnier 1:916188eae2bb 414 if (_is_connecting) {
Donatien Garnier 1:916188eae2bb 415 return;
Donatien Garnier 1:916188eae2bb 416 }
Donatien Garnier 1:916188eae2bb 417
mbed_official 17:6bf7972c4d0e 418 /* parse the advertising payload, looking for a discoverable device */
mbed_official 17:6bf7972c4d0e 419 if (memcmp(event.getPeerAddress().data(), _peer_address, sizeof(_peer_address)) == 0) {
mbed_official 17:6bf7972c4d0e 420 ble_error_t error = _ble.gap().stopScan();
mbed_official 17:6bf7972c4d0e 421
mbed_official 17:6bf7972c4d0e 422 if (error) {
mbed_official 17:6bf7972c4d0e 423 print_error(error, "Error caused by Gap::stopScan");
mbed_official 17:6bf7972c4d0e 424 return;
mbed_official 17:6bf7972c4d0e 425 }
Donatien Garnier 1:916188eae2bb 426
mbed_official 17:6bf7972c4d0e 427 ble::ConnectionParameters connection_params(
mbed_official 17:6bf7972c4d0e 428 ble::phy_t::LE_1M,
mbed_official 17:6bf7972c4d0e 429 ble::scan_interval_t(50),
mbed_official 17:6bf7972c4d0e 430 ble::scan_window_t(50),
mbed_official 17:6bf7972c4d0e 431 ble::conn_interval_t(50),
mbed_official 17:6bf7972c4d0e 432 ble::conn_interval_t(100),
mbed_official 17:6bf7972c4d0e 433 ble::slave_latency_t(0),
mbed_official 17:6bf7972c4d0e 434 ble::supervision_timeout_t(100)
mbed_official 17:6bf7972c4d0e 435 );
mbed_official 17:6bf7972c4d0e 436 connection_params.setOwnAddressType(ble::own_address_type_t::RANDOM);
mbed_official 17:6bf7972c4d0e 437
mbed_official 17:6bf7972c4d0e 438 error = _ble.gap().connect(
mbed_official 17:6bf7972c4d0e 439 event.getPeerAddressType(),
mbed_official 17:6bf7972c4d0e 440 event.getPeerAddress(),
mbed_official 17:6bf7972c4d0e 441 connection_params
mbed_official 9:674ab70e0f36 442 );
Donatien Garnier 1:916188eae2bb 443
mbed_official 9:674ab70e0f36 444 if (error) {
mbed_official 17:6bf7972c4d0e 445 print_error(error, "Error caused by Gap::connect");
Donatien Garnier 1:916188eae2bb 446 return;
Donatien Garnier 1:916188eae2bb 447 }
Donatien Garnier 1:916188eae2bb 448
mbed_official 9:674ab70e0f36 449 /* we may have already scan events waiting
mbed_official 9:674ab70e0f36 450 * to be processed so we need to remember
mbed_official 9:674ab70e0f36 451 * that we are already connecting and ignore them */
mbed_official 9:674ab70e0f36 452 _is_connecting = true;
mbed_official 9:674ab70e0f36 453
mbed_official 9:674ab70e0f36 454 return;
Donatien Garnier 1:916188eae2bb 455 }
mbed_official 17:6bf7972c4d0e 456 }
Donatien Garnier 1:916188eae2bb 457
Donatien Garnier 1:916188eae2bb 458 /** This is called by Gap to notify the application we connected,
Donatien Garnier 1:916188eae2bb 459 * in our case it immediately request pairing */
mbed_official 17:6bf7972c4d0e 460 virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event)
Donatien Garnier 1:916188eae2bb 461 {
mbed_official 17:6bf7972c4d0e 462 if (event.getStatus() == BLE_ERROR_NONE) {
mbed_official 17:6bf7972c4d0e 463 /* store the handle for future Security Manager requests */
mbed_official 17:6bf7972c4d0e 464 _handle = event.getConnectionHandle();
mbed_official 17:6bf7972c4d0e 465
mbed_official 17:6bf7972c4d0e 466 printf("Connected\r\n");
mbed_official 17:6bf7972c4d0e 467
mbed_official 17:6bf7972c4d0e 468 /* in this example the local device is the master so we request pairing */
mbed_official 17:6bf7972c4d0e 469 ble_error_t error = _ble.securityManager().requestPairing(_handle);
Donatien Garnier 1:916188eae2bb 470
mbed_official 17:6bf7972c4d0e 471 if (error) {
mbed_official 17:6bf7972c4d0e 472 printf("Error during SM::requestPairing %d\r\n", error);
mbed_official 17:6bf7972c4d0e 473 return;
mbed_official 17:6bf7972c4d0e 474 }
Donatien Garnier 1:916188eae2bb 475
mbed_official 17:6bf7972c4d0e 476 /* upon pairing success the application will disconnect */
mbed_official 17:6bf7972c4d0e 477 }
Donatien Garnier 1:916188eae2bb 478
mbed_official 17:6bf7972c4d0e 479 /* failed to connect - restart scan */
mbed_official 17:6bf7972c4d0e 480 ble_error_t error = _ble.gap().startScan();
mbed_official 9:674ab70e0f36 481
Donatien Garnier 1:916188eae2bb 482 if (error) {
mbed_official 17:6bf7972c4d0e 483 print_error(error, "Error in Gap::startScan %d\r\n");
Donatien Garnier 1:916188eae2bb 484 return;
Donatien Garnier 1:916188eae2bb 485 }
Donatien Garnier 1:916188eae2bb 486 };
Donatien Garnier 1:916188eae2bb 487 };
Donatien Garnier 1:916188eae2bb 488
mbed_official 9:674ab70e0f36 489
mbed_official 9:674ab70e0f36 490 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 491 bool create_filesystem()
mbed_official 9:674ab70e0f36 492 {
mbed_official 9:674ab70e0f36 493 static LittleFileSystem fs("fs");
mbed_official 9:674ab70e0f36 494
mbed_official 9:674ab70e0f36 495 /* replace this with any physical block device your board supports (like an SD card) */
mbed_official 9:674ab70e0f36 496 static HeapBlockDevice bd(4096, 256);
mbed_official 9:674ab70e0f36 497
mbed_official 9:674ab70e0f36 498 int err = bd.init();
mbed_official 9:674ab70e0f36 499
mbed_official 9:674ab70e0f36 500 if (err) {
mbed_official 9:674ab70e0f36 501 return false;
mbed_official 9:674ab70e0f36 502 }
mbed_official 9:674ab70e0f36 503
mbed_official 9:674ab70e0f36 504 err = bd.erase(0, bd.size());
mbed_official 9:674ab70e0f36 505
mbed_official 9:674ab70e0f36 506 if (err) {
mbed_official 9:674ab70e0f36 507 return false;
mbed_official 9:674ab70e0f36 508 }
mbed_official 9:674ab70e0f36 509
mbed_official 9:674ab70e0f36 510 err = fs.mount(&bd);
mbed_official 9:674ab70e0f36 511
mbed_official 9:674ab70e0f36 512 if (err) {
mbed_official 9:674ab70e0f36 513 /* Reformat if we can't mount the filesystem */
mbed_official 9:674ab70e0f36 514 printf("No filesystem found, formatting...\r\n");
mbed_official 9:674ab70e0f36 515
mbed_official 9:674ab70e0f36 516 err = fs.reformat(&bd);
mbed_official 9:674ab70e0f36 517
mbed_official 9:674ab70e0f36 518 if (err) {
mbed_official 9:674ab70e0f36 519 return false;
mbed_official 9:674ab70e0f36 520 }
mbed_official 9:674ab70e0f36 521 }
mbed_official 9:674ab70e0f36 522
mbed_official 9:674ab70e0f36 523 return true;
mbed_official 9:674ab70e0f36 524 }
mbed_official 9:674ab70e0f36 525 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 526
Donatien Garnier 1:916188eae2bb 527 int main()
Donatien Garnier 1:916188eae2bb 528 {
Donatien Garnier 1:916188eae2bb 529 BLE& ble = BLE::Instance();
Donatien Garnier 1:916188eae2bb 530 events::EventQueue queue;
Donatien Garnier 1:916188eae2bb 531
mbed_official 9:674ab70e0f36 532 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 533 /* if filesystem creation fails or there is no filesystem the security manager
mbed_official 9:674ab70e0f36 534 * will fallback to storing the security database in memory */
mbed_official 9:674ab70e0f36 535 if (!create_filesystem()) {
mbed_official 9:674ab70e0f36 536 printf("Filesystem creation failed, will use memory storage\r\n");
Donatien Garnier 1:916188eae2bb 537 }
mbed_official 9:674ab70e0f36 538 #endif
Donatien Garnier 1:916188eae2bb 539
mbed_official 9:674ab70e0f36 540 while(1) {
mbed_official 9:674ab70e0f36 541 {
mbed_official 9:674ab70e0f36 542 printf("\r\n PERIPHERAL \r\n\r\n");
mbed_official 9:674ab70e0f36 543 SMDevicePeripheral peripheral(ble, queue, peer_address);
mbed_official 9:674ab70e0f36 544 peripheral.run();
mbed_official 9:674ab70e0f36 545 }
mbed_official 9:674ab70e0f36 546
mbed_official 9:674ab70e0f36 547 {
mbed_official 9:674ab70e0f36 548 printf("\r\n CENTRAL \r\n\r\n");
mbed_official 9:674ab70e0f36 549 SMDeviceCentral central(ble, queue, peer_address);
mbed_official 9:674ab70e0f36 550 central.run();
mbed_official 9:674ab70e0f36 551 }
Donatien Garnier 1:916188eae2bb 552 }
Donatien Garnier 1:916188eae2bb 553
Donatien Garnier 1:916188eae2bb 554 return 0;
Donatien Garnier 1:916188eae2bb 555 }