Fork ESP-IDF's bluetooth component

i want better sbc encoding, and no cla will stop me
This commit is contained in:
jacqueline
2024-03-28 14:32:49 +11:00
parent 239e6d8950
commit ee29c25b29
1761 changed files with 737738 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,329 @@
/******************************************************************************
*
* Copyright (C) 2006-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include <string.h>
#include "common/bt_target.h"
#include "stack/avrc_api.h"
#include "stack/avrc_defs.h"
#include "avrc_int.h"
#include "osi/allocator.h"
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
/*****************************************************************************
** Global data
*****************************************************************************/
#if (AVRC_METADATA_INCLUDED == TRUE)
/*******************************************************************************
**
** Function avrc_bld_next_cmd
**
** Description This function builds the Request Continue or Abort command.
**
** Returns AVRC_STS_NO_ERROR, if the command is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_next_cmd (tAVRC_NEXT_CMD *p_cmd, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;
AVRC_TRACE_API("avrc_bld_next_cmd");
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */
/* add fixed lenth 1 - pdu_id (1) */
UINT16_TO_BE_STREAM(p_data, 1);
UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*****************************************************************************
** the following commands are introduced in AVRCP 1.4
*****************************************************************************/
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
/*******************************************************************************
**
** Function avrc_bld_set_abs_volume_cmd
**
** Description This function builds the Set Absolute Volume command.
**
** Returns AVRC_STS_NO_ERROR, if the command is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_set_abs_volume_cmd (tAVRC_SET_VOLUME_CMD *p_cmd, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;
AVRC_TRACE_API("avrc_bld_set_abs_volume_cmd");
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */
/* add fixed lenth 1 - volume (1) */
UINT16_TO_BE_STREAM(p_data, 1);
UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume));
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_vol_change_notfn
**
** Description This function builds the register notification for volume change.
**
** Returns AVRC_STS_NO_ERROR, if the command is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_register_change_notfn(UINT8 event_id, UINT32 event_parameter, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;
AVRC_TRACE_API("avrc_bld_vol_change");
/* get the existing length, if any, and also the num attributes */
// Set the notify value
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */
/* add fixed length 5 -*/
UINT16_TO_BE_STREAM(p_data, 5);
UINT8_TO_BE_STREAM(p_data, event_id);
UINT32_TO_BE_STREAM(p_data, event_parameter);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
#endif
/*******************************************************************************
**
** Function avrc_bld_init_cmd_buffer
**
** Description This function initializes the command buffer based on PDU
**
** Returns NULL, if no GKI buffer or failure to build the message.
** Otherwise, the GKI buffer that contains the initialized message.
**
*******************************************************************************/
static BT_HDR *avrc_bld_init_cmd_buffer(tAVRC_COMMAND *p_cmd)
{
UINT8 opcode = avrc_opcode_from_pdu(p_cmd->pdu);
AVRC_TRACE_API("avrc_bld_init_cmd_buffer: pdu=%x, opcode=%x", p_cmd->pdu, opcode);
UINT16 offset = 0;
switch (opcode) {
case AVRC_OP_PASS_THRU:
offset = AVRC_MSG_PASS_THRU_OFFSET;
break;
case AVRC_OP_VENDOR:
offset = AVRC_MSG_VENDOR_OFFSET;
break;
}
/* allocate and initialize the buffer */
BT_HDR *p_pkt = (BT_HDR *)osi_malloc(AVRC_META_CMD_BUF_SIZE);
if (p_pkt) {
UINT8 *p_data, *p_start;
p_pkt->layer_specific = AVCT_DATA_CTRL;
p_pkt->event = opcode;
p_pkt->offset = offset;
p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_start = p_data;
/* pass thru - group navigation - has a two byte op_id, so dont do it here */
if (opcode != AVRC_OP_PASS_THRU) {
*p_data++ = p_cmd->pdu;
}
switch (opcode) {
case AVRC_OP_VENDOR:
/* reserved 0, packet_type 0 */
UINT8_TO_BE_STREAM(p_data, 0);
/* continue to the next "case to add length */
/* add fixed lenth - 0 */
UINT16_TO_BE_STREAM(p_data, 0);
break;
}
p_pkt->len = (p_data - p_start);
}
p_cmd->cmd.opcode = opcode;
return p_pkt;
}
/*******************************************************************************
**
** Function avrc_bld_set_player_value_cmd
**
** Description This function builds the Set Player Application Value command.
**
** Returns AVRC_STS_NO_ERROR, if the command is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_set_player_value_cmd(tAVRC_SET_APP_VALUE_CMD *p_cmd, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */
/* add length */
UINT16_TO_BE_STREAM(p_data, 3);
/* Number of attributes */
UINT8_TO_BE_STREAM(p_data, 1);
UINT8_TO_BE_STREAM(p_data, p_cmd->p_vals->attr_id);
UINT8_TO_BE_STREAM(p_data, p_cmd->p_vals->attr_val);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_get_element_attr_cmd
**
** Description This function builds the Get Element Attribute command.
**
** Returns AVRC_STS_NO_ERROR, if the command is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_element_attr_cmd (tAVRC_GET_ELEM_ATTRS_CMD *p_cmd, BT_HDR *p_pkt)
{
int i;
UINT8 *p_data, *p_start;
AVRC_TRACE_API("avrc_bld_get_element_attr_cmd num_attr: %d", p_cmd->num_attr);
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */
/* add length */
UINT16_TO_BE_STREAM(p_data, 8 + 1 /* id + attr count */ + p_cmd->num_attr * sizeof(UINT32));
/* Identifier 0x0 (PLAYING) */
UINT64_TO_BE_STREAM(p_data, (UINT64)(0));
/* Attribute count */
UINT8_TO_BE_STREAM(p_data, p_cmd->num_attr);
for (i = 0; i < p_cmd->num_attr; i++) {
AVRC_TRACE_API("avrc_bld_get_element_attr_cmd attr_id: %d", p_cmd->attrs[i]);
UINT32_TO_BE_STREAM(p_data, p_cmd->attrs[i]);
}
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
static tAVRC_STS avrc_bld_get_caps_cmd(tAVRC_GET_CAPS_CMD *p_cmd, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;
AVRC_TRACE_API("avrc_bld_get_caps");
/* get the existing length, if any, and also the num attributes */
// Set the notify value
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */
/* add fixed length 1 */
UINT16_TO_BE_STREAM(p_data, 1);
/* capability id */
UINT8_TO_BE_STREAM(p_data, p_cmd->capability_id);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function AVRC_BldCommand
**
** Description This function builds the given AVRCP command to the given
** GKI buffer
**
** Returns AVRC_STS_NO_ERROR, if the command is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt)
{
tAVRC_STS status = AVRC_STS_BAD_PARAM;
BT_HDR *p_pkt;
BOOLEAN alloc = FALSE;
AVRC_TRACE_API("AVRC_BldCommand: pdu=%x status=%x", p_cmd->cmd.pdu, p_cmd->cmd.status);
if (!p_cmd || !pp_pkt) {
AVRC_TRACE_API("AVRC_BldCommand. Invalid parameters passed. p_cmd=%p, pp_pkt=%p",
p_cmd, pp_pkt);
return AVRC_STS_BAD_PARAM;
}
if (*pp_pkt == NULL) {
if ((*pp_pkt = avrc_bld_init_cmd_buffer(p_cmd)) == NULL) {
AVRC_TRACE_API("AVRC_BldCommand: Failed to initialize command buffer");
return AVRC_STS_INTERNAL_ERR;
}
alloc = TRUE;
}
status = AVRC_STS_NO_ERROR;
p_pkt = *pp_pkt;
switch (p_cmd->pdu) {
case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
status = avrc_bld_next_cmd(&p_cmd->continu, p_pkt);
break;
case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
status = avrc_bld_next_cmd(&p_cmd->abort, p_pkt);
break;
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
status = avrc_bld_set_abs_volume_cmd(&p_cmd->volume, p_pkt);
break;
#endif
case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
status = avrc_bld_set_player_value_cmd(&p_cmd->set_app_val, p_pkt);
break;
case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */
status = avrc_bld_get_element_attr_cmd(&p_cmd->get_elem_attrs, p_pkt);
break;
case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
status = avrc_bld_register_change_notfn(p_cmd->reg_notif.event_id, p_cmd->reg_notif.param, p_pkt);
break;
case AVRC_PDU_GET_CAPABILITIES:
status = avrc_bld_get_caps_cmd(&p_cmd->get_caps, p_pkt);
break;
}
if (alloc && (status != AVRC_STS_NO_ERROR) ) {
osi_free(p_pkt);
*pp_pkt = NULL;
}
AVRC_TRACE_API("AVRC_BldCommand: returning %d", status);
return status;
}
#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
#endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */
@@ -0,0 +1,892 @@
/******************************************************************************
*
* Copyright (C) 2003-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include <string.h>
#include "common/bt_target.h"
#include "stack/avrc_api.h"
#include "stack/avrc_defs.h"
#include "avrc_int.h"
#include "common/bt_defs.h"
#include "osi/allocator.h"
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
/*****************************************************************************
** Global data
*****************************************************************************/
#if (AVRC_METADATA_INCLUDED == TRUE)
/*******************************************************************************
**
** Function avrc_bld_get_capability_rsp
**
** Description This function builds the Get Capability response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_capability_rsp (tAVRC_GET_CAPS_RSP *p_rsp, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start, *p_len, *p_count;
UINT16 len = 0;
UINT8 xx;
UINT32 *p_company_id;
UINT8 *p_event_id;
tAVRC_STS status = AVRC_STS_NO_ERROR;
if (!(AVRC_IS_VALID_CAP_ID(p_rsp->capability_id))) {
AVRC_TRACE_ERROR("avrc_bld_get_capability_rsp bad parameter. p_rsp: %x", (int)p_rsp);
status = AVRC_STS_BAD_PARAM;
return status;
}
AVRC_TRACE_API("avrc_bld_get_capability_rsp");
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_len = p_start + 2; /* pdu + rsvd */
BE_STREAM_TO_UINT16(len, p_data);
UINT8_TO_BE_STREAM(p_data, p_rsp->capability_id);
p_count = p_data;
if (len == 0) {
*p_count = p_rsp->count;
p_data++;
len = 2; /* move past the capability_id and count */
} else {
p_data = p_start + p_pkt->len;
*p_count += p_rsp->count;
}
if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) {
p_company_id = p_rsp->param.company_id;
for (xx = 0; xx < p_rsp->count; xx++) {
UINT24_TO_BE_STREAM(p_data, p_company_id[xx]);
}
len += p_rsp->count * 3;
} else {
p_event_id = p_rsp->param.event_id;
*p_count = 0;
for (xx = 0; xx < p_rsp->count; xx++) {
if (AVRC_IS_VALID_EVENT_ID(p_event_id[xx])) {
(*p_count)++;
UINT8_TO_BE_STREAM(p_data, p_event_id[xx]);
}
}
len += (*p_count);
}
UINT16_TO_BE_STREAM(p_len, len);
p_pkt->len = (p_data - p_start);
status = AVRC_STS_NO_ERROR;
return status;
}
/*******************************************************************************
**
** Function avrc_bld_list_app_settings_attr_rsp
**
** Description This function builds the List Application Settings Attribute
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_list_app_settings_attr_rsp (tAVRC_LIST_APP_ATTR_RSP *p_rsp, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start, *p_len, *p_num;
UINT16 len = 0;
UINT8 xx;
AVRC_TRACE_API("avrc_bld_list_app_settings_attr_rsp");
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_len = p_start + 2; /* pdu + rsvd */
BE_STREAM_TO_UINT16(len, p_data);
p_num = p_data;
if (len == 0) {
/* first time initialize the attribute count */
*p_num = 0;
p_data++;
} else {
p_data = p_start + p_pkt->len;
}
for (xx = 0; xx < p_rsp->num_attr; xx++) {
if (AVRC_IsValidPlayerAttr(p_rsp->attrs[xx])) {
(*p_num)++;
UINT8_TO_BE_STREAM(p_data, p_rsp->attrs[xx]);
}
}
len = *p_num + 1;
UINT16_TO_BE_STREAM(p_len, len);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_list_app_settings_values_rsp
**
** Description This function builds the List Application Setting Values
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_list_app_settings_values_rsp (tAVRC_LIST_APP_VALUES_RSP *p_rsp,
BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start, *p_len, *p_num;
UINT8 xx;
UINT16 len;
AVRC_TRACE_API("avrc_bld_list_app_settings_values_rsp");
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_len = p_start + 2; /* pdu + rsvd */
/* get the existing length, if any, and also the num attributes */
BE_STREAM_TO_UINT16(len, p_data);
p_num = p_data;
/* first time initialize the attribute count */
if (len == 0) {
*p_num = p_rsp->num_val;
p_data++;
} else {
p_data = p_start + p_pkt->len;
*p_num += p_rsp->num_val;
}
for (xx = 0; xx < p_rsp->num_val; xx++) {
UINT8_TO_BE_STREAM(p_data, p_rsp->vals[xx]);
}
len = *p_num + 1;
UINT16_TO_BE_STREAM(p_len, len);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_get_cur_app_setting_value_rsp
**
** Description This function builds the Get Current Application Setting Value
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp (tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp,
BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start, *p_len, *p_count;
UINT16 len;
UINT8 xx;
if (!p_rsp->p_vals) {
AVRC_TRACE_ERROR("avrc_bld_get_cur_app_setting_value_rsp NULL parameter");
return AVRC_STS_BAD_PARAM;
}
AVRC_TRACE_API("avrc_bld_get_cur_app_setting_value_rsp");
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_len = p_start + 2; /* pdu + rsvd */
BE_STREAM_TO_UINT16(len, p_data);
p_count = p_data;
if (len == 0) {
/* first time initialize the attribute count */
*p_count = 0;
p_data++;
} else {
p_data = p_start + p_pkt->len;
}
for (xx = 0; xx < p_rsp->num_val; xx++) {
if (avrc_is_valid_player_attrib_value(p_rsp->p_vals[xx].attr_id, p_rsp->p_vals[xx].attr_val)) {
(*p_count)++;
UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_id);
UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_val);
}
}
len = ((*p_count) << 1) + 1;
UINT16_TO_BE_STREAM(p_len, len);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_set_app_setting_value_rsp
**
** Description This function builds the Set Application Setting Value
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_set_app_setting_value_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
{
UNUSED(p_rsp);
UNUSED(p_pkt);
/* nothing to be added. */
AVRC_TRACE_API("avrc_bld_set_app_setting_value_rsp");
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_app_setting_text_rsp
**
** Description This function builds the Get Application Settings Attribute Text
** or Get Application Settings Value Text response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start, *p_len, *p_count;
UINT16 len, len_left;
UINT8 xx;
tAVRC_STS sts = AVRC_STS_NO_ERROR;
UINT8 num_added = 0;
if (!p_rsp->p_attrs) {
AVRC_TRACE_ERROR("avrc_bld_app_setting_text_rsp NULL parameter");
return AVRC_STS_BAD_PARAM;
}
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_len = p_start + 2; /* pdu + rsvd */
/*
* NOTE: The buffer is allocated within avrc_bld_init_rsp_buffer(), and is
* always of size BT_DEFAULT_BUFFER_SIZE.
*/
len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE - p_pkt->offset - p_pkt->len;
BE_STREAM_TO_UINT16(len, p_data);
p_count = p_data;
if (len == 0) {
*p_count = 0;
p_data++;
} else {
p_data = p_start + p_pkt->len;
}
for (xx = 0; xx < p_rsp->num_attr; xx++) {
if (len_left < (p_rsp->p_attrs[xx].str_len + 4)) {
AVRC_TRACE_ERROR("avrc_bld_app_setting_text_rsp out of room %d(str_len:%d, left:%d)",
xx, p_rsp->p_attrs[xx].str_len, len_left);
p_rsp->num_attr = num_added;
sts = AVRC_STS_INTERNAL_ERR;
break;
}
if ( !p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str ) {
AVRC_TRACE_ERROR("avrc_bld_app_setting_text_rsp NULL attr text[%d]", xx);
continue;
}
UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id);
UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len);
ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, p_rsp->p_attrs[xx].str_len);
(*p_count)++;
num_added++;
}
len = p_data - p_count;
UINT16_TO_BE_STREAM(p_len, len);
p_pkt->len = (p_data - p_start);
return sts;
}
/*******************************************************************************
**
** Function avrc_bld_get_app_setting_attr_text_rsp
**
** Description This function builds the Get Application Setting Attribute Text
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_app_setting_attr_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp,
BT_HDR *p_pkt)
{
AVRC_TRACE_API("avrc_bld_get_app_setting_attr_text_rsp");
return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
}
/*******************************************************************************
**
** Function avrc_bld_get_app_setting_value_text_rsp
**
** Description This function builds the Get Application Setting Value Text
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_app_setting_value_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp,
BT_HDR *p_pkt)
{
AVRC_TRACE_API("avrc_bld_get_app_setting_value_text_rsp");
return avrc_bld_app_setting_text_rsp(p_rsp, p_pkt);
}
/*******************************************************************************
**
** Function avrc_bld_inform_charset_rsp
**
** Description This function builds the Inform Displayable Character Set
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_inform_charset_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
{
UNUSED(p_rsp);
UNUSED(p_pkt);
/* nothing to be added. */
AVRC_TRACE_API("avrc_bld_inform_charset_rsp");
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_inform_battery_status_rsp
**
** Description This function builds the Inform Battery Status
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_inform_battery_status_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
{
UNUSED(p_rsp);
UNUSED(p_pkt);
/* nothing to be added. */
AVRC_TRACE_API("avrc_bld_inform_battery_status_rsp");
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_get_elem_attrs_rsp
**
** Description This function builds the Get Element Attributes
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start, *p_len, *p_count;
UINT16 len;
UINT8 xx;
AVRC_TRACE_API("avrc_bld_get_elem_attrs_rsp");
if (!p_rsp->p_attrs) {
AVRC_TRACE_ERROR("avrc_bld_get_elem_attrs_rsp NULL parameter");
return AVRC_STS_BAD_PARAM;
}
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_len = p_start + 2; /* pdu + rsvd */
BE_STREAM_TO_UINT16(len, p_data);
p_count = p_data;
if (len == 0) {
*p_count = 0;
p_data++;
} else {
p_data = p_start + p_pkt->len;
}
for (xx = 0; xx < p_rsp->num_attr; xx++) {
if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id)) {
AVRC_TRACE_ERROR("avrc_bld_get_elem_attrs_rsp invalid attr id[%d]: %d", xx, p_rsp->p_attrs[xx].attr_id);
continue;
}
if ( !p_rsp->p_attrs[xx].name.p_str ) {
p_rsp->p_attrs[xx].name.str_len = 0;
}
UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id);
UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len);
ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len);
(*p_count)++;
}
len = p_data - p_count;
UINT16_TO_BE_STREAM(p_len, len);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_get_play_status_rsp
**
** Description This function builds the Get Play Status
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_play_status_rsp (tAVRC_GET_PLAY_STATUS_RSP *p_rsp, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;
AVRC_TRACE_API("avrc_bld_get_play_status_rsp");
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2;
/* add fixed lenth - song len(4) + song position(4) + status(1) */
UINT16_TO_BE_STREAM(p_data, 9);
UINT32_TO_BE_STREAM(p_data, p_rsp->song_len);
UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos);
UINT8_TO_BE_STREAM(p_data, p_rsp->play_status);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_notify_rsp
**
** Description This function builds the Notification response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;
UINT8 *p_len;
UINT16 len = 0;
UINT8 xx;
tAVRC_STS status = AVRC_STS_NO_ERROR;
AVRC_TRACE_API("avrc_bld_notify_rsp");
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_len = p_start + 2; /* pdu + rsvd */
p_data += 2;
UINT8_TO_BE_STREAM(p_data, p_rsp->event_id);
switch (p_rsp->event_id) {
case AVRC_EVT_PLAY_STATUS_CHANGE: /* 0x01 */
/* p_rsp->param.play_status >= AVRC_PLAYSTATE_STOPPED is always TRUE */
if ((p_rsp->param.play_status <= AVRC_PLAYSTATE_REV_SEEK) ||
(p_rsp->param.play_status == AVRC_PLAYSTATE_ERROR) ) {
UINT8_TO_BE_STREAM(p_data, p_rsp->param.play_status);
len = 2;
} else {
AVRC_TRACE_ERROR("bad play state");
status = AVRC_STS_BAD_PARAM;
}
break;
case AVRC_EVT_TRACK_CHANGE: /* 0x02 */
ARRAY_TO_BE_STREAM(p_data, p_rsp->param.track, AVRC_UID_SIZE);
len = (UINT8)(AVRC_UID_SIZE + 1);
break;
case AVRC_EVT_TRACK_REACHED_END: /* 0x03 */
case AVRC_EVT_TRACK_REACHED_START: /* 0x04 */
len = 1;
break;
case AVRC_EVT_PLAY_POS_CHANGED: /* 0x05 */
UINT32_TO_BE_STREAM(p_data, p_rsp->param.play_pos);
len = 5;
break;
case AVRC_EVT_BATTERY_STATUS_CHANGE: /* 0x06 */
if (AVRC_IS_VALID_BATTERY_STATUS(p_rsp->param.battery_status)) {
UINT8_TO_BE_STREAM(p_data, p_rsp->param.battery_status);
len = 2;
} else {
AVRC_TRACE_ERROR("bad battery status");
status = AVRC_STS_BAD_PARAM;
}
break;
case AVRC_EVT_SYSTEM_STATUS_CHANGE: /* 0x07 */
if (AVRC_IS_VALID_SYSTEM_STATUS(p_rsp->param.system_status)) {
UINT8_TO_BE_STREAM(p_data, p_rsp->param.system_status);
len = 2;
} else {
AVRC_TRACE_ERROR("bad system status");
status = AVRC_STS_BAD_PARAM;
}
break;
case AVRC_EVT_APP_SETTING_CHANGE: /* 0x08 */
if (p_rsp->param.player_setting.num_attr > AVRC_MAX_APP_SETTINGS) {
p_rsp->param.player_setting.num_attr = AVRC_MAX_APP_SETTINGS;
}
if (p_rsp->param.player_setting.num_attr > 0) {
UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.num_attr);
len = 2;
for (xx = 0; xx < p_rsp->param.player_setting.num_attr; xx++) {
if (avrc_is_valid_player_attrib_value(p_rsp->param.player_setting.attr_id[xx],
p_rsp->param.player_setting.attr_value[xx])) {
UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_id[xx]);
UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_value[xx]);
} else {
AVRC_TRACE_ERROR("bad player app seeting attribute or value");
status = AVRC_STS_BAD_PARAM;
break;
}
len += 2;
}
} else {
status = AVRC_STS_BAD_PARAM;
}
break;
case AVRC_EVT_VOLUME_CHANGE:
UINT8_TO_BE_STREAM(p_data, p_rsp->param.volume);
len = 2;
break;
default:
status = AVRC_STS_BAD_PARAM;
AVRC_TRACE_ERROR("unknown event_id");
}
UINT16_TO_BE_STREAM(p_len, len);
p_pkt->len = (p_data - p_start);
return status;
}
/*******************************************************************************
**
** Function avrc_bld_next_rsp
**
** Description This function builds the Request Continue or Abort
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_next_rsp (tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
{
UNUSED(p_rsp);
UNUSED(p_pkt);
/* nothing to be added. */
AVRC_TRACE_API("avrc_bld_next_rsp");
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_group_navigation_rsp
**
** Description This function builds the Group Navigation
** response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
tAVRC_STS avrc_bld_group_navigation_rsp (UINT16 navi_id, BT_HDR *p_pkt)
{
UINT8 *p_data;
if (!AVRC_IS_VALID_GROUP(navi_id)) {
AVRC_TRACE_ERROR("avrc_bld_group_navigation_rsp bad navigation op id: %d", navi_id);
return AVRC_STS_BAD_PARAM;
}
AVRC_TRACE_API("avrc_bld_group_navigation_rsp");
p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
UINT16_TO_BE_STREAM(p_data, navi_id);
p_pkt->len = 2;
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_set_absolute_volume_rsp
**
** Description This function builds the Set Absolute Volume command
** response
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
tAVRC_STS avrc_bld_set_absolute_volume_rsp(tAVRC_SET_VOLUME_RSP *p_rsp, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */
UINT16_TO_BE_STREAM(p_data, 1); /* fixed length 1 */
UINT8_TO_BE_STREAM(p_data, p_rsp->volume);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_rejected_rsp
**
** Description This function builds the General Response response.
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_rejected_rsp( tAVRC_RSP *p_rsp, BT_HDR *p_pkt )
{
UINT8 *p_data, *p_start;
AVRC_TRACE_API("avrc_bld_rejected_rsp: status=%d, pdu:x%x", p_rsp->status, p_rsp->pdu);
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2;
AVRC_TRACE_DEBUG("pdu:x%x", *p_start);
UINT16_TO_BE_STREAM(p_data, 1);
UINT8_TO_BE_STREAM(p_data, p_rsp->status);
p_pkt->len = p_data - p_start;
return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
**
** Function avrc_bld_init_rsp_buffer
**
** Description This function initializes the response buffer based on PDU
**
** Returns NULL, if no GKI buffer or failure to build the message.
** Otherwise, the GKI buffer that contains the initialized message.
**
*******************************************************************************/
static BT_HDR *avrc_bld_init_rsp_buffer(tAVRC_RESPONSE *p_rsp)
{
UINT16 offset = AVRC_MSG_PASS_THRU_OFFSET;
UINT16 chnl = AVCT_DATA_CTRL;
UINT8 opcode = avrc_opcode_from_pdu(p_rsp->pdu);
AVRC_TRACE_API("avrc_bld_init_rsp_buffer: pdu=%x, opcode=%x/%x", p_rsp->pdu, opcode,
p_rsp->rsp.opcode);
if (opcode != p_rsp->rsp.opcode && p_rsp->rsp.status != AVRC_STS_NO_ERROR &&
avrc_is_valid_opcode(p_rsp->rsp.opcode)) {
opcode = p_rsp->rsp.opcode;
AVRC_TRACE_API("opcode=%x", opcode);
}
switch (opcode) {
case AVRC_OP_PASS_THRU:
offset = AVRC_MSG_PASS_THRU_OFFSET;
break;
case AVRC_OP_VENDOR:
offset = AVRC_MSG_VENDOR_OFFSET;
break;
}
/* allocate and initialize the buffer */
BT_HDR *p_pkt = (BT_HDR *)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
if (p_pkt) {
UINT8 *p_data, *p_start;
p_pkt->layer_specific = chnl;
p_pkt->event = opcode;
p_pkt->offset = offset;
p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_start = p_data;
/* pass thru - group navigation - has a two byte op_id, so dont do it here */
if (opcode != AVRC_OP_PASS_THRU) {
*p_data++ = p_rsp->pdu;
}
switch (opcode) {
case AVRC_OP_VENDOR:
/* reserved 0, packet_type 0 */
UINT8_TO_BE_STREAM(p_data, 0);
/* continue to the next "case to add length */
/* add fixed lenth - 0 */
UINT16_TO_BE_STREAM(p_data, 0);
break;
}
p_pkt->len = (p_data - p_start);
}
p_rsp->rsp.opcode = opcode;
return p_pkt;
}
/*******************************************************************************
**
** Function AVRC_BldResponse
**
** Description This function builds the given AVRCP response to the given
** GKI buffer
**
** Returns AVRC_STS_NO_ERROR, if the response is built successfully
** Otherwise, the error code.
**
*******************************************************************************/
tAVRC_STS AVRC_BldResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_pkt)
{
tAVRC_STS status = AVRC_STS_BAD_PARAM;
BT_HDR *p_pkt;
BOOLEAN alloc = FALSE;
UNUSED(handle);
if (!p_rsp || !pp_pkt) {
AVRC_TRACE_API("AVRC_BldResponse. Invalid parameters passed. p_rsp=%p, pp_pkt=%p",
p_rsp, pp_pkt);
return AVRC_STS_BAD_PARAM;
}
if (*pp_pkt == NULL) {
if ((*pp_pkt = avrc_bld_init_rsp_buffer(p_rsp)) == NULL) {
AVRC_TRACE_API("AVRC_BldResponse: Failed to initialize response buffer");
return AVRC_STS_INTERNAL_ERR;
}
alloc = TRUE;
}
status = AVRC_STS_NO_ERROR;
p_pkt = *pp_pkt;
AVRC_TRACE_API("AVRC_BldResponse: pdu=%x status=%x", p_rsp->rsp.pdu, p_rsp->rsp.status);
if (p_rsp->rsp.status != AVRC_STS_NO_ERROR) {
return ( avrc_bld_rejected_rsp(&p_rsp->rsp, p_pkt) );
}
switch (p_rsp->pdu) {
case AVRC_PDU_NEXT_GROUP:
case AVRC_PDU_PREV_GROUP:
status = avrc_bld_group_navigation_rsp(p_rsp->pdu, p_pkt);
break;
case AVRC_PDU_GET_CAPABILITIES:
status = avrc_bld_get_capability_rsp(&p_rsp->get_caps, p_pkt);
break;
case AVRC_PDU_LIST_PLAYER_APP_ATTR:
status = avrc_bld_list_app_settings_attr_rsp(&p_rsp->list_app_attr, p_pkt);
break;
case AVRC_PDU_LIST_PLAYER_APP_VALUES:
status = avrc_bld_list_app_settings_values_rsp(&p_rsp->list_app_values, p_pkt);
break;
case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
status = avrc_bld_get_cur_app_setting_value_rsp(&p_rsp->get_cur_app_val, p_pkt);
break;
case AVRC_PDU_SET_PLAYER_APP_VALUE:
status = avrc_bld_set_app_setting_value_rsp(&p_rsp->set_app_val, p_pkt);
break;
case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
status = avrc_bld_get_app_setting_attr_text_rsp(&p_rsp->get_app_attr_txt, p_pkt);
break;
case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
status = avrc_bld_get_app_setting_value_text_rsp(&p_rsp->get_app_val_txt, p_pkt);
break;
case AVRC_PDU_INFORM_DISPLAY_CHARSET:
status = avrc_bld_inform_charset_rsp(&p_rsp->inform_charset, p_pkt);
break;
case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:
status = avrc_bld_inform_battery_status_rsp(&p_rsp->inform_battery_status, p_pkt);
break;
case AVRC_PDU_GET_ELEMENT_ATTR:
status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_elem_attrs, p_pkt);
break;
case AVRC_PDU_GET_PLAY_STATUS:
status = avrc_bld_get_play_status_rsp(&p_rsp->get_play_status, p_pkt);
break;
case AVRC_PDU_REGISTER_NOTIFICATION:
status = avrc_bld_notify_rsp(&p_rsp->reg_notif, p_pkt);
break;
case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
status = avrc_bld_next_rsp(&p_rsp->continu, p_pkt);
break;
case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt);
break;
case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
status = avrc_bld_set_absolute_volume_rsp(&p_rsp->volume, p_pkt);
break;
}
if (alloc && (status != AVRC_STS_NO_ERROR) ) {
osi_free(p_pkt);
*pp_pkt = NULL;
}
AVRC_TRACE_API("AVRC_BldResponse: returning %d", status);
return status;
}
#endif /* (AVRC_METADATA_INCLUDED == TRUE)*/
#endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */
+233
View File
@@ -0,0 +1,233 @@
/******************************************************************************
*
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* Interface to AVRCP optional commands
*
******************************************************************************/
#include <assert.h>
#include "common/bt_target.h"
#include <string.h>
#include "stack/avrc_api.h"
#include "avrc_int.h"
#include "osi/allocator.h"
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
/******************************************************************************
**
** Function avrc_vendor_msg
**
** Description Compose a VENDOR DEPENDENT command according to p_msg
**
** Input Parameters:
** p_msg: Pointer to VENDOR DEPENDENT message structure.
**
** Output Parameters:
** None.
**
** Returns pointer to a valid GKI buffer if successful.
** NULL if p_msg is NULL.
**
******************************************************************************/
static BT_HDR *avrc_vendor_msg(tAVRC_MSG_VENDOR *p_msg)
{
BT_HDR *p_cmd;
UINT8 *p_data;
assert(p_msg != NULL);
#if AVRC_METADATA_INCLUDED == TRUE
assert(AVRC_META_CMD_BUF_SIZE > (AVRC_MIN_CMD_LEN + p_msg->vendor_len));
if ((p_cmd = (BT_HDR *) osi_malloc(AVRC_META_CMD_BUF_SIZE)) != NULL)
#else
assert(AVRC_CMD_BUF_SIZE > (AVRC_MIN_CMD_LEN + p_msg->vendor_len));
if ((p_cmd = (BT_HDR *) osi_malloc(AVRC_CMD_BUF_SIZE)) != NULL)
#endif
{
p_cmd->offset = AVCT_MSG_OFFSET;
p_data = (UINT8 *)(p_cmd + 1) + p_cmd->offset;
*p_data++ = (p_msg->hdr.ctype & AVRC_CTYPE_MASK);
*p_data++ = (p_msg->hdr.subunit_type << AVRC_SUBTYPE_SHIFT) | p_msg->hdr.subunit_id;
*p_data++ = AVRC_OP_VENDOR;
AVRC_CO_ID_TO_BE_STREAM(p_data, p_msg->company_id);
if (p_msg->vendor_len && p_msg->p_vendor_data) {
memcpy(p_data, p_msg->p_vendor_data, p_msg->vendor_len);
}
p_cmd->len = (UINT16) (p_data + p_msg->vendor_len - (UINT8 *)(p_cmd + 1) - p_cmd->offset);
p_cmd->layer_specific = AVCT_DATA_CTRL;
}
return p_cmd;
}
/******************************************************************************
**
** Function AVRC_UnitCmd
**
** Description Send a UNIT INFO command to the peer device. This
** function can only be called for controller role connections.
** Any response message from the peer is passed back through
** the tAVRC_MSG_CBACK callback function.
**
** Input Parameters:
** handle: Handle of this connection.
**
** label: Transaction label.
**
** Output Parameters:
** None.
**
** Returns AVRC_SUCCESS if successful.
** AVRC_BAD_HANDLE if handle is invalid.
**
******************************************************************************/
UINT16 AVRC_UnitCmd(UINT8 handle, UINT8 label)
{
BT_HDR *p_cmd;
UINT8 *p_data;
if ((p_cmd = (BT_HDR *) osi_malloc(AVRC_CMD_BUF_SIZE)) != NULL) {
p_cmd->offset = AVCT_MSG_OFFSET;
p_data = (UINT8 *)(p_cmd + 1) + p_cmd->offset;
*p_data++ = AVRC_CMD_STATUS;
/* unit & id ignore */
*p_data++ = (AVRC_SUB_UNIT << AVRC_SUBTYPE_SHIFT) | AVRC_SUBID_IGNORE;
*p_data++ = AVRC_OP_UNIT_INFO;
memset(p_data, AVRC_CMD_OPRND_PAD, AVRC_UNIT_OPRND_BYTES);
p_cmd->len = p_data + AVRC_UNIT_OPRND_BYTES - (UINT8 *)(p_cmd + 1) - p_cmd->offset;
p_cmd->layer_specific = AVCT_DATA_CTRL;
}
return AVCT_MsgReq( handle, label, AVCT_CMD, p_cmd);
}
/******************************************************************************
**
** Function AVRC_SubCmd
**
** Description Send a SUBUNIT INFO command to the peer device. This
** function can only be called for controller role connections.
** Any response message from the peer is passed back through
** the tAVRC_MSG_CBACK callback function.
**
** Input Parameters:
** handle: Handle of this connection.
**
** label: Transaction label.
**
** page: Specifies which part of the subunit type table
** is requested. For AVRCP it is typically zero.
** Value range is 0-7.
**
** Output Parameters:
** None.
**
** Returns AVRC_SUCCESS if successful.
** AVRC_BAD_HANDLE if handle is invalid.
**
******************************************************************************/
UINT16 AVRC_SubCmd(UINT8 handle, UINT8 label, UINT8 page)
{
BT_HDR *p_cmd;
UINT8 *p_data;
if ((p_cmd = (BT_HDR *) osi_malloc(AVRC_CMD_BUF_SIZE)) != NULL) {
p_cmd->offset = AVCT_MSG_OFFSET;
p_data = (UINT8 *)(p_cmd + 1) + p_cmd->offset;
*p_data++ = AVRC_CMD_STATUS;
/* unit & id ignore */
*p_data++ = (AVRC_SUB_UNIT << AVRC_SUBTYPE_SHIFT) | AVRC_SUBID_IGNORE;
*p_data++ = AVRC_OP_SUB_INFO;
*p_data++ = ((page & AVRC_SUB_PAGE_MASK) << AVRC_SUB_PAGE_SHIFT) | AVRC_SUB_EXT_CODE;
memset(p_data, AVRC_CMD_OPRND_PAD, AVRC_SUB_OPRND_BYTES);
p_cmd->len = p_data + AVRC_SUB_OPRND_BYTES - (UINT8 *)(p_cmd + 1) - p_cmd->offset;
p_cmd->layer_specific = AVCT_DATA_CTRL;
}
return AVCT_MsgReq( handle, label, AVCT_CMD, p_cmd);
}
/******************************************************************************
**
** Function AVRC_VendorCmd
**
** Description Send a VENDOR DEPENDENT command to the peer device. This
** function can only be called for controller role connections.
** Any response message from the peer is passed back through
** the tAVRC_MSG_CBACK callback function.
**
** Input Parameters:
** handle: Handle of this connection.
**
** label: Transaction label.
**
** p_msg: Pointer to VENDOR DEPENDENT message structure.
**
** Output Parameters:
** None.
**
** Returns AVRC_SUCCESS if successful.
** AVRC_BAD_HANDLE if handle is invalid.
**
******************************************************************************/
UINT16 AVRC_VendorCmd(UINT8 handle, UINT8 label, tAVRC_MSG_VENDOR *p_msg)
{
BT_HDR *p_buf = avrc_vendor_msg(p_msg);
if (p_buf) {
return AVCT_MsgReq( handle, label, AVCT_CMD, p_buf);
} else {
return AVCT_NO_RESOURCES;
}
}
/******************************************************************************
**
** Function AVRC_VendorRsp
**
** Description Send a VENDOR DEPENDENT response to the peer device. This
** function can only be called for target role connections.
** This function must be called when a VENDOR DEPENDENT
** command message is received from the peer through the
** tAVRC_MSG_CBACK callback function.
**
** Input Parameters:
** handle: Handle of this connection.
**
** label: Transaction label. Must be the same value as
** passed with the command message in the callback function.
**
** p_msg: Pointer to VENDOR DEPENDENT message structure.
**
** Output Parameters:
** None.
**
** Returns AVRC_SUCCESS if successful.
** AVRC_BAD_HANDLE if handle is invalid.
**
******************************************************************************/
UINT16 AVRC_VendorRsp(UINT8 handle, UINT8 label, tAVRC_MSG_VENDOR *p_msg)
{
BT_HDR *p_buf = avrc_vendor_msg(p_msg);
if (p_buf) {
return AVCT_MsgReq( handle, label, AVCT_RSP, p_buf);
} else {
return AVCT_NO_RESOURCES;
}
}
#endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */
@@ -0,0 +1,165 @@
/******************************************************************************
*
* Copyright (C) 2006-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include <string.h>
#include "common/bt_target.h"
#include "stack/avrc_api.h"
#include "stack/avrc_defs.h"
#include "avrc_int.h"
#include "common/bt_defs.h"
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
/*****************************************************************************
** Global data
*****************************************************************************/
#if (AVRC_METADATA_INCLUDED == TRUE)
/*******************************************************************************
**
** Function avrc_pars_vendor_rsp
**
** Description This function parses the vendor specific commands defined by
** Bluetooth SIG
**
** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
** Otherwise, the error code defined by AVRCP 1.4
**
*******************************************************************************/
static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p_result)
{
tAVRC_STS status = AVRC_STS_NO_ERROR;
UINT8 *p;
UINT16 len;
UINT8 eventid = 0;
/* Check the vendor data */
if (p_msg->vendor_len == 0) {
return AVRC_STS_NO_ERROR;
}
if (p_msg->p_vendor_data == NULL) {
return AVRC_STS_INTERNAL_ERR;
}
p = p_msg->p_vendor_data;
BE_STREAM_TO_UINT8 (p_result->pdu, p);
p++; /* skip the reserved/packe_type byte */
BE_STREAM_TO_UINT16 (len, p);
AVRC_TRACE_DEBUG("avrc_pars_vendor_rsp() ctype:0x%x pdu:0x%x, len:%d/0x%x", p_msg->hdr.ctype, p_result->pdu, len, len);
if (p_msg->hdr.ctype == AVRC_RSP_REJ) {
p_result->rsp.status = *p;
return p_result->rsp.status;
}
switch (p_result->pdu) {
/* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
/* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
if (len != 1) {
status = AVRC_STS_INTERNAL_ERR;
} else {
BE_STREAM_TO_UINT8 (p_result->volume.volume, p);
}
break;
#endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
BE_STREAM_TO_UINT8 (eventid, p);
if (AVRC_EVT_VOLUME_CHANGE == eventid
&& (AVRC_RSP_CHANGED == p_msg->hdr.ctype || AVRC_RSP_INTERIM == p_msg->hdr.ctype
|| AVRC_RSP_REJ == p_msg->hdr.ctype || AVRC_RSP_NOT_IMPL == p_msg->hdr.ctype)) {
p_result->reg_notif.status = p_msg->hdr.ctype;
p_result->reg_notif.event_id = eventid;
BE_STREAM_TO_UINT8 (p_result->reg_notif.param.volume, p);
}
// todo: parse the response for other event_ids
AVRC_TRACE_DEBUG("avrc_pars_vendor_rsp PDU reg notif response:event 0x%x", eventid);
break;
#endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */
case AVRC_PDU_GET_CAPABILITIES: /* 0x10 */
BE_STREAM_TO_UINT8 (p_result->get_caps.capability_id, p);
BE_STREAM_TO_UINT8 (p_result->get_caps.count, p);
if (p_result->get_caps.capability_id == AVRC_CAP_EVENTS_SUPPORTED) {
if (p_result->get_caps.count > AVRC_CAP_MAX_NUM_EVT_ID) {
status = AVRC_STS_INTERNAL_ERR;
} else {
BE_STREAM_TO_ARRAY(p, p_result->get_caps.param.event_id, p_result->get_caps.count);
}
} else if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID) {
if (p_result->get_caps.count > AVRC_CAP_MAX_NUM_COMP_ID) {
status = AVRC_STS_INTERNAL_ERR;
} else {
for (int i = 0; i < p_result->get_caps.count; ++i) {
BE_STREAM_TO_UINT24(p_result->get_caps.param.company_id[i], p);
}
}
}
break;
default:
status = AVRC_STS_BAD_CMD;
break;
}
return status;
}
/*******************************************************************************
**
** Function AVRC_ParsResponse
**
** Description This function is a superset of AVRC_ParsMetadata to parse the response.
**
** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
** Otherwise, the error code defined by AVRCP 1.4
**
*******************************************************************************/
tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result)
{
tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
UINT16 id;
if (p_msg && p_result) {
switch (p_msg->hdr.opcode) {
case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */
status = avrc_pars_vendor_rsp(&p_msg->vendor, p_result);
break;
case AVRC_OP_PASS_THRU: /* 0x7C panel subunit opcode */
status = avrc_pars_pass_thru(&p_msg->pass, &id);
if (status == AVRC_STS_NO_ERROR) {
p_result->pdu = (UINT8)id;
}
break;
default:
AVRC_TRACE_ERROR("AVRC_ParsResponse() unknown opcode:0x%x", p_msg->hdr.opcode);
break;
}
p_result->rsp.opcode = p_msg->hdr.opcode;
p_result->rsp.status = status;
}
return status;
}
#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
#endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */
@@ -0,0 +1,311 @@
/******************************************************************************
*
* Copyright (C) 2003-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include <string.h>
#include "common/bt_target.h"
#include "stack/avrc_api.h"
#include "stack/avrc_defs.h"
#include "avrc_int.h"
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
/*****************************************************************************
** Global data
*****************************************************************************/
#if (AVRC_METADATA_INCLUDED == TRUE)
/*******************************************************************************
**
** Function avrc_pars_vendor_cmd
**
** Description This function parses the vendor specific commands defined by
** Bluetooth SIG
**
** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
** Otherwise, the error code defined by AVRCP 1.4
**
*******************************************************************************/
static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_result,
UINT8 *p_buf, UINT16 buf_len)
{
tAVRC_STS status = AVRC_STS_NO_ERROR;
UINT8 *p;
UINT16 len;
UINT8 xx, yy;
UINT8 *p_u8;
UINT16 *p_u16;
UINT32 u32, u32_2, *p_u32;
tAVRC_APP_SETTING *p_app_set;
UINT16 size_needed;
/* Check the vendor data */
if (p_msg->vendor_len == 0) {
return AVRC_STS_NO_ERROR;
}
if (p_msg->p_vendor_data == NULL) {
return AVRC_STS_INTERNAL_ERR;
}
p = p_msg->p_vendor_data;
p_result->pdu = *p++;
AVRC_TRACE_DEBUG("avrc_pars_vendor_cmd() pdu:0x%x", p_result->pdu);
if (!AVRC_IsValidAvcType (p_result->pdu, p_msg->hdr.ctype)) {
AVRC_TRACE_DEBUG("avrc_pars_vendor_cmd() detects wrong AV/C type!");
status = AVRC_STS_BAD_CMD;
}
p++; /* skip the reserved byte */
BE_STREAM_TO_UINT16 (len, p);
if ((len + 4) != (p_msg->vendor_len)) {
status = AVRC_STS_INTERNAL_ERR;
}
if (status != AVRC_STS_NO_ERROR) {
return status;
}
switch (p_result->pdu) {
case AVRC_PDU_GET_CAPABILITIES: /* 0x10 */
p_result->get_caps.capability_id = *p++;
if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id)) {
status = AVRC_STS_BAD_PARAM;
} else if (len != 1) {
status = AVRC_STS_INTERNAL_ERR;
}
break;
case AVRC_PDU_LIST_PLAYER_APP_ATTR: /* 0x11 */
/* no additional parameters */
if (len != 0) {
status = AVRC_STS_INTERNAL_ERR;
}
break;
case AVRC_PDU_LIST_PLAYER_APP_VALUES: /* 0x12 */
p_result->list_app_values.attr_id = *p++;
if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id)) {
status = AVRC_STS_BAD_PARAM;
} else if (len != 1) {
status = AVRC_STS_INTERNAL_ERR;
}
break;
case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p);
if (len != (p_result->get_cur_app_val.num_attr + 1)) {
status = AVRC_STS_INTERNAL_ERR;
break;
}
p_u8 = p_result->get_cur_app_val.attrs;
for (xx = 0, yy = 0; xx < p_result->get_cur_app_val.num_attr; xx++) {
/* only report the valid player app attributes */
if (AVRC_IsValidPlayerAttr(*p)) {
p_u8[yy++] = *p;
}
p++;
}
p_result->get_cur_app_val.num_attr = yy;
if (yy == 0) {
status = AVRC_STS_BAD_PARAM;
}
break;
case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
BE_STREAM_TO_UINT8 (p_result->set_app_val.num_val, p);
size_needed = sizeof(tAVRC_APP_SETTING);
if (p_buf && (len == ((p_result->set_app_val.num_val << 1) + 1))) {
p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf;
p_app_set = p_result->set_app_val.p_vals;
for (xx = 0; ((xx < p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++) {
p_app_set[xx].attr_id = *p++;
p_app_set[xx].attr_val = *p++;
if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val)) {
status = AVRC_STS_BAD_PARAM;
}
}
if (xx != p_result->set_app_val.num_val) {
AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d",
xx, p_result->set_app_val.num_val);
p_result->set_app_val.num_val = xx;
}
} else {
AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len");
status = AVRC_STS_INTERNAL_ERR;
}
break;
case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:/* 0x16 */
if (len < 3) {
status = AVRC_STS_INTERNAL_ERR;
} else {
BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.attr_id, p);
if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id)) {
status = AVRC_STS_BAD_PARAM;
} else {
BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.num_val, p);
if ( (len - 2/* attr_id & num_val */) != p_result->get_app_val_txt.num_val) {
status = AVRC_STS_INTERNAL_ERR;
} else {
p_u8 = p_result->get_app_val_txt.vals;
for (xx = 0; xx < p_result->get_app_val_txt.num_val; xx++) {
p_u8[xx] = *p++;
if (!avrc_is_valid_player_attrib_value(p_result->get_app_val_txt.attr_id,
p_u8[xx])) {
status = AVRC_STS_BAD_PARAM;
break;
}
}
}
}
}
break;
case AVRC_PDU_INFORM_DISPLAY_CHARSET: /* 0x17 */
if (len < 3) {
status = AVRC_STS_INTERNAL_ERR;
} else {
BE_STREAM_TO_UINT8 (p_result->inform_charset.num_id, p);
if ( (len - 1/* num_id */) != p_result->inform_charset.num_id * 2) {
status = AVRC_STS_INTERNAL_ERR;
} else {
p_u16 = p_result->inform_charset.charsets;
if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE) {
p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE;
}
for (xx = 0; xx < p_result->inform_charset.num_id; xx++) {
BE_STREAM_TO_UINT16 (p_u16[xx], p);
}
}
}
break;
case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT:/* 0x18 */
if (len != 1) {
status = AVRC_STS_INTERNAL_ERR;
} else {
p_result->inform_battery_status.battery_status = *p++;
if (!AVRC_IS_VALID_BATTERY_STATUS(p_result->inform_battery_status.battery_status)) {
status = AVRC_STS_BAD_PARAM;
}
}
break;
case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */
if (len < 9) { /* UID/8 and num_attr/1 */
status = AVRC_STS_INTERNAL_ERR;
} else {
BE_STREAM_TO_UINT32 (u32, p);
BE_STREAM_TO_UINT32 (u32_2, p);
if (u32 == 0 && u32_2 == 0) {
BE_STREAM_TO_UINT8 (p_result->get_elem_attrs.num_attr, p);
if ( (len - 9/* UID/8 and num_attr/1 */) != (p_result->get_elem_attrs.num_attr * 4)) {
status = AVRC_STS_INTERNAL_ERR;
} else {
p_u32 = p_result->get_elem_attrs.attrs;
if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE) {
p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE;
}
for (xx = 0; xx < p_result->get_elem_attrs.num_attr; xx++) {
BE_STREAM_TO_UINT32 (p_u32[xx], p);
}
}
} else {
status = AVRC_STS_NOT_FOUND;
}
}
break;
case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */
/* no additional parameters */
if (len != 0) {
status = AVRC_STS_INTERNAL_ERR;
}
break;
case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
if (len != 5) {
status = AVRC_STS_INTERNAL_ERR;
} else {
BE_STREAM_TO_UINT8 (p_result->reg_notif.event_id, p);
BE_STREAM_TO_UINT32 (p_result->reg_notif.param, p);
}
break;
case AVRC_PDU_SET_ABSOLUTE_VOLUME: {
if (len != 1) {
status = AVRC_STS_INTERNAL_ERR;
} else {
BE_STREAM_TO_UINT8 (p_result->volume.volume, p);
p_result->volume.volume &= 0x7F; // remove the top bit
}
break;
}
/* case AVRC_PDU_REQUEST_CONTINUATION_RSP: 0x40 */
/* case AVRC_PDU_ABORT_CONTINUATION_RSP: 0x41 */
default:
status = AVRC_STS_BAD_CMD;
break;
}
return status;
}
/*******************************************************************************
**
** Function AVRC_ParsCommand
**
** Description This function is a superset of AVRC_ParsMetadata to parse the command.
**
** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
** Otherwise, the error code defined by AVRCP 1.4
**
*******************************************************************************/
tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len)
{
tAVRC_STS status = AVRC_STS_INTERNAL_ERR;
UINT16 id;
if (p_msg && p_result) {
switch (p_msg->hdr.opcode) {
case AVRC_OP_VENDOR: /* 0x00 Vendor-dependent commands */
status = avrc_pars_vendor_cmd(&p_msg->vendor, p_result, p_buf, buf_len);
break;
case AVRC_OP_PASS_THRU: /* 0x7C panel subunit opcode */
status = avrc_pars_pass_thru(&p_msg->pass, &id);
if (status == AVRC_STS_NO_ERROR) {
p_result->pdu = (UINT8)id;
}
break;
default:
AVRC_TRACE_ERROR("AVRC_ParsCommand() unknown opcode:0x%x", p_msg->hdr.opcode);
break;
}
p_result->cmd.opcode = p_msg->hdr.opcode;
p_result->cmd.status = status;
}
AVRC_TRACE_DEBUG("AVRC_ParsCommand() return status:0x%x", status);
return status;
}
#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
#endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */
+403
View File
@@ -0,0 +1,403 @@
/******************************************************************************
*
* Copyright (C) 2003-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* AVRCP SDP related functions
*
******************************************************************************/
#include <string.h>
#include "common/bt_target.h"
#include "stack/avrc_api.h"
#include "avrc_int.h"
#include "osi/allocator.h"
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
#ifndef SDP_AVRCP_1_5
#define SDP_AVRCP_1_5 TRUE
#endif
#ifndef SDP_AVCTP_1_4
#define SDP_AVCTP_1_4 TRUE
#endif
/*****************************************************************************
** Global data
*****************************************************************************/
#if AVRC_DYNAMIC_MEMORY == FALSE
tAVRC_CB avrc_cb;
#else
tAVRC_CB *avrc_cb_ptr;
#endif
/* update AVRC_NUM_PROTO_ELEMS if this constant is changed */
const tSDP_PROTOCOL_ELEM avrc_proto_list [] = {
{UUID_PROTOCOL_L2CAP, 1, {AVCT_PSM, 0} },
#if SDP_AVCTP_1_4 == TRUE
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_4, 0} }
#else
#if (SDP_AVRCP_1_4 == TRUE || SDP_AVRCP_1_5 == TRUE)
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_3, 0} }
#else
#if AVRC_METADATA_INCLUDED == TRUE
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_2, 0} }
#else
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_0, 0} }
#endif
#endif
#endif
};
#if SDP_AVRCP_1_5 == TRUE
const tSDP_PROTO_LIST_ELEM avrc_add_proto_list [] = {
{
AVRC_NUM_PROTO_ELEMS,
{
{UUID_PROTOCOL_L2CAP, 1, {AVCT_BR_PSM, 0} },
#if SDP_AVCTP_1_4 == TRUE
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_4, 0} }
#else
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_3, 0} }
#endif
}
}
};
#endif
/******************************************************************************
**
** Function avrc_sdp_cback
**
** Description This is the SDP callback function used by A2D_FindService.
** This function will be executed by SDP when the service
** search is completed. If the search is successful, it
** finds the first record in the database that matches the
** UUID of the search. Then retrieves various parameters
** from the record. When it is finished it calls the
** application callback function.
**
** Returns Nothing.
**
******************************************************************************/
static void avrc_sdp_cback(UINT16 status)
{
AVRC_TRACE_API("avrc_sdp_cback status: %d", status);
/* reset service_uuid, so can start another find service */
avrc_cb.service_uuid = 0;
/* return info from sdp record in app callback function */
(*avrc_cb.p_cback) (status);
return;
}
/******************************************************************************
**
** Function AVRC_FindService
**
** Description This function is called by the application to perform service
** discovery and retrieve AVRCP SDP record information from a
** peer device. Information is returned for the first service
** record found on the server that matches the service UUID.
** The callback function will be executed when service discovery
** is complete. There can only be one outstanding call to
** AVRC_FindService() at a time; the application must wait for
** the callback before it makes another call to the function.
** The application is responsible for allocating memory for the
** discovery database. It is recommended that the size of the
** discovery database be at least 300 bytes. The application
** can deallocate the memory after the callback function has
** executed.
**
** Input Parameters:
** service_uuid: Indicates TG(UUID_SERVCLASS_AV_REM_CTRL_TARGET)
** or CT(UUID_SERVCLASS_AV_REMOTE_CONTROL)
**
** bd_addr: BD address of the peer device.
**
** p_db: SDP discovery database parameters.
**
** p_cback: Pointer to the callback function.
**
** Output Parameters:
** None.
**
** Returns AVRC_SUCCESS if successful.
** AVRC_BAD_PARAMS if discovery database parameters are invalid.
** AVRC_NO_RESOURCES if there are not enough resources to
** perform the service search.
**
******************************************************************************/
UINT16 AVRC_FindService(UINT16 service_uuid, BD_ADDR bd_addr,
tAVRC_SDP_DB_PARAMS *p_db, tAVRC_FIND_CBACK *p_cback)
{
tSDP_UUID uuid_list;
BOOLEAN result = TRUE;
UINT16 a2d_attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, /* update AVRC_NUM_ATTR, if changed */
ATTR_ID_PROTOCOL_DESC_LIST,
ATTR_ID_BT_PROFILE_DESC_LIST,
ATTR_ID_SERVICE_NAME,
ATTR_ID_SUPPORTED_FEATURES,
ATTR_ID_PROVIDER_NAME
};
AVRC_TRACE_API("AVRC_FindService uuid: %x", service_uuid);
if ( (service_uuid != UUID_SERVCLASS_AV_REM_CTRL_TARGET && service_uuid != UUID_SERVCLASS_AV_REMOTE_CONTROL) ||
p_db == NULL || p_db->p_db == NULL || p_cback == NULL) {
return AVRC_BAD_PARAM;
}
/* check if it is busy */
if ( avrc_cb.service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET ||
avrc_cb.service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL) {
return AVRC_NO_RESOURCES;
}
/* set up discovery database */
uuid_list.len = LEN_UUID_16;
uuid_list.uu.uuid16 = service_uuid;
if (p_db->p_attrs == NULL || p_db->num_attr == 0) {
p_db->p_attrs = a2d_attr_list;
p_db->num_attr = AVRC_NUM_ATTR;
}
result = SDP_InitDiscoveryDb(p_db->p_db, p_db->db_len, 1, &uuid_list, p_db->num_attr,
p_db->p_attrs);
if (result == TRUE) {
/* store service_uuid and discovery db pointer */
avrc_cb.p_db = p_db->p_db;
avrc_cb.service_uuid = service_uuid;
avrc_cb.p_cback = p_cback;
/* perform service search */
result = SDP_ServiceSearchAttributeRequest(bd_addr, p_db->p_db, avrc_sdp_cback);
}
return (result ? AVRC_SUCCESS : AVRC_FAIL);
}
/******************************************************************************
**
** Function AVRC_AddRecord
**
** Description This function is called to build an AVRCP SDP record.
** Prior to calling this function the application must
** call SDP_CreateRecord() to create an SDP record.
**
** Input Parameters:
** service_uuid: Indicates TG(UUID_SERVCLASS_AV_REM_CTRL_TARGET)
** or CT(UUID_SERVCLASS_AV_REMOTE_CONTROL)
**
** p_service_name: Pointer to a null-terminated character
** string containing the service name.
** If service name is not used set this to NULL.
**
** p_provider_name: Pointer to a null-terminated character
** string containing the provider name.
** If provider name is not used set this to NULL.
**
** categories: Supported categories.
**
** sdp_handle: SDP handle returned by SDP_CreateRecord().
**
** browsing_en: Supported browsing
**
** Output Parameters:
** None.
**
** Returns AVRC_SUCCESS if successful.
** AVRC_NO_RESOURCES if not enough resources to build the SDP record.
**
******************************************************************************/
UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provider_name,
UINT16 categories, UINT32 sdp_handle, BOOLEAN browsing_en)
{
UINT16 browse_list[1];
BOOLEAN result = TRUE;
UINT8 temp[8];
UINT8 *p;
UINT16 count = 1;
UINT16 class_list[2];
UINT16 supported_feature = categories;
BOOLEAN media_player_virtual_filesystem_supported = FALSE;
BOOLEAN add_additional_protocol_list = FALSE;
AVRC_TRACE_API("AVRC_AddRecord uuid: %x, browsing_en:%d", service_uuid, browsing_en);
if ( service_uuid != UUID_SERVCLASS_AV_REM_CTRL_TARGET && service_uuid != UUID_SERVCLASS_AV_REMOTE_CONTROL ) {
return AVRC_BAD_PARAM;
}
/* add service class id list */
class_list[0] = service_uuid;
#if (SDP_AVCTP_1_4 == TRUE || SDP_AVRCP_1_5 == TRUE)
if ( service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL ) {
class_list[1] = UUID_SERVCLASS_AV_REM_CTRL_CONTROL;
count = 2;
}
#endif
result &= SDP_AddServiceClassIdList(sdp_handle, count, class_list);
/* add protocol descriptor list */
result &= SDP_AddProtocolList(sdp_handle, AVRC_NUM_PROTO_ELEMS, (tSDP_PROTOCOL_ELEM *)avrc_proto_list);
/* add profile descriptor list */
#if SDP_AVRCP_1_5 == TRUE
if (browsing_en) {
add_additional_protocol_list = TRUE;
} else if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET &&
(categories & (AVRC_SUPF_TG_CAT1 | AVRC_SUPF_TG_CAT3))) {
AVRC_TRACE_WARNING("For AVRCP Target Cateory 1 and 3, SDP record shall contain additional protocol list");
add_additional_protocol_list = TRUE;
}
if (add_additional_protocol_list) {
/* additional protocol list to include browsing channel */
result &= SDP_AddAdditionProtoLists( sdp_handle, 1, (tSDP_PROTO_LIST_ELEM *)avrc_add_proto_list);
}
result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_5);
#else
#if AVRC_METADATA_INCLUDED == TRUE
result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_3);
#else
result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_0);
#endif
#endif
/* Check if browsing is supported */
if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_CONTROL && browsing_en) {
supported_feature |= AVRC_SUPF_CT_BROWSE;
} else if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET && media_player_virtual_filesystem_supported) {
supported_feature |= AVRC_SUPF_TG_BROWSE;
}
/* add supported feature */
p = temp;
UINT16_TO_BE_STREAM(p, supported_feature);
result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
(UINT32)2, (UINT8 *)temp);
/* add provider name */
if (p_provider_name != NULL) {
result &= SDP_AddAttribute(sdp_handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE,
(UINT32)(strlen(p_provider_name) + 1), (UINT8 *) p_provider_name);
}
/* add service name */
if (p_service_name != NULL) {
result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
(UINT32)(strlen(p_service_name) + 1), (UINT8 *) p_service_name);
}
/* add browse group list */
browse_list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
return (result ? AVRC_SUCCESS : AVRC_FAIL);
}
/******************************************************************************
**
** Function AVRC_SetTraceLevel
**
** Description Sets the trace level for AVRC. If 0xff is passed, the
** current trace level is returned.
**
** Input Parameters:
** new_level: The level to set the AVRC tracing to:
** 0xff-returns the current setting.
** 0-turns off tracing.
** >= 1-Errors.
** >= 2-Warnings.
** >= 3-APIs.
** >= 4-Events.
** >= 5-Debug.
**
** Returns The new trace level or current trace level if
** the input parameter is 0xff.
**
******************************************************************************/
UINT8 AVRC_SetTraceLevel (UINT8 new_level)
{
if (new_level != 0xFF) {
avrc_cb.trace_level = new_level;
}
return (avrc_cb.trace_level);
}
/*******************************************************************************
**
** Function AVRC_Init
**
** Description This function is called at stack startup to allocate the
** control block (if using dynamic memory), and initializes the
** control block and tracing level.
**
** Returns status
**
*******************************************************************************/
bt_status_t AVRC_Init(void)
{
#if AVRC_DYNAMIC_MEMORY
avrc_cb_ptr = (tAVRC_CB *)osi_malloc(sizeof(tAVRC_CB));
if (!avrc_cb_ptr) {
return BT_STATUS_NOMEM;
}
#endif /* #if AVRC_DYNAMIC_MEMORY */
memset(&avrc_cb, 0, sizeof(tAVRC_CB));
#if defined(AVRC_INITIAL_TRACE_LEVEL)
avrc_cb.trace_level = AVRC_INITIAL_TRACE_LEVEL;
#else
avrc_cb.trace_level = BT_TRACE_LEVEL_NONE;
#endif
return BT_STATUS_SUCCESS;
}
/*******************************************************************************
**
** Function AVRC_Deinit
**
** Description This function is called at stack shotdown to free the
** control block (if using dynamic memory), and deinitializes the
** control block and tracing level.
**
** Returns void
**
*******************************************************************************/
void AVRC_Deinit(void)
{
#if AVRC_DYNAMIC_MEMORY
if (avrc_cb_ptr){
osi_free(avrc_cb_ptr);
avrc_cb_ptr = NULL;
}
#endif /* #if AVRC_DYNAMIC_MEMORY */
}
#endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */
@@ -0,0 +1,239 @@
/******************************************************************************
*
* Copyright (C) 2003-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include <string.h>
#include "common/bt_target.h"
#include "stack/avrc_api.h"
#include "avrc_int.h"
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
#if (AVRC_METADATA_INCLUDED == TRUE)
/**************************************************************************
**
** Function AVRC_IsValidAvcType
**
** Description Check if correct AVC type is specified
**
** Returns returns TRUE if it is valid
**
**
*******************************************************************************/
BOOLEAN AVRC_IsValidAvcType(UINT8 pdu_id, UINT8 avc_type)
{
BOOLEAN result = FALSE;
if (avc_type < AVRC_RSP_NOT_IMPL) { /* command msg */
switch (pdu_id) {
case AVRC_PDU_GET_CAPABILITIES: /* 0x10 */
case AVRC_PDU_LIST_PLAYER_APP_ATTR: /* 0x11 */
case AVRC_PDU_LIST_PLAYER_APP_VALUES: /* 0x12 */
case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: /* 0x16 */
case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */
case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */
if (avc_type == AVRC_CMD_STATUS) {
result = TRUE;
}
break;
case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
case AVRC_PDU_INFORM_DISPLAY_CHARSET: /* 0x17 */
case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: /* 0x18 */
case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
if (avc_type == AVRC_CMD_CTRL) {
result = TRUE;
}
break;
case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
if (avc_type == AVRC_CMD_NOTIF) {
result = TRUE;
}
break;
}
} else { /* response msg */
if (avc_type >= AVRC_RSP_NOT_IMPL &&
avc_type <= AVRC_RSP_INTERIM ) {
result = TRUE;
}
}
return result;
}
/*******************************************************************************
**
** Function avrc_is_valid_player_attrib_value
**
** Description Check if the given attrib value is valid for its attribute
**
** Returns returns TRUE if it is valid
**
*******************************************************************************/
BOOLEAN avrc_is_valid_player_attrib_value(UINT8 attrib, UINT8 value)
{
BOOLEAN result = FALSE;
switch (attrib) {
case AVRC_PLAYER_SETTING_EQUALIZER:
if ((value > 0) &&
(value <= AVRC_PLAYER_VAL_ON)) {
result = TRUE;
}
break;
case AVRC_PLAYER_SETTING_REPEAT:
if ((value > 0) &&
(value <= AVRC_PLAYER_VAL_GROUP_REPEAT)) {
result = TRUE;
}
break;
case AVRC_PLAYER_SETTING_SHUFFLE:
case AVRC_PLAYER_SETTING_SCAN:
if ((value > 0) &&
(value <= AVRC_PLAYER_VAL_GROUP_SHUFFLE)) {
result = TRUE;
}
break;
}
if (attrib >= AVRC_PLAYER_SETTING_LOW_MENU_EXT) {
result = TRUE;
}
if (!result) {
AVRC_TRACE_ERROR(
"avrc_is_valid_player_attrib_value() found not matching attrib(x%x)-value(x%x) pair!",
attrib, value);
}
return result;
}
/*******************************************************************************
**
** Function AVRC_IsValidPlayerAttr
**
** Description Check if the given attrib value is a valid one
**
** Returns returns TRUE if it is valid
**
*******************************************************************************/
BOOLEAN AVRC_IsValidPlayerAttr(UINT8 attr)
{
BOOLEAN result = FALSE;
if ( (attr >= AVRC_PLAYER_SETTING_EQUALIZER && attr <= AVRC_PLAYER_SETTING_SCAN) ||
(attr >= AVRC_PLAYER_SETTING_LOW_MENU_EXT) ) {
result = TRUE;
}
return result;
}
/*******************************************************************************
**
** Function avrc_pars_pass_thru
**
** Description This function parses the pass thru commands defined by
** Bluetooth SIG
**
** Returns AVRC_STS_NO_ERROR, if the message in p_data is parsed successfully.
** Otherwise, the error code defined by AVRCP 1.4
**
*******************************************************************************/
tAVRC_STS avrc_pars_pass_thru(tAVRC_MSG_PASS *p_msg, UINT16 *p_vendor_unique_id)
{
UINT8 *p_data;
UINT32 co_id;
UINT16 id;
tAVRC_STS status = AVRC_STS_BAD_CMD;
if (p_msg->op_id == AVRC_ID_VENDOR && p_msg->pass_len == AVRC_PASS_THRU_GROUP_LEN) {
p_data = p_msg->p_pass_data;
AVRC_BE_STREAM_TO_CO_ID (co_id, p_data);
if (co_id == AVRC_CO_METADATA) {
BE_STREAM_TO_UINT16 (id, p_data);
if (AVRC_IS_VALID_GROUP(id)) {
*p_vendor_unique_id = id;
status = AVRC_STS_NO_ERROR;
}
}
}
return status;
}
/*******************************************************************************
**
** Function avrc_opcode_from_pdu
**
** Description This function returns the opcode of the given pdu
**
** Returns AVRC_OP_VENDOR, AVRC_OP_PASS_THRU or AVRC_OP_BROWSE
**
*******************************************************************************/
UINT8 avrc_opcode_from_pdu(UINT8 pdu)
{
UINT8 opcode = 0;
switch (pdu) {
case AVRC_PDU_NEXT_GROUP:
case AVRC_PDU_PREV_GROUP: /* pass thru */
opcode = AVRC_OP_PASS_THRU;
break;
default: /* vendor */
opcode = AVRC_OP_VENDOR;
break;
}
return opcode;
}
/*******************************************************************************
**
** Function avrc_is_valid_opcode
**
** Description This function returns the opcode of the given pdu
**
** Returns AVRC_OP_VENDOR, AVRC_OP_PASS_THRU or AVRC_OP_BROWSE
**
*******************************************************************************/
BOOLEAN avrc_is_valid_opcode(UINT8 opcode)
{
BOOLEAN is_valid = FALSE;
switch (opcode) {
case AVRC_OP_BROWSE:
case AVRC_OP_PASS_THRU:
case AVRC_OP_VENDOR:
is_valid = TRUE;
break;
}
return is_valid;
}
#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
#endif /* #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) */
@@ -0,0 +1,158 @@
/******************************************************************************
*
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* VRCP internal header file.
*
******************************************************************************/
#ifndef AVRC_INT_H
#define AVRC_INT_H
#include "avct_defs.h"
#include "stack/avrc_api.h"
#if (AVRC_INCLUDED == TRUE)
/* DEBUG FLAGS
*
* #define META_DEBUG_ENABLED
*/
/*****************************************************************************
** Constants
*****************************************************************************/
/* Number of attributes in AVRC SDP record. */
#define AVRC_NUM_ATTR 6
/* Number of protocol elements in protocol element list. */
#define AVRC_NUM_PROTO_ELEMS 2
#ifndef AVRC_MIN_CMD_LEN
#define AVRC_MIN_CMD_LEN 20
#endif
#define AVRC_UNIT_OPRND_BYTES 5
#define AVRC_SUB_OPRND_BYTES 4
#define AVRC_SUBRSP_OPRND_BYTES 3
#define AVRC_SUB_PAGE_MASK 7
#define AVRC_SUB_PAGE_SHIFT 4
#define AVRC_SUB_EXT_CODE 7
#define AVRC_PASS_OP_ID_MASK 0x7F
#define AVRC_PASS_STATE_MASK 0x80
#define AVRC_CMD_OPRND_PAD 0xFF
#define AVRC_CTYPE_MASK 0x0F
#define AVRC_SUBTYPE_MASK 0xF8
#define AVRC_SUBTYPE_SHIFT 3
#define AVRC_SUBID_MASK 0x07
#define AVRC_SUBID_IGNORE 0x07
#define AVRC_SINGLE_PARAM_SIZE 1
#define AVRC_METADATA_PKT_TYPE_MASK 0x03
#define AVRC_PASS_THOUGH_MSG_MASK 0x80 /* MSB of msg_type indicates the PAS THROUGH msg */
#define AVRC_VENDOR_UNIQUE_MASK 0x70 /* vendor unique id */
/* Company ID is 24-bit integer We can not use the macros in stack/bt_types.h */
#define AVRC_CO_ID_TO_BE_STREAM(p, u32) {*(p)++ = (UINT8)((u32) >> 16); *(p)++ = (UINT8)((u32) >> 8); *(p)++ = (UINT8)(u32); }
#define AVRC_BE_STREAM_TO_CO_ID(u32, p) {u32 = (((UINT32)(*((p) + 2))) + (((UINT32)(*((p) + 1))) << 8) + (((UINT32)(*(p))) << 16)); (p) += 3;}
#define AVRC_AVC_HDR_SIZE 3 /* ctype, subunit*, opcode */
#define AVRC_MIN_META_HDR_SIZE 4 /* pdu id(1), packet type(1), param len(2) */
#define AVRC_MIN_BROWSE_HDR_SIZE 3 /* pdu id(1), param len(2) */
#define AVRC_VENDOR_HDR_SIZE 6 /* ctype, subunit*, opcode, CO_ID */
#define AVRC_MSG_VENDOR_OFFSET 23
#define AVRC_MIN_VENDOR_SIZE (AVRC_MSG_VENDOR_OFFSET + BT_HDR_SIZE + AVRC_MIN_META_HDR_SIZE)
#define AVRC_PASS_THRU_SIZE 8
#define AVRC_MSG_PASS_THRU_OFFSET 25
#define AVRC_MIN_PASS_THRU_SIZE (AVRC_MSG_PASS_THRU_OFFSET + BT_HDR_SIZE + 4)
#define AVRC_MIN_BROWSE_SIZE (AVCT_BROWSE_OFFSET + BT_HDR_SIZE + AVRC_MIN_BROWSE_HDR_SIZE)
#define AVRC_CTRL_PKT_LEN(pf, pk) {pf = (UINT8 *)((pk) + 1) + (pk)->offset + 2;}
#define AVRC_MAX_CTRL_DATA_LEN (AVRC_PACKET_LEN)
/*****************************************************************************
** Type definitions
*****************************************************************************/
#if (AVRC_METADATA_INCLUDED == TRUE)
/* type for Metadata fragmentation control block */
typedef struct {
BT_HDR *p_fmsg; /* the fragmented message */
UINT8 frag_pdu; /* the PDU ID for fragmentation */
BOOLEAN frag_enabled; /* fragmentation flag */
} tAVRC_FRAG_CB;
/* type for Metadata re-assembly control block */
typedef struct {
BT_HDR *p_rmsg; /* the received message */
UINT16 rasm_offset; /* re-assembly flag, the offset of the start fragment */
UINT8 rasm_pdu; /* the PDU ID for re-assembly */
} tAVRC_RASM_CB;
#endif
typedef struct {
tAVRC_CONN_CB ccb[AVCT_NUM_CONN];
#if (AVRC_METADATA_INCLUDED == TRUE)
tAVRC_FRAG_CB fcb[AVCT_NUM_CONN];
tAVRC_RASM_CB rcb[AVCT_NUM_CONN];
#endif
tAVRC_FIND_CBACK *p_cback; /* pointer to application callback */
tSDP_DISCOVERY_DB *p_db; /* pointer to discovery database */
UINT16 service_uuid; /* service UUID to search */
UINT8 trace_level;
} tAVRC_CB;
#ifdef __cplusplus
extern "C"
{
#endif
/******************************************************************************
** Main Control Block
*******************************************************************************/
#if AVRC_DYNAMIC_MEMORY == FALSE
extern tAVRC_CB avrc_cb;
#else
extern tAVRC_CB *avrc_cb_ptr;
#define avrc_cb (*avrc_cb_ptr)
#endif
extern BOOLEAN avrc_is_valid_pdu_id(UINT8 pdu_id);
extern BOOLEAN avrc_is_valid_player_attrib_value(UINT8 attrib, UINT8 value);
extern BT_HDR *avrc_alloc_ctrl_pkt (UINT8 pdu);
extern tAVRC_STS avrc_pars_pass_thru(tAVRC_MSG_PASS *p_msg, UINT16 *p_vendor_unique_id);
extern UINT8 avrc_opcode_from_pdu(UINT8 pdu);
extern BOOLEAN avrc_is_valid_opcode(UINT8 opcode);
#ifdef __cplusplus
}
#endif
#endif ///AVRC_INCLUDED == TRUE
#endif /* AVRC_INT_H */