test

Dependencies:   nrf51-sdk

Dependents:   microbit-dal

Fork of nRF51822 by Lancaster University

Committer:
rgrover1
Date:
Fri Jun 19 15:55:32 2015 +0100
Revision:
330:0a8ebc25b57c
Parent:
325:eb6914dca928
Child:
332:b054000833d4
Synchronized with git rev 168eed4e
Author: Rohit Grover
nRFDiscoveredCharacteristic::setup() takes a GattClient poitner

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 243:a966506d1e5b 1 /* mbed Microcontroller Library
rgrover1 243:a966506d1e5b 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 243:a966506d1e5b 3 *
rgrover1 243:a966506d1e5b 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 243:a966506d1e5b 5 * you may not use this file except in compliance with the License.
rgrover1 243:a966506d1e5b 6 * You may obtain a copy of the License at
rgrover1 243:a966506d1e5b 7 *
rgrover1 243:a966506d1e5b 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 243:a966506d1e5b 9 *
rgrover1 243:a966506d1e5b 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 243:a966506d1e5b 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 243:a966506d1e5b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 243:a966506d1e5b 13 * See the License for the specific language governing permissions and
rgrover1 243:a966506d1e5b 14 * limitations under the License.
rgrover1 243:a966506d1e5b 15 */
rgrover1 243:a966506d1e5b 16
rgrover1 287:faa0dc7ae513 17 #include <stdio.h>
rgrover1 287:faa0dc7ae513 18
rgrover1 239:693a1f145b5a 19 #include "blecommon.h"
rgrover1 239:693a1f145b5a 20 #include "UUID.h"
rgrover1 239:693a1f145b5a 21 #include "Gap.h"
rgrover1 239:693a1f145b5a 22 #include "nrf_error.h"
rgrover1 239:693a1f145b5a 23 #include "btle_discovery.h"
rgrover1 239:693a1f145b5a 24 #include "ble_err.h"
rgrover1 243:a966506d1e5b 25
rgrover1 278:26e3f0ef1e14 26 static NordicServiceDiscovery sdSingleton;
rgrover1 314:2e7378b25505 27 DiscoveredCharacteristic::ReadCallback_t DiscoveredCharacteristic::onDataReadCallback = NULL;
rgrover1 239:693a1f145b5a 28
rgrover1 239:693a1f145b5a 29 ble_error_t
rgrover1 275:fd709cd8b1b2 30 ServiceDiscovery::launch(Gap::Handle_t connectionHandle,
rgrover1 275:fd709cd8b1b2 31 ServiceCallback_t sc,
rgrover1 275:fd709cd8b1b2 32 CharacteristicCallback_t cc,
rgrover1 275:fd709cd8b1b2 33 const UUID &matchingServiceUUIDIn,
rgrover1 275:fd709cd8b1b2 34 const UUID &matchingCharacteristicUUIDIn)
rgrover1 239:693a1f145b5a 35 {
rgrover1 281:2280bb1a9a9e 36 if (isActive()) {
rgrover1 281:2280bb1a9a9e 37 return BLE_ERROR_INVALID_STATE;
rgrover1 281:2280bb1a9a9e 38 }
rgrover1 281:2280bb1a9a9e 39
rgrover1 278:26e3f0ef1e14 40 sdSingleton.serviceCallback = sc;
rgrover1 278:26e3f0ef1e14 41 sdSingleton.characteristicCallback = cc;
rgrover1 278:26e3f0ef1e14 42 sdSingleton.matchingServiceUUID = matchingServiceUUIDIn;
rgrover1 278:26e3f0ef1e14 43 sdSingleton.matchingCharacteristicUUID = matchingCharacteristicUUIDIn;
rgrover1 273:8ada9e8111a3 44
rgrover1 278:26e3f0ef1e14 45 sdSingleton.serviceDiscoveryStarted(connectionHandle);
rgrover1 239:693a1f145b5a 46
rgrover1 239:693a1f145b5a 47 uint32_t rc;
rgrover1 248:71ef03789dd3 48 if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, NordicServiceDiscovery::SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) {
rgrover1 278:26e3f0ef1e14 49 sdSingleton.terminate();
rgrover1 239:693a1f145b5a 50 switch (rc) {
rgrover1 239:693a1f145b5a 51 case NRF_ERROR_INVALID_PARAM:
rgrover1 239:693a1f145b5a 52 case BLE_ERROR_INVALID_CONN_HANDLE:
rgrover1 239:693a1f145b5a 53 return BLE_ERROR_INVALID_PARAM;
rgrover1 239:693a1f145b5a 54 case NRF_ERROR_BUSY:
rgrover1 239:693a1f145b5a 55 return BLE_STACK_BUSY;
rgrover1 239:693a1f145b5a 56 default:
rgrover1 239:693a1f145b5a 57 case NRF_ERROR_INVALID_STATE:
rgrover1 239:693a1f145b5a 58 return BLE_ERROR_INVALID_STATE;
rgrover1 239:693a1f145b5a 59 }
rgrover1 239:693a1f145b5a 60 }
rgrover1 239:693a1f145b5a 61
rgrover1 239:693a1f145b5a 62 return BLE_ERROR_NONE;
rgrover1 239:693a1f145b5a 63 }
rgrover1 239:693a1f145b5a 64
rgrover1 248:71ef03789dd3 65 void
rgrover1 248:71ef03789dd3 66 ServiceDiscovery::terminate(void)
rgrover1 248:71ef03789dd3 67 {
rgrover1 278:26e3f0ef1e14 68 sdSingleton.terminateServiceDiscovery();
rgrover1 248:71ef03789dd3 69 }
rgrover1 248:71ef03789dd3 70
rgrover1 279:6e5e79f1fb61 71 bool
rgrover1 279:6e5e79f1fb61 72 ServiceDiscovery::isActive(void)
rgrover1 279:6e5e79f1fb61 73 {
rgrover1 279:6e5e79f1fb61 74 return sdSingleton.isActive();
rgrover1 279:6e5e79f1fb61 75 }
rgrover1 279:6e5e79f1fb61 76
rgrover1 280:cbaa4cb83548 77 void ServiceDiscovery::onTermination(TerminationCallback_t callback) {
rgrover1 280:cbaa4cb83548 78 sdSingleton.setOnTermination(callback);
rgrover1 280:cbaa4cb83548 79 }
rgrover1 280:cbaa4cb83548 80
rgrover1 243:a966506d1e5b 81 ble_error_t
rgrover1 252:4b3f294415f5 82 NordicServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHandle,
rgrover1 252:4b3f294415f5 83 Gap::Handle_t startHandle,
rgrover1 252:4b3f294415f5 84 Gap::Handle_t endHandle)
rgrover1 252:4b3f294415f5 85 {
rgrover1 278:26e3f0ef1e14 86 sdSingleton.characteristicDiscoveryStarted(connectionHandle);
rgrover1 239:693a1f145b5a 87
rgrover1 239:693a1f145b5a 88 ble_gattc_handle_range_t handleRange = {
rgrover1 239:693a1f145b5a 89 .start_handle = startHandle,
rgrover1 239:693a1f145b5a 90 .end_handle = endHandle
rgrover1 239:693a1f145b5a 91 };
rgrover1 239:693a1f145b5a 92 uint32_t rc;
rgrover1 239:693a1f145b5a 93 if ((rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange)) != NRF_SUCCESS) {
rgrover1 278:26e3f0ef1e14 94 sdSingleton.terminateCharacteristicDiscovery();
rgrover1 239:693a1f145b5a 95 switch (rc) {
rgrover1 239:693a1f145b5a 96 case BLE_ERROR_INVALID_CONN_HANDLE:
rgrover1 239:693a1f145b5a 97 case NRF_ERROR_INVALID_ADDR:
rgrover1 239:693a1f145b5a 98 return BLE_ERROR_INVALID_PARAM;
rgrover1 239:693a1f145b5a 99 case NRF_ERROR_BUSY:
rgrover1 239:693a1f145b5a 100 return BLE_STACK_BUSY;
rgrover1 239:693a1f145b5a 101 default:
rgrover1 239:693a1f145b5a 102 case NRF_ERROR_INVALID_STATE:
rgrover1 239:693a1f145b5a 103 return BLE_ERROR_INVALID_STATE;
rgrover1 239:693a1f145b5a 104 }
rgrover1 239:693a1f145b5a 105 }
rgrover1 239:693a1f145b5a 106
rgrover1 239:693a1f145b5a 107 return BLE_ERROR_NONE;
rgrover1 239:693a1f145b5a 108 }
rgrover1 239:693a1f145b5a 109
rgrover1 239:693a1f145b5a 110 void
rgrover1 305:293634834813 111 NordicServiceDiscovery::ServiceUUIDDiscoveryQueue::triggerFirst(void)
rgrover1 290:83c994bf62d0 112 {
rgrover1 293:cd86acfe41be 113 while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */
rgrover1 301:59e7404a4ea3 114 parentDiscoveryObject->state = DISCOVER_SERVICE_UUIDS;
rgrover1 290:83c994bf62d0 115
rgrover1 295:5566c7b83bb5 116 unsigned serviceIndex = getFirst();
rgrover1 290:83c994bf62d0 117 ble_uuid_t uuid = {
rgrover1 290:83c994bf62d0 118 .uuid = BLE_UUID_SERVICE_PRIMARY,
rgrover1 290:83c994bf62d0 119 .type = BLE_UUID_TYPE_BLE,
rgrover1 290:83c994bf62d0 120 };
rgrover1 290:83c994bf62d0 121 ble_gattc_handle_range_t handleRange = {
rgrover1 301:59e7404a4ea3 122 .start_handle = parentDiscoveryObject->services[serviceIndex].getStartHandle(),
rgrover1 301:59e7404a4ea3 123 .end_handle = parentDiscoveryObject->services[serviceIndex].getEndHandle(),
rgrover1 290:83c994bf62d0 124 };
rgrover1 301:59e7404a4ea3 125 if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) {
rgrover1 293:cd86acfe41be 126 return;
rgrover1 290:83c994bf62d0 127 }
rgrover1 290:83c994bf62d0 128
rgrover1 293:cd86acfe41be 129 /* Skip this service if we fail to launch a read for its service-declaration
rgrover1 293:cd86acfe41be 130 * attribute. Its UUID will remain INVALID, and it may not match any filters. */
rgrover1 299:19064275c0e0 131 dequeue();
rgrover1 290:83c994bf62d0 132 }
rgrover1 290:83c994bf62d0 133
rgrover1 293:cd86acfe41be 134 /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */
rgrover1 301:59e7404a4ea3 135 if (parentDiscoveryObject->state == DISCOVER_SERVICE_UUIDS) {
rgrover1 301:59e7404a4ea3 136 parentDiscoveryObject->state = SERVICE_DISCOVERY_ACTIVE;
rgrover1 290:83c994bf62d0 137 }
rgrover1 290:83c994bf62d0 138 }
rgrover1 290:83c994bf62d0 139
rgrover1 290:83c994bf62d0 140 void
rgrover1 306:76e2e7349319 141 NordicServiceDiscovery::CharUUIDDiscoveryQueue::triggerFirst(void)
rgrover1 306:76e2e7349319 142 {
rgrover1 306:76e2e7349319 143 while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */
rgrover1 306:76e2e7349319 144 parentDiscoveryObject->state = DISCOVER_CHARACTERISTIC_UUIDS;
rgrover1 306:76e2e7349319 145
rgrover1 306:76e2e7349319 146 unsigned charIndex = getFirst();
rgrover1 306:76e2e7349319 147 ble_uuid_t uuid = {
rgrover1 306:76e2e7349319 148 .uuid = BLE_UUID_CHARACTERISTIC,
rgrover1 306:76e2e7349319 149 .type = BLE_UUID_TYPE_BLE,
rgrover1 306:76e2e7349319 150 };
rgrover1 306:76e2e7349319 151 ble_gattc_handle_range_t handleRange = {
rgrover1 306:76e2e7349319 152 .start_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle(),
rgrover1 306:76e2e7349319 153 .end_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle() + 1,
rgrover1 306:76e2e7349319 154 };
rgrover1 306:76e2e7349319 155 if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) {
rgrover1 306:76e2e7349319 156 return;
rgrover1 306:76e2e7349319 157 }
rgrover1 306:76e2e7349319 158
rgrover1 306:76e2e7349319 159 /* Skip this service if we fail to launch a read for its service-declaration
rgrover1 306:76e2e7349319 160 * attribute. Its UUID will remain INVALID, and it may not match any filters. */
rgrover1 306:76e2e7349319 161 dequeue();
rgrover1 306:76e2e7349319 162 }
rgrover1 306:76e2e7349319 163
rgrover1 306:76e2e7349319 164 /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */
rgrover1 306:76e2e7349319 165 if (parentDiscoveryObject->state == DISCOVER_CHARACTERISTIC_UUIDS) {
rgrover1 306:76e2e7349319 166 parentDiscoveryObject->state = CHARACTERISTIC_DISCOVERY_ACTIVE;
rgrover1 306:76e2e7349319 167 }
rgrover1 306:76e2e7349319 168 }
rgrover1 306:76e2e7349319 169
rgrover1 306:76e2e7349319 170 void
rgrover1 290:83c994bf62d0 171 NordicServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response)
rgrover1 290:83c994bf62d0 172 {
rgrover1 299:19064275c0e0 173 if (state == DISCOVER_SERVICE_UUIDS) {
rgrover1 299:19064275c0e0 174 if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) {
rgrover1 299:19064275c0e0 175 UUID::LongUUIDBytes_t uuid;
rgrover1 299:19064275c0e0 176 /* Switch longUUID bytes to MSB */
rgrover1 299:19064275c0e0 177 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
rgrover1 299:19064275c0e0 178 uuid[i] = response->handle_value[0].p_value[UUID::LENGTH_OF_LONG_UUID - 1 - i];
rgrover1 299:19064275c0e0 179 }
rgrover1 290:83c994bf62d0 180
rgrover1 305:293634834813 181 unsigned serviceIndex = serviceUUIDDiscoveryQueue.dequeue();
rgrover1 299:19064275c0e0 182 services[serviceIndex].setupLongUUID(uuid);
rgrover1 299:19064275c0e0 183
rgrover1 305:293634834813 184 serviceUUIDDiscoveryQueue.triggerFirst();
rgrover1 306:76e2e7349319 185 } else {
rgrover1 306:76e2e7349319 186 serviceUUIDDiscoveryQueue.dequeue();
rgrover1 306:76e2e7349319 187 }
rgrover1 306:76e2e7349319 188 } else if (state == DISCOVER_CHARACTERISTIC_UUIDS) {
rgrover1 306:76e2e7349319 189 if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) {
rgrover1 306:76e2e7349319 190 UUID::LongUUIDBytes_t uuid;
rgrover1 306:76e2e7349319 191 /* Switch longUUID bytes to MSB */
rgrover1 306:76e2e7349319 192 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
rgrover1 306:76e2e7349319 193 uuid[i] = response->handle_value[0].p_value[3 + UUID::LENGTH_OF_LONG_UUID - 1 - i];
rgrover1 306:76e2e7349319 194 }
rgrover1 306:76e2e7349319 195
rgrover1 306:76e2e7349319 196 unsigned charIndex = charUUIDDiscoveryQueue.dequeue();
rgrover1 306:76e2e7349319 197 characteristics[charIndex].setupLongUUID(uuid);
rgrover1 306:76e2e7349319 198
rgrover1 306:76e2e7349319 199 charUUIDDiscoveryQueue.triggerFirst();
rgrover1 306:76e2e7349319 200 } else {
rgrover1 306:76e2e7349319 201 charUUIDDiscoveryQueue.dequeue();
rgrover1 296:8d25fe68d731 202 }
rgrover1 296:8d25fe68d731 203 }
rgrover1 290:83c994bf62d0 204 }
rgrover1 290:83c994bf62d0 205
rgrover1 290:83c994bf62d0 206 void
rgrover1 240:75b69581d1dd 207 NordicServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response)
rgrover1 239:693a1f145b5a 208 {
rgrover1 242:73fc02cc20b1 209 serviceIndex = 0;
rgrover1 242:73fc02cc20b1 210 numServices = response->count;
rgrover1 239:693a1f145b5a 211
rgrover1 239:693a1f145b5a 212 /* Account for the limitation on the number of discovered services we can handle at a time. */
rgrover1 242:73fc02cc20b1 213 if (numServices > BLE_DB_DISCOVERY_MAX_SRV) {
rgrover1 242:73fc02cc20b1 214 numServices = BLE_DB_DISCOVERY_MAX_SRV;
rgrover1 239:693a1f145b5a 215 }
rgrover1 239:693a1f145b5a 216
rgrover1 305:293634834813 217 serviceUUIDDiscoveryQueue.reset();
rgrover1 242:73fc02cc20b1 218 for (unsigned serviceIndex = 0; serviceIndex < numServices; serviceIndex++) {
rgrover1 283:c4c2aeab86c3 219 if (response->services[serviceIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
rgrover1 305:293634834813 220 serviceUUIDDiscoveryQueue.enqueue(serviceIndex);
rgrover1 294:a2219bad9d4a 221 services[serviceIndex].setup(response->services[serviceIndex].handle_range.start_handle,
rgrover1 294:a2219bad9d4a 222 response->services[serviceIndex].handle_range.end_handle);
rgrover1 294:a2219bad9d4a 223 } else {
rgrover1 294:a2219bad9d4a 224 services[serviceIndex].setup(response->services[serviceIndex].uuid.uuid,
rgrover1 294:a2219bad9d4a 225 response->services[serviceIndex].handle_range.start_handle,
rgrover1 294:a2219bad9d4a 226 response->services[serviceIndex].handle_range.end_handle);
rgrover1 283:c4c2aeab86c3 227 }
rgrover1 239:693a1f145b5a 228 }
rgrover1 290:83c994bf62d0 229
rgrover1 290:83c994bf62d0 230 /* Trigger discovery of service UUID if necessary. */
rgrover1 305:293634834813 231 if (serviceUUIDDiscoveryQueue.getCount()) {
rgrover1 305:293634834813 232 serviceUUIDDiscoveryQueue.triggerFirst();
rgrover1 290:83c994bf62d0 233 }
rgrover1 239:693a1f145b5a 234 }
rgrover1 239:693a1f145b5a 235
rgrover1 239:693a1f145b5a 236 void
rgrover1 240:75b69581d1dd 237 NordicServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response)
rgrover1 239:693a1f145b5a 238 {
rgrover1 242:73fc02cc20b1 239 characteristicIndex = 0;
rgrover1 242:73fc02cc20b1 240 numCharacteristics = response->count;
rgrover1 239:693a1f145b5a 241
rgrover1 239:693a1f145b5a 242 /* Account for the limitation on the number of discovered characteristics we can handle at a time. */
rgrover1 242:73fc02cc20b1 243 if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) {
rgrover1 242:73fc02cc20b1 244 numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV;
rgrover1 239:693a1f145b5a 245 }
rgrover1 239:693a1f145b5a 246
rgrover1 306:76e2e7349319 247 charUUIDDiscoveryQueue.reset();
rgrover1 242:73fc02cc20b1 248 for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) {
rgrover1 306:76e2e7349319 249 if (response->chars[charIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
rgrover1 306:76e2e7349319 250 charUUIDDiscoveryQueue.enqueue(charIndex);
rgrover1 330:0a8ebc25b57c 251 characteristics[charIndex].setup(NULL, /* gattc FIX THIS */
rgrover1 330:0a8ebc25b57c 252 connHandle,
rgrover1 325:eb6914dca928 253 response->chars[charIndex].char_props,
rgrover1 306:76e2e7349319 254 response->chars[charIndex].handle_decl,
rgrover1 306:76e2e7349319 255 response->chars[charIndex].handle_value);
rgrover1 306:76e2e7349319 256 } else {
rgrover1 330:0a8ebc25b57c 257 characteristics[charIndex].setup(NULL, /* gattc FIX THIS */
rgrover1 330:0a8ebc25b57c 258 connHandle,
rgrover1 311:5d5abc30e3a8 259 response->chars[charIndex].uuid.uuid,
rgrover1 325:eb6914dca928 260 response->chars[charIndex].char_props,
rgrover1 306:76e2e7349319 261 response->chars[charIndex].handle_decl,
rgrover1 306:76e2e7349319 262 response->chars[charIndex].handle_value);
rgrover1 306:76e2e7349319 263 }
rgrover1 306:76e2e7349319 264 }
rgrover1 306:76e2e7349319 265
rgrover1 306:76e2e7349319 266 /* Trigger discovery of char UUID if necessary. */
rgrover1 306:76e2e7349319 267 if (charUUIDDiscoveryQueue.getCount()) {
rgrover1 306:76e2e7349319 268 charUUIDDiscoveryQueue.triggerFirst();
rgrover1 239:693a1f145b5a 269 }
rgrover1 243:a966506d1e5b 270 }
rgrover1 243:a966506d1e5b 271
rgrover1 251:d4e0cf5e8751 272 void
rgrover1 251:d4e0cf5e8751 273 NordicServiceDiscovery::progressCharacteristicDiscovery(void)
rgrover1 251:d4e0cf5e8751 274 {
rgrover1 276:ae6e5129b395 275 /* Iterate through the previously discovered characteristics cached in characteristics[]. */
rgrover1 286:042b01e59cf8 276 while ((state == CHARACTERISTIC_DISCOVERY_ACTIVE) && (characteristicIndex < numCharacteristics)) {
rgrover1 285:55ac765bcc8d 277 if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
rgrover1 321:3ece9d123429 278 ((matchingCharacteristicUUID == characteristics[characteristicIndex].getShortUUID()) &&
rgrover1 321:3ece9d123429 279 (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
rgrover1 282:6633922380bf 280 if (characteristicCallback) {
rgrover1 318:1edcbcd1bf21 281 characteristicCallback(&characteristics[characteristicIndex]);
rgrover1 282:6633922380bf 282 }
rgrover1 255:d228656b0cd1 283 }
rgrover1 251:d4e0cf5e8751 284
rgrover1 251:d4e0cf5e8751 285 characteristicIndex++;
rgrover1 251:d4e0cf5e8751 286 }
rgrover1 251:d4e0cf5e8751 287
rgrover1 276:ae6e5129b395 288 /* Relaunch discovery of new characteristics beyond the last entry cached in characteristics[]. */
rgrover1 286:042b01e59cf8 289 if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) {
rgrover1 276:ae6e5129b395 290 /* Determine the ending handle of the last cached characteristic. */
rgrover1 264:5533ac0adf4b 291 Gap::Handle_t startHandle = characteristics[characteristicIndex - 1].getValueHandle() + 1;
rgrover1 264:5533ac0adf4b 292 Gap::Handle_t endHandle = services[serviceIndex].getEndHandle();
rgrover1 274:f82e0ecba699 293 resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */
rgrover1 251:d4e0cf5e8751 294
rgrover1 251:d4e0cf5e8751 295 if (startHandle < endHandle) {
rgrover1 251:d4e0cf5e8751 296 ble_gattc_handle_range_t handleRange = {
rgrover1 251:d4e0cf5e8751 297 .start_handle = startHandle,
rgrover1 251:d4e0cf5e8751 298 .end_handle = endHandle
rgrover1 251:d4e0cf5e8751 299 };
rgrover1 258:62d6bf03e6a4 300 if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) {
rgrover1 258:62d6bf03e6a4 301 terminateCharacteristicDiscovery();
rgrover1 258:62d6bf03e6a4 302 }
rgrover1 251:d4e0cf5e8751 303 } else {
rgrover1 277:91705df8495e 304 terminateCharacteristicDiscovery();
rgrover1 251:d4e0cf5e8751 305 }
rgrover1 251:d4e0cf5e8751 306 }
rgrover1 251:d4e0cf5e8751 307 }
rgrover1 251:d4e0cf5e8751 308
rgrover1 251:d4e0cf5e8751 309 void
rgrover1 251:d4e0cf5e8751 310 NordicServiceDiscovery::progressServiceDiscovery(void)
rgrover1 251:d4e0cf5e8751 311 {
rgrover1 276:ae6e5129b395 312 /* Iterate through the previously discovered services cached in services[]. */
rgrover1 286:042b01e59cf8 313 while ((state == SERVICE_DISCOVERY_ACTIVE) && (serviceIndex < numServices)) {
rgrover1 285:55ac765bcc8d 314 if ((matchingServiceUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
rgrover1 298:c10ee33f68ab 315 (matchingServiceUUID == services[serviceIndex].getUUID().getShortUUID())) {
rgrover1 322:788b6ac328b7 316
rgrover1 322:788b6ac328b7 317 if (serviceCallback && (matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN))) {
rgrover1 320:b1281aaf0076 318 serviceCallback(&services[serviceIndex]);
rgrover1 277:91705df8495e 319 }
rgrover1 251:d4e0cf5e8751 320
rgrover1 286:042b01e59cf8 321 if ((state == SERVICE_DISCOVERY_ACTIVE) && characteristicCallback) {
rgrover1 277:91705df8495e 322 launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle());
rgrover1 277:91705df8495e 323 } else {
rgrover1 277:91705df8495e 324 serviceIndex++;
rgrover1 277:91705df8495e 325 }
rgrover1 251:d4e0cf5e8751 326 } else {
rgrover1 277:91705df8495e 327 serviceIndex++;
rgrover1 251:d4e0cf5e8751 328 }
rgrover1 251:d4e0cf5e8751 329 }
rgrover1 276:ae6e5129b395 330
rgrover1 276:ae6e5129b395 331 /* Relaunch discovery of new services beyond the last entry cached in services[]. */
rgrover1 286:042b01e59cf8 332 if ((state == SERVICE_DISCOVERY_ACTIVE) && (numServices > 0) && (serviceIndex > 0)) {
rgrover1 276:ae6e5129b395 333 /* Determine the ending handle of the last cached service. */
rgrover1 264:5533ac0adf4b 334 Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle();
rgrover1 274:f82e0ecba699 335 resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */
rgrover1 251:d4e0cf5e8751 336
rgrover1 284:29fb6af6671d 337 if (endHandle == SRV_DISC_END_HANDLE) {
rgrover1 258:62d6bf03e6a4 338 terminateServiceDiscovery();
rgrover1 284:29fb6af6671d 339 } else {
rgrover1 284:29fb6af6671d 340 if (sd_ble_gattc_primary_services_discover(connHandle, endHandle, NULL) != NRF_SUCCESS) {
rgrover1 284:29fb6af6671d 341 terminateServiceDiscovery();
rgrover1 284:29fb6af6671d 342 }
rgrover1 258:62d6bf03e6a4 343 }
rgrover1 251:d4e0cf5e8751 344 }
rgrover1 251:d4e0cf5e8751 345 }
rgrover1 251:d4e0cf5e8751 346
rgrover1 243:a966506d1e5b 347 void bleGattcEventHandler(const ble_evt_t *p_ble_evt)
rgrover1 243:a966506d1e5b 348 {
rgrover1 243:a966506d1e5b 349 switch (p_ble_evt->header.evt_id) {
rgrover1 243:a966506d1e5b 350 case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
rgrover1 243:a966506d1e5b 351 switch (p_ble_evt->evt.gattc_evt.gatt_status) {
rgrover1 243:a966506d1e5b 352 case BLE_GATT_STATUS_SUCCESS:
rgrover1 278:26e3f0ef1e14 353 sdSingleton.setupDiscoveredServices(&p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp);
rgrover1 243:a966506d1e5b 354 break;
rgrover1 243:a966506d1e5b 355
rgrover1 243:a966506d1e5b 356 case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
rgrover1 243:a966506d1e5b 357 default:
rgrover1 278:26e3f0ef1e14 358 sdSingleton.terminate();
rgrover1 243:a966506d1e5b 359 break;
rgrover1 243:a966506d1e5b 360 }
rgrover1 243:a966506d1e5b 361 break;
rgrover1 243:a966506d1e5b 362
rgrover1 243:a966506d1e5b 363 case BLE_GATTC_EVT_CHAR_DISC_RSP:
rgrover1 243:a966506d1e5b 364 switch (p_ble_evt->evt.gattc_evt.gatt_status) {
rgrover1 243:a966506d1e5b 365 case BLE_GATT_STATUS_SUCCESS:
rgrover1 278:26e3f0ef1e14 366 sdSingleton.setupDiscoveredCharacteristics(&p_ble_evt->evt.gattc_evt.params.char_disc_rsp);
rgrover1 243:a966506d1e5b 367 break;
rgrover1 243:a966506d1e5b 368
rgrover1 243:a966506d1e5b 369 case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
rgrover1 243:a966506d1e5b 370 default:
rgrover1 278:26e3f0ef1e14 371 sdSingleton.terminateCharacteristicDiscovery();
rgrover1 243:a966506d1e5b 372 break;
rgrover1 243:a966506d1e5b 373 }
rgrover1 243:a966506d1e5b 374 break;
rgrover1 313:d579d093f23f 375
rgrover1 313:d579d093f23f 376 case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
rgrover1 290:83c994bf62d0 377 if (sdSingleton.isActive()) {
rgrover1 290:83c994bf62d0 378 sdSingleton.processDiscoverUUIDResponse(&p_ble_evt->evt.gattc_evt.params.char_val_by_uuid_read_rsp);
rgrover1 290:83c994bf62d0 379 }
rgrover1 290:83c994bf62d0 380 break;
rgrover1 319:cf62d065e70a 381
rgrover1 319:cf62d065e70a 382 case BLE_GATTC_EVT_READ_RSP:
rgrover1 319:cf62d065e70a 383 if (DiscoveredCharacteristic::onDataReadCallback != NULL) {
rgrover1 319:cf62d065e70a 384 DiscoveredCharacteristic::ReadResponse_t response = {
rgrover1 319:cf62d065e70a 385 .handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle,
rgrover1 319:cf62d065e70a 386 .offset = p_ble_evt->evt.gattc_evt.params.read_rsp.offset,
rgrover1 319:cf62d065e70a 387 .len = p_ble_evt->evt.gattc_evt.params.read_rsp.len,
rgrover1 319:cf62d065e70a 388 .data = p_ble_evt->evt.gattc_evt.params.read_rsp.data,
rgrover1 319:cf62d065e70a 389 };
rgrover1 319:cf62d065e70a 390 DiscoveredCharacteristic::onDataReadCallback(&response);
rgrover1 319:cf62d065e70a 391 }
rgrover1 319:cf62d065e70a 392 break;
rgrover1 243:a966506d1e5b 393 }
rgrover1 243:a966506d1e5b 394
rgrover1 278:26e3f0ef1e14 395 sdSingleton.progressCharacteristicDiscovery();
rgrover1 278:26e3f0ef1e14 396 sdSingleton.progressServiceDiscovery();
rgrover1 239:693a1f145b5a 397 }