mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
component/bt: transport bluedroid avct, avdt, avrc and a2dp module to stack
This commit is contained in:
parent
d472ff5856
commit
e3a4f23c9d
395
components/bt/bluedroid/stack/a2dp/a2d_api.c
Executable file
395
components/bt/bluedroid/stack/a2dp/a2d_api.c
Executable file
@ -0,0 +1,395 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* ommon API for the Advanced Audio Distribution Profile (A2DP)
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#include <string.h>
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "sdpdefs.h"
|
||||||
|
#include "a2d_api.h"
|
||||||
|
#include "a2d_int.h"
|
||||||
|
#include "avdt_api.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Global data
|
||||||
|
*****************************************************************************/
|
||||||
|
#if A2D_DYNAMIC_MEMORY == FALSE
|
||||||
|
tA2D_CB a2d_cb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function a2d_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 a2d_sdp_cback(UINT16 status)
|
||||||
|
{
|
||||||
|
tSDP_DISC_REC *p_rec = NULL;
|
||||||
|
tSDP_DISC_ATTR *p_attr;
|
||||||
|
BOOLEAN found = FALSE;
|
||||||
|
tA2D_Service a2d_svc;
|
||||||
|
tSDP_PROTOCOL_ELEM elem;
|
||||||
|
|
||||||
|
A2D_TRACE_API("a2d_sdp_cback status: %d", status);
|
||||||
|
|
||||||
|
if (status == SDP_SUCCESS)
|
||||||
|
{
|
||||||
|
/* loop through all records we found */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* get next record; if none found, we're done */
|
||||||
|
if ((p_rec = SDP_FindServiceInDb(a2d_cb.find.p_db,
|
||||||
|
a2d_cb.find.service_uuid, p_rec)) == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memset(&a2d_svc, 0, sizeof(tA2D_Service));
|
||||||
|
|
||||||
|
/* get service name */
|
||||||
|
if ((p_attr = SDP_FindAttributeInRec(p_rec,
|
||||||
|
ATTR_ID_SERVICE_NAME)) != NULL)
|
||||||
|
{
|
||||||
|
a2d_svc.p_service_name = (char *) p_attr->attr_value.v.array;
|
||||||
|
a2d_svc.service_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get provider name */
|
||||||
|
if ((p_attr = SDP_FindAttributeInRec(p_rec,
|
||||||
|
ATTR_ID_PROVIDER_NAME)) != NULL)
|
||||||
|
{
|
||||||
|
a2d_svc.p_provider_name = (char *) p_attr->attr_value.v.array;
|
||||||
|
a2d_svc.provider_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get supported features */
|
||||||
|
if ((p_attr = SDP_FindAttributeInRec(p_rec,
|
||||||
|
ATTR_ID_SUPPORTED_FEATURES)) != NULL)
|
||||||
|
{
|
||||||
|
a2d_svc.features = p_attr->attr_value.v.u16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get AVDTP version */
|
||||||
|
if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_AVDTP, &elem))
|
||||||
|
{
|
||||||
|
a2d_svc.avdt_version = elem.params[0];
|
||||||
|
A2D_TRACE_DEBUG("avdt_version: 0x%x", a2d_svc.avdt_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we've got everything, we're done */
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
} while (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
a2d_cb.find.service_uuid = 0;
|
||||||
|
/* return info from sdp record in app callback function */
|
||||||
|
if (a2d_cb.find.p_cback != NULL)
|
||||||
|
{
|
||||||
|
(*a2d_cb.find.p_cback)(found, &a2d_svc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function a2d_set_avdt_sdp_ver
|
||||||
|
**
|
||||||
|
** Description This function allows the script wrapper to change the
|
||||||
|
** avdt version of a2dp.
|
||||||
|
**
|
||||||
|
** Returns None
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void a2d_set_avdt_sdp_ver (UINT16 avdt_sdp_ver)
|
||||||
|
{
|
||||||
|
a2d_cb.avdt_sdp_ver = avdt_sdp_ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_AddRecord
|
||||||
|
**
|
||||||
|
** Description This function is called by a server application to add
|
||||||
|
** SRC or SNK information to an SDP record. Prior to
|
||||||
|
** calling this function the application must call
|
||||||
|
** SDP_CreateRecord() to create an SDP record.
|
||||||
|
**
|
||||||
|
** Input Parameters:
|
||||||
|
** service_uuid: Indicates SRC or SNK.
|
||||||
|
**
|
||||||
|
** p_service_name: Pointer to a null-terminated character
|
||||||
|
** string containing the service name.
|
||||||
|
**
|
||||||
|
** p_provider_name: Pointer to a null-terminated character
|
||||||
|
** string containing the provider name.
|
||||||
|
**
|
||||||
|
** features: Profile supported features.
|
||||||
|
**
|
||||||
|
** sdp_handle: SDP handle returned by SDP_CreateRecord().
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** None.
|
||||||
|
**
|
||||||
|
** Returns A2D_SUCCESS if function execution succeeded,
|
||||||
|
** A2D_INVALID_PARAMS if bad parameters are given.
|
||||||
|
** A2D_FAIL if function execution failed.
|
||||||
|
**
|
||||||
|
******************************************************************************/
|
||||||
|
tA2D_STATUS A2D_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provider_name,
|
||||||
|
UINT16 features, UINT32 sdp_handle)
|
||||||
|
{
|
||||||
|
UINT16 browse_list[1];
|
||||||
|
BOOLEAN result = TRUE;
|
||||||
|
UINT8 temp[8];
|
||||||
|
UINT8 *p;
|
||||||
|
tSDP_PROTOCOL_ELEM proto_list [A2D_NUM_PROTO_ELEMS];
|
||||||
|
|
||||||
|
A2D_TRACE_API("A2D_AddRecord uuid: %x", service_uuid);
|
||||||
|
|
||||||
|
if( (sdp_handle == 0) ||
|
||||||
|
(service_uuid != UUID_SERVCLASS_AUDIO_SOURCE && service_uuid != UUID_SERVCLASS_AUDIO_SINK) )
|
||||||
|
return A2D_INVALID_PARAMS;
|
||||||
|
|
||||||
|
/* add service class id list */
|
||||||
|
result &= SDP_AddServiceClassIdList(sdp_handle, 1, &service_uuid);
|
||||||
|
|
||||||
|
memset((void*) proto_list, 0 , A2D_NUM_PROTO_ELEMS*sizeof(tSDP_PROTOCOL_ELEM));
|
||||||
|
|
||||||
|
/* add protocol descriptor list */
|
||||||
|
proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
|
||||||
|
proto_list[0].num_params = 1;
|
||||||
|
proto_list[0].params[0] = AVDT_PSM;
|
||||||
|
proto_list[1].protocol_uuid = UUID_PROTOCOL_AVDTP;
|
||||||
|
proto_list[1].num_params = 1;
|
||||||
|
proto_list[1].params[0] = a2d_cb.avdt_sdp_ver;
|
||||||
|
|
||||||
|
result &= SDP_AddProtocolList(sdp_handle, A2D_NUM_PROTO_ELEMS, proto_list);
|
||||||
|
|
||||||
|
/* add profile descriptor list */
|
||||||
|
result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION, A2D_VERSION);
|
||||||
|
|
||||||
|
/* add supported feature */
|
||||||
|
if (features != 0)
|
||||||
|
{
|
||||||
|
p = temp;
|
||||||
|
UINT16_TO_BE_STREAM(p, features);
|
||||||
|
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 ? A2D_SUCCESS : A2D_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_FindService
|
||||||
|
**
|
||||||
|
** Description This function is called by a client application to
|
||||||
|
** perform service discovery and retrieve SRC or SNK SDP
|
||||||
|
** record information from a server. 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
|
||||||
|
** A2D_FindService() at a time; the application must wait
|
||||||
|
** for the callback before it makes another call to
|
||||||
|
** the function.
|
||||||
|
**
|
||||||
|
** Input Parameters:
|
||||||
|
** service_uuid: Indicates SRC or SNK.
|
||||||
|
**
|
||||||
|
** bd_addr: BD address of the peer device.
|
||||||
|
**
|
||||||
|
** p_db: Pointer to the information to initialize
|
||||||
|
** the discovery database.
|
||||||
|
**
|
||||||
|
** p_cback: Pointer to the A2D_FindService()
|
||||||
|
** callback function.
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** None.
|
||||||
|
**
|
||||||
|
** Returns A2D_SUCCESS if function execution succeeded,
|
||||||
|
** A2D_INVALID_PARAMS if bad parameters are given.
|
||||||
|
** A2D_BUSY if discovery is already in progress.
|
||||||
|
** A2D_FAIL if function execution failed.
|
||||||
|
**
|
||||||
|
******************************************************************************/
|
||||||
|
tA2D_STATUS A2D_FindService(UINT16 service_uuid, BD_ADDR bd_addr,
|
||||||
|
tA2D_SDP_DB_PARAMS *p_db, tA2D_FIND_CBACK *p_cback)
|
||||||
|
{
|
||||||
|
tSDP_UUID uuid_list;
|
||||||
|
BOOLEAN result = TRUE;
|
||||||
|
UINT16 a2d_attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, /* update A2D_NUM_ATTR, if changed */
|
||||||
|
ATTR_ID_BT_PROFILE_DESC_LIST,
|
||||||
|
ATTR_ID_SUPPORTED_FEATURES,
|
||||||
|
ATTR_ID_SERVICE_NAME,
|
||||||
|
ATTR_ID_PROTOCOL_DESC_LIST,
|
||||||
|
ATTR_ID_PROVIDER_NAME};
|
||||||
|
|
||||||
|
A2D_TRACE_API("A2D_FindService uuid: %x", service_uuid);
|
||||||
|
if( (service_uuid != UUID_SERVCLASS_AUDIO_SOURCE && service_uuid != UUID_SERVCLASS_AUDIO_SINK) ||
|
||||||
|
p_db == NULL || p_db->p_db == NULL || p_cback == NULL)
|
||||||
|
return A2D_INVALID_PARAMS;
|
||||||
|
|
||||||
|
if( a2d_cb.find.service_uuid == UUID_SERVCLASS_AUDIO_SOURCE ||
|
||||||
|
a2d_cb.find.service_uuid == UUID_SERVCLASS_AUDIO_SINK)
|
||||||
|
return A2D_BUSY;
|
||||||
|
|
||||||
|
/* 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 = A2D_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 */
|
||||||
|
a2d_cb.find.p_db = p_db->p_db;
|
||||||
|
a2d_cb.find.service_uuid = service_uuid;
|
||||||
|
a2d_cb.find.p_cback = p_cback;
|
||||||
|
|
||||||
|
/* perform service search */
|
||||||
|
result = SDP_ServiceSearchAttributeRequest(bd_addr, p_db->p_db, a2d_sdp_cback);
|
||||||
|
if(FALSE == result)
|
||||||
|
{
|
||||||
|
a2d_cb.find.service_uuid = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (result ? A2D_SUCCESS : A2D_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_SetTraceLevel
|
||||||
|
**
|
||||||
|
** Description Sets the trace level for A2D. If 0xff is passed, the
|
||||||
|
** current trace level is returned.
|
||||||
|
**
|
||||||
|
** Input Parameters:
|
||||||
|
** new_level: The level to set the A2D 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 A2D_SetTraceLevel (UINT8 new_level)
|
||||||
|
{
|
||||||
|
if (new_level != 0xFF)
|
||||||
|
a2d_cb.trace_level = new_level;
|
||||||
|
|
||||||
|
return (a2d_cb.trace_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
** Function A2D_BitsSet
|
||||||
|
**
|
||||||
|
** Description Check the given num for the number of bits set
|
||||||
|
** Returns A2D_SET_ONE_BIT, if one and only one bit is set
|
||||||
|
** A2D_SET_ZERO_BIT, if all bits clear
|
||||||
|
** A2D_SET_MULTL_BIT, if multiple bits are set
|
||||||
|
******************************************************************************/
|
||||||
|
UINT8 A2D_BitsSet(UINT8 num)
|
||||||
|
{
|
||||||
|
UINT8 count;
|
||||||
|
BOOLEAN res;
|
||||||
|
if(num == 0)
|
||||||
|
res = A2D_SET_ZERO_BIT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = (num & (num - 1));
|
||||||
|
res = ((count==0)?A2D_SET_ONE_BIT:A2D_SET_MULTL_BIT);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_Init
|
||||||
|
**
|
||||||
|
** Description This function is called to initialize the control block
|
||||||
|
** for this layer. It must be called before accessing any
|
||||||
|
** other API functions for this layer. It is typically called
|
||||||
|
** once during the start up of the stack.
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void A2D_Init(void)
|
||||||
|
{
|
||||||
|
memset(&a2d_cb, 0, sizeof(tA2D_CB));
|
||||||
|
|
||||||
|
a2d_cb.avdt_sdp_ver = AVDT_VERSION;
|
||||||
|
|
||||||
|
#if defined(A2D_INITIAL_TRACE_LEVEL)
|
||||||
|
a2d_cb.trace_level = A2D_INITIAL_TRACE_LEVEL;
|
||||||
|
#else
|
||||||
|
a2d_cb.trace_level = BT_TRACE_LEVEL_NONE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
399
components/bt/bluedroid/stack/a2dp/a2d_sbc.c
Executable file
399
components/bt/bluedroid/stack/a2dp/a2d_sbc.c
Executable file
@ -0,0 +1,399 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Utility functions to help build and parse SBC Codec Information Element
|
||||||
|
* and Media Payload.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "bt_target.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "a2d_api.h"
|
||||||
|
#include "a2d_int.h"
|
||||||
|
#include "a2d_sbc.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
|
||||||
|
/*************************************************************************************************
|
||||||
|
* SBC descramble code
|
||||||
|
* Purpose: to tie the SBC code with BTE/mobile stack code,
|
||||||
|
* especially for the case when the SBC is ported into a third-party Multimedia chip
|
||||||
|
*
|
||||||
|
* Algorithm:
|
||||||
|
* init process: all counters reset to 0,
|
||||||
|
* calculate base_index: (6 + s16NumOfChannels*s16NumOfSubBands/2)
|
||||||
|
* scramble side: the init process happens every time SBC_Encoder_Init() is called.
|
||||||
|
* descramble side: it would be nice to know if he "init" process has happened.
|
||||||
|
* alter the SBC SYNC word 0x9C (1001 1100) to 0x8C (1000 1100).
|
||||||
|
*
|
||||||
|
* scramble process:
|
||||||
|
* The CRC byte:
|
||||||
|
* Every SBC frame has a frame header.
|
||||||
|
* The 1st byte is the sync word and the following 2 bytes are about the stream format.
|
||||||
|
* They are supposed to be "constant" within a "song"
|
||||||
|
* The 4th byte is the CRC byte. The CRC byte is bound to be random.
|
||||||
|
* Derive 2 items from the CRC byte; one is the "use" bit, the other is the "index".
|
||||||
|
*
|
||||||
|
* SBC keeps 2 sets of "use" & "index"; derived the current and the previous frame.
|
||||||
|
*
|
||||||
|
* The "use" bit is any bit in SBC_PRTC_USE_MASK is set.
|
||||||
|
* If set, SBC uses the "index" from the current frame.
|
||||||
|
* If not set, SBC uses the "index" from the previous frame or 0.
|
||||||
|
*
|
||||||
|
* index = (CRC & 0x3) + ((CRC & 0x30) >> 2) // 8 is the max index
|
||||||
|
*
|
||||||
|
* if(index > 0)
|
||||||
|
* {
|
||||||
|
* p = &u8frame[base_index];
|
||||||
|
* if((index&1)&&(u16PacketLength > (base_index+index*2)))
|
||||||
|
* {
|
||||||
|
* // odd index: swap 2 bytes
|
||||||
|
* tmp = p[index];
|
||||||
|
* p[index] = p[index*2];
|
||||||
|
* p[index*2] = tmp;
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // even index: shift by 3
|
||||||
|
* tmp = (p[index] >> 3) + (p[index] << 5);
|
||||||
|
* p[index] = tmp;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* //else index is 0. The frame stays unaltered
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define A2D_SBC_SYNC_WORD 0x9C
|
||||||
|
#define A2D_SBC_CRC_IDX 3
|
||||||
|
#define A2D_SBC_USE_MASK 0x64
|
||||||
|
#define A2D_SBC_SYNC_MASK 0x10
|
||||||
|
#define A2D_SBC_CIDX 0
|
||||||
|
#define A2D_SBC_LIDX 1
|
||||||
|
#define A2D_SBC_CH_M_BITS 0xC /* channel mode bits: 0: mono; 1 ch */
|
||||||
|
#define A2D_SBC_SUBBAND_BIT 0x1 /* num of subband bit: 0:4; 1: 8 */
|
||||||
|
|
||||||
|
#define A2D_SBC_GET_IDX(sc) (((sc) & 0x3) + (((sc) & 0x30) >> 2))
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT8 use;
|
||||||
|
UINT8 idx;
|
||||||
|
} tA2D_SBC_FR_CB;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
tA2D_SBC_FR_CB fr[2];
|
||||||
|
UINT8 index;
|
||||||
|
UINT8 base;
|
||||||
|
} tA2D_SBC_DS_CB;
|
||||||
|
|
||||||
|
static tA2D_SBC_DS_CB a2d_sbc_ds_cb;
|
||||||
|
/*int a2d_count = 0;*/
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_SbcChkFrInit
|
||||||
|
**
|
||||||
|
** Description check if need to init the descramble control block.
|
||||||
|
**
|
||||||
|
** Returns nothing.
|
||||||
|
******************************************************************************/
|
||||||
|
void A2D_SbcChkFrInit(UINT8 *p_pkt)
|
||||||
|
{
|
||||||
|
UINT8 fmt;
|
||||||
|
UINT8 num_chnl = 1;
|
||||||
|
UINT8 num_subband = 4;
|
||||||
|
|
||||||
|
if((p_pkt[0] & A2D_SBC_SYNC_MASK) == 0)
|
||||||
|
{
|
||||||
|
a2d_cb.use_desc = TRUE;
|
||||||
|
fmt = p_pkt[1];
|
||||||
|
p_pkt[0] |= A2D_SBC_SYNC_MASK;
|
||||||
|
memset(&a2d_sbc_ds_cb, 0, sizeof(tA2D_SBC_DS_CB));
|
||||||
|
if(fmt & A2D_SBC_CH_M_BITS)
|
||||||
|
num_chnl = 2;
|
||||||
|
if(fmt & A2D_SBC_SUBBAND_BIT)
|
||||||
|
num_subband = 8;
|
||||||
|
a2d_sbc_ds_cb.base = 6 + num_chnl*num_subband/2;
|
||||||
|
/*printf("base: %d\n", a2d_sbc_ds_cb.base);
|
||||||
|
a2d_count = 0;*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_SbcDescramble
|
||||||
|
**
|
||||||
|
** Description descramble the packet.
|
||||||
|
**
|
||||||
|
** Returns nothing.
|
||||||
|
******************************************************************************/
|
||||||
|
void A2D_SbcDescramble(UINT8 *p_pkt, UINT16 len)
|
||||||
|
{
|
||||||
|
tA2D_SBC_FR_CB *p_cur, *p_last;
|
||||||
|
UINT32 idx, tmp, tmp2;
|
||||||
|
|
||||||
|
if(a2d_cb.use_desc)
|
||||||
|
{
|
||||||
|
/* c2l */
|
||||||
|
p_last = &a2d_sbc_ds_cb.fr[A2D_SBC_LIDX];
|
||||||
|
p_cur = &a2d_sbc_ds_cb.fr[A2D_SBC_CIDX];
|
||||||
|
p_last->idx = p_cur->idx;
|
||||||
|
p_last->use = p_cur->use;
|
||||||
|
/* getc */
|
||||||
|
p_cur->use = p_pkt[A2D_SBC_CRC_IDX] & A2D_SBC_USE_MASK;
|
||||||
|
p_cur->idx = A2D_SBC_GET_IDX(p_pkt[A2D_SBC_CRC_IDX]);
|
||||||
|
a2d_sbc_ds_cb.index = (p_cur->use)?A2D_SBC_CIDX:A2D_SBC_LIDX;
|
||||||
|
/*
|
||||||
|
printf("%05d: ar[%02d]: x%02x, msk: x%02x, use: %s, idx: %02d, ",
|
||||||
|
a2d_count++,
|
||||||
|
A2D_SBC_CRC_IDX, p_pkt[A2D_SBC_CRC_IDX], A2D_SBC_USE_MASK,
|
||||||
|
(p_cur->use)?"cur":"lst", p_cur->idx);
|
||||||
|
*/
|
||||||
|
/* descramble */
|
||||||
|
idx = a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx;
|
||||||
|
if(idx > 0)
|
||||||
|
{
|
||||||
|
p_pkt = &p_pkt[a2d_sbc_ds_cb.base];
|
||||||
|
if((idx&1) && (len > (a2d_sbc_ds_cb.base+(idx<<1))))
|
||||||
|
{
|
||||||
|
tmp2 = (idx<<1);
|
||||||
|
tmp = p_pkt[idx];
|
||||||
|
p_pkt[idx] = p_pkt[tmp2];
|
||||||
|
p_pkt[tmp2] = tmp;
|
||||||
|
/*
|
||||||
|
printf("tmp2: %02d, len: %d, idx: %d\n",
|
||||||
|
tmp2, len, a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp2 = p_pkt[idx];
|
||||||
|
tmp = (tmp2>>3)+(tmp2<<5);
|
||||||
|
p_pkt[idx] = (UINT8)tmp;
|
||||||
|
/*
|
||||||
|
printf("tmp: x%02x, len: %d, idx: %d(cmp:%d)\n",
|
||||||
|
(UINT8)tmp2, len, a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx,
|
||||||
|
(a2d_sbc_ds_cb.base+(idx<<1)));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("!!!!\n");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_BldSbcInfo
|
||||||
|
**
|
||||||
|
** Description This function is called by an application to build
|
||||||
|
** the SBC Media Codec Capabilities byte sequence
|
||||||
|
** beginning from the LOSC octet.
|
||||||
|
** Input Parameters:
|
||||||
|
** media_type: Indicates Audio, or Multimedia.
|
||||||
|
**
|
||||||
|
** p_ie: The SBC Codec Information Element information.
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** p_result: the resulting codec info byte sequence.
|
||||||
|
**
|
||||||
|
** Returns A2D_SUCCESS if function execution succeeded.
|
||||||
|
** Error status code, otherwise.
|
||||||
|
******************************************************************************/
|
||||||
|
tA2D_STATUS A2D_BldSbcInfo(UINT8 media_type, tA2D_SBC_CIE *p_ie, UINT8 *p_result)
|
||||||
|
{
|
||||||
|
tA2D_STATUS status;
|
||||||
|
|
||||||
|
if( p_ie == NULL || p_result == NULL ||
|
||||||
|
(p_ie->samp_freq & ~A2D_SBC_IE_SAMP_FREQ_MSK) ||
|
||||||
|
(p_ie->ch_mode & ~A2D_SBC_IE_CH_MD_MSK) ||
|
||||||
|
(p_ie->block_len & ~A2D_SBC_IE_BLOCKS_MSK) ||
|
||||||
|
(p_ie->num_subbands & ~A2D_SBC_IE_SUBBAND_MSK) ||
|
||||||
|
(p_ie->alloc_mthd & ~A2D_SBC_IE_ALLOC_MD_MSK) ||
|
||||||
|
(p_ie->max_bitpool < p_ie->min_bitpool) ||
|
||||||
|
(p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL) ||
|
||||||
|
(p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL) ||
|
||||||
|
(p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL) ||
|
||||||
|
(p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL) )
|
||||||
|
{
|
||||||
|
/* if any unused bit is set */
|
||||||
|
status = A2D_INVALID_PARAMS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = A2D_SUCCESS;
|
||||||
|
*p_result++ = A2D_SBC_INFO_LEN;
|
||||||
|
*p_result++ = media_type;
|
||||||
|
*p_result++ = A2D_MEDIA_CT_SBC;
|
||||||
|
|
||||||
|
/* Media Codec Specific Information Element */
|
||||||
|
*p_result++ = p_ie->samp_freq | p_ie->ch_mode;
|
||||||
|
|
||||||
|
*p_result++ = p_ie->block_len | p_ie->num_subbands | p_ie->alloc_mthd;
|
||||||
|
|
||||||
|
*p_result++ = p_ie->min_bitpool;
|
||||||
|
*p_result = p_ie->max_bitpool;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_ParsSbcInfo
|
||||||
|
**
|
||||||
|
** Description This function is called by an application to parse
|
||||||
|
** the SBC Media Codec Capabilities byte sequence
|
||||||
|
** beginning from the LOSC octet.
|
||||||
|
** Input Parameters:
|
||||||
|
** p_info: the byte sequence to parse.
|
||||||
|
**
|
||||||
|
** for_caps: TRUE, if the byte sequence is for get capabilities response.
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** p_ie: The SBC Codec Information Element information.
|
||||||
|
**
|
||||||
|
** Returns A2D_SUCCESS if function execution succeeded.
|
||||||
|
** Error status code, otherwise.
|
||||||
|
******************************************************************************/
|
||||||
|
tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps)
|
||||||
|
{
|
||||||
|
tA2D_STATUS status;
|
||||||
|
UINT8 losc;
|
||||||
|
|
||||||
|
if( p_ie == NULL || p_info == NULL)
|
||||||
|
status = A2D_INVALID_PARAMS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
losc = *p_info++;
|
||||||
|
p_info++;
|
||||||
|
/* If the function is called for the wrong Media Type or Media Codec Type */
|
||||||
|
if(losc != A2D_SBC_INFO_LEN || *p_info != A2D_MEDIA_CT_SBC)
|
||||||
|
status = A2D_WRONG_CODEC;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_info++;
|
||||||
|
p_ie->samp_freq = *p_info & A2D_SBC_IE_SAMP_FREQ_MSK;
|
||||||
|
p_ie->ch_mode = *p_info & A2D_SBC_IE_CH_MD_MSK;
|
||||||
|
p_info++;
|
||||||
|
p_ie->block_len = *p_info & A2D_SBC_IE_BLOCKS_MSK;
|
||||||
|
p_ie->num_subbands = *p_info & A2D_SBC_IE_SUBBAND_MSK;
|
||||||
|
p_ie->alloc_mthd = *p_info & A2D_SBC_IE_ALLOC_MD_MSK;
|
||||||
|
p_info++;
|
||||||
|
p_ie->min_bitpool = *p_info++;
|
||||||
|
p_ie->max_bitpool = *p_info;
|
||||||
|
status = A2D_SUCCESS;
|
||||||
|
if(p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL )
|
||||||
|
status = A2D_BAD_MIN_BITPOOL;
|
||||||
|
|
||||||
|
if(p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL ||
|
||||||
|
p_ie->max_bitpool < p_ie->min_bitpool)
|
||||||
|
status = A2D_BAD_MAX_BITPOOL;
|
||||||
|
|
||||||
|
if(for_caps == FALSE)
|
||||||
|
{
|
||||||
|
if(A2D_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT)
|
||||||
|
status = A2D_BAD_SAMP_FREQ;
|
||||||
|
if(A2D_BitsSet(p_ie->ch_mode) != A2D_SET_ONE_BIT)
|
||||||
|
status = A2D_BAD_CH_MODE;
|
||||||
|
if(A2D_BitsSet(p_ie->block_len) != A2D_SET_ONE_BIT)
|
||||||
|
status = A2D_BAD_BLOCK_LEN;
|
||||||
|
if(A2D_BitsSet(p_ie->num_subbands) != A2D_SET_ONE_BIT)
|
||||||
|
status = A2D_BAD_SUBBANDS;
|
||||||
|
if(A2D_BitsSet(p_ie->alloc_mthd) != A2D_SET_ONE_BIT)
|
||||||
|
status = A2D_BAD_ALLOC_MTHD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_BldSbcMplHdr
|
||||||
|
**
|
||||||
|
** Description This function is called by an application to parse
|
||||||
|
** the SBC Media Payload header.
|
||||||
|
** Input Parameters:
|
||||||
|
** frag: 1, if fragmented. 0, otherwise.
|
||||||
|
**
|
||||||
|
** start: 1, if the starting packet of a fragmented frame.
|
||||||
|
**
|
||||||
|
** last: 1, if the last packet of a fragmented frame.
|
||||||
|
**
|
||||||
|
** num: If frag is 1, this is the number of remaining fragments
|
||||||
|
** (including this fragment) of this frame.
|
||||||
|
** If frag is 0, this is the number of frames in this packet.
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** p_dst: the resulting media payload header byte sequence.
|
||||||
|
**
|
||||||
|
** Returns void.
|
||||||
|
******************************************************************************/
|
||||||
|
void A2D_BldSbcMplHdr(UINT8 *p_dst, BOOLEAN frag, BOOLEAN start, BOOLEAN last, UINT8 num)
|
||||||
|
{
|
||||||
|
if(p_dst)
|
||||||
|
{
|
||||||
|
*p_dst = 0;
|
||||||
|
if(frag)
|
||||||
|
*p_dst |= A2D_SBC_HDR_F_MSK;
|
||||||
|
if(start)
|
||||||
|
*p_dst |= A2D_SBC_HDR_S_MSK;
|
||||||
|
if(last)
|
||||||
|
*p_dst |= A2D_SBC_HDR_L_MSK;
|
||||||
|
*p_dst |= (A2D_SBC_HDR_NUM_MSK & num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_ParsSbcMplHdr
|
||||||
|
**
|
||||||
|
** Description This function is called by an application to parse
|
||||||
|
** the SBC Media Payload header.
|
||||||
|
** Input Parameters:
|
||||||
|
** p_src: the byte sequence to parse..
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** frag: 1, if fragmented. 0, otherwise.
|
||||||
|
**
|
||||||
|
** start: 1, if the starting packet of a fragmented frame.
|
||||||
|
**
|
||||||
|
** last: 1, if the last packet of a fragmented frame.
|
||||||
|
**
|
||||||
|
** num: If frag is 1, this is the number of remaining fragments
|
||||||
|
** (including this fragment) of this frame.
|
||||||
|
** If frag is 0, this is the number of frames in this packet.
|
||||||
|
**
|
||||||
|
** Returns void.
|
||||||
|
******************************************************************************/
|
||||||
|
void A2D_ParsSbcMplHdr(UINT8 *p_src, BOOLEAN *p_frag, BOOLEAN *p_start, BOOLEAN *p_last, UINT8 *p_num)
|
||||||
|
{
|
||||||
|
if(p_src && p_frag && p_start && p_last && p_num)
|
||||||
|
{
|
||||||
|
*p_frag = (*p_src & A2D_SBC_HDR_F_MSK) ? TRUE: FALSE;
|
||||||
|
*p_start= (*p_src & A2D_SBC_HDR_S_MSK) ? TRUE: FALSE;
|
||||||
|
*p_last = (*p_src & A2D_SBC_HDR_L_MSK) ? TRUE: FALSE;
|
||||||
|
*p_num = (*p_src & A2D_SBC_HDR_NUM_MSK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
83
components/bt/bluedroid/stack/a2dp/include/a2d_int.h
Executable file
83
components/bt/bluedroid/stack/a2dp/include/a2d_int.h
Executable file
@ -0,0 +1,83 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 2DP internal header file
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef A2D_INT_H
|
||||||
|
#define A2D_INT_H
|
||||||
|
|
||||||
|
#include "a2d_api.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Constants
|
||||||
|
*****************************************************************************/
|
||||||
|
#define A2D_VERSION 0x0102
|
||||||
|
|
||||||
|
/* Number of attributes in A2D SDP record. */
|
||||||
|
#define A2D_NUM_ATTR 6
|
||||||
|
|
||||||
|
/* Number of protocol elements in protocol element list. */
|
||||||
|
#define A2D_NUM_PROTO_ELEMS 2
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Type definitions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* Control block used by A2D_FindService(). */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
tA2D_FIND_CBACK *p_cback; /* pointer to application callback */
|
||||||
|
tSDP_DISCOVERY_DB *p_db; /* pointer to discovery database */
|
||||||
|
UINT16 service_uuid; /* service UUID of search */
|
||||||
|
} tA2D_FIND_CB;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
tA2D_FIND_CB find; /* find service control block */
|
||||||
|
UINT8 trace_level;
|
||||||
|
BOOLEAN use_desc;
|
||||||
|
UINT16 avdt_sdp_ver; /* AVDTP version */
|
||||||
|
} tA2D_CB;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
** Main Control Block
|
||||||
|
*******************************************************************************/
|
||||||
|
#if A2D_DYNAMIC_MEMORY == FALSE
|
||||||
|
extern tA2D_CB a2d_cb;
|
||||||
|
#else
|
||||||
|
extern tA2D_CB *a2d_cb_ptr;
|
||||||
|
#define a2d_cb (*a2d_cb_ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Used only for conformance testing */
|
||||||
|
extern void a2d_set_avdt_sdp_ver (UINT16 avdt_sdp_ver);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* A2D_INT_H */
|
473
components/bt/bluedroid/stack/avct/avct_api.c
Executable file
473
components/bt/bluedroid/stack/avct/avct_api.c
Executable file
@ -0,0 +1,473 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This module contains API of the audio/video control transport protocol.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bt_types.h"
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
#include "gki.h"
|
||||||
|
#include "l2c_api.h"
|
||||||
|
#include "l2cdefs.h"
|
||||||
|
#include "btm_api.h"
|
||||||
|
#include "avct_api.h"
|
||||||
|
#include "avct_int.h"
|
||||||
|
|
||||||
|
/* Control block for AVCT */
|
||||||
|
#if AVCT_DYNAMIC_MEMORY == FALSE
|
||||||
|
tAVCT_CB avct_cb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVCT_Register
|
||||||
|
**
|
||||||
|
** Description This is the system level registration function for the
|
||||||
|
** AVCTP protocol. This function initializes AVCTP and
|
||||||
|
** prepares the protocol stack for its use. This function
|
||||||
|
** must be called once by the system or platform using AVCTP
|
||||||
|
** before the other functions of the API an be used.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void AVCT_Register(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask)
|
||||||
|
{
|
||||||
|
UNUSED(mtu_br);
|
||||||
|
|
||||||
|
AVCT_TRACE_API("AVCT_Register");
|
||||||
|
|
||||||
|
/* register PSM with L2CAP */
|
||||||
|
L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_appl);
|
||||||
|
|
||||||
|
/* set security level */
|
||||||
|
BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
|
||||||
|
BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
|
||||||
|
|
||||||
|
/* initialize AVCTP data structures */
|
||||||
|
memset(&avct_cb, 0, sizeof(tAVCT_CB));
|
||||||
|
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
/* Include the browsing channel which uses eFCR */
|
||||||
|
L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_br_appl);
|
||||||
|
|
||||||
|
BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
|
||||||
|
BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
|
||||||
|
|
||||||
|
if (mtu_br < AVCT_MIN_BROWSE_MTU)
|
||||||
|
mtu_br = AVCT_MIN_BROWSE_MTU;
|
||||||
|
avct_cb.mtu_br = mtu_br;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(AVCT_INITIAL_TRACE_LEVEL)
|
||||||
|
avct_cb.trace_level = AVCT_INITIAL_TRACE_LEVEL;
|
||||||
|
#else
|
||||||
|
avct_cb.trace_level = BT_TRACE_LEVEL_NONE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (mtu < AVCT_MIN_CONTROL_MTU)
|
||||||
|
mtu = AVCT_MIN_CONTROL_MTU;
|
||||||
|
/* store mtu */
|
||||||
|
avct_cb.mtu = mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVCT_Deregister
|
||||||
|
**
|
||||||
|
** Description This function is called to deregister use AVCTP protocol.
|
||||||
|
** It is called when AVCTP is no longer being used by any
|
||||||
|
** application in the system. Before this function can be
|
||||||
|
** called, all connections must be removed with
|
||||||
|
** AVCT_RemoveConn().
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void AVCT_Deregister(void)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_API("AVCT_Deregister");
|
||||||
|
|
||||||
|
/* deregister PSM with L2CAP */
|
||||||
|
L2CA_Deregister(AVCT_PSM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVCT_CreateConn
|
||||||
|
**
|
||||||
|
** Description Create an AVCTP connection. There are two types of
|
||||||
|
** connections, initiator and acceptor, as determined by
|
||||||
|
** the p_cc->role parameter. When this function is called to
|
||||||
|
** create an initiator connection, an AVCTP connection to
|
||||||
|
** the peer device is initiated if one does not already exist.
|
||||||
|
** If an acceptor connection is created, the connection waits
|
||||||
|
** passively for an incoming AVCTP connection from a peer device.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns AVCT_SUCCESS if successful, otherwise error.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 AVCT_CreateConn(UINT8 *p_handle, tAVCT_CC *p_cc, BD_ADDR peer_addr)
|
||||||
|
{
|
||||||
|
UINT16 result = AVCT_SUCCESS;
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
tAVCT_LCB *p_lcb;
|
||||||
|
|
||||||
|
AVCT_TRACE_API("AVCT_CreateConn: %d, control:%d", p_cc->role, p_cc->control);
|
||||||
|
|
||||||
|
/* Allocate ccb; if no ccbs, return failure */
|
||||||
|
if ((p_ccb = avct_ccb_alloc(p_cc)) == NULL)
|
||||||
|
{
|
||||||
|
result = AVCT_NO_RESOURCES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* get handle */
|
||||||
|
*p_handle = avct_ccb_to_idx(p_ccb);
|
||||||
|
|
||||||
|
/* if initiator connection */
|
||||||
|
if (p_cc->role == AVCT_INT)
|
||||||
|
{
|
||||||
|
/* find link; if none allocate a new one */
|
||||||
|
if ((p_lcb = avct_lcb_by_bd(peer_addr)) == NULL)
|
||||||
|
{
|
||||||
|
if ((p_lcb = avct_lcb_alloc(peer_addr)) == NULL)
|
||||||
|
{
|
||||||
|
/* no link resources; free ccb as well */
|
||||||
|
avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
|
||||||
|
result = AVCT_NO_RESOURCES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* check if PID already in use */
|
||||||
|
else if (avct_lcb_has_pid(p_lcb, p_cc->pid))
|
||||||
|
{
|
||||||
|
avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
|
||||||
|
result = AVCT_PID_IN_USE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == AVCT_SUCCESS)
|
||||||
|
{
|
||||||
|
/* bind lcb to ccb */
|
||||||
|
p_ccb->p_lcb = p_lcb;
|
||||||
|
AVCT_TRACE_DEBUG("ch_state: %d", p_lcb->ch_state);
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVCT_RemoveConn
|
||||||
|
**
|
||||||
|
** Description Remove an AVCTP connection. This function is called when
|
||||||
|
** the application is no longer using a connection. If this
|
||||||
|
** is the last connection to a peer the L2CAP channel for AVCTP
|
||||||
|
** will be closed.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns AVCT_SUCCESS if successful, otherwise error.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 AVCT_RemoveConn(UINT8 handle)
|
||||||
|
{
|
||||||
|
UINT16 result = AVCT_SUCCESS;
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
|
||||||
|
AVCT_TRACE_API("AVCT_RemoveConn");
|
||||||
|
|
||||||
|
/* map handle to ccb */
|
||||||
|
if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
|
||||||
|
{
|
||||||
|
result = AVCT_BAD_HANDLE;
|
||||||
|
}
|
||||||
|
/* if connection not bound to lcb, dealloc */
|
||||||
|
else if (p_ccb->p_lcb == NULL)
|
||||||
|
{
|
||||||
|
avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
|
||||||
|
}
|
||||||
|
/* send unbind event to lcb */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVCT_CreateBrowse
|
||||||
|
**
|
||||||
|
** Description Create an AVCTP Browse channel. There are two types of
|
||||||
|
** connections, initiator and acceptor, as determined by
|
||||||
|
** the role parameter. When this function is called to
|
||||||
|
** create an initiator connection, the Browse channel to
|
||||||
|
** the peer device is initiated if one does not already exist.
|
||||||
|
** If an acceptor connection is created, the connection waits
|
||||||
|
** passively for an incoming AVCTP connection from a peer device.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns AVCT_SUCCESS if successful, otherwise error.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 AVCT_CreateBrowse (UINT8 handle, UINT8 role)
|
||||||
|
{
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
UINT16 result = AVCT_SUCCESS;
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
tAVCT_BCB *p_bcb;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
AVCT_TRACE_API("AVCT_CreateBrowse: %d", role);
|
||||||
|
|
||||||
|
/* map handle to ccb */
|
||||||
|
if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
|
||||||
|
{
|
||||||
|
return AVCT_BAD_HANDLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* mark this CCB as supporting browsing channel */
|
||||||
|
if ((p_ccb->allocated & AVCT_ALOC_BCB) == 0)
|
||||||
|
{
|
||||||
|
p_ccb->allocated |= AVCT_ALOC_BCB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if initiator connection */
|
||||||
|
if (role == AVCT_INT)
|
||||||
|
{
|
||||||
|
/* the link control block must exist before this function is called as INT. */
|
||||||
|
if ((p_ccb->p_lcb == NULL) || (p_ccb->p_lcb->allocated == 0))
|
||||||
|
{
|
||||||
|
result = AVCT_NOT_OPEN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* find link; if none allocate a new one */
|
||||||
|
index = p_ccb->p_lcb->allocated;
|
||||||
|
if (index > AVCT_NUM_LINKS)
|
||||||
|
{
|
||||||
|
result = AVCT_BAD_HANDLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_bcb = &avct_cb.bcb[index - 1];
|
||||||
|
p_bcb->allocated = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == AVCT_SUCCESS)
|
||||||
|
{
|
||||||
|
/* bind bcb to ccb */
|
||||||
|
p_ccb->p_bcb = p_bcb;
|
||||||
|
AVCT_TRACE_DEBUG("ch_state: %d", p_bcb->ch_state);
|
||||||
|
avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
UNUSED(handle);
|
||||||
|
UNUSED(role);
|
||||||
|
return AVCT_NO_RESOURCES;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVCT_RemoveBrowse
|
||||||
|
**
|
||||||
|
** Description Remove an AVCTP Browse channel. This function is called when
|
||||||
|
** the application is no longer using a connection. If this
|
||||||
|
** is the last connection to a peer the L2CAP channel for AVCTP
|
||||||
|
** will be closed.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns AVCT_SUCCESS if successful, otherwise error.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 AVCT_RemoveBrowse (UINT8 handle)
|
||||||
|
{
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
UINT16 result = AVCT_SUCCESS;
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
|
||||||
|
AVCT_TRACE_API("AVCT_RemoveBrowse");
|
||||||
|
|
||||||
|
/* map handle to ccb */
|
||||||
|
if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
|
||||||
|
{
|
||||||
|
result = AVCT_BAD_HANDLE;
|
||||||
|
}
|
||||||
|
else if (p_ccb->p_bcb != NULL)
|
||||||
|
/* send unbind event to bcb */
|
||||||
|
{
|
||||||
|
avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
UNUSED(handle);
|
||||||
|
return AVCT_NO_RESOURCES;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVCT_GetBrowseMtu
|
||||||
|
**
|
||||||
|
** Description Get the peer_mtu for the AVCTP Browse channel of the given
|
||||||
|
** connection.
|
||||||
|
**
|
||||||
|
** Returns the peer browsing channel MTU.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 AVCT_GetBrowseMtu (UINT8 handle)
|
||||||
|
{
|
||||||
|
UINT16 peer_mtu = AVCT_MIN_BROWSE_MTU;
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
|
||||||
|
if ((p_ccb = avct_ccb_by_idx(handle)) != NULL && p_ccb->p_bcb != NULL)
|
||||||
|
{
|
||||||
|
peer_mtu = p_ccb->p_bcb->peer_mtu;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
UNUSED(handle);
|
||||||
|
#endif
|
||||||
|
return peer_mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVCT_GetPeerMtu
|
||||||
|
**
|
||||||
|
** Description Get the peer_mtu for the AVCTP channel of the given
|
||||||
|
** connection.
|
||||||
|
**
|
||||||
|
** Returns the peer MTU size.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 AVCT_GetPeerMtu (UINT8 handle)
|
||||||
|
{
|
||||||
|
UINT16 peer_mtu = L2CAP_DEFAULT_MTU;
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
|
||||||
|
/* map handle to ccb */
|
||||||
|
if ((p_ccb = avct_ccb_by_idx(handle)) != NULL)
|
||||||
|
{
|
||||||
|
if (p_ccb->p_lcb)
|
||||||
|
{
|
||||||
|
peer_mtu = p_ccb->p_lcb->peer_mtu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return peer_mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function AVCT_MsgReq
|
||||||
|
**
|
||||||
|
** Description Send an AVCTP message to a peer device. In calling
|
||||||
|
** AVCT_MsgReq(), the application should keep track of the
|
||||||
|
** congestion state of AVCTP as communicated with events
|
||||||
|
** AVCT_CONG_IND_EVT and AVCT_UNCONG_IND_EVT. If the
|
||||||
|
** application calls AVCT_MsgReq() when AVCTP is congested
|
||||||
|
** the message may be discarded. The application may make its
|
||||||
|
** first call to AVCT_MsgReq() after it receives an
|
||||||
|
** AVCT_CONNECT_CFM_EVT or AVCT_CONNECT_IND_EVT on control channel or
|
||||||
|
** AVCT_BROWSE_CONN_CFM_EVT or AVCT_BROWSE_CONN_IND_EVT on browsing channel.
|
||||||
|
**
|
||||||
|
** p_msg->layer_specific must be set to
|
||||||
|
** AVCT_DATA_CTRL for control channel traffic;
|
||||||
|
** AVCT_DATA_BROWSE for for browse channel traffic.
|
||||||
|
**
|
||||||
|
** Returns AVCT_SUCCESS if successful, otherwise error.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg)
|
||||||
|
{
|
||||||
|
UINT16 result = AVCT_SUCCESS;
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
tAVCT_UL_MSG ul_msg;
|
||||||
|
|
||||||
|
AVCT_TRACE_API("AVCT_MsgReq");
|
||||||
|
|
||||||
|
/* verify p_msg parameter */
|
||||||
|
if (p_msg == NULL)
|
||||||
|
{
|
||||||
|
return AVCT_NO_RESOURCES;
|
||||||
|
}
|
||||||
|
AVCT_TRACE_API("len: %d", p_msg->len);
|
||||||
|
|
||||||
|
/* map handle to ccb */
|
||||||
|
if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
|
||||||
|
{
|
||||||
|
result = AVCT_BAD_HANDLE;
|
||||||
|
GKI_freebuf(p_msg);
|
||||||
|
}
|
||||||
|
/* verify channel is bound to link */
|
||||||
|
else if (p_ccb->p_lcb == NULL)
|
||||||
|
{
|
||||||
|
result = AVCT_NOT_OPEN;
|
||||||
|
GKI_freebuf(p_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == AVCT_SUCCESS)
|
||||||
|
{
|
||||||
|
ul_msg.p_buf = p_msg;
|
||||||
|
ul_msg.p_ccb = p_ccb;
|
||||||
|
ul_msg.label = label;
|
||||||
|
ul_msg.cr = cr;
|
||||||
|
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
/* send msg event to bcb */
|
||||||
|
if (p_msg->layer_specific == AVCT_DATA_BROWSE)
|
||||||
|
{
|
||||||
|
if (p_ccb->p_bcb == NULL && (p_ccb->allocated & AVCT_ALOC_BCB) == 0)
|
||||||
|
{
|
||||||
|
/* BCB channel is not open and not allocated */
|
||||||
|
result = AVCT_BAD_HANDLE;
|
||||||
|
GKI_freebuf(p_msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb);
|
||||||
|
avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* send msg event to lcb */
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
150
components/bt/bluedroid/stack/avct/avct_ccb.c
Executable file
150
components/bt/bluedroid/stack/avct/avct_ccb.c
Executable file
@ -0,0 +1,150 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This module contains functions which operate on the AVCTP connection
|
||||||
|
* control block.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bt_types.h"
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "avct_api.h"
|
||||||
|
#include "avct_int.h"
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_ccb_alloc
|
||||||
|
**
|
||||||
|
** Description Allocate a connection control block; copy parameters to ccb.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns pointer to the ccb, or NULL if none could be allocated.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVCT_CCB *avct_ccb_alloc(tAVCT_CC *p_cc)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
if (!p_ccb->allocated)
|
||||||
|
{
|
||||||
|
p_ccb->allocated = AVCT_ALOC_LCB;
|
||||||
|
memcpy(&p_ccb->cc, p_cc, sizeof(tAVCT_CC));
|
||||||
|
AVCT_TRACE_DEBUG("avct_ccb_alloc %d", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == AVCT_NUM_CONN)
|
||||||
|
{
|
||||||
|
/* out of ccbs */
|
||||||
|
p_ccb = NULL;
|
||||||
|
AVCT_TRACE_WARNING("Out of ccbs");
|
||||||
|
}
|
||||||
|
return p_ccb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_ccb_dealloc
|
||||||
|
**
|
||||||
|
** Description Deallocate a connection control block and call application
|
||||||
|
** callback.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_ccb_dealloc(tAVCT_CCB *p_ccb, UINT8 event, UINT16 result, BD_ADDR bd_addr)
|
||||||
|
{
|
||||||
|
tAVCT_CTRL_CBACK *p_cback = p_ccb->cc.p_ctrl_cback;
|
||||||
|
|
||||||
|
AVCT_TRACE_DEBUG("avct_ccb_dealloc %d", avct_ccb_to_idx(p_ccb));
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
if(p_ccb->p_bcb == NULL)
|
||||||
|
memset(p_ccb, 0, sizeof(tAVCT_CCB));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* control channel is down, but the browsing channel is still connected 0 disconnect it now */
|
||||||
|
avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
|
||||||
|
p_ccb->p_lcb = NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
memset(p_ccb, 0, sizeof(tAVCT_CCB));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (event != AVCT_NO_EVT)
|
||||||
|
{
|
||||||
|
(*p_cback)(avct_ccb_to_idx(p_ccb), event, result, bd_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_ccb_to_idx
|
||||||
|
**
|
||||||
|
** Description Given a pointer to an ccb, return its index.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Index of ccb.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT8 avct_ccb_to_idx(tAVCT_CCB *p_ccb)
|
||||||
|
{
|
||||||
|
/* use array arithmetic to determine index */
|
||||||
|
return (UINT8) (p_ccb - avct_cb.ccb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_ccb_by_idx
|
||||||
|
**
|
||||||
|
** Description Return ccb pointer based on ccb index (or handle).
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns pointer to the ccb, or NULL if none found.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVCT_CCB *avct_ccb_by_idx(UINT8 idx)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
|
||||||
|
/* verify index */
|
||||||
|
if (idx < AVCT_NUM_CONN)
|
||||||
|
{
|
||||||
|
p_ccb = &avct_cb.ccb[idx];
|
||||||
|
|
||||||
|
/* verify ccb is allocated */
|
||||||
|
if (!p_ccb->allocated)
|
||||||
|
{
|
||||||
|
p_ccb = NULL;
|
||||||
|
AVCT_TRACE_WARNING("ccb %d not allocated", idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_ccb = NULL;
|
||||||
|
AVCT_TRACE_WARNING("No ccb for idx %d", idx);
|
||||||
|
}
|
||||||
|
return p_ccb;
|
||||||
|
}
|
436
components/bt/bluedroid/stack/avct/avct_l2c.c
Executable file
436
components/bt/bluedroid/stack/avct/avct_l2c.c
Executable file
@ -0,0 +1,436 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This AVCTP module interfaces to L2CAP
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bt_types.h"
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
#include "avct_api.h"
|
||||||
|
#include "avct_int.h"
|
||||||
|
#include "l2c_api.h"
|
||||||
|
#include "l2cdefs.h"
|
||||||
|
|
||||||
|
/* Configuration flags. */
|
||||||
|
#define AVCT_L2C_CFG_IND_DONE (1<<0)
|
||||||
|
#define AVCT_L2C_CFG_CFM_DONE (1<<1)
|
||||||
|
|
||||||
|
/* callback function declarations */
|
||||||
|
void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
|
||||||
|
void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
|
||||||
|
void avct_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
|
||||||
|
void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
|
||||||
|
void avct_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
|
||||||
|
void avct_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
|
||||||
|
void avct_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
|
||||||
|
void avct_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
|
||||||
|
|
||||||
|
/* L2CAP callback function structure */
|
||||||
|
const tL2CAP_APPL_INFO avct_l2c_appl = {
|
||||||
|
avct_l2c_connect_ind_cback,
|
||||||
|
avct_l2c_connect_cfm_cback,
|
||||||
|
NULL,
|
||||||
|
avct_l2c_config_ind_cback,
|
||||||
|
avct_l2c_config_cfm_cback,
|
||||||
|
avct_l2c_disconnect_ind_cback,
|
||||||
|
avct_l2c_disconnect_cfm_cback,
|
||||||
|
NULL,
|
||||||
|
avct_l2c_data_ind_cback,
|
||||||
|
avct_l2c_congestion_ind_cback,
|
||||||
|
NULL /* tL2CA_TX_COMPLETE_CB */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_l2c_is_passive
|
||||||
|
**
|
||||||
|
** Description check is the CCB associated with the given LCB was created
|
||||||
|
** as passive
|
||||||
|
**
|
||||||
|
** Returns TRUE, if the given LCB is created as AVCT_PASSIVE
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
static BOOLEAN avct_l2c_is_passive (tAVCT_LCB *p_lcb)
|
||||||
|
{
|
||||||
|
BOOLEAN is_passive = FALSE;
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_is_ct control:x%x", p_ccb->cc.control);
|
||||||
|
if (p_ccb->cc.control & AVCT_PASSIVE)
|
||||||
|
{
|
||||||
|
is_passive = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return is_passive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_l2c_connect_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP connect indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb;
|
||||||
|
UINT16 result = L2CAP_CONN_OK;
|
||||||
|
tL2CAP_CFG_INFO cfg;
|
||||||
|
UNUSED(psm);
|
||||||
|
|
||||||
|
/* do we already have a channel for this peer? */
|
||||||
|
if ((p_lcb = avct_lcb_by_bd(bd_addr)) == NULL)
|
||||||
|
{
|
||||||
|
/* no, allocate lcb */
|
||||||
|
if ((p_lcb = avct_lcb_alloc(bd_addr)) == NULL)
|
||||||
|
{
|
||||||
|
/* no ccb available, reject L2CAP connection */
|
||||||
|
result = L2CAP_CONN_NO_RESOURCES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* else we already have a channel for this peer */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!avct_l2c_is_passive (p_lcb) || (p_lcb->ch_state == AVCT_CH_OPEN))
|
||||||
|
{
|
||||||
|
/* this LCB included CT role - reject */
|
||||||
|
result = L2CAP_CONN_NO_RESOURCES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* TG role only - accept the connection from CT. move the channel ID to the conflict list */
|
||||||
|
p_lcb->conflict_lcid = p_lcb->ch_lcid;
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback conflict_lcid:0x%x", p_lcb->conflict_lcid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p_lcb)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback: 0x%x, res: %d, ch_state: %d",
|
||||||
|
lcid, result, p_lcb->ch_state);
|
||||||
|
}
|
||||||
|
/* Send L2CAP connect rsp */
|
||||||
|
L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
|
||||||
|
|
||||||
|
/* if result ok, proceed with connection */
|
||||||
|
if (result == L2CAP_CONN_OK)
|
||||||
|
{
|
||||||
|
/* store LCID */
|
||||||
|
p_lcb->ch_lcid = lcid;
|
||||||
|
|
||||||
|
/* transition to configuration state */
|
||||||
|
p_lcb->ch_state = AVCT_CH_CFG;
|
||||||
|
|
||||||
|
/* Send L2CAP config req */
|
||||||
|
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||||
|
cfg.mtu_present = TRUE;
|
||||||
|
cfg.mtu = avct_cb.mtu;
|
||||||
|
L2CA_ConfigReq(lcid, &cfg);
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c snd Cfg Req");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (BT_USE_TRACES == TRUE)
|
||||||
|
if(p_lcb)
|
||||||
|
AVCT_TRACE_DEBUG("ch_state cni: %d ", p_lcb->ch_state);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_l2c_connect_cfm_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP connect confirm callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb;
|
||||||
|
tL2CAP_CFG_INFO cfg;
|
||||||
|
|
||||||
|
/* look up lcb for this channel */
|
||||||
|
if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback lcid:0x%x result: %d ch_state: %d, conflict_lcid:0x%x",
|
||||||
|
lcid, result, p_lcb->ch_state, p_lcb->conflict_lcid);
|
||||||
|
/* if in correct state */
|
||||||
|
if (p_lcb->ch_state == AVCT_CH_CONN)
|
||||||
|
{
|
||||||
|
/* if result successful */
|
||||||
|
if (result == L2CAP_CONN_OK)
|
||||||
|
{
|
||||||
|
/* set channel state */
|
||||||
|
p_lcb->ch_state = AVCT_CH_CFG;
|
||||||
|
|
||||||
|
/* Send L2CAP config req */
|
||||||
|
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||||
|
cfg.mtu_present = TRUE;
|
||||||
|
cfg.mtu = avct_cb.mtu;
|
||||||
|
L2CA_ConfigReq(lcid, &cfg);
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c snd Cfg Req");
|
||||||
|
}
|
||||||
|
/* else failure */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback conflict_lcid:0x%x", p_lcb->conflict_lcid);
|
||||||
|
if (p_lcb->conflict_lcid == lcid)
|
||||||
|
p_lcb->conflict_lcid = 0;
|
||||||
|
else
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p_lcb->conflict_lcid == lcid)
|
||||||
|
{
|
||||||
|
/* we must be in AVCT_CH_CFG state for the ch_lcid channel */
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback ch_state: %d, conflict_lcid:0x%x", p_lcb->ch_state, p_lcb->conflict_lcid);
|
||||||
|
if (result == L2CAP_CONN_OK)
|
||||||
|
{
|
||||||
|
/* just in case the peer also accepts our connection - Send L2CAP disconnect req */
|
||||||
|
L2CA_DisconnectReq(lcid);
|
||||||
|
}
|
||||||
|
p_lcb->conflict_lcid = 0;
|
||||||
|
}
|
||||||
|
AVCT_TRACE_DEBUG("ch_state cnc: %d ", p_lcb->ch_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_l2c_config_cfm_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP config confirm callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb;
|
||||||
|
|
||||||
|
/* look up lcb for this channel */
|
||||||
|
if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_config_cfm_cback: 0x%x, ch_state: %d, res: %d",
|
||||||
|
lcid, p_lcb->ch_state, p_cfg->result);
|
||||||
|
/* if in correct state */
|
||||||
|
if (p_lcb->ch_state == AVCT_CH_CFG)
|
||||||
|
{
|
||||||
|
/* if result successful */
|
||||||
|
if (p_cfg->result == L2CAP_CFG_OK)
|
||||||
|
{
|
||||||
|
/* update flags */
|
||||||
|
p_lcb->ch_flags |= AVCT_L2C_CFG_CFM_DONE;
|
||||||
|
|
||||||
|
/* if configuration complete */
|
||||||
|
if (p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE)
|
||||||
|
{
|
||||||
|
p_lcb->ch_state = AVCT_CH_OPEN;
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* else failure */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("ERROR avct_l2c_config_cfm_cback L2CA_DisconnectReq %d ", p_lcb->ch_state);
|
||||||
|
/* store result value */
|
||||||
|
p_lcb->ch_result = p_cfg->result;
|
||||||
|
|
||||||
|
/* Send L2CAP disconnect req */
|
||||||
|
L2CA_DisconnectReq(lcid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AVCT_TRACE_DEBUG("ch_state cfc: %d ", p_lcb->ch_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_l2c_config_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP config indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb;
|
||||||
|
|
||||||
|
/* look up lcb for this channel */
|
||||||
|
if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_config_ind_cback: 0x%x, ch_state: %d", lcid, p_lcb->ch_state);
|
||||||
|
/* store the mtu in tbl */
|
||||||
|
if (p_cfg->mtu_present)
|
||||||
|
{
|
||||||
|
p_lcb->peer_mtu = p_cfg->mtu;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_lcb->peer_mtu = L2CAP_DEFAULT_MTU;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send L2CAP configure response */
|
||||||
|
memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||||
|
p_cfg->result = L2CAP_CFG_OK;
|
||||||
|
L2CA_ConfigRsp(lcid, p_cfg);
|
||||||
|
|
||||||
|
/* if first config ind */
|
||||||
|
if ((p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) == 0)
|
||||||
|
{
|
||||||
|
/* update flags */
|
||||||
|
p_lcb->ch_flags |= AVCT_L2C_CFG_IND_DONE;
|
||||||
|
|
||||||
|
/* if configuration complete */
|
||||||
|
if (p_lcb->ch_flags & AVCT_L2C_CFG_CFM_DONE)
|
||||||
|
{
|
||||||
|
p_lcb->ch_state = AVCT_CH_OPEN;
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AVCT_TRACE_DEBUG("ch_state cfi: %d ", p_lcb->ch_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_l2c_disconnect_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP disconnect indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb;
|
||||||
|
UINT16 result = AVCT_RESULT_FAIL;
|
||||||
|
|
||||||
|
/* look up lcb for this channel */
|
||||||
|
if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_disconnect_ind_cback: 0x%x, ch_state: %d", lcid, p_lcb->ch_state);
|
||||||
|
if (ack_needed)
|
||||||
|
{
|
||||||
|
/* send L2CAP disconnect response */
|
||||||
|
L2CA_DisconnectRsp(lcid);
|
||||||
|
}
|
||||||
|
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
|
||||||
|
AVCT_TRACE_DEBUG("ch_state di: %d ", p_lcb->ch_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_l2c_disconnect_cfm_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP disconnect confirm callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb;
|
||||||
|
UINT16 res;
|
||||||
|
|
||||||
|
/* look up lcb for this channel */
|
||||||
|
if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_disconnect_cfm_cback: 0x%x, ch_state: %d, res: %d",
|
||||||
|
lcid, p_lcb->ch_state, result);
|
||||||
|
/* result value may be previously stored */
|
||||||
|
res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result;
|
||||||
|
p_lcb->ch_result = 0;
|
||||||
|
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &res);
|
||||||
|
AVCT_TRACE_DEBUG("ch_state dc: %d ", p_lcb->ch_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_l2c_congestion_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP congestion indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb;
|
||||||
|
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_congestion_ind_cback: 0x%x", lcid);
|
||||||
|
/* look up lcb for this channel */
|
||||||
|
if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, (tAVCT_LCB_EVT *) &is_congested);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_l2c_data_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP data indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb;
|
||||||
|
|
||||||
|
AVCT_TRACE_DEBUG("avct_l2c_data_ind_cback: 0x%x", lcid);
|
||||||
|
/* look up lcb for this channel */
|
||||||
|
if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, (tAVCT_LCB_EVT *) &p_buf);
|
||||||
|
}
|
||||||
|
else /* prevent buffer leak */
|
||||||
|
{
|
||||||
|
AVCT_TRACE_WARNING("ERROR -> avct_l2c_data_ind_cback drop buffer");
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
473
components/bt/bluedroid/stack/avct/avct_lcb.c
Executable file
473
components/bt/bluedroid/stack/avct/avct_lcb.c
Executable file
@ -0,0 +1,473 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This module contains the link control state machine and functions which
|
||||||
|
* operate on the link control block.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bt_types.h"
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
#include "avct_api.h"
|
||||||
|
#include "avct_int.h"
|
||||||
|
#include "gki.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** state machine constants and types
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#if BT_TRACE_VERBOSE == TRUE
|
||||||
|
|
||||||
|
/* verbose state strings for trace */
|
||||||
|
const char * const avct_lcb_st_str[] = {
|
||||||
|
"LCB_IDLE_ST",
|
||||||
|
"LCB_OPENING_ST",
|
||||||
|
"LCB_OPEN_ST",
|
||||||
|
"LCB_CLOSING_ST"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* verbose event strings for trace */
|
||||||
|
const char * const avct_lcb_evt_str[] = {
|
||||||
|
"UL_BIND_EVT",
|
||||||
|
"UL_UNBIND_EVT",
|
||||||
|
"UL_MSG_EVT",
|
||||||
|
"INT_CLOSE_EVT",
|
||||||
|
"LL_OPEN_EVT",
|
||||||
|
"LL_CLOSE_EVT",
|
||||||
|
"LL_MSG_EVT",
|
||||||
|
"LL_CONG_EVT"
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* lcb state machine states */
|
||||||
|
enum {
|
||||||
|
AVCT_LCB_IDLE_ST,
|
||||||
|
AVCT_LCB_OPENING_ST,
|
||||||
|
AVCT_LCB_OPEN_ST,
|
||||||
|
AVCT_LCB_CLOSING_ST
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state machine action enumeration list */
|
||||||
|
enum {
|
||||||
|
AVCT_LCB_CHNL_OPEN,
|
||||||
|
AVCT_LCB_CHNL_DISC,
|
||||||
|
AVCT_LCB_SEND_MSG,
|
||||||
|
AVCT_LCB_OPEN_IND,
|
||||||
|
AVCT_LCB_OPEN_FAIL,
|
||||||
|
AVCT_LCB_CLOSE_IND,
|
||||||
|
AVCT_LCB_CLOSE_CFM,
|
||||||
|
AVCT_LCB_MSG_IND,
|
||||||
|
AVCT_LCB_CONG_IND,
|
||||||
|
AVCT_LCB_BIND_CONN,
|
||||||
|
AVCT_LCB_BIND_FAIL,
|
||||||
|
AVCT_LCB_UNBIND_DISC,
|
||||||
|
AVCT_LCB_CHK_DISC,
|
||||||
|
AVCT_LCB_DISCARD_MSG,
|
||||||
|
AVCT_LCB_DEALLOC,
|
||||||
|
AVCT_LCB_FREE_MSG_IND,
|
||||||
|
AVCT_LCB_NUM_ACTIONS
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AVCT_LCB_IGNORE AVCT_LCB_NUM_ACTIONS
|
||||||
|
|
||||||
|
/* type for action functions */
|
||||||
|
typedef void (*tAVCT_LCB_ACTION)(tAVCT_LCB *p_ccb, tAVCT_LCB_EVT *p_data);
|
||||||
|
|
||||||
|
/* action function list */
|
||||||
|
const tAVCT_LCB_ACTION avct_lcb_action[] = {
|
||||||
|
avct_lcb_chnl_open,
|
||||||
|
avct_lcb_chnl_disc,
|
||||||
|
avct_lcb_send_msg,
|
||||||
|
avct_lcb_open_ind,
|
||||||
|
avct_lcb_open_fail,
|
||||||
|
avct_lcb_close_ind,
|
||||||
|
avct_lcb_close_cfm,
|
||||||
|
avct_lcb_msg_ind,
|
||||||
|
avct_lcb_cong_ind,
|
||||||
|
avct_lcb_bind_conn,
|
||||||
|
avct_lcb_bind_fail,
|
||||||
|
avct_lcb_unbind_disc,
|
||||||
|
avct_lcb_chk_disc,
|
||||||
|
avct_lcb_discard_msg,
|
||||||
|
avct_lcb_dealloc,
|
||||||
|
avct_lcb_free_msg_ind
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table information */
|
||||||
|
#define AVCT_LCB_ACTIONS 2 /* number of actions */
|
||||||
|
#define AVCT_LCB_NEXT_STATE 2 /* position of next state */
|
||||||
|
#define AVCT_LCB_NUM_COLS 3 /* number of columns in state tables */
|
||||||
|
|
||||||
|
/* state table for idle state */
|
||||||
|
const UINT8 avct_lcb_st_idle[][AVCT_LCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* UL_BIND_EVT */ {AVCT_LCB_CHNL_OPEN, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
|
||||||
|
/* UL_UNBIND_EVT */ {AVCT_LCB_UNBIND_DISC, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST},
|
||||||
|
/* UL_MSG_EVT */ {AVCT_LCB_DISCARD_MSG, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST},
|
||||||
|
/* INT_CLOSE_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST},
|
||||||
|
/* LL_OPEN_EVT */ {AVCT_LCB_OPEN_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
|
||||||
|
/* LL_CLOSE_EVT */ {AVCT_LCB_CLOSE_IND, AVCT_LCB_DEALLOC, AVCT_LCB_IDLE_ST},
|
||||||
|
/* LL_MSG_EVT */ {AVCT_LCB_FREE_MSG_IND, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST},
|
||||||
|
/* LL_CONG_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for opening state */
|
||||||
|
const UINT8 avct_lcb_st_opening[][AVCT_LCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* UL_BIND_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
|
||||||
|
/* UL_UNBIND_EVT */ {AVCT_LCB_UNBIND_DISC, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
|
||||||
|
/* UL_MSG_EVT */ {AVCT_LCB_DISCARD_MSG, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
|
||||||
|
/* INT_CLOSE_EVT */ {AVCT_LCB_CHNL_DISC, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
|
||||||
|
/* LL_OPEN_EVT */ {AVCT_LCB_OPEN_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
|
||||||
|
/* LL_CLOSE_EVT */ {AVCT_LCB_OPEN_FAIL, AVCT_LCB_DEALLOC, AVCT_LCB_IDLE_ST},
|
||||||
|
/* LL_MSG_EVT */ {AVCT_LCB_FREE_MSG_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
|
||||||
|
/* LL_CONG_EVT */ {AVCT_LCB_CONG_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for open state */
|
||||||
|
const UINT8 avct_lcb_st_open[][AVCT_LCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* UL_BIND_EVT */ {AVCT_LCB_BIND_CONN, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
|
||||||
|
/* UL_UNBIND_EVT */ {AVCT_LCB_CHK_DISC, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
|
||||||
|
/* UL_MSG_EVT */ {AVCT_LCB_SEND_MSG, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
|
||||||
|
/* INT_CLOSE_EVT */ {AVCT_LCB_CHNL_DISC, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
|
||||||
|
/* LL_OPEN_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
|
||||||
|
/* LL_CLOSE_EVT */ {AVCT_LCB_CLOSE_IND, AVCT_LCB_DEALLOC, AVCT_LCB_IDLE_ST},
|
||||||
|
/* LL_MSG_EVT */ {AVCT_LCB_MSG_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
|
||||||
|
/* LL_CONG_EVT */ {AVCT_LCB_CONG_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for closing state */
|
||||||
|
const UINT8 avct_lcb_st_closing[][AVCT_LCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* UL_BIND_EVT */ {AVCT_LCB_BIND_FAIL, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
|
||||||
|
/* UL_UNBIND_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
|
||||||
|
/* UL_MSG_EVT */ {AVCT_LCB_DISCARD_MSG, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
|
||||||
|
/* INT_CLOSE_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
|
||||||
|
/* LL_OPEN_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
|
||||||
|
/* LL_CLOSE_EVT */ {AVCT_LCB_CLOSE_CFM, AVCT_LCB_DEALLOC, AVCT_LCB_IDLE_ST},
|
||||||
|
/* LL_MSG_EVT */ {AVCT_LCB_FREE_MSG_IND, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
|
||||||
|
/* LL_CONG_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* type for state table */
|
||||||
|
typedef const UINT8 (*tAVCT_LCB_ST_TBL)[AVCT_LCB_NUM_COLS];
|
||||||
|
|
||||||
|
/* state table */
|
||||||
|
const tAVCT_LCB_ST_TBL avct_lcb_st_tbl[] = {
|
||||||
|
avct_lcb_st_idle,
|
||||||
|
avct_lcb_st_opening,
|
||||||
|
avct_lcb_st_open,
|
||||||
|
avct_lcb_st_closing
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_event
|
||||||
|
**
|
||||||
|
** Description State machine event handling function for lcb
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_event(tAVCT_LCB *p_lcb, UINT8 event, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVCT_LCB_ST_TBL state_table;
|
||||||
|
UINT8 action;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if BT_TRACE_VERBOSE == TRUE
|
||||||
|
AVCT_TRACE_EVENT("LCB lcb=%d event=%s state=%s", p_lcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_lcb->state]);
|
||||||
|
#else
|
||||||
|
AVCT_TRACE_EVENT("LCB lcb=%d event=%d state=%d", p_lcb->allocated, event, p_lcb->state);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* look up the state table for the current state */
|
||||||
|
state_table = avct_lcb_st_tbl[p_lcb->state];
|
||||||
|
|
||||||
|
/* set next state */
|
||||||
|
p_lcb->state = state_table[event][AVCT_LCB_NEXT_STATE];
|
||||||
|
|
||||||
|
/* execute action functions */
|
||||||
|
for (i = 0; i < AVCT_LCB_ACTIONS; i++)
|
||||||
|
{
|
||||||
|
if ((action = state_table[event][i]) != AVCT_LCB_IGNORE)
|
||||||
|
{
|
||||||
|
(*avct_lcb_action[action])(p_lcb, p_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_bcb_event
|
||||||
|
**
|
||||||
|
** Description State machine event handling function for lcb
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
void avct_bcb_event(tAVCT_BCB *p_bcb, UINT8 event, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVCT_LCB_ST_TBL state_table;
|
||||||
|
UINT8 action;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if BT_TRACE_VERBOSE == TRUE
|
||||||
|
AVCT_TRACE_EVENT("BCB lcb=%d event=%s state=%s", p_bcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_bcb->state]);
|
||||||
|
#else
|
||||||
|
AVCT_TRACE_EVENT("BCB lcb=%d event=%d state=%d", p_bcb->allocated, event, p_bcb->state);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* look up the state table for the current state */
|
||||||
|
state_table = avct_lcb_st_tbl[p_bcb->state];
|
||||||
|
|
||||||
|
/* set next state */
|
||||||
|
p_bcb->state = state_table[event][AVCT_LCB_NEXT_STATE];
|
||||||
|
|
||||||
|
/* execute action functions */
|
||||||
|
for (i = 0; i < AVCT_LCB_ACTIONS; i++)
|
||||||
|
{
|
||||||
|
if ((action = state_table[event][i]) != AVCT_LCB_IGNORE)
|
||||||
|
{
|
||||||
|
(*avct_bcb_action[action])(p_bcb, p_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_by_bd
|
||||||
|
**
|
||||||
|
** Description This lookup function finds the lcb for a BD address.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns pointer to the lcb, or NULL if none found.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVCT_LCB *avct_lcb_by_bd(BD_ADDR bd_addr)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb = &avct_cb.lcb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++)
|
||||||
|
{
|
||||||
|
/* if allocated lcb has matching lcb */
|
||||||
|
if (p_lcb->allocated && (!memcmp(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == AVCT_NUM_LINKS)
|
||||||
|
{
|
||||||
|
/* if no lcb found */
|
||||||
|
p_lcb = NULL;
|
||||||
|
|
||||||
|
AVCT_TRACE_DEBUG("No lcb for addr %02x-%02x-%02x-%02x-%02x-%02x",
|
||||||
|
bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
|
||||||
|
}
|
||||||
|
return p_lcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_alloc
|
||||||
|
**
|
||||||
|
** Description Allocate a link control block.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns pointer to the lcb, or NULL if none could be allocated.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb = &avct_cb.lcb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++)
|
||||||
|
{
|
||||||
|
if (!p_lcb->allocated)
|
||||||
|
{
|
||||||
|
p_lcb->allocated = (UINT8)(i + 1);
|
||||||
|
memcpy(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN);
|
||||||
|
AVCT_TRACE_DEBUG("avct_lcb_alloc %d", p_lcb->allocated);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == AVCT_NUM_LINKS)
|
||||||
|
{
|
||||||
|
/* out of lcbs */
|
||||||
|
p_lcb = NULL;
|
||||||
|
AVCT_TRACE_WARNING("Out of lcbs");
|
||||||
|
}
|
||||||
|
return p_lcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_dealloc
|
||||||
|
**
|
||||||
|
** Description Deallocate a link control block.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_dealloc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
BOOLEAN found = FALSE;
|
||||||
|
int i;
|
||||||
|
UNUSED(p_data);
|
||||||
|
|
||||||
|
AVCT_TRACE_DEBUG("avct_lcb_dealloc %d", p_lcb->allocated);
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
/* if ccb allocated and */
|
||||||
|
if (p_ccb->allocated)
|
||||||
|
{
|
||||||
|
if (p_ccb->p_lcb == p_lcb)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_lcb_dealloc used by ccb: %d", i);
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_DEBUG("avct_lcb_dealloc now");
|
||||||
|
|
||||||
|
/* clear reassembled msg buffer if in use */
|
||||||
|
if (p_lcb->p_rx_msg != NULL)
|
||||||
|
{
|
||||||
|
GKI_freebuf(p_lcb->p_rx_msg);
|
||||||
|
}
|
||||||
|
memset(p_lcb, 0, sizeof(tAVCT_LCB));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_by_lcid
|
||||||
|
**
|
||||||
|
** Description Find the LCB associated with the L2CAP LCID
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns pointer to the lcb, or NULL if none found.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVCT_LCB *avct_lcb_by_lcid(UINT16 lcid)
|
||||||
|
{
|
||||||
|
tAVCT_LCB *p_lcb = &avct_cb.lcb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++)
|
||||||
|
{
|
||||||
|
if (p_lcb->allocated && ((p_lcb->ch_lcid == lcid) || (p_lcb->conflict_lcid == lcid)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == AVCT_NUM_LINKS)
|
||||||
|
{
|
||||||
|
/* out of lcbs */
|
||||||
|
p_lcb = NULL;
|
||||||
|
AVCT_TRACE_WARNING("No lcb for lcid %x", lcid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_lcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_has_pid
|
||||||
|
**
|
||||||
|
** Description See if any ccbs on this lcb have a particular pid.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Pointer to CCB if PID found, NULL otherwise.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVCT_CCB *avct_lcb_has_pid(tAVCT_LCB *p_lcb, UINT16 pid)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb->cc.pid == pid))
|
||||||
|
{
|
||||||
|
return p_ccb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_last_ccb
|
||||||
|
**
|
||||||
|
** Description See if given ccb is only one on the lcb.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns TRUE if ccb is last, FALSE otherwise.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
BOOLEAN avct_lcb_last_ccb(tAVCT_LCB *p_lcb, tAVCT_CCB *p_ccb_last)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
AVCT_TRACE_WARNING("avct_lcb_last_ccb");
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_WARNING("%x: aloc:%d, lcb:0x%x/0x%x, ccb:0x%x/0x%x",
|
||||||
|
i, p_ccb->allocated, p_ccb->p_lcb, p_lcb, p_ccb, p_ccb_last);
|
||||||
|
if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb != p_ccb_last))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
734
components/bt/bluedroid/stack/avct/avct_lcb_act.c
Executable file
734
components/bt/bluedroid/stack/avct/avct_lcb_act.c
Executable file
@ -0,0 +1,734 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This module contains action functions of the link control state machine.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bt_types.h"
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
#include "avct_api.h"
|
||||||
|
#include "avct_int.h"
|
||||||
|
#include "gki.h"
|
||||||
|
#include "btm_api.h"
|
||||||
|
|
||||||
|
/* packet header length lookup table */
|
||||||
|
const UINT8 avct_lcb_pkt_type_len[] = {
|
||||||
|
AVCT_HDR_LEN_SINGLE,
|
||||||
|
AVCT_HDR_LEN_START,
|
||||||
|
AVCT_HDR_LEN_CONT,
|
||||||
|
AVCT_HDR_LEN_END
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_msg_asmbl
|
||||||
|
**
|
||||||
|
** Description Reassemble incoming message.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Pointer to reassembled message; NULL if no message
|
||||||
|
** available.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf)
|
||||||
|
{
|
||||||
|
UINT8 *p;
|
||||||
|
UINT8 pkt_type;
|
||||||
|
BT_HDR *p_ret;
|
||||||
|
UINT16 buf_len;
|
||||||
|
|
||||||
|
/* parse the message header */
|
||||||
|
p = (UINT8 *)(p_buf + 1) + p_buf->offset;
|
||||||
|
AVCT_PRS_PKT_TYPE(p, pkt_type);
|
||||||
|
|
||||||
|
/* quick sanity check on length */
|
||||||
|
if (p_buf->len < avct_lcb_pkt_type_len[pkt_type])
|
||||||
|
{
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
AVCT_TRACE_WARNING("Bad length during reassembly");
|
||||||
|
p_ret = NULL;
|
||||||
|
}
|
||||||
|
/* single packet */
|
||||||
|
else if (pkt_type == AVCT_PKT_TYPE_SINGLE)
|
||||||
|
{
|
||||||
|
/* if reassembly in progress drop message and process new single */
|
||||||
|
if (p_lcb->p_rx_msg != NULL)
|
||||||
|
{
|
||||||
|
GKI_freebuf(p_lcb->p_rx_msg);
|
||||||
|
p_lcb->p_rx_msg = NULL;
|
||||||
|
AVCT_TRACE_WARNING("Got single during reassembly");
|
||||||
|
}
|
||||||
|
p_ret = p_buf;
|
||||||
|
}
|
||||||
|
/* start packet */
|
||||||
|
else if (pkt_type == AVCT_PKT_TYPE_START)
|
||||||
|
{
|
||||||
|
/* if reassembly in progress drop message and process new start */
|
||||||
|
if (p_lcb->p_rx_msg != NULL)
|
||||||
|
{
|
||||||
|
GKI_freebuf(p_lcb->p_rx_msg);
|
||||||
|
AVCT_TRACE_WARNING("Got start during reassembly");
|
||||||
|
}
|
||||||
|
/* Allocate bigger buffer for reassembly. As lower layers are
|
||||||
|
* not aware of possible packet size after reassembly they
|
||||||
|
* would have allocated smaller buffer.
|
||||||
|
*/
|
||||||
|
p_lcb->p_rx_msg = (BT_HDR*)GKI_getbuf(GKI_MAX_BUF_SIZE);
|
||||||
|
if (p_lcb->p_rx_msg == NULL)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_ERROR ("Cannot alloc buffer for reassembly !!");
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy (p_lcb->p_rx_msg, p_buf,
|
||||||
|
sizeof(BT_HDR) + p_buf->offset + p_buf->len);
|
||||||
|
/* Free original buffer */
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
|
||||||
|
/* update p to point to new buffer */
|
||||||
|
p = (UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset;
|
||||||
|
|
||||||
|
/* copy first header byte over nosp */
|
||||||
|
*(p + 1) = *p;
|
||||||
|
|
||||||
|
/* set offset to point to where to copy next */
|
||||||
|
p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len;
|
||||||
|
|
||||||
|
/* adjust length for packet header */
|
||||||
|
p_lcb->p_rx_msg->len -= 1;
|
||||||
|
}
|
||||||
|
p_ret = NULL;
|
||||||
|
}
|
||||||
|
/* continue or end */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* if no reassembly in progress drop message */
|
||||||
|
if (p_lcb->p_rx_msg == NULL)
|
||||||
|
{
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
AVCT_TRACE_WARNING("Pkt type=%d out of order", pkt_type);
|
||||||
|
p_ret = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* get size of buffer holding assembled message */
|
||||||
|
buf_len = GKI_get_buf_size(p_lcb->p_rx_msg) - sizeof(BT_HDR);
|
||||||
|
|
||||||
|
/* adjust offset and len of fragment for header byte */
|
||||||
|
p_buf->offset += AVCT_HDR_LEN_CONT;
|
||||||
|
p_buf->len -= AVCT_HDR_LEN_CONT;
|
||||||
|
|
||||||
|
/* verify length */
|
||||||
|
if ((p_lcb->p_rx_msg->offset + p_buf->len) > buf_len)
|
||||||
|
{
|
||||||
|
/* won't fit; free everything */
|
||||||
|
GKI_freebuf(p_lcb->p_rx_msg);
|
||||||
|
p_lcb->p_rx_msg = NULL;
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
p_ret = NULL;
|
||||||
|
AVCT_TRACE_WARNING("Fragmented message to big!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* copy contents of p_buf to p_rx_msg */
|
||||||
|
memcpy((UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset,
|
||||||
|
(UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len);
|
||||||
|
|
||||||
|
if (pkt_type == AVCT_PKT_TYPE_END)
|
||||||
|
{
|
||||||
|
p_lcb->p_rx_msg->offset -= p_lcb->p_rx_msg->len;
|
||||||
|
p_lcb->p_rx_msg->len += p_buf->len;
|
||||||
|
p_ret = p_lcb->p_rx_msg;
|
||||||
|
p_lcb->p_rx_msg = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_lcb->p_rx_msg->offset += p_buf->len;
|
||||||
|
p_lcb->p_rx_msg->len += p_buf->len;
|
||||||
|
p_ret = NULL;
|
||||||
|
}
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_chnl_open
|
||||||
|
**
|
||||||
|
** Description Open L2CAP channel to peer
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_chnl_open(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
UINT16 result = AVCT_RESULT_FAIL;
|
||||||
|
UNUSED(p_data);
|
||||||
|
|
||||||
|
BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP, 0);
|
||||||
|
/* call l2cap connect req */
|
||||||
|
p_lcb->ch_state = AVCT_CH_CONN;
|
||||||
|
if ((p_lcb->ch_lcid = L2CA_ConnectReq(AVCT_PSM, p_lcb->peer_addr)) == 0)
|
||||||
|
{
|
||||||
|
/* if connect req failed, send ourselves close event */
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_unbind_disc
|
||||||
|
**
|
||||||
|
** Description Deallocate ccb and call callback with disconnect event.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_unbind_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
UNUSED(p_lcb);
|
||||||
|
|
||||||
|
avct_ccb_dealloc(p_data->p_ccb, AVCT_DISCONNECT_CFM_EVT, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_open_ind
|
||||||
|
**
|
||||||
|
** Description Handle an LL_OPEN event. For each allocated ccb already
|
||||||
|
** bound to this lcb, send a connect event. For each
|
||||||
|
** unbound ccb with a new PID, bind that ccb to this lcb and
|
||||||
|
** send a connect event.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_open_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
BOOLEAN bind = FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
/* if ccb allocated and */
|
||||||
|
if (p_ccb->allocated)
|
||||||
|
{
|
||||||
|
/* if bound to this lcb send connect confirm event */
|
||||||
|
if (p_ccb->p_lcb == p_lcb)
|
||||||
|
{
|
||||||
|
bind = TRUE;
|
||||||
|
L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
|
||||||
|
p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT,
|
||||||
|
0, p_lcb->peer_addr);
|
||||||
|
}
|
||||||
|
/* if unbound acceptor and lcb doesn't already have a ccb for this PID */
|
||||||
|
else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
|
||||||
|
(avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL))
|
||||||
|
{
|
||||||
|
/* bind ccb to lcb and send connect ind event */
|
||||||
|
bind = TRUE;
|
||||||
|
p_ccb->p_lcb = p_lcb;
|
||||||
|
L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
|
||||||
|
p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT,
|
||||||
|
0, p_lcb->peer_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if no ccbs bound to this lcb, disconnect */
|
||||||
|
if (bind == FALSE)
|
||||||
|
{
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_open_fail
|
||||||
|
**
|
||||||
|
** Description L2CAP channel open attempt failed. Deallocate any ccbs
|
||||||
|
** on this lcb and send connect confirm event with failure.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_open_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
|
||||||
|
{
|
||||||
|
avct_ccb_dealloc(p_ccb, AVCT_CONNECT_CFM_EVT,
|
||||||
|
p_data->result, p_lcb->peer_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_close_ind
|
||||||
|
**
|
||||||
|
** Description L2CAP channel closed by peer. Deallocate any initiator
|
||||||
|
** ccbs on this lcb and send disconnect ind event.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_close_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
UNUSED(p_data);
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
|
||||||
|
{
|
||||||
|
if (p_ccb->cc.role == AVCT_INT)
|
||||||
|
{
|
||||||
|
avct_ccb_dealloc(p_ccb, AVCT_DISCONNECT_IND_EVT,
|
||||||
|
0, p_lcb->peer_addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_ccb->p_lcb = NULL;
|
||||||
|
(*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), AVCT_DISCONNECT_IND_EVT,
|
||||||
|
0, p_lcb->peer_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_close_cfm
|
||||||
|
**
|
||||||
|
** Description L2CAP channel closed by us. Deallocate any initiator
|
||||||
|
** ccbs on this lcb and send disconnect ind or cfm event.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_close_cfm(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
UINT8 event;
|
||||||
|
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
|
||||||
|
{
|
||||||
|
/* if this ccb initiated close send disconnect cfm otherwise ind */
|
||||||
|
if (p_ccb->ch_close)
|
||||||
|
{
|
||||||
|
p_ccb->ch_close = FALSE;
|
||||||
|
event = AVCT_DISCONNECT_CFM_EVT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event = AVCT_DISCONNECT_IND_EVT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_ccb->cc.role == AVCT_INT)
|
||||||
|
{
|
||||||
|
avct_ccb_dealloc(p_ccb, event, p_data->result, p_lcb->peer_addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_ccb->p_lcb = NULL;
|
||||||
|
(*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event,
|
||||||
|
p_data->result, p_lcb->peer_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_bind_conn
|
||||||
|
**
|
||||||
|
** Description Bind ccb to lcb and send connect cfm event.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_bind_conn(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
p_data->p_ccb->p_lcb = p_lcb;
|
||||||
|
(*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
|
||||||
|
AVCT_CONNECT_CFM_EVT, 0, p_lcb->peer_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_chk_disc
|
||||||
|
**
|
||||||
|
** Description A ccb wants to close; if it is the last ccb on this lcb,
|
||||||
|
** close channel. Otherwise just deallocate and call
|
||||||
|
** callback.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_chk_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_WARNING("avct_lcb_chk_disc");
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
avct_close_bcb(p_lcb, p_data);
|
||||||
|
#endif
|
||||||
|
if (avct_lcb_last_ccb(p_lcb, p_data->p_ccb))
|
||||||
|
{
|
||||||
|
AVCT_TRACE_WARNING("closing");
|
||||||
|
p_data->p_ccb->ch_close = TRUE;
|
||||||
|
avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AVCT_TRACE_WARNING("dealloc ccb");
|
||||||
|
avct_lcb_unbind_disc(p_lcb, p_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_chnl_disc
|
||||||
|
**
|
||||||
|
** Description Disconnect L2CAP channel.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_chnl_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
UNUSED(p_data);
|
||||||
|
|
||||||
|
L2CA_DisconnectReq(p_lcb->ch_lcid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_bind_fail
|
||||||
|
**
|
||||||
|
** Description Deallocate ccb and call callback with connect event
|
||||||
|
** with failure result.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_bind_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
UNUSED(p_lcb);
|
||||||
|
|
||||||
|
avct_ccb_dealloc(p_data->p_ccb, AVCT_CONNECT_CFM_EVT, AVCT_RESULT_FAIL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_cong_ind
|
||||||
|
**
|
||||||
|
** Description Handle congestion indication from L2CAP.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_cong_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
UINT8 event;
|
||||||
|
BT_HDR *p_buf;
|
||||||
|
|
||||||
|
/* set event */
|
||||||
|
event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT;
|
||||||
|
p_lcb->cong = p_data->cong;
|
||||||
|
if (p_lcb->cong == FALSE && GKI_getfirst(&p_lcb->tx_q))
|
||||||
|
{
|
||||||
|
while ( !p_lcb->cong && (p_buf = (BT_HDR *)GKI_dequeue(&p_lcb->tx_q)) != NULL)
|
||||||
|
{
|
||||||
|
if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
|
||||||
|
{
|
||||||
|
p_lcb->cong = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send event to all ccbs on this lcb */
|
||||||
|
for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
|
||||||
|
{
|
||||||
|
(*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0, p_lcb->peer_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_discard_msg
|
||||||
|
**
|
||||||
|
** Description Discard a message sent in from the API.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_discard_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
UNUSED(p_lcb);
|
||||||
|
|
||||||
|
AVCT_TRACE_WARNING("Dropping msg");
|
||||||
|
|
||||||
|
GKI_freebuf(p_data->ul_msg.p_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_send_msg
|
||||||
|
**
|
||||||
|
** Description Build and send an AVCTP message.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
UINT16 curr_msg_len;
|
||||||
|
UINT8 pkt_type;
|
||||||
|
UINT8 hdr_len;
|
||||||
|
BT_HDR *p_buf;
|
||||||
|
UINT8 *p;
|
||||||
|
UINT8 nosp = 0; /* number of subsequent packets */
|
||||||
|
UINT16 temp;
|
||||||
|
UINT16 buf_size = p_lcb->peer_mtu + L2CAP_MIN_OFFSET + BT_HDR_SIZE;
|
||||||
|
|
||||||
|
|
||||||
|
/* store msg len */
|
||||||
|
curr_msg_len = p_data->ul_msg.p_buf->len;
|
||||||
|
|
||||||
|
/* initialize packet type and other stuff */
|
||||||
|
if (curr_msg_len <= (p_lcb->peer_mtu - AVCT_HDR_LEN_SINGLE))
|
||||||
|
{
|
||||||
|
pkt_type = AVCT_PKT_TYPE_SINGLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pkt_type = AVCT_PKT_TYPE_START;
|
||||||
|
temp = (curr_msg_len + AVCT_HDR_LEN_START - p_lcb->peer_mtu);
|
||||||
|
nosp = temp / (p_lcb->peer_mtu - 1) + 1;
|
||||||
|
if ( (temp % (p_lcb->peer_mtu - 1)) != 0)
|
||||||
|
nosp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* while we haven't sent all packets */
|
||||||
|
while (curr_msg_len != 0)
|
||||||
|
{
|
||||||
|
/* set header len */
|
||||||
|
hdr_len = avct_lcb_pkt_type_len[pkt_type];
|
||||||
|
|
||||||
|
/* if remaining msg must be fragmented */
|
||||||
|
if (p_data->ul_msg.p_buf->len > (p_lcb->peer_mtu - hdr_len))
|
||||||
|
{
|
||||||
|
/* get a new buffer for fragment we are sending */
|
||||||
|
if ((p_buf = (BT_HDR *) GKI_getbuf(buf_size)) == NULL)
|
||||||
|
{
|
||||||
|
/* whoops; free original msg buf and bail */
|
||||||
|
AVCT_TRACE_ERROR ("avct_lcb_send_msg cannot alloc buffer!!");
|
||||||
|
GKI_freebuf(p_data->ul_msg.p_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy portion of data from current message to new buffer */
|
||||||
|
p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
|
||||||
|
p_buf->len = p_lcb->peer_mtu - hdr_len;
|
||||||
|
|
||||||
|
memcpy((UINT8 *)(p_buf + 1) + p_buf->offset,
|
||||||
|
(UINT8 *)(p_data->ul_msg.p_buf + 1) + p_data->ul_msg.p_buf->offset, p_buf->len);
|
||||||
|
|
||||||
|
p_data->ul_msg.p_buf->offset += p_buf->len;
|
||||||
|
p_data->ul_msg.p_buf->len -= p_buf->len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_buf = p_data->ul_msg.p_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
curr_msg_len -= p_buf->len;
|
||||||
|
|
||||||
|
/* set up to build header */
|
||||||
|
p_buf->len += hdr_len;
|
||||||
|
p_buf->offset -= hdr_len;
|
||||||
|
p = (UINT8 *)(p_buf + 1) + p_buf->offset;
|
||||||
|
|
||||||
|
/* build header */
|
||||||
|
AVCT_BLD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
|
||||||
|
if (pkt_type == AVCT_PKT_TYPE_START)
|
||||||
|
{
|
||||||
|
UINT8_TO_STREAM(p, nosp);
|
||||||
|
}
|
||||||
|
if ((pkt_type == AVCT_PKT_TYPE_START) || (pkt_type == AVCT_PKT_TYPE_SINGLE))
|
||||||
|
{
|
||||||
|
UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_lcb->cong == TRUE)
|
||||||
|
{
|
||||||
|
GKI_enqueue (&p_lcb->tx_q, p_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send message to L2CAP */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
|
||||||
|
{
|
||||||
|
p_lcb->cong = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update pkt type for next packet */
|
||||||
|
if (curr_msg_len > (p_lcb->peer_mtu - AVCT_HDR_LEN_END))
|
||||||
|
{
|
||||||
|
pkt_type = AVCT_PKT_TYPE_CONT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pkt_type = AVCT_PKT_TYPE_END;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AVCT_TRACE_DEBUG ("avct_lcb_send_msg tx_q_count:%d", GKI_queue_length(&p_lcb->tx_q));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_free_msg_ind
|
||||||
|
**
|
||||||
|
** Description Discard an incoming AVCTP message.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_free_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
UNUSED(p_lcb);
|
||||||
|
|
||||||
|
if (p_data)
|
||||||
|
GKI_freebuf(p_data->p_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avct_lcb_msg_ind
|
||||||
|
**
|
||||||
|
** Description Handle an incoming AVCTP message.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avct_lcb_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
UINT8 *p;
|
||||||
|
UINT8 label, type, cr_ipid;
|
||||||
|
UINT16 pid;
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
BT_HDR *p_buf;
|
||||||
|
|
||||||
|
/* this p_buf is to be reported through p_msg_cback. The layer_specific
|
||||||
|
* needs to be set properly to indicate that it is received through
|
||||||
|
* control channel */
|
||||||
|
p_data->p_buf->layer_specific = AVCT_DATA_CTRL;
|
||||||
|
|
||||||
|
/* reassemble message; if no message available (we received a fragment) return */
|
||||||
|
if ((p_data->p_buf = avct_lcb_msg_asmbl(p_lcb, p_data->p_buf)) == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = (UINT8 *)(p_data->p_buf + 1) + p_data->p_buf->offset;
|
||||||
|
|
||||||
|
/* parse header byte */
|
||||||
|
AVCT_PRS_HDR(p, label, type, cr_ipid);
|
||||||
|
UNUSED(type);
|
||||||
|
|
||||||
|
/* check for invalid cr_ipid */
|
||||||
|
if (cr_ipid == AVCT_CR_IPID_INVALID)
|
||||||
|
{
|
||||||
|
AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid);
|
||||||
|
GKI_freebuf(p_data->p_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse and lookup PID */
|
||||||
|
BE_STREAM_TO_UINT16(pid, p);
|
||||||
|
if ((p_ccb = avct_lcb_has_pid(p_lcb, pid)) != NULL)
|
||||||
|
{
|
||||||
|
/* PID found; send msg up, adjust bt hdr and call msg callback */
|
||||||
|
p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
|
||||||
|
p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
|
||||||
|
(*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid, p_data->p_buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* PID not found; drop message */
|
||||||
|
AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
|
||||||
|
GKI_freebuf(p_data->p_buf);
|
||||||
|
|
||||||
|
/* if command send reject */
|
||||||
|
if (cr_ipid == AVCT_CMD)
|
||||||
|
{
|
||||||
|
if ((p_buf = (BT_HDR *) GKI_getpoolbuf(AVCT_CMD_POOL_ID)) != NULL)
|
||||||
|
{
|
||||||
|
p_buf->len = AVCT_HDR_LEN_SINGLE;
|
||||||
|
p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
|
||||||
|
p = (UINT8 *)(p_buf + 1) + p_buf->offset;
|
||||||
|
AVCT_BLD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
|
||||||
|
UINT16_TO_BE_STREAM(p, pid);
|
||||||
|
L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
components/bt/bluedroid/stack/avct/include/avct_defs.h
Executable file
62
components/bt/bluedroid/stack/avct/include/avct_defs.h
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This contains constants definitions and other information from the AVCTP
|
||||||
|
* specification. This file is intended for use internal to AVCT only.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef AVCT_DEFS_H
|
||||||
|
#define AVCT_DEFS_H
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** constants
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* packet type */
|
||||||
|
#define AVCT_PKT_TYPE_SINGLE 0 /* single packet */
|
||||||
|
#define AVCT_PKT_TYPE_START 1 /* start packet */
|
||||||
|
#define AVCT_PKT_TYPE_CONT 2 /* continue packet */
|
||||||
|
#define AVCT_PKT_TYPE_END 3 /* end packet */
|
||||||
|
|
||||||
|
/* header lengths for different packet types */
|
||||||
|
#define AVCT_HDR_LEN_SINGLE 3
|
||||||
|
#define AVCT_HDR_LEN_START 4
|
||||||
|
#define AVCT_HDR_LEN_CONT 1
|
||||||
|
#define AVCT_HDR_LEN_END 1
|
||||||
|
|
||||||
|
/* invalid cr+ipid value */
|
||||||
|
#define AVCT_CR_IPID_INVALID 1
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** message parsing and building macros
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#define AVCT_BLD_HDR(p, label, type, cr_ipid) \
|
||||||
|
*(p)++ = ((label) << 4) | ((type) << 2) | (cr_ipid);
|
||||||
|
|
||||||
|
#define AVCT_PRS_HDR(p, label, type, cr_ipid) \
|
||||||
|
label = *(p) >> 4; \
|
||||||
|
type = (*(p) >> 2) & 3; \
|
||||||
|
cr_ipid = *(p)++ & 3;
|
||||||
|
|
||||||
|
#define AVCT_PRS_PKT_TYPE(p, type) \
|
||||||
|
type = (*(p) >> 2) & 3;
|
||||||
|
|
||||||
|
#endif /* AVCT_DEFS_H */
|
237
components/bt/bluedroid/stack/avct/include/avct_int.h
Executable file
237
components/bt/bluedroid/stack/avct/include/avct_int.h
Executable file
@ -0,0 +1,237 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This file contains interfaces which are internal to AVCTP.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef AVCT_INT_H
|
||||||
|
#define AVCT_INT_H
|
||||||
|
|
||||||
|
#include "gki.h"
|
||||||
|
#include "avct_api.h"
|
||||||
|
#include "avct_defs.h"
|
||||||
|
#include "l2c_api.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** constants
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* lcb state machine events */
|
||||||
|
enum {
|
||||||
|
AVCT_LCB_UL_BIND_EVT,
|
||||||
|
AVCT_LCB_UL_UNBIND_EVT,
|
||||||
|
AVCT_LCB_UL_MSG_EVT,
|
||||||
|
AVCT_LCB_INT_CLOSE_EVT,
|
||||||
|
AVCT_LCB_LL_OPEN_EVT,
|
||||||
|
AVCT_LCB_LL_CLOSE_EVT,
|
||||||
|
AVCT_LCB_LL_MSG_EVT,
|
||||||
|
AVCT_LCB_LL_CONG_EVT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* "states" used for L2CAP channel */
|
||||||
|
#define AVCT_CH_IDLE 0 /* No connection */
|
||||||
|
#define AVCT_CH_CONN 1 /* Waiting for connection confirm */
|
||||||
|
#define AVCT_CH_CFG 2 /* Waiting for configuration complete */
|
||||||
|
#define AVCT_CH_OPEN 3 /* Channel opened */
|
||||||
|
|
||||||
|
/* "no event" indicator used by ccb dealloc */
|
||||||
|
#define AVCT_NO_EVT 0xFF
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** data types
|
||||||
|
*****************************************************************************/
|
||||||
|
/* sub control block type - common data members for tAVCT_LCB and tAVCT_BCB */
|
||||||
|
typedef struct {
|
||||||
|
UINT16 peer_mtu; /* peer l2c mtu */
|
||||||
|
UINT16 ch_result; /* L2CAP connection result value */
|
||||||
|
UINT16 ch_lcid; /* L2CAP channel LCID */
|
||||||
|
UINT8 allocated; /* 0, not allocated. index+1, otherwise. */
|
||||||
|
UINT8 state; /* The state machine state */
|
||||||
|
UINT8 ch_state; /* L2CAP channel state */
|
||||||
|
UINT8 ch_flags; /* L2CAP configuration flags */
|
||||||
|
} tAVCT_SCB;
|
||||||
|
|
||||||
|
/* link control block type */
|
||||||
|
typedef struct {
|
||||||
|
UINT16 peer_mtu; /* peer l2c mtu */
|
||||||
|
UINT16 ch_result; /* L2CAP connection result value */
|
||||||
|
UINT16 ch_lcid; /* L2CAP channel LCID */
|
||||||
|
UINT8 allocated; /* 0, not allocated. index+1, otherwise. */
|
||||||
|
UINT8 state; /* The state machine state */
|
||||||
|
UINT8 ch_state; /* L2CAP channel state */
|
||||||
|
UINT8 ch_flags; /* L2CAP configuration flags */
|
||||||
|
BT_HDR *p_rx_msg; /* Message being reassembled */
|
||||||
|
UINT16 conflict_lcid; /* L2CAP channel LCID */
|
||||||
|
BD_ADDR peer_addr; /* BD address of peer */
|
||||||
|
BUFFER_Q tx_q; /* Transmit data buffer queue */
|
||||||
|
BOOLEAN cong; /* TRUE, if congested */
|
||||||
|
} tAVCT_LCB;
|
||||||
|
|
||||||
|
/* browse control block type */
|
||||||
|
typedef struct {
|
||||||
|
UINT16 peer_mtu; /* peer l2c mtu */
|
||||||
|
UINT16 ch_result; /* L2CAP connection result value */
|
||||||
|
UINT16 ch_lcid; /* L2CAP channel LCID */
|
||||||
|
UINT8 allocated; /* 0, not allocated. index+1, otherwise. */
|
||||||
|
UINT8 state; /* The state machine state */
|
||||||
|
UINT8 ch_state; /* L2CAP channel state */
|
||||||
|
UINT8 ch_flags; /* L2CAP configuration flags */
|
||||||
|
BT_HDR *p_tx_msg; /* Message to be sent - in case the browsing channel is not open when MsgReg is called */
|
||||||
|
UINT8 ch_close; /* CCB index+1, if CCB initiated channel close */
|
||||||
|
} tAVCT_BCB;
|
||||||
|
|
||||||
|
#define AVCT_ALOC_LCB 0x01
|
||||||
|
#define AVCT_ALOC_BCB 0x02
|
||||||
|
/* connection control block */
|
||||||
|
typedef struct {
|
||||||
|
tAVCT_CC cc; /* parameters from connection creation */
|
||||||
|
tAVCT_LCB *p_lcb; /* Associated LCB */
|
||||||
|
tAVCT_BCB *p_bcb; /* associated BCB */
|
||||||
|
BOOLEAN ch_close; /* Whether CCB initiated channel close */
|
||||||
|
UINT8 allocated; /* Whether LCB/BCB is allocated */
|
||||||
|
} tAVCT_CCB;
|
||||||
|
|
||||||
|
/* data type associated with UL_MSG_EVT */
|
||||||
|
typedef struct {
|
||||||
|
BT_HDR *p_buf;
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
UINT8 label;
|
||||||
|
UINT8 cr;
|
||||||
|
} tAVCT_UL_MSG;
|
||||||
|
|
||||||
|
/* union associated with lcb state machine events */
|
||||||
|
typedef union {
|
||||||
|
tAVCT_UL_MSG ul_msg;
|
||||||
|
BT_HDR *p_buf;
|
||||||
|
tAVCT_CCB *p_ccb;
|
||||||
|
UINT16 result;
|
||||||
|
BOOLEAN cong;
|
||||||
|
UINT8 err_code;
|
||||||
|
} tAVCT_LCB_EVT;
|
||||||
|
|
||||||
|
/* Control block for AVCT */
|
||||||
|
typedef struct {
|
||||||
|
tAVCT_LCB lcb[AVCT_NUM_LINKS]; /* link control blocks */
|
||||||
|
tAVCT_BCB bcb[AVCT_NUM_LINKS]; /* browse control blocks */
|
||||||
|
tAVCT_CCB ccb[AVCT_NUM_CONN]; /* connection control blocks */
|
||||||
|
UINT16 mtu; /* our L2CAP MTU */
|
||||||
|
UINT16 mtu_br; /* our L2CAP MTU for the Browsing channel */
|
||||||
|
UINT8 trace_level; /* trace level */
|
||||||
|
} tAVCT_CB;
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** function declarations
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* LCB function declarations */
|
||||||
|
extern void avct_lcb_event(tAVCT_LCB *p_lcb, UINT8 event, tAVCT_LCB_EVT *p_data);
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
extern void avct_bcb_event(tAVCT_BCB *p_bcb, UINT8 event, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_close_bcb(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern tAVCT_LCB *avct_lcb_by_bcb(tAVCT_BCB *p_bcb);
|
||||||
|
extern tAVCT_BCB *avct_bcb_by_lcb(tAVCT_LCB *p_lcb);
|
||||||
|
extern BOOLEAN avct_bcb_last_ccb(tAVCT_BCB *p_bcb, tAVCT_CCB *p_ccb_last);
|
||||||
|
extern tAVCT_BCB *avct_bcb_by_lcid(UINT16 lcid);
|
||||||
|
#endif
|
||||||
|
extern tAVCT_LCB *avct_lcb_by_bd(BD_ADDR bd_addr);
|
||||||
|
extern tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr);
|
||||||
|
extern void avct_lcb_dealloc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern tAVCT_LCB *avct_lcb_by_lcid(UINT16 lcid);
|
||||||
|
extern tAVCT_CCB *avct_lcb_has_pid(tAVCT_LCB *p_lcb, UINT16 pid);
|
||||||
|
extern BOOLEAN avct_lcb_last_ccb(tAVCT_LCB *p_lcb, tAVCT_CCB *p_ccb_last);
|
||||||
|
|
||||||
|
/* LCB action functions */
|
||||||
|
extern void avct_lcb_chnl_open(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_unbind_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_open_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_open_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_close_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_close_cfm(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_bind_conn(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_chk_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_chnl_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_bind_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_cong_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_discard_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_lcb_free_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
|
||||||
|
/* BCB action functions */
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
typedef void (*tAVCT_BCB_ACTION)(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_chnl_open(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_unbind_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_open_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_open_fail(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_close_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_close_cfm(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_bind_conn(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_chk_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_chnl_disc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_bind_fail(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_cong_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_discard_msg(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_send_msg(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
extern void avct_bcb_free_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
|
||||||
|
extern void avct_bcb_dealloc(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data);
|
||||||
|
|
||||||
|
extern const tAVCT_BCB_ACTION avct_bcb_action[];
|
||||||
|
extern const UINT8 avct_lcb_pkt_type_len[];
|
||||||
|
extern const tL2CAP_FCR_OPTS avct_l2c_br_fcr_opts_def;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CCB function declarations */
|
||||||
|
extern tAVCT_CCB *avct_ccb_alloc(tAVCT_CC *p_cc);
|
||||||
|
extern void avct_ccb_dealloc(tAVCT_CCB *p_ccb, UINT8 event, UINT16 result, BD_ADDR bd_addr);
|
||||||
|
extern UINT8 avct_ccb_to_idx(tAVCT_CCB *p_ccb);
|
||||||
|
extern tAVCT_CCB *avct_ccb_by_idx(UINT8 idx);
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** global data
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Main control block */
|
||||||
|
#if AVCT_DYNAMIC_MEMORY == FALSE
|
||||||
|
extern tAVCT_CB avct_cb;
|
||||||
|
#else
|
||||||
|
extern tAVCT_CB *avct_cb_ptr;
|
||||||
|
#define avct_cb (*avct_cb_ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* L2CAP callback registration structure */
|
||||||
|
extern const tL2CAP_APPL_INFO avct_l2c_appl;
|
||||||
|
#if (AVCT_BROWSE_INCLUDED == TRUE)
|
||||||
|
extern const tL2CAP_APPL_INFO avct_l2c_br_appl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AVCT_INT_H */
|
641
components/bt/bluedroid/stack/avdt/avdt_ad.c
Executable file
641
components/bt/bluedroid/stack/avdt/avdt_ad.c
Executable file
@ -0,0 +1,641 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This module contains the AVDTP adaption layer.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
// #include <assert.h>
|
||||||
|
#include "bt_trace.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bt_types.h"
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
#include "avdt_api.h"
|
||||||
|
#include "avdtc_api.h"
|
||||||
|
#include "avdt_int.h"
|
||||||
|
#include "l2c_api.h"
|
||||||
|
#include "l2cdefs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_type_to_tcid
|
||||||
|
**
|
||||||
|
** Description Derives the TCID from the channel type and SCB.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns TCID value.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT8 avdt_ad_type_to_tcid(UINT8 type, tAVDT_SCB *p_scb)
|
||||||
|
{
|
||||||
|
UINT8 scb_idx;
|
||||||
|
|
||||||
|
if (type == AVDT_CHAN_SIG)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scb_idx = avdt_scb_to_hdl(p_scb) - 1;
|
||||||
|
/*
|
||||||
|
AVDT_TRACE_DEBUG("type: %d, tcid: %d", type, ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type));
|
||||||
|
*/
|
||||||
|
return ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tcid_to_type
|
||||||
|
**
|
||||||
|
** Description Derives the channel type from the TCID.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Channel type value.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
static UINT8 avdt_ad_tcid_to_type(UINT8 tcid)
|
||||||
|
{
|
||||||
|
UINT8 type;
|
||||||
|
|
||||||
|
if (tcid == 0)
|
||||||
|
{
|
||||||
|
type = AVDT_CHAN_SIG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* tcid translates to type based on number of channels, as follows:
|
||||||
|
** only media channel : tcid=1,2,3,4,5,6... type=1,1,1,1,1,1...
|
||||||
|
** media and report : tcid=1,2,3,4,5,6... type=1,2,1,2,1,2...
|
||||||
|
** media, report, recov : tcid=1,2,3,4,5,6... type=1,2,3,1,2,3...
|
||||||
|
*/
|
||||||
|
type = ((tcid + AVDT_CHAN_NUM_TYPES - 2) % (AVDT_CHAN_NUM_TYPES - 1)) + 1;
|
||||||
|
}
|
||||||
|
AVDT_TRACE_DEBUG("tcid: %d, type: %d", tcid, type);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_init
|
||||||
|
**
|
||||||
|
** Description Initialize adaption layer.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ad_init(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
|
||||||
|
memset(&avdt_cb.ad, 0, sizeof(tAVDT_AD));
|
||||||
|
|
||||||
|
/* make sure the peer_mtu is a valid value */
|
||||||
|
for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
|
||||||
|
{
|
||||||
|
p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tc_tbl_by_st
|
||||||
|
**
|
||||||
|
** Description Find adaption layer transport channel table entry matching
|
||||||
|
** the given state.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Pointer to matching entry. For control channel it returns
|
||||||
|
** the matching entry. For media or other it returns the
|
||||||
|
** first matching entry (there could be more than one).
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVDT_TC_TBL *avdt_ad_tc_tbl_by_st(UINT8 type, tAVDT_CCB *p_ccb, UINT8 state)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
|
||||||
|
UINT8 ccb_idx;
|
||||||
|
|
||||||
|
if (p_ccb == NULL)
|
||||||
|
{
|
||||||
|
/* resending security req */
|
||||||
|
for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
|
||||||
|
{
|
||||||
|
/* must be AVDT_CHAN_SIG - tcid always zero */
|
||||||
|
if ((p_tbl->tcid == 0) &&
|
||||||
|
(p_tbl->state == state))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ccb_idx = avdt_ccb_to_idx(p_ccb);
|
||||||
|
|
||||||
|
for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
|
||||||
|
{
|
||||||
|
if (type == AVDT_CHAN_SIG)
|
||||||
|
{
|
||||||
|
/* if control channel, tcid always zero */
|
||||||
|
if ((p_tbl->tcid == 0) &&
|
||||||
|
(p_tbl->ccb_idx == ccb_idx) &&
|
||||||
|
(p_tbl->state == state))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* if other channel, tcid is always > zero */
|
||||||
|
if ((p_tbl->tcid > 0) &&
|
||||||
|
(p_tbl->ccb_idx == ccb_idx) &&
|
||||||
|
(p_tbl->state == state))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if nothing found return null */
|
||||||
|
if (i == AVDT_NUM_TC_TBL)
|
||||||
|
{
|
||||||
|
p_tbl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_tbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tc_tbl_by_lcid
|
||||||
|
**
|
||||||
|
** Description Find adaption layer transport channel table entry by LCID.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Pointer to entry.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid)
|
||||||
|
{
|
||||||
|
UINT8 idx;
|
||||||
|
|
||||||
|
idx = avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
|
||||||
|
|
||||||
|
if (idx < AVDT_NUM_TC_TBL)
|
||||||
|
{
|
||||||
|
return &avdt_cb.ad.tc_tbl[idx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tc_tbl_by_type
|
||||||
|
**
|
||||||
|
** Description This function retrieves the transport channel table entry
|
||||||
|
** for a particular channel.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Pointer to transport channel table entry.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVDT_TC_TBL *avdt_ad_tc_tbl_by_type(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
|
||||||
|
{
|
||||||
|
UINT8 tcid;
|
||||||
|
int i;
|
||||||
|
tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
|
||||||
|
UINT8 ccb_idx = avdt_ccb_to_idx(p_ccb);
|
||||||
|
|
||||||
|
/* get tcid from type, scb */
|
||||||
|
tcid = avdt_ad_type_to_tcid(type, p_scb);
|
||||||
|
|
||||||
|
for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
|
||||||
|
{
|
||||||
|
if ((p_tbl->tcid == tcid) && (p_tbl->ccb_idx == ccb_idx))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(i != AVDT_NUM_TC_TBL);
|
||||||
|
|
||||||
|
return p_tbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tc_tbl_alloc
|
||||||
|
**
|
||||||
|
** Description Allocate an entry in the traffic channel table.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Pointer to entry.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVDT_TC_TBL *avdt_ad_tc_tbl_alloc(tAVDT_CCB *p_ccb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
|
||||||
|
|
||||||
|
/* find next free entry in tc table */
|
||||||
|
for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++)
|
||||||
|
{
|
||||||
|
if (p_tbl->state == AVDT_AD_ST_UNUSED)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
assert(i != AVDT_NUM_TC_TBL);
|
||||||
|
|
||||||
|
|
||||||
|
/* initialize entry */
|
||||||
|
p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
|
||||||
|
p_tbl->cfg_flags = 0;
|
||||||
|
p_tbl->ccb_idx = avdt_ccb_to_idx(p_ccb);
|
||||||
|
p_tbl->state = AVDT_AD_ST_IDLE;
|
||||||
|
return p_tbl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tc_tbl_to_idx
|
||||||
|
**
|
||||||
|
** Description Convert a transport channel table entry to an index.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Index value.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT8 avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL *p_tbl)
|
||||||
|
{
|
||||||
|
AVDT_TRACE_DEBUG("avdt_ad_tc_tbl_to_idx: %d", (p_tbl - avdt_cb.ad.tc_tbl));
|
||||||
|
/* use array arithmetic to determine index */
|
||||||
|
return (UINT8) (p_tbl - avdt_cb.ad.tc_tbl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tc_close_ind
|
||||||
|
**
|
||||||
|
** Description This function is called by the L2CAP interface when the
|
||||||
|
** L2CAP channel is closed. It looks up the CCB or SCB for
|
||||||
|
** the channel and sends it a close event. The reason
|
||||||
|
** parameter is the same value passed by the L2CAP
|
||||||
|
** callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb;
|
||||||
|
tAVDT_SCB *p_scb;
|
||||||
|
tAVDT_SCB_TC_CLOSE close;
|
||||||
|
UNUSED(reason);
|
||||||
|
|
||||||
|
close.old_tc_state = p_tbl->state;
|
||||||
|
/* clear avdt_ad_tc_tbl entry */
|
||||||
|
p_tbl->state = AVDT_AD_ST_UNUSED;
|
||||||
|
p_tbl->cfg_flags = 0;
|
||||||
|
p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("avdt_ad_tc_close_ind tcid: %d, old: %d",
|
||||||
|
p_tbl->tcid, close.old_tc_state);
|
||||||
|
/* if signaling channel, notify ccb that channel open */
|
||||||
|
if (p_tbl->tcid == 0)
|
||||||
|
{
|
||||||
|
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
|
||||||
|
avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
|
||||||
|
}
|
||||||
|
/* if media or other channel, notify scb that channel close */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* look up scb in stream routing table by ccb, tcid */
|
||||||
|
p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
|
||||||
|
if (p_scb != NULL)
|
||||||
|
{
|
||||||
|
close.tcid = p_tbl->tcid;
|
||||||
|
close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
|
||||||
|
avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, (tAVDT_SCB_EVT *)&close);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tc_open_ind
|
||||||
|
**
|
||||||
|
** Description This function is called by the L2CAP interface when
|
||||||
|
** the L2CAP channel is opened. It looks up the CCB or SCB
|
||||||
|
** for the channel and sends it an open event.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb;
|
||||||
|
tAVDT_SCB *p_scb;
|
||||||
|
tAVDT_OPEN open;
|
||||||
|
tAVDT_EVT_HDR evt;
|
||||||
|
|
||||||
|
p_tbl->state = AVDT_AD_ST_OPEN;
|
||||||
|
|
||||||
|
/* if signaling channel, notify ccb that channel open */
|
||||||
|
if (p_tbl->tcid == 0)
|
||||||
|
{
|
||||||
|
/* set the signal channel to use high priority within the ACL link */
|
||||||
|
L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid, L2CAP_CHNL_PRIORITY_HIGH);
|
||||||
|
|
||||||
|
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
|
||||||
|
/* use err_param to indicate the role of connection.
|
||||||
|
* AVDT_ACP, if ACP */
|
||||||
|
evt.err_param = AVDT_INT;
|
||||||
|
if(p_tbl->cfg_flags & AVDT_L2C_CFG_CONN_ACP)
|
||||||
|
{
|
||||||
|
evt.err_param = AVDT_ACP;
|
||||||
|
}
|
||||||
|
avdt_ccb_event(p_ccb, AVDT_CCB_LL_OPEN_EVT, (tAVDT_CCB_EVT *)&evt);
|
||||||
|
}
|
||||||
|
/* if media or other channel, notify scb that channel open */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* look up scb in stream routing table by ccb, tcid */
|
||||||
|
p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
|
||||||
|
|
||||||
|
/* put lcid in event data */
|
||||||
|
if (p_scb != NULL)
|
||||||
|
{
|
||||||
|
open.peer_mtu = p_tbl->peer_mtu;
|
||||||
|
open.lcid = avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid;
|
||||||
|
open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid);
|
||||||
|
avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, (tAVDT_SCB_EVT *) &open);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tc_cong_ind
|
||||||
|
**
|
||||||
|
** Description This function is called by the L2CAP interface layer when
|
||||||
|
** L2CAP calls the congestion callback. It looks up the CCB
|
||||||
|
** or SCB for the channel and sends it a congestion event.
|
||||||
|
** The is_congested parameter is the same value passed by
|
||||||
|
** the L2CAP callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb;
|
||||||
|
tAVDT_SCB *p_scb;
|
||||||
|
|
||||||
|
/* if signaling channel, notify ccb of congestion */
|
||||||
|
if (p_tbl->tcid == 0)
|
||||||
|
{
|
||||||
|
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
|
||||||
|
avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, (tAVDT_CCB_EVT *) &is_congested);
|
||||||
|
}
|
||||||
|
/* if media or other channel, notify scb that channel open */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* look up scb in stream routing table by ccb, tcid */
|
||||||
|
p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
|
||||||
|
if (p_scb != NULL)
|
||||||
|
{
|
||||||
|
avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, (tAVDT_SCB_EVT *) &is_congested);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_tc_data_ind
|
||||||
|
**
|
||||||
|
** Description This function is called by the L2CAP interface layer when
|
||||||
|
** incoming data is received from L2CAP. It looks up the CCB
|
||||||
|
** or SCB for the channel and routes the data accordingly.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb;
|
||||||
|
tAVDT_SCB *p_scb;
|
||||||
|
|
||||||
|
/* store type (media, recovery, reporting) */
|
||||||
|
p_buf->layer_specific = avdt_ad_tcid_to_type(p_tbl->tcid);
|
||||||
|
|
||||||
|
|
||||||
|
/* if signaling channel, handle control message */
|
||||||
|
if (p_tbl->tcid == 0)
|
||||||
|
{
|
||||||
|
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
|
||||||
|
avdt_msg_ind(p_ccb, p_buf);
|
||||||
|
}
|
||||||
|
/* if media or other channel, send event to scb */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
|
||||||
|
if (p_scb != NULL)
|
||||||
|
{
|
||||||
|
avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT *) &p_buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
AVDT_TRACE_ERROR(" avdt_ad_tc_data_ind buffer freed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_write_req
|
||||||
|
**
|
||||||
|
** Description This function is called by a CCB or SCB to send data to a
|
||||||
|
** transport channel. It looks up the LCID of the channel
|
||||||
|
** based on the type, CCB, and SCB (if present). Then it
|
||||||
|
** passes the data to L2CA_DataWrite().
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns AVDT_AD_SUCCESS, if data accepted, else FALSE
|
||||||
|
** AVDT_AD_CONGESTED, if data accepted and the channel is congested
|
||||||
|
** AVDT_AD_FAILED, if error
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT8 avdt_ad_write_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, BT_HDR *p_buf)
|
||||||
|
{
|
||||||
|
UINT8 tcid;
|
||||||
|
|
||||||
|
/* get tcid from type, scb */
|
||||||
|
tcid = avdt_ad_type_to_tcid(type, p_scb);
|
||||||
|
|
||||||
|
|
||||||
|
return L2CA_DataWrite(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid, p_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_open_req
|
||||||
|
**
|
||||||
|
** Description This function is called by a CCB or SCB to open a transport
|
||||||
|
** channel. This function allocates and initializes a
|
||||||
|
** transport channel table entry. The channel can be opened
|
||||||
|
** in two roles: as an initiator or acceptor. When opened
|
||||||
|
** as an initiator the function will start an L2CAP connection.
|
||||||
|
** When opened as an acceptor the function simply configures
|
||||||
|
** the table entry to listen for an incoming channel.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role)
|
||||||
|
{
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
UINT16 lcid;
|
||||||
|
|
||||||
|
if((p_tbl = avdt_ad_tc_tbl_alloc(p_ccb)) == NULL)
|
||||||
|
{
|
||||||
|
AVDT_TRACE_ERROR("avdt_ad_open_req: Cannot allocate p_tbl");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
p_tbl->tcid = avdt_ad_type_to_tcid(type, p_scb);
|
||||||
|
AVDT_TRACE_DEBUG("avdt_ad_open_req: type: %d, role: %d, tcid:%d",
|
||||||
|
type, role, p_tbl->tcid);
|
||||||
|
|
||||||
|
if (type == AVDT_CHAN_SIG)
|
||||||
|
{
|
||||||
|
/* if signaling, get mtu from registration control block */
|
||||||
|
p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
|
||||||
|
p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* otherwise get mtu from scb */
|
||||||
|
p_tbl->my_mtu = p_scb->cs.mtu;
|
||||||
|
p_tbl->my_flush_to = p_scb->cs.flush_to;
|
||||||
|
|
||||||
|
/* also set scb_hdl in rt_tbl */
|
||||||
|
avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl = avdt_scb_to_hdl(p_scb);
|
||||||
|
AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].scb_hdl = %d",
|
||||||
|
avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
|
||||||
|
avdt_scb_to_hdl(p_scb));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we're acceptor, we're done; just sit back and listen */
|
||||||
|
if (role == AVDT_ACP)
|
||||||
|
{
|
||||||
|
p_tbl->state = AVDT_AD_ST_ACP;
|
||||||
|
}
|
||||||
|
/* else we're inititator, start the L2CAP connection */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_tbl->state = AVDT_AD_ST_CONN;
|
||||||
|
|
||||||
|
/* call l2cap connect req */
|
||||||
|
if ((lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr)) != 0)
|
||||||
|
{
|
||||||
|
/* if connect req ok, store tcid in lcid table */
|
||||||
|
avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
|
||||||
|
AVDT_TRACE_DEBUG("avdt_cb.ad.lcid_tbl[%d] = %d",
|
||||||
|
(lcid - L2CAP_BASE_APPL_CID), avdt_ad_tc_tbl_to_idx(p_tbl));
|
||||||
|
|
||||||
|
avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
|
||||||
|
AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].lcid = 0x%x",
|
||||||
|
avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
|
||||||
|
lcid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* if connect req failed, call avdt_ad_tc_close_ind() */
|
||||||
|
avdt_ad_tc_close_ind(p_tbl, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ad_close_req
|
||||||
|
**
|
||||||
|
** Description This function is called by a CCB or SCB to close a
|
||||||
|
** transport channel. The function looks up the LCID for the
|
||||||
|
** channel and calls L2CA_DisconnectReq().
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
|
||||||
|
{
|
||||||
|
UINT8 tcid;
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
|
||||||
|
p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb);
|
||||||
|
AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d", p_tbl->state);
|
||||||
|
|
||||||
|
switch(p_tbl->state)
|
||||||
|
{
|
||||||
|
case AVDT_AD_ST_UNUSED:
|
||||||
|
/* probably for reporting */
|
||||||
|
break;
|
||||||
|
case AVDT_AD_ST_ACP:
|
||||||
|
/* if we're listening on this channel, send ourselves a close ind */
|
||||||
|
avdt_ad_tc_close_ind(p_tbl, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* get tcid from type, scb */
|
||||||
|
tcid = avdt_ad_type_to_tcid(type, p_scb);
|
||||||
|
|
||||||
|
/* call l2cap disconnect req */
|
||||||
|
L2CA_DisconnectReq(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1436
components/bt/bluedroid/stack/avdt/avdt_api.c
Executable file
1436
components/bt/bluedroid/stack/avdt/avdt_api.c
Executable file
File diff suppressed because it is too large
Load Diff
465
components/bt/bluedroid/stack/avdt/avdt_ccb.c
Executable file
465
components/bt/bluedroid/stack/avdt/avdt_ccb.c
Executable file
@ -0,0 +1,465 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This module contains the channel control block state machine and
|
||||||
|
* functions which operate on the channel control block.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bt_types.h"
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
#include "avdt_api.h"
|
||||||
|
#include "avdtc_api.h"
|
||||||
|
#include "avdt_int.h"
|
||||||
|
#include "gki.h"
|
||||||
|
#include "btu.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** state machine constants and types
|
||||||
|
*****************************************************************************/
|
||||||
|
#if AVDT_DEBUG == TRUE
|
||||||
|
|
||||||
|
/* verbose state strings for trace */
|
||||||
|
const char * const avdt_ccb_st_str[] = {
|
||||||
|
"CCB_IDLE_ST",
|
||||||
|
"CCB_OPENING_ST",
|
||||||
|
"CCB_OPEN_ST",
|
||||||
|
"CCB_CLOSING_ST"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* verbose event strings for trace */
|
||||||
|
const char * const avdt_ccb_evt_str[] = {
|
||||||
|
"API_DISCOVER_REQ_EVT",
|
||||||
|
"API_GETCAP_REQ_EVT",
|
||||||
|
"API_START_REQ_EVT",
|
||||||
|
"API_SUSPEND_REQ_EVT",
|
||||||
|
"API_DISCOVER_RSP_EVT",
|
||||||
|
"API_GETCAP_RSP_EVT",
|
||||||
|
"API_START_RSP_EVT",
|
||||||
|
"API_SUSPEND_RSP_EVT",
|
||||||
|
"API_CONNECT_REQ_EVT",
|
||||||
|
"API_DISCONNECT_REQ_EVT",
|
||||||
|
"MSG_DISCOVER_CMD_EVT",
|
||||||
|
"MSG_GETCAP_CMD_EVT",
|
||||||
|
"MSG_START_CMD_EVT",
|
||||||
|
"MSG_SUSPEND_CMD_EVT",
|
||||||
|
"MSG_DISCOVER_RSP_EVT",
|
||||||
|
"MSG_GETCAP_RSP_EVT",
|
||||||
|
"MSG_START_RSP_EVT",
|
||||||
|
"MSG_SUSPEND_RSP_EVT",
|
||||||
|
"RCVRSP_EVT",
|
||||||
|
"SENDMSG_EVT",
|
||||||
|
"RET_TOUT_EVT",
|
||||||
|
"RSP_TOUT_EVT",
|
||||||
|
"IDLE_TOUT_EVT",
|
||||||
|
"UL_OPEN_EVT",
|
||||||
|
"UL_CLOSE_EVT",
|
||||||
|
"LL_OPEN_EVT",
|
||||||
|
"LL_CLOSE_EVT",
|
||||||
|
"LL_CONG_EVT"
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* action function list */
|
||||||
|
const tAVDT_CCB_ACTION avdt_ccb_action[] = {
|
||||||
|
avdt_ccb_chan_open,
|
||||||
|
avdt_ccb_chan_close,
|
||||||
|
avdt_ccb_chk_close,
|
||||||
|
avdt_ccb_hdl_discover_cmd,
|
||||||
|
avdt_ccb_hdl_discover_rsp,
|
||||||
|
avdt_ccb_hdl_getcap_cmd,
|
||||||
|
avdt_ccb_hdl_getcap_rsp,
|
||||||
|
avdt_ccb_hdl_start_cmd,
|
||||||
|
avdt_ccb_hdl_start_rsp,
|
||||||
|
avdt_ccb_hdl_suspend_cmd,
|
||||||
|
avdt_ccb_hdl_suspend_rsp,
|
||||||
|
avdt_ccb_snd_discover_cmd,
|
||||||
|
avdt_ccb_snd_discover_rsp,
|
||||||
|
avdt_ccb_snd_getcap_cmd,
|
||||||
|
avdt_ccb_snd_getcap_rsp,
|
||||||
|
avdt_ccb_snd_start_cmd,
|
||||||
|
avdt_ccb_snd_start_rsp,
|
||||||
|
avdt_ccb_snd_suspend_cmd,
|
||||||
|
avdt_ccb_snd_suspend_rsp,
|
||||||
|
avdt_ccb_clear_cmds,
|
||||||
|
avdt_ccb_cmd_fail,
|
||||||
|
avdt_ccb_free_cmd,
|
||||||
|
avdt_ccb_cong_state,
|
||||||
|
avdt_ccb_ret_cmd,
|
||||||
|
avdt_ccb_snd_cmd,
|
||||||
|
avdt_ccb_snd_msg,
|
||||||
|
avdt_ccb_set_reconn,
|
||||||
|
avdt_ccb_clr_reconn,
|
||||||
|
avdt_ccb_chk_reconn,
|
||||||
|
avdt_ccb_chk_timer,
|
||||||
|
avdt_ccb_set_conn,
|
||||||
|
avdt_ccb_set_disconn,
|
||||||
|
avdt_ccb_do_disconn,
|
||||||
|
avdt_ccb_ll_closed,
|
||||||
|
avdt_ccb_ll_opened,
|
||||||
|
avdt_ccb_dealloc
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table information */
|
||||||
|
#define AVDT_CCB_ACTIONS 2 /* number of actions */
|
||||||
|
#define AVDT_CCB_NEXT_STATE 2 /* position of next state */
|
||||||
|
#define AVDT_CCB_NUM_COLS 3 /* number of columns in state tables */
|
||||||
|
|
||||||
|
/* state table for idle state */
|
||||||
|
const UINT8 avdt_ccb_st_idle[][AVDT_CCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_DISCOVER_REQ_EVT */ {AVDT_CCB_SND_DISCOVER_CMD, AVDT_CCB_CHAN_OPEN, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_GETCAP_REQ_EVT */ {AVDT_CCB_SND_GETCAP_CMD, AVDT_CCB_CHAN_OPEN, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_START_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* API_SUSPEND_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* API_DISCOVER_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* API_GETCAP_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* API_START_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* API_SUSPEND_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* API_CONNECT_REQ_EVT */ {AVDT_CCB_SET_CONN, AVDT_CCB_CHAN_OPEN, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_DISCONNECT_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* MSG_DISCOVER_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* MSG_GETCAP_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* MSG_DISCOVER_RSP_EVT */ {AVDT_CCB_HDL_DISCOVER_RSP, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* MSG_GETCAP_RSP_EVT */ {AVDT_CCB_HDL_GETCAP_RSP, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_CCB_HDL_START_RSP, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_CCB_HDL_SUSPEND_RSP, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* RCVRSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* SENDMSG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* RET_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* RSP_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* IDLE_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* UL_OPEN_EVT */ {AVDT_CCB_CHAN_OPEN, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* UL_CLOSE_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* LL_OPEN_EVT */ {AVDT_CCB_LL_OPENED, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* LL_CLOSE_EVT */ {AVDT_CCB_LL_CLOSED, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* LL_CONG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for opening state */
|
||||||
|
const UINT8 avdt_ccb_st_opening[][AVDT_CCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_DISCOVER_REQ_EVT */ {AVDT_CCB_SND_DISCOVER_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_GETCAP_REQ_EVT */ {AVDT_CCB_SND_GETCAP_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_START_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_SUSPEND_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_DISCOVER_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_GETCAP_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_START_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_SUSPEND_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_CONNECT_REQ_EVT */ {AVDT_CCB_SET_CONN, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* API_DISCONNECT_REQ_EVT */ {AVDT_CCB_SET_DISCONN, AVDT_CCB_DO_DISCONN, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_DISCOVER_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* MSG_GETCAP_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* MSG_DISCOVER_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* MSG_GETCAP_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* RCVRSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* SENDMSG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* RET_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* RSP_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* IDLE_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* UL_OPEN_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST},
|
||||||
|
/* UL_CLOSE_EVT */ {AVDT_CCB_CLEAR_CMDS, AVDT_CCB_CHAN_CLOSE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* LL_OPEN_EVT */ {AVDT_CCB_SND_CMD, AVDT_CCB_LL_OPENED, AVDT_CCB_OPEN_ST},
|
||||||
|
/* LL_CLOSE_EVT */ {AVDT_CCB_LL_CLOSED, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* LL_CONG_EVT */ {AVDT_CCB_CONG_STATE, AVDT_CCB_IGNORE, AVDT_CCB_OPENING_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for open state */
|
||||||
|
const UINT8 avdt_ccb_st_open[][AVDT_CCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_DISCOVER_REQ_EVT */ {AVDT_CCB_SND_DISCOVER_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* API_GETCAP_REQ_EVT */ {AVDT_CCB_SND_GETCAP_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* API_START_REQ_EVT */ {AVDT_CCB_SND_START_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* API_SUSPEND_REQ_EVT */ {AVDT_CCB_SND_SUSPEND_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* API_DISCOVER_RSP_EVT */ {AVDT_CCB_SND_DISCOVER_RSP, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* API_GETCAP_RSP_EVT */ {AVDT_CCB_SND_GETCAP_RSP, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* API_START_RSP_EVT */ {AVDT_CCB_SND_START_RSP, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* API_SUSPEND_RSP_EVT */ {AVDT_CCB_SND_SUSPEND_RSP, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* API_CONNECT_REQ_EVT */ {AVDT_CCB_SET_CONN, AVDT_CCB_LL_OPENED, AVDT_CCB_OPEN_ST},
|
||||||
|
/* API_DISCONNECT_REQ_EVT */ {AVDT_CCB_SET_DISCONN, AVDT_CCB_DO_DISCONN, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_DISCOVER_CMD_EVT */ {AVDT_CCB_HDL_DISCOVER_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* MSG_GETCAP_CMD_EVT */ {AVDT_CCB_HDL_GETCAP_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_CCB_HDL_START_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_CCB_HDL_SUSPEND_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* MSG_DISCOVER_RSP_EVT */ {AVDT_CCB_CHK_CLOSE, AVDT_CCB_HDL_DISCOVER_RSP, AVDT_CCB_OPEN_ST},
|
||||||
|
/* MSG_GETCAP_RSP_EVT */ {AVDT_CCB_CHK_CLOSE, AVDT_CCB_HDL_GETCAP_RSP, AVDT_CCB_OPEN_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_CCB_HDL_START_RSP, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_CCB_HDL_SUSPEND_RSP, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* RCVRSP_EVT */ {AVDT_CCB_FREE_CMD, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* SENDMSG_EVT */ {AVDT_CCB_SND_MSG, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* RET_TOUT_EVT */ {AVDT_CCB_RET_CMD, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* RSP_TOUT_EVT */ {AVDT_CCB_CMD_FAIL, AVDT_CCB_SND_CMD, AVDT_CCB_OPEN_ST},
|
||||||
|
/* IDLE_TOUT_EVT */ {AVDT_CCB_CLEAR_CMDS, AVDT_CCB_CHAN_CLOSE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* UL_OPEN_EVT */ {AVDT_CCB_CHK_TIMER, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* UL_CLOSE_EVT */ {AVDT_CCB_CHK_CLOSE, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* LL_OPEN_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_OPEN_ST},
|
||||||
|
/* LL_CLOSE_EVT */ {AVDT_CCB_LL_CLOSED, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* LL_CONG_EVT */ {AVDT_CCB_CONG_STATE, AVDT_CCB_SND_MSG, AVDT_CCB_OPEN_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for closing state */
|
||||||
|
const UINT8 avdt_ccb_st_closing[][AVDT_CCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_DISCOVER_REQ_EVT */ {AVDT_CCB_SET_RECONN, AVDT_CCB_SND_DISCOVER_CMD, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* API_GETCAP_REQ_EVT */ {AVDT_CCB_SET_RECONN, AVDT_CCB_SND_GETCAP_CMD, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* API_START_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* API_SUSPEND_REQ_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* API_DISCOVER_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* API_GETCAP_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* API_START_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* API_SUSPEND_RSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* API_CONNECT_REQ_EVT */ {AVDT_CCB_SET_RECONN, AVDT_CCB_SET_CONN, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* API_DISCONNECT_REQ_EVT */ {AVDT_CCB_CLR_RECONN, AVDT_CCB_SET_DISCONN, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_DISCOVER_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_GETCAP_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_DISCOVER_RSP_EVT */ {AVDT_CCB_HDL_DISCOVER_RSP, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_GETCAP_RSP_EVT */ {AVDT_CCB_HDL_GETCAP_RSP, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_CCB_HDL_START_RSP, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_CCB_HDL_SUSPEND_RSP, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* RCVRSP_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* SENDMSG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* RET_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* RSP_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* IDLE_TOUT_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* UL_OPEN_EVT */ {AVDT_CCB_SET_RECONN, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* UL_CLOSE_EVT */ {AVDT_CCB_CLR_RECONN, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* LL_OPEN_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST},
|
||||||
|
/* LL_CLOSE_EVT */ {AVDT_CCB_CHK_RECONN, AVDT_CCB_IGNORE, AVDT_CCB_IDLE_ST},
|
||||||
|
/* LL_CONG_EVT */ {AVDT_CCB_IGNORE, AVDT_CCB_IGNORE, AVDT_CCB_CLOSING_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* type for state table */
|
||||||
|
typedef const UINT8 (*tAVDT_CCB_ST_TBL)[AVDT_CCB_NUM_COLS];
|
||||||
|
|
||||||
|
/* state table */
|
||||||
|
const tAVDT_CCB_ST_TBL avdt_ccb_st_tbl[] = {
|
||||||
|
avdt_ccb_st_idle,
|
||||||
|
avdt_ccb_st_opening,
|
||||||
|
avdt_ccb_st_open,
|
||||||
|
avdt_ccb_st_closing
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ccb_init
|
||||||
|
**
|
||||||
|
** Description Initialize channel control block module.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ccb_init(void)
|
||||||
|
{
|
||||||
|
memset(&avdt_cb.ccb[0], 0, sizeof(tAVDT_CCB) * AVDT_NUM_LINKS);
|
||||||
|
avdt_cb.p_ccb_act = (tAVDT_CCB_ACTION *) avdt_ccb_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ccb_event
|
||||||
|
**
|
||||||
|
** Description State machine event handling function for ccb
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ccb_event(tAVDT_CCB *p_ccb, UINT8 event, tAVDT_CCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVDT_CCB_ST_TBL state_table;
|
||||||
|
UINT8 action;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if AVDT_DEBUG == TRUE
|
||||||
|
AVDT_TRACE_EVENT("CCB ccb=%d event=%s state=%s", avdt_ccb_to_idx(p_ccb), avdt_ccb_evt_str[event], avdt_ccb_st_str[p_ccb->state]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* look up the state table for the current state */
|
||||||
|
state_table = avdt_ccb_st_tbl[p_ccb->state];
|
||||||
|
|
||||||
|
/* set next state */
|
||||||
|
if (p_ccb->state != state_table[event][AVDT_CCB_NEXT_STATE]) {
|
||||||
|
p_ccb->state = state_table[event][AVDT_CCB_NEXT_STATE];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* execute action functions */
|
||||||
|
for (i = 0; i < AVDT_CCB_ACTIONS; i++)
|
||||||
|
{
|
||||||
|
if ((action = state_table[event][i]) != AVDT_CCB_IGNORE)
|
||||||
|
{
|
||||||
|
(*avdt_cb.p_ccb_act[action])(p_ccb, p_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ccb_by_bd
|
||||||
|
**
|
||||||
|
** Description This lookup function finds the ccb for a BD address.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns pointer to the ccb, or NULL if none found.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVDT_CCB *avdt_ccb_by_bd(BD_ADDR bd_addr)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb = &avdt_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
/* if allocated ccb has matching ccb */
|
||||||
|
if (p_ccb->allocated && (!memcmp(p_ccb->peer_addr, bd_addr, BD_ADDR_LEN)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == AVDT_NUM_LINKS)
|
||||||
|
{
|
||||||
|
/* if no ccb found */
|
||||||
|
p_ccb = NULL;
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("No ccb for addr %02x-%02x-%02x-%02x-%02x-%02x",
|
||||||
|
bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
|
||||||
|
}
|
||||||
|
return p_ccb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ccb_alloc
|
||||||
|
**
|
||||||
|
** Description Allocate a channel control block.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns pointer to the ccb, or NULL if none could be allocated.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVDT_CCB *avdt_ccb_alloc(BD_ADDR bd_addr)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb = &avdt_cb.ccb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++)
|
||||||
|
{
|
||||||
|
if (!p_ccb->allocated)
|
||||||
|
{
|
||||||
|
p_ccb->allocated = TRUE;
|
||||||
|
memcpy(p_ccb->peer_addr, bd_addr, BD_ADDR_LEN);
|
||||||
|
GKI_init_q(&p_ccb->cmd_q);
|
||||||
|
GKI_init_q(&p_ccb->rsp_q);
|
||||||
|
p_ccb->timer_entry.param = (UINT32) p_ccb;
|
||||||
|
AVDT_TRACE_DEBUG("avdt_ccb_alloc %d", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == AVDT_NUM_LINKS)
|
||||||
|
{
|
||||||
|
/* out of ccbs */
|
||||||
|
p_ccb = NULL;
|
||||||
|
AVDT_TRACE_WARNING("Out of ccbs");
|
||||||
|
}
|
||||||
|
return p_ccb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ccb_dealloc
|
||||||
|
**
|
||||||
|
** Description Deallocate a stream control block.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_ccb_dealloc(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
UNUSED(p_data);
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("avdt_ccb_dealloc %d", avdt_ccb_to_idx(p_ccb));
|
||||||
|
btu_stop_timer(&p_ccb->timer_entry);
|
||||||
|
memset(p_ccb, 0, sizeof(tAVDT_CCB));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ccb_to_idx
|
||||||
|
**
|
||||||
|
** Description Given a pointer to an ccb, return its index.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Index of ccb.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT8 avdt_ccb_to_idx(tAVDT_CCB *p_ccb)
|
||||||
|
{
|
||||||
|
/* use array arithmetic to determine index */
|
||||||
|
return (UINT8) (p_ccb - avdt_cb.ccb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_ccb_by_idx
|
||||||
|
**
|
||||||
|
** Description Return ccb pointer based on ccb index.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns pointer to the ccb, or NULL if none found.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVDT_CCB *avdt_ccb_by_idx(UINT8 idx)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb;
|
||||||
|
|
||||||
|
/* verify index */
|
||||||
|
if (idx < AVDT_NUM_LINKS)
|
||||||
|
{
|
||||||
|
p_ccb = &avdt_cb.ccb[idx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_ccb = NULL;
|
||||||
|
AVDT_TRACE_WARNING("No ccb for idx %d", idx);
|
||||||
|
}
|
||||||
|
return p_ccb;
|
||||||
|
}
|
||||||
|
|
1128
components/bt/bluedroid/stack/avdt/avdt_ccb_act.c
Executable file
1128
components/bt/bluedroid/stack/avdt/avdt_ccb_act.c
Executable file
File diff suppressed because it is too large
Load Diff
529
components/bt/bluedroid/stack/avdt/avdt_l2c.c
Executable file
529
components/bt/bluedroid/stack/avdt/avdt_l2c.c
Executable file
@ -0,0 +1,529 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This AVDTP adaption layer module interfaces to L2CAP
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bt_types.h"
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
#include "avdt_api.h"
|
||||||
|
#include "avdtc_api.h"
|
||||||
|
#include "avdt_int.h"
|
||||||
|
#include "l2c_api.h"
|
||||||
|
#include "l2cdefs.h"
|
||||||
|
#include "btm_api.h"
|
||||||
|
#include "btm_int.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* callback function declarations */
|
||||||
|
void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
|
||||||
|
void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
|
||||||
|
void avdt_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
|
||||||
|
void avdt_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
|
||||||
|
void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
|
||||||
|
void avdt_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
|
||||||
|
void avdt_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
|
||||||
|
void avdt_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
|
||||||
|
|
||||||
|
/* L2CAP callback function structure */
|
||||||
|
const tL2CAP_APPL_INFO avdt_l2c_appl = {
|
||||||
|
avdt_l2c_connect_ind_cback,
|
||||||
|
avdt_l2c_connect_cfm_cback,
|
||||||
|
NULL,
|
||||||
|
avdt_l2c_config_ind_cback,
|
||||||
|
avdt_l2c_config_cfm_cback,
|
||||||
|
avdt_l2c_disconnect_ind_cback,
|
||||||
|
avdt_l2c_disconnect_cfm_cback,
|
||||||
|
NULL,
|
||||||
|
avdt_l2c_data_ind_cback,
|
||||||
|
avdt_l2c_congestion_ind_cback,
|
||||||
|
NULL /* tL2CA_TX_COMPLETE_CB */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_sec_check_complete_term
|
||||||
|
**
|
||||||
|
** Description The function called when Security Manager finishes
|
||||||
|
** verification of the service side connection
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transport,
|
||||||
|
void *p_ref_data, UINT8 res)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb = NULL;
|
||||||
|
tL2CAP_CFG_INFO cfg;
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
UNUSED(p_ref_data);
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d", res);
|
||||||
|
if (!bd_addr)
|
||||||
|
{
|
||||||
|
AVDT_TRACE_WARNING("avdt_sec_check_complete_term: NULL BD_ADDR");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
p_ccb = avdt_ccb_by_bd(bd_addr);
|
||||||
|
|
||||||
|
p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_ACP);
|
||||||
|
if (p_tbl == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (res == BTM_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Send response to the L2CAP layer. */
|
||||||
|
L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK);
|
||||||
|
|
||||||
|
/* store idx in LCID table, store LCID in routing table */
|
||||||
|
avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
|
||||||
|
avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid;
|
||||||
|
|
||||||
|
/* transition to configuration state */
|
||||||
|
p_tbl->state = AVDT_AD_ST_CFG;
|
||||||
|
|
||||||
|
/* Send L2CAP config req */
|
||||||
|
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||||
|
cfg.mtu_present = TRUE;
|
||||||
|
cfg.mtu = p_tbl->my_mtu;
|
||||||
|
cfg.flush_to_present = TRUE;
|
||||||
|
cfg.flush_to = p_tbl->my_flush_to;
|
||||||
|
L2CA_ConfigReq(p_tbl->lcid, &cfg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK);
|
||||||
|
avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_sec_check_complete_orig
|
||||||
|
**
|
||||||
|
** Description The function called when Security Manager finishes
|
||||||
|
** verification of the service side connection
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
|
||||||
|
void *p_ref_data, UINT8 res)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb = NULL;
|
||||||
|
tL2CAP_CFG_INFO cfg;
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
UNUSED(p_ref_data);
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d", res);
|
||||||
|
if (bd_addr)
|
||||||
|
p_ccb = avdt_ccb_by_bd(bd_addr);
|
||||||
|
p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT);
|
||||||
|
if(p_tbl == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( res == BTM_SUCCESS )
|
||||||
|
{
|
||||||
|
/* set channel state */
|
||||||
|
p_tbl->state = AVDT_AD_ST_CFG;
|
||||||
|
|
||||||
|
/* Send L2CAP config req */
|
||||||
|
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||||
|
cfg.mtu_present = TRUE;
|
||||||
|
cfg.mtu = p_tbl->my_mtu;
|
||||||
|
cfg.flush_to_present = TRUE;
|
||||||
|
cfg.flush_to = p_tbl->my_flush_to;
|
||||||
|
L2CA_ConfigReq(p_tbl->lcid, &cfg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
L2CA_DisconnectReq (p_tbl->lcid);
|
||||||
|
avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_l2c_connect_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP connect indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
|
||||||
|
{
|
||||||
|
tAVDT_CCB *p_ccb;
|
||||||
|
tAVDT_TC_TBL *p_tbl = NULL;
|
||||||
|
UINT16 result;
|
||||||
|
tL2CAP_CFG_INFO cfg;
|
||||||
|
tBTM_STATUS rc;
|
||||||
|
UNUSED(psm);
|
||||||
|
|
||||||
|
/* do we already have a control channel for this peer? */
|
||||||
|
if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
|
||||||
|
{
|
||||||
|
/* no, allocate ccb */
|
||||||
|
if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
|
||||||
|
{
|
||||||
|
/* no ccb available, reject L2CAP connection */
|
||||||
|
result = L2CAP_CONN_NO_RESOURCES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* allocate and set up entry; first channel is always signaling */
|
||||||
|
p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
|
||||||
|
p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
|
||||||
|
p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
|
||||||
|
p_tbl->tcid = AVDT_CHAN_SIG;
|
||||||
|
p_tbl->lcid = lcid;
|
||||||
|
p_tbl->id = id;
|
||||||
|
p_tbl->state = AVDT_AD_ST_SEC_ACP;
|
||||||
|
p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP;
|
||||||
|
|
||||||
|
/* Check the security */
|
||||||
|
rc = btm_sec_mx_access_request (bd_addr, AVDT_PSM,
|
||||||
|
FALSE, BTM_SEC_PROTO_AVDT,
|
||||||
|
AVDT_CHAN_SIG,
|
||||||
|
&avdt_sec_check_complete_term, NULL);
|
||||||
|
if(rc == BTM_CMD_STARTED)
|
||||||
|
{
|
||||||
|
L2CA_ConnectRsp (p_ccb->peer_addr, p_tbl->id, lcid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* deal with simultaneous control channel connect case */
|
||||||
|
else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_CONN)) != NULL)
|
||||||
|
{
|
||||||
|
/* reject their connection */
|
||||||
|
result = L2CAP_CONN_NO_RESOURCES;
|
||||||
|
}
|
||||||
|
/* this must be a traffic channel; are we accepting a traffic channel
|
||||||
|
** for this ccb?
|
||||||
|
*/
|
||||||
|
else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_MEDIA, p_ccb, AVDT_AD_ST_ACP)) != NULL)
|
||||||
|
{
|
||||||
|
/* yes; proceed with connection */
|
||||||
|
result = L2CAP_CONN_OK;
|
||||||
|
}
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
/* this must be a reporting channel; are we accepting a reporting channel
|
||||||
|
** for this ccb?
|
||||||
|
*/
|
||||||
|
else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_REPORT, p_ccb, AVDT_AD_ST_ACP)) != NULL)
|
||||||
|
{
|
||||||
|
/* yes; proceed with connection */
|
||||||
|
result = L2CAP_CONN_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* else we're not listening for traffic channel; reject */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = L2CAP_CONN_NO_PSM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send L2CAP connect rsp */
|
||||||
|
L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
|
||||||
|
|
||||||
|
/* if result ok, proceed with connection */
|
||||||
|
if (result == L2CAP_CONN_OK)
|
||||||
|
{
|
||||||
|
/* store idx in LCID table, store LCID in routing table */
|
||||||
|
avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
|
||||||
|
avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
|
||||||
|
|
||||||
|
/* transition to configuration state */
|
||||||
|
p_tbl->state = AVDT_AD_ST_CFG;
|
||||||
|
|
||||||
|
/* Send L2CAP config req */
|
||||||
|
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||||
|
cfg.mtu_present = TRUE;
|
||||||
|
cfg.mtu = p_tbl->my_mtu;
|
||||||
|
cfg.flush_to_present = TRUE;
|
||||||
|
cfg.flush_to = p_tbl->my_flush_to;
|
||||||
|
L2CA_ConfigReq(lcid, &cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_l2c_connect_cfm_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP connect confirm callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
|
||||||
|
{
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
tL2CAP_CFG_INFO cfg;
|
||||||
|
tAVDT_CCB *p_ccb;
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("avdt_l2c_connect_cfm_cback lcid: %d, result: %d",
|
||||||
|
lcid, result);
|
||||||
|
/* look up info for this channel */
|
||||||
|
if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
/* if in correct state */
|
||||||
|
if (p_tbl->state == AVDT_AD_ST_CONN)
|
||||||
|
{
|
||||||
|
/* if result successful */
|
||||||
|
if (result == L2CAP_CONN_OK)
|
||||||
|
{
|
||||||
|
if(p_tbl->tcid != AVDT_CHAN_SIG)
|
||||||
|
{
|
||||||
|
/* set channel state */
|
||||||
|
p_tbl->state = AVDT_AD_ST_CFG;
|
||||||
|
|
||||||
|
/* Send L2CAP config req */
|
||||||
|
memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||||
|
cfg.mtu_present = TRUE;
|
||||||
|
cfg.mtu = p_tbl->my_mtu;
|
||||||
|
cfg.flush_to_present = TRUE;
|
||||||
|
cfg.flush_to = p_tbl->my_flush_to;
|
||||||
|
L2CA_ConfigReq(lcid, &cfg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
|
||||||
|
if(p_ccb == NULL)
|
||||||
|
{
|
||||||
|
result = L2CAP_CONN_NO_RESOURCES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* set channel state */
|
||||||
|
p_tbl->state = AVDT_AD_ST_SEC_INT;
|
||||||
|
p_tbl->lcid = lcid;
|
||||||
|
p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT;
|
||||||
|
|
||||||
|
/* Check the security */
|
||||||
|
btm_sec_mx_access_request (p_ccb->peer_addr, AVDT_PSM,
|
||||||
|
TRUE, BTM_SEC_PROTO_AVDT,
|
||||||
|
AVDT_CHAN_SIG,
|
||||||
|
&avdt_sec_check_complete_orig, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* failure; notify adaption that channel closed */
|
||||||
|
if (result != L2CAP_CONN_OK)
|
||||||
|
{
|
||||||
|
avdt_ad_tc_close_ind(p_tbl, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_l2c_config_cfm_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP config confirm callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
|
||||||
|
{
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
|
||||||
|
/* look up info for this channel */
|
||||||
|
if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
p_tbl->lcid = lcid;
|
||||||
|
|
||||||
|
/* if in correct state */
|
||||||
|
if (p_tbl->state == AVDT_AD_ST_CFG)
|
||||||
|
{
|
||||||
|
/* if result successful */
|
||||||
|
if (p_cfg->result == L2CAP_CONN_OK)
|
||||||
|
{
|
||||||
|
/* update cfg_flags */
|
||||||
|
p_tbl->cfg_flags |= AVDT_L2C_CFG_CFM_DONE;
|
||||||
|
|
||||||
|
/* if configuration complete */
|
||||||
|
if (p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE)
|
||||||
|
{
|
||||||
|
avdt_ad_tc_open_ind(p_tbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* else failure */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Send L2CAP disconnect req */
|
||||||
|
L2CA_DisconnectReq(lcid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_l2c_config_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP config indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
|
||||||
|
{
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
|
||||||
|
/* look up info for this channel */
|
||||||
|
if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
/* store the mtu in tbl */
|
||||||
|
if (p_cfg->mtu_present)
|
||||||
|
{
|
||||||
|
p_tbl->peer_mtu = p_cfg->mtu;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
|
||||||
|
}
|
||||||
|
AVDT_TRACE_DEBUG("peer_mtu: %d, lcid: x%x",p_tbl->peer_mtu, lcid);
|
||||||
|
|
||||||
|
/* send L2CAP configure response */
|
||||||
|
memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||||
|
p_cfg->result = L2CAP_CFG_OK;
|
||||||
|
L2CA_ConfigRsp(lcid, p_cfg);
|
||||||
|
|
||||||
|
/* if first config ind */
|
||||||
|
if ((p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE) == 0)
|
||||||
|
{
|
||||||
|
/* update cfg_flags */
|
||||||
|
p_tbl->cfg_flags |= AVDT_L2C_CFG_IND_DONE;
|
||||||
|
|
||||||
|
/* if configuration complete */
|
||||||
|
if (p_tbl->cfg_flags & AVDT_L2C_CFG_CFM_DONE)
|
||||||
|
{
|
||||||
|
avdt_ad_tc_open_ind(p_tbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_l2c_disconnect_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP disconnect indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
|
||||||
|
{
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d",
|
||||||
|
lcid, ack_needed);
|
||||||
|
/* look up info for this channel */
|
||||||
|
if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
if (ack_needed)
|
||||||
|
{
|
||||||
|
/* send L2CAP disconnect response */
|
||||||
|
L2CA_DisconnectRsp(lcid);
|
||||||
|
}
|
||||||
|
|
||||||
|
avdt_ad_tc_close_ind(p_tbl, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_l2c_disconnect_cfm_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP disconnect confirm callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
|
||||||
|
{
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("avdt_l2c_disconnect_cfm_cback lcid: %d, result: %d",
|
||||||
|
lcid, result);
|
||||||
|
/* look up info for this channel */
|
||||||
|
if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
avdt_ad_tc_close_ind(p_tbl, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_l2c_congestion_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP congestion indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested)
|
||||||
|
{
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
|
||||||
|
/* look up info for this channel */
|
||||||
|
if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
avdt_ad_tc_cong_ind(p_tbl, is_congested);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_l2c_data_ind_cback
|
||||||
|
**
|
||||||
|
** Description This is the L2CAP data indication callback function.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
|
||||||
|
{
|
||||||
|
tAVDT_TC_TBL *p_tbl;
|
||||||
|
|
||||||
|
/* look up info for this channel */
|
||||||
|
if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL)
|
||||||
|
{
|
||||||
|
avdt_ad_tc_data_ind(p_tbl, p_buf);
|
||||||
|
}
|
||||||
|
else /* prevent buffer leak */
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
}
|
||||||
|
|
1901
components/bt/bluedroid/stack/avdt/avdt_msg.c
Executable file
1901
components/bt/bluedroid/stack/avdt/avdt_msg.c
Executable file
File diff suppressed because it is too large
Load Diff
799
components/bt/bluedroid/stack/avdt/avdt_scb.c
Executable file
799
components/bt/bluedroid/stack/avdt/avdt_scb.c
Executable file
@ -0,0 +1,799 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This module contains the stream control block and functions which
|
||||||
|
* operate on the stream control block.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bt_types.h"
|
||||||
|
#include "bt_target.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
#include "avdt_api.h"
|
||||||
|
#include "avdtc_api.h"
|
||||||
|
#include "avdt_int.h"
|
||||||
|
#include "gki.h"
|
||||||
|
#include "btu.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** state machine constants and types
|
||||||
|
*****************************************************************************/
|
||||||
|
#if AVDT_DEBUG == TRUE
|
||||||
|
|
||||||
|
/* verbose state strings for trace */
|
||||||
|
const char * const avdt_scb_st_str[] = {
|
||||||
|
"SCB_IDLE_ST",
|
||||||
|
"SCB_CONF_ST",
|
||||||
|
"SCB_OPENING_ST",
|
||||||
|
"SCB_OPEN_ST",
|
||||||
|
"SCB_STREAM_ST",
|
||||||
|
"SCB_CLOSING_ST"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* verbose event strings for trace */
|
||||||
|
const char * const avdt_scb_evt_str[] = {
|
||||||
|
"API_REMOVE_EVT",
|
||||||
|
"API_WRITE_REQ_EVT",
|
||||||
|
"API_GETCONFIG_REQ_EVT",
|
||||||
|
"API_DELAY_RPT_REQ",
|
||||||
|
"API_SETCONFIG_REQ_EVT",
|
||||||
|
"API_OPEN_REQ_EVT",
|
||||||
|
"API_CLOSE_REQ_EVT",
|
||||||
|
"API_RECONFIG_REQ_EVT",
|
||||||
|
"API_SECURITY_REQ_EVT",
|
||||||
|
"API_ABORT_REQ_EVT",
|
||||||
|
"API_GETCONFIG_RSP_EVT",
|
||||||
|
"API_SETCONFIG_RSP_EVT",
|
||||||
|
"API_SETCONFIG_REJ_EVT",
|
||||||
|
"API_OPEN_RSP_EVT",
|
||||||
|
"API_CLOSE_RSP_EVT",
|
||||||
|
"API_RECONFIG_RSP_EVT",
|
||||||
|
"API_SECURITY_RSP_EVT",
|
||||||
|
"API_ABORT_RSP_EVT",
|
||||||
|
"MSG_SETCONFIG_CMD_EVT",
|
||||||
|
"MSG_GETCONFIG_CMD_EVT",
|
||||||
|
"MSG_OPEN_CMD_EVT",
|
||||||
|
"MSG_START_CMD_EVT",
|
||||||
|
"MSG_SUSPEND_CMD_EVT",
|
||||||
|
"MSG_CLOSE_CMD_EVT",
|
||||||
|
"MSG_ABORT_CMD_EVT",
|
||||||
|
"MSG_RECONFIG_CMD_EVT",
|
||||||
|
"MSG_SECURITY_CMD_EVT",
|
||||||
|
"MSG_DELAY_RPT_CMD_EVT",
|
||||||
|
"MSG_DELAY_RPT_RSP_EVT",
|
||||||
|
"MSG_SETCONFIG_RSP_EVT",
|
||||||
|
"MSG_GETCONFIG_RSP_EVT",
|
||||||
|
"MSG_OPEN_RSP_EVT",
|
||||||
|
"MSG_START_RSP_EVT",
|
||||||
|
"MSG_SUSPEND_RSP_EVT",
|
||||||
|
"MSG_CLOSE_RSP_EVT",
|
||||||
|
"MSG_ABORT_RSP_EVT",
|
||||||
|
"MSG_RECONFIG_RSP_EVT",
|
||||||
|
"MSG_SECURITY_RSP_EVT",
|
||||||
|
"MSG_SETCONFIG_REJ_EVT",
|
||||||
|
"MSG_OPEN_REJ_EVT",
|
||||||
|
"MSG_START_REJ_EVT",
|
||||||
|
"MSG_SUSPEND_REJ_EVT",
|
||||||
|
"TC_TOUT_EVT",
|
||||||
|
"TC_OPEN_EVT",
|
||||||
|
"TC_CLOSE_EVT",
|
||||||
|
"TC_CONG_EVT",
|
||||||
|
"TC_DATA_EVT",
|
||||||
|
"CC_CLOSE_EVT"
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* action function list */
|
||||||
|
const tAVDT_SCB_ACTION avdt_scb_action[] = {
|
||||||
|
avdt_scb_hdl_abort_cmd,
|
||||||
|
avdt_scb_hdl_abort_rsp,
|
||||||
|
avdt_scb_hdl_close_cmd,
|
||||||
|
avdt_scb_hdl_close_rsp,
|
||||||
|
avdt_scb_hdl_getconfig_cmd,
|
||||||
|
avdt_scb_hdl_getconfig_rsp,
|
||||||
|
avdt_scb_hdl_open_cmd,
|
||||||
|
avdt_scb_hdl_open_rej,
|
||||||
|
avdt_scb_hdl_open_rsp,
|
||||||
|
avdt_scb_hdl_pkt,
|
||||||
|
avdt_scb_drop_pkt,
|
||||||
|
avdt_scb_hdl_reconfig_cmd,
|
||||||
|
avdt_scb_hdl_reconfig_rsp,
|
||||||
|
avdt_scb_hdl_security_cmd,
|
||||||
|
avdt_scb_hdl_security_rsp,
|
||||||
|
avdt_scb_hdl_setconfig_cmd,
|
||||||
|
avdt_scb_hdl_setconfig_rej,
|
||||||
|
avdt_scb_hdl_setconfig_rsp,
|
||||||
|
avdt_scb_hdl_start_cmd,
|
||||||
|
avdt_scb_hdl_start_rsp,
|
||||||
|
avdt_scb_hdl_suspend_cmd,
|
||||||
|
avdt_scb_hdl_suspend_rsp,
|
||||||
|
avdt_scb_hdl_tc_close,
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
avdt_scb_hdl_tc_close_sto,
|
||||||
|
#endif
|
||||||
|
avdt_scb_hdl_tc_open,
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
avdt_scb_hdl_tc_open_sto,
|
||||||
|
#endif
|
||||||
|
avdt_scb_snd_delay_rpt_req,
|
||||||
|
avdt_scb_hdl_delay_rpt_cmd,
|
||||||
|
avdt_scb_hdl_delay_rpt_rsp,
|
||||||
|
avdt_scb_hdl_write_req,
|
||||||
|
avdt_scb_snd_abort_req,
|
||||||
|
avdt_scb_snd_abort_rsp,
|
||||||
|
avdt_scb_snd_close_req,
|
||||||
|
avdt_scb_snd_stream_close,
|
||||||
|
avdt_scb_snd_close_rsp,
|
||||||
|
avdt_scb_snd_getconfig_req,
|
||||||
|
avdt_scb_snd_getconfig_rsp,
|
||||||
|
avdt_scb_snd_open_req,
|
||||||
|
avdt_scb_snd_open_rsp,
|
||||||
|
avdt_scb_snd_reconfig_req,
|
||||||
|
avdt_scb_snd_reconfig_rsp,
|
||||||
|
avdt_scb_snd_security_req,
|
||||||
|
avdt_scb_snd_security_rsp,
|
||||||
|
avdt_scb_snd_setconfig_req,
|
||||||
|
avdt_scb_snd_setconfig_rej,
|
||||||
|
avdt_scb_snd_setconfig_rsp,
|
||||||
|
avdt_scb_snd_tc_close,
|
||||||
|
avdt_scb_cb_err,
|
||||||
|
avdt_scb_cong_state,
|
||||||
|
avdt_scb_rej_state,
|
||||||
|
avdt_scb_rej_in_use,
|
||||||
|
avdt_scb_rej_not_in_use,
|
||||||
|
avdt_scb_set_remove,
|
||||||
|
avdt_scb_free_pkt,
|
||||||
|
avdt_scb_clr_pkt,
|
||||||
|
avdt_scb_chk_snd_pkt,
|
||||||
|
avdt_scb_tc_timer,
|
||||||
|
avdt_scb_clr_vars,
|
||||||
|
avdt_scb_dealloc
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table information */
|
||||||
|
#define AVDT_SCB_ACTIONS 2 /* number of actions */
|
||||||
|
#define AVDT_SCB_NEXT_STATE 2 /* position of next state */
|
||||||
|
#define AVDT_SCB_NUM_COLS 3 /* number of columns in state tables */
|
||||||
|
|
||||||
|
/* state table for idle state */
|
||||||
|
const UINT8 avdt_scb_st_idle[][AVDT_SCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_REMOVE_EVT */ {AVDT_SCB_DEALLOC, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_SND_SETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_OPEN_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_CLOSE_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_SECURITY_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_ABORT_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_SND_SETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_SND_SETCONFIG_REJ, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_SECURITY_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_SETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_NOT_IN_USE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_SETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_HDL_SETCONFIG_REJ, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* TC_TOUT_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* TC_OPEN_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* TC_CLOSE_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* TC_CONG_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* CC_CLOSE_EVT */ {AVDT_SCB_CLR_VARS, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for configured state */
|
||||||
|
const UINT8 avdt_scb_st_conf[][AVDT_SCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_REMOVE_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_SET_REMOVE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_SND_GETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_SND_DELAY_RPT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_OPEN_REQ_EVT */ {AVDT_SCB_SND_OPEN_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_CLOSE_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_SECURITY_REQ_EVT */ {AVDT_SCB_SND_SECURITY_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_ABORT_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_SND_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_OPEN_RSP_EVT */ {AVDT_SCB_SND_OPEN_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_SECURITY_RSP_EVT */ {AVDT_SCB_SND_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_IN_USE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_GETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_HDL_OPEN_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_HDL_SECURITY_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_HDL_DELAY_RPT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_HDL_OPEN_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_HDL_ABORT_RSP, AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_HDL_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_HDL_OPEN_REJ, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* TC_TOUT_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* TC_OPEN_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* TC_CLOSE_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* TC_CONG_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_CONF_ST},
|
||||||
|
/* CC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for opening state */
|
||||||
|
const UINT8 avdt_scb_st_opening[][AVDT_SCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_REMOVE_EVT */ {AVDT_SCB_SND_CLOSE_REQ, AVDT_SCB_SET_REMOVE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_SND_GETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_SND_DELAY_RPT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_OPEN_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_CLOSE_REQ_EVT */ {AVDT_SCB_SND_CLOSE_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_SECURITY_REQ_EVT */ {AVDT_SCB_SND_SECURITY_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_ABORT_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_SND_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_CLOSE_RSP_EVT */ {AVDT_SCB_SND_CLOSE_RSP, AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_SECURITY_RSP_EVT */ {AVDT_SCB_SND_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_GETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_HDL_CLOSE_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_HDL_SECURITY_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_HDL_DELAY_RPT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_HDL_ABORT_RSP, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_HDL_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* TC_TOUT_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* TC_OPEN_EVT */ {AVDT_SCB_HDL_TC_OPEN, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* TC_CONG_EVT */ {AVDT_SCB_CONG_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_OPENING_ST},
|
||||||
|
/* CC_CLOSE_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for open state */
|
||||||
|
const UINT8 avdt_scb_st_open[][AVDT_SCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_REMOVE_EVT */ {AVDT_SCB_SND_CLOSE_REQ, AVDT_SCB_SET_REMOVE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_SND_GETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_SND_DELAY_RPT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_OPEN_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_CLOSE_REQ_EVT */ {AVDT_SCB_SND_CLOSE_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_SND_RECONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_SECURITY_REQ_EVT */ {AVDT_SCB_SND_SECURITY_REQ, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_ABORT_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_SND_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_CLOSE_RSP_EVT */ {AVDT_SCB_SND_CLOSE_RSP, AVDT_SCB_TC_TIMER, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_SND_RECONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_SECURITY_RSP_EVT */ {AVDT_SCB_SND_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_TC_TIMER, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_GETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_SCB_HDL_START_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_HDL_CLOSE_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_HDL_RECONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_HDL_SECURITY_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_HDL_DELAY_RPT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_HDL_RECONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_HDL_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* TC_TOUT_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
/* TC_OPEN_EVT */ {AVDT_SCB_HDL_TC_OPEN_STO, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE_STO, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
#else
|
||||||
|
/* TC_OPEN_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
#endif
|
||||||
|
/* TC_CONG_EVT */ {AVDT_SCB_CONG_STATE, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_OPEN_ST},
|
||||||
|
/* CC_CLOSE_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for streaming state */
|
||||||
|
const UINT8 avdt_scb_st_stream[][AVDT_SCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_REMOVE_EVT */ {AVDT_SCB_SND_STREAM_CLOSE, AVDT_SCB_SET_REMOVE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_WRITE_REQ_EVT */ {AVDT_SCB_HDL_WRITE_REQ, AVDT_SCB_CHK_SND_PKT, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_SND_GETCONFIG_REQ, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_SND_DELAY_RPT_REQ, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_OPEN_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_CLOSE_REQ_EVT */ {AVDT_SCB_SND_STREAM_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_SECURITY_REQ_EVT */ {AVDT_SCB_SND_SECURITY_REQ, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_ABORT_REQ_EVT */ {AVDT_SCB_SND_ABORT_REQ, AVDT_SCB_CLR_PKT, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_SND_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_CLOSE_RSP_EVT */ {AVDT_SCB_SND_CLOSE_RSP, AVDT_SCB_TC_TIMER, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_SECURITY_RSP_EVT */ {AVDT_SCB_SND_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_TC_TIMER, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_HDL_GETCONFIG_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_HDL_SUSPEND_CMD, AVDT_SCB_CLR_PKT, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_HDL_CLOSE_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_CLR_PKT, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_HDL_SECURITY_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_HDL_DELAY_RPT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_HDL_GETCONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_CLR_PKT, AVDT_SCB_OPEN_ST},
|
||||||
|
/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_HDL_RECONFIG_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_HDL_SECURITY_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* TC_TOUT_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* TC_OPEN_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* TC_CONG_EVT */ {AVDT_SCB_CONG_STATE, AVDT_SCB_CHK_SND_PKT, AVDT_SCB_STREAM_ST},
|
||||||
|
/* TC_DATA_EVT */ {AVDT_SCB_HDL_PKT, AVDT_SCB_IGNORE, AVDT_SCB_STREAM_ST},
|
||||||
|
/* CC_CLOSE_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state table for closing state */
|
||||||
|
const UINT8 avdt_scb_st_closing[][AVDT_SCB_NUM_COLS] = {
|
||||||
|
/* Event Action 1 Action 2 Next state */
|
||||||
|
/* API_REMOVE_EVT */ {AVDT_SCB_SET_REMOVE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_WRITE_REQ_EVT */ {AVDT_SCB_FREE_PKT, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_GETCONFIG_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_DELAY_RPT_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_SETCONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_OPEN_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_CLOSE_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_RECONFIG_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_SECURITY_REQ_EVT */ {AVDT_SCB_CB_ERR, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_ABORT_REQ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_GETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_CLOSE_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_SECURITY_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* API_ABORT_RSP_EVT */ {AVDT_SCB_SND_ABORT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_GETCONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_OPEN_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_START_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SUSPEND_CMD_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_CLOSE_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_ABORT_CMD_EVT */ {AVDT_SCB_HDL_ABORT_CMD, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_RECONFIG_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SECURITY_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_DELAY_RPT_CMD_EVT */ {AVDT_SCB_REJ_STATE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_DELAY_RPT_RSP_EVT */ {AVDT_SCB_HDL_DELAY_RPT_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_GETCONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_OPEN_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_START_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SUSPEND_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_CLOSE_RSP_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_HDL_CLOSE_RSP, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_ABORT_RSP_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_HDL_ABORT_RSP, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_RECONFIG_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SECURITY_RSP_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SETCONFIG_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_OPEN_REJ_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_START_REJ_EVT */ {AVDT_SCB_HDL_START_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* MSG_SUSPEND_REJ_EVT */ {AVDT_SCB_HDL_SUSPEND_RSP, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* TC_TOUT_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* TC_OPEN_EVT */ {AVDT_SCB_SND_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* TC_CLOSE_EVT */ {AVDT_SCB_HDL_TC_CLOSE, AVDT_SCB_IGNORE, AVDT_SCB_IDLE_ST},
|
||||||
|
/* TC_CONG_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* TC_DATA_EVT */ {AVDT_SCB_DROP_PKT, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST},
|
||||||
|
/* CC_CLOSE_EVT */ {AVDT_SCB_IGNORE, AVDT_SCB_IGNORE, AVDT_SCB_CLOSING_ST}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* type for state table */
|
||||||
|
typedef const UINT8 (*tAVDT_SCB_ST_TBL)[AVDT_SCB_NUM_COLS];
|
||||||
|
|
||||||
|
/* state table */
|
||||||
|
const tAVDT_SCB_ST_TBL avdt_scb_st_tbl[] = {
|
||||||
|
avdt_scb_st_idle,
|
||||||
|
avdt_scb_st_conf,
|
||||||
|
avdt_scb_st_opening,
|
||||||
|
avdt_scb_st_open,
|
||||||
|
avdt_scb_st_stream,
|
||||||
|
avdt_scb_st_closing
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_scb_event
|
||||||
|
**
|
||||||
|
** Description State machine event handling function for scb
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
tAVDT_SCB_ST_TBL state_table;
|
||||||
|
UINT8 action;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if AVDT_DEBUG == TRUE
|
||||||
|
AVDT_TRACE_EVENT("SCB hdl=%d event=%d/%s state=%s", avdt_scb_to_hdl(p_scb), event, avdt_scb_evt_str[event], avdt_scb_st_str[p_scb->state]);
|
||||||
|
#endif
|
||||||
|
/* set current event */
|
||||||
|
p_scb->curr_evt = event;
|
||||||
|
|
||||||
|
/* look up the state table for the current state */
|
||||||
|
state_table = avdt_scb_st_tbl[p_scb->state];
|
||||||
|
|
||||||
|
/* set next state */
|
||||||
|
if (p_scb->state != state_table[event][AVDT_SCB_NEXT_STATE]) {
|
||||||
|
p_scb->state = state_table[event][AVDT_SCB_NEXT_STATE];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* execute action functions */
|
||||||
|
for (i = 0; i < AVDT_SCB_ACTIONS; i++)
|
||||||
|
{
|
||||||
|
if ((action = state_table[event][i]) != AVDT_SCB_IGNORE)
|
||||||
|
{
|
||||||
|
(*avdt_cb.p_scb_act[action])(p_scb, p_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_scb_init
|
||||||
|
**
|
||||||
|
** Description Initialize stream control block module.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_scb_init(void)
|
||||||
|
{
|
||||||
|
memset(&avdt_cb.scb[0], 0, sizeof(tAVDT_SCB) * AVDT_NUM_SEPS);
|
||||||
|
avdt_cb.p_scb_act = (tAVDT_SCB_ACTION *) avdt_scb_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_scb_alloc
|
||||||
|
**
|
||||||
|
** Description Allocate a stream control block.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns pointer to the scb, or NULL if none could be allocated.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVDT_SCB *avdt_scb_alloc(tAVDT_CS *p_cs)
|
||||||
|
{
|
||||||
|
tAVDT_SCB *p_scb = &avdt_cb.scb[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* find available scb */
|
||||||
|
for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
|
||||||
|
{
|
||||||
|
if (!p_scb->allocated)
|
||||||
|
{
|
||||||
|
memset(p_scb,0,sizeof(tAVDT_SCB));
|
||||||
|
p_scb->allocated = TRUE;
|
||||||
|
p_scb->p_ccb = NULL;
|
||||||
|
|
||||||
|
/* initialize sink as activated */
|
||||||
|
if (p_cs->tsep == AVDT_TSEP_SNK)
|
||||||
|
{
|
||||||
|
p_scb->sink_activated = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&p_scb->cs, p_cs, sizeof(tAVDT_CS));
|
||||||
|
#if AVDT_MULTIPLEXING == TRUE
|
||||||
|
/* initialize fragments gueue */
|
||||||
|
GKI_init_q(&p_scb->frag_q);
|
||||||
|
|
||||||
|
if(p_cs->cfg.psc_mask & AVDT_PSC_MUX)
|
||||||
|
{
|
||||||
|
p_scb->cs.cfg.mux_tcid_media = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
if(p_cs->cfg.psc_mask & AVDT_PSC_REPORT)
|
||||||
|
{
|
||||||
|
p_scb->cs.cfg.mux_tcid_report = avdt_ad_type_to_tcid(AVDT_CHAN_REPORT, p_scb);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
p_scb->timer_entry.param = (UINT32) p_scb;
|
||||||
|
AVDT_TRACE_DEBUG("avdt_scb_alloc hdl=%d, psc_mask:0x%x", i+1, p_cs->cfg.psc_mask);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == AVDT_NUM_SEPS)
|
||||||
|
{
|
||||||
|
/* out of ccbs */
|
||||||
|
p_scb = NULL;
|
||||||
|
AVDT_TRACE_WARNING("Out of scbs");
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_scb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_scb_dealloc
|
||||||
|
**
|
||||||
|
** Description Deallocate a stream control block.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns void.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_scb_dealloc(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
|
||||||
|
{
|
||||||
|
#if AVDT_MULTIPLEXING == TRUE
|
||||||
|
void *p_buf;
|
||||||
|
#endif
|
||||||
|
UNUSED(p_data);
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("avdt_scb_dealloc hdl=%d", avdt_scb_to_hdl(p_scb));
|
||||||
|
btu_stop_timer(&p_scb->timer_entry);
|
||||||
|
|
||||||
|
#if AVDT_MULTIPLEXING == TRUE
|
||||||
|
/* free fragments we're holding, if any; it shouldn't happen */
|
||||||
|
while ((p_buf = GKI_dequeue (&p_scb->frag_q)) != NULL)
|
||||||
|
GKI_freebuf(p_buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memset(p_scb, 0, sizeof(tAVDT_SCB));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_scb_to_hdl
|
||||||
|
**
|
||||||
|
** Description Given a pointer to an scb, return its handle (or seid).
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Index of scb.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT8 avdt_scb_to_hdl(tAVDT_SCB *p_scb)
|
||||||
|
{
|
||||||
|
return (UINT8) (p_scb - avdt_cb.scb + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_scb_by_hdl
|
||||||
|
**
|
||||||
|
** Description Given an scb handle (or seid), return a pointer to the scb.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Pointer to scb or NULL if index is out of range or scb
|
||||||
|
** is not allocated.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
tAVDT_SCB *avdt_scb_by_hdl(UINT8 hdl)
|
||||||
|
{
|
||||||
|
tAVDT_SCB *p_scb;
|
||||||
|
|
||||||
|
/* verify index */
|
||||||
|
if ((hdl > 0) && (hdl <= AVDT_NUM_SEPS))
|
||||||
|
{
|
||||||
|
p_scb = &avdt_cb.scb[hdl - 1];
|
||||||
|
|
||||||
|
/* verify scb is allocated */
|
||||||
|
if (!p_scb->allocated)
|
||||||
|
{
|
||||||
|
p_scb = NULL;
|
||||||
|
AVDT_TRACE_WARNING("scb hdl %d not allocated", hdl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_scb = NULL;
|
||||||
|
AVDT_TRACE_WARNING("scb hdl %d out of range", hdl);
|
||||||
|
}
|
||||||
|
return p_scb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_scb_verify
|
||||||
|
**
|
||||||
|
** Description Verify the condition of a list of scbs.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns SEID that failed, or 0 if success.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
UINT8 avdt_scb_verify(tAVDT_CCB *p_ccb, UINT8 state, UINT8 *p_seid, UINT16 num_seid, UINT8 *p_err_code)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
tAVDT_SCB *p_scb;
|
||||||
|
UINT8 nsc_mask;
|
||||||
|
UINT8 ret = 0;
|
||||||
|
|
||||||
|
AVDT_TRACE_DEBUG("avdt_scb_verify state %d", state);
|
||||||
|
/* set nonsupported command mask */
|
||||||
|
/* translate public state into private state */
|
||||||
|
nsc_mask = 0;
|
||||||
|
if (state == AVDT_VERIFY_SUSPEND)
|
||||||
|
nsc_mask = AVDT_NSC_SUSPEND;
|
||||||
|
|
||||||
|
/* verify every scb */
|
||||||
|
for (i = 0, *p_err_code = 0; (i < num_seid) && (*p_err_code == 0) && (i < AVDT_NUM_SEPS); i++)
|
||||||
|
{
|
||||||
|
if ((p_scb = avdt_scb_by_hdl(p_seid[i])) == NULL)
|
||||||
|
*p_err_code = AVDT_ERR_BAD_STATE;
|
||||||
|
else if (p_scb->p_ccb != p_ccb)
|
||||||
|
*p_err_code = AVDT_ERR_BAD_STATE;
|
||||||
|
else if (p_scb->cs.nsc_mask & nsc_mask)
|
||||||
|
*p_err_code = AVDT_ERR_NSC;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case AVDT_VERIFY_OPEN:
|
||||||
|
case AVDT_VERIFY_START:
|
||||||
|
if (p_scb->state != AVDT_SCB_OPEN_ST && p_scb->state != AVDT_SCB_STREAM_ST)
|
||||||
|
*p_err_code = AVDT_ERR_BAD_STATE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVDT_VERIFY_SUSPEND:
|
||||||
|
case AVDT_VERIFY_STREAMING:
|
||||||
|
if (p_scb->state != AVDT_SCB_STREAM_ST)
|
||||||
|
*p_err_code = AVDT_ERR_BAD_STATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i != num_seid) && (i < AVDT_NUM_SEPS))
|
||||||
|
{
|
||||||
|
ret = p_seid[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function avdt_scb_peer_seid_list
|
||||||
|
**
|
||||||
|
** Description Given a list of SCB handles, return a list of peer SEIDs
|
||||||
|
** for the handles, copied in place into the struct passed in.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** Returns Nothing.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void avdt_scb_peer_seid_list(tAVDT_MULTI *p_multi)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
tAVDT_SCB *p_scb;
|
||||||
|
|
||||||
|
for (i = 0; i < p_multi->num_seps; i++)
|
||||||
|
{
|
||||||
|
if ((p_scb = avdt_scb_by_hdl(p_multi->seid_list[i])) != NULL)
|
||||||
|
{
|
||||||
|
p_multi->seid_list[i] = p_scb->peer_seid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2175
components/bt/bluedroid/stack/avdt/avdt_scb_act.c
Executable file
2175
components/bt/bluedroid/stack/avdt/avdt_scb_act.c
Executable file
File diff suppressed because it is too large
Load Diff
742
components/bt/bluedroid/stack/avdt/include/avdt_int.h
Executable file
742
components/bt/bluedroid/stack/avdt/include/avdt_int.h
Executable file
@ -0,0 +1,742 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This file contains interfaces which are internal to AVDTP.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef AVDT_INT_H
|
||||||
|
#define AVDT_INT_H
|
||||||
|
|
||||||
|
#include "gki.h"
|
||||||
|
#include "avdt_api.h"
|
||||||
|
#include "avdtc_api.h"
|
||||||
|
#include "avdt_defs.h"
|
||||||
|
#include "l2c_api.h"
|
||||||
|
#include "btm_api.h"
|
||||||
|
|
||||||
|
#ifndef AVDT_DEBUG
|
||||||
|
#define AVDT_DEBUG FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** constants
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* channel types */
|
||||||
|
enum {
|
||||||
|
AVDT_CHAN_SIG, /* signaling channel */
|
||||||
|
AVDT_CHAN_MEDIA, /* media channel */
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
AVDT_CHAN_REPORT, /* reporting channel */
|
||||||
|
#endif
|
||||||
|
AVDT_CHAN_NUM_TYPES
|
||||||
|
};
|
||||||
|
|
||||||
|
/* protocol service capabilities of this AVDTP implementation */
|
||||||
|
/* for now multiplexing will be used only for fragmentation */
|
||||||
|
#if ((AVDT_MULTIPLEXING == TRUE) && (AVDT_REPORTING == TRUE))
|
||||||
|
#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_MUX | AVDT_PSC_REPORT | AVDT_PSC_DELAY_RPT)
|
||||||
|
#define AVDT_LEG_PSC (AVDT_PSC_TRANS | AVDT_PSC_MUX | AVDT_PSC_REPORT)
|
||||||
|
#else /* AVDT_MULTIPLEXING && AVDT_REPORTING */
|
||||||
|
|
||||||
|
#if (AVDT_MULTIPLEXING == TRUE)
|
||||||
|
#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_MUX | AVDT_PSC_DELAY_RPT)
|
||||||
|
#define AVDT_LEG_PSC (AVDT_PSC_TRANS | AVDT_PSC_MUX)
|
||||||
|
#else /* AVDT_MULTIPLEXING */
|
||||||
|
|
||||||
|
#if (AVDT_REPORTING == TRUE)
|
||||||
|
#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_REPORT | AVDT_PSC_DELAY_RPT)
|
||||||
|
#define AVDT_LEG_PSC (AVDT_PSC_TRANS | AVDT_PSC_REPORT)
|
||||||
|
#else /* AVDT_REPORTING */
|
||||||
|
#define AVDT_PSC (AVDT_PSC_TRANS | AVDT_PSC_DELAY_RPT)
|
||||||
|
#define AVDT_LEG_PSC (AVDT_PSC_TRANS)
|
||||||
|
#endif /* AVDT_REPORTING */
|
||||||
|
|
||||||
|
#endif /* AVDT_MULTIPLEXING */
|
||||||
|
|
||||||
|
#endif /* AVDT_MULTIPLEXING && AVDT_REPORTING */
|
||||||
|
|
||||||
|
/* initiator/acceptor signaling roles */
|
||||||
|
#define AVDT_CLOSE_ACP 0
|
||||||
|
#define AVDT_CLOSE_INT 1
|
||||||
|
#define AVDT_OPEN_ACP 2
|
||||||
|
#define AVDT_OPEN_INT 3
|
||||||
|
|
||||||
|
/* states for avdt_scb_verify */
|
||||||
|
#define AVDT_VERIFY_OPEN 0
|
||||||
|
#define AVDT_VERIFY_STREAMING 1
|
||||||
|
#define AVDT_VERIFY_SUSPEND 2
|
||||||
|
#define AVDT_VERIFY_START 3
|
||||||
|
|
||||||
|
/* to distinguish CCB events from SCB events */
|
||||||
|
#define AVDT_CCB_MKR 0x80
|
||||||
|
|
||||||
|
/* offset where AVDTP signaling message header starts in message */
|
||||||
|
#define AVDT_HDR_OFFSET (L2CAP_MIN_OFFSET + AVDT_NUM_SEPS)
|
||||||
|
|
||||||
|
/* offset where AVDTP signaling message content starts;
|
||||||
|
** use the size of a start header since it's the largest possible
|
||||||
|
** layout of signaling message in a buffer is:
|
||||||
|
**
|
||||||
|
** | BT_HDR | SCB handles | L2CAP + HCI header | AVDTP header | data ... |
|
||||||
|
**
|
||||||
|
** Note that we "hide" the scb handles at the top of the message buffer.
|
||||||
|
*/
|
||||||
|
#define AVDT_MSG_OFFSET (L2CAP_MIN_OFFSET + AVDT_NUM_SEPS + AVDT_LEN_TYPE_START)
|
||||||
|
|
||||||
|
/* scb transport channel connect timeout value */
|
||||||
|
#define AVDT_SCB_TC_CONN_TOUT 10
|
||||||
|
|
||||||
|
/* scb transport channel disconnect timeout value */
|
||||||
|
#define AVDT_SCB_TC_DISC_TOUT 10
|
||||||
|
|
||||||
|
/* maximum number of command retransmissions */
|
||||||
|
#ifndef AVDT_RET_MAX
|
||||||
|
#define AVDT_RET_MAX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ccb state machine states */
|
||||||
|
enum {
|
||||||
|
AVDT_CCB_IDLE_ST,
|
||||||
|
AVDT_CCB_OPENING_ST,
|
||||||
|
AVDT_CCB_OPEN_ST,
|
||||||
|
AVDT_CCB_CLOSING_ST
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state machine action enumeration list */
|
||||||
|
enum {
|
||||||
|
AVDT_CCB_CHAN_OPEN,
|
||||||
|
AVDT_CCB_CHAN_CLOSE,
|
||||||
|
AVDT_CCB_CHK_CLOSE,
|
||||||
|
AVDT_CCB_HDL_DISCOVER_CMD,
|
||||||
|
AVDT_CCB_HDL_DISCOVER_RSP,
|
||||||
|
AVDT_CCB_HDL_GETCAP_CMD,
|
||||||
|
AVDT_CCB_HDL_GETCAP_RSP,
|
||||||
|
AVDT_CCB_HDL_START_CMD,
|
||||||
|
AVDT_CCB_HDL_START_RSP,
|
||||||
|
AVDT_CCB_HDL_SUSPEND_CMD,
|
||||||
|
AVDT_CCB_HDL_SUSPEND_RSP,
|
||||||
|
AVDT_CCB_SND_DISCOVER_CMD,
|
||||||
|
AVDT_CCB_SND_DISCOVER_RSP,
|
||||||
|
AVDT_CCB_SND_GETCAP_CMD,
|
||||||
|
AVDT_CCB_SND_GETCAP_RSP,
|
||||||
|
AVDT_CCB_SND_START_CMD,
|
||||||
|
AVDT_CCB_SND_START_RSP,
|
||||||
|
AVDT_CCB_SND_SUSPEND_CMD,
|
||||||
|
AVDT_CCB_SND_SUSPEND_RSP,
|
||||||
|
AVDT_CCB_CLEAR_CMDS,
|
||||||
|
AVDT_CCB_CMD_FAIL,
|
||||||
|
AVDT_CCB_FREE_CMD,
|
||||||
|
AVDT_CCB_CONG_STATE,
|
||||||
|
AVDT_CCB_RET_CMD,
|
||||||
|
AVDT_CCB_SND_CMD,
|
||||||
|
AVDT_CCB_SND_MSG,
|
||||||
|
AVDT_CCB_SET_RECONN,
|
||||||
|
AVDT_CCB_CLR_RECONN,
|
||||||
|
AVDT_CCB_CHK_RECONN,
|
||||||
|
AVDT_CCB_CHK_TIMER,
|
||||||
|
AVDT_CCB_SET_CONN,
|
||||||
|
AVDT_CCB_SET_DISCONN,
|
||||||
|
AVDT_CCB_DO_DISCONN,
|
||||||
|
AVDT_CCB_LL_CLOSED,
|
||||||
|
AVDT_CCB_LL_OPENED,
|
||||||
|
AVDT_CCB_DEALLOC,
|
||||||
|
AVDT_CCB_NUM_ACTIONS
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AVDT_CCB_IGNORE AVDT_CCB_NUM_ACTIONS
|
||||||
|
|
||||||
|
/* ccb state machine events */
|
||||||
|
enum {
|
||||||
|
AVDT_CCB_API_DISCOVER_REQ_EVT,
|
||||||
|
AVDT_CCB_API_GETCAP_REQ_EVT,
|
||||||
|
AVDT_CCB_API_START_REQ_EVT,
|
||||||
|
AVDT_CCB_API_SUSPEND_REQ_EVT,
|
||||||
|
AVDT_CCB_API_DISCOVER_RSP_EVT,
|
||||||
|
AVDT_CCB_API_GETCAP_RSP_EVT,
|
||||||
|
AVDT_CCB_API_START_RSP_EVT,
|
||||||
|
AVDT_CCB_API_SUSPEND_RSP_EVT,
|
||||||
|
AVDT_CCB_API_CONNECT_REQ_EVT,
|
||||||
|
AVDT_CCB_API_DISCONNECT_REQ_EVT,
|
||||||
|
AVDT_CCB_MSG_DISCOVER_CMD_EVT,
|
||||||
|
AVDT_CCB_MSG_GETCAP_CMD_EVT,
|
||||||
|
AVDT_CCB_MSG_START_CMD_EVT,
|
||||||
|
AVDT_CCB_MSG_SUSPEND_CMD_EVT,
|
||||||
|
AVDT_CCB_MSG_DISCOVER_RSP_EVT,
|
||||||
|
AVDT_CCB_MSG_GETCAP_RSP_EVT,
|
||||||
|
AVDT_CCB_MSG_START_RSP_EVT,
|
||||||
|
AVDT_CCB_MSG_SUSPEND_RSP_EVT,
|
||||||
|
AVDT_CCB_RCVRSP_EVT,
|
||||||
|
AVDT_CCB_SENDMSG_EVT,
|
||||||
|
AVDT_CCB_RET_TOUT_EVT,
|
||||||
|
AVDT_CCB_RSP_TOUT_EVT,
|
||||||
|
AVDT_CCB_IDLE_TOUT_EVT,
|
||||||
|
AVDT_CCB_UL_OPEN_EVT,
|
||||||
|
AVDT_CCB_UL_CLOSE_EVT,
|
||||||
|
AVDT_CCB_LL_OPEN_EVT,
|
||||||
|
AVDT_CCB_LL_CLOSE_EVT,
|
||||||
|
AVDT_CCB_LL_CONG_EVT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* scb state machine states; these state values are private to this module so
|
||||||
|
** the scb state cannot be read or set by actions functions
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
AVDT_SCB_IDLE_ST,
|
||||||
|
AVDT_SCB_CONF_ST,
|
||||||
|
AVDT_SCB_OPENING_ST,
|
||||||
|
AVDT_SCB_OPEN_ST,
|
||||||
|
AVDT_SCB_STREAM_ST,
|
||||||
|
AVDT_SCB_CLOSING_ST
|
||||||
|
};
|
||||||
|
|
||||||
|
/* state machine action enumeration list */
|
||||||
|
enum {
|
||||||
|
AVDT_SCB_HDL_ABORT_CMD,
|
||||||
|
AVDT_SCB_HDL_ABORT_RSP,
|
||||||
|
AVDT_SCB_HDL_CLOSE_CMD,
|
||||||
|
AVDT_SCB_HDL_CLOSE_RSP,
|
||||||
|
AVDT_SCB_HDL_GETCONFIG_CMD,
|
||||||
|
AVDT_SCB_HDL_GETCONFIG_RSP,
|
||||||
|
AVDT_SCB_HDL_OPEN_CMD,
|
||||||
|
AVDT_SCB_HDL_OPEN_REJ,
|
||||||
|
AVDT_SCB_HDL_OPEN_RSP,
|
||||||
|
AVDT_SCB_HDL_PKT,
|
||||||
|
AVDT_SCB_DROP_PKT,
|
||||||
|
AVDT_SCB_HDL_RECONFIG_CMD,
|
||||||
|
AVDT_SCB_HDL_RECONFIG_RSP,
|
||||||
|
AVDT_SCB_HDL_SECURITY_CMD,
|
||||||
|
AVDT_SCB_HDL_SECURITY_RSP,
|
||||||
|
AVDT_SCB_HDL_SETCONFIG_CMD,
|
||||||
|
AVDT_SCB_HDL_SETCONFIG_REJ,
|
||||||
|
AVDT_SCB_HDL_SETCONFIG_RSP,
|
||||||
|
AVDT_SCB_HDL_START_CMD,
|
||||||
|
AVDT_SCB_HDL_START_RSP,
|
||||||
|
AVDT_SCB_HDL_SUSPEND_CMD,
|
||||||
|
AVDT_SCB_HDL_SUSPEND_RSP,
|
||||||
|
AVDT_SCB_HDL_TC_CLOSE,
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
AVDT_SCB_HDL_TC_CLOSE_STO,
|
||||||
|
#endif
|
||||||
|
AVDT_SCB_HDL_TC_OPEN,
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
AVDT_SCB_HDL_TC_OPEN_STO,
|
||||||
|
#endif
|
||||||
|
AVDT_SCB_SND_DELAY_RPT_REQ,
|
||||||
|
AVDT_SCB_HDL_DELAY_RPT_CMD,
|
||||||
|
AVDT_SCB_HDL_DELAY_RPT_RSP,
|
||||||
|
AVDT_SCB_HDL_WRITE_REQ,
|
||||||
|
AVDT_SCB_SND_ABORT_REQ,
|
||||||
|
AVDT_SCB_SND_ABORT_RSP,
|
||||||
|
AVDT_SCB_SND_CLOSE_REQ,
|
||||||
|
AVDT_SCB_SND_STREAM_CLOSE,
|
||||||
|
AVDT_SCB_SND_CLOSE_RSP,
|
||||||
|
AVDT_SCB_SND_GETCONFIG_REQ,
|
||||||
|
AVDT_SCB_SND_GETCONFIG_RSP,
|
||||||
|
AVDT_SCB_SND_OPEN_REQ,
|
||||||
|
AVDT_SCB_SND_OPEN_RSP,
|
||||||
|
AVDT_SCB_SND_RECONFIG_REQ,
|
||||||
|
AVDT_SCB_SND_RECONFIG_RSP,
|
||||||
|
AVDT_SCB_SND_SECURITY_REQ,
|
||||||
|
AVDT_SCB_SND_SECURITY_RSP,
|
||||||
|
AVDT_SCB_SND_SETCONFIG_REQ,
|
||||||
|
AVDT_SCB_SND_SETCONFIG_REJ,
|
||||||
|
AVDT_SCB_SND_SETCONFIG_RSP,
|
||||||
|
AVDT_SCB_SND_TC_CLOSE,
|
||||||
|
AVDT_SCB_CB_ERR,
|
||||||
|
AVDT_SCB_CONG_STATE,
|
||||||
|
AVDT_SCB_REJ_STATE,
|
||||||
|
AVDT_SCB_REJ_IN_USE,
|
||||||
|
AVDT_SCB_REJ_NOT_IN_USE,
|
||||||
|
AVDT_SCB_SET_REMOVE,
|
||||||
|
AVDT_SCB_FREE_PKT,
|
||||||
|
AVDT_SCB_CLR_PKT,
|
||||||
|
AVDT_SCB_CHK_SND_PKT,
|
||||||
|
AVDT_SCB_TC_TIMER,
|
||||||
|
AVDT_SCB_CLR_VARS,
|
||||||
|
AVDT_SCB_DEALLOC,
|
||||||
|
AVDT_SCB_NUM_ACTIONS
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AVDT_SCB_IGNORE AVDT_SCB_NUM_ACTIONS
|
||||||
|
|
||||||
|
/* scb state machine events */
|
||||||
|
enum {
|
||||||
|
AVDT_SCB_API_REMOVE_EVT,
|
||||||
|
AVDT_SCB_API_WRITE_REQ_EVT,
|
||||||
|
AVDT_SCB_API_GETCONFIG_REQ_EVT,
|
||||||
|
AVDT_SCB_API_DELAY_RPT_REQ_EVT,
|
||||||
|
AVDT_SCB_API_SETCONFIG_REQ_EVT,
|
||||||
|
AVDT_SCB_API_OPEN_REQ_EVT,
|
||||||
|
AVDT_SCB_API_CLOSE_REQ_EVT,
|
||||||
|
AVDT_SCB_API_RECONFIG_REQ_EVT,
|
||||||
|
AVDT_SCB_API_SECURITY_REQ_EVT,
|
||||||
|
AVDT_SCB_API_ABORT_REQ_EVT,
|
||||||
|
AVDT_SCB_API_GETCONFIG_RSP_EVT,
|
||||||
|
AVDT_SCB_API_SETCONFIG_RSP_EVT,
|
||||||
|
AVDT_SCB_API_SETCONFIG_REJ_EVT,
|
||||||
|
AVDT_SCB_API_OPEN_RSP_EVT,
|
||||||
|
AVDT_SCB_API_CLOSE_RSP_EVT,
|
||||||
|
AVDT_SCB_API_RECONFIG_RSP_EVT,
|
||||||
|
AVDT_SCB_API_SECURITY_RSP_EVT,
|
||||||
|
AVDT_SCB_API_ABORT_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_SETCONFIG_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_GETCONFIG_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_OPEN_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_START_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_SUSPEND_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_CLOSE_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_ABORT_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_RECONFIG_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_SECURITY_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_DELAY_RPT_CMD_EVT,
|
||||||
|
AVDT_SCB_MSG_DELAY_RPT_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_SETCONFIG_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_GETCONFIG_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_OPEN_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_START_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_SUSPEND_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_CLOSE_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_ABORT_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_RECONFIG_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_SECURITY_RSP_EVT,
|
||||||
|
AVDT_SCB_MSG_SETCONFIG_REJ_EVT,
|
||||||
|
AVDT_SCB_MSG_OPEN_REJ_EVT,
|
||||||
|
AVDT_SCB_MSG_START_REJ_EVT,
|
||||||
|
AVDT_SCB_MSG_SUSPEND_REJ_EVT,
|
||||||
|
AVDT_SCB_TC_TOUT_EVT,
|
||||||
|
AVDT_SCB_TC_OPEN_EVT,
|
||||||
|
AVDT_SCB_TC_CLOSE_EVT,
|
||||||
|
AVDT_SCB_TC_CONG_EVT,
|
||||||
|
AVDT_SCB_TC_DATA_EVT,
|
||||||
|
AVDT_SCB_CC_CLOSE_EVT
|
||||||
|
};
|
||||||
|
|
||||||
|
/* adaption layer number of stream routing table entries */
|
||||||
|
#if AVDT_REPORTING == TRUE
|
||||||
|
/* 2 channels(1 media, 1 report) for each SEP and one for signalling */
|
||||||
|
#define AVDT_NUM_RT_TBL ((AVDT_NUM_SEPS<<1) + 1)
|
||||||
|
#else
|
||||||
|
#define AVDT_NUM_RT_TBL (AVDT_NUM_SEPS + 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* adaption layer number of transport channel table entries - moved to target.h
|
||||||
|
#define AVDT_NUM_TC_TBL (AVDT_NUM_SEPS + AVDT_NUM_LINKS) */
|
||||||
|
|
||||||
|
/* "states" used in transport channel table */
|
||||||
|
#define AVDT_AD_ST_UNUSED 0 /* Unused - unallocated */
|
||||||
|
#define AVDT_AD_ST_IDLE 1 /* No connection */
|
||||||
|
#define AVDT_AD_ST_ACP 2 /* Waiting to accept a connection */
|
||||||
|
#define AVDT_AD_ST_INT 3 /* Initiating a connection */
|
||||||
|
#define AVDT_AD_ST_CONN 4 /* Waiting for connection confirm */
|
||||||
|
#define AVDT_AD_ST_CFG 5 /* Waiting for configuration complete */
|
||||||
|
#define AVDT_AD_ST_OPEN 6 /* Channel opened */
|
||||||
|
#define AVDT_AD_ST_SEC_INT 7 /* Security process as INT */
|
||||||
|
#define AVDT_AD_ST_SEC_ACP 8 /* Security process as ACP */
|
||||||
|
|
||||||
|
/* Configuration flags. tAVDT_TC_TBL.cfg_flags */
|
||||||
|
#define AVDT_L2C_CFG_IND_DONE (1<<0)
|
||||||
|
#define AVDT_L2C_CFG_CFM_DONE (1<<1)
|
||||||
|
#define AVDT_L2C_CFG_CONN_INT (1<<2)
|
||||||
|
#define AVDT_L2C_CFG_CONN_ACP (1<<3)
|
||||||
|
|
||||||
|
|
||||||
|
/* result code for avdt_ad_write_req() (L2CA_DataWrite()) */
|
||||||
|
#define AVDT_AD_FAILED L2CAP_DW_FAILED /* FALSE */
|
||||||
|
#define AVDT_AD_SUCCESS L2CAP_DW_SUCCESS /* TRUE */
|
||||||
|
#define AVDT_AD_CONGESTED L2CAP_DW_CONGESTED /* 2 */
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** data types
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* msg union of all message parameter types */
|
||||||
|
typedef union {
|
||||||
|
tAVDT_EVT_HDR hdr;
|
||||||
|
tAVDT_EVT_HDR single;
|
||||||
|
tAVDT_SETCONFIG config_cmd;
|
||||||
|
tAVDT_CONFIG reconfig_cmd;
|
||||||
|
tAVDT_MULTI multi;
|
||||||
|
tAVDT_SECURITY security_cmd;
|
||||||
|
tAVDT_DISCOVER discover_rsp;
|
||||||
|
tAVDT_CONFIG svccap;
|
||||||
|
tAVDT_SECURITY security_rsp;
|
||||||
|
tAVDT_DELAY_RPT delay_rpt_cmd;
|
||||||
|
} tAVDT_MSG;
|
||||||
|
|
||||||
|
/* data type for AVDT_CCB_API_DISCOVER_REQ_EVT */
|
||||||
|
typedef struct {
|
||||||
|
tAVDT_CTRL_CBACK *p_cback;
|
||||||
|
tAVDT_SEP_INFO *p_sep_info;
|
||||||
|
UINT8 num_seps;
|
||||||
|
} tAVDT_CCB_API_DISCOVER;
|
||||||
|
|
||||||
|
/* data type for AVDT_CCB_API_GETCAP_REQ_EVT */
|
||||||
|
typedef struct {
|
||||||
|
tAVDT_EVT_HDR single;
|
||||||
|
tAVDT_CTRL_CBACK *p_cback;
|
||||||
|
tAVDT_CFG *p_cfg;
|
||||||
|
} tAVDT_CCB_API_GETCAP;
|
||||||
|
|
||||||
|
/* data type for AVDT_CCB_API_CONNECT_REQ_EVT */
|
||||||
|
typedef struct {
|
||||||
|
tAVDT_CTRL_CBACK *p_cback;
|
||||||
|
UINT8 sec_mask;
|
||||||
|
} tAVDT_CCB_API_CONNECT;
|
||||||
|
|
||||||
|
/* data type for AVDT_CCB_API_DISCONNECT_REQ_EVT */
|
||||||
|
typedef struct {
|
||||||
|
tAVDT_CTRL_CBACK *p_cback;
|
||||||
|
} tAVDT_CCB_API_DISCONNECT;
|
||||||
|
|
||||||
|
/* union associated with ccb state machine events */
|
||||||
|
typedef union {
|
||||||
|
tAVDT_CCB_API_DISCOVER discover;
|
||||||
|
tAVDT_CCB_API_GETCAP getcap;
|
||||||
|
tAVDT_CCB_API_CONNECT connect;
|
||||||
|
tAVDT_CCB_API_DISCONNECT disconnect;
|
||||||
|
tAVDT_MSG msg;
|
||||||
|
BOOLEAN llcong;
|
||||||
|
UINT8 err_code;
|
||||||
|
} tAVDT_CCB_EVT;
|
||||||
|
|
||||||
|
/* channel control block type */
|
||||||
|
typedef struct {
|
||||||
|
BD_ADDR peer_addr; /* BD address of peer */
|
||||||
|
TIMER_LIST_ENT timer_entry; /* CCB timer list entry */
|
||||||
|
BUFFER_Q cmd_q; /* Queue for outgoing command messages */
|
||||||
|
BUFFER_Q rsp_q; /* Queue for outgoing response and reject messages */
|
||||||
|
tAVDT_CTRL_CBACK *proc_cback; /* Procedure callback function */
|
||||||
|
tAVDT_CTRL_CBACK *p_conn_cback; /* Connection/disconnection callback function */
|
||||||
|
void *p_proc_data; /* Pointer to data storage for procedure */
|
||||||
|
BT_HDR *p_curr_cmd; /* Current command being sent awaiting response */
|
||||||
|
BT_HDR *p_curr_msg; /* Current message being sent */
|
||||||
|
BT_HDR *p_rx_msg; /* Current message being received */
|
||||||
|
BOOLEAN allocated; /* Whether ccb is allocated */
|
||||||
|
UINT8 state; /* The CCB state machine state */
|
||||||
|
BOOLEAN ll_opened; /* TRUE if LL is opened */
|
||||||
|
BOOLEAN proc_busy; /* TRUE when a discover or get capabilities procedure in progress */
|
||||||
|
UINT8 proc_param; /* Procedure parameter; either SEID for get capabilities or number of SEPS for discover */
|
||||||
|
BOOLEAN cong; /* Whether signaling channel is congested */
|
||||||
|
UINT8 label; /* Message header "label" (sequence number) */
|
||||||
|
BOOLEAN reconn; /* If TRUE, reinitiate connection after transitioning from CLOSING to IDLE state */
|
||||||
|
UINT8 ret_count; /* Command retransmission count */
|
||||||
|
} tAVDT_CCB;
|
||||||
|
|
||||||
|
/* type for action functions */
|
||||||
|
typedef void (*tAVDT_CCB_ACTION)(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
|
||||||
|
/* type for AVDT_SCB_API_WRITE_REQ_EVT */
|
||||||
|
typedef struct {
|
||||||
|
BT_HDR *p_buf;
|
||||||
|
UINT32 time_stamp;
|
||||||
|
#if AVDT_MULTIPLEXING == TRUE
|
||||||
|
BUFFER_Q frag_q; /* Queue for outgoing media fragments. p_buf should be 0 */
|
||||||
|
UINT8 *p_data;
|
||||||
|
UINT32 data_len;
|
||||||
|
#endif
|
||||||
|
UINT8 m_pt;
|
||||||
|
tAVDT_DATA_OPT_MASK opt;
|
||||||
|
} tAVDT_SCB_APIWRITE;
|
||||||
|
|
||||||
|
/* type for AVDT_SCB_TC_CLOSE_EVT */
|
||||||
|
typedef struct {
|
||||||
|
UINT8 old_tc_state; /* channel state before closed */
|
||||||
|
UINT8 tcid; /* TCID */
|
||||||
|
UINT8 type; /* channel type */
|
||||||
|
} tAVDT_SCB_TC_CLOSE;
|
||||||
|
|
||||||
|
/* type for scb event data */
|
||||||
|
typedef union {
|
||||||
|
tAVDT_MSG msg;
|
||||||
|
tAVDT_SCB_APIWRITE apiwrite;
|
||||||
|
tAVDT_DELAY_RPT apidelay;
|
||||||
|
tAVDT_OPEN open;
|
||||||
|
tAVDT_SCB_TC_CLOSE close;
|
||||||
|
BOOLEAN llcong;
|
||||||
|
BT_HDR *p_pkt;
|
||||||
|
} tAVDT_SCB_EVT;
|
||||||
|
|
||||||
|
/* stream control block type */
|
||||||
|
typedef struct {
|
||||||
|
tAVDT_CS cs; /* stream creation struct */
|
||||||
|
tAVDT_CFG curr_cfg; /* current configuration */
|
||||||
|
tAVDT_CFG req_cfg; /* requested configuration */
|
||||||
|
TIMER_LIST_ENT timer_entry; /* timer entry */
|
||||||
|
BT_HDR *p_pkt; /* packet waiting to be sent */
|
||||||
|
tAVDT_CCB *p_ccb; /* ccb associated with this scb */
|
||||||
|
UINT16 media_seq; /* media packet sequence number */
|
||||||
|
BOOLEAN allocated; /* whether scb is allocated or unused */
|
||||||
|
BOOLEAN in_use; /* whether stream being used by peer */
|
||||||
|
BOOLEAN sink_activated; /* A2DP Sink activated/de-activated from Application */
|
||||||
|
UINT8 role; /* initiator/acceptor role in current procedure */
|
||||||
|
BOOLEAN remove; /* whether CB is marked for removal */
|
||||||
|
UINT8 state; /* state machine state */
|
||||||
|
UINT8 peer_seid; /* SEID of peer stream */
|
||||||
|
UINT8 curr_evt; /* current event; set only by state machine */
|
||||||
|
BOOLEAN cong; /* Whether media transport channel is congested */
|
||||||
|
UINT8 close_code; /* Error code received in close response */
|
||||||
|
#if AVDT_MULTIPLEXING == TRUE
|
||||||
|
BUFFER_Q frag_q; /* Queue for outgoing media fragments */
|
||||||
|
UINT32 frag_off; /* length of already received media fragments */
|
||||||
|
UINT32 frag_org_len; /* original length before fragmentation of receiving media packet */
|
||||||
|
UINT8 *p_next_frag; /* next fragment to send */
|
||||||
|
UINT8 *p_media_buf; /* buffer for media packet assigned by AVDT_SetMediaBuf */
|
||||||
|
UINT32 media_buf_len; /* length of buffer for media packet assigned by AVDT_SetMediaBuf */
|
||||||
|
#endif
|
||||||
|
} tAVDT_SCB;
|
||||||
|
|
||||||
|
/* type for action functions */
|
||||||
|
typedef void (*tAVDT_SCB_ACTION)(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
|
||||||
|
/* adaption layer type for transport channel table */
|
||||||
|
typedef struct {
|
||||||
|
UINT16 peer_mtu; /* L2CAP mtu of the peer device */
|
||||||
|
UINT16 my_mtu; /* Our MTU for this channel */
|
||||||
|
UINT16 my_flush_to; /* Our flush timeout for this channel */
|
||||||
|
UINT16 lcid;
|
||||||
|
UINT8 tcid; /* transport channel id */
|
||||||
|
UINT8 ccb_idx; /* channel control block associated with this tc */
|
||||||
|
UINT8 state; /* transport channel state */
|
||||||
|
UINT8 cfg_flags; /* L2CAP configuration flags */
|
||||||
|
UINT8 id;
|
||||||
|
} tAVDT_TC_TBL;
|
||||||
|
|
||||||
|
/* adaption layer type for stream routing table */
|
||||||
|
typedef struct {
|
||||||
|
UINT16 lcid; /* L2CAP LCID of the associated transport channel */
|
||||||
|
UINT8 scb_hdl; /* stream control block associated with this tc */
|
||||||
|
} tAVDT_RT_TBL;
|
||||||
|
|
||||||
|
|
||||||
|
/* adaption layer control block */
|
||||||
|
typedef struct {
|
||||||
|
tAVDT_RT_TBL rt_tbl[AVDT_NUM_LINKS][AVDT_NUM_RT_TBL];
|
||||||
|
tAVDT_TC_TBL tc_tbl[AVDT_NUM_TC_TBL];
|
||||||
|
UINT8 lcid_tbl[MAX_L2CAP_CHANNELS]; /* map LCID to tc_tbl index */
|
||||||
|
} tAVDT_AD;
|
||||||
|
|
||||||
|
/* Control block for AVDT */
|
||||||
|
typedef struct {
|
||||||
|
tAVDT_REG rcb; /* registration control block */
|
||||||
|
tAVDT_CCB ccb[AVDT_NUM_LINKS]; /* channel control blocks */
|
||||||
|
tAVDT_SCB scb[AVDT_NUM_SEPS]; /* stream control blocks */
|
||||||
|
tAVDT_AD ad; /* adaption layer control block */
|
||||||
|
tAVDTC_CTRL_CBACK *p_conf_cback; /* conformance callback function */
|
||||||
|
tAVDT_CCB_ACTION *p_ccb_act; /* pointer to CCB action functions */
|
||||||
|
tAVDT_SCB_ACTION *p_scb_act; /* pointer to SCB action functions */
|
||||||
|
tAVDT_CTRL_CBACK *p_conn_cback; /* connection callback function */
|
||||||
|
UINT8 trace_level; /* trace level */
|
||||||
|
} tAVDT_CB;
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** function declarations
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* CCB function declarations */
|
||||||
|
extern void avdt_ccb_init(void);
|
||||||
|
extern void avdt_ccb_event(tAVDT_CCB *p_ccb, UINT8 event, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern tAVDT_CCB *avdt_ccb_by_bd(BD_ADDR bd_addr);
|
||||||
|
extern tAVDT_CCB *avdt_ccb_alloc(BD_ADDR bd_addr);
|
||||||
|
extern void avdt_ccb_dealloc(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern UINT8 avdt_ccb_to_idx(tAVDT_CCB *p_ccb);
|
||||||
|
extern tAVDT_CCB *avdt_ccb_by_idx(UINT8 idx);
|
||||||
|
|
||||||
|
/* CCB action functions */
|
||||||
|
extern void avdt_ccb_chan_open(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_chan_close(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_chk_close(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_hdl_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_hdl_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_hdl_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_hdl_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_hdl_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_discover_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_getcap_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_clear_cmds(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_free_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_cong_state(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_ret_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_snd_msg(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_set_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_clr_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_chk_reconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_chk_timer(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_set_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_do_disconn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_ll_closed(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
extern void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data);
|
||||||
|
|
||||||
|
/* SCB function prototypes */
|
||||||
|
extern void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_init(void);
|
||||||
|
extern tAVDT_SCB *avdt_scb_alloc(tAVDT_CS *p_cs);
|
||||||
|
extern void avdt_scb_dealloc(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern UINT8 avdt_scb_to_hdl(tAVDT_SCB *p_scb);
|
||||||
|
extern tAVDT_SCB *avdt_scb_by_hdl(UINT8 hdl);
|
||||||
|
extern UINT8 avdt_scb_verify(tAVDT_CCB *p_ccb, UINT8 state, UINT8 *p_seid, UINT16 num_seid, UINT8 *p_err_code);
|
||||||
|
extern void avdt_scb_peer_seid_list(tAVDT_MULTI *p_multi);
|
||||||
|
extern UINT32 avdt_scb_gen_ssrc(tAVDT_SCB *p_scb);
|
||||||
|
|
||||||
|
/* SCB action functions */
|
||||||
|
extern void avdt_scb_hdl_abort_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_abort_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_close_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_close_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_getconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_getconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_open_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_open_rej(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_open_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_drop_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_reconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_reconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_security_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_security_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_setconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_setconfig_rej(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_setconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_start_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_start_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_suspend_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_suspend_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_delay_rpt_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_delay_rpt_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_delay_rpt_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_tc_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_tc_open(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_tc_close_sto(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_tc_open_sto(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_hdl_write_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_abort_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_abort_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_close_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_stream_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_close_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_getconfig_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_getconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_open_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_open_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_reconfig_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_reconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_security_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_security_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_setconfig_req(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_setconfig_rej(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_setconfig_rsp(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_snd_tc_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_cb_err(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_cong_state(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_rej_state(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_rej_in_use(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_rej_not_in_use(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_set_remove(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_free_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_chk_snd_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_clr_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_tc_timer(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_clr_vars(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data);
|
||||||
|
extern void avdt_scb_queue_frags(tAVDT_SCB *p_scb, UINT8 **pp_data, UINT32 *p_data_len, BUFFER_Q *pq);
|
||||||
|
|
||||||
|
/* msg function declarations */
|
||||||
|
extern BOOLEAN avdt_msg_send(tAVDT_CCB *p_ccb, BT_HDR *p_msg);
|
||||||
|
extern void avdt_msg_send_cmd(tAVDT_CCB *p_ccb, void *p_scb, UINT8 sig_id, tAVDT_MSG *p_params);
|
||||||
|
extern void avdt_msg_send_rsp(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params);
|
||||||
|
extern void avdt_msg_send_rej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params);
|
||||||
|
extern void avdt_msg_send_grej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params);
|
||||||
|
extern void avdt_msg_ind(tAVDT_CCB *p_ccb, BT_HDR *p_buf);
|
||||||
|
|
||||||
|
/* adaption layer function declarations */
|
||||||
|
extern void avdt_ad_init(void);
|
||||||
|
extern UINT8 avdt_ad_type_to_tcid(UINT8 type, tAVDT_SCB *p_scb);
|
||||||
|
extern tAVDT_TC_TBL *avdt_ad_tc_tbl_by_st(UINT8 type, tAVDT_CCB *p_ccb, UINT8 state);
|
||||||
|
extern tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid);
|
||||||
|
extern tAVDT_TC_TBL *avdt_ad_tc_tbl_alloc(tAVDT_CCB *p_ccb);
|
||||||
|
extern UINT8 avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL *p_tbl);
|
||||||
|
extern void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason);
|
||||||
|
extern void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl);
|
||||||
|
extern void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested);
|
||||||
|
extern void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf);
|
||||||
|
extern tAVDT_TC_TBL *avdt_ad_tc_tbl_by_type(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb);
|
||||||
|
extern UINT8 avdt_ad_write_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, BT_HDR *p_buf);
|
||||||
|
extern void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role);
|
||||||
|
extern void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb);
|
||||||
|
|
||||||
|
extern void avdt_process_timeout(TIMER_LIST_ENT *p_tle);
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** macros
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* we store the scb and the label in the layer_specific field of the
|
||||||
|
** current cmd
|
||||||
|
*/
|
||||||
|
#define AVDT_BLD_LAYERSPEC(ls, msg, label) \
|
||||||
|
ls = (((label) << 4) | (msg))
|
||||||
|
|
||||||
|
#define AVDT_LAYERSPEC_LABEL(ls) ((UINT8)((ls) >> 4))
|
||||||
|
|
||||||
|
#define AVDT_LAYERSPEC_MSG(ls) ((UINT8)((ls) & 0x000F))
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** global data
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
** Main Control Block
|
||||||
|
*******************************************************************************/
|
||||||
|
#if AVDT_DYNAMIC_MEMORY == FALSE
|
||||||
|
extern tAVDT_CB avdt_cb;
|
||||||
|
#else
|
||||||
|
extern tAVDT_CB *avdt_cb_ptr;
|
||||||
|
#define avdt_cb (*avdt_cb_ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* L2CAP callback registration structure */
|
||||||
|
extern const tL2CAP_APPL_INFO avdt_l2c_appl;
|
||||||
|
|
||||||
|
/* reject message event lookup table */
|
||||||
|
extern const UINT8 avdt_msg_rej_2_evt[];
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AVDT_INT_H */
|
@ -21,8 +21,10 @@
|
|||||||
* Interface to AVRCP mandatory commands
|
* Interface to AVRCP mandatory commands
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#include <string.h>
|
// #include <assert.h>
|
||||||
#include "bt_trace.h"
|
#include "bt_trace.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "gki.h"
|
#include "gki.h"
|
||||||
#include "avrc_api.h"
|
#include "avrc_api.h"
|
||||||
#include "avrc_int.h"
|
#include "avrc_int.h"
|
@ -21,6 +21,7 @@
|
|||||||
#include "avrc_api.h"
|
#include "avrc_api.h"
|
||||||
#include "avrc_defs.h"
|
#include "avrc_defs.h"
|
||||||
#include "avrc_int.h"
|
#include "avrc_int.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Global data
|
** Global data
|
@ -21,8 +21,10 @@
|
|||||||
* Interface to AVRCP optional commands
|
* Interface to AVRCP optional commands
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
// #include <assert.h>
|
||||||
|
#include "bt_target.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "bt_trace.h"
|
|
||||||
#include "gki.h"
|
#include "gki.h"
|
||||||
#include "avrc_api.h"
|
#include "avrc_api.h"
|
||||||
#include "avrc_int.h"
|
#include "avrc_int.h"
|
@ -21,6 +21,7 @@
|
|||||||
#include "avrc_api.h"
|
#include "avrc_api.h"
|
||||||
#include "avrc_defs.h"
|
#include "avrc_defs.h"
|
||||||
#include "avrc_int.h"
|
#include "avrc_int.h"
|
||||||
|
#include "bt_utils.h"
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Global data
|
** Global data
|
@ -26,7 +26,7 @@
|
|||||||
#ifndef AVRC_INT_H
|
#ifndef AVRC_INT_H
|
||||||
#define AVRC_INT_H
|
#define AVRC_INT_H
|
||||||
|
|
||||||
//#include "avct_defs.h"
|
#include "avct_defs.h"
|
||||||
#include "avrc_api.h"
|
#include "avrc_api.h"
|
||||||
|
|
||||||
/* DEBUG FLAGS
|
/* DEBUG FLAGS
|
257
components/bt/bluedroid/stack/include/a2d_api.h
Executable file
257
components/bt/bluedroid/stack/include/a2d_api.h
Executable file
@ -0,0 +1,257 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2000-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* nterface to A2DP Application Programming Interface
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef A2D_API_H
|
||||||
|
#define A2D_API_H
|
||||||
|
#include "sdp_api.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** constants
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* Profile supported features */
|
||||||
|
#define A2D_SUPF_PLAYER 0x0001
|
||||||
|
#define A2D_SUPF_MIC 0x0002
|
||||||
|
#define A2D_SUPF_TUNER 0x0004
|
||||||
|
#define A2D_SUPF_MIXER 0x0008
|
||||||
|
|
||||||
|
#define A2D_SUPF_HEADPHONE 0x0001
|
||||||
|
#define A2D_SUPF_SPEAKER 0x0002
|
||||||
|
#define A2D_SUPF_RECORDER 0x0004
|
||||||
|
#define A2D_SUPF_AMP 0x0008
|
||||||
|
|
||||||
|
/* AV Media Types */
|
||||||
|
#define A2D_MEDIA_TYPE_AUDIO 0x00 /* audio media type + RFA */
|
||||||
|
#define A2D_MEDIA_TYPE_VIDEO 0x10 /* video media type + RFA */
|
||||||
|
#define A2D_MEDIA_TYPE_MULTI 0x20 /* multimedia media type + RFA */
|
||||||
|
|
||||||
|
/* AV Media Codec Type (Audio Codec ID) */
|
||||||
|
#define A2D_MEDIA_CT_SBC 0x00 /* SBC media codec type */
|
||||||
|
#define A2D_MEDIA_CT_M12 0x01 /* MPEG-1, 2 Audio media codec type */
|
||||||
|
#define A2D_MEDIA_CT_M24 0x02 /* MPEG-2, 4 AAC media codec type */
|
||||||
|
#define A2D_MEDIA_CT_ATRAC 0x04 /* ATRAC family media codec type */
|
||||||
|
|
||||||
|
#define A2D_SUCCESS 0 /* Success */
|
||||||
|
#define A2D_FAIL 0x0A /* Failed */
|
||||||
|
#define A2D_BUSY 0x0B /* A2D_FindService is already in progress */
|
||||||
|
#define A2D_INVALID_PARAMS 0x0C /* bad parameters */
|
||||||
|
#define A2D_WRONG_CODEC 0x0D /* wrong codec info */
|
||||||
|
#define A2D_BAD_CODEC_TYPE 0xC1 /* Media Codec Type is not valid */
|
||||||
|
#define A2D_NS_CODEC_TYPE 0xC2 /* Media Codec Type is not supported */
|
||||||
|
#define A2D_BAD_SAMP_FREQ 0xC3 /* Sampling Frequency is not valid or multiple values have been selected */
|
||||||
|
#define A2D_NS_SAMP_FREQ 0xC4 /* Sampling Frequency is not supported */
|
||||||
|
#define A2D_BAD_CH_MODE 0xC5 /* Channel Mode is not valid or multiple values have been selected */
|
||||||
|
#define A2D_NS_CH_MODE 0xC6 /* Channel Mode is not supported */
|
||||||
|
#define A2D_BAD_SUBBANDS 0xC7 /* None or multiple values have been selected for Number of Subbands */
|
||||||
|
#define A2D_NS_SUBBANDS 0xC8 /* Number of Subbands is not supported */
|
||||||
|
#define A2D_BAD_ALLOC_MTHD 0xC9 /* None or multiple values have been selected for Allocation Method */
|
||||||
|
#define A2D_NS_ALLOC_MTHD 0xCA /* Allocation Method is not supported */
|
||||||
|
#define A2D_BAD_MIN_BITPOOL 0xCB /* Minimum Bitpool Value is not valid */
|
||||||
|
#define A2D_NS_MIN_BITPOOL 0xCC /* Minimum Bitpool Value is not supported */
|
||||||
|
#define A2D_BAD_MAX_BITPOOL 0xCD /* Maximum Bitpool Value is not valid */
|
||||||
|
#define A2D_NS_MAX_BITPOOL 0xCE /* Maximum Bitpool Value is not supported */
|
||||||
|
#define A2D_BAD_LAYER 0xCF /* None or multiple values have been selected for Layer */
|
||||||
|
#define A2D_NS_LAYER 0xD0 /* Layer is not supported */
|
||||||
|
#define A2D_NS_CRC 0xD1 /* CRC is not supported */
|
||||||
|
#define A2D_NS_MPF 0xD2 /* MPF-2 is not supported */
|
||||||
|
#define A2D_NS_VBR 0xD3 /* VBR is not supported */
|
||||||
|
#define A2D_BAD_BIT_RATE 0xD4 /* None or multiple values have been selected for Bit Rate */
|
||||||
|
#define A2D_NS_BIT_RATE 0xD5 /* Bit Rate is not supported */
|
||||||
|
#define A2D_BAD_OBJ_TYPE 0xD6 /* Either 1) Object type is not valid (b3-b0) or 2) None or multiple values have been selected for Object Type */
|
||||||
|
#define A2D_NS_OBJ_TYPE 0xD7 /* Object type is not supported */
|
||||||
|
#define A2D_BAD_CHANNEL 0xD8 /* None or multiple values have been selected for Channels */
|
||||||
|
#define A2D_NS_CHANNEL 0xD9 /* Channels is not supported */
|
||||||
|
#define A2D_BAD_BLOCK_LEN 0xDD /* None or multiple values have been selected for Block Length */
|
||||||
|
#define A2D_BAD_CP_TYPE 0xE0 /* The requested CP Type is not supported. */
|
||||||
|
#define A2D_BAD_CP_FORMAT 0xE1 /* The format of Content Protection Service Capability/Content Protection Scheme Dependent Data is not correct. */
|
||||||
|
|
||||||
|
typedef UINT8 tA2D_STATUS;
|
||||||
|
|
||||||
|
/* the return values from A2D_BitsSet() */
|
||||||
|
#define A2D_SET_ONE_BIT 1 /* one and only one bit is set */
|
||||||
|
#define A2D_SET_ZERO_BIT 0 /* all bits clear */
|
||||||
|
#define A2D_SET_MULTL_BIT 2 /* multiple bits are set */
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** type definitions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* This data type is used in A2D_FindService() to initialize the SDP database
|
||||||
|
* to hold the result service search. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT32 db_len; /* Length, in bytes, of the discovery database */
|
||||||
|
UINT16 num_attr;/* The number of attributes in p_attrs */
|
||||||
|
tSDP_DISCOVERY_DB *p_db; /* Pointer to the discovery database */
|
||||||
|
UINT16 *p_attrs; /* The attributes filter. If NULL, A2DP API sets the attribute filter
|
||||||
|
* to be ATTR_ID_SERVICE_CLASS_ID_LIST, ATTR_ID_BT_PROFILE_DESC_LIST,
|
||||||
|
* ATTR_ID_SUPPORTED_FEATURES, ATTR_ID_SERVICE_NAME and ATTR_ID_PROVIDER_NAME.
|
||||||
|
* If not NULL, the input is taken as the filter. */
|
||||||
|
} tA2D_SDP_DB_PARAMS;
|
||||||
|
|
||||||
|
/* This data type is used in tA2D_FIND_CBACK to report the result of the SDP discovery process. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT16 service_len; /* Length, in bytes, of the service name */
|
||||||
|
UINT16 provider_len; /* Length, in bytes, of the provider name */
|
||||||
|
char * p_service_name; /* Pointer the service name. This character string may not be null terminated.
|
||||||
|
* Use the service_len parameter to safely copy this string */
|
||||||
|
char * p_provider_name;/* Pointer the provider name. This character string may not be null terminated.
|
||||||
|
* Use the provider_len parameter to safely copy this string */
|
||||||
|
UINT16 features; /* Profile supported features */
|
||||||
|
UINT16 avdt_version; /* AVDTP protocol version */
|
||||||
|
} tA2D_Service;
|
||||||
|
|
||||||
|
/* This is the callback to notify the result of the SDP discovery process. */
|
||||||
|
typedef void (tA2D_FIND_CBACK)(BOOLEAN found, tA2D_Service * p_service);
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** external function declarations
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_AddRecord
|
||||||
|
**
|
||||||
|
** Description This function is called by a server application to add
|
||||||
|
** SRC or SNK information to an SDP record. Prior to
|
||||||
|
** calling this function the application must call
|
||||||
|
** SDP_CreateRecord() to create an SDP record.
|
||||||
|
**
|
||||||
|
** Input Parameters:
|
||||||
|
** service_uuid: Indicates SRC or SNK.
|
||||||
|
**
|
||||||
|
** p_service_name: Pointer to a null-terminated character
|
||||||
|
** string containing the service name.
|
||||||
|
**
|
||||||
|
** p_provider_name: Pointer to a null-terminated character
|
||||||
|
** string containing the provider name.
|
||||||
|
**
|
||||||
|
** features: Profile supported features.
|
||||||
|
**
|
||||||
|
** sdp_handle: SDP handle returned by SDP_CreateRecord().
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** None.
|
||||||
|
**
|
||||||
|
** Returns A2D_SUCCESS if function execution succeeded,
|
||||||
|
** A2D_INVALID_PARAMS if bad parameters are given.
|
||||||
|
** A2D_FAIL if function execution failed.
|
||||||
|
**
|
||||||
|
******************************************************************************/
|
||||||
|
extern tA2D_STATUS A2D_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provider_name,
|
||||||
|
UINT16 features, UINT32 sdp_handle);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_FindService
|
||||||
|
**
|
||||||
|
** Description This function is called by a client application to
|
||||||
|
** perform service discovery and retrieve SRC or SNK SDP
|
||||||
|
** record information from a server. 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
|
||||||
|
** A2D_FindService() at a time; the application must wait
|
||||||
|
** for the callback before it makes another call to
|
||||||
|
** the function.
|
||||||
|
**
|
||||||
|
** Input Parameters:
|
||||||
|
** service_uuid: Indicates SRC or SNK.
|
||||||
|
**
|
||||||
|
** bd_addr: BD address of the peer device.
|
||||||
|
**
|
||||||
|
** p_db: Pointer to the information to initialize
|
||||||
|
** the discovery database.
|
||||||
|
**
|
||||||
|
** p_cback: Pointer to the A2D_FindService()
|
||||||
|
** callback function.
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** None.
|
||||||
|
**
|
||||||
|
** Returns A2D_SUCCESS if function execution succeeded,
|
||||||
|
** A2D_INVALID_PARAMS if bad parameters are given.
|
||||||
|
** A2D_BUSY if discovery is already in progress.
|
||||||
|
** A2D_FAIL if function execution failed.
|
||||||
|
**
|
||||||
|
******************************************************************************/
|
||||||
|
extern tA2D_STATUS A2D_FindService(UINT16 service_uuid, BD_ADDR bd_addr,
|
||||||
|
tA2D_SDP_DB_PARAMS *p_db, tA2D_FIND_CBACK *p_cback);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_SetTraceLevel
|
||||||
|
**
|
||||||
|
** Description Sets the trace level for A2D. If 0xff is passed, the
|
||||||
|
** current trace level is returned.
|
||||||
|
**
|
||||||
|
** Input Parameters:
|
||||||
|
** new_level: The level to set the A2D 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.
|
||||||
|
**
|
||||||
|
******************************************************************************/
|
||||||
|
extern UINT8 A2D_SetTraceLevel (UINT8 new_level);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
** Function A2D_BitsSet
|
||||||
|
**
|
||||||
|
** Description Check the given num for the number of bits set
|
||||||
|
** Returns A2D_SET_ONE_BIT, if one and only one bit is set
|
||||||
|
** A2D_SET_ZERO_BIT, if all bits clear
|
||||||
|
** A2D_SET_MULTL_BIT, if multiple bits are set
|
||||||
|
******************************************************************************/
|
||||||
|
extern UINT8 A2D_BitsSet(UINT8 num);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_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 void
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
extern void A2D_Init(void);
|
||||||
|
|
||||||
|
#endif /* A2D_API_H */
|
212
components/bt/bluedroid/stack/include/a2d_sbc.h
Executable file
212
components/bt/bluedroid/stack/include/a2d_sbc.h
Executable file
@ -0,0 +1,212 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2000-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* nterface to low complexity subband codec (SBC)
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef A2D_SBC_H
|
||||||
|
#define A2D_SBC_H
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Constants
|
||||||
|
*****************************************************************************/
|
||||||
|
/* the length of the SBC Media Payload header. */
|
||||||
|
#define A2D_SBC_MPL_HDR_LEN 1
|
||||||
|
|
||||||
|
/* the LOSC of SBC media codec capabilitiy */
|
||||||
|
#define A2D_SBC_INFO_LEN 6
|
||||||
|
|
||||||
|
/* for Codec Specific Information Element */
|
||||||
|
#define A2D_SBC_IE_SAMP_FREQ_MSK 0xF0 /* b7-b4 sampling frequency */
|
||||||
|
#define A2D_SBC_IE_SAMP_FREQ_16 0x80 /* b7:16 kHz */
|
||||||
|
#define A2D_SBC_IE_SAMP_FREQ_32 0x40 /* b6:32 kHz */
|
||||||
|
#define A2D_SBC_IE_SAMP_FREQ_44 0x20 /* b5:44.1kHz */
|
||||||
|
#define A2D_SBC_IE_SAMP_FREQ_48 0x10 /* b4:48 kHz */
|
||||||
|
|
||||||
|
#define A2D_SBC_IE_CH_MD_MSK 0x0F /* b3-b0 channel mode */
|
||||||
|
#define A2D_SBC_IE_CH_MD_MONO 0x08 /* b3: mono */
|
||||||
|
#define A2D_SBC_IE_CH_MD_DUAL 0x04 /* b2: dual */
|
||||||
|
#define A2D_SBC_IE_CH_MD_STEREO 0x02 /* b1: stereo */
|
||||||
|
#define A2D_SBC_IE_CH_MD_JOINT 0x01 /* b0: joint stereo */
|
||||||
|
|
||||||
|
#define A2D_SBC_IE_BLOCKS_MSK 0xF0 /* b7-b4 number of blocks */
|
||||||
|
#define A2D_SBC_IE_BLOCKS_4 0x80 /* 4 blocks */
|
||||||
|
#define A2D_SBC_IE_BLOCKS_8 0x40 /* 8 blocks */
|
||||||
|
#define A2D_SBC_IE_BLOCKS_12 0x20 /* 12blocks */
|
||||||
|
#define A2D_SBC_IE_BLOCKS_16 0x10 /* 16blocks */
|
||||||
|
|
||||||
|
#define A2D_SBC_IE_SUBBAND_MSK 0x0C /* b3-b2 number of subbands */
|
||||||
|
#define A2D_SBC_IE_SUBBAND_4 0x08 /* b3: 4 */
|
||||||
|
#define A2D_SBC_IE_SUBBAND_8 0x04 /* b2: 8 */
|
||||||
|
|
||||||
|
#define A2D_SBC_IE_ALLOC_MD_MSK 0x03 /* b1-b0 allocation mode */
|
||||||
|
#define A2D_SBC_IE_ALLOC_MD_S 0x02 /* b1: SNR */
|
||||||
|
#define A2D_SBC_IE_ALLOC_MD_L 0x01 /* b0: loundess */
|
||||||
|
|
||||||
|
#define A2D_SBC_IE_MIN_BITPOOL 2
|
||||||
|
#define A2D_SBC_IE_MAX_BITPOOL 250
|
||||||
|
|
||||||
|
/* for media payload header */
|
||||||
|
#define A2D_SBC_HDR_F_MSK 0x80
|
||||||
|
#define A2D_SBC_HDR_S_MSK 0x40
|
||||||
|
#define A2D_SBC_HDR_L_MSK 0x20
|
||||||
|
#define A2D_SBC_HDR_NUM_MSK 0x0F
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Type Definitions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* data type for the SBC Codec Information Element*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT8 samp_freq; /* Sampling frequency */
|
||||||
|
UINT8 ch_mode; /* Channel mode */
|
||||||
|
UINT8 block_len; /* Block length */
|
||||||
|
UINT8 num_subbands; /* Number of subbands */
|
||||||
|
UINT8 alloc_mthd; /* Allocation method */
|
||||||
|
UINT8 max_bitpool; /* Maximum bitpool */
|
||||||
|
UINT8 min_bitpool; /* Minimum bitpool */
|
||||||
|
} tA2D_SBC_CIE;
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** External Function Declarations
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_SbcChkFrInit
|
||||||
|
**
|
||||||
|
** Description check if need to init the descramble control block.
|
||||||
|
**
|
||||||
|
** Returns nothing.
|
||||||
|
******************************************************************************/
|
||||||
|
extern void A2D_SbcChkFrInit(UINT8 *p_pkt);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_SbcDescramble
|
||||||
|
**
|
||||||
|
** Description descramble the packet.
|
||||||
|
**
|
||||||
|
** Returns nothing.
|
||||||
|
******************************************************************************/
|
||||||
|
extern void A2D_SbcDescramble(UINT8 *p_pkt, UINT16 len);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_BldSbcInfo
|
||||||
|
**
|
||||||
|
** Description This function is called by an application to build
|
||||||
|
** the SBC Media Codec Capabilities byte sequence
|
||||||
|
** beginning from the LOSC octet.
|
||||||
|
** Input Parameters:
|
||||||
|
** media_type: Indicates Audio, or Multimedia.
|
||||||
|
**
|
||||||
|
** p_ie: The SBC Codec Information Element information.
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** p_result: the resulting codec info byte sequence.
|
||||||
|
**
|
||||||
|
** Returns A2D_SUCCESS if function execution succeeded.
|
||||||
|
** Error status code, otherwise.
|
||||||
|
******************************************************************************/
|
||||||
|
extern tA2D_STATUS A2D_BldSbcInfo(UINT8 media_type, tA2D_SBC_CIE *p_ie,
|
||||||
|
UINT8 *p_result);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_ParsSbcInfo
|
||||||
|
**
|
||||||
|
** Description This function is called by an application to parse
|
||||||
|
** the SBC Media Codec Capabilities byte sequence
|
||||||
|
** beginning from the LOSC octet.
|
||||||
|
** Input Parameters:
|
||||||
|
** p_info: the byte sequence to parse.
|
||||||
|
**
|
||||||
|
** for_caps: TRUE, if the byte sequence is for get capabilities response.
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** p_ie: The SBC Codec Information Element information.
|
||||||
|
**
|
||||||
|
** Returns A2D_SUCCESS if function execution succeeded.
|
||||||
|
** Error status code, otherwise.
|
||||||
|
******************************************************************************/
|
||||||
|
extern tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info,
|
||||||
|
BOOLEAN for_caps);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_BldSbcMplHdr
|
||||||
|
**
|
||||||
|
** Description This function is called by an application to parse
|
||||||
|
** the SBC Media Payload header.
|
||||||
|
** Input Parameters:
|
||||||
|
** frag: 1, if fragmented. 0, otherwise.
|
||||||
|
**
|
||||||
|
** start: 1, if the starting packet of a fragmented frame.
|
||||||
|
**
|
||||||
|
** last: 1, if the last packet of a fragmented frame.
|
||||||
|
**
|
||||||
|
** num: If frag is 1, this is the number of remaining fragments
|
||||||
|
** (including this fragment) of this frame.
|
||||||
|
** If frag is 0, this is the number of frames in this packet.
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** p_dst: the resulting media payload header byte sequence.
|
||||||
|
**
|
||||||
|
** Returns void.
|
||||||
|
******************************************************************************/
|
||||||
|
extern void A2D_BldSbcMplHdr(UINT8 *p_dst, BOOLEAN frag, BOOLEAN start,
|
||||||
|
BOOLEAN last, UINT8 num);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**
|
||||||
|
** Function A2D_ParsSbcMplHdr
|
||||||
|
**
|
||||||
|
** Description This function is called by an application to parse
|
||||||
|
** the SBC Media Payload header.
|
||||||
|
** Input Parameters:
|
||||||
|
** p_src: the byte sequence to parse..
|
||||||
|
**
|
||||||
|
** Output Parameters:
|
||||||
|
** frag: 1, if fragmented. 0, otherwise.
|
||||||
|
**
|
||||||
|
** start: 1, if the starting packet of a fragmented frame.
|
||||||
|
**
|
||||||
|
** last: 1, if the last packet of a fragmented frame.
|
||||||
|
**
|
||||||
|
** num: If frag is 1, this is the number of remaining fragments
|
||||||
|
** (including this fragment) of this frame.
|
||||||
|
** If frag is 0, this is the number of frames in this packet.
|
||||||
|
**
|
||||||
|
** Returns void.
|
||||||
|
******************************************************************************/
|
||||||
|
extern void A2D_ParsSbcMplHdr(UINT8 *p_src, BOOLEAN *p_frag,
|
||||||
|
BOOLEAN *p_start, BOOLEAN *p_last,
|
||||||
|
UINT8 *p_num);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* A2D_SBC_H */
|
46
components/bt/bluedroid/utils/include/bt_utils.h
Executable file
46
components/bt/bluedroid/utils/include/bt_utils.h
Executable file
@ -0,0 +1,46 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009-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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef BT_UTILS_H
|
||||||
|
#define BT_UTILS_H
|
||||||
|
|
||||||
|
// static const char BT_UTILS_MODULE[] = "bt_utils_module";
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Type definitions
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TASK_HIGH_MEDIA = 0,
|
||||||
|
TASK_HIGH_GKI_TIMER,
|
||||||
|
TASK_HIGH_BTU,
|
||||||
|
TASK_HIGH_HCI_WORKER,
|
||||||
|
TASK_HIGH_USERIAL_READ,
|
||||||
|
TASK_UIPC_READ,
|
||||||
|
TASK_JAVA_ALARM,
|
||||||
|
TASK_HIGH_MAX
|
||||||
|
} tHIGH_PRIORITY_TASK;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Functions
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
// void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task);
|
||||||
|
// void adjust_priority_a2dp(int start);
|
||||||
|
#define UNUSED(x) (void)(x)
|
||||||
|
#endif /* BT_UTILS_H */
|
@ -9,10 +9,10 @@ COMPONENT_ADD_INCLUDEDIRS := bluedroid/bta/include \
|
|||||||
bluedroid/gki/include \
|
bluedroid/gki/include \
|
||||||
bluedroid/hci/include \
|
bluedroid/hci/include \
|
||||||
bluedroid/osi/include \
|
bluedroid/osi/include \
|
||||||
|
bluedroid/utils/include \
|
||||||
bluedroid/profiles/core/include \
|
bluedroid/profiles/core/include \
|
||||||
bluedroid/profiles/esp/blufi/include \
|
bluedroid/profiles/esp/blufi/include \
|
||||||
bluedroid/profiles/esp/include \
|
bluedroid/profiles/esp/include \
|
||||||
bluedroid/profiles/std/avrc/include \
|
|
||||||
bluedroid/profiles/std/battery/include \
|
bluedroid/profiles/std/battery/include \
|
||||||
bluedroid/profiles/std/dis/include \
|
bluedroid/profiles/std/dis/include \
|
||||||
bluedroid/profiles/std/hid/include \
|
bluedroid/profiles/std/hid/include \
|
||||||
@ -26,6 +26,10 @@ COMPONENT_ADD_INCLUDEDIRS := bluedroid/bta/include \
|
|||||||
bluedroid/stack/l2cap/include \
|
bluedroid/stack/l2cap/include \
|
||||||
bluedroid/stack/sdp/include \
|
bluedroid/stack/sdp/include \
|
||||||
bluedroid/stack/smp/include \
|
bluedroid/stack/smp/include \
|
||||||
|
bluedroid/stack/avct/include \
|
||||||
|
bluedroid/stack/avrc/include \
|
||||||
|
bluedroid/stack/avdt/include \
|
||||||
|
bluedroid/stack/a2dp/include \
|
||||||
bluedroid/stack/include \
|
bluedroid/stack/include \
|
||||||
bluedroid/stack_api/include \
|
bluedroid/stack_api/include \
|
||||||
bluedroid/include \
|
bluedroid/include \
|
||||||
@ -57,7 +61,6 @@ COMPONENT_SRCDIRS := bluedroid/bta/dm \
|
|||||||
bluedroid/profiles/esp/ble_button \
|
bluedroid/profiles/esp/ble_button \
|
||||||
bluedroid/profiles/esp/wechat_AirSync \
|
bluedroid/profiles/esp/wechat_AirSync \
|
||||||
bluedroid/profiles/esp \
|
bluedroid/profiles/esp \
|
||||||
bluedroid/profiles/std/avrc \
|
|
||||||
bluedroid/profiles/std/battery \
|
bluedroid/profiles/std/battery \
|
||||||
bluedroid/profiles/std/dis \
|
bluedroid/profiles/std/dis \
|
||||||
bluedroid/profiles/std/hid \
|
bluedroid/profiles/std/hid \
|
||||||
@ -76,6 +79,10 @@ COMPONENT_SRCDIRS := bluedroid/bta/dm \
|
|||||||
bluedroid/stack/l2cap \
|
bluedroid/stack/l2cap \
|
||||||
bluedroid/stack/sdp \
|
bluedroid/stack/sdp \
|
||||||
bluedroid/stack/smp \
|
bluedroid/stack/smp \
|
||||||
|
bluedroid/stack/avct \
|
||||||
|
bluedroid/stack/avrc \
|
||||||
|
bluedroid/stack/avdt \
|
||||||
|
bluedroid/stack/a2dp \
|
||||||
bluedroid/stack \
|
bluedroid/stack \
|
||||||
bluedroid/stack_api \
|
bluedroid/stack_api \
|
||||||
bluedroid \
|
bluedroid \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user