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