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