mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-31 14:20:07 +00:00
apps/btshell: implement Broadcast source API
This patch adds commands to btshell to allow creating BIGs, BIG subgroups and BISe and create and manage Broadcast advertisements.
This commit is contained in:
committed by
Krzysztof Kopyściński
parent
7e7b4f00c4
commit
a621805349
@@ -28,6 +28,9 @@
|
||||
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_gap.h"
|
||||
#if (MYNEWT_VAL(BLE_ISO_BROADCASTER))
|
||||
#include "host/ble_audio_broadcast.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -182,6 +185,36 @@ int btshell_l2cap_send(uint16_t conn, uint16_t idx, uint16_t bytes);
|
||||
int btshell_l2cap_reconfig(uint16_t conn_handle, uint16_t mtu,
|
||||
uint8_t num, uint8_t idxs[]);
|
||||
|
||||
#if (MYNEWT_VAL(BLE_ISO_BROADCASTER))
|
||||
int btshell_broadcast_base_add(uint8_t adv_instance, uint32_t presentation_delay);
|
||||
int btshell_broadcast_big_sub_add(uint8_t adv_instance,
|
||||
uint8_t codec_fmt,
|
||||
uint16_t company_id,
|
||||
uint16_t vendor_spec,
|
||||
uint8_t *metadata,
|
||||
unsigned int metadata_len,
|
||||
uint8_t *codec_spec_cfg,
|
||||
unsigned int codec_spec_cfg_len);
|
||||
int btshell_broadcast_bis_add(uint8_t adv_instance,
|
||||
uint8_t *codec_spec_cfg,
|
||||
unsigned int codec_spec_cfg_len);
|
||||
int btshell_broadcast_create(uint8_t adv_instance,
|
||||
struct ble_gap_ext_adv_params *ext_params,
|
||||
struct ble_gap_periodic_adv_params
|
||||
*per_params,
|
||||
const char *name,
|
||||
struct ble_iso_big_params big_params,
|
||||
uint8_t *extra_data,
|
||||
unsigned int extra_data_len);
|
||||
int btshell_broadcast_destroy(uint8_t adv_instance);
|
||||
int btshell_broadcast_update(uint8_t adv_instance,
|
||||
const char *name,
|
||||
uint8_t *extra_data,
|
||||
unsigned int extra_data_len);
|
||||
int btshell_broadcast_start(uint8_t adv_instance);
|
||||
int btshell_broadcast_stop(uint8_t adv_instance);
|
||||
#endif
|
||||
|
||||
int btshell_gap_event(struct ble_gap_event *event, void *arg);
|
||||
void btshell_sync_stats(uint16_t handle);
|
||||
uint8_t btshell_get_default_own_addr_type(void);
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "btshell.h"
|
||||
#include "cmd_gatt.h"
|
||||
#include "cmd_l2cap.h"
|
||||
#include "cmd_leaudio.h"
|
||||
|
||||
#define BTSHELL_MODULE "btshell"
|
||||
|
||||
@@ -4168,6 +4169,140 @@ static const struct shell_cmd_help sync_stats_help = {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_ISO_BROADCASTER)
|
||||
#if MYNEWT_VAL(SHELL_CMD_HELP)
|
||||
static const struct shell_param leaudio_base_add_params[] = {
|
||||
{"adv_instance", "Advertising instance, usage: =<UINT8>"},
|
||||
{ "presentation_delay", "usage: =<UINT32>" },
|
||||
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct shell_cmd_help leaudio_base_add_help = {
|
||||
.summary = "Add BASE configuration for broadcast",
|
||||
.usage = NULL,
|
||||
.params = leaudio_base_add_params,
|
||||
};
|
||||
|
||||
static const struct shell_param leaudio_big_sub_add_params[] = {
|
||||
{"adv_instance", "Advertising instance, usage: =<UINT8>"},
|
||||
{ "codec_fmt", "usage: <UINT8>" },
|
||||
{ "company_id", "usage: =<UINT16>" },
|
||||
{ "vendor_spec", "usage: =<UINT16>" },
|
||||
{ "codec_spec_config", "usage: =[XX:XX...]" },
|
||||
{ "metadata", "usage: =[XX:XX...]" },
|
||||
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct shell_cmd_help leaudio_big_sub_add_help = {
|
||||
.summary = "Add BIG subgroup configuration for broadcast",
|
||||
.usage = NULL,
|
||||
.params = leaudio_big_sub_add_params,
|
||||
};
|
||||
|
||||
static const struct shell_param leaudio_bis_add_params[] = {
|
||||
{"adv_instance", "Advertising instance, usage: =<UINT8>"},
|
||||
{ "codec_spec_config", "usage: =[XX:XX...]" },
|
||||
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct shell_cmd_help leaudio_bis_add_help = {
|
||||
.summary = "Add BIS configuration for broadcast announcements to last "
|
||||
"added BIG subgroup",
|
||||
.usage = NULL,
|
||||
.params = leaudio_bis_add_params,
|
||||
};
|
||||
|
||||
static const struct shell_param leaudio_broadcast_create_params[] = {
|
||||
{"adv_instance", "Advertising instance, usage: =<UINT8>"},
|
||||
{"ext_interval_min", "usage: =[0-UINT16_MAX], default: 0"},
|
||||
{"ext_interval_max", "usage: =[0-UINT16_MAX], default: 0"},
|
||||
{"per_interval_min", "usage: =[0-UINT16_MAX], default: 0"},
|
||||
{"per_interval_max", "usage: =[0-UINT16_MAX], default: 0"},
|
||||
|
||||
{"name", "usage: =[string]"},
|
||||
|
||||
{"sdu_interval", "SDU interval, in us, usage: =<UINT32>"},
|
||||
{"max_sdu", "max SDU size, in octets, usage: =<UINT16>"},
|
||||
{"max_latency", "max transport latency, in ms, usage: =<UINT16>"},
|
||||
{"rtn", "RTN, usage: =<UINT8>"},
|
||||
{"phy", "PHY, usage: =<UINT8>"},
|
||||
{"packing", "packing, optional, true if not given, usage: =<UINT8>"},
|
||||
{"framing", "framing, optional, false if not given, usage: =<UINT8>"},
|
||||
{"encryption", "optional, encryption, usage: =<UINT8>"},
|
||||
{"broadcast_code", "optional, obligatory if encryption is enabled, "
|
||||
"usage: =<XX:XX:...>, len=16 octets"},
|
||||
{"extra_data", "usage: =[XX:XX...]"},
|
||||
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct shell_cmd_help leaudio_broadcast_create_help = {
|
||||
.summary = "Add BIS configuration for broadcast to last added BIG "
|
||||
"subgroup",
|
||||
.usage = NULL,
|
||||
.params = leaudio_broadcast_create_params,
|
||||
};
|
||||
|
||||
static const struct shell_param leaudio_broadcast_destroy_params[] = {
|
||||
{"adv_instance", "Advertising instance, usage: =<UINT8>"},
|
||||
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct shell_cmd_help leaudio_broadcast_destroy_help = {
|
||||
.summary = "Destroy BASE",
|
||||
.usage = NULL,
|
||||
|
||||
.params = leaudio_broadcast_destroy_params,
|
||||
};
|
||||
|
||||
static const struct shell_param leaudio_broadcast_update_params[] = {
|
||||
{"adv_instance", "Advertising instance, usage: =<UINT8>"},
|
||||
{"name", "usage: =[string]"},
|
||||
{"extra_data_len", "usage: =<UINT8>"},
|
||||
{"extra_data", "usage: =[XX:XX...]"},
|
||||
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct shell_cmd_help leaudio_broadcast_update_help = {
|
||||
.summary = "Update broadcast",
|
||||
.usage = NULL,
|
||||
|
||||
.params = leaudio_broadcast_update_params,
|
||||
};
|
||||
|
||||
static const struct shell_param leaudio_broadcast_start_params[] = {
|
||||
{"adv_instance", "Advertising instance, usage: =<UINT8>"},
|
||||
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct shell_cmd_help leaudio_broadcast_start_help = {
|
||||
.summary = "Start broadcast",
|
||||
.usage = NULL,
|
||||
|
||||
.params = leaudio_broadcast_start_params,
|
||||
};
|
||||
|
||||
static const struct shell_param leaudio_broadcast_stop_params[] = {
|
||||
{"adv_instance", "Advertising instance, usage: =<UINT8>"},
|
||||
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct shell_cmd_help leaudio_broadcast_stop_help = {
|
||||
.summary = "Stop broadcast",
|
||||
.usage = NULL,
|
||||
|
||||
.params = leaudio_broadcast_stop_params,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const struct shell_cmd btshell_commands[] = {
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
{
|
||||
@@ -4664,6 +4799,64 @@ static const struct shell_cmd btshell_commands[] = {
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_ISO)
|
||||
{
|
||||
.sc_cmd = "base_add",
|
||||
.sc_cmd_func = cmd_leaudio_base_add,
|
||||
#if MYNEWT_VAL(SHELL_CMD_HELP)
|
||||
.help = &leaudio_base_add_help,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.sc_cmd = "big_sub_add",
|
||||
.sc_cmd_func = cmd_leaudio_big_sub_add,
|
||||
#if MYNEWT_VAL(SHELL_CMD_HELP)
|
||||
.help = &leaudio_big_sub_add_help,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.sc_cmd = "bis_add",
|
||||
.sc_cmd_func = cmd_leaudio_bis_add,
|
||||
#if MYNEWT_VAL(SHELL_CMD_HELP)
|
||||
.help = &leaudio_bis_add_help,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.sc_cmd = "broadcast_create",
|
||||
.sc_cmd_func = cmd_leaudio_broadcast_create,
|
||||
#if MYNEWT_VAL(SHELL_CMD_HELP)
|
||||
.help = &leaudio_broadcast_create_help,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.sc_cmd = "broadcast_destroy",
|
||||
.sc_cmd_func = cmd_leaudio_broadcast_destroy,
|
||||
#if MYNEWT_VAL(SHELL_CMD_HELP)
|
||||
.help = &leaudio_broadcast_destroy_help,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.sc_cmd = "broadcast_update",
|
||||
.sc_cmd_func = cmd_leaudio_broadcast_update,
|
||||
#if MYNEWT_VAL(SHELL_CMD_HELP)
|
||||
.help = &leaudio_broadcast_update_help,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.sc_cmd = "broadcast_start",
|
||||
.sc_cmd_func = cmd_leaudio_broadcast_start,
|
||||
#if MYNEWT_VAL(SHELL_CMD_HELP)
|
||||
.help = &leaudio_broadcast_start_help,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.sc_cmd = "broadcast_stop",
|
||||
.sc_cmd_func = cmd_leaudio_broadcast_stop,
|
||||
#if MYNEWT_VAL(SHELL_CMD_HELP)
|
||||
.help = &leaudio_broadcast_stop_help,
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "host/ble_audio_broadcast.h"
|
||||
#include "cmd_leaudio.h"
|
||||
#include "btshell.h"
|
||||
#include "console/console.h"
|
||||
#include "errno.h"
|
||||
|
||||
#if (MYNEWT_VAL(BLE_ISO_BROADCASTER))
|
||||
int
|
||||
cmd_leaudio_base_add(int argc, char **argv)
|
||||
{
|
||||
uint32_t presentation_delay;
|
||||
uint8_t adv_instance;
|
||||
int rc;
|
||||
|
||||
rc = parse_arg_init(argc - 1, argv + 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
adv_instance = parse_arg_uint8("adv_instance", &rc);
|
||||
if (rc != 0 || adv_instance >= BLE_ADV_INSTANCES) {
|
||||
console_printf("invalid advertising instance\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
presentation_delay = parse_arg_uint32("presentation_delay", &rc);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return btshell_broadcast_base_add(adv_instance, presentation_delay);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_leaudio_big_sub_add(int argc, char **argv)
|
||||
{
|
||||
uint8_t adv_instance;
|
||||
uint8_t codec_fmt;
|
||||
uint16_t company_id;
|
||||
uint16_t vendor_spec;
|
||||
static uint8_t metadata[CMD_ADV_DATA_METADATA_MAX_SZ];
|
||||
unsigned int metadata_len;
|
||||
static uint8_t codec_spec_cfg[CMD_ADV_DATA_CODEC_SPEC_CFG_MAX_SZ];
|
||||
unsigned int codec_spec_cfg_len;
|
||||
int rc;
|
||||
|
||||
rc = parse_arg_init(argc - 1, argv + 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
adv_instance = parse_arg_uint8("adv_instance", &rc);
|
||||
if (rc != 0 || adv_instance >= BLE_ADV_INSTANCES) {
|
||||
console_printf("invalid advertising instance\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
codec_fmt = parse_arg_uint8("codec_fmt", &rc);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
company_id = parse_arg_uint16("company_id", &rc);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
vendor_spec = parse_arg_uint16("vendor_spec", &rc);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = parse_arg_byte_stream("codec_spec_config",
|
||||
CMD_ADV_DATA_CODEC_SPEC_CFG_MAX_SZ,
|
||||
codec_spec_cfg, &codec_spec_cfg_len);
|
||||
if (rc != 0 && rc != ENOENT) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = parse_arg_byte_stream("metadata", CMD_ADV_DATA_METADATA_MAX_SZ,
|
||||
metadata, &metadata_len);
|
||||
if (rc != 0 && rc != ENOENT) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return btshell_broadcast_big_sub_add(adv_instance,
|
||||
codec_fmt, company_id,
|
||||
vendor_spec,
|
||||
metadata, metadata_len,
|
||||
codec_spec_cfg, codec_spec_cfg_len);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_leaudio_bis_add(int argc, char **argv)
|
||||
{
|
||||
uint8_t adv_instance;
|
||||
static uint8_t codec_spec_cfg[CMD_ADV_DATA_CODEC_SPEC_CFG_MAX_SZ];
|
||||
unsigned int codec_spec_cfg_len;
|
||||
int rc;
|
||||
|
||||
rc = parse_arg_init(argc - 1, argv + 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
adv_instance = parse_arg_uint8("adv_instance", &rc);
|
||||
if (rc != 0 || adv_instance >= BLE_ADV_INSTANCES) {
|
||||
console_printf("invalid advertising instance\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = parse_arg_byte_stream("codec_spec_config",
|
||||
CMD_ADV_DATA_CODEC_SPEC_CFG_MAX_SZ,
|
||||
codec_spec_cfg, &codec_spec_cfg_len);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return btshell_broadcast_bis_add(adv_instance, codec_spec_cfg,
|
||||
codec_spec_cfg_len);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_leaudio_broadcast_create(int argc, char **argv)
|
||||
{
|
||||
struct ble_iso_big_params big_params;
|
||||
uint8_t adv_instance;
|
||||
const char *name;
|
||||
uint8_t extra_data[CMD_ADV_DATA_EXTRA_MAX_SZ];
|
||||
static uint8_t own_addr_type;
|
||||
unsigned int extra_data_len;
|
||||
struct ble_gap_periodic_adv_params periodic_params;
|
||||
struct ble_gap_ext_adv_params extended_params = {
|
||||
.scannable = 0,
|
||||
.connectable = 0,
|
||||
.primary_phy = BLE_HCI_LE_PHY_1M,
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = ble_hs_id_infer_auto(0, &own_addr_type);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
extended_params.own_addr_type = own_addr_type;
|
||||
|
||||
rc = parse_arg_init(argc - 1, argv + 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
adv_instance = parse_arg_uint8("adv_instance", &rc);
|
||||
if (rc != 0 || adv_instance >= BLE_ADV_INSTANCES) {
|
||||
console_printf("invalid advertising instance\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
extended_params.sid = adv_instance;
|
||||
extended_params.itvl_min = parse_arg_uint8_dflt("ext_interval_min",
|
||||
0, &rc);
|
||||
if (rc != 0 && rc != ENOENT) {
|
||||
console_printf("invalid extended advertising interval (min)\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
extended_params.itvl_max = parse_arg_uint8_dflt("ext_interval_max", 0,
|
||||
&rc);
|
||||
if (rc != 0 && rc != ENOENT) {
|
||||
console_printf("invalid extended advertising interval (max)\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
periodic_params.itvl_min = parse_arg_uint8_dflt("per_interval_min", 0,
|
||||
&rc);
|
||||
if (rc != 0 && rc != ENOENT) {
|
||||
console_printf("invalid periodic advertising interval (min)\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
periodic_params.itvl_max = parse_arg_uint8_dflt("per_interval_max", 0,
|
||||
&rc);
|
||||
if (rc != 0 && rc != ENOENT) {
|
||||
console_printf("invalid periodic advertising interval (max)\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
name = parse_arg_extract("name");
|
||||
|
||||
big_params.sdu_interval = parse_arg_uint32_bounds("sdu_interval",
|
||||
0x0000FF, 0x0FFFFF,
|
||||
&rc);
|
||||
if (rc != 0) {
|
||||
console_printf("invalid SDU interval\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
big_params.max_sdu = parse_arg_uint16_bounds("max_sdu", 0x0001, 0x0FFF,
|
||||
&rc);
|
||||
if (rc != 0) {
|
||||
console_printf("invalid max SDU size\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
big_params.max_transport_latency = parse_arg_uint16_bounds("max_latency",
|
||||
0x0005, 0x0FA0,
|
||||
&rc);
|
||||
if (rc != 0) {
|
||||
console_printf("invalid max transport latency\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
big_params.rtn = parse_arg_uint8_bounds("rtn", 0x00, 0x1E, &rc);
|
||||
if (rc != 0) {
|
||||
console_printf("invalid RTN\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
big_params.phy = parse_arg_uint8_bounds("phy", 0, 2, &rc);
|
||||
if (rc != 0) {
|
||||
console_printf("invalid PHY\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
extended_params.secondary_phy = big_params.phy;
|
||||
|
||||
big_params.packing = parse_arg_uint8_bounds_dflt("packing", 0, 1, 1, &rc);
|
||||
if (rc != 0) {
|
||||
console_printf("invalid packing\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
big_params.framing = parse_arg_uint8_bounds_dflt("framing", 0, 1, 0, &rc);
|
||||
if (rc != 0) {
|
||||
console_printf("invalid framing\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
big_params.encryption = parse_arg_uint8_bounds_dflt("encryption", 0, 1, 0, &rc);
|
||||
if (rc != 0) {
|
||||
console_printf("invalid encryption\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (big_params.encryption) {
|
||||
big_params.broadcast_code = parse_arg_extract("broadcast_code");
|
||||
if (big_params.broadcast_code == NULL) {
|
||||
console_printf("broadcast code missing\n");
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
if (strlen(big_params.broadcast_code) > 16) {
|
||||
console_printf("broadcast code too long\n");
|
||||
return ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
rc = parse_arg_byte_stream("extra_data",
|
||||
CMD_ADV_DATA_EXTRA_MAX_SZ,
|
||||
extra_data, &extra_data_len);
|
||||
if (rc == ENOENT) {
|
||||
extra_data_len = 0;
|
||||
} else if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return btshell_broadcast_create(adv_instance,
|
||||
&extended_params,
|
||||
&periodic_params,
|
||||
name,
|
||||
big_params,
|
||||
extra_data,
|
||||
extra_data_len);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_leaudio_broadcast_destroy(int argc, char **argv)
|
||||
{
|
||||
uint8_t adv_instance;
|
||||
int rc;
|
||||
|
||||
rc = parse_arg_init(argc - 1, argv + 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
adv_instance = parse_arg_uint8("adv_instance", &rc);
|
||||
if (rc != 0 || adv_instance >= BLE_ADV_INSTANCES) {
|
||||
console_printf("invalid advertising instance\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return btshell_broadcast_destroy(adv_instance);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_leaudio_broadcast_update(int argc, char **argv)
|
||||
{
|
||||
uint8_t adv_instance;
|
||||
uint8_t extra_data[CMD_ADV_DATA_EXTRA_MAX_SZ];
|
||||
unsigned int extra_data_len;
|
||||
const char *name;
|
||||
int rc;
|
||||
|
||||
rc = parse_arg_init(argc - 1, argv + 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
adv_instance = parse_arg_uint8("adv_instance", &rc);
|
||||
if (rc != 0 || adv_instance >= BLE_ADV_INSTANCES) {
|
||||
console_printf("invalid advertising instance\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = parse_arg_byte_stream("extra_data",
|
||||
CMD_ADV_DATA_EXTRA_MAX_SZ,
|
||||
extra_data, &extra_data_len);
|
||||
if (rc != 0 && rc != ENOENT) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
name = parse_arg_extract("name");
|
||||
|
||||
return btshell_broadcast_update(adv_instance, name, extra_data, extra_data_len);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_leaudio_broadcast_start(int argc, char **argv)
|
||||
{
|
||||
uint8_t adv_instance;
|
||||
int rc;
|
||||
|
||||
rc = parse_arg_init(argc - 1, argv + 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
adv_instance = parse_arg_uint8("adv_instance", &rc);
|
||||
if (rc != 0 || adv_instance >= BLE_ADV_INSTANCES) {
|
||||
console_printf("invalid advertising instance\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return btshell_broadcast_start(adv_instance);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_leaudio_broadcast_stop(int argc, char **argv)
|
||||
{
|
||||
uint8_t adv_instance;
|
||||
int rc;
|
||||
|
||||
rc = parse_arg_init(argc - 1, argv + 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
adv_instance = parse_arg_uint8("adv_instance", &rc);
|
||||
if (rc != 0 || adv_instance >= BLE_ADV_INSTANCES) {
|
||||
console_printf("invalid advertising instance\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return btshell_broadcast_stop(adv_instance);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_CMD_LEAUDIO_
|
||||
#define H_CMD_LEAUDIO_
|
||||
|
||||
#include "cmd.h"
|
||||
|
||||
#define CMD_ADV_DATA_CODEC_SPEC_CFG_MAX_SZ (9)
|
||||
/**
|
||||
* Maximum Metadata size is maximum adv size minus minimum size of other
|
||||
* fields in BASE advertising
|
||||
*/
|
||||
#define CMD_ADV_DATA_METADATA_MAX_SZ (MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) - 27)
|
||||
/**
|
||||
* Maximum size of extra data included in BASE advertising. Assumes minimum
|
||||
* size of other fields.
|
||||
*/
|
||||
#define CMD_ADV_DATA_EXTRA_MAX_SZ (MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) - 27)
|
||||
|
||||
int cmd_leaudio_base_add(int argc, char **argv);
|
||||
int cmd_leaudio_big_sub_add(int argc, char **argv);
|
||||
int cmd_leaudio_bis_add(int argc, char **argv);
|
||||
int cmd_leaudio_broadcast_create(int argc, char **argv);
|
||||
int cmd_leaudio_broadcast_destroy(int argc, char **argv);
|
||||
int cmd_leaudio_broadcast_update(int argc, char **argv);
|
||||
int cmd_leaudio_broadcast_start(int argc, char **argv);
|
||||
int cmd_leaudio_broadcast_stop(int argc, char **argv);
|
||||
|
||||
#endif /* H_CMD_LEAUDIO_ */
|
||||
@@ -41,6 +41,8 @@
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_store.h"
|
||||
#include "host/ble_sm.h"
|
||||
#include "host/ble_audio_common.h"
|
||||
#include "host/ble_audio_broadcast.h"
|
||||
#include "host/util/util.h"
|
||||
|
||||
/* Mandatory services. */
|
||||
@@ -123,6 +125,57 @@ int btshell_full_disc_prev_chr_val;
|
||||
struct ble_sm_sc_oob_data oob_data_local;
|
||||
struct ble_sm_sc_oob_data oob_data_remote;
|
||||
|
||||
#if MYNEWT_VAL(BLE_ISO_BROADCASTER)
|
||||
static struct {struct ble_audio_base *base; uint8_t adv_instance;}
|
||||
btshell_base_list[MYNEWT_VAL(BLE_MAX_BIG)];
|
||||
|
||||
static os_membuf_t btshell_base_mem[
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_MAX_BIG),
|
||||
sizeof(struct ble_audio_base))
|
||||
];
|
||||
static struct os_mempool btshell_base_pool;
|
||||
|
||||
static os_membuf_t btshell_big_params_mem[
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_MAX_BIG),
|
||||
sizeof(struct ble_iso_big_params))
|
||||
];
|
||||
static struct os_mempool btshell_big_params_pool;
|
||||
|
||||
/** Mempool size: in worst case every BIS is in separate subgroup */
|
||||
static os_membuf_t btshell_big_sub_mem[
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_MAX_BIS),
|
||||
sizeof(struct ble_audio_big_subgroup))
|
||||
];
|
||||
static struct os_mempool btshell_big_sub_pool;
|
||||
|
||||
static os_membuf_t btshell_bis_mem[
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_MAX_BIS),
|
||||
sizeof(struct ble_audio_bis))
|
||||
];
|
||||
static struct os_mempool btshell_bis_pool;
|
||||
|
||||
static os_membuf_t btshell_metadata_mem[
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_MAX_BIS),
|
||||
MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) - 27)
|
||||
];
|
||||
static struct os_mempool btshell_metadata_pool;
|
||||
|
||||
/**
|
||||
* Mempool size: theoretically it is possible that every BIG Subgroup has
|
||||
* codec specific configuration, every BIS is in separate subgroup and also
|
||||
* has one. This is inefficient but possible and should not cause error if
|
||||
* used that way */
|
||||
static os_membuf_t btshell_codec_spec_mem[
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_MAX_BIS) * 2, 9)
|
||||
];
|
||||
static struct os_mempool btshell_codec_spec_pool;
|
||||
|
||||
static os_membuf_t btshell_big_params_mem[
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_MAX_BIG), sizeof(struct ble_iso_big_params))
|
||||
];
|
||||
static struct os_mempool btshell_big_params_pool;
|
||||
#endif
|
||||
|
||||
#define XSTR(s) STR(s)
|
||||
#ifndef STR
|
||||
#define STR(s) #s
|
||||
@@ -2618,6 +2671,276 @@ btshell_get_default_own_addr_type(void)
|
||||
return default_own_addr_type;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_ISO_BROADCASTER))
|
||||
static int
|
||||
btshell_base_find_free(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MYNEWT_VAL(BLE_MAX_BIG); i++) {
|
||||
if (btshell_base_list[i].base == NULL) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static struct ble_audio_base *
|
||||
btshell_base_find(uint8_t adv_instance)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MYNEWT_VAL(BLE_MAX_BIG); i++) {
|
||||
if (btshell_base_list[i].adv_instance == adv_instance) {
|
||||
return btshell_base_list[i].base;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
btshell_broadcast_destroy_fn(struct ble_audio_base *base, void *args)
|
||||
{
|
||||
struct ble_iso_big_params *big_params =
|
||||
(struct ble_iso_big_params *)args;
|
||||
struct ble_audio_big_subgroup *big_sub;
|
||||
struct ble_audio_bis *bis;
|
||||
|
||||
STAILQ_FOREACH(big_sub, &base->subs, next) {
|
||||
STAILQ_FOREACH(bis, &big_sub->bises, next) {
|
||||
os_memblock_put(&btshell_bis_pool, bis);
|
||||
os_memblock_put(&btshell_codec_spec_pool, bis->codec_spec_config);
|
||||
STAILQ_REMOVE(&big_sub->bises, bis, ble_audio_bis, next);
|
||||
}
|
||||
os_memblock_put(&btshell_big_sub_pool, big_sub);
|
||||
os_memblock_put(&btshell_codec_spec_pool, big_sub->codec_spec_config);
|
||||
os_memblock_put(&btshell_metadata_pool, big_sub->metadata);
|
||||
STAILQ_REMOVE(&base->subs, big_sub, ble_audio_big_subgroup, next);
|
||||
}
|
||||
|
||||
os_memblock_put(&btshell_big_params_pool, big_params);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
btshell_broadcast_base_add(uint8_t adv_instance, uint32_t presentation_delay)
|
||||
{
|
||||
struct ble_audio_base *base;
|
||||
int free_base_idx;
|
||||
|
||||
base = os_memblock_get(&btshell_base_pool);
|
||||
if (!base) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
free_base_idx = btshell_base_find_free();
|
||||
if (free_base_idx < 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
base->presentation_delay = presentation_delay;
|
||||
|
||||
btshell_base_list[free_base_idx].base = base;
|
||||
btshell_base_list[free_base_idx].adv_instance = adv_instance;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
btshell_broadcast_big_sub_add(uint8_t adv_instance,
|
||||
uint8_t codec_fmt, uint16_t company_id,
|
||||
uint16_t vendor_spec,
|
||||
uint8_t *metadata,
|
||||
unsigned int metadata_len,
|
||||
uint8_t *codec_spec_cfg,
|
||||
unsigned int codec_spec_cfg_len)
|
||||
{
|
||||
struct ble_audio_big_subgroup *big_sub;
|
||||
struct ble_audio_base *base;
|
||||
uint8_t *new_metadata = NULL;
|
||||
uint8_t *new_codec_spec_cfg = NULL;
|
||||
|
||||
big_sub = os_memblock_get(&btshell_big_sub_pool);
|
||||
if (!big_sub) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
base = btshell_base_find(adv_instance);
|
||||
if (!base) {
|
||||
os_memblock_put(&btshell_big_sub_pool, big_sub);
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
if (metadata_len > 0) {
|
||||
new_metadata = os_memblock_get(&btshell_metadata_pool);
|
||||
if (!new_metadata) {
|
||||
os_memblock_put(&btshell_big_sub_pool, big_sub);
|
||||
return ENOMEM;
|
||||
}
|
||||
memcpy(new_metadata, metadata, metadata_len);
|
||||
}
|
||||
|
||||
if (codec_spec_cfg_len > 0) {
|
||||
new_codec_spec_cfg = os_memblock_get(&btshell_codec_spec_pool);
|
||||
if (!new_codec_spec_cfg) {
|
||||
os_memblock_put(&btshell_big_sub_pool, big_sub);
|
||||
os_memblock_put(&btshell_metadata_pool, new_metadata);
|
||||
return ENOMEM;
|
||||
}
|
||||
memcpy(new_codec_spec_cfg, codec_spec_cfg, codec_spec_cfg_len);
|
||||
}
|
||||
|
||||
big_sub->codec_id.format = codec_fmt;
|
||||
big_sub->codec_id.company_id = company_id;
|
||||
big_sub->codec_id.vendor_specific = vendor_spec;
|
||||
big_sub->codec_id.vendor_specific = vendor_spec;
|
||||
big_sub->codec_spec_config = codec_spec_cfg_len > 0 ?
|
||||
new_codec_spec_cfg : NULL;
|
||||
big_sub->codec_spec_config_len = codec_spec_cfg_len;
|
||||
big_sub->metadata = metadata_len > 0 ? new_metadata : NULL;
|
||||
big_sub->metadata_len = metadata_len;
|
||||
|
||||
if (STAILQ_EMPTY(&base->subs)) {
|
||||
STAILQ_INSERT_HEAD(&base->subs, big_sub, next);
|
||||
} else {
|
||||
STAILQ_INSERT_TAIL(&base->subs, big_sub, next);
|
||||
}
|
||||
|
||||
base->num_subgroups++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
btshell_broadcast_bis_add(uint8_t adv_instance,
|
||||
uint8_t *codec_spec_cfg,
|
||||
unsigned int codec_spec_cfg_len)
|
||||
{
|
||||
struct ble_audio_bis *bis;
|
||||
struct ble_audio_base *base;
|
||||
struct ble_audio_big_subgroup *big_sub;
|
||||
uint8_t *new_codec_spec_cfg;
|
||||
|
||||
base = btshell_base_find(adv_instance);
|
||||
if (!base) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
big_sub = STAILQ_LAST(&base->subs, ble_audio_big_subgroup, next);
|
||||
if (!big_sub) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
bis = os_memblock_get(&btshell_bis_pool);
|
||||
if (!bis) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (codec_spec_cfg_len > 0) {
|
||||
new_codec_spec_cfg = os_memblock_get(&btshell_codec_spec_pool);
|
||||
if (!new_codec_spec_cfg) {
|
||||
os_memblock_put(&btshell_bis_pool, bis);
|
||||
return ENOMEM;
|
||||
}
|
||||
memcpy(new_codec_spec_cfg, codec_spec_cfg, codec_spec_cfg_len);
|
||||
}
|
||||
|
||||
bis->codec_spec_config = codec_spec_cfg_len > 0 ?
|
||||
new_codec_spec_cfg : NULL;
|
||||
bis->codec_spec_config_len = codec_spec_cfg_len;
|
||||
|
||||
if (STAILQ_EMPTY(&big_sub->bises)) {
|
||||
STAILQ_INSERT_HEAD(&big_sub->bises, bis, next);
|
||||
} else {
|
||||
STAILQ_INSERT_TAIL(&big_sub->bises, bis, next);
|
||||
}
|
||||
|
||||
big_sub->bis_cnt++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
btshell_broadcast_create(uint8_t adv_instance,
|
||||
struct ble_gap_ext_adv_params *ext_params,
|
||||
struct ble_gap_periodic_adv_params *per_params,
|
||||
const char *name,
|
||||
struct ble_iso_big_params big_params,
|
||||
uint8_t *extra_data,
|
||||
unsigned int extra_data_len)
|
||||
{
|
||||
struct ble_audio_base *base;
|
||||
struct ble_broadcast_create_params create_params;
|
||||
struct ble_iso_big_params *big_params_ptr;
|
||||
int rc;
|
||||
|
||||
base = btshell_base_find(adv_instance);
|
||||
if (!base) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
big_params_ptr = os_memblock_get(&btshell_big_params_pool);
|
||||
if (!big_params_ptr) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
*big_params_ptr = big_params;
|
||||
|
||||
create_params.base = base;
|
||||
create_params.extended_params = ext_params;
|
||||
create_params.periodic_params = per_params;
|
||||
create_params.name = name;
|
||||
create_params.adv_instance = adv_instance;
|
||||
create_params.big_params = big_params_ptr;
|
||||
create_params.svc_data = extra_data;
|
||||
create_params.svc_data_len = extra_data_len;
|
||||
|
||||
rc = ble_audio_broadcast_create(&create_params,
|
||||
btshell_broadcast_destroy_fn,
|
||||
(void *)big_params_ptr,
|
||||
btshell_gap_event);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
btshell_broadcast_destroy(uint8_t adv_instance)
|
||||
{
|
||||
return ble_audio_broadcast_destroy(adv_instance);
|
||||
}
|
||||
|
||||
int
|
||||
btshell_broadcast_update(uint8_t adv_instance,
|
||||
const char *name,
|
||||
uint8_t *extra_data,
|
||||
unsigned int extra_data_len)
|
||||
{
|
||||
struct ble_audio_base *base;
|
||||
struct ble_broadcast_update_params params;
|
||||
|
||||
base = btshell_base_find(adv_instance);
|
||||
|
||||
params.name = name;
|
||||
params.adv_instance = adv_instance;
|
||||
params.svc_data = extra_data;
|
||||
params.svc_data_len = extra_data_len;
|
||||
params.broadcast_id = base->broadcast_id;
|
||||
|
||||
return ble_audio_broadcast_update(¶ms);
|
||||
}
|
||||
|
||||
int
|
||||
btshell_broadcast_start(uint8_t adv_instance)
|
||||
{
|
||||
return ble_audio_broadcast_start(adv_instance, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
btshell_broadcast_stop(uint8_t adv_instance)
|
||||
{
|
||||
return ble_audio_broadcast_stop(adv_instance);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* main
|
||||
*
|
||||
@@ -2667,7 +2990,43 @@ mynewt_main(int argc, char **argv)
|
||||
"btshell_coc_conn_pool");
|
||||
assert(rc == 0);
|
||||
#endif
|
||||
#if (MYNEWT_VAL(BLE_ISO_BROADCASTER))
|
||||
rc = os_mempool_init(&btshell_base_pool, MYNEWT_VAL(BLE_MAX_BIG),
|
||||
sizeof(struct ble_audio_base),
|
||||
btshell_base_mem,
|
||||
"btshell_base_pool");
|
||||
assert(rc == 0);
|
||||
rc = os_mempool_init(&btshell_big_params_pool, MYNEWT_VAL(BLE_MAX_BIG),
|
||||
sizeof(struct ble_iso_big_params),
|
||||
btshell_big_params_mem,
|
||||
"btshell_big_params_pool");
|
||||
assert(rc == 0);
|
||||
rc = os_mempool_init(&btshell_big_sub_pool, MYNEWT_VAL(BLE_MAX_BIS),
|
||||
sizeof(struct ble_audio_big_subgroup),
|
||||
btshell_big_sub_mem,
|
||||
"btshell_big_sub_pool");
|
||||
assert(rc == 0);
|
||||
rc = os_mempool_init(&btshell_bis_pool, MYNEWT_VAL(BLE_MAX_BIS),
|
||||
sizeof(struct ble_audio_bis), btshell_bis_mem,
|
||||
"btshell_bis_pool");
|
||||
assert(rc == 0);
|
||||
|
||||
rc = os_mempool_init(&btshell_metadata_pool, MYNEWT_VAL(BLE_MAX_BIS),
|
||||
MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) - 27,
|
||||
btshell_metadata_mem, "btshell_metadata_pool");
|
||||
assert(rc == 0);
|
||||
|
||||
rc = os_mempool_init(&btshell_codec_spec_pool,
|
||||
MYNEWT_VAL(BLE_MAX_BIS) * 2, 19,
|
||||
btshell_codec_spec_mem, "btshell_codec_spec_pool");
|
||||
assert(rc == 0);
|
||||
|
||||
rc = os_mempool_init(&btshell_big_params_pool,
|
||||
MYNEWT_VAL(BLE_MAX_BIG),
|
||||
sizeof(struct ble_iso_big_params),
|
||||
btshell_big_params_mem, "btshell_big_params_pool");
|
||||
assert(rc == 0);
|
||||
#endif
|
||||
/* Initialize the NimBLE host configuration. */
|
||||
ble_hs_cfg.reset_cb = btshell_on_reset;
|
||||
ble_hs_cfg.sync_cb = btshell_on_sync;
|
||||
|
||||
+17
-46
@@ -282,28 +282,24 @@ ble_iso_tx_complete(uint16_t conn_handle, const uint8_t *data,
|
||||
}
|
||||
|
||||
static int
|
||||
ble_iso_tx_segmented(uint16_t conn_handle, uint16_t max_pdu,
|
||||
const uint8_t *data, uint16_t data_len)
|
||||
ble_iso_tx_segmented(uint16_t conn_handle, const uint8_t *data,
|
||||
uint16_t data_len)
|
||||
{
|
||||
struct os_mbuf *om;
|
||||
uint16_t data_left = data_len;
|
||||
uint16_t packet_len;
|
||||
uint16_t offset = 0;
|
||||
uint8_t pb;
|
||||
uint8_t ts;
|
||||
int rc;
|
||||
|
||||
while (data_left) {
|
||||
packet_len = min(max_pdu - (BLE_HCI_DATA_HDR_SZ + 4), data_left);
|
||||
packet_len = min(MYNEWT_VAL(BLE_TRANSPORT_ISO_SIZE), data_left);
|
||||
if (data_left == data_len) {
|
||||
pb = BLE_HCI_ISO_PB_FIRST;
|
||||
ts = 1;
|
||||
} else if (packet_len == data_left) {
|
||||
pb = BLE_HCI_ISO_PB_LAST;
|
||||
ts = 0;
|
||||
} else {
|
||||
pb = BLE_HCI_ISO_PB_CONTINUATION;
|
||||
ts = 0;
|
||||
}
|
||||
|
||||
om = ble_hs_mbuf_bare_pkt();
|
||||
@@ -311,32 +307,26 @@ ble_iso_tx_segmented(uint16_t conn_handle, uint16_t max_pdu,
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
os_mbuf_extend(om, ts == 1 ? 10: 8);
|
||||
os_mbuf_extend(om, pb == BLE_HCI_ISO_PB_FIRST ? 8: 4);
|
||||
|
||||
/* Connection_Handle, PB_Flag, TS_Flag */
|
||||
put_le16(&om->om_data[0],
|
||||
BLE_HCI_ISO_HANDLE(conn_handle, pb, ts));
|
||||
/* Data_Total_Length = Data length +
|
||||
* Packet_Sequence_Number placeholder +
|
||||
* optional timestamp*/
|
||||
put_le16(&om->om_data[2], packet_len + 4 + 2 * ts);
|
||||
BLE_HCI_ISO_HANDLE(conn_handle, pb, 0));
|
||||
|
||||
if (ts) {
|
||||
/* Timestamp placeholder */
|
||||
put_le16(&om->om_data[4], 0);
|
||||
if (pb == BLE_HCI_ISO_PB_FIRST) {
|
||||
/* Data_Total_Length = Data length +
|
||||
* Packet_Sequence_Number placeholder*/
|
||||
put_le16(&om->om_data[2], packet_len + 4);
|
||||
|
||||
/* Packet_Sequence_Number placeholder */
|
||||
put_le16(&om->om_data[6], 0);
|
||||
put_le16(&om->om_data[8], 0);
|
||||
|
||||
/* ISO_SDU_Length */
|
||||
put_le16(&om->om_data[8], packet_len);
|
||||
put_le16(&om->om_data[10], packet_len);
|
||||
} else {
|
||||
put_le16(&om->om_data[2], packet_len);
|
||||
}
|
||||
|
||||
/* Packet_Sequence_Number placeholder */
|
||||
put_le16(&om->om_data[4], 0);
|
||||
/* ISO_SDU_Length */
|
||||
put_le16(&om->om_data[6], packet_len);
|
||||
|
||||
rc = os_mbuf_append(om, data + offset, packet_len);
|
||||
if (rc) {
|
||||
return rc;
|
||||
@@ -345,40 +335,21 @@ ble_iso_tx_segmented(uint16_t conn_handle, uint16_t max_pdu,
|
||||
ble_transport_to_ll_iso(om);
|
||||
|
||||
offset += packet_len;
|
||||
data_len -= packet_len;
|
||||
data_left -= packet_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_iso_tx(uint16_t conn_handle, const uint8_t *data, uint16_t data_len)
|
||||
ble_iso_tx(uint16_t conn_handle, void *data, uint16_t data_len)
|
||||
{
|
||||
struct ble_iso_big *big;
|
||||
uint16_t max_pdu = 0;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
SLIST_FOREACH(big, &ble_iso_bigs, next) {
|
||||
for (i = 0; i < big->num_bis; i++) {
|
||||
if (big->conn_handles[i] == conn_handle) {
|
||||
max_pdu = big->max_pdu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (max_pdu > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!max_pdu) {
|
||||
return BLE_HS_ENOENT;
|
||||
}
|
||||
|
||||
if (data_len <= max_pdu) {
|
||||
if (data_len <= MYNEWT_VAL(BLE_TRANSPORT_ISO_SIZE)) {
|
||||
rc = ble_iso_tx_complete(conn_handle, data, data_len);
|
||||
} else {
|
||||
rc = ble_iso_tx_segmented(conn_handle, max_pdu, data, data_len);
|
||||
rc = ble_iso_tx_segmented(conn_handle, data, data_len);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
Reference in New Issue
Block a user