1 /******************************************************************************
2 *
3 * Copyright (C) 2006-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
20 #include "avrc_api.h"
21 #include "avrc_defs.h"
22 #include "avrc_int.h"
23 #include "bt_common.h"
24 #include "bt_utils.h"
25 #include "osi/include/osi.h"
26
27 /*****************************************************************************
28 * Global data
29 ****************************************************************************/
30
31 #if (AVRC_METADATA_INCLUDED == TRUE)
32
33 /*******************************************************************************
34 *
35 * Function avrc_pars_vendor_rsp
36 *
37 * Description This function parses the vendor specific commands defined by
38 * Bluetooth SIG
39 *
40 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
41 * successfully.
42 * Otherwise, the error code defined by AVRCP 1.4
43 *
44 ******************************************************************************/
avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR * p_msg,tAVRC_RESPONSE * p_result)45 static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg,
46 tAVRC_RESPONSE* p_result) {
47 tAVRC_STS status = AVRC_STS_NO_ERROR;
48 uint8_t* p;
49 uint16_t len;
50 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
51 uint8_t eventid = 0;
52 #endif
53
54 /* Check the vendor data */
55 if (p_msg->vendor_len == 0) return AVRC_STS_NO_ERROR;
56 if (p_msg->p_vendor_data == NULL) return AVRC_STS_INTERNAL_ERR;
57
58 p = p_msg->p_vendor_data;
59 BE_STREAM_TO_UINT8(p_result->pdu, p);
60 p++; /* skip the reserved/packe_type byte */
61 BE_STREAM_TO_UINT16(len, p);
62 AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d/0x%x", __func__,
63 p_msg->hdr.ctype, p_result->pdu, len, len);
64 if (p_msg->hdr.ctype == AVRC_RSP_REJ) {
65 p_result->rsp.status = *p;
66 return p_result->rsp.status;
67 }
68
69 switch (p_result->pdu) {
70 /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
71 /* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */
72
73 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
74 case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
75 if (len != 1)
76 status = AVRC_STS_INTERNAL_ERR;
77 else {
78 BE_STREAM_TO_UINT8(p_result->volume.volume, p);
79 }
80 break;
81 #endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
82
83 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
84 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
85 BE_STREAM_TO_UINT8(eventid, p);
86 if (AVRC_EVT_VOLUME_CHANGE == eventid &&
87 (AVRC_RSP_CHANGED == p_msg->hdr.ctype ||
88 AVRC_RSP_INTERIM == p_msg->hdr.ctype ||
89 AVRC_RSP_REJ == p_msg->hdr.ctype ||
90 AVRC_RSP_NOT_IMPL == p_msg->hdr.ctype)) {
91 p_result->reg_notif.status = p_msg->hdr.ctype;
92 p_result->reg_notif.event_id = eventid;
93 BE_STREAM_TO_UINT8(p_result->reg_notif.param.volume, p);
94 }
95 AVRC_TRACE_DEBUG("%s PDU reg notif response:event %x, volume %x",
96 __func__, eventid, p_result->reg_notif.param.volume);
97 #endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
98 break;
99 default:
100 status = AVRC_STS_BAD_CMD;
101 break;
102 }
103
104 return status;
105 }
106
avrc_parse_notification_rsp(uint8_t * p_stream,tAVRC_REG_NOTIF_RSP * p_rsp)107 void avrc_parse_notification_rsp(uint8_t* p_stream,
108 tAVRC_REG_NOTIF_RSP* p_rsp) {
109 BE_STREAM_TO_UINT8(p_rsp->event_id, p_stream);
110 switch (p_rsp->event_id) {
111 case AVRC_EVT_PLAY_STATUS_CHANGE:
112 BE_STREAM_TO_UINT8(p_rsp->param.play_status, p_stream);
113 break;
114
115 case AVRC_EVT_TRACK_CHANGE:
116 BE_STREAM_TO_ARRAY(p_stream, p_rsp->param.track, 8);
117 break;
118
119 case AVRC_EVT_APP_SETTING_CHANGE:
120 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.num_attr, p_stream);
121 for (int index = 0; index < p_rsp->param.player_setting.num_attr;
122 index++) {
123 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_id[index],
124 p_stream);
125 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_value[index],
126 p_stream);
127 }
128 break;
129
130 case AVRC_EVT_NOW_PLAYING_CHANGE:
131 break;
132
133 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
134 break;
135
136 case AVRC_EVT_ADDR_PLAYER_CHANGE:
137 break;
138
139 case AVRC_EVT_UIDS_CHANGE:
140 break;
141
142 case AVRC_EVT_TRACK_REACHED_END:
143 case AVRC_EVT_TRACK_REACHED_START:
144 case AVRC_EVT_PLAY_POS_CHANGED:
145 case AVRC_EVT_BATTERY_STATUS_CHANGE:
146 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
147 default:
148 break;
149 }
150 }
151
avrc_pars_browse_rsp(tAVRC_MSG_BROWSE * p_msg,tAVRC_RESPONSE * p_rsp)152 static tAVRC_STS avrc_pars_browse_rsp(tAVRC_MSG_BROWSE* p_msg,
153 tAVRC_RESPONSE* p_rsp) {
154 tAVRC_STS status = AVRC_STS_NO_ERROR;
155 uint8_t pdu;
156
157 if (p_msg->browse_len == 0) {
158 AVRC_TRACE_ERROR("%s length ", p_msg->browse_len);
159 return AVRC_STS_BAD_PARAM;
160 }
161
162 uint8_t* p = p_msg->p_browse_data;
163
164 /* read the pdu */
165 BE_STREAM_TO_UINT8(pdu, p);
166 uint16_t pkt_len;
167 /* read the entire packet len */
168 BE_STREAM_TO_UINT16(pkt_len, p);
169
170 AVRC_TRACE_DEBUG("%s pdu %d", __func__, pdu);
171
172 /* used to track how much we have read, if we cannot read anymore but the
173 * packet says so then we have a malformed packet. Also vice versa. */
174 uint16_t pkt_len_read = 0;
175
176 switch (pdu) {
177 case AVRC_PDU_GET_FOLDER_ITEMS: {
178 tAVRC_GET_ITEMS_RSP* get_item_rsp = &(p_rsp->get_items);
179 /* Copy back the PDU */
180 get_item_rsp->pdu = pdu;
181 /* read the status */
182 BE_STREAM_TO_UINT8(get_item_rsp->status, p);
183 /* read the UID counter */
184 BE_STREAM_TO_UINT16(get_item_rsp->uid_counter, p);
185 /* read the number of items */
186 BE_STREAM_TO_UINT16(get_item_rsp->item_count, p);
187 pkt_len_read += 5;
188
189 AVRC_TRACE_DEBUG(
190 "%s pdu %d status %d pkt_len %d uid counter %d item count %d",
191 __func__, get_item_rsp->pdu, get_item_rsp->status, pkt_len,
192 get_item_rsp->uid_counter, get_item_rsp->item_count);
193
194 if (get_item_rsp->status != AVRC_STS_NO_ERROR) {
195 AVRC_TRACE_WARNING("%s returning error %d", __func__,
196 get_item_rsp->status);
197 return get_item_rsp->status;
198 }
199
200 /* get each of the items */
201 get_item_rsp->p_item_list = (tAVRC_ITEM*)osi_malloc(
202 get_item_rsp->item_count * (sizeof(tAVRC_ITEM)));
203 tAVRC_ITEM* curr_item = get_item_rsp->p_item_list;
204 for (int i = 0; i < get_item_rsp->item_count; i++) {
205 BE_STREAM_TO_UINT8(curr_item->item_type, p);
206 pkt_len_read += 1;
207 AVRC_TRACE_DEBUG("%s item type %d", __func__, curr_item->item_type);
208 switch (curr_item->item_type) {
209 case AVRC_ITEM_PLAYER: {
210 /* Handle player */
211 tAVRC_ITEM_PLAYER* player = &(curr_item->u.player);
212 uint8_t player_len;
213 BE_STREAM_TO_UINT16(player_len, p);
214 BE_STREAM_TO_UINT16(player->player_id, p);
215 BE_STREAM_TO_UINT8(player->major_type, p);
216 BE_STREAM_TO_UINT32(player->sub_type, p);
217 BE_STREAM_TO_UINT8(player->play_status, p);
218 BE_STREAM_TO_ARRAY(p, player->features, AVRC_FEATURE_MASK_SIZE);
219 pkt_len_read += (10 + AVRC_FEATURE_MASK_SIZE);
220
221 /* read str */
222 BE_STREAM_TO_UINT16(player->name.charset_id, p);
223 BE_STREAM_TO_UINT16(player->name.str_len, p);
224 player->name.p_str = (uint8_t*)osi_malloc(
225 (player->name.str_len + 1) * sizeof(uint8_t));
226 BE_STREAM_TO_ARRAY(p, player->name.p_str, player->name.str_len);
227 pkt_len_read += (4 + player->name.str_len);
228 AVRC_TRACE_DEBUG(
229 "%s type %d id %d mtype %d stype %d ps %d cs %d name len %d",
230 __func__, curr_item->item_type, player->player_id,
231 player->major_type, player->sub_type, player->play_status,
232 player->name.charset_id, player->name.str_len);
233 } break;
234
235 case AVRC_ITEM_FOLDER: {
236 tAVRC_ITEM_FOLDER* folder = &(curr_item->u.folder);
237 uint16_t folder_len;
238 BE_STREAM_TO_UINT16(folder_len, p);
239
240 BE_STREAM_TO_ARRAY(p, folder->uid, AVRC_UID_SIZE);
241 BE_STREAM_TO_UINT8(folder->type, p);
242 BE_STREAM_TO_UINT8(folder->playable, p);
243 pkt_len_read += (4 + AVRC_UID_SIZE);
244
245 /* read str, encoding to be handled by upper layers */
246 BE_STREAM_TO_UINT16(folder->name.charset_id, p);
247 BE_STREAM_TO_UINT16(folder->name.str_len, p);
248 folder->name.p_str = (uint8_t*)osi_malloc(
249 (folder->name.str_len + 1) * sizeof(uint8_t));
250 BE_STREAM_TO_ARRAY(p, folder->name.p_str, folder->name.str_len);
251 pkt_len_read += (4 + folder->name.str_len);
252 AVRC_TRACE_DEBUG("%s type %d playable %d cs %d name len %d",
253 __func__, folder->type, folder->playable,
254 folder->name.charset_id, folder->name.str_len);
255 } break;
256
257 case AVRC_ITEM_MEDIA: {
258 tAVRC_ITEM_MEDIA* media = &(curr_item->u.media);
259 uint8_t media_len;
260 BE_STREAM_TO_UINT16(media_len, p);
261 BE_STREAM_TO_ARRAY(p, media->uid, AVRC_UID_SIZE);
262 BE_STREAM_TO_UINT8(media->type, p);
263 pkt_len_read += (3 + AVRC_UID_SIZE);
264
265 /* read str, encoding to be handled by upper layers */
266 BE_STREAM_TO_UINT16(media->name.charset_id, p);
267 BE_STREAM_TO_UINT16(media->name.str_len, p);
268 media->name.p_str =
269 (uint8_t*)osi_malloc((media->name.str_len) * sizeof(uint8_t));
270 BE_STREAM_TO_ARRAY(p, media->name.p_str, media->name.str_len);
271
272 BE_STREAM_TO_UINT8(media->attr_count, p);
273 AVRC_TRACE_DEBUG("%s media type %d charset id %d len %d attr ct %d",
274 __func__, media->type, media->name.charset_id,
275 media->name.str_len, media->attr_count);
276 pkt_len_read += (5 + media->name.str_len);
277
278 media->p_attr_list = (tAVRC_ATTR_ENTRY*)osi_malloc(
279 media->attr_count * sizeof(tAVRC_ATTR_ENTRY));
280 for (int jk = 0; jk < media->attr_count; jk++) {
281 tAVRC_ATTR_ENTRY* attr_entry = &(media->p_attr_list[jk]);
282 BE_STREAM_TO_UINT32(attr_entry->attr_id, p);
283
284 /* Parse the name now */
285 BE_STREAM_TO_UINT16(attr_entry->name.charset_id, p);
286 BE_STREAM_TO_UINT16(attr_entry->name.str_len, p);
287 attr_entry->name.p_str = (uint8_t*)osi_malloc(
288 attr_entry->name.str_len * sizeof(uint8_t));
289 BE_STREAM_TO_ARRAY(p, attr_entry->name.p_str,
290 attr_entry->name.str_len);
291 pkt_len_read += (8 + attr_entry->name.str_len);
292 AVRC_TRACE_DEBUG("%s media attr id %d cs %d name len %d",
293 __func__, attr_entry->attr_id,
294 attr_entry->name.charset_id,
295 attr_entry->name.str_len);
296 }
297 } break;
298
299 default:
300 AVRC_TRACE_ERROR("%s item type not handled %d", __func__,
301 curr_item->item_type);
302 return AVRC_STS_INTERNAL_ERR;
303 }
304
305 /* we check if we have overrun */
306 if (pkt_len_read > pkt_len) {
307 AVRC_TRACE_ERROR("%s overflow in read pkt_len %d pkt_len_read %d",
308 __func__, pkt_len, pkt_len_read);
309 return AVRC_STS_BAD_CMD;
310 }
311 AVRC_TRACE_DEBUG("%s pkt_len %d pkt_len_read %d", __func__, pkt_len,
312 pkt_len_read);
313
314 /* advance to populate the next item */
315 curr_item++;
316 }
317 break;
318 }
319
320 case AVRC_PDU_CHANGE_PATH: {
321 tAVRC_CHG_PATH_RSP* change_path_rsp = &(p_rsp->chg_path);
322 /* Copyback the PDU */
323 change_path_rsp->pdu = pdu;
324 /* Read the status */
325 BE_STREAM_TO_UINT8(change_path_rsp->status, p);
326 /* Read the number of items in folder */
327 BE_STREAM_TO_UINT32(change_path_rsp->num_items, p);
328 pkt_len_read += 5;
329
330 AVRC_TRACE_DEBUG("%s pdu %d status %d item count %d", __func__,
331 change_path_rsp->pdu, change_path_rsp->status,
332 change_path_rsp->num_items);
333 break;
334 }
335
336 case AVRC_PDU_SET_BROWSED_PLAYER: {
337 tAVRC_SET_BR_PLAYER_RSP* set_br_pl_rsp = &(p_rsp->br_player);
338 /* Copyback the PDU */
339 set_br_pl_rsp->pdu = pdu;
340
341 /* Read the status */
342 BE_STREAM_TO_UINT8(set_br_pl_rsp->status, p);
343
344 if (set_br_pl_rsp->status != AVRC_STS_NO_ERROR) {
345 AVRC_TRACE_ERROR(
346 "%s Stopping further parsing because player not browsable sts %d",
347 __func__, set_br_pl_rsp->status);
348 break;
349 }
350 BE_STREAM_TO_UINT16(set_br_pl_rsp->uid_counter, p);
351 BE_STREAM_TO_UINT32(set_br_pl_rsp->num_items, p);
352 BE_STREAM_TO_UINT16(set_br_pl_rsp->charset_id, p);
353 BE_STREAM_TO_UINT8(set_br_pl_rsp->folder_depth, p);
354 AVRC_TRACE_DEBUG(
355 "%s AVRC_PDU_SET_BROWSED_PLAYER status %d items %d cs %d depth %d",
356 __func__, set_br_pl_rsp->status, set_br_pl_rsp->num_items,
357 set_br_pl_rsp->charset_id, set_br_pl_rsp->folder_depth);
358 pkt_len_read += 10;
359
360 set_br_pl_rsp->p_folders = (tAVRC_NAME*)osi_malloc(
361 set_br_pl_rsp->num_items * sizeof(tAVRC_NAME));
362
363 /* Read each of the folder in the depth */
364 for (uint32_t i = 0; i < set_br_pl_rsp->folder_depth; i++) {
365 tAVRC_NAME* folder_name = &(set_br_pl_rsp->p_folders[i]);
366 BE_STREAM_TO_UINT16(folder_name->str_len, p);
367 AVRC_TRACE_DEBUG("%s AVRC_PDU_SET_BROWSED_PLAYER item: %d len: %d",
368 __func__, i, folder_name->str_len);
369 folder_name->p_str =
370 (uint8_t*)osi_malloc((folder_name->str_len + 1) * sizeof(uint8_t));
371 BE_STREAM_TO_ARRAY(p, folder_name->p_str, folder_name->str_len);
372 pkt_len_read += (2 + folder_name->str_len);
373 }
374 break;
375 }
376
377 default:
378 AVRC_TRACE_ERROR("%s pdu %d not handled", __func__, pdu);
379 }
380
381 if (pkt_len != pkt_len_read) {
382 AVRC_TRACE_ERROR("%s finished pkt_len %d pkt_len_read %d", __func__,
383 pkt_len, pkt_len_read);
384 return AVRC_STS_BAD_CMD;
385 }
386 return status;
387 }
388
389 /*******************************************************************************
390 *
391 * Function avrc_ctrl_pars_vendor_rsp
392 *
393 * Description This function parses the vendor specific commands defined by
394 * Bluetooth SIG
395 *
396 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
397 * successfully.
398 * Otherwise, the error code defined by AVRCP 1.4
399 *
400 ******************************************************************************/
avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR * p_msg,tAVRC_RESPONSE * p_result,uint8_t * p_buf,uint16_t * buf_len)401 static tAVRC_STS avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg,
402 tAVRC_RESPONSE* p_result,
403 uint8_t* p_buf, uint16_t* buf_len) {
404 uint8_t* p = p_msg->p_vendor_data;
405 BE_STREAM_TO_UINT8(p_result->pdu, p);
406 p++; /* skip the reserved/packe_type byte */
407
408 uint16_t len;
409 BE_STREAM_TO_UINT16(len, p);
410 AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d", __func__, p_msg->hdr.ctype,
411 p_result->pdu, len);
412 /* Todo: Issue in handling reject, check */
413 if (p_msg->hdr.ctype == AVRC_RSP_REJ) {
414 p_result->rsp.status = *p;
415 return p_result->rsp.status;
416 }
417
418 /* TODO: Break the big switch into functions. */
419 switch (p_result->pdu) {
420 /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
421 /* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */
422
423 case AVRC_PDU_REGISTER_NOTIFICATION:
424 avrc_parse_notification_rsp(p, &p_result->reg_notif);
425 break;
426
427 case AVRC_PDU_GET_CAPABILITIES:
428 if (len == 0) {
429 p_result->get_caps.count = 0;
430 p_result->get_caps.capability_id = 0;
431 break;
432 }
433 BE_STREAM_TO_UINT8(p_result->get_caps.capability_id, p);
434 BE_STREAM_TO_UINT8(p_result->get_caps.count, p);
435 AVRC_TRACE_DEBUG("%s cap id = %d, cap_count = %d ", __func__,
436 p_result->get_caps.capability_id,
437 p_result->get_caps.count);
438 if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID) {
439 for (int xx = 0; ((xx < p_result->get_caps.count) &&
440 (xx < AVRC_CAP_MAX_NUM_COMP_ID));
441 xx++) {
442 BE_STREAM_TO_UINT24(p_result->get_caps.param.company_id[xx], p);
443 }
444 } else if (p_result->get_caps.capability_id ==
445 AVRC_CAP_EVENTS_SUPPORTED) {
446 for (int xx = 0; ((xx < p_result->get_caps.count) &&
447 (xx < AVRC_CAP_MAX_NUM_EVT_ID));
448 xx++) {
449 BE_STREAM_TO_UINT8(p_result->get_caps.param.event_id[xx], p);
450 }
451 }
452 break;
453
454 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
455 if (len == 0) {
456 p_result->list_app_attr.num_attr = 0;
457 break;
458 }
459 BE_STREAM_TO_UINT8(p_result->list_app_attr.num_attr, p);
460 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__,
461 p_result->list_app_attr.num_attr);
462 for (int xx = 0; xx < p_result->list_app_attr.num_attr; xx++) {
463 BE_STREAM_TO_UINT8(p_result->list_app_attr.attrs[xx], p);
464 }
465 break;
466
467 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
468 if (len == 0) {
469 p_result->list_app_values.num_val = 0;
470 break;
471 }
472 BE_STREAM_TO_UINT8(p_result->list_app_values.num_val, p);
473 AVRC_TRACE_DEBUG("%s value count = %d ", __func__,
474 p_result->list_app_values.num_val);
475 for (int xx = 0; xx < p_result->list_app_values.num_val; xx++) {
476 BE_STREAM_TO_UINT8(p_result->list_app_values.vals[xx], p);
477 }
478 break;
479
480 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: {
481 if (len == 0) {
482 p_result->get_cur_app_val.num_val = 0;
483 break;
484 }
485 BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_val, p);
486 tAVRC_APP_SETTING* app_sett = (tAVRC_APP_SETTING*)osi_malloc(
487 p_result->get_cur_app_val.num_val * sizeof(tAVRC_APP_SETTING));
488 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__,
489 p_result->get_cur_app_val.num_val);
490 for (int xx = 0; xx < p_result->get_cur_app_val.num_val; xx++) {
491 BE_STREAM_TO_UINT8(app_sett[xx].attr_id, p);
492 BE_STREAM_TO_UINT8(app_sett[xx].attr_val, p);
493 }
494 p_result->get_cur_app_val.p_vals = app_sett;
495 } break;
496
497 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: {
498 tAVRC_APP_SETTING_TEXT* p_setting_text;
499 uint8_t num_attrs;
500
501 if (len == 0) {
502 p_result->get_app_attr_txt.num_attr = 0;
503 break;
504 }
505 BE_STREAM_TO_UINT8(num_attrs, p);
506 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__,
507 p_result->get_app_attr_txt.num_attr);
508 p_result->get_app_attr_txt.num_attr = num_attrs;
509 p_setting_text = (tAVRC_APP_SETTING_TEXT*)osi_malloc(
510 num_attrs * sizeof(tAVRC_APP_SETTING_TEXT));
511 for (int xx = 0; xx < num_attrs; xx++) {
512 BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].attr_id, p);
513 BE_STREAM_TO_UINT16(p_result->get_app_attr_txt.p_attrs[xx].charset_id,
514 p);
515 BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].str_len, p);
516 if (p_result->get_app_attr_txt.p_attrs[xx].str_len != 0) {
517 uint8_t* p_str = (uint8_t*)osi_malloc(
518 p_result->get_app_attr_txt.p_attrs[xx].str_len);
519 BE_STREAM_TO_ARRAY(p, p_str,
520 p_result->get_app_attr_txt.p_attrs[xx].str_len);
521 p_result->get_app_attr_txt.p_attrs[xx].p_str = p_str;
522 } else {
523 p_result->get_app_attr_txt.p_attrs[xx].p_str = NULL;
524 }
525 }
526 } break;
527
528 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: {
529 tAVRC_APP_SETTING_TEXT* p_setting_text;
530 uint8_t num_vals;
531
532 if (len == 0) {
533 p_result->get_app_val_txt.num_attr = 0;
534 break;
535 }
536 BE_STREAM_TO_UINT8(num_vals, p);
537 p_result->get_app_val_txt.num_attr = num_vals;
538 AVRC_TRACE_DEBUG("%s value count = %d ", __func__,
539 p_result->get_app_val_txt.num_attr);
540
541 p_setting_text = (tAVRC_APP_SETTING_TEXT*)osi_malloc(
542 num_vals * sizeof(tAVRC_APP_SETTING_TEXT));
543 for (int i = 0; i < num_vals; i++) {
544 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].attr_id, p);
545 BE_STREAM_TO_UINT16(p_result->get_app_val_txt.p_attrs[i].charset_id, p);
546 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].str_len, p);
547 if (p_result->get_app_val_txt.p_attrs[i].str_len != 0) {
548 uint8_t* p_str = (uint8_t*)osi_malloc(
549 p_result->get_app_val_txt.p_attrs[i].str_len);
550 BE_STREAM_TO_ARRAY(p, p_str,
551 p_result->get_app_val_txt.p_attrs[i].str_len);
552 p_result->get_app_val_txt.p_attrs[i].p_str = p_str;
553 } else {
554 p_result->get_app_val_txt.p_attrs[i].p_str = NULL;
555 }
556 }
557 } break;
558
559 case AVRC_PDU_SET_PLAYER_APP_VALUE:
560 /* nothing comes as part of this rsp */
561 break;
562
563 case AVRC_PDU_GET_ELEMENT_ATTR: {
564 uint8_t num_attrs;
565
566 if (len <= 0) {
567 p_result->get_attrs.num_attrs = 0;
568 break;
569 }
570 BE_STREAM_TO_UINT8(num_attrs, p);
571 p_result->get_attrs.num_attrs = num_attrs;
572 if (num_attrs) {
573 tAVRC_ATTR_ENTRY* p_attrs =
574 (tAVRC_ATTR_ENTRY*)osi_malloc(num_attrs * sizeof(tAVRC_ATTR_ENTRY));
575 for (int i = 0; i < num_attrs; i++) {
576 BE_STREAM_TO_UINT32(p_attrs[i].attr_id, p);
577 BE_STREAM_TO_UINT16(p_attrs[i].name.charset_id, p);
578 BE_STREAM_TO_UINT16(p_attrs[i].name.str_len, p);
579 if (p_attrs[i].name.str_len > 0) {
580 p_attrs[i].name.p_str =
581 (uint8_t*)osi_malloc(p_attrs[i].name.str_len);
582 BE_STREAM_TO_ARRAY(p, p_attrs[i].name.p_str,
583 p_attrs[i].name.str_len);
584 }
585 }
586 p_result->get_attrs.p_attrs = p_attrs;
587 }
588 } break;
589
590 case AVRC_PDU_GET_PLAY_STATUS:
591 if (len == 0) {
592 break;
593 }
594 BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p);
595 BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p);
596 BE_STREAM_TO_UINT8(p_result->get_play_status.status, p);
597 break;
598
599 case AVRC_PDU_SET_ADDRESSED_PLAYER:
600 if (len != 1) {
601 AVRC_TRACE_ERROR("%s pdu: %d len %d", __func__, p_result->pdu, len);
602 return AVRC_STS_BAD_CMD;
603 }
604 BE_STREAM_TO_UINT8(p_result->rsp.status, p);
605 break;
606
607 default:
608 return AVRC_STS_BAD_CMD;
609 }
610 return AVRC_STS_NO_ERROR;
611 }
612
613 /*******************************************************************************
614 *
615 * Function AVRC_Ctrl_ParsResponse
616 *
617 * Description This function is a parse response for AVRCP Controller.
618 *
619 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
620 * successfully.
621 * Otherwise, the error code defined by AVRCP 1.4
622 *
623 ******************************************************************************/
AVRC_Ctrl_ParsResponse(tAVRC_MSG * p_msg,tAVRC_RESPONSE * p_result,uint8_t * p_buf,uint16_t * buf_len)624 tAVRC_STS AVRC_Ctrl_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result,
625 uint8_t* p_buf, uint16_t* buf_len) {
626 tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
627 if (p_msg && p_result) {
628 switch (p_msg->hdr.opcode) {
629 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */
630 status =
631 avrc_ctrl_pars_vendor_rsp(&p_msg->vendor, p_result, p_buf, buf_len);
632 break;
633
634 case AVRC_OP_BROWSE: /* 0xff Browse commands */
635 status = avrc_pars_browse_rsp(&p_msg->browse, p_result);
636 break;
637
638 default:
639 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
640 break;
641 }
642 p_result->rsp.opcode = p_msg->hdr.opcode;
643 p_result->rsp.status = status;
644 }
645 return status;
646 }
647
648 /*******************************************************************************
649 *
650 * Function AVRC_ParsResponse
651 *
652 * Description This function is a superset of AVRC_ParsMetadata to parse
653 * the response.
654 *
655 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
656 * successfully.
657 * Otherwise, the error code defined by AVRCP 1.4
658 *
659 ******************************************************************************/
AVRC_ParsResponse(tAVRC_MSG * p_msg,tAVRC_RESPONSE * p_result,UNUSED_ATTR uint8_t * p_buf,UNUSED_ATTR uint16_t buf_len)660 tAVRC_STS AVRC_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result,
661 UNUSED_ATTR uint8_t* p_buf,
662 UNUSED_ATTR uint16_t buf_len) {
663 tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
664 uint16_t id;
665
666 if (p_msg && p_result) {
667 switch (p_msg->hdr.opcode) {
668 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */
669 status = avrc_pars_vendor_rsp(&p_msg->vendor, p_result);
670 break;
671
672 case AVRC_OP_PASS_THRU: /* 0x7C panel subunit opcode */
673 status = avrc_pars_pass_thru(&p_msg->pass, &id);
674 if (status == AVRC_STS_NO_ERROR) {
675 p_result->pdu = (uint8_t)id;
676 }
677 break;
678
679 default:
680 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
681 break;
682 }
683 p_result->rsp.opcode = p_msg->hdr.opcode;
684 p_result->rsp.status = status;
685 }
686 return status;
687 }
688 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */
689