Merges bt_csis_client_discover and bt_csis_client_discover_sets, as they should be done together for the discovery procedure from the CSIP spec. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
390 lines
12 KiB
C
390 lines
12 KiB
C
/**
|
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef ZEPHYR_SUBSYS_BLUETOOTH_AUDIO_CSIS_H_
|
|
#define ZEPHYR_SUBSYS_BLUETOOTH_AUDIO_CSIS_H_
|
|
|
|
/**
|
|
* @brief Coordinated Set Identification Service (CSIS)
|
|
*
|
|
* @defgroup bt_gatt_csis Coordinated Set Identification Service (CSIS)
|
|
*
|
|
* @ingroup bluetooth
|
|
* @{
|
|
* *
|
|
* [Experimental] Users should note that the APIs can change as a part of ongoing development.
|
|
*/
|
|
|
|
#include <zephyr/types.h>
|
|
#include <stdbool.h>
|
|
#include <bluetooth/conn.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** 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 */
|
|
|
|
/** Minimum size of a set */
|
|
#define BT_CSIS_MINIMUM_SET_SIZE 2
|
|
|
|
/** Accept the request to read the SIRK as plaintext */
|
|
#define BT_CSIS_READ_SIRK_REQ_RSP_ACCEPT 0x00
|
|
/** Accept the request to read the SIRK, but return encrypted SIRK */
|
|
#define BT_CSIS_READ_SIRK_REQ_RSP_ACCEPT_ENC 0x01
|
|
/** Reject the request to read the SIRK */
|
|
#define BT_CSIS_READ_SIRK_REQ_RSP_REJECT 0x02
|
|
/** SIRK is available only via an OOB procedure */
|
|
#define BT_CSIS_READ_SIRK_REQ_RSP_OOB_ONLY 0x03
|
|
|
|
/** Size of the Set Identification Resolving Key (SIRK) */
|
|
#define BT_CSIS_SET_SIRK_SIZE 16
|
|
|
|
/* Coordinate Set Identification Service Error codes */
|
|
/** Service is already locked */
|
|
#define BT_CSIS_ERROR_LOCK_DENIED 0x80
|
|
/** Service is not locked */
|
|
#define BT_CSIS_ERROR_LOCK_RELEASE_DENIED 0x81
|
|
/** Invalid lock value */
|
|
#define BT_CSIS_ERROR_LOCK_INVAL_VALUE 0x82
|
|
/** SIRK only available out-of-band */
|
|
#define BT_CSIS_ERROR_SIRK_OOB_ONLY 0x83
|
|
/** Client is already owner of the lock */
|
|
#define BT_CSIS_ERROR_LOCK_ALREADY_GRANTED 0x84
|
|
|
|
/** @brief Opaque Coordinated Set Identification Service instance. */
|
|
struct bt_csis;
|
|
|
|
/** Callback structure for the Coordinated Set Identification Service */
|
|
struct bt_csis_cb {
|
|
/**
|
|
* @brief Callback whenever the lock changes on the server.
|
|
*
|
|
* @param conn The connection to the client that changed the lock.
|
|
* NULL if server changed it, either by calling
|
|
* bt_csis_lock() or by timeout.
|
|
* @param csis Pointer to the Coordinated Set Identification Service.
|
|
* @param locked Whether the lock was locked or released.
|
|
*
|
|
*/
|
|
void (*lock_changed)(struct bt_conn *conn, struct bt_csis *csis,
|
|
bool locked);
|
|
|
|
/**
|
|
* @brief Request from a peer device to read the sirk.
|
|
*
|
|
* If this callback is not set, all clients will be allowed to read
|
|
* the SIRK unencrypted.
|
|
*
|
|
* @param conn The connection to the client that requested to read the
|
|
* SIRK.
|
|
* @param csis Pointer to the Coordinated Set Identification Service.
|
|
*
|
|
* @return A BT_CSIS_READ_SIRK_REQ_RSP_* response code.
|
|
*/
|
|
uint8_t (*sirk_read_req)(struct bt_conn *conn, struct bt_csis *csis);
|
|
};
|
|
|
|
/** Register structure for Coordinated Set Identification Service */
|
|
struct bt_csis_register_param {
|
|
/**
|
|
* @brief Size of the set.
|
|
*
|
|
* If set to 0, the set size characteric won't be initialized.
|
|
* Otherwise shall be set to minimum 2.
|
|
*/
|
|
uint8_t set_size;
|
|
|
|
/**
|
|
* @brief The unique Set Identity Resolving Key (SIRK)
|
|
*
|
|
* This shall be unique between different sets, and shall be the same
|
|
* for each set member for each set.
|
|
*/
|
|
uint8_t set_sirk[BT_CSIS_SET_SIRK_SIZE];
|
|
|
|
/**
|
|
* @brief Boolean to set whether the set is lockable by clients
|
|
*
|
|
* Setting this to false will disable the lock characteristic.
|
|
*/
|
|
bool lockable;
|
|
|
|
/**
|
|
* @brief Rank of this device in this set.
|
|
*
|
|
* If the lockable parameter is set to true, this shall be > 0 and
|
|
* <= to the set_size. If the lockable parameter is set to false, this
|
|
* may be set to 0 to disable the rank characteristic.
|
|
*/
|
|
uint8_t rank;
|
|
|
|
/** Pointer to the callback structure. */
|
|
struct bt_csis_cb *cb;
|
|
};
|
|
|
|
/**
|
|
* @brief Get the service declaration attribute.
|
|
*
|
|
* The first service attribute can be included in any other GATT service.
|
|
*
|
|
* @param csis Pointer to the Coordinated Set Identification Service.
|
|
*
|
|
* @return The first CSIS attribute instance.
|
|
*/
|
|
void *bt_csis_svc_decl_get(const struct bt_csis *csis);
|
|
|
|
/**
|
|
* @brief Register a Coordinated Set Identification Service instance.
|
|
*
|
|
* This will register and enable the service and make it discoverable by
|
|
* clients.
|
|
*
|
|
* This shall only be done as a server.
|
|
*
|
|
* @param param Coordinated Set Identification Service register parameters.
|
|
* @param[out] csis Pointer to the registered Coordinated Set Identification
|
|
* Service.
|
|
*
|
|
* @return 0 if success, errno on failure.
|
|
*/
|
|
int bt_csis_register(const struct bt_csis_register_param *param,
|
|
struct bt_csis **csis);
|
|
|
|
/**
|
|
* @brief Print the SIRK to the debug output
|
|
*
|
|
* @param csis Pointer to the Coordinated Set Identification Service.
|
|
*/
|
|
void bt_csis_print_sirk(const struct bt_csis *csis);
|
|
|
|
/**
|
|
* @brief Starts advertising the Resolveable Set Identifier value.
|
|
*
|
|
* This cannot be used with other connectable advertising sets.
|
|
*
|
|
* @param csis Pointer to the Coordinated Set Identification Service.
|
|
* @param enable If true start advertising, if false stop advertising
|
|
*
|
|
* @return int 0 if on success, errno on error.
|
|
*/
|
|
int bt_csis_advertise(struct bt_csis *csis, bool enable);
|
|
|
|
/**
|
|
* @brief Locks a specific Coordinated Set Identification Service instance on the server.
|
|
*
|
|
* @param csis Pointer to the Coordinated Set Identification Service.
|
|
* @param lock If true lock the set, if false release the set.
|
|
* @param force This argument only have meaning when @p lock is false
|
|
* (release) and will force release the lock, regardless of who
|
|
* took the lock.
|
|
*
|
|
* @return 0 on success, GATT error on error.
|
|
*/
|
|
int bt_csis_lock(struct bt_csis *csis, bool lock, bool force);
|
|
|
|
/** Information about a specific set */
|
|
struct bt_csis_client_set_info {
|
|
/**
|
|
* @brief The 16 octet set Set Identity Resolving Key (SIRK)
|
|
*
|
|
* The Set SIRK may not be exposed by the server over Bluetooth, and
|
|
* may require an out-of-band solution.
|
|
*/
|
|
uint8_t set_sirk[BT_CSIS_SET_SIRK_SIZE];
|
|
|
|
/**
|
|
* @brief The size of the set
|
|
*
|
|
* Will be 0 if not exposed by the server.
|
|
*/
|
|
uint8_t set_size;
|
|
|
|
/**
|
|
* @brief The rank of the set on on the remote device
|
|
*
|
|
* Will be 0 if not exposed by the server.
|
|
*/
|
|
uint8_t rank;
|
|
};
|
|
|
|
/**
|
|
* @brief Struct representing a coordinated set instance on a remote device
|
|
*
|
|
* The values in this struct will be populated during discovery of sets
|
|
* (bt_csis_client_discover()).
|
|
*/
|
|
struct bt_csis_client_csis_inst {
|
|
struct bt_csis_client_set_info info;
|
|
|
|
/** Internally used pointer value */
|
|
struct bt_csis *csis;
|
|
};
|
|
|
|
/** Struct representing a remote device as a set member */
|
|
struct bt_csis_client_set_member {
|
|
/** Connection pointer to the remote device, populated by the user */
|
|
struct bt_conn *conn;
|
|
/** Array of Coordinated Set Identification Service instances for the remote device */
|
|
struct bt_csis_client_csis_inst insts[BT_CSIS_CLIENT_MAX_CSIS_INSTANCES];
|
|
};
|
|
|
|
/**
|
|
* @typedef bt_csis_client_discover_cb
|
|
* @brief Callback for discovering Coordinated Set Identification Services.
|
|
*
|
|
* @param member Pointer to the set member.
|
|
* @param err 0 on success, or an errno value on error.
|
|
* @param set_count Number of sets on the member.
|
|
*/
|
|
typedef void (*bt_csis_client_discover_cb)(struct bt_csis_client_set_member *member,
|
|
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 bt_csis_client_lock_set_cb
|
|
* @brief Callback for locking a set across one or more devices
|
|
*
|
|
* @param err 0 on success, or an errno value on error.
|
|
*/
|
|
typedef void (*bt_csis_client_lock_set_cb)(int err);
|
|
|
|
/**
|
|
* @typedef bt_csis_client_lock_changed_cb
|
|
* @brief Callback when the lock value on a set of a connected device changes.
|
|
*
|
|
* @param inst The Coordinated Set Identification Service instance 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_csis_client_csis_inst *inst,
|
|
bool locked);
|
|
|
|
/**
|
|
* @typedef bt_csis_client_lock_state_read_cb
|
|
* @brief Callback for bt_csis_client_get_lock_state()
|
|
*
|
|
* If any of the set members supplied to bt_csis_client_get_lock_state() is
|
|
* in the locked state, this will be called with @p locked true. If any
|
|
* set member is in the locked state, the remaining (if any) won't be read.
|
|
* Likewise, if any error occurs, the procedure will also be aborted.
|
|
*
|
|
* @param set_info Pointer to the a specific set_info struct.
|
|
* @param err Error value. 0 on success, GATT error or errno on fail.
|
|
* @param locked Whether the lock is locked or release.
|
|
*/
|
|
typedef void (*bt_csis_client_lock_state_read_cb)(const struct bt_csis_client_set_info *set_info,
|
|
int err, bool locked);
|
|
|
|
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_lock_changed_cb lock_changed;
|
|
|
|
/* Device specific callbacks */
|
|
bt_csis_client_discover_cb discover;
|
|
bt_csis_client_lock_state_read_cb lock_state_read;
|
|
};
|
|
|
|
/**
|
|
* @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 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 Check if an array of set members are unlocked
|
|
*
|
|
* This will read the set lock value on all members and respond with a single
|
|
* state.
|
|
*
|
|
* @param members Array of set members to check lock state for.
|
|
* @param count Number of set members in @p members.
|
|
* @param set_info Pointer to the a specific set_info struct, as a member may
|
|
* be part of multiple sets.
|
|
*
|
|
* @return Return 0 on success, or an errno value on error.
|
|
*/
|
|
int bt_csis_client_get_lock_state(const struct bt_csis_client_set_member **members,
|
|
uint8_t count,
|
|
const struct bt_csis_client_set_info *set_info);
|
|
|
|
/**
|
|
* @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_info Pointer to the a specific set_info struct, 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_info *set_info);
|
|
|
|
/**
|
|
* @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_info Pointer to the a specific set_info struct, 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_info *set_info);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#endif /* ZEPHYR_SUBSYS_BLUETOOTH_AUDIO_CSIS_H_ */
|