1 /** @file
2  *  @brief Audio Video Remote Control Profile
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 <errno.h>
14 #include <zephyr/sys/atomic.h>
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/sys/util.h>
17 #include <zephyr/sys/printk.h>
18 
19 #include <zephyr/bluetooth/bluetooth.h>
20 #include <zephyr/bluetooth/classic/avrcp.h>
21 #include <zephyr/bluetooth/classic/sdp.h>
22 #include <zephyr/bluetooth/l2cap.h>
23 
24 #include "host/hci_core.h"
25 #include "host/conn_internal.h"
26 #include "host/l2cap_internal.h"
27 #include "avctp_internal.h"
28 #include "avrcp_internal.h"
29 
30 #define LOG_LEVEL CONFIG_BT_AVRCP_LOG_LEVEL
31 #include <zephyr/logging/log.h>
32 LOG_MODULE_REGISTER(bt_avrcp);
33 
34 struct bt_avrcp {
35 	struct bt_avctp session;
36 	struct bt_avrcp_req req;
37 	struct k_work_delayable timeout_work;
38 	uint8_t local_tid;
39 };
40 
41 struct avrcp_handler {
42 	bt_avrcp_opcode_t opcode;
43 	void (*func)(struct bt_avrcp *avrcp, struct net_buf *buf, bt_avctp_cr_t cr);
44 };
45 
46 #define AVRCP_TIMEOUT       K_SECONDS(3) /* Shell be greater than TMTP (1000ms) */
47 #define AVRCP_AVCTP(_avctp) CONTAINER_OF(_avctp, struct bt_avrcp, session)
48 #define AVRCP_KWORK(_work)                                                                         \
49 	CONTAINER_OF(CONTAINER_OF(_work, struct k_work_delayable, work), struct bt_avrcp,          \
50 		     timeout_work)
51 
52 static const struct bt_avrcp_cb *avrcp_cb;
53 static struct bt_avrcp avrcp_connection[CONFIG_BT_MAX_CONN];
54 
55 #if defined(CONFIG_BT_AVRCP_TARGET)
56 static struct bt_sdp_attribute avrcp_tg_attrs[] = {
57 	BT_SDP_NEW_SERVICE,
58 	BT_SDP_LIST(
59 		BT_SDP_ATTR_SVCLASS_ID_LIST,
60 		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 3),
61 		BT_SDP_DATA_ELEM_LIST(
62 		{
63 			BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
64 			BT_SDP_ARRAY_16(BT_SDP_AV_REMOTE_TARGET_SVCLASS)
65 		},
66 		)
67 	),
68 	BT_SDP_LIST(
69 		BT_SDP_ATTR_PROTO_DESC_LIST,
70 		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 16),
71 		BT_SDP_DATA_ELEM_LIST(
72 		{
73 			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
74 			BT_SDP_DATA_ELEM_LIST({BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
75 			BT_SDP_ARRAY_16(BT_SDP_PROTO_L2CAP)},
76 			{
77 				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
78 				BT_SDP_ARRAY_16(BT_UUID_AVCTP_VAL)
79 			},
80 			)
81 		},
82 		{
83 			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
84 			BT_SDP_DATA_ELEM_LIST(
85 			{
86 				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
87 				BT_SDP_ARRAY_16(BT_UUID_AVCTP_VAL)
88 			},
89 			{
90 				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
91 				BT_SDP_ARRAY_16(AVCTP_VER_1_4)
92 			},
93 			)
94 		},
95 		)
96 	),
97 	/* C1: Browsing not supported */
98 	/* C2: Cover Art not supported */
99 	BT_SDP_LIST(
100 		BT_SDP_ATTR_PROFILE_DESC_LIST,
101 		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 8),
102 		BT_SDP_DATA_ELEM_LIST(
103 		{
104 			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
105 			BT_SDP_DATA_ELEM_LIST(
106 			{
107 				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
108 				BT_SDP_ARRAY_16(BT_SDP_AV_REMOTE_SVCLASS)
109 			},
110 			{
111 				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
112 				BT_SDP_ARRAY_16(AVRCP_VER_1_6)
113 			},
114 			)
115 		},
116 		)
117 	),
118 	BT_SDP_SUPPORTED_FEATURES(AVRCP_CAT_1 | AVRCP_CAT_2),
119 	/* O: Provider Name not presented */
120 	BT_SDP_SERVICE_NAME("AVRCP Target"),
121 };
122 
123 static struct bt_sdp_record avrcp_tg_rec = BT_SDP_RECORD(avrcp_tg_attrs);
124 #endif /* CONFIG_BT_AVRCP_TARGET */
125 
126 #if defined(CONFIG_BT_AVRCP_CONTROLLER)
127 static struct bt_sdp_attribute avrcp_ct_attrs[] = {
128 	BT_SDP_NEW_SERVICE,
129 	BT_SDP_LIST(
130 		BT_SDP_ATTR_SVCLASS_ID_LIST,
131 		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
132 		BT_SDP_DATA_ELEM_LIST(
133 		{
134 			BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
135 			BT_SDP_ARRAY_16(BT_SDP_AV_REMOTE_SVCLASS)
136 		},
137 		{
138 			BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
139 			BT_SDP_ARRAY_16(BT_SDP_AV_REMOTE_CONTROLLER_SVCLASS)
140 		},
141 		)
142 	),
143 	BT_SDP_LIST(
144 		BT_SDP_ATTR_PROTO_DESC_LIST,
145 		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 16),
146 		BT_SDP_DATA_ELEM_LIST(
147 		{
148 			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
149 			BT_SDP_DATA_ELEM_LIST(
150 			{
151 				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
152 				BT_SDP_ARRAY_16(BT_SDP_PROTO_L2CAP)
153 			},
154 			{
155 				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
156 				BT_SDP_ARRAY_16(BT_UUID_AVCTP_VAL)
157 			},
158 			)
159 		},
160 		{
161 			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
162 			BT_SDP_DATA_ELEM_LIST(
163 			{
164 				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
165 				BT_SDP_ARRAY_16(BT_UUID_AVCTP_VAL)
166 			},
167 			{
168 				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
169 				BT_SDP_ARRAY_16(AVCTP_VER_1_4)
170 			},
171 			)
172 		},
173 		)
174 	),
175 	/* C1: Browsing not supported */
176 	BT_SDP_LIST(
177 		BT_SDP_ATTR_PROFILE_DESC_LIST,
178 		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 8),
179 		BT_SDP_DATA_ELEM_LIST(
180 		{
181 			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
182 			BT_SDP_DATA_ELEM_LIST(
183 			{
184 				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
185 				BT_SDP_ARRAY_16(BT_SDP_AV_REMOTE_SVCLASS)
186 			},
187 			{
188 				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
189 				BT_SDP_ARRAY_16(AVRCP_VER_1_6)
190 			},
191 			)
192 		},
193 		)
194 	),
195 	BT_SDP_SUPPORTED_FEATURES(AVRCP_CAT_1 | AVRCP_CAT_2),
196 	/* O: Provider Name not presented */
197 	BT_SDP_SERVICE_NAME("AVRCP Controller"),
198 };
199 
200 static struct bt_sdp_record avrcp_ct_rec = BT_SDP_RECORD(avrcp_ct_attrs);
201 #endif /* CONFIG_BT_AVRCP_CONTROLLER */
202 
get_new_connection(struct bt_conn * conn)203 static struct bt_avrcp *get_new_connection(struct bt_conn *conn)
204 {
205 	struct bt_avrcp *avrcp;
206 
207 	if (!conn) {
208 		LOG_ERR("Invalid Input (err: %d)", -EINVAL);
209 		return NULL;
210 	}
211 
212 	avrcp = &avrcp_connection[bt_conn_index(conn)];
213 	memset(avrcp, 0, sizeof(struct bt_avrcp));
214 	return avrcp;
215 }
216 
avrcp_timeout(struct k_work * work)217 static void avrcp_timeout(struct k_work *work)
218 {
219 	struct bt_avrcp *avrcp = AVRCP_KWORK(work);
220 
221 	LOG_WRN("Timeout: tid 0x%X, opc 0x%02X", avrcp->req.tid, avrcp->req.opcode);
222 }
223 
224 /* The AVCTP L2CAP channel established */
avrcp_connected(struct bt_avctp * session)225 static void avrcp_connected(struct bt_avctp *session)
226 {
227 	struct bt_avrcp *avrcp = AVRCP_AVCTP(session);
228 
229 	if ((avrcp_cb != NULL) && (avrcp_cb->connected != NULL)) {
230 		avrcp_cb->connected(avrcp);
231 	}
232 
233 	k_work_init_delayable(&avrcp->timeout_work, avrcp_timeout);
234 }
235 
236 /* The AVCTP L2CAP channel released */
avrcp_disconnected(struct bt_avctp * session)237 static void avrcp_disconnected(struct bt_avctp *session)
238 {
239 	struct bt_avrcp *avrcp = AVRCP_AVCTP(session);
240 
241 	if ((avrcp_cb != NULL) && (avrcp_cb->disconnected != NULL)) {
242 		avrcp_cb->disconnected(avrcp);
243 	}
244 }
245 
avrcp_vendor_dependent_handler(struct bt_avrcp * avrcp,struct net_buf * buf,bt_avctp_cr_t cr)246 static void avrcp_vendor_dependent_handler(struct bt_avrcp *avrcp, struct net_buf *buf,
247 					   bt_avctp_cr_t cr)
248 {
249 	/* ToDo */
250 }
251 
avrcp_unit_info_handler(struct bt_avrcp * avrcp,struct net_buf * buf,bt_avctp_cr_t cr)252 static void avrcp_unit_info_handler(struct bt_avrcp *avrcp, struct net_buf *buf, bt_avctp_cr_t cr)
253 {
254 	struct bt_avrcp_header *avrcp_hdr;
255 	struct bt_avrcp_unit_info_rsp rsp;
256 
257 	if (cr == BT_AVCTP_CMD) {
258 		/* ToDo */
259 	} else { /* BT_AVCTP_RESPONSE */
260 		if ((avrcp_cb != NULL) && (avrcp_cb->unit_info_rsp != NULL)) {
261 			net_buf_pull(buf, sizeof(*avrcp_hdr));
262 			if (buf->len != 5) {
263 				LOG_ERR("Invalid unit info length");
264 				return;
265 			}
266 			net_buf_pull_u8(buf); /* Always 0x07 */
267 			rsp.unit_type = FIELD_GET(GENMASK(7, 3), net_buf_pull_u8(buf));
268 			rsp.company_id = net_buf_pull_be24(buf);
269 			avrcp_cb->unit_info_rsp(avrcp, &rsp);
270 		}
271 	}
272 }
273 
avrcp_subunit_info_handler(struct bt_avrcp * avrcp,struct net_buf * buf,bt_avctp_cr_t cr)274 static void avrcp_subunit_info_handler(struct bt_avrcp *avrcp, struct net_buf *buf,
275 					   bt_avctp_cr_t cr)
276 {
277 	struct bt_avrcp_header *avrcp_hdr;
278 	struct bt_avrcp_subunit_info_rsp rsp;
279 	uint8_t tmp;
280 
281 	if (cr == BT_AVCTP_CMD) {
282 		/* ToDo */
283 	} else { /* BT_AVCTP_RESPONSE */
284 		if ((avrcp_cb != NULL) && (avrcp_cb->subunit_info_rsp != NULL)) {
285 			net_buf_pull(buf, sizeof(*avrcp_hdr));
286 			if (buf->len < 5) {
287 				LOG_ERR("Invalid subunit info length");
288 				return;
289 			}
290 			net_buf_pull_u8(buf); /* Always 0x07 */
291 			tmp = net_buf_pull_u8(buf);
292 			rsp.subunit_type = FIELD_GET(GENMASK(7, 3), tmp);
293 			rsp.max_subunit_id = FIELD_GET(GENMASK(2, 0), tmp);
294 			if (buf->len < (rsp.max_subunit_id << 1)) {
295 				LOG_ERR("Invalid subunit info response");
296 				return;
297 			}
298 			rsp.extended_subunit_type = buf->data;
299 			rsp.extended_subunit_id = rsp.extended_subunit_type + rsp.max_subunit_id;
300 			avrcp_cb->subunit_info_rsp(avrcp, &rsp);
301 		}
302 	}
303 }
304 
avrcp_pass_through_handler(struct bt_avrcp * avrcp,struct net_buf * buf,bt_avctp_cr_t cr)305 static void avrcp_pass_through_handler(struct bt_avrcp *avrcp, struct net_buf *buf,
306 					   bt_avctp_cr_t cr)
307 {
308 	/* ToDo */
309 }
310 
311 static const struct avrcp_handler handler[] = {
312 	{ BT_AVRCP_OPC_VENDOR_DEPENDENT, avrcp_vendor_dependent_handler },
313 	{ BT_AVRCP_OPC_UNIT_INFO, avrcp_unit_info_handler },
314 	{ BT_AVRCP_OPC_SUBUNIT_INFO, avrcp_subunit_info_handler },
315 	{ BT_AVRCP_OPC_PASS_THROUGH, avrcp_pass_through_handler },
316 };
317 
318 /* An AVRCP message received */
avrcp_recv(struct bt_avctp * session,struct net_buf * buf)319 static int avrcp_recv(struct bt_avctp *session, struct net_buf *buf)
320 {
321 	struct bt_avrcp *avrcp = AVRCP_AVCTP(session);
322 	struct bt_avctp_header *avctp_hdr;
323 	struct bt_avrcp_header *avrcp_hdr;
324 	uint8_t tid, i;
325 	bt_avctp_cr_t cr;
326 	bt_avrcp_ctype_t ctype;
327 	bt_avrcp_subunit_id_t subunit_id;
328 	bt_avrcp_subunit_type_t subunit_type;
329 
330 	avctp_hdr = (void *)buf->data;
331 	net_buf_pull(buf, sizeof(*avctp_hdr));
332 	if (buf->len < sizeof(*avrcp_hdr)) {
333 		LOG_ERR("invalid AVRCP header received");
334 		return -EINVAL;
335 	}
336 
337 	avrcp_hdr = (void *)buf->data;
338 	tid = BT_AVCTP_HDR_GET_TRANSACTION_LABLE(avctp_hdr);
339 	cr = BT_AVCTP_HDR_GET_CR(avctp_hdr);
340 	ctype = BT_AVRCP_HDR_GET_CTYPE(avrcp_hdr);
341 	subunit_id = BT_AVRCP_HDR_GET_SUBUNIT_ID(avrcp_hdr);
342 	subunit_type = BT_AVRCP_HDR_GET_SUBUNIT_TYPE(avrcp_hdr);
343 
344 	if (avctp_hdr->pid != sys_cpu_to_be16(BT_SDP_AV_REMOTE_SVCLASS)) {
345 		return -EINVAL; /* Ignore other profile */
346 	}
347 
348 	LOG_DBG("AVRCP msg received, cr:0x%X, tid:0x%X, ctype: 0x%X, opc:0x%02X,", cr, tid, ctype,
349 		avrcp_hdr->opcode);
350 	if (cr == BT_AVCTP_RESPONSE) {
351 		if (avrcp_hdr->opcode == BT_AVRCP_OPC_VENDOR_DEPENDENT &&
352 		    ctype == BT_AVRCP_CTYPE_CHANGED) {
353 			/* Status changed notifiation, do not reset timer */
354 		} else if (avrcp_hdr->opcode == BT_AVRCP_OPC_PASS_THROUGH) {
355 			/* No max response time for pass through commands  */
356 		} else if (tid != avrcp->req.tid || subunit_type != avrcp->req.subunit ||
357 			   avrcp_hdr->opcode != avrcp->req.opcode) {
358 			LOG_WRN("unexpected AVRCP response, expected tid:0x%X, subunit:0x%X, "
359 				"opc:0x%02X",
360 				avrcp->req.tid, avrcp->req.subunit, avrcp->req.opcode);
361 		} else {
362 			k_work_cancel_delayable(&avrcp->timeout_work);
363 		}
364 	}
365 
366 	for (i = 0U; i < ARRAY_SIZE(handler); i++) {
367 		if (avrcp_hdr->opcode == handler[i].opcode) {
368 			handler[i].func(avrcp, buf, cr);
369 			return 0;
370 		}
371 	}
372 
373 	return 0;
374 }
375 
376 static const struct bt_avctp_ops_cb avctp_ops = {
377 	.connected = avrcp_connected,
378 	.disconnected = avrcp_disconnected,
379 	.recv = avrcp_recv,
380 };
381 
avrcp_accept(struct bt_conn * conn,struct bt_avctp ** session)382 static int avrcp_accept(struct bt_conn *conn, struct bt_avctp **session)
383 {
384 	struct bt_avrcp *avrcp;
385 
386 	avrcp = get_new_connection(conn);
387 	if (!avrcp) {
388 		return -ENOMEM;
389 	}
390 
391 	*session = &(avrcp->session);
392 	avrcp->session.ops = &avctp_ops;
393 
394 	LOG_DBG("session: %p", &(avrcp->session));
395 
396 	return 0;
397 }
398 
399 static struct bt_avctp_event_cb avctp_cb = {
400 	.accept = avrcp_accept,
401 };
402 
bt_avrcp_init(void)403 int bt_avrcp_init(void)
404 {
405 	int err;
406 
407 	/* Register event handlers with AVCTP */
408 	err = bt_avctp_register(&avctp_cb);
409 	if (err < 0) {
410 		LOG_ERR("AVRCP registration failed");
411 		return err;
412 	}
413 
414 #if defined(CONFIG_BT_AVRCP_TARGET)
415 	bt_sdp_register_service(&avrcp_tg_rec);
416 #endif /* CONFIG_BT_AVRCP_CONTROLLER */
417 
418 #if defined(CONFIG_BT_AVRCP_CONTROLLER)
419 	bt_sdp_register_service(&avrcp_ct_rec);
420 #endif /* CONFIG_BT_AVRCP_CONTROLLER */
421 
422 	LOG_DBG("AVRCP Initialized successfully.");
423 	return 0;
424 }
425 
bt_avrcp_connect(struct bt_conn * conn)426 struct bt_avrcp *bt_avrcp_connect(struct bt_conn *conn)
427 {
428 	struct bt_avrcp *avrcp;
429 	int err;
430 
431 	avrcp = get_new_connection(conn);
432 	if (!avrcp) {
433 		LOG_ERR("Cannot allocate memory");
434 		return NULL;
435 	}
436 
437 	avrcp->session.ops = &avctp_ops;
438 	err = bt_avctp_connect(conn, &(avrcp->session));
439 	if (err < 0) {
440 		/* If error occurs, undo the saving and return the error */
441 		memset(avrcp, 0, sizeof(struct bt_avrcp));
442 		LOG_DBG("AVCTP Connect failed");
443 		return NULL;
444 	}
445 
446 	LOG_DBG("Connection request sent");
447 	return avrcp;
448 }
449 
bt_avrcp_disconnect(struct bt_avrcp * avrcp)450 int bt_avrcp_disconnect(struct bt_avrcp *avrcp)
451 {
452 	int err;
453 
454 	err = bt_avctp_disconnect(&(avrcp->session));
455 	if (err < 0) {
456 		LOG_DBG("AVCTP Disconnect failed");
457 		return err;
458 	}
459 
460 	return err;
461 }
462 
avrcp_create_pdu(struct bt_avrcp * avrcp,bt_avctp_cr_t cr)463 static struct net_buf *avrcp_create_pdu(struct bt_avrcp *avrcp, bt_avctp_cr_t cr)
464 {
465 	struct net_buf *buf;
466 
467 	buf = bt_avctp_create_pdu(&(avrcp->session), cr, BT_AVCTP_PKT_TYPE_SINGLE,
468 				  BT_AVCTP_IPID_NONE, &avrcp->local_tid,
469 				  sys_cpu_to_be16(BT_SDP_AV_REMOTE_SVCLASS));
470 
471 	return buf;
472 }
473 
avrcp_create_unit_pdu(struct bt_avrcp * avrcp,bt_avctp_cr_t cr)474 static struct net_buf *avrcp_create_unit_pdu(struct bt_avrcp *avrcp, bt_avctp_cr_t cr)
475 {
476 	struct net_buf *buf;
477 	struct bt_avrcp_unit_info_cmd *cmd;
478 
479 	buf = avrcp_create_pdu(avrcp, cr);
480 	if (!buf) {
481 		return buf;
482 	}
483 
484 	cmd = net_buf_add(buf, sizeof(*cmd));
485 	memset(cmd, 0, sizeof(*cmd));
486 	BT_AVRCP_HDR_SET_CTYPE(&cmd->hdr, cr == BT_AVCTP_CMD ? BT_AVRCP_CTYPE_STATUS
487 							     : BT_AVRCP_CTYPE_IMPLEMENTED_STABLE);
488 	BT_AVRCP_HDR_SET_SUBUNIT_ID(&cmd->hdr, BT_AVRCP_SUBUNIT_ID_IGNORE);
489 	BT_AVRCP_HDR_SET_SUBUNIT_TYPE(&cmd->hdr, BT_AVRCP_SUBUNIT_TYPE_UNIT);
490 	cmd->hdr.opcode = BT_AVRCP_OPC_UNIT_INFO;
491 
492 	return buf;
493 }
494 
avrcp_create_subunit_pdu(struct bt_avrcp * avrcp,bt_avctp_cr_t cr)495 static struct net_buf *avrcp_create_subunit_pdu(struct bt_avrcp *avrcp, bt_avctp_cr_t cr)
496 {
497 	struct net_buf *buf;
498 	struct bt_avrcp_unit_info_cmd *cmd;
499 
500 	buf = avrcp_create_pdu(avrcp, cr);
501 	if (!buf) {
502 		return buf;
503 	}
504 
505 	cmd = net_buf_add(buf, sizeof(*cmd));
506 	memset(cmd, 0, sizeof(*cmd));
507 	BT_AVRCP_HDR_SET_CTYPE(&cmd->hdr, cr == BT_AVCTP_CMD ? BT_AVRCP_CTYPE_STATUS
508 							     : BT_AVRCP_CTYPE_IMPLEMENTED_STABLE);
509 	BT_AVRCP_HDR_SET_SUBUNIT_ID(&cmd->hdr, BT_AVRCP_SUBUNIT_ID_IGNORE);
510 	BT_AVRCP_HDR_SET_SUBUNIT_TYPE(&cmd->hdr, BT_AVRCP_SUBUNIT_TYPE_UNIT);
511 	cmd->hdr.opcode = BT_AVRCP_OPC_SUBUNIT_INFO;
512 
513 	return buf;
514 }
515 
avrcp_send(struct bt_avrcp * avrcp,struct net_buf * buf)516 static int avrcp_send(struct bt_avrcp *avrcp, struct net_buf *buf)
517 {
518 	int err;
519 	struct bt_avctp_header *avctp_hdr = (struct bt_avctp_header *)(buf->data);
520 	struct bt_avrcp_header *avrcp_hdr =
521 		(struct bt_avrcp_header *)(buf->data + sizeof(*avctp_hdr));
522 	uint8_t tid = BT_AVCTP_HDR_GET_TRANSACTION_LABLE(avctp_hdr);
523 	bt_avctp_cr_t cr = BT_AVCTP_HDR_GET_CR(avctp_hdr);
524 	bt_avrcp_ctype_t ctype = BT_AVRCP_HDR_GET_CTYPE(avrcp_hdr);
525 	bt_avrcp_subunit_type_t subunit_type = BT_AVRCP_HDR_GET_SUBUNIT_TYPE(avrcp_hdr);
526 
527 	LOG_DBG("AVRCP send cr:0x%X, tid:0x%X, ctype: 0x%X, opc:0x%02X\n", cr, tid, ctype,
528 		avrcp_hdr->opcode);
529 	err = bt_avctp_send(&(avrcp->session), buf);
530 	if (err < 0) {
531 		return err;
532 	}
533 
534 	if (cr == BT_AVCTP_CMD && avrcp_hdr->opcode != BT_AVRCP_OPC_PASS_THROUGH) {
535 		avrcp->req.tid = tid;
536 		avrcp->req.subunit = subunit_type;
537 		avrcp->req.opcode = avrcp_hdr->opcode;
538 
539 		k_work_reschedule(&avrcp->timeout_work, AVRCP_TIMEOUT);
540 	}
541 
542 	return 0;
543 }
544 
bt_avrcp_get_unit_info(struct bt_avrcp * avrcp)545 int bt_avrcp_get_unit_info(struct bt_avrcp *avrcp)
546 {
547 	struct net_buf *buf;
548 	uint8_t param[5];
549 
550 	buf = avrcp_create_unit_pdu(avrcp, BT_AVCTP_CMD);
551 	if (!buf) {
552 		return -ENOMEM;
553 	}
554 
555 	memset(param, 0xFF, ARRAY_SIZE(param));
556 	net_buf_add_mem(buf, param, sizeof(param));
557 
558 	return avrcp_send(avrcp, buf);
559 }
560 
bt_avrcp_get_subunit_info(struct bt_avrcp * avrcp)561 int bt_avrcp_get_subunit_info(struct bt_avrcp *avrcp)
562 {
563 	struct net_buf *buf;
564 	uint8_t param[5];
565 
566 	buf = avrcp_create_subunit_pdu(avrcp, BT_AVCTP_CMD);
567 	if (!buf) {
568 		return -ENOMEM;
569 	}
570 
571 	memset(param, 0xFF, ARRAY_SIZE(param));
572 	param[0] = FIELD_PREP(GENMASK(6, 4), AVRCP_SUBUNIT_PAGE) |
573 		   FIELD_PREP(GENMASK(2, 0), AVRCP_SUBUNIT_EXTENSION_COED);
574 	net_buf_add_mem(buf, param, sizeof(param));
575 
576 	return avrcp_send(avrcp, buf);
577 }
578 
bt_avrcp_register_cb(const struct bt_avrcp_cb * cb)579 int bt_avrcp_register_cb(const struct bt_avrcp_cb *cb)
580 {
581 	avrcp_cb = cb;
582 	return 0;
583 }
584