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