Message ID | 20230525153452.125789-6-silviu.barbulescu@nxp.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Add initial support for BAP broadcast source | expand |
Context | Check | Description |
---|---|---|
tedd_an/pre-ci_am | success | Success |
tedd_an/CheckPatch | warning | WARNING:LONG_LINE: line length of 86 exceeds 80 columns #211: FILE: client/player.c:1796: + if ((!cfg->ep->broadcast) && (cfg->ep->iso_group != BT_ISO_QOS_GROUP_UNSET)) { WARNING:LONG_LINE: line length of 88 exceeds 80 columns #224: FILE: client/player.c:1806: + if ((!cfg->ep->broadcast) && (cfg->ep->iso_stream != BT_ISO_QOS_STREAM_UNSET)) { WARNING:LONG_LINE_STRING: line length of 81 exceeds 80 columns #243: FILE: client/player.c:1823: + bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false"); WARNING:LONG_LINE: line length of 92 exceeds 80 columns #250: FILE: client/player.c:1828: + bt_shell_printf("Framing %s\n", bcast_qos.bcast.framing ? "true" : "false"); WARNING:LONG_LINE: line length of 82 exceeds 80 columns #253: FILE: client/player.c:1831: + &bcast_qos.bcast.framing); WARNING:LONG_LINE: line length of 106 exceeds 80 columns #309: FILE: client/player.c:1904: + DBUS_TYPE_BYTE, &cfg->ep->bcode->iov_base, WARNING:LONG_LINE: line length of 89 exceeds 80 columns #310: FILE: client/player.c:1905: + cfg->ep->bcode->iov_len); WARNING:LONG_LINE: line length of 98 exceeds 80 columns #322: FILE: client/player.c:1947: + iov_append(&cfg->ep->bcode, bcast_qos.bcast.bcode, sizeof(bcast_qos.bcast.bcode)); WARNING:LONG_LINE: line length of 81 exceeds 80 columns #324: FILE: client/player.c:1949: + iov_append(&cfg->caps, base_lc3_16_2_1, sizeof(base_lc3_16_2_1)); WARNING:LONG_LINE: line length of 84 exceeds 80 columns #327: FILE: client/player.c:1952: + iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len); WARNING:LONG_LINE: line length of 94 exceeds 80 columns #384: FILE: client/player.c:2408: + bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_iso_stream, ep); WARNING:LONG_LINE: line length of 94 exceeds 80 columns #386: FILE: client/player.c:2410: + bt_shell_prompt_input(ep->path, "BIS (auto/value):", endpoint_iso_stream, ep); WARNING:LONG_LINE: line length of 93 exceeds 80 columns #396: FILE: client/player.c:2433: + bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep); WARNING:LONG_LINE: line length of 93 exceeds 80 columns #398: FILE: client/player.c:2435: + bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep); WARNING:LONG_LINE: line length of 93 exceeds 80 columns #420: FILE: client/player.c:2461: + bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep); WARNING:LONG_LINE: line length of 93 exceeds 80 columns #422: FILE: client/player.c:2463: + bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep); WARNING:LONG_LINE_STRING: line length of 86 exceeds 80 columns #451: FILE: client/player.c:3755: + bt_shell_printf("Transport %s already in acquiring process\n", WARNING:LONG_LINE_STRING: line length of 89 exceeds 80 columns #463: FILE: client/player.c:3767: + bt_shell_printf("Link %s already in acquiring process\n", WARNING:LONG_LINE: line length of 82 exceeds 80 columns #465: FILE: client/player.c:3769: + return bt_shell_noninteractive_quit(EXIT_FAILURE); /github/workspace/src/src/13255387.patch total: 0 errors, 19 warnings, 350 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/src/13255387.patch has style problems, please review. NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. |
tedd_an/GitLint | success | Gitlint PASS |
tedd_an/IncrementalBuild | success | Incremental Build PASS |
Hi Silviu, On Thu, May 25, 2023 at 8:37 AM Silviu Florian Barbulescu <silviu.barbulescu@nxp.com> wrote: > > This adds bluetoothctl support for broadcast source. You forgot to add an example of how these changes can be used in the patch description, I know you have it in the cover letter but that will not be committed. > --- > client/player.c | 209 ++++++++++++++++++++++++++++++++++++++++++------ > 1 file changed, 185 insertions(+), 24 deletions(-) > > diff --git a/client/player.c b/client/player.c > index a9f56fb94..408118fca 100644 > --- a/client/player.c > +++ b/client/player.c > @@ -74,11 +74,13 @@ struct endpoint { > bool auto_accept; > bool acquiring; > uint8_t max_transports; > - uint8_t cig; > - uint8_t cis; > + uint8_t iso_group; > + uint8_t iso_stream; > char *transport; > DBusMessage *msg; > struct preset *preset; > + bool broadcast; > + struct iovec *bcode; > }; > > static DBusConnection *dbus_conn; > @@ -104,6 +106,22 @@ struct transport { > struct io *timer_io; > }; > > +static const uint8_t base_lc3_16_2_1[] = { > + 0x28, 0x00, 0x00, /* Presentation Delay */ > + 0x01, /* Number of Subgroups */ > + 0x01, /* Number of BIS */ > + 0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */ > + 0x11, /* Codec Specific Configuration */ > + 0x02, 0x01, 0x03, /* 16 KHZ */ > + 0x02, 0x02, 0x01, /* 10 ms */ > + 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, /* Front Left */ > + 0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */ > + 0x04, /* Metadata */ > + 0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */ > + 0x01, /* BIS */ > + 0x00, /* Codec Specific Configuration */ > +}; > + > static void endpoint_unregister(void *data) > { > struct endpoint *ep = data; > @@ -1154,6 +1172,16 @@ static const struct capabilities { > CODEC_CAPABILITIES(PAC_SOURCE_UUID, LC3_ID, > LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, > 3u, 30, 240)), > + /* Broadcast LC3 Source: > + * > + * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz > + * Duration: 7.5 ms 10 ms > + * Channel count: 3 > + * Frame length: 30-240 > + */ > + CODEC_CAPABILITIES(BAA_SERVICE_UUID, LC3_ID, > + LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, > + 3u, 30, 240)), > }; > > struct codec_qos { > @@ -1435,6 +1463,7 @@ static struct preset { > PRESET(A2DP_SINK_UUID, A2DP_CODEC_SBC, sbc_presets, 6), > PRESET(PAC_SINK_UUID, LC3_ID, lc3_presets, 3), > PRESET(PAC_SOURCE_UUID, LC3_ID, lc3_presets, 3), > + PRESET(BAA_SERVICE_UUID, LC3_ID, lc3_presets, 3), > }; > > static void parse_vendor_codec(const char *codec, uint16_t *vid, uint16_t *cid) > @@ -1707,6 +1736,27 @@ struct endpoint_config { > const struct codec_qos *qos; > }; > > +#define BCODE {0x01, 0x02, 0x68, 0x05, 0x53, 0xf1, 0x41, 0x5a, \ > + 0xa2, 0x65, 0xbb, 0xaf, 0xc6, 0xea, 0x03, 0xb8} > + > +static struct bt_iso_qos bcast_qos = { > + .bcast = { > + .big = BT_ISO_QOS_BIG_UNSET, > + .bis = BT_ISO_QOS_BIS_UNSET, > + .sync_interval = 0x07, > + .packing = 0x00, > + .framing = 0x00, > + .encryption = 0x00, > + .bcode = BCODE, > + .options = 0x00, > + .skip = 0x0000, > + .sync_timeout = 0x4000, > + .sync_cte_type = 0x00, > + .mse = 0x00, > + .timeout = 0x4000, > + } > + }; > + > static void append_properties(DBusMessageIter *iter, > struct endpoint_config *cfg) > { > @@ -1714,6 +1764,7 @@ static void append_properties(DBusMessageIter *iter, > struct codec_qos *qos = (void *)cfg->qos; > const char *key = "Capabilities"; > const char *meta = "Metadata"; > + const char *keyBCode = "BroadcastCode"; > > dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict); > > @@ -1742,16 +1793,25 @@ static void append_properties(DBusMessageIter *iter, > DBUS_TYPE_BYTE, &cfg->target_latency); > } > > - if (cfg->ep->cig != BT_ISO_QOS_CIG_UNSET) { > - bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->cig); > + if ((!cfg->ep->broadcast) && (cfg->ep->iso_group != BT_ISO_QOS_GROUP_UNSET)) { > + bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->iso_group); > g_dbus_dict_append_entry(&dict, "CIG", DBUS_TYPE_BYTE, > - &cfg->ep->cig); > + &cfg->ep->iso_group); > + } else { > + bt_shell_printf("BIG 0x%2.2x\n", bcast_qos.bcast.big); > + g_dbus_dict_append_entry(&dict, "BIG", DBUS_TYPE_BYTE, > + &bcast_qos.bcast.big); > } > > - if (cfg->ep->cis != BT_ISO_QOS_CIS_UNSET) { > - bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->cis); > + if ((!cfg->ep->broadcast) && (cfg->ep->iso_stream != BT_ISO_QOS_STREAM_UNSET)) { > + bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->iso_stream); > g_dbus_dict_append_entry(&dict, "CIS", DBUS_TYPE_BYTE, > - &cfg->ep->cis); > + &cfg->ep->iso_stream); > + > + } else { > + bt_shell_printf("BIS 0x%2.2x\n", bcast_qos.bcast.bis); > + g_dbus_dict_append_entry(&dict, "BIS", DBUS_TYPE_BYTE, > + &bcast_qos.bcast.bis); > } > > bt_shell_printf("Interval %u\n", qos->interval); > @@ -1759,10 +1819,17 @@ static void append_properties(DBusMessageIter *iter, > g_dbus_dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT32, > &qos->interval); > > - bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false"); > + if (!cfg->ep->broadcast) { > + bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false"); > > - g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, > - &qos->framing); > + g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, > + &qos->framing); > + } else { > + bt_shell_printf("Framing %s\n", bcast_qos.bcast.framing ? "true" : "false"); > + > + g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, > + &bcast_qos.bcast.framing); > + } > > bt_shell_printf("PHY %s\n", qos->phy); > > @@ -1787,6 +1854,56 @@ static void append_properties(DBusMessageIter *iter, > g_dbus_dict_append_entry(&dict, "Delay", DBUS_TYPE_UINT32, > &qos->delay); > > + if (!cfg->ep->broadcast) > + goto done; > + > + bt_shell_printf("SyncInterval %u\n", bcast_qos.bcast.sync_interval); > + > + g_dbus_dict_append_entry(&dict, "SyncInterval", DBUS_TYPE_BYTE, > + &bcast_qos.bcast.sync_interval); > + > + bt_shell_printf("Encryption %u\n", bcast_qos.bcast.encryption); > + > + g_dbus_dict_append_entry(&dict, "Encryption", DBUS_TYPE_BYTE, > + &bcast_qos.bcast.encryption); > + > + bt_shell_printf("Options %u\n", bcast_qos.bcast.options); > + > + g_dbus_dict_append_entry(&dict, "Options", DBUS_TYPE_BYTE, > + &bcast_qos.bcast.options); > + > + bt_shell_printf("Skip %u\n", bcast_qos.bcast.skip); > + > + g_dbus_dict_append_entry(&dict, "Skip", DBUS_TYPE_UINT16, > + &bcast_qos.bcast.skip); > + > + bt_shell_printf("SyncTimeout %u\n", bcast_qos.bcast.sync_timeout); > + > + g_dbus_dict_append_entry(&dict, "SyncTimeout", DBUS_TYPE_UINT16, > + &bcast_qos.bcast.sync_timeout); > + > + bt_shell_printf("SyncCteType %u\n", bcast_qos.bcast.sync_cte_type); > + > + g_dbus_dict_append_entry(&dict, "SyncCteType", DBUS_TYPE_BYTE, > + &bcast_qos.bcast.sync_cte_type); > + > + bt_shell_printf("MSE %u\n", bcast_qos.bcast.mse); > + > + g_dbus_dict_append_entry(&dict, "MSE", DBUS_TYPE_BYTE, > + &bcast_qos.bcast.mse); > + > + bt_shell_printf("Timeout %u\n", bcast_qos.bcast.timeout); > + > + g_dbus_dict_append_entry(&dict, "Timeout", DBUS_TYPE_UINT16, > + &bcast_qos.bcast.timeout); > + > + bt_shell_printf("BroadcastCode:\n"); > + bt_shell_hexdump(cfg->ep->bcode->iov_base, cfg->ep->bcode->iov_len); > + > + g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &keyBCode, > + DBUS_TYPE_BYTE, &cfg->ep->bcode->iov_base, > + cfg->ep->bcode->iov_len); > + > done: > dbus_message_iter_close_container(iter, &dict); > } > @@ -1826,8 +1943,15 @@ static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep, > cfg = new0(struct endpoint_config, 1); > cfg->ep = ep; > > - /* Copy capabilities */ > - iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len); > + if (ep->broadcast) { > + iov_append(&cfg->ep->bcode, bcast_qos.bcast.bcode, sizeof(bcast_qos.bcast.bcode)); > + /* Copy capabilities for broadcast*/ > + iov_append(&cfg->caps, base_lc3_16_2_1, sizeof(base_lc3_16_2_1)); > + } else { > + /* Copy capabilities */ > + iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len); > + } > + > cfg->target_latency = preset->target_latency; > > /* Copy metadata */ > @@ -2239,14 +2363,14 @@ fail: > > } > > -static void endpoint_cis(const char *input, void *user_data) > +static void endpoint_iso_stream(const char *input, void *user_data) > { > struct endpoint *ep = user_data; > char *endptr = NULL; > int value; > > if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) { > - ep->cis = BT_ISO_QOS_CIS_UNSET; > + ep->iso_stream = BT_ISO_QOS_STREAM_UNSET; > } else { > value = strtol(input, &endptr, 0); > > @@ -2255,20 +2379,20 @@ static void endpoint_cis(const char *input, void *user_data) > return bt_shell_noninteractive_quit(EXIT_FAILURE); > } > > - ep->cis = value; > + ep->iso_stream = value; > } > > endpoint_register(ep); > } > > -static void endpoint_cig(const char *input, void *user_data) > +static void endpoint_iso_group(const char *input, void *user_data) > { > struct endpoint *ep = user_data; > char *endptr = NULL; > int value; > > if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) { > - ep->cig = BT_ISO_QOS_CIG_UNSET; > + ep->iso_group = BT_ISO_QOS_GROUP_UNSET; > } else { > value = strtol(input, &endptr, 0); > > @@ -2277,10 +2401,13 @@ static void endpoint_cig(const char *input, void *user_data) > return bt_shell_noninteractive_quit(EXIT_FAILURE); > } > > - ep->cig = value; > + ep->iso_group = value; > } > > - bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_cis, ep); > + if (!ep->broadcast) > + bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_iso_stream, ep); > + else > + bt_shell_prompt_input(ep->path, "BIS (auto/value):", endpoint_iso_stream, ep); > } > > static void endpoint_max_transports(const char *input, void *user_data) > @@ -2302,13 +2429,22 @@ static void endpoint_max_transports(const char *input, void *user_data) > ep->max_transports = value; > } > > - bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep); > + if (ep->broadcast) > + bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep); > + else > + bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep); > } > > static void endpoint_auto_accept(const char *input, void *user_data) > { > struct endpoint *ep = user_data; > > + if (!strcmp(ep->uuid, BAA_SERVICE_UUID)) { > + ep->broadcast = true; > + } else { > + ep->broadcast = false; > + } > + > if (!strcasecmp(input, "y") || !strcasecmp(input, "yes")) { > ep->auto_accept = true; > bt_shell_prompt_input(ep->path, "Max Transports (auto/value):", > @@ -2321,7 +2457,10 @@ static void endpoint_auto_accept(const char *input, void *user_data) > return bt_shell_noninteractive_quit(EXIT_FAILURE); > } > > - bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep); > + if (ep->broadcast) > + bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep); > + else > + bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep); > } > > static void endpoint_set_metadata(const char *input, void *user_data) > @@ -3050,8 +3189,8 @@ static void register_endpoints(GDBusProxy *proxy) > ep->cid); > ep->max_transports = UINT8_MAX; > ep->auto_accept = true; > - ep->cig = BT_ISO_QOS_CIG_UNSET; > - ep->cis = BT_ISO_QOS_CIS_UNSET; > + ep->iso_group = BT_ISO_QOS_GROUP_UNSET; > + ep->iso_stream = BT_ISO_QOS_STREAM_UNSET; > endpoint_register(ep); > } > } > @@ -3595,6 +3734,7 @@ static void cmd_acquire_transport(int argc, char *argv[]) > { > GDBusProxy *proxy; > int i; > + struct endpoint *ep, *link; > > for (i = 1; i < argc; i++) { > proxy = g_dbus_proxy_lookup(transports, NULL, argv[i], > @@ -3610,6 +3750,27 @@ static void cmd_acquire_transport(int argc, char *argv[]) > return bt_shell_noninteractive_quit(EXIT_FAILURE); > } > > + ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy)); > + if (!ep || ep->acquiring) { > + bt_shell_printf("Transport %s already in acquiring process\n", > + argv[i]); > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > + } > + > + ep->acquiring = true; > + > + link = find_link_by_proxy(proxy); > + if (link) { > + bt_shell_printf("Link %s found\n", link->transport); > + /* If link already acquiring wait it to be complete */ > + if (link->acquiring) { > + bt_shell_printf("Link %s already in acquiring process\n", > + argv[i]); > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > + } > + link->acquiring = true; > + } > + > if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL, > acquire_reply, proxy, NULL)) { > bt_shell_printf("Failed acquire transport\n"); > -- > 2.34.1 >
diff --git a/client/player.c b/client/player.c index a9f56fb94..408118fca 100644 --- a/client/player.c +++ b/client/player.c @@ -74,11 +74,13 @@ struct endpoint { bool auto_accept; bool acquiring; uint8_t max_transports; - uint8_t cig; - uint8_t cis; + uint8_t iso_group; + uint8_t iso_stream; char *transport; DBusMessage *msg; struct preset *preset; + bool broadcast; + struct iovec *bcode; }; static DBusConnection *dbus_conn; @@ -104,6 +106,22 @@ struct transport { struct io *timer_io; }; +static const uint8_t base_lc3_16_2_1[] = { + 0x28, 0x00, 0x00, /* Presentation Delay */ + 0x01, /* Number of Subgroups */ + 0x01, /* Number of BIS */ + 0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */ + 0x11, /* Codec Specific Configuration */ + 0x02, 0x01, 0x03, /* 16 KHZ */ + 0x02, 0x02, 0x01, /* 10 ms */ + 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, /* Front Left */ + 0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */ + 0x04, /* Metadata */ + 0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */ + 0x01, /* BIS */ + 0x00, /* Codec Specific Configuration */ +}; + static void endpoint_unregister(void *data) { struct endpoint *ep = data; @@ -1154,6 +1172,16 @@ static const struct capabilities { CODEC_CAPABILITIES(PAC_SOURCE_UUID, LC3_ID, LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, 3u, 30, 240)), + /* Broadcast LC3 Source: + * + * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz + * Duration: 7.5 ms 10 ms + * Channel count: 3 + * Frame length: 30-240 + */ + CODEC_CAPABILITIES(BAA_SERVICE_UUID, LC3_ID, + LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, + 3u, 30, 240)), }; struct codec_qos { @@ -1435,6 +1463,7 @@ static struct preset { PRESET(A2DP_SINK_UUID, A2DP_CODEC_SBC, sbc_presets, 6), PRESET(PAC_SINK_UUID, LC3_ID, lc3_presets, 3), PRESET(PAC_SOURCE_UUID, LC3_ID, lc3_presets, 3), + PRESET(BAA_SERVICE_UUID, LC3_ID, lc3_presets, 3), }; static void parse_vendor_codec(const char *codec, uint16_t *vid, uint16_t *cid) @@ -1707,6 +1736,27 @@ struct endpoint_config { const struct codec_qos *qos; }; +#define BCODE {0x01, 0x02, 0x68, 0x05, 0x53, 0xf1, 0x41, 0x5a, \ + 0xa2, 0x65, 0xbb, 0xaf, 0xc6, 0xea, 0x03, 0xb8} + +static struct bt_iso_qos bcast_qos = { + .bcast = { + .big = BT_ISO_QOS_BIG_UNSET, + .bis = BT_ISO_QOS_BIS_UNSET, + .sync_interval = 0x07, + .packing = 0x00, + .framing = 0x00, + .encryption = 0x00, + .bcode = BCODE, + .options = 0x00, + .skip = 0x0000, + .sync_timeout = 0x4000, + .sync_cte_type = 0x00, + .mse = 0x00, + .timeout = 0x4000, + } + }; + static void append_properties(DBusMessageIter *iter, struct endpoint_config *cfg) { @@ -1714,6 +1764,7 @@ static void append_properties(DBusMessageIter *iter, struct codec_qos *qos = (void *)cfg->qos; const char *key = "Capabilities"; const char *meta = "Metadata"; + const char *keyBCode = "BroadcastCode"; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict); @@ -1742,16 +1793,25 @@ static void append_properties(DBusMessageIter *iter, DBUS_TYPE_BYTE, &cfg->target_latency); } - if (cfg->ep->cig != BT_ISO_QOS_CIG_UNSET) { - bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->cig); + if ((!cfg->ep->broadcast) && (cfg->ep->iso_group != BT_ISO_QOS_GROUP_UNSET)) { + bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->iso_group); g_dbus_dict_append_entry(&dict, "CIG", DBUS_TYPE_BYTE, - &cfg->ep->cig); + &cfg->ep->iso_group); + } else { + bt_shell_printf("BIG 0x%2.2x\n", bcast_qos.bcast.big); + g_dbus_dict_append_entry(&dict, "BIG", DBUS_TYPE_BYTE, + &bcast_qos.bcast.big); } - if (cfg->ep->cis != BT_ISO_QOS_CIS_UNSET) { - bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->cis); + if ((!cfg->ep->broadcast) && (cfg->ep->iso_stream != BT_ISO_QOS_STREAM_UNSET)) { + bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->iso_stream); g_dbus_dict_append_entry(&dict, "CIS", DBUS_TYPE_BYTE, - &cfg->ep->cis); + &cfg->ep->iso_stream); + + } else { + bt_shell_printf("BIS 0x%2.2x\n", bcast_qos.bcast.bis); + g_dbus_dict_append_entry(&dict, "BIS", DBUS_TYPE_BYTE, + &bcast_qos.bcast.bis); } bt_shell_printf("Interval %u\n", qos->interval); @@ -1759,10 +1819,17 @@ static void append_properties(DBusMessageIter *iter, g_dbus_dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT32, &qos->interval); - bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false"); + if (!cfg->ep->broadcast) { + bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false"); - g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, - &qos->framing); + g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, + &qos->framing); + } else { + bt_shell_printf("Framing %s\n", bcast_qos.bcast.framing ? "true" : "false"); + + g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, + &bcast_qos.bcast.framing); + } bt_shell_printf("PHY %s\n", qos->phy); @@ -1787,6 +1854,56 @@ static void append_properties(DBusMessageIter *iter, g_dbus_dict_append_entry(&dict, "Delay", DBUS_TYPE_UINT32, &qos->delay); + if (!cfg->ep->broadcast) + goto done; + + bt_shell_printf("SyncInterval %u\n", bcast_qos.bcast.sync_interval); + + g_dbus_dict_append_entry(&dict, "SyncInterval", DBUS_TYPE_BYTE, + &bcast_qos.bcast.sync_interval); + + bt_shell_printf("Encryption %u\n", bcast_qos.bcast.encryption); + + g_dbus_dict_append_entry(&dict, "Encryption", DBUS_TYPE_BYTE, + &bcast_qos.bcast.encryption); + + bt_shell_printf("Options %u\n", bcast_qos.bcast.options); + + g_dbus_dict_append_entry(&dict, "Options", DBUS_TYPE_BYTE, + &bcast_qos.bcast.options); + + bt_shell_printf("Skip %u\n", bcast_qos.bcast.skip); + + g_dbus_dict_append_entry(&dict, "Skip", DBUS_TYPE_UINT16, + &bcast_qos.bcast.skip); + + bt_shell_printf("SyncTimeout %u\n", bcast_qos.bcast.sync_timeout); + + g_dbus_dict_append_entry(&dict, "SyncTimeout", DBUS_TYPE_UINT16, + &bcast_qos.bcast.sync_timeout); + + bt_shell_printf("SyncCteType %u\n", bcast_qos.bcast.sync_cte_type); + + g_dbus_dict_append_entry(&dict, "SyncCteType", DBUS_TYPE_BYTE, + &bcast_qos.bcast.sync_cte_type); + + bt_shell_printf("MSE %u\n", bcast_qos.bcast.mse); + + g_dbus_dict_append_entry(&dict, "MSE", DBUS_TYPE_BYTE, + &bcast_qos.bcast.mse); + + bt_shell_printf("Timeout %u\n", bcast_qos.bcast.timeout); + + g_dbus_dict_append_entry(&dict, "Timeout", DBUS_TYPE_UINT16, + &bcast_qos.bcast.timeout); + + bt_shell_printf("BroadcastCode:\n"); + bt_shell_hexdump(cfg->ep->bcode->iov_base, cfg->ep->bcode->iov_len); + + g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &keyBCode, + DBUS_TYPE_BYTE, &cfg->ep->bcode->iov_base, + cfg->ep->bcode->iov_len); + done: dbus_message_iter_close_container(iter, &dict); } @@ -1826,8 +1943,15 @@ static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep, cfg = new0(struct endpoint_config, 1); cfg->ep = ep; - /* Copy capabilities */ - iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len); + if (ep->broadcast) { + iov_append(&cfg->ep->bcode, bcast_qos.bcast.bcode, sizeof(bcast_qos.bcast.bcode)); + /* Copy capabilities for broadcast*/ + iov_append(&cfg->caps, base_lc3_16_2_1, sizeof(base_lc3_16_2_1)); + } else { + /* Copy capabilities */ + iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len); + } + cfg->target_latency = preset->target_latency; /* Copy metadata */ @@ -2239,14 +2363,14 @@ fail: } -static void endpoint_cis(const char *input, void *user_data) +static void endpoint_iso_stream(const char *input, void *user_data) { struct endpoint *ep = user_data; char *endptr = NULL; int value; if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) { - ep->cis = BT_ISO_QOS_CIS_UNSET; + ep->iso_stream = BT_ISO_QOS_STREAM_UNSET; } else { value = strtol(input, &endptr, 0); @@ -2255,20 +2379,20 @@ static void endpoint_cis(const char *input, void *user_data) return bt_shell_noninteractive_quit(EXIT_FAILURE); } - ep->cis = value; + ep->iso_stream = value; } endpoint_register(ep); } -static void endpoint_cig(const char *input, void *user_data) +static void endpoint_iso_group(const char *input, void *user_data) { struct endpoint *ep = user_data; char *endptr = NULL; int value; if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) { - ep->cig = BT_ISO_QOS_CIG_UNSET; + ep->iso_group = BT_ISO_QOS_GROUP_UNSET; } else { value = strtol(input, &endptr, 0); @@ -2277,10 +2401,13 @@ static void endpoint_cig(const char *input, void *user_data) return bt_shell_noninteractive_quit(EXIT_FAILURE); } - ep->cig = value; + ep->iso_group = value; } - bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_cis, ep); + if (!ep->broadcast) + bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_iso_stream, ep); + else + bt_shell_prompt_input(ep->path, "BIS (auto/value):", endpoint_iso_stream, ep); } static void endpoint_max_transports(const char *input, void *user_data) @@ -2302,13 +2429,22 @@ static void endpoint_max_transports(const char *input, void *user_data) ep->max_transports = value; } - bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep); + if (ep->broadcast) + bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep); + else + bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep); } static void endpoint_auto_accept(const char *input, void *user_data) { struct endpoint *ep = user_data; + if (!strcmp(ep->uuid, BAA_SERVICE_UUID)) { + ep->broadcast = true; + } else { + ep->broadcast = false; + } + if (!strcasecmp(input, "y") || !strcasecmp(input, "yes")) { ep->auto_accept = true; bt_shell_prompt_input(ep->path, "Max Transports (auto/value):", @@ -2321,7 +2457,10 @@ static void endpoint_auto_accept(const char *input, void *user_data) return bt_shell_noninteractive_quit(EXIT_FAILURE); } - bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep); + if (ep->broadcast) + bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep); + else + bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep); } static void endpoint_set_metadata(const char *input, void *user_data) @@ -3050,8 +3189,8 @@ static void register_endpoints(GDBusProxy *proxy) ep->cid); ep->max_transports = UINT8_MAX; ep->auto_accept = true; - ep->cig = BT_ISO_QOS_CIG_UNSET; - ep->cis = BT_ISO_QOS_CIS_UNSET; + ep->iso_group = BT_ISO_QOS_GROUP_UNSET; + ep->iso_stream = BT_ISO_QOS_STREAM_UNSET; endpoint_register(ep); } } @@ -3595,6 +3734,7 @@ static void cmd_acquire_transport(int argc, char *argv[]) { GDBusProxy *proxy; int i; + struct endpoint *ep, *link; for (i = 1; i < argc; i++) { proxy = g_dbus_proxy_lookup(transports, NULL, argv[i], @@ -3610,6 +3750,27 @@ static void cmd_acquire_transport(int argc, char *argv[]) return bt_shell_noninteractive_quit(EXIT_FAILURE); } + ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy)); + if (!ep || ep->acquiring) { + bt_shell_printf("Transport %s already in acquiring process\n", + argv[i]); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + ep->acquiring = true; + + link = find_link_by_proxy(proxy); + if (link) { + bt_shell_printf("Link %s found\n", link->transport); + /* If link already acquiring wait it to be complete */ + if (link->acquiring) { + bt_shell_printf("Link %s already in acquiring process\n", + argv[i]); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + link->acquiring = true; + } + if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL, acquire_reply, proxy, NULL)) { bt_shell_printf("Failed acquire transport\n");