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 Bluetooth Low Energy

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers URIBeaconConfigService.h Source File

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