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:
Mon Oct 22 12:31:01 2018 +0100
Revision:
13:d849f18bb4dd
Parent:
9:674ab70e0f36
Child:
17:6bf7972c4d0e
Merge pull request #187 from cmonr/master

Updating mbed-os to mbed-os-5.10.2
.
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"
Donatien Garnier 1:916188eae2bb 21
mbed_official 9:674ab70e0f36 22 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 23 #include "LittleFileSystem.h"
mbed_official 9:674ab70e0f36 24 #include "HeapBlockDevice.h"
mbed_official 9:674ab70e0f36 25 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 26
Donatien Garnier 1:916188eae2bb 27 /** This example demonstrates all the basic setup required
Donatien Garnier 1:916188eae2bb 28 * for pairing and setting up link security both as a central and peripheral
Donatien Garnier 1:916188eae2bb 29 *
Donatien Garnier 1:916188eae2bb 30 * The example is implemented as two classes, one for the peripheral and one
Donatien Garnier 1:916188eae2bb 31 * for central inheriting from a common base. They are run in sequence and
Donatien Garnier 1:916188eae2bb 32 * require a peer device to connect to. During the peripheral device demonstration
Donatien Garnier 1:916188eae2bb 33 * a peer device is required to connect. In the central device demonstration
Donatien Garnier 1:916188eae2bb 34 * this peer device will be scanned for and connected to - therefore it should
Donatien Garnier 1:916188eae2bb 35 * be advertising with the same address as when it connected.
Donatien Garnier 1:916188eae2bb 36 *
Donatien Garnier 1:916188eae2bb 37 * During the test output is written on the serial connection to monitor its
Donatien Garnier 1:916188eae2bb 38 * progress.
Donatien Garnier 1:916188eae2bb 39 */
Donatien Garnier 1:916188eae2bb 40
Donatien Garnier 1:916188eae2bb 41 static const uint8_t DEVICE_NAME[] = "SM_device";
Donatien Garnier 1:916188eae2bb 42
Donatien Garnier 1:916188eae2bb 43 /* for demonstration purposes we will store the peer device address
Donatien Garnier 1:916188eae2bb 44 * of the device that connects to us in the first demonstration
Donatien Garnier 1:916188eae2bb 45 * so we can use its address to reconnect to it later */
Donatien Garnier 1:916188eae2bb 46 static BLEProtocol::AddressBytes_t peer_address;
Donatien Garnier 1:916188eae2bb 47
Donatien Garnier 1:916188eae2bb 48 /** Base class for both peripheral and central. The same class that provides
Donatien Garnier 1:916188eae2bb 49 * the logic for the application also implements the SecurityManagerEventHandler
Donatien Garnier 1:916188eae2bb 50 * which is the interface used by the Security Manager to communicate events
Donatien Garnier 1:916188eae2bb 51 * back to the applications. You can provide overrides for a selection of events
Donatien Garnier 1:916188eae2bb 52 * your application is interested in.
Donatien Garnier 1:916188eae2bb 53 */
Donatien Garnier 1:916188eae2bb 54 class SMDevice : private mbed::NonCopyable<SMDevice>,
Donatien Garnier 1:916188eae2bb 55 public SecurityManager::EventHandler
Donatien Garnier 1:916188eae2bb 56 {
Donatien Garnier 1:916188eae2bb 57 public:
Donatien Garnier 1:916188eae2bb 58 SMDevice(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) :
Donatien Garnier 1:916188eae2bb 59 _led1(LED1, 0),
Donatien Garnier 1:916188eae2bb 60 _ble(ble),
Donatien Garnier 1:916188eae2bb 61 _event_queue(event_queue),
Donatien Garnier 1:916188eae2bb 62 _peer_address(peer_address),
Donatien Garnier 1:916188eae2bb 63 _handle(0),
Donatien Garnier 1:916188eae2bb 64 _is_connecting(false) { };
Donatien Garnier 1:916188eae2bb 65
Donatien Garnier 1:916188eae2bb 66 virtual ~SMDevice()
Donatien Garnier 1:916188eae2bb 67 {
Donatien Garnier 1:916188eae2bb 68 if (_ble.hasInitialized()) {
Donatien Garnier 1:916188eae2bb 69 _ble.shutdown();
Donatien Garnier 1:916188eae2bb 70 }
Donatien Garnier 1:916188eae2bb 71 };
Donatien Garnier 1:916188eae2bb 72
Donatien Garnier 1:916188eae2bb 73 /** Start BLE interface initialisation */
Donatien Garnier 1:916188eae2bb 74 void run()
Donatien Garnier 1:916188eae2bb 75 {
Donatien Garnier 1:916188eae2bb 76 ble_error_t error;
Donatien Garnier 1:916188eae2bb 77
Donatien Garnier 1:916188eae2bb 78 /* to show we're running we'll blink every 500ms */
Donatien Garnier 1:916188eae2bb 79 _event_queue.call_every(500, this, &SMDevice::blink);
Donatien Garnier 1:916188eae2bb 80
Donatien Garnier 1:916188eae2bb 81 if (_ble.hasInitialized()) {
Donatien Garnier 1:916188eae2bb 82 printf("Ble instance already initialised.\r\n");
Donatien Garnier 1:916188eae2bb 83 return;
Donatien Garnier 1:916188eae2bb 84 }
Donatien Garnier 1:916188eae2bb 85
Donatien Garnier 1:916188eae2bb 86 /* this will inform us off all events so we can schedule their handling
Donatien Garnier 1:916188eae2bb 87 * using our event queue */
Donatien Garnier 1:916188eae2bb 88 _ble.onEventsToProcess(
Donatien Garnier 1:916188eae2bb 89 makeFunctionPointer(this, &SMDevice::schedule_ble_events)
Donatien Garnier 1:916188eae2bb 90 );
Donatien Garnier 1:916188eae2bb 91
Donatien Garnier 1:916188eae2bb 92 /* handle timeouts, for example when connection attempts fail */
Donatien Garnier 1:916188eae2bb 93 _ble.gap().onTimeout(
Donatien Garnier 1:916188eae2bb 94 makeFunctionPointer(this, &SMDevice::on_timeout)
Donatien Garnier 1:916188eae2bb 95 );
Donatien Garnier 1:916188eae2bb 96
Donatien Garnier 1:916188eae2bb 97 error = _ble.init(this, &SMDevice::on_init_complete);
Donatien Garnier 1:916188eae2bb 98
Donatien Garnier 1:916188eae2bb 99 if (error) {
Donatien Garnier 1:916188eae2bb 100 printf("Error returned by BLE::init.\r\n");
Donatien Garnier 1:916188eae2bb 101 return;
Donatien Garnier 1:916188eae2bb 102 }
Donatien Garnier 1:916188eae2bb 103
Donatien Garnier 1:916188eae2bb 104 /* this will not return until shutdown */
Donatien Garnier 1:916188eae2bb 105 _event_queue.dispatch_forever();
Donatien Garnier 1:916188eae2bb 106 };
Donatien Garnier 1:916188eae2bb 107
Donatien Garnier 1:916188eae2bb 108 /* event handler functions */
Donatien Garnier 1:916188eae2bb 109
Donatien Garnier 1:916188eae2bb 110 /** Respond to a pairing request. This will be called by the stack
Donatien Garnier 1:916188eae2bb 111 * when a pairing request arrives and expects the application to
Donatien Garnier 1:916188eae2bb 112 * call acceptPairingRequest or cancelPairingRequest */
Donatien Garnier 1:916188eae2bb 113 virtual void pairingRequest(
Donatien Garnier 1:916188eae2bb 114 ble::connection_handle_t connectionHandle
Donatien Garnier 1:916188eae2bb 115 ) {
mbed_official 9:674ab70e0f36 116 printf("Pairing requested - authorising\r\n");
Donatien Garnier 1:916188eae2bb 117 _ble.securityManager().acceptPairingRequest(connectionHandle);
Donatien Garnier 1:916188eae2bb 118 }
Donatien Garnier 1:916188eae2bb 119
Donatien Garnier 1:916188eae2bb 120 /** Inform the application of a successful pairing. Terminate the demonstration. */
Donatien Garnier 1:916188eae2bb 121 virtual void pairingResult(
Donatien Garnier 1:916188eae2bb 122 ble::connection_handle_t connectionHandle,
Donatien Garnier 1:916188eae2bb 123 SecurityManager::SecurityCompletionStatus_t result
Donatien Garnier 1:916188eae2bb 124 ) {
Donatien Garnier 1:916188eae2bb 125 if (result == SecurityManager::SEC_STATUS_SUCCESS) {
Donatien Garnier 1:916188eae2bb 126 printf("Pairing successful\r\n");
Donatien Garnier 1:916188eae2bb 127 } else {
Donatien Garnier 1:916188eae2bb 128 printf("Pairing failed\r\n");
Donatien Garnier 1:916188eae2bb 129 }
Donatien Garnier 1:916188eae2bb 130 }
Donatien Garnier 1:916188eae2bb 131
Donatien Garnier 1:916188eae2bb 132 /** Inform the application of change in encryption status. This will be
Donatien Garnier 1:916188eae2bb 133 * communicated through the serial port */
Donatien Garnier 1:916188eae2bb 134 virtual void linkEncryptionResult(
Donatien Garnier 1:916188eae2bb 135 ble::connection_handle_t connectionHandle,
Donatien Garnier 1:916188eae2bb 136 ble::link_encryption_t result
Donatien Garnier 1:916188eae2bb 137 ) {
Donatien Garnier 1:916188eae2bb 138 if (result == ble::link_encryption_t::ENCRYPTED) {
Donatien Garnier 1:916188eae2bb 139 printf("Link ENCRYPTED\r\n");
Donatien Garnier 1:916188eae2bb 140 } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) {
Donatien Garnier 1:916188eae2bb 141 printf("Link ENCRYPTED_WITH_MITM\r\n");
Donatien Garnier 1:916188eae2bb 142 } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) {
Donatien Garnier 1:916188eae2bb 143 printf("Link NOT_ENCRYPTED\r\n");
Donatien Garnier 1:916188eae2bb 144 }
mbed_official 9:674ab70e0f36 145
mbed_official 9:674ab70e0f36 146 /* disconnect in 2 s */
mbed_official 9:674ab70e0f36 147 _event_queue.call_in(
mbed_official 9:674ab70e0f36 148 2000, &_ble.gap(),
mbed_official 9:674ab70e0f36 149 &Gap::disconnect, _handle, Gap::REMOTE_USER_TERMINATED_CONNECTION
mbed_official 9:674ab70e0f36 150 );
Donatien Garnier 1:916188eae2bb 151 }
Donatien Garnier 1:916188eae2bb 152
Donatien Garnier 1:916188eae2bb 153 private:
Donatien Garnier 1:916188eae2bb 154 /** Override to start chosen activity when initialisation completes */
Donatien Garnier 1:916188eae2bb 155 virtual void start() = 0;
Donatien Garnier 1:916188eae2bb 156
Donatien Garnier 1:916188eae2bb 157 /** This is called when BLE interface is initialised and starts the demonstration */
Donatien Garnier 1:916188eae2bb 158 void on_init_complete(BLE::InitializationCompleteCallbackContext *event)
Donatien Garnier 1:916188eae2bb 159 {
Donatien Garnier 1:916188eae2bb 160 ble_error_t error;
Donatien Garnier 1:916188eae2bb 161
Donatien Garnier 1:916188eae2bb 162 if (event->error) {
Donatien Garnier 1:916188eae2bb 163 printf("Error during the initialisation\r\n");
Donatien Garnier 1:916188eae2bb 164 return;
Donatien Garnier 1:916188eae2bb 165 }
Donatien Garnier 1:916188eae2bb 166
mbed_official 9:674ab70e0f36 167 /* This path will be used to store bonding information but will fallback
mbed_official 9:674ab70e0f36 168 * to storing in memory if file access fails (for example due to lack of a filesystem) */
mbed_official 9:674ab70e0f36 169 const char* db_path = "/fs/bt_sec_db";
Donatien Garnier 1:916188eae2bb 170 /* If the security manager is required this needs to be called before any
Donatien Garnier 1:916188eae2bb 171 * calls to the Security manager happen. */
mbed_official 9:674ab70e0f36 172 error = _ble.securityManager().init(
mbed_official 9:674ab70e0f36 173 true,
mbed_official 9:674ab70e0f36 174 false,
mbed_official 9:674ab70e0f36 175 SecurityManager::IO_CAPS_NONE,
mbed_official 9:674ab70e0f36 176 NULL,
mbed_official 9:674ab70e0f36 177 false,
mbed_official 9:674ab70e0f36 178 db_path
mbed_official 9:674ab70e0f36 179 );
Donatien Garnier 1:916188eae2bb 180
Donatien Garnier 1:916188eae2bb 181 if (error) {
Donatien Garnier 1:916188eae2bb 182 printf("Error during init %d\r\n", error);
Donatien Garnier 1:916188eae2bb 183 return;
Donatien Garnier 1:916188eae2bb 184 }
Donatien Garnier 1:916188eae2bb 185
mbed_official 9:674ab70e0f36 186 error = _ble.securityManager().preserveBondingStateOnReset(true);
mbed_official 9:674ab70e0f36 187
mbed_official 9:674ab70e0f36 188 if (error) {
mbed_official 9:674ab70e0f36 189 printf("Error during preserveBondingStateOnReset %d\r\n", error);
mbed_official 9:674ab70e0f36 190 }
mbed_official 9:674ab70e0f36 191
mbed_official 9:674ab70e0f36 192 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 193 /* Enable privacy so we can find the keys */
mbed_official 9:674ab70e0f36 194 error = _ble.gap().enablePrivacy(true);
mbed_official 9:674ab70e0f36 195
mbed_official 9:674ab70e0f36 196 if (error) {
mbed_official 9:674ab70e0f36 197 printf("Error enabling privacy\r\n");
mbed_official 9:674ab70e0f36 198 }
mbed_official 9:674ab70e0f36 199
mbed_official 9:674ab70e0f36 200 Gap::PeripheralPrivacyConfiguration_t configuration_p = {
mbed_official 9:674ab70e0f36 201 /* use_non_resolvable_random_address */ false,
mbed_official 9:674ab70e0f36 202 Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS
mbed_official 9:674ab70e0f36 203 };
mbed_official 9:674ab70e0f36 204 _ble.gap().setPeripheralPrivacyConfiguration(&configuration_p);
mbed_official 9:674ab70e0f36 205
mbed_official 9:674ab70e0f36 206 Gap::CentralPrivacyConfiguration_t configuration_c = {
mbed_official 9:674ab70e0f36 207 /* use_non_resolvable_random_address */ false,
mbed_official 9:674ab70e0f36 208 Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD
mbed_official 9:674ab70e0f36 209 };
mbed_official 9:674ab70e0f36 210 _ble.gap().setCentralPrivacyConfiguration(&configuration_c);
mbed_official 9:674ab70e0f36 211
mbed_official 9:674ab70e0f36 212 /* this demo switches between being master and slave */
mbed_official 9:674ab70e0f36 213 _ble.securityManager().setHintFutureRoleReversal(true);
mbed_official 9:674ab70e0f36 214 #endif
mbed_official 9:674ab70e0f36 215
Donatien Garnier 1:916188eae2bb 216 /* Tell the security manager to use methods in this class to inform us
Donatien Garnier 1:916188eae2bb 217 * of any events. Class needs to implement SecurityManagerEventHandler. */
Donatien Garnier 1:916188eae2bb 218 _ble.securityManager().setSecurityManagerEventHandler(this);
Donatien Garnier 1:916188eae2bb 219
Donatien Garnier 1:916188eae2bb 220 /* print device address */
Donatien Garnier 1:916188eae2bb 221 Gap::AddressType_t addr_type;
Donatien Garnier 1:916188eae2bb 222 Gap::Address_t addr;
Donatien Garnier 1:916188eae2bb 223 _ble.gap().getAddress(&addr_type, addr);
Donatien Garnier 1:916188eae2bb 224 printf("Device address: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
Donatien Garnier 1:916188eae2bb 225 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
Donatien Garnier 1:916188eae2bb 226
Donatien Garnier 1:916188eae2bb 227 /* when scanning we want to connect to a peer device so we need to
Donatien Garnier 1:916188eae2bb 228 * attach callbacks that are used by Gap to notify us of events */
Donatien Garnier 1:916188eae2bb 229 _ble.gap().onConnection(this, &SMDevice::on_connect);
Donatien Garnier 1:916188eae2bb 230 _ble.gap().onDisconnection(this, &SMDevice::on_disconnect);
Donatien Garnier 1:916188eae2bb 231
Donatien Garnier 1:916188eae2bb 232 /* start test in 500 ms */
Donatien Garnier 1:916188eae2bb 233 _event_queue.call_in(500, this, &SMDevice::start);
Donatien Garnier 1:916188eae2bb 234 };
Donatien Garnier 1:916188eae2bb 235
Donatien Garnier 1:916188eae2bb 236 /** This is called by Gap to notify the application we connected */
Donatien Garnier 1:916188eae2bb 237 virtual void on_connect(const Gap::ConnectionCallbackParams_t *connection_event) = 0;
Donatien Garnier 1:916188eae2bb 238
Donatien Garnier 1:916188eae2bb 239 /** This is called by Gap to notify the application we disconnected,
Donatien Garnier 1:916188eae2bb 240 * in our case it ends the demonstration. */
Donatien Garnier 1:916188eae2bb 241 void on_disconnect(const Gap::DisconnectionCallbackParams_t *event)
Donatien Garnier 1:916188eae2bb 242 {
mbed_official 9:674ab70e0f36 243 printf("Diconnected\r\n");
Donatien Garnier 1:916188eae2bb 244 _event_queue.break_dispatch();
Donatien Garnier 1:916188eae2bb 245 };
Donatien Garnier 1:916188eae2bb 246
Donatien Garnier 1:916188eae2bb 247 /** End demonstration unexpectedly. Called if timeout is reached during advertising,
Donatien Garnier 1:916188eae2bb 248 * scanning or connection initiation */
Donatien Garnier 1:916188eae2bb 249 void on_timeout(const Gap::TimeoutSource_t source)
Donatien Garnier 1:916188eae2bb 250 {
mbed_official 9:674ab70e0f36 251 printf("Unexpected timeout - aborting\r\n");
Donatien Garnier 1:916188eae2bb 252 _event_queue.break_dispatch();
Donatien Garnier 1:916188eae2bb 253 };
Donatien Garnier 1:916188eae2bb 254
Donatien Garnier 1:916188eae2bb 255 /** Schedule processing of events from the BLE in the event queue. */
Donatien Garnier 1:916188eae2bb 256 void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
Donatien Garnier 1:916188eae2bb 257 {
Donatien Garnier 1:916188eae2bb 258 _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
Donatien Garnier 1:916188eae2bb 259 };
Donatien Garnier 1:916188eae2bb 260
Donatien Garnier 1:916188eae2bb 261 /** Blink LED to show we're running */
Donatien Garnier 1:916188eae2bb 262 void blink(void)
Donatien Garnier 1:916188eae2bb 263 {
Donatien Garnier 1:916188eae2bb 264 _led1 = !_led1;
Donatien Garnier 1:916188eae2bb 265 };
Donatien Garnier 1:916188eae2bb 266
Donatien Garnier 1:916188eae2bb 267 private:
Donatien Garnier 1:916188eae2bb 268 DigitalOut _led1;
Donatien Garnier 1:916188eae2bb 269
Donatien Garnier 1:916188eae2bb 270 protected:
Donatien Garnier 1:916188eae2bb 271 BLE &_ble;
Donatien Garnier 1:916188eae2bb 272 events::EventQueue &_event_queue;
Donatien Garnier 1:916188eae2bb 273 BLEProtocol::AddressBytes_t &_peer_address;
Donatien Garnier 1:916188eae2bb 274 ble::connection_handle_t _handle;
Donatien Garnier 1:916188eae2bb 275 bool _is_connecting;
Donatien Garnier 1:916188eae2bb 276 };
Donatien Garnier 1:916188eae2bb 277
Donatien Garnier 1:916188eae2bb 278 /** A peripheral device will advertise, accept the connection and request
Donatien Garnier 1:916188eae2bb 279 * a change in link security. */
Donatien Garnier 1:916188eae2bb 280 class SMDevicePeripheral : public SMDevice {
Donatien Garnier 1:916188eae2bb 281 public:
Donatien Garnier 1:916188eae2bb 282 SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
Donatien Garnier 1:916188eae2bb 283 : SMDevice(ble, event_queue, peer_address) { }
Donatien Garnier 1:916188eae2bb 284
Donatien Garnier 1:916188eae2bb 285 virtual void start()
Donatien Garnier 1:916188eae2bb 286 {
Donatien Garnier 1:916188eae2bb 287 /* Set up and start advertising */
Donatien Garnier 1:916188eae2bb 288
Donatien Garnier 1:916188eae2bb 289 ble_error_t error;
Donatien Garnier 1:916188eae2bb 290 GapAdvertisingData advertising_data;
Donatien Garnier 1:916188eae2bb 291
Donatien Garnier 1:916188eae2bb 292 /* add advertising flags */
Donatien Garnier 1:916188eae2bb 293 advertising_data.addFlags(GapAdvertisingData::LE_GENERAL_DISCOVERABLE
Donatien Garnier 1:916188eae2bb 294 | GapAdvertisingData::BREDR_NOT_SUPPORTED);
Donatien Garnier 1:916188eae2bb 295
Donatien Garnier 1:916188eae2bb 296 /* add device name */
Donatien Garnier 1:916188eae2bb 297 advertising_data.addData(
Donatien Garnier 1:916188eae2bb 298 GapAdvertisingData::COMPLETE_LOCAL_NAME,
Donatien Garnier 1:916188eae2bb 299 DEVICE_NAME,
Donatien Garnier 1:916188eae2bb 300 sizeof(DEVICE_NAME)
Donatien Garnier 1:916188eae2bb 301 );
Donatien Garnier 1:916188eae2bb 302
Donatien Garnier 1:916188eae2bb 303 error = _ble.gap().setAdvertisingPayload(advertising_data);
Donatien Garnier 1:916188eae2bb 304
Donatien Garnier 1:916188eae2bb 305 if (error) {
Donatien Garnier 1:916188eae2bb 306 printf("Error during Gap::setAdvertisingPayload\r\n");
Donatien Garnier 1:916188eae2bb 307 return;
Donatien Garnier 1:916188eae2bb 308 }
Donatien Garnier 1:916188eae2bb 309
Donatien Garnier 1:916188eae2bb 310 /* advertise to everyone */
Donatien Garnier 1:916188eae2bb 311 _ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Donatien Garnier 1:916188eae2bb 312 /* how many milliseconds between advertisements, lower interval
Donatien Garnier 1:916188eae2bb 313 * increases the chances of being seen at the cost of more power */
Donatien Garnier 1:916188eae2bb 314 _ble.gap().setAdvertisingInterval(20);
Donatien Garnier 1:916188eae2bb 315 _ble.gap().setAdvertisingTimeout(0);
Donatien Garnier 1:916188eae2bb 316
Donatien Garnier 1:916188eae2bb 317 error = _ble.gap().startAdvertising();
Donatien Garnier 1:916188eae2bb 318
Donatien Garnier 1:916188eae2bb 319 if (error) {
Donatien Garnier 1:916188eae2bb 320 printf("Error during Gap::startAdvertising.\r\n");
Donatien Garnier 1:916188eae2bb 321 return;
Donatien Garnier 1:916188eae2bb 322 }
Donatien Garnier 1:916188eae2bb 323
mbed_official 9:674ab70e0f36 324 printf("Please connect to device\r\n");
mbed_official 9:674ab70e0f36 325
Donatien Garnier 1:916188eae2bb 326 /** This tells the stack to generate a pairingRequest event
Donatien Garnier 1:916188eae2bb 327 * which will require this application to respond before pairing
Donatien Garnier 1:916188eae2bb 328 * can proceed. Setting it to false will automatically accept
Donatien Garnier 1:916188eae2bb 329 * pairing. */
Donatien Garnier 1:916188eae2bb 330 _ble.securityManager().setPairingRequestAuthorisation(true);
Donatien Garnier 1:916188eae2bb 331 };
Donatien Garnier 1:916188eae2bb 332
Donatien Garnier 1:916188eae2bb 333 /** This is called by Gap to notify the application we connected,
Donatien Garnier 1:916188eae2bb 334 * in our case it immediately requests a change in link security */
Donatien Garnier 1:916188eae2bb 335 virtual void on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
Donatien Garnier 1:916188eae2bb 336 {
Donatien Garnier 1:916188eae2bb 337 ble_error_t error;
Donatien Garnier 1:916188eae2bb 338
Donatien Garnier 1:916188eae2bb 339 /* remember the device that connects to us now so we can connect to it
Donatien Garnier 1:916188eae2bb 340 * during the next demonstration */
Donatien Garnier 1:916188eae2bb 341 memcpy(_peer_address, connection_event->peerAddr, sizeof(_peer_address));
Donatien Garnier 1:916188eae2bb 342
mbed_official 9:674ab70e0f36 343 printf("Connected to: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
mbed_official 9:674ab70e0f36 344 _peer_address[5], _peer_address[4], _peer_address[3],
mbed_official 9:674ab70e0f36 345 _peer_address[2], _peer_address[1], _peer_address[0]);
mbed_official 9:674ab70e0f36 346
Donatien Garnier 1:916188eae2bb 347 /* store the handle for future Security Manager requests */
Donatien Garnier 1:916188eae2bb 348 _handle = connection_event->handle;
Donatien Garnier 1:916188eae2bb 349
Donatien Garnier 1:916188eae2bb 350 /* Request a change in link security. This will be done
Donatien Garnier 1:916188eae2bb 351 * indirectly by asking the master of the connection to
Donatien Garnier 1:916188eae2bb 352 * change it. Depending on circumstances different actions
Donatien Garnier 1:916188eae2bb 353 * may be taken by the master which will trigger events
Donatien Garnier 1:916188eae2bb 354 * which the applications should deal with. */
Donatien Garnier 1:916188eae2bb 355 error = _ble.securityManager().setLinkSecurity(
Donatien Garnier 1:916188eae2bb 356 _handle,
Donatien Garnier 1:916188eae2bb 357 SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM
Donatien Garnier 1:916188eae2bb 358 );
Donatien Garnier 1:916188eae2bb 359
Donatien Garnier 1:916188eae2bb 360 if (error) {
Donatien Garnier 1:916188eae2bb 361 printf("Error during SM::setLinkSecurity %d\r\n", error);
Donatien Garnier 1:916188eae2bb 362 return;
Donatien Garnier 1:916188eae2bb 363 }
Donatien Garnier 1:916188eae2bb 364 };
Donatien Garnier 1:916188eae2bb 365 };
Donatien Garnier 1:916188eae2bb 366
Donatien Garnier 1:916188eae2bb 367 /** A central device will scan, connect to a peer and request pairing. */
Donatien Garnier 1:916188eae2bb 368 class SMDeviceCentral : public SMDevice {
Donatien Garnier 1:916188eae2bb 369 public:
Donatien Garnier 1:916188eae2bb 370 SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
Donatien Garnier 1:916188eae2bb 371 : SMDevice(ble, event_queue, peer_address) { }
Donatien Garnier 1:916188eae2bb 372
Donatien Garnier 1:916188eae2bb 373 virtual void start()
Donatien Garnier 1:916188eae2bb 374 {
Donatien Garnier 1:916188eae2bb 375 /* start scanning and attach a callback that will handle advertisements
Donatien Garnier 1:916188eae2bb 376 * and scan requests responses */
Donatien Garnier 1:916188eae2bb 377 ble_error_t error = _ble.gap().startScan(this, &SMDeviceCentral::on_scan);
Donatien Garnier 1:916188eae2bb 378
mbed_official 9:674ab70e0f36 379 printf("Please advertise\r\n");
mbed_official 9:674ab70e0f36 380
mbed_official 9:674ab70e0f36 381 printf("Scanning for: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
mbed_official 9:674ab70e0f36 382 _peer_address[5], _peer_address[4], _peer_address[3],
mbed_official 9:674ab70e0f36 383 _peer_address[2], _peer_address[1], _peer_address[0]);
mbed_official 9:674ab70e0f36 384
Donatien Garnier 1:916188eae2bb 385 if (error) {
Donatien Garnier 1:916188eae2bb 386 printf("Error during Gap::startScan %d\r\n", error);
Donatien Garnier 1:916188eae2bb 387 return;
Donatien Garnier 1:916188eae2bb 388 }
Donatien Garnier 1:916188eae2bb 389 }
Donatien Garnier 1:916188eae2bb 390
Donatien Garnier 1:916188eae2bb 391 /** Look at scan payload to find a peer device and connect to it */
Donatien Garnier 1:916188eae2bb 392 void on_scan(const Gap::AdvertisementCallbackParams_t *params)
Donatien Garnier 1:916188eae2bb 393 {
Donatien Garnier 1:916188eae2bb 394 /* don't bother with analysing scan result if we're already connecting */
Donatien Garnier 1:916188eae2bb 395 if (_is_connecting) {
Donatien Garnier 1:916188eae2bb 396 return;
Donatien Garnier 1:916188eae2bb 397 }
Donatien Garnier 1:916188eae2bb 398
mbed_official 9:674ab70e0f36 399 /* connect to the same device that connected to us */
mbed_official 9:674ab70e0f36 400 if (memcmp(params->peerAddr, _peer_address, sizeof(_peer_address)) == 0) {
Donatien Garnier 1:916188eae2bb 401
mbed_official 9:674ab70e0f36 402 ble_error_t error = _ble.gap().connect(
mbed_official 9:674ab70e0f36 403 params->peerAddr, params->peerAddrType,
mbed_official 9:674ab70e0f36 404 NULL, NULL
mbed_official 9:674ab70e0f36 405 );
Donatien Garnier 1:916188eae2bb 406
mbed_official 9:674ab70e0f36 407 if (error) {
mbed_official 9:674ab70e0f36 408 printf("Error during Gap::connect %d\r\n", error);
Donatien Garnier 1:916188eae2bb 409 return;
Donatien Garnier 1:916188eae2bb 410 }
Donatien Garnier 1:916188eae2bb 411
mbed_official 9:674ab70e0f36 412 printf("Connecting... ");
mbed_official 9:674ab70e0f36 413
mbed_official 9:674ab70e0f36 414 /* we may have already scan events waiting
mbed_official 9:674ab70e0f36 415 * to be processed so we need to remember
mbed_official 9:674ab70e0f36 416 * that we are already connecting and ignore them */
mbed_official 9:674ab70e0f36 417 _is_connecting = true;
mbed_official 9:674ab70e0f36 418
mbed_official 9:674ab70e0f36 419 return;
Donatien Garnier 1:916188eae2bb 420 }
Donatien Garnier 1:916188eae2bb 421 };
Donatien Garnier 1:916188eae2bb 422
Donatien Garnier 1:916188eae2bb 423 /** This is called by Gap to notify the application we connected,
Donatien Garnier 1:916188eae2bb 424 * in our case it immediately request pairing */
Donatien Garnier 1:916188eae2bb 425 virtual void on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
Donatien Garnier 1:916188eae2bb 426 {
Donatien Garnier 1:916188eae2bb 427 ble_error_t error;
Donatien Garnier 1:916188eae2bb 428
Donatien Garnier 1:916188eae2bb 429 /* store the handle for future Security Manager requests */
Donatien Garnier 1:916188eae2bb 430 _handle = connection_event->handle;
Donatien Garnier 1:916188eae2bb 431
Donatien Garnier 1:916188eae2bb 432 /* in this example the local device is the master so we request pairing */
Donatien Garnier 1:916188eae2bb 433 error = _ble.securityManager().requestPairing(_handle);
Donatien Garnier 1:916188eae2bb 434
mbed_official 9:674ab70e0f36 435 printf("Connected\r\n");
mbed_official 9:674ab70e0f36 436
Donatien Garnier 1:916188eae2bb 437 if (error) {
Donatien Garnier 1:916188eae2bb 438 printf("Error during SM::requestPairing %d\r\n", error);
Donatien Garnier 1:916188eae2bb 439 return;
Donatien Garnier 1:916188eae2bb 440 }
Donatien Garnier 1:916188eae2bb 441
Donatien Garnier 1:916188eae2bb 442 /* upon pairing success the application will disconnect */
Donatien Garnier 1:916188eae2bb 443 };
Donatien Garnier 1:916188eae2bb 444 };
Donatien Garnier 1:916188eae2bb 445
mbed_official 9:674ab70e0f36 446
mbed_official 9:674ab70e0f36 447 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 448 bool create_filesystem()
mbed_official 9:674ab70e0f36 449 {
mbed_official 9:674ab70e0f36 450 static LittleFileSystem fs("fs");
mbed_official 9:674ab70e0f36 451
mbed_official 9:674ab70e0f36 452 /* replace this with any physical block device your board supports (like an SD card) */
mbed_official 9:674ab70e0f36 453 static HeapBlockDevice bd(4096, 256);
mbed_official 9:674ab70e0f36 454
mbed_official 9:674ab70e0f36 455 int err = bd.init();
mbed_official 9:674ab70e0f36 456
mbed_official 9:674ab70e0f36 457 if (err) {
mbed_official 9:674ab70e0f36 458 return false;
mbed_official 9:674ab70e0f36 459 }
mbed_official 9:674ab70e0f36 460
mbed_official 9:674ab70e0f36 461 err = bd.erase(0, bd.size());
mbed_official 9:674ab70e0f36 462
mbed_official 9:674ab70e0f36 463 if (err) {
mbed_official 9:674ab70e0f36 464 return false;
mbed_official 9:674ab70e0f36 465 }
mbed_official 9:674ab70e0f36 466
mbed_official 9:674ab70e0f36 467 err = fs.mount(&bd);
mbed_official 9:674ab70e0f36 468
mbed_official 9:674ab70e0f36 469 if (err) {
mbed_official 9:674ab70e0f36 470 /* Reformat if we can't mount the filesystem */
mbed_official 9:674ab70e0f36 471 printf("No filesystem found, formatting...\r\n");
mbed_official 9:674ab70e0f36 472
mbed_official 9:674ab70e0f36 473 err = fs.reformat(&bd);
mbed_official 9:674ab70e0f36 474
mbed_official 9:674ab70e0f36 475 if (err) {
mbed_official 9:674ab70e0f36 476 return false;
mbed_official 9:674ab70e0f36 477 }
mbed_official 9:674ab70e0f36 478 }
mbed_official 9:674ab70e0f36 479
mbed_official 9:674ab70e0f36 480 return true;
mbed_official 9:674ab70e0f36 481 }
mbed_official 9:674ab70e0f36 482 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 483
Donatien Garnier 1:916188eae2bb 484 int main()
Donatien Garnier 1:916188eae2bb 485 {
Donatien Garnier 1:916188eae2bb 486 BLE& ble = BLE::Instance();
Donatien Garnier 1:916188eae2bb 487 events::EventQueue queue;
Donatien Garnier 1:916188eae2bb 488
mbed_official 9:674ab70e0f36 489 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
mbed_official 9:674ab70e0f36 490 /* if filesystem creation fails or there is no filesystem the security manager
mbed_official 9:674ab70e0f36 491 * will fallback to storing the security database in memory */
mbed_official 9:674ab70e0f36 492 if (!create_filesystem()) {
mbed_official 9:674ab70e0f36 493 printf("Filesystem creation failed, will use memory storage\r\n");
Donatien Garnier 1:916188eae2bb 494 }
mbed_official 9:674ab70e0f36 495 #endif
Donatien Garnier 1:916188eae2bb 496
mbed_official 9:674ab70e0f36 497 while(1) {
mbed_official 9:674ab70e0f36 498 {
mbed_official 9:674ab70e0f36 499 printf("\r\n PERIPHERAL \r\n\r\n");
mbed_official 9:674ab70e0f36 500 SMDevicePeripheral peripheral(ble, queue, peer_address);
mbed_official 9:674ab70e0f36 501 peripheral.run();
mbed_official 9:674ab70e0f36 502 }
mbed_official 9:674ab70e0f36 503
mbed_official 9:674ab70e0f36 504 {
mbed_official 9:674ab70e0f36 505 printf("\r\n CENTRAL \r\n\r\n");
mbed_official 9:674ab70e0f36 506 SMDeviceCentral central(ble, queue, peer_address);
mbed_official 9:674ab70e0f36 507 central.run();
mbed_official 9:674ab70e0f36 508 }
Donatien Garnier 1:916188eae2bb 509 }
Donatien Garnier 1:916188eae2bb 510
Donatien Garnier 1:916188eae2bb 511 return 0;
Donatien Garnier 1:916188eae2bb 512 }