1 /****************************************************************************** 2 * 3 * Copyright (C) 2003-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 20 #include "gki.h" 21 #include "avrc_api.h" 22 #include "avrc_defs.h" 23 #include "avrc_int.h" 24 25 /***************************************************************************** 26 ** Global data 27 *****************************************************************************/ 28 #if (AVRC_METADATA_INCLUDED == TRUE) 29 30 /******************************************************************************* 31 ** 32 ** Function avrc_pars_vendor_cmd 33 ** 34 ** Description This function parses the vendor specific commands defined by 35 ** Bluetooth SIG 36 ** 37 ** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 38 ** Otherwise, the error code defined by AVRCP 1.4 39 ** 40 *******************************************************************************/ 41 static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_result, 42 UINT8 *p_buf, UINT16 buf_len) 43 { 44 tAVRC_STS status = AVRC_STS_NO_ERROR; 45 UINT8 *p = p_msg->p_vendor_data; 46 UINT16 len; 47 UINT8 xx, yy; 48 UINT8 *p_u8; 49 UINT16 *p_u16; 50 UINT32 u32, u32_2, *p_u32; 51 tAVRC_APP_SETTING *p_app_set; 52 UINT16 size_needed; 53 54 p_result->pdu = *p++; 55 AVRC_TRACE_DEBUG1("avrc_pars_vendor_cmd() pdu:0x%x", p_result->pdu); 56 if (!AVRC_IsValidAvcType (p_result->pdu, p_msg->hdr.ctype)) 57 { 58 AVRC_TRACE_DEBUG0("avrc_pars_vendor_cmd() detects wrong AV/C type!"); 59 status = AVRC_STS_BAD_CMD; 60 } 61 62 p++; /* skip the reserved byte */ 63 BE_STREAM_TO_UINT16 (len, p); 64 if ((len+4) != (p_msg->vendor_len)) 65 { 66 status = AVRC_STS_INTERNAL_ERR; 67 } 68 69 if (status != AVRC_STS_NO_ERROR) 70 return status; 71 72 switch (p_result->pdu) 73 { 74 case AVRC_PDU_GET_CAPABILITIES: /* 0x10 */ 75 p_result->get_caps.capability_id = *p++; 76 if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id)) 77 status = AVRC_STS_BAD_PARAM; 78 else if (len != 1) 79 status = AVRC_STS_INTERNAL_ERR; 80 break; 81 82 case AVRC_PDU_LIST_PLAYER_APP_ATTR: /* 0x11 */ 83 /* no additional parameters */ 84 if (len != 0) 85 status = AVRC_STS_INTERNAL_ERR; 86 break; 87 88 case AVRC_PDU_LIST_PLAYER_APP_VALUES: /* 0x12 */ 89 p_result->list_app_values.attr_id = *p++; 90 if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id)) 91 status = AVRC_STS_BAD_PARAM; 92 else if (len != 1) 93 status = AVRC_STS_INTERNAL_ERR; 94 break; 95 96 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */ 97 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */ 98 BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p); 99 if (len != (p_result->get_cur_app_val.num_attr+1)) 100 { 101 status = AVRC_STS_INTERNAL_ERR; 102 break; 103 } 104 p_u8 = p_result->get_cur_app_val.attrs; 105 for (xx=0, yy=0; xx< p_result->get_cur_app_val.num_attr; xx++) 106 { 107 /* only report the valid player app attributes */ 108 if (AVRC_IsValidPlayerAttr(*p)) 109 p_u8[yy++] = *p; 110 p++; 111 } 112 p_result->get_cur_app_val.num_attr = yy; 113 if (yy == 0) 114 { 115 status = AVRC_STS_BAD_PARAM; 116 } 117 break; 118 119 case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */ 120 BE_STREAM_TO_UINT8 (p_result->set_app_val.num_val, p); 121 size_needed = sizeof(tAVRC_APP_SETTING); 122 if (p_buf && (len == ((p_result->set_app_val.num_val<<1) + 1))) 123 { 124 p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf; 125 p_app_set = p_result->set_app_val.p_vals; 126 for (xx=0; ((xx< p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++) 127 { 128 p_app_set[xx].attr_id = *p++; 129 p_app_set[xx].attr_val = *p++; 130 if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val)) 131 status = AVRC_STS_BAD_PARAM; 132 } 133 if (xx != p_result->set_app_val.num_val) 134 { 135 AVRC_TRACE_ERROR2("AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d", 136 xx, p_result->set_app_val.num_val); 137 p_result->set_app_val.num_val = xx; 138 } 139 } 140 else 141 { 142 AVRC_TRACE_ERROR0("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len"); 143 status = AVRC_STS_INTERNAL_ERR; 144 } 145 break; 146 147 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:/* 0x16 */ 148 if (len < 3) 149 status = AVRC_STS_INTERNAL_ERR; 150 else 151 { 152 BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.attr_id, p); 153 if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id)) 154 status = AVRC_STS_BAD_PARAM; 155 else 156 { 157 BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.num_val, p); 158 if ( (len - 2/* attr_id & num_val */) != p_result->get_app_val_txt.num_val) 159 status = AVRC_STS_INTERNAL_ERR; 160 else 161 { 162 p_u8 = p_result->get_app_val_txt.vals; 163 for (xx=0; xx< p_result->get_app_val_txt.num_val; xx++) 164 { 165 p_u8[xx] = *p++; 166 if (!avrc_is_valid_player_attrib_value(p_result->get_app_val_txt.attr_id, 167 p_u8[xx])) 168 { 169 status = AVRC_STS_BAD_PARAM; 170 break; 171 } 172 } 173 } 174 } 175 } 176 break; 177 178 case AVRC_PDU_INFORM_DISPLAY_CHARSET: /* 0x17 */ 179 if (len < 3) 180 status = AVRC_STS_INTERNAL_ERR; 181 else 182 { 183 BE_STREAM_TO_UINT8 (p_result->inform_charset.num_id, p); 184 if ( (len - 1/* num_id */) != p_result->inform_charset.num_id * 2) 185 status = AVRC_STS_INTERNAL_ERR; 186 else 187 { 188 p_u16 = p_result->inform_charset.charsets; 189 if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE) 190 p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE; 191 for (xx=0; xx< p_result->inform_charset.num_id; xx++) 192 { 193 BE_STREAM_TO_UINT16 (p_u16[xx], p); 194 } 195 } 196 } 197 break; 198 199 case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:/* 0x18 */ 200 if (len != 1) 201 status = AVRC_STS_INTERNAL_ERR; 202 else 203 { 204 p_result->inform_battery_status.battery_status = *p++; 205 if (!AVRC_IS_VALID_BATTERY_STATUS(p_result->inform_battery_status.battery_status)) 206 status = AVRC_STS_BAD_PARAM; 207 } 208 break; 209 210 case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */ 211 if (len < 9) /* UID/8 and num_attr/1 */ 212 status = AVRC_STS_INTERNAL_ERR; 213 else 214 { 215 BE_STREAM_TO_UINT32 (u32, p); 216 BE_STREAM_TO_UINT32 (u32_2, p); 217 if (u32== 0 && u32_2 == 0) 218 { 219 BE_STREAM_TO_UINT8 (p_result->get_elem_attrs.num_attr, p); 220 if ( (len - 9/* UID/8 and num_attr/1 */) != (p_result->get_elem_attrs.num_attr * 4)) 221 status = AVRC_STS_INTERNAL_ERR; 222 else 223 { 224 p_u32 = p_result->get_elem_attrs.attrs; 225 if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE) 226 p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE; 227 for (xx=0; xx< p_result->get_elem_attrs.num_attr; xx++) 228 { 229 BE_STREAM_TO_UINT32 (p_u32[xx], p); 230 } 231 } 232 } 233 else 234 status = AVRC_STS_NOT_FOUND; 235 } 236 break; 237 238 case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */ 239 /* no additional parameters */ 240 if (len != 0) 241 status = AVRC_STS_INTERNAL_ERR; 242 break; 243 244 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */ 245 if (len != 5) 246 status = AVRC_STS_INTERNAL_ERR; 247 BE_STREAM_TO_UINT8 (p_result->reg_notif.event_id, p); 248 BE_STREAM_TO_UINT32 (p_result->reg_notif.param, p); 249 break; 250 251 /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */ 252 /* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */ 253 254 default: 255 status = AVRC_STS_BAD_CMD; 256 break; 257 } 258 259 return status; 260 } 261 262 /******************************************************************************* 263 ** 264 ** Function AVRC_ParsCommand 265 ** 266 ** Description This function is a superset of AVRC_ParsMetadata to parse the command. 267 ** 268 ** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 269 ** Otherwise, the error code defined by AVRCP 1.4 270 ** 271 *******************************************************************************/ 272 tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len) 273 { 274 tAVRC_STS status = AVRC_STS_INTERNAL_ERR; 275 UINT16 id; 276 277 if (p_msg && p_result) 278 { 279 switch (p_msg->hdr.opcode) 280 { 281 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */ 282 status = avrc_pars_vendor_cmd(&p_msg->vendor, p_result, p_buf, buf_len); 283 break; 284 285 case AVRC_OP_PASS_THRU: /* 0x7C panel subunit opcode */ 286 status = avrc_pars_pass_thru(&p_msg->pass, &id); 287 if (status == AVRC_STS_NO_ERROR) 288 { 289 p_result->pdu = (UINT8)id; 290 } 291 break; 292 293 default: 294 AVRC_TRACE_ERROR1("AVRC_ParsCommand() unknown opcode:0x%x", p_msg->hdr.opcode); 295 break; 296 } 297 p_result->cmd.opcode = p_msg->hdr.opcode; 298 p_result->cmd.status = status; 299 } 300 AVRC_TRACE_DEBUG1("AVRC_ParsCommand() return status:0x%x", status); 301 return status; 302 } 303 304 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */ 305 306