From a72d967d338af41bca90da7d5046de9e89d6ab96 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 17 Feb 2016 14:03:20 +0200 Subject: [PATCH] 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 --- drivers/nble/gatt.c | 10 ++--- include/bluetooth/gatt.h | 11 ++++++ net/bluetooth/att.c | 13 ++----- net/bluetooth/gatt.c | 6 +-- samples/bluetooth/peripheral/src/main.c | 10 ++--- samples/bluetooth/peripheral_csc/src/main.c | 5 +-- samples/bluetooth/peripheral_esp/src/main.c | 41 ++++++++++----------- tests/bluetooth/tester/src/gatt.c | 10 ++--- 8 files changed, 55 insertions(+), 51 deletions(-) diff --git a/drivers/nble/gatt.c b/drivers/nble/gatt.c index 897c2c639d7..0aec2267449 100644 --- a/drivers/nble/gatt.c +++ b/drivers/nble/gatt.c @@ -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, diff --git a/include/bluetooth/gatt.h b/include/bluetooth/gatt.h index 7e78992fa67..d57b1c4336f 100644 --- a/include/bluetooth/gatt.h +++ b/include/bluetooth/gatt.h @@ -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 */ diff --git a/net/bluetooth/att.c b/net/bluetooth/att.c index 5f2e68bd5e0..351d86929a6 100644 --- a/net/bluetooth/att.c +++ b/net/bluetooth/att.c @@ -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 { diff --git a/net/bluetooth/gatt.c b/net/bluetooth/gatt.c index 74cd5c94d3b..7c952c5694e 100644 --- a/net/bluetooth/gatt.c +++ b/net/bluetooth/gatt.c @@ -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); } } diff --git a/samples/bluetooth/peripheral/src/main.c b/samples/bluetooth/peripheral/src/main.c index b13b7ad155f..08ab9a494d9 100644 --- a/samples/bluetooth/peripheral/src/main.c +++ b/samples/bluetooth/peripheral/src/main.c @@ -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); diff --git a/samples/bluetooth/peripheral_csc/src/main.c b/samples/bluetooth/peripheral_csc/src/main.c index eeaa280551c..04f985f678d 100644 --- a/samples/bluetooth/peripheral_csc/src/main.c +++ b/samples/bluetooth/peripheral_csc/src/main.c @@ -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) { diff --git a/samples/bluetooth/peripheral_esp/src/main.c b/samples/bluetooth/peripheral_esp/src/main.c index 3dbc10b2403..a557410603c 100644 --- a/samples/bluetooth/peripheral_esp/src/main.c +++ b/samples/bluetooth/peripheral_esp/src/main.c @@ -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,30 +356,28 @@ 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; - } - - if (sensor->lower_limit > ref_val || - sensor->upper_limit < ref_val) { - /* TODO: Return ERR_OUT_OF_RANGE */ - return -EINVAL; - } - - sensor->condition = req->condition; - sensor->ref_val = ref_val; + 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) { + return BT_GATT_ERR(BT_ATT_ERR_OUT_OF_RANGE); + } + + sensor->condition = req->condition; + sensor->ref_val = ref_val; } return len; diff --git a/tests/bluetooth/tester/src/gatt.c b/tests/bluetooth/tester/src/gatt.c index 35f74340353..ee0a18c3443 100644 --- a/tests/bluetooth/tester/src/gatt.c +++ b/tests/bluetooth/tester/src/gatt.c @@ -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);