1

Fork of nRF51822 by Nordic Semiconductor

Committer:
ssenwkdw
Date:
Thu Sep 03 13:02:03 2015 +0000
Revision:
429:9c91c46c004c
Parent:
360:7c68c8d67e1f
nono

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 339:e5e2157e8b44 1 /* mbed Microcontroller Library
rgrover1 339:e5e2157e8b44 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 339:e5e2157e8b44 3 *
rgrover1 339:e5e2157e8b44 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 339:e5e2157e8b44 5 * you may not use this file except in compliance with the License.
rgrover1 339:e5e2157e8b44 6 * You may obtain a copy of the License at
rgrover1 339:e5e2157e8b44 7 *
rgrover1 339:e5e2157e8b44 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 339:e5e2157e8b44 9 *
rgrover1 339:e5e2157e8b44 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 339:e5e2157e8b44 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 339:e5e2157e8b44 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 339:e5e2157e8b44 13 * See the License for the specific language governing permissions and
rgrover1 339:e5e2157e8b44 14 * limitations under the License.
rgrover1 339:e5e2157e8b44 15 */
rgrover1 339:e5e2157e8b44 16
rgrover1 339:e5e2157e8b44 17 #ifndef __NRF_SERVICE_DISCOVERY_H__
rgrover1 339:e5e2157e8b44 18 #define __NRF_SERVICE_DISCOVERY_H__
rgrover1 339:e5e2157e8b44 19
rgrover1 360:7c68c8d67e1f 20 #include "ble/ServiceDiscovery.h"
rgrover1 360:7c68c8d67e1f 21 #include "ble/DiscoveredService.h"
rgrover1 339:e5e2157e8b44 22 #include "nRF51DiscoveredCharacteristic.h"
rgrover1 339:e5e2157e8b44 23
rgrover1 339:e5e2157e8b44 24 #include "ble.h"
rgrover1 339:e5e2157e8b44 25 #include "ble_gattc.h"
rgrover1 339:e5e2157e8b44 26
rgrover1 339:e5e2157e8b44 27 class nRF51GattClient; /* forward declaration */
rgrover1 339:e5e2157e8b44 28
rgrover1 339:e5e2157e8b44 29 class nRF51ServiceDiscovery : public ServiceDiscovery
rgrover1 339:e5e2157e8b44 30 {
rgrover1 339:e5e2157e8b44 31 public:
rgrover1 339:e5e2157e8b44 32 static const uint16_t SRV_DISC_START_HANDLE = 0x0001; /**< The start handle value used during service discovery. */
rgrover1 339:e5e2157e8b44 33 static const uint16_t SRV_DISC_END_HANDLE = 0xFFFF; /**< The end handle value used during service discovery. */
rgrover1 339:e5e2157e8b44 34
rgrover1 339:e5e2157e8b44 35 public:
rgrover1 339:e5e2157e8b44 36 static const unsigned BLE_DB_DISCOVERY_MAX_SRV = 4; /**< Maximum number of services we can retain information for after a single discovery. */
rgrover1 339:e5e2157e8b44 37 static const unsigned BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV = 4; /**< Maximum number of characteristics per service we can retain information for. */
rgrover1 339:e5e2157e8b44 38
rgrover1 339:e5e2157e8b44 39 public:
rgrover1 339:e5e2157e8b44 40 nRF51ServiceDiscovery(nRF51GattClient *gattcIn) :
rgrover1 339:e5e2157e8b44 41 gattc(gattcIn),
rgrover1 339:e5e2157e8b44 42 serviceIndex(0),
rgrover1 339:e5e2157e8b44 43 numServices(0),
rgrover1 339:e5e2157e8b44 44 characteristicIndex(0),
rgrover1 339:e5e2157e8b44 45 numCharacteristics(0),
rgrover1 339:e5e2157e8b44 46 state(INACTIVE),
rgrover1 339:e5e2157e8b44 47 services(),
rgrover1 339:e5e2157e8b44 48 characteristics(),
rgrover1 339:e5e2157e8b44 49 serviceUUIDDiscoveryQueue(this),
rgrover1 339:e5e2157e8b44 50 charUUIDDiscoveryQueue(this),
rgrover1 339:e5e2157e8b44 51 onTerminationCallback(NULL) {
rgrover1 339:e5e2157e8b44 52 /* empty */
rgrover1 339:e5e2157e8b44 53 }
rgrover1 339:e5e2157e8b44 54
rgrover1 339:e5e2157e8b44 55 virtual ble_error_t launch(Gap::Handle_t connectionHandle,
rgrover1 339:e5e2157e8b44 56 ServiceDiscovery::ServiceCallback_t sc,
rgrover1 339:e5e2157e8b44 57 ServiceDiscovery::CharacteristicCallback_t cc,
rgrover1 339:e5e2157e8b44 58 const UUID &matchingServiceUUIDIn,
rgrover1 339:e5e2157e8b44 59 const UUID &matchingCharacteristicUUIDIn)
rgrover1 339:e5e2157e8b44 60 {
rgrover1 339:e5e2157e8b44 61 if (isActive()) {
rgrover1 339:e5e2157e8b44 62 return BLE_ERROR_INVALID_STATE;
rgrover1 339:e5e2157e8b44 63 }
rgrover1 339:e5e2157e8b44 64
rgrover1 339:e5e2157e8b44 65 serviceCallback = sc;
rgrover1 339:e5e2157e8b44 66 characteristicCallback = cc;
rgrover1 339:e5e2157e8b44 67 matchingServiceUUID = matchingServiceUUIDIn;
rgrover1 339:e5e2157e8b44 68 matchingCharacteristicUUID = matchingCharacteristicUUIDIn;
rgrover1 339:e5e2157e8b44 69
rgrover1 339:e5e2157e8b44 70 serviceDiscoveryStarted(connectionHandle);
rgrover1 339:e5e2157e8b44 71
rgrover1 339:e5e2157e8b44 72 uint32_t rc;
rgrover1 339:e5e2157e8b44 73 if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) {
rgrover1 339:e5e2157e8b44 74 terminate();
rgrover1 339:e5e2157e8b44 75 switch (rc) {
rgrover1 339:e5e2157e8b44 76 case NRF_ERROR_INVALID_PARAM:
rgrover1 339:e5e2157e8b44 77 case BLE_ERROR_INVALID_CONN_HANDLE:
rgrover1 339:e5e2157e8b44 78 return BLE_ERROR_INVALID_PARAM;
rgrover1 339:e5e2157e8b44 79 case NRF_ERROR_BUSY:
rgrover1 339:e5e2157e8b44 80 return BLE_STACK_BUSY;
rgrover1 339:e5e2157e8b44 81 default:
rgrover1 339:e5e2157e8b44 82 case NRF_ERROR_INVALID_STATE:
rgrover1 339:e5e2157e8b44 83 return BLE_ERROR_INVALID_STATE;
rgrover1 339:e5e2157e8b44 84 }
rgrover1 339:e5e2157e8b44 85 }
rgrover1 339:e5e2157e8b44 86
rgrover1 339:e5e2157e8b44 87 return BLE_ERROR_NONE;
rgrover1 339:e5e2157e8b44 88 }
rgrover1 339:e5e2157e8b44 89
rgrover1 339:e5e2157e8b44 90 virtual bool isActive(void) const {
rgrover1 339:e5e2157e8b44 91 return state != INACTIVE;
rgrover1 339:e5e2157e8b44 92 }
rgrover1 339:e5e2157e8b44 93
rgrover1 339:e5e2157e8b44 94 virtual void terminate(void) {
rgrover1 339:e5e2157e8b44 95 terminateServiceDiscovery();
rgrover1 339:e5e2157e8b44 96 }
rgrover1 339:e5e2157e8b44 97
rgrover1 339:e5e2157e8b44 98 virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) {
rgrover1 339:e5e2157e8b44 99 onTerminationCallback = callback;
rgrover1 339:e5e2157e8b44 100 }
rgrover1 339:e5e2157e8b44 101
rgrover1 339:e5e2157e8b44 102 private:
rgrover1 339:e5e2157e8b44 103 ble_error_t launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, Gap::Handle_t startHandle, Gap::Handle_t endHandle);
rgrover1 339:e5e2157e8b44 104
rgrover1 339:e5e2157e8b44 105 private:
rgrover1 339:e5e2157e8b44 106 void setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response);
rgrover1 339:e5e2157e8b44 107 void setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response);
rgrover1 339:e5e2157e8b44 108
rgrover1 339:e5e2157e8b44 109 void triggerServiceUUIDDiscovery(void);
rgrover1 339:e5e2157e8b44 110 void processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response);
rgrover1 339:e5e2157e8b44 111 void removeFirstServiceNeedingUUIDDiscovery(void);
rgrover1 339:e5e2157e8b44 112
rgrover1 339:e5e2157e8b44 113 void terminateServiceDiscovery(void) {
rgrover1 339:e5e2157e8b44 114 bool wasActive = isActive();
rgrover1 339:e5e2157e8b44 115 state = INACTIVE;
rgrover1 339:e5e2157e8b44 116
rgrover1 339:e5e2157e8b44 117 if (wasActive && onTerminationCallback) {
rgrover1 339:e5e2157e8b44 118 onTerminationCallback(connHandle);
rgrover1 339:e5e2157e8b44 119 }
rgrover1 339:e5e2157e8b44 120 }
rgrover1 339:e5e2157e8b44 121
rgrover1 339:e5e2157e8b44 122 void terminateCharacteristicDiscovery(void) {
rgrover1 339:e5e2157e8b44 123 if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) {
rgrover1 339:e5e2157e8b44 124 state = SERVICE_DISCOVERY_ACTIVE;
rgrover1 339:e5e2157e8b44 125 }
rgrover1 339:e5e2157e8b44 126 serviceIndex++; /* Progress service index to keep discovery alive. */
rgrover1 339:e5e2157e8b44 127 }
rgrover1 339:e5e2157e8b44 128
rgrover1 339:e5e2157e8b44 129 private:
rgrover1 339:e5e2157e8b44 130 void resetDiscoveredServices(void) {
rgrover1 339:e5e2157e8b44 131 numServices = 0;
rgrover1 339:e5e2157e8b44 132 serviceIndex = 0;
rgrover1 339:e5e2157e8b44 133 }
rgrover1 339:e5e2157e8b44 134
rgrover1 339:e5e2157e8b44 135 void resetDiscoveredCharacteristics(void) {
rgrover1 339:e5e2157e8b44 136 numCharacteristics = 0;
rgrover1 339:e5e2157e8b44 137 characteristicIndex = 0;
rgrover1 339:e5e2157e8b44 138 }
rgrover1 339:e5e2157e8b44 139
rgrover1 339:e5e2157e8b44 140 private:
rgrover1 339:e5e2157e8b44 141 void serviceDiscoveryStarted(Gap::Handle_t connectionHandle) {
rgrover1 339:e5e2157e8b44 142 connHandle = connectionHandle;
rgrover1 339:e5e2157e8b44 143 resetDiscoveredServices();
rgrover1 339:e5e2157e8b44 144 state = SERVICE_DISCOVERY_ACTIVE;
rgrover1 339:e5e2157e8b44 145 }
rgrover1 339:e5e2157e8b44 146
rgrover1 339:e5e2157e8b44 147 private:
rgrover1 339:e5e2157e8b44 148 void characteristicDiscoveryStarted(Gap::Handle_t connectionHandle) {
rgrover1 339:e5e2157e8b44 149 connHandle = connectionHandle;
rgrover1 339:e5e2157e8b44 150 resetDiscoveredCharacteristics();
rgrover1 339:e5e2157e8b44 151 state = CHARACTERISTIC_DISCOVERY_ACTIVE;
rgrover1 339:e5e2157e8b44 152 }
rgrover1 339:e5e2157e8b44 153
rgrover1 339:e5e2157e8b44 154 private:
rgrover1 339:e5e2157e8b44 155 /**
rgrover1 339:e5e2157e8b44 156 * A datatype to contain service-indices for which long UUIDs need to be
rgrover1 339:e5e2157e8b44 157 * discovered using read_val_by_uuid().
rgrover1 339:e5e2157e8b44 158 */
rgrover1 339:e5e2157e8b44 159 class ServiceUUIDDiscoveryQueue {
rgrover1 339:e5e2157e8b44 160 public:
rgrover1 339:e5e2157e8b44 161 ServiceUUIDDiscoveryQueue(nRF51ServiceDiscovery *parent) :
rgrover1 339:e5e2157e8b44 162 numIndices(0),
rgrover1 339:e5e2157e8b44 163 serviceIndices(),
rgrover1 339:e5e2157e8b44 164 parentDiscoveryObject(parent) {
rgrover1 339:e5e2157e8b44 165 /* empty */
rgrover1 339:e5e2157e8b44 166 }
rgrover1 339:e5e2157e8b44 167
rgrover1 339:e5e2157e8b44 168 public:
rgrover1 339:e5e2157e8b44 169 void reset(void) {
rgrover1 339:e5e2157e8b44 170 numIndices = 0;
rgrover1 339:e5e2157e8b44 171 for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
rgrover1 339:e5e2157e8b44 172 serviceIndices[i] = INVALID_INDEX;
rgrover1 339:e5e2157e8b44 173 }
rgrover1 339:e5e2157e8b44 174 }
rgrover1 339:e5e2157e8b44 175 void enqueue(int serviceIndex) {
rgrover1 339:e5e2157e8b44 176 serviceIndices[numIndices++] = serviceIndex;
rgrover1 339:e5e2157e8b44 177 }
rgrover1 339:e5e2157e8b44 178 int dequeue(void) {
rgrover1 339:e5e2157e8b44 179 if (numIndices == 0) {
rgrover1 339:e5e2157e8b44 180 return INVALID_INDEX;
rgrover1 339:e5e2157e8b44 181 }
rgrover1 339:e5e2157e8b44 182
rgrover1 339:e5e2157e8b44 183 unsigned valueToReturn = serviceIndices[0];
rgrover1 339:e5e2157e8b44 184 numIndices--;
rgrover1 339:e5e2157e8b44 185 for (unsigned i = 0; i < numIndices; i++) {
rgrover1 339:e5e2157e8b44 186 serviceIndices[i] = serviceIndices[i + 1];
rgrover1 339:e5e2157e8b44 187 }
rgrover1 339:e5e2157e8b44 188
rgrover1 339:e5e2157e8b44 189 return valueToReturn;
rgrover1 339:e5e2157e8b44 190 }
rgrover1 339:e5e2157e8b44 191 unsigned getFirst(void) const {
rgrover1 339:e5e2157e8b44 192 return serviceIndices[0];
rgrover1 339:e5e2157e8b44 193 }
rgrover1 339:e5e2157e8b44 194 size_t getCount(void) const {
rgrover1 339:e5e2157e8b44 195 return numIndices;
rgrover1 339:e5e2157e8b44 196 }
rgrover1 339:e5e2157e8b44 197
rgrover1 339:e5e2157e8b44 198 /**
rgrover1 339:e5e2157e8b44 199 * Trigger UUID discovery for the first of the enqueued ServiceIndices.
rgrover1 339:e5e2157e8b44 200 */
rgrover1 339:e5e2157e8b44 201 void triggerFirst(void);
rgrover1 339:e5e2157e8b44 202
rgrover1 339:e5e2157e8b44 203 private:
rgrover1 339:e5e2157e8b44 204 static const int INVALID_INDEX = -1;
rgrover1 339:e5e2157e8b44 205
rgrover1 339:e5e2157e8b44 206 private:
rgrover1 339:e5e2157e8b44 207 size_t numIndices;
rgrover1 339:e5e2157e8b44 208 int serviceIndices[BLE_DB_DISCOVERY_MAX_SRV];
rgrover1 339:e5e2157e8b44 209
rgrover1 339:e5e2157e8b44 210 nRF51ServiceDiscovery *parentDiscoveryObject;
rgrover1 339:e5e2157e8b44 211 };
rgrover1 339:e5e2157e8b44 212 friend class ServiceUUIDDiscoveryQueue;
rgrover1 339:e5e2157e8b44 213
rgrover1 339:e5e2157e8b44 214 /**
rgrover1 339:e5e2157e8b44 215 * A datatype to contain characteristic-indices for which long UUIDs need to
rgrover1 339:e5e2157e8b44 216 * be discovered using read_val_by_uuid().
rgrover1 339:e5e2157e8b44 217 */
rgrover1 339:e5e2157e8b44 218 class CharUUIDDiscoveryQueue {
rgrover1 339:e5e2157e8b44 219 public:
rgrover1 339:e5e2157e8b44 220 CharUUIDDiscoveryQueue(nRF51ServiceDiscovery *parent) :
rgrover1 339:e5e2157e8b44 221 numIndices(0),
rgrover1 339:e5e2157e8b44 222 charIndices(),
rgrover1 339:e5e2157e8b44 223 parentDiscoveryObject(parent) {
rgrover1 339:e5e2157e8b44 224 /* empty */
rgrover1 339:e5e2157e8b44 225 }
rgrover1 339:e5e2157e8b44 226
rgrover1 339:e5e2157e8b44 227 public:
rgrover1 339:e5e2157e8b44 228 void reset(void) {
rgrover1 339:e5e2157e8b44 229 numIndices = 0;
rgrover1 339:e5e2157e8b44 230 for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
rgrover1 339:e5e2157e8b44 231 charIndices[i] = INVALID_INDEX;
rgrover1 339:e5e2157e8b44 232 }
rgrover1 339:e5e2157e8b44 233 }
rgrover1 339:e5e2157e8b44 234 void enqueue(int serviceIndex) {
rgrover1 339:e5e2157e8b44 235 charIndices[numIndices++] = serviceIndex;
rgrover1 339:e5e2157e8b44 236 }
rgrover1 339:e5e2157e8b44 237 int dequeue(void) {
rgrover1 339:e5e2157e8b44 238 if (numIndices == 0) {
rgrover1 339:e5e2157e8b44 239 return INVALID_INDEX;
rgrover1 339:e5e2157e8b44 240 }
rgrover1 339:e5e2157e8b44 241
rgrover1 339:e5e2157e8b44 242 unsigned valueToReturn = charIndices[0];
rgrover1 339:e5e2157e8b44 243 numIndices--;
rgrover1 339:e5e2157e8b44 244 for (unsigned i = 0; i < numIndices; i++) {
rgrover1 339:e5e2157e8b44 245 charIndices[i] = charIndices[i + 1];
rgrover1 339:e5e2157e8b44 246 }
rgrover1 339:e5e2157e8b44 247
rgrover1 339:e5e2157e8b44 248 return valueToReturn;
rgrover1 339:e5e2157e8b44 249 }
rgrover1 339:e5e2157e8b44 250 unsigned getFirst(void) const {
rgrover1 339:e5e2157e8b44 251 return charIndices[0];
rgrover1 339:e5e2157e8b44 252 }
rgrover1 339:e5e2157e8b44 253 size_t getCount(void) const {
rgrover1 339:e5e2157e8b44 254 return numIndices;
rgrover1 339:e5e2157e8b44 255 }
rgrover1 339:e5e2157e8b44 256
rgrover1 339:e5e2157e8b44 257 /**
rgrover1 339:e5e2157e8b44 258 * Trigger UUID discovery for the first of the enqueued charIndices.
rgrover1 339:e5e2157e8b44 259 */
rgrover1 339:e5e2157e8b44 260 void triggerFirst(void);
rgrover1 339:e5e2157e8b44 261
rgrover1 339:e5e2157e8b44 262 private:
rgrover1 339:e5e2157e8b44 263 static const int INVALID_INDEX = -1;
rgrover1 339:e5e2157e8b44 264
rgrover1 339:e5e2157e8b44 265 private:
rgrover1 339:e5e2157e8b44 266 size_t numIndices;
rgrover1 339:e5e2157e8b44 267 int charIndices[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
rgrover1 339:e5e2157e8b44 268
rgrover1 339:e5e2157e8b44 269 nRF51ServiceDiscovery *parentDiscoveryObject;
rgrover1 339:e5e2157e8b44 270 };
rgrover1 339:e5e2157e8b44 271 friend class CharUUIDDiscoveryQueue;
rgrover1 339:e5e2157e8b44 272
rgrover1 339:e5e2157e8b44 273 private:
rgrover1 339:e5e2157e8b44 274 friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt);
rgrover1 339:e5e2157e8b44 275 void progressCharacteristicDiscovery(void);
rgrover1 339:e5e2157e8b44 276 void progressServiceDiscovery(void);
rgrover1 339:e5e2157e8b44 277
rgrover1 339:e5e2157e8b44 278 private:
rgrover1 339:e5e2157e8b44 279 nRF51GattClient *gattc;
rgrover1 339:e5e2157e8b44 280
rgrover1 339:e5e2157e8b44 281 private:
rgrover1 339:e5e2157e8b44 282 uint8_t serviceIndex; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/
rgrover1 339:e5e2157e8b44 283 uint8_t numServices; /**< Number of services at the peers GATT database.*/
rgrover1 339:e5e2157e8b44 284 uint8_t characteristicIndex; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/
rgrover1 339:e5e2157e8b44 285 uint8_t numCharacteristics; /**< Number of characteristics within the service.*/
rgrover1 339:e5e2157e8b44 286
rgrover1 339:e5e2157e8b44 287 enum State_t {
rgrover1 339:e5e2157e8b44 288 INACTIVE,
rgrover1 339:e5e2157e8b44 289 SERVICE_DISCOVERY_ACTIVE,
rgrover1 339:e5e2157e8b44 290 CHARACTERISTIC_DISCOVERY_ACTIVE,
rgrover1 339:e5e2157e8b44 291 DISCOVER_SERVICE_UUIDS,
rgrover1 339:e5e2157e8b44 292 DISCOVER_CHARACTERISTIC_UUIDS,
rgrover1 339:e5e2157e8b44 293 } state;
rgrover1 339:e5e2157e8b44 294
rgrover1 339:e5e2157e8b44 295 DiscoveredService services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered.
rgrover1 339:e5e2157e8b44 296 * This is intended for internal use during service discovery. */
rgrover1 339:e5e2157e8b44 297 nRF51DiscoveredCharacteristic characteristics[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
rgrover1 339:e5e2157e8b44 298
rgrover1 339:e5e2157e8b44 299 ServiceUUIDDiscoveryQueue serviceUUIDDiscoveryQueue;
rgrover1 339:e5e2157e8b44 300 CharUUIDDiscoveryQueue charUUIDDiscoveryQueue;
rgrover1 339:e5e2157e8b44 301
rgrover1 339:e5e2157e8b44 302 TerminationCallback_t onTerminationCallback;
rgrover1 339:e5e2157e8b44 303 };
rgrover1 339:e5e2157e8b44 304
rgrover1 339:e5e2157e8b44 305 #endif /*__NRF_SERVICE_DISCOVERY_H__*/