Bluetooth: has: Make HAS registration dynamic
This changes HAS registration to be dynamic and let's the application set Hearing Aid Type and binaural features. Often, devices are flashed with generic firmware with some features stored post factory production, requiring the settings to be moved from compile time to run-time. This change will increase the RAM usage as the GATT service is moved from ROM to RAM. Signed-off-by: Lars Knudsen <larsgk@gmail.com> Co-author: Soren Engquist <soren@engquist.dk>
This commit is contained in:
parent
c0455b836f
commit
081b83531b
15 changed files with 201 additions and 117 deletions
|
@ -14,49 +14,6 @@ menuconfig BT_HAS
|
|||
|
||||
if BT_HAS
|
||||
|
||||
choice BT_HAS_HEARING_AID_TYPE_CHOICE
|
||||
prompt "Hearing Aid Type selection"
|
||||
help
|
||||
Select the Hearing Aid Type to compile.
|
||||
|
||||
config BT_HAS_HEARING_AID_MONAURAL
|
||||
bool "Monaural Hearing Aid"
|
||||
|
||||
config BT_HAS_HEARING_AID_BINAURAL
|
||||
depends on BT_CSIP_SET_MEMBER
|
||||
bool "Binaural Hearing Aid"
|
||||
|
||||
config BT_HAS_HEARING_AID_BANDED
|
||||
bool "Banded Hearing Aid"
|
||||
|
||||
endchoice # BT_HAS_HEARING_AID_TYPE_CHOICE
|
||||
|
||||
if BT_HAS_HEARING_AID_MONAURAL || BT_HAS_HEARING_AID_BINAURAL
|
||||
|
||||
choice BT_HAS_HEARING_AID_LOCATION
|
||||
prompt "Hearing Aid Device Location"
|
||||
help
|
||||
Select the Hearing Aid Device location.
|
||||
|
||||
config BT_HAS_HEARING_AID_LEFT
|
||||
bool "Left Ear"
|
||||
|
||||
config BT_HAS_HEARING_AID_RIGHT
|
||||
bool "Right Ear"
|
||||
|
||||
endchoice # BT_HAS_HEARING_AID_LOCATION
|
||||
|
||||
endif # BT_HAS_HEARING_AID_MONAURAL || BT_HAS_HEARING_AID_BINAURAL
|
||||
|
||||
config BT_HAS_HEARING_AID_TYPE
|
||||
int # hidden
|
||||
range 0 2
|
||||
default 0 if BT_HAS_HEARING_AID_BINAURAL
|
||||
default 1 if BT_HAS_HEARING_AID_MONAURAL
|
||||
default 2 if BT_HAS_HEARING_AID_BANDED
|
||||
help
|
||||
The value shall be one of 3 defined by the HAS 1.0 specification table 3.2
|
||||
|
||||
config BT_HAS_PRESET_COUNT
|
||||
int "Preset record list size"
|
||||
default 2
|
||||
|
@ -70,24 +27,6 @@ config BT_HAS_PRESET_SUPPORT
|
|||
|
||||
if BT_HAS_PRESET_SUPPORT
|
||||
|
||||
if BT_HAS_HEARING_AID_BINAURAL
|
||||
|
||||
config BT_HAS_IDENTICAL_PRESET_RECORDS
|
||||
bool "Identical preset records in Binaural Hearing Aid Set"
|
||||
help
|
||||
Set if the list of preset records is identical to the list of preset records
|
||||
on the other member in the Binaural Hearing Aid Set.
|
||||
This option sets Independent Presets field in Hearing Aid Features to 0b0.
|
||||
|
||||
config BT_HAS_PRESET_SYNC_SUPPORT
|
||||
bool "Preset synchronization support"
|
||||
depends on BT_HAS_IDENTICAL_PRESET_RECORDS
|
||||
help
|
||||
Set if the hearing aid has support for relaying active preset changes to the other
|
||||
member in the Binaural Hearing Aid Set.
|
||||
|
||||
endif # BT_HAS_HEARING_AID_BINAURAL
|
||||
|
||||
config BT_HAS_PRESET_NAME_DYNAMIC
|
||||
bool "Allow to set preset name on runtime"
|
||||
help
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/check.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
|
||||
|
@ -70,7 +71,7 @@ static ssize_t read_features(struct bt_conn *conn, const struct bt_gatt_attr *at
|
|||
}
|
||||
|
||||
/* Hearing Access Service GATT Attributes */
|
||||
BT_GATT_SERVICE_DEFINE(has_svc,
|
||||
static struct bt_gatt_attr has_attrs[] = {
|
||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_HAS),
|
||||
BT_AUDIO_CHRC(BT_UUID_HAS_HEARING_AID_FEATURES,
|
||||
BT_GATT_CHRC_READ,
|
||||
|
@ -92,11 +93,13 @@ BT_GATT_SERVICE_DEFINE(has_svc,
|
|||
read_active_preset_index, NULL, NULL),
|
||||
BT_AUDIO_CCC(ccc_cfg_changed),
|
||||
#endif /* CONFIG_BT_HAS_PRESET_SUPPORT */
|
||||
);
|
||||
};
|
||||
|
||||
static struct bt_gatt_service has_svc;
|
||||
|
||||
#if defined(CONFIG_BT_HAS_PRESET_SUPPORT)
|
||||
#define PRESET_CONTROL_POINT_ATTR &has_svc.attrs[4]
|
||||
#define ACTIVE_PRESET_INDEX_ATTR &has_svc.attrs[7]
|
||||
#define PRESET_CONTROL_POINT_ATTR &has_attrs[4]
|
||||
#define ACTIVE_PRESET_INDEX_ATTR &has_attrs[7]
|
||||
|
||||
static struct has_client {
|
||||
struct bt_conn *conn;
|
||||
|
@ -865,19 +868,19 @@ static uint8_t handle_control_point_op(struct bt_conn *conn, struct net_buf_simp
|
|||
case BT_HAS_OP_SET_PREV_PRESET:
|
||||
return handle_set_prev_preset(false);
|
||||
case BT_HAS_OP_SET_ACTIVE_PRESET_SYNC:
|
||||
if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SYNC_SUPPORT)) {
|
||||
if ((has.features & BT_HAS_FEAT_PRESET_SYNC_SUPP) != 0) {
|
||||
return handle_set_active_preset(buf, true);
|
||||
} else {
|
||||
return BT_HAS_ERR_PRESET_SYNC_NOT_SUPP;
|
||||
}
|
||||
case BT_HAS_OP_SET_NEXT_PRESET_SYNC:
|
||||
if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SYNC_SUPPORT)) {
|
||||
if ((has.features & BT_HAS_FEAT_PRESET_SYNC_SUPP) != 0) {
|
||||
return handle_set_next_preset(true);
|
||||
} else {
|
||||
return BT_HAS_ERR_PRESET_SYNC_NOT_SUPP;
|
||||
}
|
||||
case BT_HAS_OP_SET_PREV_PRESET_SYNC:
|
||||
if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SYNC_SUPPORT)) {
|
||||
if ((has.features & BT_HAS_FEAT_PRESET_SYNC_SUPP) != 0) {
|
||||
return handle_set_prev_preset(true);
|
||||
} else {
|
||||
return BT_HAS_ERR_PRESET_SYNC_NOT_SUPP;
|
||||
|
@ -1123,48 +1126,51 @@ int bt_has_preset_name_change(uint8_t index, const char *name)
|
|||
}
|
||||
#endif /* CONFIG_BT_HAS_PRESET_SUPPORT */
|
||||
|
||||
static int has_init(const struct device *dev)
|
||||
int bt_has_register(const struct bt_has_register_param *param)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
int err;
|
||||
|
||||
LOG_DBG("param %p", param);
|
||||
|
||||
CHECKIF(!param) {
|
||||
LOG_DBG("NULL params pointer");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize the supported features characteristic value */
|
||||
has.features = CONFIG_BT_HAS_HEARING_AID_TYPE & BT_HAS_FEAT_HEARING_AID_TYPE_MASK;
|
||||
has.features = param->type;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SUPPORT)) {
|
||||
has.features |= BT_HAS_FEAT_DYNAMIC_PRESETS;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_HAS_HEARING_AID_BINAURAL)) {
|
||||
if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SYNC_SUPPORT)) {
|
||||
has.features |= BT_HAS_FEAT_PRESET_SYNC_SUPP;
|
||||
if (param->preset_sync_support) {
|
||||
if (param->type != BT_HAS_HEARING_AID_TYPE_BINAURAL) {
|
||||
LOG_DBG("Preset sync support only available for binaural hearing aid type");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_HAS_IDENTICAL_PRESET_RECORDS)) {
|
||||
has.features |= BT_HAS_FEAT_INDEPENDENT_PRESETS;
|
||||
has.features |= BT_HAS_FEAT_PRESET_SYNC_SUPP;
|
||||
}
|
||||
|
||||
if (param->independent_presets) {
|
||||
if (param->type != BT_HAS_HEARING_AID_TYPE_BINAURAL) {
|
||||
LOG_DBG("Independent presets only available for binaural hearing aid type");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
has.features |= BT_HAS_FEAT_INDEPENDENT_PRESETS;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC)) {
|
||||
has.features |= BT_HAS_FEAT_WRITABLE_PRESETS_SUPP;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) {
|
||||
if (IS_ENABLED(CONFIG_BT_HAS_HEARING_AID_BANDED)) {
|
||||
/* HAP_d1.0r00; 3.7 BAP Unicast Server role requirements
|
||||
* A Banded Hearing Aid in the HA role shall set the
|
||||
* Front Left and the Front Right bits to a value of 0b1
|
||||
* in the Sink Audio Locations characteristic value.
|
||||
*/
|
||||
bt_pacs_set_location(BT_AUDIO_DIR_SINK,
|
||||
(BT_AUDIO_LOCATION_FRONT_LEFT |
|
||||
BT_AUDIO_LOCATION_FRONT_RIGHT));
|
||||
} else if (IS_ENABLED(CONFIG_BT_HAS_HEARING_AID_LEFT)) {
|
||||
bt_pacs_set_location(BT_AUDIO_DIR_SINK,
|
||||
BT_AUDIO_LOCATION_FRONT_LEFT);
|
||||
} else {
|
||||
bt_pacs_set_location(BT_AUDIO_DIR_SINK,
|
||||
BT_AUDIO_LOCATION_FRONT_RIGHT);
|
||||
}
|
||||
has_svc = (struct bt_gatt_service)BT_GATT_SERVICE(has_attrs);
|
||||
err = bt_gatt_service_register(&has_svc);
|
||||
if (err != 0) {
|
||||
LOG_DBG("HAS service register failed: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_HAS_PRESET_SUPPORT)
|
||||
|
@ -1173,5 +1179,3 @@ static int has_init(const struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(has_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||
|
|
|
@ -75,6 +75,43 @@ static int cmd_preset_unreg(const struct shell *sh, size_t argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_has_register(const struct shell *sh, size_t argc, char **argv)
|
||||
{
|
||||
int err;
|
||||
struct bt_has_register_param param = {
|
||||
.type = BT_HAS_HEARING_AID_TYPE_MONAURAL,
|
||||
.preset_sync_support = false,
|
||||
.independent_presets = false
|
||||
};
|
||||
|
||||
for (size_t argn = 1; argn < argc; argn++) {
|
||||
const char *arg = argv[argn];
|
||||
|
||||
if (strcmp(arg, "binaural") == 0) {
|
||||
param.type = BT_HAS_HEARING_AID_TYPE_BINAURAL;
|
||||
} else if (strcmp(arg, "monaural") == 0) {
|
||||
param.type = BT_HAS_HEARING_AID_TYPE_MONAURAL;
|
||||
} else if (strcmp(arg, "banded") == 0) {
|
||||
param.type = BT_HAS_HEARING_AID_TYPE_BANDED;
|
||||
} else if (strcmp(arg, "sync") == 0) {
|
||||
param.preset_sync_support = true;
|
||||
} else if (strcmp(arg, "independent") == 0) {
|
||||
param.independent_presets = true;
|
||||
} else {
|
||||
shell_help(sh);
|
||||
return SHELL_CMD_HELP_PRINTED;
|
||||
}
|
||||
}
|
||||
|
||||
err = bt_has_register(¶m);
|
||||
if (err != 0) {
|
||||
shell_error(sh, "Could not register HAS: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct print_list_entry_data {
|
||||
int num;
|
||||
const struct shell *sh;
|
||||
|
@ -216,6 +253,10 @@ static int cmd_has(const struct shell *sh, size_t argc, char **argv)
|
|||
}
|
||||
|
||||
SHELL_STATIC_SUBCMD_SET_CREATE(has_cmds,
|
||||
SHELL_CMD_ARG(register, NULL,
|
||||
"Initialize the service and register type "
|
||||
"[binaural | monaural(default) | banded] [sync] [independent]",
|
||||
cmd_has_register, 1, 3),
|
||||
SHELL_CMD_ARG(preset-reg, NULL, "Register preset <index> <properties> <name>",
|
||||
cmd_preset_reg, 4, 0),
|
||||
SHELL_CMD_ARG(preset-unreg, NULL, "Unregister preset <index>", cmd_preset_unreg, 2, 0),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue