Fork ESP-IDF's bluetooth component
i want better sbc encoding, and no cla will stop me
This commit is contained in:
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) */
|
||||
@@ -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) */
|
||||
@@ -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 */
|
||||
Reference in New Issue
Block a user