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 20 #include "bt_common.h" 21 #include "avrc_api.h" 22 #include "avrc_defs.h" 23 #include "avrc_int.h" 24 #include "bt_utils.h" 25 26 /***************************************************************************** 27 ** Global data 28 *****************************************************************************/ 29 30 #if (AVRC_METADATA_INCLUDED == TRUE) 31 32 /******************************************************************************* 33 ** 34 ** Function avrc_pars_vendor_rsp 35 ** 36 ** Description This function parses the vendor specific commands defined by 37 ** Bluetooth SIG 38 ** 39 ** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 40 ** Otherwise, the error code defined by AVRCP 1.4 41 ** 42 *******************************************************************************/ 43 static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p_result) 44 { 45 tAVRC_STS status = AVRC_STS_NO_ERROR; 46 UINT8 *p; 47 UINT16 len; 48 #if (AVRC_ADV_CTRL_INCLUDED == TRUE) 49 UINT8 eventid=0; 50 #endif 51 52 /* Check the vendor data */ 53 if (p_msg->vendor_len == 0) 54 return AVRC_STS_NO_ERROR; 55 if (p_msg->p_vendor_data == NULL) 56 return AVRC_STS_INTERNAL_ERR; 57 58 p = p_msg->p_vendor_data; 59 BE_STREAM_TO_UINT8 (p_result->pdu, p); 60 p++; /* skip the reserved/packe_type byte */ 61 BE_STREAM_TO_UINT16 (len, p); 62 AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d/0x%x", 63 __func__, p_msg->hdr.ctype, p_result->pdu, len, len); 64 if (p_msg->hdr.ctype == AVRC_RSP_REJ) 65 { 66 p_result->rsp.status = *p; 67 return p_result->rsp.status; 68 } 69 70 switch (p_result->pdu) 71 { 72 /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */ 73 /* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */ 74 75 #if (AVRC_ADV_CTRL_INCLUDED == TRUE) 76 case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */ 77 if (len != 1) 78 status = AVRC_STS_INTERNAL_ERR; 79 else 80 { 81 BE_STREAM_TO_UINT8 (p_result->volume.volume, p); 82 } 83 break; 84 #endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */ 85 86 case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */ 87 #if (AVRC_ADV_CTRL_INCLUDED == TRUE) 88 BE_STREAM_TO_UINT8 (eventid, p); 89 if(AVRC_EVT_VOLUME_CHANGE==eventid 90 && (AVRC_RSP_CHANGED==p_msg->hdr.ctype || AVRC_RSP_INTERIM==p_msg->hdr.ctype 91 || AVRC_RSP_REJ==p_msg->hdr.ctype || AVRC_RSP_NOT_IMPL==p_msg->hdr.ctype)) 92 { 93 p_result->reg_notif.status=p_msg->hdr.ctype; 94 p_result->reg_notif.event_id=eventid; 95 BE_STREAM_TO_UINT8 (p_result->reg_notif.param.volume, p); 96 } 97 AVRC_TRACE_DEBUG("%s PDU reg notif response:event %x, volume %x", 98 __func__, eventid, p_result->reg_notif.param.volume); 99 #endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */ 100 break; 101 default: 102 status = AVRC_STS_BAD_CMD; 103 break; 104 } 105 106 return status; 107 } 108 109 void avrc_parse_notification_rsp (UINT8 *p_stream, tAVRC_REG_NOTIF_RSP *p_rsp) 110 { 111 BE_STREAM_TO_UINT8(p_rsp->event_id, p_stream); 112 switch (p_rsp->event_id) 113 { 114 case AVRC_EVT_PLAY_STATUS_CHANGE: 115 BE_STREAM_TO_UINT8(p_rsp->param.play_status, p_stream); 116 break; 117 118 case AVRC_EVT_TRACK_CHANGE: 119 BE_STREAM_TO_ARRAY(p_stream, p_rsp->param.track, 8); 120 break; 121 122 case AVRC_EVT_APP_SETTING_CHANGE: 123 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.num_attr, p_stream); 124 for (int index = 0; index < p_rsp->param.player_setting.num_attr; index++) 125 { 126 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_id[index], p_stream); 127 BE_STREAM_TO_UINT8(p_rsp->param.player_setting.attr_value[index], p_stream); 128 } 129 break; 130 131 case AVRC_EVT_NOW_PLAYING_CHANGE: 132 break; 133 134 case AVRC_EVT_AVAL_PLAYERS_CHANGE: 135 break; 136 137 case AVRC_EVT_ADDR_PLAYER_CHANGE: 138 break; 139 140 case AVRC_EVT_UIDS_CHANGE: 141 break; 142 143 case AVRC_EVT_TRACK_REACHED_END: 144 case AVRC_EVT_TRACK_REACHED_START: 145 case AVRC_EVT_PLAY_POS_CHANGED: 146 case AVRC_EVT_BATTERY_STATUS_CHANGE: 147 case AVRC_EVT_SYSTEM_STATUS_CHANGE: 148 default: 149 break; 150 } 151 } 152 153 #if (AVRC_CTLR_INCLUDED == TRUE) 154 /******************************************************************************* 155 ** 156 ** Function avrc_ctrl_pars_vendor_rsp 157 ** 158 ** Description This function parses the vendor specific commands defined by 159 ** Bluetooth SIG 160 ** 161 ** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 162 ** Otherwise, the error code defined by AVRCP 1.4 163 ** 164 *******************************************************************************/ 165 static tAVRC_STS avrc_ctrl_pars_vendor_rsp( 166 tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p_result, UINT8* p_buf, UINT16* buf_len) 167 { 168 UINT8 *p = p_msg->p_vendor_data; 169 BE_STREAM_TO_UINT8 (p_result->pdu, p); 170 p++; /* skip the reserved/packe_type byte */ 171 172 UINT16 len; 173 BE_STREAM_TO_UINT16 (len, p); 174 AVRC_TRACE_DEBUG("%s ctype:0x%x pdu:0x%x, len:%d", 175 __func__, p_msg->hdr.ctype, p_result->pdu, len); 176 /* Todo: Issue in handling reject, check */ 177 if (p_msg->hdr.ctype == AVRC_RSP_REJ) 178 { 179 p_result->rsp.status = *p; 180 return p_result->rsp.status; 181 } 182 183 /* TODO: Break the big switch into functions. */ 184 switch (p_result->pdu) 185 { 186 /* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */ 187 /* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */ 188 189 case AVRC_PDU_REGISTER_NOTIFICATION: 190 avrc_parse_notification_rsp(p, &p_result->reg_notif); 191 break; 192 193 case AVRC_PDU_GET_CAPABILITIES: 194 if (len == 0) 195 { 196 p_result->get_caps.count = 0; 197 p_result->get_caps.capability_id = 0; 198 break; 199 } 200 BE_STREAM_TO_UINT8(p_result->get_caps.capability_id, p); 201 BE_STREAM_TO_UINT8(p_result->get_caps.count, p); 202 AVRC_TRACE_DEBUG("%s cap id = %d, cap_count = %d ", 203 __func__, p_result->get_caps.capability_id, p_result->get_caps.count); 204 if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID) 205 { 206 for(int xx = 0; ((xx < p_result->get_caps.count) && (xx < AVRC_CAP_MAX_NUM_COMP_ID)); 207 xx++) 208 { 209 BE_STREAM_TO_UINT24(p_result->get_caps.param.company_id[xx], p); 210 } 211 } 212 else if (p_result->get_caps.capability_id == AVRC_CAP_EVENTS_SUPPORTED) 213 { 214 for(int xx = 0; ((xx < p_result->get_caps.count) && (xx < AVRC_CAP_MAX_NUM_EVT_ID)); 215 xx++) 216 { 217 BE_STREAM_TO_UINT8(p_result->get_caps.param.event_id[xx], p); 218 } 219 } 220 break; 221 222 case AVRC_PDU_LIST_PLAYER_APP_ATTR: 223 if (len == 0) 224 { 225 p_result->list_app_attr.num_attr = 0; 226 break; 227 } 228 BE_STREAM_TO_UINT8(p_result->list_app_attr.num_attr, p); 229 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__, p_result->list_app_attr.num_attr); 230 for(int xx = 0; xx < p_result->list_app_attr.num_attr; xx++) 231 { 232 BE_STREAM_TO_UINT8(p_result->list_app_attr.attrs[xx], p); 233 } 234 break; 235 236 case AVRC_PDU_LIST_PLAYER_APP_VALUES: 237 if (len == 0) 238 { 239 p_result->list_app_values.num_val = 0; 240 break; 241 } 242 BE_STREAM_TO_UINT8(p_result->list_app_values.num_val, p); 243 AVRC_TRACE_DEBUG("%s value count = %d ", __func__, p_result->list_app_values.num_val); 244 for(int xx = 0; xx < p_result->list_app_values.num_val; xx++) 245 { 246 BE_STREAM_TO_UINT8(p_result->list_app_values.vals[xx], p); 247 } 248 break; 249 250 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: 251 { 252 if (len == 0) 253 { 254 p_result->get_cur_app_val.num_val = 0; 255 break; 256 } 257 BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_val, p); 258 tAVRC_APP_SETTING *app_sett = 259 (tAVRC_APP_SETTING*)osi_malloc(p_result->get_cur_app_val.num_val*sizeof(tAVRC_APP_SETTING)); 260 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__, p_result->get_cur_app_val.num_val); 261 for (int xx = 0; xx < p_result->get_cur_app_val.num_val; xx++) 262 { 263 BE_STREAM_TO_UINT8(app_sett[xx].attr_id, p); 264 BE_STREAM_TO_UINT8(app_sett[xx].attr_val, p); 265 } 266 p_result->get_cur_app_val.p_vals = app_sett; 267 } 268 break; 269 270 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: 271 { 272 tAVRC_APP_SETTING_TEXT *p_setting_text; 273 UINT8 num_attrs; 274 275 if (len == 0) 276 { 277 p_result->get_app_attr_txt.num_attr = 0; 278 break; 279 } 280 BE_STREAM_TO_UINT8(num_attrs, p); 281 AVRC_TRACE_DEBUG("%s attr count = %d ", __func__, p_result->get_app_attr_txt.num_attr); 282 p_result->get_app_attr_txt.num_attr = num_attrs; 283 p_setting_text = (tAVRC_APP_SETTING_TEXT*)osi_malloc(num_attrs * sizeof(tAVRC_APP_SETTING_TEXT)); 284 for (int xx = 0; xx < num_attrs; xx++) 285 { 286 BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].attr_id, p); 287 BE_STREAM_TO_UINT16(p_result->get_app_attr_txt.p_attrs[xx].charset_id, p); 288 BE_STREAM_TO_UINT8(p_result->get_app_attr_txt.p_attrs[xx].str_len, p); 289 if (p_result->get_app_attr_txt.p_attrs[xx].str_len != 0) 290 { 291 UINT8 *p_str = (UINT8 *)osi_malloc(p_result->get_app_attr_txt.p_attrs[xx].str_len); 292 BE_STREAM_TO_ARRAY(p, p_str, p_result->get_app_attr_txt.p_attrs[xx].str_len); 293 p_result->get_app_attr_txt.p_attrs[xx].p_str = p_str; 294 } else { 295 p_result->get_app_attr_txt.p_attrs[xx].p_str = NULL; 296 } 297 } 298 } 299 break; 300 301 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: 302 { 303 tAVRC_APP_SETTING_TEXT *p_setting_text; 304 UINT8 num_vals; 305 306 if (len == 0) 307 { 308 p_result->get_app_val_txt.num_attr = 0; 309 break; 310 } 311 BE_STREAM_TO_UINT8(num_vals, p); 312 p_result->get_app_val_txt.num_attr = num_vals; 313 AVRC_TRACE_DEBUG("%s value count = %d ", __func__, p_result->get_app_val_txt.num_attr); 314 315 p_setting_text = (tAVRC_APP_SETTING_TEXT *)osi_malloc(num_vals * sizeof(tAVRC_APP_SETTING_TEXT)); 316 for (int i = 0; i < num_vals; i++) { 317 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].attr_id, p); 318 BE_STREAM_TO_UINT16(p_result->get_app_val_txt.p_attrs[i].charset_id, p); 319 BE_STREAM_TO_UINT8(p_result->get_app_val_txt.p_attrs[i].str_len, p); 320 if (p_result->get_app_val_txt.p_attrs[i].str_len != 0) { 321 UINT8 *p_str = (UINT8 *)osi_malloc(p_result->get_app_val_txt.p_attrs[i].str_len); 322 BE_STREAM_TO_ARRAY(p, p_str, p_result->get_app_val_txt.p_attrs[i].str_len); 323 p_result->get_app_val_txt.p_attrs[i].p_str = p_str; 324 } else { 325 p_result->get_app_val_txt.p_attrs[i].p_str = NULL; 326 } 327 } 328 } 329 break; 330 331 case AVRC_PDU_SET_PLAYER_APP_VALUE: 332 /* nothing comes as part of this rsp */ 333 break; 334 335 case AVRC_PDU_GET_ELEMENT_ATTR: 336 { 337 UINT8 num_attrs; 338 339 if (len <= 0) 340 { 341 p_result->get_elem_attrs.num_attr = 0; 342 break; 343 } 344 BE_STREAM_TO_UINT8(num_attrs, p); 345 p_result->get_elem_attrs.num_attr = num_attrs; 346 if (num_attrs) 347 { 348 tAVRC_ATTR_ENTRY *p_attrs = 349 (tAVRC_ATTR_ENTRY*)osi_malloc(num_attrs * sizeof(tAVRC_ATTR_ENTRY)); 350 for (int i = 0; i < num_attrs; i++) { 351 BE_STREAM_TO_UINT32(p_attrs[i].attr_id, p); 352 BE_STREAM_TO_UINT16(p_attrs[i].name.charset_id, p); 353 BE_STREAM_TO_UINT16(p_attrs[i].name.str_len, p); 354 if (p_attrs[i].name.str_len > 0) { 355 p_attrs[i].name.p_str = (UINT8 *)osi_malloc(p_attrs[i].name.str_len); 356 BE_STREAM_TO_ARRAY(p, p_attrs[i].name.p_str, p_attrs[i].name.str_len); 357 } 358 } 359 p_result->get_elem_attrs.p_attrs = p_attrs; 360 } 361 } 362 break; 363 364 case AVRC_PDU_GET_PLAY_STATUS: 365 if (len == 0) 366 { 367 break; 368 } 369 BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p); 370 BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p); 371 BE_STREAM_TO_UINT8(p_result->get_play_status.status, p); 372 break; 373 374 default: 375 return AVRC_STS_BAD_CMD; 376 } 377 return AVRC_STS_NO_ERROR; 378 } 379 380 /******************************************************************************* 381 ** 382 ** Function AVRC_Ctrl_ParsResponse 383 ** 384 ** Description This function is a parse response for AVRCP Controller. 385 ** 386 ** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 387 ** Otherwise, the error code defined by AVRCP 1.4 388 ** 389 *******************************************************************************/ 390 tAVRC_STS AVRC_Ctrl_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result, UINT8 *p_buf, UINT16* buf_len) 391 { 392 tAVRC_STS status = AVRC_STS_INTERNAL_ERR; 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_ctrl_pars_vendor_rsp(&p_msg->vendor, p_result, p_buf,buf_len); 399 break; 400 401 default: 402 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode); 403 break; 404 } 405 p_result->rsp.opcode = p_msg->hdr.opcode; 406 p_result->rsp.status = status; 407 } 408 return status; 409 } 410 #endif /* (AVRC_CTRL_INCLUDED) == TRUE) */ 411 /******************************************************************************* 412 ** 413 ** Function AVRC_ParsResponse 414 ** 415 ** Description This function is a superset of AVRC_ParsMetadata to parse the response. 416 ** 417 ** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully. 418 ** Otherwise, the error code defined by AVRCP 1.4 419 ** 420 *******************************************************************************/ 421 tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result, UINT8 *p_buf, UINT16 buf_len) 422 { 423 tAVRC_STS status = AVRC_STS_INTERNAL_ERR; 424 UINT16 id; 425 UNUSED(p_buf); 426 UNUSED(buf_len); 427 428 if (p_msg && p_result) 429 { 430 switch (p_msg->hdr.opcode) 431 { 432 case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */ 433 status = avrc_pars_vendor_rsp(&p_msg->vendor, p_result); 434 break; 435 436 case AVRC_OP_PASS_THRU: /* 0x7C panel subunit opcode */ 437 status = avrc_pars_pass_thru(&p_msg->pass, &id); 438 if (status == AVRC_STS_NO_ERROR) 439 { 440 p_result->pdu = (UINT8)id; 441 } 442 break; 443 444 default: 445 AVRC_TRACE_ERROR("%s unknown opcode:0x%x", __func__, p_msg->hdr.opcode); 446 break; 447 } 448 p_result->rsp.opcode = p_msg->hdr.opcode; 449 p_result->rsp.status = status; 450 } 451 return status; 452 } 453 #endif /* (AVRC_METADATA_INCLUDED == TRUE) */ 454