Bluetooth: gatt: include service api definition proposal

* service include macro definition takes reference to
   first service attribute of the included service

Change-Id: Ib2b1defe2c99aea738da791af74a534d56025eae
Signed-off-by: Roger Lendenmann <roger.lendenmann@intel.com>
This commit is contained in:
Roger Lendenmann 2016-04-12 21:07:53 +02:00 committed by Johan Hedberg
parent ee795d87ff
commit 3278f542eb
4 changed files with 52 additions and 47 deletions

View file

@ -283,10 +283,19 @@ ssize_t bt_gatt_attr_read_service(struct bt_conn *conn,
} }
ssize_t bt_gatt_attr_read_included(struct bt_conn *conn, ssize_t bt_gatt_attr_read_included(struct bt_conn *conn,
const struct bt_gatt_attr *attr, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset) void *buf, uint16_t len, uint16_t offset)
{ {
return BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED); struct bt_gatt_attr *incl = attr->user_data;
/* nble gatt register case reading user_data. */
if (!conn) {
return bt_gatt_attr_read(conn, attr, buf, len, offset, incl,
sizeof(incl));
}
/* nble handles gattc reads internally */
return -EINVAL;
} }
struct gatt_chrc { struct gatt_chrc {
@ -550,8 +559,9 @@ static uint16_t parse_include(struct bt_conn *conn, const uint8_t *data,
break; break;
} }
attr = (&(struct bt_gatt_attr) attr = (&(struct bt_gatt_attr) {
BT_GATT_INCLUDE_SERVICE(&gatt_include)); .uuid = BT_UUID_GATT_INCLUDE,
.user_data = &gatt_include, });
attr->handle = att->handle; attr->handle = att->handle;
data += sizeof(*att); data += sizeof(*att);

View file

@ -450,16 +450,16 @@ ssize_t bt_gatt_attr_read_included(struct bt_conn *conn,
/** @def BT_GATT_INCLUDE_SERVICE /** @def BT_GATT_INCLUDE_SERVICE
* @brief Include Service Declaration Macro. * @brief Include Service Declaration Macro.
* *
* Helper macro to declare a include service attribute. * Helper macro to declare database internal include service attribute.
* *
* @param _service Service attribute value. * @param _service_incl, the first service attribute of service to include
*/ */
#define BT_GATT_INCLUDE_SERVICE(_service) \ #define BT_GATT_INCLUDE_SERVICE(_service_incl) \
{ \ { \
.uuid = BT_UUID_GATT_INCLUDE, \ .uuid = BT_UUID_GATT_INCLUDE, \
.perm = BT_GATT_PERM_READ, \ .perm = BT_GATT_PERM_READ, \
.read = bt_gatt_attr_read_included, \ .read = bt_gatt_attr_read_included, \
.user_data = _service, \ .user_data = _service_incl, \
} }
/** @brief Read Characteristic Attribute helper. /** @brief Read Characteristic Attribute helper.

View file

@ -163,28 +163,49 @@ struct gatt_incl {
uint16_t uuid16; uint16_t uuid16;
} __packed; } __packed;
static uint8_t get_service_handles(const struct bt_gatt_attr *attr,
void *user_data)
{
struct gatt_incl *include = user_data;
/* Stop if attribute is a service */
if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY) ||
!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) {
return BT_GATT_ITER_STOP;
}
include->end_handle = attr->handle;
return BT_GATT_ITER_CONTINUE;
}
ssize_t bt_gatt_attr_read_included(struct bt_conn *conn, ssize_t bt_gatt_attr_read_included(struct bt_conn *conn,
const struct bt_gatt_attr *attr, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset) void *buf, uint16_t len, uint16_t offset)
{ {
struct bt_gatt_include *incl = attr->user_data; struct bt_gatt_attr *incl = attr->user_data;
struct bt_uuid *uuid = incl->user_data;
struct gatt_incl pdu; struct gatt_incl pdu;
uint8_t value_len; uint8_t value_len;
pdu.start_handle = sys_cpu_to_le16(incl->start_handle); /* first attr points to the start handle */
pdu.end_handle = sys_cpu_to_le16(incl->end_handle); pdu.start_handle = sys_cpu_to_le16(incl->handle);
value_len = sizeof(pdu.start_handle) + sizeof(pdu.end_handle); value_len = sizeof(pdu.start_handle) + sizeof(pdu.end_handle);
/* /*
* Core 4.2, Vol 3, Part G, 3.2, * Core 4.2, Vol 3, Part G, 3.2,
* The Service UUID shall only be present when the UUID is a 16-bit * The Service UUID shall only be present when the UUID is a
* Bluetooth UUID. * 16-bit Bluetooth UUID.
*/ */
if (incl->uuid->type == BT_UUID_TYPE_16) { if (uuid->type == BT_UUID_TYPE_16) {
pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(incl->uuid)->val); pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val);
value_len += sizeof(pdu.uuid16); value_len += sizeof(pdu.uuid16);
} }
/* Lookup for service end handle */
bt_gatt_foreach_attr(incl->handle + 1, 0xffff, get_service_handles,
&pdu);
return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len); return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len);
} }
@ -911,7 +932,9 @@ static uint16_t parse_include(struct bt_conn *conn, const void *pdu,
continue; continue;
} }
attr = (&(struct bt_gatt_attr)BT_GATT_INCLUDE_SERVICE(&value)); attr = (&(struct bt_gatt_attr) {
.uuid = BT_UUID_GATT_INCLUDE,
.user_data = &value, });
attr->handle = handle; attr->handle = handle;
if (params->func(conn, attr, params) == BT_GATT_ITER_STOP) { if (params->func(conn, attr, params) == BT_GATT_ITER_STOP) {

View file

@ -540,46 +540,18 @@ fail:
CONTROLLER_INDEX, BTP_STATUS_FAILED); CONTROLLER_INDEX, BTP_STATUS_FAILED);
} }
static void get_service_end_handle(const struct bt_gatt_attr *attr,
struct bt_gatt_include *include,
uint16_t svc_start_handle)
{
/* Skip first attribute found, it is a service declaration. */
while (++attr < server_db + attr_count) {
/* Stop if attribute is a service */
if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY) ||
!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) {
include->end_handle = svc_start_handle;
return;
}
svc_start_handle++;
}
/* Last attribute in db */
include->end_handle = attr_count;
}
static int alloc_included(const struct bt_gatt_attr *attr, static int alloc_included(const struct bt_gatt_attr *attr,
uint16_t *included_service_id, uint16_t svc_handle) uint16_t *included_service_id, uint16_t svc_handle)
{ {
struct bt_gatt_attr *attr_incl; struct bt_gatt_attr *attr_incl;
struct bt_gatt_include include;
include.uuid = attr->user_data;
include.start_handle = svc_handle;
include.end_handle = svc_handle;
attr_incl = gatt_db_add(&(struct bt_gatt_attr) attr_incl = gatt_db_add(&(struct bt_gatt_attr)
BT_GATT_INCLUDE_SERVICE(&include), BT_GATT_INCLUDE_SERVICE(&attr),
sizeof(include)); sizeof(attr));
if (!attr_incl) { if (!attr_incl) {
return -EINVAL; return -EINVAL;
} }
/* Get included end handle */
get_service_end_handle(attr, attr_incl->user_data, svc_handle);
*included_service_id = attr_incl->handle; *included_service_id = attr_incl->handle;
return 0; return 0;
} }