Bluetooth: ATT: Add support EATT bearer
This adds support for EATT bearer which was introduced in 5.2, they work as extra channels to have GATT traffic, at the moment it is completely transparent to application when they are in use since the allocation happens automatically. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
d148f8648b
commit
f4192bda26
6 changed files with 978 additions and 440 deletions
|
@ -872,6 +872,17 @@ struct bt_gatt_notify_params {
|
|||
int bt_gatt_notify_cb(struct bt_conn *conn,
|
||||
struct bt_gatt_notify_params *params);
|
||||
|
||||
/** @brief Notify multiple attribute value change.
|
||||
*
|
||||
* @param conn Connection object.
|
||||
* @param num_params Number of notification parameters.
|
||||
* @param params Notification parameters.
|
||||
*
|
||||
* @return 0 in case of success or negative value in case of error.
|
||||
*/
|
||||
int bt_gatt_notify_multiple(struct bt_conn *conn, u16_t num_params,
|
||||
struct bt_gatt_notify_params *params);
|
||||
|
||||
/** @brief Notify attribute value change.
|
||||
*
|
||||
* Send notification of attribute value change, if connection is NULL notify
|
||||
|
|
|
@ -34,6 +34,49 @@ config BT_ATT_TX_MAX
|
|||
amount the calls will block until an existing queued PDU gets
|
||||
sent.
|
||||
|
||||
config BT_EATT
|
||||
bool "Enhanced ATT Bearers support [EXPERIMENTAL]"
|
||||
depends on BT_L2CAP_DYNAMIC_CHANNEL
|
||||
help
|
||||
This option enables support for Enhanced ATT bearers support. When
|
||||
enabled additional L2CAP channels can be connected as bearers enabling
|
||||
multiple outstanding request.
|
||||
|
||||
if BT_EATT
|
||||
|
||||
config BT_EATT_MAX
|
||||
int "Maximum number of Enhanced ATT bearers"
|
||||
default 3
|
||||
range 1 16
|
||||
|
||||
help
|
||||
Number of Enhanced ATT bearers available.
|
||||
|
||||
config BT_EATT_RX_MTU
|
||||
int "Maximum supported Enhanced ATT MTU for incoming data"
|
||||
default 70
|
||||
range 70 519
|
||||
depends on BT_EATT
|
||||
help
|
||||
Maximum size incoming PDUs on EATT bearers, value shall include L2CAP
|
||||
headers and SDU length, maximum is limited to 512 bytes payload, which
|
||||
is the maximum size for a GATT attribute, plus 1 byte for ATT opcode.
|
||||
This option influences the stack buffer size and by that may also
|
||||
limit the outgoing MTU.
|
||||
|
||||
config BT_EATT_SEC_LEVEL
|
||||
int "Enhanced ATT bearer security level"
|
||||
default 1
|
||||
range 1 4
|
||||
help
|
||||
L2CAP server required security level of EATT bearers:
|
||||
Level 1 (BT_SECURITY_L1) = No encryption or authentication required
|
||||
Level 2 (BT_SECURITY_L2) = Only encryption required
|
||||
Level 3 (BT_SECURITY_L3) = Encryption and authentication required
|
||||
Level 4 (BT_SECURITY_L4) = Secure connection required
|
||||
|
||||
endif # BT_EATT
|
||||
|
||||
config BT_GATT_SERVICE_CHANGED
|
||||
bool "GATT Service Changed support"
|
||||
default y
|
||||
|
|
|
@ -8,8 +8,10 @@ menu "L2CAP Options"
|
|||
config BT_L2CAP_RX_MTU
|
||||
int "Maximum supported L2CAP MTU for incoming data"
|
||||
default 200 if BT_BREDR
|
||||
default BT_EATT_RX_MTU if BT_EATT
|
||||
default 65 if BT_SMP
|
||||
default 23
|
||||
range 70 1300 if BT_EATT
|
||||
range 65 1300 if BT_SMP
|
||||
range 23 1300
|
||||
depends on BT_HCI_ACL_FLOW_CONTROL
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -298,3 +298,9 @@ int bt_att_req_send(struct bt_conn *conn, struct bt_att_req *req);
|
|||
|
||||
/* Cancel ATT request */
|
||||
void bt_att_req_cancel(struct bt_conn *conn, struct bt_att_req *req);
|
||||
|
||||
/* Connect EATT channels */
|
||||
int bt_eatt_connect(struct bt_conn *conn, u8_t num_channels);
|
||||
|
||||
/* Disconnect EATT channels */
|
||||
int bt_eatt_disconnect(struct bt_conn *conn);
|
||||
|
|
|
@ -71,6 +71,7 @@ struct gatt_sub {
|
|||
#endif /* CONFIG_BT_GATT_CLIENT */
|
||||
|
||||
static struct gatt_sub subscriptions[SUB_MAX];
|
||||
|
||||
static const u16_t gap_appearance = CONFIG_BT_DEVICE_APPEARANCE;
|
||||
|
||||
#if defined(CONFIG_BT_GATT_DYNAMIC_DB)
|
||||
|
@ -401,7 +402,14 @@ enum {
|
|||
CF_NUM_FLAGS,
|
||||
};
|
||||
|
||||
#define CF_ROBUST_CACHING(_cfg) (_cfg->data[0] & BIT(0))
|
||||
#define CF_BIT_ROBUST_CACHING 0
|
||||
#define CF_BIT_EATT 1
|
||||
#define CF_BIT_LAST CF_BIT_EATT
|
||||
|
||||
#define CF_BYTE_LAST (CF_BIT_LAST % 8)
|
||||
|
||||
#define CF_ROBUST_CACHING(_cfg) (_cfg->data[0] & BIT(CF_BIT_ROBUST_CACHING))
|
||||
#define CF_EATT(_cfg) (_cfg->data[0] & BIT(CF_BIT_EATT))
|
||||
|
||||
struct gatt_cf_cfg {
|
||||
u8_t id;
|
||||
|
@ -463,15 +471,15 @@ static ssize_t cf_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
|||
static bool cf_set_value(struct gatt_cf_cfg *cfg, const u8_t *value, u16_t len)
|
||||
{
|
||||
u16_t i;
|
||||
u8_t last_byte = 1U;
|
||||
u8_t last_bit = 1U;
|
||||
u8_t last_byte = CF_BYTE_LAST;
|
||||
u8_t last_bit = CF_BIT_LAST;
|
||||
|
||||
/* Validate the bits */
|
||||
for (i = 0U; i < len && i < last_byte; i++) {
|
||||
for (i = 0U; i < len && i <= last_byte; i++) {
|
||||
u8_t chg_bits = value[i] ^ cfg->data[i];
|
||||
u8_t bit;
|
||||
|
||||
for (bit = 0U; bit < last_bit; bit++) {
|
||||
for (bit = 0U; bit <= last_bit; bit++) {
|
||||
/* A client shall never clear a bit it has set */
|
||||
if ((BIT(bit) & chg_bits) &&
|
||||
(BIT(bit) & cfg->data[i])) {
|
||||
|
@ -716,6 +724,20 @@ static void remove_cf_cfg(struct bt_conn *conn)
|
|||
atomic_clear_bit(cfg->flags, CF_OUT_OF_SYNC);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_EATT)
|
||||
#define SF_BIT_EATT 0
|
||||
#define SF_BIT_LAST SF_BIT_EATT
|
||||
|
||||
static ssize_t sf_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, u16_t len, u16_t offset)
|
||||
{
|
||||
u8_t value = BIT(SF_BIT_EATT);
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, &value,
|
||||
sizeof(value));
|
||||
}
|
||||
#endif /* CONFIG_BT_EATT */
|
||||
#endif /* CONFIG_BT_GATT_CACHING */
|
||||
|
||||
BT_GATT_SERVICE_DEFINE(_1_gatt_svc,
|
||||
|
@ -737,6 +759,11 @@ BT_GATT_SERVICE_DEFINE(_1_gatt_svc,
|
|||
BT_GATT_CHARACTERISTIC(BT_UUID_GATT_DB_HASH,
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
db_hash_read, NULL, NULL),
|
||||
#if defined(CONFIG_BT_EATT)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SERVER_FEATURES,
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
sf_read, NULL, NULL),
|
||||
#endif /* CONFIG_BT_EATT */
|
||||
#endif /* CONFIG_BT_GATT_CACHING */
|
||||
#endif /* CONFIG_BT_GATT_SERVICE_CHANGED */
|
||||
);
|
||||
|
@ -3270,9 +3297,8 @@ static int gatt_read_uuid(struct bt_conn *conn,
|
|||
}
|
||||
|
||||
#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
|
||||
static void gatt_read_multiple_rsp(struct bt_conn *conn, u8_t err,
|
||||
const void *pdu, u16_t length,
|
||||
void *user_data)
|
||||
static void gatt_read_mult_rsp(struct bt_conn *conn, u8_t err, const void *pdu,
|
||||
u16_t length, void *user_data)
|
||||
{
|
||||
struct bt_gatt_read_params *params = user_data;
|
||||
|
||||
|
@ -3289,8 +3315,8 @@ static void gatt_read_multiple_rsp(struct bt_conn *conn, u8_t err,
|
|||
params->func(conn, 0, params, NULL, 0);
|
||||
}
|
||||
|
||||
static int gatt_read_multiple(struct bt_conn *conn,
|
||||
struct bt_gatt_read_params *params)
|
||||
static int gatt_read_mult(struct bt_conn *conn,
|
||||
struct bt_gatt_read_params *params)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
u8_t i;
|
||||
|
@ -3305,10 +3331,10 @@ static int gatt_read_multiple(struct bt_conn *conn,
|
|||
net_buf_add_le16(buf, params->handles[i]);
|
||||
}
|
||||
|
||||
return gatt_send(conn, buf, gatt_read_multiple_rsp, params, NULL);
|
||||
return gatt_send(conn, buf, gatt_read_mult_rsp, params, NULL);
|
||||
}
|
||||
#else
|
||||
static int gatt_read_multiple(struct bt_conn *conn,
|
||||
static int gatt_read_mult(struct bt_conn *conn,
|
||||
struct bt_gatt_read_params *params)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
|
@ -3332,7 +3358,7 @@ int bt_gatt_read(struct bt_conn *conn, struct bt_gatt_read_params *params)
|
|||
}
|
||||
|
||||
if (params->handle_count > 1) {
|
||||
return gatt_read_multiple(conn, params);
|
||||
return gatt_read_mult(conn, params);
|
||||
}
|
||||
|
||||
if (params->single.offset) {
|
||||
|
@ -3369,6 +3395,7 @@ int bt_gatt_write_without_response_cb(struct bt_conn *conn, u16_t handle,
|
|||
{
|
||||
struct net_buf *buf;
|
||||
struct bt_att_write_cmd *cmd;
|
||||
size_t write;
|
||||
|
||||
__ASSERT(conn, "invalid parameters\n");
|
||||
__ASSERT(handle, "invalid parameters\n");
|
||||
|
@ -3397,8 +3424,14 @@ int bt_gatt_write_without_response_cb(struct bt_conn *conn, u16_t handle,
|
|||
|
||||
cmd = net_buf_add(buf, sizeof(*cmd));
|
||||
cmd->handle = sys_cpu_to_le16(handle);
|
||||
memcpy(cmd->value, data, length);
|
||||
net_buf_add(buf, length);
|
||||
|
||||
write = net_buf_append_bytes(buf, length, data, K_NO_WAIT, NULL, NULL);
|
||||
if (write != length) {
|
||||
BT_WARN("Unable to allocate length %u: only %zu written",
|
||||
length, write);
|
||||
net_buf_unref(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
BT_DBG("handle 0x%04x length %u", handle, length);
|
||||
|
||||
|
@ -3455,6 +3488,7 @@ static int gatt_prepare_write(struct bt_conn *conn,
|
|||
struct net_buf *buf;
|
||||
struct bt_att_prepare_write_req *req;
|
||||
u16_t len;
|
||||
size_t write;
|
||||
|
||||
len = MIN(params->length, bt_att_get_mtu(conn) - sizeof(*req) - 1);
|
||||
|
||||
|
@ -3467,13 +3501,15 @@ static int gatt_prepare_write(struct bt_conn *conn,
|
|||
req = net_buf_add(buf, sizeof(*req));
|
||||
req->handle = sys_cpu_to_le16(params->handle);
|
||||
req->offset = sys_cpu_to_le16(params->offset);
|
||||
memcpy(req->value, params->data, len);
|
||||
net_buf_add(buf, len);
|
||||
|
||||
/* Append as much as possible */
|
||||
write = net_buf_append_bytes(buf, len, params->data, K_NO_WAIT,
|
||||
NULL, NULL);
|
||||
|
||||
/* Update params */
|
||||
params->offset += len;
|
||||
params->offset += write;
|
||||
params->data = (const u8_t *)params->data + len;
|
||||
params->length -= len;
|
||||
params->length -= write;
|
||||
|
||||
BT_DBG("handle 0x%04x offset %u len %u", params->handle, params->offset,
|
||||
params->length);
|
||||
|
@ -3485,6 +3521,7 @@ int bt_gatt_write(struct bt_conn *conn, struct bt_gatt_write_params *params)
|
|||
{
|
||||
struct net_buf *buf;
|
||||
struct bt_att_write_req *req;
|
||||
size_t write;
|
||||
|
||||
__ASSERT(conn, "invalid parameters\n");
|
||||
__ASSERT(params && params->func, "invalid parameters\n");
|
||||
|
@ -3508,8 +3545,13 @@ int bt_gatt_write(struct bt_conn *conn, struct bt_gatt_write_params *params)
|
|||
|
||||
req = net_buf_add(buf, sizeof(*req));
|
||||
req->handle = sys_cpu_to_le16(params->handle);
|
||||
memcpy(req->value, params->data, params->length);
|
||||
net_buf_add(buf, params->length);
|
||||
|
||||
write = net_buf_append_bytes(buf, params->length, params->data,
|
||||
K_NO_WAIT, NULL, NULL);
|
||||
if (write != params->length) {
|
||||
net_buf_unref(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
BT_DBG("handle 0x%04x length %u", params->handle, params->length);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue