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