diff options
author | Kausik Sinnaswamy <kausik@broadcom.com> | 2012-03-07 19:30:20 -0800 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:12 -0700 |
commit | 95fa11b3b2f19a382c7e3a744a6afb452fad86df (patch) | |
tree | 1019e123db4596f2b8bd1259da04b51f3c44d7b2 /bta/av | |
parent | e2197423bcf1a93c620be13d458a9da6693fa94d (diff) | |
download | external_bluetooth_bluedroid-95fa11b3b2f19a382c7e3a744a6afb452fad86df.zip external_bluetooth_bluedroid-95fa11b3b2f19a382c7e3a744a6afb452fad86df.tar.gz external_bluetooth_bluedroid-95fa11b3b2f19a382c7e3a744a6afb452fad86df.tar.bz2 |
AV control and data path added
Change-Id: I88ec6084c140fa257154a98e23e075900e84cc8c
Diffstat (limited to 'bta/av')
-rw-r--r-- | bta/av/bta_av_aact.c | 4 | ||||
-rw-r--r-- | bta/av/bta_av_act.c | 6 | ||||
-rw-r--r-- | bta/av/bta_av_api.c | 4 | ||||
-rw-r--r-- | bta/av/bta_av_cfg.c | 19 | ||||
-rw-r--r-- | bta/av/bta_av_main.c | 13 | ||||
-rw-r--r-- | bta/av/bta_av_sbc.c | 577 |
6 files changed, 588 insertions, 35 deletions
diff --git a/bta/av/bta_av_aact.c b/bta/av/bta_av_aact.c index aa154b3..423c322 100644 --- a/bta/av/bta_av_aact.c +++ b/bta/av/bta_av_aact.c @@ -12,7 +12,7 @@ *****************************************************************************/ #include "bt_target.h" -#if defined(AV_INCLUDED) && (AV_INCLUDED == TRUE) +#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE) #include <string.h> #include "bta_av_int.h" @@ -2685,4 +2685,4 @@ void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) } } -#endif /* AV_INCLUDED */ +#endif /* BTA_AV_INCLUDED */ diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c index 472ed21..e501e52 100644 --- a/bta/av/bta_av_act.c +++ b/bta/av/bta_av_act.c @@ -11,7 +11,7 @@ *****************************************************************************/ #include "bt_target.h" -#if defined(AV_INCLUDED) && (AV_INCLUDED == TRUE) +#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE) #include <string.h> #include "bta_av_api.h" @@ -767,6 +767,7 @@ tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE *p_rc_rsp, tBTA_AV_RC_MSG *p_ms p_vendor->hdr.ctype = BTA_AV_RSP_NOT_IMPL; AVRC_VendorRsp(p_msg->handle, p_msg->label, &p_msg->msg.vendor); } +#if (AVRC_METADATA_INCLUDED == TRUE) else if (!AVRC_IsValidAvcType(pdu, p_vendor->hdr.ctype) ) { APPL_TRACE_DEBUG2("Invalid pdu/ctype: 0x%x, %d", pdu, p_vendor->hdr.ctype); @@ -774,6 +775,7 @@ tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE *p_rc_rsp, tBTA_AV_RC_MSG *p_ms evt = 0; p_rc_rsp->rsp.status = AVRC_STS_BAD_CMD; } +#endif else { switch (pdu) @@ -1997,4 +1999,4 @@ void bta_av_dereg_comp(tBTA_AV_DATA *p_data) utl_set_device_class(&cod, BTA_UTL_CLR_COD_SERVICE_CLASS); } } -#endif /* AV_INCLUDED */ +#endif /* BTA_AV_INCLUDED */ diff --git a/bta/av/bta_av_api.c b/bta/av/bta_av_api.c index 3bb59f7..762692f 100644 --- a/bta/av/bta_av_api.c +++ b/bta/av/bta_av_api.c @@ -12,7 +12,7 @@ *****************************************************************************/ #include "bt_target.h" -#if defined(AV_INCLUDED) && (AV_INCLUDED == TRUE) +#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE) #include "bta_api.h" #include "bd.h" @@ -565,4 +565,4 @@ void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p } } -#endif /* AV_INCLUDED */ +#endif /* BTA_AV_INCLUDED */ diff --git a/bta/av/bta_av_cfg.c b/bta/av/bta_av_cfg.c index bb01366..1c6d335 100644 --- a/bta/av/bta_av_cfg.c +++ b/bta/av/bta_av_cfg.c @@ -15,24 +15,12 @@ #include "bta_api.h" #include "bta_av_int.h" -#ifndef BTA_AV_VDP_INCLUDED -#define BTA_AV_VDP_INCLUDED TRUE -#endif -#if ((VDP_INCLUDED == FALSE) && (BTA_AV_VDP_INCLUDED == TRUE)) -#undef BTA_AV_VDP_INCLUDED -#define BTA_AV_VDP_INCLUDED FALSE -#endif #ifndef BTA_AV_RC_PASS_RSP_CODE #define BTA_AV_RC_PASS_RSP_CODE BTA_AV_RSP_NOT_IMPL #endif -#if (BTA_AV_VDP_INCLUDED == TRUE) -#define BTA_AV_NUM_A2DP_STRS (BTA_AV_NUM_STRS - 1) -#else -#define BTA_AV_NUM_A2DP_STRS (BTA_AV_NUM_STRS) -#endif const UINT32 bta_av_meta_caps_co_ids[] = { AVRC_CO_METADATA, @@ -175,13 +163,6 @@ const tBTA_AV_CFG bta_av_cfg = BTA_AV_RC_PASS_RSP_CODE,/* the default response code for pass through commands */ bta_av_meta_caps_co_ids,/* the metadata Get Capabilities response for company id */ bta_av_meta_caps_evt_ids,/* the the metadata Get Capabilities response for event id */ -#if BTA_AV_VDP_INCLUDED == TRUE - (const tBTA_AV_ACT *)bta_av_vdp_action,/* the action table for VDP */ - bta_av_reg_vdp /* action function to register VDP */ -#else - (const tBTA_AV_ACT *)NULL,/* the action table for VDP */ - NULL /* action function to register VDP */ -#endif }; tBTA_AV_CFG *p_bta_av_cfg = (tBTA_AV_CFG *) &bta_av_cfg; diff --git a/bta/av/bta_av_main.c b/bta/av/bta_av_main.c index 65c2cfe..ebf11b4 100644 --- a/bta/av/bta_av_main.c +++ b/bta/av/bta_av_main.c @@ -11,7 +11,7 @@ *****************************************************************************/ #include "bt_target.h" -#if defined(AV_INCLUDED) && (AV_INCLUDED == TRUE) +#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE) #include <string.h> #include "bta_av_int.h" @@ -602,7 +602,6 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data) bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1); /* if the AV and AVK are both supported, it cannot support the CT role */ -#if (BTA_AVK_INCLUDED == FALSE) if (bta_av_cb.features & (BTA_AV_FEAT_RCCT)) { /* if TG is not supported, we need to register to AVCT now */ @@ -624,7 +623,6 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data) p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV); #endif } -#endif } bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi); APPL_TRACE_DEBUG1("reg_audio: 0x%x",bta_av_cb.reg_audio); @@ -705,14 +703,9 @@ static void bta_av_ci_data(tBTA_AV_DATA *p_data) ** *******************************************************************************/ #if (AVDT_REPORTING == TRUE) + static void bta_av_rpc_conn(tBTA_AV_DATA *p_data) { - tBTA_AV_SCB *p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific); - if(p_scb) - { - bta_av_co_video_report_conn(p_data->str_msg.msg.report_conn.err_param, - p_scb->avdt_handle); - } } #endif @@ -1315,4 +1308,4 @@ char *bta_av_evt_code(UINT16 evt_code) } #endif -#endif /* AV_INCLUDED */ +#endif /* BTA_AV_INCLUDED */ diff --git a/bta/av/bta_av_sbc.c b/bta/av/bta_av_sbc.c new file mode 100644 index 0000000..ba11752 --- /dev/null +++ b/bta/av/bta_av_sbc.c @@ -0,0 +1,577 @@ +/***************************************************************************** +** +** Name: bta_av_sbc.c +** +** Description: This module contains utility functions for dealing with +** SBC data frames and codec capabilities. +** +** Copyright (c) 2004, Widcomm Inc., All Rights Reserved. +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "a2d_api.h" +#include "a2d_sbc.h" +#include "bta_av_sbc.h" + +typedef int (tBTA_AV_SBC_ACT)(void *p_src, void *p_dst, + UINT32 src_samples, UINT32 dst_samples, + UINT32 *p_ret); + +typedef struct +{ + INT32 cur_pos; /* current position */ + UINT32 src_sps; /* samples per second (source audio data) */ + UINT32 dst_sps; /* samples per second (converted audio data) */ + tBTA_AV_SBC_ACT *p_act; /* the action function to do the conversion */ + UINT16 bits; /* number of bits per pcm sample */ + UINT16 n_channels; /* number of channels (i.e. mono(1), stereo(2)...) */ + INT16 worker1; + INT16 worker2; + UINT8 div; +} tBTA_AV_SBC_UPS_CB; + +tBTA_AV_SBC_UPS_CB bta_av_sbc_ups_cb; + +/******************************************************************************* +** +** Function bta_av_sbc_init_up_sample +** +** Description initialize the up sample +** +** src_sps: samples per second (source audio data) +** dst_sps: samples per second (converted audio data) +** bits: number of bits per pcm sample +** n_channels: number of channels (i.e. mono(1), stereo(2)...) +** +** Returns none +** +*******************************************************************************/ +void bta_av_sbc_init_up_sample (UINT32 src_sps, UINT32 dst_sps, UINT16 bits, UINT16 n_channels) +{ + bta_av_sbc_ups_cb.cur_pos = -1; + bta_av_sbc_ups_cb.src_sps = src_sps; + bta_av_sbc_ups_cb.dst_sps = dst_sps; + bta_av_sbc_ups_cb.bits = bits; + bta_av_sbc_ups_cb.n_channels= n_channels; + + if(n_channels == 1) + { + /* mono */ + if(bits == 8) + { + bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_8m; + bta_av_sbc_ups_cb.div = 1; + } + else + { + bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_16m; + bta_av_sbc_ups_cb.div = 2; + } + } + else + { + /* stereo */ + if(bits == 8) + { + bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_8s; + bta_av_sbc_ups_cb.div = 2; + } + else + { + bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_16s; + bta_av_sbc_ups_cb.div = 4; + } + } +} + +/******************************************************************************* +** +** Function bta_av_sbc_up_sample +** +** Description Given the source (p_src) audio data and +** source speed (src_sps, samples per second), +** This function converts it to audio data in the desired format +** +** p_src: the data buffer that holds the source audio data +** p_dst: the data buffer to hold the converted audio data +** src_samples: The number of source samples (number of bytes) +** dst_samples: The size of p_dst (number of bytes) +** +** Note: An AE reported an issue with this function. +** When called with bta_av_sbc_up_sample(src, uint8_array_dst..) +** the byte before uint8_array_dst may get overwritten. +** Using uint16_array_dst avoids the problem. +** This issue is related to endian-ness and is hard to resolve +** in a generic manner. +** **************** Please use uint16 array as dst. +** +** Returns The number of bytes used in p_dst +** The number of bytes used in p_src (in *p_ret) +** +*******************************************************************************/ +int bta_av_sbc_up_sample (void *p_src, void *p_dst, + UINT32 src_samples, UINT32 dst_samples, + UINT32 *p_ret) +{ + UINT32 src; + UINT32 dst; + + if(bta_av_sbc_ups_cb.p_act) + { + src = src_samples/bta_av_sbc_ups_cb.div; + dst = dst_samples/bta_av_sbc_ups_cb.div; + return (*bta_av_sbc_ups_cb.p_act)(p_src, p_dst, src, dst, p_ret); + } + else + { + *p_ret = 0; + return 0; + } +} + +/******************************************************************************* +** +** Function bta_av_sbc_up_sample_16s (16bits-stereo) +** +** Description Given the source (p_src) audio data and +** source speed (src_sps, samples per second), +** This function converts it to audio data in the desired format +** +** p_src: the data buffer that holds the source audio data +** p_dst: the data buffer to hold the converted audio data +** src_samples: The number of source samples (in uint of 4 bytes) +** dst_samples: The size of p_dst (in uint of 4 bytes) +** +** Returns The number of bytes used in p_dst +** The number of bytes used in p_src (in *p_ret) +** +*******************************************************************************/ +int bta_av_sbc_up_sample_16s (void *p_src, void *p_dst, + UINT32 src_samples, UINT32 dst_samples, + UINT32 *p_ret) +{ + INT16 *p_src_tmp = (INT16 *)p_src; + INT16 *p_dst_tmp = (INT16 *)p_dst; + INT16 *p_worker1 = &bta_av_sbc_ups_cb.worker1; + INT16 *p_worker2 = &bta_av_sbc_ups_cb.worker2; + UINT32 src_sps = bta_av_sbc_ups_cb.src_sps; + UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps; + + while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) + { + *p_dst_tmp++ = *p_worker1; + *p_dst_tmp++ = *p_worker2; + + bta_av_sbc_ups_cb.cur_pos -= src_sps; + dst_samples--; + } + + bta_av_sbc_ups_cb.cur_pos = dst_sps; + + while (src_samples-- && dst_samples) + { + *p_worker1 = *p_src_tmp++; + *p_worker2 = *p_src_tmp++; + + do + { + *p_dst_tmp++ = *p_worker1; + *p_dst_tmp++ = *p_worker2; + + bta_av_sbc_ups_cb.cur_pos -= src_sps; + dst_samples--; + } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples); + + bta_av_sbc_ups_cb.cur_pos += dst_sps; + } + + if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps) + bta_av_sbc_ups_cb.cur_pos = 0; + + *p_ret = ((char *)p_src_tmp - (char *)p_src); + return ((char *)p_dst_tmp - (char *)p_dst); +} + +/******************************************************************************* +** +** Function bta_av_sbc_up_sample_16m (16bits-mono) +** +** Description Given the source (p_src) audio data and +** source speed (src_sps, samples per second), +** This function converts it to audio data in the desired format +** +** p_src: the data buffer that holds the source audio data +** p_dst: the data buffer to hold the converted audio data +** src_samples: The number of source samples (in uint of 2 bytes) +** dst_samples: The size of p_dst (in uint of 2 bytes) +** +** Returns The number of bytes used in p_dst +** The number of bytes used in p_src (in *p_ret) +** +*******************************************************************************/ +int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst, + UINT32 src_samples, UINT32 dst_samples, + UINT32 *p_ret) +{ + INT16 *p_src_tmp = (INT16 *)p_src; + INT16 *p_dst_tmp = (INT16 *)p_dst; + INT16 *p_worker = &bta_av_sbc_ups_cb.worker1; + UINT32 src_sps = bta_av_sbc_ups_cb.src_sps; + UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps; + + while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) + { + *p_dst_tmp++ = *p_worker; + *p_dst_tmp++ = *p_worker; + + bta_av_sbc_ups_cb.cur_pos -= src_sps; + dst_samples--; + dst_samples--; + } + + + bta_av_sbc_ups_cb.cur_pos = dst_sps; + + while (src_samples-- && dst_samples) + { + *p_worker = *p_src_tmp++; + + do + { + *p_dst_tmp++ = *p_worker; + *p_dst_tmp++ = *p_worker; + + bta_av_sbc_ups_cb.cur_pos -= src_sps; + dst_samples--; + dst_samples--; + + } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples); + + bta_av_sbc_ups_cb.cur_pos += dst_sps; + } + + if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps) + bta_av_sbc_ups_cb.cur_pos = 0; + + *p_ret = ((char *)p_src_tmp - (char *)p_src); + return ((char *)p_dst_tmp - (char *)p_dst); +} + +/******************************************************************************* +** +** Function bta_av_sbc_up_sample_8s (8bits-stereo) +** +** Description Given the source (p_src) audio data and +** source speed (src_sps, samples per second), +** This function converts it to audio data in the desired format +** +** p_src: the data buffer that holds the source audio data +** p_dst: the data buffer to hold the converted audio data +** src_samples: The number of source samples (in uint of 2 bytes) +** dst_samples: The size of p_dst (in uint of 2 bytes) +** +** Returns The number of bytes used in p_dst +** The number of bytes used in p_src (in *p_ret) +** +*******************************************************************************/ +int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst, + UINT32 src_samples, UINT32 dst_samples, + UINT32 *p_ret) +{ + UINT8 *p_src_tmp = (UINT8 *)p_src; + INT16 *p_dst_tmp = (INT16 *)p_dst; + INT16 *p_worker1 = &bta_av_sbc_ups_cb.worker1; + INT16 *p_worker2 = &bta_av_sbc_ups_cb.worker2; + UINT32 src_sps = bta_av_sbc_ups_cb.src_sps; + UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps; + + while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) + { + *p_dst_tmp++ = *p_worker1; + *p_dst_tmp++ = *p_worker2; + + bta_av_sbc_ups_cb.cur_pos -= src_sps; + dst_samples--; + dst_samples--; + } + + bta_av_sbc_ups_cb.cur_pos = dst_sps; + + while (src_samples -- && dst_samples) + { + *p_worker1 = *(UINT8 *)p_src_tmp++; + *p_worker1 -= 0x80; + *p_worker1 <<= 8; + *p_worker2 = *(UINT8 *)p_src_tmp++; + *p_worker2 -= 0x80; + *p_worker2 <<= 8; + + do + { + *p_dst_tmp++ = *p_worker1; + *p_dst_tmp++ = *p_worker2; + + bta_av_sbc_ups_cb.cur_pos -= src_sps; + dst_samples--; + dst_samples--; + } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples); + + bta_av_sbc_ups_cb.cur_pos += dst_sps; + } + + if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps) + bta_av_sbc_ups_cb.cur_pos = 0; + + *p_ret = ((char *)p_src_tmp - (char *)p_src); + return ((char *)p_dst_tmp - (char *)p_dst); +} + +/******************************************************************************* +** +** Function bta_av_sbc_up_sample_8m (8bits-mono) +** +** Description Given the source (p_src) audio data and +** source speed (src_sps, samples per second), +** This function converts it to audio data in the desired format +** +** p_src: the data buffer that holds the source audio data +** p_dst: the data buffer to hold the converted audio data +** src_samples: The number of source samples (number of bytes) +** dst_samples: The size of p_dst (number of bytes) +** +** Returns The number of bytes used in p_dst +** The number of bytes used in p_src (in *p_ret) +** +*******************************************************************************/ +int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst, + UINT32 src_samples, UINT32 dst_samples, + UINT32 *p_ret) +{ + UINT8 *p_src_tmp = (UINT8 *)p_src; + INT16 *p_dst_tmp = (INT16 *)p_dst; + INT16 *p_worker = &bta_av_sbc_ups_cb.worker1; + UINT32 src_sps = bta_av_sbc_ups_cb.src_sps; + UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps; + + while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) + { + *p_dst_tmp++ = *p_worker; + *p_dst_tmp++ = *p_worker; + + bta_av_sbc_ups_cb.cur_pos -= src_sps; + dst_samples -= 4; + } + + + bta_av_sbc_ups_cb.cur_pos = dst_sps; + + while (src_samples-- && dst_samples) + { + *p_worker = *(UINT8 *)p_src_tmp++; + *p_worker -= 0x80; + *p_worker <<= 8; + + do + { + *p_dst_tmp++ = *p_worker; + *p_dst_tmp++ = *p_worker; + + bta_av_sbc_ups_cb.cur_pos -= src_sps; + dst_samples -= 4; + + } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples); + + bta_av_sbc_ups_cb.cur_pos += dst_sps; + } + + if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps) + bta_av_sbc_ups_cb.cur_pos = 0; + + *p_ret = ((char *)p_src_tmp - (char *)p_src); + return ((char *)p_dst_tmp - (char *)p_dst); +} + +/******************************************************************************* +** +** Function bta_av_sbc_cfg_for_cap +** +** Description Determine the preferred SBC codec configuration for the +** given codec capabilities. The function is passed the +** preferred codec configuration and the peer codec +** capabilities for the stream. The function attempts to +** match the preferred capabilities with the configuration +** as best it can. The resulting codec configuration is +** returned in the same memory used for the capabilities. +** +** Returns 0 if ok, nonzero if error. +** Codec configuration in p_cap. +** +*******************************************************************************/ +UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC_CIE *p_pref) +{ + UINT8 status = A2D_SUCCESS; + tA2D_SBC_CIE peer_cie; + + /* parse peer capabilities */ + if ((status = A2D_ParsSbcInfo(&peer_cie, p_peer, TRUE)) != 0) + { + return status; + } + + /* Check if the peer supports our channel mode */ + if (peer_cie.ch_mode & p_pref->ch_mode) + { + peer_cie.ch_mode = p_pref->ch_mode; + } + else + { + APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: ch_mode(0x%02X) not supported", p_pref->ch_mode); + return A2D_FAIL; + } + + /* Check if the peer supports our sampling freq */ + if (peer_cie.samp_freq & p_pref->samp_freq) + { + peer_cie.samp_freq = p_pref->samp_freq; + } + else + { + APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: samp_freq(0x%02X) not supported", p_pref->samp_freq); + return A2D_FAIL; + } + + /* Check if the peer supports our block len */ + if (peer_cie.block_len & p_pref->block_len) + { + peer_cie.block_len = p_pref->block_len; + } + else + { + APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: block_len(0x%02X) not supported", p_pref->block_len); + return A2D_FAIL; + } + + /* Check if the peer supports our num subbands */ + if (peer_cie.num_subbands & p_pref->num_subbands) + { + peer_cie.num_subbands = p_pref->num_subbands; + } + else + { + APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: num_subbands(0x%02X) not supported", p_pref->num_subbands); + return A2D_FAIL; + } + + /* Check if the peer supports our alloc method */ + if (peer_cie.alloc_mthd & p_pref->alloc_mthd) + { + peer_cie.alloc_mthd = p_pref->alloc_mthd; + } + else + { + APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: alloc_mthd(0x%02X) not supported", p_pref->alloc_mthd); + return A2D_FAIL; + } + + /* max bitpool */ + if (p_pref->max_bitpool != 0 && p_pref->max_bitpool < peer_cie.max_bitpool) + { + peer_cie.max_bitpool = p_pref->max_bitpool; + } + + /* min bitpool */ + if (p_pref->min_bitpool != 0 && p_pref->min_bitpool > peer_cie.min_bitpool) + { + peer_cie.min_bitpool = p_pref->min_bitpool; + } + + if (status == A2D_SUCCESS) + { + /* build configuration */ + A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &peer_cie, p_peer); + } + return status; +} + +/******************************************************************************* +** +** Function bta_av_sbc_cfg_in_cap +** +** Description This function checks whether an SBC codec configuration +** is allowable for the given codec capabilities. +** +** Returns 0 if ok, nonzero if error. +** +*******************************************************************************/ +UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap) +{ + UINT8 status = 0; + tA2D_SBC_CIE cfg_cie; + + /* parse configuration */ + if ((status = A2D_ParsSbcInfo(&cfg_cie, p_cfg, FALSE)) != 0) + { + return status; + } + + /* verify that each parameter is in range */ + + /* sampling frequency */ + if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0) + { + status = A2D_NS_SAMP_FREQ; + } + /* channel mode */ + else if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0) + { + status = A2D_NS_CH_MODE; + } + /* block length */ + else if ((cfg_cie.block_len & p_cap->block_len) == 0) + { + status = A2D_BAD_BLOCK_LEN; + } + /* subbands */ + else if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0) + { + status = A2D_NS_SUBBANDS; + } + /* allocation method */ + else if ((cfg_cie.alloc_mthd & p_cap->alloc_mthd) == 0) + { + status = A2D_NS_ALLOC_MTHD; + } + /* max bitpool */ + else if (cfg_cie.max_bitpool > p_cap->max_bitpool) + { + status = A2D_NS_MAX_BITPOOL; + } + /* min bitpool */ + else if (cfg_cie.min_bitpool < p_cap->min_bitpool) + { + status = A2D_NS_MIN_BITPOOL; + } + + return status; +} + +/******************************************************************************* +** +** Function bta_av_sbc_bld_hdr +** +** Description This function builds the packet header for MPF1. +** +** Returns void +** +*******************************************************************************/ +void bta_av_sbc_bld_hdr(BT_HDR *p_buf, UINT16 fr_per_pkt) +{ + UINT8 *p; + + p_buf->offset -= BTA_AV_SBC_HDR_SIZE; + p = (UINT8 *) (p_buf + 1) + p_buf->offset; + p_buf->len += BTA_AV_SBC_HDR_SIZE; + A2D_BldSbcMplHdr(p, FALSE, FALSE, FALSE, (UINT8) fr_per_pkt); +} + |