mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #5592 from pan-/ble-nordic-fix-gatt-server-write
BLE: Fix GattServer::write on Nordic targets.pull/5586/merge
commit
1498a807c7
|
@ -26,6 +26,34 @@
|
||||||
|
|
||||||
#include "nRF5xn.h"
|
#include "nRF5xn.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static ble_error_t set_attribute_value(
|
||||||
|
Gap::Handle_t connectionHandle,
|
||||||
|
GattAttribute::Handle_t attributeHandle,
|
||||||
|
ble_gatts_value_t *value
|
||||||
|
) {
|
||||||
|
uint32_t err = sd_ble_gatts_value_set(connectionHandle, attributeHandle, value);
|
||||||
|
switch(err) {
|
||||||
|
case NRF_SUCCESS:
|
||||||
|
return BLE_ERROR_NONE;
|
||||||
|
case NRF_ERROR_INVALID_ADDR:
|
||||||
|
case NRF_ERROR_INVALID_PARAM:
|
||||||
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
|
case NRF_ERROR_NOT_FOUND:
|
||||||
|
case NRF_ERROR_DATA_SIZE:
|
||||||
|
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||||
|
case BLE_ERROR_GATTS_INVALID_ATTR_TYPE:
|
||||||
|
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||||
|
case NRF_ERROR_FORBIDDEN:
|
||||||
|
return BLE_ERROR_OPERATION_NOT_PERMITTED;
|
||||||
|
default:
|
||||||
|
return BLE_ERROR_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of anonymous namespace
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Adds a new service to the GATT table on the peripheral
|
@brief Adds a new service to the GATT table on the peripheral
|
||||||
|
@ -244,53 +272,52 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute
|
||||||
nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap();
|
nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap();
|
||||||
connectionHandle = gap.getConnectionHandle();
|
connectionHandle = gap.getConnectionHandle();
|
||||||
}
|
}
|
||||||
error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params);
|
|
||||||
if (error != ERROR_NONE) {
|
|
||||||
switch (error) {
|
|
||||||
case ERROR_BLE_NO_TX_BUFFERS: /* Notifications consume application buffers. The return value can be used for resending notifications. */
|
|
||||||
case ERROR_BUSY:
|
|
||||||
returnValue = BLE_STACK_BUSY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ERROR_INVALID_STATE:
|
bool updatesEnabled = false;
|
||||||
case ERROR_BLEGATTS_SYS_ATTR_MISSING:
|
if (connectionHandle != BLE_CONN_HANDLE_INVALID) {
|
||||||
returnValue = BLE_ERROR_INVALID_STATE;
|
ble_error_t err = areUpdatesEnabled(connectionHandle, attributeHandle, &updatesEnabled);
|
||||||
break;
|
// FIXME: The softdevice allocates and populates CCCD when the client
|
||||||
|
// interract with them. Checking for updates may return an out of
|
||||||
default :
|
// range error in such case.
|
||||||
ASSERT_INT( ERROR_NONE,
|
if(err && err != BLE_ERROR_PARAM_OUT_OF_RANGE) {
|
||||||
sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
|
return err;
|
||||||
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
|
||||||
|
|
||||||
/* Notifications consume application buffers. The return value can
|
|
||||||
* be used for resending notifications. */
|
|
||||||
returnValue = BLE_STACK_BUSY;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
uint32_t err = sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value);
|
if (updatesEnabled) {
|
||||||
switch(err) {
|
error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params);
|
||||||
case NRF_SUCCESS:
|
if (error != ERROR_NONE) {
|
||||||
returnValue = BLE_ERROR_NONE;
|
switch (error) {
|
||||||
break;
|
case ERROR_BLE_NO_TX_BUFFERS: /* Notifications consume application buffers. The return value can be used for resending notifications. */
|
||||||
case NRF_ERROR_INVALID_ADDR:
|
case ERROR_BUSY:
|
||||||
case NRF_ERROR_INVALID_PARAM:
|
returnValue = BLE_STACK_BUSY;
|
||||||
returnValue = BLE_ERROR_INVALID_PARAM;
|
break;
|
||||||
break;
|
|
||||||
case NRF_ERROR_NOT_FOUND:
|
case ERROR_INVALID_STATE:
|
||||||
case NRF_ERROR_DATA_SIZE:
|
case ERROR_BLEGATTS_SYS_ATTR_MISSING:
|
||||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
returnValue = BLE_ERROR_INVALID_STATE;
|
||||||
case BLE_ERROR_GATTS_INVALID_ATTR_TYPE:
|
break;
|
||||||
returnValue = BLE_ERROR_PARAM_OUT_OF_RANGE;
|
|
||||||
break;
|
default :
|
||||||
case NRF_ERROR_FORBIDDEN:
|
ASSERT_INT( ERROR_NONE,
|
||||||
returnValue = BLE_ERROR_OPERATION_NOT_PERMITTED;
|
sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
|
||||||
break;
|
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
||||||
default:
|
|
||||||
returnValue = BLE_ERROR_UNSPECIFIED;
|
if (connectionHandle == BLE_CONN_HANDLE_INVALID) {
|
||||||
break;
|
returnValue = BLE_ERROR_NONE;
|
||||||
|
} else {
|
||||||
|
/* Notifications consume application buffers. The return value can
|
||||||
|
* be used for resending notifications. */
|
||||||
|
returnValue = BLE_STACK_BUSY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
returnValue = set_attribute_value(connectionHandle, attributeHandle, &value);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
returnValue = set_attribute_value(connectionHandle, attributeHandle, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
|
@ -305,7 +332,12 @@ ble_error_t nRF5xGattServer::areUpdatesEnabled(const GattCharacteristic &charact
|
||||||
|
|
||||||
ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP)
|
ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP)
|
||||||
{
|
{
|
||||||
int characteristicIndex = resolveValueHandleToCharIndex(characteristic.getValueHandle());
|
return areUpdatesEnabled(connectionHandle, characteristic.getValueHandle(), enabledP);
|
||||||
|
}
|
||||||
|
|
||||||
|
ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, bool *enabledP)
|
||||||
|
{
|
||||||
|
int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle);
|
||||||
if (characteristicIndex == -1) {
|
if (characteristicIndex == -1) {
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,15 @@ private:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query if updates of a characteristics are enabled for a given connection.
|
||||||
|
*/
|
||||||
|
ble_error_t areUpdatesEnabled(
|
||||||
|
Gap::Handle_t connectionHandle,
|
||||||
|
GattAttribute::Handle_t valueHandle,
|
||||||
|
bool *enabledP
|
||||||
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GattCharacteristic *p_characteristics[BLE_TOTAL_CHARACTERISTICS];
|
GattCharacteristic *p_characteristics[BLE_TOTAL_CHARACTERISTICS];
|
||||||
ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS];
|
ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS];
|
||||||
|
|
|
@ -65,8 +65,32 @@ static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_reply = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ble_error_t set_attribute_value(
|
||||||
|
Gap::Handle_t connectionHandle,
|
||||||
|
GattAttribute::Handle_t attributeHandle,
|
||||||
|
ble_gatts_value_t *value
|
||||||
|
) {
|
||||||
|
uint32_t err = sd_ble_gatts_value_set(connectionHandle, attributeHandle, value);
|
||||||
|
switch(err) {
|
||||||
|
case NRF_SUCCESS:
|
||||||
|
return BLE_ERROR_NONE;
|
||||||
|
case NRF_ERROR_INVALID_ADDR:
|
||||||
|
case NRF_ERROR_INVALID_PARAM:
|
||||||
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
|
case NRF_ERROR_NOT_FOUND:
|
||||||
|
case NRF_ERROR_DATA_SIZE:
|
||||||
|
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||||
|
case BLE_ERROR_GATTS_INVALID_ATTR_TYPE:
|
||||||
|
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||||
|
case NRF_ERROR_FORBIDDEN:
|
||||||
|
return BLE_ERROR_OPERATION_NOT_PERMITTED;
|
||||||
|
default:
|
||||||
|
return BLE_ERROR_UNSPECIFIED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // end of anonymous namespace
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Adds a new service to the GATT table on the peripheral
|
@brief Adds a new service to the GATT table on the peripheral
|
||||||
|
@ -285,53 +309,49 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute
|
||||||
nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap();
|
nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap();
|
||||||
connectionHandle = gap.getConnectionHandle();
|
connectionHandle = gap.getConnectionHandle();
|
||||||
}
|
}
|
||||||
error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params);
|
|
||||||
if (error != ERROR_NONE) {
|
|
||||||
switch (error) {
|
|
||||||
case ERROR_BLE_NO_TX_BUFFERS: /* Notifications consume application buffers. The return value can be used for resending notifications. */
|
|
||||||
case ERROR_BUSY:
|
|
||||||
returnValue = BLE_STACK_BUSY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ERROR_INVALID_STATE:
|
bool updatesEnabled = false;
|
||||||
case ERROR_BLEGATTS_SYS_ATTR_MISSING:
|
if (connectionHandle != BLE_CONN_HANDLE_INVALID) {
|
||||||
returnValue = BLE_ERROR_INVALID_STATE;
|
ble_error_t err = areUpdatesEnabled(connectionHandle, attributeHandle, &updatesEnabled);
|
||||||
break;
|
|
||||||
|
|
||||||
default :
|
// FIXME: The softdevice allocates and populates CCCD when the client
|
||||||
ASSERT_INT( ERROR_NONE,
|
// interract with them. Checking for updates may return an out of
|
||||||
sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
|
// range error in such case.
|
||||||
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
if(err && err != BLE_ERROR_PARAM_OUT_OF_RANGE) {
|
||||||
|
return err;
|
||||||
/* Notifications consume application buffers. The return value can
|
|
||||||
* be used for resending notifications. */
|
|
||||||
returnValue = BLE_STACK_BUSY;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
uint32_t err = sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value);
|
if (updatesEnabled) {
|
||||||
switch(err) {
|
error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params);
|
||||||
case NRF_SUCCESS:
|
if (error != ERROR_NONE) {
|
||||||
returnValue = BLE_ERROR_NONE;
|
switch (error) {
|
||||||
break;
|
case ERROR_BLE_NO_TX_BUFFERS: /* Notifications consume application buffers. The return value can be used for resending notifications. */
|
||||||
case NRF_ERROR_INVALID_ADDR:
|
case ERROR_BUSY:
|
||||||
case NRF_ERROR_INVALID_PARAM:
|
returnValue = BLE_STACK_BUSY;
|
||||||
returnValue = BLE_ERROR_INVALID_PARAM;
|
break;
|
||||||
break;
|
|
||||||
case NRF_ERROR_NOT_FOUND:
|
case ERROR_INVALID_STATE:
|
||||||
case NRF_ERROR_DATA_SIZE:
|
case ERROR_BLEGATTS_SYS_ATTR_MISSING:
|
||||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
returnValue = BLE_ERROR_INVALID_STATE;
|
||||||
case BLE_ERROR_GATTS_INVALID_ATTR_TYPE:
|
break;
|
||||||
returnValue = BLE_ERROR_PARAM_OUT_OF_RANGE;
|
|
||||||
break;
|
default :
|
||||||
case NRF_ERROR_FORBIDDEN:
|
ASSERT_INT( ERROR_NONE,
|
||||||
returnValue = BLE_ERROR_OPERATION_NOT_PERMITTED;
|
sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
|
||||||
break;
|
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
||||||
default:
|
|
||||||
returnValue = BLE_ERROR_UNSPECIFIED;
|
/* Notifications consume application buffers. The return value can
|
||||||
break;
|
* be used for resending notifications. */
|
||||||
|
returnValue = BLE_STACK_BUSY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
returnValue = set_attribute_value(connectionHandle, attributeHandle, &value);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
returnValue = set_attribute_value(connectionHandle, attributeHandle, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
|
@ -346,7 +366,12 @@ ble_error_t nRF5xGattServer::areUpdatesEnabled(const GattCharacteristic &charact
|
||||||
|
|
||||||
ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP)
|
ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP)
|
||||||
{
|
{
|
||||||
int characteristicIndex = resolveValueHandleToCharIndex(characteristic.getValueHandle());
|
return areUpdatesEnabled(connectionHandle, characteristic.getValueHandle(), enabledP);
|
||||||
|
}
|
||||||
|
|
||||||
|
ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, bool *enabledP)
|
||||||
|
{
|
||||||
|
int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle);
|
||||||
if (characteristicIndex == -1) {
|
if (characteristicIndex == -1) {
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,15 @@ private:
|
||||||
*/
|
*/
|
||||||
void releaseAllWriteRequests();
|
void releaseAllWriteRequests();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query if updates of a characteristics are enabled for a given connection.
|
||||||
|
*/
|
||||||
|
ble_error_t areUpdatesEnabled(
|
||||||
|
Gap::Handle_t connectionHandle,
|
||||||
|
GattAttribute::Handle_t valueHandle,
|
||||||
|
bool *enabledP
|
||||||
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GattCharacteristic *p_characteristics[BLE_TOTAL_CHARACTERISTICS];
|
GattCharacteristic *p_characteristics[BLE_TOTAL_CHARACTERISTICS];
|
||||||
ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS];
|
ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS];
|
||||||
|
|
Loading…
Reference in New Issue