library for BLE_GAP_backpack

Dependencies:   nrf51-sdk

Fork of nRF51822 by Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nRF5xCharacteristicDescriptorDiscoverer.cpp Source File

nRF5xCharacteristicDescriptorDiscoverer.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "nRF5xCharacteristicDescriptorDiscoverer.h"
00017 #include "ble_err.h"
00018 #include "ble/DiscoveredCharacteristicDescriptor.h"
00019 
00020 nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer() :
00021     discoveryRunning() {
00022     // nothing to do
00023 }
00024 
00025 nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() {
00026     // nothing to do
00027 }
00028 
00029 ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch(
00030     const DiscoveredCharacteristic& characteristic,
00031     const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
00032     const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
00033 ) {
00034     Gap::Handle_t connHandle = characteristic.getConnectionHandle();
00035     // it is ok to deduce that the start handle for descriptors is after
00036     // the characteristic declaration and the characteristic value declaration
00037     // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] (3.3)
00038     Gap::Handle_t descriptorStartHandle = characteristic.getDeclHandle() + 2;
00039     Gap::Handle_t descriptorEndHandle = characteristic.getLastHandle();
00040 
00041     // check if there is any descriptor to discover
00042     if (descriptorEndHandle < descriptorStartHandle) {
00043         CharacteristicDescriptorDiscovery::TerminationCallbackParams_t termParams = {
00044             characteristic,
00045             BLE_ERROR_NONE
00046         };
00047         terminationCallback.call(&termParams);
00048         return BLE_ERROR_NONE;
00049     }
00050 
00051     // check if we can run this discovery
00052     if (isConnectionInUse(connHandle)) {
00053         return BLE_STACK_BUSY;
00054     }
00055 
00056     // get a new discovery slot, if none are available, just return
00057     Discovery* discovery = getAvailableDiscoverySlot();
00058     if(discovery == NULL) {
00059         return BLE_STACK_BUSY;
00060     }
00061 
00062     // try to launch the discovery
00063     ble_error_t err = gattc_descriptors_discover(connHandle, descriptorStartHandle, descriptorEndHandle);
00064     if(!err) {
00065         // commit the new discovery to its slot
00066         *discovery = Discovery(characteristic, discoveryCallback, terminationCallback);
00067     }
00068 
00069     return err;
00070 }
00071 
00072 bool nRF5xCharacteristicDescriptorDiscoverer::isActive(const DiscoveredCharacteristic& characteristic) const {
00073     for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
00074         if(discoveryRunning[i].getCharacteristic() == characteristic) {
00075             return true;
00076         }
00077     }
00078     return false;
00079 }
00080 
00081 void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) {
00082     Discovery* discovery = findRunningDiscovery(characteristic);
00083     if(discovery) {
00084         // call terminate anyway
00085         terminate(discovery, BLE_ERROR_NONE);
00086     }
00087 }
00088 
00089 void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) {
00090     Discovery* discovery = findRunningDiscovery(connectionHandle);
00091     // the discovery has been removed
00092     if(!discovery) {
00093         return;
00094     }
00095 
00096     for (uint16_t i = 0; i < descriptors.count; ++i) {
00097         discovery->process(
00098             descriptors.descs[i].handle, UUID(descriptors.descs[i].uuid.uuid)
00099         );
00100     }
00101 
00102     // prepare the next discovery request (if needed)
00103     uint16_t startHandle = descriptors.descs[descriptors.count - 1].handle + 1;
00104     uint16_t endHandle = discovery->getCharacteristic().getLastHandle();
00105 
00106     if(startHandle > endHandle) {
00107         terminate(discovery, BLE_ERROR_NONE);
00108         return;
00109     }
00110 
00111     ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
00112     if(err) {
00113         terminate(discovery, err);
00114         return;
00115     }
00116 }
00117 
00118 void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) {
00119     Discovery* discovery = findRunningDiscovery(handle);
00120     // the discovery has already been terminated
00121     if(!discovery) {
00122         return;
00123     }
00124 
00125     terminate(discovery, err);
00126 }
00127 
00128 void nRF5xCharacteristicDescriptorDiscoverer::terminate(Discovery* discovery, ble_error_t err) {
00129     // temporary copy, user code can try to launch a new discovery in the onTerminate
00130     // callback. So, this discovery should not appear in such case.
00131     Discovery tmp = *discovery;
00132     *discovery = Discovery();
00133     tmp.terminate(err);
00134 }
00135 
00136 nRF5xCharacteristicDescriptorDiscoverer::Discovery*
00137 nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) {
00138     for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
00139         if((discoveryRunning[i].getCharacteristic() == characteristic) &&
00140            (discoveryRunning[i].isEmpty() == false)) {
00141             return &discoveryRunning[i];
00142         }
00143     }
00144     return NULL;
00145 }
00146 
00147 nRF5xCharacteristicDescriptorDiscoverer::Discovery*
00148 nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) {
00149     for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
00150         if((discoveryRunning[i].getCharacteristic().getConnectionHandle() == handle) &&
00151            (discoveryRunning[i].isEmpty() == false)) {
00152             return &discoveryRunning[i];
00153         }
00154     }
00155     return NULL;
00156 }
00157 
00158 nRF5xCharacteristicDescriptorDiscoverer::Discovery*
00159 nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() {
00160     for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
00161         if(discoveryRunning[i].isEmpty()) {
00162             return &discoveryRunning[i];
00163         }
00164     }
00165     return NULL;
00166 }
00167 
00168 bool nRF5xCharacteristicDescriptorDiscoverer::isConnectionInUse(uint16_t connHandle) {
00169      return findRunningDiscovery(connHandle) != NULL;
00170 }
00171 
00172 ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_descriptors_discover(
00173     uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) {
00174 
00175     ble_gattc_handle_range_t discoveryRange = {
00176         start_handle,
00177         end_handle
00178     };
00179     uint32_t err = sd_ble_gattc_descriptors_discover(connection_handle, &discoveryRange);
00180 
00181     switch(err) {
00182         case NRF_SUCCESS:
00183             return BLE_ERROR_NONE;
00184         case BLE_ERROR_INVALID_CONN_HANDLE:
00185             return BLE_ERROR_INVALID_PARAM;
00186         case NRF_ERROR_INVALID_ADDR:
00187             return BLE_ERROR_PARAM_OUT_OF_RANGE;
00188         case NRF_ERROR_BUSY:
00189             return BLE_STACK_BUSY;
00190         default:
00191             return BLE_ERROR_UNSPECIFIED;
00192     }
00193 }
00194 
00195 // implementation of nRF5xCharacteristicDescriptorDiscoverer::Discovery
00196 
00197 nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery() :
00198     characteristic(), onDiscovery(), onTerminate() {
00199 }
00200 
00201 nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery(
00202     const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb) :
00203     characteristic(c), onDiscovery(dCb), onTerminate(tCb) {
00204 }
00205 
00206 void nRF5xCharacteristicDescriptorDiscoverer::Discovery::process(
00207     GattAttribute::Handle_t handle, const UUID& uuid) {
00208     CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
00209         characteristic,
00210         DiscoveredCharacteristicDescriptor(
00211             characteristic.getGattClient(),
00212             characteristic.getConnectionHandle(),
00213             handle,
00214             uuid
00215         )
00216     };
00217     onDiscovery.call(&params);
00218 }
00219 
00220 void nRF5xCharacteristicDescriptorDiscoverer::Discovery::terminate(ble_error_t err) {
00221     CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
00222         characteristic,
00223         err
00224     };
00225 
00226     onTerminate.call(&params);
00227 }
00228 
00229 bool nRF5xCharacteristicDescriptorDiscoverer::Discovery::isEmpty() const {
00230     return *this == Discovery();
00231 }
00232 
00233 const DiscoveredCharacteristic& nRF5xCharacteristicDescriptorDiscoverer::Discovery::getCharacteristic() const {
00234     return characteristic;
00235 }