Release 0.1.0

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

Mostly API changes.

Features
~~~~~~~~

- onConnection() callback now receives connection-parameters applicable to the
  new connection.

- onDataSent() callback now receives a count parameter containing the number of
  times notifications were sent out since the last callback.

- A 'reason' parameter has been added to Gap::disconnect() to indicate the
  reason for disconnection; and also to the onDisconnection callback to
  receive a reason from the remote host.

Bugfixes
~~~~~~~~

- onDataWritten() callback now receives an additional parameter
  (GattServer::WriteEventCallback_t) encapsulating the update. This avoids
  having to re-fetch the updated characteristic's value attribute. It also
  fixes a bug where multiple updates to the characteristic's value-attribute
  could get clobbered if they occurred in quick succession before the
  callbacks could be processed.
master
Rohit Grover 2014-09-02 15:09:46 +01:00
parent 0cb7eb3eca
commit c8eccb0222
9 changed files with 120 additions and 171 deletions

View File

@ -64,7 +64,7 @@
@endcode
*/
/**************************************************************************/
UUID::UUID(const LongUUID_t longUUID) : type(UUID_TYPE_SHORT), baseUUID(), shortUUID(0)
UUID::UUID(const LongUUIDBytes_t longUUID) : type(UUID_TYPE_SHORT), baseUUID(), shortUUID(0)
{
memcpy(baseUUID, longUUID, LENGTH_OF_LONG_UUID);
shortUUID = (uint16_t)((longUUID[2] << 8) | (longUUID[3]));
@ -98,7 +98,7 @@ UUID::UUID(const LongUUID_t longUUID) : type(UUID_TYPE_SHORT), baseUUID(), short
The 16-bit BLE UUID value.
*/
/**************************************************************************/
UUID::UUID(ShortUUID_t shortUUID) : type(UUID_TYPE_SHORT), baseUUID(), shortUUID(shortUUID)
UUID::UUID(ShortUUIDBytes_t shortUUID) : type(UUID_TYPE_SHORT), baseUUID(), shortUUID(shortUUID)
{
/* empty */
}

View File

@ -194,27 +194,27 @@ public:
*/
ble_error_t stopAdvertising(void);
ble_error_t disconnect(void);
ble_error_t disconnect(Gap::DisconnectionReason_t reason);
/* APIs to set GAP callbacks. */
void onTimeout(Gap::EventCallback_t timeoutCallback);
void onConnection(Gap::HandleSpecificEventCallback_t connectionCallback);
void onConnection(Gap::ConnectionEventCallback_t connectionCallback);
/**
* Used to setup a callback for GAP disconnection.
*/
void onDisconnection(Gap::HandleSpecificEventCallback_t disconnectionCallback);
void onDisconnection(Gap::DisconnectionEventCallback_t disconnectionCallback);
/**
* Setup a callback for the GATT event DATA_SENT.
*/
void onDataSent(GattServer::ServerEventCallback_t callback);
void onDataSent(GattServer::ServerEventCallbackWithCount_t callback);
/**
* Setup a callback for when a characteristic has its value updated by a
* client.
*/
void onDataWritten(GattServer::EventCallback_t callback);
void onDataWritten(GattServer::WriteEventCallback_t callback);
void onUpdatesEnabled(GattServer::EventCallback_t callback);
void onUpdatesDisabled(GattServer::EventCallback_t callback);
void onConfirmationReceived(GattServer::EventCallback_t callback);
@ -443,9 +443,9 @@ BLEDevice::stopAdvertising(void)
}
inline ble_error_t
BLEDevice::disconnect(void)
BLEDevice::disconnect(Gap::DisconnectionReason_t reason)
{
return transport->getGap().disconnect();
return transport->getGap().disconnect(reason);
}
inline void
@ -455,25 +455,25 @@ BLEDevice::onTimeout(Gap::EventCallback_t timeoutCallback)
}
inline void
BLEDevice::onConnection(Gap::HandleSpecificEventCallback_t connectionCallback)
BLEDevice::onConnection(Gap::ConnectionEventCallback_t connectionCallback)
{
transport->getGap().setOnConnection(connectionCallback);
}
inline void
BLEDevice::onDisconnection(Gap::HandleSpecificEventCallback_t disconnectionCallback)
BLEDevice::onDisconnection(Gap::DisconnectionEventCallback_t disconnectionCallback)
{
transport->getGap().setOnDisconnection(disconnectionCallback);
}
inline void
BLEDevice::onDataSent(GattServer::ServerEventCallback_t callback)
BLEDevice::onDataSent(GattServer::ServerEventCallbackWithCount_t callback)
{
transport->getGattServer().setOnDataSent(callback);
}
inline void
BLEDevice::onDataWritten(GattServer::EventCallback_t callback)
BLEDevice::onDataWritten(GattServer::WriteEventCallback_t callback)
{
transport->getGattServer().setOnDataWritten(callback);
}
@ -551,25 +551,25 @@ BLEDevice::getVersion(void)
inline ble_error_t
BLEDevice::setDeviceName(const uint8_t *deviceName)
{
return transport->getGattServer().setDeviceName(deviceName);
return transport->getGap().setDeviceName(deviceName);
}
inline ble_error_t
BLEDevice::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
{
return transport->getGattServer().getDeviceName(deviceName, lengthP);
return transport->getGap().getDeviceName(deviceName, lengthP);
}
inline ble_error_t
BLEDevice::setAppearance(uint16_t appearance)
{
return transport->getGattServer().setAppearance(appearance);
return transport->getGap().setAppearance(appearance);
}
inline ble_error_t
BLEDevice::getAppearance(uint16_t *appearanceP)
{
return transport->getGattServer().getAppearance(appearanceP);
return transport->getGap().getAppearance(appearanceP);
}
inline ble_error_t

