Junichi Katsu / nRF51822

Dependencies:   nrf51-sdk

Dependents:   microbit-dal

Fork of nRF51822 by Lancaster University

Committer:
vcoubard
Date:
Mon Jan 11 10:19:19 2016 +0000
Revision:
567:e1800bd55a9e
Parent:
563:9c4b96f7be8d
Child:
568:13b23a4b1f58
Synchronized with git rev 59ced0b4
Author: Vincent Coubard
rename remainingCharacteristic member, now it is named
discoveredCharacteristic. Add doc to the discovery process and the
rationale behind discoveredCharacteristic member.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vcoubard 563:9c4b96f7be8d 1 /* mbed Microcontroller Library
vcoubard 563:9c4b96f7be8d 2 * Copyright (c) 2006-2015 ARM Limited
vcoubard 563:9c4b96f7be8d 3 *
vcoubard 563:9c4b96f7be8d 4 * Licensed under the Apache License, Version 2.0 (the "License");
vcoubard 563:9c4b96f7be8d 5 * you may not use this file except in compliance with the License.
vcoubard 563:9c4b96f7be8d 6 * You may obtain a copy of the License at
vcoubard 563:9c4b96f7be8d 7 *
vcoubard 563:9c4b96f7be8d 8 * http://www.apache.org/licenses/LICENSE-2.0
vcoubard 563:9c4b96f7be8d 9 *
vcoubard 563:9c4b96f7be8d 10 * Unless required by applicable law or agreed to in writing, software
vcoubard 563:9c4b96f7be8d 11 * distributed under the License is distributed on an "AS IS" BASIS,
vcoubard 563:9c4b96f7be8d 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
vcoubard 563:9c4b96f7be8d 13 * See the License for the specific language governing permissions and
vcoubard 563:9c4b96f7be8d 14 * limitations under the License.
vcoubard 563:9c4b96f7be8d 15 */
vcoubard 563:9c4b96f7be8d 16
vcoubard 563:9c4b96f7be8d 17 #include "nRF5xCharacteristicDescriptorDiscoverer.h"
vcoubard 563:9c4b96f7be8d 18 #include "ble_err.h"
vcoubard 563:9c4b96f7be8d 19 #include "mbed-drivers/mbed_error.h"
vcoubard 563:9c4b96f7be8d 20 #include "ble/DiscoveredCharacteristicDescriptor.h"
vcoubard 563:9c4b96f7be8d 21
vcoubard 563:9c4b96f7be8d 22 namespace {
vcoubard 563:9c4b96f7be8d 23 void emptyDiscoveryCallback(const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t*) { }
vcoubard 563:9c4b96f7be8d 24 void emptyTerminationCallback(const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t*) { }
vcoubard 563:9c4b96f7be8d 25 }
vcoubard 563:9c4b96f7be8d 26
vcoubard 563:9c4b96f7be8d 27 nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer(size_t concurrentConnectionsCount) :
vcoubard 563:9c4b96f7be8d 28 maximumConcurrentConnectionsCount(concurrentConnectionsCount),
vcoubard 563:9c4b96f7be8d 29 discoveryRunning(new Discovery[concurrentConnectionsCount]) {
vcoubard 563:9c4b96f7be8d 30
vcoubard 563:9c4b96f7be8d 31 }
vcoubard 563:9c4b96f7be8d 32
vcoubard 563:9c4b96f7be8d 33 nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() {
vcoubard 563:9c4b96f7be8d 34 delete [] discoveryRunning;
vcoubard 563:9c4b96f7be8d 35 }
vcoubard 563:9c4b96f7be8d 36
vcoubard 563:9c4b96f7be8d 37 ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch(
vcoubard 563:9c4b96f7be8d 38 const DiscoveredCharacteristic& characteristic,
vcoubard 563:9c4b96f7be8d 39 const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
vcoubard 563:9c4b96f7be8d 40 const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
vcoubard 563:9c4b96f7be8d 41 ) {
vcoubard 563:9c4b96f7be8d 42 Gap::Handle_t connHandle = characteristic.getConnectionHandle();
vcoubard 563:9c4b96f7be8d 43 // it is ok to deduce that the start handle for descriptors is after
vcoubard 563:9c4b96f7be8d 44 // the characteristic declaration and the characteristic value declaration
vcoubard 563:9c4b96f7be8d 45 // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] (3.3)
vcoubard 563:9c4b96f7be8d 46 Gap::Handle_t descriptorStartHandle = characteristic.getDeclHandle() + 2;
vcoubard 563:9c4b96f7be8d 47 Gap::Handle_t descriptorEndHandle = characteristic.getLastHandle();
vcoubard 563:9c4b96f7be8d 48
vcoubard 563:9c4b96f7be8d 49 // check if their is any descriptor to discover
vcoubard 563:9c4b96f7be8d 50 if (descriptorEndHandle < descriptorStartHandle) {
vcoubard 563:9c4b96f7be8d 51 CharacteristicDescriptorDiscovery::TerminationCallbackParams_t termParams = {
vcoubard 563:9c4b96f7be8d 52 characteristic,
vcoubard 563:9c4b96f7be8d 53 BLE_ERROR_NONE
vcoubard 563:9c4b96f7be8d 54 };
vcoubard 563:9c4b96f7be8d 55 terminationCallback.call(&termParams);
vcoubard 563:9c4b96f7be8d 56 return BLE_ERROR_NONE;
vcoubard 563:9c4b96f7be8d 57 }
vcoubard 563:9c4b96f7be8d 58
vcoubard 563:9c4b96f7be8d 59 // check if we can run this discovery
vcoubard 563:9c4b96f7be8d 60 if (isConnectionInUse(connHandle)) {
vcoubard 563:9c4b96f7be8d 61 return BLE_STACK_BUSY;
vcoubard 563:9c4b96f7be8d 62 }
vcoubard 563:9c4b96f7be8d 63
vcoubard 563:9c4b96f7be8d 64 // get a new discovery slot, if none are available, just return
vcoubard 563:9c4b96f7be8d 65 Discovery* discovery = getAvailableDiscoverySlot();
vcoubard 563:9c4b96f7be8d 66 if(discovery == NULL) {
vcoubard 563:9c4b96f7be8d 67 return BLE_STACK_BUSY;
vcoubard 563:9c4b96f7be8d 68 }
vcoubard 563:9c4b96f7be8d 69
vcoubard 563:9c4b96f7be8d 70 // try to launch the discovery
vcoubard 563:9c4b96f7be8d 71 ble_error_t err = gattc_descriptors_discover(connHandle, descriptorStartHandle, descriptorEndHandle);
vcoubard 563:9c4b96f7be8d 72 if(!err) {
vcoubard 563:9c4b96f7be8d 73 // commit the new discovery to its slot
vcoubard 563:9c4b96f7be8d 74 *discovery = Discovery(characteristic, discoveryCallback, terminationCallback);
vcoubard 563:9c4b96f7be8d 75 }
vcoubard 563:9c4b96f7be8d 76
vcoubard 563:9c4b96f7be8d 77 return err;
vcoubard 563:9c4b96f7be8d 78 }
vcoubard 563:9c4b96f7be8d 79
vcoubard 563:9c4b96f7be8d 80 bool nRF5xCharacteristicDescriptorDiscoverer::isActive(const DiscoveredCharacteristic& characteristic) const {
vcoubard 563:9c4b96f7be8d 81 return findRunningDiscovery(characteristic) != NULL;
vcoubard 563:9c4b96f7be8d 82 }
vcoubard 563:9c4b96f7be8d 83
vcoubard 563:9c4b96f7be8d 84 void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) {
vcoubard 563:9c4b96f7be8d 85 Discovery* discovery = findRunningDiscovery(characteristic);
vcoubard 563:9c4b96f7be8d 86 if(discovery) {
vcoubard 563:9c4b96f7be8d 87 discovery->onDiscovery = emptyDiscoveryCallback;
vcoubard 563:9c4b96f7be8d 88 // call terminate anyway
vcoubard 563:9c4b96f7be8d 89 discovery->terminate(BLE_ERROR_NONE);
vcoubard 563:9c4b96f7be8d 90 discovery->onTerminate = emptyTerminationCallback;
vcoubard 563:9c4b96f7be8d 91 }
vcoubard 563:9c4b96f7be8d 92 }
vcoubard 563:9c4b96f7be8d 93
vcoubard 563:9c4b96f7be8d 94 void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) {
vcoubard 563:9c4b96f7be8d 95 Discovery* discovery = findRunningDiscovery(connectionHandle);
vcoubard 563:9c4b96f7be8d 96 if(!discovery) {
vcoubard 563:9c4b96f7be8d 97 error("logic error in nRF5xCharacteristicDescriptorDiscoverer::process !!!");
vcoubard 563:9c4b96f7be8d 98 }
vcoubard 563:9c4b96f7be8d 99
vcoubard 563:9c4b96f7be8d 100 for (uint16_t i = 0; i < descriptors.count; ++i) {
vcoubard 563:9c4b96f7be8d 101 discovery->process(
vcoubard 563:9c4b96f7be8d 102 descriptors.descs[i].handle, UUID(descriptors.descs[i].uuid.uuid)
vcoubard 563:9c4b96f7be8d 103 );
vcoubard 563:9c4b96f7be8d 104 }
vcoubard 563:9c4b96f7be8d 105
vcoubard 563:9c4b96f7be8d 106 // prepare the next discovery request (if needed)
vcoubard 563:9c4b96f7be8d 107 uint16_t startHandle = descriptors.descs[descriptors.count - 1].handle + 1;
vcoubard 563:9c4b96f7be8d 108 uint16_t endHandle = discovery->characteristic.getLastHandle();
vcoubard 563:9c4b96f7be8d 109
vcoubard 563:9c4b96f7be8d 110 if(startHandle > endHandle ||
vcoubard 563:9c4b96f7be8d 111 (discovery->onDiscovery == emptyDiscoveryCallback && discovery->onTerminate == emptyTerminationCallback)) {
vcoubard 563:9c4b96f7be8d 112 terminate(connectionHandle, BLE_ERROR_NONE);
vcoubard 563:9c4b96f7be8d 113 return;
vcoubard 563:9c4b96f7be8d 114 }
vcoubard 563:9c4b96f7be8d 115
vcoubard 563:9c4b96f7be8d 116 ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
vcoubard 563:9c4b96f7be8d 117 if(err) {
vcoubard 563:9c4b96f7be8d 118 terminate(connectionHandle, err);
vcoubard 563:9c4b96f7be8d 119 return;
vcoubard 563:9c4b96f7be8d 120 }
vcoubard 563:9c4b96f7be8d 121 }
vcoubard 563:9c4b96f7be8d 122
vcoubard 563:9c4b96f7be8d 123 void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) {
vcoubard 563:9c4b96f7be8d 124 Discovery* discovery = findRunningDiscovery(handle);
vcoubard 563:9c4b96f7be8d 125 if(!discovery) {
vcoubard 563:9c4b96f7be8d 126 error("logic error in nRF5xCharacteristicDescriptorDiscoverer::process !!!");
vcoubard 563:9c4b96f7be8d 127 }
vcoubard 563:9c4b96f7be8d 128
vcoubard 563:9c4b96f7be8d 129 Discovery tmp = *discovery;
vcoubard 563:9c4b96f7be8d 130 *discovery = Discovery();
vcoubard 563:9c4b96f7be8d 131 tmp.terminate(err);
vcoubard 563:9c4b96f7be8d 132 }
vcoubard 563:9c4b96f7be8d 133
vcoubard 563:9c4b96f7be8d 134 nRF5xCharacteristicDescriptorDiscoverer::Discovery*
vcoubard 563:9c4b96f7be8d 135 nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) {
vcoubard 563:9c4b96f7be8d 136 for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) {
vcoubard 563:9c4b96f7be8d 137 if(discoveryRunning[i].characteristic == characteristic) {
vcoubard 563:9c4b96f7be8d 138 return &discoveryRunning[i];
vcoubard 563:9c4b96f7be8d 139 }
vcoubard 563:9c4b96f7be8d 140 }
vcoubard 563:9c4b96f7be8d 141 return NULL;
vcoubard 563:9c4b96f7be8d 142 }
vcoubard 563:9c4b96f7be8d 143
vcoubard 563:9c4b96f7be8d 144 nRF5xCharacteristicDescriptorDiscoverer::Discovery*
vcoubard 563:9c4b96f7be8d 145 nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) const {
vcoubard 563:9c4b96f7be8d 146 for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) {
vcoubard 563:9c4b96f7be8d 147 if(discoveryRunning[i].characteristic == characteristic) {
vcoubard 563:9c4b96f7be8d 148 return &discoveryRunning[i];
vcoubard 563:9c4b96f7be8d 149 }
vcoubard 563:9c4b96f7be8d 150 }
vcoubard 563:9c4b96f7be8d 151 return NULL;
vcoubard 563:9c4b96f7be8d 152 }
vcoubard 563:9c4b96f7be8d 153
vcoubard 563:9c4b96f7be8d 154 nRF5xCharacteristicDescriptorDiscoverer::Discovery*
vcoubard 563:9c4b96f7be8d 155 nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) {
vcoubard 563:9c4b96f7be8d 156 for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) {
vcoubard 563:9c4b96f7be8d 157 if(discoveryRunning[i].characteristic.getConnectionHandle() == handle &&
vcoubard 563:9c4b96f7be8d 158 discoveryRunning[i] != Discovery()) {
vcoubard 563:9c4b96f7be8d 159 return &discoveryRunning[i];
vcoubard 563:9c4b96f7be8d 160 }
vcoubard 563:9c4b96f7be8d 161 }
vcoubard 563:9c4b96f7be8d 162 return NULL;
vcoubard 563:9c4b96f7be8d 163 }
vcoubard 563:9c4b96f7be8d 164
vcoubard 563:9c4b96f7be8d 165 void nRF5xCharacteristicDescriptorDiscoverer::removeDiscovery(Discovery* discovery) {
vcoubard 563:9c4b96f7be8d 166 for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) {
vcoubard 563:9c4b96f7be8d 167 if(&discoveryRunning[i] == discovery) {
vcoubard 563:9c4b96f7be8d 168 discoveryRunning[i] = Discovery();
vcoubard 563:9c4b96f7be8d 169 }
vcoubard 563:9c4b96f7be8d 170 }
vcoubard 563:9c4b96f7be8d 171 }
vcoubard 563:9c4b96f7be8d 172
vcoubard 563:9c4b96f7be8d 173 nRF5xCharacteristicDescriptorDiscoverer::Discovery*
vcoubard 563:9c4b96f7be8d 174 nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() {
vcoubard 563:9c4b96f7be8d 175 for(size_t i = 0; i < maximumConcurrentConnectionsCount; ++i) {
vcoubard 563:9c4b96f7be8d 176 if(discoveryRunning[i] == Discovery()) {
vcoubard 563:9c4b96f7be8d 177 return &discoveryRunning[i];
vcoubard 563:9c4b96f7be8d 178 }
vcoubard 563:9c4b96f7be8d 179 }
vcoubard 563:9c4b96f7be8d 180 return NULL;
vcoubard 563:9c4b96f7be8d 181 }
vcoubard 563:9c4b96f7be8d 182
vcoubard 563:9c4b96f7be8d 183 bool nRF5xCharacteristicDescriptorDiscoverer::isConnectionInUse(uint16_t connHandle) {
vcoubard 563:9c4b96f7be8d 184 return findRunningDiscovery(connHandle) != NULL;
vcoubard 563:9c4b96f7be8d 185 }
vcoubard 563:9c4b96f7be8d 186
vcoubard 563:9c4b96f7be8d 187 ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_descriptors_discover(
vcoubard 563:9c4b96f7be8d 188 uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) {
vcoubard 563:9c4b96f7be8d 189
vcoubard 563:9c4b96f7be8d 190 ble_gattc_handle_range_t discoveryRange = {
vcoubard 563:9c4b96f7be8d 191 start_handle,
vcoubard 563:9c4b96f7be8d 192 end_handle
vcoubard 563:9c4b96f7be8d 193 };
vcoubard 563:9c4b96f7be8d 194 uint32_t err = sd_ble_gattc_descriptors_discover(connection_handle, &discoveryRange);
vcoubard 563:9c4b96f7be8d 195
vcoubard 563:9c4b96f7be8d 196 switch(err) {
vcoubard 563:9c4b96f7be8d 197 case NRF_SUCCESS:
vcoubard 563:9c4b96f7be8d 198 return BLE_ERROR_NONE;
vcoubard 563:9c4b96f7be8d 199 case BLE_ERROR_INVALID_CONN_HANDLE:
vcoubard 563:9c4b96f7be8d 200 return BLE_ERROR_INVALID_PARAM;
vcoubard 563:9c4b96f7be8d 201 case NRF_ERROR_INVALID_ADDR:
vcoubard 563:9c4b96f7be8d 202 return BLE_ERROR_PARAM_OUT_OF_RANGE;
vcoubard 563:9c4b96f7be8d 203 case NRF_ERROR_BUSY:
vcoubard 563:9c4b96f7be8d 204 return BLE_STACK_BUSY;
vcoubard 563:9c4b96f7be8d 205 default:
vcoubard 563:9c4b96f7be8d 206 return BLE_ERROR_UNSPECIFIED;
vcoubard 563:9c4b96f7be8d 207 }
vcoubard 563:9c4b96f7be8d 208 }