1 /******************************************************************************
2  *
3  *  Copyright 2003-2016 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_int.h"
22 #include "bt_common.h"
23 
24 /**************************************************************************
25  *
26  * Function         AVRC_IsValidAvcType
27  *
28  * Description      Check if correct AVC type is specified
29  *
30  * Returns          returns true if it is valid
31  *
32  *
33  ******************************************************************************/
34 bool AVRC_IsValidAvcType(uint8_t pdu_id, uint8_t avc_type) {
35   bool result = false;
36 
37   if (avc_type < AVRC_RSP_NOT_IMPL) /* command msg */
38   {
39     switch (pdu_id) {
40       case AVRC_PDU_GET_CAPABILITIES:          /* 0x10 */
41       case AVRC_PDU_LIST_PLAYER_APP_ATTR:      /* 0x11 */
42       case AVRC_PDU_LIST_PLAYER_APP_VALUES:    /* 0x12 */
43       case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:  /* 0x13 */
44       case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:  /* 0x15 */
45       case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: /* 0x16 */
46       case AVRC_PDU_GET_ELEMENT_ATTR:          /* 0x20 */
47       case AVRC_PDU_GET_PLAY_STATUS:           /* 0x30 */
48         if (avc_type == AVRC_CMD_STATUS) result = true;
49         break;
50 
51       case AVRC_PDU_SET_PLAYER_APP_VALUE:      /* 0x14 */
52       case AVRC_PDU_INFORM_DISPLAY_CHARSET:    /* 0x17 */
53       case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: /* 0x18 */
54       case AVRC_PDU_REQUEST_CONTINUATION_RSP:  /* 0x40 */
55       case AVRC_PDU_ABORT_CONTINUATION_RSP:    /* 0x41 */
56         if (avc_type == AVRC_CMD_CTRL) result = true;
57         break;
58 
59       case AVRC_PDU_GET_FOLDER_ITEMS: /* 0x71 */
60         result = true;
61         break;
62 
63       case AVRC_PDU_SET_ABSOLUTE_VOLUME:  /* 0x50 */
64       case AVRC_PDU_SET_ADDRESSED_PLAYER: /* 0x60 */
65       case AVRC_PDU_PLAY_ITEM:            /* 0x74 */
66       case AVRC_PDU_ADD_TO_NOW_PLAYING:   /* 0x90 */
67         if (avc_type == AVRC_CMD_CTRL) result = true;
68         break;
69 
70       case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
71         if (avc_type == AVRC_CMD_NOTIF) result = true;
72         break;
73     }
74   } else /* response msg */
75   {
76     if (avc_type >= AVRC_RSP_NOT_IMPL && avc_type <= AVRC_RSP_INTERIM)
77       result = true;
78   }
79 
80   return result;
81 }
82 
83 /*******************************************************************************
84  *
85  * Function         avrc_is_valid_player_attrib_value
86  *
87  * Description      Check if the given attrib value is valid for its attribute
88  *
89  * Returns          returns true if it is valid
90  *
91  ******************************************************************************/
92 bool avrc_is_valid_player_attrib_value(uint8_t attrib, uint8_t value) {
93   bool result = false;
94 
95   switch (attrib) {
96     case AVRC_PLAYER_SETTING_EQUALIZER:
97       if ((value > 0) && (value <= AVRC_PLAYER_VAL_ON)) result = true;
98       break;
99 
100     case AVRC_PLAYER_SETTING_REPEAT:
101       if ((value > 0) && (value <= AVRC_PLAYER_VAL_GROUP_REPEAT)) result = true;
102       break;
103 
104     case AVRC_PLAYER_SETTING_SHUFFLE:
105     case AVRC_PLAYER_SETTING_SCAN:
106       if ((value > 0) && (value <= AVRC_PLAYER_VAL_GROUP_SHUFFLE))
107         result = true;
108       break;
109   }
110 
111   if (attrib >= AVRC_PLAYER_SETTING_LOW_MENU_EXT) result = true;
112 
113   if (!result) {
114     AVRC_TRACE_ERROR(" %s found not matching attrib(x%x)-value(x%x) pair!",
115                      __func__, attrib, value);
116   }
117   return result;
118 }
119 
120 /*******************************************************************************
121  *
122  * Function         AVRC_IsValidPlayerAttr
123  *
124  * Description      Check if the given attrib value is a valid one
125  *
126  * Returns          returns true if it is valid
127  *
128  ******************************************************************************/
129 bool AVRC_IsValidPlayerAttr(uint8_t attr) {
130   bool result = false;
131 
132   if ((attr >= AVRC_PLAYER_SETTING_EQUALIZER &&
133        attr <= AVRC_PLAYER_SETTING_SCAN) ||
134       (attr >= AVRC_PLAYER_SETTING_LOW_MENU_EXT)) {
135     result = true;
136   }
137 
138   return result;
139 }
140 
141 /*******************************************************************************
142  *
143  * Function         avrc_pars_pass_thru
144  *
145  * Description      This function parses the pass thru commands defined by
146  *                  Bluetooth SIG
147  *
148  * Returns          AVRC_STS_NO_ERROR, if the message in p_data is parsed
149  *                                     successfully.
150  *                  Otherwise, the error code defined by AVRCP 1.4
151  *
152  ******************************************************************************/
153 tAVRC_STS avrc_pars_pass_thru(tAVRC_MSG_PASS* p_msg,
154                               uint16_t* p_vendor_unique_id) {
155   uint8_t* p_data;
156   uint32_t co_id;
157   uint16_t id;
158   tAVRC_STS status = AVRC_STS_BAD_CMD;
159 
160   if (p_msg->op_id == AVRC_ID_VENDOR &&
161       p_msg->pass_len == AVRC_PASS_THRU_GROUP_LEN) {
162     p_data = p_msg->p_pass_data;
163     AVRC_BE_STREAM_TO_CO_ID(co_id, p_data);
164     if (co_id == AVRC_CO_METADATA) {
165       BE_STREAM_TO_UINT16(id, p_data);
166       if (AVRC_IS_VALID_GROUP(id)) {
167         *p_vendor_unique_id = id;
168         status = AVRC_STS_NO_ERROR;
169       }
170     }
171   }
172   return status;
173 }
174 
175 /*******************************************************************************
176  *
177  * Function         avrc_opcode_from_pdu
178  *
179  * Description      This function returns the opcode of the given pdu
180  *
181  * Returns          AVRC_OP_VENDOR, AVRC_OP_PASS_THRU or AVRC_OP_BROWSE
182  *
183  ******************************************************************************/
184 uint8_t avrc_opcode_from_pdu(uint8_t pdu) {
185   uint8_t opcode = 0;
186 
187   switch (pdu) {
188     case AVRC_PDU_SET_BROWSED_PLAYER:
189     case AVRC_PDU_GET_FOLDER_ITEMS:
190     case AVRC_PDU_CHANGE_PATH:
191     case AVRC_PDU_GET_ITEM_ATTRIBUTES:
192     case AVRC_PDU_SEARCH:
193     case AVRC_PDU_GENERAL_REJECT:
194     case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:
195       opcode = AVRC_OP_BROWSE;
196       break;
197 
198     case AVRC_PDU_NEXT_GROUP:
199     case AVRC_PDU_PREV_GROUP: /* pass thru */
200       opcode = AVRC_OP_PASS_THRU;
201       break;
202 
203     default: /* vendor */
204       opcode = AVRC_OP_VENDOR;
205       break;
206   }
207 
208   return opcode;
209 }
210 
211 /*******************************************************************************
212  *
213  * Function         avrc_is_valid_opcode
214  *
215  * Description      This function returns the opcode of the given pdu
216  *
217  * Returns          AVRC_OP_VENDOR, AVRC_OP_PASS_THRU or AVRC_OP_BROWSE
218  *
219  ******************************************************************************/
220 bool avrc_is_valid_opcode(uint8_t opcode) {
221   bool is_valid = false;
222   switch (opcode) {
223     case AVRC_OP_BROWSE:
224     case AVRC_OP_PASS_THRU:
225     case AVRC_OP_VENDOR:
226       is_valid = true;
227       break;
228   }
229   return is_valid;
230 }
231