1 /******************************************************************************
2 *
3 * Copyright 2003-2016 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #define LOG_TAG "avrcp"
20
21 #include <bluetooth/log.h>
22 #include <string.h>
23
24 #include <cstdint>
25
26 #include "avct_api.h"
27 #include "avrc_api.h"
28 #include "avrc_defs.h"
29 #include "avrc_int.h"
30 #include "internal_include/bt_target.h"
31 #include "osi/include/allocator.h"
32 #include "stack/avct/avct_defs.h"
33 #include "stack/include/bt_hdr.h"
34 #include "stack/include/bt_types.h"
35
36 using namespace bluetooth;
37
38 /*****************************************************************************
39 * Global data
40 ****************************************************************************/
41 #define AVRC_ITEM_PLAYER_IS_VALID(_p_player) \
42 ((_p_player)->name.p_str && ((_p_player)->major_type & AVRC_MJ_TYPE_INVALID) == 0 && \
43 ((_p_player)->sub_type & AVRC_SUB_TYPE_INVALID) == 0 && \
44 (((_p_player)->play_status <= AVRC_PLAYSTATE_REV_SEEK) || \
45 ((_p_player)->play_status == AVRC_PLAYSTATE_ERROR)))
46
47 /* 17 = item_type(1) + item len(2) + min item (14) */
48 #define AVRC_MIN_LEN_GET_FOLDER_ITEMS_RSP 17
49
50 /*******************************************************************************
51 *
52 * Function avrc_bld_get_capability_rsp
53 *
54 * Description This function builds the Get Capability response.
55 *
56 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
57 * Otherwise, the error code.
58 *
59 ******************************************************************************/
avrc_bld_get_capability_rsp(tAVRC_GET_CAPS_RSP * p_rsp,BT_HDR * p_pkt)60 static tAVRC_STS avrc_bld_get_capability_rsp(tAVRC_GET_CAPS_RSP* p_rsp, BT_HDR* p_pkt) {
61 uint8_t *p_data, *p_start, *p_len, *p_count;
62 uint16_t len = 0;
63 uint8_t xx;
64 uint32_t* p_company_id;
65 uint8_t* p_event_id;
66 tAVRC_STS status = AVRC_STS_NO_ERROR;
67
68 if (!(AVRC_IS_VALID_CAP_ID(p_rsp->capability_id))) {
69 log::error("bad parameter. p_rsp: {}", std::format_ptr(p_rsp));
70 status = AVRC_STS_BAD_PARAM;
71 return status;
72 }
73
74 log::verbose("");
75 /* get the existing length, if any, and also the num attributes */
76 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
77 p_data = p_len = p_start + 2; /* pdu + rsvd */
78
79 BE_STREAM_TO_UINT16(len, p_data);
80 UINT8_TO_BE_STREAM(p_data, p_rsp->capability_id);
81 p_count = p_data;
82
83 if (len == 0) {
84 *p_count = p_rsp->count;
85 p_data++;
86 len = 2; /* move past the capability_id and count */
87 } else {
88 p_data = p_start + p_pkt->len;
89 *p_count += p_rsp->count;
90 }
91
92 if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) {
93 p_company_id = p_rsp->param.company_id;
94 for (xx = 0; xx < p_rsp->count; xx++) {
95 UINT24_TO_BE_STREAM(p_data, p_company_id[xx]);
96 }
97 len += p_rsp->count * 3;
98 } else {
99 p_event_id = p_rsp->param.event_id;
100 *p_count = 0;
101 for (xx = 0; xx < p_rsp->count; xx++) {
102 if (AVRC_IS_VALID_EVENT_ID(p_event_id[xx])) {
103 (*p_count)++;
104 UINT8_TO_BE_STREAM(p_data, p_event_id[xx]);
105 }
106 }
107 len += (*p_count);
108 }
109 UINT16_TO_BE_STREAM(p_len, len);
110 p_pkt->len = (p_data - p_start);
111 status = AVRC_STS_NO_ERROR;
112
113 return status;
114 }
115
116 /*******************************************************************************
117 *
118 * Function avrc_bld_list_app_settings_attr_rsp
119 *
120 * Description This function builds the List Application Settings Attribute
121 * response.
122 *
123 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
124 * Otherwise, the error code.
125 *
126 ******************************************************************************/
avrc_bld_list_app_settings_attr_rsp(tAVRC_LIST_APP_ATTR_RSP * p_rsp,BT_HDR * p_pkt)127 static tAVRC_STS avrc_bld_list_app_settings_attr_rsp(tAVRC_LIST_APP_ATTR_RSP* p_rsp,
128 BT_HDR* p_pkt) {
129 uint8_t *p_data, *p_start, *p_len, *p_num;
130 uint16_t len = 0;
131 uint8_t xx;
132
133 log::verbose("");
134 /* get the existing length, if any, and also the num attributes */
135 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
136 p_data = p_len = p_start + 2; /* pdu + rsvd */
137
138 BE_STREAM_TO_UINT16(len, p_data);
139 p_num = p_data;
140 if (len == 0) {
141 /* first time initialize the attribute count */
142 *p_num = 0;
143 p_data++;
144 } else {
145 p_data = p_start + p_pkt->len;
146 }
147
148 for (xx = 0; xx < p_rsp->num_attr; xx++) {
149 if (AVRC_IsValidPlayerAttr(p_rsp->attrs[xx])) {
150 (*p_num)++;
151 UINT8_TO_BE_STREAM(p_data, p_rsp->attrs[xx]);
152 }
153 }
154
155 len = *p_num + 1;
156 UINT16_TO_BE_STREAM(p_len, len);
157 p_pkt->len = (p_data - p_start);
158
159 return AVRC_STS_NO_ERROR;
160 }
161
162 /*******************************************************************************
163 *
164 * Function avrc_bld_list_app_settings_values_rsp
165 *
166 * Description This function builds the List Application Setting Values
167 * response.
168 *
169 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
170 * Otherwise, the error code.
171 *
172 ******************************************************************************/
avrc_bld_list_app_settings_values_rsp(tAVRC_LIST_APP_VALUES_RSP * p_rsp,BT_HDR * p_pkt)173 static tAVRC_STS avrc_bld_list_app_settings_values_rsp(tAVRC_LIST_APP_VALUES_RSP* p_rsp,
174 BT_HDR* p_pkt) {
175 uint8_t *p_data, *p_start, *p_len, *p_num;
176 uint8_t xx;
177 uint16_t len;
178
179 log::verbose("");
180
181 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
182 p_data = p_len = p_start + 2; /* pdu + rsvd */
183
184 /* get the existing length, if any, and also the num attributes */
185 BE_STREAM_TO_UINT16(len, p_data);
186 p_num = p_data;
187 /* first time initialize the attribute count */
188 if (len == 0) {
189 *p_num = p_rsp->num_val;
190 p_data++;
191 } else {
192 p_data = p_start + p_pkt->len;
193 *p_num += p_rsp->num_val;
194 }
195
196 for (xx = 0; xx < p_rsp->num_val; xx++) {
197 UINT8_TO_BE_STREAM(p_data, p_rsp->vals[xx]);
198 }
199
200 len = *p_num + 1;
201 UINT16_TO_BE_STREAM(p_len, len);
202 p_pkt->len = (p_data - p_start);
203 return AVRC_STS_NO_ERROR;
204 }
205
206 /*******************************************************************************
207 *
208 * Function avrc_bld_get_cur_app_setting_value_rsp
209 *
210 * Description This function builds the Get Current Application Setting
211 * Value response.
212 *
213 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
214 * Otherwise, the error code.
215 *
216 ******************************************************************************/
avrc_bld_get_cur_app_setting_value_rsp(tAVRC_GET_CUR_APP_VALUE_RSP * p_rsp,BT_HDR * p_pkt)217 static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp(tAVRC_GET_CUR_APP_VALUE_RSP* p_rsp,
218 BT_HDR* p_pkt) {
219 uint8_t *p_data, *p_start, *p_len, *p_count;
220 uint16_t len;
221 uint8_t xx;
222
223 if (!p_rsp->p_vals) {
224 log::error("NULL parameter");
225 return AVRC_STS_BAD_PARAM;
226 }
227
228 log::verbose("");
229 /* get the existing length, if any, and also the num attributes */
230 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
231 p_data = p_len = p_start + 2; /* pdu + rsvd */
232
233 BE_STREAM_TO_UINT16(len, p_data);
234 p_count = p_data;
235 if (len == 0) {
236 /* first time initialize the attribute count */
237 *p_count = 0;
238 p_data++;
239 } else {
240 p_data = p_start + p_pkt->len;
241 }
242
243 for (xx = 0; xx < p_rsp->num_val; xx++) {
244 if (avrc_is_valid_player_attrib_value(p_rsp->p_vals[xx].attr_id, p_rsp->p_vals[xx].attr_val)) {
245 (*p_count)++;
246 UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_id);
247 UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_val);
248 }
249 }
250 len = ((*p_count) << 1) + 1;
251 UINT16_TO_BE_STREAM(p_len, len);
252 p_pkt->len = (p_data - p_start);
253
254 return AVRC_STS_NO_ERROR;
255 }
256
257 /*******************************************************************************
258 *
259 * Function avrc_bld_set_app_setting_value_rsp
260 *
261 * Description This function builds the Set Application Setting Value
262 * response.
263 *
264 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
265 * Otherwise, the error code.
266 *
267 ******************************************************************************/
avrc_bld_set_app_setting_value_rsp(tAVRC_RSP *,BT_HDR *)268 static tAVRC_STS avrc_bld_set_app_setting_value_rsp(tAVRC_RSP* /* p_rsp */, BT_HDR* /* p_pkt */) {
269 /* nothing to be added. */
270 log::verbose("");
271 return AVRC_STS_NO_ERROR;
272 }
273
274 /*******************************************************************************
275 *
276 * Function avrc_bld_app_setting_text_rsp
277 *
278 * Description This function builds the Get Application Settings Attribute
279 * Text or Get Application Settings Value Text response.
280 *
281 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
282 * Otherwise, the error code.
283 *
284 ******************************************************************************/
avrc_bld_app_setting_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp,BT_HDR * p_pkt)285 static tAVRC_STS avrc_bld_app_setting_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp, BT_HDR* p_pkt) {
286 uint8_t *p_data, *p_start, *p_len, *p_count;
287 uint16_t len, len_left;
288 uint8_t xx;
289 tAVRC_STS sts = AVRC_STS_NO_ERROR;
290 uint8_t num_added = 0;
291
292 if (!p_rsp->p_attrs) {
293 log::error("NULL parameter");
294 return AVRC_STS_BAD_PARAM;
295 }
296 /* get the existing length, if any, and also the num attributes */
297 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
298 p_data = p_len = p_start + 2; /* pdu + rsvd */
299
300 /*
301 * NOTE: The buffer is allocated within avrc_bld_init_rsp_buffer(), and is
302 * always of size BT_DEFAULT_BUFFER_SIZE.
303 */
304 len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset - p_pkt->len;
305
306 BE_STREAM_TO_UINT16(len, p_data);
307 p_count = p_data;
308
309 if (len == 0) {
310 *p_count = 0;
311 p_data++;
312 } else {
313 p_data = p_start + p_pkt->len;
314 }
315
316 for (xx = 0; xx < p_rsp->num_attr; xx++) {
317 if (len_left < (p_rsp->p_attrs[xx].str_len + 4)) {
318 log::error("out of room (str_len:{}, left:{})", p_rsp->p_attrs[xx].str_len, len_left);
319 p_rsp->num_attr = num_added;
320 sts = AVRC_STS_INTERNAL_ERR;
321 break;
322 }
323 if (!p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str) {
324 log::error("NULL attr text[{}]", xx);
325 continue;
326 }
327 UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
328 UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id);
329 UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len);
330 ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, p_rsp->p_attrs[xx].str_len);
331 (*p_count)++;
332 num_added++;
333 }
334 len = p_data - p_count;
335 UINT16_TO_BE_STREAM(p_len, len);
336 p_pkt->len = (p_data - p_start);
337
338 return sts;
339 }
340
341 /*******************************************************************************
342 *
343 * Function avrc_bld_get_app_setting_attr_text_rsp
344 *
345 * Description This function builds the Get Application Setting Attribute
346 * Text response.
347 *
348 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
349 * Otherwise, the error code.
350 *
351 ******************************************************************************/
avrc_bld_get_app_setting_attr_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp,BT_HDR * p_pkt)352 static tAVRC_STS avrc_bld_get_app_setting_attr_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp,
353 BT_HDR* p_pkt) {
354 log::verbose("");
355 return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
356 }
357
358 /*******************************************************************************
359 *
360 * Function avrc_bld_get_app_setting_value_text_rsp
361 *
362 * Description This function builds the Get Application Setting Value Text
363 * response.
364 *
365 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
366 * Otherwise, the error code.
367 *
368 ******************************************************************************/
avrc_bld_get_app_setting_value_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp,BT_HDR * p_pkt)369 static tAVRC_STS avrc_bld_get_app_setting_value_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp,
370 BT_HDR* p_pkt) {
371 log::verbose("");
372 return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
373 }
374
375 /*******************************************************************************
376 *
377 * Function avrc_bld_inform_charset_rsp
378 *
379 * Description This function builds the Inform Displayable Character Set
380 * response.
381 *
382 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
383 * Otherwise, the error code.
384 *
385 ******************************************************************************/
avrc_bld_inform_charset_rsp(tAVRC_RSP *,BT_HDR *)386 static tAVRC_STS avrc_bld_inform_charset_rsp(tAVRC_RSP* /* p_rsp */, BT_HDR* /* p_pkt */) {
387 /* nothing to be added. */
388 log::verbose("");
389 return AVRC_STS_NO_ERROR;
390 }
391
392 /*******************************************************************************
393 *
394 * Function avrc_bld_inform_battery_status_rsp
395 *
396 * Description This function builds the Inform Battery Status
397 * response.
398 *
399 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
400 * Otherwise, the error code.
401 *
402 ******************************************************************************/
avrc_bld_inform_battery_status_rsp(tAVRC_RSP *,BT_HDR *)403 static tAVRC_STS avrc_bld_inform_battery_status_rsp(tAVRC_RSP* /* p_rsp */, BT_HDR* /* p_pkt */) {
404 /* nothing to be added. */
405 log::verbose("");
406 return AVRC_STS_NO_ERROR;
407 }
408
avrc_build_attribute_entries(int num_attrs,tAVRC_ATTR_ENTRY * p_attrs,int remaining_buffer_capacity,uint8_t ** pp_data,uint8_t * p_attribute_count)409 static void avrc_build_attribute_entries(int num_attrs, tAVRC_ATTR_ENTRY* p_attrs,
410 int remaining_buffer_capacity, uint8_t** pp_data,
411 uint8_t* p_attribute_count) {
412 log::verbose("num_attrs: {}, remaining_buffer_capacity: {}", num_attrs,
413 remaining_buffer_capacity);
414 uint8_t* p_data = *pp_data;
415 /* Fill in the Attribute ID, Character Set, Length and Values */
416 for (int index = 0; index < num_attrs; index++) {
417 log::verbose("attr id[{}]: {}", index, p_attrs[index].attr_id);
418 log::assert_that(AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attrs[index].attr_id),
419 "assert failed: AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attrs[index].attr_id)");
420 if (!p_attrs[index].name.p_str) {
421 p_attrs[index].name.str_len = 0;
422 }
423 /* 8 is the size of attr_id, char set and str_len */
424 remaining_buffer_capacity -= 8;
425 if (remaining_buffer_capacity < 0) {
426 log::warn("not enough buffer space for attr_id[{}]: {}, skipping {} attributes", index,
427 p_attrs[index].attr_id, num_attrs - index);
428 break;
429 }
430 if (remaining_buffer_capacity < p_attrs[index].name.str_len) {
431 log::warn("not enough buffer space for attr_id[{}]: {}, truncating attribute", index,
432 p_attrs[index].attr_id);
433 p_attrs[index].name.str_len = remaining_buffer_capacity;
434 remaining_buffer_capacity = 0;
435 }
436 remaining_buffer_capacity -= p_attrs[index].name.str_len;
437 UINT32_TO_BE_STREAM(p_data, p_attrs[index].attr_id);
438 UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.charset_id);
439 UINT16_TO_BE_STREAM(p_data, p_attrs[index].name.str_len);
440 ARRAY_TO_BE_STREAM(p_data, p_attrs[index].name.p_str, p_attrs[index].name.str_len);
441 (*p_attribute_count)++;
442 }
443 *pp_data = p_data;
444 log::verbose("filled attributes, remaining_buffer_capacity: {}", remaining_buffer_capacity);
445 }
446
447 /*******************************************************************************
448 *
449 * Function avrc_bld_get_elem_attrs_rsp
450 *
451 * Description This function builds the Get Element Attributes
452 * response.
453 *
454 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
455 * Otherwise, the error code.
456 *
457 ******************************************************************************/
avrc_bld_get_elem_attrs_rsp(tAVRC_GET_ATTRS_RSP * p_rsp,BT_HDR * p_pkt)458 static tAVRC_STS avrc_bld_get_elem_attrs_rsp(tAVRC_GET_ATTRS_RSP* p_rsp, BT_HDR* p_pkt) {
459 log::verbose("");
460 if (!p_rsp->p_attrs) {
461 log::error("NULL p_attrs");
462 return AVRC_STS_BAD_PARAM;
463 }
464 /* Figure out how much we have left in current buffer */
465 int remaining_buffer_capacity = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset;
466 if (remaining_buffer_capacity < 5) {
467 log::error("{} not enough buffer for packet header", remaining_buffer_capacity);
468 return AVRC_STS_INTERNAL_ERR;
469 }
470 /* Get to the beginning of PDU */
471 uint8_t* p_pdu_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
472 /* Skip PDU ID and Reserved byte to get pointer to Parameter Length */
473 uint8_t *p_data, *p_parameter_len;
474 p_data = p_parameter_len = p_pdu_start + 2;
475 /* Parse parameter length */
476 uint16_t parameter_len;
477 BE_STREAM_TO_UINT16(parameter_len, p_data);
478 /* Get pointer to Attribute Count */
479 uint8_t* p_attribute_count = p_data;
480 /* Initialize field values when Parameter Length is 0 */
481 if (parameter_len == 0) {
482 *p_attribute_count = 0;
483 p_data++;
484 } else {
485 // TODO: Why do we need this case?
486 p_data = p_pdu_start + p_pkt->len;
487 }
488 remaining_buffer_capacity -= p_data - p_pdu_start;
489 ;
490 if (remaining_buffer_capacity < 0) {
491 log::error("not enough buffer capacity for response");
492 return AVRC_STS_BAD_PARAM;
493 }
494 /* Fill in the Attribute ID, Character Set, Length and Values */
495 avrc_build_attribute_entries(p_rsp->num_attrs, p_rsp->p_attrs, remaining_buffer_capacity, &p_data,
496 p_attribute_count);
497 parameter_len = p_data - p_attribute_count;
498 UINT16_TO_BE_STREAM(p_parameter_len, parameter_len);
499 p_pkt->len = (p_data - p_pdu_start);
500 return AVRC_STS_NO_ERROR;
501 }
502
503 /*******************************************************************************
504 *
505 * Function avrc_bld_get_play_status_rsp
506 *
507 * Description This function builds the Get Play Status
508 * response.
509 *
510 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
511 * Otherwise, the error code.
512 *
513 ******************************************************************************/
avrc_bld_get_play_status_rsp(tAVRC_GET_PLAY_STATUS_RSP * p_rsp,BT_HDR * p_pkt)514 static tAVRC_STS avrc_bld_get_play_status_rsp(tAVRC_GET_PLAY_STATUS_RSP* p_rsp, BT_HDR* p_pkt) {
515 uint8_t *p_data, *p_start;
516
517 log::verbose("");
518 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
519 p_data = p_start + 2;
520
521 /* add fixed length - song len(4) + song position(4) + status(1) */
522 UINT16_TO_BE_STREAM(p_data, 9);
523 UINT32_TO_BE_STREAM(p_data, p_rsp->song_len);
524 UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos);
525 UINT8_TO_BE_STREAM(p_data, p_rsp->play_status);
526 p_pkt->len = (p_data - p_start);
527
528 return AVRC_STS_NO_ERROR;
529 }
530
531 /*******************************************************************************
532 *
533 * Function avrc_bld_notify_rsp
534 *
535 * Description This function builds the Notification response.
536 *
537 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
538 * Otherwise, the error code.
539 *
540 ******************************************************************************/
avrc_bld_notify_rsp(tAVRC_REG_NOTIF_RSP * p_rsp,BT_HDR * p_pkt)541 static tAVRC_STS avrc_bld_notify_rsp(tAVRC_REG_NOTIF_RSP* p_rsp, BT_HDR* p_pkt) {
542 uint8_t *p_data, *p_start;
543 uint8_t* p_len;
544 uint16_t len = 0;
545 uint8_t xx;
546 tAVRC_STS status = AVRC_STS_NO_ERROR;
547
548 log::verbose("event_id {}", p_rsp->event_id);
549
550 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
551 p_data = p_len = p_start + 2; /* pdu + rsvd */
552 p_data += 2;
553
554 UINT8_TO_BE_STREAM(p_data, p_rsp->event_id);
555 switch (p_rsp->event_id) {
556 case AVRC_EVT_PLAY_STATUS_CHANGE: /* 0x01 */
557 /* p_rsp->param.play_status >= AVRC_PLAYSTATE_STOPPED is always true */
558 if ((p_rsp->param.play_status <= AVRC_PLAYSTATE_REV_SEEK) ||
559 (p_rsp->param.play_status == AVRC_PLAYSTATE_ERROR)) {
560 UINT8_TO_BE_STREAM(p_data, p_rsp->param.play_status);
561 len = 2;
562 } else {
563 log::error("bad play state");
564 status = AVRC_STS_BAD_PARAM;
565 }
566 break;
567
568 case AVRC_EVT_TRACK_CHANGE: /* 0x02 */
569 ARRAY_TO_BE_STREAM(p_data, p_rsp->param.track, AVRC_UID_SIZE);
570 len = (uint8_t)(AVRC_UID_SIZE + 1);
571 break;
572
573 case AVRC_EVT_TRACK_REACHED_END: /* 0x03 */
574 case AVRC_EVT_TRACK_REACHED_START: /* 0x04 */
575 case AVRC_EVT_NOW_PLAYING_CHANGE: /* 0x09 */
576 case AVRC_EVT_AVAL_PLAYERS_CHANGE: /* 0x0a */
577 len = 1;
578 break;
579
580 case AVRC_EVT_PLAY_POS_CHANGED: /* 0x05 */
581 UINT32_TO_BE_STREAM(p_data, p_rsp->param.play_pos);
582 len = 5;
583 break;
584
585 case AVRC_EVT_BATTERY_STATUS_CHANGE: /* 0x06 */
586 if (AVRC_IS_VALID_BATTERY_STATUS(p_rsp->param.battery_status)) {
587 UINT8_TO_BE_STREAM(p_data, p_rsp->param.battery_status);
588 len = 2;
589 } else {
590 log::error("bad battery status");
591 status = AVRC_STS_BAD_PARAM;
592 }
593 break;
594
595 case AVRC_EVT_SYSTEM_STATUS_CHANGE: /* 0x07 */
596 if (AVRC_IS_VALID_SYSTEM_STATUS(p_rsp->param.system_status)) {
597 UINT8_TO_BE_STREAM(p_data, p_rsp->param.system_status);
598 len = 2;
599 } else {
600 log::error("bad system status");
601 status = AVRC_STS_BAD_PARAM;
602 }
603 break;
604
605 case AVRC_EVT_APP_SETTING_CHANGE: /* 0x08 */
606 if (p_rsp->param.player_setting.num_attr > AVRC_MAX_APP_SETTINGS) {
607 p_rsp->param.player_setting.num_attr = AVRC_MAX_APP_SETTINGS;
608 }
609
610 if (p_rsp->param.player_setting.num_attr > 0) {
611 UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.num_attr);
612 len = 2;
613 for (xx = 0; xx < p_rsp->param.player_setting.num_attr; xx++) {
614 if (avrc_is_valid_player_attrib_value(p_rsp->param.player_setting.attr_id[xx],
615 p_rsp->param.player_setting.attr_value[xx])) {
616 UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_id[xx]);
617 UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_value[xx]);
618 } else {
619 log::error("bad player app seeting attribute or value");
620 status = AVRC_STS_BAD_PARAM;
621 break;
622 }
623 len += 2;
624 }
625 } else {
626 status = AVRC_STS_BAD_PARAM;
627 }
628 break;
629
630 case AVRC_EVT_VOLUME_CHANGE: /* 0x0d */
631 len = 2;
632 UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_rsp->param.volume));
633 break;
634
635 case AVRC_EVT_ADDR_PLAYER_CHANGE: /* 0x0b */
636 UINT16_TO_BE_STREAM(p_data, p_rsp->param.addr_player.player_id);
637 UINT16_TO_BE_STREAM(p_data, p_rsp->param.addr_player.uid_counter);
638 len = 5;
639 break;
640
641 case AVRC_EVT_UIDS_CHANGE: /* 0x0c */
642 UINT16_TO_BE_STREAM(p_data, p_rsp->param.uid_counter); /* uid counter */
643 len = 3;
644 break;
645
646 default:
647 status = AVRC_STS_BAD_PARAM;
648 log::error("unknown event_id");
649 }
650
651 UINT16_TO_BE_STREAM(p_len, len);
652 p_pkt->len = (p_data - p_start);
653
654 return status;
655 }
656
657 /*******************************************************************************
658 *
659 * Function avrc_bld_next_rsp
660 *
661 * Description This function builds the Request Continue or Abort
662 * response.
663 *
664 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
665 * Otherwise, the error code.
666 *
667 ******************************************************************************/
avrc_bld_next_rsp(tAVRC_NEXT_RSP * p_rsp,BT_HDR * p_pkt)668 static tAVRC_STS avrc_bld_next_rsp(tAVRC_NEXT_RSP* p_rsp, BT_HDR* p_pkt) {
669 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
670 uint8_t* p_data = (p_start + 2); /* Skip the pdu and reserved bits */
671
672 UINT16_TO_BE_STREAM(p_data, 0x0001); /* only one attribute to be sent */
673 UINT8_TO_BE_STREAM(p_data, p_rsp->target_pdu);
674
675 log::verbose("target_pdu: 0x{:02x}", p_rsp->target_pdu);
676 return AVRC_STS_NO_ERROR;
677 }
678
679 /*****************************************************************************
680 *
681 * Function avrc_bld_set_absolute_volume_rsp
682 *
683 * Description This function builds the set absolute volume response
684 *
685 * Returns AVRC_STS_NO_ERROR, if the response is build successfully
686 *
687 *****************************************************************************/
avrc_bld_set_absolute_volume_rsp(uint8_t abs_vol,BT_HDR * p_pkt)688 static tAVRC_STS avrc_bld_set_absolute_volume_rsp(uint8_t abs_vol, BT_HDR* p_pkt) {
689 log::verbose("");
690 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
691 /* To calculate length */
692 uint8_t* p_data = p_start + 2;
693 /* add fixed length status(1) */
694 UINT16_TO_BE_STREAM(p_data, 1);
695 UINT8_TO_BE_STREAM(p_data, abs_vol);
696 p_pkt->len = (p_data - p_start);
697 return AVRC_STS_NO_ERROR;
698 }
699
700 /*******************************************************************************
701 *
702 * Function avrc_bld_group_navigation_rsp
703 *
704 * Description This function builds the Group Navigation
705 * response.
706 *
707 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
708 * Otherwise, the error code.
709 *
710 ******************************************************************************/
avrc_bld_group_navigation_rsp(uint16_t navi_id,BT_HDR * p_pkt)711 static tAVRC_STS avrc_bld_group_navigation_rsp(uint16_t navi_id, BT_HDR* p_pkt) {
712 if (!AVRC_IS_VALID_GROUP(navi_id)) {
713 log::error("bad navigation op id: {}", navi_id);
714 return AVRC_STS_BAD_PARAM;
715 }
716 log::verbose("");
717 uint8_t* p_data = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
718 UINT16_TO_BE_STREAM(p_data, navi_id);
719 p_pkt->len = 2;
720 return AVRC_STS_NO_ERROR;
721 }
722
723 /*******************************************************************************
724 *
725 * Function avrc_bld_rejected_rsp
726 *
727 * Description This function builds the General Response response.
728 *
729 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
730 *
731 ******************************************************************************/
avrc_bld_rejected_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)732 static tAVRC_STS avrc_bld_rejected_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) {
733 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
734 uint8_t* p_data;
735 uint8_t opcode = p_rsp->opcode;
736
737 log::verbose("status={}, pdu:x{:x}, opcode={:x}", p_rsp->status, p_rsp->pdu, opcode);
738
739 if (opcode == AVRC_OP_BROWSE) {
740 p_data = p_start + 1;
741 if ((AVRC_PDU_INVALID == *p_start) || (avrc_opcode_from_pdu(*p_start) != AVRC_OP_BROWSE)) {
742 /* if invalid or the given opcode is not recognized as a browsing command
743 * opcode, */
744 /* use general reject command */
745 *p_start = AVRC_PDU_GENERAL_REJECT;
746 }
747 } else {
748 p_data = p_start + 2;
749 }
750 log::verbose("pdu:x{:x}, Opcode:{:x}", *p_start, opcode);
751 UINT16_TO_BE_STREAM(p_data, 1);
752 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
753 p_pkt->len = p_data - p_start;
754 return AVRC_STS_NO_ERROR;
755 }
756
757 /*****************************************************************************
758 * the following commands are introduced in AVRCP 1.4
759 ****************************************************************************/
760
761 /*******************************************************************************
762 *
763 * Function avrc_bld_ctrl_status_rsp
764 *
765 * Description This function builds the responses with a uint8_t parameter.
766 *
767 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
768 * Otherwise, the error code.
769 *
770 ******************************************************************************/
avrc_bld_ctrl_status_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)771 static tAVRC_STS avrc_bld_ctrl_status_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) {
772 uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
773 log::verbose("pdu:x{:x}", *p_start);
774
775 /* To calculate length */
776 uint8_t* p_data = p_start + 2; /* pdu + rsvd */
777
778 /* add fixed length - status(1) */
779 UINT16_TO_BE_STREAM(p_data, 1);
780 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
781 p_pkt->len = (p_data - p_start);
782 return AVRC_STS_NO_ERROR;
783 }
784
785 /*******************************************************************************
786 *
787 * Function avrc_bld_set_addr_player_rsp
788 *
789 * Description This function builds the Set Addresses Player response.
790 *
791 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
792 * Otherwise, the error code.
793 *
794 ******************************************************************************/
avrc_bld_set_addr_player_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)795 static tAVRC_STS avrc_bld_set_addr_player_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) {
796 log::verbose("");
797 return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt);
798 }
799
800 /*******************************************************************************
801 *
802 * Function avrc_bld_set_browsed_player_rsp
803 *
804 * Description This function builds the Set Browsed Player response.
805 *
806 * This message goes through the Browsing channel
807 *
808 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
809 * Otherwise, the error code.
810 *
811 ******************************************************************************/
avrc_bld_set_browsed_player_rsp(tAVRC_SET_BR_PLAYER_RSP * p_rsp,BT_HDR * p_pkt)812 static tAVRC_STS avrc_bld_set_browsed_player_rsp(tAVRC_SET_BR_PLAYER_RSP* p_rsp, BT_HDR* p_pkt) {
813 uint8_t *p_data, *p_start;
814 uint8_t* p_len;
815 uint16_t len;
816 tAVRC_NAME* p_folders = p_rsp->p_folders;
817 uint16_t len_left;
818 uint8_t* p_folder_depth;
819 uint16_t mtu;
820
821 /* make sure the given buffer can accomodate this response */
822 len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE;
823 p_data = (uint8_t*)(p_pkt + 1);
824 BE_STREAM_TO_UINT16(mtu, p_data);
825 if (len_left > mtu) {
826 len_left = mtu;
827 }
828 len_left = len_left - p_pkt->offset - p_pkt->len;
829 log::verbose("len_left:{}, mtu:{}", len_left, mtu);
830
831 /* get the existing length, if any, and also the num attributes */
832 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
833 p_data = p_len = p_start + 1; /* pdu */
834
835 /* the existing len */
836 BE_STREAM_TO_UINT16(len, p_data);
837 /* find the position to add the folder depth.
838 * 9 is sizeof (status + uid_counter + num_items + charset_id) */
839 p_folder_depth = p_data + 9;
840 if (len == 0) {
841 /* first time initialize the attribute count */
842 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
843 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
844 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
845 UINT16_TO_BE_STREAM(p_data, p_rsp->charset_id);
846 *p_folder_depth = 0;
847 p_data++;
848 len = 10;
849 /* assuming that we would never use a buffer that is too small for headers
850 */
851 len_left -= 12;
852 } else {
853 p_data = p_start + p_pkt->len;
854 }
855
856 for (uint8_t xx = 0; (xx < p_rsp->folder_depth) && (len_left > (p_folders[xx].str_len + 2));
857 xx++) {
858 (*p_folder_depth)++;
859 UINT16_TO_BE_STREAM(p_data, p_folders[xx].str_len);
860 ARRAY_TO_BE_STREAM(p_data, p_folders[xx].p_str, p_folders[xx].str_len);
861 len += (p_folders[xx].str_len + 2);
862 }
863 UINT16_TO_BE_STREAM(p_len, len);
864 p_pkt->len = (p_data - p_start);
865 return AVRC_STS_NO_ERROR;
866 }
867
868 /*******************************************************************************
869 *
870 * Function avrc_bld_get_folder_items_rsp
871 *
872 * Description This function builds the Get Folder Items response.
873 * The error code is returned in *p_status.
874 * AVRC_STS_INTERNAL_ERR means no buffers.
875 * Try again later or with smaller item_count
876 *
877 * This message goes through the Browsing channel
878 *
879 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
880 * AVRC_STS_INTERNAL_ERR, if the given buffer does not have
881 * enough room
882 * Otherwise, the error code.
883 *
884 ******************************************************************************/
avrc_bld_get_folder_items_rsp(tAVRC_GET_ITEMS_RSP * p_rsp,BT_HDR * p_pkt)885 static tAVRC_STS avrc_bld_get_folder_items_rsp(tAVRC_GET_ITEMS_RSP* p_rsp, BT_HDR* p_pkt) {
886 uint8_t *p_data, *p_start;
887 uint8_t *p_len, xx;
888 uint16_t len;
889 size_t item_len;
890 uint8_t *p_item_len, yy;
891 tAVRC_ITEM_PLAYER* p_player;
892 tAVRC_ITEM_FOLDER* p_folder;
893 tAVRC_ITEM_MEDIA* p_media;
894 tAVRC_ATTR_ENTRY* p_attr;
895 tAVRC_ITEM* p_item_list = p_rsp->p_item_list;
896 tAVRC_STS status = AVRC_STS_NO_ERROR;
897 uint16_t len_left;
898 uint8_t *p_num, *p;
899 uint8_t *p_item_start, *p_attr_count;
900 uint16_t item_count;
901 uint16_t mtu;
902 bool multi_items_add_fail = false;
903 log::verbose("");
904
905 /* make sure the given buffer can accomodate this response */
906 len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE;
907 p = (uint8_t*)(p_pkt + 1);
908 BE_STREAM_TO_UINT16(mtu, p);
909 if (len_left > mtu) {
910 len_left = mtu;
911 }
912
913 // according to spec
914 // Version 5.3 | Vol 3, Part A, Chapter 5
915 // MTU may be controlled by the peer
916 if (len_left < p_pkt->offset + p_pkt->len) {
917 log::error("memory not enough (len_left={})", len_left);
918 return AVRC_STS_INTERNAL_ERR;
919 }
920
921 len_left = len_left - p_pkt->offset - p_pkt->len;
922
923 /* get the existing length, if any, and also the num attributes */
924 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
925 p_data = p_len = p_start + 1; /* pdu */
926
927 /* the existing len */
928 BE_STREAM_TO_UINT16(len, p_data);
929 p_num = p_data + 3;
930 if (len == 0) {
931 /* first time initialize the attribute count */
932 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
933 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
934 item_count = 0;
935 p_data += 2;
936 len = 5;
937
938 if (len_left < 5) {
939 log::error("memory not enough (len_left={})", len_left);
940 return AVRC_STS_INTERNAL_ERR;
941 }
942
943 len_left -= 5;
944 } else {
945 p_data = p_start + p_pkt->len;
946 p = p_num;
947 BE_STREAM_TO_UINT16(item_count, p);
948 }
949 log::verbose("len:{}, len_left:{}, num:{}", len, len_left, item_count);
950
951 /* min len required = item_type(1) + item len(2) + min item (14) = 17 */
952 for (xx = 0; xx < p_rsp->item_count && len_left > AVRC_MIN_LEN_GET_FOLDER_ITEMS_RSP &&
953 !multi_items_add_fail;
954 xx++) {
955 p_item_start = p_data;
956 UINT8_TO_BE_STREAM(p_data, p_item_list[xx].item_type);
957 /* variable item length - save the location to add length */
958 p_item_len = p_data;
959 p_data += 2;
960 item_len = 0;
961 const uint16_t item_header_len = 3; /* item_type(1) + item len(2) */
962 uint16_t item_len_left = len_left - item_header_len;
963 switch (p_item_list[xx].item_type) {
964 case AVRC_ITEM_PLAYER:
965 /* min len required: 2 + 1 + 4 + 1 + 16 + 2 + 2 = 30 + str_len */
966 p_player = &p_item_list[xx].u.player;
967 item_len = AVRC_FEATURE_MASK_SIZE + p_player->name.str_len + 12;
968
969 if ((item_len_left < item_len) || !AVRC_ITEM_PLAYER_IS_VALID(p_player)) {
970 if (item_len_left < item_len && item_count > 0) {
971 multi_items_add_fail = true;
972 }
973 p_data = p_item_start;
974 break;
975 }
976 UINT16_TO_BE_STREAM(p_data, p_player->player_id);
977 UINT8_TO_BE_STREAM(p_data, p_player->major_type);
978 UINT32_TO_BE_STREAM(p_data, p_player->sub_type);
979 UINT8_TO_BE_STREAM(p_data, p_player->play_status);
980 ARRAY_TO_BE_STREAM(p_data, p_player->features, AVRC_FEATURE_MASK_SIZE);
981 UINT16_TO_BE_STREAM(p_data, p_player->name.charset_id);
982 UINT16_TO_BE_STREAM(p_data, p_player->name.str_len);
983 ARRAY_TO_BE_STREAM(p_data, p_player->name.p_str, p_player->name.str_len);
984 break;
985
986 case AVRC_ITEM_FOLDER:
987 /* min len required: 8 + 1 + 1 + 2 + 2 = 14 + str_len */
988 p_folder = &p_item_list[xx].u.folder;
989 item_len = AVRC_UID_SIZE + p_folder->name.str_len + 6;
990
991 if ((item_len_left < item_len) || !p_folder->name.p_str ||
992 p_folder->type > AVRC_FOLDER_TYPE_YEARS) {
993 if (item_len_left < item_len && item_count > 0) {
994 multi_items_add_fail = true;
995 }
996 p_data = p_item_start;
997 break;
998 }
999 ARRAY_TO_BE_STREAM(p_data, p_folder->uid, AVRC_UID_SIZE);
1000 UINT8_TO_BE_STREAM(p_data, p_folder->type);
1001 UINT8_TO_BE_STREAM(p_data, p_folder->playable);
1002 UINT16_TO_BE_STREAM(p_data, p_folder->name.charset_id);
1003 UINT16_TO_BE_STREAM(p_data, p_folder->name.str_len);
1004 ARRAY_TO_BE_STREAM(p_data, p_folder->name.p_str, p_folder->name.str_len);
1005 break;
1006
1007 case AVRC_ITEM_MEDIA:
1008 /* min len required: 8 + 1 + 2 + 2 + 1 = 14 + str_len */
1009 p_media = &p_item_list[xx].u.media;
1010 item_len = AVRC_UID_SIZE + p_media->name.str_len + 6;
1011
1012 if ((item_len_left < item_len) || !p_media->name.p_str ||
1013 p_media->type > AVRC_MEDIA_TYPE_VIDEO) {
1014 if (item_len_left < item_len && item_count > 0) {
1015 multi_items_add_fail = true;
1016 }
1017 p_data = p_item_start;
1018 break;
1019 }
1020 ARRAY_TO_BE_STREAM(p_data, p_media->uid, AVRC_UID_SIZE);
1021 UINT8_TO_BE_STREAM(p_data, p_media->type);
1022 UINT16_TO_BE_STREAM(p_data, p_media->name.charset_id);
1023 UINT16_TO_BE_STREAM(p_data, p_media->name.str_len);
1024 ARRAY_TO_BE_STREAM(p_data, p_media->name.p_str, p_media->name.str_len);
1025 p_attr_count = p_data++;
1026 *p_attr_count = 0;
1027 uint16_t attribute_len_left = item_len_left - item_len;
1028 p_attr = p_media->p_attr_list;
1029 for (yy = 0; yy < p_media->attr_count; yy++) {
1030 /* len required: 4 + 2 + 2 + str_len */
1031 const size_t attribute_len = p_attr[yy].name.str_len + 8;
1032 if (attribute_len_left < attribute_len || !p_attr[yy].name.p_str ||
1033 AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attr[yy].attr_id)) {
1034 if (attribute_len_left < attribute_len && item_count > 0) {
1035 multi_items_add_fail = true;
1036 p_data = p_item_start;
1037 break;
1038 }
1039 continue;
1040 }
1041 (*p_attr_count)++;
1042 UINT32_TO_BE_STREAM(p_data, p_attr[yy].attr_id);
1043 UINT16_TO_BE_STREAM(p_data, p_attr[yy].name.charset_id);
1044 UINT16_TO_BE_STREAM(p_data, p_attr[yy].name.str_len);
1045 ARRAY_TO_BE_STREAM(p_data, p_attr[yy].name.p_str, p_attr[yy].name.str_len);
1046 item_len += attribute_len;
1047 attribute_len_left -= attribute_len;
1048 }
1049 break;
1050 } /* switch item_type */
1051
1052 if (p_item_start != p_data) {
1053 /* successfully added the item */
1054 item_count++;
1055 /* fill in variable item length */
1056 UINT16_TO_BE_STREAM(p_item_len, item_len);
1057 len_left -= item_len + item_header_len;
1058 len += item_len + item_header_len;
1059 } else if (!multi_items_add_fail) {
1060 /* some item is not added properly - set an error status */
1061 if (item_len_left < item_len) {
1062 status = AVRC_STS_INTERNAL_ERR;
1063 } else {
1064 status = AVRC_STS_BAD_PARAM;
1065 }
1066 break;
1067 }
1068 log::verbose("len:{}, len_left:{}, num:{}, item_len:{}", len, len_left, item_count, item_len);
1069 } /* for item_count */
1070
1071 UINT16_TO_BE_STREAM(p_num, item_count);
1072 UINT16_TO_BE_STREAM(p_len, len);
1073 p_pkt->len = (p_data - p_start);
1074
1075 return status;
1076 }
1077
1078 /*******************************************************************************
1079 *
1080 * Function avrc_bld_change_path_rsp
1081 *
1082 * Description This function builds the Change Path response.
1083 *
1084 * This message goes through the Browsing channel
1085 *
1086 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1087 * Otherwise, the error code.
1088 *
1089 ******************************************************************************/
avrc_bld_change_path_rsp(tAVRC_CHG_PATH_RSP * p_rsp,BT_HDR * p_pkt)1090 static tAVRC_STS avrc_bld_change_path_rsp(tAVRC_CHG_PATH_RSP* p_rsp, BT_HDR* p_pkt) {
1091 uint8_t *p_data, *p_start;
1092
1093 /* get the existing length, if any, and also the num attributes */
1094 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1095 p_data = p_start + 1; /* pdu */
1096 /* add fixed length - status(1) + num_items(4) */
1097 UINT16_TO_BE_STREAM(p_data, 5);
1098 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
1099 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
1100 p_pkt->len = (p_data - p_start);
1101 return AVRC_STS_NO_ERROR;
1102 }
1103
1104 /*******************************************************************************
1105 *
1106 * Function avrc_bld_get_attrs_rsp
1107 *
1108 * Description This function builds the GetItemAttributes response,
1109 *
1110 * The Get Item Attributes message goes through the
1111 * Browsing channel (already specified in the |p_pkt|)
1112 *
1113 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1114 * AVRC_STS_INTERNAL_ERR, if the given buffer does not have
1115 * enough room
1116 * Otherwise, the error code.
1117 *
1118 ******************************************************************************/
avrc_bld_get_item_attrs_rsp(tAVRC_GET_ATTRS_RSP * p_rsp,BT_HDR * p_pkt)1119 static tAVRC_STS avrc_bld_get_item_attrs_rsp(tAVRC_GET_ATTRS_RSP* p_rsp, BT_HDR* p_pkt) {
1120 log::verbose("");
1121 if (!p_rsp->p_attrs) {
1122 log::error("NULL p_attrs");
1123 return AVRC_STS_BAD_PARAM;
1124 }
1125 /* Figure out how much we have left in current buffer */
1126 int remaining_buffer_capacity = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset;
1127 /* Get to the beginning of data section in buffer */
1128 uint8_t* p_data = (uint8_t*)(p_pkt + 1);
1129 /* Get the MTU size that is filled in earlier */
1130 uint16_t mtu;
1131 BE_STREAM_TO_UINT16(mtu, p_data);
1132 if (remaining_buffer_capacity > mtu) {
1133 remaining_buffer_capacity = mtu;
1134 }
1135 log::verbose("remaining_buffer_capacity:{}, mtu:{}", remaining_buffer_capacity, mtu);
1136 if (remaining_buffer_capacity < 5) {
1137 log::error("not enough space for packet header, remaining:{} < 5", remaining_buffer_capacity);
1138 return AVRC_STS_INTERNAL_ERR;
1139 }
1140 /* Get to the beginning of PDU */
1141 uint8_t* p_pdu_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1142 /* Skip PDU ID to get pointer to Parameter length */
1143 uint8_t* p_parameter_len;
1144 p_data = p_parameter_len = p_pdu_start + 1;
1145 /* Parse existing parameter length */
1146 uint16_t parameter_len;
1147 BE_STREAM_TO_UINT16(parameter_len, p_data);
1148 /* Skip one byte to Number of Attributes */
1149 uint8_t* p_status = p_data++;
1150 uint8_t* p_attribute_count = p_data++;
1151 if (parameter_len == 0) {
1152 /* First time, initialize the status byte */
1153 *p_status = p_rsp->status;
1154 if (p_rsp->status != AVRC_STS_NO_ERROR) {
1155 // TODO(siyuanh): This is a hack
1156 parameter_len = 1;
1157 UINT16_TO_BE_STREAM(p_parameter_len, parameter_len);
1158 p_pkt->len = p_status - p_pdu_start;
1159 return AVRC_STS_NO_ERROR;
1160 }
1161 *p_attribute_count = 0;
1162 } else {
1163 // TODO(siyuanh): Why do wee need this case?
1164 p_data = p_pdu_start + p_pkt->len;
1165 }
1166 remaining_buffer_capacity -= p_data - p_pdu_start;
1167 /* Fill in the Attribute ID, Character Set, Length and Values */
1168 avrc_build_attribute_entries(p_rsp->num_attrs, p_rsp->p_attrs, remaining_buffer_capacity, &p_data,
1169 p_attribute_count);
1170 parameter_len = p_data - p_status;
1171 UINT16_TO_BE_STREAM(p_parameter_len, parameter_len);
1172 p_pkt->len = p_data - p_pdu_start;
1173 return AVRC_STS_NO_ERROR;
1174 }
1175
1176 /*******************************************************************************
1177 *
1178 * Function avrc_bld_get_num_of_item_rsp
1179 *
1180 * Description This function builds the Get Total Number of Items response.
1181 *
1182 * This message goes through the Browsing channel
1183 *
1184 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1185 * AVRC_STS_INTERNAL_ERR, if the given buffer does not have
1186 * enough room
1187 * Otherwise, the error code.
1188 *
1189 ******************************************************************************/
avrc_bld_get_num_of_item_rsp(tAVRC_GET_NUM_OF_ITEMS_RSP * p_rsp,BT_HDR * p_pkt)1190 static tAVRC_STS avrc_bld_get_num_of_item_rsp(tAVRC_GET_NUM_OF_ITEMS_RSP* p_rsp, BT_HDR* p_pkt) {
1191 uint8_t *p_data, *p_start, *p_len;
1192
1193 log::verbose("");
1194 /* get the existing length, if any, and also the num attributes */
1195 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1196 p_data = p_len = p_start + 1; /* pdu */
1197
1198 if (p_rsp->status == AVRC_STS_NO_ERROR) {
1199 /* add fixed length - status(1) + uid_counter(2) + num_items(4) */
1200 UINT16_TO_BE_STREAM(p_data, 7);
1201 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
1202 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
1203 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
1204 p_pkt->len = (p_data - p_start);
1205 return AVRC_STS_NO_ERROR;
1206 } else {
1207 /* add fixed length - status(1) */
1208 UINT16_TO_BE_STREAM(p_data, 7);
1209 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
1210 p_pkt->len = (p_data - p_start);
1211 return p_rsp->status;
1212 }
1213 }
1214
1215 /*******************************************************************************
1216 *
1217 * Function avrc_bld_search_rsp
1218 *
1219 * Description This function builds the Search response.
1220 *
1221 * This message goes through the Browsing channel
1222 *
1223 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1224 * Otherwise, the error code.
1225 *
1226 ******************************************************************************/
avrc_bld_search_rsp(tAVRC_SEARCH_RSP * p_rsp,BT_HDR * p_pkt)1227 static tAVRC_STS avrc_bld_search_rsp(tAVRC_SEARCH_RSP* p_rsp, BT_HDR* p_pkt) {
1228 uint8_t *p_data, *p_start, *p_len;
1229
1230 log::verbose("");
1231 /* get the existing length, if any, and also the num attributes */
1232 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1233 p_data = p_len = p_start + 1; /* pdu */
1234
1235 /* add fixed length - status(1) + uid_counter(2) + num_items(4) */
1236 UINT16_TO_BE_STREAM(p_data, 7);
1237 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
1238 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
1239 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
1240 p_pkt->len = (p_data - p_start);
1241 return AVRC_STS_NO_ERROR;
1242 }
1243
1244 /*******************************************************************************
1245 *
1246 * Function avrc_bld_play_item_rsp
1247 *
1248 * Description This function builds the Play Item response.
1249 *
1250 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1251 * Otherwise, the error code.
1252 *
1253 ******************************************************************************/
avrc_bld_play_item_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)1254 static tAVRC_STS avrc_bld_play_item_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) {
1255 log::verbose("");
1256 return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt);
1257 }
1258
1259 /*******************************************************************************
1260 *
1261 * Function avrc_bld_add_to_now_playing_rsp
1262 *
1263 * Description This function builds the Add to Now Playing response.
1264 *
1265 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1266 * Otherwise, the error code.
1267 *
1268 ******************************************************************************/
avrc_bld_add_to_now_playing_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)1269 static tAVRC_STS avrc_bld_add_to_now_playing_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) {
1270 log::verbose("");
1271 return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt);
1272 }
1273
1274 /*******************************************************************************
1275 *
1276 * Function avrc_bld_init_rsp_buffer
1277 *
1278 * Description This function initializes the response buffer based on PDU
1279 *
1280 * Returns NULL, if no buffer or failure to build the message.
1281 * Otherwise, the buffer that contains the initialized message.
1282 *
1283 ******************************************************************************/
avrc_bld_init_rsp_buffer(tAVRC_RESPONSE * p_rsp)1284 static BT_HDR* avrc_bld_init_rsp_buffer(tAVRC_RESPONSE* p_rsp) {
1285 uint16_t offset = 0;
1286 uint16_t chnl = AVCT_DATA_CTRL;
1287 uint8_t opcode = avrc_opcode_from_pdu(p_rsp->pdu);
1288
1289 log::verbose("pdu={:x}, opcode={:x}/{:x}", p_rsp->pdu, opcode, p_rsp->rsp.opcode);
1290 if (opcode != p_rsp->rsp.opcode && p_rsp->rsp.status != AVRC_STS_NO_ERROR &&
1291 avrc_is_valid_opcode(p_rsp->rsp.opcode)) {
1292 opcode = p_rsp->rsp.opcode;
1293 log::verbose("opcode={:x}", opcode);
1294 }
1295
1296 switch (opcode) {
1297 case AVRC_OP_BROWSE:
1298 chnl = AVCT_DATA_BROWSE;
1299 offset = AVCT_BROWSE_OFFSET;
1300 break;
1301
1302 case AVRC_OP_PASS_THRU:
1303 offset = AVRC_MSG_PASS_THRU_OFFSET;
1304 break;
1305
1306 case AVRC_OP_VENDOR:
1307 offset = AVRC_MSG_VENDOR_OFFSET;
1308 break;
1309 }
1310
1311 /* allocate and initialize the buffer */
1312 BT_HDR* p_pkt = (BT_HDR*)osi_calloc(BT_DEFAULT_BUFFER_SIZE);
1313 uint8_t *p_data, *p_start;
1314
1315 p_pkt->layer_specific = chnl;
1316 p_pkt->event = opcode;
1317 p_pkt->offset = offset;
1318 p_data = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1319 p_start = p_data;
1320
1321 /* pass thru - group navigation - has a two byte op_id, so dont do it here */
1322 if (opcode != AVRC_OP_PASS_THRU) {
1323 *p_data++ = p_rsp->pdu;
1324 }
1325
1326 switch (opcode) {
1327 case AVRC_OP_VENDOR:
1328 /* reserved 0, packet_type 0 */
1329 UINT8_TO_BE_STREAM(p_data, 0);
1330 [[fallthrough]];
1331 case AVRC_OP_BROWSE:
1332 /* add fixed length - 0 */
1333 UINT16_TO_BE_STREAM(p_data, 0);
1334 break;
1335 }
1336
1337 p_pkt->len = (p_data - p_start);
1338 p_rsp->rsp.opcode = opcode;
1339
1340 return p_pkt;
1341 }
1342
1343 /*******************************************************************************
1344 *
1345 * Function AVRC_BldResponse
1346 *
1347 * Description This function builds the given AVRCP response to the given
1348 * buffer
1349 *
1350 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1351 * Otherwise, the error code.
1352 *
1353 ******************************************************************************/
AVRC_BldResponse(uint8_t handle,tAVRC_RESPONSE * p_rsp,BT_HDR ** pp_pkt)1354 tAVRC_STS AVRC_BldResponse(uint8_t handle, tAVRC_RESPONSE* p_rsp, BT_HDR** pp_pkt) {
1355 tAVRC_STS status = AVRC_STS_BAD_PARAM;
1356 BT_HDR* p_pkt;
1357 bool alloc = false;
1358 uint8_t* p;
1359 uint16_t peer_mtu;
1360
1361 if (!p_rsp || !pp_pkt) {
1362 log::verbose("Invalid parameters passed. p_rsp={}, pp_pkt={}", std::format_ptr(p_rsp),
1363 std::format_ptr(pp_pkt));
1364 return AVRC_STS_BAD_PARAM;
1365 }
1366
1367 if (*pp_pkt == NULL) {
1368 *pp_pkt = avrc_bld_init_rsp_buffer(p_rsp);
1369 if (*pp_pkt == NULL) {
1370 log::verbose("Failed to initialize response buffer");
1371 return AVRC_STS_INTERNAL_ERR;
1372 }
1373
1374 if ((*pp_pkt)->layer_specific == AVCT_DATA_BROWSE) {
1375 p = (uint8_t*)((*pp_pkt) + 1);
1376 peer_mtu = AVCT_GetBrowseMtu(handle) - AVCT_HDR_LEN_SINGLE;
1377 UINT16_TO_BE_STREAM(p, peer_mtu);
1378 }
1379
1380 alloc = true;
1381 }
1382 status = AVRC_STS_NO_ERROR;
1383 p_pkt = *pp_pkt;
1384
1385 log::verbose("pdu={:x} status={:x}", p_rsp->rsp.pdu, p_rsp->rsp.status);
1386 if (p_rsp->rsp.status != AVRC_STS_NO_ERROR) {
1387 return avrc_bld_rejected_rsp(&p_rsp->rsp, p_pkt);
1388 }
1389
1390 switch (p_rsp->pdu) {
1391 case AVRC_PDU_NEXT_GROUP:
1392 case AVRC_PDU_PREV_GROUP:
1393 status = avrc_bld_group_navigation_rsp(p_rsp->pdu, p_pkt);
1394 break;
1395
1396 case AVRC_PDU_GET_CAPABILITIES:
1397 status = avrc_bld_get_capability_rsp(&p_rsp->get_caps, p_pkt);
1398 break;
1399
1400 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1401 status = avrc_bld_list_app_settings_attr_rsp(&p_rsp->list_app_attr, p_pkt);
1402 break;
1403
1404 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1405 status = avrc_bld_list_app_settings_values_rsp(&p_rsp->list_app_values, p_pkt);
1406 break;
1407
1408 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1409 status = avrc_bld_get_cur_app_setting_value_rsp(&p_rsp->get_cur_app_val, p_pkt);
1410 break;
1411
1412 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1413 status = avrc_bld_set_app_setting_value_rsp(&p_rsp->set_app_val, p_pkt);
1414 break;
1415
1416 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1417 status = avrc_bld_get_app_setting_attr_text_rsp(&p_rsp->get_app_attr_txt, p_pkt);
1418 break;
1419
1420 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
1421 status = avrc_bld_get_app_setting_value_text_rsp(&p_rsp->get_app_val_txt, p_pkt);
1422 break;
1423
1424 case AVRC_PDU_INFORM_DISPLAY_CHARSET:
1425 status = avrc_bld_inform_charset_rsp(&p_rsp->inform_charset, p_pkt);
1426 break;
1427
1428 case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:
1429 status = avrc_bld_inform_battery_status_rsp(&p_rsp->inform_battery_status, p_pkt);
1430 break;
1431
1432 case AVRC_PDU_GET_ELEMENT_ATTR:
1433 status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_attrs, p_pkt);
1434 break;
1435
1436 case AVRC_PDU_GET_PLAY_STATUS:
1437 status = avrc_bld_get_play_status_rsp(&p_rsp->get_play_status, p_pkt);
1438 break;
1439
1440 case AVRC_PDU_REGISTER_NOTIFICATION:
1441 status = avrc_bld_notify_rsp(&p_rsp->reg_notif, p_pkt);
1442 break;
1443
1444 case AVRC_PDU_REQUEST_CONTINUATION_RSP:
1445 status = avrc_bld_next_rsp(&p_rsp->continu, p_pkt);
1446 break;
1447
1448 case AVRC_PDU_ABORT_CONTINUATION_RSP:
1449 status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt);
1450 break;
1451
1452 case AVRC_PDU_SET_ADDRESSED_PLAYER:
1453 status = avrc_bld_set_addr_player_rsp(&p_rsp->addr_player, p_pkt);
1454 break;
1455
1456 case AVRC_PDU_PLAY_ITEM:
1457 status = avrc_bld_play_item_rsp(&p_rsp->play_item, p_pkt);
1458 break;
1459
1460 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1461 status = avrc_bld_set_absolute_volume_rsp(p_rsp->volume.volume, p_pkt);
1462 break;
1463
1464 case AVRC_PDU_ADD_TO_NOW_PLAYING:
1465 status = avrc_bld_add_to_now_playing_rsp(&p_rsp->add_to_play, p_pkt);
1466 break;
1467
1468 case AVRC_PDU_SET_BROWSED_PLAYER:
1469 status = avrc_bld_set_browsed_player_rsp(&p_rsp->br_player, p_pkt);
1470 break;
1471
1472 case AVRC_PDU_GET_FOLDER_ITEMS:
1473 status = avrc_bld_get_folder_items_rsp(&p_rsp->get_items, p_pkt);
1474 break;
1475
1476 case AVRC_PDU_CHANGE_PATH:
1477 status = avrc_bld_change_path_rsp(&p_rsp->chg_path, p_pkt);
1478 break;
1479
1480 case AVRC_PDU_GET_ITEM_ATTRIBUTES:
1481 status = avrc_bld_get_item_attrs_rsp(&p_rsp->get_attrs, p_pkt);
1482 break;
1483
1484 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:
1485 status = avrc_bld_get_num_of_item_rsp(&p_rsp->get_num_of_items, p_pkt);
1486 break;
1487
1488 case AVRC_PDU_SEARCH:
1489 status = avrc_bld_search_rsp(&p_rsp->search, p_pkt);
1490 break;
1491 }
1492
1493 if (alloc && (status != AVRC_STS_NO_ERROR)) {
1494 osi_free(p_pkt);
1495 *pp_pkt = NULL;
1496 }
1497 log::verbose("returning {}", status);
1498 return status;
1499 }
1500