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 = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange); 00031 ble_error_t err = BLE_ERROR_NONE; 00032 00033 switch (rc) { 00034 case NRF_SUCCESS: 00035 err = BLE_ERROR_NONE; 00036 break; 00037 case BLE_ERROR_INVALID_CONN_HANDLE: 00038 case NRF_ERROR_INVALID_ADDR: 00039 err = BLE_ERROR_INVALID_PARAM; 00040 break; 00041 case NRF_ERROR_BUSY: 00042 err = BLE_STACK_BUSY; 00043 break; 00044 case NRF_ERROR_INVALID_STATE: 00045 err = BLE_ERROR_INVALID_STATE; 00046 break; 00047 default: 00048 err = BLE_ERROR_UNSPECIFIED; 00049 break; 00050 } 00051 00052 if (err) { 00053 terminateCharacteristicDiscovery(err); 00054 } 00055 return err; 00056 } 00057 00058 void 00059 nRF5xServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response) 00060 { 00061 serviceIndex = 0; 00062 numServices = response->count; 00063 00064 /* Account for the limitation on the number of discovered services we can handle at a time. */ 00065 if (numServices > BLE_DB_DISCOVERY_MAX_SRV) { 00066 numServices = BLE_DB_DISCOVERY_MAX_SRV; 00067 } 00068 00069 serviceUUIDDiscoveryQueue.reset(); 00070 for (unsigned serviceIndex = 0; serviceIndex < numServices; serviceIndex++) { 00071 if (response->services[serviceIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) { 00072 serviceUUIDDiscoveryQueue.enqueue(serviceIndex); 00073 services[serviceIndex].setup(response->services[serviceIndex].handle_range.start_handle, 00074 response->services[serviceIndex].handle_range.end_handle); 00075 } else { 00076 services[serviceIndex].setup(response->services[serviceIndex].uuid.uuid, 00077 response->services[serviceIndex].handle_range.start_handle, 00078 response->services[serviceIndex].handle_range.end_handle); 00079 } 00080 } 00081 00082 /* Trigger discovery of service UUID if necessary. */ 00083 if (serviceUUIDDiscoveryQueue.getCount()) { 00084 serviceUUIDDiscoveryQueue.triggerFirst(); 00085 } 00086 } 00087 00088 void 00089 nRF5xServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response) 00090 { 00091 numCharacteristics = response->count; 00092 00093 /* Account for the limitation on the number of discovered characteristics we can handle at a time. */ 00094 if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) { 00095 numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV; 00096 } 00097 00098 charUUIDDiscoveryQueue.reset(); 00099 for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) { 00100 if (response->chars[charIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) { 00101 charUUIDDiscoveryQueue.enqueue(charIndex); 00102 characteristics[charIndex].setup(gattc, 00103 connHandle, 00104 response->chars[charIndex].char_props, 00105 response->chars[charIndex].handle_decl, 00106 response->chars[charIndex].handle_value); 00107 } else { 00108 characteristics[charIndex].setup(gattc, 00109 connHandle, 00110 response->chars[charIndex].uuid.uuid, 00111 response->chars[charIndex].char_props, 00112 response->chars[charIndex].handle_decl, 00113 response->chars[charIndex].handle_value); 00114 } 00115 } 00116 00117 /* Trigger discovery of char UUID if necessary. */ 00118 if (charUUIDDiscoveryQueue.getCount()) { 00119 charUUIDDiscoveryQueue.triggerFirst(); 00120 } 00121 } 00122 00123 void 00124 nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) 00125 { 00126 if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) { 00127 return; 00128 } 00129 00130 if ((discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) && (numCharacteristics > 0)) { 00131 discoveredCharacteristic.setLastHandle(characteristics[0].getDeclHandle() - 1); 00132 00133 if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || 00134 ((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) && 00135 (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) { 00136 if (characteristicCallback) { 00137 characteristicCallback(&discoveredCharacteristic); 00138 } 00139 } 00140 } 00141 00142 for (uint8_t i = 0; i < numCharacteristics; ++i) { 00143 if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) { 00144 return; 00145 } 00146 00147 if (i == (numCharacteristics - 1)) { 00148 discoveredCharacteristic = characteristics[i]; 00149 break; 00150 } else { 00151 characteristics[i].setLastHandle(characteristics[i + 1].getDeclHandle() - 1); 00152 } 00153 00154 if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || 00155 ((matchingCharacteristicUUID == characteristics[i].getUUID()) && 00156 (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) { 00157 if (characteristicCallback) { 00158 characteristicCallback(&characteristics[i]); 00159 } 00160 } 00161 } 00162 00163 if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) { 00164 return; 00165 } 00166 00167 Gap::Handle_t startHandle = (numCharacteristics > 0) ? characteristics[numCharacteristics - 1].getValueHandle() + 1 : SRV_DISC_END_HANDLE; 00168 Gap::Handle_t endHandle = services[serviceIndex].getEndHandle(); 00169 resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */ 00170 00171 if (startHandle < endHandle) { 00172 ble_gattc_handle_range_t handleRange = { 00173 .start_handle = startHandle, 00174 .end_handle = endHandle 00175 }; 00176 if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { 00177 terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED); 00178 } 00179 } else { 00180 terminateCharacteristicDiscovery(BLE_ERROR_NONE); 00181 } 00182 } 00183 00184 void 00185 nRF5xServiceDiscovery::progressServiceDiscovery(void) 00186 { 00187 /* Iterate through the previously discovered services cached in services[]. */ 00188 while ((state == SERVICE_DISCOVERY_ACTIVE) && (serviceIndex < numServices)) { 00189 if ((matchingServiceUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) || 00190 (matchingServiceUUID == services[serviceIndex].getUUID())) { 00191 00192 if (serviceCallback && (matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN))) { 00193 serviceCallback(&services[serviceIndex]); 00194 } 00195 00196 if ((state == SERVICE_DISCOVERY_ACTIVE) && characteristicCallback) { 00197 launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle()); 00198 } else { 00199 serviceIndex++; 00200 } 00201 } else { 00202 serviceIndex++; 00203 } 00204 } 00205 00206 /* Relaunch discovery of new services beyond the last entry cached in services[]. */ 00207 if ((state == SERVICE_DISCOVERY_ACTIVE) && (numServices > 0) && (serviceIndex > 0)) { 00208 /* Determine the ending handle of the last cached service. */ 00209 Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle(); 00210 resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */ 00211 00212 if (endHandle == SRV_DISC_END_HANDLE) { 00213 terminateServiceDiscovery(); 00214 } else { 00215 if (sd_ble_gattc_primary_services_discover(connHandle, endHandle, NULL) != NRF_SUCCESS) { 00216 terminateServiceDiscovery(); 00217 } 00218 } 00219 } 00220 } 00221 00222 void 00223 nRF5xServiceDiscovery::ServiceUUIDDiscoveryQueue::triggerFirst(void) 00224 { 00225 while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */ 00226 parentDiscoveryObject->state = DISCOVER_SERVICE_UUIDS; 00227 00228 unsigned serviceIndex = getFirst(); 00229 ble_uuid_t uuid = { 00230 .uuid = BLE_UUID_SERVICE_PRIMARY, 00231 .type = BLE_UUID_TYPE_BLE, 00232 }; 00233 ble_gattc_handle_range_t handleRange = { 00234 .start_handle = parentDiscoveryObject->services[serviceIndex].getStartHandle(), 00235 .end_handle = parentDiscoveryObject->services[serviceIndex].getEndHandle(), 00236 }; 00237 if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) { 00238 return; 00239 } 00240 00241 /* Skip this service if we fail to launch a read for its service-declaration 00242 * attribute. Its UUID will remain INVALID, and it may not match any filters. */ 00243 dequeue(); 00244 } 00245 00246 /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */ 00247 if (parentDiscoveryObject->state == DISCOVER_SERVICE_UUIDS) { 00248 parentDiscoveryObject->state = SERVICE_DISCOVERY_ACTIVE; 00249 } 00250 } 00251 00252 void 00253 nRF5xServiceDiscovery::CharUUIDDiscoveryQueue::triggerFirst(void) 00254 { 00255 while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */ 00256 parentDiscoveryObject->state = DISCOVER_CHARACTERISTIC_UUIDS; 00257 00258 unsigned charIndex = getFirst(); 00259 ble_uuid_t uuid = { 00260 .uuid = BLE_UUID_CHARACTERISTIC, 00261 .type = BLE_UUID_TYPE_BLE, 00262 }; 00263 ble_gattc_handle_range_t handleRange = { }; 00264 handleRange.start_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle(); 00265 handleRange.end_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle() + 1; 00266 if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) { 00267 return; 00268 } 00269 00270 /* Skip this service if we fail to launch a read for its service-declaration 00271 * attribute. Its UUID will remain INVALID, and it may not match any filters. */ 00272 dequeue(); 00273 } 00274 00275 /* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */ 00276 if (parentDiscoveryObject->state == DISCOVER_CHARACTERISTIC_UUIDS) { 00277 parentDiscoveryObject->state = CHARACTERISTIC_DISCOVERY_ACTIVE; 00278 } 00279 } 00280 00281 void 00282 nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response) 00283 { 00284 if (state == DISCOVER_SERVICE_UUIDS) { 00285 if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) { 00286 UUID::LongUUIDBytes_t uuid; 00287 memcpy(uuid, response->handle_value[0].p_value, UUID::LENGTH_OF_LONG_UUID); 00288 00289 unsigned serviceIndex = serviceUUIDDiscoveryQueue.dequeue(); 00290 services[serviceIndex].setupLongUUID(uuid, UUID::LSB); 00291 00292 serviceUUIDDiscoveryQueue.triggerFirst(); 00293 } else { 00294 serviceUUIDDiscoveryQueue.dequeue(); 00295 } 00296 } else if (state == DISCOVER_CHARACTERISTIC_UUIDS) { 00297 if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) { 00298 UUID::LongUUIDBytes_t uuid; 00299 00300 memcpy(uuid, &(response->handle_value[0].p_value[3]), UUID::LENGTH_OF_LONG_UUID); 00301 00302 unsigned charIndex = charUUIDDiscoveryQueue.dequeue(); 00303 characteristics[charIndex].setupLongUUID(uuid, UUID::LSB); 00304 00305 charUUIDDiscoveryQueue.triggerFirst(); 00306 } else { 00307 charUUIDDiscoveryQueue.dequeue(); 00308 } 00309 } 00310 }
Generated on Fri Jul 15 2022 12:51:28 by
