Skip to content

Commit e153c26

Browse files
committed
Bluetooth: shell: Add support for AVRCP TG passthrough
Add a callback function in shell and a new command for AVRCP TG passthrough support Signed-off-by: Make Shi <make.shi@nxp.com>
1 parent f5163dd commit e153c26

File tree

1 file changed

+123
-0
lines changed
  • subsys/bluetooth/host/classic/shell

1 file changed

+123
-0
lines changed

subsys/bluetooth/host/classic/shell/avrcp.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,33 @@ static void avrcp_subunit_info_req(struct bt_avrcp_tg *tg, uint8_t tid)
148148
tg_tid = tid;
149149
}
150150

151+
static void avrcp_passthrough_cmd_req(struct bt_avrcp_tg *tg, uint8_t tid, bt_avrcp_opid_t opid,
152+
bt_avrcp_button_state_t state, const uint8_t *data, uint8_t len)
153+
{
154+
const char *state_str;
155+
156+
/* Convert button state to string */
157+
state_str = (state == BT_AVRCP_BUTTON_PRESSED) ? "PRESSED" : "RELEASED";
158+
159+
bt_shell_print("AVRCP passthrough command received: opid = 0x%02x (%s), tid=0x%02x, len=%u",
160+
opid, state_str, tid, len);
161+
162+
if (len > 0U && data != NULL) {
163+
bt_shell_print("Payload:");
164+
for (uint8_t i = 0U; i < len; i++) {
165+
bt_shell_print(" [%u]: 0x%02x", i, data[i]);
166+
}
167+
}
168+
169+
tg_tid = tid;
170+
}
171+
151172
static struct bt_avrcp_tg_cb app_avrcp_tg_cb = {
152173
.connected = avrcp_tg_connected,
153174
.disconnected = avrcp_tg_disconnected,
154175
.unit_info_req = avrcp_unit_info_req,
155176
.subunit_info_req = avrcp_subunit_info_req,
177+
.passthrough_cmd_req = avrcp_passthrough_cmd_req,
156178
};
157179

158180
static int register_ct_cb(const struct shell *sh)
@@ -331,6 +353,104 @@ static int cmd_send_subunit_info_rsp(const struct shell *sh, int32_t argc, char
331353
return 0;
332354
}
333355

356+
static int cmd_send_passthrough_rsp(const struct shell *sh, int32_t argc, char *argv[])
357+
{
358+
bt_avrcp_rsp_t response;
359+
bt_avrcp_opid_t opid;
360+
bt_avrcp_button_state_t state;
361+
uint16_t vu_opid = 0;
362+
uint8_t is_op_vu =0;
363+
struct bt_avrcp_passthrough_opvu_data payload;
364+
int err;
365+
366+
if (!avrcp_tg_registered && register_tg_cb(sh) != 0) {
367+
return -ENOEXEC;
368+
}
369+
370+
if (default_tg == NULL) {
371+
shell_error(sh, "AVRCP TG is not connected");
372+
return -ENOEXEC;
373+
}
374+
375+
if (argc < 5) {
376+
shell_print(sh, "Usage: send_passthrough_rsp <response> <op/opvu> <opid> <state>\n"
377+
" op/opvu: passthrough command (normal/passthrough VENDOR UNIQUE)\n"
378+
" response: [accepted|rejected|not_impl]\n"
379+
" opid: operation identifier (e.g., play/pause or hex value)\n"
380+
" state: [pressed|released]");
381+
return -EINVAL;
382+
}
383+
384+
if (!strcmp(argv[1], "accepted")) {
385+
response = BT_AVRCP_RSP_ACCEPTED;
386+
} else if (!strcmp(argv[1], "rejected")) {
387+
response = BT_AVRCP_RSP_REJECTED;
388+
} else if (!strcmp(argv[1], "not_impl")) {
389+
response = BT_AVRCP_RSP_NOT_IMPLEMENTED;
390+
} else {
391+
shell_error(sh, "Invalid response: %s", argv[1]);
392+
return -EINVAL;
393+
}
394+
395+
if (!strcmp(argv[2], "op")) {
396+
is_op_vu = 0;
397+
} else if (!strcmp(argv[2], "opvu")) {
398+
opid = BT_AVRCP_OPID_VENDOR_UNIQUE;
399+
is_op_vu = 1;
400+
} else {
401+
shell_error(sh, "Invalid response: %s", argv[2]);
402+
return -EINVAL;
403+
}
404+
405+
if (!strcmp(argv[3], "play")) {
406+
opid = BT_AVRCP_OPID_PLAY;
407+
vu_opid = (uint16_t)opid;
408+
} else if (!strcmp(argv[3], "pause")) {
409+
opid = BT_AVRCP_OPID_PAUSE;
410+
vu_opid = (uint16_t)opid;
411+
} else {
412+
/* Try to parse as hex value */
413+
char *endptr;
414+
unsigned long val = strtoul(argv[3], &endptr, 16);
415+
if (*endptr != '\0' || val > 0xFFFFU) {
416+
shell_error(sh, "Invalid opid: %s", argv[3]);
417+
return -EINVAL;
418+
}
419+
if (is_op_vu == 1) {
420+
vu_opid = (uint16_t)val;
421+
} else {
422+
opid = (bt_avrcp_opid_t)val;
423+
}
424+
}
425+
426+
if (!strcmp(argv[4], "pressed")) {
427+
state = BT_AVRCP_BUTTON_PRESSED;
428+
} else if (!strcmp(argv[4], "released")) {
429+
state = BT_AVRCP_BUTTON_RELEASED;
430+
} else {
431+
shell_error(sh, "Invalid state: %s", argv[4]);
432+
return -EINVAL;
433+
}
434+
435+
if (is_op_vu == 1) {
436+
sys_put_be24(BT_AVRCP_COMPANY_ID_BLUETOOTH_SIG, payload.company_id);
437+
payload.op_len = 5U;
438+
payload.opid_vu = vu_opid;
439+
}
440+
441+
err = bt_avrcp_tg_send_passthrough_rsp(default_tg, tg_tid, response, opid, state,
442+
payload.op_len ? (const uint8_t *)&payload : NULL,
443+
payload.op_len);
444+
if (err) {
445+
shell_error(sh, "Failed to send passthrough response: %d", err);
446+
} else {
447+
shell_print(sh, "Passthrough response sent: %s, opid=0x%02x, state=%s",
448+
argv[1], opid, argv[3]);
449+
}
450+
451+
return err;
452+
}
453+
334454
static int cmd_get_subunit_info(const struct shell *sh, int32_t argc, char *argv[])
335455
{
336456
if (!avrcp_ct_registered && register_ct_cb(sh) != 0) {
@@ -415,6 +535,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
415535
SHELL_CMD_ARG(send_unit_rsp, NULL, "send unit info response", cmd_send_unit_info_rsp, 1, 0),
416536
SHELL_CMD_ARG(send_subunit_rsp, NULL, "send subunit info response",
417537
cmd_send_subunit_info_rsp, 1, 0),
538+
SHELL_CMD_ARG(send_passthrough_rsp, NULL,
539+
"send_passthrough_rsp <response> <op/opvu> <opid> <state>",
540+
cmd_send_passthrough_rsp, 5, 0),
418541
SHELL_SUBCMD_SET_END);
419542

420543
static int cmd_avrcp(const struct shell *sh, size_t argc, char **argv)

0 commit comments

Comments
 (0)