High level Bluetooth Low Energy API and radio abstraction layer

Dependents:   BLE_ANCS_SDAPI BLE_temperature BLE_HeartRate BLE_ANCS_SDAPI_IRC ... more

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