summaryrefslogtreecommitdiff
path: root/src/gatt-database.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2019-12-26 14:01:06 -0800
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2020-03-02 14:42:32 -0800
commit45219190617b8609171f5e216f7357c629820dd8 (patch)
treed96f6203cd98627132cee2c259b40b4bb0750ca1 /src/gatt-database.c
parent76d63c91b27ab27e28267b6e5ff252252efd537f (diff)
downloadbluez-45219190617b8609171f5e216f7357c629820dd8.tar.gz
gatt: Enable EATT bearer support
This adds support for EATT connections.
Diffstat (limited to 'src/gatt-database.c')
-rw-r--r--src/gatt-database.c95
1 files changed, 69 insertions, 26 deletions
diff --git a/src/gatt-database.c b/src/gatt-database.c
index 419e4f9e1..afacae7d2 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -48,14 +48,6 @@
#include "profile.h"
#include "service.h"
-#ifndef ATT_CID
-#define ATT_CID 4
-#endif
-
-#ifndef ATT_PSM
-#define ATT_PSM 31
-#endif
-
#define GATT_MANAGER_IFACE "org.bluez.GattManager1"
#define GATT_PROFILE_IFACE "org.bluez.GattProfile1"
#define GATT_SERVICE_IFACE "org.bluez.GattService1"
@@ -80,7 +72,8 @@ struct btd_gatt_database {
struct gatt_db *db;
unsigned int db_id;
GIOChannel *le_io;
- GIOChannel *l2cap_io;
+ GIOChannel *eatt_io;
+ GIOChannel *bredr_io;
struct queue *records;
struct queue *device_states;
struct queue *ccc_callbacks;
@@ -88,6 +81,7 @@ struct btd_gatt_database {
struct gatt_db_attribute *svc_chngd_ccc;
struct gatt_db_attribute *cli_feat;
struct gatt_db_attribute *db_hash;
+ struct gatt_db_attribute *eatt;
struct queue *apps;
struct queue *profiles;
};
@@ -594,9 +588,14 @@ static void gatt_database_free(void *data)
g_io_channel_unref(database->le_io);
}
- if (database->l2cap_io) {
- g_io_channel_shutdown(database->l2cap_io, FALSE, NULL);
- g_io_channel_unref(database->l2cap_io);
+ if (database->eatt_io) {
+ g_io_channel_shutdown(database->eatt_io, FALSE, NULL);
+ g_io_channel_unref(database->eatt_io);
+ }
+
+ if (database->bredr_io) {
+ g_io_channel_shutdown(database->bredr_io, FALSE, NULL);
+ g_io_channel_unref(database->bredr_io);
}
/* TODO: Persistently store CCC states before freeing them */
@@ -717,7 +716,7 @@ static sdp_record_t *record_new(uuid_t *uuid, uint16_t start, uint16_t end)
uuid_t root_uuid, proto_uuid, l2cap;
sdp_record_t *record;
sdp_data_t *psm, *sh, *eh;
- uint16_t lp = ATT_PSM;
+ uint16_t lp = BT_ATT_PSM;
if (uuid == NULL)
return NULL;
@@ -1098,7 +1097,10 @@ static void cli_feat_write_cb(struct gatt_db_attribute *attrib,
{
struct btd_gatt_database *database = user_data;
struct device_state *state;
+ uint8_t bits[] = { BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING,
+ BT_GATT_CHRC_CLI_FEAT_EATT };
uint8_t ecode = 0;
+ unsigned int i;
DBG("Client Features write");
@@ -1113,13 +1115,12 @@ static void cli_feat_write_cb(struct gatt_db_attribute *attrib,
goto done;
}
- /* A client shall never clear a bit it has set.
- * TODO: make it generic to any bits.
- */
- if (state->cli_feat[0] & BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING &&
- !(value[0] & BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING)) {
- ecode = BT_ATT_ERROR_VALUE_NOT_ALLOWED;
- goto done;
+ for (i = 0; i < sizeof(bits); i++) {
+ /* A client shall never clear a bit it has set */
+ if (state->cli_feat[0] & (1 << i) && !(value[0] & (1 << i))) {
+ ecode = BT_ATT_ERROR_VALUE_NOT_ALLOWED;
+ goto done;
+ }
}
/* Shall we reallocate the feat array if bigger? */
@@ -1129,7 +1130,7 @@ static void cli_feat_write_cb(struct gatt_db_attribute *attrib,
len--;
}
- state->cli_feat[0] &= BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING;
+ state->cli_feat[0] &= ((1 << sizeof(bits)) - 1);
state->change_aware = true;
done:
@@ -1161,6 +1162,28 @@ static void db_hash_read_cb(struct gatt_db_attribute *attrib,
state->change_aware = true;
}
+static void server_feat_read_cb(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ struct btd_gatt_database *database = user_data;
+ struct device_state *state;
+ uint8_t ecode = 0;
+ uint8_t value = 0;
+
+ state = get_device_state(database, att);
+ if (!state) {
+ ecode = BT_ATT_ERROR_UNLIKELY;
+ goto done;
+ }
+
+ value |= BT_GATT_CHRC_SERVER_FEAT_EATT;
+
+done:
+ gatt_db_attribute_read_result(attrib, id, ecode, &value, sizeof(value));
+}
+
static void populate_gatt_service(struct btd_gatt_database *database)
{
bt_uuid_t uuid;
@@ -1168,7 +1191,7 @@ static void populate_gatt_service(struct btd_gatt_database *database)
/* Add the GATT service */
bt_uuid16_create(&uuid, UUID_GATT);
- service = gatt_db_add_service(database->db, &uuid, true, 8);
+ service = gatt_db_add_service(database->db, &uuid, true, 10);
bt_uuid16_create(&uuid, GATT_CHARAC_SERVICE_CHANGED);
database->svc_chngd = gatt_db_service_add_characteristic(service, &uuid,
@@ -1191,6 +1214,11 @@ static void populate_gatt_service(struct btd_gatt_database *database)
&uuid, BT_ATT_PERM_READ, BT_GATT_CHRC_PROP_READ,
db_hash_read_cb, NULL, database);
+ bt_uuid16_create(&uuid, GATT_CHARAC_SERVER_FEAT);
+ database->eatt = gatt_db_service_add_characteristic(service,
+ &uuid, BT_ATT_PERM_READ, BT_GATT_CHRC_PROP_READ,
+ server_feat_read_cb, NULL, database);
+
gatt_db_service_set_active(service, true);
database_add_record(database, service);
@@ -3525,7 +3553,7 @@ struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
BT_IO_OPT_SOURCE_BDADDR, addr,
BT_IO_OPT_SOURCE_TYPE,
btd_adapter_get_address_type(adapter),
- BT_IO_OPT_CID, ATT_CID,
+ BT_IO_OPT_CID, BT_ATT_CID,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
BT_IO_OPT_INVALID);
if (!database->le_io) {
@@ -3534,14 +3562,29 @@ struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
goto fail;
}
+ /* EATT socket */
+ database->eatt_io = bt_io_listen(connect_cb, NULL, NULL, NULL,
+ &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, addr,
+ BT_IO_OPT_SOURCE_TYPE,
+ btd_adapter_get_address_type(adapter),
+ BT_IO_OPT_PSM, BT_ATT_EATT_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_MTU, main_opts.gatt_mtu,
+ BT_IO_OPT_INVALID);
+ if (!database->eatt_io) {
+ g_error_free(gerr);
+ goto fail;
+ }
+
/* BR/EDR socket */
- database->l2cap_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &gerr,
+ database->bredr_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, addr,
- BT_IO_OPT_PSM, ATT_PSM,
+ BT_IO_OPT_PSM, BT_ATT_PSM,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
BT_IO_OPT_MTU, main_opts.gatt_mtu,
BT_IO_OPT_INVALID);
- if (database->l2cap_io == NULL) {
+ if (database->bredr_io == NULL) {
error("Failed to start listening: %s", gerr->message);
g_error_free(gerr);
goto fail;