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

Dependencies:   mbed-http

Committer:
ocomeni
Date:
Fri Jul 19 16:49:26 2019 +0000
Branch:
PassingRegression
Revision:
129:590bdc2dcf5b
Parent:
124:eae4512b131b
Implementation of Access token acquisition; 1. make request with credentials - DONE; 2. get response - DONE; 3. extract Id and refresh tokens from response - DONE; 4. integrate with code - DONE; Testing ongoing

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 103:7b566b522427 19 #include "debug.h"
ocomeni 76:6afda865fbf8 20 #include "common_config.h"
ocomeni 74:f26e846adfe9 21 #include "ble/BLE.h"
ocomeni 76:6afda865fbf8 22 #include "ble/services/UARTService.h"
ocomeni 74:f26e846adfe9 23 #include "SecurityManager.h"
ocomeni 75:08eff6258e1b 24 #include "BleManager.h"
ocomeni 75:08eff6258e1b 25 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 26 #include "LittleFileSystem.h"
ocomeni 75:08eff6258e1b 27 #include "HeapBlockDevice.h"
ocomeni 75:08eff6258e1b 28 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 103:7b566b522427 29 #define FILE_CODE "btle"
ocomeni 75:08eff6258e1b 30
ocomeni 75:08eff6258e1b 31
ocomeni 113:888e262ff0a9 32 //static const uint8_t DEVICE_NAME[] = "SM_device";
ocomeni 76:6afda865fbf8 33 //static const uint16_t uuid16_list[] = {LEDService::LED_SERVICE_UUID};
ocomeni 76:6afda865fbf8 34 extern UARTService *uart;
ocomeni 119:8d939a902333 35
ocomeni 75:08eff6258e1b 36 /** This example demonstrates all the basic setup required
ocomeni 75:08eff6258e1b 37 * for pairing and setting up link security both as a central and peripheral
ocomeni 75:08eff6258e1b 38 *
ocomeni 75:08eff6258e1b 39 * The example is implemented as two classes, one for the peripheral and one
ocomeni 75:08eff6258e1b 40 * for central inheriting from a common base. They are run in sequence and
ocomeni 75:08eff6258e1b 41 * require a peer device to connect to. During the peripheral device demonstration
ocomeni 75:08eff6258e1b 42 * a peer device is required to connect. In the central device demonstration
ocomeni 75:08eff6258e1b 43 * this peer device will be scanned for and connected to - therefore it should
ocomeni 75:08eff6258e1b 44 * be advertising with the same address as when it connected.
ocomeni 75:08eff6258e1b 45 *
ocomeni 75:08eff6258e1b 46 * During the test output is written on the serial connection to monitor its
ocomeni 75:08eff6258e1b 47 * progress.
ocomeni 75:08eff6258e1b 48 */
ocomeni 75:08eff6258e1b 49
ocomeni 75:08eff6258e1b 50 //static const uint8_t DEVICE_NAME[] = "SM_device";
ocomeni 75:08eff6258e1b 51
ocomeni 75:08eff6258e1b 52 /* for demonstration purposes we will store the peer device address
ocomeni 75:08eff6258e1b 53 * of the device that connects to us in the first demonstration
ocomeni 75:08eff6258e1b 54 * so we can use its address to reconnect to it later */
ocomeni 75:08eff6258e1b 55 //static BLEProtocol::AddressBytes_t peer_address;
ocomeni 75:08eff6258e1b 56
ocomeni 75:08eff6258e1b 57 /** Base class for both peripheral and central. The same class that provides
ocomeni 75:08eff6258e1b 58 * the logic for the application also implements the SecurityManagerEventHandler
ocomeni 75:08eff6258e1b 59 * which is the interface used by the Security Manager to communicate events
ocomeni 75:08eff6258e1b 60 * back to the applications. You can provide overrides for a selection of events
ocomeni 75:08eff6258e1b 61 * your application is interested in.
ocomeni 75:08eff6258e1b 62 */
ocomeni 78:07bb86e3ce14 63 SMDevice::SMDevice(BLE &ble, events::EventQueue &event_queue,
ocomeni 118:8df0e9c2ee3f 64 BLEProtocol::AddressBytes_t &peer_address,
ocomeni 118:8df0e9c2ee3f 65 MemoryPool<at_ble_msg_t, PQDSZ_BLE> *aT2BleDatamPool,
ocomeni 118:8df0e9c2ee3f 66 Queue<at_ble_msg_t, PQDSZ_BLE> *aT2BleDataQueue,
ocomeni 118:8df0e9c2ee3f 67 MemoryPool<ble_at_msg_t, PQDSZ_BLE> *ble2ATDatamPool,
ocomeni 118:8df0e9c2ee3f 68 Queue<ble_at_msg_t, PQDSZ_BLE> *ble2ATDataQueue,
ocomeni 118:8df0e9c2ee3f 69 ble_config_t *ble_config) :
ocomeni 75:08eff6258e1b 70 _ble(ble),
ocomeni 75:08eff6258e1b 71 _event_queue(event_queue),
ocomeni 75:08eff6258e1b 72 _peer_address(peer_address),
ocomeni 118:8df0e9c2ee3f 73 _aT2BleDatamPool (aT2BleDatamPool),
ocomeni 118:8df0e9c2ee3f 74 _aT2BleDataQueue (aT2BleDataQueue),
ocomeni 118:8df0e9c2ee3f 75 _ble2ATDatamPool (ble2ATDatamPool),
ocomeni 118:8df0e9c2ee3f 76 _ble2ATDataQueue (ble2ATDataQueue),
ocomeni 78:07bb86e3ce14 77 ble_config(ble_config),
ocomeni 75:08eff6258e1b 78 _handle(0),
ocomeni 113:888e262ff0a9 79 _is_connecting(false),
ocomeni 113:888e262ff0a9 80 _led1(LED1, 0)
ocomeni 113:888e262ff0a9 81 {
ocomeni 113:888e262ff0a9 82 isConnected = false;
ocomeni 113:888e262ff0a9 83 }
ocomeni 75:08eff6258e1b 84
ocomeni 75:08eff6258e1b 85 SMDevice::~SMDevice()
ocomeni 75:08eff6258e1b 86 {
ocomeni 75:08eff6258e1b 87 if (_ble.hasInitialized()) {
ocomeni 75:08eff6258e1b 88 _ble.shutdown();
ocomeni 75:08eff6258e1b 89 }
ocomeni 75:08eff6258e1b 90 }
ocomeni 75:08eff6258e1b 91
ocomeni 75:08eff6258e1b 92 /** Start BLE interface initialisation */
ocomeni 75:08eff6258e1b 93 void SMDevice::run()
ocomeni 75:08eff6258e1b 94 {
ocomeni 103:7b566b522427 95 dbg_printf(LOG, "\r\n [BTLE MAN] Thread Id = %X\r\n", (uint32_t)ThisThread::get_id());
ocomeni 87:99b37d26ff2a 96
ocomeni 75:08eff6258e1b 97 ble_error_t error;
ocomeni 75:08eff6258e1b 98
ocomeni 108:3c8fb2c6e7bf 99 /* to show we're running we'll blink every 10secs */
ocomeni 119:8d939a902333 100 //_event_queue.call_every(10000, this, &SMDevice::blink);
ocomeni 75:08eff6258e1b 101
ocomeni 77:0b505d1e15f4 102 /* to show we're advertising we'll print status every minute */
ocomeni 119:8d939a902333 103 //_event_queue.call_every(60000, this, &SMDevice::reportGapState);
ocomeni 119:8d939a902333 104
ocomeni 119:8d939a902333 105 /* process queues every BLE_PROCESS_QUEUES_INTERVAL_MS */
ocomeni 119:8d939a902333 106 _event_queue.call_every(BLE_PROCESS_QUEUES_INTERVAL_MS, this, &SMDevice::processQueues);
ocomeni 77:0b505d1e15f4 107
ocomeni 77:0b505d1e15f4 108
ocomeni 77:0b505d1e15f4 109
ocomeni 75:08eff6258e1b 110 if (_ble.hasInitialized()) {
ocomeni 103:7b566b522427 111 dbg_printf(LOG, "Ble instance already initialised.\r\n");
ocomeni 75:08eff6258e1b 112 return;
ocomeni 75:08eff6258e1b 113 }
ocomeni 75:08eff6258e1b 114
ocomeni 75:08eff6258e1b 115 /* this will inform us off all events so we can schedule their handling
ocomeni 75:08eff6258e1b 116 * using our event queue */
ocomeni 75:08eff6258e1b 117 _ble.onEventsToProcess(
ocomeni 75:08eff6258e1b 118 makeFunctionPointer(this, &SMDevice::schedule_ble_events)
ocomeni 75:08eff6258e1b 119 );
ocomeni 75:08eff6258e1b 120
ocomeni 75:08eff6258e1b 121 /* handle timeouts, for example when connection attempts fail */
ocomeni 75:08eff6258e1b 122 _ble.gap().onTimeout(
ocomeni 75:08eff6258e1b 123 makeFunctionPointer(this, &SMDevice::on_timeout)
ocomeni 75:08eff6258e1b 124 );
ocomeni 75:08eff6258e1b 125
ocomeni 75:08eff6258e1b 126 error = _ble.init(this, &SMDevice::on_init_complete);
ocomeni 75:08eff6258e1b 127
ocomeni 75:08eff6258e1b 128 if (error) {
ocomeni 103:7b566b522427 129 dbg_printf(LOG, "Error returned by BLE::init.\r\n");
ocomeni 75:08eff6258e1b 130 return;
ocomeni 75:08eff6258e1b 131 }
ocomeni 75:08eff6258e1b 132
ocomeni 75:08eff6258e1b 133 /* this will not return until shutdown */
ocomeni 77:0b505d1e15f4 134 //_event_queue.dispatch_forever();
ocomeni 75:08eff6258e1b 135 }
ocomeni 75:08eff6258e1b 136
ocomeni 77:0b505d1e15f4 137
ocomeni 77:0b505d1e15f4 138 void SMDevice::shutDown()
ocomeni 77:0b505d1e15f4 139 {
ocomeni 77:0b505d1e15f4 140 if (_ble.hasInitialized()) {
ocomeni 77:0b505d1e15f4 141 _ble.shutdown();
ocomeni 103:7b566b522427 142 dbg_printf(LOG, "Shutting down BLE Instance...\r\n");
ocomeni 77:0b505d1e15f4 143 _event_queue.break_dispatch();
ocomeni 77:0b505d1e15f4 144 }
ocomeni 77:0b505d1e15f4 145 }
ocomeni 77:0b505d1e15f4 146
ocomeni 77:0b505d1e15f4 147
ocomeni 75:08eff6258e1b 148 /* event handler functions */
ocomeni 75:08eff6258e1b 149
ocomeni 75:08eff6258e1b 150 /** Respond to a pairing request. This will be called by the stack
ocomeni 75:08eff6258e1b 151 * when a pairing request arrives and expects the application to
ocomeni 75:08eff6258e1b 152 * call acceptPairingRequest or cancelPairingRequest */
ocomeni 75:08eff6258e1b 153 void SMDevice::pairingRequest(
ocomeni 75:08eff6258e1b 154 ble::connection_handle_t connectionHandle
ocomeni 75:08eff6258e1b 155 ) {
ocomeni 103:7b566b522427 156 dbg_printf(LOG, "Pairing requested - authorising\r\n");
ocomeni 75:08eff6258e1b 157 _ble.securityManager().acceptPairingRequest(connectionHandle);
ocomeni 75:08eff6258e1b 158 }
ocomeni 75:08eff6258e1b 159
ocomeni 75:08eff6258e1b 160 /** Inform the application of a successful pairing. Terminate the demonstration. */
ocomeni 75:08eff6258e1b 161 void SMDevice::pairingResult(
ocomeni 75:08eff6258e1b 162 ble::connection_handle_t connectionHandle,
ocomeni 75:08eff6258e1b 163 SecurityManager::SecurityCompletionStatus_t result
ocomeni 75:08eff6258e1b 164 ) {
ocomeni 75:08eff6258e1b 165 if (result == SecurityManager::SEC_STATUS_SUCCESS) {
ocomeni 103:7b566b522427 166 dbg_printf(LOG, "Pairing successful\r\n");
ocomeni 75:08eff6258e1b 167 } else {
ocomeni 103:7b566b522427 168 dbg_printf(LOG, "Pairing failed\r\n");
ocomeni 75:08eff6258e1b 169 }
ocomeni 75:08eff6258e1b 170 }
ocomeni 75:08eff6258e1b 171
ocomeni 75:08eff6258e1b 172 /** Inform the application of change in encryption status. This will be
ocomeni 75:08eff6258e1b 173 * communicated through the serial port */
ocomeni 75:08eff6258e1b 174 void SMDevice::linkEncryptionResult(
ocomeni 75:08eff6258e1b 175 ble::connection_handle_t connectionHandle,
ocomeni 75:08eff6258e1b 176 ble::link_encryption_t result
ocomeni 75:08eff6258e1b 177 ) {
ocomeni 75:08eff6258e1b 178 if (result == ble::link_encryption_t::ENCRYPTED) {
ocomeni 103:7b566b522427 179 dbg_printf(LOG, "Link ENCRYPTED\r\n");
ocomeni 75:08eff6258e1b 180 } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) {
ocomeni 103:7b566b522427 181 dbg_printf(LOG, "Link ENCRYPTED_WITH_MITM\r\n");
ocomeni 75:08eff6258e1b 182 } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) {
ocomeni 103:7b566b522427 183 dbg_printf(LOG, "Link NOT_ENCRYPTED\r\n");
ocomeni 75:08eff6258e1b 184 }
ocomeni 75:08eff6258e1b 185
ocomeni 76:6afda865fbf8 186 #ifdef DEMO_BLE_SECURITY
ocomeni 75:08eff6258e1b 187 /* disconnect in 2 s */
ocomeni 75:08eff6258e1b 188 _event_queue.call_in(
ocomeni 75:08eff6258e1b 189 2000, &_ble.gap(),
ocomeni 75:08eff6258e1b 190 &Gap::disconnect, _handle, Gap::REMOTE_USER_TERMINATED_CONNECTION
ocomeni 75:08eff6258e1b 191 );
ocomeni 76:6afda865fbf8 192 #endif
ocomeni 75:08eff6258e1b 193 }
ocomeni 75:08eff6258e1b 194
ocomeni 75:08eff6258e1b 195 /** Override to start chosen activity when initialisation completes */
ocomeni 75:08eff6258e1b 196 //void SMDevice::start() = 0;
ocomeni 75:08eff6258e1b 197
ocomeni 75:08eff6258e1b 198 /** This is called when BLE interface is initialised and starts the demonstration */
ocomeni 75:08eff6258e1b 199 void SMDevice::on_init_complete(BLE::InitializationCompleteCallbackContext *event)
ocomeni 75:08eff6258e1b 200 {
ocomeni 75:08eff6258e1b 201 ble_error_t error;
ocomeni 75:08eff6258e1b 202
ocomeni 75:08eff6258e1b 203 if (event->error) {
ocomeni 103:7b566b522427 204 dbg_printf(LOG, "Error during the initialisation\r\n");
ocomeni 75:08eff6258e1b 205 return;
ocomeni 75:08eff6258e1b 206 }
ocomeni 75:08eff6258e1b 207
ocomeni 75:08eff6258e1b 208 /* This path will be used to store bonding information but will fallback
ocomeni 75:08eff6258e1b 209 * to storing in memory if file access fails (for example due to lack of a filesystem) */
ocomeni 75:08eff6258e1b 210 const char* db_path = "/fs/bt_sec_db";
ocomeni 75:08eff6258e1b 211 /* If the security manager is required this needs to be called before any
ocomeni 75:08eff6258e1b 212 * calls to the Security manager happen. */
ocomeni 75:08eff6258e1b 213 error = _ble.securityManager().init(
ocomeni 75:08eff6258e1b 214 true,
ocomeni 75:08eff6258e1b 215 false,
ocomeni 79:a2187bbfa407 216 SecurityManager::IO_CAPS_DISPLAY_ONLY, // SecurityManager::IO_CAPS_NONE
ocomeni 116:2296cf274661 217 ble_config->pairingKey,
ocomeni 75:08eff6258e1b 218 false,
ocomeni 75:08eff6258e1b 219 db_path
ocomeni 75:08eff6258e1b 220 );
ocomeni 75:08eff6258e1b 221
ocomeni 75:08eff6258e1b 222 if (error) {
ocomeni 103:7b566b522427 223 dbg_printf(LOG, "Error during init %d\r\n", error);
ocomeni 75:08eff6258e1b 224 return;
ocomeni 75:08eff6258e1b 225 }
ocomeni 75:08eff6258e1b 226
ocomeni 75:08eff6258e1b 227 error = _ble.securityManager().preserveBondingStateOnReset(true);
ocomeni 75:08eff6258e1b 228
ocomeni 75:08eff6258e1b 229 if (error) {
ocomeni 103:7b566b522427 230 dbg_printf(LOG, "Error during preserveBondingStateOnReset %d\r\n", error);
ocomeni 75:08eff6258e1b 231 }
ocomeni 75:08eff6258e1b 232
ocomeni 75:08eff6258e1b 233 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 234 /* Enable privacy so we can find the keys */
ocomeni 75:08eff6258e1b 235 error = _ble.gap().enablePrivacy(true);
ocomeni 75:08eff6258e1b 236
ocomeni 75:08eff6258e1b 237 if (error) {
ocomeni 103:7b566b522427 238 dbg_printf(LOG, "Error enabling privacy\r\n");
ocomeni 75:08eff6258e1b 239 }
ocomeni 75:08eff6258e1b 240
ocomeni 75:08eff6258e1b 241 Gap::PeripheralPrivacyConfiguration_t configuration_p = {
ocomeni 75:08eff6258e1b 242 /* use_non_resolvable_random_address */ false,
ocomeni 75:08eff6258e1b 243 Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS
ocomeni 75:08eff6258e1b 244 };
ocomeni 75:08eff6258e1b 245 _ble.gap().setPeripheralPrivacyConfiguration(&configuration_p);
ocomeni 75:08eff6258e1b 246
ocomeni 75:08eff6258e1b 247 Gap::CentralPrivacyConfiguration_t configuration_c = {
ocomeni 75:08eff6258e1b 248 /* use_non_resolvable_random_address */ false,
ocomeni 75:08eff6258e1b 249 Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD
ocomeni 75:08eff6258e1b 250 };
ocomeni 75:08eff6258e1b 251 _ble.gap().setCentralPrivacyConfiguration(&configuration_c);
ocomeni 75:08eff6258e1b 252
ocomeni 75:08eff6258e1b 253 /* this demo switches between being master and slave */
ocomeni 75:08eff6258e1b 254 _ble.securityManager().setHintFutureRoleReversal(true);
ocomeni 75:08eff6258e1b 255 #endif
ocomeni 75:08eff6258e1b 256
ocomeni 75:08eff6258e1b 257 /* Tell the security manager to use methods in this class to inform us
ocomeni 75:08eff6258e1b 258 * of any events. Class needs to implement SecurityManagerEventHandler. */
ocomeni 75:08eff6258e1b 259 _ble.securityManager().setSecurityManagerEventHandler(this);
ocomeni 75:08eff6258e1b 260
ocomeni 75:08eff6258e1b 261 /* print device address */
ocomeni 75:08eff6258e1b 262 Gap::AddressType_t addr_type;
ocomeni 75:08eff6258e1b 263 Gap::Address_t addr;
ocomeni 75:08eff6258e1b 264 _ble.gap().getAddress(&addr_type, addr);
ocomeni 103:7b566b522427 265 dbg_printf(LOG, "Device address: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
ocomeni 75:08eff6258e1b 266 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
ocomeni 75:08eff6258e1b 267
ocomeni 75:08eff6258e1b 268 /* when scanning we want to connect to a peer device so we need to
ocomeni 75:08eff6258e1b 269 * attach callbacks that are used by Gap to notify us of events */
ocomeni 75:08eff6258e1b 270 _ble.gap().onConnection(this, &SMDevice::on_connect);
ocomeni 75:08eff6258e1b 271 _ble.gap().onDisconnection(this, &SMDevice::on_disconnect);
ocomeni 76:6afda865fbf8 272 _ble.gattServer().onDataWritten(this, &SMDevice::onDataWrittenCallback);
ocomeni 79:a2187bbfa407 273 //_ble.securityManager().onPasskeyDisplay(this, &SMDevice::passkeyDisplayCallback);
ocomeni 79:a2187bbfa407 274 //_ble.securityManager().onSecuritySetupCompleted(this, &SMDevice::securitySetupCompletedCallback);
ocomeni 75:08eff6258e1b 275
ocomeni 75:08eff6258e1b 276 /* start test in 500 ms */
ocomeni 75:08eff6258e1b 277 _event_queue.call_in(500, this, &SMDevice::start);
ocomeni 75:08eff6258e1b 278 }
ocomeni 75:08eff6258e1b 279
ocomeni 75:08eff6258e1b 280 /** This is called by Gap to notify the application we connected */
ocomeni 75:08eff6258e1b 281 //void SMDevice::on_connect(const Gap::ConnectionCallbackParams_t *connection_event);
ocomeni 75:08eff6258e1b 282
ocomeni 75:08eff6258e1b 283 /** This is called by Gap to notify the application we disconnected,
ocomeni 75:08eff6258e1b 284 * in our case it ends the demonstration. */
ocomeni 75:08eff6258e1b 285 void SMDevice::on_disconnect(const Gap::DisconnectionCallbackParams_t *event)
ocomeni 75:08eff6258e1b 286 {
ocomeni 103:7b566b522427 287 dbg_printf(LOG, "Disconnected\r\n");
ocomeni 77:0b505d1e15f4 288 #ifndef DEMO_BLE_SECURITY
ocomeni 103:7b566b522427 289 dbg_printf(LOG, "Restarting advertising...\r\n");
ocomeni 113:888e262ff0a9 290 _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
ocomeni 77:0b505d1e15f4 291 #endif
ocomeni 113:888e262ff0a9 292 isConnected = false;
ocomeni 121:ac4f59839e4f 293 _event_queue.call(this, &SMDevice::setNextCommand, BLE_CMD_DISCONNECT);
ocomeni 75:08eff6258e1b 294 }
ocomeni 75:08eff6258e1b 295
ocomeni 75:08eff6258e1b 296 /** End demonstration unexpectedly. Called if timeout is reached during advertising,
ocomeni 75:08eff6258e1b 297 * scanning or connection initiation */
ocomeni 75:08eff6258e1b 298 void SMDevice::on_timeout(const Gap::TimeoutSource_t source)
ocomeni 75:08eff6258e1b 299 {
ocomeni 103:7b566b522427 300 dbg_printf(LOG, "Unexpected timeout - aborting\r\n");
ocomeni 75:08eff6258e1b 301 _event_queue.break_dispatch();
ocomeni 75:08eff6258e1b 302 }
ocomeni 75:08eff6258e1b 303
ocomeni 75:08eff6258e1b 304 /** Schedule processing of events from the BLE in the event queue. */
ocomeni 75:08eff6258e1b 305 void SMDevice::schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
ocomeni 75:08eff6258e1b 306 {
ocomeni 75:08eff6258e1b 307 _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
ocomeni 75:08eff6258e1b 308 };
ocomeni 75:08eff6258e1b 309
ocomeni 76:6afda865fbf8 310 /** Echo received data back */
ocomeni 76:6afda865fbf8 311 void SMDevice::EchoBleUartReceived()
ocomeni 76:6afda865fbf8 312 {
ocomeni 76:6afda865fbf8 313 uart->writeString(buffer);
ocomeni 76:6afda865fbf8 314 uart->writeString("\n"); //flushes uart output buffer and sends data
ocomeni 76:6afda865fbf8 315 }
ocomeni 76:6afda865fbf8 316
ocomeni 76:6afda865fbf8 317
ocomeni 79:a2187bbfa407 318 /** Send data aynchronously using BLE */
ocomeni 120:779b74689747 319 void SMDevice::sendBLEUartData(const uint8_t * buf, int len)
ocomeni 79:a2187bbfa407 320 {
ocomeni 113:888e262ff0a9 321 //gapState.connected
ocomeni 113:888e262ff0a9 322 if(isConnected){
ocomeni 120:779b74689747 323 uart->write(buf, len);
ocomeni 120:779b74689747 324 //uart->writeString("\n"); //flushes uart output buffer and sends data
ocomeni 79:a2187bbfa407 325 }
ocomeni 113:888e262ff0a9 326 else
ocomeni 113:888e262ff0a9 327 {
ocomeni 113:888e262ff0a9 328 dbg_printf(LOG, "BLE not connected\r\n");
ocomeni 113:888e262ff0a9 329 }
ocomeni 79:a2187bbfa407 330 }
ocomeni 79:a2187bbfa407 331
ocomeni 79:a2187bbfa407 332
ocomeni 76:6afda865fbf8 333 /**
ocomeni 79:a2187bbfa407 334 * This callback allows the UARTService to receive updates.
ocomeni 76:6afda865fbf8 335 *
ocomeni 76:6afda865fbf8 336 * @param[in] params
ocomeni 76:6afda865fbf8 337 * Information about the characterisitc being updated.
ocomeni 76:6afda865fbf8 338 */
ocomeni 76:6afda865fbf8 339 void SMDevice::onDataWrittenCallback(const GattWriteCallbackParams *params) {
ocomeni 76:6afda865fbf8 340 if ((uart != NULL) && (params->handle == uart->getTXCharacteristicHandle())) {
ocomeni 76:6afda865fbf8 341 uint16_t bytesRead = params->len;
ocomeni 76:6afda865fbf8 342
ocomeni 103:7b566b522427 343 dbg_printf(LOG, "received %u bytes\n\r ", bytesRead);
ocomeni 76:6afda865fbf8 344
ocomeni 76:6afda865fbf8 345 if(bytesRead >= 255){
ocomeni 103:7b566b522427 346 dbg_printf(LOG, "Overflow command %u n\r ", bytesRead);
ocomeni 76:6afda865fbf8 347 bytesRead = 255;
ocomeni 76:6afda865fbf8 348 }
ocomeni 76:6afda865fbf8 349
ocomeni 76:6afda865fbf8 350 unsigned index = 0;
ocomeni 76:6afda865fbf8 351 for (; index < bytesRead; index++) {
ocomeni 76:6afda865fbf8 352 buffer[index] = params->data[index];
ocomeni 76:6afda865fbf8 353 }
ocomeni 76:6afda865fbf8 354
ocomeni 76:6afda865fbf8 355 buffer[index++] = 0;
ocomeni 120:779b74689747 356 at_data_resp = new ble_at_msg_t;
ocomeni 120:779b74689747 357 at_data_resp->dataLen = params->len;
ocomeni 121:ac4f59839e4f 358 // first set buffer to zeroes
ocomeni 121:ac4f59839e4f 359 //memset(at_data_resp->buffer, 0x00, sizeof(at_data_resp->buffer));
ocomeni 120:779b74689747 360 memcpy(at_data_resp->buffer, params->data, params->len);
ocomeni 121:ac4f59839e4f 361 at_data_resp->buffer[params->len] = NULL;
ocomeni 121:ac4f59839e4f 362 at_data_resp->at_resp = AT_BLE_RESPONSE;
ocomeni 121:ac4f59839e4f 363 dbg_printf(LOG, "Data : %s : len = %d",(char *)at_data_resp->buffer, at_data_resp->dataLen);
ocomeni 103:7b566b522427 364 dbg_printf(LOG, "\r\n");
ocomeni 121:ac4f59839e4f 365 dbg_printf(LOG, "Data : %s : len = %d",buffer, params->len);
ocomeni 121:ac4f59839e4f 366 dbg_printf(LOG, "\r\n");
ocomeni 121:ac4f59839e4f 367 /* directly queue received data */
ocomeni 121:ac4f59839e4f 368 _event_queue.call(this, &SMDevice::sendATresponseBytes, AT_BLE_RESPONSE);
ocomeni 76:6afda865fbf8 369 /* start echo in 50 ms */
ocomeni 76:6afda865fbf8 370 _event_queue.call_in(50, this, &SMDevice::EchoBleUartReceived);
ocomeni 76:6afda865fbf8 371 //_event_queue.call(EchoBleUartReceived);
ocomeni 76:6afda865fbf8 372
ocomeni 76:6afda865fbf8 373 }
ocomeni 76:6afda865fbf8 374 }
ocomeni 79:a2187bbfa407 375
ocomeni 79:a2187bbfa407 376
ocomeni 79:a2187bbfa407 377
ocomeni 79:a2187bbfa407 378
ocomeni 75:08eff6258e1b 379 /** Blink LED to show we're running */
ocomeni 75:08eff6258e1b 380 void SMDevice::blink(void)
ocomeni 75:08eff6258e1b 381 {
ocomeni 75:08eff6258e1b 382 _led1 = !_led1;
ocomeni 75:08eff6258e1b 383 }
ocomeni 75:08eff6258e1b 384
ocomeni 75:08eff6258e1b 385
ocomeni 77:0b505d1e15f4 386 void SMDevice::reportGapState()
ocomeni 77:0b505d1e15f4 387 {
ocomeni 113:888e262ff0a9 388 //Gap::GapState_t gapState = _ble.gap().getState();
ocomeni 77:0b505d1e15f4 389 char connStr[20] = " Not Connected ";
ocomeni 77:0b505d1e15f4 390 char advStr[20] = " Not Advertising ";
ocomeni 113:888e262ff0a9 391 //char devName[20] = "";
ocomeni 113:888e262ff0a9 392 //if(gapState.advertising){
ocomeni 113:888e262ff0a9 393 if(_ble.gap().isAdvertisingActive(ble::LEGACY_ADVERTISING_HANDLE)){
ocomeni 77:0b505d1e15f4 394 strncpy(advStr, " Advertising ", 20);
ocomeni 77:0b505d1e15f4 395 }
ocomeni 113:888e262ff0a9 396 if(isConnected){
ocomeni 77:0b505d1e15f4 397 strncpy(connStr, " Connected ", 20);
ocomeni 77:0b505d1e15f4 398 }
ocomeni 103:7b566b522427 399 dbg_printf(LOG, "\n Advertising Status = %s\n Connection Status = %s\n", advStr, connStr);
ocomeni 77:0b505d1e15f4 400
ocomeni 77:0b505d1e15f4 401 }
ocomeni 77:0b505d1e15f4 402
ocomeni 77:0b505d1e15f4 403
ocomeni 75:08eff6258e1b 404 /** A peripheral device will advertise, accept the connection and request
ocomeni 75:08eff6258e1b 405 * a change in link security. */
ocomeni 118:8df0e9c2ee3f 406 SMDevicePeripheral::SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address,
ocomeni 118:8df0e9c2ee3f 407 MemoryPool<at_ble_msg_t, PQDSZ_BLE> *aT2BleDatamPool,
ocomeni 118:8df0e9c2ee3f 408 Queue<at_ble_msg_t, PQDSZ_BLE> *aT2BleDataQueue,
ocomeni 118:8df0e9c2ee3f 409 MemoryPool<ble_at_msg_t, PQDSZ_BLE> *ble2ATDatamPool,
ocomeni 118:8df0e9c2ee3f 410 Queue<ble_at_msg_t, PQDSZ_BLE> *ble2ATDataQueue,
ocomeni 118:8df0e9c2ee3f 411 ble_config_t *ble_config)
ocomeni 118:8df0e9c2ee3f 412 : SMDevice(ble, event_queue, peer_address,
ocomeni 118:8df0e9c2ee3f 413 aT2BleDatamPool, aT2BleDataQueue,
ocomeni 118:8df0e9c2ee3f 414 ble2ATDatamPool, ble2ATDataQueue,
ocomeni 118:8df0e9c2ee3f 415 ble_config) { }
ocomeni 75:08eff6258e1b 416
ocomeni 75:08eff6258e1b 417 void SMDevicePeripheral::start()
ocomeni 75:08eff6258e1b 418 {
ocomeni 75:08eff6258e1b 419 /* Set up and start advertising */
ocomeni 75:08eff6258e1b 420
ocomeni 75:08eff6258e1b 421 ble_error_t error;
ocomeni 75:08eff6258e1b 422 GapAdvertisingData advertising_data;
ocomeni 75:08eff6258e1b 423
ocomeni 75:08eff6258e1b 424 /* add advertising flags */
ocomeni 75:08eff6258e1b 425 advertising_data.addFlags(GapAdvertisingData::LE_GENERAL_DISCOVERABLE
ocomeni 75:08eff6258e1b 426 | GapAdvertisingData::BREDR_NOT_SUPPORTED);
ocomeni 75:08eff6258e1b 427
ocomeni 75:08eff6258e1b 428 /* add device name */
ocomeni 75:08eff6258e1b 429 advertising_data.addData(
ocomeni 75:08eff6258e1b 430 GapAdvertisingData::COMPLETE_LOCAL_NAME,
ocomeni 116:2296cf274661 431 (const uint8_t *)ble_config->deviceName,
ocomeni 116:2296cf274661 432 strlen(ble_config->deviceName)
ocomeni 76:6afda865fbf8 433 );
ocomeni 76:6afda865fbf8 434 /* Setup primary service */
ocomeni 76:6afda865fbf8 435 uart = new UARTService(_ble);
ocomeni 76:6afda865fbf8 436
ocomeni 75:08eff6258e1b 437
ocomeni 76:6afda865fbf8 438 /* add device name */
ocomeni 76:6afda865fbf8 439 error = advertising_data.addData(
ocomeni 76:6afda865fbf8 440 GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS ,
ocomeni 76:6afda865fbf8 441 (const uint8_t *)UARTServiceUUID_reversed,
ocomeni 76:6afda865fbf8 442 sizeof(sizeof(UARTServiceUUID_reversed))
ocomeni 76:6afda865fbf8 443 );
ocomeni 76:6afda865fbf8 444 /* setup advertising */
ocomeni 76:6afda865fbf8 445 //error = _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ocomeni 76:6afda865fbf8 446 //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
ocomeni 76:6afda865fbf8 447 //error = _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
ocomeni 76:6afda865fbf8 448 /* set up the services that can be discovered */
ocomeni 76:6afda865fbf8 449 //error = _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
ocomeni 76:6afda865fbf8 450
ocomeni 76:6afda865fbf8 451
ocomeni 76:6afda865fbf8 452 //error = _ble.gap().setAdvertisingPayload(advertising_data);
ocomeni 75:08eff6258e1b 453
ocomeni 75:08eff6258e1b 454 if (error) {
ocomeni 103:7b566b522427 455 dbg_printf(LOG, "Error during Gap::setAdvertisingPayload\r\n");
ocomeni 75:08eff6258e1b 456 return;
ocomeni 75:08eff6258e1b 457 }
ocomeni 75:08eff6258e1b 458
ocomeni 75:08eff6258e1b 459 /* advertise to everyone */
ocomeni 75:08eff6258e1b 460 _ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ocomeni 75:08eff6258e1b 461 /* how many milliseconds between advertisements, lower interval
ocomeni 75:08eff6258e1b 462 * increases the chances of being seen at the cost of more power */
ocomeni 76:6afda865fbf8 463 //_ble.gap().setAdvertisingInterval(20);
ocomeni 76:6afda865fbf8 464 //_ble.gap().setAdvertisingTimeout(0);
ocomeni 116:2296cf274661 465 _ble.gap().setAdvertisingInterval(ble_config->advInterval); /* setting in ble_config */
ocomeni 116:2296cf274661 466 _ble.gap().setAdvertisingTimeout(ble_config->advTimeout); /* setting in ble_config */
ocomeni 75:08eff6258e1b 467
ocomeni 113:888e262ff0a9 468 error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
ocomeni 75:08eff6258e1b 469
ocomeni 75:08eff6258e1b 470 if (error) {
ocomeni 103:7b566b522427 471 dbg_printf(LOG, "Error during Gap::startAdvertising.\r\n");
ocomeni 75:08eff6258e1b 472 return;
ocomeni 75:08eff6258e1b 473 }
ocomeni 75:08eff6258e1b 474
ocomeni 103:7b566b522427 475 dbg_printf(LOG, "Please connect to device\r\n");
ocomeni 75:08eff6258e1b 476
ocomeni 75:08eff6258e1b 477 /** This tells the stack to generate a pairingRequest event
ocomeni 75:08eff6258e1b 478 * which will require this application to respond before pairing
ocomeni 75:08eff6258e1b 479 * can proceed. Setting it to false will automatically accept
ocomeni 75:08eff6258e1b 480 * pairing. */
ocomeni 75:08eff6258e1b 481 _ble.securityManager().setPairingRequestAuthorisation(true);
ocomeni 75:08eff6258e1b 482 }
ocomeni 75:08eff6258e1b 483
ocomeni 75:08eff6258e1b 484 /** This is called by Gap to notify the application we connected,
ocomeni 75:08eff6258e1b 485 * in our case it immediately requests a change in link security */
ocomeni 75:08eff6258e1b 486 void SMDevicePeripheral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
ocomeni 75:08eff6258e1b 487 {
ocomeni 75:08eff6258e1b 488 ble_error_t error;
ocomeni 75:08eff6258e1b 489
ocomeni 75:08eff6258e1b 490 /* remember the device that connects to us now so we can connect to it
ocomeni 75:08eff6258e1b 491 * during the next demonstration */
ocomeni 75:08eff6258e1b 492 memcpy(_peer_address, connection_event->peerAddr, sizeof(_peer_address));
ocomeni 75:08eff6258e1b 493
ocomeni 103:7b566b522427 494 dbg_printf(LOG, "Connected to: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
ocomeni 75:08eff6258e1b 495 _peer_address[5], _peer_address[4], _peer_address[3],
ocomeni 75:08eff6258e1b 496 _peer_address[2], _peer_address[1], _peer_address[0]);
ocomeni 75:08eff6258e1b 497
ocomeni 75:08eff6258e1b 498 /* store the handle for future Security Manager requests */
ocomeni 75:08eff6258e1b 499 _handle = connection_event->handle;
ocomeni 75:08eff6258e1b 500
ocomeni 75:08eff6258e1b 501 /* Request a change in link security. This will be done
ocomeni 75:08eff6258e1b 502 * indirectly by asking the master of the connection to
ocomeni 75:08eff6258e1b 503 * change it. Depending on circumstances different actions
ocomeni 75:08eff6258e1b 504 * may be taken by the master which will trigger events
ocomeni 75:08eff6258e1b 505 * which the applications should deal with. */
ocomeni 75:08eff6258e1b 506 error = _ble.securityManager().setLinkSecurity(
ocomeni 75:08eff6258e1b 507 _handle,
ocomeni 75:08eff6258e1b 508 SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM
ocomeni 75:08eff6258e1b 509 );
ocomeni 75:08eff6258e1b 510
ocomeni 75:08eff6258e1b 511 if (error) {
ocomeni 103:7b566b522427 512 dbg_printf(LOG, "Error during SM::setLinkSecurity %d\r\n", error);
ocomeni 75:08eff6258e1b 513 return;
ocomeni 75:08eff6258e1b 514 }
ocomeni 103:7b566b522427 515 dbg_printf(LOG, "SM::setLinkSecurity setup\r\n");
ocomeni 113:888e262ff0a9 516 isConnected = true;
ocomeni 120:779b74689747 517 _event_queue.call(this, &SMDevicePeripheral::setNextCommand, BLE_CMD_CONNECT);
ocomeni 75:08eff6258e1b 518 }
ocomeni 75:08eff6258e1b 519
ocomeni 77:0b505d1e15f4 520 void SMDevicePeripheral::stopAdvertising()
ocomeni 77:0b505d1e15f4 521 {
ocomeni 77:0b505d1e15f4 522 if (_ble.hasInitialized()) {
ocomeni 77:0b505d1e15f4 523 ble_error_t error;
ocomeni 113:888e262ff0a9 524 error = _ble.gap().stopAdvertising(ble::LEGACY_ADVERTISING_HANDLE);;
ocomeni 77:0b505d1e15f4 525 if(error){
ocomeni 103:7b566b522427 526 dbg_printf(LOG, " Error stopping advertising...\r\n");
ocomeni 77:0b505d1e15f4 527 return;
ocomeni 77:0b505d1e15f4 528 }
ocomeni 103:7b566b522427 529 dbg_printf(LOG, "Stopping advertising...\r\n");
ocomeni 77:0b505d1e15f4 530 //_event_queue.break_dispatch();
ocomeni 77:0b505d1e15f4 531 }
ocomeni 77:0b505d1e15f4 532 }
ocomeni 77:0b505d1e15f4 533 void SMDevicePeripheral::startAdvertising()
ocomeni 77:0b505d1e15f4 534 {
ocomeni 77:0b505d1e15f4 535 if (_ble.hasInitialized()) {
ocomeni 77:0b505d1e15f4 536 ble_error_t error;
ocomeni 113:888e262ff0a9 537 error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
ocomeni 77:0b505d1e15f4 538 if(error){
ocomeni 103:7b566b522427 539 dbg_printf(LOG, " Error Restarting advertising...\r\n");
ocomeni 77:0b505d1e15f4 540 return;
ocomeni 77:0b505d1e15f4 541 }
ocomeni 103:7b566b522427 542 dbg_printf(LOG, "Restarting advertising...\r\n");
ocomeni 77:0b505d1e15f4 543 //_event_queue.break_dispatch();
ocomeni 77:0b505d1e15f4 544 }
ocomeni 77:0b505d1e15f4 545 }
ocomeni 77:0b505d1e15f4 546
ocomeni 77:0b505d1e15f4 547
ocomeni 121:ac4f59839e4f 548 void SMDevicePeripheral::sendConnectionResponses()
ocomeni 121:ac4f59839e4f 549 {
ocomeni 121:ac4f59839e4f 550 // send ACL Connected +UUBTACLC
ocomeni 121:ac4f59839e4f 551 at_data_resp = new ble_at_msg_t;
ocomeni 121:ac4f59839e4f 552 char * respStr = (char *)at_data_resp->buffer;
ocomeni 121:ac4f59839e4f 553 sprintf(respStr, "\r\n+UUBTACLC:%d,%d,%02X%02X%02X%02X%02X%02X\r\n",
ocomeni 121:ac4f59839e4f 554 DEFAULT_BTLE_CHANNEL, GATT_TYPE,_peer_address[5] ,_peer_address[4],
ocomeni 121:ac4f59839e4f 555 _peer_address[3],_peer_address[2],_peer_address[1],_peer_address[0]);
ocomeni 121:ac4f59839e4f 556 at_data_resp->dataLen = strlen(respStr); // get bytes total
ocomeni 121:ac4f59839e4f 557 sendATresponseBytes(AT_BLE_EVENT);
ocomeni 121:ac4f59839e4f 558
ocomeni 121:ac4f59839e4f 559 // send +UUDPC
ocomeni 121:ac4f59839e4f 560 at_data_resp = new ble_at_msg_t;
ocomeni 121:ac4f59839e4f 561 respStr = (char *)at_data_resp->buffer;
ocomeni 121:ac4f59839e4f 562 sprintf(respStr, "\r\n+UUDPC:%d,%d,%d,%02X%02X%02X%02X%02X%02X,%d\r\n",
ocomeni 121:ac4f59839e4f 563 BTLE_PEER_HANDLE, BLE_CONNECTION, BLE_UUID_PROFILE,_peer_address[5] ,
ocomeni 121:ac4f59839e4f 564 _peer_address[4], _peer_address[3],_peer_address[2],_peer_address[1],
ocomeni 121:ac4f59839e4f 565 _peer_address[0], BLE_FRAME_SIZE);
ocomeni 121:ac4f59839e4f 566 at_data_resp->dataLen = strlen(respStr); // get bytes total
ocomeni 121:ac4f59839e4f 567 sendATresponseBytes(AT_BLE_EVENT);
ocomeni 121:ac4f59839e4f 568
ocomeni 121:ac4f59839e4f 569 // send connect event
ocomeni 121:ac4f59839e4f 570 at_data_resp = new ble_at_msg_t;
ocomeni 121:ac4f59839e4f 571 at_data_resp->dataLen = 10; // 10 bytes total
ocomeni 121:ac4f59839e4f 572 int idx = 0;
ocomeni 121:ac4f59839e4f 573 // connect type BLE = 0x01
ocomeni 121:ac4f59839e4f 574 at_data_resp->buffer[idx++] = 0x01;
ocomeni 121:ac4f59839e4f 575 // Serial Port Service BLE profile = 0x0E (14)
ocomeni 121:ac4f59839e4f 576 at_data_resp->buffer[idx++] = 0x0E;
ocomeni 121:ac4f59839e4f 577 // copy peer device address
ocomeni 121:ac4f59839e4f 578 memcpy(&at_data_resp->buffer[idx], _peer_address, sizeof(_peer_address));
ocomeni 121:ac4f59839e4f 579 idx+=sizeof(_peer_address);
ocomeni 121:ac4f59839e4f 580 // frame size 0x0166
ocomeni 121:ac4f59839e4f 581 at_data_resp->buffer[idx++] = 0x01;
ocomeni 121:ac4f59839e4f 582 at_data_resp->buffer[idx++] = 0x66;
ocomeni 121:ac4f59839e4f 583 sendATresponseBytes(BLE_CONNECT_EVENT);
ocomeni 121:ac4f59839e4f 584 }
ocomeni 121:ac4f59839e4f 585
ocomeni 121:ac4f59839e4f 586
ocomeni 121:ac4f59839e4f 587 void SMDevicePeripheral::sendDisconnectionResponses()
ocomeni 121:ac4f59839e4f 588 {
ocomeni 121:ac4f59839e4f 589 // send ACL disconnected +UUBTACLD
ocomeni 121:ac4f59839e4f 590 at_data_resp = new ble_at_msg_t;
ocomeni 121:ac4f59839e4f 591 char * respStr = (char *)at_data_resp->buffer;
ocomeni 121:ac4f59839e4f 592 sprintf(respStr, "\r\n+UUBTACLD:%d\r\n", DEFAULT_BTLE_CHANNEL);
ocomeni 121:ac4f59839e4f 593 at_data_resp->dataLen = strlen(respStr); // get bytes total
ocomeni 121:ac4f59839e4f 594 sendATresponseBytes(AT_BLE_EVENT);
ocomeni 121:ac4f59839e4f 595
ocomeni 121:ac4f59839e4f 596 // send +UUDPD
ocomeni 121:ac4f59839e4f 597 at_data_resp = new ble_at_msg_t;
ocomeni 121:ac4f59839e4f 598 respStr = (char *)at_data_resp->buffer;
ocomeni 121:ac4f59839e4f 599 sprintf(respStr, "\r\n+UUDPD:%d\r\n", BTLE_PEER_HANDLE);
ocomeni 121:ac4f59839e4f 600 at_data_resp->dataLen = strlen(respStr); // get bytes total
ocomeni 121:ac4f59839e4f 601 sendATresponseBytes(AT_BLE_EVENT);
ocomeni 121:ac4f59839e4f 602
ocomeni 121:ac4f59839e4f 603 // send connect event
ocomeni 121:ac4f59839e4f 604 at_data_resp = new ble_at_msg_t;
ocomeni 121:ac4f59839e4f 605 sendATresponseBytes(BLE_DISCONNECT_EVENT);
ocomeni 121:ac4f59839e4f 606 }
ocomeni 121:ac4f59839e4f 607
ocomeni 123:a49e9ffbaca6 608
ocomeni 123:a49e9ffbaca6 609
ocomeni 119:8d939a902333 610 void SMDevicePeripheral::processQueues()
ocomeni 119:8d939a902333 611 {
ocomeni 119:8d939a902333 612 dequeueATdataResponse();
ocomeni 119:8d939a902333 613 switch(bleCmd)
ocomeni 119:8d939a902333 614 {
ocomeni 119:8d939a902333 615 case BLE_CMD_NONE:
ocomeni 119:8d939a902333 616 break;
ocomeni 119:8d939a902333 617 case BLE_CMD_CONFIG:
ocomeni 119:8d939a902333 618 _aT2BleDatamPool->free(data_msg);
ocomeni 119:8d939a902333 619 bleCmd = BLE_CMD_NONE;
ocomeni 119:8d939a902333 620 break;
ocomeni 119:8d939a902333 621 case BLE_CMD_CONNECT:
ocomeni 121:ac4f59839e4f 622 sendConnectionResponses();
ocomeni 119:8d939a902333 623 bleCmd = BLE_CMD_NONE;
ocomeni 119:8d939a902333 624 break;
ocomeni 119:8d939a902333 625 case BLE_CMD_DISCONNECT:
ocomeni 121:ac4f59839e4f 626 {
ocomeni 121:ac4f59839e4f 627 sendDisconnectionResponses();
ocomeni 119:8d939a902333 628 bleCmd = BLE_CMD_NONE;
ocomeni 119:8d939a902333 629 break;
ocomeni 121:ac4f59839e4f 630 }
ocomeni 123:a49e9ffbaca6 631 case BLE_CMD_MAC_ADDR:
ocomeni 123:a49e9ffbaca6 632 {
ocomeni 123:a49e9ffbaca6 633 // send BLE MAC_ADDR
ocomeni 123:a49e9ffbaca6 634 _aT2BleDatamPool->free(data_msg);
ocomeni 123:a49e9ffbaca6 635 at_data_resp = new ble_at_msg_t;
ocomeni 123:a49e9ffbaca6 636 char * respStr = (char *)at_data_resp->buffer;
ocomeni 123:a49e9ffbaca6 637 /* print device address */
ocomeni 123:a49e9ffbaca6 638 Gap::AddressType_t addr_type;
ocomeni 123:a49e9ffbaca6 639 Gap::Address_t addr;
ocomeni 123:a49e9ffbaca6 640 _ble.gap().getAddress(&addr_type, addr);
ocomeni 123:a49e9ffbaca6 641 //dbg_printf(LOG, "Device address: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
ocomeni 123:a49e9ffbaca6 642 // addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
ocomeni 124:eae4512b131b 643 sprintf(respStr, "\r\n%s%d,%02X%02X%02X%02X%02X%02XOK\r\n", LOCAL_ADDRESS_RESP
ocomeni 123:a49e9ffbaca6 644 , BLE_IF_ID
ocomeni 123:a49e9ffbaca6 645 , addr[5]
ocomeni 123:a49e9ffbaca6 646 , addr[4]
ocomeni 123:a49e9ffbaca6 647 , addr[3]
ocomeni 123:a49e9ffbaca6 648 , addr[2]
ocomeni 123:a49e9ffbaca6 649 , addr[1]
ocomeni 123:a49e9ffbaca6 650 , addr[0]
ocomeni 123:a49e9ffbaca6 651 );
ocomeni 123:a49e9ffbaca6 652 at_data_resp->dataLen = strlen(respStr); // get bytes total
ocomeni 123:a49e9ffbaca6 653 sendATresponseBytes(AT_BLE_MAC_RESP);
ocomeni 123:a49e9ffbaca6 654 bleCmd = BLE_CMD_NONE;
ocomeni 123:a49e9ffbaca6 655 break;
ocomeni 123:a49e9ffbaca6 656 }
ocomeni 123:a49e9ffbaca6 657 case BLE_CMD_DEVICE_NAME:
ocomeni 123:a49e9ffbaca6 658 {
ocomeni 123:a49e9ffbaca6 659 // send BLE_CMD_DEVICE_NAME
ocomeni 123:a49e9ffbaca6 660 _aT2BleDatamPool->free(data_msg);
ocomeni 123:a49e9ffbaca6 661 at_data_resp = new ble_at_msg_t;
ocomeni 123:a49e9ffbaca6 662 char * respStr = (char *)at_data_resp->buffer;
ocomeni 124:eae4512b131b 663 sprintf(respStr, "\r\n%s%sOK\r\n", BLE_DEVICE_NAME_RESP, ble_config->deviceName);
ocomeni 123:a49e9ffbaca6 664 at_data_resp->dataLen = strlen(respStr); // get bytes total
ocomeni 123:a49e9ffbaca6 665 sendATresponseBytes(AT_BLE_NAME_RESP);
ocomeni 123:a49e9ffbaca6 666 bleCmd = BLE_CMD_NONE;
ocomeni 123:a49e9ffbaca6 667 break;
ocomeni 123:a49e9ffbaca6 668 }
ocomeni 119:8d939a902333 669 case BLE_CMD_SEND_RX_DATA_2AT:
ocomeni 120:779b74689747 670 sendATresponseBytes(AT_BLE_RESPONSE);
ocomeni 119:8d939a902333 671 bleCmd = BLE_CMD_NONE;
ocomeni 119:8d939a902333 672 break;
ocomeni 119:8d939a902333 673 case BLE_CMD_SEND_AT_DATA_2BLE:
ocomeni 120:779b74689747 674 sendBLEUartData(data_msg->buffer, data_msg->dataLen);
ocomeni 119:8d939a902333 675 _aT2BleDatamPool->free(data_msg);
ocomeni 119:8d939a902333 676 bleCmd = BLE_CMD_NONE;
ocomeni 119:8d939a902333 677 break;
ocomeni 119:8d939a902333 678 default:
ocomeni 119:8d939a902333 679 _aT2BleDatamPool->free(data_msg);
ocomeni 119:8d939a902333 680 bleCmd = BLE_CMD_NONE;
ocomeni 119:8d939a902333 681 break;
ocomeni 119:8d939a902333 682 }
ocomeni 119:8d939a902333 683
ocomeni 119:8d939a902333 684 }
ocomeni 119:8d939a902333 685
ocomeni 119:8d939a902333 686
ocomeni 119:8d939a902333 687 bool SMDevicePeripheral::queueBleDataResponse(ble_at_msg_t at_resp)
ocomeni 119:8d939a902333 688 {
ocomeni 119:8d939a902333 689 ble_at_msg_t *atData = _ble2ATDatamPool->alloc();
ocomeni 119:8d939a902333 690 if(atData == NULL) return false; // queue full;
ocomeni 119:8d939a902333 691 atData->at_resp = at_resp.at_resp;
ocomeni 119:8d939a902333 692 atData->dataLen = at_resp.dataLen;
ocomeni 119:8d939a902333 693 memcpy(atData->buffer, at_resp.buffer, at_resp.dataLen);
ocomeni 119:8d939a902333 694 _ble2ATDataQueue->put(atData);
ocomeni 119:8d939a902333 695 dbg_printf(LOG, "[BLE-MAN] queued data size = %d : at_resp = %d\n", at_resp.dataLen, at_resp.at_resp);
ocomeni 119:8d939a902333 696 return true;
ocomeni 119:8d939a902333 697 }
ocomeni 119:8d939a902333 698
ocomeni 119:8d939a902333 699
ocomeni 119:8d939a902333 700 bool SMDevicePeripheral::dequeueATdataResponse(){
ocomeni 119:8d939a902333 701 if(bleCmd != BLE_CMD_NONE) return false; // busy
ocomeni 119:8d939a902333 702 osEvent evt = _aT2BleDataQueue->get(0);
ocomeni 119:8d939a902333 703 if(evt.status == osEventMessage){
ocomeni 119:8d939a902333 704 data_msg = (at_ble_msg_t*)evt.value.p;
ocomeni 119:8d939a902333 705 setNextCommand(data_msg->ble_cmd);
ocomeni 119:8d939a902333 706 //_wiFi2ATDatamPool->free(data_msg);
ocomeni 119:8d939a902333 707 }
ocomeni 119:8d939a902333 708 return true;
ocomeni 119:8d939a902333 709 }
ocomeni 119:8d939a902333 710
ocomeni 120:779b74689747 711 void SMDevicePeripheral::sendATresponseBytes(at_cmd_resp_t at_cmd)
ocomeni 119:8d939a902333 712 {
ocomeni 120:779b74689747 713 //at_data_resp = new ble_at_msg_t;
ocomeni 119:8d939a902333 714 // package and send on BLE data queue
ocomeni 119:8d939a902333 715 // set string length
ocomeni 120:779b74689747 716 //at_data_resp->dataLen = len;
ocomeni 119:8d939a902333 717 // copy data
ocomeni 120:779b74689747 718 //memcpy(at_data_resp->buffer, buf, len);
ocomeni 119:8d939a902333 719 // copy response type
ocomeni 119:8d939a902333 720 at_data_resp->at_resp = at_cmd;
ocomeni 119:8d939a902333 721 bool queueResult = true;
ocomeni 119:8d939a902333 722 int wait_count = 0;
ocomeni 119:8d939a902333 723 queueResult = queueBleDataResponse(*at_data_resp);
ocomeni 119:8d939a902333 724 delete at_data_resp;
ocomeni 119:8d939a902333 725 at_data_resp = NULL;
ocomeni 119:8d939a902333 726 dbg_printf(LOG, "[BLE-MAN] sendATresponseBytes completed successfully\r\n");
ocomeni 119:8d939a902333 727 }
ocomeni 119:8d939a902333 728
ocomeni 119:8d939a902333 729 bool SMDevicePeripheral::setNextCommand(ble_cmd_t cmd)
ocomeni 119:8d939a902333 730 {
ocomeni 119:8d939a902333 731 dbg_printf(LOG, "\n [BLE-MAN] About to set next BLE manager command to %d\n", cmd);
ocomeni 119:8d939a902333 732 if(bleCmd == BLE_CMD_NONE){
ocomeni 119:8d939a902333 733 bleCmd = cmd;
ocomeni 119:8d939a902333 734 return true; // success
ocomeni 119:8d939a902333 735 }
ocomeni 119:8d939a902333 736 dbg_printf(LOG, "\n [BLE-MAN] Busy : current state = %d \n", bleCmd);
ocomeni 119:8d939a902333 737 return false; // BleManager busy
ocomeni 119:8d939a902333 738 }
ocomeni 77:0b505d1e15f4 739
ocomeni 75:08eff6258e1b 740 /** A central device will scan, connect to a peer and request pairing. */
ocomeni 75:08eff6258e1b 741
ocomeni 118:8df0e9c2ee3f 742 SMDeviceCentral::SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address,
ocomeni 118:8df0e9c2ee3f 743 MemoryPool<at_ble_msg_t, PQDSZ_BLE> *aT2BleDatamPool,
ocomeni 118:8df0e9c2ee3f 744 Queue<at_ble_msg_t, PQDSZ_BLE> *aT2BleDataQueue,
ocomeni 118:8df0e9c2ee3f 745 MemoryPool<ble_at_msg_t, PQDSZ_BLE> *ble2ATDatamPool,
ocomeni 118:8df0e9c2ee3f 746 Queue<ble_at_msg_t, PQDSZ_BLE> *ble2ATDataQueue,
ocomeni 118:8df0e9c2ee3f 747 ble_config_t *ble_config)
ocomeni 118:8df0e9c2ee3f 748 : SMDevice(ble, event_queue, peer_address,
ocomeni 118:8df0e9c2ee3f 749 aT2BleDatamPool, aT2BleDataQueue,
ocomeni 118:8df0e9c2ee3f 750 ble2ATDatamPool, ble2ATDataQueue,
ocomeni 118:8df0e9c2ee3f 751 ble_config) { };
ocomeni 75:08eff6258e1b 752
ocomeni 75:08eff6258e1b 753 void SMDeviceCentral::start()
ocomeni 75:08eff6258e1b 754 {
ocomeni 75:08eff6258e1b 755 /* start scanning and attach a callback that will handle advertisements
ocomeni 75:08eff6258e1b 756 * and scan requests responses */
ocomeni 75:08eff6258e1b 757 ble_error_t error = _ble.gap().startScan(this, &SMDeviceCentral::on_scan);
ocomeni 75:08eff6258e1b 758
ocomeni 103:7b566b522427 759 dbg_printf(LOG, "Please advertise\r\n");
ocomeni 75:08eff6258e1b 760
ocomeni 103:7b566b522427 761 dbg_printf(LOG, "Scanning for: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
ocomeni 75:08eff6258e1b 762 _peer_address[5], _peer_address[4], _peer_address[3],
ocomeni 75:08eff6258e1b 763 _peer_address[2], _peer_address[1], _peer_address[0]);
ocomeni 75:08eff6258e1b 764
ocomeni 75:08eff6258e1b 765 if (error) {
ocomeni 103:7b566b522427 766 dbg_printf(LOG, "Error during Gap::startScan %d\r\n", error);
ocomeni 75:08eff6258e1b 767 return;
ocomeni 75:08eff6258e1b 768 }
ocomeni 75:08eff6258e1b 769 }
ocomeni 75:08eff6258e1b 770
ocomeni 75:08eff6258e1b 771 /** Look at scan payload to find a peer device and connect to it */
ocomeni 75:08eff6258e1b 772 void SMDeviceCentral::on_scan(const Gap::AdvertisementCallbackParams_t *params)
ocomeni 75:08eff6258e1b 773 {
ocomeni 75:08eff6258e1b 774 /* don't bother with analysing scan result if we're already connecting */
ocomeni 75:08eff6258e1b 775 if (_is_connecting) {
ocomeni 75:08eff6258e1b 776 return;
ocomeni 75:08eff6258e1b 777 }
ocomeni 75:08eff6258e1b 778
ocomeni 75:08eff6258e1b 779 /* connect to the same device that connected to us */
ocomeni 75:08eff6258e1b 780 if (memcmp(params->peerAddr, _peer_address, sizeof(_peer_address)) == 0) {
ocomeni 75:08eff6258e1b 781
ocomeni 75:08eff6258e1b 782 ble_error_t error = _ble.gap().connect(
ocomeni 75:08eff6258e1b 783 params->peerAddr, params->peerAddrType,
ocomeni 75:08eff6258e1b 784 NULL, NULL
ocomeni 75:08eff6258e1b 785 );
ocomeni 75:08eff6258e1b 786
ocomeni 75:08eff6258e1b 787 if (error) {
ocomeni 103:7b566b522427 788 dbg_printf(LOG, "Error during Gap::connect %d\r\n", error);
ocomeni 75:08eff6258e1b 789 return;
ocomeni 75:08eff6258e1b 790 }
ocomeni 75:08eff6258e1b 791
ocomeni 103:7b566b522427 792 dbg_printf(LOG, "Connecting... ");
ocomeni 75:08eff6258e1b 793
ocomeni 75:08eff6258e1b 794 /* we may have already scan events waiting
ocomeni 75:08eff6258e1b 795 * to be processed so we need to remember
ocomeni 75:08eff6258e1b 796 * that we are already connecting and ignore them */
ocomeni 75:08eff6258e1b 797 _is_connecting = true;
ocomeni 75:08eff6258e1b 798
ocomeni 75:08eff6258e1b 799 return;
ocomeni 75:08eff6258e1b 800 }
ocomeni 75:08eff6258e1b 801 }
ocomeni 75:08eff6258e1b 802
ocomeni 75:08eff6258e1b 803 /** This is called by Gap to notify the application we connected,
ocomeni 75:08eff6258e1b 804 * in our case it immediately request pairing */
ocomeni 75:08eff6258e1b 805 void SMDeviceCentral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
ocomeni 75:08eff6258e1b 806 {
ocomeni 75:08eff6258e1b 807 ble_error_t error;
ocomeni 75:08eff6258e1b 808
ocomeni 75:08eff6258e1b 809 /* store the handle for future Security Manager requests */
ocomeni 75:08eff6258e1b 810 _handle = connection_event->handle;
ocomeni 75:08eff6258e1b 811
ocomeni 75:08eff6258e1b 812 /* in this example the local device is the master so we request pairing */
ocomeni 75:08eff6258e1b 813 error = _ble.securityManager().requestPairing(_handle);
ocomeni 75:08eff6258e1b 814
ocomeni 103:7b566b522427 815 dbg_printf(LOG, "Connected\r\n");
ocomeni 75:08eff6258e1b 816
ocomeni 75:08eff6258e1b 817 if (error) {
ocomeni 103:7b566b522427 818 dbg_printf(LOG, "Error during SM::requestPairing %d\r\n", error);
ocomeni 75:08eff6258e1b 819 return;
ocomeni 75:08eff6258e1b 820 }
ocomeni 75:08eff6258e1b 821
ocomeni 75:08eff6258e1b 822 /* upon pairing success the application will disconnect */
ocomeni 75:08eff6258e1b 823 }
ocomeni 75:08eff6258e1b 824
ocomeni 75:08eff6258e1b 825
ocomeni 75:08eff6258e1b 826
ocomeni 75:08eff6258e1b 827 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 828 bool create_filesystem()
ocomeni 75:08eff6258e1b 829 {
ocomeni 75:08eff6258e1b 830 static LittleFileSystem fs("fs");
ocomeni 75:08eff6258e1b 831
ocomeni 75:08eff6258e1b 832 /* replace this with any physical block device your board supports (like an SD card) */
ocomeni 75:08eff6258e1b 833 static HeapBlockDevice bd(4096, 256);
ocomeni 75:08eff6258e1b 834
ocomeni 75:08eff6258e1b 835 int err = bd.init();
ocomeni 75:08eff6258e1b 836
ocomeni 75:08eff6258e1b 837 if (err) {
ocomeni 75:08eff6258e1b 838 return false;
ocomeni 75:08eff6258e1b 839 }
ocomeni 75:08eff6258e1b 840
ocomeni 75:08eff6258e1b 841 err = bd.erase(0, bd.size());
ocomeni 75:08eff6258e1b 842
ocomeni 75:08eff6258e1b 843 if (err) {
ocomeni 75:08eff6258e1b 844 return false;
ocomeni 75:08eff6258e1b 845 }
ocomeni 75:08eff6258e1b 846
ocomeni 75:08eff6258e1b 847 err = fs.mount(&bd);
ocomeni 75:08eff6258e1b 848
ocomeni 75:08eff6258e1b 849 if (err) {
ocomeni 75:08eff6258e1b 850 /* Reformat if we can't mount the filesystem */
ocomeni 103:7b566b522427 851 dbg_printf(LOG, "No filesystem found, formatting...\r\n");
ocomeni 75:08eff6258e1b 852
ocomeni 75:08eff6258e1b 853 err = fs.reformat(&bd);
ocomeni 75:08eff6258e1b 854
ocomeni 75:08eff6258e1b 855 if (err) {
ocomeni 75:08eff6258e1b 856 return false;
ocomeni 75:08eff6258e1b 857 }
ocomeni 75:08eff6258e1b 858 }
ocomeni 75:08eff6258e1b 859
ocomeni 75:08eff6258e1b 860 return true;
ocomeni 75:08eff6258e1b 861 }
ocomeni 75:08eff6258e1b 862 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 863 #ifdef BLE_SECURITY_MAIN
ocomeni 75:08eff6258e1b 864 int main()
ocomeni 75:08eff6258e1b 865 {
ocomeni 75:08eff6258e1b 866 BLE& ble = BLE::Instance();
ocomeni 75:08eff6258e1b 867 events::EventQueue queue;
ocomeni 75:08eff6258e1b 868
ocomeni 75:08eff6258e1b 869 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
ocomeni 75:08eff6258e1b 870 /* if filesystem creation fails or there is no filesystem the security manager
ocomeni 75:08eff6258e1b 871 * will fallback to storing the security database in memory */
ocomeni 75:08eff6258e1b 872 if (!create_filesystem()) {
ocomeni 103:7b566b522427 873 dbg_printf(LOG, "Filesystem creation failed, will use memory storage\r\n");
ocomeni 75:08eff6258e1b 874 }
ocomeni 75:08eff6258e1b 875 #endif
ocomeni 75:08eff6258e1b 876
ocomeni 75:08eff6258e1b 877 while(1) {
ocomeni 75:08eff6258e1b 878 {
ocomeni 103:7b566b522427 879 dbg_printf(LOG, "\r\n PERIPHERAL \r\n\r\n");
ocomeni 75:08eff6258e1b 880 SMDevicePeripheral peripheral(ble, queue, peer_address);
ocomeni 75:08eff6258e1b 881 peripheral.run();
ocomeni 75:08eff6258e1b 882 }
ocomeni 75:08eff6258e1b 883
ocomeni 75:08eff6258e1b 884 {
ocomeni 103:7b566b522427 885 dbg_printf(LOG, "\r\n CENTRAL \r\n\r\n");
ocomeni 75:08eff6258e1b 886 SMDeviceCentral central(ble, queue, peer_address);
ocomeni 75:08eff6258e1b 887 central.run();
ocomeni 75:08eff6258e1b 888 }
ocomeni 75:08eff6258e1b 889 }
ocomeni 75:08eff6258e1b 890
ocomeni 75:08eff6258e1b 891 return 0;
ocomeni 75:08eff6258e1b 892 }
ocomeni 75:08eff6258e1b 893 #endif