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