1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
23
24
25
26
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
59
62
63
64
65
66
70
71
72
73
76
77
80
81
82
91
98
107
108
109
110
114
115
122
123
126
127
128
152
178
197
208
233
240
249
250
256
257
258
259
260
261
262
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
305
306
307
308
309
310
311
/* ... */
#include <string.h>
#include "common/bt_target.h"
#include "stack/avrc_api.h"
#include "stack/avrc_defs.h"
#include "avrc_int.h"5 includes
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
/* ... */
#if (AVRC_METADATA_INCLUDED == TRUE)
/* ... */
static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_result,
UINT8 *p_buf, UINT16 buf_len)
{
tAVRC_STS status = AVRC_STS_NO_ERROR;
UINT8 *p;
UINT16 len;
UINT8 xx, yy;
UINT8 *p_u8;
UINT16 *p_u16;
UINT32 u32, u32_2, *p_u32;
tAVRC_APP_SETTING *p_app_set;
UINT16 size_needed;
if (p_msg->vendor_len == 0) {
return AVRC_STS_NO_ERROR;
}{...}
if (p_msg->p_vendor_data == NULL) {
return AVRC_STS_INTERNAL_ERR;
}{...}
p = p_msg->p_vendor_data;
p_result->pdu = *p++;
AVRC_TRACE_DEBUG("avrc_pars_vendor_cmd() pdu:0x%x", p_result->pdu);
if (!AVRC_IsValidAvcType (p_result->pdu, p_msg->hdr.ctype)) {
AVRC_TRACE_DEBUG("avrc_pars_vendor_cmd() detects wrong AV/C type!");
status = AVRC_STS_BAD_CMD;
}{...}
p++;
BE_STREAM_TO_UINT16 (len, p);
if ((len + 4) != (p_msg->vendor_len)) {
status = AVRC_STS_NOT_FOUND;
}{...}
if (status != AVRC_STS_NO_ERROR) {
return status;
}{...}
switch (p_result->pdu) {
case AVRC_PDU_GET_CAPABILITIES:
p_result->get_caps.capability_id = *p++;
if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id)) {
status = AVRC_STS_BAD_PARAM;
}{...} else if (len != 1) {
status = AVRC_STS_INTERNAL_ERR;
}{...}
break;
...
case AVRC_PDU_LIST_PLAYER_APP_ATTR:
if (len != 0) {
status = AVRC_STS_INTERNAL_ERR;
}{...}
break;
...
case AVRC_PDU_LIST_PLAYER_APP_VALUES:
p_result->list_app_values.attr_id = *p++;
if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id)) {
status = AVRC_STS_BAD_PARAM;
}{...} else if (len != 1) {
status = AVRC_STS_INTERNAL_ERR;
}{...}
break;
...
case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p);
if (len != (p_result->get_cur_app_val.num_attr + 1)) {
status = AVRC_STS_INTERNAL_ERR;
break;
}{...}
p_u8 = p_result->get_cur_app_val.attrs;
for (xx = 0, yy = 0; xx < p_result->get_cur_app_val.num_attr; xx++) {
if (AVRC_IsValidPlayerAttr(*p)) {
p_u8[yy++] = *p;
}{...}
p++;
}{...}
p_result->get_cur_app_val.num_attr = yy;
if (yy == 0) {
status = AVRC_STS_BAD_PARAM;
}{...}
break;
...
case AVRC_PDU_SET_PLAYER_APP_VALUE:
BE_STREAM_TO_UINT8 (p_result->set_app_val.num_val, p);
size_needed = sizeof(tAVRC_APP_SETTING);
if (p_buf && (len == ((p_result->set_app_val.num_val << 1) + 1))) {
p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf;
p_app_set = p_result->set_app_val.p_vals;
for (xx = 0; ((xx < p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++) {
p_app_set[xx].attr_id = *p++;
p_app_set[xx].attr_val = *p++;
if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val)) {
status = AVRC_STS_BAD_PARAM;
}{...}
}{...}
if (xx != p_result->set_app_val.num_val) {
AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d",
xx, p_result->set_app_val.num_val);
p_result->set_app_val.num_val = xx;
}{...}
}{...} else {
AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len");
status = AVRC_STS_INTERNAL_ERR;
}{...}
break;
...
case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
if (len < 3) {
status = AVRC_STS_INTERNAL_ERR;
}{...} else {
BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.attr_id, p);
if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id)) {
status = AVRC_STS_BAD_PARAM;
}{...} else {
BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.num_val, p);
if ( (len - 2) != p_result->get_app_val_txt.num_val) {
status = AVRC_STS_INTERNAL_ERR;
}{...} else {
p_u8 = p_result->get_app_val_txt.vals;
for (xx = 0; xx < p_result->get_app_val_txt.num_val; xx++) {
p_u8[xx] = *p++;
if (!avrc_is_valid_player_attrib_value(p_result->get_app_val_txt.attr_id,
p_u8[xx])) {
status = AVRC_STS_BAD_PARAM;
break;
}{...}
}{...}
}{...}
}{...}
}{...}
break;
...
case AVRC_PDU_INFORM_DISPLAY_CHARSET:
if (len < 3) {
status = AVRC_STS_INTERNAL_ERR;
}{...} else {
BE_STREAM_TO_UINT8 (p_result->inform_charset.num_id, p);
if ( (len - 1) != p_result->inform_charset.num_id * 2) {
status = AVRC_STS_INTERNAL_ERR;
}{...} else {
p_u16 = p_result->inform_charset.charsets;
if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE) {
p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE;
}{...}
for (xx = 0; xx < p_result->inform_charset.num_id; xx++) {
BE_STREAM_TO_UINT16 (p_u16[xx], p);
}{...}
}{...}
}{...}
break;
...
case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:
if (len != 1) {
status = AVRC_STS_INTERNAL_ERR;
}{...} else {
p_result->inform_battery_status.battery_status = *p++;
if (!AVRC_IS_VALID_BATTERY_STATUS(p_result->inform_battery_status.battery_status)) {
status = AVRC_STS_BAD_PARAM;
}{...}
}{...}
break;
...
case AVRC_PDU_GET_ELEMENT_ATTR:
if (len < 9) {
status = AVRC_STS_INTERNAL_ERR;
}{...} else {
BE_STREAM_TO_UINT32 (u32, p);
BE_STREAM_TO_UINT32 (u32_2, p);
if (u32 == 0 && u32_2 == 0) {
BE_STREAM_TO_UINT8 (p_result->get_elem_attrs.num_attr, p);
if ( (len - 9) != (p_result->get_elem_attrs.num_attr * 4)) {
status = AVRC_STS_INTERNAL_ERR;
}{...} else {
p_u32 = p_result->get_elem_attrs.attrs;
if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE) {
p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE;
}{...}
for (xx = 0; xx < p_result->get_elem_attrs.num_attr; xx++) {
BE_STREAM_TO_UINT32 (p_u32[xx], p);
}{...}
}{...}
}{...} else {
status = AVRC_STS_NOT_FOUND;
}{...}
}{...}
break;
...
case AVRC_PDU_GET_PLAY_STATUS:
if (len != 0) {
status = AVRC_STS_INTERNAL_ERR;
}{...}
break;
...
case AVRC_PDU_REGISTER_NOTIFICATION:
if (len != 5) {
status = AVRC_STS_INTERNAL_ERR;
}{...} else {
BE_STREAM_TO_UINT8 (p_result->reg_notif.event_id, p);
BE_STREAM_TO_UINT32 (p_result->reg_notif.param, p);
}{...}
break;
...
case AVRC_PDU_SET_ABSOLUTE_VOLUME: {
if (len != 1) {
status = AVRC_STS_INTERNAL_ERR;
}{...} else {
BE_STREAM_TO_UINT8 (p_result->volume.volume, p);
p_result->volume.volume &= 0x7F;
}{...}
break;
}{...}
...
default:
status = AVRC_STS_BAD_CMD;
break;...
}{...}
return status;
}{...}
/* ... */
tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len)
{
tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
UINT16 id;
if (p_msg && p_result) {
switch (p_msg->hdr.opcode) {
case AVRC_OP_VENDOR:
status = avrc_pars_vendor_cmd(&p_msg->vendor, p_result, p_buf, buf_len);
break;
...
case AVRC_OP_PASS_THRU:
status = avrc_pars_pass_thru(&p_msg->pass, &id);
if (status == AVRC_STS_NO_ERROR) {
p_result->pdu = (UINT8)id;
}{...}
break;
...
default:
AVRC_TRACE_ERROR("AVRC_ParsCommand() unknown opcode:0x%x", p_msg->hdr.opcode);
break;...
}{...}
p_result->cmd.opcode = p_msg->hdr.opcode;
p_result->cmd.status = status;
}{...}
AVRC_TRACE_DEBUG("AVRC_ParsCommand() return status:0x%x", status);
return status;
}{...}
/* ... */
#endif
/* ... */
#endif