From 30198ee8c1458d788d621d52c0c1932b5f6ae7a5 Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Fri, 4 Nov 2016 15:08:30 +0800 Subject: [PATCH] component/bt: add new example for A2DP 1. add new example for A2DP and the related btif layer source code is ported 2. modification on osi_alarm_new API to support periodic timer 3. enable macro BTA_AR_INCLUDED, BTA_AV_INCLUDED, BTA_AV_SINK_INCLUDED 4. The A2DP example cannot work and can only be built successfuly --- .../bt/bluedroid/bta/sys/bta_sys_main.c | 2 +- components/bt/bluedroid/hci/hci_layer.c | 2 +- components/bt/bluedroid/include/bt_target.h | 6 +- components/bt/bluedroid/osi/alarm.c | 5 +- components/bt/bluedroid/osi/include/alarm.h | 3 +- components/bt/bluedroid/osi/include/thread.h | 2 +- components/bt/bluedroid/stack/btu/btu_task.c | 6 +- components/bt/bluedroid/utils/bt_utils.c | 32 + .../bt/bluedroid/utils/include/bt_utils.h | 4 +- .../bluedroid_demos/app_core/bt_app_core.c | 2 +- .../bluedroid_demos/btif/btif_core.c | 2 +- .../bluedroid_demos/include/btif_util.h | 2 +- examples/09_a2dp/Makefile | 11 + examples/09_a2dp/README.rst | 5 + .../bluedroid_demos/app_core/bt_app_core.c | 174 + .../bluedroid_demos/app_project/SampleBtSdp.c | 169 + .../audio_a2dp_hw/audio_a2dp_hw.c | 1423 +++++++++ .../audio_a2dp_hw/include/audio_a2dp_hw.h | 88 + .../components/bluedroid_demos/btif/btif_av.c | 1435 +++++++++ .../bluedroid_demos/btif/btif_core.c | 483 +++ .../components/bluedroid_demos/btif/btif_dm.c | 233 ++ .../bluedroid_demos/btif/btif_media_task.c | 2836 +++++++++++++++++ .../bluedroid_demos/btif/btif_profile_queue.c | 179 ++ .../bluedroid_demos/btif/btif_sdp.c | 175 + .../bluedroid_demos/btif/btif_sdp_server.c | 777 +++++ .../components/bluedroid_demos/btif/btif_sm.c | 208 ++ .../bluedroid_demos/btif/btif_util.c | 159 + .../bluedroid_demos/btif/include/btif_api.h | 88 + .../bluedroid_demos/btif/include/btif_av.h | 154 + .../btif/include/btif_av_api.h | 210 ++ .../bluedroid_demos/btif/include/btif_av_co.h | 174 + .../btif/include/btif_common.h | 125 + .../bluedroid_demos/btif/include/btif_dm.h | 32 + .../bluedroid_demos/btif/include/btif_media.h | 282 ++ .../btif/include/btif_profile_queue.h | 37 + .../bluedroid_demos/btif/include/btif_sdp.h | 38 + .../bluedroid_demos/btif/include/btif_sm.h | 118 + .../btif/include/btif_stack_manager.h | 31 + .../bluedroid_demos/btif/include/btif_util.h | 53 + .../btif/include/stack_manager.h | 29 + .../bluedroid_demos/btif/stack_manager.c | 160 + .../components/bluedroid_demos/component.mk | 29 + .../embdrv/sbc/decoder/include/oi_assert.h | 86 + .../embdrv/sbc/decoder/include/oi_bitstream.h | 123 + .../embdrv/sbc/decoder/include/oi_bt_spec.h | 229 ++ .../embdrv/sbc/decoder/include/oi_codec_sbc.h | 484 +++ .../decoder/include/oi_codec_sbc_private.h | 229 ++ .../embdrv/sbc/decoder/include/oi_common.h | 43 + .../embdrv/sbc/decoder/include/oi_cpu_dep.h | 505 +++ .../embdrv/sbc/decoder/include/oi_modules.h | 171 + .../sbc/decoder/include/oi_osinterface.h | 197 ++ .../embdrv/sbc/decoder/include/oi_status.h | 579 ++++ .../embdrv/sbc/decoder/include/oi_stddefs.h | 232 ++ .../embdrv/sbc/decoder/include/oi_string.h | 208 ++ .../embdrv/sbc/decoder/include/oi_time.h | 200 ++ .../embdrv/sbc/decoder/include/oi_utils.h | 377 +++ .../embdrv/sbc/decoder/srce/alloc.c | 78 + .../embdrv/sbc/decoder/srce/bitalloc-sbc.c | 165 + .../embdrv/sbc/decoder/srce/bitalloc.c | 392 +++ .../sbc/decoder/srce/bitstream-decode.c | 92 + .../embdrv/sbc/decoder/srce/decoder-oina.c | 140 + .../embdrv/sbc/decoder/srce/decoder-private.c | 227 ++ .../embdrv/sbc/decoder/srce/decoder-sbc.c | 465 +++ .../embdrv/sbc/decoder/srce/dequant.c | 210 ++ .../embdrv/sbc/decoder/srce/framing-sbc.c | 54 + .../embdrv/sbc/decoder/srce/framing.c | 249 ++ .../sbc/decoder/srce/oi_codec_version.c | 57 + .../sbc/decoder/srce/readsamplesjoint.inc | 111 + .../sbc/decoder/srce/synthesis-8-generated.c | 135 + .../embdrv/sbc/decoder/srce/synthesis-dct8.c | 305 ++ .../embdrv/sbc/decoder/srce/synthesis-sbc.c | 510 +++ .../embdrv/sbc/encoder/include/sbc_dct.h | 91 + .../encoder/include/sbc_enc_func_declare.h | 57 + .../embdrv/sbc/encoder/include/sbc_encoder.h | 202 ++ .../embdrv/sbc/encoder/include/sbc_if.h | 47 + .../embdrv/sbc/encoder/include/sbc_types.h | 59 + .../embdrv/sbc/encoder/srce/sbc_analysis.c | 1107 +++++++ .../embdrv/sbc/encoder/srce/sbc_dct.c | 245 ++ .../embdrv/sbc/encoder/srce/sbc_dct_coeffs.c | 200 ++ .../sbc/encoder/srce/sbc_enc_bit_alloc_mono.c | 199 ++ .../sbc/encoder/srce/sbc_enc_bit_alloc_ste.c | 212 ++ .../embdrv/sbc/encoder/srce/sbc_enc_coeffs.c | 319 ++ .../embdrv/sbc/encoder/srce/sbc_encoder.c | 402 +++ .../embdrv/sbc/encoder/srce/sbc_packing.c | 274 ++ .../bluedroid_demos/include/bt_app_common.h | 30 + .../bluedroid_demos/include/bt_av.h | 103 + .../bluedroid_demos/udrv/include/uipc.h | 133 + .../bluedroid_demos/udrv/ulinux/uipc.c | 139 + examples/09_a2dp/main/component.mk | 10 + examples/09_a2dp/main/demo_main.c | 28 + 90 files changed, 20676 insertions(+), 17 deletions(-) create mode 100644 components/bt/bluedroid/utils/bt_utils.c create mode 100755 examples/09_a2dp/Makefile create mode 100755 examples/09_a2dp/README.rst create mode 100755 examples/09_a2dp/components/bluedroid_demos/app_core/bt_app_core.c create mode 100644 examples/09_a2dp/components/bluedroid_demos/app_project/SampleBtSdp.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/audio_a2dp_hw/audio_a2dp_hw.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/audio_a2dp_hw/include/audio_a2dp_hw.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/btif_av.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/btif_core.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/btif_dm.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/btif_media_task.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/btif_profile_queue.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/btif_sdp.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/btif_sdp_server.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/btif_sm.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/btif_util.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_api.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av_api.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av_co.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_common.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_dm.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_media.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_profile_queue.h create mode 100644 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_sdp.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_sm.h create mode 100644 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_stack_manager.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/btif_util.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/btif/include/stack_manager.h create mode 100644 examples/09_a2dp/components/bluedroid_demos/btif/stack_manager.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/component.mk create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_assert.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_bitstream.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_bt_spec.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_codec_sbc.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_codec_sbc_private.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_common.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_cpu_dep.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_modules.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_osinterface.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_status.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_stddefs.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_string.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_time.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_utils.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/alloc.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitalloc-sbc.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitalloc.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitstream-decode.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-oina.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-private.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-sbc.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/dequant.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/framing-sbc.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/framing.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/oi_codec_version.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/readsamplesjoint.inc create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/synthesis-8-generated.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/synthesis-dct8.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/synthesis-sbc.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_dct.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_enc_func_declare.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_encoder.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_if.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_types.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_analysis.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_dct.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_dct_coeffs.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_coeffs.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_encoder.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_packing.c create mode 100755 examples/09_a2dp/components/bluedroid_demos/include/bt_app_common.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/include/bt_av.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/udrv/include/uipc.h create mode 100755 examples/09_a2dp/components/bluedroid_demos/udrv/ulinux/uipc.c create mode 100755 examples/09_a2dp/main/component.mk create mode 100755 examples/09_a2dp/main/demo_main.c diff --git a/components/bt/bluedroid/bta/sys/bta_sys_main.c b/components/bt/bluedroid/bta/sys/bta_sys_main.c index 36901e39dc..46c12ad609 100755 --- a/components/bt/bluedroid/bta/sys/bta_sys_main.c +++ b/components/bt/bluedroid/bta/sys/bta_sys_main.c @@ -631,7 +631,7 @@ void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout_ms) { // Get the alarm for this p_tle. pthread_mutex_lock(&bta_alarm_lock); if (!hash_map_has_key(bta_alarm_hash_map, p_tle)) { - hash_map_set(bta_alarm_hash_map, p_tle, osi_alarm_new("bta_sys", bta_alarm_cb, p_tle, 0)); + hash_map_set(bta_alarm_hash_map, p_tle, osi_alarm_new("bta_sys", bta_alarm_cb, p_tle, 0, false)); } pthread_mutex_unlock(&bta_alarm_lock); diff --git a/components/bt/bluedroid/hci/hci_layer.c b/components/bt/bluedroid/hci/hci_layer.c index d9c73d8b16..2b5927d333 100755 --- a/components/bt/bluedroid/hci/hci_layer.c +++ b/components/bt/bluedroid/hci/hci_layer.c @@ -187,7 +187,7 @@ static int hci_layer_init_env(void) return -1; } pthread_mutex_init(&cmd_wait_q->commands_pending_response_lock, NULL); - cmd_wait_q->command_response_timer = osi_alarm_new("cmd_rsp_to", command_timed_out, cmd_wait_q, COMMAND_PENDING_TIMEOUT); + cmd_wait_q->command_response_timer = osi_alarm_new("cmd_rsp_to", command_timed_out, cmd_wait_q, COMMAND_PENDING_TIMEOUT, false); if (!cmd_wait_q->command_response_timer) { LOG_ERROR("%s unable to create command response timer.", __func__); return -1; diff --git a/components/bt/bluedroid/include/bt_target.h b/components/bt/bluedroid/include/bt_target.h index 9af8a2b760..59d73fc2bb 100755 --- a/components/bt/bluedroid/include/bt_target.h +++ b/components/bt/bluedroid/include/bt_target.h @@ -86,15 +86,15 @@ #endif #ifndef BTA_AR_INCLUDED -#define BTA_AR_INCLUDED FALSE//TRUE +#define BTA_AR_INCLUDED TRUE//TRUE #endif #ifndef BTA_AV_INCLUDED -#define BTA_AV_INCLUDED FALSE//TRUE +#define BTA_AV_INCLUDED TRUE//TRUE #endif #ifndef BTA_AV_SINK_INCLUDED -#define BTA_AV_SINK_INCLUDED FALSE//FALSE +#define BTA_AV_SINK_INCLUDED TRUE//FALSE #endif #ifndef BTA_DISABLE_DELAY diff --git a/components/bt/bluedroid/osi/alarm.c b/components/bt/bluedroid/osi/alarm.c index fb24824d37..9b24d8e5dd 100755 --- a/components/bt/bluedroid/osi/alarm.c +++ b/components/bt/bluedroid/osi/alarm.c @@ -73,7 +73,7 @@ static void alarm_cb_handler(TimerHandle_t xTimer) } } -osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire) +osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire, bool is_periodic) { struct alarm_t *timer_id; TimerHandle_t t; @@ -88,7 +88,8 @@ osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void return NULL; } - t = xTimerCreate(alarm_name, timer_expire / portTICK_PERIOD_MS, pdFALSE, timer_id, alarm_cb_handler); + portBASE_TYPE auto_reload = is_periodic ? pdTRUE : pdFALSE; + t = xTimerCreate(alarm_name, timer_expire / portTICK_PERIOD_MS, auto_reload, timer_id, alarm_cb_handler); if (!t) { LOG_ERROR("%s error\n", __func__); return NULL; diff --git a/components/bt/bluedroid/osi/include/alarm.h b/components/bt/bluedroid/osi/include/alarm.h index b4cd1347c2..4fea94c3ed 100755 --- a/components/bt/bluedroid/osi/include/alarm.h +++ b/components/bt/bluedroid/osi/include/alarm.h @@ -20,6 +20,7 @@ #define _ALARM_H_ #include +#include #include #include @@ -39,7 +40,7 @@ void osi_alarm_init(void); // Creates a new alarm object. The returned object must be freed by calling // |alarm_free|. Returns NULL on failure. -osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire); +osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire, bool is_periodc); // Frees an alarm object created by |alarm_new|. |alarm| may be NULL. If the // alarm is pending, it will be cancelled. It is not safe to call |alarm_free| diff --git a/components/bt/bluedroid/osi/include/thread.h b/components/bt/bluedroid/osi/include/thread.h index 80d8551c7b..f49aae1aca 100644 --- a/components/bt/bluedroid/osi/include/thread.h +++ b/components/bt/bluedroid/osi/include/thread.h @@ -26,7 +26,7 @@ enum { SIG_PRF_WORK = 0xfd, SIG_BTU_START_UP = 0xfe, SIG_BTU_WORK = 0xff, - SIG_BTIF_WORK = 0xff + // SIG_BTIF_WORK = 0xff }; void btu_task_post(uint32_t sig); diff --git a/components/bt/bluedroid/stack/btu/btu_task.c b/components/bt/bluedroid/stack/btu/btu_task.c index 05231e08f7..16a6c79597 100755 --- a/components/bt/bluedroid/stack/btu/btu_task.c +++ b/components/bt/bluedroid/stack/btu/btu_task.c @@ -522,7 +522,7 @@ void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) { // Get the alarm for the timer list entry. pthread_mutex_lock(&btu_general_alarm_lock); if (!hash_map_has_key(btu_general_alarm_hash_map, p_tle)) { - alarm = osi_alarm_new("btu_gen", btu_general_alarm_cb, (void *)p_tle, 0); + alarm = osi_alarm_new("btu_gen", btu_general_alarm_cb, (void *)p_tle, 0, false); hash_map_set(btu_general_alarm_hash_map, p_tle, alarm); } pthread_mutex_unlock(&btu_general_alarm_lock); @@ -607,7 +607,7 @@ void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ti // Get the alarm for the timer list entry. pthread_mutex_lock(&btu_l2cap_alarm_lock); if (!hash_map_has_key(btu_l2cap_alarm_hash_map, p_tle)) { - alarm = osi_alarm_new("btu_l2cap", btu_l2cap_alarm_cb, (void *)p_tle, 0); + alarm = osi_alarm_new("btu_l2cap", btu_l2cap_alarm_cb, (void *)p_tle, 0, false); hash_map_set(btu_l2cap_alarm_hash_map, p_tle, (void *)alarm); } pthread_mutex_unlock(&btu_l2cap_alarm_lock); @@ -674,7 +674,7 @@ void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ // Get the alarm for the timer list entry. pthread_mutex_lock(&btu_oneshot_alarm_lock); if (!hash_map_has_key(btu_oneshot_alarm_hash_map, p_tle)) { - alarm = osi_alarm_new("btu_oneshot", btu_oneshot_alarm_cb, (void *)p_tle, 0); + alarm = osi_alarm_new("btu_oneshot", btu_oneshot_alarm_cb, (void *)p_tle, 0, false); hash_map_set(btu_oneshot_alarm_hash_map, p_tle, alarm); } pthread_mutex_unlock(&btu_oneshot_alarm_lock); diff --git a/components/bt/bluedroid/utils/bt_utils.c b/components/bt/bluedroid/utils/bt_utils.c new file mode 100644 index 0000000000..985b9537e4 --- /dev/null +++ b/components/bt/bluedroid/utils/bt_utils.c @@ -0,0 +1,32 @@ +#include "bt_utils.h" + + +/***************************************************************************** +** +** Function raise_priority_a2dp +** +** Description Raise task priority for A2DP streaming +** +** Returns void +** +*******************************************************************************/ +void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) +{ + return; +} + +/***************************************************************************** +** +** Function adjust_priority_a2dp +** +** Description increase the a2dp consumer task priority temporarily when start +** audio playing, to avoid overflow the audio packet queue, restore +** the a2dp consumer task priority when stop audio playing. +** +** Returns void +** +*******************************************************************************/ +void adjust_priority_a2dp(int start) +{ + return; +} diff --git a/components/bt/bluedroid/utils/include/bt_utils.h b/components/bt/bluedroid/utils/include/bt_utils.h index e77fad862a..39e2535513 100755 --- a/components/bt/bluedroid/utils/include/bt_utils.h +++ b/components/bt/bluedroid/utils/include/bt_utils.h @@ -40,7 +40,7 @@ typedef enum { ** Functions ********************************************************************************/ -// void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task); -// void adjust_priority_a2dp(int start); +void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task); +void adjust_priority_a2dp(int start); #define UNUSED(x) (void)(x) #endif /* BT_UTILS_H */ diff --git a/examples/06_bluedroid_demos/components/bluedroid_demos/app_core/bt_app_core.c b/examples/06_bluedroid_demos/components/bluedroid_demos/app_core/bt_app_core.c index 09b7206ef5..5bc60b0d2d 100644 --- a/examples/06_bluedroid_demos/components/bluedroid_demos/app_core/bt_app_core.c +++ b/examples/06_bluedroid_demos/components/bluedroid_demos/app_core/bt_app_core.c @@ -329,7 +329,7 @@ void bt_app_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) // Get the alarm for the timer list entry. pthread_mutex_lock(&bt_app_general_alarm_lock); if (!hash_map_has_key(bt_app_general_alarm_hash_map, p_tle)) { - alarm = osi_alarm_new("bt_app", bt_app_general_alarm_cb, (void *)p_tle, 0); + alarm = osi_alarm_new("bt_app", bt_app_general_alarm_cb, (void *)p_tle, 0. false); hash_map_set(bt_app_general_alarm_hash_map, p_tle, alarm); } pthread_mutex_unlock(&bt_app_general_alarm_lock); diff --git a/examples/08_bt_sdp/components/bluedroid_demos/btif/btif_core.c b/examples/08_bt_sdp/components/bluedroid_demos/btif/btif_core.c index 97dc8baf79..2ca63a0b69 100755 --- a/examples/08_bt_sdp/components/bluedroid_demos/btif/btif_core.c +++ b/examples/08_bt_sdp/components/bluedroid_demos/btif/btif_core.c @@ -90,7 +90,7 @@ static void btif_thread_post(uint32_t sig); /************************************************************************************ ** Externs ************************************************************************************/ -static fixed_queue_t *xBtifQueue = NULL; +static QueueHandle_t xBtifQueue = NULL; /** TODO: Move these to _common.h */ void bte_main_boot_entry(void *); diff --git a/examples/08_bt_sdp/components/bluedroid_demos/include/btif_util.h b/examples/08_bt_sdp/components/bluedroid_demos/include/btif_util.h index 8c5e035fc7..9f2595b1d8 100755 --- a/examples/08_bt_sdp/components/bluedroid_demos/include/btif_util.h +++ b/examples/08_bt_sdp/components/bluedroid_demos/include/btif_util.h @@ -26,7 +26,7 @@ // #include #include "bt_types.h" -// #include "bt_utils.h" +#include "bt_utils.h" #include "bt_defs.h" /******************************************************************************* diff --git a/examples/09_a2dp/Makefile b/examples/09_a2dp/Makefile new file mode 100755 index 0000000000..1e91bbb891 --- /dev/null +++ b/examples/09_a2dp/Makefile @@ -0,0 +1,11 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := bluedroid_demos + +COMPONENT_ADD_INCLUDEDIRS := components/include + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/09_a2dp/README.rst b/examples/09_a2dp/README.rst new file mode 100755 index 0000000000..49306a2fd1 --- /dev/null +++ b/examples/09_a2dp/README.rst @@ -0,0 +1,5 @@ +ESP-IDF 09 A2DP +======================= + +Demo of A2DP audio sink role + diff --git a/examples/09_a2dp/components/bluedroid_demos/app_core/bt_app_core.c b/examples/09_a2dp/components/bluedroid_demos/app_core/bt_app_core.c new file mode 100755 index 0000000000..5a35eb88bf --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/app_core/bt_app_core.c @@ -0,0 +1,174 @@ +#include +#include +#include + +#include "fixed_queue.h" +#include "gki.h" +#include "bt_defs.h" +#include "bt_trace.h" +#include "bt_types.h" +#include "allocator.h" + +#include "bta_api.h" +#include "bta_gatt_api.h" +#include "bt_app_common.h" + +#include "controller.h" +#include "thread.h" +#include "bt_app_common.h" + +static fixed_queue_t *bt_app_msg_queue; + +xQueueHandle xBtAppQueue; +xTaskHandle xBtAppTaskHandle; + +static void bt_app_context_switched(void *p_msg); +static void bt_app_send_msg(void *p_msg); +static void bt_app_task_handler(void *arg); +static void bta_app_msg_ready(fixed_queue_t *queue); +static void bt_app_task_shut_down(void); + + +extern void app_main_entry(void); + +static void bt_app_task_handler(void *arg) +{ + app_main_entry(); + BtTaskEvt_t *e; + for (;;) { + if (pdTRUE == xQueueReceive(xBtAppQueue, &e, (portTickType)portMAX_DELAY)) { + if (e->sig == 0xff) { + fixed_queue_process(bt_app_msg_queue); + } + osi_free(e); + } + } +} + +static void bt_app_task_post(void) +{ + BtTaskEvt_t *evt = (BtTaskEvt_t *)osi_malloc(sizeof(BtTaskEvt_t)); + if (evt == NULL) + return; + + evt->sig = 0xff; + evt->par = 0; + + if (xQueueSend(xBtAppQueue, &evt, 10/portTICK_RATE_MS) != pdTRUE) { + ets_printf("btdm_post failed\n"); + } +} + +static void bta_app_msg_ready(fixed_queue_t *queue) { + BT_HDR *p_msg; + while (!fixed_queue_is_empty(queue)) { + p_msg = (BT_HDR *)fixed_queue_dequeue(queue); + LOG_ERROR("bta_app_msg_ready, evt: %d\n", p_msg->event); + switch (p_msg->event) { + case BT_EVT_APP_CONTEXT_SWITCH: + bt_app_context_switched(p_msg); + break; + default: + LOG_ERROR("unhandled BT_APP event (%d)\n", p_msg->event & BT_EVT_MASK); + break; + } + GKI_freebuf(p_msg); + } +} + +static void bt_app_context_switched(void *p_msg) +{ + tBTAPP_CONTEXT_SWITCH_CBACK *p = (tBTAPP_CONTEXT_SWITCH_CBACK *) p_msg; + + if (p->p_cb) + p->p_cb(p->event, p->p_param); +} + +static void bt_app_send_msg(void *p_msg) +{ + if (bt_app_msg_queue) { + fixed_queue_enqueue(bt_app_msg_queue, p_msg); + bt_app_task_post(); + } +} + +bt_status_t bt_app_transfer_context (tBTAPP_CBACK *p_cback, UINT16 event, char* p_params, int param_len, tBTAPP_COPY_CBACK *p_copy_cback) +{ + tBTAPP_CONTEXT_SWITCH_CBACK *p_msg; + + LOG_ERROR("btapp_transfer_context evt %d, len %d\n", event, param_len); + + /* allocate and send message that will be executed in btif context */ + if ((p_msg = (tBTAPP_CONTEXT_SWITCH_CBACK *) GKI_getbuf(sizeof(tBTAPP_CONTEXT_SWITCH_CBACK) + param_len)) != NULL) + { + p_msg->hdr.event = BT_EVT_APP_CONTEXT_SWITCH; /* internal event */ + p_msg->p_cb = p_cback; + + p_msg->event = event; /* callback event */ + + /* check if caller has provided a copy callback to do the deep copy */ + if (p_copy_cback) + { + p_copy_cback(event, p_msg->p_param, p_params); + } + else if (p_params) + { + memcpy(p_msg->p_param, p_params, param_len); /* callback parameter data */ + } + + bt_app_send_msg(p_msg); + return BT_STATUS_SUCCESS; + } + else + { + /* let caller deal with a failed allocation */ + return BT_STATUS_NOMEM; + } +} + +void bt_app_task_start_up(void) +{ + bt_app_msg_queue = fixed_queue_new(SIZE_MAX); + if (bt_app_msg_queue == NULL) + goto error_exit; + //ke_event_callback_set(KE_EVENT_BT_APP_TASK, &bt_app_task_handler); + + xBtAppQueue = xQueueCreate(3, sizeof(void *)); + xTaskCreate(bt_app_task_handler, "BtaApp1T", 8192, NULL, configMAX_PRIORITIES - 3, xBtAppTaskHandle); + + fixed_queue_register_dequeue(bt_app_msg_queue, bta_app_msg_ready); + + return; + +error_exit: + LOG_ERROR("%s Unable to allocate resources for bt_app\n", __func__); + bt_app_task_shut_down(); +} + +static void bt_app_task_shut_down(void) +{ + fixed_queue_unregister_dequeue(bt_app_msg_queue); + fixed_queue_free(bt_app_msg_queue, NULL); + bt_app_msg_queue = NULL; + + vTaskDelete(xBtAppTaskHandle); + vQueueDelete(xBtAppQueue); +} + +/* +static void bt_app_upstreams_evt(UINT16 event, char *p_param) +{ + tBTA_DM_SEC *p_data = (tBTA_DM_SEC*)p_param; + switch (event) { + default: + break; + } +} + +static void bt_stack_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) +{ + LOG_ERROR("bt_stack_evt: %d\n", (uint16_t)event); + bt_app_transfer_context(bt_app_upstreams_evt, (uint16_t)event, + (void *)p_data, sizeof(tBTA_DM_SEC), NULL); +} +*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/app_project/SampleBtSdp.c b/examples/09_a2dp/components/bluedroid_demos/app_project/SampleBtSdp.c new file mode 100644 index 0000000000..d9574a782a --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/app_project/SampleBtSdp.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include + + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "bt_app_common.h" +#include "btif_stack_manager.h" +#include "btif_sdp.h" +#include "bt_gap_api.h" + +#include "bta_api.h" + +#include "alarm.h" +typedef enum { + BT_APP_EVT_STACK_ON, + BT_APP_EVT_STACK_OFF, + BT_APP_EVT_ADD_SDP_RECORD_TO, + BT_APP_EVT_SDP_SEARCH_START_TO, + BT_APP_EVT +} tBT_APP_EVT; + +typedef union { + uint32_t dummy; +} tBT_APP_EVT_DATA; + +static void bt_stack_evt(tBT_APP_EVT event, tBT_APP_EVT_DATA *p_data); +static void bt_stack_state_changed(bt_state_t state); +static int bt_sdp_add_record(void); +static void bt_sdp_search_complete(bt_status_t status, bt_bdaddr_t *bd_addr, uint8_t* uuid, int num_records, bluetooth_sdp_record *records); + +// static bt_bdaddr_t peer_bd_addr = {{0x00, 0x1b, 0xdc, 0x08, 0x0f, 0xe7}}; +static bt_bdaddr_t peer_bd_addr = {{0xfc, 0x3f, 0x7c, 0xf1, 0x2c, 0x78}}; + +/* root browse +static const uint8_t target_uuid[16] = { 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; +*/ + +/* UUID_MAP_MAS */ +static const uint8_t target_uuid[] = {0x00, 0x00, 0x11, 0x32, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; + +/* UUID AUDIO Source */ +/* +static const uint8_t target_uuid[] = {0x00, 0x00, 0x11, 0x0A, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; +*/ + +static bt_callbacks_t bt_callbacks = { + bt_stack_state_changed +}; + +static btsdp_callbacks_t btsdp_callbacks = { + bt_sdp_search_complete +}; + +osi_alarm_t *app_alarm = NULL; + +static void bt_sdp_add_record_to(void *context) +{ + (void)(context); + bt_stack_evt(BT_APP_EVT_ADD_SDP_RECORD_TO, NULL); +} + +static void bt_sdp_search_start_to(void *context) +{ + (void)(context); + bt_stack_evt(BT_APP_EVT_SDP_SEARCH_START_TO, NULL); +} + +static void bt_app_stack_evt(UINT16 event, char *p_param) +{ + switch (event) { + case BT_APP_EVT_STACK_ON: { + char *dev_name = "SDP_SERVER_CLIENT"; + BTM_SetTraceLevel(BT_TRACE_LEVEL_DEBUG); + BTA_DmSetDeviceName(dev_name); + + esp_bt_gap_set_scan_mode(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); + BTIF_SdpInit(&btsdp_callbacks); + + app_alarm = osi_alarm_new("app_alarm", bt_sdp_add_record_to, NULL, 1000, false); + osi_alarm_set(app_alarm, 1000); + } + break; + case BT_APP_EVT_ADD_SDP_RECORD_TO: { + bt_sdp_add_record(); + osi_alarm_free(app_alarm); + app_alarm = NULL; + app_alarm = osi_alarm_new("app_alarm", bt_sdp_search_start_to, NULL, 20000, false); + osi_alarm_set(app_alarm, 20000); + } + break; + case BT_APP_EVT_SDP_SEARCH_START_TO: { + osi_alarm_free(app_alarm); + app_alarm = NULL; + BTIF_SdpSearch(&peer_bd_addr, target_uuid); + } + break; + default: + break; + } +} + +static void bt_stack_evt(tBT_APP_EVT event, tBT_APP_EVT_DATA *p_data) +{ + LOG_ERROR("bt_stack_evt: %d\n", (uint16_t)event); + bt_app_transfer_context(bt_app_stack_evt, (uint16_t)event, + (void *)p_data, sizeof(tBT_APP_EVT_DATA), NULL); +} + +static void bt_stack_state_changed(bt_state_t state) +{ + if (state == BT_STATE_ON) { + bt_stack_evt(BT_APP_EVT_STACK_ON, NULL); + } +} + +static int bt_sdp_add_record(void) +{ + int handle; + bluetooth_sdp_sap_record sap_svr; + memset (&sap_svr, 0, sizeof(bluetooth_sdp_sap_record)); + + sap_svr.hdr.type = SDP_TYPE_SAP_SERVER; + sap_svr.hdr.rfcomm_channel_number = 2; + sap_svr.hdr.service_name = "SIM ACCESS"; + sap_svr.hdr.service_name_length = 10; + sap_svr.hdr.profile_version = 0x0100; + + BTIF_SdpCreateRecord((bluetooth_sdp_record *)(&sap_svr), &handle); + return handle; +} + +static void bt_sdp_search_complete(bt_status_t status, bt_bdaddr_t *bd_addr, uint8_t* uuid, int num_records, bluetooth_sdp_record *records) +{ + uint8_t *addr = bd_addr->address; + bluetooth_sdp_hdr_overlay *p = &records->mas.hdr; + LOG_ERROR("sdp search cmpl: st %d, bd_addr: %02x:%02x:%02x:%02x:%02x:%02x, records %d\n", + status, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], num_records); + if (p->service_name_length > 0) { + LOG_ERROR("service name: %s\n", p->service_name); + } + LOG_ERROR("rfc_chl_num %d, l2cap_psm %d, version %02x\n", + p->rfcomm_channel_number, p->l2cap_psm, p->profile_version); +#if 0 + uint8_t *addr = bd_addr->address; + bluetooth_sdp_hdr_overlay *p = &records->hdr; + LOG_ERROR("sdp search cmpl: st %d, bd_addr: %02x:%02x:%02x:%02x:%02x:%02x, records %d, len:%d\n", + status, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], num_records, p->user1_ptr_len); + if (p->service_name_length > 0) { + LOG_ERROR("service name: %s\n", p->service_name); + } +#endif +} + +void app_main_entry(void) +{ + bt_status_t stat; + stat = BTIF_InitStack(&bt_callbacks); + if (stat == BT_STATUS_SUCCESS) { + BTIF_EnableStack(); + } +} + diff --git a/examples/09_a2dp/components/bluedroid_demos/audio_a2dp_hw/audio_a2dp_hw.c b/examples/09_a2dp/components/bluedroid_demos/audio_a2dp_hw/audio_a2dp_hw.c new file mode 100755 index 0000000000..29803366e2 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/audio_a2dp_hw/audio_a2dp_hw.c @@ -0,0 +1,1423 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/***************************************************************************** + * + * Filename: audio_a2dp_hw.c + * + * Description: Implements hal for bluedroid a2dp audio device + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "audio_a2dp_hw.h" +#include "bt_utils.h" + +#define LOG_TAG "bt_a2dp_hw" +#include "osi/include/log.h" + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ + +#define CTRL_CHAN_RETRY_COUNT 3 +#define USEC_PER_SEC 1000000L + +#define CASE_RETURN_STR(const) case const: return #const; + +#define FNLOG() LOG_VERBOSE("%s", __FUNCTION__); +#define DEBUG(fmt, ...) LOG_VERBOSE("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define INFO(fmt, ...) LOG_INFO("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define ERROR(fmt, ...) LOG_ERROR("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) + +#define ASSERTC(cond, msg, val) if (!(cond)) {ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);} + +/***************************************************************************** +** Local type definitions +******************************************************************************/ + +typedef enum { + AUDIO_A2DP_STATE_STARTING, + AUDIO_A2DP_STATE_STARTED, + AUDIO_A2DP_STATE_STOPPING, + AUDIO_A2DP_STATE_STOPPED, + AUDIO_A2DP_STATE_SUSPENDED, /* need explicit set param call to resume (suspend=false) */ + AUDIO_A2DP_STATE_STANDBY /* allows write to autoresume */ +} a2dp_state_t; + +struct a2dp_stream_in; +struct a2dp_stream_out; + +struct a2dp_audio_device { + struct audio_hw_device device; + struct a2dp_stream_in *input; + struct a2dp_stream_out *output; +}; + +struct a2dp_config { + uint32_t rate; + uint32_t channel_flags; + int format; +}; + +/* move ctrl_fd outside output stream and keep open until HAL unloaded ? */ + +struct a2dp_stream_common { + pthread_mutex_t lock; + int ctrl_fd; + int audio_fd; + size_t buffer_sz; + struct a2dp_config cfg; + a2dp_state_t state; +}; + +struct a2dp_stream_out { + struct audio_stream_out stream; + struct a2dp_stream_common common; + uint64_t frames_presented; // frames written, never reset + uint64_t frames_rendered; // frames written, reset on standby +}; + +struct a2dp_stream_in { + struct audio_stream_in stream; + struct a2dp_stream_common common; +}; + +/***************************************************************************** +** Static variables +******************************************************************************/ + +/***************************************************************************** +** Static functions +******************************************************************************/ + +static size_t out_get_buffer_size(const struct audio_stream *stream); + +/***************************************************************************** +** Externs +******************************************************************************/ + +/***************************************************************************** +** Functions +******************************************************************************/ + +/***************************************************************************** +** Miscellaneous helper functions +******************************************************************************/ + +static const char* dump_a2dp_ctrl_event(char event) +{ + switch(event) + { + CASE_RETURN_STR(A2DP_CTRL_CMD_NONE) + CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_READY) + CASE_RETURN_STR(A2DP_CTRL_CMD_START) + CASE_RETURN_STR(A2DP_CTRL_CMD_STOP) + CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND) + default: + return "UNKNOWN MSG ID"; + } +} + +/* logs timestamp with microsec precision + pprev is optional in case a dedicated diff is required */ +static void ts_log(char *tag, int val, struct timespec *pprev_opt) +{ + struct timespec now; + static struct timespec prev = {0,0}; + unsigned long long now_us; + unsigned long long diff_us; + UNUSED(tag); + UNUSED(val); + + clock_gettime(CLOCK_MONOTONIC, &now); + + now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000; + + if (pprev_opt) + { + diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000; + *pprev_opt = now; + DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val); + } + else + { + diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000; + prev = now; + DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val); + } +} + +static int calc_audiotime(struct a2dp_config cfg, int bytes) +{ + int chan_count = popcount(cfg.channel_flags); + + ASSERTC(cfg.format == AUDIO_FORMAT_PCM_16_BIT, + "unsupported sample sz", cfg.format); + + return bytes*(1000000/(chan_count*2))/cfg.rate; +} + +/***************************************************************************** +** +** bluedroid stack adaptation +** +*****************************************************************************/ + +static int skt_connect(char *path, size_t buffer_sz) +{ + int ret; + int skt_fd; + struct sockaddr_un remote; + int len; + + INFO("connect to %s (sz %zu)", path, buffer_sz); + + skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0); + + if(socket_local_client_connect(skt_fd, path, + ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0) + { + ERROR("failed to connect (%s)", strerror(errno)); + close(skt_fd); + return -1; + } + + len = buffer_sz; + ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len)); + + /* only issue warning if failed */ + if (ret < 0) + ERROR("setsockopt failed (%s)", strerror(errno)); + + ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, (int)sizeof(len)); + + /* only issue warning if failed */ + if (ret < 0) + ERROR("setsockopt failed (%s)", strerror(errno)); + + INFO("connected to stack fd = %d", skt_fd); + + return skt_fd; +} + +static int skt_read(int fd, void *p, size_t len) +{ + int read; + struct pollfd pfd; + struct timespec ts; + + FNLOG(); + + ts_log("skt_read recv", len, NULL); + + if ((read = recv(fd, p, len, MSG_NOSIGNAL)) == -1) + { + ERROR("write failed with errno=%d\n", errno); + return -1; + } + + return read; +} + +static int skt_write(int fd, const void *p, size_t len) +{ + int sent; + struct pollfd pfd; + + FNLOG(); + + pfd.fd = fd; + pfd.events = POLLOUT; + + /* poll for 500 ms */ + + /* send time out */ + if (poll(&pfd, 1, 500) == 0) + return 0; + + ts_log("skt_write", len, NULL); + + if ((sent = send(fd, p, len, MSG_NOSIGNAL)) == -1) + { + ERROR("write failed with errno=%d\n", errno); + return -1; + } + + return sent; +} + +static int skt_disconnect(int fd) +{ + INFO("fd %d", fd); + + if (fd != AUDIO_SKT_DISCONNECTED) + { + shutdown(fd, SHUT_RDWR); + close(fd); + } + return 0; +} + + + +/***************************************************************************** +** +** AUDIO CONTROL PATH +** +*****************************************************************************/ + +static int a2dp_ctrl_receive(struct a2dp_stream_common *common, void* buffer, int length) +{ + int ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL); + if (ret < 0) + { + ERROR("ack failed (%s)", strerror(errno)); + if (errno == EINTR) + { + /* retry again */ + ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL); + if (ret < 0) + { + ERROR("ack failed (%s)", strerror(errno)); + skt_disconnect(common->ctrl_fd); + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + return -1; + } + } + else + { + skt_disconnect(common->ctrl_fd); + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + return -1; + + } + } + return ret; +} + +static int a2dp_command(struct a2dp_stream_common *common, char cmd) +{ + char ack; + + DEBUG("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd)); + + /* send command */ + if (send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL) == -1) + { + ERROR("cmd failed (%s)", strerror(errno)); + skt_disconnect(common->ctrl_fd); + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + return -1; + } + + /* wait for ack byte */ + if (a2dp_ctrl_receive(common, &ack, 1) < 0) + return -1; + + DEBUG("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack); + + if (ack == A2DP_CTRL_ACK_INCALL_FAILURE) + return ack; + if (ack != A2DP_CTRL_ACK_SUCCESS) + return -1; + + return 0; +} + +static int check_a2dp_ready(struct a2dp_stream_common *common) +{ + if (a2dp_command(common, A2DP_CTRL_CMD_CHECK_READY) < 0) + { + ERROR("check a2dp ready failed"); + return -1; + } + return 0; +} + +static int a2dp_read_audio_config(struct a2dp_stream_common *common) +{ + char cmd = A2DP_CTRL_GET_AUDIO_CONFIG; + uint32_t sample_rate; + uint8_t channel_count; + + if (a2dp_command(common, A2DP_CTRL_GET_AUDIO_CONFIG) < 0) + { + ERROR("check a2dp ready failed"); + return -1; + } + + if (a2dp_ctrl_receive(common, &sample_rate, 4) < 0) + return -1; + if (a2dp_ctrl_receive(common, &channel_count, 1) < 0) + return -1; + + common->cfg.channel_flags = (channel_count == 1 ? AUDIO_CHANNEL_IN_MONO : AUDIO_CHANNEL_IN_STEREO); + common->cfg.format = AUDIO_STREAM_DEFAULT_FORMAT; + common->cfg.rate = sample_rate; + + INFO("got config %d %d", common->cfg.format, common->cfg.rate); + + return 0; +} + +static void a2dp_open_ctrl_path(struct a2dp_stream_common *common) +{ + int i; + + /* retry logic to catch any timing variations on control channel */ + for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++) + { + /* connect control channel if not already connected */ + if ((common->ctrl_fd = skt_connect(A2DP_CTRL_PATH, common->buffer_sz)) > 0) + { + /* success, now check if stack is ready */ + if (check_a2dp_ready(common) == 0) + break; + + ERROR("error : a2dp not ready, wait 250 ms and retry"); + usleep(250000); + skt_disconnect(common->ctrl_fd); + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + } + + /* ctrl channel not ready, wait a bit */ + usleep(250000); + } +} + +/***************************************************************************** +** +** AUDIO DATA PATH +** +*****************************************************************************/ + +static void a2dp_stream_common_init(struct a2dp_stream_common *common) +{ + pthread_mutexattr_t lock_attr; + + FNLOG(); + + pthread_mutexattr_init(&lock_attr); + pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&common->lock, &lock_attr); + + common->ctrl_fd = AUDIO_SKT_DISCONNECTED; + common->audio_fd = AUDIO_SKT_DISCONNECTED; + common->state = AUDIO_A2DP_STATE_STOPPED; + + /* manages max capacity of socket pipe */ + common->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ; +} + +static int start_audio_datapath(struct a2dp_stream_common *common) +{ + INFO("state %d", common->state); + + if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) { + INFO("%s AUDIO_SKT_DISCONNECTED", __func__); + return -1; + } + + int oldstate = common->state; + common->state = AUDIO_A2DP_STATE_STARTING; + + int a2dp_status = a2dp_command(common, A2DP_CTRL_CMD_START); + if (a2dp_status < 0) + { + ERROR("%s Audiopath start failed (status %d)", __func__, a2dp_status); + + common->state = oldstate; + return -1; + } + else if (a2dp_status == A2DP_CTRL_ACK_INCALL_FAILURE) + { + ERROR("%s Audiopath start failed - in call, move to suspended", __func__); + common->state = oldstate; + return -1; + } + + /* connect socket if not yet connected */ + if (common->audio_fd == AUDIO_SKT_DISCONNECTED) + { + common->audio_fd = skt_connect(A2DP_DATA_PATH, common->buffer_sz); + if (common->audio_fd < 0) + { + common->state = oldstate; + return -1; + } + + common->state = AUDIO_A2DP_STATE_STARTED; + } + + return 0; +} + +static int stop_audio_datapath(struct a2dp_stream_common *common) +{ + int oldstate = common->state; + + INFO("state %d", common->state); + + if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) + return -1; + + /* prevent any stray output writes from autostarting the stream + while stopping audiopath */ + common->state = AUDIO_A2DP_STATE_STOPPING; + + if (a2dp_command(common, A2DP_CTRL_CMD_STOP) < 0) + { + ERROR("audiopath stop failed"); + common->state = oldstate; + return -1; + } + + common->state = AUDIO_A2DP_STATE_STOPPED; + + /* disconnect audio path */ + skt_disconnect(common->audio_fd); + common->audio_fd = AUDIO_SKT_DISCONNECTED; + + return 0; +} + +static int suspend_audio_datapath(struct a2dp_stream_common *common, bool standby) +{ + INFO("state %d", common->state); + + if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) + return -1; + + if (common->state == AUDIO_A2DP_STATE_STOPPING) + return -1; + + if (a2dp_command(common, A2DP_CTRL_CMD_SUSPEND) < 0) + return -1; + + if (standby) + common->state = AUDIO_A2DP_STATE_STANDBY; + else + common->state = AUDIO_A2DP_STATE_SUSPENDED; + + /* disconnect audio path */ + skt_disconnect(common->audio_fd); + + common->audio_fd = AUDIO_SKT_DISCONNECTED; + + return 0; +} + + +/***************************************************************************** +** +** audio output callbacks +** +*****************************************************************************/ + +static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, + size_t bytes) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + int sent; + + DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd); + + pthread_mutex_lock(&out->common.lock); + + if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED) + { + DEBUG("stream suspended"); + pthread_mutex_unlock(&out->common.lock); + return -1; + } + + /* only allow autostarting if we are in stopped or standby */ + if ((out->common.state == AUDIO_A2DP_STATE_STOPPED) || + (out->common.state == AUDIO_A2DP_STATE_STANDBY)) + { + if (start_audio_datapath(&out->common) < 0) + { + /* emulate time this write represents to avoid very fast write + failures during transition periods or remote suspend */ + + int us_delay = calc_audiotime(out->common.cfg, bytes); + + DEBUG("emulate a2dp write delay (%d us)", us_delay); + + usleep(us_delay); + pthread_mutex_unlock(&out->common.lock); + return -1; + } + } + else if (out->common.state != AUDIO_A2DP_STATE_STARTED) + { + ERROR("stream not in stopped or standby"); + pthread_mutex_unlock(&out->common.lock); + return -1; + } + + pthread_mutex_unlock(&out->common.lock); + sent = skt_write(out->common.audio_fd, buffer, bytes); + + if (sent == -1) { + skt_disconnect(out->common.audio_fd); + out->common.audio_fd = AUDIO_SKT_DISCONNECTED; + if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED) + out->common.state = AUDIO_A2DP_STATE_STOPPED; + else + ERROR("write failed : stream suspended, avoid resetting state"); + } else { + const size_t frames = bytes / audio_stream_out_frame_size(stream); + out->frames_rendered += frames; + out->frames_presented += frames; + } + + DEBUG("wrote %d bytes out of %zu bytes", sent, bytes); + return sent; +} + + +static uint32_t out_get_sample_rate(const struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + DEBUG("rate %" PRIu32,out->common.cfg.rate); + + return out->common.cfg.rate; +} + +static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + DEBUG("out_set_sample_rate : %" PRIu32, rate); + + if (rate != AUDIO_STREAM_DEFAULT_RATE) + { + ERROR("only rate %d supported", AUDIO_STREAM_DEFAULT_RATE); + return -1; + } + + out->common.cfg.rate = rate; + + return 0; +} + +static size_t out_get_buffer_size(const struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + DEBUG("buffer_size : %zu", out->common.buffer_sz); + + return out->common.buffer_sz; +} + +static uint32_t out_get_channels(const struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + DEBUG("channels 0x%" PRIx32, out->common.cfg.channel_flags); + + return out->common.cfg.channel_flags; +} + +static audio_format_t out_get_format(const struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + DEBUG("format 0x%x", out->common.cfg.format); + return out->common.cfg.format; +} + +static int out_set_format(struct audio_stream *stream, audio_format_t format) +{ + UNUSED(format); + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + DEBUG("setting format not yet supported (0x%x)", format); + return -ENOSYS; +} + +static int out_standby(struct audio_stream *stream) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + int retVal = 0; + + FNLOG(); + + pthread_mutex_lock(&out->common.lock); + // Do nothing in SUSPENDED state. + if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED) + retVal = suspend_audio_datapath(&out->common, true); + out->frames_rendered = 0; // rendered is reset, presented is not + pthread_mutex_unlock (&out->common.lock); + + return retVal; +} + +static int out_dump(const struct audio_stream *stream, int fd) +{ + UNUSED(fd); + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + FNLOG(); + return 0; +} + +static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + struct str_parms *parms; + char keyval[16]; + int retval; + int status = 0; + + INFO("state %d", out->common.state); + + parms = str_parms_create_str(kvpairs); + + /* dump params */ + str_parms_dump(parms); + + retval = str_parms_get_str(parms, "closing", keyval, sizeof(keyval)); + + if (retval >= 0) + { + if (strcmp(keyval, "true") == 0) + { + DEBUG("stream closing, disallow any writes"); + pthread_mutex_lock(&out->common.lock); + out->common.state = AUDIO_A2DP_STATE_STOPPING; + pthread_mutex_unlock(&out->common.lock); + } + } + + retval = str_parms_get_str(parms, "A2dpSuspended", keyval, sizeof(keyval)); + + if (retval >= 0) + { + pthread_mutex_lock(&out->common.lock); + if (strcmp(keyval, "true") == 0) + { + if (out->common.state == AUDIO_A2DP_STATE_STARTED) + status = suspend_audio_datapath(&out->common, false); + } + else + { + /* Do not start the streaming automatically. If the phone was streaming + * prior to being suspended, the next out_write shall trigger the + * AVDTP start procedure */ + if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED) + out->common.state = AUDIO_A2DP_STATE_STANDBY; + /* Irrespective of the state, return 0 */ + } + pthread_mutex_unlock(&out->common.lock); + } + + str_parms_destroy(parms); + + return status; +} + +static char * out_get_parameters(const struct audio_stream *stream, const char *keys) +{ + UNUSED(keys); + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + FNLOG(); + + /* add populating param here */ + + return strdup(""); +} + +static uint32_t out_get_latency(const struct audio_stream_out *stream) +{ + int latency_us; + + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + FNLOG(); + + latency_us = ((out->common.buffer_sz * 1000 ) / + audio_stream_out_frame_size(&out->stream) / + out->common.cfg.rate) * 1000; + + + return (latency_us / 1000) + 200; +} + +static int out_set_volume(struct audio_stream_out *stream, float left, + float right) +{ + UNUSED(stream); + UNUSED(left); + UNUSED(right); + + FNLOG(); + + /* volume controlled in audioflinger mixer (digital) */ + + return -ENOSYS; +} + +static int out_get_presentation_position(const struct audio_stream_out *stream, + uint64_t *frames, struct timespec *timestamp) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + FNLOG(); + if (stream == NULL || frames == NULL || timestamp == NULL) + return -EINVAL; + + int ret = -EWOULDBLOCK; + pthread_mutex_lock(&out->common.lock); + uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000; + if (out->frames_presented >= latency_frames) { + *frames = out->frames_presented - latency_frames; + clock_gettime(CLOCK_MONOTONIC, timestamp); // could also be associated with out_write(). + ret = 0; + } + pthread_mutex_unlock(&out->common.lock); + return ret; +} + +static int out_get_render_position(const struct audio_stream_out *stream, + uint32_t *dsp_frames) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + FNLOG(); + if (stream == NULL || dsp_frames == NULL) + return -EINVAL; + + pthread_mutex_lock(&out->common.lock); + uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000; + if (out->frames_rendered >= latency_frames) { + *dsp_frames = (uint32_t)(out->frames_rendered - latency_frames); + } else { + *dsp_frames = 0; + } + pthread_mutex_unlock(&out->common.lock); + return 0; +} + +static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + UNUSED(stream); + UNUSED(effect); + + FNLOG(); + return 0; +} + +static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + UNUSED(stream); + UNUSED(effect); + + FNLOG(); + return 0; +} + +/* + * AUDIO INPUT STREAM + */ + +static uint32_t in_get_sample_rate(const struct audio_stream *stream) +{ + struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream; + + FNLOG(); + return in->common.cfg.rate; +} + +static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) +{ + struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream; + + FNLOG(); + + if (in->common.cfg.rate > 0 && in->common.cfg.rate == rate) + return 0; + else + return -1; +} + +static size_t in_get_buffer_size(const struct audio_stream *stream) +{ + UNUSED(stream); + + FNLOG(); + return 320; +} + +static uint32_t in_get_channels(const struct audio_stream *stream) +{ + struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream; + + FNLOG(); + return in->common.cfg.channel_flags; +} + +static audio_format_t in_get_format(const struct audio_stream *stream) +{ + UNUSED(stream); + + FNLOG(); + return AUDIO_FORMAT_PCM_16_BIT; +} + +static int in_set_format(struct audio_stream *stream, audio_format_t format) +{ + UNUSED(stream); + UNUSED(format); + + FNLOG(); + if (format == AUDIO_FORMAT_PCM_16_BIT) + return 0; + else + return -1; +} + +static int in_standby(struct audio_stream *stream) +{ + UNUSED(stream); + + FNLOG(); + return 0; +} + +static int in_dump(const struct audio_stream *stream, int fd) +{ + UNUSED(stream); + UNUSED(fd); + + FNLOG(); + return 0; +} + +static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) +{ + UNUSED(stream); + UNUSED(kvpairs); + + FNLOG(); + return 0; +} + +static char * in_get_parameters(const struct audio_stream *stream, + const char *keys) +{ + UNUSED(stream); + UNUSED(keys); + + FNLOG(); + return strdup(""); +} + +static int in_set_gain(struct audio_stream_in *stream, float gain) +{ + UNUSED(stream); + UNUSED(gain); + + FNLOG(); + return 0; +} + +static ssize_t in_read(struct audio_stream_in *stream, void* buffer, + size_t bytes) +{ + struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream; + int read; + + DEBUG("read %zu bytes, state: %d", bytes, in->common.state); + + if (in->common.state == AUDIO_A2DP_STATE_SUSPENDED) + { + DEBUG("stream suspended"); + return -1; + } + + /* only allow autostarting if we are in stopped or standby */ + if ((in->common.state == AUDIO_A2DP_STATE_STOPPED) || + (in->common.state == AUDIO_A2DP_STATE_STANDBY)) + { + pthread_mutex_lock(&in->common.lock); + + if (start_audio_datapath(&in->common) < 0) + { + /* emulate time this write represents to avoid very fast write + failures during transition periods or remote suspend */ + + int us_delay = calc_audiotime(in->common.cfg, bytes); + + DEBUG("emulate a2dp read delay (%d us)", us_delay); + + usleep(us_delay); + pthread_mutex_unlock(&in->common.lock); + return -1; + } + + pthread_mutex_unlock(&in->common.lock); + } + else if (in->common.state != AUDIO_A2DP_STATE_STARTED) + { + ERROR("stream not in stopped or standby"); + return -1; + } + + read = skt_read(in->common.audio_fd, buffer, bytes); + + if (read == -1) + { + skt_disconnect(in->common.audio_fd); + in->common.audio_fd = AUDIO_SKT_DISCONNECTED; + in->common.state = AUDIO_A2DP_STATE_STOPPED; + } else if (read == 0) { + DEBUG("read time out - return zeros"); + memset(buffer, 0, bytes); + read = bytes; + } + + DEBUG("read %d bytes out of %zu bytes", read, bytes); + return read; +} + +static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) +{ + UNUSED(stream); + + FNLOG(); + return 0; +} + +static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + UNUSED(stream); + UNUSED(effect); + + FNLOG(); + return 0; +} + +static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) +{ + UNUSED(stream); + UNUSED(effect); + + FNLOG(); + + return 0; +} + +static int adev_open_output_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + audio_output_flags_t flags, + struct audio_config *config, + struct audio_stream_out **stream_out, + const char *address) + +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_out *out; + int ret = 0; + int i; + UNUSED(address); + UNUSED(handle); + UNUSED(devices); + UNUSED(flags); + + INFO("opening output"); + + out = (struct a2dp_stream_out *)calloc(1, sizeof(struct a2dp_stream_out)); + + if (!out) + return -ENOMEM; + + out->stream.common.get_sample_rate = out_get_sample_rate; + out->stream.common.set_sample_rate = out_set_sample_rate; + out->stream.common.get_buffer_size = out_get_buffer_size; + out->stream.common.get_channels = out_get_channels; + out->stream.common.get_format = out_get_format; + out->stream.common.set_format = out_set_format; + out->stream.common.standby = out_standby; + out->stream.common.dump = out_dump; + out->stream.common.set_parameters = out_set_parameters; + out->stream.common.get_parameters = out_get_parameters; + out->stream.common.add_audio_effect = out_add_audio_effect; + out->stream.common.remove_audio_effect = out_remove_audio_effect; + out->stream.get_latency = out_get_latency; + out->stream.set_volume = out_set_volume; + out->stream.write = out_write; + out->stream.get_render_position = out_get_render_position; + out->stream.get_presentation_position = out_get_presentation_position; + + + /* initialize a2dp specifics */ + a2dp_stream_common_init(&out->common); + + out->common.cfg.channel_flags = AUDIO_STREAM_DEFAULT_CHANNEL_FLAG; + out->common.cfg.format = AUDIO_STREAM_DEFAULT_FORMAT; + out->common.cfg.rate = AUDIO_STREAM_DEFAULT_RATE; + + /* set output config values */ + if (config) + { + config->format = out_get_format((const struct audio_stream *)&out->stream); + config->sample_rate = out_get_sample_rate((const struct audio_stream *)&out->stream); + config->channel_mask = out_get_channels((const struct audio_stream *)&out->stream); + } + *stream_out = &out->stream; + a2dp_dev->output = out; + + a2dp_open_ctrl_path(&out->common); + if (out->common.ctrl_fd == AUDIO_SKT_DISCONNECTED) + { + ERROR("ctrl socket failed to connect (%s)", strerror(errno)); + ret = -1; + goto err_open; + } + + DEBUG("success"); + /* Delay to ensure Headset is in proper state when START is initiated + from DUT immediately after the connection due to ongoing music playback. */ + usleep(250000); + return 0; + +err_open: + free(out); + *stream_out = NULL; + a2dp_dev->output = NULL; + ERROR("failed"); + return ret; +} + +static void adev_close_output_stream(struct audio_hw_device *dev, + struct audio_stream_out *stream) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + + INFO("closing output (state %d)", out->common.state); + + pthread_mutex_lock(&out->common.lock); + if ((out->common.state == AUDIO_A2DP_STATE_STARTED) || (out->common.state == AUDIO_A2DP_STATE_STOPPING)) + stop_audio_datapath(&out->common); + + skt_disconnect(out->common.ctrl_fd); + free(stream); + a2dp_dev->output = NULL; + pthread_mutex_unlock(&out->common.lock); + + DEBUG("done"); +} + +static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_out *out = a2dp_dev->output; + int retval = 0; + + if (out == NULL) + return retval; + + INFO("state %d", out->common.state); + + retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs); + + return retval; +} + +static char * adev_get_parameters(const struct audio_hw_device *dev, + const char *keys) +{ + struct str_parms *parms; + UNUSED(dev); + + FNLOG(); + + parms = str_parms_create_str(keys); + + str_parms_dump(parms); + + str_parms_destroy(parms); + + return strdup(""); +} + +static int adev_init_check(const struct audio_hw_device *dev) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device*)dev; + + FNLOG(); + + return 0; +} + +static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) +{ + UNUSED(dev); + UNUSED(volume); + + FNLOG(); + + return -ENOSYS; +} + +static int adev_set_master_volume(struct audio_hw_device *dev, float volume) +{ + UNUSED(dev); + UNUSED(volume); + + FNLOG(); + + return -ENOSYS; +} + +static int adev_set_mode(struct audio_hw_device *dev, int mode) +{ + UNUSED(dev); + UNUSED(mode); + + FNLOG(); + + return 0; +} + +static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) +{ + UNUSED(dev); + UNUSED(state); + + FNLOG(); + + return -ENOSYS; +} + +static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) +{ + UNUSED(dev); + UNUSED(state); + + FNLOG(); + + return -ENOSYS; +} + +static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, + const struct audio_config *config) +{ + UNUSED(dev); + UNUSED(config); + + FNLOG(); + + return 320; +} + +static int adev_open_input_stream(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + struct audio_config *config, + struct audio_stream_in **stream_in, + audio_input_flags_t flags, + const char *address, + audio_source_t source) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_in *in; + int ret; + UNUSED(address); + UNUSED(config); + UNUSED(devices); + UNUSED(flags); + UNUSED(handle); + UNUSED(source); + + FNLOG(); + + in = (struct a2dp_stream_in *)calloc(1, sizeof(struct a2dp_stream_in)); + + if (!in) + return -ENOMEM; + + in->stream.common.get_sample_rate = in_get_sample_rate; + in->stream.common.set_sample_rate = in_set_sample_rate; + in->stream.common.get_buffer_size = in_get_buffer_size; + in->stream.common.get_channels = in_get_channels; + in->stream.common.get_format = in_get_format; + in->stream.common.set_format = in_set_format; + in->stream.common.standby = in_standby; + in->stream.common.dump = in_dump; + in->stream.common.set_parameters = in_set_parameters; + in->stream.common.get_parameters = in_get_parameters; + in->stream.common.add_audio_effect = in_add_audio_effect; + in->stream.common.remove_audio_effect = in_remove_audio_effect; + in->stream.set_gain = in_set_gain; + in->stream.read = in_read; + in->stream.get_input_frames_lost = in_get_input_frames_lost; + + /* initialize a2dp specifics */ + a2dp_stream_common_init(&in->common); + + *stream_in = &in->stream; + a2dp_dev->input = in; + + a2dp_open_ctrl_path(&in->common); + if (in->common.ctrl_fd == AUDIO_SKT_DISCONNECTED) + { + ERROR("ctrl socket failed to connect (%s)", strerror(errno)); + ret = -1; + goto err_open; + } + + if (a2dp_read_audio_config(&in->common) < 0) { + ERROR("a2dp_read_audio_config failed (%s)", strerror(errno)); + ret = -1; + goto err_open; + } + + DEBUG("success"); + return 0; + +err_open: + free(in); + *stream_in = NULL; + a2dp_dev->input = NULL; + ERROR("failed"); + return ret; +} + +static void adev_close_input_stream(struct audio_hw_device *dev, + struct audio_stream_in *stream) +{ + struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev; + struct a2dp_stream_in* in = (struct a2dp_stream_in *)stream; + a2dp_state_t state = in->common.state; + + INFO("closing input (state %d)", state); + + if ((state == AUDIO_A2DP_STATE_STARTED) || (state == AUDIO_A2DP_STATE_STOPPING)) + stop_audio_datapath(&in->common); + + skt_disconnect(in->common.ctrl_fd); + free(stream); + a2dp_dev->input = NULL; + + DEBUG("done"); +} + +static int adev_dump(const audio_hw_device_t *device, int fd) +{ + UNUSED(device); + UNUSED(fd); + + FNLOG(); + + return 0; +} + +static int adev_close(hw_device_t *device) +{ + FNLOG(); + + free(device); + return 0; +} + +static int adev_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + struct a2dp_audio_device *adev; + int ret; + + INFO(" adev_open in A2dp_hw module"); + FNLOG(); + + if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) + { + ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE); + return -EINVAL; + } + + adev = calloc(1, sizeof(struct a2dp_audio_device)); + + if (!adev) + return -ENOMEM; + + adev->device.common.tag = HARDWARE_DEVICE_TAG; + adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0; + adev->device.common.module = (struct hw_module_t *) module; + adev->device.common.close = adev_close; + + adev->device.init_check = adev_init_check; + adev->device.set_voice_volume = adev_set_voice_volume; + adev->device.set_master_volume = adev_set_master_volume; + adev->device.set_mode = adev_set_mode; + adev->device.set_mic_mute = adev_set_mic_mute; + adev->device.get_mic_mute = adev_get_mic_mute; + adev->device.set_parameters = adev_set_parameters; + adev->device.get_parameters = adev_get_parameters; + adev->device.get_input_buffer_size = adev_get_input_buffer_size; + adev->device.open_output_stream = adev_open_output_stream; + adev->device.close_output_stream = adev_close_output_stream; + adev->device.open_input_stream = adev_open_input_stream; + adev->device.close_input_stream = adev_close_input_stream; + adev->device.dump = adev_dump; + + adev->output = NULL; + + + *device = &adev->device.common; + + return 0; +} + +static struct hw_module_methods_t hal_module_methods = { + .open = adev_open, +}; + +struct audio_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = AUDIO_HARDWARE_MODULE_ID, + .name = "A2DP Audio HW HAL", + .author = "The Android Open Source Project", + .methods = &hal_module_methods, + }, +}; diff --git a/examples/09_a2dp/components/bluedroid_demos/audio_a2dp_hw/include/audio_a2dp_hw.h b/examples/09_a2dp/components/bluedroid_demos/audio_a2dp_hw/include/audio_a2dp_hw.h new file mode 100755 index 0000000000..1e9464c390 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/audio_a2dp_hw/include/audio_a2dp_hw.h @@ -0,0 +1,88 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/***************************************************************************** + * + * Filename: audio_a2dp_hw.h + * + * Description: + * + *****************************************************************************/ + +#ifndef AUDIO_A2DP_HW_H +#define AUDIO_A2DP_HW_H + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ + +#define A2DP_AUDIO_HARDWARE_INTERFACE "audio.a2dp" +#define A2DP_CTRL_PATH "/data/misc/bluedroid/.a2dp_ctrl" +#define A2DP_DATA_PATH "/data/misc/bluedroid/.a2dp_data" + +#define AUDIO_STREAM_DEFAULT_RATE 44100 +#define AUDIO_STREAM_DEFAULT_FORMAT AUDIO_FORMAT_PCM_16_BIT +#define AUDIO_STREAM_DEFAULT_CHANNEL_FLAG AUDIO_CHANNEL_OUT_STEREO +#define AUDIO_STREAM_OUTPUT_BUFFER_SZ (20*512) +#define AUDIO_SKT_DISCONNECTED (-1) + +typedef enum { + A2DP_CTRL_CMD_NONE, + A2DP_CTRL_CMD_CHECK_READY, + A2DP_CTRL_CMD_START, + A2DP_CTRL_CMD_STOP, + A2DP_CTRL_CMD_SUSPEND, + A2DP_CTRL_GET_AUDIO_CONFIG, +} tA2DP_CTRL_CMD; + +typedef enum { + A2DP_CTRL_ACK_SUCCESS, + A2DP_CTRL_ACK_FAILURE, + A2DP_CTRL_ACK_INCALL_FAILURE /* Failure when in Call*/ +} tA2DP_CTRL_ACK; + + +/***************************************************************************** +** Type definitions for callback functions +******************************************************************************/ + +/***************************************************************************** +** Type definitions and return values +******************************************************************************/ + +/***************************************************************************** +** Extern variables and functions +******************************************************************************/ + +/***************************************************************************** +** Functions +******************************************************************************/ + + +/***************************************************************************** +** +** Function +** +** Description +** +** Returns +** +******************************************************************************/ + +#endif /* A2DP_AUDIO_HW_H */ + diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/btif_av.c b/examples/09_a2dp/components/bluedroid_demos/btif/btif_av.c new file mode 100755 index 0000000000..78e87c731f --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/btif_av.c @@ -0,0 +1,1435 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + + +/***************************************************************************** + * + * Filename: btif_av.c + * + * Description: Bluedroid AV implementation + * + *****************************************************************************/ + +// #include +#include "bt_trace.h" +#include + +// #include +#include "bt_defs.h" +// #include +#include "bt_av.h" +#include "allocator.h" + +#define LOG_TAG "bt_btif_av" + +#include "btif_av.h" +#include "btif_util.h" +#include "btif_profile_queue.h" +#include "bta_api.h" +#include "btif_media.h" +#include "bta_av_api.h" +#include "gki.h" +#include "btu.h" +#include "bt_utils.h" + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ +#define BTIF_AV_SERVICE_NAME "Advanced Audio" + +#define BTIF_TIMEOUT_AV_OPEN_ON_RC_SECS 2 + +typedef enum { + BTIF_AV_STATE_IDLE = 0x0, + BTIF_AV_STATE_OPENING, + BTIF_AV_STATE_OPENED, + BTIF_AV_STATE_STARTED, + BTIF_AV_STATE_CLOSING +} btif_av_state_t; + +/* Should not need dedicated suspend state as actual actions are no + different than open state. Suspend flags are needed however to prevent + media task from trying to restart stream during remote suspend or while + we are in the process of a local suspend */ + +#define BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING 0x1 +#define BTIF_AV_FLAG_REMOTE_SUSPEND 0x2 +#define BTIF_AV_FLAG_PENDING_START 0x4 +#define BTIF_AV_FLAG_PENDING_STOP 0x8 + +/***************************************************************************** +** Local type definitions +******************************************************************************/ + +typedef struct +{ + tBTA_AV_HNDL bta_handle; + bt_bdaddr_t peer_bda; + btif_sm_handle_t sm_handle; + UINT8 flags; + tBTA_AV_EDR edr; + UINT8 peer_sep; /* sep type of peer device */ +} btif_av_cb_t; + +typedef struct +{ + bt_bdaddr_t *target_bda; + uint16_t uuid; +} btif_av_connect_req_t; + +typedef struct +{ + int sample_rate; + int channel_count; +} btif_av_sink_config_req_t; + +/***************************************************************************** +** Static variables +******************************************************************************/ +static btav_callbacks_t *bt_av_src_callbacks = NULL; +static btav_callbacks_t *bt_av_sink_callbacks = NULL; +static btif_av_cb_t btif_av_cb = {0}; +static TIMER_LIST_ENT tle_av_open_on_rc; + +/* both interface and media task needs to be ready to alloc incoming request */ +#define CHECK_BTAV_INIT() if (((bt_av_src_callbacks == NULL) &&(bt_av_sink_callbacks == NULL)) \ + || (btif_av_cb.sm_handle == NULL))\ +{\ + BTIF_TRACE_WARNING("%s: BTAV not initialized", __FUNCTION__);\ + return BT_STATUS_NOT_READY;\ +}\ +else\ +{\ + BTIF_TRACE_EVENT("%s", __FUNCTION__);\ +} + +/* Helper macro to avoid code duplication in the state machine handlers */ +#define CHECK_RC_EVENT(e, d) \ + case BTA_AV_RC_OPEN_EVT: \ + case BTA_AV_RC_CLOSE_EVT: \ + case BTA_AV_REMOTE_CMD_EVT: \ + case BTA_AV_VENDOR_CMD_EVT: \ + case BTA_AV_META_MSG_EVT: \ + case BTA_AV_RC_FEAT_EVT: \ + case BTA_AV_REMOTE_RSP_EVT: \ + { \ + btif_rc_handler(e, d);\ + }break; \ + +static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *data); +static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *data); +static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *data); +static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *data); +static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *data); + +static const btif_sm_handler_t btif_av_state_handlers[] = +{ + btif_av_state_idle_handler, + btif_av_state_opening_handler, + btif_av_state_opened_handler, + btif_av_state_started_handler, + btif_av_state_closing_handler +}; + +static void btif_av_event_free_data(btif_sm_event_t event, void *p_data); + +/************************************************************************* +** Extern functions +*************************************************************************/ +extern void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data); +extern BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr); +extern void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp); + +/***************************************************************************** +** Local helper functions +******************************************************************************/ + +const char *dump_av_sm_state_name(btif_av_state_t state) +{ + switch (state) + { + CASE_RETURN_STR(BTIF_AV_STATE_IDLE) + CASE_RETURN_STR(BTIF_AV_STATE_OPENING) + CASE_RETURN_STR(BTIF_AV_STATE_OPENED) + CASE_RETURN_STR(BTIF_AV_STATE_STARTED) + CASE_RETURN_STR(BTIF_AV_STATE_CLOSING) + default: return "UNKNOWN_STATE"; + } +} + +const char *dump_av_sm_event_name(btif_av_sm_event_t event) +{ + switch((int)event) + { + CASE_RETURN_STR(BTA_AV_ENABLE_EVT) + CASE_RETURN_STR(BTA_AV_REGISTER_EVT) + CASE_RETURN_STR(BTA_AV_OPEN_EVT) + CASE_RETURN_STR(BTA_AV_CLOSE_EVT) + CASE_RETURN_STR(BTA_AV_START_EVT) + CASE_RETURN_STR(BTA_AV_STOP_EVT) + CASE_RETURN_STR(BTA_AV_PROTECT_REQ_EVT) + CASE_RETURN_STR(BTA_AV_PROTECT_RSP_EVT) + CASE_RETURN_STR(BTA_AV_RC_OPEN_EVT) + CASE_RETURN_STR(BTA_AV_RC_CLOSE_EVT) + CASE_RETURN_STR(BTA_AV_REMOTE_CMD_EVT) + CASE_RETURN_STR(BTA_AV_REMOTE_RSP_EVT) + CASE_RETURN_STR(BTA_AV_VENDOR_CMD_EVT) + CASE_RETURN_STR(BTA_AV_VENDOR_RSP_EVT) + CASE_RETURN_STR(BTA_AV_RECONFIG_EVT) + CASE_RETURN_STR(BTA_AV_SUSPEND_EVT) + CASE_RETURN_STR(BTA_AV_PENDING_EVT) + CASE_RETURN_STR(BTA_AV_META_MSG_EVT) + CASE_RETURN_STR(BTA_AV_REJECT_EVT) + CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT) + CASE_RETURN_STR(BTIF_SM_ENTER_EVT) + CASE_RETURN_STR(BTIF_SM_EXIT_EVT) + CASE_RETURN_STR(BTIF_AV_CONNECT_REQ_EVT) + CASE_RETURN_STR(BTIF_AV_DISCONNECT_REQ_EVT) + CASE_RETURN_STR(BTIF_AV_START_STREAM_REQ_EVT) + CASE_RETURN_STR(BTIF_AV_STOP_STREAM_REQ_EVT) + CASE_RETURN_STR(BTIF_AV_SUSPEND_STREAM_REQ_EVT) + CASE_RETURN_STR(BTIF_AV_SINK_CONFIG_REQ_EVT) + default: return "UNKNOWN_EVENT"; + } +} + +/**************************************************************************** +** Local helper functions +*****************************************************************************/ +/******************************************************************************* +** +** Function btif_initiate_av_open_tmr_hdlr +** +** Description Timer to trigger AV open if the remote headset establishes +** RC connection w/o AV connection. The timer is needed to IOP +** with headsets that do establish AV after RC connection. +** +** Returns void +** +*******************************************************************************/ +static void btif_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle) +{ + BD_ADDR peer_addr; + UNUSED(tle); + btif_av_connect_req_t connect_req; + UNUSED(tle); + /* is there at least one RC connection - There should be */ + if (btif_rc_get_connected_peer(peer_addr)) { + BTIF_TRACE_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__); + /* In case of AVRCP connection request, we will initiate SRC connection */ + connect_req.target_bda = (bt_bdaddr_t*)&peer_addr; + connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE; + btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req); + } + else + { + BTIF_TRACE_ERROR("%s No connected RC peers", __FUNCTION__); + } +} + +/***************************************************************************** +** Static functions +******************************************************************************/ + +static void btif_report_connection_state(btav_connection_state_t state, bt_bdaddr_t *bd_addr) +{ + if (bt_av_sink_callbacks != NULL) { + HAL_CBACK(bt_av_sink_callbacks, connection_state_cb, state, bd_addr); + } else if (bt_av_src_callbacks != NULL) { + HAL_CBACK(bt_av_src_callbacks, connection_state_cb, state, bd_addr); + } +} + +static void btif_report_audio_state(btav_audio_state_t state, bt_bdaddr_t *bd_addr) +{ + if (bt_av_sink_callbacks != NULL) { + HAL_CBACK(bt_av_sink_callbacks, audio_state_cb, state, bd_addr); + } else if (bt_av_src_callbacks != NULL) { + HAL_CBACK(bt_av_src_callbacks, audio_state_cb, state, bd_addr); + } +} + +/***************************************************************************** +** +** Function btif_av_state_idle_handler +** +** Description State managing disconnected AV link +** +** Returns TRUE if event was processed, FALSE otherwise +** +*******************************************************************************/ + +static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data) +{ + BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__, + dump_av_sm_event_name(event), btif_av_cb.flags); + + switch (event) + { + case BTIF_SM_ENTER_EVT: + /* clear the peer_bda */ + memset(&btif_av_cb.peer_bda, 0, sizeof(bt_bdaddr_t)); + btif_av_cb.flags = 0; + btif_av_cb.edr = 0; + btif_a2dp_on_idle(); + break; + + case BTIF_SM_EXIT_EVT: + break; + + case BTA_AV_ENABLE_EVT: + break; + + case BTA_AV_REGISTER_EVT: + btif_av_cb.bta_handle = ((tBTA_AV*)p_data)->registr.hndl; + break; + + case BTA_AV_PENDING_EVT: + case BTIF_AV_CONNECT_REQ_EVT: + { + if (event == BTIF_AV_CONNECT_REQ_EVT) + { + memcpy(&btif_av_cb.peer_bda, ((btif_av_connect_req_t*)p_data)->target_bda, + sizeof(bt_bdaddr_t)); + BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle, + TRUE, BTA_SEC_AUTHENTICATE, ((btif_av_connect_req_t*)p_data)->uuid); + } + else if (event == BTA_AV_PENDING_EVT) + { + bdcpy(btif_av_cb.peer_bda.address, ((tBTA_AV*)p_data)->pend.bd_addr); + BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle, + TRUE, BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SOURCE); + } + btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING); + } break; + + case BTA_AV_RC_OPEN_EVT: + /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So + * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore, + * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state. + * We initiate the AV connection after a small 3s timeout to avoid any collisions from the + * headsets, as some headsets initiate the AVRC connection first and then + * immediately initiate the AV connection + * + * TODO: We may need to do this only on an AVRCP Play. FixMe + */ + + BTIF_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV"); + memset(&tle_av_open_on_rc, 0, sizeof(tle_av_open_on_rc)); + tle_av_open_on_rc.param = (UINT32)btif_initiate_av_open_tmr_hdlr; + btu_start_timer(&tle_av_open_on_rc, BTU_TTYPE_USER_FUNC, + BTIF_TIMEOUT_AV_OPEN_ON_RC_SECS); + btif_rc_handler(event, p_data); + break; + + case BTA_AV_REMOTE_CMD_EVT: + case BTA_AV_VENDOR_CMD_EVT: + case BTA_AV_META_MSG_EVT: + case BTA_AV_RC_FEAT_EVT: + case BTA_AV_REMOTE_RSP_EVT: + btif_rc_handler(event, (tBTA_AV*)p_data); + break; + + case BTA_AV_RC_CLOSE_EVT: + if (tle_av_open_on_rc.in_use) { + BTIF_TRACE_DEBUG("BTA_AV_RC_CLOSE_EVT: Stopping AV timer."); + btu_stop_timer(&tle_av_open_on_rc); + } + btif_rc_handler(event, p_data); + break; + + default: + BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__, + dump_av_sm_event_name(event)); + return FALSE; + + } + + return TRUE; +} +/***************************************************************************** +** +** Function btif_av_state_opening_handler +** +** Description Intermediate state managing events during establishment +** of avdtp channel +** +** Returns TRUE if event was processed, FALSE otherwise +** +*******************************************************************************/ + +static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data) +{ + BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__, + dump_av_sm_event_name(event), btif_av_cb.flags); + + switch (event) + { + case BTIF_SM_ENTER_EVT: + /* inform the application that we are entering connecting state */ + btif_report_connection_state(BTAV_CONNECTION_STATE_CONNECTING, &(btif_av_cb.peer_bda)); + break; + + case BTIF_SM_EXIT_EVT: + break; + + case BTA_AV_REJECT_EVT: + BTIF_TRACE_DEBUG(" Received BTA_AV_REJECT_EVT "); + btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda)); + btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE); + break; + + case BTA_AV_OPEN_EVT: + { + tBTA_AV *p_bta_data = (tBTA_AV*)p_data; + btav_connection_state_t state; + btif_sm_state_t av_state; + BTIF_TRACE_DEBUG("status:%d, edr 0x%x",p_bta_data->open.status, + p_bta_data->open.edr); + + if (p_bta_data->open.status == BTA_AV_SUCCESS) + { + state = BTAV_CONNECTION_STATE_CONNECTED; + av_state = BTIF_AV_STATE_OPENED; + btif_av_cb.edr = p_bta_data->open.edr; + + btif_av_cb.peer_sep = p_bta_data->open.sep; + btif_a2dp_set_peer_sep(p_bta_data->open.sep); + } + else + { + BTIF_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d", + p_bta_data->open.status ); + state = BTAV_CONNECTION_STATE_DISCONNECTED; + av_state = BTIF_AV_STATE_IDLE; + } + + /* inform the application of the event */ + btif_report_connection_state(state, &(btif_av_cb.peer_bda)); + /* change state to open/idle based on the status */ + btif_sm_change_state(btif_av_cb.sm_handle, av_state); + if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) + { + /* if queued PLAY command, send it now */ + btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, + (p_bta_data->open.status == BTA_AV_SUCCESS)); + } + else if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) + { + /* if queued PLAY command, send it now */ + btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE); + /* Bring up AVRCP connection too */ + BTA_AvOpenRc(btif_av_cb.bta_handle); + } + btif_queue_advance(); + } break; + + case BTIF_AV_SINK_CONFIG_REQ_EVT: + { + btif_av_sink_config_req_t req; + // copy to avoid alignment problems + memcpy(&req, p_data, sizeof(req)); + + BTIF_TRACE_WARNING("BTIF_AV_SINK_CONFIG_REQ_EVT %d %d", req.sample_rate, + req.channel_count); + if (btif_av_cb.peer_sep == AVDT_TSEP_SRC && bt_av_sink_callbacks != NULL) { + HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(btif_av_cb.peer_bda), + req.sample_rate, req.channel_count); + } + } break; + + case BTIF_AV_CONNECT_REQ_EVT: + // Check for device, if same device which moved to opening then ignore callback + if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb.peer_bda), + sizeof(btif_av_cb.peer_bda)) == 0) + { + BTIF_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Connect Req", __func__); + btif_queue_advance(); + break; + } + else + { + BTIF_TRACE_DEBUG("%s: Moved from idle by Incoming Connection request", __func__); + btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t*)p_data); + btif_queue_advance(); + break; + } + + case BTA_AV_PENDING_EVT: + // Check for device, if same device which moved to opening then ignore callback + if (memcmp (((tBTA_AV*)p_data)->pend.bd_addr, &(btif_av_cb.peer_bda), + sizeof(btif_av_cb.peer_bda)) == 0) + { + BTIF_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Pending Req", __func__); + break; + } + else + { + BTIF_TRACE_DEBUG("%s: Moved from idle by outgoing Connection request", __func__); + BTA_AvDisconnect(((tBTA_AV*)p_data)->pend.bd_addr); + break; + } + + CHECK_RC_EVENT(event, p_data); + + default: + BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__, + dump_av_sm_event_name(event)); + return FALSE; + + } + return TRUE; +} + + +/***************************************************************************** +** +** Function btif_av_state_closing_handler +** +** Description Intermediate state managing events during closing +** of avdtp channel +** +** Returns TRUE if event was processed, FALSE otherwise +** +*******************************************************************************/ + +static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data) +{ + BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__, + dump_av_sm_event_name(event), btif_av_cb.flags); + + switch (event) + { + case BTIF_SM_ENTER_EVT: + if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) + { + /* immediately stop transmission of frames */ + btif_a2dp_set_tx_flush(TRUE); + /* wait for audioflinger to stop a2dp */ + } + if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) + { + btif_a2dp_set_rx_flush(TRUE); + } + break; + + case BTA_AV_STOP_EVT: + case BTIF_AV_STOP_STREAM_REQ_EVT: + if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) + { + /* immediately flush any pending tx frames while suspend is pending */ + btif_a2dp_set_tx_flush(TRUE); + } + if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) + { + btif_a2dp_set_rx_flush(TRUE); + } + + btif_a2dp_on_stopped(NULL); + break; + + case BTIF_SM_EXIT_EVT: + break; + + case BTA_AV_CLOSE_EVT: + + /* inform the application that we are disconnecting */ + btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda)); + + btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE); + break; + + /* Handle the RC_CLOSE event for the cleanup */ + case BTA_AV_RC_CLOSE_EVT: + btif_rc_handler(event, (tBTA_AV*)p_data); + break; + + default: + BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__, + dump_av_sm_event_name(event)); + return FALSE; + } + return TRUE; +} + + +/***************************************************************************** +** +** Function btif_av_state_opened_handler +** +** Description Handles AV events while AVDTP is in OPEN state +** +** Returns TRUE if event was processed, FALSE otherwise +** +*******************************************************************************/ + +static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data) +{ + tBTA_AV *p_av = (tBTA_AV*)p_data; + + BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__, + dump_av_sm_event_name(event), btif_av_cb.flags); + + if ( (event == BTA_AV_REMOTE_CMD_EVT) && (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND) && + (p_av->remote_cmd.rc_id == BTA_AV_RC_PLAY) ) + { + BTIF_TRACE_EVENT("%s: Resetting remote suspend flag on RC PLAY", __FUNCTION__); + btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND; + } + + switch (event) + { + case BTIF_SM_ENTER_EVT: + btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_STOP; + btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START; + break; + + case BTIF_SM_EXIT_EVT: + btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START; + break; + + case BTIF_AV_START_STREAM_REQ_EVT: + if (btif_av_cb.peer_sep != AVDT_TSEP_SRC) + btif_a2dp_setup_codec(); + BTA_AvStart(); + btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START; + break; + + case BTA_AV_START_EVT: + { + BTIF_TRACE_EVENT("BTA_AV_START_EVT status %d, suspending %d, init %d", + p_av->start.status, p_av->start.suspending, p_av->start.initiator); + + if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE)) + return TRUE; + + /* if remote tries to start a2dp when DUT is a2dp source + * then suspend. In case a2dp is sink and call is active + * then disconnect the AVDTP channel + */ + if (!(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START)) + { + if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) + { + BTIF_TRACE_EVENT("%s: trigger suspend as remote initiated!!", __FUNCTION__); + btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0); + } + } + + /* In case peer is A2DP SRC we do not want to ack commands on UIPC*/ + if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) + { + if (btif_a2dp_on_started(&p_av->start, + ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) != 0))) + { + /* only clear pending flag after acknowledgement */ + btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START; + } + } + + /* remain in open state if status failed */ + if (p_av->start.status != BTA_AV_SUCCESS) + return FALSE; + + if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) + { + btif_a2dp_set_rx_flush(FALSE); /* remove flush state, ready for streaming*/ + } + + /* change state to started, send acknowledgement if start is pending */ + if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) { + if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) + btif_a2dp_on_started(NULL, TRUE); + /* pending start flag will be cleared when exit current state */ + } + btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_STARTED); + + } break; + + case BTIF_AV_DISCONNECT_REQ_EVT: + BTA_AvClose(btif_av_cb.bta_handle); + if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) { + BTA_AvCloseRc(btif_av_cb.bta_handle); + } + + /* inform the application that we are disconnecting */ + btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda)); + break; + + case BTA_AV_CLOSE_EVT: + /* avdtp link is closed */ + btif_a2dp_on_stopped(NULL); + + /* inform the application that we are disconnected */ + btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda)); + + /* change state to idle, send acknowledgement if start is pending */ + if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) { + btif_a2dp_ack_fail(); + /* pending start flag will be cleared when exit current state */ + } + btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE); + break; + + case BTA_AV_RECONFIG_EVT: + if((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) && + (p_av->reconfig.status == BTA_AV_SUCCESS)) + { + APPL_TRACE_WARNING("reconfig done BTA_AVstart()"); + BTA_AvStart(); + } + else if(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) + { + btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START; + btif_a2dp_ack_fail(); + } + break; + + case BTIF_AV_CONNECT_REQ_EVT: + if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb.peer_bda), + sizeof(btif_av_cb.peer_bda)) == 0) + { + BTIF_TRACE_DEBUG("%s: Ignore BTIF_AV_CONNECT_REQ_EVT for same device", __func__); + } + else + { + BTIF_TRACE_DEBUG("%s: Moved to opened by Other Incoming Conn req", __func__); + btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, + (bt_bdaddr_t*)p_data); + } + btif_queue_advance(); + break; + + CHECK_RC_EVENT(event, p_data); + + default: + BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__, + dump_av_sm_event_name(event)); + return FALSE; + + } + return TRUE; +} + +/***************************************************************************** +** +** Function btif_av_state_started_handler +** +** Description Handles AV events while A2DP stream is started +** +** Returns TRUE if event was processed, FALSE otherwise +** +*******************************************************************************/ + +static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data) +{ + tBTA_AV *p_av = (tBTA_AV*)p_data; + + BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__, + dump_av_sm_event_name(event), btif_av_cb.flags); + + switch (event) + { + case BTIF_SM_ENTER_EVT: + + /* we are again in started state, clear any remote suspend flags */ + btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND; + + btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda)); + + /* increase the a2dp consumer task priority temporarily when start + ** audio playing, to avoid overflow the audio packet queue. */ + adjust_priority_a2dp(TRUE); + + break; + + case BTIF_SM_EXIT_EVT: + /* restore the a2dp consumer task priority when stop audio playing. */ + adjust_priority_a2dp(FALSE); + + break; + + case BTIF_AV_START_STREAM_REQ_EVT: + /* we were remotely started, just ack back the local request */ + if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) + btif_a2dp_on_started(NULL, TRUE); + break; + + /* fixme -- use suspend = true always to work around issue with BTA AV */ + case BTIF_AV_STOP_STREAM_REQ_EVT: + case BTIF_AV_SUSPEND_STREAM_REQ_EVT: + + /* set pending flag to ensure btif task is not trying to restart + stream while suspend is in progress */ + btif_av_cb.flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING; + + /* if we were remotely suspended but suspend locally, local suspend + always overrides */ + btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND; + + if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) + { + /* immediately stop transmission of frames while suspend is pending */ + btif_a2dp_set_tx_flush(TRUE); + } + + if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) { + btif_a2dp_set_rx_flush(TRUE); + btif_a2dp_on_stopped(NULL); + } + + BTA_AvStop(TRUE); + break; + + case BTIF_AV_DISCONNECT_REQ_EVT: + + /* request avdtp to close */ + BTA_AvClose(btif_av_cb.bta_handle); + if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) { + BTA_AvCloseRc(btif_av_cb.bta_handle); + } + + /* inform the application that we are disconnecting */ + btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda)); + + /* wait in closing state until fully closed */ + btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_CLOSING); + break; + + case BTA_AV_SUSPEND_EVT: + + BTIF_TRACE_EVENT("BTA_AV_SUSPEND_EVT status %d, init %d", + p_av->suspend.status, p_av->suspend.initiator); + + /* a2dp suspended, stop media task until resumed */ + btif_a2dp_on_suspended(&p_av->suspend); + + /* if not successful, remain in current state */ + if (p_av->suspend.status != BTA_AV_SUCCESS) + { + btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING; + + if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) + { + /* suspend failed, reset back tx flush state */ + btif_a2dp_set_tx_flush(FALSE); + } + return FALSE; + } + + if (p_av->suspend.initiator != TRUE) + { + /* remote suspend, notify HAL and await audioflinger to + suspend/stop stream */ + + /* set remote suspend flag to block media task from restarting + stream only if we did not already initiate a local suspend */ + if ((btif_av_cb.flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0) + btif_av_cb.flags |= BTIF_AV_FLAG_REMOTE_SUSPEND; + + btif_report_audio_state(BTAV_AUDIO_STATE_REMOTE_SUSPEND, &(btif_av_cb.peer_bda)); + } + else + { + btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda)); + } + + btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED); + + /* suspend completed and state changed, clear pending status */ + btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING; + break; + + case BTA_AV_STOP_EVT: + + btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP; + btif_a2dp_on_stopped(&p_av->suspend); + + btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda)); + + /* if stop was successful, change state to open */ + if (p_av->suspend.status == BTA_AV_SUCCESS) + btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED); + + break; + + case BTA_AV_CLOSE_EVT: + + btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP; + + /* avdtp link is closed */ + btif_a2dp_on_stopped(NULL); + + /* inform the application that we are disconnected */ + btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda)); + + btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE); + break; + + CHECK_RC_EVENT(event, p_data); + + default: + BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__, + dump_av_sm_event_name(event)); + return FALSE; + + } + return TRUE; +} + +/***************************************************************************** +** Local event handlers +******************************************************************************/ + +static void btif_av_handle_event(UINT16 event, char* p_param) +{ + btif_sm_dispatch(btif_av_cb.sm_handle, event, (void*)p_param); + btif_av_event_free_data(event, p_param); +} + +void btif_av_event_deep_copy(UINT16 event, char *p_dest, char *p_src) +{ + tBTA_AV *av_src = (tBTA_AV *)p_src; + tBTA_AV *av_dest = (tBTA_AV *)p_dest; + + // First copy the structure + memcpy(p_dest, p_src, sizeof(tBTA_AV)); + + switch (event) + { + case BTA_AV_META_MSG_EVT: + if (av_src->meta_msg.p_data && av_src->meta_msg.len) + { + av_dest->meta_msg.p_data = osi_calloc(av_src->meta_msg.len); + assert(av_dest->meta_msg.p_data); + memcpy(av_dest->meta_msg.p_data, av_src->meta_msg.p_data, av_src->meta_msg.len); + } + + if (av_src->meta_msg.p_msg) + { + av_dest->meta_msg.p_msg = osi_calloc(sizeof(tAVRC_MSG)); + assert(av_dest->meta_msg.p_msg); + memcpy(av_dest->meta_msg.p_msg, av_src->meta_msg.p_msg, sizeof(tAVRC_MSG)); + + if (av_src->meta_msg.p_msg->vendor.p_vendor_data && + av_src->meta_msg.p_msg->vendor.vendor_len) + { + av_dest->meta_msg.p_msg->vendor.p_vendor_data = osi_calloc( + av_src->meta_msg.p_msg->vendor.vendor_len); + assert(av_dest->meta_msg.p_msg->vendor.p_vendor_data); + memcpy(av_dest->meta_msg.p_msg->vendor.p_vendor_data, + av_src->meta_msg.p_msg->vendor.p_vendor_data, + av_src->meta_msg.p_msg->vendor.vendor_len); + } + } + break; + + default: + break; + } +} + +static void btif_av_event_free_data(btif_sm_event_t event, void *p_data) +{ + switch (event) + { + case BTA_AV_META_MSG_EVT: + { + tBTA_AV *av = (tBTA_AV*)p_data; + if (av->meta_msg.p_data) + osi_free(av->meta_msg.p_data); + + if (av->meta_msg.p_msg) + { + if (av->meta_msg.p_msg->vendor.p_vendor_data) + osi_free(av->meta_msg.p_msg->vendor.p_vendor_data); + osi_free(av->meta_msg.p_msg); + } + } + break; + + default: + break; + } +} + +static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data) +{ + btif_transfer_context(btif_av_handle_event, event, + (char*)p_data, sizeof(tBTA_AV), btif_av_event_deep_copy); +} + +static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) +{ + btif_sm_state_t state; + UINT8 que_len; + tA2D_STATUS a2d_status; + tA2D_SBC_CIE sbc_cie; + btif_av_sink_config_req_t config_req; + + if (event == BTA_AV_MEDIA_DATA_EVT)/* Switch to BTIF_MEDIA context */ + { + state= btif_sm_get_state(btif_av_cb.sm_handle); + if ( (state == BTIF_AV_STATE_STARTED) || /* send SBC packets only in Started State */ + (state == BTIF_AV_STATE_OPENED) ) + { + que_len = btif_media_sink_enque_buf((BT_HDR *)p_data); + BTIF_TRACE_DEBUG(" Packets in Que %d",que_len); + } + else + return; + } + + if (event == BTA_AV_MEDIA_SINK_CFG_EVT) { + /* send a command to BT Media Task */ + btif_reset_decoder((UINT8*)p_data); + + a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE); + if (a2d_status == A2D_SUCCESS) { + /* Switch to BTIF context */ + config_req.sample_rate = btif_a2dp_get_track_frequency(sbc_cie.samp_freq); + config_req.channel_count = btif_a2dp_get_track_channel_count(sbc_cie.ch_mode); + btif_transfer_context(btif_av_handle_event, BTIF_AV_SINK_CONFIG_REQ_EVT, + (char*)&config_req, sizeof(config_req), NULL); + } else { + APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d", a2d_status); + } + } +} +/******************************************************************************* +** +** Function btif_av_init +** +** Description Initializes btif AV if not already done +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_av_init() +{ + if (btif_av_cb.sm_handle == NULL) + { + if (!btif_a2dp_start_media_task()) + return BT_STATUS_FAIL; + + /* Also initialize the AV state machine */ + btif_av_cb.sm_handle = + btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE); + + btif_enable_service(BTA_A2DP_SOURCE_SERVICE_ID); +#if (BTA_AV_SINK_INCLUDED == TRUE) + btif_enable_service(BTA_A2DP_SINK_SERVICE_ID); +#endif + + btif_a2dp_on_init(); + } + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function init_src +** +** Description Initializes the AV interface for source mode +** +** Returns bt_status_t +** +*******************************************************************************/ + +static bt_status_t init_src(btav_callbacks_t* callbacks) +{ + BTIF_TRACE_EVENT("%s()", __func__); + + bt_status_t status = btif_av_init(); + if (status == BT_STATUS_SUCCESS) + bt_av_src_callbacks = callbacks; + + return status; +} + +/******************************************************************************* +** +** Function init_sink +** +** Description Initializes the AV interface for sink mode +** +** Returns bt_status_t +** +*******************************************************************************/ + +static bt_status_t init_sink(btav_callbacks_t* callbacks) +{ + BTIF_TRACE_EVENT("%s()", __func__); + + bt_status_t status = btif_av_init(); + if (status == BT_STATUS_SUCCESS) + bt_av_sink_callbacks = callbacks; + + return status; +} + +/******************************************************************************* +** +** Function connect +** +** Description Establishes the AV signalling channel with the remote headset +** +** Returns bt_status_t +** +*******************************************************************************/ + +static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid) +{ + btif_av_connect_req_t connect_req; + connect_req.target_bda = bd_addr; + connect_req.uuid = uuid; + BTIF_TRACE_EVENT("%s", __FUNCTION__); + + btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req); + + return BT_STATUS_SUCCESS; +} + +static bt_status_t src_connect_sink(bt_bdaddr_t *bd_addr) +{ + BTIF_TRACE_EVENT("%s", __FUNCTION__); + CHECK_BTAV_INIT(); + + return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int); +} + +static bt_status_t sink_connect_src(bt_bdaddr_t *bd_addr) +{ + BTIF_TRACE_EVENT("%s", __FUNCTION__); + CHECK_BTAV_INIT(); + + return btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, bd_addr, connect_int); +} + +/******************************************************************************* +** +** Function disconnect +** +** Description Tears down the AV signalling channel with the remote headset +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t disconnect(bt_bdaddr_t *bd_addr) +{ + BTIF_TRACE_EVENT("%s", __FUNCTION__); + + CHECK_BTAV_INIT(); + + /* Switch to BTIF context */ + return btif_transfer_context(btif_av_handle_event, BTIF_AV_DISCONNECT_REQ_EVT, + (char*)bd_addr, sizeof(bt_bdaddr_t), NULL); +} + +/******************************************************************************* +** +** Function cleanup +** +** Description Shuts down the AV interface and does the cleanup +** +** Returns None +** +*******************************************************************************/ +static void cleanup(void) +{ + BTIF_TRACE_EVENT("%s", __FUNCTION__); + + btif_a2dp_stop_media_task(); + + btif_disable_service(BTA_A2DP_SOURCE_SERVICE_ID); +#if (BTA_AV_SINK_INCLUDED == TRUE) + btif_disable_service(BTA_A2DP_SINK_SERVICE_ID); +#endif + + /* Also shut down the AV state machine */ + btif_sm_shutdown(btif_av_cb.sm_handle); + btif_av_cb.sm_handle = NULL; +} + +static void cleanup_src(void) { + BTIF_TRACE_EVENT("%s", __FUNCTION__); + + if (bt_av_src_callbacks) + { + bt_av_src_callbacks = NULL; + if (bt_av_sink_callbacks == NULL) + cleanup(); + } +} + +static void cleanup_sink(void) { + BTIF_TRACE_EVENT("%s", __FUNCTION__); + + if (bt_av_sink_callbacks) + { + bt_av_sink_callbacks = NULL; + if (bt_av_src_callbacks == NULL) + cleanup(); + } +} + +static const btav_interface_t bt_av_src_interface = { + sizeof(btav_interface_t), + init_src, + src_connect_sink, + disconnect, + cleanup_src, +}; + +static const btav_interface_t bt_av_sink_interface = { + sizeof(btav_interface_t), + init_sink, + sink_connect_src, + disconnect, + cleanup_sink, +}; + +/******************************************************************************* +** +** Function btif_av_get_sm_handle +** +** Description Fetches current av SM handle +** +** Returns None +** +*******************************************************************************/ + +btif_sm_handle_t btif_av_get_sm_handle(void) +{ + return btif_av_cb.sm_handle; +} + +/******************************************************************************* +** +** Function btif_av_stream_ready +** +** Description Checks whether AV is ready for starting a stream +** +** Returns None +** +*******************************************************************************/ + +BOOLEAN btif_av_stream_ready(void) +{ + btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle); + + BTIF_TRACE_DEBUG("btif_av_stream_ready : sm hdl %d, state %d, flags %x", + btif_av_cb.sm_handle, state, btif_av_cb.flags); + + /* also make sure main adapter is enabled */ + if (btif_is_enabled() == 0) + { + BTIF_TRACE_EVENT("main adapter not enabled"); + return FALSE; + } + + /* check if we are remotely suspended or stop is pending */ + if (btif_av_cb.flags & (BTIF_AV_FLAG_REMOTE_SUSPEND|BTIF_AV_FLAG_PENDING_STOP)) + return FALSE; + + return (state == BTIF_AV_STATE_OPENED); +} + +/******************************************************************************* +** +** Function btif_av_stream_started_ready +** +** Description Checks whether AV ready for media start in streaming state +** +** Returns None +** +*******************************************************************************/ + +BOOLEAN btif_av_stream_started_ready(void) +{ + btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle); + + BTIF_TRACE_DEBUG("btif_av_stream_started : sm hdl %d, state %d, flags %x", + btif_av_cb.sm_handle, state, btif_av_cb.flags); + + /* disallow media task to start if we have pending actions */ + if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND + | BTIF_AV_FLAG_PENDING_STOP)) + return FALSE; + + return (state == BTIF_AV_STATE_STARTED); +} + +/******************************************************************************* +** +** Function btif_dispatch_sm_event +** +** Description Send event to AV statemachine +** +** Returns None +** +*******************************************************************************/ + +/* used to pass events to AV statemachine from other tasks */ +void btif_dispatch_sm_event(btif_av_sm_event_t event, void *p_data, int len) +{ + /* Switch to BTIF context */ + btif_transfer_context(btif_av_handle_event, event, + (char*)p_data, len, NULL); +} + +/******************************************************************************* +** +** Function btif_av_execute_service +** +** Description Initializes/Shuts down the service +** +** Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_av_execute_service(BOOLEAN b_enable) +{ + if (b_enable) + { + /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not + * handle this request in order to allow incoming connections to succeed. + * We need to put this back once support for this is added */ + + /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not + * auto-suspend av streaming on AG events(SCO or Call). The suspend shall + * be initiated by the app/audioflinger layers */ +#if (AVRC_METADATA_INCLUDED == TRUE) + BTA_AvEnable(BTA_SEC_AUTHENTICATE, + BTA_AV_FEAT_RCTG|BTA_AV_FEAT_METADATA|BTA_AV_FEAT_VENDOR|BTA_AV_FEAT_NO_SCO_SSPD +#if (AVRC_ADV_CTRL_INCLUDED == TRUE) + |BTA_AV_FEAT_RCCT + |BTA_AV_FEAT_ADV_CTRL +#endif + ,bte_av_callback); +#else + BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_NO_SCO_SSPD), + bte_av_callback); +#endif + BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback); + } + else { + BTA_AvDeregister(btif_av_cb.bta_handle); + BTA_AvDisable(); + } + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_av_sink_execute_service +** +** Description Initializes/Shuts down the service +** +** Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_av_sink_execute_service(BOOLEAN b_enable) +{ +#if (BTA_AV_SINK_INCLUDED == TRUE) + BTA_AvEnable_Sink(b_enable); +#endif + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_av_get_src_interface +** +** Description Get the AV callback interface for A2DP source profile +** +** Returns btav_interface_t +** +*******************************************************************************/ +const btav_interface_t *btif_av_get_src_interface(void) +{ + BTIF_TRACE_EVENT("%s", __FUNCTION__); + return &bt_av_src_interface; +} + +/******************************************************************************* +** +** Function btif_av_get_sink_interface +** +** Description Get the AV callback interface for A2DP sink profile +** +** Returns btav_interface_t +** +*******************************************************************************/ +const btav_interface_t *btif_av_get_sink_interface(void) +{ + BTIF_TRACE_EVENT("%s", __FUNCTION__); + return &bt_av_sink_interface; +} + +/******************************************************************************* +** +** Function btif_av_is_connected +** +** Description Checks if av has a connected sink +** +** Returns BOOLEAN +** +*******************************************************************************/ +BOOLEAN btif_av_is_connected(void) +{ + btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle); + return ((state == BTIF_AV_STATE_OPENED) || (state == BTIF_AV_STATE_STARTED)); +} + +/******************************************************************************* +** +** Function btif_av_is_peer_edr +** +** Description Check if the connected a2dp device supports +** EDR or not. Only when connected this function +** will accurately provide a true capability of +** remote peer. If not connected it will always be false. +** +** Returns TRUE if remote device is capable of EDR +** +*******************************************************************************/ +BOOLEAN btif_av_is_peer_edr(void) +{ + ASSERTC(btif_av_is_connected(), "No active a2dp connection", 0); + + if (btif_av_cb.edr) + return TRUE; + else + return FALSE; +} + +/****************************************************************************** +** +** Function btif_av_clear_remote_suspend_flag +** +** Description Clears btif_av_cd.flags if BTIF_AV_FLAG_REMOTE_SUSPEND is set +** +** Returns void +******************************************************************************/ +void btif_av_clear_remote_suspend_flag(void) +{ + BTIF_TRACE_DEBUG("%s: flag :%x",__func__, btif_av_cb.flags); + btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND; +} diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/btif_core.c b/examples/09_a2dp/components/bluedroid_demos/btif/btif_core.c new file mode 100755 index 0000000000..0036beb221 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/btif_core.c @@ -0,0 +1,483 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * 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. + * + ******************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_core.c + * + * Description: Contains core functionality related to interfacing between + * Bluetooth HAL and BTE core stack. + * + ***********************************************************************************/ + +#include +// #include +// #include +// #include +// #include +#include +#include +// #include +// #include + +#define LOG_TAG "bt_btif_core" +// #include "btcore/include/bdaddr.h" + +#include "bdaddr.h" +// #include "bt_utils.h" +#include "bta_api.h" +#include "bte.h" +#include "btif_api.h" +// #include "btif_av.h" +// #include "btif_config.h" +// #include "btif_pan.h" +// #include "btif_profile_queue.h" +// #include "btif_config.h" +// #include "btif_sock.h" +// #include "btif_storage.h" +#include "btif_util.h" +#include "btu.h" +#include "controller.h" +#include "fixed_queue.h" +#include "future.h" +#include "gki.h" +#include "osi.h" +// #include "osi/include/log.h" +#include "stack_manager.h" +#include "thread.h" +#include "btif_common.h" +#include "btif_dm.h" +/************************************************************************************ +** Constants & Macros +************************************************************************************/ + +/************************************************************************************ +** Local type definitions +************************************************************************************/ + +/************************************************************************************ +** Static variables +************************************************************************************/ + +static tBTA_SERVICE_MASK btif_enabled_services = 0; + +static fixed_queue_t *btif_msg_queue = NULL; +static xTaskHandle xBtifTaskHandle = NULL; + +/************************************************************************************ +** Static functions +************************************************************************************/ + +/* sends message to btif task */ +static void btif_sendmsg(void *p_msg); +static void btif_thread_post(uint32_t sig); +/************************************************************************************ +** Externs +************************************************************************************/ +static fixed_queue_t *xBtifQueue = NULL; + +/** TODO: Move these to _common.h */ +void bte_main_boot_entry(void *); +void bte_main_disable(void); +void bte_main_shutdown(void); +void btif_dm_execute_service_request(UINT16 event, char *p_param); + +/******************************************************************************* +** +** Function btif_context_switched +** +** Description Callback used to execute transferred context callback +** +** p_msg : message to be executed in btif context +** +** Returns void +** +*******************************************************************************/ + +static void btif_context_switched(void *p_msg) +{ + + BTIF_TRACE_VERBOSE("btif_context_switched"); + + tBTIF_CONTEXT_SWITCH_CBACK *p = (tBTIF_CONTEXT_SWITCH_CBACK *) p_msg; + + /* each callback knows how to parse the data */ + if (p->p_cb) + p->p_cb(p->event, p->p_param); +} + + +/******************************************************************************* +** +** Function btif_transfer_context +** +** Description This function switches context to btif task +** +** p_cback : callback used to process message in btif context +** event : event id of message +** p_params : parameter area passed to callback (copied) +** param_len : length of parameter area +** p_copy_cback : If set this function will be invoked for deep copy +** +** Returns void +** +*******************************************************************************/ + +bt_status_t btif_transfer_context (tBTIF_CBACK *p_cback, UINT16 event, char* p_params, int param_len, tBTIF_COPY_CBACK *p_copy_cback) +{ + tBTIF_CONTEXT_SWITCH_CBACK *p_msg; + + BTIF_TRACE_VERBOSE("btif_transfer_context event %d, len %d", event, param_len); + + /* allocate and send message that will be executed in btif context */ + if ((p_msg = (tBTIF_CONTEXT_SWITCH_CBACK *) GKI_getbuf(sizeof(tBTIF_CONTEXT_SWITCH_CBACK) + param_len)) != NULL) + { + p_msg->hdr.event = BT_EVT_CONTEXT_SWITCH_EVT; /* internal event */ + p_msg->p_cb = p_cback; + + p_msg->event = event; /* callback event */ + + /* check if caller has provided a copy callback to do the deep copy */ + if (p_copy_cback) + { + p_copy_cback(event, p_msg->p_param, p_params); + } + else if (p_params) + { + memcpy(p_msg->p_param, p_params, param_len); /* callback parameter data */ + } + + btif_sendmsg(p_msg); + return BT_STATUS_SUCCESS; + } + else + { + /* let caller deal with a failed allocation */ + return BT_STATUS_NOMEM; + } +} + +int btif_is_enabled(void) +{ + return (stack_manager_is_stack_running()); +} + +void btif_init_ok(void) { + BTIF_TRACE_DEBUG("btif_task: received trigger stack init event"); + future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS); +} + +/******************************************************************************* +** +** Function btif_enable_bluetooth_evt +** +** Description Event indicating bluetooth enable is completed +** Notifies HAL user with updated adapter state +** +** Returns void +** +*******************************************************************************/ + +void btif_enable_bluetooth_evt(tBTA_STATUS status) +{ + if (status == BTA_SUCCESS) { + future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS); + } else { + future_ready(stack_manager_get_hack_future(), FUTURE_FAIL); + } +} + +/******************************************************************************* +** +** Function btif_disable_bluetooth_evt +** +** Description Event notifying BT disable is now complete. +** Terminates main stack tasks and notifies HAL +** user with updated BT state. +** +** Returns void +** +*******************************************************************************/ + +void btif_disable_bluetooth_evt(void) +{ + BTIF_TRACE_DEBUG("%s", __FUNCTION__); + + /* callback to HAL */ + future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS); +} + +/******************************************************************************* +** +** Function btif_task +** +** Description BTIF task handler managing all messages being passed +** Bluetooth HAL and BTA. +** +** Returns void +** +*******************************************************************************/ +static void bt_jni_msg_ready(fixed_queue_t *queue) { + BT_HDR *p_msg; + while (!fixed_queue_is_empty(queue)) { + p_msg = (BT_HDR *)fixed_queue_dequeue(queue); + BTIF_TRACE_VERBOSE("btif task fetched event %x", p_msg->event); + switch (p_msg->event) { + case BT_EVT_CONTEXT_SWITCH_EVT: + btif_context_switched(p_msg); + break; + default: + BTIF_TRACE_ERROR("unhandled btif event (%d)", p_msg->event & BT_EVT_MASK); break; + } + GKI_freebuf(p_msg); + } +} + +/******************************************************************************* +** +** Function btif_sendmsg +** +** Description Sends msg to BTIF task +** +** Returns void +** +*******************************************************************************/ + +void btif_sendmsg(void *p_msg) +{ + fixed_queue_enqueue(btif_msg_queue, p_msg); + btif_thread_post(SIG_BTIF_WORK); +} + +static void btif_thread_post(uint32_t sig) { + BtTaskEvt_t *evt = (BtTaskEvt_t *)osi_malloc(sizeof(BtTaskEvt_t)); + if (evt == NULL) + return; + + evt->sig = sig; + evt->par = 0; + + if (xQueueSend(xBtifQueue, &evt, 10/portTICK_RATE_MS) != pdTRUE) { + ets_printf("xBtifQueue failed\n"); + } +} + +/***************************************************************************** +** +** Function btif_task_thread_handler +** +** Description Process BTif Task Thread. +******************************************************************************/ +void btif_task_thread_handler(void *arg) +{ + BtTaskEvt_t *e; + + for (;;) { + if (pdTRUE == xQueueReceive(xBtifQueue, &e, (portTickType)portMAX_DELAY)) { + + if (e->sig == SIG_BTIF_WORK) { + fixed_queue_process(btif_msg_queue); + } + osi_free(e); + } + } +} + +/******************************************************************************* +** +** Function btif_init_bluetooth +** +** Description Creates BTIF task and prepares BT scheduler for startup +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_init_bluetooth(void) { + bte_main_boot_entry(btif_init_ok); + + btif_msg_queue = fixed_queue_new(SIZE_MAX); + if (btif_msg_queue == NULL) { + goto error_exit; + } + xBtifQueue = xQueueCreate(60, sizeof(void *)); + xTaskCreate(btif_task_thread_handler, "BtifT", 8192, NULL, configMAX_PRIORITIES - 1, &xBtifTaskHandle); + fixed_queue_register_dequeue(btif_msg_queue, bt_jni_msg_ready); + + return BT_STATUS_SUCCESS; + +error_exit:; + btif_shutdown_bluetooth(); + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function btif_enable_bluetooth +** +** Description Inititates shutdown of Bluetooth system. +** Any active links will be dropped and device entering +** non connectable/discoverable mode +** +** Returns void +** +*******************************************************************************/ +bt_status_t btif_enable_bluetooth(void) +{ + BTIF_TRACE_DEBUG("BTIF ENABLE BLUETOOTH"); + + BTA_EnableBluetooth(bte_dm_evt); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_disable_bluetooth +** +** Description Inititates shutdown of Bluetooth system. +** Any active links will be dropped and device entering +** non connectable/discoverable mode +** +** Returns void +** +*******************************************************************************/ +bt_status_t btif_disable_bluetooth(void) +{ + BTIF_TRACE_DEBUG("BTIF DISABLE BLUETOOTH"); + + // btif_dm_on_disable(); + /* cleanup rfcomm & l2cap api */ + // btif_sock_cleanup(); + // btif_pan_cleanup(); + BTA_DisableBluetooth(); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_shutdown_bluetooth +** +** Description Finalizes BT scheduler shutdown and terminates BTIF +** task. +** +** Returns void +** +*******************************************************************************/ + +bt_status_t btif_shutdown_bluetooth(void) +{ + BTIF_TRACE_DEBUG("%s", __FUNCTION__); + + fixed_queue_unregister_dequeue(btif_msg_queue); + fixed_queue_free(btif_msg_queue, NULL); + btif_msg_queue = NULL; + + vTaskDelete(xBtifTaskHandle); + xBtifTaskHandle = NULL; + + vQueueDelete(xBtifQueue); + xBtifQueue = NULL; + + bte_main_shutdown(); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_get_enabled_services_mask +** +** Description Fetches currently enabled services +** +** Returns tBTA_SERVICE_MASK +** +*******************************************************************************/ + +tBTA_SERVICE_MASK btif_get_enabled_services_mask(void) +{ + return btif_enabled_services; +} + +/******************************************************************************* +** +** Function btif_enable_service +** +** Description Enables the service 'service_ID' to the service_mask. +** Upon BT enable, BTIF core shall invoke the BTA APIs to +** enable the profiles +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_enable_service(tBTA_SERVICE_ID service_id) +{ + tBTA_SERVICE_ID *p_id = &service_id; + + /* If BT is enabled, we need to switch to BTIF context and trigger the + * enable for that profile + * + * Otherwise, we just set the flag. On BT_Enable, the DM will trigger + * enable for the profiles that have been enabled */ + + btif_enabled_services |= (1 << service_id); + + BTIF_TRACE_DEBUG("%s: current services:0x%x", __FUNCTION__, btif_enabled_services); + + if (btif_is_enabled()) { + btif_transfer_context(btif_dm_execute_service_request, + BTIF_DM_ENABLE_SERVICE, + (char*)p_id, sizeof(tBTA_SERVICE_ID), NULL); + } + + return BT_STATUS_SUCCESS; +} +/******************************************************************************* +** +** Function btif_disable_service +** +** Description Disables the service 'service_ID' to the service_mask. +** Upon BT disable, BTIF core shall invoke the BTA APIs to +** disable the profiles +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_disable_service(tBTA_SERVICE_ID service_id) +{ + tBTA_SERVICE_ID *p_id = &service_id; + + /* If BT is enabled, we need to switch to BTIF context and trigger the + * disable for that profile so that the appropriate uuid_property_changed will + * be triggerred. Otherwise, we just need to clear the service_id in the mask + */ + + btif_enabled_services &= (tBTA_SERVICE_MASK)(~(1< +// #include +#include +#include +#include +// #include +// #include + +// #include + +// #include +#include "gki.h" +#include "btu.h" +// #include "btcore/include/bdaddr.h" +#include "bta_api.h" +#include "btif_api.h" +#include "btif_util.h" +#include "btif_dm.h" +// #include "btif_storage.h" +// #include "btif_hh.h" +// #include "btif_config.h" +// #include "btif_sdp.h" +// #include "bta_gatt_api.h" +// #include "device/include/interop.h" +// #include "include/stack_config.h" +// #include "osi/include/log.h" +#include "allocator.h" +#include "btm_int.h" +#include "bt_defs.h" +#include "future.h" +#include "stack_manager.h" + +/****************************************************************************** +** Constants & Macros +******************************************************************************/ +#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id)) + +/************************************************************************************ +** Static variables +************************************************************************************/ +/****************************************************************************** +** Static functions +******************************************************************************/ +/****************************************************************************** +** Externs +******************************************************************************/ +extern bt_status_t btif_sdp_execute_service(BOOLEAN b_enable); + +/****************************************************************************** +** Functions +******************************************************************************/ + +static void btif_dm_data_copy(uint16_t event, char *dst, char *src) +{ + tBTA_DM_SEC *dst_dm_sec = (tBTA_DM_SEC*)dst; + tBTA_DM_SEC *src_dm_sec = (tBTA_DM_SEC*)src; + + if (!src_dm_sec) + return; + + assert(dst_dm_sec); + memcpy(dst_dm_sec, src_dm_sec, sizeof(tBTA_DM_SEC)); + + if (event == BTA_DM_BLE_KEY_EVT) { + dst_dm_sec->ble_key.p_key_value = osi_malloc(sizeof(tBTM_LE_KEY_VALUE)); + assert(src_dm_sec->ble_key.p_key_value); + assert(dst_dm_sec->ble_key.p_key_value); + memcpy(dst_dm_sec->ble_key.p_key_value, src_dm_sec->ble_key.p_key_value, sizeof(tBTM_LE_KEY_VALUE)); + } +} + +static void btif_dm_data_free(uint16_t event, tBTA_DM_SEC *dm_sec) +{ + if (event == BTA_DM_BLE_KEY_EVT) { + osi_free(dm_sec->ble_key.p_key_value); + } +} + +bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id, + BOOLEAN b_enable) +{ + BTIF_TRACE_DEBUG("%s service_id: %d\n", __FUNCTION__, service_id); + /* Check the service_ID and invoke the profile's BT state changed API */ + switch (service_id) { + case BTA_SDP_SERVICE_ID: + btif_sdp_execute_service(b_enable); + break; + default: + BTIF_TRACE_ERROR("%s: Unknown service being enabled\n", __FUNCTION__); + return BT_STATUS_FAIL; + } + return BT_STATUS_SUCCESS; +} + +void btif_dm_execute_service_request(UINT16 event, char *p_param) +{ + BOOLEAN b_enable = FALSE; + if (event == BTIF_DM_ENABLE_SERVICE) { + b_enable = TRUE; + } + + btif_in_execute_service_request(*((tBTA_SERVICE_ID*)p_param), b_enable); +} + +/******************************************************************************* +** +** Function btif_dm_upstreams_cback +** +** Description Executes UPSTREAMS events in btif context +** +** Returns void +** +*******************************************************************************/ +static void btif_dm_upstreams_evt(UINT16 event, char* p_param) +{ + tBTA_DM_SEC *p_data = (tBTA_DM_SEC*)p_param; + tBTA_SERVICE_MASK service_mask; + uint32_t i; + BTIF_TRACE_EVENT("btif_dm_upstreams_cback ev: %d\n", event); + + switch (event) { + case BTA_DM_ENABLE_EVT: + /* for each of the enabled services in the mask, trigger the profile + * enable */ + service_mask = btif_get_enabled_services_mask(); + for (i=0; i <= BTA_MAX_SERVICE_ID; i++) { + if (service_mask & + (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(i))) { + btif_in_execute_service_request(i, TRUE); + } + } + btif_enable_bluetooth_evt(p_data->enable.status); + break; + case BTA_DM_DISABLE_EVT: + /* for each of the enabled services in the mask, trigger the profile + * disable */ + service_mask = btif_get_enabled_services_mask(); + for (i=0; i <= BTA_MAX_SERVICE_ID; i++) { + if (service_mask & + (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(i))) { + btif_in_execute_service_request(i, FALSE); + } + } + btif_disable_bluetooth_evt(); + break; + case BTA_DM_PIN_REQ_EVT: + case BTA_DM_AUTH_CMPL_EVT: + case BTA_DM_BOND_CANCEL_CMPL_EVT: + case BTA_DM_SP_CFM_REQ_EVT: + case BTA_DM_SP_KEY_NOTIF_EVT: + + case BTA_DM_DEV_UNPAIRED_EVT: + case BTA_DM_BUSY_LEVEL_EVT: + case BTA_DM_LINK_UP_EVT: + case BTA_DM_LINK_DOWN_EVT: + case BTA_DM_HW_ERROR_EVT: + +#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) + case BTA_DM_BLE_KEY_EVT: + case BTA_DM_BLE_SEC_REQ_EVT: + case BTA_DM_BLE_PASSKEY_NOTIF_EVT: + case BTA_DM_BLE_PASSKEY_REQ_EVT: + case BTA_DM_BLE_NC_REQ_EVT: + case BTA_DM_BLE_OOB_REQ_EVT: + case BTA_DM_BLE_LOCAL_IR_EVT: + case BTA_DM_BLE_LOCAL_ER_EVT: + case BTA_DM_BLE_AUTH_CMPL_EVT: + case BTA_DM_LE_FEATURES_READ: + case BTA_DM_ENER_INFO_READ: +#endif + + case BTA_DM_AUTHORIZE_EVT: + case BTA_DM_SIG_STRENGTH_EVT: + case BTA_DM_SP_RMT_OOB_EVT: + case BTA_DM_SP_KEYPRESS_EVT: + case BTA_DM_ROLE_CHG_EVT: + + default: + BTIF_TRACE_WARNING( "btif_dm_cback : unhandled event (%d)\n", event ); + break; + } + + btif_dm_data_free(event, p_data); +} + +/******************************************************************************* +** +** Function bte_dm_evt +** +** Description Switches context from BTE to BTIF for all DM events +** +** Returns void +** +*******************************************************************************/ + +void bte_dm_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data) +{ + /* switch context to btif task context (copy full union size for convenience) */ + bt_status_t status = btif_transfer_context(btif_dm_upstreams_evt, (uint16_t)event, + (void*)p_data, sizeof(tBTA_DM_SEC), btif_dm_data_copy); + + /* catch any failed context transfers */ + ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed\n", status); +} diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/btif_media_task.c b/examples/09_a2dp/components/bluedroid_demos/btif/btif_media_task.c new file mode 100755 index 0000000000..67a1ec1249 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/btif_media_task.c @@ -0,0 +1,2836 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/****************************************************************************** + ** + ** Name: btif_media_task.c + ** + ** Description: This is the multimedia module for the BTIF system. It + ** contains task implementations AV, HS and HF profiles + ** audio & video processing + ** + ******************************************************************************/ + +#define LOG_TAG "bt_btif_media" + +// #include +#include "bt_trace.h" +#include +#include +// #include +// #include +// #include +// #include +// #include +#include +// #include +// #include + +#include "bt_target.h" +#include "fixed_queue.h" +#include "gki.h" +#include "bta_api.h" +#include "btu.h" +#include "bta_sys.h" +#include "bta_sys_int.h" + +#include "bta_av_api.h" +#include "a2d_api.h" +#include "a2d_sbc.h" +#include "a2d_int.h" +#include "bta_av_sbc.h" +#include "bta_av_ci.h" +#include "l2c_api.h" + +#include "btif_av_co.h" +#include "btif_media.h" + +#include "alarm.h" +// #include "ois/include/log.h" +#include "bt_trace.h" +#include "thread.h" + +#if (BTA_AV_INCLUDED == TRUE) +#include "sbc_encoder.h" +#endif + +// #include +#include "bt_defs.h" +#include "audio_a2dp_hw.h" +#include "btif_av.h" +#include "btif_sm.h" +#include "btif_util.h" +#if (BTA_AV_SINK_INCLUDED == TRUE) +#include "oi_codec_sbc.h" +#include "oi_status.h" +#endif +#include "stdio.h" +// #include +#include "btif_media.h" +#include "allocator.h" +#include "bt_utils.h" + +#if (BTA_AV_SINK_INCLUDED == TRUE) +OI_CODEC_SBC_DECODER_CONTEXT context; +OI_UINT32 contextData[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)]; +OI_INT16 pcmData[15*SBC_MAX_SAMPLES_PER_FRAME*SBC_MAX_CHANNELS]; +#endif + + +/***************************************************************************** + ** Constants + *****************************************************************************/ + +#ifndef AUDIO_CHANNEL_OUT_MONO +#define AUDIO_CHANNEL_OUT_MONO 0x01 +#endif + +#ifndef AUDIO_CHANNEL_OUT_STEREO +#define AUDIO_CHANNEL_OUT_STEREO 0x03 +#endif + +/* BTIF media cmd event definition : BTIF_MEDIA_TASK_CMD */ +enum +{ + BTIF_MEDIA_START_AA_TX = 1, + BTIF_MEDIA_STOP_AA_TX, + BTIF_MEDIA_AA_RX_RDY, + BTIF_MEDIA_UIPC_RX_RDY, + BTIF_MEDIA_SBC_ENC_INIT, + BTIF_MEDIA_SBC_ENC_UPDATE, + BTIF_MEDIA_SBC_DEC_INIT, + BTIF_MEDIA_VIDEO_DEC_INIT, + BTIF_MEDIA_FLUSH_AA_TX, + BTIF_MEDIA_FLUSH_AA_RX, + BTIF_MEDIA_AUDIO_FEEDING_INIT, + BTIF_MEDIA_AUDIO_RECEIVING_INIT, + BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE, + BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK +}; + +enum { + MEDIA_TASK_STATE_OFF = 0, + MEDIA_TASK_STATE_ON = 1, + MEDIA_TASK_STATE_SHUTTING_DOWN = 2 +}; + +enum { + SIG_MEDIA_TASK_INIT = 0xf0, + SIG_MEDIA_TASK_CLEAN_UP = 0xf1, + SIG_MEDIA_TASK_AVK_ALARM_TO = 0xf2, + SIG_MEDIA_TASK_AA_ALARM_TO = 0xf3, + SIG_MEDIA_TASK_CMD_READY = 0xf4 +}; + +/* Macro to multiply the media task tick */ +#ifndef BTIF_MEDIA_NUM_TICK +#define BTIF_MEDIA_NUM_TICK 1 +#endif + +/* Media task tick in milliseconds, must be set to multiple of + (1000/TICKS_PER_SEC) (10) */ + +#define BTIF_MEDIA_TIME_TICK (20 * BTIF_MEDIA_NUM_TICK) +#define A2DP_DATA_READ_POLL_MS (BTIF_MEDIA_TIME_TICK / 2) +#define BTIF_SINK_MEDIA_TIME_TICK (20 * BTIF_MEDIA_NUM_TICK) + + +/* buffer pool */ +#define BTIF_MEDIA_AA_POOL_ID GKI_POOL_ID_3 +#define BTIF_MEDIA_AA_BUF_SIZE GKI_BUF3_SIZE + +/* offset */ +#if (BTA_AV_CO_CP_SCMS_T == TRUE) +#define BTIF_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE + 1) +#else +#define BTIF_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE) +#endif + +/* Define the bitrate step when trying to match bitpool value */ +#ifndef BTIF_MEDIA_BITRATE_STEP +#define BTIF_MEDIA_BITRATE_STEP 5 +#endif + +/* Middle quality quality setting @ 44.1 khz */ +#define DEFAULT_SBC_BITRATE 328 + +#ifndef BTIF_A2DP_NON_EDR_MAX_RATE +#define BTIF_A2DP_NON_EDR_MAX_RATE 229 +#endif + +#define USEC_PER_SEC 1000000L +#define TPUT_STATS_INTERVAL_US (3000*1000) + +/* + * CONGESTION COMPENSATION CTRL :: + * + * Thus setting controls how many buffers we will hold in media task + * during temp link congestion. Together with the stack buffer queues + * it controls much temporary a2dp link congestion we can + * compensate for. It however also depends on the default run level of sinks + * jitterbuffers. Depending on type of sink this would vary. + * Ideally the (SRC) max tx buffer capacity should equal the sinks + * jitterbuffer runlevel including any intermediate buffers on the way + * towards the sinks codec. + */ + +/* fixme -- define this in pcm time instead of buffer count */ + +/* The typical runlevel of the tx queue size is ~1 buffer + but due to link flow control or thread preemption in lower + layers we might need to temporarily buffer up data */ + +/* 18 frames is equivalent to 6.89*18*2.9 ~= 360 ms @ 44.1 khz, 20 ms mediatick */ +#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ 18 + +#ifndef MAX_PCM_FRAME_NUM_PER_TICK +#define MAX_PCM_FRAME_NUM_PER_TICK 14 +#endif + +/* In case of A2DP SINK, we will delay start by 5 AVDTP Packets*/ +#define MAX_A2DP_DELAYED_START_FRAME_COUNT 5 +#define PACKET_PLAYED_PER_TICK_48 8 +#define PACKET_PLAYED_PER_TICK_44 7 +#define PACKET_PLAYED_PER_TICK_32 5 +#define PACKET_PLAYED_PER_TICK_16 3 + +typedef struct +{ + UINT16 num_frames_to_be_processed; + UINT16 len; + UINT16 offset; + UINT16 layer_specific; +} tBT_SBC_HDR; + +typedef struct +{ + UINT32 aa_frame_counter; + INT32 aa_feed_counter; + INT32 aa_feed_residue; + UINT32 counter; + UINT32 bytes_per_tick; /* pcm bytes read each media task tick */ +} tBTIF_AV_MEDIA_FEEDINGS_PCM_STATE; + +typedef union +{ + tBTIF_AV_MEDIA_FEEDINGS_PCM_STATE pcm; +} tBTIF_AV_MEDIA_FEEDINGS_STATE; + +typedef struct +{ +#if (BTA_AV_INCLUDED == TRUE) + BUFFER_Q TxAaQ; + BUFFER_Q RxSbcQ; + BOOLEAN is_tx_timer; + BOOLEAN is_rx_timer; + UINT16 TxAaMtuSize; + UINT32 timestamp; + UINT8 TxTranscoding; + tBTIF_AV_FEEDING_MODE feeding_mode; + tBTIF_AV_MEDIA_FEEDINGS media_feeding; + tBTIF_AV_MEDIA_FEEDINGS_STATE media_feeding_state; + SBC_ENC_PARAMS encoder; + UINT8 busy_level; + void* av_sm_hdl; + UINT8 a2dp_cmd_pending; /* we can have max one command pending */ + BOOLEAN tx_flush; /* discards any outgoing data when true */ + BOOLEAN rx_flush; /* discards any incoming data when true */ + UINT8 peer_sep; + BOOLEAN data_channel_open; + UINT8 frames_to_process; + + UINT32 sample_rate; + UINT8 channel_count; + osi_alarm_t *media_alarm; + osi_alarm_t *decode_alarm; +#endif + +} tBTIF_MEDIA_CB; + +typedef struct { + long long rx; + long long rx_tot; + long long tx; + long long tx_tot; + long long ts_prev_us; +} t_stat; + +static UINT64 last_frame_us = 0; + +static void btif_a2dp_data_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event); +static void btif_a2dp_ctrl_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event); +static void btif_a2dp_encoder_update(void); +#if (BTA_AV_SINK_INCLUDED == TRUE) +extern OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, + const OI_BYTE **frameData, + unsigned long *frameBytes, + OI_INT16 *pcmData, + unsigned long *pcmBytes); +extern OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, + unsigned long *decoderData, + unsigned long decoderDataBytes, + OI_UINT8 maxChannels, + OI_UINT8 pcmStride, + OI_BOOL enhanced); +#endif +static void btif_media_flush_q(BUFFER_Q *p_q); +static void btif_media_task_aa_handle_stop_decoding(void ); +static void btif_media_task_aa_rx_flush(void); + +static const char *dump_media_event(UINT16 event); +// static void btif_media_thread_init(void *context); +// static void btif_media_thread_cleanup(void *context); +static void btif_media_thread_handle_cmd(fixed_queue_t *queue); + +/* Handle incoming media packets A2DP SINK streaming*/ +#if (BTA_AV_SINK_INCLUDED == TRUE) +static void btif_media_task_handle_inc_media(tBT_SBC_HDR*p_msg); +#endif + +#if (BTA_AV_INCLUDED == TRUE) +static void btif_media_send_aa_frame(void); +static void btif_media_task_feeding_state_reset(void); +static void btif_media_task_aa_start_tx(void); +static void btif_media_task_aa_stop_tx(void); +static void btif_media_task_enc_init(BT_HDR *p_msg); +static void btif_media_task_enc_update(BT_HDR *p_msg); +static void btif_media_task_audio_feeding_init(BT_HDR *p_msg); +static void btif_media_task_aa_tx_flush(BT_HDR *p_msg); +static void btif_media_aa_prep_2_send(UINT8 nb_frame); +#if (BTA_AV_SINK_INCLUDED == TRUE) +static void btif_media_task_aa_handle_decoder_reset(BT_HDR *p_msg); +static void btif_media_task_aa_handle_clear_track(void); +#endif +static void btif_media_task_aa_handle_start_decoding(void); +#endif +BOOLEAN btif_media_task_clear_track(void); +static void btif_media_task_handler(void *arg); +static void btif_media_task_aa_handle_timer(UNUSED_ATTR void *context); +static void btif_media_task_avk_handle_timer(UNUSED_ATTR void *context); +static void btif_media_thread_init(UNUSED_ATTR void *context); +static void btif_media_thread_cleanup(UNUSED_ATTR void *context); +extern BOOLEAN btif_hf_is_call_idle(); + +static tBTIF_MEDIA_CB btif_media_cb; +static int media_task_running = MEDIA_TASK_STATE_OFF; + +static fixed_queue_t *btif_media_cmd_msg_queue = NULL; +// static thread_t *worker_thread; +static xTaskHandle xBtifMediaTaskHandle = NULL; +static QueueHandle_t xBtifMediaQueue = NULL; + +/***************************************************************************** + ** Misc helper functions + *****************************************************************************/ + +static UINT64 time_now_us() +{ + // TODO: implement this function + return 0; +} + +static void log_tstamps_us(char *comment) +{ + static UINT64 prev_us = 0; + const UINT64 now_us = time_now_us(); + APPL_TRACE_DEBUG("[%s] ts %08llu, diff : %08llu, queue sz %d", comment, now_us, now_us - prev_us, + GKI_queue_length(&btif_media_cb.TxAaQ)); + prev_us = now_us; +} + +UNUSED_ATTR static const char *dump_media_event(UINT16 event) +{ + switch(event) + { + CASE_RETURN_STR(BTIF_MEDIA_START_AA_TX) + CASE_RETURN_STR(BTIF_MEDIA_STOP_AA_TX) + CASE_RETURN_STR(BTIF_MEDIA_AA_RX_RDY) + CASE_RETURN_STR(BTIF_MEDIA_UIPC_RX_RDY) + CASE_RETURN_STR(BTIF_MEDIA_SBC_ENC_INIT) + CASE_RETURN_STR(BTIF_MEDIA_SBC_ENC_UPDATE) + CASE_RETURN_STR(BTIF_MEDIA_SBC_DEC_INIT) + CASE_RETURN_STR(BTIF_MEDIA_VIDEO_DEC_INIT) + CASE_RETURN_STR(BTIF_MEDIA_FLUSH_AA_TX) + CASE_RETURN_STR(BTIF_MEDIA_FLUSH_AA_RX) + CASE_RETURN_STR(BTIF_MEDIA_AUDIO_FEEDING_INIT) + CASE_RETURN_STR(BTIF_MEDIA_AUDIO_RECEIVING_INIT) + CASE_RETURN_STR(BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE) + CASE_RETURN_STR(BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK) + + default: + return "UNKNOWN MEDIA EVENT"; + } +} + +/***************************************************************************** + ** A2DP CTRL PATH + *****************************************************************************/ + +static const char* dump_a2dp_ctrl_event(UINT8 event) +{ + switch(event) + { + CASE_RETURN_STR(A2DP_CTRL_CMD_NONE) + CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_READY) + CASE_RETURN_STR(A2DP_CTRL_CMD_START) + CASE_RETURN_STR(A2DP_CTRL_CMD_STOP) + CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND) + default: + return "UNKNOWN MSG ID"; + } +} + +static void btif_audiopath_detached(void) +{ + APPL_TRACE_EVENT("## AUDIO PATH DETACHED ##"); + + /* send stop request only if we are actively streaming and haven't received + a stop request. Potentially audioflinger detached abnormally */ + if (btif_media_cb.is_tx_timer) + { + /* post stop event and wait for audio path to stop */ + btif_dispatch_sm_event(BTIF_AV_STOP_STREAM_REQ_EVT, NULL, 0); + } +} + +static void a2dp_cmd_acknowledge(int status) +{ + UINT8 ack = status; + + APPL_TRACE_EVENT("## a2dp ack : %s, status %d ##", + dump_a2dp_ctrl_event(btif_media_cb.a2dp_cmd_pending), status); + + /* sanity check */ + if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_NONE) + { + APPL_TRACE_ERROR("warning : no command pending, ignore ack"); + return; + } + + /* clear pending */ + btif_media_cb.a2dp_cmd_pending = A2DP_CTRL_CMD_NONE; + + /* acknowledge start request */ + UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, &ack, 1); +} + + +static void btif_recv_ctrl_data(void) +{ + UINT8 cmd = 0; + int n; + n = UIPC_Read(UIPC_CH_ID_AV_CTRL, NULL, &cmd, 1); + + /* detach on ctrl channel means audioflinger process was terminated */ + if (n == 0) + { + APPL_TRACE_EVENT("CTRL CH DETACHED"); + UIPC_Close(UIPC_CH_ID_AV_CTRL); + /* we can operate only on datachannel, if af client wants to + do send additional commands the ctrl channel would be reestablished */ + //btif_audiopath_detached(); + return; + } + + APPL_TRACE_DEBUG("a2dp-ctrl-cmd : %s", dump_a2dp_ctrl_event(cmd)); + + btif_media_cb.a2dp_cmd_pending = cmd; + + switch(cmd) + { + case A2DP_CTRL_CMD_CHECK_READY: + + if (media_task_running == MEDIA_TASK_STATE_SHUTTING_DOWN) + { + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE); + return; + } + + /* check whether av is ready to setup a2dp datapath */ + if ((btif_av_stream_ready() == TRUE) || (btif_av_stream_started_ready() == TRUE)) + { + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + } + else + { + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE); + } + break; + + case A2DP_CTRL_CMD_START: + /* Don't sent START request to stack while we are in call. + Some headsets like the Sony MW600, don't allow AVDTP START + in call and respond BAD_STATE. */ + if (!btif_hf_is_call_idle()) + { + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_INCALL_FAILURE); + break; + } + + if (btif_av_stream_ready() == TRUE) + { + /* setup audio data channel listener */ + UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb); + + /* post start event and wait for audio path to open */ + btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0); + +#if (BTA_AV_SINK_INCLUDED == TRUE) + if (btif_media_cb.peer_sep == AVDT_TSEP_SRC) + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); +#endif + } + else if (btif_av_stream_started_ready()) + { + /* already started, setup audio data channel listener + and ack back immediately */ + UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb); + + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + } + else + { + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE); + break; + } + break; + + case A2DP_CTRL_CMD_STOP: + if (btif_media_cb.peer_sep == AVDT_TSEP_SNK && btif_media_cb.is_tx_timer == FALSE) + { + /* we are already stopped, just ack back */ + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + break; + } + + btif_dispatch_sm_event(BTIF_AV_STOP_STREAM_REQ_EVT, NULL, 0); + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + break; + + case A2DP_CTRL_CMD_SUSPEND: + /* local suspend */ + if (btif_av_stream_started_ready()) + { + btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0); + } + else + { + /* if we are not in started state, just ack back ok and let + audioflinger close the channel. This can happen if we are + remotely suspended, clear REMOTE SUSPEND Flag */ + btif_av_clear_remote_suspend_flag(); + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + } + break; + + case A2DP_CTRL_GET_AUDIO_CONFIG: + { + uint32_t sample_rate = btif_media_cb.sample_rate; + uint8_t channel_count = btif_media_cb.channel_count; + + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, (UINT8 *)&sample_rate, 4); + UIPC_Send(UIPC_CH_ID_AV_CTRL, 0, &channel_count, 1); + break; + } + + default: + APPL_TRACE_ERROR("UNSUPPORTED CMD (%d)", cmd); + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE); + break; + } + APPL_TRACE_DEBUG("a2dp-ctrl-cmd : %s DONE", dump_a2dp_ctrl_event(cmd)); +} + +static void btif_a2dp_ctrl_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event) +{ + UNUSED(ch_id); + + APPL_TRACE_DEBUG("A2DP-CTRL-CHANNEL EVENT %s", dump_uipc_event(event)); + + switch(event) + { + case UIPC_OPEN_EVT: + /* fetch av statemachine handle */ + btif_media_cb.av_sm_hdl = btif_av_get_sm_handle(); + break; + + case UIPC_CLOSE_EVT: + /* restart ctrl server unless we are shutting down */ + if (media_task_running == MEDIA_TASK_STATE_ON) + UIPC_Open(UIPC_CH_ID_AV_CTRL , btif_a2dp_ctrl_cb); + break; + + case UIPC_RX_DATA_READY_EVT: + btif_recv_ctrl_data(); + break; + + default : + APPL_TRACE_ERROR("### A2DP-CTRL-CHANNEL EVENT %d NOT HANDLED ###", event); + break; + } +} + +static void btif_a2dp_data_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event) +{ + UNUSED(ch_id); + + APPL_TRACE_DEBUG("BTIF MEDIA (A2DP-DATA) EVENT %s", dump_uipc_event(event)); + + switch(event) + { + case UIPC_OPEN_EVT: + + /* read directly from media task from here on (keep callback for + connection events */ + UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REG_REMOVE_ACTIVE_READSET, NULL); + UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO, + (void *)A2DP_DATA_READ_POLL_MS); + + if (btif_media_cb.peer_sep == AVDT_TSEP_SNK) { + /* Start the media task to encode SBC */ + btif_media_task_start_aa_req(); + + /* make sure we update any changed sbc encoder params */ + btif_a2dp_encoder_update(); + } + btif_media_cb.data_channel_open = TRUE; + + /* ack back when media task is fully started */ + break; + + case UIPC_CLOSE_EVT: + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + btif_audiopath_detached(); + btif_media_cb.data_channel_open = FALSE; + break; + + default : + APPL_TRACE_ERROR("### A2DP-DATA EVENT %d NOT HANDLED ###", event); + break; + } +} + + +/***************************************************************************** + ** BTIF ADAPTATION + *****************************************************************************/ + +static UINT16 btif_media_task_get_sbc_rate(void) +{ + UINT16 rate = DEFAULT_SBC_BITRATE; + + /* restrict bitrate if a2dp link is non-edr */ + if (!btif_av_is_peer_edr()) + { + rate = BTIF_A2DP_NON_EDR_MAX_RATE; + APPL_TRACE_DEBUG("non-edr a2dp sink detected, restrict rate to %d", rate); + } + + return rate; +} + +static void btif_a2dp_encoder_init(void) +{ + UINT16 minmtu; + tBTIF_MEDIA_INIT_AUDIO msg; + tA2D_SBC_CIE sbc_config; + + /* lookup table for converting channel mode */ + UINT16 codec_mode_tbl[5] = { SBC_JOINT_STEREO, SBC_STEREO, SBC_DUAL, 0, SBC_MONO }; + + /* lookup table for converting number of blocks */ + UINT16 codec_block_tbl[5] = { 16, 12, 8, 0, 4 }; + + /* lookup table to convert freq */ + UINT16 freq_block_tbl[5] = { SBC_sf48000, SBC_sf44100, SBC_sf32000, 0, SBC_sf16000 }; + + APPL_TRACE_DEBUG("btif_a2dp_encoder_init"); + + /* Retrieve the current SBC configuration (default if currently not used) */ + bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu); + msg.NumOfSubBands = (sbc_config.num_subbands == A2D_SBC_IE_SUBBAND_4) ? 4 : 8; + msg.NumOfBlocks = codec_block_tbl[sbc_config.block_len >> 5]; + msg.AllocationMethod = (sbc_config.alloc_mthd == A2D_SBC_IE_ALLOC_MD_L) ? SBC_LOUDNESS : SBC_SNR; + msg.ChannelMode = codec_mode_tbl[sbc_config.ch_mode >> 1]; + msg.SamplingFreq = freq_block_tbl[sbc_config.samp_freq >> 5]; + msg.MtuSize = minmtu; + + APPL_TRACE_EVENT("msg.ChannelMode %x", msg.ChannelMode); + + /* Init the media task to encode SBC properly */ + btif_media_task_enc_init_req(&msg); +} + +static void btif_a2dp_encoder_update(void) +{ + UINT16 minmtu; + tA2D_SBC_CIE sbc_config; + tBTIF_MEDIA_UPDATE_AUDIO msg; + UINT8 pref_min; + UINT8 pref_max; + + APPL_TRACE_DEBUG("btif_a2dp_encoder_update"); + + /* Retrieve the current SBC configuration (default if currently not used) */ + bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu); + + APPL_TRACE_DEBUG("btif_a2dp_encoder_update: Common min_bitpool:%d(0x%x) max_bitpool:%d(0x%x)", + sbc_config.min_bitpool, sbc_config.min_bitpool, + sbc_config.max_bitpool, sbc_config.max_bitpool); + + if (sbc_config.min_bitpool > sbc_config.max_bitpool) + { + APPL_TRACE_ERROR("btif_a2dp_encoder_update: ERROR btif_a2dp_encoder_update min_bitpool > max_bitpool"); + } + + /* check if remote sink has a preferred bitpool range */ + if (bta_av_co_get_remote_bitpool_pref(&pref_min, &pref_max) == TRUE) + { + /* adjust our preferred bitpool with the remote preference if within + our capable range */ + + if (pref_min < sbc_config.min_bitpool) + pref_min = sbc_config.min_bitpool; + + if (pref_max > sbc_config.max_bitpool) + pref_max = sbc_config.max_bitpool; + + msg.MinBitPool = pref_min; + msg.MaxBitPool = pref_max; + + if ((pref_min != sbc_config.min_bitpool) || (pref_max != sbc_config.max_bitpool)) + { + APPL_TRACE_EVENT("## adjusted our bitpool range to peer pref [%d:%d] ##", + pref_min, pref_max); + } + } + else + { + msg.MinBitPool = sbc_config.min_bitpool; + msg.MaxBitPool = sbc_config.max_bitpool; + } + + msg.MinMtuSize = minmtu; + + /* Update the media task to encode SBC properly */ + btif_media_task_enc_update_req(&msg); +} + + +static void btif_media_task_post(uint32_t sig) +{ + BtTaskEvt_t *evt = (BtTaskEvt_t *)osi_malloc(sizeof(BtTaskEvt_t)); + if (evt == NULL) + return; + + evt->sig = sig; + evt->par = 0; + + if (xQueueSend(xBtifMediaQueue, &evt, 10/portTICK_RATE_MS) != pdTRUE) { + APPL_TRACE_ERROR("xBtifMediaQueue failed\n"); + } +} + +static void btif_media_task_handler(void *arg) +{ + BtTaskEvt_t *e; + + for (;;) { + if (pdTRUE == xQueueReceive(xBtifMediaQueue, &e, (portTickType)portMAX_DELAY)) { + switch (e->sig) { + case SIG_MEDIA_TASK_AVK_ALARM_TO: + btif_media_task_avk_handle_timer(NULL); + break; + case SIG_MEDIA_TASK_AA_ALARM_TO: + btif_media_task_aa_handle_timer(NULL); + break; + case SIG_MEDIA_TASK_CMD_READY: + fixed_queue_process(btif_media_cmd_msg_queue); + case SIG_MEDIA_TASK_INIT: + btif_media_thread_init(NULL); + break; + case SIG_MEDIA_TASK_CLEAN_UP: + btif_media_thread_cleanup(NULL); + break; + default: + APPL_TRACE_ERROR("media task unhandled evt: 0x%x\n", e->sig); + } + } + osi_free(e); + } +} + +bool btif_a2dp_start_media_task(void) +{ + if (media_task_running != MEDIA_TASK_STATE_OFF) + { + APPL_TRACE_ERROR("warning : media task already running"); + return false; + } + + APPL_TRACE_EVENT("## A2DP START MEDIA THREAD ##"); + + btif_media_cmd_msg_queue = fixed_queue_new(SIZE_MAX); + if (btif_media_cmd_msg_queue == NULL) { + goto error_exit; + } + + xBtifMediaQueue = xQueueCreate(60, sizeof(void *)); + if (xBtifMediaQueue == 0) { + goto error_exit; + } + xTaskCreate(btif_media_task_handler, "BtifMediaT", 8192, NULL, configMAX_PRIORITIES - 1, &xBtifMediaTaskHandle); + if (xBtifMediaTaskHandle == NULL) + goto error_exit; + fixed_queue_register_dequeue(btif_media_cmd_msg_queue, btif_media_thread_handle_cmd); + btif_media_task_post(SIG_MEDIA_TASK_INIT); + + APPL_TRACE_EVENT("## A2DP MEDIA THREAD STARTED ##"); + + return true; + + error_exit:; + APPL_TRACE_ERROR("%s unable to start up media thread", __func__); + + if (xBtifMediaTaskHandle != NULL) { + vTaskDelete(xBtifMediaTaskHandle); + xBtifMediaTaskHandle = NULL; + } + + if (xBtifMediaQueue != 0) { + vQueueDelete(xBtifMediaQueue); + xBtifMediaQueue = 0; + } + fixed_queue_free(btif_media_cmd_msg_queue, NULL); + btif_media_cmd_msg_queue = NULL; + return false; +} + +void btif_a2dp_stop_media_task(void) +{ + APPL_TRACE_EVENT("## A2DP STOP MEDIA THREAD ##"); + + // Stop timer + osi_alarm_free(btif_media_cb.media_alarm); + btif_media_cb.media_alarm = NULL; + btif_media_cb.is_tx_timer = FALSE; + + // Exit thread + btif_media_task_post(SIG_MEDIA_TASK_CLEAN_UP); + vTaskDelete(xBtifMediaTaskHandle); + xBtifMediaTaskHandle = NULL; + vQueueDelete(xBtifMediaQueue); + xBtifMediaQueue = NULL; + + fixed_queue_free(btif_media_cmd_msg_queue, NULL); + btif_media_cmd_msg_queue = NULL; +} + +/***************************************************************************** +** +** Function btif_a2dp_on_init +** +** Description +** +** Returns +** +*******************************************************************************/ + +void btif_a2dp_on_init(void) +{ + //tput_mon(1, 0, 1); +} + + +/***************************************************************************** +** +** Function btif_a2dp_setup_codec +** +** Description +** +** Returns +** +*******************************************************************************/ + +void btif_a2dp_setup_codec(void) +{ + tBTIF_AV_MEDIA_FEEDINGS media_feeding; + tBTIF_STATUS status; + + APPL_TRACE_EVENT("## A2DP SETUP CODEC ##"); + + GKI_disable(); + + /* for now hardcode 44.1 khz 16 bit stereo PCM format */ + media_feeding.cfg.pcm.sampling_freq = 44100; + media_feeding.cfg.pcm.bit_per_sample = 16; + media_feeding.cfg.pcm.num_channel = 2; + media_feeding.format = BTIF_AV_CODEC_PCM; + + if (bta_av_co_audio_set_codec(&media_feeding, &status)) + { + tBTIF_MEDIA_INIT_AUDIO_FEEDING mfeed; + + /* Init the encoding task */ + btif_a2dp_encoder_init(); + + /* Build the media task configuration */ + mfeed.feeding = media_feeding; + mfeed.feeding_mode = BTIF_AV_FEEDING_ASYNCHRONOUS; + /* Send message to Media task to configure transcoding */ + btif_media_task_audio_feeding_init_req(&mfeed); + } + + GKI_enable(); +} + + +/***************************************************************************** +** +** Function btif_a2dp_on_idle +** +** Description +** +** Returns +** +*******************************************************************************/ + +void btif_a2dp_on_idle(void) +{ + APPL_TRACE_EVENT("## ON A2DP IDLE ##"); + if (btif_media_cb.peer_sep == AVDT_TSEP_SNK) + { + /* Make sure media task is stopped */ + btif_media_task_stop_aa_req(); + } + + bta_av_co_init(); +#if (BTA_AV_SINK_INCLUDED == TRUE) + if (btif_media_cb.peer_sep == AVDT_TSEP_SRC) + { + btif_media_cb.rx_flush = TRUE; + btif_media_task_aa_rx_flush_req(); + btif_media_task_aa_handle_stop_decoding(); + btif_media_task_clear_track(); + APPL_TRACE_DEBUG("Stopped BT track"); + } +#endif +} + +/***************************************************************************** +** +** Function btif_a2dp_on_open +** +** Description +** +** Returns +** +*******************************************************************************/ + +void btif_a2dp_on_open(void) +{ + APPL_TRACE_EVENT("## ON A2DP OPEN ##"); + + /* always use callback to notify socket events */ + UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb); +} + +/******************************************************************************* + ** + ** Function btif_media_task_clear_track + ** + ** Description + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +BOOLEAN btif_media_task_clear_track(void) +{ + BT_HDR *p_buf; + + if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR)))) + { + return FALSE; + } + + p_buf->event = BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK; + + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); + return TRUE; +} + +/***************************************************************************** +** +** Function btif_reset_decoder +** +** Description +** +** Returns +** +*******************************************************************************/ + +void btif_reset_decoder(UINT8 *p_av) +{ + APPL_TRACE_EVENT("btif_reset_decoder"); + APPL_TRACE_DEBUG("btif_reset_decoder p_codec_info[%x:%x:%x:%x:%x:%x]", + p_av[1], p_av[2], p_av[3], + p_av[4], p_av[5], p_av[6]); + + tBTIF_MEDIA_SINK_CFG_UPDATE *p_buf; + if (NULL == (p_buf = GKI_getbuf(sizeof(tBTIF_MEDIA_SINK_CFG_UPDATE)))) + { + APPL_TRACE_EVENT("btif_reset_decoder No Buffer "); + return; + } + + memcpy(p_buf->codec_info,p_av, AVDT_CODEC_SIZE); + p_buf->hdr.event = BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE; + + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); +} + +/***************************************************************************** +** +** Function btif_a2dp_on_started +** +** Description +** +** Returns +** +*******************************************************************************/ + +BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start) +{ + BOOLEAN ack = FALSE; + + APPL_TRACE_EVENT("## ON A2DP STARTED ##"); + + if (p_av == NULL) + { + /* ack back a local start request */ + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + return TRUE; + } + + if (p_av->status == BTA_AV_SUCCESS) + { + if (p_av->suspending == FALSE) + { + if (p_av->initiator) + { + if (pending_start) { + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + ack = TRUE; + } + } + else + { + /* we were remotely started, make sure codec + is setup before datapath is started */ + btif_a2dp_setup_codec(); + } + + /* media task is autostarted upon a2dp audiopath connection */ + } + } + else if (pending_start) + { + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE); + ack = TRUE; + } + return ack; +} + + +/***************************************************************************** +** +** Function btif_a2dp_ack_fail +** +** Description +** +** Returns +** +*******************************************************************************/ + +void btif_a2dp_ack_fail(void) +{ + APPL_TRACE_EVENT("## A2DP_CTRL_ACK_FAILURE ##"); + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE); +} + +/***************************************************************************** +** +** Function btif_a2dp_on_stopped +** +** Description +** +** Returns +** +*******************************************************************************/ + +void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av) +{ + APPL_TRACE_EVENT("## ON A2DP STOPPED ##"); + if (btif_media_cb.peer_sep == AVDT_TSEP_SRC) /* Handling for A2DP SINK cases*/ + { + btif_media_cb.rx_flush = TRUE; + btif_media_task_aa_rx_flush_req(); + btif_media_task_aa_handle_stop_decoding(); + UIPC_Close(UIPC_CH_ID_AV_AUDIO); + btif_media_cb.data_channel_open = FALSE; + return; + } + /* allow using this api for other than suspend */ + if (p_av != NULL) + { + if (p_av->status != BTA_AV_SUCCESS) + { + APPL_TRACE_EVENT("AV STOP FAILED (%d)", p_av->status); + + if (p_av->initiator) + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE); + return; + } + } + + /* ensure tx frames are immediately suspended */ + btif_media_cb.tx_flush = 1; + + /* request to stop media task */ + btif_media_task_aa_tx_flush_req(); + btif_media_task_stop_aa_req(); + + /* once stream is fully stopped we will ack back */ +} + + +/***************************************************************************** +** +** Function btif_a2dp_on_suspended +** +** Description +** +** Returns +** +*******************************************************************************/ + +void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av) +{ + APPL_TRACE_EVENT("## ON A2DP SUSPENDED ##"); + if (btif_media_cb.peer_sep == AVDT_TSEP_SRC) + { + btif_media_cb.rx_flush = TRUE; + btif_media_task_aa_rx_flush_req(); + btif_media_task_aa_handle_stop_decoding(); + return; + } + + /* check for status failures */ + if (p_av->status != BTA_AV_SUCCESS) + { + if (p_av->initiator == TRUE) + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE); + } + + /* once stream is fully stopped we will ack back */ + + /* ensure tx frames are immediately flushed */ + btif_media_cb.tx_flush = 1; + + /* stop timer tick */ + btif_media_task_stop_aa_req(); +} + +/* when true media task discards any rx frames */ +void btif_a2dp_set_rx_flush(BOOLEAN enable) +{ + APPL_TRACE_EVENT("## DROP RX %d ##", enable); + btif_media_cb.rx_flush = enable; +} + +/* when true media task discards any tx frames */ +void btif_a2dp_set_tx_flush(BOOLEAN enable) +{ + APPL_TRACE_EVENT("## DROP TX %d ##", enable); + btif_media_cb.tx_flush = enable; +} + +#if (BTA_AV_SINK_INCLUDED == TRUE) +static void btif_media_task_avk_handle_timer(UNUSED_ATTR void *context) +{ + UINT8 count; + tBT_SBC_HDR *p_msg; + int num_sbc_frames; + int num_frames_to_process; + + count = btif_media_cb.RxSbcQ._count; + if (0 == count) + { + APPL_TRACE_DEBUG(" QUE EMPTY "); + } + else + { + if (btif_media_cb.rx_flush == TRUE) + { + btif_media_flush_q(&(btif_media_cb.RxSbcQ)); + return; + } + + num_frames_to_process = btif_media_cb.frames_to_process; + APPL_TRACE_DEBUG(" Process Frames + "); + + do + { + p_msg = (tBT_SBC_HDR *)GKI_getfirst(&(btif_media_cb.RxSbcQ)); + if (p_msg == NULL) + return; + num_sbc_frames = p_msg->num_frames_to_be_processed; /* num of frames in Que Packets */ + APPL_TRACE_DEBUG(" Frames left in topmost packet %d", num_sbc_frames); + APPL_TRACE_DEBUG(" Remaining frames to process in tick %d", num_frames_to_process); + APPL_TRACE_DEBUG(" Num of Packets in Que %d", btif_media_cb.RxSbcQ._count); + + if ( num_sbc_frames > num_frames_to_process) /* Que Packet has more frames*/ + { + p_msg->num_frames_to_be_processed= num_frames_to_process; + btif_media_task_handle_inc_media(p_msg); + p_msg->num_frames_to_be_processed = num_sbc_frames - num_frames_to_process; + num_frames_to_process = 0; + break; + } + else /* Que packet has less frames */ + { + btif_media_task_handle_inc_media(p_msg); + p_msg = (tBT_SBC_HDR *)GKI_dequeue(&(btif_media_cb.RxSbcQ)); + if( p_msg == NULL ) + { + APPL_TRACE_ERROR("Insufficient data in que "); + break; + } + num_frames_to_process = num_frames_to_process - p_msg->num_frames_to_be_processed; + GKI_freebuf(p_msg); + } + }while(num_frames_to_process > 0); + + APPL_TRACE_DEBUG(" Process Frames - "); + } +} +#else +static void btif_media_task_avk_handle_timer(UNUSED_ATTR void *context) {} +#endif + +static void btif_media_task_aa_handle_timer(UNUSED_ATTR void *context) +{ + log_tstamps_us("media task tx timer"); + +#if (BTA_AV_INCLUDED == TRUE) + if(btif_media_cb.is_tx_timer == TRUE) + { + btif_media_send_aa_frame(); + } + else + { + APPL_TRACE_ERROR("ERROR Media task Scheduled after Suspend"); + } +#endif +} + +#if (BTA_AV_INCLUDED == TRUE) +static void btif_media_task_aa_handle_uipc_rx_rdy(void) +{ + /* process all the UIPC data */ + btif_media_aa_prep_2_send(0xFF); + + /* send it */ + LOG_VERBOSE("btif_media_task_aa_handle_uipc_rx_rdy calls bta_av_ci_src_data_ready"); + bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO); +} +#endif + +static void btif_media_thread_init(UNUSED_ATTR void *context) { + memset(&btif_media_cb, 0, sizeof(btif_media_cb)); + UIPC_Init(NULL); + +#if (BTA_AV_INCLUDED == TRUE) + UIPC_Open(UIPC_CH_ID_AV_CTRL , btif_a2dp_ctrl_cb); +#endif + + raise_priority_a2dp(TASK_HIGH_MEDIA); + media_task_running = MEDIA_TASK_STATE_ON; +} + +static void btif_media_thread_cleanup(UNUSED_ATTR void *context) { + /* make sure no channels are restarted while shutting down */ + media_task_running = MEDIA_TASK_STATE_SHUTTING_DOWN; + + /* this calls blocks until uipc is fully closed */ + UIPC_Close(UIPC_CH_ID_ALL); + + /* Clear media task flag */ + media_task_running = MEDIA_TASK_STATE_OFF; +} + +/******************************************************************************* + ** + ** Function btif_media_task_send_cmd_evt + ** + ** Description + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +BOOLEAN btif_media_task_send_cmd_evt(UINT16 Evt) +{ + BT_HDR *p_buf; + if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR)))) + { + return FALSE; + } + + p_buf->event = Evt; + + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); + return TRUE; +} + +/******************************************************************************* + ** + ** Function btif_media_flush_q + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_flush_q(BUFFER_Q *p_q) +{ + while (!GKI_queue_is_empty(p_q)) + { + GKI_freebuf(GKI_dequeue(p_q)); + } +} + +static void btif_media_thread_handle_cmd(fixed_queue_t *queue) +{ + BT_HDR *p_msg; + while (!fixed_queue_is_empty(queue)) { + p_msg = (BT_HDR *)fixed_queue_dequeue(queue); + LOG_VERBOSE("btif_media_thread_handle_cmd : %d %s", p_msg->event, + dump_media_event(p_msg->event)); + + switch (p_msg->event) + { +#if (BTA_AV_INCLUDED == TRUE) + case BTIF_MEDIA_START_AA_TX: + btif_media_task_aa_start_tx(); + break; + case BTIF_MEDIA_STOP_AA_TX: + btif_media_task_aa_stop_tx(); + break; + case BTIF_MEDIA_SBC_ENC_INIT: + btif_media_task_enc_init(p_msg); + break; + case BTIF_MEDIA_SBC_ENC_UPDATE: + btif_media_task_enc_update(p_msg); + break; + case BTIF_MEDIA_AUDIO_FEEDING_INIT: + btif_media_task_audio_feeding_init(p_msg); + break; + case BTIF_MEDIA_FLUSH_AA_TX: + btif_media_task_aa_tx_flush(p_msg); + break; + case BTIF_MEDIA_UIPC_RX_RDY: + btif_media_task_aa_handle_uipc_rx_rdy(); + break; + case BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE: +#if (BTA_AV_SINK_INCLUDED == TRUE) + btif_media_task_aa_handle_decoder_reset(p_msg); +#endif + break; + case BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK: +#if (BTA_AV_SINK_INCLUDED == TRUE) + btif_media_task_aa_handle_clear_track(); +#endif + break; + case BTIF_MEDIA_FLUSH_AA_RX: + btif_media_task_aa_rx_flush(); + break; +#endif + default: + APPL_TRACE_ERROR("ERROR in %s unknown event %d", __func__, p_msg->event); + } + GKI_freebuf(p_msg); + LOG_VERBOSE("%s: %s DONE", __func__, dump_media_event(p_msg->event)); + } +} + + +#if (BTA_AV_SINK_INCLUDED == TRUE) +/******************************************************************************* + ** + ** Function btif_media_task_handle_inc_media + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_handle_inc_media(tBT_SBC_HDR*p_msg) +{ + UINT8 *sbc_start_frame = ((UINT8*)(p_msg + 1) + p_msg->offset + 1); + int count; + UINT32 pcmBytes, availPcmBytes; + OI_INT16 *pcmDataPointer = pcmData; /*Will be overwritten on next packet receipt*/ + OI_STATUS status; + int num_sbc_frames = p_msg->num_frames_to_be_processed; + UINT32 sbc_frame_len = p_msg->len - 1; + availPcmBytes = 2*sizeof(pcmData); + + if ((btif_media_cb.peer_sep == AVDT_TSEP_SNK) || (btif_media_cb.rx_flush)) + { + APPL_TRACE_DEBUG(" State Changed happened in this tick "); + return; + } + + // ignore data if no one is listening + if (!btif_media_cb.data_channel_open) + return; + + APPL_TRACE_DEBUG("Number of sbc frames %d, frame_len %d", num_sbc_frames, sbc_frame_len); + + for(count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++) + { + pcmBytes = availPcmBytes; + status = OI_CODEC_SBC_DecodeFrame(&context, (const OI_BYTE**)&sbc_start_frame, + (OI_UINT32 *)&sbc_frame_len, + (OI_INT16 *)pcmDataPointer, + (OI_UINT32 *)&pcmBytes); + if (!OI_SUCCESS(status)) { + APPL_TRACE_ERROR("Decoding failure: %d\n", status); + break; + } + availPcmBytes -= pcmBytes; + pcmDataPointer += pcmBytes/2; + p_msg->offset += (p_msg->len - 1) - sbc_frame_len; + p_msg->len = sbc_frame_len + 1; + } + + UIPC_Send(UIPC_CH_ID_AV_AUDIO, 0, (UINT8 *)pcmData, (2*sizeof(pcmData) - availPcmBytes)); +} +#endif + +#if (BTA_AV_INCLUDED == TRUE) +/******************************************************************************* + ** + ** Function btif_media_task_enc_init_req + ** + ** Description + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +BOOLEAN btif_media_task_enc_init_req(tBTIF_MEDIA_INIT_AUDIO *p_msg) +{ + tBTIF_MEDIA_INIT_AUDIO *p_buf; + if (NULL == (p_buf = GKI_getbuf(sizeof(tBTIF_MEDIA_INIT_AUDIO)))) + { + return FALSE; + } + + memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_INIT_AUDIO)); + p_buf->hdr.event = BTIF_MEDIA_SBC_ENC_INIT; + + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); + return TRUE; +} + +/******************************************************************************* + ** + ** Function btif_media_task_enc_update_req + ** + ** Description + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +BOOLEAN btif_media_task_enc_update_req(tBTIF_MEDIA_UPDATE_AUDIO *p_msg) +{ + tBTIF_MEDIA_UPDATE_AUDIO *p_buf; + if (NULL == (p_buf = GKI_getbuf(sizeof(tBTIF_MEDIA_UPDATE_AUDIO)))) + { + return FALSE; + } + + memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_UPDATE_AUDIO)); + p_buf->hdr.event = BTIF_MEDIA_SBC_ENC_UPDATE; + + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); + return TRUE; +} + +/******************************************************************************* + ** + ** Function btif_media_task_audio_feeding_init_req + ** + ** Description + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +BOOLEAN btif_media_task_audio_feeding_init_req(tBTIF_MEDIA_INIT_AUDIO_FEEDING *p_msg) +{ + tBTIF_MEDIA_INIT_AUDIO_FEEDING *p_buf; + if (NULL == (p_buf = GKI_getbuf(sizeof(tBTIF_MEDIA_INIT_AUDIO_FEEDING)))) + { + return FALSE; + } + + memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_INIT_AUDIO_FEEDING)); + p_buf->hdr.event = BTIF_MEDIA_AUDIO_FEEDING_INIT; + + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); + return TRUE; +} + +/******************************************************************************* + ** + ** Function btif_media_task_start_aa_req + ** + ** Description + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +BOOLEAN btif_media_task_start_aa_req(void) +{ + BT_HDR *p_buf; + if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR)))) + { + APPL_TRACE_EVENT("GKI failed"); + return FALSE; + } + + p_buf->event = BTIF_MEDIA_START_AA_TX; + + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); + return TRUE; +} + +/******************************************************************************* + ** + ** Function btif_media_task_stop_aa_req + ** + ** Description + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +BOOLEAN btif_media_task_stop_aa_req(void) +{ + BT_HDR *p_buf; + if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR)))) + { + return FALSE; + } + + p_buf->event = BTIF_MEDIA_STOP_AA_TX; + + /* + * Explicitly check whether the btif_media_cmd_msg_queue is not NULL to + * avoid a race condition during shutdown of the Bluetooth stack. + * This race condition is triggered when A2DP audio is streaming on + * shutdown: + * "btif_a2dp_on_stopped() -> btif_media_task_stop_aa_req()" is called + * to stop the particular audio stream, and this happens right after + * the "cleanup() -> btif_a2dp_stop_media_task()" processing during + * the shutdown of the Bluetooth stack. + */ + if (btif_media_cmd_msg_queue != NULL) + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); + + return TRUE; +} +/******************************************************************************* + ** + ** Function btif_media_task_aa_rx_flush_req + ** + ** Description + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +BOOLEAN btif_media_task_aa_rx_flush_req(void) +{ + BT_HDR *p_buf; + + if (GKI_queue_is_empty(&(btif_media_cb.RxSbcQ))== TRUE) /* Que is already empty */ + return TRUE; + + if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR)))) + { + return FALSE; + } + + p_buf->event = BTIF_MEDIA_FLUSH_AA_RX; + + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); + return TRUE; +} + +/******************************************************************************* + ** + ** Function btif_media_task_aa_tx_flush_req + ** + ** Description + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +BOOLEAN btif_media_task_aa_tx_flush_req(void) +{ + BT_HDR *p_buf = GKI_getbuf(sizeof(BT_HDR)); + + if (p_buf == NULL) + return FALSE; + + p_buf->event = BTIF_MEDIA_FLUSH_AA_TX; + + /* + * Explicitly check whether the btif_media_cmd_msg_queue is not NULL to + * avoid a race condition during shutdown of the Bluetooth stack. + * This race condition is triggered when A2DP audio is streaming on + * shutdown: + * "btif_a2dp_on_stopped() -> btif_media_task_aa_tx_flush_req()" is called + * to stop the particular audio stream, and this happens right after + * the "cleanup() -> btif_a2dp_stop_media_task()" processing during + * the shutdown of the Bluetooth stack. + */ + if (btif_media_cmd_msg_queue != NULL) + fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); + + return TRUE; +} +/******************************************************************************* + ** + ** Function btif_media_task_aa_rx_flush + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_aa_rx_flush(void) +{ + /* Flush all enqueued GKI SBC buffers (encoded) */ + APPL_TRACE_DEBUG("btif_media_task_aa_rx_flush"); + + btif_media_flush_q(&(btif_media_cb.RxSbcQ)); +} + + +/******************************************************************************* + ** + ** Function btif_media_task_aa_tx_flush + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_aa_tx_flush(BT_HDR *p_msg) +{ + UNUSED(p_msg); + + /* Flush all enqueued GKI music buffers (encoded) */ + APPL_TRACE_DEBUG("btif_media_task_aa_tx_flush"); + + btif_media_cb.media_feeding_state.pcm.counter = 0; + btif_media_cb.media_feeding_state.pcm.aa_feed_residue = 0; + + btif_media_flush_q(&(btif_media_cb.TxAaQ)); + + UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REQ_RX_FLUSH, NULL); +} + +/******************************************************************************* + ** + ** Function btif_media_task_enc_init + ** + ** Description Initialize encoding task + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_enc_init(BT_HDR *p_msg) +{ + tBTIF_MEDIA_INIT_AUDIO *pInitAudio = (tBTIF_MEDIA_INIT_AUDIO *) p_msg; + + APPL_TRACE_DEBUG("btif_media_task_enc_init"); + + btif_media_cb.timestamp = 0; + + /* SBC encoder config (enforced even if not used) */ + btif_media_cb.encoder.s16ChannelMode = pInitAudio->ChannelMode; + btif_media_cb.encoder.s16NumOfSubBands = pInitAudio->NumOfSubBands; + btif_media_cb.encoder.s16NumOfBlocks = pInitAudio->NumOfBlocks; + btif_media_cb.encoder.s16AllocationMethod = pInitAudio->AllocationMethod; + btif_media_cb.encoder.s16SamplingFreq = pInitAudio->SamplingFreq; + + btif_media_cb.encoder.u16BitRate = btif_media_task_get_sbc_rate(); + + /* Default transcoding is PCM to SBC, modified by feeding configuration */ + btif_media_cb.TxTranscoding = BTIF_MEDIA_TRSCD_PCM_2_SBC; + btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE-BTIF_MEDIA_AA_SBC_OFFSET-sizeof(BT_HDR)) + < pInitAudio->MtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET + - sizeof(BT_HDR)) : pInitAudio->MtuSize; + + APPL_TRACE_EVENT("btif_media_task_enc_init busy %d, mtu %d, peer mtu %d", + btif_media_cb.busy_level, btif_media_cb.TxAaMtuSize, pInitAudio->MtuSize); + APPL_TRACE_EVENT(" ch mode %d, subnd %d, nb blk %d, alloc %d, rate %d, freq %d", + btif_media_cb.encoder.s16ChannelMode, btif_media_cb.encoder.s16NumOfSubBands, + btif_media_cb.encoder.s16NumOfBlocks, + btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate, + btif_media_cb.encoder.s16SamplingFreq); + + /* Reset entirely the SBC encoder */ + SBC_Encoder_Init(&(btif_media_cb.encoder)); + APPL_TRACE_DEBUG("btif_media_task_enc_init bit pool %d", btif_media_cb.encoder.s16BitPool); +} + +/******************************************************************************* + ** + ** Function btif_media_task_enc_update + ** + ** Description Update encoding task + ** + ** Returns void + ** + *******************************************************************************/ + +static void btif_media_task_enc_update(BT_HDR *p_msg) +{ + tBTIF_MEDIA_UPDATE_AUDIO * pUpdateAudio = (tBTIF_MEDIA_UPDATE_AUDIO *) p_msg; + SBC_ENC_PARAMS *pstrEncParams = &btif_media_cb.encoder; + UINT16 s16SamplingFreq; + SINT16 s16BitPool = 0; + SINT16 s16BitRate; + SINT16 s16FrameLen; + UINT8 protect = 0; + + APPL_TRACE_DEBUG("btif_media_task_enc_update : minmtu %d, maxbp %d minbp %d", + pUpdateAudio->MinMtuSize, pUpdateAudio->MaxBitPool, pUpdateAudio->MinBitPool); + + /* Only update the bitrate and MTU size while timer is running to make sure it has been initialized */ + //if (btif_media_cb.is_tx_timer) + { + btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - + BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR)) + < pUpdateAudio->MinMtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET + - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize; + + /* Set the initial target bit rate */ + pstrEncParams->u16BitRate = btif_media_task_get_sbc_rate(); + + if (pstrEncParams->s16SamplingFreq == SBC_sf16000) + s16SamplingFreq = 16000; + else if (pstrEncParams->s16SamplingFreq == SBC_sf32000) + s16SamplingFreq = 32000; + else if (pstrEncParams->s16SamplingFreq == SBC_sf44100) + s16SamplingFreq = 44100; + else + s16SamplingFreq = 48000; + + do + { + if (pstrEncParams->s16NumOfBlocks == 0 || pstrEncParams->s16NumOfSubBands == 0 + || pstrEncParams->s16NumOfChannels == 0) + { + APPL_TRACE_ERROR("btif_media_task_enc_update() - Avoiding division by zero..."); + APPL_TRACE_ERROR("btif_media_task_enc_update() - block=%d, subBands=%d, channels=%d", + pstrEncParams->s16NumOfBlocks, pstrEncParams->s16NumOfSubBands, + pstrEncParams->s16NumOfChannels); + break; + } + + if ((pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) || + (pstrEncParams->s16ChannelMode == SBC_STEREO) ) + { + s16BitPool = (SINT16)( (pstrEncParams->u16BitRate * + pstrEncParams->s16NumOfSubBands * 1000 / s16SamplingFreq) + -( (32 + (4 * pstrEncParams->s16NumOfSubBands * + pstrEncParams->s16NumOfChannels) + + ( (pstrEncParams->s16ChannelMode - 2) * + pstrEncParams->s16NumOfSubBands ) ) + / pstrEncParams->s16NumOfBlocks) ); + + s16FrameLen = 4 + (4*pstrEncParams->s16NumOfSubBands* + pstrEncParams->s16NumOfChannels)/8 + + ( ((pstrEncParams->s16ChannelMode - 2) * + pstrEncParams->s16NumOfSubBands) + + (pstrEncParams->s16NumOfBlocks * s16BitPool) ) / 8; + + s16BitRate = (8 * s16FrameLen * s16SamplingFreq) + / (pstrEncParams->s16NumOfSubBands * + pstrEncParams->s16NumOfBlocks * 1000); + + if (s16BitRate > pstrEncParams->u16BitRate) + s16BitPool--; + + if(pstrEncParams->s16NumOfSubBands == 8) + s16BitPool = (s16BitPool > 255) ? 255 : s16BitPool; + else + s16BitPool = (s16BitPool > 128) ? 128 : s16BitPool; + } + else + { + s16BitPool = (SINT16)( ((pstrEncParams->s16NumOfSubBands * + pstrEncParams->u16BitRate * 1000) + / (s16SamplingFreq * pstrEncParams->s16NumOfChannels)) + -( ( (32 / pstrEncParams->s16NumOfChannels) + + (4 * pstrEncParams->s16NumOfSubBands) ) + / pstrEncParams->s16NumOfBlocks ) ); + + pstrEncParams->s16BitPool = (s16BitPool > + (16 * pstrEncParams->s16NumOfSubBands)) + ? (16*pstrEncParams->s16NumOfSubBands) : s16BitPool; + } + + if (s16BitPool < 0) + { + s16BitPool = 0; + } + + APPL_TRACE_EVENT("bitpool candidate : %d (%d kbps)", + s16BitPool, pstrEncParams->u16BitRate); + + if (s16BitPool > pUpdateAudio->MaxBitPool) + { + APPL_TRACE_DEBUG("btif_media_task_enc_update computed bitpool too large (%d)", + s16BitPool); + /* Decrease bitrate */ + btif_media_cb.encoder.u16BitRate -= BTIF_MEDIA_BITRATE_STEP; + /* Record that we have decreased the bitrate */ + protect |= 1; + } + else if (s16BitPool < pUpdateAudio->MinBitPool) + { + APPL_TRACE_WARNING("btif_media_task_enc_update computed bitpool too small (%d)", s16BitPool); + + /* Increase bitrate */ + UINT16 previous_u16BitRate = btif_media_cb.encoder.u16BitRate; + btif_media_cb.encoder.u16BitRate += BTIF_MEDIA_BITRATE_STEP; + /* Record that we have increased the bitrate */ + protect |= 2; + /* Check over-flow */ + if (btif_media_cb.encoder.u16BitRate < previous_u16BitRate) + protect |= 3; + } + else + { + break; + } + /* In case we have already increased and decreased the bitrate, just stop */ + if (protect == 3) + { + APPL_TRACE_ERROR("btif_media_task_enc_update could not find bitpool in range"); + break; + } + } while (1); + + /* Finally update the bitpool in the encoder structure */ + pstrEncParams->s16BitPool = s16BitPool; + + APPL_TRACE_DEBUG("btif_media_task_enc_update final bit rate %d, final bit pool %d", + btif_media_cb.encoder.u16BitRate, btif_media_cb.encoder.s16BitPool); + + /* make sure we reinitialize encoder with new settings */ + SBC_Encoder_Init(&(btif_media_cb.encoder)); + } +} + +/******************************************************************************* + ** + ** Function btif_media_task_pcm2sbc_init + ** + ** Description Init encoding task for PCM to SBC according to feeding + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_pcm2sbc_init(tBTIF_MEDIA_INIT_AUDIO_FEEDING * p_feeding) +{ + BOOLEAN reconfig_needed = FALSE; + + APPL_TRACE_DEBUG("PCM feeding:"); + APPL_TRACE_DEBUG("sampling_freq:%d", p_feeding->feeding.cfg.pcm.sampling_freq); + APPL_TRACE_DEBUG("num_channel:%d", p_feeding->feeding.cfg.pcm.num_channel); + APPL_TRACE_DEBUG("bit_per_sample:%d", p_feeding->feeding.cfg.pcm.bit_per_sample); + + /* Check the PCM feeding sampling_freq */ + switch (p_feeding->feeding.cfg.pcm.sampling_freq) + { + case 8000: + case 12000: + case 16000: + case 24000: + case 32000: + case 48000: + /* For these sampling_freq the AV connection must be 48000 */ + if (btif_media_cb.encoder.s16SamplingFreq != SBC_sf48000) + { + /* Reconfiguration needed at 48000 */ + APPL_TRACE_DEBUG("SBC Reconfiguration needed at 48000"); + btif_media_cb.encoder.s16SamplingFreq = SBC_sf48000; + reconfig_needed = TRUE; + } + break; + + case 11025: + case 22050: + case 44100: + /* For these sampling_freq the AV connection must be 44100 */ + if (btif_media_cb.encoder.s16SamplingFreq != SBC_sf44100) + { + /* Reconfiguration needed at 44100 */ + APPL_TRACE_DEBUG("SBC Reconfiguration needed at 44100"); + btif_media_cb.encoder.s16SamplingFreq = SBC_sf44100; + reconfig_needed = TRUE; + } + break; + default: + APPL_TRACE_DEBUG("Feeding PCM sampling_freq unsupported"); + break; + } + + /* Some AV Headsets do not support Mono => always ask for Stereo */ + if (btif_media_cb.encoder.s16ChannelMode == SBC_MONO) + { + APPL_TRACE_DEBUG("SBC Reconfiguration needed in Stereo"); + btif_media_cb.encoder.s16ChannelMode = SBC_JOINT_STEREO; + reconfig_needed = TRUE; + } + + if (reconfig_needed != FALSE) + { + APPL_TRACE_DEBUG("btif_media_task_pcm2sbc_init :: mtu %d", btif_media_cb.TxAaMtuSize); + APPL_TRACE_DEBUG("ch mode %d, nbsubd %d, nb %d, alloc %d, rate %d, freq %d", + btif_media_cb.encoder.s16ChannelMode, + btif_media_cb.encoder.s16NumOfSubBands, btif_media_cb.encoder.s16NumOfBlocks, + btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate, + btif_media_cb.encoder.s16SamplingFreq); + + SBC_Encoder_Init(&(btif_media_cb.encoder)); + } + else + { + APPL_TRACE_DEBUG("btif_media_task_pcm2sbc_init no SBC reconfig needed"); + } +} + + +/******************************************************************************* + ** + ** Function btif_media_task_audio_feeding_init + ** + ** Description Initialize the audio path according to the feeding format + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_audio_feeding_init(BT_HDR *p_msg) +{ + tBTIF_MEDIA_INIT_AUDIO_FEEDING *p_feeding = (tBTIF_MEDIA_INIT_AUDIO_FEEDING *) p_msg; + + APPL_TRACE_DEBUG("btif_media_task_audio_feeding_init format:%d", p_feeding->feeding.format); + + /* Save Media Feeding information */ + btif_media_cb.feeding_mode = p_feeding->feeding_mode; + btif_media_cb.media_feeding = p_feeding->feeding; + + /* Handle different feeding formats */ + switch (p_feeding->feeding.format) + { + case BTIF_AV_CODEC_PCM: + btif_media_cb.TxTranscoding = BTIF_MEDIA_TRSCD_PCM_2_SBC; + btif_media_task_pcm2sbc_init(p_feeding); + break; + + default : + APPL_TRACE_ERROR("unknown feeding format %d", p_feeding->feeding.format); + break; + } +} + +int btif_a2dp_get_track_frequency(UINT8 frequency) { + int freq = 48000; + switch (frequency) { + case A2D_SBC_IE_SAMP_FREQ_16: + freq = 16000; + break; + case A2D_SBC_IE_SAMP_FREQ_32: + freq = 32000; + break; + case A2D_SBC_IE_SAMP_FREQ_44: + freq = 44100; + break; + case A2D_SBC_IE_SAMP_FREQ_48: + freq = 48000; + break; + } + return freq; +} + +int btif_a2dp_get_track_channel_count(UINT8 channeltype) { + int count = 1; + switch (channeltype) { + case A2D_SBC_IE_CH_MD_MONO: + count = 1; + break; + case A2D_SBC_IE_CH_MD_DUAL: + case A2D_SBC_IE_CH_MD_STEREO: + case A2D_SBC_IE_CH_MD_JOINT: + count = 2; + break; + } + return count; +} + +void btif_a2dp_set_peer_sep(UINT8 sep) { + btif_media_cb.peer_sep = sep; +} + +static void btif_decode_alarm_cb(UNUSED_ATTR void *context) { +#if 0 + thread_post(worker_thread, btif_media_task_avk_handle_timer, NULL); +#else + btif_media_task_post(SIG_MEDIA_TASK_AVK_ALARM_TO); + // TODO: btif_media_task_avk_handle_timer +#endif +} + +static void btif_media_task_aa_handle_stop_decoding(void) { + osi_alarm_free(btif_media_cb.decode_alarm); + btif_media_cb.decode_alarm = NULL; +} + +static void btif_media_task_aa_handle_start_decoding(void) { + if (btif_media_cb.decode_alarm) + return; + + btif_media_cb.decode_alarm = osi_alarm_new("dec_timer", btif_decode_alarm_cb, NULL, BTIF_SINK_MEDIA_TIME_TICK, true); + if (!btif_media_cb.decode_alarm) { + APPL_TRACE_ERROR("%s unable to allocate decode alarm.", __func__); + return; + } + + osi_alarm_set(btif_media_cb.decode_alarm, BTIF_SINK_MEDIA_TIME_TICK); + // alarm_set_periodic(btif_media_cb.decode_alarm, BTIF_SINK_MEDIA_TIME_TICK, btif_decode_alarm_cb, NULL); +} + +#if (BTA_AV_SINK_INCLUDED == TRUE) + +static void btif_media_task_aa_handle_clear_track (void) +{ + APPL_TRACE_DEBUG("btif_media_task_aa_handle_clear_track"); +} + +/******************************************************************************* + ** + ** Function btif_media_task_aa_handle_decoder_reset + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_aa_handle_decoder_reset(BT_HDR *p_msg) +{ + tBTIF_MEDIA_SINK_CFG_UPDATE *p_buf = (tBTIF_MEDIA_SINK_CFG_UPDATE*) p_msg; + tA2D_STATUS a2d_status; + tA2D_SBC_CIE sbc_cie; + OI_STATUS status; + UINT32 freq_multiple = 48*20; /* frequency multiple for 20ms of data , initialize with 48K*/ + UINT32 num_blocks = 16; + UINT32 num_subbands = 8; + + APPL_TRACE_DEBUG("btif_media_task_aa_handle_decoder_reset p_codec_info[%x:%x:%x:%x:%x:%x]", + p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[3], + p_buf->codec_info[4], p_buf->codec_info[5], p_buf->codec_info[6]); + + a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_buf->codec_info, FALSE); + if (a2d_status != A2D_SUCCESS) + { + APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d", a2d_status); + return; + } + + btif_media_cb.sample_rate = btif_a2dp_get_track_frequency(sbc_cie.samp_freq); + btif_media_cb.channel_count = btif_a2dp_get_track_channel_count(sbc_cie.ch_mode); + + btif_media_cb.rx_flush = FALSE; + APPL_TRACE_DEBUG("Reset to sink role"); + status = OI_CODEC_SBC_DecoderReset(&context, contextData, sizeof(contextData), 2, 2, FALSE); + if (!OI_SUCCESS(status)) { + APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); + } + + UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb); + + switch(sbc_cie.samp_freq) + { + case A2D_SBC_IE_SAMP_FREQ_16: + APPL_TRACE_DEBUG("\tsamp_freq:%d (16000)", sbc_cie.samp_freq); + freq_multiple = 16*20; + break; + case A2D_SBC_IE_SAMP_FREQ_32: + APPL_TRACE_DEBUG("\tsamp_freq:%d (32000)", sbc_cie.samp_freq); + freq_multiple = 32*20; + break; + case A2D_SBC_IE_SAMP_FREQ_44: + APPL_TRACE_DEBUG("\tsamp_freq:%d (44100)", sbc_cie.samp_freq); + freq_multiple = 441*2; + break; + case A2D_SBC_IE_SAMP_FREQ_48: + APPL_TRACE_DEBUG("\tsamp_freq:%d (48000)", sbc_cie.samp_freq); + freq_multiple = 48*20; + break; + default: + APPL_TRACE_DEBUG(" Unknown Frequency "); + break; + } + + switch(sbc_cie.ch_mode) + { + case A2D_SBC_IE_CH_MD_MONO: + APPL_TRACE_DEBUG("\tch_mode:%d (Mono)", sbc_cie.ch_mode); + break; + case A2D_SBC_IE_CH_MD_DUAL: + APPL_TRACE_DEBUG("\tch_mode:%d (DUAL)", sbc_cie.ch_mode); + break; + case A2D_SBC_IE_CH_MD_STEREO: + APPL_TRACE_DEBUG("\tch_mode:%d (STEREO)", sbc_cie.ch_mode); + break; + case A2D_SBC_IE_CH_MD_JOINT: + APPL_TRACE_DEBUG("\tch_mode:%d (JOINT)", sbc_cie.ch_mode); + break; + default: + APPL_TRACE_DEBUG(" Unknown Mode "); + break; + } + + switch(sbc_cie.block_len) + { + case A2D_SBC_IE_BLOCKS_4: + APPL_TRACE_DEBUG("\tblock_len:%d (4)", sbc_cie.block_len); + num_blocks = 4; + break; + case A2D_SBC_IE_BLOCKS_8: + APPL_TRACE_DEBUG("\tblock_len:%d (8)", sbc_cie.block_len); + num_blocks = 8; + break; + case A2D_SBC_IE_BLOCKS_12: + APPL_TRACE_DEBUG("\tblock_len:%d (12)", sbc_cie.block_len); + num_blocks = 12; + break; + case A2D_SBC_IE_BLOCKS_16: + APPL_TRACE_DEBUG("\tblock_len:%d (16)", sbc_cie.block_len); + num_blocks = 16; + break; + default: + APPL_TRACE_DEBUG(" Unknown BlockLen "); + break; + } + + switch(sbc_cie.num_subbands) + { + case A2D_SBC_IE_SUBBAND_4: + APPL_TRACE_DEBUG("\tnum_subbands:%d (4)", sbc_cie.num_subbands); + num_subbands = 4; + break; + case A2D_SBC_IE_SUBBAND_8: + APPL_TRACE_DEBUG("\tnum_subbands:%d (8)", sbc_cie.num_subbands); + num_subbands = 8; + break; + default: + APPL_TRACE_DEBUG(" Unknown SubBands "); + break; + } + + switch(sbc_cie.alloc_mthd) + { + case A2D_SBC_IE_ALLOC_MD_S: + APPL_TRACE_DEBUG("\talloc_mthd:%d (SNR)", sbc_cie.alloc_mthd); + break; + case A2D_SBC_IE_ALLOC_MD_L: + APPL_TRACE_DEBUG("\talloc_mthd:%d (Loudness)", sbc_cie.alloc_mthd); + break; + default: + APPL_TRACE_DEBUG(" Unknown Allocation Method"); + break; + } + + APPL_TRACE_DEBUG("\tBit pool Min:%d Max:%d", sbc_cie.min_bitpool, sbc_cie.max_bitpool); + + btif_media_cb.frames_to_process = ((freq_multiple)/(num_blocks*num_subbands)) + 1; + APPL_TRACE_DEBUG(" Frames to be processed in 20 ms %d",btif_media_cb.frames_to_process); +} +#endif + +/******************************************************************************* + ** + ** Function btif_media_task_feeding_state_reset + ** + ** Description Reset the media feeding state + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_feeding_state_reset(void) +{ + /* By default, just clear the entire state */ + memset(&btif_media_cb.media_feeding_state, 0, sizeof(btif_media_cb.media_feeding_state)); + + if (btif_media_cb.TxTranscoding == BTIF_MEDIA_TRSCD_PCM_2_SBC) + { + btif_media_cb.media_feeding_state.pcm.bytes_per_tick = + (btif_media_cb.media_feeding.cfg.pcm.sampling_freq * + btif_media_cb.media_feeding.cfg.pcm.bit_per_sample / 8 * + btif_media_cb.media_feeding.cfg.pcm.num_channel * + BTIF_MEDIA_TIME_TICK)/1000; + + APPL_TRACE_WARNING("pcm bytes per tick %d", + (int)btif_media_cb.media_feeding_state.pcm.bytes_per_tick); + } +} + +static void btif_media_task_alarm_cb(UNUSED_ATTR void *context) +{ +#if 0 + thread_post(worker_thread, btif_media_task_aa_handle_timer, NULL); +#else + btif_media_task_post(SIG_MEDIA_TASK_AA_ALARM_TO); +#endif +} + +/******************************************************************************* + ** + ** Function btif_media_task_aa_start_tx + ** + ** Description Start media task encoding + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_aa_start_tx(void) +{ + APPL_TRACE_DEBUG("btif_media_task_aa_start_tx is timer %d, feeding mode %d", + btif_media_cb.is_tx_timer, btif_media_cb.feeding_mode); + + /* Use a timer to poll the UIPC, get rid of the UIPC call back */ + // UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REG_CBACK, NULL); + + btif_media_cb.is_tx_timer = TRUE; + last_frame_us = 0; + + /* Reset the media feeding state */ + btif_media_task_feeding_state_reset(); + + APPL_TRACE_EVENT("starting timer %dms", BTIF_MEDIA_TIME_TICK); + + assert(btif_media_cb.media_alarm == NULL); + + btif_media_cb.media_alarm = osi_alarm_new("media_alarm", btif_media_task_alarm_cb, NULL, BTIF_MEDIA_TIME_TICK, true); + if (!btif_media_cb.media_alarm) { + APPL_TRACE_ERROR("%s unable to allocate media alarm.", __func__); + return; + } + + // alarm_set_periodic(btif_media_cb.media_alarm, BTIF_MEDIA_TIME_TICK, btif_media_task_alarm_cb, NULL); + osi_alarm_set(btif_media_cb.media_alarm, BTIF_MEDIA_TIME_TICK); +} + +/******************************************************************************* + ** + ** Function btif_media_task_aa_stop_tx + ** + ** Description Stop media task encoding + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_task_aa_stop_tx(void) +{ + APPL_TRACE_DEBUG("%s is_tx_timer: %d", __func__, btif_media_cb.is_tx_timer); + + const bool send_ack = (btif_media_cb.is_tx_timer != FALSE); + + /* Stop the timer first */ + osi_alarm_free(btif_media_cb.media_alarm); + btif_media_cb.media_alarm = NULL; + btif_media_cb.is_tx_timer = FALSE; + + UIPC_Close(UIPC_CH_ID_AV_AUDIO); + + /* Try to send acknowldegment once the media stream is + stopped. This will make sure that the A2DP HAL layer is + un-blocked on wait for acknowledgment for the sent command. + This resolves a corner cases AVDTP SUSPEND collision + when the DUT and the remote device issue SUSPEND simultaneously + and due to the processing of the SUSPEND request from the remote, + the media path is torn down. If the A2DP HAL happens to wait + for ACK for the initiated SUSPEND, it would never receive it casuing + a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed + to get the ACK for any pending command in such cases. */ + + if (send_ack) + a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS); + + /* audio engine stopped, reset tx suspended flag */ + btif_media_cb.tx_flush = 0; + last_frame_us = 0; + + /* Reset the media feeding state */ + btif_media_task_feeding_state_reset(); +} + +/******************************************************************************* + ** + ** Function btif_get_num_aa_frame + ** + ** Description + ** + ** Returns The number of media frames in this time slice + ** + *******************************************************************************/ +static UINT8 btif_get_num_aa_frame(void) +{ + UINT8 result=0; + + switch (btif_media_cb.TxTranscoding) + { + case BTIF_MEDIA_TRSCD_PCM_2_SBC: + { + UINT32 pcm_bytes_per_frame = btif_media_cb.encoder.s16NumOfSubBands * + btif_media_cb.encoder.s16NumOfBlocks * + btif_media_cb.media_feeding.cfg.pcm.num_channel * + btif_media_cb.media_feeding.cfg.pcm.bit_per_sample / 8; + + UINT32 us_this_tick = BTIF_MEDIA_TIME_TICK * 1000; + UINT64 now_us = time_now_us(); + if (last_frame_us != 0) + us_this_tick = (now_us - last_frame_us); + last_frame_us = now_us; + + btif_media_cb.media_feeding_state.pcm.counter += + btif_media_cb.media_feeding_state.pcm.bytes_per_tick * + us_this_tick / (BTIF_MEDIA_TIME_TICK * 1000); + + /* calculate nbr of frames pending for this media tick */ + result = btif_media_cb.media_feeding_state.pcm.counter/pcm_bytes_per_frame; + if (result > MAX_PCM_FRAME_NUM_PER_TICK) + { + APPL_TRACE_WARNING("%s() - Limiting frames to be sent from %d to %d" + , __FUNCTION__, result, MAX_PCM_FRAME_NUM_PER_TICK); + result = MAX_PCM_FRAME_NUM_PER_TICK; + } + btif_media_cb.media_feeding_state.pcm.counter -= result*pcm_bytes_per_frame; + + LOG_VERBOSE("WRITE %d FRAMES", result); + } + break; + + default: + APPL_TRACE_ERROR("ERROR btif_get_num_aa_frame Unsupported transcoding format 0x%x", + btif_media_cb.TxTranscoding); + result = 0; + break; + } + + return (UINT8)result; +} + +/******************************************************************************* + ** + ** Function btif_media_sink_enque_buf + ** + ** Description This function is called by the av_co to fill A2DP Sink Queue + ** + ** + ** Returns size of the queue + *******************************************************************************/ +UINT8 btif_media_sink_enque_buf(BT_HDR *p_pkt) +{ + tBT_SBC_HDR *p_msg; + + if(btif_media_cb.rx_flush == TRUE) /* Flush enabled, do not enque*/ + return GKI_queue_length(&btif_media_cb.RxSbcQ); + if(GKI_queue_length(&btif_media_cb.RxSbcQ) == MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ) + { + GKI_freebuf(GKI_dequeue(&(btif_media_cb.RxSbcQ))); + } + + BTIF_TRACE_VERBOSE("btif_media_sink_enque_buf + "); + /* allocate and Queue this buffer */ + if ((p_msg = (tBT_SBC_HDR *) GKI_getbuf(sizeof(tBT_SBC_HDR) + + p_pkt->offset+ p_pkt->len)) != NULL) + { + memcpy(p_msg, p_pkt, (sizeof(BT_HDR) + p_pkt->offset + p_pkt->len)); + p_msg->num_frames_to_be_processed = (*((UINT8*)(p_msg + 1) + p_msg->offset)) & 0x0f; + BTIF_TRACE_VERBOSE("btif_media_sink_enque_buf + ", p_msg->num_frames_to_be_processed); + GKI_enqueue(&(btif_media_cb.RxSbcQ), p_msg); + if(GKI_queue_length(&btif_media_cb.RxSbcQ) == MAX_A2DP_DELAYED_START_FRAME_COUNT) + { + BTIF_TRACE_DEBUG(" Initiate Decoding "); + btif_media_task_aa_handle_start_decoding(); + } + } + else + { + /* let caller deal with a failed allocation */ + BTIF_TRACE_VERBOSE("btif_media_sink_enque_buf No Buffer left - "); + } + return GKI_queue_length(&btif_media_cb.RxSbcQ); +} + +/******************************************************************************* + ** + ** Function btif_media_aa_readbuf + ** + ** Description This function is called by the av_co to get the next buffer to send + ** + ** + ** Returns void + *******************************************************************************/ +BT_HDR *btif_media_aa_readbuf(void) +{ + return GKI_dequeue(&(btif_media_cb.TxAaQ)); +} + +/******************************************************************************* + ** + ** Function btif_media_aa_read_feeding + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ + +BOOLEAN btif_media_aa_read_feeding(tUIPC_CH_ID channel_id) +{ + UINT16 event; + UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * \ + btif_media_cb.encoder.s16NumOfBlocks; + UINT32 read_size; + UINT16 sbc_sampling = 48000; + UINT32 src_samples; + UINT16 bytes_needed = blocm_x_subband * btif_media_cb.encoder.s16NumOfChannels * \ + btif_media_cb.media_feeding.cfg.pcm.bit_per_sample / 8; + static UINT16 up_sampled_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS + * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * 2]; + static UINT16 read_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS + * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS]; + UINT32 src_size_used; + UINT32 dst_size_used; + BOOLEAN fract_needed; + INT32 fract_max; + INT32 fract_threshold; + UINT32 nb_byte_read; + + /* Get the SBC sampling rate */ + switch (btif_media_cb.encoder.s16SamplingFreq) + { + case SBC_sf48000: + sbc_sampling = 48000; + break; + case SBC_sf44100: + sbc_sampling = 44100; + break; + case SBC_sf32000: + sbc_sampling = 32000; + break; + case SBC_sf16000: + sbc_sampling = 16000; + break; + } + + if (sbc_sampling == btif_media_cb.media_feeding.cfg.pcm.sampling_freq) { + read_size = bytes_needed - btif_media_cb.media_feeding_state.pcm.aa_feed_residue; + nb_byte_read = UIPC_Read(channel_id, &event, + ((UINT8 *)btif_media_cb.encoder.as16PcmBuffer) + + btif_media_cb.media_feeding_state.pcm.aa_feed_residue, + read_size); + if (nb_byte_read == read_size) { + btif_media_cb.media_feeding_state.pcm.aa_feed_residue = 0; + return TRUE; + } else { + APPL_TRACE_WARNING("### UNDERFLOW :: ONLY READ %d BYTES OUT OF %d ###", + nb_byte_read, read_size); + btif_media_cb.media_feeding_state.pcm.aa_feed_residue += nb_byte_read; + return FALSE; + } + } + + /* Some Feeding PCM frequencies require to split the number of sample */ + /* to read. */ + /* E.g 128/6=21.3333 => read 22 and 21 and 21 => max = 2; threshold = 0*/ + fract_needed = FALSE; /* Default */ + switch (btif_media_cb.media_feeding.cfg.pcm.sampling_freq) + { + case 32000: + case 8000: + fract_needed = TRUE; + fract_max = 2; /* 0, 1 and 2 */ + fract_threshold = 0; /* Add one for the first */ + break; + case 16000: + fract_needed = TRUE; + fract_max = 2; /* 0, 1 and 2 */ + fract_threshold = 1; /* Add one for the first two frames*/ + break; + } + + /* Compute number of sample to read from source */ + src_samples = blocm_x_subband; + src_samples *= btif_media_cb.media_feeding.cfg.pcm.sampling_freq; + src_samples /= sbc_sampling; + + /* The previous division may have a remainder not null */ + if (fract_needed) + { + if (btif_media_cb.media_feeding_state.pcm.aa_feed_counter <= fract_threshold) + { + src_samples++; /* for every read before threshold add one sample */ + } + + /* do nothing if counter >= threshold */ + btif_media_cb.media_feeding_state.pcm.aa_feed_counter++; /* one more read */ + if (btif_media_cb.media_feeding_state.pcm.aa_feed_counter > fract_max) + { + btif_media_cb.media_feeding_state.pcm.aa_feed_counter = 0; + } + } + + /* Compute number of bytes to read from source */ + read_size = src_samples; + read_size *= btif_media_cb.media_feeding.cfg.pcm.num_channel; + read_size *= (btif_media_cb.media_feeding.cfg.pcm.bit_per_sample / 8); + + /* Read Data from UIPC channel */ + nb_byte_read = UIPC_Read(channel_id, &event, (UINT8 *)read_buffer, read_size); + + //tput_mon(TRUE, nb_byte_read, FALSE); + + if (nb_byte_read < read_size) + { + APPL_TRACE_WARNING("### UNDERRUN :: ONLY READ %d BYTES OUT OF %d ###", + nb_byte_read, read_size); + + if (nb_byte_read == 0) + return FALSE; + + if(btif_media_cb.feeding_mode == BTIF_AV_FEEDING_ASYNCHRONOUS) + { + /* Fill the unfilled part of the read buffer with silence (0) */ + memset(((UINT8 *)read_buffer) + nb_byte_read, 0, read_size - nb_byte_read); + nb_byte_read = read_size; + } + } + + /* Initialize PCM up-sampling engine */ + bta_av_sbc_init_up_sample(btif_media_cb.media_feeding.cfg.pcm.sampling_freq, + sbc_sampling, btif_media_cb.media_feeding.cfg.pcm.bit_per_sample, + btif_media_cb.media_feeding.cfg.pcm.num_channel); + + /* re-sample read buffer */ + /* The output PCM buffer will be stereo, 16 bit per sample */ + dst_size_used = bta_av_sbc_up_sample((UINT8 *)read_buffer, + (UINT8 *)up_sampled_buffer + btif_media_cb.media_feeding_state.pcm.aa_feed_residue, + nb_byte_read, + sizeof(up_sampled_buffer) - btif_media_cb.media_feeding_state.pcm.aa_feed_residue, + &src_size_used); + + /* update the residue */ + btif_media_cb.media_feeding_state.pcm.aa_feed_residue += dst_size_used; + + /* only copy the pcm sample when we have up-sampled enough PCM */ + if(btif_media_cb.media_feeding_state.pcm.aa_feed_residue >= bytes_needed) + { + /* Copy the output pcm samples in SBC encoding buffer */ + memcpy((UINT8 *)btif_media_cb.encoder.as16PcmBuffer, + (UINT8 *)up_sampled_buffer, + bytes_needed); + /* update the residue */ + btif_media_cb.media_feeding_state.pcm.aa_feed_residue -= bytes_needed; + + if (btif_media_cb.media_feeding_state.pcm.aa_feed_residue != 0) + { + memcpy((UINT8 *)up_sampled_buffer, + (UINT8 *)up_sampled_buffer + bytes_needed, + btif_media_cb.media_feeding_state.pcm.aa_feed_residue); + } + return TRUE; + } + + return FALSE; +} + +/******************************************************************************* + ** + ** Function btif_media_aa_prep_sbc_2_send + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_aa_prep_sbc_2_send(UINT8 nb_frame) +{ + BT_HDR * p_buf; + UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * + btif_media_cb.encoder.s16NumOfBlocks; + + while (nb_frame) + { + if (NULL == (p_buf = GKI_getpoolbuf(BTIF_MEDIA_AA_POOL_ID))) + { + APPL_TRACE_ERROR ("ERROR btif_media_aa_prep_sbc_2_send no buffer TxCnt %d ", + GKI_queue_length(&btif_media_cb.TxAaQ)); + return; + } + + /* Init buffer */ + p_buf->offset = BTIF_MEDIA_AA_SBC_OFFSET; + p_buf->len = 0; + p_buf->layer_specific = 0; + + do + { + /* Write @ of allocated buffer in encoder.pu8Packet */ + btif_media_cb.encoder.pu8Packet = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len; + /* Fill allocated buffer with 0 */ + memset(btif_media_cb.encoder.as16PcmBuffer, 0, blocm_x_subband + * btif_media_cb.encoder.s16NumOfChannels); + + /* Read PCM data and upsample them if needed */ + if (btif_media_aa_read_feeding(UIPC_CH_ID_AV_AUDIO)) + { + /* SBC encode and descramble frame */ + SBC_Encoder(&(btif_media_cb.encoder)); + A2D_SbcChkFrInit(btif_media_cb.encoder.pu8Packet); + A2D_SbcDescramble(btif_media_cb.encoder.pu8Packet, btif_media_cb.encoder.u16PacketLength); + /* Update SBC frame length */ + p_buf->len += btif_media_cb.encoder.u16PacketLength; + nb_frame--; + p_buf->layer_specific++; + } + else + { + APPL_TRACE_WARNING("btif_media_aa_prep_sbc_2_send underflow %d, %d", + nb_frame, btif_media_cb.media_feeding_state.pcm.aa_feed_residue); + btif_media_cb.media_feeding_state.pcm.counter += nb_frame * + btif_media_cb.encoder.s16NumOfSubBands * + btif_media_cb.encoder.s16NumOfBlocks * + btif_media_cb.media_feeding.cfg.pcm.num_channel * + btif_media_cb.media_feeding.cfg.pcm.bit_per_sample / 8; + /* no more pcm to read */ + nb_frame = 0; + + /* break read loop if timer was stopped (media task stopped) */ + if ( btif_media_cb.is_tx_timer == FALSE ) + { + GKI_freebuf(p_buf); + return; + } + } + + } while (((p_buf->len + btif_media_cb.encoder.u16PacketLength) < btif_media_cb.TxAaMtuSize) + && (p_buf->layer_specific < 0x0F) && nb_frame); + + if(p_buf->len) + { + /* timestamp of the media packet header represent the TS of the first SBC frame + i.e the timestamp before including this frame */ + *((UINT32 *) (p_buf + 1)) = btif_media_cb.timestamp; + + btif_media_cb.timestamp += p_buf->layer_specific * blocm_x_subband; + + if (btif_media_cb.tx_flush) + { + APPL_TRACE_DEBUG("### tx suspended, discarded frame ###"); + + if (GKI_queue_length(&btif_media_cb.TxAaQ) > 0) + btif_media_flush_q(&(btif_media_cb.TxAaQ)); + + GKI_freebuf(p_buf); + return; + } + + /* Enqueue the encoded SBC frame in AA Tx Queue */ + GKI_enqueue(&(btif_media_cb.TxAaQ), p_buf); + } + else + { + GKI_freebuf(p_buf); + } + } +} + + +/******************************************************************************* + ** + ** Function btif_media_aa_prep_2_send + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ + +static void btif_media_aa_prep_2_send(UINT8 nb_frame) +{ + // Check for TX queue overflow + + if (nb_frame > MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ) + nb_frame = MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ; + + if (GKI_queue_length(&btif_media_cb.TxAaQ) > (MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ - nb_frame)) + { + APPL_TRACE_WARNING("%s() - TX queue buffer count %d/%d", __func__, + GKI_queue_length(&btif_media_cb.TxAaQ), MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ - nb_frame); + } + + while (GKI_queue_length(&btif_media_cb.TxAaQ) > (MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ - nb_frame)) + GKI_freebuf(GKI_dequeue(&(btif_media_cb.TxAaQ))); + + // Transcode frame + + switch (btif_media_cb.TxTranscoding) + { + case BTIF_MEDIA_TRSCD_PCM_2_SBC: + btif_media_aa_prep_sbc_2_send(nb_frame); + break; + + default: + APPL_TRACE_ERROR("%s unsupported transcoding format 0x%x", __func__, btif_media_cb.TxTranscoding); + break; + } +} + +/******************************************************************************* + ** + ** Function btif_media_send_aa_frame + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ +static void btif_media_send_aa_frame(void) +{ + UINT8 nb_frame_2_send; + + /* get the number of frame to send */ + nb_frame_2_send = btif_get_num_aa_frame(); + + if (nb_frame_2_send != 0) + { + /* format and Q buffer to send */ + btif_media_aa_prep_2_send(nb_frame_2_send); + } + + /* send it */ + LOG_VERBOSE("btif_media_send_aa_frame : send %d frames", nb_frame_2_send); + bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO); +} + +#endif /* BTA_AV_INCLUDED == TRUE */ + +/******************************************************************************* + ** + ** Function dump_codec_info + ** + ** Description Decode and display codec_info (for debug) + ** + ** Returns void + ** + *******************************************************************************/ +void dump_codec_info(unsigned char *p_codec) +{ + tA2D_STATUS a2d_status; + tA2D_SBC_CIE sbc_cie; + + a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec, FALSE); + if (a2d_status != A2D_SUCCESS) + { + APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d", a2d_status); + return; + } + + APPL_TRACE_DEBUG("dump_codec_info"); + + if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_16) + { APPL_TRACE_DEBUG("\tsamp_freq:%d (16000)", sbc_cie.samp_freq);} + else if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_32) + { APPL_TRACE_DEBUG("\tsamp_freq:%d (32000)", sbc_cie.samp_freq);} + else if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_44) + { APPL_TRACE_DEBUG("\tsamp_freq:%d (44.100)", sbc_cie.samp_freq);} + else if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_48) + { APPL_TRACE_DEBUG("\tsamp_freq:%d (48000)", sbc_cie.samp_freq);} + else + { APPL_TRACE_DEBUG("\tBAD samp_freq:%d", sbc_cie.samp_freq);} + + if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_MONO) + { APPL_TRACE_DEBUG("\tch_mode:%d (Mono)", sbc_cie.ch_mode);} + else if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_DUAL) + { APPL_TRACE_DEBUG("\tch_mode:%d (Dual)", sbc_cie.ch_mode);} + else if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_STEREO) + { APPL_TRACE_DEBUG("\tch_mode:%d (Stereo)", sbc_cie.ch_mode);} + else if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_JOINT) + { APPL_TRACE_DEBUG("\tch_mode:%d (Joint)", sbc_cie.ch_mode);} + else + { APPL_TRACE_DEBUG("\tBAD ch_mode:%d", sbc_cie.ch_mode);} + + if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_4) + { APPL_TRACE_DEBUG("\tblock_len:%d (4)", sbc_cie.block_len);} + else if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_8) + { APPL_TRACE_DEBUG("\tblock_len:%d (8)", sbc_cie.block_len);} + else if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_12) + { APPL_TRACE_DEBUG("\tblock_len:%d (12)", sbc_cie.block_len);} + else if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_16) + { APPL_TRACE_DEBUG("\tblock_len:%d (16)", sbc_cie.block_len);} + else + { APPL_TRACE_DEBUG("\tBAD block_len:%d", sbc_cie.block_len);} + + if (sbc_cie.num_subbands == A2D_SBC_IE_SUBBAND_4) + { APPL_TRACE_DEBUG("\tnum_subbands:%d (4)", sbc_cie.num_subbands);} + else if (sbc_cie.num_subbands == A2D_SBC_IE_SUBBAND_8) + { APPL_TRACE_DEBUG("\tnum_subbands:%d (8)", sbc_cie.num_subbands);} + else + { APPL_TRACE_DEBUG("\tBAD num_subbands:%d", sbc_cie.num_subbands);} + + if (sbc_cie.alloc_mthd == A2D_SBC_IE_ALLOC_MD_S) + { APPL_TRACE_DEBUG("\talloc_mthd:%d (SNR)", sbc_cie.alloc_mthd);} + else if (sbc_cie.alloc_mthd == A2D_SBC_IE_ALLOC_MD_L) + { APPL_TRACE_DEBUG("\talloc_mthd:%d (Loundess)", sbc_cie.alloc_mthd);} + else + { APPL_TRACE_DEBUG("\tBAD alloc_mthd:%d", sbc_cie.alloc_mthd);} + + APPL_TRACE_DEBUG("\tBit pool Min:%d Max:%d", sbc_cie.min_bitpool, sbc_cie.max_bitpool); + +} diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/btif_profile_queue.c b/examples/09_a2dp/components/bluedroid_demos/btif/btif_profile_queue.c new file mode 100755 index 0000000000..02eb33ba64 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/btif_profile_queue.c @@ -0,0 +1,179 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/******************************************************************************* + * + * Filename: btif_profile_queue.c + * + * Description: Bluetooth remote device connection queuing implementation. + * + ******************************************************************************/ + +// #include +#include "bt_trace.h" +#include +// #include +#include "bt_defs.h" +#include + +#define LOG_TAG "bt_btif_queue" +#include "btif_common.h" +#include "btif_profile_queue.h" +#include "gki.h" +#include "list.h" +#include "allocator.h" +#include "stack_manager.h" + +/******************************************************************************* +** Local type definitions +*******************************************************************************/ + +typedef enum { + BTIF_QUEUE_CONNECT_EVT, + BTIF_QUEUE_ADVANCE_EVT, +} btif_queue_event_t; + +typedef struct { + bt_bdaddr_t bda; + uint16_t uuid; + bool busy; + btif_connect_cb_t connect_cb; +} connect_node_t; + +/******************************************************************************* +** Static variables +*******************************************************************************/ + +static list_t *connect_queue; + +static const size_t MAX_REASONABLE_REQUESTS = 10; + +/******************************************************************************* +** Queue helper functions +*******************************************************************************/ + +static void queue_int_add(connect_node_t *p_param) { + if (!connect_queue) { + connect_queue = list_new(osi_free); + assert(connect_queue != NULL); + } + + // Sanity check to make sure we're not leaking connection requests + assert(list_length(connect_queue) < MAX_REASONABLE_REQUESTS); + + for (const list_node_t *node = list_begin(connect_queue); node != list_end(connect_queue); node = list_next(node)) { + if (((connect_node_t *)list_node(node))->uuid == p_param->uuid) { + LOG_INFO("%s dropping duplicate connect request for uuid: %04x", __func__, p_param->uuid); + return; + } + } + + connect_node_t *p_node = osi_malloc(sizeof(connect_node_t)); + assert(p_node != NULL); + memcpy(p_node, p_param, sizeof(connect_node_t)); + list_append(connect_queue, p_node); +} + +static void queue_int_advance() { + if (connect_queue && !list_is_empty(connect_queue)) + list_remove(connect_queue, list_front(connect_queue)); +} + +static void queue_int_handle_evt(UINT16 event, char *p_param) { + switch(event) { + case BTIF_QUEUE_CONNECT_EVT: + queue_int_add((connect_node_t *)p_param); + break; + + case BTIF_QUEUE_ADVANCE_EVT: + queue_int_advance(); + break; + } + + // if (stack_manager_get_interface()->get_stack_is_running()) + if (stack_manager_is_stack_running()) + btif_queue_connect_next(); +} + +/******************************************************************************* +** +** Function btif_queue_connect +** +** Description Add a new connection to the queue and trigger the next +** scheduled connection. +** +** Returns BT_STATUS_SUCCESS if successful +** +*******************************************************************************/ +bt_status_t btif_queue_connect(uint16_t uuid, const bt_bdaddr_t *bda, btif_connect_cb_t connect_cb) { + connect_node_t node; + memset(&node, 0, sizeof(connect_node_t)); + memcpy(&node.bda, bda, sizeof(bt_bdaddr_t)); + node.uuid = uuid; + node.connect_cb = connect_cb; + + return btif_transfer_context(queue_int_handle_evt, BTIF_QUEUE_CONNECT_EVT, + (char *)&node, sizeof(connect_node_t), NULL); +} + +/******************************************************************************* +** +** Function btif_queue_advance +** +** Description Clear the queue's busy status and advance to the next +** scheduled connection. +** +** Returns void +** +*******************************************************************************/ +void btif_queue_advance() { + btif_transfer_context(queue_int_handle_evt, BTIF_QUEUE_ADVANCE_EVT, + NULL, 0, NULL); +} + +// This function dispatches the next pending connect request. It is called from +// stack_manager when the stack comes up. +bt_status_t btif_queue_connect_next(void) { + if (!connect_queue || list_is_empty(connect_queue)) + return BT_STATUS_FAIL; + + connect_node_t *p_head = list_front(connect_queue); + + // If the queue is currently busy, we return success anyway, + // since the connection has been queued... + if (p_head->busy) + return BT_STATUS_SUCCESS; + + p_head->busy = true; + return p_head->connect_cb(&p_head->bda, p_head->uuid); +} + + +/******************************************************************************* +** +** Function btif_queue_release +** +** Description Free up all the queue nodes and set the queue head to NULL +** +** Returns void +** +*******************************************************************************/ +void btif_queue_release() { + list_free(connect_queue); + connect_queue = NULL; +} diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/btif_sdp.c b/examples/09_a2dp/components/bluedroid_demos/btif/btif_sdp.c new file mode 100755 index 0000000000..d77f61869a --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/btif_sdp.c @@ -0,0 +1,175 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Samsung System LSI + * + * 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. + * + ******************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_sdp.c + * Description: SDP Bluetooth Interface. + * Implements the generic message handling and search functionality. + * References btif_sdp_server.c for SDP record creation. + * + ***********************************************************************************/ + +#include "btif_sdp.h" +#include +#include + +#define LOG_TAG "BTIF_SDP" +#include "btif_common.h" +#include "btif_util.h" +#include "bta_api.h" + +#include "bt_sdp_api.h" + +/***************************************************************************** +** Functions implemented in sdp_server.c +******************************************************************************/ +bt_status_t sdp_server_init(); +void sdp_server_cleanup(); +void on_create_record_event(int handle); +void on_remove_record_event(int handle); + +// Utility functions: +int get_sdp_records_size(bluetooth_sdp_record* in_record, int count); +void copy_sdp_records(bluetooth_sdp_record* in_records, + bluetooth_sdp_record* out_records, int count); + + +/***************************************************************************** +** Static variables +******************************************************************************/ + +static btsdp_callbacks_t *bt_sdp_callbacks = NULL; + +static void btif_sdp_search_comp_evt(UINT16 event, char *p_param) +{ + bt_sdp_search_comp_t *evt_data = (bt_sdp_search_comp_t *) p_param; + bt_bdaddr_t addr; + BTIF_TRACE_DEBUG("%s: event = %d\n", __FUNCTION__, event); + + if (event != BT_SDP_SEARCH_COMP_EVT) + return; + + bdcpy(addr.address, evt_data->remote_addr); + + HAL_CBACK(bt_sdp_callbacks, sdp_search_cb, evt_data->status, + &addr, (uint8_t*)(evt_data->uuid.uu.uuid128), + evt_data->record_count, evt_data->records); +} + +static void sdp_search_comp_copy_cb(UINT16 event, char *p_dest, char *p_src) +{ + bt_sdp_search_comp_t *p_dest_data = (bt_sdp_search_comp_t *) p_dest; + bt_sdp_search_comp_t *p_src_data = (bt_sdp_search_comp_t *) p_src; + if (!p_src) + return; + + if (event != BT_SDP_SEARCH_COMP_EVT) + return; + + memcpy(p_dest_data, p_src_data, sizeof(bt_sdp_search_comp_t)); + + copy_sdp_records(p_src_data->records, p_dest_data->records, p_src_data->record_count); +} + + +static void sdp_dm_cback(bt_sdp_evt_t event, bt_sdp_t *p_data, void * user_data) +{ + switch (event) + { + case BT_SDP_SEARCH_COMP_EVT: + { + int size = sizeof(bt_sdp_t); + size += get_sdp_records_size(p_data->sdp_search_comp.records, + p_data->sdp_search_comp.record_count); + + BTIF_TRACE_DEBUG("%s: stat %d, record_cnt = %d\n", __FUNCTION__, p_data->sdp_search_comp.status, p_data->sdp_search_comp.record_count); + /* need to deep copy the record content */ + btif_transfer_context(btif_sdp_search_comp_evt, event, + (char*)p_data, size, sdp_search_comp_copy_cb); + break; + } + case BT_SDP_CREATE_RECORD_USER_EVT: + { + on_create_record_event((int)user_data); + break; + } + case BT_SDP_REMOVE_RECORD_USER_EVT: + { + on_remove_record_event((int)user_data); + break; + } + default: + break; + } +} + +bt_status_t BTIF_SdpInit(btsdp_callbacks_t *callbacks) +{ + BTIF_TRACE_DEBUG("Sdp Search %s\n", __FUNCTION__); + + bt_sdp_callbacks = callbacks; + sdp_server_init(); + + btif_enable_service(BTA_SDP_SERVICE_ID); + + return BT_STATUS_SUCCESS; +} + +bt_status_t BTIF_SdpDeinit(void) +{ + BTIF_TRACE_DEBUG("Sdp Search %s\n", __FUNCTION__); + + bt_sdp_callbacks = NULL; + sdp_server_cleanup(); + btif_disable_service(BTA_SDP_SERVICE_ID); + + return BT_STATUS_SUCCESS; +} + +bt_status_t BTIF_SdpSearch(bt_bdaddr_t *bd_addr, const uint8_t* uuid) +{ + esp_bt_uuid_t sdp_uuid; + sdp_uuid.len = 16; + memcpy(sdp_uuid.uu.uuid128, uuid, sizeof(sdp_uuid.uu.uuid128)); + + esp_bt_sdp_search(bd_addr->address, &sdp_uuid); + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btif_sdp_execute_service +** +** Description Initializes/Shuts down the service +** +** Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btif_sdp_execute_service(BOOLEAN b_enable) +{ + BTIF_TRACE_DEBUG("%s enable:%d\n", __FUNCTION__, b_enable); + + if (b_enable) { + esp_bt_sdp_enable(sdp_dm_cback); + } else { + /* This is called on BT disable so no need to extra cleanup */ + } + return BT_STATUS_SUCCESS; +} + diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/btif_sdp_server.c b/examples/09_a2dp/components/bluedroid_demos/btif/btif_sdp_server.c new file mode 100755 index 0000000000..ebb3f8422f --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/btif_sdp_server.c @@ -0,0 +1,777 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Samsung System LSI + * + * 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. + * + ******************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_sdp_server.c + * Description: SDP server Bluetooth Interface to create and remove SDP records. + * To be used in combination with the RFCOMM/L2CAP(LE) sockets. + * + * + ***********************************************************************************/ + +#include "btif_sdp.h" +#include +#include +#define LOG_TAG "BTIF_SDP_SERVER" +#include "allocator.h" +#include "btif_common.h" +#include "bta_sys.h" +#include "utl.h" +#include "bt_sdp_api.h" + +static pthread_mutex_t sdp_lock; + +/** + * The need for a state variable have been reduced to two states. + * The remaining state control is handled by program flow + */ +typedef enum { + SDP_RECORD_FREE = 0, + SDP_RECORD_ALLOCED, +} sdp_state_t; + +typedef struct { + sdp_state_t state; + int sdp_handle; + bluetooth_sdp_record* record_data; +} sdp_slot_t; + +#define MAX_SDP_SLOTS 128 +static sdp_slot_t sdp_slots[MAX_SDP_SLOTS]; + +/***************************************************************************** + * LOCAL Functions + *****************************************************************************/ +static int add_maps_sdp(const bluetooth_sdp_mas_record* rec); +static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec); +static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec); +static int add_opps_sdp(const bluetooth_sdp_ops_record* rec); +static int add_saps_sdp(const bluetooth_sdp_sap_record* rec); +bt_status_t remove_sdp_record(int record_id); +static int free_sdp_slot(int id); + +/****************************************************************************** + * WARNING: Functions below are not called in BTU context. + * Introduced to make it possible to create SDP records from JAVA with both a + * RFCOMM channel and a L2CAP PSM. + * Overall architecture: + * 1) JAVA calls createRecord() which returns a pseudo ID which at a later + * point will be linked to a specific SDP handle. + * 2) createRecord() requests the BTU task(thread) to call a callback in SDP + * which creates the actual record, and updates the ID<->SDPHandle map + * based on the ID beeing passed to BTA as user_data. + *****************************************************************************/ + +static void init_sdp_slots() +{ + int i; + memset(sdp_slots, 0, sizeof(sdp_slot_t)*MAX_SDP_SLOTS); + /* if SDP_RECORD_FREE is zero - no need to set the value */ + if(SDP_RECORD_FREE != 0) { + for(i = 0; i < MAX_SDP_SLOTS; i++) + { + sdp_slots[i].state = SDP_RECORD_FREE; + } + } +} + +bt_status_t sdp_server_init() +{ + BTIF_TRACE_DEBUG("Sdp Server %s\n", __FUNCTION__); + pthread_mutex_init(&sdp_lock, NULL); + init_sdp_slots(); + return BT_STATUS_SUCCESS; +} + +void sdp_server_cleanup() +{ + BTIF_TRACE_DEBUG("Sdp Server %s\n", __FUNCTION__); + pthread_mutex_lock(&sdp_lock); + int i; + for(i = 0; i < MAX_SDP_SLOTS; i++) + { + /*remove_sdp_record(i); we cannot send messages to the other threads, since they might + * have been shut down already. Just do local cleanup. + */ + free_sdp_slot(i); + } + pthread_mutex_unlock(&sdp_lock); + pthread_mutex_destroy(&sdp_lock); +} + +int get_sdp_records_size(bluetooth_sdp_record* in_record, int count) { + bluetooth_sdp_record* record = in_record; + int records_size = 0; + int i; + for(i=0; ihdr.service_name_length; + if(record->hdr.service_name_length > 0){ + records_size++; /* + '\0' termination of string */ + } + records_size += record->hdr.user1_ptr_len; + records_size += record->hdr.user2_ptr_len; + } + return records_size; +} + +/* Deep copy all content of in_records into out_records. + * out_records must point to a chunk of memory large enough to contain all + * the data. Use getSdpRecordsSize() to calculate the needed size. */ +void copy_sdp_records(bluetooth_sdp_record* in_records, + bluetooth_sdp_record* out_records, int count) { + int i; + bluetooth_sdp_record* in_record; + bluetooth_sdp_record* out_record; + char* free_ptr = (char*)(&out_records[count]); /* set pointer to after the last entry */ + + for(i=0; ihdr.service_name == NULL || in_record->hdr.service_name_length == 0) { + out_record->hdr.service_name = NULL; + out_record->hdr.service_name_length = 0; + } else { + out_record->hdr.service_name = free_ptr; // Update service_name pointer + // Copy string + memcpy(free_ptr, in_record->hdr.service_name, in_record->hdr.service_name_length); + free_ptr += in_record->hdr.service_name_length; + *(free_ptr) = '\0'; // Set '\0' termination of string + free_ptr++; + } + if(in_record->hdr.user1_ptr != NULL) { + out_record->hdr.user1_ptr = (UINT8*)free_ptr; // Update pointer + memcpy(free_ptr, in_record->hdr.user1_ptr, in_record->hdr.user1_ptr_len); // Copy content + free_ptr += in_record->hdr.user1_ptr_len; + } + if(in_record->hdr.user2_ptr != NULL) { + out_record->hdr.user2_ptr = (UINT8*)free_ptr; // Update pointer + memcpy(free_ptr, in_record->hdr.user2_ptr, in_record->hdr.user2_ptr_len); // Copy content + free_ptr += in_record->hdr.user2_ptr_len; + } + } + return; +} + +/* Reserve a slot in sdp_slots, copy data and set a reference to the copy. + * The record_data will contain both the record and any data pointed to by + * the record. + * Currently this covers: + * service_name string, + * user1_ptr and + * user2_ptr. */ +static int alloc_sdp_slot(bluetooth_sdp_record* in_record) { + int i; + int record_size = get_sdp_records_size(in_record, 1); + bluetooth_sdp_record* record = osi_malloc(record_size); + + copy_sdp_records(in_record, record, 1); + + /* We are optimists here, and preallocate the record. + * This is to reduce the time we hold the sdp_lock. */ + pthread_mutex_lock(&sdp_lock); + for(i = 0; i < MAX_SDP_SLOTS; i++) + { + if(sdp_slots[i].state == SDP_RECORD_FREE) { + sdp_slots[i].state = SDP_RECORD_ALLOCED; + sdp_slots[i].record_data = record; + break; + } + } + pthread_mutex_unlock(&sdp_lock); + if(i >= MAX_SDP_SLOTS) { + APPL_TRACE_ERROR("%s() failed - no more free slots!\n", __func__); + /* Rearly the optimist is too optimistic, and cleanup is needed...*/ + osi_free(record); + return -1; + } + return i; +} + +static int free_sdp_slot(int id) { + int handle = -1; + bluetooth_sdp_record* record = NULL; + if(id >= MAX_SDP_SLOTS) { + APPL_TRACE_ERROR("%s() failed - id %d is invalid\n", __func__, id); + return handle; + } + pthread_mutex_lock(&sdp_lock); + handle = sdp_slots[id].sdp_handle; + sdp_slots[id].sdp_handle = 0; + if(sdp_slots[id].state != SDP_RECORD_FREE) + { + /* safe a copy of the pointer, and free after unlock() */ + record = sdp_slots[id].record_data; + } + sdp_slots[id].state = SDP_RECORD_FREE; + pthread_mutex_unlock(&sdp_lock); + + if(record != NULL) { + osi_free(record); + } else { + // Record have already been freed + handle = -1; + } + return handle; +} + +/*** + * Use this to get a reference to a SDP slot AND change the state to + * SDP_RECORD_CREATE_INITIATED. + */ +static const sdp_slot_t* start_create_sdp(int id) { + sdp_slot_t* sdp_slot; + if(id >= MAX_SDP_SLOTS) { + APPL_TRACE_ERROR("%s() failed - id %d is invalid\n", __func__, id); + return NULL; + } + pthread_mutex_lock(&sdp_lock); + if(sdp_slots[id].state == SDP_RECORD_ALLOCED) { + sdp_slot = &(sdp_slots[id]); + } else { + /* The record have been removed before this event occurred - e.g. deinit */ + sdp_slot = NULL; + } + pthread_mutex_unlock(&sdp_lock); + if(sdp_slot == NULL) { + APPL_TRACE_ERROR("%s() failed - state for id %d is \n" + "sdp_slots[id].state = %d expected %d\n", __func__, + id, sdp_slots[id].state, SDP_RECORD_ALLOCED); + } + return sdp_slot; +} + +static void set_sdp_handle(int id, int handle) { + pthread_mutex_lock(&sdp_lock); + sdp_slots[id].sdp_handle = handle; + pthread_mutex_unlock(&sdp_lock); + BTIF_TRACE_DEBUG("%s() id=%d to handle=0x%08x\n", __FUNCTION__, id, handle); +} + +bt_status_t BTIF_SdpCreateRecord(bluetooth_sdp_record *record, int* record_handle) { + int handle; + + handle = alloc_sdp_slot(record); + BTIF_TRACE_DEBUG("%s() handle = 0x%08x\n", __FUNCTION__, handle); + + if(handle < 0) + return BT_STATUS_FAIL; + + esp_bt_sdp_create_record_by_user((void*) handle); + + *record_handle = handle; + + return BT_STATUS_SUCCESS; +} + +bt_status_t BTIF_SdpRemoveRecord(int record_handle) { + int handle; + + /* Get the Record handle, and free the slot */ + handle = free_sdp_slot(record_handle); + BTIF_TRACE_DEBUG("Sdp Server %s id=%d to handle=0x%08x\n", + __FUNCTION__, record_handle, handle); + + /* Pass the actual record handle */ + if(handle > 0) { + esp_bt_sdp_remove_record_by_user((void *)handle); + return BT_STATUS_SUCCESS; + } + BTIF_TRACE_DEBUG("Sdp Server %s - record already removed - or never created\n", __FUNCTION__); + return BT_STATUS_FAIL; +} + + +/****************************************************************************** + * CALLBACK FUNCTIONS + * Called in BTA context to create/remove SDP records. + ******************************************************************************/ + +void on_create_record_event(int id) { + /* + * 1) Fetch the record pointer, and change its state? + * 2) switch on the type to create the correct record + * 3) Update state on completion + * 4) What to do at fail? + * */ + BTIF_TRACE_DEBUG("Sdp Server %s\n", __FUNCTION__); + const sdp_slot_t* sdp_slot = start_create_sdp(id); + /* In the case we are shutting down, sdp_slot is NULL */ + if(sdp_slot != NULL) { + bluetooth_sdp_record* record = sdp_slot->record_data; + int handle = -1; + switch(record->hdr.type) { + case SDP_TYPE_MAP_MAS: + handle = add_maps_sdp(&record->mas); + break; + case SDP_TYPE_MAP_MNS: + handle = add_mapc_sdp(&record->mns); + break; + case SDP_TYPE_PBAP_PSE: + handle = add_pbaps_sdp(&record->pse); + break; + case SDP_TYPE_OPP_SERVER: + handle = add_opps_sdp(&record->ops); + break; + case SDP_TYPE_SAP_SERVER: + handle = add_saps_sdp(&record->sap); + break; + case SDP_TYPE_PBAP_PCE: + // break; not yet supported + default: + BTIF_TRACE_DEBUG("Record type %d is not supported\n",record->hdr.type); + break; + } + if(handle != -1) { + set_sdp_handle(id, handle); + } + } +} + +void on_remove_record_event(int handle) { + BTIF_TRACE_DEBUG("Sdp Server %s\n", __FUNCTION__); + + // User data carries the actual SDP handle, not the ID. + if(handle != -1 && handle != 0) { + BOOLEAN result; + result = SDP_DeleteRecord( handle ); + if(result == FALSE) { + BTIF_TRACE_ERROR(" Unable to remove handle 0x%08x\n", handle); + } + } +} + +/**** + * Below the actual functions accessing BTA context data - hence only call from BTA context! + */ + +/* Create a MAP MAS SDP record based on information stored in a bluetooth_sdp_mas_record */ +static int add_maps_sdp(const bluetooth_sdp_mas_record* rec) +{ + + sdp_proto_elem_t protoList[3]; + UINT16 service = UUID_SERVCLASS_MESSAGE_ACCESS; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + BOOLEAN status = TRUE; + UINT32 sdp_handle = 0; + UINT8 temp[4]; + UINT8* p_temp = temp; + + APPL_TRACE_DEBUG("%s(): MASID = 0x%02x, scn 0x%02x, psm = 0x%04x\n service name %s\n", __func__, + rec->mas_instance_id, rec->hdr.rfcomm_channel_number, + rec->hdr.l2cap_psm, rec->hdr.service_name); + + APPL_TRACE_DEBUG(" msg_types: 0x%02x, feature_bits: 0x%08x\n", + rec->supported_message_types, rec->supported_features); + + if ((sdp_handle = esp_bt_sdp_create_record()) == 0) + { + APPL_TRACE_ERROR("%s() - Unable to register MAPS Service\n", __func__); + return sdp_handle; + } + + /* add service class */ + status &= esp_bt_sdp_add_service_class_id_list(sdp_handle, 1, &service); + memset( protoList, 0 , 3*sizeof(sdp_proto_elem_t) ); + + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + status &= esp_bt_sdp_add_protocol_list(sdp_handle, 3, protoList); + + /* Add a name entry */ + status &= esp_bt_sdp_add_attribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + status &= esp_bt_sdp_add_profile_dscp_list(sdp_handle, + UUID_SERVCLASS_MAP_PROFILE, + rec->hdr.profile_version); + + /* Add MAS instance ID */ + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE, + (UINT32)1, (UINT8*)&rec->mas_instance_id); + + /* Add supported message types */ + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE, + (UINT32)1, (UINT8*)&rec->supported_message_types); + + /* Add supported feature */ + UINT32_TO_BE_STREAM(p_temp, rec->supported_features); + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES, + UINT_DESC_TYPE, (UINT32)4, temp); + + /* Add the L2CAP PSM if present */ + if(rec->hdr.l2cap_psm != -1) { + p_temp = temp;// The macro modifies p_temp, hence rewind. + UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm); + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, + UINT_DESC_TYPE, (UINT32)2, temp); + } + + /* Make the service browseable */ + status &= esp_bt_sdp_add_uuid_sequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) + { + esp_bt_sdp_delete_record(sdp_handle); + sdp_handle = 0; + APPL_TRACE_ERROR("%s() FAILED\n", __func__); + } + else + { + bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */ + APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)\n", __func__, sdp_handle); + } + return sdp_handle; +} + + +/* Create a MAP MNS SDP record based on information stored in a bluetooth_sdp_mns_record */ +static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec) +{ + + sdp_proto_elem_t protoList [3]; + UINT16 service = UUID_SERVCLASS_MESSAGE_NOTIFICATION; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + BOOLEAN status = TRUE; + UINT32 sdp_handle = 0; + UINT8 temp[4]; + UINT8* p_temp = temp; + + APPL_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s\n", __func__, + rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name); + + APPL_TRACE_DEBUG(" feature_bits: 0x%08x\n", rec->supported_features); + + if ((sdp_handle = esp_bt_sdp_create_record()) == 0) + { + APPL_TRACE_ERROR("%s(): Unable to register MAP Notification Service\n", __func__); + return sdp_handle; + } + + /* add service class */ + status &= esp_bt_sdp_add_service_class_id_list(sdp_handle, 1, &service); + memset( protoList, 0 , 3*sizeof(sdp_proto_elem_t) ); + + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + status &= esp_bt_sdp_add_protocol_list(sdp_handle, 3, protoList); + + /* Add a name entry */ + status &= esp_bt_sdp_add_attribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + status &= esp_bt_sdp_add_profile_dscp_list(sdp_handle, + UUID_SERVCLASS_MAP_PROFILE, + rec->hdr.profile_version); + + /* Add supported feature */ + UINT32_TO_BE_STREAM(p_temp, rec->supported_features); + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES, + UINT_DESC_TYPE, (UINT32)4, temp); + + /* Add the L2CAP PSM if present */ + if(rec->hdr.l2cap_psm != -1) { + p_temp = temp;// The macro modifies p_temp, hence rewind. + UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm); + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, + UINT_DESC_TYPE, (UINT32)2, temp); + } + + /* Make the service browseable */ + status &= esp_bt_sdp_add_uuid_sequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) + { + esp_bt_sdp_delete_record(sdp_handle); + sdp_handle = 0; + APPL_TRACE_ERROR("%s() FAILED\n", __func__); + } + else + { + bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */ + APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)\n", __func__, sdp_handle); + } + return sdp_handle; +} + +/* Create a PBAP Server SDP record based on information stored in a bluetooth_sdp_pse_record */ +static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec) +{ + + sdp_proto_elem_t protoList [3]; + UINT16 service = UUID_SERVCLASS_PBAP_PSE; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + BOOLEAN status = TRUE; + UINT32 sdp_handle = 0; + UINT8 temp[4]; + UINT8* p_temp = temp; + + APPL_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s\n", __func__, + rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name); + + APPL_TRACE_DEBUG(" supported_repositories: 0x%08x, feature_bits: 0x%08x\n", + rec->supported_repositories, rec->supported_features); + + if ((sdp_handle = esp_bt_sdp_create_record()) == 0) + { + APPL_TRACE_ERROR("%s(): Unable to register PBAP Server Service\n", __func__); + return sdp_handle; + } + + /* add service class */ + status &= esp_bt_sdp_add_service_class_id_list(sdp_handle, 1, &service); + memset( protoList, 0 , 3*sizeof(sdp_proto_elem_t) ); + + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + status &= esp_bt_sdp_add_protocol_list(sdp_handle, 3, protoList); + + /* Add a name entry */ + status &= esp_bt_sdp_add_attribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + status &= esp_bt_sdp_add_profile_dscp_list(sdp_handle, + UUID_SERVCLASS_PHONE_ACCESS, + rec->hdr.profile_version); + + /* Add supported repositories 1 byte */ + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, + UINT_DESC_TYPE, (UINT32)1, (UINT8*)&rec->supported_repositories); + + /* Add supported feature 4 bytes*/ + UINT32_TO_BE_STREAM(p_temp, rec->supported_features); + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES, + UINT_DESC_TYPE, (UINT32)4, temp); + + /* Add the L2CAP PSM if present */ + if(rec->hdr.l2cap_psm != -1) { + p_temp = temp;// The macro modifies p_temp, hence rewind. + UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm); + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, + UINT_DESC_TYPE, (UINT32)2, temp); + } + + /* Make the service browseable */ + status &= esp_bt_sdp_add_uuid_sequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) + { + esp_bt_sdp_delete_record(sdp_handle); + sdp_handle = 0; + APPL_TRACE_ERROR("%s() FAILED\n", __func__); + } + else + { + bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */ + APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)\n", __func__, sdp_handle); + } + return sdp_handle; +} + + +/* Create a OPP Server SDP record based on information stored in a bluetooth_sdp_ops_record */ +static int add_opps_sdp(const bluetooth_sdp_ops_record* rec) +{ + + sdp_proto_elem_t protoList [3]; + UINT16 service = UUID_SERVCLASS_OBEX_OBJECT_PUSH; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + UINT8 type_len[rec->supported_formats_list_len]; + UINT8 desc_type[rec->supported_formats_list_len]; + UINT8 *type_value[rec->supported_formats_list_len]; + BOOLEAN status = TRUE; + UINT32 sdp_handle = 0; + UINT8 temp[4]; + UINT8* p_temp = temp; + tBTA_UTL_COD cod; + int i,j; + + APPL_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s\n", __func__, + rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name); + + APPL_TRACE_DEBUG(" supported formats count: %d\n", + rec->supported_formats_list_len); + + if ((sdp_handle = esp_bt_sdp_create_record()) == 0) + { + APPL_TRACE_ERROR("%s(): Unable to register Object Push Server Service\n", __func__); + return sdp_handle; + } + + /* add service class */ + status &= esp_bt_sdp_add_service_class_id_list(sdp_handle, 1, &service); + memset( protoList, 0 , 3*sizeof(sdp_proto_elem_t) ); + + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + status &= esp_bt_sdp_add_protocol_list(sdp_handle, 3, protoList); + + /* Add a name entry */ + status &= esp_bt_sdp_add_attribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + status &= esp_bt_sdp_add_profile_dscp_list(sdp_handle, + UUID_SERVCLASS_OBEX_OBJECT_PUSH, + rec->hdr.profile_version); + + /* add sequence for supported types */ + for (i = 0, j = 0; i < rec->supported_formats_list_len; i++) + { + type_value[j] = (UINT8 *) &rec->supported_formats_list[i]; + desc_type[j] = UINT_DESC_TYPE; + type_len[j++] = 1; + } + + status &= esp_bt_sdp_add_sequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST, + (UINT8) rec->supported_formats_list_len, desc_type, type_len, type_value); + + /* Add the L2CAP PSM if present */ + if(rec->hdr.l2cap_psm != -1) { + p_temp = temp;// The macro modifies p_temp, hence rewind. + UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm); + status &= esp_bt_sdp_add_attribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, + UINT_DESC_TYPE, (UINT32)2, temp); + } + + /* Make the service browseable */ + status &= esp_bt_sdp_add_uuid_sequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) + { + esp_bt_sdp_delete_record(sdp_handle); + sdp_handle = 0; + APPL_TRACE_ERROR("%s() FAILED\n", __func__); + } + else + { + /* set class of device */ + cod.service = BTM_COD_SERVICE_OBJ_TRANSFER; + utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); + + bta_sys_add_uuid(service); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */ + APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)\n", __func__, sdp_handle); + } + return sdp_handle; +} + +// Create a Sim Access Profile SDP record based on information stored in a bluetooth_sdp_sap_record. +static int add_saps_sdp(const bluetooth_sdp_sap_record* rec) +{ + sdp_proto_elem_t protoList [2]; + UINT16 services[2]; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + BOOLEAN status = TRUE; + UINT32 sdp_handle = 0; + + APPL_TRACE_DEBUG("%s(): scn 0x%02x, service name %s\n", __func__, + rec->hdr.rfcomm_channel_number, rec->hdr.service_name); + + if ((sdp_handle = esp_bt_sdp_create_record()) == 0) + { + APPL_TRACE_ERROR("%s(): Unable to register SAPS Service\n", __func__); + return sdp_handle; + } + + services[0] = UUID_SERVCLASS_SAP; + services[1] = UUID_SERVCLASS_GENERIC_TELEPHONY; + + // add service class + status &= esp_bt_sdp_add_service_class_id_list(sdp_handle, 2, services); + memset(protoList, 0, 2 * sizeof(sdp_proto_elem_t)); + + // add protocol list, including RFCOMM scn + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + status &= esp_bt_sdp_add_protocol_list(sdp_handle, 2, protoList); + + // Add a name entry + status &= esp_bt_sdp_add_attribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + // Add in the Bluetooth Profile Descriptor List + status &= esp_bt_sdp_add_profile_dscp_list(sdp_handle, + UUID_SERVCLASS_SAP, + rec->hdr.profile_version); + + // Make the service browseable + status &= esp_bt_sdp_add_uuid_sequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) + { + esp_bt_sdp_delete_record(sdp_handle); + sdp_handle = 0; + APPL_TRACE_ERROR("%s(): FAILED deleting record\n", __func__); + } + else + { + bta_sys_add_uuid(UUID_SERVCLASS_SAP); + APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)\n", __func__, sdp_handle); + } + return sdp_handle; +} + diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/btif_sm.c b/examples/09_a2dp/components/bluedroid_demos/btif/btif_sm.c new file mode 100755 index 0000000000..9074e4cdd3 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/btif_sm.c @@ -0,0 +1,208 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + + +/***************************************************************************** + * + * Filename: btif_sm.c + * + * Description: Generic BTIF state machine API + * + *****************************************************************************/ + +#define LOG_TAG "bt_btif" + +// #include +#include "bt_defs.h" +#include "allocator.h" +#include "btif_common.h" +#include "btif_sm.h" +#include "gki.h" + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ + + +/***************************************************************************** +** Local type definitions +******************************************************************************/ +typedef struct { + btif_sm_state_t state; + btif_sm_handler_t *p_handlers; +} btif_sm_cb_t; + +/***************************************************************************** +** Static variables +******************************************************************************/ + +/***************************************************************************** +** Static functions +******************************************************************************/ + +/***************************************************************************** +** Externs +******************************************************************************/ + +/***************************************************************************** +** Functions +******************************************************************************/ + +/***************************************************************************** +** +** Function btif_sm_init +** +** Description Initializes the state machine with the state handlers +** The caller should ensure that the table and the corresponding +** states match. The location that 'p_handlers' points to shall +** be available until the btif_sm_shutdown API is invoked. +** +** Returns Returns a pointer to the initialized state machine handle. +** +******************************************************************************/ + +btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers, btif_sm_state_t initial_state) +{ + btif_sm_cb_t *p_cb; + + if (p_handlers == NULL) + { + BTIF_TRACE_ERROR("%s : p_handlers is NULL", __FUNCTION__); + return NULL; + } + + p_cb = (btif_sm_cb_t *)osi_malloc(sizeof(btif_sm_cb_t)); + p_cb->state = initial_state; + p_cb->p_handlers = (btif_sm_handler_t*)p_handlers; + + /* Send BTIF_SM_ENTER_EVT to the initial state */ + p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL); + + return (btif_sm_handle_t)p_cb; +} + +/***************************************************************************** +** +** Function btif_sm_shutdown +** +** Description Tears down the state machine +** +** Returns None +** +******************************************************************************/ +void btif_sm_shutdown(btif_sm_handle_t handle) +{ + btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; + + if (p_cb == NULL) + { + BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); + return; + } + osi_free(p_cb); +} + +/***************************************************************************** +** +** Function btif_sm_get_state +** +** Description Fetches the current state of the state machine +** +** Returns Current state +** +******************************************************************************/ +btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle) +{ + btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; + + if (p_cb == NULL) + { + BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); + return 0; + } + + return p_cb->state; +} + +/***************************************************************************** +** +** Function btif_sm_dispatch +** +** Description Dispatches the 'event' along with 'data' to the current state handler +** +** Returns BT_STATUS_SUCCESS on success +** BT_STATUS_UNHANDLED if event was not processed +** BT_STATUS_FAIL otherwise +** +******************************************************************************/ +bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event, + void *data) +{ + bt_status_t status = BT_STATUS_SUCCESS; + + btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; + + if (p_cb == NULL) + { + BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); + return BT_STATUS_FAIL; + } + + if (p_cb->p_handlers[p_cb->state](event, data) == FALSE) + return BT_STATUS_UNHANDLED; + + return status; +} + +/***************************************************************************** +** +** Function btif_sm_change_state +** +** Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT' +** shall be invoked before exiting the current state. The +** 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new state +** +** Returns BT_STATUS_SUCCESS on success +** BT_STATUS_UNHANDLED if event was not processed +** BT_STATUS_FAIL otherwise +** +******************************************************************************/ +bt_status_t btif_sm_change_state(btif_sm_handle_t handle, btif_sm_state_t state) +{ + bt_status_t status = BT_STATUS_SUCCESS; + btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; + + if (p_cb == NULL) + { + BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); + return BT_STATUS_FAIL; + } + + /* Send exit event to the current state */ + if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL) == FALSE) + status = BT_STATUS_UNHANDLED; + + /* Change to the new state */ + p_cb->state = state; + + /* Send enter event to the new state */ + if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL) == FALSE) + status = BT_STATUS_UNHANDLED; + + return status; +} diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/btif_util.c b/examples/09_a2dp/components/bluedroid_demos/btif/btif_util.c new file mode 100755 index 0000000000..b64e7fdeb2 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/btif_util.c @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * 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. + * + ******************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_util.c + * + * Description: Miscellaneous helper functions + * + * + ***********************************************************************************/ + +// #include +// #include +// #include +// #include +#include +#include +#include +#include + + +#define LOG_TAG "bt_btif_util" +// #include "btif_common.h" +// #include "bta_api.h" +// #include "gki.h" +// #include "btu.h" +// #include "bte.h" +// #include "btif_dm.h" +#include "btif_util.h" +// #include "bta_ag_api.h" +// #include "bta_av_api.h" +// #include "bta_hh_api.h" +// #include "bta_hf_client_api.h" +// #include "avrc_defs.h" +#include "bt_defs.h" + +/************************************************************************************ +** Constants & Macros +************************************************************************************/ +#define ISDIGIT(a) ((a>='0') && (a<='9')) +#define ISXDIGIT(a) (((a>='0') && (a<='9'))||((a>='A') && (a<='F'))||((a>='a') && (a<='f'))) + +/************************************************************************************ +** Local type definitions +************************************************************************************/ + +/************************************************************************************ +** Static variables +************************************************************************************/ + +/************************************************************************************ +** Static functions +************************************************************************************/ + +/************************************************************************************ +** Externs +************************************************************************************/ + +/************************************************************************************ +** Functions +************************************************************************************/ + +/***************************************************************************** +** Logging helper functions +*****************************************************************************/ + +UINT32 devclass2uint(DEV_CLASS dev_class) +{ + UINT32 cod = 0; + + if(dev_class != NULL) + { + /* if COD is 0, irrespective of the device type set it to Unclassified device */ + cod = (dev_class[2]) | (dev_class[1] << 8) | (dev_class[0] << 16); + } + return cod; +} +void uint2devclass(UINT32 cod, DEV_CLASS dev_class) +{ + dev_class[2] = (UINT8)cod; + dev_class[1] = (UINT8)(cod >> 8); + dev_class[0] = (UINT8)(cod >> 16); +} + +static const UINT8 sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; + +void uuid16_to_uuid128(uint16_t uuid16, bt_uuid_t* uuid128) +{ + uint16_t uuid16_bo; + memset(uuid128, 0, sizeof(bt_uuid_t)); + + memcpy(uuid128->uu, sdp_base_uuid, MAX_UUID_SIZE); + uuid16_bo = ntohs(uuid16); + memcpy(uuid128->uu + 2, &uuid16_bo, sizeof(uint16_t)); +} + +void string_to_uuid(char *str, bt_uuid_t *p_uuid) +{ + uint32_t uuid0, uuid4; + uint16_t uuid1, uuid2, uuid3, uuid5; + + sscanf(str, "%08x-%04hx-%04hx-%04hx-%08x%04hx", + &uuid0, &uuid1, &uuid2, &uuid3, &uuid4, &uuid5); + + uuid0 = htonl(uuid0); + uuid1 = htons(uuid1); + uuid2 = htons(uuid2); + uuid3 = htons(uuid3); + uuid4 = htonl(uuid4); + uuid5 = htons(uuid5); + + memcpy(&(p_uuid->uu[0]), &uuid0, 4); + memcpy(&(p_uuid->uu[4]), &uuid1, 2); + memcpy(&(p_uuid->uu[6]), &uuid2, 2); + memcpy(&(p_uuid->uu[8]), &uuid3, 2); + memcpy(&(p_uuid->uu[10]), &uuid4, 4); + memcpy(&(p_uuid->uu[14]), &uuid5, 2); + + return; + +} + +void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str) +{ + uint32_t uuid0, uuid4; + uint16_t uuid1, uuid2, uuid3, uuid5; + + memcpy(&uuid0, &(p_uuid->uu[0]), 4); + memcpy(&uuid1, &(p_uuid->uu[4]), 2); + memcpy(&uuid2, &(p_uuid->uu[6]), 2); + memcpy(&uuid3, &(p_uuid->uu[8]), 2); + memcpy(&uuid4, &(p_uuid->uu[10]), 4); + memcpy(&uuid5, &(p_uuid->uu[14]), 2); + + sprintf((char *)str, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", + ntohl(uuid0), ntohs(uuid1), + ntohs(uuid2), ntohs(uuid3), + ntohl(uuid4), ntohs(uuid5)); + return; +} + diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_api.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_api.h new file mode 100755 index 0000000000..753fec100d --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_api.h @@ -0,0 +1,88 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/******************************************************************************* + * + * Filename: btif_api.h + * + * Description: Main API header file for all BTIF functions accessed + * from main bluetooth HAL. All HAL extensions will not + * require headerfiles as they would be accessed through + * callout/callins. + * + *******************************************************************************/ + +#ifndef BTIF_API_H +#define BTIF_API_H + +#include "btif_common.h" +#include "btif_dm.h" + +/******************************************************************************* +** BTIF CORE API +********************************************************************************/ + +/******************************************************************************* +** +** Function btif_init_bluetooth +** +** Description Creates BTIF task and prepares BT scheduler for startup +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_init_bluetooth(void); + +/******************************************************************************* +** +** Function btif_enable_bluetooth +** +** Description Performs chip power on and kickstarts OS scheduler +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_enable_bluetooth(void); + +/******************************************************************************* +** +** Function btif_disable_bluetooth +** +** Description Inititates shutdown of Bluetooth system. +** Any active links will be dropped and device entering +** non connectable/discoverable mode +** +** Returns void +** +*******************************************************************************/ +bt_status_t btif_disable_bluetooth(void); + +/******************************************************************************* +** +** Function btif_shutdown_bluetooth +** +** Description Finalizes BT scheduler shutdown and terminates BTIF +** task. +** +** +** Returns void +** +*******************************************************************************/ +bt_status_t btif_shutdown_bluetooth(void); + +#endif /* BTIF_API_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av.h new file mode 100755 index 0000000000..cedc1b7fe6 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av.h @@ -0,0 +1,154 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/******************************************************************************* + * + * Filename: btif_av.h + * + * Description: Main API header file for all BTIF AV functions accessed + * from internal stack. + * + *******************************************************************************/ + +#ifndef BTIF_AV_H +#define BTIF_AV_H + +#include "btif_common.h" +#include "btif_sm.h" +#include "bta_av_api.h" + + +/******************************************************************************* +** Type definitions for callback functions +********************************************************************************/ + +typedef enum { + /* Reuse BTA_AV_XXX_EVT - No need to redefine them here */ + BTIF_AV_CONNECT_REQ_EVT = BTA_AV_MAX_EVT, + BTIF_AV_DISCONNECT_REQ_EVT, + BTIF_AV_START_STREAM_REQ_EVT, + BTIF_AV_STOP_STREAM_REQ_EVT, + BTIF_AV_SUSPEND_STREAM_REQ_EVT, + BTIF_AV_SINK_CONFIG_REQ_EVT, +} btif_av_sm_event_t; + + +/******************************************************************************* +** BTIF AV API +********************************************************************************/ + +/******************************************************************************* +** +** Function btif_av_get_sm_handle +** +** Description Fetches current av SM handle +** +** Returns None +** +*******************************************************************************/ + +btif_sm_handle_t btif_av_get_sm_handle(void); + +/******************************************************************************* +** +** Function btif_av_stream_ready +** +** Description Checks whether AV is ready for starting a stream +** +** Returns None +** +*******************************************************************************/ + +BOOLEAN btif_av_stream_ready(void); + +/******************************************************************************* +** +** Function btif_av_stream_started_ready +** +** Description Checks whether AV ready for media start in streaming state +** +** Returns None +** +*******************************************************************************/ + +BOOLEAN btif_av_stream_started_ready(void); + +/******************************************************************************* +** +** Function btif_dispatch_sm_event +** +** Description Send event to AV statemachine +** +** Returns None +** +*******************************************************************************/ + +/* used to pass events to AV statemachine from other tasks */ +void btif_dispatch_sm_event(btif_av_sm_event_t event, void *p_data, int len); + +/******************************************************************************* +** +** Function btif_av_init +** +** Description Initializes btif AV if not already done +** +** Returns bt_status_t +** +*******************************************************************************/ + +bt_status_t btif_av_init(void); + +/******************************************************************************* +** +** Function btif_av_is_connected +** +** Description Checks if av has a connected sink +** +** Returns BOOLEAN +** +*******************************************************************************/ + +BOOLEAN btif_av_is_connected(void); + + +/******************************************************************************* +** +** Function btif_av_is_peer_edr +** +** Description Check if the connected a2dp device supports +** EDR or not. Only when connected this function +** will accurately provide a true capability of +** remote peer. If not connected it will always be false. +** +** Returns TRUE if remote device is capable of EDR +** +*******************************************************************************/ + +BOOLEAN btif_av_is_peer_edr(void); + +/****************************************************************************** +** +** Function btif_av_clear_remote_suspend_flag +** +** Description Clears remote suspended flag +** +** Returns Void +********************************************************************************/ +void btif_av_clear_remote_suspend_flag(void); + +#endif /* BTIF_AV_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av_api.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av_api.h new file mode 100755 index 0000000000..86cd40b399 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av_api.h @@ -0,0 +1,210 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/***************************************************************************** + ** + ** Name: btif_av_api.h + ** + ** Description: This is the public interface file for the advanced + ** audio/video streaming (AV) subsystem of BTIF, Broadcom's + ** Bluetooth application layer for mobile phones. + ** + *****************************************************************************/ + +#ifndef BTIF_AV_API_H +#define BTIF_AV_API_H + +#include "bt_target.h" +#include "bta_av_api.h" +#include "uipc.h" + +#include "btif_media.h" +#include "a2d_api.h" +#include "a2d_sbc.h" + + +/***************************************************************************** + ** Constants and data types + *****************************************************************************/ + +/* Codec type */ +#define BTIF_AV_CODEC_NONE 0xFF +#define BTIF_AV_CODEC_SBC A2D_MEDIA_CT_SBC /* SBC media codec type */ + +#define BTIF_AV_CODEC_PCM 0x5 /* Raw PCM */ + +typedef UINT8 tBTIF_AV_CODEC_ID; + +/* AV features masks */ +#define BTIF_AV_FEAT_RCTG BTA_AV_FEAT_RCTG /* remote control target */ +#define BTIF_AV_FEAT_RCCT BTA_AV_FEAT_RCCT /* remote control controller */ +#define BTIF_AV_FEAT_METADATA BTA_AV_FEAT_METADATA /* remote control Metadata Transfer command/response */ + +typedef UINT16 tBTIF_AV_FEAT; + +/* AV channel values */ +#define BTIF_AV_CHNL_MSK BTA_AV_CHNL_MSK +#define BTIF_AV_CHNL_AUDIO BTA_AV_CHNL_AUDIO /* audio channel */ +#define BTIF_AV_CHNL_VIDEO BTA_AV_CHNL_VIDEO /* video channel */ +typedef UINT8 tBTIF_AV_CHNL; + +typedef UINT8 tBTIF_AV_HNDL; + +/* Operation id list for BTIF_AvRemoteCmd */ +#define BTIF_AV_ID_SELECT 0x00 /* select */ +#define BTIF_AV_ID_UP 0x01 /* up */ +#define BTIF_AV_ID_DOWN 0x02 /* down */ +#define BTIF_AV_ID_LEFT 0x03 /* left */ +#define BTIF_AV_ID_RIGHT 0x04 /* right */ +#define BTIF_AV_ID_RIGHT_UP 0x05 /* right-up */ +#define BTIF_AV_ID_RIGHT_DOWN 0x06 /* right-down */ +#define BTIF_AV_ID_LEFT_UP 0x07 /* left-up */ +#define BTIF_AV_ID_LEFT_DOWN 0x08 /* left-down */ +#define BTIF_AV_ID_ROOT_MENU 0x09 /* root menu */ +#define BTIF_AV_ID_SETUP_MENU 0x0A /* setup menu */ +#define BTIF_AV_ID_CONT_MENU 0x0B /* contents menu */ +#define BTIF_AV_ID_FAV_MENU 0x0C /* favorite menu */ +#define BTIF_AV_ID_EXIT 0x0D /* exit */ +#define BTIF_AV_ID_0 0x20 /* 0 */ +#define BTIF_AV_ID_1 0x21 /* 1 */ +#define BTIF_AV_ID_2 0x22 /* 2 */ +#define BTIF_AV_ID_3 0x23 /* 3 */ +#define BTIF_AV_ID_4 0x24 /* 4 */ +#define BTIF_AV_ID_5 0x25 /* 5 */ +#define BTIF_AV_ID_6 0x26 /* 6 */ +#define BTIF_AV_ID_7 0x27 /* 7 */ +#define BTIF_AV_ID_8 0x28 /* 8 */ +#define BTIF_AV_ID_9 0x29 /* 9 */ +#define BTIF_AV_ID_DOT 0x2A /* dot */ +#define BTIF_AV_ID_ENTER 0x2B /* enter */ +#define BTIF_AV_ID_CLEAR 0x2C /* clear */ +#define BTIF_AV_ID_CHAN_UP 0x30 /* channel up */ +#define BTIF_AV_ID_CHAN_DOWN 0x31 /* channel down */ +#define BTIF_AV_ID_PREV_CHAN 0x32 /* previous channel */ +#define BTIF_AV_ID_SOUND_SEL 0x33 /* sound select */ +#define BTIF_AV_ID_INPUT_SEL 0x34 /* input select */ +#define BTIF_AV_ID_DISP_INFO 0x35 /* display information */ +#define BTIF_AV_ID_HELP 0x36 /* help */ +#define BTIF_AV_ID_PAGE_UP 0x37 /* page up */ +#define BTIF_AV_ID_PAGE_DOWN 0x38 /* page down */ +#define BTIF_AV_ID_POWER 0x40 /* power */ +#define BTIF_AV_ID_VOL_UP 0x41 /* volume up */ +#define BTIF_AV_ID_VOL_DOWN 0x42 /* volume down */ +#define BTIF_AV_ID_MUTE 0x43 /* mute */ +#define BTIF_AV_ID_PLAY 0x44 /* play */ +#define BTIF_AV_ID_STOP 0x45 /* stop */ +#define BTIF_AV_ID_PAUSE 0x46 /* pause */ +#define BTIF_AV_ID_RECORD 0x47 /* record */ +#define BTIF_AV_ID_REWIND 0x48 /* rewind */ +#define BTIF_AV_ID_FAST_FOR 0x49 /* fast forward */ +#define BTIF_AV_ID_EJECT 0x4A /* eject */ +#define BTIF_AV_ID_FORWARD 0x4B /* forward */ +#define BTIF_AV_ID_BACKWARD 0x4C /* backward */ +#define BTIF_AV_ID_ANGLE 0x50 /* angle */ +#define BTIF_AV_ID_SUBPICT 0x51 /* subpicture */ +#define BTIF_AV_ID_F1 0x71 /* F1 */ +#define BTIF_AV_ID_F2 0x72 /* F2 */ +#define BTIF_AV_ID_F3 0x73 /* F3 */ +#define BTIF_AV_ID_F4 0x74 /* F4 */ +#define BTIF_AV_ID_F5 0x75 /* F5 */ +#define BTIF_AV_ID_VENDOR 0x7E /* vendor unique */ +#define BTIF_AV_KEYPRESSED_RELEASE 0x80 + +typedef UINT8 tBTIF_AV_RC; + +/* State flag for pass through command */ +#define BTIF_AV_STATE_PRESS 0 /* key pressed */ +#define BTIF_AV_STATE_RELEASE 1 /* key released */ + +typedef UINT8 tBTIF_AV_STATE; + +typedef UINT8 tBTIF_AV_RC_HNDL; + +/* Command codes for BTIF_AvVendorCmd */ +#define BTIF_AV_CMD_CTRL 0 +#define BTIF_AV_CMD_STATUS 1 +#define BTIF_AV_CMD_SPEC_INQ 2 +#define BTIF_AV_CMD_NOTIF 3 +#define BTIF_AV_CMD_GEN_INQ 4 + +typedef UINT8 tBTIF_AV_CMD; + +/* AV callback events */ +#define BTIF_AV_OPEN_EVT 0 /* connection opened */ +#define BTIF_AV_CLOSE_EVT 1 /* connection closed */ +#define BTIF_AV_START_EVT 2 /* stream data transfer started */ +#define BTIF_AV_STOP_EVT 3 /* stream data transfer stopped */ +#define BTIF_AV_RC_OPEN_EVT 4 /* remote control channel open */ +#define BTIF_AV_RC_CLOSE_EVT 5 /* remote control channel closed */ +#define BTIF_AV_REMOTE_CMD_EVT 6 /* remote control command */ +#define BTIF_AV_REMOTE_RSP_EVT 7 /* remote control response */ +#define BTIF_AV_META_MSG_EVT 8 /* metadata messages */ + +typedef UINT8 tBTIF_AV_EVT; + +#define BTIF_AV_FEEDING_ASYNCHRONOUS 0 /* asynchronous feeding, use tx av timer */ +#define BTIF_AV_FEEDING_SYNCHRONOUS 1 /* synchronous feeding, no av tx timer */ + +#define BTIF_AV_MAX_SYNCHRONOUS_LATENCY 80 /* max latency in ms for BTIF_AV_FEEDING_SYNCHRONOUS */ +#define BTIF_AV_MIN_SYNCHRONOUS_LATENCY 4 /* min latency in ms for BTIF_AV_FEEDING_SYNCHRONOUS */ + +typedef UINT8 tBTIF_AV_FEEDING_MODE; + +#define BTIF_AV_CHANNEL_MODE_MONO A2D_SBC_IE_CH_MD_MONO +#define BTIF_AV_CHANNEL_MODE_STEREO A2D_SBC_IE_CH_MD_STEREO +#define BTIF_AV_CHANNEL_MODE_JOINT A2D_SBC_IE_CH_MD_JOINT +#define BTIF_AV_CHANNEL_MODE_DUAL A2D_SBC_IE_CH_MD_DUAL + +typedef UINT8 tBTIF_AV_CHANNEL_MODE; + +/** + * Structure used to configure the AV codec capabilities/config + */ +typedef struct +{ + tBTIF_AV_CODEC_ID id; /* Codec ID (in terms of BTIF) */ + UINT8 info[AVDT_CODEC_SIZE]; /* Codec info (can be config or capabilities) */ +} tBTIF_AV_CODEC_INFO; + +/** + * Structure used to configure the AV media feeding + */ +typedef struct +{ + UINT16 sampling_freq; /* 44100, 48000 etc */ + UINT16 num_channel; /* 1 for mono or 2 stereo */ + UINT8 bit_per_sample; /* Number of bits per sample (8, 16) */ +} tBTIF_AV_MEDIA_FEED_CFG_PCM; + +typedef union +{ + tBTIF_AV_MEDIA_FEED_CFG_PCM pcm; /* Raw PCM feeding format */ +}tBTIF_AV_MEDIA_FEED_CFG; + +typedef struct +{ + tBTIF_AV_CODEC_ID format; /* Media codec identifier */ + tBTIF_AV_MEDIA_FEED_CFG cfg; /* Media codec configuration */ +} tBTIF_AV_MEDIA_FEEDINGS; + + +#ifdef __cplusplus +} +#endif + +#endif /* BTIF_AV_API_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av_co.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av_co.h new file mode 100755 index 0000000000..a6a5bfaba6 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_av_co.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * 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 BTIF_AV_CO_H +#define BTIF_AV_CO_H + +#include "btif_media.h" + +/******************************************************************************* +** Constants & Macros +********************************************************************************/ + +enum +{ + BTIF_SV_AV_AA_SBC_INDEX = 0, + BTIF_SV_AV_AA_SBC_SINK_INDEX, + BTIF_SV_AV_AA_SEP_INDEX /* Last index */ +}; + + +/******************************************************************************* +** Functions +********************************************************************************/ + +/******************************************************************************* + ** + ** Function bta_av_co_cp_is_active + ** + ** Description Get the current configuration of content protection + ** + ** Returns TRUE if the current streaming has CP, FALSE otherwise + ** + *******************************************************************************/ +BOOLEAN bta_av_co_cp_is_active(void); + +/******************************************************************************* + ** + ** Function bta_av_co_cp_get_flag + ** + ** Description Get content protection flag + ** BTA_AV_CP_SCMS_COPY_NEVER + ** BTA_AV_CP_SCMS_COPY_ONCE + ** BTA_AV_CP_SCMS_COPY_FREE + ** + ** Returns The current flag value + ** + *******************************************************************************/ +UINT8 bta_av_co_cp_get_flag(void); + +/******************************************************************************* + ** + ** Function bta_av_co_cp_set_flag + ** + ** Description Set content protection flag + ** BTA_AV_CP_SCMS_COPY_NEVER + ** BTA_AV_CP_SCMS_COPY_ONCE + ** BTA_AV_CP_SCMS_COPY_FREE + ** + ** Returns TRUE if setting the SCMS flag is supported else FALSE + ** + *******************************************************************************/ +BOOLEAN bta_av_co_cp_set_flag(UINT8 cp_flag); + +/******************************************************************************* + ** + ** Function bta_av_co_audio_codec_reset + ** + ** Description Reset the current codec configuration + ** + ** Returns void + ** + *******************************************************************************/ +void bta_av_co_audio_codec_reset(void); + +/******************************************************************************* + ** + ** Function bta_av_co_audio_codec_supported + ** + ** Description Check if all opened connections are compatible with a codec + ** configuration + ** + ** Returns TRUE if all opened devices support this codec, FALSE otherwise + ** + *******************************************************************************/ +BOOLEAN bta_av_co_audio_codec_supported(tBTIF_STATUS *p_status); + +/******************************************************************************* + ** + ** Function bta_av_co_audio_set_codec + ** + ** Description Set the current codec configuration from the feeding type. + ** This function is starting to modify the configuration, it + ** should be protected. + ** + ** Returns TRUE if successful, FALSE otherwise + ** + *******************************************************************************/ +BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTIF_STATUS *p_status); + +/******************************************************************************* + ** + ** Function bta_av_co_audio_get_sbc_config + ** + ** Description Retrieves the SBC codec configuration. If the codec in use + ** is not SBC, return the default SBC codec configuration. + ** + ** Returns TRUE if codec is SBC, FALSE otherwise + ** + *******************************************************************************/ +BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_minmtu); + +/******************************************************************************* + ** + ** Function bta_av_co_audio_discard_config + ** + ** Description Discard the codec configuration of a connection + ** + ** Returns Nothing + ** + *******************************************************************************/ +void bta_av_co_audio_discard_config(tBTA_AV_HNDL hndl); + +/******************************************************************************* + ** + ** Function bta_av_co_init + ** + ** Description Initialization + ** + ** Returns Nothing + ** + *******************************************************************************/ +void bta_av_co_init(void); + + +/******************************************************************************* + ** + ** Function bta_av_co_peer_cp_supported + ** + ** Description Checks if the peer supports CP + ** + ** Returns TRUE if the peer supports CP + ** + *******************************************************************************/ +BOOLEAN bta_av_co_peer_cp_supported(tBTA_AV_HNDL hndl); + +/******************************************************************************* + ** + ** Function bta_av_co_get_remote_bitpool_pref + ** + ** Description Check if remote side did a setconfig within the limits + ** of our exported bitpool range. If set we will set the + ** remote preference. + ** + ** Returns TRUE if config set, FALSE otherwize + ** + *******************************************************************************/ +BOOLEAN bta_av_co_get_remote_bitpool_pref(UINT8 *min, UINT8 *max); + +#endif diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_common.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_common.h new file mode 100755 index 0000000000..fe52139f44 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_common.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * 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 BTIF_COMMON_H +#define BTIF_COMMON_H + +#include +// #include + +#include "bt_types.h" +#include "bta_api.h" +#include "osi.h" + +// #include "osi/include/log.h" + +/******************************************************************************* +** Constants & Macros +********************************************************************************/ +#define ASSERTC(cond, msg, val) if (!(cond)) { LOG_ERROR( \ + "### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);} + +/* Calculate start of event enumeration; id is top 8 bits of event */ +#define BTIF_SIG_START(id) ((id) << 8) + +/* For upstream the MSB bit is always SET */ +#define BTIF_SIG_CB_BIT (0x8000) +#define BTIF_SIG_CB_START(id) (((id) << 8) | BTIF_SIG_CB_BIT) + +/* BTIF sub-systems */ +#define BTIF_CORE 0 +#define BTIF_DM 1 +// #define BTIF_HFP 2 +// #define BTIF_AV 3 +// #define BTIF_PAN 4 +// #define BTIF_HF_CLIENT 5 + +#define HAL_CBACK(P_CB, P_CBACK, ...)\ + if (P_CB && P_CB->P_CBACK) { \ + BTIF_TRACE_API("HAL %s->%s", #P_CB, #P_CBACK); \ + P_CB->P_CBACK(__VA_ARGS__); \ + } \ + else { \ + ASSERTC(0, "Callback is NULL", 0); \ + } + +/** + * BTIF events for requests that require context switch to btif task + * on downstreams path + */ +enum +{ + BTIF_CORE_API_START = BTIF_SIG_START(BTIF_CORE), + /* add here */ + + BTIF_DM_API_START = BTIF_SIG_START(BTIF_DM), + BTIF_DM_ENABLE_SERVICE, + BTIF_DM_DISABLE_SERVICE, + /* add here */ + +}; + +enum { + SIG_BTIF_WORK = 0xff +}; + +/******************************************************************************* +** Type definitions for callback functions +********************************************************************************/ + +typedef void (tBTIF_CBACK) (UINT16 event, char *p_param); +typedef void (tBTIF_COPY_CBACK) (UINT16 event, char *p_dest, char *p_src); + + +/******************************************************************************* +** Type definitions and return values +********************************************************************************/ + +/* this type handles all btif context switches between BTU and HAL */ +typedef struct +{ + BT_HDR hdr; + tBTIF_CBACK* p_cb; /* context switch callback */ + + /* parameters passed to callback */ + UINT16 event; /* message event id */ + char p_param[0]; /* parameter area needs to be last */ +} tBTIF_CONTEXT_SWITCH_CBACK; + + +/******************************************************************************* +** Functions +********************************************************************************/ + +bt_status_t btif_transfer_context (tBTIF_CBACK *p_cback, UINT16 event, char* p_params, + int param_len, tBTIF_COPY_CBACK *p_copy_cback); +tBTA_SERVICE_MASK btif_get_enabled_services_mask(void); +bt_status_t btif_enable_service(tBTA_SERVICE_ID service_id); +bt_status_t btif_disable_service(tBTA_SERVICE_ID service_id); +int btif_is_enabled(void); + +/** + * BTIF_Events + */ +void btif_enable_bluetooth_evt(tBTA_STATUS status); +void btif_disable_bluetooth_evt(void); + + + +#endif /* BTIF_COMMON_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_dm.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_dm.h new file mode 100755 index 0000000000..58f535c30b --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_dm.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * + * 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 BTIF_DM_H +#define BTIF_DM_H + +#include "bta_api.h" +/************************************************************************************ +** Functions +********************************************************************************/ + +/** + * BTIF callback to switch context from bte to btif + */ +void bte_dm_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data); + +#endif diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_media.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_media.h new file mode 100755 index 0000000000..2ec19cbdf7 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_media.h @@ -0,0 +1,282 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/******************************************************************************* + * + * Filename: btif_media.h + * + * Description: This is the audio module for the BTIF system. + * + *******************************************************************************/ + +#ifndef BTIF_MEDIA_H +#define BTIF_MEDIA_H + +#include + +#include "bta_api.h" +#include "gki.h" +#include "btif_av_api.h" +#include "audio_a2dp_hw.h" + +/******************************************************************************* + ** Constants + *******************************************************************************/ + +/* Generic part */ +#define BTIF_SUCCESS 0 + +/** + * AV (Audio Video source) Errors + */ +#define BTIF_ERROR_SRV_AV_NOT_ENABLED 700 /* AV is not enabled */ +#define BTIF_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED 701 /* Requested Feeding not supported */ +#define BTIF_ERROR_SRV_AV_BUSY 702 /* Another operation ongoing */ +#define BTIF_ERROR_SRV_AV_NOT_OPENED 703 /* No AV link opened */ +#define BTIF_ERROR_SRV_AV_NOT_STARTED 704 /* AV is not started */ +#define BTIF_ERROR_SRV_AV_CP_NOT_SUPPORTED 705 /* Content protection is not supported by all headsets */ + +/* Transcoding definition for TxTranscoding and RxTranscoding */ +#define BTIF_MEDIA_TRSCD_OFF 0 +#define BTIF_MEDIA_TRSCD_PCM_2_SBC 1 /* Tx */ + + +/******************************************************************************* + ** Data types + *******************************************************************************/ + +typedef int tBTIF_STATUS; + +/* tBTIF_MEDIA_INIT_AUDIO msg structure */ +typedef struct +{ + BT_HDR hdr; + UINT16 SamplingFreq; /* 16k, 32k, 44.1k or 48k*/ + UINT8 ChannelMode; /* mono, dual, stereo or joint stereo*/ + UINT8 NumOfSubBands; /* 4 or 8 */ + UINT8 NumOfBlocks; /* 4, 8, 12 or 16*/ + UINT8 AllocationMethod; /* loudness or SNR*/ + UINT16 MtuSize; /* peer mtu size */ +} tBTIF_MEDIA_INIT_AUDIO; + +#if (BTA_AV_INCLUDED == TRUE) +/* tBTIF_MEDIA_UPDATE_AUDIO msg structure */ +typedef struct +{ + BT_HDR hdr; + UINT16 MinMtuSize; /* Minimum peer mtu size */ + UINT8 MaxBitPool; /* Maximum peer bitpool */ + UINT8 MinBitPool; /* Minimum peer bitpool */ +} tBTIF_MEDIA_UPDATE_AUDIO; + +/* tBTIF_MEDIA_INIT_AUDIO_FEEDING msg structure */ +typedef struct +{ + BT_HDR hdr; + tBTIF_AV_FEEDING_MODE feeding_mode; + tBTIF_AV_MEDIA_FEEDINGS feeding; +} tBTIF_MEDIA_INIT_AUDIO_FEEDING; + +typedef struct +{ + BT_HDR hdr; + UINT8 codec_info[AVDT_CODEC_SIZE]; +} tBTIF_MEDIA_SINK_CFG_UPDATE; +#endif + +/******************************************************************************* + ** Public functions + *******************************************************************************/ + +/******************************************************************************* + ** + ** Function btif_av_task + ** + ** Description + ** + ** Returns void + ** + *******************************************************************************/ +extern void btif_media_task(void); + +/******************************************************************************* + ** + ** Function btif_media_task_enc_init_req + ** + ** Description Request to initialize the media task encoder + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +extern BOOLEAN btif_media_task_enc_init_req(tBTIF_MEDIA_INIT_AUDIO * p_msg); + +/******************************************************************************* + ** + ** Function btif_media_task_enc_update_req + ** + ** Description Request to update the media task encoder + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +#if (BTA_AV_INCLUDED == TRUE) +extern BOOLEAN btif_media_task_enc_update_req(tBTIF_MEDIA_UPDATE_AUDIO * p_msg); +#endif + +/******************************************************************************* + ** + ** Function btif_media_task_start_aa_req + ** + ** Description Request to start audio encoding task + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +extern BOOLEAN btif_media_task_start_aa_req(void); + +/******************************************************************************* + ** + ** Function btif_media_task_stop_aa_req + ** + ** Description Request to stop audio encoding task + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +extern BOOLEAN btif_media_task_stop_aa_req(void); + +/******************************************************************************* + ** + ** Function btif_media_task_aa_rx_flush_req + ** + ** Description Request to flush audio decoding pipe + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +extern BOOLEAN btif_media_task_aa_rx_flush_req(void); +/******************************************************************************* + ** + ** Function btif_media_task_aa_tx_flush_req + ** + ** Description Request to flush audio encoding pipe + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +extern BOOLEAN btif_media_task_aa_tx_flush_req(void); + +/******************************************************************************* + ** + ** Function btif_media_aa_readbuf + ** + ** Description Read an audio GKI buffer from the BTIF media TX queue + ** + ** Returns pointer on a GKI aa buffer ready to send + ** + *******************************************************************************/ +extern BT_HDR *btif_media_aa_readbuf(void); + +/******************************************************************************* + ** + ** Function btif_media_sink_enque_buf + ** + ** Description This function is called by the av_co to fill A2DP Sink Queue + ** + ** + ** Returns size of the queue + *******************************************************************************/ + UINT8 btif_media_sink_enque_buf(BT_HDR *p_buf); + + + +/******************************************************************************* + ** + ** Function btif_media_aa_writebuf + ** + ** Description Enqueue a Advance Audio media GKI buffer to be processed by btif media task. + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +extern void btif_media_aa_writebuf(BT_HDR *pBuf, UINT32 timestamp, UINT16 seq_num); + +/******************************************************************************* + ** + ** Function btif_media_av_writebuf + ** + ** Description Enqueue a video media GKI buffer to be processed by btif media task. + ** + ** Returns TRUE is success + ** + *******************************************************************************/ +extern BOOLEAN btif_media_av_writebuf(UINT8 *p_media, UINT32 media_len, + UINT32 timestamp, UINT16 seq_num); + +#if (BTA_AV_INCLUDED == TRUE) +/******************************************************************************* + ** + ** Function btif_media_task_audio_feeding_init_req + ** + ** Description Request to initialize audio feeding + ** + ** Returns TRUE is success + ** + *******************************************************************************/ + +extern BOOLEAN btif_media_task_audio_feeding_init_req(tBTIF_MEDIA_INIT_AUDIO_FEEDING *p_msg); +#endif + +/******************************************************************************* + ** + ** Function dump_codec_info + ** + ** Description Decode and display codec_info (for debug) + ** + ** Returns void + ** + *******************************************************************************/ +extern void dump_codec_info(unsigned char *p_codec); + +/** + * Local adaptation helper functions between btif and media task + */ + +bool btif_a2dp_start_media_task(void); +void btif_a2dp_stop_media_task(void); + +void btif_a2dp_on_init(void); +void btif_a2dp_setup_codec(void); +void btif_a2dp_on_idle(void); +void btif_a2dp_on_open(void); +BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start); +void btif_a2dp_ack_fail(void); +void btif_a2dp_on_stop_req(void); +void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av); +void btif_a2dp_on_suspend(void); +void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av); +void btif_a2dp_set_tx_flush(BOOLEAN enable); +void btif_a2dp_set_rx_flush(BOOLEAN enable); +void btif_media_check_iop_exceptions(UINT8 *peer_bda); +void btif_reset_decoder(UINT8 *p_av); + +int btif_a2dp_get_track_frequency(UINT8 frequency); +int btif_a2dp_get_track_channel_count(UINT8 channeltype); +void btif_a2dp_set_peer_sep(UINT8 sep); + +#endif diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_profile_queue.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_profile_queue.h new file mode 100755 index 0000000000..f28daac5ec --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_profile_queue.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/******************************************************************************* + * + * Filename: btif_profile_queue.h + * + * Description: Bluetooth remote device connection queuing + * + *******************************************************************************/ + +#ifndef BTIF_PROFILE_QUEUE_H +#define BTIF_PROFILE_QUEUE_H + +typedef bt_status_t (*btif_connect_cb_t) (bt_bdaddr_t *bda, uint16_t uuid); + +bt_status_t btif_queue_connect(uint16_t uuid, const bt_bdaddr_t *bda, btif_connect_cb_t connect_cb); +void btif_queue_advance(); +bt_status_t btif_queue_connect_next(void); +void btif_queue_release(); + +#endif diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_sdp.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_sdp.h new file mode 100644 index 0000000000..e345ef03f2 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_sdp.h @@ -0,0 +1,38 @@ +#ifndef __BTIF_SDP_H__ +#define __BTIF_SDP_H__ + +#include "bt_sdp.h" + +/** Callback for SDP search */ +typedef void (*btsdp_search_callback)(bt_status_t status, bt_bdaddr_t *bd_addr, uint8_t* uuid, int num_records, bluetooth_sdp_record *records); + +typedef struct { + btsdp_search_callback sdp_search_cb; +} btsdp_callbacks_t; + +/** Register BT SDP search callbacks */ +bt_status_t BTIF_SdpInit(btsdp_callbacks_t *callbacks); + +/** Unregister BT SDP */ +bt_status_t BTIF_SdpDeinit(void); + +/** Search for SDP records with specific uuid on remote device */ +bt_status_t BTIF_SdpSearch(bt_bdaddr_t *bd_addr, const uint8_t* uuid); + +/** + * Use listen in the socket interface to create rfcomm and/or l2cap PSM channels, + * (without UUID and service_name and set the BTSOCK_FLAG_NO_SDP flag in flags). + * Then use createSdpRecord to create the SDP record associated with the rfcomm/l2cap channels. + * + * Returns a handle to the SDP record, which can be parsed to remove_sdp_record. + * + * record (in) The SDP record to create + * record_handle (out)The corresponding record handle will be written to this pointer. + */ +bt_status_t BTIF_SdpCreateRecord(bluetooth_sdp_record *record, int* record_handle); + +/** Remove a SDP record created by BTIF_SdpCreateRecord */ +bt_status_t BTIF_SdpRemoveRecord(int record_handle); + + +#endif /* __BTIF_SDP_H__ */ diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_sm.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_sm.h new file mode 100755 index 0000000000..baad0d94d6 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_sm.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/***************************************************************************** + * + * Filename: btif_sm.h + * + * Description: Generic BTIF state machine API + * + *****************************************************************************/ + +#ifndef BTIF_SM_H +#define BTIF_SM_H + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ + +/* Generic Enter/Exit state machine events */ +#define BTIF_SM_ENTER_EVT 0xFFFF +#define BTIF_SM_EXIT_EVT 0xFFFE + + +/***************************************************************************** +** Type definitions and return values +******************************************************************************/ +typedef UINT32 btif_sm_state_t; +typedef UINT32 btif_sm_event_t; +typedef void* btif_sm_handle_t; +typedef BOOLEAN(*btif_sm_handler_t)(btif_sm_event_t event, void *data); + + +/***************************************************************************** +** Functions +** +** NOTE: THESE APIs SHOULD BE INVOKED ONLY IN THE BTIF CONTEXT +** +******************************************************************************/ + +/***************************************************************************** +** +** Function btif_sm_init +** +** Description Initializes the state machine with the state handlers +** The caller should ensure that the table and the corresponding +** states match. The location that 'p_handlers' points to shall +** be available until the btif_sm_shutdown API is invoked. +** +** Returns Returns a pointer to the initialized state machine handle. +** +******************************************************************************/ +btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers, + btif_sm_state_t initial_state); + +/***************************************************************************** +** +** Function btif_sm_shutdown +** +** Description Tears down the state machine +** +** Returns None +** +******************************************************************************/ +void btif_sm_shutdown(btif_sm_handle_t handle); + +/***************************************************************************** +** +** Function btif_sm_get_state +** +** Description Fetches the current state of the state machine +** +** Returns Current state +** +******************************************************************************/ +btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle); + +/***************************************************************************** +** +** Function btif_sm_dispatch +** +** Description Dispatches the 'event' along with 'data' to the current state handler +** +** Returns Returns BT_STATUS_OK on success, BT_STATUS_FAIL otherwise +** +******************************************************************************/ +bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event, + void *data); + +/***************************************************************************** +** +** Function btif_sm_change_state +** +** Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT' +** shall be invoked before exiting the current state. The +** 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new state +** +** +** Returns Returns BT_STATUS_OK on success, BT_STATUS_FAIL otherwise +** +******************************************************************************/ +bt_status_t btif_sm_change_state(btif_sm_handle_t handle, btif_sm_state_t state); + +#endif /* BTIF_SM_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_stack_manager.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_stack_manager.h new file mode 100644 index 0000000000..a780fded25 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_stack_manager.h @@ -0,0 +1,31 @@ +#ifndef __BTIF_STACK_MANAGER_H__ +#define __BTIF_STACK_MANAGER_H__ + +#include "bt_defs.h" + +/** Bluetooth Adapter State */ +typedef enum { + BT_STATE_OFF, + BT_STATE_ON +} bt_state_t; + +/** Bluetooth Interface callbacks */ + +/** Bluetooth Enable/Disable Callback. */ +typedef void (*adapter_state_changed_callback)(bt_state_t state); + + +/** Bluetooth Device callback structure. */ +typedef struct { + adapter_state_changed_callback adapter_state_changed_cb; +} bt_callbacks_t; + +bt_status_t BTIF_InitStack(bt_callbacks_t *cb); + +bt_status_t BTIF_EnableStack(void); + +bt_status_t BTIF_DisableStack(void); + +bt_status_t BTIF_CleanUpStack(void); + +#endif /* __BTIF_STACK_MANAGER_H__ */ diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_util.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_util.h new file mode 100755 index 0000000000..80cdc5f4ef --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/btif_util.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * 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 BTIF_UTIL_H +#define BTIF_UTIL_H + +// #include +// #include +#include +// #include + +#include "bt_types.h" +// #include "bt_utils.h" +#include "bt_defs.h" + +/******************************************************************************* +** Constants & Macros +********************************************************************************/ +#define CASE_RETURN_STR(const) case const: return #const; +/******************************************************************************* +** Type definitions for callback functions +********************************************************************************/ + +typedef char bdstr_t[18]; + + +/******************************************************************************* +** Functions +********************************************************************************/ +UINT32 devclass2uint(DEV_CLASS dev_class); +void uint2devclass(UINT32 dev, DEV_CLASS dev_class); +void uuid16_to_uuid128(uint16_t uuid16, bt_uuid_t* uuid128); + +void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str); +void string_to_uuid(char *str, bt_uuid_t *p_uuid); + +#endif /* BTIF_UTIL_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/include/stack_manager.h b/examples/09_a2dp/components/bluedroid_demos/btif/include/stack_manager.h new file mode 100755 index 0000000000..466cdca122 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/include/stack_manager.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * 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 __STACK_MANAGER_H__ +#define __STACK_MANAGER_H__ + +#include +#include "future.h" + +bool stack_manager_is_stack_running(void); + +future_t *stack_manager_get_hack_future(void); + +#endif /* __STACK_MANAGER_H__*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/btif/stack_manager.c b/examples/09_a2dp/components/bluedroid_demos/btif/stack_manager.c new file mode 100644 index 0000000000..37843cdea2 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/btif/stack_manager.c @@ -0,0 +1,160 @@ +#include +#include +#include "btif_stack_manager.h" +#include "stack_manager.h" +#include "bt_defs.h" +#include "bt_trace.h" +#include "future.h" +#include "btif_common.h" +#include "btif_api.h" +#include "btif_dm.h" + +/************************************************************************************ +** Constants & Macros +************************************************************************************/ +/************************************************************************************ +** Local type definitions +************************************************************************************/ +/************************************************************************************ +** Static variables +************************************************************************************/ +static bool stack_is_initialized = false; +static bool stack_is_running = false; +static bt_callbacks_t *bt_hal_cbacks = NULL; +static future_t *hack_future = NULL; + +static bt_status_t event_init_stack(bt_callbacks_t *cb); +static bt_status_t event_start_up_stack(void); +static bt_status_t event_shut_down_stack(void); +static bt_status_t event_clean_up_stack(void); +static void event_signal_stack_up(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param); +static void event_signal_stack_down(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param); + +static bt_status_t event_init_stack(bt_callbacks_t *cb) +{ + bt_status_t ret; + if (!stack_is_initialized) { + hack_future = future_new(); + ret = btif_init_bluetooth(); + if (future_await(hack_future) != FUTURE_SUCCESS) { + return BT_STATUS_FAIL; + } + if (ret == BT_STATUS_SUCCESS) { + bt_hal_cbacks = cb; + stack_is_initialized = true; + } + return ret; + } + else { + return BT_STATUS_DONE; + } +} + +static bt_status_t event_start_up_stack(void) +{ + if (!stack_is_initialized) { + LOG_DEBUG("%s stack not initialized yet.\n", __func__); + return BT_STATUS_NOT_READY; + } + + if (stack_is_running) { + LOG_DEBUG("%s stack already brought up.\n", __func__); + return BT_STATUS_DONE; + } + + LOG_DEBUG("%s is bringing up the stack.\n", __func__); + hack_future = future_new(); + + btif_enable_bluetooth(); + + if (future_await(hack_future) != FUTURE_SUCCESS) { + stack_is_running = true; // So stack shutdown actually happens + event_shut_down_stack(); + return BT_STATUS_FAIL; + } + + stack_is_running = true; + LOG_DEBUG("%s finished\n", __func__); + btif_transfer_context(event_signal_stack_up, 0, NULL, 0, NULL); + return BT_STATUS_SUCCESS; +} + +static bt_status_t event_shut_down_stack(void) +{ + if (!stack_is_running) { + LOG_DEBUG("%s stack is already brought down.\n", __func__); + return BT_STATUS_DONE; + } + + LOG_DEBUG("%s is bringing down the stack.\n", __func__); + hack_future = future_new(); + stack_is_running = false; + + btif_disable_bluetooth(); + + future_await(hack_future); + + LOG_DEBUG("%s finished.\n", __func__); + btif_transfer_context(event_signal_stack_down, 0, NULL, 0, NULL); + return BT_STATUS_SUCCESS; +} + +static bt_status_t event_clean_up_stack(void) +{ + if (!stack_is_initialized) { + LOG_DEBUG("%s found the stack already in a clean state.\n", __func__); + return BT_STATUS_DONE; + } + + if (stack_is_running) { + event_shut_down_stack(); + } + + LOG_DEBUG("%s is cleaning up the stack.\n", __func__); + + stack_is_initialized = false; + + btif_shutdown_bluetooth(); + + return BT_STATUS_SUCCESS; +} + +static void event_signal_stack_up(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param) +{ + HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON); +} + +static void event_signal_stack_down(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param) +{ + HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF); +} + +bt_status_t BTIF_InitStack(bt_callbacks_t *cb) +{ + return event_init_stack(cb); +} + +bt_status_t BTIF_EnableStack(void) +{ + return event_start_up_stack(); +} + +bt_status_t BTIF_DisableStack(void) +{ + return event_shut_down_stack(); +} + +bt_status_t BTIF_CleanUpStack(void) +{ + return event_clean_up_stack(); +} + +bool stack_manager_is_stack_running(void) +{ + return stack_is_running; +} + +future_t *stack_manager_get_hack_future(void) +{ + return hack_future; +} diff --git a/examples/09_a2dp/components/bluedroid_demos/component.mk b/examples/09_a2dp/components/bluedroid_demos/component.mk new file mode 100755 index 0000000000..6e20af7362 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/component.mk @@ -0,0 +1,29 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# +# This Makefile should, at the very least, just include $(SDK_PATH)/make/component_common.mk. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +COMPONENT_ADD_INCLUDEDIRS := \ + udrv/include \ + btif/include \ + audio_a2dp_hw/include \ + embdrv/sbc/encoder/include \ + embdrv/sbc/decoder/include \ + include \ + +COMPONENT_SRCDIRS := \ + app_core \ + app_project \ + udrv/ulinux \ + embdrv/sbc/encoder \ + embdrv/sbc/decoder \ + btif + +CFLAGS += -Wno-error=unused-label -Wno-error=return-type -Wno-error=missing-braces -Wno-error=pointer-sign -Wno-error=parentheses -I./include + + +include $(IDF_PATH)/make/component_common.mk diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_assert.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_assert.h new file mode 100755 index 0000000000..35d86cfc5f --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_assert.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_ASSERT_H +#define _OI_ASSERT_H +/** @file + This file provides macros and functions for compile-time and run-time assertions. + + When the OI_DEBUG preprocessor value is defined, the macro OI_ASSERT is compiled into + the program, providing for a runtime assertion failure check. + C_ASSERT is a macro that can be used to perform compile time checks. +*/ +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + + +/** \addtogroup Debugging Debugging APIs */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef OI_DEBUG + +/** The macro OI_ASSERT takes a condition argument. If the asserted condition + does not evaluate to true, the OI_ASSERT macro calls the host-dependent function, + OI_AssertFail(), which reports the failure and generates a runtime error. +*/ +void OI_AssertFail(char* file, int line, char* reason); + + +#define OI_ASSERT(condition) \ + { if (!(condition)) OI_AssertFail(__FILE__, __LINE__, #condition); } + +#define OI_ASSERT_FAIL(msg) \ + { OI_AssertFail(__FILE__, __LINE__, msg); } + +#else + + +#define OI_ASSERT(condition) +#define OI_ASSERT_FAIL(msg) + +#endif + + +/** + C_ASSERT() can be used to perform many compile-time assertions: type sizes, field offsets, etc. + An assertion failure results in compile time error C2118: negative subscript. + Unfortunately, this elegant macro doesn't work with GCC, so it's all commented out + for now. Perhaps later..... +*/ + +#ifndef C_ASSERT +// #define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +// #define C_ASSERT(e) +#endif + + +/*****************************************************************************/ +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif /* _OI_ASSERT_H */ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_bitstream.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_bitstream.h new file mode 100755 index 0000000000..df0c10f5de --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_bitstream.h @@ -0,0 +1,123 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_BITSTREAM_H +#define _OI_BITSTREAM_H + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + + +/** +@file +Function prototypes and macro definitions for manipulating input and output +bitstreams. + +@ingroup codec_internal +*/ + +/** +@addtogroup codec_internal +@{ +*/ + +#include "oi_codec_sbc_private.h" +#include "oi_stddefs.h" + +INLINE void OI_BITSTREAM_ReadInit(OI_BITSTREAM *bs, const OI_BYTE *buffer); + +INLINE void OI_BITSTREAM_WriteInit(OI_BITSTREAM *bs, OI_BYTE *buffer); + +INLINE OI_UINT32 OI_BITSTREAM_ReadUINT(OI_BITSTREAM *bs, OI_UINT bits); + +INLINE OI_UINT8 OI_BITSTREAM_ReadUINT4Aligned(OI_BITSTREAM *bs); + +INLINE OI_UINT8 OI_BITSTREAM_ReadUINT8Aligned(OI_BITSTREAM *bs); + +INLINE void OI_BITSTREAM_WriteUINT(OI_BITSTREAM *bs, + OI_UINT16 value, + OI_UINT bits); + +/* + * Use knowledge that the bitstream is aligned to optimize the write of a byte + */ +PRIVATE void OI_BITSTREAM_WriteUINT8Aligned(OI_BITSTREAM *bs, + OI_UINT8 datum); + +/* + * Use knowledge that the bitstream is aligned to optimize the write pair of nibbles + */ +PRIVATE void OI_BITSTREAM_Write2xUINT4Aligned(OI_BITSTREAM *bs, + OI_UINT8 datum1, + OI_UINT8 datum2); + +/** Internally the bitstream looks ahead in the stream. When + * OI_SBC_ReadScalefactors() goes to temporarily break the abstraction, it will + * need to know where the "logical" pointer is in the stream. + */ +#define OI_BITSTREAM_GetWritePtr(bs) ((bs)->ptr.w - 3) +#define OI_BITSTREAM_GetReadPtr(bs) ((bs)->ptr.r - 3) + +/** This is declared here as a macro because decoder.c breaks the bitsream + * encapsulation for efficiency reasons. + */ +#define OI_BITSTREAM_READUINT(result, bits, ptr, value, bitPtr) \ +do { \ + OI_ASSERT((bits) <= 16); \ + OI_ASSERT((bitPtr) < 16); \ + OI_ASSERT((bitPtr) >= 8); \ + \ + result = (value) << (bitPtr); \ + result >>= 32 - (bits); \ + \ + bitPtr += (bits); \ + while (bitPtr >= 16) { \ + value = ((value) << 8) | *ptr++; \ + bitPtr -= 8; \ + } \ + OI_ASSERT((bits == 0) || (result < (1u << (bits)))); \ +} while (0) + + +#define OI_BITSTREAM_WRITEUINT(ptr, value, bitPtr, datum, bits) \ +do {\ + bitPtr -= bits;\ + value |= datum << bitPtr;\ + \ + while (bitPtr <= 16) {\ + bitPtr += 8;\ + *ptr++ = (OI_UINT8)(value >> 24);\ + value <<= 8;\ + }\ +} while (0) + +#define OI_BITSTREAM_WRITEFLUSH(ptr, value, bitPtr) \ +do {\ + while (bitPtr < 32) {\ + bitPtr += 8;\ + *ptr++ = (OI_UINT8)(value >> 24);\ + value <<= 8;\ + }\ +} while (0) + +/** +@} +*/ + +#endif /* _OI_BITSTREAM_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_bt_spec.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_bt_spec.h new file mode 100755 index 0000000000..b98a5821dd --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_bt_spec.h @@ -0,0 +1,229 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_BT_SPEC_H +#define _OI_BT_SPEC_H +/** + * @file + * + * This file contains common definitions from the Bluetooth specification. + * + */ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#include "oi_stddefs.h" + +/** \addtogroup Misc Miscellaneous APIs */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** The maximum number of active slaves in a piconet. */ +#define OI_BT_MAX_ACTIVE_SLAVES 7 + +/** the number of bytes in a Bluetooth device address (BD_ADDR) */ +#define OI_BD_ADDR_BYTE_SIZE 6 + +/** + * 48-bit Bluetooth device address + * + * Because 48-bit integers may not be supported on all platforms, the + * address is defined as an array of bytes. This array is big-endian, + * meaning that + * - array[0] contains bits 47-40, + * - array[1] contains bits 39-32, + * - array[2] contains bits 31-24, + * - array[3] contains bits 23-16, + * - array[4] contains bits 15-8, and + * - array[5] contains bits 7-0. + */ +typedef struct { + OI_UINT8 addr[OI_BD_ADDR_BYTE_SIZE] ; /**< Bluetooth device address represented as an array of 8-bit values */ +} OI_BD_ADDR ; + +/** + * @name Data types for working with UUIDs + * UUIDs are 16 bytes (128 bits). + * + * To avoid having to pass around 128-bit values all the time, 32-bit and 16-bit + * UUIDs are defined, along with a mapping from the shorter versions to the full + * version. + * + * @{ + */ + +/** + * 16-bit representation of a 128-bit UUID + */ +typedef OI_UINT16 OI_UUID16; + +/** + * 32-bit representation of a 128-bit UUID + */ +typedef OI_UINT32 OI_UUID32; + +/** + * number of bytes in a 128 bit UUID + */ +#define OI_BT_UUID128_SIZE 16 + +/** + * number of bytes in IPv6 style addresses + */ +#define OI_BT_IPV6ADDR_SIZE 16 + +/** + * type definition for a 128-bit UUID + * + * To simplify conversion between 128-bit UUIDs and 16-bit and 32-bit UUIDs, + * the most significant 32 bits are stored with the same endian-ness as is + * native on the target (local) device. The remainder of the 128-bit UUID is + * stored as bytes in big-endian order. + */ +typedef struct { + OI_UINT32 ms32bits; /**< most significant 32 bits of 128-bit UUID */ + OI_UINT8 base[OI_BT_UUID128_SIZE - sizeof(OI_UINT32)]; /**< remainder of 128-bit UUID, array of 8-bit values */ +} OI_UUID128; + +/** @} */ + +/** number of bytes in a link key */ +#define OI_BT_LINK_KEY_SIZE 16 + +/** + * type definition for a baseband link key + * + * Because 128-bit integers may not be supported on all platforms, we define + * link keys as an array of bytes. Unlike the Bluetooth device address, + * the link key is stored in little-endian order, meaning that + * - array[0] contains bits 0 - 7, + * - array[1] contains bits 8 - 15, + * - array[2] contains bits 16 - 23, + * - array[3] contains bits 24 - 31, + * - array[4] contains bits 32 - 39, + * - array[5] contains bits 40 - 47, + * - array[6] contains bits 48 - 55, + * - array[7] contains bits 56 - 63, + * - array[8] contains bits 64 - 71, + * - array[9] contains bits 72 - 79, + * - array[10] contains bits 80 - 87, + * - array[11] contains bits 88 - 95, + * - array[12] contains bits 96 - 103, + * - array[13] contains bits 104- 111, + * - array[14] contains bits 112- 119, and + * - array[15] contains bits 120- 127. + */ +typedef struct { + OI_UINT8 key[OI_BT_LINK_KEY_SIZE] ; /**< link key represented as an array of 8-bit values */ +} OI_LINK_KEY ; + + +/** Out-of-band data size - C and R values are 16-bytes each */ +#define OI_BT_OOB_NUM_BYTES 16 + +typedef struct { + OI_UINT8 value[OI_BT_OOB_NUM_BYTES] ; /**< same struct used for C and R values */ +} OI_OOB_DATA ; + + +/** + * link key types + */ +typedef enum { + OI_LINK_KEY_TYPE_COMBO = 0, /**< combination key */ + OI_LINK_KEY_TYPE_LOCAL_UNIT = 1, /**< local unit key */ + OI_LINK_KEY_TYPE_REMOTE_UNIT = 2, /**< remote unit key */ + OI_LINK_KEY_TYPE_DEBUG_COMBO = 3, /**< debug combination key */ + OI_LINK_KEY_TYPE_UNAUTHENTICATED = 4, /**< Unauthenticated */ + OI_LINK_KEY_TYPE_AUTHENTICATED = 5, /**< Authenticated */ + OI_LINK_KEY_TYPE_CHANGED_COMBO = 6 /**< Changed */ + +} OI_BT_LINK_KEY_TYPE ; + + +/** amount of space allocated for a PIN (personal indentification number) in bytes */ +#define OI_BT_PIN_CODE_SIZE 16 + +/** data type for a PIN (PINs are treated as strings, so endianness does not apply.) */ +typedef struct { + OI_UINT8 pin[OI_BT_PIN_CODE_SIZE] ; /**< PIN represented as an array of 8-bit values */ +} OI_PIN_CODE ; + +/** maximum number of SCO connections per device, which is 3 as of version 2.0+EDR + of the Bluetooth specification (see sec 4.3 of vol 2 part B) */ +#define OI_BT_MAX_SCO_CONNECTIONS 3 + +/** data type for clock offset */ +typedef OI_UINT16 OI_BT_CLOCK_OFFSET ; + +/** data type for a LM handle */ +typedef OI_UINT16 OI_HCI_LM_HANDLE; + +/** opaque data type for a SCO or ACL connection handle */ +typedef struct _OI_HCI_CONNECTION *OI_HCI_CONNECTION_HANDLE; + +/** data type for HCI Error Code, as defined in oi_hcispec.h */ +typedef OI_UINT8 OI_HCI_ERROR_CODE ; + +/** + * The Bluetooth device type is indicated by a 24-bit bitfield, represented as a + * 32-bit number in the stack. The bit layout and values for device class are specified + * in the file oi_bt_assigned_nos.h and in the Bluetooth "Assigned Numbers" specification + * at http://www.bluetooth.org/assigned-numbers/. + */ +typedef OI_UINT32 OI_BT_DEVICE_CLASS ; + +#define OI_BT_DEV_CLASS_FORMAT_MASK 0x000003 /**< Bits 0-1 contain format type. */ +#define OI_BT_DEV_CLASS_MINOR_DEVICE_MASK 0x0000FC /**< Bits 2-7 contain minor device class value. */ +#define OI_BT_DEV_CLASS_MAJOR_DEVICE_MASK 0x001F00 /**< Bits 8-12 contain major device class value. */ +#define OI_BT_DEV_CLASS_MAJOR_SERVICE_MASK 0xFFE000 /**< Bits 13-23 contain major service class value. */ + +/** There is currently only one device class format defined, type 00. */ +#define OI_BT_DEV_CLASS_FORMAT_TYPE 00 + +/** Bit 13 in device class indicates limited discoverability mode (GAP v2.0+EDR, section 4.1.2.2) */ +#define OI_BT_DEV_CLASS_LIMITED_DISCO_BIT BIT13 + +/** macro to test validity of the Device Class Format */ +#define OI_BT_VALID_DEVICE_CLASS_FORMAT(class) (OI_BT_DEV_CLASS_FORMAT_TYPE == ((class) & OI_BT_DEV_CLASS_FORMAT_MASK)) + +/** the time between baseband clock ticks, currently 625 microseconds (one slot) */ +#define OI_BT_TICK 625 +/** some macros to convert to/from baseband clock ticks - use no floating point! */ +#define OI_SECONDS_TO_BT_TICKS(secs) ((secs)*1600) +#define OI_BT_TICKS_TO_SECONDS(ticks) ((ticks)/1600) +#define OI_MSECS_TO_BT_TICKS(msecs) (((msecs)*8)/5) +#define OI_BT_TICKS_TO_MSECS(ticks) (((ticks)*5)/8) + +/** EIR byte order */ +#define OI_EIR_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER + + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +/*****************************************************************************/ +#endif /* _OI_BT_SPEC_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_codec_sbc.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_codec_sbc.h new file mode 100755 index 0000000000..ff5e6c10a2 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_codec_sbc.h @@ -0,0 +1,484 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#ifndef _OI_CODEC_SBC_CORE_H +#define _OI_CODEC_SBC_CORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** +@file +Declarations of codec functions, data types, and macros. + +@ingroup codec_lib +*/ + +/** +@addtogroup codec_lib +@{ +*/ + +/* Non-BM3 users of of the codec must include oi_codec_sbc_bm3defs.h prior to + * including this file, or else these includes will fail because the BM3 SDK is + * not in the include path */ +#ifndef _OI_CODEC_SBC_BM3DEFS_H +#include "oi_stddefs.h" +#include "oi_status.h" +#endif + +#include + +#define SBC_MAX_CHANNELS 2 +#define SBC_MAX_BANDS 8 +#define SBC_MAX_BLOCKS 16 +#define SBC_MIN_BITPOOL 2 /**< Minimum size of the bit allocation pool used to encode the stream */ +#define SBC_MAX_BITPOOL 250 /**< Maximum size of the bit allocation pool used to encode the stream */ +#define SBC_MAX_ONE_CHANNEL_BPS 320000 +#define SBC_MAX_TWO_CHANNEL_BPS 512000 + + +#define SBC_WBS_BITRATE 62000 +#define SBC_WBS_BITPOOL 27 +#define SBC_WBS_NROF_BLOCKS 16 +#define SBC_WBS_FRAME_LEN 62 +#define SBC_WBS_SAMPLES_PER_FRAME 128 + + +#define SBC_HEADER_LEN 4 +#define SBC_MAX_FRAME_LEN (SBC_HEADER_LEN + \ + ((SBC_MAX_BANDS * SBC_MAX_CHANNELS / 2) + \ + (SBC_MAX_BANDS + SBC_MAX_BLOCKS * SBC_MAX_BITPOOL + 7)/8)) +#define SBC_MAX_SAMPLES_PER_FRAME (SBC_MAX_BANDS * SBC_MAX_BLOCKS) + +#define SBC_MAX_SCALEFACTOR_BYTES ((4*(SBC_MAX_CHANNELS * SBC_MAX_BANDS) + 7)/8) + +#define OI_SBC_SYNCWORD 0x9c +#define OI_SBC_ENHANCED_SYNCWORD 0x9d + +/**@name Sampling frequencies */ +/**@{*/ +#define SBC_FREQ_16000 0 /**< The sampling frequency is 16 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_FREQ_32000 1 /**< The sampling frequency is 32 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_FREQ_44100 2 /**< The sampling frequency is 44.1 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_FREQ_48000 3 /**< The sampling frequency is 48 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */ +/**@}*/ + +/**@name Channel modes */ +/**@{*/ +#define SBC_MONO 0 /**< The mode of the encoded channel is mono. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_DUAL_CHANNEL 1 /**< The mode of the encoded channel is dual-channel. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_STEREO 2 /**< The mode of the encoded channel is stereo. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_JOINT_STEREO 3 /**< The mode of the encoded channel is joint stereo. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */ +/**@}*/ + +/**@name Subbands */ +/**@{*/ +#define SBC_SUBBANDS_4 0 /**< The encoded stream has 4 subbands. One possible value for the @a subbands parameter of OI_CODEC_SBC_EncoderConfigure()*/ +#define SBC_SUBBANDS_8 1 /**< The encoded stream has 8 subbands. One possible value for the @a subbands parameter of OI_CODEC_SBC_EncoderConfigure() */ +/**@}*/ + +/**@name Block lengths */ +/**@{*/ +#define SBC_BLOCKS_4 0 /**< A block size of 4 blocks was used to encode the stream. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_BLOCKS_8 1 /**< A block size of 8 blocks was used to encode the stream is. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_BLOCKS_12 2 /**< A block size of 12 blocks was used to encode the stream. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_BLOCKS_16 3 /**< A block size of 16 blocks was used to encode the stream. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */ +/**@}*/ + +/**@name Bit allocation methods */ +/**@{*/ +#define SBC_LOUDNESS 0 /**< The bit allocation method. One possible value for the @a loudness parameter of OI_CODEC_SBC_EncoderConfigure() */ +#define SBC_SNR 1 /**< The bit allocation method. One possible value for the @a loudness parameter of OI_CODEC_SBC_EncoderConfigure() */ +/**@}*/ + +/** +@} + +@addtogroup codec_internal +@{ +*/ + +typedef OI_INT16 SBC_BUFFER_T; + + +/** Used internally. */ +typedef struct { + OI_UINT16 frequency; /**< The sampling frequency. Input parameter. */ + OI_UINT8 freqIndex; + + OI_UINT8 nrof_blocks; /**< The block size used to encode the stream. Input parameter. */ + OI_UINT8 blocks; + + + OI_UINT8 nrof_subbands; /**< The number of subbands of the encoded stream. Input parameter. */ + OI_UINT8 subbands; + + OI_UINT8 mode; /**< The mode of the encoded channel. Input parameter. */ + OI_UINT8 nrof_channels; /**< The number of channels of the encoded stream. */ + + OI_UINT8 alloc; /**< The bit allocation method. Input parameter. */ + OI_UINT8 bitpool; /**< Size of the bit allocation pool used to encode the stream. Input parameter. */ + OI_UINT8 crc; /**< Parity check byte used for error detection. */ + OI_UINT8 join; /**< Whether joint stereo has been used. */ + OI_UINT8 enhanced; + OI_UINT8 min_bitpool; /**< This value is only used when encoding. SBC_MAX_BITPOOL if variable + bitpools are disallowed, otherwise the minimum bitpool size that will + be used by the bit allocator. */ + + OI_UINT8 cachedInfo; /**< Information about the previous frame */ +} OI_CODEC_SBC_FRAME_INFO; + +/** Used internally. */ +typedef struct { + const OI_CHAR *codecInfo; + OI_CODEC_SBC_FRAME_INFO frameInfo; + OI_INT8 scale_factor[SBC_MAX_CHANNELS*SBC_MAX_BANDS]; + OI_UINT32 frameCount; + OI_INT32 *subdata; + + SBC_BUFFER_T *filterBuffer[SBC_MAX_CHANNELS]; + OI_INT32 filterBufferLen; + OI_UINT filterBufferOffset; + + union { + OI_UINT8 uint8[SBC_MAX_CHANNELS*SBC_MAX_BANDS]; + OI_UINT32 uint32[SBC_MAX_CHANNELS*SBC_MAX_BANDS/4]; + } bits; + OI_UINT8 maxBitneed; /**< Running maximum bitneed */ + OI_BYTE formatByte; + OI_UINT8 pcmStride; + OI_UINT8 maxChannels; +} OI_CODEC_SBC_COMMON_CONTEXT; + + +/* + * A smaller value reduces RAM usage at the expense of increased CPU usage. Values in the range + * 27..50 are recommended, beyond 50 there is a diminishing return on reduced CPU usage. + */ +#define SBC_CODEC_MIN_FILTER_BUFFERS 16 +#define SBC_CODEC_FAST_FILTER_BUFFERS 27 + +/* Expands to the number of OI_UINT32s needed to ensure enough memory to encode + * or decode streams of numChannels channels, using numBuffers buffers. + * Example: + * OI_UINT32 decoderData[CODEC_DATA_WORDS(SBC_MAX_CHANNELS, SBC_DECODER_FAST_SYNTHESIS_BUFFERS)]; + * */ +#define CODEC_DATA_WORDS(numChannels, numBuffers) \ + ((\ + (sizeof(OI_INT32) * SBC_MAX_BLOCKS * numChannels * SBC_MAX_BANDS) \ + + (sizeof(SBC_BUFFER_T) * SBC_MAX_CHANNELS * SBC_MAX_BANDS * numBuffers) \ + + (sizeof (OI_UINT32) - 1) \ + ) / sizeof(OI_UINT32)) + +/** Opaque parameter to decoding functions; maintains decoder context. */ +typedef struct { + OI_CODEC_SBC_COMMON_CONTEXT common; + OI_UINT8 limitFrameFormat; /* Boolean, set by OI_CODEC_SBC_DecoderLimit() */ + OI_UINT8 restrictSubbands; + OI_UINT8 enhancedEnabled; + OI_UINT8 bufferedBlocks; +} OI_CODEC_SBC_DECODER_CONTEXT; + +typedef struct { + OI_UINT32 data[CODEC_DATA_WORDS(1, SBC_CODEC_FAST_FILTER_BUFFERS)]; +} OI_CODEC_SBC_CODEC_DATA_MONO; + +typedef struct { + OI_UINT32 data[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)]; +} OI_CODEC_SBC_CODEC_DATA_STEREO; + +/** +@} + +@addtogroup codec_lib +@{ +*/ + +/** + * This function resets the decoder. The context must be reset when + * changing streams, or if the following stream parameters change: + * number of subbands, stereo mode, or frequency. + * + * @param context Pointer to the decoder context structure to be reset. + * + * @param enhanced If true, enhanced SBC operation is enabled. If enabled, + * the codec will recognize the alternative syncword for + * decoding an enhanced SBC stream. Enhancements should not + * be enabled unless the stream is known to be generated + * by an enhanced encoder, or there is a small possibility + * for decoding glitches if synchronization were to be lost. + */ +OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_UINT32 *decoderData, + OI_UINT32 decoderDataBytes, + OI_UINT8 maxChannels, + OI_UINT8 pcmStride, + OI_BOOL enhanced); + +/** + * This function restricts the kind of SBC frames that the Decoder will + * process. Its use is optional. If used, it must be called after + * calling OI_CODEC_SBC_DecoderReset(). After it is called, any calls + * to OI_CODEC_SBC_DecodeFrame() with SBC frames that do not conform + * to the Subband and Enhanced SBC setting will be rejected with an + * OI_STATUS_INVALID_PARAMETERS return. + * + * @param context Pointer to the decoder context structure to be limited. + * + * @param enhanced If true, all frames passed to the decoder must be + * Enhanced SBC frames. If false, all frames must be + * standard SBC frames. + * + * @param subbands May be set to SBC_SUBBANDS_4 or SBC_SUBBANDS_8. All + * frames passed to the decoder must be encoded with + * the requested number of subbands. + * + */ +OI_STATUS OI_CODEC_SBC_DecoderLimit(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_BOOL enhanced, + OI_UINT8 subbands); + +/** + * This function sets the decoder parameters for a raw decode where the decoder parameters are not + * available in the sbc data stream. OI_CODEC_SBC_DecoderReset must be called + * prior to calling this function. + * + * @param context Decoder context structure. This must be the context must be + * used each time a frame is decoded. + * + * @param enhanced Set to TRUE to enable Qualcomm proprietary + * quality enhancements. + * + * @param frequency One of SBC_FREQ_16000, SBC_FREQ_32000, SBC_FREQ_44100, + * SBC_FREQ_48000 + * + * @param mode One of SBC_MONO, SBC_DUAL_CHANNEL, SBC_STEREO, + * SBC_JOINT_STEREO + * + * @param subbands One of SBC_SUBBANDS_4, SBC_SUBBANDS_8 + * + * @param blocks One of SBC_BLOCKS_4, SBC_BLOCKS_8, SBC_BLOCKS_12, + * SBC_BLOCKS_16 + * + * @param alloc One of SBC_LOUDNESS, SBC_SNR + * + * @param maxBitpool The maximum bitpool size for this context + */ +OI_STATUS OI_CODEC_SBC_DecoderConfigureRaw(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_BOOL enhanced, + OI_UINT8 frequency, + OI_UINT8 mode, + OI_UINT8 subbands, + OI_UINT8 blocks, + OI_UINT8 alloc, + OI_UINT8 maxBitpool); + +/** + * Decode one SBC frame. The frame has no header bytes. The context must have been previously + * initialized by calling OI_CODEC_SBC_DecoderConfigureRaw(). + * + * @param context Pointer to a decoder context structure. The same context + * must be used each time when decoding from the same stream. + * + * @param bitpool The actual bitpool size for this frame. Must be <= the maxbitpool specified + * in the call to OI_CODEC_SBC_DecoderConfigureRaw(), + * + * @param frameData Address of a pointer to the SBC data to decode. This + * value will be updated to point to the next frame after + * successful decoding. + * + * @param frameBytes Pointer to a UINT32 containing the number of available + * bytes of frame data. This value will be updated to reflect + * the number of bytes remaining after a decoding operation. + * + * @param pcmData Address of an array of OI_INT16 pairs, which will be + * populated with the decoded audio data. This address + * is not updated. + * + * @param pcmBytes Pointer to a UINT32 in/out parameter. On input, it + * should contain the number of bytes available for pcm + * data. On output, it will contain the number of bytes + * written. Note that this differs from the semantics of + * frameBytes. + */ +OI_STATUS OI_CODEC_SBC_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_UINT8 bitpool, + const OI_BYTE **frameData, + OI_UINT32 *frameBytes, + OI_INT16 *pcmData, + OI_UINT32 *pcmBytes); + +/** + * Decode one SBC frame. + * + * @param context Pointer to a decoder context structure. The same context + * must be used each time when decoding from the same stream. + * + * @param frameData Address of a pointer to the SBC data to decode. This + * value will be updated to point to the next frame after + * successful decoding. + * + * @param frameBytes Pointer to a UINT32 containing the number of available + * bytes of frame data. This value will be updated to reflect + * the number of bytes remaining after a decoding operation. + * + * @param pcmData Address of an array of OI_INT16 pairs, which will be + * populated with the decoded audio data. This address + * is not updated. + * + * @param pcmBytes Pointer to a UINT32 in/out parameter. On input, it + * should contain the number of bytes available for pcm + * data. On output, it will contain the number of bytes + * written. Note that this differs from the semantics of + * frameBytes. + */ +OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, + const OI_BYTE **frameData, + OI_UINT32 *frameBytes, + OI_INT16 *pcmData, + OI_UINT32 *pcmBytes); + +/** + * Calculate the number of SBC frames but don't decode. CRC's are not checked, + * but the Sync word is found prior to count calculation. + * + * @param frameData Pointer to the SBC data. + * + * @param frameBytes Number of bytes avaiable in the frameData buffer + * + */ +OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData, + OI_UINT32 frameBytes); + +/** + * Analyze an SBC frame but don't do the decode. + * + * @param context Pointer to a decoder context structure. The same context + * must be used each time when decoding from the same stream. + * + * @param frameData Address of a pointer to the SBC data to decode. This + * value will be updated to point to the next frame after + * successful decoding. + * + * @param frameBytes Pointer to a UINT32 containing the number of available + * bytes of frame data. This value will be updated to reflect + * the number of bytes remaining after a decoding operation. + * + */ +OI_STATUS OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, + const OI_BYTE **frameData, + OI_UINT32 *frameBytes); + +/* Common functions */ + +/** + Calculate the frame length. + + @param frame The frame whose length to calculate + + @return the length of an individual encoded frame in + bytes + */ +OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame); + + +/** + * Calculate the maximum bitpool size that fits within a given frame length. + * + * @param frame The frame to calculate the bitpool size for + * @param frameLen The frame length to fit the bitpool to + * + * @return the maximum bitpool that will fit in the specified frame length + */ +OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame, + OI_UINT16 frameLen); + +/** + Calculate the bit rate. + + @param frame The frame whose bit rate to calculate + + @return the approximate bit rate in bits per second, + assuming that stream parameters are constant + */ +OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame); + +/** + Calculate decoded audio data length for one frame. + + @param frame The frame whose audio data length to calculate + + @return length of decoded audio data for a + single frame, in bytes + */ +OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common); + +/** + * Get the codec version text. + * + * @return pointer to text string containing codec version text + * + */ +OI_CHAR *OI_CODEC_Version(void); + + +/** +@} + +@addtogroup codec_internal +@{ +*/ + +extern const OI_CHAR* const OI_CODEC_SBC_FreqText[]; +extern const OI_CHAR* const OI_CODEC_SBC_ModeText[]; +extern const OI_CHAR* const OI_CODEC_SBC_SubbandsText[]; +extern const OI_CHAR* const OI_CODEC_SBC_BlocksText[]; +extern const OI_CHAR* const OI_CODEC_SBC_AllocText[]; + +/** +@} + +@addtogroup codec_lib +@{ +*/ + +#ifdef OI_DEBUG +void OI_CODEC_SBC_DumpConfig(OI_CODEC_SBC_FRAME_INFO *frameInfo); +#else +#define OI_CODEC_SBC_DumpConfig(f) +#endif + +/** +@} +*/ + +#ifdef __cplusplus +} +#endif + + +#endif /* _OI_CODEC_SBC_CORE_H */ + + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_codec_sbc_private.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_codec_sbc_private.h new file mode 100755 index 0000000000..d7489e7766 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_codec_sbc_private.h @@ -0,0 +1,229 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_CODEC_SBC_PRIVATE_H +#define _OI_CODEC_SBC_PRIVATE_H + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +/** +@file +Function prototypes and macro definitions used internally by the codec. + +@ingroup codec_internal +*/ + +/** +@addtogroup codec_internal +@{ +*/ + +#ifdef USE_RESTRICT_KEYWORD +#define RESTRICT restrict +#else +#define RESTRICT +#endif + +#ifdef CODEC_DEBUG +#include +#define ERROR(x) do { printf x; printf("\n"); } while (0) +#else +#define ERROR(x) +#endif + +#ifdef TRACE_EXECUTION +#define TRACE(x) do { printf x; printf("\n"); } while (0) +#else +#define TRACE(x) +#endif + +#ifndef PRIVATE +#define PRIVATE +#endif + +#ifndef INLINE +#define INLINE +#endif + +#include "oi_assert.h" +#include "oi_codec_sbc.h" + +#ifndef OI_SBC_SYNCWORD +#define OI_SBC_SYNCWORD 0x9c +#endif + +#ifndef DIVIDE +#define DIVIDE(a, b) ((a) / (b)) +#endif + +typedef union { + OI_UINT8 uint8[SBC_MAX_BANDS]; + OI_UINT32 uint32[SBC_MAX_BANDS / 4]; +} BITNEED_UNION1; + +typedef union { + OI_UINT8 uint8[2 * SBC_MAX_BANDS]; + OI_UINT32 uint32[2 * SBC_MAX_BANDS / 4]; +} BITNEED_UNION2; + +static const OI_UINT16 freq_values[] = { 16000, 32000, 44100, 48000 }; +static const OI_UINT8 block_values[] = { 4, 8, 12, 16 }; +static const OI_UINT8 channel_values[] = { 1, 2, 2, 2 }; +static const OI_UINT8 band_values[] = { 4, 8 }; + + +#define TEST_MODE_SENTINEL "OINA" +#define TEST_MODE_SENTINEL_LENGTH 4 + +/** Used internally. */ +typedef struct { + union { + const OI_UINT8 *r; + OI_UINT8 *w; + } ptr; + OI_UINT32 value; + OI_UINT bitPtr; +} OI_BITSTREAM; + + +#define VALID_INT16(x) (((x) >= OI_INT16_MIN) && ((x) <= OI_INT16_MAX)) +#define VALID_INT32(x) (((x) >= OI_INT32_MIN) && ((x) <= OI_INT32_MAX)) + +#define DCTII_8_SHIFT_IN 0 +#define DCTII_8_SHIFT_OUT 16-DCTII_8_SHIFT_IN + +#define DCTII_8_SHIFT_0 (DCTII_8_SHIFT_OUT) +#define DCTII_8_SHIFT_1 (DCTII_8_SHIFT_OUT) +#define DCTII_8_SHIFT_2 (DCTII_8_SHIFT_OUT) +#define DCTII_8_SHIFT_3 (DCTII_8_SHIFT_OUT) +#define DCTII_8_SHIFT_4 (DCTII_8_SHIFT_OUT) +#define DCTII_8_SHIFT_5 (DCTII_8_SHIFT_OUT) +#define DCTII_8_SHIFT_6 (DCTII_8_SHIFT_OUT-1) +#define DCTII_8_SHIFT_7 (DCTII_8_SHIFT_OUT-2) + +#define DCT_SHIFT 15 + +#define DCTIII_4_SHIFT_IN 2 +#define DCTIII_4_SHIFT_OUT 15 + +#define DCTIII_8_SHIFT_IN 3 +#define DCTIII_8_SHIFT_OUT 14 + +OI_UINT computeBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common, + OI_UINT8 *bitneeds, + OI_UINT ch, + OI_UINT *preferredBitpool); + +void oneChannelBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common, + BITNEED_UNION1 *bitneeds, + OI_UINT ch, + OI_UINT bitcount); + + +OI_INT adjustToFitBitpool(const OI_UINT bitpool, + OI_UINT32 *bitneeds, + const OI_UINT subbands, + OI_UINT bitcount, + OI_UINT *excess); + +INLINE OI_INT allocAdjustedBits(OI_UINT8 *dest, + OI_INT bits, + OI_INT excess); + +INLINE OI_INT allocExcessBits(OI_UINT8 *dest, + OI_INT excess); + +PRIVATE OI_UINT32 internal_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame); + +PRIVATE OI_UINT16 internal_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame); + +void monoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common); + +typedef void (*BIT_ALLOC)(OI_CODEC_SBC_COMMON_CONTEXT *common); + +PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_UINT8 bitpool, + const OI_BYTE **frameData, + OI_UINT32 *frameBytes, + OI_INT16 *pcmData, + OI_UINT32 *pcmBytes); + +INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_UINT32 *decoderData, + OI_UINT32 decoderDataBytes, + OI_BYTE maxChannels, + OI_BYTE pcmStride, + OI_BOOL enhanced); + +INLINE OI_UINT16 OI_SBC_CalculateFrameAndHeaderlen(OI_CODEC_SBC_FRAME_INFO *frame, OI_UINT *headerLen_); + +PRIVATE OI_UINT32 OI_SBC_MaxBitpool(OI_CODEC_SBC_FRAME_INFO *frame); + +PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *frame); +PRIVATE OI_UINT8 OI_SBC_CalculateChecksum(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data); + +/* Transform functions */ +PRIVATE void shift_buffer(SBC_BUFFER_T *dest, SBC_BUFFER_T *src, OI_UINT wordCount); +PRIVATE void cosineModulateSynth4(SBC_BUFFER_T * RESTRICT out, OI_INT32 const * RESTRICT in); +PRIVATE void SynthWindow40_int32_int32_symmetry_with_sum(OI_INT16 *pcm, SBC_BUFFER_T buffer[80], OI_UINT strideShift); + +INLINE void dct3_4(OI_INT32 * RESTRICT out, OI_INT32 const * RESTRICT in); +PRIVATE void analyze4_generated(SBC_BUFFER_T analysisBuffer[RESTRICT 40], + OI_INT16 *pcm, + OI_UINT strideShift, + OI_INT32 subband[4]); + +INLINE void dct3_8(OI_INT32 * RESTRICT out, OI_INT32 const * RESTRICT in); + +PRIVATE void analyze8_generated(SBC_BUFFER_T analysisBuffer[RESTRICT 80], + OI_INT16 *pcm, + OI_UINT strideShift, + OI_INT32 subband[8]); + +#ifdef SBC_ENHANCED +PRIVATE void analyze8_enhanced_generated(SBC_BUFFER_T analysisBuffer[RESTRICT 112], + OI_INT16 *pcm, + OI_UINT strideShift, + OI_INT32 subband[8]); +#endif + +/* Decoder functions */ + +INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data); +PRIVATE void OI_SBC_ReadScalefactors(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *b, OI_BITSTREAM *bs); +PRIVATE void OI_SBC_ReadSamples(OI_CODEC_SBC_DECODER_CONTEXT *common, OI_BITSTREAM *ob); +PRIVATE void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT *common, OI_BITSTREAM *global_bs); +PRIVATE void OI_SBC_SynthFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT start_block, OI_UINT nrof_blocks); +INLINE OI_INT32 OI_SBC_Dequant(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits); +PRIVATE OI_BOOL OI_SBC_ExamineCommandPacket(OI_CODEC_SBC_DECODER_CONTEXT *context, const OI_BYTE *data, OI_UINT32 len); +PRIVATE void OI_SBC_GenerateTestSignal(OI_INT16 pcmData[][2], OI_UINT32 sampleCount); + +PRIVATE void OI_SBC_ExpandFrameFields(OI_CODEC_SBC_FRAME_INFO *frame); +PRIVATE OI_STATUS OI_CODEC_SBC_Alloc(OI_CODEC_SBC_COMMON_CONTEXT *common, + OI_UINT32 *codecDataAligned, + OI_UINT32 codecDataBytes, + OI_UINT8 maxChannels, + OI_UINT8 pcmStride); +/** +@} +*/ + +#endif /* _OI_CODEC_SBC_PRIVATE_H */ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_common.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_common.h new file mode 100755 index 0000000000..c4169f932c --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_common.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_COMMON_H +#define _OI_COMMON_H +/** + * @file + * + * This file is used to group commonly used BLUEmagic 3.0 software + * header files. + * + * This file should be included in application source code along with the header + * files for the specific modules of the protocol stack being used. + */ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#include "oi_bt_spec.h" +#include "oi_stddefs.h" +#include "oi_status.h" +#include "oi_time.h" +#include "oi_osinterface.h" + + +/*****************************************************************************/ +#endif /* _OI_COMMON_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_cpu_dep.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_cpu_dep.h new file mode 100755 index 0000000000..da7473acdb --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_cpu_dep.h @@ -0,0 +1,505 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_CPU_DEP_H +#define _OI_CPU_DEP_H +/** + * @file + * This file contains definitions for characteristics of the target CPU and + * compiler, including primitive data types and endianness. + * + * This file defines the byte order and primitive data types for various + * CPU families. The preprocessor symbol 'CPU' must be defined to be an + * appropriate value or this header will generate a compile-time error. + * + * @note The documentation for this header file uses the x86 family of processors + * as an illustrative example for CPU/compiler-dependent data type definitions. + * Go to the source code of this header file to see the details of primitive type + * definitions for each platform. + * + * Additional information is available in the @ref data_types_docpage section. + */ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup Misc Miscellaneous APIs */ +/**@{*/ + +/** @name Definitions indicating family of target OI_CPU_TYPE + * @{ + */ + +#define OI_CPU_X86 1 /**< x86 processor family */ +#define OI_CPU_ARM 2 /**< ARM processor family. + @deprecated Use #OI_CPU_ARM7_LEND or + #OI_CPU_ARM7_BEND. */ +#define OI_CPU_ARC 3 /**< ARC processor family. + @deprecated Use #OI_CPU_ARC_LEND or + #OI_CPU_ARC_BEND. */ +#define OI_CPU_SH3 4 /**< Hitachi SH-3 processor family */ +#define OI_CPU_H8 5 /**< Hitachi H8 processor family */ +#define OI_CPU_MIPS 6 /**< MIPS processor family */ +#define OI_CPU_SPARC 7 /**< SPARC processor family */ +#define OI_CPU_M68000 8 /**< Motorola M68000 processor family */ +#define OI_CPU_PPC 9 /**< PowerPC (PPC) processor family */ +#define OI_CPU_SH4_7750 10 /**< Hitachi SH7750 series in SH-4 processor family */ +#define OI_CPU_SH2 11 /**< Hitachi SH-2 processor family */ +#define OI_CPU_ARM7_LEND 12 /**< ARM7, little-endian */ +#define OI_CPU_ARM7_BEND 13 /**< ARM7, big-endian */ +#define OI_CPU_GDM1202 14 /**< GCT GDM1202 */ +#define OI_CPU_ARC_LEND 15 /**< ARC processor family, little-endian */ +#define OI_CPU_ARC_BEND 16 /**< ARC processor family, big-endian */ +#define OI_CPU_M30833F 17 /**< Mitsubishi M308 processor family */ +#define OI_CPU_CR16C 18 /**< National Semiconductor 16 bit processor family */ +#define OI_CPU_M64111 19 /**< Renesas M64111 processor (M32R family) */ +#define OI_CPU_ARMV5_LEND 20 //*< ARM5, little-endian */ + +#define OI_CPU_TYPE 12 + +#ifndef OI_CPU_TYPE + #error "OI_CPU_TYPE type not defined" +#endif + +/**@}*/ + + +/** @name Definitions indicating byte-wise endianness of target CPU + * @{ + */ + +#define OI_BIG_ENDIAN_BYTE_ORDER 0 /**< Multiple-byte values are stored in memory beginning with the most significant byte at the lowest address. */ +#define OI_LITTLE_ENDIAN_BYTE_ORDER 1 /**< Multiple-byte values are stored in memory beginning with the least significant byte at the lowest address. */ + +/**@}*/ + + +/** @name CPU/compiler-independent primitive data type definitions + * @{ + */ + +typedef int OI_BOOL; /**< Boolean values use native integer data type for target CPU. */ +typedef int OI_INT; /**< Integer values use native integer data type for target CPU. */ +typedef unsigned int OI_UINT; /**< Unsigned integer values use native unsigned integer data type for target CPU. */ +typedef unsigned char OI_BYTE; /**< Raw bytes type uses native character data type for target CPU. */ + +/**@}*/ + + + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_X86 + +#define OI_CPU_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER /**< x86 platform byte ordering is little-endian */ + +/** @name CPU/compiler-dependent primitive data type definitions for x86 processor family + * @{ + */ +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for x86 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for x86 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for x86 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for x86 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for x86 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for x86 processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_ARM +/* This CPU type is deprecated (removed from use). Instead, use OI_CPU_ARM7_LEND or OI_CPU_ARM7_BEND for + little-endian or big-endian configurations of the ARM7, respectively. */ +#error OI_CPU_ARM is deprecated +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_ARC +/* This CPU type is deprecated (removed from use). Instead, use OI_CPU_ARC_LEND or OI_CPU_ARC_BEND for + little-endian or big-endian configurations of the ARC, respectively. */ +#error OI_CPU_ARC is deprecated +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_SH3 +/* The Hitachi SH C compiler defines _LIT or _BIG, depending on the endianness + specified to the compiler on the command line. */ +#if defined(_LIT) + #define OI_CPU_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER /**< If _LIT is defined, SH-3 platform byte ordering is little-endian. */ +#elif defined(_BIG) + #define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER /**< If _BIG is defined, SH-3 platform byte ordering is big-endian. */ +#else + #error SH compiler endianness undefined +#endif + +/** @name CPU/compiler-dependent primitive data type definitions for SH-3 processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for SH-3 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for SH-3 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for SH-3 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for SH-3 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for SH-3 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for SH-3 processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_SH2 + +#define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER /**< SH-2 platform byte ordering is big-endian. */ + +/** @name CPU/compiler-dependent primitive data type definitions for SH-2 processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for SH-2 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for SH-2 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for SH-2 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for SH-2 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for SH-2 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for SH-2 processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_H8 +#define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER +#error basic types not defined +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_MIPS +#define OI_CPU_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER +/** @name CPU/compiler-dependent primitive data type definitions for MIPS processor family + * @{ + */ +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for ARM7 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for ARM7 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for ARM7 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for ARM7 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for ARM7 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for ARM7 processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_SPARC +#define OI_CPU_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER +#error basic types not defined +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_M68000 +#define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER /**< M68000 platform byte ordering is big-endian. */ + +/** @name CPU/compiler-dependent primitive data type definitions for M68000 processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for M68000 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for M68000 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for M68000 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for M68000 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for M68000 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for M68000 processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_PPC +#define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER + + +/** @name CPU/compiler-dependent primitive data type definitions for PPC 8XX processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for PPC8XX processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for PPC8XX processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for PPC8XX processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for PPC8XX processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for PPC8XX processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for PPC8XX processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_SH4_7750 +#define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER /**< SH7750 platform byte ordering is big-endian. */ + +/** @name CPU/compiler-dependent primitive data type definitions for SH7750 processor series of the SH-4 processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for SH7750 SH-4 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for SH7750 SH-4 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for SH7750 SH-4 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for SH7750 SH-4 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for SH7750 SH-4 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for SH7750 SH-4 processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_ARM7_LEND +#define OI_CPU_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER + +/** @name little-endian CPU/compiler-dependent primitive data type definitions for the ARM7 processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for ARM7 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for ARM7 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for ARM7 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for ARM7 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for ARM7 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for ARM7 processor. */ + +typedef void * OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_ARM7_BEND +#define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER +/** @name big-endian CPU/compiler-dependent primitive data type definitions for the ARM7 processor family + * @{ + */ +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for ARM7 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for ARM7 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for ARM7 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for ARM7 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for ARM7 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for ARM7 processor. */ + +typedef void * OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_GDM1202 +#define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER + +typedef signed char OI_INT8; /**< 8-bit signed integer. */ +typedef signed short OI_INT16; /**< 16-bit signed integer. */ +typedef signed long OI_INT32; /**< 32-bit signed integer. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_ARC_LEND + +#define OI_CPU_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER + +/** @name CPU/compiler-dependent primitive data type definitions for ARC processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for ARC processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for ARC processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for ARC processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for ARC processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for ARC processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for ARC processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_ARC_BEND + +#define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER + +/** @name CPU/compiler-dependent primitive data type definitions for ARC processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for ARC processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for ARC processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for ARC processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for ARC processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for ARC processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for ARC processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_M30833F + +#define OI_CPU_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER + +/** @name CPU/compiler-dependent primitive data type definitions for Mitsubishi M308 processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for M308 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for M308 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for M308 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for M308 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for M308 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for M308 processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_CR16C + +#define OI_CPU_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER + +/** @name CPU/compiler-dependent primitive data type definitions for National Semicnductor processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for CR16C processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for CR16C processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for CR16C processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for CR16C processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for CR16C processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for CR16C processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_M64111 + +#define OI_CPU_BYTE_ORDER OI_BIG_ENDIAN_BYTE_ORDER + +/** @name CPU/compiler-dependent primitive data type definitions for Renesas M32R processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for M64111 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for M64111 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for M64111 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for M64111 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for M64111 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for M64111 processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ +#endif + +/*********************************************************************************/ + +#if OI_CPU_TYPE==OI_CPU_ARMV5_LEND +#define OI_CPU_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER + +/** @name little-endian CPU/compiler-dependent primitive data type definitions for the ARM7 processor family + * @{ + */ + +typedef signed char OI_INT8; /**< 8-bit signed integer values use native signed character data type for ARM7 processor. */ +typedef signed short OI_INT16; /**< 16-bit signed integer values use native signed short integer data type for ARM7 processor. */ +typedef signed long OI_INT32; /**< 32-bit signed integer values use native signed long integer data type for ARM7 processor. */ +typedef unsigned char OI_UINT8; /**< 8-bit unsigned integer values use native unsigned character data type for ARM7 processor. */ +typedef unsigned short OI_UINT16; /**< 16-bit unsigned integer values use native unsigned short integer data type for ARM7 processor. */ +typedef unsigned long OI_UINT32; /**< 32-bit unsigned integer values use native unsigned long integer data type for ARM7 processor. */ + +typedef OI_UINT32 OI_ELEMENT_UNION; /**< Type for first element of a union to support all data types up to pointer width. */ + +/**@}*/ + +#endif + +/*********************************************************************************/ + + +#ifndef OI_CPU_BYTE_ORDER + #error "Byte order (endian-ness) not defined" +#endif + + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +/*********************************************************************************/ +#endif /* _OI_CPU_DEP_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_modules.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_modules.h new file mode 100755 index 0000000000..a0b68dd09f --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_modules.h @@ -0,0 +1,171 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_MODULES_H +#define _OI_MODULES_H +/** + * @file + * + * Enumeration type defining the inidivual stack components. + * + */ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + + +/** \addtogroup Misc Miscellaneous APIs */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * This enumeration lists constants for referencing the components of + * the BLUEmagic 3.0 protocol stack, profiles, and other functionalities. + * + * In order to distinguish types of modules, items are grouped with markers to + * delineate start and end of the groups + * + * The module type is used for various purposes: + * identification in debug print statements + * access to initialization flags + * access to the configuration table + */ + +typedef enum { + /* profiles and protocols --> Updates to oi_debug.c and oi_config_table.c */ + + /* XX --> Keep Enum values up-to-date! */ + OI_MODULE_AT, /**< 00 AT command processing */ + OI_MODULE_A2DP, /**< 01 Advanced Audio Distribution Profile */ + OI_MODULE_AVCTP, /**< 02 Audio-Visual Control Transport Profile */ + OI_MODULE_AVDTP, /**< 03 Audio-Visual Distribution Protocol */ + OI_MODULE_AVRCP, /**< 04 Audio-Visual Remote Control Profile */ + OI_MODULE_BIP_CLI, /**< 05 Basic Imaging Profile protocol client */ + OI_MODULE_BIP_SRV, /**< 06 Basic Imaging Profile protocol server */ + OI_MODULE_BNEP, /**< 07 Bluetooth Network Encapsulation Protocol */ + OI_MODULE_BPP_SENDER, /**< 08 Basic Printing Profile */ + OI_MODULE_BPP_PRINTER, /**< 09 Basic Printing Profile */ + OI_MODULE_CTP, /**< 10 Cordless Telephony Profile */ + OI_MODULE_DUN, /**< 11 Dial-Up Networking Profile */ + OI_MODULE_FAX, /**< 12 Fax Profile */ + OI_MODULE_FTP_CLI, /**< 13 File Transfer Profile protocol client */ + OI_MODULE_FTP_SRV, /**< 14 File Transfer Profile protocol server */ + OI_MODULE_HANDSFREE, /**< 15 Hands-Free Profile */ + OI_MODULE_HANDSFREE_AG, /**< 16 Hands-Free Profile */ + OI_MODULE_HCRP_CLI, /**< 17 Hardcopy Cable Replacement Profile */ + OI_MODULE_HCRP_SRV, /**< 18 Hardcopy Cable Replacement Profile */ + OI_MODULE_HEADSET, /**< 19 Headset Profile */ + OI_MODULE_HEADSET_AG, /**< 20 Headset Profile */ + OI_MODULE_HID, /**< 21 Human Interface Device profile */ + OI_MODULE_INTERCOM, /**< 22 Intercom Profile */ + OI_MODULE_OBEX_CLI, /**< 23 OBEX protocol client, Generic Object Exchange Profile */ + OI_MODULE_OBEX_SRV, /**< 24 OBEX protocol server, Generic Object Exchange Profile */ + OI_MODULE_OPP_CLI, /**< 25 Object Push Profile protocol client */ + OI_MODULE_OPP_SRV, /**< 26 Object Push Profile protocol server */ + OI_MODULE_PAN, /**< 27 PAN profile */ + OI_MODULE_PBAP_CLI, /**< 28 Phonebook Access Profile client */ + OI_MODULE_PBAP_SRV, /**< 29 Phonebook Access Profile server */ + OI_MODULE_SAP_CLI, /**< 30 SIM Access Profile */ + OI_MODULE_SAP_SRV, /**< 31 SIM Access Profile */ + OI_MODULE_SPP, /**< 32 Serial Port Profile */ + OI_MODULE_SYNC_CLI, /**< 33 Synchronization Profile */ + OI_MODULE_SYNC_SRV, /**< 34 Synchronization Profile */ + OI_MODULE_SYNC_CMD_CLI, /**< 35 Synchronization Profile */ + OI_MODULE_SYNC_CMD_SRV, /**< 36 Synchronization Profile */ + OI_MODULE_SYNCML, /**< 37 SyncML Profile */ + OI_MODULE_TCS, /**< 38 TCS Binary */ + OI_MODULE_VDP, /**< 39 Video Distribution Profile */ + + /* corestack components --> Updates to oi_debug.c and oi_config_table.c */ + + OI_MODULE_COMMON_CONFIG, /**< 40 Common configuration, module has no meaning other than for config struct */ + OI_MODULE_CMDCHAIN, /**< 41 Command chaining utility */ + OI_MODULE_DISPATCH, /**< 42 Dispatcher */ + OI_MODULE_DATAELEM, /**< 43 Data Elements, marshaller */ + OI_MODULE_DEVMGR, /**< 44 Device Manager */ + OI_MODULE_DEVMGR_MODES, /**< 45 Device Manager connectability/discoverability modes */ + OI_MODULE_HCI, /**< 46 Host Controller Interface command layer */ + OI_MODULE_L2CAP, /**< 47 L2CAP */ + OI_MODULE_MEMMGR, /**< 48 modules that do memory management */ + OI_MODULE_POLICYMGR, /**< 49 Policy Manager */ + OI_MODULE_RFCOMM, /**< 50 RFCOMM */ + OI_MODULE_RFCOMM_SD, /**< 51 RFCOMM Service discovery */ + OI_MODULE_SDP_CLI, /**< 52 Service Discovery Protocol client */ + OI_MODULE_SDP_SRV, /**< 53 Service Discovery Protocol server */ + OI_MODULE_SDPDB, /**< 54 Service Discovery Protocol database */ + OI_MODULE_SECMGR, /**< 55 Security Manager */ + OI_MODULE_SNIFFLOG, /**< 56 sniff log */ + OI_MODULE_SUPPORT, /**< 57 support functions, including CThru Dispatcher, time functions, and stack initialization */ + OI_MODULE_TRANSPORT, /**< 58 transport layer between HCI command layer and driver */ + OI_MODULE_TEST, /**< 59 used to debug output from internal test programs */ + OI_MODULE_XML, /**< 60 XML/CSS parser */ + + OI_MODULE_DI, /**< 61 Device Identification Profile */ + + // bhapi components --> Updates to oi_debug.c + + OI_MODULE_BHAPI, /**< 62 BLUEmagic Host API generic */ + OI_MODULE_BHCLI, /**< 63 BLUEmagic Host API client side */ + OI_MODULE_BHSRV, /**< 64 BLUEmagic Host API server side */ + OI_MODULE_MSGQ, /**< 65 module that handles message queuing */ + OI_MODULE_BHAPI_TRANSPORT, /**< 66 module that handles message queuing */ + OI_MODULE_BLST_SRV, /**< 67 module that provides server side BHAPI Lightweight Serial Transport */ + OI_MODULE_BLST_CLI, /**< 68 module that provides client side BHAPI Lightweight Serial Transport */ + + // OEM files --> Updates to oi_debug.c + OI_MODULE_OEM, /**< 69 Application Memory allocation */ + + // Application glue --> Updates to oi_debug.c + OI_MODULE_APP, /**< 70 Application Memory allocation */ + + /* various pieces of code depend on these last 2 elements occuring in a specific order: + OI_MODULE_ALL must be the 2nd to last element + OI_MODULE_UNKNOWN must be the last element + */ + OI_MODULE_ALL, /**< 71 special value identifying all modules - used for control of debug print statements */ + OI_MODULE_UNKNOWN /**< 72 special value - used for debug print statements */ +} OI_MODULE; + +/** + * This constant is the number of actual modules in the list. ALL and UNKNOWN are + * special values that are not actually modules. + * Used for debug print and memmgr profiling + */ +#define OI_NUM_MODULES OI_MODULE_ALL + + +/** + * This constant is the number of profile and core components. It is used to size + * the initialization and configuration tables. + */ +#define OI_NUM_STACK_MODULES OI_MODULE_BHAPI + + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif /* _OI_MODULES_H */ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_osinterface.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_osinterface.h new file mode 100755 index 0000000000..7868041900 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_osinterface.h @@ -0,0 +1,197 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_OSINTERFACE_H +#define _OI_OSINTERFACE_H +/** + @file + * This file provides the platform-independent interface for functions for which + * implementation is platform-specific. + * + * The functions in this header file define the operating system or hardware + * services needed by the BLUEmagic 3.0 protocol stack. The + * actual implementation of these services is platform-dependent. + * + */ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#include "oi_stddefs.h" +#include "oi_time.h" +#include "oi_status.h" +#include "oi_modules.h" + +/** \addtogroup Misc Miscellaneous APIs */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Terminates execution. + * + * @param reason Reason for termination + */ +void OI_FatalError(OI_STATUS reason); + +/** + * This function logs an error. + * + * When built for release mode, BLUEmagic 3 errors are logged to + * this function. (in debug mode, errors are logged via + * OI_Print()). + * + * @param module Module in which the error was detected (see + * oi_modules.h) + * @param lineno Line number of the C file OI_SLOG_ERROR called + * @param status Status code associated with the error event + */ +void OI_LogError(OI_MODULE module, OI_INT lineno, OI_STATUS status); + +/** + * This function initializes the debug code handling. + * + * When built for debug mode, this function performs platform + * dependent initialization to handle message codes passed in + * via OI_SetMsgCode(). + */ +void OI_InitDebugCodeHandler(void); + + +/** + * This function reads the time from the real time clock. + * + * All timing in BM3 is relative, typically a granularity + * of 5 or 10 msecs is adequate. + * + * @param[out] now Pointer to the buffer to which the current + * time will be returned + */ +void OI_Time_Now(OI_TIME *now); + +/** + * This function causes the current thread to sleep for the + * specified amount of time. This function must be called + * without the stack access token. + * + * @note BM3 corestack and profiles never suspend and never call + * OI_Sleep. The use of OI_Sleep is limited to applications and + * platform-specific code. + * + * If your port and applications never use OI_Sleep, this function can be left unimplemented. + * + * @param milliseconds Number of milliseconds to sleep + */ +void OI_Sleep(OI_UINT32 milliseconds); + + +/** + * Defines for message type codes. + */ +#define OI_MSG_CODE_APPLICATION 0 /**< Application output */ +#define OI_MSG_CODE_ERROR 1 /**< Error message output */ +#define OI_MSG_CODE_WARNING 2 /**< Warning message output */ +#define OI_MSG_CODE_TRACE 3 /**< User API function trace output */ +#define OI_MSG_CODE_PRINT1 4 /**< Catagory 1 debug print output */ +#define OI_MSG_CODE_PRINT2 5 /**< Catagory 2 debug print output */ +#define OI_MSG_CODE_HEADER 6 /**< Error/Debug output header */ + +/** + * This function is used to indicate the type of text being output with + * OI_Print(). For the Linux and Win32 platforms, it will set + * the color of the text. Other possible uses could be to insert + * HTML style tags, add some other message type indication, or + * be completely ignored altogether. + * + * @param code OI_MSG_CODE_* indicating setting the message type. + */ +void OI_SetMsgCode(OI_UINT8 code); + +/** + * All output from OI_Printf() and all debug output is sent to OI_Print. + * Typically, if the platform has a console, OI_Print() is sent to stdout. + * Embedded platforms typically send OI_Print() output to a serial port. + * + * @param str String to print + */ +void OI_Print(OI_CHAR const *str); + +/** + * In cases where OI_Print() is sending output to a logfile in addition to console, + * it is desirable to also put console input into the logfile. + * This function can be called by the console input process. + * + * @note This is an optional API which is strictly + * between the platform-specific stack_console and osinterface + * modules. This API need only be implemented on those + * platforms where is serves a useful purpose, e.g., win32. + * + * @param str Console input string + */ + +void OI_Print_ConsoleInput(OI_CHAR const *str); + +/** + * This function computes the CRC16 of the program image. + */ +OI_UINT16 OI_ProgramImageCRC16(void); + +/** + * Writes an integer to stdout in hex. This macro is intended + * for selective use when debugging in small memory + * configurations or other times when it is not possible to use + * OI_DBGPRINT. + * + * @param n the integer to print + */ + +#define OI_Print_Int(n) \ +{ \ + static const OI_CHAR _digits[] = "0123456789ABCDEF"; \ + OI_CHAR _buf[9]; \ + OI_CHAR *_str = &_buf[8]; \ + OI_UINT32 _i = n; \ + *_str = 0; \ + do { *(--_str) = _digits[(_i & 0xF)]; _i >>= 4; } while (_i); \ + OI_Print(_str); \ +} + +/** + * Application Dynamic Memory allocation. + * + * These APIs are provided for application use on those + * platforms which have no dynamic memory support. Memory is + * allocated from the pool-based heap managed by the stack's + * internal memory manager. + */ +void *OI_APP_Malloc(OI_INT32 size); +void OI_APP_Free(void *ptr); + +/*****************************************************************************/ +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif /* _OI_OSINTERFACE_H */ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_status.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_status.h new file mode 100755 index 0000000000..868d8dc44a --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_status.h @@ -0,0 +1,579 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_STATUS_H +#define _OI_STATUS_H +/** + * @file + * This file contains status codes for BLUEmagic 3.0 software. + */ + +#include "oi_stddefs.h" + +/** \addtogroup Misc Miscellaneous APIs */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + + + /** test it **/ + +/** + * OI_STATUS must fit in 16 bits, so status codes can range from 0 to 66535, inclusive. + */ + +typedef enum { + OI_STATUS_SUCCESS = 0, /**< function call succeeded alias for #OI_OK */ + OI_OK = 0, /**< function call succeeded alias for #OI_STATUS_SUCCESS */ + OI_STATUS_INVALID_PARAMETERS = 101, /**< invalid function input parameters */ + OI_STATUS_NOT_IMPLEMENTED = 102, /**< attempt to use an unimplemented function */ + OI_STATUS_NOT_INITIALIZED = 103, /**< data not initialized */ + OI_STATUS_NO_RESOURCES = 104, /**< generic resource allocation failure status */ + OI_STATUS_INTERNAL_ERROR = 105, /**< internal inconsistency */ + OI_STATUS_OUT_OF_MEMORY = 106, /**< generally, OI_Malloc failed */ + OI_ILLEGAL_REENTRANT_CALL = 107, /**< violation of non-reentrant module policy */ + OI_STATUS_INITIALIZATION_FAILED = 108, /**< module initialization failed */ + OI_STATUS_INITIALIZATION_PENDING = 109, /**< inititialization not yet complete */ + OI_STATUS_NO_SCO_SUPPORT = 110, /**< SCO operation rejected; system not configured for SCO */ + OI_STATUS_OUT_OF_STATIC_MEMORY = 111, /**< static malloc failed */ + OI_TIMEOUT = 112, /**< generic timeout */ + OI_OS_ERROR = 113, /**< some operating system error */ + OI_FAIL = 114, /**< generic failure */ + OI_STRING_FORMAT_ERROR = 115, /**< error in VarString formatting string */ + OI_STATUS_PENDING = 116, /**< The operation is pending. */ + OI_STATUS_INVALID_COMMAND = 117, /**< The command was invalid. */ + OI_BUSY_FAIL = 118, /**< command rejected due to busy */ + OI_STATUS_ALREADY_REGISTERED = 119, /**< The registration has already been performed. */ + OI_STATUS_NOT_FOUND = 120, /**< The referenced resource was not found. */ + OI_STATUS_NOT_REGISTERED = 121, /**< not registered */ + OI_STATUS_NOT_CONNECTED = 122, /**< not connected */ + OI_CALLBACK_FUNCTION_REQUIRED = 123, /**< A callback function parameter was required. */ + OI_STATUS_MBUF_OVERFLOW = 124, /**< There is no room to add another buffer to an mbuf. */ + OI_STATUS_MBUF_UNDERFLOW = 125, /**< There was an attempt to pull too many bytes from an mbuf. */ + OI_STATUS_CONNECTION_EXISTS = 126, /**< connection exists */ + OI_STATUS_NOT_CONFIGURED = 127, /**< module not configured */ + OI_LOWER_STACK_ERROR = 128, /**< An error was reported by lower stack API. This is used for embedded platforms. */ + OI_STATUS_RESET_IN_PROGRESS = 129, /**< Request failed/rejected because we're busy resetting. */ + OI_STATUS_ACCESS_DENIED = 130, /**< Generic access denied error. */ + OI_STATUS_DATA_ERROR = 131, /**< Generic data error. */ + OI_STATUS_INVALID_ROLE = 132, /**< The requested role was invalid. */ + OI_STATUS_ALREADY_CONNECTED = 133, /**< The requested connection is already established. */ + OI_STATUS_PARSE_ERROR = 134, /**< Parse error */ + OI_STATUS_END_OF_FILE = 135, /**< End of file */ + OI_STATUS_READ_ERROR = 136, /**< Generic read error */ + OI_STATUS_WRITE_ERROR = 137, /**< Generic write error */ + OI_STATUS_NEGOTIATION_FAILURE = 138, /**< Error in negotiation */ + OI_STATUS_READ_IN_PROGRESS = 139, /**< A read is already in progress */ + OI_STATUS_ALREADY_INITIALIZED = 140, /**< Initialization has already been done */ + OI_STATUS_STILL_CONNECTED = 141, /**< The service cannot be shutdown because there are still active connections. */ + OI_STATUS_MTU_EXCEEDED = 142, /**< The packet is too big */ + OI_STATUS_LINK_TERMINATED = 143, /**< The link was terminated */ + OI_STATUS_PIN_CODE_TOO_LONG = 144, /**< Application gave us a pin code that is too long */ + OI_STATUS_STILL_REGISTERED = 145, /**< The service cannot be shutdown because there are still active registrations. */ + OI_STATUS_SPEC_VIOLATION = 146, /**< Some application behavior contrary to BT specifications */ + + + OI_STATUS_PSM_ALREADY_REGISTERED = 402, /**< L2CAP: The specified PSM has already been registered. */ + OI_STATUS_INVALID_CID = 403, /**< L2CAP: CID is invalid or no longer valid (connection terminated) */ + OI_STATUS_CID_NOT_FOUND = 404, /**< L2CAP: CID does not represent a current connection */ + OI_STATUS_CHANNEL_NOT_FOUND = 406, /**< L2CAP: CID does not represent a current connection */ + OI_STATUS_PSM_NOT_FOUND = 407, /**< L2CAP: PSM not found */ + OI_STATUS_INVALID_STATE = 408, /**< L2CAP: invalid state */ + OI_STATUS_WRITE_IN_PROGRESS = 410, /**< L2CAP: write in progress */ + OI_STATUS_INVALID_PACKET = 411, /**< L2CAP: invalid packet */ + OI_STATUS_SEND_COMPLETE = 412, /**< L2CAP: send is complete */ + OI_STATUS_INVALID_HANDLE = 414, /**< L2CAP: handle is invalid */ + OI_STATUS_GROUP_FULL = 418, /**< L2CAP: No more members can be added to the specified group. */ + OI_STATUS_DEVICE_ALREADY_IN_GROUP = 423, /**< L2CAP: The device already exists in the group. */ + OI_STATUS_DUPLICATE_GROUP = 425, /**< L2CAP: attempt to add more than one group */ + OI_STATUS_EMPTY_GROUP = 426, /**< L2CAP: group is empty */ + OI_STATUS_PACKET_NOT_FOUND = 427, /**< L2CAP: packet not found */ + OI_STATUS_BUFFER_TOO_SMALL = 428, /**< L2CAP: The buffer size is too small. */ + OI_STATUS_IDENTIFIER_NOT_FOUND = 429, /**< L2CAP: identifier not found */ + + OI_L2CAP_DISCONNECT_LOWER_LAYER = 430, /**< L2CAP: The lower level forced a disconnect. */ + OI_L2CAP_DISCONNECT_REMOTE_REQUEST = 431, /**< L2CAP: The remote device requested a disconnect. */ + OI_L2CAP_GROUP_ADD_CONNECT_FAIL = 433, /**< L2CAP: Group add connect faiL */ + OI_L2CAP_GROUP_REMOVE_FAILURE = 434, /**< L2CAP: Group remove failure */ + OI_L2CAP_DATA_WRITE_ERROR_LINK_TERM = 435, /**< L2CAP: Data write error LINK_TERM */ + OI_L2CAP_DISCONNECT_LOCAL_REQUEST = 436, /**< L2CAP: Disconnect local request */ + + OI_L2CAP_CONNECT_TIMEOUT = 437, /**< L2CAP: Connect timeout */ + OI_L2CAP_DISCONNECT_TIMEOUT = 439, /**< L2CAP: Disconnect timeout */ + OI_L2CAP_PING_TIMEOUT = 440, /**< L2CAP: Ping timeout */ + OI_L2CAP_GET_INFO_TIMEOUT = 441, /**< L2CAP: Get info timeout */ + OI_L2CAP_INVALID_ADDRESS = 444, /**< L2CAP: Invalid address */ + OI_L2CAP_CMD_REJECT_RCVD = 445, /**< L2CAP: remote sent us 'command reject' response */ + + OI_L2CAP_CONNECT_BASE = 450, /**< L2CAP: Connect base */ + OI_L2CAP_CONNECT_PENDING = 451, /**< L2CAP: Connect pending */ + OI_L2CAP_CONNECT_REFUSED_INVALID_PSM = 452, /**< L2CAP: Connect refused invalid PSM */ + OI_L2CAP_CONNECT_REFUSED_SECURITY = 453, /**< L2CAP: Connect refused security */ + OI_L2CAP_CONNECT_REFUSED_NO_RESOURCES = 454, /**< L2CAP: Connect refused no resources */ + + OI_L2CAP_CONFIG_BASE = 460, /**< L2CAP: Config base */ + OI_L2CAP_CONFIG_FAIL_INVALID_PARAMETERS= 461, /**< L2CAP: Config fail invalid parameters */ + OI_L2CAP_CONFIG_FAIL_NO_REASON = 462, /**< L2CAP: Config fail no reason */ + OI_L2CAP_CONFIG_FAIL_UNKNOWN_OPTIONS = 463, /**< L2CAP: Config fail unknown options */ + + OI_L2CAP_GET_INFO_BASE = 470, /**< L2CAP: Get info base */ + OI_L2CAP_GET_INFO_NOT_SUPPORTED = 471, /**< L2CAP: Get info not supported */ + OI_L2CAP_MTU_EXCEEDED = 472, /**< L2CAP: The MTU of the channel was exceeded */ + OI_L2CAP_INVALID_PSM = 482, /**< L2CAP: Invalid PSM */ + OI_L2CAP_INVALID_MTU = 483, /**< L2CAP: Invalid MTU */ + OI_L2CAP_INVALID_FLUSHTO = 484, /**< L2CAP: Invalid flush timeout */ + + OI_HCI_NO_SUCH_CONNECTION = 601, /**< HCI: caller specified a non-existent connection handle */ + OI_HCI_CB_LIST_FULL = 603, /**< HCI: callback list is full, cannot attempt to send command */ + OI_HCI_EVENT_UNDERRUN = 605, /**< HCI: parsing event packet, premature end-of-parameters */ + OI_HCI_UNKNOWN_EVENT_CODE = 607, /**< HCI: event received - event code is unknown */ + OI_HCI_BAD_EVENT_PARM_LEN = 608, /**< HCI: event - parameter length is incorrect */ + OI_HCI_CMD_QUEUE_FULL = 611, /**< HCI: command queue is full */ + OI_HCI_SHORT_EVENT = 612, /**< HCI: event received, missing event code and/or parm len */ + OI_HCI_TRANSMIT_NOT_READY = 613, /**< HCI: ACL/SCO transmit request failed - busy or no buffers available */ + OI_HCI_ORPHAN_SENT_EVENT = 614, /**< HCI: got spurious 'sent' event from transport layer */ + OI_HCI_CMD_TABLE_ERROR = 615, /**< HCI: inconsistency in the internal command table */ + OI_HCI_UNKNOWN_CMD_ID = 616, /**< HCI: HciApi Command - unknown command id */ + OI_HCI_UNEXPECTED_EVENT = 619, /**< HCI: event received which only occurs in response to our cmd */ + OI_HCI_EVENT_TABLE_ERROR = 620, /**< HCI: inconsistency in the internal event table */ + OI_HCI_EXPECTED_EVENT_TIMOUT = 621, /**< HCI: timed out waiting for an expected event */ + OI_HCI_NO_CMD_DESC_FOR_OPCODE = 622, /**< HCI: event opcode is not known */ + OI_HCI_INVALID_OPCODE_ERROR = 623, /**< HCI: command opcode is invalid */ + OI_HCI_FLOW_CONTROL_DISABLED = 624, /**< HCI: can not use host flow control APIs if disabled in configuration */ + OI_HCI_TX_COMPLETE = 625, /**< HCI: packet delivery to Host Controler complete */ + OI_HCI_TX_ERROR = 626, /**< HCI: failed to deliver packet to Host Controler */ + OI_HCI_DEVICE_NOT_INITIALIZED = 627, /**< HCI: commands from upper layers disallowed until device is up and running */ + OI_HCI_UNSUPPORTED_COMMAND = 628, /**< HCI: command requested is not supported by local device */ + OI_HCI_PASSTHROUGH_ERROR = 629, /**< HCI: Error processing passthrough command */ + OI_HCI_PASSTHROUGH_ALREADY_SET = 630, /**< HCI: Passthrough mode already enabled */ + OI_HCI_RESET_FAILURE = 631, /**< HCI: failed to reset the device/baseband */ + OI_HCI_TRANSPORT_RESET = 632, /**< HCI: some operation failed because of a reset in the transport */ + OI_HCIERR_HCIIFC_INIT_FAILURE = 633, /**< HCI: failed to initialize transport layer interface */ + + OI_HCIERR_FIRST_ERROR_VALUE = 701, /**< marker for first HCI protocol error */ + OI_HCIERR_UNKNOWN_HCI_COMMAND = 701, /**< HCI: protocol error 0x01 */ + OI_HCIERR_NO_CONNECTION = 702, /**< HCI: protocol error 0x02 */ + OI_HCIERR_HARDWARE_FAILURE = 703, /**< HCI: protocol error 0x03 */ + OI_HCIERR_PAGE_TIMEOUT = 704, /**< HCI: protocol error 0x04 */ + OI_HCIERR_AUTHENTICATION_FAILURE = 705, /**< HCI: protocol error 0x05 */ + OI_HCIERR_KEY_MISSING = 706, /**< HCI: protocol error 0x06 */ + OI_HCIERR_MEMORY_FULL = 707, /**< HCI: protocol error 0x07 */ + OI_HCIERR_CONNECTION_TIMEOUT = 708, /**< HCI: protocol error 0x08 */ + OI_HCIERR_MAX_NUM_OF_CONNECTIONS = 709, /**< HCI: protocol error 0x09 */ + OI_HCIERR_MAX_NUM_OF_SCO_CONNECTIONS = 710, /**< HCI: protocol error 0x0A */ + OI_HCIERR_ACL_CONNECTION_ALREADY_EXISTS = 711, /**< HCI: protocol error 0x0B */ + OI_HCIERR_COMMAND_DISALLOWED = 712, /**< HCI: protocol error 0x0C */ + OI_HCIERR_HOST_REJECTED_RESOURCES = 713, /**< HCI: protocol error 0x0D */ + OI_HCIERR_HOST_REJECTED_SECURITY = 714, /**< HCI: protocol error 0x0E */ + OI_HCIERR_HOST_REJECTED_PERSONAL_DEVICE = 715, /**< HCI: protocol error 0x0F */ + OI_HCIERR_HOST_TIMEOUT = 716, /**< HCI: protocol error 0x10 */ + OI_HCIERR_UNSUPPORTED = 717, /**< HCI: protocol error 0x11 */ + OI_HCIERR_INVALID_PARAMETERS = 718, /**< HCI: protocol error 0x12 */ + OI_HCIERR_OTHER_END_USER_DISCONNECT = 719, /**< HCI: protocol error 0x13 */ + OI_HCIERR_OTHER_END_LOW_RESOURCES = 720, /**< HCI: protocol error 0x14 */ + OI_HCIERR_OTHER_END_POWERING_OFF = 721, /**< HCI: protocol error 0x15 */ + OI_HCIERR_CONNECTION_TERMINATED_LOCALLY = 722, /**< HCI: protocol error 0x16 */ + OI_HCIERR_REPEATED_ATTEMPTS = 723, /**< HCI: protocol error 0x17 */ + OI_HCIERR_PAIRING_NOT_ALLOWED = 724, /**< HCI: protocol error 0x18 */ + OI_HCIERR_UNKNOWN_LMP_PDU = 725, /**< HCI: protocol error 0x19 */ + OI_HCIERR_UNSUPPORTED_REMOTE_FEATURE = 726, /**< HCI: protocol error 0x1A */ + OI_HCIERR_SCO_OFFSET_REJECTED = 727, /**< HCI: protocol error 0x1B */ + OI_HCIERR_SCO_INTERVAL_REJECTED = 728, /**< HCI: protocol error 0x1C */ + OI_HCIERR_SCO_AIR_MODE_REJECTED = 729, /**< HCI: protocol error 0x1D */ + OI_HCIERR_INVALID_LMP_PARMS = 730, /**< HCI: protocol error 0x1E */ + OI_HCIERR_UNSPECIFIED_ERROR = 731, /**< HCI: protocol error 0x1F */ + OI_HCIERR_UNSUPPORTED_LMP_PARAMETERS = 732, /**< HCI: protocol error 0x20 */ + OI_HCIERR_ROLE_CHANGE_NOT_ALLOWED = 733, /**< HCI: protocol error 0x21 */ + OI_HCIERR_LMP_RESPONSE_TIMEOUT = 734, /**< HCI: protocol error 0x22 */ + OI_HCIERR_LMP_ERROR_TRANS_COLLISION = 735, /**< HCI: protocol error 0x23 */ + OI_HCIERR_LMP_PDU_NOT_ALLOWED = 736, /**< HCI: protocol error 0x24 */ + OI_HCIERR_ENCRYPTION_MODE_NOT_ACCEPTABLE = 737, /**< HCI: protocol error 0x25 */ + OI_HCIERR_UNIT_KEY_USED = 738, /**< HCI: protocol error 0x26 */ + OI_HCIERR_QOS_NOT_SUPPORTED = 739, /**< HCI: protocol error 0x27 */ + OI_HCIERR_INSTANT_PASSED = 740, /**< HCI: protocol error 0x28 */ + OI_HCIERR_UNIT_KEY_PAIRING_UNSUPPORTED = 741, /**< HCI: protocol error 0x29 */ + OI_HCIERR_DIFFERENT_TRANS_COLLISION = 742, /**< HCI: protocol error 0x2A */ + OI_HCIERR_RESERVED_2B = 743, /**< HCI: protocol error 0x2B */ + OI_HCIERR_QOS_UNACCEPTABLE_PARAMETER = 744, /**< HCI: protocol error 0x2C */ + OI_HCIERR_QOS_REJECTED = 745, /**< HCI: protocol error 0x2D */ + OI_HCIERR_CHANNEL_CLASSIFICATION_NS = 746, /**< HCI: protocol error 0x2E */ + OI_HCIERR_INSUFFICIENT_SECURITY = 747, /**< HCI: protocol error 0x2F */ + OI_HCIERR_PARM_OUT_OF_MANDATORY_RANGE = 748, /**< HCI: protocol error 0x30 */ + OI_HCIERR_RESERVED_31 = 749, /**< HCI: protocol error 0x31 */ + OI_HCIERR_ROLE_SWITCH_PENDING = 750, /**< HCI: protocol error 0x32 */ + OI_HCIERR_RESERVED_33 = 751, /**< HCI: protocol error 0x33 */ + OI_HCIERR_RESERVED_SLOT_VIOLATION = 752, /**< HCI: protocol error 0x34 */ + OI_HCIERR_ROLE_SWITCH_FAILED = 753, /**< HCI: protocol error 0x35 */ + OI_HCIERR_EIR_TOO_LARGE = 754, /**< HCI: protocol error 0x36 */ + OI_HCIERR_SSP_NOT_SUPPORTED_BY_HOST = 755, /**< HCI: protocol error 0x37 */ + OI_HCIERR_HOST_BUSY_PAIRING = 756, /**< HCI: protocol error 0x38 */ + + OI_HCIERR_UNKNOWN_ERROR = 757, /**< HCI: unknown error code */ + OI_HCIERR_LAST_ERROR_VALUE = 757, /**< marker for last HCI protocol error */ + + OI_SDP_SPEC_ERROR = 800, /**< SDP: Base error status for mapping OI_STATUS codes to SDP errors */ + OI_SDP_INVALID_SERVICE_RECORD_HANDLE = (OI_SDP_SPEC_ERROR + 2), /**< SDP: protocol error Invalid Service Record Handle */ + OI_SDP_INVALID_REQUEST_SYNTAX = (OI_SDP_SPEC_ERROR + 3), /**< SDP: protocol error Invalid Request Syntax */ + OI_SDP_INVALID_PDU_SIZE = (OI_SDP_SPEC_ERROR + 4), /**< SDP: protocol error Invalid PDU Size */ + OI_SDP_INVALID_CONTINUATION_STATE = (OI_SDP_SPEC_ERROR + 5), /**< SDP: protocol error Invalid Continuation State */ + OI_SDP_INSUFFICIENT_RESOURCES = (OI_SDP_SPEC_ERROR + 6), /**< SDP: protocol error Insufficient Resources */ + OI_SDP_ERROR = 807, /**< SDP: server returned an error code */ + OI_SDP_CORRUPT_DATA_ELEMENT = 808, /**< SDP: Invalid or corrupt data element representation */ + OI_SDP_SERVER_NOT_CONNECTED = 810, /**< SDP: Attempt to disconnect from an unconnected server */ + OI_SDP_ACCESS_DENIED = 811, /**< SDP: Server denied access to server */ + OI_SDP_ATTRIBUTES_OUT_OF_ORDER = 812, /**< SDP: Attributes in attribute list not in ascending order */ + OI_SDP_DEVICE_DOES_NOT_SUPPORT_SDP = 813, /**< SDP: Tried to connect to a device that does not support SDP */ + OI_SDP_NO_MORE_DATA = 815, /**< SDP: Server does not have more continuation data */ + OI_SDP_REQUEST_PARAMS_TOO_LONG = 816, /**< SDP: Parameters for a request exceed the L2CAP buffer size */ + OI_SDP_REQUEST_PENDING = 817, /**< SDP: Cannot make a request when another request is being processed */ + OI_SDP_SERVER_CONNECT_FAILED = 819, /**< SDP: Failed attempt to connect to an SDP server */ + OI_SDP_SERVER_TOO_MANY_CONNECTIONS = 821, /**< SDP: Exceeded maximum number of simultaneous server connections */ + OI_SDP_NO_MATCHING_SERVICE_RECORD = 823, /**< SDP: No service record matched the UUID list */ + OI_SDP_PARTIAL_RESPONSE = 824, /**< SDP: Internal use only */ + OI_SDP_ILLEGAL_ARGUMENT = 825, /**< SDP: Illegal argument passed to an SDP function */ + OI_SDP_ATTRIBUTE_NOT_FOUND = 826, /**< SDP: A requested attribute was not found in a service record */ + OI_SDP_DATABASE_OUT_OF_RESOURCES = 827, /**< SDP: server database is out of memory */ + OI_SDP_SHORT_PDU = 829, /**< SDP: Not enough bytes in the packet */ + OI_SDP_TRANSACTION_ID_MISMATCH = 830, /**< SDP: Transaction Id was not as expected */ + OI_SDP_UNEXPECTED_RESPONSE_PDU_ID = 831, /**< SDP: Did not expect this response PDU */ + OI_SDP_REQUEST_TIMEOUT = 832, /**< SDP: Did not get a response within the timeout period */ + OI_SDP_INVALID_RESPONSE_SYNTAX = 833, /**< SDP: Response is not correctly formatted */ + OI_SDP_CONNECTION_TIMEOUT = 834, /**< SDP: Connection attempt timed out at a lower layer */ + OI_SDP_RESPONSE_DATA_ERROR = 835, /**< SDP: Response to a service request appears to be corrupt */ + OI_SDP_TOO_MANY_ATTRIBUTE_BYTES = 836, /**< SDP: Response contained more bytes than requested. */ + OI_SDP_TOO_MANY_SERVICE_RECORDS = 837, /**< SDP: Response contained more service records than requested. */ + OI_SDP_INVALID_CONNECTION_ID = 838, /**< SDP: Invalid connection ID in an SDP request */ + OI_SDP_CANNOT_SET_ATTRIBUTE = 839, /**< SDP: Attempt to set a dynamic attribute value failed */ + OI_SDP_BADLY_FORMED_ATTRIBUTE_VALUE = 840, /**< SDP: An attribute value has the wrong type or structure */ + OI_SDP_NO_ATTRIBUTE_LIST_TO_REMOVE = 841, /**< SDP: Attempt to remove a non-existent attribute list from a service record */ + OI_SDP_ATTRIBUTE_LIST_ALREADY_ADDED = 842, /**< SDP: An attribute list has already been added to the service record */ + OI_SDP_DATA_ELEMENT_TRUNCATED = 843, /**< SDP: Data element truncated (too few bytes) */ + + OI_RFCOMM_WRITE_IN_PROGRESS = 901, /**< RFCOMM: Write in progress */ + OI_RFCOMM_INVALID_BAUDRATE = 903, /**< RFCOMM: Invalid baudrate */ + OI_RFCOMM_INVALID_DATABIT = 904, /**< RFCOMM: Invalid databit */ + OI_RFCOMM_INVALID_STOPBIT = 905, /**< RFCOMM: Invalid stopbit */ + OI_RFCOMM_INVALID_PARITY = 906, /**< RFCOMM: Invalid parity */ + OI_RFCOMM_INVALID_PARITYTYPE = 907, /**< RFCOMM: Invalid paritytype */ + OI_RFCOMM_INVALID_FLOWCONTROL = 908, /**< RFCOMM: Invalid flowcontrol */ + OI_RFCOMM_SESSION_EXISTS = 909, /**< RFCOMM: Session exists */ + OI_RFCOMM_INVALID_CHANNEL = 910, /**< RFCOMM: Invalid channel */ + OI_RFCOMM_DLCI_EXISTS = 911, /**< RFCOMM: DLCI exists */ + OI_RFCOMM_LINK_NOT_FOUND = 912, /**< RFCOMM: Link not found */ + OI_RFCOMM_REMOTE_REJECT = 913, /**< RFCOMM: Remote reject */ + OI_RFCOMM_TEST_IN_PROGRESS = 915, /**< RFCOMM: Test in progress */ + OI_RFCOMM_SESSION_NOT_FOUND = 916, /**< RFCOMM: Session not found */ + OI_RFCOMM_INVALID_PACKET = 917, /**< RFCOMM: Invalid packet */ + OI_RFCOMM_FRAMESIZE_EXCEEDED = 918, /**< RFCOMM: Framesize exceeded */ + OI_RFCOMM_INVALID_DLCI = 920, /**< RFCOMM: Invalid dlci */ + OI_RFCOMM_SERVER_NOT_REGISTERED = 921, /**< RFCOMM: Server not registered */ + OI_RFCOMM_CREDIT_ERROR = 922, /**< RFCOMM: Credit error */ + OI_RFCOMM_NO_CHANNEL_NUMBER = 923, /**< RFCOMM: No channel number */ + OI_RFCOMM_QUERY_IN_PROGRESS = 924, /**< RFCOMM: Query in progress */ + OI_RFCOMM_SESSION_SHUTDOWN = 925, /**< RFCOMM: Session shutdown */ + OI_RFCOMM_LOCAL_DEVICE_DISCONNECTED = 926, /**< RFCOMM: Local device disconnected */ + OI_RFCOMM_REMOTE_DEVICE_DISCONNECTED = 927, /**< RFCOMM: Remote device disconnected */ + OI_RFCOMM_OUT_OF_SERVER_CHANNELS = 928, /**< RFCOMM: Out of server channels */ + + OI_DISPATCH_INVALID_CB_HANDLE = 1001, /**< Dispatcher was handed an invalid callback handle */ + OI_DISPATCH_TABLE_OVERFLOW = 1002, /**< Dispatcher table is full */ + + OI_TEST_UNKNOWN_TEST = 1101, /**< TEST: Unknown test */ + OI_TEST_FAIL = 1102, /**< TEST: Fail */ + + OI_HCITRANS_CANNOT_CONNECT_TO_DEVICE = 1201, /**< TRANSPORT: Cannot connect to device */ + OI_HCITRANS_BUFFER_TOO_SMALL = 1203, /**< TRANSPORT: Buffer too small */ + OI_HCITRANS_NULL_DEVICE_HANDLE = 1204, /**< TRANSPORT: Null device handle */ + OI_HCITRANS_IO_ERROR = 1205, /**< TRANSPORT: IO error */ + OI_HCITRANS_DEVICE_NOT_READY = 1206, /**< TRANSPORT: Device not ready */ + OI_HCITRANS_FUNCTION_NOT_SUPPORTED = 1207, /**< TRANSPORT: Function not supporteD */ + OI_HCITRANS_ACCESS_DENIED = 1209, /**< TRANSPORT: win32 */ + OI_HCITRANS_ACL_DATA_ERROR = 1210, /**< TRANSPORT: ACL data error */ + OI_HCITRANS_SCO_DATA_ERROR = 1211, /**< TRANSPORT: SCO data error */ + OI_HCITRANS_EVENT_DATA_ERROR = 1212, /**< TRANSPORT: HCI event data error */ + OI_HCITRANS_INTERNAL_ERROR = 1214, /**< TRANSPORT: Internal error in the transport */ + OI_HCITRANS_LINK_NOT_ACTIVE = 1215, /**< TRANSPORT: Link to the device is not currently active */ + OI_HCITRANS_INITIALIZING = 1216, /**< TRANSPORT: Transport is initializing */ + + OI_DEVMGR_NO_CONNECTION = 1301, /**< DEVMGR: No connection */ + OI_DEVMGR_HARDWARE_ERROR = 1305, /**< DEVMGR: error reported by HCI */ + OI_DEVMGR_PENDING_CONNECT_LIST_FULL = 1307, /**< DEVMGR: Pending connect list full */ + OI_DEVMGR_CONNECTION_LIST_FULL = 1309, /**< DEVMGR: Connection list full */ + OI_DEVMGR_NO_SUCH_CONNECTION = 1310, /**< DEVMGR: No such connection */ + OI_DEVMGR_INQUIRY_IN_PROGRESS = 1311, /**< DEVMGR: Inquiry in progress */ + OI_DEVMGR_PERIODIC_INQUIRY_ACTIVE = 1312, /**< DEVMGR: Periodic inquiry active */ + OI_DEVMGR_NO_INQUIRIES_ACTIVE = 1313, /**< DEVMGR: can not cancel/exit if not active */ + OI_DEVMGR_DUPLICATE_CONNECTION = 1314, /**< DEVMGR: internal error */ + OI_DEVMGR_DUPLICATE_EVENT_CALLBACK = 1316, /**< DEVMGR: attempt to register same callback twice */ + OI_DEVMGR_EVENT_CALLBACK_LIST_FULL = 1317, /**< DEVMGR: can not register event callback, list is full */ + OI_DEVMGR_EVENT_CALLBACK_NOT_FOUND = 1318, /**< DEVMGR: attempt to unregister callback failed */ + OI_DEVMGR_BUSY = 1319, /**< DEVMGR: some operations can only execute one at a time */ + OI_DEVMGR_ENUM_UNEXPECTED_INQ_COMPLETE = 1320, /**< DEVMGR: inquiry complete event in inappropriate enumeration state */ + OI_DEVMGR_ENUM_UNEXPECTED_INQ_RESULT = 1321, /**< DEVMGR: inquiry result event in inappropriate enumeration state */ + OI_DEVMGR_ENUM_DATABASE_FULL = 1322, /**< DEVMGR: device enumeration, database is full, couldn't add a new device */ + OI_DEVMGR_ENUM_INQUIRIES_OVERLAP = 1323, /**< DEVMGR: device enumeration, periodic inquiries occurring too close together */ + OI_DEVMGR_UNKNOWN_LINK_TYPE = 1324, /**< DEVMGR: HCI connect request with unkown link type */ + OI_DEVMGR_PARAM_IO_ACTIVE = 1325, /**< DEVMGR: request for parameter read/write while param read/write active */ + OI_DEVMGR_UNKNOWN_IAC_LAP = 1326, /**< DEVMGR: unrecognized IAC LAP */ + OI_DEVMGR_SCO_ALREADY_REGISTERED = 1327, /**< DEVMGR: only one application can use SCO */ + OI_DEVMGR_SCO_NOT_REGISTERED = 1328, /**< DEVMGR: SCO applications must register before using the API */ + OI_DEVMGR_SCO_WITHOUT_ACL = 1329, /**< DEVMGR: Got SCO connection but there is no underlying ACL connection */ + OI_DEVMGR_NO_SUPPORT = 1330, /**< DEVMGR: Request is not supported by the device */ + OI_DEVMGR_WRITE_POLICY_FAILED = 1331, /**< DEVMGR: connection attempt failed - unable to write link policy */ + OI_DEVMGR_NOT_IN_MASTER_MODE = 1332, /**< DEVMGR: OI_DEVMGR EndMasterMode without prior OI_DEVMGR_BeginMasterMode */ + OI_DEVMGR_POLICY_VIOLATION = 1333, /**< DEVMGR: low-power request is rejected - link policy does not allow it */ + OI_DEVMGR_BUSY_TIMEOUT = 1334, /**< DEVMGR: queued operation timed out while in the queue; \n + timeout configurable via @ref OI_CONFIG_DEVMGR::connectQueueTimeoutSecs "connectQueueTimeoutSecs" */ + OI_DEVMGR_REENCRYPT_FAILED = 1335, /**< DEVMGR: failed to re-encrypt link after role switch */ + OI_DEVMGR_ROLE_POLICY_CONFLICT = 1336, /**< DEVMGR: requested role conflicts with current policy */ + OI_DEVMGR_BAD_INTERVAL = 1337, /**< DEVMGR: current linkTO outside range of requested min/max interval */ + OI_DEVMGR_INVALID_SCO_HANDLE = 1338, /**< DEVMGR: HCI SCO event, invalid handle */ + OI_DEVMGR_CONNECTION_OVERLAP = 1339, /**< DEVMGR: Connection failed due to race condition with remote side */ + OI_DEVMGR_ORPHAN_SUBRATE_COMPLETE = 1340, /**< DEVMGR: sniff subrate complete, but no callback */ + OI_DEVMGR_EIR_RESPONSE_2_LARGE = 1341, /**< DEVMGR: eir builder, response length would exceed spec max */ + + OI_SECMGR_NO_POLICY = 1401, /**< SECMGR: no security policy has been established */ + OI_SECMGR_INTERNAL_ERROR = 1402, /**< SECMGR: internal inconsistency */ + OI_SECMGR_ORPHANED_CALLBACK = 1403, /**< SECMGR: we've been called back, but CB context is gone */ + OI_SECMGR_BUSY = 1404, /**< SECMGR: configure and access request cannot be concurrent */ + OI_SECMGR_DEVICE_NOT_TRUSTED = 1405, /**< SECMGR: l2cap access denied - device is not trusted */ + OI_SECMGR_DEVICE_ENCRYPT_FAIL = 1407, /**< SECMGR: l2cap access denied - failed to start encryption */ + OI_SECMGR_DISCONNECTED_FAIL = 1408, /**< SECMGR: l2cap access denied - disconnected */ + OI_SECMGR_ACCESS_PENDING = 1409, /**< SECMGR: l2cap access request is still pending */ + OI_SECMGR_PIN_CODE_TOO_SHORT = 1410, /**< SECMGR: Higher-layer process gave us a pin code that is too short */ + OI_SECMGR_UNKNOWN_ENCRYPT_VALUE = 1411, /**< SECMGR: got EncryptionChange event, unknown encryption enable value */ + OI_SECMGR_INVALID_POLICY = 1412, /**< SECMGR: the specified security policy is not valid for security mode */ + OI_SECMGR_AUTHORIZATION_FAILED = 1413, /**< SECMGR: device authorization failed */ + OI_SECMGR_ENCRYPTION_FAILED = 1414, /**< SECMGR: device encryption failed */ + OI_SECMGR_UNIT_KEY_UNSUPPORTED = 1415, /**< SECMGR: authentication failed due to non-support of unit keys */ + OI_SECMGR_NOT_REGISTERED = 1416, /**< SECMGR: required registrations have not yet occurred */ + OI_SECMGR_ILLEGAL_WRITE_SSP_MODE = 1417, /**< SECMGR: 2.1 HCI spec does not allow SSP mode to be disabled */ + OI_SECMGR_INVALID_SEC_LEVEL = 1418, /**< SECMGR: security level for a service is not a valid value */ + OI_SECMGR_INSUFFICIENT_LINK_KEY = 1419, /**< SECMGR: link key type is not sufficient to meet service requirements */ + OI_SECMGR_INVALID_KEY_TYPE = 1420, /**< SECMGR: link key type is not a valid value */ + OI_SECMGR_SSP_NOT_ENCRYPTED = 1421, /**< SECMGR: ssp required encryption on incoming link */ + OI_SECMGR_ORPHAN_EVENT = 1422, /**< SECMGR: some HCI security event unrelated to current processes */ + OI_SECMGR_NOT_BONDABLE = 1423, /**< SECMGR: not in bondable mode */ + + OI_TCS_INVALID_ELEMENT_TYPE = 1602, /**< TCS: element type is invalid */ + OI_TCS_INVALID_PACKET = 1603, /**< TCS: packet is invalide */ + OI_TCS_CALL_IN_PROGRESS = 1604, /**< TCS: call is in progress */ + OI_TCS_NO_CALL_IN_PROGRESS = 1605, /**< TCS: no call in progress */ + + OI_OBEX_CONTINUE = 1701, /**< OBEX: Continue processing OBEX request */ + OI_OBEX_COMMAND_ERROR = 1702, /**< OBEX: An unrecognized OBEX command opcode */ + OI_OBEX_CONNECTION_TIMEOUT = 1703, /**< OBEX: Timeout waiting for a response to a request */ + OI_OBEX_CONNECT_FAILED = 1704, /**< OBEX: An OBEX connection request did not succeed */ + OI_OBEX_DISCONNECT_FAILED = 1705, /**< OBEX: A disconnect failed probably because the connection did not exist */ + OI_OBEX_ERROR = 1706, /**< OBEX: Unspecified OBEX error */ + OI_OBEX_INCOMPLETE_PACKET = 1707, /**< OBEX: Packet too short or corrupt */ + OI_OBEX_LENGTH_REQUIRED = 1708, /**< OBEX: Length header required in OBEX command */ + OI_OBEX_NOT_CONNECTED = 1709, /**< OBEX: No connection to OBEX server */ + OI_OBEX_NO_MORE_CONNECTIONS = 1710, /**< OBEX: Reached max connections limit */ + OI_OBEX_OPERATION_IN_PROGRESS = 1711, /**< OBEX: Another operation is still in progress on a connection */ + OI_OBEX_PUT_RESPONSE_ERROR = 1712, /**< OBEX: An error in the response to a PUT command */ + OI_OBEX_GET_RESPONSE_ERROR = 1713, /**< OBEX: An error in the response to a GET command */ + OI_OBEX_REQUIRED_HEADER_NOT_FOUND = 1714, /**< OBEX: packet was missing a required header */ + OI_OBEX_SERVICE_UNAVAILABLE = 1715, /**< OBEX: Unown OBEX target or required service */ + OI_OBEX_TOO_MANY_HEADER_BYTES = 1716, /**< OBEX: Headers will not fit in single OBEX packet */ + OI_OBEX_UNKNOWN_COMMAND = 1717, /**< OBEX: Unrecognized OBEX command */ + OI_OBEX_UNSUPPORTED_VERSION = 1718, /**< OBEX: Version mismatch */ + OI_OBEX_CLIENT_ABORTED_COMMAND = 1719, /**< OBEX: server received abort command */ + OI_OBEX_BAD_PACKET = 1720, /**< OBEX: Any malformed OBEX packet */ + OI_OBEX_BAD_REQUEST = 1721, /**< OBEX: Maps to OBEX response of the same name */ + OI_OBEX_OBJECT_OVERFLOW = 1723, /**< OBEX: Too many bytes received. */ + OI_OBEX_NOT_FOUND = 1724, /**< OBEX: Maps to obex response of same name */ + OI_OBEX_ACCESS_DENIED = 1735, /**< OBEX: Object could not be read or written. */ + OI_OBEX_VALUE_NOT_ACCEPTABLE = 1736, /**< OBEX: Value in a command was not in the acceptable range. */ + OI_OBEX_PACKET_OVERFLOW = 1737, /**< OBEX: Buffer will not fit in a single OBEX packet. */ + OI_OBEX_NO_SUCH_FOLDER = 1738, /**< OBEX: Error returned by a setpath operation. */ + OI_OBEX_NAME_REQUIRED = 1739, /**< OBEX: Name must be non-null and non-empty. */ + OI_OBEX_PASSWORD_TOO_LONG = 1740, /**< OBEX: Password exceeds implementation imposed length limit. */ + OI_OBEX_PRECONDITION_FAILED = 1741, /**< OBEX: response Precondition Failed */ + OI_OBEX_UNAUTHORIZED = 1742, /**< OBEX: authentication was not successful. */ + OI_OBEX_NOT_IMPLEMENTED = 1743, /**< OBEX: Unimplemented feature. */ + OI_OBEX_INVALID_AUTH_DIGEST = 1744, /**< OBEX: An authentication digest was bad. */ + OI_OBEX_INVALID_OPERATION = 1745, /**< OBEX: Operation not allowed at this time. */ + OI_OBEX_DATABASE_FULL = 1746, /**< OBEX: Sync database full. */ + OI_OBEX_DATABASE_LOCKED = 1747, /**< OBEX: Sync database locked. */ + OI_OBEX_INTERNAL_SERVER_ERROR = 1748, /**< OBEX: response Internal Server Error */ + OI_OBEX_UNSUPPORTED_MEDIA_TYPE = 1749, /**< OBEX: response Unsupported Media Type */ + OI_OBEX_PARTIAL_CONTENT = 1750, /**< OBEX: response Partial Content */ + OI_OBEX_METHOD_NOT_ALLOWED = 1751, /**< OBEX: response Method Not Allowed */ + OI_OBEXSRV_INCOMPLETE_GET = 1752, /**< OBEX: Indicates to a GET handler that the request phase is still in progress */ + OI_OBEX_FOLDER_BROWSING_NOT_ALLOWED = 1753, /**< OBEX: Indicates that an FTP server does not allow folder browsing */ + OI_OBEX_SERVER_FORCED_DISCONNECT = 1754, /**< OBEX: connection was forcibly terminated by the server */ + OI_OBEX_OFS_ERROR = 1755, /**< OBEX: OPP object file system error occurred */ + OI_OBEX_FILEOP_ERROR = 1756, /**< OBEX: FTP/PBAP file operation system error occurred */ + OI_OBEX_USERID_TOO_LONG = 1757, /**< OBEX: User Id exceeds spec limited length limit. */ + + OI_HANDSFREE_EVENT_REPORTING_DISABLED = 1801, /**< HANDSFREE: Event reporting disabled */ + OI_HANDSFREE_NOT_CONNECTED = 1802, /**< HANDSFREE: Not connected */ + OI_HANDSFREE_SERVICE_NOT_STARTED = 1803, /**< HANDSFREE: Cannot connect to handsfree AG if handsfree service not started */ + OI_HANDSFREE_AG_SERVICE_NOT_STARTED = 1804, /**< HANDSFREE: Cannot connect to handsfree device if handsfree AG service not started */ + OI_HANDSFREE_COMMAND_IN_PROGRESS = 1805, /**< HANDSFREE: Cannot accept a command at this time */ + OI_HANDSFREE_AUDIO_ALREADY_CONNECTED = 1806, /**< HANDSFREE: Audio is already connected */ + OI_HANDSFREE_AUDIO_NOT_CONNECTED = 1807, /**< HANDSFREE: Audio is not connected */ + OI_HANDSFREE_FEATURE_NOT_SUPPORTED = 1808, /**< HANDSFREE: Local or remote feature not supported for requested command */ + + OI_HEADSET_SERVICE_NOT_STARTED = 1901, /**< HEADSET: Cannot connect to headset AG if headset service not started */ + OI_HEADSET_AG_SERVICE_NOT_STARTED = 1902, /**< HEADSET: Cannot connect to headset device if headset AG service not started */ + OI_HEADSET_COMMAND_IN_PROGRESS = 1903, /**< HEADSET: Cannot accept a command at this time */ + + OI_BNEP_INVALID_MTU = 2001, /**< BNEP: The remote device cannot support the minimum BNEP MTU */ + OI_BNEP_SETUP_TIMEOUT = 2002, /**< BNEP: The setup request timed out. */ + OI_BNEP_SERVICE_NOT_REGISTERED = 2003, /**< BNEP: The requested service was not found. */ + OI_BNEP_INVALID_HANDLE = 2004, /**< BNEP: The specified connection handle is not valid. */ + OI_BNEP_RESPONSE_TIMEOUT = 2005, /**< BNEP: The timer for receiving a response has expired. */ + OI_BNEP_INVALID_CONNECTION = 2006, /**< BNEP: Invalid connection */ + OI_BNEP_INVALID_FILTER = 2007, /**< BNEP: The supplied filter was invalid. */ + OI_BNEP_CONNECTION_EXISTS = 2008, /**< BNEP: An attempt was made to create a duplicate connection. */ + OI_BNEP_NOT_INITIALIZED = 2009, /**< BNEP: Init has not been called */ + OI_BNEP_CONNECT_BASE = 2010, /**< BNEP: connection response codes */ + OI_BNEP_CONNECT_FAILED_INVALID_DEST_UUID = 2011, /**< BNEP: connect response code Invalid Dest UUID */ + OI_BNEP_CONNECT_FAILED_INVALID_SOURCE_UUID = 2012, /**< BNEP: connect response code Invalid Source UUID */ + OI_BNEP_CONNECT_FAILED_INVALID_UUID_SIZE = 2013, /**< BNEP: connect response code Invalid UUID Size */ + OI_BNEP_CONNECT_FAILED_NOT_ALLOWED = 2014, /**< BNEP: connect response code Not Allowed */ + OI_BNEP_FILTER_NET_BASE = 2020, /**< BNEP: filter response codes */ + OI_BNEP_FILTER_NET_UNSUPPORTED_REQUEST = 2021, /**< BNEP: filter response code Unsupported Request */ + OI_BNEP_FILTER_NET_FAILED_INVALID_PROTOCOL_TYPE = 2022, /**< BNEP: filter response code Invalid Protocol Type */ + OI_BNEP_FILTER_NET_FAILED_MAX_LIMIT_REACHED = 2023, /**< BNEP: filter response code Max Limit Reached */ + OI_BNEP_FILTER_NET_FAILED_SECURITY = 2024, /**< BNEP: filter response code Security */ + OI_BNEP_FILTER_MULTI_BASE = 2030, /**< BNEP: multicast response codes */ + OI_BNEP_FILTER_MULTI_UNSUPPORTED_REQUEST = 2031, /**< BNEP: multicast response code Unsupported Request */ + OI_BNEP_FILTER_MULTI_FAILED_INVALID_ADDRESS = 2032, /**< BNEP: multicast response code Invalid Address */ + OI_BNEP_FILTER_MULTI_FAILED_MAX_LIMIT_REACHED = 2033, /**< BNEP: multicast response code Max Limit Reached */ + OI_BNEP_FILTER_MULTI_FAILED_SECURITY = 2034, /**< BNEP: multicast response code Security */ + OI_BNEP_LOCAL_DEVICE_MUST_BE_MASTER = 2040, /**< BNEP: Device must be master of the piconet for this function */ + OI_BNEP_PACKET_FILTERED_OUT = 2041, /**< BNEP: Packet did not pass current filters */ + + OI_NETIFC_UP_FAILED = 2101, /**< NETIFC: Could not bring up network interface */ + OI_NETIFC_COULD_NOT_CREATE_THREAD = 2102, /**< NETIFC: Network interface could not create a read thread */ + OI_NETIFC_INITIALIZATION_FAILED = 2103, /**< NETIFC: Error in network interface initialization */ + OI_NETIFC_INTERFACE_ALREADY_UP = 2104, /**< NETIFC: Network interface is already up */ + OI_NETIFC_INTERFACE_NOT_UP = 2105, /**< NETIFC: Network interface is not up */ + OI_NETIFC_PACKET_TOO_BIG = 2106, /**< NETIFC: The packet is too big */ + + OI_PAN_ROLE_ALREADY_REGISTERED = 2201, /**< PAN: This PAN role was already registered */ + OI_PAN_ROLE_NOT_ALLOWED = 2202, /**< PAN: The PAN role is not currently allowed */ + OI_PAN_INCOMPATIBLE_ROLES = 2203, /**< PAN: Only certain local and remote role combinations are permitted */ + OI_PAN_INVALID_ROLE = 2204, /**< PAN: Role specified is not one the defined PAN roles */ + OI_PAN_CONNECTION_IN_PROGRESS = 2205, /**< PAN: A PAN connection is currently being established */ + OI_PAN_USER_ALREADY_CONNECTED = 2206, /**< PAN: PAN user role only allows a single connection */ + OI_PAN_DEVICE_CONNECTED = 2207, /**< PAN: A PAN connection already exists to specified device */ + + OI_CODEC_SBC_NO_SYNCWORD = 2301, /**< CODEC: Couldn't find an SBC SYNCWORD */ + OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA = 2302, /**< CODEC: Not enough data provided to decode an SBC header */ + OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA = 2303, /**< CODEC: Decoded the header, but not enough data to contain the rest of the frame */ + OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA = 2304, /**< CODEC: Not enough audio data for this frame */ + OI_CODEC_SBC_CHECKSUM_MISMATCH = 2305, /**< CODEC: The frame header didn't match the checksum */ + OI_CODEC_SBC_PARTIAL_DECODE = 2306, /**< CODEC: Decoding was successful, but frame data still remains. Next call will provide audio without consuming input data. */ + + OI_FIFOQ_QUEUE_NOT_ALIGNED = 2401, /**< FIFOQ: queue must be 32-bit aligned */ + OI_FIFOQ_INVALID_Q = 2402, /**< FIFOQ: queue parameter is not a valid queue */ + OI_FIFOQ_BUF_TOO_LARGE = 2403, /**< FIFOQ: attempt to queue a buffer which is too large */ + OI_FIFOQ_FULL = 2404, /**< FIFOQ: enqueue() failed, queue is full */ + OI_FIFOQ_NOT_ALLOCATED = 2405, /**< FIFOQ: Enqueue QBuf() failed, buffer not allocated */ + OI_FIFOQ_INVALID_DATA_PTR = 2406, /**< FIFOQ: Enqueue QBuf() failed, data pointer does not match */ + + OI_HID_HOST_SERVICE_NOT_STARTED = 2601, /**< HID: Cannot connect to a HID device unless HID host is started */ + OI_HID_DEVICE_SERVICE_NOT_STARTED = 2602, /**< HID: Cannot connect to a HID host unless HID device is started */ + + OI_AT_ERROR = 2701, /**< AT: ERROR response */ + OI_AT_NO_CARRIER = 2702, /**< AT: NO CARRIER response */ + OI_AT_BUSY = 2703, /**< AT: BUSY response */ + OI_AT_NO_ANSWER = 2704, /**< AT: NO ANSWER response */ + OI_AT_DELAYED = 2705, /**< AT: DELAYED response */ + OI_AT_BLACKLISTED = 2706, /**< AT: BLACKLISTED response */ + OI_AT_CME_ERROR = 2707, /**< AT: +CME ERROR response */ + OI_AT_CMS_ERROR = 2708, /**< AT: +CMS ERROR response */ + + OI_BLST_CHARACTER_TIMEOUT = 2801, /**< BLST: Timeout expired while waiting for a character from the client. */ + OI_BLST_ACKNOWLDGE_TIMEOUT = 2802, /**< BLST: Timeout expired while waiting for event acknowledgment from the client */ + OI_BLST_TX_NOT_READY = 2803, /**< BLST: BLST is not ready to send a BHAPI message to the client. */ + OI_BLST_TX_BUSY = 2804, /**< BLST: BLST transmit buffer is in use. */ + + OI_AVDTP_CONNECTION_SEQ_ERROR = 2901, /**< AVDTP: sequencing of signalling/media channel connections broken. */ + OI_AVDTP_OUT_OF_RESOURCES = 2902, /**< AVDTP: Tried to allocate too many endpoints or signalling channels. */ + + OI_PBAP_REPOSITORY_NOT_SET = 3001, /**< PBAP: Phonebook repository must be set for operation to complete. */ + OI_PBAP_PHONEBOOK_NOT_SET = 3002, /**< PBAP: Phonebook be set for operation to complete. */ + + OI_AADP_BAD_ENDPOINT = 3101, /**< AADP: Invalid local endpoint specified */ + OI_AADP_BAD_STATE = 3102, /**< AADP: AADP State is not correct for this operation. */ + + OI_UNICODE_INVALID_SOURCE = 3200, /**< Unicode Conversion: Source string has invalid character encoding. */ + OI_UNICODE_SOURCE_EXHAUSTED = 3201, /**< Unicode Conversion: Incomplete Unicode character at end of source buffer. */ + OI_UNICODE_DESTINATION_EXHAUSTED = 3202, /**< Unicode Conversion: Destination buffer not large enough to hold resulting Unicode string. */ + + OI_AVRCP_TOO_MANY_CONNECTIONS = 3300, /**< AVRCP: Exceeded maximum number of simultaneous AVCTP connections. */ + OI_AVRCP_NOT_IMPLEMENTED = 3301, /**< AVRCP: The target does not implement the command specified by the opcode and operand. */ + OI_AVRCP_REJECTED = 3302, /**< AVRCP: The target cannot respond because of invalid operands in command packet. */ + OI_AVRCP_INVALID_RESPONSE = 3303, /**< AVRCP: The controller received the response with invalid parameters */ + OI_AVRCP_RESPONSE_PACKET_OVERFLOW = 3304, /**< AVRCP: The response message does not fir in one AVRCP packet (512 bytes), has to be fragmented. */ + OI_AVRCP_RESPONSE_INVALID_PDU = 3305, /**< AVRCP: Command rejected: target received a PDU that it did not understand. */ + OI_AVRCP_RESPONSE_INVALID_PARAMETER = 3306, /**< AVRCP: Command rejected: target received a PDU with a parameter ID that it did not understand. */ + OI_AVRCP_RESPONSE_PARAMETER_NOT_FOUND = 3307, /**< AVRCP: Command rejected: specified parameter not found, sent if the parameter ID is understood, but content is wrong or corrupted.*/ + OI_AVRCP_RESPONSE_INTERNAL_ERROR = 3308, /**< AVRCP: Command rejected: target detected other error conditions. */ + OI_MAX_BM3_STATUS_VAL, /* Maximum BM3 status code */ + + /* Status code values reserved for BM3 SDK platform-specific implementations */ + OI_STATUS_RESERVED_FOR_BCOT = 9000, + + /* Status code values reserved for BHAPI products */ + OI_STATUS_RESERVED_FOR_BHAPI = 9200, + + /* Status code values reserved for Soundabout products */ + OI_STATUS_RESERVED_FOR_SOUNDABOUT= 9400, + + /* + * Status code values greater than or equal to this value are reserved for use by applications. + * However, because of differences between compilers, and differences between 16-bit and 32-bit + * platforms custom status codes should be in the 16-bit range, so status codes can range from 0 + * to 65534, inclusive (65535 is reserved) + */ + OI_STATUS_RESERVED_FOR_APPS = 10000, + + + + OI_STATUS_NONE = 0xffff /**< Special status code to indicate that there is no status. (Only to be used for special cases involving OI_SLOG_ERROR() and OI_SLOG_WARNING().) */ + +} OI_STATUS; + + +/* Remeber to update the #define below when new reserved blocks are added to + * the list above. */ +#define OI_NUM_RESERVED_STATUS_BLOCKS 4 /**< Number of status code blocks reserved, including user apps */ + + +/** + * Test for success + */ +#define OI_SUCCESS(x) ((x) == OI_OK) + +/*****************************************************************************/ +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif /* _OI_STATUS_H */ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_stddefs.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_stddefs.h new file mode 100755 index 0000000000..ec8c45312f --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_stddefs.h @@ -0,0 +1,232 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 OI_STDDEFS_H +#define OI_STDDEFS_H +/** + * @file + * This file contains BM3 standard type definitions. + * + */ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#include "oi_cpu_dep.h" + +/** \addtogroup Misc Miscellaneous APIs */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef FALSE +#define FALSE 0 /**< This define statement sets FALSE as a preprocessor alias for 0. */ +#endif + +#ifndef TRUE +#define TRUE (!FALSE) /**< This define statement sets TRUE as a preprocessor alias for !FALSE. */ +#endif + +#ifdef HEW_TOOLCHAIN + #ifdef NULL + #undef NULL /**< Override HEW toolchain NULL definition */ + #endif + #define NULL 0 /**< HEW toolchain does not allow us to compare (void*) type to function pointer */ +#else + #ifndef NULL + #define NULL ((void*)0) /**< This define statement sets NULL as a preprocessor alias for (void*)0 */ + #endif +#endif + +/** + * @name Maximum and minimum values for basic types + * @{ + */ +#define OI_INT8_MIN ((OI_INT8)0x80) /**< decimal value: -128 */ +#define OI_INT8_MAX ((OI_INT8)0x7F) /**< decimal value: 127 */ +#define OI_INT16_MIN ((OI_INT16)0x8000) /**< decimal value: -32768 */ +#define OI_INT16_MAX ((OI_INT16)0x7FFF) /**< decimal value: 32767 */ +#define OI_INT32_MIN ((OI_INT32)0x80000000) /**< decimal value: -2,147,483,648 */ +#define OI_INT32_MAX ((OI_INT32)0x7FFFFFFF) /**< decimal value: 2,147,483,647 */ +#define OI_UINT8_MIN ((OI_UINT8)0) /**< decimal value: 0 */ +#define OI_UINT8_MAX ((OI_UINT8)0xFF) /**< decimal value: 255 */ +#define OI_UINT16_MIN ((OI_UINT16)0) /**< decimal value: 0 */ +#define OI_UINT16_MAX ((OI_UINT16)0xFFFF) /**< decimal value: 65535 */ +#define OI_UINT32_MIN ((OI_UINT32)0) /**< decimal value: 0 */ +#define OI_UINT32_MAX ((OI_UINT32)0xFFFFFFFF) /**< decimal value: 4,294,967,295 */ + +/** + * @} + */ + +/** + * @name Integer types required by the Service Discovery Protocol + * @{ + */ + +/** unsigned 64-bit integer as a structure of two unsigned 32-bit integers */ +typedef struct { + OI_UINT32 I1; /**< most significant 32 bits */ + OI_UINT32 I2; /**< least significant 32 bits */ +} OI_UINT64; + +#define OI_UINT64_MIN { (OI_UINT32)0x00000000, (OI_UINT32)0x00000000 } +#define OI_UINT64_MAX { (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF } + +/** signed 64-bit integer as a structure of one unsigned 32-bit integer and one signed 32-bit integer */ +typedef struct { + OI_INT32 I1; /**< most significant 32 bits as a signed integer */ + OI_UINT32 I2; /**< least significant 32 bits as an unsigned integer */ +} OI_INT64; + +#define OI_INT64_MIN { (OI_INT32)0x80000000, (OI_UINT32)0x00000000 } +#define OI_INT64_MAX { (OI_INT32)0X7FFFFFFF, (OI_UINT32)0XFFFFFFFF } + +/** unsigned 128-bit integer as a structure of four unsigned 32-bit integers */ +typedef struct { + OI_UINT32 I1; /**< most significant 32 bits */ + OI_UINT32 I2; /**< second-most significant 32 bits */ + OI_UINT32 I3; /**< third-most significant 32 bits */ + OI_UINT32 I4; /**< least significant 32 bits */ +} OI_UINT128; + +#define OI_UINT128_MIN { (OI_UINT32)0x00000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000 } +#define OI_UINT128_MAX { (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF } + +/** signed 128-bit integer as a structure of three unsigned 32-bit integers and one signed 32-bit integer */ +typedef struct { + OI_INT32 I1; /**< most significant 32 bits as a signed integer */ + OI_UINT32 I2; /**< second-most significant 32 bits as an unsigned integer */ + OI_UINT32 I3; /**< third-most significant 32 bits as an unsigned integer */ + OI_UINT32 I4; /**< least significant 32 bits as an unsigned integer */ +} OI_INT128; + +#define OI_INT128_MIN { (OI_UINT32)0x80000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000 } +#define OI_INT128_MAX { (OI_UINT32)0X7FFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF } + +/** + * @} + */ + + +/** + * type for ASCII character data items + */ +typedef char OI_CHAR; + +/** + * type for double-byte character data items + */ +typedef OI_UINT16 OI_CHAR16; + +/** + * types for UTF encoded strings. + */ +typedef OI_UINT8 OI_UTF8; +typedef OI_UINT16 OI_UTF16; +typedef OI_UINT32 OI_UTF32; + + +/** + * @name Single-bit operation macros + * @{ + * In these macros, x is the data item for which a bit is to be tested or set and y specifies which bit + * is to be tested or set. + */ + +/** This macro's value is TRUE if the bit specified by y is set in data item x. */ +#define OI_BIT_TEST(x,y) ((x) & (y)) + +/** This macro's value is TRUE if the bit specified by y is not set in data item x. */ +#define OI_BIT_CLEAR_TEST(x,y) (((x) & (y)) == 0) + +/** This macro sets the bit specified by y in data item x. */ +#define OI_BIT_SET(x,y) ((x) |= (y)) + +/** This macro clears the bit specified by y in data item x. */ +#define OI_BIT_CLEAR(x,y) ((x) &= ~(y)) + +/** @} */ + +/** + * The OI_ARRAYSIZE macro is set to the number of elements in an array + * (instead of the number of bytes, which is returned by sizeof()). + */ + +#ifndef OI_ARRAYSIZE +#define OI_ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) +#endif + +/** + * @name Preprocessor aliases for individual bit positions + * Bits are defined here only if they are not already defined. + * @{ + */ + +#ifndef BIT0 + +#define BIT0 0x00000001 /**< preprocessor alias for 32-bit value with bit 0 set, used to specify this single bit */ +#define BIT1 0x00000002 /**< preprocessor alias for 32-bit value with bit 1 set, used to specify this single bit */ +#define BIT2 0x00000004 /**< preprocessor alias for 32-bit value with bit 2 set, used to specify this single bit */ +#define BIT3 0x00000008 /**< preprocessor alias for 32-bit value with bit 3 set, used to specify this single bit */ +#define BIT4 0x00000010 /**< preprocessor alias for 32-bit value with bit 4 set, used to specify this single bit */ +#define BIT5 0x00000020 /**< preprocessor alias for 32-bit value with bit 5 set, used to specify this single bit */ +#define BIT6 0x00000040 /**< preprocessor alias for 32-bit value with bit 6 set, used to specify this single bit */ +#define BIT7 0x00000080 /**< preprocessor alias for 32-bit value with bit 7 set, used to specify this single bit */ +#define BIT8 0x00000100 /**< preprocessor alias for 32-bit value with bit 8 set, used to specify this single bit */ +#define BIT9 0x00000200 /**< preprocessor alias for 32-bit value with bit 9 set, used to specify this single bit */ +#define BIT10 0x00000400 /**< preprocessor alias for 32-bit value with bit 10 set, used to specify this single bit */ +#define BIT11 0x00000800 /**< preprocessor alias for 32-bit value with bit 11 set, used to specify this single bit */ +#define BIT12 0x00001000 /**< preprocessor alias for 32-bit value with bit 12 set, used to specify this single bit */ +#define BIT13 0x00002000 /**< preprocessor alias for 32-bit value with bit 13 set, used to specify this single bit */ +#define BIT14 0x00004000 /**< preprocessor alias for 32-bit value with bit 14 set, used to specify this single bit */ +#define BIT15 0x00008000 /**< preprocessor alias for 32-bit value with bit 15 set, used to specify this single bit */ +#define BIT16 0x00010000 /**< preprocessor alias for 32-bit value with bit 16 set, used to specify this single bit */ +#define BIT17 0x00020000 /**< preprocessor alias for 32-bit value with bit 17 set, used to specify this single bit */ +#define BIT18 0x00040000 /**< preprocessor alias for 32-bit value with bit 18 set, used to specify this single bit */ +#define BIT19 0x00080000 /**< preprocessor alias for 32-bit value with bit 19 set, used to specify this single bit */ +#define BIT20 0x00100000 /**< preprocessor alias for 32-bit value with bit 20 set, used to specify this single bit */ +#define BIT21 0x00200000 /**< preprocessor alias for 32-bit value with bit 21 set, used to specify this single bit */ +#define BIT22 0x00400000 /**< preprocessor alias for 32-bit value with bit 22 set, used to specify this single bit */ +#define BIT23 0x00800000 /**< preprocessor alias for 32-bit value with bit 23 set, used to specify this single bit */ +#define BIT24 0x01000000 /**< preprocessor alias for 32-bit value with bit 24 set, used to specify this single bit */ +#define BIT25 0x02000000 /**< preprocessor alias for 32-bit value with bit 25 set, used to specify this single bit */ +#define BIT26 0x04000000 /**< preprocessor alias for 32-bit value with bit 26 set, used to specify this single bit */ +#define BIT27 0x08000000 /**< preprocessor alias for 32-bit value with bit 27 set, used to specify this single bit */ +#define BIT28 0x10000000 /**< preprocessor alias for 32-bit value with bit 28 set, used to specify this single bit */ +#define BIT29 0x20000000 /**< preprocessor alias for 32-bit value with bit 29 set, used to specify this single bit */ +#define BIT30 0x40000000 /**< preprocessor alias for 32-bit value with bit 30 set, used to specify this single bit */ +#define BIT31 0x80000000 /**< preprocessor alias for 32-bit value with bit 31 set, used to specify this single bit */ + +#endif /* BIT0 et al */ + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +/*****************************************************************************/ +#endif /* OI_STDDEFS_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_string.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_string.h new file mode 100755 index 0000000000..1b12b5ab81 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_string.h @@ -0,0 +1,208 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 OI_STRING_H +#define OI_STRING_H +/** + * @file + * This file contains BM3 supplied portable string.h functions + * + */ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#include "oi_cpu_dep.h" +#include "oi_stddefs.h" + +#if defined(USE_NATIVE_MEMCPY) || defined(USE_NATIVE_MALLOC) +#include +#endif + +/** \addtogroup Misc Miscellaneous APIs */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * If we are using Native malloc(), we must also use + * native Ansi string.h functions for memory manipulation. + */ +#ifdef USE_NATIVE_MALLOC +#ifndef USE_NATIVE_MEMCPY +#define USE_NATIVE_MEMCPY +#endif +#endif + +#ifdef USE_NATIVE_MEMCPY + +#define OI_MemCopy(to, from, size) memcpy((to), (from), (size)) +#define OI_MemSet(block, val, size) memset((block), (val), (size)) +#define OI_MemZero(block, size) memset((block), 0, (size)) +#define OI_MemCmp(s1, s2, n) memcmp((s1), (s2), (n)) +#define OI_Strcpy(dest, src) strcpy((dest),(src)) +#define OI_Strcat(dest, src) strcat((dest),(src)) +#define OI_StrLen(str) strlen((str)) +#define OI_Strcmp(s1, s2) strcmp((s1), (s2)) +#define OI_Strncmp(s1, s2, n) strncmp((s1), (s2), (n)) + +#else + +/* + * OI_MemCopy + * + * Copy an arbitrary number of bytes from one memory address to another. + * The underlying implementation is the ANSI memmove() or equivalant, so + * overlapping memory copies will work correctly. + */ +void OI_MemCopy(void *To, void const *From, OI_UINT32 Size); + + +/* + * OI_MemSet + * + * Sets all bytes in a block of memory to the same value + */ +void OI_MemSet(void *Block, OI_UINT8 Val, OI_UINT32 Size); + + +/* + * OI_MemZero + * + * Sets all bytes in a block of memory to zero + */ +void OI_MemZero(void *Block, OI_UINT32 Size); + + +/* + * OI_MemCmp + * + * Compare two blocks of memory + * + * Returns: + * 0, if s1 == s2 + * < 0, if s1 < s2 + * > 0, if s2 > s2 + */ +OI_INT OI_MemCmp(void const *s1, void const *s2, OI_UINT32 n); + +/* + * OI_Strcpy + * + * Copies the Null terminated string from pStr to pDest, and + * returns pDest. + */ + +OI_CHAR* OI_Strcpy(OI_CHAR *pDest, + OI_CHAR const *pStr); + +/* + * OI_Strcat + * + * Concatonates the pStr string to the end of pDest, and + * returns pDest. + */ + +OI_CHAR* OI_Strcat(OI_CHAR *pDest, + OI_CHAR const *pStr) ; + +/* + * OI_StrLen + * + * Calculates the number of OI_CHARs in pStr (not including + * the Null terminator) and returns the value. + */ +OI_UINT OI_StrLen(OI_CHAR const *pStr) ; + +/* + * OI_Strcmp + * + * Compares two Null terminated strings + * + * Returns: + * 0, if s1 == s2 + * < 0, if s1 < s2 + * > 0, if s2 > s2 + */ +OI_INT OI_Strcmp(OI_CHAR const *s1, + OI_CHAR const *s2); + +/* + * OI_Strncmp + * + * Compares the first "len" OI_CHARs of strings s1 and s2. + * + * Returns: + * 0, if s1 == s2 + * < 0, if s1 < s2 + * > 0, if s2 > s2 + */ +OI_INT OI_Strncmp(OI_CHAR const *s1, + OI_CHAR const *s2, + OI_UINT32 len); + + +#endif /* USE_NATIVE_MEMCPY */ + +/* + * OI_StrcmpInsensitive + * + * Compares two Null terminated strings, treating + * the Upper and Lower case of 'A' through 'Z' as + * equivilent. + * + * Returns: + * 0, if s1 == s2 + * < 0, if s1 < s2 + * > 0, if s2 > s2 + */ +OI_INT OI_StrcmpInsensitive(OI_CHAR const *s1, + OI_CHAR const *s2); + +/* + * OI_StrncmpInsensitive + * + * Compares the first "len" OI_CHARs of strings s1 and s2, + * treating the Upper and Lower case of 'A' through 'Z' as + * equivilent. + * + * + * Returns: + * 0, if s1 == s2 + * < 0, if s1 < s2 + * > 0, if s2 > s2 + */ +OI_INT OI_StrncmpInsensitive(OI_CHAR const *s1, + OI_CHAR const *s2, + OI_UINT len); + + + +#ifdef __cplusplus +} +#endif + +/** @} */ + +/*****************************************************************************/ +#endif /* OI_STRING_H */ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_time.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_time.h new file mode 100755 index 0000000000..40b8dfc4d7 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_time.h @@ -0,0 +1,200 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_TIME_H +#define _OI_TIME_H +/** @file + * + * This file provides time type definitions and interfaces to time-related functions. + * + * The stack maintains a 64-bit real-time millisecond clock. The choice of + * milliseconds is for convenience, not accuracy. + * + * Timeouts are specified as tenths of seconds in a 32-bit value. Timeout values + * specified by the Bluetooth specification are usually muliple seconds, so + * accuracy to a tenth of a second is more than adequate. + * + * This file also contains macros to convert between seconds and the Link + * Manager's 1.28-second units. + * + */ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#include "oi_stddefs.h" + + +/** \addtogroup Misc Miscellaneous APIs */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + * Within the core stack timeouts are specified in intervals of tenths of seconds + */ + +typedef OI_UINT16 OI_INTERVAL; +#define OI_INTERVALS_PER_SECOND 10 +#define MSECS_PER_OI_INTERVAL (1000 / OI_INTERVALS_PER_SECOND) + +/** maximum interval (54 min 36.7 sec) */ +#define OI_MAX_INTERVAL 0x7fff + + +/** + * Macro to convert seconds to OI_INTERVAL time units + */ + +#define OI_SECONDS(n) ((OI_INTERVAL) ((n) * OI_INTERVALS_PER_SECOND)) + +/** + * Macro to convert milliseconds to OI_INTERVAL time units (Rounded Up) + */ + +#define OI_MSECONDS(n) ((OI_INTERVAL) ((n + MSECS_PER_OI_INTERVAL - 1) / MSECS_PER_OI_INTERVAL)) + +/** + * Macro to convert minutes to OI_INTERVAL time units + */ + +#define OI_MINUTES(n) ((OI_INTERVAL) ((n) * OI_SECONDS(60))) + +/** Convert an OI_INTERVAL to milliseconds. */ +#define OI_INTERVAL_TO_MILLISECONDS(i) ((i) * MSECS_PER_OI_INTERVAL) + +/** + * The stack depends on relative not absolute time. Any mapping between the + * stack's real-time clock and absolute time and date is implementation-dependent. + */ + +typedef struct { + OI_INT32 seconds; + OI_INT16 mseconds; +} OI_TIME; + +/** + * Convert an OI_TIME to milliseconds. + * + * @param t the time to convert + * + * @return the time in milliseconds + */ +OI_UINT32 OI_Time_ToMS(OI_TIME *t); + + +/** + * This function compares two time values. + * + * @param T1 first time to compare. + * + * @param T2 second time to compare. + * + * @return + @verbatim + -1 if t1 < t2 + 0 if t1 = t2 + +1 if t1 > t2 + @endverbatim + */ + +OI_INT16 OI_Time_Compare(OI_TIME *T1, + OI_TIME *T2); + + +/** + * This function returns the interval between two times to a granularity of 0.1 seconds. + * + * @param Sooner a time value more recent that Later + * + * @param Later a time value later than Sooner + * + * @note The result is an OI_INTERVAL value so this function only works for time intervals + * that are less than about 71 minutes. + * + * @return the time interval between the two times = (Later - Sooner) + */ + +OI_INTERVAL OI_Time_Interval(OI_TIME *Sooner, + OI_TIME *Later); + + + +/** + * This function returns the interval between two times to a granularity of milliseconds. + * + * @param Sooner a time value more recent that Later + * + * @param Later a time value later than Sooner + * + * @note The result is an OI_UINT32 value so this function only works for time intervals + * that are less than about 50 days. + * + * @return the time interval between the two times = (Later - Sooner) + */ + +OI_UINT32 OI_Time_IntervalMsecs(OI_TIME *Sooner, + OI_TIME *Later); + + + +/** + * This function answers the question, Have we reached or gone past the target time? + * + * @param pTargetTime target time + * + * @return TRUE means time now is at or past target time + * FALSE means target time is still some time in the future + */ + +OI_BOOL OI_Time_NowReachedTime(OI_TIME *pTargetTime); + +/** + * Convert seconds to the Link Manager 1.28-second units + * Approximate by using 1.25 conversion factor. + */ + +#define OI_SECONDS_TO_LM_TIME_UNITS(lmUnits) ((lmUnits)<4?(lmUnits):(lmUnits)-((lmUnits)>>2)) + + +/** + * Convert Link Manager 1.28-second units to seconds. + * Approximate by using 1.25 conversion factor. + */ + +#define OI_LM_TIME_UNITS_TO_SECONDS(lmUnits) ((lmUnits) + ((lmUnits)>>2)) + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +/* Include for OI_Time_Now() prototype + * Must be included at end to obtain OI_TIME typedef + */ +#include "oi_osinterface.h" + +/*****************************************************************************/ +#endif /* _OI_TIME_H */ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_utils.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_utils.h new file mode 100755 index 0000000000..5272259bbe --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/include/oi_utils.h @@ -0,0 +1,377 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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 _OI_UTILS_H +#define _OI_UTILS_H +/** + * @file + * + * This file provides the interface for utility functions. + * Among the utilities are strlen (string length), strcmp (string compare), and + * other string manipulation functions. These are provided for those plaforms + * where this functionality is not available in stdlib. + */ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#include +#include "oi_common.h" +#include "oi_string.h" +#include "oi_bt_spec.h" + +/** \addtogroup Misc Miscellaneous APIs */ +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Opaque type for a callback function handle. See OI_ScheduleCallbackFunction() + */ +typedef OI_UINT32 OI_CALLBACK_HANDLE; + + +/** + * Function prototype for a timed procedure callback. + * + * @param arg Value that was passed into the OI_ScheduleCallback() function + * + */ +typedef void (*OI_SCHEDULED_CALLBACK)(void *arg); + + +/** + * Registers a function to be called when a timeout expires. This API uses BLUEmagic's internal + * function dispatch mechanism, so applications that make extensive use of this facility may need to + * increase the value of DispatchTableSize in the configuration block for the dispatcher (see + * oi_bt_stack_config.h). + * + * @param callbackFunction The function that will be called when the timeout expires + * + * @param arg Value that will be returned as the parameter to the callback function. + * + * @param timeout A timeout expressed in OI_INTERVALs (tenths of seconds). This can be + * zero in which case the callback function will be called as soon as + * possible. + * + * @param handle NULL or a pointer receive the callback handle. + * + * @return OI_OK if the function was reqistered, or an error status. + */ +OI_STATUS OI_ScheduleCallbackFunction(OI_SCHEDULED_CALLBACK callbackFunction, + void *arg, + OI_INTERVAL timeout, + OI_CALLBACK_HANDLE *handle); + + +/** + * Cancels a function registered with OI_ScheduleCallbackFunction() before its timer expires. + * + * @param handle handle returned by OI_ScheduleCallbackFunction(). + * + * @return OI_OK if the function was cancelled, or an error status. + */ +OI_STATUS OI_CancelCallbackFunction(OI_CALLBACK_HANDLE handle); + + +/** + * Registers a function to be called when a timeout expires. This version does not return a handle + * so can only be canceled by calling OI_CancelCallback(). + * + * @param callbackFunction The function that will be called when the timeout expires + * + * @param arg Value that will be returned as the parameter to the callback function. + * + * @param timeout A timeout expressed in OI_INTERVALs (tenths of seconds). This can be + * zero in which case the callback function will be called as soon as + * possible. + * + * @return OI_OK if the function was reqistered, or an error status. + */ +#define OI_ScheduleCallback(f, a, t) OI_ScheduleCallbackFunction(f, a, t, NULL); + + +/** + * Cancels a function registered with OI_ScheduleCallback() before its timer expires. This + * function will cancel the first entry matches the indicated callback function pointer. + * + * @param callbackFunction The function that was originally registered + * + * @return OI_OK if the function was cancelled, or an error status. + */ +OI_STATUS OI_CancelCallback(OI_SCHEDULED_CALLBACK callbackFunction); + + +/** + * Parse a Bluetooth device address from the specified string. + * + * @param str the string to parse + * @param addr the parsed address, if successful + * + * @return TRUE if an address was successfully parsed, FALSE otherwise + */ + +OI_BOOL OI_ParseBdAddr(const OI_CHAR *str, + OI_BD_ADDR *addr) ; + +/** + * Printf function for platforms which have no stdio or printf available. + * OI_Printf supports the basic formatting types, with the exception of + * floating point types. Additionally, OI_Printf supports several formats + * specific to BLUEmagic 3.0 software: + * + * \%! prints the string for an #OI_STATUS value. + * @code OI_Printf("There was an error %!", status); @endcode + * + * \%@ prints a hex dump of a buffer. + * Requires a pointer to the buffer and a signed integer length + * (0 for default length). If the buffer is large, only an excerpt will + * be printed. + * @code OI_Printf("Contents of buffer %@", buffer, sizeof(buffer)); @endcode + * + * \%: prints a Bluetooth address in the form "HH:HH:HH:HH:HH:HH". + * Requires a pointer to an #OI_BD_ADDR. + * @code OI_Printf("Bluetooth address %:", &bdaddr); @endcode + * + * \%^ decodes and prints a data element as formatted XML. + * Requires a pointer to an #OI_DATAELEM. + * @code OI_Printf("Service attribute list is:\n%^", &attributes); @endcode + * + * \%/ prints the base file name of a path, that is, the final substring + * following a '/' or '\\' character. Requires a pointer to a null + * terminated string. + * @code OI_Printf("File %/", "c:\\dir1\\dir2\\file.txt"); @endcode + * + * \%~ prints a string, escaping characters as needed to display it in + * ASCII. Requires a pointer to an #OI_PSTR and an #OI_UNICODE_ENCODING + * parameter. + * @code OI_Printf("Identifier %~", &id, OI_UNICODE_UTF16_BE); @endcode + * + * \%[ inserts an ANSI color escape sequence. Requires a single character + * identifying the color to select. Colors are red (r/R), green (g/G), + * blue (b/B), yellow (y/Y), cyan (c/C), magenta (m/M), white (W), + * light-gray (l/L), dark-gray (d/D), and black (0). The lower case is + * dim, the upper case is bright (except in the case of light-gray and + * dark-gray, where bright and dim are identical). Any other value will + * select the default color. + * @code OI_Printf("%[red text %[black %[normal\n", 'r', '0', 0); @endcode + * + * \%a same as \%s, except '\\r' and '\\n' are output as "" and "". + * \%?a is valid, but \%la is not. + * + * \%b prints an integer in base 2. + * @code OI_Printf("Bits are %b", I); @endcode + * + * \%lb prints a long integer in base 2. + * + * \%?b prints the least significant N bits of an integer (or long integer) + * in base 2. Requires the integer and a length N. + * @code OI_Printf("Bottom 4 bits are: %?b", I, 4); @endcode + * + * \%B prints an integer as boolean text, "TRUE" or "FALSE". + * @code OI_Printf("The value 0 is %B, the value 1 is %B", 0, 1); @endcode + * + * \%?s prints a substring up to a specified maximum length. + * Requires a pointer to a string and a length parameter. + * @code OI_Printf("String prefix is %?s", str, 3); @endcode + * + * \%ls same as \%S. + * + * \%S prints a UTF16 string as UTF8 (plain ASCII, plus 8-bit char sequences + * where needed). Requires a pointer to #OI_CHAR16. \%?S is valid. The + * length parameter is in OI_CHAR16 characters. + * + * \%T prints time, formatted as "secs.msecs". + * Requires pointer to #OI_TIME struct, NULL pointer prints current time. + * @code OI_Printf("The time now is %T", NULL); @endcode + * + * @param format The format string + * + */ +void OI_Printf(const OI_CHAR *format, ...); + + +/** + * Var-args version OI_Printf + * + * @param format Same as for OI_Printf. + * + * @param argp Var-args list. + */ +void OI_VPrintf(const OI_CHAR *format, va_list argp); + + +/** + * Writes a formatted string to a buffer. This function supports the same format specifiers as + * OI_Printf(). + * + * @param buffer Destination buffer for the formatted string. + * + * @param bufLen The length of the destination buffer. + * + * @param format The format string + * + * @return Number of characters written or -1 in the case of an error. + */ +OI_INT32 OI_SNPrintf(OI_CHAR *buffer, + OI_UINT16 bufLen, + const OI_CHAR* format, ...); + + +/** + * Var-args version OI_SNPrintf + * + * @param buffer Destination buffer for the formatted string. + * + * @param bufLen The length of the destination buffer. + * + * @param format The format string + * + * @param argp Var-args list. + * + * @return Number of characters written or -1 in the case of an error. + */ +OI_INT32 OI_VSNPrintf(OI_CHAR *buffer, + OI_UINT16 bufLen, + const OI_CHAR *format, va_list argp); + + +/** + * Convert a string to an integer. + * + * @param str the string to parse + * + * @return the integer value of the string or 0 if the string could not be parsed + */ +OI_INT OI_atoi(const OI_CHAR *str); + + +/** + * Parse a signed integer in a string. + * + * Skips leading whitespace (space and tabs only) and parses a decimal or hex string. Hex string + * must be prefixed by "0x". Returns pointer to first character following the integer. Returns the + * pointer passed in if the string does not describe an integer. + * + * @param str String to parse. + * + * @param val Pointer to receive the parsed integer value. + * + * @return A pointer to the first character following the integer or the pointer passed in. + */ +const OI_CHAR* OI_ScanInt(const OI_CHAR *str, + OI_INT32 *val); + + +/** + * Parse an unsigned integer in a string. + * + * Skips leading whitespace (space and tabs only) and parses a decimal or hex string. Hex string + * must be prefixed by "0x". Returns pointer to first character following the integer. Returns the + * pointer passed in if the string does not describe an integer. + * + * @param str String to parse. + * + * @param val Pointer to receive the parsed unsigned integer value. + * + * @return A pointer to the first character following the unsigned integer or the pointer passed in. + */ +const OI_CHAR* OI_ScanUInt(const OI_CHAR *str, + OI_UINT32 *val); + +/** + * Parse a whitespace delimited substring out of a string. + * + * @param str Input string to parse. + * @param outStr Buffer to return the substring + * @param len Length of outStr + * + * + * @return A pointer to the first character following the substring or the pointer passed in. + */ +const OI_CHAR* OI_ScanStr(const OI_CHAR *str, + OI_CHAR *outStr, + OI_UINT16 len); + + +/** + * Parse a string for one of a set of alternative value. Skips leading whitespace (space and tabs + * only) and parses text matching one of the alternative strings. Returns pointer to first character + * following the matched text. + * + * @param str String to parse. + * + * @param alts Alternative matching strings separated by '|' + * + * @param index Pointer to receive the index of the matching alternative, return value is -1 if + * there is no match. + * + * @return A pointer to the first character following the matched value or the pointer passed in + * if there was no matching text. + */ +const OI_CHAR* OI_ScanAlt(const OI_CHAR *str, + const OI_CHAR *alts, + OI_INT *index); + +/** + * Parse a string for a BD Addr. Skips leading whitespace (space and tabs only) and parses a + * Bluetooth device address with nibbles optionally separated by colons. Return pointet to first + * character following the BD Addr. + * + * @param str String to parse. + * + * @param addr Pointer to receive the Bluetooth device address + * + * @return A pointer to the first character following the BD Addr or the pointer passed in. + */ +const OI_CHAR* OI_ScanBdAddr(const OI_CHAR *str, + OI_BD_ADDR *addr); + + +/** Get a character from a digit integer value (0 - 9). */ +#define OI_DigitToChar(d) ((d) + '0') + +/** + * Determine Maximum and Minimum between two arguments. + * + * @param a 1st value + * @param b 2nd value + * + * @return the max or min value between a & b + */ +#define OI_MAX(a, b) (((a) < (b)) ? (b) : (a) ) +#define OI_MIN(a, b) (((a) > (b)) ? (b) : (a) ) + +/** + * Compare two BD_ADDRs + * SAME_BD_ADDR - Boolean: TRUE if they are the same address + */ + +#define SAME_BD_ADDR(x, y) (0 == OI_MemCmp((x),(y),OI_BD_ADDR_BYTE_SIZE) ) + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif /* _OI_UTILS_H */ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/alloc.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/alloc.c new file mode 100755 index 0000000000..f8723f21ab --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/alloc.c @@ -0,0 +1,78 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include +#include + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +PRIVATE OI_STATUS OI_CODEC_SBC_Alloc(OI_CODEC_SBC_COMMON_CONTEXT *common, + OI_UINT32 *codecDataAligned, + OI_UINT32 codecDataBytes, + OI_UINT8 maxChannels, + OI_UINT8 pcmStride) +{ + int i; + size_t filterBufferCount; + size_t subdataSize; + OI_BYTE *codecData = (OI_BYTE*)codecDataAligned; + + if (maxChannels < 1 || maxChannels > 2) { + return OI_STATUS_INVALID_PARAMETERS; + } + + if (pcmStride < 1 || pcmStride > maxChannels) { + return OI_STATUS_INVALID_PARAMETERS; + } + + common->maxChannels = maxChannels; + common->pcmStride = pcmStride; + + /* Compute sizes needed for the memory regions, and bail if we don't have + * enough memory for them. */ + subdataSize = maxChannels * sizeof(common->subdata[0]) * SBC_MAX_BANDS * SBC_MAX_BLOCKS; + if (subdataSize > codecDataBytes) { + return OI_STATUS_OUT_OF_MEMORY; + } + + filterBufferCount = (codecDataBytes - subdataSize) / (sizeof(common->filterBuffer[0][0]) * SBC_MAX_BANDS * maxChannels); + if (filterBufferCount < SBC_CODEC_MIN_FILTER_BUFFERS) { + return OI_STATUS_OUT_OF_MEMORY; + } + common->filterBufferLen = filterBufferCount * SBC_MAX_BANDS; + + /* Allocate memory for the subband data */ + common->subdata = (OI_INT32*)codecData; + codecData += subdataSize; + OI_ASSERT(codecDataBytes >= subdataSize); + codecDataBytes -= subdataSize; + + /* Allocate memory for the synthesis buffers */ + for (i = 0; i < maxChannels; ++i) { + size_t allocSize = common->filterBufferLen * sizeof(common->filterBuffer[0][0]); + common->filterBuffer[i] = (SBC_BUFFER_T*)codecData; + OI_ASSERT(codecDataBytes >= allocSize); + codecData += allocSize; + codecDataBytes -= allocSize; + } + + return OI_OK; +} diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitalloc-sbc.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitalloc-sbc.c new file mode 100755 index 0000000000..8120298d06 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitalloc-sbc.c @@ -0,0 +1,165 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +/** @file +@ingroup codec_internal +*/ + +/**@addgroup codec_internal*/ +/**@{*/ + +#include + +static void dualBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common) +{ + OI_UINT bitcountL; + OI_UINT bitcountR; + OI_UINT bitpoolPreferenceL = 0; + OI_UINT bitpoolPreferenceR = 0; + BITNEED_UNION1 bitneedsL; + BITNEED_UNION1 bitneedsR; + + bitcountL = computeBitneed(common, bitneedsL.uint8, 0, &bitpoolPreferenceL); + bitcountR = computeBitneed(common, bitneedsR.uint8, 1, &bitpoolPreferenceR); + + oneChannelBitAllocation(common, &bitneedsL, 0, bitcountL); + oneChannelBitAllocation(common, &bitneedsR, 1, bitcountR); +} + +static void stereoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common) +{ + const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands; + BITNEED_UNION2 bitneeds; + OI_UINT excess; + OI_INT bitadjust; + OI_UINT bitcount; + OI_UINT sbL; + OI_UINT sbR; + OI_UINT bitpoolPreference = 0; + + bitcount = computeBitneed(common, &bitneeds.uint8[0], 0, &bitpoolPreference); + bitcount += computeBitneed(common, &bitneeds.uint8[nrof_subbands], 1, &bitpoolPreference); + + { + OI_UINT ex; + bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds.uint32, 2 * nrof_subbands, bitcount, &ex); + /* We want the compiler to put excess into a register */ + excess = ex; + } + sbL = 0; + sbR = nrof_subbands; + while (sbL < nrof_subbands) { + excess = allocAdjustedBits(&common->bits.uint8[sbL], bitneeds.uint8[sbL] + bitadjust, excess); + ++sbL; + excess = allocAdjustedBits(&common->bits.uint8[sbR], bitneeds.uint8[sbR] + bitadjust, excess); + ++sbR; + } + sbL = 0; + sbR = nrof_subbands; + while (excess) { + excess = allocExcessBits(&common->bits.uint8[sbL], excess); + ++sbL; + if (!excess) { + break; + } + excess = allocExcessBits(&common->bits.uint8[sbR], excess); + ++sbR; + } + +} + +static const BIT_ALLOC balloc[] = { + monoBitAllocation, /* SBC_MONO */ + dualBitAllocation, /* SBC_DUAL_CHANNEL */ + stereoBitAllocation, /* SBC_STEREO */ + stereoBitAllocation /* SBC_JOINT_STEREO */ +}; + + +PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common) +{ + OI_ASSERT(common->frameInfo.bitpool <= OI_SBC_MaxBitpool(&common->frameInfo)); + OI_ASSERT(common->frameInfo.mode < OI_ARRAYSIZE(balloc)); + + /* + * Using an array of function pointers prevents the compiler from creating a suboptimal + * monolithic inlined bit allocation function. + */ + balloc[common->frameInfo.mode](common); +} + +OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame) +{ + return internal_CalculateBitrate(frame); +} + +/* + * Return the current maximum bitneed and clear it. + */ +OI_UINT8 OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common) +{ + OI_UINT8 max = common->maxBitneed; + + common->maxBitneed = 0; + return max; +} + +/* + * Calculates the bitpool size for a given frame length + */ +OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame, + OI_UINT16 frameLen) +{ + OI_UINT16 nrof_subbands = frame->nrof_subbands; + OI_UINT16 nrof_blocks = frame->nrof_blocks; + OI_UINT16 hdr; + OI_UINT16 bits; + + if (frame->mode == SBC_JOINT_STEREO) { + hdr = 9 * nrof_subbands; + } else { + if (frame->mode == SBC_MONO) { + hdr = 4 * nrof_subbands; + } else { + hdr = 8 * nrof_subbands; + } + if (frame->mode == SBC_DUAL_CHANNEL) { + nrof_blocks *= 2; + } + } + bits = 8 * (frameLen - SBC_HEADER_LEN) - hdr; + return DIVIDE(bits, nrof_blocks); +} + +OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common) +{ + return sizeof(OI_INT16) * common->pcmStride * common->frameInfo.nrof_subbands * common->frameInfo.nrof_blocks; +} + + +OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame) +{ + return internal_CalculateFramelen(frame); +} + +/**@}*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitalloc.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitalloc.c new file mode 100755 index 0000000000..544c470d16 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitalloc.c @@ -0,0 +1,392 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ + ***********************************************************************************/ + +/** +@file + +The functions in this file relate to the allocation of available bits to +subbands within the SBC/eSBC frame, along with support functions for computing +frame length and bitrate. + +@ingroup codec_internal +*/ + +/** +@addtogroup codec_internal +@{ +*/ + +#include "oi_utils.h" +#include + +OI_UINT32 OI_SBC_MaxBitpool(OI_CODEC_SBC_FRAME_INFO *frame) +{ + switch (frame->mode) { + case SBC_MONO: + case SBC_DUAL_CHANNEL: + return 16 * frame->nrof_subbands; + case SBC_STEREO: + case SBC_JOINT_STEREO: + return 32 * frame->nrof_subbands; + } + + ERROR(("Invalid frame mode %d", frame->mode)); + OI_ASSERT(FALSE); + return 0; /* Should never be reached */ +} + + +PRIVATE OI_UINT16 internal_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame) +{ + OI_UINT16 nbits = frame->nrof_blocks * frame->bitpool; + OI_UINT16 nrof_subbands = frame->nrof_subbands; + OI_UINT16 result = nbits; + + if (frame->mode == SBC_JOINT_STEREO) { + result += nrof_subbands + (8 * nrof_subbands); + } else { + if (frame->mode == SBC_DUAL_CHANNEL) { result += nbits; } + if (frame->mode == SBC_MONO) { result += 4*nrof_subbands; } else { result += 8*nrof_subbands; } + } + return SBC_HEADER_LEN + (result + 7) / 8; +} + + +PRIVATE OI_UINT32 internal_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame) +{ + OI_UINT blocksbands; + blocksbands = frame->nrof_subbands * frame->nrof_blocks; + + return DIVIDE(8 * internal_CalculateFramelen(frame) * frame->frequency, blocksbands); +} + + +INLINE OI_UINT16 OI_SBC_CalculateFrameAndHeaderlen(OI_CODEC_SBC_FRAME_INFO *frame, OI_UINT *headerLen_) +{ + OI_UINT headerLen = SBC_HEADER_LEN + frame->nrof_subbands * frame->nrof_channels/2; + + if (frame->mode == SBC_JOINT_STEREO) { headerLen++; } + + *headerLen_ = headerLen; + return internal_CalculateFramelen(frame); +} + + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + + +/* + * Computes the bit need for each sample and as also returns a counts of bit needs that are greater + * than one. This count is used in the first phase of bit allocation. + * + * We also compute a preferred bitpool value that this is the minimum bitpool needed to guarantee + * lossless representation of the audio data. The preferred bitpool may be larger than the bits + * actually required but the only input we have are the scale factors. For example, it takes 2 bits + * to represent values in the range -1 .. +1 but the scale factor is 0. To guarantee lossless + * representation we add 2 to each scale factor and sum them to come up with the preferred bitpool. + * This is not ideal because 0 requires 0 bits but we currently have no way of knowing this. + * + * @param bitneed Array to return bitneeds for each subband + * + * @param ch Channel 0 or 1 + * + * @param preferredBitpool Returns the number of reserved bits + * + * @return The SBC bit need + * + */ +OI_UINT computeBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common, + OI_UINT8 *bitneeds, + OI_UINT ch, + OI_UINT *preferredBitpool) +{ + static const OI_INT8 offset4[4][4] = { + { -1, 0, 0, 0 }, + { -2, 0, 0, 1 }, + { -2, 0, 0, 1 }, + { -2, 0, 0, 1 } + }; + + static const OI_INT8 offset8[4][8] = { + { -2, 0, 0, 0, 0, 0, 0, 1 }, + { -3, 0, 0, 0, 0, 0, 1, 2 }, + { -4, 0, 0, 0, 0, 0, 1, 2 }, + { -4, 0, 0, 0, 0, 0, 1, 2 } + }; + + const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands; + OI_UINT sb; + OI_INT8 *scale_factor = &common->scale_factor[ch ? nrof_subbands : 0]; + OI_UINT bitcount = 0; + OI_UINT8 maxBits = 0; + OI_UINT8 prefBits = 0; + + if (common->frameInfo.alloc == SBC_SNR) { + for (sb = 0; sb < nrof_subbands; sb++) { + OI_INT bits = scale_factor[sb]; + if (bits > maxBits) { + maxBits = bits; + } + if ((bitneeds[sb] = bits) > 1) { + bitcount += bits; + } + prefBits += 2 + bits; + } + } else { + const OI_INT8 *offset; + if (nrof_subbands == 4) { + offset = offset4[common->frameInfo.freqIndex]; + } else { + offset = offset8[common->frameInfo.freqIndex]; + } + for (sb = 0; sb < nrof_subbands; sb++) { + OI_INT bits = scale_factor[sb]; + if (bits > maxBits) { + maxBits = bits; + } + prefBits += 2 + bits; + if (bits) { + bits -= offset[sb]; + if (bits > 0) { + bits /= 2; + } + bits += 5; + } + if ((bitneeds[sb] = bits) > 1) { + bitcount += bits; + } + } + } + common->maxBitneed = OI_MAX(maxBits, common->maxBitneed); + *preferredBitpool += prefBits; + return bitcount; +} + + +/* + * Explanation of the adjustToFitBitpool inner loop. + * + * The inner loop computes the effect of adjusting the bit allocation up or + * down. Allocations must be 0 or in the range 2..16. This is accomplished by + * the following code: + * + * for (s = bands - 1; s >= 0; --s) { + * OI_INT bits = bitadjust + bitneeds[s]; + * bits = bits < 2 ? 0 : bits; + * bits = bits > 16 ? 16 : bits; + * count += bits; + * } + * + * This loop can be optimized to perform 4 operations at a time as follows: + * + * Adjustment is computed as a 7 bit signed value and added to the bitneed. + * + * Negative allocations are zeroed by masking. (n & 0x40) >> 6 puts the + * sign bit into bit 0, adding this to 0x7F give us a mask of 0x80 + * for -ve values and 0x7F for +ve values. + * + * n &= 0x7F + (n & 0x40) >> 6) + * + * Allocations greater than 16 are truncated to 16. Adjusted allocations are in + * the range 0..31 so we know that bit 4 indicates values >= 16. We use this bit + * to create a mask that zeroes bits 0 .. 3 if bit 4 is set. + * + * n &= (15 + (n >> 4)) + * + * Allocations of 1 are disallowed. Add and shift creates a mask that + * eliminates the illegal value + * + * n &= ((n + 14) >> 4) | 0x1E + * + * These operations can be performed in 8 bits without overflowing so we can + * operate on 4 values at once. + */ + + +/* + * Encoder/Decoder + * + * Computes adjustment +/- of bitneeds to fill bitpool and returns overall + * adjustment and excess bits. + * + * @param bitpool The bitpool we have to work within + * + * @param bitneeds An array of bit needs (more acturately allocation prioritities) for each + * subband across all blocks in the SBC frame + * + * @param subbands The number of subbands over which the adkustment is calculated. For mono and + * dual mode this is 4 or 8, for stereo or joint stereo this is 8 or 16. + * + * @param bitcount A starting point for the adjustment + * + * @param excess Returns the excess bits after the adjustment + * + * @return The adjustment. + */ +OI_INT adjustToFitBitpool(const OI_UINT bitpool, + OI_UINT32 *bitneeds, + const OI_UINT subbands, + OI_UINT bitcount, + OI_UINT *excess) +{ + OI_INT maxBitadjust = 0; + OI_INT bitadjust = (bitcount > bitpool) ? -8 : 8; + OI_INT chop = 8; + + /* + * This is essentially a binary search for the optimal adjustment value. + */ + while ((bitcount != bitpool) && chop) { + OI_UINT32 total = 0; + OI_UINT count; + OI_UINT32 adjust4; + OI_INT i; + + adjust4 = bitadjust & 0x7F; + adjust4 |= (adjust4 << 8); + adjust4 |= (adjust4 << 16); + + for (i = (subbands / 4 - 1); i >= 0; --i) { + OI_UINT32 mask; + OI_UINT32 n = bitneeds[i] + adjust4; + mask = 0x7F7F7F7F + ((n & 0x40404040) >> 6); + n &= mask; + mask = 0x0F0F0F0F + ((n & 0x10101010) >> 4); + n &= mask; + mask = (((n + 0x0E0E0E0E) >> 4) | 0x1E1E1E1E); + n &= mask; + total += n; + } + + count = (total & 0xFFFF) + (total >> 16); + count = (count & 0xFF) + (count >> 8); + + chop >>= 1; + if (count > bitpool) { + bitadjust -= chop; + } else { + maxBitadjust = bitadjust; + bitcount = count; + bitadjust += chop; + } + } + + *excess = bitpool - bitcount; + + return maxBitadjust; +} + + +/* + * The bit allocator trys to avoid single bit allocations except as a last resort. So in the case + * where a bitneed of 1 was passed over during the adsjustment phase 2 bits are now allocated. + */ +INLINE OI_INT allocAdjustedBits(OI_UINT8 *dest, + OI_INT bits, + OI_INT excess) +{ + if (bits < 16) { + if (bits > 1) { + if (excess) { + ++bits; + --excess; + } + } else if ((bits == 1) && (excess > 1)) { + bits = 2; + excess -= 2; + } else { + bits = 0; + } + } else { + bits = 16; + } + *dest = (OI_UINT8)bits; + return excess; +} + + +/* + * Excess bits not allocated by allocaAdjustedBits are allocated round-robin. + */ +INLINE OI_INT allocExcessBits(OI_UINT8 *dest, + OI_INT excess) +{ + if (*dest < 16) { + *dest += 1; + return excess - 1; + } else { + return excess; + } +} + +void oneChannelBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common, + BITNEED_UNION1 *bitneeds, + OI_UINT ch, + OI_UINT bitcount) +{ + const OI_UINT8 nrof_subbands = common->frameInfo.nrof_subbands; + OI_UINT excess; + OI_UINT sb; + OI_INT bitadjust; + OI_UINT8 RESTRICT *allocBits; + + + { + OI_UINT ex; + bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds->uint32, nrof_subbands, bitcount, &ex); + /* We want the compiler to put excess into a register */ + excess = ex; + } + + /* + * Allocate adjusted bits + */ + allocBits = &common->bits.uint8[ch ? nrof_subbands : 0]; + + sb = 0; + while (sb < nrof_subbands) { + excess = allocAdjustedBits(&allocBits[sb], bitneeds->uint8[sb] + bitadjust, excess); + ++sb; + } + sb = 0; + while (excess) { + excess = allocExcessBits(&allocBits[sb], excess); + ++sb; + } +} + + +void monoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common) +{ + BITNEED_UNION1 bitneeds; + OI_UINT bitcount; + OI_UINT bitpoolPreference = 0; + + bitcount = computeBitneed(common, bitneeds.uint8, 0, &bitpoolPreference); + + oneChannelBitAllocation(common, &bitneeds, 0, bitcount); +} + +/** +@} +*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitstream-decode.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitstream-decode.c new file mode 100755 index 0000000000..7eb2a90c66 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/bitstream-decode.c @@ -0,0 +1,92 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +/** +@file +Functions for manipulating input bitstreams. + +@ingroup codec_internal +*/ + +/** +@addtogroup codec_internal +@{ +*/ + +#include "oi_stddefs.h" +#include "oi_bitstream.h" +#include "oi_assert.h" + +PRIVATE void OI_BITSTREAM_ReadInit(OI_BITSTREAM *bs, + const OI_BYTE *buffer) +{ + bs->value = ((OI_INT32)buffer[0] << 16) | ((OI_INT32)buffer[1] << 8) | (buffer[2]); + bs->ptr.r = buffer + 3; + bs->bitPtr = 8; +} + +PRIVATE OI_UINT32 OI_BITSTREAM_ReadUINT(OI_BITSTREAM *bs, OI_UINT bits) +{ + OI_UINT32 result; + + OI_BITSTREAM_READUINT(result, bits, bs->ptr.r, bs->value, bs->bitPtr); + + return result; +} + +PRIVATE OI_UINT8 OI_BITSTREAM_ReadUINT4Aligned(OI_BITSTREAM *bs) +{ + OI_UINT32 result; + + OI_ASSERT(bs->bitPtr < 16); + OI_ASSERT(bs->bitPtr % 4 == 0); + + if (bs->bitPtr == 8) { + result = bs->value << 8; + bs->bitPtr = 12; + } else { + result = bs->value << 12; + bs->value = (bs->value << 8) | *bs->ptr.r++; + bs->bitPtr = 8; + } + result >>= 28; + OI_ASSERT(result < (1u << 4)); + return (OI_UINT8)result; +} + +PRIVATE OI_UINT8 OI_BITSTREAM_ReadUINT8Aligned(OI_BITSTREAM *bs) +{ + OI_UINT32 result; + OI_ASSERT(bs->bitPtr == 8); + + result = bs->value >> 16; + bs->value = (bs->value << 8) | *bs->ptr.r++; + + return (OI_UINT8)result; +} + +/** +@} +*/ + + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-oina.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-oina.c new file mode 100755 index 0000000000..93d05ea5f0 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-oina.c @@ -0,0 +1,140 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2006 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ + ***********************************************************************************/ + +/** +@file +This file exposes OINA-specific interfaces to decoder functions. + +@ingroup codec_internal +*/ + +/** +@addtogroup codec_internal +@{ +*/ + + +#include + +OI_STATUS OI_CODEC_SBC_DecoderConfigureRaw(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_BOOL enhanced, + OI_UINT8 frequency, + OI_UINT8 mode, + OI_UINT8 subbands, + OI_UINT8 blocks, + OI_UINT8 alloc, + OI_UINT8 maxBitpool) +{ + if (frequency > SBC_FREQ_48000) { + return OI_STATUS_INVALID_PARAMETERS; + } + + if (enhanced) { +#ifdef SBC_ENHANCED + if (subbands != SBC_SUBBANDS_8) { + return OI_STATUS_INVALID_PARAMETERS; + } +#else + return OI_STATUS_INVALID_PARAMETERS; +#endif + } + + if (mode > SBC_JOINT_STEREO) { + return OI_STATUS_INVALID_PARAMETERS; + } + + if (subbands > SBC_SUBBANDS_8) { + return OI_STATUS_INVALID_PARAMETERS; + } + + if (blocks > SBC_BLOCKS_16) { + return OI_STATUS_INVALID_PARAMETERS; + } + + if (alloc > SBC_SNR) { + return OI_STATUS_INVALID_PARAMETERS; + } + +#ifdef SBC_ENHANCED + context->common.frameInfo.enhanced = enhanced; +#else + context->common.frameInfo.enhanced = FALSE; +#endif + context->common.frameInfo.freqIndex = frequency; + context->common.frameInfo.mode = mode; + context->common.frameInfo.subbands = subbands; + context->common.frameInfo.blocks = blocks; + context->common.frameInfo.alloc = alloc; + context->common.frameInfo.bitpool = maxBitpool; + + OI_SBC_ExpandFrameFields(&context->common.frameInfo); + + if (context->common.frameInfo.nrof_channels >= context->common.pcmStride) { + return OI_STATUS_INVALID_PARAMETERS; + } + + return OI_OK; +} + + + +OI_STATUS OI_CODEC_SBC_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_UINT8 bitpool, + const OI_BYTE **frameData, + OI_UINT32 *frameBytes, + OI_INT16 *pcmData, + OI_UINT32 *pcmBytes) +{ + return internal_DecodeRaw(context, + bitpool, + frameData, + frameBytes, + pcmData, + pcmBytes); +} + +OI_STATUS OI_CODEC_SBC_DecoderLimit(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_BOOL enhanced, + OI_UINT8 subbands) +{ + if (enhanced) + { +#ifdef SBC_ENHANCED + context->enhancedEnabled = TRUE; +#else + context->enhancedEnabled = FALSE; +#endif + } + else + { + context->enhancedEnabled = FALSE; + } + context->restrictSubbands = subbands; + context->limitFrameFormat = TRUE; + return OI_OK; +} + + +/** +@} +*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-private.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-private.c new file mode 100755 index 0000000000..faccbf0e1a --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-private.c @@ -0,0 +1,227 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ + ***********************************************************************************/ + +/** +@file +This file drives SBC decoding. + +@ingroup codec_internal +*/ + +/** +@addtogroup codec_internal +@{ +*/ + +#include "oi_codec_sbc_private.h" +#include "oi_bitstream.h" +#include + +OI_CHAR * const OI_Codec_Copyright = "Copyright 2002-2007 Open Interface North America, Inc. All rights reserved"; + +INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_UINT32 *decoderData, + OI_UINT32 decoderDataBytes, + OI_BYTE maxChannels, + OI_BYTE pcmStride, + OI_BOOL enhanced) +{ + OI_UINT i; + OI_STATUS status; + + for (i = 0; i < sizeof(*context); i++) { + ((char *)context)[i] = 0; + } + +#ifdef SBC_ENHANCED + context->enhancedEnabled = enhanced ? TRUE : FALSE; +#else + context->enhancedEnabled = FALSE; + if (enhanced){ + return OI_STATUS_INVALID_PARAMETERS; + } +#endif + + status = OI_CODEC_SBC_Alloc(&context->common, decoderData, decoderDataBytes, maxChannels, pcmStride); + + if (!OI_SUCCESS(status)) { + return status; + } + + context->common.codecInfo = OI_Codec_Copyright; + context->common.maxBitneed = 0; + context->limitFrameFormat = FALSE; + OI_SBC_ExpandFrameFields(&context->common.frameInfo); + + /*PLATFORM_DECODER_RESET(context);*/ + + return OI_OK; +} + + + + +/** + * Read the SBC header up to but not including the joint stereo mask. The syncword has already been + * examined, and the enhanced mode flag set, by FindSyncword. + */ +INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data) +{ + OI_CODEC_SBC_FRAME_INFO *frame = &common->frameInfo; + OI_UINT8 d1; + + + OI_ASSERT(data[0] == OI_SBC_SYNCWORD || data[0] == OI_SBC_ENHANCED_SYNCWORD); + + /* Avoid filling out all these strucutures if we already remember the values + * from last time. Just in case we get a stream corresponding to data[1] == + * 0, DecoderReset is responsible for ensuring the lookup table entries have + * already been populated + */ + d1 = data[1]; + if (d1 != frame->cachedInfo) { + + frame->freqIndex = (d1 & (BIT7 | BIT6)) >> 6; + frame->frequency = freq_values[frame->freqIndex]; + + frame->blocks = (d1 & (BIT5 | BIT4)) >> 4; + frame->nrof_blocks = block_values[frame->blocks]; + + frame->mode = (d1 & (BIT3 | BIT2)) >> 2; + frame->nrof_channels = channel_values[frame->mode]; + + frame->alloc = (d1 & BIT1) >> 1; + + frame->subbands = (d1 & BIT0); + frame->nrof_subbands = band_values[frame->subbands]; + + frame->cachedInfo = d1; + } + /* + * For decode, the bit allocator needs to know the bitpool value + */ + frame->bitpool = data[2]; + frame->crc = data[3]; +} + + +#define LOW(x) ((x)& 0xf) +#define HIGH(x) ((x) >> 4) + +/* + * Read scalefactor values and prepare the bitstream for OI_SBC_ReadSamples + */ +PRIVATE void OI_SBC_ReadScalefactors(OI_CODEC_SBC_COMMON_CONTEXT *common, + const OI_BYTE *b, + OI_BITSTREAM *bs) +{ + OI_UINT i = common->frameInfo.nrof_subbands * common->frameInfo.nrof_channels; + OI_INT8 *scale_factor = common->scale_factor; + OI_UINT f; + + if (common->frameInfo.nrof_subbands == 8 || common->frameInfo.mode != SBC_JOINT_STEREO) { + if (common->frameInfo.mode == SBC_JOINT_STEREO) { + common->frameInfo.join = *b++; + } else { + common->frameInfo.join = 0; + } + i /= 2; + do { + *scale_factor++ = HIGH(f = *b++); + *scale_factor++ = LOW(f); + } while (--i); + /* + * In this case we know that the scale factors end on a byte boundary so all we need to do + * is initialize the bitstream. + */ + OI_BITSTREAM_ReadInit(bs, b); + } else { + OI_ASSERT(common->frameInfo.nrof_subbands == 4 && common->frameInfo.mode == SBC_JOINT_STEREO); + common->frameInfo.join = HIGH(f = *b++); + i = (i - 1) / 2; + do { + *scale_factor++ = LOW(f); + *scale_factor++ = HIGH(f = *b++); + } while (--i); + *scale_factor++ = LOW(f); + /* + * In 4-subband joint stereo mode, the joint stereo information ends on a half-byte + * boundary, so it's necessary to use the bitstream abstraction to read it, since + * OI_SBC_ReadSamples will need to pick up in mid-byte. + */ + OI_BITSTREAM_ReadInit(bs, b); + *scale_factor++ = OI_BITSTREAM_ReadUINT4Aligned(bs); + } +} + +/** Read quantized subband samples from the input bitstream and expand them. */ +PRIVATE void OI_SBC_ReadSamples(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) +{ + OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common; + OI_UINT nrof_blocks = common->frameInfo.nrof_blocks; + OI_INT32 * RESTRICT s = common->subdata; + OI_UINT8 *ptr = global_bs->ptr.w; + OI_UINT32 value = global_bs->value; + OI_UINT bitPtr = global_bs->bitPtr; + + const OI_UINT iter_count = common->frameInfo.nrof_channels * common->frameInfo.nrof_subbands / 4; + do { + OI_UINT i; + for (i = 0; i < iter_count; ++i) { + OI_UINT32 sf_by4 = ((OI_UINT32*)common->scale_factor)[i]; + OI_UINT32 bits_by4 = common->bits.uint32[i]; + OI_UINT n; + for (n = 0; n < 4; ++n) { + OI_INT32 dequant; + OI_UINT bits; + OI_INT sf; + + if (OI_CPU_BYTE_ORDER == OI_LITTLE_ENDIAN_BYTE_ORDER) { + bits = bits_by4 & 0xFF; + bits_by4 >>= 8; + sf = sf_by4 & 0xFF; + sf_by4 >>= 8; + } else { + bits = (bits_by4 >> 24) & 0xFF; + bits_by4 <<= 8; + sf = (sf_by4 >> 24) & 0xFF; + sf_by4 <<= 8; + } + if (bits) { + OI_UINT32 raw; + OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr); + dequant = OI_SBC_Dequant(raw, sf, bits); + } else { + dequant = 0; + } + *s++ = dequant; + } + } + } while (--nrof_blocks); +} + + + +/** +@} +*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-sbc.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-sbc.c new file mode 100755 index 0000000000..2c3a98d5b0 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/decoder-sbc.c @@ -0,0 +1,465 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2006 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ + ***********************************************************************************/ + +/** @file +@ingroup codec_internal +*/ + +/**@addtogroup codec_internal */ +/**@{*/ + +#include "oi_codec_sbc_private.h" +#include "oi_bitstream.h" + +#define SPECIALIZE_READ_SAMPLES_JOINT + +/** + * Scans through a buffer looking for a codec syncword. If the decoder has been + * set for enhanced operation using OI_CODEC_SBC_DecoderReset(), it will search + * for both a standard and an enhanced syncword. + */ +PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context, + const OI_BYTE **frameData, + OI_UINT32 *frameBytes) +{ +#ifdef SBC_ENHANCED + OI_BYTE search1 = OI_SBC_SYNCWORD; + OI_BYTE search2 = OI_SBC_ENHANCED_SYNCWORD; +#endif // SBC_ENHANCED + + if (*frameBytes == 0) { + return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; + } + +#ifdef SBC_ENHANCED + if (context->limitFrameFormat && context->enhancedEnabled){ + /* If the context is restricted, only search for specified SYNCWORD */ + search1 = search2; + } else if (context->enhancedEnabled == FALSE) { + /* If enhanced is not enabled, only search for classic SBC SYNCWORD*/ + search2 = search1; + } + while (*frameBytes && (**frameData != search1) && (**frameData != search2)) { + (*frameBytes)--; + (*frameData)++; + } + if (*frameBytes) { + /* Syncword found, *frameData points to it, and *frameBytes correctly + * reflects the number of bytes available to read, including the + * syncword. */ + context->common.frameInfo.enhanced = (**frameData == OI_SBC_ENHANCED_SYNCWORD); + return OI_OK; + } else { + /* No syncword was found anywhere in the provided input data. + * *frameData points past the end of the original input, and + * *frameBytes is 0. */ + return OI_CODEC_SBC_NO_SYNCWORD; + } +#else // SBC_ENHANCED + while (*frameBytes && (**frameData != OI_SBC_SYNCWORD)) { + (*frameBytes)--; + (*frameData)++; + } + if (*frameBytes) { + /* Syncword found, *frameData points to it, and *frameBytes correctly + * reflects the number of bytes available to read, including the + * syncword. */ + context->common.frameInfo.enhanced = FALSE; + return OI_OK; + } else { + /* No syncword was found anywhere in the provided input data. + * *frameData points past the end of the original input, and + * *frameBytes is 0. */ + return OI_CODEC_SBC_NO_SYNCWORD; + } +#endif // SBC_ENHANCED +} + +static OI_STATUS DecodeBody(OI_CODEC_SBC_DECODER_CONTEXT *context, + const OI_BYTE *bodyData, + OI_INT16 *pcmData, + OI_UINT32 *pcmBytes, + OI_BOOL allowPartial) +{ + OI_BITSTREAM bs; + OI_UINT frameSamples = context->common.frameInfo.nrof_blocks * context->common.frameInfo.nrof_subbands; + OI_UINT decode_block_count; + + /* + * Based on the header data, make sure that there is enough room to write the output samples. + */ + if (*pcmBytes < (sizeof(OI_INT16) * frameSamples * context->common.pcmStride) && !allowPartial) { + /* If we're not allowing partial decodes, we need room for the entire + * codec frame */ + TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA")); + return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA; + } else if (*pcmBytes < sizeof (OI_INT16) * context->common.frameInfo.nrof_subbands * context->common.pcmStride) { + /* Even if we're allowing partials, we can still only decode on a frame + * boundary */ + return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA; + } + + if (context->bufferedBlocks == 0) { + TRACE(("Reading scalefactors")); + OI_SBC_ReadScalefactors(&context->common, bodyData, &bs); + + TRACE(("Computing bit allocation")); + OI_SBC_ComputeBitAllocation(&context->common); + + TRACE(("Reading samples")); + if (context->common.frameInfo.mode == SBC_JOINT_STEREO) { + OI_SBC_ReadSamplesJoint(context, &bs); + } else { + OI_SBC_ReadSamples(context, &bs); + } + + context->bufferedBlocks = context->common.frameInfo.nrof_blocks; + } + + if (allowPartial) { + decode_block_count = *pcmBytes / sizeof(OI_INT16) / context->common.pcmStride / context->common.frameInfo.nrof_subbands; + + if (decode_block_count > context->bufferedBlocks) { + decode_block_count = context->bufferedBlocks; + } + + } else { + decode_block_count = context->common.frameInfo.nrof_blocks; + } + + TRACE(("Synthesizing frame")); + { + OI_UINT start_block = context->common.frameInfo.nrof_blocks - context->bufferedBlocks; + OI_SBC_SynthFrame(context, pcmData, start_block, decode_block_count); + } + + OI_ASSERT(context->bufferedBlocks >= decode_block_count); + context->bufferedBlocks -= decode_block_count; + + frameSamples = decode_block_count * context->common.frameInfo.nrof_subbands; + + /* + * When decoding mono into a stride-2 array, copy pcm data to second channel + */ + if (context->common.frameInfo.nrof_channels == 1 && context->common.pcmStride == 2) { + OI_UINT i; + for (i = 0; i < frameSamples; ++i) { + pcmData[2*i+1] = pcmData[2*i]; + } + } + + /* + * Return number of pcm bytes generated by the decode operation. + */ + *pcmBytes = frameSamples * sizeof(OI_INT16) * context->common.pcmStride; + if (context->bufferedBlocks > 0) { + return OI_CODEC_SBC_PARTIAL_DECODE; + } else { + return OI_OK; + } +} + +PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_UINT8 bitpool, + const OI_BYTE **frameData, + OI_UINT32 *frameBytes, + OI_INT16 *pcmData, + OI_UINT32 *pcmBytes) +{ + OI_STATUS status; + OI_UINT bodyLen; + + TRACE(("+OI_CODEC_SBC_DecodeRaw")); + + if (context->bufferedBlocks == 0) { + /* + * The bitallocator needs to know the bitpool value. + */ + context->common.frameInfo.bitpool = bitpool; + /* + * Compute the frame length and check we have enough frame data to proceed + */ + bodyLen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo) - SBC_HEADER_LEN; + if (*frameBytes < bodyLen) { + TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA")); + return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; + } + } else { + bodyLen = 0; + } + /* + * Decode the SBC data. Pass TRUE to DecodeBody to allow partial decoding of + * tones. + */ + status = DecodeBody(context, *frameData, pcmData, pcmBytes, TRUE); + if (OI_SUCCESS(status) || status == OI_CODEC_SBC_PARTIAL_DECODE) { + *frameData += bodyLen; + *frameBytes -= bodyLen; + } + TRACE(("-OI_CODEC_SBC_DecodeRaw: %d", status)); + return status; +} + +OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, + OI_UINT32 *decoderData, + OI_UINT32 decoderDataBytes, + OI_UINT8 maxChannels, + OI_UINT8 pcmStride, + OI_BOOL enhanced) +{ + return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced); +} + +OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, + const OI_BYTE **frameData, + OI_UINT32 *frameBytes, + OI_INT16 *pcmData, + OI_UINT32 *pcmBytes) +{ + OI_STATUS status; + OI_UINT framelen; + OI_UINT8 crc; + + TRACE(("+OI_CODEC_SBC_DecodeFrame")); + + TRACE(("Finding syncword")); + status = FindSyncword(context, frameData, frameBytes); + if (!OI_SUCCESS(status)) { + return status; + } + + /* Make sure enough data remains to read the header. */ + if (*frameBytes < SBC_HEADER_LEN) { + TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA")); + return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; + } + + TRACE(("Reading Header")); + OI_SBC_ReadHeader(&context->common, *frameData); + + /* + * Some implementations load the decoder into RAM and use overlays for 4 vs 8 subbands. We need + * to ensure that the SBC parameters for this frame are compatible with the restrictions imposed + * by the loaded overlays. + */ + if (context->limitFrameFormat && (context->common.frameInfo.subbands != context->restrictSubbands)) { + ERROR(("SBC parameters incompatible with loaded overlay")); + return OI_STATUS_INVALID_PARAMETERS; + } + + if (context->common.frameInfo.nrof_channels > context->common.maxChannels) { + ERROR(("SBC parameters incompatible with number of channels specified during reset")); + return OI_STATUS_INVALID_PARAMETERS; + } + + if (context->common.pcmStride < 1 || context->common.pcmStride > 2) { + ERROR(("PCM stride not set correctly during reset")); + return OI_STATUS_INVALID_PARAMETERS; + } + + /* + * At this point a header has been read. However, it's possible that we found a false syncword, + * so the header data might be invalid. Make sure we have enough bytes to read in the + * CRC-protected header, but don't require we have the whole frame. That way, if it turns out + * that we're acting on bogus header data, we don't stall the decoding process by waiting for + * data that we don't actually need. + */ + framelen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo); + if (*frameBytes < framelen) { + TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA")); + return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; + } + + TRACE(("Calculating checksum")); + + crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData); + if (crc != context->common.frameInfo.crc) { + TRACE(("CRC Mismatch: calc=%02x read=%02x\n", crc, context->common.frameInfo.crc)); + TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_CHECKSUM_MISMATCH")); + return OI_CODEC_SBC_CHECKSUM_MISMATCH; + } + +#ifdef OI_DEBUG + /* + * Make sure the bitpool values are sane. + */ + if ((context->common.frameInfo.bitpool < SBC_MIN_BITPOOL) && !context->common.frameInfo.enhanced) { + ERROR(("Bitpool too small: %d (must be >= 2)", context->common.frameInfo.bitpool)); + return OI_STATUS_INVALID_PARAMETERS; + } + if (context->common.frameInfo.bitpool > OI_SBC_MaxBitpool(&context->common.frameInfo)) { + ERROR(("Bitpool too large: %d (must be <= %ld)", context->common.frameInfo.bitpool, OI_SBC_MaxBitpool(&context->common.frameInfo))); + return OI_STATUS_INVALID_PARAMETERS; + } +#endif + + /* + * Now decode the SBC data. Partial decode is not yet implemented for an SBC + * stream, so pass FALSE to decode body to have it enforce the old rule that + * you have to decode a whole packet at a time. + */ + status = DecodeBody(context, *frameData + SBC_HEADER_LEN, pcmData, pcmBytes, FALSE); + if (OI_SUCCESS(status)) { + *frameData += framelen; + *frameBytes -= framelen; + } + TRACE(("-OI_CODEC_SBC_DecodeFrame: %d", status)); + + return status; +} + +OI_STATUS OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, + const OI_BYTE **frameData, + OI_UINT32 *frameBytes) +{ + OI_STATUS status; + OI_UINT framelen; + OI_UINT headerlen; + OI_UINT8 crc; + + status = FindSyncword(context, frameData, frameBytes); + if (!OI_SUCCESS(status)) { + return status; + } + if (*frameBytes < SBC_HEADER_LEN) { + return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; + } + OI_SBC_ReadHeader(&context->common, *frameData); + framelen = OI_SBC_CalculateFrameAndHeaderlen(&context->common.frameInfo, &headerlen); + if (*frameBytes < headerlen) { + return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; + } + crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData); + if (crc != context->common.frameInfo.crc) { + return OI_CODEC_SBC_CHECKSUM_MISMATCH; + } + if (*frameBytes < framelen) { + return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; + } + context->bufferedBlocks = 0; + *frameData += framelen; + *frameBytes -= framelen; + return OI_OK; +} + +OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData, + OI_UINT32 frameBytes) +{ + OI_UINT8 mode; + OI_UINT8 blocks; + OI_UINT8 subbands; + OI_UINT8 frameCount = 0; + OI_UINT frameLen; + + while (frameBytes){ + while (frameBytes && ((frameData[0] & 0xFE) != 0x9C)){ + frameData++; + frameBytes--; + } + + if (frameBytes < SBC_HEADER_LEN) { + return frameCount; + } + + /* Extract and translate required fields from Header */ + subbands = mode = blocks = frameData[1];; + mode = (mode & (BIT3 | BIT2)) >> 2; + blocks = block_values[(blocks & (BIT5 | BIT4)) >> 4]; + subbands = band_values[(subbands & BIT0)]; + + /* Inline logic to avoid corrupting context */ + frameLen = blocks * frameData[2]; + switch (mode){ + case SBC_JOINT_STEREO: + frameLen += subbands + (8 * subbands); + break; + + case SBC_DUAL_CHANNEL: + frameLen *= 2; + /* fall through */ + + default: + if (mode == SBC_MONO){ + frameLen += 4*subbands; + } else { + frameLen += 8*subbands; + } + } + + frameCount++; + frameLen = SBC_HEADER_LEN + (frameLen + 7) / 8; + if (frameBytes > frameLen){ + frameBytes -= frameLen; + frameData += frameLen; + } else { + frameBytes = 0; + } + } + return frameCount; +} + +/** Read quantized subband samples from the input bitstream and expand them. */ + +#ifdef SPECIALIZE_READ_SAMPLES_JOINT + +PRIVATE void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) +{ +#define NROF_SUBBANDS 4 +#include "readsamplesjoint.inc" +#undef NROF_SUBBANDS +} + +PRIVATE void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) +{ +#define NROF_SUBBANDS 8 +#include "readsamplesjoint.inc" +#undef NROF_SUBBANDS +} + +typedef void (*READ_SAMPLES)(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs); + +static const READ_SAMPLES SpecializedReadSamples[] = { + OI_SBC_ReadSamplesJoint4, + OI_SBC_ReadSamplesJoint8 +}; + +#endif /* SPECIALIZE_READ_SAMPLES_JOINT */ + + +PRIVATE void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) +{ + OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common; + OI_UINT nrof_subbands = common->frameInfo.nrof_subbands; +#ifdef SPECIALIZE_READ_SAMPLES_JOINT + OI_ASSERT((nrof_subbands >> 3u) <= 1u); + SpecializedReadSamples[nrof_subbands >> 3](context, global_bs); +#else + +#define NROF_SUBBANDS nrof_subbands +#include "readsamplesjoint.inc" +#undef NROF_SUBBANDS +#endif /* SPECIALIZE_READ_SAMPLES_JOINT */ +} + +/**@}*/ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/dequant.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/dequant.c new file mode 100755 index 0000000000..e06069c1fb --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/dequant.c @@ -0,0 +1,210 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +/** + @file + + Dequantizer for SBC decoder; reconstructs quantized representation of subband samples. + + @ingroup codec_internal + */ + +/** +@addtogroup codec_internal +@{ +*/ + +/** + This function is a fixed-point approximation of a modification of the following + dequantization operation defined in the spec, as inferred from section 12.6.4: + + @code + dequant = 2^(scale_factor+1) * ((raw * 2.0 + 1.0) / ((2^bits) - 1) - 1) + + 2 <= bits <= 16 + 0 <= raw < (2^bits)-1 (the -1 is because quantized values with all 1's are forbidden) + + -65535 < dequant < 65535 + @endcode + + The code below computes the dequantized value divided by a scaling constant + equal to about 1.38. This constant is chosen to ensure that the entry in the + dequant_long_scaled table for 16 bits is as accurate as possible, since it has + the least relative precision available to it due to its small magnitude. + + This routine outputs in Q16.15 format. + + The helper array dequant_long is defined as follows: + + @code + dequant_long_long[bits] = round(2^31 * 1/((2^bits - 1) / 1.38...) for 2 <= bits <= 16 + @endcode + + + Additionally, the table entries have the following property: + + @code + dequant_long_scaled[bits] <= 2^31 / ((2^bits - 1)) for 2 <= bits <= 16 + @endcode + + Therefore + + @code + d = 2 * raw + 1 1 <= d <= 2^bits - 2 + + d' = d * dequant_long[bits] + + d * dequant_long_scaled[bits] <= (2^bits - 2) * (2^31 / (2^bits - 1)) + d * dequant_long_scaled[bits] <= 2^31 * (2^bits - 2)/(2^bits - 1) < 2^31 + @endcode + + Therefore, d' doesn't overflow a signed 32-bit value. + + @code + + d' =~ 2^31 * (raw * 2.0 + 1.0) / (2^bits - 1) / 1.38... + + result = d' - 2^31/1.38... =~ 2^31 * ((raw * 2.0 + 1.0) / (2^bits - 1) - 1) / 1.38... + + result is therefore a scaled approximation to dequant. It remains only to + turn 2^31 into 2^(scale_factor+1). Since we're aiming for Q16.15 format, + this is achieved by shifting right by (15-scale_factor): + + (2^31 * x) >> (15-scale_factor) =~ 2^(31-15+scale_factor) * x = 2^15 * 2^(1+scale_factor) * x + @endcode + + */ + +#include + +#ifndef SBC_DEQUANT_LONG_SCALED_OFFSET +#define SBC_DEQUANT_LONG_SCALED_OFFSET 1555931970 +#endif + +#ifndef SBC_DEQUANT_LONG_UNSCALED_OFFSET +#define SBC_DEQUANT_LONG_UNSCALED_OFFSET 2147483648 +#endif + +#ifndef SBC_DEQUANT_SCALING_FACTOR +#define SBC_DEQUANT_SCALING_FACTOR 1.38019122262781f +#endif + +const OI_UINT32 dequant_long_scaled[17]; +const OI_UINT32 dequant_long_unscaled[17]; + +/** Scales x by y bits to the right, adding a rounding factor. + */ +#ifndef SCALE +#define SCALE(x, y) (((x) + (1 <<((y)-1))) >> (y)) +#endif + +#ifdef DEBUG_DEQUANTIZATION + +#include + +INLINE float dequant_float(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits) +{ + float result = (1 << (scale_factor+1)) * ((raw * 2.0f + 1.0f) / ((1 << bits) - 1.0f) - 1.0f); + + result /= SBC_DEQUANT_SCALING_FACTOR; + + /* Unless the encoder screwed up, all correct dequantized values should + * satisfy this inequality. Non-compliant encoders which generate quantized + * values with all 1-bits set can, theoretically, trigger this assert. This + * is unlikely, however, and only an issue in debug mode. + */ + OI_ASSERT(fabs(result) < 32768 * 1.6); + + return result; +} + +#endif + + +INLINE OI_INT32 OI_SBC_Dequant(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits) +{ + OI_UINT32 d; + OI_INT32 result; + + OI_ASSERT(scale_factor <= 15); + OI_ASSERT(bits <= 16); + + if (bits <= 1) { + return 0; + } + + d = (raw * 2) + 1; + d *= dequant_long_scaled[bits]; + result = d - SBC_DEQUANT_LONG_SCALED_OFFSET; + +#ifdef DEBUG_DEQUANTIZATION + { + OI_INT32 integerized_float_result; + float float_result; + + float_result = dequant_float(raw, scale_factor, bits); + integerized_float_result = (OI_INT32)floor(0.5f+float_result * (1 << 15)); + + /* This detects overflow */ + OI_ASSERT(((result >= 0) && (integerized_float_result >= 0)) || + ((result <= 0) && (integerized_float_result <= 0))); + } +#endif + return result >> (15 - scale_factor); +} + +/* This version of Dequant does not incorporate the scaling factor of 1.38. It + * is intended for use with implementations of the filterbank which are + * hard-coded into a DSP. Output is Q16.4 format, so that after joint stereo + * processing (which leaves the most significant bit equal to the sign bit if + * the encoder is conformant) the result will fit a 24 bit fixed point signed + * value.*/ + +INLINE OI_INT32 OI_SBC_Dequant_Unscaled(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits) +{ + OI_UINT32 d; + OI_INT32 result; + + OI_ASSERT(scale_factor <= 15); + OI_ASSERT(bits <= 16); + + + if (bits <= 1) { + return 0; + } + if (bits == 16) { + result = (raw << 16) + raw - 0x7fff7fff; + return SCALE(result, 24 - scale_factor); + } + + + d = (raw * 2) + 1; + d *= dequant_long_unscaled[bits]; + result = d - 0x80000000; + + return SCALE(result, 24 - scale_factor); +} + +/** +@} +*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/framing-sbc.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/framing-sbc.c new file mode 100755 index 0000000000..88cb2e23a6 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/framing-sbc.c @@ -0,0 +1,54 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +/** @file +@ingroup codec_internal +*/ + +/**@addgroup codec_internal*/ +/**@{*/ + +#include "oi_codec_sbc_private.h" + +const OI_CHAR* const OI_CODEC_SBC_FreqText[] = { "SBC_FREQ_16000", "SBC_FREQ_32000", "SBC_FREQ_44100", "SBC_FREQ_48000" }; +const OI_CHAR* const OI_CODEC_SBC_ModeText[] = { "SBC_MONO", "SBC_DUAL_CHANNEL", "SBC_STEREO", "SBC_JOINT_STEREO" }; +const OI_CHAR* const OI_CODEC_SBC_SubbandsText[] = { "SBC_SUBBANDS_4", "SBC_SUBBANDS_8" }; +const OI_CHAR* const OI_CODEC_SBC_BlocksText[] = { "SBC_BLOCKS_4", "SBC_BLOCKS_8", "SBC_BLOCKS_12", "SBC_BLOCKS_16" }; +const OI_CHAR* const OI_CODEC_SBC_AllocText[] = { "SBC_LOUDNESS", "SBC_SNR" }; + +#ifdef OI_DEBUG +void OI_CODEC_SBC_DumpConfig(OI_CODEC_SBC_FRAME_INFO *frameInfo) +{ + printf("SBC configuration\n"); + printf(" enhanced: %s\n", frameInfo->enhanced ? "TRUE" : "FALSE"); + printf(" frequency: %d\n", frameInfo->frequency); + printf(" subbands: %d\n", frameInfo->nrof_subbands); + printf(" blocks: %d\n", frameInfo->nrof_blocks); + printf(" channels: %d\n", frameInfo->nrof_channels); + printf(" mode: %s\n", OI_CODEC_SBC_ModeText[frameInfo->mode]); + printf(" alloc: %s\n", OI_CODEC_SBC_AllocText[frameInfo->alloc]); + printf(" bitpool: %d\n", frameInfo->bitpool); +} +#endif /* OI_DEBUG */ + +/**@}*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/framing.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/framing.c new file mode 100755 index 0000000000..c94ec90ed6 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/framing.c @@ -0,0 +1,249 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +/** +@file +Checksum and header-related functions. + +@ingroup codec_internal +*/ + +/** +@addtogroup codec_internal +@{ +*/ + +#include "oi_codec_sbc_private.h" +#include "oi_assert.h" + + +/* asdasd */ + +#define USE_NIBBLEWISE_CRC + +/* #define PRINT_SAMPLES */ +/* #define PRINT_SCALEFACTORS */ +/* #define DEBUG_CRC */ + +/* + * CRC-8 table for X^8 + X^4 + X^3 + X^2 + 1; byte-wise lookup + */ +#ifdef USE_WIDE_CRC +/* Save space if a char is 16 bits, such as on the C54x */ +const OI_BYTE crc8_wide[128] = { + 0x001d, 0x3a27, 0x7469, 0x4e53, 0xe8f5, 0xd2cf, 0x9c81, 0xa6bb, 0xcdd0, 0xf7ea, 0xb9a4, 0x839e, 0x2538, 0x1f02, 0x514c, 0x6b76, 0x879a, 0xbda0, 0xf3ee, 0xc9d4, 0x6f72, 0x5548, 0x1b06, 0x213c, 0x4a57, 0x706d, 0x3e23, 0x0419, 0xa2bf, 0x9885, 0xd6cb, 0xecf1, 0x130e, 0x2934, 0x677a, 0x5d40, 0xfbe6, 0xc1dc, 0x8f92, 0xb5a8, 0xdec3, 0xe4f9, 0xaab7, 0x908d, 0x362b, 0x0c11, 0x425f, 0x7865, 0x9489, 0xaeb3, 0xe0fd, 0xdac7, 0x7c61, 0x465b, 0x0815, 0x322f, 0x5944, 0x637e, 0x2d30, 0x170a, 0xb1ac, 0x8b96, 0xc5d8, 0xffe2, 0x263b, 0x1c01, 0x524f, 0x6875, 0xced3, 0xf4e9, 0xbaa7, 0x809d, 0xebf6, 0xd1cc, 0x9f82, 0xa5b8, 0x031e, 0x3924, 0x776a, 0x4d50, 0xa1bc, 0x9b86, 0xd5c8, 0xeff2, 0x4954, 0x736e, 0x3d20, 0x071a, 0x6c71, 0x564b, 0x1805, 0x223f, 0x8499, 0xbea3, 0xf0ed, 0xcad7, 0x3528, 0x0f12, 0x415c, 0x7b66, 0xddc0, 0xe7fa, 0xa9b4, 0x938e, 0xf8e5, 0xc2df, 0x8c91, 0xb6ab, 0x100d, 0x2a37, 0x6479, 0x5e43, 0xb2af, 0x8895, 0xc6db, 0xfce1, 0x5a47, 0x607d, 0x2e33, 0x1409, 0x7f62, 0x4558, 0x0b16, 0x312c, 0x978a, 0xadb0, 0xe3fe, 0xd9c4, +}; +#elif defined(USE_NIBBLEWISE_CRC) +const OI_BYTE crc8_narrow[16] = { + 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb +}; +#else +const OI_BYTE crc8_narrow[256] = { + 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb, 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e, 0x25, 0x38, 0x1f, 0x02, 0x51, 0x4c, 0x6b, 0x76, 0x87, 0x9a, 0xbd, 0xa0, 0xf3, 0xee, 0xc9, 0xd4, 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x06, 0x21, 0x3c, 0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x04, 0x19, 0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1, 0x13, 0x0e, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40, 0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8, 0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, 0x90, 0x8d, 0x36, 0x2b, 0x0c, 0x11, 0x42, 0x5f, 0x78, 0x65, 0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, 0x7c, 0x61, 0x46, 0x5b, 0x08, 0x15, 0x32, 0x2f, 0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0x0a, 0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2, 0x26, 0x3b, 0x1c, 0x01, 0x52, 0x4f, 0x68, 0x75, 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d, 0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, 0x03, 0x1e, 0x39, 0x24, 0x77, 0x6a, 0x4d, 0x50, 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2, 0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x07, 0x1a, 0x6c, 0x71, 0x56, 0x4b, 0x18, 0x05, 0x22, 0x3f, 0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7, 0x35, 0x28, 0x0f, 0x12, 0x41, 0x5c, 0x7b, 0x66, 0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, 0x93, 0x8e, 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab, 0x10, 0x0d, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, 0xb2, 0xaf, 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1, 0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x09, 0x7f, 0x62, 0x45, 0x58, 0x0b, 0x16, 0x31, 0x2c, 0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4 +}; +#endif +const OI_UINT32 dequant_long_scaled[17] = { + 0, + 0, + 0x1ee9e116, /* bits=2 0.24151243 1/3 * (1/1.38019122262781) (0x00000008)*/ + 0x0d3fa99c, /* bits=3 0.10350533 1/7 * (1/1.38019122262781) (0x00000013)*/ + 0x062ec69e, /* bits=4 0.04830249 1/15 * (1/1.38019122262781) (0x00000029)*/ + 0x02fddbfa, /* bits=5 0.02337217 1/31 * (1/1.38019122262781) (0x00000055)*/ + 0x0178d9f5, /* bits=6 0.01150059 1/63 * (1/1.38019122262781) (0x000000ad)*/ + 0x00baf129, /* bits=7 0.00570502 1/127 * (1/1.38019122262781) (0x0000015e)*/ + 0x005d1abe, /* bits=8 0.00284132 1/255 * (1/1.38019122262781) (0x000002bf)*/ + 0x002e760d, /* bits=9 0.00141788 1/511 * (1/1.38019122262781) (0x00000582)*/ + 0x00173536, /* bits=10 0.00070825 1/1023 * (1/1.38019122262781) (0x00000b07)*/ + 0x000b9928, /* bits=11 0.00035395 1/2047 * (1/1.38019122262781) (0x00001612)*/ + 0x0005cc37, /* bits=12 0.00017693 1/4095 * (1/1.38019122262781) (0x00002c27)*/ + 0x0002e604, /* bits=13 0.00008846 1/8191 * (1/1.38019122262781) (0x00005852)*/ + 0x000172fc, /* bits=14 0.00004422 1/16383 * (1/1.38019122262781) (0x0000b0a7)*/ + 0x0000b97d, /* bits=15 0.00002211 1/32767 * (1/1.38019122262781) (0x00016150)*/ + 0x00005cbe, /* bits=16 0.00001106 1/65535 * (1/1.38019122262781) (0x0002c2a5)*/ +}; + + +const OI_UINT32 dequant_long_unscaled[17] = { + 0, + 0, + 0x2aaaaaab, /* bits=2 0.33333333 1/3 (0x00000005)*/ + 0x12492492, /* bits=3 0.14285714 1/7 (0x0000000e)*/ + 0x08888889, /* bits=4 0.06666667 1/15 (0x0000001d)*/ + 0x04210842, /* bits=5 0.03225806 1/31 (0x0000003e)*/ + 0x02082082, /* bits=6 0.01587302 1/63 (0x0000007e)*/ + 0x01020408, /* bits=7 0.00787402 1/127 (0x000000fe)*/ + 0x00808081, /* bits=8 0.00392157 1/255 (0x000001fd)*/ + 0x00402010, /* bits=9 0.00195695 1/511 (0x000003fe)*/ + 0x00200802, /* bits=10 0.00097752 1/1023 (0x000007fe)*/ + 0x00100200, /* bits=11 0.00048852 1/2047 (0x00000ffe)*/ + 0x00080080, /* bits=12 0.00024420 1/4095 (0x00001ffe)*/ + 0x00040020, /* bits=13 0.00012209 1/8191 (0x00003ffe)*/ + 0x00020008, /* bits=14 0.00006104 1/16383 (0x00007ffe)*/ + 0x00010002, /* bits=15 0.00003052 1/32767 (0x0000fffe)*/ + 0x00008001, /* bits=16 0.00001526 1/65535 (0x0001fffc)*/ +}; + +#if defined(OI_DEBUG) || defined(PRINT_SAMPLES) || defined(PRINT_SCALEFACTORS) +#include +#endif + +#ifdef USE_WIDE_CRC +INLINE OI_CHAR crc_iterate(OI_UINT8 oldcrc, OI_UINT8 next) +{ + OI_UINT crc; + OI_UINT idx; + idx = oldcrc^next; + crc = crc8_wide[idx >> 1]; + if (idx%2) { + crc &= 0xff; + } else { + crc >>= 8; + } + + return crc; +} + +INLINE OI_CHAR crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next) +{ + OI_UINT crc; + OI_UINT idx; + idx = (oldcrc ^ next) >> 4; + crc = crc8_wide[idx>>1]; + if (idx%2) { + crc &= 0xff; + } else { + crc >>= 8; + } + + return (oldcrc << 4) ^ crc; +} + +#else // USE_WIDE_CRC + +INLINE OI_UINT8 crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next) +{ + return (oldcrc << 4) ^ crc8_narrow[(oldcrc^next) >> 4]; +} + +#ifdef USE_NIBBLEWISE_CRC +INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next) +{ + crc = (crc << 4) ^ crc8_narrow[(crc^next) >> 4]; + crc = (crc << 4) ^ crc8_narrow[((crc>>4)^next)&0xf]; + + return crc; +} + +#else // USE_NIBBLEWISE_CRC +INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next) +{ + return crc8_narrow[crc^next]; +} + +#endif // USE_NIBBLEWISE_CRC + +#endif // USE_WIDE_CRC + + +PRIVATE OI_UINT8 OI_SBC_CalculateChecksum(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data) +{ + OI_UINT i; + OI_UINT8 crc = 0x0f; + /* Count is the number of whole bytes subject to CRC. Actually, it's one + * more than this number, because data[3] is the CRC field itself, which is + * explicitly skipped. Since crc_iterate (should be) inlined, it's cheaper + * spacewise to include the check in the loop. This shouldn't be much of a + * bottleneck routine in the first place. */ + OI_UINT count = (frame->nrof_subbands * frame->nrof_channels / 2u) + 4; + + if (frame->mode == SBC_JOINT_STEREO && frame->nrof_subbands == 8) { + count++; + } + + for (i = 1; i < count; i++) { + if (i != 3) { + crc = crc_iterate(crc,data[i]); + } + } + + if (frame->mode == SBC_JOINT_STEREO && frame->nrof_subbands == 4) { + crc = crc_iterate_top4(crc, data[i]); + } + + return crc; +} + +void OI_SBC_ExpandFrameFields(OI_CODEC_SBC_FRAME_INFO *frame) +{ + frame->nrof_blocks = block_values[frame->blocks]; + frame->nrof_subbands = band_values[frame->subbands]; + + frame->frequency = freq_values[frame->freqIndex]; + frame->nrof_channels = channel_values[frame->mode]; +} + +/** + * Unrolled macro to copy 4 32-bit aligned 32-bit values backward in memory + */ +#define COPY4WORDS_BACK(_dest, _src) \ + do { \ + OI_INT32 _a, _b, _c, _d; \ + _a = *--_src; \ + _b = *--_src; \ + _c = *--_src; \ + _d = *--_src; \ + *--_dest = _a; \ + *--_dest = _b; \ + *--_dest = _c; \ + *--_dest = _d; \ + } while (0) + + +#if defined(USE_PLATFORM_MEMMOVE) || defined(USE_PLATFORM_MEMCPY) +#include +#endif +PRIVATE void shift_buffer(SBC_BUFFER_T *dest, SBC_BUFFER_T *src, OI_UINT wordCount) +{ +#ifdef USE_PLATFORM_MEMMOVE + memmove(dest, src, wordCount * sizeof(SBC_BUFFER_T)); +#elif defined(USE_PLATFORM_MEMCPY) + OI_ASSERT(((OI_CHAR *)(dest) - (OI_CHAR *)(src)) >= wordCount*sizeof(*dest)); + memcpy(dest, src, wordCount * sizeof(SBC_BUFFER_T)); +#else + OI_UINT n; + OI_INT32 *d; + OI_INT32 *s; + n = wordCount / 4 / (sizeof(OI_INT32)/sizeof(*dest)); + OI_ASSERT((n * 4 * (sizeof(OI_INT32)/sizeof(*dest))) == wordCount); + + d = (void*)(dest + wordCount); + s = (void*)(src + wordCount); + + do { + COPY4WORDS_BACK(d, s); + } while (--n); +#endif +} +/** +@} +*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/oi_codec_version.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/oi_codec_version.c new file mode 100755 index 0000000000..25dc162ae1 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/oi_codec_version.c @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/** +@file +This file contains a single function, which returns a string indicating the +version number of the eSBC codec + +@ingroup codec_internal +*/ + +/** +@addtogroup codec_internal +@{ +*/ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +#include "oi_stddefs.h" +#include "oi_codec_sbc_private.h" + +/** Version string for the BLUEmagic 3.0 protocol stack and profiles */ +PRIVATE OI_CHAR * const codecVersion = "v1.5" +#ifdef OI_SBC_EVAL +" (Evaluation version)" +#endif +; + +/** This function returns the version string for the BLUEmagic 3.0 protocol stack + and profiles */ +OI_CHAR *OI_CODEC_Version(void) { + return codecVersion; +} + +/**********************************************************************************/ + +/** +@} +*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/readsamplesjoint.inc b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/readsamplesjoint.inc new file mode 100755 index 0000000000..875a394975 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/readsamplesjoint.inc @@ -0,0 +1,111 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/******************************************************************************* + * @file readsamplesjoint.inc + * + * This is the body of the generic version of OI_SBC_ReadSamplesJoint(). + * It is designed to be \#included into a function as follows: + \code + void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_COMMON_CONTEXT *common, OI_BITSTREAM *global_bs) + { + #define NROF_SUBBANDS 4 + #include "readsamplesjoint.inc" + #undef NROF_SUBBANDS + } + + void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_COMMON_CONTEXT *common, OI_BITSTREAM *global_bs) + { + #define NROF_SUBBANDS 8 + #include "readsamplesjoint.inc" + #undef NROF_SUBBANDS + } + \endcode + * Or to make a generic version: + \code + void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_COMMON_CONTEXT *common, OI_BITSTREAM *global_bs) + { + OI_UINT nrof_subbands = common->frameInfo.nrof_subbands; + + #define NROF_SUBBANDS nrof_subbands + #include "readsamplesjoint.inc" + #undef NROF_SUBBANDS + } + \endcode + * @ingroup codec_internal + *******************************************************************************/ + +/********************************************************************************** + $Revision: #1 $ +***********************************************************************************/ + +{ + OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common; + OI_UINT bl = common->frameInfo.nrof_blocks; + OI_INT32 * RESTRICT s = common->subdata; + OI_UINT8 *ptr = global_bs->ptr.w; + OI_UINT32 value = global_bs->value; + OI_UINT bitPtr = global_bs->bitPtr; + OI_UINT8 jmask = common->frameInfo.join << (8 - NROF_SUBBANDS); + + do { + OI_INT8 *sf_array = &common->scale_factor[0]; + OI_UINT8 *bits_array = &common->bits.uint8[0]; + OI_UINT8 joint = jmask; + OI_UINT sb; + /* + * Left channel + */ + sb = NROF_SUBBANDS; + do { + OI_UINT32 raw; + OI_INT32 dequant; + OI_UINT8 bits = *bits_array++; + OI_INT sf = *sf_array++; + + OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr); + dequant = OI_SBC_Dequant(raw, sf, bits); + *s++ = dequant; + } while (--sb); + /* + * Right channel + */ + sb = NROF_SUBBANDS; + do { + OI_UINT32 raw; + OI_INT32 dequant; + OI_UINT8 bits = *bits_array++; + OI_INT sf = *sf_array++; + + OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr); + dequant = OI_SBC_Dequant(raw, sf, bits); + /* + * Check if we need to do mid/side + */ + if (joint & 0x80) { + OI_INT32 mid = *(s - NROF_SUBBANDS); + OI_INT32 side = dequant; + *(s - NROF_SUBBANDS) = mid + side; + dequant = mid - side; + } + joint <<= 1; + *s++ = dequant; + } while (--sb); + } while (--bl); +} diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/synthesis-8-generated.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/synthesis-8-generated.c new file mode 100755 index 0000000000..c33498e275 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/decoder/srce/synthesis-8-generated.c @@ -0,0 +1,135 @@ +/****************************************************************************** + * + * Copyright (C) 2014 The Android Open Source Project + * Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved. + * + * 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. + * + ******************************************************************************/ + +/** + @file + + DO NOT EDIT THIS FILE DIRECTLY + + This file is automatically generated by the "synthesis-gen.pl" script. + Any changes to this generated file will be lost when the script is re-run. + + These functions are called by functions in synthesis.c to perform the synthesis + filterbank computations for the SBC decoder. + + + */ + +#include + +#ifndef CLIP_INT16 +#define CLIP_INT16(x) do { if (x > OI_INT16_MAX) { x = OI_INT16_MAX; } else if (x < OI_INT16_MIN) { x = OI_INT16_MIN; } } while (0) +#endif + +#define MUL_16S_16S(_x, _y) ((_x) * (_y)) + +PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRICT buffer, OI_UINT strideShift) +{ + OI_INT32 pcm_a, pcm_b; + /* 1 - stage 0 */ pcm_b = 0; + /* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(8235, buffer[ 12]))>> 3; + /* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(-23167, buffer[ 20]))>> 3; + /* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(26479, buffer[ 28]))>> 2; + /* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(-17397, buffer[ 36]))<< 1; + /* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(9399, buffer[ 44]))<< 3; + /* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(17397, buffer[ 52]))<< 1; + /* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(26479, buffer[ 60]))>> 2; + /* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(23167, buffer[ 68]))>> 3; + /* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(8235, buffer[ 76]))>> 3; + /* 1 - stage 0 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[0<> 5; + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(9293, buffer[ 5]))>> 3; + /* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(29293, buffer[ 11]))>> 5; + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(-6087, buffer[ 11]))>> 2; + /* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(-5229, buffer[ 21])); + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(1247, buffer[ 21]))<< 3; + /* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(30835, buffer[ 27]))>> 3; + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(-2893, buffer[ 27]))<< 3; + /* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(-27021, buffer[ 37]))<< 1; + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(23671, buffer[ 37]))<< 2; + /* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(31633, buffer[ 43]))<< 1; + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(18055, buffer[ 43]))<< 1; + /* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(17319, buffer[ 53]))<< 1; + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(11537, buffer[ 53]))>> 1; + /* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(26663, buffer[ 59]))>> 2; + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(1747, buffer[ 59]))<< 1; + /* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(4555, buffer[ 69]))>> 1; + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(685, buffer[ 69]))<< 1; + /* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(12419, buffer[ 75]))>> 4; + /* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(8721, buffer[ 75]))>> 7; + /* 1 - stage 1 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[1<> 6; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(11167, buffer[ 6]))>> 4; + /* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(24995, buffer[ 10]))>> 5; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(-10337, buffer[ 10]))>> 4; + /* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(-309, buffer[ 22]))<< 4; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(1917, buffer[ 22]))<< 2; + /* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(9161, buffer[ 26]))>> 3; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(-30605, buffer[ 26]))>> 1; + /* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(-23063, buffer[ 38]))<< 1; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(8317, buffer[ 38]))<< 3; + /* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(27561, buffer[ 42]))<< 1; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(9553, buffer[ 42]))<< 2; + /* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(2309, buffer[ 54]))<< 3; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(22117, buffer[ 54]))>> 4; + /* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(12705, buffer[ 58]))>> 1; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(16383, buffer[ 58]))>> 2; + /* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(6239, buffer[ 70]))>> 3; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(7543, buffer[ 70]))>> 3; + /* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(9251, buffer[ 74]))>> 4; + /* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(8603, buffer[ 74]))>> 6; + /* 1 - stage 2 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[2<> 6; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(16913, buffer[ 7]))>> 5; + /* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(19083, buffer[ 9]))>> 5; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(-8443, buffer[ 9]))>> 7; + /* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-23641, buffer[ 23]))>> 2; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(3687, buffer[ 23]))<< 1; + /* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-29015, buffer[ 25]))>> 4; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(-301, buffer[ 25]))<< 5; + /* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-12889, buffer[ 39]))<< 2; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(15447, buffer[ 39]))<< 2; + /* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(6145, buffer[ 41]))<< 3; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(10255, buffer[ 41]))<< 2; + /* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(24211, buffer[ 55]))>> 1; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(-18233, buffer[ 55]))>> 3; + /* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(23469, buffer[ 57]))>> 2; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(9405, buffer[ 57]))>> 1; + /* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(21223, buffer[ 71]))>> 8; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(1499, buffer[ 71]))>> 1; + /* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(26913, buffer[ 73]))>> 6; + /* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(26189, buffer[ 73]))>> 7; + /* 1 - stage 3 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[3<> 4; + /* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(-5297, buffer[ 24]))<< 1; + /* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(22299, buffer[ 40]))<< 2; + /* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(10603, buffer[ 56])); + /* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(9539, buffer[ 72]))>> 4; + /* 1 - stage 4 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[4<> (y)) +#endif + +/** + * Default C language implementation of a 32x32->32 multiply. This function may + * be replaced by a platform-specific version for speed. + * + * @param u A signed 32-bit multiplicand + * @param v A signed 32-bit multiplier + + * @return A signed 32-bit value corresponding to the 32 most significant bits + * of the 64-bit product of u and v. + */ +INLINE OI_INT32 default_mul_32s_32s_hi(OI_INT32 u, OI_INT32 v) +{ + OI_UINT32 u0, v0; + OI_INT32 u1, v1, w1, w2, t; + + u0 = u & 0xFFFF; u1 = u >> 16; + v0 = v & 0xFFFF; v1 = v >> 16; + t = u0*v0; + t = u1*v0 + ((OI_UINT32)t >> 16); + w1 = t & 0xFFFF; + w2 = t >> 16; + w1 = u0*v1 + w1; + return u1*v1 + w2 + (w1 >> 16); +} + +#define MUL_32S_32S_HI(_x, _y) default_mul_32s_32s_hi(_x, _y) + + +#ifdef DEBUG_DCT +PRIVATE void float_dct2_8(float * RESTRICT out, OI_INT32 const *RESTRICT in) +{ +#define FIX(x,bits) (((int)floor(0.5f+((x)*((float)(1<= 8 ? 16 : 0) + and VSIGN(i) maps i%16 into {1, 1, 1, 1, 0, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1 } + These values correspond to the + signs of the redundant values as + shown in the explanation three + paragraphs above. +@endcode + +We saw above how V[4..8,13..15] (and by extension +V[(4..8,13..15)+16*n]) can be defined in terms of other elements +within the subblock of V. V[0..3,9..12] correspond to DCT elements. + +@code + for i=0 to 79 do + W[i] = D[i]*DSIGN(i)*DCT[remap_DCT(i)] +@endcode + +The DCT is calculated using the Arai-Agui-Nakajima factorization, +which saves some computation by producing output that needs to be +multiplied by scaling factors before being used. + +@code + for i=0 to 79 do + W[i] = D[i]*SCALE[i%8]*AAN_DCT[remap_DCT(i)] +@endcode + +D can be premultiplied with the DCT scaling factors to yield + +@code + for i=0 to 79 do + W[i] = DSCALED[i]*AAN_DCT[remap_DCT(i)] where DSCALED[i] = D[i]*SCALE[i%8] +@endcode + +The output samples X[0..7] are defined as sums of W: + +@code + X[j] = sum{i=0..9}(W[j+8*i]) +@endcode + +@ingroup codec_internal +*/ + +/** +@addtogroup codec_internal +@{ +*/ + +#include "oi_codec_sbc_private.h" + +const OI_INT32 dec_window_4[21] = { + 0, /* +0.00000000E+00 */ + 97, /* +5.36548976E-04 */ + 270, /* +1.49188357E-03 */ + 495, /* +2.73370904E-03 */ + 694, /* +3.83720193E-03 */ + 704, /* +3.89205149E-03 */ + 338, /* +1.86581691E-03 */ + -554, /* -3.06012286E-03 */ + 1974, /* +1.09137620E-02 */ + 3697, /* +2.04385087E-02 */ + 5224, /* +2.88757392E-02 */ + 5824, /* +3.21939290E-02 */ + 4681, /* +2.58767811E-02 */ + 1109, /* +6.13245186E-03 */ + -5214, /* -2.88217274E-02 */ + -14047, /* -7.76463494E-02 */ + 24529, /* +1.35593274E-01 */ + 35274, /* +1.94987841E-01 */ + 44618, /* +2.46636662E-01 */ + 50984, /* +2.81828203E-01 */ + 53243, /* +2.94315332E-01 */ +}; + +#define DCTII_4_K06_FIX ( 11585)/* S1.14 11585 0.707107*/ + +#define DCTII_4_K08_FIX ( 21407)/* S1.14 21407 1.306563*/ + +#define DCTII_4_K09_FIX (-15137)/* S1.14 -15137 -0.923880*/ + +#define DCTII_4_K10_FIX ( -8867)/* S1.14 -8867 -0.541196*/ + +/** Scales x by y bits to the right, adding a rounding factor. + */ +#ifndef SCALE +#define SCALE(x, y) (((x) + (1 <<((y)-1))) >> (y)) +#endif + +#ifndef CLIP_INT16 +#define CLIP_INT16(x) do { if (x > OI_INT16_MAX) { x = OI_INT16_MAX; } else if (x < OI_INT16_MIN) { x = OI_INT16_MIN; } } while (0) +#endif + +/** + * Default C language implementation of a 16x32->32 multiply. This function may + * be replaced by a platform-specific version for speed. + * + * @param u A signed 16-bit multiplicand + * @param v A signed 32-bit multiplier + + * @return A signed 32-bit value corresponding to the 32 most significant bits + * of the 48-bit product of u and v. + */ +INLINE OI_INT32 default_mul_16s_32s_hi(OI_INT16 u, OI_INT32 v) +{ + OI_UINT16 v0; + OI_INT16 v1; + + OI_INT32 w,x; + + v0 = (OI_UINT16)(v & 0xffff); + v1 = (OI_INT16) (v >> 16); + + w = v1 * u; + x = u * v0; + + return w + (x >> 16); +} + +#define MUL_16S_32S_HI(_x, _y) default_mul_16s_32s_hi(_x, _y) + +#define LONG_MULT_DCT(K, sample) (MUL_16S_32S_HI(K, sample)<<2) + +PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRICT buffer, OI_UINT strideShift); +PRIVATE void SynthWindow112_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRICT buffer, OI_UINT strideShift); +PRIVATE void dct2_8(SBC_BUFFER_T * RESTRICT out, OI_INT32 const * RESTRICT x); + +typedef void (*SYNTH_FRAME)(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT blkstart, OI_UINT blkcount); + +#ifndef COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS +#define COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(dest, src) do { shift_buffer(dest, src, 72); } while (0) +#endif + +#ifndef DCT2_8 +#define DCT2_8(dst, src) dct2_8(dst, src) +#endif + +#ifndef SYNTH80 +#define SYNTH80 SynthWindow80_generated +#endif + +#ifndef SYNTH112 +#define SYNTH112 SynthWindow112_generated +#endif + +PRIVATE void OI_SBC_SynthFrame_80(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT blkstart, OI_UINT blkcount) +{ + OI_UINT blk; + OI_UINT ch; + OI_UINT nrof_channels = context->common.frameInfo.nrof_channels; + OI_UINT pcmStrideShift = context->common.pcmStride == 1 ? 0 : 1; + OI_UINT offset = context->common.filterBufferOffset; + OI_INT32 *s = context->common.subdata + 8 * nrof_channels * blkstart; + OI_UINT blkstop = blkstart + blkcount; + + for (blk = blkstart; blk < blkstop; blk++) { + if (offset == 0) { + COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(context->common.filterBuffer[0] + context->common.filterBufferLen - 72, context->common.filterBuffer[0]); + if (nrof_channels == 2) { + COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(context->common.filterBuffer[1] + context->common.filterBufferLen - 72, context->common.filterBuffer[1]); + } + offset = context->common.filterBufferLen - 80; + } else { + offset -= 1*8; + } + + for (ch = 0; ch < nrof_channels; ch++) { + DCT2_8(context->common.filterBuffer[ch] + offset, s); + SYNTH80(pcm + ch, context->common.filterBuffer[ch] + offset, pcmStrideShift); + s += 8; + } + pcm += (8 << pcmStrideShift); + } + context->common.filterBufferOffset = offset; +} + +PRIVATE void OI_SBC_SynthFrame_4SB(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT blkstart, OI_UINT blkcount) +{ + OI_UINT blk; + OI_UINT ch; + OI_UINT nrof_channels = context->common.frameInfo.nrof_channels; + OI_UINT pcmStrideShift = context->common.pcmStride == 1 ? 0 : 1; + OI_UINT offset = context->common.filterBufferOffset; + OI_INT32 *s = context->common.subdata + 8 * nrof_channels * blkstart; + OI_UINT blkstop = blkstart + blkcount; + + for (blk = blkstart; blk < blkstop; blk++) { + if (offset == 0) { + COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(context->common.filterBuffer[0] + context->common.filterBufferLen - 72,context->common.filterBuffer[0]); + if (nrof_channels == 2) { + COPY_BACKWARD_32BIT_ALIGNED_72_HALFWORDS(context->common.filterBuffer[1] + context->common.filterBufferLen - 72,context->common.filterBuffer[1]); + } + offset =context->common.filterBufferLen - 80; + } else { + offset -= 8; + } + for (ch = 0; ch < nrof_channels; ch++) { + cosineModulateSynth4(context->common.filterBuffer[ch] + offset, s); + SynthWindow40_int32_int32_symmetry_with_sum(pcm + ch, + context->common.filterBuffer[ch] + offset, + pcmStrideShift); + s += 4; + } + pcm += (4 << pcmStrideShift); + } + context->common.filterBufferOffset = offset; +} + +#ifdef SBC_ENHANCED + +PRIVATE void OI_SBC_SynthFrame_Enhanced(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT blkstart, OI_UINT blkcount) +{ + OI_UINT blk; + OI_UINT ch; + OI_UINT nrof_channels = context->common.frameInfo.nrof_channels; + OI_UINT pcmStrideShift = context->common.pcmStride == 1 ? 0 : 1; + OI_UINT offset = context->common.filterBufferOffset; + OI_INT32 *s = context->common.subdata + 8 * nrof_channels * blkstart; + OI_UINT blkstop = blkstart + blkcount; + + for (blk = blkstart; blk < blkstop; blk++) { + if (offset == 0) { + COPY_BACKWARD_32BIT_ALIGNED_104_HALFWORDS(context->common.filterBuffer[0] +context->common.filterBufferLen - 104, context->common.filterBuffer[0]); + if (nrof_channels == 2) { + COPY_BACKWARD_32BIT_ALIGNED_104_HALFWORDS(context->common.filterBuffer[1] + context->common.filterBufferLen - 104, context->common.filterBuffer[1]); + } + offset = context->common.filterBufferLen - 112; + } else { + offset -= 8; + } + for (ch = 0; ch < nrof_channels; ++ch) { + DCT2_8(context->common.filterBuffer[ch] + offset, s); + SYNTH112(pcm + ch, context->common.filterBuffer[ch] + offset, pcmStrideShift); + s += 8; + } + pcm += (8 << pcmStrideShift); + } + context->common.filterBufferOffset = offset; +} + +static const SYNTH_FRAME SynthFrameEnhanced[] = { + NULL, /* invalid */ + OI_SBC_SynthFrame_Enhanced, /* mono */ + OI_SBC_SynthFrame_Enhanced /* stereo */ +}; + +#endif + +static const SYNTH_FRAME SynthFrame8SB[] = { + NULL, /* invalid */ + OI_SBC_SynthFrame_80, /* mono */ + OI_SBC_SynthFrame_80 /* stereo */ +}; + + +static const SYNTH_FRAME SynthFrame4SB[] = { + NULL, /* invalid */ + OI_SBC_SynthFrame_4SB, /* mono */ + OI_SBC_SynthFrame_4SB /* stereo */ +}; + +PRIVATE void OI_SBC_SynthFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT start_block, OI_UINT nrof_blocks) +{ + OI_UINT nrof_subbands = context->common.frameInfo.nrof_subbands; + OI_UINT nrof_channels = context->common.frameInfo.nrof_channels; + + OI_ASSERT(nrof_subbands == 4 || nrof_subbands == 8); + if (nrof_subbands == 4) { + SynthFrame4SB[nrof_channels](context, pcm, start_block, nrof_blocks); +#ifdef SBC_ENHANCED + } else if (context->common.frameInfo.enhanced) { + SynthFrameEnhanced[nrof_channels](context, pcm, start_block, nrof_blocks); +#endif /* SBC_ENHANCED */ + } else { + SynthFrame8SB[nrof_channels](context, pcm, start_block, nrof_blocks); + } +} + + +void SynthWindow40_int32_int32_symmetry_with_sum(OI_INT16 *pcm, SBC_BUFFER_T buffer[80], OI_UINT strideShift) +{ + OI_INT32 pa; + OI_INT32 pb; + + /* These values should be zero, since out[2] of the 4-band cosine modulation + * is always zero. */ + OI_ASSERT(buffer[ 2] == 0); + OI_ASSERT(buffer[10] == 0); + OI_ASSERT(buffer[18] == 0); + OI_ASSERT(buffer[26] == 0); + OI_ASSERT(buffer[34] == 0); + OI_ASSERT(buffer[42] == 0); + OI_ASSERT(buffer[50] == 0); + OI_ASSERT(buffer[58] == 0); + OI_ASSERT(buffer[66] == 0); + OI_ASSERT(buffer[74] == 0); + + + pa = dec_window_4[ 4] * (buffer[12] + buffer[76]); + pa += dec_window_4[ 8] * (buffer[16] - buffer[64]); + pa += dec_window_4[12] * (buffer[28] + buffer[60]); + pa += dec_window_4[16] * (buffer[32] - buffer[48]); + pa += dec_window_4[20] * buffer[44]; + pa = SCALE(-pa, 15); + CLIP_INT16(pa); + pcm[0 << strideShift] = (OI_INT16)pa; + + + pa = dec_window_4[ 1] * buffer[ 1]; pb = dec_window_4[ 1] * buffer[79]; + pb += dec_window_4[ 3] * buffer[ 3]; pa += dec_window_4[ 3] * buffer[77]; + pa += dec_window_4[ 5] * buffer[13]; pb += dec_window_4[ 5] * buffer[67]; + pb += dec_window_4[ 7] * buffer[15]; pa += dec_window_4[ 7] * buffer[65]; + pa += dec_window_4[ 9] * buffer[17]; pb += dec_window_4[ 9] * buffer[63]; + pb += dec_window_4[11] * buffer[19]; pa += dec_window_4[11] * buffer[61]; + pa += dec_window_4[13] * buffer[29]; pb += dec_window_4[13] * buffer[51]; + pb += dec_window_4[15] * buffer[31]; pa += dec_window_4[15] * buffer[49]; + pa += dec_window_4[17] * buffer[33]; pb += dec_window_4[17] * buffer[47]; + pb += dec_window_4[19] * buffer[35]; pa += dec_window_4[19] * buffer[45]; + pa = SCALE(-pa, 15); + CLIP_INT16(pa); + pcm[1 << strideShift] = (OI_INT16)(pa); + pb = SCALE(-pb, 15); + CLIP_INT16(pb); + pcm[3 << strideShift] = (OI_INT16)(pb); + + + pa = dec_window_4[2] * (/*buffer[ 2] + */ buffer[78]); /* buffer[ 2] is always zero */ + pa += dec_window_4[6] * (buffer[14] /* + buffer[66]*/); /* buffer[66] is always zero */ + pa += dec_window_4[10] * (/*buffer[18] + */ buffer[62]); /* buffer[18] is always zero */ + pa += dec_window_4[14] * (buffer[30] /* + buffer[50]*/); /* buffer[50] is always zero */ + pa += dec_window_4[18] * (/*buffer[34] + */ buffer[46]); /* buffer[34] is always zero */ + pa = SCALE(-pa, 15); + CLIP_INT16(pa); + pcm[2 << strideShift] = (OI_INT16)(pa); +} + + +/** + This routine implements the cosine modulation matrix for 4-subband + synthesis. This is called "matrixing" in the SBC specification. This + matrix, M4, can be factored into an 8-point Type II Discrete Cosine + Transform, DCTII_4 and a matrix S4, given here: + + @code + __ __ + | 0 0 1 0 | + | 0 0 0 1 | + | 0 0 0 0 | + | 0 0 0 -1 | + S4 = | 0 0 -1 0 | + | 0 -1 0 0 | + | -1 0 0 0 | + |__ 0 -1 0 0 __| + + M4 * in = S4 * (DCTII_4 * in) + @endcode + + (DCTII_4 * in) is computed using a Fast Cosine Transform. The algorithm + here is based on an implementation computed by the SPIRAL computer + algebra system, manually converted to fixed-point arithmetic. S4 can be + implemented using only assignment and negation. + */ +PRIVATE void cosineModulateSynth4(SBC_BUFFER_T * RESTRICT out, OI_INT32 const * RESTRICT in) +{ + OI_INT32 f0, f1, f2, f3, f4, f7, f8, f9, f10; + OI_INT32 y0, y1, y2, y3; + + f0 = (in[0] - in[3]); + f1 = (in[0] + in[3]); + f2 = (in[1] - in[2]); + f3 = (in[1] + in[2]); + + f4 = f1 - f3; + + y0 = -SCALE(f1 + f3, DCT_SHIFT); + y2 = -SCALE(LONG_MULT_DCT(DCTII_4_K06_FIX, f4), DCT_SHIFT); + f7 = f0 + f2; + f8 = LONG_MULT_DCT(DCTII_4_K08_FIX, f0); + f9 = LONG_MULT_DCT(DCTII_4_K09_FIX, f7); + f10 = LONG_MULT_DCT(DCTII_4_K10_FIX, f2); + y3 = -SCALE(f8 + f9, DCT_SHIFT); + y1 = -SCALE(f10 - f9, DCT_SHIFT); + + out[0] = (OI_INT16)-y2; + out[1] = (OI_INT16)-y3; + out[2] = (OI_INT16)0; + out[3] = (OI_INT16)y3; + out[4] = (OI_INT16)y2; + out[5] = (OI_INT16)y1; + out[6] = (OI_INT16)y0; + out[7] = (OI_INT16)y1; +} + + + +/** +@} +*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_dct.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_dct.h new file mode 100755 index 0000000000..245e65d139 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_dct.h @@ -0,0 +1,91 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Definitions for the fast DCT. + * + ******************************************************************************/ + +#ifndef SBC_DCT_H +#define SBC_DCT_H + +#if (SBC_ARM_ASM_OPT==TRUE) +#define SBC_MULT_32_16_SIMPLIFIED(s16In2, s32In1, s32OutLow) \ +{ \ + __asm \ +{ \ + MUL s32OutLow,(SINT32)s16In2, (s32In1>>15) \ +} \ +} +#else +#if (SBC_DSP_OPT==TRUE) +#define SBC_MULT_32_16_SIMPLIFIED(s16In2, s32In1 , s32OutLow) s32OutLow = SBC_Multiply_32_16_Simplified((SINT32)s16In2,s32In1); +#else +#if (SBC_IPAQ_OPT==TRUE) +/*#define SBC_MULT_32_16_SIMPLIFIED(s16In2, s32In1 , s32OutLow) s32OutLow=(SINT32)((SINT32)(s16In2)*(SINT32)(s32In1>>15)); */ +#define SBC_MULT_32_16_SIMPLIFIED(s16In2, s32In1 , s32OutLow) s32OutLow=(SINT32)(((SINT64)s16In2*(SINT64)s32In1)>>15); +#if (SBC_IS_64_MULT_IN_IDCT == TRUE) +#define SBC_MULT_32_32(s32In2, s32In1, s32OutLow) \ +{ \ + s64Temp = ((SINT64) s32In2) * ((SINT64) s32In1)>>31; \ + s32OutLow = (SINT32) s64Temp; \ +} +#endif +#else +#define SBC_MULT_32_16_SIMPLIFIED(s16In2, s32In1 , s32OutLow) \ +{ \ + s32In1Temp = s32In1; \ + s32In2Temp = (SINT32)s16In2; \ + \ + /* Multiply one +ve and the other -ve number */ \ + if (s32In1Temp < 0) \ + { \ + s32In1Temp ^= 0xFFFFFFFF; \ + s32In1Temp++; \ + s32OutLow = (s32In2Temp * (s32In1Temp >> 16)); \ + s32OutLow += (( s32In2Temp * (s32In1Temp & 0xFFFF)) >> 16); \ + s32OutLow ^= 0xFFFFFFFF; \ + s32OutLow++; \ + } \ + else \ + { \ + s32OutLow = (s32In2Temp * (s32In1Temp >> 16)); \ + s32OutLow += (( s32In2Temp * (s32In1Temp & 0xFFFF)) >> 16); \ + } \ + s32OutLow <<= 1; \ +} +#if (SBC_IS_64_MULT_IN_IDCT == TRUE) +#define SBC_MULT_64(s32In1, s32In2, s32OutLow, s32OutHi) \ +{\ + s32OutLow=(SINT32)(((SINT64)s32In1*(SINT64)s32In2)& 0x00000000FFFFFFFF);\ + s32OutHi=(SINT32)(((SINT64)s32In1*(SINT64)s32In2)>>32);\ +} +#define SBC_MULT_32_32(s32In2, s32In1, s32OutLow) \ +{ \ + s32HiTemp = 0; \ + SBC_MULT_64(s32In2,s32In1 , s32OutLow, s32HiTemp); \ + s32OutLow = (((s32OutLow>>15)&0x1FFFF) | (s32HiTemp << 17)); \ +} +#endif + +#endif +#endif +#endif + +#endif diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_enc_func_declare.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_enc_func_declare.h new file mode 100755 index 0000000000..2ac34ff75a --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_enc_func_declare.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Function declarations. + * + ******************************************************************************/ + +#ifndef SBC_FUNCDECLARE_H +#define SBC_FUNCDECLARE_H + +/*#include "sbc_encoder.h"*/ +/* Global data */ +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == FALSE) +extern const SINT16 gas32CoeffFor4SBs[]; +extern const SINT16 gas32CoeffFor8SBs[]; +#else +extern const SINT32 gas32CoeffFor4SBs[]; +extern const SINT32 gas32CoeffFor8SBs[]; +#endif + +/* Global functions*/ + +extern void sbc_enc_bit_alloc_mono(SBC_ENC_PARAMS *CodecParams); +extern void sbc_enc_bit_alloc_ste(SBC_ENC_PARAMS *CodecParams); + +extern void SbcAnalysisInit (void); + +extern void SbcAnalysisFilter4(SBC_ENC_PARAMS *strEncParams); +extern void SbcAnalysisFilter8(SBC_ENC_PARAMS *strEncParams); + +extern void SBC_FastIDCT8 (SINT32 *pInVect, SINT32 *pOutVect); +extern void SBC_FastIDCT4 (SINT32 *x0, SINT32 *pOutVect); + +extern void EncPacking(SBC_ENC_PARAMS *strEncParams); +extern void EncQuantizer(SBC_ENC_PARAMS *); +#if (SBC_DSP_OPT==TRUE) + SINT32 SBC_Multiply_32_16_Simplified(SINT32 s32In2Temp,SINT32 s32In1Temp); +#endif +#endif + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_encoder.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_encoder.h new file mode 100755 index 0000000000..a1c963f3e1 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_encoder.h @@ -0,0 +1,202 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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 constants and structures used by Encoder. + * + ******************************************************************************/ + +#ifndef SBC_ENCODER_H +#define SBC_ENCODER_H + +#define ENCODER_VERSION "0025" + +#ifdef BUILDCFG + #include "bt_target.h" +#endif + +/*DEFINES*/ +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#define SBC_MAX_NUM_OF_SUBBANDS 8 +#define SBC_MAX_NUM_OF_CHANNELS 2 +#define SBC_MAX_NUM_OF_BLOCKS 16 + +#define SBC_LOUDNESS 0 +#define SBC_SNR 1 + +#define SUB_BANDS_8 8 +#define SUB_BANDS_4 4 + +#define SBC_sf16000 0 +#define SBC_sf32000 1 +#define SBC_sf44100 2 +#define SBC_sf48000 3 + +#define SBC_MONO 0 +#define SBC_DUAL 1 +#define SBC_STEREO 2 +#define SBC_JOINT_STEREO 3 + +#define SBC_BLOCK_0 4 +#define SBC_BLOCK_1 8 +#define SBC_BLOCK_2 12 +#define SBC_BLOCK_3 16 + +#define SBC_NULL 0 + +#ifndef SBC_MAX_NUM_FRAME +#define SBC_MAX_NUM_FRAME 1 +#endif + +#ifndef SBC_DSP_OPT +#define SBC_DSP_OPT FALSE +#endif + +/* Set SBC_USE_ARM_PRAGMA to TRUE to use "#pragma arm section zidata" */ +#ifndef SBC_USE_ARM_PRAGMA +#define SBC_USE_ARM_PRAGMA FALSE +#endif + +/* Set SBC_ARM_ASM_OPT to TRUE in case the target is an ARM */ +/* this will replace all the 32 and 64 bit mult by in line assembly code */ +#ifndef SBC_ARM_ASM_OPT +#define SBC_ARM_ASM_OPT FALSE +#endif + +/* green hill compiler option -> Used to distinguish the syntax for inline assembly code*/ +#ifndef SBC_GHS_COMPILER +#define SBC_GHS_COMPILER FALSE +#endif + +/* ARM compiler option -> Used to distinguish the syntax for inline assembly code */ +#ifndef SBC_ARM_COMPILER +#define SBC_ARM_COMPILER TRUE +#endif + +/* Set SBC_IPAQ_OPT to TRUE in case the target is an ARM */ +/* 32 and 64 bit mult will be performed using SINT64 ( usualy __int64 ) cast that usualy give optimal performance if supported */ +#ifndef SBC_IPAQ_OPT +#define SBC_IPAQ_OPT TRUE +#endif + +/* Debug only: set SBC_IS_64_MULT_IN_WINDOW_ACCU to TRUE to use 64 bit multiplication in the windowing */ +/* -> not recomended, more MIPS for the same restitution. */ +#ifndef SBC_IS_64_MULT_IN_WINDOW_ACCU +#define SBC_IS_64_MULT_IN_WINDOW_ACCU FALSE +#endif /*SBC_IS_64_MULT_IN_WINDOW_ACCU */ + +/* Set SBC_IS_64_MULT_IN_IDCT to TRUE to use 64 bits multiplication in the DCT of Matrixing */ +/* -> more MIPS required for a better audio quality. comparasion with the SIG utilities shows a division by 10 of the RMS */ +/* CAUTION: It only apply in the if SBC_FAST_DCT is set to TRUE */ +#ifndef SBC_IS_64_MULT_IN_IDCT +#define SBC_IS_64_MULT_IN_IDCT FALSE +#endif /*SBC_IS_64_MULT_IN_IDCT */ + +/* set SBC_IS_64_MULT_IN_QUANTIZER to TRUE to use 64 bits multiplication in the quantizer */ +/* setting this flag to FALSE add whistling noise at 5.5 and 11 KHz usualy not perceptible by human's hears. */ +#ifndef SBC_IS_64_MULT_IN_QUANTIZER +#define SBC_IS_64_MULT_IN_QUANTIZER TRUE +#endif /*SBC_IS_64_MULT_IN_IDCT */ + +/* Debug only: set this flag to FALSE to disable fast DCT algorithm */ +#ifndef SBC_FAST_DCT +#define SBC_FAST_DCT TRUE +#endif /*SBC_FAST_DCT */ + +/* In case we do not use joint stereo mode the flag save some RAM and ROM in case it is set to FALSE */ +#ifndef SBC_JOINT_STE_INCLUDED +#define SBC_JOINT_STE_INCLUDED TRUE +#endif + +/* TRUE -> application should provide PCM buffer, FALSE PCM buffer reside in SBC_ENC_PARAMS */ +#ifndef SBC_NO_PCM_CPY_OPTION +#define SBC_NO_PCM_CPY_OPTION FALSE +#endif + +#define MINIMUM_ENC_VX_BUFFER_SIZE (8*10*2) +#ifndef ENC_VX_BUFFER_SIZE +#define ENC_VX_BUFFER_SIZE (MINIMUM_ENC_VX_BUFFER_SIZE + 64) +/*#define ENC_VX_BUFFER_SIZE MINIMUM_ENC_VX_BUFFER_SIZE + 1024*/ +#endif + +#ifndef SBC_FOR_EMBEDDED_LINUX +#define SBC_FOR_EMBEDDED_LINUX FALSE +#endif + +/*constants used for index calculation*/ +#define SBC_BLK (SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS) + +#include "sbc_types.h" + +typedef struct SBC_ENC_PARAMS_TAG +{ + SINT16 s16SamplingFreq; /* 16k, 32k, 44.1k or 48k*/ + SINT16 s16ChannelMode; /* mono, dual, streo or joint streo*/ + SINT16 s16NumOfSubBands; /* 4 or 8 */ + SINT16 s16NumOfChannels; + SINT16 s16NumOfBlocks; /* 4, 8, 12 or 16*/ + SINT16 s16AllocationMethod; /* loudness or SNR*/ + SINT16 s16BitPool; /* 16*numOfSb for mono & dual; + 32*numOfSb for stereo & joint stereo */ + UINT16 u16BitRate; + UINT8 u8NumPacketToEncode; /* number of sbc frame to encode. Default is 1 */ +#if (SBC_JOINT_STE_INCLUDED == TRUE) + SINT16 as16Join[SBC_MAX_NUM_OF_SUBBANDS]; /*1 if JS, 0 otherwise*/ +#endif + + SINT16 s16MaxBitNeed; + SINT16 as16ScaleFactor[SBC_MAX_NUM_OF_CHANNELS*SBC_MAX_NUM_OF_SUBBANDS]; + + SINT16 *ps16NextPcmBuffer; +#if (SBC_NO_PCM_CPY_OPTION == TRUE) + SINT16 *ps16PcmBuffer; +#else + SINT16 as16PcmBuffer[SBC_MAX_NUM_FRAME*SBC_MAX_NUM_OF_BLOCKS * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS]; +#endif + + SINT16 s16ScartchMemForBitAlloc[16]; + + SINT32 s32SbBuffer[SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * SBC_MAX_NUM_OF_BLOCKS]; + + SINT16 as16Bits[SBC_MAX_NUM_OF_CHANNELS*SBC_MAX_NUM_OF_SUBBANDS]; + + UINT8 *pu8Packet; + UINT8 *pu8NextPacket; + UINT16 FrameHeader; + UINT16 u16PacketLength; + +}SBC_ENC_PARAMS; + +#ifdef __cplusplus +extern "C" +{ +#endif +extern void SBC_Encoder(SBC_ENC_PARAMS *strEncParams); +extern void SBC_Encoder_Init(SBC_ENC_PARAMS *strEncParams); +#ifdef __cplusplus +} +#endif +#endif diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_if.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_if.h new file mode 100755 index 0000000000..de8dd48290 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_if.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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 _SBC_IF_H +#define _SBC_IF_H + +#define PCM_BUFFER_SIZE 512 + +/* + SBC_Init - called once for each track played + + pcm_sample_freq - 4000 to 48000 + channels - 1 mono 2 stereo + bits_per_sample - 8 or 16 + return - 0 sucess +*/ + +int SBC_init(int pcm_sample_freq, int channels, int bits_per_sample); + +/* + SBC_write - called repeatedly with pcm_in pointer + increasing by length until track is finished. + + pcm_in - pointer to PCM buffer + length - any + sbc_out - pointer to SBC output buffer + return - number of bytes written to sbc_out +*/ + +int SBC_write(unsigned char *pcm_in, int length, unsigned char *sbc_out); + +#endif diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_types.h b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_types.h new file mode 100755 index 0000000000..4bb8829c70 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/include/sbc_types.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Data type declarations. + * + ******************************************************************************/ + +#ifndef SBC_TYPES_H +#define SBC_TYPES_H + +#include + +#ifdef BUILDCFG +#include "bt_target.h" +#endif + +#include "bt_types.h" + +typedef short SINT16; +typedef long SINT32; + +#if (SBC_IPAQ_OPT == TRUE) + +#if (SBC_FOR_EMBEDDED_LINUX == TRUE) +typedef long long SINT64; +#else +typedef int64_t SINT64; +#endif + +#elif (SBC_IS_64_MULT_IN_WINDOW_ACCU == TRUE) || (SBC_IS_64_MULT_IN_IDCT == TRUE) + +#if (SBC_FOR_EMBEDDED_LINUX == TRUE) +typedef long long SINT64; +#else +typedef int64_t SINT64; +#endif + +#endif + +#define abs32(x) ( (x >= 0) ? x : (-x) ) + +#endif diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_analysis.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_analysis.c new file mode 100755 index 0000000000..95079fac65 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_analysis.c @@ -0,0 +1,1107 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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 the code that performs Analysis of the input audio + * stream. + * + ******************************************************************************/ +#include +#include "sbc_encoder.h" +#include "sbc_enc_func_declare.h" +/*#include */ + +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == TRUE) +#define WIND_4_SUBBANDS_0_1 (SINT32)0x01659F45 /* gas32CoeffFor4SBs[8] = -gas32CoeffFor4SBs[32] = 0x01659F45 */ +#define WIND_4_SUBBANDS_0_2 (SINT32)0x115B1ED2 /* gas32CoeffFor4SBs[16] = -gas32CoeffFor4SBs[24] = 0x115B1ED2 */ +#define WIND_4_SUBBANDS_1_0 (SINT32)0x001194E6 /* gas32CoeffFor4SBs[1 et 39] = 0x001194E6 */ +#define WIND_4_SUBBANDS_1_1 (SINT32)0x029DBAA3 /* gas32CoeffFor4SBs[9 et 31] = 0x029DBAA3 */ +#define WIND_4_SUBBANDS_1_2 (SINT32)0x18F55C90 /* gas32CoeffFor4SBs[17 et 23] = 0x18F55C90 */ +#define WIND_4_SUBBANDS_1_3 (SINT32)0xF60FAF37 /* gas32CoeffFor4SBs[15 et 25] = 0xF60FAF37 */ +#define WIND_4_SUBBANDS_1_4 (SINT32)0xFF9BB9D5 /* gas32CoeffFor4SBs[7 et 33] = 0xFF9BB9D5 */ +#define WIND_4_SUBBANDS_2_0 (SINT32)0x0030E2D3 /* gas32CoeffFor4SBs[2 et 38] = 0x0030E2D3 */ +#define WIND_4_SUBBANDS_2_1 (SINT32)0x03B23341 /* gas32CoeffFor4SBs[10 et 30] = 0x03B23341 */ +#define WIND_4_SUBBANDS_2_2 (SINT32)0x1F91CA46 /* gas32CoeffFor4SBs[18 et 22] = 0x1F91CA46 */ +#define WIND_4_SUBBANDS_2_3 (SINT32)0xFC4F91D4 /* gas32CoeffFor4SBs[14 et 26] = 0xFC4F91D4 */ +#define WIND_4_SUBBANDS_2_4 (SINT32)0x003D239B /* gas32CoeffFor4SBs[6 et 34] = 0x003D239B */ +#define WIND_4_SUBBANDS_3_0 (SINT32)0x00599403 /* gas32CoeffFor4SBs[3 et 37] = 0x00599403 */ +#define WIND_4_SUBBANDS_3_1 (SINT32)0x041EEE40 /* gas32CoeffFor4SBs[11 et 29] = 0x041EEE40 */ +#define WIND_4_SUBBANDS_3_2 (SINT32)0x2412F251 /* gas32CoeffFor4SBs[19 et 21] = 0x2412F251 */ +#define WIND_4_SUBBANDS_3_3 (SINT32)0x00C8F2BC /* gas32CoeffFor4SBs[13 et 27] = 0x00C8F2BC */ +#define WIND_4_SUBBANDS_3_4 (SINT32)0x007F88E4 /* gas32CoeffFor4SBs[5 et 35] = 0x007F88E4 */ +#define WIND_4_SUBBANDS_4_0 (SINT32)0x007DBCC8 /* gas32CoeffFor4SBs[4 et 36] = 0x007DBCC8 */ +#define WIND_4_SUBBANDS_4_1 (SINT32)0x034FEE2C /* gas32CoeffFor4SBs[12 et 28] = 0x034FEE2C */ +#define WIND_4_SUBBANDS_4_2 (SINT32)0x25AC1FF2 /* gas32CoeffFor4SBs[20] = 0x25AC1FF2 */ + +#define WIND_8_SUBBANDS_0_1 (SINT32)0x00B97348 /* 16 0x00B97348 */ +#define WIND_8_SUBBANDS_0_2 (SINT32)0x08B4307A /* 32 0x08B4307A */ +#define WIND_8_SUBBANDS_1_0 (SINT32)0x00052173 /* 1 et 79 = 0x00052173 */ +#define WIND_8_SUBBANDS_1_1 (SINT32)0x01071B96 /* 17 et 63 = 0x01071B96 */ +#define WIND_8_SUBBANDS_1_2 (SINT32)0x0A9F3E9A /* 33 et 47 = 0x0A9F3E9A*/ +#define WIND_8_SUBBANDS_1_3 (SINT32)0xF9312891 /* 31 et 49 = 0xF9312891 */ +#define WIND_8_SUBBANDS_1_4 (SINT32)0xFF8D6793 /* 15 et 65 = 0xFF8D6793 */ +#define WIND_8_SUBBANDS_2_0 (SINT32)0x000B3F71 /* 2 et 78 = 0x000B3F71 */ +#define WIND_8_SUBBANDS_2_1 (SINT32)0x0156B3CA /* 18 et 62 = 0x0156B3CA */ +#define WIND_8_SUBBANDS_2_2 (SINT32)0x0C7D59B6 /* 34 et 46 = 0x0C7D59B6 */ +#define WIND_8_SUBBANDS_2_3 (SINT32)0xFAFF95FC /* 30 et 50 = 0xFAFF95FC */ +#define WIND_8_SUBBANDS_2_4 (SINT32)0xFFC9F10E /* 14 et 66 = 0xFFC9F10E */ +#define WIND_8_SUBBANDS_3_0 (SINT32)0x00122C7D /* 3 et 77 = 0x00122C7D*/ +#define WIND_8_SUBBANDS_3_1 (SINT32)0x01A1B38B /* 19 et 61 = 0x01A1B38B */ +#define WIND_8_SUBBANDS_3_2 (SINT32)0x0E3BB16F /* 35 et 45 = 0x0E3BB16F */ +#define WIND_8_SUBBANDS_3_3 (SINT32)0xFCA86E7E /* 29 et 51 = 0xFCA86E7E */ +#define WIND_8_SUBBANDS_3_4 (SINT32)0xFFFA2413 /* 13 et 67 = 0xFFFA2413 */ +#define WIND_8_SUBBANDS_4_0 (SINT32)0x001AFF89 /* 4 et 66 = 0x001AFF89 */ +#define WIND_8_SUBBANDS_4_1 (SINT32)0x01E0224C /* 20 et 60 = 0x01E0224C */ +#define WIND_8_SUBBANDS_4_2 (SINT32)0x0FC721F9 /* 36 et 44 = 0x0FC721F9 */ +#define WIND_8_SUBBANDS_4_3 (SINT32)0xFE20435D /* 28 et 52 = 0xFE20435D */ +#define WIND_8_SUBBANDS_4_4 (SINT32)0x001D8FD2 /* 12 et 68 = 0x001D8FD2 */ +#define WIND_8_SUBBANDS_5_0 (SINT32)0x00255A62 /* 5 et 75 = 0x00255A62 */ +#define WIND_8_SUBBANDS_5_1 (SINT32)0x0209291F /* 21 et 59 = 0x0209291F */ +#define WIND_8_SUBBANDS_5_2 (SINT32)0x110ECEF0 /* 37 et 43 = 0x110ECEF0 */ +#define WIND_8_SUBBANDS_5_3 (SINT32)0xFF5EEB73 /* 27 et 53 = 0xFF5EEB73 */ +#define WIND_8_SUBBANDS_5_4 (SINT32)0x0034F8B6 /* 11 et 69 = 0x0034F8B6 */ +#define WIND_8_SUBBANDS_6_0 (SINT32)0x003060F4 /* 6 et 74 = 0x003060F4 */ +#define WIND_8_SUBBANDS_6_1 (SINT32)0x02138653 /* 22 et 58 = 0x02138653 */ +#define WIND_8_SUBBANDS_6_2 (SINT32)0x120435FA /* 38 et 42 = 0x120435FA */ +#define WIND_8_SUBBANDS_6_3 (SINT32)0x005FD0FF /* 26 et 54 = 0x005FD0FF */ +#define WIND_8_SUBBANDS_6_4 (SINT32)0x00415B75 /* 10 et 70 = 0x00415B75 */ +#define WIND_8_SUBBANDS_7_0 (SINT32)0x003A72E7 /* 7 et 73 = 0x003A72E7 */ +#define WIND_8_SUBBANDS_7_1 (SINT32)0x01F5F424 /* 23 et 57 = 0x01F5F424 */ +#define WIND_8_SUBBANDS_7_2 (SINT32)0x129C226F /* 39 et 41 = 0x129C226F */ +#define WIND_8_SUBBANDS_7_3 (SINT32)0x01223EBA /* 25 et 55 = 0x01223EBA */ +#define WIND_8_SUBBANDS_7_4 (SINT32)0x0044EF48 /* 9 et 71 = 0x0044EF48 */ +#define WIND_8_SUBBANDS_8_0 (SINT32)0x0041EC6A /* 8 et 72 = 0x0041EC6A */ +#define WIND_8_SUBBANDS_8_1 (SINT32)0x01A7ECEF /* 24 et 56 = 0x01A7ECEF */ +#define WIND_8_SUBBANDS_8_2 (SINT32)0x12CF6C75 /* 40 = 0x12CF6C75 */ +#else +#define WIND_4_SUBBANDS_0_1 (SINT16)0x0166 /* gas32CoeffFor4SBs[8] = -gas32CoeffFor4SBs[32] = 0x01659F45 */ +#define WIND_4_SUBBANDS_0_2 (SINT16)0x115B /* gas32CoeffFor4SBs[16] = -gas32CoeffFor4SBs[24] = 0x115B1ED2 */ +#define WIND_4_SUBBANDS_1_0 (SINT16)0x0012 /* gas32CoeffFor4SBs[1 et 39] = 0x001194E6 */ +#define WIND_4_SUBBANDS_1_1 (SINT16)0x029E /* gas32CoeffFor4SBs[9 et 31] = 0x029DBAA3 */ +#define WIND_4_SUBBANDS_1_2 (SINT16)0x18F5 /* gas32CoeffFor4SBs[17 et 23] = 0x18F55C90 */ +#define WIND_4_SUBBANDS_1_3 (SINT16)0xF610 /* gas32CoeffFor4SBs[15 et 25] = 0xF60FAF37 */ +#define WIND_4_SUBBANDS_1_4 (SINT16)0xFF9C /* gas32CoeffFor4SBs[7 et 33] = 0xFF9BB9D5 */ +#define WIND_4_SUBBANDS_2_0 (SINT16)0x0031 /* gas32CoeffFor4SBs[2 et 38] = 0x0030E2D3 */ +#define WIND_4_SUBBANDS_2_1 (SINT16)0x03B2 /* gas32CoeffFor4SBs[10 et 30] = 0x03B23341 */ +#define WIND_4_SUBBANDS_2_2 (SINT16)0x1F91 /* gas32CoeffFor4SBs[18 et 22] = 0x1F91CA46 */ +#define WIND_4_SUBBANDS_2_3 (SINT16)0xFC50 /* gas32CoeffFor4SBs[14 et 26] = 0xFC4F91D4 */ +#define WIND_4_SUBBANDS_2_4 (SINT16)0x003D /* gas32CoeffFor4SBs[6 et 34] = 0x003D239B */ +#define WIND_4_SUBBANDS_3_0 (SINT16)0x005A /* gas32CoeffFor4SBs[3 et 37] = 0x00599403 */ +#define WIND_4_SUBBANDS_3_1 (SINT16)0x041F /* gas32CoeffFor4SBs[11 et 29] = 0x041EEE40 */ +#define WIND_4_SUBBANDS_3_2 (SINT16)0x2413 /* gas32CoeffFor4SBs[19 et 21] = 0x2412F251 */ +#define WIND_4_SUBBANDS_3_3 (SINT16)0x00C9 /* gas32CoeffFor4SBs[13 et 27] = 0x00C8F2BC */ +#define WIND_4_SUBBANDS_3_4 (SINT16)0x0080 /* gas32CoeffFor4SBs[5 et 35] = 0x007F88E4 */ +#define WIND_4_SUBBANDS_4_0 (SINT16)0x007E /* gas32CoeffFor4SBs[4 et 36] = 0x007DBCC8 */ +#define WIND_4_SUBBANDS_4_1 (SINT16)0x0350 /* gas32CoeffFor4SBs[12 et 28] = 0x034FEE2C */ +#define WIND_4_SUBBANDS_4_2 (SINT16)0x25AC /* gas32CoeffFor4SBs[20] = 25AC1FF2 */ + +#define WIND_8_SUBBANDS_0_1 (SINT16)0x00B9 /* 16 0x12CF6C75 */ +#define WIND_8_SUBBANDS_0_2 (SINT16)0x08B4 /* 32 0x08B4307A */ +#define WIND_8_SUBBANDS_1_0 (SINT16)0x0005 /* 1 et 79 = 0x00052173 */ +#define WIND_8_SUBBANDS_1_1 (SINT16)0x0107 /* 17 et 63 = 0x01071B96 */ +#define WIND_8_SUBBANDS_1_2 (SINT16)0x0A9F /* 33 et 47 = 0x0A9F3E9A*/ +#define WIND_8_SUBBANDS_1_3 (SINT16)0xF931 /* 31 et 49 = 0xF9312891 */ +#define WIND_8_SUBBANDS_1_4 (SINT16)0xFF8D /* 15 et 65 = 0xFF8D6793 */ +#define WIND_8_SUBBANDS_2_0 (SINT16)0x000B /* 2 et 78 = 0x000B3F71 */ +#define WIND_8_SUBBANDS_2_1 (SINT16)0x0157 /* 18 et 62 = 0x0156B3CA */ +#define WIND_8_SUBBANDS_2_2 (SINT16)0x0C7D /* 34 et 46 = 0x0C7D59B6 */ +#define WIND_8_SUBBANDS_2_3 (SINT16)0xFB00 /* 30 et 50 = 0xFAFF95FC */ +#define WIND_8_SUBBANDS_2_4 (SINT16)0xFFCA /* 14 et 66 = 0xFFC9F10E */ +#define WIND_8_SUBBANDS_3_0 (SINT16)0x0012 /* 3 et 77 = 0x00122C7D*/ +#define WIND_8_SUBBANDS_3_1 (SINT16)0x01A2 /* 19 et 61 = 0x01A1B38B */ +#define WIND_8_SUBBANDS_3_2 (SINT16)0x0E3C /* 35 et 45 = 0x0E3BB16F */ +#define WIND_8_SUBBANDS_3_3 (SINT16)0xFCA8 /* 29 et 51 = 0xFCA86E7E */ +#define WIND_8_SUBBANDS_3_4 (SINT16)0xFFFA /* 13 et 67 = 0xFFFA2413 */ +#define WIND_8_SUBBANDS_4_0 (SINT16)0x001B /* 4 et 66 = 0x001AFF89 */ +#define WIND_8_SUBBANDS_4_1 (SINT16)0x01E0 /* 20 et 60 = 0x01E0224C */ +#define WIND_8_SUBBANDS_4_2 (SINT16)0x0FC7 /* 36 et 44 = 0x0FC721F9 */ +#define WIND_8_SUBBANDS_4_3 (SINT16)0xFE20 /* 28 et 52 = 0xFE20435D */ +#define WIND_8_SUBBANDS_4_4 (SINT16)0x001E /* 12 et 68 = 0x001D8FD2 */ +#define WIND_8_SUBBANDS_5_0 (SINT16)0x0025 /* 5 et 75 = 0x00255A62 */ +#define WIND_8_SUBBANDS_5_1 (SINT16)0x0209 /* 21 et 59 = 0x0209291F */ +#define WIND_8_SUBBANDS_5_2 (SINT16)0x110F /* 37 et 43 = 0x110ECEF0 */ +#define WIND_8_SUBBANDS_5_3 (SINT16)0xFF5F /* 27 et 53 = 0xFF5EEB73 */ +#define WIND_8_SUBBANDS_5_4 (SINT16)0x0035 /* 11 et 69 = 0x0034F8B6 */ +#define WIND_8_SUBBANDS_6_0 (SINT16)0x0030 /* 6 et 74 = 0x003060F4 */ +#define WIND_8_SUBBANDS_6_1 (SINT16)0x0214 /* 22 et 58 = 0x02138653 */ +#define WIND_8_SUBBANDS_6_2 (SINT16)0x1204 /* 38 et 42 = 0x120435FA */ +#define WIND_8_SUBBANDS_6_3 (SINT16)0x0060 /* 26 et 54 = 0x005FD0FF */ +#define WIND_8_SUBBANDS_6_4 (SINT16)0x0041 /* 10 et 70 = 0x00415B75 */ +#define WIND_8_SUBBANDS_7_0 (SINT16)0x003A /* 7 et 73 = 0x003A72E7 */ +#define WIND_8_SUBBANDS_7_1 (SINT16)0x01F6 /* 23 et 57 = 0x01F5F424 */ +#define WIND_8_SUBBANDS_7_2 (SINT16)0x129C /* 39 et 41 = 0x129C226F */ +#define WIND_8_SUBBANDS_7_3 (SINT16)0x0122 /* 25 et 55 = 0x01223EBA */ +#define WIND_8_SUBBANDS_7_4 (SINT16)0x0045 /* 9 et 71 = 0x0044EF48 */ +#define WIND_8_SUBBANDS_8_0 (SINT16)0x0042 /* 8 et 72 = 0x0041EC6A */ +#define WIND_8_SUBBANDS_8_1 (SINT16)0x01A8 /* 24 et 56 = 0x01A7ECEF */ +#define WIND_8_SUBBANDS_8_2 (SINT16)0x12CF /* 40 = 0x12CF6C75 */ +#endif + +#if (SBC_USE_ARM_PRAGMA==TRUE) +#pragma arm section zidata = "sbc_s32_analysis_section" +#endif +static SINT32 s32DCTY[16] = {0}; +static SINT32 s32X[ENC_VX_BUFFER_SIZE/2]; +static SINT16 *s16X=(SINT16*) s32X; /* s16X must be 32 bits aligned cf SHIFTUP_X8_2*/ +#if (SBC_USE_ARM_PRAGMA==TRUE) +#pragma arm section zidata +#endif + +/* This macro is for 4 subbands */ +#define SHIFTUP_X4 \ +{ \ + ps32X=(SINT32 *)(s16X+EncMaxShiftCounter+38); \ + for (i=0;i<9;i++) \ + { \ + *ps32X=*(ps32X-2-(ShiftCounter>>1)); ps32X--; \ + *ps32X=*(ps32X-2-(ShiftCounter>>1)); ps32X--; \ + } \ +} +#define SHIFTUP_X4_2 \ +{ \ + ps32X=(SINT32 *)(s16X+EncMaxShiftCounter+38); \ + ps32X2=(SINT32 *)(s16X+(EncMaxShiftCounter<<1)+78); \ + for (i=0;i<9;i++) \ + { \ + *ps32X=*(ps32X-2-(ShiftCounter>>1)); *(ps32X2)=*(ps32X2-2-(ShiftCounter>>1)); ps32X--; ps32X2--; \ + *ps32X=*(ps32X-2-(ShiftCounter>>1)); *(ps32X2)=*(ps32X2-2-(ShiftCounter>>1)); ps32X--; ps32X2--; \ + } \ +} + +/* This macro is for 8 subbands */ +#define SHIFTUP_X8 \ +{ \ + ps32X=(SINT32 *)(s16X+EncMaxShiftCounter+78); \ + for (i=0;i<9;i++) \ + { \ + *ps32X=*(ps32X-4-(ShiftCounter>>1)); ps32X--; \ + *ps32X=*(ps32X-4-(ShiftCounter>>1)); ps32X--; \ + *ps32X=*(ps32X-4-(ShiftCounter>>1)); ps32X--; \ + *ps32X=*(ps32X-4-(ShiftCounter>>1)); ps32X--; \ + } \ +} +#define SHIFTUP_X8_2 \ +{ \ + ps32X=(SINT32 *)(s16X+EncMaxShiftCounter+78); \ + ps32X2=(SINT32 *)(s16X+(EncMaxShiftCounter<<1)+158); \ + for (i=0;i<9;i++) \ + { \ + *ps32X=*(ps32X-4-(ShiftCounter>>1)); *(ps32X2)=*(ps32X2-4-(ShiftCounter>>1)); ps32X--; ps32X2--; \ + *ps32X=*(ps32X-4-(ShiftCounter>>1)); *(ps32X2)=*(ps32X2-4-(ShiftCounter>>1)); ps32X--; ps32X2--; \ + *ps32X=*(ps32X-4-(ShiftCounter>>1)); *(ps32X2)=*(ps32X2-4-(ShiftCounter>>1)); ps32X--; ps32X2--; \ + *ps32X=*(ps32X-4-(ShiftCounter>>1)); *(ps32X2)=*(ps32X2-4-(ShiftCounter>>1)); ps32X--; ps32X2--; \ + } \ +} + +#if (SBC_ARM_ASM_OPT==TRUE) +#define WINDOW_ACCU_8_0 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_8_SUBBANDS_0_1,(s16X[ChOffset+16]-s16X[ChOffset+64]);\ + MLA s32Hi,WIND_8_SUBBANDS_0_2,(s16X[ChOffset+32]-s16X[ChOffset+48]),s32Hi;\ + MOV s32DCTY[0],s32Hi;\ + }\ +} +#define WINDOW_ACCU_8_1_15 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_8_SUBBANDS_1_0,s16X[ChOffset+1];\ + MUL s32Hi2,WIND_8_SUBBANDS_1_0,s16X[ChOffset+64+15];\ + MLA s32Hi,WIND_8_SUBBANDS_1_1,s16X[ChOffset+16+1],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_1_1,s16X[ChOffset+48+15],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_1_2,s16X[ChOffset+32+1],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_1_2,s16X[ChOffset+32+15],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_1_3,s16X[ChOffset+48+1],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_1_3,s16X[ChOffset+16+15],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_1_4,s16X[ChOffset+64+1],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_1_4,s16X[ChOffset+15],s32Hi2;\ + MOV s32DCTY[1],s32Hi;\ + MOV s32DCTY[15],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_8_2_14 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_8_SUBBANDS_2_0,s16X[ChOffset+2];\ + MUL s32Hi2,WIND_8_SUBBANDS_2_0,s16X[ChOffset+64+14];\ + MLA s32Hi,WIND_8_SUBBANDS_2_1,s16X[ChOffset+16+2],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_2_1,s16X[ChOffset+48+14],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_2_2,s16X[ChOffset+32+2],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_2_2,s16X[ChOffset+32+14],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_2_3,s16X[ChOffset+48+2],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_2_3,s16X[ChOffset+16+14],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_2_4,s16X[ChOffset+64+2],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_2_4,s16X[ChOffset+14],s32Hi2;\ + MOV s32DCTY[2],s32Hi;\ + MOV s32DCTY[14],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_8_3_13 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_8_SUBBANDS_3_0,s16X[ChOffset+3];\ + MUL s32Hi2,WIND_8_SUBBANDS_3_0,s16X[ChOffset+64+13];\ + MLA s32Hi,WIND_8_SUBBANDS_3_1,s16X[ChOffset+16+3],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_3_1,s16X[ChOffset+48+13],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_3_2,s16X[ChOffset+32+3],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_3_2,s16X[ChOffset+32+13],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_3_3,s16X[ChOffset+48+3],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_3_3,s16X[ChOffset+16+13],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_3_4,s16X[ChOffset+64+3],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_3_4,s16X[ChOffset+13],s32Hi2;\ + MOV s32DCTY[3],s32Hi;\ + MOV s32DCTY[13],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_8_4_12 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_8_SUBBANDS_4_0,s16X[ChOffset+4];\ + MUL s32Hi2,WIND_8_SUBBANDS_4_0,s16X[ChOffset+64+12];\ + MLA s32Hi,WIND_8_SUBBANDS_4_1,s16X[ChOffset+16+4],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_4_1,s16X[ChOffset+48+12],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_4_2,s16X[ChOffset+32+4],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_4_2,s16X[ChOffset+32+12],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_4_3,s16X[ChOffset+48+4],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_4_3,s16X[ChOffset+16+12],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_4_4,s16X[ChOffset+64+4],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_4_4,s16X[ChOffset+12],s32Hi2;\ + MOV s32DCTY[4],s32Hi;\ + MOV s32DCTY[12],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_8_5_11 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_8_SUBBANDS_5_0,s16X[ChOffset+5];\ + MUL s32Hi2,WIND_8_SUBBANDS_5_0,s16X[ChOffset+64+11];\ + MLA s32Hi,WIND_8_SUBBANDS_5_1,s16X[ChOffset+16+5],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_5_1,s16X[ChOffset+48+11],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_5_2,s16X[ChOffset+32+5],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_5_2,s16X[ChOffset+32+11],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_5_3,s16X[ChOffset+48+5],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_5_3,s16X[ChOffset+16+11],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_5_4,s16X[ChOffset+64+5],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_5_4,s16X[ChOffset+11],s32Hi2;\ + MOV s32DCTY[5],s32Hi;\ + MOV s32DCTY[11],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_8_6_10 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_8_SUBBANDS_6_0,s16X[ChOffset+6];\ + MUL s32Hi2,WIND_8_SUBBANDS_6_0,s16X[ChOffset+64+10];\ + MLA s32Hi,WIND_8_SUBBANDS_6_1,s16X[ChOffset+16+6],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_6_1,s16X[ChOffset+48+10],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_6_2,s16X[ChOffset+32+6],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_6_2,s16X[ChOffset+32+10],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_6_3,s16X[ChOffset+48+6],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_6_3,s16X[ChOffset+16+10],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_6_4,s16X[ChOffset+64+6],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_6_4,s16X[ChOffset+10],s32Hi2;\ + MOV s32DCTY[6],s32Hi;\ + MOV s32DCTY[10],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_8_7_9 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_8_SUBBANDS_7_0,s16X[ChOffset+7];\ + MUL s32Hi2,WIND_8_SUBBANDS_7_0,s16X[ChOffset+64+9];\ + MLA s32Hi,WIND_8_SUBBANDS_7_1,s16X[ChOffset+16+7],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_7_1,s16X[ChOffset+48+9],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_7_2,s16X[ChOffset+32+7],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_7_2,s16X[ChOffset+32+9],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_7_3,s16X[ChOffset+48+7],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_7_3,s16X[ChOffset+16+9],s32Hi2;\ + MLA s32Hi,WIND_8_SUBBANDS_7_4,s16X[ChOffset+64+7],s32Hi;\ + MLA s32Hi2,WIND_8_SUBBANDS_7_4,s16X[ChOffset+9],s32Hi2;\ + MOV s32DCTY[7],s32Hi;\ + MOV s32DCTY[9],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_8_8 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_8_SUBBANDS_8_0,(s16X[ChOffset+8]+s16X[ChOffset+8+64]);\ + MLA s32Hi,WIND_8_SUBBANDS_8_1,(s16X[ChOffset+8+16]+s16X[ChOffset+8+64]),s32Hi;\ + MLA s32Hi,WIND_8_SUBBANDS_8_2,s16X[ChOffset+8+32],s32Hi;\ + MOV s32DCTY[8],s32Hi;\ + }\ +} +#define WINDOW_ACCU_4_0 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_4_SUBBANDS_0_1,(s16X[ChOffset+8]-s16X[ChOffset+32]);\ + MLA s32Hi,WIND_4_SUBBANDS_0_2,(s16X[ChOffset+16]-s16X[ChOffset+24]),s32Hi;\ + MOV s32DCTY[0],s32Hi;\ + }\ +} +#define WINDOW_ACCU_4_1_7 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_4_SUBBANDS_1_0,s16X[ChOffset+1];\ + MUL s32Hi2,WIND_4_SUBBANDS_1_0,s16X[ChOffset+32+7];\ + MLA s32Hi,WIND_4_SUBBANDS_1_1,s16X[ChOffset+8+1],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_1_1,s16X[ChOffset+24+7],s32Hi2;\ + MLA s32Hi,WIND_4_SUBBANDS_1_2,s16X[ChOffset+16+1],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_1_2,s16X[ChOffset+16+7],s32Hi2;\ + MLA s32Hi,WIND_4_SUBBANDS_1_3,s16X[ChOffset+24+1],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_1_3,s16X[ChOffset+8+7],s32Hi2;\ + MLA s32Hi,WIND_4_SUBBANDS_1_4,s16X[ChOffset+32+1],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_1_4,s16X[ChOffset+7],s32Hi2;\ + MOV s32DCTY[1],s32Hi;\ + MOV s32DCTY[7],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_4_2_6 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_4_SUBBANDS_2_0,s16X[ChOffset+2];\ + MUL s32Hi2,WIND_4_SUBBANDS_2_0,s16X[ChOffset+32+6];\ + MLA s32Hi,WIND_4_SUBBANDS_2_1,s16X[ChOffset+8+2],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_2_1,s16X[ChOffset+24+6],s32Hi2;\ + MLA s32Hi,WIND_4_SUBBANDS_2_2,s16X[ChOffset+16+2],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_2_2,s16X[ChOffset+16+6],s32Hi2;\ + MLA s32Hi,WIND_4_SUBBANDS_2_3,s16X[ChOffset+24+2],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_2_3,s16X[ChOffset+8+6],s32Hi2;\ + MLA s32Hi,WIND_4_SUBBANDS_2_4,s16X[ChOffset+32+2],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_2_4,s16X[ChOffset+6],s32Hi2;\ + MOV s32DCTY[2],s32Hi;\ + MOV s32DCTY[6],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_4_3_5 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_4_SUBBANDS_3_0,s16X[ChOffset+3];\ + MUL s32Hi2,WIND_4_SUBBANDS_3_0,s16X[ChOffset+32+5];\ + MLA s32Hi,WIND_4_SUBBANDS_3_1,s16X[ChOffset+8+3],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_3_1,s16X[ChOffset+24+5],s32Hi2;\ + MLA s32Hi,WIND_4_SUBBANDS_3_2,s16X[ChOffset+16+3],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_3_2,s16X[ChOffset+16+5],s32Hi2;\ + MLA s32Hi,WIND_4_SUBBANDS_3_3,s16X[ChOffset+24+3],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_3_3,s16X[ChOffset+8+5],s32Hi2;\ + MLA s32Hi,WIND_4_SUBBANDS_3_4,s16X[ChOffset+32+3],s32Hi;\ + MLA s32Hi2,WIND_4_SUBBANDS_3_4,s16X[ChOffset+5],s32Hi2;\ + MOV s32DCTY[3],s32Hi;\ + MOV s32DCTY[5],s32Hi2;\ + }\ +} +#define WINDOW_ACCU_4_4 \ +{\ + __asm\ + {\ + MUL s32Hi,WIND_4_SUBBANDS_4_0,(s16X[ChOffset+4]+s16X[ChOffset+4+32]);\ + MLA s32Hi,WIND_4_SUBBANDS_4_1,(s16X[ChOffset+4+8]+s16X[ChOffset+4+24]),s32Hi;\ + MLA s32Hi,WIND_4_SUBBANDS_4_2,s16X[ChOffset+4+16],s32Hi;\ + MOV s32DCTY[4],s32Hi;\ + }\ +} + +#define WINDOW_PARTIAL_4 \ +{\ + WINDOW_ACCU_4_0; WINDOW_ACCU_4_1_7;\ + WINDOW_ACCU_4_2_6; WINDOW_ACCU_4_3_5;\ + WINDOW_ACCU_4_4;\ +} + +#define WINDOW_PARTIAL_8 \ +{\ + WINDOW_ACCU_8_0; WINDOW_ACCU_8_1_15;\ + WINDOW_ACCU_8_2_14; WINDOW_ACCU_8_3_13;\ + WINDOW_ACCU_8_4_12; WINDOW_ACCU_8_5_11;\ + WINDOW_ACCU_8_6_10; WINDOW_ACCU_8_7_9;\ + WINDOW_ACCU_8_8;\ +} + +#else +#if (SBC_IPAQ_OPT==TRUE) + +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == TRUE) +#define WINDOW_ACCU_8_0 \ +{\ + s64Temp=(SINT64)WIND_8_SUBBANDS_0_1*(SINT64)(s16X[ChOffset+16]-s16X[ChOffset+64]);\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_0_2*(SINT64)(s16X[ChOffset+32]-s16X[ChOffset+48]);\ + s32DCTY[0]=(SINT32)(s64Temp>>16);\ +} +#define WINDOW_ACCU_8_1_15 \ +{\ + s64Temp=(SINT64)WIND_8_SUBBANDS_1_0*(SINT64)s16X[ChOffset+1];\ + s64Temp2=(SINT64)WIND_8_SUBBANDS_1_0*(SINT64)s16X[ChOffset+64+15];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_1_1*(SINT64)s16X[ChOffset+16+1];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_1_1*(SINT64)s16X[ChOffset+48+15];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_1_2*(SINT64)s16X[ChOffset+32+1];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_1_2*(SINT64)s16X[ChOffset+32+15];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_1_3*(SINT64)s16X[ChOffset+48+1];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_1_3*(SINT64)s16X[ChOffset+16+15];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_1_4*(SINT64)s16X[ChOffset+64+1];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_1_4*(SINT64)s16X[ChOffset+15];\ + s32DCTY[1]=(SINT32)(s64Temp>>16);\ + s32DCTY[15]=(SINT32)(s64Temp2>>16);\ +} +#define WINDOW_ACCU_8_2_14 \ +{\ + s64Temp=(SINT64)WIND_8_SUBBANDS_2_0*(SINT64)s16X[ChOffset+2];\ + s64Temp2=(SINT64)WIND_8_SUBBANDS_2_0*(SINT64)s16X[ChOffset+64+14];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_2_1*(SINT64)s16X[ChOffset+16+2];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_2_1*(SINT64)s16X[ChOffset+48+14];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_2_2*(SINT64)s16X[ChOffset+32+2];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_2_2*(SINT64)s16X[ChOffset+32+14];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_2_3*(SINT64)s16X[ChOffset+48+2];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_2_3*(SINT64)s16X[ChOffset+16+14];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_2_4*(SINT64)s16X[ChOffset+64+2];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_2_4*(SINT64)s16X[ChOffset+14];\ + s32DCTY[2]=(SINT32)(s64Temp>>16);\ + s32DCTY[14]=(SINT32)(s64Temp2>>16);\ +} +#define WINDOW_ACCU_8_3_13 \ +{\ + s64Temp=(SINT64)WIND_8_SUBBANDS_3_0*(SINT64)s16X[ChOffset+3];\ + s64Temp2=(SINT64)WIND_8_SUBBANDS_3_0*(SINT64)s16X[ChOffset+64+13];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_3_1*(SINT64)s16X[ChOffset+16+3];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_3_1*(SINT64)s16X[ChOffset+48+13];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_3_2*(SINT64)s16X[ChOffset+32+3];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_3_2*(SINT64)s16X[ChOffset+32+13];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_3_3*(SINT64)s16X[ChOffset+48+3];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_3_3*(SINT64)s16X[ChOffset+16+13];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_3_4*(SINT64)s16X[ChOffset+64+3];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_3_4*(SINT64)s16X[ChOffset+13];\ + s32DCTY[3]=(SINT32)(s64Temp>>16);\ + s32DCTY[13]=(SINT32)(s64Temp2>>16);\ +} +#define WINDOW_ACCU_8_4_12 \ +{\ + s64Temp=(SINT64)WIND_8_SUBBANDS_4_0*(SINT64)s16X[ChOffset+4];\ + s64Temp2=(SINT64)WIND_8_SUBBANDS_4_0*(SINT64)s16X[ChOffset+64+12];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_4_1*(SINT64)s16X[ChOffset+16+4];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_4_1*(SINT64)s16X[ChOffset+48+12];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_4_2*(SINT64)s16X[ChOffset+32+4];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_4_2*(SINT64)s16X[ChOffset+32+12];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_4_3*(SINT64)s16X[ChOffset+48+4];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_4_3*(SINT64)s16X[ChOffset+16+12];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_4_4*(SINT64)s16X[ChOffset+64+4];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_4_4*(SINT64)s16X[ChOffset+12];\ + s32DCTY[4]=(SINT32)(s64Temp>>16);\ + s32DCTY[12]=(SINT32)(s64Temp2>>16);\ +} +#define WINDOW_ACCU_8_5_11 \ +{\ + s64Temp=(SINT64)WIND_8_SUBBANDS_5_0*(SINT64)s16X[ChOffset+5];\ + s64Temp2=(SINT64)WIND_8_SUBBANDS_5_0*(SINT64)s16X[ChOffset+64+11];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_5_1*(SINT64)s16X[ChOffset+16+5];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_5_1*(SINT64)s16X[ChOffset+48+11];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_5_2*(SINT64)s16X[ChOffset+32+5];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_5_2*(SINT64)s16X[ChOffset+32+11];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_5_3*(SINT64)s16X[ChOffset+48+5];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_5_3*(SINT64)s16X[ChOffset+16+11];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_5_4*(SINT64)s16X[ChOffset+64+5];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_5_4*(SINT64)s16X[ChOffset+11];\ + s32DCTY[5]=(SINT32)(s64Temp>>16);\ + s32DCTY[11]=(SINT32)(s64Temp2>>16);\ +} +#define WINDOW_ACCU_8_6_10 \ +{\ + s64Temp=(SINT64)WIND_8_SUBBANDS_6_0*(SINT64)s16X[ChOffset+6];\ + s64Temp2=(SINT64)WIND_8_SUBBANDS_6_0*(SINT64)s16X[ChOffset+64+10];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_6_1*(SINT64)s16X[ChOffset+16+6];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_6_1*(SINT64)s16X[ChOffset+48+10];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_6_2*(SINT64)s16X[ChOffset+32+6];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_6_2*(SINT64)s16X[ChOffset+32+10];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_6_3*(SINT64)s16X[ChOffset+48+6];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_6_3*(SINT64)s16X[ChOffset+16+10];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_6_4*(SINT64)s16X[ChOffset+64+6];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_6_4*(SINT64)s16X[ChOffset+10];\ + s32DCTY[6]=(SINT32)(s64Temp>>16);\ + s32DCTY[10]=(SINT32)(s64Temp2>>16);\ +} +#define WINDOW_ACCU_8_7_9 \ +{\ + s64Temp=(SINT64)WIND_8_SUBBANDS_7_0*(SINT64)s16X[ChOffset+7];\ + s64Temp2=(SINT64)WIND_8_SUBBANDS_7_0*(SINT64)s16X[ChOffset+64+9];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_7_1*(SINT64)s16X[ChOffset+16+7];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_7_1*(SINT64)s16X[ChOffset+48+9];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_7_2*(SINT64)s16X[ChOffset+32+7];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_7_2*(SINT64)s16X[ChOffset+32+9];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_7_3*(SINT64)s16X[ChOffset+48+7];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_7_3*(SINT64)s16X[ChOffset+16+9];\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_7_4*(SINT64)s16X[ChOffset+64+7];\ + s64Temp2+=(SINT64)WIND_8_SUBBANDS_7_4*(SINT64)s16X[ChOffset+9];\ + s32DCTY[7]=(SINT32)(s64Temp>>16);\ + s32DCTY[9]=(SINT32)(s64Temp2>>16);\ +} +#define WINDOW_ACCU_8_8 \ +{\ + s64Temp=(SINT64)WIND_8_SUBBANDS_8_0*(SINT64)(s16X[ChOffset+8]+s16X[ChOffset+64+8]);\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_8_1*(SINT64)(s16X[ChOffset+16+8]+s16X[ChOffset+48+8]);\ + s64Temp+=(SINT64)WIND_8_SUBBANDS_8_2*(SINT64)s16X[ChOffset+32+8];\ + s32DCTY[8]=(SINT32)(s64Temp>>16);\ +} +#define WINDOW_ACCU_4_0 \ +{\ + s64Temp=(SINT64)WIND_4_SUBBANDS_0_1*(SINT64)(s16X[ChOffset+8]-s16X[ChOffset+32]);\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_0_2*(SINT64)(s16X[ChOffset+16]-s16X[ChOffset+24]);\ + s32DCTY[0]=(SINT32)(s64Temp>>16);\ +} +#define WINDOW_ACCU_4_1_7 \ +{\ + s64Temp=(SINT64)WIND_4_SUBBANDS_1_0*(SINT64)s16X[ChOffset+1];\ + s64Temp2=(SINT64)WIND_4_SUBBANDS_1_0*(SINT64)s16X[ChOffset+32+7];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_1_1*(SINT64)s16X[ChOffset+8+1];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_1_1*(SINT64)s16X[ChOffset+24+7];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_1_2*(SINT64)s16X[ChOffset+16+1];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_1_2*(SINT64)s16X[ChOffset+16+7];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_1_3*(SINT64)s16X[ChOffset+24+1];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_1_3*(SINT64)s16X[ChOffset+8+7];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_1_4*(SINT64)s16X[ChOffset+32+1];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_1_4*(SINT64)s16X[ChOffset+7];\ + s32DCTY[1]=(SINT32)(s64Temp>>16);\ + s32DCTY[7]=(SINT32)(s64Temp2>>16);\ +} +#define WINDOW_ACCU_4_2_6 \ +{\ + s64Temp=(SINT64)WIND_4_SUBBANDS_2_0*(SINT64)s16X[ChOffset+2];\ + s64Temp2=(SINT64)WIND_4_SUBBANDS_2_0*(SINT64)s16X[ChOffset+32+6];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_2_1*(SINT64)s16X[ChOffset+8+2];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_2_1*(SINT64)s16X[ChOffset+24+6];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_2_2*(SINT64)s16X[ChOffset+16+2];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_2_2*(SINT64)s16X[ChOffset+16+6];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_2_3*(SINT64)s16X[ChOffset+24+2];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_2_3*(SINT64)s16X[ChOffset+8+6];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_2_4*(SINT64)s16X[ChOffset+32+2];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_2_4*(SINT64)s16X[ChOffset+6];\ + s32DCTY[2]=(SINT32)(s64Temp>>16);\ + s32DCTY[6]=(SINT32)(s64Temp2>>16);\ +} +#define WINDOW_ACCU_4_3_5 \ +{\ + s64Temp=(SINT64)WIND_4_SUBBANDS_3_0*(SINT64)s16X[ChOffset+3];\ + s64Temp2=(SINT64)WIND_4_SUBBANDS_3_0*(SINT64)s16X[ChOffset+32+5];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_3_1*(SINT64)s16X[ChOffset+8+3];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_3_1*(SINT64)s16X[ChOffset+24+5];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_3_2*(SINT64)s16X[ChOffset+16+3];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_3_2*(SINT64)s16X[ChOffset+16+5];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_3_3*(SINT64)s16X[ChOffset+24+3];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_3_3*(SINT64)s16X[ChOffset+8+5];\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_3_4*(SINT64)s16X[ChOffset+32+3];\ + s64Temp2+=(SINT64)WIND_4_SUBBANDS_3_4*(SINT64)s16X[ChOffset+5];\ + s32DCTY[3]=(SINT32)(s64Temp>>16);\ + s32DCTY[5]=(SINT32)(s64Temp2>>16);\ +} + +#define WINDOW_ACCU_4_4 \ +{\ + s64Temp=(SINT64)WIND_4_SUBBANDS_4_0*(SINT64)(s16X[ChOffset+4]+s16X[ChOffset+4+32]);\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_4_1*(SINT64)(s16X[ChOffset+4+8]+s16X[ChOffset+4+24]);\ + s64Temp+=(SINT64)WIND_4_SUBBANDS_4_2*(SINT64)s16X[ChOffset+4+16];\ + s32DCTY[4]=(SINT32)(s64Temp>>16);\ +} +#else /* SBC_IS_64_MULT_IN_WINDOW_ACCU == FALSE */ +#define WINDOW_ACCU_8_0 \ +{\ + s32Temp=(SINT32)WIND_8_SUBBANDS_0_1*(SINT32)(s16X[ChOffset+16]-s16X[ChOffset+64]);\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_0_2*(SINT32)(s16X[ChOffset+32]-s16X[ChOffset+48]);\ + s32DCTY[0]=(SINT32)s32Temp;\ +} +#define WINDOW_ACCU_8_1_15 \ +{\ + s32Temp=(SINT32)WIND_8_SUBBANDS_1_0*(SINT32)s16X[ChOffset+1];\ + s32Temp2=(SINT32)WIND_8_SUBBANDS_1_0*(SINT32)s16X[ChOffset+64+15];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_1_1*(SINT32)s16X[ChOffset+16+1];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_1_1*(SINT32)s16X[ChOffset+48+15];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_1_2*(SINT32)s16X[ChOffset+32+1];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_1_2*(SINT32)s16X[ChOffset+32+15];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_1_3*(SINT32)s16X[ChOffset+48+1];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_1_3*(SINT32)s16X[ChOffset+16+15];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_1_4*(SINT32)s16X[ChOffset+64+1];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_1_4*(SINT32)s16X[ChOffset+15];\ + s32DCTY[1]=(SINT32)s32Temp;\ + s32DCTY[15]=(SINT32)s32Temp2;\ +} +#define WINDOW_ACCU_8_2_14 \ +{\ + s32Temp=(SINT32)WIND_8_SUBBANDS_2_0*(SINT32)s16X[ChOffset+2];\ + s32Temp2=(SINT32)WIND_8_SUBBANDS_2_0*(SINT32)s16X[ChOffset+64+14];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_2_1*(SINT32)s16X[ChOffset+16+2];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_2_1*(SINT32)s16X[ChOffset+48+14];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_2_2*(SINT32)s16X[ChOffset+32+2];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_2_2*(SINT32)s16X[ChOffset+32+14];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_2_3*(SINT32)s16X[ChOffset+48+2];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_2_3*(SINT32)s16X[ChOffset+16+14];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_2_4*(SINT32)s16X[ChOffset+64+2];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_2_4*(SINT32)s16X[ChOffset+14];\ + s32DCTY[2]=(SINT32)s32Temp;\ + s32DCTY[14]=(SINT32)s32Temp2;\ +} +#define WINDOW_ACCU_8_3_13 \ +{\ + s32Temp=(SINT32)WIND_8_SUBBANDS_3_0*(SINT32)s16X[ChOffset+3];\ + s32Temp2=(SINT32)WIND_8_SUBBANDS_3_0*(SINT32)s16X[ChOffset+64+13];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_3_1*(SINT32)s16X[ChOffset+16+3];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_3_1*(SINT32)s16X[ChOffset+48+13];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_3_2*(SINT32)s16X[ChOffset+32+3];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_3_2*(SINT32)s16X[ChOffset+32+13];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_3_3*(SINT32)s16X[ChOffset+48+3];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_3_3*(SINT32)s16X[ChOffset+16+13];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_3_4*(SINT32)s16X[ChOffset+64+3];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_3_4*(SINT32)s16X[ChOffset+13];\ + s32DCTY[3]=(SINT32)s32Temp;\ + s32DCTY[13]=(SINT32)s32Temp2;\ +} +#define WINDOW_ACCU_8_4_12 \ +{\ + s32Temp=(SINT32)WIND_8_SUBBANDS_4_0*(SINT32)s16X[ChOffset+4];\ + s32Temp2=(SINT32)WIND_8_SUBBANDS_4_0*(SINT32)s16X[ChOffset+64+12];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_4_1*(SINT32)s16X[ChOffset+16+4];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_4_1*(SINT32)s16X[ChOffset+48+12];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_4_2*(SINT32)s16X[ChOffset+32+4];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_4_2*(SINT32)s16X[ChOffset+32+12];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_4_3*(SINT32)s16X[ChOffset+48+4];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_4_3*(SINT32)s16X[ChOffset+16+12];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_4_4*(SINT32)s16X[ChOffset+64+4];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_4_4*(SINT32)s16X[ChOffset+12];\ + s32DCTY[4]=(SINT32)s32Temp;\ + s32DCTY[12]=(SINT32)s32Temp2;\ +} +#define WINDOW_ACCU_8_5_11 \ +{\ + s32Temp=(SINT32)WIND_8_SUBBANDS_5_0*(SINT32)s16X[ChOffset+5];\ + s32Temp2=(SINT32)WIND_8_SUBBANDS_5_0*(SINT32)s16X[ChOffset+64+11];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_5_1*(SINT32)s16X[ChOffset+16+5];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_5_1*(SINT32)s16X[ChOffset+48+11];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_5_2*(SINT32)s16X[ChOffset+32+5];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_5_2*(SINT32)s16X[ChOffset+32+11];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_5_3*(SINT32)s16X[ChOffset+48+5];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_5_3*(SINT32)s16X[ChOffset+16+11];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_5_4*(SINT32)s16X[ChOffset+64+5];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_5_4*(SINT32)s16X[ChOffset+11];\ + s32DCTY[5]=(SINT32)s32Temp;\ + s32DCTY[11]=(SINT32)s32Temp2;\ +} +#define WINDOW_ACCU_8_6_10 \ +{\ + s32Temp=(SINT32)WIND_8_SUBBANDS_6_0*(SINT32)s16X[ChOffset+6];\ + s32Temp2=(SINT32)WIND_8_SUBBANDS_6_0*(SINT32)s16X[ChOffset+64+10];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_6_1*(SINT32)s16X[ChOffset+16+6];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_6_1*(SINT32)s16X[ChOffset+48+10];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_6_2*(SINT32)s16X[ChOffset+32+6];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_6_2*(SINT32)s16X[ChOffset+32+10];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_6_3*(SINT32)s16X[ChOffset+48+6];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_6_3*(SINT32)s16X[ChOffset+16+10];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_6_4*(SINT32)s16X[ChOffset+64+6];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_6_4*(SINT32)s16X[ChOffset+10];\ + s32DCTY[6]=(SINT32)s32Temp;\ + s32DCTY[10]=(SINT32)s32Temp2;\ +} +#define WINDOW_ACCU_8_7_9 \ +{\ + s32Temp=(SINT32)WIND_8_SUBBANDS_7_0*(SINT32)s16X[ChOffset+7];\ + s32Temp2=(SINT32)WIND_8_SUBBANDS_7_0*(SINT32)s16X[ChOffset+64+9];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_7_1*(SINT32)s16X[ChOffset+16+7];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_7_1*(SINT32)s16X[ChOffset+48+9];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_7_2*(SINT32)s16X[ChOffset+32+7];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_7_2*(SINT32)s16X[ChOffset+32+9];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_7_3*(SINT32)s16X[ChOffset+48+7];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_7_3*(SINT32)s16X[ChOffset+16+9];\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_7_4*(SINT32)s16X[ChOffset+64+7];\ + s32Temp2+=(SINT32)WIND_8_SUBBANDS_7_4*(SINT32)s16X[ChOffset+9];\ + s32DCTY[7]=(SINT32)s32Temp;\ + s32DCTY[9]=(SINT32)s32Temp2;\ +} +#define WINDOW_ACCU_8_8 \ +{\ + s32Temp=(SINT32)WIND_8_SUBBANDS_8_0*(SINT32)(s16X[ChOffset+8]+s16X[ChOffset+64+8]);\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_8_1*(SINT32)(s16X[ChOffset+16+8]+s16X[ChOffset+48+8]);\ + s32Temp+=(SINT32)WIND_8_SUBBANDS_8_2*(SINT32)s16X[ChOffset+32+8];\ + s32DCTY[8]=(SINT32)s32Temp;\ +} +#define WINDOW_ACCU_4_0 \ +{\ + s32Temp=(SINT32)WIND_4_SUBBANDS_0_1*(SINT32)(s16X[ChOffset+8]-s16X[ChOffset+32]);\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_0_2*(SINT32)(s16X[ChOffset+16]-s16X[ChOffset+24]);\ + s32DCTY[0]=(SINT32)(s32Temp);\ +} +#define WINDOW_ACCU_4_1_7 \ +{\ + s32Temp=(SINT32)WIND_4_SUBBANDS_1_0*(SINT32)s16X[ChOffset+1];\ + s32Temp2=(SINT32)WIND_4_SUBBANDS_1_0*(SINT32)s16X[ChOffset+32+7];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_1_1*(SINT32)s16X[ChOffset+8+1];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_1_1*(SINT32)s16X[ChOffset+24+7];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_1_2*(SINT32)s16X[ChOffset+16+1];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_1_2*(SINT32)s16X[ChOffset+16+7];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_1_3*(SINT32)s16X[ChOffset+24+1];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_1_3*(SINT32)s16X[ChOffset+8+7];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_1_4*(SINT32)s16X[ChOffset+32+1];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_1_4*(SINT32)s16X[ChOffset+7];\ + s32DCTY[1]=(SINT32)(s32Temp);\ + s32DCTY[7]=(SINT32)(s32Temp2);\ +} +#define WINDOW_ACCU_4_2_6 \ +{\ + s32Temp=(SINT32)WIND_4_SUBBANDS_2_0*(SINT32)s16X[ChOffset+2];\ + s32Temp2=(SINT32)WIND_4_SUBBANDS_2_0*(SINT32)s16X[ChOffset+32+6];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_2_1*(SINT32)s16X[ChOffset+8+2];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_2_1*(SINT32)s16X[ChOffset+24+6];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_2_2*(SINT32)s16X[ChOffset+16+2];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_2_2*(SINT32)s16X[ChOffset+16+6];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_2_3*(SINT32)s16X[ChOffset+24+2];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_2_3*(SINT32)s16X[ChOffset+8+6];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_2_4*(SINT32)s16X[ChOffset+32+2];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_2_4*(SINT32)s16X[ChOffset+6];\ + s32DCTY[2]=(SINT32)(s32Temp);\ + s32DCTY[6]=(SINT32)(s32Temp2);\ +} +#define WINDOW_ACCU_4_3_5 \ +{\ + s32Temp=(SINT32)WIND_4_SUBBANDS_3_0*(SINT32)s16X[ChOffset+3];\ + s32Temp2=(SINT32)WIND_4_SUBBANDS_3_0*(SINT32)s16X[ChOffset+32+5];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_3_1*(SINT32)s16X[ChOffset+8+3];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_3_1*(SINT32)s16X[ChOffset+24+5];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_3_2*(SINT32)s16X[ChOffset+16+3];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_3_2*(SINT32)s16X[ChOffset+16+5];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_3_3*(SINT32)s16X[ChOffset+24+3];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_3_3*(SINT32)s16X[ChOffset+8+5];\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_3_4*(SINT32)s16X[ChOffset+32+3];\ + s32Temp2+=(SINT32)WIND_4_SUBBANDS_3_4*(SINT32)s16X[ChOffset+5];\ + s32DCTY[3]=(SINT32)(s32Temp);\ + s32DCTY[5]=(SINT32)(s32Temp2);\ +} + +#define WINDOW_ACCU_4_4 \ +{\ + s32Temp=(SINT32)WIND_4_SUBBANDS_4_0*(SINT32)(s16X[ChOffset+4]+s16X[ChOffset+4+32]);\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_4_1*(SINT32)(s16X[ChOffset+4+8]+s16X[ChOffset+4+24]);\ + s32Temp+=(SINT32)WIND_4_SUBBANDS_4_2*(SINT32)s16X[ChOffset+4+16];\ + s32DCTY[4]=(SINT32)(s32Temp);\ +} +#endif +#define WINDOW_PARTIAL_4 \ +{\ + WINDOW_ACCU_4_0; WINDOW_ACCU_4_1_7;\ + WINDOW_ACCU_4_2_6; WINDOW_ACCU_4_3_5;\ + WINDOW_ACCU_4_4;\ +} + +#define WINDOW_PARTIAL_8 \ +{\ + WINDOW_ACCU_8_0; WINDOW_ACCU_8_1_15;\ + WINDOW_ACCU_8_2_14; WINDOW_ACCU_8_3_13;\ + WINDOW_ACCU_8_4_12; WINDOW_ACCU_8_5_11;\ + WINDOW_ACCU_8_6_10; WINDOW_ACCU_8_7_9;\ + WINDOW_ACCU_8_8;\ +} +#else +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == TRUE) +#define WINDOW_ACCU_4(i) \ +{\ + s64Temp=((SINT64)gas32CoeffFor4SBs[i] * (SINT64)s16X[ChOffset+i]); \ + s64Temp+=((SINT64)gas32CoeffFor4SBs[(i+8)] * (SINT64)s16X[ChOffset+i+8]); \ + s64Temp+=((SINT64)gas32CoeffFor4SBs[(i+16)] * (SINT64)s16X[ChOffset+i+16]); \ + s64Temp+=((SINT64)gas32CoeffFor4SBs[(i+24)] * (SINT64)s16X[ChOffset+i+24]); \ + s64Temp+=((SINT64)gas32CoeffFor4SBs[(i+32)] * (SINT64)s16X[ChOffset+i+32]); \ + s32DCTY[i]=(SINT32)(s64Temp>>16);\ + /*printf("s32DCTY4: 0x%x \n", s32DCTY[i]);*/\ +} +#else +#define WINDOW_ACCU_4(i) \ +{\ + s32DCTY[i]=(gas32CoeffFor4SBs[i * 2] * s16X[ChOffset+i]) \ + + (((SINT32)(UINT16)(gas32CoeffFor4SBs[(i * 2) + 1]) * s16X[ChOffset+i]) >> 16); \ + s32DCTY[i]+=(gas32CoeffFor4SBs[(i+8) * 2] * s16X[ChOffset+i+8]) \ + + (((SINT32)(UINT16)(gas32CoeffFor4SBs[((i+8) * 2) + 1]) * s16X[ChOffset+i+8]) >> 16); \ + s32DCTY[i]+=(gas32CoeffFor4SBs[(i+16) * 2] * s16X[ChOffset+i+16]) \ + + (((SINT32)(UINT16)(gas32CoeffFor4SBs[((i+16) * 2) + 1]) * s16X[ChOffset+i+16]) >> 16); \ + s32DCTY[i]+=(gas32CoeffFor4SBs[(i+24) * 2] * s16X[ChOffset+i+24]) \ + + (((SINT32)(UINT16)(gas32CoeffFor4SBs[((i+24) * 2) + 1]) * s16X[ChOffset+i+24]) >> 16); \ + s32DCTY[i]+=(gas32CoeffFor4SBs[(i+32) * 2] * s16X[ChOffset+i+32]) \ + + (((SINT32)(UINT16)(gas32CoeffFor4SBs[((i+32) * 2) + 1]) * s16X[ChOffset+i+32]) >> 16); \ +} +#endif +#define WINDOW_PARTIAL_4 \ +{\ + WINDOW_ACCU_4(0); WINDOW_ACCU_4(1);\ + WINDOW_ACCU_4(2); WINDOW_ACCU_4(3);\ + WINDOW_ACCU_4(4); WINDOW_ACCU_4(5);\ + WINDOW_ACCU_4(6); WINDOW_ACCU_4(7);\ +} + +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == TRUE) +#define WINDOW_ACCU_8(i) \ +{\ + s64Temp = ((((SINT64)gas32CoeffFor8SBs[i] * (SINT64)s16X[ChOffset+i] ))); \ + s64Temp+= ((((SINT64)gas32CoeffFor8SBs[(i+16)] * (SINT64)s16X[ChOffset+i+16]))); \ + s64Temp+= ((((SINT64)gas32CoeffFor8SBs[(i+32)] * (SINT64)s16X[ChOffset+i+32]))); \ + s64Temp+= ((((SINT64)gas32CoeffFor8SBs[(i+48)] * (SINT64)s16X[ChOffset+i+48]))); \ + s64Temp+= ((((SINT64)gas32CoeffFor8SBs[(i+64)] * (SINT64)s16X[ChOffset+i+64]))); \ + /*printf("s32DCTY8: %d= 0x%x * %d\n", s32DCTY[i], gas32CoeffFor8SBs[i], s16X[ChOffset+i]);*/ \ + s32DCTY[i]=(SINT32)(s64Temp>>16);\ +} +#else +#define WINDOW_ACCU_8(i) \ +{\ + s32DCTY[i]=(gas32CoeffFor8SBs[i * 2] * s16X[ChOffset+i]) \ + + (((SINT32)(UINT16)(gas32CoeffFor8SBs[(i * 2) + 1]) * s16X[ChOffset+i]) >> 16); \ + s32DCTY[i]+=(gas32CoeffFor8SBs[(i+16) * 2] * s16X[ChOffset+i+16]) \ + + (((SINT32)(UINT16)(gas32CoeffFor8SBs[((i+16) * 2) + 1]) * s16X[ChOffset+i+16]) >> 16); \ + s32DCTY[i]+=(gas32CoeffFor8SBs[(i+32) * 2] * s16X[ChOffset+i+32]) \ + + (((SINT32)(UINT16)(gas32CoeffFor8SBs[((i+32) * 2) + 1]) * s16X[ChOffset+i+32]) >> 16); \ + s32DCTY[i]+=(gas32CoeffFor8SBs[(i+48) * 2] * s16X[ChOffset+i+48]) \ + + (((SINT32)(UINT16)(gas32CoeffFor8SBs[((i+48) * 2) + 1]) * s16X[ChOffset+i+48]) >> 16); \ + s32DCTY[i]+=(gas32CoeffFor8SBs[(i+64) * 2] * s16X[ChOffset+i+64]) \ + + (((SINT32)(UINT16)(gas32CoeffFor8SBs[((i+64) * 2) + 1]) * s16X[ChOffset+i+64]) >> 16); \ + /*printf("s32DCTY8: %d = 0x%4x%4x * %d\n", s32DCTY[i], gas32CoeffFor8SBs[i * 2], (gas32CoeffFor8SBs[(i * 2) + 1]), s16X[ChOffset+i]);*/\ + /*s32DCTY[i]=(SINT32)(s64Temp>>16);*/\ +} +#endif +#define WINDOW_PARTIAL_8 \ +{\ + WINDOW_ACCU_8(0); WINDOW_ACCU_8(1);\ + WINDOW_ACCU_8(2); WINDOW_ACCU_8(3);\ + WINDOW_ACCU_8(4); WINDOW_ACCU_8(5);\ + WINDOW_ACCU_8(6); WINDOW_ACCU_8(7);\ + WINDOW_ACCU_8(8); WINDOW_ACCU_8(9);\ + WINDOW_ACCU_8(10); WINDOW_ACCU_8(11);\ + WINDOW_ACCU_8(12); WINDOW_ACCU_8(13);\ + WINDOW_ACCU_8(14); WINDOW_ACCU_8(15);\ +} +#endif +#endif + +static SINT16 ShiftCounter=0; +extern SINT16 EncMaxShiftCounter; +/**************************************************************************** +* SbcAnalysisFilter - performs Analysis of the input audio stream +* +* RETURNS : N/A +*/ +void SbcAnalysisFilter4(SBC_ENC_PARAMS *pstrEncParams) +{ + SINT16 *ps16PcmBuf; + SINT32 *ps32SbBuf; + SINT32 s32Blk,s32Ch; + SINT32 s32NumOfChannels, s32NumOfBlocks; + SINT32 i,*ps32X,*ps32X2; + SINT32 Offset,Offset2,ChOffset; +#if (SBC_ARM_ASM_OPT==TRUE) + register SINT32 s32Hi,s32Hi2; +#else +#if (SBC_IPAQ_OPT==TRUE) +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == TRUE) + register SINT64 s64Temp,s64Temp2; +#else + register SINT32 s32Temp,s32Temp2; +#endif +#else + +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == TRUE) + SINT64 s64Temp; +#endif + +#endif +#endif + + s32NumOfChannels = pstrEncParams->s16NumOfChannels; + s32NumOfBlocks = pstrEncParams->s16NumOfBlocks; + + ps16PcmBuf = pstrEncParams->ps16NextPcmBuffer; + + ps32SbBuf = pstrEncParams->s32SbBuffer; + Offset2=(SINT32)(EncMaxShiftCounter+40); + for (s32Blk=0; s32Blk =EncMaxShiftCounter) + { + SHIFTUP_X4; + ShiftCounter=0; + } + else + { + ShiftCounter+=SUB_BANDS_4; + } + } + else + { + if (ShiftCounter>=EncMaxShiftCounter) + { + SHIFTUP_X4_2; + ShiftCounter=0; + } + else + { + ShiftCounter+=SUB_BANDS_4; + } + } + } +} + +/* //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ +void SbcAnalysisFilter8 (SBC_ENC_PARAMS *pstrEncParams) +{ + SINT16 *ps16PcmBuf; + SINT32 *ps32SbBuf; + SINT32 s32Blk,s32Ch; /* counter for block*/ + SINT32 Offset,Offset2; + SINT32 s32NumOfChannels, s32NumOfBlocks; + SINT32 i,*ps32X,*ps32X2; + SINT32 ChOffset; +#if (SBC_ARM_ASM_OPT==TRUE) + register SINT32 s32Hi,s32Hi2; +#else +#if (SBC_IPAQ_OPT==TRUE) +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == TRUE) + register SINT64 s64Temp,s64Temp2; +#else + register SINT32 s32Temp,s32Temp2; +#endif +#else +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == TRUE) + SINT64 s64Temp; +#endif +#endif +#endif + + s32NumOfChannels = pstrEncParams->s16NumOfChannels; + s32NumOfBlocks = pstrEncParams->s16NumOfBlocks; + + ps16PcmBuf = pstrEncParams->ps16NextPcmBuffer; + + ps32SbBuf = pstrEncParams->s32SbBuffer; + Offset2=(SINT32)(EncMaxShiftCounter+80); + for (s32Blk=0; s32Blk =EncMaxShiftCounter) + { + SHIFTUP_X8; + ShiftCounter=0; + } + else + { + ShiftCounter+=SUB_BANDS_8; + } + } + else + { + if (ShiftCounter>=EncMaxShiftCounter) + { + SHIFTUP_X8_2; + ShiftCounter=0; + } + else + { + ShiftCounter+=SUB_BANDS_8; + } + } + } +} + +void SbcAnalysisInit (void) +{ + memset(s16X,0,ENC_VX_BUFFER_SIZE*sizeof(SINT16)); + ShiftCounter=0; +} diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_dct.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_dct.c new file mode 100755 index 0000000000..0f6c9d3f4f --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_dct.c @@ -0,0 +1,245 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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. + * + ******************************************************************************/ + +/****************************************************************************** + * + * source file for fast dct operations + * + ******************************************************************************/ + +#include "sbc_encoder.h" +#include "sbc_enc_func_declare.h" +#include "sbc_dct.h" + + + +/******************************************************************************* +** +** Function SBC_FastIDCT8 +** +** Description implementation of fast DCT algorithm by Feig and Winograd +** +** +** Returns y = dct(pInVect) +** +** +*******************************************************************************/ + +#if (SBC_IS_64_MULT_IN_IDCT == FALSE) +#define SBC_COS_PI_SUR_4 (0x00005a82) /* ((0x8000) * 0.7071) = cos(pi/4) */ +#define SBC_COS_PI_SUR_8 (0x00007641) /* ((0x8000) * 0.9239) = (cos(pi/8)) */ +#define SBC_COS_3PI_SUR_8 (0x000030fb) /* ((0x8000) * 0.3827) = (cos(3*pi/8)) */ +#define SBC_COS_PI_SUR_16 (0x00007d8a) /* ((0x8000) * 0.9808)) = (cos(pi/16)) */ +#define SBC_COS_3PI_SUR_16 (0x00006a6d) /* ((0x8000) * 0.8315)) = (cos(3*pi/16)) */ +#define SBC_COS_5PI_SUR_16 (0x0000471c) /* ((0x8000) * 0.5556)) = (cos(5*pi/16)) */ +#define SBC_COS_7PI_SUR_16 (0x000018f8) /* ((0x8000) * 0.1951)) = (cos(7*pi/16)) */ +#define SBC_IDCT_MULT(a,b,c) SBC_MULT_32_16_SIMPLIFIED(a,b,c) +#else +#define SBC_COS_PI_SUR_4 (0x5A827999) /* ((0x80000000) * 0.707106781) = (cos(pi/4) ) */ +#define SBC_COS_PI_SUR_8 (0x7641AF3C) /* ((0x80000000) * 0.923879533) = (cos(pi/8) ) */ +#define SBC_COS_3PI_SUR_8 (0x30FBC54D) /* ((0x80000000) * 0.382683432) = (cos(3*pi/8) ) */ +#define SBC_COS_PI_SUR_16 (0x7D8A5F3F) /* ((0x80000000) * 0.98078528 )) = (cos(pi/16) ) */ +#define SBC_COS_3PI_SUR_16 (0x6A6D98A4) /* ((0x80000000) * 0.831469612)) = (cos(3*pi/16)) */ +#define SBC_COS_5PI_SUR_16 (0x471CECE6) /* ((0x80000000) * 0.555570233)) = (cos(5*pi/16)) */ +#define SBC_COS_7PI_SUR_16 (0x18F8B83C) /* ((0x80000000) * 0.195090322)) = (cos(7*pi/16)) */ +#define SBC_IDCT_MULT(a,b,c) SBC_MULT_32_32(a,b,c) +#endif /* SBC_IS_64_MULT_IN_IDCT */ + +#if (SBC_FAST_DCT == FALSE) +extern const SINT16 gas16AnalDCTcoeff8[]; +extern const SINT16 gas16AnalDCTcoeff4[]; +#endif + +void SBC_FastIDCT8(SINT32 *pInVect, SINT32 *pOutVect) +{ +#if (SBC_FAST_DCT == TRUE) +#if (SBC_ARM_ASM_OPT==TRUE) +#else +#if (SBC_IPAQ_OPT==TRUE) +#if (SBC_IS_64_MULT_IN_IDCT == TRUE) + SINT64 s64Temp; +#endif +#else +#if (SBC_IS_64_MULT_IN_IDCT == TRUE) + SINT32 s32HiTemp; +#else + SINT32 s32In2Temp; + register SINT32 s32In1Temp; +#endif +#endif +#endif + + register SINT32 x0, x1, x2, x3, x4, x5, x6, x7,temp; + SINT32 res_even[4], res_odd[4]; + /*x0= (pInVect[4])/2 ;*/ + SBC_IDCT_MULT(SBC_COS_PI_SUR_4,pInVect[4], x0); + /*printf("x0 0x%x = %d = %d * %d\n", x0, x0, SBC_COS_PI_SUR_4, pInVect[4]);*/ + + x1 = (pInVect[3] + pInVect[5]) >>1; + x2 = (pInVect[2] + pInVect[6]) >>1; + x3 = (pInVect[1] + pInVect[7]) >>1; + x4 = (pInVect[0] + pInVect[8]) >>1; + x5 = (pInVect[9] - pInVect[15]) >>1; + x6 = (pInVect[10] - pInVect[14])>>1; + x7 = (pInVect[11] - pInVect[13])>>1; + + /* 2-point IDCT of x0 and x4 as in (11) */ + temp = x0 ; + SBC_IDCT_MULT(SBC_COS_PI_SUR_4, ( x0 + x4 ), x0); /*x0 = ( x0 + x4 ) * cos(1*pi/4) ; */ + SBC_IDCT_MULT(SBC_COS_PI_SUR_4, ( temp - x4 ), x4); /*x4 = ( temp - x4 ) * cos(1*pi/4) ; */ + + /* rearrangement of x2 and x6 as in (15) */ + x2 -=x6; + x6 <<= 1 ; + + /* 2-point IDCT of x2 and x6 and post-multiplication as in (15) */ + SBC_IDCT_MULT(SBC_COS_PI_SUR_4,x6, x6); /*x6 = x6 * cos(1*pi/4) ; */ + temp = x2 ; + SBC_IDCT_MULT(SBC_COS_PI_SUR_8,( x2 + x6 ), x2); /*x2 = ( x2 + x6 ) * cos(1*pi/8) ; */ + SBC_IDCT_MULT(SBC_COS_3PI_SUR_8,( temp - x6 ), x6); /*x6 = ( temp - x6 ) * cos(3*pi/8) ;*/ + + /* 4-point IDCT of x0,x2,x4 and x6 as in (11) */ + res_even[ 0 ] = x0 + x2 ; + res_even[ 1 ] = x4 + x6 ; + res_even[ 2 ] = x4 - x6 ; + res_even[ 3 ] = x0 - x2 ; + + + /* rearrangement of x1,x3,x5,x7 as in (15) */ + x7 <<= 1 ; + x5 = ( x5 <<1 ) - x7 ; + x3 = ( x3 <<1 ) - x5 ; + x1 -= x3 >>1 ; + + /* two-dimensional IDCT of x1 and x5 */ + SBC_IDCT_MULT(SBC_COS_PI_SUR_4, x5, x5); /*x5 = x5 * cos(1*pi/4) ; */ + temp = x1 ; + x1 = x1 + x5 ; + x5 = temp - x5 ; + + /* rearrangement of x3 and x7 as in (15) */ + x3 -= x7; + x7 <<= 1 ; + SBC_IDCT_MULT(SBC_COS_PI_SUR_4, x7, x7); /*x7 = x7 * cos(1*pi/4) ; */ + + /* 2-point IDCT of x3 and x7 and post-multiplication as in (15) */ + temp = x3 ; + SBC_IDCT_MULT( SBC_COS_PI_SUR_8,( x3 + x7 ), x3); /*x3 = ( x3 + x7 ) * cos(1*pi/8) ; */ + SBC_IDCT_MULT( SBC_COS_3PI_SUR_8,( temp - x7 ), x7); /*x7 = ( temp - x7 ) * cos(3*pi/8) ;*/ + + /* 4-point IDCT of x1,x3,x5 and x7 and post multiplication by diagonal matrix as in (14) */ + SBC_IDCT_MULT((SBC_COS_PI_SUR_16), ( x1 + x3 ) , res_odd[0]); /*res_odd[ 0 ] = ( x1 + x3 ) * cos(1*pi/16) ; */ + SBC_IDCT_MULT((SBC_COS_3PI_SUR_16), ( x5 + x7 ) , res_odd[1]); /*res_odd[ 1 ] = ( x5 + x7 ) * cos(3*pi/16) ; */ + SBC_IDCT_MULT((SBC_COS_5PI_SUR_16), ( x5 - x7 ) , res_odd[2]); /*res_odd[ 2 ] = ( x5 - x7 ) * cos(5*pi/16) ; */ + SBC_IDCT_MULT((SBC_COS_7PI_SUR_16), ( x1 - x3 ) , res_odd[3]); /*res_odd[ 3 ] = ( x1 - x3 ) * cos(7*pi/16) ; */ + + /* additions and subtractions as in (9) */ + pOutVect[0] = (res_even[ 0 ] + res_odd[ 0 ]) ; + pOutVect[1] = (res_even[ 1 ] + res_odd[ 1 ]) ; + pOutVect[2] = (res_even[ 2 ] + res_odd[ 2 ]) ; + pOutVect[3] = (res_even[ 3 ] + res_odd[ 3 ]) ; + pOutVect[7] = (res_even[ 0 ] - res_odd[ 0 ]) ; + pOutVect[6] = (res_even[ 1 ] - res_odd[ 1 ]) ; + pOutVect[5] = (res_even[ 2 ] - res_odd[ 2 ]) ; + pOutVect[4] = (res_even[ 3 ] - res_odd[ 3 ]) ; +#else + UINT8 Index, k; + SINT32 temp; + /*Calculate 4 subband samples by matrixing*/ + for(Index=0; Index<8; Index++) + { + temp = 0; + for(k=0; k<16; k++) + { + /*temp += (SINT32)(((SINT64)M[(Index*strEncParams->numOfSubBands*2)+k] * Y[k]) >> 16 );*/ + temp += (gas16AnalDCTcoeff8[(Index*8*2)+k] * (pInVect[k] >> 16)); + temp += ((gas16AnalDCTcoeff8[(Index*8*2)+k] * (pInVect[k] & 0xFFFF)) >> 16); + } + pOutVect[Index] = temp; + } +#endif +/* printf("pOutVect: 0x%x;0x%x;0x%x;0x%x;0x%x;0x%x;0x%x;0x%x\n",\ + pOutVect[0],pOutVect[1],pOutVect[2],pOutVect[3],pOutVect[4],pOutVect[5],pOutVect[6],pOutVect[7]);*/ +} + +/******************************************************************************* +** +** Function SBC_FastIDCT4 +** +** Description implementation of fast DCT algorithm by Feig and Winograd +** +** +** Returns y = dct(x0) +** +** +*******************************************************************************/ +void SBC_FastIDCT4(SINT32 *pInVect, SINT32 *pOutVect) +{ +#if (SBC_FAST_DCT == TRUE) +#if (SBC_ARM_ASM_OPT==TRUE) +#else +#if (SBC_IPAQ_OPT==TRUE) +#if (SBC_IS_64_MULT_IN_IDCT == TRUE) + SINT64 s64Temp; +#endif +#else +#if (SBC_IS_64_MULT_IN_IDCT == TRUE) + SINT32 s32HiTemp; +#else + UINT16 s32In2Temp; + SINT32 s32In1Temp; +#endif +#endif +#endif + SINT32 temp,x2; + SINT32 tmp[8]; + + x2=pInVect[2]>>1; + temp=(pInVect[0]+pInVect[4]); + SBC_IDCT_MULT((SBC_COS_PI_SUR_4>>1), temp , tmp[0]); + tmp[1]=x2-tmp[0]; + tmp[0]+=x2; + temp=(pInVect[1]+pInVect[3]); + SBC_IDCT_MULT((SBC_COS_3PI_SUR_8>>1), temp , tmp[3]); + SBC_IDCT_MULT((SBC_COS_PI_SUR_8>>1), temp , tmp[2]); + temp=(pInVect[5]-pInVect[7]); + SBC_IDCT_MULT((SBC_COS_3PI_SUR_8>>1), temp , tmp[5]); + SBC_IDCT_MULT((SBC_COS_PI_SUR_8>>1), temp , tmp[4]); + tmp[6]=tmp[2]+tmp[5]; + tmp[7]=tmp[3]-tmp[4]; + pOutVect[0] = (tmp[0]+tmp[6]); + pOutVect[1] = (tmp[1]+tmp[7]); + pOutVect[2] = (tmp[1]-tmp[7]); + pOutVect[3] = (tmp[0]-tmp[6]); +#else + UINT8 Index, k; + SINT32 temp; + /*Calculate 4 subband samples by matrixing*/ + for(Index=0; Index<4; Index++) + { + temp = 0; + for(k=0; k<8; k++) + { + /*temp += (SINT32)(((SINT64)M[(Index*strEncParams->numOfSubBands*2)+k] * Y[k]) >> 16 ); */ + temp += (gas16AnalDCTcoeff4[(Index*4*2)+k] * (pInVect[k] >> 16)); + temp += ((gas16AnalDCTcoeff4[(Index*4*2)+k] * (pInVect[k] & 0xFFFF)) >> 16); + } + pOutVect[Index] = temp; + } +#endif +} diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_dct_coeffs.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_dct_coeffs.c new file mode 100755 index 0000000000..c450c272ab --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_dct_coeffs.c @@ -0,0 +1,200 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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 the coefficient table used for DCT computation in + * analysis. + * + ******************************************************************************/ + +#include "sbc_encoder.h" +/*DCT coeff for 4 sub-band case.*/ +#if (SBC_FAST_DCT == FALSE) +const SINT16 gas16AnalDCTcoeff4[] = +{ + (SINT16)(0.7071*32768), + (SINT16)(0.9239*32768), + (SINT16)(1.0000*32767), + (SINT16)(0.9239*32768), + (SINT16)(0.7071*32768), + (SINT16)(0.3827*32768), + (SINT16)(0.0000*32768), + (SINT16)(-0.3827*32768), + + (SINT16)(-0.7071*32768), + (SINT16)(0.3827*32768), + (SINT16)(1.0000*32767), + (SINT16)(0.3827*32768), + (SINT16)(-0.7071*32768), + (SINT16)(-0.9239*32768), + (SINT16)(-0.0000*32768), + (SINT16)(0.9239*32768), + + (SINT16)(-0.7071*32768), + (SINT16)(-0.3827*32768), + (SINT16)(1.0000*32767), + (SINT16)(-0.3827*32768), + (SINT16)(-0.7071*32768), + (SINT16)(0.9239*32768), + (SINT16)(0.0000*32768), + (SINT16)(-0.9239*32768), + + (SINT16)(0.7071*32768), + (SINT16)(-0.9239*32768), + (SINT16)(1.0000*32767), + (SINT16)(-0.9239*32768), + (SINT16)(0.7071*32768), + (SINT16)(-0.3827*32768), + (SINT16)(-0.0000*32768), + (SINT16)(0.3827*32768) +}; + +/*DCT coeff for 8 sub-band case.*/ +const SINT16 gas16AnalDCTcoeff8[] = +{ + (SINT16)(0.7071*32768), + (SINT16)(0.8315*32768), + (SINT16)(0.9239*32768), + (SINT16)(0.9808*32768), + (SINT16)(1.0000*32767), + (SINT16)(0.9808*32768), + (SINT16)(0.9239*32768), + (SINT16)(0.8315*32768), + (SINT16)(0.7071*32768), + (SINT16)(0.5556*32768), + (SINT16)(0.3827*32768), + (SINT16)(0.1951*32768), + (SINT16)(0.0000*32768), + (SINT16)(-0.1951*32768), + (SINT16)(-0.3827*32768), + (SINT16)(-0.5556*32768), + (SINT16)(-0.7071*32768), + (SINT16)(-0.1951*32768), + (SINT16)(0.3827*32768), + (SINT16)(0.8315*32768), + (SINT16)(1.0000*32767), + (SINT16)(0.8315*32768), + (SINT16)(0.3827*32768), + (SINT16)(-0.1951*32768), + (SINT16)(-0.7071*32768), + (SINT16)(-0.9808*32768), + (SINT16)(-0.9239*32768), + (SINT16)(-0.5556*32768), + (SINT16)(-0.0000*32768), + (SINT16)(0.5556*32768), + (SINT16)(0.9239*32768), + (SINT16)(0.9808*32768), + (SINT16)(-0.7071*32768), + (SINT16)(-0.9808*32768), + (SINT16)(-0.3827*32768), + (SINT16)(0.5556*32768), + (SINT16)(1.0000*32767), + (SINT16)(0.5556*32768), + (SINT16)(-0.3827*32768), + (SINT16)(-0.9808*32768), + (SINT16)(-0.7071*32768), + (SINT16)(0.1951*32768), + (SINT16)(0.9239*32768), + (SINT16)(0.8315*32768), + (SINT16)(0.0000*32768), + (SINT16)(-0.8315*32768), + (SINT16)(-0.9239*32768), + (SINT16)(-0.1951*32768), + (SINT16)(0.7071*32768), + (SINT16)(-0.5556*32768), + (SINT16)(-0.9239*32768), + (SINT16)(0.1951*32768), + (SINT16)(1.0000*32767), + (SINT16)(0.1951*32768), + (SINT16)(-0.9239*32768), + (SINT16)(-0.5556*32768), + (SINT16)(0.7071*32768), + (SINT16)(0.8315*32768), + (SINT16)(-0.3827*32768), + (SINT16)(-0.9808*32768), + (SINT16)(-0.0000*32768), + (SINT16)(0.9808*32768), + (SINT16)(0.3827*32768), + (SINT16)(-0.8315*32768), + (SINT16)(0.7071*32768), + (SINT16)(0.5556*32768), + (SINT16)(-0.9239*32768), + (SINT16)(-0.1951*32768), + (SINT16)(1.0000*32767), + (SINT16)(-0.1951*32768), + (SINT16)(-0.9239*32768), + (SINT16)(0.5556*32768), + (SINT16)(0.7071*32768), + (SINT16)(-0.8315*32768), + (SINT16)(-0.3827*32768), + (SINT16)(0.9808*32768), + (SINT16)(0.0000*32768), + (SINT16)(-0.9808*32768), + (SINT16)(0.3827*32768), + (SINT16)(0.8315*32768), + (SINT16)(-0.7071*32768), + (SINT16)(0.9808*32768), + (SINT16)(-0.3827*32768), + (SINT16)(-0.5556*32768), + (SINT16)(1.0000*32767), + (SINT16)(-0.5556*32768), + (SINT16)(-0.3827*32768), + (SINT16)(0.9808*32768), + (SINT16)(-0.7071*32768), + (SINT16)(-0.1951*32768), + (SINT16)(0.9239*32768), + (SINT16)(-0.8315*32768), + (SINT16)(-0.0000*32768), + (SINT16)(0.8315*32768), + (SINT16)(-0.9239*32768), + (SINT16)(0.1951*32768), + (SINT16)(-0.7071*32768), + (SINT16)(0.1951*32768), + (SINT16)(0.3827*32768), + (SINT16)(-0.8315*32768), + (SINT16)(1.0000*32767), + (SINT16)(-0.8315*32768), + (SINT16)(0.3827*32768), + (SINT16)(0.1951*32768), + (SINT16)(-0.7071*32768), + (SINT16)(0.9808*32768), + (SINT16)(-0.9239*32768), + (SINT16)(0.5556*32768), + (SINT16)(-0.0000*32768), + (SINT16)(-0.5556*32768), + (SINT16)(0.9239*32768), + (SINT16)(-0.9808*32768), + (SINT16)(0.7071*32768), + (SINT16)(-0.8315*32768), + (SINT16)(0.9239*32768), + (SINT16)(-0.9808*32768), + (SINT16)(1.0000*32767), + (SINT16)(-0.9808*32768), + (SINT16)(0.9239*32768), + (SINT16)(-0.8315*32768), + (SINT16)(0.7071*32768), + (SINT16)(-0.5556*32768), + (SINT16)(0.3827*32768), + (SINT16)(-0.1951*32768), + (SINT16)(-0.0000*32768), + (SINT16)(0.1951*32768), + (SINT16)(-0.3827*32768), + (SINT16)(0.5556*32768) +}; +#endif diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c new file mode 100755 index 0000000000..c033e2405b --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c @@ -0,0 +1,199 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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 the code for bit allocation algorithm. It calculates + * the number of bits required for the encoded stream of data. + * + ******************************************************************************/ + +/*Includes*/ +#include "sbc_encoder.h" +#include "sbc_enc_func_declare.h" + +/*global arrays*/ +const SINT16 sbc_enc_as16Offset4[4][4] = { {-1, 0, 0, 0}, {-2, 0, 0, 1}, + {-2, 0, 0, 1}, {-2, 0, 0, 1} }; +const SINT16 sbc_enc_as16Offset8[4][8] = { {-2, 0, 0, 0, 0, 0, 0, 1}, + {-3, 0, 0, 0, 0, 0, 1, 2}, + {-4, 0, 0, 0, 0, 0, 1, 2}, + {-4, 0, 0, 0, 0, 0, 1, 2} }; + +/**************************************************************************** +* BitAlloc - Calculates the required number of bits for the given scale factor +* and the number of subbands. +* +* RETURNS : N/A +*/ + +void sbc_enc_bit_alloc_mono(SBC_ENC_PARAMS *pstrCodecParams) +{ + SINT32 s32MaxBitNeed; /*to store the max bits needed per sb*/ + SINT32 s32BitCount; /*the used number of bits*/ + SINT32 s32SliceCount; /*to store hwo many slices can be put in bitpool*/ + SINT32 s32BitSlice; /*number of bitslices in bitpool*/ + SINT32 s32Sb; /*counter for sub-band*/ + SINT32 s32Ch; /*counter for channel*/ + SINT16 *ps16BitNeed; /*temp memory to store required number of bits*/ + SINT32 s32Loudness; /*used in Loudness calculation*/ + SINT16 *ps16GenBufPtr; + SINT16 *ps16GenArrPtr; + SINT16 *ps16GenTabPtr; + SINT32 s32NumOfSubBands = pstrCodecParams->s16NumOfSubBands; + + ps16BitNeed = pstrCodecParams->s16ScartchMemForBitAlloc; + + for (s32Ch = 0; s32Ch < pstrCodecParams->s16NumOfChannels; s32Ch++) + { + ps16GenBufPtr = ps16BitNeed + s32Ch*s32NumOfSubBands; + ps16GenArrPtr = pstrCodecParams->as16Bits+s32Ch*SBC_MAX_NUM_OF_SUBBANDS; + + /* bitneed values are derived from scale factor */ + if (pstrCodecParams->s16AllocationMethod == SBC_SNR) + { + ps16BitNeed = pstrCodecParams->as16ScaleFactor; + ps16GenBufPtr = ps16BitNeed + s32Ch * s32NumOfSubBands; + } + else + { + ps16GenBufPtr = ps16BitNeed + s32Ch*s32NumOfSubBands; + if(s32NumOfSubBands == 4) + { + ps16GenTabPtr = (SINT16 *) + sbc_enc_as16Offset4[pstrCodecParams->s16SamplingFreq]; + } + else + { + ps16GenTabPtr = (SINT16 *) + sbc_enc_as16Offset8[pstrCodecParams->s16SamplingFreq]; + } + for(s32Sb=0; s32Sbas16ScaleFactor[s32Ch*s32NumOfSubBands+s32Sb] == 0) + *(ps16GenBufPtr) = -5; + else + { + s32Loudness = + (SINT32)(pstrCodecParams->as16ScaleFactor[s32Ch*s32NumOfSubBands+s32Sb] + - *ps16GenTabPtr); + if(s32Loudness > 0) + *(ps16GenBufPtr) = (SINT16)(s32Loudness >>1); + else + *(ps16GenBufPtr) = (SINT16)s32Loudness; + } + ps16GenBufPtr++; + ps16GenTabPtr++; + } + + } + + /* max bitneed index is searched*/ + s32MaxBitNeed = 0; + ps16GenBufPtr = ps16BitNeed + s32Ch*s32NumOfSubBands; + for(s32Sb=0; s32Sb s32MaxBitNeed) + s32MaxBitNeed = *(ps16GenBufPtr); + + ps16GenBufPtr++; + } + ps16GenBufPtr = ps16BitNeed + s32Ch*s32NumOfSubBands; + /*iterative process to find hwo many bitslices fit into the bitpool*/ + s32BitSlice = s32MaxBitNeed + 1; + s32BitCount = pstrCodecParams->s16BitPool; + s32SliceCount = 0; + do + { + s32BitSlice --; + s32BitCount -= s32SliceCount; + s32SliceCount = 0; + + for(s32Sb=0; s32Sb= 1)) + { + if((*ps16GenBufPtr-s32BitSlice) == 1) + s32SliceCount+=2; + else + s32SliceCount++; + } + ps16GenBufPtr++; + + }/*end of for*/ + ps16GenBufPtr = ps16BitNeed + s32Ch*s32NumOfSubBands; + }while(s32BitCount-s32SliceCount>0); + + if(s32BitCount == 0) + { + s32BitCount -= s32SliceCount; + s32BitSlice --; + } + + /*Bits are distributed until the last bitslice is reached*/ + ps16GenArrPtr = pstrCodecParams->as16Bits+s32Ch*s32NumOfSubBands; + ps16GenBufPtr = ps16BitNeed + s32Ch*s32NumOfSubBands; + for(s32Sb=0; s32Sbas16Bits+s32Ch*s32NumOfSubBands; + ps16GenBufPtr = ps16BitNeed + s32Ch*s32NumOfSubBands; + /*the remaining bits are allocated starting at subband 0*/ + s32Sb=0; + while( (s32BitCount > 0) && (s32Sb < s32NumOfSubBands) ) + { + if( (*(ps16GenArrPtr) >= 2) && (*(ps16GenArrPtr) < 16) ) + { + (*(ps16GenArrPtr))++; + s32BitCount--; + } + else if( (*(ps16GenBufPtr) == s32BitSlice+1) && + (s32BitCount > 1) ) + { + *(ps16GenArrPtr) = 2; + s32BitCount -= 2; + } + s32Sb++; + ps16GenArrPtr++; + ps16GenBufPtr++; + } + ps16GenArrPtr = pstrCodecParams->as16Bits+s32Ch*s32NumOfSubBands; + + + s32Sb=0; + while( (s32BitCount > 0) && (s32Sb < s32NumOfSubBands) ) + { + if( *(ps16GenArrPtr) < 16) + { + (*(ps16GenArrPtr))++; + s32BitCount--; + } + s32Sb++; + ps16GenArrPtr++; + } + } +} +/*End of BitAlloc() function*/ diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c new file mode 100755 index 0000000000..75d1630314 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c @@ -0,0 +1,212 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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 the code for bit allocation algorithm. It calculates + * the number of bits required for the encoded stream of data. + * + ******************************************************************************/ + +/*Includes*/ +#include "sbc_encoder.h" +#include "sbc_enc_func_declare.h" + +/*global arrays*/ +extern const SINT16 sbc_enc_as16Offset4[4][4]; +extern const SINT16 sbc_enc_as16Offset8[4][8]; + +/**************************************************************************** +* BitAlloc - Calculates the required number of bits for the given scale factor +* and the number of subbands. +* +* RETURNS : N/A +*/ + +void sbc_enc_bit_alloc_ste(SBC_ENC_PARAMS *pstrCodecParams) +{ + /* CAUTIOM -> mips optim for arm 32 require to use SINT32 instead of SINT16 */ + /* Do not change variable type or name */ + SINT32 s32MaxBitNeed; /*to store the max bits needed per sb*/ + SINT32 s32BitCount; /*the used number of bits*/ + SINT32 s32SliceCount; /*to store hwo many slices can be put in bitpool*/ + SINT32 s32BitSlice; /*number of bitslices in bitpool*/ + SINT32 s32Sb; /*counter for sub-band*/ + SINT32 s32Ch; /*counter for channel*/ + SINT16 *ps16BitNeed; /*temp memory to store required number of bits*/ + SINT32 s32Loudness; /*used in Loudness calculation*/ + SINT16 *ps16GenBufPtr,*pas16ScaleFactor; + SINT16 *ps16GenArrPtr; + SINT16 *ps16GenTabPtr; + SINT32 s32NumOfSubBands = pstrCodecParams->s16NumOfSubBands; + SINT32 s32BitPool = pstrCodecParams->s16BitPool; + + /* bitneed values are derived from scale factor */ + if (pstrCodecParams->s16AllocationMethod == SBC_SNR) + { + ps16BitNeed = pstrCodecParams->as16ScaleFactor; + s32MaxBitNeed = pstrCodecParams->s16MaxBitNeed; + } + else + { + ps16BitNeed = pstrCodecParams->s16ScartchMemForBitAlloc; + pas16ScaleFactor=pstrCodecParams->as16ScaleFactor; + s32MaxBitNeed = 0; + ps16GenBufPtr = ps16BitNeed; + for (s32Ch = 0; s32Ch < 2; s32Ch++) + { + if (s32NumOfSubBands == 4) + { + ps16GenTabPtr = (SINT16 *)sbc_enc_as16Offset4[pstrCodecParams->s16SamplingFreq]; + } + else + { + ps16GenTabPtr = (SINT16 *)sbc_enc_as16Offset8[pstrCodecParams->s16SamplingFreq]; + } + + for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) + { + if (*pas16ScaleFactor == 0) + *ps16GenBufPtr = -5; + else + { + s32Loudness = (SINT32)(*pas16ScaleFactor - *ps16GenTabPtr); + + if (s32Loudness > 0) + *ps16GenBufPtr = (SINT16)(s32Loudness >> 1); + else + *ps16GenBufPtr = (SINT16)s32Loudness; + } + + if (*ps16GenBufPtr > s32MaxBitNeed) + s32MaxBitNeed = *ps16GenBufPtr; + pas16ScaleFactor++; + ps16GenBufPtr++; + ps16GenTabPtr++; + } + } + } + + /* iterative process to find out hwo many bitslices fit into the bitpool */ + s32BitSlice = s32MaxBitNeed + 1; + s32BitCount = s32BitPool; + s32SliceCount = 0; + do + { + s32BitSlice --; + s32BitCount -= s32SliceCount; + s32SliceCount = 0; + ps16GenBufPtr = ps16BitNeed; + + for (s32Sb = 0; s32Sb < 2*s32NumOfSubBands; s32Sb++) + { + if ( (*ps16GenBufPtr >= s32BitSlice + 1) && (*ps16GenBufPtr < s32BitSlice + 16) ) + { + if (*(ps16GenBufPtr) == s32BitSlice+1) + s32SliceCount += 2; + else + s32SliceCount++; + } + ps16GenBufPtr++; + } + } while (s32BitCount-s32SliceCount>0); + + if (s32BitCount-s32SliceCount == 0) + { + s32BitCount -= s32SliceCount; + s32BitSlice --; + } + + /* Bits are distributed until the last bitslice is reached */ + ps16GenBufPtr = ps16BitNeed; + ps16GenArrPtr = pstrCodecParams->as16Bits; + for (s32Ch = 0; s32Ch < 2; s32Ch++) + { + for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) + { + if (*ps16GenBufPtr < s32BitSlice+2) + *ps16GenArrPtr = 0; + else + *ps16GenArrPtr = ((*(ps16GenBufPtr)-s32BitSlice) < 16) ? + (SINT16)(*(ps16GenBufPtr)-s32BitSlice):16; + ps16GenBufPtr++; + ps16GenArrPtr++; + } + } + + /* the remaining bits are allocated starting at subband 0 */ + s32Ch=0; + s32Sb=0; + ps16GenBufPtr = ps16BitNeed; + ps16GenArrPtr -= 2*s32NumOfSubBands; + + while ( (s32BitCount > 0) && (s32Sb < s32NumOfSubBands) ) + { + if ( (*(ps16GenArrPtr) >= 2) && (*(ps16GenArrPtr) < 16) ) + { + (*(ps16GenArrPtr))++; + s32BitCount--; + } + else if ((*ps16GenBufPtr == s32BitSlice+1) && (s32BitCount > 1)) + { + *(ps16GenArrPtr) = 2; + s32BitCount -= 2; + } + if(s32Ch == 1) + { + s32Ch = 0; + s32Sb++; + ps16GenBufPtr = ps16BitNeed+s32Sb; + ps16GenArrPtr = pstrCodecParams->as16Bits+s32Sb; + + } + else + { + s32Ch =1; + ps16GenBufPtr = ps16BitNeed+s32NumOfSubBands+s32Sb; + ps16GenArrPtr = pstrCodecParams->as16Bits+s32NumOfSubBands+s32Sb; + } + } + + s32Ch=0; + s32Sb=0; + ps16GenArrPtr = pstrCodecParams->as16Bits; + + while ((s32BitCount >0) && (s32Sb < s32NumOfSubBands)) + { + if(*(ps16GenArrPtr) < 16) + { + (*(ps16GenArrPtr))++; + s32BitCount--; + } + if (s32Ch == 1) + { + s32Ch = 0; + s32Sb++; + ps16GenArrPtr = pstrCodecParams->as16Bits+s32Sb; + } + else + { + s32Ch = 1; + ps16GenArrPtr = pstrCodecParams->as16Bits+s32NumOfSubBands+s32Sb; + } + } +} + +/*End of BitAlloc() function*/ + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_coeffs.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_coeffs.c new file mode 100755 index 0000000000..2ecfbfdc85 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_enc_coeffs.c @@ -0,0 +1,319 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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 the Windowing coeffs for synthesis filter + * + ******************************************************************************/ + +#include "sbc_encoder.h" + +#if (SBC_ARM_ASM_OPT==FALSE && SBC_IPAQ_OPT==FALSE) +#if (SBC_IS_64_MULT_IN_WINDOW_ACCU == FALSE) +/*Window coeff for 4 sub band case*/ +const SINT16 gas32CoeffFor4SBs[] = +{ + (SINT16)((SINT32)0x00000000 >> 16), (SINT16)0x00000000, + (SINT16)((SINT32)0x001194E6 >> 16), (SINT16)0x001194E6, + (SINT16)((SINT32)0x0030E2D3 >> 16), (SINT16)0x0030E2D3, + (SINT16)((SINT32)0x00599403 >> 16), (SINT16)0x00599403, + (SINT16)((SINT32)0x007DBCC8 >> 16), (SINT16)0x007DBCC8, + (SINT16)((SINT32)0x007F88E4 >> 16), (SINT16)0x007F88E4, + (SINT16)((SINT32)0x003D239B >> 16), (SINT16)0x003D239B, + (SINT16)((SINT32)0xFF9BB9D5 >> 16), (SINT16)0xFF9BB9D5, + + (SINT16)((SINT32)0x01659F45 >> 16), (SINT16)0x01659F45, + (SINT16)((SINT32)0x029DBAA3 >> 16), (SINT16)0x029DBAA3, + (SINT16)((SINT32)0x03B23341 >> 16), (SINT16)0x03B23341, + (SINT16)((SINT32)0x041EEE40 >> 16), (SINT16)0x041EEE40, + (SINT16)((SINT32)0x034FEE2C >> 16), (SINT16)0x034FEE2C, + (SINT16)((SINT32)0x00C8F2BC >> 16), (SINT16)0x00C8F2BC, + (SINT16)((SINT32)0xFC4F91D4 >> 16), (SINT16)0xFC4F91D4, + (SINT16)((SINT32)0xF60FAF37 >> 16), (SINT16)0xF60FAF37, + + (SINT16)((SINT32)0x115B1ED2 >> 16), (SINT16)0x115B1ED2, + (SINT16)((SINT32)0x18F55C90 >> 16), (SINT16)0x18F55C90, + (SINT16)((SINT32)0x1F91CA46 >> 16), (SINT16)0x1F91CA46, + (SINT16)((SINT32)0x2412F251 >> 16), (SINT16)0x2412F251, + (SINT16)((SINT32)0x25AC1FF2 >> 16), (SINT16)0x25AC1FF2, + (SINT16)((SINT32)0x2412F251 >> 16), (SINT16)0x2412F251, + (SINT16)((SINT32)0x1F91CA46 >> 16), (SINT16)0x1F91CA46, + (SINT16)((SINT32)0x18F55C90 >> 16), (SINT16)0x18F55C90, + + (SINT16)((SINT32)0xEEA4E12E >> 16), (SINT16)0xEEA4E12E, + (SINT16)((SINT32)0xF60FAF37 >> 16), (SINT16)0xF60FAF37, + (SINT16)((SINT32)0xFC4F91D4 >> 16), (SINT16)0xFC4F91D4, + (SINT16)((SINT32)0x00C8F2BC >> 16), (SINT16)0x00C8F2BC, + (SINT16)((SINT32)0x034FEE2C >> 16), (SINT16)0x034FEE2C, + (SINT16)((SINT32)0x041EEE40 >> 16), (SINT16)0x041EEE40, + (SINT16)((SINT32)0x03B23341 >> 16), (SINT16)0x03B23341, + (SINT16)((SINT32)0x029DBAA3 >> 16), (SINT16)0x029DBAA3, + + (SINT16)((SINT32)0xFE9A60BB >> 16), (SINT16)0xFE9A60BB, + (SINT16)((SINT32)0xFF9BB9D5 >> 16), (SINT16)0xFF9BB9D5, + (SINT16)((SINT32)0x003D239B >> 16), (SINT16)0x003D239B, + (SINT16)((SINT32)0x007F88E4 >> 16), (SINT16)0x007F88E4, + (SINT16)((SINT32)0x007DBCC8 >> 16), (SINT16)0x007DBCC8, + (SINT16)((SINT32)0x00599403 >> 16), (SINT16)0x00599403, + (SINT16)((SINT32)0x0030E2D3 >> 16), (SINT16)0x0030E2D3, + (SINT16)((SINT32)0x001194E6 >> 16), (SINT16)0x001194E6 +}; + +/*Window coeff for 8 sub band case*/ +const SINT16 gas32CoeffFor8SBs[] = +{ + (SINT16)((SINT32)0x00000000 >>16), (SINT16)0x00000000, + (SINT16)((SINT32)0x00052173 >>16), (SINT16)0x00052173, + (SINT16)((SINT32)0x000B3F71 >>16), (SINT16)0x000B3F71, + (SINT16)((SINT32)0x00122C7D >>16), (SINT16)0x00122C7D, + (SINT16)((SINT32)0x001AFF89 >>16), (SINT16)0x001AFF89, + (SINT16)((SINT32)0x00255A62 >>16), (SINT16)0x00255A62, + (SINT16)((SINT32)0x003060F4 >>16), (SINT16)0x003060F4, + (SINT16)((SINT32)0x003A72E7 >>16), (SINT16)0x003A72E7, + + (SINT16)((SINT32)0x0041EC6A >>16), (SINT16)0x0041EC6A, /* 8 */ + (SINT16)((SINT32)0x0044EF48 >>16), (SINT16)0x0044EF48, + (SINT16)((SINT32)0x00415B75 >>16), (SINT16)0x00415B75, + (SINT16)((SINT32)0x0034F8B6 >>16), (SINT16)0x0034F8B6, + (SINT16)((SINT32)0x001D8FD2 >>16), (SINT16)0x001D8FD2, + (SINT16)((SINT32)0xFFFA2413 >>16), (SINT16)0xFFFA2413, + (SINT16)((SINT32)0xFFC9F10E >>16), (SINT16)0xFFC9F10E, + (SINT16)((SINT32)0xFF8D6793 >>16), (SINT16)0xFF8D6793, + + (SINT16)((SINT32)0x00B97348 >>16), (SINT16)0x00B97348, /* 16 */ + (SINT16)((SINT32)0x01071B96 >>16), (SINT16)0x01071B96, + (SINT16)((SINT32)0x0156B3CA >>16), (SINT16)0x0156B3CA, + (SINT16)((SINT32)0x01A1B38B >>16), (SINT16)0x01A1B38B, + (SINT16)((SINT32)0x01E0224C >>16), (SINT16)0x01E0224C, + (SINT16)((SINT32)0x0209291F >>16), (SINT16)0x0209291F, + (SINT16)((SINT32)0x02138653 >>16), (SINT16)0x02138653, + (SINT16)((SINT32)0x01F5F424 >>16), (SINT16)0x01F5F424, + + (SINT16)((SINT32)0x01A7ECEF >>16), (SINT16)0x01A7ECEF, /* 24 */ + (SINT16)((SINT32)0x01223EBA >>16), (SINT16)0x01223EBA, + (SINT16)((SINT32)0x005FD0FF >>16), (SINT16)0x005FD0FF, + (SINT16)((SINT32)0xFF5EEB73 >>16), (SINT16)0xFF5EEB73, + (SINT16)((SINT32)0xFE20435D >>16), (SINT16)0xFE20435D, + (SINT16)((SINT32)0xFCA86E7E >>16), (SINT16)0xFCA86E7E, + (SINT16)((SINT32)0xFAFF95FC >>16), (SINT16)0xFAFF95FC, + (SINT16)((SINT32)0xF9312891 >>16), (SINT16)0xF9312891, + + (SINT16)((SINT32)0x08B4307A >>16), (SINT16)0x08B4307A, /* 32 */ + (SINT16)((SINT32)0x0A9F3E9A >>16), (SINT16)0x0A9F3E9A, + (SINT16)((SINT32)0x0C7D59B6 >>16), (SINT16)0x0C7D59B6, + (SINT16)((SINT32)0x0E3BB16F >>16), (SINT16)0x0E3BB16F, + (SINT16)((SINT32)0x0FC721F9 >>16), (SINT16)0x0FC721F9, + (SINT16)((SINT32)0x110ECEF0 >>16), (SINT16)0x110ECEF0, + (SINT16)((SINT32)0x120435FA >>16), (SINT16)0x120435FA, + (SINT16)((SINT32)0x129C226F >>16), (SINT16)0x129C226F, + + (SINT16)((SINT32)0x12CF6C75 >>16), (SINT16)0x12CF6C75, /* 40 */ + (SINT16)((SINT32)0x129C226F >>16), (SINT16)0x129C226F, + (SINT16)((SINT32)0x120435FA >>16), (SINT16)0x120435FA, + (SINT16)((SINT32)0x110ECEF0 >>16), (SINT16)0x110ECEF0, + (SINT16)((SINT32)0x0FC721F9 >>16), (SINT16)0x0FC721F9, + (SINT16)((SINT32)0x0E3BB16F >>16), (SINT16)0x0E3BB16F, + (SINT16)((SINT32)0x0C7D59B6 >>16), (SINT16)0x0C7D59B6, + (SINT16)((SINT32)0x0A9F3E9A >>16), (SINT16)0x0A9F3E9A, + + (SINT16)((SINT32)0xF74BCF86 >>16), (SINT16)0xF74BCF86, /* 48 */ + (SINT16)((SINT32)0xF9312891 >>16), (SINT16)0xF9312891, + (SINT16)((SINT32)0xFAFF95FC >>16), (SINT16)0xFAFF95FC, + (SINT16)((SINT32)0xFCA86E7E >>16), (SINT16)0xFCA86E7E, + (SINT16)((SINT32)0xFE20435D >>16), (SINT16)0xFE20435D, + (SINT16)((SINT32)0xFF5EEB73 >>16), (SINT16)0xFF5EEB73, + (SINT16)((SINT32)0x005FD0FF >>16), (SINT16)0x005FD0FF, + (SINT16)((SINT32)0x01223EBA >>16), (SINT16)0x01223EBA, + + (SINT16)((SINT32)0x01A7ECEF >>16), (SINT16)0x01A7ECEF, /* 56 */ + (SINT16)((SINT32)0x01F5F424 >>16), (SINT16)0x01F5F424, + (SINT16)((SINT32)0x02138653 >>16), (SINT16)0x02138653, + (SINT16)((SINT32)0x0209291F >>16), (SINT16)0x0209291F, + (SINT16)((SINT32)0x01E0224C >>16), (SINT16)0x01E0224C, + (SINT16)((SINT32)0x01A1B38B >>16), (SINT16)0x01A1B38B, + (SINT16)((SINT32)0x0156B3CA >>16), (SINT16)0x0156B3CA, + (SINT16)((SINT32)0x01071B96 >>16), (SINT16)0x01071B96, + + (SINT16)((SINT32)0xFF468CB8 >>16), (SINT16)0xFF468CB8, /* 64 */ + (SINT16)((SINT32)0xFF8D6793 >>16), (SINT16)0xFF8D6793, + (SINT16)((SINT32)0xFFC9F10E >>16), (SINT16)0xFFC9F10E, + (SINT16)((SINT32)0xFFFA2413 >>16), (SINT16)0xFFFA2413, + (SINT16)((SINT32)0x001D8FD2 >>16), (SINT16)0x001D8FD2, + (SINT16)((SINT32)0x0034F8B6 >>16), (SINT16)0x0034F8B6, + (SINT16)((SINT32)0x00415B75 >>16), (SINT16)0x00415B75, + (SINT16)((SINT32)0x0044EF48 >>16), (SINT16)0x0044EF48, + + (SINT16)((SINT32)0x0041EC6A >>16), (SINT16)0x0041EC6A, /* 72 */ + (SINT16)((SINT32)0x003A72E7 >>16), (SINT16)0x003A72E7, + (SINT16)((SINT32)0x003060F4 >>16), (SINT16)0x003060F4, + (SINT16)((SINT32)0x00255A62 >>16), (SINT16)0x00255A62, + (SINT16)((SINT32)0x001AFF89 >>16), (SINT16)0x001AFF89, + (SINT16)((SINT32)0x00122C7D >>16), (SINT16)0x00122C7D, + (SINT16)((SINT32)0x000B3F71 >>16), (SINT16)0x000B3F71, + (SINT16)((SINT32)0x00052173 >>16), (SINT16)0x00052173 +}; + +#else + +/*Window coeff for 4 sub band case*/ +const SINT32 gas32CoeffFor4SBs[] = +{ + (SINT32)0x00000000, + (SINT32)0x001194E6, + (SINT32)0x0030E2D3, + (SINT32)0x00599403, + (SINT32)0x007DBCC8, + (SINT32)0x007F88E4, + (SINT32)0x003D239B, + (SINT32)0xFF9BB9D5, + + (SINT32)0x01659F45, + (SINT32)0x029DBAA3, + (SINT32)0x03B23341, + (SINT32)0x041EEE40, + (SINT32)0x034FEE2C, + (SINT32)0x00C8F2BC, + (SINT32)0xFC4F91D4, + (SINT32)0xF60FAF37, + + (SINT32)0x115B1ED2, + (SINT32)0x18F55C90, + (SINT32)0x1F91CA46, + (SINT32)0x2412F251, + (SINT32)0x25AC1FF2, + (SINT32)0x2412F251, + (SINT32)0x1F91CA46, + (SINT32)0x18F55C90, + + (SINT32)0xEEA4E12E, + (SINT32)0xF60FAF37, + (SINT32)0xFC4F91D4, + (SINT32)0x00C8F2BC, + (SINT32)0x034FEE2C, + (SINT32)0x041EEE40, + (SINT32)0x03B23341, + (SINT32)0x029DBAA3, + + (SINT32)0xFE9A60BB, + (SINT32)0xFF9BB9D5, + (SINT32)0x003D239B, + (SINT32)0x007F88E4, + (SINT32)0x007DBCC8, + (SINT32)0x00599403, + (SINT32)0x0030E2D3, + (SINT32)0x001194E6 +}; + +/*Window coeff for 8 sub band case*/ +const SINT32 gas32CoeffFor8SBs[] = +{ + (SINT32)0x00000000, + (SINT32)0x00052173, + (SINT32)0x000B3F71, + (SINT32)0x00122C7D, + (SINT32)0x001AFF89, + (SINT32)0x00255A62, + (SINT32)0x003060F4, + (SINT32)0x003A72E7, + + (SINT32)0x0041EC6A, /* 8 */ + (SINT32)0x0044EF48, + (SINT32)0x00415B75, + (SINT32)0x0034F8B6, + (SINT32)0x001D8FD2, + (SINT32)0xFFFA2413, + (SINT32)0xFFC9F10E, + (SINT32)0xFF8D6793, + + (SINT32)0x00B97348, /* 16 */ + (SINT32)0x01071B96, + (SINT32)0x0156B3CA, + (SINT32)0x01A1B38B, + (SINT32)0x01E0224C, + (SINT32)0x0209291F, + (SINT32)0x02138653, + (SINT32)0x01F5F424, + + (SINT32)0x01A7ECEF, /* 24 */ + (SINT32)0x01223EBA, + (SINT32)0x005FD0FF, + (SINT32)0xFF5EEB73, + (SINT32)0xFE20435D, + (SINT32)0xFCA86E7E, + (SINT32)0xFAFF95FC, + (SINT32)0xF9312891, + + (SINT32)0x08B4307A, /* 32 */ + (SINT32)0x0A9F3E9A, + (SINT32)0x0C7D59B6, + (SINT32)0x0E3BB16F, + (SINT32)0x0FC721F9, + (SINT32)0x110ECEF0, + (SINT32)0x120435FA, + (SINT32)0x129C226F, + + (SINT32)0x12CF6C75, /* 40 */ + (SINT32)0x129C226F, + (SINT32)0x120435FA, + (SINT32)0x110ECEF0, + (SINT32)0x0FC721F9, + (SINT32)0x0E3BB16F, + (SINT32)0x0C7D59B6, + (SINT32)0x0A9F3E9A, + + (SINT32)0xF74BCF86, /* 48 */ + (SINT32)0xF9312891, + (SINT32)0xFAFF95FC, + (SINT32)0xFCA86E7E, + (SINT32)0xFE20435D, + (SINT32)0xFF5EEB73, + (SINT32)0x005FD0FF, + (SINT32)0x01223EBA, + + (SINT32)0x01A7ECEF, /* 56 */ + (SINT32)0x01F5F424, + (SINT32)0x02138653, + (SINT32)0x0209291F, + (SINT32)0x01E0224C, + (SINT32)0x01A1B38B, + (SINT32)0x0156B3CA, + (SINT32)0x01071B96, + + (SINT32)0xFF468CB8, /* 64 */ + (SINT32)0xFF8D6793, + (SINT32)0xFFC9F10E, + (SINT32)0xFFFA2413, + (SINT32)0x001D8FD2, + (SINT32)0x0034F8B6, + (SINT32)0x00415B75, + (SINT32)0x0044EF48, + + (SINT32)0x0041EC6A, /* 72 */ + (SINT32)0x003A72E7, + (SINT32)0x003060F4, + (SINT32)0x00255A62, + (SINT32)0x001AFF89, + (SINT32)0x00122C7D, + (SINT32)0x000B3F71, + (SINT32)0x00052173 +}; + +#endif +#endif + diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_encoder.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_encoder.c new file mode 100755 index 0000000000..0811ed104d --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_encoder.c @@ -0,0 +1,402 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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. + * + ******************************************************************************/ + +/****************************************************************************** + * + * contains code for encoder flow and initalization of encoder + * + ******************************************************************************/ + +#include +#include "bt_target.h" +#include "sbc_encoder.h" +#include "sbc_enc_func_declare.h" + +SINT16 EncMaxShiftCounter; + +/************************************************************************************************* + * SBC encoder scramble 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] >> 5) + (p[index] << 3); + * p[index] = tmp; + * } + * } + * //else index is 0. The frame stays unaltered + * + */ + +#define SBC_PRTC_CRC_IDX 3 +#define SBC_PRTC_USE_MASK 0x64 +#define SBC_PRTC_SYNC_MASK 0x10 +#define SBC_PRTC_CIDX 0 +#define SBC_PRTC_LIDX 1 +typedef struct +{ + UINT8 use; + UINT8 idx; +} tSBC_FR_CB; + +typedef struct +{ + tSBC_FR_CB fr[2]; + UINT8 init; + UINT8 index; + UINT8 base; +} tSBC_PRTC_CB; +tSBC_PRTC_CB sbc_prtc_cb; + +#define SBC_PRTC_IDX(sc) (((sc) & 0x3) + (((sc) & 0x30) >> 2)) +#define SBC_PRTC_CHK_INIT(ar) {if(sbc_prtc_cb.init == 0){sbc_prtc_cb.init=1; ar[0] &= ~SBC_PRTC_SYNC_MASK;}} +#define SBC_PRTC_C2L() {p_last=&sbc_prtc_cb.fr[SBC_PRTC_LIDX]; p_cur=&sbc_prtc_cb.fr[SBC_PRTC_CIDX]; \ + p_last->idx = p_cur->idx; p_last->use = p_cur->use;} +#define SBC_PRTC_GETC(ar) {p_cur->use = ar[SBC_PRTC_CRC_IDX] & SBC_PRTC_USE_MASK; \ + p_cur->idx = SBC_PRTC_IDX(ar[SBC_PRTC_CRC_IDX]);} +#define SBC_PRTC_CHK_CRC(ar) {SBC_PRTC_C2L();SBC_PRTC_GETC(ar);sbc_prtc_cb.index = (p_cur->use)?SBC_PRTC_CIDX:SBC_PRTC_LIDX;} +#define SBC_PRTC_SCRMB(ar) {idx = sbc_prtc_cb.fr[sbc_prtc_cb.index].idx; \ + if(idx > 0){if((idx&1)&&(pstrEncParams->u16PacketLength > (sbc_prtc_cb.base+(idx<<1)))) {tmp2=idx<<1; tmp=ar[idx];ar[idx]=ar[tmp2];ar[tmp2]=tmp;} \ + else{tmp2=ar[idx]; tmp=(tmp2>>5)+(tmp2<<3);ar[idx]=(UINT8)tmp;}}} + +#if (SBC_JOINT_STE_INCLUDED == TRUE) +SINT32 s32LRDiff[SBC_MAX_NUM_OF_BLOCKS] = {0}; +SINT32 s32LRSum[SBC_MAX_NUM_OF_BLOCKS] = {0}; +#endif + +void SBC_Encoder(SBC_ENC_PARAMS *pstrEncParams) +{ + SINT32 s32Ch; /* counter for ch*/ + SINT32 s32Sb; /* counter for sub-band*/ + UINT32 u32Count, maxBit = 0; /* loop count*/ + SINT32 s32MaxValue; /* temp variable to store max value */ + + SINT16 *ps16ScfL; + SINT32 *SbBuffer; + SINT32 s32Blk; /* counter for block*/ + SINT32 s32NumOfBlocks = pstrEncParams->s16NumOfBlocks; +#if (SBC_JOINT_STE_INCLUDED == TRUE) + SINT32 s32MaxValue2; + UINT32 u32CountSum,u32CountDiff; + SINT32 *pSum, *pDiff; +#endif + UINT8 *pu8; + tSBC_FR_CB *p_cur, *p_last; + UINT32 idx, tmp, tmp2; + register SINT32 s32NumOfSubBands = pstrEncParams->s16NumOfSubBands; + + pstrEncParams->pu8NextPacket = pstrEncParams->pu8Packet; + +#if (SBC_NO_PCM_CPY_OPTION == TRUE) + pstrEncParams->ps16NextPcmBuffer = pstrEncParams->ps16PcmBuffer; +#else + pstrEncParams->ps16NextPcmBuffer = pstrEncParams->as16PcmBuffer; +#endif + do + { + /* SBC ananlysis filter*/ + if (s32NumOfSubBands == 4) + SbcAnalysisFilter4(pstrEncParams); + else + SbcAnalysisFilter8(pstrEncParams); + + /* compute the scale factor, and save the max */ + ps16ScfL = pstrEncParams->as16ScaleFactor; + s32Ch=pstrEncParams->s16NumOfChannels*s32NumOfSubBands; + + pstrEncParams->ps16NextPcmBuffer+=s32Ch*s32NumOfBlocks; /* in case of multible sbc frame to encode update the pcm pointer */ + + for (s32Sb=0; s32Sbs32SbBuffer+s32Sb; + s32MaxValue=0; + for (s32Blk=s32NumOfBlocks;s32Blk>0;s32Blk--) + { + if (s32MaxValue 0x800000) ? 9 : 0; + + for ( ; u32Count < 15; u32Count++) + { + if (s32MaxValue <= (SINT32)(0x8000 << u32Count)) + break; + } + *ps16ScfL++ = (SINT16)u32Count; + + if (u32Count > maxBit) + maxBit = u32Count; + } + /* In case of JS processing,check whether to use JS */ +#if (SBC_JOINT_STE_INCLUDED == TRUE) + if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) + { + /* Calculate sum and differance scale factors for making JS decision */ + ps16ScfL = pstrEncParams->as16ScaleFactor ; + /* calculate the scale factor of Joint stereo max sum and diff */ + for (s32Sb = 0; s32Sb < s32NumOfSubBands-1; s32Sb++) + { + SbBuffer=pstrEncParams->s32SbBuffer+s32Sb; + s32MaxValue2=0; + s32MaxValue=0; + pSum = s32LRSum; + pDiff = s32LRDiff; + for (s32Blk=0;s32Blk>1; + if (abs32(*pSum)>s32MaxValue) + s32MaxValue=abs32(*pSum); + pSum++; + *pDiff=(*SbBuffer-*(SbBuffer+s32NumOfSubBands))>>1; + if (abs32(*pDiff)>s32MaxValue2) + s32MaxValue2=abs32(*pDiff); + pDiff++; + SbBuffer+=s32Ch; + } + u32Count = (s32MaxValue > 0x800000) ? 9 : 0; + for ( ; u32Count < 15; u32Count++) + { + if (s32MaxValue <= (SINT32)(0x8000 << u32Count)) + break; + } + u32CountSum=u32Count; + u32Count = (s32MaxValue2 > 0x800000) ? 9 : 0; + for ( ; u32Count < 15; u32Count++) + { + if (s32MaxValue2 <= (SINT32)(0x8000 << u32Count)) + break; + } + u32CountDiff=u32Count; + if ( (*ps16ScfL + *(ps16ScfL+s32NumOfSubBands)) > (SINT16)(u32CountSum + u32CountDiff) ) + { + + if (u32CountSum > maxBit) + maxBit = u32CountSum; + + if (u32CountDiff > maxBit) + maxBit = u32CountDiff; + + *ps16ScfL = (SINT16)u32CountSum; + *(ps16ScfL+s32NumOfSubBands) = (SINT16)u32CountDiff; + + SbBuffer=pstrEncParams->s32SbBuffer+s32Sb; + pSum = s32LRSum; + pDiff = s32LRDiff; + + for (s32Blk = 0; s32Blk < s32NumOfBlocks; s32Blk++) + { + *SbBuffer = *pSum; + *(SbBuffer+s32NumOfSubBands) = *pDiff; + + SbBuffer += s32NumOfSubBands<<1; + pSum++; + pDiff++; + } + + pstrEncParams->as16Join[s32Sb] = 1; + } + else + { + pstrEncParams->as16Join[s32Sb] = 0; + } + ps16ScfL++; + } + pstrEncParams->as16Join[s32Sb] = 0; + } +#endif + + pstrEncParams->s16MaxBitNeed = (SINT16)maxBit; + + /* bit allocation */ + if ((pstrEncParams->s16ChannelMode == SBC_STEREO) || (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO)) + sbc_enc_bit_alloc_ste(pstrEncParams); + else + sbc_enc_bit_alloc_mono(pstrEncParams); + + /* save the beginning of the frame. pu8NextPacket is modified in EncPacking() */ + pu8 = pstrEncParams->pu8NextPacket; + /* Quantize the encoded audio */ + EncPacking(pstrEncParams); + + /* scramble the code */ + SBC_PRTC_CHK_INIT(pu8); + SBC_PRTC_CHK_CRC(pu8); +#if 0 + if(pstrEncParams->u16PacketLength > ((sbc_prtc_cb.fr[sbc_prtc_cb.index].idx * 2) + sbc_prtc_cb.base)) + printf("len: %d, idx: %d\n", pstrEncParams->u16PacketLength, sbc_prtc_cb.fr[sbc_prtc_cb.index].idx); + else + printf("len: %d, idx: %d!!!!\n", pstrEncParams->u16PacketLength, sbc_prtc_cb.fr[sbc_prtc_cb.index].idx); +#endif + SBC_PRTC_SCRMB((&pu8[sbc_prtc_cb.base])); + } + while(--(pstrEncParams->u8NumPacketToEncode)); + + pstrEncParams->u8NumPacketToEncode = 1; /* default is one for retrocompatibility purpose */ + +} + +/**************************************************************************** +* InitSbcAnalysisFilt - Initalizes the input data to 0 +* +* RETURNS : N/A +*/ +void SBC_Encoder_Init(SBC_ENC_PARAMS *pstrEncParams) +{ + UINT16 s16SamplingFreq; /*temp variable to store smpling freq*/ + SINT16 s16Bitpool; /*to store bit pool value*/ + SINT16 s16BitRate; /*to store bitrate*/ + SINT16 s16FrameLen; /*to store frame length*/ + UINT16 HeaderParams; + + pstrEncParams->u8NumPacketToEncode = 1; /* default is one for retrocompatibility purpose */ + + /* Required number of channels */ + if (pstrEncParams->s16ChannelMode == SBC_MONO) + pstrEncParams->s16NumOfChannels = 1; + else + pstrEncParams->s16NumOfChannels = 2; + + /* Bit pool calculation */ + if (pstrEncParams->s16SamplingFreq == SBC_sf16000) + s16SamplingFreq = 16000; + else if (pstrEncParams->s16SamplingFreq == SBC_sf32000) + s16SamplingFreq = 32000; + else if (pstrEncParams->s16SamplingFreq == SBC_sf44100) + s16SamplingFreq = 44100; + else + s16SamplingFreq = 48000; + + if ( (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) + || (pstrEncParams->s16ChannelMode == SBC_STEREO) ) + { + s16Bitpool = (SINT16)( (pstrEncParams->u16BitRate * + pstrEncParams->s16NumOfSubBands * 1000 / s16SamplingFreq) + -( (32 + (4 * pstrEncParams->s16NumOfSubBands * + pstrEncParams->s16NumOfChannels) + + ( (pstrEncParams->s16ChannelMode - 2) * + pstrEncParams->s16NumOfSubBands ) ) + / pstrEncParams->s16NumOfBlocks) ); + + s16FrameLen = 4 + (4*pstrEncParams->s16NumOfSubBands* + pstrEncParams->s16NumOfChannels)/8 + + ( ((pstrEncParams->s16ChannelMode - 2) * + pstrEncParams->s16NumOfSubBands) + + (pstrEncParams->s16NumOfBlocks * s16Bitpool) ) / 8; + + s16BitRate = (8 * s16FrameLen * s16SamplingFreq) + / (pstrEncParams->s16NumOfSubBands * + pstrEncParams->s16NumOfBlocks * 1000); + + if (s16BitRate > pstrEncParams->u16BitRate) + s16Bitpool--; + + if(pstrEncParams->s16NumOfSubBands == 8) + pstrEncParams->s16BitPool = (s16Bitpool > 255) ? 255 : s16Bitpool; + else + pstrEncParams->s16BitPool = (s16Bitpool > 128) ? 128 : s16Bitpool; + } + else + { + s16Bitpool = (SINT16)( ((pstrEncParams->s16NumOfSubBands * + pstrEncParams->u16BitRate * 1000) + / (s16SamplingFreq * pstrEncParams->s16NumOfChannels)) + -( ( (32 / pstrEncParams->s16NumOfChannels) + + (4 * pstrEncParams->s16NumOfSubBands) ) + / pstrEncParams->s16NumOfBlocks ) ); + + pstrEncParams->s16BitPool = (s16Bitpool > + (16 * pstrEncParams->s16NumOfSubBands)) + ? (16*pstrEncParams->s16NumOfSubBands) : s16Bitpool; + } + + if (pstrEncParams->s16BitPool < 0) + pstrEncParams->s16BitPool = 0; + /* sampling freq */ + HeaderParams = ((pstrEncParams->s16SamplingFreq & 3)<< 6); + + /* number of blocks*/ + HeaderParams |= (((pstrEncParams->s16NumOfBlocks -4) & 12) << 2); + + /* channel mode: mono, dual...*/ + HeaderParams |= ((pstrEncParams->s16ChannelMode & 3)<< 2); + + /* Loudness or SNR */ + HeaderParams |= ((pstrEncParams->s16AllocationMethod & 1)<< 1); + HeaderParams |= ((pstrEncParams->s16NumOfSubBands >> 3) & 1); /*4 or 8*/ + pstrEncParams->FrameHeader=HeaderParams; + + if (pstrEncParams->s16NumOfSubBands==4) + { + if (pstrEncParams->s16NumOfChannels==1) + EncMaxShiftCounter=((ENC_VX_BUFFER_SIZE-4*10)>>2)<<2; + else + EncMaxShiftCounter=((ENC_VX_BUFFER_SIZE-4*10*2)>>3)<<2; + } + else + { + if (pstrEncParams->s16NumOfChannels==1) + EncMaxShiftCounter=((ENC_VX_BUFFER_SIZE-8*10)>>3)<<3; + else + EncMaxShiftCounter=((ENC_VX_BUFFER_SIZE-8*10*2)>>4)<<3; + } + + APPL_TRACE_EVENT("SBC_Encoder_Init : bitrate %d, bitpool %d", + pstrEncParams->u16BitRate, pstrEncParams->s16BitPool); + + SbcAnalysisInit(); + + memset(&sbc_prtc_cb, 0, sizeof(tSBC_PRTC_CB)); + sbc_prtc_cb.base = 6 + pstrEncParams->s16NumOfChannels*pstrEncParams->s16NumOfSubBands/2; +} diff --git a/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_packing.c b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_packing.c new file mode 100755 index 0000000000..bdbefea537 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/embdrv/sbc/encoder/srce/sbc_packing.c @@ -0,0 +1,274 @@ +/****************************************************************************** + * + * Copyright (C) 1999-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 code for packing the Encoded data into bit streams. + * + ******************************************************************************/ + +#include "sbc_encoder.h" +#include "sbc_enc_func_declare.h" + +#if (SBC_ARM_ASM_OPT==TRUE) +#define Mult32(s32In1,s32In2,s32OutLow) \ +{ \ + __asm \ + { \ + MUL s32OutLow,s32In1,s32In2; \ + } \ +} +#define Mult64(s32In1, s32In2, s32OutLow, s32OutHi) \ +{ \ + __asm \ + { \ + SMULL s32OutLow,s32OutHi,s32In1,s32In2 \ + } \ +} +#else +#define Mult32(s32In1,s32In2,s32OutLow) s32OutLow=(SINT32)s32In1*(SINT32)s32In2; +#define Mult64(s32In1, s32In2, s32OutLow, s32OutHi) \ +{ \ + s32OutLow = ((SINT32)(UINT16)s32In1 * (UINT16)s32In2); \ + s32TempVal2 = (SINT32)((s32In1 >> 16) * (UINT16)s32In2); \ + s32Carry = ( (((UINT32)(s32OutLow)>>16)&0xFFFF) + \ + + (s32TempVal2 & 0xFFFF) ) >> 16; \ + s32OutLow += (s32TempVal2 << 16); \ + s32OutHi = (s32TempVal2 >> 16) + s32Carry; \ +} +#endif + +void EncPacking(SBC_ENC_PARAMS *pstrEncParams) +{ + UINT8 *pu8PacketPtr; /* packet ptr*/ + UINT8 Temp; + SINT32 s32Blk; /* counter for block*/ + SINT32 s32Ch; /* counter for channel*/ + SINT32 s32Sb; /* counter for sub-band*/ + SINT32 s32PresentBit; /* represents bit to be stored*/ + /*SINT32 s32LoopCountI; loop counter*/ + SINT32 s32LoopCountJ; /* loop counter*/ + UINT32 u32QuantizedSbValue,u32QuantizedSbValue0; /* temp variable to store quantized sb val*/ + SINT32 s32LoopCount; /* loop counter*/ + UINT8 u8XoredVal; /* to store XORed value in CRC calculation*/ + UINT8 u8CRC; /* to store CRC value*/ + SINT16 *ps16GenPtr; + SINT32 s32NumOfBlocks; + SINT32 s32NumOfSubBands = pstrEncParams->s16NumOfSubBands; + SINT32 s32NumOfChannels = pstrEncParams->s16NumOfChannels; + UINT32 u32SfRaisedToPow2; /*scale factor raised to power 2*/ + SINT16 *ps16ScfPtr; + SINT32 *ps32SbPtr; + UINT16 u16Levels; /*to store levels*/ + SINT32 s32Temp1; /*used in 64-bit multiplication*/ + SINT32 s32Low; /*used in 64-bit multiplication*/ +#if (SBC_IS_64_MULT_IN_QUANTIZER==TRUE) + SINT32 s32Hi1,s32Low1,s32Carry,s32TempVal2,s32Hi, s32Temp2; +#endif + + pu8PacketPtr = pstrEncParams->pu8NextPacket; /*Initialize the ptr*/ + *pu8PacketPtr++ = (UINT8)0x9C; /*Sync word*/ + *pu8PacketPtr++=(UINT8)(pstrEncParams->FrameHeader); + + *pu8PacketPtr = (UINT8)(pstrEncParams->s16BitPool & 0x00FF); + pu8PacketPtr += 2; /*skip for CRC*/ + + /*here it indicate if it is byte boundary or nibble boundary*/ + s32PresentBit = 8; + Temp=0; +#if (SBC_JOINT_STE_INCLUDED == TRUE) + if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) + { + /* pack join stero parameters */ + for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) + { + Temp <<= 1; + Temp |= pstrEncParams->as16Join[s32Sb]; + } + + /* pack RFA */ + if (s32NumOfSubBands == SUB_BANDS_4) + { + s32PresentBit = 4; + } + else + { + *(pu8PacketPtr++)=Temp; + Temp = 0; + } + } +#endif + + /* Pack Scale factor */ + ps16GenPtr = pstrEncParams->as16ScaleFactor; + s32Sb=s32NumOfChannels*s32NumOfSubBands; + /*Temp=*pu8PacketPtr;*/ + for (s32Ch = s32Sb; s32Ch >0; s32Ch--) + { + Temp<<= 4; + Temp |= *ps16GenPtr++; + + if(s32PresentBit == 4) + { + s32PresentBit = 8; + *(pu8PacketPtr++)=Temp; + Temp = 0; + } + else + { + s32PresentBit = 4; + } + } + + /* Pack samples */ + ps32SbPtr = pstrEncParams->s32SbBuffer; + /*Temp=*pu8PacketPtr;*/ + s32NumOfBlocks= pstrEncParams->s16NumOfBlocks; + for (s32Blk = s32NumOfBlocks-1; s32Blk >=0; s32Blk--) + { + ps16GenPtr = pstrEncParams->as16Bits; + ps16ScfPtr = pstrEncParams->as16ScaleFactor; + for (s32Ch = s32Sb-1; s32Ch >= 0; s32Ch--) + { + s32LoopCount = *ps16GenPtr++; + if (s32LoopCount != 0) + { +#if (SBC_IS_64_MULT_IN_QUANTIZER==TRUE) + /* finding level from reconstruction part of decoder */ + u32SfRaisedToPow2 = ((UINT32)1 << ((*ps16ScfPtr)+1)); + u16Levels = (UINT16)(((UINT32)1 << s32LoopCount) - 1); + + /* quantizer */ + s32Temp1 = (*ps32SbPtr >> 2) + (u32SfRaisedToPow2 << 12); + s32Temp2 = u16Levels; + + Mult64 (s32Temp1, s32Temp2, s32Low, s32Hi); + + s32Low1 = s32Low >> ((*ps16ScfPtr)+2); + s32Low1 &= ((UINT32)1 << (32 - ((*ps16ScfPtr)+2))) - 1; + s32Hi1 = s32Hi << (32 - ((*ps16ScfPtr) +2)); + + u32QuantizedSbValue0 = (UINT16)((s32Low1 | s32Hi1) >> 12); +#else + /* finding level from reconstruction part of decoder */ + u32SfRaisedToPow2 = ((UINT32)1 << *ps16ScfPtr); + u16Levels = (UINT16)(((UINT32)1 << s32LoopCount)-1); + + /* quantizer */ + s32Temp1 = (*ps32SbPtr >> 15) + u32SfRaisedToPow2; + Mult32(s32Temp1,u16Levels,s32Low); + s32Low>>= (*ps16ScfPtr+1); + u32QuantizedSbValue0 = (UINT16)s32Low; +#endif + /*store the number of bits required and the quantized s32Sb + sample to ease the coding*/ + u32QuantizedSbValue = u32QuantizedSbValue0; + + if(s32PresentBit >= s32LoopCount) + { + Temp <<= s32LoopCount; + Temp |= u32QuantizedSbValue; + s32PresentBit -= s32LoopCount; + } + else + { + while (s32PresentBit < s32LoopCount) + { + s32LoopCount -= s32PresentBit; + u32QuantizedSbValue >>= s32LoopCount; + + /*remove the unwanted msbs*/ + /*u32QuantizedSbValue <<= 16 - s32PresentBit; + u32QuantizedSbValue >>= 16 - s32PresentBit;*/ + + Temp <<= s32PresentBit; + + Temp |= u32QuantizedSbValue ; + /*restore the original*/ + u32QuantizedSbValue=u32QuantizedSbValue0; + + *(pu8PacketPtr++)=Temp; + Temp = 0; + s32PresentBit = 8; + } + Temp <<= s32LoopCount; + + /* remove the unwanted msbs */ + /*u32QuantizedSbValue <<= 16 - s32LoopCount; + u32QuantizedSbValue >>= 16 - s32LoopCount;*/ + + Temp |= u32QuantizedSbValue; + + s32PresentBit -= s32LoopCount; + } + } + ps16ScfPtr++; + ps32SbPtr++; + } + } + + Temp <<= s32PresentBit; + *pu8PacketPtr=Temp; + pstrEncParams->u16PacketLength=pu8PacketPtr-pstrEncParams->pu8NextPacket+1; + /*find CRC*/ + pu8PacketPtr = pstrEncParams->pu8NextPacket+1; /*Initialize the ptr*/ + u8CRC = 0x0F; + s32LoopCount = s32Sb >> 1; + + /* + The loops is run from the start of the packet till the scale factor + parameters. In case of JS, 'join' parameter is included in the packet + so that many more bytes are included in CRC calculation. + */ + Temp=*pu8PacketPtr; + for (s32Ch=1; s32Ch < (s32LoopCount+4); s32Ch++) + { + /* skip sync word and CRC bytes */ + if (s32Ch != 3) + { + for (s32LoopCountJ=7; s32LoopCountJ>=0; s32LoopCountJ--) + { + u8XoredVal = ((u8CRC >> 7) & 0x01) ^((Temp >> s32LoopCountJ) & 0x01); + u8CRC <<= 1; + u8CRC ^= (u8XoredVal * 0x1D); + u8CRC &= 0xFF; + } + } + Temp=*(++pu8PacketPtr); + } + + if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) + { + for (s32LoopCountJ = 7; s32LoopCountJ >= (8 - s32NumOfSubBands); s32LoopCountJ--) + { + u8XoredVal = ((u8CRC >> 7) & 0x01) ^((Temp >> s32LoopCountJ) & 0x01); + u8CRC <<= 1; + u8CRC ^= (u8XoredVal * 0x1D); + u8CRC &= 0xFF; + } + } + + /* CRC calculation ends here */ + + /* store CRC in packet */ + pu8PacketPtr = pstrEncParams->pu8NextPacket; /*Initialize the ptr*/ + pu8PacketPtr += 3; + *pu8PacketPtr = u8CRC; + pstrEncParams->pu8NextPacket+=pstrEncParams->u16PacketLength; /* move the pointer to the end in case there is more than one frame to encode */ +} + diff --git a/examples/09_a2dp/components/bluedroid_demos/include/bt_app_common.h b/examples/09_a2dp/components/bluedroid_demos/include/bt_app_common.h new file mode 100755 index 0000000000..501bfccc97 --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/include/bt_app_common.h @@ -0,0 +1,30 @@ +#ifndef __BT_APP_COMMON_H__ +#define __BT_APP_COMMON_H__ + +#include +#include "osi.h" +#include "bt_common_types.h" +#include "bt_defs.h" + +/* BT APP Events */ +#define BT_EVT_APP (0xB000) +#define BT_EVT_APP_CONTEXT_SWITCH (0x0001 | BT_EVT_APP) + +typedef void (tBTAPP_CBACK) (uint16_t event, char *p_param); +typedef void (tBTAPP_COPY_CBACK) (uint16_t event, char *p_dest, char *p_src); + +typedef struct +{ + BT_HDR hdr; + tBTAPP_CBACK* p_cb; /* context switch callback */ + + /* parameters passed to callback */ + UINT16 event; /* message event id */ + char p_param[0]; /* parameter area needs to be last */ +} tBTAPP_CONTEXT_SWITCH_CBACK; + +bt_status_t bt_app_transfer_context (tBTAPP_CBACK *p_cback, UINT16 event, char* p_params, int param_len, tBTAPP_COPY_CBACK *p_copy_cback); + +void bt_app_task_start_up(void); + +#endif /* __BT_APP_COMMON_H__ */ diff --git a/examples/09_a2dp/components/bluedroid_demos/include/bt_av.h b/examples/09_a2dp/components/bluedroid_demos/include/bt_av.h new file mode 100755 index 0000000000..5252a179bb --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/include/bt_av.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 ANDROID_INCLUDE_BT_AV_H +#define ANDROID_INCLUDE_BT_AV_H + +__BEGIN_DECLS + +/* Bluetooth AV connection states */ +typedef enum { + BTAV_CONNECTION_STATE_DISCONNECTED = 0, + BTAV_CONNECTION_STATE_CONNECTING, + BTAV_CONNECTION_STATE_CONNECTED, + BTAV_CONNECTION_STATE_DISCONNECTING +} btav_connection_state_t; + +/* Bluetooth AV datapath states */ +typedef enum { + BTAV_AUDIO_STATE_REMOTE_SUSPEND = 0, + BTAV_AUDIO_STATE_STOPPED, + BTAV_AUDIO_STATE_STARTED, +} btav_audio_state_t; + + +/** Callback for connection state change. + * state will have one of the values from btav_connection_state_t + */ +typedef void (* btav_connection_state_callback)(btav_connection_state_t state, + bt_bdaddr_t *bd_addr); + +/** Callback for audiopath state change. + * state will have one of the values from btav_audio_state_t + */ +typedef void (* btav_audio_state_callback)(btav_audio_state_t state, + bt_bdaddr_t *bd_addr); + +/** Callback for audio configuration change. + * Used only for the A2DP sink interface. + * state will have one of the values from btav_audio_state_t + * sample_rate: sample rate in Hz + * channel_count: number of channels (1 for mono, 2 for stereo) + */ +typedef void (* btav_audio_config_callback)(bt_bdaddr_t *bd_addr, + uint32_t sample_rate, + uint8_t channel_count); + +/** BT-AV callback structure. */ +typedef struct { + /** set to sizeof(btav_callbacks_t) */ + size_t size; + btav_connection_state_callback connection_state_cb; + btav_audio_state_callback audio_state_cb; + btav_audio_config_callback audio_config_cb; +} btav_callbacks_t; + +/** + * NOTE: + * + * 1. AVRCP 1.0 shall be supported initially. AVRCP passthrough commands + * shall be handled internally via uinput + * + * 2. A2DP data path shall be handled via a socket pipe between the AudioFlinger + * android_audio_hw library and the Bluetooth stack. + * + */ +/** Represents the standard BT-AV interface. + * Used for both the A2DP source and sink interfaces. + */ +typedef struct { + + /** set to sizeof(btav_interface_t) */ + size_t size; + /** + * Register the BtAv callbacks + */ + bt_status_t (*init)( btav_callbacks_t* callbacks ); + + /** connect to headset */ + bt_status_t (*connect)( bt_bdaddr_t *bd_addr ); + + /** dis-connect from headset */ + bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr ); + + /** Closes the interface. */ + void (*cleanup)( void ); +} btav_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_AV_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/udrv/include/uipc.h b/examples/09_a2dp/components/bluedroid_demos/udrv/include/uipc.h new file mode 100755 index 0000000000..9068c369df --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/udrv/include/uipc.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * Copyright (C) 2007-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 UIPC_H +#define UIPC_H + +#include "bt_types.h" + +#define UIPC_CH_ID_AV_CTRL 0 +#define UIPC_CH_ID_AV_AUDIO 1 +#define UIPC_CH_NUM 2 + +#define UIPC_CH_ID_ALL 3 /* used to address all the ch id at once */ + +#define DEFAULT_READ_POLL_TMO_MS 100 + +typedef UINT8 tUIPC_CH_ID; + +/* Events generated */ +typedef enum { + UIPC_OPEN_EVT = 0x0001, + UIPC_CLOSE_EVT = 0x0002, + UIPC_RX_DATA_EVT = 0x0004, + UIPC_RX_DATA_READY_EVT = 0x0008, + UIPC_TX_DATA_READY_EVT = 0x0010 +} tUIPC_EVENT; + +/* + * UIPC IOCTL Requests + */ + +#define UIPC_REQ_RX_FLUSH 1 +#define UIPC_REG_CBACK 2 +#define UIPC_REG_REMOVE_ACTIVE_READSET 3 +#define UIPC_SET_READ_POLL_TMO 4 + +typedef void (tUIPC_RCV_CBACK)(tUIPC_CH_ID ch_id, tUIPC_EVENT event); /* points to BT_HDR which describes event type and length of data; len contains the number of bytes of entire message (sizeof(BT_HDR) + offset + size of data) */ + +const char* dump_uipc_event(tUIPC_EVENT event); + +/******************************************************************************* +** +** Function UIPC_Init +** +** Description Initialize UIPC module +** +** Returns void +** +*******************************************************************************/ +void UIPC_Init(void *); + +/******************************************************************************* +** +** Function UIPC_Open +** +** Description Open UIPC interface +** +** Returns void +** +*******************************************************************************/ +BOOLEAN UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK *p_cback); + +/******************************************************************************* +** +** Function UIPC_Close +** +** Description Close UIPC interface +** +** Returns void +** +*******************************************************************************/ +void UIPC_Close(tUIPC_CH_ID ch_id); + +/******************************************************************************* +** +** Function UIPC_SendBuf +** +** Description Called to transmit a message over UIPC. +** Message buffer will be freed by UIPC_SendBuf. +** +** Returns void +** +*******************************************************************************/ +BOOLEAN UIPC_SendBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg); + +/******************************************************************************* +** +** Function UIPC_Send +** +** Description Called to transmit a message over UIPC. +** +** Returns void +** +*******************************************************************************/ +BOOLEAN UIPC_Send(tUIPC_CH_ID ch_id, UINT16 msg_evt, UINT8 *p_buf, UINT16 msglen); + +/******************************************************************************* +** +** Function UIPC_Read +** +** Description Called to read a message from UIPC. +** +** Returns void +** +*******************************************************************************/ +UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf, UINT32 len); + +/******************************************************************************* +** +** Function UIPC_Ioctl +** +** Description Called to control UIPC. +** +** Returns void +** +*******************************************************************************/ +BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *param); + +#endif /* UIPC_H */ diff --git a/examples/09_a2dp/components/bluedroid_demos/udrv/ulinux/uipc.c b/examples/09_a2dp/components/bluedroid_demos/udrv/ulinux/uipc.c new file mode 100755 index 0000000000..cb0c14c45d --- /dev/null +++ b/examples/09_a2dp/components/bluedroid_demos/udrv/ulinux/uipc.c @@ -0,0 +1,139 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +/***************************************************************************** + * + * Filename: uipc.c + * + * Description: UIPC implementation for bluedroid + * + *****************************************************************************/ +#include +#include "uipc.h" + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ + + + +const char* dump_uipc_event(tUIPC_EVENT event) +{ + return NULL; +} + +/******************************************************************************* +** +** Function UIPC_Init +** +** Description Initialize UIPC module +** +** Returns void +** +*******************************************************************************/ +void UIPC_Init(void *dummy) +{ + return; +} + +/******************************************************************************* +** +** Function UIPC_Open +** +** Description Open UIPC interface +** +** Returns void +** +*******************************************************************************/ +BOOLEAN UIPC_Open(tUIPC_CH_ID ch_id, tUIPC_RCV_CBACK *p_cback) +{ + return TRUE; +} + +/******************************************************************************* +** +** Function UIPC_Close +** +** Description Close UIPC interface +** +** Returns void +** +*******************************************************************************/ +void UIPC_Close(tUIPC_CH_ID ch_id) +{ + return; +} + +/******************************************************************************* +** +** Function UIPC_SendBuf +** +** Description Called to transmit a message over UIPC. +** Message buffer will be freed by UIPC_SendBuf. +** +** Returns void +** +*******************************************************************************/ +BOOLEAN UIPC_SendBuf(tUIPC_CH_ID ch_id, BT_HDR *p_msg) +{ + return TRUE; +} + +/******************************************************************************* +** +** Function UIPC_Send +** +** Description Called to transmit a message over UIPC. +** +** Returns void +** +*******************************************************************************/ +BOOLEAN UIPC_Send(tUIPC_CH_ID ch_id, UINT16 msg_evt, UINT8 *p_buf, UINT16 msglen) +{ + return TRUE; +} + +/******************************************************************************* +** +** Function UIPC_Read +** +** Description Called to read a message from UIPC. +** +** Returns void +** +*******************************************************************************/ +UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf, UINT32 len) +{ + return 0; +} + + +/******************************************************************************* +** +** Function UIPC_Ioctl +** +** Description Called to control UIPC. +** +** Returns void +** +*******************************************************************************/ +BOOLEAN UIPC_Ioctl(tUIPC_CH_ID ch_id, UINT32 request, void *param) +{ + return TRUE; +} + diff --git a/examples/09_a2dp/main/component.mk b/examples/09_a2dp/main/component.mk new file mode 100755 index 0000000000..24356f23ed --- /dev/null +++ b/examples/09_a2dp/main/component.mk @@ -0,0 +1,10 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# +# This Makefile should, at the very least, just include $(SDK_PATH)/make/component_common.mk. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +include $(IDF_PATH)/make/component_common.mk diff --git a/examples/09_a2dp/main/demo_main.c b/examples/09_a2dp/main/demo_main.c new file mode 100755 index 0000000000..ad8243a1fc --- /dev/null +++ b/examples/09_a2dp/main/demo_main.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include "bt.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "string.h" + + +extern void bte_main_boot_entry(void *); +extern void bt_app_task_start_up(void); +extern void bt_app_core_start(void); + +void pingTask(void *pvParameters) +{ + while (1) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + printf("ping\n"); + } +} + +void app_main() +{ + bt_controller_init(); + xTaskCreatePinnedToCore(&pingTask, "pingTask", 2048, NULL, 5, NULL, 0); + bt_app_task_start_up(); + // bte_main_boot_entry(bt_app_core_start); +} -- 2.40.0