test

Dependencies:   nrf51-sdk

Dependents:   microbit-dal

Fork of nRF51822 by Lancaster University

Committer:
rgrover1
Date:
Fri Jun 19 15:55:27 2015 +0100
Revision:
285:55ac765bcc8d
Parent:
284:29fb6af6671d
Child:
286:042b01e59cf8
Synchronized with git rev ede98b00
Author: Rohit Grover
UUID types have moved into UUID class.

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 239:693a1f145b5a 17 #include "blecommon.h"
rgrover1 239:693a1f145b5a 18 #include "UUID.h"
rgrover1 239:693a1f145b5a 19 #include "Gap.h"
rgrover1 239:693a1f145b5a 20 #include "nrf_error.h"
rgrover1 239:693a1f145b5a 21 #include "btle_discovery.h"
rgrover1 239:693a1f145b5a 22 #include "ble_err.h"
rgrover1 243:a966506d1e5b 23
rgrover1 278:26e3f0ef1e14 24 static NordicServiceDiscovery sdSingleton;
rgrover1 239:693a1f145b5a 25
rgrover1 239:693a1f145b5a 26 ble_error_t
rgrover1 275:fd709cd8b1b2 27 ServiceDiscovery::launch(Gap::Handle_t connectionHandle,
rgrover1 275:fd709cd8b1b2 28 ServiceCallback_t sc,
rgrover1 275:fd709cd8b1b2 29 CharacteristicCallback_t cc,
rgrover1 275:fd709cd8b1b2 30 const UUID &matchingServiceUUIDIn,
rgrover1 275:fd709cd8b1b2 31 const UUID &matchingCharacteristicUUIDIn)
rgrover1 239:693a1f145b5a 32 {
rgrover1 281:2280bb1a9a9e 33 if (isActive()) {
rgrover1 281:2280bb1a9a9e 34 return BLE_ERROR_INVALID_STATE;
rgrover1 281:2280bb1a9a9e 35 }
rgrover1 281:2280bb1a9a9e 36
rgrover1 278:26e3f0ef1e14 37 sdSingleton.serviceCallback = sc;
rgrover1 278:26e3f0ef1e14 38 sdSingleton.characteristicCallback = cc;
rgrover1 278:26e3f0ef1e14 39 sdSingleton.matchingServiceUUID = matchingServiceUUIDIn;
rgrover1 278:26e3f0ef1e14 40 sdSingleton.matchingCharacteristicUUID = matchingCharacteristicUUIDIn;
rgrover1 273:8ada9e8111a3 41
rgrover1 278:26e3f0ef1e14 42 sdSingleton.serviceDiscoveryStarted(connectionHandle);
rgrover1 239:693a1f145b5a 43
rgrover1 239:693a1f145b5a 44 uint32_t rc;
rgrover1 248:71ef03789dd3 45 if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, NordicServiceDiscovery::SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) {
rgrover1 278:26e3f0ef1e14 46 sdSingleton.terminate();
rgrover1 239:693a1f145b5a 47 switch (rc) {
rgrover1 239:693a1f145b5a 48 case NRF_ERROR_INVALID_PARAM:
rgrover1 239:693a1f145b5a 49 case BLE_ERROR_INVALID_CONN_HANDLE:
rgrover1 239:693a1f145b5a 50 return BLE_ERROR_INVALID_PARAM;
rgrover1 239:693a1f145b5a 51 case NRF_ERROR_BUSY:
rgrover1 239:693a1f145b5a 52 return BLE_STACK_BUSY;
rgrover1 239:693a1f145b5a 53 default:
rgrover1 239:693a1f145b5a 54 case NRF_ERROR_INVALID_STATE:
rgrover1 239:693a1f145b5a 55 return BLE_ERROR_INVALID_STATE;
rgrover1 239:693a1f145b5a 56 }
rgrover1 239:693a1f145b5a 57 }
rgrover1 239:693a1f145b5a 58
rgrover1 239:693a1f145b5a 59 return BLE_ERROR_NONE;
rgrover1 239:693a1f145b5a 60 }
rgrover1 239:693a1f145b5a 61
rgrover1 248:71ef03789dd3 62 void
rgrover1 248:71ef03789dd3 63 ServiceDiscovery::terminate(void)
rgrover1 248:71ef03789dd3 64 {
rgrover1 278:26e3f0ef1e14 65 sdSingleton.terminateServiceDiscovery();
rgrover1 248:71ef03789dd3 66 }
rgrover1 248:71ef03789dd3 67
rgrover1 279:6e5e79f1fb61 68 bool
rgrover1 279:6e5e79f1fb61 69 ServiceDiscovery::isActive(void)
rgrover1 279:6e5e79f1fb61 70 {
rgrover1 279:6e5e79f1fb61 71 return sdSingleton.isActive();
rgrover1 279:6e5e79f1fb61 72 }
rgrover1 279:6e5e79f1fb61 73
rgrover1 280:cbaa4cb83548 74 void ServiceDiscovery::onTermination(TerminationCallback_t callback) {
rgrover1 280:cbaa4cb83548 75 sdSingleton.setOnTermination(callback);
rgrover1 280:cbaa4cb83548 76 }
rgrover1 280:cbaa4cb83548 77
rgrover1 243:a966506d1e5b 78 ble_error_t
rgrover1 252:4b3f294415f5 79 NordicServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHandle,
rgrover1 252:4b3f294415f5 80 Gap::Handle_t startHandle,
rgrover1 252:4b3f294415f5 81 Gap::Handle_t endHandle)
rgrover1 252:4b3f294415f5 82 {
rgrover1 278:26e3f0ef1e14 83 sdSingleton.characteristicDiscoveryStarted(connectionHandle);
rgrover1 239:693a1f145b5a 84
rgrover1 239:693a1f145b5a 85 ble_gattc_handle_range_t handleRange = {
rgrover1 239:693a1f145b5a 86 .start_handle = startHandle,
rgrover1 239:693a1f145b5a 87 .end_handle = endHandle
rgrover1 239:693a1f145b5a 88 };
rgrover1 239:693a1f145b5a 89 uint32_t rc;
rgrover1 239:693a1f145b5a 90 if ((rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange)) != NRF_SUCCESS) {
rgrover1 278:26e3f0ef1e14 91 sdSingleton.terminateCharacteristicDiscovery();
rgrover1 239:693a1f145b5a 92 switch (rc) {
rgrover1 239:693a1f145b5a 93 case BLE_ERROR_INVALID_CONN_HANDLE:
rgrover1 239:693a1f145b5a 94 case NRF_ERROR_INVALID_ADDR:
rgrover1 239:693a1f145b5a 95 return BLE_ERROR_INVALID_PARAM;
rgrover1 239:693a1f145b5a 96 case NRF_ERROR_BUSY:
rgrover1 239:693a1f145b5a 97 return BLE_STACK_BUSY;
rgrover1 239:693a1f145b5a 98 default:
rgrover1 239:693a1f145b5a 99 case NRF_ERROR_INVALID_STATE:
rgrover1 239:693a1f145b5a 100 return BLE_ERROR_INVALID_STATE;
rgrover1 239:693a1f145b5a 101 }
rgrover1 239:693a1f145b5a 102 }
rgrover1 239:693a1f145b5a 103
rgrover1 239:693a1f145b5a 104 return BLE_ERROR_NONE;
rgrover1 239:693a1f145b5a 105 }
rgrover1 239:693a1f145b5a 106
rgrover1 283:c4c2aeab86c3 107 #include <stdio.h>
rgrover1 283:c4c2aeab86c3 108
rgrover1 239:693a1f145b5a 109 void
rgrover1 240:75b69581d1dd 110 NordicServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response)
rgrover1 239:693a1f145b5a 111 {
rgrover1 242:73fc02cc20b1 112 serviceIndex = 0;
rgrover1 242:73fc02cc20b1 113 numServices = response->count;
rgrover1 239:693a1f145b5a 114
rgrover1 239:693a1f145b5a 115 /* Account for the limitation on the number of discovered services we can handle at a time. */
rgrover1 242:73fc02cc20b1 116 if (numServices > BLE_DB_DISCOVERY_MAX_SRV) {
rgrover1 242:73fc02cc20b1 117 numServices = BLE_DB_DISCOVERY_MAX_SRV;
rgrover1 239:693a1f145b5a 118 }
rgrover1 239:693a1f145b5a 119
rgrover1 242:73fc02cc20b1 120 for (unsigned serviceIndex = 0; serviceIndex < numServices; serviceIndex++) {
rgrover1 283:c4c2aeab86c3 121 if (response->services[serviceIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
rgrover1 283:c4c2aeab86c3 122 printf("service[0] uuid type %u\r\n", response->services[0].uuid.type);
rgrover1 283:c4c2aeab86c3 123 }
rgrover1 283:c4c2aeab86c3 124 // sd_ble_gattc_char_value_by_uuid_read
rgrover1 239:693a1f145b5a 125 services[serviceIndex].setup(response->services[serviceIndex].uuid.uuid,
rgrover1 239:693a1f145b5a 126 response->services[serviceIndex].handle_range.start_handle,
rgrover1 239:693a1f145b5a 127 response->services[serviceIndex].handle_range.end_handle);
rgrover1 239:693a1f145b5a 128 }
rgrover1 239:693a1f145b5a 129 }
rgrover1 239:693a1f145b5a 130
rgrover1 239:693a1f145b5a 131 void
rgrover1 240:75b69581d1dd 132 NordicServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response)
rgrover1 239:693a1f145b5a 133 {
rgrover1 242:73fc02cc20b1 134 characteristicIndex = 0;
rgrover1 242:73fc02cc20b1 135 numCharacteristics = response->count;
rgrover1 239:693a1f145b5a 136
rgrover1 239:693a1f145b5a 137 /* Account for the limitation on the number of discovered characteristics we can handle at a time. */
rgrover1 242:73fc02cc20b1 138 if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) {
rgrover1 242:73fc02cc20b1 139 numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV;
rgrover1 239:693a1f145b5a 140 }
rgrover1 239:693a1f145b5a 141
rgrover1 242:73fc02cc20b1 142 for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) {
rgrover1 239:693a1f145b5a 143 characteristics[charIndex].setup(response->chars[charIndex].uuid.uuid,
rgrover1 239:693a1f145b5a 144 *(const uint8_t *)(&response->chars[charIndex].char_props),
rgrover1 239:693a1f145b5a 145 response->chars[charIndex].handle_decl,
rgrover1 239:693a1f145b5a 146 response->chars[charIndex].handle_value);
rgrover1 239:693a1f145b5a 147 }
rgrover1 243:a966506d1e5b 148 }
rgrover1 243:a966506d1e5b 149
rgrover1 251:d4e0cf5e8751 150 void
rgrover1 251:d4e0cf5e8751 151 NordicServiceDiscovery::progressCharacteristicDiscovery(void)
rgrover1 251:d4e0cf5e8751 152 {
rgrover1 276:ae6e5129b395 153 /* Iterate through the previously discovered characteristics cached in characteristics[]. */
rgrover1 251:d4e0cf5e8751 154 while (cDiscoveryActive && (characteristicIndex < numCharacteristics)) {
rgrover1 285:55ac765bcc8d 155 if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
rgrover1 282:6633922380bf 156 (matchingCharacteristicUUID == characteristics[characteristicIndex].getShortUUID())) {
rgrover1 282:6633922380bf 157 if (characteristicCallback) {
rgrover1 282:6633922380bf 158 characteristicCallback(characteristics[characteristicIndex]);
rgrover1 282:6633922380bf 159 }
rgrover1 255:d228656b0cd1 160 }
rgrover1 251:d4e0cf5e8751 161
rgrover1 251:d4e0cf5e8751 162 characteristicIndex++;
rgrover1 251:d4e0cf5e8751 163 }
rgrover1 251:d4e0cf5e8751 164
rgrover1 276:ae6e5129b395 165 /* Relaunch discovery of new characteristics beyond the last entry cached in characteristics[]. */
rgrover1 251:d4e0cf5e8751 166 if (cDiscoveryActive) {
rgrover1 276:ae6e5129b395 167 /* Determine the ending handle of the last cached characteristic. */
rgrover1 264:5533ac0adf4b 168 Gap::Handle_t startHandle = characteristics[characteristicIndex - 1].getValueHandle() + 1;
rgrover1 264:5533ac0adf4b 169 Gap::Handle_t endHandle = services[serviceIndex].getEndHandle();
rgrover1 274:f82e0ecba699 170 resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */
rgrover1 251:d4e0cf5e8751 171
rgrover1 251:d4e0cf5e8751 172 if (startHandle < endHandle) {
rgrover1 251:d4e0cf5e8751 173 ble_gattc_handle_range_t handleRange = {
rgrover1 251:d4e0cf5e8751 174 .start_handle = startHandle,
rgrover1 251:d4e0cf5e8751 175 .end_handle = endHandle
rgrover1 251:d4e0cf5e8751 176 };
rgrover1 258:62d6bf03e6a4 177 if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) {
rgrover1 258:62d6bf03e6a4 178 terminateCharacteristicDiscovery();
rgrover1 258:62d6bf03e6a4 179 }
rgrover1 251:d4e0cf5e8751 180 } else {
rgrover1 277:91705df8495e 181 terminateCharacteristicDiscovery();
rgrover1 251:d4e0cf5e8751 182 }
rgrover1 251:d4e0cf5e8751 183 }
rgrover1 251:d4e0cf5e8751 184 }
rgrover1 251:d4e0cf5e8751 185
rgrover1 251:d4e0cf5e8751 186 void
rgrover1 251:d4e0cf5e8751 187 NordicServiceDiscovery::progressServiceDiscovery(void)
rgrover1 251:d4e0cf5e8751 188 {
rgrover1 276:ae6e5129b395 189 /* Iterate through the previously discovered services cached in services[]. */
rgrover1 251:d4e0cf5e8751 190 while (sDiscoveryActive && (serviceIndex < numServices)) {
rgrover1 285:55ac765bcc8d 191 if ((matchingServiceUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
rgrover1 277:91705df8495e 192 (matchingServiceUUID == services[serviceIndex].getShortUUID())) {
rgrover1 277:91705df8495e 193 if (serviceCallback) {
rgrover1 277:91705df8495e 194 serviceCallback(services[serviceIndex]);
rgrover1 277:91705df8495e 195 }
rgrover1 251:d4e0cf5e8751 196
rgrover1 277:91705df8495e 197 if (sDiscoveryActive && characteristicCallback) {
rgrover1 277:91705df8495e 198 launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle());
rgrover1 277:91705df8495e 199 } else {
rgrover1 277:91705df8495e 200 serviceIndex++;
rgrover1 277:91705df8495e 201 }
rgrover1 251:d4e0cf5e8751 202 } else {
rgrover1 277:91705df8495e 203 serviceIndex++;
rgrover1 251:d4e0cf5e8751 204 }
rgrover1 251:d4e0cf5e8751 205 }
rgrover1 276:ae6e5129b395 206
rgrover1 276:ae6e5129b395 207 /* Relaunch discovery of new services beyond the last entry cached in services[]. */
rgrover1 251:d4e0cf5e8751 208 if (sDiscoveryActive && (numServices > 0) && (serviceIndex > 0)) {
rgrover1 276:ae6e5129b395 209 /* Determine the ending handle of the last cached service. */
rgrover1 264:5533ac0adf4b 210 Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle();
rgrover1 274:f82e0ecba699 211 resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */
rgrover1 251:d4e0cf5e8751 212
rgrover1 284:29fb6af6671d 213 if (endHandle == SRV_DISC_END_HANDLE) {
rgrover1 258:62d6bf03e6a4 214 terminateServiceDiscovery();
rgrover1 284:29fb6af6671d 215 } else {
rgrover1 284:29fb6af6671d 216 if (sd_ble_gattc_primary_services_discover(connHandle, endHandle, NULL) != NRF_SUCCESS) {
rgrover1 284:29fb6af6671d 217 terminateServiceDiscovery();
rgrover1 284:29fb6af6671d 218 }
rgrover1 258:62d6bf03e6a4 219 }
rgrover1 251:d4e0cf5e8751 220 }
rgrover1 251:d4e0cf5e8751 221 }
rgrover1 251:d4e0cf5e8751 222
rgrover1 243:a966506d1e5b 223 void bleGattcEventHandler(const ble_evt_t *p_ble_evt)
rgrover1 243:a966506d1e5b 224 {
rgrover1 243:a966506d1e5b 225 switch (p_ble_evt->header.evt_id) {
rgrover1 243:a966506d1e5b 226 case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
rgrover1 243:a966506d1e5b 227 switch (p_ble_evt->evt.gattc_evt.gatt_status) {
rgrover1 243:a966506d1e5b 228 case BLE_GATT_STATUS_SUCCESS:
rgrover1 278:26e3f0ef1e14 229 sdSingleton.setupDiscoveredServices(&p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp);
rgrover1 243:a966506d1e5b 230 break;
rgrover1 243:a966506d1e5b 231
rgrover1 243:a966506d1e5b 232 case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
rgrover1 243:a966506d1e5b 233 default:
rgrover1 278:26e3f0ef1e14 234 sdSingleton.terminate();
rgrover1 243:a966506d1e5b 235 break;
rgrover1 243:a966506d1e5b 236 }
rgrover1 243:a966506d1e5b 237 break;
rgrover1 243:a966506d1e5b 238
rgrover1 243:a966506d1e5b 239 case BLE_GATTC_EVT_CHAR_DISC_RSP:
rgrover1 243:a966506d1e5b 240 switch (p_ble_evt->evt.gattc_evt.gatt_status) {
rgrover1 243:a966506d1e5b 241 case BLE_GATT_STATUS_SUCCESS:
rgrover1 278:26e3f0ef1e14 242 sdSingleton.setupDiscoveredCharacteristics(&p_ble_evt->evt.gattc_evt.params.char_disc_rsp);
rgrover1 243:a966506d1e5b 243 break;
rgrover1 243:a966506d1e5b 244
rgrover1 243:a966506d1e5b 245 case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
rgrover1 243:a966506d1e5b 246 default:
rgrover1 278:26e3f0ef1e14 247 sdSingleton.terminateCharacteristicDiscovery();
rgrover1 243:a966506d1e5b 248 break;
rgrover1 243:a966506d1e5b 249 }
rgrover1 243:a966506d1e5b 250 break;
rgrover1 243:a966506d1e5b 251 }
rgrover1 243:a966506d1e5b 252
rgrover1 278:26e3f0ef1e14 253 sdSingleton.progressCharacteristicDiscovery();
rgrover1 278:26e3f0ef1e14 254 sdSingleton.progressServiceDiscovery();
rgrover1 239:693a1f145b5a 255 }