Clone of the nRF51822 repository from github The correct home is https://github.com/lancaster-university/nRF51822

Dependencies:   nrf51-sdk

Dependents:   microbit-dal microbit-ble-open microbit-dal-eddystone microbit-dal-ble-accelerometer-example ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nRF5xServiceDiscovery.h Source File

nRF5xServiceDiscovery.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 __NRF_SERVICE_DISCOVERY_H__
00018 #define __NRF_SERVICE_DISCOVERY_H__
00019 
00020 #include "ble/ServiceDiscovery.h"
00021 #include "ble/DiscoveredService.h"
00022 #include "nRF5xDiscoveredCharacteristic.h"
00023 
00024 #include "ble.h"
00025 #include "ble_gattc.h"
00026 
00027 class nRF5xGattClient; /* forward declaration */
00028 
00029 class nRF5xServiceDiscovery : public ServiceDiscovery
00030 {
00031 public:
00032     static const uint16_t SRV_DISC_START_HANDLE             = 0x0001; /**< The start handle value used during service discovery. */
00033     static const uint16_t SRV_DISC_END_HANDLE               = 0xFFFF; /**< The end handle value used during service discovery. */
00034 
00035 public:
00036     static const unsigned BLE_DB_DISCOVERY_MAX_SRV          = 4;      /**< Maximum number of services we can retain information for after a single discovery. */
00037     static const unsigned BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV = 4;      /**< Maximum number of characteristics per service we can retain information for. */
00038 
00039 public:
00040     nRF5xServiceDiscovery(nRF5xGattClient *gattcIn) :
00041         gattc(gattcIn),
00042         serviceIndex(0),
00043         numServices(0),
00044         numCharacteristics(0),
00045         state(INACTIVE),
00046         services(),
00047         characteristics(),
00048         serviceUUIDDiscoveryQueue(this),
00049         charUUIDDiscoveryQueue(this),
00050         onTerminationCallback(NULL) {
00051         /* empty */
00052     }
00053 
00054     virtual ble_error_t launch(Gap::Handle_t                               connectionHandle,
00055                                ServiceDiscovery::ServiceCallback_t         sc,
00056                                ServiceDiscovery::CharacteristicCallback_t  cc,
00057                                const UUID                                 &matchingServiceUUIDIn,
00058                                const UUID                                 &matchingCharacteristicUUIDIn)
00059     {
00060         if (isActive()) {
00061             return BLE_ERROR_INVALID_STATE;
00062         }
00063 
00064         serviceCallback            = sc;
00065         characteristicCallback     = cc;
00066         matchingServiceUUID        = matchingServiceUUIDIn;
00067         matchingCharacteristicUUID = matchingCharacteristicUUIDIn;
00068 
00069         serviceDiscoveryStarted(connectionHandle);
00070 
00071         uint32_t rc;
00072         if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) {
00073             terminate();
00074             switch (rc) {
00075                 case NRF_ERROR_INVALID_PARAM:
00076                 case BLE_ERROR_INVALID_CONN_HANDLE:
00077                     return BLE_ERROR_INVALID_PARAM;
00078                 case NRF_ERROR_BUSY:
00079                     return BLE_STACK_BUSY;
00080                 default:
00081                 case NRF_ERROR_INVALID_STATE:
00082                     return BLE_ERROR_INVALID_STATE;
00083             }
00084         }
00085 
00086         return BLE_ERROR_NONE;
00087     }
00088 
00089     virtual bool isActive(void) const {
00090         return state != INACTIVE;
00091     }
00092 
00093     virtual void terminate(void) {
00094         terminateServiceDiscovery();
00095     }
00096 
00097     void terminate(Gap::Handle_t connectionHandle) {
00098         if(connHandle == connectionHandle) {
00099             terminate();
00100         }
00101     }
00102 
00103     virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) {
00104         onTerminationCallback = callback;
00105     }
00106 
00107     /**
00108      * @brief  Clear nRF5xServiceDiscovery's state.
00109      *
00110      * @return
00111      *           BLE_ERROR_NONE if successful.
00112      */
00113     virtual ble_error_t reset(void) {
00114         /* Clear all state that is from the parent, including private members */
00115         if (ServiceDiscovery::reset() != BLE_ERROR_NONE) {
00116             return BLE_ERROR_INVALID_STATE;
00117         }
00118 
00119         /* Clear derived class members */
00120         serviceIndex = 0;
00121         numServices = 0;
00122         numCharacteristics = 0;
00123 
00124         state = INACTIVE;
00125 
00126         serviceUUIDDiscoveryQueue.reset();
00127         charUUIDDiscoveryQueue.reset();
00128 
00129         onTerminationCallback = NULL;
00130 
00131         return BLE_ERROR_NONE;
00132     }
00133 
00134 private:
00135     ble_error_t launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, Gap::Handle_t startHandle, Gap::Handle_t endHandle);
00136 
00137 private:
00138     void setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response);
00139     void setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response);
00140 
00141     void triggerServiceUUIDDiscovery(void);
00142     void processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response);
00143     void removeFirstServiceNeedingUUIDDiscovery(void);
00144 
00145     void terminateServiceDiscovery(void) {
00146         discoveredCharacteristic = nRF5xDiscoveredCharacteristic();
00147 
00148         bool wasActive = isActive();
00149         state = INACTIVE;
00150 
00151         if (wasActive && onTerminationCallback) {
00152             onTerminationCallback(connHandle);
00153         }
00154     }
00155 
00156     void terminateCharacteristicDiscovery(ble_error_t err) {
00157         if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) {
00158             if(discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) {
00159                if(err == BLE_ERROR_NONE) {
00160                     // fullfill the last characteristic
00161                     discoveredCharacteristic.setLastHandle(services[serviceIndex].getEndHandle());
00162 
00163                     if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
00164                         ((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) &&
00165                          (matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
00166                         if (characteristicCallback) {
00167                             characteristicCallback(&discoveredCharacteristic);
00168                         }
00169                     }
00170                }
00171                discoveredCharacteristic = nRF5xDiscoveredCharacteristic();
00172             }
00173 
00174             state = SERVICE_DISCOVERY_ACTIVE;
00175         }
00176         serviceIndex++; /* Progress service index to keep discovery alive. */
00177     }
00178 
00179 private:
00180     void resetDiscoveredServices(void) {
00181         numServices  = 0;
00182         serviceIndex = 0;
00183     }
00184 
00185     void resetDiscoveredCharacteristics(void) {
00186         numCharacteristics  = 0;
00187     }
00188 
00189 private:
00190     void serviceDiscoveryStarted(Gap::Handle_t connectionHandle) {
00191         connHandle = connectionHandle;
00192         resetDiscoveredServices();
00193         state = SERVICE_DISCOVERY_ACTIVE;
00194     }
00195 
00196 private:
00197     void characteristicDiscoveryStarted(Gap::Handle_t connectionHandle) {
00198         connHandle = connectionHandle;
00199         resetDiscoveredCharacteristics();
00200         state = CHARACTERISTIC_DISCOVERY_ACTIVE;
00201     }
00202 
00203 private:
00204     /**
00205      * A datatype to contain service-indices for which long UUIDs need to be
00206      * discovered using read_val_by_uuid().
00207      */
00208     class ServiceUUIDDiscoveryQueue {
00209     public:
00210         ServiceUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) :
00211             numIndices(0),
00212             serviceIndices(),
00213             parentDiscoveryObject(parent) {
00214             /* empty */
00215         }
00216 
00217     public:
00218         void reset(void) {
00219             numIndices = 0;
00220             for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
00221                 serviceIndices[i] = INVALID_INDEX;
00222             }
00223         }
00224         void enqueue(int serviceIndex) {
00225             serviceIndices[numIndices++] = serviceIndex;
00226         }
00227         int dequeue(void) {
00228             if (numIndices == 0) {
00229                 return INVALID_INDEX;
00230             }
00231 
00232             unsigned valueToReturn = serviceIndices[0];
00233             numIndices--;
00234             for (unsigned i = 0; i < numIndices; i++) {
00235                 serviceIndices[i] = serviceIndices[i + 1];
00236             }
00237 
00238             return valueToReturn;
00239         }
00240         unsigned getFirst(void) const {
00241             return serviceIndices[0];
00242         }
00243         size_t getCount(void) const {
00244             return numIndices;
00245         }
00246 
00247         /**
00248          * Trigger UUID discovery for the first of the enqueued ServiceIndices.
00249          */
00250         void triggerFirst(void);
00251 
00252     private:
00253         static const int INVALID_INDEX = -1;
00254 
00255     private:
00256         size_t numIndices;
00257         int    serviceIndices[BLE_DB_DISCOVERY_MAX_SRV];
00258 
00259         nRF5xServiceDiscovery *parentDiscoveryObject;
00260     };
00261     friend class ServiceUUIDDiscoveryQueue;
00262 
00263     /**
00264      * A datatype to contain characteristic-indices for which long UUIDs need to
00265      * be discovered using read_val_by_uuid().
00266      */
00267     class CharUUIDDiscoveryQueue {
00268     public:
00269         CharUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) :
00270             numIndices(0),
00271             charIndices(),
00272             parentDiscoveryObject(parent) {
00273             /* empty */
00274         }
00275 
00276     public:
00277         void reset(void) {
00278             numIndices = 0;
00279             for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
00280                 charIndices[i] = INVALID_INDEX;
00281             }
00282         }
00283         void enqueue(int serviceIndex) {
00284             charIndices[numIndices++] = serviceIndex;
00285         }
00286         int dequeue(void) {
00287             if (numIndices == 0) {
00288                 return INVALID_INDEX;
00289             }
00290 
00291             unsigned valueToReturn = charIndices[0];
00292             numIndices--;
00293             for (unsigned i = 0; i < numIndices; i++) {
00294                 charIndices[i] = charIndices[i + 1];
00295             }
00296 
00297             return valueToReturn;
00298         }
00299         unsigned getFirst(void) const {
00300             return charIndices[0];
00301         }
00302         size_t getCount(void) const {
00303             return numIndices;
00304         }
00305 
00306         /**
00307          * Trigger UUID discovery for the first of the enqueued charIndices.
00308          */
00309         void triggerFirst(void);
00310 
00311     private:
00312         static const int INVALID_INDEX = -1;
00313 
00314     private:
00315         size_t numIndices;
00316         int    charIndices[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
00317 
00318         nRF5xServiceDiscovery *parentDiscoveryObject;
00319     };
00320     friend class CharUUIDDiscoveryQueue;
00321 
00322 private:
00323     friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt);
00324     void progressCharacteristicDiscovery(void);
00325     void progressServiceDiscovery(void);
00326 
00327 private:
00328     nRF5xGattClient *gattc;
00329 
00330 private:
00331     uint8_t  serviceIndex;        /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/
00332     uint8_t  numServices;         /**< Number of services at the peers GATT database.*/
00333     uint8_t  numCharacteristics;  /**< Number of characteristics within the service.*/
00334 
00335     enum State_t {
00336         INACTIVE,
00337         SERVICE_DISCOVERY_ACTIVE,
00338         CHARACTERISTIC_DISCOVERY_ACTIVE,
00339         DISCOVER_SERVICE_UUIDS,
00340         DISCOVER_CHARACTERISTIC_UUIDS,
00341     } state;
00342 
00343     DiscoveredService           services[BLE_DB_DISCOVERY_MAX_SRV];  /**< Information related to the current service being discovered.
00344                                                                       *  This is intended for internal use during service discovery. */
00345     nRF5xDiscoveredCharacteristic characteristics[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
00346 
00347     ServiceUUIDDiscoveryQueue   serviceUUIDDiscoveryQueue;
00348     CharUUIDDiscoveryQueue      charUUIDDiscoveryQueue;
00349 
00350     TerminationCallback_t       onTerminationCallback;
00351 
00352     /*
00353      * The currently discovered characteristic. Discovery of a characteristic
00354      * is a two phase process.
00355      * First, declaration handle is fetched, it provide the UUID, the value handle and
00356      * the properties of a characteristic.
00357      * Second, the next declaration handle is fetched, with its declaration handle, it is
00358      * possible to compute the last handle of the discovered characteristic and fill the
00359      * missing part of the object.
00360      * If there is no remaining characteristic to discover, the last handle of the
00361      * discovered characteristic will be set to the last handle of its enclosing service.
00362      */
00363     nRF5xDiscoveredCharacteristic discoveredCharacteristic;
00364 };
00365 
00366 #endif /*__NRF_SERVICE_DISCOVERY_H__*/