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 	int err;
86 
87 	if (buf->len < sizeof(*hdr)) {
88 		LOG_ERR("invalid AVCTP header received");
89 		return -EINVAL;
90 	}
91 
92 	tid = BT_AVCTP_HDR_GET_TRANSACTION_LABLE(hdr);
93 	pkt_type = BT_AVCTP_HDR_GET_PACKET_TYPE(hdr);
94 	cr = BT_AVCTP_HDR_GET_CR(hdr);
95 
96 	switch (pkt_type) {
97 	case BT_AVCTP_PKT_TYPE_SINGLE:
98 		break;
99 	case BT_AVCTP_PKT_TYPE_START:
100 	case BT_AVCTP_PKT_TYPE_CONTINUE:
101 	case BT_AVCTP_PKT_TYPE_END:
102 	default:
103 		LOG_ERR("fragmented AVCTP message is not supported, pkt_type = %d", pkt_type);
104 		return -EINVAL;
105 	}
106 
107 	switch (hdr->pid) {
108 #if defined(CONFIG_BT_AVRCP)
109 	case sys_cpu_to_be16(BT_SDP_AV_REMOTE_SVCLASS):
110 		break;
111 #endif
112 	default:
113 		LOG_ERR("unsupported AVCTP PID received: 0x%04x", sys_be16_to_cpu(hdr->pid));
114 		if (cr == BT_AVCTP_CMD) {
115 			rsp = bt_avctp_create_pdu(session, BT_AVCTP_RESPONSE,
116 						  BT_AVCTP_PKT_TYPE_SINGLE, BT_AVCTP_IPID_INVALID,
117 						  tid, hdr->pid);
118 			if (!rsp) {
119 				return -ENOMEM;
120 			}
121 
122 			err = bt_avctp_send(session, rsp);
123 			if (err < 0) {
124 				net_buf_unref(rsp);
125 				LOG_ERR("AVCTP send fail, err = %d", err);
126 				return err;
127 			}
128 		}
129 		return 0; /* No need to report to the upper layer */
130 	}
131 
132 	return session->ops->recv(session, buf);
133 }
134 
135 static const struct bt_l2cap_chan_ops ops = {
136 	.connected = avctp_l2cap_connected,
137 	.disconnected = avctp_l2cap_disconnected,
138 	.encrypt_change = avctp_l2cap_encrypt_changed,
139 	.recv = avctp_l2cap_recv,
140 };
141 
bt_avctp_connect(struct bt_conn * conn,struct bt_avctp * session)142 int bt_avctp_connect(struct bt_conn *conn, struct bt_avctp *session)
143 {
144 	if (!session) {
145 		return -EINVAL;
146 	}
147 
148 	session->br_chan.rx.mtu = BT_L2CAP_RX_MTU;
149 	session->br_chan.chan.ops = &ops;
150 	session->br_chan.required_sec_level = BT_SECURITY_L2;
151 
152 	return bt_l2cap_chan_connect(conn, &session->br_chan.chan, BT_L2CAP_PSM_AVCTP);
153 }
154 
bt_avctp_disconnect(struct bt_avctp * session)155 int bt_avctp_disconnect(struct bt_avctp *session)
156 {
157 	if (!session) {
158 		return -EINVAL;
159 	}
160 
161 	LOG_DBG("session %p", session);
162 
163 	return bt_l2cap_chan_disconnect(&session->br_chan.chan);
164 }
165 
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)166 struct net_buf *bt_avctp_create_pdu(struct bt_avctp *session, bt_avctp_cr_t cr,
167 				    bt_avctp_pkt_type_t pkt_type, bt_avctp_ipid_t ipid,
168 				    uint8_t tid, uint16_t pid)
169 {
170 	struct net_buf *buf;
171 	struct bt_avctp_header *hdr;
172 
173 	LOG_DBG("");
174 
175 	buf = bt_l2cap_create_pdu(NULL, 0);
176 	if (!buf) {
177 		LOG_ERR("No buff available");
178 		return buf;
179 	}
180 
181 	hdr = net_buf_add(buf, sizeof(*hdr));
182 	BT_AVCTP_HDR_SET_TRANSACTION_LABLE(hdr, tid);
183 	BT_AVCTP_HDR_SET_PACKET_TYPE(hdr, pkt_type);
184 	BT_AVCTP_HDR_SET_CR(hdr, cr);
185 	BT_AVCTP_HDR_SET_IPID(hdr, ipid);
186 	hdr->pid = pid;
187 
188 	LOG_DBG("cr:0x%lX, tid:0x%02lX", BT_AVCTP_HDR_GET_CR(hdr),
189 		BT_AVCTP_HDR_GET_TRANSACTION_LABLE(hdr));
190 	return buf;
191 }
192 
bt_avctp_send(struct bt_avctp * session,struct net_buf * buf)193 int bt_avctp_send(struct bt_avctp *session, struct net_buf *buf)
194 {
195 	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
196 }
197 
bt_avctp_register(const struct bt_avctp_event_cb * cb)198 int bt_avctp_register(const struct bt_avctp_event_cb *cb)
199 {
200 	LOG_DBG("");
201 
202 	if (event_cb) {
203 		return -EALREADY;
204 	}
205 
206 	event_cb = cb;
207 
208 	return 0;
209 }
210 
avctp_l2cap_accept(struct bt_conn * conn,struct bt_l2cap_server * server,struct bt_l2cap_chan ** chan)211 static int avctp_l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server,
212 			      struct bt_l2cap_chan **chan)
213 {
214 	struct bt_avctp *session = NULL;
215 	int err;
216 
217 	LOG_DBG("conn %p", conn);
218 
219 	if (!event_cb) {
220 		LOG_WRN("AVCTP server is unsupported");
221 		return -ENOTSUP;
222 	}
223 
224 	/* Get the AVCTP session from upper layer */
225 	err = event_cb->accept(conn, &session);
226 	if (err < 0) {
227 		LOG_ERR("Get the AVCTP session failed %d", err);
228 		return err;
229 	}
230 
231 	session->br_chan.rx.mtu = BT_L2CAP_RX_MTU;
232 	session->br_chan.psm = BT_L2CAP_PSM_AVCTP;
233 	session->br_chan.chan.ops = &ops;
234 	*chan = &session->br_chan.chan;
235 
236 	return 0;
237 }
238 
bt_avctp_init(void)239 int bt_avctp_init(void)
240 {
241 	int err;
242 	static struct bt_l2cap_server avctp_l2cap = {
243 		.psm = BT_L2CAP_PSM_AVCTP,
244 		.sec_level = BT_SECURITY_L2,
245 		.accept = avctp_l2cap_accept,
246 	};
247 
248 	LOG_DBG("");
249 
250 	/* Register AVCTP PSM with L2CAP */
251 	err = bt_l2cap_br_server_register(&avctp_l2cap);
252 	if (err < 0) {
253 		LOG_ERR("AVCTP L2CAP registration failed %d", err);
254 	}
255 
256 	return err;
257 }
258