1 /** @file
2 * @brief Audio Video Control Transport Protocol
3 */
4
5 /*
6 * Copyright (c) 2015-2016 Intel Corporation
7 * Copyright (C) 2024 Xiaomi Corporation
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #include <string.h>
13 #include <strings.h>
14 #include <errno.h>
15 #include <zephyr/sys/atomic.h>
16 #include <zephyr/sys/byteorder.h>
17 #include <zephyr/sys/util.h>
18
19 #include <zephyr/bluetooth/hci.h>
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/l2cap.h>
22 #include <zephyr/bluetooth/classic/sdp.h>
23
24 #include "avctp_internal.h"
25 #include "host/hci_core.h"
26 #include "host/conn_internal.h"
27 #include "l2cap_br_internal.h"
28
29 #define LOG_LEVEL CONFIG_BT_AVCTP_LOG_LEVEL
30 #include <zephyr/logging/log.h>
31 LOG_MODULE_REGISTER(bt_avctp);
32
33 #define AVCTP_CHAN(_ch) CONTAINER_OF(_ch, struct bt_avctp, br_chan.chan)
34
35 static const struct bt_avctp_event_cb *event_cb;
36
avctp_l2cap_connected(struct bt_l2cap_chan * chan)37 static void avctp_l2cap_connected(struct bt_l2cap_chan *chan)
38 {
39 struct bt_avctp *session;
40
41 if (!chan) {
42 LOG_ERR("Invalid AVCTP chan");
43 return;
44 }
45
46 session = AVCTP_CHAN(chan);
47 LOG_DBG("chan %p session %p", chan, session);
48
49 if (session->ops && session->ops->connected) {
50 session->ops->connected(session);
51 }
52 }
53
avctp_l2cap_disconnected(struct bt_l2cap_chan * chan)54 static void avctp_l2cap_disconnected(struct bt_l2cap_chan *chan)
55 {
56 struct bt_avctp *session;
57
58 if (!chan) {
59 LOG_ERR("Invalid AVCTP chan");
60 return;
61 }
62
63 session = AVCTP_CHAN(chan);
64 LOG_DBG("chan %p session %p", chan, session);
65 session->br_chan.chan.conn = NULL;
66
67 if (session->ops && session->ops->disconnected) {
68 session->ops->disconnected(session);
69 }
70 }
71
avctp_l2cap_encrypt_changed(struct bt_l2cap_chan * chan,uint8_t status)72 static void avctp_l2cap_encrypt_changed(struct bt_l2cap_chan *chan, uint8_t status)
73 {
74 LOG_DBG("");
75 }
76
avctp_l2cap_recv(struct bt_l2cap_chan * chan,struct net_buf * buf)77 static int avctp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
78 {
79 struct net_buf *rsp;
80 struct bt_avctp *session = AVCTP_CHAN(chan);
81 struct bt_avctp_header *hdr = (void *)buf->data;
82 uint8_t tid;
83 bt_avctp_pkt_type_t pkt_type;
84 bt_avctp_cr_t cr;
85
86 if (buf->len < sizeof(*hdr)) {
87 LOG_ERR("invalid AVCTP header received");
88 return -EINVAL;
89 }
90
91 tid = BT_AVCTP_HDR_GET_TRANSACTION_LABLE(hdr);
92 pkt_type = BT_AVCTP_HDR_GET_PACKET_TYPE(hdr);
93 cr = BT_AVCTP_HDR_GET_CR(hdr);
94
95 switch (pkt_type) {
96 case BT_AVCTP_PKT_TYPE_SINGLE:
97 break;
98 case BT_AVCTP_PKT_TYPE_START:
99 case BT_AVCTP_PKT_TYPE_CONTINUE:
100 case BT_AVCTP_PKT_TYPE_END:
101 default:
102 LOG_ERR("fragmented AVCTP message is not supported, pkt_type = %d", pkt_type);
103 return -EINVAL;
104 }
105
106 switch (hdr->pid) {
107 #if defined(CONFIG_BT_AVRCP)
108 case sys_cpu_to_be16(BT_SDP_AV_REMOTE_SVCLASS):
109 break;
110 #endif
111 default:
112 LOG_ERR("unsupported AVCTP PID received: 0x%04x", sys_be16_to_cpu(hdr->pid));
113 if (cr == BT_AVCTP_CMD) {
114 rsp = bt_avctp_create_pdu(session, BT_AVCTP_RESPONSE,
115 BT_AVCTP_PKT_TYPE_SINGLE, BT_AVCTP_IPID_INVALID,
116 &tid, hdr->pid);
117 if (!rsp) {
118 return -ENOMEM;
119 }
120 return bt_avctp_send(session, rsp);
121 }
122 return 0; /* No need to report to the upper layer */
123 }
124
125 return session->ops->recv(session, buf);
126 }
127
bt_avctp_connect(struct bt_conn * conn,struct bt_avctp * session)128 int bt_avctp_connect(struct bt_conn *conn, struct bt_avctp *session)
129 {
130 static const struct bt_l2cap_chan_ops ops = {
131 .connected = avctp_l2cap_connected,
132 .disconnected = avctp_l2cap_disconnected,
133 .encrypt_change = avctp_l2cap_encrypt_changed,
134 .recv = avctp_l2cap_recv,
135 };
136
137 if (!session) {
138 return -EINVAL;
139 }
140
141 session->br_chan.rx.mtu = BT_L2CAP_RX_MTU;
142 session->br_chan.chan.ops = &ops;
143 session->br_chan.required_sec_level = BT_SECURITY_L2;
144
145 return bt_l2cap_chan_connect(conn, &session->br_chan.chan, BT_L2CAP_PSM_AVCTP);
146 }
147
bt_avctp_disconnect(struct bt_avctp * session)148 int bt_avctp_disconnect(struct bt_avctp *session)
149 {
150 if (!session) {
151 return -EINVAL;
152 }
153
154 LOG_DBG("session %p", session);
155
156 return bt_l2cap_chan_disconnect(&session->br_chan.chan);
157 }
158
bt_avctp_create_pdu(struct bt_avctp * session,bt_avctp_cr_t cr,bt_avctp_pkt_type_t pkt_type,bt_avctp_ipid_t ipid,uint8_t * tid,uint16_t pid)159 struct net_buf *bt_avctp_create_pdu(struct bt_avctp *session, bt_avctp_cr_t cr,
160 bt_avctp_pkt_type_t pkt_type, bt_avctp_ipid_t ipid,
161 uint8_t *tid, uint16_t pid)
162 {
163 struct net_buf *buf;
164 struct bt_avctp_header *hdr;
165
166 LOG_DBG("");
167
168 buf = bt_l2cap_create_pdu(NULL, 0);
169 if (!buf) {
170 LOG_ERR("No buff available");
171 return buf;
172 }
173
174 hdr = net_buf_add(buf, sizeof(*hdr));
175 BT_AVCTP_HDR_SET_TRANSACTION_LABLE(hdr, *tid);
176 BT_AVCTP_HDR_SET_PACKET_TYPE(hdr, pkt_type);
177 BT_AVCTP_HDR_SET_CR(hdr, cr);
178 BT_AVCTP_HDR_SET_IPID(hdr, ipid);
179 hdr->pid = pid;
180
181 if (cr == BT_AVCTP_CMD) {
182 *tid = (*tid + 1) & 0x0F; /* Incremented by one */
183 }
184
185 LOG_DBG("cr:0x%lX, tid:0x%02lX", BT_AVCTP_HDR_GET_CR(hdr),
186 BT_AVCTP_HDR_GET_TRANSACTION_LABLE(hdr));
187 return buf;
188 }
189
bt_avctp_send(struct bt_avctp * session,struct net_buf * buf)190 int bt_avctp_send(struct bt_avctp *session, struct net_buf *buf)
191 {
192 int err;
193
194 err = bt_l2cap_chan_send(&session->br_chan.chan, buf);
195 if (err < 0) {
196 net_buf_unref(buf);
197 LOG_ERR("L2CAP send fail err = %d", err);
198 return err;
199 }
200
201 return err;
202 }
203
bt_avctp_register(const struct bt_avctp_event_cb * cb)204 int bt_avctp_register(const struct bt_avctp_event_cb *cb)
205 {
206 LOG_DBG("");
207
208 if (event_cb) {
209 return -EALREADY;
210 }
211
212 event_cb = cb;
213
214 return 0;
215 }
216
avctp_l2cap_accept(struct bt_conn * conn,struct bt_l2cap_server * server,struct bt_l2cap_chan ** chan)217 static int avctp_l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server,
218 struct bt_l2cap_chan **chan)
219 {
220 /* TODO */
221
222 return -ENOTSUP;
223 }
224
bt_avctp_init(void)225 int bt_avctp_init(void)
226 {
227 int err;
228 static struct bt_l2cap_server avctp_l2cap = {
229 .psm = BT_L2CAP_PSM_AVCTP,
230 .sec_level = BT_SECURITY_L2,
231 .accept = avctp_l2cap_accept,
232 };
233
234 LOG_DBG("");
235
236 /* Register AVCTP PSM with L2CAP */
237 err = bt_l2cap_br_server_register(&avctp_l2cap);
238 if (err < 0) {
239 LOG_ERR("AVCTP L2CAP registration failed %d", err);
240 }
241
242 return err;
243 }
244