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: %d", buf->len);
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: %d", buf->len);
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 struct bt_avrcp_header *avrcp_hdr;
309 struct bt_avrcp_passthrough_rsp rsp;
310 uint8_t tmp;
311
312 if (cr == BT_AVCTP_CMD) {
313 /* ToDo */
314 } else { /* BT_AVCTP_RESPONSE */
315 if ((avrcp_cb != NULL) && (avrcp_cb->subunit_info_rsp != NULL)) {
316 avrcp_hdr = (struct bt_avrcp_header *)buf->data;
317 net_buf_pull(buf, sizeof(*avrcp_hdr));
318 if (buf->len < 2) {
319 LOG_ERR("Invalid passthrough length: %d", buf->len);
320 return;
321 }
322
323 rsp.response = BT_AVRCP_HDR_GET_CTYPE_OR_RSP(avrcp_hdr);
324 tmp = net_buf_pull_u8(buf);
325 rsp.operation_id = FIELD_GET(GENMASK(6, 0), tmp);
326 rsp.state = FIELD_GET(GENMASK(7, 7), tmp);
327 rsp.len = net_buf_pull_u8(buf);
328 rsp.payload = rsp.len ? buf->data : NULL;
329
330 avrcp_cb->passthrough_rsp(avrcp, &rsp);
331 }
332 }
333 }
334
335 static const struct avrcp_handler handler[] = {
336 { BT_AVRCP_OPC_VENDOR_DEPENDENT, avrcp_vendor_dependent_handler },
337 { BT_AVRCP_OPC_UNIT_INFO, avrcp_unit_info_handler },
338 { BT_AVRCP_OPC_SUBUNIT_INFO, avrcp_subunit_info_handler },
339 { BT_AVRCP_OPC_PASS_THROUGH, avrcp_pass_through_handler },
340 };
341
342 /* An AVRCP message received */
avrcp_recv(struct bt_avctp * session,struct net_buf * buf)343 static int avrcp_recv(struct bt_avctp *session, struct net_buf *buf)
344 {
345 struct bt_avrcp *avrcp = AVRCP_AVCTP(session);
346 struct bt_avctp_header *avctp_hdr;
347 struct bt_avrcp_header *avrcp_hdr;
348 uint8_t tid, i;
349 bt_avctp_cr_t cr;
350 bt_avrcp_rsp_t rsp;
351 bt_avrcp_subunit_id_t subunit_id;
352 bt_avrcp_subunit_type_t subunit_type;
353
354 avctp_hdr = (void *)buf->data;
355 net_buf_pull(buf, sizeof(*avctp_hdr));
356 if (buf->len < sizeof(*avrcp_hdr)) {
357 LOG_ERR("invalid AVRCP header received");
358 return -EINVAL;
359 }
360
361 avrcp_hdr = (void *)buf->data;
362 tid = BT_AVCTP_HDR_GET_TRANSACTION_LABLE(avctp_hdr);
363 cr = BT_AVCTP_HDR_GET_CR(avctp_hdr);
364 rsp = BT_AVRCP_HDR_GET_CTYPE_OR_RSP(avrcp_hdr);
365 subunit_id = BT_AVRCP_HDR_GET_SUBUNIT_ID(avrcp_hdr);
366 subunit_type = BT_AVRCP_HDR_GET_SUBUNIT_TYPE(avrcp_hdr);
367
368 if (avctp_hdr->pid != sys_cpu_to_be16(BT_SDP_AV_REMOTE_SVCLASS)) {
369 return -EINVAL; /* Ignore other profile */
370 }
371
372 LOG_DBG("AVRCP msg received, cr:0x%X, tid:0x%X, rsp: 0x%X, opc:0x%02X,", cr, tid, rsp,
373 avrcp_hdr->opcode);
374 if (cr == BT_AVCTP_RESPONSE) {
375 if (avrcp_hdr->opcode == BT_AVRCP_OPC_VENDOR_DEPENDENT &&
376 rsp == BT_AVRCP_RSP_CHANGED) {
377 /* Status changed notifiation, do not reset timer */
378 } else if (avrcp_hdr->opcode == BT_AVRCP_OPC_PASS_THROUGH) {
379 /* No max response time for pass through commands */
380 } else if (tid != avrcp->req.tid || subunit_type != avrcp->req.subunit ||
381 avrcp_hdr->opcode != avrcp->req.opcode) {
382 LOG_WRN("unexpected AVRCP response, expected tid:0x%X, subunit:0x%X, "
383 "opc:0x%02X",
384 avrcp->req.tid, avrcp->req.subunit, avrcp->req.opcode);
385 } else {
386 k_work_cancel_delayable(&avrcp->timeout_work);
387 }
388 }
389
390 for (i = 0U; i < ARRAY_SIZE(handler); i++) {
391 if (avrcp_hdr->opcode == handler[i].opcode) {
392 handler[i].func(avrcp, buf, cr);
393 return 0;
394 }
395 }
396
397 return 0;
398 }
399
400 static const struct bt_avctp_ops_cb avctp_ops = {
401 .connected = avrcp_connected,
402 .disconnected = avrcp_disconnected,
403 .recv = avrcp_recv,
404 };
405
avrcp_accept(struct bt_conn * conn,struct bt_avctp ** session)406 static int avrcp_accept(struct bt_conn *conn, struct bt_avctp **session)
407 {
408 struct bt_avrcp *avrcp;
409
410 avrcp = get_new_connection(conn);
411 if (!avrcp) {
412 return -ENOMEM;
413 }
414
415 *session = &(avrcp->session);
416 avrcp->session.ops = &avctp_ops;
417
418 LOG_DBG("session: %p", &(avrcp->session));
419
420 return 0;
421 }
422
423 static struct bt_avctp_event_cb avctp_cb = {
424 .accept = avrcp_accept,
425 };
426
bt_avrcp_init(void)427 int bt_avrcp_init(void)
428 {
429 int err;
430
431 /* Register event handlers with AVCTP */
432 err = bt_avctp_register(&avctp_cb);
433 if (err < 0) {
434 LOG_ERR("AVRCP registration failed");
435 return err;
436 }
437
438 #if defined(CONFIG_BT_AVRCP_TARGET)
439 bt_sdp_register_service(&avrcp_tg_rec);
440 #endif /* CONFIG_BT_AVRCP_CONTROLLER */
441
442 #if defined(CONFIG_BT_AVRCP_CONTROLLER)
443 bt_sdp_register_service(&avrcp_ct_rec);
444 #endif /* CONFIG_BT_AVRCP_CONTROLLER */
445
446 LOG_DBG("AVRCP Initialized successfully.");
447 return 0;
448 }
449
bt_avrcp_connect(struct bt_conn * conn)450 struct bt_avrcp *bt_avrcp_connect(struct bt_conn *conn)
451 {
452 struct bt_avrcp *avrcp;
453 int err;
454
455 avrcp = get_new_connection(conn);
456 if (!avrcp) {
457 LOG_ERR("Cannot allocate memory");
458 return NULL;
459 }
460
461 avrcp->session.ops = &avctp_ops;
462 err = bt_avctp_connect(conn, &(avrcp->session));
463 if (err < 0) {
464 /* If error occurs, undo the saving and return the error */
465 memset(avrcp, 0, sizeof(struct bt_avrcp));
466 LOG_DBG("AVCTP Connect failed");
467 return NULL;
468 }
469
470 LOG_DBG("Connection request sent");
471 return avrcp;
472 }
473
bt_avrcp_disconnect(struct bt_avrcp * avrcp)474 int bt_avrcp_disconnect(struct bt_avrcp *avrcp)
475 {
476 int err;
477
478 err = bt_avctp_disconnect(&(avrcp->session));
479 if (err < 0) {
480 LOG_DBG("AVCTP Disconnect failed");
481 return err;
482 }
483
484 return err;
485 }
486
avrcp_create_pdu(struct bt_avrcp * avrcp,bt_avctp_cr_t cr)487 static struct net_buf *avrcp_create_pdu(struct bt_avrcp *avrcp, bt_avctp_cr_t cr)
488 {
489 struct net_buf *buf;
490
491 buf = bt_avctp_create_pdu(&(avrcp->session), cr, BT_AVCTP_PKT_TYPE_SINGLE,
492 BT_AVCTP_IPID_NONE, &avrcp->local_tid,
493 sys_cpu_to_be16(BT_SDP_AV_REMOTE_SVCLASS));
494
495 return buf;
496 }
497
avrcp_create_unit_pdu(struct bt_avrcp * avrcp,bt_avctp_cr_t cr)498 static struct net_buf *avrcp_create_unit_pdu(struct bt_avrcp *avrcp, bt_avctp_cr_t cr)
499 {
500 struct net_buf *buf;
501 struct bt_avrcp_frame *cmd;
502
503 buf = avrcp_create_pdu(avrcp, cr);
504 if (!buf) {
505 return NULL;
506 }
507
508 cmd = net_buf_add(buf, sizeof(*cmd));
509 memset(cmd, 0, sizeof(*cmd));
510 BT_AVRCP_HDR_SET_CTYPE_OR_RSP(&cmd->hdr, cr == BT_AVCTP_CMD ? BT_AVRCP_CTYPE_STATUS
511 : BT_AVRCP_RSP_STABLE);
512 BT_AVRCP_HDR_SET_SUBUNIT_ID(&cmd->hdr, BT_AVRCP_SUBUNIT_ID_IGNORE);
513 BT_AVRCP_HDR_SET_SUBUNIT_TYPE(&cmd->hdr, BT_AVRCP_SUBUNIT_TYPE_UNIT);
514 cmd->hdr.opcode = BT_AVRCP_OPC_UNIT_INFO;
515
516 return buf;
517 }
518
avrcp_create_subunit_pdu(struct bt_avrcp * avrcp,bt_avctp_cr_t cr)519 static struct net_buf *avrcp_create_subunit_pdu(struct bt_avrcp *avrcp, bt_avctp_cr_t cr)
520 {
521 struct net_buf *buf;
522 struct bt_avrcp_frame *cmd;
523
524 buf = avrcp_create_pdu(avrcp, cr);
525 if (!buf) {
526 return NULL;
527 }
528
529 cmd = net_buf_add(buf, sizeof(*cmd));
530 memset(cmd, 0, sizeof(*cmd));
531 BT_AVRCP_HDR_SET_CTYPE_OR_RSP(&cmd->hdr, cr == BT_AVCTP_CMD ? BT_AVRCP_CTYPE_STATUS
532 : BT_AVRCP_RSP_STABLE);
533 BT_AVRCP_HDR_SET_SUBUNIT_ID(&cmd->hdr, BT_AVRCP_SUBUNIT_ID_IGNORE);
534 BT_AVRCP_HDR_SET_SUBUNIT_TYPE(&cmd->hdr, BT_AVRCP_SUBUNIT_TYPE_UNIT);
535 cmd->hdr.opcode = BT_AVRCP_OPC_SUBUNIT_INFO;
536
537 return buf;
538 }
539
avrcp_create_passthrough_pdu(struct bt_avrcp * avrcp,bt_avctp_cr_t cr,bt_avrcp_ctype_t ctype)540 static struct net_buf *avrcp_create_passthrough_pdu(struct bt_avrcp *avrcp, bt_avctp_cr_t cr,
541 bt_avrcp_ctype_t ctype)
542 {
543 struct net_buf *buf;
544 struct bt_avrcp_frame *cmd;
545
546 buf = avrcp_create_pdu(avrcp, cr);
547 if (!buf) {
548 return NULL;
549 }
550
551 cmd = net_buf_add(buf, sizeof(*cmd));
552 memset(cmd, 0, sizeof(*cmd));
553 BT_AVRCP_HDR_SET_CTYPE_OR_RSP(&cmd->hdr, ctype);
554 BT_AVRCP_HDR_SET_SUBUNIT_ID(&cmd->hdr, BT_AVRCP_SUBUNIT_ID_ZERO);
555 BT_AVRCP_HDR_SET_SUBUNIT_TYPE(&cmd->hdr, BT_AVRCP_SUBUNIT_TYPE_PANEL);
556 cmd->hdr.opcode = BT_AVRCP_OPC_PASS_THROUGH;
557
558 return buf;
559 }
560
avrcp_send(struct bt_avrcp * avrcp,struct net_buf * buf)561 static int avrcp_send(struct bt_avrcp *avrcp, struct net_buf *buf)
562 {
563 int err;
564 struct bt_avctp_header *avctp_hdr = (struct bt_avctp_header *)(buf->data);
565 struct bt_avrcp_header *avrcp_hdr =
566 (struct bt_avrcp_header *)(buf->data + sizeof(*avctp_hdr));
567 uint8_t tid = BT_AVCTP_HDR_GET_TRANSACTION_LABLE(avctp_hdr);
568 bt_avctp_cr_t cr = BT_AVCTP_HDR_GET_CR(avctp_hdr);
569 bt_avrcp_ctype_t ctype = BT_AVRCP_HDR_GET_CTYPE_OR_RSP(avrcp_hdr);
570 bt_avrcp_subunit_type_t subunit_type = BT_AVRCP_HDR_GET_SUBUNIT_TYPE(avrcp_hdr);
571
572 LOG_DBG("AVRCP send cr:0x%X, tid:0x%X, ctype: 0x%X, opc:0x%02X\n", cr, tid, ctype,
573 avrcp_hdr->opcode);
574 err = bt_avctp_send(&(avrcp->session), buf);
575 if (err < 0) {
576 net_buf_unref(buf);
577 LOG_ERR("AVCTP send fail, err = %d", err);
578 return err;
579 }
580
581 if (cr == BT_AVCTP_CMD && avrcp_hdr->opcode != BT_AVRCP_OPC_PASS_THROUGH) {
582 avrcp->req.tid = tid;
583 avrcp->req.subunit = subunit_type;
584 avrcp->req.opcode = avrcp_hdr->opcode;
585
586 k_work_reschedule(&avrcp->timeout_work, AVRCP_TIMEOUT);
587 }
588
589 return 0;
590 }
591
bt_avrcp_get_unit_info(struct bt_avrcp * avrcp)592 int bt_avrcp_get_unit_info(struct bt_avrcp *avrcp)
593 {
594 struct net_buf *buf;
595 uint8_t param[5];
596
597 buf = avrcp_create_unit_pdu(avrcp, BT_AVCTP_CMD);
598 if (!buf) {
599 return -ENOMEM;
600 }
601
602 memset(param, 0xFF, ARRAY_SIZE(param));
603 net_buf_add_mem(buf, param, sizeof(param));
604
605 return avrcp_send(avrcp, buf);
606 }
607
bt_avrcp_get_subunit_info(struct bt_avrcp * avrcp)608 int bt_avrcp_get_subunit_info(struct bt_avrcp *avrcp)
609 {
610 struct net_buf *buf;
611 uint8_t param[5];
612
613 buf = avrcp_create_subunit_pdu(avrcp, BT_AVCTP_CMD);
614 if (!buf) {
615 return -ENOMEM;
616 }
617
618 memset(param, 0xFF, ARRAY_SIZE(param));
619 param[0] = FIELD_PREP(GENMASK(6, 4), AVRCP_SUBUNIT_PAGE) |
620 FIELD_PREP(GENMASK(2, 0), AVRCP_SUBUNIT_EXTENSION_COED);
621 net_buf_add_mem(buf, param, sizeof(param));
622
623 return avrcp_send(avrcp, buf);
624 }
625
bt_avrcp_passthrough(struct bt_avrcp * avrcp,bt_avrcp_opid_t operation_id,bt_avrcp_button_state_t state,const uint8_t * payload,uint8_t len)626 int bt_avrcp_passthrough(struct bt_avrcp *avrcp, bt_avrcp_opid_t operation_id,
627 bt_avrcp_button_state_t state, const uint8_t *payload, uint8_t len)
628 {
629 struct net_buf *buf;
630 uint8_t param[2];
631
632 buf = avrcp_create_passthrough_pdu(avrcp, BT_AVCTP_CMD, BT_AVRCP_CTYPE_CONTROL);
633 if (!buf) {
634 return -ENOMEM;
635 }
636
637 param[0] = FIELD_PREP(GENMASK(7, 7), state) | FIELD_PREP(GENMASK(6, 0), operation_id);
638 param[1] = len;
639 net_buf_add_mem(buf, param, sizeof(param));
640 if (len) {
641 net_buf_add_mem(buf, payload, len);
642 }
643
644 return avrcp_send(avrcp, buf);
645 }
646
bt_avrcp_register_cb(const struct bt_avrcp_cb * cb)647 int bt_avrcp_register_cb(const struct bt_avrcp_cb *cb)
648 {
649 avrcp_cb = cb;
650 return 0;
651 }
652