Bluetooth: GATT: Expose ATT error codes to application callbacks

Introduce BT_GATT_ERR macro to make it possible for application
callbacks to return exact ATT error codes.

Change-Id: I971536508e75036fbddc40b3f33e5201e11940bc
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2016-02-17 14:03:20 +02:00
commit a72d967d33
8 changed files with 55 additions and 51 deletions

View file

@ -301,7 +301,7 @@ int bt_gatt_attr_read_ccc(struct bt_conn *conn,
const struct bt_gatt_attr *attr, void *buf,
uint16_t len, uint16_t offset)
{
return -ENOSYS;
return BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED);
}
int bt_gatt_attr_write_ccc(struct bt_conn *conn,
@ -312,11 +312,11 @@ int bt_gatt_attr_write_ccc(struct bt_conn *conn,
const uint16_t *data = buf;
if (offset > sizeof(*data)) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
if (offset + len > sizeof(*data)) {
return -EFBIG;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
/* We expect to receive this only when the has really changed */
@ -346,14 +346,14 @@ int bt_gatt_attr_read_cud(struct bt_conn *conn,
const struct bt_gatt_attr *attr, void *buf,
uint16_t len, uint16_t offset)
{
return -ENOSYS;
return BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED);
}
int bt_gatt_attr_read_cpf(struct bt_conn *conn,
const struct bt_gatt_attr *attr, void *buf,
uint16_t len, uint16_t offset)
{
return -ENOSYS;
return BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED);
}
int bt_gatt_notify(struct bt_conn *conn, const struct bt_gatt_attr *attr,

View file

@ -88,6 +88,17 @@ extern "C" {
*/
#define BT_GATT_FLUSH_SYNC 0x01
/** @def BT_GATT_ERR
* @brief Construct error return value for attribute read, write and
* flush callbacks.
*
* @param _att_err ATT error code
*
* @return Appropriate error code for the attribute callbacks.
*
*/
#define BT_GATT_ERR(_att_err) (-(_att_err))
/** @brief GATT Attribute structure. */
struct bt_gatt_attr {
/** Attribute UUID */

View file

@ -571,16 +571,11 @@ static uint8_t err_to_att(int err)
{
BT_DBG("%d", err);
switch (err) {
case -EINVAL:
return BT_ATT_ERR_INVALID_OFFSET;
case -EFBIG:
return BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
case -EACCES:
return BT_ATT_ERR_ENCRYPTION_KEY_SIZE;
default:
return BT_ATT_ERR_UNLIKELY;
if (err < 0 && err >= -0xff) {
return -err;
}
return BT_ATT_ERR_UNLIKELY;
}
struct read_type_data {

View file

@ -316,11 +316,11 @@ int bt_gatt_attr_write_ccc(struct bt_conn *conn,
size_t i;
if (offset > sizeof(*data)) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
if (offset + len > sizeof(*data)) {
return -EFBIG;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
if (bt_keys_find_addr(&conn->le.dst))
@ -348,7 +348,7 @@ int bt_gatt_attr_write_ccc(struct bt_conn *conn,
if (i == ccc->cfg_len) {
BT_WARN("No space to store CCC cfg");
return -ENOMEM;
return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES);
}
}

View file

@ -141,7 +141,7 @@ static int write_ct(struct bt_conn *conn, const struct bt_gatt_attr *attr,
uint8_t *value = attr->user_data;
if (offset + len > sizeof(ct)) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
memcpy(value + offset, buf, len);
@ -198,7 +198,7 @@ static int write_vnd(struct bt_conn *conn, const struct bt_gatt_attr *attr,
uint8_t *value = attr->user_data;
if (offset + len > sizeof(vnd_value)) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
memcpy(value + offset, buf, len);
@ -233,7 +233,7 @@ static int write_long_vnd(struct bt_conn *conn,
struct vnd_long_value *value = attr->user_data;
if (offset + len > sizeof(value->buf)) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
/* Copy to buffer */
@ -258,7 +258,7 @@ static int flush_long_vnd(struct bt_conn *conn,
return 0;
}
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
}
static const struct bt_uuid_128 vnd_long_uuid = BT_UUID_INIT_128(
@ -286,7 +286,7 @@ static int write_signed(struct bt_conn *conn, const struct bt_gatt_attr *attr,
uint8_t *value = attr->user_data;
if (offset + len > sizeof(signed_value)) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
memcpy(value + offset, buf, len);

View file

@ -238,12 +238,11 @@ static int write_ctrl_point(struct bt_conn *conn,
int i;
if (!ctrl_point_configured) {
/* TODO: Return CSC_ERR_CCC_CONFIG */
return -EINVAL;
return BT_GATT_ERR(CSC_ERR_CCC_CONFIG);
}
if (!len) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
switch (req->op) {

View file

@ -328,15 +328,16 @@ static int write_temp_trigger_setting(struct bt_conn *conn,
uint16_t offset)
{
const struct write_es_trigger_setting_req *req = buf;
const struct es_trigger_setting_reference *ref;
struct temperature_sensor *sensor = attr->user_data;
uint16_t ref_val;
if (!len) {
return -EFBIG;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
if (req->condition > 0x09) {
/* TODO: Return ESS_ERR_COND_NOT_SUPP */
return -EINVAL;
return BT_GATT_ERR(ESS_ERR_COND_NOT_SUPP);
}
switch (req->condition) {
@ -345,7 +346,7 @@ static int write_temp_trigger_setting(struct bt_conn *conn,
/* fallthrough */
case ESS_VALUE_CHANGED:
if (len != sizeof(sensor->condition)) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
sensor->condition = req->condition;
@ -355,31 +356,29 @@ static int write_temp_trigger_setting(struct bt_conn *conn,
/* fallthrough */
case ESS_NO_LESS_THAN_SPECIFIED_TIME:
if (len != sizeof(struct es_trigger_setting_seconds)) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
sensor->condition = req->condition;
sensor->seconds = le24_to_int(req->operand);
break;
/* Reference temperature */
default: {
const struct es_trigger_setting_reference *req = buf;
uint16_t ref_val = sys_le16_to_cpu(req->ref_val);
if (len != sizeof(*req)) {
return -EINVAL;
default:
if (len != sizeof(*ref)) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
ref = buf;
ref_val = sys_le16_to_cpu(ref->ref_val);
if (sensor->lower_limit > ref_val ||
sensor->upper_limit < ref_val) {
/* TODO: Return ERR_OUT_OF_RANGE */
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_OUT_OF_RANGE);
}
sensor->condition = req->condition;
sensor->ref_val = ref_val;
}
}
return len;
}

View file

@ -231,7 +231,7 @@ static int read_value(struct bt_conn *conn, const struct bt_gatt_attr *attr,
if ((attr->perm & GATT_PERM_ENC_READ_MASK) &&
(value->enc_key_size > bt_conn_enc_key_size(conn))) {
return -EACCES;
return BT_GATT_ERR(BT_ATT_ERR_ENCRYPTION_KEY_SIZE);
}
return bt_gatt_attr_read(conn, attr, buf, len, offset, value->data,
@ -245,7 +245,7 @@ static int write_value(struct bt_conn *conn, const struct bt_gatt_attr *attr,
if ((attr->perm & GATT_PERM_ENC_WRITE_MASK) &&
(value->enc_key_size > bt_conn_enc_key_size(conn))) {
return -EACCES;
return BT_GATT_ERR(BT_ATT_ERR_ENCRYPTION_KEY_SIZE);
}
/*
@ -254,11 +254,11 @@ static int write_value(struct bt_conn *conn, const struct bt_gatt_attr *attr,
* «Invalid Offset».
*/
if (offset > value->len) {
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
if (offset + len > value->len) {
return -EFBIG;
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
memcpy(value->prep_data + offset, buf, len);
@ -281,7 +281,7 @@ static int flush_value(struct bt_conn *conn,
return 0;
}
return -EINVAL;
return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
}
static struct bt_gatt_attr chr = BT_GATT_CHARACTERISTIC(NULL, 0);