View File

@ -40,6 +40,12 @@ public:
ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE
} addr_type_t;
enum DisconnectionReason_t {
REMOTE_USER_TERMINATED_CONNECTION,
CONN_INTERVAL_UNACCEPTABLE,
LOCAL_HOST_TERMINATED_CONNECTION,
};
/* Describes the current state of the device (more than one bit can be set) */
typedef struct GapState_s {
unsigned advertising : 1; /**< peripheral is currently advertising */
@ -61,39 +67,42 @@ public:
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 disconnect(void) = 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 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;
typedef void (*EventCallback_t)(void);
typedef void (*HandleSpecificEventCallback_t)(Handle_t);
typedef void (*ConnectionEventCallback_t)(Handle_t, const ConnectionParams_t *);
typedef void (*DisconnectionEventCallback_t)(Handle_t, DisconnectionReason_t);
/* Event callback handlers */
void setOnTimeout(EventCallback_t callback) {
onTimeout = callback;
}
void setOnConnection(HandleSpecificEventCallback_t callback) {
void setOnConnection(ConnectionEventCallback_t callback) {
onConnection = callback;
}
void setOnDisconnection(HandleSpecificEventCallback_t callback) {
void setOnDisconnection(DisconnectionEventCallback_t callback) {
onDisconnection = callback;
}
void processHandleSpecificEvent(GapEvents::gapEvent_e type, Handle_t handle) {
switch (type) {
case GapEvents::GAP_EVENT_CONNECTED:
state.connected = 1;
if (onConnection) {
onConnection(handle);
}
break;
case GapEvents::GAP_EVENT_DISCONNECTED:
state.connected = 0;
if (onDisconnection) {
onDisconnection(handle);
}
break;
void processConnectionEvent(Handle_t handle, const ConnectionParams_t *params) {
state.connected = 1;
if (onConnection) {
onConnection(handle, params);
}
}
void processDisconnectionEvent(Handle_t handle, DisconnectionReason_t reason) {
state.connected = 0;
if (onDisconnection) {
onDisconnection(handle, reason);
}
}
@ -121,9 +130,9 @@ protected:
GapState_t state;
private:
EventCallback_t onTimeout;
HandleSpecificEventCallback_t onConnection;
HandleSpecificEventCallback_t onDisconnection;
EventCallback_t onTimeout;
ConnectionEventCallback_t onConnection;
DisconnectionEventCallback_t onDisconnection;
};
#endif // ifndef __GAP_H__

View File

@ -63,23 +63,15 @@ public:
\li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 9.3
*/
/**************************************************************************/
enum AdvertisingType
{
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 */
enum AdvertisingType {
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 */
};
GapAdvertisingParams(AdvertisingType advType =
GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED,
uint16_t interval =
GAP_ADV_PARAMS_INTERVAL_MIN_NONCON,
GapAdvertisingParams(AdvertisingType advType = GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED,
uint16_t interval = GAP_ADV_PARAMS_INTERVAL_MIN_NONCON,
uint16_t timeout = 0);
virtual ~GapAdvertisingParams(void);
@ -146,5 +138,4 @@ GapAdvertisingParams::getTimeout(void) const
return _timeout;
}
#endif // ifndef __GAP_ADVERTISING_PARAMS_H__

View File

@ -38,43 +38,10 @@ public:
*/
/******************************************************************/
typedef enum gapEvent_e {
GAP_EVENT_TIMEOUT = 1, /**< Advertising timed out
*before a connection was
*established */
GAP_EVENT_CONNECTED = 2, /**< A connection was
*established with a
*central device */
GAP_EVENT_DISCONNECTED = 3 /**< A connection was
*closed or lost with a
*central device */
GAP_EVENT_TIMEOUT = 1, /**< Advertising timed out before a connection was established */
GAP_EVENT_CONNECTED = 2, /**< A connection was established with a central device */
GAP_EVENT_DISCONNECTED = 3 /**< A connection was closed or lost with a central device */
} gapEvent_t;
/******************************************************************/
/*!
\brief
Advertising timed out before a connection was established
*/
/******************************************************************/
virtual void onTimeout(void) {
}
/******************************************************************/
/*!
\brief
A connection was established with a central device
*/
/******************************************************************/
virtual void onConnected(void) {
}
/******************************************************************/
/*!
\brief
A connection was closed or lost with a central device
*/
/******************************************************************/
virtual void onDisconnected(void) {
}
};
#endif // ifndef __GAP_EVENTS_H__

View File

@ -0,0 +1,35 @@
/* 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_CHARACTERISTIC_WRITE_CB_PARAMS_H__
#define __GATT_CHARACTERISTIC_WRITE_CB_PARAMS_H__
struct GattCharacteristicWriteCBParams {
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. */
};
#endif /*__GATT_CHARACTERISTIC_WRITE_CB_PARAMS_H__*/

View File

@ -21,6 +21,7 @@
#include "blecommon.h"
#include "GattService.h"
#include "GattServerEvents.h"
#include "GattCharacteristicWriteCBParams.h"
/**************************************************************************/
/*!
@ -36,10 +37,6 @@ public:
virtual ble_error_t addService(GattService &) = 0;
virtual ble_error_t readValue(uint16_t handle, uint8_t buffer[], uint16_t *const lengthP) = 0;
virtual ble_error_t updateValue(uint16_t, uint8_t[], uint16_t, bool localOnly = false) = 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;
// 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
@ -48,11 +45,13 @@ public:
/* Event callback handlers. */
typedef void (*EventCallback_t)(uint16_t attributeHandle);
typedef void (*ServerEventCallback_t)(void); /* independent of any particular attribute */
void setOnDataSent(ServerEventCallback_t callback) {
typedef void (*WriteEventCallback_t)(uint16_t attributeHandle, const GattCharacteristicWriteCBParams *eventDataP);
typedef void (*ServerEventCallback_t)(void); /**< independent of any particular attribute */
typedef void (*ServerEventCallbackWithCount_t)(unsigned count); /**< independent of any particular attribute */
void setOnDataSent(ServerEventCallbackWithCount_t callback) {
onDataSent = callback;
}
void setOnDataWritten(EventCallback_t callback) {
void setOnDataWritten(WriteEventCallback_t callback) {
onDataWritten = callback;
}
void setOnUpdatesEnabled(EventCallback_t callback) {
@ -65,13 +64,14 @@ public:
onConfirmationReceived = callback;
}
void handleDataWrittenEvent(uint16_t charHandle, const GattCharacteristicWriteCBParams *params) {
if (onDataWritten) {
onDataWritten(charHandle, params);
}
}
void handleEvent(GattServerEvents::gattEvent_e type, uint16_t charHandle) {
switch (type) {
case GattServerEvents::GATT_EVENT_DATA_WRITTEN:
if (onDataWritten) {
onDataWritten(charHandle);
}
break;
case GattServerEvents::GATT_EVENT_UPDATES_ENABLED:
if (onUpdatesEnabled) {
onUpdatesEnabled(charHandle);
@ -90,15 +90,9 @@ public:
}
}
void handleEvent(GattServerEvents::gattEvent_e type) {
switch (type) {
case GattServerEvents::GATT_EVENT_DATA_SENT:
if (onDataSent) {
onDataSent();
}
break;
default:
break;
void handleDataSentEvent(unsigned count) {
if (onDataSent) {
onDataSent(count);
}
}
@ -113,11 +107,11 @@ protected:
uint8_t descriptorCount;
private:
ServerEventCallback_t onDataSent;
EventCallback_t onDataWritten;
EventCallback_t onUpdatesEnabled;
EventCallback_t onUpdatesDisabled;
EventCallback_t onConfirmationReceived;
ServerEventCallbackWithCount_t onDataSent;
WriteEventCallback_t onDataWritten;
EventCallback_t onUpdatesEnabled;
EventCallback_t onUpdatesDisabled;
EventCallback_t onConfirmationReceived;
};
#endif // ifndef __GATT_SERVER_H__

View File

@ -44,53 +44,6 @@ public:
GATT_EVENT_UPDATES_DISABLED = 4, /**< Notify/Indicate Disabled in CCCD */
GATT_EVENT_CONFIRMATION_RECEIVED = 5 /**< Response received from Indicate message */
} gattEvent_t;
/******************************************************************/
/*!
\brief
A message was successfully transmitted
*/
/******************************************************************/
virtual void onDataSent(uint16_t charHandle) {
}
/******************************************************************/
/*!
\brief
The GATT client (the phone, tablet, etc.) wrote data to a
characteristic or descriptor on the GATT Server (the peripheral
device).
*/
/******************************************************************/
virtual void onDataWritten(uint16_t charHandle) {
}
/******************************************************************/
/*!
\brief
A Notify or Indicate flag was enabled in the CCCD
*/
/******************************************************************/
virtual void onUpdatesEnabled(uint16_t charHandle) {
}
/******************************************************************/
/*!
\brief
A Notify or Indicate flag was disabled in the CCCD
*/
/******************************************************************/
virtual void onUpdatesDisabled(uint16_t charHandle) {
}
/******************************************************************/
/*!
\brief
A confirmation response was received from an Indicate message
*/
/******************************************************************/
virtual void onConfirmationReceived(uint16_t charHandle) {
}
};
#endif // ifndef __GATT_SERVER_EVENTS_H__

View File

@ -21,8 +21,8 @@
#include "blecommon.h"
const unsigned LENGTH_OF_LONG_UUID = 16;
typedef uint16_t ShortUUID_t;
typedef uint8_t LongUUID_t[LENGTH_OF_LONG_UUID];
typedef uint16_t ShortUUIDBytes_t;
typedef uint8_t LongUUIDBytes_t[LENGTH_OF_LONG_UUID];
class UUID
{
@ -33,8 +33,8 @@ public:
};
public:
UUID(const LongUUID_t);
UUID(ShortUUID_t);
UUID(const LongUUIDBytes_t);
UUID(ShortUUIDBytes_t);
virtual ~UUID(void);
public:
@ -44,18 +44,18 @@ public:
const uint8_t* getBaseUUID(void) const {
return baseUUID;
}
ShortUUID_t getShortUUID(void) const {
ShortUUIDBytes_t getShortUUID(void) const {
return shortUUID;
}
private:
uint8_t type; // UUID_TYPE_SHORT or UUID_TYPE_LONG
LongUUID_t baseUUID; /* the base of the long UUID (if
uint8_t type; // UUID_TYPE_SHORT or UUID_TYPE_LONG
LongUUIDBytes_t baseUUID; /* the base of the long UUID (if
* used). Note: bytes 12 and 13 (counting from LSB)
* are zeroed out to allow comparison with other long
* UUIDs which differ only in the 16-bit relative
* part.*/
ShortUUID_t shortUUID; // 16 bit uuid (byte 2-3 using with base)
ShortUUIDBytes_t shortUUID; // 16 bit uuid (byte 2-3 using with base)
};
#endif // ifndef __UUID_H__