Release 0.3.6

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

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

* Add APIs for scanning of advertisements.

    BLEDevice::setScanParams(uint16_t interval, uint16_t window, uint16_t timeout, bool activeScanning);
    BLEDevice::startScan(Gap::AdvertisementReportCallback_t callback);
    BLEDevice::stopScan(void);
  Also introduced a type to encapsulate scanning-parameters. There's a new demo on mbed.org for a trivial observer.

Bugfixes
~~~~~~~~

* fix #40: fix value of Gap::UNIT_0_625_MS
This commit is contained in:
Rohit Grover 2015-05-12 10:24:32 +01:00
commit dcc18e3d18
4 changed files with 245 additions and 9 deletions

View file

@ -20,6 +20,7 @@
#include "blecommon.h"
#include "Gap.h"
#include "GattServer.h"
#include "GapScanningParams.h"
#include "BLEDeviceInstanceBase.h"
/**
@ -231,6 +232,52 @@ public:
*/
ble_error_t stopAdvertising(void);
/**
* Setup parameters for GAP scanning--i.e. observer mode.
* @param interval Scan interval (in milliseconds) [valid values lie between 2.5ms and 10.24s].
* @param window Scan Window (in milliseconds) [valid values lie between 2.5ms and 10.24s].
* @param timeout Scan timeout (in seconds) between 0x0001 and 0xFFFF, 0x0000 disables timeout.
* @param 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 setScanInterval(uint16_t interval);
ble_error_t setScanWindow (uint16_t window);
ble_error_t setScanTimeout (uint16_t timeout);
void setActiveScan (bool activeScanning);
/**
* Start scanning (Observer Procedure) based on the scan-params currently
* in effect.
*
* @param callback The application callback to be invoked upon receiving
* every advertisement report. Can be passed in as NULL, in which case
* scanning may not be enabled at all.
*/
ble_error_t startScan(Gap::AdvertisementReportCallback_t callback);
/**
* Stop scanning. The current scanning parameters remain in effect.
*
* @retval BLE_ERROR_NONE if successfully stopped scanning procedure.
*/
ble_error_t stopScan(void);
/**
* This call initiates the disconnection procedure, and its completion will
* be communicated to the application with an invocation of the
@ -528,7 +575,7 @@ public:
ble_error_t purgeAllBondingState(void);
public:
BLEDevice() : transport(createBLEDeviceInstance()), advParams(), advPayload(), scanResponse(), needToSetAdvPayload(true) {
BLEDevice() : transport(createBLEDeviceInstance()), advParams(), advPayload(), scanResponse(), needToSetAdvPayload(true), scanningParams() {
advPayload.clear();
scanResponse.clear();
}
@ -544,6 +591,8 @@ private:
* eventually result in a call to the target's setAdvertisingData() before
* the server begins advertising. This flag marks the status of the pending update.*/
bool needToSetAdvPayload;
GapScanningParams scanningParams;
};
/* BLEDevice methods. Most of these simply forward the calls to the underlying
@ -699,6 +748,51 @@ BLEDevice::stopAdvertising(void)
return transport->getGap().stopAdvertising();
}
inline ble_error_t
BLEDevice::setScanParams(uint16_t interval, uint16_t window, uint16_t timeout, bool activeScanning) {
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;
}
inline ble_error_t
BLEDevice::setScanInterval(uint16_t interval) {
return scanningParams.setInterval(interval);
}
inline ble_error_t
BLEDevice::setScanWindow(uint16_t window) {
return scanningParams.setWindow(window);
}
inline ble_error_t
BLEDevice::setScanTimeout(uint16_t timeout) {
return scanningParams.setTimeout(timeout);
}
inline void
BLEDevice::setActiveScan(bool activeScanning) {
return scanningParams.setActiveScanning(activeScanning);
}
inline ble_error_t
BLEDevice::startScan(Gap::AdvertisementReportCallback_t callback) {
return transport->getGap().startScan(scanningParams, callback);
}
inline ble_error_t
BLEDevice::stopScan(void) {
return transport->getGap().stopScan();
}
inline ble_error_t
BLEDevice::disconnect(Gap::DisconnectionReason_t reason)
{

View file

@ -24,6 +24,8 @@
using namespace mbed;
class GapScanningParams; /* forward declaration */
class Gap {
public:
enum AddressType_t {
@ -32,11 +34,18 @@ public:
ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE,
ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE
};
typedef enum AddressType_t addr_type_t; /* @Note: decprecated. */
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. */
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
@ -119,14 +128,14 @@ public:
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 = 650; /**< Number of microseconds in 0.625 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 GAP_DURATION_UNITS_TO_MS(uint16_t gapUnits) {
static uint16_t ADVERTISEMENT_DURATION_UNITS_TO_MS(uint16_t gapUnits) {
return (gapUnits * UNIT_0_625_MS) / 1000;
}
@ -143,7 +152,15 @@ public:
typedef void (*LinkSecuredCallback_t)(Handle_t handle, SecurityMode_t securityMode);
typedef void (*PasskeyDisplayCallback_t)(Handle_t handle, const Passkey_t passkey);
typedef void (*AdvertisementReportCallback_t)(const address_t peerAddr,
int8_t rssi,
bool isScanResponse,
AdvertisementType_t type,
uint8_t advertisingDataLen,
const uint8_t *advertisingData);
friend class BLEDevice;
private:
/* These functions must be defined in the sub-class */
virtual ble_error_t setAddress(addr_type_t type, const address_t address) = 0;
@ -151,6 +168,8 @@ private:
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 startScan(const GapScanningParams &scanningParams, AdvertisementReportCallback_t callback) = 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;
@ -246,6 +265,7 @@ protected:
onLinkSecured(),
onSecurityContextStored(),
onPasskeyDisplay(),
onAdvertisementReport(),
disconnectionCallChain() {
/* empty */
}
@ -296,6 +316,17 @@ public:
}
}
void processAdvertisementReport(const address_t peerAddr,
int8_t rssi,
bool isScanResponse,
AdvertisementType_t type,
uint8_t advertisingDataLen,
const uint8_t *advertisingData) {
if (onAdvertisementReport) {
onAdvertisementReport(peerAddr, rssi, isScanResponse, type, advertisingDataLen, advertisingData);
}
}
void processEvent(GapEvents::gapEvent_e type) {
switch (type) {
case GapEvents::GAP_EVENT_TIMEOUT:
@ -322,6 +353,7 @@ protected:
LinkSecuredCallback_t onLinkSecured;
HandleSpecificEvent_t onSecurityContextStored;
PasskeyDisplayCallback_t onPasskeyDisplay;
AdvertisementReportCallback_t onAdvertisementReport;
CallChain disconnectionCallChain;
private:

110
public/GapScanningParams.h Normal file
View file

@ -0,0 +1,110 @@
/* 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_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. */
static const unsigned SCAN_INTERVAL_MAX = 0x4000; /**< Maximum Scan interval in 625 us units, i.e. 10.24 s. */
static const unsigned SCAN_WINDOW_MIN = 0x0004; /**< Minimum Scan window in 625 us units, i.e. 2.5 ms. */
static const unsigned SCAN_WINDOW_MAX = 0x4000; /**< Maximum Scan window in 625 us units, i.e. 10.24 s. */
static const unsigned SCAN_TIMEOUT_MIN = 0x0001; /**< Minimum Scan timeout in seconds. */
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;
}
if (_timeout > SCAN_TIMEOUT_MAX) {
_timeout = SCAN_TIMEOUT_MAX;
}
}
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;
}
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
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) {
if (newTimeout <= SCAN_TIMEOUT_MAX) {
_timeout = newTimeout;
return BLE_ERROR_NONE;
}
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
void setActiveScanning(bool activeScanning) {
_activeScanning = activeScanning;
}
/* @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; }
uint16_t getTimeout(void) const {return _timeout; }
bool getActiveScanning(void) const {return _activeScanning;}
private:
uint16_t _interval; /**< Scan interval in units of 625us (between 2.5ms to 10.24s). */
uint16_t _window; /**< Scan window in units of 625us (between 2.5ms to 10.24s). */
uint16_t _timeout; /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */
bool _activeScanning; /**< obtain not only the advertising data from the peer device, but also their scanResponse if possible. */
private:
/* disallow copy constructor */
GapScanningParams(const GapScanningParams &);
GapScanningParams& operator =(const GapScanningParams &in);
};
#endif // ifndef __GAP_SCANNING_PARAMS_H__

