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 "bt_common.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#if (AVRC_CTLR_INCLUDED == TRUE) 31/******************************************************************************* 32** 33** Function avrc_ctrl_pars_vendor_cmd 34** 35** Description This function parses the vendor specific commands defined by 36** Bluetooth SIG for AVRCP Conroller. 37** 38** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 39** Otherwise, the error code defined by AVRCP 1.4 40** 41*******************************************************************************/ 42static tAVRC_STS avrc_ctrl_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_result) 43{ 44 tAVRC_STS status = AVRC_STS_NO_ERROR; 45 46 UINT8 *p = p_msg->p_vendor_data; 47 p_result->pdu = *p++; 48 AVRC_TRACE_DEBUG("%s pdu:0x%x", __func__, p_result->pdu); 49 if (!AVRC_IsValidAvcType (p_result->pdu, p_msg->hdr.ctype)) 50 { 51 AVRC_TRACE_DEBUG("%s detects wrong AV/C type!", __func__); 52 status = AVRC_STS_BAD_CMD; 53 } 54 55 p++; /* skip the reserved byte */ 56 UINT16 len; 57 BE_STREAM_TO_UINT16 (len, p); 58 if ((len+4) != (p_msg->vendor_len)) 59 { 60 status = AVRC_STS_INTERNAL_ERR; 61 } 62 63 if (status != AVRC_STS_NO_ERROR) 64 return status; 65 66 switch (p_result->pdu) 67 { 68 case AVRC_PDU_SET_ABSOLUTE_VOLUME: 69 { 70 if(len!=1) 71 status = AVRC_STS_INTERNAL_ERR; 72 else 73 { 74 BE_STREAM_TO_UINT8 (p_result->volume.volume, p); 75 p_result->volume.volume = AVRC_MAX_VOLUME & p_result->volume.volume; 76 } 77 break; 78 } 79 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */ 80 BE_STREAM_TO_UINT8 (p_result->reg_notif.event_id, p); 81 BE_STREAM_TO_UINT32 (p_result->reg_notif.param, p); 82 break; 83 default: 84 status = AVRC_STS_BAD_CMD; 85 break; 86 } 87 return status; 88} 89#endif 90 91/******************************************************************************* 92** 93** Function avrc_pars_vendor_cmd 94** 95** Description This function parses the vendor specific commands defined by 96** Bluetooth SIG 97** 98** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 99** Otherwise, the error code defined by AVRCP 1.4 100** 101*******************************************************************************/ 102static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_result, 103 UINT8 *p_buf, UINT16 buf_len) 104{ 105 tAVRC_STS status = AVRC_STS_NO_ERROR; 106 UINT8 *p; 107 UINT16 len; 108 UINT8 xx, yy; 109 UINT8 *p_u8; 110 UINT16 *p_u16; 111 UINT32 u32, u32_2, *p_u32; 112 tAVRC_APP_SETTING *p_app_set; 113 UINT16 size_needed; 114 115 /* Check the vendor data */ 116 if (p_msg->vendor_len == 0) 117 return AVRC_STS_NO_ERROR; 118 if (p_msg->p_vendor_data == NULL) 119 return AVRC_STS_INTERNAL_ERR; 120 121 p = p_msg->p_vendor_data; 122 p_result->pdu = *p++; 123 AVRC_TRACE_DEBUG("%s pdu:0x%x", __func__, p_result->pdu); 124 if (!AVRC_IsValidAvcType (p_result->pdu, p_msg->hdr.ctype)) 125 { 126 AVRC_TRACE_DEBUG("%s detects wrong AV/C type!", __func__); 127 status = AVRC_STS_BAD_CMD; 128 } 129 130 p++; /* skip the reserved byte */ 131 BE_STREAM_TO_UINT16 (len, p); 132 if ((len+4) != (p_msg->vendor_len)) 133 { 134 status = AVRC_STS_INTERNAL_ERR; 135 } 136 137 if (status != AVRC_STS_NO_ERROR) 138 return status; 139 140 switch (p_result->pdu) 141 { 142 case AVRC_PDU_GET_CAPABILITIES: /* 0x10 */ 143 p_result->get_caps.capability_id = *p++; 144 if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id)) 145 status = AVRC_STS_BAD_PARAM; 146 else if (len != 1) 147 status = AVRC_STS_INTERNAL_ERR; 148 break; 149 150 case AVRC_PDU_LIST_PLAYER_APP_ATTR: /* 0x11 */ 151 /* no additional parameters */ 152 if (len != 0) 153 status = AVRC_STS_INTERNAL_ERR; 154 break; 155 156 case AVRC_PDU_LIST_PLAYER_APP_VALUES: /* 0x12 */ 157 p_result->list_app_values.attr_id = *p++; 158 if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id)) 159 status = AVRC_STS_BAD_PARAM; 160 else if (len != 1) 161 status = AVRC_STS_INTERNAL_ERR; 162 break; 163 164 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */ 165 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */ 166 BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p); 167 if (len != (p_result->get_cur_app_val.num_attr+1)) 168 { 169 status = AVRC_STS_INTERNAL_ERR; 170 break; 171 } 172 p_u8 = p_result->get_cur_app_val.attrs; 173 for (xx=0, yy=0; xx< p_result->get_cur_app_val.num_attr; xx++) 174 { 175 /* only report the valid player app attributes */ 176 if (AVRC_IsValidPlayerAttr(*p)) 177 p_u8[yy++] = *p; 178 p++; 179 } 180 p_result->get_cur_app_val.num_attr = yy; 181 if (yy == 0) 182 { 183 status = AVRC_STS_BAD_PARAM; 184 } 185 break; 186 187 case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */ 188 BE_STREAM_TO_UINT8 (p_result->set_app_val.num_val, p); 189 size_needed = sizeof(tAVRC_APP_SETTING); 190 if (p_buf && (len == ((p_result->set_app_val.num_val<<1) + 1))) 191 { 192 p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf; 193 p_app_set = p_result->set_app_val.p_vals; 194 for (xx=0; ((xx< p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++) 195 { 196 p_app_set[xx].attr_id = *p++; 197 p_app_set[xx].attr_val = *p++; 198 if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val)) 199 status = AVRC_STS_BAD_PARAM; 200 } 201 if (xx != p_result->set_app_val.num_val) 202 { 203 AVRC_TRACE_ERROR( 204 "%s AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d", 205 __func__, xx, p_result->set_app_val.num_val); 206 p_result->set_app_val.num_val = xx; 207 } 208 } 209 else 210 { 211 AVRC_TRACE_ERROR("%s AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len", 212 __func__); 213 status = AVRC_STS_INTERNAL_ERR; 214 } 215 break; 216 217 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:/* 0x16 */ 218 if (len < 3) 219 status = AVRC_STS_INTERNAL_ERR; 220 else 221 { 222 BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.attr_id, p); 223 if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id)) 224 status = AVRC_STS_BAD_PARAM; 225 else 226 { 227 BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.num_val, p); 228 if ( (len - 2/* attr_id & num_val */) != p_result->get_app_val_txt.num_val) 229 status = AVRC_STS_INTERNAL_ERR; 230 else 231 { 232 p_u8 = p_result->get_app_val_txt.vals; 233 for (xx=0; xx< p_result->get_app_val_txt.num_val; xx++) 234 { 235 p_u8[xx] = *p++; 236 if (!avrc_is_valid_player_attrib_value(p_result->get_app_val_txt.attr_id, 237 p_u8[xx])) 238 { 239 status = AVRC_STS_BAD_PARAM; 240 break; 241 } 242 } 243 } 244 } 245 } 246 break; 247 248 case AVRC_PDU_INFORM_DISPLAY_CHARSET: /* 0x17 */ 249 if (len < 3) 250 status = AVRC_STS_INTERNAL_ERR; 251 else 252 { 253 BE_STREAM_TO_UINT8 (p_result->inform_charset.num_id, p); 254 if ( (len - 1/* num_id */) != p_result->inform_charset.num_id * 2) 255 status = AVRC_STS_INTERNAL_ERR; 256 else 257 { 258 p_u16 = p_result->inform_charset.charsets; 259 if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE) 260 p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE; 261 for (xx=0; xx< p_result->inform_charset.num_id; xx++) 262 { 263 BE_STREAM_TO_UINT16 (p_u16[xx], p); 264 } 265 } 266 } 267 break; 268 269 case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:/* 0x18 */ 270 if (len != 1) 271 status = AVRC_STS_INTERNAL_ERR; 272 else 273 { 274 p_result->inform_battery_status.battery_status = *p++; 275 if (!AVRC_IS_VALID_BATTERY_STATUS(p_result->inform_battery_status.battery_status)) 276 status = AVRC_STS_BAD_PARAM; 277 } 278 break; 279 280 case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */ 281 if (len < 9) /* UID/8 and num_attr/1 */ 282 status = AVRC_STS_INTERNAL_ERR; 283 else 284 { 285 BE_STREAM_TO_UINT32 (u32, p); 286 BE_STREAM_TO_UINT32 (u32_2, p); 287 if (u32== 0 && u32_2 == 0) 288 { 289 BE_STREAM_TO_UINT8 (p_result->get_elem_attrs.num_attr, p); 290 if ( (len - 9/* UID/8 and num_attr/1 */) != (p_result->get_elem_attrs.num_attr * 4)) 291 status = AVRC_STS_INTERNAL_ERR; 292 else 293 { 294 p_u32 = p_result->get_elem_attrs.attrs; 295 if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE) 296 p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE; 297 for (xx=0; xx< p_result->get_elem_attrs.num_attr; xx++) 298 { 299 BE_STREAM_TO_UINT32 (p_u32[xx], p); 300 } 301 } 302 } 303 else 304 status = AVRC_STS_NOT_FOUND; 305 } 306 break; 307 308 case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */ 309 /* no additional parameters */ 310 if (len != 0) 311 status = AVRC_STS_INTERNAL_ERR; 312 break; 313 314 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */ 315 if (len != 5) 316 status = AVRC_STS_INTERNAL_ERR; 317 else 318 { 319 BE_STREAM_TO_UINT8 (p_result->reg_notif.event_id, p); 320 BE_STREAM_TO_UINT32 (p_result->reg_notif.param, p); 321 } 322 break; 323 324 case AVRC_PDU_SET_ABSOLUTE_VOLUME: 325 { 326 if(len!=1) 327 status = AVRC_STS_INTERNAL_ERR; 328 break; 329 } 330 331 /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */ 332 /* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */ 333 334 default: 335 status = AVRC_STS_BAD_CMD; 336 break; 337 } 338 339 return status; 340} 341 342#if (AVRC_CTLR_INCLUDED == TRUE) 343/******************************************************************************* 344** 345** Function AVRC_Ctrl_ParsCommand 346** 347** Description This function is used to parse cmds received for CTRL 348** Currently it is for SetAbsVolume and Volume Change Notification.. 349** 350** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 351** Otherwise, the error code defined by AVRCP 1.4 352** 353*******************************************************************************/ 354tAVRC_STS AVRC_Ctrl_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result) 355{ 356 tAVRC_STS status = AVRC_STS_INTERNAL_ERR; 357 358 if (p_msg && p_result) 359 { 360 switch (p_msg->hdr.opcode) 361 { 362 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */ 363 status = avrc_ctrl_pars_vendor_cmd(&p_msg->vendor, p_result); 364 break; 365 366 default: 367 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode); 368 break; 369 } 370 p_result->cmd.opcode = p_msg->hdr.opcode; 371 p_result->cmd.status = status; 372 } 373 AVRC_TRACE_DEBUG("%s return status:0x%x", __FUNCTION__, status); 374 return status; 375} 376#endif 377 378/******************************************************************************* 379** 380** Function AVRC_ParsCommand 381** 382** Description This function is a superset of AVRC_ParsMetadata to parse the command. 383** 384** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 385** Otherwise, the error code defined by AVRCP 1.4 386** 387*******************************************************************************/ 388tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len) 389{ 390 tAVRC_STS status = AVRC_STS_INTERNAL_ERR; 391 UINT16 id; 392 393 if (p_msg && p_result) 394 { 395 switch (p_msg->hdr.opcode) 396 { 397 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */ 398 status = avrc_pars_vendor_cmd(&p_msg->vendor, p_result, p_buf, buf_len); 399 break; 400 401 case AVRC_OP_PASS_THRU: /* 0x7C panel subunit opcode */ 402 status = avrc_pars_pass_thru(&p_msg->pass, &id); 403 if (status == AVRC_STS_NO_ERROR) 404 { 405 p_result->pdu = (UINT8)id; 406 } 407 break; 408 409 default: 410 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode); 411 break; 412 } 413 p_result->cmd.opcode = p_msg->hdr.opcode; 414 p_result->cmd.status = status; 415 } 416 AVRC_TRACE_DEBUG("%s return status:0x%x", __func__, status); 417 return status; 418} 419 420#endif /* (AVRC_METADATA_INCLUDED == TRUE) */ 421 422