Skip to content

Commit b7814a1

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 5dd3d89 commit b7814a1

File tree

1 file changed

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

1 file changed

+113
-0
lines changed

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

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,34 @@ 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,
153+
uint8_t len)
154+
{
155+
const char *state_str;
156+
157+
/* Convert button state to string */
158+
state_str = (state == BT_AVRCP_BUTTON_PRESSED) ? "PRESSED" : "RELEASED";
159+
160+
bt_shell_print("AVRCP passthrough command received: opid = 0x%02x (%s), tid=0x%02x, len=%u",
161+
opid, state_str, tid, len);
162+
163+
if (len > 0U && data != NULL) {
164+
bt_shell_print("Payload:");
165+
for (uint8_t i = 0U; i < len; i++) {
166+
bt_shell_print(" [%u]: 0x%02x", i, data[i]);
167+
}
168+
}
169+
170+
tg_tid = tid;
171+
}
172+
151173
static struct bt_avrcp_tg_cb app_avrcp_tg_cb = {
152174
.connected = avrcp_tg_connected,
153175
.disconnected = avrcp_tg_disconnected,
154176
.unit_info_req = avrcp_unit_info_req,
155177
.subunit_info_req = avrcp_subunit_info_req,
178+
.passthrough_cmd_req = avrcp_passthrough_cmd_req,
156179
};
157180

158181
static int register_ct_cb(const struct shell *sh)
@@ -331,6 +354,93 @@ static int cmd_send_subunit_info_rsp(const struct shell *sh, int32_t argc, char
331354
return 0;
332355
}
333356

357+
static int cmd_send_passthrough_rsp(const struct shell *sh, int32_t argc, char *argv[])
358+
{
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+
char *endptr;
365+
unsigned long val;
366+
int err;
367+
368+
if (!avrcp_tg_registered && register_tg_cb(sh) != 0) {
369+
return -ENOEXEC;
370+
}
371+
372+
if (default_tg == NULL) {
373+
shell_error(sh, "AVRCP TG is not connected");
374+
return -ENOEXEC;
375+
}
376+
377+
if (argc < 4) {
378+
shell_print(sh, "Usage: send_passthrough_rsp <response> <op/opvu> <opid> <state>\n"
379+
" op/opvu: passthrough command (normal/passthrough VENDOR UNIQUE)\n"
380+
" opid: operation identifier (e.g., play/pause or hex value)\n"
381+
" state: [pressed|released]");
382+
return -EINVAL;
383+
}
384+
385+
memset(&payload, 0, sizeof(payload));
386+
387+
if (!strcmp(argv[1], "op")) {
388+
is_op_vu = 0;
389+
} else if (!strcmp(argv[1], "opvu")) {
390+
opid = BT_AVRCP_OPID_VENDOR_UNIQUE;
391+
is_op_vu = 1;
392+
} else {
393+
shell_error(sh, "Invalid response: %s", argv[2]);
394+
return -EINVAL;
395+
}
396+
397+
if (!strcmp(argv[2], "play")) {
398+
opid = BT_AVRCP_OPID_PLAY;
399+
vu_opid = (uint16_t)opid;
400+
} else if (!strcmp(argv[2], "pause")) {
401+
opid = BT_AVRCP_OPID_PAUSE;
402+
vu_opid = (uint16_t)opid;
403+
} else {
404+
/* Try to parse as hex value */
405+
val = strtoul(argv[2], &endptr, 16);
406+
if (*endptr != '\0' || val > 0xFFFFU) {
407+
shell_error(sh, "Invalid opid: %s", argv[2]);
408+
return -EINVAL;
409+
}
410+
if (is_op_vu == 1) {
411+
vu_opid = (uint16_t)val;
412+
} else {
413+
opid = (bt_avrcp_opid_t)val;
414+
}
415+
}
416+
417+
if (!strcmp(argv[3], "pressed")) {
418+
state = BT_AVRCP_BUTTON_PRESSED;
419+
} else if (!strcmp(argv[3], "released")) {
420+
state = BT_AVRCP_BUTTON_RELEASED;
421+
} else {
422+
shell_error(sh, "Invalid state: %s", argv[3]);
423+
return -EINVAL;
424+
}
425+
426+
if (is_op_vu == 1) {
427+
sys_put_be24(BT_AVRCP_COMPANY_ID_BLUETOOTH_SIG, payload.company_id);
428+
payload.op_len = 5U;
429+
payload.opid_vu = vu_opid;
430+
}
431+
432+
err = bt_avrcp_tg_send_passthrough_rsp(default_tg, tg_tid, BT_AVRCP_RSP_ACCEPTED, opid, state,
433+
payload.op_len ? (const uint8_t *)&payload : NULL,
434+
payload.op_len);
435+
if (err) {
436+
shell_error(sh, "Failed to send passthrough response: %d", err);
437+
} else {
438+
shell_print(sh, "Passthrough opid=0x%02x, state=%s", opid, argv[2]);
439+
}
440+
441+
return err;
442+
}
443+
334444
static int cmd_get_subunit_info(const struct shell *sh, int32_t argc, char *argv[])
335445
{
336446
if (!avrcp_ct_registered && register_ct_cb(sh) != 0) {
@@ -415,6 +525,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
415525
SHELL_CMD_ARG(send_unit_rsp, NULL, "send unit info response", cmd_send_unit_info_rsp, 1, 0),
416526
SHELL_CMD_ARG(send_subunit_rsp, NULL, "send subunit info response",
417527
cmd_send_subunit_info_rsp, 1, 0),
528+
SHELL_CMD_ARG(send_passthrough_rsp, NULL,
529+
"send_passthrough_rsp <response> <op/opvu> <opid> <state>",
530+
cmd_send_passthrough_rsp, 4, 0),
418531
SHELL_SUBCMD_SET_END);
419532

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

0 commit comments

Comments
 (0)