Michael Galis / nRF51822

Fork of nRF51822 by Nordic Semiconductor

Committer:
rgrover1
Date:
Fri Jun 19 15:55:32 2015 +0100
Revision:
332:b054000833d4
Child:
333:8eedcd324853
Synchronized with git rev 5a4e62f1
Author: Rohit Grover
one massive commit to integrate with GattClient.
DiscoveredCharacteristic still needs to setup gattc pointers.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 332:b054000833d4 1 /* mbed Microcontroller Library
rgrover1 332:b054000833d4 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 332:b054000833d4 3 *
rgrover1 332:b054000833d4 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 332:b054000833d4 5 * you may not use this file except in compliance with the License.
rgrover1 332:b054000833d4 6 * You may obtain a copy of the License at
rgrover1 332:b054000833d4 7 *
rgrover1 332:b054000833d4 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 332:b054000833d4 9 *
rgrover1 332:b054000833d4 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 332:b054000833d4 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 332:b054000833d4 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 332:b054000833d4 13 * See the License for the specific language governing permissions and
rgrover1 332:b054000833d4 14 * limitations under the License.
rgrover1 332:b054000833d4 15 */
rgrover1 332:b054000833d4 16
rgrover1 332:b054000833d4 17 #include "nRFServiceDiscovery.h"
rgrover1 332:b054000833d4 18
rgrover1 332:b054000833d4 19
rgrover1 332:b054000833d4 20 ble_error_t
rgrover1 332:b054000833d4 21 nRFServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHandle,
rgrover1 332:b054000833d4 22 Gap::Handle_t startHandle,
rgrover1 332:b054000833d4 23 Gap::Handle_t endHandle)
rgrover1 332:b054000833d4 24 {
rgrover1 332:b054000833d4 25 characteristicDiscoveryStarted(connectionHandle);
rgrover1 332:b054000833d4 26
rgrover1 332:b054000833d4 27 ble_gattc_handle_range_t handleRange = {
rgrover1 332:b054000833d4 28 .start_handle = startHandle,
rgrover1 332:b054000833d4 29 .end_handle = endHandle
rgrover1 332:b054000833d4 30 };
rgrover1 332:b054000833d4 31 uint32_t rc;
rgrover1 332:b054000833d4 32 if ((rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange)) != NRF_SUCCESS) {
rgrover1 332:b054000833d4 33 terminateCharacteristicDiscovery();
rgrover1 332:b054000833d4 34 switch (rc) {
rgrover1 332:b054000833d4 35 case BLE_ERROR_INVALID_CONN_HANDLE:
rgrover1 332:b054000833d4 36 case NRF_ERROR_INVALID_ADDR:
rgrover1 332:b054000833d4 37 return BLE_ERROR_INVALID_PARAM;
rgrover1 332:b054000833d4 38 case NRF_ERROR_BUSY:
rgrover1 332:b054000833d4 39 return BLE_STACK_BUSY;
rgrover1 332:b054000833d4 40 default:
rgrover1 332:b054000833d4 41 case NRF_ERROR_INVALID_STATE:
rgrover1 332:b054000833d4 42 return BLE_ERROR_INVALID_STATE;
rgrover1 332:b054000833d4 43 }
rgrover1 332:b054000833d4 44 }
rgrover1 332:b054000833d4 45
rgrover1 332:b054000833d4 46 return BLE_ERROR_NONE;
rgrover1 332:b054000833d4 47 }
rgrover1 332:b054000833d4 48
rgrover1 332:b054000833d4 49 void
rgrover1 332:b054000833d4 50 nRFServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response)
rgrover1 332:b054000833d4 51 {
rgrover1 332:b054000833d4 52 serviceIndex = 0;
rgrover1 332:b054000833d4 53 numServices = response->count;
rgrover1 332:b054000833d4 54
rgrover1 332:b054000833d4 55 /* Account for the limitation on the number of discovered services we can handle at a time. */
rgrover1 332:b054000833d4 56 if (numServices > BLE_DB_DISCOVERY_MAX_SRV) {
rgrover1 332:b054000833d4 57 numServices = BLE_DB_DISCOVERY_MAX_SRV;
rgrover1 332:b054000833d4 58 }
rgrover1 332:b054000833d4 59
rgrover1 332:b054000833d4 60 serviceUUIDDiscoveryQueue.reset();
rgrover1 332:b054000833d4 61 for (unsigned serviceIndex = 0; serviceIndex < numServices; serviceIndex++) {
rgrover1 332:b054000833d4 62 if (response->services[serviceIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
rgrover1 332:b054000833d4 63 serviceUUIDDiscoveryQueue.enqueue(serviceIndex);
rgrover1 332:b054000833d4 64 services[serviceIndex].setup(response->services[serviceIndex].handle_range.start_handle,
rgrover1 332:b054000833d4 65 response->services[serviceIndex].handle_range.end_handle);
rgrover1 332:b054000833d4 66 } else {
rgrover1 332:b054000833d4 67 services[serviceIndex].setup(response->services[serviceIndex].uuid.uuid,
rgrover1 332:b054000833d4 68 response->services[serviceIndex].handle_range.start_handle,
rgrover1 332:b054000833d4 69 response->services[serviceIndex].handle_range.end_handle);
rgrover1 332:b054000833d4 70 }
rgrover1 332:b054000833d4 71 }
rgrover1 332:b054000833d4 72
rgrover1 332:b054000833d4 73 /* Trigger discovery of service UUID if necessary. */
rgrover1 332:b054000833d4 74 if (serviceUUIDDiscoveryQueue.getCount()) {
rgrover1 332:b054000833d4 75 serviceUUIDDiscoveryQueue.triggerFirst();
rgrover1 332:b054000833d4 76 }
rgrover1 332:b054000833d4 77 }
rgrover1 332:b054000833d4 78
rgrover1 332:b054000833d4 79 void
rgrover1 332:b054000833d4 80 nRFServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response)
rgrover1 332:b054000833d4 81 {
rgrover1 332:b054000833d4 82 characteristicIndex = 0;
rgrover1 332:b054000833d4 83 numCharacteristics = response->count;
rgrover1 332:b054000833d4 84
rgrover1 332:b054000833d4 85 /* Account for the limitation on the number of discovered characteristics we can handle at a time. */
rgrover1 332:b054000833d4 86 if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) {
rgrover1 332:b054000833d4 87 numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV;
rgrover1 332:b054000833d4 88 }
rgrover1 332:b054000833d4 89
rgrover1 332:b054000833d4 90 charUUIDDiscoveryQueue.reset();
rgrover1 332:b054000833d4 91 for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) {
rgrover1 332:b054000833d4 92 if (response->chars[charIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
rgrover1 332:b054000833d4 93 charUUIDDiscoveryQueue.enqueue(charIndex);
rgrover1 332:b054000833d4 94 characteristics[charIndex].setup(NULL, /* gattc FIX THIS */
rgrover1 332:b054000833d4 95 connHandle,
rgrover1 332:b054000833d4 96 response->chars[charIndex].char_props,
rgrover1 332:b054000833d4 97 response->chars[charIndex].handle_decl,
rgrover1 332:b054000833d4 98 response->chars[charIndex].handle_value);
rgrover1 332:b054000833d4 99 } else {
rgrover1 332:b054000833d4 100 characteristics[charIndex].setup(NULL, /* gattc FIX THIS */
rgrover1 332:b054000833d4 101 connHandle,
rgrover1 332:b054000833d4 102 response->chars[charIndex].uuid.uuid,
rgrover1 332:b054000833d4 103 response->chars[charIndex].char_props,
rgrover1 332:b054000833d4 104 response->chars[charIndex].handle_decl,
rgrover1 332:b054000833d4 105 response->chars[charIndex].handle_value);
rgrover1 332:b054000833d4 106 }
rgrover1 332:b054000833d4 107 }
rgrover1 332:b054000833d4 108
rgrover1 332:b054000833d4 109 /* Trigger discovery of char UUID if necessary. */
rgrover1 332:b054000833d4 110 if (charUUIDDiscoveryQueue.getCount()) {
rgrover1 332:b054000833d4 111 charUUIDDiscoveryQueue.triggerFirst();
rgrover1 332:b054000833d4 112 }
rgrover1 332:b054000833d4 113 }
rgrover1 332:b054000833d4 114
rgrover1 332:b054000833d4 115 void
rgrover1 332:b054000833d4 116 nRFServiceDiscovery::progressCharacteristicDiscovery(void)
rgrover1 332:b054000833d4 117 {
rgrover1 332:b054000833d4 118 /* Iterate through the previously discovered characteristics cached in characteristics[]. */
rgrover1 332:b054000833d4 119 while ((state == CHARACTERISTIC_DISCOVERY_ACTIVE) && (characteristicIndex < numCharacteristics)) {
rgrover1 332:b054000833d4 120 if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
rgrover1 332:b054000833d4 121 ((matchingCharacteristicUUID == characteristics[characteristicIndex].getShortUUID()) &&
rgrover1 332:b054000833d4 122 (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
rgrover1 332:b054000833d4 123 if (characteristicCallback) {
rgrover1 332:b054000833d4 124 characteristicCallback(&characteristics[characteristicIndex]);
rgrover1 332:b054000833d4 125 }
rgrover1 332:b054000833d4 126 }
rgrover1 332:b054000833d4 127
rgrover1 332:b054000833d4 128 characteristicIndex++;
rgrover1 332:b054000833d4 129 }
rgrover1 332:b054000833d4 130
rgrover1 332:b054000833d4 131 /* Relaunch discovery of new characteristics beyond the last entry cached in characteristics[]. */
rgrover1 332:b054000833d4 132 if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) {
rgrover1 332:b054000833d4 133 /* Determine the ending handle of the last cached characteristic. */
rgrover1 332:b054000833d4 134 Gap::Handle_t startHandle = characteristics[characteristicIndex - 1].getValueHandle() + 1;
rgrover1 332:b054000833d4 135 Gap::Handle_t endHandle = services[serviceIndex].getEndHandle();
rgrover1 332:b054000833d4 136 resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */
rgrover1 332:b054000833d4 137
rgrover1 332:b054000833d4 138 if (startHandle < endHandle) {
rgrover1 332:b054000833d4 139 ble_gattc_handle_range_t handleRange = {
rgrover1 332:b054000833d4 140 .start_handle = startHandle,
rgrover1 332:b054000833d4 141 .end_handle = endHandle
rgrover1 332:b054000833d4 142 };
rgrover1 332:b054000833d4 143 if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) {
rgrover1 332:b054000833d4 144 terminateCharacteristicDiscovery();
rgrover1 332:b054000833d4 145 }
rgrover1 332:b054000833d4 146 } else {
rgrover1 332:b054000833d4 147 terminateCharacteristicDiscovery();
rgrover1 332:b054000833d4 148 }
rgrover1 332:b054000833d4 149 }
rgrover1 332:b054000833d4 150 }
rgrover1 332:b054000833d4 151
rgrover1 332:b054000833d4 152 void
rgrover1 332:b054000833d4 153 nRFServiceDiscovery::progressServiceDiscovery(void)
rgrover1 332:b054000833d4 154 {
rgrover1 332:b054000833d4 155 /* Iterate through the previously discovered services cached in services[]. */
rgrover1 332:b054000833d4 156 while ((state == SERVICE_DISCOVERY_ACTIVE) && (serviceIndex < numServices)) {
rgrover1 332:b054000833d4 157 if ((matchingServiceUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
rgrover1 332:b054000833d4 158 (matchingServiceUUID == services[serviceIndex].getUUID().getShortUUID())) {
rgrover1 332:b054000833d4 159
rgrover1 332:b054000833d4 160 if (serviceCallback && (matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN))) {
rgrover1 332:b054000833d4 161 serviceCallback(&services[serviceIndex]);
rgrover1 332:b054000833d4 162 }
rgrover1 332:b054000833d4 163
rgrover1 332:b054000833d4 164 if ((state == SERVICE_DISCOVERY_ACTIVE) && characteristicCallback) {
rgrover1 332:b054000833d4 165 launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle());
rgrover1 332:b054000833d4 166 } else {
rgrover1 332:b054000833d4 167 serviceIndex++;
rgrover1 332:b054000833d4 168 }
rgrover1 332:b054000833d4 169 } else {
rgrover1 332:b054000833d4 170 serviceIndex++;
rgrover1 332:b054000833d4 171 }
rgrover1 332:b054000833d4 172 }
rgrover1 332:b054000833d4 173
rgrover1 332:b054000833d4 174 /* Relaunch discovery of new services beyond the last entry cached in services[]. */
rgrover1 332:b054000833d4 175 if ((state == SERVICE_DISCOVERY_ACTIVE) && (numServices > 0) && (serviceIndex > 0)) {
rgrover1 332:b054000833d4 176 /* Determine the ending handle of the last cached service. */
rgrover1 332:b054000833d4 177 Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle();
rgrover1 332:b054000833d4 178 resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */
rgrover1 332:b054000833d4 179
rgrover1 332:b054000833d4 180 if (endHandle == SRV_DISC_END_HANDLE) {
rgrover1 332:b054000833d4 181 terminateServiceDiscovery();
rgrover1 332:b054000833d4 182 } else {
rgrover1 332:b054000833d4 183 if (sd_ble_gattc_primary_services_discover(connHandle, endHandle, NULL) != NRF_SUCCESS) {
rgrover1 332:b054000833d4 184 terminateServiceDiscovery();
rgrover1 332:b054000833d4 185 }
rgrover1 332:b054000833d4 186 }
rgrover1 332:b054000833d4 187 }
rgrover1 332:b054000833d4 188 }
rgrover1 332:b054000833d4 189
rgrover1 332:b054000833d4 190 void
rgrover1 332:b054000833d4 191 nRFServiceDiscovery::ServiceUUIDDiscoveryQueue::triggerFirst(void)
rgrover1 332:b054000833d4 192 {
rgrover1 332:b054000833d4 193 while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */
rgrover1 332:b054000833d4 194 parentDiscoveryObject->state = DISCOVER_SERVICE_UUIDS;
rgrover1 332:b054000833d4 195
rgrover1 332:b054000833d4 196 unsigned serviceIndex = getFirst();
rgrover1 332:b054000833d4 197 ble_uuid_t uuid = {
rgrover1 332:b054000833d4 198 .uuid = BLE_UUID_SERVICE_PRIMARY,
rgrover1 332:b054000833d4 199 .type = BLE_UUID_TYPE_BLE,
rgrover1 332:b054000833d4 200 };
rgrover1 332:b054000833d4 201 ble_gattc_handle_range_t handleRange = {
rgrover1 332:b054000833d4 202 .start_handle = parentDiscoveryObject->services[serviceIndex].getStartHandle(),
rgrover1 332:b054000833d4 203 .end_handle = parentDiscoveryObject->services[serviceIndex].getEndHandle(),
rgrover1 332:b054000833d4 204 };
rgrover1 332:b054000833d4 205 if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) {
rgrover1 332:b054000833d4 206 return;
rgrover1 332:b054000833d4 207 }
rgrover1 332:b054000833d4 208
rgrover1 332:b054000833d4 209 /* Skip this service if we fail to launch a read for its service-declaration
rgrover1 332:b054000833d4 210 * attribute. Its UUID will remain INVALID, and it may not match any filters. */
rgrover1 332:b054000833d4 211 dequeue();
rgrover1 332:b054000833d4 212 }
rgrover1 332:b054000833d4 213
rgrover1 332:b054000833d4 214 /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */
rgrover1 332:b054000833d4 215 if (parentDiscoveryObject->state == DISCOVER_SERVICE_UUIDS) {
rgrover1 332:b054000833d4 216 parentDiscoveryObject->state = SERVICE_DISCOVERY_ACTIVE;
rgrover1 332:b054000833d4 217 }
rgrover1 332:b054000833d4 218 }
rgrover1 332:b054000833d4 219
rgrover1 332:b054000833d4 220 void
rgrover1 332:b054000833d4 221 nRFServiceDiscovery::CharUUIDDiscoveryQueue::triggerFirst(void)
rgrover1 332:b054000833d4 222 {
rgrover1 332:b054000833d4 223 while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */
rgrover1 332:b054000833d4 224 parentDiscoveryObject->state = DISCOVER_CHARACTERISTIC_UUIDS;
rgrover1 332:b054000833d4 225
rgrover1 332:b054000833d4 226 unsigned charIndex = getFirst();
rgrover1 332:b054000833d4 227 ble_uuid_t uuid = {
rgrover1 332:b054000833d4 228 .uuid = BLE_UUID_CHARACTERISTIC,
rgrover1 332:b054000833d4 229 .type = BLE_UUID_TYPE_BLE,
rgrover1 332:b054000833d4 230 };
rgrover1 332:b054000833d4 231 ble_gattc_handle_range_t handleRange = {
rgrover1 332:b054000833d4 232 .start_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle(),
rgrover1 332:b054000833d4 233 .end_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle() + 1,
rgrover1 332:b054000833d4 234 };
rgrover1 332:b054000833d4 235 if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) {
rgrover1 332:b054000833d4 236 return;
rgrover1 332:b054000833d4 237 }
rgrover1 332:b054000833d4 238
rgrover1 332:b054000833d4 239 /* Skip this service if we fail to launch a read for its service-declaration
rgrover1 332:b054000833d4 240 * attribute. Its UUID will remain INVALID, and it may not match any filters. */
rgrover1 332:b054000833d4 241 dequeue();
rgrover1 332:b054000833d4 242 }
rgrover1 332:b054000833d4 243
rgrover1 332:b054000833d4 244 /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */
rgrover1 332:b054000833d4 245 if (parentDiscoveryObject->state == DISCOVER_CHARACTERISTIC_UUIDS) {
rgrover1 332:b054000833d4 246 parentDiscoveryObject->state = CHARACTERISTIC_DISCOVERY_ACTIVE;
rgrover1 332:b054000833d4 247 }
rgrover1 332:b054000833d4 248 }
rgrover1 332:b054000833d4 249
rgrover1 332:b054000833d4 250 void
rgrover1 332:b054000833d4 251 nRFServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response)
rgrover1 332:b054000833d4 252 {
rgrover1 332:b054000833d4 253 if (state == DISCOVER_SERVICE_UUIDS) {
rgrover1 332:b054000833d4 254 if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) {
rgrover1 332:b054000833d4 255 UUID::LongUUIDBytes_t uuid;
rgrover1 332:b054000833d4 256 /* Switch longUUID bytes to MSB */
rgrover1 332:b054000833d4 257 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
rgrover1 332:b054000833d4 258 uuid[i] = response->handle_value[0].p_value[UUID::LENGTH_OF_LONG_UUID - 1 - i];
rgrover1 332:b054000833d4 259 }
rgrover1 332:b054000833d4 260
rgrover1 332:b054000833d4 261 unsigned serviceIndex = serviceUUIDDiscoveryQueue.dequeue();
rgrover1 332:b054000833d4 262 services[serviceIndex].setupLongUUID(uuid);
rgrover1 332:b054000833d4 263
rgrover1 332:b054000833d4 264 serviceUUIDDiscoveryQueue.triggerFirst();
rgrover1 332:b054000833d4 265 } else {
rgrover1 332:b054000833d4 266 serviceUUIDDiscoveryQueue.dequeue();
rgrover1 332:b054000833d4 267 }
rgrover1 332:b054000833d4 268 } else if (state == DISCOVER_CHARACTERISTIC_UUIDS) {
rgrover1 332:b054000833d4 269 if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) {
rgrover1 332:b054000833d4 270 UUID::LongUUIDBytes_t uuid;
rgrover1 332:b054000833d4 271 /* Switch longUUID bytes to MSB */
rgrover1 332:b054000833d4 272 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
rgrover1 332:b054000833d4 273 uuid[i] = response->handle_value[0].p_value[3 + UUID::LENGTH_OF_LONG_UUID - 1 - i];
rgrover1 332:b054000833d4 274 }
rgrover1 332:b054000833d4 275
rgrover1 332:b054000833d4 276 unsigned charIndex = charUUIDDiscoveryQueue.dequeue();
rgrover1 332:b054000833d4 277 characteristics[charIndex].setupLongUUID(uuid);
rgrover1 332:b054000833d4 278
rgrover1 332:b054000833d4 279 charUUIDDiscoveryQueue.triggerFirst();
rgrover1 332:b054000833d4 280 } else {
rgrover1 332:b054000833d4 281 charUUIDDiscoveryQueue.dequeue();
rgrover1 332:b054000833d4 282 }
rgrover1 332:b054000833d4 283 }
rgrover1 332:b054000833d4 284 }