Release 0.4.0

=============

This is a major release which introduces the GATT Client functionality. It
also aligns BLE_API with builds using our new package manager: yotta
(https://github.com/armmbed/yotta).

Many APIs have seen some redesign. We encourage our users to pay attention to
the changes and migrate appropriately over time. We've also taken care to
ensure that existing code continues to work the same way. There's more
documentation in the form of comment headers for APIs to explain proper usage;
in many cases comment headers suggest alternative use of APIs.

Enhancements
~~~~~~~~~~~~

* Introduce GattClient. This includes functionality for service-discovery,
  connections, and attribute-reads and writes. You'll find a demo program for
  LEDBlinker on the mbed.org Bluetooth team page to use the new APIs. Some of
  the GATT client functionality hasn't been implemented yet, but the APIs have
  been added.

* Most APIs in the abstract base classes like Gap and GattServer return
  BLE_ERROR_NOT_IMPLEMENTED. Previously many APIs were pure-virtual, which did
  not permit partial ports to compile.

* We've added a new abstract base class for SecurityManager. All security
  related APIs have been moved into that.

* BLEDevice has been renamed as BLE. A deprecated alias for BLEDevice is
  available to support existing code.

* There has been a major cleanup of APIs under BLE. APIs have now been
  categorized as belonging to Gap, GattServer, GattClient, or SecurityManager.
  There are accessors to get references for Gap, GattServer, GattClient, and
  SecurityManager. A former call to ble.setAddress(...) is now expected to be
  achieved with ble.gap().setAddress(...).

* We've cleaned up our APIs, and this has resulted in dropping some APIs like
  BLE::reset().

* We've also dropped GattServer::initializeGattDatabase(). THis was added at
  some point to support controllers where a commit point was needed to
  indicate when the application had finished constructing the GATT database.
  This API would get called internally before Gap::startAdvertising(). We now
  expect the underlying port to do the equivalent of initializeGattDatabase()
  implicitly upon Gap::startAdvertising().

* The callback for BLE.onTimeout() now receives a TimeoutSource_t to indicate
  the cause of the timeout. This is perhaps the only breaking API change. We
  expect it to have very little disruptive effect.

* We've added a version of Gap::disconnect() which takes a connection handle.
  The previous API (which did not take a connection handle) has been
  deprecated; it will still work for situations where there's only a single
  active connection. We hold on to that API to allow existing code to migrate
  to the new API.

Bugfixes
~~~~~~~~

* None.
This commit is contained in:
Rohit Grover 2015-06-19 15:46:48 +01:00
commit d80fec885c
43 changed files with 3852 additions and 1988 deletions

1342
ble/BLE.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,36 +17,40 @@
#ifndef __BLE_DEVICE_INSTANCE_BASE__
#define __BLE_DEVICE_INSTANCE_BASE__
#include "Gap.h"
/* forward declarations */
class GattServer;
class GattClient;
/**
* The interface for the transport object to be created by the target library's
* createBLEDeviceInstance().
* createBLEInstance().
*/
class BLEDeviceInstanceBase
class BLEInstanceBase
{
public:
virtual const char *getVersion(void) = 0;
virtual Gap& getGap() = 0;
virtual GattServer& getGattServer() = 0;
virtual ble_error_t init(void) = 0;
virtual ble_error_t shutdown(void) = 0;
virtual ble_error_t reset(void) = 0;
virtual ble_error_t initializeSecurity(bool enableBonding = true,
bool requireMITM = true,
Gap::SecurityIOCapabilities_t iocaps = Gap::IO_CAPS_NONE,
const Gap::Passkey_t passkey = NULL) = 0;
virtual ble_error_t setTxPower(int8_t txPower) = 0;
virtual void getPermittedTxPowerValues(const int8_t **, size_t *) = 0;
virtual ble_error_t init(void) = 0;
virtual ble_error_t shutdown(void) = 0;
virtual const char *getVersion(void) = 0;
virtual Gap& getGap() = 0;
virtual const Gap& getGap() const = 0;
virtual GattServer& getGattServer() = 0;
virtual const GattServer& getGattServer() const = 0;
virtual GattClient& getGattClient() = 0;
virtual SecurityManager& getSecurityManager() = 0;
virtual const SecurityManager& getSecurityManager() const = 0;
virtual void waitForEvent(void) = 0;
};
/**
* BLEDevice uses composition to hide an interface object encapsulating the
* BLE uses composition to hide an interface object encapsulating the
* backend transport.
*
* The following API is used to create the singleton interface object. An
* implementation for this function must be provided by the device-specific
* library, otherwise there will be a linker error.
*/
extern BLEDeviceInstanceBase *createBLEDeviceInstance(void);
extern BLEInstanceBase *createBLEInstance(void);
#endif // ifndef __BLE_DEVICE_INSTANCE_BASE__

View File

@ -0,0 +1,191 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __DISCOVERED_CHARACTERISTIC_H__
#define __DISCOVERED_CHARACTERISTIC_H__
#include "UUID.h"
#include "Gap.h"
#include "GattAttribute.h"
#include "GattClient.h"
/**
* Structure for holding information about the service and the characteristics
* found during the discovery process.
*/
class DiscoveredCharacteristic {
public:
struct Properties_t {
uint8_t _broadcast :1; /**< Broadcasting of the value permitted. */
uint8_t _read :1; /**< Reading the value permitted. */
uint8_t _writeWoResp :1; /**< Writing the value with Write Command permitted. */
uint8_t _write :1; /**< Writing the value with Write Request permitted. */
uint8_t _notify :1; /**< Notications of the value permitted. */
uint8_t _indicate :1; /**< Indications of the value permitted. */
uint8_t _authSignedWrite :1; /**< Writing the value with Signed Write Command permitted. */
public:
bool broadcast(void) const {return _broadcast; }
bool read(void) const {return _read; }
bool writeWoResp(void) const {return _writeWoResp; }
bool write(void) const {return _write; }
bool notify(void) const {return _notify; }
bool indicate(void) const {return _indicate; }
bool authSignedWrite(void) const {return _authSignedWrite;}
private:
operator uint8_t() const; /* disallow implicit conversion into an integer */
operator unsigned() const; /* disallow implicit conversion into an integer */
};
/**
* Structure for holding information about the service and the characteristics
* found during the discovery process.
*/
struct DiscoveredDescriptor {
GattAttribute::Handle_t handle; /**< Descriptor Handle. */
UUID uuid; /**< Descriptor UUID. */
};
/**
* Callback type for when a characteristic descriptor is found during descriptor-
* discovery. The receiving function is passed in a pointer to a
* DiscoveredDescriptor object which will remain valid for the lifetime
* of the callback. Memory for this object is owned by the BLE_API eventing
* framework. The application can safely make a persistent shallow-copy of
* this object in order to work with the characteristic beyond the callback.
*/
typedef void (*DescriptorCallback_t)(const DiscoveredDescriptor *);
/**
* Initiate (or continue) a read for the value attribute, optionally at a
* given offset. If the Characteristic or Descriptor to be read is longer
* than ATT_MTU - 1, this function must be called multiple times with
* appropriate offset to read the complete value.
*
* @return BLE_ERROR_NONE if a read has been initiated, else
* BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
* BLE_STACK_BUSY if some client procedure already in progress, or
* BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
*/
ble_error_t read(uint16_t offset = 0) const;
/**
* Perform a write without response procedure.
*
* @param length
* The amount of data being written.
* @param value
* The bytes being written.
*
* @note It is important to note that a write without response will generate
* an onDataSent() callback when the packet has been transmitted. There
* will be a BLE-stack specific limit to the number of pending
* writeWoResponse operations; the user may want to use the onDataSent()
* callback for flow-control.
*
* @retval BLE_ERROR_NONE Successfully started the Write procedure, else
* BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
* BLE_STACK_BUSY if some client procedure already in progress, or
* BLE_ERROR_NO_MEM if there are no available buffers left to process the request, or
* BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
*/
ble_error_t writeWoResponse(uint16_t length, const uint8_t *value) const;
/**
* Initiate a GATT Characteristic Descriptor Discovery procedure for descriptors within this characteristic.
*
* @param callback
* @param matchingUUID
* filter for descriptors. Defaults to wildcard which will discover all descriptors.
*
* @return BLE_ERROR_NONE if descriptor discovery is launched successfully; else an appropriate error.
*/
ble_error_t discoverDescriptors(DescriptorCallback_t callback, const UUID &matchingUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) const;
/**
* Perform a write procedure.
*
* @param length
* The amount of data being written.
* @param value
* The bytes being written.
*
* @note It is important to note that a write will generate
* an onDataWritten() callback when the peer acknowledges the request.
*
* @retval BLE_ERROR_NONE Successfully started the Write procedure, else
* BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
* BLE_STACK_BUSY if some client procedure already in progress, or
* BLE_ERROR_NO_MEM if there are no available buffers left to process the request, or
* BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
*/
ble_error_t write(uint16_t length, const uint8_t *value) const;
static void setupOnDataRead(GattClient::ReadCallback_t callback) {
onDataReadCallback = callback;
}
static void setupOnDataWrite(GattClient::WriteCallback_t callback) {
onDataWriteCallback = callback;
}
void setupLongUUID(UUID::LongUUIDBytes_t longUUID) {
uuid.setupLong(longUUID);
}
public:
UUID::ShortUUIDBytes_t getShortUUID(void) const {
return uuid.getShortUUID();
}
const Properties_t& getProperties(void) const {
return props;
}
const GattAttribute::Handle_t& getDeclHandle(void) const {
return declHandle;
}
const GattAttribute::Handle_t& getValueHandle(void) const {
return valueHandle;
}
public:
DiscoveredCharacteristic() : gattc(NULL),
uuid(UUID::ShortUUIDBytes_t(0)),
props(),
declHandle(GattAttribute::INVALID_HANDLE),
valueHandle(GattAttribute::INVALID_HANDLE) {
/* empty */
}
protected:
GattClient *gattc;
protected:
UUID uuid;
Properties_t props;
GattAttribute::Handle_t declHandle;
GattAttribute::Handle_t valueHandle;
Gap::Handle_t connHandle;
public:
static GattClient::ReadCallback_t onDataReadCallback;
static GattClient::WriteCallback_t onDataWriteCallback;
};
#endif /*__DISCOVERED_CHARACTERISTIC_H__*/

71
ble/DiscoveredService.h Normal file
View File

@ -0,0 +1,71 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __DISCOVERED_SERVICE_H__
#define __DISCOVERED_SERVICE_H__
#include "UUID.h"
#include "GattAttribute.h"
/**@brief Type for holding information about the service and the characteristics found during
* the discovery process.
*/
class DiscoveredService {
public:
void setup(UUID uuidIn, GattAttribute::Handle_t startHandleIn, GattAttribute::Handle_t endHandleIn) {
uuid = uuidIn;
startHandle = startHandleIn;
endHandle = endHandleIn;
}
void setup(GattAttribute::Handle_t startHandleIn, GattAttribute::Handle_t endHandleIn) {
startHandle = startHandleIn;
endHandle = endHandleIn;
}
void setupLongUUID(UUID::LongUUIDBytes_t longUUID) {
uuid.setupLong(longUUID);
}
public:
const UUID &getUUID(void) const {
return uuid;
}
const GattAttribute::Handle_t& getStartHandle(void) const {
return startHandle;
}
const GattAttribute::Handle_t& getEndHandle(void) const {
return endHandle;
}
public:
DiscoveredService() : uuid(UUID::ShortUUIDBytes_t(0)),
startHandle(GattAttribute::INVALID_HANDLE),
endHandle(GattAttribute::INVALID_HANDLE) {
/* empty */
}
private:
DiscoveredService(const DiscoveredService &);
private:
UUID uuid; /**< UUID of the service. */
GattAttribute::Handle_t startHandle; /**< Service Handle Range. */
GattAttribute::Handle_t endHandle; /**< Service Handle Range. */
};
#endif /*__DISCOVERED_SERVICE_H__*/

886
ble/Gap.h Normal file
View File

@ -0,0 +1,886 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __GAP_H__
#define __GAP_H__
#include "GapAdvertisingData.h"
#include "GapAdvertisingParams.h"
#include "GapScanningParams.h"
#include "GapEvents.h"
#include "CallChain.h"
#include "FunctionPointerWithContext.h"
using namespace mbed;
/* Forward declarations for classes which will only be used for pointers or references in the following. */
class GapAdvertisingParams;
class GapScanningParams;
class GapAdvertisingData;
class Gap {
public:
enum AddressType_t {
ADDR_TYPE_PUBLIC = 0,
ADDR_TYPE_RANDOM_STATIC,
ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE,
ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE
};
typedef enum AddressType_t addr_type_t; /* @Note: deprecated. Use AddressType_t instead. */
static const unsigned ADDR_LEN = 6;
typedef uint8_t Address_t[ADDR_LEN]; /* 48-bit address, LSB format. */
typedef Address_t address_t; /* @Note: deprecated. Use Address_t instead. */
enum TimeoutSource_t {
TIMEOUT_SRC_ADVERTISING = 0x00, /**< Advertising timeout. */
TIMEOUT_SRC_SECURITY_REQUEST = 0x01, /**< Security request timeout. */
TIMEOUT_SRC_SCAN = 0x02, /**< Scanning timeout. */
TIMEOUT_SRC_CONN = 0x03, /**< Connection timeout. */
};
/**
* Enumeration for disconnection reasons. The values for these reasons are
* derived from Nordic's implementation; but the reasons are meant to be
* independent of the transport. If you are returned a reason which is not
* covered by this enumeration, then please refer to the underlying
* transport library.
*/
enum DisconnectionReason_t {
CONNECTION_TIMEOUT = 0x08,
REMOTE_USER_TERMINATED_CONNECTION = 0x13,
REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES = 0x14, /**< Remote Device Terminated Connection due to low resources.*/
REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF = 0x15, /**< Remote Device Terminated Connection due to power off. */
LOCAL_HOST_TERMINATED_CONNECTION = 0x16,
CONN_INTERVAL_UNACCEPTABLE = 0x3B,
};
/* Describes the current state of the device (more than one bit can be set) */
struct GapState_t {
unsigned advertising : 1; /**< peripheral is currently advertising */
unsigned connected : 1; /**< peripheral is connected to a central */
};
typedef uint16_t Handle_t; /* Type for connection handle. */
typedef struct {
uint16_t minConnectionInterval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
uint16_t maxConnectionInterval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
uint16_t slaveLatency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/
uint16_t connectionSupervisionTimeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/
} ConnectionParams_t;
enum Role_t {
PERIPHERAL = 0x1, /**< Peripheral Role. */
CENTRAL = 0x2, /**< Central Role. */
};
struct AdvertisementCallbackParams_t {
Address_t peerAddr;
int8_t rssi;
bool isScanResponse;
GapAdvertisingParams::AdvertisingType_t type;
uint8_t advertisingDataLen;
const uint8_t *advertisingData;
};
typedef FunctionPointerWithContext<const AdvertisementCallbackParams_t *> AdvertisementReportCallback_t;
struct ConnectionCallbackParams_t {
Handle_t handle;
Role_t role;
AddressType_t peerAddrType;
Address_t peerAddr;
AddressType_t ownAddrType;
Address_t ownAddr;
const ConnectionParams_t *connectionParams;
ConnectionCallbackParams_t(Handle_t handleIn,
Role_t roleIn,
AddressType_t peerAddrTypeIn,
const uint8_t *peerAddrIn,
AddressType_t ownAddrTypeIn,
const uint8_t *ownAddrIn,
const ConnectionParams_t *connectionParamsIn) :
handle(handleIn),
role(roleIn),
peerAddrType(peerAddrTypeIn),
peerAddr(),
ownAddrType(ownAddrTypeIn),
ownAddr(),
connectionParams(connectionParamsIn) {
memcpy(peerAddr, peerAddrIn, ADDR_LEN);
memcpy(ownAddr, ownAddrIn, ADDR_LEN);
}
};
static const uint16_t UNIT_1_25_MS = 1250; /**< Number of microseconds in 1.25 milliseconds. */
static const uint16_t UNIT_0_625_MS = 625; /**< Number of microseconds in 0.625 milliseconds. */
static uint16_t MSEC_TO_GAP_DURATION_UNITS(uint32_t durationInMillis) {
return (durationInMillis * 1000) / UNIT_1_25_MS;
}
static uint16_t MSEC_TO_ADVERTISEMENT_DURATION_UNITS(uint32_t durationInMillis) {
return (durationInMillis * 1000) / UNIT_0_625_MS;
}
static uint16_t ADVERTISEMENT_DURATION_UNITS_TO_MS(uint16_t gapUnits) {
return (gapUnits * UNIT_0_625_MS) / 1000;
}
typedef void (*TimeoutEventCallback_t)(TimeoutSource_t source);
typedef void (*ConnectionEventCallback_t)(const ConnectionCallbackParams_t *params);
typedef void (*DisconnectionEventCallback_t)(Handle_t, DisconnectionReason_t);
typedef void (*RadioNotificationEventCallback_t)(bool radio_active); /* gets passed true for ACTIVE; false for INACTIVE. */
/*
* The following functions are meant to be overridden in the platform-specific sub-class.
*/
public:
/**
* Set the BTLE MAC address and type. Please note that the address format is
* LSB (least significant byte first). Please refer to Address_t.
*
* @return BLE_ERROR_NONE on success.
*/
virtual ble_error_t setAddress(AddressType_t type, const Address_t address) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Fetch the BTLE MAC address and type.
*
* @return BLE_ERROR_NONE on success.
*/
virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* @return Minimum Advertising interval in milliseconds.
*/
virtual uint16_t getMinAdvertisingInterval(void) const {
return 0; /* default implementation; override this API if this capability is supported. */
}
/**
* @return Minimum Advertising interval in milliseconds for non-connectible mode.
*/
virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const {
return 0; /* default implementation; override this API if this capability is supported. */
}
/**
* @return Maximum Advertising interval in milliseconds.
*/
virtual uint16_t getMaxAdvertisingInterval(void) const {
return 0xFFFF; /* default implementation; override this API if this capability is supported. */
}
virtual ble_error_t stopAdvertising(void) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Stop scanning. The current scanning parameters remain in effect.
*
* @retval BLE_ERROR_NONE if successfully stopped scanning procedure.
*/
virtual ble_error_t stopScan() {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Create a connection (GAP Link Establishment).
*
* @param peerAddr
* 48-bit address, LSB format.
* @param peerAddrType
* Address type of the peer.
* @param connectionParams
* Connection parameters.
* @param scanParams
* Paramters to be used while scanning for the peer.
* @return BLE_ERROR_NONE if connection establishment procedure is started
* successfully. The connectionCallback (if set) will be invoked upon
* a connection event.
*/
virtual ble_error_t connect(const Address_t peerAddr,
Gap::AddressType_t peerAddrType,
const ConnectionParams_t *connectionParams,
const GapScanningParams *scanParams) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* This call initiates the disconnection procedure, and its completion will
* be communicated to the application with an invocation of the
* disconnectionCallback.
*
* @param reason
* The reason for disconnection to be sent back to the peer.
*/
virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* This call initiates the disconnection procedure, and its completion will
* be communicated to the application with an invocation of the
* disconnectionCallback.
*
* @param reason
* The reason for disconnection to be sent back to the peer.
*
* @note: this version of disconnect() doesn't take a connection handle. It
* will work reliably only for stacks which are limited to a single
* connection. This API should be considered *deprecated* in favour of the
* altertive which takes a connection handle. It will be dropped in the future.
*/
virtual ble_error_t disconnect(DisconnectionReason_t reason) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Get the GAP peripheral preferred connection parameters. These are the
* defaults that the peripheral would like to have in a connection. The
* choice of the connection parameters is eventually up to the central.
*
* @param[out] params
* The structure where the parameters will be stored. Memory
* for this is owned by the caller.
*
* @return BLE_ERROR_NONE if the parameters were successfully filled into
* the given structure pointed to by params.
*/
virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Set the GAP peripheral preferred connection parameters. These are the
* defaults that the peripheral would like to have in a connection. The
* choice of the connection parameters is eventually up to the central.
*
* @param[in] params
* The structure containing the desired parameters.
*/
virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Update connection parameters while in the peripheral role.
* @details In the peripheral role, this will send the corresponding L2CAP request to the connected peer and wait for
* the central to perform the procedure.
* @param[in] handle
* Connection Handle
* @param[in] params
* Pointer to desired connection parameters. If NULL is provided on a peripheral role,
* the parameters in the PPCP characteristic of the GAP service will be used instead.
*/
virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Set the device name characteristic in the GAP service.
* @param[in] deviceName
* The new value for the device-name. This is a UTF-8 encoded, <b>NULL-terminated</b> string.
*/
virtual ble_error_t setDeviceName(const uint8_t *deviceName) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Get the value of the device name characteristic in the GAP service.
* @param[out] deviceName
* Pointer to an empty buffer where the UTF-8 *non NULL-
* terminated* string will be placed. Set this
* value to NULL in order to obtain the deviceName-length
* from the 'length' parameter.
*
* @param[in/out] lengthP
* (on input) Length of the buffer pointed to by deviceName;
* (on output) the complete device name length (without the
* null terminator).
*
* @note If the device name is longer than the size of the supplied buffer,
* length will return the complete device name length, and not the
* number of bytes actually returned in deviceName. The application may
* use this information to retry with a suitable buffer size.
*/
virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Set the appearance characteristic in the GAP service.
* @param[in] appearance
* The new value for the device-appearance.
*/
virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Get the appearance characteristic in the GAP service.
* @param[out] appearance
* The new value for the device-appearance.
*/
virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Set the radio's transmit power.
* @param[in] txPower Radio transmit power in dBm.
*/
virtual ble_error_t setTxPower(int8_t txPower) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Query the underlying stack for permitted arguments for setTxPower().
*
* @param[out] valueArrayPP
* Out parameter to receive the immutable array of Tx values.
* @param[out] countP
* Out parameter to receive the array's size.
*/
virtual void getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) {
*countP = 0; /* default implementation; override this API if this capability is supported. */
}
protected:
/* Override the following in the underlying adaptation layer to provide the functionality of scanning. */
virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/*
* APIs with non-virtual implementations.
*/
public:
/**
* Returns the current GAP state of the device using a bitmask which
* describes whether the device is advertising and/or connected.
*/
GapState_t getState(void) const {
return state;
}
/**
* Set the GAP advertising mode to use for this device.
*/
void setAdvertisingType(GapAdvertisingParams::AdvertisingType_t advType) {
_advParams.setAdvertisingType(advType);
}
/**
* @param[in] interval
* Advertising interval in units of milliseconds. Advertising
* is disabled if interval is 0. If interval is smaller than
* the minimum supported value, then the minimum supported
* value is used instead. This minimum value can be discovered
* using getMinAdvertisingInterval().
*
* This field must be set to 0 if connectionMode is equal
* to ADV_CONNECTABLE_DIRECTED.
*
* @note: Decreasing this value will allow central devices to detect a
* peripheral faster at the expense of more power being used by the radio
* due to the higher data transmit rate.
*
* @note: This API is now *deprecated* and will be dropped in the future.
* You should use the parallel API from Gap directly. A former call to
* ble.setAdvertisingInterval(...) should now be achieved using
* ble.gap().setAdvertisingInterval(...).
*
* @Note: [WARNING] This API previously used 0.625ms as the unit for its
* 'interval' argument. That required an explicit conversion from
* milliseconds using Gap::MSEC_TO_GAP_DURATION_UNITS(). This conversion is
* no longer required as the new units are milliseconds. Any application
* code depending on the old semantics would need to be updated accordingly.
*/
void setAdvertisingInterval(uint16_t interval) {
if (interval == 0) {
stopAdvertising();
} else if (interval < getMinAdvertisingInterval()) {
interval = getMinAdvertisingInterval();
}
_advParams.setInterval(MSEC_TO_ADVERTISEMENT_DURATION_UNITS(interval));
}
/**
* @param[in] timeout
* Advertising timeout (in seconds) between 0x1 and 0x3FFF (1
* and 16383). Use 0 to disable the advertising timeout.
*/
void setAdvertisingTimeout(uint16_t timeout) {
_advParams.setTimeout(timeout);
}
/**
* Start advertising.
*/
ble_error_t startAdvertising(void) {
setAdvertisingData(); /* update the underlying stack */
return startAdvertising(_advParams);
}
/**
* Reset any advertising payload prepared from prior calls to
* accumulateAdvertisingPayload(). This automatically propagates the re-
* initialized adv payload to the underlying stack.
*
* Note: This should be followed by a call to setAdvertisingPayload() or
* startAdvertising() before the update takes effect.
*/
void clearAdvertisingPayload(void) {
_advPayload.clear();
setAdvertisingData();
}
/**
* Accumulate an AD structure in the advertising payload. Please note that
* the payload is limited to 31 bytes. The SCAN_RESPONSE message may be used
* as an additional 31 bytes if the advertising payload proves to be too
* small.
*
* @param[in] flags
* The flags to be added. Please refer to
* GapAdvertisingData::Flags for valid flags. Multiple
* flags may be specified in combination.
*/
ble_error_t accumulateAdvertisingPayload(uint8_t flags) {
ble_error_t rc;
if ((rc = _advPayload.addFlags(flags)) != BLE_ERROR_NONE) {
return rc;
}
return setAdvertisingData();
}
/**
* Accumulate an AD structure in the advertising payload. Please note that
* the payload is limited to 31 bytes. The SCAN_RESPONSE message may be used
* as an additional 31 bytes if the advertising payload proves to be too
* small.
*
* @param app
* The appearance of the peripheral.
*/
ble_error_t accumulateAdvertisingPayload(GapAdvertisingData::Appearance app) {
setAppearance(app);
ble_error_t rc;
if ((rc = _advPayload.addAppearance(app)) != BLE_ERROR_NONE) {
return rc;
}
return setAdvertisingData();
}
/**
* Accumulate an AD structure in the advertising payload. Please note that
* the payload is limited to 31 bytes. The SCAN_RESPONSE message may be used
* as an additional 31 bytes if the advertising payload proves to be too
* small.
*
* @param app
* The max transmit power to be used by the controller. This is
* only a hint.
*/
ble_error_t accumulateAdvertisingPayloadTxPower(int8_t power) {
ble_error_t rc;
if ((rc = _advPayload.addTxPower(power)) != BLE_ERROR_NONE) {
return rc;
}
return setAdvertisingData();
}
/**
* Accumulate a variable length byte-stream as an AD structure in the
* advertising payload. Please note that the payload is limited to 31 bytes.
* The SCAN_RESPONSE message may be used as an additional 31 bytes if the
* advertising payload proves to be too small.
*
* @param type The type which describes the variable length data.
* @param data data bytes.
* @param len length of data.
*/
ble_error_t accumulateAdvertisingPayload(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) {
if (type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
setDeviceName(data);
}
ble_error_t rc;
if ((rc = _advPayload.addData(type, data, len)) != BLE_ERROR_NONE) {
return rc;
}
return setAdvertisingData();
}
/**
* Setup a particular, user-constructed advertisement payload for the
* underlying stack. It would be uncommon for this API to be used directly;
* there are other APIs to build an advertisement payload (see above).
*/
ble_error_t setAdvertisingPayload(const GapAdvertisingData &payload) {
_advPayload = payload;
return setAdvertisingData();
}
/**
* @return Read back advertising data. Useful for storing and
* restoring payload.
*/
const GapAdvertisingData &getAdvertisingPayload(void) const {
return _advPayload;
}
/**
* Accumulate a variable length byte-stream as an AD structure in the
* scanResponse payload.
*
* @param[in] type The type which describes the variable length data.
* @param[in] data data bytes.
* @param[in] len length of data.
*/
ble_error_t accumulateScanResponse(GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) {
ble_error_t rc;
if ((rc = _scanResponse.addData(type, data, len)) != BLE_ERROR_NONE) {
return rc;
}
return setAdvertisingData();
}
/**
* Reset any scan response prepared from prior calls to
* accumulateScanResponse().
*
* Note: This should be followed by a call to setAdvertisingPayload() or
* startAdvertising() before the update takes effect.
*/
void clearScanResponse(void) {
_scanResponse.clear();
setAdvertisingData();
}
/**
* Setup parameters for GAP scanning--i.e. observer mode.
* @param[in] interval
* Scan interval (in milliseconds) [valid values lie between 2.5ms and 10.24s].
* @param[in] window
* Scan Window (in milliseconds) [valid values lie between 2.5ms and 10.24s].
* @param[in] timeout
* Scan timeout (in seconds) between 0x0001 and 0xFFFF, 0x0000 disables timeout.
* @param[in] activeScanning
* Set to True if active-scanning is required. This is used to fetch the
* scan response from a peer if possible.
*
* The scanning window divided by the interval determines the duty cycle for
* scanning. For example, if the interval is 100ms and the window is 10ms,
* then the controller will scan for 10 percent of the time. It is possible
* to have the interval and window set to the same value. In this case,
* scanning is continuous, with a change of scanning frequency once every
* interval.
*
* Once the scanning parameters have been configured, scanning can be
* enabled by using startScan().
*
* @Note: The scan interval and window are recommendations to the BLE stack.
*/
ble_error_t setScanParams(uint16_t interval = GapScanningParams::SCAN_INTERVAL_MAX,
uint16_t window = GapScanningParams::SCAN_WINDOW_MAX,
uint16_t timeout = 0,
bool activeScanning = false) {
ble_error_t rc;
if (((rc = _scanningParams.setInterval(interval)) == BLE_ERROR_NONE) &&
((rc = _scanningParams.setWindow(window)) == BLE_ERROR_NONE) &&
((rc = _scanningParams.setTimeout(timeout)) == BLE_ERROR_NONE)) {
_scanningParams.setActiveScanning(activeScanning);
return BLE_ERROR_NONE;
}
return rc;
}
/**
* Setup the scanInterval parameter for GAP scanning--i.e. observer mode.
* @param[in] interval
* Scan interval (in milliseconds) [valid values lie between 2.5ms and 10.24s].
*
* The scanning window divided by the interval determines the duty cycle for
* scanning. For example, if the interval is 100ms and the window is 10ms,
* then the controller will scan for 10 percent of the time. It is possible
* to have the interval and window set to the same value. In this case,
* scanning is continuous, with a change of scanning frequency once every
* interval.
*
* Once the scanning parameters have been configured, scanning can be
* enabled by using startScan().
*/
ble_error_t setScanInterval(uint16_t interval) {
return _scanningParams.setInterval(interval);
}
/**
* Setup the scanWindow parameter for GAP scanning--i.e. observer mode.
* @param[in] window
* Scan Window (in milliseconds) [valid values lie between 2.5ms and 10.24s].
*
* The scanning window divided by the interval determines the duty cycle for
* scanning. For example, if the interval is 100ms and the window is 10ms,
* then the controller will scan for 10 percent of the time. It is possible
* to have the interval and window set to the same value. In this case,
* scanning is continuous, with a change of scanning frequency once every
* interval.
*
* Once the scanning parameters have been configured, scanning can be
* enabled by using startScan().
*/
ble_error_t setScanWindow(uint16_t window) {
return _scanningParams.setWindow(window);
}
/**
* Setup parameters for GAP scanning--i.e. observer mode.
* @param[in] timeout
* Scan timeout (in seconds) between 0x0001 and 0xFFFF, 0x0000 disables timeout.
*
* Once the scanning parameters have been configured, scanning can be
* enabled by using startScan().
*/
ble_error_t setScanTimeout(uint16_t timeout) {
return _scanningParams.setTimeout(timeout);
}
/**
* Setup parameters for GAP scanning--i.e. observer mode.
* @param[in] activeScanning
* Set to True if active-scanning is required. This is used to fetch the
* scan response from a peer if possible.
*
* Once the scanning parameters have been configured, scanning can be
* enabled by using startScan().
*/
void setActiveScanning(bool activeScanning) {
_scanningParams.setActiveScanning(activeScanning);
}
/**
* Start scanning (Observer Procedure) based on the parameters currently in
* effect.
*
* @param[in] callback
* The application specific callback to be invoked upon
* receiving every advertisement report. This can be passed in
* as NULL, in which case scanning may not be enabled at all.
*/
ble_error_t startScan(void (*callback)(const AdvertisementCallbackParams_t *params)) {
ble_error_t err = BLE_ERROR_NONE;
if (callback) {
if ((err = startRadioScan(_scanningParams)) == BLE_ERROR_NONE) {
onAdvertisementReport.attach(callback);
}
}
return err;
}
/**
* Same as above, but this takes an (object, method) pair for a callback.
*/
template<typename T>
ble_error_t startScan(T *object, void (T::*callbackMember)(const AdvertisementCallbackParams_t *params)) {
ble_error_t err = BLE_ERROR_NONE;
if (object && callbackMember) {
if ((err = startRadioScan(_scanningParams)) == BLE_ERROR_NONE) {
onAdvertisementReport.attach(object, callbackMember);
}
}
return err;
}
private:
ble_error_t setAdvertisingData(void) {
return setAdvertisingData(_advPayload, _scanResponse);
}
private:
virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &) = 0;
virtual ble_error_t startAdvertising(const GapAdvertisingParams &) = 0;
public:
/**
* Accessors to read back currently active advertising params.
*/
GapAdvertisingParams &getAdvertisingParams(void) {
return _advParams;
}
const GapAdvertisingParams &getAdvertisingParams(void) const {
return _advParams;
}
/**
* Setup a particular, user-constructed set of advertisement parameters for
* the underlying stack. It would be uncommon for this API to be used
* directly; there are other APIs to tweak advertisement parameters
* individually.
*/
void setAdvertisingParams(const GapAdvertisingParams &newParams) {
_advParams = newParams;
}
/* Event callback handlers. */
public:
/**
* Setup a callback for timeout events. Refer to TimeoutSource_t for
* possible event types.
*/
void onTimeout(TimeoutEventCallback_t callback) {timeoutCallback = callback;}
/**
* Setup a callback for connection events. Refer to ConnectionEventCallback_t.
*/
void onConnection(ConnectionEventCallback_t callback) {connectionCallback = callback;}
/**
* Set the application callback for disconnection events.
* @param callback
* Pointer to the unique callback.
*/
void onDisconnection(DisconnectionEventCallback_t callback) {disconnectionCallback = callback;}
/**
* Append to a chain of callbacks to be invoked upon disconnection; these
* callbacks receive no context and are therefore different from the
* disconnectionCallback callback.
* @param callback
* function pointer to be invoked upon disconnection; receives no context.
*/
template<typename T>
void addToDisconnectionCallChain(T *tptr, void (T::*mptr)(void)) {disconnectionCallChain.add(tptr, mptr);}
/**
* Set the application callback for radio-notification events.
*
* Radio Notification is a feature that enables ACTIVE and INACTIVE
* (nACTIVE) signals from the stack that notify the application when the
* radio is in use. The signal is sent using software interrupt.
*
* The ACTIVE signal is sent before the Radio Event starts. The nACTIVE
* signal is sent at the end of the Radio Event. These signals can be used
* by the application programmer to synchronize application logic with radio
* activity. For example, the ACTIVE signal can be used to shut off external
* devices to manage peak current drawn during periods when the radio is on,
* or to trigger sensor data collection for transmission in the Radio Event.
*
* @param callback
* The application handler to be invoked in response to a radio
* ACTIVE/INACTIVE event.
*/
virtual void onRadioNotification(RadioNotificationEventCallback_t callback) {radioNotificationCallback = callback;}
protected:
Gap() :
_advParams(),
_advPayload(),
_scanningParams(),
_scanResponse(),
state(),
timeoutCallback(NULL),
connectionCallback(NULL),
disconnectionCallback(NULL),
radioNotificationCallback(),
onAdvertisementReport(),
disconnectionCallChain() {
_advPayload.clear();
_scanResponse.clear();
}
/* Entry points for the underlying stack to report events back to the user. */
public:
void processConnectionEvent(Handle_t handle,
Role_t role,
AddressType_t peerAddrType,
const Address_t peerAddr,
AddressType_t ownAddrType,
const Address_t ownAddr,
const ConnectionParams_t *connectionParams) {
state.connected = 1;
if (connectionCallback) {
ConnectionCallbackParams_t callbackParams(handle, role, peerAddrType, peerAddr, ownAddrType, ownAddr, connectionParams);
connectionCallback(&callbackParams);
}
}
void processDisconnectionEvent(Handle_t handle, DisconnectionReason_t reason) {
state.connected = 0;
if (disconnectionCallback) {
disconnectionCallback(handle, reason);
}
disconnectionCallChain.call();
}
void processAdvertisementReport(const Address_t peerAddr,
int8_t rssi,
bool isScanResponse,
GapAdvertisingParams::AdvertisingType_t type,
uint8_t advertisingDataLen,
const uint8_t *advertisingData) {
AdvertisementCallbackParams_t params;
memcpy(params.peerAddr, peerAddr, ADDR_LEN);
params.rssi = rssi;
params.isScanResponse = isScanResponse;
params.type = type;
params.advertisingDataLen = advertisingDataLen;
params.advertisingData = advertisingData;
onAdvertisementReport.call(&params);
}
void processTimeoutEvent(TimeoutSource_t source) {
if (timeoutCallback) {
timeoutCallback(source);
}
}
protected:
GapAdvertisingParams _advParams;
GapAdvertisingData _advPayload;
GapScanningParams _scanningParams;
GapAdvertisingData _scanResponse;
GapState_t state;
protected:
TimeoutEventCallback_t timeoutCallback;
ConnectionEventCallback_t connectionCallback;
DisconnectionEventCallback_t disconnectionCallback;
RadioNotificationEventCallback_t radioNotificationCallback;
AdvertisementReportCallback_t onAdvertisementReport;
CallChain disconnectionCallChain;
private:
/* disallow copy and assignment */
Gap(const Gap &);
Gap& operator=(const Gap &);
};
#endif // ifndef __GAP_H__

