Bluetooth: Audio: Add coordinated sets identification service client

Adds the coordinated set identification service (CSIS) client.

    This is still a work in progress and thus there are no public
    API for it yet, and some code changes will still be needed.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2021-10-21 14:04:55 +02:00 committed by Carles Cufí
commit c7b49cf1e4
5 changed files with 1631 additions and 2 deletions

View file

@ -27,4 +27,7 @@ zephyr_library_sources_ifdef(CONFIG_BT_CCID ccid.c)
zephyr_library_link_libraries(subsys__bluetooth)
zephyr_library_sources_ifdef(CONFIG_BT_CSIS csis.c)
zephyr_library_sources_ifdef(CONFIG_BT_CSIS csis_crypto.c)
zephyr_library_sources_ifdef(CONFIG_BT_CSIS_CLIENT csis_client.c)
if (CONFIG_BT_CSIS OR CONFIG_BT_CSIS_CLIENT)
zephyr_library_sources(csis_crypto.c)
endif()

View file

@ -57,10 +57,60 @@ config BT_DEBUG_CSIS
endif # BT_CSIS
#################### Coordinated Set Identification Client ####################
config BT_CSIS_CLIENT
bool "Coordinated Set Identification Profile Support [EXPERIMENTAL]"
select BT_GATT_CLIENT
select BT_GATT_AUTO_DISCOVER_CCC
select EXPERIMENTAL
help
This option enables support for Coordinated Set Identification
Profile.
if BT_CSIS_CLIENT
config BT_CSIS_CLIENT_TEST_SAMPLE_DATA
bool "Coordinated Set Identification Service Test Sample Data"
help
Enable the use of the sample data defined by the CSIS spec.
This will use the sample SIRK, prand and LTK.
WARNING: This option enables the client to use the sample data
to locate members and decrypt the SIRK, and thus won't work
with set members that are not using the sample data.
Should not be used for production builds.
config BT_CSIS_CLIENT_MAX_CSIS_INSTANCES
int "Coordinated Set Identification Service Count"
default 1
range 1 3
help
Sets the number of service instances, which corresponds to the number
of different sets the peer device may be in.
config BT_CSIS_CLIENT_ENC_SIRK_SUPPORT
bool "Support for encrypted SIRK"
default y
select BT_SMP_SC_PAIR_ONLY
help
Enables support encrypting the SIRK.
############### DEBUG ###############
config BT_DEBUG_CSIS_CLIENT
bool "Coordinated Set Identification Profile debug"
depends on BT_AUDIO_DEBUG
help
Use this option to enable Coordinated Set Identification Profile debug
logs for the Bluetooth Audio functionality.
endif # BT_CSIS_CLIENT
config BT_DEBUG_CSIS_CRYPTO
bool "Coordinated Set Identification Service crypto functions debug"
depends on BT_AUDIO_DEBUG
depends on BT_CSIS
depends on BT_CSIS_CLIENT || BT_CSIS
help
Use this option to enable Coordinated Set Identification Service
crypto functions debug logs for the Bluetooth Audio functionality.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,212 @@
/** @file
* @brief APIs for Bluetooth Coordinated Set Identification Client
*
* Copyright (c) 2020 Bose Corporation
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/gatt.h>
#include "csis.h"
#include "csis_internal.h"
/* Recommended timer for member discovery */
#define CSIS_CLIENT_DISCOVER_TIMER_VALUE K_SECONDS(10)
#if defined(CONFIG_BT_CSIS_CLIENT)
#define BT_CSIS_CLIENT_MAX_CSIS_INSTANCES CONFIG_BT_CSIS_CLIENT_MAX_CSIS_INSTANCES
#else
#define BT_CSIS_CLIENT_MAX_CSIS_INSTANCES 0
#endif /* CONFIG_BT_CSIS_CLIENT */
struct bt_csis_client_set {
struct bt_csis_set_sirk set_sirk;
uint8_t set_size;
uint8_t rank;
};
struct bt_csis_client_set_member {
struct bt_conn *conn;
bt_addr_le_t addr;
struct bt_csis_client_set sets[BT_CSIS_CLIENT_MAX_CSIS_INSTANCES];
};
typedef void (*bt_csis_client_discover_cb)(struct bt_conn *conn, int err,
uint8_t set_count);
/**
* @brief Initialise the csis_client instance for a connection. This will do a
* discovery on the device and prepare the instance for following commands.
*
* @param member Pointer to a set member struct to store discovery results in
*
* @return int Return 0 on success, or an errno value on error.
*/
int bt_csis_client_discover(struct bt_csis_client_set_member *member);
typedef void (*bt_csis_client_discover_sets_cb)(struct bt_conn *conn,
int err, uint8_t set_count,
struct bt_csis_client_set *sets);
/**
* @brief Reads CSIS characteristics from a device, to find more information
* about the set(s) that the device is part of.
*
* @param conn The connection to the device to read CSIS characteristics
*
* @return int Return 0 on success, or an errno value on error.
*/
int bt_csis_client_discover_sets(struct bt_conn *conn);
typedef void (*bt_csis_client_discover_members_cb)(int err, uint8_t set_size,
uint8_t members_found);
/**
* @brief Start scanning for all devices that are part of a set.
*
* @param set The set to find devices for
*
* @return int Return 0 on success, or an errno value on error.
*/
int bt_csis_client_discover_members(struct bt_csis_client_set *set);
typedef void (*bt_csis_client_lock_set_cb)(int err);
/**
* @brief Callback when the lock value on a set of a connected device changes.
*
* @param conn Connection of the CSIS server.
* @param set The set that was changed.
* @param locked Whether the lock is locked or release.
*
* @return int Return 0 on success, or an errno value on error.
*/
typedef void (*bt_csis_client_lock_changed_cb)(struct bt_conn *conn,
struct bt_csis_client_set *set,
bool locked);
/**
* @brief Callback when the lock value is read on a device.
*
* @param conn Connection of the CSIS server.
* @param err Error value. 0 on success, GATT error or errno on fail.
* @param inst_idx The index of the CSIS service.
* @param locked Whether the lock is locked or release.
*/
typedef void (*bt_csis_client_lock_read_cb)(struct bt_conn *conn, int err,
uint8_t inst_idx, bool locked);
/**
* @brief Callback when the lock value is written to a device.
*
* @param conn Connection of the CSIS server.
* @param err Error value. 0 on success, GATT error or errno on fail.
* @param inst_idx The index of the CSIS service.
*/
typedef void (*bt_csis_client_lock_cb)(struct bt_conn *conn, int err,
uint8_t inst_idx);
/**
* @brief Callback when the release value is written to a device.
*
* @param conn Connection of the CSIS server.
* @param err Error value. 0 on success, GATT error or errno on fail.
* @param inst_idx The index of the CSIS service.
*/
typedef void (*bt_csis_client_release_cb)(struct bt_conn *conn, int err,
uint8_t inst_idx);
struct bt_csis_client_cb {
/* Set callbacks */
bt_csis_client_lock_set_cb lock_set;
bt_csis_client_lock_set_cb release_set;
bt_csis_client_discover_members_cb members;
bt_csis_client_discover_sets_cb sets;
bt_csis_client_lock_changed_cb lock_changed;
/* Device specific callbacks */
bt_csis_client_discover_cb discover;
bt_csis_client_lock_read_cb lock_read;
bt_csis_client_lock_cb lock;
bt_csis_client_release_cb release;
};
/**
* @brief Check if advertising data indicates a set member
*
* @param set_sirk The SIRK of the set to check against
* @param data The advertising data
*
* @return true if the advertising data indicates a set member, false otherwise
*/
bool bt_csis_client_is_set_member(uint8_t set_sirk[BT_CSIS_SET_SIRK_SIZE],
struct bt_data *data);
/**
* @brief Lock the set
*
* Connect to and set the lock for all devices in a set.
*
* @return Return 0 on success, or an errno value on error.
*/
int bt_csis_client_lock_set(void);
/**
* @brief Connect to and release the lock for all devices in a set
*
* @return int Return 0 on success, or an errno value on error.
*/
int bt_csis_client_release_set(void);
/**
* @brief Registers callbacks for csis_client.
*
* @param cb Pointer to the callback structure.
*/
void bt_csis_client_register_cb(struct bt_csis_client_cb *cb);
/**
* @brief Read the lock value of a specific device and instance.
*
* @param conn Pointer to the connection to the device.
* @param inst_idx Index of the CSIS index of the peer device (as it may have
* multiple CSIS instances).
*
* @return Return 0 on success, or an errno value on error.
*/
int bt_csis_client_lock_get(struct bt_conn *conn, uint8_t inst_idx);
/**
* @brief Lock an array of set members
*
* The members will be locked starting from lowest rank going up.
*
* TODO: If locking fails, the already locked members will not be unlocked.
*
* @param members Array of set members to lock.
* @param count Number of set members in @p members.
* @param set Pointer to the specified set, as a member may be part of
* multiple sets.
*
* @return Return 0 on success, or an errno value on error.
*/
int bt_csis_client_lock(const struct bt_csis_client_set_member **members,
uint8_t count, const struct bt_csis_client_set *set);
/**
* @brief Release an array of set members
*
* The members will be released starting from highest rank going down.
*
* @param members Array of set members to lock.
* @param count Number of set members in @p members.
* @param set Pointer to the specified set, as a member may be part of
* multiple sets.
*
* @return Return 0 on success, or an errno value on error.
*/
int bt_csis_client_release(const struct bt_csis_client_set_member **members,
uint8_t count, const struct bt_csis_client_set *set);

View file

@ -57,3 +57,5 @@ CONFIG_BT_MICS_CLIENT_MAX_AICS_INST=1
# Coordinated Set Identification
CONFIG_BT_CSIS=y
CONFIG_BT_CSIS_CLIENT=y
CONFIG_BT_CSIS_CLIENT_MAX_CSIS_INSTANCES=2