View file

@ -104,7 +104,7 @@ public:
\note See https://developer.bluetooth.org/gatt/units/Pages/default.aspx
*/
/**************************************************************************/
typedef enum ble_gatt_unit_e {
enum {
BLE_GATT_UNIT_NONE = 0x2700, /**< No specified unit type */
BLE_GATT_UNIT_LENGTH_METRE = 0x2701, /**< Length, Metre */
BLE_GATT_UNIT_MASS_KILOGRAM = 0x2702, /**< Mass, Kilogram */
@ -214,7 +214,7 @@ public:
BLE_GATT_UNIT_TIME_MONTH = 0x27B4, /**< Time, Month */
BLE_GATT_UNIT_CONCENTRATION_COUNT_PER_CUBIC_METRE = 0x27B5, /**< */
BLE_GATT_UNIT_IRRADIANCE_WATT_PER_SQUARE_METRE = 0x27B6 /**< */
} ble_gatt_unit_t;
};
/**************************************************************************/
/*!
@ -224,7 +224,7 @@ public:
\note See http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
*/
/**************************************************************************/
typedef enum ble_gatt_format_e {
enum {
BLE_GATT_FORMAT_RFU = 0x00, /**< Reserved For Future Use. */
BLE_GATT_FORMAT_BOOLEAN = 0x01, /**< Boolean. */
BLE_GATT_FORMAT_2BIT = 0x02, /**< Unsigned 2-bit integer. */
@ -253,7 +253,7 @@ public:
BLE_GATT_FORMAT_UTF8S = 0x19, /**< UTF-8 string. */
BLE_GATT_FORMAT_UTF16S = 0x1A, /**< UTF-16 string. */
BLE_GATT_FORMAT_STRUCT = 0x1B /**< Opaque Structure. */
} ble_gatt_format_t;
};
/**************************************************************************/
/*!