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 "bt_common.h"
25 #include "bt_utils.h"
26 #include "osi/include/osi.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 uint16_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 len_left = len_left - p_pkt->offset - p_pkt->len;
931
932 /* get the existing length, if any, and also the num attributes */
933 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
934 p_data = p_len = p_start + 1; /* pdu */
935
936 /* the existing len */
937 BE_STREAM_TO_UINT16(len, p_data);
938 p_num = p_data + 3;
939 if (len == 0) {
940 /* first time initialize the attribute count */
941 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
942 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
943 item_count = 0;
944 p_data += 2;
945 len = 5;
946 len_left -= 5;
947 } else {
948 p_data = p_start + p_pkt->len;
949 p = p_num;
950 BE_STREAM_TO_UINT16(item_count, p);
951 }
952 AVRC_TRACE_DEBUG("len:%d, len_left:%d, num:%d", len, len_left, item_count);
953
954 /* min len required = item_type(1) + item len(2) + min item (14) = 17 */
955 for (xx = 0;
956 xx < p_rsp->item_count && len_left > AVRC_MIN_LEN_GET_FOLDER_ITEMS_RSP &&
957 !multi_items_add_fail;
958 xx++) {
959 p_item_start = p_data;
960 UINT8_TO_BE_STREAM(p_data, p_item_list[xx].item_type);
961 /* variable item lenth - save the location to add length */
962 p_item_len = p_data;
963 p_data += 2;
964 item_len = 0;
965 len_left -= 3; /* item_type(1) + item len(2) */
966 switch (p_item_list[xx].item_type) {
967 case AVRC_ITEM_PLAYER:
968 /* min len required: 2 + 1 + 4 + 1 + 16 + 2 + 2 = 30 + str_len */
969 p_player = &p_item_list[xx].u.player;
970 item_len = AVRC_FEATURE_MASK_SIZE + p_player->name.str_len + 12;
971
972 if ((len_left <= item_len) || !AVRC_ITEM_PLAYER_IS_VALID(p_player)) {
973 p_data = p_item_start;
974 } else {
975 UINT16_TO_BE_STREAM(p_data, p_player->player_id);
976 UINT8_TO_BE_STREAM(p_data, p_player->major_type);
977 UINT32_TO_BE_STREAM(p_data, p_player->sub_type);
978 UINT8_TO_BE_STREAM(p_data, p_player->play_status);
979 ARRAY_TO_BE_STREAM(p_data, p_player->features,
980 AVRC_FEATURE_MASK_SIZE);
981 UINT16_TO_BE_STREAM(p_data, p_player->name.charset_id);
982 UINT16_TO_BE_STREAM(p_data, p_player->name.str_len);
983 ARRAY_TO_BE_STREAM(p_data, p_player->name.p_str,
984 p_player->name.str_len);
985 }
986 break;
987
988 case AVRC_ITEM_FOLDER:
989 /* min len required: 8 + 1 + 1 + 2 + 2 = 14 + str_len */
990 p_folder = &p_item_list[xx].u.folder;
991 item_len = AVRC_UID_SIZE + p_folder->name.str_len + 6;
992
993 if ((len_left > item_len) && p_folder->name.p_str &&
994 p_folder->type <= AVRC_FOLDER_TYPE_YEARS) {
995 ARRAY_TO_BE_STREAM(p_data, p_folder->uid, AVRC_UID_SIZE);
996 UINT8_TO_BE_STREAM(p_data, p_folder->type);
997 UINT8_TO_BE_STREAM(p_data, p_folder->playable);
998 UINT16_TO_BE_STREAM(p_data, p_folder->name.charset_id);
999 UINT16_TO_BE_STREAM(p_data, p_folder->name.str_len);
1000 ARRAY_TO_BE_STREAM(p_data, p_folder->name.p_str,
1001 p_folder->name.str_len);
1002 } else {
1003 p_data = p_item_start;
1004 }
1005 break;
1006
1007 case AVRC_ITEM_MEDIA:
1008 /* min len required: 8 + 1 + 2 + 2 + 1 = 14 + str_len */
1009 p_media = &p_item_list[xx].u.media;
1010 item_len = AVRC_UID_SIZE + p_media->name.str_len + 6;
1011
1012 if ((len_left >= item_len) && p_media->name.p_str &&
1013 p_media->type <= AVRC_MEDIA_TYPE_VIDEO) {
1014 ARRAY_TO_BE_STREAM(p_data, p_media->uid, AVRC_UID_SIZE);
1015 UINT8_TO_BE_STREAM(p_data, p_media->type);
1016 UINT16_TO_BE_STREAM(p_data, p_media->name.charset_id);
1017 UINT16_TO_BE_STREAM(p_data, p_media->name.str_len);
1018 ARRAY_TO_BE_STREAM(p_data, p_media->name.p_str,
1019 p_media->name.str_len);
1020 p_attr_count = p_data++;
1021 *p_attr_count = 0;
1022 len_left -= item_len;
1023 if (p_media->attr_count > 0) {
1024 p_attr = p_media->p_attr_list;
1025 for (yy = 0; yy < p_media->attr_count; yy++) {
1026 if (p_attr[yy].name.p_str &&
1027 AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_attr[yy].attr_id) &&
1028 (len_left >= (p_attr[yy].name.str_len + 8))) {
1029 (*p_attr_count)++;
1030 UINT32_TO_BE_STREAM(p_data, p_attr[yy].attr_id);
1031 UINT16_TO_BE_STREAM(p_data, p_attr[yy].name.charset_id);
1032 UINT16_TO_BE_STREAM(p_data, p_attr[yy].name.str_len);
1033 ARRAY_TO_BE_STREAM(p_data, p_attr[yy].name.p_str,
1034 p_attr[yy].name.str_len);
1035 item_len += (p_attr[yy].name.str_len + 8);
1036 len_left -= (p_attr[yy].name.str_len + 8);
1037 } else if ((len_left < (p_attr[yy].name.str_len + 8)) &&
1038 item_count > 0) {
1039 p_data = p_item_start;
1040 multi_items_add_fail = TRUE;
1041 break;
1042 }
1043 }
1044 }
1045 } else {
1046 if (len_left < item_len && item_count > 0)
1047 multi_items_add_fail = TRUE;
1048 p_data = p_item_start;
1049 }
1050 break;
1051 } /* switch item_type */
1052
1053 if (p_item_start != p_data) {
1054 /* successfully added the item */
1055 item_count++;
1056 /* fill in variable item lenth */
1057 UINT16_TO_BE_STREAM(p_item_len, item_len);
1058 } else {
1059 if (!multi_items_add_fail) {
1060 /* some item is not added properly - set an error status */
1061 if (len_left < item_len)
1062 status = AVRC_STS_INTERNAL_ERR;
1063 else
1064 status = AVRC_STS_BAD_PARAM;
1065 }
1066 }
1067 if (!multi_items_add_fail) {
1068 len += item_len;
1069 len += 3; /* the item_type(1) and item_len(2) */
1070 }
1071 AVRC_TRACE_DEBUG("len:%d, len_left:%d, num:%d, item_len:%d", len, len_left,
1072 item_count, item_len);
1073 } /* for item_count */
1074
1075 UINT16_TO_BE_STREAM(p_num, item_count);
1076 UINT16_TO_BE_STREAM(p_len, len);
1077 p_pkt->len = (p_data - p_start);
1078
1079 return status;
1080 }
1081
1082 /*******************************************************************************
1083 *
1084 * Function avrc_bld_change_path_rsp
1085 *
1086 * Description This function builds the Change Path response.
1087 *
1088 * This message goes through the Browsing channel
1089 *
1090 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1091 * Otherwise, the error code.
1092 *
1093 ******************************************************************************/
avrc_bld_change_path_rsp(tAVRC_CHG_PATH_RSP * p_rsp,BT_HDR * p_pkt)1094 static tAVRC_STS avrc_bld_change_path_rsp(tAVRC_CHG_PATH_RSP* p_rsp,
1095 BT_HDR* p_pkt) {
1096 uint8_t *p_data, *p_start;
1097
1098 /* get the existing length, if any, and also the num attributes */
1099 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1100 p_data = p_start + 1; /* pdu */
1101 /* add fixed length - status(1) + num_items(4) */
1102 UINT16_TO_BE_STREAM(p_data, 5);
1103 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
1104 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
1105 p_pkt->len = (p_data - p_start);
1106 return AVRC_STS_NO_ERROR;
1107 }
1108
1109 /*******************************************************************************
1110 *
1111 * Function avrc_bld_get_attrs_rsp
1112 *
1113 * Description This function builds the GetItemAttributes response,
1114 *
1115 * The Get Item Attributes message goes through the
1116 * Browsing channel (already specified in the |p_pkt|)
1117 *
1118 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1119 * AVRC_STS_INTERNAL_ERR, if the given buffer does not have
1120 * enough room
1121 * Otherwise, the error code.
1122 *
1123 ******************************************************************************/
avrc_bld_get_item_attrs_rsp(tAVRC_GET_ATTRS_RSP * p_rsp,BT_HDR * p_pkt)1124 static tAVRC_STS avrc_bld_get_item_attrs_rsp(tAVRC_GET_ATTRS_RSP* p_rsp,
1125 BT_HDR* p_pkt) {
1126 AVRC_TRACE_API("%s", __func__);
1127 if (!p_rsp->p_attrs) {
1128 AVRC_TRACE_ERROR("%s NULL p_attrs", __func__);
1129 return AVRC_STS_BAD_PARAM;
1130 }
1131 /* Figure out how much we have left in current buffer */
1132 int remaining_buffer_capacity =
1133 BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset;
1134 /* Get to the beginning of data section in buffer */
1135 uint8_t* p_data = (uint8_t*)(p_pkt + 1);
1136 /* Get the MTU size that is filled in earlier */
1137 uint16_t mtu;
1138 BE_STREAM_TO_UINT16(mtu, p_data);
1139 if (remaining_buffer_capacity > mtu) {
1140 remaining_buffer_capacity = mtu;
1141 }
1142 AVRC_TRACE_DEBUG("%s: remaining_buffer_capacity:%d, mtu:%d", __func__,
1143 remaining_buffer_capacity, mtu);
1144 if (remaining_buffer_capacity < 5) {
1145 AVRC_TRACE_ERROR("%s: not enough space for packet header, remaining:%d < 5",
1146 __func__, remaining_buffer_capacity);
1147 return AVRC_STS_INTERNAL_ERR;
1148 }
1149 /* Get to the beginning of PDU */
1150 uint8_t* p_pdu_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1151 /* Skip PDU ID to get pointer to Parameter length */
1152 uint8_t* p_parameter_len;
1153 p_data = p_parameter_len = p_pdu_start + 1;
1154 /* Parse existing parameter length */
1155 uint16_t parameter_len;
1156 BE_STREAM_TO_UINT16(parameter_len, p_data);
1157 /* Skip one byte to Number of Attributes */
1158 uint8_t* p_status = p_data++;
1159 uint8_t* p_attribute_count = p_data++;
1160 if (parameter_len == 0) {
1161 /* First time, initialize the status byte */
1162 *p_status = p_rsp->status;
1163 if (p_rsp->status != AVRC_STS_NO_ERROR) {
1164 // TODO(siyuanh): This is a hack
1165 parameter_len = 1;
1166 UINT16_TO_BE_STREAM(p_parameter_len, parameter_len);
1167 p_pkt->len = p_status - p_pdu_start;
1168 return AVRC_STS_NO_ERROR;
1169 }
1170 *p_attribute_count = 0;
1171 } else {
1172 // TODO(siyuanh): Why do wee need this case?
1173 p_data = p_pdu_start + p_pkt->len;
1174 }
1175 remaining_buffer_capacity -= p_data - p_pdu_start;
1176 /* Fill in the Attribute ID, Character Set, Length and Values */
1177 avrc_build_attribute_entries(p_rsp->num_attrs, p_rsp->p_attrs,
1178 remaining_buffer_capacity, &p_data,
1179 p_attribute_count);
1180 parameter_len = p_data - p_status;
1181 UINT16_TO_BE_STREAM(p_parameter_len, parameter_len);
1182 p_pkt->len = p_data - p_pdu_start;
1183 return AVRC_STS_NO_ERROR;
1184 }
1185
1186 /*******************************************************************************
1187 *
1188 * Function avrc_bld_get_num_of_item_rsp
1189 *
1190 * Description This function builds the Get Total Number of Items response.
1191 *
1192 * This message goes through the Browsing channel
1193 *
1194 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1195 * AVRC_STS_INTERNAL_ERR, if the given buffer does not have
1196 * enough room
1197 * Otherwise, the error code.
1198 *
1199 ******************************************************************************/
avrc_bld_get_num_of_item_rsp(tAVRC_GET_NUM_OF_ITEMS_RSP * p_rsp,BT_HDR * p_pkt)1200 static tAVRC_STS avrc_bld_get_num_of_item_rsp(tAVRC_GET_NUM_OF_ITEMS_RSP* p_rsp,
1201 BT_HDR* p_pkt) {
1202 uint8_t *p_data, *p_start, *p_len;
1203
1204 AVRC_TRACE_API("%s", __func__);
1205 /* get the existing length, if any, and also the num attributes */
1206 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1207 p_data = p_len = p_start + 1; /* pdu */
1208
1209 if (p_rsp->status == AVRC_STS_NO_ERROR) {
1210 /* add fixed lenth - status(1) + uid_counter(2) + num_items(4) */
1211 UINT16_TO_BE_STREAM(p_data, 7);
1212 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
1213 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
1214 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
1215 p_pkt->len = (p_data - p_start);
1216 return AVRC_STS_NO_ERROR;
1217 } else {
1218 /* add fixed lenth - status(1) */
1219 UINT16_TO_BE_STREAM(p_data, 7);
1220 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
1221 p_pkt->len = (p_data - p_start);
1222 return p_rsp->status;
1223 }
1224 }
1225
1226 /*******************************************************************************
1227 *
1228 * Function avrc_bld_search_rsp
1229 *
1230 * Description This function builds the Search response.
1231 *
1232 * This message goes through the Browsing channel
1233 *
1234 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1235 * Otherwise, the error code.
1236 *
1237 ******************************************************************************/
avrc_bld_search_rsp(tAVRC_SEARCH_RSP * p_rsp,BT_HDR * p_pkt)1238 static tAVRC_STS avrc_bld_search_rsp(tAVRC_SEARCH_RSP* p_rsp, BT_HDR* p_pkt) {
1239 uint8_t *p_data, *p_start, *p_len;
1240
1241 AVRC_TRACE_API("%s", __func__);
1242 /* get the existing length, if any, and also the num attributes */
1243 p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1244 p_data = p_len = p_start + 1; /* pdu */
1245
1246 /* add fixed lenth - status(1) + uid_counter(2) + num_items(4) */
1247 UINT16_TO_BE_STREAM(p_data, 7);
1248 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
1249 UINT16_TO_BE_STREAM(p_data, p_rsp->uid_counter);
1250 UINT32_TO_BE_STREAM(p_data, p_rsp->num_items);
1251 p_pkt->len = (p_data - p_start);
1252 return AVRC_STS_NO_ERROR;
1253 }
1254
1255 /*******************************************************************************
1256 *
1257 * Function avrc_bld_play_item_rsp
1258 *
1259 * Description This function builds the Play Item response.
1260 *
1261 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1262 * Otherwise, the error code.
1263 *
1264 ******************************************************************************/
avrc_bld_play_item_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)1265 static tAVRC_STS avrc_bld_play_item_rsp(tAVRC_RSP* p_rsp, BT_HDR* p_pkt) {
1266 AVRC_TRACE_API("%s", __func__);
1267 return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt);
1268 }
1269
1270 /*******************************************************************************
1271 *
1272 * Function avrc_bld_add_to_now_playing_rsp
1273 *
1274 * Description This function builds the Add to Now Playing response.
1275 *
1276 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1277 * Otherwise, the error code.
1278 *
1279 ******************************************************************************/
avrc_bld_add_to_now_playing_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)1280 static tAVRC_STS avrc_bld_add_to_now_playing_rsp(tAVRC_RSP* p_rsp,
1281 BT_HDR* p_pkt) {
1282 AVRC_TRACE_API("%s", __func__);
1283 return avrc_bld_ctrl_status_rsp(p_rsp, p_pkt);
1284 }
1285
1286 /*******************************************************************************
1287 *
1288 * Function avrc_bld_init_rsp_buffer
1289 *
1290 * Description This function initializes the response buffer based on PDU
1291 *
1292 * Returns NULL, if no buffer or failure to build the message.
1293 * Otherwise, the buffer that contains the initialized message.
1294 *
1295 ******************************************************************************/
avrc_bld_init_rsp_buffer(tAVRC_RESPONSE * p_rsp)1296 static BT_HDR* avrc_bld_init_rsp_buffer(tAVRC_RESPONSE* p_rsp) {
1297 uint16_t offset = 0;
1298 uint16_t chnl = AVCT_DATA_CTRL;
1299 uint8_t opcode = avrc_opcode_from_pdu(p_rsp->pdu);
1300
1301 AVRC_TRACE_API("%s: pdu=%x, opcode=%x/%x", __func__, p_rsp->pdu, opcode,
1302 p_rsp->rsp.opcode);
1303 if (opcode != p_rsp->rsp.opcode && p_rsp->rsp.status != AVRC_STS_NO_ERROR &&
1304 avrc_is_valid_opcode(p_rsp->rsp.opcode)) {
1305 opcode = p_rsp->rsp.opcode;
1306 AVRC_TRACE_API("%s opcode=%x", __func__, opcode);
1307 }
1308
1309 switch (opcode) {
1310 case AVRC_OP_BROWSE:
1311 chnl = AVCT_DATA_BROWSE;
1312 offset = AVCT_BROWSE_OFFSET;
1313 break;
1314
1315 case AVRC_OP_PASS_THRU:
1316 offset = AVRC_MSG_PASS_THRU_OFFSET;
1317 break;
1318
1319 case AVRC_OP_VENDOR:
1320 offset = AVRC_MSG_VENDOR_OFFSET;
1321 break;
1322 }
1323
1324 /* allocate and initialize the buffer */
1325 BT_HDR* p_pkt = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
1326 uint8_t *p_data, *p_start;
1327
1328 p_pkt->layer_specific = chnl;
1329 p_pkt->event = opcode;
1330 p_pkt->offset = offset;
1331 p_data = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
1332 p_start = p_data;
1333
1334 /* pass thru - group navigation - has a two byte op_id, so dont do it here */
1335 if (opcode != AVRC_OP_PASS_THRU) *p_data++ = p_rsp->pdu;
1336
1337 switch (opcode) {
1338 case AVRC_OP_VENDOR:
1339 /* reserved 0, packet_type 0 */
1340 UINT8_TO_BE_STREAM(p_data, 0);
1341 /* continue to the next "case to add length */
1342
1343 case AVRC_OP_BROWSE:
1344 /* add fixed lenth - 0 */
1345 UINT16_TO_BE_STREAM(p_data, 0);
1346 break;
1347 }
1348
1349 p_pkt->len = (p_data - p_start);
1350 p_rsp->rsp.opcode = opcode;
1351
1352 return p_pkt;
1353 }
1354
1355 /*******************************************************************************
1356 *
1357 * Function AVRC_BldResponse
1358 *
1359 * Description This function builds the given AVRCP response to the given
1360 * buffer
1361 *
1362 * Returns AVRC_STS_NO_ERROR, if the response is built successfully
1363 * Otherwise, the error code.
1364 *
1365 ******************************************************************************/
AVRC_BldResponse(uint8_t handle,tAVRC_RESPONSE * p_rsp,BT_HDR ** pp_pkt)1366 tAVRC_STS AVRC_BldResponse(uint8_t handle, tAVRC_RESPONSE* p_rsp,
1367 BT_HDR** pp_pkt) {
1368 tAVRC_STS status = AVRC_STS_BAD_PARAM;
1369 BT_HDR* p_pkt;
1370 bool alloc = false;
1371 uint8_t* p;
1372 uint16_t peer_mtu;
1373
1374 if (!p_rsp || !pp_pkt) {
1375 AVRC_TRACE_API("%s Invalid parameters passed. p_rsp=%p, pp_pkt=%p",
1376 __func__, p_rsp, pp_pkt);
1377 return AVRC_STS_BAD_PARAM;
1378 }
1379
1380 if (*pp_pkt == NULL) {
1381 *pp_pkt = avrc_bld_init_rsp_buffer(p_rsp);
1382 if (*pp_pkt == NULL) {
1383 AVRC_TRACE_API("%s Failed to initialize response buffer", __func__);
1384 return AVRC_STS_INTERNAL_ERR;
1385 }
1386
1387 if ((*pp_pkt)->layer_specific == AVCT_DATA_BROWSE) {
1388 p = (uint8_t*)((*pp_pkt) + 1);
1389 peer_mtu = AVCT_GetBrowseMtu(handle) - AVCT_HDR_LEN_SINGLE;
1390 UINT16_TO_BE_STREAM(p, peer_mtu);
1391 }
1392
1393 alloc = true;
1394 }
1395 status = AVRC_STS_NO_ERROR;
1396 p_pkt = *pp_pkt;
1397
1398 AVRC_TRACE_API("%s pdu=%x status=%x", __func__, p_rsp->rsp.pdu,
1399 p_rsp->rsp.status);
1400 if (p_rsp->rsp.status != AVRC_STS_NO_ERROR) {
1401 return (avrc_bld_rejected_rsp(&p_rsp->rsp, p_pkt));
1402 }
1403
1404 switch (p_rsp->pdu) {
1405 case AVRC_PDU_NEXT_GROUP:
1406 case AVRC_PDU_PREV_GROUP:
1407 status = avrc_bld_group_navigation_rsp(p_rsp->pdu, p_pkt);
1408 break;
1409
1410 case AVRC_PDU_GET_CAPABILITIES:
1411 status = avrc_bld_get_capability_rsp(&p_rsp->get_caps, p_pkt);
1412 break;
1413
1414 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1415 status =
1416 avrc_bld_list_app_settings_attr_rsp(&p_rsp->list_app_attr, p_pkt);
1417 break;
1418
1419 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1420 status =
1421 avrc_bld_list_app_settings_values_rsp(&p_rsp->list_app_values, p_pkt);
1422 break;
1423
1424 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1425 status = avrc_bld_get_cur_app_setting_value_rsp(&p_rsp->get_cur_app_val,
1426 p_pkt);
1427 break;
1428
1429 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1430 status = avrc_bld_set_app_setting_value_rsp(&p_rsp->set_app_val, p_pkt);
1431 break;
1432
1433 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1434 status = avrc_bld_get_app_setting_attr_text_rsp(&p_rsp->get_app_attr_txt,
1435 p_pkt);
1436 break;
1437
1438 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
1439 status = avrc_bld_get_app_setting_value_text_rsp(&p_rsp->get_app_val_txt,
1440 p_pkt);
1441 break;
1442
1443 case AVRC_PDU_INFORM_DISPLAY_CHARSET:
1444 status = avrc_bld_inform_charset_rsp(&p_rsp->inform_charset, p_pkt);
1445 break;
1446
1447 case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:
1448 status = avrc_bld_inform_battery_status_rsp(&p_rsp->inform_battery_status,
1449 p_pkt);
1450 break;
1451
1452 case AVRC_PDU_GET_ELEMENT_ATTR:
1453 status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_attrs, p_pkt);
1454 break;
1455
1456 case AVRC_PDU_GET_PLAY_STATUS:
1457 status = avrc_bld_get_play_status_rsp(&p_rsp->get_play_status, p_pkt);
1458 break;
1459
1460 case AVRC_PDU_REGISTER_NOTIFICATION:
1461 status = avrc_bld_notify_rsp(&p_rsp->reg_notif, p_pkt);
1462 break;
1463
1464 case AVRC_PDU_REQUEST_CONTINUATION_RSP:
1465 status = avrc_bld_next_rsp(&p_rsp->continu, p_pkt);
1466 break;
1467
1468 case AVRC_PDU_ABORT_CONTINUATION_RSP:
1469 status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt);
1470 break;
1471
1472 case AVRC_PDU_SET_ADDRESSED_PLAYER:
1473 status = avrc_bld_set_addr_player_rsp(&p_rsp->addr_player, p_pkt);
1474 break;
1475
1476 case AVRC_PDU_PLAY_ITEM:
1477 status = avrc_bld_play_item_rsp(&p_rsp->play_item, p_pkt);
1478 break;
1479
1480 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1481 status = avrc_bld_set_absolute_volume_rsp(p_rsp->volume.volume, p_pkt);
1482 break;
1483
1484 case AVRC_PDU_ADD_TO_NOW_PLAYING:
1485 status = avrc_bld_add_to_now_playing_rsp(&p_rsp->add_to_play, p_pkt);
1486 break;
1487
1488 case AVRC_PDU_SET_BROWSED_PLAYER:
1489 status = avrc_bld_set_browsed_player_rsp(&p_rsp->br_player, p_pkt);
1490 break;
1491
1492 case AVRC_PDU_GET_FOLDER_ITEMS:
1493 status = avrc_bld_get_folder_items_rsp(&p_rsp->get_items, p_pkt);
1494 break;
1495
1496 case AVRC_PDU_CHANGE_PATH:
1497 status = avrc_bld_change_path_rsp(&p_rsp->chg_path, p_pkt);
1498 break;
1499
1500 case AVRC_PDU_GET_ITEM_ATTRIBUTES:
1501 status = avrc_bld_get_item_attrs_rsp(&p_rsp->get_attrs, p_pkt);
1502 break;
1503
1504 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:
1505 status = avrc_bld_get_num_of_item_rsp(&p_rsp->get_num_of_items, p_pkt);
1506 break;
1507
1508 case AVRC_PDU_SEARCH:
1509 status = avrc_bld_search_rsp(&p_rsp->search, p_pkt);
1510 break;
1511 }
1512
1513 if (alloc && (status != AVRC_STS_NO_ERROR)) {
1514 osi_free(p_pkt);
1515 *pp_pkt = NULL;
1516 }
1517 AVRC_TRACE_API("%s returning %d", __func__, status);
1518 return status;
1519 }
1520