test

Fork of nRF51822 by Nordic Semiconductor

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         characteristicIndex(0),
00045         numCharacteristics(0),
00046         state(INACTIVE),
00047         services(),
00048         characteristics(),
00049         serviceUUIDDiscoveryQueue(this),
00050         charUUIDDiscoveryQueue(this),
00051         onTerminationCallback(NULL) {
00052         /* empty */
00053     }
00054 
00055     virtual ble_error_t launch(Gap::Handle_t                               connectionHandle,
00056                                ServiceDiscovery::ServiceCallback_t         sc,
00057                                ServiceDiscovery::CharacteristicCallback_t  cc,
00058                                const UUID                                 &matchingServiceUUIDIn,
00059                                const UUID                                 &matchingCharacteristicUUIDIn)
00060     {
00061         if (isActive()) {
00062             return BLE_ERROR_INVALID_STATE;
00063         }
00064 
00065         serviceCallback            = sc;
00066         characteristicCallback     = cc;
00067         matchingServiceUUID        = matchingServiceUUIDIn;
00068         matchingCharacteristicUUID = matchingCharacteristicUUIDIn;
00069 
00070         serviceDiscoveryStarted(connectionHandle);
00071 
00072         uint32_t rc;
00073         if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) {
00074             terminate();
00075             switch (rc) {
00076                 case NRF_ERROR_INVALID_PARAM:
00077                 case BLE_ERROR_INVALID_CONN_HANDLE:
00078                     return BLE_ERROR_INVALID_PARAM;
00079                 case NRF_ERROR_BUSY:
00080                     return BLE_STACK_BUSY;
00081                 default:
00082                 case NRF_ERROR_INVALID_STATE:
00083                     return BLE_ERROR_INVALID_STATE;
00084             }
00085         }
00086 
00087         return BLE_ERROR_NONE;
00088     }
00089 
00090     virtual bool isActive(void) const {
00091         return state != INACTIVE;
00092     }
00093 
00094     virtual void terminate(void) {
00095         terminateServiceDiscovery();
00096     }
00097 
00098     virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) {
00099         onTerminationCallback = callback;
00100     }
00101 
00102 private:
00103     ble_error_t launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, Gap::Handle_t startHandle, Gap::Handle_t endHandle);
00104 
00105 private:
00106     void setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response);
00107     void setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response);
00108 
00109     void triggerServiceUUIDDiscovery(void);
00110     void processDiscoverUUIDResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t *response);
00111     void removeFirstServiceNeedingUUIDDiscovery(void);
00112 
00113     void terminateServiceDiscovery(void) {
00114         bool wasActive = isActive();
00115         state = INACTIVE;
00116 
00117         if (wasActive && onTerminationCallback) {
00118             onTerminationCallback(connHandle);
00119         }
00120     }
00121 
00122     void terminateCharacteristicDiscovery(void) {
00123         if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) {
00124             state = SERVICE_DISCOVERY_ACTIVE;
00125         }
00126         serviceIndex++; /* Progress service index to keep discovery alive. */
00127     }
00128 
00129 private:
00130     void resetDiscoveredServices(void) {
00131         numServices  = 0;
00132         serviceIndex = 0;
00133     }
00134 
00135     void resetDiscoveredCharacteristics(void) {
00136         numCharacteristics  = 0;
00137         characteristicIndex = 0;
00138     }
00139 
00140 private:
00141     void serviceDiscoveryStarted(Gap::Handle_t connectionHandle) {
00142         connHandle = connectionHandle;
00143         resetDiscoveredServices();
00144         state = SERVICE_DISCOVERY_ACTIVE;
00145     }
00146 
00147 private:
00148     void characteristicDiscoveryStarted(Gap::Handle_t connectionHandle) {
00149         connHandle = connectionHandle;
00150         resetDiscoveredCharacteristics();
00151         state = CHARACTERISTIC_DISCOVERY_ACTIVE;
00152     }
00153 
00154 private:
00155     /**
00156      * A datatype to contain service-indices for which long UUIDs need to be
00157      * discovered using read_val_by_uuid().
00158      */
00159     class ServiceUUIDDiscoveryQueue {
00160     public:
00161         ServiceUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) :
00162             numIndices(0),
00163             serviceIndices(),
00164             parentDiscoveryObject(parent) {
00165             /* empty */
00166         }
00167 
00168     public:
00169         void reset(void) {
00170             numIndices = 0;
00171             for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
00172                 serviceIndices[i] = INVALID_INDEX;
00173             }
00174         }
00175         void enqueue(int serviceIndex) {
00176             serviceIndices[numIndices++] = serviceIndex;
00177         }
00178         int dequeue(void) {
00179             if (numIndices == 0) {
00180                 return INVALID_INDEX;
00181             }
00182 
00183             unsigned valueToReturn = serviceIndices[0];
00184             numIndices--;
00185             for (unsigned i = 0; i < numIndices; i++) {
00186                 serviceIndices[i] = serviceIndices[i + 1];
00187             }
00188 
00189             return valueToReturn;
00190         }
00191         unsigned getFirst(void) const {
00192             return serviceIndices[0];
00193         }
00194         size_t getCount(void) const {
00195             return numIndices;
00196         }
00197 
00198         /**
00199          * Trigger UUID discovery for the first of the enqueued ServiceIndices.
00200          */
00201         void triggerFirst(void);
00202 
00203     private:
00204         static const int INVALID_INDEX = -1;
00205 
00206     private:
00207         size_t numIndices;
00208         int    serviceIndices[BLE_DB_DISCOVERY_MAX_SRV];
00209 
00210         nRF5xServiceDiscovery *parentDiscoveryObject;
00211     };
00212     friend class ServiceUUIDDiscoveryQueue;
00213 
00214     /**
00215      * A datatype to contain characteristic-indices for which long UUIDs need to
00216      * be discovered using read_val_by_uuid().
00217      */
00218     class CharUUIDDiscoveryQueue {
00219     public:
00220         CharUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) :
00221             numIndices(0),
00222             charIndices(),
00223             parentDiscoveryObject(parent) {
00224             /* empty */
00225         }
00226 
00227     public:
00228         void reset(void) {
00229             numIndices = 0;
00230             for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
00231                 charIndices[i] = INVALID_INDEX;
00232             }
00233         }
00234         void enqueue(int serviceIndex) {
00235             charIndices[numIndices++] = serviceIndex;
00236         }
00237         int dequeue(void) {
00238             if (numIndices == 0) {
00239                 return INVALID_INDEX;
00240             }
00241 
00242             unsigned valueToReturn = charIndices[0];
00243             numIndices--;
00244             for (unsigned i = 0; i < numIndices; i++) {
00245                 charIndices[i] = charIndices[i + 1];
00246             }
00247 
00248             return valueToReturn;
00249         }
00250         unsigned getFirst(void) const {
00251             return charIndices[0];
00252         }
00253         size_t getCount(void) const {
00254             return numIndices;
00255         }
00256 
00257         /**
00258          * Trigger UUID discovery for the first of the enqueued charIndices.
00259          */
00260         void triggerFirst(void);
00261 
00262     private:
00263         static const int INVALID_INDEX = -1;
00264 
00265     private:
00266         size_t numIndices;
00267         int    charIndices[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
00268 
00269         nRF5xServiceDiscovery *parentDiscoveryObject;
00270     };
00271     friend class CharUUIDDiscoveryQueue;
00272 
00273 private:
00274     friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt);
00275     void progressCharacteristicDiscovery(void);
00276     void progressServiceDiscovery(void);
00277 
00278 private:
00279     nRF5xGattClient *gattc;
00280 
00281 private:
00282     uint8_t  serviceIndex;        /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/
00283     uint8_t  numServices;         /**< Number of services at the peers GATT database.*/
00284     uint8_t  characteristicIndex; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/
00285     uint8_t  numCharacteristics;  /**< Number of characteristics within the service.*/
00286 
00287     enum State_t {
00288         INACTIVE,
00289         SERVICE_DISCOVERY_ACTIVE,
00290         CHARACTERISTIC_DISCOVERY_ACTIVE,
00291         DISCOVER_SERVICE_UUIDS,
00292         DISCOVER_CHARACTERISTIC_UUIDS,
00293     } state;
00294 
00295     DiscoveredService           services[BLE_DB_DISCOVERY_MAX_SRV];  /**< Information related to the current service being discovered.
00296                                                                       *  This is intended for internal use during service discovery. */
00297     nRF5xDiscoveredCharacteristic characteristics[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
00298 
00299     ServiceUUIDDiscoveryQueue   serviceUUIDDiscoveryQueue;
00300     CharUUIDDiscoveryQueue      charUUIDDiscoveryQueue;
00301 
00302     TerminationCallback_t       onTerminationCallback;
00303 };
00304 
00305 #endif /*__NRF_SERVICE_DISCOVERY_H__*/