test
Fork of nRF51822 by
Embed:
(wiki syntax)
Show/hide line numbers
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 1.7.2