Bluetooth: Shell: AVRCP: support unit info request and response

Add avrcp_unit_info_req callback function in shell and a command to set
the unit info response.

Signed-off-by: Make Shi <make.shi@nxp.com>
This commit is contained in:
Make Shi 2025-04-21 16:17:39 +08:00 committed by Alberto Escolar
parent c95d3167e2
commit ba05d5c2b2

View File

@ -30,8 +30,11 @@
#include "common/bt_shell_private.h"
struct bt_avrcp_ct *default_ct;
struct bt_avrcp_tg *default_tg;
static bool avrcp_ct_registered;
static bool avrcp_tg_registered;
static uint8_t local_tid;
static uint8_t tg_tid;
static uint8_t get_next_tid(void)
{
@ -54,6 +57,7 @@ static void avrcp_ct_disconnected(struct bt_avrcp_ct *ct)
{
bt_shell_print("AVRCP CT disconnected");
local_tid = 0;
default_ct = NULL;
}
static void avrcp_get_cap_rsp(struct bt_avrcp_ct *ct, uint8_t tid,
@ -111,7 +115,7 @@ static void avrcp_passthrough_rsp(struct bt_avrcp_ct *ct, uint8_t tid, bt_avrcp_
}
}
static struct bt_avrcp_ct_cb avrcp_ct_cb = {
static struct bt_avrcp_ct_cb app_avrcp_ct_cb = {
.connected = avrcp_ct_connected,
.disconnected = avrcp_ct_disconnected,
.get_cap_rsp = avrcp_get_cap_rsp,
@ -120,6 +124,30 @@ static struct bt_avrcp_ct_cb avrcp_ct_cb = {
.passthrough_rsp = avrcp_passthrough_rsp,
};
static void avrcp_tg_connected(struct bt_conn *conn, struct bt_avrcp_tg *tg)
{
bt_shell_print("AVRCP TG connected");
default_tg = tg;
}
static void avrcp_tg_disconnected(struct bt_avrcp_tg *tg)
{
bt_shell_print("AVRCP TG disconnected");
default_tg = NULL;
}
static void avrcp_unit_info_req(struct bt_avrcp_tg *tg, uint8_t tid)
{
bt_shell_print("AVRCP unit info request received");
tg_tid = tid;
}
static struct bt_avrcp_tg_cb app_avrcp_tg_cb = {
.connected = avrcp_tg_connected,
.disconnected = avrcp_tg_disconnected,
.unit_info_req = avrcp_unit_info_req,
};
static int register_ct_cb(const struct shell *sh)
{
int err;
@ -128,12 +156,12 @@ static int register_ct_cb(const struct shell *sh)
return 0;
}
err = bt_avrcp_ct_register_cb(&avrcp_ct_cb);
err = bt_avrcp_ct_register_cb(&app_avrcp_ct_cb);
if (!err) {
avrcp_ct_registered = true;
shell_print(sh, "AVRCP callbacks registered");
shell_print(sh, "AVRCP CT callbacks registered");
} else {
shell_print(sh, "failed to register callbacks");
shell_print(sh, "failed to register AVRCP CT callbacks");
}
return err;
@ -151,14 +179,47 @@ static int cmd_register_ct_cb(const struct shell *sh, int32_t argc, char *argv[]
return 0;
}
static int register_tg_cb(const struct shell *sh)
{
int err;
if (avrcp_tg_registered) {
return 0;
}
err = bt_avrcp_tg_register_cb(&app_avrcp_tg_cb);
if (!err) {
avrcp_tg_registered = true;
shell_print(sh, "AVRCP TG callbacks registered");
} else {
shell_print(sh, "failed to register AVRCP TG callbacks");
}
return err;
}
static int cmd_register_tg_cb(const struct shell *sh, int32_t argc, char *argv[])
{
if (avrcp_tg_registered) {
shell_print(sh, "already registered");
return 0;
}
register_tg_cb(sh);
return 0;
}
static int cmd_connect(const struct shell *sh, int32_t argc, char *argv[])
{
int err;
if (!avrcp_ct_registered) {
if (register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (!avrcp_ct_registered && register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (!avrcp_tg_registered && register_tg_cb(sh) != 0) {
return -ENOEXEC;
}
if (!default_conn) {
@ -167,7 +228,7 @@ static int cmd_connect(const struct shell *sh, int32_t argc, char *argv[])
}
err = bt_avrcp_connect(default_conn);
if (!err) {
if (err) {
shell_error(sh, "fail to connect AVRCP");
}
@ -176,15 +237,18 @@ static int cmd_connect(const struct shell *sh, int32_t argc, char *argv[])
static int cmd_disconnect(const struct shell *sh, int32_t argc, char *argv[])
{
if (!avrcp_ct_registered) {
if (register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if ((!avrcp_ct_registered) && (!avrcp_tg_registered)) {
shell_error(sh, "Neither CT nor TG callbacks are registered.");
return -ENOEXEC;
}
if (default_ct != NULL) {
if (!default_conn) {
shell_print(sh, "Not connected");
return -ENOEXEC;
}
if ((default_ct != NULL) || (default_tg != NULL)) {
bt_avrcp_disconnect(default_conn);
default_ct = NULL;
} else {
shell_error(sh, "AVRCP is not connected");
}
@ -194,10 +258,8 @@ static int cmd_disconnect(const struct shell *sh, int32_t argc, char *argv[])
static int cmd_get_unit_info(const struct shell *sh, int32_t argc, char *argv[])
{
if (!avrcp_ct_registered) {
if (register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (!avrcp_ct_registered && register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (default_ct != NULL) {
@ -209,12 +271,36 @@ static int cmd_get_unit_info(const struct shell *sh, int32_t argc, char *argv[])
return 0;
}
static int cmd_send_unit_info_rsp(const struct shell *sh, int32_t argc, char *argv[])
{
struct bt_avrcp_unit_info_rsp rsp;
int err;
if (!avrcp_tg_registered && register_tg_cb(sh) != 0) {
return -ENOEXEC;
}
rsp.unit_type = BT_AVRCP_SUBUNIT_TYPE_PANEL;
rsp.company_id = BT_AVRCP_COMPANY_ID_BLUETOOTH_SIG;
if (default_tg != NULL) {
err = bt_avrcp_tg_send_unit_info_rsp(default_tg, tg_tid, &rsp);
if (!err) {
shell_print(sh, "AVRCP send unit info response");
} else {
shell_error(sh, "Failed to send unit info response");
}
} else {
shell_error(sh, "AVRCP is not connected");
}
return 0;
}
static int cmd_get_subunit_info(const struct shell *sh, int32_t argc, char *argv[])
{
if (!avrcp_ct_registered) {
if (register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (!avrcp_ct_registered && register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (default_ct != NULL) {
@ -229,17 +315,15 @@ static int cmd_get_subunit_info(const struct shell *sh, int32_t argc, char *argv
static int cmd_passthrough(const struct shell *sh, bt_avrcp_opid_t opid, const uint8_t *payload,
uint8_t len)
{
if (!avrcp_ct_registered) {
if (register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (!avrcp_ct_registered && register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (default_ct != NULL) {
bt_avrcp_ct_passthrough(default_ct, get_next_tid(), opid, BT_AVRCP_BUTTON_PRESSED,
payload, len);
payload, len);
bt_avrcp_ct_passthrough(default_ct, get_next_tid(), opid, BT_AVRCP_BUTTON_RELEASED,
payload, len);
payload, len);
} else {
shell_error(sh, "AVRCP is not connected");
}
@ -261,10 +345,8 @@ static int cmd_get_cap(const struct shell *sh, int32_t argc, char *argv[])
{
const char *cap_id;
if (!avrcp_ct_registered) {
if (register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (!avrcp_ct_registered && register_ct_cb(sh) != 0) {
return -ENOEXEC;
}
if (default_ct == NULL) {
@ -284,7 +366,7 @@ static int cmd_get_cap(const struct shell *sh, int32_t argc, char *argv[])
SHELL_STATIC_SUBCMD_SET_CREATE(
ct_cmds,
SHELL_CMD_ARG(register_ct_cb, NULL, "register avrcp callbacks", cmd_register_ct_cb, 1, 0),
SHELL_CMD_ARG(register_cb, NULL, "register avrcp ct callbacks", cmd_register_ct_cb, 1, 0),
SHELL_CMD_ARG(get_unit, NULL, "get unit info", cmd_get_unit_info, 1, 0),
SHELL_CMD_ARG(get_subunit, NULL, "get subunit info", cmd_get_subunit_info, 1, 0),
SHELL_CMD_ARG(get_cap, NULL, "get capabilities <cap_id: company or events>", cmd_get_cap, 2,
@ -293,6 +375,12 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
SHELL_CMD_ARG(pause, NULL, "request a pause at the remote player", cmd_pause, 1, 0),
SHELL_SUBCMD_SET_END);
SHELL_STATIC_SUBCMD_SET_CREATE(
tg_cmds,
SHELL_CMD_ARG(register_cb, NULL, "register avrcp tg callbacks", cmd_register_tg_cb, 1, 0),
SHELL_CMD_ARG(send_unit_rsp, NULL, "send unit info response", cmd_send_unit_info_rsp, 1, 0),
SHELL_SUBCMD_SET_END);
static int cmd_avrcp(const struct shell *sh, size_t argc, char **argv)
{
if (argc == 1) {
@ -310,7 +398,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
avrcp_cmds,
SHELL_CMD_ARG(connect, NULL, "connect AVRCP", cmd_connect, 1, 0),
SHELL_CMD_ARG(disconnect, NULL, "disconnect AVRCP", cmd_disconnect, 1, 0),
SHELL_CMD(ct, &ct_cmds, "AVRCP CT shell commands", cmd_avrcp),
SHELL_CMD(ct, &ct_cmds, "AVRCP CT shell commands", cmd_avrcp),
SHELL_CMD(tg, &tg_cmds, "AVRCP TG shell commands", cmd_avrcp),
SHELL_SUBCMD_SET_END);
SHELL_CMD_ARG_REGISTER(avrcp, &avrcp_cmds, "Bluetooth AVRCP sh commands", cmd_avrcp, 1, 1);