View File

@ -17,6 +17,7 @@
#ifndef __GAP_ADVERTISING_DATA_H__
#define __GAP_ADVERTISING_DATA_H__
#include <stdint.h>
#include <string.h>
#include "blecommon.h"

View File

@ -39,30 +39,22 @@ public:
static const unsigned GAP_ADV_PARAMS_INTERVAL_MAX = 0x4000;
static const unsigned GAP_ADV_PARAMS_TIMEOUT_MAX = 0x3FFF;
/**************************************************************************/
/*!
\brief
Encapsulates the peripheral advertising modes, which determine how
the device appears to other central devices in hearing range
\par
See the following for more information on advertising types:
\li \c Bluetooth Core Specification 4.0 (Vol. 6), Part B, Section 2.3.1
\li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 9.3
*/
/**************************************************************************/
enum AdvertisingType {
* Encapsulates the peripheral advertising modes, which determine how
* the device appears to other central devices in hearing range
*/
enum AdvertisingType_t {
ADV_CONNECTABLE_UNDIRECTED, /**< Vol 3, Part C, Section 9.3.4 and Vol 6, Part B, Section 2.3.1.1 */
ADV_CONNECTABLE_DIRECTED, /**< Vol 3, Part C, Section 9.3.3 and Vol 6, Part B, Section 2.3.1.2 */
ADV_SCANNABLE_UNDIRECTED, /**< Include support for Scan Response payloads, see Vol 6, Part B, Section 2.3.1.4 */
ADV_NON_CONNECTABLE_UNDIRECTED /**< Vol 3, Part C, Section 9.3.2 and Vol 6, Part B, Section 2.3.1.3 */
};
typedef enum AdvertisingType_t AdvertisingType; /* deprecated type alias. */
public:
GapAdvertisingParams(AdvertisingType advType = GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED,
uint16_t interval = GAP_ADV_PARAMS_INTERVAL_MIN_NONCON,
uint16_t timeout = 0) : _advType(advType), _interval(interval), _timeout(timeout) {
GapAdvertisingParams(AdvertisingType_t advType = ADV_CONNECTABLE_UNDIRECTED,
uint16_t interval = GAP_ADV_PARAMS_INTERVAL_MIN_NONCON,
uint16_t timeout = 0) : _advType(advType), _interval(interval), _timeout(timeout) {
/* Interval checks */
if (_advType == ADV_CONNECTABLE_DIRECTED) {
/* Interval must be 0 in directed connectable mode */
@ -94,18 +86,18 @@ public:
}
}
AdvertisingType getAdvertisingType(void) const {return _advType; }
uint16_t getInterval(void) const {return _interval;}
uint16_t getTimeout(void) const {return _timeout; }
AdvertisingType_t getAdvertisingType(void) const {return _advType; }
uint16_t getInterval(void) const {return _interval;}
uint16_t getTimeout(void) const {return _timeout; }
void setAdvertisingType(AdvertisingType newAdvType) {_advType = newAdvType; }
void setInterval(uint16_t newInterval) {_interval = newInterval;}
void setTimeout(uint16_t newTimeout) {_timeout = newTimeout; }
void setAdvertisingType(AdvertisingType_t newAdvType) {_advType = newAdvType; }
void setInterval(uint16_t newInterval) {_interval = newInterval;}
void setTimeout(uint16_t newTimeout) {_timeout = newTimeout; }
private:
AdvertisingType _advType;
uint16_t _interval;
uint16_t _timeout;
AdvertisingType_t _advType;
uint16_t _interval;
uint16_t _timeout;
};
#endif // ifndef __GAP_ADVERTISING_PARAMS_H__

View File

@ -17,8 +17,6 @@
#ifndef __GAP_SCANNING_PARAMS_H__
#define __GAP_SCANNING_PARAMS_H__
#include "Gap.h"
class GapScanningParams {
public:
static const unsigned SCAN_INTERVAL_MIN = 0x0004; /**< Minimum Scan interval in 625 us units, i.e. 2.5 ms. */
@ -29,58 +27,20 @@ public:
static const unsigned SCAN_TIMEOUT_MAX = 0xFFFF; /**< Maximum Scan timeout in seconds. */
public:
GapScanningParams(uint16_t interval = SCAN_INTERVAL_MAX,
uint16_t window = SCAN_WINDOW_MAX,
uint16_t timeout = 0,
bool activeScanning = false) : _interval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(interval)),
_window(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(window)),
_timeout(timeout),
_activeScanning(activeScanning) {
/* stay within limits */
if (_interval < SCAN_INTERVAL_MIN) {
_interval = SCAN_INTERVAL_MIN;
}
if (_interval > SCAN_INTERVAL_MAX) {
_interval = SCAN_INTERVAL_MAX;
}
if (_window < SCAN_WINDOW_MIN) {
_window = SCAN_WINDOW_MIN;
}
if (_window > SCAN_WINDOW_MAX) {
_window = SCAN_WINDOW_MAX;
}
}
GapScanningParams(uint16_t interval = SCAN_INTERVAL_MAX,
uint16_t window = SCAN_WINDOW_MAX,
uint16_t timeout = 0,
bool activeScanning = false);
ble_error_t setInterval(uint16_t newIntervalInMS) {
uint16_t newInterval = Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(newIntervalInMS);
if ((newInterval >= SCAN_INTERVAL_MIN) && (newInterval < SCAN_INTERVAL_MAX)) {
_interval = newInterval;
return BLE_ERROR_NONE;
}
ble_error_t setInterval(uint16_t newIntervalInMS);
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
ble_error_t setWindow(uint16_t newWindowInMS);
ble_error_t setWindow(uint16_t newWindowInMS) {
uint16_t newWindow = Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(newWindowInMS);
if ((newWindow >= SCAN_WINDOW_MIN) && (newWindow < SCAN_WINDOW_MAX)) {
_window = newWindow;
return BLE_ERROR_NONE;
}
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
ble_error_t setTimeout(uint16_t newTimeout) {
_timeout = newTimeout;
return BLE_ERROR_NONE;
}
void setActiveScanning(bool activeScanning) {
_activeScanning = activeScanning;
}
ble_error_t setTimeout(uint16_t newTimeout);
void setActiveScanning(bool activeScanning);
public:
/* @Note: The following return durations in units of 0.625 ms */
uint16_t getInterval(void) const {return _interval;}
uint16_t getWindow(void) const {return _window; }

View File

@ -17,6 +17,8 @@
#ifndef __GATT_ATTRIBUTE_H__
#define __GATT_ATTRIBUTE_H__
#include "UUID.h"
class GattAttribute {
public:
typedef uint16_t Handle_t;

View File

@ -14,37 +14,35 @@
* limitations under the License.
*/
#ifndef __GATT_CHARACTERISTIC_CALLBACK_PARAMS_H__
#define __GATT_CHARACTERISTIC_CALLBACK_PARAMS_H__
#ifndef __GATT_CALLBACK_PARAM_TYPES_H__
#define __GATT_CALLBACK_PARAM_TYPES_H__
struct GattCharacteristicWriteCBParams {
GattAttribute::Handle_t charHandle;
enum Type {
GATTS_CHAR_OP_INVALID = 0x00, /**< Invalid Operation. */
GATTS_CHAR_OP_WRITE_REQ = 0x01, /**< Write Request. */
GATTS_CHAR_OP_WRITE_CMD = 0x02, /**< Write Command. */
GATTS_CHAR_OP_SIGN_WRITE_CMD = 0x03, /**< Signed Write Command. */
GATTS_CHAR_OP_PREP_WRITE_REQ = 0x04, /**< Prepare Write Request. */
GATTS_CHAR_OP_EXEC_WRITE_REQ_CANCEL = 0x05, /**< Execute Write Request: Cancel all prepared writes. */
GATTS_CHAR_OP_EXEC_WRITE_REQ_NOW = 0x06, /**< Execute Write Request: Immediately execute all prepared writes. */
} op; /**< Type of write operation, */
uint16_t offset; /**< Offset for the write operation. */
uint16_t len; /**< Length of the incoming data. */
const uint8_t *data; /**< Incoming data, variable length. */
struct GattWriteCallbackParams {
enum WriteOp_t {
OP_INVALID = 0x00, /**< Invalid Operation. */
OP_WRITE_REQ = 0x01, /**< Write Request. */
OP_WRITE_CMD = 0x02, /**< Write Command. */
OP_SIGN_WRITE_CMD = 0x03, /**< Signed Write Command. */
OP_PREP_WRITE_REQ = 0x04, /**< Prepare Write Request. */
OP_EXEC_WRITE_REQ_CANCEL = 0x05, /**< Execute Write Request: Cancel all prepared writes. */
OP_EXEC_WRITE_REQ_NOW = 0x06, /**< Execute Write Request: Immediately execute all prepared writes. */
};
GattAttribute::Handle_t handle;
WriteOp_t writeOp; /**< Type of write operation, */
uint16_t offset; /**< Offset for the write operation. */
uint16_t len;
const uint8_t *data; /* @note: data might not persist beyond the callback; make a local copy if needed. */
};
struct GattCharacteristicReadCBParams {
GattAttribute::Handle_t charHandle;
enum Type {
GATTS_CHAR_OP_INVALID = 0x00, /**< Invalid Operation. */
GATTS_CHAR_OP_READ_REQ = 0x0A, /**< Read Request. */
} op; /**< Type of write operation, */
uint16_t offset; /**< Offset for the read operation. */
uint16_t *len; /**< Length of the outgoing data. */
uint8_t *data; /**< Outgoing data, variable length. */
struct GattReadCallbackParams {
GattAttribute::Handle_t handle;
uint16_t offset; /**< Offset for the read operation. */
uint16_t len;
const uint8_t *data; /* @note: data might not persist beyond the callback; make a local copy if needed. */
};
enum GattCharacteristicAuthCBReply_t {
enum GattAuthCallbackReply_t {
AUTH_CALLBACK_REPLY_SUCCESS = 0x00, /**< Success. */
AUTH_CALLBACK_REPLY_ATTERR_INVALID_HANDLE = 0x0101, /**< ATT Error: Invalid Attribute Handle. */
AUTH_CALLBACK_REPLY_ATTERR_READ_NOT_PERMITTED = 0x0102, /**< ATT Error: Read not permitted. */
@ -59,22 +57,22 @@ enum GattCharacteristicAuthCBReply_t {
AUTH_CALLBACK_REPLY_ATTERR_INSUF_RESOURCES = 0x0111, /**< ATT Error: Encrypted link required. */
};
struct GattCharacteristicWriteAuthCBParams {
GattAttribute::Handle_t charHandle;
struct GattWriteAuthCallbackParams {
GattAttribute::Handle_t handle;
uint16_t offset; /**< Offset for the write operation. */
uint16_t len; /**< Length of the incoming data. */
const uint8_t *data; /**< Incoming data, variable length. */
GattCharacteristicAuthCBReply_t authorizationReply; /* This is the out parameter which needs to be set to true by the callback if the
* request is to proceed; false otherwise. */
GattAuthCallbackReply_t authorizationReply; /* This is the out parameter which needs to be set to true by the callback if the
* request is to proceed; false otherwise. */
};
struct GattCharacteristicReadAuthCBParams {
GattAttribute::Handle_t charHandle;
struct GattReadAuthCallbackParams {
GattAttribute::Handle_t handle;
uint16_t offset; /**< Offset for the read operation. */
uint16_t len; /**< Optional: new length of the outgoing data. */
uint8_t *data; /**< Optional: new outgoing data. Leave at NULL if data is unchanged. */
GattCharacteristicAuthCBReply_t authorizationReply; /* This is the out parameter which needs to be set to true by the callback if the
* request is to proceed; false otherwise. */
GattAuthCallbackReply_t authorizationReply; /* This is the out parameter which needs to be set to true by the callback if the
* request is to proceed; false otherwise. */
};
#endif /*__GATT_CHARACTERISTIC_CALLBACK_PARAMS_H__*/
#endif /*__GATT_CALLBACK_PARAM_TYPES_H__*/

View File

@ -18,8 +18,9 @@
#define __GATT_CHARACTERISTIC_H__
#include "Gap.h"
#include "SecurityManager.h"
#include "GattAttribute.h"
#include "GattCharacteristicCallbackParams.h"
#include "GattCallbackParamTypes.h"
#include "FunctionPointerWithContext.h"
class GattCharacteristic {
@ -331,7 +332,7 @@ public:
unsigned numDescriptors = 0) :
_valueAttribute(uuid, valuePtr, initialLen, maxLen),
_properties(props),
_requiredSecurity(Gap::SECURITY_MODE_ENCRYPTION_OPEN_LINK),
_requiredSecurity(SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK),
_descriptors(descriptors),
_descriptorCount(numDescriptors),
enabledReadAuthorization(false),
@ -347,7 +348,7 @@ public:
*
* @param securityMode Can be one of encryption or signing, with or without protection for MITM (man in the middle attacks).
*/
void requireSecurity(Gap::SecurityMode_t securityMode) {
void requireSecurity(SecurityManager::SecurityMode_t securityMode) {
_requiredSecurity = securityMode;
}
@ -355,21 +356,21 @@ public:
/**
* Authorization.
*/
void setWriteAuthorizationCallback(void (*callback)(GattCharacteristicWriteAuthCBParams *)) {
void setWriteAuthorizationCallback(void (*callback)(GattWriteAuthCallbackParams *)) {
writeAuthorizationCallback.attach(callback);
enabledWriteAuthorization = true;
}
template <typename T>
void setWriteAuthorizationCallback(T *object, void (T::*member)(GattCharacteristicWriteAuthCBParams *)) {
void setWriteAuthorizationCallback(T *object, void (T::*member)(GattWriteAuthCallbackParams *)) {
writeAuthorizationCallback.attach(object, member);
enabledWriteAuthorization = true;
}
void setReadAuthorizationCallback(void (*callback)(GattCharacteristicReadAuthCBParams *)) {
void setReadAuthorizationCallback(void (*callback)(GattReadAuthCallbackParams *)) {
readAuthorizationCallback.attach(callback);
enabledReadAuthorization = true;
}
template <typename T>
void setReadAuthorizationCallback(T *object, void (T::*member)(GattCharacteristicReadAuthCBParams *)) {
void setReadAuthorizationCallback(T *object, void (T::*member)(GattReadAuthCallbackParams *)) {
readAuthorizationCallback.attach(object, member);
enabledReadAuthorization = true;
}
@ -380,7 +381,7 @@ public:
* @param params to capture the context of the write-auth request; and also contains an out-parameter for reply.
* @return true if the write is authorized to proceed.
*/
GattCharacteristicAuthCBReply_t authorizeWrite(GattCharacteristicWriteAuthCBParams *params) {
GattAuthCallbackReply_t authorizeWrite(GattWriteAuthCallbackParams *params) {
if (!isWriteAuthorizationEnabled()) {
return AUTH_CALLBACK_REPLY_SUCCESS;
}
@ -406,7 +407,7 @@ public:
*
* @return true if the read is authorized to proceed.
*/
GattCharacteristicAuthCBReply_t authorizeRead(GattCharacteristicReadAuthCBParams *params) {
GattAuthCallbackReply_t authorizeRead(GattReadAuthCallbackParams *params) {
if (!isReadAuthorizationEnabled()) {
return AUTH_CALLBACK_REPLY_SUCCESS;
}
@ -422,7 +423,7 @@ public:
const GattAttribute& getValueAttribute() const {return _valueAttribute; }
GattAttribute::Handle_t getValueHandle(void) const {return getValueAttribute().getHandle();}
uint8_t getProperties(void) const {return _properties; }
Gap::SecurityMode_t getRequiredSecurity() const {return _requiredSecurity; }
SecurityManager::SecurityMode_t getRequiredSecurity() const {return _requiredSecurity; }
uint8_t getDescriptorCount(void) const {return _descriptorCount; }
bool isReadAuthorizationEnabled() const {return enabledReadAuthorization; }
bool isWriteAuthorizationEnabled() const {return enabledWriteAuthorization; }
@ -436,16 +437,16 @@ public:
}
private:
GattAttribute _valueAttribute;
uint8_t _properties;
Gap::SecurityMode_t _requiredSecurity;
GattAttribute **_descriptors;
uint8_t _descriptorCount;
GattAttribute _valueAttribute;
uint8_t _properties;
SecurityManager::SecurityMode_t _requiredSecurity;
GattAttribute **_descriptors;
uint8_t _descriptorCount;
bool enabledReadAuthorization;
bool enabledWriteAuthorization;
FunctionPointerWithContext<GattCharacteristicReadAuthCBParams *> readAuthorizationCallback;
FunctionPointerWithContext<GattCharacteristicWriteAuthCBParams *> writeAuthorizationCallback;
FunctionPointerWithContext<GattReadAuthCallbackParams *> readAuthorizationCallback;
FunctionPointerWithContext<GattWriteAuthCallbackParams *> writeAuthorizationCallback;
private:
/* disallow copy and assignment */

229
ble/GattClient.h Normal file
View File

@ -0,0 +1,229 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __GATT_CLIENT_H__
#define __GATT_CLIENT_H__
#include "Gap.h"
#include "GattAttribute.h"
#include "ServiceDiscovery.h"
#include "GattCallbackParamTypes.h"
class GattClient {
public:
typedef void (*ReadCallback_t)(const GattReadCallbackParams *params);
enum WriteOp_t {
GATT_OP_WRITE_REQ = 0x01, /**< Write Request. */
GATT_OP_WRITE_CMD = 0x02, /**< Write Command. */
};
typedef void (*WriteCallback_t)(const GattWriteCallbackParams *params);
/*
* The following functions are meant to be overridden in the platform-specific sub-class.
*/
public:
/**
* Launch service discovery. Once launched, service discovery will remain
* active with callbacks being issued back into the application for matching
* services/characteristics. isServiceDiscoveryActive() can be used to
* determine status; and a termination callback (if setup) will be invoked
* at the end. Service discovery can be terminated prematurely if needed
* using terminateServiceDiscovery().
*
* @param connectionHandle
* Handle for the connection with the peer.
* @param sc
* This is the application callback for matching service. Taken as
* NULL by default. Note: service discovery may still be active
* when this callback is issued; calling asynchronous BLE-stack
* APIs from within this application callback might cause the
* stack to abort service discovery. If this becomes an issue, it
* may be better to make local copy of the discoveredService and
* wait for service discovery to terminate before operating on the
* service.
* @param cc
* This is the application callback for matching characteristic.
* Taken as NULL by default. Note: service discovery may still be
* active when this callback is issued; calling asynchronous
* BLE-stack APIs from within this application callback might cause
* the stack to abort service discovery. If this becomes an issue,
* it may be better to make local copy of the discoveredCharacteristic
* and wait for service discovery to terminate before operating on the
* characteristic.
* @param matchingServiceUUID
* UUID based filter for specifying a service in which the application is
* interested. By default it is set as the wildcard UUID_UNKNOWN,
* in which case it matches all services. If characteristic-UUID
* filter (below) is set to the wildcard value, then a service
* callback will be invoked for the matching service (or for every
* service if the service filter is a wildcard).
* @param matchingCharacteristicUUIDIn
* UUID based filter for specifying characteristic in which the application
* is interested. By default it is set as the wildcard UUID_UKNOWN
* to match against any characteristic. If both service-UUID
* filter and characteristic-UUID filter are used with non- wildcard
* values, then only a single characteristic callback is
* invoked for the matching characteristic.
*
* @note Using wildcard values for both service-UUID and characteristic-
* UUID will result in complete service discovery--callbacks being
* called for every service and characteristic.
*
* @note Providing NULL for the characteristic callback will result in
* characteristic discovery being skipped for each matching
* service. This allows for an inexpensive method to discover only
* services.
*
* @return
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
*/
virtual ble_error_t launchServiceDiscovery(Gap::Handle_t connectionHandle,
ServiceDiscovery::ServiceCallback_t sc = NULL,
ServiceDiscovery::CharacteristicCallback_t cc = NULL,
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN),
const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Launch service discovery for services. Once launched, service discovery will remain
* active with service-callbacks being issued back into the application for matching
* services. isServiceDiscoveryActive() can be used to
* determine status; and a termination callback (if setup) will be invoked
* at the end. Service discovery can be terminated prematurely if needed
* using terminateServiceDiscovery().
*
* @param connectionHandle
* Handle for the connection with the peer.
* @param sc
* This is the application callback for matching service. Note: service discovery may still be active
* when this callback is issued; calling asynchronous BLE-stack
* APIs from within this application callback might cause the
* stack to abort service discovery. If this becomes an issue, it
* may be better to make local copy of the discoveredService and
* wait for service discovery to terminate before operating on the
* service.
* @param matchingServiceUUID
* UUID based filter for specifying a service in which the application is
* interested. By default it is set as the wildcard UUID_UNKNOWN,
* in which case it matches all services.
*
* @return
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
*/
virtual ble_error_t discoverServices(Gap::Handle_t connectionHandle,
ServiceDiscovery::ServiceCallback_t callback,
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Launch service discovery for services. Once launched, service discovery will remain
* active with service-callbacks being issued back into the application for matching
* services. isServiceDiscoveryActive() can be used to
* determine status; and a termination callback (if setup) will be invoked
* at the end. Service discovery can be terminated prematurely if needed
* using terminateServiceDiscovery().
*
* @param connectionHandle
* Handle for the connection with the peer.
* @param sc
* This is the application callback for matching service. Note: service discovery may still be active
* when this callback is issued; calling asynchronous BLE-stack
* APIs from within this application callback might cause the
* stack to abort service discovery. If this becomes an issue, it
* may be better to make local copy of the discoveredService and
* wait for service discovery to terminate before operating on the
* service.
* @param startHandle, endHandle
* Handle range within which to limit the search
*
* @return
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
*/
virtual ble_error_t discoverServices(Gap::Handle_t connectionHandle,
ServiceDiscovery::ServiceCallback_t callback,
GattAttribute::Handle_t startHandle,
GattAttribute::Handle_t endHandle) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Is service-discovery currently active?
*/
virtual bool isServiceDiscoveryActive(void) const {
return false; /* default implementation; override this API if this capability is supported. */
}
/**
* Terminate an ongoing service-discovery. This should result in an
* invocation of the TerminationCallback if service-discovery is active.
*/
virtual void terminateServiceDiscovery(void) {
/* default implementation; override this API if this capability is supported. */
}
/* Initiate a Gatt Client read procedure by attribute-handle. */
virtual ble_error_t read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Initiate a GATT Client write procedure.
*
* @param[in] cmd
* Command can be either a write-request (which generates a
* matching response from the peripheral), or a write-command,
* which doesn't require the connected peer to respond.
* @param[in] connHandle
* Connection handle.
* @param[in] attributeHandle
* handle for the target attribtue on the remote GATT server.
* @param[in] length
* length of the new value.
* @param[in] value
* new value being written.
*/
virtual ble_error_t write(GattClient::WriteOp_t cmd,
Gap::Handle_t connHandle,
GattAttribute::Handle_t attributeHandle,
size_t length,
const uint8_t *value) const {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Setup callback for when serviceDiscovery terminates.
*/
virtual void onServiceDiscoveryTermination(ServiceDiscovery::TerminationCallback_t callback) {
/* default implementation; override this API if this capability is supported. */
}
protected:
GattClient() {
/* empty */
}
private:
/* disallow copy and assignment */
GattClient(const GattClient &);
GattClient& operator=(const GattClient &);
};
#endif // ifndef __GATT_CLIENT_H__

316
ble/GattServer.h Normal file
View File

@ -0,0 +1,316 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __GATT_SERVER_H__
#define __GATT_SERVER_H__
#include "Gap.h"
#include "GattService.h"
#include "GattAttribute.h"
#include "GattServerEvents.h"
#include "GattCallbackParamTypes.h"
#include "CallChainOfFunctionPointersWithContext.h"
class GattServer {
public:
/* Event callback handlers. */
typedef void (*EventCallback_t)(GattAttribute::Handle_t attributeHandle);
typedef void (*ServerEventCallback_t)(void); /**< independent of any particular attribute */
protected:
GattServer() :
serviceCount(0),
characteristicCount(0),
dataSentCallChain(),
dataWrittenCallChain(),
dataReadCallChain(),
updatesEnabledCallback(NULL),
updatesDisabledCallback(NULL),
confirmationReceivedCallback(NULL) {
/* empty */
}
/*
* The following functions are meant to be overridden in the platform-specific sub-class.
*/
public:
/**
* Add a service declaration to the local server ATT table. Also add the
* characteristics contained within.
*/
virtual ble_error_t addService(GattService &) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Read the value of a characteristic from the local GattServer
* @param[in] attributeHandle
* Attribute handle for the value attribute of the characteristic.
* @param[out] buffer
* A buffer to hold the value being read.
* @param[in/out] lengthP
* Length of the buffer being supplied. If the attribute
* value is longer than the size of the supplied buffer,
* this variable will hold upon return the total attribute value length
* (excluding offset). The application may use this
* information to allocate a suitable buffer size.
*
* @return BLE_ERROR_NONE if a value was read successfully into the buffer.
*/
virtual ble_error_t read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Read the value of a characteristic from the local GattServer
* @param[in] connectionHandle
* Connection Handle.
* @param[in] attributeHandle
* Attribute handle for the value attribute of the characteristic.
* @param[out] buffer
* A buffer to hold the value being read.
* @param[in/out] lengthP
* Length of the buffer being supplied. If the attribute
* value is longer than the size of the supplied buffer,
* this variable will hold upon return the total attribute value length
* (excluding offset). The application may use this
* information to allocate a suitable buffer size.
*
* @return BLE_ERROR_NONE if a value was read successfully into the buffer.
*
* @note This API is a version of above with an additional connection handle
* parameter to allow fetches for connection-specific multivalued
* attribtues (such as the CCCDs).
*/
virtual ble_error_t read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t *buffer, uint16_t *lengthP) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Update the value of a characteristic on the local GattServer.
*
* @param[in] attributeHandle
* Handle for the value attribute of the Characteristic.
* @param[in] value
* A pointer to a buffer holding the new value
* @param[in] size
* Size of the new value (in bytes).
* @param[in] localOnly
* Should this update be kept on the local
* GattServer regardless of the state of the
* notify/indicate flag in the CCCD for this
* Characteristic? If set to true, no notification
* or indication is generated.
*
* @return BLE_ERROR_NONE if we have successfully set the value of the attribute.
*/
virtual ble_error_t write(GattAttribute::Handle_t, const uint8_t *, uint16_t, bool localOnly = false) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* Update the value of a characteristic on the local GattServer. A version
* of the same as above with connection handle parameter to allow updates
* for connection-specific multivalued attribtues (such as the CCCDs).
*
* @param[in] connectionHandle
* Connection Handle.
* @param[in] attributeHandle
* Handle for the value attribute of the Characteristic.
* @param[in] value
* A pointer to a buffer holding the new value
* @param[in] size
* Size of the new value (in bytes).
* @param[in] localOnly
* Should this update be kept on the local
* GattServer regardless of the state of the
* notify/indicate flag in the CCCD for this
* Characteristic? If set to true, no notification
* or indication is generated.
*
* @return BLE_ERROR_NONE if we have successfully set the value of the attribute.
*/
virtual ble_error_t write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t, const uint8_t *, uint16_t, bool localOnly = false) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this API if this capability is supported. */
}
/**
* A virtual function to allow underlying stacks to indicate if they support
* onDataRead(). It should be overridden to return true as applicable.
*/
virtual bool isOnDataReadAvailable() const {
return false; /* default implementation; override this API if this capability is supported. */
}
/*
* APIs with non-virtual implementations.
*/
public:
/**
* Add a callback for the GATT event DATA_SENT (which is triggered when
* updates are sent out by GATT in the form of notifications).
*
* @Note: it is possible to chain together multiple onDataSent callbacks
* (potentially from different modules of an application) to receive updates
* to characteristics.
*
* @Note: it is also possible to setup a callback into a member function of
* some object.
*/
void onDataSent(void (*callback)(unsigned count)) {dataSentCallChain.add(callback);}
template <typename T>
void onDataSent(T *objPtr, void (T::*memberPtr)(unsigned count)) {
dataSentCallChain.add(objPtr, memberPtr);
}
/**
* Setup a callback for when an attribute has its value updated by or at the
* connected peer. For a peripheral, this callback triggered when the local
* GATT server has an attribute updated by a write command from the peer.
* For a Central, this callback is triggered when a response is received for
* a write request.
*
* @Note: it is possible to chain together multiple onDataWritten callbacks
* (potentially from different modules of an application) to receive updates
* to characteristics. Many services, such as DFU and UART add their own
* onDataWritten callbacks behind the scenes to trap interesting events.
*
* @Note: it is also possible to setup a callback into a member function of
* some object.
*/
void onDataWritten(void (*callback)(const GattWriteCallbackParams *eventDataP)) {dataWrittenCallChain.add(callback);}
template <typename T>
void onDataWritten(T *objPtr, void (T::*memberPtr)(const GattWriteCallbackParams *context)) {
dataWrittenCallChain.add(objPtr, memberPtr);
}
/**
* Setup a callback to be invoked on the peripheral when an attribute is
* being read by a remote client.
*
* @Note: this functionality may not be available on all underlying stacks.
* You could use GattCharacteristic::setReadAuthorizationCallback() as an
* alternative.
*
* @Note: it is possible to chain together multiple onDataRead callbacks
* (potentially from different modules of an application) to receive updates
* to characteristics. Services may add their own onDataRead callbacks
* behind the scenes to trap interesting events.
*
* @Note: it is also possible to setup a callback into a member function of
* some object.
*
* @return BLE_ERROR_NOT_IMPLEMENTED if this functionality isn't available;
* else BLE_ERROR_NONE.
*/
ble_error_t onDataRead(void (*callback)(const GattReadCallbackParams *eventDataP)) {
if (!isOnDataReadAvailable()) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
dataReadCallChain.add(callback);
return BLE_ERROR_NONE;
}
template <typename T>
ble_error_t onDataRead(T *objPtr, void (T::*memberPtr)(const GattReadCallbackParams *context)) {
if (!isOnDataReadAvailable()) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
dataReadCallChain.add(objPtr, memberPtr);
return BLE_ERROR_NONE;
}
/**
* Setup a callback for when notifications/indications are enabled for a
* characteristic on the local GattServer.
*/
void onUpdatesEnabled(EventCallback_t callback) {updatesEnabledCallback = callback;}
/**
* Setup a callback for when notifications/indications are disabled for a
* characteristic on the local GattServer.
*/
void onUpdatesDisabled(EventCallback_t callback) {updatesDisabledCallback = callback;}
/**
* Setup a callback for when the GATT server receives a response for an
* indication event sent previously.
*/
void onConfirmationReceived(EventCallback_t callback) {confirmationReceivedCallback = callback;}
/* Entry points for the underlying stack to report events back to the user. */
protected:
void handleDataWrittenEvent(const GattWriteCallbackParams *params) {
if (dataWrittenCallChain.hasCallbacksAttached()) {
dataWrittenCallChain.call(params);
}
}
void handleDataReadEvent(const GattReadCallbackParams *params) {
if (dataReadCallChain.hasCallbacksAttached()) {
dataReadCallChain.call(params);
}
}
void handleEvent(GattServerEvents::gattEvent_e type, GattAttribute::Handle_t charHandle) {
switch (type) {
case GattServerEvents::GATT_EVENT_UPDATES_ENABLED:
if (updatesEnabledCallback) {
updatesEnabledCallback(charHandle);
}
break;
case GattServerEvents::GATT_EVENT_UPDATES_DISABLED:
if (updatesDisabledCallback) {
updatesDisabledCallback(charHandle);
}
break;
case GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED:
if (confirmationReceivedCallback) {
confirmationReceivedCallback(charHandle);
}
break;
default:
break;
}
}
void handleDataSentEvent(unsigned count) {
if (dataSentCallChain.hasCallbacksAttached()) {
dataSentCallChain.call(count);
}
}
protected:
uint8_t serviceCount;
uint8_t characteristicCount;
private:
CallChainOfFunctionPointersWithContext<unsigned> dataSentCallChain;
CallChainOfFunctionPointersWithContext<const GattWriteCallbackParams *> dataWrittenCallChain;
CallChainOfFunctionPointersWithContext<const GattReadCallbackParams *> dataReadCallChain;
EventCallback_t updatesEnabledCallback;
EventCallback_t updatesDisabledCallback;
EventCallback_t confirmationReceivedCallback;
private:
/* disallow copy and assignment */
GattServer(const GattServer &);
GattServer& operator=(const GattServer &);
};
#endif // ifndef __GATT_SERVER_H__

215
ble/SecurityManager.h Normal file
View File

@ -0,0 +1,215 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __SECURITY_MANAGER_H__
#define __SECURITY_MANAGER_H__
#include <stdint.h>
#include "Gap.h"
class SecurityManager {
public:
enum SecurityMode_t {
SECURITY_MODE_NO_ACCESS,
SECURITY_MODE_ENCRYPTION_OPEN_LINK, /**< require no protection, open link. */
SECURITY_MODE_ENCRYPTION_NO_MITM, /**< require encryption, but no MITM protection. */
SECURITY_MODE_ENCRYPTION_WITH_MITM, /**< require encryption and MITM protection. */
SECURITY_MODE_SIGNED_NO_MITM, /**< require signing or encryption, but no MITM protection. */
SECURITY_MODE_SIGNED_WITH_MITM, /**< require signing or encryption, and MITM protection. */
};
/**
* @brief Defines possible security status/states.
*
* @details Defines possible security status/states of a link when requested by getLinkSecurity().
*/
enum LinkSecurityStatus_t {
NOT_ENCRYPTED, /**< The link is not secured. */
ENCRYPTION_IN_PROGRESS, /**< Link security is being established.*/
ENCRYPTED /**< The link is secure.*/
};
enum SecurityIOCapabilities_t {
IO_CAPS_DISPLAY_ONLY = 0x00, /**< Display Only. */
IO_CAPS_DISPLAY_YESNO = 0x01, /**< Display and Yes/No entry. */
IO_CAPS_KEYBOARD_ONLY = 0x02, /**< Keyboard Only. */
IO_CAPS_NONE = 0x03, /**< No I/O capabilities. */
IO_CAPS_KEYBOARD_DISPLAY = 0x04, /**< Keyboard and Display. */
};
enum SecurityCompletionStatus_t {
SEC_STATUS_SUCCESS = 0x00, /**< Procedure completed with success. */
SEC_STATUS_TIMEOUT = 0x01, /**< Procedure timed out. */
SEC_STATUS_PDU_INVALID = 0x02, /**< Invalid PDU received. */
SEC_STATUS_PASSKEY_ENTRY_FAILED = 0x81, /**< Passkey entry failed (user canceled or other). */
SEC_STATUS_OOB_NOT_AVAILABLE = 0x82, /**< Out of Band Key not available. */
SEC_STATUS_AUTH_REQ = 0x83, /**< Authentication requirements not met. */
SEC_STATUS_CONFIRM_VALUE = 0x84, /**< Confirm value failed. */
SEC_STATUS_PAIRING_NOT_SUPP = 0x85, /**< Pairing not supported. */
SEC_STATUS_ENC_KEY_SIZE = 0x86, /**< Encryption key size. */
SEC_STATUS_SMP_CMD_UNSUPPORTED = 0x87, /**< Unsupported SMP command. */
SEC_STATUS_UNSPECIFIED = 0x88, /**< Unspecified reason. */
SEC_STATUS_REPEATED_ATTEMPTS = 0x89, /**< Too little time elapsed since last attempt. */
SEC_STATUS_INVALID_PARAMS = 0x8A, /**< Invalid parameters. */
};
/**
* Declaration of type containing a passkey to be used during pairing. This
* is passed into initializeSecurity() to specify a pre-programmed passkey
* for authentication instead of generating a random one.
*/
static const unsigned PASSKEY_LEN = 6;
typedef uint8_t Passkey_t[PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */
public:
typedef void (*HandleSpecificEvent_t)(Gap::Handle_t handle);
typedef void (*SecuritySetupInitiatedCallback_t)(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps);
typedef void (*SecuritySetupCompletedCallback_t)(Gap::Handle_t, SecurityCompletionStatus_t status);
typedef void (*LinkSecuredCallback_t)(Gap::Handle_t handle, SecurityMode_t securityMode);
typedef void (*PasskeyDisplayCallback_t)(Gap::Handle_t handle, const Passkey_t passkey);
/*
* The following functions are meant to be overridden in the platform-specific sub-class.
*/
public:
/**
* Enable the BLE stack's Security Manager. The Security Manager implements
* the actual cryptographic algorithms and protocol exchanges that allow two
* devices to securely exchange data and privately detect each other.
* Calling this API is a prerequisite for encryption and pairing (bonding).
*
* @param[in] enableBonding Allow for bonding.
* @param[in] requireMITM Require protection for man-in-the-middle attacks.
* @param[in] iocaps To specify IO capabilities of this peripheral,
* such as availability of a display or keyboard to
* support out-of-band exchanges of security data.
* @param[in] passkey To specify a static passkey.
*
* @return BLE_ERROR_NONE on success.
*/
virtual ble_error_t init(bool enableBonding = true,
bool requireMITM = true,
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
const Passkey_t passkey = NULL) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this if security is supported. */
}
/**
* Get the security status of a connection.
*
* @param[in] connectionHandle Handle to identify the connection.
* @param[out] securityStatusP security status.
*
* @return BLE_SUCCESS Or appropriate error code indicating reason for failure.
*/
virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this if security is supported. */
}
/**
* Delete all peer device context and all related bonding information from
* the database within the security manager.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure.
* @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
*/
virtual ble_error_t purgeAllBondingState(void) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this if security is supported. */
}
/* Event callback handlers. */
public:
/**
* To indicate that security procedure for link has started.
*/
virtual void onSecuritySetupInitiated(SecuritySetupInitiatedCallback_t callback) {securitySetupInitiatedCallback = callback;}
/**
* To indicate that security procedure for link has completed.
*/
virtual void onSecuritySetupCompleted(SecuritySetupCompletedCallback_t callback) {securitySetupCompletedCallback = callback;}
/**
* To indicate that link with the peer is secured. For bonded devices,
* subsequent re-connections with bonded peer will result only in this callback
* when the link is secured and setup procedures will not occur unless the
* bonding information is either lost or deleted on either or both sides.
*/
virtual void onLinkSecured(LinkSecuredCallback_t callback) {linkSecuredCallback = callback;}
/**
* To indicate that device context is stored persistently.
*/
virtual void onSecurityContextStored(HandleSpecificEvent_t callback) {securityContextStoredCallback = callback;}
/**
* To set the callback for when the passkey needs to be displayed on a peripheral with DISPLAY capability.
*/
virtual void onPasskeyDisplay(PasskeyDisplayCallback_t callback) {passkeyDisplayCallback = callback;}
/* Entry points for the underlying stack to report events back to the user. */
public:
void processSecuritySetupInitiatedEvent(Gap::Handle_t handle, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps) {
if (securitySetupInitiatedCallback) {
securitySetupInitiatedCallback(handle, allowBonding, requireMITM, iocaps);
}
}
void processSecuritySetupCompletedEvent(Gap::Handle_t handle, SecurityCompletionStatus_t status) {
if (securitySetupCompletedCallback) {
securitySetupCompletedCallback(handle, status);
}
}
void processLinkSecuredEvent(Gap::Handle_t handle, SecurityMode_t securityMode) {
if (linkSecuredCallback) {
linkSecuredCallback(handle, securityMode);
}
}
void processSecurityContextStoredEvent(Gap::Handle_t handle) {
if (securityContextStoredCallback) {
securityContextStoredCallback(handle);
}
}
void processPasskeyDisplayEvent(Gap::Handle_t handle, const Passkey_t passkey) {
if (passkeyDisplayCallback) {
passkeyDisplayCallback(handle, passkey);
}
}
protected:
SecurityManager() :
securitySetupInitiatedCallback(),
securitySetupCompletedCallback(),
linkSecuredCallback(),
securityContextStoredCallback(),
passkeyDisplayCallback() {
/* empty */
}
protected:
SecuritySetupInitiatedCallback_t securitySetupInitiatedCallback;
SecuritySetupCompletedCallback_t securitySetupCompletedCallback;
LinkSecuredCallback_t linkSecuredCallback;
HandleSpecificEvent_t securityContextStoredCallback;
PasskeyDisplayCallback_t passkeyDisplayCallback;
};
#endif /*__SECURITY_MANAGER_H__*/

143
ble/ServiceDiscovery.h Normal file
View File

@ -0,0 +1,143 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __SERVICE_DISOVERY_H__
#define __SERVICE_DISOVERY_H__
#include "UUID.h"
#include "Gap.h"
#include "GattAttribute.h"
class DiscoveredService;
class DiscoveredCharacteristic;
class ServiceDiscovery {
public:
/*
* Exposed application callback types.
*/
/**
* Callback type for when a matching Service is found during service-
* discovery. The receiving function is passed in a pointer to a
* DiscoveredService object which will remain valid for the lifetime of the
* callback. Memory for this object is owned by the BLE_API eventing
* framework. The application can safely make a persistent shallow-copy of
* this object in order to work with the service beyond the callback.
*/
typedef void (*ServiceCallback_t)(const DiscoveredService *);
/**
* Callback type for when a matching Characteristic is found during service-
* discovery. The receiving function is passed in a pointer to a
* DiscoveredCharacteristic object which will remain valid for the lifetime
* of the callback. Memory for this object is owned by the BLE_API eventing
* framework. The application can safely make a persistent shallow-copy of
* this object in order to work with the characteristic beyond the callback.
*/
typedef void (*CharacteristicCallback_t)(const DiscoveredCharacteristic *);
/**
* Callback type for when serviceDiscovery terminates.
*/
typedef void (*TerminationCallback_t)(Gap::Handle_t connectionHandle);
public:
/**
* Launch service discovery. Once launched, service discovery will remain
* active with callbacks being issued back into the application for matching
* services/characteristics. isActive() can be used to determine status; and
* a termination callback (if setup) will be invoked at the end. Service
* discovery can be terminated prematurely if needed using terminate().
*
* @param connectionHandle
* Handle for the connection with the peer.
* @param sc
* This is the application callback for matching service. Taken as
* NULL by default. Note: service discovery may still be active
* when this callback is issued; calling asynchronous BLE-stack
* APIs from within this application callback might cause the
* stack to abort service discovery. If this becomes an issue, it
* may be better to make local copy of the discoveredService and
* wait for service discovery to terminate before operating on the
* service.
* @param cc
* This is the application callback for matching characteristic.
* Taken as NULL by default. Note: service discovery may still be
* active when this callback is issued; calling asynchronous
* BLE-stack APIs from within this application callback might cause
* the stack to abort service discovery. If this becomes an issue,
* it may be better to make local copy of the discoveredCharacteristic
* and wait for service discovery to terminate before operating on the
* characteristic.
* @param matchingServiceUUID
* UUID based filter for specifying a service in which the application is
* interested. By default it is set as the wildcard UUID_UNKNOWN,
* in which case it matches all services. If characteristic-UUID
* filter (below) is set to the wildcard value, then a service
* callback will be invoked for the matching service (or for every
* service if the service filter is a wildcard).
* @param matchingCharacteristicUUIDIn
* UUID based filter for specifying characteristic in which the application
* is interested. By default it is set as the wildcard UUID_UKNOWN
* to match against any characteristic. If both service-UUID
* filter and characteristic-UUID filter are used with non- wildcard
* values, then only a single characteristic callback is
* invoked for the matching characteristic.
*
* @note Using wildcard values for both service-UUID and characteristic-
* UUID will result in complete service discovery--callbacks being
* called for every service and characteristic.
*
* @note Providing NULL for the characteristic callback will result in
* characteristic discovery being skipped for each matching
* service. This allows for an inexpensive method to discover only
* services.
*
* @return
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
*/
virtual ble_error_t launch(Gap::Handle_t connectionHandle,
ServiceCallback_t sc = NULL,
CharacteristicCallback_t cc = NULL,
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN),
const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) = 0;
/**
* Is service-discovery currently active?
*/
virtual bool isActive(void) const = 0;
/**
* Terminate an ongoing service-discovery. This should result in an
* invocation of the TerminationCallback if service-discovery is active.
*/
virtual void terminate(void) = 0;
/**
* Setup callback to be invoked when service discovery is terminated.
*/
virtual void onTermination(TerminationCallback_t callback) = 0;
protected:
Gap::Handle_t connHandle; /**< Connection handle as provided by the SoftDevice. */
UUID matchingServiceUUID;
ServiceCallback_t serviceCallback;
UUID matchingCharacteristicUUID;
CharacteristicCallback_t characteristicCallback;
};
#endif // ifndef __SERVICE_DISOVERY_H__

View File

@ -17,6 +17,7 @@
#ifndef __UUID_H__
#define __UUID_H__
#include <stdint.h>
#include <string.h>
#include "blecommon.h"
@ -28,9 +29,10 @@ public:
UUID_TYPE_LONG = 1 // Full 128-bit UUID
};
typedef uint16_t ShortUUIDBytes_t;
static const unsigned LENGTH_OF_LONG_UUID = 16;
typedef uint16_t ShortUUIDBytes_t;
typedef uint8_t LongUUIDBytes_t[LENGTH_OF_LONG_UUID];
typedef uint8_t LongUUIDBytes_t[LENGTH_OF_LONG_UUID];
public:
/**

View File

@ -21,8 +21,6 @@
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
/** @defgroup BLE_UUID_VALUES Assigned Values for BLE UUIDs
* @{ */
@ -115,18 +113,18 @@ enum {
\brief Error codes for the BLE API
*/
/**************************************************************************/
typedef enum ble_error_e
{
BLE_ERROR_NONE = 0, /**< No error */
BLE_ERROR_BUFFER_OVERFLOW = 1, /**< The requested action would cause a buffer overflow and has been aborted */
BLE_ERROR_NOT_IMPLEMENTED = 2, /**< Requested a feature that isn't yet implement or isn't supported by the target HW */
BLE_ERROR_PARAM_OUT_OF_RANGE = 3, /**< One of the supplied parameters is outside the valid range */
BLE_ERROR_INVALID_PARAM = 4, /**< One of the supplied parameters is invalid */
BLE_STACK_BUSY = 5, /**< The stack is busy */
BLE_ERROR_INVALID_STATE = 6, /**< Invalid state. */
BLE_ERROR_NO_MEM = 7, /**< Out of Memory */
BLE_ERROR_UNSPECIFIED = 8, /**< Unknown error. */
} ble_error_t;
enum ble_error_t {
BLE_ERROR_NONE = 0, /**< No error */
BLE_ERROR_BUFFER_OVERFLOW = 1, /**< The requested action would cause a buffer overflow and has been aborted */
BLE_ERROR_NOT_IMPLEMENTED = 2, /**< Requested a feature that isn't yet implement or isn't supported by the target HW */
BLE_ERROR_PARAM_OUT_OF_RANGE = 3, /**< One of the supplied parameters is outside the valid range */
BLE_ERROR_INVALID_PARAM = 4, /**< One of the supplied parameters is invalid */
BLE_STACK_BUSY = 5, /**< The stack is busy */
BLE_ERROR_INVALID_STATE = 6, /**< Invalid state. */
BLE_ERROR_NO_MEM = 7, /**< Out of Memory */
BLE_ERROR_OPERATION_NOT_PERMITTED = 8,
BLE_ERROR_UNSPECIFIED = 9, /**< Unknown error. */
};
#ifdef __cplusplus
}

View File

@ -17,7 +17,7 @@
#ifndef __BLE_BATTERY_SERVICE_H__
#define __BLE_BATTERY_SERVICE_H__
#include "BLEDevice.h"
#include "ble/BLE.h"
/**
* @class BatteryService
@ -29,25 +29,19 @@ class BatteryService {
public:
/**
* @param[ref] _ble
* BLEDevice object for the underlying controller.
* BLE object for the underlying controller.
* @param[in] level
* 8bit batterly level. Usually used to represent percentage of batterly charge remaining.
*/
BatteryService(BLEDevice &_ble, uint8_t level = 100) :
BatteryService(BLE &_ble, uint8_t level = 100) :
ble(_ble),
batteryLevel(level),
batteryLevelCharacteristic(GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, &batteryLevel, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */
if (serviceAdded) {
return;
}
GattCharacteristic *charTable[] = {&batteryLevelCharacteristic};
GattService batteryService(GattService::UUID_BATTERY_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
ble.addService(batteryService);
serviceAdded = true;
}
/**
@ -62,8 +56,8 @@ public:
ble.updateCharacteristicValue(batteryLevelCharacteristic.getValueAttribute().getHandle(), &batteryLevel, 1);
}
private:
BLEDevice &ble;
protected:
BLE &ble;
uint8_t batteryLevel;
ReadOnlyGattCharacteristic<uint8_t> batteryLevelCharacteristic;

View File

@ -17,8 +17,8 @@
#ifndef __BLE_DFU_SERVICE_H__
#define __BLE_DFU_SERVICE_H__
#include "BLEDevice.h"
#include "UUID.h"
#include "ble/BLE.h"
#include "ble/UUID.h"
extern "C" void bootloader_start(void);
@ -48,17 +48,17 @@ public:
* @brief Adds Device Firmware Update service to an existing ble object.
*
* @param[ref] _ble
* BLEDevice object for the underlying controller.
* BLE object for the underlying controller.
* @param[in] _handoverCallback
* Application specific handover callback.
*/
DFUService(BLEDevice &_ble, ResetPrepare_t _handoverCallback = NULL) :
DFUService(BLE &_ble, ResetPrepare_t _handoverCallback = NULL) :
ble(_ble),
controlBytes(),
packetBytes(),
controlPoint(DFUServiceControlCharacteristicUUID, controlBytes, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
packet(DFUServicePacketCharacteristicUUID, packetBytes, SIZEOF_PACKET_BYTES, SIZEOF_PACKET_BYTES,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE) {
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
controlBytes(),
packetBytes() {
static bool serviceAdded = false; /* We should only ever need to add the DFU service once. */
if (serviceAdded) {
return;
@ -94,8 +94,8 @@ public:
* @param[in] params
* Information about the characterisitc being updated.
*/
virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
if (params->charHandle == controlPoint.getValueHandle()) {
virtual void onDataWritten(const GattWriteCallbackParams *params) {
if (params->handle == controlPoint.getValueHandle()) {
/* At present, writing anything will do the trick--this needs to be improved. */
if (handoverCallback) {
handoverCallback();
@ -105,16 +105,12 @@ public:
}
}
private:
protected:
static const unsigned SIZEOF_CONTROL_BYTES = 2;
static const unsigned SIZEOF_PACKET_BYTES = 20;
static ResetPrepare_t handoverCallback; /**< application specific handover callback. */
private:
BLEDevice &ble;
uint8_t controlBytes[SIZEOF_CONTROL_BYTES];
uint8_t packetBytes[SIZEOF_PACKET_BYTES];
protected:
BLE &ble;
/**< Writing to the control characteristic triggers the handover to dfu-
* bootloader. At present, writing anything will do the trick--this needs
@ -127,6 +123,11 @@ private:
* FOTA clients might get confused as service definitions change after
* handing control over to the bootloader. */
GattCharacteristic packet;
uint8_t controlBytes[SIZEOF_CONTROL_BYTES];
uint8_t packetBytes[SIZEOF_PACKET_BYTES];
static ResetPrepare_t handoverCallback; /**< application specific handover callback. */
};
#endif /* #ifndef __BLE_DFU_SERVICE_H__*/

View File

@ -17,7 +17,7 @@
#ifndef __BLE_DEVICE_INFORMATION_SERVICE_H__
#define __BLE_DEVICE_INFORMATION_SERVICE_H__
#include "BLEDevice.h"
#include "ble/BLE.h"
/**
* @class DeviceInformationService
@ -31,7 +31,7 @@ public:
* @brief Device Information Service Constructor.
*
* @param[ref] _ble
* BLEDevice object for the underlying controller.
* BLE object for the underlying controller.
* @param[in] manufacturersName
* This characteristic represents the name of the
* manufacturer of the device. The name is copied into the
@ -57,7 +57,7 @@ public:
* the software within the device. The value is copied
* into the BLE stack during this constructor.
*/
DeviceInformationService(BLEDevice &_ble,
DeviceInformationService(BLE &_ble,
const char *manufacturersName = NULL,
const char *modelNumber = NULL,
const char *serialNumber = NULL,
@ -114,8 +114,8 @@ public:
serviceAdded = true;
}
private:
BLEDevice &ble;
protected:
BLE &ble;
GattCharacteristic manufacturersNameStringCharacteristic;
GattCharacteristic modelNumberStringCharacteristic;
GattCharacteristic serialNumberStringCharacteristic;

View File

@ -17,7 +17,7 @@
#ifndef __BLE_HEALTH_THERMOMETER_SERVICE_H__
#define __BLE_HEALTH_THERMOMETER_SERVICE_H__
#include "BLEDevice.h"
#include "BLE.h"
/**
* @class HealthThermometerService
@ -51,7 +51,7 @@ public:
* @param[in] initialTemp initial value in celsius
* @param[in] _location
*/
HealthThermometerService(BLEDevice &_ble, float initialTemp, uint8_t _location) :
HealthThermometerService(BLE &_ble, float initialTemp, uint8_t _location) :
ble(_ble),
valueBytes(initialTemp),
tempMeasurement(GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, (TemperatureValueBytes *)valueBytes.getPointer(), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
@ -141,7 +141,7 @@ private:
};
private:
BLEDevice &ble;
BLE &ble;
TemperatureValueBytes valueBytes;
ReadOnlyGattCharacteristic<TemperatureValueBytes> tempMeasurement;
ReadOnlyGattCharacteristic<uint8_t> tempLocation;

View File

@ -17,7 +17,7 @@
#ifndef __BLE_HEART_RATE_SERVICE_H__
#define __BLE_HEART_RATE_SERVICE_H__
#include "BLEDevice.h"
#include "ble/BLE.h"
/**
* @class HeartRateService
@ -47,13 +47,13 @@ public:
* @brief Constructor with 8bit HRM Counter value.
*
* @param[ref] _ble
* Reference to the underlying BLEDevice.
* Reference to the underlying BLE.
* @param[in] hrmCounter (8-bit)
* initial value for the hrm counter.
* @param[in] location
* Sensor's location.
*/
HeartRateService(BLEDevice &_ble, uint8_t hrmCounter, uint8_t location) :
HeartRateService(BLE &_ble, uint8_t hrmCounter, uint8_t location) :
ble(_ble),
valueBytes(hrmCounter),
hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
@ -68,13 +68,13 @@ public:
* @brief Constructor with a 16-bit HRM Counter value.
*
* @param[in] _ble
* Reference to the underlying BLEDevice.
* Reference to the underlying BLE.
* @param[in] hrmCounter (8-bit)
* initial value for the hrm counter.
* @param[in] location
* Sensor's location.
*/
HeartRateService(BLEDevice &_ble, uint16_t hrmCounter, uint8_t location) :
HeartRateService(BLE &_ble, uint16_t hrmCounter, uint8_t location) :
ble(_ble),
valueBytes(hrmCounter),
hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
@ -114,8 +114,8 @@ public:
* @param[in] params
* Information about the characterisitc being updated.
*/
virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
if (params->charHandle == controlPoint.getValueAttribute().getHandle()) {
virtual void onDataWritten(const GattWriteCallbackParams *params) {
if (params->handle == controlPoint.getValueAttribute().getHandle()) {
/* Do something here if the new value is 1; else you can override this method by
* extending this class.
* @NOTE: if you are extending this class, be sure to also call
@ -125,23 +125,16 @@ public:
}
}
private:
protected:
void setupService(void) {
static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */
if (serviceAdded) {
return;
}
GattCharacteristic *charTable[] = {&hrmRate, &hrmLocation, &controlPoint};
GattService hrmService(GattService::UUID_HEART_RATE_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
ble.addService(hrmService);
serviceAdded = true;
ble.onDataWritten(this, &HeartRateService::onDataWritten);
}
private:
protected:
/* Private internal representation for the bytes used to work with the vaulue of the heart-rate characteristic. */
struct HeartRateValueBytes {
static const unsigned MAX_VALUE_BYTES = 3; /* FLAGS + up to two bytes for heart-rate */
@ -181,14 +174,14 @@ private:
return 1 + ((valueBytes[FLAGS_BYTE_INDEX] & VALUE_FORMAT_FLAG) ? sizeof(uint16_t) : sizeof(uint8_t));
}
private:
private:
/* First byte = 8-bit values, no extra info, Second byte = uint8_t HRM value */
/* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
uint8_t valueBytes[MAX_VALUE_BYTES];
};
private:
BLEDevice &ble;
protected:
BLE &ble;
HeartRateValueBytes valueBytes;
uint8_t controlPointValue;

View File

@ -37,9 +37,9 @@ public:
/**
* @param[ref] ble
* BLEDevice object for the underlying controller.
* BLE object for the underlying controller.
*/
LinkLossService(BLEDevice &bleIn, callback_t callbackIn, AlertLevel_t levelIn = NO_ALERT) :
LinkLossService(BLE &bleIn, callback_t callbackIn, AlertLevel_t levelIn = NO_ALERT) :
ble(bleIn),
alertLevel(levelIn),
callback(callbackIn),
@ -80,7 +80,7 @@ private:
* @param[in] params
* Information about the characterisitc being updated.
*/
virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
virtual void onDataWritten(const GattWriteCallbackParams *params) {
if (params->charHandle == alertLevelChar.getValueHandle()) {
alertLevel = *reinterpret_cast<const AlertLevel_t *>(params->data);
}
@ -92,8 +92,8 @@ private:
}
}
private:
BLEDevice &ble;
protected:
BLE &ble;
AlertLevel_t alertLevel;
callback_t callback;

View File

@ -20,8 +20,8 @@
#include "mbed.h"
#include "Stream.h"
#include "UUID.h"
#include "BLEDevice.h"
#include "ble/UUID.h"
#include "ble/BLE.h"
extern const uint8_t UARTServiceBaseUUID[UUID::LENGTH_OF_LONG_UUID];
extern const uint16_t UARTServiceShortUUID;
@ -48,9 +48,9 @@ public:
/**
* @param[ref] ble
* BLEDevice object for the underlying controller.
* BLE object for the underlying controller.
*/
UARTService(BLEDevice &_ble) :
UARTService(BLE &_ble) :
ble(_ble),
receiveBuffer(),
sendBuffer(),
@ -167,8 +167,8 @@ private:
* function from the global onDataWritten() callback handler; or if that's
* not used, this method can be used as a callback directly.
*/
void onDataWritten(const GattCharacteristicWriteCBParams *params) {
if (params->charHandle == getTXCharacteristicHandle()) {
void onDataWritten(const GattWriteCallbackParams *params) {
if (params->handle == getTXCharacteristicHandle()) {
uint16_t bytesRead = params->len;
if (bytesRead <= BLE_UART_SERVICE_MAX_DATA_LEN) {
numBytesReceived = bytesRead;
@ -179,7 +179,7 @@ private:
}
private:
BLEDevice &ble;
BLE &ble;
uint8_t receiveBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which we receive
* inbound data before forwarding it to the

View File

@ -17,7 +17,7 @@
#ifndef SERVICES_URIBEACONCONFIGSERVICE_H_
#define SERVICES_URIBEACONCONFIGSERVICE_H_
#include "BLEDevice.h"
#include "ble/BLE.h"
#include "mbed.h"
extern const uint8_t UUID_URI_BEACON_SERVICE[UUID::LENGTH_OF_LONG_UUID];
@ -71,7 +71,7 @@ class URIBeaconConfigService {
/**
* @param[ref] ble
* BLEDevice object for the underlying controller.
* BLE object for the underlying controller.
* @param[in/out] paramsIn
* Reference to application-visible beacon state, loaded
* from persistent storage at startup.
@ -85,7 +85,7 @@ class URIBeaconConfigService {
* @param[in] defaultAdvPowerLevelsIn
* Default power-levels array; applies only if the resetToDefaultsFlag is true.
*/
URIBeaconConfigService(BLEDevice &bleIn,
URIBeaconConfigService(BLE &bleIn,
Params_t &paramsIn,
bool resetToDefaultsFlag,
const char *defaultURIDataIn,
@ -159,26 +159,26 @@ class URIBeaconConfigService {
{
const char DEVICE_NAME[] = "mUriBeacon Config";
ble.clearAdvertisingPayload();
ble.gap().clearAdvertisingPayload();
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
// UUID is in different order in the ADV frame (!)
uint8_t reversedServiceUUID[sizeof(UUID_URI_BEACON_SERVICE)];
for (unsigned int i = 0; i < sizeof(UUID_URI_BEACON_SERVICE); i++) {
reversedServiceUUID[i] = UUID_URI_BEACON_SERVICE[sizeof(UUID_URI_BEACON_SERVICE) - i - 1];
}
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, reversedServiceUUID, sizeof(reversedServiceUUID));
ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG);
ble.accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, reinterpret_cast<const uint8_t *>(&DEVICE_NAME), sizeof(DEVICE_NAME));
ble.accumulateScanResponse(GapAdvertisingData::TX_POWER_LEVEL,
reinterpret_cast<uint8_t *>(&defaultAdvPowerLevels[URIBeaconConfigService::TX_POWER_MODE_LOW]),
sizeof(uint8_t));
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, reversedServiceUUID, sizeof(reversedServiceUUID));
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG);
ble.gap().accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, reinterpret_cast<const uint8_t *>(&DEVICE_NAME), sizeof(DEVICE_NAME));
ble.gap().accumulateScanResponse(GapAdvertisingData::TX_POWER_LEVEL,
reinterpret_cast<uint8_t *>(&defaultAdvPowerLevels[URIBeaconConfigService::TX_POWER_MODE_LOW]),
sizeof(uint8_t));
ble.setTxPower(params.advPowerLevels[params.txPowerMode]);
ble.setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADVERTISING_INTERVAL_MSEC));
ble.gap().setTxPower(params.advPowerLevels[params.txPowerMode]);
ble.gap().setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ble.gap().setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADVERTISING_INTERVAL_MSEC));
}
/* Helper function to switch to the non-connectible normal mode for URIBeacon. This gets called after a timeout. */
@ -202,12 +202,12 @@ class URIBeaconConfigService {
extern void saveURIBeaconConfigParams(const Params_t *paramsP); /* forward declaration; necessary to avoid a circular dependency. */
saveURIBeaconConfigParams(&params);
ble.clearAdvertisingPayload();
ble.setTxPower(params.advPowerLevels[params.txPowerMode]);
ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
ble.setAdvertisingInterval(beaconPeriod);
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_UUID, sizeof(BEACON_UUID));
ble.gap().clearAdvertisingPayload();
ble.gap().setTxPower(params.advPowerLevels[params.txPowerMode]);
ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
ble.gap().setAdvertisingInterval(beaconPeriod);
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_UUID, sizeof(BEACON_UUID));
serviceData[serviceDataLen++] = BEACON_UUID[0];
serviceData[serviceDataLen++] = BEACON_UUID[1];
@ -216,7 +216,7 @@ class URIBeaconConfigService {
for (unsigned j = 0; j < uriDataLength; j++) {
serviceData[serviceDataLen++] = uriData[j];
}
ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen);
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen);
}
private:
@ -232,8 +232,8 @@ class URIBeaconConfigService {
* characteristics of this service. Attempts to do so are also applied to
* the internal state of this service object.
*/
void onDataWrittenCallback(const GattCharacteristicWriteCBParams *writeParams) {
uint16_t handle = writeParams->charHandle;
void onDataWrittenCallback(const GattWriteCallbackParams *writeParams) {
uint16_t handle = writeParams->handle;
if (handle == lockChar.getValueHandle()) {
// Validated earlier
@ -259,11 +259,11 @@ class URIBeaconConfigService {
/* Re-map beaconPeriod to within permissible bounds if necessary. */
if (params.beaconPeriod != 0) {
bool paramsUpdated = false;
if (params.beaconPeriod < ble.getMinAdvertisingInterval()) {
params.beaconPeriod = ble.getMinAdvertisingInterval();
if (params.beaconPeriod < ble.gap().getMinAdvertisingInterval()) {
params.beaconPeriod = ble.gap().getMinAdvertisingInterval();
paramsUpdated = true;
} else if (params.beaconPeriod > ble.getMaxAdvertisingInterval()) {
params.beaconPeriod = ble.getMaxAdvertisingInterval();
} else if (params.beaconPeriod > ble.gap().getMaxAdvertisingInterval()) {
params.beaconPeriod = ble.gap().getMaxAdvertisingInterval();
paramsUpdated = true;
}
if (paramsUpdated) {
@ -305,8 +305,8 @@ class URIBeaconConfigService {
reinterpret_cast<uint8_t *>(params.advPowerLevels), sizeof(PowerLevels_t));
}
private:
void lockAuthorizationCallback(GattCharacteristicWriteAuthCBParams *authParams) {
private:
void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
if (lockedState) {
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
} else if (authParams->len != sizeof(Lock_t)) {
@ -319,7 +319,7 @@ class URIBeaconConfigService {
}
void unlockAuthorizationCallback(GattCharacteristicWriteAuthCBParams *authParams) {
void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
if (!lockedState) {
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
} else if (authParams->len != sizeof(Lock_t)) {
@ -333,7 +333,7 @@ class URIBeaconConfigService {
}
}
void uriDataWriteAuthorizationCallback(GattCharacteristicWriteAuthCBParams *authParams) {
void uriDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
if (lockedState) {
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
} else if (authParams->offset != 0) {
@ -343,7 +343,7 @@ class URIBeaconConfigService {
}
}
void powerModeAuthorizationCallback(GattCharacteristicWriteAuthCBParams *authParams) {
void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
if (lockedState) {
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
} else if (authParams->len != sizeof(uint8_t)) {
@ -358,7 +358,7 @@ class URIBeaconConfigService {
}
template <typename T>
void basicAuthorizationCallback(GattCharacteristicWriteAuthCBParams *authParams) {
void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
if (lockedState) {
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
} else if (authParams->len != sizeof(T)) {
@ -370,7 +370,8 @@ class URIBeaconConfigService {
}
}
BLEDevice &ble;
protected:
BLE &ble;
Params_t &params;
size_t defaultUriDataLength; // Default value that is restored on reset
@ -391,7 +392,7 @@ class URIBeaconConfigService {
ReadWriteGattCharacteristic<uint16_t> beaconPeriodChar;
WriteOnlyGattCharacteristic<uint8_t> resetChar;
public:
public:
/*
* Encode a human-readable URI into the binary format defined by URIBeacon spec (https://github.com/google/uribeacon/tree/master/specification).
*/

View File

@ -1,74 +1,74 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __BLE_IBEACON_SERVICE_H__
#define __BLE_IBEACON_SERVICE_H__
#include "core_cmInstr.h"
#include "BLEDevice.h"
/**
* @class iBeaconService
* @brief iBeacon Service. This service sets up a device to broadcast advertising packets to mimic an iBeacon<br>
*/
class iBeaconService
{
public:
typedef const uint8_t LocationUUID_t[16];
union Payload {
uint8_t raw[25];
struct {
uint16_t companyID;
uint8_t ID;
uint8_t len;
uint8_t proximityUUID[16];
uint16_t majorNumber;
uint16_t minorNumber;
uint8_t txPower;
};
Payload(LocationUUID_t uuid, uint16_t majNum, uint16_t minNum, uint8_t transmitPower, uint16_t companyIDIn) :
companyID(companyIDIn), ID(0x02), len(0x15), majorNumber(__REV16(majNum)), minorNumber(__REV16(minNum)), txPower(transmitPower)
{
memcpy(proximityUUID, uuid, sizeof(LocationUUID_t));
}
};
public:
iBeaconService(BLEDevice &_ble,
LocationUUID_t uuid,
uint16_t majNum,
uint16_t minNum,
uint8_t txP = 0xC8,
uint16_t compID = 0x004C) :
ble(_ble), data(uuid, majNum, minNum, txP, compID)
{
// Generate the 0x020106 part of the iBeacon Prefix
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE );
// Generate the 0x1AFF part of the iBeacon Prefix
ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, data.raw, sizeof(data.raw));
// Set advertising type
ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
}
private:
BLEDevice &ble;
Payload data;
};
#endif //__BLE_IBEACON_SERVICE_H__
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __BLE_IBEACON_SERVICE_H__
#define __BLE_IBEACON_SERVICE_H__
#include "core_cmInstr.h"
#include "BLE.h"
/**
* @class iBeaconService
* @brief iBeacon Service. This service sets up a device to broadcast advertising packets to mimic an iBeacon<br>
*/
class iBeaconService
{
public:
typedef const uint8_t LocationUUID_t[16];
union Payload {
uint8_t raw[25];
struct {
uint16_t companyID;
uint8_t ID;
uint8_t len;
uint8_t proximityUUID[16];
uint16_t majorNumber;
uint16_t minorNumber;
uint8_t txPower;
};
Payload(LocationUUID_t uuid, uint16_t majNum, uint16_t minNum, uint8_t transmitPower, uint16_t companyIDIn) :
companyID(companyIDIn), ID(0x02), len(0x15), majorNumber(__REV16(majNum)), minorNumber(__REV16(minNum)), txPower(transmitPower)
{
memcpy(proximityUUID, uuid, sizeof(LocationUUID_t));
}
};
public:
iBeaconService(BLE &_ble,
LocationUUID_t uuid,
uint16_t majNum,
uint16_t minNum,
uint8_t txP = 0xC8,
uint16_t compID = 0x004C) :
ble(_ble), data(uuid, majNum, minNum, txP, compID)
{
// Generate the 0x020106 part of the iBeacon Prefix
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE );
// Generate the 0x1AFF part of the iBeacon Prefix
ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, data.raw, sizeof(data.raw));
// Set advertising type
ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
}
private:
BLE &ble;
Payload data;
};
#endif //__BLE_IBEACON_SERVICE_H__

View File

@ -1 +0,0 @@
These files are common to all implementations of the BLE_API.

29
module.json Normal file
View File

@ -0,0 +1,29 @@
{
"name": "ble",
"version": "0.0.0",
"description": "The BLE module offers a high level abstraction for using Bluetooth Low Energy on multiple platforms.",
"keywords": [
"Bluetooth",
"BLE"
],
"author": "Rohit Grover",
"repository": {
"url": "git@github.com:mbedmicro/BLE_API.git",
"type": "git"
},
"homepage": "http://mbed.org/ble",
"licenses": [
{
"url": "https://spdx.org/licenses/Apache-2.0",
"type": "Apache-2.0"
}
],
"dependencies": {
"mbed": "^3.0.2"
},
"targetDependencies": {
"nrf51822": {
"ble-nrf51822":"~0.0.1"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,398 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __GAP_H__
#define __GAP_H__
#include "GapAdvertisingData.h"
#include "GapAdvertisingParams.h"
#include "GapEvents.h"
#include "CallChain.h"
#include "FunctionPointerWithContext.h"
using namespace mbed;
class GapScanningParams; /* forward declaration */
class Gap {
public:
enum AddressType_t {
ADDR_TYPE_PUBLIC = 0,
ADDR_TYPE_RANDOM_STATIC,
ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE,
ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE
};
typedef enum AddressType_t addr_type_t; /* @Note: deprecated. Use AddressType_t instead. */
static const unsigned ADDR_LEN = 6;
typedef uint8_t Address_t[ADDR_LEN]; /* 48-bit address, LSB format. */
typedef Address_t address_t; /* @Note: deprecated. Use Address_t instead. */
enum AdvertisementType_t {
ADV_IND = 0x00, /**< Connectable undirected. */
ADV_DIRECT_IND = 0x01, /**< Connectable directed. */
ADV_SCAN_IND = 0x02, /**< Scannable undirected. */
ADV_NONCONN_IND = 0x03, /**< Non connectable undirected. */
};
/**
* Enumeration for disconnection reasons. The values for these reasons are
* derived from Nordic's implementation; but the reasons are meant to be
* independent of the transport. If you are returned a reason which is not
* covered by this enumeration, then please refer to the underlying
* transport library.
*/
enum DisconnectionReason_t {
REMOTE_USER_TERMINATED_CONNECTION = 0x13,
LOCAL_HOST_TERMINATED_CONNECTION = 0x16,
CONN_INTERVAL_UNACCEPTABLE = 0x3B,
};
/* Describes the current state of the device (more than one bit can be set) */
struct GapState_t {
unsigned advertising : 1; /**< peripheral is currently advertising */
unsigned connected : 1; /**< peripheral is connected to a central */
};
typedef uint16_t Handle_t;
typedef struct {
uint16_t minConnectionInterval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
uint16_t maxConnectionInterval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
uint16_t slaveLatency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/
uint16_t connectionSupervisionTimeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/
} ConnectionParams_t;
enum SecurityMode_t {
SECURITY_MODE_NO_ACCESS,
SECURITY_MODE_ENCRYPTION_OPEN_LINK, /**< require no protection, open link. */
SECURITY_MODE_ENCRYPTION_NO_MITM, /**< require encryption, but no MITM protection. */
SECURITY_MODE_ENCRYPTION_WITH_MITM, /**< require encryption and MITM protection. */
SECURITY_MODE_SIGNED_NO_MITM, /**< require signing or encryption, but no MITM protection. */
SECURITY_MODE_SIGNED_WITH_MITM, /**< require signing or encryption, and MITM protection. */
};
/**
* @brief Defines possible security status/states.
*
* @details Defines possible security status/states of a link when requested by getLinkSecurity().
*/
enum LinkSecurityStatus_t {
NOT_ENCRYPTED, /**< The link is not secured. */
ENCRYPTION_IN_PROGRESS, /**< Link security is being established.*/
ENCRYPTED /**< The link is secure.*/
};
enum SecurityIOCapabilities_t {
IO_CAPS_DISPLAY_ONLY = 0x00, /**< Display Only. */
IO_CAPS_DISPLAY_YESNO = 0x01, /**< Display and Yes/No entry. */
IO_CAPS_KEYBOARD_ONLY = 0x02, /**< Keyboard Only. */
IO_CAPS_NONE = 0x03, /**< No I/O capabilities. */
IO_CAPS_KEYBOARD_DISPLAY = 0x04, /**< Keyboard and Display. */
};
enum SecurityCompletionStatus_t {
SEC_STATUS_SUCCESS = 0x00, /**< Procedure completed with success. */
SEC_STATUS_TIMEOUT = 0x01, /**< Procedure timed out. */
SEC_STATUS_PDU_INVALID = 0x02, /**< Invalid PDU received. */
SEC_STATUS_PASSKEY_ENTRY_FAILED = 0x81, /**< Passkey entry failed (user canceled or other). */
SEC_STATUS_OOB_NOT_AVAILABLE = 0x82, /**< Out of Band Key not available. */
SEC_STATUS_AUTH_REQ = 0x83, /**< Authentication requirements not met. */
SEC_STATUS_CONFIRM_VALUE = 0x84, /**< Confirm value failed. */
SEC_STATUS_PAIRING_NOT_SUPP = 0x85, /**< Pairing not supported. */
SEC_STATUS_ENC_KEY_SIZE = 0x86, /**< Encryption key size. */
SEC_STATUS_SMP_CMD_UNSUPPORTED = 0x87, /**< Unsupported SMP command. */
SEC_STATUS_UNSPECIFIED = 0x88, /**< Unspecified reason. */
SEC_STATUS_REPEATED_ATTEMPTS = 0x89, /**< Too little time elapsed since last attempt. */
SEC_STATUS_INVALID_PARAMS = 0x8A, /**< Invalid parameters. */
};
/**
* Declaration of type containing a passkey to be used during pairing. This
* is passed into initializeSecurity() to specify a pre-programmed passkey
* for authentication instead of generating a random one.
*/
static const unsigned PASSKEY_LEN = 6;
typedef uint8_t Passkey_t[PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */
static const uint16_t UNIT_1_25_MS = 1250; /**< Number of microseconds in 1.25 milliseconds. */
static const uint16_t UNIT_0_625_MS = 625; /**< Number of microseconds in 0.625 milliseconds. */
static uint16_t MSEC_TO_GAP_DURATION_UNITS(uint32_t durationInMillis) {
return (durationInMillis * 1000) / UNIT_1_25_MS;
}
static uint16_t MSEC_TO_ADVERTISEMENT_DURATION_UNITS(uint32_t durationInMillis) {
return (durationInMillis * 1000) / UNIT_0_625_MS;
}
static uint16_t ADVERTISEMENT_DURATION_UNITS_TO_MS(uint16_t gapUnits) {
return (gapUnits * UNIT_0_625_MS) / 1000;
}
typedef void (*EventCallback_t)(void);
typedef void (*ConnectionEventCallback_t)(Handle_t,
AddressType_t peerAddrType, const Address_t peerAddr,
AddressType_t ownAddrType, const Address_t ownAddr,
const ConnectionParams_t *);
typedef void (*HandleSpecificEvent_t)(Handle_t handle);
typedef void (*DisconnectionEventCallback_t)(Handle_t, DisconnectionReason_t);
typedef void (*RadioNotificationEventCallback_t) (bool radio_active); /* gets passed true for ACTIVE; false for INACTIVE. */
typedef void (*SecuritySetupInitiatedCallback_t)(Handle_t, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps);
typedef void (*SecuritySetupCompletedCallback_t)(Handle_t, SecurityCompletionStatus_t status);
typedef void (*LinkSecuredCallback_t)(Handle_t handle, SecurityMode_t securityMode);
typedef void (*PasskeyDisplayCallback_t)(Handle_t handle, const Passkey_t passkey);
struct AdvertisementCallbackParams_t {
Address_t peerAddr;
int8_t rssi;
bool isScanResponse;
AdvertisementType_t type;
uint8_t advertisingDataLen;
const uint8_t *advertisingData;
};
typedef FunctionPointerWithContext<const AdvertisementCallbackParams_t *> AdvertisementReportCallback_t;
friend class BLEDevice;
private:
/* These functions must be defined in the sub-class */
virtual ble_error_t setAddress(AddressType_t type, const Address_t address) = 0;
virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address) = 0;
virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &) = 0;
virtual ble_error_t startAdvertising(const GapAdvertisingParams &) = 0;
virtual ble_error_t stopAdvertising(void) = 0;
virtual ble_error_t stopScan() = 0;
virtual uint16_t getMinAdvertisingInterval(void) const = 0;
virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const = 0;
virtual uint16_t getMaxAdvertisingInterval(void) const = 0;
virtual ble_error_t disconnect(DisconnectionReason_t reason) = 0;
virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params) = 0;
virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params) = 0;
virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params) = 0;
virtual ble_error_t purgeAllBondingState(void) = 0;
virtual ble_error_t getLinkSecurity(Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) = 0;
virtual ble_error_t setDeviceName(const uint8_t *deviceName) = 0;
virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP) = 0;
virtual ble_error_t setAppearance(uint16_t appearance) = 0;
virtual ble_error_t getAppearance(uint16_t *appearanceP) = 0;
ble_error_t startScan(const GapScanningParams &scanningParams, void (*callback)(const AdvertisementCallbackParams_t *params)) {
ble_error_t err = BLE_ERROR_NONE;
if (callback) {
if ((err = startRadioScan(scanningParams)) == BLE_ERROR_NONE) {
onAdvertisementReport.attach(callback);
}
}
return err;
}
template<typename T>
ble_error_t startScan(const GapScanningParams &scanningParams, T *object, void (T::*callbackMember)(const AdvertisementCallbackParams_t *params)) {
ble_error_t err = BLE_ERROR_NONE;
if (object && callbackMember) {
if ((err = startRadioScan(scanningParams)) == BLE_ERROR_NONE) {
onAdvertisementReport.attach(object, callbackMember);
}
}
return err;
}
protected:
virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams) = 0;
/* Event callback handlers */
void setOnTimeout(EventCallback_t callback) {onTimeout = callback;}
void setOnConnection(ConnectionEventCallback_t callback) {onConnection = callback;}
/**
* Set the application callback for disconnection events.
* @param callback
* Pointer to the unique callback.
*/
void setOnDisconnection(DisconnectionEventCallback_t callback) {onDisconnection = callback;}
/**
* Set the application callback for radio-notification events.
* @param callback
* Handler to be executed in response to a radio notification event.
*/
virtual void setOnRadioNotification(RadioNotificationEventCallback_t callback) {onRadioNotification = callback;}
/**
* To indicate that security procedure for link has started.
*/
virtual void setOnSecuritySetupInitiated(SecuritySetupInitiatedCallback_t callback) {onSecuritySetupInitiated = callback;}
/**
* To indicate that security procedure for link has completed.
*/
virtual void setOnSecuritySetupCompleted(SecuritySetupCompletedCallback_t callback) {onSecuritySetupCompleted = callback;}
/**
* To indicate that link with the peer is secured. For bonded devices,
* subsequent re-connections with bonded peer will result only in this callback
* when the link is secured and setup procedures will not occur unless the
* bonding information is either lost or deleted on either or both sides.
*/
virtual void setOnLinkSecured(LinkSecuredCallback_t callback) {onLinkSecured = callback;}
/**
* To indicate that device context is stored persistently.
*/
virtual void setOnSecurityContextStored(HandleSpecificEvent_t callback) {onSecurityContextStored = callback;}
/**
* To set the callback for when the passkey needs to be displayed on a peripheral with DISPLAY capability.
*/
virtual void setOnPasskeyDisplay(PasskeyDisplayCallback_t callback) {onPasskeyDisplay = callback;}
/**
* Append to a chain of callbacks to be invoked upon disconnection; these
* callbacks receive no context and are therefore different from the
* onDisconnection callback.
* @param callback
* function pointer to be invoked upon disconnection; receives no context.
*
* @note the disconnection CallChain should have been merged with
* onDisconnctionCallback; but this was not possible because
* FunctionPointer (which is a building block for CallChain) doesn't
* accept variadic templates.
*/
template<typename T>
void addToDisconnectionCallChain(T *tptr, void (T::*mptr)(void)) {disconnectionCallChain.add(tptr, mptr);}
private:
GapState_t getState(void) const {
return state;
}
protected:
Gap() :
state(),
onTimeout(NULL),
onConnection(NULL),
onDisconnection(NULL),
onRadioNotification(),
onSecuritySetupInitiated(),
onSecuritySetupCompleted(),
onLinkSecured(),
onSecurityContextStored(),
onPasskeyDisplay(),
onAdvertisementReport(),
disconnectionCallChain() {
/* empty */
}
public:
void processConnectionEvent(Handle_t handle, AddressType_t peerAddrType, const Address_t peerAddr, AddressType_t ownAddrType, const Address_t ownAddr, const ConnectionParams_t *params) {
state.connected = 1;
if (onConnection) {
onConnection(handle, peerAddrType, peerAddr, ownAddrType, ownAddr, params);
}
}
void processDisconnectionEvent(Handle_t handle, DisconnectionReason_t reason) {
state.connected = 0;
if (onDisconnection) {
onDisconnection(handle, reason);
}
disconnectionCallChain.call();
}
void processSecuritySetupInitiatedEvent(Handle_t handle, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps) {
if (onSecuritySetupInitiated) {
onSecuritySetupInitiated(handle, allowBonding, requireMITM, iocaps);
}
}
void processSecuritySetupCompletedEvent(Handle_t handle, SecurityCompletionStatus_t status) {
if (onSecuritySetupCompleted) {
onSecuritySetupCompleted(handle, status);
}
}
void processLinkSecuredEvent(Handle_t handle, SecurityMode_t securityMode) {
if (onLinkSecured) {
onLinkSecured(handle, securityMode);
}
}
void processSecurityContextStoredEvent(Handle_t handle) {
if (onSecurityContextStored) {
onSecurityContextStored(handle);
}
}
void processPasskeyDisplayEvent(Handle_t handle, const Passkey_t passkey) {
if (onPasskeyDisplay) {
onPasskeyDisplay(handle, passkey);
}
}
void processAdvertisementReport(const Address_t peerAddr,
int8_t rssi,
bool isScanResponse,
AdvertisementType_t type,
uint8_t advertisingDataLen,
const uint8_t *advertisingData) {
AdvertisementCallbackParams_t params;
memcpy(params.peerAddr, peerAddr, ADDR_LEN);
params.rssi = rssi;
params.isScanResponse = isScanResponse;
params.type = type;
params.advertisingDataLen = advertisingDataLen;
params.advertisingData = advertisingData;
onAdvertisementReport.call(&params);
}
void processEvent(GapEvents::gapEvent_e type) {
switch (type) {
case GapEvents::GAP_EVENT_TIMEOUT:
state.advertising = 0;
if (onTimeout) {
onTimeout();
}
break;
default:
break;
}
}
protected:
GapState_t state;
protected:
EventCallback_t onTimeout;
ConnectionEventCallback_t onConnection;
DisconnectionEventCallback_t onDisconnection;
RadioNotificationEventCallback_t onRadioNotification;
SecuritySetupInitiatedCallback_t onSecuritySetupInitiated;
SecuritySetupCompletedCallback_t onSecuritySetupCompleted;
LinkSecuredCallback_t onLinkSecured;
HandleSpecificEvent_t onSecurityContextStored;
PasskeyDisplayCallback_t onPasskeyDisplay;
AdvertisementReportCallback_t onAdvertisementReport;
CallChain disconnectionCallChain;
private:
/* disallow copy and assignment */
Gap(const Gap &);
Gap& operator=(const Gap &);
};
#endif // ifndef __GAP_H__

View File

@ -1,159 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __GATT_SERVER_H__
#define __GATT_SERVER_H__
#include "Gap.h"
#include "GattService.h"
#include "GattAttribute.h"
#include "GattServerEvents.h"
#include "GattCharacteristicCallbackParams.h"
#include "CallChainOfFunctionPointersWithContext.h"
class GattServer {
public:
/* Event callback handlers. */
typedef void (*EventCallback_t)(GattAttribute::Handle_t attributeHandle);
typedef void (*ServerEventCallback_t)(void); /**< independent of any particular attribute */
protected:
GattServer() :
serviceCount(0),
characteristicCount(0),
onDataSent(),
onDataWritten(),
onDataRead(),
onUpdatesEnabled(NULL),
onUpdatesDisabled(NULL),
onConfirmationReceived(NULL) {
/* empty */
}
friend class BLEDevice;
private:
/* These functions must be defined in the sub-class */
virtual ble_error_t addService(GattService &) = 0;
virtual ble_error_t readValue(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) = 0;
virtual ble_error_t readValue(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) = 0;
virtual ble_error_t updateValue(GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false) = 0;
virtual ble_error_t updateValue(Gap::Handle_t connectionHandle, GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false) = 0;
virtual ble_error_t initializeGATTDatabase(void) = 0;
// ToDo: For updateValue, check the CCCD to see if the value we are
// updating has the notify or indicate bits sent, and if BOTH are set
// be sure to call sd_ble_gatts_hvx() twice with notify then indicate!
// Strange use case, but valid and must be covered!
void setOnDataSent(void (*callback)(unsigned count)) {onDataSent.add(callback);}
template <typename T>
void setOnDataSent(T *objPtr, void (T::*memberPtr)(unsigned count)) {
onDataSent.add(objPtr, memberPtr);
}
void setOnDataWritten(void (*callback)(const GattCharacteristicWriteCBParams *eventDataP)) {onDataWritten.add(callback);}
template <typename T>
void setOnDataWritten(T *objPtr, void (T::*memberPtr)(const GattCharacteristicWriteCBParams *context)) {
onDataWritten.add(objPtr, memberPtr);
}
/**
* A virtual function to allow underlying stacks to indicate if they support
* onDataRead(). It should be overridden to return true as applicable.
*/
virtual bool isOnDataReadAvailable() const {
return false;
}
ble_error_t setOnDataRead(void (*callback)(const GattCharacteristicReadCBParams *eventDataP)) {
if (!isOnDataReadAvailable()) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
onDataRead.add(callback);
return BLE_ERROR_NONE;
}
template <typename T>
ble_error_t setOnDataRead(T *objPtr, void (T::*memberPtr)(const GattCharacteristicReadCBParams *context)) {
if (!isOnDataReadAvailable()) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
onDataRead.add(objPtr, memberPtr);
return BLE_ERROR_NONE;
}
void setOnUpdatesEnabled(EventCallback_t callback) {onUpdatesEnabled = callback;}
void setOnUpdatesDisabled(EventCallback_t callback) {onUpdatesDisabled = callback;}
void setOnConfirmationReceived(EventCallback_t callback) {onConfirmationReceived = callback;}
protected:
void handleDataWrittenEvent(const GattCharacteristicWriteCBParams *params) {
if (onDataWritten.hasCallbacksAttached()) {
onDataWritten.call(params);
}
}
void handleDataReadEvent(const GattCharacteristicReadCBParams *params) {
if (onDataRead.hasCallbacksAttached()) {
onDataRead.call(params);
}
}
void handleEvent(GattServerEvents::gattEvent_e type, GattAttribute::Handle_t charHandle) {
switch (type) {
case GattServerEvents::GATT_EVENT_UPDATES_ENABLED:
if (onUpdatesEnabled) {
onUpdatesEnabled(charHandle);
}
break;
case GattServerEvents::GATT_EVENT_UPDATES_DISABLED:
if (onUpdatesDisabled) {
onUpdatesDisabled(charHandle);
}
break;
case GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED:
if (onConfirmationReceived) {
onConfirmationReceived(charHandle);
}
break;
default:
break;
}
}
void handleDataSentEvent(unsigned count) {
if (onDataSent.hasCallbacksAttached()) {
onDataSent.call(count);
}
}
protected:
uint8_t serviceCount;
uint8_t characteristicCount;
private:
CallChainOfFunctionPointersWithContext<unsigned> onDataSent;
CallChainOfFunctionPointersWithContext<const GattCharacteristicWriteCBParams *> onDataWritten;
CallChainOfFunctionPointersWithContext<const GattCharacteristicReadCBParams *> onDataRead;
EventCallback_t onUpdatesEnabled;
EventCallback_t onUpdatesDisabled;
EventCallback_t onConfirmationReceived;
private:
/* disallow copy and assignment */
GattServer(const GattServer &);
GattServer& operator=(const GattServer &);
};
#endif // ifndef __GATT_SERVER_H__

View File

@ -1 +0,0 @@
The public API exposed through header files.

View File

@ -14,14 +14,14 @@
* limitations under the License.
*/
#include "BLEDevice.h"
#include "ble/BLE.h"
#if defined(TARGET_OTA_ENABLED)
#include "DFUService.h"
#endif
ble_error_t
BLEDevice::init()
BLE::init()
{
ble_error_t err = transport->init();
if (err != BLE_ERROR_NONE) {

View File

@ -0,0 +1,69 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ble/DiscoveredCharacteristic.h"
#include "ble/GattClient.h"
GattClient::ReadCallback_t DiscoveredCharacteristic::onDataReadCallback;
GattClient::WriteCallback_t DiscoveredCharacteristic::onDataWriteCallback;
ble_error_t
DiscoveredCharacteristic::read(uint16_t offset) const
{
if (!props.read()) {
return BLE_ERROR_OPERATION_NOT_PERMITTED;
}
if (!gattc) {
return BLE_ERROR_INVALID_STATE;
}
return gattc->read(connHandle, valueHandle, offset);
}
ble_error_t
DiscoveredCharacteristic::write(uint16_t length, const uint8_t *value) const
{
if (!props.write()) {
return BLE_ERROR_OPERATION_NOT_PERMITTED;
}
if (!gattc) {
return BLE_ERROR_INVALID_STATE;
}
return gattc->write(GattClient::GATT_OP_WRITE_REQ, connHandle, valueHandle, length, value);
}
ble_error_t
DiscoveredCharacteristic::writeWoResponse(uint16_t length, const uint8_t *value) const
{
if (!props.writeWoResp()) {
return BLE_ERROR_OPERATION_NOT_PERMITTED;
}
if (!gattc) {
return BLE_ERROR_INVALID_STATE;
}
return gattc->write(GattClient::GATT_OP_WRITE_CMD, connHandle, valueHandle, length, value);
}
ble_error_t
DiscoveredCharacteristic::discoverDescriptors(DescriptorCallback_t callback, const UUID &matchingUUID) const
{
return BLE_ERROR_NOT_IMPLEMENTED; /* TODO: this needs to be filled in. */
}

View File

@ -0,0 +1,75 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ble/Gap.h"
#include "ble/GapScanningParams.h"
GapScanningParams::GapScanningParams(uint16_t interval, uint16_t window, uint16_t timeout, bool activeScanning) :
_interval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(interval)),
_window(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(window)),
_timeout(timeout),
_activeScanning(activeScanning) {
/* stay within limits */
if (_interval < SCAN_INTERVAL_MIN) {
_interval = SCAN_INTERVAL_MIN;
}
if (_interval > SCAN_INTERVAL_MAX) {
_interval = SCAN_INTERVAL_MAX;
}
if (_window < SCAN_WINDOW_MIN) {
_window = SCAN_WINDOW_MIN;
}
if (_window > SCAN_WINDOW_MAX) {
_window = SCAN_WINDOW_MAX;
}
}
ble_error_t
GapScanningParams::setInterval(uint16_t newIntervalInMS)
{
uint16_t newInterval = Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(newIntervalInMS);
if ((newInterval >= SCAN_INTERVAL_MIN) && (newInterval < SCAN_INTERVAL_MAX)) {
_interval = newInterval;
return BLE_ERROR_NONE;
}
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
ble_error_t
GapScanningParams::setWindow(uint16_t newWindowInMS)
{
uint16_t newWindow = Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(newWindowInMS);
if ((newWindow >= SCAN_WINDOW_MIN) && (newWindow < SCAN_WINDOW_MAX)) {
_window = newWindow;
return BLE_ERROR_NONE;
}
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
ble_error_t
GapScanningParams::setTimeout(uint16_t newTimeout)
{
_timeout = newTimeout;
return BLE_ERROR_NONE;
}
void
GapScanningParams::setActiveScanning(bool activeScanning)
{
_activeScanning = activeScanning;
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "DFUService.h"
#include "ble/services/DFUService.h"
const uint8_t DFUServiceBaseUUID[] = {
0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0xEF, 0xDE,

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "UARTService.h"
#include "ble/services/UARTService.h"
const uint8_t UARTServiceBaseUUID[UUID::LENGTH_OF_LONG_UUID] = {
0x6E, 0x40, 0x00, 0x00, 0xB5, 0xA3, 0xF3, 0x93,

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "URIBeaconConfigService.h"
#include "ble/services/URIBeaconConfigService.h"
#define UUID_URI_BEACON(FIRST, SECOND) { \
0xee, 0x0c, FIRST, SECOND, 0x87, 0x86, 0x40, 0xba, \