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