nordic

Fork of nRF51822 by Nordic Semiconductor

Committer:
rgrover1
Date:
Fri Jun 19 15:55:26 2015 +0100
Revision:
280:6e5e79f1fb61
Parent:
279:26e3f0ef1e14
Child:
281:cbaa4cb83548
Synchronized with git rev 9a1cb121
Author: Rohit Grover
add ServiceDiscovery::isActive()

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 244:a966506d1e5b 1 /* mbed Microcontroller Library
rgrover1 244:a966506d1e5b 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 244:a966506d1e5b 3 *
rgrover1 244:a966506d1e5b 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 244:a966506d1e5b 5 * you may not use this file except in compliance with the License.
rgrover1 244:a966506d1e5b 6 * You may obtain a copy of the License at
rgrover1 244:a966506d1e5b 7 *
rgrover1 244:a966506d1e5b 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 244:a966506d1e5b 9 *
rgrover1 244:a966506d1e5b 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 244:a966506d1e5b 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 244:a966506d1e5b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 244:a966506d1e5b 13 * See the License for the specific language governing permissions and
rgrover1 244:a966506d1e5b 14 * limitations under the License.
rgrover1 244:a966506d1e5b 15 */
rgrover1 244:a966506d1e5b 16
rgrover1 240:693a1f145b5a 17 #include "blecommon.h"
rgrover1 240:693a1f145b5a 18 #include "UUID.h"
rgrover1 240:693a1f145b5a 19 #include "Gap.h"
rgrover1 240:693a1f145b5a 20 #include "nrf_error.h"
rgrover1 240:693a1f145b5a 21 #include "btle_discovery.h"
rgrover1 240:693a1f145b5a 22 #include "ble_err.h"
rgrover1 244:a966506d1e5b 23
rgrover1 279:26e3f0ef1e14 24 static NordicServiceDiscovery sdSingleton;
rgrover1 240:693a1f145b5a 25
rgrover1 240:693a1f145b5a 26 ble_error_t
rgrover1 276:fd709cd8b1b2 27 ServiceDiscovery::launch(Gap::Handle_t connectionHandle,
rgrover1 276:fd709cd8b1b2 28 ServiceCallback_t sc,
rgrover1 276:fd709cd8b1b2 29 CharacteristicCallback_t cc,
rgrover1 276:fd709cd8b1b2 30 const UUID &matchingServiceUUIDIn,
rgrover1 276:fd709cd8b1b2 31 const UUID &matchingCharacteristicUUIDIn)
rgrover1 240:693a1f145b5a 32 {
rgrover1 279:26e3f0ef1e14 33 sdSingleton.serviceCallback = sc;
rgrover1 279:26e3f0ef1e14 34 sdSingleton.characteristicCallback = cc;
rgrover1 279:26e3f0ef1e14 35 sdSingleton.matchingServiceUUID = matchingServiceUUIDIn;
rgrover1 279:26e3f0ef1e14 36 sdSingleton.matchingCharacteristicUUID = matchingCharacteristicUUIDIn;
rgrover1 274:8ada9e8111a3 37
rgrover1 279:26e3f0ef1e14 38 sdSingleton.serviceDiscoveryStarted(connectionHandle);
rgrover1 240:693a1f145b5a 39
rgrover1 240:693a1f145b5a 40 uint32_t rc;
rgrover1 249:71ef03789dd3 41 if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, NordicServiceDiscovery::SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) {
rgrover1 279:26e3f0ef1e14 42 sdSingleton.terminate();
rgrover1 240:693a1f145b5a 43 switch (rc) {
rgrover1 240:693a1f145b5a 44 case NRF_ERROR_INVALID_PARAM:
rgrover1 240:693a1f145b5a 45 case BLE_ERROR_INVALID_CONN_HANDLE:
rgrover1 240:693a1f145b5a 46 return BLE_ERROR_INVALID_PARAM;
rgrover1 240:693a1f145b5a 47 case NRF_ERROR_BUSY:
rgrover1 240:693a1f145b5a 48 return BLE_STACK_BUSY;
rgrover1 240:693a1f145b5a 49 default:
rgrover1 240:693a1f145b5a 50 case NRF_ERROR_INVALID_STATE:
rgrover1 240:693a1f145b5a 51 return BLE_ERROR_INVALID_STATE;
rgrover1 240:693a1f145b5a 52 }
rgrover1 240:693a1f145b5a 53 }
rgrover1 240:693a1f145b5a 54
rgrover1 240:693a1f145b5a 55 return BLE_ERROR_NONE;
rgrover1 240:693a1f145b5a 56 }
rgrover1 240:693a1f145b5a 57
rgrover1 249:71ef03789dd3 58 void
rgrover1 249:71ef03789dd3 59 ServiceDiscovery::terminate(void)
rgrover1 249:71ef03789dd3 60 {
rgrover1 279:26e3f0ef1e14 61 sdSingleton.terminateServiceDiscovery();
rgrover1 249:71ef03789dd3 62 }
rgrover1 249:71ef03789dd3 63
rgrover1 280:6e5e79f1fb61 64 bool
rgrover1 280:6e5e79f1fb61 65 ServiceDiscovery::isActive(void)
rgrover1 280:6e5e79f1fb61 66 {
rgrover1 280:6e5e79f1fb61 67 return sdSingleton.isActive();
rgrover1 280:6e5e79f1fb61 68 }
rgrover1 280:6e5e79f1fb61 69
rgrover1 244:a966506d1e5b 70 ble_error_t
rgrover1 253:4b3f294415f5 71 NordicServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHandle,
rgrover1 253:4b3f294415f5 72 Gap::Handle_t startHandle,
rgrover1 253:4b3f294415f5 73 Gap::Handle_t endHandle)
rgrover1 253:4b3f294415f5 74 {
rgrover1 279:26e3f0ef1e14 75 sdSingleton.characteristicDiscoveryStarted(connectionHandle);
rgrover1 240:693a1f145b5a 76
rgrover1 240:693a1f145b5a 77 ble_gattc_handle_range_t handleRange = {
rgrover1 240:693a1f145b5a 78 .start_handle = startHandle,
rgrover1 240:693a1f145b5a 79 .end_handle = endHandle
rgrover1 240:693a1f145b5a 80 };
rgrover1 240:693a1f145b5a 81 uint32_t rc;
rgrover1 240:693a1f145b5a 82 if ((rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange)) != NRF_SUCCESS) {
rgrover1 279:26e3f0ef1e14 83 sdSingleton.terminateCharacteristicDiscovery();
rgrover1 240:693a1f145b5a 84 switch (rc) {
rgrover1 240:693a1f145b5a 85 case BLE_ERROR_INVALID_CONN_HANDLE:
rgrover1 240:693a1f145b5a 86 case NRF_ERROR_INVALID_ADDR:
rgrover1 240:693a1f145b5a 87 return BLE_ERROR_INVALID_PARAM;
rgrover1 240:693a1f145b5a 88 case NRF_ERROR_BUSY:
rgrover1 240:693a1f145b5a 89 return BLE_STACK_BUSY;
rgrover1 240:693a1f145b5a 90 default:
rgrover1 240:693a1f145b5a 91 case NRF_ERROR_INVALID_STATE:
rgrover1 240:693a1f145b5a 92 return BLE_ERROR_INVALID_STATE;
rgrover1 240:693a1f145b5a 93 }
rgrover1 240:693a1f145b5a 94 }
rgrover1 240:693a1f145b5a 95
rgrover1 240:693a1f145b5a 96 return BLE_ERROR_NONE;
rgrover1 240:693a1f145b5a 97 }
rgrover1 240:693a1f145b5a 98
rgrover1 240:693a1f145b5a 99 void
rgrover1 241:75b69581d1dd 100 NordicServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response)
rgrover1 240:693a1f145b5a 101 {
rgrover1 243:73fc02cc20b1 102 serviceIndex = 0;
rgrover1 243:73fc02cc20b1 103 numServices = response->count;
rgrover1 240:693a1f145b5a 104
rgrover1 240:693a1f145b5a 105 /* Account for the limitation on the number of discovered services we can handle at a time. */
rgrover1 243:73fc02cc20b1 106 if (numServices > BLE_DB_DISCOVERY_MAX_SRV) {
rgrover1 243:73fc02cc20b1 107 numServices = BLE_DB_DISCOVERY_MAX_SRV;
rgrover1 240:693a1f145b5a 108 }
rgrover1 240:693a1f145b5a 109
rgrover1 243:73fc02cc20b1 110 for (unsigned serviceIndex = 0; serviceIndex < numServices; serviceIndex++) {
rgrover1 240:693a1f145b5a 111 services[serviceIndex].setup(response->services[serviceIndex].uuid.uuid,
rgrover1 240:693a1f145b5a 112 response->services[serviceIndex].handle_range.start_handle,
rgrover1 240:693a1f145b5a 113 response->services[serviceIndex].handle_range.end_handle);
rgrover1 240:693a1f145b5a 114 }
rgrover1 240:693a1f145b5a 115 }
rgrover1 240:693a1f145b5a 116
rgrover1 240:693a1f145b5a 117 void
rgrover1 241:75b69581d1dd 118 NordicServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response)
rgrover1 240:693a1f145b5a 119 {
rgrover1 243:73fc02cc20b1 120 characteristicIndex = 0;
rgrover1 243:73fc02cc20b1 121 numCharacteristics = response->count;
rgrover1 240:693a1f145b5a 122
rgrover1 240:693a1f145b5a 123 /* Account for the limitation on the number of discovered characteristics we can handle at a time. */
rgrover1 243:73fc02cc20b1 124 if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) {
rgrover1 243:73fc02cc20b1 125 numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV;
rgrover1 240:693a1f145b5a 126 }
rgrover1 240:693a1f145b5a 127
rgrover1 243:73fc02cc20b1 128 for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) {
rgrover1 240:693a1f145b5a 129 characteristics[charIndex].setup(response->chars[charIndex].uuid.uuid,
rgrover1 240:693a1f145b5a 130 *(const uint8_t *)(&response->chars[charIndex].char_props),
rgrover1 240:693a1f145b5a 131 response->chars[charIndex].handle_decl,
rgrover1 240:693a1f145b5a 132 response->chars[charIndex].handle_value);
rgrover1 240:693a1f145b5a 133 }
rgrover1 244:a966506d1e5b 134 }
rgrover1 244:a966506d1e5b 135
rgrover1 252:d4e0cf5e8751 136 void
rgrover1 252:d4e0cf5e8751 137 NordicServiceDiscovery::progressCharacteristicDiscovery(void)
rgrover1 252:d4e0cf5e8751 138 {
rgrover1 277:ae6e5129b395 139 /* Iterate through the previously discovered characteristics cached in characteristics[]. */
rgrover1 252:d4e0cf5e8751 140 while (cDiscoveryActive && (characteristicIndex < numCharacteristics)) {
rgrover1 256:d228656b0cd1 141 if (characteristicCallback) {
rgrover1 256:d228656b0cd1 142 characteristicCallback(characteristics[characteristicIndex]);
rgrover1 256:d228656b0cd1 143 }
rgrover1 252:d4e0cf5e8751 144
rgrover1 252:d4e0cf5e8751 145 characteristicIndex++;
rgrover1 252:d4e0cf5e8751 146 }
rgrover1 252:d4e0cf5e8751 147
rgrover1 277:ae6e5129b395 148 /* Relaunch discovery of new characteristics beyond the last entry cached in characteristics[]. */
rgrover1 252:d4e0cf5e8751 149 if (cDiscoveryActive) {
rgrover1 277:ae6e5129b395 150 /* Determine the ending handle of the last cached characteristic. */
rgrover1 265:5533ac0adf4b 151 Gap::Handle_t startHandle = characteristics[characteristicIndex - 1].getValueHandle() + 1;
rgrover1 265:5533ac0adf4b 152 Gap::Handle_t endHandle = services[serviceIndex].getEndHandle();
rgrover1 275:f82e0ecba699 153 resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */
rgrover1 252:d4e0cf5e8751 154
rgrover1 252:d4e0cf5e8751 155 if (startHandle < endHandle) {
rgrover1 252:d4e0cf5e8751 156 ble_gattc_handle_range_t handleRange = {
rgrover1 252:d4e0cf5e8751 157 .start_handle = startHandle,
rgrover1 252:d4e0cf5e8751 158 .end_handle = endHandle
rgrover1 252:d4e0cf5e8751 159 };
rgrover1 259:62d6bf03e6a4 160 if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) {
rgrover1 259:62d6bf03e6a4 161 terminateCharacteristicDiscovery();
rgrover1 259:62d6bf03e6a4 162 }
rgrover1 252:d4e0cf5e8751 163 } else {
rgrover1 278:91705df8495e 164 terminateCharacteristicDiscovery();
rgrover1 252:d4e0cf5e8751 165 }
rgrover1 252:d4e0cf5e8751 166 }
rgrover1 252:d4e0cf5e8751 167 }
rgrover1 252:d4e0cf5e8751 168
rgrover1 252:d4e0cf5e8751 169 void
rgrover1 252:d4e0cf5e8751 170 NordicServiceDiscovery::progressServiceDiscovery(void)
rgrover1 252:d4e0cf5e8751 171 {
rgrover1 277:ae6e5129b395 172 /* Iterate through the previously discovered services cached in services[]. */
rgrover1 252:d4e0cf5e8751 173 while (sDiscoveryActive && (serviceIndex < numServices)) {
rgrover1 278:91705df8495e 174 if ((matchingServiceUUID == ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
rgrover1 278:91705df8495e 175 (matchingServiceUUID == services[serviceIndex].getShortUUID())) {
rgrover1 278:91705df8495e 176 if (serviceCallback) {
rgrover1 278:91705df8495e 177 serviceCallback(services[serviceIndex]);
rgrover1 278:91705df8495e 178 }
rgrover1 252:d4e0cf5e8751 179
rgrover1 278:91705df8495e 180 if (sDiscoveryActive && characteristicCallback) {
rgrover1 278:91705df8495e 181 launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle());
rgrover1 278:91705df8495e 182 } else {
rgrover1 278:91705df8495e 183 serviceIndex++;
rgrover1 278:91705df8495e 184 }
rgrover1 252:d4e0cf5e8751 185 } else {
rgrover1 278:91705df8495e 186 serviceIndex++;
rgrover1 252:d4e0cf5e8751 187 }
rgrover1 252:d4e0cf5e8751 188 }
rgrover1 277:ae6e5129b395 189
rgrover1 277:ae6e5129b395 190 /* Relaunch discovery of new services beyond the last entry cached in services[]. */
rgrover1 252:d4e0cf5e8751 191 if (sDiscoveryActive && (numServices > 0) && (serviceIndex > 0)) {
rgrover1 277:ae6e5129b395 192 /* Determine the ending handle of the last cached service. */
rgrover1 265:5533ac0adf4b 193 Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle();
rgrover1 275:f82e0ecba699 194 resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */
rgrover1 252:d4e0cf5e8751 195
rgrover1 259:62d6bf03e6a4 196 if (sd_ble_gattc_primary_services_discover(connHandle, endHandle, NULL) != NRF_SUCCESS) {
rgrover1 259:62d6bf03e6a4 197 terminateServiceDiscovery();
rgrover1 259:62d6bf03e6a4 198 }
rgrover1 252:d4e0cf5e8751 199 }
rgrover1 252:d4e0cf5e8751 200 }
rgrover1 252:d4e0cf5e8751 201
rgrover1 244:a966506d1e5b 202 void bleGattcEventHandler(const ble_evt_t *p_ble_evt)
rgrover1 244:a966506d1e5b 203 {
rgrover1 244:a966506d1e5b 204 switch (p_ble_evt->header.evt_id) {
rgrover1 244:a966506d1e5b 205 case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
rgrover1 244:a966506d1e5b 206 switch (p_ble_evt->evt.gattc_evt.gatt_status) {
rgrover1 244:a966506d1e5b 207 case BLE_GATT_STATUS_SUCCESS:
rgrover1 279:26e3f0ef1e14 208 sdSingleton.setupDiscoveredServices(&p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp);
rgrover1 244:a966506d1e5b 209 break;
rgrover1 244:a966506d1e5b 210
rgrover1 244:a966506d1e5b 211 case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
rgrover1 244:a966506d1e5b 212 default:
rgrover1 279:26e3f0ef1e14 213 sdSingleton.terminate();
rgrover1 244:a966506d1e5b 214 break;
rgrover1 244:a966506d1e5b 215 }
rgrover1 244:a966506d1e5b 216 break;
rgrover1 244:a966506d1e5b 217
rgrover1 244:a966506d1e5b 218 case BLE_GATTC_EVT_CHAR_DISC_RSP:
rgrover1 244:a966506d1e5b 219 switch (p_ble_evt->evt.gattc_evt.gatt_status) {
rgrover1 244:a966506d1e5b 220 case BLE_GATT_STATUS_SUCCESS:
rgrover1 279:26e3f0ef1e14 221 sdSingleton.setupDiscoveredCharacteristics(&p_ble_evt->evt.gattc_evt.params.char_disc_rsp);
rgrover1 244:a966506d1e5b 222 break;
rgrover1 244:a966506d1e5b 223
rgrover1 244:a966506d1e5b 224 case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
rgrover1 244:a966506d1e5b 225 default:
rgrover1 279:26e3f0ef1e14 226 sdSingleton.terminateCharacteristicDiscovery();
rgrover1 244:a966506d1e5b 227 break;
rgrover1 244:a966506d1e5b 228 }
rgrover1 244:a966506d1e5b 229 break;
rgrover1 244:a966506d1e5b 230 }
rgrover1 244:a966506d1e5b 231
rgrover1 279:26e3f0ef1e14 232 sdSingleton.progressCharacteristicDiscovery();
rgrover1 279:26e3f0ef1e14 233 sdSingleton.progressServiceDiscovery();
rgrover1 240:693a1f145b5a 234 }