rtkbt:rtk bt update to 20190520
authorLongjian Lin <llj@rock-chips.com>
Tue, 9 Jul 2019 03:15:37 +0000 (23:15 -0400)
committerLongjian Lin <llj@rock-chips.com>
Tue, 9 Jul 2019 03:15:37 +0000 (23:15 -0400)
Change-Id: Id5995d2fab680260fe833aca5f357fe5f2064ce6

117 files changed:
rtkbt/code/libbt-vendor/Android.mk
rtkbt/code/libbt-vendor/codec/Android.mk [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/msbc/sbc.c [deleted file]
rtkbt/code/libbt-vendor/codec/msbc/sbc.h [deleted file]
rtkbt/code/libbt-vendor/codec/msbc/sbc_math.h [deleted file]
rtkbt/code/libbt-vendor/codec/msbc/sbc_tables.h [deleted file]
rtkbt/code/libbt-vendor/codec/sbc/formats.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_math.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_armv6.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_armv6.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_iwmmxt.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_iwmmxt.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_mmx.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_mmx.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_neon.c [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_neon.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_private.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/codec/sbc/sbc_tables.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/include/bt_list.h
rtkbt/code/libbt-vendor/include/bt_skbuff.h
rtkbt/code/libbt-vendor/include/bt_vendor_rtk.h
rtkbt/code/libbt-vendor/include/hardware.h
rtkbt/code/libbt-vendor/include/hci_h5_int.h
rtkbt/code/libbt-vendor/include/rtk_btservice.h
rtkbt/code/libbt-vendor/include/rtk_btsnoop_net.h
rtkbt/code/libbt-vendor/include/rtk_common.h [new file with mode: 0755]
rtkbt/code/libbt-vendor/include/rtk_hcidefs.h
rtkbt/code/libbt-vendor/include/rtk_parse.h
rtkbt/code/libbt-vendor/include/rtk_poll.h
rtkbt/code/libbt-vendor/include/rtk_socket.h
rtkbt/code/libbt-vendor/include/unused.h
rtkbt/code/libbt-vendor/include/upio.h
rtkbt/code/libbt-vendor/include/userial_vendor.h
rtkbt/code/libbt-vendor/src/Android.mk [new file with mode: 0755]
rtkbt/code/libbt-vendor/src/bt_list.c
rtkbt/code/libbt-vendor/src/bt_skbuff.c
rtkbt/code/libbt-vendor/src/bt_vendor_rtk.c
rtkbt/code/libbt-vendor/src/hardware.c
rtkbt/code/libbt-vendor/src/hardware_uart.c
rtkbt/code/libbt-vendor/src/hardware_usb.c
rtkbt/code/libbt-vendor/src/hci_h5.c
rtkbt/code/libbt-vendor/src/rtk_btservice.c
rtkbt/code/libbt-vendor/src/rtk_btsnoop_net.c
rtkbt/code/libbt-vendor/src/rtk_heartbeat.c
rtkbt/code/libbt-vendor/src/rtk_parse.c
rtkbt/code/libbt-vendor/src/rtk_poll.c
rtkbt/code/libbt-vendor/src/rtk_socket.c
rtkbt/code/libbt-vendor/src/upio.c
rtkbt/code/libbt-vendor/src/userial_vendor.c
rtkbt/vendor/firmware/BT_Firmware.mk [changed mode: 0644->0755]
rtkbt/vendor/firmware/fw_info.txt [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8703as_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8703as_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8703bs_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8703bs_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8703cs_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8703cs_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723a_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723a_config_addr [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723a_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723as_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723as_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723b_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723b_config_2Ant_S0 [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723b_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723bs_VQ0_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723bs_VQ0_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723bs_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723bs_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723bu_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723c_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723cs_cg_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723cs_cg_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723cs_vf_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723cs_vf_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723cs_xx_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723cs_xx_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723d_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723d_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723ds_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8723ds_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8725a_config [new file with mode: 0755]
rtkbt/vendor/firmware/rtl8725a_fw [new file with mode: 0755]
rtkbt/vendor/firmware/rtl8761a_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761at8192ee_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761at8812ae_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761at_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761at_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761au8192ee_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761au8812ae_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761au_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761aw8192eu_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761aw8192eu_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8761b_config [new file with mode: 0755]
rtkbt/vendor/firmware/rtl8761b_fw [new file with mode: 0755]
rtkbt/vendor/firmware/rtl8761bt_config [new file with mode: 0755]
rtkbt/vendor/firmware/rtl8761bt_fw [new file with mode: 0755]
rtkbt/vendor/firmware/rtl8821a_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8821a_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8821as_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8821as_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8821c_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8821c_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8821cs_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8821cs_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8822b_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8822b_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8822bs_config [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8822bs_fw [changed mode: 0644->0755]
rtkbt/vendor/firmware/rtl8822c_config [new file with mode: 0755]
rtkbt/vendor/firmware/rtl8822c_fw [new file with mode: 0755]
rtkbt/vendor/firmware/rtl8822cs_config [new file with mode: 0755]
rtkbt/vendor/firmware/rtl8822cs_fw [new file with mode: 0755]

index ea5fdb6e3f38b7d0852f2fe9e07871a4f7318c5b..5053e7d64389d3eaa35c6e807277fff9f83898f6 100755 (executable)
@@ -1,40 +1 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-BDROID_DIR := $(TOP_DIR)system/bt
-
-LOCAL_SRC_FILES := \
-        codec/msbc/sbc.c \
-        src/rtk_socket.c \
-        src/bt_vendor_rtk.c \
-        src/hardware.c \
-        src/userial_vendor.c \
-        src/upio.c \
-        src/bt_list.c \
-        src/bt_skbuff.c \
-        src/hci_h5.c \
-        src/rtk_parse.c \
-        src/rtk_btservice.c \
-        src/hardware_uart.c \
-        src/hardware_usb.c \
-        src/rtk_heartbeat.c \
-        src/rtk_poll.c \
-        src/rtk_btsnoop_net.c
-
-LOCAL_C_INCLUDES += \
-        $(LOCAL_PATH)/include \
-        $(LOCAL_PATH)/codec/msbc \
-        $(BDROID_DIR)/hci/include
-
-LOCAL_SHARED_LIBRARIES := \
-        libcutils \
-        liblog  \
-        libutils
-
-LOCAL_MODULE := libbt-vendor-realtek
-LOCAL_MODULE_TAGS := optional
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-
-include $(BUILD_SHARED_LIBRARY)
+include $(call all-subdir-makefiles)
diff --git a/rtkbt/code/libbt-vendor/codec/Android.mk b/rtkbt/code/libbt-vendor/codec/Android.mk
new file mode 100755 (executable)
index 0000000..7e72ef6
--- /dev/null
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+
+# libbt-codec.a
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+        ./sbc/sbc.c \
+        ./sbc/sbc_primitives.c \
+        ./sbc/sbc_primitives_mmx.c \
+        ./sbc/sbc_primitives_neon.c
+
+LOCAL_C_INCLUDES :=
+LOCAL_CFLAGS := \
+        -Wno-error=unused-parameter \
+        -Wno-ignored-attributes
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_SHARED_LIBRARIES := libcutils libc
+LOCAL_MODULE := libbt-codec
+#LOCAL_MULTILIB := 32
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/rtkbt/code/libbt-vendor/codec/msbc/sbc.c b/rtkbt/code/libbt-vendor/codec/msbc/sbc.c
deleted file mode 100755 (executable)
index e138e9d..0000000
+++ /dev/null
@@ -1,1763 +0,0 @@
-/*
- *
- *  Bluetooth low-complexity, subband codec (SBC) library
- *
- *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
- *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
- *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-/* todo items:
-
-  use a log2 table for byte integer scale factors calculation (sum log2 results for high and low bytes)
-  fill bitpool by 16 bits instead of one at a time in bits allocation/bitpool generation
-  port to the dsp
-  don't consume more bytes than passed into the encoder
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-//#include <stdint.h>
-#include <malloc.h>
-#include <string.h>
-//#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-
-#include "sbc.h"
-#include "sbc_math.h"
-#include "sbc_tables.h"
-#include "cutils/log.h"
-
-
-#define SBC_SYNCWORD    0xAD
-#define SBC_POOLTAG     'CBSR'
-
-/* sampling frequency */
-#define SBC_FS_16   0x00
-#define SBC_FS_32   0x01
-#define SBC_FS_44   0x02
-#define SBC_FS_48   0x03
-
-/* nrof_blocks */
-#define SBC_NB_4    0x00
-#define SBC_NB_8    0x01
-#define SBC_NB_12   0x02
-#define SBC_NB_16   0x03
-
-/* channel mode */
-#define SBC_CM_MONO     0x00
-#define SBC_CM_DUAL_CHANNEL 0x01
-#define SBC_CM_STEREO       0x02
-#define SBC_CM_JOINT_STEREO 0x03
-
-/* allocation mode */
-#define SBC_AM_LOUDNESS     0x00
-#define SBC_AM_SNR      0x01
-
-/* subbands */
-#define SBC_SB_4    0x00
-#define SBC_SB_8    0x01
-
-#define SBC_ALIGN_BITS 4
-#define SBC_ALIGN_MASK ((1 << (SBC_ALIGN_BITS)) - 1)
-
-
-typedef unsigned short  uint16_t;
-typedef unsigned char uint8_t;
-typedef short int16_t;
-typedef unsigned int  u_int32_t;
-
-#ifndef UINT
-typedef unsigned int   UINT;
-#endif
-
-
-#if defined(WIN32) && !defined(__cplusplus)
-
-#define inline __inline
-
-#endif
-
-typedef long long sbc_extended_t;
-/*
-static __inline  void sbc_synthesize_four(struct sbc_decoder_state *state,
-        struct sbc_frame *frame, int ch, int blk);
-*/
-
-
-/* This structure contains an unpacked SBC frame.
-   Yes, there is probably quite some unused space herein */
-struct sbc_frame
-{
-    uint16_t sampling_frequency;    /* in kHz */
-    unsigned char blocks;
-    enum {
-        MONO        = SBC_CM_MONO,
-        DUAL_CHANNEL    = SBC_CM_DUAL_CHANNEL,
-        STEREO      = SBC_CM_STEREO,
-        JOINT_STEREO    = SBC_CM_JOINT_STEREO
-    } channel_mode;
-    uint8_t channels;
-    enum {
-        LOUDNESS    = SBC_AM_LOUDNESS,
-        SNR     = SBC_AM_SNR
-    } allocation_method;
-    uint8_t subbands;
-    uint8_t bitpool;
-    uint8_t join;               /* bit number x set means joint stereo has been used in subband x */
-    int scale_factor[2][8];     /* only the lower 4 bits of every element are to be used */
-    uint16_t audio_sample[16][2][8];    /* raw integer subband samples in the frame */
-
-    int sb_sample_f[16][2][8];
-    int sb_sample[16][2][8];        /* modified subband samples */
-    short pcm_sample[2][16*8];      /* original pcm audio samples */
-};
-
-struct sbc_decoder_state {
-    int subbands;
-    long long V[2][170];
-    int offset[2][16];
-};
-
-struct sbc_encoder_state {
-    int subbands;
-    int32_t X[2][80];
-};
-
-/*
- * Calculates the CRC-8 of the first len bits in data
- */
-static const uint8_t crc_table[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
-};
-
-static uint8_t sbc_crc8(const uint8_t * data, size_t len)
-{
-    uint8_t crc = 0x0f;
-    size_t i;
-    uint8_t octet;
-
-    for (i = 0; i < len / 8; i++)
-        crc = crc_table[crc ^ data[i]];
-
-    octet = data[i];
-    for (i = 0; i < len % 8; i++)
-    {
-        char bit = ((octet ^ crc) & 0x80) >> 7;
-
-        crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0);
-
-        octet = octet << 1;
-    }
-
-    return crc;
-}
-
-/*
- * Code straight from the spec to calculate the bits array
- * Takes a pointer to the frame in question, a pointer to the bits array and the sampling frequency (as 2 bit integer)
- */
-static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], uint8_t sf)
-{
-    if (frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL)
-    {
-        int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice;
-        int ch, sb;
-
-        for (ch = 0; ch < frame->channels; ch++)
-        {
-            if (frame->allocation_method == SNR)
-            {
-                for (sb = 0; sb < frame->subbands; sb++)
-                {
-                    bitneed[ch][sb] = frame->scale_factor[ch][sb];
-                }
-            }
-
-            else
-            {
-                for (sb = 0; sb < frame->subbands; sb++)
-                {
-                    if (frame->scale_factor[ch][sb] == 0)
-                    {
-                        bitneed[ch][sb] = -5;
-                    }
-                    else
-                    {
-                        if (frame->subbands == 4)
-                        {
-                            loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
-                        }
-
-                        else
-                        {
-                            loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
-                        }
-
-                        if (loudness > 0)
-                        {
-                            bitneed[ch][sb] = loudness / 2;
-                        }
-
-                        else
-                        {
-                            bitneed[ch][sb] = loudness;
-                        }
-                    }
-                }
-            }
-
-            max_bitneed = 0;
-            for (sb = 0; sb < frame->subbands; sb++)
-            {
-                if (bitneed[ch][sb] > max_bitneed)
-                    max_bitneed = bitneed[ch][sb];
-            }
-
-            bitcount = 0;
-            slicecount = 0;
-            bitslice = max_bitneed + 1;
-            do
-            {
-                bitslice--;
-                bitcount += slicecount;
-                slicecount = 0;
-                for (sb = 0; sb < frame->subbands; sb++)
-                {
-                    if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
-                    {
-                        slicecount++;
-                    }
-
-                    else if (bitneed[ch][sb] == bitslice + 1)
-                    {
-                        slicecount += 2;
-                    }
-                }
-            } while (bitcount + slicecount < frame->bitpool);
-
-            if (bitcount + slicecount == frame->bitpool)
-            {
-                bitcount += slicecount;
-                bitslice--;
-            }
-
-            for (sb = 0; sb < frame->subbands; sb++)
-            {
-                if (bitneed[ch][sb] < bitslice + 2)
-                {
-                    bits[ch][sb] = 0;
-                }
-
-                else
-                {
-                    bits[ch][sb] = bitneed[ch][sb] - bitslice;
-                    if (bits[ch][sb] > 16)
-                        bits[ch][sb] = 16;
-                }
-            }
-
-            sb = 0;
-            while (bitcount < frame->bitpool && sb < frame->subbands)
-            {
-                if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16))
-                {
-                    bits[ch][sb]++;
-                    bitcount++;
-                }
-
-                else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1))
-                {
-                    bits[ch][sb] = 2;
-                    bitcount += 2;
-                }
-                sb++;
-            }
-
-            sb = 0;
-            while (bitcount < frame->bitpool && sb < frame->subbands)
-            {
-                if (bits[ch][sb] < 16)
-                {
-                    bits[ch][sb]++;
-                    bitcount++;
-                }
-                sb++;
-            }
-
-        }
-
-    }
-
-    else if (frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO)
-    {
-        int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice;
-        int ch, sb;
-
-        if (frame->allocation_method == SNR)
-        {
-            for (ch = 0; ch < 2; ch++) {
-                for (sb = 0; sb < frame->subbands; sb++)
-                {
-                    bitneed[ch][sb] = frame->scale_factor[ch][sb];
-                }
-            }
-        }
-
-        else
-        {
-            for (ch = 0; ch < 2; ch++)
-            {
-                for (sb = 0; sb < frame->subbands; sb++)
-                {
-                    if (frame->scale_factor[ch][sb] == 0)
-                    {
-                        bitneed[ch][sb] = -5;
-                    }
-
-                    else
-                    {
-                        if (frame->subbands == 4)
-                        {
-                            loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
-                        }
-
-                        else
-                        {
-                            loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
-                        }
-
-                        if (loudness > 0)
-                        {
-                            bitneed[ch][sb] = loudness / 2;
-                        }
-
-                        else
-                        {
-                            bitneed[ch][sb] = loudness;
-                        }
-                    }
-                }
-            }
-        }
-
-        max_bitneed = 0;
-        for (ch = 0; ch < 2; ch++)
-        {
-            for (sb = 0; sb < frame->subbands; sb++)
-            {
-                if (bitneed[ch][sb] > max_bitneed)
-                    max_bitneed = bitneed[ch][sb];
-            }
-        }
-
-        bitcount = 0;
-        slicecount = 0;
-        bitslice = max_bitneed + 1;
-        do {
-            bitslice--;
-            bitcount += slicecount;
-            slicecount = 0;
-            for (ch = 0; ch < 2; ch++)
-            {
-                for (sb = 0; sb < frame->subbands; sb++)
-                {
-                    if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
-                    {
-                        slicecount++;
-                    }
-
-                    else if (bitneed[ch][sb] == bitslice + 1)
-                    {
-                        slicecount += 2;
-                    }
-                }
-            }
-        } while (bitcount + slicecount < frame->bitpool);
-
-        if (bitcount + slicecount == frame->bitpool)
-        {
-            bitcount += slicecount;
-            bitslice--;
-        }
-
-        for (ch = 0; ch < 2; ch++)
-        {
-            for (sb = 0; sb < frame->subbands; sb++)
-            {
-                if (bitneed[ch][sb] < bitslice + 2)
-                {
-                    bits[ch][sb] = 0;
-                }
-
-                else
-                {
-                    bits[ch][sb] = bitneed[ch][sb] - bitslice;
-                    if (bits[ch][sb] > 16)
-                        bits[ch][sb] = 16;
-                }
-            }
-        }
-
-        ch = 0;
-        sb = 0;
-        while ((bitcount < frame->bitpool) && (sb < frame->subbands))
-        {
-            if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16))
-            {
-                bits[ch][sb]++;
-                bitcount++;
-            }
-
-            else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1))
-            {
-                bits[ch][sb] = 2;
-                bitcount += 2;
-            }
-            if (ch == 1)
-            {
-                ch = 0;
-                sb++;
-            }
-            else
-            {
-                ch = 1;
-            }
-        }
-
-        ch = 0;
-        sb = 0;
-        while ((bitcount < frame->bitpool) && (sb < frame->subbands))
-        {
-            if (bits[ch][sb] < 16)
-            {
-                bits[ch][sb]++;
-                bitcount++;
-            }
-            if (ch == 1)
-            {
-                ch = 0;
-                sb++;
-            }
-
-            else
-            {
-                ch = 1;
-            }
-        }
-
-    }
-}
-
-/*
- * Unpacks a SBC frame at the beginning of the stream in data,
- * which has at most len bytes into frame.
- * Returns the length in bytes of the packed frame, or a negative
- * value on error. The error codes are:
- *
- *  -1   Data stream too short
- *  -2   Sync byte incorrect
- *  -3   CRC8 incorrect
- *  -4   Bitpool value out of bounds
- */
-static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_t len)
-{
-    UINT consumed;
-    /* Will copy the parts of the header that are relevant to crc calculation here */
-    uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-    int crc_pos = 0;
-    int32_t temp;
-
-    uint8_t sf;     /* sampling_frequency, temporarily needed as array index */
-
-//  int audio_sample;
-    int ch, sb, blk, bit;   /* channel, subband, block and bit standard counters */
-    int bits[2][8];     /* bits distribution */
-    int levels[2][8];   /* levels derived from that */
-
-    if (len < 4)
-    {
-        //DbgPrint("Exit when len < 4\n");
-        return -1;
-    }
-
-    if (data[0] != SBC_SYNCWORD)
-    {
-        //DbgPrint("Exit when data[0] != SBC_SYNCWORD\n");
-        return -2;
-    }
-
-#if 0
-    sf = (data[1] >> 6) & 0x03;
-    switch (sf) {
-    case SBC_FS_16:
-        frame->sampling_frequency = 16000;
-        break;
-    case SBC_FS_32:
-        frame->sampling_frequency = 32000;
-        break;
-    case SBC_FS_44:
-        frame->sampling_frequency = 44100;
-        break;
-    case SBC_FS_48:
-        frame->sampling_frequency = 48000;
-        break;
-    }
-
-    switch ((data[1] >> 4) & 0x03) {
-    case SBC_NB_4:
-        frame->blocks = 4;
-        break;
-    case SBC_NB_8:
-        frame->blocks = 8;
-        break;
-    case SBC_NB_12:
-        frame->blocks = 12;
-        break;
-    case SBC_NB_16:
-        frame->blocks = 16;
-        break;
-    }
-
-    frame->channel_mode = (data[1] >> 2) & 0x03;
-    switch (frame->channel_mode) {
-    case MONO:
-        frame->channels = 1;
-        break;
-    case DUAL_CHANNEL:  /* fall-through */
-    case STEREO:
-    case JOINT_STEREO:
-        frame->channels = 2;
-        break;
-    }
-
-    frame->allocation_method = (data[1] >> 1) & 0x01;
-    frame->subbands = (data[1] & 0x01) ? 8 : 4;
-    frame->bitpool = data[2];
-#endif
-
-    frame->sampling_frequency = 16000;
-    frame->blocks = 15;
-    frame->channel_mode = MONO;
-    frame->channels = 1;
-    frame->allocation_method  = SBC_AM_LOUDNESS;
-    frame->subbands = 8;
-    frame->bitpool = 26;
-
-
-    if (((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL)
-         && frame->bitpool > 16 * frame->subbands)
-        || ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO)
-        && frame->bitpool > 32 * frame->subbands))
-    {
-        //DbgPrint("Exit when frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&"
-        //  "frame->bitpool > 16 * frame->subbands\n");
-        return -4;
-    }
-
-    /* data[3] is crc, we're checking it later */
-    consumed = 32;
-#if 1
-    crc_header[0] = data[1];
-    crc_header[1] = data[2];
-#endif
-
-#if 0
-    crc_header[0] = 0x31;
-    crc_header[1] = 0x1a;
-#endif
-
-    crc_pos = 16;
-
-    if (frame->channel_mode == JOINT_STEREO)
-    {
-        if (len * 8 < consumed + frame->subbands)
-            return -1;
-
-        frame->join = 0x00;
-        for (sb = 0; sb < frame->subbands - 1; sb++) {
-            frame->join |= ((data[4] >> (7 - sb)) & 0x01) << sb;
-        }
-        if (frame->subbands == 4) {
-            crc_header[crc_pos / 8] = data[4] & 0xf0;
-        } else {
-            crc_header[crc_pos / 8] = data[4];
-        }
-
-        consumed += frame->subbands;
-        crc_pos += frame->subbands;
-    }
-
-    if (len * 8 < consumed + (4 * frame->subbands * frame->channels))
-    {
-        //DbgPrint("len * 8 < consumed + (4 * frame->subbands * frame->channels\n");
-        return -1;
-    }
-
-    for (ch = 0; ch < frame->channels; ch++)
-    {
-        for (sb = 0; sb < frame->subbands; sb++)
-        {
-            /* FIXME assert(consumed % 4 == 0); */
-            frame->scale_factor[ch][sb] = (data[consumed >> 3] >> (4 - (consumed & 0x7))) & 0x0F;
-            crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] << (4 - (crc_pos & 0x7));
-
-            consumed += 4;
-            crc_pos += 4;
-        }
-    }
-
-    if (data[3] != sbc_crc8(crc_header, crc_pos))
-    {
-        ALOGD("sbc_crc %02x -> %02x\n",data[3],sbc_crc8(crc_header, crc_pos));
-        return -3;
-    }
-
-    sf = SBC_FS_16;
-    sbc_calculate_bits(frame, bits, sf);
-
-    for (ch = 0; ch < frame->channels; ch++)
-    {
-        for (sb = 0; sb < frame->subbands; sb++)
-        {
-            levels[ch][sb] = (1 << bits[ch][sb]) - 1;
-        }
-    }
-#if 0
-    for (blk = 0; blk < frame->blocks; blk++)
-    {
-        for (ch = 0; ch < frame->channels; ch++)
-        {
-            for (sb = 0; sb < frame->subbands; sb++)
-            {
-                if (levels[ch][sb] > 0)
-                {
-                    audio_sample = 0;
-                    for (bit = 0; bit < bits[ch][sb]; bit++)
-                    {
-                        if (consumed > len * 8)
-                        {
-                            LogEvent("Exit when consumed > len * 8\n");
-                            return -1;
-                        }
-
-                        if ((data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01)
-                            audio_sample |= 1 << (bits[ch][sb] - bit - 1);
-
-                        consumed++;
-                    }
-
-                    frame->sb_sample[blk][ch][sb] =
-                        (((audio_sample << 1) | 1) << frame->scale_factor[ch][sb]) /
-                        levels[ch][sb] - (1 << frame->scale_factor[ch][sb]);
-                }
-
-                else
-                    frame->sb_sample[blk][ch][sb] = 0;
-            }
-        }
-    }
-#endif
-
-#if 1
-
-    for (blk = 0; blk < frame->blocks; blk++)
-    {
-        for (ch = 0; ch < frame->channels; ch++)
-        {
-            for (sb = 0; sb < frame->subbands; sb++)
-            {
-                frame->audio_sample[blk][ch][sb] = 0;
-                if (bits[ch][sb] == 0)
-                    continue;
-
-                for (bit = 0; bit < bits[ch][sb]; bit++)
-                {
-                    int b;  /* A bit */
-                    if (consumed > len * 8)
-                        return -1;
-
-                    b = (data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01;
-                    frame->audio_sample[blk][ch][sb] |= b << (bits[ch][sb] - bit - 1);
-
-                    consumed++;
-                }
-            }
-        }
-    }
-
-    for (blk = 0; blk < frame->blocks; blk++)
-    {
-        for (ch = 0; ch < frame->channels; ch++)
-        {
-            for (sb = 0; sb < frame->subbands; sb++)
-            {
-                if (levels[ch][sb] > 0)
-                {
-                    frame->sb_sample[blk][ch][sb] =
-                        (((frame->audio_sample[blk][ch][sb] << 16) | 0x8000) / levels[ch][sb]) - 0x8000;
-
-                    frame->sb_sample[blk][ch][sb] >>= 3;
-                    frame->sb_sample[blk][ch][sb] = (frame->sb_sample[blk][ch][sb] << (frame->scale_factor[ch][sb] + 1)); // Q13
-                }
-                else
-                {
-                    frame->sb_sample[blk][ch][sb] = 0;
-                }
-            }
-        }
-    }
-#endif
-
-    if (frame->channel_mode == JOINT_STEREO)
-    {
-        for (blk = 0; blk < frame->blocks; blk++)
-        {
-            for (sb = 0; sb < frame->subbands; sb++)
-            {
-                if (frame->join & (0x01 << sb)) {
-                    temp = frame->sb_sample[blk][0][sb] + frame->sb_sample[blk][1][sb];
-                    frame->sb_sample[blk][1][sb] = frame->sb_sample[blk][0][sb] - frame->sb_sample[blk][1][sb];
-                    frame->sb_sample[blk][0][sb] = temp;
-                }
-            }
-        }
-    }
-
-    if ((consumed & 0x7) != 0)
-        consumed += 8 - (consumed & 0x7);
-
-
-    return consumed >> 3;
-}
-
-static void sbc_decoder_init(struct sbc_decoder_state *state, const struct sbc_frame *frame)
-{
-    int i, ch;
-
-    memset(state->V, 0, sizeof(state->V));
-    state->subbands = frame->subbands;
-
-    for (ch = 0; ch < 2; ch++)
-        for (i = 0; i < frame->subbands * 2; i++)
-            state->offset[ch][i] = (10 * i + 10);
-}
-
-static __inline void sbc_synthesize_four(struct sbc_decoder_state *state,
-                struct sbc_frame *frame, int ch, int blk)
-{
-    int i, j, k, idx;
-    sbc_extended_t res;
-
-    for(i = 0; i < 8; i++) {
-        /* Shifting */
-        state->offset[ch][i]--;
-        if(state->offset[ch][i] < 0) {
-            state->offset[ch][i] = 79;
-            for(j = 0; j < 9; j++) {
-                state->V[ch][j+80] = state->V[ch][j];
-            }
-        }
-    }
-
-
-    for(i = 0; i < 8; i++) {
-        /* Distribute the new matrix value to the shifted position */
-        SBC_FIXED_0(res);
-        for (j = 0; j < 4; j++) {
-            MULA(res, synmatrix4[i][j], frame->sb_sample[blk][ch][j]);
-        }
-        state->V[ch][state->offset[ch][i]] = SCALE4_STAGED1(res);
-    }
-
-    /* Compute the samples */
-    for(idx = 0, i = 0; i < 4; i++) {
-        k = (i + 4) & 0xf;
-        SBC_FIXED_0(res);
-        for(j = 0; j < 10; idx++) {
-        MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_4_40m0[idx]);
-            MULA(res, state->V[ch][state->offset[ch][k]+j++], sbc_proto_4_40m1[idx]);
-        }
-        /* Store in output */
-        frame->pcm_sample[ch][blk * 4 + i] = (short)SCALE4_STAGED2(res); // Q0
-    }
-}
-
-static __inline void sbc_synthesize_eight(struct sbc_decoder_state *state,
-                struct sbc_frame *frame, int ch, int blk)
-{
-    int i, j, k, idx;
-    sbc_extended_t res;
-
-    for(i = 0; i < 16; i++) {
-        /* Shifting */
-        state->offset[ch][i]--;
-        if(state->offset[ch][i] < 0) {
-            state->offset[ch][i] = 159;
-            for(j = 0; j < 9; j++) {
-                state->V[ch][j+160] = state->V[ch][j];
-            }
-        }
-    }
-
-    for(i = 0; i < 16; i++) {
-        /* Distribute the new matrix value to the shifted position */
-        SBC_FIXED_0(res);
-        for (j = 0; j < 8; j++) {
-            MULA(res, synmatrix8[i][j], frame->sb_sample[blk][ch][j]); // Q28 = Q15 * Q13
-        }
-        state->V[ch][state->offset[ch][i]] = SCALE8_STAGED1(res); // Q10
-    }
-
-
-    /* Compute the samples */
-    for(idx = 0, i = 0; i < 8; i++) {
-        k = (i + 8) & 0xf;
-        SBC_FIXED_0(res);
-        for(j = 0; j < 10; idx++) {
-            MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_8_80m0[idx]);
-            MULA(res, state->V[ch][state->offset[ch][k]+j++], sbc_proto_8_80m1[idx]);
-        }
-        /* Store in output */
-        frame->pcm_sample[ch][blk * 8 + i] = (short)SCALE8_STAGED2(res); // Q0
-
-    }
-}
-
-static int sbc_synthesize_audio(struct sbc_decoder_state *state, struct sbc_frame *frame)
-{
-    int ch, blk;
-
-    switch (frame->subbands) {
-    case 4:
-        for (ch = 0; ch < frame->channels; ch++) {
-            for (blk = 0; blk < frame->blocks; blk++)
-                sbc_synthesize_four(state, frame, ch, blk);
-        }
-        return frame->blocks * 4;
-
-    case 8:
-        for (ch = 0; ch < frame->channels; ch++) {
-            for (blk = 0; blk < frame->blocks; blk++)
-                sbc_synthesize_eight(state, frame, ch, blk);
-        }
-        return frame->blocks * 8;
-
-    default:
-        return -EIO;
-    }
-}
-
-static void sbc_encoder_init(struct sbc_encoder_state *state, const struct sbc_frame *frame)
-{
-    memset(&state->X, 0, sizeof(state->X));
-    state->subbands = frame->subbands;
-}
-
-static __inline void _sbc_analyze_four(const int32_t *in, int32_t *out)
-{
-
-    sbc_extended_t res;
-    sbc_extended_t t[8];
-
-    out[0] = out[1] = out[2] = out[3] = 0;
-
-    MUL(res, _sbc_proto_4[0], (in[8] - in[32])); // Q18
-    MULA(res, _sbc_proto_4[1], (in[16] - in[24]));
-    t[0] = SCALE4_STAGE1(res); // Q8
-
-    MUL(res, _sbc_proto_4[2], in[1]);
-    MULA(res, _sbc_proto_4[3], in[9]);
-    MULA(res, _sbc_proto_4[4], in[17]);
-    MULA(res, _sbc_proto_4[5], in[25]);
-    MULA(res, _sbc_proto_4[6], in[33]);
-    t[1] = SCALE4_STAGE1(res);
-
-    MUL(res, _sbc_proto_4[7], in[2]);
-    MULA(res, _sbc_proto_4[8], in[10]);
-    MULA(res, _sbc_proto_4[9], in[18]);
-    MULA(res, _sbc_proto_4[10], in[26]);
-    MULA(res, _sbc_proto_4[11], in[34]);
-    t[2] = SCALE4_STAGE1(res);
-
-    MUL(res, _sbc_proto_4[12], in[3]);
-    MULA(res, _sbc_proto_4[13], in[11]);
-    MULA(res, _sbc_proto_4[14], in[19]);
-    MULA(res, _sbc_proto_4[15], in[27]);
-    MULA(res, _sbc_proto_4[16], in[35]);
-    t[3] = SCALE4_STAGE1(res);
-
-    MUL(res, _sbc_proto_4[17], in[4]);
-    MULA(res, _sbc_proto_4[18], (in[12] + in[28]));
-    MULA(res, _sbc_proto_4[19], in[20]);
-    MULA(res, _sbc_proto_4[17], in[36]);
-    t[4] = SCALE4_STAGE1(res);
-
-    MUL(res, _sbc_proto_4[16], in[5]);
-    MULA(res, _sbc_proto_4[15], in[13]);
-    MULA(res, _sbc_proto_4[14], in[21]);
-    MULA(res, _sbc_proto_4[13], in[29]);
-    MULA(res, _sbc_proto_4[12], in[37]);
-    t[5] = SCALE4_STAGE1(res);
-
-    MUL(res, _sbc_proto_4[11], in[6]);
-    MULA(res, _sbc_proto_4[10], in[14]);
-    MULA(res, _sbc_proto_4[9], in[22]);
-    MULA(res, _sbc_proto_4[8], in[30]);
-    MULA(res, _sbc_proto_4[7], in[38]);
-    t[6] = SCALE4_STAGE1(res);
-
-    MUL(res, _sbc_proto_4[6], in[7]);
-    MULA(res, _sbc_proto_4[5], in[15]);
-    MULA(res, _sbc_proto_4[4], in[23]);
-    MULA(res, _sbc_proto_4[3], in[31]);
-    MULA(res, _sbc_proto_4[2], in[39]);
-    t[7] = SCALE4_STAGE1(res);
-
-    MUL(res, _anamatrix4[0], t[0]);
-    MULA(res, _anamatrix4[1], t[1]);
-    MULA(res, _anamatrix4[2], t[2]);
-    MULA(res, _anamatrix4[1], t[3]);
-    MULA(res, _anamatrix4[0], t[4]);
-    MULA(res, _anamatrix4[3], t[5]);
-    MULA(res, -_anamatrix4[3], t[7]);
-    out[0] = (int)SCALE4_STAGE2(res); // Q0
-
-    MUL(res, -_anamatrix4[0], t[0]);
-    MULA(res, _anamatrix4[3], t[1]);
-    MULA(res, _anamatrix4[2], t[2]);
-    MULA(res, _anamatrix4[3], t[3]);
-    MULA(res, -_anamatrix4[0], t[4]);
-    MULA(res, -_anamatrix4[1], t[5]);
-    MULA(res, _anamatrix4[1], t[7]);
-    out[1] = (int)SCALE4_STAGE2(res);
-
-
-    MUL(res, -_anamatrix4[0], t[0]);
-    MULA(res, -_anamatrix4[3], t[1]);
-    MULA(res, _anamatrix4[2], t[2]);
-    MULA(res, -_anamatrix4[3], t[3]);
-    MULA(res, -_anamatrix4[0], t[4]);
-    MULA(res, _anamatrix4[1], t[5]);
-    MULA(res, -_anamatrix4[1], t[7]);
-    out[2] = (int)SCALE4_STAGE2(res);
-
-    MUL(res, _anamatrix4[0], t[0]);
-    MULA(res, -_anamatrix4[1], t[1]);
-    MULA(res, _anamatrix4[2], t[2]);
-    MULA(res, -_anamatrix4[1], t[3]);
-    MULA(res, _anamatrix4[0], t[4]);
-    MULA(res, -_anamatrix4[3], t[5]);
-    MULA(res, _anamatrix4[3], t[7]);
-    out[3] = (int)SCALE4_STAGE2(res);
-}
-static __inline  void sbc_analyze_four(struct sbc_encoder_state *state,
-                struct sbc_frame *frame, int ch, int blk)
-{
-    int i;
-    /* Input 4 New Audio Samples */
-    for (i = 39; i >= 4; i--)
-        state->X[ch][i] = state->X[ch][i - 4];
-    for (i = 3; i >= 0; i--)
-        state->X[ch][i] = frame->pcm_sample[ch][blk * 4 + (3 - i)];
-    _sbc_analyze_four(state->X[ch], frame->sb_sample_f[blk][ch]);
-}
-
-static __inline void _sbc_analyze_eight(const int32_t *in, int32_t *out)
-{
-    sbc_extended_t res;
-    sbc_extended_t t[8];
-
-    out[0] = out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = 0;
-
-    MUL(res,  _sbc_proto_8[0], (in[16] - in[64])); // Q18 = Q18 * Q0
-    MULA(res, _sbc_proto_8[1], (in[32] - in[48]));
-    MULA(res, _sbc_proto_8[2], in[4]);
-    MULA(res, _sbc_proto_8[3], in[20]);
-    MULA(res, _sbc_proto_8[4], in[36]);
-    MULA(res, _sbc_proto_8[5], in[52]);
-    t[0] = SCALE8_STAGE1(res); // Q10
-
-    MUL(res,   _sbc_proto_8[6], in[2]);
-    MULA(res,  _sbc_proto_8[7], in[18]);
-    MULA(res,  _sbc_proto_8[8], in[34]);
-    MULA(res,  _sbc_proto_8[9], in[50]);
-    MULA(res, _sbc_proto_8[10], in[66]);
-    t[1] = SCALE8_STAGE1(res);
-
-    MUL(res,  _sbc_proto_8[11], in[1]);
-    MULA(res, _sbc_proto_8[12], in[17]);
-    MULA(res, _sbc_proto_8[13], in[33]);
-    MULA(res, _sbc_proto_8[14], in[49]);
-    MULA(res, _sbc_proto_8[15], in[65]);
-    MULA(res, _sbc_proto_8[16], in[3]);
-    MULA(res, _sbc_proto_8[17], in[19]);
-    MULA(res, _sbc_proto_8[18], in[35]);
-    MULA(res, _sbc_proto_8[19], in[51]);
-    MULA(res, _sbc_proto_8[20], in[67]);
-    t[2] = SCALE8_STAGE1(res);
-
-    MUL(res,   _sbc_proto_8[21], in[5]);
-    MULA(res,  _sbc_proto_8[22], in[21]);
-    MULA(res,  _sbc_proto_8[23], in[37]);
-    MULA(res,  _sbc_proto_8[24], in[53]);
-    MULA(res,  _sbc_proto_8[25], in[69]);
-    MULA(res, -_sbc_proto_8[15], in[15]);
-    MULA(res, -_sbc_proto_8[14], in[31]);
-    MULA(res, -_sbc_proto_8[13], in[47]);
-    MULA(res, -_sbc_proto_8[12], in[63]);
-    MULA(res, -_sbc_proto_8[11], in[79]);
-    t[3] = SCALE8_STAGE1(res);
-
-    MUL(res,   _sbc_proto_8[26], in[6]);
-    MULA(res,  _sbc_proto_8[27], in[22]);
-    MULA(res,  _sbc_proto_8[28], in[38]);
-    MULA(res,  _sbc_proto_8[29], in[54]);
-    MULA(res,  _sbc_proto_8[30], in[70]);
-    MULA(res, -_sbc_proto_8[10], in[14]);
-    MULA(res,  -_sbc_proto_8[9], in[30]);
-    MULA(res,  -_sbc_proto_8[8], in[46]);
-    MULA(res,  -_sbc_proto_8[7], in[62]);
-    MULA(res,  -_sbc_proto_8[6], in[78]);
-    t[4] = SCALE8_STAGE1(res);
-
-    MUL(res,   _sbc_proto_8[31], in[7]);
-    MULA(res,  _sbc_proto_8[32], in[23]);
-    MULA(res,  _sbc_proto_8[33], in[39]);
-    MULA(res,  _sbc_proto_8[34], in[55]);
-    MULA(res,  _sbc_proto_8[35], in[71]);
-    MULA(res, -_sbc_proto_8[20], in[13]);
-    MULA(res, -_sbc_proto_8[19], in[29]);
-    MULA(res, -_sbc_proto_8[18], in[45]);
-    MULA(res, -_sbc_proto_8[17], in[61]);
-    MULA(res, -_sbc_proto_8[16], in[77]);
-    t[5] = SCALE8_STAGE1(res);
-
-    MUL(res,   _sbc_proto_8[36], (in[8] + in[72]));
-    MULA(res,  _sbc_proto_8[37], in[24]);
-    MULA(res,  _sbc_proto_8[38], in[40]);
-    MULA(res,  _sbc_proto_8[37], in[56]);
-    MULA(res, -_sbc_proto_8[39], in[12]);
-    MULA(res,  -_sbc_proto_8[5], in[28]);
-    MULA(res,  -_sbc_proto_8[4], in[44]);
-    MULA(res,  -_sbc_proto_8[3], in[60]);
-    MULA(res,  -_sbc_proto_8[2], in[76]);
-    t[6] = SCALE8_STAGE1(res);
-
-    MUL(res,   _sbc_proto_8[35], in[9]);
-    MULA(res,  _sbc_proto_8[34], in[25]);
-    MULA(res,  _sbc_proto_8[33], in[41]);
-    MULA(res,  _sbc_proto_8[32], in[57]);
-    MULA(res,  _sbc_proto_8[31], in[73]);
-    MULA(res, -_sbc_proto_8[25], in[11]);
-    MULA(res, -_sbc_proto_8[24], in[27]);
-    MULA(res, -_sbc_proto_8[23], in[43]);
-    MULA(res, -_sbc_proto_8[22], in[59]);
-    MULA(res, -_sbc_proto_8[21], in[75]);
-    t[7] = SCALE8_STAGE1(res);
-
-    MUL(res, _anamatrix8[0], t[0]); // = Q14 * Q10
-    MULA(res, _anamatrix8[7], t[1]);
-    MULA(res, _anamatrix8[2], t[2]);
-    MULA(res, _anamatrix8[3], t[3]);
-    MULA(res, _anamatrix8[6], t[4]);
-    MULA(res, _anamatrix8[4], t[5]);
-    MULA(res, _anamatrix8[1], t[6]);
-    MULA(res, _anamatrix8[5], t[7]);
-    out[0] = (int)SCALE8_STAGE2(res); // Q0
-
-    MUL(res, _anamatrix8[1], t[0]);
-    MULA(res, _anamatrix8[7], t[1]);
-    MULA(res, _anamatrix8[3], t[2]);
-    MULA(res, -_anamatrix8[5], t[3]);
-    MULA(res, -_anamatrix8[6], t[4]);
-    MULA(res, -_anamatrix8[2], t[5]);
-    MULA(res, -_anamatrix8[0], t[6]);
-    MULA(res, -_anamatrix8[4], t[7]);
-    out[1] = (int)SCALE8_STAGE2(res);
-
-    MUL(res, -_anamatrix8[1], t[0]);
-    MULA(res, _anamatrix8[7], t[1]);
-    MULA(res, _anamatrix8[4], t[2]);
-    MULA(res, -_anamatrix8[2], t[3]);
-    MULA(res, -_anamatrix8[6], t[4]);
-    MULA(res, _anamatrix8[5], t[5]);
-    MULA(res, _anamatrix8[0], t[6]);
-    MULA(res, _anamatrix8[3], t[7]);
-    out[2] = (int)SCALE8_STAGE2(res);
-
-    MUL(res, -_anamatrix8[0], t[0]);
-    MULA(res, _anamatrix8[7], t[1]);
-    MULA(res, _anamatrix8[5], t[2]);
-    MULA(res, -_anamatrix8[4], t[3]);
-    MULA(res, _anamatrix8[6], t[4]);
-    MULA(res, _anamatrix8[3], t[5]);
-    MULA(res, -_anamatrix8[1], t[6]);
-    MULA(res, -_anamatrix8[2], t[7]);
-    out[3] = (int)SCALE8_STAGE2(res);
-
-    MUL(res, -_anamatrix8[0], t[0]);
-    MULA(res, _anamatrix8[7], t[1]);
-    MULA(res, -_anamatrix8[5], t[2]);
-    MULA(res, _anamatrix8[4], t[3]);
-    MULA(res, _anamatrix8[6], t[4]);
-    MULA(res, -_anamatrix8[3], t[5]);
-    MULA(res, -_anamatrix8[1], t[6]);
-    MULA(res, _anamatrix8[2], t[7]);
-    out[4] = (int)SCALE8_STAGE2(res);
-
-    MUL(res, -_anamatrix8[1], t[0]);
-    MULA(res, _anamatrix8[7], t[1]);
-    MULA(res, -_anamatrix8[4], t[2]);
-    MULA(res, _anamatrix8[2], t[3]);
-    MULA(res, -_anamatrix8[6], t[4]);
-    MULA(res, -_anamatrix8[5], t[5]);
-    MULA(res, _anamatrix8[0], t[6]);
-    MULA(res, -_anamatrix8[3], t[7]);
-    out[5] = (int)SCALE8_STAGE2(res);
-
-    MUL(res, _anamatrix8[1], t[0]);
-    MULA(res, _anamatrix8[7], t[1]);
-    MULA(res, -_anamatrix8[3], t[2]);
-    MULA(res, _anamatrix8[5], t[3]);
-    MULA(res, -_anamatrix8[6], t[4]);
-    MULA(res, _anamatrix8[2], t[5]);
-    MULA(res, -_anamatrix8[0], t[6]);
-    MULA(res, _anamatrix8[4], t[7]);
-    out[6] = (int)SCALE8_STAGE2(res);
-
-    MUL(res, _anamatrix8[0], t[0]);
-    MULA(res, _anamatrix8[7], t[1]);
-    MULA(res, -_anamatrix8[2], t[2]);
-    MULA(res, -_anamatrix8[3], t[3]);
-    MULA(res, _anamatrix8[6], t[4]);
-    MULA(res, -_anamatrix8[4], t[5]);
-    MULA(res, _anamatrix8[1], t[6]);
-    MULA(res, -_anamatrix8[5], t[7]);
-    out[7] = (int)SCALE8_STAGE2(res);
-}
-
-static __inline void sbc_analyze_eight(struct sbc_encoder_state *state,
-                     struct sbc_frame *frame, int ch, int blk)
-{
-    int i;
-
-    /* Input 8 Audio Samples */
-    for (i = 79; i >= 8; i--)
-        state->X[ch][i] = state->X[ch][i - 8];
-    for (i = 7; i >= 0; i--)
-        state->X[ch][i] = frame->pcm_sample[ch][blk * 8 + (7 - i)];
-    _sbc_analyze_eight(state->X[ch], frame->sb_sample_f[blk][ch]);
-}
-
-static int sbc_analyze_audio(struct sbc_encoder_state *state, struct sbc_frame *frame)
-{
-    int ch, blk;
-
-    switch (frame->subbands)
-    {
-        case 4:
-            for (ch = 0; ch < frame->channels; ch++)
-                for (blk = 0; blk < frame->blocks; blk++) {
-                    sbc_analyze_four(state, frame, ch, blk);
-                }
-            return frame->blocks * 4;
-
-        case 8:
-            for (ch = 0; ch < frame->channels; ch++)
-                for (blk = 0; blk < frame->blocks; blk++) {
-                    sbc_analyze_eight(state, frame, ch, blk);
-                }
-            return frame->blocks * 8;
-
-        default:
-            return -EIO;
-    }
-}
-
-/*
- * Packs the SBC frame from frame into the memory at data. At most len
- * bytes will be used, should more memory be needed an appropriate
- * error code will be returned. Returns the length of the packed frame
- * on success or a negative value on error.
- *
- * The error codes are:
- * -1 Not enough memory reserved
- * -2 Unsupported sampling rate
- * -3 Unsupported number of blocks
- * -4 Unsupported number of subbands
- * -5 Bitpool value out of bounds
- * -99 not implemented
- */
-
-static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len)
-{
-    size_t produced;
-    /* Will copy the header parts for CRC-8 calculation here */
-    uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-    int crc_pos = 0;
-
-    uint8_t sf;     /* Sampling frequency as temporary value for table lookup */
-
-    int ch, sb, blk, bit;   /* channel, subband, block and bit counters */
-    int bits[2][8];     /* bits distribution */
-    int levels[2][8];   /* levels are derived from that */
-
-    u_int32_t scalefactor[2][8];    /* derived from frame->scale_factor */
-
-    if (len < 4)
-    {
-        return -1;
-    }
-
-    /* Clear first 4 bytes of data (that's the constant length part of the SBC header) */
-    memset(data, 0, 4);
-
-    data[0] = SBC_SYNCWORD;
-
-    if (frame->sampling_frequency == 16000)
-    {
-        data[1] |= (SBC_FS_16 & 0x03) << 6;
-        sf = SBC_FS_16;
-    }
-    else if (frame->sampling_frequency == 32000)
-    {
-        data[1] |= (SBC_FS_32 & 0x03) << 6;
-        sf = SBC_FS_32;
-    }
-    else if (frame->sampling_frequency == 44100)
-    {
-        data[1] |= (SBC_FS_44 & 0x03) << 6;
-        sf = SBC_FS_44;
-    }
-    else if (frame->sampling_frequency == 48000)
-    {
-        data[1] |= (SBC_FS_48 & 0x03) << 6;
-        sf = SBC_FS_48;
-    }
-    else
-    {
-        return -2;
-    }
-
-    switch (frame->blocks)
-    {
-    case 4:
-        data[1] |= (SBC_NB_4 & 0x03) << 4;
-        break;
-    case 8:
-        data[1] |= (SBC_NB_8 & 0x03) << 4;
-        break;
-    case 12:
-        data[1] |= (SBC_NB_12 & 0x03) << 4;
-        break;
-    case 15:
-        data[1] |= (SBC_NB_16 & 0x03) << 4;
-        break;
-    default:
-        return -3;
-        break;
-    }
-
-    data[1] |= (frame->channel_mode & 0x03) << 2;
-
-    data[1] |= (frame->allocation_method & 0x01) << 1;
-
-    switch (frame->subbands) {
-    case 4:
-        /* Nothing to do */
-        break;
-    case 8:
-        data[1] |= 0x01;
-        break;
-    default:
-        return -4;
-        break;
-    }
-
-    data[2] = frame->bitpool;
-    if (((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL)
-         && frame->bitpool > 16 * frame->subbands)
-        || ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO)
-        && frame->bitpool > 32 * frame->subbands)) {
-        return -5;
-    }
-
-    /* Can't fill in crc yet */
-
-    produced = 32;
-
-    // evan.
-    data[1] = 0x00;
-    data[2] = 0x00;
-
-    crc_header[0] = data[1];
-    crc_header[1] = data[2];
-    crc_pos = 16;
-
-
-    for (ch = 0; ch < frame->channels; ch++) {
-        for (sb = 0; sb < frame->subbands; sb++) {
-            frame->scale_factor[ch][sb] = 0;
-            scalefactor[ch][sb] = 2;
-            for (blk = 0; blk < frame->blocks; blk++) {
-                while (scalefactor[ch][sb] < (u_int32_t)fabs(frame->sb_sample_f[blk][ch][sb])) {
-                    frame->scale_factor[ch][sb]++;
-                    scalefactor[ch][sb] *= 2;
-                }
-            }
-        }
-    }
-
-    if (frame->channel_mode == JOINT_STEREO) {
-        int32_t sb_sample_j[16][2][7]; /* like frame->sb_sample but joint stereo */
-        u_int32_t scalefactor_j[2][7], scale_factor_j[2][7]; /* scalefactor and scale_factor in joint case */
-
-        /* Calculate joint stereo signal */
-        for (sb = 0; sb < frame->subbands - 1; sb++) {
-            for (blk = 0; blk < frame->blocks; blk++) {
-                sb_sample_j[blk][0][sb] = (frame->sb_sample_f[blk][0][sb] +  frame->sb_sample_f[blk][1][sb]) >> 1;
-                sb_sample_j[blk][1][sb] = (frame->sb_sample_f[blk][0][sb] -  frame->sb_sample_f[blk][1][sb]) >> 1;
-            }
-        }
-
-        /* calculate scale_factor_j and scalefactor_j for joint case */
-        for (ch = 0; ch < 2; ch++) {
-            for (sb = 0; sb < frame->subbands - 1; sb++) {
-                scale_factor_j[ch][sb] = 0;
-                scalefactor_j[ch][sb] = 2;
-                for (blk = 0; blk < frame->blocks; blk++) {
-                    while (scalefactor_j[ch][sb] < (u_int32_t)fabs(sb_sample_j[blk][ch][sb])) {
-                        scale_factor_j[ch][sb]++;
-                        scalefactor_j[ch][sb] *= 2;
-                    }
-                }
-            }
-        }
-
-        /* decide which subbands to join */
-        frame->join = 0;
-        for (sb = 0; sb < frame->subbands - 1; sb++) {
-            if ((scalefactor[0][sb] + scalefactor[1][sb]) >
-                    (scalefactor_j[0][sb] + scalefactor_j[1][sb]) ) {
-                /* use joint stereo for this subband */
-                frame->join |= 1 << sb;
-                frame->scale_factor[0][sb] = scale_factor_j[0][sb];
-                frame->scale_factor[1][sb] = scale_factor_j[1][sb];
-                scalefactor[0][sb] = scalefactor_j[0][sb];
-                scalefactor[1][sb] = scalefactor_j[1][sb];
-                for (blk = 0; blk < frame->blocks; blk++) {
-                    frame->sb_sample_f[blk][0][sb] = sb_sample_j[blk][0][sb];
-                    frame->sb_sample_f[blk][1][sb] = sb_sample_j[blk][1][sb];
-                }
-            }
-        }
-
-        if (len * 8 < produced + frame->subbands)
-            return -1;
-
-        data[4] = 0;
-        for (sb = 0; sb < frame->subbands - 1; sb++) {
-            data[4] |= ((frame->join >> sb) & 0x01) << (7 - sb);
-        }
-        if (frame->subbands == 4) {
-            crc_header[crc_pos / 8] = data[4] & 0xf0;
-        } else {
-            crc_header[crc_pos / 8] = data[4];
-        }
-
-        produced += frame->subbands;
-        crc_pos += frame->subbands;
-    }
-
-    if (len * 8 < produced + (4 * frame->subbands * frame->channels))
-        return -1;
-
-    for (ch = 0; ch < frame->channels; ch++) {
-        for (sb = 0; sb < frame->subbands; sb++) {
-            if (produced % 8 == 0)
-                data[produced / 8] = 0;
-            data[produced / 8] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (produced % 8)));
-            crc_header[crc_pos / 8] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (crc_pos % 8)));
-
-            produced += 4;
-            crc_pos += 4;
-        }
-    }
-
-    data[3] = sbc_crc8(crc_header, crc_pos);
-
-
-
-    sbc_calculate_bits(frame, bits, sf);
-
-    for (ch = 0; ch < frame->channels; ch++) {
-        for (sb = 0; sb < frame->subbands; sb++) {
-            levels[ch][sb] = (1 << bits[ch][sb]) - 1;
-        }
-    }
-
-    for (blk = 0; blk < frame->blocks; blk++) {
-        for (ch = 0; ch < frame->channels; ch++) {
-            for (sb = 0; sb < frame->subbands; sb++) {
-                if (levels[ch][sb] > 0) {
-                    frame->audio_sample[blk][ch][sb] =
-                        (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> (frame->scale_factor[ch][sb] + 1)) +
-                        levels[ch][sb]) >> 1);
-                } else {
-                    frame->audio_sample[blk][ch][sb] = 0;
-                }
-            }
-        }
-    }
-
-    for (blk = 0; blk < frame->blocks; blk++) {
-        for (ch = 0; ch < frame->channels; ch++) {
-            for (sb = 0; sb < frame->subbands; sb++) {
-                if (bits[ch][sb] != 0) {
-                    for (bit = 0; bit < bits[ch][sb]; bit++) {
-                        int b;  /* A bit */
-                        if (produced > len * 8) {
-                            return -1;
-                        }
-                        if (produced % 8 == 0) {
-                            data[produced / 8] = 0;
-                        }
-                        b = ((frame->audio_sample[blk][ch][sb]) >> (bits[ch][sb] - bit -
-                                                1)) & 0x01;
-                        data[produced / 8] |= b << (7 - (produced % 8));
-                        produced++;
-                    }
-                }
-            }
-        }
-    }
-
-    if (produced % 8 != 0) {
-        produced += 8 - (produced % 8);
-    }
-
-    return (int)(produced / 8);
-}
-
-struct sbc_priv {
-    int init;
-    struct sbc_frame frame;
-    struct sbc_decoder_state dec_state;
-    struct sbc_encoder_state enc_state;
-};
-
-int sbc_init(sbc_t *sbc)//int sbc_init(sbc_t *sbc, unsigned long flags)
-{
-    if (!sbc)
-        return -EIO;
-
-    //flags = flags;
-
-    memset(sbc, 0, sizeof(sbc_t));
-
-    sbc->priv = malloc(sizeof(struct sbc_priv) + SBC_ALIGN_MASK);
-    if (!sbc->priv)
-        return -ENOMEM;
-    memset(sbc->priv, 0, sizeof(struct sbc_priv));
-
-    sbc->rate = 16000;
-    sbc->channels = 1;
-    sbc->joint = 0;
-    sbc->subbands = 8;
-    sbc->blocks = 15;
-    sbc->bitpool = 26;
-
-    return 0;
-}
-
-int sbc_reinit(sbc_t *sbc)//int sbc_reinit(sbc_t *sbc, unsigned long flags)
-{
-    struct sbc_priv *priv;
-
-    if (!sbc || !sbc->priv)
-        return -EIO;
-
-    //flags = flags;
-    priv = sbc->priv;
-
-    if (priv->init == 1)
-        memset(sbc->priv, 0, sizeof(struct sbc_priv));
-
-    return 0;
-}
-
-
-int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,
-               int output_len, int *written)
-{
-    struct sbc_priv *priv;
-    char *ptr;
-    int i, ch, framelen, samples;
-
-    if (!sbc)
-    {
-        //DbgPrint("Exit.when sbc is NULL.\n");
-        return -EIO;
-    }
-
-    if (!sbc && !input)
-    {
-        //DbgPrint("!sbc && !input\n");
-        return -EIO;
-    }
-
-    priv = sbc->priv;
-    if(!priv)
-        return -99;
-
-    framelen = sbc_unpack_frame(input, &priv->frame, input_len);
-
-    if (!priv->init)
-    {
-        sbc_decoder_init(&priv->dec_state, &priv->frame);
-        priv->init = 1;
-
-        sbc->rate = priv->frame.sampling_frequency;
-        sbc->channels = priv->frame.channels;
-        sbc->subbands = priv->frame.subbands;
-        sbc->blocks = priv->frame.blocks;
-        sbc->bitpool = priv->frame.bitpool;
-    }
-
-    if (!output)
-    {
-        //DbgPrint("!output\n");
-        return framelen;
-    }
-
-    if (written)
-        *written = 0;
-
-    if (framelen <= 0)
-    {
-        //DbgPrint("Exit when framelen <= 0\n");
-        return framelen;
-    }
-
-    samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame);
-
-    ptr = output;
-    if (output_len < samples * priv->frame.channels * 2)
-        samples = output_len / (priv->frame.channels * 2);
-
-/*
-    if (!sbc->data)
-    {
-        sbc->size = samples * priv->frame.channels * 2;
-        sbc->data = malloc(sbc->size);
-    }
-
-
-    if (sbc->size < samples * priv->frame.channels * 2)
-    {
-        sbc->size = samples * priv->frame.channels * 2;
-        sbc->data = realloc(sbc->data, sbc->size);
-    }
-
-    if (!sbc->data)
-    {
-        sbc->size = 0;
-        return -ENOMEM;
-    }
-*/
-
-    for (i = 0; i < samples; i++)
-    {
-        for (ch = 0; ch < priv->frame.channels; ch++)
-        {
-            int16_t s;
-            s = priv->frame.pcm_sample[ch][i];
-        /*
-            *ptr++ = (s & 0xff00) >> 8;
-            *ptr++ = (s & 0x00ff);
-        */
-            *ptr++ = (s & 0x00ff);
-            *ptr++ = (s & 0xff00) >> 8;
-        }
-    }
-
-    if (written)
-        *written = samples * priv->frame.channels * 2;
-
-    return framelen;
-}
-
-int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output,
-               int output_len, int *written)
-{
-    struct sbc_priv *priv;
-    char *ptr;
-    int i, ch, framelen, samples;
-
-    if (!sbc)
-    {
-        //DbgPrint("Exit, when !sbc.\n");
-        return -EIO;
-    }
-
-
-    if (!sbc && !input)
-    {
-        //DbgPrint("Exit, when !sbc && !input.\n");
-        return -EIO;
-    }
-
-    /// make sure sbc has been initialized
-    priv = sbc->priv;
-    if(priv == NULL){
-        //DbgPrint("priv == NULL\n");
-        return -EIO;
-    }
-
-    if (written)
-        *written = 0;
-
-    if (!priv->init)
-    {
-        //DbgPrint("Initial priv->frame ,when priv->init is null\n");
-        priv->frame.sampling_frequency = sbc->rate;
-        priv->frame.channels = sbc->channels;
-        priv->frame.channel_mode = MONO;
-        priv->frame.allocation_method = LOUDNESS;
-        priv->frame.subbands = sbc->subbands;
-        priv->frame.blocks = sbc->blocks;
-        priv->frame.bitpool = sbc->bitpool;
-
-        sbc_encoder_init(&priv->enc_state, &priv->frame);
-        priv->init = 1;
-    }
-
-    /* input must be large enough to encode a complete frame */
-    if (input_len < 240)
-    {
-        //DbgPrint("Exit, when input_len < priv->frame.codesize..\n");
-        return 0;
-    }
-
-    /* output must be large enough to receive the encoded frame */
-    if (!output || output_len < 57)
-    {
-        //DbgPrint("Exit, when !output || output_len < priv->frame.length\n");
-        return -ENOSPC;
-    }
-
-    ptr = input;
-    for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++)
-    {
-        for (ch = 0; ch < sbc->channels; ch++)
-        {
-        //  int16_t s = (ptr[0] & 0xff) << 8 | (ptr[1] & 0xff);
-            int16_t s = (ptr[1] & 0xff) << 8 | (ptr[0] & 0xff);
-            ptr += 2;
-            priv->frame.pcm_sample[ch][i] = s;
-        }
-    }
-
-    samples = 0;
-    samples = sbc_analyze_audio(&priv->enc_state, &priv->frame);
-
-    if (!sbc->data)
-    {
-        sbc->size = 1024;
-//      sbc->data = malloc(sbc->size);
-        sbc->data = malloc(sbc->size);
-        if (!sbc->data)
-        {
-            //DbgPrint("sbc->data allocate failed!!!\n");
-            return -ENOMEM;
-        }
-        memset(sbc->data, 0, sbc->size);
-    }
-
-    if (!sbc->data)
-    {
-        sbc->size = 0;
-        //DbgPrint("sbc->data is null, so exit!!!\n");
-        return -ENOMEM;
-    }
-
-    framelen = sbc_pack_frame(output, &priv->frame, output_len);
-    if (written)
-    {
-        *written = (int)framelen;//in 64 bit os, it should be okay.
-    }
-
-    sbc->len = framelen;
-    sbc->duration = (1000000 * priv->frame.subbands * priv->frame.blocks) / sbc->rate;
-
-    return samples * sbc->channels * 2;
-}
-
-
-void sbc_finish(sbc_t *sbc)
-{
-    if (!sbc)
-        return;
-
-    if (sbc->data)
-        free(sbc->data);
-
-
-    if (sbc->priv)
-    {
-        free(sbc->priv);
-    }
-    memset(sbc, 0, sizeof(sbc_t));
-}
diff --git a/rtkbt/code/libbt-vendor/codec/msbc/sbc.h b/rtkbt/code/libbt-vendor/codec/msbc/sbc.h
deleted file mode 100755 (executable)
index 5e74751..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *
- *  Bluetooth low-complexity, subband codec (SBC) library
- *
- *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
- *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
- *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifndef __SBC_H
-#define __SBC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-struct sbc_struct {
-    unsigned long flags;
-    unsigned short rate;
-    unsigned char channels;
-    unsigned char joint;
-    unsigned char blocks;
-    unsigned char subbands;
-    unsigned char bitpool;
-
-    void *data;
-    int size;
-    int len;
-
-    unsigned long duration;
-
-    void *priv;
-};
-
-typedef struct sbc_struct sbc_t;
-
-int sbc_init(sbc_t *sbc);//int sbc_init(sbc_t *sbc, unsigned long flags);
-
-int sbc_reinit(sbc_t *sbc);//int sbc_reinit(sbc_t *sbc, unsigned long flags);
-
-
-int sbc_encode(sbc_t *sbc,
-               void *input,
-               int input_len,
-               void *output,
-               int output_len,
-               int *written);
-
-int sbc_decode(sbc_t *sbc,
-               void *input,
-               int input_len,
-               void *output,
-               int output_len,
-               int *written);
-
-void sbc_finish(sbc_t *sbc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __SBC_H */
diff --git a/rtkbt/code/libbt-vendor/codec/msbc/sbc_math.h b/rtkbt/code/libbt-vendor/codec/msbc/sbc_math.h
deleted file mode 100755 (executable)
index d620822..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- *  Bluetooth low-complexity, subband codec (SBC) library
- *
- *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
- *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
- *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#define fabs(x) ((x) < 0 ? -(x) : (x))
-/* C does not provide an explicit arithmetic shift right but this will
-   always be correct and every compiler *should* generate optimal code */
-#define ASR(val, bits) ((-2 >> 1 == -1) ? \
-         ((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits)))
-#define ASR_64(val, bits) ((-2 >> 1 == -1) ? \
-         ((long long)(val)) >> (bits) : ((long long) (val)) / (1 << (bits)))
-
-#define SCALE_PROTO4_TBL    15
-#define SCALE_ANA4_TBL      16
-#define SCALE_PROTO8_TBL    15
-#define SCALE_ANA8_TBL      16
-#define SCALE_SPROTO4_TBL   16
-#define SCALE_SPROTO8_TBL   16
-#define SCALE_NPROTO4_TBL   10
-#define SCALE_NPROTO8_TBL   12
-#define SCALE_SAMPLES       14
-#define SCALE4_STAGE1_BITS  10
-#define SCALE4_STAGE2_BITS  21
-#define SCALE4_STAGED1_BITS 18
-#define SCALE4_STAGED2_BITS 23
-#define SCALE8_STAGE1_BITS  8
-#define SCALE8_STAGE2_BITS  24
-#define SCALE8_STAGED1_BITS 18
-#define SCALE8_STAGED2_BITS 23
-
-//typedef int     int32_t;
-//typedef int32_t sbc_fixed_t;
-//typedef long long sbc_extended_t;
-
-#define SCALE4_STAGE1(src)  ASR_64(src, SCALE4_STAGE1_BITS)
-#define SCALE4_STAGE2(src)  ASR_64(src, SCALE4_STAGE2_BITS)
-#define SCALE4_STAGED1(src) ASR_64(src, SCALE4_STAGED1_BITS)
-#define SCALE4_STAGED2(src) ASR_64(src, SCALE4_STAGED2_BITS)
-#define SCALE8_STAGE1(src)  ASR_64(src, SCALE8_STAGE1_BITS)
-#define SCALE8_STAGE2(src)  ASR_64(src, SCALE8_STAGE2_BITS)
-#define SCALE8_STAGED1(src) ASR_64(src, SCALE8_STAGED1_BITS)
-#define SCALE8_STAGED2(src) ASR_64(src, SCALE8_STAGED2_BITS)
-
-#define SBC_FIXED_0(val) { val = 0; }
-#define ADD(dst, src)    { dst += src; }
-#define SUB(dst, src)    { dst -= src; }
-#define MUL(dst, a, b)   { dst = (sbc_extended_t) (a) * (b); }
-#define MULA(dst, a, b)  { dst += (sbc_extended_t) (a) * (b); }
-#define DIV2(dst, src)   { dst = ASR(src, 1); }
diff --git a/rtkbt/code/libbt-vendor/codec/msbc/sbc_tables.h b/rtkbt/code/libbt-vendor/codec/msbc/sbc_tables.h
deleted file mode 100755 (executable)
index f532cec..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *
- *  Bluetooth low-complexity, subband codec (SBC) library
- *
- *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
- *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
- *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include "sbc_math.h"
-
-/* A2DP specification: Appendix B, page 69 */
-static const int sbc_offset4[4][4] = {
-    { -1, 0, 0, 0 },
-    { -2, 0, 0, 1 },
-    { -2, 0, 0, 1 },
-    { -2, 0, 0, 1 }
-};
-
-/* A2DP specification: Appendix B, page 69 */
-static const int sbc_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 }
-};
-
-#define SP4(val) ASR(val, SCALE_PROTO4_TBL)
-#define SA4(val) ASR(val, SCALE_ANA4_TBL)
-#define SP8(val) ASR(val, SCALE_PROTO8_TBL)
-#define SA8(val) ASR(val, SCALE_ANA8_TBL)
-#define SS4(val) ASR(val, SCALE_SPROTO4_TBL)
-#define SS8(val) ASR(val, SCALE_SPROTO8_TBL)
-#define SN4(val) ASR(val, SCALE_NPROTO4_TBL)
-#define SN8(val) ASR(val, SCALE_NPROTO8_TBL)
-
-static const int32_t _sbc_proto_4[20] = {
-    SP4(0x02cb3e8c), SP4(0x22b63dc0), SP4(0x002329cc), SP4(0x053b7548),
-    SP4(0x31eab940), SP4(0xec1f5e60), SP4(0xff3773a8), SP4(0x0061c5a7),
-    SP4(0x07646680), SP4(0x3f239480), SP4(0xf89f23a8), SP4(0x007a4737),
-    SP4(0x00b32807), SP4(0x083ddc80), SP4(0x4825e480), SP4(0x0191e578),
-    SP4(0x00ff11ca), SP4(0x00fb7991), SP4(0x069fdc58), SP4(0x4b584000)
-};
-
-static const int32_t _anamatrix4[4] = {
-    SA4(0x2d413cc0), SA4(0x3b20d780), SA4(0x40000000), SA4(0x187de2a0)
-};
-
-static const int32_t _sbc_proto_8[40] = {
-    SP8(0x02e5cd20), SP8(0x22d0c200), SP8(0x006bfe27), SP8(0x07808930),
-    SP8(0x3f1c8800), SP8(0xf8810d70), SP8(0x002cfdc6), SP8(0x055acf28),
-    SP8(0x31f566c0), SP8(0xebfe57e0), SP8(0xff27c437), SP8(0x001485cc),
-    SP8(0x041c6e58), SP8(0x2a7cfa80), SP8(0xe4c4a240), SP8(0xfe359e4c),
-    SP8(0x0048b1f8), SP8(0x0686ce30), SP8(0x38eec5c0), SP8(0xf2a1b9f0),
-    SP8(0xffe8904a), SP8(0x0095698a), SP8(0x0824a480), SP8(0x443b3c00),
-    SP8(0xfd7badc8), SP8(0x00d3e2d9), SP8(0x00c183d2), SP8(0x084e1950),
-    SP8(0x4810d800), SP8(0x017f43fe), SP8(0x01056dd8), SP8(0x00e9cb9f),
-    SP8(0x07d7d090), SP8(0x4a708980), SP8(0x0488fae8), SP8(0x0113bd20),
-    SP8(0x0107b1a8), SP8(0x069fb3c0), SP8(0x4b3db200), SP8(0x00763f48)
-};
-
-static const int32_t sbc_proto_4_40m0[] = {
-    SS4(0x00000000), SS4(0xffa6982f), SS4(0xfba93848), SS4(0x0456c7b8),
-    SS4(0x005967d1), SS4(0xfffb9ac7), SS4(0xff589157), SS4(0xf9c2a8d8),
-    SS4(0x027c1434), SS4(0x0019118b), SS4(0xfff3c74c), SS4(0xff137330),
-    SS4(0xf81b8d70), SS4(0x00ec1b8b), SS4(0xfff0b71a), SS4(0xffe99b00),
-    SS4(0xfef84470), SS4(0xf6fb4370), SS4(0xffcdc351), SS4(0xffe01dc7)
-};
-
-static const int32_t sbc_proto_4_40m1[] = {
-    SS4(0xffe090ce), SS4(0xff2c0475), SS4(0xf694f800), SS4(0xff2c0475),
-    SS4(0xffe090ce), SS4(0xffe01dc7), SS4(0xffcdc351), SS4(0xf6fb4370),
-    SS4(0xfef84470), SS4(0xffe99b00), SS4(0xfff0b71a), SS4(0x00ec1b8b),
-    SS4(0xf81b8d70), SS4(0xff137330), SS4(0xfff3c74c), SS4(0x0019118b),
-    SS4(0x027c1434), SS4(0xf9c2a8d8), SS4(0xff589157), SS4(0xfffb9ac7)
-};
-
-static const int32_t sbc_proto_8_80m0[] = {
-    SS8(0x00000000), SS8(0xfe8d1970), SS8(0xee979f00), SS8(0x11686100),
-    SS8(0x0172e690), SS8(0xfff5bd1a), SS8(0xfdf1c8d4), SS8(0xeac182c0),
-    SS8(0x0d9daee0), SS8(0x00e530da), SS8(0xffe9811d), SS8(0xfd52986c),
-    SS8(0xe7054ca0), SS8(0x0a00d410), SS8(0x006c1de4), SS8(0xffdba705),
-    SS8(0xfcbc98e8), SS8(0xe3889d20), SS8(0x06af2308), SS8(0x000bb7db),
-    SS8(0xffca00ed), SS8(0xfc3fbb68), SS8(0xe071bc00), SS8(0x03bf7948),
-    SS8(0xffc4e05c), SS8(0xffb54b3b), SS8(0xfbedadc0), SS8(0xdde26200),
-    SS8(0x0142291c), SS8(0xff960e94), SS8(0xff9f3e17), SS8(0xfbd8f358),
-    SS8(0xdbf79400), SS8(0xff405e01), SS8(0xff7d4914), SS8(0xff8b1a31),
-    SS8(0xfc1417b8), SS8(0xdac7bb40), SS8(0xfdbb828c), SS8(0xff762170)
-};
-
-static const int32_t sbc_proto_8_80m1[] = {
-    SS8(0xff7c272c), SS8(0xfcb02620), SS8(0xda612700), SS8(0xfcb02620),
-    SS8(0xff7c272c), SS8(0xff762170), SS8(0xfdbb828c), SS8(0xdac7bb40),
-    SS8(0xfc1417b8), SS8(0xff8b1a31), SS8(0xff7d4914), SS8(0xff405e01),
-    SS8(0xdbf79400), SS8(0xfbd8f358), SS8(0xff9f3e17), SS8(0xff960e94),
-    SS8(0x0142291c), SS8(0xdde26200), SS8(0xfbedadc0), SS8(0xffb54b3b),
-    SS8(0xffc4e05c), SS8(0x03bf7948), SS8(0xe071bc00), SS8(0xfc3fbb68),
-    SS8(0xffca00ed), SS8(0x000bb7db), SS8(0x06af2308), SS8(0xe3889d20),
-    SS8(0xfcbc98e8), SS8(0xffdba705), SS8(0x006c1de4), SS8(0x0a00d410),
-    SS8(0xe7054ca0), SS8(0xfd52986c), SS8(0xffe9811d), SS8(0x00e530da),
-    SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a)
-};
-
-static const int32_t _anamatrix8[8] = {
-    SA8(0x3b20d780), SA8(0x187de2a0), SA8(0x3ec52f80), SA8(0x3536cc40),
-    SA8(0x238e7680), SA8(0x0c7c5c20), SA8(0x2d413cc0), SA8(0x40000000)
-};
-
-static const int32_t synmatrix4[8][4] = {
-    { SN4(0x05a82798), SN4(0xfa57d868), SN4(0xfa57d868), SN4(0x05a82798) },
-    { SN4(0x030fbc54), SN4(0xf89be510), SN4(0x07641af0), SN4(0xfcf043ac) },
-    { SN4(0x00000000), SN4(0x00000000), SN4(0x00000000), SN4(0x00000000) },
-    { SN4(0xfcf043ac), SN4(0x07641af0), SN4(0xf89be510), SN4(0x030fbc54) },
-    { SN4(0xfa57d868), SN4(0x05a82798), SN4(0x05a82798), SN4(0xfa57d868) },
-    { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) },
-    { SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000) },
-    { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) }
-};
-
-static const int32_t synmatrix8[16][8] = {
-    { SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798),
-      SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798) },
-    { SN8(0x0471ced0), SN8(0xf8275a10), SN8(0x018f8b84), SN8(0x06a6d988),
-      SN8(0xf9592678), SN8(0xfe70747c), SN8(0x07d8a5f0), SN8(0xfb8e3130) },
-    { SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac),
-      SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54) },
-    { SN8(0x018f8b84), SN8(0xfb8e3130), SN8(0x06a6d988), SN8(0xf8275a10),
-      SN8(0x07d8a5f0), SN8(0xf9592678), SN8(0x0471ced0), SN8(0xfe70747c) },
-    { SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000),
-      SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000) },
-    { SN8(0xfe70747c), SN8(0x0471ced0), SN8(0xf9592678), SN8(0x07d8a5f0),
-      SN8(0xf8275a10), SN8(0x06a6d988), SN8(0xfb8e3130), SN8(0x018f8b84) },
-    { SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54),
-      SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac) },
-    { SN8(0xfb8e3130), SN8(0x07d8a5f0), SN8(0xfe70747c), SN8(0xf9592678),
-      SN8(0x06a6d988), SN8(0x018f8b84), SN8(0xf8275a10), SN8(0x0471ced0) },
-    { SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868),
-      SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868) },
-    { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
-      SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) },
-    { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
-      SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
-    { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
-      SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
-    { SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000),
-      SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000) },
-    { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
-      SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
-    { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
-      SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
-    { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
-      SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) }
-};
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/formats.h b/rtkbt/code/libbt-vendor/codec/sbc/formats.h
new file mode 100755 (executable)
index 0000000..3050b25
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <byteswap.h>
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define COMPOSE_ID(a,b,c,d)    ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
+#define LE_SHORT(v)            (v)
+#define LE_INT(v)              (v)
+#define BE_SHORT(v)            bswap_16(v)
+#define BE_INT(v)              bswap_32(v)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define COMPOSE_ID(a,b,c,d)    ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
+#define LE_SHORT(v)            bswap_16(v)
+#define LE_INT(v)              bswap_32(v)
+#define BE_SHORT(v)            (v)
+#define BE_INT(v)              (v)
+#else
+#error "Wrong endian"
+#endif
+
+#define AU_MAGIC               COMPOSE_ID('.','s','n','d')
+
+#define AU_FMT_ULAW            1
+#define AU_FMT_LIN8            2
+#define AU_FMT_LIN16           3
+
+struct au_header {
+       uint32_t magic;         /* '.snd' */
+       uint32_t hdr_size;      /* size of header (min 24) */
+       uint32_t data_size;     /* size of data */
+       uint32_t encoding;      /* see to AU_FMT_XXXX */
+       uint32_t sample_rate;   /* sample rate */
+       uint32_t channels;      /* number of channels (voices) */
+};
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc.c b/rtkbt/code/libbt-vendor/codec/sbc/sbc.c
new file mode 100755 (executable)
index 0000000..606f11c
--- /dev/null
@@ -0,0 +1,1505 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2008  Brad Midgley <bmidgley@xmission.com>
+ *  Copyright (C) 2012-2013  Intel Corporation
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include "sbc_math.h"
+#include "sbc_tables.h"
+
+#include "sbc.h"
+#include "sbc_private.h"
+#include "sbc_primitives.h"
+
+#define SBC_SYNCWORD   0x9C
+
+#define MSBC_SYNCWORD  0xAD
+#define MSBC_BLOCKS    15
+
+#define A2DP_SAMPLING_FREQ_16000               (1 << 3)
+#define A2DP_SAMPLING_FREQ_32000               (1 << 2)
+#define A2DP_SAMPLING_FREQ_44100               (1 << 1)
+#define A2DP_SAMPLING_FREQ_48000               (1 << 0)
+
+#define A2DP_CHANNEL_MODE_MONO                 (1 << 3)
+#define A2DP_CHANNEL_MODE_DUAL_CHANNEL         (1 << 2)
+#define A2DP_CHANNEL_MODE_STEREO               (1 << 1)
+#define A2DP_CHANNEL_MODE_JOINT_STEREO         (1 << 0)
+
+#define A2DP_BLOCK_LENGTH_4                    (1 << 3)
+#define A2DP_BLOCK_LENGTH_8                    (1 << 2)
+#define A2DP_BLOCK_LENGTH_12                   (1 << 1)
+#define A2DP_BLOCK_LENGTH_16                   (1 << 0)
+
+#define A2DP_SUBBANDS_4                                (1 << 1)
+#define A2DP_SUBBANDS_8                                (1 << 0)
+
+#define A2DP_ALLOCATION_SNR                    (1 << 1)
+#define A2DP_ALLOCATION_LOUDNESS               (1 << 0)
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct a2dp_sbc {
+       uint8_t channel_mode:4;
+       uint8_t frequency:4;
+       uint8_t allocation_method:2;
+       uint8_t subbands:2;
+       uint8_t block_length:4;
+       uint8_t min_bitpool;
+       uint8_t max_bitpool;
+} __attribute__ ((packed));
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct a2dp_sbc {
+       uint8_t frequency:4;
+       uint8_t channel_mode:4;
+       uint8_t block_length:4;
+       uint8_t subbands:2;
+       uint8_t allocation_method:2;
+       uint8_t min_bitpool;
+       uint8_t max_bitpool;
+} __attribute__ ((packed));
+
+#else
+#error "Unknown byte order"
+#endif
+
+/* This structure contains an unpacked SBC frame.
+   Yes, there is probably quite some unused space herein */
+struct sbc_frame {
+       uint8_t frequency;
+       uint8_t block_mode;
+       uint8_t blocks;
+       enum {
+               MONO            = SBC_MODE_MONO,
+               DUAL_CHANNEL    = SBC_MODE_DUAL_CHANNEL,
+               STEREO          = SBC_MODE_STEREO,
+               JOINT_STEREO    = SBC_MODE_JOINT_STEREO
+       } mode;
+       uint8_t channels;
+       enum {
+               LOUDNESS        = SBC_AM_LOUDNESS,
+               SNR             = SBC_AM_SNR
+       } allocation;
+       uint8_t subband_mode;
+       uint8_t subbands;
+       uint8_t bitpool;
+       uint16_t codesize;
+       uint16_t length;
+
+       /* bit number x set means joint stereo has been used in subband x */
+       uint8_t joint;
+
+       /* only the lower 4 bits of every element are to be used */
+       uint32_t SBC_ALIGNED scale_factor[2][8];
+
+       /* raw integer subband samples in the frame */
+       int32_t SBC_ALIGNED sb_sample_f[16][2][8];
+
+       /* modified subband samples */
+       int32_t SBC_ALIGNED sb_sample[16][2][8];
+
+       /* original pcm audio samples */
+       int16_t SBC_ALIGNED pcm_sample[2][16*8];
+};
+
+struct sbc_decoder_state {
+       int subbands;
+       int32_t V[2][170];
+       int offset[2][16];
+};
+
+/*
+ * Calculates the CRC-8 of the first len bits in data
+ */
+static const uint8_t crc_table[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
+};
+
+static uint8_t sbc_crc8(const uint8_t *data, size_t len)
+{
+       uint8_t crc = 0x0f;
+       size_t i;
+       uint8_t octet;
+
+       for (i = 0; i < len / 8; i++)
+               crc = crc_table[crc ^ data[i]];
+
+       octet = data[i];
+       for (i = 0; i < len % 8; i++) {
+               char bit = ((octet ^ crc) & 0x80) >> 7;
+
+               crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0);
+
+               octet = octet << 1;
+       }
+
+       return crc;
+}
+
+/*
+ * Code straight from the spec to calculate the bits array
+ * Takes a pointer to the frame in question, a pointer to the bits array and
+ * the sampling frequency (as 2 bit integer)
+ */
+static SBC_ALWAYS_INLINE void sbc_calculate_bits_internal(
+               const struct sbc_frame *frame, int (*bits)[8], int subbands)
+{
+       uint8_t sf = frame->frequency;
+
+       if (frame->mode == MONO || frame->mode == DUAL_CHANNEL) {
+               int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice;
+               int ch, sb;
+
+               for (ch = 0; ch < frame->channels; ch++) {
+                       max_bitneed = 0;
+                       if (frame->allocation == SNR) {
+                               for (sb = 0; sb < subbands; sb++) {
+                                       bitneed[ch][sb] = frame->scale_factor[ch][sb];
+                                       if (bitneed[ch][sb] > max_bitneed)
+                                               max_bitneed = bitneed[ch][sb];
+                               }
+                       } else {
+                               for (sb = 0; sb < subbands; sb++) {
+                                       if (frame->scale_factor[ch][sb] == 0)
+                                               bitneed[ch][sb] = -5;
+                                       else {
+                                               if (subbands == 4)
+                                                       loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
+                                               else
+                                                       loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
+                                               if (loudness > 0)
+                                                       bitneed[ch][sb] = loudness / 2;
+                                               else
+                                                       bitneed[ch][sb] = loudness;
+                                       }
+                                       if (bitneed[ch][sb] > max_bitneed)
+                                               max_bitneed = bitneed[ch][sb];
+                               }
+                       }
+
+                       bitcount = 0;
+                       slicecount = 0;
+                       bitslice = max_bitneed + 1;
+                       do {
+                               bitslice--;
+                               bitcount += slicecount;
+                               slicecount = 0;
+                               for (sb = 0; sb < subbands; sb++) {
+                                       if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
+                                               slicecount++;
+                                       else if (bitneed[ch][sb] == bitslice + 1)
+                                               slicecount += 2;
+                               }
+                       } while (bitcount + slicecount < frame->bitpool);
+
+                       if (bitcount + slicecount == frame->bitpool) {
+                               bitcount += slicecount;
+                               bitslice--;
+                       }
+
+                       for (sb = 0; sb < subbands; sb++) {
+                               if (bitneed[ch][sb] < bitslice + 2)
+                                       bits[ch][sb] = 0;
+                               else {
+                                       bits[ch][sb] = bitneed[ch][sb] - bitslice;
+                                       if (bits[ch][sb] > 16)
+                                               bits[ch][sb] = 16;
+                               }
+                       }
+
+                       for (sb = 0; bitcount < frame->bitpool &&
+                                                       sb < subbands; sb++) {
+                               if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) {
+                                       bits[ch][sb]++;
+                                       bitcount++;
+                               } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) {
+                                       bits[ch][sb] = 2;
+                                       bitcount += 2;
+                               }
+                       }
+
+                       for (sb = 0; bitcount < frame->bitpool &&
+                                                       sb < subbands; sb++) {
+                               if (bits[ch][sb] < 16) {
+                                       bits[ch][sb]++;
+                                       bitcount++;
+                               }
+                       }
+
+               }
+
+       } else if (frame->mode == STEREO || frame->mode == JOINT_STEREO) {
+               int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice;
+               int ch, sb;
+
+               max_bitneed = 0;
+               if (frame->allocation == SNR) {
+                       for (ch = 0; ch < 2; ch++) {
+                               for (sb = 0; sb < subbands; sb++) {
+                                       bitneed[ch][sb] = frame->scale_factor[ch][sb];
+                                       if (bitneed[ch][sb] > max_bitneed)
+                                               max_bitneed = bitneed[ch][sb];
+                               }
+                       }
+               } else {
+                       for (ch = 0; ch < 2; ch++) {
+                               for (sb = 0; sb < subbands; sb++) {
+                                       if (frame->scale_factor[ch][sb] == 0)
+                                               bitneed[ch][sb] = -5;
+                                       else {
+                                               if (subbands == 4)
+                                                       loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
+                                               else
+                                                       loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
+                                               if (loudness > 0)
+                                                       bitneed[ch][sb] = loudness / 2;
+                                               else
+                                                       bitneed[ch][sb] = loudness;
+                                       }
+                                       if (bitneed[ch][sb] > max_bitneed)
+                                               max_bitneed = bitneed[ch][sb];
+                               }
+                       }
+               }
+
+               bitcount = 0;
+               slicecount = 0;
+               bitslice = max_bitneed + 1;
+               do {
+                       bitslice--;
+                       bitcount += slicecount;
+                       slicecount = 0;
+                       for (ch = 0; ch < 2; ch++) {
+                               for (sb = 0; sb < subbands; sb++) {
+                                       if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
+                                               slicecount++;
+                                       else if (bitneed[ch][sb] == bitslice + 1)
+                                               slicecount += 2;
+                               }
+                       }
+               } while (bitcount + slicecount < frame->bitpool);
+
+               if (bitcount + slicecount == frame->bitpool) {
+                       bitcount += slicecount;
+                       bitslice--;
+               }
+
+               for (ch = 0; ch < 2; ch++) {
+                       for (sb = 0; sb < subbands; sb++) {
+                               if (bitneed[ch][sb] < bitslice + 2) {
+                                       bits[ch][sb] = 0;
+                               } else {
+                                       bits[ch][sb] = bitneed[ch][sb] - bitslice;
+                                       if (bits[ch][sb] > 16)
+                                               bits[ch][sb] = 16;
+                               }
+                       }
+               }
+
+               ch = 0;
+               sb = 0;
+               while (bitcount < frame->bitpool) {
+                       if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) {
+                               bits[ch][sb]++;
+                               bitcount++;
+                       } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) {
+                               bits[ch][sb] = 2;
+                               bitcount += 2;
+                       }
+                       if (ch == 1) {
+                               ch = 0;
+                               sb++;
+                               if (sb >= subbands)
+                                       break;
+                       } else
+                               ch = 1;
+               }
+
+               ch = 0;
+               sb = 0;
+               while (bitcount < frame->bitpool) {
+                       if (bits[ch][sb] < 16) {
+                               bits[ch][sb]++;
+                               bitcount++;
+                       }
+                       if (ch == 1) {
+                               ch = 0;
+                               sb++;
+                               if (sb >= subbands)
+                                       break;
+                       } else
+                               ch = 1;
+               }
+
+       }
+
+}
+
+static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8])
+{
+       if (frame->subbands == 4)
+               sbc_calculate_bits_internal(frame, bits, 4);
+       else
+               sbc_calculate_bits_internal(frame, bits, 8);
+}
+
+/*
+ * Unpacks a SBC frame at the beginning of the stream in data,
+ * which has at most len bytes into frame.
+ * Returns the length in bytes of the packed frame, or a negative
+ * value on error. The error codes are:
+ *
+ *  -1   Data stream too short
+ *  -2   Sync byte incorrect
+ *  -3   CRC8 incorrect
+ *  -4   Bitpool value out of bounds
+ */
+static int sbc_unpack_frame_internal(const uint8_t *data,
+               struct sbc_frame *frame, size_t len)
+{
+       unsigned int consumed;
+       /* Will copy the parts of the header that are relevant to crc
+        * calculation here */
+       uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+       int crc_pos = 0;
+       int32_t temp;
+
+       uint32_t audio_sample;
+       int ch, sb, blk, bit;   /* channel, subband, block and bit standard
+                                  counters */
+       int bits[2][8];         /* bits distribution */
+       uint32_t levels[2][8];  /* levels derived from that */
+
+       consumed = 32;
+
+       crc_header[0] = data[1];
+       crc_header[1] = data[2];
+       crc_pos = 16;
+
+       if (frame->mode == JOINT_STEREO) {
+               if (len * 8 < consumed + frame->subbands)
+                       return -1;
+
+               frame->joint = 0x00;
+               for (sb = 0; sb < frame->subbands - 1; sb++)
+                       frame->joint |= ((data[4] >> (7 - sb)) & 0x01) << sb;
+               if (frame->subbands == 4)
+                       crc_header[crc_pos / 8] = data[4] & 0xf0;
+               else
+                       crc_header[crc_pos / 8] = data[4];
+
+               consumed += frame->subbands;
+               crc_pos += frame->subbands;
+       }
+
+       if (len * 8 < consumed + (4 * frame->subbands * frame->channels))
+               return -1;
+
+       for (ch = 0; ch < frame->channels; ch++) {
+               for (sb = 0; sb < frame->subbands; sb++) {
+                       /* FIXME assert(consumed % 4 == 0); */
+                       frame->scale_factor[ch][sb] =
+                               (data[consumed >> 3] >> (4 - (consumed & 0x7))) & 0x0F;
+                       crc_header[crc_pos >> 3] |=
+                               frame->scale_factor[ch][sb] << (4 - (crc_pos & 0x7));
+
+                       consumed += 4;
+                       crc_pos += 4;
+               }
+       }
+
+       if (data[3] != sbc_crc8(crc_header, crc_pos))
+               return -3;
+
+       sbc_calculate_bits(frame, bits);
+
+       for (ch = 0; ch < frame->channels; ch++) {
+               for (sb = 0; sb < frame->subbands; sb++)
+                       levels[ch][sb] = (1 << bits[ch][sb]) - 1;
+       }
+
+       for (blk = 0; blk < frame->blocks; blk++) {
+               for (ch = 0; ch < frame->channels; ch++) {
+                       for (sb = 0; sb < frame->subbands; sb++) {
+                               uint32_t shift;
+
+                               if (levels[ch][sb] == 0) {
+                                       frame->sb_sample[blk][ch][sb] = 0;
+                                       continue;
+                               }
+
+                               shift = frame->scale_factor[ch][sb] +
+                                               1 + SBCDEC_FIXED_EXTRA_BITS;
+
+                               audio_sample = 0;
+                               for (bit = 0; bit < bits[ch][sb]; bit++) {
+                                       if (consumed > len * 8)
+                                               return -1;
+
+                                       if ((data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01)
+                                               audio_sample |= 1 << (bits[ch][sb] - bit - 1);
+
+                                       consumed++;
+                               }
+
+                               frame->sb_sample[blk][ch][sb] = (int32_t)
+                                       (((((uint64_t) audio_sample << 1) | 1) << shift) /
+                                       levels[ch][sb]) - (1 << shift);
+                       }
+               }
+       }
+
+       if (frame->mode == JOINT_STEREO) {
+               for (blk = 0; blk < frame->blocks; blk++) {
+                       for (sb = 0; sb < frame->subbands; sb++) {
+                               if (frame->joint & (0x01 << sb)) {
+                                       temp = frame->sb_sample[blk][0][sb] +
+                                               frame->sb_sample[blk][1][sb];
+                                       frame->sb_sample[blk][1][sb] =
+                                               frame->sb_sample[blk][0][sb] -
+                                               frame->sb_sample[blk][1][sb];
+                                       frame->sb_sample[blk][0][sb] = temp;
+                               }
+                       }
+               }
+       }
+
+       if ((consumed & 0x7) != 0)
+               consumed += 8 - (consumed & 0x7);
+
+       return consumed >> 3;
+}
+
+static int sbc_unpack_frame(const uint8_t *data,
+               struct sbc_frame *frame, size_t len)
+{
+       if (len < 4)
+               return -1;
+
+       if (data[0] != SBC_SYNCWORD)
+               return -2;
+
+       frame->frequency = (data[1] >> 6) & 0x03;
+       frame->block_mode = (data[1] >> 4) & 0x03;
+
+       switch (frame->block_mode) {
+       case SBC_BLK_4:
+               frame->blocks = 4;
+               break;
+       case SBC_BLK_8:
+               frame->blocks = 8;
+               break;
+       case SBC_BLK_12:
+               frame->blocks = 12;
+               break;
+       case SBC_BLK_16:
+               frame->blocks = 16;
+               break;
+       }
+
+       frame->mode = (data[1] >> 2) & 0x03;
+
+       switch (frame->mode) {
+       case MONO:
+               frame->channels = 1;
+               break;
+       case DUAL_CHANNEL:      /* fall-through */
+       case STEREO:
+       case JOINT_STEREO:
+               frame->channels = 2;
+               break;
+       }
+
+       frame->allocation = (data[1] >> 1) & 0x01;
+
+       frame->subband_mode = (data[1] & 0x01);
+       frame->subbands = frame->subband_mode ? 8 : 4;
+
+       frame->bitpool = data[2];
+
+       if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+                       frame->bitpool > 16 * frame->subbands)
+               return -4;
+
+       if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+                       frame->bitpool > 32 * frame->subbands)
+               return -4;
+
+       return sbc_unpack_frame_internal(data, frame, len);
+}
+
+static int msbc_unpack_frame(const uint8_t *data,
+               struct sbc_frame *frame, size_t len)
+{
+       if (len < 4)
+               return -1;
+
+       if (data[0] != MSBC_SYNCWORD)
+               return -2;
+       if (data[1] != 0)
+               return -2;
+       if (data[2] != 0)
+               return -2;
+
+       frame->frequency = SBC_FREQ_16000;
+       frame->block_mode = SBC_BLK_4;
+       frame->blocks = MSBC_BLOCKS;
+       frame->allocation = LOUDNESS;
+       frame->mode = MONO;
+       frame->channels = 1;
+       frame->subband_mode = 1;
+       frame->subbands = 8;
+       frame->bitpool = 26;
+
+       return sbc_unpack_frame_internal(data, frame, len);
+}
+
+static void sbc_decoder_init(struct sbc_decoder_state *state,
+                                       const struct sbc_frame *frame)
+{
+       int i, ch;
+
+       memset(state->V, 0, sizeof(state->V));
+       state->subbands = frame->subbands;
+
+       for (ch = 0; ch < 2; ch++)
+               for (i = 0; i < frame->subbands * 2; i++)
+                       state->offset[ch][i] = (10 * i + 10);
+}
+
+static SBC_ALWAYS_INLINE int16_t sbc_clip16(int32_t s)
+{
+       if (s > 0x7FFF)
+               return 0x7FFF;
+       else if (s < -0x8000)
+               return -0x8000;
+       else
+               return s;
+}
+
+static inline void sbc_synthesize_four(struct sbc_decoder_state *state,
+                               struct sbc_frame *frame, int ch, int blk)
+{
+       int i, k, idx;
+       int32_t *v = state->V[ch];
+       int *offset = state->offset[ch];
+
+       for (i = 0; i < 8; i++) {
+               /* Shifting */
+               offset[i]--;
+               if (offset[i] < 0) {
+                       offset[i] = 79;
+                       memcpy(v + 80, v, 9 * sizeof(*v));
+               }
+
+               /* Distribute the new matrix value to the shifted position */
+               v[offset[i]] = SCALE4_STAGED1(
+                       MULA(synmatrix4[i][0], frame->sb_sample[blk][ch][0],
+                       MULA(synmatrix4[i][1], frame->sb_sample[blk][ch][1],
+                       MULA(synmatrix4[i][2], frame->sb_sample[blk][ch][2],
+                       MUL (synmatrix4[i][3], frame->sb_sample[blk][ch][3])))));
+       }
+
+       /* Compute the samples */
+       for (idx = 0, i = 0; i < 4; i++, idx += 5) {
+               k = (i + 4) & 0xf;
+
+               /* Store in output, Q0 */
+               frame->pcm_sample[ch][blk * 4 + i] = sbc_clip16(SCALE4_STAGED1(
+                       MULA(v[offset[i] + 0], sbc_proto_4_40m0[idx + 0],
+                       MULA(v[offset[k] + 1], sbc_proto_4_40m1[idx + 0],
+                       MULA(v[offset[i] + 2], sbc_proto_4_40m0[idx + 1],
+                       MULA(v[offset[k] + 3], sbc_proto_4_40m1[idx + 1],
+                       MULA(v[offset[i] + 4], sbc_proto_4_40m0[idx + 2],
+                       MULA(v[offset[k] + 5], sbc_proto_4_40m1[idx + 2],
+                       MULA(v[offset[i] + 6], sbc_proto_4_40m0[idx + 3],
+                       MULA(v[offset[k] + 7], sbc_proto_4_40m1[idx + 3],
+                       MULA(v[offset[i] + 8], sbc_proto_4_40m0[idx + 4],
+                       MUL( v[offset[k] + 9], sbc_proto_4_40m1[idx + 4]))))))))))));
+       }
+}
+
+static inline void sbc_synthesize_eight(struct sbc_decoder_state *state,
+                               struct sbc_frame *frame, int ch, int blk)
+{
+       int i, j, k, idx;
+       int *offset = state->offset[ch];
+
+       for (i = 0; i < 16; i++) {
+               /* Shifting */
+               offset[i]--;
+               if (offset[i] < 0) {
+                       offset[i] = 159;
+                       for (j = 0; j < 9; j++)
+                               state->V[ch][j + 160] = state->V[ch][j];
+               }
+
+               /* Distribute the new matrix value to the shifted position */
+               state->V[ch][offset[i]] = SCALE8_STAGED1(
+                       MULA(synmatrix8[i][0], frame->sb_sample[blk][ch][0],
+                       MULA(synmatrix8[i][1], frame->sb_sample[blk][ch][1],
+                       MULA(synmatrix8[i][2], frame->sb_sample[blk][ch][2],
+                       MULA(synmatrix8[i][3], frame->sb_sample[blk][ch][3],
+                       MULA(synmatrix8[i][4], frame->sb_sample[blk][ch][4],
+                       MULA(synmatrix8[i][5], frame->sb_sample[blk][ch][5],
+                       MULA(synmatrix8[i][6], frame->sb_sample[blk][ch][6],
+                       MUL( synmatrix8[i][7], frame->sb_sample[blk][ch][7])))))))));
+       }
+
+       /* Compute the samples */
+       for (idx = 0, i = 0; i < 8; i++, idx += 5) {
+               k = (i + 8) & 0xf;
+
+               /* Store in output, Q0 */
+               frame->pcm_sample[ch][blk * 8 + i] = sbc_clip16(SCALE8_STAGED1(
+                       MULA(state->V[ch][offset[i] + 0], sbc_proto_8_80m0[idx + 0],
+                       MULA(state->V[ch][offset[k] + 1], sbc_proto_8_80m1[idx + 0],
+                       MULA(state->V[ch][offset[i] + 2], sbc_proto_8_80m0[idx + 1],
+                       MULA(state->V[ch][offset[k] + 3], sbc_proto_8_80m1[idx + 1],
+                       MULA(state->V[ch][offset[i] + 4], sbc_proto_8_80m0[idx + 2],
+                       MULA(state->V[ch][offset[k] + 5], sbc_proto_8_80m1[idx + 2],
+                       MULA(state->V[ch][offset[i] + 6], sbc_proto_8_80m0[idx + 3],
+                       MULA(state->V[ch][offset[k] + 7], sbc_proto_8_80m1[idx + 3],
+                       MULA(state->V[ch][offset[i] + 8], sbc_proto_8_80m0[idx + 4],
+                       MUL( state->V[ch][offset[k] + 9], sbc_proto_8_80m1[idx + 4]))))))))))));
+       }
+}
+
+static int sbc_synthesize_audio(struct sbc_decoder_state *state,
+                                               struct sbc_frame *frame)
+{
+       int ch, blk;
+
+       switch (frame->subbands) {
+       case 4:
+               for (ch = 0; ch < frame->channels; ch++) {
+                       for (blk = 0; blk < frame->blocks; blk++)
+                               sbc_synthesize_four(state, frame, ch, blk);
+               }
+               return frame->blocks * 4;
+
+       case 8:
+               for (ch = 0; ch < frame->channels; ch++) {
+                       for (blk = 0; blk < frame->blocks; blk++)
+                               sbc_synthesize_eight(state, frame, ch, blk);
+               }
+               return frame->blocks * 8;
+
+       default:
+               return -EIO;
+       }
+}
+
+static int sbc_analyze_audio(struct sbc_encoder_state *state,
+                                               struct sbc_frame *frame)
+{
+       int ch, blk;
+       int16_t *x;
+
+       switch (frame->subbands) {
+       case 4:
+               for (ch = 0; ch < frame->channels; ch++) {
+                       x = &state->X[ch][state->position - 4 *
+                                       state->increment + frame->blocks * 4];
+                       for (blk = 0; blk < frame->blocks;
+                                               blk += state->increment) {
+                               state->sbc_analyze_4s(
+                                       state, x,
+                                       frame->sb_sample_f[blk][ch],
+                                       frame->sb_sample_f[blk + 1][ch] -
+                                       frame->sb_sample_f[blk][ch]);
+                               x -= 4 * state->increment;
+                       }
+               }
+               return frame->blocks * 4;
+
+       case 8:
+               for (ch = 0; ch < frame->channels; ch++) {
+                       x = &state->X[ch][state->position - 8 *
+                                       state->increment + frame->blocks * 8];
+                       for (blk = 0; blk < frame->blocks;
+                                               blk += state->increment) {
+                               state->sbc_analyze_8s(
+                                       state, x,
+                                       frame->sb_sample_f[blk][ch],
+                                       frame->sb_sample_f[blk + 1][ch] -
+                                       frame->sb_sample_f[blk][ch]);
+                               x -= 8 * state->increment;
+                       }
+               }
+               return frame->blocks * 8;
+
+       default:
+               return -EIO;
+       }
+}
+
+/* Supplementary bitstream writing macros for 'sbc_pack_frame' */
+
+#define PUT_BITS(data_ptr, bits_cache, bits_count, v, n)               \
+       do {                                                            \
+               bits_cache = (v) | (bits_cache << (n));                 \
+               bits_count += (n);                                      \
+               if (bits_count >= 16) {                                 \
+                       bits_count -= 8;                                \
+                       *data_ptr++ = (uint8_t)                         \
+                               (bits_cache >> bits_count);             \
+                       bits_count -= 8;                                \
+                       *data_ptr++ = (uint8_t)                         \
+                               (bits_cache >> bits_count);             \
+               }                                                       \
+       } while (0)
+
+#define FLUSH_BITS(data_ptr, bits_cache, bits_count)                   \
+       do {                                                            \
+               while (bits_count >= 8) {                               \
+                       bits_count -= 8;                                \
+                       *data_ptr++ = (uint8_t)                         \
+                               (bits_cache >> bits_count);             \
+               }                                                       \
+               if (bits_count > 0)                                     \
+                       *data_ptr++ = (uint8_t)                         \
+                               (bits_cache << (8 - bits_count));       \
+       } while (0)
+
+/*
+ * Packs the SBC frame from frame into the memory at data. At most len
+ * bytes will be used, should more memory be needed an appropriate
+ * error code will be returned. Returns the length of the packed frame
+ * on success or a negative value on error.
+ *
+ * The error codes are:
+ * -1 Not enough memory reserved
+ * -2 Unsupported sampling rate
+ * -3 Unsupported number of blocks
+ * -4 Unsupported number of subbands
+ * -5 Bitpool value out of bounds
+ * -99 not implemented
+ */
+
+static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(uint8_t *data,
+                                       struct sbc_frame *frame, size_t len,
+                                       int frame_subbands, int frame_channels,
+                                       int joint)
+{
+       /* Bitstream writer starts from the fourth byte */
+       uint8_t *data_ptr = data + 4;
+       uint32_t bits_cache = 0;
+       uint32_t bits_count = 0;
+
+       /* Will copy the header parts for CRC-8 calculation here */
+       uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+       int crc_pos = 0;
+
+       uint32_t audio_sample;
+
+       int ch, sb, blk;        /* channel, subband, block and bit counters */
+       int bits[2][8];         /* bits distribution */
+       uint32_t levels[2][8];  /* levels are derived from that */
+       uint32_t sb_sample_delta[2][8];
+
+       /* Can't fill in crc yet */
+
+       crc_header[0] = data[1];
+       crc_header[1] = data[2];
+       crc_pos = 16;
+
+       if (frame->mode == JOINT_STEREO) {
+               PUT_BITS(data_ptr, bits_cache, bits_count,
+                       joint, frame_subbands);
+               crc_header[crc_pos >> 3] = joint;
+               crc_pos += frame_subbands;
+       }
+
+       for (ch = 0; ch < frame_channels; ch++) {
+               for (sb = 0; sb < frame_subbands; sb++) {
+                       PUT_BITS(data_ptr, bits_cache, bits_count,
+                               frame->scale_factor[ch][sb] & 0x0F, 4);
+                       crc_header[crc_pos >> 3] <<= 4;
+                       crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] & 0x0F;
+                       crc_pos += 4;
+               }
+       }
+
+       /* align the last crc byte */
+       if (crc_pos % 8)
+               crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8);
+
+       data[3] = sbc_crc8(crc_header, crc_pos);
+
+       sbc_calculate_bits(frame, bits);
+
+       for (ch = 0; ch < frame_channels; ch++) {
+               for (sb = 0; sb < frame_subbands; sb++) {
+                       levels[ch][sb] = ((1 << bits[ch][sb]) - 1) <<
+                               (32 - (frame->scale_factor[ch][sb] +
+                                       SCALE_OUT_BITS + 2));
+                       sb_sample_delta[ch][sb] = (uint32_t) 1 <<
+                               (frame->scale_factor[ch][sb] +
+                                       SCALE_OUT_BITS + 1);
+               }
+       }
+
+       for (blk = 0; blk < frame->blocks; blk++) {
+               for (ch = 0; ch < frame_channels; ch++) {
+                       for (sb = 0; sb < frame_subbands; sb++) {
+
+                               if (bits[ch][sb] == 0)
+                                       continue;
+
+                               audio_sample = ((uint64_t) levels[ch][sb] *
+                                       (sb_sample_delta[ch][sb] +
+                                       frame->sb_sample_f[blk][ch][sb])) >> 32;
+
+                               PUT_BITS(data_ptr, bits_cache, bits_count,
+                                       audio_sample, bits[ch][sb]);
+                       }
+               }
+       }
+
+       FLUSH_BITS(data_ptr, bits_cache, bits_count);
+
+       return data_ptr - data;
+}
+
+static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len,
+                                                               int joint)
+{
+       int frame_subbands = 4;
+
+       data[0] = SBC_SYNCWORD;
+
+       data[1] = (frame->frequency & 0x03) << 6;
+       data[1] |= (frame->block_mode & 0x03) << 4;
+       data[1] |= (frame->mode & 0x03) << 2;
+       data[1] |= (frame->allocation & 0x01) << 1;
+
+       data[2] = frame->bitpool;
+
+       if (frame->subbands != 4)
+               frame_subbands = 8;
+
+       if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+                       frame->bitpool > frame_subbands << 4)
+               return -5;
+
+       if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+                       frame->bitpool > frame_subbands << 5)
+               return -5;
+
+       if (frame->subbands == 4) {
+               if (frame->channels == 1)
+                       return sbc_pack_frame_internal(
+                               data, frame, len, 4, 1, joint);
+               else
+                       return sbc_pack_frame_internal(
+                               data, frame, len, 4, 2, joint);
+       } else {
+               data[1] |= 0x01;
+               if (frame->channels == 1)
+                       return sbc_pack_frame_internal(
+                               data, frame, len, 8, 1, joint);
+               else
+                       return sbc_pack_frame_internal(
+                               data, frame, len, 8, 2, joint);
+       }
+}
+
+static ssize_t msbc_pack_frame(uint8_t *data, struct sbc_frame *frame,
+                                               size_t len, int joint)
+{
+       data[0] = MSBC_SYNCWORD;
+       data[1] = 0;
+       data[2] = 0;
+
+       return sbc_pack_frame_internal(data, frame, len, 8, 1, joint);
+}
+
+static void sbc_encoder_init(bool msbc, struct sbc_encoder_state *state,
+                                               const struct sbc_frame *frame)
+{
+       memset(&state->X, 0, sizeof(state->X));
+       state->position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7;
+       if (msbc)
+               state->increment = 1;
+       else
+               state->increment = 4;
+
+       sbc_init_primitives(state);
+}
+
+struct sbc_priv {
+       bool init;
+       bool msbc;
+       struct SBC_ALIGNED sbc_frame frame;
+       struct SBC_ALIGNED sbc_decoder_state dec_state;
+       struct SBC_ALIGNED sbc_encoder_state enc_state;
+       int (*unpack_frame)(const uint8_t *data, struct sbc_frame *frame,
+                       size_t len);
+       ssize_t (*pack_frame)(uint8_t *data, struct sbc_frame *frame,
+                       size_t len, int joint);
+};
+
+static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
+{
+       struct sbc_priv *priv = sbc->priv;
+
+       if (priv->msbc) {
+               priv->pack_frame = msbc_pack_frame;
+               priv->unpack_frame = msbc_unpack_frame;
+       } else {
+               priv->pack_frame = sbc_pack_frame;
+               priv->unpack_frame = sbc_unpack_frame;
+       }
+
+       sbc->flags = flags;
+       sbc->frequency = SBC_FREQ_44100;
+       sbc->mode = SBC_MODE_STEREO;
+       sbc->subbands = SBC_SB_8;
+       sbc->blocks = SBC_BLK_16;
+       sbc->bitpool = 32;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+       sbc->endian = SBC_LE;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+       sbc->endian = SBC_BE;
+#else
+#error "Unknown byte order"
+#endif
+}
+
+SBC_EXPORT int sbc_init(sbc_t *sbc, unsigned long flags)
+{
+       if (!sbc)
+               return -EIO;
+
+       memset(sbc, 0, sizeof(sbc_t));
+
+       sbc->priv_alloc_base = malloc(sizeof(struct sbc_priv) + SBC_ALIGN_MASK);
+       if (!sbc->priv_alloc_base)
+               return -ENOMEM;
+
+       sbc->priv = (void *) (((uintptr_t) sbc->priv_alloc_base +
+                       SBC_ALIGN_MASK) & ~((uintptr_t) SBC_ALIGN_MASK));
+
+       memset(sbc->priv, 0, sizeof(struct sbc_priv));
+
+       sbc_set_defaults(sbc, flags);
+
+       return 0;
+}
+
+SBC_EXPORT int sbc_init_msbc(sbc_t *sbc, unsigned long flags)
+{
+       struct sbc_priv *priv;
+
+       if (!sbc)
+               return -EIO;
+
+       memset(sbc, 0, sizeof(sbc_t));
+
+       sbc->priv_alloc_base = malloc(sizeof(struct sbc_priv) + SBC_ALIGN_MASK);
+       if (!sbc->priv_alloc_base)
+               return -ENOMEM;
+
+       sbc->priv = (void *) (((uintptr_t) sbc->priv_alloc_base +
+                       SBC_ALIGN_MASK) & ~((uintptr_t) SBC_ALIGN_MASK));
+
+       memset(sbc->priv, 0, sizeof(struct sbc_priv));
+
+       priv = sbc->priv;
+       priv->msbc = true;
+
+       sbc_set_defaults(sbc, flags);
+
+       sbc->frequency = SBC_FREQ_16000;
+       sbc->blocks = MSBC_BLOCKS;
+       sbc->subbands = SBC_SB_8;
+       sbc->mode = SBC_MODE_MONO;
+       sbc->allocation = SBC_AM_LOUDNESS;
+       sbc->bitpool = 26;
+
+       return 0;
+}
+
+static int sbc_set_a2dp(sbc_t *sbc, unsigned long flags,
+                                       const void *conf, size_t conf_len)
+{
+       const struct a2dp_sbc *a2dp;
+
+       if (conf_len != sizeof(*a2dp))
+               return -EINVAL;
+
+       a2dp = conf;
+
+       switch (a2dp->frequency) {
+       case A2DP_SAMPLING_FREQ_16000:
+               sbc->frequency = SBC_FREQ_16000;
+               break;
+       case A2DP_SAMPLING_FREQ_32000:
+               sbc->frequency = SBC_FREQ_32000;
+               break;
+       case A2DP_SAMPLING_FREQ_44100:
+               sbc->frequency = SBC_FREQ_44100;
+               break;
+       case A2DP_SAMPLING_FREQ_48000:
+               sbc->frequency = SBC_FREQ_48000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (a2dp->channel_mode) {
+       case A2DP_CHANNEL_MODE_MONO:
+               sbc->mode = SBC_MODE_MONO;
+               break;
+       case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
+               sbc->mode = SBC_MODE_DUAL_CHANNEL;
+               break;
+       case A2DP_CHANNEL_MODE_STEREO:
+               sbc->mode = SBC_MODE_STEREO;
+               break;
+       case A2DP_CHANNEL_MODE_JOINT_STEREO:
+               sbc->mode = SBC_MODE_JOINT_STEREO;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (a2dp->allocation_method) {
+       case A2DP_ALLOCATION_SNR:
+               sbc->allocation = SBC_AM_SNR;
+               break;
+       case A2DP_ALLOCATION_LOUDNESS:
+               sbc->allocation = SBC_AM_LOUDNESS;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (a2dp->subbands) {
+       case A2DP_SUBBANDS_4:
+               sbc->subbands = SBC_SB_4;
+               break;
+       case A2DP_SUBBANDS_8:
+               sbc->subbands = SBC_SB_8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (a2dp->block_length) {
+       case A2DP_BLOCK_LENGTH_4:
+               sbc->blocks = SBC_BLK_4;
+               break;
+       case A2DP_BLOCK_LENGTH_8:
+               sbc->blocks = SBC_BLK_8;
+               break;
+       case A2DP_BLOCK_LENGTH_12:
+               sbc->blocks = SBC_BLK_12;
+               break;
+       case A2DP_BLOCK_LENGTH_16:
+               sbc->blocks = SBC_BLK_16;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+SBC_EXPORT int sbc_init_a2dp(sbc_t *sbc, unsigned long flags,
+                                       const void *conf, size_t conf_len)
+{
+       int err;
+
+       err = sbc_init(sbc, flags);
+       if (err < 0)
+               return err;
+
+       err = sbc_set_a2dp(sbc, flags, conf, conf_len);
+       if (err < 0) {
+               sbc_finish(sbc);
+               return err;
+       }
+
+       return 0;
+}
+
+int sbc_reinit_a2dp(sbc_t *sbc, unsigned long flags,
+                                       const void *conf, size_t conf_len)
+{
+       int err;
+
+       err = sbc_reinit(sbc, flags);
+       if (err < 0)
+               return err;
+
+       return sbc_set_a2dp(sbc, flags, conf, conf_len);
+}
+
+SBC_EXPORT ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len)
+{
+       return sbc_decode(sbc, input, input_len, NULL, 0, NULL);
+}
+
+SBC_EXPORT ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
+                       void *output, size_t output_len, size_t *written)
+{
+       struct sbc_priv *priv;
+       char *ptr;
+       int i, ch, framelen, samples;
+
+       if (!sbc || !input)
+               return -EIO;
+
+       priv = sbc->priv;
+
+       framelen = priv->unpack_frame(input, &priv->frame, input_len);
+
+       if (!priv->init) {
+               sbc_decoder_init(&priv->dec_state, &priv->frame);
+               priv->init = true;
+
+               sbc->frequency = priv->frame.frequency;
+               sbc->mode = priv->frame.mode;
+               sbc->subbands = priv->frame.subband_mode;
+               sbc->blocks = priv->frame.block_mode;
+               sbc->allocation = priv->frame.allocation;
+               sbc->bitpool = priv->frame.bitpool;
+
+               priv->frame.codesize = sbc_get_codesize(sbc);
+               priv->frame.length = framelen;
+       } else if (priv->frame.bitpool != sbc->bitpool) {
+               priv->frame.length = framelen;
+               sbc->bitpool = priv->frame.bitpool;
+       }
+
+       if (!output)
+               return framelen;
+
+       if (written)
+               *written = 0;
+
+       if (framelen <= 0)
+               return framelen;
+
+       samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame);
+
+       ptr = output;
+
+       if (output_len < (size_t) (samples * priv->frame.channels * 2))
+               samples = output_len / (priv->frame.channels * 2);
+
+       for (i = 0; i < samples; i++) {
+               for (ch = 0; ch < priv->frame.channels; ch++) {
+                       int16_t s;
+                       s = priv->frame.pcm_sample[ch][i];
+
+                       if (sbc->endian == SBC_BE) {
+                               *ptr++ = (s & 0xff00) >> 8;
+                               *ptr++ = (s & 0x00ff);
+                       } else {
+                               *ptr++ = (s & 0x00ff);
+                               *ptr++ = (s & 0xff00) >> 8;
+                       }
+               }
+       }
+
+       if (written)
+               *written = samples * priv->frame.channels * 2;
+
+       return framelen;
+}
+
+SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
+                       void *output, size_t output_len, ssize_t *written)
+{
+       struct sbc_priv *priv;
+       int samples;
+       ssize_t framelen;
+       int (*sbc_enc_process_input)(int position,
+                       const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+                       int nsamples, int nchannels);
+
+       if (!sbc || !input)
+               return -EIO;
+
+       priv = sbc->priv;
+
+       if (written)
+               *written = 0;
+
+       if (!priv->init) {
+               priv->frame.frequency = sbc->frequency;
+               priv->frame.mode = sbc->mode;
+               priv->frame.channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+               priv->frame.allocation = sbc->allocation;
+               priv->frame.subband_mode = sbc->subbands;
+               priv->frame.subbands = sbc->subbands ? 8 : 4;
+               priv->frame.block_mode = sbc->blocks;
+               if (priv->msbc)
+                       priv->frame.blocks = MSBC_BLOCKS;
+               else
+                       priv->frame.blocks = 4 + (sbc->blocks * 4);
+               priv->frame.bitpool = sbc->bitpool;
+               priv->frame.codesize = sbc_get_codesize(sbc);
+               priv->frame.length = sbc_get_frame_length(sbc);
+
+               sbc_encoder_init(priv->msbc, &priv->enc_state, &priv->frame);
+               priv->init = true;
+       } else if (priv->frame.bitpool != sbc->bitpool) {
+               priv->frame.length = sbc_get_frame_length(sbc);
+               priv->frame.bitpool = sbc->bitpool;
+       }
+
+       /* input must be large enough to encode a complete frame */
+       if (input_len < priv->frame.codesize)
+               return 0;
+
+       /* output must be large enough to receive the encoded frame */
+       if (!output || output_len < priv->frame.length)
+               return -ENOSPC;
+
+       /* Select the needed input data processing function and call it */
+       if (priv->frame.subbands == 8) {
+               if (sbc->endian == SBC_BE)
+                       sbc_enc_process_input =
+                               priv->enc_state.sbc_enc_process_input_8s_be;
+               else
+                       sbc_enc_process_input =
+                               priv->enc_state.sbc_enc_process_input_8s_le;
+       } else {
+               if (sbc->endian == SBC_BE)
+                       sbc_enc_process_input =
+                               priv->enc_state.sbc_enc_process_input_4s_be;
+               else
+                       sbc_enc_process_input =
+                               priv->enc_state.sbc_enc_process_input_4s_le;
+       }
+
+       priv->enc_state.position = sbc_enc_process_input(
+               priv->enc_state.position, (const uint8_t *) input,
+               priv->enc_state.X, priv->frame.subbands * priv->frame.blocks,
+               priv->frame.channels);
+
+       samples = sbc_analyze_audio(&priv->enc_state, &priv->frame);
+
+       if (priv->frame.mode == JOINT_STEREO) {
+               int j = priv->enc_state.sbc_calc_scalefactors_j(
+                       priv->frame.sb_sample_f, priv->frame.scale_factor,
+                       priv->frame.blocks, priv->frame.subbands);
+               framelen = priv->pack_frame(output,
+                               &priv->frame, output_len, j);
+       } else {
+               priv->enc_state.sbc_calc_scalefactors(
+                       priv->frame.sb_sample_f, priv->frame.scale_factor,
+                       priv->frame.blocks, priv->frame.channels,
+                       priv->frame.subbands);
+               framelen = priv->pack_frame(output,
+                               &priv->frame, output_len, 0);
+       }
+
+       if (written)
+               *written = framelen;
+
+       return samples * priv->frame.channels * 2;
+}
+
+SBC_EXPORT void sbc_finish(sbc_t *sbc)
+{
+       if (!sbc)
+               return;
+
+       free(sbc->priv_alloc_base);
+
+       memset(sbc, 0, sizeof(sbc_t));
+}
+
+SBC_EXPORT size_t sbc_get_frame_length(sbc_t *sbc)
+{
+       int ret;
+       uint8_t subbands, channels, blocks, joint, bitpool;
+       struct sbc_priv *priv;
+
+       priv = sbc->priv;
+       if (priv->init && priv->frame.bitpool == sbc->bitpool)
+               return priv->frame.length;
+
+       subbands = sbc->subbands ? 8 : 4;
+       if (priv->msbc)
+               blocks = MSBC_BLOCKS;
+       else
+               blocks = 4 + (sbc->blocks * 4);
+       channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+       joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0;
+       bitpool = sbc->bitpool;
+
+       ret = 4 + (4 * subbands * channels) / 8;
+       /* This term is not always evenly divide so we round it up */
+       if (channels == 1 || sbc->mode == SBC_MODE_DUAL_CHANNEL)
+               ret += ((blocks * channels * bitpool) + 7) / 8;
+       else
+               ret += (((joint ? subbands : 0) + blocks * bitpool) + 7) / 8;
+
+       return ret;
+}
+
+SBC_EXPORT unsigned sbc_get_frame_duration(sbc_t *sbc)
+{
+       uint8_t subbands, blocks;
+       uint16_t frequency;
+       struct sbc_priv *priv;
+
+       priv = sbc->priv;
+       if (!priv->init) {
+               subbands = sbc->subbands ? 8 : 4;
+               if (priv->msbc)
+                       blocks = MSBC_BLOCKS;
+               else
+                       blocks = 4 + (sbc->blocks * 4);
+       } else {
+               subbands = priv->frame.subbands;
+               blocks = priv->frame.blocks;
+       }
+
+       switch (sbc->frequency) {
+       case SBC_FREQ_16000:
+               frequency = 16000;
+               break;
+
+       case SBC_FREQ_32000:
+               frequency = 32000;
+               break;
+
+       case SBC_FREQ_44100:
+               frequency = 44100;
+               break;
+
+       case SBC_FREQ_48000:
+               frequency = 48000;
+               break;
+       default:
+               return 0;
+       }
+
+       return (1000000 * blocks * subbands) / frequency;
+}
+
+SBC_EXPORT size_t sbc_get_codesize(sbc_t *sbc)
+{
+       uint16_t subbands, channels, blocks;
+       struct sbc_priv *priv;
+
+       priv = sbc->priv;
+       if (!priv->init) {
+               subbands = sbc->subbands ? 8 : 4;
+               if (priv->msbc)
+                       blocks = MSBC_BLOCKS;
+               else
+                       blocks = 4 + (sbc->blocks * 4);
+               channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+       } else {
+               subbands = priv->frame.subbands;
+               blocks = priv->frame.blocks;
+               channels = priv->frame.channels;
+       }
+
+       return subbands * blocks * channels * 2;
+}
+
+SBC_EXPORT const char *sbc_get_implementation_info(sbc_t *sbc)
+{
+       struct sbc_priv *priv;
+
+       if (!sbc)
+               return NULL;
+
+       priv = sbc->priv;
+       if (!priv)
+               return NULL;
+
+       return priv->enc_state.implementation_info;
+}
+
+SBC_EXPORT int sbc_reinit(sbc_t *sbc, unsigned long flags)
+{
+       struct sbc_priv *priv;
+
+       if (!sbc || !sbc->priv)
+               return -EIO;
+
+       priv = sbc->priv;
+
+       if (priv->init)
+               memset(sbc->priv, 0, sizeof(struct sbc_priv));
+
+       sbc_set_defaults(sbc, flags);
+
+       return 0;
+}
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc.h b/rtkbt/code/libbt-vendor/codec/sbc/sbc.h
new file mode 100755 (executable)
index 0000000..d6f123e
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2012-2014  Intel Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __SBC_H
+#define __SBC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <sys/types.h>
+
+/* sampling frequency */
+#define SBC_FREQ_16000         0x00
+#define SBC_FREQ_32000         0x01
+#define SBC_FREQ_44100         0x02
+#define SBC_FREQ_48000         0x03
+
+/* blocks */
+#define SBC_BLK_4              0x00
+#define SBC_BLK_8              0x01
+#define SBC_BLK_12             0x02
+#define SBC_BLK_16             0x03
+
+/* channel mode */
+#define SBC_MODE_MONO          0x00
+#define SBC_MODE_DUAL_CHANNEL  0x01
+#define SBC_MODE_STEREO                0x02
+#define SBC_MODE_JOINT_STEREO  0x03
+
+/* allocation method */
+#define SBC_AM_LOUDNESS                0x00
+#define SBC_AM_SNR             0x01
+
+/* subbands */
+#define SBC_SB_4               0x00
+#define SBC_SB_8               0x01
+
+/* data endianess */
+#define SBC_LE                 0x00
+#define SBC_BE                 0x01
+
+struct sbc_struct {
+       unsigned long flags;
+
+       uint8_t frequency;
+       uint8_t blocks;
+       uint8_t subbands;
+       uint8_t mode;
+       uint8_t allocation;
+       uint8_t bitpool;
+       uint8_t endian;
+
+       void *priv;
+       void *priv_alloc_base;
+};
+
+typedef struct sbc_struct sbc_t;
+
+int sbc_init(sbc_t *sbc, unsigned long flags);
+int sbc_reinit(sbc_t *sbc, unsigned long flags);
+int sbc_init_msbc(sbc_t *sbc, unsigned long flags);
+int sbc_init_a2dp(sbc_t *sbc, unsigned long flags,
+                                       const void *conf, size_t conf_len);
+int sbc_reinit_a2dp(sbc_t *sbc, unsigned long flags,
+                                       const void *conf, size_t conf_len);
+
+ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len);
+
+/* Decodes ONE input block into ONE output block */
+ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
+                       void *output, size_t output_len, size_t *written);
+
+/* Encodes ONE input block into ONE output block */
+ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
+                       void *output, size_t output_len, ssize_t *written);
+
+/* Returns the output block size in bytes */
+size_t sbc_get_frame_length(sbc_t *sbc);
+
+/* Returns the time one input/output block takes to play in msec*/
+unsigned sbc_get_frame_duration(sbc_t *sbc);
+
+/* Returns the input block size in bytes */
+size_t sbc_get_codesize(sbc_t *sbc);
+
+const char *sbc_get_implementation_info(sbc_t *sbc);
+void sbc_finish(sbc_t *sbc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SBC_H */
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_math.h b/rtkbt/code/libbt-vendor/codec/sbc/sbc_math.h
new file mode 100755 (executable)
index 0000000..5476860
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2008  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define fabs(x) ((x) < 0 ? -(x) : (x))
+/* C does not provide an explicit arithmetic shift right but this will
+   always be correct and every compiler *should* generate optimal code */
+#define ASR(val, bits) ((-2 >> 1 == -1) ? \
+                ((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits)))
+
+#define SCALE_SPROTO4_TBL      12
+#define SCALE_SPROTO8_TBL      14
+#define SCALE_NPROTO4_TBL      11
+#define SCALE_NPROTO8_TBL      11
+#define SCALE4_STAGED1_BITS    15
+#define SCALE4_STAGED2_BITS    16
+#define SCALE8_STAGED1_BITS    15
+#define SCALE8_STAGED2_BITS    16
+
+typedef int32_t sbc_fixed_t;
+
+#define SCALE4_STAGED1(src) ASR(src, SCALE4_STAGED1_BITS)
+#define SCALE4_STAGED2(src) ASR(src, SCALE4_STAGED2_BITS)
+#define SCALE8_STAGED1(src) ASR(src, SCALE8_STAGED1_BITS)
+#define SCALE8_STAGED2(src) ASR(src, SCALE8_STAGED2_BITS)
+
+#define SBC_FIXED_0(val) { val = 0; }
+#define MUL(a, b)        ((a) * (b))
+#if defined(__arm__) && (!defined(__thumb__) || defined(__thumb2__))
+#define MULA(a, b, res) ({                             \
+               int tmp = res;                  \
+               __asm__(                                \
+                       "mla %0, %2, %3, %0"            \
+                       : "=&r" (tmp)                   \
+                       : "0" (tmp), "r" (a), "r" (b)); \
+               tmp; })
+#else
+#define MULA(a, b, res)  ((a) * (b) + (res))
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives.c b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives.c
new file mode 100755 (executable)
index 0000000..ff343cf
--- /dev/null
@@ -0,0 +1,639 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *  Copyright (C) 2012-2013  Intel Corporation
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdint.h>
+#include <limits.h>
+#include <string.h>
+#include "sbc.h"
+#include "sbc_math.h"
+#include "sbc_tables.h"
+
+#include "sbc_primitives.h"
+#include "sbc_primitives_mmx.h"
+#include "sbc_primitives_iwmmxt.h"
+#include "sbc_primitives_neon.h"
+#include "sbc_primitives_armv6.h"
+
+/*
+ * A reference C code of analysis filter with SIMD-friendly tables
+ * reordering and code layout. This code can be used to develop platform
+ * specific SIMD optimizations. Also it may be used as some kind of test
+ * for compiler autovectorization capabilities (who knows, if the compiler
+ * is very good at this stuff, hand optimized assembly may be not strictly
+ * needed for some platform).
+ *
+ * Note: It is also possible to make a simple variant of analysis filter,
+ * which needs only a single constants table without taking care about
+ * even/odd cases. This simple variant of filter can be implemented without
+ * input data permutation. The only thing that would be lost is the
+ * possibility to use pairwise SIMD multiplications. But for some simple
+ * CPU cores without SIMD extensions it can be useful. If anybody is
+ * interested in implementing such variant of a filter, sourcecode from
+ * bluez versions 4.26/4.27 can be used as a reference and the history of
+ * the changes in git repository done around that time may be worth checking.
+ */
+
+static inline void sbc_analyze_four_simd(const int16_t *in, int32_t *out,
+                                                       const FIXED_T *consts)
+{
+       FIXED_A t1[4];
+       FIXED_T t2[4];
+       int hop = 0;
+
+       /* rounding coefficient */
+       t1[0] = t1[1] = t1[2] = t1[3] =
+               (FIXED_A) 1 << (SBC_PROTO_FIXED4_SCALE - 1);
+
+       /* low pass polyphase filter */
+       for (hop = 0; hop < 40; hop += 8) {
+               t1[0] += (FIXED_A) in[hop] * consts[hop];
+               t1[0] += (FIXED_A) in[hop + 1] * consts[hop + 1];
+               t1[1] += (FIXED_A) in[hop + 2] * consts[hop + 2];
+               t1[1] += (FIXED_A) in[hop + 3] * consts[hop + 3];
+               t1[2] += (FIXED_A) in[hop + 4] * consts[hop + 4];
+               t1[2] += (FIXED_A) in[hop + 5] * consts[hop + 5];
+               t1[3] += (FIXED_A) in[hop + 6] * consts[hop + 6];
+               t1[3] += (FIXED_A) in[hop + 7] * consts[hop + 7];
+       }
+
+       /* scaling */
+       t2[0] = t1[0] >> SBC_PROTO_FIXED4_SCALE;
+       t2[1] = t1[1] >> SBC_PROTO_FIXED4_SCALE;
+       t2[2] = t1[2] >> SBC_PROTO_FIXED4_SCALE;
+       t2[3] = t1[3] >> SBC_PROTO_FIXED4_SCALE;
+
+       /* do the cos transform */
+       t1[0]  = (FIXED_A) t2[0] * consts[40 + 0];
+       t1[0] += (FIXED_A) t2[1] * consts[40 + 1];
+       t1[1]  = (FIXED_A) t2[0] * consts[40 + 2];
+       t1[1] += (FIXED_A) t2[1] * consts[40 + 3];
+       t1[2]  = (FIXED_A) t2[0] * consts[40 + 4];
+       t1[2] += (FIXED_A) t2[1] * consts[40 + 5];
+       t1[3]  = (FIXED_A) t2[0] * consts[40 + 6];
+       t1[3] += (FIXED_A) t2[1] * consts[40 + 7];
+
+       t1[0] += (FIXED_A) t2[2] * consts[40 + 8];
+       t1[0] += (FIXED_A) t2[3] * consts[40 + 9];
+       t1[1] += (FIXED_A) t2[2] * consts[40 + 10];
+       t1[1] += (FIXED_A) t2[3] * consts[40 + 11];
+       t1[2] += (FIXED_A) t2[2] * consts[40 + 12];
+       t1[2] += (FIXED_A) t2[3] * consts[40 + 13];
+       t1[3] += (FIXED_A) t2[2] * consts[40 + 14];
+       t1[3] += (FIXED_A) t2[3] * consts[40 + 15];
+
+       out[0] = t1[0] >>
+               (SBC_COS_TABLE_FIXED4_SCALE - SCALE_OUT_BITS);
+       out[1] = t1[1] >>
+               (SBC_COS_TABLE_FIXED4_SCALE - SCALE_OUT_BITS);
+       out[2] = t1[2] >>
+               (SBC_COS_TABLE_FIXED4_SCALE - SCALE_OUT_BITS);
+       out[3] = t1[3] >>
+               (SBC_COS_TABLE_FIXED4_SCALE - SCALE_OUT_BITS);
+}
+
+static inline void sbc_analyze_eight_simd(const int16_t *in, int32_t *out,
+                                                       const FIXED_T *consts)
+{
+       FIXED_A t1[8];
+       FIXED_T t2[8];
+       int i, hop;
+
+       /* rounding coefficient */
+       t1[0] = t1[1] = t1[2] = t1[3] = t1[4] = t1[5] = t1[6] = t1[7] =
+               (FIXED_A) 1 << (SBC_PROTO_FIXED8_SCALE-1);
+
+       /* low pass polyphase filter */
+       for (hop = 0; hop < 80; hop += 16) {
+               t1[0] += (FIXED_A) in[hop] * consts[hop];
+               t1[0] += (FIXED_A) in[hop + 1] * consts[hop + 1];
+               t1[1] += (FIXED_A) in[hop + 2] * consts[hop + 2];
+               t1[1] += (FIXED_A) in[hop + 3] * consts[hop + 3];
+               t1[2] += (FIXED_A) in[hop + 4] * consts[hop + 4];
+               t1[2] += (FIXED_A) in[hop + 5] * consts[hop + 5];
+               t1[3] += (FIXED_A) in[hop + 6] * consts[hop + 6];
+               t1[3] += (FIXED_A) in[hop + 7] * consts[hop + 7];
+               t1[4] += (FIXED_A) in[hop + 8] * consts[hop + 8];
+               t1[4] += (FIXED_A) in[hop + 9] * consts[hop + 9];
+               t1[5] += (FIXED_A) in[hop + 10] * consts[hop + 10];
+               t1[5] += (FIXED_A) in[hop + 11] * consts[hop + 11];
+               t1[6] += (FIXED_A) in[hop + 12] * consts[hop + 12];
+               t1[6] += (FIXED_A) in[hop + 13] * consts[hop + 13];
+               t1[7] += (FIXED_A) in[hop + 14] * consts[hop + 14];
+               t1[7] += (FIXED_A) in[hop + 15] * consts[hop + 15];
+       }
+
+       /* scaling */
+       t2[0] = t1[0] >> SBC_PROTO_FIXED8_SCALE;
+       t2[1] = t1[1] >> SBC_PROTO_FIXED8_SCALE;
+       t2[2] = t1[2] >> SBC_PROTO_FIXED8_SCALE;
+       t2[3] = t1[3] >> SBC_PROTO_FIXED8_SCALE;
+       t2[4] = t1[4] >> SBC_PROTO_FIXED8_SCALE;
+       t2[5] = t1[5] >> SBC_PROTO_FIXED8_SCALE;
+       t2[6] = t1[6] >> SBC_PROTO_FIXED8_SCALE;
+       t2[7] = t1[7] >> SBC_PROTO_FIXED8_SCALE;
+
+
+       /* do the cos transform */
+       t1[0] = t1[1] = t1[2] = t1[3] = t1[4] = t1[5] = t1[6] = t1[7] = 0;
+
+       for (i = 0; i < 4; i++) {
+               t1[0] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 0];
+               t1[0] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 1];
+               t1[1] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 2];
+               t1[1] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 3];
+               t1[2] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 4];
+               t1[2] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 5];
+               t1[3] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 6];
+               t1[3] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 7];
+               t1[4] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 8];
+               t1[4] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 9];
+               t1[5] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 10];
+               t1[5] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 11];
+               t1[6] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 12];
+               t1[6] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 13];
+               t1[7] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 14];
+               t1[7] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 15];
+       }
+
+       for (i = 0; i < 8; i++)
+               out[i] = t1[i] >>
+                       (SBC_COS_TABLE_FIXED8_SCALE - SCALE_OUT_BITS);
+}
+
+static inline void sbc_analyze_4b_4s_simd(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       sbc_analyze_four_simd(x + 12, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       sbc_analyze_four_simd(x + 8, out, analysis_consts_fixed4_simd_even);
+       out += out_stride;
+       sbc_analyze_four_simd(x + 4, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       sbc_analyze_four_simd(x + 0, out, analysis_consts_fixed4_simd_even);
+}
+
+static inline void sbc_analyze_4b_8s_simd(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       sbc_analyze_eight_simd(x + 24, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       sbc_analyze_eight_simd(x + 16, out, analysis_consts_fixed8_simd_even);
+       out += out_stride;
+       sbc_analyze_eight_simd(x + 8, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       sbc_analyze_eight_simd(x + 0, out, analysis_consts_fixed8_simd_even);
+}
+
+static inline void sbc_analyze_1b_8s_simd_even(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride);
+
+static inline void sbc_analyze_1b_8s_simd_odd(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       sbc_analyze_eight_simd(x, out, analysis_consts_fixed8_simd_odd);
+       state->sbc_analyze_8s = sbc_analyze_1b_8s_simd_even;
+}
+
+static inline void sbc_analyze_1b_8s_simd_even(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       sbc_analyze_eight_simd(x, out, analysis_consts_fixed8_simd_even);
+       state->sbc_analyze_8s = sbc_analyze_1b_8s_simd_odd;
+}
+
+static inline int16_t unaligned16_be(const uint8_t *ptr)
+{
+       return (int16_t) ((ptr[0] << 8) | ptr[1]);
+}
+
+static inline int16_t unaligned16_le(const uint8_t *ptr)
+{
+       return (int16_t) (ptr[0] | (ptr[1] << 8));
+}
+
+/*
+ * Internal helper functions for input data processing. In order to get
+ * optimal performance, it is important to have "nsamples", "nchannels"
+ * and "big_endian" arguments used with this inline function as compile
+ * time constants.
+ */
+
+static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s4_internal(
+       int position,
+       const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+       int nsamples, int nchannels, int big_endian)
+{
+       /* handle X buffer wraparound */
+       if (position < nsamples) {
+               if (nchannels > 0)
+                       memcpy(&X[0][SBC_X_BUFFER_SIZE - 40], &X[0][position],
+                                                       36 * sizeof(int16_t));
+               if (nchannels > 1)
+                       memcpy(&X[1][SBC_X_BUFFER_SIZE - 40], &X[1][position],
+                                                       36 * sizeof(int16_t));
+               position = SBC_X_BUFFER_SIZE - 40;
+       }
+
+       #define PCM(i) (big_endian ? \
+               unaligned16_be(pcm + (i) * 2) : unaligned16_le(pcm + (i) * 2))
+
+       /* copy/permutate audio samples */
+       while ((nsamples -= 8) >= 0) {
+               position -= 8;
+               if (nchannels > 0) {
+                       int16_t *x = &X[0][position];
+                       x[0]  = PCM(0 + 7 * nchannels);
+                       x[1]  = PCM(0 + 3 * nchannels);
+                       x[2]  = PCM(0 + 6 * nchannels);
+                       x[3]  = PCM(0 + 4 * nchannels);
+                       x[4]  = PCM(0 + 0 * nchannels);
+                       x[5]  = PCM(0 + 2 * nchannels);
+                       x[6]  = PCM(0 + 1 * nchannels);
+                       x[7]  = PCM(0 + 5 * nchannels);
+               }
+               if (nchannels > 1) {
+                       int16_t *x = &X[1][position];
+                       x[0]  = PCM(1 + 7 * nchannels);
+                       x[1]  = PCM(1 + 3 * nchannels);
+                       x[2]  = PCM(1 + 6 * nchannels);
+                       x[3]  = PCM(1 + 4 * nchannels);
+                       x[4]  = PCM(1 + 0 * nchannels);
+                       x[5]  = PCM(1 + 2 * nchannels);
+                       x[6]  = PCM(1 + 1 * nchannels);
+                       x[7]  = PCM(1 + 5 * nchannels);
+               }
+               pcm += 16 * nchannels;
+       }
+       #undef PCM
+
+       return position;
+}
+
+static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
+       int position,
+       const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+       int nsamples, int nchannels, int big_endian)
+{
+       /* handle X buffer wraparound */
+       if (position < nsamples) {
+               if (nchannels > 0)
+                       memcpy(&X[0][SBC_X_BUFFER_SIZE - 72], &X[0][position],
+                                                       72 * sizeof(int16_t));
+               if (nchannels > 1)
+                       memcpy(&X[1][SBC_X_BUFFER_SIZE - 72], &X[1][position],
+                                                       72 * sizeof(int16_t));
+               position = SBC_X_BUFFER_SIZE - 72;
+       }
+
+       #define PCM(i) (big_endian ? \
+               unaligned16_be(pcm + (i) * 2) : unaligned16_le(pcm + (i) * 2))
+
+       if (position % 16 == 8) {
+               position -= 8;
+               nsamples -= 8;
+               if (nchannels > 0) {
+                       int16_t *x = &X[0][position];
+                       x[0]  = PCM(0 + (15-8) * nchannels);
+                       x[2]  = PCM(0 + (14-8) * nchannels);
+                       x[3]  = PCM(0 + (8-8) * nchannels);
+                       x[4]  = PCM(0 + (13-8) * nchannels);
+                       x[5]  = PCM(0 + (9-8) * nchannels);
+                       x[6]  = PCM(0 + (12-8) * nchannels);
+                       x[7]  = PCM(0 + (10-8) * nchannels);
+                       x[8]  = PCM(0 + (11-8) * nchannels);
+               }
+               if (nchannels > 1) {
+                       int16_t *x = &X[1][position];
+                       x[0]  = PCM(1 + (15-8) * nchannels);
+                       x[2]  = PCM(1 + (14-8) * nchannels);
+                       x[3]  = PCM(1 + (8-8) * nchannels);
+                       x[4]  = PCM(1 + (13-8) * nchannels);
+                       x[5]  = PCM(1 + (9-8) * nchannels);
+                       x[6]  = PCM(1 + (12-8) * nchannels);
+                       x[7]  = PCM(1 + (10-8) * nchannels);
+                       x[8]  = PCM(1 + (11-8) * nchannels);
+               }
+
+               pcm += 16 * nchannels;
+       }
+
+       /* copy/permutate audio samples */
+       while (nsamples >= 16) {
+               position -= 16;
+               if (nchannels > 0) {
+                       int16_t *x = &X[0][position];
+                       x[0]  = PCM(0 + 15 * nchannels);
+                       x[1]  = PCM(0 + 7 * nchannels);
+                       x[2]  = PCM(0 + 14 * nchannels);
+                       x[3]  = PCM(0 + 8 * nchannels);
+                       x[4]  = PCM(0 + 13 * nchannels);
+                       x[5]  = PCM(0 + 9 * nchannels);
+                       x[6]  = PCM(0 + 12 * nchannels);
+                       x[7]  = PCM(0 + 10 * nchannels);
+                       x[8]  = PCM(0 + 11 * nchannels);
+                       x[9]  = PCM(0 + 3 * nchannels);
+                       x[10] = PCM(0 + 6 * nchannels);
+                       x[11] = PCM(0 + 0 * nchannels);
+                       x[12] = PCM(0 + 5 * nchannels);
+                       x[13] = PCM(0 + 1 * nchannels);
+                       x[14] = PCM(0 + 4 * nchannels);
+                       x[15] = PCM(0 + 2 * nchannels);
+               }
+               if (nchannels > 1) {
+                       int16_t *x = &X[1][position];
+                       x[0]  = PCM(1 + 15 * nchannels);
+                       x[1]  = PCM(1 + 7 * nchannels);
+                       x[2]  = PCM(1 + 14 * nchannels);
+                       x[3]  = PCM(1 + 8 * nchannels);
+                       x[4]  = PCM(1 + 13 * nchannels);
+                       x[5]  = PCM(1 + 9 * nchannels);
+                       x[6]  = PCM(1 + 12 * nchannels);
+                       x[7]  = PCM(1 + 10 * nchannels);
+                       x[8]  = PCM(1 + 11 * nchannels);
+                       x[9]  = PCM(1 + 3 * nchannels);
+                       x[10] = PCM(1 + 6 * nchannels);
+                       x[11] = PCM(1 + 0 * nchannels);
+                       x[12] = PCM(1 + 5 * nchannels);
+                       x[13] = PCM(1 + 1 * nchannels);
+                       x[14] = PCM(1 + 4 * nchannels);
+                       x[15] = PCM(1 + 2 * nchannels);
+               }
+               pcm += 32 * nchannels;
+               nsamples -= 16;
+       }
+
+       if (nsamples == 8) {
+               position -= 8;
+               if (nchannels > 0) {
+                       int16_t *x = &X[0][position];
+                       x[-7] = PCM(0 + 7 * nchannels);
+                       x[1]  = PCM(0 + 3 * nchannels);
+                       x[2]  = PCM(0 + 6 * nchannels);
+                       x[3]  = PCM(0 + 0 * nchannels);
+                       x[4]  = PCM(0 + 5 * nchannels);
+                       x[5]  = PCM(0 + 1 * nchannels);
+                       x[6]  = PCM(0 + 4 * nchannels);
+                       x[7]  = PCM(0 + 2 * nchannels);
+               }
+               if (nchannels > 1) {
+                       int16_t *x = &X[1][position];
+                       x[-7] = PCM(1 + 7 * nchannels);
+                       x[1]  = PCM(1 + 3 * nchannels);
+                       x[2]  = PCM(1 + 6 * nchannels);
+                       x[3]  = PCM(1 + 0 * nchannels);
+                       x[4]  = PCM(1 + 5 * nchannels);
+                       x[5]  = PCM(1 + 1 * nchannels);
+                       x[6]  = PCM(1 + 4 * nchannels);
+                       x[7]  = PCM(1 + 2 * nchannels);
+               }
+       }
+       #undef PCM
+
+       return position;
+}
+
+/*
+ * Input data processing functions. The data is endian converted if needed,
+ * channels are deintrleaved and audio samples are reordered for use in
+ * SIMD-friendly analysis filter function. The results are put into "X"
+ * array, getting appended to the previous data (or it is better to say
+ * prepended, as the buffer is filled from top to bottom). Old data is
+ * discarded when neededed, but availability of (10 * nrof_subbands)
+ * contiguous samples is always guaranteed for the input to the analysis
+ * filter. This is achieved by copying a sufficient part of old data
+ * to the top of the buffer on buffer wraparound.
+ */
+
+static int sbc_enc_process_input_4s_le(int position,
+               const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+               int nsamples, int nchannels)
+{
+       if (nchannels > 1)
+               return sbc_encoder_process_input_s4_internal(
+                       position, pcm, X, nsamples, 2, 0);
+       else
+               return sbc_encoder_process_input_s4_internal(
+                       position, pcm, X, nsamples, 1, 0);
+}
+
+static int sbc_enc_process_input_4s_be(int position,
+               const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+               int nsamples, int nchannels)
+{
+       if (nchannels > 1)
+               return sbc_encoder_process_input_s4_internal(
+                       position, pcm, X, nsamples, 2, 1);
+       else
+               return sbc_encoder_process_input_s4_internal(
+                       position, pcm, X, nsamples, 1, 1);
+}
+
+static int sbc_enc_process_input_8s_le(int position,
+               const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+               int nsamples, int nchannels)
+{
+       if (nchannels > 1)
+               return sbc_encoder_process_input_s8_internal(
+                       position, pcm, X, nsamples, 2, 0);
+       else
+               return sbc_encoder_process_input_s8_internal(
+                       position, pcm, X, nsamples, 1, 0);
+}
+
+static int sbc_enc_process_input_8s_be(int position,
+               const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+               int nsamples, int nchannels)
+{
+       if (nchannels > 1)
+               return sbc_encoder_process_input_s8_internal(
+                       position, pcm, X, nsamples, 2, 1);
+       else
+               return sbc_encoder_process_input_s8_internal(
+                       position, pcm, X, nsamples, 1, 1);
+}
+
+/* Supplementary function to count the number of leading zeros */
+
+static inline int sbc_clz(uint32_t x)
+{
+#ifdef __GNUC__
+       return __builtin_clz(x);
+#else
+       /* TODO: this should be replaced with something better if good
+        * performance is wanted when using compilers other than gcc */
+       int cnt = 0;
+       while (x) {
+               cnt++;
+               x >>= 1;
+       }
+       return 32 - cnt;
+#endif
+}
+
+static void sbc_calc_scalefactors(
+       int32_t sb_sample_f[16][2][8],
+       uint32_t scale_factor[2][8],
+       int blocks, int channels, int subbands)
+{
+       int ch, sb, blk;
+       for (ch = 0; ch < channels; ch++) {
+               for (sb = 0; sb < subbands; sb++) {
+                       uint32_t x = 1 << SCALE_OUT_BITS;
+                       for (blk = 0; blk < blocks; blk++) {
+                               int32_t tmp = fabs(sb_sample_f[blk][ch][sb]);
+                               if (tmp != 0)
+                                       x |= tmp - 1;
+                       }
+                       scale_factor[ch][sb] = (31 - SCALE_OUT_BITS) -
+                               sbc_clz(x);
+               }
+       }
+}
+
+static int sbc_calc_scalefactors_j(
+       int32_t sb_sample_f[16][2][8],
+       uint32_t scale_factor[2][8],
+       int blocks, int subbands)
+{
+       int blk, joint = 0;
+       int32_t tmp0, tmp1;
+       uint32_t x, y;
+
+       /* last subband does not use joint stereo */
+       int sb = subbands - 1;
+       x = 1 << SCALE_OUT_BITS;
+       y = 1 << SCALE_OUT_BITS;
+       for (blk = 0; blk < blocks; blk++) {
+               tmp0 = fabs(sb_sample_f[blk][0][sb]);
+               tmp1 = fabs(sb_sample_f[blk][1][sb]);
+               if (tmp0 != 0)
+                       x |= tmp0 - 1;
+               if (tmp1 != 0)
+                       y |= tmp1 - 1;
+       }
+       scale_factor[0][sb] = (31 - SCALE_OUT_BITS) - sbc_clz(x);
+       scale_factor[1][sb] = (31 - SCALE_OUT_BITS) - sbc_clz(y);
+
+       /* the rest of subbands can use joint stereo */
+       while (--sb >= 0) {
+               int32_t sb_sample_j[16][2];
+               x = 1 << SCALE_OUT_BITS;
+               y = 1 << SCALE_OUT_BITS;
+               for (blk = 0; blk < blocks; blk++) {
+                       tmp0 = sb_sample_f[blk][0][sb];
+                       tmp1 = sb_sample_f[blk][1][sb];
+                       sb_sample_j[blk][0] = ASR(tmp0, 1) + ASR(tmp1, 1);
+                       sb_sample_j[blk][1] = ASR(tmp0, 1) - ASR(tmp1, 1);
+                       tmp0 = fabs(tmp0);
+                       tmp1 = fabs(tmp1);
+                       if (tmp0 != 0)
+                               x |= tmp0 - 1;
+                       if (tmp1 != 0)
+                               y |= tmp1 - 1;
+               }
+               scale_factor[0][sb] = (31 - SCALE_OUT_BITS) -
+                       sbc_clz(x);
+               scale_factor[1][sb] = (31 - SCALE_OUT_BITS) -
+                       sbc_clz(y);
+               x = 1 << SCALE_OUT_BITS;
+               y = 1 << SCALE_OUT_BITS;
+               for (blk = 0; blk < blocks; blk++) {
+                       tmp0 = fabs(sb_sample_j[blk][0]);
+                       tmp1 = fabs(sb_sample_j[blk][1]);
+                       if (tmp0 != 0)
+                               x |= tmp0 - 1;
+                       if (tmp1 != 0)
+                               y |= tmp1 - 1;
+               }
+               x = (31 - SCALE_OUT_BITS) - sbc_clz(x);
+               y = (31 - SCALE_OUT_BITS) - sbc_clz(y);
+
+               /* decide whether to use joint stereo for this subband */
+               if ((scale_factor[0][sb] + scale_factor[1][sb]) > x + y) {
+                       joint |= 1 << (subbands - 1 - sb);
+                       scale_factor[0][sb] = x;
+                       scale_factor[1][sb] = y;
+                       for (blk = 0; blk < blocks; blk++) {
+                               sb_sample_f[blk][0][sb] = sb_sample_j[blk][0];
+                               sb_sample_f[blk][1][sb] = sb_sample_j[blk][1];
+                       }
+               }
+       }
+
+       /* bitmask with the information about subbands using joint stereo */
+       return joint;
+}
+
+/*
+ * Detect CPU features and setup function pointers
+ */
+void sbc_init_primitives(struct sbc_encoder_state *state)
+{
+       /* Default implementation for analyze functions */
+       state->sbc_analyze_4s = sbc_analyze_4b_4s_simd;
+       if (state->increment == 1)
+               state->sbc_analyze_8s = sbc_analyze_1b_8s_simd_odd;
+       else
+               state->sbc_analyze_8s = sbc_analyze_4b_8s_simd;
+
+       /* Default implementation for input reordering / deinterleaving */
+       state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le;
+       state->sbc_enc_process_input_4s_be = sbc_enc_process_input_4s_be;
+       state->sbc_enc_process_input_8s_le = sbc_enc_process_input_8s_le;
+       state->sbc_enc_process_input_8s_be = sbc_enc_process_input_8s_be;
+
+       /* Default implementation for scale factors calculation */
+       state->sbc_calc_scalefactors = sbc_calc_scalefactors;
+       state->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j;
+       state->implementation_info = "Generic C";
+
+       /* X86/AMD64 optimizations */
+#ifdef SBC_BUILD_WITH_MMX_SUPPORT
+       sbc_init_primitives_mmx(state);
+#endif
+
+       /* ARM optimizations */
+#ifdef SBC_BUILD_WITH_ARMV6_SUPPORT
+       sbc_init_primitives_armv6(state);
+#endif
+#ifdef SBC_BUILD_WITH_IWMMXT_SUPPORT
+       sbc_init_primitives_iwmmxt(state);
+#endif
+#ifdef SBC_BUILD_WITH_NEON_SUPPORT
+       sbc_init_primitives_neon(state);
+
+       if (state->increment == 1) {
+               state->sbc_analyze_8s = sbc_analyze_1b_8s_simd_odd;
+               state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le;
+               state->sbc_enc_process_input_4s_be = sbc_enc_process_input_4s_be;
+               state->sbc_enc_process_input_8s_le = sbc_enc_process_input_8s_le;
+               state->sbc_enc_process_input_8s_be = sbc_enc_process_input_8s_be;
+       }
+#endif
+}
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives.h b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives.h
new file mode 100755 (executable)
index 0000000..f4598d5
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __SBC_PRIMITIVES_H
+#define __SBC_PRIMITIVES_H
+
+#define SCALE_OUT_BITS 15
+#define SBC_X_BUFFER_SIZE 328
+
+#ifdef __GNUC__
+#define SBC_ALWAYS_INLINE inline __attribute__((always_inline))
+#else
+#define SBC_ALWAYS_INLINE inline
+#endif
+
+struct SBC_ALIGNED sbc_encoder_state {
+       int position;
+       /* Number of consecutive blocks handled by the encoder */
+       uint8_t increment;
+       int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
+       /* Polyphase analysis filter for 4 subbands configuration,
+        * it handles "increment" blocks at once */
+       void (*sbc_analyze_4s)(struct sbc_encoder_state *state,
+                       int16_t *x, int32_t *out, int out_stride);
+       /* Polyphase analysis filter for 8 subbands configuration,
+        * it handles "increment" blocks at once */
+       void (*sbc_analyze_8s)(struct sbc_encoder_state *state,
+                       int16_t *x, int32_t *out, int out_stride);
+       /* Process input data (deinterleave, endian conversion, reordering),
+        * depending on the number of subbands and input data byte order */
+       int (*sbc_enc_process_input_4s_le)(int position,
+                       const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+                       int nsamples, int nchannels);
+       int (*sbc_enc_process_input_4s_be)(int position,
+                       const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+                       int nsamples, int nchannels);
+       int (*sbc_enc_process_input_8s_le)(int position,
+                       const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+                       int nsamples, int nchannels);
+       int (*sbc_enc_process_input_8s_be)(int position,
+                       const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+                       int nsamples, int nchannels);
+       /* Scale factors calculation */
+       void (*sbc_calc_scalefactors)(int32_t sb_sample_f[16][2][8],
+                       uint32_t scale_factor[2][8],
+                       int blocks, int channels, int subbands);
+       /* Scale factors calculation with joint stereo support */
+       int (*sbc_calc_scalefactors_j)(int32_t sb_sample_f[16][2][8],
+                       uint32_t scale_factor[2][8],
+                       int blocks, int subbands);
+       const char *implementation_info;
+};
+
+/*
+ * Initialize pointers to the functions which are the basic "building bricks"
+ * of SBC codec. Best implementation is selected based on target CPU
+ * capabilities.
+ */
+void sbc_init_primitives(struct sbc_encoder_state *encoder_state);
+
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_armv6.c b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_armv6.c
new file mode 100755 (executable)
index 0000000..665f157
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdint.h>
+#include <limits.h>
+#include "sbc.h"
+#include "sbc_math.h"
+#include "sbc_tables.h"
+
+#include "sbc_primitives_armv6.h"
+
+/*
+ * ARMv6 optimizations. The instructions are scheduled for ARM11 pipeline.
+ */
+
+#ifdef SBC_BUILD_WITH_ARMV6_SUPPORT
+
+static void __attribute__((naked)) sbc_analyze_four_armv6()
+{
+       /* r0 = in, r1 = out, r2 = consts */
+       __asm__ volatile (
+               "push   {r1, r4-r7, lr}\n"
+               "push   {r8-r11}\n"
+               "ldrd   r4,  r5,  [r0, #0]\n"
+               "ldrd   r6,  r7,  [r2, #0]\n"
+               "ldrd   r8,  r9,  [r0, #16]\n"
+               "ldrd   r10, r11, [r2, #16]\n"
+               "mov    r14, #0x8000\n"
+               "smlad  r3,  r4,  r6,  r14\n"
+               "smlad  r12, r5,  r7,  r14\n"
+               "ldrd   r4,  r5,  [r0, #32]\n"
+               "ldrd   r6,  r7,  [r2, #32]\n"
+               "smlad  r3,  r8,  r10, r3\n"
+               "smlad  r12, r9,  r11, r12\n"
+               "ldrd   r8,  r9,  [r0, #48]\n"
+               "ldrd   r10, r11, [r2, #48]\n"
+               "smlad  r3,  r4,  r6,  r3\n"
+               "smlad  r12, r5,  r7,  r12\n"
+               "ldrd   r4,  r5,  [r0, #64]\n"
+               "ldrd   r6,  r7,  [r2, #64]\n"
+               "smlad  r3,  r8,  r10, r3\n"
+               "smlad  r12, r9,  r11, r12\n"
+               "ldrd   r8,  r9,  [r0, #8]\n"
+               "ldrd   r10, r11, [r2, #8]\n"
+               "smlad  r3,  r4,  r6,  r3\n"      /* t1[0] is done */
+               "smlad  r12, r5,  r7,  r12\n"     /* t1[1] is done */
+               "ldrd   r4,  r5,  [r0, #24]\n"
+               "ldrd   r6,  r7,  [r2, #24]\n"
+               "pkhtb  r3,  r12, r3, asr #16\n"  /* combine t1[0] and t1[1] */
+               "smlad  r12, r8,  r10, r14\n"
+               "smlad  r14, r9,  r11, r14\n"
+               "ldrd   r8,  r9,  [r0, #40]\n"
+               "ldrd   r10, r11, [r2, #40]\n"
+               "smlad  r12, r4,  r6,  r12\n"
+               "smlad  r14, r5,  r7,  r14\n"
+               "ldrd   r4,  r5,  [r0, #56]\n"
+               "ldrd   r6,  r7,  [r2, #56]\n"
+               "smlad  r12, r8,  r10, r12\n"
+               "smlad  r14, r9,  r11, r14\n"
+               "ldrd   r8,  r9,  [r0, #72]\n"
+               "ldrd   r10, r11, [r2, #72]\n"
+               "smlad  r12, r4,  r6,  r12\n"
+               "smlad  r14, r5,  r7,  r14\n"
+               "ldrd   r4,  r5,  [r2, #80]\n"    /* start loading cos table */
+               "smlad  r12, r8,  r10, r12\n"     /* t1[2] is done */
+               "smlad  r14, r9,  r11, r14\n"     /* t1[3] is done */
+               "ldrd   r6,  r7,  [r2, #88]\n"
+               "ldrd   r8,  r9,  [r2, #96]\n"
+               "ldrd   r10, r11, [r2, #104]\n"   /* cos table fully loaded */
+               "pkhtb  r12, r14, r12, asr #16\n" /* combine t1[2] and t1[3] */
+               "smuad  r4,  r3,  r4\n"
+               "smuad  r5,  r3,  r5\n"
+               "smlad  r4,  r12, r8,  r4\n"
+               "smlad  r5,  r12, r9,  r5\n"
+               "smuad  r6,  r3,  r6\n"
+               "smuad  r7,  r3,  r7\n"
+               "smlad  r6,  r12, r10, r6\n"
+               "smlad  r7,  r12, r11, r7\n"
+               "pop    {r8-r11}\n"
+               "stmia  r1, {r4, r5, r6, r7}\n"
+               "pop    {r1, r4-r7, pc}\n"
+       );
+}
+
+#define sbc_analyze_four(in, out, consts) \
+       ((void (*)(int16_t *, int32_t *, const FIXED_T*)) \
+               sbc_analyze_four_armv6)((in), (out), (consts))
+
+static void __attribute__((naked)) sbc_analyze_eight_armv6()
+{
+       /* r0 = in, r1 = out, r2 = consts */
+       __asm__ volatile (
+               "push   {r1, r4-r7, lr}\n"
+               "push   {r8-r11}\n"
+               "ldrd   r4,  r5,  [r0, #24]\n"
+               "ldrd   r6,  r7,  [r2, #24]\n"
+               "ldrd   r8,  r9,  [r0, #56]\n"
+               "ldrd   r10, r11, [r2, #56]\n"
+               "mov    r14, #0x8000\n"
+               "smlad  r3,  r4,  r6,  r14\n"
+               "smlad  r12, r5,  r7,  r14\n"
+               "ldrd   r4,  r5,  [r0, #88]\n"
+               "ldrd   r6,  r7,  [r2, #88]\n"
+               "smlad  r3,  r8,  r10, r3\n"
+               "smlad  r12, r9,  r11, r12\n"
+               "ldrd   r8,  r9,  [r0, #120]\n"
+               "ldrd   r10, r11, [r2, #120]\n"
+               "smlad  r3,  r4,  r6,  r3\n"
+               "smlad  r12, r5,  r7,  r12\n"
+               "ldrd   r4,  r5,  [r0, #152]\n"
+               "ldrd   r6,  r7,  [r2, #152]\n"
+               "smlad  r3,  r8,  r10, r3\n"
+               "smlad  r12, r9,  r11, r12\n"
+               "ldrd   r8,  r9,  [r0, #16]\n"
+               "ldrd   r10, r11, [r2, #16]\n"
+               "smlad  r3,  r4,  r6,  r3\n"      /* t1[6] is done */
+               "smlad  r12, r5,  r7,  r12\n"     /* t1[7] is done */
+               "ldrd   r4,  r5,  [r0, #48]\n"
+               "ldrd   r6,  r7,  [r2, #48]\n"
+               "pkhtb  r3,  r12, r3, asr #16\n"  /* combine t1[6] and t1[7] */
+               "str    r3,  [sp, #-4]!\n"        /* save to stack */
+               "smlad  r3,  r8,  r10, r14\n"
+               "smlad  r12, r9,  r11, r14\n"
+               "ldrd   r8,  r9,  [r0, #80]\n"
+               "ldrd   r10, r11, [r2, #80]\n"
+               "smlad  r3,  r4,  r6,  r3\n"
+               "smlad  r12, r5,  r7,  r12\n"
+               "ldrd   r4,  r5,  [r0, #112]\n"
+               "ldrd   r6,  r7,  [r2, #112]\n"
+               "smlad  r3,  r8,  r10, r3\n"
+               "smlad  r12, r9,  r11, r12\n"
+               "ldrd   r8,  r9,  [r0, #144]\n"
+               "ldrd   r10, r11, [r2, #144]\n"
+               "smlad  r3,  r4,  r6,  r3\n"
+               "smlad  r12, r5,  r7,  r12\n"
+               "ldrd   r4,  r5,  [r0, #0]\n"
+               "ldrd   r6,  r7,  [r2, #0]\n"
+               "smlad  r3,  r8,  r10, r3\n"      /* t1[4] is done */
+               "smlad  r12, r9,  r11, r12\n"     /* t1[5] is done */
+               "ldrd   r8,  r9,  [r0, #32]\n"
+               "ldrd   r10, r11, [r2, #32]\n"
+               "pkhtb  r3,  r12, r3, asr #16\n"  /* combine t1[4] and t1[5] */
+               "str    r3,  [sp, #-4]!\n"        /* save to stack */
+               "smlad  r3,  r4,  r6,  r14\n"
+               "smlad  r12, r5,  r7,  r14\n"
+               "ldrd   r4,  r5,  [r0, #64]\n"
+               "ldrd   r6,  r7,  [r2, #64]\n"
+               "smlad  r3,  r8,  r10, r3\n"
+               "smlad  r12, r9,  r11, r12\n"
+               "ldrd   r8,  r9,  [r0, #96]\n"
+               "ldrd   r10, r11, [r2, #96]\n"
+               "smlad  r3,  r4,  r6,  r3\n"
+               "smlad  r12, r5,  r7,  r12\n"
+               "ldrd   r4,  r5,  [r0, #128]\n"
+               "ldrd   r6,  r7,  [r2, #128]\n"
+               "smlad  r3,  r8,  r10, r3\n"
+               "smlad  r12, r9,  r11, r12\n"
+               "ldrd   r8,  r9,  [r0, #8]\n"
+               "ldrd   r10, r11, [r2, #8]\n"
+               "smlad  r3,  r4,  r6,  r3\n"      /* t1[0] is done */
+               "smlad  r12, r5,  r7,  r12\n"     /* t1[1] is done */
+               "ldrd   r4,  r5,  [r0, #40]\n"
+               "ldrd   r6,  r7,  [r2, #40]\n"
+               "pkhtb  r3,  r12, r3, asr #16\n"  /* combine t1[0] and t1[1] */
+               "smlad  r12, r8,  r10, r14\n"
+               "smlad  r14, r9,  r11, r14\n"
+               "ldrd   r8,  r9,  [r0, #72]\n"
+               "ldrd   r10, r11, [r2, #72]\n"
+               "smlad  r12, r4,  r6,  r12\n"
+               "smlad  r14, r5,  r7,  r14\n"
+               "ldrd   r4,  r5,  [r0, #104]\n"
+               "ldrd   r6,  r7,  [r2, #104]\n"
+               "smlad  r12, r8,  r10, r12\n"
+               "smlad  r14, r9,  r11, r14\n"
+               "ldrd   r8,  r9,  [r0, #136]\n"
+               "ldrd   r10, r11, [r2, #136]!\n"
+               "smlad  r12, r4,  r6,  r12\n"
+               "smlad  r14, r5,  r7,  r14\n"
+               "ldrd   r4,  r5,  [r2, #(160 - 136 + 0)]\n"
+               "smlad  r12, r8,  r10, r12\n"     /* t1[2] is done */
+               "smlad  r14, r9,  r11, r14\n"     /* t1[3] is done */
+               "ldrd   r6,  r7,  [r2, #(160 - 136 + 8)]\n"
+               "smuad  r4,  r3,  r4\n"
+               "smuad  r5,  r3,  r5\n"
+               "pkhtb  r12, r14, r12, asr #16\n" /* combine t1[2] and t1[3] */
+                                                 /* r3  = t2[0:1] */
+                                                 /* r12 = t2[2:3] */
+               "pop    {r0, r14}\n"              /* t2[4:5], t2[6:7] */
+               "ldrd   r8,  r9,  [r2, #(160 - 136 + 32)]\n"
+               "smuad  r6,  r3,  r6\n"
+               "smuad  r7,  r3,  r7\n"
+               "ldrd   r10, r11, [r2, #(160 - 136 + 40)]\n"
+               "smlad  r4,  r12, r8,  r4\n"
+               "smlad  r5,  r12, r9,  r5\n"
+               "ldrd   r8,  r9,  [r2, #(160 - 136 + 64)]\n"
+               "smlad  r6,  r12, r10, r6\n"
+               "smlad  r7,  r12, r11, r7\n"
+               "ldrd   r10, r11, [r2, #(160 - 136 + 72)]\n"
+               "smlad  r4,  r0,  r8,  r4\n"
+               "smlad  r5,  r0,  r9,  r5\n"
+               "ldrd   r8,  r9,  [r2, #(160 - 136 + 96)]\n"
+               "smlad  r6,  r0,  r10, r6\n"
+               "smlad  r7,  r0,  r11, r7\n"
+               "ldrd   r10, r11, [r2, #(160 - 136 + 104)]\n"
+               "smlad  r4,  r14, r8,  r4\n"
+               "smlad  r5,  r14, r9,  r5\n"
+               "ldrd   r8,  r9,  [r2, #(160 - 136 + 16 + 0)]\n"
+               "smlad  r6,  r14, r10, r6\n"
+               "smlad  r7,  r14, r11, r7\n"
+               "ldrd   r10, r11, [r2, #(160 - 136 + 16 + 8)]\n"
+               "stmia  r1!, {r4, r5}\n"
+               "smuad  r4,  r3,  r8\n"
+               "smuad  r5,  r3,  r9\n"
+               "ldrd   r8,  r9,  [r2, #(160 - 136 + 16 + 32)]\n"
+               "stmia  r1!, {r6, r7}\n"
+               "smuad  r6,  r3,  r10\n"
+               "smuad  r7,  r3,  r11\n"
+               "ldrd   r10, r11, [r2, #(160 - 136 + 16 + 40)]\n"
+               "smlad  r4,  r12, r8,  r4\n"
+               "smlad  r5,  r12, r9,  r5\n"
+               "ldrd   r8,  r9,  [r2, #(160 - 136 + 16 + 64)]\n"
+               "smlad  r6,  r12, r10, r6\n"
+               "smlad  r7,  r12, r11, r7\n"
+               "ldrd   r10, r11, [r2, #(160 - 136 + 16 + 72)]\n"
+               "smlad  r4,  r0,  r8,  r4\n"
+               "smlad  r5,  r0,  r9,  r5\n"
+               "ldrd   r8,  r9,  [r2, #(160 - 136 + 16 + 96)]\n"
+               "smlad  r6,  r0,  r10, r6\n"
+               "smlad  r7,  r0,  r11, r7\n"
+               "ldrd   r10, r11, [r2, #(160 - 136 + 16 + 104)]\n"
+               "smlad  r4,  r14, r8,  r4\n"
+               "smlad  r5,  r14, r9,  r5\n"
+               "smlad  r6,  r14, r10, r6\n"
+               "smlad  r7,  r14, r11, r7\n"
+               "pop    {r8-r11}\n"
+               "stmia  r1!, {r4, r5, r6, r7}\n"
+               "pop    {r1, r4-r7, pc}\n"
+       );
+}
+
+#define sbc_analyze_eight(in, out, consts) \
+       ((void (*)(int16_t *, int32_t *, const FIXED_T*)) \
+               sbc_analyze_eight_armv6)((in), (out), (consts))
+
+static void sbc_analyze_4b_4s_armv6(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       sbc_analyze_four(x + 12, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       sbc_analyze_four(x + 8, out, analysis_consts_fixed4_simd_even);
+       out += out_stride;
+       sbc_analyze_four(x + 4, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       sbc_analyze_four(x + 0, out, analysis_consts_fixed4_simd_even);
+}
+
+static void sbc_analyze_4b_8s_armv6(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       sbc_analyze_eight(x + 24, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       sbc_analyze_eight(x + 16, out, analysis_consts_fixed8_simd_even);
+       out += out_stride;
+       sbc_analyze_eight(x + 8, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       sbc_analyze_eight(x + 0, out, analysis_consts_fixed8_simd_even);
+}
+
+static inline void sbc_analyze_1b_8s_armv6_even(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride);
+
+static inline void sbc_analyze_1b_8s_armv6_odd(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       sbc_analyze_eight_armv6(x, out, analysis_consts_fixed8_simd_odd);
+       state->sbc_analyze_8s = sbc_analyze_1b_8s_armv6_even;
+}
+
+static inline void sbc_analyze_1b_8s_armv6_even(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       sbc_analyze_eight_armv6(x, out, analysis_consts_fixed8_simd_even);
+       state->sbc_analyze_8s = sbc_analyze_1b_8s_armv6_odd;
+}
+
+void sbc_init_primitives_armv6(struct sbc_encoder_state *state)
+{
+       state->sbc_analyze_4s = sbc_analyze_4b_4s_armv6;
+       if (state->increment == 1)
+               state->sbc_analyze_8s = sbc_analyze_1b_8s_armv6_odd;
+       else
+               state->sbc_analyze_8s = sbc_analyze_4b_8s_armv6;
+       state->implementation_info = "ARMv6 SIMD";
+}
+
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_armv6.h b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_armv6.h
new file mode 100755 (executable)
index 0000000..6a9efe5
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __SBC_PRIMITIVES_ARMV6_H
+#define __SBC_PRIMITIVES_ARMV6_H
+
+#include "sbc_primitives.h"
+
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
+       defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
+       defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) || \
+       defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7__) || \
+       defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \
+       defined(__ARM_ARCH_7M__)
+#define SBC_HAVE_ARMV6 1
+#endif
+
+#if !defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15) && \
+       defined(__GNUC__) && defined(SBC_HAVE_ARMV6) && \
+       defined(__ARM_EABI__) && !defined(__ARM_NEON__) && \
+       (!defined(__thumb__) || defined(__thumb2__))
+
+#define SBC_BUILD_WITH_ARMV6_SUPPORT
+
+void sbc_init_primitives_armv6(struct sbc_encoder_state *encoder_state);
+
+#endif
+
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_iwmmxt.c b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_iwmmxt.c
new file mode 100755 (executable)
index 0000000..5be8933
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2010 Keith Mok <ek9852@gmail.com>
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdint.h>
+#include <limits.h>
+#include "sbc.h"
+#include "sbc_math.h"
+#include "sbc_tables.h"
+
+#include "sbc_primitives_iwmmxt.h"
+
+/*
+ * IWMMXT optimizations
+ */
+
+#ifdef SBC_BUILD_WITH_IWMMXT_SUPPORT
+
+static inline void sbc_analyze_four_iwmmxt(const int16_t *in, int32_t *out,
+                                       const FIXED_T *consts)
+{
+       __asm__ volatile (
+               "wldrd        wr0, [%0]\n"
+               "tbcstw       wr4, %2\n"
+               "wldrd        wr2, [%1]\n"
+               "wldrd        wr1, [%0, #8]\n"
+               "wldrd        wr3, [%1, #8]\n"
+               "wmadds       wr0, wr2, wr0\n"
+               " wldrd       wr6, [%0, #16]\n"
+               "wmadds       wr1, wr3, wr1\n"
+               " wldrd       wr7, [%0, #24]\n"
+               "waddwss      wr0, wr0, wr4\n"
+               " wldrd       wr8, [%1, #16]\n"
+               "waddwss      wr1, wr1, wr4\n"
+               " wldrd       wr9, [%1, #24]\n"
+               " wmadds      wr6, wr8, wr6\n"
+               "  wldrd      wr2, [%0, #32]\n"
+               " wmadds      wr7, wr9, wr7\n"
+               "  wldrd      wr3, [%0, #40]\n"
+               " waddwss     wr0, wr6, wr0\n"
+               "  wldrd      wr4, [%1, #32]\n"
+               " waddwss     wr1, wr7, wr1\n"
+               "  wldrd      wr5, [%1, #40]\n"
+               "  wmadds     wr2, wr4, wr2\n"
+               "wldrd        wr6, [%0, #48]\n"
+               "  wmadds     wr3, wr5, wr3\n"
+               "wldrd        wr7, [%0, #56]\n"
+               "  waddwss    wr0, wr2, wr0\n"
+               "wldrd        wr8, [%1, #48]\n"
+               "  waddwss    wr1, wr3, wr1\n"
+               "wldrd        wr9, [%1, #56]\n"
+               "wmadds       wr6, wr8, wr6\n"
+               " wldrd       wr2, [%0, #64]\n"
+               "wmadds       wr7, wr9, wr7\n"
+               " wldrd       wr3, [%0, #72]\n"
+               "waddwss      wr0, wr6, wr0\n"
+               " wldrd       wr4, [%1, #64]\n"
+               "waddwss      wr1, wr7, wr1\n"
+               " wldrd       wr5, [%1, #72]\n"
+               " wmadds      wr2, wr4, wr2\n"
+               "tmcr       wcgr0, %4\n"
+               " wmadds      wr3, wr5, wr3\n"
+               " waddwss     wr0, wr2, wr0\n"
+               " waddwss     wr1, wr3, wr1\n"
+               "\n"
+               "wsrawg       wr0, wr0, wcgr0\n"
+               " wldrd       wr4, [%1, #80]\n"
+               "wsrawg       wr1, wr1, wcgr0\n"
+               " wldrd       wr5, [%1, #88]\n"
+               "wpackwss     wr0, wr0, wr0\n"
+               " wldrd       wr6, [%1, #96]\n"
+               "wpackwss     wr1, wr1, wr1\n"
+               "wmadds       wr2, wr5, wr0\n"
+               " wldrd       wr7, [%1, #104]\n"
+               "wmadds       wr0, wr4, wr0\n"
+               "\n"
+               " wmadds      wr3, wr7, wr1\n"
+               " wmadds      wr1, wr6, wr1\n"
+               " waddwss     wr2, wr3, wr2\n"
+               " waddwss     wr0, wr1, wr0\n"
+               "\n"
+               "wstrd        wr0, [%3]\n"
+               "wstrd        wr2, [%3, #8]\n"
+               :
+               : "r" (in), "r" (consts),
+                       "r" (1 << (SBC_PROTO_FIXED4_SCALE - 1)), "r" (out),
+                       "r" (SBC_PROTO_FIXED4_SCALE)
+               : "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7",
+                 "wr8", "wr9", "wcgr0", "memory");
+}
+
+static inline void sbc_analyze_eight_iwmmxt(const int16_t *in, int32_t *out,
+                                                       const FIXED_T *consts)
+{
+       __asm__ volatile (
+               "wldrd        wr0, [%0]\n"
+               "tbcstw       wr15, %2\n"
+               "wldrd        wr1, [%0, #8]\n"
+               "wldrd        wr2, [%0, #16]\n"
+               "wldrd        wr3, [%0, #24]\n"
+               "wldrd        wr4, [%1]\n"
+               "wldrd        wr5, [%1, #8]\n"
+               "wldrd        wr6, [%1, #16]\n"
+               "wldrd        wr7, [%1, #24]\n"
+               "wmadds       wr0, wr0, wr4\n"
+               " wldrd       wr8, [%1, #32]\n"
+               "wmadds       wr1, wr1, wr5\n"
+               " wldrd       wr9, [%1, #40]\n"
+               "wmadds       wr2, wr2, wr6\n"
+               " wldrd      wr10, [%1, #48]\n"
+               "wmadds       wr3, wr3, wr7\n"
+               " wldrd      wr11, [%1, #56]\n"
+               "waddwss      wr0, wr0, wr15\n"
+               " wldrd       wr4, [%0, #32]\n"
+               "waddwss      wr1, wr1, wr15\n"
+               " wldrd       wr5, [%0, #40]\n"
+               "waddwss      wr2, wr2, wr15\n"
+               " wldrd       wr6, [%0, #48]\n"
+               "waddwss      wr3, wr3, wr15\n"
+               " wldrd       wr7, [%0, #56]\n"
+               " wmadds      wr4, wr4, wr8\n"
+               "  wldrd     wr12, [%0, #64]\n"
+               " wmadds      wr5, wr5, wr9\n"
+               "  wldrd     wr13, [%0, #72]\n"
+               " wmadds      wr6, wr6, wr10\n"
+               "  wldrd     wr14, [%0, #80]\n"
+               " wmadds      wr7, wr7, wr11\n"
+               "  wldrd     wr15, [%0, #88]\n"
+               " waddwss     wr0, wr4, wr0\n"
+               "  wldrd      wr8, [%1, #64]\n"
+               " waddwss     wr1, wr5, wr1\n"
+               "  wldrd      wr9, [%1, #72]\n"
+               " waddwss     wr2, wr6, wr2\n"
+               "  wldrd     wr10, [%1, #80]\n"
+               " waddwss     wr3, wr7, wr3\n"
+               "  wldrd     wr11, [%1, #88]\n"
+               "  wmadds    wr12, wr12, wr8\n"
+               "wldrd        wr4, [%0, #96]\n"
+               "  wmadds    wr13, wr13, wr9\n"
+               "wldrd        wr5, [%0, #104]\n"
+               "  wmadds    wr14, wr14, wr10\n"
+               "wldrd        wr6, [%0, #112]\n"
+               "  wmadds    wr15, wr15, wr11\n"
+               "wldrd        wr7, [%0, #120]\n"
+               "  waddwss    wr0, wr12, wr0\n"
+               "wldrd        wr8, [%1, #96]\n"
+               "  waddwss    wr1, wr13, wr1\n"
+               "wldrd        wr9, [%1, #104]\n"
+               "  waddwss    wr2, wr14, wr2\n"
+               "wldrd       wr10, [%1, #112]\n"
+               "  waddwss    wr3, wr15, wr3\n"
+               "wldrd       wr11, [%1, #120]\n"
+               "wmadds       wr4, wr4, wr8\n"
+               " wldrd      wr12, [%0, #128]\n"
+               "wmadds       wr5, wr5, wr9\n"
+               " wldrd      wr13, [%0, #136]\n"
+               "wmadds       wr6, wr6, wr10\n"
+               " wldrd      wr14, [%0, #144]\n"
+               "wmadds       wr7, wr7, wr11\n"
+               " wldrd      wr15, [%0, #152]\n"
+               "waddwss      wr0, wr4, wr0\n"
+               " wldrd       wr8, [%1, #128]\n"
+               "waddwss      wr1, wr5, wr1\n"
+               " wldrd       wr9, [%1, #136]\n"
+               "waddwss      wr2, wr6, wr2\n"
+               " wldrd      wr10, [%1, #144]\n"
+               " waddwss     wr3, wr7, wr3\n"
+               " wldrd     wr11, [%1, #152]\n"
+               " wmadds     wr12, wr12, wr8\n"
+               "tmcr       wcgr0, %4\n"
+               " wmadds     wr13, wr13, wr9\n"
+               " wmadds     wr14, wr14, wr10\n"
+               " wmadds     wr15, wr15, wr11\n"
+               " waddwss     wr0, wr12, wr0\n"
+               " waddwss     wr1, wr13, wr1\n"
+               " waddwss     wr2, wr14, wr2\n"
+               " waddwss     wr3, wr15, wr3\n"
+               "\n"
+               "wsrawg       wr0, wr0, wcgr0\n"
+               "wsrawg       wr1, wr1, wcgr0\n"
+               "wsrawg       wr2, wr2, wcgr0\n"
+               "wsrawg       wr3, wr3, wcgr0\n"
+               "\n"
+               "wpackwss     wr0, wr0, wr0\n"
+               "wpackwss     wr1, wr1, wr1\n"
+               " wldrd       wr4, [%1, #160]\n"
+               "wpackwss     wr2, wr2, wr2\n"
+               " wldrd       wr5, [%1, #168]\n"
+               "wpackwss     wr3, wr3, wr3\n"
+               "  wldrd      wr6, [%1, #192]\n"
+               " wmadds      wr4, wr4, wr0\n"
+               "  wldrd      wr7, [%1, #200]\n"
+               " wmadds      wr5, wr5, wr0\n"
+               "   wldrd     wr8, [%1, #224]\n"
+               "  wmadds     wr6, wr6, wr1\n"
+               "   wldrd     wr9, [%1, #232]\n"
+               "  wmadds     wr7, wr7, wr1\n"
+               "  waddwss    wr4, wr6, wr4\n"
+               "  waddwss    wr5, wr7, wr5\n"
+               "   wmadds    wr8, wr8, wr2\n"
+               "wldrd        wr6, [%1, #256]\n"
+               "   wmadds    wr9, wr9, wr2\n"
+               "wldrd        wr7, [%1, #264]\n"
+               "waddwss      wr4, wr8, wr4\n"
+               "   waddwss   wr5, wr9, wr5\n"
+               "wmadds       wr6, wr6, wr3\n"
+               "wmadds       wr7, wr7, wr3\n"
+               "waddwss      wr4, wr6, wr4\n"
+               "waddwss      wr5, wr7, wr5\n"
+               "\n"
+               "wstrd        wr4, [%3]\n"
+               "wstrd        wr5, [%3, #8]\n"
+               "\n"
+               "wldrd        wr6, [%1, #176]\n"
+               "wldrd        wr5, [%1, #184]\n"
+               "wmadds       wr5, wr5, wr0\n"
+               "wldrd        wr8, [%1, #208]\n"
+               "wmadds       wr0, wr6, wr0\n"
+               "wldrd        wr9, [%1, #216]\n"
+               "wmadds       wr9, wr9, wr1\n"
+               "wldrd        wr6, [%1, #240]\n"
+               "wmadds       wr1, wr8, wr1\n"
+               "wldrd        wr7, [%1, #248]\n"
+               "waddwss      wr0, wr1, wr0\n"
+               "waddwss      wr5, wr9, wr5\n"
+               "wmadds       wr7, wr7, wr2\n"
+               "wldrd        wr8, [%1, #272]\n"
+               "wmadds       wr2, wr6, wr2\n"
+               "wldrd        wr9, [%1, #280]\n"
+               "waddwss      wr0, wr2, wr0\n"
+               "waddwss      wr5, wr7, wr5\n"
+               "wmadds       wr9, wr9, wr3\n"
+               "wmadds       wr3, wr8, wr3\n"
+               "waddwss      wr0, wr3, wr0\n"
+               "waddwss      wr5, wr9, wr5\n"
+               "\n"
+               "wstrd        wr0, [%3, #16]\n"
+               "wstrd        wr5, [%3, #24]\n"
+               :
+               : "r" (in), "r" (consts),
+                       "r" (1 << (SBC_PROTO_FIXED8_SCALE - 1)), "r" (out),
+                       "r" (SBC_PROTO_FIXED8_SCALE)
+               : "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7",
+                 "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15",
+                 "wcgr0", "memory");
+}
+
+static inline void sbc_analyze_4b_4s_iwmmxt(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       sbc_analyze_four_iwmmxt(x + 12, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       sbc_analyze_four_iwmmxt(x + 8, out, analysis_consts_fixed4_simd_even);
+       out += out_stride;
+       sbc_analyze_four_iwmmxt(x + 4, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       sbc_analyze_four_iwmmxt(x + 0, out, analysis_consts_fixed4_simd_even);
+}
+
+static inline void sbc_analyze_4b_8s_iwmmxt(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       sbc_analyze_eight_iwmmxt(x + 24, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       sbc_analyze_eight_iwmmxt(x + 16, out, analysis_consts_fixed8_simd_even);
+       out += out_stride;
+       sbc_analyze_eight_iwmmxt(x + 8, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       sbc_analyze_eight_iwmmxt(x + 0, out, analysis_consts_fixed8_simd_even);
+}
+
+static inline void sbc_analyze_1b_8s_iwmmxt_even(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride);
+
+static inline void sbc_analyze_1b_8s_iwmmxt_odd(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       sbc_analyze_eight_iwmmxt(x, out, analysis_consts_fixed8_simd_odd);
+       state->sbc_analyze_8s = sbc_analyze_1b_8s_iwmmxt_even;
+}
+
+static inline void sbc_analyze_1b_8s_iwmmxt_even(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       sbc_analyze_eight_iwmmxt(x, out, analysis_consts_fixed8_simd_even);
+       state->sbc_analyze_8s = sbc_analyze_1b_8s_iwmmxt_odd;
+}
+
+void sbc_init_primitives_iwmmxt(struct sbc_encoder_state *state)
+{
+       state->sbc_analyze_4s = sbc_analyze_4b_4s_iwmmxt;
+       if (state->increment == 1)
+               state->sbc_analyze_8s = sbc_analyze_1b_8s_iwmmxt_odd;
+       else
+               state->sbc_analyze_8s = sbc_analyze_4b_8s_iwmmxt;
+       state->implementation_info = "IWMMXT";
+}
+
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_iwmmxt.h b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_iwmmxt.h
new file mode 100755 (executable)
index 0000000..b535e68
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2010 Keith Mok <ek9852@gmail.com>
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __SBC_PRIMITIVES_IWMMXT_H
+#define __SBC_PRIMITIVES_IWMMXT_H
+
+#include "sbc_primitives.h"
+
+#if defined(__GNUC__) && defined(__IWMMXT__) && \
+               !defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15)
+
+#define SBC_BUILD_WITH_IWMMXT_SUPPORT
+
+void sbc_init_primitives_iwmmxt(struct sbc_encoder_state *encoder_state);
+
+#endif
+
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_mmx.c b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_mmx.c
new file mode 100755 (executable)
index 0000000..e2c3e56
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdint.h>
+#include <limits.h>
+#include "sbc.h"
+#include "sbc_math.h"
+#include "sbc_tables.h"
+
+#include "sbc_primitives_mmx.h"
+
+/*
+ * MMX optimizations
+ */
+
+#ifdef SBC_BUILD_WITH_MMX_SUPPORT
+
+static inline void sbc_analyze_four_mmx(const int16_t *in, int32_t *out,
+                                       const FIXED_T *consts)
+{
+       static const SBC_ALIGNED int32_t round_c[2] = {
+               1 << (SBC_PROTO_FIXED4_SCALE - 1),
+               1 << (SBC_PROTO_FIXED4_SCALE - 1),
+       };
+       __asm__ volatile (
+               "movq        (%0), %%mm0\n"
+               "movq       8(%0), %%mm1\n"
+               "pmaddwd     (%1), %%mm0\n"
+               "pmaddwd    8(%1), %%mm1\n"
+               "paddd       (%2), %%mm0\n"
+               "paddd       (%2), %%mm1\n"
+               "\n"
+               "movq      16(%0), %%mm2\n"
+               "movq      24(%0), %%mm3\n"
+               "pmaddwd   16(%1), %%mm2\n"
+               "pmaddwd   24(%1), %%mm3\n"
+               "paddd      %%mm2, %%mm0\n"
+               "paddd      %%mm3, %%mm1\n"
+               "\n"
+               "movq      32(%0), %%mm2\n"
+               "movq      40(%0), %%mm3\n"
+               "pmaddwd   32(%1), %%mm2\n"
+               "pmaddwd   40(%1), %%mm3\n"
+               "paddd      %%mm2, %%mm0\n"
+               "paddd      %%mm3, %%mm1\n"
+               "\n"
+               "movq      48(%0), %%mm2\n"
+               "movq      56(%0), %%mm3\n"
+               "pmaddwd   48(%1), %%mm2\n"
+               "pmaddwd   56(%1), %%mm3\n"
+               "paddd      %%mm2, %%mm0\n"
+               "paddd      %%mm3, %%mm1\n"
+               "\n"
+               "movq      64(%0), %%mm2\n"
+               "movq      72(%0), %%mm3\n"
+               "pmaddwd   64(%1), %%mm2\n"
+               "pmaddwd   72(%1), %%mm3\n"
+               "paddd      %%mm2, %%mm0\n"
+               "paddd      %%mm3, %%mm1\n"
+               "\n"
+               "psrad         %4, %%mm0\n"
+               "psrad         %4, %%mm1\n"
+               "packssdw   %%mm0, %%mm0\n"
+               "packssdw   %%mm1, %%mm1\n"
+               "\n"
+               "movq       %%mm0, %%mm2\n"
+               "pmaddwd   80(%1), %%mm0\n"
+               "pmaddwd   88(%1), %%mm2\n"
+               "\n"
+               "movq       %%mm1, %%mm3\n"
+               "pmaddwd   96(%1), %%mm1\n"
+               "pmaddwd  104(%1), %%mm3\n"
+               "paddd      %%mm1, %%mm0\n"
+               "paddd      %%mm3, %%mm2\n"
+               "\n"
+               "movq       %%mm0, (%3)\n"
+               "movq       %%mm2, 8(%3)\n"
+               :
+               : "r" (in), "r" (consts), "r" (&round_c), "r" (out),
+                       "i" (SBC_PROTO_FIXED4_SCALE)
+               : "cc", "memory");
+}
+
+static inline void sbc_analyze_eight_mmx(const int16_t *in, int32_t *out,
+                                                       const FIXED_T *consts)
+{
+       static const SBC_ALIGNED int32_t round_c[2] = {
+               1 << (SBC_PROTO_FIXED8_SCALE - 1),
+               1 << (SBC_PROTO_FIXED8_SCALE - 1),
+       };
+       __asm__ volatile (
+               "movq        (%0), %%mm0\n"
+               "movq       8(%0), %%mm1\n"
+               "movq      16(%0), %%mm2\n"
+               "movq      24(%0), %%mm3\n"
+               "pmaddwd     (%1), %%mm0\n"
+               "pmaddwd    8(%1), %%mm1\n"
+               "pmaddwd   16(%1), %%mm2\n"
+               "pmaddwd   24(%1), %%mm3\n"
+               "paddd       (%2), %%mm0\n"
+               "paddd       (%2), %%mm1\n"
+               "paddd       (%2), %%mm2\n"
+               "paddd       (%2), %%mm3\n"
+               "\n"
+               "movq      32(%0), %%mm4\n"
+               "movq      40(%0), %%mm5\n"
+               "movq      48(%0), %%mm6\n"
+               "movq      56(%0), %%mm7\n"
+               "pmaddwd   32(%1), %%mm4\n"
+               "pmaddwd   40(%1), %%mm5\n"
+               "pmaddwd   48(%1), %%mm6\n"
+               "pmaddwd   56(%1), %%mm7\n"
+               "paddd      %%mm4, %%mm0\n"
+               "paddd      %%mm5, %%mm1\n"
+               "paddd      %%mm6, %%mm2\n"
+               "paddd      %%mm7, %%mm3\n"
+               "\n"
+               "movq      64(%0), %%mm4\n"
+               "movq      72(%0), %%mm5\n"
+               "movq      80(%0), %%mm6\n"
+               "movq      88(%0), %%mm7\n"
+               "pmaddwd   64(%1), %%mm4\n"
+               "pmaddwd   72(%1), %%mm5\n"
+               "pmaddwd   80(%1), %%mm6\n"
+               "pmaddwd   88(%1), %%mm7\n"
+               "paddd      %%mm4, %%mm0\n"
+               "paddd      %%mm5, %%mm1\n"
+               "paddd      %%mm6, %%mm2\n"
+               "paddd      %%mm7, %%mm3\n"
+               "\n"
+               "movq      96(%0), %%mm4\n"
+               "movq     104(%0), %%mm5\n"
+               "movq     112(%0), %%mm6\n"
+               "movq     120(%0), %%mm7\n"
+               "pmaddwd   96(%1), %%mm4\n"
+               "pmaddwd  104(%1), %%mm5\n"
+               "pmaddwd  112(%1), %%mm6\n"
+               "pmaddwd  120(%1), %%mm7\n"
+               "paddd      %%mm4, %%mm0\n"
+               "paddd      %%mm5, %%mm1\n"
+               "paddd      %%mm6, %%mm2\n"
+               "paddd      %%mm7, %%mm3\n"
+               "\n"
+               "movq     128(%0), %%mm4\n"
+               "movq     136(%0), %%mm5\n"
+               "movq     144(%0), %%mm6\n"
+               "movq     152(%0), %%mm7\n"
+               "pmaddwd  128(%1), %%mm4\n"
+               "pmaddwd  136(%1), %%mm5\n"
+               "pmaddwd  144(%1), %%mm6\n"
+               "pmaddwd  152(%1), %%mm7\n"
+               "paddd      %%mm4, %%mm0\n"
+               "paddd      %%mm5, %%mm1\n"
+               "paddd      %%mm6, %%mm2\n"
+               "paddd      %%mm7, %%mm3\n"
+               "\n"
+               "psrad         %4, %%mm0\n"
+               "psrad         %4, %%mm1\n"
+               "psrad         %4, %%mm2\n"
+               "psrad         %4, %%mm3\n"
+               "\n"
+               "packssdw   %%mm0, %%mm0\n"
+               "packssdw   %%mm1, %%mm1\n"
+               "packssdw   %%mm2, %%mm2\n"
+               "packssdw   %%mm3, %%mm3\n"
+               "\n"
+               "movq       %%mm0, %%mm4\n"
+               "movq       %%mm0, %%mm5\n"
+               "pmaddwd  160(%1), %%mm4\n"
+               "pmaddwd  168(%1), %%mm5\n"
+               "\n"
+               "movq       %%mm1, %%mm6\n"
+               "movq       %%mm1, %%mm7\n"
+               "pmaddwd  192(%1), %%mm6\n"
+               "pmaddwd  200(%1), %%mm7\n"
+               "paddd      %%mm6, %%mm4\n"
+               "paddd      %%mm7, %%mm5\n"
+               "\n"
+               "movq       %%mm2, %%mm6\n"
+               "movq       %%mm2, %%mm7\n"
+               "pmaddwd  224(%1), %%mm6\n"
+               "pmaddwd  232(%1), %%mm7\n"
+               "paddd      %%mm6, %%mm4\n"
+               "paddd      %%mm7, %%mm5\n"
+               "\n"
+               "movq       %%mm3, %%mm6\n"
+               "movq       %%mm3, %%mm7\n"
+               "pmaddwd  256(%1), %%mm6\n"
+               "pmaddwd  264(%1), %%mm7\n"
+               "paddd      %%mm6, %%mm4\n"
+               "paddd      %%mm7, %%mm5\n"
+               "\n"
+               "movq       %%mm4, (%3)\n"
+               "movq       %%mm5, 8(%3)\n"
+               "\n"
+               "movq       %%mm0, %%mm5\n"
+               "pmaddwd  176(%1), %%mm0\n"
+               "pmaddwd  184(%1), %%mm5\n"
+               "\n"
+               "movq       %%mm1, %%mm7\n"
+               "pmaddwd  208(%1), %%mm1\n"
+               "pmaddwd  216(%1), %%mm7\n"
+               "paddd      %%mm1, %%mm0\n"
+               "paddd      %%mm7, %%mm5\n"
+               "\n"
+               "movq       %%mm2, %%mm7\n"
+               "pmaddwd  240(%1), %%mm2\n"
+               "pmaddwd  248(%1), %%mm7\n"
+               "paddd      %%mm2, %%mm0\n"
+               "paddd      %%mm7, %%mm5\n"
+               "\n"
+               "movq       %%mm3, %%mm7\n"
+               "pmaddwd  272(%1), %%mm3\n"
+               "pmaddwd  280(%1), %%mm7\n"
+               "paddd      %%mm3, %%mm0\n"
+               "paddd      %%mm7, %%mm5\n"
+               "\n"
+               "movq       %%mm0, 16(%3)\n"
+               "movq       %%mm5, 24(%3)\n"
+               :
+               : "r" (in), "r" (consts), "r" (&round_c), "r" (out),
+                       "i" (SBC_PROTO_FIXED8_SCALE)
+               : "cc", "memory");
+}
+
+static inline void sbc_analyze_4b_4s_mmx(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       sbc_analyze_four_mmx(x + 12, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       sbc_analyze_four_mmx(x + 8, out, analysis_consts_fixed4_simd_even);
+       out += out_stride;
+       sbc_analyze_four_mmx(x + 4, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       sbc_analyze_four_mmx(x + 0, out, analysis_consts_fixed4_simd_even);
+
+       __asm__ volatile ("emms\n");
+}
+
+static inline void sbc_analyze_4b_8s_mmx(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       sbc_analyze_eight_mmx(x + 24, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       sbc_analyze_eight_mmx(x + 16, out, analysis_consts_fixed8_simd_even);
+       out += out_stride;
+       sbc_analyze_eight_mmx(x + 8, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       sbc_analyze_eight_mmx(x + 0, out, analysis_consts_fixed8_simd_even);
+
+       __asm__ volatile ("emms\n");
+}
+
+static inline void sbc_analyze_1b_8s_mmx_even(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride);
+
+static inline void sbc_analyze_1b_8s_mmx_odd(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       sbc_analyze_eight_mmx(x, out, analysis_consts_fixed8_simd_odd);
+       state->sbc_analyze_8s = sbc_analyze_1b_8s_mmx_even;
+
+       __asm__ volatile ("emms\n");
+}
+
+static inline void sbc_analyze_1b_8s_mmx_even(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       sbc_analyze_eight_mmx(x, out, analysis_consts_fixed8_simd_even);
+       state->sbc_analyze_8s = sbc_analyze_1b_8s_mmx_odd;
+
+       __asm__ volatile ("emms\n");
+}
+
+static void sbc_calc_scalefactors_mmx(
+       int32_t sb_sample_f[16][2][8],
+       uint32_t scale_factor[2][8],
+       int blocks, int channels, int subbands)
+{
+       static const SBC_ALIGNED int32_t consts[2] = {
+               1 << SCALE_OUT_BITS,
+               1 << SCALE_OUT_BITS,
+       };
+       int ch, sb;
+       intptr_t blk;
+       for (ch = 0; ch < channels; ch++) {
+               for (sb = 0; sb < subbands; sb += 2) {
+                       blk = (blocks - 1) * (((char *) &sb_sample_f[1][0][0] -
+                               (char *) &sb_sample_f[0][0][0]));
+                       __asm__ volatile (
+                               "movq         (%4), %%mm0\n"
+                       "1:\n"
+                               "movq     (%1, %0), %%mm1\n"
+                               "pxor        %%mm2, %%mm2\n"
+                               "pcmpgtd     %%mm2, %%mm1\n"
+                               "paddd    (%1, %0), %%mm1\n"
+                               "pcmpgtd     %%mm1, %%mm2\n"
+                               "pxor        %%mm2, %%mm1\n"
+
+                               "por         %%mm1, %%mm0\n"
+
+                               "sub            %2, %0\n"
+                               "jns            1b\n"
+
+                               "movd        %%mm0, %k0\n"
+                               "psrlq         $32, %%mm0\n"
+                               "bsrl          %k0, %k0\n"
+                               "subl           %5, %k0\n"
+                               "movl          %k0, (%3)\n"
+
+                               "movd        %%mm0, %k0\n"
+                               "bsrl          %k0, %k0\n"
+                               "subl           %5, %k0\n"
+                               "movl          %k0, 4(%3)\n"
+                       : "+r" (blk)
+                       : "r" (&sb_sample_f[0][ch][sb]),
+                               "i" ((char *) &sb_sample_f[1][0][0] -
+                                       (char *) &sb_sample_f[0][0][0]),
+                               "r" (&scale_factor[ch][sb]),
+                               "r" (&consts),
+                               "i" (SCALE_OUT_BITS)
+                       : "cc", "memory");
+               }
+       }
+       __asm__ volatile ("emms\n");
+}
+
+static int check_mmx_support(void)
+{
+#ifdef __amd64__
+       return 1; /* We assume that all 64-bit processors have MMX support */
+#else
+       int cpuid_feature_information;
+       __asm__ volatile (
+               /* According to Intel manual, CPUID instruction is supported
+                * if the value of ID bit (bit 21) in EFLAGS can be modified */
+               "pushf\n"
+               "movl     (%%esp),   %0\n"
+               "xorl     $0x200000, (%%esp)\n" /* try to modify ID bit */
+               "popf\n"
+               "pushf\n"
+               "xorl     (%%esp),   %0\n"      /* check if ID bit changed */
+               "jz       1f\n"
+               "push     %%eax\n"
+               "push     %%ebx\n"
+               "push     %%ecx\n"
+               "mov      $1,        %%eax\n"
+               "cpuid\n"
+               "pop      %%ecx\n"
+               "pop      %%ebx\n"
+               "pop      %%eax\n"
+               "1:\n"
+               "popf\n"
+               : "=d" (cpuid_feature_information)
+               :
+               : "cc");
+    return cpuid_feature_information & (1 << 23);
+#endif
+}
+
+void sbc_init_primitives_mmx(struct sbc_encoder_state *state)
+{
+       if (check_mmx_support()) {
+               state->sbc_analyze_4s = sbc_analyze_4b_4s_mmx;
+               if (state->increment == 1)
+                       state->sbc_analyze_8s = sbc_analyze_1b_8s_mmx_odd;
+               else
+                       state->sbc_analyze_8s = sbc_analyze_4b_8s_mmx;
+               state->sbc_calc_scalefactors = sbc_calc_scalefactors_mmx;
+               state->implementation_info = "MMX";
+       }
+}
+
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_mmx.h b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_mmx.h
new file mode 100755 (executable)
index 0000000..e0e728b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __SBC_PRIMITIVES_MMX_H
+#define __SBC_PRIMITIVES_MMX_H
+
+#include "sbc_primitives.h"
+
+#if defined(__GNUC__) && (defined(__i386__) || defined(__amd64__)) && \
+               !defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15)
+
+#define SBC_BUILD_WITH_MMX_SUPPORT
+
+void sbc_init_primitives_mmx(struct sbc_encoder_state *encoder_state);
+
+#endif
+
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_neon.c b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_neon.c
new file mode 100755 (executable)
index 0000000..eda4ed3
--- /dev/null
@@ -0,0 +1,893 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdint.h>
+#include <limits.h>
+#include "sbc.h"
+#include "sbc_math.h"
+#include "sbc_tables.h"
+
+#include "sbc_primitives_neon.h"
+
+/*
+ * ARM NEON optimizations
+ */
+
+#ifdef SBC_BUILD_WITH_NEON_SUPPORT
+
+static inline void _sbc_analyze_four_neon(const int16_t *in, int32_t *out,
+                                                       const FIXED_T *consts)
+{
+       /* TODO: merge even and odd cases (or even merge all four calls to this
+        * function) in order to have only aligned reads from 'in' array
+        * and reduce number of load instructions */
+       __asm__ volatile (
+               "vld1.16    {d4, d5}, [%0, :64]!\n"
+               "vld1.16    {d8, d9}, [%1, :128]!\n"
+
+               "vmull.s16  q0, d4, d8\n"
+               "vld1.16    {d6,  d7}, [%0, :64]!\n"
+               "vmull.s16  q1, d5, d9\n"
+               "vld1.16    {d10, d11}, [%1, :128]!\n"
+
+               "vmlal.s16  q0, d6, d10\n"
+               "vld1.16    {d4, d5}, [%0, :64]!\n"
+               "vmlal.s16  q1, d7, d11\n"
+               "vld1.16    {d8, d9}, [%1, :128]!\n"
+
+               "vmlal.s16  q0, d4, d8\n"
+               "vld1.16    {d6,  d7}, [%0, :64]!\n"
+               "vmlal.s16  q1, d5, d9\n"
+               "vld1.16    {d10, d11}, [%1, :128]!\n"
+
+               "vmlal.s16  q0, d6, d10\n"
+               "vld1.16    {d4, d5}, [%0, :64]!\n"
+               "vmlal.s16  q1, d7, d11\n"
+               "vld1.16    {d8, d9}, [%1, :128]!\n"
+
+               "vmlal.s16  q0, d4, d8\n"
+               "vmlal.s16  q1, d5, d9\n"
+
+               "vpadd.s32  d0, d0, d1\n"
+               "vpadd.s32  d1, d2, d3\n"
+
+               "vrshrn.s32 d0, q0, %3\n"
+
+               "vld1.16    {d2, d3, d4, d5}, [%1, :128]!\n"
+
+               "vdup.i32   d1, d0[1]\n"  /* TODO: can be eliminated */
+               "vdup.i32   d0, d0[0]\n"  /* TODO: can be eliminated */
+
+               "vmull.s16  q3, d2, d0\n"
+               "vmull.s16  q4, d3, d0\n"
+               "vmlal.s16  q3, d4, d1\n"
+               "vmlal.s16  q4, d5, d1\n"
+
+               "vpadd.s32  d0, d6, d7\n" /* TODO: can be eliminated */
+               "vpadd.s32  d1, d8, d9\n" /* TODO: can be eliminated */
+
+               "vst1.32    {d0, d1}, [%2, :128]\n"
+               : "+r" (in), "+r" (consts)
+               : "r" (out),
+                       "i" (SBC_PROTO_FIXED4_SCALE)
+               : "memory",
+                       "d0", "d1", "d2", "d3", "d4", "d5",
+                       "d6", "d7", "d8", "d9", "d10", "d11");
+}
+
+static inline void _sbc_analyze_eight_neon(const int16_t *in, int32_t *out,
+                                                       const FIXED_T *consts)
+{
+       /* TODO: merge even and odd cases (or even merge all four calls to this
+        * function) in order to have only aligned reads from 'in' array
+        * and reduce number of load instructions */
+       __asm__ volatile (
+               "vld1.16    {d4, d5}, [%0, :64]!\n"
+               "vld1.16    {d8, d9}, [%1, :128]!\n"
+
+               "vmull.s16  q6, d4, d8\n"
+               "vld1.16    {d6,  d7}, [%0, :64]!\n"
+               "vmull.s16  q7, d5, d9\n"
+               "vld1.16    {d10, d11}, [%1, :128]!\n"
+               "vmull.s16  q8, d6, d10\n"
+               "vld1.16    {d4, d5}, [%0, :64]!\n"
+               "vmull.s16  q9, d7, d11\n"
+               "vld1.16    {d8, d9}, [%1, :128]!\n"
+
+               "vmlal.s16  q6, d4, d8\n"
+               "vld1.16    {d6,  d7}, [%0, :64]!\n"
+               "vmlal.s16  q7, d5, d9\n"
+               "vld1.16    {d10, d11}, [%1, :128]!\n"
+               "vmlal.s16  q8, d6, d10\n"
+               "vld1.16    {d4, d5}, [%0, :64]!\n"
+               "vmlal.s16  q9, d7, d11\n"
+               "vld1.16    {d8, d9}, [%1, :128]!\n"
+
+               "vmlal.s16  q6, d4, d8\n"
+               "vld1.16    {d6,  d7}, [%0, :64]!\n"
+               "vmlal.s16  q7, d5, d9\n"
+               "vld1.16    {d10, d11}, [%1, :128]!\n"
+               "vmlal.s16  q8, d6, d10\n"
+               "vld1.16    {d4, d5}, [%0, :64]!\n"
+               "vmlal.s16  q9, d7, d11\n"
+               "vld1.16    {d8, d9}, [%1, :128]!\n"
+
+               "vmlal.s16  q6, d4, d8\n"
+               "vld1.16    {d6,  d7}, [%0, :64]!\n"
+               "vmlal.s16  q7, d5, d9\n"
+               "vld1.16    {d10, d11}, [%1, :128]!\n"
+               "vmlal.s16  q8, d6, d10\n"
+               "vld1.16    {d4, d5}, [%0, :64]!\n"
+               "vmlal.s16  q9, d7, d11\n"
+               "vld1.16    {d8, d9}, [%1, :128]!\n"
+
+               "vmlal.s16  q6, d4, d8\n"
+               "vld1.16    {d6,  d7}, [%0, :64]!\n"
+               "vmlal.s16  q7, d5, d9\n"
+               "vld1.16    {d10, d11}, [%1, :128]!\n"
+
+               "vmlal.s16  q8, d6, d10\n"
+               "vmlal.s16  q9, d7, d11\n"
+
+               "vpadd.s32  d0, d12, d13\n"
+               "vpadd.s32  d1, d14, d15\n"
+               "vpadd.s32  d2, d16, d17\n"
+               "vpadd.s32  d3, d18, d19\n"
+
+               "vrshr.s32 q0, q0, %3\n"
+               "vrshr.s32 q1, q1, %3\n"
+               "vmovn.s32 d0, q0\n"
+               "vmovn.s32 d1, q1\n"
+
+               "vdup.i32   d3, d1[1]\n"  /* TODO: can be eliminated */
+               "vdup.i32   d2, d1[0]\n"  /* TODO: can be eliminated */
+               "vdup.i32   d1, d0[1]\n"  /* TODO: can be eliminated */
+               "vdup.i32   d0, d0[0]\n"  /* TODO: can be eliminated */
+
+               "vld1.16    {d4, d5}, [%1, :128]!\n"
+               "vmull.s16  q6, d4, d0\n"
+               "vld1.16    {d6, d7}, [%1, :128]!\n"
+               "vmull.s16  q7, d5, d0\n"
+               "vmull.s16  q8, d6, d0\n"
+               "vmull.s16  q9, d7, d0\n"
+
+               "vld1.16    {d4, d5}, [%1, :128]!\n"
+               "vmlal.s16  q6, d4, d1\n"
+               "vld1.16    {d6, d7}, [%1, :128]!\n"
+               "vmlal.s16  q7, d5, d1\n"
+               "vmlal.s16  q8, d6, d1\n"
+               "vmlal.s16  q9, d7, d1\n"
+
+               "vld1.16    {d4, d5}, [%1, :128]!\n"
+               "vmlal.s16  q6, d4, d2\n"
+               "vld1.16    {d6, d7}, [%1, :128]!\n"
+               "vmlal.s16  q7, d5, d2\n"
+               "vmlal.s16  q8, d6, d2\n"
+               "vmlal.s16  q9, d7, d2\n"
+
+               "vld1.16    {d4, d5}, [%1, :128]!\n"
+               "vmlal.s16  q6, d4, d3\n"
+               "vld1.16    {d6, d7}, [%1, :128]!\n"
+               "vmlal.s16  q7, d5, d3\n"
+               "vmlal.s16  q8, d6, d3\n"
+               "vmlal.s16  q9, d7, d3\n"
+
+               "vpadd.s32  d0, d12, d13\n" /* TODO: can be eliminated */
+               "vpadd.s32  d1, d14, d15\n" /* TODO: can be eliminated */
+               "vpadd.s32  d2, d16, d17\n" /* TODO: can be eliminated */
+               "vpadd.s32  d3, d18, d19\n" /* TODO: can be eliminated */
+
+               "vst1.32    {d0, d1, d2, d3}, [%2, :128]\n"
+               : "+r" (in), "+r" (consts)
+               : "r" (out),
+                       "i" (SBC_PROTO_FIXED8_SCALE)
+               : "memory",
+                       "d0", "d1", "d2", "d3", "d4", "d5",
+                       "d6", "d7", "d8", "d9", "d10", "d11",
+                       "d12", "d13", "d14", "d15", "d16", "d17",
+                       "d18", "d19");
+}
+
+static inline void sbc_analyze_4b_4s_neon(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       _sbc_analyze_four_neon(x + 12, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       _sbc_analyze_four_neon(x + 8, out, analysis_consts_fixed4_simd_even);
+       out += out_stride;
+       _sbc_analyze_four_neon(x + 4, out, analysis_consts_fixed4_simd_odd);
+       out += out_stride;
+       _sbc_analyze_four_neon(x + 0, out, analysis_consts_fixed4_simd_even);
+}
+
+static inline void sbc_analyze_4b_8s_neon(struct sbc_encoder_state *state,
+               int16_t *x, int32_t *out, int out_stride)
+{
+       /* Analyze blocks */
+       _sbc_analyze_eight_neon(x + 24, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       _sbc_analyze_eight_neon(x + 16, out, analysis_consts_fixed8_simd_even);
+       out += out_stride;
+       _sbc_analyze_eight_neon(x + 8, out, analysis_consts_fixed8_simd_odd);
+       out += out_stride;
+       _sbc_analyze_eight_neon(x + 0, out, analysis_consts_fixed8_simd_even);
+}
+
+static void sbc_calc_scalefactors_neon(
+       int32_t sb_sample_f[16][2][8],
+       uint32_t scale_factor[2][8],
+       int blocks, int channels, int subbands)
+{
+       int ch, sb;
+       for (ch = 0; ch < channels; ch++) {
+               for (sb = 0; sb < subbands; sb += 4) {
+                       int blk = blocks;
+                       int32_t *in = &sb_sample_f[0][ch][sb];
+                       __asm__ volatile (
+                               "vmov.s32  q0, #0\n"
+                               "vmov.s32  q1, %[c1]\n"
+                               "vmov.s32  q14, #1\n"
+                               "vmov.s32  q15, %[c2]\n"
+                               "vadd.s32  q1, q1, q14\n"
+                       "1:\n"
+                               "vld1.32   {d16, d17}, [%[in], :128], %[inc]\n"
+                               "vabs.s32  q8,  q8\n"
+                               "vld1.32   {d18, d19}, [%[in], :128], %[inc]\n"
+                               "vabs.s32  q9,  q9\n"
+                               "vld1.32   {d20, d21}, [%[in], :128], %[inc]\n"
+                               "vabs.s32  q10, q10\n"
+                               "vld1.32   {d22, d23}, [%[in], :128], %[inc]\n"
+                               "vabs.s32  q11, q11\n"
+                               "vmax.s32  q0,  q0,  q8\n"
+                               "vmax.s32  q1,  q1,  q9\n"
+                               "vmax.s32  q0,  q0,  q10\n"
+                               "vmax.s32  q1,  q1,  q11\n"
+                               "subs      %[blk], %[blk], #4\n"
+                               "bgt       1b\n"
+                               "vmax.s32  q0,  q0,  q1\n"
+                               "vsub.s32  q0,  q0,  q14\n"
+                               "vclz.s32  q0,  q0\n"
+                               "vsub.s32  q0,  q15, q0\n"
+                               "vst1.32   {d0, d1}, [%[out], :128]\n"
+                       :
+                         [blk]    "+r" (blk),
+                         [in]     "+r" (in)
+                       :
+                         [inc]     "r" ((char *) &sb_sample_f[1][0][0] -
+                                        (char *) &sb_sample_f[0][0][0]),
+                         [out]     "r" (&scale_factor[ch][sb]),
+                         [c1]      "i" (1 << SCALE_OUT_BITS),
+                         [c2]      "i" (31 - SCALE_OUT_BITS)
+                       : "d0", "d1", "d2", "d3", "d16", "d17", "d18", "d19",
+                         "d20", "d21", "d22", "d23", "d24", "d25", "d26",
+                         "d27", "d28", "d29", "d30", "d31", "cc", "memory");
+               }
+       }
+}
+
+int sbc_calc_scalefactors_j_neon(
+       int32_t sb_sample_f[16][2][8],
+       uint32_t scale_factor[2][8],
+       int blocks, int subbands)
+{
+       static SBC_ALIGNED int32_t joint_bits_mask[8] = {
+               8,   4,  2,  1, 128, 64, 32, 16
+       };
+       int joint, i;
+       int32_t  *in0, *in1;
+       int32_t  *in = &sb_sample_f[0][0][0];
+       uint32_t *out0, *out1;
+       uint32_t *out = &scale_factor[0][0];
+       int32_t  *consts = joint_bits_mask;
+
+       i = subbands;
+
+       __asm__ volatile (
+               /*
+                * constants: q13 = (31 - SCALE_OUT_BITS), q14 = 1
+                * input:     q0  = ((1 << SCALE_OUT_BITS) + 1)
+                *            %[in0] - samples for channel 0
+                *            %[in1] - samples for shannel 1
+                * output:    q0, q1 - scale factors without joint stereo
+                *            q2, q3 - scale factors with joint stereo
+                *            q15    - joint stereo selection mask
+                */
+               ".macro calc_scalefactors\n"
+                       "vmov.s32  q1, q0\n"
+                       "vmov.s32  q2, q0\n"
+                       "vmov.s32  q3, q0\n"
+                       "mov       %[i], %[blocks]\n"
+               "1:\n"
+                       "vld1.32   {d18, d19}, [%[in1], :128], %[inc]\n"
+                       "vbic.s32  q11, q9,  q14\n"
+                       "vld1.32   {d16, d17}, [%[in0], :128], %[inc]\n"
+                       "vhadd.s32 q10, q8,  q11\n"
+                       "vhsub.s32 q11, q8,  q11\n"
+                       "vabs.s32  q8,  q8\n"
+                       "vabs.s32  q9,  q9\n"
+                       "vabs.s32  q10, q10\n"
+                       "vabs.s32  q11, q11\n"
+                       "vmax.s32  q0,  q0,  q8\n"
+                       "vmax.s32  q1,  q1,  q9\n"
+                       "vmax.s32  q2,  q2,  q10\n"
+                       "vmax.s32  q3,  q3,  q11\n"
+                       "subs      %[i], %[i], #1\n"
+                       "bgt       1b\n"
+                       "vsub.s32  q0,  q0,  q14\n"
+                       "vsub.s32  q1,  q1,  q14\n"
+                       "vsub.s32  q2,  q2,  q14\n"
+                       "vsub.s32  q3,  q3,  q14\n"
+                       "vclz.s32  q0,  q0\n"
+                       "vclz.s32  q1,  q1\n"
+                       "vclz.s32  q2,  q2\n"
+                       "vclz.s32  q3,  q3\n"
+                       "vsub.s32  q0,  q13, q0\n"
+                       "vsub.s32  q1,  q13, q1\n"
+                       "vsub.s32  q2,  q13, q2\n"
+                       "vsub.s32  q3,  q13, q3\n"
+               ".endm\n"
+               /*
+                * constants: q14 = 1
+                * input: q15    - joint stereo selection mask
+                *        %[in0] - value set by calc_scalefactors macro
+                *        %[in1] - value set by calc_scalefactors macro
+                */
+               ".macro update_joint_stereo_samples\n"
+                       "sub       %[out1], %[in1], %[inc]\n"
+                       "sub       %[out0], %[in0], %[inc]\n"
+                       "sub       %[in1], %[in1], %[inc], asl #1\n"
+                       "sub       %[in0], %[in0], %[inc], asl #1\n"
+                       "vld1.32   {d18, d19}, [%[in1], :128]\n"
+                       "vbic.s32  q11, q9,  q14\n"
+                       "vld1.32   {d16, d17}, [%[in0], :128]\n"
+                       "vld1.32   {d2, d3}, [%[out1], :128]\n"
+                       "vbic.s32  q3,  q1,  q14\n"
+                       "vld1.32   {d0, d1}, [%[out0], :128]\n"
+                       "vhsub.s32 q10, q8,  q11\n"
+                       "vhadd.s32 q11, q8,  q11\n"
+                       "vhsub.s32 q2,  q0,  q3\n"
+                       "vhadd.s32 q3,  q0,  q3\n"
+                       "vbif.s32  q10, q9,  q15\n"
+                       "vbif.s32  d22, d16, d30\n"
+                       "sub       %[inc], %[zero], %[inc], asl #1\n"
+                       "sub       %[i], %[blocks], #2\n"
+               "2:\n"
+                       "vbif.s32  d23, d17, d31\n"
+                       "vst1.32   {d20, d21}, [%[in1], :128], %[inc]\n"
+                       "vbif.s32  d4,  d2,  d30\n"
+                       "vld1.32   {d18, d19}, [%[in1], :128]\n"
+                       "vbif.s32  d5,  d3,  d31\n"
+                       "vst1.32   {d22, d23}, [%[in0], :128], %[inc]\n"
+                       "vbif.s32  d6,  d0,  d30\n"
+                       "vld1.32   {d16, d17}, [%[in0], :128]\n"
+                       "vbif.s32  d7,  d1,  d31\n"
+                       "vst1.32   {d4, d5}, [%[out1], :128], %[inc]\n"
+                       "vbic.s32  q11, q9,  q14\n"
+                       "vld1.32   {d2, d3}, [%[out1], :128]\n"
+                       "vst1.32   {d6, d7}, [%[out0], :128], %[inc]\n"
+                       "vbic.s32  q3,  q1,  q14\n"
+                       "vld1.32   {d0, d1}, [%[out0], :128]\n"
+                       "vhsub.s32 q10, q8,  q11\n"
+                       "vhadd.s32 q11, q8,  q11\n"
+                       "vhsub.s32 q2,  q0,  q3\n"
+                       "vhadd.s32 q3,  q0,  q3\n"
+                       "vbif.s32  q10, q9,  q15\n"
+                       "vbif.s32  d22, d16, d30\n"
+                       "subs      %[i], %[i], #2\n"
+                       "bgt       2b\n"
+                       "sub       %[inc], %[zero], %[inc], asr #1\n"
+                       "vbif.s32  d23, d17, d31\n"
+                       "vst1.32   {d20, d21}, [%[in1], :128]\n"
+                       "vbif.s32  q2,  q1,  q15\n"
+                       "vst1.32   {d22, d23}, [%[in0], :128]\n"
+                       "vbif.s32  q3,  q0,  q15\n"
+                       "vst1.32   {d4, d5}, [%[out1], :128]\n"
+                       "vst1.32   {d6, d7}, [%[out0], :128]\n"
+               ".endm\n"
+
+               "vmov.s32  q14, #1\n"
+               "vmov.s32  q13, %[c2]\n"
+
+               "cmp   %[i], #4\n"
+               "bne   8f\n"
+
+       "4:\n" /* 4 subbands */
+               "add   %[in0], %[in], #0\n"
+               "add   %[in1], %[in], #32\n"
+               "add   %[out0], %[out], #0\n"
+               "add   %[out1], %[out], #32\n"
+               "vmov.s32  q0, %[c1]\n"
+               "vadd.s32  q0, q0, q14\n"
+
+               "calc_scalefactors\n"
+
+               /* check whether to use joint stereo for subbands 0, 1, 2 */
+               "vadd.s32  q15, q0,  q1\n"
+               "vadd.s32  q9,  q2,  q3\n"
+               "vmov.s32  d31[1], %[zero]\n" /* last subband -> no joint */
+               "vld1.32   {d16, d17}, [%[consts], :128]!\n"
+               "vcgt.s32  q15, q15, q9\n"
+
+               /* calculate and save to memory 'joint' variable */
+               /* update and save scale factors to memory */
+               "  vand.s32  q8, q8, q15\n"
+               "vbit.s32  q0,  q2,  q15\n"
+               "  vpadd.s32 d16, d16, d17\n"
+               "vbit.s32  q1,  q3,  q15\n"
+               "  vpadd.s32 d16, d16, d16\n"
+               "vst1.32   {d0, d1}, [%[out0], :128]\n"
+               "vst1.32   {d2, d3}, [%[out1], :128]\n"
+               "  vst1.32   {d16[0]}, [%[joint]]\n"
+
+               "update_joint_stereo_samples\n"
+               "b     9f\n"
+
+       "8:\n" /* 8 subbands */
+               "add   %[in0], %[in], #16\n\n"
+               "add   %[in1], %[in], #48\n"
+               "add   %[out0], %[out], #16\n\n"
+               "add   %[out1], %[out], #48\n"
+               "vmov.s32  q0, %[c1]\n"
+               "vadd.s32  q0, q0, q14\n"
+
+               "calc_scalefactors\n"
+
+               /* check whether to use joint stereo for subbands 4, 5, 6 */
+               "vadd.s32  q15, q0,  q1\n"
+               "vadd.s32  q9,  q2,  q3\n"
+               "vmov.s32  d31[1], %[zero]\n"  /* last subband -> no joint */
+               "vld1.32   {d16, d17}, [%[consts], :128]!\n"
+               "vcgt.s32  q15, q15, q9\n"
+
+               /* calculate part of 'joint' variable and save it to d24 */
+               /* update and save scale factors to memory */
+               "  vand.s32  q8, q8, q15\n"
+               "vbit.s32  q0,  q2,  q15\n"
+               "  vpadd.s32 d16, d16, d17\n"
+               "vbit.s32  q1,  q3,  q15\n"
+               "vst1.32   {d0, d1}, [%[out0], :128]\n"
+               "vst1.32   {d2, d3}, [%[out1], :128]\n"
+               "  vpadd.s32 d24, d16, d16\n"
+
+               "update_joint_stereo_samples\n"
+
+               "add   %[in0], %[in], #0\n"
+               "add   %[in1], %[in], #32\n"
+               "add   %[out0], %[out], #0\n\n"
+               "add   %[out1], %[out], #32\n"
+               "vmov.s32  q0, %[c1]\n"
+               "vadd.s32  q0, q0, q14\n"
+
+               "calc_scalefactors\n"
+
+               /* check whether to use joint stereo for subbands 0, 1, 2, 3 */
+               "vadd.s32  q15, q0,  q1\n"
+               "vadd.s32  q9,  q2,  q3\n"
+               "vld1.32   {d16, d17}, [%[consts], :128]!\n"
+               "vcgt.s32  q15, q15, q9\n"
+
+               /* combine last part of 'joint' with d24 and save to memory */
+               /* update and save scale factors to memory */
+               "  vand.s32  q8, q8, q15\n"
+               "vbit.s32  q0,  q2,  q15\n"
+               "  vpadd.s32 d16, d16, d17\n"
+               "vbit.s32  q1,  q3,  q15\n"
+               "  vpadd.s32 d16, d16, d16\n"
+               "vst1.32   {d0, d1}, [%[out0], :128]\n"
+               "  vadd.s32  d16, d16, d24\n"
+               "vst1.32   {d2, d3}, [%[out1], :128]\n"
+               "  vst1.32   {d16[0]}, [%[joint]]\n"
+
+               "update_joint_stereo_samples\n"
+       "9:\n"
+               ".purgem calc_scalefactors\n"
+               ".purgem update_joint_stereo_samples\n"
+               :
+                 [i]      "+&r" (i),
+                 [in]     "+&r" (in),
+                 [in0]    "=&r" (in0),
+                 [in1]    "=&r" (in1),
+                 [out]    "+&r" (out),
+                 [out0]   "=&r" (out0),
+                 [out1]   "=&r" (out1),
+                 [consts] "+&r" (consts)
+               :
+                 [inc]      "r" ((char *) &sb_sample_f[1][0][0] -
+                                (char *) &sb_sample_f[0][0][0]),
+                 [blocks]   "r" (blocks),
+                 [joint]    "r" (&joint),
+                 [c1]       "i" (1 << SCALE_OUT_BITS),
+                 [c2]       "i" (31 - SCALE_OUT_BITS),
+                 [zero]     "r" (0)
+               : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+                 "d16", "d17", "d18", "d19", "d20", "d21", "d22",
+                 "d23", "d24", "d25", "d26", "d27", "d28", "d29",
+                 "d30", "d31", "cc", "memory");
+
+       return joint;
+}
+
+#define PERM_BE(a, b, c, d) {             \
+               (a * 2) + 1, (a * 2) + 0, \
+               (b * 2) + 1, (b * 2) + 0, \
+               (c * 2) + 1, (c * 2) + 0, \
+               (d * 2) + 1, (d * 2) + 0  \
+       }
+#define PERM_LE(a, b, c, d) {             \
+               (a * 2) + 0, (a * 2) + 1, \
+               (b * 2) + 0, (b * 2) + 1, \
+               (c * 2) + 0, (c * 2) + 1, \
+               (d * 2) + 0, (d * 2) + 1  \
+       }
+
+static SBC_ALWAYS_INLINE int sbc_enc_process_input_4s_neon_internal(
+       int position,
+       const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+       int nsamples, int nchannels, int big_endian)
+{
+       static SBC_ALIGNED uint8_t perm_be[2][8] = {
+               PERM_BE(7, 3, 6, 4),
+               PERM_BE(0, 2, 1, 5)
+       };
+       static SBC_ALIGNED uint8_t perm_le[2][8] = {
+               PERM_LE(7, 3, 6, 4),
+               PERM_LE(0, 2, 1, 5)
+       };
+       /* handle X buffer wraparound */
+       if (position < nsamples) {
+               int16_t *dst = &X[0][SBC_X_BUFFER_SIZE - 40];
+               int16_t *src = &X[0][position];
+               __asm__ volatile (
+                       "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                       "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                       "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                       "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                       "vld1.16 {d0}, [%[src], :64]!\n"
+                       "vst1.16 {d0}, [%[dst], :64]!\n"
+                       :
+                         [dst] "+r" (dst),
+                         [src] "+r" (src)
+                       : : "memory", "d0", "d1", "d2", "d3");
+               if (nchannels > 1) {
+                       dst = &X[1][SBC_X_BUFFER_SIZE - 40];
+                       src = &X[1][position];
+                       __asm__ volatile (
+                               "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                               "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                               "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                               "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                               "vld1.16 {d0}, [%[src], :64]!\n"
+                               "vst1.16 {d0}, [%[dst], :64]!\n"
+                               :
+                                 [dst] "+r" (dst),
+                                 [src] "+r" (src)
+                               : : "memory", "d0", "d1", "d2", "d3");
+               }
+               position = SBC_X_BUFFER_SIZE - 40;
+       }
+
+       if ((nchannels > 1) && ((uintptr_t)pcm & 1)) {
+               /* poor 'pcm' alignment */
+               int16_t *x = &X[0][position];
+               int16_t *y = &X[1][position];
+               __asm__ volatile (
+                       "vld1.8  {d0, d1}, [%[perm], :128]\n"
+               "1:\n"
+                       "sub     %[x], %[x], #16\n"
+                       "sub     %[y], %[y], #16\n"
+                       "sub     %[position], %[position], #8\n"
+                       "vld1.8  {d4, d5}, [%[pcm]]!\n"
+                       "vuzp.16 d4,  d5\n"
+                       "vld1.8  {d20, d21}, [%[pcm]]!\n"
+                       "vuzp.16 d20, d21\n"
+                       "vswp    d5,  d20\n"
+                       "vtbl.8  d16, {d4, d5}, d0\n"
+                       "vtbl.8  d17, {d4, d5}, d1\n"
+                       "vtbl.8  d18, {d20, d21}, d0\n"
+                       "vtbl.8  d19, {d20, d21}, d1\n"
+                       "vst1.16 {d16, d17}, [%[x], :128]\n"
+                       "vst1.16 {d18, d19}, [%[y], :128]\n"
+                       "subs    %[nsamples], %[nsamples], #8\n"
+                       "bgt     1b\n"
+                       :
+                         [x]        "+r" (x),
+                         [y]        "+r" (y),
+                         [pcm]      "+r" (pcm),
+                         [nsamples] "+r" (nsamples),
+                         [position] "+r" (position)
+                       :
+                         [perm]      "r" (big_endian ? perm_be : perm_le)
+                       : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+                         "d5", "d6", "d7", "d16", "d17", "d18", "d19",
+                         "d20", "d21", "d22", "d23");
+       } else if (nchannels > 1) {
+               /* proper 'pcm' alignment */
+               int16_t *x = &X[0][position];
+               int16_t *y = &X[1][position];
+               __asm__ volatile (
+                       "vld1.8  {d0, d1}, [%[perm], :128]\n"
+               "1:\n"
+                       "sub     %[x], %[x], #16\n"
+                       "sub     %[y], %[y], #16\n"
+                       "sub     %[position], %[position], #8\n"
+                       "vld2.16 {d4, d5}, [%[pcm]]!\n"
+                       "vld2.16 {d20, d21}, [%[pcm]]!\n"
+                       "vswp    d5, d20\n"
+                       "vtbl.8  d16, {d4, d5}, d0\n"
+                       "vtbl.8  d17, {d4, d5}, d1\n"
+                       "vtbl.8  d18, {d20, d21}, d0\n"
+                       "vtbl.8  d19, {d20, d21}, d1\n"
+                       "vst1.16 {d16, d17}, [%[x], :128]\n"
+                       "vst1.16 {d18, d19}, [%[y], :128]\n"
+                       "subs    %[nsamples], %[nsamples], #8\n"
+                       "bgt     1b\n"
+                       :
+                         [x]        "+r" (x),
+                         [y]        "+r" (y),
+                         [pcm]      "+r" (pcm),
+                         [nsamples] "+r" (nsamples),
+                         [position] "+r" (position)
+                       :
+                         [perm]      "r" (big_endian ? perm_be : perm_le)
+                       : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+                         "d5", "d6", "d7", "d16", "d17", "d18", "d19",
+                         "d20", "d21", "d22", "d23");
+       } else {
+               int16_t *x = &X[0][position];
+               __asm__ volatile (
+                       "vld1.8  {d0, d1}, [%[perm], :128]\n"
+               "1:\n"
+                       "sub     %[x], %[x], #16\n"
+                       "sub     %[position], %[position], #8\n"
+                       "vld1.8  {d4, d5}, [%[pcm]]!\n"
+                       "vtbl.8  d16, {d4, d5}, d0\n"
+                       "vtbl.8  d17, {d4, d5}, d1\n"
+                       "vst1.16 {d16, d17}, [%[x], :128]\n"
+                       "subs    %[nsamples], %[nsamples], #8\n"
+                       "bgt     1b\n"
+                       :
+                         [x]        "+r" (x),
+                         [pcm]      "+r" (pcm),
+                         [nsamples] "+r" (nsamples),
+                         [position] "+r" (position)
+                       :
+                         [perm]      "r" (big_endian ? perm_be : perm_le)
+                       : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+                         "d5", "d6", "d7", "d16", "d17", "d18", "d19");
+       }
+       return position;
+}
+
+static SBC_ALWAYS_INLINE int sbc_enc_process_input_8s_neon_internal(
+       int position,
+       const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+       int nsamples, int nchannels, int big_endian)
+{
+       static SBC_ALIGNED uint8_t perm_be[4][8] = {
+               PERM_BE(15, 7, 14, 8),
+               PERM_BE(13, 9, 12, 10),
+               PERM_BE(11, 3, 6,  0),
+               PERM_BE(5,  1, 4,  2)
+       };
+       static SBC_ALIGNED uint8_t perm_le[4][8] = {
+               PERM_LE(15, 7, 14, 8),
+               PERM_LE(13, 9, 12, 10),
+               PERM_LE(11, 3, 6,  0),
+               PERM_LE(5,  1, 4,  2)
+       };
+       /* handle X buffer wraparound */
+       if (position < nsamples) {
+               int16_t *dst = &X[0][SBC_X_BUFFER_SIZE - 72];
+               int16_t *src = &X[0][position];
+               __asm__ volatile (
+                       "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                       "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                       "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                       "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                       "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                       "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                       "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                       "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                       "vld1.16 {d0, d1}, [%[src], :128]!\n"
+                       "vst1.16 {d0, d1}, [%[dst], :128]!\n"
+                       :
+                         [dst] "+r" (dst),
+                         [src] "+r" (src)
+                       : : "memory", "d0", "d1", "d2", "d3");
+               if (nchannels > 1) {
+                       dst = &X[1][SBC_X_BUFFER_SIZE - 72];
+                       src = &X[1][position];
+                       __asm__ volatile (
+                               "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                               "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                               "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                               "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                               "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                               "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                               "vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
+                               "vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
+                               "vld1.16 {d0, d1}, [%[src], :128]!\n"
+                               "vst1.16 {d0, d1}, [%[dst], :128]!\n"
+                               :
+                                 [dst] "+r" (dst),
+                                 [src] "+r" (src)
+                               : : "memory", "d0", "d1", "d2", "d3");
+               }
+               position = SBC_X_BUFFER_SIZE - 72;
+       }
+
+       if ((nchannels > 1) && ((uintptr_t)pcm & 1)) {
+               /* poor 'pcm' alignment */
+               int16_t *x = &X[0][position];
+               int16_t *y = &X[1][position];
+               __asm__ volatile (
+                       "vld1.8  {d0, d1, d2, d3}, [%[perm], :128]\n"
+               "1:\n"
+                       "sub     %[x], %[x], #32\n"
+                       "sub     %[y], %[y], #32\n"
+                       "sub     %[position], %[position], #16\n"
+                       "vld1.8  {d4, d5, d6, d7}, [%[pcm]]!\n"
+                       "vuzp.16 q2,  q3\n"
+                       "vld1.8  {d20, d21, d22, d23}, [%[pcm]]!\n"
+                       "vuzp.16 q10, q11\n"
+                       "vswp    q3,  q10\n"
+                       "vtbl.8  d16, {d4, d5, d6, d7}, d0\n"
+                       "vtbl.8  d17, {d4, d5, d6, d7}, d1\n"
+                       "vtbl.8  d18, {d4, d5, d6, d7}, d2\n"
+                       "vtbl.8  d19, {d4, d5, d6, d7}, d3\n"
+                       "vst1.16 {d16, d17, d18, d19}, [%[x], :128]\n"
+                       "vtbl.8  d16, {d20, d21, d22, d23}, d0\n"
+                       "vtbl.8  d17, {d20, d21, d22, d23}, d1\n"
+                       "vtbl.8  d18, {d20, d21, d22, d23}, d2\n"
+                       "vtbl.8  d19, {d20, d21, d22, d23}, d3\n"
+                       "vst1.16 {d16, d17, d18, d19}, [%[y], :128]\n"
+                       "subs    %[nsamples], %[nsamples], #16\n"
+                       "bgt     1b\n"
+                       :
+                         [x]        "+r" (x),
+                         [y]        "+r" (y),
+                         [pcm]      "+r" (pcm),
+                         [nsamples] "+r" (nsamples),
+                         [position] "+r" (position)
+                       :
+                         [perm]      "r" (big_endian ? perm_be : perm_le)
+                       : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+                         "d5", "d6", "d7", "d16", "d17", "d18", "d19",
+                         "d20", "d21", "d22", "d23");
+       } else if (nchannels > 1) {
+               /* proper 'pcm' alignment */
+               int16_t *x = &X[0][position];
+               int16_t *y = &X[1][position];
+               __asm__ volatile (
+                       "vld1.8  {d0, d1, d2, d3}, [%[perm], :128]\n"
+               "1:\n"
+                       "sub     %[x], %[x], #32\n"
+                       "sub     %[y], %[y], #32\n"
+                       "sub     %[position], %[position], #16\n"
+                       "vld2.16  {d4, d5, d6, d7}, [%[pcm]]!\n"
+                       "vld2.16  {d20, d21, d22, d23}, [%[pcm]]!\n"
+                       "vswp    q3, q10\n"
+                       "vtbl.8  d16, {d4, d5, d6, d7}, d0\n"
+                       "vtbl.8  d17, {d4, d5, d6, d7}, d1\n"
+                       "vtbl.8  d18, {d4, d5, d6, d7}, d2\n"
+                       "vtbl.8  d19, {d4, d5, d6, d7}, d3\n"
+                       "vst1.16 {d16, d17, d18, d19}, [%[x], :128]\n"
+                       "vtbl.8  d16, {d20, d21, d22, d23}, d0\n"
+                       "vtbl.8  d17, {d20, d21, d22, d23}, d1\n"
+                       "vtbl.8  d18, {d20, d21, d22, d23}, d2\n"
+                       "vtbl.8  d19, {d20, d21, d22, d23}, d3\n"
+                       "vst1.16 {d16, d17, d18, d19}, [%[y], :128]\n"
+                       "subs    %[nsamples], %[nsamples], #16\n"
+                       "bgt     1b\n"
+                       :
+                         [x]        "+r" (x),
+                         [y]        "+r" (y),
+                         [pcm]      "+r" (pcm),
+                         [nsamples] "+r" (nsamples),
+                         [position] "+r" (position)
+                       :
+                         [perm]      "r" (big_endian ? perm_be : perm_le)
+                       : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+                         "d5", "d6", "d7", "d16", "d17", "d18", "d19",
+                         "d20", "d21", "d22", "d23");
+       } else {
+               int16_t *x = &X[0][position];
+               __asm__ volatile (
+                       "vld1.8  {d0, d1, d2, d3}, [%[perm], :128]\n"
+               "1:\n"
+                       "sub     %[x], %[x], #32\n"
+                       "sub     %[position], %[position], #16\n"
+                       "vld1.8  {d4, d5, d6, d7}, [%[pcm]]!\n"
+                       "vtbl.8  d16, {d4, d5, d6, d7}, d0\n"
+                       "vtbl.8  d17, {d4, d5, d6, d7}, d1\n"
+                       "vtbl.8  d18, {d4, d5, d6, d7}, d2\n"
+                       "vtbl.8  d19, {d4, d5, d6, d7}, d3\n"
+                       "vst1.16 {d16, d17, d18, d19}, [%[x], :128]\n"
+                       "subs    %[nsamples], %[nsamples], #16\n"
+                       "bgt     1b\n"
+                       :
+                         [x]        "+r" (x),
+                         [pcm]      "+r" (pcm),
+                         [nsamples] "+r" (nsamples),
+                         [position] "+r" (position)
+                       :
+                         [perm]      "r" (big_endian ? perm_be : perm_le)
+                       : "cc", "memory", "d0", "d1", "d2", "d3", "d4",
+                         "d5", "d6", "d7", "d16", "d17", "d18", "d19");
+       }
+       return position;
+}
+
+#undef PERM_BE
+#undef PERM_LE
+
+static int sbc_enc_process_input_4s_be_neon(int position, const uint8_t *pcm,
+                                       int16_t X[2][SBC_X_BUFFER_SIZE],
+                                       int nsamples, int nchannels)
+{
+       return sbc_enc_process_input_4s_neon_internal(
+               position, pcm, X, nsamples, nchannels, 1);
+}
+
+static int sbc_enc_process_input_4s_le_neon(int position, const uint8_t *pcm,
+                                       int16_t X[2][SBC_X_BUFFER_SIZE],
+                                       int nsamples, int nchannels)
+{
+       return sbc_enc_process_input_4s_neon_internal(
+               position, pcm, X, nsamples, nchannels, 0);
+}
+
+static int sbc_enc_process_input_8s_be_neon(int position, const uint8_t *pcm,
+                                       int16_t X[2][SBC_X_BUFFER_SIZE],
+                                       int nsamples, int nchannels)
+{
+       return sbc_enc_process_input_8s_neon_internal(
+               position, pcm, X, nsamples, nchannels, 1);
+}
+
+static int sbc_enc_process_input_8s_le_neon(int position, const uint8_t *pcm,
+                                       int16_t X[2][SBC_X_BUFFER_SIZE],
+                                       int nsamples, int nchannels)
+{
+       return sbc_enc_process_input_8s_neon_internal(
+               position, pcm, X, nsamples, nchannels, 0);
+}
+
+void sbc_init_primitives_neon(struct sbc_encoder_state *state)
+{
+       state->sbc_analyze_4s = sbc_analyze_4b_4s_neon;
+       state->sbc_analyze_8s = sbc_analyze_4b_8s_neon;
+       state->sbc_calc_scalefactors = sbc_calc_scalefactors_neon;
+       state->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j_neon;
+       state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le_neon;
+       state->sbc_enc_process_input_4s_be = sbc_enc_process_input_4s_be_neon;
+       state->sbc_enc_process_input_8s_le = sbc_enc_process_input_8s_le_neon;
+       state->sbc_enc_process_input_8s_be = sbc_enc_process_input_8s_be_neon;
+       state->implementation_info = "NEON";
+}
+
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_neon.h b/rtkbt/code/libbt-vendor/codec/sbc/sbc_primitives_neon.h
new file mode 100755 (executable)
index 0000000..ea3da06
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __SBC_PRIMITIVES_NEON_H
+#define __SBC_PRIMITIVES_NEON_H
+
+#include "sbc_primitives.h"
+
+#if defined(__GNUC__) && defined(__ARM_NEON__) && \
+               !defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15)
+
+#define SBC_BUILD_WITH_NEON_SUPPORT
+
+void sbc_init_primitives_neon(struct sbc_encoder_state *encoder_state);
+
+#endif
+
+#endif
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_private.h b/rtkbt/code/libbt-vendor/codec/sbc/sbc_private.h
new file mode 100755 (executable)
index 0000000..1d420d5
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define SBC_EXPORT __attribute__ ((visibility("default")))
diff --git a/rtkbt/code/libbt-vendor/codec/sbc/sbc_tables.h b/rtkbt/code/libbt-vendor/codec/sbc/sbc_tables.h
new file mode 100755 (executable)
index 0000000..24a8bff
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2008-2010  Nokia Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/* A2DP specification: Appendix B, page 69 */
+static const int sbc_offset4[4][4] = {
+       { -1, 0, 0, 0 },
+       { -2, 0, 0, 1 },
+       { -2, 0, 0, 1 },
+       { -2, 0, 0, 1 }
+};
+
+/* A2DP specification: Appendix B, page 69 */
+static const int sbc_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 }
+};
+
+/* extra bits of precision for the synthesis filter input data */
+#define SBCDEC_FIXED_EXTRA_BITS 2
+
+#define SS4(val) ASR(val, SCALE_SPROTO4_TBL)
+#define SS8(val) ASR(val, SCALE_SPROTO8_TBL)
+#define SN4(val) ASR(val, SCALE_NPROTO4_TBL + 1 + SBCDEC_FIXED_EXTRA_BITS)
+#define SN8(val) ASR(val, SCALE_NPROTO8_TBL + 1 + SBCDEC_FIXED_EXTRA_BITS)
+
+static const int32_t sbc_proto_4_40m0[] = {
+       SS4(0x00000000), SS4(0xffa6982f), SS4(0xfba93848), SS4(0x0456c7b8),
+       SS4(0x005967d1), SS4(0xfffb9ac7), SS4(0xff589157), SS4(0xf9c2a8d8),
+       SS4(0x027c1434), SS4(0x0019118b), SS4(0xfff3c74c), SS4(0xff137330),
+       SS4(0xf81b8d70), SS4(0x00ec1b8b), SS4(0xfff0b71a), SS4(0xffe99b00),
+       SS4(0xfef84470), SS4(0xf6fb4370), SS4(0xffcdc351), SS4(0xffe01dc7)
+};
+
+static const int32_t sbc_proto_4_40m1[] = {
+       SS4(0xffe090ce), SS4(0xff2c0475), SS4(0xf694f800), SS4(0xff2c0475),
+       SS4(0xffe090ce), SS4(0xffe01dc7), SS4(0xffcdc351), SS4(0xf6fb4370),
+       SS4(0xfef84470), SS4(0xffe99b00), SS4(0xfff0b71a), SS4(0x00ec1b8b),
+       SS4(0xf81b8d70), SS4(0xff137330), SS4(0xfff3c74c), SS4(0x0019118b),
+       SS4(0x027c1434), SS4(0xf9c2a8d8), SS4(0xff589157), SS4(0xfffb9ac7)
+};
+
+static const int32_t sbc_proto_8_80m0[] = {
+       SS8(0x00000000), SS8(0xfe8d1970), SS8(0xee979f00), SS8(0x11686100),
+       SS8(0x0172e690), SS8(0xfff5bd1a), SS8(0xfdf1c8d4), SS8(0xeac182c0),
+       SS8(0x0d9daee0), SS8(0x00e530da), SS8(0xffe9811d), SS8(0xfd52986c),
+       SS8(0xe7054ca0), SS8(0x0a00d410), SS8(0x006c1de4), SS8(0xffdba705),
+       SS8(0xfcbc98e8), SS8(0xe3889d20), SS8(0x06af2308), SS8(0x000bb7db),
+       SS8(0xffca00ed), SS8(0xfc3fbb68), SS8(0xe071bc00), SS8(0x03bf7948),
+       SS8(0xffc4e05c), SS8(0xffb54b3b), SS8(0xfbedadc0), SS8(0xdde26200),
+       SS8(0x0142291c), SS8(0xff960e94), SS8(0xff9f3e17), SS8(0xfbd8f358),
+       SS8(0xdbf79400), SS8(0xff405e01), SS8(0xff7d4914), SS8(0xff8b1a31),
+       SS8(0xfc1417b8), SS8(0xdac7bb40), SS8(0xfdbb828c), SS8(0xff762170)
+};
+
+static const int32_t sbc_proto_8_80m1[] = {
+       SS8(0xff7c272c), SS8(0xfcb02620), SS8(0xda612700), SS8(0xfcb02620),
+       SS8(0xff7c272c), SS8(0xff762170), SS8(0xfdbb828c), SS8(0xdac7bb40),
+       SS8(0xfc1417b8), SS8(0xff8b1a31), SS8(0xff7d4914), SS8(0xff405e01),
+       SS8(0xdbf79400), SS8(0xfbd8f358), SS8(0xff9f3e17), SS8(0xff960e94),
+       SS8(0x0142291c), SS8(0xdde26200), SS8(0xfbedadc0), SS8(0xffb54b3b),
+       SS8(0xffc4e05c), SS8(0x03bf7948), SS8(0xe071bc00), SS8(0xfc3fbb68),
+       SS8(0xffca00ed), SS8(0x000bb7db), SS8(0x06af2308), SS8(0xe3889d20),
+       SS8(0xfcbc98e8), SS8(0xffdba705), SS8(0x006c1de4), SS8(0x0a00d410),
+       SS8(0xe7054ca0), SS8(0xfd52986c), SS8(0xffe9811d), SS8(0x00e530da),
+       SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a)
+};
+
+static const int32_t synmatrix4[8][4] = {
+       { SN4(0x05a82798), SN4(0xfa57d868), SN4(0xfa57d868), SN4(0x05a82798) },
+       { SN4(0x030fbc54), SN4(0xf89be510), SN4(0x07641af0), SN4(0xfcf043ac) },
+       { SN4(0x00000000), SN4(0x00000000), SN4(0x00000000), SN4(0x00000000) },
+       { SN4(0xfcf043ac), SN4(0x07641af0), SN4(0xf89be510), SN4(0x030fbc54) },
+       { SN4(0xfa57d868), SN4(0x05a82798), SN4(0x05a82798), SN4(0xfa57d868) },
+       { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) },
+       { SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000) },
+       { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) }
+};
+
+static const int32_t synmatrix8[16][8] = {
+       { SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798),
+         SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798) },
+       { SN8(0x0471ced0), SN8(0xf8275a10), SN8(0x018f8b84), SN8(0x06a6d988),
+         SN8(0xf9592678), SN8(0xfe70747c), SN8(0x07d8a5f0), SN8(0xfb8e3130) },
+       { SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac),
+         SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54) },
+       { SN8(0x018f8b84), SN8(0xfb8e3130), SN8(0x06a6d988), SN8(0xf8275a10),
+         SN8(0x07d8a5f0), SN8(0xf9592678), SN8(0x0471ced0), SN8(0xfe70747c) },
+       { SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000),
+         SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000) },
+       { SN8(0xfe70747c), SN8(0x0471ced0), SN8(0xf9592678), SN8(0x07d8a5f0),
+         SN8(0xf8275a10), SN8(0x06a6d988), SN8(0xfb8e3130), SN8(0x018f8b84) },
+       { SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54),
+         SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac) },
+       { SN8(0xfb8e3130), SN8(0x07d8a5f0), SN8(0xfe70747c), SN8(0xf9592678),
+         SN8(0x06a6d988), SN8(0x018f8b84), SN8(0xf8275a10), SN8(0x0471ced0) },
+       { SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868),
+         SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868) },
+       { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
+         SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) },
+       { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
+         SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
+       { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
+         SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
+       { SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000),
+         SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000) },
+       { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
+         SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
+       { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
+         SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
+       { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
+         SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) }
+};
+
+#ifdef SBC_HIGH_PRECISION
+#define FIXED_A int64_t /* data type for fixed point accumulator */
+#define FIXED_T int32_t /* data type for fixed point constants */
+#define SBC_FIXED_EXTRA_BITS 16
+#else
+#define FIXED_A int32_t /* data type for fixed point accumulator */
+#define FIXED_T int16_t /* data type for fixed point constants */
+#define SBC_FIXED_EXTRA_BITS 0
+#endif
+
+/* A2DP specification: Section 12.8 Tables
+ *
+ * Original values are premultiplied by 2 for better precision (that is the
+ * maximum which is possible without overflows)
+ *
+ * Note: in each block of 8 numbers sign was changed for elements 2 and 7
+ * in order to compensate the same change applied to cos_table_fixed_4
+ */
+#define SBC_PROTO_FIXED4_SCALE \
+       ((sizeof(FIXED_T) * CHAR_BIT - 1) - SBC_FIXED_EXTRA_BITS + 1)
+#define F_PROTO4(x) (FIXED_A) ((x * 2) * \
+       ((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
+#define F(x) F_PROTO4(x)
+static const FIXED_T _sbc_proto_fixed4[40] = {
+       F(0.00000000E+00),  F(5.36548976E-04),
+       -F(1.49188357E-03),  F(2.73370904E-03),
+       F(3.83720193E-03),  F(3.89205149E-03),
+       F(1.86581691E-03),  F(3.06012286E-03),
+
+       F(1.09137620E-02),  F(2.04385087E-02),
+       -F(2.88757392E-02),  F(3.21939290E-02),
+       F(2.58767811E-02),  F(6.13245186E-03),
+       -F(2.88217274E-02),  F(7.76463494E-02),
+
+       F(1.35593274E-01),  F(1.94987841E-01),
+       -F(2.46636662E-01),  F(2.81828203E-01),
+       F(2.94315332E-01),  F(2.81828203E-01),
+       F(2.46636662E-01), -F(1.94987841E-01),
+
+       -F(1.35593274E-01), -F(7.76463494E-02),
+       F(2.88217274E-02),  F(6.13245186E-03),
+       F(2.58767811E-02),  F(3.21939290E-02),
+       F(2.88757392E-02), -F(2.04385087E-02),
+
+       -F(1.09137620E-02), -F(3.06012286E-03),
+       -F(1.86581691E-03),  F(3.89205149E-03),
+       F(3.83720193E-03),  F(2.73370904E-03),
+       F(1.49188357E-03), -F(5.36548976E-04),
+};
+#undef F
+
+/*
+ * To produce this cosine matrix in Octave:
+ *
+ * b = zeros(4, 8);
+ * for i = 0:3
+ * for j = 0:7 b(i+1, j+1) = cos((i + 0.5) * (j - 2) * (pi/4))
+ * endfor
+ * endfor;
+ * printf("%.10f, ", b');
+ *
+ * Note: in each block of 8 numbers sign was changed for elements 2 and 7
+ *
+ * Change of sign for element 2 allows to replace constant 1.0 (not
+ * representable in Q15 format) with -1.0 (fine with Q15).
+ * Changed sign for element 7 allows to have more similar constants
+ * and simplify subband filter function code.
+ */
+#define SBC_COS_TABLE_FIXED4_SCALE \
+       ((sizeof(FIXED_T) * CHAR_BIT - 1) + SBC_FIXED_EXTRA_BITS)
+#define F_COS4(x) (FIXED_A) ((x) * \
+       ((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
+#define F(x) F_COS4(x)
+static const FIXED_T cos_table_fixed_4[32] = {
+       F(0.7071067812),  F(0.9238795325), -F(1.0000000000),  F(0.9238795325),
+       F(0.7071067812),  F(0.3826834324),  F(0.0000000000),  F(0.3826834324),
+
+       -F(0.7071067812),  F(0.3826834324), -F(1.0000000000),  F(0.3826834324),
+       -F(0.7071067812), -F(0.9238795325), -F(0.0000000000), -F(0.9238795325),
+
+       -F(0.7071067812), -F(0.3826834324), -F(1.0000000000), -F(0.3826834324),
+       -F(0.7071067812),  F(0.9238795325),  F(0.0000000000),  F(0.9238795325),
+
+       F(0.7071067812), -F(0.9238795325), -F(1.0000000000), -F(0.9238795325),
+       F(0.7071067812), -F(0.3826834324), -F(0.0000000000), -F(0.3826834324),
+};
+#undef F
+
+/* A2DP specification: Section 12.8 Tables
+ *
+ * Original values are premultiplied by 4 for better precision (that is the
+ * maximum which is possible without overflows)
+ *
+ * Note: in each block of 16 numbers sign was changed for elements 4, 13, 14, 15
+ * in order to compensate the same change applied to cos_table_fixed_8
+ */
+#define SBC_PROTO_FIXED8_SCALE \
+       ((sizeof(FIXED_T) * CHAR_BIT - 1) - SBC_FIXED_EXTRA_BITS + 1)
+#define F_PROTO8(x) (FIXED_A) ((x * 2) * \
+       ((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
+#define F(x) F_PROTO8(x)
+static const FIXED_T _sbc_proto_fixed8[80] = {
+       F(0.00000000E+00),  F(1.56575398E-04),
+       F(3.43256425E-04),  F(5.54620202E-04),
+       -F(8.23919506E-04),  F(1.13992507E-03),
+       F(1.47640169E-03),  F(1.78371725E-03),
+       F(2.01182542E-03),  F(2.10371989E-03),
+       F(1.99454554E-03),  F(1.61656283E-03),
+       F(9.02154502E-04),  F(1.78805361E-04),
+       F(1.64973098E-03),  F(3.49717454E-03),
+
+       F(5.65949473E-03),  F(8.02941163E-03),
+       F(1.04584443E-02),  F(1.27472335E-02),
+       -F(1.46525263E-02),  F(1.59045603E-02),
+       F(1.62208471E-02),  F(1.53184106E-02),
+       F(1.29371806E-02),  F(8.85757540E-03),
+       F(2.92408442E-03), -F(4.91578024E-03),
+       -F(1.46404076E-02),  F(2.61098752E-02),
+       F(3.90751381E-02),  F(5.31873032E-02),
+
+       F(6.79989431E-02),  F(8.29847578E-02),
+       F(9.75753918E-02),  F(1.11196689E-01),
+       -F(1.23264548E-01),  F(1.33264415E-01),
+       F(1.40753505E-01),  F(1.45389847E-01),
+       F(1.46955068E-01),  F(1.45389847E-01),
+       F(1.40753505E-01),  F(1.33264415E-01),
+       F(1.23264548E-01), -F(1.11196689E-01),
+       -F(9.75753918E-02), -F(8.29847578E-02),
+
+       -F(6.79989431E-02), -F(5.31873032E-02),
+       -F(3.90751381E-02), -F(2.61098752E-02),
+       F(1.46404076E-02), -F(4.91578024E-03),
+       F(2.92408442E-03),  F(8.85757540E-03),
+       F(1.29371806E-02),  F(1.53184106E-02),
+       F(1.62208471E-02),  F(1.59045603E-02),
+       F(1.46525263E-02), -F(1.27472335E-02),
+       -F(1.04584443E-02), -F(8.02941163E-03),
+
+       -F(5.65949473E-03), -F(3.49717454E-03),
+       -F(1.64973098E-03), -F(1.78805361E-04),
+       -F(9.02154502E-04),  F(1.61656283E-03),
+       F(1.99454554E-03),  F(2.10371989E-03),
+       F(2.01182542E-03),  F(1.78371725E-03),
+       F(1.47640169E-03),  F(1.13992507E-03),
+       F(8.23919506E-04), -F(5.54620202E-04),
+       -F(3.43256425E-04), -F(1.56575398E-04),
+};
+#undef F
+
+/*
+ * To produce this cosine matrix in Octave:
+ *
+ * b = zeros(8, 16);
+ * for i = 0:7
+ * for j = 0:15 b(i+1, j+1) = cos((i + 0.5) * (j - 4) * (pi/8))
+ * endfor endfor;
+ * printf("%.10f, ", b');
+ *
+ * Note: in each block of 16 numbers sign was changed for elements 4, 13, 14, 15
+ *
+ * Change of sign for element 4 allows to replace constant 1.0 (not
+ * representable in Q15 format) with -1.0 (fine with Q15).
+ * Changed signs for elements 13, 14, 15 allow to have more similar constants
+ * and simplify subband filter function code.
+ */
+#define SBC_COS_TABLE_FIXED8_SCALE \
+       ((sizeof(FIXED_T) * CHAR_BIT - 1) + SBC_FIXED_EXTRA_BITS)
+#define F_COS8(x) (FIXED_A) ((x) * \
+       ((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
+#define F(x) F_COS8(x)
+static const FIXED_T cos_table_fixed_8[128] = {
+       F(0.7071067812),  F(0.8314696123),  F(0.9238795325),  F(0.9807852804),
+       -F(1.0000000000),  F(0.9807852804),  F(0.9238795325),  F(0.8314696123),
+       F(0.7071067812),  F(0.5555702330),  F(0.3826834324),  F(0.1950903220),
+       F(0.0000000000),  F(0.1950903220),  F(0.3826834324),  F(0.5555702330),
+
+       -F(0.7071067812), -F(0.1950903220),  F(0.3826834324),  F(0.8314696123),
+       -F(1.0000000000),  F(0.8314696123),  F(0.3826834324), -F(0.1950903220),
+       -F(0.7071067812), -F(0.9807852804), -F(0.9238795325), -F(0.5555702330),
+       -F(0.0000000000), -F(0.5555702330), -F(0.9238795325), -F(0.9807852804),
+
+       -F(0.7071067812), -F(0.9807852804), -F(0.3826834324),  F(0.5555702330),
+       -F(1.0000000000),  F(0.5555702330), -F(0.3826834324), -F(0.9807852804),
+       -F(0.7071067812),  F(0.1950903220),  F(0.9238795325),  F(0.8314696123),
+       F(0.0000000000),  F(0.8314696123),  F(0.9238795325),  F(0.1950903220),
+
+       F(0.7071067812), -F(0.5555702330), -F(0.9238795325),  F(0.1950903220),
+       -F(1.0000000000),  F(0.1950903220), -F(0.9238795325), -F(0.5555702330),
+       F(0.7071067812),  F(0.8314696123), -F(0.3826834324), -F(0.9807852804),
+       -F(0.0000000000), -F(0.9807852804), -F(0.3826834324),  F(0.8314696123),
+
+       F(0.7071067812),  F(0.5555702330), -F(0.9238795325), -F(0.1950903220),
+       -F(1.0000000000), -F(0.1950903220), -F(0.9238795325),  F(0.5555702330),
+       F(0.7071067812), -F(0.8314696123), -F(0.3826834324),  F(0.9807852804),
+       F(0.0000000000),  F(0.9807852804), -F(0.3826834324), -F(0.8314696123),
+
+       -F(0.7071067812),  F(0.9807852804), -F(0.3826834324), -F(0.5555702330),
+       -F(1.0000000000), -F(0.5555702330), -F(0.3826834324),  F(0.9807852804),
+       -F(0.7071067812), -F(0.1950903220),  F(0.9238795325), -F(0.8314696123),
+       -F(0.0000000000), -F(0.8314696123),  F(0.9238795325), -F(0.1950903220),
+
+       -F(0.7071067812),  F(0.1950903220),  F(0.3826834324), -F(0.8314696123),
+       -F(1.0000000000), -F(0.8314696123),  F(0.3826834324),  F(0.1950903220),
+       -F(0.7071067812),  F(0.9807852804), -F(0.9238795325),  F(0.5555702330),
+       -F(0.0000000000),  F(0.5555702330), -F(0.9238795325),  F(0.9807852804),
+
+       F(0.7071067812), -F(0.8314696123),  F(0.9238795325), -F(0.9807852804),
+       -F(1.0000000000), -F(0.9807852804),  F(0.9238795325), -F(0.8314696123),
+       F(0.7071067812), -F(0.5555702330),  F(0.3826834324), -F(0.1950903220),
+       -F(0.0000000000), -F(0.1950903220),  F(0.3826834324), -F(0.5555702330),
+};
+#undef F
+
+/*
+ * Enforce 16 byte alignment for the data, which is supposed to be used
+ * with SIMD optimized code.
+ */
+
+#define SBC_ALIGN_BITS 4
+#define SBC_ALIGN_MASK ((1 << (SBC_ALIGN_BITS)) - 1)
+
+#ifdef __GNUC__
+#define SBC_ALIGNED __attribute__((aligned(1 << (SBC_ALIGN_BITS))))
+#else
+#define SBC_ALIGNED
+#endif
+
+/*
+ * Constant tables for the use in SIMD optimized analysis filters
+ * Each table consists of two parts:
+ * 1. reordered "proto" table
+ * 2. reordered "cos" table
+ *
+ * Due to non-symmetrical reordering, separate tables for "even"
+ * and "odd" cases are needed
+ */
+
+static const FIXED_T SBC_ALIGNED analysis_consts_fixed4_simd_even[40 + 16] = {
+#define C0 1.0932568993
+#define C1 1.3056875580
+#define C2 1.3056875580
+#define C3 1.6772280856
+
+#define F(x) F_PROTO4(x)
+        F(0.00000000E+00 * C0),  F(3.83720193E-03 * C0),
+        F(5.36548976E-04 * C1),  F(2.73370904E-03 * C1),
+        F(3.06012286E-03 * C2),  F(3.89205149E-03 * C2),
+        F(0.00000000E+00 * C3), -F(1.49188357E-03 * C3),
+        F(1.09137620E-02 * C0),  F(2.58767811E-02 * C0),
+        F(2.04385087E-02 * C1),  F(3.21939290E-02 * C1),
+        F(7.76463494E-02 * C2),  F(6.13245186E-03 * C2),
+        F(0.00000000E+00 * C3), -F(2.88757392E-02 * C3),
+        F(1.35593274E-01 * C0),  F(2.94315332E-01 * C0),
+        F(1.94987841E-01 * C1),  F(2.81828203E-01 * C1),
+       -F(1.94987841E-01 * C2),  F(2.81828203E-01 * C2),
+        F(0.00000000E+00 * C3), -F(2.46636662E-01 * C3),
+       -F(1.35593274E-01 * C0),  F(2.58767811E-02 * C0),
+       -F(7.76463494E-02 * C1),  F(6.13245186E-03 * C1),
+       -F(2.04385087E-02 * C2),  F(3.21939290E-02 * C2),
+        F(0.00000000E+00 * C3),  F(2.88217274E-02 * C3),
+       -F(1.09137620E-02 * C0),  F(3.83720193E-03 * C0),
+       -F(3.06012286E-03 * C1),  F(3.89205149E-03 * C1),
+       -F(5.36548976E-04 * C2),  F(2.73370904E-03 * C2),
+        F(0.00000000E+00 * C3), -F(1.86581691E-03 * C3),
+#undef F
+#define F(x) F_COS4(x)
+        F(0.7071067812 / C0),  F(0.9238795325 / C1),
+       -F(0.7071067812 / C0),  F(0.3826834324 / C1),
+       -F(0.7071067812 / C0), -F(0.3826834324 / C1),
+        F(0.7071067812 / C0), -F(0.9238795325 / C1),
+        F(0.3826834324 / C2), -F(1.0000000000 / C3),
+       -F(0.9238795325 / C2), -F(1.0000000000 / C3),
+        F(0.9238795325 / C2), -F(1.0000000000 / C3),
+       -F(0.3826834324 / C2), -F(1.0000000000 / C3),
+#undef F
+
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+};
+
+static const FIXED_T SBC_ALIGNED analysis_consts_fixed4_simd_odd[40 + 16] = {
+#define C0 1.3056875580
+#define C1 1.6772280856
+#define C2 1.0932568993
+#define C3 1.3056875580
+
+#define F(x) F_PROTO4(x)
+        F(2.73370904E-03 * C0),  F(5.36548976E-04 * C0),
+       -F(1.49188357E-03 * C1),  F(0.00000000E+00 * C1),
+        F(3.83720193E-03 * C2),  F(1.09137620E-02 * C2),
+        F(3.89205149E-03 * C3),  F(3.06012286E-03 * C3),
+        F(3.21939290E-02 * C0),  F(2.04385087E-02 * C0),
+       -F(2.88757392E-02 * C1),  F(0.00000000E+00 * C1),
+        F(2.58767811E-02 * C2),  F(1.35593274E-01 * C2),
+        F(6.13245186E-03 * C3),  F(7.76463494E-02 * C3),
+        F(2.81828203E-01 * C0),  F(1.94987841E-01 * C0),
+       -F(2.46636662E-01 * C1),  F(0.00000000E+00 * C1),
+        F(2.94315332E-01 * C2), -F(1.35593274E-01 * C2),
+        F(2.81828203E-01 * C3), -F(1.94987841E-01 * C3),
+        F(6.13245186E-03 * C0), -F(7.76463494E-02 * C0),
+        F(2.88217274E-02 * C1),  F(0.00000000E+00 * C1),
+        F(2.58767811E-02 * C2), -F(1.09137620E-02 * C2),
+        F(3.21939290E-02 * C3), -F(2.04385087E-02 * C3),
+        F(3.89205149E-03 * C0), -F(3.06012286E-03 * C0),
+       -F(1.86581691E-03 * C1),  F(0.00000000E+00 * C1),
+        F(3.83720193E-03 * C2),  F(0.00000000E+00 * C2),
+        F(2.73370904E-03 * C3), -F(5.36548976E-04 * C3),
+#undef F
+#define F(x) F_COS4(x)
+        F(0.9238795325 / C0), -F(1.0000000000 / C1),
+        F(0.3826834324 / C0), -F(1.0000000000 / C1),
+       -F(0.3826834324 / C0), -F(1.0000000000 / C1),
+       -F(0.9238795325 / C0), -F(1.0000000000 / C1),
+        F(0.7071067812 / C2),  F(0.3826834324 / C3),
+       -F(0.7071067812 / C2), -F(0.9238795325 / C3),
+       -F(0.7071067812 / C2),  F(0.9238795325 / C3),
+        F(0.7071067812 / C2), -F(0.3826834324 / C3),
+#undef F
+
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+};
+
+static const FIXED_T SBC_ALIGNED analysis_consts_fixed8_simd_even[80 + 64] = {
+#define C0 2.7906148894
+#define C1 2.4270044280
+#define C2 2.8015616024
+#define C3 3.1710363741
+#define C4 2.5377944043
+#define C5 2.4270044280
+#define C6 2.8015616024
+#define C7 3.1710363741
+
+#define F(x) F_PROTO8(x)
+        F(0.00000000E+00 * C0),  F(2.01182542E-03 * C0),
+        F(1.56575398E-04 * C1),  F(1.78371725E-03 * C1),
+        F(3.43256425E-04 * C2),  F(1.47640169E-03 * C2),
+        F(5.54620202E-04 * C3),  F(1.13992507E-03 * C3),
+       -F(8.23919506E-04 * C4),  F(0.00000000E+00 * C4),
+        F(2.10371989E-03 * C5),  F(3.49717454E-03 * C5),
+        F(1.99454554E-03 * C6),  F(1.64973098E-03 * C6),
+        F(1.61656283E-03 * C7),  F(1.78805361E-04 * C7),
+        F(5.65949473E-03 * C0),  F(1.29371806E-02 * C0),
+        F(8.02941163E-03 * C1),  F(1.53184106E-02 * C1),
+        F(1.04584443E-02 * C2),  F(1.62208471E-02 * C2),
+        F(1.27472335E-02 * C3),  F(1.59045603E-02 * C3),
+       -F(1.46525263E-02 * C4),  F(0.00000000E+00 * C4),
+        F(8.85757540E-03 * C5),  F(5.31873032E-02 * C5),
+        F(2.92408442E-03 * C6),  F(3.90751381E-02 * C6),
+       -F(4.91578024E-03 * C7),  F(2.61098752E-02 * C7),
+        F(6.79989431E-02 * C0),  F(1.46955068E-01 * C0),
+        F(8.29847578E-02 * C1),  F(1.45389847E-01 * C1),
+        F(9.75753918E-02 * C2),  F(1.40753505E-01 * C2),
+        F(1.11196689E-01 * C3),  F(1.33264415E-01 * C3),
+       -F(1.23264548E-01 * C4),  F(0.00000000E+00 * C4),
+        F(1.45389847E-01 * C5), -F(8.29847578E-02 * C5),
+        F(1.40753505E-01 * C6), -F(9.75753918E-02 * C6),
+        F(1.33264415E-01 * C7), -F(1.11196689E-01 * C7),
+       -F(6.79989431E-02 * C0),  F(1.29371806E-02 * C0),
+       -F(5.31873032E-02 * C1),  F(8.85757540E-03 * C1),
+       -F(3.90751381E-02 * C2),  F(2.92408442E-03 * C2),
+       -F(2.61098752E-02 * C3), -F(4.91578024E-03 * C3),
+        F(1.46404076E-02 * C4),  F(0.00000000E+00 * C4),
+        F(1.53184106E-02 * C5), -F(8.02941163E-03 * C5),
+        F(1.62208471E-02 * C6), -F(1.04584443E-02 * C6),
+        F(1.59045603E-02 * C7), -F(1.27472335E-02 * C7),
+       -F(5.65949473E-03 * C0),  F(2.01182542E-03 * C0),
+       -F(3.49717454E-03 * C1),  F(2.10371989E-03 * C1),
+       -F(1.64973098E-03 * C2),  F(1.99454554E-03 * C2),
+       -F(1.78805361E-04 * C3),  F(1.61656283E-03 * C3),
+       -F(9.02154502E-04 * C4),  F(0.00000000E+00 * C4),
+        F(1.78371725E-03 * C5), -F(1.56575398E-04 * C5),
+        F(1.47640169E-03 * C6), -F(3.43256425E-04 * C6),
+        F(1.13992507E-03 * C7), -F(5.54620202E-04 * C7),
+#undef F
+#define F(x) F_COS8(x)
+        F(0.7071067812 / C0),  F(0.8314696123 / C1),
+       -F(0.7071067812 / C0), -F(0.1950903220 / C1),
+       -F(0.7071067812 / C0), -F(0.9807852804 / C1),
+        F(0.7071067812 / C0), -F(0.5555702330 / C1),
+        F(0.7071067812 / C0),  F(0.5555702330 / C1),
+       -F(0.7071067812 / C0),  F(0.9807852804 / C1),
+       -F(0.7071067812 / C0),  F(0.1950903220 / C1),
+        F(0.7071067812 / C0), -F(0.8314696123 / C1),
+        F(0.9238795325 / C2),  F(0.9807852804 / C3),
+        F(0.3826834324 / C2),  F(0.8314696123 / C3),
+       -F(0.3826834324 / C2),  F(0.5555702330 / C3),
+       -F(0.9238795325 / C2),  F(0.1950903220 / C3),
+       -F(0.9238795325 / C2), -F(0.1950903220 / C3),
+       -F(0.3826834324 / C2), -F(0.5555702330 / C3),
+        F(0.3826834324 / C2), -F(0.8314696123 / C3),
+        F(0.9238795325 / C2), -F(0.9807852804 / C3),
+       -F(1.0000000000 / C4),  F(0.5555702330 / C5),
+       -F(1.0000000000 / C4), -F(0.9807852804 / C5),
+       -F(1.0000000000 / C4),  F(0.1950903220 / C5),
+       -F(1.0000000000 / C4),  F(0.8314696123 / C5),
+       -F(1.0000000000 / C4), -F(0.8314696123 / C5),
+       -F(1.0000000000 / C4), -F(0.1950903220 / C5),
+       -F(1.0000000000 / C4),  F(0.9807852804 / C5),
+       -F(1.0000000000 / C4), -F(0.5555702330 / C5),
+        F(0.3826834324 / C6),  F(0.1950903220 / C7),
+       -F(0.9238795325 / C6), -F(0.5555702330 / C7),
+        F(0.9238795325 / C6),  F(0.8314696123 / C7),
+       -F(0.3826834324 / C6), -F(0.9807852804 / C7),
+       -F(0.3826834324 / C6),  F(0.9807852804 / C7),
+        F(0.9238795325 / C6), -F(0.8314696123 / C7),
+       -F(0.9238795325 / C6),  F(0.5555702330 / C7),
+        F(0.3826834324 / C6), -F(0.1950903220 / C7),
+#undef F
+
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+#undef C4
+#undef C5
+#undef C6
+#undef C7
+};
+
+static const FIXED_T SBC_ALIGNED analysis_consts_fixed8_simd_odd[80 + 64] = {
+#define C0 2.5377944043
+#define C1 2.4270044280
+#define C2 2.8015616024
+#define C3 3.1710363741
+#define C4 2.7906148894
+#define C5 2.4270044280
+#define C6 2.8015616024
+#define C7 3.1710363741
+
+#define F(x) F_PROTO8(x)
+        F(0.00000000E+00 * C0), -F(8.23919506E-04 * C0),
+        F(1.56575398E-04 * C1),  F(1.78371725E-03 * C1),
+        F(3.43256425E-04 * C2),  F(1.47640169E-03 * C2),
+        F(5.54620202E-04 * C3),  F(1.13992507E-03 * C3),
+        F(2.01182542E-03 * C4),  F(5.65949473E-03 * C4),
+        F(2.10371989E-03 * C5),  F(3.49717454E-03 * C5),
+        F(1.99454554E-03 * C6),  F(1.64973098E-03 * C6),
+        F(1.61656283E-03 * C7),  F(1.78805361E-04 * C7),
+        F(0.00000000E+00 * C0), -F(1.46525263E-02 * C0),
+        F(8.02941163E-03 * C1),  F(1.53184106E-02 * C1),
+        F(1.04584443E-02 * C2),  F(1.62208471E-02 * C2),
+        F(1.27472335E-02 * C3),  F(1.59045603E-02 * C3),
+        F(1.29371806E-02 * C4),  F(6.79989431E-02 * C4),
+        F(8.85757540E-03 * C5),  F(5.31873032E-02 * C5),
+        F(2.92408442E-03 * C6),  F(3.90751381E-02 * C6),
+       -F(4.91578024E-03 * C7),  F(2.61098752E-02 * C7),
+        F(0.00000000E+00 * C0), -F(1.23264548E-01 * C0),
+        F(8.29847578E-02 * C1),  F(1.45389847E-01 * C1),
+        F(9.75753918E-02 * C2),  F(1.40753505E-01 * C2),
+        F(1.11196689E-01 * C3),  F(1.33264415E-01 * C3),
+        F(1.46955068E-01 * C4), -F(6.79989431E-02 * C4),
+        F(1.45389847E-01 * C5), -F(8.29847578E-02 * C5),
+        F(1.40753505E-01 * C6), -F(9.75753918E-02 * C6),
+        F(1.33264415E-01 * C7), -F(1.11196689E-01 * C7),
+        F(0.00000000E+00 * C0),  F(1.46404076E-02 * C0),
+       -F(5.31873032E-02 * C1),  F(8.85757540E-03 * C1),
+       -F(3.90751381E-02 * C2),  F(2.92408442E-03 * C2),
+       -F(2.61098752E-02 * C3), -F(4.91578024E-03 * C3),
+        F(1.29371806E-02 * C4), -F(5.65949473E-03 * C4),
+        F(1.53184106E-02 * C5), -F(8.02941163E-03 * C5),
+        F(1.62208471E-02 * C6), -F(1.04584443E-02 * C6),
+        F(1.59045603E-02 * C7), -F(1.27472335E-02 * C7),
+        F(0.00000000E+00 * C0), -F(9.02154502E-04 * C0),
+       -F(3.49717454E-03 * C1),  F(2.10371989E-03 * C1),
+       -F(1.64973098E-03 * C2),  F(1.99454554E-03 * C2),
+       -F(1.78805361E-04 * C3),  F(1.61656283E-03 * C3),
+        F(2.01182542E-03 * C4),  F(0.00000000E+00 * C4),
+        F(1.78371725E-03 * C5), -F(1.56575398E-04 * C5),
+        F(1.47640169E-03 * C6), -F(3.43256425E-04 * C6),
+        F(1.13992507E-03 * C7), -F(5.54620202E-04 * C7),
+#undef F
+#define F(x) F_COS8(x)
+       -F(1.0000000000 / C0),  F(0.8314696123 / C1),
+       -F(1.0000000000 / C0), -F(0.1950903220 / C1),
+       -F(1.0000000000 / C0), -F(0.9807852804 / C1),
+       -F(1.0000000000 / C0), -F(0.5555702330 / C1),
+       -F(1.0000000000 / C0),  F(0.5555702330 / C1),
+       -F(1.0000000000 / C0),  F(0.9807852804 / C1),
+       -F(1.0000000000 / C0),  F(0.1950903220 / C1),
+       -F(1.0000000000 / C0), -F(0.8314696123 / C1),
+        F(0.9238795325 / C2),  F(0.9807852804 / C3),
+        F(0.3826834324 / C2),  F(0.8314696123 / C3),
+       -F(0.3826834324 / C2),  F(0.5555702330 / C3),
+       -F(0.9238795325 / C2),  F(0.1950903220 / C3),
+       -F(0.9238795325 / C2), -F(0.1950903220 / C3),
+       -F(0.3826834324 / C2), -F(0.5555702330 / C3),
+        F(0.3826834324 / C2), -F(0.8314696123 / C3),
+        F(0.9238795325 / C2), -F(0.9807852804 / C3),
+        F(0.7071067812 / C4),  F(0.5555702330 / C5),
+       -F(0.7071067812 / C4), -F(0.9807852804 / C5),
+       -F(0.7071067812 / C4),  F(0.1950903220 / C5),
+        F(0.7071067812 / C4),  F(0.8314696123 / C5),
+        F(0.7071067812 / C4), -F(0.8314696123 / C5),
+       -F(0.7071067812 / C4), -F(0.1950903220 / C5),
+       -F(0.7071067812 / C4),  F(0.9807852804 / C5),
+        F(0.7071067812 / C4), -F(0.5555702330 / C5),
+        F(0.3826834324 / C6),  F(0.1950903220 / C7),
+       -F(0.9238795325 / C6), -F(0.5555702330 / C7),
+        F(0.9238795325 / C6),  F(0.8314696123 / C7),
+       -F(0.3826834324 / C6), -F(0.9807852804 / C7),
+       -F(0.3826834324 / C6),  F(0.9807852804 / C7),
+        F(0.9238795325 / C6), -F(0.8314696123 / C7),
+       -F(0.9238795325 / C6),  F(0.5555702330 / C7),
+        F(0.3826834324 / C6), -F(0.1950903220 / C7),
+#undef F
+
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+#undef C4
+#undef C5
+#undef C6
+#undef C7
+};
index cf070d5678ee9c4f7df4b36c8bc7ecc33d081550..1ea99d5ee42dd9abdba8503817c090867b4b9acb 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2016 Realtek Corporation.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 3a3eca69c9a823d22805f4ca0f35a29290f92caa..f3d41ed901b8711829ad7ddb0091edaac95cc691 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2016 Realtek Corporation.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 5ca3ec6fd9be6c29fc77afbde9117f7d0be3af30..c2b00daa1cb2764ee306902c2d7df32bba4ab55f 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -31,7 +31,6 @@
 #define BT_VENDOR_RTK_H
 
 #include "bt_vendor_lib.h"
-#include "vnd_buildcfg.h"
 #include "rtk_btsnoop_net.h"
 #include <string.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <ctype.h>
 #include <cutils/properties.h>
+#include "rtk_common.h"
 
-
+#define RTK_VERSION "5.0.1"
 /******************************************************************************
 **  Constants & Macros
 ******************************************************************************/
 #define RTKBT_TRANS_H4          0x20
 #define RTKBT_TRANS_H5          0x10
 #define RTKBT_TRANS_UART        0x01
-#define RTKBT_TRANS_USB         0x20
-
+#define RTKBT_TRANS_USB         0x02
 
 #ifndef FALSE
 #define FALSE  0
 #define BTVNDDBG(param, ...) {}
 #endif
 
-#define DOWN_FW_CFG             _IOW('H', 201, int)
-#define SET_ISO_CFG             _IOW('H', 202, int)
-#define GET_USB_INFO            _IOW('H', 203, int)
-#define RESET_CONTROLLER        _IOW('H', 204, int)
+#define DOWN_FW_CFG             _IOW('E', 176, int)
+#define SET_ISO_CFG             _IOW('E', 177, int)
+#define RESET_CONTROLLER        _IOW('E', 178, int)
+#define DWFW_CMPLT              _IOW('E', 179, int)
+
+#define GET_USB_INFO            _IOR('E', 180, int)
+
 
 /* Device port name where Bluetooth controller attached */
 #ifndef BLUETOOTH_UART_DEVICE_PORT
index 016d15fde7721e9c0c61cf6b4abd9f5de94e2d91..bfcd51cbc4d743f90d0c5f9ccd71c796c96639b1 100755 (executable)
@@ -1,3 +1,21 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2018 Realtek 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 HARDWARE_H
 #define HARDWARE_H
 
 #define MAX_ORG_CONFIG_SIZE     (0x100*14)
 #define MAX_ALT_CONFIG_SIZE     (0x100*2)
 
-#define STREAM_TO_UINT8(u8, p) \
-  {                            \
-    (u8) = (uint8_t)(*(p));    \
-    (p) += 1;                  \
-  }
-
 struct rtk_bt_vendor_config_entry{
     uint16_t offset;
     uint8_t entry_len;
@@ -70,6 +82,7 @@ struct rtk_bt_vendor_config{
 
 #define CONFIG_MAC_OFFSET_GEN_1_2       (0x3C)      //MAC's OFFSET in config/efuse for realtek generation 1~2 bluetooth chip
 #define CONFIG_MAC_OFFSET_GEN_3PLUS     (0x44)      //MAC's OFFSET in config/efuse for rtk generation 3+ bluetooth chip
+#define CONFIG_MAC_OFFSET_GEN_4PLUS     (0x30)      //MAC's OFFSET in config/efuse for rtk generation 4+ bluetooth chip
 
 #define HCI_EVT_CMD_CMPL_OPCODE_OFFSET          (3)     //opcode's offset in COMMAND Completed Event
 #define HCI_EVT_CMD_CMPL_STATUS_OFFSET          (5)     //status's offset in COMMAND Completed Event
@@ -168,6 +181,7 @@ typedef struct
 #define ROM_LMP_8723b               0x8723
 #define ROM_LMP_8821a               0X8821
 #define ROM_LMP_8761a               0X8761
+#define ROM_LMP_8761b               0X8761
 #define ROM_LMP_8703a               0x8723
 #define ROM_LMP_8763a               0x8763
 #define ROM_LMP_8703b               0x8703
@@ -175,6 +189,7 @@ typedef struct
 #define ROM_LMP_8822b               0x8822
 #define ROM_LMP_8723d               0x8723
 #define ROM_LMP_8821c               0x8821
+#define ROM_LMP_8822c               0x8822
 
 struct rtk_epatch_entry{
     uint16_t chip_id;
index 6d62c9bbcc8443bcee4d1d76bf6977165b2af733..d5b45591ae4b139ee36fa35b3fbdcfa9cedb1382 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
  *
  ******************************************************************************/
 
+
 #ifndef RTK_HCI_H5_INT_H
 #define RTK_HCI_H5_INT_H
 
@@ -29,6 +30,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "rtk_hcidefs.h"
+#include "rtk_common.h"
 
 //HCI Command opcodes
 #define HCI_LE_READ_BUFFER_SIZE     0x2002
 #define HCI_VENDOR_RESET                0x0C03
 #define HCI_VENDOR_FORCE_RESET_AND_PATCHABLE 0xFC66
 
-
-#define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
-#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
-#define UINT32_TO_STREAM(p, u32) {*(p)++ = (uint8_t)(u32); *(p)++ = (uint8_t)((u32) >> 8); *(p)++ = (uint8_t)((u32) >> 16); *(p)++ = (uint8_t)((u32) >> 24);}
-#define STREAM_TO_UINT32(u32, p) {u32 = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + ((((uint32_t)(*((p) + 2)))) << 16) + ((((uint32_t)(*((p) + 3)))) << 24)); (p) += 4;}
-#define UINT8_TO_STREAM(p, u8)   {*(p)++ = (uint8_t)(u8);}
-
 void ms_delay (uint32_t timeout);
 
 
index f8529bb247d6946b41b12fc543b7b398d8fb424c..c1eff18ee8ff3b262d346c92e2ee323e8051dc19 100755 (executable)
@@ -1,3 +1,20 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2018 Realtek 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 RTK_BTSERVICE_H
 #define RTK_BTSERVICE_H
 
@@ -6,13 +23,6 @@
 
 #define HCI_RTKBT_AUTOPAIR_EVT                               0x30
 
-#define STREAM_TO_UINT8(u8, p) \
-      {                            \
-              (u8) = (uint8_t)(*(p));    \
-              (p) += 1;                  \
-            }
-
-
 #endif
 
 
index 3f6d4f41723dda1a3c6c55decff576c5c8e83b5b..8fa21d4b111c7103856b5902aaf9932889d775bb 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
diff --git a/rtkbt/code/libbt-vendor/include/rtk_common.h b/rtkbt/code/libbt-vendor/include/rtk_common.h
new file mode 100755 (executable)
index 0000000..8d9f748
--- /dev/null
@@ -0,0 +1,40 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2018 Realtek 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 RTK_COMMON_H
+#define RTK_COMMON_H
+
+#define RTK_UNUSED(x) (void)(x)
+
+#define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
+#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
+#define UINT32_TO_STREAM(p, u32) {*(p)++ = (uint8_t)(u32); *(p)++ = (uint8_t)((u32) >> 8); *(p)++ = (uint8_t)((u32) >> 16); *(p)++ = (uint8_t)((u32) >> 24);}
+#define STREAM_TO_UINT32(u32, p) {u32 = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + ((((uint32_t)(*((p) + 2)))) << 16) + ((((uint32_t)(*((p) + 3)))) << 24)); (p) += 4;}
+#define UINT8_TO_STREAM(p, u8)   {*(p)++ = (uint8_t)(u8);}
+#define STREAM_TO_UINT8(u8, p)   {u8 = (uint8_t)(*(p)); (p) += 1;}
+
+
+#define STREAM_SKIP_UINT8(p) \
+  do {                       \
+    (p) += 1;                \
+  } while (0)
+#define STREAM_SKIP_UINT16(p) \
+  do {                        \
+    (p) += 2;                 \
+  } while (0)
+
+#endif
index 6de14a80b1d6d8469caa992f8b0aac2172c48154..43b354436cfc13b3d1751acef10e0b1171273063 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 1999-2014 Broadcom Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
  *  limitations under the License.
  *
  ******************************************************************************/
-
 #ifndef HCIDEFS_H
 #define HCIDEFS_H
 
@@ -27,6 +26,8 @@
 #define HCI_PROTO_VERSION_4_0 0x06      /* Version for BT spec 4.0          */
 #define HCI_PROTO_VERSION_4_1 0x07      /* Version for BT spec 4.1          */
 #define HCI_PROTO_VERSION_4_2 0x08      /* Version for BT spec 4.2          */
+#define HCI_PROTO_VERSION_5_0 0x09      /* Version for BT spec 5.0          */
+
 
 /*
 **  Definitions for HCI groups
 #define HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL  (0x002C | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_SET_ADDR_RESOLUTION_ENABLE  (0x002D | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT   (0x002E | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_MAXIMUM_DATA_LENGTH    (0x002F | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_PHY                    (0x0030 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_DEFAULT_PHY             (0x0031 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_PHY                     (0x0032 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_ENH_RECEIVER_TEST           (0x0033 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_ENH_TRANSMITTER_TEST        (0x0034 | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_EXT_ADVERTISING_RANDOM_ADDRESS (0x35 | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_EXT_ADVERTISING_PARAM    (0x36 | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_EXT_ADVERTISING_DATA     (0x37 | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_EXT_ADVERTISING_SCAN_RESP (0x38 | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_EXT_ADVERTISING_ENABLE   (0x39 | HCI_GRP_BLE_CMDS)
+#define HCI_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH (0x003A | HCI_GRP_BLE_CMDS)
+#define HCI_LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS \
+  (0x003B | HCI_GRP_BLE_CMDS)
+#define HCI_LE_REMOVE_ADVERTISING_SET       (0x003C | HCI_GRP_BLE_CMDS)
+#define HCI_LE_CLEAR_ADVERTISING_SETS       (0x003D | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_PERIODIC_ADVERTISING_PARAM (0x003E | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_PERIODIC_ADVERTISING_DATA (0x003F | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE (0x0040 | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_EXTENDED_SCAN_PARAMETERS (0x0041 | HCI_GRP_BLE_CMDS)
+#define HCI_LE_SET_EXTENDED_SCAN_ENABLE     (0x0042 | HCI_GRP_BLE_CMDS)
+#define HCI_LE_EXTENDED_CREATE_CONNECTION   (0x0043 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_PERIODIC_ADVERTISING_CREATE_SYNC (0x0044 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL \
+  (0x0045 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_PERIODIC_ADVERTISING_TERMINATE_SYNC \
+  (0x0046 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_ADD_DEVICE_TO_PERIODIC_ADVERTISING_LIST \
+  (0x0047 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_RM_DEVICE_FROM_PERIODIC_ADVERTISING_LIST \
+  (0x0048 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_CLEAR_PERIODIC_ADVERTISING_LIST (0x0049 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_PERIODIC_ADVERTISING_LIST_SIZE (0x004A | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_TRANSMIT_POWER         (0x004B | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_RF_COMPENS_POWER       (0x004C | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_WRITE_RF_COMPENS_POWER      (0x004D | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_PRIVACY_MODE            (0x004E | HCI_GRP_BLE_CMDS)
 
 /* LE Get Vendor Capabilities Command OCF */
 #define HCI_BLE_VENDOR_CAP_OCF    (0x0153 | HCI_GRP_VENDOR_SPECIFIC)
 /* tracking sub event */
 #define HCI_VSE_SUBCODE_BLE_TRACKING_SUB_EVT       0x56 /* Tracking event */
 
+/* debug info sub event */
+#define HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT         0x57
+
 /* LE supported states definition */
 #define HCI_LE_ADV_STATE          0x00000001
 #define HCI_LE_SCAN_STATE         0x00000002
@@ -2609,5 +2650,49 @@ typedef struct
 #define HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_NEG_RPY_OFF           33
 #define HCI_LE_RC_CONN_PARAM_UPD_NEG_RPY_SUPPORTED(x)      ((x)[HCI_SUPP_COMMANDS_LE_RC_CONN_PARAM_UPD_NEG_RPY_OFF] & HCI_SUPP_COMMANDS_RLE_RC_CONN_PARAM_UPD_NEG_RPY_MASK)
 
+
+#define HCI_DATA_EVENT_MASK 3
+#define HCI_DATA_EVENT_OFFSET 12
+
+#define RTK_HANDLE_MASK 0x0FFF
+#define RTK_NONF_START_PACKET_BOUNDARY 0
+#define RTK_START_PACKET_BOUNDARY 2
+#define RTK_CONTINUATION_PACKET_BOUNDARY 1
+#define RTK_L2CAP_HEADER_PDU_LEN_SIZE 2
+#define RTK_L2CAP_HEADER_CID_SIZE 2
+#define RTK_L2CAP_HEADER_SIZE (RTK_L2CAP_HEADER_PDU_LEN_SIZE + RTK_L2CAP_HEADER_CID_SIZE)
+
+#define RTK_GET_BOUNDARY_FLAG(handle) (((handle) >> 12) & 0x0003)
+
+    // 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
+#define COMMAND_PREAMBLE_SIZE 3
+    // 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
+#define ACL_PREAMBLE_SIZE 4
+    // 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
+#define SCO_PREAMBLE_SIZE 3
+    // 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
+#define EVENT_PREAMBLE_SIZE 2
+
+#define HCI_PACKET_TYPE_TO_INDEX(type) ((type) - 1)
+
+#define COMMON_DATA_LENGTH_INDEX 3
+
+#define EVENT_DATA_LENGTH_INDEX 2
+
+typedef struct {
+  uint8_t hci_version;
+  uint16_t hci_revision;
+  uint8_t lmp_version;
+  uint16_t manufacturer;
+  uint16_t lmp_subversion;
+} rtkbt_version_t;
+
+typedef struct {
+  uint8_t adverting_type;
+  bool    adverting_enable;
+  bool    adverting_start;
+  bool    connetion_enable;
+} rtkbt_lescn_t;
+
 #endif
 
index 4de047c52e612291b8b2e8f289be2aacf9b1bd30..654d8eee92019ea36c2050220feb3e9386af6ac2 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2016 Realtek Corporation.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -85,6 +85,8 @@ typedef struct rtk_parse_manager_t {
 
     void (*rtk_add_le_data_count)(uint8_t data_type);
 
+    void (*rtk_set_bt_on)(uint8_t bt_on);
+
 }rtk_parse_manager_t;
 
 rtk_parse_manager_t *rtk_parse_manager_get_interface();
index c449d24c44c1b9228c14b5df0e7c97c046204d0f..824a713f902f6476367b22d41d5403de52803f49 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Realtek, Inc.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
  *  limitations under the License.
  *
  ******************************************************************************/
-
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
index b878559a2e6fa86c81d5b7fd9dc4e3602a4d9c87..65ce74317136f0139e88b805d7035942f29bf092 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -53,6 +53,7 @@ typedef enum {
     SCO_CTRL_CMD_SUSPEND,
     SCO_CTRL_GET_AUDIO_CONFIG,
     SCO_CTRL_CMD_OFFLOAD_START,
+    SCO_CTRL_CMD_CLOSE,
 } tSCO_CTRL_CMD;
 
 #define SCO_SAMPLE_RATE_8K   1
@@ -66,7 +67,7 @@ typedef enum {
 **  Constants & Macros
 ******************************************************************************/
 
-uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len);
+uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len, bool* condition);
 int Skt_Read_noblock(int fd, uint8_t *p_buf, uint32_t len);
 bool Skt_Send(int fd, uint8_t *p_buf, uint16_t msglen);
 int Skt_Send_noblock(int fd, uint8_t *p_buf, uint16_t msglen);
index d44033ee14a846436337c6ed7a237d9e388b2e1a..d0dd145b454e75068b578c29638897962fc8d158 100755 (executable)
@@ -1,19 +1,20 @@
-/*
- * Copyright (C) 2011 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
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *  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:
  *
- * 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.
- *  - 1 control system sysfs proc env & property
- */
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
 #ifndef BT_UNUSED_H
 #define BT_UNUSED_H
 #ifdef __GNUC__
index 24427a99b73374a41337055f5128a560d2996174..24bee923493087dd3348bb05ff6b17867824fb71 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -101,7 +101,7 @@ int upio_set_bluetooth_power(int on);
 ** Returns         None
 **
 *******************************************************************************/
-void upio_set(uint8_t pio, uint8_t action);//void upio_set(uint8_t pio, uint8_t action, uint8_t polarity);
+void upio_set(uint8_t pio, uint8_t action, uint8_t polarity);
 
 
 /*******************************************************************************
index 573667b09530a0f52aab3b9fdd6fcb75f0192b8c..6d6d4695721fdb06df42579194699bc04703e857 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 #include <assert.h>
 #include "rtk_parse.h"
 #include "bt_skbuff.h"
+#include "rtk_common.h"
 
 /******************************************************************************
 **  Constants & Macros
 ******************************************************************************/
 #define RTK_NO_INTR(fn)  do {} while ((fn) == -1 && errno == EINTR)
 
-#define RTK_GET_BOUNDARY_FLAG(handle) (((handle) >> 12) & 0x0003)
-#define RTK_START_PACKET_BOUNDARY 2
-
 /**** baud rates ****/
 #define USERIAL_BAUD_300        0
 #define USERIAL_BAUD_600        1
 /******************************************************************************
 **  Type definitions
 ******************************************************************************/
-    // 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
-#define COMMAND_PREAMBLE_SIZE 3
-    // 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
-#define ACL_PREAMBLE_SIZE 4
-    // 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
-#define SCO_PREAMBLE_SIZE 3
-    // 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
-#define EVENT_PREAMBLE_SIZE 2
-
-#define HCI_PACKET_TYPE_TO_INDEX(type) ((type) - 1)
-
-#define COMMON_DATA_LENGTH_INDEX 3
-
-#define EVENT_DATA_LENGTH_INDEX 2
-
 /* Structure used to configure serial port during open */
 typedef struct
 {
@@ -219,5 +202,5 @@ void userial_recv_rawdata_hook(unsigned char *buffer, unsigned int total_length)
 
 #define RTK_HANDLE_EVENT
 #define RTK_HANDLE_CMD
-#define CONFIG_SCO_OVER_HCI
+//#define CONFIG_SCO_OVER_HCI
 #endif /* USERIAL_VENDOR_H */
diff --git a/rtkbt/code/libbt-vendor/src/Android.mk b/rtkbt/code/libbt-vendor/src/Android.mk
new file mode 100755 (executable)
index 0000000..aa1b06e
--- /dev/null
@@ -0,0 +1,42 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+BDROID_DIR := $(TOP_DIR)system/bt
+
+LOCAL_SRC_FILES := \
+        rtk_socket.c \
+        bt_vendor_rtk.c \
+        hardware.c \
+        userial_vendor.c \
+        upio.c \
+        bt_list.c \
+        bt_skbuff.c \
+        hci_h5.c \
+        rtk_parse.c \
+        rtk_btservice.c \
+        hardware_uart.c \
+        hardware_usb.c \
+        rtk_heartbeat.c \
+        rtk_poll.c \
+        rtk_btsnoop_net.c
+
+LOCAL_C_INCLUDES += \
+        $(LOCAL_PATH)/../include \
+        $(LOCAL_PATH)/../codec/sbc \
+        $(BDROID_DIR)/hci/include
+
+LOCAL_SHARED_LIBRARIES := \
+        libcutils \
+        libutils \
+        liblog
+
+LOCAL_WHOLE_STATIC_LIBRARIES := \
+        libbt-codec
+
+LOCAL_MODULE := libbt-vendor-realtek
+LOCAL_MODULE_TAGS := optional
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+include $(BUILD_SHARED_LIBRARY)
index 77227b64f91aaca77bfa0edbc4bf08c8d9d02224..61d0ac07a4ff079a6c18a253b7d3686dcd2a5def 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2016 Realtek Corporation.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 8600d0eb56ce8533e67dc7db94be411802897f3a..75977fae79415a55da65a6c947ede6732cbef3e1 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2016 Realtek Corporation.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -267,14 +267,16 @@ RtbQueueInit(
 )
 {
     RTB_QUEUE_HEAD* RtbQueue = NULL;
-
+    int ret = 0;
     RtbQueue = malloc(sizeof(RTB_QUEUE_HEAD));
     if(RtbQueue)
     {
-        pthread_mutex_init(&RtbQueue->Lock, NULL);
-        ListInitializeHeader(&RtbQueue->List);
-        RtbQueue->QueueLen = 0;
-        return RtbQueue;
+        ret = pthread_mutex_init(&RtbQueue->Lock, NULL);
+        if(!ret) {
+          ListInitializeHeader(&RtbQueue->List);
+          RtbQueue->QueueLen = 0;
+          return RtbQueue;
+        }
     }
 
     //error code comes here
index f7151ce850761c6e40b6a3d3369130ba3ff45683..f523af81449a62238a3bc267d403f241a6dd0f44 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
 
 #undef NDEBUG
 #define LOG_TAG "libbt_vendor"
-#define RTKBT_RELEASE_NAME "20180702_BT_ANDROID_9.0"
+#define RTKBT_RELEASE_NAME "20190520_BT_ANDROID_9.0"
 #include <utils/Log.h>
 #include "bt_vendor_rtk.h"
 #include "upio.h"
@@ -282,6 +282,7 @@ static void load_rtkbt_conf()
         if (!split) {
         ALOGE("%s no key/value separator found on line %d.", __func__, line_num);
         strcpy(rtkbt_device_node,"/dev/rtkbt_dev");
+        fclose(fp);
         return;
       }
 
@@ -327,6 +328,20 @@ static void load_rtkbt_conf()
     }
     else {
         rtkbt_transtype |= RTKBT_TRANS_USB;
+        rtkbt_transtype |= RTKBT_TRANS_H4;
+    }
+}
+
+static void byte_reverse(unsigned char* data, int len)
+{
+    int i;
+    int tmp;
+
+    for(i = 0; i < len/2; i++) {
+        tmp = len - i - 1;
+        data[i] ^= data[tmp];
+        data[tmp] ^= data[i];
+        data[i] ^= data[tmp];
     }
 }
 
@@ -362,6 +377,7 @@ static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr)
 
     /* This is handed over from the stack */
     memcpy(vnd_local_bd_addr, local_bdaddr, 6);
+    byte_reverse(vnd_local_bd_addr, 6);
 
     if(rtk_btsnoop_dump)
         rtk_btsnoop_open();
@@ -411,8 +427,15 @@ static int op(bt_vendor_opcode_t opcode, void *param)
                     hw_config_start(rtkbt_transtype);
                 }
                 else {
-                  retval = userial_vendor_usb_ioctl(GET_USB_INFO, NULL);
-                  hw_usb_config_start(RTKBT_TRANS_H4,retval);
+                  int usb_info = 0;
+                  retval = userial_vendor_usb_ioctl(GET_USB_INFO, &usb_info);
+                  if(retval == -1) {
+                    ALOGE("get usb info fail");
+                    bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
+                    return retval;
+                  }
+                  else
+                    hw_usb_config_start(RTKBT_TRANS_H4, usb_info);
                 }
                 RTK_btservice_init();
             }
index b26f897ad78dff281d51611b9d212cdf70e66700..b6abc8fe1b5fa219b4afe63097f7d8dd8ba27d92 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
  ******************************************************************************/
 
 #define LOG_TAG "bt_hwcfg"
-#define RTKBT_RELEASE_NAME "20180702_BT_ANDROID_9.0"
+#define RTKBT_RELEASE_NAME "20190520_BT_ANDROID_9.0"
 
 #include <utils/Log.h>
 #include <sys/types.h>
@@ -56,7 +56,6 @@
 /******************************************************************************
 **  Constants &  Macros
 ******************************************************************************/
-#define RTK_VERSION "4.1.1"
 
 /******************************************************************************
 **  Externs
@@ -96,16 +95,32 @@ int getmacaddr(unsigned char * addr)
     char data[256], *str;
     int addr_fd;
 
-    if ((addr_fd = open("/data/misc/bluetooth/bdaddr", O_RDONLY)) != -1)
-    {
-        memset(data, 0, sizeof(data));
-        read(addr_fd, data, 17);
-        for (i = 0,str = data; i < 6; i++) {
-           addr[5-i] = (unsigned char)strtoul(str, &str, 16);
-           str++;
+    char property[100] = {0};
+    if (property_get("persist.vendor.rtkbt.bdaddr_path", property, "none")) {
+        if(strcmp(property, "none") == 0) {
+            return -1;
+        }
+        else if(strcmp(property, "default") == 0) {
+          memcpy(addr, vnd_local_bd_addr, BD_ADDR_LEN);
+          return 0;
+
+        }
+        else if ((addr_fd = open(property, O_RDONLY)) != -1)
+        {
+            memset(data, 0, sizeof(data));
+            int ret = read(addr_fd, data, 17);
+            if(ret < 17) {
+                ALOGE("%s, read length = %d", __func__, ret);
+                close(addr_fd);
+                return -1;
+            }
+            for (i = 0,str = data; i < 6; i++) {
+                addr[5-i] = (unsigned char)strtoul(str, &str, 16);
+                str++;
+            }
+            close(addr_fd);
+            return 0;
         }
-        close(addr_fd);
-        return 0;
     }
     return -1;
 }
index 29dfe11d747920cfaeba5a004096f7cbd0739632..39dd76695a9662d5547147532a65a5d17225abc9 100755 (executable)
@@ -1,5 +1,23 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2018 Realtek 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.
+ *
+ ******************************************************************************/
+
 #define LOG_TAG "bt_hwcfg_uart"
-#define RTKBT_RELEASE_NAME     "Test"
+#define RTKBT_RELEASE_NAME "20190520_BT_ANDROID_9.0"
 
 #include <utils/Log.h>
 #include <sys/types.h>
@@ -28,7 +46,6 @@
 /******************************************************************************
 **  Constants &  Macros
 ******************************************************************************/
-#define RTK_VERSION "4.1.1"
 
 extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
 extern bool rtkbt_auto_restart;
@@ -40,6 +57,9 @@ extern struct rtk_epatch_entry *rtk_get_patch_entry(bt_hw_cfg_cb_t *cfg_cb);
 extern int rtk_get_bt_firmware(uint8_t** fw_buf, char* fw_short_name);
 extern volatile int h5_init_datatrans_flag;
 
+#define EXTRA_CONFIG_FILE "/vendor/etc/bluetooth/rtk_btconfig.txt"
+static struct rtk_bt_vendor_config_entry *extra_extry;
+static struct rtk_bt_vendor_config_entry *extra_entry_inx = NULL;
 
 
 /******************************************************************************
@@ -87,14 +107,19 @@ static patch_info patch_table[] = {
     {0x8723,            ~(HCI_VERSION_MASK_21),  ~(1<<0xd),             CHIP_TYPE_MASK_ALL,  1<<1,                  "rtl8723bs_fw",         "rtl8723bs_config",     CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K},     //Rtl8723BS
 //    {0x8723,            ~(HCI_VERSION_MASK_21),  ~(1<<0xd),             CHIP_TYPE_MASK_ALL,  1<<1,                  "rtl8723bs_VQ0_fw",     "rtl8723bs_VQ0_config", CONFIG_MAC_OFFSET_GEN_1_2}, //Rtl8723BS_VQ0
     {0x8821,            HCI_VERSION_MASK_ALL,    ~(1<<0xc),             CHIP_TYPE_MASK_ALL,  1<<2,                  "rtl8821as_fw",         "rtl8821as_config",     CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K},     //Rtl8821AS
-    {0x8761,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL,  1<<3,                  "rtl8761at_fw",         "rtl8761at_config",     CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K},     //Rtl8761AW
+//  {0x8761,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL,  1<<3,                  "rtl8761at_fw",         "rtl8761at_config",     CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K},     //Rtl8761AW
+    {0x8761,            HCI_VERSION_MASK_ALL,    ~(1<<0xb),             CHIP_TYPE_MASK_ALL,  1<<3,                  "rtl8761at_fw",         "rtl8761at_config",     CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K},     //Rtl8761AW
+    {0x8761,            HCI_VERSION_MASK_ALL,    (1<<0xb),              CHIP_TYPE_MASK_ALL,  1<<14,                 "rtl8761bt_fw",         "rtl8761bt_config",     CONFIG_MAC_OFFSET_GEN_4PLUS,  MAX_PATCH_SIZE_40K},     //Rtl8761BW
+
     {0x8723,            HCI_VERSION_MASK_21,     HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL,  1<<4,                  "rtl8703as_fw",         "rtl8703as_config",     CONFIG_MAC_OFFSET_GEN_1_2,  MAX_PATCH_SIZE_24K},     //Rtl8703AS
 
     {0x8703,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, 1<<7,                1<<6,                  "rtl8703bs_fw",         "rtl8703bs_config",     CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_24K},     //Rtl8703BS
     {0x8703,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, 1<<5,                1<<7,                  "rtl8723cs_xx_fw",      "rtl8723cs_xx_config",  CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_24K},     //rtl8723cs_xx
     {0x8703,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, 1<<3,                1<<7,                  "rtl8723cs_cg_fw",      "rtl8723cs_cg_config",  CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_24K},     //rtl8723cs_cg
     {0x8703,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, 1<<4,                1<<7,                  "rtl8723cs_vf_fw",      "rtl8723cs_vf_config",  CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_24K},     //rtl8723cs_vf
-    {0x8822,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL,  1<<8,                  "rtl8822bs_fw",         "rtl8822bs_config",     CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_24K},     //Rtl8822BS
+//  {0x8822,            HCI_VERSION_MASK_ALL,    HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL,  1<<8,                  "rtl8822bs_fw",         "rtl8822bs_config",     CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_24K},   //Rtl8822BS
+    {0x8822,            HCI_VERSION_MASK_ALL,    ~(1<<0xc),             CHIP_TYPE_MASK_ALL,  1<<8,                  "rtl8822bs_fw",         "rtl8822bs_config",     CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_24K},     //Rtl8822BS
+    {0x8822,            HCI_VERSION_MASK_ALL,    (1<<0xc),              CHIP_TYPE_MASK_ALL,  1<<13,                 "rtl8822cs_fw",         "rtl8822cs_config",     CONFIG_MAC_OFFSET_GEN_4PLUS,  MAX_PATCH_SIZE_40K},     //Rtl8822CS
 
     {0x8723,            HCI_VERSION_MASK_ALL,    (1<<0xd),              ~(1<<7),           1<<9,                    "rtl8723ds_fw",         "rtl8723ds_config",     CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_40K}, //Rtl8723ds
     {0x8723,            HCI_VERSION_MASK_ALL,    (1<<0xd),              1<<7,              1<<9,                    "rtl8703cs_fw",         "rtl8703cs_config",     CONFIG_MAC_OFFSET_GEN_3PLUS,  MAX_PATCH_SIZE_40K}, //Rtl8703cs
@@ -388,26 +413,160 @@ static inline void uart_speed_to_rtk_speed(uint32_t uart_speed, uint32_t* rtk_sp
 }
 */
 
+static void line_process(char *buf, unsigned short *offset, int *t)
+{
+    char *head = buf;
+    char *ptr = buf;
+    char *argv[32];
+    int argc = 0;
+    unsigned char len = 0;
+    int i = 0;
+    static int alt_size = 0;
+
+    if(buf[0] == '\0' || buf[0] == '#' || buf[0] == '[')
+        return;
+    if(alt_size > MAX_ALT_CONFIG_SIZE-4)
+    {
+        ALOGW("Extra Config file is too large");
+        return;
+    }
+    if(extra_entry_inx == NULL)
+        extra_entry_inx = extra_extry;
+    ALOGI("line_process:%s", buf);
+    while((ptr = strsep(&head, ", \t")) != NULL)
+    {
+        if(!ptr[0])
+            continue;
+        argv[argc++] = ptr;
+        if(argc >= 32) {
+            ALOGW("Config item is too long");
+            break;
+        }
+    }
+
+    if(argc <4) {
+        ALOGE("Invalid Config item, ignore");
+        return;
+    }
+
+    offset[(*t)] = (unsigned short)((strtoul(argv[0], NULL, 16)) | (strtoul(argv[1], NULL, 16) << 8));
+    ALOGI("Extra Config offset %04x", offset[(*t)]);
+    extra_entry_inx->offset = offset[(*t)];
+    (*t)++;
+    len = (unsigned char)strtoul(argv[2], NULL, 16);
+    if(len != (unsigned char)(argc - 3)) {
+        ALOGE("Extra Config item len %d is not match, we assume the actual len is %d", len, (argc-3));
+        len = argc -3;
+    }
+    extra_entry_inx->entry_len = len;
+
+    alt_size += len + sizeof(struct rtk_bt_vendor_config_entry);
+    if(alt_size > MAX_ALT_CONFIG_SIZE)
+    {
+        ALOGW("Extra Config file is too large");
+        extra_entry_inx->offset = 0;
+        extra_entry_inx->entry_len = 0;
+        alt_size -= (len + sizeof(struct rtk_bt_vendor_config_entry));
+        return;
+    }
+    for(i = 0; i < len; i++)
+    {
+        extra_entry_inx->entry_data[i] = (uint8_t)strtoul(argv[3+i], NULL, 16);
+        ALOGI("data[%d]:%02x", i, extra_entry_inx->entry_data[i]);
+    }
+    extra_entry_inx = (struct rtk_bt_vendor_config_entry *)((uint8_t *)extra_entry_inx + len + sizeof(struct rtk_bt_vendor_config_entry));
+}
+
+static void parse_extra_config(const char *path, patch_info *patch_entry, unsigned short *offset, int *t)
+{
+    int fd, ret;
+    unsigned char buf[1024];
+
+    fd = open(path, O_RDONLY);
+    if(fd == -1) {
+        ALOGI("Couldn't open extra config %s, err:%s", path, strerror(errno));
+        return;
+    }
+
+    ret = read(fd, buf, sizeof(buf));
+    if(ret == -1) {
+        ALOGE("Couldn't read %s, err:%s", path, strerror(errno));
+        close(fd);
+        return;
+    }
+    else if(ret == 0) {
+        ALOGE("%s is empty", path);
+        close(fd);
+        return;
+    }
+
+    if(ret > 1022) {
+        ALOGE("Extra config file is too big");
+        close(fd);
+        return;
+    }
+    buf[ret++] = '\n';
+    buf[ret++] = '\0';
+    close(fd);
+    char *head = (void *)buf;
+    char *ptr = (void *)buf;
+    ptr = strsep(&head, "\n\r");
+    if(strncmp(ptr, patch_entry->config_name, strlen(ptr)))
+    {
+        ALOGW("Extra config file not set for %s, ignore", patch_entry->config_name);
+        return;
+    }
+    while((ptr = strsep(&head, "\n\r")) != NULL)
+    {
+        if(!ptr[0])
+            continue;
+        line_process(ptr, offset, t);
+    }
+}
 
 static inline int getAltSettings(patch_info *patch_entry, unsigned short *offset)//(patch_info *patch_entry, unsigned short *offset, int max_group_cnt)
 {
     int n = 0;
     if(patch_entry)
         offset[n++] = patch_entry->mac_offset;
+    else
+      return n;
 /*
 //sample code, add special settings
 
     offset[n++] = 0x15B;
 */
+    if(extra_extry)
+        parse_extra_config(EXTRA_CONFIG_FILE, patch_entry, offset, &n);
+
     return n;
 }
 static inline int getAltSettingVal(patch_info *patch_entry, unsigned short offset, unsigned char * val)
 {
     int res = 0;
+    int i = 0;
+    struct rtk_bt_vendor_config_entry *ptr = extra_extry;
 
-    switch(offset)
+    while(ptr->offset)
     {
+        if(ptr->offset == offset)
+        {
+            if(offset != patch_entry->mac_offset)
+            {
+                memcpy(val, ptr->entry_data, ptr->entry_len);
+                res = ptr->entry_len;
+                ALOGI("Get Extra offset:%04x, val:", offset);
+                for(i = 0; i < ptr->entry_len; i++)
+                    ALOGI("%02x", ptr->entry_data[i]);
+            }
+            break;
+        }
+        ptr = (struct rtk_bt_vendor_config_entry *)((uint8_t *)ptr + ptr->entry_len + sizeof(struct rtk_bt_vendor_config_entry));
+    }
 /*
+    switch(offset)
+    {
+
 //sample code, add special settings
         case 0x15B:
             val[0] = 0x0B;
@@ -416,11 +575,12 @@ static inline int getAltSettingVal(patch_info *patch_entry, unsigned short offse
             val[3] = 0x0B;
             res = 4;
             break;
-*/
+
         default:
             res = 0;
             break;
     }
+*/
     if((patch_entry)&&(offset == patch_entry->mac_offset)&&(res == 0))
     {
         if(getmacaddr(val) == 0){
@@ -441,7 +601,14 @@ static void rtk_update_altsettings(patch_info *patch_entry, unsigned char* confi
     struct rtk_bt_vendor_config_entry* entry = config->entry;
     size_t config_len = *config_len_ptr;
     unsigned int  i = 0;
-       int count = 0,temp = 0, j;
+    int count = 0,temp = 0, j;
+
+    if((extra_extry = (struct rtk_bt_vendor_config_entry *)malloc(MAX_ALT_CONFIG_SIZE)) == NULL)
+    {
+        ALOGE("malloc buffer for extra_extry failed");
+    }
+    else
+        memset(extra_extry, 0, MAX_ALT_CONFIG_SIZE);
 
     ALOGI("ORG Config len=%08zx:\n", config_len);
     for(i=0;i<=config_len;i+=0x10)
@@ -474,7 +641,23 @@ static void rtk_update_altsettings(patch_info *patch_entry, unsigned char* confi
         for(j = 0; j < count;j++)
         {
             if(le16_to_cpu(entry->offset) == offset[j])
-                offset[j] = 0;
+            {
+                if(offset[j] == patch_entry->mac_offset)
+                    offset[j] = 0;
+                else
+                {
+                    struct rtk_bt_vendor_config_entry *t = extra_extry;
+                    while(t->offset) {
+                        if(t->offset == le16_to_cpu(entry->offset))
+                        {
+                            if(t->entry_len == entry->entry_len)
+                                offset[j] = 0;
+                            break;
+                        }
+                        t = (struct rtk_bt_vendor_config_entry *)((uint8_t *)t + t->entry_len + sizeof(struct rtk_bt_vendor_config_entry));
+                    }
+                }
+            }
         }
         if(getAltSettingVal(patch_entry, le16_to_cpu(entry->offset), val) == entry->entry_len){
             ALOGI("rtk_update_altsettings: replace %04x[%02x]", le16_to_cpu(entry->offset), entry->entry_len);
@@ -500,6 +683,13 @@ static void rtk_update_altsettings(patch_info *patch_entry, unsigned char* confi
     config->data_len = cpu_to_le16(i);
     *config_len_ptr = i+sizeof(struct rtk_bt_vendor_config);
 
+    if(extra_extry)
+    {
+        free(extra_extry);
+        extra_extry = NULL;
+        extra_entry_inx = NULL;
+    }
+
     ALOGI("NEW Config len=%08zx:\n", *config_len_ptr);
     for(i=0;i<=(*config_len_ptr);i+=0x10)
     {
@@ -522,7 +712,7 @@ static uint32_t rtk_parse_config_file(unsigned char** config_buf, size_t* filele
     //uint32_t config_has_bdaddr = 0;
     uint8_t *p;
 
-       ALOGD("bt_addr = %x", bt_addr[0]);
+    ALOGD("bt_addr = %x", bt_addr[0]);
     if (le32_to_cpu(config->signature) != RTK_VENDOR_CONFIG_MAGIC)
     {
         ALOGE("config signature magic number(0x%x) is not set to RTK_VENDOR_CONFIG_MAGIC", config->signature);
@@ -571,7 +761,7 @@ static uint32_t rtk_parse_config_file(unsigned char** config_buf, size_t* filele
             }
             case 0x01be:
             {
-                if(mac_offset == CONFIG_MAC_OFFSET_GEN_3PLUS)
+                if(mac_offset == CONFIG_MAC_OFFSET_GEN_3PLUS || mac_offset == CONFIG_MAC_OFFSET_GEN_4PLUS)
                 {
                     p = (uint8_t *)entry->entry_data;
                     STREAM_TO_UINT8(heartbeat_buf, p);
@@ -584,21 +774,6 @@ static uint32_t rtk_parse_config_file(unsigned char** config_buf, size_t* filele
                 }
                 break;
             }
-#if (USE_CONTROLLER_BDADDR == FALSE)
-            case 0x44:
-            case 0x3c:
-            {
-                 int j=0;
-                 for (j=0; j<entry->entry_len; j++)
-                     entry->entry_data[j] = bt_addr[entry->entry_len - 1- j];
-                 ALOGI("rtk_parse_config_file: DO NOT USE_CONTROLLER_BDADDR, config has bdaddr");
-                 ALOGI("rtk_parse_config_file : CONFIG_ADDR is: %02X:%02X:%02X:%02X:%02X:%02X",
-                    bt_addr[0], bt_addr[1],
-                    bt_addr[2], bt_addr[3],
-                    bt_addr[4], bt_addr[5]);
-                 break;
-            }
-#endif
             default:
                 ALOGI("config offset(0x%x),length(0x%x)", entry->offset, entry->entry_len);
                 break;
@@ -743,27 +918,27 @@ static uint32_t rtk_get_bt_config(unsigned char** config_buf,
     if (stat(bt_config_file_name, &st) < 0)
     {
         ALOGE("can't access bt config file:%s, errno:%d\n", bt_config_file_name, errno);
-        return -1;
+        return 0;
     }
 
     filelen = st.st_size;
     if(filelen > MAX_ORG_CONFIG_SIZE)
     {
         ALOGE("bt config file is too large(>0x%04x)", MAX_ORG_CONFIG_SIZE);
-        return -1;
+        return 0;
     }
 
     if ((fd = open(bt_config_file_name, O_RDONLY)) < 0)
     {
         ALOGE("Can't open bt config file");
-        return -1;
+        return 0;
     }
 
     if ((*config_buf = malloc(MAX_ORG_CONFIG_SIZE+MAX_ALT_CONFIG_SIZE)) == NULL)
     {
         ALOGE("malloc buffer for config file fail(0x%zx)\n", filelen);
         close(fd);
-        return -1;
+        return 0;
     }
 
     if (read(fd, *config_buf, filelen) < (ssize_t)filelen)
@@ -771,7 +946,7 @@ static uint32_t rtk_get_bt_config(unsigned char** config_buf,
         ALOGE("Can't load bt config file");
         free(*config_buf);
         close(fd);
-        return -1;
+        return 0;
     }
 
     *config_baud_rate = rtk_parse_config_file(config_buf, &filelen, vnd_local_bd_addr, mac_offset);
@@ -837,9 +1012,10 @@ void hw_config_cback(void *p_mem)
         if(status != 0) {
           ALOGE("%s, status = %d", __func__, status);
           if ((bt_vendor_cbacks) && (p_evt_buf != NULL))
-          bt_vendor_cbacks->dealloc(p_evt_buf);
+              bt_vendor_cbacks->dealloc(p_evt_buf);
           if(rtkbt_auto_restart) {
-              bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
+              if(bt_vendor_cbacks)
+                  bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
               kill(getpid(), SIGKILL);
           }
           return;
@@ -874,7 +1050,7 @@ void hw_config_cback(void *p_mem)
             }
             case HW_CFG_READ_LOCAL_VER:
             {
-                if (status == 0)
+                if (status == 0 && p_evt_buf)
                 {
                     p = ((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_VERSION_OFFSET);
                     STREAM_TO_UINT16(hw_cfg_cb.hci_version, p);
@@ -902,7 +1078,7 @@ void hw_config_cback(void *p_mem)
             }
             case HW_CFG_READ_ECO_VER:
             {
-                if(status == 0)
+                if(status == 0 && p_evt_buf)
                 {
                     hw_cfg_cb.eversion = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPFC6D_EVERSION_OFFSET);
                     BTVNDDBG("hw_config_cback chip_id of the IC:%d", hw_cfg_cb.eversion+1);
@@ -942,6 +1118,11 @@ void hw_config_cback(void *p_mem)
             }
             case HW_CFG_READ_CHIP_TYPE:
             {
+                if(!p_evt_buf) {
+                    ALOGE("%s, buffer is null", __func__);
+                    is_proceeding = FALSE;
+                    break;
+                }
                 BTVNDDBG("READ_CHIP_TYPE status = %d, length = %d", status, p_evt_buf->len);
                 p = (uint8_t *)(p_evt_buf + 1) ;
                 for (i = 0; i < p_evt_buf->len; i++)
@@ -1011,10 +1192,10 @@ CFG_START:
                 }
                 hw_cfg_cb.max_patch_size = prtk_patch_file_info->max_patch_size;
                 hw_cfg_cb.config_len = rtk_get_bt_config(&hw_cfg_cb.config_buf, &hw_cfg_cb.baudrate, prtk_patch_file_info->config_name, prtk_patch_file_info->mac_offset);
-                if (hw_cfg_cb.config_len < 0)
+                if (hw_cfg_cb.config_len == 0)
                 {
                     ALOGE("Get Config file fail, just use efuse settings");
-                    hw_cfg_cb.config_len = 0;
+                    //hw_cfg_cb.config_len = 0;
                 }
                 rtk_update_altsettings(prtk_patch_file_info, hw_cfg_cb.config_buf, &(hw_cfg_cb.config_len));
 
index cf8aa775e5483bc00b17a8518eed45cdd63f2c64..afcc7504afbc8dd4fe3f612e8c19dec7448af9a2 100755 (executable)
@@ -1,5 +1,23 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2018 Realtek 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.
+ *
+ ******************************************************************************/
+
 #define LOG_TAG "bt_hwcfg_usb"
-#define RTKBT_RELEASE_NAME     "Test"
+#define RTKBT_RELEASE_NAME "20190520_BT_ANDROID_9.0"
 
 #include <utils/Log.h>
 #include <sys/types.h>
 
 #include "bt_vendor_lib.h"
 #include "hardware.h"
+#include "rtk_common.h"
 
 /******************************************************************************
 **  Constants &  Macros
 ******************************************************************************/
-#define RTK_VERSION "4.1.1"
 
 extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
 extern bool rtkbt_auto_restart;
@@ -39,6 +57,9 @@ extern struct rtk_epatch_entry *rtk_get_patch_entry(bt_hw_cfg_cb_t *cfg_cb);
 extern int rtk_get_bt_firmware(uint8_t** fw_buf, char* fw_short_name);
 extern uint8_t rtk_get_fw_project_id(uint8_t *p_buf);
 
+#define EXTRA_CONFIG_FILE "/vendor/etc/bluetooth/rtk_btconfig.txt"
+static struct rtk_bt_vendor_config_entry *extra_extry;
+static struct rtk_bt_vendor_config_entry *extra_entry_inx = NULL;
 
 /******************************************************************************
 **  Static variables
@@ -98,6 +119,8 @@ static usb_patch_info usb_fw_patch_table[] = {
 { 0x0BDA, 0xB761, 0x8761, 0, 0, "mp_rtl8761a_fw", "rtl8761au_fw", "rtl8761a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8761AUV only */
 { 0x0BDA, 0x8761, 0x8761, 0, 0, "mp_rtl8761a_fw", "rtl8761au8192ee_fw", "rtl8761a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8761AU + 8192EE for LI */
 { 0x0BDA, 0x8A60, 0x8761, 0, 0, "mp_rtl8761a_fw", "rtl8761au8812ae_fw", "rtl8761a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8761AU + 8812AE */
+{ 0x0BDA, 0x8771, 0x8761, 0, 0, "mp_rtl8761b_fw", "rtl8761b_fw", "rtl8761b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, /* RTL8761BU */
+{ 0x0BDA, 0xa725, 0x8761, 0, 0, "mp_rtl8725a_fw", "rtl8725a_fw", "rtl8725a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, /* RTL8725AU */
 
 { 0x0BDA, 0x8821, 0x8821, 0, 0, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8821AE */
 { 0x0BDA, 0x0821, 0x8821, 0, 0, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8821AE */
@@ -111,6 +134,8 @@ static usb_patch_info usb_fw_patch_table[] = {
 { 0x0BDA, 0xB82C, 0x8822, 0, 0, "mp_rtl8822b_fw", "rtl8822b_fw", "rtl8822b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, /* RTL8822BU */
 { 0x0BDA, 0xB023, 0x8822, 0, 0, "mp_rtl8822b_fw", "rtl8822b_fw", "rtl8822b_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, /* RTL8822BE */
 { 0x0BDA, 0xB703, 0x8703, 0, 0, "mp_rtl8723c_fw", "rtl8723c_fw", "rtl8723c_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, /* RTL8723CU */
+{ 0x0BDA, 0xC82C, 0x8822, 0, 0, "mp_rtl8822c_fw", "rtl8822c_fw", "rtl8822c_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, /* RTL8822CU */
+{ 0x0BDA, 0xC822, 0x8822, 0, 0, "mp_rtl8822c_fw", "rtl8822c_fw", "rtl8822c_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, /* RTL8822CE */
 /* todo: RTL8703BU */
 
 { 0x0BDA, 0xD723, 0x8723, 0, 0, "mp_rtl8723d_fw", "rtl8723d_fw", "rtl8723d_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, /* RTL8723DU */
@@ -137,6 +162,10 @@ uint16_t usb_project_id[] = {
     ROM_LMP_8822b,
     ROM_LMP_8723d,
     ROM_LMP_8821c,
+    ROM_LMP_NONE,
+    ROM_LMP_NONE,
+    ROM_LMP_8822c,
+    ROM_LMP_8761b,
     ROM_LMP_NONE
 };
 //signature: realtech
@@ -144,16 +173,132 @@ static const uint8_t RTK_EPATCH_SIGNATURE[8]={0x52,0x65,0x61,0x6C,0x74,0x65,0x63
 //Extension Section IGNATURE:0x77FD0451
 static const uint8_t EXTENSION_SECTION_SIGNATURE[4]={0x51,0x04,0xFD,0x77};
 
+static void usb_line_process(char *buf, unsigned short *offset, int *t)
+{
+    char *head = buf;
+    char *ptr = buf;
+    char *argv[32];
+    int argc = 0;
+    unsigned char len = 0;
+    int i = 0;
+    static int alt_size = 0;
+
+    if(buf[0] == '\0' || buf[0] == '#' || buf[0] == '[')
+        return;
+    if(alt_size > MAX_ALT_CONFIG_SIZE-4)
+    {
+        ALOGW("Extra Config file is too large");
+        return;
+    }
+    if(extra_entry_inx == NULL)
+        extra_entry_inx = extra_extry;
+    ALOGI("line_process:%s", buf);
+    while((ptr = strsep(&head, ", \t")) != NULL)
+    {
+        if(!ptr[0])
+            continue;
+        argv[argc++] = ptr;
+        if(argc >= 32) {
+            ALOGW("Config item is too long");
+            break;
+        }
+    }
+
+    if(argc <4) {
+        ALOGE("Invalid Config item, ignore");
+        return;
+    }
+
+    offset[(*t)] = (unsigned short)((strtoul(argv[0], NULL, 16)) | (strtoul(argv[1], NULL, 16) << 8));
+    ALOGI("Extra Config offset %04x", offset[(*t)]);
+    extra_entry_inx->offset = offset[(*t)];
+    (*t)++;
+    len = (unsigned char)strtoul(argv[2], NULL, 16);
+    if(len != (unsigned char)(argc - 3)) {
+        ALOGE("Extra Config item len %d is not match, we assume the actual len is %d", len, (argc-3));
+        len = argc -3;
+    }
+    extra_entry_inx->entry_len = len;
+
+    alt_size += len + sizeof(struct rtk_bt_vendor_config_entry);
+    if(alt_size > MAX_ALT_CONFIG_SIZE)
+    {
+        ALOGW("Extra Config file is too large");
+        extra_entry_inx->offset = 0;
+        extra_entry_inx->entry_len = 0;
+        alt_size -= (len + sizeof(struct rtk_bt_vendor_config_entry));
+        return;
+    }
+    for(i = 0; i < len; i++)
+    {
+        extra_entry_inx->entry_data[i] = (uint8_t)strtoul(argv[3+i], NULL, 16);
+        ALOGI("data[%d]:%02x", i, extra_entry_inx->entry_data[i]);
+    }
+    extra_entry_inx = (struct rtk_bt_vendor_config_entry *)((uint8_t *)extra_entry_inx + len + sizeof(struct rtk_bt_vendor_config_entry));
+}
+
+static void usb_parse_extra_config(const char *path, usb_patch_info *patch_entry, unsigned short *offset, int *t)
+{
+    int fd, ret;
+    unsigned char buf[1024];
+
+    fd = open(path, O_RDONLY);
+    if(fd == -1) {
+        ALOGI("Couldn't open extra config %s, err:%s", path, strerror(errno));
+        return;
+    }
+
+    ret = read(fd, buf, sizeof(buf));
+    if(ret == -1) {
+        ALOGE("Couldn't read %s, err:%s", path, strerror(errno));
+        close(fd);
+        return;
+    }
+    else if(ret == 0) {
+        ALOGE("%s is empty", path);
+        close(fd);
+        return;
+    }
+
+    if(ret > 1022) {
+        ALOGE("Extra config file is too big");
+        close(fd);
+        return;
+    }
+    buf[ret++] = '\n';
+    buf[ret++] = '\0';
+    close(fd);
+    char *head = (void *)buf;
+    char *ptr = (void *)buf;
+    ptr = strsep(&head, "\n\r");
+    if(strncmp(ptr, patch_entry->config_name, strlen(ptr)))
+    {
+        ALOGW("Extra config file not set for %s, ignore", patch_entry->config_name);
+        return;
+    }
+    while((ptr = strsep(&head, "\n\r")) != NULL)
+    {
+        if(!ptr[0])
+            continue;
+        usb_line_process(ptr, offset, t);
+    }
+}
+
 static inline int getUsbAltSettings(usb_patch_info *patch_entry, unsigned short *offset)//(patch_info *patch_entry, unsigned short *offset, int max_group_cnt)
 {
     int n = 0;
     if(patch_entry)
         offset[n++] = patch_entry->mac_offset;
+    else
+      return n;
 /*
 //sample code, add special settings
 
     offset[n++] = 0x15B;
 */
+    if(extra_extry)
+        usb_parse_extra_config(EXTRA_CONFIG_FILE, patch_entry, offset, &n);
+
     return n;
 }
 
@@ -161,9 +306,28 @@ static inline int getUsbAltSettingVal(usb_patch_info *patch_entry, unsigned shor
 {
     int res = 0;
 
-    switch(offset)
+    int i = 0;
+    struct rtk_bt_vendor_config_entry *ptr = extra_extry;
+
+    while(ptr->offset)
+    {
+        if(ptr->offset == offset)
+        {
+            if(offset != patch_entry->mac_offset)
+            {
+                memcpy(val, ptr->entry_data, ptr->entry_len);
+                res = ptr->entry_len;
+                ALOGI("Get Extra offset:%04x, val:", offset);
+                for(i = 0; i < ptr->entry_len; i++)
+                    ALOGI("%02x", ptr->entry_data[i]);
+            }
+            break;
+        }
+        ptr = (struct rtk_bt_vendor_config_entry *)((uint8_t *)ptr + ptr->entry_len + sizeof(struct rtk_bt_vendor_config_entry));
+    }
+
+/*    switch(offset)
     {
-/*
 //sample code, add special settings
         case 0x15B:
             val[0] = 0x0B;
@@ -172,11 +336,12 @@ static inline int getUsbAltSettingVal(usb_patch_info *patch_entry, unsigned shor
             val[3] = 0x0B;
             res = 4;
             break;
-*/
+
         default:
             res = 0;
             break;
     }
+*/
     if((patch_entry)&&(offset == patch_entry->mac_offset)&&(res == 0))
     {
         if(getmacaddr(val) == 0){
@@ -196,10 +361,17 @@ static void rtk_usb_update_altsettings(usb_patch_info *patch_entry, unsigned cha
     struct rtk_bt_vendor_config_entry* entry = config->entry;
     size_t config_len = *config_len_ptr;
     unsigned int  i = 0;
-       int count = 0,temp = 0, j;
+    int count = 0,temp = 0, j;
+
+    if((extra_extry = (struct rtk_bt_vendor_config_entry *)malloc(MAX_ALT_CONFIG_SIZE)) == NULL)
+    {
+        ALOGE("malloc buffer for extra_extry failed");
+    }
+    else
+        memset(extra_extry, 0, MAX_ALT_CONFIG_SIZE);
 
     ALOGI("ORG Config len=%08zx:\n", config_len);
-    for(i=0;i<=config_len;i+=0x10)
+    for(i = 0; i <= config_len; i+= 0x10)
     {
         ALOGI("%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i, \
             config_buf_ptr[i], config_buf_ptr[i+1], config_buf_ptr[i+2], config_buf_ptr[i+3], config_buf_ptr[i+4], config_buf_ptr[i+5], config_buf_ptr[i+6], config_buf_ptr[i+7], \
@@ -224,12 +396,27 @@ static void rtk_usb_update_altsettings(usb_patch_info *patch_entry, unsigned cha
         return;
     }
 
-    for (i=0; i<data_len;)
+    for (i = 0; i < data_len;)
     {
         for(j = 0; j < count;j++)
         {
-            if(le16_to_cpu(entry->offset) == offset[j])
-                offset[j] = 0;
+            if(le16_to_cpu(entry->offset) == offset[j]) {
+                if(offset[j] == patch_entry->mac_offset)
+                    offset[j] = 0;
+                else
+                {
+                    struct rtk_bt_vendor_config_entry *t = extra_extry;
+                    while(t->offset) {
+                        if(t->offset == le16_to_cpu(entry->offset))
+                        {
+                            if(t->entry_len == entry->entry_len)
+                                offset[j] = 0;
+                            break;
+                        }
+                        t = (struct rtk_bt_vendor_config_entry *)((uint8_t *)t + t->entry_len + sizeof(struct rtk_bt_vendor_config_entry));
+                    }
+                }
+            }
         }
         if(getUsbAltSettingVal(patch_entry, le16_to_cpu(entry->offset), val) == entry->entry_len){
             ALOGI("rtk_update_altsettings: replace %04x[%02x]", le16_to_cpu(entry->offset), entry->entry_len);
@@ -239,6 +426,7 @@ static void rtk_usb_update_altsettings(usb_patch_info *patch_entry, unsigned cha
         i += temp;
         entry = (struct rtk_bt_vendor_config_entry*)((uint8_t*)entry + temp);
     }
+
     for(j = 0; j < count;j++){
         if(offset[j] == 0)
             continue;
@@ -253,10 +441,17 @@ static void rtk_usb_update_altsettings(usb_patch_info *patch_entry, unsigned cha
         entry = (struct rtk_bt_vendor_config_entry*)((uint8_t*)entry + temp);
     }
     config->data_len = cpu_to_le16(i);
-    *config_len_ptr = i+sizeof(struct rtk_bt_vendor_config);
+    *config_len_ptr = i + sizeof(struct rtk_bt_vendor_config);
+
+    if(extra_extry)
+    {
+        free(extra_extry);
+        extra_extry = NULL;
+        extra_entry_inx = NULL;
+    }
 
     ALOGI("NEW Config len=%08zx:\n", *config_len_ptr);
-    for(i=0;i<=(*config_len_ptr);i+=0x10)
+    for(i = 0; i<= (*config_len_ptr); i+= 0x10)
     {
         ALOGI("%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i, \
             config_buf_ptr[i], config_buf_ptr[i+1], config_buf_ptr[i+2], config_buf_ptr[i+3], config_buf_ptr[i+4], config_buf_ptr[i+5], config_buf_ptr[i+6], config_buf_ptr[i+7], \
@@ -276,7 +471,7 @@ static void rtk_usb_parse_config_file(unsigned char** config_buf, size_t* filele
     //uint32_t config_has_bdaddr = 0;
     uint8_t *p;
 
-       ALOGD("bt_addr = %x", bt_addr[0]);
+    ALOGD("bt_addr = %x", bt_addr[0]);
     if (le32_to_cpu(config->signature) != RTK_VENDOR_CONFIG_MAGIC)
     {
         ALOGE("config signature magic number(0x%x) is not set to RTK_VENDOR_CONFIG_MAGIC", config->signature);
@@ -290,7 +485,7 @@ static void rtk_usb_parse_config_file(unsigned char** config_buf, size_t* filele
     }
 
     hw_cfg_cb.heartbeat = 0;
-    for (i=0; i<config_len;)
+    for (i = 0; i < config_len;)
     {
         switch(le16_to_cpu(entry->offset))
         {
@@ -311,7 +506,7 @@ static void rtk_usb_parse_config_file(unsigned char** config_buf, size_t* filele
             }
             case 0x01be:
             {
-                if(mac_offset == CONFIG_MAC_OFFSET_GEN_3PLUS)
+                if(mac_offset == CONFIG_MAC_OFFSET_GEN_3PLUS || mac_offset == CONFIG_MAC_OFFSET_GEN_4PLUS)
                 {
                     p = (uint8_t *)entry->entry_data;
                     STREAM_TO_UINT8(heartbeat_buf, p);
@@ -351,27 +546,27 @@ static uint32_t rtk_usb_get_bt_config(unsigned char** config_buf,
     if (stat(bt_config_file_name, &st) < 0)
     {
         ALOGE("can't access bt config file:%s, errno:%d\n", bt_config_file_name, errno);
-        return -1;
+        return 0;
     }
 
     filelen = st.st_size;
     if(filelen > MAX_ORG_CONFIG_SIZE)
     {
         ALOGE("bt config file is too large(>0x%04x)", MAX_ORG_CONFIG_SIZE);
-        return -1;
+        return 0;
     }
 
     if ((fd = open(bt_config_file_name, O_RDONLY)) < 0)
     {
         ALOGE("Can't open bt config file");
-        return -1;
+        return 0;
     }
 
-    if ((*config_buf = malloc(MAX_ORG_CONFIG_SIZE+MAX_ALT_CONFIG_SIZE)) == NULL)
+    if ((*config_buf = malloc(MAX_ORG_CONFIG_SIZE + MAX_ALT_CONFIG_SIZE)) == NULL)
     {
         ALOGE("malloc buffer for config file fail(0x%zx)\n", filelen);
         close(fd);
-        return -1;
+        return 0;
     }
 
     if (read(fd, *config_buf, filelen) < (ssize_t)filelen)
@@ -379,7 +574,7 @@ static uint32_t rtk_usb_get_bt_config(unsigned char** config_buf,
         ALOGE("Can't load bt config file");
         free(*config_buf);
         close(fd);
-        return -1;
+        return 0;
     }
 
     rtk_usb_parse_config_file(config_buf, &filelen, vnd_local_bd_addr, mac_offset);
@@ -620,7 +815,7 @@ void hw_usb_config_cback(void *p_mem)
             }
             case HW_CFG_READ_LOCAL_VER:
             {
-                if (status == 0)
+                if (status == 0 && p_evt_buf)
                 {
                     p = ((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OP1001_HCI_VERSION_OFFSET);
                     STREAM_TO_UINT16(hw_cfg_cb.hci_version, p);
@@ -628,7 +823,7 @@ void hw_usb_config_cback(void *p_mem)
                     STREAM_TO_UINT16(hw_cfg_cb.hci_revision, p);
                     p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OP1001_LMP_SUBVERSION_OFFSET;
                     STREAM_TO_UINT16(hw_cfg_cb.lmp_subversion, p);
-                    
+
                     prtk_usb_patch_file_info = rtk_usb_get_fw_table_entry(hw_cfg_cb.vid, hw_cfg_cb.pid);
                     if((prtk_usb_patch_file_info == NULL) || (prtk_usb_patch_file_info->lmp_sub_default == 0))
                     {
@@ -641,7 +836,8 @@ void hw_usb_config_cback(void *p_mem)
                     rtk_usb_get_fw_version(&hw_cfg_cb);
 
                     hw_cfg_cb.lmp_subversion_default = prtk_usb_patch_file_info->lmp_sub_default;
-                    BTVNDDBG("lmp_subversion = 0x%x hw_cfg_cb.hci_version = 0x%x hw_cfg_cb.hci_revision = 0x%x, hw_cfg_cb.lmp_sub_current = 0x%x", hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision, hw_cfg_cb.lmp_sub_current);
+                    BTVNDDBG("lmp_subversion = 0x%x hw_cfg_cb.hci_version = 0x%x hw_cfg_cb.hci_revision = 0x%x, hw_cfg_cb.lmp_sub_current = 0x%x",
+                        hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision, hw_cfg_cb.lmp_sub_current);
 
                     if(prtk_usb_patch_file_info->lmp_sub_default == hw_cfg_cb.lmp_subversion)
                     {
@@ -663,6 +859,7 @@ void hw_usb_config_cback(void *p_mem)
                     else
                     {
                         BTVNDDBG("%s: Warm BT controller startup with same lmp", __func__);
+                        userial_vendor_usb_ioctl(DWFW_CMPLT, &hw_cfg_cb.lmp_sub_current);
                         free(hw_cfg_cb.total_buf);
                         hw_cfg_cb.total_len = 0;
 
@@ -672,7 +869,7 @@ void hw_usb_config_cback(void *p_mem)
                         hw_cfg_cb.state = 0;
                         is_proceeding = TRUE;
                     }
-                    
+
  /*                   if(hw_cfg_cb.lmp_subversion == LMPSUBVERSION_8723a)
                     {
                         hw_cfg_cb.state = HW_CFG_START;
@@ -688,6 +885,9 @@ void hw_usb_config_cback(void *p_mem)
                         is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_READ_ROM_VERSION, p_buf, hw_usb_config_cback);
                     }*/
                 }
+                else {
+                  ALOGE("status = %d, or p_evt_buf is NULL", status);
+                }
                 break;
             }
 RESET_HW_CONTROLLER:
@@ -708,7 +908,7 @@ RESET_HW_CONTROLLER:
             }
             case HW_CFG_READ_ECO_VER:
             {
-                if(status == 0)
+                if(status == 0 && p_evt_buf)
                 {
                     hw_cfg_cb.eversion = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPFC6D_EVERSION_OFFSET);
                     BTVNDDBG("hw_usb_config_cback chip_id of the IC:%d", hw_cfg_cb.eversion+1);
@@ -741,18 +941,19 @@ CFG_USB_START:
                 }
                 hw_cfg_cb.max_patch_size = prtk_usb_patch_file_info->max_patch_size;
                 hw_cfg_cb.config_len = rtk_usb_get_bt_config(&hw_cfg_cb.config_buf, prtk_usb_patch_file_info->config_name, prtk_usb_patch_file_info->mac_offset);
-                if (hw_cfg_cb.config_len < 0)
+                if (hw_cfg_cb.config_len)
                 {
-                    ALOGE("Get Config file fail, just use efuse settings");
-                    hw_cfg_cb.config_len = 0;
+                    ALOGE("update altsettings");
+                    rtk_usb_update_altsettings(prtk_usb_patch_file_info, hw_cfg_cb.config_buf, &(hw_cfg_cb.config_len));
                 }
-                rtk_usb_update_altsettings(prtk_usb_patch_file_info, hw_cfg_cb.config_buf, &(hw_cfg_cb.config_len));
 
                 hw_cfg_cb.fw_len = rtk_get_bt_firmware(&hw_cfg_cb.fw_buf, prtk_usb_patch_file_info->patch_name);
                 if (hw_cfg_cb.fw_len < 0)
                 {
                     ALOGE("Get BT firmware fail");
                     hw_cfg_cb.fw_len = 0;
+                    is_proceeding = FALSE;
+                    break;
                 }
                 else{
                     //hw_cfg_cb.project_id_mask = prtk_usb_patch_file_info->project_id_mask;
@@ -799,9 +1000,10 @@ DOWNLOAD_USB_FW:
                     BTVNDDBG("bt vendor lib: HW_CFG_DL_FW_PATCH status:%i, iIndexRx:%i", status, iIndexRx);
                     hw_cfg_cb.patch_frag_idx++;
 
-                    if(iIndexRx&0x80)
+                    if(iIndexRx & 0x80)
                     {
                         BTVNDDBG("vendor lib fwcfg completed");
+                        userial_vendor_usb_ioctl(DWFW_CMPLT, &hw_cfg_cb.lmp_sub_current);
                         free(hw_cfg_cb.total_buf);
                         hw_cfg_cb.total_len = 0;
 
@@ -851,6 +1053,7 @@ DOWNLOAD_USB_FW:
             if (p_buf != NULL)
                 bt_vendor_cbacks->dealloc(p_buf);
 
+            userial_vendor_usb_ioctl(DWFW_CMPLT, &hw_cfg_cb.lmp_sub_current);
             bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
         }
 
@@ -886,11 +1089,12 @@ DOWNLOAD_USB_FW:
 *******************************************************************************/
 void hw_usb_config_start(char transtype, uint32_t usb_id)
 {
+    RTK_UNUSED(transtype);
     memset(&hw_cfg_cb, 0, sizeof(bt_hw_cfg_cb_t));
     hw_cfg_cb.dl_fw_flag = 1;
     hw_cfg_cb.chip_type = CHIPTYPE_NONE;
     hw_cfg_cb.pid = usb_id & 0x0000ffff;
-    hw_cfg_cb.vid = (usb_id>>16) & 0x0000ffff;
+    hw_cfg_cb.vid = (usb_id >> 16) & 0x0000ffff;
     BTVNDDBG("RTKBT_RELEASE_NAME: %s",RTKBT_RELEASE_NAME);
     BTVNDDBG("\nRealtek libbt-vendor_usb Version %s \n",RTK_VERSION);
     HC_BT_HDR  *p_buf = NULL;
index 2d838bd2d4628de807604cf7900662123c7ab85a..0aff445e9bd95e7c8f71587b85c90f8011b58822 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2016 Realtek Corporation.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 #include <fcntl.h>
 #include <termios.h>
 #include <errno.h>
-#include <pthread.h>
 #include <signal.h>
 #include <time.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
 #include <sys/prctl.h>
 #include <sys/syscall.h>
 #include <arpa/inet.h>
 #include <string.h>
 #include <linux/wait.h>
-#include <unistd.h>
 
 #include "hci_h5_int.h"
 #include "bt_skbuff.h"
@@ -274,6 +275,7 @@ static pthread_mutex_t h5_wakeup_mutex = PTHREAD_MUTEX_INITIALIZER;
 /* Num of allowed outstanding HCI CMD packets */
 volatile int num_hci_cmd_pkts = 1;
 extern unsigned int rtkbt_h5logfilter;
+extern void userial_recv_rawdata_hook(unsigned char *buffer, unsigned int total_length);
 
 /******************************************************************************
 **  Static variables
@@ -395,24 +397,26 @@ static void H5LogMsg(const char *fmt_str, ...)
         return;
      }
 }
-/*
-static void H5LogMsgVerbose(const char *fmt_str, ...)
-{
-#if H5_LOG_VERBOSE
-       static char buffer[H5_LOG_BUF_SIZE];
-    va_list ap;
-    va_start(ap, fmt_str);
-    vsnprintf(&buffer[0], H5_LOG_MAX_SIZE, fmt_str, ap);
-    va_end(ap);
-
-    LOGI0("H5: ", buffer);
-#else
-       va_list ap;
-       va_start(ap, fmt_str);
-    va_end(ap);
-    return;
-#endif
-}*/
+
+static void rtkbt_h5_send_hw_error()
+{
+    unsigned char p_buf[100];
+    const char *str = "host stack: h5 send error";
+    int length = strlen(str) + 1 + 4;
+    p_buf[0] = HCIT_TYPE_EVENT;//event
+    p_buf[1] = HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT;//firmwre event log
+    p_buf[2] = strlen(str) + 2;//len
+    p_buf[3] = 0x01;// host log opcode
+    strcpy((char *)&p_buf[4], str);
+    userial_recv_rawdata_hook(p_buf,length);
+
+    length = 4;
+    p_buf[0] = HCIT_TYPE_EVENT;//event
+    p_buf[1] = HCI_HARDWARE_ERROR_EVT;//hardware error
+    p_buf[2] = 0x01;//len
+    p_buf[3] = 0xfb;//h5 error code
+    userial_recv_rawdata_hook(p_buf,length);
+}
 
 // reverse bit
 static __inline uint8_t bit_rev8(uint8_t byte)
@@ -798,6 +802,7 @@ static sk_buff * h5_prepare_pkt(tHCI_H5_CB *h5, uint8_t *data, signed long len,
     case H5_ACK_PKT:
     case H5_VDRSPEC_PKT:
     case H5_LINK_CTL_PKT:
+    case HCI_SCODATA_PKT:
     rel = H5_UNRELIABLE_PKT;// unreliable
     break;
     default:
@@ -1204,6 +1209,10 @@ static void rtk_notify_hw_h5_init_result(uint8_t status)
     sk_buff     *rx_skb;
     rx_skb = skb_alloc_and_init(HCI_EVENT_PKT, sync_event, sizeof(sync_event));
 
+    if(!rx_skb) {
+        ALOGE("%s, rx_skb alloc fail!", __func__);
+        return;
+    }
     pthread_mutex_lock(&rtk_h5.data_mutex);
     skb_queue_tail(rtk_h5.recv_data, rx_skb);
     pthread_cond_signal(&rtk_h5.data_cond);
@@ -1317,6 +1326,7 @@ int h5_enqueue(IN sk_buff *skb)
     case H5_LINK_CTL_PKT:
     case H5_ACK_PKT:
     case H5_VDRSPEC_PKT:
+    case HCI_SCODATA_PKT:
         skb_queue_tail(rtk_h5.unrel, skb);/* 3-wire LinkEstablishment*/
         break;
     default:
@@ -1441,7 +1451,8 @@ void h5_process_ctl_pkts(void)
         if (!memcmp(skb_get_data(skb), h5sync, 0x2)) {
 
             H5LogMsg("H5: <<<---recv sync req in H5_ACTIVE");
-            kill(getpid(), SIGKILL);
+            rtkbt_h5_send_hw_error();
+            //kill(getpid(), SIGKILL);
             hci_h5_send_sync_resp();
             H5LogMsg("H5 : H5_ACTIVE transit to H5_UNINITIALIZED");
             rtk_h5.link_estab_state = H5_UNINITIALIZED;
@@ -1478,95 +1489,7 @@ uint8_t isRtkInternalCommand(uint16_t opcode)
 
 }
 
-
-/*******************************************************************************
-**
-** Function         internal_event_intercept_h5
-**
-** Description      This function is called to parse received HCI event and
-**                  - update the Num_HCI_Command_Packets
-**                  - intercept the event if it is the result of an early
-**                    issued internal command.
-**
-** Returns          TRUE : if the event had been intercepted for internal process
-**                  FALSE : send this event to core stack
-**
-*******************************************************************************/
-uint8_t internal_event_intercept_h5(void)
-{
-    bool h5_int_command = 0;//if it the H5 int command like H5 vendor cmd or Coex cmd h5_int_command=1;
-    tHCI_H5_CB *p_cb = &rtk_h5;
-    sk_buff * skb = rtk_h5.rx_skb;
-    //uint8_t *ph5_payload = NULL;
-    //ph5_payload = (uint8_t *)(p_cb->p_rcv_msg + 1);
-
-    //process fw change baudrate and patch download
-    uint8_t     *p;
-    uint8_t     event_code;
-    uint16_t    opcode, len;
-    p = (uint8_t *)(p_cb->p_rcv_msg + 1);
-
-    event_code = *p++;
-    len = *p++;
-    H5LogMsg("event_code(0x%x), len = %d", event_code, len);
-    if (event_code == HCI_COMMAND_COMPLETE_EVT)
-    {
-        num_hci_cmd_pkts = *p++;
-        STREAM_TO_UINT16(opcode, p);
-        H5LogMsg("event_code(0x%x)  opcode (0x%x) p_cb->int_cmd_rsp_pending %d", event_code,opcode,p_cb->int_cmd_rsp_pending);
-
-        if (p_cb->int_cmd_rsp_pending > 0)
-        {
-            H5LogMsg("CommandCompleteEvent for command (0x%04X)", opcode);
-            if (opcode == p_cb->int_cmd[p_cb->int_cmd_rd_idx].opcode)
-            {
-                //ONLY HANDLE H5 INIT CMD COMMAND COMPLETE EVT
-                h5_int_command = 1;
-                if(opcode == HCI_VSC_UPDATE_BAUDRATE)
-                {
-                    //need to set a timer, add wait for retransfer packet from controller.
-                    //if there is no packet rx from controller, we can assure baudrate change success.
-                    H5LogMsg("CommandCompleteEvent for command 2 h5_start_wait_controller_baudrate_ready_timer (0x%04X)", opcode);
-                    h5_start_wait_controller_baudrate_ready_timer();
-                }
-                else
-                {
-
-                    if (p_cb->int_cmd[p_cb->int_cmd_rd_idx].cback != NULL)
-                    {
-                        H5LogMsg("CommandCompleteEvent for command (0x%04X) p_cb->int_cmd[p_cb->int_cmd_rd_idx].cback(p_cb->p_rcv_msg)", opcode);
-                        p_cb->int_cmd[p_cb->int_cmd_rd_idx].cback(p_cb->p_rcv_msg);
-                    }
-                    else
-                    {
-                        H5LogMsg("CommandCompleteEvent for command Missing cback function buffer_allocator->free(p_cb->p_rcv_msg) (0x%04X)", opcode);
-                        free(p_cb->p_rcv_msg);
-                    }
-                }
-
-                p_cb->int_cmd_rd_idx = ((p_cb->int_cmd_rd_idx+1) & INT_CMD_PKT_IDX_MASK);
-                p_cb->int_cmd_rsp_pending--;
-            }
-        }
-        else {
-            if(opcode == HCI_VSC_UPDATE_BAUDRATE)
-            {
-                h5_int_command |= 0x80;
-                rtk_h5.internal_skb = skb;
-                //need to set a timer, add wait for retransfer packet from controller.
-                //if there is no packet rx from controller, we can assure baudrate change success.
-                H5LogMsg("CommandCompleteEvent for command 2 h5_start_wait_controller_baudrate_ready_timer (0x%04X)", opcode);
-                h5_start_wait_controller_baudrate_ready_timer();
-            }
-        }
-    }
-
-    return h5_int_command;
-
-}
-
-
-/**
+/*****************************************************************************
 * Check if it's a hci frame, if it is, complete it with response or parse the cmd complete event
 *
 * @param skb socket buffer
@@ -1594,6 +1517,24 @@ static void send_fake_le_pack(uint8_t *pack,uint32_t len){
        pthread_cond_signal(&rtk_h5.data_cond);
        pthread_mutex_unlock(&rtk_h5.data_mutex);
 }
+
+
+static uint16_t encHandle = 0x0000;
+
+static void send_fake_enc_keysize(uint16_t handle,uint8_t keysize){
+       sk_buff         *rx_skb;
+       uint8_t pack[9]={0x0e, 0x07, 0x01, 0x08, 0x14, 0x00, 0x03, 0x00, 0x10};
+       pack[6]=(uint8_t)handle;pack[7]=(uint8_t)(handle>>8);
+       pack[8] = keysize;
+       rx_skb = skb_alloc_and_init(HCI_EVENT_PKT, pack, 9);
+
+       pthread_mutex_lock(&rtk_h5.data_mutex);
+       skb_queue_tail(rtk_h5.recv_data, rx_skb);
+       pthread_cond_signal(&rtk_h5.data_cond);
+       pthread_mutex_unlock(&rtk_h5.data_mutex);
+}
+
+
 #endif
 static uint8_t hci_recv_frame(sk_buff *skb, uint8_t pkt_type)
 {
@@ -1645,12 +1586,21 @@ static uint8_t hci_recv_frame(sk_buff *skb, uint8_t pkt_type)
                 p[4]=0x05;
                 p[7]=0x05;
             }
+            if(event_code == HCI_COMMAND_COMPLETE_EVT
+               && len==0x44 && p[0]==0x02 && p[1]==0x02 && p[2]==0x10){
+                p[24]|=0x10;
+            }
             if(event_code == HCI_COMMAND_COMPLETE_EVT && len==0x0e && p[0]==0x02 && p[1]==0x04 && p[2]==0x10 ){
                 if(p[4]==0x00)
                     p[10]|=0x40;
                 if(p[4]==0x01)
                     p[6]|=0x02;
             }
+            if(event_code == HCI_COMMAND_COMPLETE_EVT && len==0x04 &&  p[1]==0x08 &&p[2]==0x14){
+                skb_free(&skb);
+                intercepted = 1;
+                send_fake_enc_keysize(encHandle,0x10);
+            }
             if(event_code == HCI_COMMAND_STATUS_EVT && len==0x04 && p[0]==0x01 && p[1]==0x02 && p[2]==0x0f &&p[3]==0x20){
                 skb_free(&skb);
                 intercepted = 1;
@@ -2016,14 +1966,9 @@ static bool h5_recv(tHCI_H5_CB *h5, uint8_t *data, int count)
 /******************************************************************************
 **  Static functions
 ******************************************************************************/
-static void h5_data_ready_cb_signal_exit()
-{
-    pthread_mutex_lock(&rtk_h5.data_mutex);
-    pthread_cond_signal(&rtk_h5.data_cond);
-    pthread_mutex_unlock(&rtk_h5.data_mutex);
-}
-static void data_ready_cb_thread()
+static void data_ready_cb_thread(void *arg)
 {
+    RTK_UNUSED(arg);
     sk_buff *skb;
     uint8_t pkt_type = 0;
     unsigned int total_length = 0;
@@ -2035,33 +1980,32 @@ static void data_ready_cb_thread()
     while (h5_data_ready_running)
     {
         pthread_mutex_lock(&rtk_h5.data_mutex);
-        while ((skb_queue_get_length(rtk_h5.recv_data) == 0) && h5_retransfer_running)
+        while (h5_data_ready_running && (skb_queue_get_length(rtk_h5.recv_data) == 0))
         {
             pthread_cond_wait(&rtk_h5.data_cond, &rtk_h5.data_mutex);
         }
         pthread_mutex_unlock(&rtk_h5.data_mutex);
 
-        if(!h5_retransfer_running)
-            break;
-
-        if((skb = skb_dequeue_head(rtk_h5.recv_data)) != NULL) {
+        if(h5_data_ready_running && (skb = skb_dequeue_head(rtk_h5.recv_data)) != NULL) {
             rtk_h5.data_skb = skb;
         }
+        else
+          continue;
 
         pkt_type = skb_get_pkt_type(rtk_h5.data_skb);
         total_length = skb_get_data_length(rtk_h5.data_skb);
         h5_int_hal_callbacks->h5_data_ready_cb(pkt_type, total_length);
     }
 
-    ALOGE("data_ready_cb_thread exiting");
+    H5LogMsg("data_ready_cb_thread exiting");
     pthread_exit(NULL);
 
 }
 
-static void data_retransfer_thread()//(void *arg)
+static void data_retransfer_thread(void *arg)
 {
+    RTK_UNUSED(arg);
     uint16_t events;
-    //uint32_t i = 0;
     uint16_t data_retrans_counts = DATA_RETRANS_COUNT;
 
     H5LogMsg("data_retransfer_thread started");
@@ -2090,6 +2034,7 @@ static void data_retransfer_thread()//(void *arg)
 
             if(rtk_h5.data_retrans_count < data_retrans_counts)
             {
+                pthread_mutex_lock(&h5_wakeup_mutex);
                 while ((skb = skb_dequeue_tail(rtk_h5.unack)) != NULL)
                 {
 #if H5_TRACE_DATA_ENABLE
@@ -2105,6 +2050,7 @@ static void data_retransfer_thread()//(void *arg)
                     skb_queue_head(rtk_h5.rel, skb);
 
                 }
+                pthread_mutex_unlock(&h5_wakeup_mutex);
                 rtk_h5.data_retrans_count++;
                 h5_wake_up();
 
@@ -2113,7 +2059,8 @@ static void data_retransfer_thread()//(void *arg)
             {
             //do not put packet to rel queue, and do not send
             //Kill bluetooth
-            kill(getpid(), SIGKILL);
+            rtkbt_h5_send_hw_error();
+            //kill(getpid(), SIGKILL);
             }
 
         }
@@ -2125,7 +2072,7 @@ static void data_retransfer_thread()//(void *arg)
 
 }
 
-    ALOGE("data_retransfer_thread exiting");
+    H5LogMsg("data_retransfer_thread exiting");
     pthread_exit(NULL);
 
 }
@@ -2280,12 +2227,11 @@ void hci_h5_int_init(hci_h5_callbacks_t* h5_callbacks)
 *******************************************************************************/
 void hci_h5_cleanup(void)
 {
-    ALOGE("hci_h5_cleanup");
+    H5LogMsg("hci_h5_cleanup");
     //uint8_t try_cnt=10;
     int result;
 
     rtk_h5.cleanuping = 1;
-    ms_delay(200);
 
 
     //btsnoop_cleanup();
@@ -2296,27 +2242,29 @@ void hci_h5_cleanup(void)
     h5_free_wait_controller_baudrate_ready_timer();
     h5_free_hw_init_ready_timer();
 
+    if(h5_data_ready_running) {
+        h5_data_ready_running = 0;
+        pthread_mutex_lock(&rtk_h5.data_mutex);
+        pthread_cond_signal(&rtk_h5.data_cond);
+        pthread_mutex_unlock(&rtk_h5.data_mutex);
+        if ((result = pthread_join(rtk_h5.thread_data_ready_cb, NULL)) < 0)
+            ALOGE("H5 thread_data_ready_cb pthread_join() FAILED result:%d", result);
+    }
 
     if (h5_retransfer_running)
     {
         h5_retransfer_running = 0;
-        h5_data_ready_cb_signal_exit();
-        if ((result = pthread_join(rtk_h5.thread_data_ready_cb, NULL)) < 0)
-            ALOGE("H5 thread_data_ready_cb pthread_join() FAILED result:%d", result);
-               
         h5_retransfer_signal_event(H5_EVENT_EXIT);
         if ((result = pthread_join(rtk_h5.thread_data_retrans, NULL)) < 0)
         ALOGE("H5 pthread_join() FAILED result:%d", result);
     }
 
-    ms_delay(200);
-
-
-    pthread_mutex_destroy(&rtk_h5.data_mutex);
-    pthread_cond_destroy(&rtk_h5.data_cond);
+    //ms_delay(200);
 
     pthread_mutex_destroy(&rtk_h5.mutex);
+    pthread_mutex_destroy(&rtk_h5.data_mutex);
     pthread_cond_destroy(&rtk_h5.cond);
+    pthread_cond_destroy(&rtk_h5.data_cond);
 
     RtbQueueFree(rtk_h5.unack);
     RtbQueueFree(rtk_h5.rel);
@@ -2326,28 +2274,6 @@ void hci_h5_cleanup(void)
     rtk_h5.internal_skb = NULL;
 }
 
-
-/*******************************************************************************
-**
-** Function        hci_h5_parse_msg
-**
-** Description     Construct HCI EVENT/ACL packets and send them to stack once
-**                 complete packet has been received.
-**
-** Returns         Number of need to be red bytes
-**
-*******************************************************************************/
-uint16_t  hci_h5_parse_msg(uint8_t *byte, uint16_t count)
-{
-    //uint16_t bytes_needed = 0;
-    uint8_t     h5_byte;
-    h5_byte  = *byte;
-    //H5LogMsg("hci_h5_receive_msg byte:%d",h5_byte);
-    h5_recv(&rtk_h5, &h5_byte, count);
-    return 1;
-}
-
-
 /*******************************************************************************
 **
 ** Function        hci_h5_receive_msg
@@ -2408,6 +2334,11 @@ uint16_t hci_h5_send_cmd(serial_data_type_t type, uint8_t *data, uint16_t length
     sk_buff * skb = NULL;
     uint16_t bytes_to_send, opcode;
 
+    if(type != DATA_TYPE_COMMAND) {
+        ALOGE("%s Receive wrong type type : %d", __func__, type);
+        return -1;
+    }
+
     skb = skb_alloc_and_init(type, data, length);
     if(!skb) {
         ALOGE("send cmd skb_alloc_and_init fail!");
@@ -2431,6 +2362,11 @@ uint16_t hci_h5_send_cmd(serial_data_type_t type, uint8_t *data, uint16_t length
     }
     if(opcode == HCI_WRITE_LOOPBACK_MODE)
         loopbackmode = 0x01;
+       #if ENABLE_BLE_8703
+               if(opcode == 0x1408)//enc key size
+                        encHandle = (uint16_t)data[1] + ((uint16_t)data[2] << 8);
+        
+       #endif
 
     bytes_to_send = h5_wake_up();
     return length;
@@ -2611,7 +2547,8 @@ static timer_t OsAllocateTimer(tTIMER_HANDLE_CBACK timer_callback)
     return OsStartTimer(timerid, 0, 0);
  }
 
-static void h5_retransfer_timeout_handler(){//(union sigval sigev_value) {
+static void h5_retransfer_timeout_handler(union sigval sigev_value) {
+    RTK_UNUSED(sigev_value);
     H5LogMsg("h5_retransfer_timeout_handler");
     if(rtk_h5.cleanuping)
     {
@@ -2621,7 +2558,8 @@ static void h5_retransfer_timeout_handler(){//(union sigval sigev_value) {
     h5_retransfer_signal_event(H5_EVENT_RX);
 }
 
-static void h5_sync_retrans_timeout_handler(){//(union sigval sigev_value) {
+static void h5_sync_retrans_timeout_handler(union sigval sigev_value) {
+    RTK_UNUSED(sigev_value);
     H5LogMsg("h5_sync_retrans_timeout_handler");
     if(rtk_h5.cleanuping)
     {
@@ -2643,7 +2581,8 @@ static void h5_sync_retrans_timeout_handler(){//(union sigval sigev_value) {
 
 }
 
-static void h5_conf_retrans_timeout_handler(){//(union sigval sigev_value) {
+static void h5_conf_retrans_timeout_handler(union sigval sigev_value) {
+    RTK_UNUSED(sigev_value);
     H5LogMsg("h5_conf_retrans_timeout_handler");
     if(rtk_h5.cleanuping)
     {
@@ -2667,7 +2606,8 @@ static void h5_conf_retrans_timeout_handler(){//(union sigval sigev_value) {
 
 }
 
-static void h5_wait_controller_baudrate_ready_timeout_handler(){//(union sigval sigev_value) {
+static void h5_wait_controller_baudrate_ready_timeout_handler(union sigval sigev_value) {
+    RTK_UNUSED(sigev_value);
     H5LogMsg("h5_wait_ct_baundrate_ready_timeout_handler");
     if(rtk_h5.cleanuping)
     {
@@ -2685,7 +2625,8 @@ static void h5_wait_controller_baudrate_ready_timeout_handler(){//(union sigval
     rtk_h5.internal_skb = NULL;
 }
 
-static void h5_hw_init_ready_timeout_handler(){//(union sigval sigev_value) {
+static void h5_hw_init_ready_timeout_handler(union sigval sigev_value) {
+    RTK_UNUSED(sigev_value);
     H5LogMsg("h5_hw_init_ready_timeout_handler");
     if(rtk_h5.cleanuping)
     {
index 1f8437e92c2fae547a6f271f9cd9381f96492fc3..1f9f18fc57d97fda6c1d22422f50263ad27d4cc7 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
  ******************************************************************************/
 
 #define LOG_TAG "bt_service"
-#define RTKBT_RELEASE_NAME     "Test"
+#define RTKBT_RELEASE_NAME "20190520_BT_ANDROID_9.0"
 
 #include <utils/Log.h>
 #include <sys/types.h>
@@ -83,6 +83,7 @@ typedef void (*tTIMER_HANDLE_CBACK)(union sigval sigval_value);
 typedef struct Rtk_Btservice_Info
 {
     int socketfd;
+    int sig_fd[2];
     pthread_t       cmdreadythd;
     pthread_t       epollthd;
     int             current_client_sock;
@@ -127,7 +128,8 @@ typedef struct Rtk_Queue_Data
     void            (*complete_cback)(void *);
 }Rtkqueuedata;
 
-static Rtk_Btservice_Info *rtk_btservice;
+extern void rtk_vendor_cmd_to_fw(uint16_t opcode, uint8_t parameter_len, uint8_t* parameter, tINT_CMD_CBACK p_cback);
+static Rtk_Btservice_Info *rtk_btservice = NULL;
 static void Rtk_Service_Send_Hwerror_Event();
 //extern void userial_recv_rawdata_hook(unsigned char *, unsigned int);
 static timer_t OsAllocateTimer(tTIMER_HANDLE_CBACK timer_callback)
@@ -269,13 +271,12 @@ static int hcicmd_stop_reply_timer()
 static void Rtk_Client_Cmd_Cback(void *p_mem)
 {
     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
-    unsigned char *sendbuf=NULL;
+    unsigned char *sendbuf = NULL;
     int len;
-    //ALOGE("%s p_evt_buf = %x,%x,%x,%x,%x!", __func__,p_evt_buf->event,p_evt_buf->len,p_evt_buf->offset,p_evt_buf->layer_specific,p_evt_buf->data[0]);
-    len=8+p_evt_buf->len;
+
     if(p_evt_buf != NULL)
     {
-        sendbuf = (unsigned char *)malloc(sizeof(char)*len);
+        len = 8 + p_evt_buf->len;
         sendbuf = p_mem;
         if(rtk_btservice->current_client_sock != -1)
         {
@@ -285,18 +286,25 @@ static void Rtk_Client_Cmd_Cback(void *p_mem)
         {
             ALOGE("%s current_client_sock is not exist!", __func__);
         }
-        free(sendbuf);
     }
 }
 
 void Rtk_Service_Vendorcmd_Hook(Rtk_Service_Data *RtkData, int client_sock)
 {
     Rtkqueuedata* rtkqueue_data = NULL;
+    if(!rtk_btservice) {
+        ALOGE("rtkbt service is null");
+        return;
+    }
+
     pthread_mutex_lock(&rtk_btservice->cmdqueue_mutex);
     rtkqueue_data = (Rtkqueuedata *)malloc(sizeof(Rtkqueuedata));
     if (NULL == rtkqueue_data)
     {
         ALOGE("rtkqueue_data: allocate error");
+        if(RtkData->parameter_len > 0) {
+            free(RtkData->parameter);
+        }
         return;
     }
 
@@ -318,15 +326,15 @@ static void Rtk_Service_Cmd_Event_Cback(void *p_mem)
     //ALOGE("%s p_mem = %x,%x,%x,%x,%x,%x!", __func__,a[0],a[1],a[2],a[3],a[4],a[5]);
     if(p_mem != NULL)
     {
-        if(rtk_btservice->current_complete_cback!=NULL)
+        if(rtk_btservice->current_complete_cback != NULL)
         {
-            rtk_btservice->current_complete_cback(p_mem);
+            (*rtk_btservice->current_complete_cback)(p_mem);
         }
         else
         {
             ALOGE("%s current_complete_cback is not exist!", __func__);
         }
-        rtk_btservice->current_complete_cback=NULL;
+        rtk_btservice->current_complete_cback = NULL;
         hcicmd_stop_reply_timer();
         sem_post(&rtk_btservice->cmdsend_sem);
     }
@@ -334,17 +342,17 @@ static void Rtk_Service_Cmd_Event_Cback(void *p_mem)
 
 static void Rtk_Service_Send_Hwerror_Event()
 {
-    unsigned char *p_buf=(unsigned char *)malloc(sizeof(char)*4);
-    int length=4;
-    p_buf[0]=0x04;//event
-    p_buf[1]=0x10;//hardware error
-    p_buf[2]=0x01;//len
-    p_buf[3]=0xfd;//error code
+    unsigned char p_buf[4];
+    int length = 4;
+    p_buf[0] = 0x04;//event
+    p_buf[1] = 0x10;//hardware error
+    p_buf[2] = 0x01;//len
+    p_buf[3] = 0xfd;//rtkbtservice error code
     userial_recv_rawdata_hook(p_buf,length);
-    free(p_buf);
+
 }
 
-static void *cmdready_thread()
+static voidcmdready_thread()
 {
     //Rtkqueuedata* rtk_data;
 
@@ -369,42 +377,18 @@ static void *cmdready_thread()
             pthread_mutex_unlock(&rtk_btservice->cmdqueue_mutex);
 
             if(desc) {
-                HC_BT_HDR  *p_buf = NULL;
-                p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + desc->parameter_len);
-
-                if(NULL == p_buf)
-                {
-                    ALOGE("rtk_vendor_cmd_to_fw: HC_BT_HDR alloc error");
-                    pthread_exit(0);
-                }
-                p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
-                p_buf->offset = 0;
-                p_buf->len = HCI_CMD_PREAMBLE_SIZE + desc->parameter_len;
-                p_buf->layer_specific = 0;
-
-                uint8_t *p = (uint8_t *) (p_buf + 1);
-                UINT16_TO_STREAM(p, desc->opcode);
-                *p++ = desc->parameter_len;
-
                 if(desc->opcode == 0xfc77)
                 {
                     rtk_btservice->autopair_fd = desc->client_sock;
                 }
 
-                if(desc->parameter_len > 0)
-                {
-                    memcpy(p, desc->parameter, desc->parameter_len);
-                }
-                if(desc->opcode != 0xfc94 )
+                if(desc->opcode != 0xfc94)
                     ALOGD("%s, transmit_command Opcode:%x",__func__, desc->opcode);
                 rtk_btservice->current_client_sock = desc->client_sock;
                 rtk_btservice->current_complete_cback = desc->complete_cback;
                 //bt_vendor_cbacks->xmit_cb(desc->opcode, p_buf, desc->complete_cback);
-                if(bt_vendor_cbacks != NULL)
-                {
-                    bt_vendor_cbacks->xmit_cb(desc->opcode, p_buf, Rtk_Service_Cmd_Event_Cback);
-                    hcicmd_start_reply_timer();
-                }
+                rtk_vendor_cmd_to_fw(desc->opcode, desc->parameter_len, desc->parameter, Rtk_Service_Cmd_Event_Cback);
+                hcicmd_start_reply_timer();
                 if(desc->parameter_len > 0)
                     free(desc->parameter);
             }
@@ -417,8 +401,6 @@ static void *cmdready_thread()
 
 static void Getpacket(int client_sock)
 {
-
-    //unsigned char recvbuf[Rtk_Service_Data_SIZE];
     unsigned char type=0;
     unsigned char opcodeh=0;
     unsigned char opcodel=0;
@@ -426,12 +408,10 @@ static void Getpacket(int client_sock)
     unsigned char *parameter = NULL;
     int recvlen=0;
     Rtk_Service_Data *p_buf;
-    //int i;
-
 
-    recvlen = read(client_sock,&type,1);
+    recvlen = read(client_sock, &type, 1);
     ALOGD("%s recvlen=%d,type=%d",__func__,recvlen, type);
-    if(recvlen<=0)
+    if(recvlen <= 0)
     {
         close(client_sock);
         if(client_sock == rtk_btservice->autopair_fd)
@@ -446,32 +426,37 @@ static void Getpacket(int client_sock)
         case RTK_HCICMD:
         {
             recvlen = read(client_sock,&opcodeh,1);
-            if(recvlen<=0)
+            if(recvlen <= 0)
             {
                 ALOGE("read opcode high char error");
                 break;
             }
             recvlen = read(client_sock,&opcodel,1);
-            if(recvlen<=0)
+            if(recvlen <= 0)
             {
                 ALOGE("read opcode low char error");
                 break;
             }
             recvlen = read(client_sock,&parameter_length,1);
-            if(recvlen<=0)
+            if(recvlen <= 0)
             {
                 ALOGE("read parameter_length char error");
                 break;
             }
 
-            if(parameter_length>0)
+            if(parameter_length > 0)
             {
                 parameter = (unsigned char *)malloc(sizeof(char)*parameter_length);
-                recvlen = read(client_sock,parameter,parameter_length);
+                if(!parameter) {
+                    ALOGE("%s parameter alloc fail!", __func__);
+                    return;
+                }
+                recvlen = read(client_sock, parameter, parameter_length);
                 ALOGD("%s parameter_length=%d,recvlen=%d",__func__,parameter_length, recvlen);
-                if(recvlen<=0 || recvlen!=parameter_length)
+                if(recvlen <= 0 || recvlen != parameter_length)
                 {
                     ALOGE("read parameter_length char error recvlen=%d,parameter_length=%d\n",recvlen,parameter_length);
+                    free(parameter);
                     break;
                 }
             }
@@ -479,19 +464,15 @@ static void Getpacket(int client_sock)
             if (NULL == p_buf)
             {
                 ALOGE("p_buf: allocate error");
+                if(parameter)
+                  free(parameter);
                 return;
             }
+
             p_buf->opcode = ((unsigned short)opcodeh)<<8 | opcodel;
             p_buf->parameter = parameter;
             p_buf->parameter_len = parameter_length;
             p_buf->complete_cback = Rtk_Client_Cmd_Cback;
-            //ALOGE("p_buf->parameter_len: %d",p_buf->parameter_len);
-            //ALOGE("p_buf->opcode: %x",p_buf->opcode);
-            //ALOGE("opcodeh: %x,opcodel: %x",opcodeh,opcodel);
-            //for(i=0;i<p_buf->parameter_len;i++)
-            //{
-            //    ALOGE("i=%d,p_buf->parameter: %x",i,p_buf->parameter[i]);
-            //}
             Rtk_Service_Vendorcmd_Hook(p_buf,client_sock);
             free(p_buf);
             break;
@@ -511,7 +492,7 @@ static void Getpacket(int client_sock)
 
 }
 
-void rtk_btservice_internal_event_intercept(uint8_t *p_full_msg,uint8_t *p_msg)
+void rtk_btservice_internal_event_intercept(uint8_t *p_full_msg, uint8_t *p_msg)
 {
     uint8_t *p = p_msg;
     uint8_t event_code = *p++;
@@ -531,18 +512,15 @@ void rtk_btservice_internal_event_intercept(uint8_t *p_full_msg,uint8_t *p_msg)
                 {
 
                     ALOGD("p_evt_buf_len=%d",p_evt_buf->len);
-                    //for(int i=0;i<p_evt_buf->len;i++)
-                      //ALOGE("@jason buf[%d]=0x%x",i,p_evt_buf->data[i]);
-                    //
                     if(rtk_btservice->autopair_fd != -1)
                     {
                         write(rtk_btservice->autopair_fd, p_evt_buf, p_evt_buf->len+8);
                         uint8_t p_bluedroid_len = p_evt_buf->len+1;
-                        uint8_t *p_bluedroid = malloc(p_bluedroid_len);
-                        p_bluedroid[0]=DATA_TYPE_EVENT;
+                        uint8_t p_bluedroid[p_bluedroid_len];
+                        p_bluedroid[0] = DATA_TYPE_EVENT;
                         memcpy((uint8_t *)(p_bluedroid + 1), p_msg, p_evt_buf->len);
-                        p_bluedroid[1]=0x3e;  //event_code
-                        p_bluedroid[3]=0x02;  //subcode
+                        p_bluedroid[1] = 0x3e;  //event_code
+                        p_bluedroid[3] = 0x02;  //subcode
                         userial_recv_rawdata_hook(p_bluedroid, p_bluedroid_len);
                     }
                 }
@@ -552,10 +530,6 @@ void rtk_btservice_internal_event_intercept(uint8_t *p_full_msg,uint8_t *p_msg)
             }
             break;
         }
-        //case HCI_COMMAND_COMPLETE_EVT:
-        //{
-            //rtkservice_handle_cmd_complete_evt();
-        //}
         default:
             break;
     }
@@ -566,7 +540,7 @@ static int socket_accept(socketfd)
 {
     struct sockaddr_un un;
     socklen_t len;
-    int client_sock=0;
+    int client_sock = 0;
     len = sizeof(un);
     struct epoll_event event;
 
@@ -578,10 +552,10 @@ static int socket_accept(socketfd)
     }
     //pthread_create(&connectthread,NULL,(void *)accept_request_thread,&client_sock);
 
-    event.data.fd=client_sock;
-    event.events=EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR;
+    event.data.fd = client_sock;
+    event.events = EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR;
     //list_add(client_sock);
-    if(epoll_ctl(rtk_btservice->epoll_fd,EPOLL_CTL_ADD,client_sock,&event)==-1)
+    if(epoll_ctl(rtk_btservice->epoll_fd, EPOLL_CTL_ADD, client_sock, &event)==-1)
     {
         ALOGE("%s unable to register fd %d to epoll set: %s", __func__, client_sock, strerror(errno));
         close(client_sock);
@@ -598,21 +572,26 @@ static void *epoll_thread()
 
     while(rtk_btservice->epoll_thread_running)
     {
-        nfds=epoll_wait(rtk_btservice->epoll_fd,events,32,500);
+        nfds = epoll_wait(rtk_btservice->epoll_fd,events, 32, 500);
         if(rtk_btservice->epoll_thread_running != 0)
         {
-            if(nfds>0)
+            if(nfds > 0)
             {
-                for(i=0;i<nfds;i++)
+                for(i = 0; i < nfds; i++)
                 {
-                    if(events[i].data.fd == rtk_btservice->socketfd && events[i].events&EPOLLIN)
+                    if(events[i].data.fd == rtk_btservice->sig_fd[1]) {
+                        ALOGE("epoll_thread , receive exit signal");
+                        continue;
+                    }
+
+                    if(events[i].data.fd == rtk_btservice->socketfd && events[i].events & EPOLLIN)
                     {
-                        if(socket_accept(events[i].data.fd)<0)
+                        if(socket_accept(events[i].data.fd) < 0)
                         {
                             pthread_exit(0);
                         }
                     }
-                    else if(events[i].events&(EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR))
+                    else if(events[i].events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR))
                     {
                         ALOGD("%s events[i].data.fd = %d ", __func__, events[i].data.fd);
                         Getpacket(events[i].data.fd);
@@ -659,17 +638,31 @@ static int unix_socket_start(const char *servername)
         ALOGE("%s chmod failed");
     }
     */
-    event.data.fd=rtk_btservice->socketfd;
-    event.events=EPOLLIN;
-    if(epoll_ctl(rtk_btservice->epoll_fd,EPOLL_CTL_ADD,rtk_btservice->socketfd,&event)==-1)
+    event.data.fd = rtk_btservice->socketfd;
+    event.events = EPOLLIN;
+    if(epoll_ctl(rtk_btservice->epoll_fd, EPOLL_CTL_ADD, rtk_btservice->socketfd,&event) == -1)
     {
         ALOGE("%s unable to register fd %d to epoll set: %s", __func__, rtk_btservice->socketfd, strerror(errno));
         return -1;
     }
 
+    event.data.fd = rtk_btservice->sig_fd[1];
+    event.events = EPOLLIN;
+    if(epoll_ctl(rtk_btservice->epoll_fd, EPOLL_CTL_ADD, rtk_btservice->sig_fd[1], &event) == -1)
+    {
+        ALOGE("%s unable to register signal fd %d to epoll set: %s", __func__, rtk_btservice->sig_fd[1], strerror(errno));
+        return -1;
+    }
     return 0;
 }
 
+void RTK_btservice_send_close_signal(void)
+{
+    unsigned char close_signal = 1;
+    ssize_t ret;
+    RTK_NO_INTR(ret = write(rtk_btservice->sig_fd[0], &close_signal, 1));
+}
+
 int RTK_btservice_thread_start()
 {
     rtk_btservice->epoll_thread_running=1;
@@ -679,7 +672,7 @@ int RTK_btservice_thread_start()
         return -1;
     }
 
-    rtk_btservice->cmdqueue_thread_running=1;
+    rtk_btservice->cmdqueue_thread_running = 1;
     if (pthread_create(&rtk_btservice->cmdreadythd, NULL, cmdready_thread, NULL)!=0)
     {
         ALOGE("pthread_create cmdready_thread: %s", strerror(errno));
@@ -691,9 +684,9 @@ int RTK_btservice_thread_start()
 
 void RTK_btservice_thread_stop()
 {
-    ALOGD("%s !", __func__);
     rtk_btservice->epoll_thread_running=0;
     rtk_btservice->cmdqueue_thread_running=0;
+    RTK_btservice_send_close_signal();
     sem_post(&rtk_btservice->cmdqueue_sem);
     sem_post(&rtk_btservice->cmdsend_sem);
     pthread_join(rtk_btservice->cmdreadythd, NULL);
@@ -705,12 +698,17 @@ void RTK_btservice_thread_stop()
 int RTK_btservice_init()
 {
     int ret;
-    rtk_btservice=(Rtk_Btservice_Info *)malloc(sizeof(Rtk_Btservice_Info));
+    rtk_btservice = (Rtk_Btservice_Info *)malloc(sizeof(Rtk_Btservice_Info));
+    if(rtk_btservice)
+        memset(rtk_btservice, 0, sizeof(Rtk_Btservice_Info));
+    else {
+        ALOGE("%s, alloc fail", __func__);
+        return -1;
+    }
 
     rtk_btservice->current_client_sock = -1;
-    rtk_btservice->current_complete_cback=NULL;
+    rtk_btservice->current_complete_cback = NULL;
     rtk_btservice->autopair_fd = -1;
-    ALOGD("%s init start!", __func__);
     hcicmd_alloc_reply_timer();
 
     sem_init(&rtk_btservice->cmdqueue_sem, 0, 0);
@@ -724,6 +722,11 @@ int RTK_btservice_init()
         return -1;
     }
 
+    if((ret = socketpair(AF_UNIX, SOCK_STREAM, 0, rtk_btservice->sig_fd)) < 0) {
+        ALOGE("%s, errno : %s", __func__, strerror(errno));
+        return ret;
+    }
+
     rtk_btservice->epoll_fd = epoll_create(64);
     if (rtk_btservice->epoll_fd == -1) {
         ALOGE("%s unable to create epoll instance: %s", __func__, strerror(errno));
@@ -737,7 +740,7 @@ int RTK_btservice_init()
     }
 
     ret = RTK_btservice_thread_start();
-    if(ret<0)
+    if(ret < 0)
     {
         ALOGE("%s RTK_btservice_thread_start fail!", __func__);
         return -1;
@@ -748,9 +751,13 @@ int RTK_btservice_init()
 
 void RTK_btservice_destroyed()
 {
-    ALOGD("%s destroyed start!", __func__);
+    if(!rtk_btservice)
+        return;
     RTK_btservice_thread_stop();
     close(rtk_btservice->socketfd);
+    rtk_btservice->socketfd = -1;
+    close(rtk_btservice->sig_fd[0]);
+    close(rtk_btservice->sig_fd[1]);
     sem_destroy(&rtk_btservice->cmdqueue_sem);
     sem_destroy(&rtk_btservice->cmdsend_sem);
     flush_cmdqueue_hash(rtk_btservice);
@@ -759,6 +766,7 @@ void RTK_btservice_destroyed()
     rtk_btservice->autopair_fd = -1;
     rtk_btservice->current_client_sock = -1;
     free(rtk_btservice);
+    rtk_btservice = NULL;
     ALOGD("%s destroyed done!", __func__);
 }
 
index 2de46182acaf4fa1d2db68043849d8bdcbd127a3..fec741f50b85603cd573e1360b3c86255e6323f6 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2013 Google, Inc.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *  limitations under the License.
  *
  ******************************************************************************/
-
 #define LOG_TAG "rtk_btsnoop_net"
 #include "rtk_btsnoop_net.h"
 #include <unistd.h>
 
+#define RTK_NO_INTR(fn)  do {} while ((fn) == -1 && errno == EINTR)
+
 #define DATA_DIRECT_2_ELLISY 1
 
 #define HCI_COMMAND         0x01
@@ -44,7 +45,7 @@ static pthread_mutex_t btsnoop_log_lock;
 
 
 static void rtk_safe_close_(int *fd);
-static void *rtk_listen_fn_();
+static void *rtk_listen_fn_(void *context);
 
 static const char *RTK_LISTEN_THREAD_NAME_ = "rtk_btsnoop_net";
 static const int RTK_LOCALHOST_ = 0xC0A80AE2;       // 192.168.10.226
@@ -344,12 +345,14 @@ void rtk_btsnoop_net_write(serial_data_type_t type, uint8_t *data, bool is_recei
     client_addr.sin_addr.s_addr = htonl(RTK_REMOTEHOST_);
     client_addr.sin_port = htons(RTK_REMOTE_PORT_);
     pthread_mutex_lock(&rtk_client_socket_lock_);
-    sendto(rtk_listen_socket_, buffer, (length+i), 0,(struct sockaddr*)&client_addr, sizeof(struct sockaddr_in));
+    int ret;
+    RTK_NO_INTR(ret = sendto(rtk_listen_socket_, buffer, (length+i), 0,(struct sockaddr*)&client_addr, sizeof(struct sockaddr_in)));
     //sendto(rtk_listen_socket_, buffer, 25, 0,(struct sockaddr*)&client_addr, sizeof(struct sockaddr_in));
     pthread_mutex_unlock(&rtk_client_socket_lock_);
 }
 
-static void *rtk_listen_fn_() {
+static void *rtk_listen_fn_(void *context) {
+    RTK_UNUSED(context);
     prctl(PR_SET_NAME, (unsigned long)RTK_LISTEN_THREAD_NAME_, 0, 0, 0);
 
     rtk_listen_socket_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
index 9a8fe05147d69b6d6b833e9455676519a5a1858f..0b34a885e316840b8a6246cb6529c0ced92609a7 100755 (executable)
@@ -1,5 +1,22 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2018 Realtek 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.
+ *
+ ******************************************************************************/
 #define LOG_TAG "rtk_heartbeat"
-#define RTKBT_RELEASE_NAME     "Test"
+#define RTKBT_RELEASE_NAME "20190520_BT_ANDROID_9.0"
 
 #include <utils/Log.h>
 #include <sys/types.h>
@@ -26,7 +43,7 @@
 #include <semaphore.h>
 #include <endian.h>
 #include <byteswap.h>
-#include <sys/un.h> 
+#include <sys/un.h>
 #include <stddef.h>
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -46,6 +63,7 @@ static bool heartbeatFlag = false;
 static int heartbeatCount= 0;
 static uint16_t nextSeqNum= 1;
 static uint16_t cleanupFlag = 0;
+static pthread_mutex_t heartbeat_mutex;
 
 typedef struct Rtk_Service_Data
 {
@@ -115,53 +133,92 @@ static void load_rtkbt_heartbeat_conf()
 
 }
 
+static void rtkbt_heartbeat_send_hw_error(uint8_t status, uint16_t seqnum, uint16_t next_seqnum, int heartbeatCnt)
+{
+    if(!heartbeatFlag)
+      return;
+    unsigned char p_buf[100];
+    int length;
+    p_buf[0] = HCIT_TYPE_EVENT;//event
+    p_buf[1] = HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT;//firmwre event log
+    p_buf[3] = 0x01;// host log opcode
+    length = sprintf((char *)&p_buf[4], "host stack: heartbeat hw error: %d:%d:%d:%d",
+      status, seqnum, next_seqnum, heartbeatCnt);
+    p_buf[2] = length + 2;//len
+    length = length + 1 + 4;
+    userial_recv_rawdata_hook(p_buf,length);
+
+    length = 4;
+    p_buf[0] = HCIT_TYPE_EVENT;//event
+    p_buf[1] = HCI_HARDWARE_ERROR_EVT;//hardware error
+    p_buf[2] = 0x01;//len
+    p_buf[3] = 0xfc;//heartbeat error code
+    userial_recv_rawdata_hook(p_buf,length);
+}
+
 static void rtkbt_heartbeat_cmpl_cback (void *p_params)
 {
     uint8_t  status = 0;
-    uint16_t seqnum;
+    uint16_t seqnum = 0;
     HC_BT_HDR *p_evt_buf = p_params;
     //uint8_t  *p = NULL;
+
+    if(!heartbeatFlag)
+      return;
+
     if(p_params != NULL)
     {
         p_evt_buf = (HC_BT_HDR *) p_params;
         status = p_evt_buf->data[HCI_EVT_HEARTBEAT_STATUS_OFFSET];
         seqnum = p_evt_buf->data[HCI_EVT_HEARTBEAT_SEQNUM_OFFSET_H]<<8 | p_evt_buf->data[HCI_EVT_HEARTBEAT_SEQNUM_OFFSET_L];
     }
-    
+
     if(status == 0 && seqnum == nextSeqNum)
     {
-        nextSeqNum = (seqnum+1);
+        nextSeqNum = (seqnum + 1);
+        pthread_mutex_lock(&heartbeat_mutex);
         heartbeatCount = 0;
+        pthread_mutex_unlock(&heartbeat_mutex);
     }
     else
     {
         ALOGE("rtkbt_heartbeat_cmpl_cback: Current SeqNum = %d,should SeqNum=%d, status = %d", seqnum, nextSeqNum, status);
         ALOGE("heartbeat event missing:  restart bluedroid stack\n");
         usleep(1000);
-        //kill(getpid(), SIGKILL);
+        rtkbt_heartbeat_send_hw_error(status, seqnum, nextSeqNum, heartbeatCount);
     }
-   
+
 }
 
 
 static void heartbeat_timed_out()//(union sigval arg)
 {
     Rtk_Service_Data *p_buf;
-    
+    int count;
+
+    if(!heartbeatFlag)
+      return;
+    pthread_mutex_lock(&heartbeat_mutex);
     heartbeatCount++;
     if(heartbeatCount >= 3)
     {
         if(cleanupFlag == 1)
         {
             ALOGW("Already cleanup, ignore.");
+            pthread_mutex_unlock(&heartbeat_mutex);
             return;
         }
         ALOGE("heartbeat_timed_out: heartbeatCount = %d, expected nextSeqNum = %d",heartbeatCount, nextSeqNum);
         ALOGE("heartbeat_timed_out,controller may be suspend! Now restart bluedroid stack\n");
+        count = heartbeatCount;
+        pthread_mutex_unlock(&heartbeat_mutex);
         usleep(1000);
+        rtkbt_heartbeat_send_hw_error(0,0,nextSeqNum,count);
+
         //kill(getpid(), SIGKILL);
         return;
     }
+    pthread_mutex_unlock(&heartbeat_mutex);
     if(heartbeatFlag)
     {
         p_buf = (Rtk_Service_Data *)malloc(sizeof(Rtk_Service_Data));
@@ -175,7 +232,7 @@ static void heartbeat_timed_out()//(union sigval arg)
         p_buf->parameter_len = 0;
         p_buf->complete_cback = rtkbt_heartbeat_cmpl_cback;
 
-        Rtk_Service_Vendorcmd_Hook(p_buf,-1);
+        Rtk_Service_Vendorcmd_Hook(p_buf, -1);
         free(p_buf);
         poll_timer_flush();
     }
@@ -207,16 +264,17 @@ static void rtkbt_heartbeat_beginTimer_func(void)
     p_buf->parameter = NULL;
     p_buf->parameter_len = 0;
     p_buf->complete_cback = rtkbt_heartbeat_cmpl_cback;
-    
-    Rtk_Service_Vendorcmd_Hook(p_buf,-1);
+
+    Rtk_Service_Vendorcmd_Hook(p_buf, -1);
     free(p_buf);
 
-    //rtkbt_api_callbacks->BTM_VendorSpecificCommand(HCI_CMD_VNDR_HEARTBEAT,0,NULL,rtkbt_heartbeat_cmpl_cback);
     poll_timer_flush();
 }
 
 void Heartbeat_cleanup()
 {
+    if(!heartbeatFlag)
+      return;
     heartbeatFlag = false;
     nextSeqNum = 1;
     heartbeatCount = 0;
@@ -231,6 +289,7 @@ void Heartbeat_init()
     ALOGD("Heartbeat_init start");
     Heartbeat_cleanup();
     load_rtkbt_heartbeat_conf();
+    pthread_mutex_init(&heartbeat_mutex, NULL);
     heartbeatFlag = true;
     heartbeatCount = 0;
     cleanupFlag = 0;
index 36dcb1f22364244645f9893b7855b5de44844307..ddababfcf374245c2f98e14ccfe6016247da3497 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2016 Realtek Corporation.
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
  *  limitations under the License.
  *
  ******************************************************************************/
+
 /******************************************************************************
 *
 *      Module Name:
@@ -33,7 +34,7 @@
 *
 ******************************************************************************/
 #define LOG_TAG "rtk_parse"
-#define RTKBT_RELEASE_NAME "20180702_BT_ANDROID_9.0"
+#define RTKBT_RELEASE_NAME "20190520_BT_ANDROID_9.0"
 
 #include <utils/Log.h>
 #include <stdlib.h>
@@ -63,7 +64,7 @@
 #include "rtk_parse.h"
 #include <sys/syscall.h>
 
-#define RTK_VERSION "2.1"
+#define RTK_COEX_VERSION "3.0"
 
 char invite_req[] = "INVITE_REQ";
 char invite_rsp[] = "INVITE_RSP";
@@ -123,8 +124,8 @@ char bt_leave[] =   "BT_LEAVE";
 //vendor cmd to wifi driver
 #define HCI_OP_HCI_EXTENSION_VERSION_NOTIFY (0x0100 | HCI_GRP_VENDOR_SPECIFIC)
 #define HCI_OP_BT_OPERATION_NOTIFY          (0x0102 | HCI_GRP_VENDOR_SPECIFIC)
-#define    HCI_OP_HCI_BT_INFO_NOTIFY           (0x0106 | HCI_GRP_VENDOR_SPECIFIC)
-#define    HCI_OP_HCI_BT_COEX_NOTIFY           (0x0107 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_OP_HCI_BT_INFO_NOTIFY           (0x0106 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_OP_HCI_BT_COEX_NOTIFY           (0x0107 | HCI_GRP_VENDOR_SPECIFIC)
 #define HCI_OP_HCI_BT_PATCH_VER_NOTIFY      (0x0108 | HCI_GRP_VENDOR_SPECIFIC)
 #define HCI_OP_HCI_BT_AFH_MAP_NOTIFY        (0x0109 | HCI_GRP_VENDOR_SPECIFIC)
 #define HCI_OP_HCI_BT_REGISTER_VALUE_NOTIFY (0x010a | HCI_GRP_VENDOR_SPECIFIC)
@@ -195,6 +196,7 @@ typedef struct RTK_COEX_INFO {
     RT_LIST_ENTRY   list;
     HC_BT_HDR  *    p_buf;
     uint16_t        opcode;
+    tINT_CMD_CBACK  p_cback;
 }tRTK_COEX_INFO;
 
 //profile info data
@@ -221,9 +223,10 @@ typedef struct RTK_PROF {
     RT_LIST_HEAD    conn_hash;      //hash for connections
     RT_LIST_HEAD    profile_list;   //hash for profile info
     RT_LIST_HEAD    coex_list;
+    tINT_CMD_CBACK  current_cback;
     pthread_mutex_t profile_mutex;
     pthread_mutex_t coex_mutex;
-    pthread_mutex_t udpsocket_mutex;
+    pthread_mutex_t btwifi_mutex;
     pthread_t thread_monitor;
     pthread_t thread_data;
     timer_t  timer_a2dp_packet_count;
@@ -247,15 +250,17 @@ typedef struct RTK_PROF {
     uint8_t  autoreport;
     uint8_t  polling_enable;
     uint8_t  polling_interval;
-    volatile uint8_t udpsocket_recv_thread_running;
+    volatile uint8_t coex_recv_thread_running;
     //int32_t   nlsocket;
-    int32_t   udpsocket;
+    int32_t  btcoex_chr;
+    int32_t  udpsocket;
     uint8_t  piconet_id;
     uint8_t  mode;
     uint8_t  afh_map[10];
     uint16_t hci_reversion;
     uint16_t lmp_subversion;
     uint8_t  wifi_on;
+    uint8_t  bt_on;
     //uint8_t  le_profile_index;
 }tRTK_PROF;
 
@@ -271,8 +276,6 @@ typedef struct HCI_EVENT_BT_INFO_CONTROL {
     uint8_t     autoreport_enable;
 }tHCI_EVENT_BT_INFO_CONTROL;
 
-extern void Heartbeat_init();
-
 tRTK_PROF rtk_prof;
 volatile int poweroff_allowed = 0;
 uint8_t coex_log_enable = 0;
@@ -283,6 +286,10 @@ static volatile bool coex_cmd_send = false;
 #define is_profile_busy(profile)        ((rtk_prof.profile_status & BIT(profile)) >0)
 
 static void timeout_handler(int signo, siginfo_t * info, void *context);
+static void notify_func(union sigval sig);
+
+static int coex_msg_send(char *tx_msg, int msg_size);
+static int coex_msg_recv(uint8_t *recv_msg, uint8_t *msg_size);
 
 #ifndef RTK_PARSE_LOG_BUF_SIZE
 #define RTK_PARSE_LOG_BUF_SIZE  1024
@@ -340,10 +347,15 @@ static timer_t OsAllocateTimer(int signo)
     timer_t timerid = (timer_t)-1;
 
     // Create the POSIX timer to generate signo
-    sigev.sigev_notify = SIGEV_THREAD_ID;
-    sigev.sigev_notify_thread_id = syscall(__NR_gettid);
-    sigev.sigev_signo = signo;
-    sigev.sigev_value.sival_ptr = &timerid;
+    //sigev.sigev_notify = SIGEV_THREAD_ID;
+    //sigev.sigev_notify_thread_id = syscall(__NR_gettid);
+    //sigev.sigev_signo = signo;
+    //sigev.sigev_value.sival_ptr = &timerid;
+
+    memset(&sigev, 0, sizeof(sigev));
+    sigev.sigev_notify = SIGEV_THREAD;
+    sigev.sigev_notify_function = notify_func;
+    sigev.sigev_value.sival_int = signo;
 
     //ALOGE("OsAllocateTimer rtk_parse sigev.sigev_notify_thread_id = syscall(__NR_gettid)!");
 
@@ -404,6 +416,7 @@ static int OsStopTimer(timer_t timerid)
 
 int alloc_polling_timer()
 {
+/*
     struct sigaction sigact;
 
     sigemptyset(&sigact.sa_mask);
@@ -418,7 +431,7 @@ int alloc_polling_timer()
         ALOGE("alloc_polling_timer, sigaction failed");
         return -1;
     }
-
+*/
     // Create and set the timer when to expire
     rtk_prof.timer_polling= OsAllocateTimer(TIMER_POLLING);
     RtkLogMsg("alloc polling timer");
@@ -445,6 +458,7 @@ int start_polling_timer(int value)
 
 int alloc_hogp_packet_count_timer()
 {
+/*
     struct sigaction sigact;
 
     sigemptyset(&sigact.sa_mask);
@@ -459,7 +473,7 @@ int alloc_hogp_packet_count_timer()
         ALOGE("alloc_hogp_packet_count_timer, sigaction failed");
         return -1;
     }
-
+*/
     // Create and set the timer when to expire
     rtk_prof.timer_hogp_packet_count= OsAllocateTimer(TIMER_HOGP_PACKET_COUNT);
     RtkLogMsg("alloc hogp packet");
@@ -486,6 +500,7 @@ int start_hogp_packet_count_timer()
 
 int alloc_a2dp_packet_count_timer()
 {
+/*
     struct sigaction sigact;
 
     sigemptyset(&sigact.sa_mask);
@@ -500,7 +515,7 @@ int alloc_a2dp_packet_count_timer()
         ALOGE("alloc_a2dp_packet_count_timer, sigaction failed");
         return -1;
     }
-
+*/
     // Create and set the timer when to expire
     rtk_prof.timer_a2dp_packet_count= OsAllocateTimer(TIMER_A2DP_PACKET_COUNT);
     RtkLogMsg("alloc a2dp packet");
@@ -527,6 +542,7 @@ int start_a2dp_packet_count_timer()
 
 int alloc_pan_packet_count_timer()
 {
+/*
     struct sigaction sigact;
 
     sigemptyset(&sigact.sa_mask);
@@ -541,7 +557,7 @@ int alloc_pan_packet_count_timer()
         ALOGE("alloc_pan_packet_count_timer, sigaction failed");
         return -1;
     }
-
+*/
     // Create and set the timer when to expire
     rtk_prof.timer_pan_packet_count= OsAllocateTimer(TIMER_PAN_PACKET_COUNT);
 
@@ -694,7 +710,7 @@ uint8_t list_allocate_add(uint16_t handle, uint16_t psm, int8_t profile_index, u
 
 void delete_profile_from_hash(tRTK_PROF_INFO* desc)
 {
-    RtkLogMsg("delete profile for handle: %x, psm:%x, dcid:%x, scid:%x", desc->handle, desc->psm, desc->dcid, desc->scid);
+    //RtkLogMsg("delete profile for handle: %x, psm:%x, dcid:%x, scid:%x", desc->handle, desc->psm, desc->dcid, desc->scid);
     if (desc)
     {
         ListDeleteNode(&desc->list);
@@ -804,8 +820,6 @@ void flush_coex_hash(tRTK_PROF* h5)
 
 static void rtk_cmd_complete_cback(void *p_mem)
 {
-    if(p_mem)
-        bt_vendor_cbacks->dealloc(p_mem);
     pthread_mutex_lock(&rtk_prof.coex_mutex);
     RT_LIST_ENTRY* iter = ListGetTop(&(rtk_prof.coex_list));
     tRTK_COEX_INFO* desc = NULL;
@@ -821,8 +835,17 @@ static void rtk_cmd_complete_cback(void *p_mem)
     }
     pthread_mutex_unlock(&rtk_prof.coex_mutex);
 
+    if(rtk_prof.current_cback) {
+        rtk_prof.current_cback(p_mem);
+        rtk_prof.current_cback = NULL;
+    }
+
+    if(p_mem)
+        bt_vendor_cbacks->dealloc(p_mem);
+
     if(desc) {
         ALOGE("%s, transmit_command Opcode:%x",__func__, desc->opcode);
+        rtk_prof.current_cback = desc->p_cback;
         bt_vendor_cbacks->xmit_cb(desc->opcode, desc->p_buf, rtk_cmd_complete_cback);
     }
 
@@ -830,11 +853,13 @@ static void rtk_cmd_complete_cback(void *p_mem)
     return;
 }
 
-void rtk_vendor_cmd_to_fw(uint16_t opcode, uint8_t parameter_len, uint8_t* parameter)
+void rtk_vendor_cmd_to_fw(uint16_t opcode, uint8_t parameter_len, uint8_t* parameter, tINT_CMD_CBACK p_cback)
 {
-    //uint8_t temp = 0;
     HC_BT_HDR  *p_buf = NULL;
 
+    if(!rtk_prof.bt_on)
+        return;
+
     if(bt_vendor_cbacks)
         p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + parameter_len);
 
@@ -843,6 +868,7 @@ void rtk_vendor_cmd_to_fw(uint16_t opcode, uint8_t parameter_len, uint8_t* param
         ALOGE("rtk_vendor_cmd_to_fw: HC_BT_HDR alloc error");
         return;
     }
+    memset(p_buf, 0, (BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + parameter_len));
     p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
     p_buf->offset = 0;
     p_buf->len = HCI_CMD_PREAMBLE_SIZE + parameter_len;
@@ -850,20 +876,21 @@ void rtk_vendor_cmd_to_fw(uint16_t opcode, uint8_t parameter_len, uint8_t* param
 
     uint8_t *p = (uint8_t *) (p_buf + 1);
     UINT16_TO_STREAM(p, opcode);
-    RtkLogMsg("rtk_vendor_cmd_to_fw: Opcode:%x",opcode);
+    *p++ = parameter_len;
+    RtkLogMsg("rtk_vendor_cmd_to_fw: Opcode:%x, parameter_len = %d",opcode, parameter_len);
 
     if(parameter_len > 0)
     {
-        *p++ = parameter_len;
         memcpy(p, parameter, parameter_len);
     }
     if(bt_vendor_cbacks)
     {
-        RtkLogMsg("begin transmit_command Opcode:%x",opcode);
         pthread_mutex_lock(&rtk_prof.coex_mutex);
         if(!coex_cmd_send) {
             coex_cmd_send = true;
+            RtkLogMsg("begin transmit_command Opcode:%x",opcode);
             pthread_mutex_unlock(&rtk_prof.coex_mutex);
+            rtk_prof.current_cback = p_cback;
             bt_vendor_cbacks->xmit_cb(opcode, p_buf, rtk_cmd_complete_cback);
         }
         else {
@@ -872,11 +899,13 @@ void rtk_vendor_cmd_to_fw(uint16_t opcode, uint8_t parameter_len, uint8_t* param
             if (NULL == pcoex_info)
             {
                 ALOGE("rtk_vendor_cmd_to_fw: allocate error");
+                pthread_mutex_unlock(&rtk_prof.coex_mutex);
                 return;
             }
 
             pcoex_info->p_buf = p_buf;
             pcoex_info->opcode = opcode;
+            pcoex_info->p_cback = p_cback;
 
             ListAddToTail(&(pcoex_info->list), &(rtk_prof.coex_list));
             pthread_mutex_unlock(&rtk_prof.coex_mutex);
@@ -936,7 +965,7 @@ void rtk_notify_profileinfo_to_fw()
     *p++ = rtk_prof.profile_status;
     RtkLogMsg("rtk_notify_profileinfo_to_fw, profile_status is %x",rtk_prof.profile_status);
 
-    rtk_vendor_cmd_to_fw(HCI_VENDOR_SET_PROFILE_REPORT_COMMAND, buffer_size, p_buf);
+    rtk_vendor_cmd_to_fw(HCI_VENDOR_SET_PROFILE_REPORT_COMMAND, buffer_size, p_buf, NULL);
 
     free(p_buf);
 
@@ -1287,7 +1316,7 @@ void packets_count(uint16_t handle, uint16_t scid, uint16_t length, uint8_t dire
                 bitpool = sbc_header->bitpool;
                 print_sbc_header(sbc_header);
                 RtkLogMsg("rtp: v %u, cc %u, pt %u", rtph->v, rtph->cc, rtph->pt);
-                rtk_vendor_cmd_to_fw(HCI_VENDOR_ADD_BITPOOL_FW, 1, &bitpool);
+                rtk_vendor_cmd_to_fw(HCI_VENDOR_ADD_BITPOOL_FW, 1, &bitpool, NULL);
             }
             rtk_prof.a2dp_packet_count++;
         }
@@ -1299,14 +1328,8 @@ void packets_count(uint16_t handle, uint16_t scid, uint16_t length, uint8_t dire
 
 static void timeout_handler(int signo, siginfo_t * info, void *context)
 {
-       if(info == NULL)
-       {
-               RtkLogMsg("info null");
-       }
-       if(context == NULL)
-       {
-               RtkLogMsg("context null");
-       }
+    RTK_UNUSED(info);
+    RTK_UNUSED(context);
     if (signo == TIMER_POLLING)
     {
         RtkLogMsg("polling timeout");
@@ -1314,7 +1337,7 @@ static void timeout_handler(int signo, siginfo_t * info, void *context)
         {
             uint8_t temp_cmd[1];
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_REPORT_CONN_SCO_INQ_INFO;
-            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 1, temp_cmd);
+            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 1, temp_cmd, NULL);
         }
     }
     else if (signo == TIMER_A2DP_PACKET_COUNT)
@@ -1385,6 +1408,12 @@ static void timeout_handler(int signo, siginfo_t * info, void *context)
     }
 }
 
+static void notify_func(union sigval sig)
+{
+    int signo = sig.sival_int;
+    timeout_handler(signo, NULL, NULL);
+}
+
 #if 0
 int netlink_send(int nlsk, char *buffer)
 {
@@ -1454,8 +1483,8 @@ int udpsocket_recv(uint8_t *recv_msg, uint8_t *msg_size)
     bzero(buf, MAX_PAYLOAD);
 
     while (poll(&pfd, 1, 1000) <= 0) {
-        if (rtk_prof.udpsocket_recv_thread_running ==0) {
-            RtkLogMsg("SIGUSR2 should have caught us before this");
+        if (rtk_prof.coex_recv_thread_running ==0) {
+            RtkLogMsg("%s, SIGUSR2 should have caught us before this", __func__);
             return -1;
         }
     }
@@ -1472,6 +1501,57 @@ int udpsocket_recv(uint8_t *recv_msg, uint8_t *msg_size)
     return 0;
 }
 
+
+int btcoex_chr_send(char *tx_msg, int msg_size)
+{
+    int n; /* message byte size */
+
+    RtkLogMsg("btcoex_chr_send tx_msg:%s",tx_msg);
+    RTK_NO_INTR (n = write(rtk_prof.btcoex_chr, tx_msg, msg_size));
+    if (n < 0)
+    {
+        ALOGE("ERROR in write");
+        return -1;
+    }
+    return n;
+}
+
+int btcoex_chr_recv(uint8_t *recv_msg, uint8_t *msg_size)
+{
+    char buf[MAX_PAYLOAD];  /* message buf */
+    int n = -1;                  /* message byte size */
+    struct pollfd pfd = {
+        .events = POLLPRI|POLLIN|POLLHUP|POLLERR|POLLRDHUP,
+        .revents = 0,
+        .fd = rtk_prof.btcoex_chr
+    };
+
+    bzero(buf, MAX_PAYLOAD);
+
+    while (poll(&pfd, 1, 1000) <= 0) {
+        if (rtk_prof.coex_recv_thread_running == 0) {
+            RtkLogMsg("%s, SIGUSR2 should have caught us before this", __func__);
+            return -1;
+        }
+    }
+
+    if (pfd.revents & POLLIN) {
+        RTK_NO_INTR(n = read(rtk_prof.btcoex_chr, buf, MAX_PAYLOAD));
+        if (n < 0) {
+            ALOGE("ERROR in recvfrom");
+            return -1;
+        } else {
+            *msg_size = n;
+            memcpy(recv_msg, buf, n);
+        }
+    }
+    else {
+        ALOGE("rtk_btcoex is wrong");
+        return -1;
+    }
+    return 0;
+}
+
 void rtk_notify_extension_version_to_wifi()
 {
     uint8_t para_length = 2;
@@ -1485,7 +1565,7 @@ void rtk_notify_extension_version_to_wifi()
     *p++ = para_length;
     UINT16_TO_STREAM(p, HCI_EXTENSION_VERSION);
     RtkLogMsg("extension version is 0x%x", HCI_EXTENSION_VERSION);
-    if(udpsocket_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
+    if(coex_msg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
         ALOGE("rtk_notify_extension_version_to_wifi: udpsocket send error");
 }
 
@@ -1504,7 +1584,7 @@ void rtk_notify_btpatch_version_to_wifi()
     UINT16_TO_STREAM(p, rtk_prof.lmp_subversion);
     RtkLogMsg("btpatch_version, length is 0x%x, hci_reversion is 0x%x, lmp_subversion is %x", para_length, rtk_prof.hci_reversion, rtk_prof.lmp_subversion);
 
-    if(udpsocket_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
+    if(coex_msg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
         ALOGE("rtk_notify_btpatch_version_to_wifi: udpsocket send error");
 }
 
@@ -1529,7 +1609,7 @@ void rtk_notify_afhmap_to_wifi()
     for(kk=0; kk < 10; kk++)
         RtkLogMsg("afhmap data[%d] is 0x%x", kk, rtk_prof.afh_map[kk]);
 
-    if(udpsocket_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
+    if(coex_msg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
         ALOGE("rtk_notify_afhmap_to_wifi: udpsocket send error");
 }
 
@@ -1552,7 +1632,7 @@ void rtk_notify_btcoex_to_wifi(uint8_t opcode, uint8_t status)
 
     RtkLogMsg("btcoex, opcode is 0x%x, status is 0x%x", opcode, status);
 
-    if(udpsocket_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
+    if(coex_msg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
         ALOGE("rtk_notify_btcoex_to_wifi: udpsocket send error");
 }
 
@@ -1580,7 +1660,7 @@ void rtk_notify_btoperation_to_wifi(uint8_t operation, uint8_t append_data_lengt
             RtkLogMsg("append data is 0x%x", *(append_data+kk));
     }
 
-    if(udpsocket_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
+    if(coex_msg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
         ALOGE("rtk_notify_btoperation_to_wifi: udpsocket send error");
 }
 
@@ -1612,7 +1692,7 @@ void rtk_notify_info_to_wifi(uint8_t reason, uint8_t length, uint8_t* report_inf
             RtkLogMsg("bt info[%d]: %02x", i, report_info[i]);
     }
 
-    if(udpsocket_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
+    if(coex_msg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
         ALOGE("rtk_notify_info_to_wifi: udpsocket send error");
 }
 
@@ -1634,7 +1714,7 @@ void rtk_notify_regester_to_wifi(uint8_t* reg_value)
     RtkLogMsg("bt register, register offset is %x", reg->offset);
     RtkLogMsg("bt register, register value is %x", reg->value);
 
-    if(udpsocket_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
+    if(coex_msg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
         ALOGE("rtk_notify_regester_to_wifi: udpsocket send error");
 }
 
@@ -1660,7 +1740,7 @@ static void rtk_handle_bt_info_control(uint8_t* p)
     temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_ENABLE;
     temp_cmd[1] = 1;
     temp_cmd[2] = info->autoreport_enable;
-    rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
+    rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd, NULL);
 
     rtk_notify_info_to_wifi(HOST_RESPONSE, 0, NULL);
 }
@@ -1687,7 +1767,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_ENABLE_IGNORE_WLAN_ACT_CMD;
             temp_cmd[1] = 1;
             temp_cmd[2] = value;
-            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
+            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd, NULL);
             break;
         }
 
@@ -1700,7 +1780,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_SET_BT_LNA_CONSTRAINT;
             temp_cmd[1] = 1;
             temp_cmd[2] = value;
-            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
+            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd, NULL);
             break;
         }
 
@@ -1713,7 +1793,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_WIFI_FORCE_TX_POWER_CMD;
             temp_cmd[1] = 1;
             temp_cmd[2] = power_decrease;
-            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
+            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd, NULL);
             break;
         }
 
@@ -1726,7 +1806,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_SET_BT_PSD_MODE;
             temp_cmd[1] = 1;
             temp_cmd[2] = psd_mode;
-            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
+            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd, NULL);
             break;
         }
 
@@ -1738,7 +1818,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             temp_cmd[0] = HCI_VENDOR_SUB_CMD_WIFI_CHANNEL_AND_BANDWIDTH_CMD;
             temp_cmd[1] = 3;
             memcpy(temp_cmd+2, p, 3);//wifi_state, wifi_centralchannel, chnnels_btnotuse
-            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 5, temp_cmd);
+            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 5, temp_cmd, NULL);
             break;
         }
 
@@ -1753,7 +1833,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
             temp_cmd[1] = 2;
             temp_cmd[2] = rtk_prof.piconet_id;
             temp_cmd[3] = rtk_prof.mode;
-            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4, temp_cmd);
+            rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4, temp_cmd, NULL);
             break;
         }
 
@@ -1769,7 +1849,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
                 temp_cmd[1] = 5;
                 temp_cmd[2] = *p++;
                 memcpy(temp_cmd+3, p, 4);
-                rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 7, temp_cmd);
+                rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 7, temp_cmd, NULL);
             }
             else //write
             {
@@ -1778,7 +1858,7 @@ static void rtk_handle_bt_coex_control(uint8_t* p)
                 temp_cmd[1] = 5;
                 temp_cmd[2] = *p++;
                 memcpy(temp_cmd+3, p, 8);
-                rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 11, temp_cmd);
+                rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 11, temp_cmd, NULL);
             }
             break;
         }
@@ -1792,7 +1872,9 @@ void rtk_handle_event_from_wifi(uint8_t* msg)
 {
     uint8_t *p = msg;
     uint8_t event_code = *p++;
-       uint8_t total_length = 0;
+    uint8_t total_length = 0;
+
+    RtkLogMsg("receive invite rsp from wifi msg : %s", msg);
     if(memcmp(msg, invite_rsp, sizeof(invite_rsp)) == 0)
     {
 #if 0
@@ -1812,7 +1894,7 @@ void rtk_handle_event_from_wifi(uint8_t* msg)
     {
         RtkLogMsg("receive attend req from wifi, wifi turn on");
         rtk_prof.wifi_on = 1;
-        udpsocket_send(attend_ack, sizeof(attend_ack));
+        coex_msg_send(attend_ack, sizeof(attend_ack));
         rtk_notify_extension_version_to_wifi();
     }
 
@@ -1820,7 +1902,7 @@ void rtk_handle_event_from_wifi(uint8_t* msg)
     {
         RtkLogMsg("receive wifi leave from wifi, wifi turn off");
         rtk_prof.wifi_on = 0;
-        udpsocket_send(leave_ack, sizeof(leave_ack));
+        coex_msg_send(leave_ack, sizeof(leave_ack));
         if(rtk_prof.polling_enable)
         {
             rtk_prof.polling_enable = 0;
@@ -1874,15 +1956,16 @@ void rtk_handle_event_from_wifi(uint8_t* msg)
     }
 }
 
-static void udpsocket_receive_thread_exit_handler(int sig)
+static void coex_receive_thread_exit_handler(int sig)
 {
     RtkLogMsg("USR2, this signal is %d \n", sig);
     usleep(100);
     pthread_exit(0);
 }
 
-static void udpsocket_receive_thread()//(void *arg)
+static void btwifi_coex_receive_thread(void *arg)
 {
+    RTK_UNUSED(arg);
     uint8_t msg_recv[MAX_PAYLOAD];
     uint8_t recv_length;
     struct sigaction actions;
@@ -1890,21 +1973,21 @@ static void udpsocket_receive_thread()//(void *arg)
     memset(&actions, 0, sizeof(actions));
     sigemptyset(&actions.sa_mask);
     actions.sa_flags = 0;
-    actions.sa_handler = udpsocket_receive_thread_exit_handler;
+    actions.sa_handler = coex_receive_thread_exit_handler;
 
     sigaction(SIGUSR2,&actions,NULL);//int rc = sigaction(SIGUSR2,&actions,NULL);
 
-    RtkLogMsg("udpsocket_receive_thread started");
-    prctl(PR_SET_NAME, (unsigned long)"udpsocket_receive_thread", 0, 0, 0);
+    RtkLogMsg("btwifi_coex_receive_thread started");
+    prctl(PR_SET_NAME, (unsigned long)"btwifi_coex_receive_thread", 0, 0, 0);
 
-    while(rtk_prof.udpsocket_recv_thread_running)
+    while(rtk_prof.coex_recv_thread_running)
     {
         memset(msg_recv, 0 , MAX_PAYLOAD);
-        if (udpsocket_recv(msg_recv, &recv_length) == 0)
+        if (coex_msg_recv(msg_recv, &recv_length) == 0)
             rtk_handle_event_from_wifi(msg_recv);
     }
 
-    RtkLogMsg("udpsocket_receive_thread exiting");
+    RtkLogMsg("btwifi_coex_receive_thread exiting");
     pthread_exit(NULL);
 }
 
@@ -1915,27 +1998,26 @@ int create_udpsocket_socket()
 
     RtkLogMsg("create udpsocket port: %d\n", portno);
 
-    pthread_mutex_lock(&rtk_prof.udpsocket_mutex);
+    pthread_mutex_lock(&rtk_prof.btwifi_mutex);
 
     pthread_attr_t thread_attr_data;
-    if (rtk_prof.udpsocket_recv_thread_running)
+    if (rtk_prof.coex_recv_thread_running)
     {
         ALOGE("udp_receive_thread already exit");
-        pthread_mutex_unlock(&rtk_prof.udpsocket_mutex);
+        pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
         return -1 ;
     }
 
-    rtk_prof.udpsocket_recv_thread_running = 1;
+    rtk_prof.coex_recv_thread_running = 1;
     rtk_prof.udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
     RtkLogMsg("create socket %d", rtk_prof.udpsocket);
 
     if (rtk_prof.udpsocket < 0)
     {
         ALOGE("create udpsocket error...%s\n", strerror(errno));
-        rtk_prof.udpsocket_recv_thread_running = 0;
-        close(rtk_prof.udpsocket);
+        rtk_prof.coex_recv_thread_running = 0;
         RtkLogMsg("close socket %d", rtk_prof.udpsocket);
-        pthread_mutex_unlock(&rtk_prof.udpsocket_mutex);
+        pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
         return -1 ;
     }
 
@@ -1950,42 +2032,45 @@ int create_udpsocket_socket()
     rtk_prof.client_addr.sin_port = htons(CONNECT_PORT_WIFI);
 
     optval = 1;
-    setsockopt(rtk_prof.udpsocket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));
+    int ret = setsockopt(rtk_prof.udpsocket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));
+    if(ret == -1){
+        ALOGE("%s, setsockopt error: %s", __func__, strerror(errno));
+    }
 
     if (bind(rtk_prof.udpsocket, (struct sockaddr *)&rtk_prof.server_addr, sizeof(rtk_prof.server_addr)) < 0)
     {
         ALOGE("bind udpsocket error...%s\n", strerror(errno));
-        rtk_prof.udpsocket_recv_thread_running = 0;
+        rtk_prof.coex_recv_thread_running = 0;
         close(rtk_prof.udpsocket);
         RtkLogMsg("close socket %d", rtk_prof.udpsocket);
-        pthread_mutex_unlock(&rtk_prof.udpsocket_mutex);
+        pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
         return -1 ;
     }
 
     pthread_attr_init(&thread_attr_data);
-    if (pthread_create(&rtk_prof.thread_data, &thread_attr_data, (void*)udpsocket_receive_thread, NULL) != 0)
+    if (pthread_create(&rtk_prof.thread_data, &thread_attr_data, (void*)btwifi_coex_receive_thread, NULL) != 0)
     {
         ALOGE("pthread_create failed!");
         pthread_attr_destroy(&thread_attr_data);
-        rtk_prof.udpsocket_recv_thread_running = 0;
-        pthread_mutex_unlock(&rtk_prof.udpsocket_mutex);
+        rtk_prof.coex_recv_thread_running = 0;
+        pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
         return -1 ;
     }
     pthread_attr_destroy(&thread_attr_data);
-    pthread_mutex_unlock(&rtk_prof.udpsocket_mutex);
+    pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
     return 0;
 }
 
-int stop_udpsocket_receive_thread()
+int stop_btwifi_coex_receive_thread()
 {
-    pthread_mutex_lock(&rtk_prof.udpsocket_mutex);
+    pthread_mutex_lock(&rtk_prof.btwifi_mutex);
     int result = 0;
 
     RtkLogMsg("notify wifi bt turn off");
     if(rtk_prof.wifi_on)
-        udpsocket_send(bt_leave, sizeof(bt_leave));
+        coex_msg_send(bt_leave, sizeof(bt_leave));
 
-    if (rtk_prof.udpsocket_recv_thread_running)
+    if (rtk_prof.coex_recv_thread_running)
     {
         RtkLogMsg("data thread is running, stop it");
 
@@ -1994,20 +2079,29 @@ int stop_udpsocket_receive_thread()
         {
             ALOGE("error cancelling data thread");
         }
-        rtk_prof.udpsocket_recv_thread_running = 0;
+        rtk_prof.coex_recv_thread_running = 0;
 
         if ((result = pthread_join(rtk_prof.thread_data, NULL)) < 0)
         {
             ALOGE( "data thread pthread_join() failed result:%d", result);
         }
 
-        RtkLogMsg("close socket %d", rtk_prof.udpsocket);
-        if((result = close(rtk_prof.udpsocket)) != 0)
-        {
-            ALOGE("close socket error!");
+        if(rtk_prof.udpsocket > 0) {
+            RtkLogMsg("close socket %d", rtk_prof.udpsocket);
+            if((result = close(rtk_prof.udpsocket)) != 0)
+            {
+                ALOGE("close socket error!");
+            }
+        }
+        else if(rtk_prof.btcoex_chr > 0) {
+            RtkLogMsg("close char device  %d", rtk_prof.btcoex_chr);
+            if((result = close(rtk_prof.btcoex_chr)) != 0)
+            {
+                ALOGE("close char device  error!");
+            }
         }
     }
-    pthread_mutex_unlock(&rtk_prof.udpsocket_mutex);
+    pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
     return 0;
 }
 
@@ -2042,14 +2136,52 @@ int create_netlink_socket()
 }
 #endif
 
+int open_btcoex_chrdev()
+{
+    RtkLogMsg("open_btcoex_chrdev\n");
+
+    pthread_mutex_lock(&rtk_prof.btwifi_mutex);
+
+    pthread_attr_t thread_attr_data;
+    if (rtk_prof.coex_recv_thread_running)
+    {
+        ALOGE("udp_receive_thread already exit");
+        pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
+        return -1 ;
+    }
+
+    rtk_prof.coex_recv_thread_running = 1;
+    if ((rtk_prof.btcoex_chr = open("/dev/rtk_btcoex", O_RDWR)) < 0)
+    {
+        ALOGE("open rtk_btcoex error...%s\n", strerror(errno));
+        rtk_prof.coex_recv_thread_running = 0;
+        pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
+        return -1 ;
+    }
+
+    pthread_attr_init(&thread_attr_data);
+    if (pthread_create(&rtk_prof.thread_data, &thread_attr_data, (void*)btwifi_coex_receive_thread, NULL) != 0)
+    {
+        ALOGE("create coexchr_receive_thread failed!");
+        pthread_attr_destroy(&thread_attr_data);
+        rtk_prof.coex_recv_thread_running = 0;
+        pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
+        return -1 ;
+    }
+    pthread_attr_destroy(&thread_attr_data);
+    pthread_mutex_unlock(&rtk_prof.btwifi_mutex);
+    return 0;
+}
+
 void rtk_parse_init(void)
 {
     ALOGI("RTKBT_RELEASE_NAME: %s",RTKBT_RELEASE_NAME);
-    RtkLogMsg("rtk_profile_init, version: %s", RTK_VERSION);
+    RtkLogMsg("rtk_profile_init, version: %s", RTK_COEX_VERSION);
 
+    memset(&rtk_prof, 0, sizeof(rtk_prof));
     pthread_mutex_init(&rtk_prof.profile_mutex, NULL);
     pthread_mutex_init(&rtk_prof.coex_mutex, NULL);
-    pthread_mutex_init(&rtk_prof.udpsocket_mutex, NULL);
+    pthread_mutex_init(&rtk_prof.btwifi_mutex, NULL);
     alloc_a2dp_packet_count_timer();
     alloc_pan_packet_count_timer();
     alloc_hogp_packet_count_timer();
@@ -2059,13 +2191,15 @@ void rtk_parse_init(void)
     init_connection_hash(&rtk_prof);
     init_coex_hash(&rtk_prof);
 
-    create_udpsocket_socket();
+    if(create_udpsocket_socket() < 0) {
+        ALOGE("UDP socket fail, try to use rtk_btcoex chrdev");
+        open_btcoex_chrdev();
+    }
 }
 
 void rtk_parse_cleanup()
 {
     RtkLogMsg("rtk_profile_cleanup");
-    int kk = 0;
     free_a2dp_packet_count_timer();
     free_pan_packet_count_timer();
     free_hogp_packet_count_timer();
@@ -2077,14 +2211,10 @@ void rtk_parse_cleanup()
     flush_coex_hash(&rtk_prof);
     pthread_mutex_destroy(&rtk_prof.coex_mutex);
 
-    stop_udpsocket_receive_thread();
-    pthread_mutex_destroy(&rtk_prof.udpsocket_mutex);
+    stop_btwifi_coex_receive_thread();
+    pthread_mutex_destroy(&rtk_prof.btwifi_mutex);
 
-    rtk_prof.polling_enable = 0;
-    rtk_prof.profile_bitmap = 0;
-    rtk_prof.profile_status = 0;
-    for(kk = 0; kk < 8; kk++)
-        rtk_prof.profile_refcount[kk] = 0;
+    memset(&rtk_prof, 0, sizeof(rtk_prof));
 }
 
 static void rtk_handle_vender_mailbox_cmp_evt(uint8_t* p, uint8_t len)
@@ -2147,7 +2277,7 @@ static void rtk_handle_vender_mailbox_cmp_evt(uint8_t* p, uint8_t len)
                 temp_cmd[1] = 2;
                 temp_cmd[2] = rtk_prof.piconet_id;
                 temp_cmd[3] = rtk_prof.mode;
-                rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4, temp_cmd);
+                rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4, temp_cmd, NULL);
             }
             else //fail
             {
@@ -2166,7 +2296,7 @@ static void rtk_handle_vender_mailbox_cmp_evt(uint8_t* p, uint8_t len)
                 temp_cmd[1] = 2;
                 temp_cmd[2] = rtk_prof.piconet_id;
                 temp_cmd[3] = rtk_prof.mode;
-                rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4, temp_cmd);
+                rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4, temp_cmd, NULL);
             }
             else //fail
             {
@@ -2241,7 +2371,7 @@ static void rtk_handle_cmd_complete_evt(uint8_t*p, uint8_t len)
         case HCI_RESET:
         {
             RtkLogMsg("bt start ok");
-            udpsocket_send(invite_req, sizeof(invite_req));
+            coex_msg_send(invite_req, sizeof(invite_req));
 #if 0
             if(create_netlink_socket() == 0)
             {
@@ -2252,8 +2382,6 @@ static void rtk_handle_cmd_complete_evt(uint8_t*p, uint8_t len)
             else
                 RtkLogMsg("wifi is off when bt turn on, wait for wifi turning on...");
 #endif
-            uint8_t ttmp[1] = {1};
-            rtk_vendor_cmd_to_fw(0xfc1b, 1, ttmp);
             break;
         }
 
@@ -2266,10 +2394,6 @@ static void rtk_handle_cmd_complete_evt(uint8_t*p, uint8_t len)
             rtk_handle_vender_mailbox_cmp_evt(p, len);
             break;
 
-        case HCI_SET_EVENT_MASK:
-            Heartbeat_init();
-            break;
-
         case HCI_VENDOR_ADD_BITPOOL_FW:
             status = *p++;
             RtkLogMsg("received cmd complete event for HCI_VENDOR_ADD_BITPOOL_FW status:%d",status);
@@ -2492,6 +2616,30 @@ static void rtk_handle_le_meta_evt(uint8_t* p)
     }
 }
 
+static int coex_msg_send(char *tx_msg, int msg_size)
+{
+    int ret = -1;
+    if(rtk_prof.udpsocket > 0) {
+        ret = udpsocket_send(tx_msg, msg_size);
+    }
+    else if(rtk_prof.btcoex_chr > 0) {
+        ret = btcoex_chr_send(tx_msg, msg_size);
+    }
+    return ret;
+
+}
+
+static int coex_msg_recv(uint8_t *recv_msg, uint8_t *msg_size)
+{
+    int ret = -1;
+    if(rtk_prof.udpsocket > 0) {
+        ret = udpsocket_recv(recv_msg, msg_size);
+    }
+    else if(rtk_prof.btcoex_chr > 0) {
+        ret = btcoex_chr_recv(recv_msg, msg_size);
+    }
+    return ret;
+}
 void rtk_parse_internal_event_intercept(uint8_t *p_msg)
 {
     //ALOGE("in rtk_parse_internal_event_intercept, *p= %x", *p);
@@ -2632,7 +2780,7 @@ void rtk_parse_internal_event_intercept(uint8_t *p_msg)
 
 void rtk_parse_command(uint8_t *pp)
 {
-    uint8_t *p =pp;
+    uint8_t *p = pp;
     uint16_t cmd;
     STREAM_TO_UINT16(cmd, p);
 
@@ -2683,12 +2831,15 @@ void rtk_parse_l2cap_data(uint8_t *pp, uint8_t direction)
     uint16_t handle, total_len, pdu_len, channel_ID, command_len, psm, scid, dcid, result, status;
     uint8_t flag, code, identifier;
     STREAM_TO_UINT16 (handle, pp);
-    flag = handle >> 12;
+    flag = (handle >> HCI_DATA_EVENT_OFFSET) & HCI_DATA_EVENT_MASK;
     handle = handle & 0x0FFF;
     STREAM_TO_UINT16 (total_len, pp);
     STREAM_TO_UINT16 (pdu_len, pp);
     STREAM_TO_UINT16 (channel_ID, pp);
 
+    if(flag != RTK_START_PACKET_BOUNDARY)
+      return;
+
     if(channel_ID == 0x0001)
     {
         code = (uint8_t)(*pp++);
@@ -2740,8 +2891,9 @@ void rtk_parse_l2cap_data(uint8_t *pp, uint8_t direction)
 
 void rtk_add_le_profile(BD_ADDR bdaddr, uint16_t handle, uint8_t profile_map)
 {
+    RTK_UNUSED(bdaddr);
     RtkLogMsg("rtk_add_le_profile, handle is %x, profile_map is %x", handle, profile_map);
-       RtkLogMsg("bdaddr[0] = %d", bdaddr[0]);
+
     tRTK_CONN_PROF* hci_conn = find_connection_by_handle(&rtk_prof, handle);
     if(hci_conn)
     {
@@ -2759,8 +2911,9 @@ void rtk_add_le_profile(BD_ADDR bdaddr, uint16_t handle, uint8_t profile_map)
 
 void rtk_delete_le_profile(BD_ADDR bdaddr, uint16_t handle, uint8_t profile_map)
 {
+    RTK_UNUSED(bdaddr);
     RtkLogMsg("rtk_delete_le_profile, handle is %x, profile_map is %x", handle, profile_map);
-       RtkLogMsg("bdaddr[0] = %d", bdaddr[0]);
+
     pthread_mutex_lock(&rtk_prof.profile_mutex);
     tRTK_CONN_PROF* hci_conn = find_connection_by_handle(&rtk_prof, handle);
     if(hci_conn == NULL)
@@ -2803,6 +2956,13 @@ void rtk_add_le_data_count(uint8_t data_type)
     }
 }
 
+void rtk_set_bt_on(uint8_t bt_on) {
+    RtkLogMsg("bt stack is init");
+    rtk_prof.bt_on = bt_on;
+    uint8_t ttmp[1] = {1};
+    rtk_vendor_cmd_to_fw(0xfc1b, 1, ttmp, NULL);
+}
+
 static rtk_parse_manager_t parse_interface = {
   rtk_parse_internal_event_intercept,
   rtk_parse_l2cap_data,
@@ -2812,6 +2972,7 @@ static rtk_parse_manager_t parse_interface = {
   rtk_add_le_profile,
   rtk_delete_le_profile,
   rtk_add_le_data_count,
+  rtk_set_bt_on,
 };
 
 rtk_parse_manager_t *rtk_parse_manager_get_interface() {
index 2ed91c9eb8566ec30a53ef80962dabdb39b8910c..6d2ce9b3ff1490afec0e8cef963495ea0dc3dde1 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014-2016 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
  *  limitations under the License.
  *
  ******************************************************************************/
-
 /******************************************************************************
  *
  *  Filename:      poll.c
@@ -217,6 +216,7 @@ void poll_timer_flush(void)
     struct itimerspec ts;
     struct sigevent se;
 
+    memset(&se, 0, sizeof(struct sigevent));
     BTPOLLDBG("poll_timer_flush: state %d", bt_poll_cb.state);
 
     if (bt_poll_cb.state != POLL_ENABLED)
index 18aa68903d142c086e65c538cbb2509c6d110427..b4606075eceb33763225ea0a1b6eb107bfd3d031 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
  *  limitations under the License.
  *
  ******************************************************************************/
-
 /******************************************************************************
  *
  *  Filename:      userial_vendor.c
@@ -56,7 +55,7 @@
 /******************************************************************************
 **  functions
 ******************************************************************************/
-uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len)
+uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len, bool* condition)
 {
     int n_read = 0;
     struct pollfd pfd;
@@ -68,8 +67,10 @@ uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len)
 
     while (n_read < (int)len)
     {
+        if(condition && !(*condition))
+            return n_read;
         pfd.fd = fd;
-        pfd.events = POLLIN|POLLHUP;
+        pfd.events = POLLIN|POLLHUP|POLLNVAL|POLLRDHUP;
 
         /* make sure there is data prior to attempting read to avoid blocking
            a read for more than poll timeout */
@@ -86,7 +87,7 @@ uint32_t Skt_Read(int fd, uint8_t *p_buf, uint32_t len)
             break;
         }
 
-        if (pfd.revents & (POLLHUP|POLLNVAL) )
+        if (pfd.revents & (POLLHUP|POLLNVAL|POLLRDHUP) )
         {
             return 0;
         }
@@ -125,14 +126,14 @@ int Skt_Read_noblock(int fd, uint8_t *p_buf, uint32_t len)
     }
 
     pfd.fd = fd;
-    pfd.events = POLLIN|POLLHUP;
+    pfd.events = POLLIN|POLLHUP|POLLRDHUP;
 
     if (poll(&pfd, 1, 0) == 0)
     {
         return 0;
     }
 
-    if (pfd.revents & (POLLHUP|POLLNVAL) )
+    if (pfd.revents & (POLLHUP|POLLNVAL|POLLRDHUP) )
     {
         return 0;
     }
index 929111432356bf4ba757add9207b93963874f207..080189d740ec6afd3ba81c71da0a5de6bfc54841 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -172,7 +172,7 @@ static int init_rfkill()
             break;
         }
     }
-       
+
     asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
     return 0;
 }
@@ -369,9 +369,10 @@ int upio_set_bluetooth_power(int on)
 ** Returns         None
 **
 *******************************************************************************/
-void upio_set(uint8_t pio, uint8_t action)//(uint8_t pio, uint8_t action, uint8_t polarity)
+void upio_set(uint8_t pio, uint8_t action, uint8_t polarity)
 {
     //int rc;
+    RTK_UNUSED(polarity);
 #if (BT_WAKE_VIA_PROC == TRUE)
     int fd = -1;
     char buffer;
@@ -382,6 +383,7 @@ void upio_set(uint8_t pio, uint8_t action)//(uint8_t pio, uint8_t action, uint8_
         case UPIO_LPM_MODE:
             if (upio_state[UPIO_LPM_MODE] == action)
             {
+                RTK_UNUSED(lpm_mode[action]);
                 UPIODBG("LPM is %s already", lpm_mode[action]);
                 return;
             }
@@ -451,6 +453,7 @@ void upio_set(uint8_t pio, uint8_t action)//(uint8_t pio, uint8_t action, uint8_
         case UPIO_BT_WAKE:
             if (upio_state[UPIO_BT_WAKE] == action)
             {
+                RTK_UNUSED(lpm_state[action]);
                 UPIODBG("BT_WAKE is %s already", lpm_state[action]);
 
 #if (BT_WAKE_VIA_PROC == TRUE)
index 06ece9b9d7e4d7192fc5a1131b5b6ceff9909a1d..c2ad284ac8a6348bf2f19ae46d60080340c12449 100755 (executable)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Realtek Corporation
+ *  Copyright (C) 2009-2018 Realtek Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -35,6 +35,8 @@
 #include "userial.h"
 #include "userial_vendor.h"
 #include "rtk_socket.h"
+#include <cutils/sockets.h>
+
 
 #ifdef CONFIG_SCO_OVER_HCI
 #include "sbc.h"
@@ -64,6 +66,7 @@
 ******************************************************************************/
 extern char rtkbt_transtype;
 extern void Heartbeat_cleanup();
+extern void Heartbeat_init();
 
 /******************************************************************************
 **  Local type definitions
@@ -88,6 +91,7 @@ typedef struct
 {
     int fd;                     /* fd to Bluetooth device */
     int uart_fd[2];
+    int signal_fd[2];
     int epoll_fd;
     int cpoll_fd;
     int event_fd;
@@ -108,13 +112,16 @@ typedef struct
 uint16_t btui_msbc_h2[] = {0x0801,0x3801,0xc801,0xf801};
 typedef struct
 {
-    pthread_mutex_t sco_mutex;
-    pthread_cond_t  sco_cond;
+    pthread_mutex_t sco_recv_mutex;
+    pthread_cond_t  sco_recv_cond;
+    pthread_mutex_t sco_send_mutex;
     pthread_t thread_socket_sco_id;
     pthread_t thread_recv_sco_id;
     pthread_t thread_send_sco_id;
     uint16_t  sco_handle;
     bool thread_sco_running;
+    bool thread_recv_sco_running;
+    bool thread_send_sco_running;
     uint16_t voice_settings;
     RTB_QUEUE_HEAD *recv_sco_data;
     RTB_QUEUE_HEAD *send_sco_data;
@@ -125,6 +132,7 @@ typedef struct
     int ctrl_fd, data_fd;
     sbc_t sbc_dec, sbc_enc;
     uint32_t pcm_enc_seq;
+    int signal_fd[2];
 }sco_cb_t;
 #endif
 
@@ -158,10 +166,12 @@ static int coex_resvered_length = 0;
 
 #ifdef RTK_HANDLE_EVENT
 static int received_packet_state = RTKBT_PACKET_IDLE;
-static int received_packet_bytes_need = 0;
+static unsigned int received_packet_bytes_need = 0;
 static serial_data_type_t recv_packet_current_type = 0;
 static unsigned char received_resvered_header[2048] = {0};
 static int received_resvered_length = 0;
+static rtkbt_version_t rtkbt_version;
+static rtkbt_lescn_t  rtkbt_adv_con;
 #endif
 
 static rtk_parse_manager_t * rtk_parse_manager = NULL;
@@ -272,6 +282,8 @@ void userial_ioctl_init_bt_wake(int fd)
 *******************************************************************************/
 void userial_vendor_init(char *bt_device_node)
 {
+    memset(&rtkbt_adv_con, 0, sizeof(rtkbt_lescn_t));
+    memset(&vnd_userial, 0, sizeof(vnd_userial_cb_t));
     vnd_userial.fd = -1;
     char value[100];
     snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", \
@@ -281,7 +293,7 @@ void userial_vendor_init(char *bt_device_node)
         h5_int_interface->h5_int_init(&h5_int_callbacks);
     }
     rtk_parse_manager = NULL;
-    property_get("persist.bluetooth.rtkcoex", value, "true");
+    property_get("persist.vendor.bluetooth.rtkcoex", value, "true");
     if(strncmp(value, "true", 4) == 0) {
         rtk_parse_manager = rtk_parse_manager_get_interface();
         rtk_parse_manager->rtk_parse_init();
@@ -289,15 +301,33 @@ void userial_vendor_init(char *bt_device_node)
     vnd_userial.data_order = RtbQueueInit();
     vnd_userial.recv_data = RtbQueueInit();
     vnd_userial.send_data = RtbQueueInit();
+
+    //reset coex gloable variables
+    coex_packet_recv_state = RTKBT_PACKET_IDLE;
+    coex_packet_bytes_need = 0;
+    coex_current_type = 0;
+    coex_resvered_length = 0;
+
+#ifdef RTK_HANDLE_EVENT
+    //reset handle event gloable variables
+    received_packet_state = RTKBT_PACKET_IDLE;
+    received_packet_bytes_need = 0;
+    recv_packet_current_type = 0;
+    received_resvered_length = 0;
+#endif
+
 #ifdef CONFIG_SCO_OVER_HCI
     sco_cb.recv_sco_data = RtbQueueInit();
     sco_cb.send_sco_data = RtbQueueInit();
-    pthread_mutex_init(&sco_cb.sco_mutex, NULL);
-    pthread_cond_init(&sco_cb.sco_cond, NULL);
+    pthread_mutex_init(&sco_cb.sco_recv_mutex, NULL);
+    pthread_cond_init(&sco_cb.sco_recv_cond, NULL);
+    pthread_mutex_init(&sco_cb.sco_send_mutex, NULL);
     memset(&sco_cb.sbc_enc, 0, sizeof(sbc_t));
-    sbc_init(&sco_cb.sbc_enc);//sbc_init(&sco_cb.sbc_enc, 0);
+    sbc_init_msbc(&sco_cb.sbc_enc, 0L);
+    sco_cb.sbc_enc.endian = SBC_LE;
     memset(&sco_cb.sbc_dec, 0, sizeof(sbc_t));
-    sbc_init(&sco_cb.sbc_dec);//sbc_init(&sco_cb.sbc_enc, 0);
+    sbc_init_msbc(&sco_cb.sbc_dec, 0L);
+    sco_cb.sbc_dec.endian = SBC_LE;
 #endif
 }
 
@@ -414,28 +444,43 @@ static void userial_socket_close(void)
 {
     int result;
 
-    if ((result = close(vnd_userial.uart_fd[0])) < 0)
+    if ((vnd_userial.uart_fd[0] > 0) && (result = close(vnd_userial.uart_fd[0])) < 0)
         ALOGE( "%s (fd:%d) FAILED result:%d", __func__, vnd_userial.uart_fd[0], result);
 
     if (epoll_ctl(vnd_userial.epoll_fd, EPOLL_CTL_DEL, vnd_userial.uart_fd[1], NULL) == -1)
       ALOGE("%s unable to unregister fd %d from epoll set: %s", __func__, vnd_userial.uart_fd[1], strerror(errno));
 
-    if ((result = close(vnd_userial.uart_fd[1])) < 0)
+    if (epoll_ctl(vnd_userial.epoll_fd, EPOLL_CTL_DEL, vnd_userial.signal_fd[1], NULL) == -1)
+      ALOGE("%s unable to unregister signal fd %d from epoll set: %s", __func__, vnd_userial.signal_fd[1], strerror(errno));
+
+    if ((vnd_userial.uart_fd[1] > 0) && (result = close(vnd_userial.uart_fd[1])) < 0)
         ALOGE( "%s (fd:%d) FAILED result:%d", __func__, vnd_userial.uart_fd[1], result);
 
-    pthread_join(vnd_userial.thread_socket_id, NULL);
-    close(vnd_userial.epoll_fd);
+    if(vnd_userial.thread_socket_id != -1)
+        pthread_join(vnd_userial.thread_socket_id, NULL);
+
+    if(vnd_userial.epoll_fd > 0)
+        close(vnd_userial.epoll_fd);
+
+    if ((vnd_userial.signal_fd[0] > 0) && (result = close(vnd_userial.signal_fd[0])) < 0)
+        ALOGE( "%s (signal fd[0]:%d) FAILED result:%d", __func__, vnd_userial.signal_fd[0], result);
+    if ((vnd_userial.signal_fd[1] > 0) && (result = close(vnd_userial.signal_fd[1])) < 0)
+        ALOGE( "%s (signal fd[1]:%d) FAILED result:%d", __func__, vnd_userial.signal_fd[1], result);
+
     vnd_userial.epoll_fd = -1;
     vnd_userial.uart_fd[0] = -1;
     vnd_userial.uart_fd[1] = -1;
+    vnd_userial.signal_fd[0] = -1;
+    vnd_userial.signal_fd[1] = -1;
 }
 
 static void userial_uart_close(void)
 {
     int result;
-    if ((result = close(vnd_userial.fd)) < 0)
+    if ((vnd_userial.fd > 0) && (result = close(vnd_userial.fd)) < 0)
         ALOGE( "%s (fd:%d) FAILED result:%d", __func__, vnd_userial.fd, result);
-    pthread_join(vnd_userial.thread_uart_id, NULL);
+    if(vnd_userial.thread_uart_id != -1)
+      pthread_join(vnd_userial.thread_uart_id, NULL);
 }
 
 static void userial_coex_close(void)
@@ -443,17 +488,27 @@ static void userial_coex_close(void)
     int result;
 
     if (epoll_ctl(vnd_userial.cpoll_fd, EPOLL_CTL_DEL, vnd_userial.event_fd, NULL) == -1)
-      ALOGE("%s unable to unregister fd %d from epoll set: %s", __func__, vnd_userial.event_fd, strerror(errno));
+      ALOGE("%s unable to unregister fd %d from cpoll set: %s", __func__, vnd_userial.event_fd, strerror(errno));
+
+    if (epoll_ctl(vnd_userial.cpoll_fd, EPOLL_CTL_DEL, vnd_userial.signal_fd[1], NULL) == -1)
+      ALOGE("%s unable to unregister fd %d from cpoll set: %s", __func__, vnd_userial.signal_fd[1], strerror(errno));
 
     if ((result = close(vnd_userial.event_fd)) < 0)
         ALOGE( "%s (fd:%d) FAILED result:%d", __func__, vnd_userial.event_fd, result);
 
     close(vnd_userial.cpoll_fd);
-    pthread_join(vnd_userial.thread_coex_id, NULL);
+    if(vnd_userial.thread_coex_id != -1)
+      pthread_join(vnd_userial.thread_coex_id, NULL);
     vnd_userial.cpoll_fd = -1;
     vnd_userial.event_fd = -1;
 }
 
+void userial_send_close_signal(void)
+{
+    unsigned char close_signal = 1;
+    ssize_t ret;
+    RTK_NO_INTR(ret = write(vnd_userial.signal_fd[0], &close_signal, 1));
+}
 
 /*******************************************************************************
 **
@@ -466,20 +521,38 @@ static void userial_coex_close(void)
 *******************************************************************************/
 void userial_vendor_close(void)
 {
-    //int result;
-    RTK_btservice_destroyed();
     if (vnd_userial.fd == -1)
         return;
 
+    if((rtkbt_transtype & RTKBT_TRANS_UART) && (rtkbt_transtype & RTKBT_TRANS_H5)) {
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+        /* de-assert bt_wake BEFORE closing port */
+        ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL);
+#endif
+        //h5_int_interface->h5_int_cleanup();
 
+    }
 
     vnd_userial.thread_running = false;
-
-    userial_socket_close();
+#ifdef CONFIG_SCO_OVER_HCI
+    if(sco_cb.thread_sco_running) {
+        sco_cb.thread_sco_running = false;
+        unsigned char close_signal = 1;
+        ssize_t ret;
+        RTK_NO_INTR(ret = write(sco_cb.signal_fd[0], &close_signal, 1));
+        pthread_join(sco_cb.thread_socket_sco_id, NULL);
+    }
+#endif
+    Heartbeat_cleanup();
+    RTK_btservice_destroyed();
+    userial_send_close_signal();
     userial_uart_close();
     userial_coex_close();
-    Heartbeat_cleanup();
-    
+    userial_socket_close();
+
+    if((rtkbt_transtype & RTKBT_TRANS_UART) && (rtkbt_transtype & RTKBT_TRANS_H5)) {
+        h5_int_interface->h5_int_cleanup();
+    }
 
     vnd_userial.fd = -1;
     vnd_userial.btdriver_state = false;
@@ -491,14 +564,7 @@ void userial_vendor_close(void)
     sbc_finish(&sco_cb.sbc_enc);
     sbc_finish(&sco_cb.sbc_dec);
 #endif
-    if((rtkbt_transtype & RTKBT_TRANS_UART) && (rtkbt_transtype & RTKBT_TRANS_H5)) {
-#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
-        /* de-assert bt_wake BEFORE closing port */
-        ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL);
-#endif
-        h5_int_interface->h5_int_cleanup();
-
-    }
+    ALOGD( "%s finish", __func__);
 }
 
 /*******************************************************************************
@@ -539,10 +605,7 @@ void userial_vendor_set_baud(uint8_t userial_baud)
 *******************************************************************************/
 void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data)
 {
-       if(p_data == NULL)
-       {
-               VNDUSERIALDBG("p_data is null");
-       }
+    RTK_UNUSED(p_data);
     switch(op)
     {
 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
@@ -578,10 +641,8 @@ void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data)
 *******************************************************************************/
 int userial_set_port(char *p_conf_name, char *p_conf_value, int param)
 {
-       if(p_conf_name == NULL || param == 0)
-       {
-               VNDUSERIALDBG("p_conf_name is null");
-       }
+    RTK_UNUSED(p_conf_name);
+    RTK_UNUSED(param);
     strcpy(vnd_userial.port_name, p_conf_value);
 
     return 0;
@@ -689,6 +750,40 @@ static void userial_enqueue_coex_rawdata(unsigned char * buffer, int length, boo
     }
 }
 
+static void userial_send_cmd_to_controller(unsigned char * recv_buffer, int total_length)
+{
+    if(rtkbt_transtype & RTKBT_TRANS_H4) {
+        h4_int_transmit_data(recv_buffer, total_length);
+    }
+    else {
+        h5_int_interface->h5_send_cmd(DATA_TYPE_COMMAND, &recv_buffer[1], (total_length - 1));
+    }
+    userial_enqueue_coex_rawdata(recv_buffer, total_length, false);
+}
+
+static void userial_send_acl_to_controller(unsigned char * recv_buffer, int total_length)
+{
+    if(rtkbt_transtype & RTKBT_TRANS_H4) {
+        h4_int_transmit_data(recv_buffer, total_length);
+    }
+    else {
+        h5_int_interface->h5_send_acl_data(DATA_TYPE_ACL, &recv_buffer[1], (total_length - 1));
+    }
+    userial_enqueue_coex_rawdata(recv_buffer, total_length, false);
+}
+
+static void userial_send_sco_to_controller(unsigned char * recv_buffer, int total_length)
+{
+    if(rtkbt_transtype & RTKBT_TRANS_H4) {
+        h4_int_transmit_data(recv_buffer, total_length);
+    }
+    else {
+        h5_int_interface->h5_send_sco_data(DATA_TYPE_SCO, &recv_buffer[1], (total_length - 1));
+    }
+    userial_enqueue_coex_rawdata(recv_buffer, total_length, false);
+}
+
+
 static int userial_coex_recv_data_handler(unsigned char * recv_buffer, int total_length)
 {
     serial_data_type_t type = 0;
@@ -778,8 +873,10 @@ static int userial_coex_recv_data_handler(unsigned char * recv_buffer, int total
             //fall through
 
         case RTKBT_PACKET_END:
+        {
             len = BT_HC_HDR_SIZE + coex_resvered_length;
-            p_buf = (HC_BT_HDR *) malloc(len);
+            uint8_t packet[len];
+            p_buf = (HC_BT_HDR *) packet;
             p_buf->offset = 0;
             p_buf->layer_specific = 0;
             p_buf->len = coex_resvered_length;
@@ -797,10 +894,8 @@ static int userial_coex_recv_data_handler(unsigned char * recv_buffer, int total
                     acl_length = *(uint16_t *)&coex_resvered_buffer[2];
                     l2cap_length = *(uint16_t *)&coex_resvered_buffer[4];
                     boundary_flag = RTK_GET_BOUNDARY_FLAG(handle);
-                    if (boundary_flag == RTK_START_PACKET_BOUNDARY) {
-                        if(rtk_parse_manager)
-                            rtk_parse_manager->rtk_parse_l2cap_data(coex_resvered_buffer, 0);
-                    }
+                    if(rtk_parse_manager)
+                        rtk_parse_manager->rtk_parse_l2cap_data(coex_resvered_buffer, 0);
                 break;
 
                 case DATA_TYPE_SCO:
@@ -812,7 +907,7 @@ static int userial_coex_recv_data_handler(unsigned char * recv_buffer, int total
                 break;
             }
             rtk_btsnoop_capture(p_buf, true);
-            free(p_buf);
+        }
         break;
 
         default:
@@ -838,7 +933,8 @@ static void userial_coex_send_data_handler(unsigned char * send_buffer, int tota
     uint16_t len, handle, acl_length, l2cap_length;
 
     len = BT_HC_HDR_SIZE + (length - 1);
-    p_buf = (HC_BT_HDR *) malloc(len);
+    uint8_t packet[len];
+    p_buf = (HC_BT_HDR *) packet;
     p_buf->offset = 0;
     p_buf->layer_specific = 0;
     p_buf->len = total_length -1;
@@ -857,10 +953,8 @@ static void userial_coex_send_data_handler(unsigned char * send_buffer, int tota
             acl_length = *(uint16_t *)&send_buffer[3];
             l2cap_length = *(uint16_t *)&send_buffer[5];
             boundary_flag = RTK_GET_BOUNDARY_FLAG(handle);
-            if (boundary_flag == RTK_START_PACKET_BOUNDARY) {
-                if(rtk_parse_manager)
-                    rtk_parse_manager->rtk_parse_l2cap_data(&send_buffer[1], 1);
-            }
+            if(rtk_parse_manager)
+                rtk_parse_manager->rtk_parse_l2cap_data(&send_buffer[1], 1);
 
         break;
 
@@ -873,11 +967,11 @@ static void userial_coex_send_data_handler(unsigned char * send_buffer, int tota
         break;
     }
     rtk_btsnoop_capture(p_buf, false);
-    free(p_buf);
 }
 
-static void userial_coex_handler()//(void *context)
+static void userial_coex_handler(void *context)
 {
+    RTK_UNUSED(context);
     RTK_BUFFER* skb_data;
     RTK_BUFFER* skb_type;
     eventfd_t value;
@@ -915,16 +1009,18 @@ static void userial_coex_handler()//(void *context)
 }
 
 #ifdef CONFIG_SCO_OVER_HCI
-//receive sco encode data over hci, we need to decode msbc data to pcm, and send it to sco audio hal
-static void* userial_recv_sco_thread()//(void *arg)
+//receive sco encode or non-encode data over hci, we need to decode msbc data to pcm, and send it to sco audio hal
+static void* userial_recv_sco_thread(void *arg)
 {
+    RTK_UNUSED(arg);
     RTK_BUFFER* skb_sco_data;
     unsigned char dec_data[480];
     unsigned char pcm_data[960];
     int index = 0;
     //uint16_t sco_packet_len = 60;
     uint8_t * p_data = NULL;
-    int res = 0, writen = 0;
+    int res = 0;
+    size_t writen = 0;
     prctl(PR_SET_NAME, (unsigned long)"userial_recv_sco_thread", 0, 0, 0);
     /*
     FILE *file;
@@ -937,18 +1033,34 @@ static void* userial_recv_sco_thread()//(void *arg)
         return NULL;
     }
     */
-    RtbEmptyQueue(sco_cb.recv_sco_data);
+    //RtbEmptyQueue(sco_cb.recv_sco_data);
+    pthread_mutex_lock(&sco_cb.sco_recv_mutex);
+    while(RtbGetQueueLen(sco_cb.recv_sco_data) > 60) {
+        RTK_BUFFER* sco_data = RtbDequeueHead(sco_cb.recv_sco_data);
+        if(sco_data)
+        RtbFree(sco_data);
+    }
+    pthread_mutex_unlock(&sco_cb.sco_recv_mutex);
+
     ALOGE("userial_recv_sco_thread start");
-    while(sco_cb.thread_sco_running) {
-        pthread_mutex_lock(&sco_cb.sco_mutex);
+    while(sco_cb.thread_recv_sco_running) {
+        pthread_mutex_lock(&sco_cb.sco_recv_mutex);
         while(RtbQueueIsEmpty(sco_cb.recv_sco_data) && sco_cb.thread_sco_running) {
-            pthread_cond_wait(&sco_cb.sco_cond, &sco_cb.sco_mutex);
+            pthread_cond_wait(&sco_cb.sco_recv_cond, &sco_cb.sco_recv_mutex);
         }
-        pthread_mutex_unlock(&sco_cb.sco_mutex);
+        pthread_mutex_unlock(&sco_cb.sco_recv_mutex);
         skb_sco_data = RtbDequeueHead(sco_cb.recv_sco_data);
         if(!skb_sco_data)
           continue;
         p_data = skb_sco_data->Data;
+
+        if(!sco_cb.msbc_used) {
+            res = Skt_Send_noblock(sco_cb.data_fd, p_data, sco_cb.sco_packet_len);
+            if(res < 0) {
+                ALOGE("userial_recv_sco_thread, send noblock error");
+            }
+        }
+        else {
         //if (fwrite(skb_sco_data->Data, 1, 60, file) != 60) {
             //ALOGE("Error capturing sample");
         //}
@@ -964,19 +1076,20 @@ static void* userial_recv_sco_thread()//(void *arg)
             }
         }
         */
-        res = sbc_decode(&sco_cb.sbc_dec, (p_data+2), 58, dec_data, 240, &writen);
-        if(res > 0) {
-            memcpy(&pcm_data[240 * index], dec_data, 240);
-            //if (fwrite(dec_data, 240, 1, file2) != 240) {
+            res = sbc_decode(&sco_cb.sbc_dec, (p_data+2), 58, dec_data, 240, &writen);
+            if(res > 0) {
+                memcpy(&pcm_data[240 * index], dec_data, 240);
+                //if (fwrite(dec_data, 240, 1, file2) != 240) {
                     //ALOGE("Error capturing sample");
-            //}
-            index = (index + 1) % 4;
-            if(index == 0) {
-                Skt_Send_noblock(sco_cb.data_fd, pcm_data, 960);
+                //}
+                index = (index + 1) % 4;
+                if(index == 0) {
+                    Skt_Send_noblock(sco_cb.data_fd, pcm_data, 960);
+                }
+            }
+            else {
+                ALOGE("msbc decode fail!");
             }
-        }
-        else {
-            ALOGE("msbc decode fail!");
         }
         RtbFree(skb_sco_data);
     }
@@ -985,10 +1098,11 @@ static void* userial_recv_sco_thread()//(void *arg)
     return NULL;
 }
 
-static void* userial_send_sco_thread()//(void *arg)
+static void* userial_send_sco_thread(void *arg)
 {
+    RTK_UNUSED(arg);
     unsigned char enc_data[240];
-    unsigned char pcm_data[960];
+    unsigned char pcm_data[960 * 2];
     unsigned char send_data[100];
     int writen = 0;
     int num_read;
@@ -1004,63 +1118,134 @@ static void* userial_send_sco_thread()//(void *arg)
         return NULL;
     }
     */
+    //when start sco send thread, first send 6 sco data to controller
+    if(!sco_cb.msbc_used) {
+        memset(pcm_data, 0, (48*6));
+        for(i = 0; i < 6; i++) {
+            send_data[0] = DATA_TYPE_SCO;
+            send_data[3] = 48;
+            *(uint16_t *)&send_data[1] = sco_cb.sco_handle;
+            memcpy(&send_data[4], &pcm_data[i*48], 48);
+            userial_send_sco_to_controller(send_data, 52);
+        }
+    }
     ALOGE("userial_send_sco_thread start");
-    while(sco_cb.thread_sco_running) {
-        num_read = Skt_Read(sco_cb.data_fd, pcm_data, 960 * 2);
+    while(sco_cb.thread_send_sco_running) {
+        if(!sco_cb.msbc_used) {
+            num_read = Skt_Read(sco_cb.data_fd, pcm_data, 48 * 5, &sco_cb.thread_send_sco_running);
+            if(!num_read)
+                continue;
+            for(i = 0; i < 5; i++) {
+                send_data[0] = DATA_TYPE_SCO;
+                send_data[3] = 48;
+                *(uint16_t *)&send_data[1] = sco_cb.sco_handle;
+                memcpy(&send_data[4], &pcm_data[i*48], 48);
+                userial_send_sco_to_controller(send_data, 52);
+            }
+        }
+        else {
+            num_read = Skt_Read(sco_cb.data_fd, pcm_data, 960, &sco_cb.thread_send_sco_running);
         /*
         for(i = 0; i < 5; i ++) {
             if(fread(&enc_data[4], 1, 48, file) > 0) {
                 enc_data[0] = DATA_TYPE_SCO;
                 enc_data[3] = 48;
                 *(uint16_t *)&enc_data[1] = sco_cb.sco_handle;
-                h4_int_transmit_data(enc_data, 52);
+                userial_send_sco_to_controller(enc_data, 52);
             }
             else {
             fseek(file, 0L, SEEK_SET);
             }
         }
-        userial_enqueue_coex_rawdata(enc_data,52, false);
         //usleep(7500);
         continue;
         */
-        for(i = 0; i < 4; i++) {
-            if(sbc_encode(&sco_cb.sbc_enc, &pcm_data[240*i], 240, &enc_data[i*60 +2], 58, &writen) <= 0) {
-                ALOGE("sbc encode error!");
+            if(!num_read)
+                continue;
+            for(i = 0; i < 4; i++) {
+                if(sbc_encode(&sco_cb.sbc_enc, &pcm_data[240*i], 240, &enc_data[i*60 +2], 58, (ssize_t *)&writen) <= 0) {
+                    ALOGE("sbc encode error!");
+                }
+                else {
+                    *(uint16_t*)(&(enc_data[i*60])) = btui_msbc_h2[sco_cb.pcm_enc_seq % 4];
+                    sco_cb.pcm_enc_seq++;
+                    enc_data[i*60 + 59] = 0x00;    //padding
+                }
             }
-            else {
-                *(uint16_t*)(&(enc_data[i*60])) = btui_msbc_h2[sco_cb.pcm_enc_seq % 4];
-                sco_cb.pcm_enc_seq++;
-                enc_data[i*60 + 59] = 0x00;    //padding
+            for(i = 0; i < 5; i++) {
+                send_data[0] = DATA_TYPE_SCO;
+                send_data[3] = 48;
+                *(uint16_t *)&send_data[1] = sco_cb.sco_handle;
+                memcpy(&send_data[4], &enc_data[i*48], 48);
+                userial_send_sco_to_controller(send_data, 52);
             }
         }
-        for(i = 0; i < 5; i++) {
-            send_data[0] = DATA_TYPE_SCO;
-            send_data[3] = 48;
-            *(uint16_t *)&send_data[1] = sco_cb.sco_handle;
-            memcpy(&send_data[4], &enc_data[i*48], 48);
-            h4_int_transmit_data(send_data, 52);
-            userial_enqueue_coex_rawdata(enc_data, 52, false);
-        }
     }
     ALOGE("userial_send_sco_thread exit");
     return NULL;
 }
 
+static void userial_sco_send_socket_stop()
+{
+    ALOGE("%s", __func__);
+    pthread_mutex_lock(&sco_cb.sco_send_mutex);
+    if(sco_cb.thread_send_sco_running) {
+        sco_cb.thread_send_sco_running = false;
+    }
+    else {
+        pthread_mutex_unlock(&sco_cb.sco_send_mutex);
+        return;
+    }
+    pthread_mutex_unlock(&sco_cb.sco_send_mutex);
+
+    if(sco_cb.thread_send_sco_id != -1) {
+        pthread_join(sco_cb.thread_send_sco_id, NULL);
+        sco_cb.thread_send_sco_id = -1;
+    }
+}
+
+static void userial_sco_recv_socket_stop()
+{
+    ALOGE("%s", __func__);
+    pthread_mutex_lock(&sco_cb.sco_recv_mutex);
+    if(sco_cb.thread_recv_sco_running) {
+        sco_cb.thread_recv_sco_running = false;
+        pthread_cond_signal(&sco_cb.sco_recv_cond);
+    }
+    else {
+        pthread_mutex_unlock(&sco_cb.sco_recv_mutex);
+        return;
+
+    }
+    pthread_mutex_unlock(&sco_cb.sco_recv_mutex);
+
+    if(sco_cb.thread_recv_sco_id != -1) {
+        pthread_join(sco_cb.thread_recv_sco_id, NULL);
+        sco_cb.thread_recv_sco_id = -1;
+    }
+
+}
+
 static void userial_sco_socket_stop()
 {
-    sco_cb.thread_sco_running = false;
-    pthread_mutex_lock(&sco_cb.sco_mutex);
-    pthread_cond_signal(&sco_cb.sco_cond);
-    pthread_mutex_unlock(&sco_cb.sco_mutex);
-    pthread_join(sco_cb.thread_socket_sco_id, NULL);
-    pthread_join(sco_cb.thread_recv_sco_id, NULL);
-    pthread_join(sco_cb.thread_send_sco_id, NULL);
+    ALOGE("%s", __func__);
+    userial_sco_send_socket_stop();
+    userial_sco_recv_socket_stop();
+    if(sco_cb.ctrl_fd > 0) {
+        close(sco_cb.ctrl_fd);
+        sco_cb.ctrl_fd = -1;
+    }
+    if(sco_cb.data_fd > 0) {
+        close(sco_cb.data_fd);
+        sco_cb.data_fd = -1;
+    }
+    RtbEmptyQueue(sco_cb.recv_sco_data);
 }
 
 static void userial_sco_ctrl_skt_handle()
 {
     uint8_t cmd = 0, ack = 0;;
-    int result = Skt_Read(sco_cb.ctrl_fd, &cmd, 1);
+    int result = Skt_Read(sco_cb.ctrl_fd, &cmd, 1, NULL);
 
     if(result == 0) {
         userial_sco_socket_stop();
@@ -1078,6 +1263,7 @@ static void userial_sco_ctrl_skt_handle()
             pthread_attr_t thread_attr;
             pthread_attr_init(&thread_attr);
             pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+            sco_cb.thread_send_sco_running = true;
             if(pthread_create(&sco_cb.thread_send_sco_id, &thread_attr, userial_send_sco_thread, NULL)!= 0 )
             {
                 ALOGE("pthread_create : %s", strerror(errno));
@@ -1090,6 +1276,7 @@ static void userial_sco_ctrl_skt_handle()
             pthread_attr_t thread_attr;
             pthread_attr_init(&thread_attr);
             pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+            sco_cb.thread_recv_sco_running = true;
             if(pthread_create(&sco_cb.thread_recv_sco_id, &thread_attr, userial_recv_sco_thread, NULL)!= 0 )
             {
                 ALOGE("pthread_create : %s", strerror(errno));
@@ -1098,6 +1285,11 @@ static void userial_sco_ctrl_skt_handle()
         break;
 
         case SCO_CTRL_CMD_OUT_STOP:
+            userial_sco_send_socket_stop();
+        break;
+
+        case SCO_CTRL_CMD_IN_STOP:
+            userial_sco_recv_socket_stop();
 
         break;
 
@@ -1116,63 +1308,110 @@ static void userial_sco_ctrl_skt_handle()
             }
         break;
 
+        case SCO_CTRL_CMD_CLOSE:
+            userial_sco_socket_stop();
+        break;
+
         default:
 
         break;
     }
 }
 
-static void* userial_socket_sco_thread()//(void *arg)
+static void* userial_socket_sco_thread(void *arg)
 {
+    RTK_UNUSED(arg);
     struct sockaddr_un addr, remote;
-    socklen_t alen, len = sizeof(struct sockaddr_un);
+    //socklen_t alen;
+    socklen_t len = sizeof(struct sockaddr_un);
     fd_set read_set, active_set;
     int result, max_fd;
     int s_ctrl = socket(AF_LOCAL, SOCK_STREAM, 0);
+    if(s_ctrl < 0) {
+        ALOGE("ctrl socket create fail");
+        return NULL;
+    }
     int s_data = socket(AF_LOCAL, SOCK_STREAM, 0);
+    if(s_data < 0) {
+        ALOGE("data socket create fail");
+        close(s_ctrl);
+        return NULL;
+    }
     prctl(PR_SET_NAME, (unsigned long)"userial_socket_sco_thread", 0, 0, 0);
 
+    if((socketpair(AF_UNIX, SOCK_STREAM, 0, sco_cb.signal_fd)) < 0) {
+        ALOGE("%s, errno : %s", __func__, strerror(errno));
+        goto socket_close;
+    }
+
     //bind sco ctrl socket
-    unlink(SCO_CTRL_PATH);
+    //unlink(SCO_CTRL_PATH);
+
+#if 0
     memset(&addr, 0, sizeof(addr));
     strcpy(addr.sun_path, SCO_CTRL_PATH);
-    addr.sun_family = AF_LOCAL;
+    addr.sun_family = AF_UNIX;
+    addr.sun_path[0] = 0;
     alen = strlen(addr.sun_path) + offsetof(struct sockaddr_un, sun_path);
     if (bind(s_ctrl, (struct sockaddr *)&addr, alen) < 0) {
         ALOGE("userial_socket_sco_thread, bind ctrl socket error : %s", strerror(errno));
         return NULL;
     }
+#else
+    if(socket_local_server_bind(s_ctrl, SCO_CTRL_PATH, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0)
+    {
+        ALOGE("ctrl socket failed to create (%s)", strerror(errno));
+        goto signal_close;
+    }
+#endif
 
     if(listen(s_ctrl, 5) < 0) {
         ALOGE("userial_socket_sco_thread, listen ctrl socket error : %s", strerror(errno));
-        return NULL;
+        goto signal_close;
     }
 
-    chmod(SCO_CTRL_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+    int res = chmod(SCO_CTRL_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+    if(res < 0) {
+        ALOGE("chmod ctrl path fail");
+    }
     //bind sco data socket
-    unlink(SCO_DATA_PATH);
+    //unlink(SCO_DATA_PATH);
+#if 0
     memset(&addr, 0, sizeof(addr));
     strcpy(addr.sun_path, SCO_DATA_PATH);
-    addr.sun_family = AF_LOCAL;
+    addr.sun_family = AF_UNIX;
+    addr.sun_path[0] = 0;
     alen = strlen(addr.sun_path) + offsetof(struct sockaddr_un, sun_path);
     if (bind(s_data, (struct sockaddr *)&addr, alen) < 0) {
         ALOGE("userial_socket_sco_thread, bind data socket error : %s", strerror(errno));
         return NULL;
     }
 
+#else
+    if(socket_local_server_bind(s_data, SCO_DATA_PATH, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0)
+    {
+        ALOGE("data socket failed to create (%s)", strerror(errno));
+        goto signal_close;
+    }
+
+#endif
     if(listen(s_data, 5) < 0) {
         ALOGE("userial_socket_sco_thread, listen data socket error : %s", strerror(errno));
-        return NULL;
+        goto signal_close;
+    }
+    res = chmod(SCO_DATA_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+    if(res < 0) {
+        ALOGE("chmod data path fail");
     }
-    chmod(SCO_DATA_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
 
     ALOGE("userial_socket_sco_thread");
     FD_ZERO(&read_set);
     FD_ZERO(&active_set);
     FD_SET(s_ctrl, &active_set);
     FD_SET(s_data, &active_set);
-    max_fd = (MAX(s_ctrl, s_data)) + 1;
-
+    FD_SET(sco_cb.signal_fd[1], &active_set);
+    max_fd = MAX(s_ctrl, s_data);
+    max_fd = MAX(max_fd, sco_cb.signal_fd[1]) + 1;
     while(sco_cb.thread_sco_running) {
         read_set = active_set;
         result = select(max_fd, &read_set, NULL, NULL, NULL);
@@ -1186,10 +1425,15 @@ static void* userial_socket_sco_thread()//(void *arg)
             continue;
         }
         if(FD_ISSET(s_ctrl, &read_set)) {
+            if(sco_cb.ctrl_fd > 0) {
+                ALOGE("Already has connect a control fd: %d", sco_cb.ctrl_fd);
+                FD_SET(sco_cb.ctrl_fd, &read_set);
+                close(sco_cb.ctrl_fd);
+            }
             RTK_NO_INTR(sco_cb.ctrl_fd = accept(s_ctrl, (struct sockaddr *)&remote, &len));
             if (sco_cb.ctrl_fd == -1) {
                 ALOGE("sock accept failed (%s)", strerror(errno));
-                return NULL;
+                continue;
             }
             const int size = (512);
             setsockopt(sco_cb.ctrl_fd, SOL_SOCKET, SO_RCVBUF, (char*)&size, (int)sizeof(size));
@@ -1198,22 +1442,43 @@ static void* userial_socket_sco_thread()//(void *arg)
         }
 
         if(FD_ISSET(s_data, &read_set)) {
+            if(sco_cb.data_fd > 0) {
+                ALOGE("Already has connect a control fd: %d", sco_cb.data_fd);
+                close(sco_cb.data_fd);
+            }
             RTK_NO_INTR(sco_cb.data_fd = accept(s_data, (struct sockaddr *)&remote, &len));
             if (sco_cb.data_fd == -1) {
-                ALOGE("sock accept failed (%s)", strerror(errno));
-                return NULL;
+                ALOGE("socket accept failed (%s)", strerror(errno));
+                continue;
             }
             const int size = (30 * 960);
             int ret = setsockopt(sco_cb.data_fd, SOL_SOCKET, SO_RCVBUF, (char*)&size, (int)sizeof(size));
             ret = setsockopt(sco_cb.data_fd, SOL_SOCKET, SO_SNDBUF, (char*)&size, (int)sizeof(size));
         }
 
-        if(FD_ISSET(sco_cb.ctrl_fd, &read_set)) {
+        if(sco_cb.ctrl_fd > 0 && FD_ISSET(sco_cb.ctrl_fd, &read_set)) {
             userial_sco_ctrl_skt_handle();
         }
     }
+
+    userial_sco_socket_stop();
+signal_close:
+    close(sco_cb.signal_fd[0]);
+    close(sco_cb.signal_fd[1]);
+socket_close:
     close(s_ctrl);
     close(s_data);
+
+    memset(&addr, 0, sizeof(addr));
+    strcpy((addr.sun_path + 1), SCO_DATA_PATH);
+    addr.sun_path[0] = 0;
+    unlink(addr.sun_path);
+
+    memset(&addr, 0, sizeof(addr));
+    strcpy((addr.sun_path + 1), SCO_CTRL_PATH);
+    addr.sun_path[0] = 0;
+    unlink(addr.sun_path);
+    ALOGE("userial_socket_sco_thread exit");
     return NULL;
 }
 
@@ -1222,29 +1487,60 @@ static void* userial_socket_sco_thread()//(void *arg)
 #ifdef RTK_HANDLE_CMD
 static void userial_handle_cmd(unsigned char * recv_buffer, int total_length)
 {
+    RTK_UNUSED(total_length);
     uint16_t opcode = *(uint16_t*)recv_buffer;
     uint16_t scan_int, scan_win;
     static uint16_t voice_settings;
-       if(total_length == 0)
-       {
-               ALOGE("total_length = %d", total_length);
-       }
-  //ALOGE("opcode = 0x%x",opcode);
+    char prop_value[100];
     switch (opcode) {
         case HCI_BLE_WRITE_SCAN_PARAMS :
             scan_int = *(uint16_t*)&recv_buffer[4];
             scan_win = *(uint16_t*)&recv_buffer[6];
-            //ALOGE("scan_int = %d, scan_win = %d",scan_int,scan_win);
-            if(scan_win > 0x10){
-                *(uint16_t*)&recv_buffer[4] = (scan_int * 0x10) / scan_win;
-                *(uint16_t*)&recv_buffer[6] = 0x10;
+            if(scan_win > 20){
+                if((scan_int/scan_win) > 2) {
+                  *(uint16_t*)&recv_buffer[4] = (scan_int * 20) / scan_win;
+                  *(uint16_t*)&recv_buffer[6] = 20;
+                }
+                else {
+                  *(uint16_t*)&recv_buffer[4] = 40;
+                  *(uint16_t*)&recv_buffer[6] = 20;
+                }
+            }
+            else if(scan_win == scan_int) {
+              *(uint16_t*)&recv_buffer[4] = (scan_int * 5) & 0xFE;
+            }
+            else if((scan_int/scan_win) <= 2) {
+              *(uint16_t*)&recv_buffer[4] = (scan_int * 3) & 0xFE;
             }
         break;
 
+        case HCI_LE_SET_EXTENDED_SCAN_PARAMETERS:
+            scan_int = *(uint16_t*)&recv_buffer[7];
+            scan_win = *(uint16_t*)&recv_buffer[9];
+            if(scan_win > 20){
+                if((scan_int/scan_win) > 2) {
+                    *(uint16_t*)&recv_buffer[7] = (scan_int * 20) / scan_win;
+                    *(uint16_t*)&recv_buffer[9] = 20;
+                }
+                else {
+                    *(uint16_t*)&recv_buffer[7] = 40;
+                    *(uint16_t*)&recv_buffer[9] = 20;
+                }
+            }
+            else if(scan_win == scan_int) {
+              *(uint16_t*)&recv_buffer[7] = (scan_int * 5) & 0xFE;
+            }
+            else if((scan_int/scan_win) <= 2) {
+              *(uint16_t*)&recv_buffer[9] = (scan_int * 3) & 0xFE;
+            }
+
+        break;
 
         case HCI_WRITE_VOICE_SETTINGS :
             voice_settings = *(uint16_t*)&recv_buffer[3];
-            userial_vendor_usb_ioctl(SET_ISO_CFG, &voice_settings);
+            if(rtkbt_transtype & RTKBT_TRANS_USB) {
+                userial_vendor_usb_ioctl(SET_ISO_CFG, &voice_settings);
+            }
 #ifdef CONFIG_SCO_OVER_HCI
             sco_cb.voice_settings = voice_settings;
 #endif
@@ -1252,16 +1548,70 @@ static void userial_handle_cmd(unsigned char * recv_buffer, int total_length)
 #ifdef CONFIG_SCO_OVER_HCI
         case HCI_SETUP_ESCO_CONNECTION :
             sco_cb.voice_settings = *(uint16_t*)&recv_buffer[15];
-            pthread_attr_t thread_attr;
-            pthread_attr_init(&thread_attr);
-            pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
-            sco_cb.thread_sco_running = true;
-            if(pthread_create(&sco_cb.thread_socket_sco_id, &thread_attr, userial_socket_sco_thread, NULL)!= 0 )
-            {
-                ALOGE("pthread_create : %s", strerror(errno));
-            }
+            sco_cb.ctrl_fd = -1;
+            sco_cb.data_fd = -1;
         break;
 #endif
+        case HCI_SET_EVENT_MASK:
+          ALOGE("set event mask, it should bt stack init, set coex bt on");
+          if(rtk_parse_manager) {
+              rtk_parse_manager->rtk_set_bt_on(1);
+          }
+          Heartbeat_init();
+        break;
+
+        case HCI_ACCEPT_CONNECTION_REQUEST:
+          property_get("persist.vendor.bluetooth.prefferedrole", prop_value, "none");
+          if(strcmp(prop_value, "none") != 0) {
+              int role = recv_buffer[9];
+              if(role == 0x01 && (strcmp(prop_value, "master") == 0))
+                recv_buffer[9] = 0x00;
+              else if(role == 0x00 && (strcmp(prop_value, "slave") == 0))
+                recv_buffer[9] = 0x01;
+          }
+        break;
+
+        case HCI_BLE_WRITE_ADV_PARAMS:
+        {
+            if(rtkbt_version.hci_version> HCI_PROTO_VERSION_4_2) {
+                break;
+            }
+            rtkbt_adv_con.adverting_type = recv_buffer[7];
+            property_get("persist.vendor.rtkbtadvdisable", prop_value, "false");
+            if(rtkbt_adv_con.adverting_type == 0x00 && (strcmp(prop_value, "true") == 0)) {
+                recv_buffer[7] = 0x03;
+                rtkbt_adv_con.adverting_type = 0x03;
+            }
+        }
+        break;
+        case HCI_BLE_WRITE_ADV_ENABLE:
+        {
+            if(rtkbt_version.hci_version > HCI_PROTO_VERSION_4_2) {
+                break;
+            }
+            if(recv_buffer[2] == 0x01) {
+                rtkbt_adv_con.adverting_start = TRUE;
+            }
+            else if(recv_buffer[2] == 0x00) {
+                rtkbt_adv_con.adverting_type = 0;
+                rtkbt_adv_con.adverting_enable = FALSE;
+                rtkbt_adv_con.adverting_start = FALSE;
+            }
+        }
+        break;
+        case HCI_BLE_CREATE_LL_CONN:
+          if(rtkbt_version.hci_version > HCI_PROTO_VERSION_4_2) {
+              break;
+          }
+          if(rtkbt_adv_con.adverting_enable &&
+            ((rtkbt_adv_con.adverting_type == 0x00) ||
+            (rtkbt_adv_con.adverting_type == 0x01) ||
+            (rtkbt_adv_con.adverting_type == 0x04))) {
+              uint8_t disable_adv_cmd[5] = {0x01, 0x0A, 0x20, 0x01, 0x00};
+              rtkbt_adv_con.adverting_enable = FALSE;
+              userial_send_cmd_to_controller(disable_adv_cmd, 5);
+          }
+        break;
         default:
         break;
     }
@@ -1271,8 +1621,9 @@ static void userial_handle_cmd(unsigned char * recv_buffer, int total_length)
 
 //This recv data from bt process. The data type only have ACL/SCO/COMMAND
 // direction  BT HOST ----> CONTROLLER
-static void userial_recv_H4_rawdata()//(void *context)
+static void userial_recv_H4_rawdata(void *context)
 {
+    RTK_UNUSED(context);
     serial_data_type_t type = 0;
     ssize_t bytes_read;
     uint16_t opcode;
@@ -1373,31 +1724,21 @@ static void userial_recv_H4_rawdata()//(void *context)
                             transmitted_length = h5_int_interface->h5_send_cmd(type, &h4_read_buffer[1], h4_read_length);
                         }
                     }
+                    userial_enqueue_coex_rawdata(h4_read_buffer,(h4_read_length + 1), false);
                 break;
 
                 case DATA_TYPE_ACL:
-                    if(rtkbt_transtype & RTKBT_TRANS_H4) {
-                        h4_int_transmit_data(h4_read_buffer, (h4_read_length + 1));
-                    }
-                    else {
-                        transmitted_length = h5_int_interface->h5_send_acl_data(type, &h4_read_buffer[1], h4_read_length);
-                    }
+                    userial_send_acl_to_controller(h4_read_buffer, (h4_read_length + 1));
                 break;
 
                 case DATA_TYPE_SCO:
-                    if(rtkbt_transtype & RTKBT_TRANS_H4) {
-                        h4_int_transmit_data(h4_read_buffer, (h4_read_length + 1));
-                    }
-                    else {
-                        transmitted_length = h5_int_interface->h5_send_sco_data(type, &h4_read_buffer[1], h4_read_length);
-                    }
+                    userial_send_sco_to_controller(h4_read_buffer, (h4_read_length + 1));
                 break;
                 default:
                     ALOGE("%s invalid data type: %d", __func__, current_type);
+                    userial_enqueue_coex_rawdata(h4_read_buffer,(h4_read_length + 1), false);
                 break;
             }
-
-            userial_enqueue_coex_rawdata(h4_read_buffer,(h4_read_length + 1), false);
         break;
 
         default:
@@ -1447,24 +1788,60 @@ done:;
 #ifdef RTK_HANDLE_EVENT
 static void userial_handle_event(unsigned char * recv_buffer, int total_length)
 {
+    RTK_UNUSED(total_length);
     uint8_t event;
     uint8_t *p_data = recv_buffer;
     event = p_data[0];
-    if(total_length == 0)
+    switch (event) {
+    case HCI_COMMAND_COMPLETE_EVT:
     {
-        ALOGD("total_length %d",total_length);
+        uint16_t opcode = *((uint16_t*)&p_data[3]);
+        uint8_t* stream = &p_data[6];
+        if(opcode == HCI_READ_LOCAL_VERSION_INFO) {
+            STREAM_TO_UINT8(rtkbt_version.hci_version, stream);
+            STREAM_TO_UINT16(rtkbt_version.hci_revision, stream);
+            STREAM_TO_UINT8(rtkbt_version.lmp_version, stream);
+            STREAM_TO_UINT16(rtkbt_version.manufacturer, stream);
+            STREAM_TO_UINT16(rtkbt_version.lmp_subversion, stream);
+        }
+        else if(opcode == HCI_BLE_WRITE_ADV_ENABLE){
+            if(rtkbt_version.hci_version > HCI_PROTO_VERSION_4_2) {
+                break;
+            }
+            if(rtkbt_adv_con.adverting_start &&(p_data[5] == HCI_SUCCESS)) {
+                rtkbt_adv_con.adverting_enable = TRUE;
+                rtkbt_adv_con.adverting_start = FALSE;
+            }
+        }
     }
+    break;
 #ifdef CONFIG_SCO_OVER_HCI
-    if(event == HCI_ESCO_CONNECTION_COMP_EVT) {
+    case HCI_ESCO_CONNECTION_COMP_EVT: {
         if(p_data[2] != 0) {
             sco_cb.thread_sco_running = false;
-            pthread_join(sco_cb.thread_recv_sco_id, NULL);
-            pthread_join(sco_cb.thread_send_sco_id, NULL);
+            sco_cb.thread_recv_sco_running = false;
+            sco_cb.thread_send_sco_running = false;
+            sco_cb.data_fd = -1;
+            sco_cb.ctrl_fd = -1;
         }
         else {
           sco_cb.sco_handle = *((uint16_t *)&p_data[3]);
+          pthread_attr_t thread_attr;
+          pthread_attr_init(&thread_attr);
+          pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+          sco_cb.thread_sco_running = true;
+          sco_cb.thread_recv_sco_running = false;
+          sco_cb.thread_send_sco_running = false;
+          sco_cb.data_fd = -1;
+          sco_cb.ctrl_fd = -1;
+          if(pthread_create(&sco_cb.thread_socket_sco_id, &thread_attr, userial_socket_sco_thread, NULL)!= 0 )
+          {
+              ALOGE("pthread_create : %s", strerror(errno));
+          }
+
+          RtbEmptyQueue(sco_cb.recv_sco_data);
           if(!(sco_cb.voice_settings & 0x0003)) {
-              sco_cb.sco_packet_len = 240;
+              sco_cb.sco_packet_len = 240;    //every 5 cvsd packets form a sco pcm data
               sco_cb.msbc_used = false;
           }
           else {
@@ -1476,18 +1853,32 @@ static void userial_handle_event(unsigned char * recv_buffer, int total_length)
 
         ALOGE("userial_handle_event sco_handle: %d",sco_cb.sco_handle);
     }
-    if(event == HCI_DISCONNECTION_COMP_EVT) {
+    break;
+
+    case HCI_DISCONNECTION_COMP_EVT: {
         if((*((uint16_t *)&p_data[3])) == sco_cb.sco_handle) {
             sco_cb.sco_handle = 0;
             sco_cb.msbc_used = false;
+            RtbEmptyQueue(sco_cb.recv_sco_data);
+            if(sco_cb.thread_sco_running) {
+                sco_cb.thread_sco_running = false;
+                unsigned char close_signal = 1;
+                ssize_t ret;
+                RTK_NO_INTR(ret = write(sco_cb.signal_fd[0], &close_signal, 1));
+            }
         }
     }
+    break;
 #endif
+    default :
+    break;
+  }
 }
 
 #ifdef CONFIG_SCO_OVER_HCI
-static void userial_enqueue_sco_data(unsigned char * recv_buffer, int total_length)
+static void userial_enqueue_recv_sco_data(unsigned char * recv_buffer, int total_length)
 {
+    RTK_UNUSED(total_length);
     uint16_t sco_handle;
     uint8_t sco_length;
     uint8_t *p_data = recv_buffer;
@@ -1496,22 +1887,21 @@ static void userial_enqueue_sco_data(unsigned char * recv_buffer, int total_leng
     sco_handle = *((uint16_t *)p_data);
     uint16_t current_pos = sco_cb.current_pos;
     uint16_t sco_packet_len = sco_cb.sco_packet_len;
-    if(total_length == 0)
-    {
-        ALOGD("total_length %d",total_length);
-    }
+
     if(sco_handle == sco_cb.sco_handle) {
         sco_length = p_data[SCO_PREAMBLE_SIZE - 1];
         p_data += SCO_PREAMBLE_SIZE;
+
         if(current_pos) {
             if((sco_packet_len - current_pos) <= sco_length) {
                 memcpy(&sco_cb.enc_data[current_pos], p_data, (sco_packet_len - current_pos));
                 skb_sco_data = RtbAllocate(sco_packet_len, 0);
                 memcpy(skb_sco_data->Data, sco_cb.enc_data, sco_packet_len);
-                pthread_mutex_lock(&sco_cb.sco_mutex);
+                RtbAddTail(skb_sco_data, sco_packet_len);
+                pthread_mutex_lock(&sco_cb.sco_recv_mutex);
                 RtbQueueTail(sco_cb.recv_sco_data, skb_sco_data);
-                pthread_cond_signal(&sco_cb.sco_cond);
-                pthread_mutex_unlock(&sco_cb.sco_mutex);
+                pthread_cond_signal(&sco_cb.sco_recv_cond);
+                pthread_mutex_unlock(&sco_cb.sco_recv_mutex);
 
                 sco_cb.current_pos = 0;
                 p_data += (sco_packet_len - current_pos);
@@ -1524,16 +1914,18 @@ static void userial_enqueue_sco_data(unsigned char * recv_buffer, int total_leng
             }
         }
 
+        //if use cvsd codec
         if(!sco_cb.msbc_used) {
             for(i = 0; i < (sco_length/sco_packet_len); i++) {
                 skb_sco_data = RtbAllocate(sco_packet_len, 0);
                 memcpy(skb_sco_data->Data, p_data + i*sco_packet_len, sco_packet_len);
+                RtbAddTail(skb_sco_data, sco_packet_len);
                 RtbQueueTail(sco_cb.recv_sco_data, skb_sco_data);
             }
             if((sco_length/sco_packet_len)) {
-                pthread_mutex_lock(&sco_cb.sco_mutex);
-                pthread_cond_signal(&sco_cb.sco_cond);
-                pthread_mutex_unlock(&sco_cb.sco_mutex);
+                pthread_mutex_lock(&sco_cb.sco_recv_mutex);
+                pthread_cond_signal(&sco_cb.sco_recv_cond);
+                pthread_mutex_unlock(&sco_cb.sco_recv_mutex);
             }
 
             i = (sco_length % sco_packet_len);
@@ -1544,6 +1936,8 @@ static void userial_enqueue_sco_data(unsigned char * recv_buffer, int total_leng
             }
             return;
         }
+
+        //use msbc codec
         for(i = 0; i < sco_length; i++) {
             if((p_data[i] == 0x01) && ((p_data[i+1] & 0x0f) == 0x08) && (p_data[i+2] == 0xAD)) {
               if((sco_length - i) < sco_packet_len) {
@@ -1555,10 +1949,11 @@ static void userial_enqueue_sco_data(unsigned char * recv_buffer, int total_leng
                   memcpy(sco_cb.enc_data, &p_data[i], sco_packet_len);   //complete msbc data
                   skb_sco_data = RtbAllocate(sco_packet_len, 0);
                   memcpy(skb_sco_data->Data, sco_cb.enc_data, sco_packet_len);
-                  pthread_mutex_lock(&sco_cb.sco_mutex);
+                  RtbAddTail(skb_sco_data, sco_packet_len);
+                  pthread_mutex_lock(&sco_cb.sco_recv_mutex);
                   RtbQueueTail(sco_cb.recv_sco_data, skb_sco_data);
-                  pthread_cond_signal(&sco_cb.sco_cond);
-                  pthread_mutex_unlock(&sco_cb.sco_mutex);
+                  pthread_cond_signal(&sco_cb.sco_recv_cond);
+                  pthread_mutex_unlock(&sco_cb.sco_recv_mutex);
 
                   sco_cb.current_pos = 0;
                   i += (sco_packet_len - 1);
@@ -1569,13 +1964,17 @@ static void userial_enqueue_sco_data(unsigned char * recv_buffer, int total_leng
 }
 #endif
 
-static int userial_handle_recv_data(unsigned char * recv_buffer, int total_length)
+static int userial_handle_recv_data(unsigned char * recv_buffer, unsigned int total_length)
 {
     serial_data_type_t type = 0;
     unsigned char * p_data = recv_buffer;
-    int length = total_length;
+    unsigned int length = total_length;
     uint8_t event;
 
+    if(!length){
+        ALOGE("%s, length is 0, return immediately", __func__);
+        return total_length;
+    }
     switch (received_packet_state) {
         case RTKBT_PACKET_IDLE:
             received_packet_bytes_need = 1;
@@ -1633,14 +2032,20 @@ static int userial_handle_recv_data(unsigned char * recv_buffer, int total_lengt
         case RTKBT_PACKET_CONTENT:
             if(recv_packet_current_type == DATA_TYPE_EVENT) {
                 event = received_resvered_header[0];
+
                 if(event == HCI_COMMAND_COMPLETE_EVT) {
-                    if(length >= 1) {
-                        *p_data = 1;
+                    if(received_resvered_length == 2) {
+                      if(length >= 1) {
+                          *p_data = 1;
+                      }
                     }
                 }
                 else if(event == HCI_COMMAND_STATUS_EVT) {
-                    if(length >= 2) {
-                        *(p_data + 1) = 1;
+                    if(received_resvered_length < 4) {
+                      unsigned int act_len = 4 - received_resvered_length;
+                      if(length >= act_len) {
+                          *(p_data + act_len -1) = 1;
+                      }
                     }
                 }
             }
@@ -1662,21 +2067,19 @@ static int userial_handle_recv_data(unsigned char * recv_buffer, int total_lengt
             //fall through
 
         case RTKBT_PACKET_END:
-#ifdef CONFIG_SCO_OVER_HCI
             switch (recv_packet_current_type) {
                 case DATA_TYPE_EVENT :
                     userial_handle_event(received_resvered_header, received_resvered_length);
                 break;
-
+#ifdef CONFIG_SCO_OVER_HCI
                 case DATA_TYPE_SCO :
-                    userial_enqueue_sco_data(received_resvered_header, received_resvered_length);
+                    userial_enqueue_recv_sco_data(received_resvered_header, received_resvered_length);
                 break;
-
+#endif
                 default :
 
                 break;
             }
-#endif
         break;
 
         default:
@@ -1696,8 +2099,12 @@ static int userial_handle_recv_data(unsigned char * recv_buffer, int total_lengt
 static void h5_data_ready_cb(serial_data_type_t type, unsigned int total_length)
 {
     unsigned char buffer[1028] = {0};
-    unsigned int length = 0;
+    int length = 0;
     length = h5_int_interface->h5_int_read_data(&buffer[1], total_length);
+    if(length == -1) {
+        ALOGE("%s, error read length", __func__);
+        assert(length != -1);
+    }
     buffer[0] = type;
     length++;
     uint16_t transmitted_length = 0;
@@ -1706,7 +2113,7 @@ static void h5_data_ready_cb(serial_data_type_t type, unsigned int total_length)
     unsigned int read_length = 0;
     do {
         read_length += userial_handle_recv_data(buffer + read_length, real_length - read_length);
-    }while(read_length < total_length);
+    }while(vnd_userial.thread_running && read_length < total_length);
 #endif
 
     while (length > 0) {
@@ -1742,10 +2149,9 @@ static void userial_recv_uart_rawdata(unsigned char *buffer, unsigned int total_
     unsigned int read_length = 0;
     do {
         read_length += userial_handle_recv_data(buffer + read_length, total_length - read_length);
-
     }while(read_length < total_length);
 #endif
-    while (length > 0) {
+    while (length > 0 && vnd_userial.thread_running) {
         ssize_t ret;
         RTK_NO_INTR(ret = write(vnd_userial.uart_fd[1], buffer + transmitted_length, length));
         switch (ret) {
@@ -1770,16 +2176,36 @@ done:;
 
 void userial_recv_rawdata_hook(unsigned char *buffer, unsigned int total_length)
 {
-    if(rtkbt_transtype & RTKBT_TRANS_H5) {
-      h5_int_interface->h5_recv_msg(buffer, total_length);
-    }
-    else {
-      userial_recv_uart_rawdata(buffer, total_length);
-    }
+      uint16_t transmitted_length = 0;
+      unsigned int real_length = total_length;
+
+      while (vnd_userial.thread_running && (total_length > 0)) {
+          ssize_t ret;
+          RTK_NO_INTR(ret = write(vnd_userial.uart_fd[1], buffer + transmitted_length, total_length));
+          switch (ret) {
+          case -1:
+              ALOGE("In %s, error writing to the uart serial port: %s", __func__, strerror(errno));
+              goto done;
+          case 0:
+              // If we wrote nothing, don't loop more because we
+              // can't go to infinity or beyond
+              goto done;
+          default:
+              transmitted_length += ret;
+              total_length -= ret;
+              break;
+          }
+      }
+  done:;
+      if(real_length && vnd_userial.thread_running)
+          userial_enqueue_coex_rawdata(buffer, real_length, true);
+      return;
+
 }
 
-static void* userial_recv_socket_thread()//(void *arg)
+static void* userial_recv_socket_thread(void *arg)
 {
+    RTK_UNUSED(arg);
     struct epoll_event events[64];
     int j;
     while(vnd_userial.thread_running) {
@@ -1787,6 +2213,7 @@ static void* userial_recv_socket_thread()//(void *arg)
         do{
             ret = epoll_wait(vnd_userial.epoll_fd, events, 32, 500);
         }while(vnd_userial.thread_running && ret == -1 && errno == EINTR);
+
         if (ret == -1) {
             ALOGE("%s error in epoll_wait: %s", __func__, strerror(errno));
         }
@@ -1802,27 +2229,41 @@ static void* userial_recv_socket_thread()//(void *arg)
             }
         }
     }
+    vnd_userial.thread_socket_id = -1;
     ALOGD("%s exit", __func__);
     return NULL;
 }
 
-static void* userial_recv_uart_thread()//(void *arg)
+static void* userial_recv_uart_thread(void *arg)
 {
-    struct pollfd pfd;
-    pfd.events = POLLIN|POLLHUP|POLLERR|POLLRDHUP;
-    pfd.fd = vnd_userial.fd;
+    RTK_UNUSED(arg);
+    struct pollfd pfd[2];
+    pfd[0].events = POLLIN|POLLHUP|POLLERR|POLLRDHUP;
+    pfd[0].fd = vnd_userial.signal_fd[1];
+    pfd[1].events = POLLIN|POLLHUP|POLLERR|POLLRDHUP;
+    pfd[1].fd = vnd_userial.fd;
     int ret;
     unsigned char read_buffer[2056] = {0};
     ssize_t bytes_read;
     while(vnd_userial.thread_running) {
         do{
-            ret = poll(&pfd, 1, 50);
+            ret = poll(pfd, 2, 500);
         }while(ret == -1 && errno == EINTR && vnd_userial.thread_running);
 
-        if (pfd.revents & POLLIN) {
+        //exit signal is always at first index
+        if(pfd[0].revents && !vnd_userial.thread_running) {
+            ALOGE("receive exit signal and stop thread ");
+            return NULL;
+        }
+
+        if (pfd[1].revents & POLLIN) {
             RTK_NO_INTR(bytes_read = read(vnd_userial.fd, read_buffer, sizeof(read_buffer)));
             if(!bytes_read)
                 continue;
+            if(bytes_read < 0) {
+                ALOGE("%s, read fail, error : %s", __func__, strerror(errno));
+                continue;
+            }
 
             if(rtkbt_transtype & RTKBT_TRANS_H5) {
                 h5_int_interface->h5_recv_msg(read_buffer, bytes_read);
@@ -1832,7 +2273,7 @@ static void* userial_recv_uart_thread()//(void *arg)
             }
         }
 
-        if (pfd.revents & (POLLERR|POLLHUP)) {
+        if (pfd[1].revents & (POLLERR|POLLHUP)) {
             ALOGE("%s poll error, fd : %d", __func__, vnd_userial.fd);
             vnd_userial.btdriver_state = false;
             close(vnd_userial.fd);
@@ -1844,12 +2285,14 @@ static void* userial_recv_uart_thread()//(void *arg)
             continue;
         }
     }
+    vnd_userial.thread_uart_id = -1;
     ALOGD("%s exit", __func__);
     return NULL;
 }
 
-static void* userial_coex_thread()//(void *arg)
+static void* userial_coex_thread(void *arg)
 {
+    RTK_UNUSED(arg);
     struct epoll_event events[64];
     int j;
     while(vnd_userial.thread_running) {
@@ -1872,6 +2315,7 @@ static void* userial_coex_thread()//(void *arg)
             }
         }
     }
+    vnd_userial.thread_coex_id = -1;
     ALOGD("%s exit", __func__);
     return NULL;
 }
@@ -1885,6 +2329,11 @@ int userial_socket_open()
         return ret;
     }
 
+    if((ret = socketpair(AF_UNIX, SOCK_STREAM, 0, vnd_userial.signal_fd)) < 0) {
+        ALOGE("%s, errno : %s", __func__, strerror(errno));
+        return ret;
+    }
+
     vnd_userial.epoll_fd = epoll_create(64);
     if (vnd_userial.epoll_fd == -1) {
         ALOGE("%s unable to create epoll instance: %s", __func__, strerror(errno));
@@ -1899,9 +2348,17 @@ int userial_socket_open()
     if (epoll_ctl(vnd_userial.epoll_fd, EPOLL_CTL_ADD, vnd_userial.uart_fd[1], &event) == -1) {
         ALOGE("%s unable to register fd %d to epoll set: %s", __func__, vnd_userial.uart_fd[1], strerror(errno));
         close(vnd_userial.epoll_fd);
+        vnd_userial.epoll_fd = -1;
         return -1;
     }
 
+    event.data.ptr = NULL;
+    if (epoll_ctl(vnd_userial.epoll_fd, EPOLL_CTL_ADD, vnd_userial.signal_fd[1], &event) == -1) {
+        ALOGE("%s unable to register signal fd %d to epoll set: %s", __func__, vnd_userial.signal_fd[1], strerror(errno));
+        close(vnd_userial.epoll_fd);
+        vnd_userial.epoll_fd = -1;
+        return -1;
+    }
     pthread_attr_t thread_attr;
     pthread_attr_init(&thread_attr);
     pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
@@ -1910,6 +2367,8 @@ int userial_socket_open()
     {
         ALOGE("pthread_create : %s", strerror(errno));
         close(vnd_userial.epoll_fd);
+        vnd_userial.epoll_fd = -1;
+        vnd_userial.thread_socket_id = -1;
         return -1;
     }
 
@@ -1920,6 +2379,7 @@ int userial_socket_open()
         close(vnd_userial.epoll_fd);
         vnd_userial.thread_running = false;
         pthread_join(vnd_userial.thread_socket_id, NULL);
+        vnd_userial.thread_socket_id = -1;
         return -1;
     }
 
@@ -1939,12 +2399,20 @@ int userial_socket_open()
             assert(false);
         }
 
+        event.data.ptr = NULL;
+        if (epoll_ctl(vnd_userial.cpoll_fd, EPOLL_CTL_ADD, vnd_userial.signal_fd[1], &event) == -1) {
+            ALOGE("%s unable to register fd %d to cpoll set: %s", __func__, vnd_userial.signal_fd[1], strerror(errno));
+            assert(false);
+        }
+
         if (pthread_create(&vnd_userial.thread_coex_id, &thread_attr, userial_coex_thread, NULL) !=0 )
         {
             ALOGE("pthread create  coex : %s", strerror(errno));
+            vnd_userial.thread_coex_id = -1;
             assert(false);
         }
     }
+
     ret = vnd_userial.uart_fd[0];
     return ret;
 }
@@ -1953,6 +2421,8 @@ int userial_vendor_usb_ioctl(int operation, void* param)
 {
     int retval;
     retval = ioctl(vnd_userial.fd, operation, param);
+    if(retval == -1)
+      ALOGE("%s: error: %d : %s", __func__,errno, strerror(errno));
     return retval;
 }
 
old mode 100644 (file)
new mode 100755 (executable)
index 87e3759..72b9a27
@@ -47,3 +47,15 @@ PRODUCT_COPY_FILES += \
        $(LOCAL_PATH)/Firmware/BT/rtl8822b_fw:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8822b_fw \
        $(LOCAL_PATH)/Firmware/BT/rtl8822bs_config:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8822bs_config \
        $(LOCAL_PATH)/Firmware/BT/rtl8822bs_fw:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8822bs_fw \
+       $(LOCAL_PATH)/Firmware/BT/rtl8822c_config:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8822c_config \
+       $(LOCAL_PATH)/Firmware/BT/rtl8822c_fw:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8822c_fw \
+       $(LOCAL_PATH)/Firmware/BT/rtl8822cs_config:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8822cs_config \
+       $(LOCAL_PATH)/Firmware/BT/rtl8822cs_fw:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8822cs_fw \
+       $(LOCAL_PATH)/Firmware/BT/rtl8761b_config:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8761b_config \
+       $(LOCAL_PATH)/Firmware/BT/rtl8761b_fw:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8761b_fw \
+       $(LOCAL_PATH)/Firmware/BT/rtl8761bt_config:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8761bt_config \
+       $(LOCAL_PATH)/Firmware/BT/rtl8761bt_fw:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8761bt_fw \
+       $(LOCAL_PATH)/Firmware/BT/rtl8725a_config:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8725a_config \
+       $(LOCAL_PATH)/Firmware/BT/rtl8725a_fw:$(TARGET_COPY_OUT_VENDOR)/firmware/rtl8725a_fw \
+
+
old mode 100644 (file)
new mode 100755 (executable)
index 7c30d0f..4b277cc
@@ -1,26 +1,31 @@
           FW           CUT     SVN     Coex
-rtl8761au8192ee_fw      D      19653   0006
-rtl8761au_fw            D      19653   0006
+rtl8761au8192ee_fw      D      20411   0007
+rtl8761au_fw            D      20411   0007
 rtl8723c_fw             B      16592   0700
 rtl8703cs_fw            C      17903   0a0a
-rtl8761aw8192eu_fw      D      19653   0006
+rtl8761aw8192eu_fw      D      20411   0007
 rtl8761at8812ae_fw      D      19653   0006
-rtl8723ds_fw            C      19297   1616
-rtl8703bs_fw            B      19297   1600
-rtl8822b_fw             C      19664   4b4b
-rtl8821cs_fw            B      19504   1616
-rtl8761at_fw            D      19653   0006
+rtl8723ds_fw            C      21291   2d2d
+rtl8761bt_fw            B      21430   0909
+rtl8703bs_fw            B      20010   1c00
+rtl8822b_fw             C      21253   6c6c
+rtl8821cs_fw            B      21209   3939
+rtl8761at_fw            D      20411   0007
+rtl8822c_fw             D      21479   0a0a
+rtl8761b_fw             B      21475   0a0a
 rtl8761au8812ae_fw      D      19653   0006
 rtl8821as_fw            B      19132   635d
 rtl8821a_fw             B      19132   635d
-rtl8723bs_fw            B      19587   6b4e
-rtl8723b_fw             B      19587   6b4e
+rtl8723bs_fw            B      19897   6d50
+rtl8725a_fw             B      21430   0909
+rtl8723b_fw             B      19897   6d50
 rtl8723cs_vf_fw         B      15854   5844
 rtl8703as_fw            B      12234   473d
-rtl8723cs_xx_fw         B      19602   1600
-rtl8821c_fw             B      19504   1616
-rtl8822bs_fw            C      19664   4b4b
-rtl8723d_fw             C      19297   1616
+rtl8822cs_fw            D      21479   0a0a
+rtl8723cs_xx_fw         B      19927   1c00
+rtl8821c_fw             B      21209   3939
+rtl8822bs_fw            C      21253   6c6c
+rtl8723d_fw             C      21291   2d2d
 rtl8723cs_cg_fw         B      15854   5844
-rtl8761at8192ee_fw      D      19653   0006
+rtl8761at8192ee_fw      D      20411   0007
 rtl8723bs_VQ0_fw        B      16527   6549
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 8f3f660..517e52b
Binary files a/rtkbt/vendor/firmware/rtl8703bs_config and b/rtkbt/vendor/firmware/rtl8703bs_config differ
old mode 100644 (file)
new mode 100755 (executable)
index daa29e1..9c3c3ed
Binary files a/rtkbt/vendor/firmware/rtl8703bs_fw and b/rtkbt/vendor/firmware/rtl8703bs_fw differ
old mode 100644 (file)
new mode 100755 (executable)
index bd7a99e..4b26df2
Binary files a/rtkbt/vendor/firmware/rtl8703cs_config and b/rtkbt/vendor/firmware/rtl8703cs_config differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 69e4ef5..158aaef
Binary files a/rtkbt/vendor/firmware/rtl8723as_config and b/rtkbt/vendor/firmware/rtl8723as_config differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 57b5932..a242ddc
Binary files a/rtkbt/vendor/firmware/rtl8723b_config and b/rtkbt/vendor/firmware/rtl8723b_config differ
old mode 100644 (file)
new mode 100755 (executable)
index 40177db..e2fee21
Binary files a/rtkbt/vendor/firmware/rtl8723b_config_2Ant_S0 and b/rtkbt/vendor/firmware/rtl8723b_config_2Ant_S0 differ
old mode 100644 (file)
new mode 100755 (executable)
index 833b8a4..876211f
Binary files a/rtkbt/vendor/firmware/rtl8723b_fw and b/rtkbt/vendor/firmware/rtl8723b_fw differ
old mode 100644 (file)
new mode 100755 (executable)
index 95a56cd..567b3bc
Binary files a/rtkbt/vendor/firmware/rtl8723bs_VQ0_config and b/rtkbt/vendor/firmware/rtl8723bs_VQ0_config differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index d0e3370..e43f0b2
Binary files a/rtkbt/vendor/firmware/rtl8723bs_config and b/rtkbt/vendor/firmware/rtl8723bs_config differ
old mode 100644 (file)
new mode 100755 (executable)
index 6ad6f96..715af03
Binary files a/rtkbt/vendor/firmware/rtl8723bs_fw and b/rtkbt/vendor/firmware/rtl8723bs_fw differ
old mode 100644 (file)
new mode 100755 (executable)
index 40177db..e2fee21
Binary files a/rtkbt/vendor/firmware/rtl8723bu_config and b/rtkbt/vendor/firmware/rtl8723bu_config differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 0f507ed..517e52b
Binary files a/rtkbt/vendor/firmware/rtl8723cs_cg_config and b/rtkbt/vendor/firmware/rtl8723cs_cg_config differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 0f507ed..517e52b
Binary files a/rtkbt/vendor/firmware/rtl8723cs_vf_config and b/rtkbt/vendor/firmware/rtl8723cs_vf_config differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 9b46c87..517e52b
Binary files a/rtkbt/vendor/firmware/rtl8723cs_xx_config and b/rtkbt/vendor/firmware/rtl8723cs_xx_config differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index ed5d500..0f5f2f4
Binary files a/rtkbt/vendor/firmware/rtl8723d_fw and b/rtkbt/vendor/firmware/rtl8723d_fw differ
old mode 100644 (file)
new mode 100755 (executable)
index 6d81538..99475ee
Binary files a/rtkbt/vendor/firmware/rtl8723ds_config and b/rtkbt/vendor/firmware/rtl8723ds_config differ
old mode 100644 (file)
new mode 100755 (executable)
index 8891b1a..33c692a
Binary files a/rtkbt/vendor/firmware/rtl8723ds_fw and b/rtkbt/vendor/firmware/rtl8723ds_fw differ
diff --git a/rtkbt/vendor/firmware/rtl8725a_config b/rtkbt/vendor/firmware/rtl8725a_config
new file mode 100755 (executable)
index 0000000..91d3f44
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8725a_config differ
diff --git a/rtkbt/vendor/firmware/rtl8725a_fw b/rtkbt/vendor/firmware/rtl8725a_fw
new file mode 100755 (executable)
index 0000000..91758ef
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8725a_fw differ
old mode 100644 (file)
new mode 100755 (executable)
index 57b5932..a242ddc
Binary files a/rtkbt/vendor/firmware/rtl8761a_config and b/rtkbt/vendor/firmware/rtl8761a_config differ
old mode 100644 (file)
new mode 100755 (executable)
index 0ea654f..1e3116b
Binary files a/rtkbt/vendor/firmware/rtl8761at8192ee_fw and b/rtkbt/vendor/firmware/rtl8761at8192ee_fw differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index d0e3370..e43f0b2
Binary files a/rtkbt/vendor/firmware/rtl8761at_config and b/rtkbt/vendor/firmware/rtl8761at_config differ
old mode 100644 (file)
new mode 100755 (executable)
index 6d0fac4..7a6d63d
Binary files a/rtkbt/vendor/firmware/rtl8761at_fw and b/rtkbt/vendor/firmware/rtl8761at_fw differ
old mode 100644 (file)
new mode 100755 (executable)
index 0190dcb..a54fc84
Binary files a/rtkbt/vendor/firmware/rtl8761au8192ee_fw and b/rtkbt/vendor/firmware/rtl8761au8192ee_fw differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index d91c70b..5350a4b
Binary files a/rtkbt/vendor/firmware/rtl8761au_fw and b/rtkbt/vendor/firmware/rtl8761au_fw differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 2f91bc2..82567d8
Binary files a/rtkbt/vendor/firmware/rtl8761aw8192eu_fw and b/rtkbt/vendor/firmware/rtl8761aw8192eu_fw differ
diff --git a/rtkbt/vendor/firmware/rtl8761b_config b/rtkbt/vendor/firmware/rtl8761b_config
new file mode 100755 (executable)
index 0000000..91d3f44
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8761b_config differ
diff --git a/rtkbt/vendor/firmware/rtl8761b_fw b/rtkbt/vendor/firmware/rtl8761b_fw
new file mode 100755 (executable)
index 0000000..9c4a02f
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8761b_fw differ
diff --git a/rtkbt/vendor/firmware/rtl8761bt_config b/rtkbt/vendor/firmware/rtl8761bt_config
new file mode 100755 (executable)
index 0000000..99475ee
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8761bt_config differ
diff --git a/rtkbt/vendor/firmware/rtl8761bt_fw b/rtkbt/vendor/firmware/rtl8761bt_fw
new file mode 100755 (executable)
index 0000000..04228bf
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8761bt_fw differ
old mode 100644 (file)
new mode 100755 (executable)
index 57b5932..a242ddc
Binary files a/rtkbt/vendor/firmware/rtl8821a_config and b/rtkbt/vendor/firmware/rtl8821a_config differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index a54ab97..99e5a11
Binary files a/rtkbt/vendor/firmware/rtl8821as_config and b/rtkbt/vendor/firmware/rtl8821as_config differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 18500ea..201205f
Binary files a/rtkbt/vendor/firmware/rtl8821c_fw and b/rtkbt/vendor/firmware/rtl8821c_fw differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 92f8bab..ab88fee
Binary files a/rtkbt/vendor/firmware/rtl8821cs_fw and b/rtkbt/vendor/firmware/rtl8821cs_fw differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 67c87e5..694ec68
Binary files a/rtkbt/vendor/firmware/rtl8822b_fw and b/rtkbt/vendor/firmware/rtl8822b_fw differ
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 340ac74..c498b15
Binary files a/rtkbt/vendor/firmware/rtl8822bs_fw and b/rtkbt/vendor/firmware/rtl8822bs_fw differ
diff --git a/rtkbt/vendor/firmware/rtl8822c_config b/rtkbt/vendor/firmware/rtl8822c_config
new file mode 100755 (executable)
index 0000000..91d3f44
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8822c_config differ
diff --git a/rtkbt/vendor/firmware/rtl8822c_fw b/rtkbt/vendor/firmware/rtl8822c_fw
new file mode 100755 (executable)
index 0000000..4e9456f
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8822c_fw differ
diff --git a/rtkbt/vendor/firmware/rtl8822cs_config b/rtkbt/vendor/firmware/rtl8822cs_config
new file mode 100755 (executable)
index 0000000..99475ee
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8822cs_config differ
diff --git a/rtkbt/vendor/firmware/rtl8822cs_fw b/rtkbt/vendor/firmware/rtl8822cs_fw
new file mode 100755 (executable)
index 0000000..c1a01a9
Binary files /dev/null and b/rtkbt/vendor/firmware/rtl8822cs_fw differ