1 /******************************************************************************
2  *
3  *  Copyright (C) 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 #include "common/bt_target.h"
20 #include "stack/avrc_api.h"
21 #include "stack/avrc_defs.h"
22 #include "avrc_int.h"
23 #include "common/bt_defs.h"
24 
25 #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
26 
27 /*****************************************************************************
28 **  Global data
29 *****************************************************************************/
30 
31 #if (AVRC_METADATA_INCLUDED == TRUE)
32 
33 /*******************************************************************************
34 **
35 ** Function         avrc_pars_vendor_rsp
36 **
37 ** Description      This function parses the vendor specific commands defined by
38 **                  Bluetooth SIG
39 **
40 ** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
41 **                  Otherwise, the error code defined by AVRCP 1.4
42 **
43 *******************************************************************************/
avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR * p_msg,tAVRC_RESPONSE * p_result)44 static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p_result)
45 {
46     tAVRC_STS  status = AVRC_STS_NO_ERROR;
47     UINT8   *p;
48     UINT16  len;
49     UINT8 eventid = 0;
50 
51     /* Check the vendor data */
52     if (p_msg->vendor_len == 0) {
53         return AVRC_STS_NO_ERROR;
54     }
55     if (p_msg->p_vendor_data == NULL) {
56         return AVRC_STS_INTERNAL_ERR;
57     }
58 
59     p = p_msg->p_vendor_data;
60     BE_STREAM_TO_UINT8 (p_result->pdu, p);
61     p++; /* skip the reserved/packe_type byte */
62     BE_STREAM_TO_UINT16 (len, p);
63     AVRC_TRACE_DEBUG("avrc_pars_vendor_rsp() ctype:0x%x pdu:0x%x, len:%d/0x%x", p_msg->hdr.ctype, p_result->pdu, len, len);
64     if (p_msg->hdr.ctype == AVRC_RSP_REJ) {
65         p_result->rsp.status = *p;
66         return p_result->rsp.status;
67     }
68 
69     switch (p_result->pdu) {
70         /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
71         /* case AVRC_PDU_ABORT_CONTINUATION_RSP:   0x41 */
72 
73 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
74     case AVRC_PDU_SET_ABSOLUTE_VOLUME:      /* 0x50 */
75         if (len != 1) {
76             status = AVRC_STS_INTERNAL_ERR;
77         } else {
78             BE_STREAM_TO_UINT8 (p_result->volume.volume, p);
79         }
80         break;
81 #endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
82 
83     case AVRC_PDU_REGISTER_NOTIFICATION:    /* 0x31 */
84 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
85         BE_STREAM_TO_UINT8 (eventid, p);
86         if (AVRC_EVT_VOLUME_CHANGE == eventid
87                 && (AVRC_RSP_CHANGED == p_msg->hdr.ctype || AVRC_RSP_INTERIM == p_msg->hdr.ctype
88                     || AVRC_RSP_REJ == p_msg->hdr.ctype || AVRC_RSP_NOT_IMPL == p_msg->hdr.ctype)) {
89             p_result->reg_notif.status = p_msg->hdr.ctype;
90             p_result->reg_notif.event_id = eventid;
91             BE_STREAM_TO_UINT8 (p_result->reg_notif.param.volume, p);
92         }
93         // todo: parse the response for other event_ids
94         AVRC_TRACE_DEBUG("avrc_pars_vendor_rsp PDU reg notif response:event 0x%x", eventid);
95         break;
96 #endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
97     case AVRC_PDU_GET_CAPABILITIES:        /* 0x10 */
98         BE_STREAM_TO_UINT8 (p_result->get_caps.capability_id, p);
99         BE_STREAM_TO_UINT8 (p_result->get_caps.count, p);
100         if (p_result->get_caps.capability_id == AVRC_CAP_EVENTS_SUPPORTED) {
101             if (p_result->get_caps.count > AVRC_CAP_MAX_NUM_EVT_ID) {
102                 status = AVRC_STS_INTERNAL_ERR;
103             } else {
104                 BE_STREAM_TO_ARRAY(p, p_result->get_caps.param.event_id, p_result->get_caps.count);
105             }
106         } else if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID) {
107             if (p_result->get_caps.count > AVRC_CAP_MAX_NUM_COMP_ID) {
108                 status = AVRC_STS_INTERNAL_ERR;
109             } else {
110                 for (int i = 0; i < p_result->get_caps.count; ++i) {
111                     BE_STREAM_TO_UINT24(p_result->get_caps.param.company_id[i], p);
112                 }
113             }
114         }
115         break;
116     default:
117         status = AVRC_STS_BAD_CMD;
118         break;
119     }
120 
121     return status;
122 }
123 
124 /*******************************************************************************
125 **
126 ** Function         AVRC_ParsResponse
127 **
128 ** Description      This function is a superset of AVRC_ParsMetadata to parse the response.
129 **
130 ** Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
131 **                  Otherwise, the error code defined by AVRCP 1.4
132 **
133 *******************************************************************************/
AVRC_ParsResponse(tAVRC_MSG * p_msg,tAVRC_RESPONSE * p_result)134 tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result)
135 {
136     tAVRC_STS  status = AVRC_STS_INTERNAL_ERR;
137     UINT16  id;
138 
139     if (p_msg && p_result) {
140         switch (p_msg->hdr.opcode) {
141         case AVRC_OP_VENDOR:     /*  0x00    Vendor-dependent commands */
142             status = avrc_pars_vendor_rsp(&p_msg->vendor, p_result);
143             break;
144 
145         case AVRC_OP_PASS_THRU:  /*  0x7C    panel subunit opcode */
146             status = avrc_pars_pass_thru(&p_msg->pass, &id);
147             if (status == AVRC_STS_NO_ERROR) {
148                 p_result->pdu = (UINT8)id;
149             }
150             break;
151 
152         default:
153             AVRC_TRACE_ERROR("AVRC_ParsResponse() unknown opcode:0x%x", p_msg->hdr.opcode);
154             break;
155         }
156         p_result->rsp.opcode = p_msg->hdr.opcode;
157         p_result->rsp.status = status;
158     }
159     return status;
160 }
161 
162 
163 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */
164 
165 #endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */
166