Arch X / Mbed 2 deprecated BLE_Micro_Release

Dependencies:   BLE_API Buffer mbed

Fork of BLE_LEDBlinker by Bluetooth Low Energy

Committer:
arch
Date:
Tue Dec 08 08:34:22 2015 +0000
Revision:
12:c4090cb58976
Parent:
11:c8cbc4bc2c17
fix USBTX/USBRX pins config

Who changed what in which revision?

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