Jason Garner / nRF51822

Fork of nRF51822 by Nordic Semiconductor

Committer:
rgrover1
Date:
Thu Jul 02 09:08:44 2015 +0100
Revision:
362:6fa0d4d555f6
Synchronized with git rev 2716309c
Author: Rohit Grover
Release 0.4.0
=============

This is a major release which introduces the GATT Client functionality. It
aligns with release 0.4.0 of BLE_API.

Enhancements
~~~~~~~~~~~~

* Introduce GattClient. This includes functionality for service-discovery,
connections, and attribute-reads and writes. You'll find a demo program for
LEDBlinker on the mbed.org Bluetooth team page to use the new APIs. Some of
the GATT client functionality hasn't been implemented yet, but the APIs have
been added.

* We've added an implementation for the abstract base class for
SecurityManager. All security related APIs have been moved into that.

* There has been a major cleanup of APIs under BLE. APIs have now been
categorized as belonging to Gap, GattServer, GattClient, or SecurityManager.
There are accessors to get references for Gap, GattServer, GattClient, and
SecurityManager. A former call to ble.setAddress(...) is now expected to be
achieved with ble.gap().setAddress(...).

* We've cleaned up our APIs, and this has resulted in dropping some APIs like
BLE::reset().

* We've also dropped GattServer::initializeGattDatabase(). THis was added at
some point to support controllers where a commit point was needed to
indicate when the application had finished constructing the GATT database.
This API would get called internally before Gap::startAdvertising(). We now
expect the underlying port to do the equivalent of initializeGattDatabase()
implicitly upon Gap::startAdvertising().

* We've added a version of Gap::disconnect() which takes a connection handle.
The previous API (which did not take a connection handle) has been
deprecated; it will still work for situations where there's only a single
active connection. We hold on to that API to allow existing code to migrate
to the new API.

Bugfixes
~~~~~~~~

* None.

Who changed what in which revision?

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