1 /******************************************************************************
2 *
3 * Copyright 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 "log/log.h"
26 #include "osi/include/osi.h"
27
28 /*****************************************************************************
29 * Global data
30 ****************************************************************************/
31
32 #define MIN(x, y) ((x) < (y) ? (x) : (y))
33
34 /*******************************************************************************
35 *
36 * Function avrc_pars_vendor_rsp
37 *
38 * Description This function parses the vendor specific commands defined by
39 * Bluetooth SIG
40 *
41 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
42 * successfully.
43 * Otherwise, the error code defined by AVRCP 1.4
44 *
45 ******************************************************************************/
avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR * p_msg,tAVRC_RESPONSE * p_result)46 static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg,
47 tAVRC_RESPONSE* p_result) {
48 tAVRC_STS status = AVRC_STS_NO_ERROR;
49 uint8_t* p;
50 uint16_t len;
51 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
52 uint8_t eventid = 0;
53 #endif
54
55 /* Check the vendor data */
56 if (p_msg->vendor_len == 0) return AVRC_STS_NO_ERROR;
57 if (p_msg->p_vendor_data == NULL) return AVRC_STS_INTERNAL_ERR;
58
59 if (p_msg->vendor_len < 4) {
60 android_errorWriteLog(0x534e4554, "111450531");
61 AVRC_TRACE_WARNING("%s: message length %d too short: must be at least 4",
62 __func__, p_msg->vendor_len);
63 return AVRC_STS_INTERNAL_ERR;
64 }
65 p = p_msg->p_vendor_data;
66 BE_STREAM_TO_UINT8(p_result->pdu, p);
67 p++; /* skip the reserved/packe_type byte */
68 BE_STREAM_TO_UINT16(len, p);
69 AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d/0x%x vendor_len=0x%x",
70 __func__, p_msg->hdr.ctype, p_result->pdu, len, len,
71 p_msg->vendor_len);
72 if (p_msg->vendor_len < len + 4) {
73 android_errorWriteLog(0x534e4554, "111450531");
74 AVRC_TRACE_WARNING("%s: message length %d too short: must be at least %d",
75 __func__, p_msg->vendor_len, len + 4);
76 return AVRC_STS_INTERNAL_ERR;
77 }
78
79 if (p_msg->hdr.ctype == AVRC_RSP_REJ) {
80 if (len < 1) {
81 android_errorWriteLog(0x534e4554, "111450531");
82 AVRC_TRACE_WARNING("%s: invalid parameter length %d: must be at least 1",
83 __func__, len);
84 return AVRC_STS_INTERNAL_ERR;
85 }
86 p_result->rsp.status = *p;
87 return p_result->rsp.status;
88 }
89
90 switch (p_result->pdu) {
91 /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
92 /* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */
93
94 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
95 case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
96 if (len != 1)
97 status = AVRC_STS_INTERNAL_ERR;
98 else {
99 BE_STREAM_TO_UINT8(p_result->volume.volume, p);
100 }
101 break;
102 #endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
103
104 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
105 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
106 if (len < 1) {
107 android_errorWriteLog(0x534e4554, "111450531");
108 AVRC_TRACE_WARNING(
109 "%s: invalid parameter length %d: must be at least 1", __func__,
110 len);
111 return AVRC_STS_INTERNAL_ERR;
112 }
113 BE_STREAM_TO_UINT8(eventid, p);
114 if (AVRC_EVT_VOLUME_CHANGE == eventid &&
115 (AVRC_RSP_CHANGED == p_msg->hdr.ctype ||
116 AVRC_RSP_INTERIM == p_msg->hdr.ctype ||
117 AVRC_RSP_REJ == p_msg->hdr.ctype ||
118 AVRC_RSP_NOT_IMPL == p_msg->hdr.ctype)) {
119 if (len < 2) {
120 android_errorWriteLog(0x534e4554, "111450531");
121 AVRC_TRACE_WARNING(
122 "%s: invalid parameter length %d: must be at least 2", __func__,
123 len);
124 return AVRC_STS_INTERNAL_ERR;
125 }
126 p_result->reg_notif.status = p_msg->hdr.ctype;
127 p_result->reg_notif.event_id = eventid;
128 BE_STREAM_TO_UINT8(p_result->reg_notif.param.volume, p);
129 }
130 AVRC_TRACE_DEBUG("%s PDU reg notif response:event %x, volume %x",
131 __func__, eventid, p_result->reg_notif.param.volume);
132 #endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
133 break;
134 default:
135 status = AVRC_STS_BAD_CMD;
136 break;
137 }
138
139 return status;
140 }
141
avrc_parse_notification_rsp(uint8_t * p_stream,uint16_t len,tAVRC_REG_NOTIF_RSP * p_rsp)142 tAVRC_STS avrc_parse_notification_rsp(uint8_t* p_stream, uint16_t len,
143 tAVRC_REG_NOTIF_RSP* p_rsp) {
144 uint16_t min_len = 1;
145
146 if (len < min_len) goto length_error;
147 BE_STREAM_TO_UINT8(p_rsp->event_id, p_stream);
148 switch (p_rsp->event_id) {
149 case AVRC_EVT_PLAY_STATUS_CHANGE:
150 min_len += 1;
151 if (len < min_len) goto length_error;
152 BE_STREAM_TO_UINT8(p_rsp->param.play_status, p_stream);
153 break;
154
155 case AVRC_EVT_TRACK_CHANGE:
156 min_len += 8;
157 if (len < min_len) goto length_error;
158 BE_STREAM_TO_ARRAY(p_stream, p_rsp->param.track, 8);
159 break;
160
161 case AVRC_EVT_APP_SETTING_CHANGE:
162 min_len += 1;
163 if (len < min_len) goto length_error;
164 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.num_attr, p_stream);
165 if (p_rsp->param.player_setting.num_attr > AVRC_MAX_APP_SETTINGS) {
166 android_errorWriteLog(0x534e4554, "73782082");
167 p_rsp->param.player_setting.num_attr = AVRC_MAX_APP_SETTINGS;
168 }
169 min_len += p_rsp->param.player_setting.num_attr * 2;
170 if (len < min_len) goto length_error;
171 for (int index = 0; index < p_rsp->param.player_setting.num_attr;
172 index++) {
173 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_id[index],
174 p_stream);
175 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_value[index],
176 p_stream);
177 }
178 break;
179
180 case AVRC_EVT_NOW_PLAYING_CHANGE:
181 break;
182
183 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
184 break;
185
186 case AVRC_EVT_ADDR_PLAYER_CHANGE:
187 break;
188
189 case AVRC_EVT_UIDS_CHANGE:
190 break;
191
192 case AVRC_EVT_TRACK_REACHED_END:
193 case AVRC_EVT_TRACK_REACHED_START:
194 case AVRC_EVT_PLAY_POS_CHANGED:
195 case AVRC_EVT_BATTERY_STATUS_CHANGE:
196 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
197 default:
198 break;
199 }
200
201 return AVRC_STS_NO_ERROR;
202
203 length_error:
204 android_errorWriteLog(0x534e4554, "111450417");
205 AVRC_TRACE_WARNING("%s: invalid parameter length %d: must be at least %d",
206 __func__, len, min_len);
207 return AVRC_STS_INTERNAL_ERR;
208 }
209
avrc_pars_browse_rsp(tAVRC_MSG_BROWSE * p_msg,tAVRC_RESPONSE * p_rsp)210 static tAVRC_STS avrc_pars_browse_rsp(tAVRC_MSG_BROWSE* p_msg,
211 tAVRC_RESPONSE* p_rsp) {
212 tAVRC_STS status = AVRC_STS_NO_ERROR;
213 uint8_t pdu;
214
215 if (p_msg->browse_len == 0) {
216 AVRC_TRACE_ERROR("%s length ", p_msg->browse_len);
217 return AVRC_STS_BAD_PARAM;
218 }
219
220 uint8_t* p = p_msg->p_browse_data;
221
222 /* read the pdu */
223 if (p_msg->browse_len < 3) {
224 android_errorWriteLog(0x534e4554, "111451066");
225 AVRC_TRACE_WARNING("%s: message length %d too short: must be at least 3",
226 __func__, p_msg->browse_len);
227 return AVRC_STS_BAD_PARAM;
228 }
229 BE_STREAM_TO_UINT8(pdu, p);
230 uint16_t pkt_len;
231 int min_len = 0;
232 /* read the entire packet len */
233 BE_STREAM_TO_UINT16(pkt_len, p);
234
235 AVRC_TRACE_DEBUG("%s pdu:%d, pkt_len:%d", __func__, pdu, pkt_len);
236
237 if (p_msg->browse_len < (pkt_len + 3)) {
238 android_errorWriteLog(0x534e4554, "111451066");
239 AVRC_TRACE_WARNING("%s: message length %d too short: must be at least %d",
240 __func__, p_msg->browse_len, pkt_len + 3);
241 return AVRC_STS_INTERNAL_ERR;
242 }
243
244 switch (pdu) {
245 case AVRC_PDU_GET_FOLDER_ITEMS: {
246 tAVRC_GET_ITEMS_RSP* get_item_rsp = &(p_rsp->get_items);
247 /* Copy back the PDU */
248 get_item_rsp->pdu = pdu;
249
250 min_len += 1;
251 if (pkt_len < min_len) goto browse_length_error;
252 /* read the status */
253 BE_STREAM_TO_UINT8(get_item_rsp->status, p);
254 if (get_item_rsp->status != AVRC_STS_NO_ERROR) {
255 AVRC_TRACE_WARNING("%s returning error %d", __func__,
256 get_item_rsp->status);
257 return get_item_rsp->status;
258 }
259
260 min_len += 4;
261 if (pkt_len < min_len) goto browse_length_error;
262 /* read the UID counter */
263 BE_STREAM_TO_UINT16(get_item_rsp->uid_counter, p);
264 /* read the number of items */
265 BE_STREAM_TO_UINT16(get_item_rsp->item_count, p);
266
267 AVRC_TRACE_DEBUG(
268 "%s pdu %d status %d pkt_len %d uid counter %d item count %d",
269 __func__, get_item_rsp->pdu, get_item_rsp->status, pkt_len,
270 get_item_rsp->uid_counter, get_item_rsp->item_count);
271
272 /* get each of the items */
273 get_item_rsp->p_item_list = (tAVRC_ITEM*)osi_malloc(
274 get_item_rsp->item_count * (sizeof(tAVRC_ITEM)));
275 tAVRC_ITEM* curr_item = get_item_rsp->p_item_list;
276 for (int i = 0; i < get_item_rsp->item_count; i++) {
277 min_len += 1;
278 if (pkt_len < min_len) goto browse_length_error;
279 BE_STREAM_TO_UINT8(curr_item->item_type, p);
280 AVRC_TRACE_DEBUG("%s item type %d", __func__, curr_item->item_type);
281 switch (curr_item->item_type) {
282 case AVRC_ITEM_PLAYER: {
283 /* Handle player */
284 tAVRC_ITEM_PLAYER* player = &(curr_item->u.player);
285 uint8_t player_len;
286 min_len += 10 + AVRC_FEATURE_MASK_SIZE;
287 if (pkt_len < min_len) goto browse_length_error;
288 BE_STREAM_TO_UINT16(player_len, p);
289 BE_STREAM_TO_UINT16(player->player_id, p);
290 BE_STREAM_TO_UINT8(player->major_type, p);
291 BE_STREAM_TO_UINT32(player->sub_type, p);
292 BE_STREAM_TO_UINT8(player->play_status, p);
293 BE_STREAM_TO_ARRAY(p, player->features, AVRC_FEATURE_MASK_SIZE);
294
295 /* read str */
296 min_len += 4;
297 if (pkt_len < min_len) goto browse_length_error;
298 BE_STREAM_TO_UINT16(player->name.charset_id, p);
299 BE_STREAM_TO_UINT16(player->name.str_len, p);
300 min_len += player->name.str_len;
301 if (pkt_len < min_len) goto browse_length_error;
302 player->name.p_str = (uint8_t*)osi_malloc(
303 (player->name.str_len + 1) * sizeof(uint8_t));
304 BE_STREAM_TO_ARRAY(p, player->name.p_str, player->name.str_len);
305 AVRC_TRACE_DEBUG(
306 "%s type %d id %d mtype %d stype %d ps %d cs %d name len %d",
307 __func__, curr_item->item_type, player->player_id,
308 player->major_type, player->sub_type, player->play_status,
309 player->name.charset_id, player->name.str_len);
310 } break;
311
312 case AVRC_ITEM_FOLDER: {
313 tAVRC_ITEM_FOLDER* folder = &(curr_item->u.folder);
314 uint16_t folder_len;
315 min_len += 4 + AVRC_UID_SIZE;
316 if (pkt_len < min_len) goto browse_length_error;
317 BE_STREAM_TO_UINT16(folder_len, p);
318
319 BE_STREAM_TO_ARRAY(p, folder->uid, AVRC_UID_SIZE);
320 BE_STREAM_TO_UINT8(folder->type, p);
321 BE_STREAM_TO_UINT8(folder->playable, p);
322
323 /* read str, encoding to be handled by upper layers */
324 min_len += 4;
325 if (pkt_len < min_len) goto browse_length_error;
326 BE_STREAM_TO_UINT16(folder->name.charset_id, p);
327 BE_STREAM_TO_UINT16(folder->name.str_len, p);
328 min_len += folder->name.str_len;
329 if (pkt_len < min_len) goto browse_length_error;
330 folder->name.p_str = (uint8_t*)osi_malloc(
331 (folder->name.str_len + 1) * sizeof(uint8_t));
332 BE_STREAM_TO_ARRAY(p, folder->name.p_str, folder->name.str_len);
333 AVRC_TRACE_DEBUG("%s type %d playable %d cs %d name len %d",
334 __func__, folder->type, folder->playable,
335 folder->name.charset_id, folder->name.str_len);
336 } break;
337
338 case AVRC_ITEM_MEDIA: {
339 tAVRC_ITEM_MEDIA* media = &(curr_item->u.media);
340 uint8_t media_len;
341 min_len += 3 + AVRC_UID_SIZE;
342 if (pkt_len < min_len) goto browse_length_error;
343 BE_STREAM_TO_UINT16(media_len, p);
344 BE_STREAM_TO_ARRAY(p, media->uid, AVRC_UID_SIZE);
345 BE_STREAM_TO_UINT8(media->type, p);
346
347 /* read str, encoding to be handled by upper layers */
348 min_len += 4;
349 if (pkt_len < min_len) goto browse_length_error;
350 BE_STREAM_TO_UINT16(media->name.charset_id, p);
351 BE_STREAM_TO_UINT16(media->name.str_len, p);
352 min_len += 1 + media->name.str_len;
353 if (pkt_len < min_len) goto browse_length_error;
354 media->name.p_str =
355 (uint8_t*)osi_malloc((media->name.str_len) * sizeof(uint8_t));
356 BE_STREAM_TO_ARRAY(p, media->name.p_str, media->name.str_len);
357
358 BE_STREAM_TO_UINT8(media->attr_count, p);
359 AVRC_TRACE_DEBUG("%s media type %d charset id %d len %d attr ct %d",
360 __func__, media->type, media->name.charset_id,
361 media->name.str_len, media->attr_count);
362
363 media->p_attr_list = (tAVRC_ATTR_ENTRY*)osi_malloc(
364 media->attr_count * sizeof(tAVRC_ATTR_ENTRY));
365 for (int jk = 0; jk < media->attr_count; jk++) {
366 tAVRC_ATTR_ENTRY* attr_entry = &(media->p_attr_list[jk]);
367 min_len += 8;
368 if (pkt_len < min_len) goto browse_length_error;
369 BE_STREAM_TO_UINT32(attr_entry->attr_id, p);
370
371 /* Parse the name now */
372 BE_STREAM_TO_UINT16(attr_entry->name.charset_id, p);
373 BE_STREAM_TO_UINT16(attr_entry->name.str_len, p);
374 min_len += attr_entry->name.str_len;
375 if (pkt_len < min_len) goto browse_length_error;
376 attr_entry->name.p_str = (uint8_t*)osi_malloc(
377 attr_entry->name.str_len * sizeof(uint8_t));
378 BE_STREAM_TO_ARRAY(p, attr_entry->name.p_str,
379 attr_entry->name.str_len);
380 AVRC_TRACE_DEBUG("%s media attr id %d cs %d name len %d",
381 __func__, attr_entry->attr_id,
382 attr_entry->name.charset_id,
383 attr_entry->name.str_len);
384 }
385 } break;
386
387 default:
388 AVRC_TRACE_ERROR("%s item type not handled %d", __func__,
389 curr_item->item_type);
390 return AVRC_STS_INTERNAL_ERR;
391 }
392
393 AVRC_TRACE_DEBUG("%s pkt_len %d min_len %d", __func__, pkt_len,
394 min_len);
395
396 /* advance to populate the next item */
397 curr_item++;
398 }
399 break;
400 }
401
402 case AVRC_PDU_CHANGE_PATH: {
403 tAVRC_CHG_PATH_RSP* change_path_rsp = &(p_rsp->chg_path);
404 min_len += 5;
405 if (pkt_len < min_len) goto browse_length_error;
406 /* Copyback the PDU */
407 change_path_rsp->pdu = pdu;
408 /* Read the status */
409 BE_STREAM_TO_UINT8(change_path_rsp->status, p);
410 /* Read the number of items in folder */
411 BE_STREAM_TO_UINT32(change_path_rsp->num_items, p);
412
413 AVRC_TRACE_DEBUG("%s pdu %d status %d item count %d", __func__,
414 change_path_rsp->pdu, change_path_rsp->status,
415 change_path_rsp->num_items);
416 break;
417 }
418
419 case AVRC_PDU_SET_BROWSED_PLAYER: {
420 tAVRC_SET_BR_PLAYER_RSP* set_br_pl_rsp = &(p_rsp->br_player);
421 /* Copyback the PDU */
422 set_br_pl_rsp->pdu = pdu;
423
424 /* Read the status */
425 min_len += 10;
426 if (pkt_len < min_len) goto browse_length_error;
427 BE_STREAM_TO_UINT8(set_br_pl_rsp->status, p);
428
429 if (set_br_pl_rsp->status != AVRC_STS_NO_ERROR) {
430 AVRC_TRACE_ERROR(
431 "%s Stopping further parsing because player not browsable sts %d",
432 __func__, set_br_pl_rsp->status);
433 break;
434 }
435 BE_STREAM_TO_UINT16(set_br_pl_rsp->uid_counter, p);
436 BE_STREAM_TO_UINT32(set_br_pl_rsp->num_items, p);
437 BE_STREAM_TO_UINT16(set_br_pl_rsp->charset_id, p);
438 BE_STREAM_TO_UINT8(set_br_pl_rsp->folder_depth, p);
439 AVRC_TRACE_DEBUG(
440 "%s AVRC_PDU_SET_BROWSED_PLAYER status %d items %d cs %d depth %d",
441 __func__, set_br_pl_rsp->status, set_br_pl_rsp->num_items,
442 set_br_pl_rsp->charset_id, set_br_pl_rsp->folder_depth);
443
444 set_br_pl_rsp->p_folders = (tAVRC_NAME*)osi_malloc(
445 set_br_pl_rsp->num_items * sizeof(tAVRC_NAME));
446
447 /* Read each of the folder in the depth */
448 for (uint32_t i = 0; i < set_br_pl_rsp->folder_depth; i++) {
449 tAVRC_NAME* folder_name = &(set_br_pl_rsp->p_folders[i]);
450 min_len += 2;
451 if (pkt_len < min_len) goto browse_length_error;
452 BE_STREAM_TO_UINT16(folder_name->str_len, p);
453 min_len += folder_name->str_len;
454 if (pkt_len < min_len) goto browse_length_error;
455 AVRC_TRACE_DEBUG("%s AVRC_PDU_SET_BROWSED_PLAYER item: %d len: %d",
456 __func__, i, folder_name->str_len);
457 folder_name->p_str =
458 (uint8_t*)osi_malloc((folder_name->str_len + 1) * sizeof(uint8_t));
459 BE_STREAM_TO_ARRAY(p, folder_name->p_str, folder_name->str_len);
460 }
461 break;
462 }
463
464 default:
465 AVRC_TRACE_ERROR("%s pdu %d not handled", __func__, pdu);
466 }
467
468 return status;
469
470 browse_length_error:
471 android_errorWriteLog(0x534e4554, "111451066");
472 AVRC_TRACE_WARNING("%s: invalid parameter length %d: must be at least %d",
473 __func__, pkt_len, min_len);
474 return AVRC_STS_BAD_CMD;
475 }
476
477 /*******************************************************************************
478 *
479 * Function avrc_ctrl_pars_vendor_rsp
480 *
481 * Description This function parses the vendor specific commands defined by
482 * Bluetooth SIG
483 *
484 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
485 * successfully.
486 * Otherwise, the error code defined by AVRCP 1.4
487 *
488 ******************************************************************************/
avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR * p_msg,tAVRC_RESPONSE * p_result,uint8_t * p_buf,uint16_t * buf_len)489 static tAVRC_STS avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg,
490 tAVRC_RESPONSE* p_result,
491 uint8_t* p_buf, uint16_t* buf_len) {
492 if (p_msg->vendor_len < 4) {
493 android_errorWriteLog(0x534e4554, "111450417");
494 AVRC_TRACE_WARNING("%s: message length %d too short: must be at least 4",
495 __func__, p_msg->vendor_len);
496 return AVRC_STS_INTERNAL_ERR;
497 }
498
499 uint8_t* p = p_msg->p_vendor_data;
500 BE_STREAM_TO_UINT8(p_result->pdu, p);
501 p++; /* skip the reserved/packe_type byte */
502
503 uint16_t len;
504 uint16_t min_len = 0;
505 BE_STREAM_TO_UINT16(len, p);
506 AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d vendor_len=0x%x", __func__,
507 p_msg->hdr.ctype, p_result->pdu, len, p_msg->vendor_len);
508 if (p_msg->vendor_len < len + 4) {
509 android_errorWriteLog(0x534e4554, "111450417");
510 AVRC_TRACE_WARNING("%s: message length %d too short: must be at least %d",
511 __func__, p_msg->vendor_len, len + 4);
512 return AVRC_STS_INTERNAL_ERR;
513 }
514 /* Todo: Issue in handling reject, check */
515 if (p_msg->hdr.ctype == AVRC_RSP_REJ) {
516 min_len += 1;
517 if (len < min_len) goto length_error;
518 p_result->rsp.status = *p;
519 return p_result->rsp.status;
520 }
521
522 /* TODO: Break the big switch into functions. */
523 switch (p_result->pdu) {
524 /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
525 /* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */
526
527 case AVRC_PDU_REGISTER_NOTIFICATION:
528 return avrc_parse_notification_rsp(p, len, &p_result->reg_notif);
529
530 case AVRC_PDU_GET_CAPABILITIES:
531 if (len == 0) {
532 p_result->get_caps.count = 0;
533 p_result->get_caps.capability_id = 0;
534 break;
535 }
536 min_len += 2;
537 if (len < min_len) goto length_error;
538 BE_STREAM_TO_UINT8(p_result->get_caps.capability_id, p);
539 BE_STREAM_TO_UINT8(p_result->get_caps.count, p);
540 AVRC_TRACE_DEBUG("%s cap id = %d, cap_count = %d ", __func__,
541 p_result->get_caps.capability_id,
542 p_result->get_caps.count);
543 if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID) {
544 min_len += MIN(p_result->get_caps.count, AVRC_CAP_MAX_NUM_COMP_ID) * 3;
545 if (len < min_len) goto length_error;
546 for (int xx = 0; ((xx < p_result->get_caps.count) &&
547 (xx < AVRC_CAP_MAX_NUM_COMP_ID));
548 xx++) {
549 BE_STREAM_TO_UINT24(p_result->get_caps.param.company_id[xx], p);
550 }
551 } else if (p_result->get_caps.capability_id ==
552 AVRC_CAP_EVENTS_SUPPORTED) {
553 min_len += MIN(p_result->get_caps.count, AVRC_CAP_MAX_NUM_EVT_ID);
554 if (len < min_len) goto length_error;
555 for (int xx = 0; ((xx < p_result->get_caps.count) &&
556 (xx < AVRC_CAP_MAX_NUM_EVT_ID));
557 xx++) {
558 BE_STREAM_TO_UINT8(p_result->get_caps.param.event_id[xx], p);
559 }
560 }
561 break;
562
563 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
564 if (len == 0) {
565 p_result->list_app_attr.num_attr = 0;
566 break;
567 }
568 min_len += 1;
569 BE_STREAM_TO_UINT8(p_result->list_app_attr.num_attr, p);
570 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__,
571 p_result->list_app_attr.num_attr);
572
573 if (p_result->list_app_attr.num_attr > AVRC_MAX_APP_ATTR_SIZE) {
574 android_errorWriteLog(0x534e4554, "63146237");
575 p_result->list_app_attr.num_attr = AVRC_MAX_APP_ATTR_SIZE;
576 }
577
578 min_len += p_result->list_app_attr.num_attr;
579 if (len < min_len) goto length_error;
580 for (int xx = 0; xx < p_result->list_app_attr.num_attr; xx++) {
581 BE_STREAM_TO_UINT8(p_result->list_app_attr.attrs[xx], p);
582 }
583 break;
584
585 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
586 if (len == 0) {
587 p_result->list_app_values.num_val = 0;
588 break;
589 }
590 min_len += 1;
591 BE_STREAM_TO_UINT8(p_result->list_app_values.num_val, p);
592 if (p_result->list_app_values.num_val > AVRC_MAX_APP_ATTR_SIZE) {
593 android_errorWriteLog(0x534e4554, "78526423");
594 p_result->list_app_values.num_val = AVRC_MAX_APP_ATTR_SIZE;
595 }
596
597 AVRC_TRACE_DEBUG("%s value count = %d ", __func__,
598 p_result->list_app_values.num_val);
599 min_len += p_result->list_app_values.num_val;
600 if (len < min_len) goto length_error;
601 for (int xx = 0; xx < p_result->list_app_values.num_val; xx++) {
602 BE_STREAM_TO_UINT8(p_result->list_app_values.vals[xx], p);
603 }
604 break;
605
606 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: {
607 if (len == 0) {
608 p_result->get_cur_app_val.num_val = 0;
609 break;
610 }
611 min_len += 1;
612 BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_val, p);
613 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__,
614 p_result->get_cur_app_val.num_val);
615
616 if (p_result->get_cur_app_val.num_val > AVRC_MAX_APP_ATTR_SIZE) {
617 android_errorWriteLog(0x534e4554, "63146237");
618 p_result->get_cur_app_val.num_val = AVRC_MAX_APP_ATTR_SIZE;
619 }
620
621 min_len += p_result->get_cur_app_val.num_val * 2;
622 if (len < min_len) {
623 p_result->get_cur_app_val.num_val = 0;
624 goto length_error;
625 }
626 tAVRC_APP_SETTING* app_sett = (tAVRC_APP_SETTING*)osi_calloc(
627 p_result->get_cur_app_val.num_val * sizeof(tAVRC_APP_SETTING));
628 for (int xx = 0; xx < p_result->get_cur_app_val.num_val; xx++) {
629 BE_STREAM_TO_UINT8(app_sett[xx].attr_id, p);
630 BE_STREAM_TO_UINT8(app_sett[xx].attr_val, p);
631 }
632 p_result->get_cur_app_val.p_vals = app_sett;
633 } break;
634
635 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: {
636 uint8_t num_attrs;
637
638 if (len == 0) {
639 p_result->get_app_attr_txt.num_attr = 0;
640 break;
641 }
642 min_len += 1;
643 BE_STREAM_TO_UINT8(num_attrs, p);
644 if (num_attrs > AVRC_MAX_APP_ATTR_SIZE) {
645 num_attrs = AVRC_MAX_APP_ATTR_SIZE;
646 }
647 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__,
648 p_result->get_app_attr_txt.num_attr);
649 p_result->get_app_attr_txt.num_attr = num_attrs;
650
651 p_result->get_app_attr_txt.p_attrs = (tAVRC_APP_SETTING_TEXT*)osi_calloc(
652 num_attrs * sizeof(tAVRC_APP_SETTING_TEXT));
653 for (int xx = 0; xx < num_attrs; xx++) {
654 min_len += 4;
655 if (len < min_len) {
656 for (int j = 0; j < xx; j++) {
657 osi_free(p_result->get_app_attr_txt.p_attrs[j].p_str);
658 }
659 osi_free_and_reset((void**)&p_result->get_app_attr_txt.p_attrs);
660 p_result->get_app_attr_txt.num_attr = 0;
661 goto length_error;
662 }
663 BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].attr_id, p);
664 BE_STREAM_TO_UINT16(p_result->get_app_attr_txt.p_attrs[xx].charset_id,
665 p);
666 BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].str_len, p);
667 min_len += p_result->get_app_attr_txt.p_attrs[xx].str_len;
668 if (len < min_len) {
669 for (int j = 0; j < xx; j++) {
670 osi_free(p_result->get_app_attr_txt.p_attrs[j].p_str);
671 }
672 osi_free_and_reset((void**)&p_result->get_app_attr_txt.p_attrs);
673 p_result->get_app_attr_txt.num_attr = 0;
674 goto length_error;
675 }
676 if (p_result->get_app_attr_txt.p_attrs[xx].str_len != 0) {
677 uint8_t* p_str = (uint8_t*)osi_calloc(
678 p_result->get_app_attr_txt.p_attrs[xx].str_len);
679 BE_STREAM_TO_ARRAY(p, p_str,
680 p_result->get_app_attr_txt.p_attrs[xx].str_len);
681 p_result->get_app_attr_txt.p_attrs[xx].p_str = p_str;
682 } else {
683 p_result->get_app_attr_txt.p_attrs[xx].p_str = NULL;
684 }
685 }
686 } break;
687
688 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: {
689 uint8_t num_vals;
690
691 if (len == 0) {
692 p_result->get_app_val_txt.num_attr = 0;
693 break;
694 }
695 min_len += 1;
696 BE_STREAM_TO_UINT8(num_vals, p);
697 if (num_vals > AVRC_MAX_APP_ATTR_SIZE) {
698 num_vals = AVRC_MAX_APP_ATTR_SIZE;
699 }
700 p_result->get_app_val_txt.num_attr = num_vals;
701 AVRC_TRACE_DEBUG("%s value count = %d ", __func__,
702 p_result->get_app_val_txt.num_attr);
703
704 p_result->get_app_val_txt.p_attrs = (tAVRC_APP_SETTING_TEXT*)osi_calloc(
705 num_vals * sizeof(tAVRC_APP_SETTING_TEXT));
706 for (int i = 0; i < num_vals; i++) {
707 min_len += 4;
708 if (len < min_len) {
709 for (int j = 0; j < i; j++) {
710 osi_free(p_result->get_app_val_txt.p_attrs[j].p_str);
711 }
712 osi_free_and_reset((void**)&p_result->get_app_val_txt.p_attrs);
713 p_result->get_app_val_txt.num_attr = 0;
714 goto length_error;
715 }
716 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].attr_id, p);
717 BE_STREAM_TO_UINT16(p_result->get_app_val_txt.p_attrs[i].charset_id, p);
718 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].str_len, p);
719 min_len += p_result->get_app_val_txt.p_attrs[i].str_len;
720 if (len < min_len) {
721 for (int j = 0; j < i; j++) {
722 osi_free(p_result->get_app_val_txt.p_attrs[j].p_str);
723 }
724 osi_free_and_reset((void**)&p_result->get_app_val_txt.p_attrs);
725 p_result->get_app_val_txt.num_attr = 0;
726 goto length_error;
727 }
728 if (p_result->get_app_val_txt.p_attrs[i].str_len != 0) {
729 uint8_t* p_str = (uint8_t*)osi_calloc(
730 p_result->get_app_val_txt.p_attrs[i].str_len);
731 BE_STREAM_TO_ARRAY(p, p_str,
732 p_result->get_app_val_txt.p_attrs[i].str_len);
733 p_result->get_app_val_txt.p_attrs[i].p_str = p_str;
734 } else {
735 p_result->get_app_val_txt.p_attrs[i].p_str = NULL;
736 }
737 }
738 } break;
739
740 case AVRC_PDU_SET_PLAYER_APP_VALUE:
741 /* nothing comes as part of this rsp */
742 break;
743
744 case AVRC_PDU_GET_ELEMENT_ATTR: {
745 uint8_t num_attrs;
746
747 if (len <= 0) {
748 p_result->get_attrs.num_attrs = 0;
749 break;
750 }
751 min_len += 1;
752 BE_STREAM_TO_UINT8(num_attrs, p);
753 p_result->get_attrs.num_attrs = num_attrs;
754 if (num_attrs) {
755 tAVRC_ATTR_ENTRY* p_attrs =
756 (tAVRC_ATTR_ENTRY*)osi_calloc(num_attrs * sizeof(tAVRC_ATTR_ENTRY));
757 for (int i = 0; i < num_attrs; i++) {
758 min_len += 8;
759 if (len < min_len) {
760 for (int j = 0; j < i; j++) {
761 osi_free(p_attrs[j].name.p_str);
762 }
763 osi_free(p_attrs);
764 p_result->get_attrs.num_attrs = 0;
765 goto length_error;
766 }
767 BE_STREAM_TO_UINT32(p_attrs[i].attr_id, p);
768 BE_STREAM_TO_UINT16(p_attrs[i].name.charset_id, p);
769 BE_STREAM_TO_UINT16(p_attrs[i].name.str_len, p);
770 min_len += p_attrs[i].name.str_len;
771 if (len < min_len) {
772 for (int j = 0; j < i; j++) {
773 osi_free(p_attrs[j].name.p_str);
774 }
775 osi_free(p_attrs);
776 p_result->get_attrs.num_attrs = 0;
777 goto length_error;
778 }
779 if (p_attrs[i].name.str_len > 0) {
780 p_attrs[i].name.p_str =
781 (uint8_t*)osi_calloc(p_attrs[i].name.str_len);
782 BE_STREAM_TO_ARRAY(p, p_attrs[i].name.p_str,
783 p_attrs[i].name.str_len);
784 } else {
785 p_attrs[i].name.p_str = NULL;
786 }
787 }
788 p_result->get_attrs.p_attrs = p_attrs;
789 }
790 } break;
791
792 case AVRC_PDU_GET_PLAY_STATUS:
793 if (len == 0) {
794 break;
795 }
796 min_len += 9;
797 if (len < min_len) goto length_error;
798 BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p);
799 BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p);
800 BE_STREAM_TO_UINT8(p_result->get_play_status.status, p);
801 break;
802
803 case AVRC_PDU_SET_ADDRESSED_PLAYER:
804 if (len != 1) {
805 AVRC_TRACE_ERROR("%s pdu: %d len %d", __func__, p_result->pdu, len);
806 return AVRC_STS_BAD_CMD;
807 }
808 BE_STREAM_TO_UINT8(p_result->rsp.status, p);
809 break;
810
811 default:
812 return AVRC_STS_BAD_CMD;
813 }
814 return AVRC_STS_NO_ERROR;
815
816 length_error:
817 android_errorWriteLog(0x534e4554, "111450417");
818 AVRC_TRACE_WARNING("%s: invalid parameter length %d: must be at least %d",
819 __func__, len, min_len);
820 return AVRC_STS_INTERNAL_ERR;
821 }
822
823 /*******************************************************************************
824 *
825 * Function AVRC_Ctrl_ParsResponse
826 *
827 * Description This function is a parse response for AVRCP Controller.
828 *
829 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
830 * successfully.
831 * Otherwise, the error code defined by AVRCP 1.4
832 *
833 ******************************************************************************/
AVRC_Ctrl_ParsResponse(tAVRC_MSG * p_msg,tAVRC_RESPONSE * p_result,uint8_t * p_buf,uint16_t * buf_len)834 tAVRC_STS AVRC_Ctrl_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result,
835 uint8_t* p_buf, uint16_t* buf_len) {
836 tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
837 if (p_msg && p_result) {
838 switch (p_msg->hdr.opcode) {
839 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */
840 status =
841 avrc_ctrl_pars_vendor_rsp(&p_msg->vendor, p_result, p_buf, buf_len);
842 break;
843
844 case AVRC_OP_BROWSE: /* 0xff Browse commands */
845 status = avrc_pars_browse_rsp(&p_msg->browse, p_result);
846 break;
847
848 default:
849 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
850 break;
851 }
852 p_result->rsp.opcode = p_msg->hdr.opcode;
853 p_result->rsp.status = status;
854 }
855 return status;
856 }
857
858 /*******************************************************************************
859 *
860 * Function AVRC_ParsResponse
861 *
862 * Description This function is a superset of AVRC_ParsMetadata to parse
863 * the response.
864 *
865 * Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed
866 * successfully.
867 * Otherwise, the error code defined by AVRCP 1.4
868 *
869 ******************************************************************************/
AVRC_ParsResponse(tAVRC_MSG * p_msg,tAVRC_RESPONSE * p_result,UNUSED_ATTR uint8_t * p_buf,UNUSED_ATTR uint16_t buf_len)870 tAVRC_STS AVRC_ParsResponse(tAVRC_MSG* p_msg, tAVRC_RESPONSE* p_result,
871 UNUSED_ATTR uint8_t* p_buf,
872 UNUSED_ATTR uint16_t buf_len) {
873 tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
874 uint16_t id;
875
876 if (p_msg && p_result) {
877 switch (p_msg->hdr.opcode) {
878 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */
879 status = avrc_pars_vendor_rsp(&p_msg->vendor, p_result);
880 break;
881
882 case AVRC_OP_PASS_THRU: /* 0x7C panel subunit opcode */
883 status = avrc_pars_pass_thru(&p_msg->pass, &id);
884 if (status == AVRC_STS_NO_ERROR) {
885 p_result->pdu = (uint8_t)id;
886 }
887 break;
888
889 default:
890 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode);
891 break;
892 }
893 p_result->rsp.opcode = p_msg->hdr.opcode;
894 p_result->rsp.status = status;
895 }
896 return status;
897 }
898