Added an EddystoneURLConfigService in addition to UriBeaconConfigService. Updated README and converted comments that used UriBeacon to EddystoneURL in the EddystoneService.h
Dependents: mbed_EddystoneURL_Beacon_ssci mbed_EddystoneURL_Beacon_ssci mbed_EddystoneURL_Beacon_ssci
Fork of BLE_API by
EddystoneURLConfigService.h
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 #ifndef SERVICES_EDDYSTONECONFIGSERVICE_H_ 00018 #define SERVICES_EDDYSTONECONFIGSERVICE_H_ 00019 00020 #include "ble/BLE.h" 00021 #include "mbed.h" 00022 00023 extern const uint8_t UUID_EDDYSTONE_URL_SERVICE[UUID::LENGTH_OF_LONG_UUID]; 00024 extern const uint8_t UUID_LOCK_STATE_CHAR[UUID::LENGTH_OF_LONG_UUID]; 00025 extern const uint8_t UUID_LOCK_CHAR[UUID::LENGTH_OF_LONG_UUID]; 00026 extern const uint8_t UUID_UNLOCK_CHAR[UUID::LENGTH_OF_LONG_UUID]; 00027 extern const uint8_t UUID_URI_DATA_CHAR[UUID::LENGTH_OF_LONG_UUID]; 00028 extern const uint8_t UUID_FLAGS_CHAR[UUID::LENGTH_OF_LONG_UUID]; 00029 extern const uint8_t UUID_ADV_POWER_LEVELS_CHAR[UUID::LENGTH_OF_LONG_UUID]; 00030 extern const uint8_t UUID_TX_POWER_MODE_CHAR[UUID::LENGTH_OF_LONG_UUID]; 00031 extern const uint8_t UUID_BEACON_PERIOD_CHAR[UUID::LENGTH_OF_LONG_UUID]; 00032 extern const uint8_t UUID_RESET_CHAR[UUID::LENGTH_OF_LONG_UUID]; 00033 00034 extern const uint8_t EDDYSTONE_BEACON_UUID[sizeof(UUID::ShortUUIDBytes_t)]; 00035 00036 /** 00037 * @class EddystoneURLConfigService 00038 * @brief Eddystone URL Configuration Service. Can be used to set URL, adjust power levels, and set flags. 00039 * See https://github.com/google/eddystone/tree/master/eddystone-url 00040 * 00041 */ 00042 class EddystoneURLConfigService { 00043 public: 00044 /** 00045 * @brief Transmission Power Modes for Eddystone-URL beacon 00046 */ 00047 static const uint8_t TX_POWER_MODE_LOWEST = 0; /*!< Lowest TX power mode */ 00048 static const uint8_t TX_POWER_MODE_LOW = 1; /*!< Low TX power mode */ 00049 static const uint8_t TX_POWER_MODE_MEDIUM = 2; /*!< Medium TX power mode */ 00050 static const uint8_t TX_POWER_MODE_HIGH = 3; /*!< High TX power mode */ 00051 static const unsigned NUM_POWER_MODES = 4; /*!< Number of Power Modes defined */ 00052 00053 static const int ADVERTISING_INTERVAL_MSEC = 1000; // Advertising interval for config service. 00054 static const int SERVICE_DATA_MAX = 31; // Maximum size of service data in ADV packets 00055 00056 typedef uint8_t Lock_t[16]; /* 128 bits */ 00057 typedef int8_t PowerLevels_t[NUM_POWER_MODES ]; 00058 00059 static const int URI_DATA_MAX = 18; 00060 typedef uint8_t UriData_t[URI_DATA_MAX]; 00061 00062 struct Params_t { 00063 uint8_t lockedState; 00064 Lock_t lock; 00065 uint8_t uriDataLength; 00066 UriData_t uriData; 00067 uint8_t flags; 00068 PowerLevels_t advPowerLevels; // Current value of AdvertisedPowerLevels 00069 uint8_t txPowerMode; // Firmware power levels used with setTxPower() 00070 uint16_t beaconPeriod; 00071 }; 00072 00073 /** 00074 * @param[ref] ble 00075 * BLE object for the underlying controller. 00076 * @param[in/out] paramsIn 00077 * Reference to application-visible beacon state, loaded 00078 * from persistent storage at startup. 00079 * @paramsP[in] resetToDefaultsFlag 00080 * Applies to the state of the 'paramsIn' parameter. 00081 * If true, it indicates that paramsIn is potentially 00082 * un-initialized, and default values should be used 00083 * instead. Otherwise, paramsIn overrides the defaults. 00084 * @param[in] defaultUriDataIn 00085 * Default un-encoded URI; applies only if the resetToDefaultsFlag is true. 00086 * @param[in] defaultAdvPowerLevelsIn 00087 * Default power-levels array; applies only if the resetToDefaultsFlag is true. 00088 */ 00089 EddystoneURLConfigService (BLE &bleIn, 00090 Params_t ¶msIn, 00091 bool resetToDefaultsFlag, 00092 const char *defaultURIDataIn, 00093 PowerLevels_t &defaultAdvPowerLevelsIn) : 00094 ble(bleIn), 00095 params(paramsIn), 00096 defaultUriDataLength(), 00097 defaultUriData(), 00098 defaultAdvPowerLevels(defaultAdvPowerLevelsIn), 00099 initSucceeded(false), 00100 resetFlag(), 00101 lockedStateChar(UUID_LOCK_STATE_CHAR, ¶ms.lockedState), 00102 lockChar(UUID_LOCK_CHAR, ¶ms.lock), 00103 uriDataChar(UUID_URI_DATA_CHAR, params.uriData, 0, URI_DATA_MAX, 00104 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE), 00105 unlockChar(UUID_UNLOCK_CHAR, ¶ms.lock), 00106 flagsChar(UUID_FLAGS_CHAR, ¶ms.flags), 00107 advPowerLevelsChar(UUID_ADV_POWER_LEVELS_CHAR, ¶ms.advPowerLevels), 00108 txPowerModeChar(UUID_TX_POWER_MODE_CHAR, ¶ms.txPowerMode), 00109 beaconPeriodChar(UUID_BEACON_PERIOD_CHAR, ¶ms.beaconPeriod), 00110 resetChar(UUID_RESET_CHAR, &resetFlag) { 00111 00112 encodeURI(defaultURIDataIn, defaultUriData, defaultUriDataLength); 00113 if (defaultUriDataLength > URI_DATA_MAX) { 00114 return; 00115 } 00116 00117 if (!resetToDefaultsFlag && (params.uriDataLength > URI_DATA_MAX)) { 00118 resetToDefaultsFlag = true; 00119 } 00120 if (resetToDefaultsFlag) { 00121 resetToDefaults(); 00122 } else { 00123 updateCharacteristicValues(); 00124 } 00125 00126 lockChar.setWriteAuthorizationCallback(this, &EddystoneURLConfigService::lockAuthorizationCallback); 00127 unlockChar.setWriteAuthorizationCallback(this, &EddystoneURLConfigService::unlockAuthorizationCallback); 00128 uriDataChar.setWriteAuthorizationCallback(this, &EddystoneURLConfigService::uriDataWriteAuthorizationCallback); 00129 flagsChar.setWriteAuthorizationCallback(this, &EddystoneURLConfigService::basicAuthorizationCallback<uint8_t>); 00130 advPowerLevelsChar.setWriteAuthorizationCallback(this, &EddystoneURLConfigService::basicAuthorizationCallback<PowerLevels_t>); 00131 txPowerModeChar.setWriteAuthorizationCallback(this, &EddystoneURLConfigService::powerModeAuthorizationCallback); 00132 beaconPeriodChar.setWriteAuthorizationCallback(this, &EddystoneURLConfigService::basicAuthorizationCallback<uint16_t>); 00133 resetChar.setWriteAuthorizationCallback(this, &EddystoneURLConfigService::basicAuthorizationCallback<uint8_t>); 00134 00135 static GattCharacteristic *charTable[] = { 00136 &lockedStateChar, &lockChar, &unlockChar, &uriDataChar, 00137 &flagsChar, &advPowerLevelsChar, &txPowerModeChar, &beaconPeriodChar, &resetChar 00138 }; 00139 00140 GattService configService(UUID_EDDYSTONE_URL_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *)); 00141 00142 ble.addService(configService); 00143 ble.onDataWritten(this, &EddystoneURLConfigService::onDataWrittenCallback); 00144 00145 setupEddystoneURLConfigAdvertisements(); /* Setup advertising for the configService. */ 00146 00147 initSucceeded = true; 00148 } 00149 00150 bool configuredSuccessfully(void) const { 00151 return initSucceeded; 00152 } 00153 00154 /* Start out by advertising the configService for a limited time after 00155 * startup; and switch to the normal non-connectible beacon functionality 00156 * afterwards. */ 00157 void setupEddystoneURLConfigAdvertisements() 00158 { 00159 const char DEVICE_NAME[] = "mbed ES Config URL"; 00160 00161 ble.gap().clearAdvertisingPayload(); 00162 00163 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 00164 00165 // UUID is in different order in the ADV frame (!) 00166 uint8_t reversedServiceUUID[sizeof(UUID_EDDYSTONE_URL_SERVICE)]; 00167 for (unsigned int i = 0; i < sizeof(UUID_EDDYSTONE_URL_SERVICE); i++) { 00168 reversedServiceUUID[i] = UUID_EDDYSTONE_URL_SERVICE[sizeof(UUID_EDDYSTONE_URL_SERVICE) - i - 1]; 00169 } 00170 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, reversedServiceUUID, sizeof(reversedServiceUUID)); 00171 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG); 00172 ble.gap().accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, reinterpret_cast<const uint8_t *>(&DEVICE_NAME), sizeof(DEVICE_NAME)); 00173 ble.gap().accumulateScanResponse(GapAdvertisingData::TX_POWER_LEVEL, 00174 reinterpret_cast<uint8_t *>(&defaultAdvPowerLevels[EddystoneURLConfigService::TX_POWER_MODE_LOW ]), 00175 sizeof(uint8_t)); 00176 00177 ble.gap().setTxPower(params.advPowerLevels[params.txPowerMode]); 00178 ble.gap().setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME)); 00179 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00180 ble.gap().setAdvertisingInterval(GapAdvertisingParams::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADVERTISING_INTERVAL_MSEC)); 00181 } 00182 00183 /* Helper function to switch to the non-connectible normal mode for Eddystone-URL beacon. This gets called after a timeout. */ 00184 void setupEddystoneURLAdvertisements() 00185 { 00186 /* Reinitialize the BLE stack. This will clear away the existing services and advertising state. */ 00187 ble.shutdown(); 00188 ble.init(); 00189 00190 // Fields from the Service 00191 unsigned beaconPeriod = params.beaconPeriod; 00192 unsigned txPowerMode = params.txPowerMode; 00193 unsigned uriDataLength = params.uriDataLength; 00194 EddystoneURLConfigService::UriData_t &uriData = params.uriData; 00195 EddystoneURLConfigService::PowerLevels_t &advPowerLevels = params.advPowerLevels; 00196 uint8_t flags = params.flags; 00197 00198 extern void saveEddystoneURLConfigParams(const Params_t *paramsP); /* forward declaration; necessary to avoid a circular dependency. */ 00199 saveEddystoneURLConfigParams(¶ms); 00200 00201 ble.gap().clearAdvertisingPayload(); 00202 ble.gap().setTxPower(params.advPowerLevels[params.txPowerMode]); 00203 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); 00204 ble.gap().setAdvertisingInterval(beaconPeriod); 00205 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 00206 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, EDDYSTONE_BEACON_UUID, sizeof(EDDYSTONE_BEACON_UUID)); 00207 00208 uint8_t serviceData[SERVICE_DATA_MAX]; 00209 unsigned serviceDataLen = 0; 00210 serviceData[serviceDataLen++] = EDDYSTONE_BEACON_UUID[0]; 00211 serviceData[serviceDataLen++] = EDDYSTONE_BEACON_UUID[1]; 00212 serviceData[serviceDataLen++] = flags; 00213 serviceData[serviceDataLen++] = advPowerLevels[txPowerMode]; 00214 for (unsigned j = 0; j < uriDataLength; j++) { 00215 serviceData[serviceDataLen++] = uriData[j]; 00216 } 00217 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen); 00218 } 00219 00220 private: 00221 /* 00222 * This callback is invoked when a GATT client attempts to modify any of the 00223 * characteristics of this service. Attempts to do so are also applied to 00224 * the internal state of this service object. 00225 */ 00226 void onDataWrittenCallback(const GattWriteCallbackParams *writeParams) { 00227 uint16_t handle = writeParams->handle; 00228 00229 if (handle == lockChar.getValueHandle()) { 00230 // Validated earlier 00231 memcpy(params.lock, writeParams->data, sizeof(Lock_t)); 00232 // use isLocked() in case bits are being set to all 0's 00233 params.lockedState = true; 00234 } else if (handle == unlockChar.getValueHandle()) { 00235 // Validated earlier 00236 memset(params.lock, 0, sizeof(Lock_t)); 00237 params.lockedState = false; 00238 } else if (handle == uriDataChar.getValueHandle()) { 00239 params.uriDataLength = writeParams->len; 00240 memcpy(params.uriData, writeParams->data, params.uriDataLength); 00241 } else if (handle == flagsChar.getValueHandle()) { 00242 params.flags = *(writeParams->data); 00243 } else if (handle == advPowerLevelsChar.getValueHandle()) { 00244 memcpy(params.advPowerLevels, writeParams->data, sizeof(PowerLevels_t)); 00245 } else if (handle == txPowerModeChar.getValueHandle()) { 00246 params.txPowerMode = *(writeParams->data); 00247 } else if (handle == beaconPeriodChar.getValueHandle()) { 00248 params.beaconPeriod = *((uint16_t *)(writeParams->data)); 00249 00250 /* Re-map beaconPeriod to within permissible bounds if necessary. */ 00251 if (params.beaconPeriod != 0) { 00252 bool paramsUpdated = false; 00253 if (params.beaconPeriod < ble.gap().getMinAdvertisingInterval()) { 00254 params.beaconPeriod = ble.gap().getMinAdvertisingInterval(); 00255 paramsUpdated = true; 00256 } else if (params.beaconPeriod > ble.gap().getMaxAdvertisingInterval()) { 00257 params.beaconPeriod = ble.gap().getMaxAdvertisingInterval(); 00258 paramsUpdated = true; 00259 } 00260 if (paramsUpdated) { 00261 ble.gattServer().write(beaconPeriodChar.getValueHandle(), reinterpret_cast<uint8_t *>(¶ms.beaconPeriod), sizeof(uint16_t)); 00262 } 00263 } 00264 } else if (handle == resetChar.getValueHandle()) { 00265 resetToDefaults(); 00266 } 00267 } 00268 00269 /* 00270 * Reset the default values. 00271 */ 00272 void resetToDefaults(void) { 00273 params.lockedState = false; 00274 memset(params.lock, 0, sizeof(Lock_t)); 00275 memcpy(params.uriData, defaultUriData, URI_DATA_MAX); 00276 params.uriDataLength = defaultUriDataLength; 00277 params.flags = 0x10; 00278 memcpy(params.advPowerLevels, defaultAdvPowerLevels, sizeof(PowerLevels_t)); 00279 params.txPowerMode = TX_POWER_MODE_LOW ; 00280 params.beaconPeriod = 1000; 00281 updateCharacteristicValues(); 00282 } 00283 00284 /* 00285 * Internal helper function used to update the GATT database following any 00286 * change to the internal state of the service object. 00287 */ 00288 void updateCharacteristicValues(void) { 00289 ble.gattServer().write(lockedStateChar.getValueHandle(), ¶ms.lockedState, 1); 00290 ble.gattServer().write(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength); 00291 ble.gattServer().write(flagsChar.getValueHandle(), ¶ms.flags, 1); 00292 ble.gattServer().write(beaconPeriodChar.getValueHandle(), 00293 reinterpret_cast<uint8_t *>(¶ms.beaconPeriod), sizeof(uint16_t)); 00294 ble.gattServer().write(txPowerModeChar.getValueHandle(), ¶ms.txPowerMode, 1); 00295 ble.gattServer().write(advPowerLevelsChar.getValueHandle(), 00296 reinterpret_cast<uint8_t *>(params.advPowerLevels), sizeof(PowerLevels_t)); 00297 } 00298 00299 protected: 00300 void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) { 00301 if (params.lockedState) { 00302 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION; 00303 } else if (authParams->len != sizeof(Lock_t)) { 00304 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH; 00305 } else if (authParams->offset != 0) { 00306 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET; 00307 } else { 00308 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS; 00309 } 00310 } 00311 00312 00313 void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) { 00314 if ((!params.lockedState) && (authParams->len == sizeof(Lock_t))) { 00315 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS; 00316 } else if (authParams->len != sizeof(Lock_t)) { 00317 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH; 00318 } else if (authParams->offset != 0) { 00319 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET; 00320 } else if (memcmp(authParams->data, params.lock, sizeof(Lock_t)) != 0) { 00321 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION; 00322 } else { 00323 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS; 00324 } 00325 } 00326 00327 void uriDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams) { 00328 if (params.lockedState) { 00329 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION; 00330 } else if (authParams->offset != 0) { 00331 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET; 00332 } else { 00333 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS; 00334 } 00335 } 00336 00337 void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams) { 00338 if (params.lockedState) { 00339 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION; 00340 } else if (authParams->len != sizeof(uint8_t)) { 00341 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH; 00342 } else if (authParams->offset != 0) { 00343 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET; 00344 } else if (*((uint8_t *)authParams->data) >= NUM_POWER_MODES ) { 00345 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED; 00346 } else { 00347 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS; 00348 } 00349 } 00350 00351 template <typename T> 00352 void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams) { 00353 if (params.lockedState) { 00354 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION; 00355 } else if (authParams->len != sizeof(T)) { 00356 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH; 00357 } else if (authParams->offset != 0) { 00358 authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET; 00359 } else { 00360 authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS; 00361 } 00362 } 00363 00364 protected: 00365 BLE &ble; 00366 Params_t ¶ms; 00367 00368 size_t defaultUriDataLength; // Default value that is restored on reset 00369 UriData_t defaultUriData; // Default value that is restored on reset 00370 PowerLevels_t &defaultAdvPowerLevels; // Default value that is restored on reset 00371 00372 bool initSucceeded; 00373 uint8_t resetFlag; 00374 00375 ReadOnlyGattCharacteristic<uint8_t> lockedStateChar; 00376 WriteOnlyGattCharacteristic<Lock_t> lockChar; 00377 GattCharacteristic uriDataChar; 00378 WriteOnlyGattCharacteristic<Lock_t> unlockChar; 00379 ReadWriteGattCharacteristic<uint8_t> flagsChar; 00380 ReadWriteGattCharacteristic<PowerLevels_t> advPowerLevelsChar; 00381 ReadWriteGattCharacteristic<uint8_t> txPowerModeChar; 00382 ReadWriteGattCharacteristic<uint16_t> beaconPeriodChar; 00383 WriteOnlyGattCharacteristic<uint8_t> resetChar; 00384 00385 public: 00386 /* 00387 * Encode a human-readable URI into the binary format defined by Eddysteone URL beacon spec (https://github.com/google/eddystone/tree/master/eddystone-url. 00388 */ 00389 static void encodeURI(const char *uriDataIn, UriData_t uriDataOut, size_t &sizeofURIDataOut) { 00390 const char *prefixes[] = { 00391 "http://www.", 00392 "https://www.", 00393 "http://", 00394 "https://", 00395 "urn:uuid:" 00396 }; 00397 const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *); 00398 const char *suffixes[] = { 00399 ".com/", 00400 ".org/", 00401 ".edu/", 00402 ".net/", 00403 ".info/", 00404 ".biz/", 00405 ".gov/", 00406 ".com", 00407 ".org", 00408 ".edu", 00409 ".net", 00410 ".info", 00411 ".biz", 00412 ".gov" 00413 }; 00414 const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *); 00415 00416 sizeofURIDataOut = 0; 00417 memset(uriDataOut, 0, sizeof(UriData_t)); 00418 00419 if ((uriDataIn == NULL) || (strlen(uriDataIn) == 0)) { 00420 return; 00421 } 00422 00423 /* 00424 * handle prefix 00425 */ 00426 for (unsigned i = 0; i < NUM_PREFIXES; i++) { 00427 size_t prefixLen = strlen(prefixes[i]); 00428 if (strncmp(uriDataIn, prefixes[i], prefixLen) == 0) { 00429 uriDataOut[sizeofURIDataOut++] = i; 00430 uriDataIn += prefixLen; 00431 break; 00432 } 00433 } 00434 00435 /* 00436 * handle suffixes 00437 */ 00438 while (*uriDataIn && (sizeofURIDataOut < URI_DATA_MAX)) { 00439 /* check for suffix match */ 00440 unsigned i; 00441 for (i = 0; i < NUM_SUFFIXES; i++) { 00442 size_t suffixLen = strlen(suffixes[i]); 00443 if (strncmp(uriDataIn, suffixes[i], suffixLen) == 0) { 00444 uriDataOut[sizeofURIDataOut++] = i; 00445 uriDataIn += suffixLen; 00446 break; /* from the for loop for checking against suffixes */ 00447 } 00448 } 00449 /* This is the default case where we've got an ordinary character which doesn't match a suffix. */ 00450 if (i == NUM_SUFFIXES) { 00451 uriDataOut[sizeofURIDataOut++] = *uriDataIn; 00452 ++uriDataIn; 00453 } 00454 } 00455 } 00456 }; 00457 00458 #endif // SERVICES_EDDYSTONEURLCONFIGSERVICE_H_
Generated on Tue Jul 12 2022 21:57:19 by 1.7.2