this is using the mbed os version 5-13-1

Dependencies:   mbed-http

Committer:
ocomeni
Date:
Thu Mar 14 21:34:06 2019 +0000
Revision:
75:08eff6258e1b
Parent:
74:f26e846adfe9
Child:
76:6afda865fbf8
Ble Security example now working!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ocomeni 74:f26e846adfe9 1 /* mbed Microcontroller Library
ocomeni 74:f26e846adfe9 2 * Copyright (c) 2006-2013 ARM Limited
ocomeni 74:f26e846adfe9 3 *
ocomeni 74:f26e846adfe9 4 * Licensed under the Apache License, Version 2.0 (the "License");
ocomeni 74:f26e846adfe9 5 * you may not use this file except in compliance with the License.
ocomeni 74:f26e846adfe9 6 * You may obtain a copy of the License at
ocomeni 74:f26e846adfe9 7 *
ocomeni 74:f26e846adfe9 8 * http://www.apache.org/licenses/LICENSE-2.0
ocomeni 74:f26e846adfe9 9 *
ocomeni 74:f26e846adfe9 10 * Unless required by applicable law or agreed to in writing, software
ocomeni 74:f26e846adfe9 11 * distributed under the License is distributed on an "AS IS" BASIS,
ocomeni 74:f26e846adfe9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ocomeni 74:f26e846adfe9 13 * See the License for the specific language governing permissions and
ocomeni 74:f26e846adfe9 14 * limitations under the License.
ocomeni 74:f26e846adfe9 15 */
ocomeni 75:08eff6258e1b 16
ocomeni 74:f26e846adfe9 17 #include <events/mbed_events.h>
ocomeni 74:f26e846adfe9 18 #include <mbed.h>
ocomeni 74:f26e846adfe9 19 #include "ble/BLE.h"
ocomeni 74:f26e846adfe9 20 #include "SecurityManager.h"
ocomeni 75:08eff6258e1b 21 #include "BleManager.h"
ocomeni 75:08eff6258e1b 22 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 23 #include "LittleFileSystem.h"
ocomeni 75:08eff6258e1b 24 #include "HeapBlockDevice.h"
ocomeni 75:08eff6258e1b 25 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 26
ocomeni 75:08eff6258e1b 27
ocomeni 75:08eff6258e1b 28 static const uint8_t DEVICE_NAME[] = "SM_device";
ocomeni 75:08eff6258e1b 29
ocomeni 75:08eff6258e1b 30 /** This example demonstrates all the basic setup required
ocomeni 75:08eff6258e1b 31 * for pairing and setting up link security both as a central and peripheral
ocomeni 75:08eff6258e1b 32 *
ocomeni 75:08eff6258e1b 33 * The example is implemented as two classes, one for the peripheral and one
ocomeni 75:08eff6258e1b 34 * for central inheriting from a common base. They are run in sequence and
ocomeni 75:08eff6258e1b 35 * require a peer device to connect to. During the peripheral device demonstration
ocomeni 75:08eff6258e1b 36 * a peer device is required to connect. In the central device demonstration
ocomeni 75:08eff6258e1b 37 * this peer device will be scanned for and connected to - therefore it should
ocomeni 75:08eff6258e1b 38 * be advertising with the same address as when it connected.
ocomeni 75:08eff6258e1b 39 *
ocomeni 75:08eff6258e1b 40 * During the test output is written on the serial connection to monitor its
ocomeni 75:08eff6258e1b 41 * progress.
ocomeni 75:08eff6258e1b 42 */
ocomeni 75:08eff6258e1b 43
ocomeni 75:08eff6258e1b 44 //static const uint8_t DEVICE_NAME[] = "SM_device";
ocomeni 75:08eff6258e1b 45
ocomeni 75:08eff6258e1b 46 /* for demonstration purposes we will store the peer device address
ocomeni 75:08eff6258e1b 47 * of the device that connects to us in the first demonstration
ocomeni 75:08eff6258e1b 48 * so we can use its address to reconnect to it later */
ocomeni 75:08eff6258e1b 49 //static BLEProtocol::AddressBytes_t peer_address;
ocomeni 75:08eff6258e1b 50
ocomeni 75:08eff6258e1b 51 /** Base class for both peripheral and central. The same class that provides
ocomeni 75:08eff6258e1b 52 * the logic for the application also implements the SecurityManagerEventHandler
ocomeni 75:08eff6258e1b 53 * which is the interface used by the Security Manager to communicate events
ocomeni 75:08eff6258e1b 54 * back to the applications. You can provide overrides for a selection of events
ocomeni 75:08eff6258e1b 55 * your application is interested in.
ocomeni 75:08eff6258e1b 56 */
ocomeni 75:08eff6258e1b 57 SMDevice::SMDevice(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) :
ocomeni 75:08eff6258e1b 58 _led1(LED1, 0),
ocomeni 75:08eff6258e1b 59 _ble(ble),
ocomeni 75:08eff6258e1b 60 _event_queue(event_queue),
ocomeni 75:08eff6258e1b 61 _peer_address(peer_address),
ocomeni 75:08eff6258e1b 62 _handle(0),
ocomeni 75:08eff6258e1b 63 _is_connecting(false) { }
ocomeni 75:08eff6258e1b 64
ocomeni 75:08eff6258e1b 65 SMDevice::~SMDevice()
ocomeni 75:08eff6258e1b 66 {
ocomeni 75:08eff6258e1b 67 if (_ble.hasInitialized()) {
ocomeni 75:08eff6258e1b 68 _ble.shutdown();
ocomeni 75:08eff6258e1b 69 }
ocomeni 75:08eff6258e1b 70 }
ocomeni 75:08eff6258e1b 71
ocomeni 75:08eff6258e1b 72 /** Start BLE interface initialisation */
ocomeni 75:08eff6258e1b 73 void SMDevice::run()
ocomeni 75:08eff6258e1b 74 {
ocomeni 75:08eff6258e1b 75 ble_error_t error;
ocomeni 75:08eff6258e1b 76
ocomeni 75:08eff6258e1b 77 /* to show we're running we'll blink every 500ms */
ocomeni 75:08eff6258e1b 78 _event_queue.call_every(500, this, &SMDevice::blink);
ocomeni 75:08eff6258e1b 79
ocomeni 75:08eff6258e1b 80 if (_ble.hasInitialized()) {
ocomeni 75:08eff6258e1b 81 printf("Ble instance already initialised.\r\n");
ocomeni 75:08eff6258e1b 82 return;
ocomeni 75:08eff6258e1b 83 }
ocomeni 75:08eff6258e1b 84
ocomeni 75:08eff6258e1b 85 /* this will inform us off all events so we can schedule their handling
ocomeni 75:08eff6258e1b 86 * using our event queue */
ocomeni 75:08eff6258e1b 87 _ble.onEventsToProcess(
ocomeni 75:08eff6258e1b 88 makeFunctionPointer(this, &SMDevice::schedule_ble_events)
ocomeni 75:08eff6258e1b 89 );
ocomeni 75:08eff6258e1b 90
ocomeni 75:08eff6258e1b 91 /* handle timeouts, for example when connection attempts fail */
ocomeni 75:08eff6258e1b 92 _ble.gap().onTimeout(
ocomeni 75:08eff6258e1b 93 makeFunctionPointer(this, &SMDevice::on_timeout)
ocomeni 75:08eff6258e1b 94 );
ocomeni 75:08eff6258e1b 95
ocomeni 75:08eff6258e1b 96 error = _ble.init(this, &SMDevice::on_init_complete);
ocomeni 75:08eff6258e1b 97
ocomeni 75:08eff6258e1b 98 if (error) {
ocomeni 75:08eff6258e1b 99 printf("Error returned by BLE::init.\r\n");
ocomeni 75:08eff6258e1b 100 return;
ocomeni 75:08eff6258e1b 101 }
ocomeni 75:08eff6258e1b 102
ocomeni 75:08eff6258e1b 103 /* this will not return until shutdown */
ocomeni 75:08eff6258e1b 104 _event_queue.dispatch_forever();
ocomeni 75:08eff6258e1b 105 }
ocomeni 75:08eff6258e1b 106
ocomeni 75:08eff6258e1b 107 /* event handler functions */
ocomeni 75:08eff6258e1b 108
ocomeni 75:08eff6258e1b 109 /** Respond to a pairing request. This will be called by the stack
ocomeni 75:08eff6258e1b 110 * when a pairing request arrives and expects the application to
ocomeni 75:08eff6258e1b 111 * call acceptPairingRequest or cancelPairingRequest */
ocomeni 75:08eff6258e1b 112 void SMDevice::pairingRequest(
ocomeni 75:08eff6258e1b 113 ble::connection_handle_t connectionHandle
ocomeni 75:08eff6258e1b 114 ) {
ocomeni 75:08eff6258e1b 115 printf("Pairing requested - authorising\r\n");
ocomeni 75:08eff6258e1b 116 _ble.securityManager().acceptPairingRequest(connectionHandle);
ocomeni 75:08eff6258e1b 117 }
ocomeni 75:08eff6258e1b 118
ocomeni 75:08eff6258e1b 119 /** Inform the application of a successful pairing. Terminate the demonstration. */
ocomeni 75:08eff6258e1b 120 void SMDevice::pairingResult(
ocomeni 75:08eff6258e1b 121 ble::connection_handle_t connectionHandle,
ocomeni 75:08eff6258e1b 122 SecurityManager::SecurityCompletionStatus_t result
ocomeni 75:08eff6258e1b 123 ) {
ocomeni 75:08eff6258e1b 124 if (result == SecurityManager::SEC_STATUS_SUCCESS) {
ocomeni 75:08eff6258e1b 125 printf("Pairing successful\r\n");
ocomeni 75:08eff6258e1b 126 } else {
ocomeni 75:08eff6258e1b 127 printf("Pairing failed\r\n");
ocomeni 75:08eff6258e1b 128 }
ocomeni 75:08eff6258e1b 129 }
ocomeni 75:08eff6258e1b 130
ocomeni 75:08eff6258e1b 131 /** Inform the application of change in encryption status. This will be
ocomeni 75:08eff6258e1b 132 * communicated through the serial port */
ocomeni 75:08eff6258e1b 133 void SMDevice::linkEncryptionResult(
ocomeni 75:08eff6258e1b 134 ble::connection_handle_t connectionHandle,
ocomeni 75:08eff6258e1b 135 ble::link_encryption_t result
ocomeni 75:08eff6258e1b 136 ) {
ocomeni 75:08eff6258e1b 137 if (result == ble::link_encryption_t::ENCRYPTED) {
ocomeni 75:08eff6258e1b 138 printf("Link ENCRYPTED\r\n");
ocomeni 75:08eff6258e1b 139 } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) {
ocomeni 75:08eff6258e1b 140 printf("Link ENCRYPTED_WITH_MITM\r\n");
ocomeni 75:08eff6258e1b 141 } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) {
ocomeni 75:08eff6258e1b 142 printf("Link NOT_ENCRYPTED\r\n");
ocomeni 75:08eff6258e1b 143 }
ocomeni 75:08eff6258e1b 144
ocomeni 75:08eff6258e1b 145 /* disconnect in 2 s */
ocomeni 75:08eff6258e1b 146 _event_queue.call_in(
ocomeni 75:08eff6258e1b 147 2000, &_ble.gap(),
ocomeni 75:08eff6258e1b 148 &Gap::disconnect, _handle, Gap::REMOTE_USER_TERMINATED_CONNECTION
ocomeni 75:08eff6258e1b 149 );
ocomeni 75:08eff6258e1b 150 }
ocomeni 75:08eff6258e1b 151
ocomeni 75:08eff6258e1b 152 /** Override to start chosen activity when initialisation completes */
ocomeni 75:08eff6258e1b 153 //void SMDevice::start() = 0;
ocomeni 75:08eff6258e1b 154
ocomeni 75:08eff6258e1b 155 /** This is called when BLE interface is initialised and starts the demonstration */
ocomeni 75:08eff6258e1b 156 void SMDevice::on_init_complete(BLE::InitializationCompleteCallbackContext *event)
ocomeni 75:08eff6258e1b 157 {
ocomeni 75:08eff6258e1b 158 ble_error_t error;
ocomeni 75:08eff6258e1b 159
ocomeni 75:08eff6258e1b 160 if (event->error) {
ocomeni 75:08eff6258e1b 161 printf("Error during the initialisation\r\n");
ocomeni 75:08eff6258e1b 162 return;
ocomeni 75:08eff6258e1b 163 }
ocomeni 75:08eff6258e1b 164
ocomeni 75:08eff6258e1b 165 /* This path will be used to store bonding information but will fallback
ocomeni 75:08eff6258e1b 166 * to storing in memory if file access fails (for example due to lack of a filesystem) */
ocomeni 75:08eff6258e1b 167 const char* db_path = "/fs/bt_sec_db";
ocomeni 75:08eff6258e1b 168 /* If the security manager is required this needs to be called before any
ocomeni 75:08eff6258e1b 169 * calls to the Security manager happen. */
ocomeni 75:08eff6258e1b 170 error = _ble.securityManager().init(
ocomeni 75:08eff6258e1b 171 true,
ocomeni 75:08eff6258e1b 172 false,
ocomeni 75:08eff6258e1b 173 SecurityManager::IO_CAPS_NONE,
ocomeni 75:08eff6258e1b 174 NULL,
ocomeni 75:08eff6258e1b 175 false,
ocomeni 75:08eff6258e1b 176 db_path
ocomeni 75:08eff6258e1b 177 );
ocomeni 75:08eff6258e1b 178
ocomeni 75:08eff6258e1b 179 if (error) {
ocomeni 75:08eff6258e1b 180 printf("Error during init %d\r\n", error);
ocomeni 75:08eff6258e1b 181 return;
ocomeni 75:08eff6258e1b 182 }
ocomeni 75:08eff6258e1b 183
ocomeni 75:08eff6258e1b 184 error = _ble.securityManager().preserveBondingStateOnReset(true);
ocomeni 75:08eff6258e1b 185
ocomeni 75:08eff6258e1b 186 if (error) {
ocomeni 75:08eff6258e1b 187 printf("Error during preserveBondingStateOnReset %d\r\n", error);
ocomeni 75:08eff6258e1b 188 }
ocomeni 75:08eff6258e1b 189
ocomeni 75:08eff6258e1b 190 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 191 /* Enable privacy so we can find the keys */
ocomeni 75:08eff6258e1b 192 error = _ble.gap().enablePrivacy(true);
ocomeni 75:08eff6258e1b 193
ocomeni 75:08eff6258e1b 194 if (error) {
ocomeni 75:08eff6258e1b 195 printf("Error enabling privacy\r\n");
ocomeni 75:08eff6258e1b 196 }
ocomeni 75:08eff6258e1b 197
ocomeni 75:08eff6258e1b 198 Gap::PeripheralPrivacyConfiguration_t configuration_p = {
ocomeni 75:08eff6258e1b 199 /* use_non_resolvable_random_address */ false,
ocomeni 75:08eff6258e1b 200 Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS
ocomeni 75:08eff6258e1b 201 };
ocomeni 75:08eff6258e1b 202 _ble.gap().setPeripheralPrivacyConfiguration(&configuration_p);
ocomeni 75:08eff6258e1b 203
ocomeni 75:08eff6258e1b 204 Gap::CentralPrivacyConfiguration_t configuration_c = {
ocomeni 75:08eff6258e1b 205 /* use_non_resolvable_random_address */ false,
ocomeni 75:08eff6258e1b 206 Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD
ocomeni 75:08eff6258e1b 207 };
ocomeni 75:08eff6258e1b 208 _ble.gap().setCentralPrivacyConfiguration(&configuration_c);
ocomeni 75:08eff6258e1b 209
ocomeni 75:08eff6258e1b 210 /* this demo switches between being master and slave */
ocomeni 75:08eff6258e1b 211 _ble.securityManager().setHintFutureRoleReversal(true);
ocomeni 75:08eff6258e1b 212 #endif
ocomeni 75:08eff6258e1b 213
ocomeni 75:08eff6258e1b 214 /* Tell the security manager to use methods in this class to inform us
ocomeni 75:08eff6258e1b 215 * of any events. Class needs to implement SecurityManagerEventHandler. */
ocomeni 75:08eff6258e1b 216 _ble.securityManager().setSecurityManagerEventHandler(this);
ocomeni 75:08eff6258e1b 217
ocomeni 75:08eff6258e1b 218 /* print device address */
ocomeni 75:08eff6258e1b 219 Gap::AddressType_t addr_type;
ocomeni 75:08eff6258e1b 220 Gap::Address_t addr;
ocomeni 75:08eff6258e1b 221 _ble.gap().getAddress(&addr_type, addr);
ocomeni 75:08eff6258e1b 222 printf("Device address: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
ocomeni 75:08eff6258e1b 223 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
ocomeni 75:08eff6258e1b 224
ocomeni 75:08eff6258e1b 225 /* when scanning we want to connect to a peer device so we need to
ocomeni 75:08eff6258e1b 226 * attach callbacks that are used by Gap to notify us of events */
ocomeni 75:08eff6258e1b 227 _ble.gap().onConnection(this, &SMDevice::on_connect);
ocomeni 75:08eff6258e1b 228 _ble.gap().onDisconnection(this, &SMDevice::on_disconnect);
ocomeni 75:08eff6258e1b 229
ocomeni 75:08eff6258e1b 230 /* start test in 500 ms */
ocomeni 75:08eff6258e1b 231 _event_queue.call_in(500, this, &SMDevice::start);
ocomeni 75:08eff6258e1b 232 }
ocomeni 75:08eff6258e1b 233
ocomeni 75:08eff6258e1b 234 /** This is called by Gap to notify the application we connected */
ocomeni 75:08eff6258e1b 235 //void SMDevice::on_connect(const Gap::ConnectionCallbackParams_t *connection_event);
ocomeni 75:08eff6258e1b 236
ocomeni 75:08eff6258e1b 237 /** This is called by Gap to notify the application we disconnected,
ocomeni 75:08eff6258e1b 238 * in our case it ends the demonstration. */
ocomeni 75:08eff6258e1b 239 void SMDevice::on_disconnect(const Gap::DisconnectionCallbackParams_t *event)
ocomeni 75:08eff6258e1b 240 {
ocomeni 75:08eff6258e1b 241 printf("Disconnected\r\n");
ocomeni 75:08eff6258e1b 242 _event_queue.break_dispatch();
ocomeni 75:08eff6258e1b 243 }
ocomeni 75:08eff6258e1b 244
ocomeni 75:08eff6258e1b 245 /** End demonstration unexpectedly. Called if timeout is reached during advertising,
ocomeni 75:08eff6258e1b 246 * scanning or connection initiation */
ocomeni 75:08eff6258e1b 247 void SMDevice::on_timeout(const Gap::TimeoutSource_t source)
ocomeni 75:08eff6258e1b 248 {
ocomeni 75:08eff6258e1b 249 printf("Unexpected timeout - aborting\r\n");
ocomeni 75:08eff6258e1b 250 _event_queue.break_dispatch();
ocomeni 75:08eff6258e1b 251 }
ocomeni 75:08eff6258e1b 252
ocomeni 75:08eff6258e1b 253 /** Schedule processing of events from the BLE in the event queue. */
ocomeni 75:08eff6258e1b 254 void SMDevice::schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
ocomeni 75:08eff6258e1b 255 {
ocomeni 75:08eff6258e1b 256 _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
ocomeni 75:08eff6258e1b 257 };
ocomeni 75:08eff6258e1b 258
ocomeni 75:08eff6258e1b 259 /** Blink LED to show we're running */
ocomeni 75:08eff6258e1b 260 void SMDevice::blink(void)
ocomeni 75:08eff6258e1b 261 {
ocomeni 75:08eff6258e1b 262 _led1 = !_led1;
ocomeni 75:08eff6258e1b 263 }
ocomeni 75:08eff6258e1b 264
ocomeni 75:08eff6258e1b 265
ocomeni 75:08eff6258e1b 266 /** A peripheral device will advertise, accept the connection and request
ocomeni 75:08eff6258e1b 267 * a change in link security. */
ocomeni 75:08eff6258e1b 268 SMDevicePeripheral::SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
ocomeni 75:08eff6258e1b 269 : SMDevice(ble, event_queue, peer_address) { }
ocomeni 75:08eff6258e1b 270
ocomeni 75:08eff6258e1b 271 void SMDevicePeripheral::start()
ocomeni 75:08eff6258e1b 272 {
ocomeni 75:08eff6258e1b 273 /* Set up and start advertising */
ocomeni 75:08eff6258e1b 274
ocomeni 75:08eff6258e1b 275 ble_error_t error;
ocomeni 75:08eff6258e1b 276 GapAdvertisingData advertising_data;
ocomeni 75:08eff6258e1b 277
ocomeni 75:08eff6258e1b 278 /* add advertising flags */
ocomeni 75:08eff6258e1b 279 advertising_data.addFlags(GapAdvertisingData::LE_GENERAL_DISCOVERABLE
ocomeni 75:08eff6258e1b 280 | GapAdvertisingData::BREDR_NOT_SUPPORTED);
ocomeni 75:08eff6258e1b 281
ocomeni 75:08eff6258e1b 282 /* add device name */
ocomeni 75:08eff6258e1b 283 advertising_data.addData(
ocomeni 75:08eff6258e1b 284 GapAdvertisingData::COMPLETE_LOCAL_NAME,
ocomeni 75:08eff6258e1b 285 DEVICE_NAME,
ocomeni 75:08eff6258e1b 286 sizeof(DEVICE_NAME)
ocomeni 75:08eff6258e1b 287 );
ocomeni 75:08eff6258e1b 288
ocomeni 75:08eff6258e1b 289 error = _ble.gap().setAdvertisingPayload(advertising_data);
ocomeni 75:08eff6258e1b 290
ocomeni 75:08eff6258e1b 291 if (error) {
ocomeni 75:08eff6258e1b 292 printf("Error during Gap::setAdvertisingPayload\r\n");
ocomeni 75:08eff6258e1b 293 return;
ocomeni 75:08eff6258e1b 294 }
ocomeni 75:08eff6258e1b 295
ocomeni 75:08eff6258e1b 296 /* advertise to everyone */
ocomeni 75:08eff6258e1b 297 _ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ocomeni 75:08eff6258e1b 298 /* how many milliseconds between advertisements, lower interval
ocomeni 75:08eff6258e1b 299 * increases the chances of being seen at the cost of more power */
ocomeni 75:08eff6258e1b 300 _ble.gap().setAdvertisingInterval(20);
ocomeni 75:08eff6258e1b 301 _ble.gap().setAdvertisingTimeout(0);
ocomeni 75:08eff6258e1b 302
ocomeni 75:08eff6258e1b 303 error = _ble.gap().startAdvertising();
ocomeni 75:08eff6258e1b 304
ocomeni 75:08eff6258e1b 305 if (error) {
ocomeni 75:08eff6258e1b 306 printf("Error during Gap::startAdvertising.\r\n");
ocomeni 75:08eff6258e1b 307 return;
ocomeni 75:08eff6258e1b 308 }
ocomeni 75:08eff6258e1b 309
ocomeni 75:08eff6258e1b 310 printf("Please connect to device\r\n");
ocomeni 75:08eff6258e1b 311
ocomeni 75:08eff6258e1b 312 /** This tells the stack to generate a pairingRequest event
ocomeni 75:08eff6258e1b 313 * which will require this application to respond before pairing
ocomeni 75:08eff6258e1b 314 * can proceed. Setting it to false will automatically accept
ocomeni 75:08eff6258e1b 315 * pairing. */
ocomeni 75:08eff6258e1b 316 _ble.securityManager().setPairingRequestAuthorisation(true);
ocomeni 75:08eff6258e1b 317 }
ocomeni 75:08eff6258e1b 318
ocomeni 75:08eff6258e1b 319 /** This is called by Gap to notify the application we connected,
ocomeni 75:08eff6258e1b 320 * in our case it immediately requests a change in link security */
ocomeni 75:08eff6258e1b 321 void SMDevicePeripheral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
ocomeni 75:08eff6258e1b 322 {
ocomeni 75:08eff6258e1b 323 ble_error_t error;
ocomeni 75:08eff6258e1b 324
ocomeni 75:08eff6258e1b 325 /* remember the device that connects to us now so we can connect to it
ocomeni 75:08eff6258e1b 326 * during the next demonstration */
ocomeni 75:08eff6258e1b 327 memcpy(_peer_address, connection_event->peerAddr, sizeof(_peer_address));
ocomeni 75:08eff6258e1b 328
ocomeni 75:08eff6258e1b 329 printf("Connected to: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
ocomeni 75:08eff6258e1b 330 _peer_address[5], _peer_address[4], _peer_address[3],
ocomeni 75:08eff6258e1b 331 _peer_address[2], _peer_address[1], _peer_address[0]);
ocomeni 75:08eff6258e1b 332
ocomeni 75:08eff6258e1b 333 /* store the handle for future Security Manager requests */
ocomeni 75:08eff6258e1b 334 _handle = connection_event->handle;
ocomeni 75:08eff6258e1b 335
ocomeni 75:08eff6258e1b 336 /* Request a change in link security. This will be done
ocomeni 75:08eff6258e1b 337 * indirectly by asking the master of the connection to
ocomeni 75:08eff6258e1b 338 * change it. Depending on circumstances different actions
ocomeni 75:08eff6258e1b 339 * may be taken by the master which will trigger events
ocomeni 75:08eff6258e1b 340 * which the applications should deal with. */
ocomeni 75:08eff6258e1b 341 error = _ble.securityManager().setLinkSecurity(
ocomeni 75:08eff6258e1b 342 _handle,
ocomeni 75:08eff6258e1b 343 SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM
ocomeni 75:08eff6258e1b 344 );
ocomeni 75:08eff6258e1b 345
ocomeni 75:08eff6258e1b 346 if (error) {
ocomeni 75:08eff6258e1b 347 printf("Error during SM::setLinkSecurity %d\r\n", error);
ocomeni 75:08eff6258e1b 348 return;
ocomeni 75:08eff6258e1b 349 }
ocomeni 75:08eff6258e1b 350 }
ocomeni 75:08eff6258e1b 351
ocomeni 75:08eff6258e1b 352 /** A central device will scan, connect to a peer and request pairing. */
ocomeni 75:08eff6258e1b 353
ocomeni 75:08eff6258e1b 354 SMDeviceCentral::SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
ocomeni 75:08eff6258e1b 355 : SMDevice(ble, event_queue, peer_address) { };
ocomeni 75:08eff6258e1b 356
ocomeni 75:08eff6258e1b 357 void SMDeviceCentral::start()
ocomeni 75:08eff6258e1b 358 {
ocomeni 75:08eff6258e1b 359 /* start scanning and attach a callback that will handle advertisements
ocomeni 75:08eff6258e1b 360 * and scan requests responses */
ocomeni 75:08eff6258e1b 361 ble_error_t error = _ble.gap().startScan(this, &SMDeviceCentral::on_scan);
ocomeni 75:08eff6258e1b 362
ocomeni 75:08eff6258e1b 363 printf("Please advertise\r\n");
ocomeni 75:08eff6258e1b 364
ocomeni 75:08eff6258e1b 365 printf("Scanning for: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
ocomeni 75:08eff6258e1b 366 _peer_address[5], _peer_address[4], _peer_address[3],
ocomeni 75:08eff6258e1b 367 _peer_address[2], _peer_address[1], _peer_address[0]);
ocomeni 75:08eff6258e1b 368
ocomeni 75:08eff6258e1b 369 if (error) {
ocomeni 75:08eff6258e1b 370 printf("Error during Gap::startScan %d\r\n", error);
ocomeni 75:08eff6258e1b 371 return;
ocomeni 75:08eff6258e1b 372 }
ocomeni 75:08eff6258e1b 373 }
ocomeni 75:08eff6258e1b 374
ocomeni 75:08eff6258e1b 375 /** Look at scan payload to find a peer device and connect to it */
ocomeni 75:08eff6258e1b 376 void SMDeviceCentral::on_scan(const Gap::AdvertisementCallbackParams_t *params)
ocomeni 75:08eff6258e1b 377 {
ocomeni 75:08eff6258e1b 378 /* don't bother with analysing scan result if we're already connecting */
ocomeni 75:08eff6258e1b 379 if (_is_connecting) {
ocomeni 75:08eff6258e1b 380 return;
ocomeni 75:08eff6258e1b 381 }
ocomeni 75:08eff6258e1b 382
ocomeni 75:08eff6258e1b 383 /* connect to the same device that connected to us */
ocomeni 75:08eff6258e1b 384 if (memcmp(params->peerAddr, _peer_address, sizeof(_peer_address)) == 0) {
ocomeni 75:08eff6258e1b 385
ocomeni 75:08eff6258e1b 386 ble_error_t error = _ble.gap().connect(
ocomeni 75:08eff6258e1b 387 params->peerAddr, params->peerAddrType,
ocomeni 75:08eff6258e1b 388 NULL, NULL
ocomeni 75:08eff6258e1b 389 );
ocomeni 75:08eff6258e1b 390
ocomeni 75:08eff6258e1b 391 if (error) {
ocomeni 75:08eff6258e1b 392 printf("Error during Gap::connect %d\r\n", error);
ocomeni 75:08eff6258e1b 393 return;
ocomeni 75:08eff6258e1b 394 }
ocomeni 75:08eff6258e1b 395
ocomeni 75:08eff6258e1b 396 printf("Connecting... ");
ocomeni 75:08eff6258e1b 397
ocomeni 75:08eff6258e1b 398 /* we may have already scan events waiting
ocomeni 75:08eff6258e1b 399 * to be processed so we need to remember
ocomeni 75:08eff6258e1b 400 * that we are already connecting and ignore them */
ocomeni 75:08eff6258e1b 401 _is_connecting = true;
ocomeni 75:08eff6258e1b 402
ocomeni 75:08eff6258e1b 403 return;
ocomeni 75:08eff6258e1b 404 }
ocomeni 75:08eff6258e1b 405 }
ocomeni 75:08eff6258e1b 406
ocomeni 75:08eff6258e1b 407 /** This is called by Gap to notify the application we connected,
ocomeni 75:08eff6258e1b 408 * in our case it immediately request pairing */
ocomeni 75:08eff6258e1b 409 void SMDeviceCentral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
ocomeni 75:08eff6258e1b 410 {
ocomeni 75:08eff6258e1b 411 ble_error_t error;
ocomeni 75:08eff6258e1b 412
ocomeni 75:08eff6258e1b 413 /* store the handle for future Security Manager requests */
ocomeni 75:08eff6258e1b 414 _handle = connection_event->handle;
ocomeni 75:08eff6258e1b 415
ocomeni 75:08eff6258e1b 416 /* in this example the local device is the master so we request pairing */
ocomeni 75:08eff6258e1b 417 error = _ble.securityManager().requestPairing(_handle);
ocomeni 75:08eff6258e1b 418
ocomeni 75:08eff6258e1b 419 printf("Connected\r\n");
ocomeni 75:08eff6258e1b 420
ocomeni 75:08eff6258e1b 421 if (error) {
ocomeni 75:08eff6258e1b 422 printf("Error during SM::requestPairing %d\r\n", error);
ocomeni 75:08eff6258e1b 423 return;
ocomeni 75:08eff6258e1b 424 }
ocomeni 75:08eff6258e1b 425
ocomeni 75:08eff6258e1b 426 /* upon pairing success the application will disconnect */
ocomeni 75:08eff6258e1b 427 }
ocomeni 75:08eff6258e1b 428
ocomeni 75:08eff6258e1b 429
ocomeni 75:08eff6258e1b 430
ocomeni 75:08eff6258e1b 431 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 432 bool create_filesystem()
ocomeni 75:08eff6258e1b 433 {
ocomeni 75:08eff6258e1b 434 static LittleFileSystem fs("fs");
ocomeni 75:08eff6258e1b 435
ocomeni 75:08eff6258e1b 436 /* replace this with any physical block device your board supports (like an SD card) */
ocomeni 75:08eff6258e1b 437 static HeapBlockDevice bd(4096, 256);
ocomeni 75:08eff6258e1b 438
ocomeni 75:08eff6258e1b 439 int err = bd.init();
ocomeni 75:08eff6258e1b 440
ocomeni 75:08eff6258e1b 441 if (err) {
ocomeni 75:08eff6258e1b 442 return false;
ocomeni 75:08eff6258e1b 443 }
ocomeni 75:08eff6258e1b 444
ocomeni 75:08eff6258e1b 445 err = bd.erase(0, bd.size());
ocomeni 75:08eff6258e1b 446
ocomeni 75:08eff6258e1b 447 if (err) {
ocomeni 75:08eff6258e1b 448 return false;
ocomeni 75:08eff6258e1b 449 }
ocomeni 75:08eff6258e1b 450
ocomeni 75:08eff6258e1b 451 err = fs.mount(&bd);
ocomeni 75:08eff6258e1b 452
ocomeni 75:08eff6258e1b 453 if (err) {
ocomeni 75:08eff6258e1b 454 /* Reformat if we can't mount the filesystem */
ocomeni 75:08eff6258e1b 455 printf("No filesystem found, formatting...\r\n");
ocomeni 75:08eff6258e1b 456
ocomeni 75:08eff6258e1b 457 err = fs.reformat(&bd);
ocomeni 75:08eff6258e1b 458
ocomeni 75:08eff6258e1b 459 if (err) {
ocomeni 75:08eff6258e1b 460 return false;
ocomeni 75:08eff6258e1b 461 }
ocomeni 75:08eff6258e1b 462 }
ocomeni 75:08eff6258e1b 463
ocomeni 75:08eff6258e1b 464 return true;
ocomeni 75:08eff6258e1b 465 }
ocomeni 75:08eff6258e1b 466 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 467 #ifdef BLE_SECURITY_MAIN
ocomeni 75:08eff6258e1b 468 int main()
ocomeni 75:08eff6258e1b 469 {
ocomeni 75:08eff6258e1b 470 BLE& ble = BLE::Instance();
ocomeni 75:08eff6258e1b 471 events::EventQueue queue;
ocomeni 75:08eff6258e1b 472
ocomeni 75:08eff6258e1b 473 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 474 /* if filesystem creation fails or there is no filesystem the security manager
ocomeni 75:08eff6258e1b 475 * will fallback to storing the security database in memory */
ocomeni 75:08eff6258e1b 476 if (!create_filesystem()) {
ocomeni 75:08eff6258e1b 477 printf("Filesystem creation failed, will use memory storage\r\n");
ocomeni 75:08eff6258e1b 478 }
ocomeni 75:08eff6258e1b 479 #endif
ocomeni 75:08eff6258e1b 480
ocomeni 75:08eff6258e1b 481 while(1) {
ocomeni 75:08eff6258e1b 482 {
ocomeni 75:08eff6258e1b 483 printf("\r\n PERIPHERAL \r\n\r\n");
ocomeni 75:08eff6258e1b 484 SMDevicePeripheral peripheral(ble, queue, peer_address);
ocomeni 75:08eff6258e1b 485 peripheral.run();
ocomeni 75:08eff6258e1b 486 }
ocomeni 75:08eff6258e1b 487
ocomeni 75:08eff6258e1b 488 {
ocomeni 75:08eff6258e1b 489 printf("\r\n CENTRAL \r\n\r\n");
ocomeni 75:08eff6258e1b 490 SMDeviceCentral central(ble, queue, peer_address);
ocomeni 75:08eff6258e1b 491 central.run();
ocomeni 75:08eff6258e1b 492 }
ocomeni 75:08eff6258e1b 493 }
ocomeni 75:08eff6258e1b 494
ocomeni 75:08eff6258e1b 495 return 0;
ocomeni 75:08eff6258e1b 496 }
ocomeni 75:08eff6258e1b 497 #endif
ocomeni 75:08eff6258e1b 498
ocomeni 75:08eff6258e1b 499 #ifdef OLD_BLE_SECURITY
ocomeni 75:08eff6258e1b 500 /* mbed Microcontroller Library
ocomeni 75:08eff6258e1b 501 * Copyright (c) 2006-2013 ARM Limited
ocomeni 75:08eff6258e1b 502 *
ocomeni 75:08eff6258e1b 503 * Licensed under the Apache License, Version 2.0 (the "License");
ocomeni 75:08eff6258e1b 504 * you may not use this file except in compliance with the License.
ocomeni 75:08eff6258e1b 505 * You may obtain a copy of the License at
ocomeni 75:08eff6258e1b 506 *
ocomeni 75:08eff6258e1b 507 * http://www.apache.org/licenses/LICENSE-2.0
ocomeni 75:08eff6258e1b 508 *
ocomeni 75:08eff6258e1b 509 * Unless required by applicable law or agreed to in writing, software
ocomeni 75:08eff6258e1b 510 * distributed under the License is distributed on an "AS IS" BASIS,
ocomeni 75:08eff6258e1b 511 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ocomeni 75:08eff6258e1b 512 * See the License for the specific language governing permissions and
ocomeni 75:08eff6258e1b 513 * limitations under the License.
ocomeni 75:08eff6258e1b 514 */
ocomeni 75:08eff6258e1b 515 //#ifdef BLE_SECURITY_ENABLED
ocomeni 75:08eff6258e1b 516 #include <events/mbed_events.h>
ocomeni 75:08eff6258e1b 517 #include <mbed.h>
ocomeni 75:08eff6258e1b 518 #include "ble/BLE.h"
ocomeni 75:08eff6258e1b 519 #include "ble/Gap.h"
ocomeni 75:08eff6258e1b 520 #include "Types.h"
ocomeni 75:08eff6258e1b 521 #include "ble/services/UARTService.h"
ocomeni 75:08eff6258e1b 522
ocomeni 75:08eff6258e1b 523 //#include "ble/gap/Types.h"
ocomeni 75:08eff6258e1b 524 #include "SecurityManager.h"
ocomeni 74:f26e846adfe9 525 #include "pretty_printer.h"
ocomeni 74:f26e846adfe9 526
ocomeni 74:f26e846adfe9 527 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 74:f26e846adfe9 528 #include "LittleFileSystem.h"
ocomeni 74:f26e846adfe9 529 #include "HeapBlockDevice.h"
ocomeni 74:f26e846adfe9 530 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 74:f26e846adfe9 531
ocomeni 74:f26e846adfe9 532 /** This example demonstrates all the basic setup required
ocomeni 74:f26e846adfe9 533 * for pairing and setting up link security both as a central and peripheral
ocomeni 74:f26e846adfe9 534 *
ocomeni 74:f26e846adfe9 535 * The example is implemented as two classes, one for the peripheral and one
ocomeni 74:f26e846adfe9 536 * for central inheriting from a common base. They are run in sequence and
ocomeni 74:f26e846adfe9 537 * require a peer device to connect to. During the peripheral device demonstration
ocomeni 74:f26e846adfe9 538 * a peer device is required to connect. In the central device demonstration
ocomeni 74:f26e846adfe9 539 * this peer device will be scanned for and connected to - therefore it should
ocomeni 74:f26e846adfe9 540 * be advertising with the same address as when it connected.
ocomeni 74:f26e846adfe9 541 *
ocomeni 74:f26e846adfe9 542 * During the test output is written on the serial connection to monitor its
ocomeni 74:f26e846adfe9 543 * progress.
ocomeni 74:f26e846adfe9 544 */
ocomeni 74:f26e846adfe9 545
ocomeni 74:f26e846adfe9 546 static const char DEVICE_NAME[] = "SM_device";
ocomeni 74:f26e846adfe9 547
ocomeni 74:f26e846adfe9 548 /* we have to specify the disconnect call because of ambiguous overloads */
ocomeni 75:08eff6258e1b 549 //typedef ble_error_t (Gap::*disconnect_call_t)(ble::connection_handle_t, ble::local_disconnection_reason_t);
ocomeni 75:08eff6258e1b 550 //const static disconnect_call_t disconnect_call = &Gap::disconnect;
ocomeni 75:08eff6258e1b 551 //typedef ble_error_t (Gap::*disconnect_call_t)(ble::connection_handle_t, ble::local_disconnection_reason_t);
ocomeni 75:08eff6258e1b 552 //const static (Gap::*disconnect_call_t) disconnect_call = &Gap::disconnect;
ocomeni 74:f26e846adfe9 553
ocomeni 74:f26e846adfe9 554 /* for demonstration purposes we will store the peer device address
ocomeni 74:f26e846adfe9 555 * of the device that connects to us in the first demonstration
ocomeni 74:f26e846adfe9 556 * so we can use its address to reconnect to it later */
ocomeni 74:f26e846adfe9 557 static BLEProtocol::AddressBytes_t peer_address;
ocomeni 74:f26e846adfe9 558
ocomeni 74:f26e846adfe9 559 /** Base class for both peripheral and central. The same class that provides
ocomeni 74:f26e846adfe9 560 * the logic for the application also implements the SecurityManagerEventHandler
ocomeni 74:f26e846adfe9 561 * which is the interface used by the Security Manager to communicate events
ocomeni 74:f26e846adfe9 562 * back to the applications. You can provide overrides for a selection of events
ocomeni 74:f26e846adfe9 563 * your application is interested in.
ocomeni 74:f26e846adfe9 564 */
ocomeni 74:f26e846adfe9 565 class SMDevice : private mbed::NonCopyable<SMDevice>,
ocomeni 74:f26e846adfe9 566 public SecurityManager::EventHandler,
ocomeni 75:08eff6258e1b 567 public Gap::EventHandler
ocomeni 74:f26e846adfe9 568 {
ocomeni 74:f26e846adfe9 569 public:
ocomeni 74:f26e846adfe9 570 SMDevice(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address) :
ocomeni 74:f26e846adfe9 571 _led1(LED1, 0),
ocomeni 74:f26e846adfe9 572 _ble(ble),
ocomeni 74:f26e846adfe9 573 _event_queue(event_queue),
ocomeni 74:f26e846adfe9 574 _peer_address(peer_address),
ocomeni 74:f26e846adfe9 575 _handle(0),
ocomeni 74:f26e846adfe9 576 _is_connecting(false) { };
ocomeni 74:f26e846adfe9 577
ocomeni 74:f26e846adfe9 578 virtual ~SMDevice()
ocomeni 74:f26e846adfe9 579 {
ocomeni 74:f26e846adfe9 580 if (_ble.hasInitialized()) {
ocomeni 74:f26e846adfe9 581 _ble.shutdown();
ocomeni 74:f26e846adfe9 582 }
ocomeni 74:f26e846adfe9 583 };
ocomeni 74:f26e846adfe9 584
ocomeni 74:f26e846adfe9 585 /** Start BLE interface initialisation */
ocomeni 74:f26e846adfe9 586 void run()
ocomeni 74:f26e846adfe9 587 {
ocomeni 74:f26e846adfe9 588 ble_error_t error;
ocomeni 74:f26e846adfe9 589
ocomeni 74:f26e846adfe9 590 /* to show we're running we'll blink every 500ms */
ocomeni 74:f26e846adfe9 591 _event_queue.call_every(500, this, &SMDevice::blink);
ocomeni 74:f26e846adfe9 592
ocomeni 74:f26e846adfe9 593 if (_ble.hasInitialized()) {
ocomeni 74:f26e846adfe9 594 printf("Ble instance already initialised.\r\n");
ocomeni 74:f26e846adfe9 595 return;
ocomeni 74:f26e846adfe9 596 }
ocomeni 74:f26e846adfe9 597
ocomeni 74:f26e846adfe9 598 /* this will inform us off all events so we can schedule their handling
ocomeni 74:f26e846adfe9 599 * using our event queue */
ocomeni 74:f26e846adfe9 600 _ble.onEventsToProcess(
ocomeni 74:f26e846adfe9 601 makeFunctionPointer(this, &SMDevice::schedule_ble_events)
ocomeni 74:f26e846adfe9 602 );
ocomeni 74:f26e846adfe9 603
ocomeni 74:f26e846adfe9 604 /* handle gap events */
ocomeni 74:f26e846adfe9 605 _ble.gap().setEventHandler(this);
ocomeni 74:f26e846adfe9 606
ocomeni 74:f26e846adfe9 607 error = _ble.init(this, &SMDevice::on_init_complete);
ocomeni 74:f26e846adfe9 608
ocomeni 74:f26e846adfe9 609 if (error) {
ocomeni 74:f26e846adfe9 610 printf("Error returned by BLE::init.\r\n");
ocomeni 74:f26e846adfe9 611 return;
ocomeni 74:f26e846adfe9 612 }
ocomeni 74:f26e846adfe9 613
ocomeni 74:f26e846adfe9 614 /* this will not return until shutdown */
ocomeni 74:f26e846adfe9 615 _event_queue.dispatch_forever();
ocomeni 74:f26e846adfe9 616 };
ocomeni 74:f26e846adfe9 617
ocomeni 74:f26e846adfe9 618 private:
ocomeni 74:f26e846adfe9 619 /** Override to start chosen activity when initialisation completes */
ocomeni 74:f26e846adfe9 620 virtual void start() = 0;
ocomeni 74:f26e846adfe9 621
ocomeni 74:f26e846adfe9 622 /** This is called when BLE interface is initialised and starts the demonstration */
ocomeni 74:f26e846adfe9 623 void on_init_complete(BLE::InitializationCompleteCallbackContext *event)
ocomeni 74:f26e846adfe9 624 {
ocomeni 74:f26e846adfe9 625 ble_error_t error;
ocomeni 74:f26e846adfe9 626
ocomeni 74:f26e846adfe9 627 if (event->error) {
ocomeni 74:f26e846adfe9 628 printf("Error during the initialisation\r\n");
ocomeni 74:f26e846adfe9 629 return;
ocomeni 74:f26e846adfe9 630 }
ocomeni 74:f26e846adfe9 631
ocomeni 74:f26e846adfe9 632 /* This path will be used to store bonding information but will fallback
ocomeni 74:f26e846adfe9 633 * to storing in memory if file access fails (for example due to lack of a filesystem) */
ocomeni 74:f26e846adfe9 634 const char* db_path = "/fs/bt_sec_db";
ocomeni 74:f26e846adfe9 635 /* If the security manager is required this needs to be called before any
ocomeni 74:f26e846adfe9 636 * calls to the Security manager happen. */
ocomeni 74:f26e846adfe9 637 error = _ble.securityManager().init(
ocomeni 74:f26e846adfe9 638 true,
ocomeni 74:f26e846adfe9 639 false,
ocomeni 74:f26e846adfe9 640 SecurityManager::IO_CAPS_NONE,
ocomeni 74:f26e846adfe9 641 NULL,
ocomeni 74:f26e846adfe9 642 false,
ocomeni 74:f26e846adfe9 643 db_path
ocomeni 74:f26e846adfe9 644 );
ocomeni 74:f26e846adfe9 645
ocomeni 74:f26e846adfe9 646 if (error) {
ocomeni 74:f26e846adfe9 647 printf("Error during init %d\r\n", error);
ocomeni 74:f26e846adfe9 648 return;
ocomeni 74:f26e846adfe9 649 }
ocomeni 74:f26e846adfe9 650
ocomeni 74:f26e846adfe9 651 error = _ble.securityManager().preserveBondingStateOnReset(true);
ocomeni 74:f26e846adfe9 652
ocomeni 74:f26e846adfe9 653 if (error) {
ocomeni 74:f26e846adfe9 654 printf("Error during preserveBondingStateOnReset %d\r\n", error);
ocomeni 74:f26e846adfe9 655 }
ocomeni 74:f26e846adfe9 656
ocomeni 74:f26e846adfe9 657 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 74:f26e846adfe9 658 /* Enable privacy so we can find the keys */
ocomeni 74:f26e846adfe9 659 error = _ble.gap().enablePrivacy(true);
ocomeni 74:f26e846adfe9 660
ocomeni 74:f26e846adfe9 661 if (error) {
ocomeni 74:f26e846adfe9 662 printf("Error enabling privacy\r\n");
ocomeni 74:f26e846adfe9 663 }
ocomeni 74:f26e846adfe9 664
ocomeni 74:f26e846adfe9 665 Gap::PeripheralPrivacyConfiguration_t configuration_p = {
ocomeni 74:f26e846adfe9 666 /* use_non_resolvable_random_address */ false,
ocomeni 74:f26e846adfe9 667 Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS
ocomeni 74:f26e846adfe9 668 };
ocomeni 74:f26e846adfe9 669 _ble.gap().setPeripheralPrivacyConfiguration(&configuration_p);
ocomeni 74:f26e846adfe9 670
ocomeni 74:f26e846adfe9 671 Gap::CentralPrivacyConfiguration_t configuration_c = {
ocomeni 74:f26e846adfe9 672 /* use_non_resolvable_random_address */ false,
ocomeni 74:f26e846adfe9 673 Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD
ocomeni 74:f26e846adfe9 674 };
ocomeni 74:f26e846adfe9 675 _ble.gap().setCentralPrivacyConfiguration(&configuration_c);
ocomeni 74:f26e846adfe9 676
ocomeni 74:f26e846adfe9 677 /* this demo switches between being master and slave */
ocomeni 74:f26e846adfe9 678 _ble.securityManager().setHintFutureRoleReversal(true);
ocomeni 74:f26e846adfe9 679 #endif
ocomeni 74:f26e846adfe9 680
ocomeni 74:f26e846adfe9 681 /* Tell the security manager to use methods in this class to inform us
ocomeni 74:f26e846adfe9 682 * of any events. Class needs to implement SecurityManagerEventHandler. */
ocomeni 74:f26e846adfe9 683 _ble.securityManager().setSecurityManagerEventHandler(this);
ocomeni 74:f26e846adfe9 684
ocomeni 74:f26e846adfe9 685 /* gap events also handled by this class */
ocomeni 74:f26e846adfe9 686 _ble.gap().setEventHandler(this);
ocomeni 74:f26e846adfe9 687
ocomeni 74:f26e846adfe9 688 /* print device address */
ocomeni 74:f26e846adfe9 689 Gap::AddressType_t addr_type;
ocomeni 74:f26e846adfe9 690 Gap::Address_t addr;
ocomeni 74:f26e846adfe9 691 _ble.gap().getAddress(&addr_type, addr);
ocomeni 74:f26e846adfe9 692 print_address(addr);
ocomeni 74:f26e846adfe9 693
ocomeni 74:f26e846adfe9 694 /* start test in 500 ms */
ocomeni 74:f26e846adfe9 695 _event_queue.call_in(500, this, &SMDevice::start);
ocomeni 74:f26e846adfe9 696 };
ocomeni 74:f26e846adfe9 697
ocomeni 74:f26e846adfe9 698 /** Schedule processing of events from the BLE in the event queue. */
ocomeni 74:f26e846adfe9 699 void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
ocomeni 74:f26e846adfe9 700 {
ocomeni 74:f26e846adfe9 701 _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
ocomeni 74:f26e846adfe9 702 };
ocomeni 74:f26e846adfe9 703
ocomeni 74:f26e846adfe9 704 /** Blink LED to show we're running */
ocomeni 74:f26e846adfe9 705 void blink(void)
ocomeni 74:f26e846adfe9 706 {
ocomeni 74:f26e846adfe9 707 _led1 = !_led1;
ocomeni 74:f26e846adfe9 708 };
ocomeni 74:f26e846adfe9 709
ocomeni 74:f26e846adfe9 710 private:
ocomeni 74:f26e846adfe9 711 /* Event handler */
ocomeni 74:f26e846adfe9 712
ocomeni 74:f26e846adfe9 713 /** Respond to a pairing request. This will be called by the stack
ocomeni 74:f26e846adfe9 714 * when a pairing request arrives and expects the application to
ocomeni 74:f26e846adfe9 715 * call acceptPairingRequest or cancelPairingRequest */
ocomeni 74:f26e846adfe9 716 virtual void pairingRequest(
ocomeni 74:f26e846adfe9 717 ble::connection_handle_t connectionHandle
ocomeni 74:f26e846adfe9 718 ) {
ocomeni 74:f26e846adfe9 719 printf("Pairing requested - authorising\r\n");
ocomeni 74:f26e846adfe9 720 _ble.securityManager().acceptPairingRequest(connectionHandle);
ocomeni 74:f26e846adfe9 721 }
ocomeni 74:f26e846adfe9 722
ocomeni 74:f26e846adfe9 723 /** Inform the application of a successful pairing. Terminate the demonstration. */
ocomeni 74:f26e846adfe9 724 virtual void pairingResult(
ocomeni 74:f26e846adfe9 725 ble::connection_handle_t connectionHandle,
ocomeni 74:f26e846adfe9 726 SecurityManager::SecurityCompletionStatus_t result
ocomeni 74:f26e846adfe9 727 ) {
ocomeni 74:f26e846adfe9 728 if (result == SecurityManager::SEC_STATUS_SUCCESS) {
ocomeni 74:f26e846adfe9 729 printf("Pairing successful\r\n");
ocomeni 74:f26e846adfe9 730 } else {
ocomeni 74:f26e846adfe9 731 printf("Pairing failed\r\n");
ocomeni 74:f26e846adfe9 732 }
ocomeni 74:f26e846adfe9 733 }
ocomeni 74:f26e846adfe9 734
ocomeni 74:f26e846adfe9 735 /** Inform the application of change in encryption status. This will be
ocomeni 74:f26e846adfe9 736 * communicated through the serial port */
ocomeni 74:f26e846adfe9 737 virtual void linkEncryptionResult(
ocomeni 74:f26e846adfe9 738 ble::connection_handle_t connectionHandle,
ocomeni 74:f26e846adfe9 739 ble::link_encryption_t result
ocomeni 74:f26e846adfe9 740 ) {
ocomeni 74:f26e846adfe9 741 if (result == ble::link_encryption_t::ENCRYPTED) {
ocomeni 74:f26e846adfe9 742 printf("Link ENCRYPTED\r\n");
ocomeni 74:f26e846adfe9 743 } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) {
ocomeni 74:f26e846adfe9 744 printf("Link ENCRYPTED_WITH_MITM\r\n");
ocomeni 74:f26e846adfe9 745 } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) {
ocomeni 74:f26e846adfe9 746 printf("Link NOT_ENCRYPTED\r\n");
ocomeni 74:f26e846adfe9 747 }
ocomeni 74:f26e846adfe9 748
ocomeni 74:f26e846adfe9 749 /* disconnect in 2 s */
ocomeni 74:f26e846adfe9 750 _event_queue.call_in(
ocomeni 74:f26e846adfe9 751 2000,
ocomeni 74:f26e846adfe9 752 &_ble.gap(),
ocomeni 75:08eff6258e1b 753 &Gap::disconnect, //disconnect_call,
ocomeni 74:f26e846adfe9 754 _handle,
ocomeni 75:08eff6258e1b 755 (Gap::DisconnectionReason_t)0x13
ocomeni 75:08eff6258e1b 756 //Gap::DisconnectionReason_t::REMOTE_USER_TERMINATED_CONNECTION)
ocomeni 75:08eff6258e1b 757 //ble::local_disconnection_reason_t(ble::local_disconnection_reason_t::USER_TERMINATION)
ocomeni 74:f26e846adfe9 758 );
ocomeni 74:f26e846adfe9 759 }
ocomeni 75:08eff6258e1b 760
ocomeni 75:08eff6258e1b 761
ocomeni 74:f26e846adfe9 762
ocomeni 74:f26e846adfe9 763 /** This is called by Gap to notify the application we disconnected,
ocomeni 74:f26e846adfe9 764 * in our case it ends the demonstration. */
ocomeni 75:08eff6258e1b 765 //virtual void onDisconnectionComplete(const Gap::DisconnectionCompleteEvent &)
ocomeni 75:08eff6258e1b 766 virtual void onDisconnectionComplete(const Gap::DisconnectionCallbackParams_t *params)
ocomeni 74:f26e846adfe9 767 {
ocomeni 75:08eff6258e1b 768 printf("Disconnected\r\n");
ocomeni 74:f26e846adfe9 769 _event_queue.break_dispatch();
ocomeni 74:f26e846adfe9 770 };
ocomeni 74:f26e846adfe9 771
ocomeni 75:08eff6258e1b 772 //virtual void onAdvertisingEnd(const ble::AdvertisingEndEvent &)
ocomeni 75:08eff6258e1b 773 //void onAdvertisingEnd(const ble::AdvertisingEndEvent &)
ocomeni 75:08eff6258e1b 774 //{
ocomeni 75:08eff6258e1b 775 // printf("Advertising timed out - aborting\r\n");
ocomeni 75:08eff6258e1b 776 // _event_queue.break_dispatch();
ocomeni 75:08eff6258e1b 777 //}
ocomeni 74:f26e846adfe9 778
ocomeni 75:08eff6258e1b 779 //virtual void onScanTimeout(const ble::ScanTimeoutEvent &)
ocomeni 75:08eff6258e1b 780 //{
ocomeni 75:08eff6258e1b 781 // printf("Scan timed out - aborting\r\n");
ocomeni 75:08eff6258e1b 782 // _event_queue.break_dispatch();
ocomeni 75:08eff6258e1b 783 //}
ocomeni 74:f26e846adfe9 784
ocomeni 74:f26e846adfe9 785 private:
ocomeni 74:f26e846adfe9 786 DigitalOut _led1;
ocomeni 74:f26e846adfe9 787
ocomeni 74:f26e846adfe9 788 protected:
ocomeni 74:f26e846adfe9 789 BLE &_ble;
ocomeni 74:f26e846adfe9 790 events::EventQueue &_event_queue;
ocomeni 74:f26e846adfe9 791 BLEProtocol::AddressBytes_t &_peer_address;
ocomeni 74:f26e846adfe9 792 ble::connection_handle_t _handle;
ocomeni 74:f26e846adfe9 793 bool _is_connecting;
ocomeni 74:f26e846adfe9 794 };
ocomeni 74:f26e846adfe9 795
ocomeni 74:f26e846adfe9 796 /** A peripheral device will advertise, accept the connection and request
ocomeni 74:f26e846adfe9 797 * a change in link security. */
ocomeni 74:f26e846adfe9 798 class SMDevicePeripheral : public SMDevice {
ocomeni 74:f26e846adfe9 799 public:
ocomeni 74:f26e846adfe9 800 SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
ocomeni 74:f26e846adfe9 801 : SMDevice(ble, event_queue, peer_address) { }
ocomeni 74:f26e846adfe9 802
ocomeni 74:f26e846adfe9 803 virtual void start()
ocomeni 74:f26e846adfe9 804 {
ocomeni 74:f26e846adfe9 805 /* Set up and start advertising */
ocomeni 75:08eff6258e1b 806 #ifdef NEW_BLE5_API
ocomeni 75:08eff6258e1b 807 //uint8_t adv_buffer[Gap::LEGACY_ADVERTISING_MAX_SIZE];
ocomeni 75:08eff6258e1b 808 uint8_t adv_buffer[32];
ocomeni 74:f26e846adfe9 809 /* use the helper to build the payload */
ocomeni 75:08eff6258e1b 810 ble::Gap::AdvertisingDataBuilder adv_data_builder(
ocomeni 75:08eff6258e1b 811 adv_buffer, 32
ocomeni 74:f26e846adfe9 812 );
ocomeni 74:f26e846adfe9 813
ocomeni 74:f26e846adfe9 814 adv_data_builder.setFlags();
ocomeni 74:f26e846adfe9 815 adv_data_builder.setName(DEVICE_NAME);
ocomeni 74:f26e846adfe9 816
ocomeni 74:f26e846adfe9 817 /* Set payload for the set */
ocomeni 74:f26e846adfe9 818 ble_error_t error = _ble.gap().setAdvertisingPayload(
ocomeni 74:f26e846adfe9 819 ble::LEGACY_ADVERTISING_HANDLE,
ocomeni 74:f26e846adfe9 820 adv_data_builder.getAdvertisingData()
ocomeni 74:f26e846adfe9 821 );
ocomeni 74:f26e846adfe9 822
ocomeni 74:f26e846adfe9 823 if (error) {
ocomeni 74:f26e846adfe9 824 print_error(error, "Gap::setAdvertisingPayload() failed");
ocomeni 74:f26e846adfe9 825 _event_queue.break_dispatch();
ocomeni 74:f26e846adfe9 826 return;
ocomeni 74:f26e846adfe9 827 }
ocomeni 74:f26e846adfe9 828
ocomeni 75:08eff6258e1b 829 ble::gap::AdvertisingParameters adv_parameters(
ocomeni 74:f26e846adfe9 830 ble::advertising_type_t::CONNECTABLE_UNDIRECTED
ocomeni 74:f26e846adfe9 831 );
ocomeni 74:f26e846adfe9 832
ocomeni 74:f26e846adfe9 833 error = _ble.gap().setAdvertisingParameters(
ocomeni 74:f26e846adfe9 834 ble::LEGACY_ADVERTISING_HANDLE,
ocomeni 74:f26e846adfe9 835 adv_parameters
ocomeni 74:f26e846adfe9 836 );
ocomeni 74:f26e846adfe9 837
ocomeni 74:f26e846adfe9 838 if (error) {
ocomeni 74:f26e846adfe9 839 print_error(error, "Gap::setAdvertisingParameters() failed");
ocomeni 74:f26e846adfe9 840 return;
ocomeni 74:f26e846adfe9 841 }
ocomeni 74:f26e846adfe9 842
ocomeni 74:f26e846adfe9 843 error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
ocomeni 74:f26e846adfe9 844
ocomeni 74:f26e846adfe9 845 if (error) {
ocomeni 74:f26e846adfe9 846 print_error(error, "Gap::startAdvertising() failed");
ocomeni 74:f26e846adfe9 847 return;
ocomeni 74:f26e846adfe9 848 }
ocomeni 75:08eff6258e1b 849 #else
ocomeni 75:08eff6258e1b 850 /* setup advertising */
ocomeni 75:08eff6258e1b 851 _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ocomeni 75:08eff6258e1b 852 //_ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
ocomeni 75:08eff6258e1b 853 _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
ocomeni 75:08eff6258e1b 854 /* set up the services that can be discovered */
ocomeni 75:08eff6258e1b 855 _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
ocomeni 75:08eff6258e1b 856 _ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ocomeni 75:08eff6258e1b 857 _ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
ocomeni 75:08eff6258e1b 858 _ble.gap().setAdvertisingTimeout(300); /* 16 * 1000ms. */
ocomeni 75:08eff6258e1b 859 _ble.gap().startAdvertising();
ocomeni 74:f26e846adfe9 860
ocomeni 75:08eff6258e1b 861 #endif
ocomeni 74:f26e846adfe9 862 printf("Please connect to device\r\n");
ocomeni 74:f26e846adfe9 863
ocomeni 74:f26e846adfe9 864 /** This tells the stack to generate a pairingRequest event
ocomeni 74:f26e846adfe9 865 * which will require this application to respond before pairing
ocomeni 74:f26e846adfe9 866 * can proceed. Setting it to false will automatically accept
ocomeni 74:f26e846adfe9 867 * pairing. */
ocomeni 74:f26e846adfe9 868 _ble.securityManager().setPairingRequestAuthorisation(true);
ocomeni 74:f26e846adfe9 869 };
ocomeni 74:f26e846adfe9 870
ocomeni 74:f26e846adfe9 871 /** This is called by Gap to notify the application we connected,
ocomeni 74:f26e846adfe9 872 * in our case it immediately requests a change in link security */
ocomeni 75:08eff6258e1b 873 //virtual void onConnectionComplete(const ble::ConnectionCompleteEvent_t &event)
ocomeni 75:08eff6258e1b 874 virtual void onConnectionComplete(const Gap::ConnectionCallbackParams_t &event)
ocomeni 74:f26e846adfe9 875 {
ocomeni 74:f26e846adfe9 876 ble_error_t error;
ocomeni 74:f26e846adfe9 877
ocomeni 74:f26e846adfe9 878 /* remember the device that connects to us now so we can connect to it
ocomeni 74:f26e846adfe9 879 * during the next demonstration */
ocomeni 75:08eff6258e1b 880 memcpy(_peer_address, event.peerAddr, 6);
ocomeni 74:f26e846adfe9 881
ocomeni 74:f26e846adfe9 882 printf("Connected to peer: ");
ocomeni 75:08eff6258e1b 883 print_address(event.peerAddr);
ocomeni 74:f26e846adfe9 884
ocomeni 75:08eff6258e1b 885 _handle = event.handle;
ocomeni 74:f26e846adfe9 886
ocomeni 74:f26e846adfe9 887 /* Request a change in link security. This will be done
ocomeni 74:f26e846adfe9 888 * indirectly by asking the master of the connection to
ocomeni 74:f26e846adfe9 889 * change it. Depending on circumstances different actions
ocomeni 74:f26e846adfe9 890 * may be taken by the master which will trigger events
ocomeni 74:f26e846adfe9 891 * which the applications should deal with. */
ocomeni 74:f26e846adfe9 892 error = _ble.securityManager().setLinkSecurity(
ocomeni 74:f26e846adfe9 893 _handle,
ocomeni 74:f26e846adfe9 894 SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM
ocomeni 74:f26e846adfe9 895 );
ocomeni 74:f26e846adfe9 896
ocomeni 74:f26e846adfe9 897 if (error) {
ocomeni 74:f26e846adfe9 898 printf("Error during SM::setLinkSecurity %d\r\n", error);
ocomeni 74:f26e846adfe9 899 return;
ocomeni 74:f26e846adfe9 900 }
ocomeni 74:f26e846adfe9 901 };
ocomeni 74:f26e846adfe9 902 };
ocomeni 74:f26e846adfe9 903
ocomeni 74:f26e846adfe9 904 /** A central device will scan, connect to a peer and request pairing. */
ocomeni 74:f26e846adfe9 905 class SMDeviceCentral : public SMDevice {
ocomeni 74:f26e846adfe9 906 public:
ocomeni 74:f26e846adfe9 907 SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address)
ocomeni 74:f26e846adfe9 908 : SMDevice(ble, event_queue, peer_address) { }
ocomeni 74:f26e846adfe9 909
ocomeni 74:f26e846adfe9 910 virtual void start()
ocomeni 74:f26e846adfe9 911 {
ocomeni 74:f26e846adfe9 912 ble::ScanParameters params;
ocomeni 74:f26e846adfe9 913 ble_error_t error = _ble.gap().setScanParameters(params);
ocomeni 74:f26e846adfe9 914
ocomeni 74:f26e846adfe9 915 if (error) {
ocomeni 74:f26e846adfe9 916 print_error(error, "Error in Gap::startScan %d\r\n");
ocomeni 74:f26e846adfe9 917 return;
ocomeni 74:f26e846adfe9 918 }
ocomeni 74:f26e846adfe9 919
ocomeni 74:f26e846adfe9 920 /* start scanning, results will be handled by onAdvertisingReport */
ocomeni 74:f26e846adfe9 921 error = _ble.gap().startScan();
ocomeni 74:f26e846adfe9 922
ocomeni 74:f26e846adfe9 923 if (error) {
ocomeni 74:f26e846adfe9 924 print_error(error, "Error in Gap::startScan %d\r\n");
ocomeni 74:f26e846adfe9 925 return;
ocomeni 74:f26e846adfe9 926 }
ocomeni 74:f26e846adfe9 927
ocomeni 74:f26e846adfe9 928 printf("Please advertise\r\n");
ocomeni 74:f26e846adfe9 929
ocomeni 74:f26e846adfe9 930 printf("Scanning for: ");
ocomeni 74:f26e846adfe9 931 print_address(_peer_address);
ocomeni 74:f26e846adfe9 932 }
ocomeni 74:f26e846adfe9 933
ocomeni 74:f26e846adfe9 934 private:
ocomeni 74:f26e846adfe9 935 /* Gap::EventHandler */
ocomeni 74:f26e846adfe9 936
ocomeni 74:f26e846adfe9 937 /** Look at scan payload to find a peer device and connect to it */
ocomeni 75:08eff6258e1b 938 virtual void onAdvertisingReport(const Gap::AdvertisementCallbackParams_t &event)
ocomeni 74:f26e846adfe9 939 {
ocomeni 74:f26e846adfe9 940 /* don't bother with analysing scan result if we're already connecting */
ocomeni 74:f26e846adfe9 941 if (_is_connecting) {
ocomeni 74:f26e846adfe9 942 return;
ocomeni 74:f26e846adfe9 943 }
ocomeni 74:f26e846adfe9 944
ocomeni 74:f26e846adfe9 945 /* parse the advertising payload, looking for a discoverable device */
ocomeni 75:08eff6258e1b 946 if (memcmp(event.peerAddr, _peer_address, sizeof(_peer_address)) == 0) {
ocomeni 74:f26e846adfe9 947 ble_error_t error = _ble.gap().stopScan();
ocomeni 74:f26e846adfe9 948
ocomeni 74:f26e846adfe9 949 if (error) {
ocomeni 74:f26e846adfe9 950 print_error(error, "Error caused by Gap::stopScan");
ocomeni 74:f26e846adfe9 951 return;
ocomeni 74:f26e846adfe9 952 }
ocomeni 74:f26e846adfe9 953
ocomeni 74:f26e846adfe9 954 ble::ConnectionParameters connection_params(
ocomeni 74:f26e846adfe9 955 ble::phy_t::LE_1M,
ocomeni 74:f26e846adfe9 956 ble::scan_interval_t(50),
ocomeni 74:f26e846adfe9 957 ble::scan_window_t(50),
ocomeni 74:f26e846adfe9 958 ble::conn_interval_t(50),
ocomeni 74:f26e846adfe9 959 ble::conn_interval_t(100),
ocomeni 74:f26e846adfe9 960 ble::slave_latency_t(0),
ocomeni 74:f26e846adfe9 961 ble::supervision_timeout_t(100)
ocomeni 74:f26e846adfe9 962 );
ocomeni 74:f26e846adfe9 963 connection_params.setOwnAddressType(ble::own_address_type_t::RANDOM);
ocomeni 74:f26e846adfe9 964
ocomeni 74:f26e846adfe9 965 error = _ble.gap().connect(
ocomeni 74:f26e846adfe9 966 event.getPeerAddressType(),
ocomeni 74:f26e846adfe9 967 event.getPeerAddress(),
ocomeni 74:f26e846adfe9 968 connection_params
ocomeni 74:f26e846adfe9 969 );
ocomeni 74:f26e846adfe9 970
ocomeni 74:f26e846adfe9 971 if (error) {
ocomeni 74:f26e846adfe9 972 print_error(error, "Error caused by Gap::connect");
ocomeni 74:f26e846adfe9 973 return;
ocomeni 74:f26e846adfe9 974 }
ocomeni 74:f26e846adfe9 975
ocomeni 74:f26e846adfe9 976 /* we may have already scan events waiting
ocomeni 74:f26e846adfe9 977 * to be processed so we need to remember
ocomeni 74:f26e846adfe9 978 * that we are already connecting and ignore them */
ocomeni 74:f26e846adfe9 979 _is_connecting = true;
ocomeni 74:f26e846adfe9 980
ocomeni 74:f26e846adfe9 981 return;
ocomeni 74:f26e846adfe9 982 }
ocomeni 74:f26e846adfe9 983 }
ocomeni 74:f26e846adfe9 984
ocomeni 74:f26e846adfe9 985 /** This is called by Gap to notify the application we connected,
ocomeni 74:f26e846adfe9 986 * in our case it immediately request pairing */
ocomeni 75:08eff6258e1b 987 virtual void onConnectionComplete(const Gap::ConnectionCallbackParams_t &event)
ocomeni 74:f26e846adfe9 988 {
ocomeni 74:f26e846adfe9 989 if (event.getStatus() == BLE_ERROR_NONE) {
ocomeni 74:f26e846adfe9 990 /* store the handle for future Security Manager requests */
ocomeni 74:f26e846adfe9 991 _handle = event.getConnectionHandle();
ocomeni 74:f26e846adfe9 992
ocomeni 74:f26e846adfe9 993 printf("Connected\r\n");
ocomeni 74:f26e846adfe9 994
ocomeni 74:f26e846adfe9 995 /* in this example the local device is the master so we request pairing */
ocomeni 74:f26e846adfe9 996 ble_error_t error = _ble.securityManager().requestPairing(_handle);
ocomeni 74:f26e846adfe9 997
ocomeni 74:f26e846adfe9 998 if (error) {
ocomeni 74:f26e846adfe9 999 printf("Error during SM::requestPairing %d\r\n", error);
ocomeni 74:f26e846adfe9 1000 return;
ocomeni 74:f26e846adfe9 1001 }
ocomeni 74:f26e846adfe9 1002
ocomeni 74:f26e846adfe9 1003 /* upon pairing success the application will disconnect */
ocomeni 74:f26e846adfe9 1004 }
ocomeni 74:f26e846adfe9 1005
ocomeni 74:f26e846adfe9 1006 /* failed to connect - restart scan */
ocomeni 74:f26e846adfe9 1007 ble_error_t error = _ble.gap().startScan();
ocomeni 74:f26e846adfe9 1008
ocomeni 74:f26e846adfe9 1009 if (error) {
ocomeni 74:f26e846adfe9 1010 print_error(error, "Error in Gap::startScan %d\r\n");
ocomeni 74:f26e846adfe9 1011 return;
ocomeni 74:f26e846adfe9 1012 }
ocomeni 74:f26e846adfe9 1013 };
ocomeni 74:f26e846adfe9 1014 };
ocomeni 74:f26e846adfe9 1015
ocomeni 74:f26e846adfe9 1016
ocomeni 74:f26e846adfe9 1017 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 74:f26e846adfe9 1018 bool create_filesystem()
ocomeni 74:f26e846adfe9 1019 {
ocomeni 74:f26e846adfe9 1020 static LittleFileSystem fs("fs");
ocomeni 74:f26e846adfe9 1021
ocomeni 74:f26e846adfe9 1022 /* replace this with any physical block device your board supports (like an SD card) */
ocomeni 74:f26e846adfe9 1023 static HeapBlockDevice bd(4096, 256);
ocomeni 74:f26e846adfe9 1024
ocomeni 74:f26e846adfe9 1025 int err = bd.init();
ocomeni 74:f26e846adfe9 1026
ocomeni 74:f26e846adfe9 1027 if (err) {
ocomeni 74:f26e846adfe9 1028 return false;
ocomeni 74:f26e846adfe9 1029 }
ocomeni 74:f26e846adfe9 1030
ocomeni 74:f26e846adfe9 1031 err = bd.erase(0, bd.size());
ocomeni 74:f26e846adfe9 1032
ocomeni 74:f26e846adfe9 1033 if (err) {
ocomeni 74:f26e846adfe9 1034 return false;
ocomeni 74:f26e846adfe9 1035 }
ocomeni 74:f26e846adfe9 1036
ocomeni 74:f26e846adfe9 1037 err = fs.mount(&bd);
ocomeni 74:f26e846adfe9 1038
ocomeni 74:f26e846adfe9 1039 if (err) {
ocomeni 74:f26e846adfe9 1040 /* Reformat if we can't mount the filesystem */
ocomeni 74:f26e846adfe9 1041 printf("No filesystem found, formatting...\r\n");
ocomeni 74:f26e846adfe9 1042
ocomeni 74:f26e846adfe9 1043 err = fs.reformat(&bd);
ocomeni 74:f26e846adfe9 1044
ocomeni 74:f26e846adfe9 1045 if (err) {
ocomeni 74:f26e846adfe9 1046 return false;
ocomeni 74:f26e846adfe9 1047 }
ocomeni 74:f26e846adfe9 1048 }
ocomeni 74:f26e846adfe9 1049
ocomeni 74:f26e846adfe9 1050 return true;
ocomeni 74:f26e846adfe9 1051 }
ocomeni 74:f26e846adfe9 1052 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 1053 #ifdef BLE_MAIN
ocomeni 74:f26e846adfe9 1054 int main()
ocomeni 74:f26e846adfe9 1055 {
ocomeni 74:f26e846adfe9 1056 BLE& ble = BLE::Instance();
ocomeni 74:f26e846adfe9 1057 events::EventQueue queue;
ocomeni 74:f26e846adfe9 1058
ocomeni 74:f26e846adfe9 1059 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 74:f26e846adfe9 1060 /* if filesystem creation fails or there is no filesystem the security manager
ocomeni 74:f26e846adfe9 1061 * will fallback to storing the security database in memory */
ocomeni 74:f26e846adfe9 1062 if (!create_filesystem()) {
ocomeni 74:f26e846adfe9 1063 printf("Filesystem creation failed, will use memory storage\r\n");
ocomeni 74:f26e846adfe9 1064 }
ocomeni 74:f26e846adfe9 1065 #endif
ocomeni 74:f26e846adfe9 1066
ocomeni 74:f26e846adfe9 1067 while(1) {
ocomeni 74:f26e846adfe9 1068 {
ocomeni 74:f26e846adfe9 1069 printf("\r\n PERIPHERAL \r\n\r\n");
ocomeni 74:f26e846adfe9 1070 SMDevicePeripheral peripheral(ble, queue, peer_address);
ocomeni 74:f26e846adfe9 1071 peripheral.run();
ocomeni 74:f26e846adfe9 1072 }
ocomeni 74:f26e846adfe9 1073
ocomeni 74:f26e846adfe9 1074 {
ocomeni 74:f26e846adfe9 1075 printf("\r\n CENTRAL \r\n\r\n");
ocomeni 74:f26e846adfe9 1076 SMDeviceCentral central(ble, queue, peer_address);
ocomeni 74:f26e846adfe9 1077 central.run();
ocomeni 74:f26e846adfe9 1078 }
ocomeni 74:f26e846adfe9 1079 }
ocomeni 74:f26e846adfe9 1080
ocomeni 74:f26e846adfe9 1081 return 0;
ocomeni 74:f26e846adfe9 1082 }
ocomeni 74:f26e846adfe9 1083
ocomeni 75:08eff6258e1b 1084 #endif
ocomeni 75:08eff6258e1b 1085
ocomeni 74:f26e846adfe9 1086 #endif