library for BLE_GAP_backpack
Dependencies: nrf51-sdk
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 Wed Jul 13 2022 11:18:00 by 1.7.2