test

Dependencies:   nrf51-sdk

Dependents:   microbit-dal

Fork of nRF51822 by Lancaster University

Committer:
rgrover1
Date:
Fri Jun 19 15:55:30 2015 +0100
Revision:
312:d55797e0d632
Parent:
311:5d5abc30e3a8
Child:
315:044071756a8d
Synchronized with git rev 2e38bb80
Author: Rohit Grover
flesh out nRFDiscoveredCharacteristic::read()

Who changed what in which revision?

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