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

Dependencies:   mbed-http

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