Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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