From 7dfbae4ee545086bb0bb1f5e81d73738ab5f5054 Mon Sep 17 00:00:00 2001 From: Zihao Gao Date: Fri, 12 Jul 2024 22:16:55 +0800 Subject: [PATCH] Bluetooth : AVRCP: allow to receive an AVRCP message. This patch received an AVRCP message and remove timeout timers. Signed-off-by: Zihao Gao --- subsys/bluetooth/host/classic/avctp.c | 4 +- subsys/bluetooth/host/classic/avrcp.c | 41 ++++++++++++++++++++- subsys/bluetooth/host/classic/shell/avrcp.c | 41 +++++++++++---------- 3 files changed, 64 insertions(+), 22 deletions(-) diff --git a/subsys/bluetooth/host/classic/avctp.c b/subsys/bluetooth/host/classic/avctp.c index e5c9be3b7eb00a..cbe004efb4d92f 100644 --- a/subsys/bluetooth/host/classic/avctp.c +++ b/subsys/bluetooth/host/classic/avctp.c @@ -87,8 +87,8 @@ static int avctp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) default: LOG_ERR("unsupported AVCTP PID received: 0x%04x", sys_be16_to_cpu(hdr->pid)); if (hdr->cr == BT_AVCTP_CMD) { - rsp = bt_avctp_create_pdu(session, BT_AVCTP_RESPONSE, - BT_AVCTP_IPID_INVALID, &hdr->tid, hdr->pid); + rsp = bt_avctp_create_pdu(session, BT_AVCTP_RESPONSE, BT_AVCTP_IPID_INVALID, + &hdr->tid, hdr->pid); if (!rsp) { return -ENOMEM; } diff --git a/subsys/bluetooth/host/classic/avrcp.c b/subsys/bluetooth/host/classic/avrcp.c index 52ccfe4be55409..59563133242648 100644 --- a/subsys/bluetooth/host/classic/avrcp.c +++ b/subsys/bluetooth/host/classic/avrcp.c @@ -249,9 +249,49 @@ static void avrcp_disconnected(struct bt_avctp *session) } } +/* An AVRCP message received */ +static int avrcp_recv(struct bt_avctp *session, struct net_buf *buf) +{ + struct bt_avrcp *avrcp = AVRCP_AVCTP(session); + struct bt_avctp_header *avctp_hdr; + struct bt_avrcp_header *avrcp_hdr; + + avctp_hdr = (void *)buf->data; + net_buf_pull(buf, sizeof(*avctp_hdr)); + avrcp_hdr = (void *)buf->data; + + if (avctp_hdr->pid != sys_cpu_to_be16(BT_SDP_AV_REMOTE_SVCLASS)) { + return -EINVAL; /* Ignore other profile */ + } + + LOG_DBG("AVRCP msg received, cr:0x%X, tid:0x%X, ctype: 0x%X, opc:0x%02X,", avctp_hdr->cr, + avctp_hdr->tid, avrcp_hdr->ctype, avrcp_hdr->opcode); + if (avctp_hdr->cr == BT_AVCTP_RESPONSE) { + if (avrcp_hdr->opcode == BT_AVRCP_OPC_VENDOR_DEPENDENT && + avrcp_hdr->ctype == BT_AVRCP_CTYPE_CHANGED) { + /* Status changed notifiation, do not reset timer */ + } else if (avrcp_hdr->opcode == BT_AVRCP_OPC_PASS_THROUGH) { + /* No max response time for pass through commands */ + } else if (avrcp->req.tid != avctp_hdr->tid || + avrcp->req.subunit != avrcp_hdr->subunit_id || + avrcp->req.opcode != avrcp_hdr->opcode) { + LOG_WRN("unexpected AVRCP response, expected tid:0x%X, subunit:0x%X, " + "opc:0x%02X", + avrcp->req.tid, avrcp->req.subunit, avrcp->req.opcode); + } else { + k_work_cancel_delayable(&avrcp->timeout_work); + } + } + + /* TODO: add handlers */ + + return 0; +} + static const struct bt_avctp_ops_cb avctp_ops = { .connected = avrcp_connected, .disconnected = avrcp_disconnected, + .recv = avrcp_recv, }; static int avrcp_accept(struct bt_conn *conn, struct bt_avctp **session) @@ -397,7 +437,6 @@ static int avrcp_send(struct bt_avrcp *avrcp, struct net_buf *buf) avrcp->req.opcode = avrcp_hdr.opcode; k_work_reschedule(&avrcp->timeout_work, AVRCP_TIMEOUT); - /* TODO: k_work_cancel_delayable(&avrcp->timeout_work); when response received */ } return 0; diff --git a/subsys/bluetooth/host/classic/shell/avrcp.c b/subsys/bluetooth/host/classic/shell/avrcp.c index 46e87e8795a676..4bf758f6178960 100644 --- a/subsys/bluetooth/host/classic/shell/avrcp.c +++ b/subsys/bluetooth/host/classic/shell/avrcp.c @@ -31,14 +31,6 @@ struct bt_avrcp *default_avrcp; static bool avrcp_registered; -#define CHECK_REGISTER_CALLBACKS(_sh, _errno) \ - do { \ - if (!avrcp_registered) { \ - if (register_cb(_sh) != 0) \ - return _errno; \ - } \ - } while (0) - static void avrcp_connected(struct bt_avrcp *avrcp) { default_avrcp = avrcp; @@ -88,7 +80,11 @@ static int cmd_register_cb(const struct shell *sh, int32_t argc, char *argv[]) static int cmd_connect(const struct shell *sh, int32_t argc, char *argv[]) { - CHECK_REGISTER_CALLBACKS(sh, -ENOEXEC); + if (!avrcp_registered) { + if (register_cb(sh) != 0) { + return -ENOEXEC; + } + } if (!default_conn) { shell_error(sh, "BR/EDR not connected"); @@ -105,7 +101,11 @@ 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[]) { - CHECK_REGISTER_CALLBACKS(sh, -ENOEXEC); + if (!avrcp_registered) { + if (register_cb(sh) != 0) { + return -ENOEXEC; + } + } if (default_avrcp != NULL) { bt_avrcp_disconnect(default_avrcp); @@ -119,7 +119,11 @@ 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[]) { - CHECK_REGISTER_CALLBACKS(sh, -ENOEXEC); + if (!avrcp_registered) { + if (register_cb(sh) != 0) { + return -ENOEXEC; + } + } if (default_avrcp != NULL) { bt_avrcp_get_unit_info(default_avrcp); @@ -131,12 +135,12 @@ static int cmd_get_unit_info(const struct shell *sh, int32_t argc, char *argv[]) } SHELL_STATIC_SUBCMD_SET_CREATE(avrcp_cmds, - SHELL_CMD_ARG(register_cb, NULL, "register avrcp callbacks", - cmd_register_cb, 1, 0), - SHELL_CMD_ARG(connect, NULL, "
", cmd_connect, 2, 0), - SHELL_CMD_ARG(disconnect, NULL, "
", cmd_disconnect, 2, 0), - SHELL_CMD_ARG(get_unit, NULL, "
", cmd_get_unit_info, 2, 0), - SHELL_SUBCMD_SET_END); + SHELL_CMD_ARG(register_cb, NULL, "register avrcp callbacks", + cmd_register_cb, 1, 0), + SHELL_CMD_ARG(connect, NULL, "
", cmd_connect, 2, 0), + SHELL_CMD_ARG(disconnect, NULL, "
", cmd_disconnect, 2, 0), + SHELL_CMD_ARG(get_unit, NULL, "
", cmd_get_unit_info, 2, 0), + SHELL_SUBCMD_SET_END); static int cmd_avrcp(const struct shell *sh, size_t argc, char **argv) { @@ -151,5 +155,4 @@ static int cmd_avrcp(const struct shell *sh, size_t argc, char **argv) return -ENOEXEC; } -SHELL_CMD_ARG_REGISTER(avrcp, &avrcp_cmds, "Bluetooth AVRCP sh commands", - cmd_avrcp, 1, 1); +SHELL_CMD_ARG_REGISTER(avrcp, &avrcp_cmds, "Bluetooth AVRCP sh commands", cmd_avrcp, 1, 1);