zephyr/subsys/bluetooth/services/bas.c
Luiz Augusto von Dentz 03b9ce487c Bluetooth: GATT: Add support to setting permission on CCCD
This adds support to set different permissions to CCCD so security can
be checked when enabling notification which conforms to:

BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2360:

  '3.3.3.3 Client Characteristic Configuration

   Authentication and authorization may be required by the server to
   write the configuration descriptor.'

In addition to that also ensure that notification are not re-enabled
until the proper security level is reached to conform to the following
statement:

  '10.3.1.1 Handling of GATT indications and notifications

   A client “requests” a server to send indications and notifications
   by appropriately configuring the server via a Client Characteristic
   Configuration Descriptor. Since the configuration is persistent
   across a disconnection and reconnection, security requirements must
   be checked against the configuration upon a reconnection before
   sending indications or notifications. When a server reconnects to a
   client to send an indication or notification for which security is
   required, the server shall initiate or request encryption with the
   client prior to sending an indication or notification. If the client
   does not have an LTK indicating that the client has lost the bond,
   enabling encryption will fail.'

Fixes #17983

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2019-09-19 21:12:39 +03:00

88 lines
1.8 KiB
C

/** @file
* @brief GATT Battery Service
*/
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <init.h>
#include <misc/__assert.h>
#include <stdbool.h>
#include <zephyr/types.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/gatt.h>
#include <bluetooth/uuid.h>
#include <bluetooth/services/bas.h>
#define LOG_LEVEL CONFIG_BT_GATT_BAS_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(bas);
static u8_t battery_level = 100U;
static void blvl_ccc_cfg_changed(const struct bt_gatt_attr *attr,
u16_t value)
{
ARG_UNUSED(attr);
bool notif_enabled = (value == BT_GATT_CCC_NOTIFY);
LOG_INF("BAS Notifications %s", notif_enabled ? "enabled" : "disabled");
}
static ssize_t read_blvl(struct bt_conn *conn,
const struct bt_gatt_attr *attr, void *buf,
u16_t len, u16_t offset)
{
u8_t lvl8 = battery_level;
return bt_gatt_attr_read(conn, attr, buf, len, offset, &lvl8,
sizeof(lvl8));
}
BT_GATT_SERVICE_DEFINE(bas,
BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS),
BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL,
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ, read_blvl, NULL,
&battery_level),
BT_GATT_CCC(blvl_ccc_cfg_changed,
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
);
static int bas_init(struct device *dev)
{
ARG_UNUSED(dev);
return 0;
}
u8_t bt_gatt_bas_get_battery_level(void)
{
return battery_level;
}
int bt_gatt_bas_set_battery_level(u8_t level)
{
int rc;
if (level > 100U) {
return -EINVAL;
}
battery_level = level;
rc = bt_gatt_notify(NULL, &bas.attrs[1], &level, sizeof(level));
return rc == -ENOTCONN ? 0 : rc;
}
SYS_INIT(bas_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);