Bluetooth: CSIP: Add support for dynamic SIRKs
Add support for dynamically change the SIRK in a CSIS. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
3850f4ca64
commit
41a589c5fa
13 changed files with 537 additions and 174 deletions
|
@ -28,12 +28,38 @@ register callbacks.
|
|||
lock :Lock the set
|
||||
release :Release the set [force]
|
||||
print_sirk :Print the currently used SIRK
|
||||
set_sirk :Set the currently used SIRK <sirk>
|
||||
get_sirk :Get the currently used SIRK
|
||||
set_sirk_rsp :Set the response used in SIRK requests <accept, accept_enc,
|
||||
reject, oob>
|
||||
|
||||
Besides initializing the CAS and the CSIS, there are also commands to lock and release the CSIS
|
||||
instance, as well as printing and modifying access to the SIRK of the CSIS.
|
||||
|
||||
Setting a new SIRK
|
||||
------------------
|
||||
|
||||
This command can modify the currently used SIRK. To get the new RSI to advertise on air,
|
||||
:code:`bt adv-data`` or :code:`bt advertise` must be called again to set the new advertising data.
|
||||
If :code:`CONFIG_BT_CSIP_SET_MEMBER_NOTIFIABLE` is enabled, this will also notify connected
|
||||
clients.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
uart:~$ cap_acceptor set_sirk 00112233445566778899aabbccddeeff
|
||||
Set SIRK updated
|
||||
|
||||
Getting the current SIRK
|
||||
------------------------
|
||||
|
||||
This command can get the currently used SIRK.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
uart:~$ cap_acceptor get_sirk
|
||||
Set SIRK
|
||||
36 04 9a dc 66 3a a1 a1 |6...f:..
|
||||
1d 9a 2f 41 01 73 3e 01 |../A.s>.
|
||||
|
||||
CAP Initiator
|
||||
*************
|
||||
|
|
|
@ -146,10 +146,11 @@ Using the Set Member
|
|||
Subcommands:
|
||||
register :Initialize the service and register callbacks [size <int>]
|
||||
[rank <int>] [not-lockable] [sirk <data>]
|
||||
update_psri :Update the advertised PSRI
|
||||
lock :Lock the set
|
||||
release :Release the set [force]
|
||||
print_sirk :Print the currently used SIRK
|
||||
set_sirk :Set the currently used SIRK <sirk>
|
||||
get_sirk :Get the currently used SIRK
|
||||
set_sirk_rsp :Set the response used in SIRK requests <accept, accept_enc,
|
||||
reject, oob>
|
||||
|
||||
|
@ -163,3 +164,29 @@ Setup
|
|||
|
||||
uart:~$ bt init
|
||||
uart:~$ csip_set_member register
|
||||
|
||||
|
||||
Setting a new SIRK
|
||||
------------------
|
||||
|
||||
This command can modify the currently used SIRK. To get the new RSI to advertise on air,
|
||||
:code:`bt adv-data`` or :code:`bt advertise` must be called again to set the new advertising data.
|
||||
If :code:`CONFIG_BT_CSIP_SET_MEMBER_NOTIFIABLE` is enabled, this will also notify connected
|
||||
clients.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
uart:~$ csip_set_member set_sirk 00112233445566778899aabbccddeeff
|
||||
Set SIRK updated
|
||||
|
||||
Getting the current SIRK
|
||||
------------------------
|
||||
|
||||
This command can get the currently used SIRK.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
uart:~$ csip_set_member get_sirk
|
||||
Set SIRK
|
||||
36 04 9a dc 66 3a a1 a1 |6...f:..
|
||||
1d 9a 2f 41 01 73 3e 01 |../A.s>.
|
||||
|
|
|
@ -197,6 +197,24 @@ int bt_csip_set_member_register(const struct bt_csip_set_member_register_param *
|
|||
*/
|
||||
int bt_csip_set_member_unregister(struct bt_csip_set_member_svc_inst *svc_inst);
|
||||
|
||||
/**
|
||||
* @brief Set the SIRK of a service instance
|
||||
*
|
||||
* @param svc_inst Pointer to the registered Coordinated Set Identification Service.
|
||||
* @param sirk The new SIRK.
|
||||
*/
|
||||
int bt_csip_set_member_set_sirk(struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE]);
|
||||
|
||||
/**
|
||||
* @brief Get the SIRK of a service instance
|
||||
*
|
||||
* @param[in] svc_inst Pointer to the registered Coordinated Set Identification Service.
|
||||
* @param[out] sirk Array to store the SIRK in.
|
||||
*/
|
||||
int bt_csip_set_member_get_sirk(struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
uint8_t sirk[BT_CSIP_SET_SIRK_SIZE]);
|
||||
|
||||
/**
|
||||
* @brief Print the SIRK to the debug output
|
||||
*
|
||||
|
@ -323,6 +341,16 @@ typedef void (*bt_csip_set_coordinator_lock_set_cb)(int err);
|
|||
typedef void (*bt_csip_set_coordinator_lock_changed_cb)(
|
||||
struct bt_csip_set_coordinator_csis_inst *inst, bool locked);
|
||||
|
||||
/**
|
||||
* @typedef bt_csip_set_coordinator_sirk_changed_cb
|
||||
* @brief Callback when the SIRK value of a set of a connected device changes.
|
||||
*
|
||||
* @param inst The Coordinated Set Identification Service instance that was changed.
|
||||
* The new SIRK can be accessed via the @p inst.info.
|
||||
*/
|
||||
typedef void (*bt_csip_set_coordinator_sirk_changed_cb)(
|
||||
struct bt_csip_set_coordinator_csis_inst *inst);
|
||||
|
||||
/**
|
||||
* @typedef bt_csip_set_coordinator_ordered_access_cb_t
|
||||
* @brief Callback for bt_csip_set_coordinator_ordered_access()
|
||||
|
@ -347,6 +375,7 @@ struct bt_csip_set_coordinator_cb {
|
|||
bt_csip_set_coordinator_lock_set_cb lock_set;
|
||||
bt_csip_set_coordinator_lock_set_cb release_set;
|
||||
bt_csip_set_coordinator_lock_changed_cb lock_changed;
|
||||
bt_csip_set_coordinator_sirk_changed_cb sirk_changed;
|
||||
|
||||
/* Device specific callbacks */
|
||||
bt_csip_set_coordinator_discover_cb discover;
|
||||
|
@ -455,7 +484,6 @@ int bt_csip_set_coordinator_release(const struct bt_csip_set_coordinator_set_mem
|
|||
uint8_t count,
|
||||
const struct bt_csip_set_coordinator_set_info *set_info);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,11 @@ config BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT
|
|||
Enabling BT_CAP_ACCEPTOR_SET_MEMBER will take one of the allocated
|
||||
instances.
|
||||
|
||||
config BT_CSIP_SET_MEMBER_NOTIFIABLE
|
||||
bool "SIRK notifiable Support"
|
||||
help
|
||||
This option enables support for clients to be notified on SIRK changes.
|
||||
|
||||
endif # BT_CSIP_SET_MEMBER
|
||||
|
||||
#################### Coordinated Set Identification Client ####################
|
||||
|
|
|
@ -300,6 +300,17 @@ static void lock_changed(struct bt_csip_set_coordinator_csis_inst *inst, bool lo
|
|||
}
|
||||
}
|
||||
|
||||
static void sirk_changed(struct bt_csip_set_coordinator_csis_inst *inst)
|
||||
{
|
||||
struct bt_csip_set_coordinator_cb *listener;
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&csip_set_coordinator_cbs, listener, _node) {
|
||||
if (listener->sirk_changed) {
|
||||
listener->sirk_changed(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void release_set_complete(int err)
|
||||
{
|
||||
struct bt_csip_set_coordinator_cb *listener;
|
||||
|
@ -389,10 +400,12 @@ static uint8_t sirk_notify_func(struct bt_conn *conn,
|
|||
struct bt_csip_set_sirk *sirk =
|
||||
(struct bt_csip_set_sirk *)data;
|
||||
struct bt_csip_set_coordinator_inst *client;
|
||||
struct bt_csip_set_coordinator_csis_inst *inst;
|
||||
uint8_t *dst_sirk;
|
||||
|
||||
client = &client_insts[bt_conn_index(conn)];
|
||||
dst_sirk = client->set_member.insts[svc_inst->idx].info.set_sirk;
|
||||
inst = &client->set_member.insts[svc_inst->idx];
|
||||
dst_sirk = inst->info.set_sirk;
|
||||
|
||||
LOG_DBG("Set SIRK %sencrypted",
|
||||
sirk->type == BT_CSIP_SIRK_TYPE_PLAIN ? "not " : "");
|
||||
|
@ -422,7 +435,7 @@ static uint8_t sirk_notify_func(struct bt_conn *conn,
|
|||
LOG_HEXDUMP_DBG(dst_sirk, BT_CSIP_SET_SIRK_SIZE,
|
||||
"Set SIRK");
|
||||
|
||||
/* TODO: Notify app */
|
||||
sirk_changed(inst);
|
||||
} else {
|
||||
LOG_DBG("Invalid length %u", length);
|
||||
}
|
||||
|
|
|
@ -39,9 +39,10 @@
|
|||
|
||||
LOG_MODULE_REGISTER(bt_csip_set_member, CONFIG_BT_CSIP_SET_MEMBER_LOG_LEVEL);
|
||||
|
||||
enum csip_pending_notify_flag {
|
||||
enum csip_flag {
|
||||
FLAG_ACTIVE,
|
||||
FLAG_SET_MEMBER_LOCK,
|
||||
FLAG_NOTIFY_LOCK,
|
||||
FLAG_NOTIFY_SIRK,
|
||||
FLAG_NUM,
|
||||
};
|
||||
|
||||
|
@ -67,16 +68,9 @@ struct bt_csip_set_member_svc_inst {
|
|||
static struct bt_csip_set_member_svc_inst svc_insts[CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT];
|
||||
static bt_addr_le_t server_dummy_addr; /* 0'ed address */
|
||||
|
||||
static atomic_t notify_in_progress;
|
||||
|
||||
static void deferred_nfy_work_handler(struct k_work *work);
|
||||
|
||||
static K_WORK_DEFINE(deferred_nfy_work, deferred_nfy_work_handler);
|
||||
|
||||
struct csip_notify_foreach {
|
||||
struct bt_conn *excluded_client;
|
||||
struct bt_csip_set_member_svc_inst *svc_inst;
|
||||
};
|
||||
static K_WORK_DELAYABLE_DEFINE(deferred_nfy_work, deferred_nfy_work_handler);
|
||||
|
||||
static bool is_last_client_to_write(const struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
const struct bt_conn *conn)
|
||||
|
@ -90,114 +84,27 @@ static bool is_last_client_to_write(const struct bt_csip_set_member_svc_inst *sv
|
|||
}
|
||||
}
|
||||
|
||||
static void csip_gatt_notify_complete_cb(struct bt_conn *conn, void *user_data)
|
||||
{
|
||||
/* Notification done, clear bit and reschedule work */
|
||||
atomic_clear(¬ify_in_progress);
|
||||
k_work_submit(&deferred_nfy_work);
|
||||
}
|
||||
|
||||
static int csip_gatt_notify_set_lock(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr,
|
||||
const void *data,
|
||||
uint16_t len)
|
||||
static void notify_work_reschedule(k_timeout_t delay)
|
||||
{
|
||||
int err;
|
||||
struct bt_gatt_notify_params params;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.uuid = BT_UUID_CSIS_SET_LOCK;
|
||||
params.attr = attr;
|
||||
params.data = data;
|
||||
params.len = len;
|
||||
params.func = csip_gatt_notify_complete_cb;
|
||||
|
||||
/* Mark notification in progress */
|
||||
atomic_set(¬ify_in_progress, 1);
|
||||
|
||||
err = bt_gatt_notify_cb(conn, ¶ms);
|
||||
if (err != 0) {
|
||||
atomic_clear(¬ify_in_progress);
|
||||
|
||||
if (err != -ENOTCONN) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void csip_set_notify_bit(struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
enum csip_pending_notify_flag flag)
|
||||
{
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) {
|
||||
struct csip_client *client;
|
||||
|
||||
client = &svc_inst->clients[i];
|
||||
if (atomic_test_bit(client->flags, FLAG_ACTIVE)) {
|
||||
atomic_set_bit(client->flags, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int notify_lock_value(const struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
struct bt_conn *conn)
|
||||
{
|
||||
LOG_DBG("");
|
||||
|
||||
if (svc_inst->service_p != NULL) {
|
||||
return csip_gatt_notify_set_lock(conn, svc_inst->service_p->attrs,
|
||||
&svc_inst->set_lock, sizeof(svc_inst->set_lock));
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_client(struct bt_conn *conn, void *data)
|
||||
{
|
||||
struct csip_notify_foreach *csip_data = (struct csip_notify_foreach *)data;
|
||||
struct bt_csip_set_member_svc_inst *svc_inst = csip_data->svc_inst;
|
||||
struct bt_conn *excluded_conn = csip_data->excluded_client;
|
||||
|
||||
if (excluded_conn != NULL && conn == excluded_conn) {
|
||||
/* If it is already scheduled, don't reschedule */
|
||||
if (k_work_delayable_remaining_get(&deferred_nfy_work) > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) {
|
||||
struct csip_client *client;
|
||||
|
||||
client = &svc_inst->clients[i];
|
||||
|
||||
if (atomic_test_bit(client->flags, FLAG_SET_MEMBER_LOCK) &&
|
||||
bt_addr_le_eq(bt_conn_get_dst(conn), &client->addr)) {
|
||||
/* First try to send the notification directly, and if it fails add it
|
||||
* to system workqueue for retry. We do it like this here as the client
|
||||
* wants the lock notification asap to begin ordered access procedure
|
||||
*/
|
||||
if (notify_lock_value(svc_inst, conn) != 0) {
|
||||
csip_set_notify_bit(svc_inst, FLAG_SET_MEMBER_LOCK);
|
||||
k_work_submit(&deferred_nfy_work);
|
||||
} else {
|
||||
atomic_clear_bit(client->flags, FLAG_SET_MEMBER_LOCK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
err = k_work_reschedule(&deferred_nfy_work, delay);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to reschedule notification work err %d", err);
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_clients(struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
struct bt_conn *excluded_client)
|
||||
struct bt_conn *excluded_client, enum csip_flag flag)
|
||||
{
|
||||
struct csip_notify_foreach data = {
|
||||
.excluded_client = excluded_client,
|
||||
.svc_inst = svc_inst,
|
||||
};
|
||||
bool submit_work = false;
|
||||
|
||||
/* Mark all bonded devices as pending notifications, and clear those
|
||||
* that are notified in `notify_client`
|
||||
*/
|
||||
/* Mark all bonded devices (except the excluded one) as pending notifications */
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) {
|
||||
struct csip_client *client;
|
||||
|
||||
|
@ -209,11 +116,15 @@ static void notify_clients(struct bt_csip_set_member_svc_inst *svc_inst,
|
|||
continue;
|
||||
}
|
||||
|
||||
atomic_set_bit(client->flags, FLAG_SET_MEMBER_LOCK);
|
||||
atomic_set_bit(client->flags, flag);
|
||||
submit_work = true;
|
||||
}
|
||||
}
|
||||
|
||||
bt_conn_foreach(BT_CONN_TYPE_LE, notify_client, &data);
|
||||
/* Reschedule work for notifying */
|
||||
if (submit_work) {
|
||||
notify_work_reschedule(K_NO_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
static int sirk_encrypt(struct bt_conn *conn,
|
||||
|
@ -373,11 +284,13 @@ static ssize_t read_set_sirk(struct bt_conn *conn,
|
|||
sirk, sizeof(*sirk));
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CSIP_SET_MEMBER_NOTIFIABLE)
|
||||
static void set_sirk_cfg_changed(const struct bt_gatt_attr *attr,
|
||||
uint16_t value)
|
||||
{
|
||||
LOG_DBG("value 0x%04x", value);
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER_NOTIFIABLE */
|
||||
|
||||
static ssize_t read_set_size(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr,
|
||||
|
@ -467,7 +380,7 @@ static uint8_t set_lock(struct bt_conn *conn,
|
|||
* client writing the value, shall be notified
|
||||
* (if subscribed)
|
||||
*/
|
||||
notify_clients(svc_inst, conn);
|
||||
notify_clients(svc_inst, conn, FLAG_NOTIFY_LOCK);
|
||||
|
||||
if (svc_inst->cb != NULL && svc_inst->cb->lock_changed != NULL) {
|
||||
bool locked = svc_inst->set_lock == BT_CSIP_LOCK_VALUE;
|
||||
|
@ -534,7 +447,7 @@ static void set_lock_timer_handler(struct k_work *work)
|
|||
|
||||
LOG_DBG("Lock timeout, releasing");
|
||||
svc_inst->set_lock = BT_CSIP_RELEASE_VALUE;
|
||||
notify_clients(svc_inst, NULL);
|
||||
notify_clients(svc_inst, NULL, FLAG_NOTIFY_LOCK);
|
||||
|
||||
if (svc_inst->cb != NULL && svc_inst->cb->lock_changed != NULL) {
|
||||
bool locked = svc_inst->set_lock == BT_CSIP_LOCK_VALUE;
|
||||
|
@ -562,9 +475,9 @@ static void csip_security_changed(struct bt_conn *conn, bt_security_t level,
|
|||
|
||||
client = &svc_inst->clients[i];
|
||||
|
||||
if (atomic_test_bit(client->flags, FLAG_SET_MEMBER_LOCK) &&
|
||||
if (atomic_test_bit(client->flags, FLAG_NOTIFY_LOCK) &&
|
||||
bt_addr_le_eq(bt_conn_get_dst(conn), &client->addr)) {
|
||||
k_work_submit(&deferred_nfy_work);
|
||||
notify_work_reschedule(K_NO_WAIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +492,7 @@ static void handle_csip_disconnect(struct bt_csip_set_member_svc_inst *svc_inst,
|
|||
(void)memset(&svc_inst->lock_client_addr, 0,
|
||||
sizeof(svc_inst->lock_client_addr));
|
||||
svc_inst->set_lock = BT_CSIP_RELEASE_VALUE;
|
||||
notify_clients(svc_inst, NULL);
|
||||
notify_clients(svc_inst, NULL, FLAG_NOTIFY_LOCK);
|
||||
|
||||
if (svc_inst->cb != NULL && svc_inst->cb->lock_changed != NULL) {
|
||||
bool locked = svc_inst->set_lock == BT_CSIP_LOCK_VALUE;
|
||||
|
@ -640,7 +553,7 @@ static void handle_csip_auth_complete(struct bt_csip_set_member_svc_inst *svc_in
|
|||
memcpy(&client->addr, bt_conn_get_dst(conn), sizeof(bt_addr_le_t));
|
||||
|
||||
/* Send out all pending notifications */
|
||||
k_work_submit(&deferred_nfy_work);
|
||||
notify_work_reschedule(K_NO_WAIT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -701,13 +614,20 @@ static struct bt_conn_auth_info_cb auth_callbacks = {
|
|||
.bond_deleted = csip_bond_deleted
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BT_CSIP_SET_MEMBER_NOTIFIABLE)
|
||||
#define BT_CSIS_CHR_SIRK(_csip) \
|
||||
BT_AUDIO_CHRC(BT_UUID_CSIS_SET_SIRK, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
|
||||
BT_GATT_PERM_READ_ENCRYPT, read_set_sirk, NULL, &_csip), \
|
||||
BT_AUDIO_CCC(set_sirk_cfg_changed)
|
||||
#else
|
||||
#define BT_CSIS_CHR_SIRK(_csip) \
|
||||
BT_AUDIO_CHRC(BT_UUID_CSIS_SET_SIRK, BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, \
|
||||
read_set_sirk, NULL, &_csip)
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER_NOTIFIABLE */
|
||||
|
||||
#define BT_CSIP_SERVICE_DEFINITION(_csip) {\
|
||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_CSIS), \
|
||||
BT_AUDIO_CHRC(BT_UUID_CSIS_SET_SIRK, \
|
||||
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
|
||||
BT_GATT_PERM_READ_ENCRYPT, \
|
||||
read_set_sirk, NULL, &_csip), \
|
||||
BT_AUDIO_CCC(set_sirk_cfg_changed), \
|
||||
BT_CSIS_CHR_SIRK(_csip), \
|
||||
BT_AUDIO_CHRC(BT_UUID_CSIS_SET_SIZE, \
|
||||
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
|
||||
BT_GATT_PERM_READ_ENCRYPT, \
|
||||
|
@ -805,6 +725,25 @@ static void remove_csis_char(const struct bt_uuid *uuid, struct bt_gatt_service
|
|||
__ASSERT(false, "Failed to remove CSIS char %s", bt_uuid_str(uuid));
|
||||
}
|
||||
|
||||
static void notify(struct bt_csip_set_member_svc_inst *svc_inst, struct bt_conn *conn,
|
||||
const struct bt_uuid *uuid, const void *data, uint16_t len)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (svc_inst->service_p == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
err = bt_gatt_notify_uuid(conn, uuid, svc_inst->service_p->attrs, data, len);
|
||||
if (err) {
|
||||
if (err == -ENOTCONN) {
|
||||
LOG_DBG("Notification error: ENOTCONN (%d)", err);
|
||||
} else {
|
||||
LOG_ERR("Notification error: %d", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_cb(struct bt_conn *conn, void *data)
|
||||
{
|
||||
struct bt_conn_info info;
|
||||
|
@ -817,7 +756,7 @@ static void notify_cb(struct bt_conn *conn, void *data)
|
|||
|
||||
if (info.state != BT_CONN_STATE_CONNECTED) {
|
||||
/* Not connected */
|
||||
LOG_DBG("Not connected");
|
||||
LOG_DBG("Not connected: %u", info.state);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -825,22 +764,21 @@ static void notify_cb(struct bt_conn *conn, void *data)
|
|||
struct bt_csip_set_member_svc_inst *svc_inst = &svc_insts[i];
|
||||
struct csip_client *client = &svc_inst->clients[bt_conn_index(conn)];
|
||||
|
||||
if (atomic_test_bit(client->flags, FLAG_SET_MEMBER_LOCK)) {
|
||||
err = notify_lock_value(svc_inst, conn);
|
||||
if (!err) {
|
||||
atomic_clear_bit(client->flags, FLAG_SET_MEMBER_LOCK);
|
||||
if (atomic_test_and_clear_bit(client->flags, FLAG_NOTIFY_LOCK)) {
|
||||
notify(svc_inst, conn, BT_UUID_CSIS_SET_LOCK, &svc_inst->set_lock,
|
||||
sizeof(svc_inst->set_lock));
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_NOTIFIABLE) &&
|
||||
atomic_test_and_clear_bit(client->flags, FLAG_NOTIFY_SIRK)) {
|
||||
notify(svc_inst, conn, BT_UUID_CSIS_SET_SIRK, &svc_inst->set_sirk,
|
||||
sizeof(svc_inst->set_sirk));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void deferred_nfy_work_handler(struct k_work *work)
|
||||
{
|
||||
/* Check if we have unverified notifications in progress */
|
||||
if (atomic_get(¬ify_in_progress)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bt_conn_foreach(BT_CONN_TYPE_LE, notify_cb, NULL);
|
||||
}
|
||||
|
||||
|
@ -973,6 +911,44 @@ int bt_csip_set_member_unregister(struct bt_csip_set_member_svc_inst *svc_inst)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bt_csip_set_member_set_sirk(struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE])
|
||||
{
|
||||
CHECKIF(svc_inst == NULL) {
|
||||
LOG_DBG("NULL svc_inst");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CHECKIF(sirk == NULL) {
|
||||
LOG_DBG("NULL SIRK");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(svc_inst->set_sirk.value, sirk, BT_CSIP_SET_SIRK_SIZE);
|
||||
|
||||
notify_clients(svc_inst, NULL, FLAG_NOTIFY_SIRK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_csip_set_member_get_sirk(struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
uint8_t sirk[BT_CSIP_SET_SIRK_SIZE])
|
||||
{
|
||||
CHECKIF(svc_inst == NULL) {
|
||||
LOG_DBG("NULL svc_inst");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CHECKIF(sirk == NULL) {
|
||||
LOG_DBG("NULL SIRK");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(sirk, svc_inst->set_sirk.value, BT_CSIP_SET_SIRK_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_csip_set_member_lock(struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
bool lock, bool force)
|
||||
{
|
||||
|
@ -987,7 +963,7 @@ int bt_csip_set_member_lock(struct bt_csip_set_member_svc_inst *svc_inst,
|
|||
|
||||
if (!lock && force) {
|
||||
svc_inst->set_lock = BT_CSIP_RELEASE_VALUE;
|
||||
notify_clients(svc_inst, NULL);
|
||||
notify_clients(svc_inst, NULL, FLAG_NOTIFY_LOCK);
|
||||
|
||||
if (svc_inst->cb != NULL && svc_inst->cb->lock_changed != NULL) {
|
||||
svc_inst->cb->lock_changed(NULL, &svc_insts[0], false);
|
||||
|
|
|
@ -228,6 +228,59 @@ static int cmd_cap_acceptor_release(const struct shell *sh, size_t argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_cap_acceptor_set_sirk(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
uint8_t sirk[BT_CSIP_SET_SIRK_SIZE];
|
||||
size_t len;
|
||||
int err;
|
||||
|
||||
if (cap_csip_svc_inst == NULL) {
|
||||
shell_error(sh, "CSIS not registered");
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
len = hex2bin(argv[1], strlen(argv[1]), sirk, sizeof(sirk));
|
||||
if (len != sizeof(sirk)) {
|
||||
shell_error(sh, "Invalid SIRK Length: %zu", len);
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_set_sirk(cap_csip_svc_inst, sirk);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to set SIRK: %d", err);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
shell_print(sh, "SIRK updated");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_cap_acceptor_get_sirk(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
uint8_t sirk[BT_CSIP_SET_SIRK_SIZE];
|
||||
int err;
|
||||
|
||||
if (cap_csip_svc_inst == NULL) {
|
||||
shell_error(sh, "CSIS not registered");
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_get_sirk(cap_csip_svc_inst, sirk);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to get SIRK: %d", err);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
shell_print(sh, "Set SIRK");
|
||||
shell_hexdump(sh, sirk, sizeof(sirk));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_cap_acceptor_set_sirk_rsp(const struct shell *sh, size_t argc,
|
||||
char *argv[])
|
||||
{
|
||||
|
@ -268,6 +321,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(cap_acceptor_cmds,
|
|||
SHELL_CMD_ARG(print_sirk, NULL,
|
||||
"Print the currently used SIRK",
|
||||
cmd_cap_acceptor_print_sirk, 1, 0),
|
||||
SHELL_CMD_ARG(set_sirk, NULL, "Set the currently used SIRK <sirk>",
|
||||
cmd_cap_acceptor_set_sirk, 2, 0),
|
||||
SHELL_CMD_ARG(get_sirk, NULL, "Get the currently used SIRK", cmd_cap_acceptor_get_sirk,
|
||||
1, 0),
|
||||
SHELL_CMD_ARG(set_sirk_rsp, NULL,
|
||||
"Set the response used in SIRK requests "
|
||||
"<accept, accept_enc, reject, oob>",
|
||||
|
|
|
@ -164,6 +164,59 @@ static int cm_csip_set_member_print_sirk(const struct shell *sh, size_t argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_csip_set_member_set_sirk(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
uint8_t sirk[BT_CSIP_SET_SIRK_SIZE];
|
||||
size_t len;
|
||||
int err;
|
||||
|
||||
if (svc_inst == NULL) {
|
||||
shell_error(sh, "CSIS not registered yet");
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
len = hex2bin(argv[1], strlen(argv[1]), sirk, sizeof(sirk));
|
||||
if (len != sizeof(sirk)) {
|
||||
shell_error(sh, "Invalid SIRK Length: %zu", len);
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_set_sirk(svc_inst, sirk);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to set SIRK: %d", err);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
shell_print(sh, "SIRK updated");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_csip_set_member_get_sirk(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
uint8_t sirk[BT_CSIP_SET_SIRK_SIZE];
|
||||
int err;
|
||||
|
||||
if (svc_inst == NULL) {
|
||||
shell_error(sh, "CSIS not registered yet");
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_get_sirk(svc_inst, sirk);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Failed to get SIRK: %d", err);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
shell_print(sh, "Set SIRK");
|
||||
shell_hexdump(sh, sirk, sizeof(sirk));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cm_csip_set_member_lock(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
int err;
|
||||
|
@ -232,20 +285,20 @@ static int cm_csip_set_member(const struct shell *sh, size_t argc, char **argv)
|
|||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
SHELL_STATIC_SUBCMD_SET_CREATE(csip_set_member_cmds,
|
||||
SHELL_STATIC_SUBCMD_SET_CREATE(
|
||||
csip_set_member_cmds,
|
||||
SHELL_CMD_ARG(register, NULL,
|
||||
"Initialize the service and register callbacks "
|
||||
"[size <int>] [rank <int>] [not-lockable] [sirk <data>]",
|
||||
cm_csip_set_member_register, 1, 4),
|
||||
SHELL_CMD_ARG(lock, NULL,
|
||||
"Lock the set",
|
||||
cm_csip_set_member_lock, 1, 0),
|
||||
SHELL_CMD_ARG(release, NULL,
|
||||
"Release the set [force]",
|
||||
cm_csip_set_member_release, 1, 1),
|
||||
SHELL_CMD_ARG(print_sirk, NULL,
|
||||
"Print the currently used SIRK",
|
||||
SHELL_CMD_ARG(lock, NULL, "Lock the set", cm_csip_set_member_lock, 1, 0),
|
||||
SHELL_CMD_ARG(release, NULL, "Release the set [force]", cm_csip_set_member_release, 1, 1),
|
||||
SHELL_CMD_ARG(print_sirk, NULL, "Print the currently used SIRK",
|
||||
cm_csip_set_member_print_sirk, 1, 0),
|
||||
SHELL_CMD_ARG(set_sirk, NULL, "Set the currently used SIRK <sirk>",
|
||||
cmd_csip_set_member_set_sirk, 2, 0),
|
||||
SHELL_CMD_ARG(get_sirk, NULL, "Get the currently used SIRK", cmd_csip_set_member_get_sirk,
|
||||
1, 0),
|
||||
SHELL_CMD_ARG(set_sirk_rsp, NULL,
|
||||
"Set the response used in SIRK requests "
|
||||
"<accept, accept_enc, reject, oob>",
|
||||
|
|
|
@ -69,6 +69,7 @@ CONFIG_BT_MICP_MIC_CTLR_MAX_AICS_INST=2
|
|||
# Coordinated Set Identification
|
||||
CONFIG_BT_CSIP_SET_MEMBER=y
|
||||
CONFIG_BT_CSIP_SET_MEMBER_TEST_SAMPLE_DATA=y
|
||||
CONFIG_BT_CSIP_SET_MEMBER_NOTIFIABLE=y
|
||||
CONFIG_BT_CSIP_SET_COORDINATOR=y
|
||||
CONFIG_BT_CSIP_SET_COORDINATOR_TEST_SAMPLE_DATA=y
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Bose Corporation
|
||||
* Copyright (c) 2020-2022 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2020-2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -22,7 +22,9 @@ static volatile bool set_unlocked;
|
|||
static volatile bool ordered_access_locked;
|
||||
static volatile bool ordered_access_unlocked;
|
||||
static const struct bt_csip_set_coordinator_csis_inst *primary_inst;
|
||||
CREATE_FLAG(flag_sirk_changed);
|
||||
|
||||
static uint8_t connected_member_count;
|
||||
static uint8_t members_found;
|
||||
static struct k_work_delayable discover_members_timer;
|
||||
static bt_addr_le_t addr_found[CONFIG_BT_MAX_CONN];
|
||||
|
@ -113,6 +115,13 @@ static void csip_lock_changed_cb(struct bt_csip_set_coordinator_csis_inst *inst,
|
|||
printk("inst %p %s\n", inst, locked ? "locked" : "released");
|
||||
}
|
||||
|
||||
static void csip_sirk_changed_cb(struct bt_csip_set_coordinator_csis_inst *inst)
|
||||
{
|
||||
printk("Inst %p SIRK changed\n", inst);
|
||||
|
||||
SET_FLAG(flag_sirk_changed);
|
||||
}
|
||||
|
||||
static void csip_set_coordinator_ordered_access_cb(
|
||||
const struct bt_csip_set_coordinator_set_info *set_info, int err,
|
||||
bool locked, struct bt_csip_set_coordinator_set_member *member)
|
||||
|
@ -133,7 +142,8 @@ static struct bt_csip_set_coordinator_cb cbs = {
|
|||
.release_set = csip_set_coordinator_lock_release_cb,
|
||||
.discover = csip_discover_cb,
|
||||
.lock_changed = csip_lock_changed_cb,
|
||||
.ordered_access = csip_set_coordinator_ordered_access_cb
|
||||
.sirk_changed = csip_sirk_changed_cb,
|
||||
.ordered_access = csip_set_coordinator_ordered_access_cb,
|
||||
};
|
||||
|
||||
static bool csip_set_coordinator_oap_cb(const struct bt_csip_set_coordinator_set_info *set_info,
|
||||
|
@ -263,12 +273,9 @@ static void discover_csis(struct bt_conn *conn)
|
|||
WAIT_FOR_COND(discovered);
|
||||
}
|
||||
|
||||
static void test_main(void)
|
||||
static void init(void)
|
||||
{
|
||||
int err;
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
const struct bt_csip_set_coordinator_set_member *locked_members[CONFIG_BT_MAX_CONN];
|
||||
uint8_t connected_member_count = 0;
|
||||
|
||||
err = bt_enable(NULL);
|
||||
if (err != 0) {
|
||||
|
@ -282,21 +289,31 @@ static void test_main(void)
|
|||
k_work_init_delayable(&discover_members_timer,
|
||||
discover_members_timer_handler);
|
||||
bt_le_scan_cb_register(&csip_set_coordinator_scan_callbacks);
|
||||
}
|
||||
|
||||
static void connect_set(void)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
int err;
|
||||
|
||||
connected_member_count = 0U;
|
||||
|
||||
err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
|
||||
if (err != 0) {
|
||||
FAIL("Scanning failed to start (err %d)\n", err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Scanning successfully started\n");
|
||||
|
||||
WAIT_FOR_COND(members_found == 1);
|
||||
WAIT_FOR_COND(members_found == 1U);
|
||||
|
||||
printk("Stopping scan\n");
|
||||
err = bt_le_scan_stop();
|
||||
if (err != 0) {
|
||||
FAIL("Could not stop scan");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -305,6 +322,7 @@ static void test_main(void)
|
|||
BT_LE_CONN_PARAM_DEFAULT, &conns[0]);
|
||||
if (err != 0) {
|
||||
FAIL("Failed to connect to %s: %d\n", err);
|
||||
|
||||
return;
|
||||
}
|
||||
printk("Connecting to %s\n", addr);
|
||||
|
@ -318,6 +336,7 @@ static void test_main(void)
|
|||
err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL);
|
||||
if (err != 0) {
|
||||
FAIL("Could not start scan: %d", err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -325,10 +344,11 @@ static void test_main(void)
|
|||
BT_CSIP_SET_COORDINATOR_DISCOVER_TIMER_VALUE);
|
||||
if (err < 0) { /* Can return 0, 1 and 2 for success */
|
||||
FAIL("Could not schedule discover_members_timer %d", err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (primary_inst->info.set_size > 0) {
|
||||
if (primary_inst->info.set_size > 0U) {
|
||||
WAIT_FOR_COND(members_found == primary_inst->info.set_size);
|
||||
|
||||
(void)k_work_cancel_delayable(&discover_members_timer);
|
||||
|
@ -339,6 +359,7 @@ static void test_main(void)
|
|||
err = bt_le_scan_stop();
|
||||
if (err != 0) {
|
||||
FAIL("Scanning failed to stop (err %d)\n", err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -347,12 +368,11 @@ static void test_main(void)
|
|||
|
||||
UNSET_FLAG(flag_connected);
|
||||
printk("Connecting to member[%d] (%s)", i, addr);
|
||||
err = bt_conn_le_create(&addr_found[i],
|
||||
BT_CONN_LE_CREATE_CONN,
|
||||
BT_LE_CONN_PARAM_DEFAULT,
|
||||
&conns[i]);
|
||||
err = bt_conn_le_create(&addr_found[i], BT_CONN_LE_CREATE_CONN,
|
||||
BT_LE_CONN_PARAM_DEFAULT, &conns[i]);
|
||||
if (err != 0) {
|
||||
FAIL("Failed to connect to %s: %d\n", addr, err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -363,6 +383,33 @@ static void test_main(void)
|
|||
printk("Doing discovery on member[%u]", i);
|
||||
discover_csis(conns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void disconnect_set(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < connected_member_count; i++) {
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
int err;
|
||||
|
||||
bt_addr_le_to_str(&addr_found[i], addr, sizeof(addr));
|
||||
|
||||
printk("Disconnecting member[%u] (%s)", i, addr);
|
||||
err = bt_conn_disconnect(conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
||||
(void)memset(&set_members[i], 0, sizeof(set_members[i]));
|
||||
if (err != 0) {
|
||||
FAIL("Failed to do disconnect\n", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_main(void)
|
||||
{
|
||||
const struct bt_csip_set_coordinator_set_member *locked_members[CONFIG_BT_MAX_CONN];
|
||||
int err;
|
||||
|
||||
init();
|
||||
connect_set();
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(locked_members); i++) {
|
||||
locked_members[i] = set_members[i];
|
||||
|
@ -436,17 +483,23 @@ static void test_main(void)
|
|||
WAIT_FOR_COND(set_unlocked);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < members_found; i++) {
|
||||
printk("Disconnecting member[%u] (%s)", i, addr);
|
||||
err = bt_conn_disconnect(conns[i],
|
||||
BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
||||
(void)memset(&set_members[i], 0, sizeof(set_members[i]));
|
||||
if (err != 0) {
|
||||
FAIL("Failed to do disconnect\n", err);
|
||||
return;
|
||||
}
|
||||
disconnect_set();
|
||||
|
||||
PASS("All members disconnected\n");
|
||||
}
|
||||
|
||||
static void test_new_sirk(void)
|
||||
{
|
||||
init();
|
||||
connect_set();
|
||||
|
||||
backchannel_sync_send_all();
|
||||
backchannel_sync_wait_all();
|
||||
|
||||
WAIT_FOR_FLAG(flag_sirk_changed);
|
||||
|
||||
disconnect_set();
|
||||
|
||||
PASS("All members disconnected\n");
|
||||
}
|
||||
|
||||
|
@ -468,7 +521,6 @@ static void test_args(int argc, char *argv[])
|
|||
}
|
||||
|
||||
static const struct bst_test_instance test_connect[] = {
|
||||
|
||||
{
|
||||
.test_id = "csip_set_coordinator",
|
||||
.test_post_init_f = test_init,
|
||||
|
@ -476,8 +528,15 @@ static const struct bst_test_instance test_connect[] = {
|
|||
.test_main_f = test_main,
|
||||
.test_args_f = test_args,
|
||||
},
|
||||
|
||||
BSTEST_END_MARKER};
|
||||
{
|
||||
.test_id = "csip_set_coordinator_new_sirk",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_new_sirk,
|
||||
.test_args_f = test_args,
|
||||
},
|
||||
BSTEST_END_MARKER,
|
||||
};
|
||||
|
||||
struct bst_test_list *test_csip_set_coordinator_install(struct bst_test_list *tests)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Bose Corporation
|
||||
* Copyright (c) 2020-2022 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2020-2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -76,6 +76,35 @@ static void bt_ready(int err)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_set_sirk(void)
|
||||
{
|
||||
const uint8_t new_set_sirk[] = {0xff, 0xcc, 0x72, 0xdd, 0x86, 0x8c, 0xcd, 0xce,
|
||||
0x22, 0xfd, 0xa1, 0x21, 0x09, 0x7d, 0x7d, 0x45};
|
||||
uint8_t tmp_sirk[BT_CSIP_SET_SIRK_SIZE];
|
||||
int err;
|
||||
|
||||
printk("Setting new SIRK\n");
|
||||
err = bt_csip_set_member_set_sirk(svc_inst, new_set_sirk);
|
||||
if (err != 0) {
|
||||
FAIL("Failed to set SIRK: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Getting new SIRK\n");
|
||||
err = bt_csip_set_member_get_sirk(svc_inst, tmp_sirk);
|
||||
if (err != 0) {
|
||||
FAIL("Failed to get SIRK: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(new_set_sirk, tmp_sirk, BT_CSIP_SET_SIRK_SIZE) != 0) {
|
||||
FAIL("The SIRK set and the SIRK set were different\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("New SIRK correctly set and retrieved\n");
|
||||
}
|
||||
|
||||
static void test_main(void)
|
||||
{
|
||||
int err;
|
||||
|
@ -88,6 +117,18 @@ static void test_main(void)
|
|||
}
|
||||
|
||||
WAIT_FOR_FLAG(flag_connected);
|
||||
|
||||
if (param.lockable) {
|
||||
/* Waiting for lock */
|
||||
WAIT_FOR_COND(g_locked);
|
||||
/* Waiting for lock release */
|
||||
WAIT_FOR_COND(!g_locked);
|
||||
/* Waiting for lock */
|
||||
WAIT_FOR_COND(g_locked);
|
||||
/* Waiting for lock release */
|
||||
WAIT_FOR_COND(!g_locked);
|
||||
}
|
||||
|
||||
WAIT_FOR_UNSET_FLAG(flag_connected);
|
||||
|
||||
err = bt_csip_set_member_unregister(svc_inst);
|
||||
|
@ -136,6 +177,36 @@ static void test_csip_enc(void)
|
|||
test_main();
|
||||
}
|
||||
|
||||
static void test_new_sirk(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_enable(bt_ready);
|
||||
|
||||
if (err != 0) {
|
||||
FAIL("Bluetooth init failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
WAIT_FOR_FLAG(flag_connected);
|
||||
|
||||
backchannel_sync_send_all();
|
||||
backchannel_sync_wait_all();
|
||||
|
||||
test_set_sirk();
|
||||
|
||||
WAIT_FOR_UNSET_FLAG(flag_connected);
|
||||
|
||||
err = bt_csip_set_member_unregister(svc_inst);
|
||||
if (err != 0) {
|
||||
FAIL("Could not unregister CSIP (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
svc_inst = NULL;
|
||||
|
||||
PASS("CSIP Set member passed: Client successfully disconnected\n");
|
||||
}
|
||||
|
||||
static void test_args(int argc, char *argv[])
|
||||
{
|
||||
for (size_t argn = 0; argn < argc; argn++) {
|
||||
|
@ -186,8 +257,14 @@ static const struct bst_test_instance test_connect[] = {
|
|||
.test_main_f = test_csip_enc,
|
||||
.test_args_f = test_args,
|
||||
},
|
||||
|
||||
BSTEST_END_MARKER
|
||||
{
|
||||
.test_id = "csip_set_member_new_sirk",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_new_sirk,
|
||||
.test_args_f = test_args,
|
||||
},
|
||||
BSTEST_END_MARKER,
|
||||
};
|
||||
|
||||
struct bst_test_list *test_csip_set_member_install(struct bst_test_list *tests)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2023 Nordic Semiconductor ASA
|
||||
# Copyright (c) 2023-2024 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
|
@ -12,6 +12,8 @@ $dir_path/csip_encrypted_sirk.sh
|
|||
|
||||
$dir_path/csip_forced_release.sh
|
||||
|
||||
$dir_path/csip_new_sirk.sh
|
||||
|
||||
$dir_path/csip_no_lock.sh
|
||||
|
||||
$dir_path/csip_no_rank.sh
|
||||
|
|
39
tests/bsim/bluetooth/audio/test_scripts/csip_new_sirk.sh
Executable file
39
tests/bsim/bluetooth/audio/test_scripts/csip_new_sirk.sh
Executable file
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Basic CSIP test. A set coordinator connects to multiple set members
|
||||
# lock thems, unlocks them and disconnects.
|
||||
|
||||
source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
|
||||
|
||||
VERBOSITY_LEVEL=2
|
||||
EXECUTE_TIMEOUT=30
|
||||
|
||||
cd ${BSIM_OUT_PATH}/bin
|
||||
|
||||
SIMULATION_ID="csip_new_sirk"
|
||||
|
||||
Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \
|
||||
-v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=csip_set_coordinator_new_sirk \
|
||||
-RealEncryption=1 -rs=1 -D=4
|
||||
|
||||
Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \
|
||||
-v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=csip_set_member_new_sirk \
|
||||
-RealEncryption=1 -rs=2 -D=4 -argstest rank 1
|
||||
|
||||
Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \
|
||||
-v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=csip_set_member_new_sirk \
|
||||
-RealEncryption=1 -rs=3 -D=4 -argstest rank 2
|
||||
|
||||
Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \
|
||||
-v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=3 -testid=csip_set_member_new_sirk \
|
||||
-RealEncryption=1 -rs=4 -D=4 -argstest rank 3
|
||||
|
||||
# Simulation time should be larger than the WAIT_TIME in common.h
|
||||
Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \
|
||||
-D=4 -sim_length=60e6 $@
|
||||
|
||||
wait_for_background_jobs
|
Loading…
Add table
Add a link
Reference in a new issue