test

Dependencies:   nrf51-sdk

Dependents:   microbit-dal

Fork of nRF51822 by Lancaster University

Committer:
rgrover1
Date:
Thu Jul 02 09:08:44 2015 +0100
Revision:
362:6fa0d4d555f6
Parent:
361:d2405f5a4853
Child:
370:295f76db798e
Synchronized with git rev 2716309c
Author: Rohit Grover
Release 0.4.0
=============

This is a major release which introduces the GATT Client functionality. It
aligns with release 0.4.0 of BLE_API.

Enhancements
~~~~~~~~~~~~

* Introduce GattClient. This includes functionality for service-discovery,
connections, and attribute-reads and writes. You'll find a demo program for
LEDBlinker on the mbed.org Bluetooth team page to use the new APIs. Some of
the GATT client functionality hasn't been implemented yet, but the APIs have
been added.

* We've added an implementation for the abstract base class for
SecurityManager. All security related APIs have been moved into that.

* There has been a major cleanup of APIs under BLE. APIs have now been
categorized as belonging to Gap, GattServer, GattClient, or SecurityManager.
There are accessors to get references for Gap, GattServer, GattClient, and
SecurityManager. A former call to ble.setAddress(...) is now expected to be
achieved with ble.gap().setAddress(...).

* We've cleaned up our APIs, and this has resulted in dropping some APIs like
BLE::reset().

* We've also dropped GattServer::initializeGattDatabase(). THis was added at
some point to support controllers where a commit point was needed to
indicate when the application had finished constructing the GATT database.
This API would get called internally before Gap::startAdvertising(). We now
expect the underlying port to do the equivalent of initializeGattDatabase()
implicitly upon Gap::startAdvertising().

* We've added a version of Gap::disconnect() which takes a connection handle.
The previous API (which did not take a connection handle) has been
deprecated; it will still work for situations where there's only a single
active connection. We hold on to that API to allow existing code to migrate
to the new API.

Bugfixes
~~~~~~~~

