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

Dependencies:   mbed-http

Committer:
ocomeni
Date:
Sun Mar 10 09:46:06 2019 +0000
Revision:
74:f26e846adfe9
Child:
75:08eff6258e1b
ATCmdManager now instaltiates ok

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