No changes
Fork of nRF51822 by
source/nRF5xCharacteristicDescriptorDiscoverer.cpp@568:13b23a4b1f58, 2016-01-11 (annotated)
- Committer:
- vcoubard
- Date:
- Mon Jan 11 10:19:20 2016 +0000
- Revision:
- 568:13b23a4b1f58
- Parent:
- 563:9c4b96f7be8d
- Child:
- 569:9e72aa06ec32
Synchronized with git rev c8d826ff
Author: Vincent Coubard
Documentation of descriptor discoverer class.
Simplify the process
Who changed what in which revision?
User | Revision | Line number | New 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 | #include "nRF5xCharacteristicDescriptorDiscoverer.h" |
vcoubard | 563:9c4b96f7be8d | 17 | #include "ble_err.h" |
vcoubard | 563:9c4b96f7be8d | 18 | #include "mbed-drivers/mbed_error.h" |
vcoubard | 563:9c4b96f7be8d | 19 | #include "ble/DiscoveredCharacteristicDescriptor.h" |
vcoubard | 563:9c4b96f7be8d | 20 | |
vcoubard | 568:13b23a4b1f58 | 21 | |
vcoubard | 568:13b23a4b1f58 | 22 | nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer() : |
vcoubard | 568:13b23a4b1f58 | 23 | discoveryRunning() { |
vcoubard | 568:13b23a4b1f58 | 24 | // nothing to do |
vcoubard | 563:9c4b96f7be8d | 25 | } |
vcoubard | 563:9c4b96f7be8d | 26 | |
vcoubard | 568:13b23a4b1f58 | 27 | nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() { |
vcoubard | 568:13b23a4b1f58 | 28 | // nothing to do |
vcoubard | 563:9c4b96f7be8d | 29 | } |
vcoubard | 563:9c4b96f7be8d | 30 | |
vcoubard | 563:9c4b96f7be8d | 31 | ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch( |
vcoubard | 568:13b23a4b1f58 | 32 | const DiscoveredCharacteristic& characteristic, |
vcoubard | 563:9c4b96f7be8d | 33 | const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, |
vcoubard | 563:9c4b96f7be8d | 34 | const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback |
vcoubard | 563:9c4b96f7be8d | 35 | ) { |
vcoubard | 563:9c4b96f7be8d | 36 | Gap::Handle_t connHandle = characteristic.getConnectionHandle(); |
vcoubard | 568:13b23a4b1f58 | 37 | // it is ok to deduce that the start handle for descriptors is after |
vcoubard | 563:9c4b96f7be8d | 38 | // the characteristic declaration and the characteristic value declaration |
vcoubard | 563:9c4b96f7be8d | 39 | // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] (3.3) |
vcoubard | 563:9c4b96f7be8d | 40 | Gap::Handle_t descriptorStartHandle = characteristic.getDeclHandle() + 2; |
vcoubard | 563:9c4b96f7be8d | 41 | Gap::Handle_t descriptorEndHandle = characteristic.getLastHandle(); |
vcoubard | 563:9c4b96f7be8d | 42 | |
vcoubard | 568:13b23a4b1f58 | 43 | // check if there is any descriptor to discover |
vcoubard | 568:13b23a4b1f58 | 44 | if (descriptorEndHandle < descriptorStartHandle) { |
vcoubard | 568:13b23a4b1f58 | 45 | CharacteristicDescriptorDiscovery::TerminationCallbackParams_t termParams = { |
vcoubard | 563:9c4b96f7be8d | 46 | characteristic, |
vcoubard | 563:9c4b96f7be8d | 47 | BLE_ERROR_NONE |
vcoubard | 563:9c4b96f7be8d | 48 | }; |
vcoubard | 563:9c4b96f7be8d | 49 | terminationCallback.call(&termParams); |
vcoubard | 563:9c4b96f7be8d | 50 | return BLE_ERROR_NONE; |
vcoubard | 563:9c4b96f7be8d | 51 | } |
vcoubard | 563:9c4b96f7be8d | 52 | |
vcoubard | 563:9c4b96f7be8d | 53 | // check if we can run this discovery |
vcoubard | 568:13b23a4b1f58 | 54 | if (isConnectionInUse(connHandle)) { |
vcoubard | 563:9c4b96f7be8d | 55 | return BLE_STACK_BUSY; |
vcoubard | 563:9c4b96f7be8d | 56 | } |
vcoubard | 563:9c4b96f7be8d | 57 | |
vcoubard | 563:9c4b96f7be8d | 58 | // get a new discovery slot, if none are available, just return |
vcoubard | 563:9c4b96f7be8d | 59 | Discovery* discovery = getAvailableDiscoverySlot(); |
vcoubard | 563:9c4b96f7be8d | 60 | if(discovery == NULL) { |
vcoubard | 568:13b23a4b1f58 | 61 | return BLE_STACK_BUSY; |
vcoubard | 563:9c4b96f7be8d | 62 | } |
vcoubard | 563:9c4b96f7be8d | 63 | |
vcoubard | 568:13b23a4b1f58 | 64 | // try to launch the discovery |
vcoubard | 563:9c4b96f7be8d | 65 | ble_error_t err = gattc_descriptors_discover(connHandle, descriptorStartHandle, descriptorEndHandle); |
vcoubard | 568:13b23a4b1f58 | 66 | if(!err) { |
vcoubard | 563:9c4b96f7be8d | 67 | // commit the new discovery to its slot |
vcoubard | 563:9c4b96f7be8d | 68 | *discovery = Discovery(characteristic, discoveryCallback, terminationCallback); |
vcoubard | 563:9c4b96f7be8d | 69 | } |
vcoubard | 563:9c4b96f7be8d | 70 | |
vcoubard | 563:9c4b96f7be8d | 71 | return err; |
vcoubard | 563:9c4b96f7be8d | 72 | } |
vcoubard | 563:9c4b96f7be8d | 73 | |
vcoubard | 563:9c4b96f7be8d | 74 | bool nRF5xCharacteristicDescriptorDiscoverer::isActive(const DiscoveredCharacteristic& characteristic) const { |
vcoubard | 568:13b23a4b1f58 | 75 | for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) { |
vcoubard | 568:13b23a4b1f58 | 76 | if(discoveryRunning[i].characteristic == characteristic) { |
vcoubard | 568:13b23a4b1f58 | 77 | return true; |
vcoubard | 568:13b23a4b1f58 | 78 | } |
vcoubard | 568:13b23a4b1f58 | 79 | } |
vcoubard | 568:13b23a4b1f58 | 80 | return false; |
vcoubard | 563:9c4b96f7be8d | 81 | } |
vcoubard | 563:9c4b96f7be8d | 82 | |
vcoubard | 563:9c4b96f7be8d | 83 | void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) { |
vcoubard | 563:9c4b96f7be8d | 84 | Discovery* discovery = findRunningDiscovery(characteristic); |
vcoubard | 568:13b23a4b1f58 | 85 | if(discovery) { |
vcoubard | 563:9c4b96f7be8d | 86 | // call terminate anyway |
vcoubard | 568:13b23a4b1f58 | 87 | terminate(discovery, BLE_ERROR_NONE); |
vcoubard | 563:9c4b96f7be8d | 88 | } |
vcoubard | 563:9c4b96f7be8d | 89 | } |
vcoubard | 563:9c4b96f7be8d | 90 | |
vcoubard | 563:9c4b96f7be8d | 91 | void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) { |
vcoubard | 563:9c4b96f7be8d | 92 | Discovery* discovery = findRunningDiscovery(connectionHandle); |
vcoubard | 568:13b23a4b1f58 | 93 | // the discovery has been removed |
vcoubard | 568:13b23a4b1f58 | 94 | if(!discovery) { |
vcoubard | 568:13b23a4b1f58 | 95 | return; |
vcoubard | 563:9c4b96f7be8d | 96 | } |
vcoubard | 563:9c4b96f7be8d | 97 | |
vcoubard | 563:9c4b96f7be8d | 98 | for (uint16_t i = 0; i < descriptors.count; ++i) { |
vcoubard | 563:9c4b96f7be8d | 99 | discovery->process( |
vcoubard | 563:9c4b96f7be8d | 100 | descriptors.descs[i].handle, UUID(descriptors.descs[i].uuid.uuid) |
vcoubard | 563:9c4b96f7be8d | 101 | ); |
vcoubard | 563:9c4b96f7be8d | 102 | } |
vcoubard | 563:9c4b96f7be8d | 103 | |
vcoubard | 563:9c4b96f7be8d | 104 | // prepare the next discovery request (if needed) |
vcoubard | 563:9c4b96f7be8d | 105 | uint16_t startHandle = descriptors.descs[descriptors.count - 1].handle + 1; |
vcoubard | 563:9c4b96f7be8d | 106 | uint16_t endHandle = discovery->characteristic.getLastHandle(); |
vcoubard | 563:9c4b96f7be8d | 107 | |
vcoubard | 568:13b23a4b1f58 | 108 | if(startHandle > endHandle) { |
vcoubard | 568:13b23a4b1f58 | 109 | terminate(discovery, BLE_ERROR_NONE); |
vcoubard | 563:9c4b96f7be8d | 110 | return; |
vcoubard | 563:9c4b96f7be8d | 111 | } |
vcoubard | 563:9c4b96f7be8d | 112 | |
vcoubard | 563:9c4b96f7be8d | 113 | ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle); |
vcoubard | 568:13b23a4b1f58 | 114 | if(err) { |
vcoubard | 568:13b23a4b1f58 | 115 | terminate(discovery, err); |
vcoubard | 563:9c4b96f7be8d | 116 | return; |
vcoubard | 563:9c4b96f7be8d | 117 | } |
vcoubard | 563:9c4b96f7be8d | 118 | } |
vcoubard | 563:9c4b96f7be8d | 119 | |
vcoubard | 563:9c4b96f7be8d | 120 | void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) { |
vcoubard | 563:9c4b96f7be8d | 121 | Discovery* discovery = findRunningDiscovery(handle); |
vcoubard | 568:13b23a4b1f58 | 122 | // the discovery has already been terminated |
vcoubard | 568:13b23a4b1f58 | 123 | if(!discovery) { |
vcoubard | 568:13b23a4b1f58 | 124 | return; |
vcoubard | 563:9c4b96f7be8d | 125 | } |
vcoubard | 563:9c4b96f7be8d | 126 | |
vcoubard | 568:13b23a4b1f58 | 127 | terminate(discovery, err); |
vcoubard | 568:13b23a4b1f58 | 128 | } |
vcoubard | 568:13b23a4b1f58 | 129 | |
vcoubard | 568:13b23a4b1f58 | 130 | void nRF5xCharacteristicDescriptorDiscoverer::terminate(Discovery* discovery, ble_error_t err) { |
vcoubard | 568:13b23a4b1f58 | 131 | // temporary copy, user code can try to launch a new discovery in the onTerminate |
vcoubard | 568:13b23a4b1f58 | 132 | // callback. So, this discovery should not appear in such case. |
vcoubard | 563:9c4b96f7be8d | 133 | Discovery tmp = *discovery; |
vcoubard | 563:9c4b96f7be8d | 134 | *discovery = Discovery(); |
vcoubard | 563:9c4b96f7be8d | 135 | tmp.terminate(err); |
vcoubard | 563:9c4b96f7be8d | 136 | } |
vcoubard | 563:9c4b96f7be8d | 137 | |
vcoubard | 568:13b23a4b1f58 | 138 | |
vcoubard | 568:13b23a4b1f58 | 139 | |
vcoubard | 568:13b23a4b1f58 | 140 | nRF5xCharacteristicDescriptorDiscoverer::Discovery* |
vcoubard | 563:9c4b96f7be8d | 141 | nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) { |
vcoubard | 568:13b23a4b1f58 | 142 | for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) { |
vcoubard | 568:13b23a4b1f58 | 143 | if(discoveryRunning[i].characteristic == characteristic && discoveryRunning[i].isEmpty() == false) { |
vcoubard | 563:9c4b96f7be8d | 144 | return &discoveryRunning[i]; |
vcoubard | 563:9c4b96f7be8d | 145 | } |
vcoubard | 563:9c4b96f7be8d | 146 | } |
vcoubard | 563:9c4b96f7be8d | 147 | return NULL; |
vcoubard | 563:9c4b96f7be8d | 148 | } |
vcoubard | 563:9c4b96f7be8d | 149 | |
vcoubard | 568:13b23a4b1f58 | 150 | nRF5xCharacteristicDescriptorDiscoverer::Discovery* |
vcoubard | 568:13b23a4b1f58 | 151 | nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) { |
vcoubard | 568:13b23a4b1f58 | 152 | for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) { |
vcoubard | 568:13b23a4b1f58 | 153 | if(discoveryRunning[i].characteristic.getConnectionHandle() == handle && |
vcoubard | 568:13b23a4b1f58 | 154 | discoveryRunning[i].isEmpty() == false) { |
vcoubard | 563:9c4b96f7be8d | 155 | return &discoveryRunning[i]; |
vcoubard | 563:9c4b96f7be8d | 156 | } |
vcoubard | 563:9c4b96f7be8d | 157 | } |
vcoubard | 563:9c4b96f7be8d | 158 | return NULL; |
vcoubard | 563:9c4b96f7be8d | 159 | } |
vcoubard | 563:9c4b96f7be8d | 160 | |
vcoubard | 568:13b23a4b1f58 | 161 | |
vcoubard | 568:13b23a4b1f58 | 162 | nRF5xCharacteristicDescriptorDiscoverer::Discovery* |
vcoubard | 568:13b23a4b1f58 | 163 | nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() { |
vcoubard | 568:13b23a4b1f58 | 164 | for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) { |
vcoubard | 568:13b23a4b1f58 | 165 | if(discoveryRunning[i].isEmpty()) { |
vcoubard | 563:9c4b96f7be8d | 166 | return &discoveryRunning[i]; |
vcoubard | 563:9c4b96f7be8d | 167 | } |
vcoubard | 563:9c4b96f7be8d | 168 | } |
vcoubard | 563:9c4b96f7be8d | 169 | return NULL; |
vcoubard | 563:9c4b96f7be8d | 170 | } |
vcoubard | 563:9c4b96f7be8d | 171 | |
vcoubard | 563:9c4b96f7be8d | 172 | bool nRF5xCharacteristicDescriptorDiscoverer::isConnectionInUse(uint16_t connHandle) { |
vcoubard | 563:9c4b96f7be8d | 173 | return findRunningDiscovery(connHandle) != NULL; |
vcoubard | 563:9c4b96f7be8d | 174 | } |
vcoubard | 563:9c4b96f7be8d | 175 | |
vcoubard | 563:9c4b96f7be8d | 176 | ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_descriptors_discover( |
vcoubard | 568:13b23a4b1f58 | 177 | uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) { |
vcoubard | 563:9c4b96f7be8d | 178 | |
vcoubard | 563:9c4b96f7be8d | 179 | ble_gattc_handle_range_t discoveryRange = { |
vcoubard | 563:9c4b96f7be8d | 180 | start_handle, |
vcoubard | 563:9c4b96f7be8d | 181 | end_handle |
vcoubard | 563:9c4b96f7be8d | 182 | }; |
vcoubard | 563:9c4b96f7be8d | 183 | uint32_t err = sd_ble_gattc_descriptors_discover(connection_handle, &discoveryRange); |
vcoubard | 563:9c4b96f7be8d | 184 | |
vcoubard | 568:13b23a4b1f58 | 185 | switch(err) { |
vcoubard | 563:9c4b96f7be8d | 186 | case NRF_SUCCESS: |
vcoubard | 568:13b23a4b1f58 | 187 | return BLE_ERROR_NONE; |
vcoubard | 563:9c4b96f7be8d | 188 | case BLE_ERROR_INVALID_CONN_HANDLE: |
vcoubard | 563:9c4b96f7be8d | 189 | return BLE_ERROR_INVALID_PARAM; |
vcoubard | 563:9c4b96f7be8d | 190 | case NRF_ERROR_INVALID_ADDR: |
vcoubard | 563:9c4b96f7be8d | 191 | return BLE_ERROR_PARAM_OUT_OF_RANGE; |
vcoubard | 563:9c4b96f7be8d | 192 | case NRF_ERROR_BUSY: |
vcoubard | 563:9c4b96f7be8d | 193 | return BLE_STACK_BUSY; |
vcoubard | 563:9c4b96f7be8d | 194 | default: |
vcoubard | 563:9c4b96f7be8d | 195 | return BLE_ERROR_UNSPECIFIED; |
vcoubard | 563:9c4b96f7be8d | 196 | } |
vcoubard | 563:9c4b96f7be8d | 197 | } |