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