test

Committer:
Donatien Garnier
Date:
Fri Jun 01 13:54:04 2018 -0500
Revision:
1:916188eae2bb
Parent:
0:fcb1e0b995a9
Child:
9:674ab70e0f36
Update ST support status

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