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 ******************************************************************************/
avrc_bld_get_capability_rsp(tAVRC_GET_CAPS_RSP * p_rsp,BT_HDR * p_pkt)52 static 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 ******************************************************************************/
avrc_bld_list_app_settings_attr_rsp(tAVRC_LIST_APP_ATTR_RSP * p_rsp,BT_HDR * p_pkt)120 static 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 ******************************************************************************/
avrc_bld_list_app_settings_values_rsp(tAVRC_LIST_APP_VALUES_RSP * p_rsp,BT_HDR * p_pkt)166 static 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 ******************************************************************************/
avrc_bld_get_cur_app_setting_value_rsp(tAVRC_GET_CUR_APP_VALUE_RSP * p_rsp,BT_HDR * p_pkt)210 static 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 ******************************************************************************/
avrc_bld_set_app_setting_value_rsp(UNUSED_ATTR tAVRC_RSP * p_rsp,UNUSED_ATTR BT_HDR * p_pkt)262 static 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 ******************************************************************************/
avrc_bld_app_setting_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp,BT_HDR * p_pkt)280 static 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 ******************************************************************************/
avrc_bld_get_app_setting_attr_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp,BT_HDR * p_pkt)350 static 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 ******************************************************************************/
avrc_bld_get_app_setting_value_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp,BT_HDR * p_pkt)367 static 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 ******************************************************************************/
avrc_bld_inform_charset_rsp(UNUSED_ATTR tAVRC_RSP * p_rsp,UNUSED_ATTR BT_HDR * p_pkt)384 static 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 ******************************************************************************/
avrc_bld_inform_battery_status_rsp(UNUSED_ATTR tAVRC_RSP * p_rsp,UNUSED_ATTR BT_HDR * p_pkt)402 static 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
avrc_build_attribute_entries(int num_attrs,tAVRC_ATTR_ENTRY * p_attrs,int remaining_buffer_capacity,uint8_t ** pp_data,uint8_t * p_attribute_count)409 static void avrc_build_attribute_entries(int num_attrs,
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 ******************************************************************************/
avrc_bld_get_elem_attrs_rsp(tAVRC_GET_ATTRS_RSP * p_rsp,BT_HDR * p_pkt)466 static 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 ******************************************************************************/
avrc_bld_get_play_status_rsp(tAVRC_GET_PLAY_STATUS_RSP * p_rsp,BT_HDR * p_pkt)526 static 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 ******************************************************************************/
avrc_bld_notify_rsp(tAVRC_REG_NOTIF_RSP * p_rsp,BT_HDR * p_pkt)554 static 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 ******************************************************************************/
avrc_bld_next_rsp(tAVRC_NEXT_RSP * p_rsp,BT_HDR * p_pkt)683 static 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 *****************************************************************************/
avrc_bld_set_absolute_volume_rsp(uint8_t abs_vol,BT_HDR * p_pkt)703 static 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 ******************************************************************************/
avrc_bld_group_navigation_rsp(uint16_t navi_id,BT_HDR * p_pkt)727 tAVRC_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 ******************************************************************************/
avrc_bld_rejected_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)748 static 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 ******************************************************************************/
avrc_bld_ctrl_status_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)789 static 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 ******************************************************************************/
avrc_bld_set_addr_player_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)813 static 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 ******************************************************************************/
avrc_bld_set_browsed_player_rsp(tAVRC_SET_BR_PLAYER_RSP * p_rsp,BT_HDR * p_pkt)830 static 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 ******************************************************************************/
avrc_bld_get_folder_items_rsp(tAVRC_GET_ITEMS_RSP * p_rsp,BT_HDR * p_pkt)905 static 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 ******************************************************************************/
avrc_bld_change_path_rsp(tAVRC_CHG_PATH_RSP * p_rsp,BT_HDR * p_pkt)1096 static 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 ******************************************************************************/
avrc_bld_get_item_attrs_rsp(tAVRC_GET_ATTRS_RSP * p_rsp,BT_HDR * p_pkt)1126 static 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 ******************************************************************************/
avrc_bld_get_num_of_item_rsp(tAVRC_GET_NUM_OF_ITEMS_RSP * p_rsp,BT_HDR * p_pkt)1202 static 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 ******************************************************************************/
avrc_bld_search_rsp(tAVRC_SEARCH_RSP * p_rsp,BT_HDR * p_pkt)1240 static 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 ******************************************************************************/
avrc_bld_play_item_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)1267 static 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 ******************************************************************************/
avrc_bld_add_to_now_playing_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)1282 static 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 ******************************************************************************/
avrc_bld_init_rsp_buffer(tAVRC_RESPONSE * p_rsp)1298 static 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 ******************************************************************************/
AVRC_BldResponse(uint8_t handle,tAVRC_RESPONSE * p_rsp,BT_HDR ** pp_pkt)1368 tAVRC_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