* None.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 133:74079098b3c9 1 /* mbed Microcontroller Library
rgrover1 133:74079098b3c9 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 133:74079098b3c9 3 *
rgrover1 133:74079098b3c9 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 133:74079098b3c9 5 * you may not use this file except in compliance with the License.
rgrover1 133:74079098b3c9 6 * You may obtain a copy of the License at
rgrover1 133:74079098b3c9 7 *
rgrover1 133:74079098b3c9 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 133:74079098b3c9 9 *
rgrover1 133:74079098b3c9 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 133:74079098b3c9 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 133:74079098b3c9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 133:74079098b3c9 13 * See the License for the specific language governing permissions and
rgrover1 133:74079098b3c9 14 * limitations under the License.
rgrover1 133:74079098b3c9 15 */
rgrover1 133:74079098b3c9 16
rgrover1 133:74079098b3c9 17 #include "btle.h"
rgrover1 133:74079098b3c9 18 #include "pstorage.h"
rgrover1 362:6fa0d4d555f6 19
rgrover1 133:74079098b3c9 20 #include "nRF51Gap.h"
rgrover1 362:6fa0d4d555f6 21 #include "nRF51SecurityManager.h"
rgrover1 362:6fa0d4d555f6 22
rgrover1 133:74079098b3c9 23 #include "device_manager.h"
rgrover1 134:df7e7964a9c3 24 #include "btle_security.h"
rgrover1 133:74079098b3c9 25
rgrover1 147:457a129dfa5e 26 static dm_application_instance_t applicationInstance;
rgrover1 133:74079098b3c9 27 static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result);
rgrover1 133:74079098b3c9 28
rgrover1 133:74079098b3c9 29 ble_error_t
rgrover1 362:6fa0d4d555f6 30 btle_initializeSecurity(bool enableBonding,
rgrover1 362:6fa0d4d555f6 31 bool requireMITM,
rgrover1 362:6fa0d4d555f6 32 SecurityManager::SecurityIOCapabilities_t iocaps,
rgrover1 362:6fa0d4d555f6 33 const SecurityManager::Passkey_t passkey)
rgrover1 133:74079098b3c9 34 {
rgrover1 144:9d8fce4b4d5a 35 /* guard against multiple initializations */
rgrover1 144:9d8fce4b4d5a 36 static bool initialized = false;
rgrover1 144:9d8fce4b4d5a 37 if (initialized) {
rgrover1 144:9d8fce4b4d5a 38 return BLE_ERROR_NONE;
rgrover1 144:9d8fce4b4d5a 39 }
rgrover1 144:9d8fce4b4d5a 40
rgrover1 133:74079098b3c9 41 if (pstorage_init() != NRF_SUCCESS) {
rgrover1 133:74079098b3c9 42 return BLE_ERROR_UNSPECIFIED;
rgrover1 133:74079098b3c9 43 }
rgrover1 133:74079098b3c9 44
rgrover1 150:44c40836c82f 45 ret_code_t rc;
rgrover1 150:44c40836c82f 46 if (passkey) {
rgrover1 150:44c40836c82f 47 ble_opt_t opts;
rgrover1 150:44c40836c82f 48 opts.gap_opt.passkey.p_passkey = const_cast<uint8_t *>(passkey);
rgrover1 150:44c40836c82f 49 if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) {
rgrover1 150:44c40836c82f 50 switch (rc) {
rgrover1 150:44c40836c82f 51 case BLE_ERROR_INVALID_CONN_HANDLE:
rgrover1 150:44c40836c82f 52 case NRF_ERROR_INVALID_ADDR:
rgrover1 150:44c40836c82f 53 case NRF_ERROR_INVALID_PARAM:
rgrover1 150:44c40836c82f 54 default:
rgrover1 150:44c40836c82f 55 return BLE_ERROR_INVALID_PARAM;
rgrover1 150:44c40836c82f 56 case NRF_ERROR_INVALID_STATE:
rgrover1 150:44c40836c82f 57 return BLE_ERROR_INVALID_STATE;
rgrover1 150:44c40836c82f 58 case NRF_ERROR_BUSY:
rgrover1 150:44c40836c82f 59 return BLE_STACK_BUSY;
rgrover1 150:44c40836c82f 60 }
rgrover1 150:44c40836c82f 61 }
rgrover1 150:44c40836c82f 62 }
rgrover1 150:44c40836c82f 63
rgrover1 133:74079098b3c9 64 dm_init_param_t dm_init_param = {
rgrover1 133:74079098b3c9 65 .clear_persistent_data = false /* Set to true in case the module should clear all persistent data. */
rgrover1 133:74079098b3c9 66 };
rgrover1 133:74079098b3c9 67 if (dm_init(&dm_init_param) != NRF_SUCCESS) {
rgrover1 133:74079098b3c9 68 return BLE_ERROR_UNSPECIFIED;
rgrover1 133:74079098b3c9 69 }
rgrover1 133:74079098b3c9 70
rgrover1 133:74079098b3c9 71 const dm_application_param_t dm_param = {
rgrover1 133:74079098b3c9 72 .evt_handler = dm_handler,
rgrover1 133:74079098b3c9 73 .service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID,
rgrover1 133:74079098b3c9 74 .sec_param = {
rgrover1 150:44c40836c82f 75 .bond = enableBonding,/**< Perform bonding. */
rgrover1 150:44c40836c82f 76 .mitm = requireMITM, /**< Man In The Middle protection required. */
rgrover1 150:44c40836c82f 77 .io_caps = iocaps, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */
rgrover1 133:74079098b3c9 78 .oob = 0, /**< Out Of Band data available. */
rgrover1 133:74079098b3c9 79 .min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */
rgrover1 133:74079098b3c9 80 .max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */
rgrover1 133:74079098b3c9 81 .kdist_periph = {
rgrover1 133:74079098b3c9 82 .enc = 1, /**< Long Term Key and Master Identification. */
rgrover1 133:74079098b3c9 83 .id = 1, /**< Identity Resolving Key and Identity Address Information. */
rgrover1 133:74079098b3c9 84 .sign = 1, /**< Connection Signature Resolving Key. */
rgrover1 133:74079098b3c9 85 }, /**< Key distribution bitmap: keys that the peripheral device will distribute. */
rgrover1 133:74079098b3c9 86 }
rgrover1 133:74079098b3c9 87 };
rgrover1 133:74079098b3c9 88
rgrover1 143:9d73e7f9f2bf 89 if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) {
rgrover1 143:9d73e7f9f2bf 90 switch (rc) {
rgrover1 143:9d73e7f9f2bf 91 case NRF_ERROR_INVALID_STATE:
rgrover1 143:9d73e7f9f2bf 92 return BLE_ERROR_INVALID_STATE;
rgrover1 143:9d73e7f9f2bf 93 case NRF_ERROR_NO_MEM:
rgrover1 143:9d73e7f9f2bf 94 return BLE_ERROR_NO_MEM;
rgrover1 143:9d73e7f9f2bf 95 default:
rgrover1 143:9d73e7f9f2bf 96 return BLE_ERROR_UNSPECIFIED;
rgrover1 143:9d73e7f9f2bf 97 }
rgrover1 133:74079098b3c9 98 }
rgrover1 133:74079098b3c9 99
rgrover1 144:9d8fce4b4d5a 100 initialized = true;
rgrover1 143:9d73e7f9f2bf 101 return BLE_ERROR_NONE;
rgrover1 136:9bb49953de6a 102 }
rgrover1 136:9bb49953de6a 103
rgrover1 136:9bb49953de6a 104 ble_error_t
rgrover1 140:3a5282e3f30c 105 btle_purgeAllBondingState(void)
rgrover1 136:9bb49953de6a 106 {
rgrover1 136:9bb49953de6a 107 ret_code_t rc;
rgrover1 137:aafab7b0a8bd 108 if ((rc = dm_device_delete_all(&applicationInstance)) == NRF_SUCCESS) {
rgrover1 137:aafab7b0a8bd 109 return BLE_ERROR_NONE;
rgrover1 137:aafab7b0a8bd 110 }
rgrover1 136:9bb49953de6a 111
rgrover1 137:aafab7b0a8bd 112 switch (rc) {
rgrover1 137:aafab7b0a8bd 113 case NRF_ERROR_INVALID_STATE:
rgrover1 137:aafab7b0a8bd 114 return BLE_ERROR_INVALID_STATE;
rgrover1 137:aafab7b0a8bd 115 case NRF_ERROR_NO_MEM:
rgrover1 137:aafab7b0a8bd 116 return BLE_ERROR_NO_MEM;
rgrover1 137:aafab7b0a8bd 117 default:
rgrover1 137:aafab7b0a8bd 118 return BLE_ERROR_UNSPECIFIED;
rgrover1 137:aafab7b0a8bd 119 }
rgrover1 133:74079098b3c9 120 }
rgrover1 133:74079098b3c9 121
rgrover1 138:750eca573e18 122 ble_error_t
rgrover1 362:6fa0d4d555f6 123 btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP)
rgrover1 138:750eca573e18 124 {
rgrover1 141:586e146a3903 125 ret_code_t rc;
rgrover1 148:a67b1b776aab 126 dm_handle_t dmHandle = {
rgrover1 148:a67b1b776aab 127 .appl_id = applicationInstance,
rgrover1 148:a67b1b776aab 128 };
rgrover1 138:750eca573e18 129 if ((rc = dm_handle_get(connectionHandle, &dmHandle)) != NRF_SUCCESS) {
rgrover1 138:750eca573e18 130 if (rc == NRF_ERROR_NOT_FOUND) {
rgrover1 138:750eca573e18 131 return BLE_ERROR_INVALID_PARAM;
rgrover1 138:750eca573e18 132 } else {
rgrover1 138:750eca573e18 133 return BLE_ERROR_UNSPECIFIED;
rgrover1 138:750eca573e18 134 }
rgrover1 138:750eca573e18 135 }
rgrover1 138:750eca573e18 136
rgrover1 138:750eca573e18 137 if ((rc = dm_security_status_req(&dmHandle, reinterpret_cast<dm_security_status_t *>(securityStatusP))) != NRF_SUCCESS) {
rgrover1 138:750eca573e18 138 switch (rc) {
rgrover1 138:750eca573e18 139 case NRF_ERROR_INVALID_STATE:
rgrover1 138:750eca573e18 140 return BLE_ERROR_INVALID_STATE;
rgrover1 138:750eca573e18 141 case NRF_ERROR_NO_MEM:
rgrover1 138:750eca573e18 142 return BLE_ERROR_NO_MEM;
rgrover1 138:750eca573e18 143 default:
rgrover1 138:750eca573e18 144 return BLE_ERROR_UNSPECIFIED;
rgrover1 138:750eca573e18 145 }
rgrover1 138:750eca573e18 146 }
rgrover1 138:750eca573e18 147
rgrover1 138:750eca573e18 148 return BLE_ERROR_NONE;
rgrover1 138:750eca573e18 149 }
rgrover1 138:750eca573e18 150
rgrover1 133:74079098b3c9 151 ret_code_t
rgrover1 133:74079098b3c9 152 dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result)
rgrover1 133:74079098b3c9 153 {
rgrover1 133:74079098b3c9 154 switch (p_event->event_id) {
rgrover1 152:0e74b7590ab2 155 case DM_EVT_SECURITY_SETUP: /* started */ {
rgrover1 152:0e74b7590ab2 156 const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params;
rgrover1 362:6fa0d4d555f6 157 nRF51SecurityManager::getInstance().processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle,
rgrover1 362:6fa0d4d555f6 158 peerParams->bond,
rgrover1 362:6fa0d4d555f6 159 peerParams->mitm,
rgrover1 362:6fa0d4d555f6 160 (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps);
rgrover1 133:74079098b3c9 161 break;
rgrover1 152:0e74b7590ab2 162 }
rgrover1 133:74079098b3c9 163 case DM_EVT_SECURITY_SETUP_COMPLETE:
rgrover1 362:6fa0d4d555f6 164 nRF51SecurityManager::getInstance().
rgrover1 362:6fa0d4d555f6 165 processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle,
rgrover1 362:6fa0d4d555f6 166 (SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status));
rgrover1 133:74079098b3c9 167 break;
rgrover1 158:ad708a3d7ad7 168 case DM_EVT_LINK_SECURED: {
rgrover1 158:ad708a3d7ad7 169 unsigned securityMode = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.sm;
rgrover1 158:ad708a3d7ad7 170 unsigned level = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.lv;
rgrover1 362:6fa0d4d555f6 171 SecurityManager::SecurityMode_t resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS;
rgrover1 158:ad708a3d7ad7 172 switch (securityMode) {
rgrover1 158:ad708a3d7ad7 173 case 1:
rgrover1 158:ad708a3d7ad7 174 switch (level) {
rgrover1 158:ad708a3d7ad7 175 case 1:
rgrover1 362:6fa0d4d555f6 176 resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK;
rgrover1 158:ad708a3d7ad7 177 break;
rgrover1 158:ad708a3d7ad7 178 case 2:
rgrover1 362:6fa0d4d555f6 179 resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM;
rgrover1 158:ad708a3d7ad7 180 break;
rgrover1 158:ad708a3d7ad7 181 case 3:
rgrover1 362:6fa0d4d555f6 182 resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM;
rgrover1 158:ad708a3d7ad7 183 break;
rgrover1 158:ad708a3d7ad7 184 }
rgrover1 158:ad708a3d7ad7 185 break;
rgrover1 158:ad708a3d7ad7 186 case 2:
rgrover1 158:ad708a3d7ad7 187 switch (level) {
rgrover1 158:ad708a3d7ad7 188 case 1:
rgrover1 362:6fa0d4d555f6 189 resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM;
rgrover1 158:ad708a3d7ad7 190 break;
rgrover1 158:ad708a3d7ad7 191 case 2:
rgrover1 362:6fa0d4d555f6 192 resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM;
rgrover1 158:ad708a3d7ad7 193 break;
rgrover1 158:ad708a3d7ad7 194 }
rgrover1 158:ad708a3d7ad7 195 break;
rgrover1 158:ad708a3d7ad7 196 }
rgrover1 158:ad708a3d7ad7 197
rgrover1 362:6fa0d4d555f6 198 nRF51SecurityManager::getInstance().processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode);
rgrover1 133:74079098b3c9 199 break;
rgrover1 158:ad708a3d7ad7 200 }
rgrover1 133:74079098b3c9 201 case DM_EVT_DEVICE_CONTEXT_STORED:
rgrover1 362:6fa0d4d555f6 202 nRF51SecurityManager::getInstance().processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle);
rgrover1 133:74079098b3c9 203 break;
rgrover1 133:74079098b3c9 204 default:
rgrover1 133:74079098b3c9 205 break;
rgrover1 133:74079098b3c9 206 }
rgrover1 133:74079098b3c9 207
rgrover1 133:74079098b3c9 208 return NRF_SUCCESS;
rgrover1 133:74079098b3c9 209 }