test

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 }