Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nRF51822 by
nRF5xServiceDiscovery.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "nRF5xServiceDiscovery.h" 00018 00019 ble_error_t 00020 nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, 00021 Gap::Handle_t startHandle, 00022 Gap::Handle_t endHandle) 00023 { 00024 characteristicDiscoveryStarted(connectionHandle); 00025 00026 ble_gattc_handle_range_t handleRange = { 00027 .start_handle = startHandle, 00028 .end_handle = endHandle 00029 }; 00030 uint32_t rc; 00031 if ((rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange)) != NRF_SUCCESS) { 00032 terminateCharacteristicDiscovery(); 00033 switch (rc) { 00034 case BLE_ERROR_INVALID_CONN_HANDLE: 00035 case NRF_ERROR_INVALID_ADDR: 00036 return BLE_ERROR_INVALID_PARAM; 00037 case NRF_ERROR_BUSY: 00038 return BLE_STACK_BUSY; 00039 default: 00040 case NRF_ERROR_INVALID_STATE: 00041 return BLE_ERROR_INVALID_STATE; 00042 } 00043 } 00044 00045 return BLE_ERROR_NONE; 00046 } 00047 00048 void 00049 nRF5xServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response) 00050 { 00051 serviceIndex = 0; 00052 numServices = response->count; 00053 00054 /* Account for the limitation on the number of discovered services we can handle at a time. */ 00055 if (numServices > BLE_DB_DISCOVERY_MAX_SRV) { 00056 numServices = BLE_DB_DISCOVERY_MAX_SRV; 00057 } 00058 00059 serviceUUIDDiscoveryQueue.reset(); 00060 for (unsigned serviceIndex = 0; serviceIndex < numServices; serviceIndex++) { 00061 if (response->services[serviceIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) { 00062 serviceUUIDDiscoveryQueue.enqueue(serviceIndex); 00063 services[serviceIndex].setup(response->services[serviceIndex].handle_range.start_handle, 00064 response->services[serviceIndex].handle_range.end_handle); 00065 } else { 00066 services[serviceIndex].setup(response->services[serviceIndex].uuid.uuid, 00067 response->services[serviceIndex].handle_range.start_handle, 00068 response->services[serviceIndex].handle_range.end_handle); 00069 } 00070 } 00071 00072 /* Trigger discovery of service UUID if necessary. */ 00073 if (serviceUUIDDiscoveryQueue.getCount()) { 00074 serviceUUIDDiscoveryQueue.triggerFirst(); 00075 } 00076 } 00077 00078 void 00079 nRF5xServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response) 00080 { 00081 characteristicIndex = 0; 00082 numCharacteristics = response->count; 00083 00084 /* Account for the limitation on the number of discovered characteristics we can handle at a time. */ 00085 if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) { 00086 numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV; 00087 } 00088 00089 charUUIDDiscoveryQueue.reset(); 00090 for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) { 00091 if (response->chars[charIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) { 00092 charUUIDDiscoveryQueue.enqueue(charIndex); 00093 characteristics[charIndex].setup(gattc, 00094 connHandle, 00095 response->chars[charIndex].char_props, 00096 response->chars[charIndex].handle_decl, 00097 response->chars[charIndex].handle_value); 00098 } else { 00099 characteristics[charIndex].setup(gattc, 00100 connHandle, 00101 response->chars[charIndex].uuid.uuid, 00102 response->chars[charIndex].char_props, 00103 response->chars[charIndex].handle_decl, 00104 response->chars[charIndex].handle_value); 00105 } 00106 } 00107 00108 /* Trigger discovery of char UUID if necessary. */ 00109 if (charUUIDDiscoveryQueue.getCount()) { 00110 charUUIDDiscoveryQueue.triggerFirst(); 00111 } 00112 } 00113 00114 void 00115 nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) 00116 { 00117 /* Iterate through the previously discovered characteristics cached in characteristics[]. */ 00118 while ((state == CHARACTERISTIC_DISCOVERY_ACTIVE) && (characteristicIndex < numCharacteristics)) { 00119 if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || 00120 ((matchingCharacteristicUUID == characteristics[characteristicIndex].getUUID()) && 00121 (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) { 00122 if (characteristicCallback) { 00123 characteristicCallback(&characteristics[characteristicIndex]); 00124 } 00125 } 00126 00127 characteristicIndex++; 00128 } 00129 00130 /* Relaunch discovery of new characteristics beyond the last entry cached in characteristics[]. */ 00131 if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) { 00132 /* Determine the ending handle of the last cached characteristic. */ 00133 Gap::Handle_t startHandle = characteristics[characteristicIndex - 1].getValueHandle() + 1; 00134 Gap::Handle_t endHandle = services[serviceIndex].getEndHandle(); 00135 resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */ 00136 00137 if (startHandle < endHandle) { 00138 ble_gattc_handle_range_t handleRange = { 00139 .start_handle = startHandle, 00140 .end_handle = endHandle 00141 }; 00142 if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { 00143 terminateCharacteristicDiscovery(); 00144 } 00145 } else { 00146 terminateCharacteristicDiscovery(); 00147 } 00148 } 00149 } 00150 00151 void 00152 nRF5xServiceDiscovery::progressServiceDiscovery(void) 00153 { 00154 /* Iterate through the previously discovered services cached in services[]. */ 00155 while ((state == SERVICE_DISCOVERY_ACTIVE) && (serviceIndex < numServices)) { 00156 if ((matchingServiceUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || 00157 (matchingServiceUUID == services[serviceIndex].getUUID())) { 00158 00159 if (serviceCallback && (matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN))) { 00160 serviceCallback(&services[serviceIndex]); 00161 } 00162 00163 if ((state == SERVICE_DISCOVERY_ACTIVE) && characteristicCallback) { 00164 launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle()); 00165 } else { 00166 serviceIndex++; 00167 } 00168 } else { 00169 serviceIndex++; 00170 } 00171 } 00172 00173 /* Relaunch discovery of new services beyond the last entry cached in services[]. */ 00174 if ((state == SERVICE_DISCOVERY_ACTIVE) && (numServices > 0) && (serviceIndex > 0)) { 00175 /* Determine the ending handle of the last cached service. */ 00176 Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle(); 00177 resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */ 00178 00179 if (endHandle == SRV_DISC_END_HANDLE) { 00180 terminateServiceDiscovery(); 00181 } else { 00182 if (sd_ble_gattc_primary_services_discover(connHandle, endHandle, NULL) != NRF_SUCCESS) { 00183 terminateServiceDiscovery(); 00184 } 00185 } 00186 } 00187 } 00188 00189 void 00190 nRF5xServiceDiscovery::ServiceUUIDDiscoveryQueue::triggerFirst(void) 00191 { 00192 while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */ 00193 parentDiscoveryObject->state = DISCOVER_SERVICE_UUIDS; 00194 00195 unsigned serviceIndex = getFirst(); 00196 ble_uuid_t uuid = { 00197 .uuid = BLE_UUID_SERVICE_PRIMARY, 00198 .type = BLE_UUID_TYPE_BLE, 00199 }; 00200 ble_gattc_handle_range_t handleRange = { 00201 .start_handle = parentDiscoveryObject->services[serviceIndex].getStartHandle(), 00202 .end_handle = parentDiscoveryObject->services[serviceIndex].getEndHandle(), 00203 }; 00204 if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) { 00205 return; 00206 } 00207 00208 /* Skip this service if we fail to launch a read for its service-declaration 00209 * attribute. Its UUID will remain INVALID, and it may not match any filters. */ 00210 dequeue(); 00211 } 00212 00213 /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */ 00214 if (parentDiscoveryObject->state == DISCOVER_SERVICE_UUIDS) { 00215 parentDiscoveryObject->state = SERVICE_DISCOVERY_ACTIVE; 00216 } 00217 } 00218 00219 void 00220 nRF5xServiceDiscovery::CharUUIDDiscoveryQueue::triggerFirst(void) 00221 { 00222 while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */ 00223 parentDiscoveryObject->state = DISCOVER_CHARACTERISTIC_UUIDS; 00224 00225 unsigned charIndex = getFirst(); 00226 ble_uuid_t uuid = { 00227 .uuid = BLE_UUID_CHARACTERISTIC, 00228 .type = BLE_UUID_TYPE_BLE, 00229 }; 00230 ble_gattc_handle_range_t handleRange = { }; 00231 handleRange.start_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle(); 00232 handleRange.end_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle() + 1; 00233 if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) { 00234 return; 00235 } 00236 00237 /* Skip this service if we fail to launch a read for its service-declaration 00238 * attribute. Its UUID will remain INVALID, and it may not match any filters. */ 00239 dequeue(); 00240 } 00241 00242 /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */ 00243 if (parentDiscoveryObject->state == DISCOVER_CHARACTERISTIC_UUIDS) { 00244 parentDiscoveryObject->state = CHARACTERISTIC_DISCOVERY_ACTIVE; 00245 } 00246 } 00247 00248 void 00249 nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response) 00250 { 00251 if (state == DISCOVER_SERVICE_UUIDS) { 00252 if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) { 00253 UUID::LongUUIDBytes_t uuid; 00254 /* Switch longUUID bytes to MSB */ 00255 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { 00256 uuid[i] = response->handle_value[0].p_value[UUID::LENGTH_OF_LONG_UUID - 1 - i]; 00257 } 00258 00259 unsigned serviceIndex = serviceUUIDDiscoveryQueue.dequeue(); 00260 services[serviceIndex].setupLongUUID(uuid); 00261 00262 serviceUUIDDiscoveryQueue.triggerFirst(); 00263 } else { 00264 serviceUUIDDiscoveryQueue.dequeue(); 00265 } 00266 } else if (state == DISCOVER_CHARACTERISTIC_UUIDS) { 00267 if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) { 00268 UUID::LongUUIDBytes_t uuid; 00269 /* Switch longUUID bytes to MSB */ 00270 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { 00271 uuid[i] = response->handle_value[0].p_value[3 + UUID::LENGTH_OF_LONG_UUID - 1 - i]; 00272 } 00273 00274 unsigned charIndex = charUUIDDiscoveryQueue.dequeue(); 00275 characteristics[charIndex].setupLongUUID(uuid); 00276 00277 charUUIDDiscoveryQueue.triggerFirst(); 00278 } else { 00279 charUUIDDiscoveryQueue.dequeue(); 00280 } 00281 } 00282 }
Generated on Tue Jul 12 2022 21:00:17 by
