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