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:
paulszczepanek
Date:
Thu Mar 08 18:08:23 2018 +0000
Revision:
0:fcb1e0b995a9
Child:
1:916188eae2bb
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
paulszczepanek 0:fcb1e0b995a9 1 /* mbed Microcontroller Library
paulszczepanek 0:fcb1e0b995a9 2 * Copyright (c) 2006-2013 ARM Limited
paulszczepanek 0:fcb1e0b995a9 3 *
paulszczepanek 0:fcb1e0b995a9 4 * Licensed under the Apache License, Version 2.0 (the "License");
paulszczepanek 0:fcb1e0b995a9 5 * you may not use this file except in compliance with the License.
paulszczepanek 0:fcb1e0b995a9 6 * You may obtain a copy of the License at
paulszczepanek 0:fcb1e0b995a9 7 *
paulszczepanek 0:fcb1e0b995a9 8 * http://www.apache.org/licenses/LICENSE-2.0
paulszczepanek 0:fcb1e0b995a9 9 *
paulszczepanek 0:fcb1e0b995a9 10 * Unless required by applicable law or agreed to in writing, software
paulszczepanek 0:fcb1e0b995a9 11 * distributed under the License is distributed on an "AS IS" BASIS,
paulszczepanek 0:fcb1e0b995a9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
paulszczepanek 0:fcb1e0b995a9 13 * See the License for the specific language governing permissions and
paulszczepanek 0:fcb1e0b995a9 14 * limitations under the License.
paulszczepanek 0:fcb1e0b995a9 15 */
paulszczepanek 0:fcb1e0b995a9 16
paulszczepanek 0:fcb1e0b995a9 17 #include <events/mbed_events.h>
paulszczepanek 0:fcb1e0b995a9 18 #include <mbed.h>
paulszczepanek 0:fcb1e0b995a9 19 #include "ble/BLE.h"
paulszczepanek 0:fcb1e0b995a9 20 #include "SecurityManager.h"
paulszczepanek 0:fcb1e0b995a9 21
paulszczepanek 0:fcb1e0b995a9 22 /** This example demonstrates all the basic setup required
paulszczepanek 0:fcb1e0b995a9 23 * for pairing and setting up link security both as a central and peripheral
paulszczepanek 0:fcb1e0b995a9 24 *
paulszczepanek 0:fcb1e0b995a9 25 * The example is implemented as two classes, one for the peripheral and one
paulszczepanek 0:fcb1e0b995a9 26 * for central inheriting from a common base. They are run in sequence and
paulszczepanek 0:fcb1e0b995a9 27 * require a peer device to connect to. During the peripheral device demonstration
paulszczepanek 0:fcb1e0b995a9 28 * a peer device is required to connect. In the central device demonstration
paulszczepanek 0:fcb1e0b995a9 29 * this peer device will be scanned for and connected to - therefore it should
paulszczepanek 0:fcb1e0b995a9 30 * be advertising with the same address as when it connected.
paulszczepanek 0:fcb1e0b995a9 31 *
paulszczepanek 0:fcb1e0b995a9 32 * During the test output is written on the serial connection to monitor its
paulszczepanek 0:fcb1e0b995a9 33 * progress.
paulszczepanek 0:fcb1e0b995a9 34 */
paulszczepanek 0:fcb1e0b995a9 35
paulszczepanek 0:fcb1e0b995a9 36 static const uint8_t DEVICE_NAME[] = "SM_device";
paulszczepanek 0:fcb1e0b995a9 37
paulszczepanek 0:fcb1e0b995a9 38 /* for demonstration purposes we will store the peer device address
paulszczepanek 0:fcb1e0b995a9 39 * of the device that connects to us in the first demonstration
paulszczepanek 0:fcb1e0b995a9 40 * so we can use its address to reconnect to it later */
paulszczepanek 0:fcb1e0b995a9 41 static BLEProtocol::AddressBytes_t peer_address;
paulszczepanek 0:fcb1e0b995a9 42
paulszczepanek 0:fcb1e0b995a9 43 /** Base class for both peripheral and central. The same class that provides
paulszczepanek 0:fcb1e0b995a9 44 * the logic for the application also implements the SecurityManagerEventHandler
paulszczepanek 0:fcb1e0b995a9 45 * which is the interface used by the Security Manager to communicate events
paulszczepanek 0:fcb1e0b995a9 46 * back to the applications. You can provide overrides for a selection of events
paulszczepanek 0:fcb1e0b995a9 47 * your application is interested in.
paulszczepanek 0:fcb1e0b995a9 48 */
paulszczepanek 0:fcb1e0b995a9 49 class SMDevice : private mbed::NonCopyable<SMDevice>,
paulszczepanek 0:fcb1e0b995a9 50 public SecurityManager::EventHandler
paulszczepanek 0:fcb1e0b995a9 51 {
paulszczepanek 0:fcb1e0b995a9 52 public:
paulszczepanek 0:fcb1e0b995a9 53 SMDevice(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) :
paulszczepanek 0:fcb1e0b995a9 54 _led1(LED1, 0),
paulszczepanek 0:fcb1e0b995a9 55 _ble(ble),
paulszczepanek 0:fcb1e0b995a9 56 _event_queue(event_queue),
paulszczepanek 0:fcb1e0b995a9 57 _peer_address(peer_address),
paulszczepanek 0:fcb1e0b995a9 58 _handle(0),
paulszczepanek 0:fcb1e0b995a9 59 _is_connecting(false) { };
paulszczepanek 0:fcb1e0b995a9 60
paulszczepanek 0:fcb1e0b995a9 61 virtual ~SMDevice()
paulszczepanek 0:fcb1e0b995a9 62 {
paulszczepanek 0:fcb1e0b995a9 63 if (_ble.hasInitialized()) {
paulszczepanek 0:fcb1e0b995a9 64 _ble.shutdown();
paulszczepanek 0:fcb1e0b995a9 65 }
paulszczepanek 0:fcb1e0b995a9 66 };
paulszczepanek 0:fcb1e0b995a9 67
paulszczepanek 0:fcb1e0b995a9 68 /** Start BLE interface initialisation */
paulszczepanek 0:fcb1e0b995a9 69 void run()
paulszczepanek 0:fcb1e0b995a9 70 {
paulszczepanek 0:fcb1e0b995a9 71 ble_error_t error;
paulszczepanek 0:fcb1e0b995a9 72
paulszczepanek 0:fcb1e0b995a9 73 /* to show we're running we'll blink every 500ms */
paulszczepanek 0:fcb1e0b995a9 74 _event_queue.call_every(500, this, &SMDevice::blink);
paulszczepanek 0:fcb1e0b995a9 75
paulszczepanek 0:fcb1e0b995a9 76 if (_ble.hasInitialized()) {
paulszczepanek 0:fcb1e0b995a9 77 printf("Ble instance already initialised.\r\n");
paulszczepanek 0:fcb1e0b995a9 78 return;
paulszczepanek 0:fcb1e0b995a9 79 }
paulszczepanek 0:fcb1e0b995a9 80
paulszczepanek 0:fcb1e0b995a9 81 /* this will inform us off all events so we can schedule their handling
paulszczepanek 0:fcb1e0b995a9 82 * using our event queue */
paulszczepanek 0:fcb1e0b995a9 83 _ble.onEventsToProcess(
paulszczepanek 0:fcb1e0b995a9 84 makeFunctionPointer(this, &SMDevice::schedule_ble_events)
paulszczepanek 0:fcb1e0b995a9 85 );
paulszczepanek 0:fcb1e0b995a9 86
paulszczepanek 0:fcb1e0b995a9 87 /* handle timeouts, for example when connection attempts fail */
paulszczepanek 0:fcb1e0b995a9 88 _ble.gap().onTimeout(
paulszczepanek 0:fcb1e0b995a9 89 makeFunctionPointer(this, &SMDevice::on_timeout)
paulszczepanek 0:fcb1e0b995a9 90 );
paulszczepanek 0:fcb1e0b995a9 91
paulszczepanek 0:fcb1e0b995a9 92 error = _ble.init(this, &SMDevice::on_init_complete);
paulszczepanek 0:fcb1e0b995a9 93
paulszczepanek 0:fcb1e0b995a9 94 if (error) {
paulszczepanek 0:fcb1e0b995a9 95 printf("Error returned by BLE::init.\r\n");
paulszczepanek 0:fcb1e0b995a9 96 return;
paulszczepanek 0:fcb1e0b995a9 97 }
paulszczepanek 0:fcb1e0b995a9 98
paulszczepanek 0:fcb1e0b995a9 99 /* this will not return until shutdown */
paulszczepanek 0:fcb1e0b995a9 100 _event_queue.dispatch_forever();
paulszczepanek 0:fcb1e0b995a9 101 };
paulszczepanek 0:fcb1e0b995a9 102
paulszczepanek 0:fcb1e0b995a9 103 /* event handler functions */
paulszczepanek 0:fcb1e0b995a9 104
paulszczepanek 0:fcb1e0b995a9 105 /** Respond to a pairing request. This will be called by the stack
paulszczepanek 0:fcb1e0b995a9 106 * when a pairing request arrives and expects the application to
paulszczepanek 0:fcb1e0b995a9 107 * call acceptPairingRequest or cancelPairingRequest */
paulszczepanek 0:fcb1e0b995a9 108 virtual void pairingRequest(
paulszczepanek 0:fcb1e0b995a9 109 ble::connection_handle_t connectionHandle
paulszczepanek 0:fcb1e0b995a9 110 ) {
paulszczepanek 0:fcb1e0b995a9 111 printf("Pairing requested. Authorising.\r\n");
paulszczepanek 0:fcb1e0b995a9 112 _ble.securityManager().acceptPairingRequest(connectionHandle);
paulszczepanek 0:fcb1e0b995a9 113 }
paulszczepanek 0:fcb1e0b995a9 114
paulszczepanek 0:fcb1e0b995a9 115 /** Inform the application of a successful pairing. Terminate the demonstration. */
paulszczepanek 0:fcb1e0b995a9 116 virtual void pairingResult(
paulszczepanek 0:fcb1e0b995a9 117 ble::connection_handle_t connectionHandle,
paulszczepanek 0:fcb1e0b995a9 118 SecurityManager::SecurityCompletionStatus_t result
paulszczepanek 0:fcb1e0b995a9 119 ) {
paulszczepanek 0:fcb1e0b995a9 120 if (result == SecurityManager::SEC_STATUS_SUCCESS) {
paulszczepanek 0:fcb1e0b995a9 121 printf("Pairing successful\r\n");
paulszczepanek 0:fcb1e0b995a9 122 } else {
paulszczepanek 0:fcb1e0b995a9 123 printf("Pairing failed\r\n");
paulszczepanek 0:fcb1e0b995a9 124 }
paulszczepanek 0:fcb1e0b995a9 125
paulszczepanek 0:fcb1e0b995a9 126 /* disconnect in 500 ms */
paulszczepanek 0:fcb1e0b995a9 127 _event_queue.call_in(
paulszczepanek 0:fcb1e0b995a9 128 500, &_ble.gap(),
paulszczepanek 0:fcb1e0b995a9 129 &Gap::disconnect, _handle, Gap::REMOTE_USER_TERMINATED_CONNECTION
paulszczepanek 0:fcb1e0b995a9 130 );
paulszczepanek 0:fcb1e0b995a9 131 }
paulszczepanek 0:fcb1e0b995a9 132
paulszczepanek 0:fcb1e0b995a9 133 /** Inform the application of change in encryption status. This will be
paulszczepanek 0:fcb1e0b995a9 134 * communicated through the serial port */
paulszczepanek 0:fcb1e0b995a9 135 virtual void linkEncryptionResult(
paulszczepanek 0:fcb1e0b995a9 136 ble::connection_handle_t connectionHandle,
paulszczepanek 0:fcb1e0b995a9 137 ble::link_encryption_t result
paulszczepanek 0:fcb1e0b995a9 138 ) {
paulszczepanek 0:fcb1e0b995a9 139 if (result == ble::link_encryption_t::ENCRYPTED) {
paulszczepanek 0:fcb1e0b995a9 140 printf("Link ENCRYPTED\r\n");
paulszczepanek 0:fcb1e0b995a9 141 } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) {
paulszczepanek 0:fcb1e0b995a9 142 printf("Link ENCRYPTED_WITH_MITM\r\n");
paulszczepanek 0:fcb1e0b995a9 143 } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) {
paulszczepanek 0:fcb1e0b995a9 144 printf("Link NOT_ENCRYPTED\r\n");
paulszczepanek 0:fcb1e0b995a9 145 }
paulszczepanek 0:fcb1e0b995a9 146 }
paulszczepanek 0:fcb1e0b995a9 147
paulszczepanek 0:fcb1e0b995a9 148 private:
paulszczepanek 0:fcb1e0b995a9 149 /** Override to start chosen activity when initialisation completes */
paulszczepanek 0:fcb1e0b995a9 150 virtual void start() = 0;
paulszczepanek 0:fcb1e0b995a9 151
paulszczepanek 0:fcb1e0b995a9 152 /** This is called when BLE interface is initialised and starts the demonstration */
paulszczepanek 0:fcb1e0b995a9 153 void on_init_complete(BLE::InitializationCompleteCallbackContext *event)
paulszczepanek 0:fcb1e0b995a9 154 {
paulszczepanek 0:fcb1e0b995a9 155 ble_error_t error;
paulszczepanek 0:fcb1e0b995a9 156
paulszczepanek 0:fcb1e0b995a9 157 if (event->error) {
paulszczepanek 0:fcb1e0b995a9 158 printf("Error during the initialisation\r\n");
paulszczepanek 0:fcb1e0b995a9 159 return;
paulszczepanek 0:fcb1e0b995a9 160 }
paulszczepanek 0:fcb1e0b995a9 161
paulszczepanek 0:fcb1e0b995a9 162 /* If the security manager is required this needs to be called before any
paulszczepanek 0:fcb1e0b995a9 163 * calls to the Security manager happen. */
paulszczepanek 0:fcb1e0b995a9 164 error = _ble.securityManager().init();
paulszczepanek 0:fcb1e0b995a9 165
paulszczepanek 0:fcb1e0b995a9 166 if (error) {
paulszczepanek 0:fcb1e0b995a9 167 printf("Error during init %d\r\n", error);
paulszczepanek 0:fcb1e0b995a9 168 return;
paulszczepanek 0:fcb1e0b995a9 169 }
paulszczepanek 0:fcb1e0b995a9 170
paulszczepanek 0:fcb1e0b995a9 171 /* Tell the security manager to use methods in this class to inform us
paulszczepanek 0:fcb1e0b995a9 172 * of any events. Class needs to implement SecurityManagerEventHandler. */
paulszczepanek 0:fcb1e0b995a9 173 _ble.securityManager().setSecurityManagerEventHandler(this);
paulszczepanek 0:fcb1e0b995a9 174
paulszczepanek 0:fcb1e0b995a9 175 /* print device address */
paulszczepanek 0:fcb1e0b995a9 176 Gap::AddressType_t addr_type;
paulszczepanek 0:fcb1e0b995a9 177 Gap::Address_t addr;
paulszczepanek 0:fcb1e0b995a9 178 _ble.gap().getAddress(&addr_type, addr);
paulszczepanek 0:fcb1e0b995a9 179 printf("Device address: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
paulszczepanek 0:fcb1e0b995a9 180 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
paulszczepanek 0:fcb1e0b995a9 181
paulszczepanek 0:fcb1e0b995a9 182 /* when scanning we want to connect to a peer device so we need to
paulszczepanek 0:fcb1e0b995a9 183 * attach callbacks that are used by Gap to notify us of events */
paulszczepanek 0:fcb1e0b995a9 184 _ble.gap().onConnection(this, &SMDevice::on_connect);
paulszczepanek 0:fcb1e0b995a9 185 _ble.gap().onDisconnection(this, &SMDevice::on_disconnect);
paulszczepanek 0:fcb1e0b995a9 186
paulszczepanek 0:fcb1e0b995a9 187 /* start test in 500 ms */
paulszczepanek 0:fcb1e0b995a9 188 _event_queue.call_in(500, this, &SMDevice::start);
paulszczepanek 0:fcb1e0b995a9 189 };
paulszczepanek 0:fcb1e0b995a9 190
paulszczepanek 0:fcb1e0b995a9 191 /** This is called by Gap to notify the application we connected */
paulszczepanek 0:fcb1e0b995a9 192 virtual void on_connect(const Gap::ConnectionCallbackParams_t *connection_event) = 0;
paulszczepanek 0:fcb1e0b995a9 193
paulszczepanek 0:fcb1e0b995a9 194 /** This is called by Gap to notify the application we disconnected,
paulszczepanek 0:fcb1e0b995a9 195 * in our case it ends the demonstration. */
paulszczepanek 0:fcb1e0b995a9 196 void on_disconnect(const Gap::DisconnectionCallbackParams_t *event)
paulszczepanek 0:fcb1e0b995a9 197 {
paulszczepanek 0:fcb1e0b995a9 198 printf("Disconnected - demonstration ended \r\n");
paulszczepanek 0:fcb1e0b995a9 199 _event_queue.break_dispatch();
paulszczepanek 0:fcb1e0b995a9 200 };
paulszczepanek 0:fcb1e0b995a9 201
paulszczepanek 0:fcb1e0b995a9 202 /** End demonstration unexpectedly. Called if timeout is reached during advertising,
paulszczepanek 0:fcb1e0b995a9 203 * scanning or connection initiation */
paulszczepanek 0:fcb1e0b995a9 204 void on_timeout(const Gap::TimeoutSource_t source)
paulszczepanek 0:fcb1e0b995a9 205 {
paulszczepanek 0:fcb1e0b995a9 206 printf("Unexpected timeout - aborting \r\n");
paulszczepanek 0:fcb1e0b995a9 207 _event_queue.break_dispatch();
paulszczepanek 0:fcb1e0b995a9 208 };
paulszczepanek 0:fcb1e0b995a9 209
paulszczepanek 0:fcb1e0b995a9 210 /** Schedule processing of events from the BLE in the event queue. */
paulszczepanek 0:fcb1e0b995a9 211 void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
paulszczepanek 0:fcb1e0b995a9 212 {
paulszczepanek 0:fcb1e0b995a9 213 _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
paulszczepanek 0:fcb1e0b995a9 214 };
paulszczepanek 0:fcb1e0b995a9 215
paulszczepanek 0:fcb1e0b995a9 216 /** Blink LED to show we're running */
paulszczepanek 0:fcb1e0b995a9 217 void blink(void)
paulszczepanek 0:fcb1e0b995a9 218 {
paulszczepanek 0:fcb1e0b995a9 219 _led1 = !_led1;
paulszczepanek 0:fcb1e0b995a9 220 };
paulszczepanek 0:fcb1e0b995a9 221
paulszczepanek 0:fcb1e0b995a9 222 private:
paulszczepanek 0:fcb1e0b995a9 223 DigitalOut _led1;
paulszczepanek 0:fcb1e0b995a9 224
paulszczepanek 0:fcb1e0b995a9 225 protected:
paulszczepanek 0:fcb1e0b995a9 226 BLE &_ble;
paulszczepanek 0:fcb1e0b995a9 227 events::EventQueue &_event_queue;
paulszczepanek 0:fcb1e0b995a9 228 BLEProtocol::AddressBytes_t &_peer_address;
paulszczepanek 0:fcb1e0b995a9 229 ble::connection_handle_t _handle;
paulszczepanek 0:fcb1e0b995a9 230 bool _is_connecting;
paulszczepanek 0:fcb1e0b995a9 231 };
paulszczepanek 0:fcb1e0b995a9 232
paulszczepanek 0:fcb1e0b995a9 233 /** A peripheral device will advertise, accept the connection and request
paulszczepanek 0:fcb1e0b995a9 234 * a change in link security. */
paulszczepanek 0:fcb1e0b995a9 235 class SMDevicePeripheral : public SMDevice {
paulszczepanek 0:fcb1e0b995a9 236 public:
paulszczepanek 0:fcb1e0b995a9 237 SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
paulszczepanek 0:fcb1e0b995a9 238 : SMDevice(ble, event_queue, peer_address) { }
paulszczepanek 0:fcb1e0b995a9 239
paulszczepanek 0:fcb1e0b995a9 240 virtual void start()
paulszczepanek 0:fcb1e0b995a9 241 {
paulszczepanek 0:fcb1e0b995a9 242 /* Set up and start advertising */
paulszczepanek 0:fcb1e0b995a9 243
paulszczepanek 0:fcb1e0b995a9 244 ble_error_t error;
paulszczepanek 0:fcb1e0b995a9 245 GapAdvertisingData advertising_data;
paulszczepanek 0:fcb1e0b995a9 246
paulszczepanek 0:fcb1e0b995a9 247 /* add advertising flags */
paulszczepanek 0:fcb1e0b995a9 248 advertising_data.addFlags(GapAdvertisingData::LE_GENERAL_DISCOVERABLE
paulszczepanek 0:fcb1e0b995a9 249 | GapAdvertisingData::BREDR_NOT_SUPPORTED);
paulszczepanek 0:fcb1e0b995a9 250
paulszczepanek 0:fcb1e0b995a9 251 /* add device name */
paulszczepanek 0:fcb1e0b995a9 252 advertising_data.addData(
paulszczepanek 0:fcb1e0b995a9 253 GapAdvertisingData::COMPLETE_LOCAL_NAME,
paulszczepanek 0:fcb1e0b995a9 254 DEVICE_NAME,
paulszczepanek 0:fcb1e0b995a9 255 sizeof(DEVICE_NAME)
paulszczepanek 0:fcb1e0b995a9 256 );
paulszczepanek 0:fcb1e0b995a9 257
paulszczepanek 0:fcb1e0b995a9 258 error = _ble.gap().setAdvertisingPayload(advertising_data);
paulszczepanek 0:fcb1e0b995a9 259
paulszczepanek 0:fcb1e0b995a9 260 if (error) {
paulszczepanek 0:fcb1e0b995a9 261 printf("Error during Gap::setAdvertisingPayload\r\n");
paulszczepanek 0:fcb1e0b995a9 262 return;
paulszczepanek 0:fcb1e0b995a9 263 }
paulszczepanek 0:fcb1e0b995a9 264
paulszczepanek 0:fcb1e0b995a9 265 /* advertise to everyone */
paulszczepanek 0:fcb1e0b995a9 266 _ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
paulszczepanek 0:fcb1e0b995a9 267 /* how many milliseconds between advertisements, lower interval
paulszczepanek 0:fcb1e0b995a9 268 * increases the chances of being seen at the cost of more power */
paulszczepanek 0:fcb1e0b995a9 269 _ble.gap().setAdvertisingInterval(20);
paulszczepanek 0:fcb1e0b995a9 270 _ble.gap().setAdvertisingTimeout(0);
paulszczepanek 0:fcb1e0b995a9 271
paulszczepanek 0:fcb1e0b995a9 272 error = _ble.gap().startAdvertising();
paulszczepanek 0:fcb1e0b995a9 273
paulszczepanek 0:fcb1e0b995a9 274 if (error) {
paulszczepanek 0:fcb1e0b995a9 275 printf("Error during Gap::startAdvertising.\r\n");
paulszczepanek 0:fcb1e0b995a9 276 return;
paulszczepanek 0:fcb1e0b995a9 277 }
paulszczepanek 0:fcb1e0b995a9 278
paulszczepanek 0:fcb1e0b995a9 279 /** This tells the stack to generate a pairingRequest event
paulszczepanek 0:fcb1e0b995a9 280 * which will require this application to respond before pairing
paulszczepanek 0:fcb1e0b995a9 281 * can proceed. Setting it to false will automatically accept
paulszczepanek 0:fcb1e0b995a9 282 * pairing. */
paulszczepanek 0:fcb1e0b995a9 283 _ble.securityManager().setPairingRequestAuthorisation(true);
paulszczepanek 0:fcb1e0b995a9 284 };
paulszczepanek 0:fcb1e0b995a9 285
paulszczepanek 0:fcb1e0b995a9 286 /** This is called by Gap to notify the application we connected,
paulszczepanek 0:fcb1e0b995a9 287 * in our case it immediately requests a change in link security */
paulszczepanek 0:fcb1e0b995a9 288 virtual void on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
paulszczepanek 0:fcb1e0b995a9 289 {
paulszczepanek 0:fcb1e0b995a9 290 ble_error_t error;
paulszczepanek 0:fcb1e0b995a9 291
paulszczepanek 0:fcb1e0b995a9 292 /* remember the device that connects to us now so we can connect to it
paulszczepanek 0:fcb1e0b995a9 293 * during the next demonstration */
paulszczepanek 0:fcb1e0b995a9 294 memcpy(_peer_address, connection_event->peerAddr, sizeof(_peer_address));
paulszczepanek 0:fcb1e0b995a9 295
paulszczepanek 0:fcb1e0b995a9 296 /* store the handle for future Security Manager requests */
paulszczepanek 0:fcb1e0b995a9 297 _handle = connection_event->handle;
paulszczepanek 0:fcb1e0b995a9 298
paulszczepanek 0:fcb1e0b995a9 299 /* Request a change in link security. This will be done
paulszczepanek 0:fcb1e0b995a9 300 * indirectly by asking the master of the connection to
paulszczepanek 0:fcb1e0b995a9 301 * change it. Depending on circumstances different actions
paulszczepanek 0:fcb1e0b995a9 302 * may be taken by the master which will trigger events
paulszczepanek 0:fcb1e0b995a9 303 * which the applications should deal with. */
paulszczepanek 0:fcb1e0b995a9 304 error = _ble.securityManager().setLinkSecurity(
paulszczepanek 0:fcb1e0b995a9 305 _handle,
paulszczepanek 0:fcb1e0b995a9 306 SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM
paulszczepanek 0:fcb1e0b995a9 307 );
paulszczepanek 0:fcb1e0b995a9 308
paulszczepanek 0:fcb1e0b995a9 309 if (error) {
paulszczepanek 0:fcb1e0b995a9 310 printf("Error during SM::setLinkSecurity %d\r\n", error);
paulszczepanek 0:fcb1e0b995a9 311 return;
paulszczepanek 0:fcb1e0b995a9 312 }
paulszczepanek 0:fcb1e0b995a9 313 };
paulszczepanek 0:fcb1e0b995a9 314 };
paulszczepanek 0:fcb1e0b995a9 315
paulszczepanek 0:fcb1e0b995a9 316 /** A central device will scan, connect to a peer and request pairing. */
paulszczepanek 0:fcb1e0b995a9 317 class SMDeviceCentral : public SMDevice {
paulszczepanek 0:fcb1e0b995a9 318 public:
paulszczepanek 0:fcb1e0b995a9 319 SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
paulszczepanek 0:fcb1e0b995a9 320 : SMDevice(ble, event_queue, peer_address) { }
paulszczepanek 0:fcb1e0b995a9 321
paulszczepanek 0:fcb1e0b995a9 322 virtual void start()
paulszczepanek 0:fcb1e0b995a9 323 {
paulszczepanek 0:fcb1e0b995a9 324 /* start scanning and attach a callback that will handle advertisements
paulszczepanek 0:fcb1e0b995a9 325 * and scan requests responses */
paulszczepanek 0:fcb1e0b995a9 326 ble_error_t error = _ble.gap().startScan(this, &SMDeviceCentral::on_scan);
paulszczepanek 0:fcb1e0b995a9 327
paulszczepanek 0:fcb1e0b995a9 328 if (error) {
paulszczepanek 0:fcb1e0b995a9 329 printf("Error during Gap::startScan %d\r\n", error);
paulszczepanek 0:fcb1e0b995a9 330 return;
paulszczepanek 0:fcb1e0b995a9 331 }
paulszczepanek 0:fcb1e0b995a9 332 }
paulszczepanek 0:fcb1e0b995a9 333
paulszczepanek 0:fcb1e0b995a9 334 /** Look at scan payload to find a peer device and connect to it */
paulszczepanek 0:fcb1e0b995a9 335 void on_scan(const Gap::AdvertisementCallbackParams_t *params)
paulszczepanek 0:fcb1e0b995a9 336 {
paulszczepanek 0:fcb1e0b995a9 337 /* don't bother with analysing scan result if we're already connecting */
paulszczepanek 0:fcb1e0b995a9 338 if (_is_connecting) {
paulszczepanek 0:fcb1e0b995a9 339 return;
paulszczepanek 0:fcb1e0b995a9 340 }
paulszczepanek 0:fcb1e0b995a9 341
paulszczepanek 0:fcb1e0b995a9 342 /* parse the advertising payload, looking for a discoverable device */
paulszczepanek 0:fcb1e0b995a9 343 for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
paulszczepanek 0:fcb1e0b995a9 344 /* The advertising payload is a collection of key/value records where
paulszczepanek 0:fcb1e0b995a9 345 * byte 0: length of the record excluding this byte
paulszczepanek 0:fcb1e0b995a9 346 * byte 1: The key, it is the type of the data
paulszczepanek 0:fcb1e0b995a9 347 * byte [2..N] The value. N is equal to byte0 - 1 */
paulszczepanek 0:fcb1e0b995a9 348 const uint8_t record_length = params->advertisingData[i];
paulszczepanek 0:fcb1e0b995a9 349 if (record_length == 0) {
paulszczepanek 0:fcb1e0b995a9 350 continue;
paulszczepanek 0:fcb1e0b995a9 351 }
paulszczepanek 0:fcb1e0b995a9 352
paulszczepanek 0:fcb1e0b995a9 353 /* connect to the same device that connected to us */
paulszczepanek 0:fcb1e0b995a9 354 if (memcmp(params->peerAddr, _peer_address, sizeof(_peer_address)) == 0) {
paulszczepanek 0:fcb1e0b995a9 355
paulszczepanek 0:fcb1e0b995a9 356 ble_error_t error = _ble.gap().connect(
paulszczepanek 0:fcb1e0b995a9 357 params->peerAddr, params->addressType,
paulszczepanek 0:fcb1e0b995a9 358 NULL, NULL
paulszczepanek 0:fcb1e0b995a9 359 );
paulszczepanek 0:fcb1e0b995a9 360
paulszczepanek 0:fcb1e0b995a9 361 if (error) {
paulszczepanek 0:fcb1e0b995a9 362 printf("Error during Gap::connect %d\r\n", error);
paulszczepanek 0:fcb1e0b995a9 363 return;
paulszczepanek 0:fcb1e0b995a9 364 }
paulszczepanek 0:fcb1e0b995a9 365
paulszczepanek 0:fcb1e0b995a9 366 /* we may have already scan events waiting
paulszczepanek 0:fcb1e0b995a9 367 * to be processed so we need to remember
paulszczepanek 0:fcb1e0b995a9 368 * that we are already connecting and ignore them */
paulszczepanek 0:fcb1e0b995a9 369 _is_connecting = true;
paulszczepanek 0:fcb1e0b995a9 370
paulszczepanek 0:fcb1e0b995a9 371 return;
paulszczepanek 0:fcb1e0b995a9 372 }
paulszczepanek 0:fcb1e0b995a9 373
paulszczepanek 0:fcb1e0b995a9 374 i += record_length;
paulszczepanek 0:fcb1e0b995a9 375 }
paulszczepanek 0:fcb1e0b995a9 376 };
paulszczepanek 0:fcb1e0b995a9 377
paulszczepanek 0:fcb1e0b995a9 378 /** This is called by Gap to notify the application we connected,
paulszczepanek 0:fcb1e0b995a9 379 * in our case it immediately request pairing */
paulszczepanek 0:fcb1e0b995a9 380 virtual void on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
paulszczepanek 0:fcb1e0b995a9 381 {
paulszczepanek 0:fcb1e0b995a9 382 ble_error_t error;
paulszczepanek 0:fcb1e0b995a9 383
paulszczepanek 0:fcb1e0b995a9 384 /* store the handle for future Security Manager requests */
paulszczepanek 0:fcb1e0b995a9 385 _handle = connection_event->handle;
paulszczepanek 0:fcb1e0b995a9 386
paulszczepanek 0:fcb1e0b995a9 387 /* in this example the local device is the master so we request pairing */
paulszczepanek 0:fcb1e0b995a9 388 error = _ble.securityManager().requestPairing(_handle);
paulszczepanek 0:fcb1e0b995a9 389
paulszczepanek 0:fcb1e0b995a9 390 if (error) {
paulszczepanek 0:fcb1e0b995a9 391 printf("Error during SM::requestPairing %d\r\n", error);
paulszczepanek 0:fcb1e0b995a9 392 return;
paulszczepanek 0:fcb1e0b995a9 393 }
paulszczepanek 0:fcb1e0b995a9 394
paulszczepanek 0:fcb1e0b995a9 395 /* upon pairing success the application will disconnect */
paulszczepanek 0:fcb1e0b995a9 396 };
paulszczepanek 0:fcb1e0b995a9 397 };
paulszczepanek 0:fcb1e0b995a9 398
paulszczepanek 0:fcb1e0b995a9 399 int main()
paulszczepanek 0:fcb1e0b995a9 400 {
paulszczepanek 0:fcb1e0b995a9 401 BLE& ble = BLE::Instance();
paulszczepanek 0:fcb1e0b995a9 402 events::EventQueue queue;
paulszczepanek 0:fcb1e0b995a9 403
paulszczepanek 0:fcb1e0b995a9 404 {
paulszczepanek 0:fcb1e0b995a9 405 printf("\r\n PERIPHERAL \r\n\r\n");
paulszczepanek 0:fcb1e0b995a9 406 SMDevicePeripheral peripheral(ble, queue, peer_address);
paulszczepanek 0:fcb1e0b995a9 407 peripheral.run();
paulszczepanek 0:fcb1e0b995a9 408 }
paulszczepanek 0:fcb1e0b995a9 409
paulszczepanek 0:fcb1e0b995a9 410 {
paulszczepanek 0:fcb1e0b995a9 411 printf("\r\n CENTRAL \r\n\r\n");
paulszczepanek 0:fcb1e0b995a9 412 SMDeviceCentral central(ble, queue, peer_address);
paulszczepanek 0:fcb1e0b995a9 413 central.run();
paulszczepanek 0:fcb1e0b995a9 414 }
paulszczepanek 0:fcb1e0b995a9 415
paulszczepanek 0:fcb1e0b995a9 416 return 0;
paulszczepanek 0:fcb1e0b995a9 417 }