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