1 /******************************************************************************
2 *
3 * Copyright (C) 2003-2013 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 <string.h>
19 #include "common/bt_target.h"
20 #include "stack/avrc_api.h"
21 #include "stack/avrc_defs.h"
22 #include "avrc_int.h"
23 #include "common/bt_defs.h"
24 #include "osi/allocator.h"
25
26 #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
27
28 /*****************************************************************************
29 ** Global data
30 *****************************************************************************/
31 #if (AVRC_METADATA_INCLUDED == TRUE)
32
33 /*******************************************************************************
34 **
35 ** Function avrc_bld_get_capability_rsp
36 **
37 ** Description This function builds the Get Capability response.
38 **
39 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
40 ** Otherwise, the error code.
41 **
42 *******************************************************************************/
avrc_bld_get_capability_rsp(tAVRC_GET_CAPS_RSP * p_rsp,BT_HDR * p_pkt)43 static tAVRC_STS avrc_bld_get_capability_rsp (tAVRC_GET_CAPS_RSP *p_rsp, BT_HDR *p_pkt)
44 {
45 UINT8 *p_data, *p_start, *p_len, *p_count;
46 UINT16 len = 0;
47 UINT8 xx;
48 UINT32 *p_company_id;
49 UINT8 *p_event_id;
50 tAVRC_STS status = AVRC_STS_NO_ERROR;
51
52 if (!(AVRC_IS_VALID_CAP_ID(p_rsp->capability_id))) {
53 AVRC_TRACE_ERROR("avrc_bld_get_capability_rsp bad parameter. p_rsp: %x", (int)p_rsp);
54 status = AVRC_STS_BAD_PARAM;
55 return status;
56 }
57
58 AVRC_TRACE_API("avrc_bld_get_capability_rsp");
59 /* get the existing length, if any, and also the num attributes */
60 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
61 p_data = p_len = p_start + 2; /* pdu + rsvd */
62
63 BE_STREAM_TO_UINT16(len, p_data);
64 UINT8_TO_BE_STREAM(p_data, p_rsp->capability_id);
65 p_count = p_data;
66
67 if (len == 0) {
68 *p_count = p_rsp->count;
69 p_data++;
70 len = 2; /* move past the capability_id and count */
71 } else {
72 p_data = p_start + p_pkt->len;
73 *p_count += p_rsp->count;
74 }
75
76 if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) {
77 p_company_id = p_rsp->param.company_id;
78 for (xx = 0; xx < p_rsp->count; xx++) {
79 UINT24_TO_BE_STREAM(p_data, p_company_id[xx]);
80 }
81 len += p_rsp->count * 3;
82 } else {
83 p_event_id = p_rsp->param.event_id;
84 *p_count = 0;
85 for (xx = 0; xx < p_rsp->count; xx++) {
86 if (AVRC_IS_VALID_EVENT_ID(p_event_id[xx])) {
87 (*p_count)++;
88 UINT8_TO_BE_STREAM(p_data, p_event_id[xx]);
89 }
90 }
91 len += (*p_count);
92 }
93 UINT16_TO_BE_STREAM(p_len, len);
94 p_pkt->len = (p_data - p_start);
95 status = AVRC_STS_NO_ERROR;
96
97 return status;
98 }
99
100 /*******************************************************************************
101 **
102 ** Function avrc_bld_list_app_settings_attr_rsp
103 **
104 ** Description This function builds the List Application Settings Attribute
105 ** response.
106 **
107 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
108 ** Otherwise, the error code.
109 **
110 *******************************************************************************/
avrc_bld_list_app_settings_attr_rsp(tAVRC_LIST_APP_ATTR_RSP * p_rsp,BT_HDR * p_pkt)111 static tAVRC_STS avrc_bld_list_app_settings_attr_rsp (tAVRC_LIST_APP_ATTR_RSP *p_rsp, BT_HDR *p_pkt)
112 {
113 UINT8 *p_data, *p_start, *p_len, *p_num;
114 UINT16 len = 0;
115 UINT8 xx;
116
117 AVRC_TRACE_API("avrc_bld_list_app_settings_attr_rsp");
118 /* get the existing length, if any, and also the num attributes */
119 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
120 p_data = p_len = p_start + 2; /* pdu + rsvd */
121
122 BE_STREAM_TO_UINT16(len, p_data);
123 p_num = p_data;
124 if (len == 0) {
125 /* first time initialize the attribute count */
126 *p_num = 0;
127 p_data++;
128 } else {
129 p_data = p_start + p_pkt->len;
130 }
131
132 for (xx = 0; xx < p_rsp->num_attr; xx++) {
133 if (AVRC_IsValidPlayerAttr(p_rsp->attrs[xx])) {
134 (*p_num)++;
135 UINT8_TO_BE_STREAM(p_data, p_rsp->attrs[xx]);
136 }
137 }
138
139 len = *p_num + 1;
140 UINT16_TO_BE_STREAM(p_len, len);
141 p_pkt->len = (p_data - p_start);
142
143 return AVRC_STS_NO_ERROR;
144 }
145
146 /*******************************************************************************
147 **
148 ** Function avrc_bld_list_app_settings_values_rsp
149 **
150 ** Description This function builds the List Application Setting Values
151 ** response.
152 **
153 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
154 ** Otherwise, the error code.
155 **
156 *******************************************************************************/
avrc_bld_list_app_settings_values_rsp(tAVRC_LIST_APP_VALUES_RSP * p_rsp,BT_HDR * p_pkt)157 static tAVRC_STS avrc_bld_list_app_settings_values_rsp (tAVRC_LIST_APP_VALUES_RSP *p_rsp,
158 BT_HDR *p_pkt)
159 {
160 UINT8 *p_data, *p_start, *p_len, *p_num;
161 UINT8 xx;
162 UINT16 len;
163
164 AVRC_TRACE_API("avrc_bld_list_app_settings_values_rsp");
165
166 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
167 p_data = p_len = p_start + 2; /* pdu + rsvd */
168
169 /* get the existing length, if any, and also the num attributes */
170 BE_STREAM_TO_UINT16(len, p_data);
171 p_num = p_data;
172 /* first time initialize the attribute count */
173 if (len == 0) {
174 *p_num = p_rsp->num_val;
175 p_data++;
176 } else {
177 p_data = p_start + p_pkt->len;
178 *p_num += p_rsp->num_val;
179 }
180
181
182 for (xx = 0; xx < p_rsp->num_val; xx++) {
183 UINT8_TO_BE_STREAM(p_data, p_rsp->vals[xx]);
184 }
185
186 len = *p_num + 1;
187 UINT16_TO_BE_STREAM(p_len, len);
188 p_pkt->len = (p_data - p_start);
189 return AVRC_STS_NO_ERROR;
190 }
191
192 /*******************************************************************************
193 **
194 ** Function avrc_bld_get_cur_app_setting_value_rsp
195 **
196 ** Description This function builds the Get Current Application Setting Value
197 ** response.
198 **
199 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
200 ** Otherwise, the error code.
201 **
202 *******************************************************************************/
avrc_bld_get_cur_app_setting_value_rsp(tAVRC_GET_CUR_APP_VALUE_RSP * p_rsp,BT_HDR * p_pkt)203 static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp (tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp,
204 BT_HDR *p_pkt)
205 {
206 UINT8 *p_data, *p_start, *p_len, *p_count;
207 UINT16 len;
208 UINT8 xx;
209
210 if (!p_rsp->p_vals) {
211 AVRC_TRACE_ERROR("avrc_bld_get_cur_app_setting_value_rsp NULL parameter");
212 return AVRC_STS_BAD_PARAM;
213 }
214
215 AVRC_TRACE_API("avrc_bld_get_cur_app_setting_value_rsp");
216 /* get the existing length, if any, and also the num attributes */
217 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
218 p_data = p_len = p_start + 2; /* pdu + rsvd */
219
220 BE_STREAM_TO_UINT16(len, p_data);
221 p_count = p_data;
222 if (len == 0) {
223 /* first time initialize the attribute count */
224 *p_count = 0;
225 p_data++;
226 } else {
227 p_data = p_start + p_pkt->len;
228 }
229
230 for (xx = 0; xx < p_rsp->num_val; xx++) {
231 if (avrc_is_valid_player_attrib_value(p_rsp->p_vals[xx].attr_id, p_rsp->p_vals[xx].attr_val)) {
232 (*p_count)++;
233 UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_id);
234 UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_val);
235 }
236 }
237 len = ((*p_count) << 1) + 1;
238 UINT16_TO_BE_STREAM(p_len, len);
239 p_pkt->len = (p_data - p_start);
240
241 return AVRC_STS_NO_ERROR;
242 }
243
244 /*******************************************************************************
245 **
246 ** Function avrc_bld_set_app_setting_value_rsp
247 **
248 ** Description This function builds the Set Application Setting Value
249 ** response.
250 **
251 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
252 ** Otherwise, the error code.
253 **
254 *******************************************************************************/
avrc_bld_set_app_setting_value_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)255 static tAVRC_STS avrc_bld_set_app_setting_value_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
256 {
257 UNUSED(p_rsp);
258 UNUSED(p_pkt);
259
260 /* nothing to be added. */
261 AVRC_TRACE_API("avrc_bld_set_app_setting_value_rsp");
262 return AVRC_STS_NO_ERROR;
263 }
264
265 /*******************************************************************************
266 **
267 ** Function avrc_bld_app_setting_text_rsp
268 **
269 ** Description This function builds the Get Application Settings Attribute Text
270 ** or Get Application Settings Value Text response.
271 **
272 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
273 ** Otherwise, the error code.
274 **
275 *******************************************************************************/
avrc_bld_app_setting_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp,BT_HDR * p_pkt)276 static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt)
277 {
278 UINT8 *p_data, *p_start, *p_len, *p_count;
279 UINT16 len, len_left;
280 UINT8 xx;
281 tAVRC_STS sts = AVRC_STS_NO_ERROR;
282 UINT8 num_added = 0;
283
284 if (!p_rsp->p_attrs) {
285 AVRC_TRACE_ERROR("avrc_bld_app_setting_text_rsp NULL parameter");
286 return AVRC_STS_BAD_PARAM;
287 }
288 /* get the existing length, if any, and also the num attributes */
289 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
290 p_data = p_len = p_start + 2; /* pdu + rsvd */
291
292 /*
293 * NOTE: The buffer is allocated within avrc_bld_init_rsp_buffer(), and is
294 * always of size BT_DEFAULT_BUFFER_SIZE.
295 */
296 len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset - p_pkt->len;
297
298 BE_STREAM_TO_UINT16(len, p_data);
299 p_count = p_data;
300
301 if (len == 0) {
302 *p_count = 0;
303 p_data++;
304 } else {
305 p_data = p_start + p_pkt->len;
306 }
307
308 for (xx = 0; xx < p_rsp->num_attr; xx++) {
309 if (len_left < (p_rsp->p_attrs[xx].str_len + 4)) {
310 AVRC_TRACE_ERROR("avrc_bld_app_setting_text_rsp out of room %d(str_len:%d, left:%d)",
311 xx, p_rsp->p_attrs[xx].str_len, len_left);
312 p_rsp->num_attr = num_added;
313 sts = AVRC_STS_INTERNAL_ERR;
314 break;
315 }
316 if ( !p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str ) {
317 AVRC_TRACE_ERROR("avrc_bld_app_setting_text_rsp NULL attr text[%d]", xx);
318 continue;
319 }
320 UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
321 UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id);
322 UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len);
323 ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, p_rsp->p_attrs[xx].str_len);
324 (*p_count)++;
325 num_added++;
326 }
327 len = p_data - p_count;
328 UINT16_TO_BE_STREAM(p_len, len);
329 p_pkt->len = (p_data - p_start);
330
331 return sts;
332 }
333
334 /*******************************************************************************
335 **
336 ** Function avrc_bld_get_app_setting_attr_text_rsp
337 **
338 ** Description This function builds the Get Application Setting Attribute Text
339 ** response.
340 **
341 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
342 ** Otherwise, the error code.
343 **
344 *******************************************************************************/
avrc_bld_get_app_setting_attr_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp,BT_HDR * p_pkt)345 static tAVRC_STS avrc_bld_get_app_setting_attr_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp,
346 BT_HDR *p_pkt)
347 {
348 AVRC_TRACE_API("avrc_bld_get_app_setting_attr_text_rsp");
349 return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
350 }
351
352 /*******************************************************************************
353 **
354 ** Function avrc_bld_get_app_setting_value_text_rsp
355 **
356 ** Description This function builds the Get Application Setting Value Text
357 ** response.
358 **
359 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
360 ** Otherwise, the error code.
361 **
362 *******************************************************************************/
avrc_bld_get_app_setting_value_text_rsp(tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp,BT_HDR * p_pkt)363 static tAVRC_STS avrc_bld_get_app_setting_value_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp,
364 BT_HDR *p_pkt)
365 {
366 AVRC_TRACE_API("avrc_bld_get_app_setting_value_text_rsp");
367 return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
368 }
369
370 /*******************************************************************************
371 **
372 ** Function avrc_bld_inform_charset_rsp
373 **
374 ** Description This function builds the Inform Displayable Character Set
375 ** response.
376 **
377 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
378 ** Otherwise, the error code.
379 **
380 *******************************************************************************/
avrc_bld_inform_charset_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)381 static tAVRC_STS avrc_bld_inform_charset_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
382 {
383 UNUSED(p_rsp);
384 UNUSED(p_pkt);
385
386 /* nothing to be added. */
387 AVRC_TRACE_API("avrc_bld_inform_charset_rsp");
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(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)402 static tAVRC_STS avrc_bld_inform_battery_status_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
403 {
404 UNUSED(p_rsp);
405 UNUSED(p_pkt);
406
407 /* nothing to be added. */
408 AVRC_TRACE_API("avrc_bld_inform_battery_status_rsp");
409 return AVRC_STS_NO_ERROR;
410 }
411
412 /*******************************************************************************
413 **
414 ** Function avrc_bld_get_elem_attrs_rsp
415 **
416 ** Description This function builds the Get Element Attributes
417 ** response.
418 **
419 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
420 ** Otherwise, the error code.
421 **
422 *******************************************************************************/
avrc_bld_get_elem_attrs_rsp(tAVRC_GET_ELEM_ATTRS_RSP * p_rsp,BT_HDR * p_pkt)423 static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
424 {
425 UINT8 *p_data, *p_start, *p_len, *p_count;
426 UINT16 len;
427 UINT8 xx;
428
429 AVRC_TRACE_API("avrc_bld_get_elem_attrs_rsp");
430 if (!p_rsp->p_attrs) {
431 AVRC_TRACE_ERROR("avrc_bld_get_elem_attrs_rsp NULL parameter");
432 return AVRC_STS_BAD_PARAM;
433 }
434
435 /* get the existing length, if any, and also the num attributes */
436 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
437 p_data = p_len = p_start + 2; /* pdu + rsvd */
438
439 BE_STREAM_TO_UINT16(len, p_data);
440 p_count = p_data;
441
442 if (len == 0) {
443 *p_count = 0;
444 p_data++;
445 } else {
446 p_data = p_start + p_pkt->len;
447 }
448
449 for (xx = 0; xx < p_rsp->num_attr; xx++) {
450 if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id)) {
451 AVRC_TRACE_ERROR("avrc_bld_get_elem_attrs_rsp invalid attr id[%d]: %d", xx, p_rsp->p_attrs[xx].attr_id);
452 continue;
453 }
454 if ( !p_rsp->p_attrs[xx].name.p_str ) {
455 p_rsp->p_attrs[xx].name.str_len = 0;
456 }
457 UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
458 UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id);
459 UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len);
460 ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len);
461 (*p_count)++;
462 }
463 len = p_data - p_count;
464 UINT16_TO_BE_STREAM(p_len, len);
465 p_pkt->len = (p_data - p_start);
466 return AVRC_STS_NO_ERROR;
467 }
468
469 /*******************************************************************************
470 **
471 ** Function avrc_bld_get_play_status_rsp
472 **
473 ** Description This function builds the Get Play Status
474 ** response.
475 **
476 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
477 ** Otherwise, the error code.
478 **
479 *******************************************************************************/
avrc_bld_get_play_status_rsp(tAVRC_GET_PLAY_STATUS_RSP * p_rsp,BT_HDR * p_pkt)480 static tAVRC_STS avrc_bld_get_play_status_rsp (tAVRC_GET_PLAY_STATUS_RSP *p_rsp, BT_HDR *p_pkt)
481 {
482 UINT8 *p_data, *p_start;
483
484 AVRC_TRACE_API("avrc_bld_get_play_status_rsp");
485 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
486 p_data = p_start + 2;
487
488 /* add fixed lenth - song len(4) + song position(4) + status(1) */
489 UINT16_TO_BE_STREAM(p_data, 9);
490 UINT32_TO_BE_STREAM(p_data, p_rsp->song_len);
491 UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos);
492 UINT8_TO_BE_STREAM(p_data, p_rsp->play_status);
493 p_pkt->len = (p_data - p_start);
494
495 return AVRC_STS_NO_ERROR;
496 }
497
498 /*******************************************************************************
499 **
500 ** Function avrc_bld_notify_rsp
501 **
502 ** Description This function builds the Notification response.
503 **
504 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
505 ** Otherwise, the error code.
506 **
507 *******************************************************************************/
avrc_bld_notify_rsp(tAVRC_REG_NOTIF_RSP * p_rsp,BT_HDR * p_pkt)508 static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt)
509 {
510 UINT8 *p_data, *p_start;
511 UINT8 *p_len;
512 UINT16 len = 0;
513 UINT8 xx;
514 tAVRC_STS status = AVRC_STS_NO_ERROR;
515
516 AVRC_TRACE_API("avrc_bld_notify_rsp");
517
518 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
519 p_data = p_len = p_start + 2; /* pdu + rsvd */
520 p_data += 2;
521
522 UINT8_TO_BE_STREAM(p_data, p_rsp->event_id);
523 switch (p_rsp->event_id) {
524 case AVRC_EVT_PLAY_STATUS_CHANGE: /* 0x01 */
525 /* p_rsp->param.play_status >= AVRC_PLAYSTATE_STOPPED is always TRUE */
526 if ((p_rsp->param.play_status <= AVRC_PLAYSTATE_REV_SEEK) ||
527 (p_rsp->param.play_status == AVRC_PLAYSTATE_ERROR) ) {
528 UINT8_TO_BE_STREAM(p_data, p_rsp->param.play_status);
529 len = 2;
530 } else {
531 AVRC_TRACE_ERROR("bad play state");
532 status = AVRC_STS_BAD_PARAM;
533 }
534 break;
535
536 case AVRC_EVT_TRACK_CHANGE: /* 0x02 */
537 ARRAY_TO_BE_STREAM(p_data, p_rsp->param.track, AVRC_UID_SIZE);
538 len = (UINT8)(AVRC_UID_SIZE + 1);
539 break;
540
541 case AVRC_EVT_TRACK_REACHED_END: /* 0x03 */
542 case AVRC_EVT_TRACK_REACHED_START: /* 0x04 */
543 len = 1;
544 break;
545
546 case AVRC_EVT_PLAY_POS_CHANGED: /* 0x05 */
547 UINT32_TO_BE_STREAM(p_data, p_rsp->param.play_pos);
548 len = 5;
549 break;
550
551 case AVRC_EVT_BATTERY_STATUS_CHANGE: /* 0x06 */
552 if (AVRC_IS_VALID_BATTERY_STATUS(p_rsp->param.battery_status)) {
553 UINT8_TO_BE_STREAM(p_data, p_rsp->param.battery_status);
554 len = 2;
555 } else {
556 AVRC_TRACE_ERROR("bad battery status");
557 status = AVRC_STS_BAD_PARAM;
558 }
559 break;
560
561 case AVRC_EVT_SYSTEM_STATUS_CHANGE: /* 0x07 */
562 if (AVRC_IS_VALID_SYSTEM_STATUS(p_rsp->param.system_status)) {
563 UINT8_TO_BE_STREAM(p_data, p_rsp->param.system_status);
564 len = 2;
565 } else {
566 AVRC_TRACE_ERROR("bad system status");
567 status = AVRC_STS_BAD_PARAM;
568 }
569 break;
570
571 case AVRC_EVT_APP_SETTING_CHANGE: /* 0x08 */
572 if (p_rsp->param.player_setting.num_attr > AVRC_MAX_APP_SETTINGS) {
573 p_rsp->param.player_setting.num_attr = AVRC_MAX_APP_SETTINGS;
574 }
575
576 if (p_rsp->param.player_setting.num_attr > 0) {
577 UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.num_attr);
578 len = 2;
579 for (xx = 0; xx < p_rsp->param.player_setting.num_attr; xx++) {
580 if (avrc_is_valid_player_attrib_value(p_rsp->param.player_setting.attr_id[xx],
581 p_rsp->param.player_setting.attr_value[xx])) {
582 UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_id[xx]);
583 UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_value[xx]);
584 } else {
585 AVRC_TRACE_ERROR("bad player app seeting attribute or value");
586 status = AVRC_STS_BAD_PARAM;
587 break;
588 }
589 len += 2;
590 }
591 } else {
592 status = AVRC_STS_BAD_PARAM;
593 }
594 break;
595
596 case AVRC_EVT_VOLUME_CHANGE:
597 UINT8_TO_BE_STREAM(p_data, p_rsp->param.volume);
598 len = 2;
599 break;
600 default:
601 status = AVRC_STS_BAD_PARAM;
602 AVRC_TRACE_ERROR("unknown event_id");
603 }
604
605 UINT16_TO_BE_STREAM(p_len, len);
606 p_pkt->len = (p_data - p_start);
607
608 return status;
609 }
610
611 /*******************************************************************************
612 **
613 ** Function avrc_bld_next_rsp
614 **
615 ** Description This function builds the Request Continue or Abort
616 ** response.
617 **
618 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
619 ** Otherwise, the error code.
620 **
621 *******************************************************************************/
avrc_bld_next_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)622 static tAVRC_STS avrc_bld_next_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
623 {
624 UNUSED(p_rsp);
625 UNUSED(p_pkt);
626
627 /* nothing to be added. */
628 AVRC_TRACE_API("avrc_bld_next_rsp");
629 return AVRC_STS_NO_ERROR;
630 }
631
632 /*******************************************************************************
633 **
634 ** Function avrc_bld_group_navigation_rsp
635 **
636 ** Description This function builds the Group Navigation
637 ** response.
638 **
639 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
640 ** Otherwise, the error code.
641 **
642 *******************************************************************************/
avrc_bld_group_navigation_rsp(UINT16 navi_id,BT_HDR * p_pkt)643 tAVRC_STS avrc_bld_group_navigation_rsp (UINT16 navi_id, BT_HDR *p_pkt)
644 {
645 UINT8 *p_data;
646
647 if (!AVRC_IS_VALID_GROUP(navi_id)) {
648 AVRC_TRACE_ERROR("avrc_bld_group_navigation_rsp bad navigation op id: %d", navi_id);
649 return AVRC_STS_BAD_PARAM;
650 }
651
652 AVRC_TRACE_API("avrc_bld_group_navigation_rsp");
653 p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
654 UINT16_TO_BE_STREAM(p_data, navi_id);
655 p_pkt->len = 2;
656 return AVRC_STS_NO_ERROR;
657 }
658
659 /*******************************************************************************
660 **
661 ** Function avrc_bld_set_absolute_volume_rsp
662 **
663 ** Description This function builds the Set Absolute Volume command
664 ** response
665 **
666 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
667 ** Otherwise, the error code.
668 **
669 *******************************************************************************/
avrc_bld_set_absolute_volume_rsp(tAVRC_SET_VOLUME_RSP * p_rsp,BT_HDR * p_pkt)670 tAVRC_STS avrc_bld_set_absolute_volume_rsp(tAVRC_SET_VOLUME_RSP *p_rsp, BT_HDR *p_pkt)
671 {
672 UINT8 *p_data, *p_start;
673
674 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
675 p_data = p_start + 2; /* pdu + rsvd */
676 UINT16_TO_BE_STREAM(p_data, 1); /* fixed length 1 */
677 UINT8_TO_BE_STREAM(p_data, p_rsp->volume);
678
679 p_pkt->len = (p_data - p_start);
680
681 return AVRC_STS_NO_ERROR;
682 }
683
684 /*******************************************************************************
685 **
686 ** Function avrc_bld_rejected_rsp
687 **
688 ** Description This function builds the General Response response.
689 **
690 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
691 ** Otherwise, the error code.
692 **
693 *******************************************************************************/
avrc_bld_rejected_rsp(tAVRC_RSP * p_rsp,BT_HDR * p_pkt)694 static tAVRC_STS avrc_bld_rejected_rsp( tAVRC_RSP *p_rsp, BT_HDR *p_pkt )
695 {
696 UINT8 *p_data, *p_start;
697
698 AVRC_TRACE_API("avrc_bld_rejected_rsp: status=%d, pdu:x%x", p_rsp->status, p_rsp->pdu);
699
700 p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
701 p_data = p_start + 2;
702 AVRC_TRACE_DEBUG("pdu:x%x", *p_start);
703
704 UINT16_TO_BE_STREAM(p_data, 1);
705 UINT8_TO_BE_STREAM(p_data, p_rsp->status);
706 p_pkt->len = p_data - p_start;
707
708 return AVRC_STS_NO_ERROR;
709 }
710
711 /*******************************************************************************
712 **
713 ** Function avrc_bld_init_rsp_buffer
714 **
715 ** Description This function initializes the response buffer based on PDU
716 **
717 ** Returns NULL, if no GKI buffer or failure to build the message.
718 ** Otherwise, the GKI buffer that contains the initialized message.
719 **
720 *******************************************************************************/
avrc_bld_init_rsp_buffer(tAVRC_RESPONSE * p_rsp)721 static BT_HDR *avrc_bld_init_rsp_buffer(tAVRC_RESPONSE *p_rsp)
722 {
723 UINT16 offset = AVRC_MSG_PASS_THRU_OFFSET;
724 UINT16 chnl = AVCT_DATA_CTRL;
725 UINT8 opcode = avrc_opcode_from_pdu(p_rsp->pdu);
726
727 AVRC_TRACE_API("avrc_bld_init_rsp_buffer: pdu=%x, opcode=%x/%x", p_rsp->pdu, opcode,
728 p_rsp->rsp.opcode);
729 if (opcode != p_rsp->rsp.opcode && p_rsp->rsp.status != AVRC_STS_NO_ERROR &&
730 avrc_is_valid_opcode(p_rsp->rsp.opcode)) {
731 opcode = p_rsp->rsp.opcode;
732 AVRC_TRACE_API("opcode=%x", opcode);
733 }
734
735 switch (opcode) {
736 case AVRC_OP_PASS_THRU:
737 offset = AVRC_MSG_PASS_THRU_OFFSET;
738 break;
739
740 case AVRC_OP_VENDOR:
741 offset = AVRC_MSG_VENDOR_OFFSET;
742 break;
743 }
744
745 /* allocate and initialize the buffer */
746 BT_HDR *p_pkt = (BT_HDR *)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
747 if (p_pkt) {
748 UINT8 *p_data, *p_start;
749
750 p_pkt->layer_specific = chnl;
751 p_pkt->event = opcode;
752 p_pkt->offset = offset;
753 p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
754 p_start = p_data;
755
756 /* pass thru - group navigation - has a two byte op_id, so dont do it here */
757 if (opcode != AVRC_OP_PASS_THRU) {
758 *p_data++ = p_rsp->pdu;
759 }
760
761 switch (opcode) {
762 case AVRC_OP_VENDOR:
763 /* reserved 0, packet_type 0 */
764 UINT8_TO_BE_STREAM(p_data, 0);
765 /* continue to the next "case to add length */
766 /* add fixed lenth - 0 */
767 UINT16_TO_BE_STREAM(p_data, 0);
768 break;
769 }
770
771 p_pkt->len = (p_data - p_start);
772 }
773 p_rsp->rsp.opcode = opcode;
774 return p_pkt;
775 }
776
777 /*******************************************************************************
778 **
779 ** Function AVRC_BldResponse
780 **
781 ** Description This function builds the given AVRCP response to the given
782 ** GKI buffer
783 **
784 ** Returns AVRC_STS_NO_ERROR, if the response is built successfully
785 ** Otherwise, the error code.
786 **
787 *******************************************************************************/
AVRC_BldResponse(UINT8 handle,tAVRC_RESPONSE * p_rsp,BT_HDR ** pp_pkt)788 tAVRC_STS AVRC_BldResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt)
789 {
790 tAVRC_STS status = AVRC_STS_BAD_PARAM;
791 BT_HDR *p_pkt;
792 BOOLEAN alloc = FALSE;
793 UNUSED(handle);
794
795 if (!p_rsp || !pp_pkt) {
796 AVRC_TRACE_API("AVRC_BldResponse. Invalid parameters passed. p_rsp=%p, pp_pkt=%p",
797 p_rsp, pp_pkt);
798 return AVRC_STS_BAD_PARAM;
799 }
800
801 if (*pp_pkt == NULL) {
802 if ((*pp_pkt = avrc_bld_init_rsp_buffer(p_rsp)) == NULL) {
803 AVRC_TRACE_API("AVRC_BldResponse: Failed to initialize response buffer");
804 return AVRC_STS_INTERNAL_ERR;
805 }
806 alloc = TRUE;
807 }
808 status = AVRC_STS_NO_ERROR;
809 p_pkt = *pp_pkt;
810
811 AVRC_TRACE_API("AVRC_BldResponse: pdu=%x status=%x", p_rsp->rsp.pdu, p_rsp->rsp.status);
812 if (p_rsp->rsp.status != AVRC_STS_NO_ERROR) {
813 return ( avrc_bld_rejected_rsp(&p_rsp->rsp, p_pkt) );
814 }
815
816 switch (p_rsp->pdu) {
817 case AVRC_PDU_NEXT_GROUP:
818 case AVRC_PDU_PREV_GROUP:
819 status = avrc_bld_group_navigation_rsp(p_rsp->pdu, p_pkt);
820 break;
821
822 case AVRC_PDU_GET_CAPABILITIES:
823 status = avrc_bld_get_capability_rsp(&p_rsp->get_caps, p_pkt);
824 break;
825
826 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
827 status = avrc_bld_list_app_settings_attr_rsp(&p_rsp->list_app_attr, p_pkt);
828 break;
829
830 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
831 status = avrc_bld_list_app_settings_values_rsp(&p_rsp->list_app_values, p_pkt);
832 break;
833
834 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
835 status = avrc_bld_get_cur_app_setting_value_rsp(&p_rsp->get_cur_app_val, p_pkt);
836 break;
837
838 case AVRC_PDU_SET_PLAYER_APP_VALUE:
839 status = avrc_bld_set_app_setting_value_rsp(&p_rsp->set_app_val, p_pkt);
840 break;
841
842 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
843 status = avrc_bld_get_app_setting_attr_text_rsp(&p_rsp->get_app_attr_txt, p_pkt);
844 break;
845
846 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
847 status = avrc_bld_get_app_setting_value_text_rsp(&p_rsp->get_app_val_txt, p_pkt);
848 break;
849
850 case AVRC_PDU_INFORM_DISPLAY_CHARSET:
851 status = avrc_bld_inform_charset_rsp(&p_rsp->inform_charset, p_pkt);
852 break;
853
854 case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:
855 status = avrc_bld_inform_battery_status_rsp(&p_rsp->inform_battery_status, p_pkt);
856 break;
857
858 case AVRC_PDU_GET_ELEMENT_ATTR:
859 status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_elem_attrs, p_pkt);
860 break;
861
862 case AVRC_PDU_GET_PLAY_STATUS:
863 status = avrc_bld_get_play_status_rsp(&p_rsp->get_play_status, p_pkt);
864 break;
865
866 case AVRC_PDU_REGISTER_NOTIFICATION:
867 status = avrc_bld_notify_rsp(&p_rsp->reg_notif, p_pkt);
868 break;
869
870 case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
871 status = avrc_bld_next_rsp(&p_rsp->continu, p_pkt);
872 break;
873
874 case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
875 status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt);
876 break;
877 case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
878 status = avrc_bld_set_absolute_volume_rsp(&p_rsp->volume, p_pkt);
879 break;
880 }
881
882 if (alloc && (status != AVRC_STS_NO_ERROR) ) {
883 osi_free(p_pkt);
884 *pp_pkt = NULL;
885 }
886 AVRC_TRACE_API("AVRC_BldResponse: returning %d", status);
887 return status;
888 }
889
890 #endif /* (AVRC_METADATA_INCLUDED == TRUE)*/
891
892 #endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */
893